diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.gdbinit | 28 | ||||
-rw-r--r-- | src/ChangeLog | 4357 | ||||
-rw-r--r-- | src/ChangeLog.8 | 1266 | ||||
-rw-r--r-- | src/Makefile.in | 185 | ||||
-rw-r--r-- | src/alloc.c | 1325 | ||||
-rw-r--r-- | src/atimer.c | 221 | ||||
-rw-r--r-- | src/atimer.h | 3 | ||||
-rw-r--r-- | src/bidi.c | 1697 | ||||
-rw-r--r-- | src/buffer.c | 347 | ||||
-rw-r--r-- | src/buffer.h | 30 | ||||
-rw-r--r-- | src/bytecode.c | 11 | ||||
-rw-r--r-- | src/callint.c | 135 | ||||
-rw-r--r-- | src/callproc.c | 128 | ||||
-rw-r--r-- | src/category.c | 2 | ||||
-rw-r--r-- | src/ccl.c | 7 | ||||
-rw-r--r-- | src/character.c | 26 | ||||
-rw-r--r-- | src/character.h | 38 | ||||
-rw-r--r-- | src/charset.c | 104 | ||||
-rw-r--r-- | src/charset.h | 2 | ||||
-rw-r--r-- | src/chartab.c | 81 | ||||
-rw-r--r-- | src/cmds.c | 13 | ||||
-rw-r--r-- | src/coding.c | 137 | ||||
-rw-r--r-- | src/coding.h | 63 | ||||
-rw-r--r-- | src/commands.h | 4 | ||||
-rw-r--r-- | src/composite.c | 91 | ||||
-rw-r--r-- | src/conf_post.h | 64 | ||||
-rw-r--r-- | src/data.c | 114 | ||||
-rw-r--r-- | src/dbusbind.c | 19 | ||||
-rw-r--r-- | src/decompress.c | 10 | ||||
-rw-r--r-- | src/deps.mk | 6 | ||||
-rw-r--r-- | src/dired.c | 2 | ||||
-rw-r--r-- | src/dispextern.h | 135 | ||||
-rw-r--r-- | src/dispnew.c | 338 | ||||
-rw-r--r-- | src/doc.c | 32 | ||||
-rw-r--r-- | src/dosfns.c | 53 | ||||
-rw-r--r-- | src/dosfns.h | 3 | ||||
-rw-r--r-- | src/editfns.c | 478 | ||||
-rw-r--r-- | src/emacs.c | 178 | ||||
-rw-r--r-- | src/eval.c | 151 | ||||
-rw-r--r-- | src/fileio.c | 217 | ||||
-rw-r--r-- | src/filelock.c | 10 | ||||
-rw-r--r-- | src/fns.c | 651 | ||||
-rw-r--r-- | src/font.c | 273 | ||||
-rw-r--r-- | src/font.h | 69 | ||||
-rw-r--r-- | src/fontset.c | 65 | ||||
-rw-r--r-- | src/frame.c | 1119 | ||||
-rw-r--r-- | src/frame.h | 545 | ||||
-rw-r--r-- | src/fringe.c | 107 | ||||
-rw-r--r-- | src/ftfont.c | 232 | ||||
-rw-r--r-- | src/ftfont.h | 1 | ||||
-rw-r--r-- | src/ftxfont.c | 31 | ||||
-rw-r--r-- | src/gmalloc.c | 243 | ||||
-rw-r--r-- | src/gnutls.c | 16 | ||||
-rw-r--r-- | src/gtkutil.c | 795 | ||||
-rw-r--r-- | src/gtkutil.h | 27 | ||||
-rw-r--r-- | src/image.c | 194 | ||||
-rw-r--r-- | src/indent.c | 2 | ||||
-rw-r--r-- | src/insdel.c | 47 | ||||
-rw-r--r-- | src/intervals.h | 2 | ||||
-rw-r--r-- | src/keyboard.c | 523 | ||||
-rw-r--r-- | src/keyboard.h | 57 | ||||
-rw-r--r-- | src/keymap.c | 104 | ||||
-rw-r--r-- | src/keymap.h | 2 | ||||
-rw-r--r-- | src/lastfile.c | 2 | ||||
-rw-r--r-- | src/lisp.h | 796 | ||||
-rw-r--r-- | src/lisp.mk | 3 | ||||
-rw-r--r-- | src/lread.c | 226 | ||||
-rw-r--r-- | src/macfont.h | 13 | ||||
-rw-r--r-- | src/macfont.m | 3353 | ||||
-rw-r--r-- | src/macros.c | 27 | ||||
-rw-r--r-- | src/marker.c | 17 | ||||
-rw-r--r-- | src/menu.c | 256 | ||||
-rw-r--r-- | src/menu.h | 33 | ||||
-rw-r--r-- | src/minibuf.c | 64 | ||||
-rw-r--r-- | src/msdos.c | 113 | ||||
-rw-r--r-- | src/nsfns.m | 117 | ||||
-rw-r--r-- | src/nsfont.m | 40 | ||||
-rw-r--r-- | src/nsgui.h | 9 | ||||
-rw-r--r-- | src/nsimage.m | 2 | ||||
-rw-r--r-- | src/nsmenu.m | 115 | ||||
-rw-r--r-- | src/nsselect.m | 43 | ||||
-rw-r--r-- | src/nsterm.h | 73 | ||||
-rw-r--r-- | src/nsterm.m | 504 | ||||
-rw-r--r-- | src/print.c | 54 | ||||
-rw-r--r-- | src/process.c | 383 | ||||
-rw-r--r-- | src/process.h | 6 | ||||
-rw-r--r-- | src/profiler.c | 2 | ||||
-rw-r--r-- | src/puresize.h | 2 | ||||
-rw-r--r-- | src/ralloc.c | 12 | ||||
-rw-r--r-- | src/regex.c | 73 | ||||
-rw-r--r-- | src/regex.h | 3 | ||||
-rw-r--r-- | src/scroll.c | 48 | ||||
-rw-r--r-- | src/search.c | 113 | ||||
-rw-r--r-- | src/sheap.c | 2 | ||||
-rw-r--r-- | src/sound.c | 184 | ||||
-rw-r--r-- | src/syntax.c | 14 | ||||
-rw-r--r-- | src/sysdep.c | 418 | ||||
-rw-r--r-- | src/sysselect.h | 42 | ||||
-rw-r--r-- | src/syssignal.h | 4 | ||||
-rw-r--r-- | src/systime.h | 16 | ||||
-rw-r--r-- | src/systty.h | 6 | ||||
-rw-r--r-- | src/term.c | 291 | ||||
-rw-r--r-- | src/termcap.c | 2 | ||||
-rw-r--r-- | src/termhooks.h | 78 | ||||
-rw-r--r-- | src/terminal.c | 120 | ||||
-rw-r--r-- | src/textprop.c | 25 | ||||
-rw-r--r-- | src/unexcoff.c | 2 | ||||
-rw-r--r-- | src/unexcw.c | 19 | ||||
-rw-r--r-- | src/unexhp9k800.c | 1 | ||||
-rw-r--r-- | src/unexmacosx.c | 112 | ||||
-rw-r--r-- | src/unexw32.c | 60 | ||||
-rw-r--r-- | src/vm-limit.c | 57 | ||||
-rw-r--r-- | src/w32.c | 130 | ||||
-rw-r--r-- | src/w32.h | 11 | ||||
-rw-r--r-- | src/w32console.c | 15 | ||||
-rw-r--r-- | src/w32fns.c | 644 | ||||
-rw-r--r-- | src/w32font.c | 207 | ||||
-rw-r--r-- | src/w32font.h | 4 | ||||
-rw-r--r-- | src/w32gui.h | 5 | ||||
-rw-r--r-- | src/w32heap.c | 819 | ||||
-rw-r--r-- | src/w32heap.h | 21 | ||||
-rw-r--r-- | src/w32inevt.c | 9 | ||||
-rw-r--r-- | src/w32inevt.h | 2 | ||||
-rw-r--r-- | src/w32menu.c | 123 | ||||
-rw-r--r-- | src/w32notify.c | 4 | ||||
-rw-r--r-- | src/w32proc.c | 225 | ||||
-rw-r--r-- | src/w32select.c | 6 | ||||
-rw-r--r-- | src/w32term.c | 825 | ||||
-rw-r--r-- | src/w32term.h | 126 | ||||
-rw-r--r-- | src/w32uniscribe.c | 18 | ||||
-rw-r--r-- | src/widget.c | 196 | ||||
-rw-r--r-- | src/widgetprv.h | 1 | ||||
-rw-r--r-- | src/window.c | 614 | ||||
-rw-r--r-- | src/window.h | 299 | ||||
-rw-r--r-- | src/xdisp.c | 592 | ||||
-rw-r--r-- | src/xfaces.c | 71 | ||||
-rw-r--r-- | src/xfns.c | 738 | ||||
-rw-r--r-- | src/xfont.c | 62 | ||||
-rw-r--r-- | src/xftfont.c | 67 | ||||
-rw-r--r-- | src/xgselect.c | 2 | ||||
-rw-r--r-- | src/xmenu.c | 292 | ||||
-rw-r--r-- | src/xrdb.c | 6 | ||||
-rw-r--r-- | src/xselect.c | 284 | ||||
-rw-r--r-- | src/xsmfns.c | 10 | ||||
-rw-r--r-- | src/xterm.c | 1650 | ||||
-rw-r--r-- | src/xterm.h | 149 |
146 files changed, 20442 insertions, 12956 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index a74fe3db7a1..d76c3aa8e05 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -49,7 +49,7 @@ define xgetptr else set $bugfix = $arg0 end - set $ptr = ($bugfix & VALMASK) | DATA_SEG_BITS + set $ptr = $bugfix & VALMASK end define xgetint @@ -468,18 +468,18 @@ define pgx end # GLYPHLESS_GLYPH if ($g.type == 2) - printf "GLYPHLESS[" + printf "G-LESS[" if ($g.u.glyphless.method == 0) - printf "THIN]" + printf "THIN;0x%x]", $g.u.glyphless.ch end if ($g.u.glyphless.method == 1) - printf "EMPTY]" + printf "EMPTY;0x%x]", $g.u.glyphless.ch end if ($g.u.glyphless.method == 2) - printf "ACRO]" + printf "ACRO;0x%x]", $g.u.glyphless.ch end if ($g.u.glyphless.method == 3) - printf "HEX]" + printf "HEX;0x%x]", $g.u.glyphless.ch end end # IMAGE_GLYPH @@ -498,7 +498,7 @@ define pgx printf " pos=%d", $g.charpos end # For characters, print their resolved level and bidi type - if ($g.type == 0) + if ($g.type == 0 || $g.type == 2) printf " blev=%d,btyp=", $g.resolved_level pbiditype $g.bidi_type end @@ -862,10 +862,8 @@ end define xsubchartable xgetptr $ print (struct Lisp_Sub_Char_Table *) $ptr - xgetint $->depth - set $depth = $int - xgetint $->min_char - printf "Depth: %d, Min char: %d (0x%x)\n", $depth, $int, $int + set $subchartab = (struct Lisp_Sub_Char_Table *) $ptr + printf "Depth: %d, Min char: %d (0x%x)\n", $subchartab->depth, $subchartab->min_char, $subchartab->min_char end document xsubchartable Print the address of the sub-char-table $, its depth and min-char. @@ -1085,8 +1083,8 @@ document xprintsym end define xcoding - set $tmp = (struct Lisp_Hash_Table *) ((Vcoding_system_hash_table & VALMASK) | DATA_SEG_BITS) - set $tmp = (struct Lisp_Vector *) (($tmp->key_and_value & VALMASK) | DATA_SEG_BITS) + set $tmp = (struct Lisp_Hash_Table *) (Vcoding_system_hash_table & VALMASK) + set $tmp = (struct Lisp_Vector *) ($tmp->key_and_value & VALMASK) set $name = $tmp->contents[$arg0 * 2] print $name pr @@ -1098,8 +1096,8 @@ document xcoding end define xcharset - set $tmp = (struct Lisp_Hash_Table *) ((Vcharset_hash_table & VALMASK) | DATA_SEG_BITS) - set $tmp = (struct Lisp_Vector *) (($tmp->key_and_value & VALMASK) | DATA_SEG_BITS) + set $tmp = (struct Lisp_Hash_Table *) (Vcharset_hash_table & VALMASK) + set $tmp = (struct Lisp_Vector *) ($tmp->key_and_value & VALMASK) p $tmp->contents[charset_table[$arg0].hash_index * 2] pr end diff --git a/src/ChangeLog b/src/ChangeLog index e0e46a63b0b..f00caa30733 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,6 +1,99 @@ 2014-10-20 Glenn Morris <rgm@gnu.org> - * Version 24.4 released. + * Merge in all changes up to 24.4 release. + +2014-10-19 Jan Djärv <jan.h.d@swipnet.se> + + * gtkutil.c (xg_update_menubar, xg_update_menu_item): Only call + g_object_notify for label if Gtk+ >= 2.16 (Bug#16522). + + * xterm.h (x_output): Remove net_wm_state_hidden_seen. + + * xterm.c (handle_one_xevent): Check return value from + x_handle_net_wm_state, remove net_wm_state_hidden_seen (Bug#18722). + (get_current_wm_state): Remove net_wm_state_hidden_seen setting. + + * gtkutil.c (create_dialog): Don't use gtk_dialog_get_action_area on + Gt+ >= 3.12, or gtk_misc_set_alignment on Gtk+ >= 3.14 (Bug#18674). + (make_widget_for_menu_item): Don't use gtk_misc_set_alignment on + Gtk+ >= 3.14 (Bug#18674). + (update_frame_tool_bar): Don't use gtk_misc_set_padding on + Gtk+ >= 3.14 (Bug#18674). + +2014-10-18 Paul Eggert <eggert@cs.ucla.edu> + + * gtkutil.c: Remove no-longer-used code. + (xg_update_menubar): Remove unused local and unnecessary call to + gtk_menu_item_get_submenu. + (XG_TOOL_BAR_PROXY_BUTTON, xg_tool_bar_proxy_callback) + (xg_get_tool_bar_widgets, xg_tool_bar_proxy_help_callback) + (TOOLBAR_TOP_WIDGET): Remove; no longer used. + +2014-10-18 Jan Djärv <jan.h.d@swipnet.se> + + * xfns.c (syms_of_xfns): Remove x-gtk-whole-detached-tool-bar. + + * xterm.h (handlebox_widget): Remove. + + * xmenu.c (set_frame_menubar): Remove GTK block that calls + xg_have_tear_offs. + + * gtkutil.h (xg_have_tear_offs): Remove declaration. + + * gtkutil.c (XG_TEXT_CANCEL, XG_TEXT_OPEN, XG_TEXT_OK): New defines + to handle Gtk versions. + (xg_get_file_with_chooser): Use them. + (xg_have_tear_offs, tearoff_remove, tearoff_activate): Remove + (create_menus): Remove teroff argument and code. + Remove call to gtk_menu_set_title. + (xg_update_menubar, xg_update_submenu): Remove tearoff code. Adjust + args to create_menus. + (xg_tool_bar_menu_proxy, xg_tool_bar_detach_callback) + (xg_tool_bar_attach_callback, TOOLBAR_TOP_WIDGET): Remove. + (xg_pack_tool_bar): Replace TOOLBAR_TOP_WIDGET, remove detach code. + (xg_make_tool_item): Remove detach code. + (xg_update_tool_bar_sizes): Replace TOOLBAR_TOP_WIDGET. + (find_icon_from_name): New function. + (update_frame_tool_bar): Remove GtkStockItem code, move to + find_icon_from_name. Let stock be a list of icon names to try. + Only use gtk_image_new_from_stock on Gtk+ < 3.10. + Replace TOOLBAR_TOP_WIDGET. + (free_frame_tool_bar, xg_change_toolbar_position ): Replace + TOOLBAR_TOP_WIDGET. + (xg_initialize): Remove tearoff code. + +2014-10-18 Eli Zaretskii <eliz@gnu.org> + + * xterm.c (x_draw_bar_cursor, x_draw_hollow_cursor): Subtract 1 + pixel from the window's cursor glyph width, since X renders hollow + blocks 1 pixel wider than the 'width' parameter. + + * xdisp.c (get_phys_cursor_geometry): Don't subtract 1 pixel from + glyph->pixel_width; this is now done in xterm.c. + + Fix reordering of bracket characters in isolates. + * bidi.c (bidi_cache_find): Rename the argument NEUTRALS_OK to + RESOLVED_ONLY; when non-zero, return from the cache only fully + resolved states. All callers changed. + (CANONICAL_EQU): New macro. + (PUSH_BPA_STACK): Use it to push onto the BPA stack the canonical + equivalent of the paired closing bracket character. + (bidi_find_bracket_pairs): Set the bracket_pairing_pos member to + the default non-negative value, to be checked later in + bidi_resolve_brackets. Use CANONICAL_EQU to test candidate + characters against those pushed onto the BPA stack. + (bidi_record_type_for_neutral): New function. + (bidi_resolve_brackets): Record next_for_neutral and + prev_for_neutral when embedding level gets pushed. Force + resolution of bracket pairs when entering a level run that was not + yet BPA-resolved. + (bidi_resolve_neutral): Add assertions before calling + bidi_resolve_neutral_1. + (bidi_level_of_next_char): Remove the code that attempted to + resolve unresolved neutrals; that is now done by + bidi_resolve_neutral. + + * w32select.c (owner_callback): Mark with ALIGN_STACK attribute. 2014-10-17 Eli Zaretskii <eliz@gnu.org> @@ -9,37 +102,424 @@ Reported by Dmitry Antipov <dmantipov@yandex.ru>, see http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg00518.html. -2014-10-10 Paul Eggert <eggert@cs.ucla.edu> +2014-10-16 Eli Zaretskii <eliz@gnu.org> + + * bidi.c (bidi_find_bracket_pairs): Avoid a loop that does nothing + useful. + +2014-10-15 Paul Eggert <eggert@cs.ucla.edu> + + * bidi.c (bidi_find_bracket_pairs): Initialize local var. + This pacifies GCC 4.9.1 with --enable-gcc-warnings. + It's not clear to me whether the initialization is needed, + but it can't hurt so I played it safe. + +2014-10-15 Stefan Monnier <monnier@iro.umontreal.ca> + + * lisp.mk (lisp): Add emacs-lisp/eldoc.elc. + +2014-10-15 Eli Zaretskii <eliz@gnu.org> + + Update the bidirectional reordering engine for Unicode 6.3 and 7.0. + * bidi.c (bidi_ignore_explicit_marks_for_paragraph_level): + Remove variable. + (bidi_get_type): Return the isolate initiators and terminator types. + (bidi_isolate_fmt_char, bidi_paired_bracket_type) + (bidi_fetch_char_skip_isolates, find_first_strong_char) + (bidi_find_bracket_pairs, bidi_resolve_brackets): New functions. + (bidi_set_sos_type): Rename from bidi_set_sor_type and updated + for the new features. + (bidi_push_embedding_level, bidi_pop_embedding_level): Update to + push and pop correctly for isolates. + (bidi_remember_char): Modify to accept an additional argument + and record the bidi type according to its value. + (bidi_cache_iterator_state): Accept an additional argument to only + update an existing state. Handle the new members of struct bidi_it. + (bidi_cache_find): Arguments changed: no longer accepts a level, + instead accepts a flag telling it whether it is okay to return + unresolved neutrals. + (bidi_initialize): Initiate and staticpro the bracket-type uniprop + table. Initialize new isolate-related members. + (bidi_paragraph_init): Some code factored out into + find_first_strong_char. + (bidi_resolve_explicit_1): Function deleted, its code incorporated + into bidi_resolve_explicit. + (bidi_resolve_explicit): Support the isolate initiators and + terminator. Fix handling of embeddings and overrides according to + new UBA requirements. Record information about previously seen + characters here (moved from bidi_level_of_next_char). + (bidi_resolve_weak): Adapt to changes in struct members. + (FLAG_EMBEDDING_INSIDE, FLAG_OPPOSITE_INSIDE, MAX_BPA_STACK) + (STORE_BRACKET_CHARPOS, PUSH_BPA_STACK): New macros. + (bidi_resolve_neutral): Call bidi_resolve_brackets to handle the + paired bracket resolution. Handle isolate initiators and + terminator. + (bidi_type_of_next_char): Remove unneeded code for BN limit. + (bidi_level_of_next_char): Move the code that records information + about previous characters to bidi_resolve_explicit. Fix logic of + resolving neutrals and make sure their cache entries are updated. + Remove now unneeded special handling of PDF level. + + * dispextern.h (struct glyph): Enlarge the width of resolved_level. + (BIDI_MAXDEPTH): New macro, renamed from BIDI_MAXLEVEL and + enlarged per Unicode 6.3. + (enum bidi_bracket_type_t): New data type. + (struct bidi_saved_info): Leave only 2 type members out of 4. + Remove bytepos. + (struct bidi_stack): Add members necessary to support isolating + sequences. + (struct bidi_it): Add new members necessary to support isolating + sequences and bracket pair resolution. + + * xdisp.c (Fbidi_resolved_levels): New function. + (syms_of_xdisp): Defsubr it. + (append_glyph, append_composite_glyph, produce_image_glyph) + (append_stretch_glyph, append_glyphless_glyph): Convert aborts to + assertions. + (syms_of_xdisp) <inhibit-bidi-mirroring>: New variable. + + * term.c (append_glyph, append_composite_glyph) + (append_glyphless_glyph): Convert aborts to assertions. + + * .gdbinit (pgx): Display the character codepoint, resolved level, + and bidi type also for glyphless glyphs. + +2014-10-15 Dmitry Antipov <dmantipov@yandex.ru> + + Avoid unwanted point motion in Fline_beginning_position. + * lisp.h (scan_newline_from_point): Add prototype. + * search.c (scan_newline_from_point): New function, refactored from... + * cmds.c (Fforward_line): ...adjusted user. + * editfns.c (Fline_beginning_position): Use scan_newline_from_point + and simplify the former since the latter doesn't move point. + +2014-10-14 Dmitry Antipov <dmantipov@yandex.ru> + + Cleanup terminal handling code. + * dispextern.h (get_named_tty): Remove prototype but... + * termhooks.h (get_named_terminal): ...resurrect it under + more meaningful name. + (get_terminal): Likewise, but with... + (decode_live_terminal): ...this name. + (decode_tty_terminal): Add prototype. + * term.c (get_tty_terminal): Remove. + (get_named_tty): Remove. + (Ftty_display_color_p, Ftty_display_color_cells, Ftty_type) + (Fcontrolling_tty_p, Fsuspend_tty, Fresume_tty): + Use decode_tty_terminal. + (Ftty_no_underline, Ftty_top_frame): Use decode_live_terminal. + * terminal.c (get_terminal): Refactor to... + (decode_terminal, decode_live_terminal): ...new functions. + (decode_tty_terminal): Replacement for get_tty_terminal. + (get_named_terminal): Likewise for get_named_tty. + * coding.c (Fset_terminal_coding_system_internal) + (Fterminal_coding_system, Fset_keyboard_coding_system_internal): + (Fkeyboard_coding_system): + * composite.c (Fcomposition_get_gstring): + * dispnew.c (Fsend_string_to_terminal): + * frame.c (Fmake_terminal_frame): + * nsfns.m (check_ns_display_info): + * w32fns.c, xfns.c (check_x_display_info): + * xselect.c (frame_for_x_selection): Use decode_live_terminal. + * keyboard.c (handle_interrupt_signal, handle_interrupt) + (Fset_quit_char): Use get_named_terminal. + (Fset_output_flow_control, Fset_input_meta_mode): + Use decode_tty_terminal. + +2014-10-13 Eli Zaretskii <eliz@gnu.org> + + * w32term.h (ALIGN_STACK): Use _WIN64, not _W64, to distinguish + between 32-bit and 64-bit MinGW builds. (Bug#18699) + +2014-10-12 Paul Eggert <eggert@cs.ucla.edu> Fix port to Debian GNU/kFreeBSD 7 (wheezy) (Bug#18666). * process.c (accept4) [!HAVE_ACCEPT4]: New macro. -2014-10-09 Stefan Monnier <monnier@iro.umontreal.ca> +2014-10-12 Stefan Monnier <monnier@iro.umontreal.ca> * frame.c (Fmouse_pixel_position): Call Vmouse_position_function (bug#18638). -2014-10-08 K. Handa <handa@gnu.org> +2014-10-12 Paul Eggert <eggert@cs.ucla.edu> + + * editfns.c (dump_tz_string): No longer const. + It might be modified. + + * nsmenu.m (clear): Assume OS X 10.6 or later. + +2014-10-12 Jan Djärv <jan.h.d@swipnet.se> + + * unexmacosx.c: Remove include ppc/reloc.h. + (unrelocate, copy_dysymtab): Remove PPC code. + (rebase_reloc_address): Remove, only used for PPC: + + * nsterm.m: Always include macfont.h on COCOA. + (ns_update_auto_hide_menu_bar, ns_draw_fringe_bitmap) + (ns_dumpglyphs_image, ns_check_menu_open) + (applicationDidFinishLaunching) + (antialiasThresholdDidChange:) + (keyDown:, toggleFullScreen:, setPosition:portion:whole:): + Remove checks for OSX <= 10.5/10.6. + (changeFont:): Use macfont on COCOA, nsfont on GNUSTEP. + (syms_of_nsterm): Call syms_of_macfont on COCOA, syms_of_nsfont on + GNUSTEP. + + * nsterm.h (MAC_OS_X_VERSION_10_4, MAC_OS_X_VERSION_10_5): Remove. + (NS_HAVE_NSINTEGER): Remove block. + Remove >= OSX 10.6 tests. + + * nsmenu.m (NSMenuDidBeginTrackingNotification): Remove. + (x_activate_menubar, trackingNotification:): Remove check for + OSX >= 10.5. + (menuNeedsUpdate:): Remove check for OSX < 10.5. + + * nsimage.m (allocInitFromFile:): Remove code for OSX < 10.6. + + * nsfns.m: Always include macfont.h on COCOA. + (ns_filename_from_panel, ns_directory_from_panel) + (Fx_create_frame, Fns_popup_font_panel, ns_run_file_dialog) + (Fns_read_file_name, Fns_list_services): Remove code for OSX < 10.6 + + * macfont.m: Remove >= 1050 check. + (macfont_create_family_with_symbol) + (macfont_get_glyph_for_character) + (mac_font_get_glyphs_for_variants) + (mac_ctfont_create_available_families, syms_of_macfont): + Remove code for OSX < 10.6. + (mac_font_family_group, mac_font_family_compare): Remove, only used + for OSX < 10.6. + + * macfont.h (MAC_FONT_FORMAT_ATTRIBUTE, MAC_FONT_FORMAT_BITMAP) + (mac_font_copy_non_synthetic_table): Remove versions for OSX < 10.6 + + * Makefile.in: Replace nsfont.o macfont.o with ns_fontfile in + comment. + +2014-10-12 Paul Eggert <eggert@cs.ucla.edu> + + Fix putenv race conditions with undefined behavior (Bug#8705). + Do all putenv calls before Emacs creates any threads. + Use a safer way to modify the TZ environment variable in the + presence of multiple threads. For further thread-safety, + prefer localtime_r and gmtime_r to localtime and gmtime, + and prefer struct tm's tm_gmtoff (if available) to calling + both localtime_r and gmtime_r. + * dbusbind.c (Fdbus__init_bus): Move xputenv call from here ... + (init_dbusbind): ... to this new function. + * emacs.c (main) [HAVE_DBUS]: Call it before creating threads. + * xterm.c (x_term_init): Move xputenv call from here ... + (init_xterm): ... to this new function. + * emacs.c (main) [USE_GTK]: Call it before creating threads. + * editfns.c (HAVE_TM_GMTOFF): Default to false. + (dump_tz_string): New constant. + (init_editfns): Use it. This centralizes the dump_tz stuff. + Call set_time_zone_rule here, so that its xputenv is done + before Emacs goes multithreaded. + (mktime_z) [!HAVE_TZALLOC]: New function, which is typically + thread-safe enough for Emacs. + (format_time_string, Fdecode_time, Fcurrent_time_string) + (Fcurrent_time_zone): + Prefer localtime_r and gmtime_r, which are more thread-safe, to + localtime and gmtime. Remove now-unnecessary calls to block_input. + (tm_gmtoff): New static function. + (Fdecode_time, Fcurrent_time_zone): Use it. + (Fencode_time): Use mktime_z, for better thread-safety. + (set_time_zone_rule): Now static. Rewrite to be mostly thread-safe, + i.e., not quite thread-safe but good enough for Emacs typical usage. + Do not reclaim storage that is in the environment; let it leak. + Always call tzset, since localtime_r does not. + * emacs.c (dump_tz, Fdump_emacs) [HAVE_TZSET]: Remove dump_tz stuff. + This is now done in init_editfns. + * systime.h (mktime_z, timezone_t, tzalloc, tzfree) [!HAVE_TZALLOC]: + New macros and declarations, for platforms lacking tzalloc & friends. + +2014-10-09 Paul Eggert <eggert@cs.ucla.edu> + + * lisp.h (USE_STACK_STRING): Now true only if USE_STACK CONS. + On x86 platforms this works around GCC bug 63495 + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63495>, + and more generally should fix a portability problem in Emacs. + Problem reported by Stefan Monnier in: + http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg00261.html + +2014-10-08 Leo Liu <sdl.web@gmail.com> + + Enhance terpri to allow conditionally output a newline. (Bug#18652) + * keymap.c (describe_vector_princ): + * keyboard.c (Fcommand_error_default_function): Adapt to change to + Fterpri. + + * print.c (printchar_stdout_last): Declare. + (printchar): Record the last char written to stdout. + (Fterpri): Add optional argument ENSURE. + +2014-10-08 Eli Zaretskii <eliz@gnu.org> + + * w32inevt.c (maybe_generate_resize_event): Pass non-zero as the + DELAY argument to change_frame_size, so that the frame size + changes, if any are needed, are delayed until the next redisplay. + This is to avoid a too early QUIT inside change_frame_size, when + it calls Lisp in frame_windows_min_size, in case one of the events + we've read sets the quit-flag. (Bug#18649) + + * w32fns.c (check_x_display_info): Accept terminal objects as + argument, to follow what xfns.c does. + +2014-10-07 Glenn Morris <rgm@gnu.org> + + * Makefile.in ($(srcdir)/macuvs.h) + ($(lispsource)/international/charprop.el): Add explicit FORCE. + +2014-10-07 Eli Zaretskii <eliz@gnu.org> + + * decompress.c (init_zlib_functions): Move the message about zlib + being unavailable from here... + (Fzlib_decompress_region): ...to here. (Bug#18650) + +2014-10-07 Dmitry Antipov <dmantipov@yandex.ru> + + * font.c (Ffont_get_glyphs): Use validate_subarray and fix + the case where an optional string is used. Adjust docstring. + +2014-10-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * lisp.mk (lisp): Remove w32-common-fns.elc. + +2014-10-05 Paul Eggert <eggert@cs.ucla.edu> + + * keyboard.c (Qleft, Qright): Remove duplicate definitions (Bug#9927). + These were already defined in buffer.c, and the duplicate + definitions cause problems on platforms like 'gcc -fno-common'. + Reported by Peter Dyballa in: http://bugs.gnu.org/9927#137 + +2014-10-05 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (updateFrameSize:): Only call update_frame_tool_bar + if toolbar is visible. + + * nsfont.m (nsfont_draw): Use CGFloat for GNUstep newer than + 0.23 (Bug#18030). + + * nsterm.m (syms_of_nsterm): ns-use-fullscreen-animation is new. + (toggleFullScreen:): Use ns-use-fullscreen-animation for animate. + (ns_select, ns_read_socket): Use unwind_protect to decrease + apploopnr (Bug#18345). + (ns_draw_window_cursor): Adjust y for hbar cursor only if smaller than + line height (Bug#17977). + + * macfont.m: Fix indentation and import changes from macport 24.3.94. + (macfont_closest_traits_index): New function. + (macfont_closest_traits_index_p): Rename from + macfont_closest_traits_index. + (macfont_list): Use macfont_closest_traits_index_p. + +2014-10-05 K. Handa <handa@gnu.org> * coding.c (detect_coding_iso_2022): Set coding->rejected correctly when an invalid escape sequence is found (Bug#18610). -2014-10-03 Dmitry Antipov <dmantipov@yandex.ru> +2014-10-04 Jan Djärv <jan.h.d@swipnet.se> - * font.c (font_list_entities): Do not add empty vector to font cache. - (font_matching_entity): Likewise. If matching entity is found, insert - 1-item vector with this entity instead of an entity itself (Bug#17125). + * gtkutil.c (create_menus): Only add tearoffs to empty menus. + (xg_update_submenu): Remove has_tearoff_p, pass 1 to create_menus + for add_tearoff_p. -2014-10-02 Eli Zaretskii <eliz@gnu.org> +2014-10-04 Martin Rudalics <rudalics@gmx.at> + + * buffer.c (scroll_bar_width, scroll_bar_height): + Fix doc-strings. + * window.c (Fset_window_scroll_bars): Fix doc-string. + (Fwindow_scroll_bars): Have it return what the doc-string says. + +2014-10-03 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_by_lines): Call reseat_1 after moving the iterator backwards, to resync the bidi iterator. (Bug#18584) -2014-10-01 Jan Djärv <jan.h.d@swipnet.se> +2014-10-03 Dmitry Antipov <dmantipov@yandex.ru> + + Consistently use min and max macros from lisp.h. + * coding.c (min, max): + * font.c (MAX): + * unexhp9k800.c (min): + * unexw32.c (min, max): Use definitions from lisp.h. + * regex.c (MAX, MIN) [!emacs]: Define own max and min as such. + Adjust users. + * gmalloc.c (min): Tiny style change. + + * fileio.c (emacs_readlinkat, Finsert_file_contents): + * w32fns.c, xfns.c (x_create_tip_frame): Use AUTO_STRING. + +2014-10-03 Paul Eggert <eggert@cs.ucla.edu> + + Fix x-focus-frame bug with "Not an in-range integer" (Bug#18586). + * xselect.c (X_SHRT_MAX, X_SHRT_MIN, X_LONG_MAX, X_LONG_MIN) + (X_ULONG_MAX): Move these macros to xterm.h. + (x_fill_property_data): Be more generous about allowing either + signed or unsigned data of the appropriate width. + * xterm.h (x_display_set_last_user_time): New function. + All setters of last_user_time changd to use this function. + If ENABLE_CHECKING, check that the times are in range. + +2014-10-02 Eli Zaretskii <eliz@gnu.org> + + * dispnew.c (adjust_decode_mode_spec_buffer): Use 'int' instead of + 'ssize_t'. Suggested by Paul Eggert <eggert@cs.ucla.edu>. + +2014-10-02 Jan Djärv <jan.h.d@swipnet.se> * xfaces.c (Finternal_set_lisp_face_attribute): Don't try to make a font_object from a tty frame (Bug#18573). - (Finternal_set_lisp_face_attribute): Added FIXME comment. + (Finternal_set_lisp_face_attribute): Add FIXME comment. + +2014-10-02 Dmitry Antipov <dmantipov@yandex.ru> + + * alloc.c (mark_overlay): Assume that overlay boundaries are + always markers. Add comment. + * lread.c (read_internal_start): Use convenient validate_subarray. + Adjust docstring. + (Fread_from_string): Adjust docstring. + +2014-10-02 Stefan Monnier <monnier@iro.umontreal.ca> + + * lisp.h: Fix up compilation for USE_STACK_LISP_OBJECTS=false. + + * nsselect.m (ns-own-selection-internal, ns-disown-selection-internal): + Rename from the "x-" prefix. + +2014-10-01 Stefan Monnier <monnier@iro.umontreal.ca> + + * xselect.c (selection-converter-alist): Fix docstring. + +2014-10-01 Eli Zaretskii <eliz@gnu.org> + + * w32proc.c (sys_spawnve): Avoid modification of the CMDNAME + argument passed by the caller, when we mirror all slashes into + backslashes. + +2014-10-01 Dmitry Antipov <dmantipov@yandex.ru> + + * gtkutil.c (xg_set_toolkit_horizontal_scroll_bar_thumb): + Resurrect old code and fix compilation with GTK < 2.13.6. + +2014-10-01 Paul Eggert <eggert@cs.ucla.edu> + + Use AUTO_CONS instead of SCOPED_CONS, etc. + * frame.h (AUTO_FRAME_ARG): Rename from FRAME_PARAMETER. + * lisp.h (AUTO_CONS): Rename from scoped_cons. + (AUTO_LIST1): Rename from scoped_list1. + (AUTO_LIST2): Rename from scoped_list2. + (AUTO_LIST3): Rename from scoped_list3. + (AUTO_LIST4): Rename from scoped_list4. + (AUTO_STRING): Rename from SCOPED_STRING. + * frame.h (AUTO_FRAME_ARG): + * lisp.h (AUTO_CONS, AUTO_LIST1, AUTO_LIST2, AUTO_LIST3) + (AUTO_LIST4, AUTO_STRING): + Prepend a new argument 'name'. + Declare a variable instead of yielding a value. + All uses changed. + * lisp.h (STACK_CONS, AUTO_CONS_EXPR): New internal macros. 2014-09-30 Eli Zaretskii <eliz@gnu.org> @@ -51,11 +531,11 @@ values. (my_create_window): Move the calculation of the coordinates of the frame's top-left edge here. Pass them to the input thread via the - second parameter of the WM_EMACS_CREATEWINDOW message. See - http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00892.html + second parameter of the WM_EMACS_CREATEWINDOW message. + See http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00892.html for the details. -2014-09-29 Eli Zaretskii <eliz@gnu.org> +2014-09-30 Eli Zaretskii <eliz@gnu.org> * xdisp.c (cursor_row_fully_visible_p): Update commentary. (redisplay_window): Treat the frame's frozen_window_starts flag @@ -63,12 +543,12 @@ obey it if the glyph row showing point will be fully visible. Likewise when the window start is in a continuation line. If, after trying everything under the 'force_start' label, point is - still not fully visible, give up and scroll the window. Add - debugging traces. (Bug#18545) + still not fully visible, give up and scroll the window. + Add debugging traces. (Bug#18545) * window.c (Frecenter): Set the window's redisplay flag. -2014-09-24 Eli Zaretskii <eliz@gnu.org> +2014-09-30 Eli Zaretskii <eliz@gnu.org> * w32term.c (w32_read_socket): Don't use frame dimensions for resizing if GetClientRect returned an empty (0, 0, 0, 0) @@ -81,22 +561,328 @@ (adjust_decode_mode_spec_buffer): Add assertion to avoid passing negative values to xrealloc. (Bug#18528) +2014-09-30 Paul Eggert <eggert@cs.ucla.edu> + + * alloc.c: Remove now-unnecessary check. + Suggested by Dmitry Antipov in: + http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00891.html + + * xterm.c (x_term_init): Allocate temps on stack, not on heap. + + * frame.c (x_set_frame_parameters): Port --enable-gcc-warnings + to Ubuntu 14.04.1 x86-64. + + Simplify stack-allocated Lisp objects, and make them more portable. + The build_local_string macro was used in two ways: (1) string + literals for which scoped allocation suffices, and (2) file name + components, where it's not safe in general to assume bounded-size + ASCII data. Simplify by defining a new macro SCOPED_STRING that + allocates a block-scope string, and by using SCOPED_STRING for (1) + and build_string for (2). Furthermore, actually use stack + allocation only for objects known to have sufficient alignment. + This simpler implementation means Emacs can make + USE_STACK_LISP_OBJECTS the default unless GC_MARK_STACK != + GC_MAKE_GCPROS_NOOPS. + * lisp.h (GCALIGNED): Align even if !USE_STACK_LISP_OBJECTS, + for fewer differences among implementations. + (struct Lisp_String): Now GCALIGNED. + (USE_STACK_LISP_OBJECTS): Default to true, since the + implementation no longer insists on a nonempty GCALIGNED. + But make it false if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS. + (SCOPED_CONS_INITIALIZER): Remove, since it's no longer needed + separately. Move definiens to scoped_cons. The old definition + was incorrect when GCALIGNED was defined to be empty. + (union Aligned_String): New type. + (USE_STACK_CONS, USE_STACK_STRING): New constants, so that the + implementation ports to compilers that don't align strictly enough. + Don't worry about the union sizes; it's not worth bothering about. + (scoped_cons, scoped_list1, scoped_list3, scoped_list4): + Rewrite using USE_STACK_CONS. + (scoped_cons): Assume the use of union Aligned_Cons. + (lisp_string_size, make_local_string, build_local_string): Remove. + Unless otherwise specified, all callers of build_local_string + changed to use SCOPED_STRING. + (SCOPED_STRING): New macro. + * data.c (wrong_choice): + * menu.c (single_menu_item): + * process.c (Fformat_network_address): + Hoist use of SCOPED_STRING out of a scope, so that its returned + object lives long enough. + * fileio.c (Fexpand_file_name): Use build_string, not SCOPED_STRING, + as the string might be long or might not be ASCII. + +2014-09-29 Eli Zaretskii <eliz@gnu.org> + + * msdos.c (internal_terminal_init): Bump version to 25. + +2014-09-29 Dmitry Antipov <dmantipov@yandex.ru> + + Keep stack-allocated Lisp objects fast rather than versatile. + * lisp.h (union Aligned_Cons) [!GCALIGNED]: Define as such. + (SCOPED_CONS_INITIALIZER): New macro. + (scoped_cons) [USE_STACK_LISP_OBJECTS]: Use it. + (USE_LOCAL_ALLOCA): Remove. + (local_cons, local_list1, local_list2, local_list3, local_list4): + Remove. Stack overflow checking makes them too slow. + (make_local_vector): Likewise. Also we just don't have enough + users for it. + (enum LISP_STRING_OVERHEAD): Remove. + (local_string_init, local_vector_init): Remove prototypes. + (make_local_string, build_local_string): Redesign to target short + compile-time string constants, fall back to regular string allocation + where appropriate. + (lisp_string_size): New function. + (verify_ascii) [ENABLE_CHECKING]: Add prototype. + * alloc.c (local_string_init, local_vector_init): Remove. + (verify_ascii) [ENABLE_CHECKING]: New function. + * buffer.c, charset.c, chartab.c, data.c, editfns.c, emacs.c, fileio.c: + * fns.c, font.c, fontset.c, frame.c, keyboard.c, keymap.c, lread.c: + * menu.c, minibuf.c, process.c, textprop.c, xdisp.c, xfns.c, xfont.c: + * xselect.c, xterm.c: All related users changed. + +2014-09-28 Ken Brown <kbrown@cornell.edu> + + * sheap.c (bss_sbrk_buffer_beg): Remove redundant variable. + * gmalloc.c [CYGWIN]: Adapt to change in sheap.c. + +2014-09-27 Ken Brown <kbrown@cornell.edu> + + Fix implementation of HYBRID_MALLOC on Cygwin. + * sheap.c (bss_sbrk_buffer_end): Cast to void *. + (bss_sbrk_buffer_beg): New variable. Use it... + * gmalloc.c (ALLOCATED_BEFORE_DUMPING) [CYGWIN]: ...here, to fix + incorrect definition. + +2014-09-27 Stefan Monnier <monnier@iro.umontreal.ca> + + * keyboard.c (track-mouse): Rename to internal--track-mouse. + Make it into a function and change arg to be a function. + + * lisp.mk (lisp): Add elisp-mode.elc. + +2014-09-26 Paul Eggert <eggert@cs.ucla.edu> + + * xfns.c (x_default_scroll_bar_color_parameter): + Use USE_LOCAL_ALLOCA only if USE_TOOLKIT_SCROLL_BARS, + to pacify --enable-gcc-warnings in non-scrollbar builds. + +2014-09-26 Ken Brown <kbrown@cornell.edu> + + * w32term.h (ALIGN_STACK): Fix the cpp condition. + +2014-09-25 Eli Zaretskii <eliz@gnu.org> + + * lisp.h (USE_STACK_LISP_OBJECTS): Default to false for 32-bit + MinGW builds that use GCC before 4.2. + + Default to stack objects on DOS_NT platforms as well. + * w32term.h (ALIGN_STACK) [__GNUC__]: Define to + __attribute__((force_align_arg_pointer)) for GCC 4.2 and later. + + * lisp.h (USE_STACK_LISP_OBJECTS): Remove the !DOS_NT condition. + + * w32proc.c (enum_locale_fn, enum_codepage_fn): Add the + ALIGN_STACK attribute. + + * w32fns.c (w32_monitor_enum): Add the ALIGN_STACK attribute. + + * w32uniscribe.c (add_opentype_font_name_to_list): Add the + ALIGN_STACK attribute. + + * w32font.c (add_font_name_to_list, add_font_entity_to_list) + (add_one_font_entity_to_list): Add the ALIGN_STACK attribute. + +2014-09-25 Martin Rudalics <rudalics@gmx.at> + + * frame.c (frame_inhibit_resize): + * widget.c (EmacsFrameResize): + * window.c (resize_frame_windows, Fset_window_configuration): + * xdisp.c (expose_frame): + * xfns.c (x_change_tool_bar_height): + * xmenu.c (update_frame_menubar): + * xterm.c (handle_one_xevent, x_new_font, x_set_window_size_1): + Remove code left dead after 2014-07-27 changes. + +2014-09-25 Paul Eggert <eggert@cs.ucla.edu> + + Fix local_cons etc. to not exhaust the stack when in a loop. + Problem reported in: + http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00696.html + * buffer.c (Fother_buffer, other_buffer_safely, init_buffer): + * charset.c (load_charset_map_from_file, Ffind_charset_region) + (Ffind_charset_string): + * chartab.c (uniprop_encode_value_numeric, uniprop_table): + * data.c (wrong_range): + * editfns.c (Fpropertize, format2): + * emacs.c (init_cmdargs, decode_env_path): + * fileio.c (auto_save_error): + * fns.c (Fyes_or_no_p): + * font.c (font_style_to_value, font_parse_xlfd) + (font_parse_family_registry, font_delete_unmatched) + (font_add_log): + * fontset.c (Fset_fontset_font): + * frame.c (x_get_arg): + * keyboard.c (echo_dash, safe_run_hooks_error, parse_menu_item) + (read_char_minibuf_menu_prompt): + * keymap.c (silly_event_symbol_error, describe_vector): + * lread.c (load_warn_old_style_backquotes): + * menu.c (single_menu_item): + * minibuf.c (Fread_buffer): + * process.c (status_message, Fformat_network_address) + (server_accept_connection): + * textprop.c (copy_text_properties): + * xdisp.c (Fcurrent_bidi_paragraph_direction): + * xfns.c (x_default_scroll_bar_color_parameter): + * xfont.c (xfont_open): + * xselect.c (x_clipboard_manager_error_1): + * xterm.c (x_term_init): + Put USE_LOCAL_ALLOCA at the start of the function. + * fns.c (maybe_resize_hash_table): Use build_string instead of + build_local_string, since we'd otherwise need a conditional + USE_LOCAL_ALLOCA here, but this is just debugging output and is + not worth the bother of optimization. + * font.c (font_delete_unmatched): Remove by-hand code that + observed MAX_ALLOCA limit, since it's now done automatically. + * keymap.c (Fsingle_key_description): Put USE_SAFE_ALLOCA at top, + since build_local_string needs its sa_alloc. + * lisp.h (lisp_word_count): New function. + (SAFE_ALLOCA_LISP): Use it. + (USE_LOCAL_ALLOCA): New macro. + (local_cons, make_local_vector, make_local_string): + Observe the MAX_ALLOCA limit. + (LISP_STRING_OVERHEAD): New constant. + (make_local_string): Use it. + +2014-09-24 Paul Eggert <eggert@cs.ucla.edu> + + Default to stack objects on non-GNU/Linux, non-DOS_NT platforms. + * lisp.h (USE_STACK_LISP_OBJECTS): Also default to true + if !defined DOS_NT && !defined GNU_LINUX. I've tested this on AIX + and Solaris and it's likely to work on similar platforms. + + Avoid signed integer overflow when converting Time to ptrdiff_t. + * keyboard.c (INPUT_EVENT_POS_MAX, INPUT_EVENT_POS_MIN): + New macros. + (position_to_Time, Time_to_position): New functions. + (gen_help_event, kbd_buffer_get_event): Use them. + * systime.h (Time) [emacs && !HAVE_X_WINDOWS]: + Go back to plain 'unsigned long', so that 'Time' is the same + for both X and non-X builds; this is less likely to cause surprise. + * termhooks.h: Remove compile-time check that Time and ptrdiff_t + are the same size; this is no longer required. + + * keyboard.c (make_lispy_event): Avoid unnecessary tests + of bit 28 and of whether an unsigned value is negative. + This simplifies the code a bit, and pacifies clang 3.4. + +2014-09-24 Eli Zaretskii <eliz@gnu.org> + + * systime.h (Time): Define as size_t, to be consistent with 64-bit + Windows builds, where 'long' is a 32-bit type. + + * w32inevt.h (w32_console_mouse_position): Update the argument + types to use 'Time'. + + * w32term.c (w32_mouse_position) + (x_horizontal_scroll_bar_report_motion) + (x_scroll_bar_report_motion): Update the argument types to use + 'Time'. + +2014-09-24 Dmitry Antipov <dmantipov@yandex.ru> + + * termhooks.h (enum scroll_bar_part): Begin from 0 to allow... + (struct input_event): ...unsigned bitfields. Likewise for + `event_kind' member. Prefer unsigned for `code' and 'modifiers'. + Use `timestamp' for HELP_EVENT position. Add compile-time assert. + * keyboard.c (gen_help_event, kbd_buffer_store_help_event) + (kbd_buffer_get_event): Adjust users. + (scroll_bar_parts): Add Qnil to match scroll_bar_nowhere. + (make_scroll_bar_position): New function, refactored out of... + (make_lispy_event): ...adjusted user. + * nsterm.h (EmacsScroller): Use enum for `last_hit_part' member. + * nsterm.m (ns_mouse_position, mouseUp): + * term.c (term_mouse_position): + * w32inevt.c (w32_console_mouse_position): + * w32term.c (w32_mouse_position): + * xterm.c (XTmouse_position): Use scroll_bar_above_handle. + (x_send_scroll_bar_event, xm_scroll_callback, xg_scroll_callback): + Prefer enum and explicit enum members to integers and numeric values. + + * chartab.c (uniprop_encode_value_numeric): + * font.c (font_style_to_value): Use make_local_vector. + (font_delete_unmatched): Use local_cons but respect MAX_ALLOCA. + * keymap.c (append_key): Use scoped_list1. + + * lisp.h (USE_STACK_LISP_OBJECTS): Enable by default if GNU_LINUX + && __GNUC__ && !__clang__. Mention known problems. Adjust comment. + +2014-09-24 Paul Eggert <eggert@cs.ucla.edu> + + Fix some slow uses and misuses of strcat. + * doc.c (get_doc_string): + * gtkutil.c (get_utf8_string): + * xsmfns.c (x_session_initialize): + Avoid recomputation of string length. + * ftfont.c (ftfont_spec_pattern): + * xfns.c (xic_create_fontsetname): + Don't assume output buffer is initially zero. + +2014-09-23 Paul Eggert <eggert@cs.ucla.edu> + + * lisp.h (lispstpcpy): Rename from lispstrcpy, and act like stpcpy. + All callers changed. + * xterm.c (x_term_init): Use new functionality to avoid two needs + to compute a string length. + + * dispextern.h, xdisp.c (window_box_right_offset): Now static. + +2014-09-23 Dmitry Antipov <dmantipov@yandex.ru> + + Use known length of a Lisp string to copy it faster. + * lisp.h (lispstrcpy): New function. Add comment. + * callproc.c (child_setup): + * dbusbind.c (xd_append_arg): + * doc.c (get_doc_string): + * font.c (Ffont_xlfd_name): + * frame.c (xrdb_get_resource): + * process.c (Fmake_network_process, network_interface_info): + * w32fns.c (Fx_open_connection): + * w32proc.c (sys_spawnve): + * xfns.c (select_visual): + * xfont.c (xfont_list): + * xsmfns.c (x_session_initialize): + * xterm.c (x_term_init): Use it. + +2014-09-23 Paul Eggert <eggert@cs.ucla.edu> + + Fix SAFE_ALLOCA to not exhaust the stack when in a loop. + Problem reported by Dmitry Antipov in thread leading to: + http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00713.html + This patch fixes only SAFE_ALLOCA, SAFE_NALLOCA, and SAFE_ALLOCA_LISP; + the experimental local_* macros enabled by USE_LOCAL_ALLOCATORS + remain unfixed. + * callproc.c (call_process): Save and restore sa_avail. + * lisp.h (USE_SAFE_ALLOCA): Define sa_avail. + (AVAIL_ALLOCA): New macro. + (SAFE_ALLOCA, SAFE_NALLOCA, SAFE_ALLOCA_LISP): + Use it, and check against sa_avail rather than MAX_ALLOCA. + 2014-09-22 Dmitry Antipov <dmantipov@yandex.ru> On OSX, do not free font-specific data more than once (Bug#18501). * macfont.m (macfont_close): Release and free font-specific data only if it wasn't previously freed. -2014-09-21 David Caldwell <david@porkrind.org> (tiny change) +2014-09-22 David Caldwell <david@porkrind.org> (tiny change) * unexmacosx.c (dump_it): Improve error message. -2014-09-18 Juri Linkov <juri@jurta.org> +2014-09-22 Juri Linkov <juri@jurta.org> * image.c (imagemagick_load_image): Add delay to imagemagick metadata. (Bug#10747, bug#18334) -2014-09-18 Eli Zaretskii <eliz@gnu.org> +2014-09-22 Eli Zaretskii <eliz@gnu.org> * frame.c (Fmouse_position, Fset_mouse_position): Clarify the units in which the position is measured. (Bug#18493) @@ -104,7 +890,7 @@ * xdisp.c (redisplay_internal): Force redisplay of all windows that show a buffer whose narrowing has changed. (Bug#18490) -2014-09-16 Eli Zaretskii <eliz@gnu.org> +2014-09-22 Eli Zaretskii <eliz@gnu.org> * xterm.c (x_draw_hollow_cursor, x_draw_bar_cursor): * w32term.c (x_draw_hollow_cursor, x_draw_bar_cursor): In R2L @@ -118,7 +904,7 @@ every window except the leftmost one. Reported by Martin Rudalics <rudalics@gmx.at>. -2014-09-16 Dmitry Antipov <dmantipov@yandex.ru> +2014-09-22 Dmitry Antipov <dmantipov@yandex.ru> Always use matched specpdl entry to record call arguments (Bug#18473). * lisp.h (record_in_backtrace): Adjust prototype. @@ -135,7 +921,7 @@ overflow on string size calculation. * data.c (Faset): Likewise for byte index. -2014-09-15 Eli Zaretskii <eliz@gnu.org> +2014-09-22 Eli Zaretskii <eliz@gnu.org> Fix display of R2L lines in partial-width windows. * xdisp.c (init_iterator): Don't use it->bidi_p before it is @@ -149,17 +935,169 @@ of the right one. (produce_special_glyphs): Fix bogus assignments. -2014-09-14 Eli Zaretskii <eliz@gnu.org> +2014-09-22 Eli Zaretskii <eliz@gnu.org> + + * fileio.c (Fexpand_file_name) [DOS_NT]: Make sure newdirlim is + always set to a valid value. Make sure the size passed to alloca + is always positive. (Bug#18516) + +2014-09-22 Dmitry Antipov <dmantipov@yandex.ru> + + Avoid extra call to oblookup when interning symbols. + * lisp.h (intern_driver): Add prototype. + * lread.c (intern_driver): New function. + (intern1, intern_c_string_1, Fintern): + * font.c (font_intern_prop): + * w32font.c (intern_font_name): Use it. + +2014-09-21 Paul Eggert <eggert@cs.ucla.edu> + + Minor improvements to new stack-allocated Lisp objects. + * frame.h (FRAME_PARAMETER): + Prefer scoped_list1 to local_list1 where either would do. + * lisp.h (scoped_list4): New macro. + (local_cons, local_list1, local_list2, local_list3, local_list4) + (make_local_vector, make_local_string, build_local_string): + Prefer functions to macros where either would do. + * xdisp.c (build_desired_tool_bar_string): + Prefer scoped_list4 to local_list4 where either would do. + +2014-09-18 Dmitry Antipov <dmantipov@yandex.ru> + + More and more stack-allocated Lisp objects if USE_LOCAL_ALLOCATORS. + * lisp.h (local_list4) [USE_LOCAL_ALLOCATORS]: New macro. + [!USE_LOCAL_ALLOCATORS]: Fall back to regular list4. + * frame.h (FRAME_PARAMETER): New macro. + * dispnew.c (init_display): + * fontset.c (Fset_fontset_font): + * frame.c (x_default_parameter): + * xfaces.c (set_font_frame_param, Finternal_merge_in_global_face): + * xfns.c (x_default_scroll_bar_color_parameter) + (x_default_font_parameter, x_create_tip_frame): Use it. + * editfns.c (Fpropertize): Use local_cons. + * process.c (status_message): Use build_local_string. + * xfont.c (xfont_open): Use make_local_string. + * xdisp.c (build_desired_tool_bar_string): Use local_list4. + +2014-09-18 Paul Eggert <eggert@cs.ucla.edu> + + Port USE_LOCAL_ALLOCATORS code to clang 3.4 x86-64. + * lisp.h (USE_LOCAL_ALLOCATORS): Define only if __GNUC__ && + !__clang__. This works with GCC and with clang and is safer for + compilers we don't know about. + (local_cons): Rename parameter to make capture less likely. + +2014-09-17 Samuel Bronson <naesten@gmail.com> + + * unexmacosx.c (copy_data_segment): Port to GCC 4.6+ (Bug#9927). + +2014-09-17 Paul Eggert <eggert@cs.ucla.edu> - * w32.c (fcntl): Support O_NONBLOCK fcntl on the write side of - pipes. + Fix minor problems found by static checking. + * alloc.c, lisp.h (SAVE_TYPE_INT_OBJ, make_save_int_obj): + Remove; now unused. + * buffer.h (decode_buffer): Doc and indentation fixes. + * fns.c (Qstring_collate_lessp, Qstring_collate_equalp): Now static. + +2014-09-17 Dmitry Antipov <dmantipov@yandex.ru> + + Avoid clang-specific warnings. + * buffer.c (init_buffer): Shut up -Wself-assign. + * process.c (server_accept_connection): Shut up -Wunsequenced. + +2014-09-16 Daniel Colascione <dancol@dancol.org> + + * fns.c (sxhash): For symbols, use address as hash code. + +2014-09-16 Dmitry Antipov <dmantipov@yandex.ru> + + If USE_LOCAL_ALLOCATORS, allocate even more Lisp objects on stack. + * charset.c (load_charset_map_from_file): Use scoped_list2 + and build_local_string. + * buffer.c (Fother_buffer, other_buffer_safely, init_buffer): + * emacs.c (init_cmdargs, decode_env_path): + * fileio.c (Fexpand_file_name): + * fns.c (maybe_resize_hash_table) [ENABLE_CHECKING]: + * frame.c (x_get_arg): + * keyboard.c (safe_run_hooks_error): + * lread.c (load_warn_old_style_backquotes): + * xdisp.c (Fcurrent_bidi_paragraph_direction): + * xfns.c (x_default_scroll_bar_color_parameter, select_visual): + * xselect.c (x_clipboard_manager_error_1) + (x_clipboard_manager_save_all): + * xterm.c (x_term_init): Use build_local_string. + + Avoid more integer overflows on string size calculations. + * category.c (Fmake_category_set): + * xdisp.c (get_overlay_arrow_glyph_row): + * w32font.c (intern_font_name): Prefer ptrdiff_t to int. + +2014-09-15 Eli Zaretskii <eliz@gnu.org> + + * sound.c [WINDOWSNT]: Include w32common.h and mbstring.h. + (SOUND_WARNING) [WINDOWSNT]: Include in do..while and improve the + error message format. Use message_with_string to have non-ASCII + file names properly displayed. + (do_play_sound) [WINDOWSNT]: Use Unicode APIs to play sound files + when w32-unicode-filenames is non-nil, but not on Windows 9X, + where these APIs are not available even in UNICOWS.DLL. + Improve the format of error messages and include the file name in them + where appropriate. + (Fplay_sound_internal) [WINDOWSNT]: Make the MS-Windows branch + call play-sound-functions, per documentation. + + * w32.c (w32_get_long_filename, w32_get_short_filename): + Constify the input file name arguments. + + * w32.h (w32_get_long_filename, w32_get_short_filename): + Update prototypes. + +2014-09-15 Dmitry Antipov <dmantipov@yandex.ru> + + If USE_LOCAL_ALLOCATORS, allocate some Lisp objects on stack. + * lisp.h (local_cons, local_list1, local_list2, local_list3) + [USE_LOCAL_ALLOCATORS]: New macros. + [!USE_LOCAL_ALLOCATORS]: Fall back to regular functions. + (build_local_string): Avoid argument name expansion clash with + make_local_string. + * alloc.c (toplevel) + [USE_LOCAL_ALLOCATORS && GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS]: + Preprocessor guard to avoid impossible configuration. + * charset.c (Ffind_charset_region, Ffind_charset_string): + Use make_local_vector. + * lread.c (read1, substitute_object_recurse): Use scoped_cons. + * textprop.c (Fput_text_property, Fadd_face_text_property): + Use scoped_list2. + (copy_text_properties): Use local_cons and local_list3. + * chartab.c (uniprop_table): + * data.c (wrong_choice, wrong_range): + * doc.c (get_doc_string): + * editfns.c (format2): + * fileio.c (Fexpand_file_name, auto_save_error): + * fns.c (Fyes_or_no_p): + * font.c (font_parse_xlfd, font_parse_family_registry, font_add_log): + * fontset.c (Fset_fontset_font): + * keyboard.c (echo_add_key, echo_dash, parse_menu_item) + (read_char_minibuf_menu_prompt): + * keymap.c (silly_event_symbol_error, describe_vector): + * menu.c (single_menu_item): + * minibuf.c (Fread_buffer): + * process.c (status_message, Fformat_network_address) + (server_accept_connection): Use make_local_string and + build_local_string. Prefer compound literals where appropriate. + +2014-09-15 Daniel Colascione <dancol@dancol.org> + + * fns.c (Fsort): Tweak sort docstring. + +2014-09-15 Eli Zaretskii <eliz@gnu.org> + + * w32.c (fcntl): Support O_NONBLOCK fcntl on the write side of pipes. (sys_write): When a write to a non-blocking pipe returns ENOSPC, set errno to EAGAIN instead, to allow the caller to retry the write after some waiting. Fixes deadlocks when Emacs exchanges a lot of data through the pipe. (Bug#18420) -2014-09-13 Eli Zaretskii <eliz@gnu.org> - * sound.c (Fplay_sound_internal): Encode the sound file name in the ANSI codepage. Expand it against data-directory, as per docs, not against the current directory. No need to make a local copy @@ -171,92 +1109,791 @@ the string with "?" replacement characters, which will fail the caller. This avoids returning a random value in that case. -2014-09-11 Martin Rudalics <rudalics@gmx.at> +2014-09-15 Martin Rudalics <rudalics@gmx.at> * window.c (Fresize_mini_window_internal): Set w->total_lines from w->pixel_height (Bug#18422). -2014-09-09 Jan Djärv <jan.h.d@swipnet.se> +2014-09-15 Jan Djärv <jan.h.d@swipnet.se> * nsterm.m (updateFrameSize:, initFrameFromEmacs:) (toggleFullScreen:): Take frame_resize_pixelwise into account when setting resize increments (Bug#18435). -2014-09-09 Eli Zaretskii <eliz@gnu.org> +2014-09-15 Eli Zaretskii <eliz@gnu.org> * xdisp.c (pos_visible_p): Properly save and restore the iterator state around the call to line_bottom, since it can move the iterator to another screen line. This fixes off-by-one errors in the reported row in some rare cases. -2014-09-07 Eli Zaretskii <eliz@gnu.org> +2014-09-14 Jan Djärv <jan.h.d@swipnet.se> + + * callproc.c (init_callproc): Fix bug introduced at + 2014-09-07 (Bug#18474). + +2014-09-13 Dmitry Antipov <dmantipov@yandex.ru> + + Prefer ptrdiff_t to int and avoid integer overflows. + * fileio.c (make_temp_name): + * font.c (font_parse_family_registry): Avoid integer + overflow on string size calculation. + * data.c (Faset): Likewise for byte index. + +2014-09-12 Detlev Zundel <dzu@member.fsf.org> + + * buffer.c (syms_of_buffer): DEFSYM Qchoice (Bug#18337). + +2014-09-11 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (make_local_string): Nitpick indent. + * print.c (Fprin1_to_string): Remove unused GCPROs. + + More debugging aids around GCPROs. + * lisp.h (struct gcpro) [DEBUG_GCPRO]: Add extra members. + (GCPRO1, GCPRO2, GCPRO3, GCPRO4, GCPRO5, GCPRO6, GCPRO7): + Minor restyle. If DEBUG_GCPRO, initialize extra fields. + + * lread.c (readevalloop_eager_expand_eval): Add GCPRO and fix + bootstrap broken if GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE. + + Remove redundant GCPROs around Ffuncall and Fapply calls. + This is safe because Ffuncall protects all of its arguments by itself. + * charset.c (map_charset_for_dump): Remove redundant GCPRO. + * eval.c (Fapply, apply1, call0, call1, call2, call3, call4, call5) + (call6, call7): Likewise. Use compound literals where applicable. + (run_hook_with_args_2): Use compound literal. + +2014-09-11 Paul Eggert <eggert@cs.ucla.edu> + + Pacify --enable-gcc-warnings when no window system is used. + These warnings found that subscript error, so they seem worthwhile. + * composite.c (char_composable_p): Simplify a bit. + * frame.c (x_set_frame_parameters): Add an IF_LINT. + * frame.c (x_set_horizontal_scroll_bars, x_set_scroll_bar_height): + * frame.h (FRAME_HAS_HORIZONTAL_SCROLL_BARS): + * window.c (set_window_scroll_bars): + Use USE_HORIZONTAL_SCROLL_BARS for simplicity. + * frame.h [! USE_HORIZONTAL_SCROLL_BARS]: + Ignore -Wsuggest-attribute=const. + * window.h (USE_HORIZONTAL_SCROLL_BARS): New macro. + (WINDOW_HAS_HORIZONTAL_SCROLL_BAR): Use it. + +2014-09-10 Paul Eggert <eggert@penguin.cs.ucla.edu> + + * charset.c (Fget_unused_iso_final_char): Fix subscript error. + Use check_iso_charset_parameter instead of doing the checks by hand. + (check_iso_charset_parameter): Move up. Check parameters a bit + more carefully, and return true for 96-char sets. All callers changed. + +2014-09-10 Paul Eggert <eggert@cs.ucla.edu> + + Simplify lisp.h by removing the __COUNTER__ business. + Problem reported by Dmitry Antipov in: + http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00220.html + * lisp.h (make_local_vector, make_local_string) + (build_local_string): Simplify by not bothering with __COUNTER__. + The __COUNTER__ business wasn't working properly, and was needed + only for hypothetical future expansion anyway. + +2014-09-10 Alp Aker <alp.tekin.aker@gmail.com> + + * nsterm.m (ns_draw_fringe_bitmap): Use the same logic as other + terms to determine bitmap color. (Bug#18437) + +2014-09-10 Eli Zaretskii <eliz@gnu.org> + + * w32.c (sys_write): Use SAFE_NALLOCA for the NL -> CRLF + translation buffer. + +2014-09-10 Paul Eggert <eggert@cs.ucla.edu> + + * xterm.c (handle_one_xevent): Add braces to pacify gcc -Wall. + +2014-09-10 Jan Djärv <jan.h.d@swipnet.se> + + * xterm.c (handle_one_xevent): Detect iconified by looking at + _NET_WM_STATE_HIDDEN. + +2014-09-10 Paul Eggert <eggert@cs.ucla.edu> + + * lisp.h (DEFINE_GDB_SYMBOL_ENUM): Remove. + These can generate a constant with the correct value but the wrong + width, which doesn't work as a printf argument. All uses removed. + Problem reported by Dmitry Antipov in: + http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00213.html + (ENUMABLE): Remove; no longer needed. + (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): + Remove; no longer needed because of the above change. + Each definiens moved to the only use. + + Improve the experimental local and scoped allocation. + * alloc.c (local_string_init, local_vector_init): + New functions, defined if USE_LOCAL_ALLOCATORS. + Mostly, these are moved here from lisp.h, as it's not + clear it's worth making them inline. + * lisp.h (USE_STACK_LISP_OBJECTS): Default to false. + (GCALIGNED): Depend on HAVE_STRUCT_ATTRIBUTE_ALIGNED and + USE_STACK_LISP_OBJECTS, not on a laundry list. + (local_string_init, local_vector_init): New decls. + (union Aligned_Cons): New type. + (scoped_cons): Use it. Give up on the char trick, as it's a too + much of a maintenance hassle; if someone wants this speedup + they'll just need to convince their compiler to align properly. + Conversely, use the speedup if struct Lisp_Cons happens to + be aligned even without a directive. Better yet, help it along + by using union Aligned_Cons rather than struct Lisp_Cons. + (pointer_valid_for_lisp_object): Remove. This check is not + necessary, since make_lisp_ptr is already doing it. All uses removed. + (local_vector_init, local_string_init): Move to alloc.c. + (build_local_vector): Remove this awkward macro, replacing with ... + (make_local_vector): New macro, which acts more like a function. + Use statement expressions and use __COUNTER__ to avoid macro + capture. Fall back on functions if these features are not supported. + (build_local_string, make_local_string): Likewise. + +2014-09-09 Dmitry Antipov <dmantipov@yandex.ru> + + * xterm.c (x_term_init): Consolidate duplicated code. + [USE_LUCID]: Revert 2014-04-02 change (Bug#18403). Add comment. + (x_delete_terminal): Do not close X connection fd (Bug#18403). + Add eassert and mark dpyinfo as dead only if it was alive. + + Add macros to allocate temporary Lisp objects with alloca. + Respect MAX_ALLOCA and fall back to regular GC for large objects. + * character.h (parse_str_as_multibyte): Move prototype to ... + * lisp.h (parse_str_as_multibyte): ... here. + (struct Lisp_Cons): Add GCALIGNED attribute if supported. + (scoped_cons, scoped_list2, build_local_vector, build_local_string): + New macros. + (scoped_cons_init, pointer_valid_for_lisp_object, local_vector_init) + (local_string_init): New functions. + * alloc.c (verify_alloca) [ENABLE_CHECKING]: New function. + (init_alloc_once): Call it. + + Cleanup last change and make all new stuff conditional. + * lisp.h (build_local_string): Rename to ... + (make_local_string): ... this macro. + (build_local_string, scoped_list1, scoped_list3): New macros. + (toplevel) [USE_STACK_LISP_OBJECTS]: Define all new macros + and functions as such, use regular fallbacks otherwise. + * alloc.c (verify_alloca) [USE_STACK_LISP_OBJECTS]: Define + conditionally. + +2014-09-08 Eli Zaretskii <eliz@gnu.org> * dispnew.c (prepare_desired_row): When MODE_LINE_P is zero, always make sure the marginal areas of the row are in sync with what the window wants. (Bug#18419) -2014-09-04 Eli Zaretskii <eliz@gnu.org> - * data.c (set_internal): Use assq_no_quit, not Fassq, to find an existing binding of a variable, to avoid silently aborting commands that use specbind. (Bug#18331) -2014-09-02 Eli Zaretskii <eliz@gnu.org> +2014-09-07 Paul Eggert <eggert@cs.ucla.edu> + + Fix bug uncovered by changing alloca to auto buffer (Bug#18410). + * coding.c (growable_destination): New function. + (produce_chars): Use it for sanity checks. Do not fiddle with + dst_end if the source and destination are both nil, as it's + the caller's responsibility to avoid overlap. + * keyboard.c (read_decoded_event_from_main_queue): + The destination must be MAX_MULTIBYTE_LENGTH times the max source + length, not 4 times, to prevent decode_coding_c_string from trying + to reallocate a destination. This removes the need for the FIXME. + + * callproc.c (exec_failed) [DOS_NT]: Define a dummy. + All callers simplified. Add a comment about exec_failed, vfork, + and alloca. + + Adjust drag-and-drop fix when window is above top (Bug#18303). + * xselect.c (x_fill_property_data): Don't let sign bit of negative + XCDR bleed into XCAR's encoded value. Improve checks for + out-of-range data while we're at it. + +2014-09-07 Jan Djärv <jan.h.d@swipnet.se> + + * xselect.c (x_fill_property_data): Handle negative XCDR when data + is CONSP (Bug#18303). + +2014-09-07 Eli Zaretskii <eliz@gnu.org> + + * callproc.c (child_setup) [WINDOWSNT]: Don't call exec_failed if + 'alloca' gets passed arguments larger than MAX_ALLOCA. + + * font.c (MAX): Define if not defined elsewhere. + +2014-09-07 Paul Eggert <eggert@cs.ucla.edu> + + * keyboard.c (read_decoded_event_from_main_queue): Reinstitute alloca + here for destination buffer, to work around what appears to be a + bug in decode_coding_c_string when the source and destination are + both C strings. + + Use SAFE_ALLOCA etc. to avoid unbounded stack allocation (Bug#18410). + This follows up on the recent thread in emacs-devel on alloca; see: + http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00042.html + This patch also cleans up alloca-related glitches noted while + examining the code looking for unbounded alloca. + * alloc.c (listn): + * callproc.c (init_callproc): + Rewrite to avoid need for alloca. + * buffer.c (mouse_face_overlay_overlaps) + (report_overlay_modification): + * buffer.h (GET_OVERLAYS_AT): + * coding.c (make_subsidiaries): + * doc.c (Fsnarf_documentation): + * editfns.c (Fuser_full_name): + * fileio.c (Ffile_name_directory, Fexpand_file_name) + (search_embedded_absfilename, Fsubstitute_in_file_name): + * fns.c (Fmake_hash_table): + * font.c (font_vconcat_entity_vectors, font_update_drivers): + * fontset.c (fontset_pattern_regexp, Ffontset_info): + * frame.c (Fmake_terminal_frame, x_set_frame_parameters) + (xrdb_get_resource, x_get_resource_string): + * ftfont.c (ftfont_get_charset, ftfont_check_otf, ftfont_drive_otf): + * ftxfont.c (ftxfont_draw): + * image.c (xbm_load, xpm_load, jpeg_load_body): + * keyboard.c (echo_add_key, menu_bar_items, tool_bar_items) + + * keymap.c (Fdescribe_buffer_bindings, describe_map): + * lread.c (openp): + * menu.c (digest_single_submenu, find_and_call_menu_selection) + (find_and_return_menu_selection): + * print.c (PRINTFINISH): + * process.c (Fformat_network_address): + * scroll.c (do_scrolling, do_direct_scrolling, scrolling_1): + * search.c (search_buffer, Fmatch_data, Fregexp_quote): + * sound.c (wav_play, au_play): + * syntax.c (skip_chars): + * term.c (tty_menu_activate, tty_menu_show): + * textprop.c (get_char_property_and_overlay): + * window.c (Fset_window_configuration): + * xdisp.c (safe__call, next_overlay_change, vmessage) + (compute_overhangs_and_x, draw_glyphs, note_mouse_highlight): + * xfaces.c (face_at_buffer_position): + * xmenu.c (x_menu_show): + Use SAFE_ALLOCA etc. instead of plain alloca, since the + allocation size isn't bounded. + * callint.c (Fcall_interactively): Redo memory_full check + so that it can be done at compile-time on some platforms. + * coding.c (MAX_LOOKUP_MAX): New constant. + (get_translation_table): Use it. + * callproc.c (call_process): Use SAFE_NALLOCA instead of + SAFE_ALLOCA, to catch integer overflows on size calculation. + (exec_failed) [!DOS_NT]: New function. + (child_setup) [!DOS_NT]: Use it. + * editfns.c (Ftranspose_regions): + Hoist USE_SAFE_ALLOC + SAFE_FREE out of 'if'. + * editfns.c (check_translation): + Allocate larger buffers on the heap. + * eval.c (internal_lisp_condition_case): + Check for MAX_ALLOCA overflow. + * fns.c (sort_vector): Use SAFE_ALLOCA_LISP rather than Fmake_vector. + (Fbase64_encode_region, Fbase64_decode_region): + Avoid unnecessary calls to SAFE_FREE before 'error'. + * buffer.c (mouse_face_overlay_overlaps): + * editfns.c (Fget_pos_property, check_translation): + * eval.c (Ffuncall): + * font.c (font_unparse_xlfd, font_find_for_lface): + * ftfont.c (ftfont_drive_otf): + * keyboard.c (echo_add_key, read_decoded_event_from_main_queue) + (menu_bar_items, tool_bar_items): + * sound.c (Fplay_sound_internal): + * xdisp.c (load_overlay_strings, dump_glyph_row): + Use an ordinary auto buffer rather than alloca, since the + allocation size is fixed and small. + * ftfont.c: Include <c-strcase.h>. + (matching_prefix): New function. + (get_adstyle_property): Use it, to avoid need for alloca. + * keyboard.c (echo_add_key): + * keymap.c (describe_map): Use ptrdiff_t, not int. + * keyboard.c (echo_add_key): Prefer sizeof to strlen. + * keymap.c (Fdescribe_buffer_bindings): Use SBYTES, not SCHARS, + when counting bytes. + * lisp.h (xlispstrdupa): Remove, replacing with ... + (SAFE_ALLOCA_STRING): ... new macro with different API. + This fixes a portability problem, namely, alloca result + passed to another function. All uses changed. + (SAFE_ALLOCA, SAFE_ALLOCA_LISP): Check for MAX_ALLOCA, + not MAX_ALLOCA - 1. + * regex.c (REGEX_USE_SAFE_ALLOCA, REGEX_SAFE_FREE) + (REGEX_ALLOCATE): New macros. + (REGEX_REALLOCATE, REGEX_ALLOCATE_STACK, REGEX_REALLOCATE_STACK) + (REGEX_FREE_STACK, FREE_VARIABLES, re_match_2_internal): + Use them. + * xdisp.c (message3): Use SAFE_ALLOCA_STRING rather than doing it + by hand. + (decode_mode_spec_coding): Store directly into buf rather than + into an alloca temporary and copying the temporary to the buf. + +2014-09-06 Eli Zaretskii <eliz@gnu.org> + + * Makefile.in (EMACS_HEAPSIZE): Remove, no longer used. (Bug#18416) + +2014-09-04 Jan D <jan.h.d@swipnet.se> + + * xterm.c (x_term_init): Don't call x_session_initialize if running + as a daemon (Bug#18375). + + * xsmfns.c: Initialize ice_fd. + +2014-09-04 Paul Eggert <eggert@cs.ucla.edu> + + Less chatter in 'make' output. + * Makefile.in (AM_V_GEN, am__v_GEN_, am__v_GEN_0, am__v_GEN_1, AM_V_at) + (am__v_at_, am__v_at_0, am__v_at_1): New macros, taken from Automake. + ($(etc)/DOC, buildobj.h, gl-stamp): Use them. + +2014-09-03 Martin Rudalics <rudalics@gmx.at> + + * buffer.c (scroll-bar-height): Fix typo in doc-string. + * frame.c (Vdefault_frame_horizontal_scroll_bars): + Remove variable. + * nsfns.m (Fx_create_frame): + * w32fns.c (Fx_create_frame): + * xfns.c (Fx_create_frame): Default horizontal scroll bars to + nil. + +2014-09-03 Eli Zaretskii <eliz@gnu.org> * dispnew.c (buffer_posn_from_coords): Fix an off-by-one error in the reported row in the case of a window with a header line, by improving on the fix committed in 2011-10-08T10:58:50Z!eliz@gnu.org eliz@gnu.org-20111008105850-ht4tvsayohvr1kjc. (Bug#18384) -2014-09-02 Paul Eggert <eggert@cs.ucla.edu> +2014-09-03 Paul Eggert <eggert@cs.ucla.edu> * eval.c (internal_lisp_condition_case): Don't overrun the stack when configured --with-wide-int on typical 32-bit platforms. -2014-08-31 Eli Zaretskii <eliz@gnu.org> +2014-09-03 Eli Zaretskii <eliz@gnu.org> * xdisp.c (display_and_set_cursor): Call erase_phys_cursor also when HPOS is negative, for the benefit of R2L glyph rows whose newline overflows into the fringe. -2014-08-30 Ken Brown <kbrown@cornell.edu> +2014-09-03 Ken Brown <kbrown@cornell.edu> - * conf_post.h (strnicmp) [CYGWIN && HAVE_NTGUI]: Define. - (Bug#18366) + * conf_post.h (strnicmp) [CYGWIN && HAVE_NTGUI]: Define. (Bug#18366) -2014-08-28 Eli Zaretskii <eliz@gnu.org> +2014-09-02 Paul Eggert <eggert@cs.ucla.edu> - * syntax.c (scan_lists): Don't examine positions before BEGV. - (Bug#18339) + Minor cleanup of recent strlen-avoiding patch. + * fileio.c (CHECK_LENGTH): Remove. + Rewrite callers so that they don't need it. + (Fexpand_file_name) [DOS_NT]: Fix a case where directory length + variable wasn't set. + +2014-09-02 Dmitry Antipov <dmantipov@yandex.ru> + + * fileio.c (CHECK_LENGTH): New macro. + (Fexpand_file_name): Use it and get rid of a few more calls + to strlen and strcat. + * callproc.c (egetenv_internal): Add arg and rename from egetenv ... + * lisp.h (egetenv): ... because of a new inline function used to + avoid calls to strlen for a compile-time constants. + + * buffer.h (decode_buffer): New function. + * buffer.c (Fbuffer_name, Fbuffer_file_name, Fbuffer_base_buffer) + (Fbuffer_local_variables, Fbuffer_modified_p, Fbuffer_modified_tick) + (Fbuffer_chars_modified_tick, Fdelete_all_overlays): + * data.c (Flocal_variables_p): + * fileio.c (Fverify_visited_file_modtime): + * marker.c (live_buffer): Use it. + +2014-09-01 Dmitry Antipov <dmantipov@yandex.ru> + + Avoid extra calls to strlen in filesystem I/O routines. + * fileio.c (Fexpand_file_name): Avoid calls to strlen if + the length of 'newdir' is known or may be precalculated. + (file_accessible_directory_p): Prefer to pass Lisp_Object, + not 'char *', and so use precalculated length. + (Ffile_accessible_directory_p): + * callproc.c (encode_current_directory, init_callproc): + * charset.c (init_charset): + * lread.c (load_path_check, load_path_default): Adjust users. + * lisp.h (file_accessible_directory_p): Tweak prototype. + +2014-09-01 Eli Zaretskii <eliz@gnu.org> + + * w32proc.c (w32_compare_strings): Support "C" and "POSIX" + locales. + +2014-09-01 Paul Eggert <eggert@cs.ucla.edu> + + --enable-silent-rules now suppresses more chatter. + * Makefile.in (AM_DEFAULT_VERBOSITY, AM_V_CC, am__v_CC_) + (am__v_CC_0, am__v_CC_1, AM_V_CCLD, am__v_CCLD_, am__v_CCLD_0) + (am__v_CCLD_1): New macros, taken from Automake. + (.c.o, .m.o, temacs$(EXEEXT)): Use them. + + Clean up extern decls a bit. + * bytecode.c: Include blockinput.h and keyboard.h rather + than rolling their APIs by hand. + * emacs.c: Include regex.h and rely on its and lisp.h's API + rather than rolling them by hand. + * lastfile.c: Include lisp.h, to check this file's API. + * lisp.h (lisp_eval_depth, my_edata, my_endbss, my_endbss_static): + New decls. + * regex.h (re_max_failures): New decl. + * unexcw.c, unexmacosx.c, unexw32.c: + Rely on lisp.h's API rather than rolling it by hand. + * vm-limit.c (__after_morecore_hook, __morecore, real_morecore): + Declare at top level, to pacify GCC -Wnested-externs. -2014-08-25 Eli Zaretskii <eliz@gnu.org> +2014-08-31 Eli Zaretskii <eliz@gnu.org> - * conf_post.h (_GL_EXECINFO_INLINE) [MSDOS]: Don't define. + * xdisp.c (get_glyph_string_clip_rects): Don't let the width of a + clipping rectangle become negative (i.e. large positive, since + it's an unsigned data type). This can happen in R2L hscrolled + glyph rows, and caused us to draw the cursor glyph on the fringe. + For the details, see + http://lists.gnu.org/archive/html/emacs-devel/2014-08/msg00543.html. + +2014-08-31 Ken Brown <kbrown@cornell.edu> + + * gmalloc.c: Don't include <stdlib.h>. Declare system malloc and + friends before defining hybrid_malloc and friends if HYBRID_MALLOC + is defined. (Bug#18368) + +2014-08-30 Paul Eggert <eggert@cs.ucla.edu> + + Vector-sorting fixes (Bug#18361). + It's not safe to call qsort or qsort_r, since they have undefined + behavior if the user-specified predicate is not a total order. + Also, watch out for garbage-collection while sorting vectors. + * fns.c: Include <vla.h>. + (sort_vector_predicate) [!HAVE_QSORT_R]: Remove. + (sort_vector_compare): Remove, replacing with .... + (inorder, merge_vectors, sort_vector_inplace, sort_vector_copy): + ... these new functions. + (sort_vector): Rewrite to use the new functions. + GCPRO locals, since the predicate can invoke the GC. + Since it's in-place return void; caller changed. + (merge): Use 'inorder', for clarity. + + * sysdep.c (str_collate): Clear errno just before wcscoll(_l). + One can't hoist this out of the 'if', because intervening calls to + newlocale, twolower, etc. can change errno. + +2014-08-30 Eli Zaretskii <eliz@gnu.org> + + * sysdep.c (str_collate) [__STDC_ISO_10646__]: Improve the + wording of the error messages. + (str_collate) [WINDOWSNT]: Signal an error if w32_compare_strings + sets errno. + + * w32proc.c (get_lcid_callback): Accept locale specifications + without the country part, as in "enu" vs "enu_USA". + (w32_compare_strings): Signal an error if a locale was specified, + but couldn't be translated into a valid LCID. + +2014-08-29 Michael Albinus <michael.albinus@gmx.de> + + * sysdep.c (str_collate) [__STDC_ISO_10646__]: Move up setting errno. + +2014-08-29 Paul Eggert <eggert@cs.ucla.edu> + + * sysdep.c (str_collate) [__STDC_ISO_10646__]: Do not look at + errno after towlower_l. errno's value is not specified after + towlower_l. Instead, assume that towlower_l returns its argument + on failure, which is portable in practice. + +2014-08-29 Eli Zaretskii <eliz@gnu.org> + + * fns.c (Fstring_collate_lessp, Fstring_collate_equalp): Doc fix. + + * w32proc.c (w32_compare_strings): Accept additional argument + IGNORE_CASE. Set up the flags for CompareStringW to ignore case + if requested. If w32-collate-ignore-punctuation is non-nil, add + NORM_IGNORESYMBOLS to the flags. + (LINGUISTIC_IGNORECASE): Define if not already defined. + (syms_of_ntproc) <Vw32_collate_ignore_punctuation>: New variable. + + * sysdep.c (str_collate) [WINDOWSNT]: Adapt to the interface + change. + +2014-08-29 Michael Albinus <michael.albinus@gmx.de> + + * sysdep.c (LC_CTYPE, LC_CTYPE_MASK, towlower_l): + Define substitutes for platforms that lack them. + (str_collate): Add arguments locale and ignore_case. + + * fns.c (Fstring_collate_lessp, Fstring_collate_equalp): + Add optional arguments LOCALE and IGNORE-CASE. + + * lisp.h (str_collate): Adapt argument list. + +2014-08-29 Dmitry Antipov <dmantipov@yandex.ru> + + Add vectors support to Fsort. + * fns.c (sort_vector, sort_vector_compare): New functions. + (sort_list): Likewise, refactored out of ... + (Fsort): ... adjusted user. Mention vectors in docstring. + (sort_vector_predicate) [!HAVE_QSORT_R]: New variable. + * alloc.c (make_save_int_obj): New function. + * lisp.h (enum Lisp_Save_Type): New member SAVE_TYPE_INT_OBJ. + (make_save_int_obj): Add prototype. + + Fix last change to support Darwin/OSX and FreeBSD (Bug#18354). + * sysdep.c (sort_vector_compare) [DARWIN_OS || __FreeBSD__]: + Conditionally define to match system's qsort_r signature. + (sort_vector) [DARWIN_OS || __FreeBSD__]: Likewise in call to qsort_r. + +2014-08-28 Ken Brown <kbrown@cornell.edu> + + Add support for HYBRID_MALLOC, allowing the use of gmalloc before + dumping and the system malloc after dumping. (Bug#18222) + + * conf_post.h (malloc, realloc, calloc, free) [HYBRID_MALLOC]: + Define as macros, expanding to hybrid_malloc, etc. + (HYBRID_GET_CURRENT_DIR_NAME): New macro. + (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Define as + macro. + * gmalloc.c: Set up the infrastructure for HYBRID_MALLOC, with a + full implementation on Cygwin. Remove Cygwin-specific code that + is no longer needed. + (malloc, realloc, calloc, free, aligned_alloc) [HYBRID_MALLOC]: + Redefine as macros expanding to gmalloc, grealloc, etc. + (DUMPED, ALLOCATED_BEFORE_DUMPING) [CYGWIN]: New macros. + (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Undefine. + (USE_PTHREAD, posix_memalign) [HYBRID_MALLOC]: Don't define. + (hybrid_malloc, hybrid_calloc, hybrid_free, hybrid_realloc) + [HYBRID_MALLOC]: + (hybrid_get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: + (hybrid_aligned_alloc) [HYBRID_MALLOC && (HAVE_ALIGNED_ALLOC || + HAVE_POSIX_MEMALIGN)]: New functions. + * alloc.c (aligned_alloc) [HYBRID_MALLOC && (ALIGNED_ALLOC || + HAVE_POSIX_MEMALIGN)]: Define as macro expanding to + hybrid_aligned_alloc; declare. + (USE_ALIGNED_ALLOC) [HYBRID_MALLOC && (ALIGNED_ALLOC || + HAVE_POSIX_MEMALIGN)]: Define. + (refill_memory_reserve) [HYBRID_MALLOC]: Do nothing. + * sysdep.c (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: + Define as macro, expanding to gget_current_dir_name, and define + the latter. + * emacs.c (main) [HYBRID_MALLOC]: Don't call memory_warnings() or + malloc_enable_thread(). Don't initialize malloc. + * lisp.h (NONPOINTER_BITS) [CYGWIN]: Define (because GNU_MALLOC is + no longer defined on Cygwin). + (refill_memory_reserve) [HYBRID_MALLOC]: Don't declare. + * sheap.c (bss_sbrk_buffer_end): New variable. + * unexcw.c (__malloc_initialized): Remove variable. + * ralloc.c: Throughout, treat HYBRID_MALLOC the same as + SYSTEM_MALLOC. + * xdisp.c (decode_mode_spec) [HYBRID_MALLOC]: Don't check + Vmemory_full. + +2014-08-28 Martin Rudalics <rudalics@gmx.at> + + * w32term.c (w32_horizontal_scroll_bar_handle_click): + In `event->y' return entire range (the size of the scroll bar minus + that of the thumb). + * xterm.c (xm_scroll_callback, xaw_jump_callback): In `whole' + return entire range (the scaled size of the scroll bar minus + that of the slider). In `portion' return the scaled position of + the slider. + (xaw_jump_callback): Restore part of code for vertical scroll + bar broken in change from 2014-07-27. + (xaw_scroll_callback): Provide incremental scrolling with + horizontal scroll bars. -2014-08-18 Eli Zaretskii <eliz@gnu.org> +2014-08-28 Eli Zaretskii <eliz@gnu.org> - * xdisp.c (handle_stop): Improve commentary. + * conf_post.h (_GL_EXECINFO_INLINE) [MSDOS]: Don't define. * indent.c (Fvertical_motion): Fix vertical motion up through a display property after a newline. (Bug#18276) -2014-08-17 Eli Zaretskii <eliz@gnu.org> - * xdisp.c (display_line): Don't assume that the call to reseat_at_next_visible_line_start ends up at a character - immediately following the newline on the previous line. Avoids - setting the ends_at_zv_p flag on screen lines that are not at or + immediately following the newline on the previous line. + Avoids setting the ends_at_zv_p flag on screen lines that are not at or beyond ZV, which causes infloop in redisplay. For the details, see http://lists.gnu.org/archive/html/emacs-devel/2014-08/msg00368.html. * dispnew.c (buffer_posn_from_coords): Fix mirroring of X coordinate for hscrolled R2L screen lines. (Bug#18277) -2014-08-11 Ken Brown <kbrown@cornell.edu> +2014-08-28 Paul Eggert <eggert@cs.ucla.edu> + + * sysdep.c (LC_COLLATE, LC_COLLATE_MASK): Give individual defaults + (Bug#18051). + +2014-08-27 Eli Zaretskii <eliz@gnu.org> + + * syntax.c (scan_lists): Don't examine positions before BEGV. + (Bug#18339) + +2014-08-27 Paul Eggert <eggert@cs.ucla.edu> + + Improve robustness of new string-collation code (Bug#18051). + * sysdep.c (LC_COLLATE, LC_COLLATE_MASK, freelocale, locale_t) + (newlocale, wcscoll_l): Define substitutes for platforms that + lack them, so as to simplify the mainline code. + (str_collate): Simplify the code by assuming the above definitions. + Use wcscoll_l, not uselocale, as uselocale is too fragile. + For example, the old version left the Emacs in the wrong locale if + wcscoll reported an error. Use 'int', not ptrdiff_t, for the int + result. Report an error if newlocale fails. + +2014-08-27 Michael Albinus <michael.albinus@gmx.de> + + * lisp.h (str_collate): + * sysdep.c (str_collate): Return int. + (str_collate) [__STDC_ISO_10646__]: Propagate error of wcscoll. + +2014-08-27 Dmitry Antipov <dmantipov@yandex.ru> + + Fix some glitches in previous change. + * sysdep.c (stack_direction): Replace stack_grows_down + to simplify calculation of stack boundaries. + (handle_sigsegv): Check whether we really crash somewhere near + to stack boundary, and handle fatal signal as usual if not. + (init_sigsegv): Adjust accordingly. + * keyboard.c (Vtop_level_message): Rename to + Vinternal__top_level_message, as suggested by Stefan Monnier in + http://lists.gnu.org/archive/html/emacs-devel/2014-08/msg00493.html + All related users changed. + +2014-08-26 Dmitry Antipov <dmantipov@yandex.ru> + + Handle C stack overflow caused by too nested Lisp evaluation. + * lisp.h (toplevel) [HAVE_STACK_OVERFLOW_HANDLING]: Declare + siglongjmp point to transfer control from SIGSEGV handler. + * keyboard.c (return_to_command_loop, recover_top_level_message) + [HAVE_STACK_OVERFLOW_HANDLING]: New variables. + (regular_top_level_message): New variable. + (command_loop) [HAVE_STACK_OVERFLOW_HANDLING]: Handle non-local + exit from SIGSEGV handler and adjust message displayed by Vtop_level + if appropriate. + (syms_of_keyboard): DEFVAR Vtop_level_message and initialize + new variables described above. + * sysdep.c [HAVE_SYS_RESOURCE_H]: Include sys/resource.h as such. + (stack_grows_down, sigsegv_stack, handle_sigsegv) + [HAVE_STACK_OVERFLOW_HANDLING]: New variables and function. + (init_sigsegv): New function. + (init_signals): Use it. + +2014-08-25 Ken Brown <kbrown@cornell.edu> + + * emacs.c (main): Remove use of obsolete macro + G_SLICE_ALWAYS_MALLOC. + +2014-08-25 Eli Zaretskii <eliz@gnu.org> + + Implement locale-sensitive string collation for MS-Windows. + * w32proc.c (get_lcid_callback, get_lcid, w32_compare_strings): + New functions. (Bug#18051) + + * w32.h (w32_compare_strings): Add prototype. + + * w32.c <g_b_init_compare_string_w>: New global flag. + (globals_of_w32): Initialize it. + + * sysdep.c (str_collate) [WINDOWSNT]: Implementation for MS-Windows. + + * fns.c (Fstring_collate_lessp, Fstring_collate_equalp) + [WINDOWSNT]: Call str_collate on MS-Windows. + +2014-08-25 Dmitry Antipov <dmantipov@yandex.ru> + + One more minor cleanup of font subsystem. + * font.h (struct font_driver): Convert text_extents to + return void because returned value is never actually used. + * macfont.m (macfont_text_extents): + * w32font.c (w32font_text_extents): + * xftfont.c (xftfont_text_extents): Adjust to return void + and assume that 'metrics' argument is always non-NULL. + * ftfont.c (ftfont_text_extents): + * xfont.c (xfont_text_extents): Likewise. Avoid redundant memset. + +2014-08-25 Paul Eggert <eggert@cs.ucla.edu> + + Minor cleanups of str_collate fix (Bug#18051). + * fns.c (str_collate): Move decl from here ... + * lisp.h (str_collate): ... to here. + * sysdep.c (str_collate): Prune away some of the forest of ifdefs. + Remove unnecessary casts. Use SAFE_NALLOCA to avoid + potential problems with integer overflow. Don't assume + setlocale succeeds. Remove unnecessary test before restoring + locale via setlocale, and free the copied setlocale string + when done with it. + +2014-08-24 Michael Albinus <michael.albinus@gmx.de> + + * fns.c (Fstring_collate_lessp, Fstring_collate_equalp): New DEFUNs. + + * sysdep.c (str_collate): New function. (Bug#18051) + +2014-08-23 Karol Ostrovsky <karol.ostrovsky@gmail.com> (tiny change) + + * Makefile.in (emacs$(EXEEXT)): Retry deletion of bootstrap-emacs + if the initial "rm -f" fails. This is for MinGW builds, where + MS-Windows will not allow deleting the executable file of a + running program. + +2014-08-20 Eli Zaretskii <eliz@gnu.org> + + * w32term.c (w32_scroll_bar_handle_click) + (w32_horizontal_scroll_bar_handle_click) + (x_scroll_bar_report_motion) + (x_horizontal_scroll_bar_report_motion): For SB_THUMBPOSITION and + SB_THUMBTRACK, use the 32-bit position information returned by + GetScrollInfo, not the 16-bit information returned in the Windows + message sent to us. + +2014-08-19 Eli Zaretskii <eliz@gnu.org> + + * w32term.c (w32_horizontal_scroll_bar_handle_click): Fix the + second coordinate ('y') reported for dragging the horizontal + scroll bar thumb. + +2014-08-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * xdisp.c (erase_phys_cursor): Fix confusion between window-relative + and text area-relative x-coordinates. + +2014-08-17 Eli Zaretskii <eliz@gnu.org> + + Avoid overwriting the reversed_p flags in the glyph matrices when + init_iterator or start_display are called. + * xdisp.c (init_iterator): Don't initialize the reversed_p flag of + the glyph row here. + (tool_bar_height, redisplay_tool_bar, try_window) + (try_window_reusing_current_matrix, try_window_id) + (get_overlay_arrow_glyph_row, display_menu_bar): Initialize the + reversed_p flag of the iterator's glyph row where the glyph row + is going to be redrawn. + +2014-08-16 Paul Eggert <eggert@cs.ucla.edu> + + * xdisp.c (set_horizontal_scroll_bar): Don't use uninitialized local. + +2014-08-16 Martin Rudalics <rudalics@gmx.at> + + * w32term.c (w32_horizontal_scroll_bar_handle_click): In y part + of emacs_event return length from si.nPage to si.nMax. + * xdisp.c (set_horizontal_scroll_bar): For right-to-left text + interchange start and end of thumb. + +2014-08-15 Ken Brown <kbrown@cornell.edu> * gmalloc.c (_malloc_mutex, _aligned_blocks_mutex) [CYGWIN]: Use ERRORCHECK mutexes. (Bug#18222) +2014-08-12 Martin Rudalics <rudalics@gmx.at> + + * frame.c (set_menu_bar_lines_1): Remove. + (set_menu_bar_lines): Call change_frame_size instead of + set_menu_bar_lines_1. + +2014-08-11 Jan Djärv <jan.h.d@swipnet.se> + + * nsfns.m (Fx_create_frame): Call adjust_frame_size, + set f->official. + 2014-08-11 Glenn Morris <rgm@gnu.org> * fileio.c: Revert 2013-01-31 change, which chose coding system for @@ -266,42 +1903,136 @@ Move last piece back here from Fwrite_region. (Fwrite_region, syms_of_fileio): Update for above changes. -2014-08-09 Martin Rudalics <rudalics@gmx.at> - - * window.c (Fwindow_new_total, Fwindow_new_normal) - (Fwindow_new_pixel, Fset_window_new_pixel) - (Fset_window_new_total, Fset_window_new_normal): Second attempt - to fix the doc-strings of these functions. See: - http://lists.gnu.org/archive/html/bug-gnu-emacs/2014-08/msg00287.html - -2014-08-08 Martin Rudalics <rudalics@gmx.at> +2014-08-11 Martin Rudalics <rudalics@gmx.at> * window.c (Fwindow_valid_p): Fix doc-string (Bug#18194). (Fwindow_new_total, Fwindow_normal_size, Fwindow_new_normal) (Fwindow_new_pixel, Fset_window_new_pixel) (Fset_window_new_total, Fset_window_new_normal) (Fwindow_resize_apply): Fix doc-strings (see Bug#18112). + See also: + http://lists.gnu.org/archive/html/bug-gnu-emacs/2014-08/msg00287.html -2014-08-07 Eli Zaretskii <eliz@gnu.org> +2014-08-11 Eli Zaretskii <eliz@gnu.org> * fontset.c (Finternal_char_font): Recompute basic faces if the frame's face cache was cleared. (Bug#18162) -2014-08-05 Dmitry Antipov <dmantipov@yandex.ru> +2014-08-11 Dmitry Antipov <dmantipov@yandex.ru> Fix bug with uninitialized undo list of an indirect buffer (Bug#18180). * buffer.c (Fmake_indirect_buffer): Initialize undo list with the base buffer's undo list. -2014-08-03 Dmitry Antipov <dmantipov@yandex.ru> +2014-08-10 Reuben Thomas <rrt@sc3d.org> + + Fix a couple of recent inadvertent breaks of the MSDOS port. + * msdos.c: include required menu.h + * term.c: set correct menu_show_hook on MSDOS. - Fix bug with an attempt to select uninitialized frame (Bug#18161). - * xfns.c (Fx_create_frame): Move call to change_frame_size to - a section where Lisp evaluation is disabled. This way a pointer - to uninitialized frame is not accessible from Lisp, which becomes - critical if following call to x_figure_window_size throws an error. +2014-08-10 Martin Rudalics <rudalics@gmx.at> + + Fix handling of menu bar line on TTY frames (Bug#18136) + (Bug#18196). + * dispnew.c (handle_window_change_signal): + * keyboard.c (Fsuspend_emacs): Call change_frame_size with + frame's menu bar lines subtracted from height. + * frame.c (frame_inhibit_resize): Inhibit resizing of TTY + frames. + (adjust_frame_size): Count in menu bar when setting FrameRows. + (make_terminal_frame): When setting up the frame's lines and + text height don't count in the menu bar. + (Fmake_terminal_frame): Call adjust_frame_size with menu bar + lines subtracted from height. + (do_switch_frame): Set tty's FrameRows to number of total lines + of frame. + (Fframe_pixel_height, Fframe_pixel_width): If no window system + is used, return total number of lines and columns. + * menu.c (emulate_dialog_with_menu): Use FRAME_TOTAL_LINES instead + of FRAME_LINES. + * term.c (OUTPUT, tty_set_terminal_modes) + (tty_set_terminal_window, tty_set_scroll_region) + (tty_clear_to_end, tty_write_glyphs, tty_write_glyphs_with_face) + (tty_ins_del_lines, tty_menu_display, tty_menu_activate): + Use FRAME_TOTAL_LINES instead of FRAME_LINES. + (Fresume_tty): Use FRAME_TOTAL_LINES instead of FRAME_LINES. + Call change_frame_size with frame's menu bar lines subtracted + from height. + * w32console.c (w32con_clear_to_end, w32con_clear_frame) + (w32con_ins_del_lines): Use FRAME_TOTAL_LINES instead of + FRAME_LINES. -2014-08-02 Paul Eggert <eggert@cs.ucla.edu> +2014-08-09 Reuben Thomas <rrt@sc3d.org> + + * alloc.c (Fmemory_info): Remove a stray brace. + + * process.c: Fix a comment typo. + + * msdos.c, dosfns.c (init_dosfns): Remove support for DJGPP < 2.02. + +2014-08-09 Jan Djärv <jan.h.d@swipnet.se> + + * widgetprv.h (EmacsFramePart): Remove font. + + * widget.c (DEFAULT_FACE_FONT, EmacsFrameSetValues, setup_frame_gcs) + (resources, setup_frame_cursor_bits): Remove unused variables and + functions, esp. wrt. font (Bug#18227). + +2014-08-07 Paul Eggert <eggert@cs.ucla.edu> + + * xterm.c (x_delete_terminal): Plug file descriptor leak (Bug#17691). + +2014-08-07 Reuben Thomas <rrt@sc3d.org> + + Refer to MS-DOS using the same name everywhere. + + * editfns.c: Fix a couple of ``MS-DOG''s missed in the previous + commit. + * xfaces.c: ditto. + +2014-08-05 Martin Rudalics <rudalics@gmx.at> + + * w32term.c (w32_redeem_scroll_bar): + * xterm.c (XTredeem_scroll_bar): Revert part of last change by + not redeeming scroll bars that have been turned off. + +2014-08-05 Dmitry Antipov <dmantipov@yandex.ru> + + * keyboard.c (safe_run_hooks): Follow the convenient style to bind + inhibit-quit to t and pass 2 args to safe_run_hook_funcall. See + <http://lists.gnu.org/archive/html/emacs-devel/2014-08/msg00077.html>. + (safe_run_hook_funcall): Adjust accordingly. + +2014-08-04 Martin Rudalics <rudalics@gmx.at> + + * frame.h (FRAME_HAS_HORIZONTAL_SCROLL_BARS): + Condition correctly according to toolkit used. + * frame.c (make_initial_frame, make_terminal_frame) + (x_set_horizontal_scroll_bars, x_set_scroll_bar_height) + (Vdefault_frame_horizontal_scroll_bars): Correctly condition + assignments according to presence of toolkit scrollbars. + * window.h (WINDOW_HAS_HORIZONTAL_SCROLL_BAR): + Condition correctly according to toolkit used. + * window.c (set_window_scroll_bars): Set horizontal scroll bar + only if toolkit supports it. + * w32term.c (w32_redeem_scroll_bar): Always redeem scroll bar if + present. + * xterm.c (x_scroll_bar_create): Initialize horizontal slot for + non-toolkit builds. + (XTredeem_scroll_bar): Always redeem scroll bar if present. + +2014-08-04 Dmitry Antipov <dmantipov@yandex.ru> + + * keyboard.c (safe_run_hook_funcall): Avoid consing around + Vinhibit_quit and prefer internal_condition_case_n to pass args. + (safe_run_hooks_error, safe_run_hooks_1): Adjust accordingly. + (safe_run_hooks): Remove comment which is not relevant any more. + +2014-08-03 Paul Eggert <eggert@cs.ucla.edu> + + Don't let big frames overrun the stack. + * dispnew.c (mirrored_line_dance, mirror_line_dance, scrolling): + Use SAFE_NALLOCA, not alloca. Fix bug with clang + directory_files_internal + GC (Bug#16986). * dired.c (directory_files_internal): Use a volatile variable @@ -314,6 +2045,42 @@ so that x_delete_terminal has a file descriptor to pass to delete_keyboard_wait_descriptor. + Don't mishandle year-9999 dates (Bug#18176). + * editfns.c (decode_time_components): Store an invalid timespec + on overflow, instead of returning false, so that the caller can + distinguish overflow from other errors. + (lisp_time_argument, lisp_seconds_argument): If the time is out + of range, signal a time overflow instead of an invalid time spec. + * keyboard.c (decode_timer): Treat time overflow like other + timespec errors. + + Avoid undefined behavior with signed left shift. + Caught by 'gcc -fsanitize=undefined'. + * dispextern.h, scroll.c (scrolling_max_lines_saved, scrolling_1): + * dispnew.c (line_hash_code, scrolling): + * scroll.c (calculate_scrolling, calculate_direct_scrolling): + Use 'unsigned', not 'int', for line hashes. + (scrolling_max_lines_saved): Avoid mystery constants for hash sizes. + +2014-08-02 Paul Eggert <eggert@cs.ucla.edu> + + Make compare-strings more compatible with old behavior (Bug#17903). + * fns.c (Fcompare_strings): Silently bring too-large ends into range. + +2014-08-02 Jan Djärv <jan.h.d@swipnet.se> + + * gtkutil.c (create_dialog): Force min spacing 10 between buttons. + Don't add label between left and right buttons (Bug#18129). + +2014-08-01 Paul Eggert <eggert@cs.ucla.edu> + + Make functions static that no longer need to be extern. + * frame.c, frame.h (set_menu_bar_lines): + * keyboard.c (Qleftmost, Qrightmost): + * xfns.c, frame.h, menu.h (x_set_menu_bar_lines, x_set_tool_bar_lines) + (x_set_internal_border_width): + Now static. + 2014-08-01 Eli Zaretskii <eliz@gnu.org> Fix display of R2L lines when the last character fits only partially. @@ -327,30 +2094,600 @@ line. When the last glyph fits only partially, give the row a negative x offset. -2014-07-29 Eli Zaretskii <eliz@gnu.org> - Fix hscroll of R2L lines that begin with a TAB or another wide glyph. * xdisp.c (append_stretch_glyph): In a R2L glyph row, decrease the pixel width of the first glyph that is hscrolled from display. (display_line): In R2L glyph rows, don't give a negative offset to row->x when the first glyph begins before first_visible_x. -2014-07-29 Andreas Schwab <schwab@suse.de> + * xdisp.c (display_line): If called with iterator set up to write + to a marginal area, delay the call to handle_line_prefix until we + switch back to the text area. (Bug#18035) + + * .gdbinit (xwindow): The members total_cols, total_lines, + left_col, and top_line are C integers (and has been so for the + last 1.5 years). + +2014-08-01 Andreas Schwab <schwab@suse.de> * macros.c (Fstart_kbd_macro): Initialize kbd_macro_ptr and kbd_macro_end together with kbd_macro_buffer. (Bug#18140) -2014-07-28 Eli Zaretskii <eliz@gnu.org> +2014-08-01 Dmitry Antipov <dmantipov@yandex.ru> - * xdisp.c (display_line): If called with iterator set up to write - to a marginal area, delay the call to handle_line_prefix until we - switch back to the text area. (Bug#18035) + * atimer.c (toplevel) [HAVE_TIMERFD]: Include errno.h. + (timerfd_callback): Ignore weird events with no data. Add tight + assertions and comments. + (init_atimer) [HAVE_TIMERFD]: Add environment variable to optionally + disable timerfd-based timer. Use TFD_NONBLOCK for timer descriptor. + +2014-08-01 Paul Eggert <eggert@cs.ucla.edu> + + * frame.c (x_set_frame_parameters): Fix typo in previous patch. + I had confused && with ||. + +2014-07-31 Paul Eggert <eggert@cs.ucla.edu> + + Simplify timerfd configuration and fix some minor glitches. + * atimer.c (TIMERFD_CREATE_FLAGS): Remove; we now assume TFD_CLOEXEC. + (alarm_timer, alarm_timer_ok, set_alarm, init_atimer): + Fall back on timer_create if timerfd_create fails at runtime. + (resolution) [HAVE_CLOCK_GETRES]: Remove; we now rely on the + kernel primitives to do resolution. All uses removed. + (timerfd) [!HAVE_TIMERFD]: Define to be -1, for convenience. + (turn_on_atimers): Clear timer_create-based timers too, + for consistency. + + * frame.c (x_set_frame_parameters): Don't use uninitialized locals. + Without this change, the code can access the local variable 'width' + even when it has not been initialized, and likewise for 'height'; + in either case this leads to undefined behavior. + +2014-07-30 Dmitry Antipov <dmantipov@yandex.ru> + + * xrdb.c (x_load_resources) [USE_MOTIF]: Although not strictly + necessary, put horizontal scroll bar resources as well. See + <http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00430.html>. + * xterm.c (x_sync_with_move): Really wait 0.5s, not 0.0005s. + +2014-07-29 Dmitry Antipov <dmantipov@yandex.ru> + + * xrdb.c (x_load_resources) [!USE_MOTIF]: Put horizontal scroll bar + background value to match the resource of its vertical counterpart. + +2014-07-29 Martin Rudalics <rudalics@gmx.at> + + * frame.c (adjust_frame_size): Use FRAME_WINDOW_P instead of + FRAME_X_WINDOW when calling x_set_window_size (Bug#18138). + +2014-07-28 Martin Rudalics <rudalics@gmx.at> + + * frame.c (x_set_frame_parameters): Revert part of 2014-07-24 + change that added the top margin height to the requested height + and revert (undocumented) part of 2014-07-28 change that changed + the logic of whether a size change occurred. + +2014-07-28 Eli Zaretskii <eliz@gnu.org> * .gdbinit (xwindow): The members total_cols, total_lines, left_col, and top_line are C integers (and has been so for the last 1.5 years). -2014-07-20 Jan Djärv <jan.h.d@swipnet.se> + * .gdbinit (xsubchartable): The members 'depth' and 'min_char' are + now C integers. + +2014-07-28 Dmitry Antipov <dmantipov@yandex.ru> + + On GNU/Linux, use timerfd for asynchronous timers. + * atimer.c (toplevel) [HAVE_TIMERFD]: Include sys/timerfd.h. + (toplevel): Rename alarm_timer_ok to special_timer_available. + [HAVE_TIMERFD]: Declare timerfd. + [HAVE_CLOCK_GETRES]: Declare resolution. + (start_atimer) [HAVE_CLOCK_GETRES]: Round up timestamp to + system timer resolution. + (set_alarm) [HAVE_TIMERFD]: Use timerfd_settime. + (timerfd_callback) [HAVE_TIMERFD]: New function. + (atimer_result, debug_timer_callback, Fdebug_timer_check) + [ENABLE_CHECKING]: New function for the sake of automated tests. + (init_atimer) [HAVE_TIMERFD]: Setup timerfd. + [HAVE_CLOCK_GETRES]: Likewise for system timer resolution. + [ENABLE_CHECKING]: Defsubr test function. + * atimer.h (timerfd_callback) [HAVE_TIMERFD]: Add prototype. + * lisp.h (add_timer_wait_descriptor) [HAVE_TIMERFD]: Likewise. + * process.c (add_timer_wait_descriptor) [HAVE_TIMERFD]: New function. + + Fix --without-x build and pacify --enable-gcc-warnings. + Problems reported in Bug#18122 and Bug#18124. + * frame.c (get_frame_param): Define even if !HAVE_WINDOW_SYSTEM. + (frame_windows_min_size): Now static. + * frame.h (FRAME_HAS_HORIZONTAL_SCROLL_BARS) [!HAVE_WINDOW_SYSTEM]: + Define as no-op. + (adjust_frame_size): Always declare prototype. + + Fix Gnus-related issues reported by David Kastrup <dak@gnu.org> in + <http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00370.html>. + * atimer.c (timerfd_callback): Always read expiration data. + Add comment. + (turn_on_atimers) [HAVE_TIMERFD]: Disarm timerfd timer. + * process.c (add_timer_wait_descriptor): Add timer descriptor + to input_wait_mask and non_process_wait_mask as well. + +2014-07-28 Paul Eggert <eggert@cs.ucla.edu> + + * frame.c (x_set_frame_parameters): Don't use uninitialized locals. + +2014-07-27 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (applicationDidFinishLaunching antialiasThresholdDidChange): + Reinstate code removed by the prevoius commit to this file. + +2014-07-27 Martin Rudalics <rudalics@gmx.at> + + * buffer.h (struct buffer): New fields scroll_bar_height and + horizontal_scroll_bar_type. + * buffer.c (bset_scroll_bar_height) + (bset_horizontal_scroll_bar_type): New functions. + (Fbuffer_swap_text): Handle old_pointm field. + (init_buffer_once): Set defaults for scroll_bar_height and + horizontal_scroll_bar_type. + (syms_of_buffer): New variables scroll_bar_height and + horizontal_scroll_bar_type. + * dispextern.h (window_part): Rename ON_SCROLL_BAR to + ON_VERTICAL_SCROLL_BAR. Add ON_HORIZONTAL_SCROLL_BAR. + (set_vertical_scroll_bar): Remove prototype. + (x_change_tool_bar_height): Add prototype. + * dispnew.c (adjust_frame_glyphs_for_frame_redisplay) + (window_to_frame_vpos, update_frame_1, scrolling, init_display): + Use FRAME_TOTAL_COLS and FRAME_TOTAL_LINES instead of FRAME_COLS + and FRAME_LINES. + (adjust_frame_glyphs_for_window_redisplay): Rearrange lines. + (update_window): Start mode_line_row->y after horizontal scroll + bar. + (change_frame_size_1): Call adjust_frame_size. + (init_display): When changing the size of a tty frame do not + pass height of menu bar. + (Qframe_windows_min_size): New symbol. + * frame.h (struct frame): List tool bar fields after menu bar + fields. Add official, total_lines, horizontal_scroll_bars, + config_scroll_bar_height and config_scroll_bar_lines fields. + (FRAME_HAS_HORIZONTAL_SCROLL_BARS) + (FRAME_CONFIG_SCROLL_BAR_HEIGHT, FRAME_CONFIG_SCROLL_BAR_LINES) + (FRAME_SCROLL_BAR_AREA_HEIGHT, FRAME_SCROLL_BAR_COLS) + (FRAME_SCROLL_BAR_LINES, FRAME_TOTAL_LINES, SET_FRAME_LINES) + (FRAME_WINDOWS_HEIGHT): New macros. + (SET_FRAME_HEIGHT, FRAME_TEXT_LINES_TO_PIXEL_HEIGHT) + (FRAME_PIXEL_Y_TO_LINE, FRAME_PIXEL_HEIGHT_TO_TEXT_LINES) + (FRAME_TEXT_TO_PIXEL_HEIGHT): Separately count top margin and + horizontal scroll bar. + (frame_inhibit_resize, adjust_frame_size) + (frame_windows_min_size): Add declarations. + (Qscroll_bar_height, Qhorizontal_scroll_bars) + (x_set_scroll_bar_default_height, x_set_left_fringe) + (x_set_right_fringe, x_set_vertical_scroll_bars) + (x_set_horizontal_scroll_bars, x_set_scroll_bar_width) + (x_set_scroll_bar_height): Add external declarations. + * frame.c: (frame_inhibit_resize, frame_windows_min_size) + (adjust_frame_size): New functions. + (make_frame): Initial horizontal_scroll_bars field. + Use SET_FRAME_LINES. Don't allow horizontal scroll bar in + minibuffer window. + (make_initial_frame, make_terminal_frame): No horizontal scroll + bar in initial and terminal frames. Use adjust_frame_size. + (Fframe_total_cols): Fix doc-string. + (Fframe_total_lines, Fscroll_bar_height): New Lisp functions. + (Fset_frame_height, Fset_frame_width, Fset_frame_size): + Rewrite using adjust_frame_size. + (Qscroll_bar_height, Qhorizontal_scroll_bars) + (Qframe_windows_min_size): New symbols. + (x_set_frame_parameters): Remove call of check_frame_size. + (x_report_frame_params): Return scroll_bar_height value. + (x_set_left_fringe, x_set_right_fringe): New functions. + (adjust_frame_height, x_set_internal_border_width) + (x_set_fringe_width): Remove. + (x_set_internal_border_width, x_set_vertical_scroll_bars) + (x_set_scroll_bar_width, x_set_right_divider_width) + (x_set_bottom_divider_width): Rewrite using adjust_frame_size. + (x_set_horizontal_scroll_bars, x_set_scroll_bar_height): + New functions. + (x_figure_window_size): Rewrite to make frame display the + expected number of lines. + (Vdefault_frame_scroll_bars): Rewrite doc-string. + (Vdefault_frame_horizontal_scroll_bars) + (Vframe_initial_frame_tool_bar_height) + (frame_inhibit_implied_resize): New variables. + * fringe.c (compute_fringe_widths): Remove. + * gtkutil.h (YG_SB_MIN, YG_SB_MAX, YG_SB_RANGE): Define. + (xg_create_horizontal_scroll_bar) + (xg_update_horizontal_scrollbar_pos) + (xg_set_toolkit_horizontal_scroll_bar_thumb) + (xg_get_default_scrollbar_height) + (xg_clear_under_internal_border): Extern. + * gtkutil.c (xg_frame_resized): Don't call + do_pending_window_change. + (xg_frame_set_char_size): Use adjust_frame_size. + (style_changed_cb): Call update_theme_scrollbar_height and + x_set_scroll_bar_default_height. + (x_wm_set_size_hint): Don't call check_frame_size. + (update_theme_scrollbar_height) + (xg_get_default_scrollbar_height) + (xg_create_horizontal_scroll_bar) + (xg_update_horizontal_scrollbar_pos) + (xg_set_toolkit_horizontal_scroll_bar_thumb): New functions. + (xg_create_scroll_bar): Set horizontal slot of bar. + (xg_initialize): Call update_theme_scrollbar_height. + (xg_clear_under_internal_border): No more static. + * insdel.c (adjust_suspend_auto_hscroll): New function. + (adjust_markers_for_delete, adjust_markers_for_insert) + (adjust_markers_for_replace): Call adjust_suspend_auto_hscroll. + * keyboard.c (readable_events, discard_mouse_events) + (make_lispy_event): Handle horizontal scroll bar click events. + (Fsuspend_emacs): When changing the size of a tty frame do not + pass height of menu bar. + (Qbefore_handle, Qhorizontal_handle, Qafter_handle, Qleft) + (Qright, Qleftmost, Qrightmost): New symbols. + * menu.c (Fx_popup_dialog): Use FRAME_TOTAL_LINES instead of + FRAME_LINES. + * minibuf.c (read_minibuf): Initialize suspend_auto_hscroll. + * nsfns.m (x_set_internal_border_width): New function. + * nsterm.m (ns_draw_fringe_bitmap, ns_set_vertical_scroll_bar): + Remove extended fringe code. + (x_set_window_size, x_new_font): Don't call + compute_fringe_widths. + * term.c (Fresume_tty): When changing the size of a tty frame do + not pass height of menu bar. + (clear_tty_hooks, set_tty_hooks): + Clear horizontal_scroll_bar_hook. + (init_tty): Frame has no horizontal scroll bars. + * termhooks.h (enum scroll_bar_part): Add scroll_bar_move_ratio, + scroll_bar_before_handle, scroll_bar_horizontal_handle, + scroll_bar_after_handle, scroll_bar_left_arrow, + scroll_bar_right_arrow, scroll_bar_to_leftmost and + scroll_bar_to_rightmost entries. + (enum event_kind): Add HORIZONTAL_SCROLL_BAR_CLICK_EVENT + (struct terminal): Add set_horizontal_scroll_bar_hook. + * w32console.c (initialize_w32_display): + Clear horizontal_scroll_bar_hook. + * w32fns.c (x_set_mouse_color): Use FRAME_W32_DISPLAY instead of + FRAME_X_DISPLAY. + (x_clear_under_internal_border, x_set_internal_border_width): + New functions. + (x_set_menu_bar_lines): Rewrite using frame_inhibit_resize. + Set windows_or_buffers_changed when adding the menu bar. + (x_set_tool_bar_lines): Rewrite using adjust_frame_size. + (x_change_tool_bar_height, x_set_scroll_bar_default_height) + (w32_createhscrollbar): New functions. + (w32_createscrollbar): Rename to w32_createvscrollbar. + (w32_createwindow): Init WND_HSCROLLBAR_INDEX. + (w32_name_of_message): Replace WM_EMACS_CREATESCROLLBAR by + WM_EMACS_CREATEVSCROLLBAR and WM_EMACS_CREATEHSCROLLBAR. + Add WM_EMACS_SHOWCURSOR. + (w32_wnd_proc): Handle WM_HSCROLL case. In WM_WINDOWPOSCHANGING + case do not artificially impose WM size hints. + Handle WM_EMACS_SHOWCURSOR case. Replace WM_EMACS_CREATESCROLLBAR case + by WM_EMACS_CREATEVSCROLLBAR and WM_EMACS_CREATEHSCROLLBAR + cases. + (my_create_tip_window): Replace WND_SCROLLBAR_INDEX by + WND_VSCROLLBAR_INDEX and WND_HSCROLLBAR_INDEX. + (unwind_create_frame_1): Remove. + (Fx_create_frame): Make both scrollbars the system standard + width and height. Use official field of frame structure to + inhibit running window-configuration-change-hook. + (x_create_tip_frame): Call SET_FRAME_LINES and change_frame_size + pixelwise. Handle frame's official field. + (w32_frame_parm_handlers): Remove x_set_fringe_width + entries. Add x_set_scroll_bar_height, + x_set_horizontal_scroll_bars, x_set_left_fringe and + x_set_right_fringe. + * w32inevt.c (resize_event, maybe_generate_resize_event): Do not + pass height of menu bar to change_frame_size. + * w32menu.c (set_frame_menubar): Rewrite using + frame_inhibit_resize. + * w32term.h (struct w32_display_info): + Add horizontal_scroll_bar_cursor and cursor_display_counter. + (struct scroll_bar): Add horizontal. + (HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT) + (HORIZONTAL_SCROLL_BAR_LEFT_RANGE) + (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH) + (HORIZONTAL_SCROLL_BAR_LEFT_BORDER) + (HORIZONTAL_SCROLL_BAR_RIGHT_BORDER) + (HORIZONTAL_SCROLL_BAR_TOP_BORDER) + (HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER) + (HORIZONTAL_SCROLL_BAR_MIN_HANDLE): New macros. + (WM_EMACS_CREATEVSCROLLBAR, WM_EMACS_CREATEHSCROLLBAR): + Define instead of WM_EMACS_CREATESCROLLBAR. + (WND_VSCROLLBAR_INDEX, WND_HSCROLLBAR_INDEX): Define instead of + WND_SCROLLBAR_INDEX. + * w32term.c (horizontal_scroll_bar_min_handle) + (horizontal_scroll_bar_left_border) + (horizontal_scroll_bar_right_border): New integers. + (x_set_frame_alpha): Replace x_highlight_frame by + w32_focus_frame. + (x_window_to_scroll_bar): New argument "type". Update callers + accordingly. + (w32_set_horizontal_scroll_bar_thumb) + (x_horizontal_scroll_bar_report_motion) + (w32_set_horizontal_scroll_bar) + (w32_horizontal_scroll_bar_handle_click) + (x_horizontal_scroll_bar_report_motion): New functions. + (w32_mouse_position): Discriminate horizontal and vertical + scrollbar cases. + (my_create_scrollbar): Replace with two new functions + my_create_vscrollbar and my_create_hscrollbar. + (x_scroll_bar_create): New argument "horizontal". + Update callers accordingly. + (x_scroll_bar_remove, w32_condemn_scroll_bars) + (w32_redeem_scroll_bar, x_scroll_bar_clear): Handle horizontal + scroll bar case. + (w32_read_socket): Handle WM_HSCROLL cae. + (x_new_font): Don't recompute fringe widths. + Use frame_inhibit_resize. Calculate new menu bar height iff we + build without toolkit. Always clear under internal border. + (x_set_window_size): Don't check frame size or recompute + fringes. Reset fullscreen status before applying sizes. + Always resize as requested by pixelwise argument. Don't call + do_pending_window_change. + (x_wm_set_size_hint): Add call for FRAME_SCROLL_BAR_AREA_HEIGHT. + (w32_initialize_display_info): Initialize dpyinfo's + horizontal_scroll_bar_cursor entry. + (w32_create_terminal): Add set_horizontal_scroll_bar_hook. + (w32_initialize): Init horizontal_scroll_bar_min_handle and + horizontal_scroll_bar_left_border. + (w32fullscreen_hook): Intermittently resize window to normal + when switching from fullscreen to maximized state. + (run_window_configuration_change_hook): Don't run it if frame is + not official yet. + (unwind_change_frame): Remove. + (Fset_window_configuration): Rewrite using frame's official field. + * widget.c (set_frame_size): Don't call compute_fringe_widths. + (EmacsFrameSetCharSize): Obey frame_inhibit_resize. + * window.h (struct window): New fields old_pointm, + horizontal_scroll_bar, horizontal_scroll_bar_type, hscroll_whole, + scroll_bar_height and suspend_auto_hscroll. + (wset_horizontal_scroll_bar, wset_horizontal_scroll_bar_type): + New functions. + (sanitize_window_sizes): Extern. + (MINI_NON_ONLY_WINDOW_P, MINI_ONLY_WINDOW_P, WINDOW_PSEUDO_P) + (WINDOW_TOPMOST_P, WINDOW_HAS_HORIZONTAL_SCROLL_BAR) + (WINDOW_CONFIG_SCROLL_BAR_HEIGHT) + (WINDOW_CONFIG_SCROLL_BAR_LINES) + (WINDOW_SCROLL_BAR_LINES, WINDOW_SCROLL_BAR_AREA_HEIGHT): + New macros. + (WINDOW_LEFT_FRINGE_COLS, WINDOW_RIGHT_FRINGE_COLS) + (WINDOW_FRINGE_COLS, WINDOW_FRINGE_EXTENDED_P): Remove macros. + (WINDOW_VERTICAL_SCROLL_BAR_TYPE) + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT) + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT) + (WINDOW_HAS_VERTICAL_SCROLL_BAR): Minor rewrite. + (WINDOW_BOX_HEIGHT_NO_MODE_LINE, WINDOW_BOX_TEXT_HEIGHT) + (WINDOW_SCROLL_BAR_AREA_Y): Count in scroll bar height. + * window.c (wset_old_pointm, Fwindow_scroll_bar_height) + (Fwindow_old_point, sanitize_window_sizes): New functions. + (Qwindow_sanitize_window_sizes): New symbol. + (window_body_height): Count in horizontal scroll bar. + (set_window_hscroll, Fscroll_left, Fscroll_right): + Set suspend_auto_hscroll slot. + (Fwindow_inside_edges): Count fringes pixelwise. + (coordinates_in_window, Fcoordinates_in_window_p): + Consider horizontal scroll bar. + (check_frame_size, adjust_window_margins): Remove functions and + corresponding calls. + (set_window_buffer): Initialize old_pointm and horizontal scroll + bars. + (temp_output_buffer_show): Reset hscroll related fields. + Initialize old_pointm. + (make_parent_window): Initialize old_pointm. + (make_window): Initialize old_pointm, horizontal scroll bar type, + and scroll bar height. + (resize_frame_windows): Don't count top margin in new sizes. + Don't use safe sizes when shrinking a frame; let the window + manager do the clipping. + (Fsplit_window_internal): Inherit horizontal scroll bar type and + height. + (Fdelete_window_internal): Unchain old_pointm marker. + (window_scroll_pixel_based, Fscroll_other_window): + Adjust old_pointm. + (Fwindow_text_width, Fwindow_text_height): New argument + "pixelwise". + (struct saved_window): New fields, old_pointm, hscroll_whole, + suspend_auto_hscroll, scroll_bar_height and + horizontal_scroll_bar_type. + (Fset_window_configuration, save_window_save): Set new fields of + saved_window. + (apply_window_adjustment): Don't call adjust_window_margins. + (set_window_margins): Don't change margins if new sizes don't + fit into window. + (set_window_scroll_bars): New argument "horizontal_type". + Handle horizontal scroll bars. Don't change scroll bars if they + don't fit into window. + (Fset_window_scroll_bars): New argument "horizontal_type". + (Fwindow_scroll_bars): Return values for horizontal scroll bars. + (compare_window_configurations): Compare horizontal scroll bar + settings. + * xdisp.c (window_text_bottom_y, window_box_height): Count in + horizontal scroll bar height. + (pixel_to_glyph_coords, init_xdisp): Use FRAME_TOTAL_LINES + instead of FRAME_LINES. + (remember_mouse_glyph): Case ON_SCROLL_BAR changed to + ON_VERTICAL_SCROLL_BAR. + (with_echo_area_buffer): Initialize old_pointm. + (with_echo_area_buffer_unwind_data): Store old_pointm values in + vector. + (unwind_with_echo_area_buffer): Handle old_pointm. + (update_tool_bar): Set do_update when the tool bar window has at + least one line (since this is what the user sets). + (MAX_FRAME_TOOL_BAR_HEIGHT): Remove macro. + (redisplay_tool_bar): Return early when toolbar has zero lines. + Call x_change_tool_bar_height. Don't use max_tool_bar_height. + (hscroll_window_tree): Handle suspension of auto_hscroll and + old_pointm. + (set_horizontal_scroll_bar): New function. + (redisplay_window): Set ignore_mouse_drag_p when tool bar has + more than one line. Handle horizontal scroll bars. + (note_mouse_highlight): Handle horizontal scrol bars. + (expose_frame): Set dimensions of XRectangle from frame's text + sizes. + (Vvoid_text_area_pointer): Update doc-string. + * xfns.c (x_set_menu_bar_lines): Use adjust_frame_size. + (x_change_tool_bar_height, x_set_scroll_bar_default_height) + (x_set_internal_border_width): New functions. + (x_set_tool_bar_lines): Call x_change_tool_bar_height. + (unwind_create_frame_1): Remove. + (Fx_create_frame): Handle horizontal scroll bars. Use official + field of frame structure to inhibit running + window-configuration-change-hook. + (x_create_tip_frame): Call SET_FRAME_LINES and change_frame_size + pixelwise. Handle frame's official field. + (x_frame_parm_handlers): Add x_set_scroll_bar_height, + x_set_horizontal_scroll_bars, x_set_left_fringe, + x_set_right_fringe. + * xmenu.c (update_frame_menubar, free_frame_menubar): + Use adjust_frame_size. + * xterm.h (struct x_display_info): + Add horizontal_scroll_bar_cursor and Xatom_Horizontal_Scrollbar + slots. + (struct scroll_bar): Add horizontal slot. + (HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT) + (HORIZONTAL_SCROLL_BAR_LEFT_RANGE) + (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH): New macros. + (HORIZONTAL_SCROLL_BAR_LEFT_BORDER) + (HORIZONTAL_SCROLL_BAR_RIGHT_BORDER) + (HORIZONTAL_SCROLL_BAR_TOP_BORDER) + (HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER) + (HORIZONTAL_SCROLL_BAR_MIN_HANDLE): Define. + (x_clear_under_internal_border): Remove. + * xterm.c (XTmouse_position): Handle horizontal scroll bars. + (x_window_to_scroll_bar): New argument TYPE. Update callers. + (x_send_scroll_bar_event, x_scroll_bar_create): New arguments + HORIZONTAL. Update callers. + (horizontal_action_hook_id): New action hook id. + (x_horizontal_scroll_bar_to_input_event) + (x_create_horizontal_toolkit_scroll_bar) + (xt_horizontal_action_hook) + (x_set_toolkit_horizontal_scroll_bar_thumb) + (XTset_horizontal_scroll_bar, x_net_wm_state) + (x_horizontal_scroll_bar_report_motion): New functions. + (xg_scroll_callback, x_scroll_bar_handle_click): + Handle horizontal scroll bars. + (SCROLL_BAR_HORIZONTAL_NAME): Define. + (XTset_vertical_scroll_bar): Attempt to clear areas not covered + by scroll bar. + (XTcondemn_scroll_bars, XTredeem_scroll_bar): Rewrite. + Handle horizontal scroll bars. + (handle_one_xevent): Handle horizontal scroll bar events. + Call x_net_wm_state. + (x_set_window_size_1, x_wm_set_size_hint): Don't call + check_frame_size. + (x_set_window_size): Don't call check_frame_size and + do_pending_window_change. + (x_term_init): Init horizontal_scroll_bar_cursor display info. + (x_create_terminal): Add set_horizontal_scroll_bar_hook. + (x_scroll_bar_set_handle): Add some checks when calling + x_clear_area. + +2014-07-26 Paul Eggert <eggert@cs.ucla.edu> + + Revert previous change. + There is certainly nothing wrong with writing code like 'lo <= i + && i <= hi', even if LO happens to a constant. There isn't even + anything wrong in general with writing 'a <= b' if A happens to + be a constant. At any rate stylistic changes shouldn't + be done like this without discussion. + +2014-07-26 Andreas Schwab <schwab@linux-m68k.org> + + * alloc.c (xnmalloc, xnrealloc, xpalloc, make_save_value) + (Fgarbage_collect): Reorder conditions that are written backwards. + * data.c (cons_to_unsigned): Likewise. + * dispnew.c (update_frame_1, sit_for): Likewise. + * fileio.c (file_offset): Likewise. + * filelock.c (read_lock_data, lock_file): Likewise. + * fns.c (larger_vector, make_hash_table, Fmake_hash_table): + Likewise. + * font.c (font_intern_prop, font_style_symbolic): Likewise. + * lisp.h (FIXNUM_OVERFLOW_P): Likewise. + * lread.c (read1): Likewise. + * minibuf.c (read_minibuf_noninteractive): Likewise. + * nsterm.m (x_set_frame_alpha): Likewise. + * process.c (wait_reading_process_output): Likewise. + * region-cache.c (delete_cache_boundaries): Likewise. + * xterm.c (x_set_frame_alpha): Likewise. + +2014-07-25 Paul Eggert <eggert@cs.ucla.edu> + + * dispextern.h, xdisp.c (hourglass_shown_p, hourglass_atimer): + Now static. + +2014-07-26 Dmitry Antipov <dmantipov@yandex.ru> + + * atimer.c (set_alarm) [HAVE_ITIMERSPEC]: Use TIMER_ABSTIME + because atimer expiration is absolute rather than relative. + +2014-07-25 Eli Zaretskii <eliz@gnu.org> + + * w32term.h (current_popup_menu, menubar_in_use): + Move declarations from w32term.c. + +2014-07-25 Martin Rudalics <rudalics@gmx.at> + + * w32fns.c (menubar_in_use): No more static. + * w32term.c (current_popup_menu, menubar_in_use): Declare. + +2014-07-25 Dmitry Antipov <dmantipov@yandex.ru> + + Move hourglass machinery to RIF. + * dispextern.h (struct redisplay_interface): New members + show_hourglass and hide_hourglass. Indent comments. + (show_hourglass, hide_hourglass): Remove prototypes. + * nsterm.m (show_hourgass, hide_hourglass): Refactor to ... + (ns_show_hourglass, ns_hide_hourglass): ... new no-ops. + (ns_redisplay_interface): Add them. + * w32fns.c (show_hourglass, hide_hourglass): Refactor to ... + * w32term.c (w32_show_hourglass, w32_hide_hourglass): ... these. + (w32_arrow_cursor): New function to hack around non-GUI frames. + (w32_redisplay_interface): Add new functions. + * w32term.h (w32_arror_cursor): Add prototype. + * xdisp.c (show_hourglass): New function, refactored out from + platform-dependent code. + (cancel_hourglass): Now call to RIF function. + * xfns.c (show_hourglass, hide_hourglass): Refactor to ... + * xterm.c (x_show_hourglass, x_hide_hourglass): ... these. + (x_redisplay_interface): Add new functions. + +2014-07-24 Dmitry Antipov <dmantipov@yandex.ru> + + Fix error reported by Angelo Graziosi <angelo.graziosi@alice.it> in + <http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00274.html> + and complete previous change. + * frame.c (adjust_frame_height): New function. + (Fset_frame_height, Fset_frame_size): Use it. + (x_set_frame_parameters): Take frame top margin into account. + +2014-07-23 Dmitry Antipov <dmantipov@yandex.ru> + + * frame.c (Fset_frame_height): Take frame top margin into account. + Incorrect behavior was reported by Martin Rudalics <rudalics@gmx.at> in + <http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00258.html> + +2014-07-22 Dmitry Antipov <dmantipov@yandex.ru> + + * xterm.h (struct x_output) [USE_X_TOOLKIT || USE_GTK]: Define + menubar_height as such. Tweak comment. + [USE_LUCID && USE_TOOLKIT_SCROLL_BARS]: Likewise for + scroll_bar_top_shadow_pixel and scroll_bar_bottom_shadow_pixel. + All related users changed. + (FRAME_MENUBAR_HEIGHT) [!USE_X_TOOLKIT && !USE_GTK]: No-op. + * xterm.c (handle_one_xevent): + * gtkutil.c (xg_event_is_for_menubar): + * xfns.c (x_window) [USE_X_TOOLKIT]: + * xmenu.c (set_frame_menubar, free_frame_menubar): + Prefer to use FRAME_MENUBAR_HEIGHT. + +2014-07-21 Dmitry Antipov <dmantipov@yandex.ru> + + * frame.c (Fframe_parameters): Always report frame height without + menu and tool bar lines. + +2014-07-21 Jan Djärv <jan.h.d@swipnet.se> * nsterm.m (applicationDidFinishLaunching:): Call antialiasThresholdDidChange, register for antialias changes (Bug#17534). @@ -362,14 +2699,14 @@ * macfont.h (macfont_update_antialias_threshold): Declare. -2014-07-17 Eli Zaretskii <eliz@gnu.org> +2014-07-21 Eli Zaretskii <eliz@gnu.org> - * w32select.c (setup_windows_coding_system): Apply - CODING_ANNOTATION_MASK to the common_flags member of struct + * w32select.c (setup_windows_coding_system): + Apply CODING_ANNOTATION_MASK to the common_flags member of struct coding_system. Reported by martin rudalics <rudalics@gmx.at>. - * w16select.c (Fw16_get_clipboard_data): Apply - CODING_ANNOTATION_MASK to the common_flags member of struct + * w16select.c (Fw16_get_clipboard_data): + Apply CODING_ANNOTATION_MASK to the common_flags member of struct coding_system. * xdisp.c (init_iterator): Initialize it->stop_charpos to the @@ -377,20 +2714,183 @@ (handle_invisible_prop): Record in it->stop_charpos the position where the invisible text ends. (Bug#18035) (hscroll_window_tree): Don't try hscrolling windows whose cursor - row has zero buffer position as their start position. Reported by - martin rudalics <rudalics@gmx.at>. - -2014-07-16 Eli Zaretskii <eliz@gnu.org> + row has zero buffer position as their start position. + Reported by martin rudalics <rudalics@gmx.at>. * xdisp.c (move_it_vertically_backward, move_it_by_lines): Prevent infinite looping in redisplay when display lines don't have enough space to display even a single character. (Bug#18036) -2014-07-13 Eli Zaretskii <eliz@gnu.org> +2014-07-20 Dmitry Antipov <dmantipov@yandex.ru> + + * frame.h (struct frame) [USE_X_TOOLKIT]: New member shell_position. + * xfns.c (x_window): Use it to allow xfree later. + (x_encode_text): Drop 3rd arg; unused. Tweak comment and adjust users + where appropriate. Use bool for booleans and remove redundant checks. + (Fx_backspace_delete_keys_p): Use XkbFreeKeyboard; explain why. + * xterm.c (x_free_frame_resources): Free shell_position. + +2014-07-19 K. Handa <handa@gnu.org> + + * xfaces.c (realize_x_face): Call font_load_for_lface with no + mandatory font spec (Bug#17973). + +2014-07-19 Stefan Monnier <monnier@iro.umontreal.ca> + + * font.c (font_score): Return the worst score if the size of + ENTITY is wrong by more than a factor 2 (Bug#17973). + +2014-07-18 Dmitry Antipov <dmantipov@yandex.ru> + + * frame.c (frame_unspecified_color): New function + refactored out from ... + (Fframe_parameters, Fframe_parameter): ... adjusted users. + (x_fullscreen_adjust, set_frame_param): Move Windows-specific + function to ... + * w32term.c (x_fullscreen_adjust, set_frame_param): ... static here. + * frame.h (x_fullscreen_adjust) [HAVE_NTGUI]: + * lisp.h (set_frame_param): Remove prototype. + * xterm.c (x_display_pixel_width, x_display_pixel_height): Now ... + * xterm.h (x_display_pixel_width, x_display_pixel_height): ... + inlined from here. + + Prefer 'x_display_info *' to 'Display *' in X selection code. + This helps to avoid unneeded calls to x_display_info_for_display. + * xterm.h (struct selection_input_event): Record 'x_display_info *' + instead of 'Display *'. + (SELECTION_EVENT_DPYINFO): New macro. + (SELECTION_EVENT_DISPLAY): Now inline function to prohibit using + it as an lvalue. Mention this in comment. + * xterm.c (handle_one_xevent): Use SELECTION_EVENT_DPYINFO. + * xselect.c (x_get_window_property_as_lisp_data, x_atom_to_symbol) + (selection_data_to_lisp_data, receive_incremental_selection): + Convert to use 'x_display_info *'. Adjust users where appropriate. + (lisp_data_to_selection_data): Likewise. Also pass 'struct + selection data *' as last arg to not return values in args. + (unexpect_property_change): Use common removal technique. + +2014-07-17 Dmitry Antipov <dmantipov@yandex.ru> + + * print.c (print_preprocess): Adjust to match changed + sub char-table structure and avoid crash (Bug#18038). + + * data.c (wrong_choice): Not static any more. + * lisp.h (wrong_choice): Add prototype. + * frame.h (struct frame) [USE_X_TOOLKIT || HAVE_NTGUI]: + Declare namebuf as such. Tweak comment. + [USE_GTK]: Likewise for tool_bar_position. + (fset_tool_bar_position) [USE_GTK]: Ditto. + (FRAME_TOOL_BAR_POSITION): New macro. + * frame.c (x_report_frame_params): + * gtkutil.c (update_frame_tool_bar): + * xfns.c (Fx_create_frame): Use it. + (x_set_tool_bar_position): Add meaningful diagnostic messages. + +2014-07-16 Eli Zaretskii <eliz@gnu.org> * xdisp.c (decode_mode_spec): Call file-remote-p on the current buffer's default-directory only if it is a string. (Bug#17986) +2014-07-16 Dmitry Antipov <dmantipov@yandex.ru> + + More precise control over values of some buffer-local variables. + * keyboard.c (Qvertical_scroll_bar): + * frame.c (Qleft, Qright): Move to ... + * buffer.c (Qleft, Qright, Qvertical_scroll_bar): ... here. + * buffer.c (Qchoice, Qrange, Qoverwrite_mode, Qfraction): New symbols. + (syms_of_buffer): DEFSYM all of the above, attach special properties. + Use special symbols to DEFVAR_PER_BUFFER overwrite-mode, + vertical-scroll-bar, scroll-up-aggressively + and scroll-down-aggressively. + * buffer.h (Qchoice, Qrange, Qleft, Qright, Qvertical_scroll_bar): + Add declarations. + * nsfns.m, frame.h (Qleft, Qright): + * nsterm.m (Qleft): Remove declarations. + * gtkutil.c (toplevel): Include buffer.h. + * data.c (wrong_choice, wrong_range): New functions. + (store_symval_forwarding): Handle special properties of buffer-local + variables and use functions from the above to signal error, if any. + + * frame.h (enum fullscreen_type) [HAVE_WINDOW_SYSTEM]: Use more natural + values. Add comment. + (struct frame): Re-arrange layout to avoid extra padding and use bit + fields for output_method, want_fullscreen and vertical_scroll_bar_type. + (FRAME_VERTICAL_SCROLL_BAR_TYPE, FRAME_HAS_VERTICAL_SCROLL_BARS) + (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT) + (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT) [!HAVE_WINDOW_SYSTEM]: + Define as no-ops because there are no scroll bars anyway. + * frame.c (make_frame, make_terminal_frame, make_initial_frame): + Adjust users. + + * font.c (fset_font_data) [HAVE_XFT || HAVE_FREETYPE]: + Add convenient setter. + (font_put_frame_data, font_get_frame_data): Use it. + +2014-07-15 Daiki Ueno <ueno@gnu.org> + + * nsgui.h (XCHAR2B_BYTE1): Add missing parentheses around + pointer argument, before dereferencing. + (XCHAR2B_BYTE2): Likewise. + +2014-07-15 Dmitry Antipov <dmantipov@yandex.ru> + + * xmenu.c (toplevel): Use LWLIB_ID for next_menubar_widget_id. + (pop_down_menu) [USE_X_TOOLKIT]: Accept integer arg. + (create_and_show_popup_menu, create_and_show_dialog) [USE_X_TOOLKIT]: + Use record_unwind_protect_int and avoid consing. + (syms_of_xmenu) [USE_X_TOOLKIT]: Declare WIDGET_ID_TICK_START. + + * regex.c (re_search_2): Use ssize_t to avoid integer overflow. + +2014-07-14 Paul Eggert <eggert@cs.ucla.edu> + + Use binary-io module, O_BINARY, and "b" flag (Bug#18006). + * callproc.c (create_temp_file): Use mkostemp's O_BINARY flag. + * emacs.c [MSDOS]: + * emacs.c (main) [DOS_NT]: Don't mess with _fmode. + (main) [MSDOS]: Use SET_BINARY instead of setmode. + * minibuf.c: Include binary-io.h instead of fcntl.h. + (read_minibuf_noninteractive): + Use set_binary_mode instead of handcrafted code. + Don't call emacs_set_tty if emacs_get_tty failed. + * sysdep.c, systty.h (emacs_get_tty): Return int, not void. + * sysdep.c (emacs_open, emacs_pipe): Use O_BINARY. + * w32.c (pipe2): Adjust eassert to include O_BINARY. + + * macros.c (Fstart_kbd_macro): Avoid need for overflow check. + This works around a GCC compiler bug when Emacs is configured with + --enable-gcc-warnings. + +2014-07-14 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (CHECK_VECTOR_OR_STRING): Return number of elements + or characters in string, respectively. Add comment. + * fringe.c (Fdefine_fringe_bitmap): + * fns.c (Fsubstring, substring_both): Use it. + * keymap.c (Fdefine_key, Flookup_key): + * macros.c (Fstart_kbd_macro): Likewise. Avoid call to Flength. + + * term.c (tty_menu_add_pane, tty_menu_add_selection): + Use menu_item_width. + (tty_menu_show): Simplify because tty_menu_create never return NULL. + +2014-07-13 Paul Eggert <eggert@cs.ucla.edu> + + Improve behavior of 'bzr up; cd src; make -k'. + * Makefile.in (top_srcdir): New var. + (ntsource, lispsource, ALL_CFLAGS, gl-stamp, emacs.res): + Use '$(top_srcdir)' instead of '$(srcdir)/..'; + its expansion is a bit shorter. + (../config.status): Actually build config.status instead of + just complaining. + (ACLOCAL_INPUTS, AUTOCONF_INPUTS): + New macros, copied and relocated from ../Makefile.in. + ($(top_srcdir)/aclocal.m4, $(top_srcdir)/configure, config.in) + (../config.status, Makefile): New dependencies and rules, + copied with relocation from ../Makefile.in. This should be more + likely to rebuild the build machinery properly if you do a 'make' + in the src directory. + 2014-07-12 Eli Zaretskii <eliz@gnu.org> * xdisp.c (display_line): Don't call FETCH_BYTE with argument less @@ -403,39 +2903,134 @@ * xfns.c (Fx_file_dialog) [USE_MOTIF, USE_GTK]: Update the doc string to match the one in w32fns.c. -2014-07-08 Eli Zaretskii <eliz@gnu.org> + * minibuf.c (read_minibuf_noninteractive) [WINDOWSNT]: Switch + stdin to binary mode only if it is connected to a terminal. + +2014-07-11 Paul Eggert <eggert@cs.ucla.edu> + + Coalesce extern decls. + * minibuf.c (emacs_get_tty, emacs_set_tty, suppress_echo_on_tty): + * sysdep.c (emacs_get_tty, emacs_set_tty): + Move duplicate extern decls from here ... + * systty.h: ... to here, so that there's just one copy. + +2014-07-11 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (changeFont:): Add ifdef NS_IMPL_COCOA. + + * nsfns.m (Fns_popup_font_panel): Ditto. + +2014-07-11 Eli Zaretskii <eliz@gnu.org> + + * minibuf.c (read_minibuf_noninteractive): Finish reading on '\r', + not only on '\n'. + [WINDOWSNT]: Switch stdin to binary mode when not echoing input. + + * sysdep.c (emacs_get_tty, emacs_set_tty, suppress_echo_on_tty) + [DOS_NT]: Implement for WINDOWSNT. + + * systty.h (struct emacs_tty) [DOS_NT]: The struct member is now + unsigned. + +2014-07-11 Michael Albinus <michael.albinus@gmx.de> + + * sysdep.c (suppress_echo_on_tty): New function. + * minibuf.c (read_minibuf_noninteractive): Use it. + +2014-07-11 Dmitry Antipov <dmantipov@yandex.ru> + + * alloc.c (Fmemory_info) [HAVE_LINUX_SYSINFO]: Return nil if + sysinfo failed. Adjust docstring. + +2014-07-11 Eli Zaretskii <eliz@gnu.org> + + Implement memory-info for MS-DOS. + * dosfns.c (dos_memory_info): New function. + * dosfns.h (dos_memory_info): Add prototype. + * alloc.c (Fmemory_info) [MSDOS]: Call dos_memory_info. + * vm-limit.c (get_lim_data) [MSDOS]: Call dos_memory_info, instead + of doing some of its job. + + * minibuf.c (read_minibuf_noninteractive) [WINDOWSNT]: Don't + reference termios structure members. + +2014-07-11 Michael Albinus <michael.albinus@gmx.de> + + * sysdep.c (emacs_get_tty, emacs_set_tty): Make them externally visible. + + * minibuf.c (top): Include systty.h. Declare external + emacs_get_tty and emacs_set_tty. + (Vread_hide_char): New lisp variable. + (read_minibuf_noninteractive): Hide characters with + Vread_hide_char if it is a character. (Bug#17839) + +2014-07-10 Eli Zaretskii <eliz@gnu.org> + + Implement memory-info for MS-Windows. + * w32.c (w32_memory_info): New function. + * w32.h (w32_memory_info): Prototype it. + * alloc.c (Fmemory_info) [WINDOWSNT]: Call it. + +2014-07-10 Dmitry Antipov <dmantipov@yandex.ru> + + * coding.h (struct coding_system): Remove 'error_positions' (unused) + and 'errors' (set but unused) fields. Use bitfields for 'eol_seen', + 'mode', 'common_flags' and 'result' fields, adjust layout to avoid + extra padding and shrink struct coding_system by 56 bytes (x86_64). + * coding.c (decode_coding_utf_8, decode_coding_utf_16) + (decode_coding_emacs_mule, decode_coding_iso_2022, decode_coding_sjis) + (decode_coding_big5, decode_coding_charset, decode_coding) + (encode_coding): Adjust users. + + * alloc.c (Fmemory_info): New function. + +2014-07-09 Paul Eggert <eggert@cs.ucla.edu> + + * syntax.c (back_comment): Use more-natural location for label. + + * font.c, font.h (font_unparse_fcname): Now static. + Define only if HAVE_XFT || HAVE_FREETYPE || HAVE_NS. + +2014-07-09 Dmitry Antipov <dmantipov@yandex.ru> + + Next minor cleanup of font subsystem. + * font.h (enum font_property_index): Remove FONT_ENTITY_INDEX (no + users) and FONT_FORMAT_INDEX (set by a few font drivers but never + really used). + (FONT_ENTITY_NOT_LOADABLE, FONT_ENTITY_SET_NOT_LOADABLE): Remove; + unused. + * ftfont.h (ftfont_font_format): Remove prototype. + * ftfont.c (ftfont_font_format): Remove; now unused. + (ftfont_open): + * nsfont.m (nsfont_open): + * w32font.c (w32font_open_internal): + * w32uniscribe.c (uniscribe_open): + * xfont.c (xfont_open): + * xftfont.c (xftfont_open): All users changed. + + * coding.c (ALLOC_CONVERSION_WORK_AREA): Prefer ptrdiff_t to int and + so avoid integer overflow if decoded gap size exceeds INT_MAX bytes. + +2014-07-09 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_to): Adjust calculation of line_start_x to what x_produce_glyphs does when it generates a stretch glyph that represents a TAB. (Bug#17969) -2014-07-05 Eli Zaretskii <eliz@gnu.org> - * xdisp.c (pos_visible_p): If CHARPOS is at beginning of window, and there is a display property at that position, don't call move_it_to to move to a position before window start. (Bug#17942) Fix condition for finding CHARPOS by the first call to move_it_to. (Bug#17944) -2014-07-05 Stefan Monnier <monnier@iro.umontreal.ca> +2014-07-09 Stefan Monnier <monnier@iro.umontreal.ca> * syntax.c (find_defun_start): Try the cache even if !open_paren_in_column_0_is_defun_start. (back_comment): If find_defun_start was pessimistic, use the scan_sexps_forward result to improve the cache (bug#16526). -2014-07-04 Daniel Colascione <dancol@dancol.org> - - Backport from trunk. - * xfns.c (create_frame_xic): Pass XNStatusAttributes to XCreateIC - only if xic_style calls for it. This change allows Emacs to work - with ibus. Also, don't leak resources if create_frame_xic fails, - and stop caching xic_style across different displays (Bug#17928). - (supported_xim_styles): Make const. - (best_xim_style): Remove first parameter: it's always just - supported_xim_styles. Change to look at supported_xim_styles directly. - -2014-07-04 Eli Zaretskii <eliz@gnu.org> +2014-07-09 Eli Zaretskii <eliz@gnu.org> * xdisp.c (redisplay_window): If redisplay of a window ends up with point in a partially visible line at end of the window, make @@ -450,7 +3045,109 @@ * w32.c (network_interface_info): Make sure the argument is a Lisp string. -2014-07-01 Eli Zaretskii <eliz@gnu.org> +2014-07-08 Paul Eggert <eggert@cs.ucla.edu> + + * process.c (read_and_dispose_of_process_output): Fix typo + in previous patch: we want nonnegative fds, not nonzero fds. + +2014-07-08 Dmitry Antipov <dmantipov@yandex.ru> + + * chartab.c (char_table_translate): Move to... + * character.h (char_table_translate): ... inline function here. + Avoid Faref and assume that args are always valid. This helps to + speedup search, which is especially important for a huge buffers. + * lisp.h (char_table_translate): Remove prototype. + + * nsfont.m (nsfont_close): Free glyphs and metrics arrays as well. + * font.c (font_build_object) [HAVE_XFT || HAVE_FREETYPE || HAVE_NS]: + New function, with an intention to avoid code duplication between + a few font drivers. + * font.h (font_build_object) [HAVE_XFT || HAVE_FREETYPE || HAVE_NS]: + Add prototype. + * ftfont.c (ftfont_open): + * macfont.m (macfont_open): + * xftfont.c (xftfont_open): Use it. + +2014-07-08 Paul Eggert <eggert@cs.ucla.edu> + + * process.c: Add sanity checks for file descriptors (Bug#17844). + (wait_reading_process_output, Fprocess_filter_multibyte_p): + Check that infd is nonnegative before using it as an fd. + (read_and_dispose_of_process_output, Fprocess_send_eof): + Likewise, for outfd. + (wait_reading_process_output): Omit unnecessary check of infd. + +2014-07-07 Paul Eggert <eggert@cs.ucla.edu> + + Minor fixups related to usage of the 'long' type. + * gnutls.c (emacs_gnutls_handshake): + * xfaces.c (dump_realized_face): + Work even if 'long' is narrower than 'void *'. + * termcap.c (scan_file): + * xselect.c (x_decline_selection_request) + (x_reply_selection_request, x_get_window_property): + * xterm.c (x_set_frame_alpha): + Remove unnecessary 'L' suffixes of integer constants. + * xfns.c (hack_wm_protocols): + * xselect.c (x_fill_property_data): + * xterm.c (x_set_offset, x_set_window_size_1, x_make_frame_invisible): + Remove unnecessary casts to 'long'. + (set_machine_and_pid_properties): Don't assume pid_t fits in 32 bits. + + Minor ImageMagick safety fixes. + * image.c (imagemagick_compute_animated_image): + Remove useless assignment to local. Avoid problems if dest_width is 0. + (imagemagick_load_image): Use int for pixel counts that can't + exceed INT_MAX. Avoid problem if PixelGetNextIteratorRow returns + a row width greater than the image width (or greater than LONG_MAX!). + +2014-07-04 K. Handa <handa@gnu.org> + + * coding.c (MIN_CHARBUF_SIZE): Delete it. + (MAX_CHARBUF_EXTRA_SIZE): New macro. + (ALLOC_CONVERSION_WORK_AREA): Use MAX_CHARBUF_EXTRA_SIZE. + +2014-07-04 Dmitry Antipov <dmantipov@yandex.ru> + + * font.h (struct font_driver): Remove get_outline and free_outline; + not used by any font driver. + * ftfont.c (ftfont_driver): + * macfont.m (macfont_driver): + * nsfont.m (nsfont_driver): + * w32font.c (w32font_driver): + * w32uniscribe.c (uniscribe_font_driver): + * xfont.c (xfont_driver): Related users changed. + * xselect.c (x_get_window_property): Use convenient xmalloc. + Call to xfree only if some data was really allocated. + +2014-07-03 Dmitry Antipov <dmantipov@yandex.ru> + + On MS-Windows, display busy cursor on all GUI frames. + This is similar to what we have on X. Quickly tested by Dani Moncayo. + * w32fns.c (toplevel): Remove hourglass_hwnd; no longer used. + (w32_show_hourglass, w32_hide_hourglass, w32_note_current_window): + Likewise. + (hide_hourglass, show_hourglass): Redesign to match X counterparts. + * xdisp.c (start_hourglass): Remove Windows-specific bits. + +2014-07-03 Dmitry Antipov <dmantipov@yandex.ru> + + Use convenient alists to manage per-frame font driver-specific data. + * frame.h (struct frame): Rename font_data_list to... + [HAVE_XFT || HAVE_FREETYPE]: ... font_data, which is a Lisp_Object now. + * font.h (struct font_data_list): Remove; no longer need a special + data type. + (font_put_frame_data, font_get_frame_data) [HAVE_XFT || HAVE_FREETYPE]: + Adjust prototypes. + * font.c (font_put_frame_data, font_get_frame_data) + [HAVE_XFT || HAVE_FREETYPE]: Prefer alist functions to ad-hoc list + management. + * xftfont.c (xftfont_get_xft_draw, xftfont_end_for_frame): + Related users changed. + * ftxfont.c (ftxfont_get_gcs, ftxfont_end_for_frame): Likewise. + Prefer convenient xmalloc and xfree. + +2014-07-03 Eli Zaretskii <eliz@gnu.org> * dispnew.c (prepare_desired_row): Accept 2 additional arguments: the window whose glyph row is being prepared and a flag whether it @@ -458,31 +3155,173 @@ are in sync with what the window wants. (Bug#17892) - * xdisp.c (display_line, display_mode_line): Call - prepare_desired_row with additional arguments, as appropriate. + * xdisp.c (display_line, display_mode_line): + Call prepare_desired_row with additional arguments, as appropriate. * dispextern.h (prepare_desired_row): Adjust prototype. -2014-07-01 Dmitry Antipov <dmantipov@yandex.ru> +2014-07-03 Dmitry Antipov <dmantipov@yandex.ru> * xfaces.c (init_frame_faces): Always realize basic faces (Bug#17889). * menu.c (Fx_popup_dialog): Set Vmenu_updating_frame to avoid crash caused by xw_popup_dialog in daemon mode (Bug#17891). -2014-06-30 Eli Zaretskii <eliz@gnu.org> +2014-07-03 Eli Zaretskii <eliz@gnu.org> * frame.c (do_switch_frame): When switching to another TTY frame, make sure FrameCols and FrameRows are in sync with the new frame's data. (Bug#17875) +2014-07-02 Dmitry Antipov <dmantipov@yandex.ru> + + Shrink Lisp_Sub_Char_Table by preferring C integers to Lisp_Objects. + * lisp.h (struct Lisp_Sub_Char_Table): Use C integers for depth and + min_char slots. Adjust comment. + (enum char_table_specials): Rename from CHAR_TABLE_STANDARD_SLOTS. + Add SUB_CHAR_TABLE_OFFSET member. + (make_uninit_sub_char_table): New function. + (toplevel): Add compile-time assert to verify suitable member layout + in Lisp_Sub_Char_Table. + * alloc.c (mark_char_table): Add extra argument to denote char table + subtype. Adjust to match new layout of sub char-table. + (mark_object): Always mark sub char-tables with mark_char_table. + * chartab.c (make_sub_char_table, copy_sub_char_table) + (sub_char_table_ref, sub_char_table_ref_and_range, sub_char_table_set) + (sub_char_table_set_range, optimize_sub_char_table, map_sub_char_table) + (map_sub_char_table_for_charset, uniprop_table_uncompress): + All related users changed. + * lread.c (read1): Adjust to match new layout of sub char-table. + * print.c (print_object): Likewise (Bug#17898). + +2014-07-02 Stefan Monnier <monnier@iro.umontreal.ca> + + * keymap.c (get_keyelt): Simplify. + (copy_keymap_item): Remove left-over code for when we had + key-shortcut caches. + +2014-06-30 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (judge): EmacsScroller: Move dealloc code here. + (dealloc): Remove for EmacsScroller. + + * nsterm.h (EmacsScroller): Remove dealloc. + +2014-06-30 Eli Zaretskii <eliz@gnu.org> + + * coding.c (MIN_CHARBUF_SIZE): Enlarge to 32. (Bug#17881) + +2014-06-30 Jan Djärv <jan.h.d@swipnet.se> + + * nsmenu.m (update_frame_tool_bar): Set wait_for_tool_bar to NO + when setNeedsDisplay is called so we don't trigger redisplay for every + tool bar update. + + * nsterm.m (any_help_event_p): New variable. + (mouseMoved:): Set any_help_event_p to YES if help event is + generated. Remove else with empty help event that triggered redisplay + for every mouse move. + (windowDidResignKey:): If any_help_event_p, generate empty help event. + +2014-06-29 Dmitry Antipov <dmantipov@yandex.ru> + + * xfns.c (Qsuppress_icon): Remove; no real users. + (syms_of_xfns): Don't DEFSYM it. Remove ancient comments. + * w32fns.c (Qsuppress_icon): Remove, for the same reason. + (syms_of_w32fns): Don't DEFSYM it. + +2014-06-29 Glenn Morris <rgm@gnu.org> + + * Makefile.in (ns-app): Mark as PHONY. + +2014-06-28 Glenn Morris <rgm@gnu.org> + + * Makefile.in (mostlyclean): There are no libXMenu11.a, + liblw.a in this directory. + 2014-06-28 Andreas Schwab <schwab@linux-m68k.org> * coding.c (encode_coding_utf_8): Correctly count produced_chars also in unibyte case. (Bug#17865) -2014-06-25 Glenn Morris <rgm@gnu.org> +2014-06-28 K. Handa <handa@gnu.org> + + * coding.c (MAX_CHARBUF_SIZE): Rename from CHARBUF_SIZE. + (MIN_CHARBUF_SIZE): New macro. + (ALLOC_CONVERSION_WORK_AREA): New arg SIZE. Callers changed. + +2014-06-27 Glenn Morris <rgm@gnu.org> + + * Makefile.in: Replace BOOTSTRAPEMACS sleight-of-hand + with an order-only dependence on bootstrap-emacs. (Bug#2151) + (.el.elc): Replace suffix rule with pattern rule. + (%.elc): New pattern rule, with order-only prerequisite. + ($(lisp)): No more need to depend on BOOTSTRAPEMACS. + ($(lispsource)/loaddefs.el): Use an order-only prerequisite + in place of BOOTSTRAPEMACS. + +2014-06-26 Dmitry Antipov <dmantipov@yandex.ru> + + * fns.c (Fcompare_strings): Use FETCH_STRING_CHAR_AS_MULTIBYTE_ADVANCE. + +2014-06-25 Dmitry Antipov <dmantipov@yandex.ru> - * puresize.h (BASE_PURESIZE): Increase a bit. (Bug#17846) + Consistently use validate_subarray to verify substring. + * fns.c (validate_substring): Not static any more. Adjust to + use ptrdiff_t, not EMACS_INT, because string and vector limits + can't exceed ptrdiff_t even if EMACS_INT is wider. + (Fcompare_strings, Fsubstring, Fsubstring_no_properties) + (secure_hash): Adjust user. + * lisp.h (validate_subarray): Add prototype. + * coding.c (Fundecodable_char_position): + * composite.c (Fcomposition_get_gstring, Fcompose_string_internal): + Use validate_subarray. Adjust comment to mention substring. + +2014-06-25 Dmitry Antipov <dmantipov@yandex.ru> + + Do not allow out-of-range character position in Fcompare_strings. + * fns.c (validate_subarray): Add prototype. + (Fcompare_substring): Use validate_subarray to check ranges. + Adjust comment to mention that the semantics was changed. Also see + http://lists.gnu.org/archive/html/emacs-devel/2014-06/msg00447.html. + +2014-06-24 Paul Eggert <eggert@cs.ucla.edu> + + Be more consistent about the 'Qfoo' naming convention. + * image.c (Fimagemagick_types): + * lisp.h (lisp_h_CHECK_TYPE, CHECK_TYPE, CHECK_ARRAY): + * process.c (Fmake_network_process): + Rename C local identifier 'Qfoo to avoid giving the false + impression that it stands for the symbol 'foo'. + +2014-06-23 Dmitry Antipov <dmantipov@yandex.ru> + + Simplify and cleanup character conversion stuff. + * lisp.h (multibyte_char_to_unibyte, multibyte_char_to_unibyte_safe): + Remove prototypes. + * character.c (multibyte_char_to_unibyte) + (multibyte_char_to_unibyte_safe): Remove; no longer used. + * character.h (make_char): Remove; unused. + (CHAR_TO_BYTE8, CHAR_TO_BYTE_SAFE): Simplify. + (ASCII_BYTE_P): Remove; ASCII_CHAR_P does the same thing. + * buffer.c, charset.c, charset.h, cmds.c, coding.c, editfns.c: + * fileio.c, indent.c, insdel.c, keyboard.c, lread.c, print.c: + * search.c, term.c, xdisp.c, xterm.c: Related users changed. + +2014-06-22 Mario Lang <mlang@delysid.org> + + * w32fns.c (Fw32_shell_execute): The the -> the. + +2014-06-22 Dmitry Antipov <dmantipov@yandex.ru> + + * xmenu.c (mouse_position_for_popup): + * xselect.c (mouse_position_for_drop): Do not duplicate ... + * xfns.c (x_relative_mouse_position): ... and prefer this function. + * menu.c (Fx_popup_menu): + * xselect.c (x_handle_dnd_message): Adjust users. + * menu.h (mouse_position_for_popup): Remove prototype. + * xterm.h (x_relative_mouse_position): Add prototype. + * xterm.c (x_find_topmost_parent): Break from the loop and do not + call XFree if XQueryTree returns zero. 2014-06-21 Eli Zaretskii <eliz@gnu.org> @@ -498,17 +3337,17 @@ * fileio.c (Ffile_acl): Port to OS X, where acl_get_file (..., ACL_TYPE_ACCESS) doesn't work. -2014-06-19 Stefan Monnier <monnier@iro.umontreal.ca> +2014-06-21 Stefan Monnier <monnier@iro.umontreal.ca> * keyboard.c (read_key_sequence): Don't invoke Vprefix_help_command before checking key-translation-map (bug#17659). -2014-06-19 Dmitry Antipov <dmantipov@yandex.ru> +2014-06-21 Dmitry Antipov <dmantipov@yandex.ru> * font.c (font_make_object): Avoid dangling pointer which may crash GC (Bug#17771). -2014-06-18 Eli Zaretskii <eliz@gnu.org> +2014-06-21 Eli Zaretskii <eliz@gnu.org> * image.c [5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)]: Declare the prototype of DGifCloseFile as appropriate for older and newer @@ -518,46 +3357,254 @@ (gif_load): Call gif_close instead of DGifCloseFile. Divulge the error string where appropriate. (Bug#17790) -2014-06-16 Eli Zaretskii <eliz@gnu.org> - * xdisp.c (Fmove_point_visually): Instead of testing for keyboard macro execution, make sure point didn't move since last complete redisplay, as the condition for using the glyph matrix information. (Bug#17777) -2014-06-14 Eli Zaretskii <eliz@gnu.org> +2014-06-19 Dmitry Antipov <dmantipov@yandex.ru> + + Minor cleanup of fonset code. + * fontset.c (FONTSET_ID, set_fontset_id, FONTSET_NAME) + (set_fontset_name, FONTSET_ASCII, set_fontset_ascii) + (FONTSET_BASE, set_fontset_base, FONTSET_FRAME) + (set_fontset_frame, FONTSET_NOFONT_FACE, set_fontset_nofont_face) + (FONTSET_DEFAULT, set_fontset_default, FONTSET_FALLBACK) + (set_fontset_fallback): Reorder extra slots and avoid unused slots. + (free_realized_fontset): Remove because a no-op since 2008. + (free_face_fontset): Adjust user. + (syms_of_fontset): Shrink fontset by one extra slot. + +2014-06-17 Paul Eggert <eggert@cs.ucla.edu> + + Omit redundant extern decls. + Most of this patch is from Dmitry Antipov, in: + http://lists.gnu.org/archive/html/emacs-devel/2014-06/msg00263.html + * commands.h (update_mode_lines): + * frame.h (Qbackground_color, Qforeground_color) + (x_set_menu_bar_lines): + * ftfont.c (ftfont_font_format): + * intervals.h (Qkeymap, Qfont): + * keyboard.c (timer_check, safe_run_hooks, Qregion_extract_function): + * lisp.h (Ffboundp, Qnil, Qt, Qlambda, Qintegerp, Qwholenump) + (Qsymbolp, Qlisp, Qconsp, Qstringp, Qarrayp, Qbufferp, Qmarkerp) + (Qvectorp, Qbuffer_or_string_p, Qchar_table_p, Qvector_or_char_table_p) + (Qfloatp, Qnumberp, Qfont_spec, Qfont_entity, Qfont_object) + (Fbyteorder, wrong_type_argument, Fmax_char, syms_of_composite) + (Fidentity, extract_float, init_display, syms_of_display, Qdisplay): + (Qimage, Qbox, redisplay_preserve_echo_area, char_table_ref) + (char_table_set, char_table_translate, Qautoload, Qbottom, Qtop) + (Qvisible, Qfont, Qfront_sticky, Qrear_nonsticky, init_sigio) + (Qtool_bar, Qheader_line): + * macros.c (Fexecute_kbd_macro): + * xdisp.c (Ftool_bar_height, Ftool_bar_height): + * xterm.c (x_delete_terminal, XSetIMValues): + * xterm.h (x_set_window_size, x_query_color, x_get_focus_frame) + (x_implicitly_set_name, popup_activated) + (widget_store_internal_border): + Remove redundant decls. + * frame.c [USE_X_TOOLKIT]: Include widget.h. + * keyboard.c (Fexit_recursive_edit, Fabort_recursive_edit): + Remove _Noreturn, as make-docfile now does that for us. + * lisp.h (DEFUN): Don't declare fnname here; rely on make-docfile. + (Qregion_extract_function): New decl. + * window.c, xfns.c: Include menu.h. + +2014-06-17 Stefan Monnier <monnier@iro.umontreal.ca> + + * callint.c (Fcall_interactively): Fix up last change (bug#17701). + +2014-06-17 Dmitry Antipov <dmantipov@yandex.ru> + + * fileio.c (Fread_file_name): Do not pass redundant args and ... + * callint.c (read_file_name): ... convert to static here. + * lisp.h (Fread_file_name): Do not EXFUN it. + (STRING_COPYIN): Remove; unused. + * composite.c (CHAR_COMPOSABLE_P): Replace unsafe macro with ... + (char_composable_p): ... static function. All users changed. + * eval.c (toplevel): Remove redundant #include directives. + * xterm.c (x_initialize): Add static to match prototype. + * ccl.c (Fccl_execute_on_string): + * font.c (fon_intern_prop): Use make_specified_string. + +2014-06-16 Paul Eggert <eggert@cs.ucla.edu> + + * Makefile.in (ns-app): Fix typo that broke build on OS X. + Reported by David Caldwell in: + http://lists.gnu.org/archive/html/emacs-devel/2014-06/msg00251.html + +2014-06-16 Dmitry Antipov <dmantipov@yandex.ru> + + Do not ask for XRender extension each time XFT font is opened. + * xftfont.c (xftfont_open): Move call to XRenderQueryExtension ... + * xterm.c (x_term_init) [HAVE_XFT]: ... to here. Adjust comment. + +2014-06-15 Glenn Morris <rgm@gnu.org> + + * Makefile.in: Use `make -C' rather than `cd && make' throughout. + +2014-06-15 Eli Zaretskii <eliz@gnu.org> * xdisp.c (Fmove_point_visually): Don't use the glyph matrix information if we are in the middle of executing a keyboard macro, since redisplay doesn't update the screen until the macro is finished. (Bug#17777) -2014-06-13 Eli Zaretskii <eliz@gnu.org> - * alloc.c (cleanup_vector): Don't dereference a font driver pointer if it is NULL. (Bug#17771) +2014-06-13 Glenn Morris <rgm@gnu.org> + + * Makefile.in ($(leimdir)/leim-list.el, $(srcdir)/macuvs.h) + ($(lispsource)/international/charprop.el) + ($(libsrc)/make-docfile$(EXEEXT), $(lwlibdir)/liblw.a) + ($(oldXMenudir)/libXMenu11.a, ns-app, .el.elc) + ($(lispsource)/loaddefs.el, bootstrap-emacs$(EXEEXT)): + GNU make automatically passes command-line arguments to sub-makes. + +2014-06-13 Paul Eggert <eggert@cs.ucla.edu> + + Avoid hangs in accept-process-output (Bug#17647). + * lisp.h, process.c (wait_reading_process_input): + Return int, not bool. All uses changed. + * process.c (SELECT_CANT_DO_WRITE_MASK): + Remove macro, replacing with ... + (SELECT_CAN_DO_WRITE_MASK): ... new constant, with inverted sense. + All uses changed. + (status_notify): New arg WAIT_PROC. Return int, not void. + All uses changed. + +2014-06-13 Eli Zaretskii <eliz@gnu.org> + + * menu.c (Fx_popup_menu): Don't call the frame's menu_show_hook if + the frame is the initial frame, because the hook is not set up + then, and Emacs crashes. + Reported by Fabrice Popineau <fabrice.popineau@gmail.com>. + +2014-06-12 Stefan Monnier <monnier@iro.umontreal.ca> + + * keymap.c (silly_event_symbol_error): Don't recommend the use + of strings. + 2014-06-11 Eli Zaretskii <eliz@gnu.org> * xdisp.c (set_cursor_from_row): Fix an off-by-one error when matching overlay strings with 'cursor' property against buffer positions traversed in the glyph row. (Bug#17744) +2014-06-11 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.h (EmacsApp): Always compile in shouldKeepRunning, isFirst + on Cocoa. + + * nsterm.m (run): Always compile for Cocoa. Use runtime check to + determine 10.9 (Bug#17751). + + * macfont.m (macfont_draw): Positions were not freed. + +2014-06-10 Dmitry Antipov <dmantipov@yandex.ru> + + * dispextern.h (PREPARE_FACE_FOR_DISPLAY): Remove as a duplicate of ... + * xfaces.c (prepare_face_for_display) [HAVE_WINDOW_SYSTEM]: ... this + function. Also adjust comment. + * fringe.c, w32term.c, xdisp.c, xterm.c: All users changed. + + * dispextern.h (struct face) [HAVE_XFT]: Ifdef 'extra' member. + * font.c (font_done_for_face): + * xfaces.c (realize_non_ascii_face): Adjust user. + * font.h (struct font_driver): Convert 'prepare_face' to return + void because its return value is never used anyway. + * xfont.c (xfont_prepare_face): Return void. + * xftfont.c (xftfont_prepare_face): Likewise. Use xmalloc. + (xftfont_done_face): Use xfree. + + * dispextern.h (last_tool_bar_item): Remove declaration. + * frame.h (struct frame): New member last_tool_bar_item. + * frame.c (make_frame): Initialize it. + * xdisp.c (toplevel): Remove last_tool_bar_item. + (handle_tool_bar_click, note_tool_bar_highlight): + * w32term.c (w32_read_socket, w32_initialize): + * xterm.c (handle_one_xevent, x_initialize): Adjust users. + + * frame.h (window_system_available) [!HAVE_WINDOW_SYSTEM]: Always false. + * frame.c (window_system_available) [HAVE_WINDOW_SYSTEM]: Now here. + +2014-06-09 Paul Eggert <eggert@cs.ucla.edu> + + Say (accept-process-output P)'s result pertains to P if P is non-nil. + * process.c (Faccept_process_output) + (wait_reading_process_output): Mention that if PROCESS is non-nil, + the return value is about PROCESS, not about other processes. + +2014-06-09 Dmitry Antipov <dmantipov@yandex.ru> + + Further adjustments to mark_object and friends. + Now the mark_object's stack is just 32 bytes on a 64-bit + system, which means extra 20% off the stack usage. + * alloc.c (mark_save_value): As before, refactored out from ... + (mark_object): ... adjusted user. Also add comment. + +2014-06-09 Paul Eggert <eggert@cs.ucla.edu> + + Fix core dump after a dropped X connection (Bug#17704). + * sysdep.c (stuff_char): Don't abort merely because the selected frame + is dead, as we may be shutting down. + 2014-06-08 Glenn Morris <rgm@gnu.org> * fileio.c (write-region-inhibit-fsync): Doc tweak. * data.c (Flss, Fgtr, Fleq, Fgeq): Doc tweaks. -2014-06-04 Eli Zaretskii <eliz@gnu.org> +2014-06-08 Paul Eggert <eggert@cs.ucla.edu> + + If a C name must be extern on some platforms, make it extern on all. + * dispextern.h (set_vertical_scroll_bar, erase_phys_cursor) + (load_color): + * font.h (ftxfont_driver) [HAVE_XFT]: + * keyboard.h (menu_items_inuse, ignore_mouse_drag_p, make_ctrl_char): + * lisp.h (get_frame_param): + * menu.h (tty_menu_show): + * process.h (conv_sockaddr_to_lisp, catch_child_signal): + * termhooks.h (encode_terminal_code): + * xterm.h (x_menu_wait_for_event): + Always declare. + * frame.c (get_frame_param): + * fringe.c (max_used_fringe_bitmap): + * ftxfont.c (ftxfont_driver): + * keyboard.c (ignore_mouse_drag_p, make_ctrl_char): + * menu.c (menu_items_inuse): + * process.c (conv_sockaddr_to_lisp, catch_child_signal): + * term.c (encode_terminal_code, tty_menu_show): + * xdisp.c (set_vertical_scroll_bar, erase_phys_cursor): + * xfaces.c (load_color): + * xmenu.c (x_menu_wait_for_event): + Now always extern. + +2014-06-08 Dmitry Antipov <dmantipov@yandex.ru> + + Change object marking routines to minimize stack usage. + This change moves a few cold paths from mark_object to NO_INLINE + functions and adjusts symbol marking loop. According to GCC 4.8.2 + -Wstack-usage, this reduces mark_object's stack usage from 80 to + 48 bytes on a 64-bit system. For a long byte-force-recompile runs, + stack usage at the mark phase is reduced up to 28%. Surprisingly, + it also gains up to 3% in speed (with default '-O2 -g3' flags). + * alloc.c (mark_compiled, mark_localized_symbol): New functions, + refactored out from ... + (mark_object): ... adjusted user. Also mark symbols in a tight + inner loop. + (mark_face_cache): Add NO_INLINE. + +2014-06-08 Eli Zaretskii <eliz@gnu.org> * sysdep.c (reset_sys_modes): Use cursorX, not curX, as the latter contains garbage on WINDOWSNT (which could potentially infloop at exit). Minimize cursor motion during TTY menu updates. - * term.c (tty_menu_display): Don't position cursor here. Instead, - pass the cursor coordinates to update_frame_with_menu. + * term.c (tty_menu_display): Don't position cursor here. + Instead, pass the cursor coordinates to update_frame_with_menu. (tty_menu_activate): Send the hide cursor command only once in an iteration through the outer 'while' loop. @@ -568,30 +3615,193 @@ update_frame_with_menu. (update_frame_with_menu): Accept 2 additional arguments ROW and COL; if they are non-negative, instruct update_frame_1 not to - position the cursor, and instead position it according to ROW and - COL. + position the cursor, and instead position it according to ROW and COL. * dispextern.h (update_frame_with_menu): Update prototype. -2014-06-02 Stefan Monnier <monnier@iro.umontreal.ca> +2014-06-08 Stefan Monnier <monnier@iro.umontreal.ca> * callproc.c (call_process): Don't check read-only if we don't insert anything (bug#17666). -2014-06-02 Eli Zaretskii <eliz@gnu.org> +2014-06-08 Eli Zaretskii <eliz@gnu.org> * dispnew.c (update_frame_with_menu): Set display_completed. -2014-06-01 Paul Eggert <eggert@cs.ucla.edu> +2014-06-07 Eli Zaretskii <eliz@gnu.org> + + * term.c (tty_menu_show) [WINDOWSNT]: Make tty_menu_show extern + only for WINDOWSNT. + * menu.h (tty_menu_show) [WINDOWSNT]: Declare extern only for WINDOWSNT. + +2014-06-06 Paul Eggert <eggert@cs.ucla.edu> + + * term.c (tty_menu_show) [!HAVE_NTGUI]: Now static. + * menu.h (tty_menu_show) [!HAVE_NTGUI]: Omit extern decl. + +2014-06-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Frecenter): Signal an error if window-buffer is not + current-buffer. + + * keyboard.c (make_lispy_position): Don't include a buffer position in + mode/header-line mouse events. + + * keyboard.c (read_char): Handle (t . <event>) in the second use of + Vunread_command_events (bug#17650). + +2014-06-06 Dmitry Antipov <dmantipov@yandex.ru> + + * xterm.c (x_setup_pointer_blanking): + Conditionally probe Xfixes until this stuff is stabilized (Bug#17609). + +2014-06-05 Dmitry Antipov <dmantipov@yandex.ru> + + * keyboard.c, process.c: Do not define POLL_FOR_INPUT here + because it will be defined in generated config.h if needed. + +2014-06-04 Dmitry Antipov <dmantipov@yandex.ru> + + Use terminal-specific hooks to display popup dialogs. + * termhooks.h (struct terminal): New field popup_dialog_hook. + * menu.c (emulate_dialog_with_menu): New function, refactored from ... + (Fx_popup_dialog): ... adjusted user. Also remove old #if 0 + code and use popup_dialog_hook. + * nsmenu.m (ns_popup_dialog): Make hook-compatible. + * nsterm.h (ns_popup_dialog): Adjust prototype. + * nsterm.m (ns_create_terminal): + * w32term.c (w32_create_terminal): + * xterm.c (x_create_terminal) [USE_X_TOOLKIT || USE_GTK]: + Setup popup_dialog_hook. + +2014-06-04 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (report_temacs_memory_usage): Improve the report by + reporting the large blocks that are actually occupied at dump time. + + * w32console.c (initialize_w32_display): Set the console + menu_show_hook, otherwise TTY menus are broken on w32. + +2014-06-04 Dmitry Antipov <dmantipov@yandex.ru> + + Use terminal-specific hooks to display menus. + * termhooks.h (struct terminal): New field menu_show_hook. + * menu.h (<anonymous enum>): Bit flags for menu hooks. + (x_menu_show, w32_menu_show, ns_menu_show, tty_menu_show): + Adjust prototypes. + * menu.c (Fx_popup_menu): Use bit flags and menu_show_hook. + * nsmenu.m (ns_menu_show): + * w32menu.c (w32_menu_show): + * xmenu.c (x_menu_show): + * term.c (tty_menu_show): Adjust to use bit flags. + (set_tty_hooks): Set menu_show_hook. + * xterm.c (x_create_terminal): + * nsterm.m (ns_create_terminal): + * msdos.c (initialize_msdos_display): + * w32term.c (w32_create_terminal): Likewise. + +2014-06-03 Juanma Barranquero <lekktu@gmail.com> + + * w32heap.c (DUMPED_HEAP_SIZE) [!_WIN64]: Reduce to 11 MB. + +2014-06-03 Eli Zaretskii <eliz@gnu.org> + + * sysselect.h (fd_CLR, fd_ISSET, fd_SET, FD_CLR, FD_ISSET) + (FD_SET): Don't define on WINDOWSNT. + +2014-06-03 Paul Eggert <eggert@cs.ucla.edu> + + * emacs.c: Include "sysselect.h", to define its inline functions. + Problem reported by Glenn Morris in: + http://lists.gnu.org/archive/html/emacs-devel/2014-06/msg00077.html + + Do not require libXt-devel when building with gtk. + * gtkutil.h, menu.h: Include lwlib-widget.h, not lwlib-h, to avoid + dependency on libXt-devel. + * menu.h [HAVE_NTGUI]: Include lwlib-widget.h in this case too. + (enum button_type, widget_value) [HAVE_NTGUI]: Remove, as + lwlib-widget.h now does this. + * nsmenu.m (ns_menu_show): "enabled" -> "enable" to fix typo. + +2014-06-03 Paul Eggert <eggert@penguin.cs.ucla.edu> + + If ENABLE_CHECKING, range-check args of FD_CLR, FD_ISSET, FD_SET. + * process.c (add_read_fd, delete_read_fd, add_write_fd) + (delete_write_fd, wait_reading_process_output): + Remove now-redundant easserts. + * sysselect.h (SYSSELECT_H): New macro, to avoid double-inclusion woes. + Use INLINE_HEADER_BEGIN, INLINE_HEADER_END. + (fd_CLR, fd_ISSET, fd_SET): New inline functions. + (FD_CLR, FD_ISSET, FD_SET): Redefine in terms of these functions. + +2014-06-03 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (DUMPED_HEAP_SIZE): Move from w32heap.h. Don't use + HEAPSIZE; instead, define separate values for the 32- and 64-bit builds. + (calloc): Don't undef, it is never defined. + (HEAP_ENTRY_SHIFT): Remove unused macro. + + * Makefile.in (C_HEAP_SWITCH): Remove. + (ALL_CFLAGS): Don't use $(C_HEAP_SWITCH). + + Fix MS-Windows build broken by menu changes on 2014-06-02. + * w32menu.c (w32_menu_show): Fix a typo that broke compilation. + + * menu.h (enum button_type, struct _widget_value) [HAVE_NTGUI]: + Define instead of including ../lwlib/lwlib.h, which causes + compilation errors due to missing X11 headers. + +2014-06-03 Paul Eggert <eggert@cs.ucla.edu> + + * process.c (wait_reading_process_output): Omit incorrect test of + p->infd against zero. Add easserts for infd having a plausible value. + +2014-06-02 Dmitry Antipov <dmantipov@yandex.ru> + + Adjust to match recent lwlib changes. + * menu.h (xmalloc_widget_value): Replace by ... + (make_widget_value): ... new prototype. + * menu.c (xmalloc_widget_value): Replace by ... + (make_widget_value): ... new function. + (free_menubar_widget_value_tree, digest_single_submenu): Adjust users. + * gtkutil.c (malloc_widget_value, free_widget_value): + (widget_value_free_list, malloc_cpt): Remove old lwlib-compatible code. + * keyboard.h (enum button_type, struct _widget_value): + * gtkutil.h, nsgui.h, w32gui.h (malloc_widget_value, free_widget_value): + Likewise. + * nsmenu.m (ns_update_menubar, ns_menu_show): + * w32menu.c (set_frame_menubar, w32_menu_show, w32_dialog_show): + * xmenu.c (set_frame_menubar, xmenu_show, x_dialog_show): Adjust users. + * xterm.h (XtParent) [USE_GTK]: Remove unused macro. + +2014-06-02 Dmitry Antipov <dmantipov@yandex.ru> + + * image.c (x_query_frame_background_color) + [HAVE_PNG || HAVE_NS || HAVE_IMAGEMAGICK || HAVE_RSVG]: + Fix --enable-gcc-warnings compilation without image libraries. + +2014-06-02 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (malloc_after_dump, realloc_after_dump): Update the + emulated break value only if it goes up. + (sbrk): Add assertion that the INCREMENT argument is strictly + zero. Improve and correct the commentary. + +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> + + Improve AIX-related merge from emacs-24. + * conf_post.h (FLEXIBLE_ARRAY_MEMBER): Fix comment. + * lisp.h (ENUMABLE) [!_AIX]: Don't define to 0 merely because we're + not on AIX; since we're on the trunk we can use enums more broadly. * frame.c (x_set_frame_parameters): Don't read uninitialized storage. -2014-06-01 Jan Djärv <jan.h.d@swipnet.se> +2014-06-02 Jan Djärv <jan.h.d@swipnet.se> * xterm.c (xg_scroll_callback): Remove position, for jump set portion to min(value, whole). -2014-06-01 Paul Eggert <eggert@cs.ucla.edu> +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> Bring back the changes to GDB-visible symbols, but only on AIX. And only if it's not pre-4.2 GCC. @@ -600,7 +3810,7 @@ (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): New macros. -2014-05-31 Eli Zaretskii <eliz@gnu.org> +2014-06-02 Eli Zaretskii <eliz@gnu.org> * fileio.c (Finsert_file_contents): Call prepare_to_modify_buffer with PT, not GPT. (Bug#16433) @@ -611,11 +3821,11 @@ (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): Delete macros. -2014-05-31 Glenn Morris <rgm@gnu.org> +2014-06-02 Glenn Morris <rgm@gnu.org> * cmds.c (Fself_insert_command): Allow zero repeat count. (Bug#17649) -2014-05-30 Paul Eggert <eggert@cs.ucla.edu> +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> Fix port to 32-bit AIX with xlc (Bug#17598). * alloc.c (gdb_make_enums_visible): Remove FLOAT_TO_STRING_BUFSIZE. @@ -623,13 +3833,13 @@ * lisp.h (FLOAT_TO_STRING_BUFSIZE): Make it a macro, instead of an enum, to work around a compiler bug in IBM xlc 12.1. -2014-05-29 Eli Zaretskii <eliz@gnu.org> +2014-06-02 Eli Zaretskii <eliz@gnu.org> * xterm.c (x_update_window_end): Don't invalidate the entire mouse-highlight info, just signal frame_up_to_date_hook that mouse highlight needs to be redisplayed. (Bug#17588) -2014-05-29 Paul Eggert <eggert@cs.ucla.edu> +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> Port the GDB-visible symbols to AIX. Without them, GDB doesn't work to debug Emacs, since the AIX linker @@ -640,35 +3850,248 @@ (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): New macros. -2014-05-26 Paul Eggert <eggert@cs.ucla.edu> - Include sources used to create macuvs.h. * Makefile.in ($(srcdir)/macuvs.h): New rule. * macuvs.h: Use automatically-generated header. -2014-05-25 Eli Zaretskii <eliz@gnu.org> +2014-06-01 Paul Eggert <eggert@cs.ucla.edu> + + Port signal-handling to DragonFly BSD (Bug#17646). + * callproc.c, sysdep.c (block_child_signal, unblock_child_signal): + Move implementations from callproc.c to sysdep.c. + * process.h, syssignal.h (block_child_signal, unblock_child_signal): + Move declarations from process.h to syssignal.h. + +2014-06-01 Juanma Barranquero <lekktu@gmail.com> + + * callint.c (Ffuncall_interactively): Add usage. + +2014-06-01 Jan Djärv <jan.h.d@swipnet.se> + + * nsfns.m (ns_appkit_version_str): Add os version for Cocoa. + +2014-05-30 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (malloc_before_dump, malloc_after_dump) + (malloc_before_dump, realloc_after_dump, realloc_before_dump) + (mmap_alloc, mmap_realloc): Check for errors more thoroughly and + set errno where appropriate to emulate CRT functions. + +2014-05-30 Dmitry Antipov <dmantipov@yandex.ru> + + Debugging facility to check whether 'const char *' points to + relocatable data of non-pure Lisp string. + * alloc.c (maybe_lisp_pointer): New function, refactored out of ... + (mark_maybe_pointer): ... adjusted user. + (relocatable_string_data_p): New function. + * lisp.h (relocatable_string_data_p): Add prototype. + * xdisp.c (message_with_string): If ENABLE_CHECKING, make sure + the pointer to relocatable Lisp data is not used. + +2014-05-30 Paul Eggert <eggert@cs.ucla.edu> + + Don't let SIGINT handling block SIGCHLD indefinitely (Bug#17561). + * atimer.c (block_atimers): + * callproc.c (block_child_signal): Block SIGINT too; + otherwise, its handler might now unblock signals that it shouldn't. + * keyboard.c (read_char): Clear signal mask, since we may + be in a SIGINT handler, and many signals may be masked. + * keyboard.c (handle_interrupt): + * sysdep.c (handle_arith_signal): + Clear signal mask instead of just unblocking the signal that + was received, since several signals may be blocked at this point. + +2014-05-29 Eli Zaretskii <eliz@gnu.org> + + * Makefile.in (TEMACS_POST_LINK): Remove target. + (emacs$(EXEEXT)): Remove $(ADDSECTION) from prerequisites. + (temacs$(EXEEXT)): Remove $(TEMACS_POST_LINK) from the recipe. + +2014-05-29 Dmitry Antipov <dmantipov@yandex.ru> + + * xmenu.c (xdialog_show): Remove prototype, rename to + x_dialog_show, remove 2nd arg because it's always zero + and simplify accordingly. + (xw_popup_dialog): Adjust user. + * w32menu.c (w32_dialog_show): Adjust prototype, remove + 2nd arg because it's always zero and simplify accordingly. + (w32_popup_dialog): Adjust user. + +2014-05-29 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (report_temacs_memory_usage): New function. + + * unexw32.c (unexec) [ENABLE_CHECKING]: + Call report_temacs_memory_usage. + + * w32heap.h (report_temacs_memory_usage): Add prototype. + +2014-05-29 Paul Eggert <eggert@cs.ucla.edu> + + Don't substitute sigprocmask for pthread_sigmask (Bug#17561). + * Makefile.in (LIB_PTHREAD_SIGMASK): Remove; all uses removed. + +2014-05-29 Eli Zaretskii <eliz@gnu.org> + + * buffer.c (init_buffer): Accept an argument 'initialized'. + [USE_MMAP_FOR_BUFFERS]: If 'initialized' is non-zero, reset + mmap_regions and mmap_fd, to avoid referencing stale data from the + dump phase. Add an assertion for buffer text of buffers created + in temacs before this function is called. (Bug#17622) + (mmap_regions_1, mmap_fd_1): Remove unused variables. + + * lisp.h (init_buffer): Update prototype. + + * emacs.c (main): Pass 'initialized' as the argument to init_buffer. + +2014-05-29 Dmitry Antipov <dmantipov@yandex.ru> + + * alloc.c (Fgarbage_collect): Fix compilation with + GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE. + +2014-05-29 Paul Eggert <eggert@cs.ucla.edu> + + * frame.c, frame.h (frame_char_to_pixel_position) + (frame_set_mouse_position): Now static, and made private in + frame.c rather than public in frame.h. + +2014-05-28 Dmitry Antipov <dmantipov@yandex.ru> + + Refactor mouse positioning stuff to avoid code duplication. + * frame.h (frame_char_to_pixel_position): New function. + (x_set_mouse_position): Rename to... + (frame_set_mouse_position): ...new function. + (frame_set_mouse_pixel_position): Add prototype. + * nsterm.m, w32term.c, xterm.c (x_set_mouse_pixel_position): + Rename to frame_set_mouse_pixel_position. + * frame.c (Fset_mouse_pixel_position, Fset_mouse_position): + Adjust users. + * xterm.h, w32term.h ( x_set_mouse_position) + (x_set_mouse_pixel_position): Remove prototypes. + +2014-05-28 Dmitry Antipov <dmantipov@yandex.ru> + + On X, always make pointer visible when deleting frame (Bug#17609). + * frame.c (frame_make_pointer_visible, frame_make_pointer_invisible): + Pass frame as arg. + * frame.h (frame_make_pointer_visible, frame_make_pointer_invisible): + Adjust prototypes. + * cmds.c (Fself_insert_command): Use SELECTED_FRAME. + * keyboard.c (gobble_input): If there is no terminal input error, + make sure the pointer is visible for all frames on this terminal. + * xterm.c (x_free_frame_resources): Enable pointer visibility if + it was previously disabled. + +2014-05-28 Stefan Monnier <monnier@iro.umontreal.ca> + + * data.c (Fzerop): Move to Elisp. + (syms_of_data): Don't defsubr it. + * keyboard.c (echo_keystrokes_p): New function. + (read_char, record_menu_key, read_key_sequence): Use it. + + * callint.c (Qfuncall_interactively): New var. + (Qcall_interactively): Remove. + (Ffuncall_interactively): New function. + (Fcall_interactively): Use it. + (syms_of_callint): Defsubr it. + +2014-05-27 Stefan Monnier <monnier@iro.umontreal.ca> + + * bytecode.c (FETCH) [BYTE_CODE_SAFE]: Check the bytecode wasn't + relocated from under us. + +2014-05-27 Fabrice Popineau <fabrice.popineau@gmail.com> + + Use mmap(2) emulation for allocating buffer text on MS-Windows. + * Makefile.in (C_HEAP_SWITCH): Get the predefined heap size from + configure, not from HEAPSIZE. + (ADDSECTION, MINGW_TEMACS_POST_LINK): Remove, no longer used. + + * lisp.h (NONPOINTER_BITS): Modify the condition to define to zero + for MinGW, since it no longer uses gmalloc. + + * buffer.c: Do not define mmap allocations functions for Windows. + Remove mmap_find which is unused. Remove mmap_set_vars which does + nothing useful. + [WINDOWSNT]: Include w32heap.h. + (init_buffer): Always allocate new memory for buffers. + + * emacs.c: Remove mmap_set_vars calls. + + * image.c (free_image): Undef free for Windows because it is + redirected to our private version. + + * unexw32.c (COPY_PROC_CHUNK): Use %p format for 64bits compatibility. + (copy_executable_and_dump_data): Remove dumping the heap section. + (unexec): Restore using_dynamic_heap after dumping. + + * w32heap.c (dumped_data_commit, malloc_after_dump) + (malloc_before_dump, realloc_after_dump, realloc_before_dump) + (free_after_dump, free_before_dump, mmap_alloc, mmap_realloc) + (mmap_free): New functions. + + * w32heap.h: Declare dumped_data and mmap_* function prototypes. + +2014-05-27 Paul Eggert <eggert@cs.ucla.edu> + + * image.c (imagemagick_load_image): Use MagickRealType for local + 'color_scale', instead of double, to avoid a GCC warning about + double promotion. + + * xfns.c (Fx_window_property): Remove unused local. + + Don't kill already-reaped process (Bug#17561). + * process.c (process_send_signal): Fix race condition where a + subprocess was reaped by a signal handler between the check for + liveness and calling 'kill', which meant that Emacs could in + theory kill an innocent bystander process. Do the fix by blocking + SIGCHLD in a critical section that checks liveness before killing. + +2014-05-26 Eli Zaretskii <eliz@gnu.org> + + * w32.c (_ANONYMOUS_UNION, _ANONYMOUS_STRUCT): Define only if undefined. + +2014-05-26 Ken Brown <kbrown@cornell.edu> + + * w32term.c (x_delete_display): Don't free dpyinfo->w32_id_name, + even if !CYGWIN (see bug#17510). + +2014-05-26 Jan Djärv <jan.h.d@swipnet.se> + + * nsfns.m (Fns_do_applescript): Surround NSApp run + with calls to ns_init_events, ns_finish_events (Bug#17424). + + * nsterm.h (ns_init_events, ns_finish_events): Declare. + + * nsterm.m (ns_init_events, ns_finish_events): New functions. + (ns_read_socket, ns_select): Call ns_init_events, ns_finish_events. + + * nsfns.m (ns_do_applescript): Surround executeAndReturnError + with calls to ns_init_events, ns_finish_events (Bug#17424). + +2014-05-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_in_display_line_to): Don't record wrap position if we are iterating over an object that generates glyphs for marginal areas. (Bug#17585) -2014-05-24 Paul Eggert <eggert@cs.ucla.edu> +2014-05-26 Paul Eggert <eggert@cs.ucla.edu> * xdisp.c (safe__call1, safe__eval): Now static. -2014-05-24 Eli Zaretskii <eliz@gnu.org> +2014-05-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (safe__call): Accept va_list argument instead of '...'. (safe_call, safe__call1): Construct a va_list argument for safe_call. (safe_call1): Call safe_call instead of safe__call directly. -2014-05-24 Ken Brown <kbrown@cornell.edu> +2014-05-26 Ken Brown <kbrown@cornell.edu> * w32term.c (x_delete_display) [CYGWIN]: Don't free dpyinfo->w32_id_name, to make sure it doesn't get freed more than once. (Bug#17510) -2014-05-24 Stefan Monnier <monnier@iro.umontreal.ca> +2014-05-26 Stefan Monnier <monnier@iro.umontreal.ca> * xdisp.c: Bind inhibit-quit during pre-redisplay-function. (safe__call, safe__call1, safe__eval): New functions. @@ -676,67 +4099,215 @@ (prepare_menu_bars): Use it for pre-redisplay-function (bug#17577). (display_mode_element): Same for `:eval'. -2014-05-22 Paul Eggert <eggert@cs.ucla.edu> +2014-05-26 Paul Eggert <eggert@cs.ucla.edu> Fix port to 32-bit AIX (Bug#17540). * unexaix.c (copy_text_and_data): Don't add text_scnptr to ptr twice. _text already includes this offset. (unrelocate_symbols): Don't cast 64-bit integer to pointer. -2014-05-21 Eli Zaretskii <eliz@gnu.org> +2014-05-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_in_display_line_to): Avoid infinite recursion: when closest_pos is identical to to_charpos, don't recurse, since we already tried that, and failed. (Bug#17539) -2014-05-20 Eli Zaretskii <eliz@gnu.org> - * w32fns.c (unwind_create_frame) [GLYPH_DEBUG]: If we are unwinding when frame's faces were not initialized yet, increment the frame's image-cache reference count before calling x_free_frame_resources. Don't dereference dpyinfo->terminal->image_cache if it is NULL. (Bug#17524) -2014-05-11 Glenn Morris <rgm@gnu.org> +2014-05-25 Jan Djärv <jan.h.d@swipnet.se> + + * nsfont.m (nsfont_draw): Simplify as arguments are adjusted in + nsterm.m now. + + * nsterm.m (ns_draw_glyph_string): Move isComposite and end from + macfont.m, call draw with adjusted arguments so font drivers + don't need to do that. + + * macfont.m (macfont_draw): Merge changes from Macport. + +2014-05-24 Eli Zaretskii <eliz@gnu.org> + + * alloc.c (garbage_collect_1): New function, with all of the guts + of Fgarbage_collect. + (mark_stack): Accept an argument END and don't mark Lisp objects + on the stack beyond the address given by END. Calculation of END + was moved to Fgarbage_collect. + (Fgarbage_collect): Calculate the end address of the stack portion + that needs to be examined by mark_stack, and pass that address to + garbage_collect_1, which will pass it to mark_stack. + See http://lists.gnu.org/archive/html/emacs-devel/2014-05/msg00270.html + for more details about the underlying problems. In particular, + this avoids dumping Emacs with the large hash-table whose value is + held in purify-flag for most of the time loadup.el runs. + +2014-05-24 Jan Djärv <jan.h.d@swipnet.se> + + * xfns.c (x_window_property_intern): New function (code from + x_window_property). + (Fx_window_property): Call x_window_property_intern. If property + not found and NILP (source) and outer window != inner window, + check outer window for property (Bug#17537). + +2014-05-22 Paul Eggert <eggert@cs.ucla.edu> + + Supply malloc and alloc_size attributes for extern allocators. + This documents the C API, and helps GCC generate a bit better code. + * conf_post.h (ATTRIBUTE_MALLOC, ATTRIBUTE_ALLOC_SIZE) + (ATTRIBUTE_MALLOC_SIZE): New macros. + * gmalloc.c (malloc, realloc, calloc): + * gtkutil.h (malloc_widget_value): + * lisp.h (ralloc, r_re_alloc, xmalloc, xzalloc, xrealloc, xnmalloc) + (xnrealloc, xstrdup, xlispstrdup, record_xmalloc): + Use them. + +2014-05-21 Paul Eggert <eggert@cs.ucla.edu> + + Don't assume that ImageMagick uses a 16-bit quantum (Bug#17519). + * image.c (imagemagick_load_image): Port to hosts that do not use + a 16-bit quantum, i.e., QuantumRange does not equal 65535. + +2014-05-21 Leo Liu <sdl.web@gmail.com> + + * fns.c (Fnreverse): Accept strings for SEQ and update doc-string. + +2014-05-20 Michael Albinus <michael.albinus@gmx.de> + + * dbusbind.c (xd_signature): Revert last 2 patches. + +2014-05-19 Paul Eggert <eggert@cs.ucla.edu> + + Allow any non-nil value to count as true in bool-vector. + Likewise for xd_signature in dbusbind.c. + This is more consistent with the usual practice in Emacs, which is + that any non-nil value counts as true. + * alloc.c (Fbool_vector): Don't require args to be t or nil. + * dbusbind.c (xd_signature): Likewise, for booleans. + * data.c, lisp.h (Qbooleanp): + * lisp.h (CHECK_BOOLEAN): Remove. All uses removed. + +2014-05-19 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (CHECK_BOOLEAN): New function. + * alloc.c (Fbool_vector): New function. + (syms_of_alloc): Defsubr it. + * data.c (Qbooleanp): New symbol. + (syms_of_data): DEFSYM it. + * dbusbind.c (xd_signature): Use CHECK_BOOLEAN. + + * font.c (font_matching_entity): Extract font-entity object + from the vector of matching entities (Bug#17486). + +2014-05-17 Paul Eggert <eggert@cs.ucla.edu> + + Assume C99 or later (Bug#17487). + * bytecode.c (B__dummy__): Remove. + * conf_post.h (bool_bf) [!NS_IMPL_GNUSTEP]: Use bool. + (FLEXIBLE_ARRAY_MEMBER): Now always empty. + * dbusbind.c (XD_DEBUG_MESSAGE) [!DBUS_DEBUG]: + * regex.c (DEBUG_PRINT): Assume varargs macros. + * lisp.h (DEFUN_FUNCTION_INIT): Remove. All uses now assume C99. + +2014-05-17 Fabrice Popineau <fabrice.popineau@gmail.com> + + * buffer.c (init_buffer) [USE_MMAP_FOR_BUFFERS]: Always map new + memory for every buffer that was dumped. + +2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> + + * fns.c (Freverse): Allow vectors, bool vectors and strings. + (Fnreverse): Allow vectors and bool vectors. + +2014-05-14 Dmitry Antipov <dmantipov@yandex.ru> + + Minor cleanup for terminal setup. + * termhooks.h (create_terminal): Adjust prototype. + * terminal.c (create_terminal): Pass output method and RIF as args. + (init_initial_terminal): + * nsterm.m (ns_create_terminal): + * term.c (init_tty): + * w32term.c (w32_create_terminal): + * xterm.c (x_create_terminal): Adjust users. + Avoid redundant NULL initializers and add comments. + +2014-05-13 Paul Eggert <eggert@cs.ucla.edu> + + * keyboard.c (Qdeactivate_mark): Now static. + +2014-05-13 Dmitry Antipov <dmantipov@yandex.ru> + + If available, use Xfixes extension to do pointer blanking. + * Makefile.in (XFIXES_CFLAGS, XFIXES_LIBS): New var. + * xfns.c (x_set_mouse_color): Do not call make_invisible_cursor here. + (make_invisible_cursor): Move to... + * xterm.c (make_invisible_cursor): ...here. + (x_probe_xfixes_extension, xfixes_toggle_visible_pointer) + (x_toggle_visible_pointer, x_setup_pointer_blanking): New functions. + (x_term_init): Call to x_setup_pointer_blanking. + (XTtoggle_invisible_pointer): Use blanking specific to this display. + * xterm.h (struct x_display_info): New member toggle_visible_pointer. + +2014-05-12 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * xdisp.c (draw_glyphs): Set clipping to highlight boundaries. + +2014-05-12 Glenn Morris <rgm@gnu.org> * fileio.c (Ffile_executable_p): Doc tweak. -2014-05-10 Jan Djärv <jan.h.d@swipnet.se> +2014-05-12 Jan Djärv <jan.h.d@swipnet.se> * xsettings.c (init_gsettings): Use g_settings_schema_source_lookup instead of deprecated g_settings_list_schemas if possible (Bug#17434). -2014-05-07 Paul Eggert <eggert@cs.ucla.edu> +2014-05-08 Paul Eggert <eggert@cs.ucla.edu> * minibuf.c (read_minibuf): Avoid C99ism in previous patch (Bug#17430). -2014-05-07 Jarek Czekalski <jarekczek@poczta.onet.pl> +2014-05-08 Jarek Czekalski <jarekczek@poczta.onet.pl> Fix initialization of minibuffer history variable (Bug#17430). * minibuf.c (read_minibuf): Initialize histval to Qnil if unbound. Move the initialization up to prevent any "value void" message. -2014-05-06 Samuel Bronson <naesten@gmail.com> +2014-05-08 Samuel Bronson <naesten@gmail.com> * keyboard.c (Frecursive_edit): Ensure inc&dec of command_loop_level are matched (bug#17413). -2014-05-06 Jarek Czekalski <jarekczek@poczta.onet.pl> +2014-05-08 Jarek Czekalski <jarekczek@poczta.onet.pl> Stop tooltips pulling Emacs window to front (Bug#17408). * w32fns.c (Fx_show_tip): Add SWP_NOOWNERZORDER flag to SetWindowPos invocations. -2014-05-05 Jan Djärv <jan.h.d@swipnet.se> +2014-05-08 Jan Djärv <jan.h.d@swipnet.se> * nsselect.m (Fx_selection_exists_p): Just return Qnil if window system not initialized (Bug#17398). +2014-05-07 Paul Eggert <eggert@cs.ucla.edu> + + * image.c: Include <png.h> before <setjmp.h> (Bug#17429). + +2014-05-06 Paul Eggert <eggert@cs.ucla.edu> + + * image.c: Do not use libpng if HAVE_NS, as NS does its own thing. + [HAVE_NS]: Do not include png.h. + (x_query_frame_background_color): New function. + (png_load_body, imagemagick_load_image, svg_load_image): Use it. + (png_load_body): Coalesce duplicate code. + 2014-05-04 Paul Eggert <eggert@cs.ucla.edu> - Revert recent libpng changes (Bug#17339). - * Makefile.in (PNG_CFLAGS): Remove; all uses removed. - * image.c [HAVE_LIBPNG_PNG_H]: Include <libpng/png.h>, not <png.h>. + Consult libpng-config more consistently (Bug#17339). + * Makefile.in (PNG_CFLAGS): New var. + (ALL_CFLAGS): Use it. + * image.c [HAVE_PNG]: Don't worry about <libpng/png.h>, as + CFLAGS now handles this. 2014-05-03 Paul Eggert <eggert@cs.ucla.edu> @@ -749,14 +4320,6 @@ * buffer.c (overlay_strings): Fix the wording of the commentary. -2014-05-02 Paul Eggert <eggert@cs.ucla.edu> - - Consult libpng-config more consistently (Bug#17339). - * Makefile.in (PNG_CFLAGS): New var. - (ALL_CFLAGS): Use it. - * image.c [HAVE_PNG]: Don't worry about <libpng/png.h>, as - CFLAGS now handles this. - 2014-05-01 Glenn Morris <rgm@gnu.org> * floatfns.c (Fisnan): @@ -789,26 +4352,66 @@ GCC 4.9.0 warned about this, and I couldn't easily prove to my own satisfaction that they would always be initialized. -2014-04-29 Eli Zaretskii <eliz@gnu.org> +2014-04-30 Eli Zaretskii <eliz@gnu.org> - * term.c (tty_menu_display): Move the cursor to the active menu - item. + * term.c (tty_menu_display): Move the cursor to the active menu item. (tty_menu_activate): Return the cursor to the active menu item - after displaying the menu and after displaying help-echo. See - http://lists.gnu.org/archive/html/emacs-devel/2014-04/msg00402.html + after displaying the menu and after displaying help-echo. + See http://lists.gnu.org/archive/html/emacs-devel/2014-04/msg00402.html for the details of why this is needed by screen readers and Braille displays. -2014-04-29 Glenn Morris <rgm@gnu.org> +2014-04-30 Glenn Morris <rgm@gnu.org> * process.c (handle_child_signal): Handle systems without WCONTINUED. (Bug#15110, 17339) -2014-04-23 Eli Zaretskii <eliz@gnu.org> +2014-04-29 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (struct saved_window): Remove mark. + (Fset_window_configuration, save_window_save) + (compare_window_configurations): Don't touch marks any more. + +2014-04-28 Paul Eggert <eggert@cs.ucla.edu> + + Use bits_word for gcmarkbits. + * alloc.c (struct cons_block, struct float_block): On 64-bit hosts, + bits_word is typically a tad more efficient for mark bits than + unsigned is, so use bits_word. All uses changed. + * lisp.h (BITS_PER_INT): Remove; no longer used. + + Avoid undefined behavior in signed left shift. + This ports to GCC 4.9.0 with -fsanitize=undefined. + * alloc.c (bool_vector_fill, SETMARKBIT, UNSETMARKBIT): + * data.c (Fash): + * regex.c (extract_number): + * lisp.h (make_number, XINT): + Do not shift a 1 bit left into a sign bit. + * alloc.c (struct cons_block, struct float_block): Use unsigned, + not int, for gcmarkbits. All uses changed. + +2014-04-25 Eli Zaretskii <eliz@gnu.org> * search.c (Fnewline_cache_check): Don't try to count newlines outside the buffer's restriction, as find_newline doesn't support that. +2014-04-24 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Fset_window_configuration): Deactivate the mark before + unsetting the mark. + (set_window_buffer): Ignore window_initialized. + (window_initialized): Remove. + * keyboard.c (Qdeactivate_mark): Not static any more. + * buffer.c (buffer_local_value): Rename from buffer_local_value_1. + Update all callers. + +2014-04-23 Paul Eggert <eggert@cs.ucla.edu> + + * conf_post.h (ADDRESS_SANITIZER_WORKAROUND): Port to GCC 4.9.0 + and to clang 3.4, which have fixed the bug. This should let us + run a bit faster on these platforms when address sanitization is + in effect. + 2014-04-22 Paul Eggert <eggert@cs.ucla.edu> Port to GCC 4.9.0 with --enable-gcc-warnings. @@ -825,42 +4428,61 @@ (Fnewline_cache_check): New function. (syms_of_search): Defsubr it. -2014-04-21 Jarek Czekalski <jarekczek@poczta.onet.pl> +2014-04-22 Jarek Czekalski <jarekczek@poczta.onet.pl> Fix freezing with scroll bars of GTK3 Toolkit (bug#15801). * keyboard.c (unblock_input): Add comment. * xgselect.c (xg_select): Prevent Glib main loop recursion. +2014-04-22 Daniel Colascione <dancol@dancol.org> + + * lread.c (readevalloop_eager_expand_eval): New function + that can recurse into toplevel forms. + (readevalloop): Call it. + * lisp.h: Declare Qprogn. + * callint.c (Qprogn): No longer static. + 2014-04-19 Stefan Monnier <monnier@iro.umontreal.ca> * intervals.c (rotate_right, rotate_left): Fix up length computation. Also change identifiers to match the comments, and add more assertions (bug#16234). -2014-04-18 Eli Zaretskii <eliz@gnu.org> - - * xdisp.c (insert_left_trunc_glyphs): Ensure the left truncation - glyph is written to TEXT_AREA of the temporary glyph_row. - (Bug#17288) - 2014-04-18 Paul Eggert <eggert@cs.ucla.edu> * emacs.c (close_output_streams): Don't clear and restore errno. -2014-04-17 Jan Djärv <jan.h.d@swipnet.se> +2014-04-18 Jan Djärv <jan.h.d@swipnet.se> * xterm.c (x_make_frame_visible): Prevent endless loop when frame never becomes visible, i.e. using XMonad (Bug#17237). -2014-04-17 Eli Zaretskii <eliz@gnu.org> +2014-04-18 Eli Zaretskii <eliz@gnu.org> - * xdisp.c (Fline_pixel_height): Don't assume that the current - buffer and the selected window's buffer are one and the same. - (Bug#17281) + * xdisp.c (insert_left_trunc_glyphs): Ensure the left truncation + glyph is written to TEXT_AREA of the temporary glyph_row. (Bug#17288) + (Fline_pixel_height): Don't assume that the current buffer and the + selected window's buffer are one and the same. (Bug#17281) * insdel.c (invalidate_buffer_caches): Invalidate the bidi paragraph-start cache before the newline cache. (Bug#17269) +2014-04-17 Paul Eggert <eggert@cs.ucla.edu> + + * term.c (tty_send_additional_strings): No need to fflush here, + as callers fflush. + (tty_set_terminal_modes): fflush after sending additional strings, + not before. + +2014-04-17 Daniel Colascione <dancol@dancol.org> + + * term.c (Qtty_mode_set_strings, Qtty_mode_reset_strings): + New symbols. + (tty_send_additional_strings): New function. + (tty_set_terminal_modes, tty_reset_terminal_modes): Use it. + (syms_of_term): Intern tty-mode-set-strings and + tty-mode-reset-strings. + 2014-04-16 Stefan Monnier <monnier@iro.umontreal.ca> * window.c (save_window_save): Lookup window_point_insertion_type in @@ -928,44 +4550,57 @@ Move vfork-related portions under #ifndef MSDOS. (syms_of_callproc): Unify templates of MSDOS and WINDOWSNT. -2014-04-15 Stefan Monnier <monnier@iro.umontreal.ca> +2014-04-16 Stefan Monnier <monnier@iro.umontreal.ca> * buffer.c (Foverlays_at): Add argument `sorted'. -2014-04-14 Eli Zaretskii <eliz@gnu.org> +2014-04-16 Eli Zaretskii <eliz@gnu.org> * insdel.c (invalidate_buffer_caches): When deleting or replacing text, invalidate the bidi_paragraph_cache upto and including the preceding newline. -2014-04-13 Paul Eggert <eggert@cs.ucla.edu> +2014-04-16 Paul Eggert <eggert@cs.ucla.edu> Port to IRIX 6.5 (Bug#9684). - * alloc.c (TAGGABLE_NULL): New constant, - for porting to hosts with nontrivial DATA_SEG_BITS settings. - (next_vector, set_next_vector): Use it. * conf_post.h (INET6) [IRIX6_5]: Define. (HAVE_GETADDRINFO) [IRIX6_5]: Undef. * data.c (BITS_PER_ULL): Don't assume ULLONG_MAX is defined. - * lisp.h (lisp_h_XPNTR): Don't OR in bits that aren't masked out, - for consistency with how TAGGABLE_NULL is computed. -2014-04-13 Eli Zaretskii <eliz@gnu.org> +2014-04-16 Eli Zaretskii <eliz@gnu.org> * keyboard.c (Fopen_dribble_file): Encode the dribble file-name before passing it to system APIs. - * puresize.h (BASE_PURESIZE): Bump by 1K. (Bug#17255) - -2014-04-13 Stefan Monnier <monnier@iro.umontreal.ca> +2014-04-16 Stefan Monnier <monnier@iro.umontreal.ca> * bytecode.c (exec_byte_code): Rework the volatiles. Most importantly, make sure stack.byte_string_start is not de-adjusted by pushhandler. -2014-04-12 Paul Eggert <eggert@cs.ucla.edu> +2014-04-16 Paul Eggert <eggert@cs.ucla.edu> * keyboard.c (Fopen_dribble_file): Avoid some races. (Bug#17187) +2014-04-15 Paul Eggert <eggert@cs.ucla.edu> + + Remove DATA_SEG_BITS. + The DATA_SEG_BITS hack was needed for older 32 bit platforms. + As a result of this change, Emacs won't work on IRIX 6.5 with IRIX + cc, but that platform is so old that SGI itself stopped supporting + it in December 2013. If you still need Emacs on IRIX, please + either compile with GCC and port the undumping code, or run + './configure --with-wide-int'. + * alloc.c (gdb_make_enums_visible): Update to match lisp.h. + * lisp.h (GCTYPEBITS): Move definition up, and switch to the + DEFINE_GDB_SYMBOL_START way to define it. + (NONPOINTER_BITS): New macro. + (EMACS_INT): Use it. + [!USE_LSB_TAG && !WIDE_EMACS_INT]: Fail, and suggest reporting + the problem and/or configuring --with-wide-int. + (USE_LSB_TAG): Simplify, based on above changes. + (gdb_DATA_SEG_BITS): Remove. All uses removed. + * vm-limit.c (exceeds_lisp_ptr): Remove. All uses removed. + 2014-04-12 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_by_lines): If a large portion of buffer text is @@ -976,8 +4611,6 @@ * indent.c (Fvertical_motion): Handle correctly the case when the display string is preceded by an empty line. -2014-04-11 Eli Zaretskii <eliz@gnu.org> - * w32.c (sys_umask) <WRITE_USER>: Remove redundant constant, and use S_IWRITE instead. @@ -985,10 +4618,33 @@ * keyboard.c (Fopen_dribble_file): Make file private. (Bug#17187) -2014-04-09 Ken Brown <kbrown@cornell.edu> +2014-04-11 Ken Brown <kbrown@cornell.edu> * Makefile.in (EMACS_MANIFEST): Revert last change. +2014-04-10 Daniel Colascione <dancol@dancol.org> + + * puresize.h (BASE_PURESIZE): Increase. + +2014-04-09 Stefan Monnier <monnier@iro.umontreal.ca> + + * keyboard.c (syms_of_keyboard): Make deactivate-mark buffer-local. + + * insdel.c (prepare_to_modify_buffer_1): Cancel lock-file checks and + region handling (and don't call signal_before_change) if + inhibit_modification_hooks is set. + (signal_before_change): Don't check inhibit_modification_hooks any more. + +2014-04-08 Daniel Colascione <dancol@dancol.org> + + * alloc.c (sweep_symbols, mark_object): Assert that symbol + function cells contain valid lisp objects. (Modified version of + patch from Dmitry). + + * alloc.c (detect_suspicious_free): Split actual stack capturing + out into new function for easier breakpoint setting. + (note_suspicious_free): New function. + 2014-04-07 Stefan Monnier <monnier@iro.umontreal.ca> * lisp.h (struct Lisp_Symbol): New bitfield `pinned'. @@ -1004,58 +4660,183 @@ (Fgarbage_collect): Use it. (gc_sweep): Remove hack made unnecessary. -2014-04-05 Glenn Morris <rgm@gnu.org> +2014-04-07 Glenn Morris <rgm@gnu.org> * keyboard.c (Fopen_dribble_file): Doc tweak. -2014-04-04 Jan Djärv <jan.h.d@swipnet.se> +2014-04-07 Ken Brown <kbrown@cornell.edu> - Backport from trunk. - * nsterm.m (updateFrameSize:): If waiting for the tool bar and tool - bar is zero height, just return (Bug#16976). - (initFrameFromEmacs:): Initialize wait_for_tool_bar. - * nsterm.h (EmacsView): Add wait_for_tool_bar. - * nsmenu.m (update_frame_tool_bar): Return early if view or toolbar - is nil. If waiting for toolbar to complete, force a redraw. - (free_frame_tool_bar): Set wait_for_tool_bar = NO (Bug#16976). + * Makefile.in (EMACS_MANIFEST): Update comment. (Bug#17176) -2014-04-03 Ken Brown <kbrown@cornell.edu> +2014-04-07 Paul Eggert <eggert@cs.ucla.edu> - * Makefile.in (EMACS_MANIFEST): Update comment. (Bug#17176) + * alloc.c: Simplify by removing use of HAVE_EXECINFO_H. + We have a substitute execinfo.h on hosts that lack it. + (suspicious_free_history): Make it EXTERNALLY_VISIBLE so it + isn't optimized away. + +2014-04-05 Paul Eggert <eggert@cs.ucla.edu> + + Prefer 'ARRAYELTS (x)' to 'sizeof x / sizeof *x'. + * alloc.c (memory_full): + * charset.c (syms_of_charset): + * doc.c (Fsnarf_documentation): + * emacs.c (main): + * font.c (BUILD_STYLE_TABLE): + * keyboard.c (make_lispy_event): + * profiler.c (setup_cpu_timer): + * xgselect.c (xg_select): + * xterm.c (record_event, STORE_KEYSYM_FOR_DEBUG): + Use ARRAYELTS. + * font.c (FONT_PROPERTY_TABLE_SIZE): Remove. + Replace the only use with ARRAYELTS (font_property_table). + * xfaces.c (DIM): Remove. All uses replaced by ARRAYELTS. + +2014-04-03 Daniel Colascione <dancol@dancol.org> + + * xterm.c (x_term_init): + * xfns.c (best_xim_style): + * xfaces.c (Fdump_colors): + * w32fns.c (w32_default_color_map): + * w32.c (init_environment, N_ENV_VARS): + * unexcw.c (read_exe_header): + * term.c (term_get_fkeys_1): + * sysdep.c (init_baud_rate): + * nsterm.m (ns_convert_key): + * nsfns.m (get_geometry_from_preferences): + * msdos.c (dos_set_window_size, init_environment): + * macfont.m (mac_font_get_glyph_for_cid) + (macfont_store_descriptor_attributes) + (macfont_create_attributes_with_spec, mac_ctfont_get_glyph_for_cid): + * keyboard.c (command_loop_1, read_menu_command, make_lispy_event) + (NUM_MOD_NAMES, read_key_sequence_vs, Fcurrent_input_mode) + (syms_of_keyboard): + * image.c (xpm_str_to_color_key): + * fringe.c (MAX_STANDARD_FRINGE_BITMAPS): + * frame.c (x_set_frame_parameters): + * fileio.c (Ffile_selinux_context): + * emacs.c (sort_args): + * dosfns.c (msdos_stdcolor_name): + * dired.c (file_attributes): + * chartab.c (uniprop_decoder_count, uniprop_encode_count): + Change expressions of the form sizeof(arr) / sizeof(arr[0]) + to ARRAYELTS (arr). + +2014-04-02 Daniel Colascione <dancol@dancol.org> + + * data.c (Ffset): Abort if we're trying to set a function call to + a dead lisp object. + + * lisp.h (ARRAYELTS): New macro. + + * alloc.c: Include execinfo.h if available. + (SUSPICIOUS_OBJECT_CHECKING): New macro; define unconditionally. + (suspicious_free_record): New structure. + (suspicious_objects, suspicious_object_index) + (suspicious_free_history, suspicious_free_history_index): + New variables. + (find_suspicious_object_in_range, detect_suspicious_free) + (Fsuspicious_object): New functions. + (cleanup_vector): Call find_suspicious_object_in_range. 2014-04-02 Martin Rudalics <rudalics@gmx.at> * xterm.c (x_new_font): Don't calculate non-toolkit scrollbar width from font width (Bug#17163). -2014-03-30 Martin Rudalics <rudalics@gmx.at> - * frame.c (x_set_frame_parameters): Calculate default values of new frame sizes only after all other frame parameters have been processed (Bug#17142). -2014-03-28 Ken Brown <kbrown@cornell.edu> +2014-04-02 Ken Brown <kbrown@cornell.edu> * conf_post.h (SYSTEM_PURESIZE_EXTRA) [CYGWIN]: Set to 10000. (Bug#17112) -2014-03-28 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> +2014-04-02 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> * xterm.c (x_draw_image_glyph_string): Adjust image background width accordingly when its x position is adjusted. (Bug#17115) +2014-04-02 Dmitry Antipov <dmantipov@yandex.ru> + + * font.c (font_list_entities): Do not add empty vector to font cache. + (font_matching_entity): Likewise. If matching entity is found, insert + 1-item vector with this entity instead of entity itself (Bug#17125). + + * xterm.c (x_term_init) [USE_LUCID]: Fix minor memory leak. + +2014-04-01 Paul Eggert <eggert@cs.ucla.edu> + + * fns.c (validate_subarray): Rename from validate_substring, + since it works for vectors too. New arg ARRAY. Optimize for the + non-nil case. Instead of returning bool, throw an error if out of + range, so that the caller needn't do that. All uses changed. + Report original values if out of range. + (Fsubstring, Fsubstring_no_properties, secure_hash): + Also optimize the case where FROM is 0 or TO is the size. + +2014-03-31 Dmitry Antipov <dmantipov@yandex.ru> + + * search.c (Freplace_match): Use make_specified_string. + * xterm.c, w32term.c (x_set_glyph_string_gc): Use emacs_abort + to catch bogus override face of glyph strings. + * fns.c (Fsubstring, Fsubstring_no_properties, secure_hash): + Move common substring range checking code to... + (validate_substring): ...this function. + +2014-03-31 Jan Djärv <jan.h.d@swipnet.se> + + * nsmenu.m (free_frame_tool_bar): Set wait_for_tool_bar = NO (Bug#16976) + +2014-03-30 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (updateFrameSize:): If waiting for the tool bar and tool + bar is zero height, just return (Bug#16976). + (initFrameFromEmacs:): Initialize wait_for_tool_bar. + + * nsterm.h (EmacsView): Add wait_for_tool_bar. + + * nsmenu.m (update_frame_tool_bar): Return early if view or toolbar + is nil. If waiting for toolbar to complete, force a redraw. + +2014-03-28 Glenn Morris <rgm@gnu.org> + + * emacs.c (emacs_version): Use PACKAGE_VERSION rather than VERSION. + (emacs_bugreport): New variable. + (usage_message): Use PACKAGE_BUGREPORT. + (syms_of_emacs) <report-emacs-bug-address>: New variable. + + * emacs.c (syms_of_emacs) <system-configuration-features>: New var. + +2014-03-27 Paul Eggert <eggert@cs.ucla.edu> + + Port recent signal-related changes to FreeBSD. + Problem reported by Herbert J. Skuhra. + * lisp.h (block_tty_out_signal, unblock_tty_out_signal): + Move decls from here ... + * syssignal.h: ... to here, so that lisp.h doesn't depend on signal.h. + 2014-03-27 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> * w32term.c (x_draw_image_glyph_string): Fix computation of height and width of image background when it is displayed with a 'box' face. (Bug#17115) -2014-03-26 Paul Eggert <eggert@penguin.cs.ucla.edu> +2014-03-27 Paul Eggert <eggert@penguin.cs.ucla.edu> More backward-compatible fix to char-equal core dump (Bug#17011). * editfns.c (Fchar_equal): In unibyte buffers, assume values in range 128-255 are raw bytes. Suggested by Eli Zaretskii. +2014-03-27 Juanma Barranquero <lekktu@gmail.com> + + * image.c (init_svg_functions): When loading SVG-related libraries, + free already loaded libraries if the initialization fails. + (rsvg_handle_set_size_callback): Remove declaration, unused. + +2014-03-26 Paul Eggert <eggert@cs.ucla.edu> + Fix core dump in char-equal (Bug#17011). * editfns.c (Fchar_equal): Do not use MAKE_CHAR_MULTIBYTE in unibyte buffers, as we can't tell whether the characters are @@ -1063,7 +4844,7 @@ * insdel.c (adjust_markers_for_delete): Remove unused local. -2014-03-24 Barry O'Reilly <gundaetiapo@gmail.com> +2014-03-26 Barry O'Reilly <gundaetiapo@gmail.com> Have (MARKER . ADJUSTMENT) undo records always be immediately after their corresponding (TEXT . POS) record in undo list. @@ -1091,38 +4872,134 @@ (record_point): at_boundary calculation no longer needs to account for marker adjustments. -2014-03-24 Martin Rudalics <rudalics@gmx.at> +2014-03-26 Martin Rudalics <rudalics@gmx.at> * w32term.c (x_set_window_size): Refine fix from 2014-03-14 (Bug#17077). -2014-03-23 Glenn Morris <rgm@gnu.org> +2014-03-26 Glenn Morris <rgm@gnu.org> * fileio.c (Ffile_symlink_p): Doc fix. (Bug#17073) -2014-03-23 Stefan Monnier <monnier@iro.umontreal.ca> +2014-03-26 Stefan Monnier <monnier@iro.umontreal.ca> * buffer.c (struct sortvec): Add field `spriority'. (compare_overlays): Use it. (sort_overlays): Set it. -2014-03-23 Eli Zaretskii <eliz@gnu.org> +2014-03-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (redisplay_window): If all previous attempts to find the cursor row failed, try a few alternatives before falling back to the top-most row of the window. Use row_containing_pos. (Bug#17047) -2014-03-22 Daniel Colascione <dancol@dancol.org> +2014-03-26 Juanma Barranquero <lekktu@gmail.com> - * process.c (conv_sockaddr_to_lisp): When extracting the string - names of AF_LOCAL sockets, stop before reading uninitialized - memory. + * image.c (x_bitmap_height, x_bitmap_width) [HAVE_X_WINDOWS]: + * sysdep.c (reset_sigio) [!DOS_NT]: Declare conditionally. + + * keyboard.c (read_decoded_event_from_main_queue): #ifdef out + variables on Windows. + + * w32fns.c (Ffile_system_info): Use parenthesis in and/or expression. + + * w32.c (unsetenv): Remove unused var `retval'. + (emacs_gnutls_pull): Remove unused vars `fdset' and `timeout'. + + * w32notify.c (watch_worker): Remove unnecesary var sleep_result. + (start_watching): Remove unused var `thr'. + + * w32proc.c (sys_spawnve): Comment out unused vars `first', `last'. + (find_child_console): Remove unnecesary var `thread_id'. + + * w32term.c (w32_read_socket): Comment out unused vars `row', `columns'. + (x_focus_frame): #ifdef 0 unused variable `dpyinfo'. + +2014-03-26 Glenn Morris <rgm@gnu.org> + + * filelock.c (Flock_buffer): Doc tweak. + + * buffer.c (Frestore_buffer_modified_p, Fkill_buffer): + * emacs.c (shut_down_emacs): + * fileio.c (Finsert_file_contents, write_region): + * filelock.c (top-level, syms_of_filelock): + * insdel.c (prepare_to_modify_buffer_1): + CLASH_DETECTION is always defined now. + +2014-03-25 Eli Zaretskii <eliz@gnu.org> + + * w32.c (w32_delayed_load): Call DisableThreadLibraryCalls on the + DLL handle, to speed up thread startup. + +2014-03-25 Paul Eggert <eggert@cs.ucla.edu> + + Handle sigmask better with nested signal handlers (Bug#15561). + * atimer.c (sigmask_atimers): Remove. + Remaining use rewritten to use body of this function. + * atimer.c (block_atimers, unblock_atimers): + * callproc.c (block_child_signal, unblock_child_signal): + * sysdep.c (block_tty_out_signal, unblock_tty_out_signal): + New arg OLDSET. All callers changed. + * atimer.c (block_atimers, unblock_atimers): + * callproc.c (block_child_signal, unblock_child_signal): + * keyboard.c (handle_interrupt): + * sound.c (vox_configure, vox_close): + Restore the old signal mask rather than unilaterally clearing bits + from the mask, in case a handler is running within another + handler. All callers changed. + * lisp.h, process.c, process.h, term.c: + Adjust decls and callers to match new API. + * sysdep.c (emacs_sigaction_init): Don't worry about masking SIGFPE; + signal handlers aren't supposed to use floating point anyway. + (handle_arith_signal): Unblock just SIGFPE rather than clearing mask. + +2014-03-23 Daniel Colascione <dancol@dancol.org> + + Split gc_sweep into discrete functions for legibility and better + stack traces. + + * alloc.c (sweep_strings, sweep_vectors): Add NO_INLINE + (sweep_vectors): Fix typo in comment. + (sweep_conses, sweep_floats, sweep_intervals) + (sweep_symbols, sweep_misc, sweep_buffers): New functions. + (gc_sweep): Call new functions, to which existing functionality is + moved. + * fns.c (sweep_weak_hash_tables): Add NO_INLINE. + +2014-03-23 Juanma Barranquero <lekktu@gmail.com> + + * w32fns.c (Fw32_shell_execute): Declare `result' only on Cygwin. + +2014-03-23 Daniel Colascione <dancol@dancol.org> + + * xfns.c (create_frame_xic): Pass XNStatusAttributes to XCreateIC + only if xic_style calls for it. This change allows Emacs to work + with ibus. Also, don't leak resources if create_frame_xic fails, + and stop caching xic_style across different displays. + (supported_xim_styles): Make const. + (best_xim_style): Remove first parameter: it's always just + supported_xim_styles. Change to look at supported_xim_styles + directly. + +2014-03-23 Daniel Colascione <dancol@dancol.org> + + * term.c (init_tty): Rearrange condition for clarity; print + appropriate diagnostic. 2014-03-23 Daniel Colascione <dancol@dancol.org> * process.c (DATAGRAM_CONN_P): Don't underflow datagram_address array. (ASAN caught.) +2014-03-22 Glenn Morris <rgm@gnu.org> + + * callproc.c (init_callproc): In etc, look for NEWS rather than GNU. + +2014-03-22 Daniel Colascione <dancol@dancol.org> + + * process.c (conv_sockaddr_to_lisp): When extracting the string + names of AF_LOCAL sockets, stop before reading uninitialized memory. + 2014-03-21 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> Fix regression introduced by patch for Bug#10500. @@ -1135,6 +5012,33 @@ constrain frame size in SW_SHOWMAXIMIZED case so we can truly maximize a frame for odd default fonts. +2014-03-21 Glenn Morris <rgm@gnu.org> + + * minibuf.c (history-length): Increase default from 30 to 100. + +2014-03-21 Daniel Colascione <dancol@dancol.org> + + * xterm.c (x_bitmap_icon): Stop reading the icon bitmap from disk + every time we switch to minibuffer. + + * alloc.c (lisp_align_malloc, allocate_string_data) + (allocate_vectorlike): Allow mmap allocation of lisp objects. + (pointers_fit_in_lispobj_p, mmap_lisp_allowed_p): New functions. + +2014-03-21 Eli Zaretskii <eliz@gnu.org> + + * w32fns.c (Fw32_shell_execute) [!CYGWIN]: Use ShellExecuteEx, to + support more "verbs". + +2014-03-21 Daniel Colascione <dancol@dancol.org> + + Always prohibit dumping a dumped Emacs. + + * emacs.c (might_dump): New variable. + (Fdump_emacs): Always prohibit dumping of dumped Emacs. + * lisp.h (might_dump): Declare. + * unexcw.c (unexec): Remove now-redundant multiple-dump detection code. + 2014-03-20 Paul Eggert <eggert@cs.ucla.edu> * doc.c (store_function_docstring): Fix pointer signedness mismatch. @@ -1144,8 +5048,7 @@ * doc.c (store_function_docstring): Warn when we don't know where to put a docstring. (Fsubstitute_command_keys): Don't advertise the fact that - text-properties are dropped, since we think it's a bug that we'll fix - in 24.5. + text-properties are dropped, since we think it's a bug that we'll fix. * frame.h (SET_FRAME_VISIBLE): Keep frame_garbaged up to date. * xterm.c (handle_one_xevent) <MapNotify>: Don't garbage the frame. @@ -6784,7 +10687,7 @@ (imagemagick_get_animation_cache): Fix a double-free error. (imagemagick_load_image): Remove the ping_wand code, which only apparently saved time on invalid animated images, and slowed down - everything else. Optimise for the common case. + everything else. Optimize for the common case. 2013-08-16 Xue Fuqiao <xfq.free@gmail.com> diff --git a/src/ChangeLog.8 b/src/ChangeLog.8 index a483a561d06..fd8ae6caa20 100644 --- a/src/ChangeLog.8 +++ b/src/ChangeLog.8 @@ -73,8 +73,8 @@ * msdos.c (dos_set_window_size) [__DJGPP__ > 1]: If the frame dimensions changed, invalidate the mouse highlight info. - (disable_mouse_highlight, help_echo, previous_help_echo): New - variables. + (disable_mouse_highlight, help_echo, previous_help_echo): + New variables. (IT_set_mouse_pointer, show_mouse_face, clear_mouse_face) (fast_find_position, IT_note_mode_line_highlight) (IT_note_mouse_highlight): New functions. @@ -89,8 +89,8 @@ (internal_terminal_init): Initialize mouse-highlight related members of the_only_x_display. Assign IT_frame_up_to_date to frame_up_to_date_hook. - (dos_rawgetc): If the mouse moved, update mouse highlight. If - help_echo changed value, generate a HELP_EVENT event. + (dos_rawgetc): If the mouse moved, update mouse highlight. + If help_echo changed value, generate a HELP_EVENT event. (syms_of_msdos): Staticpro help_echo and previous_help_echo. * msdos.h (struct display_info): New. @@ -116,7 +116,7 @@ * lisp.h (GLYPH): Defined as `int', not `unsigned int'. Now the lowest 8 bits are single byte character code, the bits above are face ID. - (GLYPH_MASK_FACE, GLYPH_MASK_CHAR): Adjusted for the change + (GLYPH_MASK_FACE, GLYPH_MASK_CHAR): Adjust for the change above. (FAST_MAKE_GLYPH, FSST_GLYPH_FACE): Likewise. (GLYPH_MASK_REV_DIR, GLYPH_MASK_PADDING): Macros deleted. @@ -131,20 +131,20 @@ level members. Change members in union `u'. (GLYPH_EQUAL_P): Check also members face_id and padding_p. (GLYPH_CHAR_AND_FACE_EQUAL_P): New macro. - (SET_CHAR_GLYPH): Adjusted for the change of struct glyph. + (SET_CHAR_GLYPH): Adjust for the change of struct glyph. (CHAR_GLYPH_PADDING_P): Likewise. (GLYPH_FROM_CHAR_GLYPH): Likewise. Always return -1 for multibyte characters. - * dispnew.c (line_hash_code, direct_output_for_insert): Adjusted - for the change of struct glyph. - (line_draw_cost): Adjusted for the change of + * dispnew.c (line_hash_code, direct_output_for_insert): + Adjust for the change of struct glyph. + (line_draw_cost): Adjust for the change of GLYPH_FROM_CHAR_GLYPH. (count_match): Use macro GLYPH_CHAR_AND_FACE_EQUAL_P. - * term.c (encode_terminal_code): Adjusted for the change of struct + * term.c (encode_terminal_code): Adjust for the change of struct glyph and GLYPH_FROM_CHAR_GLYPH. - (write_glyphs, insert_glyphs, append_glyph): Adjusted for the + (write_glyphs, insert_glyphs, append_glyph): Adjust for the change of struct glyph. * xdisp.c: All codes adjusted for the change of struct glyph. @@ -284,8 +284,8 @@ 1999-12-15 Kenichi Handa <handa@etl.go.jp> - The following changes are for the new composition mechanism. We - have deleted `composition' charset and composite characters, + The following changes are for the new composition mechanism. + We have deleted `composition' charset and composite characters, instead introduced a special text property `composition'. * Makefile.in (INTERVAL_SRC): Include composite.h. @@ -298,7 +298,7 @@ (keyboard.o) (textprop.o) (intervals.o): Depend on INTERVAL_SRC. (composite.o): New target. - * alloc.c (Fmake_string): Adjusted for the change of CHAR_STRING. + * alloc.c (Fmake_string): Adjust for the change of CHAR_STRING. * callproc.c (Fcall_process): Call code_convert_string to encode arguments. Use CODING_REQUIRE_DECODING to check if the process @@ -317,7 +317,7 @@ (Fmake_category_table): New function. (syms_of_category): Defsubr it. - * ccl.c (CCL_WRITE_CHAR): Adjusted for the change of CHAR_STRING. + * ccl.c (CCL_WRITE_CHAR): Adjust for the change of CHAR_STRING. (ccl_driver): Delete codes for a composite character. * charset.h: In this entry, just `Modified' means that codes for a @@ -326,49 +326,49 @@ (charset_composition) (MIN_CHAR_COMPOSITION) (MAX_CHAR_COMPOSITION) (GENERIC_COMPOSITION_CHAR) (COMPOSITE_CHAR_P) (MAKE_COMPOSITE_CHAR) (COMPOSITE_CHAR_ID) - (PARSE_COMPOSITE_SEQ) (PARSE_CHARACTER_SEQ): Deleted. + (PARSE_COMPOSITE_SEQ) (PARSE_CHARACTER_SEQ): Delete. (MAX_CHAR) (CHARSET_VALID_P) (CHARSET_DEFINED_P) (CHARSET_AT) (FIRST_CHARSET_AT) (SAME_CHARSET_P) (MAKE_NON_ASCII_CHAR) (PARSE_MULTIBYTE_SEQ) (SPLIT_NON_ASCII_CHAR) (CHAR_PRINTABLE_P): - Modified. + Modify. (SPLIT_STRING): Call split_string, not split_non_ascii_string. (CHAR_STRING): Delete WORKBUF argument. Call char_string, not non_ascii_char_to_string. (STRING_CHAR): Call string_to_char, not string_to_non_ascii_char. (STRING_CHAR_AND_LENGTH): Likewise. (FETCH_CHAR_ADVANCE): New macro. - (MAX_COMPONENT_COUNT) (struct cmpchar_info): Deleted. + (MAX_COMPONENT_COUNT) (struct cmpchar_info): Delete. (MAX_MULTIBYTE_LENGTH): New macro. - (MAX_LENGTH_OF_MULTI_BYTE_FORM): Deleted. + (MAX_LENGTH_OF_MULTI_BYTE_FORM): Delete. (find_charset_in_str): Argument adjusted. - (CHAR_LEN): Modified. + (CHAR_LEN): Modify. * charset.c: In this entry, just `Modified' means that codes for a composite character is deleted. (Qcomposition) (leading_code_composition) (charset_composition) (min_composite_char) (cmpchar_table) - (cmpchar_table_size) (n_cmpchars): Deleted. - (SPLIT_COMPOSITE_SEQ): Deleted. - (SPLIT_MULTIBYTE_SEQ): Modified. - (char_to_string): Renamed from non_ascii_char_to_string. + (cmpchar_table_size) (n_cmpchars): Delete. + (SPLIT_COMPOSITE_SEQ): Delete. + (SPLIT_MULTIBYTE_SEQ): Modify. + (char_to_string): Rename from non_ascii_char_to_string. Modified. - (string_to_char): Renamed from string_to_non_ascii_char. - (split_string): Renamed from split_non_ascii_string. + (string_to_char): Rename from string_to_non_ascii_char. + (split_string): Rename from split_non_ascii_string. (char_printable_p) (Fsplit_char) (Ffind_charset_region) (Ffind_charset_string) (char_valid_p) - (char_bytes) (Fchar_width) (strwidth): Modified. + (char_bytes) (Fchar_width) (strwidth): Modify. (find_charset_in_str): Argument CMPCHARP deleted. Modified. - (Fstring): Adjusted for the change of CHAR_STRING. Modified. + (Fstring): Adjust for the change of CHAR_STRING. Modified. (hash_string) (CMPCHAR_HASH_TABLE_SIZE) (cmpchar_hash_table) (CMPCHAR_HASH_SIZE) (CMPCHAR_HASH_USED) (CMPCHAR_HASH_CMPCHAR_ID) (str_cmpchar_id) (cmpchar_component) (Fcmpcharp) (Fcmpchar_component) (Fcmpchar_cmp_rule) (Fcmpchar_cmp_rule_p) - (Fcmpchar_cmp_count): Deleted. + (Fcmpchar_cmp_count): Delete. (Fcompose_string): Implemented by Emacs Lisp in composite.el. - (init_charset_once): Modified. - (syms_of_charset): Modified. + (init_charset_once): Modify. + (syms_of_charset): Modify. - * cmds.c (internal_self_insert): Adjusted for the change of + * cmds.c (internal_self_insert): Adjust for the change of CHAR_STRING. * coding.h (emacs_code_class_type): Delete the member @@ -377,8 +377,8 @@ (COMPOSING_WITH_RULE_TAIL) (COMPOSING_NO_RULE_TAIL) (COMPOSING_WITH_RULE_RULE) (COMPOSING_HEAD_P) (COMPOSING_WITH_RULE_P): Macros deleted. - (COMPOSITION_DATA_SIZE) (COMPOSITION_DATA_MAX_BUNCH_LENGTH): New - macros. + (COMPOSITION_DATA_SIZE) (COMPOSITION_DATA_MAX_BUNCH_LENGTH): + New macros. (struct composition_data): New structure. (CODING_FINISH_INSUFFICIENT_CMP): New macro. (struct coding_system): New members composition_rule_follows, @@ -395,7 +395,7 @@ EMACS_leading_code_composition to 0x80. (detect_coding_iso2022): Handle new composition sequence. (DECODE_ISO_CHARACTER): Likewise. - (check_composing_code): Deleted. + (check_composing_code): Delete. (coding_allocate_composition_data): New function. (CODING_ADD_COMPOSITION_START) (CODING_ADD_COMPOSITION_END) (CODING_ADD_COMPOSITION_COMPONENT) (DECODE_COMPOSITION_START) @@ -404,7 +404,7 @@ (ENCODE_ISO_CHARACTER): Don't check composition here. (ENCODE_COMPOSITION_RULE) (ENCODE_COMPOSITION_START): New macros. (ENCODE_COMPOSITION_NO_RULE_START) - (ENCODE_COMPOSITION_WITH_RULE_START): Deleted. + (ENCODE_COMPOSITION_WITH_RULE_START): Delete. (ENCODE_COMPOSITION_END): Handle new composition sequence. (ENCODE_COMPOSITION_FAKE_START): New macro. (encode_coding_iso2022): Handle new composition sequence. @@ -414,12 +414,12 @@ coding_system. Enable composition only when the coding system has `composition' property t. (coding_free_composition_data) (coding_adjust_composition_offset) - (coding_save_composition) (coding_restore_composition): New - functions. + (coding_save_composition) (coding_restore_composition): + New functions. (code_convert_region): Call coding_save_composition for encoding and coding_allocate_composition_data for decoding. Don't skip - ASCII characters if we handle composition on encoding. Call - signal_after_change with Check_BORDER. + ASCII characters if we handle composition on encoding. + Call signal_after_change with Check_BORDER. (code_convert_string): Call coding_save_composition for encoding and coding_allocate_composition_data for decoding. Don't skip ASCII characters if we handle composition on encoding. @@ -448,9 +448,9 @@ * dispnew.c (direct_output_forward_char): Check point moving into or out of a composition. If so, give up direct method. - * doprnt.c (doprnt1): Adjusted for the change of CHAR_STRING. + * doprnt.c (doprnt1): Adjust for the change of CHAR_STRING. - * editfns.c (Fchar_to_string): Adjusted for the change of + * editfns.c (Fchar_to_string): Adjust for the change of CHAR_STRING. (general_insert_function): Likewise. (Finsert_char): Likewise. @@ -460,19 +460,19 @@ * emacs.c (main): Call syms_of_composite. - * fileio.c (Fsubstitute_in_file_name): Adjusted for the change of + * fileio.c (Fsubstitute_in_file_name): Adjust for the change of CHAR_STRING. (Finsert_file_contents): Set Vlast_coding_system_used before calling signal_after_change. Call update_compositions if some texts are inserted.. - (Fwrite_region): Adjusted for the change of a_write and e_write. + (Fwrite_region): Adjust for the change of a_write and e_write. (a_write): Argument changed. Work based on character position, not byte position. (e_write): Argument changed. Handle new way of composition. * fns.c (Flength): The length of char-table is MAX_CHAR. - (concat): Adjusted for the change of CHAR_STRING. - (Ffillarray): Adjusted for the change of CHAR_STRING. + (concat): Adjust for the change of CHAR_STRING. + (Ffillarray): Adjust for the change of CHAR_STRING. (Fset_char_table_default): Delete codes for a composite character. (hash_put): Return hash index. @@ -492,7 +492,7 @@ (Fmove_to_column): Likewise. (compute_motion): Likewise. - * insdel.c (copy_text): Adjusted for the change of CHAR_STRING. + * insdel.c (copy_text): Adjust for the change of CHAR_STRING. (insert_char): Likewise. (insert): Call update_compositions. (insert_and_inherit): Likewise. @@ -502,7 +502,7 @@ (insert_from_string_before_markers): Likewise. (insert_from_buffer): Likewise. (replace_range): Likewise. - (count_combining_composition): Deleted. + (count_combining_composition): Delete. (count_combining_before): Delete codes for a composite character. (count_combining_after): Likewise. (del_range_1): Call update_compositions. @@ -526,16 +526,16 @@ necessary. (adjust_point_for_property): New function. - * keymap.c (push_key_description): Adjusted for the change of + * keymap.c (push_key_description): Adjust for the change of CHAR_STRING. (Ftext_char_description): Likewise. * lisp.h (QCtest, QCweakness, Qequal): Extern them. - (hash_put): Adjusted for the change of the definition. + (hash_put): Adjust for the change of the definition. (signal_after_change): Likewise. (check_point_in_composition): Extern it. - * lread.c (readchar): Adjusted for the change of CHAR_STRING. + * lread.c (readchar): Adjust for the change of CHAR_STRING. Delete a code that handles an invalid too-long multibyte sequence because we are now sure that we never encounter with such a sequence. @@ -544,14 +544,14 @@ (init_obarray): Likewise. (read1): Likewise. Adjusted for the change of CHAR_STRING. - * print.c (printchar): Adjusted for the change of CHAR_STRING. + * print.c (printchar): Adjust for the change of CHAR_STRING. * process.c: Include composite.h. (read_process_output): Call update_compositions. - * regex.c (regex_compile): Adjusted for the change of CHAR_STRING. + * regex.c (regex_compile): Adjust for the change of CHAR_STRING. - * search.c (search_buffer): Adjusted for the change of CHAR_STRING. + * search.c (search_buffer): Adjust for the change of CHAR_STRING. * syntax.h (SYNTAX_ENTRY_INT): Delete codes for a composite character. @@ -570,19 +570,19 @@ (face_before_or_after_it_pos): For composition, check face of a character after the composition. (handle_composition_prop): New function. - (get_next_display_element): Adjusted for the change of + (get_next_display_element): Adjust for the change of CHAR_STRING. (set_iterator_to_next): Handle the case that it->method == next_element_from_composition. (next_element_from_composition): New function. - (message_dolog): Adjusted for the change of CHAR_STRING. + (message_dolog): Adjust for the change of CHAR_STRING. (set_message_1): Likewise. (check_point_in_composition): New function. (reconsider_clip_changes): If point moved into or out of composition, set b->clip_changed to 1 to force updating of the screen. (disp_char_vector): Delete codes for a composite character. - (decode_mode_spec_coding): Adjusted for the change of CHAR_STRING. + (decode_mode_spec_coding): Adjust for the change of CHAR_STRING. * xfaces.c (choose_face_fontset_font): Delete codes for a composite character. @@ -592,7 +592,7 @@ * xfns.c: Include intervals.h. (syms_of_xfns): Make `display' property nonsticky by default. - * xselect.c (lisp_data_to_selection_data): Adjusted for the change + * xselect.c (lisp_data_to_selection_data): Adjust for the change for find_charset_in_str. * xterm.h (struct x_output): Change member font_baseline to @@ -618,9 +618,9 @@ (x_draw_composite_glyph_string_foreground): New function. (x_draw_glyph_string_box): Check s->cmp, not s->cmpcharp. (x_draw_glyph_string): Handle the case of COMPOSITE_GLYPH. - (struct work): Deleted. - (x_fill_composite_glyph_string): Argument changed. Mostly - rewritten for that. + (struct work): Delete. + (x_fill_composite_glyph_string): Argument changed. + Mostly rewritten for that. (x_fill_glyph_string): Don't check CHARSET_COMPOSITION. (BUILD_CHAR_GLYPH_STRINGS): Don't handle composition here. (BUILD_COMPOSITE_GLYPH_STRING): New macro. @@ -656,8 +656,8 @@ * frame.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL) [!MSDOS && !WINDOWSNT && !macintosh]: Moved here from xterm.h. - * xterm.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Moved - to frame.h. + * xterm.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): + Move to frame.h. 1999-12-09 Stefan Monnier <monnier@cs.yale.edu> @@ -668,11 +668,11 @@ * xterm.c (#includes): Allow compilation with only Xaw. (xaw3d_arrow_scroll, xaw3d_pick_top): New variables. (xt_action_hook): Replace XAW3D by XAW. - (xaw3d_jump_callback): Renamed to xaw_jump_callback. - (xaw_jump_callback): Renamed from xaw3d_jump_callback. + (xaw3d_jump_callback): Rename to xaw_jump_callback. + (xaw_jump_callback): Rename from xaw3d_jump_callback. Determine epsilon dynamically and don't try to be too clever. - (xaw3d_scroll_callback): Renamed to xaw_scroll_callback. - (xaw_scroll_callback): Renamed from xaw3d_scroll_callback. + (xaw3d_scroll_callback): Rename to xaw_scroll_callback. + (xaw_scroll_callback): Rename from xaw3d_scroll_callback. Handle both Xaw3d with arrow-scrollbars and with Xaw-style scrollbar (using `ratio'). (x_create_toolkit_scroll_bar): Try to detect which style of Xaw3d @@ -710,9 +710,9 @@ 1999-12-07 Alexandre Oliva <oliva@dcc.unicamp.br> - * unexelf.c: Include <syms.h>, not <sym.h> on IRIX. Removed - duplicate definition of ElfW. - (find_section): Copied from unexsgi.c. + * unexelf.c: Include <syms.h>, not <sym.h> on IRIX. + Removed duplicate definition of ElfW. + (find_section): Copy from unexsgi.c. (unexec): Use find_section. Adjust whitespace. Initialize new_data2_offset based on old_data, not sbss (this fixes a bug on IRIX6). Change #ifdef __mips to __sgi, since it's IRIX-specific. @@ -798,8 +798,8 @@ (FRAME_PARAM_FACES, FRAME_N_PARAM_FACES, FRAME_DEFAULT_PARAM_FACE) (FRAME_MODE_LINE_PARAM_FACE, FRAME_COMPUTED_FACES) (FRAME_N_COMPUTED_FACES, FRAME_SIZE_COMPUTED_FACES) - (FRAME_DEFAULT_FACE, FRAME_MODE_LINE_FACE, unload_color): Remove - unused macro definitions. + (FRAME_DEFAULT_FACE, FRAME_MODE_LINE_FACE, unload_color): + Remove unused macro definitions. * msdos.c (IT_set_frame_parameters): Don't call recompute_basic_faces, the next redisplay will, anyway. @@ -818,13 +818,13 @@ * Makefile.in (lisp, shortlisp): Add lisp/term/tty-colors.elc. - * xfns.c (x_defined_color): Rename from defined_color. All - callers changed. - (Fxw_color_defined_p): Renamed from Fx_color_defined_p; + * xfns.c (x_defined_color): Rename from defined_color. + All callers changed. + (Fxw_color_defined_p): Rename from Fx_color_defined_p; all callers changed. - (Fxw_color_values): Renamed from Fx_color_values; all callers + (Fxw_color_values): Rename from Fx_color_values; all callers changed. - (Fxw_display_color_p): Renamed from Fx_display_color_p; all + (Fxw_display_color_p): Rename from Fx_display_color_p; all callers changed. (x_window_to_frame, x_any_window_to_frame) (x_non_menubar_window_to_frame, x_menubar_window_to_frame) @@ -834,11 +834,11 @@ * w32fns.c (x_window_to_frame): Use FRAME_W32_P instead of f->output_data.nothing. - (Fxw_color_defined_p): Renamed from Fx_color_defined_p; + (Fxw_color_defined_p): Rename from Fx_color_defined_p; all callers changed. - (Fxw_color_values): Renamed from Fx_color_values; all callers + (Fxw_color_values): Rename from Fx_color_values; all callers changed. - (Fxw_display_color_p): Renamed from Fx_display_color_p; all + (Fxw_display_color_p): Rename from Fx_display_color_p; all callers changed. * dispextern.h (tty_color_name): Add prototype. @@ -856,7 +856,7 @@ 1999-12-06 Kenichi Handa <handa@etl.go.jp> - * fileio.c (decide_coding_unwind): Renamed from + * fileio.c (decide_coding_unwind): Rename from set_auto_coding_unwind. (Finsert_file_contents): Make single unwind protect to call both Vset_auto_coding_function and Ffind_operation_coding_system. @@ -868,7 +868,7 @@ * regex.c (regex_compile): Recognize *?, +? and ?? as non-greedy operators and handle them properly. * regex.h (RE_ALL_GREEDY): New option. - (RE_UNMATCHED_RIGHT_PAREN_ORD): Moved to the end where alphabetic + (RE_UNMATCHED_RIGHT_PAREN_ORD): Move to the end where alphabetic sorting would put it. (RE_SYNTAX_AWK, RE_SYNTAX_GREP, RE_SYNTAX_EGREP) (_RE_SYNTAX_POSIX_COMMON): Use the new option to keep old behavior. @@ -898,8 +898,8 @@ 1999-11-28 Gerd Moellmann <gerd@gnu.org> * systime.h (EMACS_TIME_CMP, EMACS_TIME_EQ, EMACS_TIME_NE) - (EMACS_TIME_GT, EMACS_TIME_GE, EMACS_TIME_LT, EMACS_TIME_LE): New - macros. + (EMACS_TIME_GT, EMACS_TIME_GE, EMACS_TIME_LT, EMACS_TIME_LE): + New macros. * config.in (HAVE_SETITIMER, HAVE_UALARM): New. @@ -932,8 +932,8 @@ * puresize.h (BASE_PURESIZE): Increase to 550000. - * textprop.c (set_text_properties): New function. Like - Fset_text_properties, but with additional parameter + * textprop.c (set_text_properties): New function. + Like Fset_text_properties, but with additional parameter SIGNAL_AFTER_CHANGE_P. If that is nil, don't signal after changes. (Fset_text_properties): Use it. @@ -1018,7 +1018,7 @@ * fileio.c (strerror): Likewise. * process.c (strerror): Likewise. * emacs.c (strerror): Likewise. - (Vsystem_messages_locale): Renamed from Vmessages_locale. + (Vsystem_messages_locale): Rename from Vmessages_locale. All uses changed. (Vprevious_system_messages_locale): Likewise, from Vprevious_messages_locale. @@ -1041,7 +1041,7 @@ (FREE_RETURN_TYPE): New macro. (free): Return type is now FREE_RETURN_TYPE. - * lisp.h (synchronize_system_time_locale): Renamed from + * lisp.h (synchronize_system_time_locale): Rename from synchronize_time_locale. All uses changed. (synchronize_system_messages_locale): Likewise, from synchronize_messages_locale. @@ -1135,13 +1135,13 @@ 1999-11-10 Gerd Moellmann <gerd@gnu.org> - * xfns.c (QCuser_data): Removed. + * xfns.c (QCuser_data): Remove. (syms_of_xfns): Initialization of QCuser_data removed. - (parse_image_spec): Don't handle :user-data specially. Allow - unknown keys. Remove parameter ALLOW_OTHER_KEYS. + (parse_image_spec): Don't handle :user-data specially. + Allow unknown keys. Remove parameter ALLOW_OTHER_KEYS. (xbm_image_p, xbm_load, xpm_image_p, pbm_image_p, png_image_p) - (tiff_image_p, jpeg_image_p, gif_image_p, gs_image_p): Call - parse_image_spec accordingly. + (tiff_image_p, jpeg_image_p, gif_image_p, gs_image_p): + Call parse_image_spec accordingly. 1999-11-09 Richard M. Stallman <rms@gnu.org> @@ -1178,8 +1178,8 @@ * lisp.h: Add prototype for unmark_byte_stack. * bytecode.c (mark_byte_stack): Use XMARKBIT and XMARK. - (unmark_byte_stack): Renamed from relocate_byte_pcs. Use - XUNMARK. + (unmark_byte_stack): Rename from relocate_byte_pcs. + Use XUNMARK. * xdisp.c (resize_mini_window): Fix computation of needed mini-window height. @@ -1214,7 +1214,7 @@ (byte_stack_list, mark_byte_stack, relocate_byte_pcs): New. (BEFORE_POTENTIAL_GC, AFTER_POTENTIAL_GC): New. (FETCH, PUSH, POP, DISCARD, TOP, MAYBE_GC): Rewritten. - (HANDLE_RELOCATION): Removed. + (HANDLE_RELOCATION): Remove. (Fbyte_code): Use byte_stack structures. * filelock.c (Ffile_locked_p): Make FILENAME a required argument. @@ -1224,10 +1224,10 @@ 1999-11-04 Gerd Moellmann <gerd@gnu.org> - * editfns.c (Fdelete_field): Renamed from Ferase_field. + * editfns.c (Fdelete_field): Rename from Ferase_field. - * minibuf.c (do_completion, Fminibuffer_complete_word): Use - Ferase_field instead of Fdelete_field. + * minibuf.c (do_completion, Fminibuffer_complete_word): + Use Ferase_field instead of Fdelete_field. 1999-11-03 Gerd Moellmann <gerd@gnu.org> @@ -1279,7 +1279,7 @@ * xfns.c (png_load) [PNG_READ_sRGB_SUPPORTED]: Put code using png_get_sRGB in #ifdef. - * dispnew.c (Finternal_show_cursor): Renamed from Fshow_cursor. + * dispnew.c (Finternal_show_cursor): Rename from Fshow_cursor. (syms_of_display): Use the new name. * textprop.c (verify_interval_modification): Signal text-read-only @@ -1346,7 +1346,7 @@ 1999-10-27 Richard M. Stallman <rms@gnu.org> - * data.c (Qad_activate_internal): Renamed from Qad_activate. + * data.c (Qad_activate_internal): Rename from Qad_activate. (Ffset): Call Qad_activate_internal. (syms_of_data): Initialize Qad_activate_internal. @@ -1493,12 +1493,12 @@ * editfns.c: Include coding.h. (emacs_strftime): Remove decl. (emacs_strftimeu): New decl. - (emacs_memftimeu): Renamed from emacs_memftime; new arg UT. + (emacs_memftimeu): Rename from emacs_memftime; new arg UT. Use emacs_strftimeu instead of emacs_strftime. (Fformat_time_string): Convert format string using Vlocale_coding_system, and convert result back. Synchronize time - locale before invoking lower level function. Invoke - emacs_memftimeu, passing ut, instead of emacs_memftime. + locale before invoking lower level function. + Invoke emacs_memftimeu, passing ut, instead of emacs_memftime. * emacs.c: Include <locale.h> if HAVE_SETLOCALE is defined. (Vmessages_locale, Vprevious_messages_locale, Vtime_locale) @@ -1506,7 +1506,7 @@ (main): Invoke setlocale early, so that initial error messages are localized properly. But skip locale-setting if LC_ALL is "C". Fix up locale when it's safe to do so. - (fixup_locale): Moved here from xterm.c. + (fixup_locale): Move here from xterm.c. (synchronize_locale, synchronize_time_locale) (synchronize_messages_locale): New functions. (syms_of_emacs): Accommodate above changes. @@ -1534,8 +1534,8 @@ * lread.c (file_offset, file_tell): New macros. All uses of ftell changed to file_tell. - (saved_doc_string_position, prev_saved_doc_string_position): Now - of type file_offset. + (saved_doc_string_position, prev_saved_doc_string_position): + Now of type file_offset. (init_lread): Do not fix locale here; fixup_locale now does this. * m/amdahl.h, s/usg5-4.h: @@ -1589,10 +1589,10 @@ (emacs_open, emacs_close, emacs_read, emacs_write): Always define; the old INTERRUPTIBLE_OPEN, INTERRUPTIBLE_CLOSE, and INTERRUPTIBLE_IO macros are no longer used. - (emacs_open): Renamed from sys_open. Merge BSD4_1 version. - (emacs_close): Renamed from sys_close. - (emacs_read): Renamed from sys_read. - (emacs_write): Renamed from sys_write. + (emacs_open): Rename from sys_open. Merge BSD4_1 version. + (emacs_close): Rename from sys_close. + (emacs_read): Rename from sys_read. + (emacs_write): Rename from sys_write. (sys_siglist): Do not declare if HAVE_STRSIGNAL. (dup2): Do not print error on failure; the real dup2 doesn't. (strsignal): New function, defined if !HAVE_STRSIGNAL. @@ -1638,8 +1638,8 @@ 1999-10-18 Kenichi Handa <handa@etl.go.jp> * coding.c (code_convert_string): Add record_unwind_protect to - assure setting inhibit_pre_post_conversion back to zero. Take - care of the multibyteness of the working buffer. + assure setting inhibit_pre_post_conversion back to zero. + Take care of the multibyteness of the working buffer. * coding.c (inhibit_pre_post_conversion): New variable. (setup_coding_system): If inhibit_pre_post_conversion is nonzero, @@ -1666,13 +1666,13 @@ * minibuf.c (Fminibuffer_complete_and_exit): Supply value for new ESCAPE_FROM_EDGE parameter to Ffield_beginning. - * editfns.c (text_property_eq, text_property_stickiness): Don't - use initializers for auto variables of type Lisp_Object. + * editfns.c (text_property_eq, text_property_stickiness): + Don't use initializers for auto variables of type Lisp_Object. (find_field): Likewise. Use braces around nested ifs. (Fline_end_position): Store the raw eol in a variable, so that the final expression doesn't look so ugly. (Fconstrain_to_field): Doc fix. - (preceding_pos): Renamed from `preceeding_pos'. + (preceding_pos): Rename from `preceeding_pos'. (text_property_stickiness, find_field): Call preceding_pos, not preceeding_pos. @@ -1696,8 +1696,8 @@ * syntax.c (Fforward_word): Supply new ESCAPE_FROM_EDGE parameter to Fconstrain_to_field. - * minibuf.c (Fminibuffer_complete_word): Use - Ffield_beginning to find the prompt end. + * minibuf.c (Fminibuffer_complete_word): + Use Ffield_beginning to find the prompt end. 1999-10-17 Miles Bader <miles@gnu.org> @@ -1746,8 +1746,8 @@ 1999-10-16 Gerd Moellmann <gerd@gnu.org> * window.c (enum save_restore_action): New. - (save_restore_orig_size): Change parameter list. Add - functionality to check for valid orig_top and orig_height members + (save_restore_orig_size): Change parameter list. + Add functionality to check for valid orig_top and orig_height members in a window tree. (grow_mini_window): Call save_restore_orig_size with new parameter list. @@ -1848,8 +1848,8 @@ (Finternal_set_lisp_face_attribute): Ditto. (Fpixmap_spec_p): Rewritten. Extend doc string. - * xmenu.c (set_frame_menubar, xmenu_show): Call - x_set_menu_resources_from_menu_face. + * xmenu.c (set_frame_menubar, xmenu_show): + Call x_set_menu_resources_from_menu_face. * dispextern.h (enum face_id): Add MENU_FACE_ID. (toplevel): Include X11/Intrinsic.h. @@ -1869,7 +1869,7 @@ 1999-09-29 Gerd Moellmann <gerd@gnu.org> - * editfns.c (Fpropertize): Renamed from Fproperties. + * editfns.c (Fpropertize): Rename from Fproperties. 1999-09-29 Gerd Moellmann <gerd@gnu.org> @@ -1897,8 +1897,8 @@ * textprop.c (next_single_char_property_change): New. - * xdisp.c (display_prop_end, invisible_text_between_p): Use - next_single_char_property_change. + * xdisp.c (display_prop_end, invisible_text_between_p): + Use next_single_char_property_change. 1999-09-25 Gerd Moellmann <gerd@gnu.org> @@ -1928,7 +1928,7 @@ * xfaces.c (add_to_log): Move to xdisp.c. - * xdisp.c (add_to_log): Moved from xfaces.c. Remove frame + * xdisp.c (add_to_log): Move from xfaces.c. Remove frame parameter. 1999-09-23 Gerd Moellmann <gerd@gnu.org> @@ -1945,10 +1945,10 @@ (grow_mini_window, shrink_mini_window): New. (make_window, replace_window): Initialize orig_top and orig_height. - (enlarge_window): Renamed from change_window_height. Make it + (enlarge_window): Rename from change_window_height. Make it static. - (Fdisplay_buffer, Fenlage_window, Fshrink_window): Call - enlarge_window instead of change_window_height. + (Fdisplay_buffer, Fenlage_window, Fshrink_window): + Call enlarge_window instead of change_window_height. * window.h (struct window): New members orig_top, orig_height. (toplevel): Add prototypes for grow_mini_window and @@ -2003,8 +2003,8 @@ * xdisp.c (compute_window_start_on_continuation_line): Handle case that window start is out of range. - (handle_display_prop, handle_single_display_prop): Replace - marginal area specifications like `left-margin' with `(margin + (handle_display_prop, handle_single_display_prop): + Replace marginal area specifications like `left-margin' with `(margin left-margin)'. (Qmargin): New. (syms_of_xdisp): Initialize Qmargin. @@ -2020,7 +2020,7 @@ (Fopen_network_stream, create_process): Add parentheses to conditional expressions. (create_process): Put declaration of sigchld in #if 0. - (Fopen_network_stream): Removed unused variables. + (Fopen_network_stream): Remove unused variables. (Fopen_network_stream, wait_reading_process_input) (wait_reading_process_input, send_process, send_process): Ditto. (toplevel): Add prototypes for set_waiting_for_input and @@ -2057,7 +2057,7 @@ * buffer.h: Add prototype for r_re_alloc. - * insdel.c (copy_text): Removed unused variables. + * insdel.c (copy_text): Remove unused variables. (count_combining_after, count_combining_after, insert_1_both) (insert_from_string_1, insert_from_buffer_1, check_markers): Ditto. (adjust_after_replace, replace_range): Add parentheses to logical @@ -2177,8 +2177,8 @@ * xdisp.c (resize_mini_window): Don't report changed window height if it actually hasn't changed. - * widget.c (set_frame_size, EmacsFrameSetCharSize): Remove - unused variables. + * widget.c (set_frame_size, EmacsFrameSetCharSize): + Remove unused variables. (mark_shell_size_user_specified): Put in #if 0 because not used. (create_frame_gcs): Put in #if 0 because currently unused. (first_frame_p): Ditto. @@ -2188,7 +2188,7 @@ (free_frame_menubar, xmenu_show, xdialog_show): Remove unused variables. - * print.c (PRINTFULLP): Removed because it is no longer used and + * print.c (PRINTFULLP): Remove because it is no longer used and is misleading. (Ferror_message_string): Remove unused variables. (print_object): Cast argument of sprintf to long for `%ld' @@ -2297,7 +2297,7 @@ * xterm.c (XTcursor_to): Change for Lisp_Object selected_frame. (x_clear_frame, XTring_bell, XTmouse_position, XTread_socket): Ditto. - (XRINGBELL): Removed. + (XRINGBELL): Remove. 1999-09-13 Dave Love <fx@gnu.org> @@ -2307,7 +2307,7 @@ 1999-09-13 Gerd Moellmann <gerd@delysid.gnu.org> - * xfns.c (QCfile): Moved to xdisp.c. + * xfns.c (QCfile): Move to xdisp.c. (syms_of_xfns): Don't initialize QCfile. (check_x_frame): Change for Lisp_Object selected_frame. (check_x_display_info, x_get_resource_string): Ditto. @@ -2317,7 +2317,7 @@ * minibuf.c (choose_minibuf_frame): Don't try to set the mini-buffer window's buffer, if the buffer is invalid. - * xfns.c (QCfile): Moved to xdisp.c. + * xfns.c (QCfile): Move to xdisp.c. (syms_of_xfns): Don't initialize QCfile. * xdisp.c (QCfile): Move here from xfns.c. @@ -2401,7 +2401,7 @@ * xterm.c (XTcursor_to): Change for Lisp_Object selected_frame. (x_clear_frame, XTring_bell, XTmouse_position, XTread_socket): Ditto. - (XRINGBELL): Removed. + (XRINGBELL): Remove. * window.c (Fminibuffer_window): Change for Lisp_Object selected_frame. @@ -2456,8 +2456,8 @@ * keyboard.c (command_loop_1): Resize mini-window to the exact size of a message displayed, if any. - * xdisp.c (resize_mini_window): Add parameter exact_p. Resize - to exact size if exact_p is non-zero. + * xdisp.c (resize_mini_window): Add parameter exact_p. + Resize to exact size if exact_p is non-zero. (display_echo_area_1): Call resize_mini_window with new parameter. (redisplay_internal): Ditto. @@ -2498,8 +2498,8 @@ (Fkill_buffer): Ditto. (Ferase_buffer): Ditto. - * buffer.h (prompt_end_charpos): Replaces - minibuffer_prompt_length. + * buffer.h (prompt_end_charpos): + Replaces minibuffer_prompt_length. * minibuf.c (read_minibuf): Return mini-buffer contents without the prompt. @@ -2582,8 +2582,8 @@ (x_load_font, x_find_ccl_program, x_term_init, x_delete_display): Likewise. - * alloc.c (make_float, make_pure_float, Fpurecopy): Use - XFLOAT_DATA. + * alloc.c (make_float, make_pure_float, Fpurecopy): + Use XFLOAT_DATA. * bytecode.c (Fbyte_code): Likewise. * floatfns.c (extract_float, Fexpt, Fabs, rounding_driver) (fmod_float): Likewise. @@ -2614,7 +2614,7 @@ 1999-09-10 Keisuke Nishida <kxn30@po.cwru.edu> * print.c: Support print-circle and related features. - (Vprint_gensym_alist): Removed. + (Vprint_gensym_alist): Remove. (Vprint_circle, Vprint_continuous_numbering, print_number_index) (Vprint_number_table): New variables. (PRINT_NUMBER_OBJECT, PRINT_NUMBER_STATUS): New macros. @@ -2703,8 +2703,8 @@ 1999-09-07 Gerd Moellmann <gerd@gnu.org> - * xfns.c (x_set_foreground_color): Call - update_face_from_frame_parameter. + * xfns.c (x_set_foreground_color): + Call update_face_from_frame_parameter. (x_set_background_color): Ditto. (x_set_mouse_color): Ditto. (x_set_cursor_color): Ditto. @@ -2926,7 +2926,7 @@ (Fset_window_start): Ditto. * xdisp.c (Vresize_mini_config, resize_mini_frame) - (resize_mini_initial_height): Removed. + (resize_mini_initial_height): Remove. (syms_of_xdisp): Remove references to these variables. (resize_mini_window): Don't save window configuration, freeze window starts instead. Enlarge window until displaying an empty @@ -2952,16 +2952,16 @@ * xterm.c (x_scroll_bar_create): Don't clear under scroll bar here. - (XTset_vertical_scroll_bar): Clarify position computations. Clear - under newly created scroll bar. Put toolkit scroll bars in the + (XTset_vertical_scroll_bar): Clarify position computations. + Clear under newly created scroll bar. Put toolkit scroll bars in the middle of the area reserved for the scroll bar. 1999-09-03 Kenichi Handa <handa@etl.go.jp> The following changes are for the new handling of multibyte sequence. Now, except for a composite character, no multibyte - character in string/buffer has trailing garbage bytes. For - instance, the length of string "\201\300\300" is now 2, the first + character in string/buffer has trailing garbage bytes. + For instance, the length of string "\201\300\300" is now 2, the first character is Latin-1 A-grave, the second is raw \300. * charset.h (MAKE_NON_ASCII_CHAR): Handle the case that C1 or C2 @@ -2972,7 +2972,7 @@ (PARSE_CHARACTER_SEQ): New macro. (PARSE_MULTIBYTE_SEQ): New macro. (CHAR_PRINTABLE_P): New macro. - (STRING_CHAR): Adjusted for the change of string_to_non_ascii_char. + (STRING_CHAR): Adjust for the change of string_to_non_ascii_char. (STRING_CHAR_AND_LENGTH): Likewise. (STRING_CHAR_AND_CHAR_LENGTH): Define it as STRING_CHAR_AND_LENGTH. (INC_POS): Use the macro PARSE_MULTIBYTE_SEQ. @@ -3016,8 +3016,8 @@ * insdel.c (count_combining_composition): New function. (count_combining_before): Adjust the way to check byte-combining - possibility for the new handling of multibyte sequence. Call - count_combining_composition for a composite character. + possibility for the new handling of multibyte sequence. + Call count_combining_composition for a composite character. (count_combining_after): Likewise. * print.c (print_string): Use the macro STRING_CHAR_AND_LENGTH. @@ -3093,8 +3093,8 @@ (window_box_left): Use FRAME_LEFT_FLAGS_AREA_WIDTH instead of FRAME_FLAGS_AREA_WIDTH. - * window.c (coordinates_in_window): Use - FRAME_LEFT_FLAGS_AREA_WIDTH instead of FRAME_FLAGS_AREA_WIDTH. + * window.c (coordinates_in_window): + Use FRAME_LEFT_FLAGS_AREA_WIDTH instead of FRAME_FLAGS_AREA_WIDTH. (window_internal_width): Subtract FRAME_FLAGS_AREA_WIDTH once instead of twice. @@ -3105,14 +3105,14 @@ * dispnew.c (mode_line_string): Add FRAME_LEFT_FLAGS_AREA_WIDTH instead of FRAME_FLAGS_AREA_WIDTH. - * dispextern.h (WINDOW_DISPLAY_PIXEL_WIDTH): Subtract - FRAME_FLAGS_AREA_COLS once. - (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X): Add - FRAME_LEFT_FLAGS_AREA_WIDTH instead of FRAME_FLAGS_AREA_WIDTH. + * dispextern.h (WINDOW_DISPLAY_PIXEL_WIDTH): + Subtract FRAME_FLAGS_AREA_COLS once. + (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X): + Add FRAME_LEFT_FLAGS_AREA_WIDTH instead of FRAME_FLAGS_AREA_WIDTH. 1999-08-30 Gerd Moellmann <gerd@gnu.org> - * s/freebsd.h (C_SWITCH_SYSTEM): Added to let configure find headers + * s/freebsd.h (C_SWITCH_SYSTEM): Add to let configure find headers in /usr/X11R6/include which are checked for with AC_CHECK_HEADER. 1999-08-30 Gerd Moellmann <gerd@gnu.org> @@ -3139,8 +3139,8 @@ 1999-08-28 Ken Raeburn <raeburn@gnu.org> - * lisp.h (struct Lisp_Cons, XCAR, XCDR, struct Lisp_Float): Change - names of structure elements if HIDE_LISP_IMPLEMENTATION is + * lisp.h (struct Lisp_Cons, XCAR, XCDR, struct Lisp_Float): + Change names of structure elements if HIDE_LISP_IMPLEMENTATION is defined, to help detect code that uses knowledge of the Lisp internals that it shouldn't have. (XFLOAT_DATA): New macro. @@ -3226,8 +3226,8 @@ 1999-08-22 Gerd Moellmann <gerd@gnu.org> - * xdisp.c (unwind_with_echo_area_buffer): Use - set_buffer_internal_1 instead of set_buffer_internal. + * xdisp.c (unwind_with_echo_area_buffer): + Use set_buffer_internal_1 instead of set_buffer_internal. (with_echo_area_buffer): Ditto. * buffer.c (set_buffer_internal): Set windows_or_buffers_changed @@ -3255,8 +3255,8 @@ (mark_window_display_accurate, redisplay_internal): Set current matrix' buffer, begv, zv. - * window.c (Fset_window_hscroll): Set - prevent_redisplay_optimizations_p instead of clip_changed. + * window.c (Fset_window_hscroll): + Set prevent_redisplay_optimizations_p instead of clip_changed. (Fset_window_hscroll): Ditto. (temp_output_buffer_show): Ditto. (Fset_window_vscroll): Ditto. @@ -3273,7 +3273,7 @@ unchanged_modified, overlay_unchanged_modified. * window.h (beg_unchanged, end_unchanged, unchanged_modified) - (overlay_unchanged_modified): Removed. + (overlay_unchanged_modified): Remove. (with_echo_area_unwind_data): Don't save beg/end_unchanged. (unwind_with_echo_area_buffer): Don't restore them. (debug_beg_unchanged, debug_end_unchanged) [GLYPH_DEBUG]: Removed. @@ -3310,8 +3310,8 @@ * lisp.h: Add prototype for copy_hash_table and Fcopy_hash_table. - * fns.c (Qkey, Qvalue): Renamed from Qkey_weak, and Qvalue_weak. - (Qkey_value_weak): Removed. + * fns.c (Qkey, Qvalue): Rename from Qkey_weak, and Qvalue_weak. + (Qkey_value_weak): Remove. (make_hash_table): Use nil, `key', `value', t for weakness. (Fmake_hash_table): Ditto. (copy_hash_table): New. @@ -3336,7 +3336,7 @@ * fns.c (hash_lookup): Test with EQ before calling key comparison function. (hash_remove): Ditto. - (cmpfn_eq): Removed. + (cmpfn_eq): Remove. (cmpfn_eql): Don't test with EQ. (cmpfn_equal): Ditto. (make_hash_table): Set comparison function for `eq' to null. @@ -3344,7 +3344,7 @@ * buffer.c, cmds.c, editfns.c, indent.c, insdel.c, buffer.h: Remove conditional compilation on NO_PROMPT_IN_BUFFER. - * dispextern.h (NO_PROMPT_IN_BUFFER): Removed. + * dispextern.h (NO_PROMPT_IN_BUFFER): Remove. * window.c, widget.c, process.c, keyboard.c, frame.c, xdisp.c, xterm.c: Call change_frame_size and do_pending_window_change with @@ -3369,8 +3369,8 @@ NO_PROMPT_IN_BUFFER. * minibuf.c (Fminibuffer_prompt_end): New. - (syms_of_minibuf): Defsubr it. Remove - minibuffer-prompt-in-buffer. + (syms_of_minibuf): Defsubr it. + Remove minibuffer-prompt-in-buffer. (Fminibuffer_prompt_width): Return 0 if not in mini-buffer. Extend documentation. @@ -3381,7 +3381,7 @@ 1999-08-21 Gerd Moellmann <gerd@gnu.org> - * xdisp.c (minibuffer_scroll_overlap): Removed because not used + * xdisp.c (minibuffer_scroll_overlap): Remove because not used anywhere. (unwind_redisplay): Return nil. (clear_garbaged_frames): New. @@ -3400,7 +3400,7 @@ * xdisp.c (echo_area_glyphs, echo_area_message) (echo_area_glyphs_length, previous_echo_glyphs) (previous_echo_area_message, previous_echo_area_glyphs_length): - Removed. + Remove. (Vmessage_stack, echo_area_buffer, echo_buffer) (display_last_displayed_message_p, Vwith_echo_area_save_vector): New. (message2_nolog): Use set_message and clear_message. @@ -3426,7 +3426,7 @@ Remove initialization of removed variables. (init_xdisp): Remove references to removed variables. - * dispnew.c (adjust_frame_message_buffer): Removed references + * dispnew.c (adjust_frame_message_buffer): Remove references to echo_area_glyphs and previous_echo_glyphs. (direct_output_for_insert): Check for mini-window displaying echo area message differently. @@ -3440,7 +3440,7 @@ longer used in that way. (PRINTDECLARE): Add multibyte. (PRINTPREPARE, PRINTFINISH): Handle printcharfun t differently. - (printbufidx): Removed. + (printbufidx): Remove. (printchar, strout): Rewritten. * keyboard.c (ok_to_echo_at_next_pause): Make it a pointer to @@ -3493,8 +3493,8 @@ 1999-08-19 Gerd Moellmann <gerd@gnu.org> - * xterm.c (XTset_vertical_scroll_bar): Fix previous change. Clear - under scroll bar with width FRAME_SCROLL_BAR_COLS. + * xterm.c (XTset_vertical_scroll_bar): Fix previous change. + Clear under scroll bar with width FRAME_SCROLL_BAR_COLS. 1999-08-18 Dave Love <fx@gnu.org> @@ -3511,8 +3511,8 @@ * xfns.c (x_window) [USE_X_TOOLKIT]: Remove test for FRAME_X_WINDOW (f) being null at the of the function. If widgets - cannot be created we will already have crashed earlier. Call - lw_set_main_areas with a null menu-bar widget, so that we have + cannot be created we will already have crashed earlier. + Call lw_set_main_areas with a null menu-bar widget, so that we have a reasonable default. (Fx_create_frame): Rearranged so that Lisp errors during frame initialization cause less damage. Initialize menu bar widget @@ -3526,8 +3526,8 @@ 1999-08-17 Gerd Moellmann <gerd@gnu.org> * window.c (Fcoordinates_in_window_p): Return `left-bitmap-area' - and `right-bitmap-area' if position is in the bitmap areas. This - avoids an error when clicking on the bitmap areas. Instead, they + and `right-bitmap-area' if position is in the bitmap areas. + This avoids an error when clicking on the bitmap areas. Instead, they are currently treated like clicks inside the window. (coordinates_in_window): Return 5 and 6 for bitmap areas. (Qleft_bitmap_area, Qright_bitmap_area): New. @@ -3553,14 +3553,14 @@ * dispextern.h (struct it): Remove member show_trailing_whitespace_p. - * dispnew.c (direct_output_for_insert): Use - Vshow_trailing_whitespace instead of former iterator member + * dispnew.c (direct_output_for_insert): + Use Vshow_trailing_whitespace instead of former iterator member show_trailing_whitespace_p. (direct_output_forward_char): Don't do it if highlighting trailing whitespace. - * xdisp.c (Qshow_trailing_whitespace): Removed. - (Vshow_trailing_whitespace): Added. + * xdisp.c (Qshow_trailing_whitespace): Remove. + (Vshow_trailing_whitespace): Add. (init_iterator): Remove initialization code for show_trailing_whitespace_p. (redisplay_internal): Don't try cursor movement in this_line @@ -3578,7 +3578,7 @@ * window.c (Fpos_visible_in_window_p): Rewritten. - * xfaces.c (add_to_log): Renamed from display_message. + * xfaces.c (add_to_log): Rename from display_message. Don't display messages in echo area. * xterm.c (x_draw_glyph_string_box): Use the background width @@ -3650,7 +3650,7 @@ 1999-08-13 Gerd Moellmann <gerd@gnu.org> - * window.c (MINSIZE): Removed. + * window.c (MINSIZE): Remove. (window_min_size): New. (set_window_height): Use window_min_size. (change_window_height): Ditto. @@ -3819,8 +3819,8 @@ * dispextern.h (MATRIX_ROW_OVERLAPPING_P): New. - * dispextern.h (struct redisplay_interface): Add - fix_overlapping_area. + * dispextern.h (struct redisplay_interface): + Add fix_overlapping_area. * xterm.c (x_append_glyph): Set glyph flag overlaps_vertically_p. @@ -3869,7 +3869,7 @@ 1999-08-03 Tom Breton <tob@world.std.com> - * lread.c (read1): Added circular reading code to #N=. + * lread.c (read1): Add circular reading code to #N=. (SUBSTITUTE): New macro. (seen_list): New variable. (substitute_object_in_subtree): New function. @@ -4068,7 +4068,7 @@ * ccl.c (ccl_driver) <CCL_Call>: Now CCL program ID to call may be stored in the following CCL code. Adjusted for the change of Vccl_program_table. - (resolve_symbol_ccl_program): Adjusted for the new style of + (resolve_symbol_ccl_program): Adjust for the new style of embedded symbols (SYMBOL . PROP) in CCL compiled code. Return Qt is resolving failed. (ccl_get_compiled_code): New function. @@ -4078,7 +4078,7 @@ (Fccl_execute): Get compiled CCL code by just calling setup_ccl_program. (Fccl_execute_on_string): Likewise. - (Fregister_ccl_program): Adjusted for the change of + (Fregister_ccl_program): Adjust for the change of Vccl_program_table. * coding.c (setup_coding_system): Get compiled CCL code by just @@ -4125,7 +4125,7 @@ * xrdb.c (x_load_resources): Set double-click time defaults for Motif list boxes from double-click-time. - * fns.c (Vhash_table_tests): Removed. + * fns.c (Vhash_table_tests): Remove. (Qhash_table_test): New. (syms_of_fns): Initialize Qhash_table_test. (Fmake_hash_table): Look up user-defined tests in symbol prop @@ -4152,7 +4152,7 @@ 1999-07-16 Gerd Moellmann <gerd@gnu.org> - * frame.h (FRAME_WINDOW_REDISPLAY_P): Removed. Use FRAME_WINDOW_P + * frame.h (FRAME_WINDOW_REDISPLAY_P): Remove. Use FRAME_WINDOW_P instead. * fns.c (cmpfn_eq): Add hash code parameters. @@ -4162,7 +4162,7 @@ 1999-07-15 Gerd Moellmann <gerd@gnu.org> - * lisp.h (DEFAULT_REHASH_THRESHOLD): Changed to 0.8. + * lisp.h (DEFAULT_REHASH_THRESHOLD): Change to 0.8. * fns.c (maybe_resize_hash_table): Correct computation of index vector size. @@ -4175,19 +4175,19 @@ (survives_gc_p): Make it externally visible. (mark_object): Ditto. - * fns.c (remove_hash_entry): Removed. + * fns.c (remove_hash_entry): Remove. (sweep_weak_hash_tables): New. * print.c (print): Print more information about hash tables. - * xfns.c (image_spec_hash): Removed. + * xfns.c (image_spec_hash): Remove. (lookup_image): Use sxhash instead of image_spec_hash. - (image_spec_equal_p): Removed. + (image_spec_equal_p): Remove. (lookup_image): Use Fequal instead of image_spec_equal_p. 1999-07-14 Gerd Moellmann <gerd@gnu.org> - * lisp.h (P_): Moved to top of file. + * lisp.h (P_): Move to top of file. * fns.c (make_hash_table): Set new members. @@ -4197,8 +4197,8 @@ * lisp.h (struct Lisp_Hash_Table): Add user_cmp_function, user_hash_function, cmpfn, and hashfn. - * fns.c (build_hash): Removed. - (hash_test): Removed. + * fns.c (build_hash): Remove. + (hash_test): Remove. (cmpfn_eq, cmpfn_eql, cmpfn_equal, cmpfn_user_defined): New. (hashfn_eq, hashfn_eql, hashfn_equal, hashfn_user_defined): New. @@ -4261,7 +4261,7 @@ properties. (handle_single_display_prop): Handle some display property forms for terminal frames. - (Qimage): Moved here from xfns.c. + (Qimage): Move here from xfns.c. * dispextern.h (struct it): New field string_from_display_prop_p. @@ -4331,8 +4331,8 @@ 1999-07-05 Gerd Moellmann <gerd@gnu.org> - * term.c (TS_cursor_visible): Renamed from TS_visual_mode. - (TS_cursor_normal): Renamed from TS_end_visual_mode. + * term.c (TS_cursor_visible): Rename from TS_visual_mode. + (TS_cursor_normal): Rename from TS_end_visual_mode. (TS_cursor_invisible): New. (term_init): Initialize TS_cursor_invisible. (tty_hide_cursor): New. @@ -4364,7 +4364,7 @@ 1999-07-02 Gerd Moellmann <gerd@gnu.org> - * dispextern.h (HSCROLL_WINDOWS): Removed. + * dispextern.h (HSCROLL_WINDOWS): Remove. * xdisp.c (mark_window_display_accurate): Don't set w->region_showing. @@ -4378,12 +4378,12 @@ up when cursor is partially visible, make it fully visible. (mark_window_display_accurate): Some cleanup. Record window's last cursor information. - (debug_method_add): Improved. + (debug_method_add): Improve. (redisplay_internal): Record last cursor info only if not consider_all_windows_p. * dispnew.c (update_window): Update top line after scrolling. - (blank_row): Renamed from make_empty_enabled_row. + (blank_row): Rename from make_empty_enabled_row. (increment_glyph_row_buffer_positions): Increment positions in buffers, only. @@ -4406,7 +4406,7 @@ * dispextern.h (struct glyph_matrix): Add member window_vscroll. * xdisp.c (debug_method_add): New. - (debug_redisplay_method): Removed. + (debug_redisplay_method): Remove. (try_window_reusing_current_matrix): Handle case where old window start is the same as new window start. @@ -4550,8 +4550,8 @@ (CURRENT_TOP_LINE_HEIGHT): New. (DESIRED_TOP_LINE_HEIGHT): New. (WINDOW_DISPLAY_TOP_LINE_HEIGHT): New. - (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE): Replaces - WINDOW_DISPLAY_TEXT_AREA_PIXEL_HEIGHT. + (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE): + Replaces WINDOW_DISPLAY_TEXT_AREA_PIXEL_HEIGHT. (WINDOW_DISPLAY_TEXT_HEIGHT): New. * xterm.c (x_after_update_window_line): Don't draw bitmaps for top @@ -4562,8 +4562,8 @@ x_frame_mode_line_height. (x_get_glyph_string_clip_rect): Take top line into account. (x_clear_end_of_line): Ditto. - (note_mode_line_highlight): Add parameter mode_line_p. Handle - top lines. + (note_mode_line_highlight): Add parameter mode_line_p. + Handle top lines. (note_mouse_highlight): Call note_mode_line_highlight for top lines. (x_erase_phys_cursor): Take top line into account. @@ -4578,12 +4578,12 @@ * xterm.c (x_frame_mode_line_height): Add parameter face_id. - * term.c (estimate_mode_line_height): Renamed from + * term.c (estimate_mode_line_height): Rename from frame_mode_line_height. Add parameter face_id. - (estimate_mode_line_height_hook): Renamed from + (estimate_mode_line_height_hook): Rename from frame_mode_line_height_hook. - (produce_special_glyphs_hook): Removed. - (produce_glyphs_hook): Removed. + (produce_special_glyphs_hook): Remove. + (produce_glyphs_hook): Remove. 1999-06-23 Gerd Moellmann <gerd@gnu.org> @@ -4604,7 +4604,7 @@ * buffer.h: Add top_line_format. - * xdisp.c (overlay_arrow_changed_p): Removed because not used. + * xdisp.c (overlay_arrow_changed_p): Remove because not used. 1999-06-17 Dave Love <fx@gnu.org> @@ -4629,8 +4629,8 @@ * Makefile.in (LIBGIF): Use libungif. - * xdisp.c (compute_window_start_on_continuation_line): Don't - do it if line start is too far away from window start. + * xdisp.c (compute_window_start_on_continuation_line): + Don't do it if line start is too far away from window start. 1999-06-14 Gerd Moellmann <gerd@gnu.org> @@ -4714,8 +4714,8 @@ * xfaces.c (SCALABLE_FONTS): Define this to enable scalable font support. (Vscalable_fonts_allowed) [SCALABLE_FONTS]: New. - (x_face_list_fonts): Add parameter scalable_fonts_p. Handle - scalable fonts depending on the setting of SCALABLE_FONTS. + (x_face_list_fonts): Add parameter scalable_fonts_p. + Handle scalable fonts depending on the setting of SCALABLE_FONTS. (first_font_matching): List more than one font to find the first non-scalable matching font. (sorted_font_list): Let x_face_list_fonts return scalable fonts @@ -4730,8 +4730,8 @@ 1999-05-26 Gerd Moellmann <gerd@gnu.org> - * xfns.c (png_load): Let PNG lib handle gamma. Construct - mask only if image contains simple transparency information. + * xfns.c (png_load): Let PNG lib handle gamma. + Construct mask only if image contains simple transparency information. Otherwise, combine image with frame background color. * configure.in (--with-png, HAVE_PNG): New. @@ -4829,7 +4829,7 @@ 1999-03-29 Gerd Moellmann <gerd@gnu.org> - * xfaces.c (Qraised, Qsunken, QCshadow): Removed. + * xfaces.c (Qraised, Qsunken, QCshadow): Remove. (QCline_width, QCstyle, Qpressed_button, Qreleased_button): New. Use these symbols for the box face attribute instead of the removed ones. @@ -4852,7 +4852,7 @@ * xfaces.c (x_face_list_fonts): New parameter try_alternatives_p. (first_font_matching): New. (set_lface_from_font_name): Use it if font name is a pattern. - (font_field_wildcard_p): Removed. + (font_field_wildcard_p): Remove. * dispnew.c (shift_glyph_matrix): Add `window' parameter. Recompute visible height of rows. @@ -4881,12 +4881,12 @@ (update_window_line): Call after_update_window_line_hook if visible row height has changed. - * dispextern.h (MATRIX_ROW_VISIBLE_HEIGHT): Removed. + * dispextern.h (MATRIX_ROW_VISIBLE_HEIGHT): Remove. (struct glyph_row): New member visible_height. * xfaces.c (font_field_wildcard_p): New. - (set_lface_from_font_name): Remove parameter force_p. Accept - font names containing wildcards. + (set_lface_from_font_name): Remove parameter force_p. + Accept font names containing wildcards. 1999-03-04 Gerd Moellmann <gerd@gnu.org> @@ -4906,7 +4906,7 @@ * dispextern.h (struct face): Add use_box_color_for_shadows_p. * xterm.c (x_draw_box_rect): New. - (x_draw_glyph_string_box): Renamed from + (x_draw_glyph_string_box): Rename from x_draw_glyph_string_relief. Call x_draw_box_rect. * xfns.c (QCrelief): New. @@ -4914,20 +4914,20 @@ * dispextern.h (struct glyph): Rename left_shadow_p to left_box_line_p, right_shadow_p to right_box_line_p. - (MAX_RELIEF_THICKNESS): Removed. + (MAX_RELIEF_THICKNESS): Remove. (struct it): Rename members having `relief' in their names to contain `box' instead. * xfaces.c (realize_x_face): Handle new box attribute values. - (QCrelief, Qbox): Removed. + (QCrelief, Qbox): Remove. (QCshadow, QCcolor, Qraised, Qsunken): New. (syms_of_xfaces): Initialize new symbols. 1999-03-02 Gerd Moellmann <gerd@gnu.org> - * dispextern.h (LFACE_RELIEF_INDEX): Removed. + * dispextern.h (LFACE_RELIEF_INDEX): Remove. - * xfaces.c (LFACE_RELIEF): Removed. + * xfaces.c (LFACE_RELIEF): Remove. (merge_face_vector_with_property): Remove handling of `:relief'. (Finternal_set_lisp_face_attribute): Ditto. (Finternal_set_lisp_face_attribute_from_resource): Ditto. @@ -4946,7 +4946,7 @@ * xterm.c (x_draw_glyph_string): Draw underline, overline, strike-through, and boxes. - (x_draw_glyph_string_underline): Removed. + (x_draw_glyph_string_underline): Remove. * xfaces.c (QCoverline, QCstrike_through, QCbox): New. (Qoverline, Qstrike_through, Qbox): New. @@ -5019,7 +5019,7 @@ 1999-01-03 Masatake Yamato <masata-y@is.aist-nara.ac.jp> * dispextern.h (UNDERLINE_COLOR): Defined. - (struct face): Added two new members. + (struct face): Add two new members. underline_color, underline_defaulted_p. * xfaces.c (merge_face_vector_with_property): @@ -5032,7 +5032,7 @@ 1999-02-12 Gerd Moellmann <gerd@gnu.org> - * xfns.c (Fx_image_header): Removed. + * xfns.c (Fx_image_header): Remove. 1999-02-07 Gerd Moellmann <gerd@gnu.org> @@ -5073,16 +5073,16 @@ * xdisp.c (handle_single_display_prop): New. (handle_display_prop): Call it. - (handle_raise_prop): Removed. - (handle_height_prop): Removed. - (handle_space_width_prop): Removed. + (handle_raise_prop): Remove. + (handle_height_prop): Remove. + (handle_space_width_prop): Remove. (handle_face_prop): Remove handling of raised text. (handle_display_prop): Do it here. * dispextern.h (DISPLAY_PROP_IDX): Replaces GLYPH_PROP_IDX. - (RAISE_PROP_IDX): Removed. - (HEIGHT_PROP_IDX): Removed. - (SPACE_WIDTH_PROP_IDX): Removed. + (RAISE_PROP_IDX): Remove. + (HEIGHT_PROP_IDX): Remove. + (SPACE_WIDTH_PROP_IDX): Remove. * xdisp.c (Qdisplay): Replaces Qglyph. (handle_display_prop): Formerly handle_glyph_prop. @@ -5090,8 +5090,8 @@ 1999-01-11 Gerd Moellmann <gerd@gnu.org> * xdisp.c (reseat_to_string): Set position in display vector to -1. - (handle_stop): Set position in display vector to -1. Don't - check overlay strings when set up to deliver characters from a + (handle_stop): Set position in display vector to -1. + Don't check overlay strings when set up to deliver characters from a display vector. (set_iterator_to_next): At the end of a run of characters from a display vector, check whether the display vector display replaces @@ -5124,7 +5124,7 @@ * buffer.h (struct buffer): indicate_empty_lines renamed from indicate_zv_lines. - * buffer.c (indicate-empty-lines): Renamed from indicate_zv_lines. + * buffer.c (indicate-empty-lines): Rename from indicate_zv_lines. (default-indicate-zv-lines): Likewise. * dispextern.h (struct glyph_row): Rename indicate_zv_line_p @@ -5139,7 +5139,7 @@ and `N-'. * xfns.c (xbm_scan): New. - (xbm_read_hexint): Removed. + (xbm_read_hexint): Remove. (xbm_read_bitmap_file_data): Use xbm_scan. * fileio.c (Finsert_file_contents): Prevent redisplay optimizations. @@ -5155,8 +5155,8 @@ * xfaces.c (face_with_height): New. - * xdisp.c (eval_handler): Renamed from eval_mode_handler. - (eval_form): Renamed from eval_mode_element. + * xdisp.c (eval_handler): Rename from eval_mode_handler. + (eval_form): Rename from eval_mode_element. (handle_face_prop): Use it. (Qheight): Replaces Qsmaller. (handle_height_prop): Replaces handle_smaller_prop. @@ -5183,7 +5183,7 @@ 1998-11-28 Gerd Moellmann <gerd@gnu.org> - * config.in (PROTO): Removed. + * config.in (PROTO): Remove. * xterm.h: Change PROTO to P_. @@ -5225,7 +5225,7 @@ * xterm.c (x_scroll_bar_move): Clear to the left and right of toolkit scroll bars differently. - (x_scroll_bar_move): Removed. + (x_scroll_bar_move): Remove. (XTset_vertical_scroll_bar): Move code from x_scroll_bar_move here. * dispextern.h: Make it compilable --with-x=no. @@ -5256,8 +5256,8 @@ 1998-11-23 Gerd Moellmann <gerd@gnu.org> - * xdisp.c (restore_overlay_strings): Removed. - (restore_dpvec): Removed. + * xdisp.c (restore_overlay_strings): Remove. + (restore_dpvec): Remove. (init_from_display_pos): Inline both functions above. * xfns.c (IMAGE_NON_NEGATIVE_INTEGER_VALUE): New. @@ -5270,7 +5270,7 @@ (gif_format): Ditto. (gs_format): Ditto. - * xdisp.c (set_window_cursor): Removed. + * xdisp.c (set_window_cursor): Remove. (redisplay_internal): Case cursor motion in cursor line of selected window; use set_cursor_from_row. @@ -5641,7 +5641,7 @@ * xdisp.c (redisplay_window): Always resize toolbar window if auto_resize_toolbar_p is non-zero. - (auto_resize_toolbar_p): Renamed from auto_resize_toolbar. + (auto_resize_toolbar_p): Rename from auto_resize_toolbar. (window_box): New. (window_box_height): New. (window_box_width): New. @@ -5735,12 +5735,12 @@ * xfns.c (x_laplace): New. (x_laplace_read_row): New. (x_laplace_write_row): New. - (lookup_image): Handle common image attributes here. New - attribute `:algorithm'. + (lookup_image): Handle common image attributes here. + New attribute `:algorithm'. * xfaces.c (clear_face_cache): Call clear_image_cache. - * xterm.c (x_inverted_image_mask): Removed. + * xterm.c (x_inverted_image_mask): Remove. (x_draw_image_foreground_1): New. (x_draw_image_glyph_string): Draw images with mask to a temporary pixmap to reduce flickering. @@ -5755,7 +5755,7 @@ * xfns.c (cache_image): Correct call to xrealloc. - * dispnew.c (Fset_toolbar_height): Removed. + * dispnew.c (Fset_toolbar_height): Remove. * xdisp.c (init_xdisp): Use FRAME_TOP_MARGIN instead of FRAME_MENU_BAR_LINES. @@ -5838,8 +5838,8 @@ (clear_image_cache): Additional parameter force_p. (Fclear_image_cache): New. (x_find_image_file): New. - (xbm_load): Handle `:margin' and `:relief'. Use - x_find_image_file. + (xbm_load): Handle `:margin' and `:relief'. + Use x_find_image_file. (xpm_load): Likewise. (pbm_load): Likewise. (jpeg_load): Likewise. @@ -5939,8 +5939,8 @@ * frame.h (struct frame): Add toolbar-related members toolbar_window, desired_toolbar_items, current_toolbar_items, desired_toolbar_string, current_toolbar_string, - n_desired_toolbar_items, n_current_toolbar_items. Add - window_height. + n_desired_toolbar_items, n_current_toolbar_items. + Add window_height. * xterm.c (x_after_update_window_line): Don't draw bitmap areas for pseudo-windows. @@ -6024,17 +6024,17 @@ 1998-09-06 Gerd Moellmann <gerd@gnu.org> - * lisp.h (HAVE_FACES): Removed. + * lisp.h (HAVE_FACES): Remove. - * dispextern.h (HAVE_FACES): Removed. + * dispextern.h (HAVE_FACES): Remove. - * config.in (HAVE_FACES): Removed. + * config.in (HAVE_FACES): Remove. - * dispnew.c (HAVE_FACES): Removed. + * dispnew.c (HAVE_FACES): Remove. - * xdisp.c (HAVE_FACES): Removed. + * xdisp.c (HAVE_FACES): Remove. - * xfaces.c (HAVE_FACES): Removed. + * xfaces.c (HAVE_FACES): Remove. 1998-09-05 Gerd Moellmann <gerd@gnu.org> @@ -6042,8 +6042,8 @@ free realized faces. * xfaces.c (free_all_realized_faces): Make it externally visible. - (Finternal_set_lisp_face_attribute): Increment - windows_or_buffers_changed. + (Finternal_set_lisp_face_attribute): + Increment windows_or_buffers_changed. * dispnew.c (direct_output_for_insert): Give up if face_change_count is non-zero. @@ -6076,9 +6076,9 @@ * term.c (OUTPUT_IF): Make replacement text have statement form. (OUTPUT1_IF): Ditto. - (TS_italic_mode, TS_end_italic_mode): Removed. - (TS_bold_mode): Removed. - (TS_underscore_mode, TS_end_underscore_mode): Removed. + (TS_italic_mode, TS_end_italic_mode): Remove. + (TS_bold_mode): Remove. + (TS_underscore_mode, TS_end_underscore_mode): Remove. (TS_enter_bold_mode, TS_enter_dim_mode, TS_enter_blink_mode): New. (TS_enter_reverse_mode): New. (TS_enter_underline_mode, TS_exit_underline_mode): New. @@ -6187,8 +6187,8 @@ * frame.h (FRAME_WINDOW_WIDTH_ARG): Add bitmap area widths. - * dispnew.c (allocate_matrices_for_window_redisplay): Compute - total pixel width of window differently. + * dispnew.c (allocate_matrices_for_window_redisplay): + Compute total pixel width of window differently. * xdisp.c (init_iterator): Compute width of mode line differently. @@ -6209,7 +6209,7 @@ (update_window_tree): Parameter no_scrolling_p removed. (update_single_window): Ditto. - * xterm.c (x_get_char_font_and_encoding): Renamed to + * xterm.c (x_get_char_font_and_encoding): Rename to x_get_char_face_and_encoding. * dispnew.c (update_text_area): Don't call get_glyph_overhangs @@ -6254,8 +6254,8 @@ * xterm.c (note_mouse_highlight): Set BEGV_BYTE, ZV_BYTE. - * xfaces.c (Vx_unibyte_registry_and_encoding): Removed. Use - face_default_registry instead. + * xfaces.c (Vx_unibyte_registry_and_encoding): Remove. + Use face_default_registry instead. * syntax.c (scan_sexps_forward): Set up syntax table before jumping to initial state label. @@ -6372,13 +6372,13 @@ (struct iterator_stack_entry): Add multibyte_p. * xdisp.c (string_pos): Use string_char_to_byte. - (char_charset): Removed. + (char_charset): Remove. 1998-08-03 Gerd Moellmann <gerd@gnu.org> * xterm.c (x_draw_image_glyph_string_foreground): Draw a rectangle for a block cursor over an image without a mask. - (x_stretch_block_cursor): Added. Non-zero means don't draw + (x_stretch_block_cursor): Add. Non-zero means don't draw a block cursor over a stretch as wide as that stretch. (x_draw_stretch_glyph_string): Use it. (x_draw_hollow_cursor): Ditto. @@ -6389,7 +6389,7 @@ * xdisp.c (char_charset): Return charset of a character, depending on whether or not multi-byte characters are enabled. - * xfaces.c (Fset_face_charset_registry): Removed. + * xfaces.c (Fset_face_charset_registry): Remove. (x_charset_registry): Determine registry from charset plist. 1998-08-02 Gerd Moellmann <gerd@gnu.org> @@ -6401,7 +6401,7 @@ redisplay interface. * keyboard.c (detect_input_pending_run_timers): Likewise. - * dispextern.h (produce_*glyphs_hook): Removed. + * dispextern.h (produce_*glyphs_hook): Remove. * term.c (produce_*glyphs): Ditto. (cursor_to): Remove pixel position parameters. @@ -6457,7 +6457,7 @@ * xterm.c (x_flush): Flush X output buffer. (XTflash): Use it. - * xfaces.c (lface_from_face_name): Renamed from lface_from_symbol. + * xfaces.c (lface_from_face_name): Rename from lface_from_symbol. Allow strings as face names. * xfns.c (forall_images_in_image_cache): Check that frame is @@ -6493,7 +6493,7 @@ (Finternal_lisp_face_attribute_values): Ditto. (syms_of_xfaces): Define the symbol `:reverse-video'. - * xdisp.c (get_glyph_property): Renamed from + * xdisp.c (get_glyph_property): Rename from fill_iterator_from_glyph_property. (next_element_from_buffer): Handle case that no `glyph' property was found correctly. @@ -6501,28 +6501,28 @@ 1998-07-29 Gerd Moellmann <gerd@gnu.org> - * dispnew.c (Fshow_cursor): Renamed from blink_cursor. Take - additional window argument. + * dispnew.c (Fshow_cursor): Rename from blink_cursor. + Take additional window argument. - * xdisp.c (reseat_at_previous_visible_line_start): Renamed from + * xdisp.c (reseat_at_previous_visible_line_start): Rename from set_iterator_to_previous_visible_line_start. (reseat_at_next_visible_line_start): Likewise. - (compute_stop_pos): Renamed from set_iterator_stop_pos. - (face_before_or_after_it_pos): Renamed from get_face_at_it_pos. - (compute_face_in_buffer): Renamed from + (compute_stop_pos): Rename from set_iterator_stop_pos. + (face_before_or_after_it_pos): Rename from get_face_at_it_pos. + (compute_face_in_buffer): Rename from compute_face_at_iterator_position. - (compute_face_in_string): Renamed from + (compute_face_in_string): Rename from compute_face_at_iterator_string_position. - (get_space_width): Renamed from get_iterator_space_width. - (next_overlay_string): Renamed from + (get_space_width): Rename from get_iterator_space_width. + (next_overlay_string): Rename from set_iterator_to_next_overlay_string. - (get_overlay_strings): Renamed from + (get_overlay_strings): Rename from get_overlay_strings_at_iterator_position. - (restore_overlay_strings): Renamed from + (restore_overlay_strings): Rename from setup_overlay_strings_from_glyph_pos. - (restore_dpvec): Renamed from setup_iterator_dpvec_from_glyph_pos. - (init_from_display_pos): Renamed from init_iterator_from_glyph_pos. - (init_to_row_start): Renamed from init_iterator_to_row_start. + (restore_dpvec): Rename from setup_iterator_dpvec_from_glyph_pos. + (init_from_display_pos): Rename from init_iterator_from_glyph_pos. + (init_to_row_start): Rename from init_iterator_to_row_start. (init_to_row_end): Formerly init_iterator_to_next_row_start. * xterm.c: Merge with 20.2.97. @@ -6532,26 +6532,26 @@ simple charpos. * xdisp.c (this_line_start_pos): Use struct text_pos. - (this_line_end_pos): Renamed from .*endpos; use struct text_pos. - (enum move_it_result): Renamed from move_iterator_result. + (this_line_end_pos): Rename from .*endpos; use struct text_pos. + (enum move_it_result): Rename from move_iterator_result. (string_pos_nchars_ahead): Compute text_pos in a string from a known text_pos plus a character delta. (string_pos): Compute text_pos in string from charpos. (c_string_pos): Likewise for a C string. (number_of_chars): Return number of characters in a possibly multi-byte C string. - (check_it): Renamed from check_iterator. Check that charpos and + (check_it): Rename from check_iterator. Check that charpos and bytepos are in sync. - (push_it): Renamed from save_iterator_settings. - (pop_it): Renamed from restore_iterator_settings. - (move_it_.*): Renamed from move_iterator_.*. + (push_it): Rename from save_iterator_settings. + (pop_it): Rename from restore_iterator_settings. + (move_it_.*): Rename from move_iterator_.*. (charset_at_position): Take charpos/bytepos into account. (back_to_previous_line_start): Set iterator to previous line start. (forward_to_next_line_start): Set iterator to next line start. - (back_to_previous_visible_line_start): Renamed from + (back_to_previous_visible_line_start): Rename from move_iterator_previous_visible_line_start. (set_iterator_to_next_visible_line_start): Handle charpos/bytepos. - (get_face_at_it_pos): Renamed from get_face_from_cursor_pos. + (get_face_at_it_pos): Rename from get_face_from_cursor_pos. Handle charpos/bytepos. (compute_face_at_iterator_position): Handle charpos/bytepos. (compute_face_at_iterator_string_position): Likewise. @@ -6593,7 +6593,7 @@ (copy_glyph_row_contents): Ditto. (check_matrix_invariants): Add additional checks for charpos/ bytepos consistency. - (direct_output_for_insert): Changed for charpos/bytepos. + (direct_output_for_insert): Change for charpos/bytepos. (buffer_posn_from_coords): Likewise. Put code dealing with `direction-reversed' in #if 0. @@ -6630,10 +6630,10 @@ (SET_TEXT_POS_FROM_MARKER): Set a text_pos from a marker. (SET_MARKER_FROM_TEXT_POS): Set a marker from a text_pos. (TEXT_POS_EQUAL_P): Compare two text_pos structures for equality. - (struct display_pos): Renamed from glyph_pos. Use struct text_pos + (struct display_pos): Rename from glyph_pos. Use struct text_pos for buffer and string positions. (struct glyph): Use text_pos. - (struct it): Renamed from display_iterator. Use text_pos. + (struct it): Rename from display_iterator. Use text_pos. 1998-07-23 Gerd Moellmann <gerd@gnu.org> @@ -6650,7 +6650,7 @@ * xfns.c (prepare_image_for_display): Don't set loading_failed_p flag of images. - * dispextern.h (struct image): Removed member loading_failed_p. + * dispextern.h (struct image): Remove member loading_failed_p. It's probably better to have the chance to try to load an image again. @@ -6703,28 +6703,28 @@ * xfns.c (tiff_image_p, tiff_load): Support TIFF images via libtiff34. - * configure.in (--with-tiff, HAVE_TIFF): Added. + * configure.in (--with-tiff, HAVE_TIFF): Add. - * config.in (HAVE_TIFF): Added. + * config.in (HAVE_TIFF): Add. - * Makefile.in (LIBTIFF): Added. + * Makefile.in (LIBTIFF): Add. * xfns.c (jpeg_image_p, jpeg_load): Support JPEG images. - * Makefile.in (LIBJPEG): Added. + * Makefile.in (LIBJPEG): Add. * xfns.c (resource_types): Enumerators renamed to RES_TYPE_NUMBER, RES_TYPE_BOOLEAN etc. because of conflict of `boolean' with jpeglib.h. - * configure.in (HAVE_JPEG, --with-jpeg): Added. On systems + * configure.in (HAVE_JPEG, --with-jpeg): Add. On systems where the library is installed in /usr/local/lib, e.g. FreeBSD, configure must be run with `--x-includes=/usr/X11R6/include: /usr/local/include --x-libraries=/usr/X11R6/lib:/usr/local/lib'. 1998-07-18 Gerd Moellmann <gerd@gnu.org> - * config.in (HAVE_JPEG): Added. + * config.in (HAVE_JPEG): Add. * xfns.c (ct_init): Initialize color table used to map RGB colors from images to X pixel colors. @@ -6837,20 +6837,20 @@ (redisplay_window): Case cursor movement. Don't try it if last_cursor.vpos is out of range. - * xdisp.c (set_cursor_from_row): Set this_line_.* variables. This - way, the display optimization for the line containing the cursor + * xdisp.c (set_cursor_from_row): Set this_line_.* variables. + This way, the display optimization for the line containing the cursor is used more frequently, esp. when we have a blinking cursor. (display_line): Don't set this_line_.* variables. - * xterm.c (x_redraw_cursor): Removed. + * xterm.c (x_redraw_cursor): Remove. (x_display_and_set_cursor): Set cursor type depending on cursor_off_p flag of window. - * dispnew.c (redraw_cursor_hook): Removed. + * dispnew.c (redraw_cursor_hook): Remove. (Fblink_cursor): Additional parameter on_p to set the cursor_off_p member of the selected window. - * xfaces.c (Fface_font): Added for compatibility with 20.2. + * xfaces.c (Fface_font): Add for compatibility with 20.2. * xterm.c (x_y_to_hpos_vpos): Return null if not over text. Return glyph area under x/y. @@ -6880,8 +6880,8 @@ 1998-06-29 Gerd Moellmann <gerd@gnu.org> - * xfaces.c (Finternal_make_lisp_face): Increment - lface_id_to_name_size when lface_id_to_name is reallocated. + * xfaces.c (Finternal_make_lisp_face): + Increment lface_id_to_name_size when lface_id_to_name is reallocated. 1998-06-27 Gerd Moellmann <gerd@gnu.org> @@ -6892,12 +6892,12 @@ 1998-05-09 Gerd Moellmann <gerd@gnu.org> - * xdisp.c (set_iterator_to_next_visible_line_start): Don't - do anything if iterator is at ZV because scan_buffer doesn't + * xdisp.c (set_iterator_to_next_visible_line_start): + Don't do anything if iterator is at ZV because scan_buffer doesn't work otherwise. * xterm.c (x_encode_char): Inline it. - (x_get_char_font_and_encoding): Simplified. + (x_get_char_font_and_encoding): Simplify. (x_per_char_metric): Inline it. * xterm.c (x_draw_glyph_string_relief): Use clipping. @@ -6926,15 +6926,15 @@ * xdisp.c (display_line): Compute row height from glyphs in marginal areas. - * xterm.c (x_draw_image_glyph_string_background): Draw - background of an image glyph string. + * xterm.c (x_draw_image_glyph_string_background): + Draw background of an image glyph string. (x_draw_glyph_string_bg_rect): Draw a rectangular region of the background of a glyph string. (x_draw_image_glyph_string_foreground): Draw the foreground of an image glyph string. (x_inverted_image_mask): Return the inverted mask of an image. - * xfns.c (x_draw_image): Removed. + * xfns.c (x_draw_image): Remove. * dispextern.h (struct image_type): Remove drawing function. @@ -6966,8 +6966,8 @@ image drawing function. * xdisp.c (fill_iterator_from_glyph_property): Use position of - first character with `glyph' property as image position. Set - iterator back to that position as long as the image hasn't been + first character with `glyph' property as image position. + Set iterator back to that position as long as the image hasn't been consumed with set_iterator_to_next. (set_cursor_from_row): Accept when glyph with given position is not found in the row. Set cursor x to end of line in that case, @@ -6993,7 +6993,7 @@ * dispextern.h (struct glyph_row): Use unsigned hash value. - * xdisp.c (display_line): Simplified and made faster by setting + * xdisp.c (display_line): Simplify and made faster by setting the cursor with set_cursor_from_row. (set_cursor_from_row): Handle rows of desired matrix. @@ -7001,8 +7001,8 @@ * xdisp.c (set_cursor_from_row): Don't put cursor on glyphs with type != CHAR_GLYPH. - (fill_iterator_from_glyph_property): Return void. Set - method to next_element_from_image. + (fill_iterator_from_glyph_property): Return void. + Set method to next_element_from_image. (next_element_from_image): Dummy function for delivering a single image id. (set_iterator_to_next): Add method next_element_from_image. @@ -7037,7 +7037,7 @@ * xterm.c (x_produce_glyphs): Use ASCII face for spaces of a TAB. - * xdisp.c (fill_iterator_from_glyph_property): Renamed from + * xdisp.c (fill_iterator_from_glyph_property): Rename from setup_iterator_from_glyph_property. Don't do it for terminal frames. @@ -7073,12 +7073,12 @@ * config.in: Add HAVE_XPM. - * xfns.c (xbm_draw): Removed. + * xfns.c (xbm_draw): Remove. (x_draw_image): Default implementation for drawing images. (xbm_keyword_index): Remove XBM_DEPTH. (xbm_format): Remove `:depth'. - (xbm_image_spec_from_file): Removed to reduce consing. - (xbm_load_image_from_file): Added for the same reason. + (xbm_image_spec_from_file): Remove to reduce consing. + (xbm_load_image_from_file): Add for the same reason. * xterm.c (x_fill_image_glyph_string): Don't set ybase of glyph string. @@ -7148,8 +7148,8 @@ * widget.c (widget_store_internal_border): Return void. - * xfns.c (x_destroy_bitmap): Use xfree instead of free. Return - void. + * xfns.c (x_destroy_bitmap): Use xfree instead of free. + Return void. (init_x_parm_symbols): Return void. (x_report_frame_params): Ditto. (x_set_border_pixel): Ditto. @@ -7220,7 +7220,7 @@ * dispnew.c (adjust_frame_glyphs_for_window_redisplay): Use these macros. - * xterm.c (x_font_min_bounds): Moved here from xfaces.c. + * xterm.c (x_font_min_bounds): Move here from xfaces.c. (x_compute_min_char_bounds): Formerly min_char_bounds in xfaces.c. (x_load_font): Use x_compute_min_char_bounds. @@ -7238,7 +7238,7 @@ for characters < 0177 in default face. Prepare face for display before returning it. (x_produce_glyphs): Use it->charset. - (x_get_char_font_and_encoding): Simplified. + (x_get_char_font_and_encoding): Simplify. (x_encode_char): Remove parameter `font'. * xfaces.c (choose_face_font): If registry from charset symbol @@ -7309,8 +7309,8 @@ * dispextern.h (FACE_FOR_CHARSET): Replacement for function lookup_face_for_charset. - * xfaces.c (free_font_names): Renamed from free_split_font_names. - (free_all_realized_faces): Renamed from remove_all_realized_faces. + * xfaces.c (free_font_names): Rename from free_split_font_names. + (free_all_realized_faces): Rename from remove_all_realized_faces. 1998-04-25 Gerd Moellmann <gerd@gnu.org> @@ -7329,8 +7329,8 @@ 1998-04-24 Gerd Moellmann <gerd@gnu.org> - * dispextern.h (struct face): Member - fontset_chosen_for_realization_p removed. + * dispextern.h (struct face): + Member fontset_chosen_for_realization_p removed. * xfaces.c (cache_face): If face->fontset >= 0, add face to the end of the collision list, so that we find more specific faces @@ -7365,8 +7365,8 @@ (xlfd_point_size): Return -1 if resolution or point size of font unknown. - * xfaces.c (free_font): Removed. - (load_face_font_or_fontset): Renamed from load_font. + * xfaces.c (free_font): Remove. + (load_face_font_or_fontset): Rename from load_font. (load_face_font_or_fontset): Use message2 instead of signaling. (load_color): Likewise. (load_pixmap): Likewise. @@ -7408,8 +7408,8 @@ to -1 so that it will compute the right face for the truncation glyphs. - * xfaces.c (realize_face): Set - face->fontset_chosen_for_realization_p. + * xfaces.c (realize_face): + Set face->fontset_chosen_for_realization_p. (lookup_face_for_charset): If fontset wasn't specified originally and new charset != CHARSET_COMPOSITION, get a new face for that charset. @@ -7461,9 +7461,9 @@ (lface_hash): Add weight, slant, swidth and relief to hash value. (lface_equal_p): Make it faster. (lface_from_symbol): Use assq_no_quit. - (Fnote_default_face_changed): Removed. + (Fnote_default_face_changed): Remove. (cmp_font_names): Use strcmp instead of xstricmp. - (face_charset_registries): Removed. + (face_charset_registries): Remove. 1998-04-20 Gerd Moellmann <gerd@gnu.org> @@ -7487,8 +7487,8 @@ * xfaces.c (Finternal_set_lisp_face_attribute): Add :bold and :italic for compatibility. - (Finternal_set_lisp_face_attribute_from_resource): Handle - :bold and :italic. Handle boolean resource values for + (Finternal_set_lisp_face_attribute_from_resource): + Handle :bold and :italic. Handle boolean resource values for :underline and :italic. * xfns.c (display_x_get_resource): Make it externally visible. @@ -7500,7 +7500,7 @@ definitions. (Finternal_lisp_face_equal_p): Additional frame argument. (merge_lisp_face_vector_with_property): Ditto. - (Frealize_basic_faces): Removed. + (Frealize_basic_faces): Remove. (Finternal_get_lisp_face_attribute): Additional frame argument. (Finternal_lisp_face_p): Ditto. (load_color) [MSDOS]: Removed because it isn't clear how @@ -7531,8 +7531,8 @@ * xdisp.c (redisplay_internal, echo_area-display): If realized faces have been cleared, call recompute_basic_faces. - * xfaces.c (recompute_basic_faces): Free realized faces. Reset - face_attributes_changed_p. + * xfaces.c (recompute_basic_faces): Free realized faces. + Reset face_attributes_changed_p. (remove_all_realized_faces): Remove all realized faces on all frames. (Finternal_set_lisp_face_attribute): Call remove_all_realized_faces. @@ -7541,7 +7541,7 @@ changed since the last redisplay, recompute basic faces. (echo_area_display): Ditto. - * xfaces.c (clear_face_gcs): Renamed from clear_realized_face_cache. + * xfaces.c (clear_face_gcs): Rename from clear_realized_face_cache. * xfaces.c (min_char_bounds): If face cache not yet present, don't try to get font dimensions from faces. @@ -7549,11 +7549,11 @@ * xterm.c (x_frame_mode_line_height): If face cache not present set, return default height. - * alloc.c (mark_face_cache): Check for null faces. Correct - index bug. + * alloc.c (mark_face_cache): Check for null faces. + Correct index bug. - * dispextern.h (struct face): Renamed from struct rface. Member - underline renamed underline_p. Make it a bit-field. + * dispextern.h (struct face): Rename from struct rface. + Member underline renamed underline_p. Make it a bit-field. * xfaces.c (init_frame_faces): Allocate face cache. (free_frame_faces): Free face cache. @@ -7562,7 +7562,7 @@ * frame.c (make_frame): Initialze face cache with null. - * xfaces.c (same_size_fonts): Removed. + * xfaces.c (same_size_fonts): Remove. * xterm.c (x_set_glyph_string_gc): Add post-condition s->gc != 0. @@ -7584,56 +7584,56 @@ * xfaces.c (syms_of_xfaces): Correct calls to defsubr. - * xfns.c (Fx_face_fixed_p): Removed. - (Fx_list_fonts): Moved to xfaces.c. + * xfns.c (Fx_face_fixed_p): Remove. + (Fx_list_fonts): Move to xfaces.c. - * xfaces.c (compute_face_at_buffer_pos): Renamed to + * xfaces.c (compute_face_at_buffer_pos): Rename to face_at_buffer_position. Parameter charset removed; always compute face for CHARSET_ASCII. - (face_at_string_position): Renamed from + (face_at_string_position): Rename from compute_face_at_string_pos. Parameter charset removed; always compute for CHARSET_ASCII. (lookup_face_for_charset): Take frame parameter instead of face_cache. (lookup_face): Ditto. - (compute_char_face): Renamed from compute_glyph_face. + (compute_char_face): Rename from compute_glyph_face. * xdisp.c (init_iterator): Initialize charset member. (reseat_iterator_to_string): Ditto. (get_charset_at_buffer_position): Determine charset at buffer position in current_buffer. (reseat_iterator): Call above function. - (compute_face_at_iterator_position): Call - compute_face_at_buffer_pos. - (compute_face_at_iterator_string_position): Call - compute_face_at_string_pos. - (get_face_from_id): Removed. + (compute_face_at_iterator_position): + Call compute_face_at_buffer_pos. + (compute_face_at_iterator_string_position): + Call compute_face_at_string_pos. + (get_face_from_id): Remove. (get_face_from_cursor_pos): Call compute_face_at_buffer_pos. Call get_charset_at_buffer_position. (reseat_iterator): Determine face if charset at pos differs from iterator's charset. - (reseat_iterator_to_glyph_pos): Removed. + (reseat_iterator_to_glyph_pos): Remove. * xfaces.c (compute_face_at_bufpos): Remove parameter charset. Determine charset from buffer position. - (compute_string_char_face): Renamed to compute_face_at_string_pos. - (compute_face_at_bufpos): Renamed to compute_face_at_buffer_pos. + (compute_string_char_face): Rename to compute_face_at_string_pos. + (compute_face_at_bufpos): Rename to compute_face_at_buffer_pos. * dispextern.h (struct display_iterator): Add member charset. 1998-04-15 Gerd Moellmann <gerd@gnu.org> - * xfaces.c (compute_char_face): Removed. + * xfaces.c (compute_char_face): Remove. * xdisp.c (get_overlay_arrow_glyph_row): Use compute_glyph_face with new parameter list. - * xfaces.c (region_face): Removed. - (allocate_face): Removed. + * xfaces.c (region_face): Remove. + (allocate_face): Remove. (copy_face): Ditto. - (face_eql): Removed. - (intern_face): Removed. - (clear_face_cache): Removed. + (face_eql): Remove. + (intern_face): Remove. + (clear_face_cache): Remove. (load_font): Ditto. (unload_font): Ditto. (load_color): Ditto. @@ -7644,9 +7644,9 @@ (merge_faces): Ditto. (compute_base_face): Ditto. (merge_face_list): Ditto. - (Fmake_face_internal): Removed. + (Fmake_face_internal): Remove. (Fset_face_attribute_internal): Ditto. - (face_name_id_number): Removed. + (face_name_id_number): Remove. (Fframe_face_alist): Ditto. (Fset_frame_face_alist): Ditto. (Finternal_next_face_id): Ditto. @@ -7693,7 +7693,7 @@ * fontset.h: Add external declarations for Vfontset_alias_alist and Vglobal_fontset_alist. - * xfaces.c (merge_lisp_face_vector_with_property): Simplified. + * xfaces.c (merge_lisp_face_vector_with_property): Simplify. (realize_default_face): If frame parameters contain an artificial font name naming a fontset, set the family of the default face to the fontset name given by the registry. @@ -7741,11 +7741,11 @@ * xdisp.c (set_cursor_from_row): If PT is not found in the row, display the cursor at the start of the row. - * dispnew.c (direct_output_forward_char): Call - set_cursor_from_row. + * dispnew.c (direct_output_forward_char): + Call set_cursor_from_row. - * xdisp.c (setup_iterator_overlay_strings_from_glyph_pos): If - position is not in an overlay string, set iterator's position and + * xdisp.c (setup_iterator_overlay_strings_from_glyph_pos): + If position is not in an overlay string, set iterator's position and method explicitly so. (set_cursor_from_row): Correct cursor position calculation. Make it externally visible. @@ -7907,7 +7907,7 @@ * dispnew.c: Make compilable with -Wall. * term.c: Ditto. - * charset.h (CHAR_LEN): Moved here from dispextern.h. + * charset.h (CHAR_LEN): Move here from dispextern.h. 1998-03-14 Gerd Moellmann <gerd@gnu.org> @@ -7939,8 +7939,8 @@ * xdisp.c (init_iterator): Increase last_visible_x by vertical scroll bar width for mode lines. - * dispnew.c (allocate_matrices_for_window_redisplay): Include - vertical scroll bar width in width calculation so that we can + * dispnew.c (allocate_matrices_for_window_redisplay): + Include vertical scroll bar width in width calculation so that we can display mode lines wider. * xdisp.c (redisplay_window): Restore buffers before returning @@ -7958,7 +7958,7 @@ * dispextern.h (struct glyph_row): Member max_ascent renamed ascent. Member max_descent replaced by height. (struct display_iterator): Member max_descent replaced by height. - (MATRIX_ROW_PIXEL_HEIGHT): Removed. + (MATRIX_ROW_PIXEL_HEIGHT): Remove. * xterm.c (x_alloc_lighter_color): Don't free colors if visual class makes it unnecessary or dangerous. @@ -7999,10 +7999,10 @@ * xterm.c (x_scroll_run): Don't set updated_window to null. This resets updated_window when called from scrolling_window. - * dispextern.h (scroll_run_hook): Renamed from line_dance_hook. + * dispextern.h (scroll_run_hook): Rename from line_dance_hook. - * xterm.c (x_scroll_run): Additional window parameter. Set - and reset updated_window. + * xterm.c (x_scroll_run): Additional window parameter. + Set and reset updated_window. * dispnew.c (line_dance_hook): Additional window parameter. @@ -8016,7 +8016,7 @@ * dispnew.c (Fblink_cursor): Remove call to detect_input_pending. Don't redraw cursor during redisplay. - * xterm.c (x_scroll_run): Renamed from do_line_dance. + * xterm.c (x_scroll_run): Rename from do_line_dance. * xdisp.c (redisplay_window): For window-based redisplay, always try try_window_id. @@ -8080,8 +8080,8 @@ * xdisp.c (set_next_iterator_stop_pos): No longer static. - * dispnew.c (direct_output_for_insert): Call - set_next_iterator_stop_pos after having changed it2.endpos. + * dispnew.c (direct_output_for_insert): + Call set_next_iterator_stop_pos after having changed it2.endpos. 1998-02-17 Gerd Moellmann <gerd@gnu.org> @@ -8102,22 +8102,22 @@ enough glyphs to display a mode line or menu line which draws over flags areas. - * xterm.c (XTset_vertical_scroll_bar): Use - WINDOW_DISPLAY_TEXT_AREA_PIXEL_HEIGHT instead of + * xterm.c (XTset_vertical_scroll_bar): + Use WINDOW_DISPLAY_TEXT_AREA_PIXEL_HEIGHT instead of VERTICAL_SCROLL_BAR_PIXEL_HEIGHT. (x_draw_glyphs): Draw over flags areas when drawing a mode line or menu. (x_set_glyph_string_clipping): Set clipping differently if drawing a mode line or menu line. - * xterm.h (VERTICAL_SCROLL_BAR_PIXEL_HEIGHT): Removed. + * xterm.h (VERTICAL_SCROLL_BAR_PIXEL_HEIGHT): Remove. * xterm.c (expose_line): Don't draw bitmaps for mode lines and menu lines. (x_scroll_bar_create): Don't clear flags areas. (x_draw_row_bitmaps): Clear visible row height, only. - * dispnew.c (Fblink_cursor): Moved here from xdisp.c. + * dispnew.c (Fblink_cursor): Move here from xdisp.c. 1998-02-15 Gerd Moellmann <gerd@gnu.org> @@ -8137,21 +8137,21 @@ * dispnew.c (update_window_line): Special handling of inverse lines in #if 0 removed. - * xterm.c (x_write_glyphs): Renamed from XTwrite_glyphs. - (x_insert_glyphs): Renamed from XTinsert_glyphs. - (x_clear_frame): Renamed from XTclear_frame. - (x_clear_end_of_line): Renamed from XTclear_end_of_line. - (x_ins_del_lines): Renamed from XTins_del_lines. - (x_change_line_height): Renamed from XTchange_line_height. - (x_delete_glyphs): Renamed from XTdelete_glyphs. - (x_clear_cursor): Renamed from clear_cursor. - (x_update_begin): Renamed from XTupdate_begin. - (x_update_end): Renamed from XTupdate_end. - (x_update_window_begin): Renamed from XTupdate_window_begin. - (x_update_window_end): Renamed from XTupdate_window_end. - (x_frame_mode_line_height): Renamed from XTframe_mode_line_height. - (x_produce_glyphs): Renamed from XTproduce_glyphs. - (x_produce_special_glyphs): Renamed from XTproduce_special_glyphs. + * xterm.c (x_write_glyphs): Rename from XTwrite_glyphs. + (x_insert_glyphs): Rename from XTinsert_glyphs. + (x_clear_frame): Rename from XTclear_frame. + (x_clear_end_of_line): Rename from XTclear_end_of_line. + (x_ins_del_lines): Rename from XTins_del_lines. + (x_change_line_height): Rename from XTchange_line_height. + (x_delete_glyphs): Rename from XTdelete_glyphs. + (x_clear_cursor): Rename from clear_cursor. + (x_update_begin): Rename from XTupdate_begin. + (x_update_end): Rename from XTupdate_end. + (x_update_window_begin): Rename from XTupdate_window_begin. + (x_update_window_end): Rename from XTupdate_window_end. + (x_frame_mode_line_height): Rename from XTframe_mode_line_height. + (x_produce_glyphs): Rename from XTproduce_glyphs. + (x_produce_special_glyphs): Rename from XTproduce_special_glyphs. (x_produce_special_glyphs): Implementation in #if 0 removed. * xdisp.c (Fdump_redisplay_state): Display row's fill_line_p @@ -8232,14 +8232,14 @@ * dispextern.h (struct glyph_matrix): New member window_width. - * dispnew.c (adjust_glyph_matrix): Set window_width. Optimize - case of changing window height. + * dispnew.c (adjust_glyph_matrix): Set window_width. + Optimize case of changing window height. * xterm.c (x_draw_row_bitmaps): Don't clear vertical window border to the left. - * dispextern.h (struct glyph_row): Remove right_to_left_p. RMS - says this aspect of Emacs is currently redesigned. + * dispextern.h (struct glyph_row): Remove right_to_left_p. + RMS says this aspect of Emacs is currently redesigned. * xterm.c (x_clip_to_row): Subtract 1 from clip width if we have to draw a vertical border. @@ -8268,8 +8268,8 @@ removed. (struct glyph): Ditto. - * xterm.c (x_draw_relief): Removed. - (x_draw_bitmap): Renamed from draw_bitmap. + * xterm.c (x_draw_relief): Remove. + (x_draw_bitmap): Rename from draw_bitmap. (x_draw_glyphs): Completely new implementation of draw_glyphs capable of handling arbitrary lbearing and rbearing values. Several sub-functions not mentioned here. @@ -8347,11 +8347,11 @@ 1998-01-25 Gerd Moellmann <gerd@gnu.org> - * dispextern.h (DEFAULT_FACE_ID, MODE_LINE_FACE_ID): Symbolic - names for face ids of frame default face and mode line face. + * dispextern.h (DEFAULT_FACE_ID, MODE_LINE_FACE_ID): + Symbolic names for face ids of frame default face and mode line face. - * xdisp.c (compute_face_at_iterator_string_position): If - displaying a mode line use MODE_LINE_FACE_ID instead of + * xdisp.c (compute_face_at_iterator_string_position): + If displaying a mode line use MODE_LINE_FACE_ID instead of DEFAULT_FACE_ID. * xdisp.c (reseat_iterator_to_string): Additional parameter start. @@ -8405,8 +8405,8 @@ (move_iterator_in_display_line_to): If to_pos specified, move over before-strings. - * dispextern.h (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P): Test - start.string_index > 0. + * dispextern.h (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P): + Test start.string_index > 0. * xdisp.c (redisplay_internal): Adjust glyphs if fonts_changed_p is set. Retry redisplay if fonts_changed_p is set before update. @@ -8415,7 +8415,7 @@ * xfaces.c (Fset_face_attribute_internal): Set fonts_changed_p. - * dispnew.c (adjust_glyphs_for_font_change): Removed. + * dispnew.c (adjust_glyphs_for_font_change): Remove. * xdisp.c (try_window): Check fonts_changed_p. (try_window_reusing_current_matrix): Ditto. @@ -8468,8 +8468,8 @@ * editfns.c (make_buffer_string): If PROMPT_IN_BUFFER, add prompt length to start position. - * buffer.c (Fget_buffer_create): Initialize - minibuffer_prompt_length. + * buffer.c (Fget_buffer_create): + Initialize minibuffer_prompt_length. (Fmake_indirect_buffer): Ditto. (Fkill_buffer): Ditto. @@ -8489,15 +8489,15 @@ * xfaces.c (compute_string_char_face): Compute face for arbitrary Lisp string. Renamed from compute_overlay_string_char_face. - * xdisp.c (next_element_from_string): Renamed from + * xdisp.c (next_element_from_string): Rename from next_element_from_overlay_string. - (compute_face_at_iterator_string_position): Renamed from + (compute_face_at_iterator_string_position): Rename from compute_face_at_iterator_overlay_string_position. * dispextern.h (struct display_iterator): Member overlay_string renamed string. - * xdisp.c (next_element_from_c_string): Renamed from + * xdisp.c (next_element_from_c_string): Rename from next_element_from_string. * dispextern.h (struct glyph_pos): Reversed meaning of @@ -8535,8 +8535,8 @@ 1998-01-17 Gerd Moellmann <gerd@gnu.org> - * xdisp.c (move_iterator_vertically): Check post-condition. Move - to start of line if ending at ZV and no newline in front. + * xdisp.c (move_iterator_vertically): Check post-condition. + Move to start of line if ending at ZV and no newline in front. (move_iterator_to): If to_y specified, always first move to x = 0, so that move stops at line start instead of line end. This is probably what callers would expect to happen. @@ -8561,19 +8561,19 @@ try_window_reusing_current_matrix if window scroll functions exist. - * dispextern.h (struct display_iterator): Member - redisplay_end_trigger_p removed. + * dispextern.h (struct display_iterator): + Member redisplay_end_trigger_p removed. * dispextern.h (WINDOW_DISPLAY_PIXEL_HEIGHT_WITHOUT_MODE_LINE): - Renamed to WINDOW_DISPLAY_TEXT_AREA_PIXEL_HEIGHT. + Rename to WINDOW_DISPLAY_TEXT_AREA_PIXEL_HEIGHT. 1998-01-16 Gerd Moellmann <gerd@gnu.org> * xdisp.c (move_iterator_by_lines): Optimize for truncate-lines nil. Optimize truncate-lines t and moving backward. (move_iterator_to_previous_visible_line_start): Contains the heart - of the previous set_iterator_to_previous_visible_line_end. Don't - reseat the iterator. Used by move_iterator_by_lines. + of the previous set_iterator_to_previous_visible_line_end. + Don't reseat the iterator. Used by move_iterator_by_lines. (set_iterator_to_previous_visible_line_start): Call function above. (move_iterator_in_display_line_to): Check TO_POS before doing @@ -8608,8 +8608,8 @@ (Fset_face_attribute_internal): Use XINT instead of XFASTINT to get a relief because they can be negative. - * xterm.c (x_draw_relief): Correct line drawing positions. Pixel - positions are for the middle of lines under X. + * xterm.c (x_draw_relief): Correct line drawing positions. + Pixel positions are for the middle of lines under X. * xdisp.c (try_window_id): Always search for the cursor by setting w->cursor.vpos = -1. Search in unchanged rows at the top and @@ -8642,16 +8642,16 @@ * xdisp.c (display_line): Bug fix cursor positioning. - * xfns.c (x-list-fonts): Copied from x-list-fonts.c; #include + * xfns.c (x-list-fonts): Copy from x-list-fonts.c; #include removed. x-list-fonts.c is now obsolete. - (Qfixed, Qvariable): Moved here from xfaces.c. + (Qfixed, Qvariable): Move here from xfaces.c. 1998-01-14 Gerd Moellmann <gerd@gnu.org> * xdisp.c (display_line): Set row->ends_at_zv_p based on FETCH_BYTE for truncated lines. (display_line): Set cursor differently. - (display_line): Fixed bug setting last_pos_on_this_line wrong + (display_line): Fix bug setting last_pos_on_this_line wrong for truncated lines. * dispnew.c (adjust_glyph_matrix): Always adjust for frame-based @@ -8659,8 +8659,8 @@ * window.c (Fsplit_window): Adjust glyphs before setting buffer. - * dispnew.c (adjust_frame_glyphs_for_window_redisplay): Add - assertion that character dimensions are not zero. + * dispnew.c (adjust_frame_glyphs_for_window_redisplay): + Add assertion that character dimensions are not zero. * xterm.c (x_load_font): adjust_glyphs_for_font_change while input is blocked. @@ -8680,7 +8680,7 @@ * xterm.h (FRAME_FLAGS_BITMAP_WIDTH): Macro giving the width in pixels of a flags area of a frame. - (FRAME_X_FLAGS_AREA_WIDTH): Removed. + (FRAME_X_FLAGS_AREA_WIDTH): Remove. (FRAME_X_FLAGS_AREA_COLS): Macro giving the number of columns occupied by a flags area. @@ -8694,7 +8694,7 @@ * xdisp.c (display_line): Correct wrong calculation of row->x for the case of nglyphs == 1. - (hscroll_window_tree): Renamed from hscroll_windows. + (hscroll_window_tree): Rename from hscroll_windows. (hscroll_windows): New function calling hscroll_window_tree that clears desired matrices on a frame when hscroll has been changed. (redisplay_p): Global flag set during redisplay. @@ -8725,8 +8725,8 @@ * xfaces.c (Qfixed, Qvariable): Symbols for use by x-list-fonts. (syms_of_xfaces): Initialize them. - * xterm.c (x_list_fonts): Include auto-scaled fonts. Extend - cached information. + * xterm.c (x_list_fonts): Include auto-scaled fonts. + Extend cached information. 1998-01-11 Gerd Moellmann <gerd@acm.org> @@ -8742,7 +8742,7 @@ 1998-01-05 Gerd Moellmann <gerd@acm.org> - * xdisp.c (get_row_start_continuation_line_width): Removed. + * xdisp.c (get_row_start_continuation_line_width): Remove. (init_iterator_to_row_start): Set it.current_x from row. (try_window_id): Set it.continuation_lines_width directly from row. @@ -8768,7 +8768,7 @@ 1998-01-02 Gerd Moellmann <gerd@acm.org> - * xterm.c (x_get_mode_line_face_gc): Renamed from + * xterm.c (x_get_mode_line_face_gc): Rename from x_get_modeline_face_gc. * xdisp.c (TEXT_PROP_DISTANCE_LIMIT): Max. distance from current @@ -8820,22 +8820,22 @@ * xterm.c (x_get_cursor_gc): Don't return cursor_gc for font == frame font if line height differs from font height. - * xdisp.c (set_iterator_to_next): Renamed from + * xdisp.c (set_iterator_to_next): Rename from move_iterator_forward to avoid confusion with other move_.* functions. - * dispextern.h (FACE_RELIEF_P): Renamed from FACE_3D_P. + * dispextern.h (FACE_RELIEF_P): Rename from FACE_3D_P. 1997-12-31 Gerd Moellmann <gerd@acm.org> - * xterm.c (x_get_cursor_gc): Renamed from x_cursor_gc to use the + * xterm.c (x_get_cursor_gc): Rename from x_cursor_gc to use the same naming convention as for other GC functions. (draw_glyphs): Don't fill background when drawing a cursor and font height is less than line height. 1997-12-30 Gerd Moellmann <gerd@acm.org> - * xdisp.c (init_display_iterator.*): Renamed to shorter names + * xdisp.c (init_display_iterator.*): Rename to shorter names init_iterator_.*. * xdisp.c (move_iterator_forward): Restore it->len from @@ -8918,8 +8918,8 @@ (x_get_char_font_and_encoding): Return null if font could not be loaded. Reset font to null if fontset could not be loaded. (draw_glyphs): Fill background if font not found. - (draw_glyphs): Unused parameter just_foreground_p removed. New - parameter composite_glyph. + (draw_glyphs): Unused parameter just_foreground_p removed. + New parameter composite_glyph. (draw_glyphs): Use enumeration for parameter hl. (draw_glyphs): Pass a display area relative x-position to draw_glyphs when calling it recursively for composite chars. @@ -8961,8 +8961,8 @@ * xterm.c (x_after_update_window_line): Draw continuation line bitmap. - * dispnew.c (update_window_line): Call - after_update_window_line_hook when row's continuation_line_p + * dispnew.c (update_window_line): + Call after_update_window_line_hook when row's continuation_line_p changes. * xterm.c (draw_bitmap): Draw new bitmap CONTINUATION_LINE_BITMAP. @@ -8999,27 +8999,27 @@ 1997-12-14 Gerd Moellmann <gerd@acm.org> - * frame.h (FRAME_MODE_LINE_PIXEL_HEIGHT): Removed. + * frame.h (FRAME_MODE_LINE_PIXEL_HEIGHT): Remove. * window.c (coordinates_in_window): Call frame_mode_line_height. - * xterm.c (x_draw_3d_border): Removed. - (x_draw_row_borders): Removed. + * xterm.c (x_draw_3d_border): Remove. + (x_draw_row_borders): Remove. * dispnew.c (update_window): References to FRAME_MODE_LINE_BORDER_WIDTH removed. - * xterm.h (FRAME_MODE_LINE_BORDER_WIDTH): Removed. - (FRAME_MODE_LINE_HEIGHT): Removed. + * xterm.h (FRAME_MODE_LINE_BORDER_WIDTH): Remove. + (FRAME_MODE_LINE_HEIGHT): Remove. - * xterm.c (draw_3d_borders_p): Removed. + * xterm.c (draw_3d_borders_p): Remove. (draw_glyphs): Ditto. (XTwrite_glyphs): Ditto. (expose_line): Ditto. (x_initialize): Ditto. - * dispextern.h (WINDOW_DISPLAY_MODE_LINE_HEIGHT): Call - frame_mode_line_height. + * dispextern.h (WINDOW_DISPLAY_MODE_LINE_HEIGHT): + Call frame_mode_line_height. * term.c (frame_mode_line_height): Get the pixel height of a frame's mode line. @@ -9047,8 +9047,8 @@ * xdisp.c (compute_face_at_iterator_overlay_string_position): Use it. - * xdisp.c (set_iterator_to_next_overlay_string): Formerly - set_iterator_to_next_overlay. + * xdisp.c (set_iterator_to_next_overlay_string): + Formerly set_iterator_to_next_overlay. (struct overlay_entry): Structure used to sort overlay strings. (compare_overlay_entries): Compare overlay strings. (load_iterator_with_overlay_strings): Load a chunk of overlay @@ -9056,11 +9056,11 @@ (get_overlay_strings_at_iterator_position): Call it. (next_element_from_overlay_string): Set it->object to the overlay string. Prepare for setting it->position to a string position. - (get_overlay_strings_at_iterator_position): Renamed from + (get_overlay_strings_at_iterator_position): Rename from get_overlays_at_iterator_position. - (setup_iterator_overlay_strings_from_glyph_pos): Changed to load + (setup_iterator_overlay_strings_from_glyph_pos): Change to load chunks of overlay strings. - (load_overlay_strings): Renamed from load_iterator_overlay_strings. + (load_overlay_strings): Rename from load_iterator_overlay_strings. * dispextern.h (struct display_iterator): New vector overlay_strings and new member n_overlay_strings---formerly @@ -9072,9 +9072,9 @@ * xdisp.c (copy_iterator): Increment n_iterator_overlay_vectors when allocating a vector. - (release_iterator): Removed. - (restore_iterator): Removed. - (copy_iterator): Removed. + (release_iterator): Remove. + (restore_iterator): Remove. + (copy_iterator): Remove. 1997-12-08 Gerd Moellmann <gerd@acm.org> @@ -9087,10 +9087,10 @@ * xterm.h (struct x_output): trunc_area_extra renamed flags_areas_extra. - (FRAME_X_FLAGS_AREA_WIDTH): Renamed from FRAME_X_TRUNC_WIDTH. + (FRAME_X_FLAGS_AREA_WIDTH): Rename from FRAME_X_TRUNC_WIDTH. - * dispnew.c (update_window_line): Call - after_update_window_line_hook when current row is not enabled + * dispnew.c (update_window_line): + Call after_update_window_line_hook when current row is not enabled which is the case after a frame has been cleared. * xdisp.c (display_mode_line): Reset row flags for truncation @@ -9129,8 +9129,8 @@ face changes and changes in invisible text property. (struct glyph_pos): Former ovlen now overlay_string_index. - * xdisp.c (setup_iterator_overlays_from_glyph_pos): Set - overlay_string. + * xdisp.c (setup_iterator_overlays_from_glyph_pos): + Set overlay_string. (set_iterator_to_next_overlay_string): Set overlay_string and pos.overlay_string_index. (get_overlays_at_iterator_position): Use overlay_string and @@ -9167,7 +9167,7 @@ * buffer.h (overlays_at): Function prototype. * xdisp.c (reseat_iterator_to_string): Clear iterator position. - * dispextern.h (GET_NEXT_DISPLAY_ELEMENT): Removed. + * dispextern.h (GET_NEXT_DISPLAY_ELEMENT): Remove. * xdisp.c (release_iterator): Release dynamically allocated memory of a display_iterator. @@ -9187,23 +9187,23 @@ * buffer.c (overlays_at): Make it work when extending vectors and an initial vector of zero size. - * xdisp.c (set_iterator_to_previous_visible_line_end): Renamed - from set_cursor_to_previous_visible_line_end. - (set_iterator_to_next_visible_line_start): Renamed from + * xdisp.c (set_iterator_to_previous_visible_line_end): + Rename from set_cursor_to_previous_visible_line_end. + (set_iterator_to_next_visible_line_start): Rename from set_cursor_to_next_visible_line_end. - (set_next_iterator_stop_pos): Renamed from set_next_stop_pos. - (compute_face_at_iterator_position): Renamed from + (set_next_iterator_stop_pos): Rename from set_next_stop_pos. + (compute_face_at_iterator_position): Rename from compute_cursor_face. - (set_iterator_to_next_overlay_string): Renamed from + (set_iterator_to_next_overlay_string): Rename from cursor_to_next_overlay_string. - (get_overlays_at_iterator_position): Renamed from + (get_overlays_at_iterator_position): Rename from get_overlays_for_cursor. - (reseat_iterator): Renamed from reseat_cursor. - (setup_iterator_overlays_from_glyph_pos): Renamed from + (reseat_iterator): Rename from reseat_cursor. + (setup_iterator_overlays_from_glyph_pos): Rename from setup_overlays_from_pos. - (init_string_iterator): Renamed from init_string_cursor. - (get_next_display_element): Renamed from next_display_element. - (move_iterator_forward): Renamed from advance_display_cursor. + (init_string_iterator): Rename from init_string_cursor. + (get_next_display_element): Rename from next_display_element. + (move_iterator_forward): Rename from advance_display_cursor. (get_overlays_at_iterator_position): Allocate overlays vector dynamically. @@ -9214,7 +9214,7 @@ 1997-12-01 Gerd Moellmann <gerd@acm.org> * window.c (mark_window_cursors_off): Function comment added. - (window_topmost_p, window_rightmost_p): Removed because not used. + (window_topmost_p, window_rightmost_p): Remove because not used. 1997-11-30 Gerd Moellmann <gerd@acm.org> @@ -9229,7 +9229,7 @@ frame_title_buf. (init_xdisp): Initialize frame_title_.* variables to null. - * dispnew.c (quit_error_check): Removed. + * dispnew.c (quit_error_check): Remove. * eval.c (Fsignal): Call to quit_error_check removed. * keyboard.c (quit_throw_to_read_char): Ditto. @@ -9275,8 +9275,8 @@ * xterm.c (XTupdate_window_end): Don't display cursor if pseudo_window_p. - * dispnew.c (adjust_frame_glyphs_for_window_redisplay): Don't - set mini_p. + * dispnew.c (adjust_frame_glyphs_for_window_redisplay): + Don't set mini_p. (update_window): Don't set cursor if pseudo_window_p. * dispextern.h (WINDOW_WANTS_MODELINE_P): Test pseudo_window_p. @@ -9307,8 +9307,8 @@ f->menu_bar_window if appropriate. (display_mode_line): Use MATRIX_MODE_LINE_ROW. - * dispnew.c (adjust_frame_glyphs_for_window_redisplay): Allocate - dummy window and window matrices for f->menu_bar_window. + * dispnew.c (adjust_frame_glyphs_for_window_redisplay): + Allocate dummy window and window matrices for f->menu_bar_window. (free_glyphs): Free the dummy window and its glyph matrices. * frame.h (struct frame): New member menu_bar_window. @@ -9323,8 +9323,8 @@ first_row_to_display. The previous scheme failed if the last row was fully visible. - * dispnew.c (update_window): Remove cost calculations. Remove - redundant preempt_count calculations. + * dispnew.c (update_window): Remove cost calculations. + Remove redundant preempt_count calculations. * xterm.c (x_clip_to_row): Set clipping for non-text rows differently. @@ -9345,7 +9345,7 @@ try_window_id. (try_window_reusing_current_matrix): Give up for terminal frames if window is not full width or we cannot insert/delete lines. - (try_window_reusing_current_matrix): Fixed scrolling for terminal + (try_window_reusing_current_matrix): Fix scrolling for terminal frames. * alloc.c (mark_glyph_matrix): Bug fix - pass pointer to @@ -9407,8 +9407,8 @@ (update_window_line): Set it. (update_marginal_area): Clear to end of line if not in text area. - * window.c (Fset_window_margins): Increment - windows_or_buffer_changed. Adjust glyphs. + * window.c (Fset_window_margins): + Increment windows_or_buffer_changed. Adjust glyphs. * dispextern.h (WINDOW_TEXT_TO_FRAME_PIXEL_X): Convert text area X coordinates to frame coordinates. @@ -9496,8 +9496,8 @@ 1997-10-27 Gerd Moellmann <gerd@acm.org> - * dispnew.c (update_window_line): Call - after_update_window_line_hook only for interesting constellations. + * dispnew.c (update_window_line): + Call after_update_window_line_hook only for interesting constellations. (free_glyph_matrix): Fix memory leak. * window.h: Include blocker WINDOW_H_INCLUDED, include @@ -9507,7 +9507,7 @@ (replace_window): Ditto. * dispnew.c (free_window_matrices): Remove freeing of phys_cursor_glyph. - (check_matrix_invariants): Renamed from check_current_matrix_... + (check_matrix_invariants): Rename from check_current_matrix_... * xterm.c: All references to phys_cursor_glyph changed. * dispextern.h (DISPEXTERN_H_INCLUDED): New include blocker. @@ -9665,8 +9665,8 @@ * dispextern.h (MATRIX_ROW_FIRST_POS): Use row start. - * dispnew.c (increment_glyph_row_buffer_positions): Adjust - start and end positions in rows. + * dispnew.c (increment_glyph_row_buffer_positions): + Adjust start and end positions in rows. (increment_glyph_row_buffer_positions): Stop adjusting at glyphs with positions <= 0. @@ -9682,8 +9682,8 @@ 1997-10-21 Gerd Moellmann <gerd@acm.org> - * dispnew.c (update_window): Add scrolling_window again. It's - necessary for scroll_step != 0. + * dispnew.c (update_window): Add scrolling_window again. + It's necessary for scroll_step != 0. * xdisp.c (redisplay_window): Use vmotion for scroll_step scrolling. @@ -9745,7 +9745,7 @@ 1997-10-19 Gerd Moellmann <gerd@acm.org> * dispnew.c (update_window): Remove unused variable. - (update_window_line): Simplified. + (update_window_line): Simplify. * xterm.c (x_get_char_font_and_encoding): Handle most common case at the beginning. @@ -9756,8 +9756,8 @@ * xdisp.c (try_window_id): New implementation. - * dispnew.c (increment_glyph_row_buffer_positions): Capture - rows displaying a line end, only. + * dispnew.c (increment_glyph_row_buffer_positions): + Capture rows displaying a line end, only. 1997-10-18 Gerd Moellmann <gerd@acm.org> @@ -9850,8 +9850,8 @@ * term.c: Some hooks with function prototypes. - * xdisp.c (reseat_cursor): Additional argument force_p. Avoid - computing face if possible. + * xdisp.c (reseat_cursor): Additional argument force_p. + Avoid computing face if possible. * xdisp.c (next_display_element): Use face from glyph from display table only if != 0. @@ -9883,7 +9883,7 @@ (init_display_info): Subtract vertical border glyph from last_visible_x. - * scroll.c (scrolling_window_1): Removed. + * scroll.c (scrolling_window_1): Remove. * dispnew.c (adjust_frame_glyphs): Split into two functions, based on redisplay method used. @@ -9892,7 +9892,7 @@ (adjust_frame_glyphs_for_window_redisplay): Part for purely window based redisplay. - * frame.h (FRAME_WINDOW_REDISPLAY_P): Changed to not depend + * frame.h (FRAME_WINDOW_REDISPLAY_P): Change to not depend on data structures. * dispnew.c (adjust_glyph_matrix): Additional parameter W. @@ -9904,8 +9904,8 @@ * dispextern.h (struct glyph_matrix): window_top_y, window_height. - * dispnew.c (allocate_matrices_for_window_redisplay): Detect - and optimize some common cases of window changes. + * dispnew.c (allocate_matrices_for_window_redisplay): + Detect and optimize some common cases of window changes. * emacs.c (main): Remove own profiling code because 0.95 now has it in. @@ -9965,9 +9965,9 @@ * xterm.c (x_draw_row_borders): Use FRAME_MODE_LINE_HEIGHT height value. (x_clip_to_row): Use MATRIX_ROW_VISIBLE_HEIGHT. Simplified. - (do_line_dance): Simplified and pixel corrected. + (do_line_dance): Simplify and pixel corrected. - * dispnew.c (scrolling_window): Simplified. + * dispnew.c (scrolling_window): Simplify. * xterm.c (x_draw_3d_border): Insert rectangle by line width. @@ -10049,15 +10049,15 @@ * xterm.h (WINDOW_COL_PIXEL_X etc.) Removed. - * dispextern.h (WINDOW_TO_FRAME_HPOS/VPOS): Moved to dispnew.c. + * dispextern.h (WINDOW_TO_FRAME_HPOS/VPOS): Move to dispnew.c. * xfns.c (x_contour_region): Use pixel coordinates from window cursor instead of WINDOW_TO_FRAME_H/VPOS. * dispextern.h (FRAME_TO_WINDOW_HPOS, FRAME_TO_WINDOW_VPOS): - Removed. + Remove. - * dispnew.c (frame_to_window_hpos, frame_to_window_vpos): Removed. + * dispnew.c (frame_to_window_hpos, frame_to_window_vpos): Remove. * xterm.c (x_y_to_hpos_vpos): Get hpos/vpos from window relative pixel coordinates. @@ -10541,16 +10541,16 @@ * xfns.c (Fx_create_frame): Don't set PHYS_CURSOR_X to -1. I don't believe this is really necessary. - * dispnew.c (build_frame_matrix_from_leaf_window): Determine - border glyph once. + * dispnew.c (build_frame_matrix_from_leaf_window): + Determine border glyph once. 1997-07-15 Gerd Moellmann <gerd@acm.org> * window.c (mark_window_cursors_off): Mark all cursors in window tree off. - * xterm.c (x_display_box_cursor): Window parameter. Use - window matrix. + * xterm.c (x_display_box_cursor): Window parameter. + Use window matrix. (glyph_to_pixel_pos): Convert matrix pos -> pixels. (pixel_to_glyph_pos): Convert pixel pos -> matrix pos. (x_update_cursor): Work on windows. @@ -10576,7 +10576,7 @@ * frame.h (struct frame): Cursor information removed. - * frame.h (FRAME_SCROLL_BAR_WIDTH): Removed because unused. + * frame.h (FRAME_SCROLL_BAR_WIDTH): Remove because unused. (FRAME_WINDOW_WIDTH_ARG): Don't add scroll bar width. * window.h (WINDOW_LEFT_MARGIN): Remove FRAME_LEFT_SCROLL_BAR. @@ -10650,7 +10650,7 @@ * window.h: CURSOR_VPOS/HPOS added. * frame.h (struct frame): CURSOR_X/Y removed. - (FRAME_CURSOR_X): Removed. + (FRAME_CURSOR_X): Remove. (FRAME_CURSOR_Y): Ditto. * dispnew.c (direct_output_for_insert): LAST_POINT_X removed. @@ -10687,10 +10687,10 @@ * minibuf.c (read_minibuf): Build frame matrix. - * xdisp.c (this_line_start_hpos): Renamed to + * xdisp.c (this_line_start_hpos): Rename to THIS_LINE_START_WINDOW_HPOS to make it clear that this is window relative. - (this_line_vpos): Renamed to THIS_LINE_WINDOW_VPOS for the same + (this_line_vpos): Rename to THIS_LINE_WINDOW_VPOS for the same reason. * dispnew.c (build_frame_matrix): Don't clear rows of the @@ -10717,7 +10717,7 @@ * lisp.h: Prototype for SCAN_BUFFER. - * xdisp.c (redisplay_windows): Simplified. + * xdisp.c (redisplay_windows): Simplify. * dispnew.c (window_to_frame_vpos): Convert window to frame vpos with debug checks. @@ -10739,8 +10739,8 @@ * xdisp.c (try_window_id): Use CANCEL_WINDOW_LINE. (redisplay_internal): Ditto. - * dispnew.c (cancel_window_line): Use window matrix. Changed - name to CANCEL_WINDOW_LINE. + * dispnew.c (cancel_window_line): Use window matrix. + Changed name to CANCEL_WINDOW_LINE. * xdisp.c (try_window_id): Use DISPLAY_TEXT_LINE with window relative VPOS. @@ -10790,7 +10790,7 @@ (allocate_leaf_matrix): Add FRAME_MENU_BAR_LINES to the height of top-most windows. - * window.h (WINDOW_TOPMOST_P): Added. + * window.h (WINDOW_TOPMOST_P): Add. * xdisp.c (echo_area_display): Use PREPARE_DESIRED_ROW. (redisplay_window): Ditto. @@ -10860,25 +10860,25 @@ * dispnew.c (check_matrix_pointer_lossage): Check against pointer lossage in matrices. - (get_glyph_matrix_row): Removed. + (get_glyph_matrix_row): Remove. - * scroll.c (do_scrolling): Simplified. - (do_direct_scrolling): Simplified. + * scroll.c (do_scrolling): Simplify. + (do_direct_scrolling): Simplify. (scrolling_1): Pass CURRENT_MATRIX instead of FRAME to DO_.*SCROLLING. * dispnew.c (ins_del_glyph_rows): Insert/delete rows in a matrix. - (rotate_vector): Removed. - (rotate_pointers): Removed. - (scroll_frame_lines): Simplified. + (rotate_vector): Remove. + (rotate_pointers): Remove. + (scroll_frame_lines): Simplify. 1997-07-03 Gerd Moellmann <gerd@acm.org> - * dispextern.h (MATRIX_ROW_SWAP_CONTENTS): Removed. + * dispextern.h (MATRIX_ROW_SWAP_CONTENTS): Remove. - * dispnew.c (increment_glyph_matrix_buffer_positions): Does - what the name says. + * dispnew.c (increment_glyph_matrix_buffer_positions): + Does what the name says. (clear_glyph_row): Make a glyph row structure empty. (make_matrix_row_current): Make a glyph row current. (make_window_matrix_row_current): Perform analogous row swaps @@ -10895,11 +10895,11 @@ * All files: Use above new names. - * dispnew.c (scroll_frame_lines): Simplified. Use - SCROLL_GLYPH_MATRIX. + * dispnew.c (scroll_frame_lines): Simplify. + Use SCROLL_GLYPH_MATRIX. (make_glyph_row_empty): Mark a glyph row empty. - (increment_glyph_row_buffer_positions): Increment - buffer positions in a glyph row. + (increment_glyph_row_buffer_positions): + Increment buffer positions in a glyph row. (increment_glyph_matrix_buffer_positions): Increment buffer positions in a range of rows. (scroll_glyph_matrix): Scroll a glyph matrix. @@ -10942,7 +10942,7 @@ (MATRIX_ROW_USED): Ditto. (MATRIX_ROW_SET_USED): Ditto. - * dispnew.c (line_hash_code): Simplified. + * dispnew.c (line_hash_code): Simplify. 1997-06-30 Gerd Moellmann <gerd@acm.org> @@ -10966,8 +10966,8 @@ DO_PENDING_WINDOW_CHANGE, CHANGE_FRAME_SIZE, BITCH_AT_USER, SIT_FOR, INIT_DISPLAY, SYMS_OF_DISPLAY, - * dispnew.c (redraw_frame): FRAME_PTR -> struct frame. Return - void. + * dispnew.c (redraw_frame): FRAME_PTR -> struct frame. + Return void. (cancel_line): Return void. (clear_frame_records): Return void. @@ -11085,13 +11085,13 @@ WRITE_GLYPHS_HOOK, DELETE_GLYPHS_HOOK, * xdisp.c (redisplay_internal): Remove call to VERIFY_CHARSTARTS. - (do_verify_charstarts): Removed. + (do_verify_charstarts): Remove. * frame.c (Fmake_terminal_frame): Adjust glyphs. (Fdelete_frame): Free glyphs. (make_frame): Initialize matrix fields in frame. - * config.in (PROTO): Added. + * config.in (PROTO): Add. * emacs.c (shut_down_emacs): Check glyph memory. @@ -11261,7 +11261,7 @@ * emacs.c [DOUG_LEA_MALLOC] (malloc_initialize_hook): Move the handling of MALLOC_CHECK_ envvar here. - (main): Moved from here. + (main): Move from here. 1999-06-29 Wolfram Gloger <wmglo@dent.med.uni-muenchen.de> @@ -11414,8 +11414,8 @@ * w32console.c (clear_frame): Remember that the window width might be smaller than the screen buffer width. - (write_glyphs): Remove redundant variable attrs. Use - FillConsoleOutputAttribute instead of WriteConsoleOutputAttribute. + (write_glyphs): Remove redundant variable attrs. + Use FillConsoleOutputAttribute instead of WriteConsoleOutputAttribute. 1999-05-20 Andrew Innes <andrewi@gnu.org> @@ -11423,8 +11423,8 @@ loses focus. * w32fns.c (w32_wnd_proc): Ensure mouse capture is released if - frame loses focus, and that mouse button state is reset. Ditto - when the menu bar is activated. + frame loses focus, and that mouse button state is reset. + Ditto when the menu bar is activated. 1999-05-18 Richard Stallman <rms@gnu.org> @@ -11599,7 +11599,7 @@ (w32_clear_frame, clear_cursor, x_display_bar_cursor) (x_display_box_cursor, x_set_window_size): Use phys_cursor_on field in frame. - (do_line_dance): Updated WRT xterm.c. Use macros where possible. + (do_line_dance): Update WRT xterm.c. Use macros where possible. (dumprectangle): Take into account the width of a left-side scroll bar. @@ -11617,8 +11617,8 @@ 1999-05-02 Kenichi HANDA <handa@etl.go.jp> - * coding.c (setup_raw_text_coding_system): Call - setup_coding_system to initialize the fields of struct + * coding.c (setup_raw_text_coding_system): + Call setup_coding_system to initialize the fields of struct coding_system correctly. 1999-04-26 Kenichi HANDA <handa@etl.go.jp> @@ -11773,11 +11773,11 @@ 1999-03-25 Andrew Innes <andrewi@gnu.org> * makefile.nt (PREPARED_HEADERS): Change name of paths.h to epaths.h. - (epaths.h): Renamed from paths.h. + (epaths.h): Rename from paths.h. (clean): ($(BLD)\filelock.obj): ($(BLD)\lread.obj): - ($(BLD)\w32fns.obj): Renamed paths.h to epaths.h. + ($(BLD)\w32fns.obj): Rename paths.h to epaths.h. 1999-03-23 Ken'ichi Handa <handa@gnu.org> @@ -11791,8 +11791,8 @@ 1999-03-20 Kenichi HANDA <handa@etl.go.jp> - * coding.c (ENCODE_ISO_CHARACTER): Check validity of CHARSET. If - invalid, produce the buffer internal byte sequence without encoding. + * coding.c (ENCODE_ISO_CHARACTER): Check validity of CHARSET. + If invalid, produce the buffer internal byte sequence without encoding. 1999-03-19 Karl Heuer <kwzh@gnu.org> @@ -11965,8 +11965,8 @@ 1999-02-24 Kenichi Handa <handa@etl.go.jp> * keymap.c (push_key_description): If enable-multibyte-characters - is non-nil, try to convert unibyte character to multibyte. For - invalid multibyte character, show all bits by octal form. + is non-nil, try to convert unibyte character to multibyte. + For invalid multibyte character, show all bits by octal form. (Fsingle_key_description): Check the validity of charset for a generic character. @@ -12083,8 +12083,8 @@ 1999-02-15 Kenichi Handa <handa@etl.go.jp> - * coding.c (Fdecode_sjis_char, Fencode_sjis_char): Handle - ASCII correctly. Signal error on invalid characters. + * coding.c (Fdecode_sjis_char, Fencode_sjis_char): + Handle ASCII correctly. Signal error on invalid characters. (Fdecode_big5_char, Fencode_big5_char): Likewise. 1999-02-15 Eli Zaretskii <eliz@gnu.org> @@ -12146,8 +12146,8 @@ 1999-02-04 Eli Zaretskii <eliz@gnu.org> - * w16select.c (last_clipboard_text, clipboard_storage_size): New - static variables. + * w16select.c (last_clipboard_text, clipboard_storage_size): + New static variables. (set_clipboard_data): Save a copy of the text we put into clipboard in last_clipboard_text. (get_clipboard_data): If the clipboard text is identical to what @@ -12305,8 +12305,8 @@ (x_destroy_bitmap): Returns void not int. (x_set_border_pixel): Returns void. (w32_load_bdf_font): New function. - (w32_load_system_font): New function, was w32_load_font. List - fonts before loading. Explicitly set encoding for SJIS fonts. + (w32_load_system_font): New function, was w32_load_font. + List fonts before loading. Explicitly set encoding for SJIS fonts. Set default_ascent to 0 as comment indicates. (w32_load_font): Call w32_load_system_font and w32_load_bdf_font. (w32_unload_font): Support BDF fonts. @@ -12350,7 +12350,7 @@ w32_codepage_for_charset. Add cast to int where float operation is assigned to int. (Vw32_charset_to_codepage_alist): New variable. - (w32_codepage_for_charset): Removed. + (w32_codepage_for_charset): Remove. (w32_codepage_for_font): New function, replacing w32_codepage_for_charset. (syms_of_w32term): Add and initialize @@ -12369,7 +12369,7 @@ * w32heap.h (ROUND_UP): (ROUND_DOWN): New macros. - (need_to_recreate_heap): Renamed to using_dynamic_heap. + (need_to_recreate_heap): Rename to using_dynamic_heap. (init_heap): New extern. (data_region_size): (recreate_heap): @@ -12384,11 +12384,11 @@ (round_to_next): Obsolete function removed. (preload_heap_section): New variable. (data_region_size): Obsolete variable removed. - (allocate_heap): Modified to determine end of static heap section + (allocate_heap): Modify to determine end of static heap section used during preload, and use that as initial base address for dynamic heap instead of hard-coded value. - (sbrk): Remove call to allocate_heap; handled by init_heap. Skip - calls to commit or decommit pages when allocating from static heap + (sbrk): Remove call to allocate_heap; handled by init_heap. + Skip calls to commit or decommit pages when allocating from static heap section during preload. (recreate_heap): Obsolete function removed. (init_heap): New function to initialize internal sbrk heap @@ -12399,10 +12399,10 @@ * unexw32.c: Major rewrite to support cleaner method of dumping; a static "bss" section is used for heap space during preload, and bss data is now written to the proper section area when dumping. - (need_to_recreate_heap): Renamed to using_dynamic_heap. + (need_to_recreate_heap): Rename to using_dynamic_heap. (heap_index_in_executable): Obsolete variable removed. (data_section): New variable. - (data_start_va): Renamed to data_start. + (data_start_va): Rename to data_start. (data_start_file): Obsolete variable removed. (bss_section): (extra_bss_size): @@ -12432,8 +12432,8 @@ sections where data will be dumped. Allows for static and global bss data to be in separate ranges. No longer relies on knowledge of section names. - (copy_executable_and_dump_data_section): Renamed - copy_executable_and_dump_data. Completely rewritten to copy + (copy_executable_and_dump_data_section): + Rename copy_executable_and_dump_data. Completely rewritten to copy executable section by section, so that raw data areas can be expanded to hold dumped data as necessary. Allows for bss data to be in same section as initialized data. Reduces size of static @@ -12511,8 +12511,8 @@ Return zero in case of success, 1 or 2 otherwise. (get_clipboard_data): Only bail out if the null character is in the last 32-byte chunk of clipboard data. - (Fw16_set_clipboard_data): Make ok and put_status be unsigned. If - they save binary data, print a message in the echo area saying the + (Fw16_set_clipboard_data): Make ok and put_status be unsigned. + If they save binary data, print a message in the echo area saying the text was not put into the clipboard. * msdos.c (IT_write_glyphs): Move constant expression out of the loop. @@ -12688,8 +12688,8 @@ based on VEC. * charset.c (Qunknown): New variable. - (init_charset_once): Intern and staticpro Qunknown. Initialize - all elements of Vcharset_symbol_table to Qunknown. + (init_charset_once): Intern and staticpro Qunknown. + Initialize all elements of Vcharset_symbol_table to Qunknown. (find_charset_in_str): New arg MULTIBYTE. If it is zero, check unibyte characters only. For an invalid composition sequence, set CHARSETS[1] to 1. @@ -12997,8 +12997,8 @@ (RIGHT_WIN_PRESSED): (APPS_PRESSED): New console keyboard modifier flags. - * w32term.c (convert_to_key_event): Removed. - (is_dead_key): Copied to w32fns.c. + * w32term.c (convert_to_key_event): Remove. + (is_dead_key): Copy to w32fns.c. (w32_read_socket): Generate language_change_event. Modify to work with keyboard handling changes in w32_wnd_proc. @@ -13037,10 +13037,10 @@ code. (is_dead_key): Copy from w32fns.c. (w32_kbd_patch_key): Comment attempt to improve handling of - dead-keys, and system bug relating to same on Windows NT. Work - around the bug by calling ToUnicode and then converting to the + dead-keys, and system bug relating to same on Windows NT. + Work around the bug by calling ToUnicode and then converting to the correct codepage. - (map_virt_key): Removed obsolete variable. + (map_virt_key): Remove obsolete variable. (lispy_function_keys): Add extern. (key_event): Major rework of keyboard input handling: optionally recognize Windows keys and Apps key as modifiers; optionally treat @@ -13066,7 +13066,7 @@ for given key. (w32_get_modifiers): Returns modifier flags for non-keyboard input events. - (construct_console_modifiers): Renamed from construct_modifiers; + (construct_console_modifiers): Rename from construct_modifiers; recognize Windows and Apps keys as modifiers. (w32_get_key_modifiers): New function. Returns modifier flags for keyboard input events. @@ -13098,12 +13098,12 @@ 1998-11-10 Kenichi Handa <handa@etl.go.jp> - * category.h (CATEGORY_SET): Adjusted for the change of + * category.h (CATEGORY_SET): Adjust for the change of cmpchar_component. (CATEGORY_SET): Likewise. - * charset.c (cmpchar_component): New arg NOERROR. Check - composition char ID more strictly. + * charset.c (cmpchar_component): New arg NOERROR. + Check composition char ID more strictly. (Fcmpchar_component): Call cmpchar_component with NOERROR arg zero. (Fcmpchar_cmp_rule): If CHARACTER should be composed relatively, return 255. @@ -13303,8 +13303,8 @@ (insert_from_buffer_1): Likewise. (adjust_after_replace): Inhibit bytes combined across region boundary. Update end_unchanged correctly. - (replace_range): Call CHECK_BYTE_COMBINING_FOR_INSERT. Update - end_unchanged correctly. + (replace_range): Call CHECK_BYTE_COMBINING_FOR_INSERT. + Update end_unchanged correctly. (del_range_2): Inhibit bytes combined across region boundary. Update end_unchanged correctly. @@ -13333,8 +13333,8 @@ 1998-10-27 Dave Love <fx@gnu.org> - * fns.c (Fbase64_decode_region, Fbase64_encode_region): Fix - newline in doc string. + * fns.c (Fbase64_decode_region, Fbase64_encode_region): + Fix newline in doc string. 1998-10-27 Kenichi Handa <handa@etl.go.jp> @@ -13415,28 +13415,28 @@ * w32fns.c (Vx_pixel_size_width): New global variable. (unibyte_display_via_language_environment): New global variable. (x_set_font): Add support for setting fontsets. - (Fx_create_frame): Add check_w32(). Initialize fontsets. Fix - font names to match xlfd-tight-regexp. + (Fx_create_frame): Add check_w32(). Initialize fontsets. + Fix font names to match xlfd-tight-regexp. (w32_load_font): Rewrite based on x_load_font. - (x_to_w32_charset, w32_to_x_charset): Add character sets. Use - `iso8859-1' rather than `ansi'. + (x_to_w32_charset, w32_to_x_charset): Add character sets. + Use `iso8859-1' rather than `ansi'. (w32_to_x_font): Remove `-' from font name. Remove the `-' off the end. Move charset into `charset registry' field. (enum_font_cb2): Check charsets match. Include width in font list. (w32_list_fonts): Rewrite based on x_list_fonts. Moved from w32term.c to have access to enumfont_t struct. - (Fx_list_fonts): w32 specific version eliminated. Include - `x-list-fonts.c'. - (w32_get_font_info, w32_query_font, w32_find_ccl_program): New - functions for fontset support - adapted from x_ equivalents. - (syms_of_w32fns): New lisp variables initialized. Function - pointers for fontset.c set up. + (Fx_list_fonts): w32 specific version eliminated. + Include `x-list-fonts.c'. + (w32_get_font_info, w32_query_font, w32_find_ccl_program): + New functions for fontset support - adapted from x_ equivalents. + (syms_of_w32fns): New lisp variables initialized. + Function pointers for fontset.c set up. * w32term.c: Include fontset.h. Define codepage macros. Add ENCODE_BIG5 macro from coding.c. (w32_no_unicode_output): New variable. - (w32_codepage_for_charset, w32_use_unicode_for_codepage): New - functions. + (w32_codepage_for_charset, w32_use_unicode_for_codepage): + New functions. (BUILD_WCHAR_T, BYTE1, BYTE2): New macros. (dumpglyphs): Rewrite based on xterm.c equivalent. (x_new_font): Use functionality provided in fontset.c. @@ -13552,8 +13552,8 @@ * lisp.h (clear_string_char_byte_cache): Extern it. - * xselect.c (lisp_data_to_selection_data): Call - find_charset_in_str with CMPCHARP arg 0. + * xselect.c (lisp_data_to_selection_data): + Call find_charset_in_str with CMPCHARP arg 0. * w16select.c (Fw16_set_clipboard_data): Likewise. * w32select.c (Fw32_set_clipboard_data): Likewise. @@ -13623,7 +13623,7 @@ * coding.c (check_composing_code): Fix previous change. Now it always returns 0 or -1. - (decode_coding_iso2022): Adjusted for the above change. + (decode_coding_iso2022): Adjust for the above change. (encode_coding_iso2022): When encoding the last block, flush out tailing garbage bytes. (setup_coding_system): Delete unnecessary code. @@ -13700,8 +13700,8 @@ * ccl.c (CCL_WRITE_CHAR): Don't use bcopy. (ccl_driver): If BUFFER-MAGNIFICATION of the CCL program is 0, - cause error if the program is going to output some bytes. When - outputting a string to notify an error, check the case that + cause error if the program is going to output some bytes. + When outputting a string to notify an error, check the case that DST_BYTES is zero. * coding.h (CODING_FINISH_INTERRUPT): New macro. @@ -13838,8 +13838,8 @@ * w16select.c (Vnext_selection_coding_system): New variable. (syms_of_win16select): DEFVAR_LISP it. No need to staticpro Vselection_coding_system. - (Fw16_set_clipboard_data): Always convert multibyte strings. Use - Vnext_selection_coding_system if non-nil. + (Fw16_set_clipboard_data): Always convert multibyte strings. + Use Vnext_selection_coding_system if non-nil. (Fw16_get_clipboard_data): Always convert a string that includes non-ASCII characters. Use Vnext_selection_coding_system if non-nil. @@ -13911,8 +13911,8 @@ 1998-08-28 Kenichi Handa <handa@etl.go.jp> * insdel.c (adjust_after_replace): Fix the code to record undo - information for the case that `before combining' happens. Remove - text properties which are added to the new text by + information for the case that `before combining' happens. + Remove text properties which are added to the new text by offset_intervals. * coding.c (code_convert_region1): Remove all text properties of diff --git a/src/Makefile.in b/src/Makefile.in index 70e31b50946..36e145744b3 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ ### @configure_input@ -# Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2014 Free Software -# Foundation, Inc. +# Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2014 +# Free Software Foundation, Inc. # This file is part of GNU Emacs. @@ -28,9 +28,10 @@ SHELL = @SHELL@ # Here are the things that we expect ../configure to edit. # We use $(srcdir) explicitly in dependencies so as not to depend on VPATH. srcdir = @srcdir@ +top_srcdir = @top_srcdir@ # MinGW CPPFLAGS may use this. abs_top_srcdir=@abs_top_srcdir@ -ntsource = $(srcdir)/../nt +ntsource = $(top_srcdir)/nt VPATH = $(srcdir) CC = @CC@ WINDRES = @WINDRES@ @@ -48,7 +49,7 @@ MKDIR_P = @MKDIR_P@ # LIBS = @LIBS@ LIBOBJS = @LIBOBJS@ -lispsource = $(srcdir)/../lisp +lispsource = $(top_srcdir)/lisp lib = ../lib libsrc = ../lib-src etc = ../etc @@ -77,6 +78,7 @@ C_SWITCH_MACHINE=@C_SWITCH_MACHINE@ C_SWITCH_SYSTEM=@C_SWITCH_SYSTEM@ GNUSTEP_CFLAGS=@GNUSTEP_CFLAGS@ +PNG_CFLAGS=@PNG_CFLAGS@ ## Define C_SWITCH_X_SITE to contain any special flags your compiler ## may need to deal with X Windows. For instance, if you've defined @@ -121,7 +123,7 @@ LIBS_SYSTEM=@LIBS_SYSTEM@ ## -lm, or empty. LIB_MATH=@LIB_MATH@ -## -lpthreads, or empty. +## -lpthread, or empty. LIB_PTHREAD=@LIB_PTHREAD@ LIBIMAGE=@LIBTIFF@ @LIBJPEG@ @LIBPNG@ @LIBGIF@ @LIBXPM@ @@ -230,6 +232,9 @@ XRANDR_CFLAGS = @XRANDR_CFLAGS@ XINERAMA_LIBS = @XINERAMA_LIBS@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ + ## widget.o if USE_X_TOOLKIT, otherwise empty. WIDGET_OBJ=@WIDGET_OBJ@ @@ -245,7 +250,7 @@ MSDOS_OBJ = MSDOS_X_OBJ = NS_OBJ=@NS_OBJ@ -## nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o macfont.o if HAVE_NS. +## nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o ns_fontfile if HAVE_NS. NS_OBJC_OBJ=@NS_OBJC_OBJ@ ## Only set if NS_IMPL_GNUSTEP. GNU_OBJC_CFLAGS=@GNU_OBJC_CFLAGS@ @@ -286,26 +291,39 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@ LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ -LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ - INTERVALS_H = dispextern.h intervals.h composite.h GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ RUN_TEMACS = ./temacs -## Invoke ../nt/addsection for MinGW, ":" elsewhere. -TEMACS_POST_LINK = @TEMACS_POST_LINK@ -ADDSECTION = @ADDSECTION@ -EMACS_HEAPSIZE = @EMACS_HEAPSIZE@ -MINGW_TEMACS_POST_LINK = \ - mv temacs$(EXEEXT) temacs.tmp; \ - ../nt/addsection temacs.tmp temacs$(EXEEXT) EMHEAP $(EMACS_HEAPSIZE) - UNEXEC_OBJ = @UNEXEC_OBJ@ CANNOT_DUMP=@CANNOT_DUMP@ +# 'make' verbosity. +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ + +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = + +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = + +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = + +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = + DEPDIR=deps ## -MMD -MF $(DEPDIR)/$*.d if AUTO_DEPEND; else empty. DEPFLAGS=@DEPFLAGS@ @@ -322,10 +340,11 @@ MKDEPDIR=@MKDEPDIR@ ## ## FIXME? MYCPPFLAGS only referenced in etc/DEBUG. ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ - -I$(lib) -I$(srcdir)/../lib \ + -I$(lib) -I$(top_srcdir)/lib \ $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ - $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) \ + $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ + $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) \ @@ -335,10 +354,10 @@ ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) .SUFFIXES: .m .c.o: @$(MKDEPDIR) - $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $(PROFILING_CFLAGS) $< + $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $(PROFILING_CFLAGS) $< .m.o: @$(MKDEPDIR) - $(CC) -c $(CPPFLAGS) $(ALL_OBJC_CFLAGS) $(PROFILING_CFLAGS) $< + $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_OBJC_CFLAGS) $(PROFILING_CFLAGS) $< ## lastfile must follow all files whose initialized data areas should ## be dumped as pure by dump-emacs. @@ -405,29 +424,33 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ - $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) \ + $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ - $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \ + $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \ $(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) all: emacs$(EXEEXT) $(OTHER_FILES) .PHONY: all $(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT) - cd ../leim && $(MAKE) $(MFLAGS) leim-list.el EMACS="$(bootstrap_exe)" + $(MAKE) -C ../leim leim-list.el EMACS="$(bootstrap_exe)" +## FORCE it so that admin/unidata can decide whether these files +## are up-to-date. Although since charprop depends on bootstrap-emacs, +## and emacs (which recreates bootstrap-emacs) depends on charprop, +## in practice this rule was always run anyway. $(srcdir)/macuvs.h $(lispsource)/international/charprop.el: \ - bootstrap-emacs$(EXEEXT) - cd ../admin/unidata && $(MAKE) $(MFLAGS) all EMACS="../$(bootstrap_exe)" + bootstrap-emacs$(EXEEXT) FORCE + $(MAKE) -C ../admin/unidata all EMACS="../$(bootstrap_exe)" ## The dumped Emacs is as functional and more efficient than ## bootstrap-emacs, so we replace the latter with the former. ## Strictly speaking, emacs does not depend directly on all of $lisp, ## since not all pieces are used on all platforms. But DOC depends ## on all of $lisp, and emacs depends on DOC, so it is ok to use $lisp here. -emacs$(EXEEXT): temacs$(EXEEXT) $(ADDSECTION) \ +emacs$(EXEEXT): temacs$(EXEEXT) \ $(etc)/DOC $(lisp) $(leimdir)/leim-list.el \ $(lispsource)/international/charprop.el if test "$(CANNOT_DUMP)" = "yes"; then \ @@ -436,7 +459,9 @@ emacs$(EXEEXT): temacs$(EXEEXT) $(ADDSECTION) \ else \ LC_ALL=C $(RUN_TEMACS) -batch -l loadup dump || exit 1; \ test "X$(PAXCTL)" = X || $(PAXCTL) -zex emacs$(EXEEXT); \ - rm -f bootstrap-emacs$(EXEEXT); \ + while test -f bootstrap-emacs$(EXEEXT); do \ + rm -f bootstrap-emacs$(EXEEXT); \ + done; \ ln emacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \ fi @@ -455,34 +480,37 @@ emacs$(EXEEXT): temacs$(EXEEXT) $(ADDSECTION) \ ## in the contents of the DOC file. ## $(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(obj) $(lisp) - $(MKDIR_P) $(etc) - -rm -f $(etc)/DOC - $(libsrc)/make-docfile -d $(srcdir) $(SOME_MACHINE_OBJECTS) $(obj) > $(etc)/DOC - $(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) `sed -n -e 's| \\\\||' -e 's|^[ ]*$$(lispsource)/||p' $(srcdir)/lisp.mk` + $(AM_V_GEN)$(MKDIR_P) $(etc) + -$(AM_V_at)rm -f $(etc)/DOC + $(AM_V_at)$(libsrc)/make-docfile -d $(srcdir) \ + $(SOME_MACHINE_OBJECTS) $(obj) > $(etc)/DOC + $(AM_V_at)$(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) \ + `sed -n -e 's| \\\\||' -e 's|^[ ]*$$(lispsource)/||p' \ + $(srcdir)/lisp.mk` $(libsrc)/make-docfile$(EXEEXT): - cd $(libsrc); $(MAKE) $(MFLAGS) make-docfile$(EXEEXT) + $(MAKE) -C $(libsrc) make-docfile$(EXEEXT) buildobj.h: Makefile - for i in $(ALLOBJS); do \ + $(AM_V_GEN)for i in $(ALLOBJS); do \ echo "$$i" | sed 's,.*/,,; s/\.obj$$/\.o/; s/^/"/; s/$$/",/' \ || exit; \ done >$@.tmp - mv $@.tmp $@ + $(AM_V_at)mv $@.tmp $@ globals.h: gl-stamp; @true GLOBAL_SOURCES = $(base_obj:.o=.c) $(NS_OBJC_OBJ:.o=.m) gl-stamp: $(libsrc)/make-docfile$(EXEEXT) $(GLOBAL_SOURCES) - $(libsrc)/make-docfile -d $(srcdir) -g $(obj) > gl.tmp - $(srcdir)/../build-aux/move-if-change gl.tmp globals.h - echo timestamp > $@ + $(AM_V_GEN)$(libsrc)/make-docfile -d $(srcdir) -g $(obj) > gl.tmp + $(AM_V_at)$(top_srcdir)/build-aux/move-if-change gl.tmp globals.h + $(AM_V_at)echo timestamp > $@ $(ALLOBJS): globals.h $(lib)/libgnu.a: $(config_h) - cd $(lib) && $(MAKE) libgnu.a + $(MAKE) -C $(lib) libgnu.a ## We have to create $(etc) here because init_cmdargs tests its ## existence when setting Vinstallation_directory (FIXME?). @@ -490,10 +518,9 @@ $(lib)/libgnu.a: $(config_h) ## to start if Vinstallation_directory has the wrong value. temacs$(EXEEXT): $(LIBXMENU) $(ALLOBJS) \ $(lib)/libgnu.a $(EMACSRES) - $(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \ + $(AM_V_CCLD)$(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \ -o temacs $(ALLOBJS) $(lib)/libgnu.a $(W32_RES_LINK) $(LIBES) $(MKDIR_P) $(etc) - $(TEMACS_POST_LINK) test "$(CANNOT_DUMP)" = "yes" || \ test "X$(PAXCTL)" = X || $(PAXCTL) -r temacs$(EXEEXT) test "$(CANNOT_DUMP)" = "yes" || test -z "$(SETFATTR)" || \ @@ -502,37 +529,40 @@ temacs$(EXEEXT): $(LIBXMENU) $(ALLOBJS) \ ## The following oldxmenu-related rules are only (possibly) used if ## HAVE_X11 && !USE_GTK, but there is no harm in always defining them. $(lwlibdir)/liblw.a: $(config_h) globals.h lisp.h FORCE - cd $(lwlibdir) && \ - $(MAKE) $(MFLAGS) CC='$(CC)' CFLAGS='$(CFLAGS)' MAKE='$(MAKE)' \ - liblw.a + $(MAKE) -C $(lwlibdir) liblw.a $(oldXMenudir)/libXMenu11.a: FORCE - cd $(oldXMenudir) && \ - $(MAKE) $(MFLAGS) CC='$(CC)' CFLAGS='$(CFLAGS)' MAKE='$(MAKE)' \ - libXMenu11.a + $(MAKE) -C $(oldXMenudir) libXMenu11.a FORCE: .PHONY: FORCE -../config.status: config.in epaths.in - @echo "The file ${?:.in=.h} needs to be set up from $?." - @echo "Please run the 'configure' script again." - exit 1 +ACLOCAL_INPUTS = $(top_srcdir)/configure.ac $(wildcard $(top_srcdir)/m4/*.m4) +AUTOCONF_INPUTS = $(top_srcdir)/configure.ac $(top_srcdir)/aclocal.m4 +$(top_srcdir)/aclocal.m4: $(ACLOCAL_INPUTS) +$(top_srcdir)/configure config.in: $(AUTOCONF_INPUTS) +.PRECIOUS: ../config.status Makefile +../config.status: $(top_srcdir)/configure $(top_srcdir)/lisp/version.el +Makefile: ../config.status $(srcdir)/Makefile.in +$(top_srcdir)/aclocal.m4 $(top_srcdir)/configure config.in ../config.status \ + Makefile: + $(MAKE) -C .. am--refresh doc.o: buildobj.h emacs.res: $(ntsource)/emacs.rc \ $(ntsource)/icons/emacs.ico \ $(ntsource)/$(EMACS_MANIFEST) - $(WINDRES) -O COFF --include-dir=$(srcdir)/../nt \ + $(WINDRES) -O COFF --include-dir=$(top_srcdir)/nt \ -o $@ $(ntsource)/emacs.rc +.PHONY: ns-app ns-app: emacs$(EXEEXT) - cd ../nextstep && $(MAKE) $(MFLAGS) all + $(MAKE) -C ../nextstep all .PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean .PHONY: versionclean extraclean mostlyclean: - rm -f temacs$(EXEEXT) core *.core \#* *.o libXMenu11.a liblw.a + rm -f temacs$(EXEEXT) core *.core \#* *.o rm -f ../etc/DOC rm -f bootstrap-emacs$(EXEEXT) emacs-$(version)$(EXEEXT) rm -f buildobj.h @@ -585,10 +615,10 @@ TAGS: $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2) $(srcdir)/$(ctagsfiles3) ## Arrange to make tags tables for ../lisp and ../lwlib, ## which the above TAGS file for the C files includes by reference. ../lisp/TAGS: - cd ../lisp && $(MAKE) TAGS ETAGS="$(ETAGS)" + $(MAKE) -C ../lisp TAGS ETAGS="$(ETAGS)" $(lwlibdir)/TAGS: - cd $(lwlibdir) && $(MAKE) TAGS ETAGS="$(ETAGS)" + $(MAKE) -C $(lwlibdir) TAGS ETAGS="$(ETAGS)" tags: TAGS ../lisp/TAGS $(lwlibdir)/TAGS .PHONY: tags @@ -601,47 +631,34 @@ tags: TAGS ../lisp/TAGS $(lwlibdir)/TAGS ## such as loaddefs.el or *.elc can typically be produced by any old ## Emacs executable, so we would like to avoid rebuilding them whenever ## we build a new Emacs executable. +## +## (In other words, changing a single file src/foo.c would force +## dumping a new bootstrap-emacs, then re-byte-compiling all preloaded +## elisp files, and only then dump the actual src/emacs, which is not +## wrong, but is overkill in 99.99% of the cases.) +## ## To solve the circularity, we use 2 different Emacs executables, ## "emacs" is the main target and "bootstrap-emacs" is the one used ## to build the *.elc and loaddefs.el files. -## To solve the freshness issue, we used to use a third file "witness-emacs" -## which was used to witness the fact that there is a bootstrap-emacs -## executable, and then have dependencies on witness-emacs rather than -## bootstrap-emacs, but that lead to problems in parallel builds (because -## witness-emacs needed to be free from dependencies (to avoid rebuilding -## it), so it was compiled in parallel, leading typically to having 2 -## processes dumping bootstrap-emacs at the same time). -## So instead, we replace the witness-emacs dependencies by conditional -## bootstrap-dependencies (via $(BOOTSTRAPEMACS)). Of course, since we do -## not want to rely on GNU Make features, we have to rely on an external -## script to do the conditional part of the dependency -## (i.e. see the $(SUBDIR) rule ../Makefile.in). - -.SUFFIXES: .elc .el - -## These suffix rules do not allow additional dependencies, sadly, so -## instead of adding a $(BOOTSTRAPEMACS) dependency here, we add it -## separately below. -## With GNU Make, we would just say "%.el : %.elc $(BOOTSTRAPEMACS)" -.el.elc: - @cd ../lisp; $(MAKE) $(MFLAGS) compile-onefile \ - THEFILE=$< EMACS="$(bootstrap_exe)" - -## Since the .el.elc rule cannot specify an extra dependency, we do it here. -$(lisp): $(BOOTSTRAPEMACS) +## To solve the freshness issue, in the past we tried various clever tricks, +## but now that we require GNU make, we can simply specify +## bootstrap-emacs$(EXEEXT) as an order-only prerequisite. + +%.elc: %.el | bootstrap-emacs$(EXEEXT) + @$(MAKE) -C ../lisp compile-onefile THEFILE=$< EMACS="$(bootstrap_exe)" ## VCSWITNESS points to the file that holds info about the current checkout. ## We use it as a heuristic to decide when to rebuild loaddefs.el. ## If empty it is ignored; the parent makefile can set it to some other value. VCSWITNESS = -$(lispsource)/loaddefs.el: $(BOOTSTRAPEMACS) $(VCSWITNESS) - cd ../lisp; $(MAKE) $(MFLAGS) autoloads EMACS="$(bootstrap_exe)" +$(lispsource)/loaddefs.el: $(VCSWITNESS) | bootstrap-emacs$(EXEEXT) + $(MAKE) -C ../lisp autoloads EMACS="$(bootstrap_exe)" ## Dump an Emacs executable named bootstrap-emacs containing the ## files from loadup.el in source form. bootstrap-emacs$(EXEEXT): temacs$(EXEEXT) - cd ../lisp; $(MAKE) $(MFLAGS) update-subdirs + $(MAKE) -C ../lisp update-subdirs if test "$(CANNOT_DUMP)" = "yes"; then \ rm -f bootstrap-emacs$(EXEEXT); \ ln temacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \ @@ -651,7 +668,7 @@ bootstrap-emacs$(EXEEXT): temacs$(EXEEXT) mv -f emacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \ fi @: Compile some files earlier to speed up further compilation. - cd ../lisp; $(MAKE) $(MFLAGS) compile-first EMACS="$(bootstrap_exe)" + $(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)" ## Insert either autodeps.mk (if AUTO_DEPEND), else deps.mk. @deps_frag@ diff --git a/src/alloc.c b/src/alloc.c index a3f3f5478cb..faad0b59c87 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -47,6 +47,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif /* HAVE_WINDOW_SYSTEM */ #include <verify.h> +#include <execinfo.h> /* For backtrace. */ + +#ifdef HAVE_LINUX_SYSINFO +#include <sys/sysinfo.h> +#endif + +#ifdef MSDOS +#include "dosfns.h" /* For dos_memory_info. */ +#endif #if (defined ENABLE_CHECKING \ && defined HAVE_VALGRIND_VALGRIND_H \ @@ -71,7 +80,7 @@ static bool valgrind_p; marked objects. */ #if (defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC \ - || defined GC_CHECK_MARKED_OBJECTS) + || defined HYBRID_MALLOC || defined GC_CHECK_MARKED_OBJECTS) #undef GC_MALLOC_CHECK #endif @@ -192,6 +201,35 @@ static ptrdiff_t pure_bytes_used_non_lisp; const char *pending_malloc_warning; +#if 0 /* Normally, pointer sanity only on request... */ +#ifdef ENABLE_CHECKING +#define SUSPICIOUS_OBJECT_CHECKING 1 +#endif +#endif + +/* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC + bug is unresolved. */ +#define SUSPICIOUS_OBJECT_CHECKING 1 + +#ifdef SUSPICIOUS_OBJECT_CHECKING +struct suspicious_free_record +{ + void *suspicious_object; + void *backtrace[128]; +}; +static void *suspicious_objects[32]; +static int suspicious_object_index; +struct suspicious_free_record suspicious_free_history[64] EXTERNALLY_VISIBLE; +static int suspicious_free_history_index; +/* Find the first currently-monitored suspicious pointer in range + [begin,end) or NULL if no such pointer exists. */ +static void *find_suspicious_object_in_range (void *begin, void *end); +static void detect_suspicious_free (void *ptr); +#else +# define find_suspicious_object_in_range(begin, end) NULL +# define detect_suspicious_free(ptr) (void) +#endif + /* Maximum amount of C stack to save when a GC happens. */ #ifndef MAX_SAVE_STACK @@ -247,7 +285,7 @@ static void gc_sweep (void); static Lisp_Object make_pure_vector (ptrdiff_t); static void mark_buffer (struct buffer *); -#if !defined REL_ALLOC || defined SYSTEM_MALLOC +#if !defined REL_ALLOC || defined SYSTEM_MALLOC || defined HYBRID_MALLOC static void refill_memory_reserve (void); #endif static void compact_small_strings (void); @@ -403,6 +441,23 @@ XFLOAT_INIT (Lisp_Object f, double n) XFLOAT (f)->u.data = n; } +static bool +pointers_fit_in_lispobj_p (void) +{ + return (UINTPTR_MAX <= VAL_MAX) || USE_LSB_TAG; +} + +static bool +mmap_lisp_allowed_p (void) +{ + /* If we can't store all memory addresses in our lisp objects, it's + risky to let the heap use mmap and give us addresses from all + over our address space. We also can't use mmap for lisp objects + if we might dump: unexec doesn't preserve the contents of mmapped + regions. */ + return pointers_fit_in_lispobj_p () && !might_dump; +} + /************************************************************************ Malloc @@ -959,10 +1014,17 @@ lisp_free (void *block) clang 3.3 anyway. */ #if ! ADDRESS_SANITIZER -# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC +# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC # define USE_ALIGNED_ALLOC 1 /* Defined in gmalloc.c. */ void *aligned_alloc (size_t, size_t); +# elif defined HYBRID_MALLOC +# if defined ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN +# define USE_ALIGNED_ALLOC 1 +# define aligned_alloc hybrid_aligned_alloc +/* Defined in gmalloc.c. */ +void *aligned_alloc (size_t, size_t); +# endif # elif defined HAVE_ALIGNED_ALLOC # define USE_ALIGNED_ALLOC 1 # elif defined HAVE_POSIX_MEMALIGN @@ -1073,10 +1135,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) intptr_t aligned; /* int gets warning casting to 64-bit pointer. */ #ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. */ - mallopt (M_MMAP_MAX, 0); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, 0); #endif #ifdef USE_ALIGNED_ALLOC @@ -1097,8 +1157,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) ((void **) abase)[-1] = base; #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif #if ! USE_LSB_TAG @@ -1733,23 +1793,15 @@ allocate_string_data (struct Lisp_String *s, size_t size = offsetof (struct sblock, data) + needed; #ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. - - In case you think of allowing it in a dumped Emacs at the - cost of not being able to re-dump, there's another reason: - mmap'ed data typically have an address towards the top of the - address space, which won't fit into an EMACS_INT (at least on - 32-bit systems with the current tagging scheme). --fx */ - mallopt (M_MMAP_MAX, 0); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, 0); #endif b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif b->next_free = b->data; @@ -1810,6 +1862,7 @@ allocate_string_data (struct Lisp_String *s, /* Sweep and compact strings. */ +NO_INLINE /* For better stack traces */ static void sweep_strings (void) { @@ -2093,7 +2146,7 @@ bool_vector_fill (Lisp_Object a, Lisp_Object init) unsigned char *data = bool_vector_uchar_data (a); int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; ptrdiff_t nbytes = bool_vector_bytes (nbits); - int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); + int last_mask = ~ (~0u << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); memset (data, pattern, nbytes - 1); data[nbytes - 1] = pattern & last_mask; } @@ -2136,6 +2189,21 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) return bool_vector_fill (val, init); } +DEFUN ("bool-vector", Fbool_vector, Sbool_vector, 0, MANY, 0, + doc: /* Return a new bool-vector with specified arguments as elements. +Any number of arguments, even zero arguments, are allowed. +usage: (bool-vector &rest OBJECTS) */) + (ptrdiff_t nargs, Lisp_Object *args) +{ + ptrdiff_t i; + Lisp_Object vector; + + vector = make_uninit_bool_vector (nargs); + for (i = 0; i < nargs; i++) + bool_vector_set (vector, i, !NILP (args[i])); + + return vector; +} /* Make a string from NBYTES bytes at CONTENTS, and compute the number of characters from the contents. This string may be unibyte or @@ -2158,7 +2226,6 @@ make_string (const char *contents, ptrdiff_t nbytes) return val; } - /* Make an unibyte string from LENGTH bytes at CONTENTS. */ Lisp_Object @@ -2294,21 +2361,21 @@ make_formatted_string (char *buf, const char *format, ...) #define FLOAT_BLOCK_SIZE \ (((BLOCK_BYTES - sizeof (struct float_block *) \ /* The compiler might add padding at the end. */ \ - - (sizeof (struct Lisp_Float) - sizeof (int))) * CHAR_BIT) \ + - (sizeof (struct Lisp_Float) - sizeof (bits_word))) * CHAR_BIT) \ / (sizeof (struct Lisp_Float) * CHAR_BIT + 1)) #define GETMARKBIT(block,n) \ - (((block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ - >> ((n) % (sizeof (int) * CHAR_BIT))) \ + (((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \ + >> ((n) % BITS_PER_BITS_WORD)) \ & 1) #define SETMARKBIT(block,n) \ - (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ - |= 1 << ((n) % (sizeof (int) * CHAR_BIT)) + ((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \ + |= (bits_word) 1 << ((n) % BITS_PER_BITS_WORD)) #define UNSETMARKBIT(block,n) \ - (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ - &= ~(1 << ((n) % (sizeof (int) * CHAR_BIT))) + ((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \ + &= ~((bits_word) 1 << ((n) % BITS_PER_BITS_WORD))) #define FLOAT_BLOCK(fptr) \ ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))) @@ -2320,7 +2387,7 @@ struct float_block { /* Place `floats' at the beginning, to ease up FLOAT_INDEX's job. */ struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; - int gcmarkbits[1 + FLOAT_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)]; + bits_word gcmarkbits[1 + FLOAT_BLOCK_SIZE / BITS_PER_BITS_WORD]; struct float_block *next; }; @@ -2401,7 +2468,7 @@ make_float (double float_value) #define CONS_BLOCK_SIZE \ (((BLOCK_BYTES - sizeof (struct cons_block *) \ /* The compiler might add padding at the end. */ \ - - (sizeof (struct Lisp_Cons) - sizeof (int))) * CHAR_BIT) \ + - (sizeof (struct Lisp_Cons) - sizeof (bits_word))) * CHAR_BIT) \ / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1)) #define CONS_BLOCK(fptr) \ @@ -2414,7 +2481,7 @@ struct cons_block { /* Place `conses' at the beginning, to ease up CONS_INDEX's job. */ struct Lisp_Cons conses[CONS_BLOCK_SIZE]; - int gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)]; + bits_word gcmarkbits[1 + CONS_BLOCK_SIZE / BITS_PER_BITS_WORD]; struct cons_block *next; }; @@ -2550,29 +2617,28 @@ list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, L Lisp_Object listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...) { - va_list ap; - ptrdiff_t i; - Lisp_Object val, *objp; + Lisp_Object (*cons) (Lisp_Object, Lisp_Object); + switch (type) + { + case CONSTYPE_PURE: cons = pure_cons; break; + case CONSTYPE_HEAP: cons = Fcons; break; + default: emacs_abort (); + } - /* Change to SAFE_ALLOCA if you hit this eassert. */ - eassert (count <= MAX_ALLOCA / word_size); + eassume (0 < count); + Lisp_Object val = cons (arg, Qnil); + Lisp_Object tail = val; - objp = alloca (count * word_size); - objp[0] = arg; + va_list ap; va_start (ap, arg); - for (i = 1; i < count; i++) - objp[i] = va_arg (ap, Lisp_Object); - va_end (ap); - - for (val = Qnil, i = count - 1; i >= 0; i--) + for (ptrdiff_t i = 1; i < count; i++) { - if (type == CONSTYPE_PURE) - val = pure_cons (objp[i], val); - else if (type == CONSTYPE_HEAP) - val = Fcons (objp[i], val); - else - emacs_abort (); + Lisp_Object elem = cons (va_arg (ap, Lisp_Object), Qnil); + XSETCDR (tail, elem); + tail = elem; } + va_end (ap); + return val; } @@ -2651,20 +2717,16 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, pointer cannot be tagged, represent it with a Lisp 0. Usually you don't want to touch this. */ -enum { TAGGABLE_NULL = (DATA_SEG_BITS & ~VALMASK) == 0 }; - static struct Lisp_Vector * next_vector (struct Lisp_Vector *v) { - if (! TAGGABLE_NULL && EQ (v->contents[0], make_number (0))) - return 0; return XUNTAG (v->contents[0], 0); } static void set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p) { - v->contents[0] = TAGGABLE_NULL || p ? make_lisp_ptr (p, 0) : make_number (0); + v->contents[0] = make_lisp_ptr (p, 0); } /* This value is balanced well enough to avoid too much internal overhead @@ -2920,6 +2982,7 @@ vector_nbytes (struct Lisp_Vector *v) static void cleanup_vector (struct Lisp_Vector *vector) { + detect_suspicious_free (vector); if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT) && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX)) @@ -2939,6 +3002,7 @@ cleanup_vector (struct Lisp_Vector *vector) /* Reclaim space used by unmarked vectors. */ +NO_INLINE /* For better stack traces */ static void sweep_vectors (void) { @@ -2993,7 +3057,7 @@ sweep_vectors (void) if (vector == (struct Lisp_Vector *) block->data && !VECTOR_IN_BLOCK (next, block)) - /* This block should be freed because all of it's + /* This block should be freed because all of its space was coalesced into the only free vector. */ free_this_block = 1; else @@ -3063,10 +3127,8 @@ allocate_vectorlike (ptrdiff_t len) size_t nbytes = header_size + len * word_size; #ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. */ - mallopt (M_MMAP_MAX, 0); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, 0); #endif if (nbytes <= VBLOCK_BYTES_MAX) @@ -3083,10 +3145,13 @@ allocate_vectorlike (ptrdiff_t len) } #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif + if (find_suspicious_object_in_range (p, (char *) p + nbytes)) + emacs_abort (); + consing_since_gc += nbytes; vector_cells_consed += len; } @@ -3222,7 +3287,6 @@ See also the function `vector'. */) return vector; } - DEFUN ("vector", Fvector, Svector, 0, MANY, 0, doc: /* Return a newly created vector with specified arguments as elements. Any number of arguments, even zero arguments, are allowed. @@ -3741,7 +3805,7 @@ memory_full (size_t nbytes) memory_full_cons_threshold = sizeof (struct cons_block); /* The first time we get here, free the spare memory. */ - for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++) + for (i = 0; i < ARRAYELTS (spare_memory); i++) if (spare_memory[i]) { if (i == 0) @@ -3769,7 +3833,7 @@ memory_full (size_t nbytes) void refill_memory_reserve (void) { -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC if (spare_memory[0] == 0) spare_memory[0] = malloc (SPARE_MEMORY); if (spare_memory[1] == 0) @@ -4502,6 +4566,15 @@ mark_maybe_object (Lisp_Object obj) } } +/* Return true if P can point to Lisp data, and false otherwise. + USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. + Otherwise, assume that Lisp data is aligned on even addresses. */ + +static bool +maybe_lisp_pointer (void *p) +{ + return !((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2)); +} /* If P points to Lisp data, mark that as live if it isn't already marked. */ @@ -4516,10 +4589,7 @@ mark_maybe_pointer (void *p) VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p)); #endif - /* Quickly rule out some values which can't point to Lisp data. - USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. - Otherwise, assume that Lisp data is aligned on even addresses. */ - if ((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2)) + if (!maybe_lisp_pointer (p)) return; m = mem_find (p); @@ -4831,61 +4901,8 @@ dump_zombies (void) from the stack start. */ static void -mark_stack (void) +mark_stack (void *end) { - void *end; - -#ifdef HAVE___BUILTIN_UNWIND_INIT - /* Force callee-saved registers and register windows onto the stack. - This is the preferred method if available, obviating the need for - machine dependent methods. */ - __builtin_unwind_init (); - end = &end; -#else /* not HAVE___BUILTIN_UNWIND_INIT */ -#ifndef GC_SAVE_REGISTERS_ON_STACK - /* jmp_buf may not be aligned enough on darwin-ppc64 */ - union aligned_jmpbuf { - Lisp_Object o; - sys_jmp_buf j; - } j; - volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; -#endif - /* This trick flushes the register windows so that all the state of - the process is contained in the stack. */ - /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is - needed on ia64 too. See mach_dep.c, where it also says inline - assembler doesn't work with relevant proprietary compilers. */ -#ifdef __sparc__ -#if defined (__sparc64__) && defined (__FreeBSD__) - /* FreeBSD does not have a ta 3 handler. */ - asm ("flushw"); -#else - asm ("ta 3"); -#endif -#endif - - /* Save registers that we need to see on the stack. We need to see - registers used to hold register variables and registers used to - pass parameters. */ -#ifdef GC_SAVE_REGISTERS_ON_STACK - GC_SAVE_REGISTERS_ON_STACK (end); -#else /* not GC_SAVE_REGISTERS_ON_STACK */ - -#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that - setjmp will definitely work, test it - and print a message with the result - of the test. */ - if (!setjmp_tested_p) - { - setjmp_tested_p = 1; - test_setjmp (); - } -#endif /* GC_SETJMP_WORKS */ - - sys_setjmp (j.j); - end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; -#endif /* not GC_SAVE_REGISTERS_ON_STACK */ -#endif /* not HAVE___BUILTIN_UNWIND_INIT */ /* This assumes that the stack is a contiguous region in memory. If that's not the case, something has to be done here to iterate @@ -5015,9 +5032,34 @@ valid_lisp_object_p (Lisp_Object obj) #endif } +/* If GC_MARK_STACK, return 1 if STR is a relocatable data of Lisp_String + (i.e. there is a non-pure Lisp_Object X so that SDATA (X) == STR) and 0 + if not. Otherwise we can't rely on valid_lisp_object_p and return -1. + This function is slow and should be used for debugging purposes. */ +int +relocatable_string_data_p (const char *str) +{ + if (PURE_POINTER_P (str)) + return 0; +#if GC_MARK_STACK + if (str) + { + struct sdata *sdata + = (struct sdata *) (str - offsetof (struct sdata, data)); + + if (valid_pointer_p (sdata) + && valid_pointer_p (sdata->string) + && maybe_lisp_pointer (sdata->string)) + return (valid_lisp_object_p + (make_lisp_ptr (sdata->string, Lisp_String)) + && (const char *) sdata->string->data == str); + } + return 0; +#endif /* GC_MARK_STACK */ + return -1; +} - /*********************************************************************** Pure Storage Management ***********************************************************************/ @@ -5493,22 +5535,15 @@ mark_pinned_symbols (void) } } -DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", - doc: /* Reclaim storage for Lisp objects no longer needed. -Garbage collection happens automatically if you cons more than -`gc-cons-threshold' bytes of Lisp data since previous garbage collection. -`garbage-collect' normally returns a list with info on amount of space in use, -where each entry has the form (NAME SIZE USED FREE), where: -- NAME is a symbol describing the kind of objects this entry represents, -- SIZE is the number of bytes used by each one, -- USED is the number of those objects that were found live in the heap, -- FREE is the number of those objects that are not live but that Emacs - keeps around for future allocations (maybe because it does not know how - to return them to the OS). -However, if there was overflow in pure space, `garbage-collect' -returns nil, because real GC can't be done. -See Info node `(elisp)Garbage Collection'. */) - (void) +/* Subroutine of Fgarbage_collect that does most of the work. It is a + separate function so that we could limit mark_stack in searching + the stack frames below this function, thus avoiding the rare cases + where mark_stack finds values that look like live Lisp objects on + portions of stack that couldn't possibly contain such live objects. + For more details of this, see the discussion at + http://lists.gnu.org/archive/html/emacs-devel/2014-05/msg00270.html. */ +static Lisp_Object +garbage_collect_1 (void *end) { struct buffer *nextb; char stack_top_variable; @@ -5606,7 +5641,7 @@ See Info node `(elisp)Garbage Collection'. */) #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS) - mark_stack (); + mark_stack (end); #else { register struct gcpro *tail; @@ -5629,7 +5664,7 @@ See Info node `(elisp)Garbage Collection'. */) #endif #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES - mark_stack (); + mark_stack (end); #endif /* Everything is now marked, except for the data in font caches @@ -5789,6 +5824,87 @@ See Info node `(elisp)Garbage Collection'. */) return retval; } +DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", + doc: /* Reclaim storage for Lisp objects no longer needed. +Garbage collection happens automatically if you cons more than +`gc-cons-threshold' bytes of Lisp data since previous garbage collection. +`garbage-collect' normally returns a list with info on amount of space in use, +where each entry has the form (NAME SIZE USED FREE), where: +- NAME is a symbol describing the kind of objects this entry represents, +- SIZE is the number of bytes used by each one, +- USED is the number of those objects that were found live in the heap, +- FREE is the number of those objects that are not live but that Emacs + keeps around for future allocations (maybe because it does not know how + to return them to the OS). +However, if there was overflow in pure space, `garbage-collect' +returns nil, because real GC can't be done. +See Info node `(elisp)Garbage Collection'. */) + (void) +{ +#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ + || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS \ + || GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES) + void *end; + +#ifdef HAVE___BUILTIN_UNWIND_INIT + /* Force callee-saved registers and register windows onto the stack. + This is the preferred method if available, obviating the need for + machine dependent methods. */ + __builtin_unwind_init (); + end = &end; +#else /* not HAVE___BUILTIN_UNWIND_INIT */ +#ifndef GC_SAVE_REGISTERS_ON_STACK + /* jmp_buf may not be aligned enough on darwin-ppc64 */ + union aligned_jmpbuf { + Lisp_Object o; + sys_jmp_buf j; + } j; + volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; +#endif + /* This trick flushes the register windows so that all the state of + the process is contained in the stack. */ + /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is + needed on ia64 too. See mach_dep.c, where it also says inline + assembler doesn't work with relevant proprietary compilers. */ +#ifdef __sparc__ +#if defined (__sparc64__) && defined (__FreeBSD__) + /* FreeBSD does not have a ta 3 handler. */ + asm ("flushw"); +#else + asm ("ta 3"); +#endif +#endif + + /* Save registers that we need to see on the stack. We need to see + registers used to hold register variables and registers used to + pass parameters. */ +#ifdef GC_SAVE_REGISTERS_ON_STACK + GC_SAVE_REGISTERS_ON_STACK (end); +#else /* not GC_SAVE_REGISTERS_ON_STACK */ + +#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that + setjmp will definitely work, test it + and print a message with the result + of the test. */ + if (!setjmp_tested_p) + { + setjmp_tested_p = 1; + test_setjmp (); + } +#endif /* GC_SETJMP_WORKS */ + + sys_setjmp (j.j); + end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; +#endif /* not GC_SAVE_REGISTERS_ON_STACK */ +#endif /* not HAVE___BUILTIN_UNWIND_INIT */ + return garbage_collect_1 (end); +#elif (GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE) + /* Old GCPROs-based method without stack marking. */ + return garbage_collect_1 (NULL); +#else + emacs_abort (); +#endif /* GC_MARK_STACK */ +} /* Mark Lisp objects in glyph matrix MATRIX. Currently the only interesting objects referenced from glyphs are strings. */ @@ -5854,14 +5970,15 @@ mark_vectorlike (struct Lisp_Vector *ptr) symbols. */ static void -mark_char_table (struct Lisp_Vector *ptr) +mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype) { int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; + /* Consult the Lisp_Sub_Char_Table layout before changing this. */ + int i, idx = (pvectype == PVEC_SUB_CHAR_TABLE ? SUB_CHAR_TABLE_OFFSET : 0); eassert (!VECTOR_MARKED_P (ptr)); VECTOR_MARK (ptr); - for (i = 0; i < size; i++) + for (i = idx; i < size; i++) { Lisp_Object val = ptr->contents[i]; @@ -5870,13 +5987,26 @@ mark_char_table (struct Lisp_Vector *ptr) if (SUB_CHAR_TABLE_P (val)) { if (! VECTOR_MARKED_P (XVECTOR (val))) - mark_char_table (XVECTOR (val)); + mark_char_table (XVECTOR (val), PVEC_SUB_CHAR_TABLE); } else mark_object (val); } } +NO_INLINE /* To reduce stack depth in mark_object. */ +static Lisp_Object +mark_compiled (struct Lisp_Vector *ptr) +{ + int i, size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; + + VECTOR_MARK (ptr); + for (i = 0; i < size; i++) + if (i != COMPILED_CONSTANTS) + mark_object (ptr->contents[i]); + return size > COMPILED_CONSTANTS ? ptr->contents[COMPILED_CONSTANTS] : Qnil; +} + /* Mark the chain of overlays starting at PTR. */ static void @@ -5885,8 +6015,9 @@ mark_overlay (struct Lisp_Overlay *ptr) for (; ptr && !ptr->gcmarkbit; ptr = ptr->next) { ptr->gcmarkbit = 1; - mark_object (ptr->start); - mark_object (ptr->end); + /* These two are always markers and can be marked fast. */ + XMARKER (ptr->start)->gcmarkbit = 1; + XMARKER (ptr->end)->gcmarkbit = 1; mark_object (ptr->plist); } } @@ -5917,6 +6048,7 @@ mark_buffer (struct buffer *buffer) /* Mark Lisp faces in the face cache C. */ +NO_INLINE /* To reduce stack depth in mark_object. */ static void mark_face_cache (struct face_cache *c) { @@ -5939,6 +6071,48 @@ mark_face_cache (struct face_cache *c) } } +NO_INLINE /* To reduce stack depth in mark_object. */ +static void +mark_localized_symbol (struct Lisp_Symbol *ptr) +{ + struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); + Lisp_Object where = blv->where; + /* If the value is set up for a killed buffer or deleted + frame, restore its global binding. If the value is + forwarded to a C variable, either it's not a Lisp_Object + var, or it's staticpro'd already. */ + if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) + || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) + swap_in_global_binding (ptr); + mark_object (blv->where); + mark_object (blv->valcell); + mark_object (blv->defcell); +} + +NO_INLINE /* To reduce stack depth in mark_object. */ +static void +mark_save_value (struct Lisp_Save_Value *ptr) +{ + /* If `save_type' is zero, `data[0].pointer' is the address + of a memory area containing `data[1].integer' potential + Lisp_Objects. */ + if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY) + { + Lisp_Object *p = ptr->data[0].pointer; + ptrdiff_t nelt; + for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++) + mark_maybe_object (*p); + } + else + { + /* Find Lisp_Objects in `data[N]' slots and mark them. */ + int i; + for (i = 0; i < SAVE_VALUE_SLOTS; i++) + if (save_type (ptr, i) == SAVE_OBJECT) + mark_object (ptr->data[i].object); + } +} + /* Remove killed buffers or items whose car is a killed buffer from LIST, and mark other items. Return changed LIST, which is marked. */ @@ -5966,7 +6140,13 @@ mark_discard_killed_buffers (Lisp_Object list) return list; } -/* Determine type of generic Lisp_Object and mark it accordingly. */ +/* Determine type of generic Lisp_Object and mark it accordingly. + + This function implements a straightforward depth-first marking + algorithm and so the recursion depth may be very high (a few + tens of thousands is not uncommon). To minimize stack usage, + a few cold paths are moved out to NO_INLINE functions above. + In general, inlining them doesn't help you to gain more speed. */ void mark_object (Lisp_Object arg) @@ -6083,22 +6263,13 @@ mark_object (Lisp_Object arg) break; case PVEC_COMPILED: - { /* We could treat this just like a vector, but it is better - to save the COMPILED_CONSTANTS element for last and avoid - recursion there. */ - int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; - - VECTOR_MARK (ptr); - for (i = 0; i < size; i++) - if (i != COMPILED_CONSTANTS) - mark_object (ptr->contents[i]); - if (size > COMPILED_CONSTANTS) - { - obj = ptr->contents[COMPILED_CONSTANTS]; - goto loop; - } - } + /* Although we could treat this just like a vector, mark_compiled + returns the COMPILED_CONSTANTS element, which is marked at the + next iteration of goto-loop here. This is done to avoid a few + recursive calls to mark_object. */ + obj = mark_compiled (ptr); + if (!NILP (obj)) + goto loop; break; case PVEC_FRAME: @@ -6163,7 +6334,8 @@ mark_object (Lisp_Object arg) break; case PVEC_CHAR_TABLE: - mark_char_table (ptr); + case PVEC_SUB_CHAR_TABLE: + mark_char_table (ptr, (enum pvec_type) pvectype); break; case PVEC_BOOL_VECTOR: @@ -6186,12 +6358,13 @@ mark_object (Lisp_Object arg) case Lisp_Symbol: { register struct Lisp_Symbol *ptr = XSYMBOL (obj); - struct Lisp_Symbol *ptrx; - + nextsym: if (ptr->gcmarkbit) break; CHECK_ALLOCATED_AND_LIVE (live_symbol_p); ptr->gcmarkbit = 1; + /* Attempt to catch bogus objects. */ + eassert (valid_lisp_object_p (ptr->function) >= 1); mark_object (ptr->function); mark_object (ptr->plist); switch (ptr->redirect) @@ -6205,21 +6378,8 @@ mark_object (Lisp_Object arg) break; } case SYMBOL_LOCALIZED: - { - struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); - Lisp_Object where = blv->where; - /* If the value is set up for a killed buffer or deleted - frame, restore it's global binding. If the value is - forwarded to a C variable, either it's not a Lisp_Object - var, or it's staticpro'd already. */ - if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) - || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) - swap_in_global_binding (ptr); - mark_object (blv->where); - mark_object (blv->valcell); - mark_object (blv->defcell); - break; - } + mark_localized_symbol (ptr); + break; case SYMBOL_FORWARDED: /* If the value is forwarded to a buffer or keyboard field, these are marked when we see the corresponding object. @@ -6231,14 +6391,10 @@ mark_object (Lisp_Object arg) if (!PURE_POINTER_P (XSTRING (ptr->name))) MARK_STRING (XSTRING (ptr->name)); MARK_INTERVAL_TREE (string_intervals (ptr->name)); - + /* Inner loop to mark next symbol in this bucket, if any. */ ptr = ptr->next; if (ptr) - { - ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun. */ - XSETSYMBOL (obj, ptrx); - goto loop; - } + goto nextsym; } break; @@ -6259,27 +6415,7 @@ mark_object (Lisp_Object arg) case Lisp_Misc_Save_Value: XMISCANY (obj)->gcmarkbit = 1; - { - struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); - /* If `save_type' is zero, `data[0].pointer' is the address - of a memory area containing `data[1].integer' potential - Lisp_Objects. */ - if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY) - { - Lisp_Object *p = ptr->data[0].pointer; - ptrdiff_t nelt; - for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++) - mark_maybe_object (*p); - } - else - { - /* Find Lisp_Objects in `data[N]' slots and mark them. */ - int i; - for (i = 0; i < SAVE_VALUE_SLOTS; i++) - if (save_type (ptr, i) == SAVE_OBJECT) - mark_object (ptr->data[i].object); - } - } + mark_save_value (XSAVE_VALUE (obj)); break; case Lisp_Misc_Overlay: @@ -6399,332 +6535,397 @@ survives_gc_p (Lisp_Object obj) -/* Sweep: find all structures not marked, and free them. */ +NO_INLINE /* For better stack traces */ static void -gc_sweep (void) +sweep_conses (void) { - /* Remove or mark entries in weak hash tables. - This must be done before any object is unmarked. */ - sweep_weak_hash_tables (); + struct cons_block *cblk; + struct cons_block **cprev = &cons_block; + int lim = cons_block_index; + EMACS_INT num_free = 0, num_used = 0; - sweep_strings (); - check_string_bytes (!noninteractive); + cons_free_list = 0; - /* Put all unmarked conses on free list. */ - { - register struct cons_block *cblk; - struct cons_block **cprev = &cons_block; - register int lim = cons_block_index; - EMACS_INT num_free = 0, num_used = 0; - - cons_free_list = 0; - - for (cblk = cons_block; cblk; cblk = *cprev) - { - register int i = 0; - int this_free = 0; - int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT; + for (cblk = cons_block; cblk; cblk = *cprev) + { + int i = 0; + int this_free = 0; + int ilim = (lim + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD; - /* Scan the mark bits an int at a time. */ - for (i = 0; i < ilim; i++) - { - if (cblk->gcmarkbits[i] == -1) - { - /* Fast path - all cons cells for this int are marked. */ - cblk->gcmarkbits[i] = 0; - num_used += BITS_PER_INT; - } - else - { - /* Some cons cells for this int are not marked. - Find which ones, and free them. */ - int start, pos, stop; - - start = i * BITS_PER_INT; - stop = lim - start; - if (stop > BITS_PER_INT) - stop = BITS_PER_INT; - stop += start; - - for (pos = start; pos < stop; pos++) - { - if (!CONS_MARKED_P (&cblk->conses[pos])) - { - this_free++; - cblk->conses[pos].u.chain = cons_free_list; - cons_free_list = &cblk->conses[pos]; + /* Scan the mark bits an int at a time. */ + for (i = 0; i < ilim; i++) + { + if (cblk->gcmarkbits[i] == BITS_WORD_MAX) + { + /* Fast path - all cons cells for this int are marked. */ + cblk->gcmarkbits[i] = 0; + num_used += BITS_PER_BITS_WORD; + } + else + { + /* Some cons cells for this int are not marked. + Find which ones, and free them. */ + int start, pos, stop; + + start = i * BITS_PER_BITS_WORD; + stop = lim - start; + if (stop > BITS_PER_BITS_WORD) + stop = BITS_PER_BITS_WORD; + stop += start; + + for (pos = start; pos < stop; pos++) + { + if (!CONS_MARKED_P (&cblk->conses[pos])) + { + this_free++; + cblk->conses[pos].u.chain = cons_free_list; + cons_free_list = &cblk->conses[pos]; #if GC_MARK_STACK - cons_free_list->car = Vdead; + cons_free_list->car = Vdead; #endif - } - else - { - num_used++; - CONS_UNMARK (&cblk->conses[pos]); - } - } - } - } + } + else + { + num_used++; + CONS_UNMARK (&cblk->conses[pos]); + } + } + } + } - lim = CONS_BLOCK_SIZE; - /* If this block contains only free conses and we have already - seen more than two blocks worth of free conses then deallocate - this block. */ - if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE) - { - *cprev = cblk->next; - /* Unhook from the free list. */ - cons_free_list = cblk->conses[0].u.chain; - lisp_align_free (cblk); - } - else - { - num_free += this_free; - cprev = &cblk->next; - } - } - total_conses = num_used; - total_free_conses = num_free; - } + lim = CONS_BLOCK_SIZE; + /* If this block contains only free conses and we have already + seen more than two blocks worth of free conses then deallocate + this block. */ + if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE) + { + *cprev = cblk->next; + /* Unhook from the free list. */ + cons_free_list = cblk->conses[0].u.chain; + lisp_align_free (cblk); + } + else + { + num_free += this_free; + cprev = &cblk->next; + } + } + total_conses = num_used; + total_free_conses = num_free; +} - /* Put all unmarked floats on free list. */ - { - register struct float_block *fblk; - struct float_block **fprev = &float_block; - register int lim = float_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_floats (void) +{ + register struct float_block *fblk; + struct float_block **fprev = &float_block; + register int lim = float_block_index; + EMACS_INT num_free = 0, num_used = 0; - float_free_list = 0; + float_free_list = 0; - for (fblk = float_block; fblk; fblk = *fprev) - { - register int i; - int this_free = 0; - for (i = 0; i < lim; i++) - if (!FLOAT_MARKED_P (&fblk->floats[i])) - { - this_free++; - fblk->floats[i].u.chain = float_free_list; - float_free_list = &fblk->floats[i]; - } - else - { - num_used++; - FLOAT_UNMARK (&fblk->floats[i]); - } - lim = FLOAT_BLOCK_SIZE; - /* If this block contains only free floats and we have already - seen more than two blocks worth of free floats then deallocate - this block. */ - if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE) - { - *fprev = fblk->next; - /* Unhook from the free list. */ - float_free_list = fblk->floats[0].u.chain; - lisp_align_free (fblk); - } - else - { - num_free += this_free; - fprev = &fblk->next; - } - } - total_floats = num_used; - total_free_floats = num_free; - } + for (fblk = float_block; fblk; fblk = *fprev) + { + register int i; + int this_free = 0; + for (i = 0; i < lim; i++) + if (!FLOAT_MARKED_P (&fblk->floats[i])) + { + this_free++; + fblk->floats[i].u.chain = float_free_list; + float_free_list = &fblk->floats[i]; + } + else + { + num_used++; + FLOAT_UNMARK (&fblk->floats[i]); + } + lim = FLOAT_BLOCK_SIZE; + /* If this block contains only free floats and we have already + seen more than two blocks worth of free floats then deallocate + this block. */ + if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE) + { + *fprev = fblk->next; + /* Unhook from the free list. */ + float_free_list = fblk->floats[0].u.chain; + lisp_align_free (fblk); + } + else + { + num_free += this_free; + fprev = &fblk->next; + } + } + total_floats = num_used; + total_free_floats = num_free; +} - /* Put all unmarked intervals on free list. */ - { - register struct interval_block *iblk; - struct interval_block **iprev = &interval_block; - register int lim = interval_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_intervals (void) +{ + register struct interval_block *iblk; + struct interval_block **iprev = &interval_block; + register int lim = interval_block_index; + EMACS_INT num_free = 0, num_used = 0; - interval_free_list = 0; + interval_free_list = 0; - for (iblk = interval_block; iblk; iblk = *iprev) - { - register int i; - int this_free = 0; + for (iblk = interval_block; iblk; iblk = *iprev) + { + register int i; + int this_free = 0; - for (i = 0; i < lim; i++) - { - if (!iblk->intervals[i].gcmarkbit) - { - set_interval_parent (&iblk->intervals[i], interval_free_list); - interval_free_list = &iblk->intervals[i]; - this_free++; - } - else - { - num_used++; - iblk->intervals[i].gcmarkbit = 0; - } - } - lim = INTERVAL_BLOCK_SIZE; - /* If this block contains only free intervals and we have already - seen more than two blocks worth of free intervals then - deallocate this block. */ - if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE) - { - *iprev = iblk->next; - /* Unhook from the free list. */ - interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); - lisp_free (iblk); - } - else - { - num_free += this_free; - iprev = &iblk->next; - } - } - total_intervals = num_used; - total_free_intervals = num_free; - } + for (i = 0; i < lim; i++) + { + if (!iblk->intervals[i].gcmarkbit) + { + set_interval_parent (&iblk->intervals[i], interval_free_list); + interval_free_list = &iblk->intervals[i]; + this_free++; + } + else + { + num_used++; + iblk->intervals[i].gcmarkbit = 0; + } + } + lim = INTERVAL_BLOCK_SIZE; + /* If this block contains only free intervals and we have already + seen more than two blocks worth of free intervals then + deallocate this block. */ + if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE) + { + *iprev = iblk->next; + /* Unhook from the free list. */ + interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); + lisp_free (iblk); + } + else + { + num_free += this_free; + iprev = &iblk->next; + } + } + total_intervals = num_used; + total_free_intervals = num_free; +} - /* Put all unmarked symbols on free list. */ - { - register struct symbol_block *sblk; - struct symbol_block **sprev = &symbol_block; - register int lim = symbol_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_symbols (void) +{ + register struct symbol_block *sblk; + struct symbol_block **sprev = &symbol_block; + register int lim = symbol_block_index; + EMACS_INT num_free = 0, num_used = 0; - symbol_free_list = NULL; + symbol_free_list = NULL; - for (sblk = symbol_block; sblk; sblk = *sprev) - { - int this_free = 0; - union aligned_Lisp_Symbol *sym = sblk->symbols; - union aligned_Lisp_Symbol *end = sym + lim; + for (sblk = symbol_block; sblk; sblk = *sprev) + { + int this_free = 0; + union aligned_Lisp_Symbol *sym = sblk->symbols; + union aligned_Lisp_Symbol *end = sym + lim; - for (; sym < end; ++sym) - { - if (!sym->s.gcmarkbit) - { - if (sym->s.redirect == SYMBOL_LOCALIZED) - xfree (SYMBOL_BLV (&sym->s)); - sym->s.next = symbol_free_list; - symbol_free_list = &sym->s; + for (; sym < end; ++sym) + { + if (!sym->s.gcmarkbit) + { + if (sym->s.redirect == SYMBOL_LOCALIZED) + xfree (SYMBOL_BLV (&sym->s)); + sym->s.next = symbol_free_list; + symbol_free_list = &sym->s; #if GC_MARK_STACK - symbol_free_list->function = Vdead; + symbol_free_list->function = Vdead; #endif - ++this_free; - } - else - { - ++num_used; - eassert (!STRING_MARKED_P (XSTRING (sym->s.name))); - sym->s.gcmarkbit = 0; - } - } + ++this_free; + } + else + { + ++num_used; + sym->s.gcmarkbit = 0; + /* Attempt to catch bogus objects. */ + eassert (valid_lisp_object_p (sym->s.function) >= 1); + } + } - lim = SYMBOL_BLOCK_SIZE; - /* If this block contains only free symbols and we have already - seen more than two blocks worth of free symbols then deallocate - this block. */ - if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE) - { - *sprev = sblk->next; - /* Unhook from the free list. */ - symbol_free_list = sblk->symbols[0].s.next; - lisp_free (sblk); - } - else - { - num_free += this_free; - sprev = &sblk->next; - } - } - total_symbols = num_used; - total_free_symbols = num_free; - } + lim = SYMBOL_BLOCK_SIZE; + /* If this block contains only free symbols and we have already + seen more than two blocks worth of free symbols then deallocate + this block. */ + if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE) + { + *sprev = sblk->next; + /* Unhook from the free list. */ + symbol_free_list = sblk->symbols[0].s.next; + lisp_free (sblk); + } + else + { + num_free += this_free; + sprev = &sblk->next; + } + } + total_symbols = num_used; + total_free_symbols = num_free; +} - /* Put all unmarked misc's on free list. - For a marker, first unchain it from the buffer it points into. */ - { - register struct marker_block *mblk; - struct marker_block **mprev = &marker_block; - register int lim = marker_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_misc (void) +{ + register struct marker_block *mblk; + struct marker_block **mprev = &marker_block; + register int lim = marker_block_index; + EMACS_INT num_free = 0, num_used = 0; - marker_free_list = 0; + /* Put all unmarked misc's on free list. For a marker, first + unchain it from the buffer it points into. */ - for (mblk = marker_block; mblk; mblk = *mprev) - { - register int i; - int this_free = 0; + marker_free_list = 0; - for (i = 0; i < lim; i++) - { - if (!mblk->markers[i].m.u_any.gcmarkbit) - { - if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) - unchain_marker (&mblk->markers[i].m.u_marker); - /* Set the type of the freed object to Lisp_Misc_Free. - We could leave the type alone, since nobody checks it, - but this might catch bugs faster. */ - mblk->markers[i].m.u_marker.type = Lisp_Misc_Free; - mblk->markers[i].m.u_free.chain = marker_free_list; - marker_free_list = &mblk->markers[i].m; - this_free++; - } - else - { - num_used++; - mblk->markers[i].m.u_any.gcmarkbit = 0; - } - } - lim = MARKER_BLOCK_SIZE; - /* If this block contains only free markers and we have already - seen more than two blocks worth of free markers then deallocate - this block. */ - if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) - { - *mprev = mblk->next; - /* Unhook from the free list. */ - marker_free_list = mblk->markers[0].m.u_free.chain; - lisp_free (mblk); - } - else - { - num_free += this_free; - mprev = &mblk->next; - } - } + for (mblk = marker_block; mblk; mblk = *mprev) + { + register int i; + int this_free = 0; - total_markers = num_used; - total_free_markers = num_free; - } + for (i = 0; i < lim; i++) + { + if (!mblk->markers[i].m.u_any.gcmarkbit) + { + if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) + unchain_marker (&mblk->markers[i].m.u_marker); + /* Set the type of the freed object to Lisp_Misc_Free. + We could leave the type alone, since nobody checks it, + but this might catch bugs faster. */ + mblk->markers[i].m.u_marker.type = Lisp_Misc_Free; + mblk->markers[i].m.u_free.chain = marker_free_list; + marker_free_list = &mblk->markers[i].m; + this_free++; + } + else + { + num_used++; + mblk->markers[i].m.u_any.gcmarkbit = 0; + } + } + lim = MARKER_BLOCK_SIZE; + /* If this block contains only free markers and we have already + seen more than two blocks worth of free markers then deallocate + this block. */ + if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) + { + *mprev = mblk->next; + /* Unhook from the free list. */ + marker_free_list = mblk->markers[0].m.u_free.chain; + lisp_free (mblk); + } + else + { + num_free += this_free; + mprev = &mblk->next; + } + } - /* Free all unmarked buffers */ - { - register struct buffer *buffer, **bprev = &all_buffers; + total_markers = num_used; + total_free_markers = num_free; +} - total_buffers = 0; - for (buffer = all_buffers; buffer; buffer = *bprev) - if (!VECTOR_MARKED_P (buffer)) - { - *bprev = buffer->next; - lisp_free (buffer); - } - else - { - VECTOR_UNMARK (buffer); - /* Do not use buffer_(set|get)_intervals here. */ - buffer->text->intervals = balance_intervals (buffer->text->intervals); - total_buffers++; - bprev = &buffer->next; - } - } +NO_INLINE /* For better stack traces */ +static void +sweep_buffers (void) +{ + register struct buffer *buffer, **bprev = &all_buffers; + + total_buffers = 0; + for (buffer = all_buffers; buffer; buffer = *bprev) + if (!VECTOR_MARKED_P (buffer)) + { + *bprev = buffer->next; + lisp_free (buffer); + } + else + { + VECTOR_UNMARK (buffer); + /* Do not use buffer_(set|get)_intervals here. */ + buffer->text->intervals = balance_intervals (buffer->text->intervals); + total_buffers++; + bprev = &buffer->next; + } +} +/* Sweep: find all structures not marked, and free them. */ +static void +gc_sweep (void) +{ + /* Remove or mark entries in weak hash tables. + This must be done before any object is unmarked. */ + sweep_weak_hash_tables (); + + sweep_strings (); + check_string_bytes (!noninteractive); + sweep_conses (); + sweep_floats (); + sweep_intervals (); + sweep_symbols (); + sweep_misc (); + sweep_buffers (); sweep_vectors (); check_string_bytes (!noninteractive); } +DEFUN ("memory-info", Fmemory_info, Smemory_info, 0, 0, 0, + doc: /* Return a list of (TOTAL-RAM FREE-RAM TOTAL-SWAP FREE-SWAP). +All values are in Kbytes. If there is no swap space, +last two values are zero. If the system is not supported +or memory information can't be obtained, return nil. */) + (void) +{ +#if defined HAVE_LINUX_SYSINFO + struct sysinfo si; + uintmax_t units; + if (sysinfo (&si)) + return Qnil; +#ifdef LINUX_SYSINFO_UNIT + units = si.mem_unit; +#else + units = 1; +#endif + return list4i ((uintmax_t) si.totalram * units / 1024, + (uintmax_t) si.freeram * units / 1024, + (uintmax_t) si.totalswap * units / 1024, + (uintmax_t) si.freeswap * units / 1024); +#elif defined WINDOWSNT + unsigned long long totalram, freeram, totalswap, freeswap; + + if (w32_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0) + return list4i ((uintmax_t) totalram / 1024, + (uintmax_t) freeram / 1024, + (uintmax_t) totalswap / 1024, + (uintmax_t) freeswap / 1024); + else + return Qnil; +#elif defined MSDOS + unsigned long totalram, freeram, totalswap, freeswap; + + if (dos_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0) + return list4i ((uintmax_t) totalram / 1024, + (uintmax_t) freeram / 1024, + (uintmax_t) totalswap / 1024, + (uintmax_t) freeswap / 1024); + else + return Qnil; +#else /* not HAVE_LINUX_SYSINFO, not WINDOWSNT, not MSDOS */ + /* FIXME: add more systems. */ + return Qnil; +#endif /* HAVE_LINUX_SYSINFO, not WINDOWSNT, not MSDOS */ +} - /* Debugging aids. */ DEFUN ("memory-limit", Fmemory_limit, Smemory_limit, 0, 0, 0, @@ -6821,6 +7022,78 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) return found; } +#ifdef SUSPICIOUS_OBJECT_CHECKING + +static void * +find_suspicious_object_in_range (void *begin, void *end) +{ + char *begin_a = begin; + char *end_a = end; + int i; + + for (i = 0; i < ARRAYELTS (suspicious_objects); ++i) + { + char *suspicious_object = suspicious_objects[i]; + if (begin_a <= suspicious_object && suspicious_object < end_a) + return suspicious_object; + } + + return NULL; +} + +static void +note_suspicious_free (void* ptr) +{ + struct suspicious_free_record* rec; + + rec = &suspicious_free_history[suspicious_free_history_index++]; + if (suspicious_free_history_index == + ARRAYELTS (suspicious_free_history)) + { + suspicious_free_history_index = 0; + } + + memset (rec, 0, sizeof (*rec)); + rec->suspicious_object = ptr; + backtrace (&rec->backtrace[0], ARRAYELTS (rec->backtrace)); +} + +static void +detect_suspicious_free (void* ptr) +{ + int i; + + eassert (ptr != NULL); + + for (i = 0; i < ARRAYELTS (suspicious_objects); ++i) + if (suspicious_objects[i] == ptr) + { + note_suspicious_free (ptr); + suspicious_objects[i] = NULL; + } +} + +#endif /* SUSPICIOUS_OBJECT_CHECKING */ + +DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0, + doc: /* Return OBJ, maybe marking it for extra scrutiny. +If Emacs is compiled with suspicious object checking, capture +a stack trace when OBJ is freed in order to help track down +garbage collection bugs. Otherwise, do nothing and return OBJ. */) + (Lisp_Object obj) +{ +#ifdef SUSPICIOUS_OBJECT_CHECKING + /* Right now, we care only about vectors. */ + if (VECTORLIKEP (obj)) + { + suspicious_objects[suspicious_object_index++] = XVECTOR (obj); + if (suspicious_object_index == ARRAYELTS (suspicious_objects)) + suspicious_object_index = 0; + } +#endif + return obj; +} + #ifdef ENABLE_CHECKING bool suppress_checking; @@ -6832,8 +7105,48 @@ die (const char *msg, const char *file, int line) file, line, msg); terminate_due_to_signal (SIGABRT, INT_MAX); } -#endif - + +#endif /* ENABLE_CHECKING */ + +#if defined (ENABLE_CHECKING) && USE_STACK_LISP_OBJECTS + +/* Debugging check whether STR is ASCII-only. */ + +const char * +verify_ascii (const char *str) +{ + const unsigned char *ptr = (unsigned char *) str, *end = ptr + strlen (str); + while (ptr < end) + { + int c = STRING_CHAR_ADVANCE (ptr); + if (!ASCII_CHAR_P (c)) + emacs_abort (); + } + return str; +} + +/* Stress alloca with inconveniently sized requests and check + whether all allocated areas may be used for Lisp_Object. */ + +NO_INLINE static void +verify_alloca (void) +{ + int i; + enum { ALLOCA_CHECK_MAX = 256 }; + /* Start from size of the smallest Lisp object. */ + for (i = sizeof (struct Lisp_Cons); i <= ALLOCA_CHECK_MAX; i++) + { + void *ptr = alloca (i); + make_lisp_ptr (ptr, Lisp_Cons); + } +} + +#else /* not ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */ + +#define verify_alloca() ((void) 0) + +#endif /* ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */ + /* Initialization. */ void @@ -6843,6 +7156,8 @@ init_alloc_once (void) purebeg = PUREBEG; pure_size = PURESIZE; + verify_alloca (); + #if GC_MARK_STACK || defined GC_MALLOC_CHECK mem_init (); Vdead = make_pure_string ("DEAD", 4, 4, 0); @@ -6980,6 +7295,7 @@ The time is in seconds as a floating point value. */); defsubr (&Scons); defsubr (&Slist); defsubr (&Svector); + defsubr (&Sbool_vector); defsubr (&Smake_byte_code); defsubr (&Smake_list); defsubr (&Smake_vector); @@ -6990,7 +7306,9 @@ The time is in seconds as a floating point value. */); defsubr (&Spurecopy); defsubr (&Sgarbage_collect); defsubr (&Smemory_limit); + defsubr (&Smemory_info); defsubr (&Smemory_use_counts); + defsubr (&Ssuspicious_object); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES defsubr (&Sgc_status); @@ -7005,11 +7323,10 @@ The time is in seconds as a floating point value. */); union { enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS; - enum CHAR_TABLE_STANDARD_SLOTS CHAR_TABLE_STANDARD_SLOTS; + enum char_table_specials char_table_specials; enum char_bits char_bits; enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE; enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE; - enum enum_USE_LSB_TAG enum_USE_LSB_TAG; enum Lisp_Bits Lisp_Bits; enum Lisp_Compiled Lisp_Compiled; enum maxargs maxargs; diff --git a/src/atimer.c b/src/atimer.c index d98ddac0171..ce782f6adb6 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -26,6 +26,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "atimer.h" #include <unistd.h> +#ifdef HAVE_TIMERFD +#include <errno.h> +# include <sys/timerfd.h> +#endif + /* Free-list of atimer structures. */ static struct atimer *free_atimers; @@ -40,32 +45,35 @@ static struct atimer *stopped_atimers; static struct atimer *atimers; +#ifdef HAVE_ITIMERSPEC /* The alarm timer and whether it was properly initialized, if POSIX timers are available. */ -#ifdef HAVE_ITIMERSPEC static timer_t alarm_timer; static bool alarm_timer_ok; + +# ifdef HAVE_TIMERFD +/* File descriptor for timer, or -1 if it could not be created. */ +static int timerfd; +# else +enum { timerfd = -1 }; +# endif #endif /* Block/unblock SIGALRM. */ static void -sigmask_atimers (int how) +block_atimers (sigset_t *oldset) { sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGALRM); - pthread_sigmask (how, &blocked, 0); -} -static void -block_atimers (void) -{ - sigmask_atimers (SIG_BLOCK); + sigaddset (&blocked, SIGINT); + pthread_sigmask (SIG_BLOCK, &blocked, oldset); } static void -unblock_atimers (void) +unblock_atimers (sigset_t const *oldset) { - sigmask_atimers (SIG_UNBLOCK); + pthread_sigmask (SIG_SETMASK, oldset, 0); } /* Function prototypes. */ @@ -75,20 +83,20 @@ static void schedule_atimer (struct atimer *); static struct atimer *append_atimer_lists (struct atimer *, struct atimer *); -/* Start a new atimer of type TYPE. TIME specifies when the timer is +/* Start a new atimer of type TYPE. TIMESTAMP specifies when the timer is ripe. FN is the function to call when the timer fires. CLIENT_DATA is stored in the client_data member of the atimer structure returned and so made available to FN when it is called. - If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the + If TYPE is ATIMER_ABSOLUTE, TIMESTAMP is the absolute time at which the timer fires. - If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the + If TYPE is ATIMER_RELATIVE, the timer is ripe TIMESTAMP seconds in the future. In both cases, the timer is automatically freed after it has fired. - If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us. + If TYPE is ATIMER_CONTINUOUS, the timer fires every TIMESTAMP seconds. Value is a pointer to the atimer started. It can be used in calls to cancel_atimer; don't free it yourself. */ @@ -98,9 +106,9 @@ start_atimer (enum atimer_type type, struct timespec timestamp, atimer_callback fn, void *client_data) { struct atimer *t; + sigset_t oldset; - /* Round TIME up to the next full second if we don't have - itimers. */ + /* Round TIMESTAMP up to the next full second if we don't have itimers. */ #ifndef HAVE_SETITIMER if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t)) timestamp = make_timespec (timestamp.tv_sec + 1, 0); @@ -122,7 +130,7 @@ start_atimer (enum atimer_type type, struct timespec timestamp, t->fn = fn; t->client_data = client_data; - block_atimers (); + block_atimers (&oldset); /* Compute the timer's expiration time. */ switch (type) @@ -143,7 +151,7 @@ start_atimer (enum atimer_type type, struct timespec timestamp, /* Insert the timer in the list of active atimers. */ schedule_atimer (t); - unblock_atimers (); + unblock_atimers (&oldset); /* Arrange for a SIGALRM at the time the next atimer is ripe. */ set_alarm (); @@ -158,8 +166,9 @@ void cancel_atimer (struct atimer *timer) { int i; + sigset_t oldset; - block_atimers (); + block_atimers (&oldset); for (i = 0; i < 2; ++i) { @@ -186,7 +195,7 @@ cancel_atimer (struct atimer *timer) } } - unblock_atimers (); + unblock_atimers (&oldset); } @@ -217,7 +226,8 @@ append_atimer_lists (struct atimer *list_1, struct atimer *list_2) void stop_other_atimers (struct atimer *t) { - block_atimers (); + sigset_t oldset; + block_atimers (&oldset); if (t) { @@ -242,7 +252,7 @@ stop_other_atimers (struct atimer *t) stopped_atimers = append_atimer_lists (atimers, stopped_atimers); atimers = t; - unblock_atimers (); + unblock_atimers (&oldset); } @@ -256,8 +266,9 @@ run_all_atimers (void) { struct atimer *t = atimers; struct atimer *next; + sigset_t oldset; - block_atimers (); + block_atimers (&oldset); atimers = stopped_atimers; stopped_atimers = NULL; @@ -268,7 +279,7 @@ run_all_atimers (void) t = next; } - unblock_atimers (); + unblock_atimers (&oldset); } } @@ -286,12 +297,20 @@ set_alarm (void) struct timespec now, interval; #ifdef HAVE_ITIMERSPEC - if (alarm_timer_ok) + if (0 <= timerfd || alarm_timer_ok) { struct itimerspec ispec; ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; - if (timer_settime (alarm_timer, 0, &ispec, 0) == 0) +# ifdef HAVE_TIMERFD + if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) + { + add_timer_wait_descriptor (timerfd); + return; + } +# endif + if (alarm_timer_ok + && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) return; } #endif @@ -373,6 +392,37 @@ handle_alarm_signal (int sig) pending_signals = 1; } +#ifdef HAVE_TIMERFD + +/* Called from wait_reading_process_output when FD, which + should be equal to TIMERFD, is available for reading. */ + +void +timerfd_callback (int fd, void *arg) +{ + ptrdiff_t nbytes; + uint64_t expirations; + + eassert (fd == timerfd); + nbytes = emacs_read (fd, &expirations, sizeof (expirations)); + + if (nbytes == sizeof (expirations)) + { + /* Timer should expire just once. */ + eassert (expirations == 1); + do_pending_atimers (); + } + else if (nbytes < 0) + /* For some not yet known reason, we may get weird event and no + data on timer descriptor. This can break Gnus at least, see: + http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00503.html. */ + eassert (errno == EAGAIN); + else + /* I don't know what else can happen with this descriptor. */ + emacs_abort (); +} + +#endif /* HAVE_TIMERFD */ /* Do pending timers. */ @@ -381,9 +431,10 @@ do_pending_atimers (void) { if (atimers) { - block_atimers (); + sigset_t oldset; + block_atimers (&oldset); run_timers (); - unblock_atimers (); + unblock_atimers (&oldset); } } @@ -397,23 +448,121 @@ turn_on_atimers (bool on) if (on) set_alarm (); else - alarm (0); + { +#ifdef HAVE_ITIMERSPEC + struct itimerspec ispec; + memset (&ispec, 0, sizeof ispec); + if (alarm_timer_ok) + timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0); +# ifdef HAVE_TIMERFD + timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); +# endif +#endif + alarm (0); + } } +/* This is intended to use from automated tests. */ + +#ifdef ENABLE_CHECKING + +#define MAXTIMERS 10 + +struct atimer_result +{ + /* Time when we expect this timer to trigger. */ + struct timespec expected; + + /* Timer status: -1 if not triggered, 0 if triggered + too early or too late, 1 if triggered timely. */ + int intime; +}; + +static void +debug_timer_callback (struct atimer *t) +{ + struct timespec now = current_timespec (); + struct atimer_result *r = (struct atimer_result *) t->client_data; + int result = timespec_cmp (now, r->expected); + + if (result < 0) + /* Too early. */ + r->intime = 0; + else if (result >= 0) + { +#ifdef HAVE_SETITIMER + struct timespec delta = timespec_sub (now, r->expected); + /* Too late if later than expected + 0.01s. FIXME: + this should depend from system clock resolution. */ + if (timespec_cmp (delta, make_timespec (0, 10000000)) > 0) + r->intime = 0; + else +#endif /* HAVE_SETITIMER */ + r->intime = 1; + } +} + +DEFUN ("debug-timer-check", Fdebug_timer_check, Sdebug_timer_check, 0, 0, 0, + doc: /* Run internal self-tests to check timers subsystem. +Return t if all self-tests are passed, nil otherwise. */) + (void) +{ + int i, ok; + struct atimer *timer; + struct atimer_result *results[MAXTIMERS]; + struct timespec t = make_timespec (0, 0); + + /* Arm MAXTIMERS relative timers to trigger with 0.1s intervals. */ + for (i = 0; i < MAXTIMERS; i++) + { + results[i] = xmalloc (sizeof (struct atimer_result)); + t = timespec_add (t, make_timespec (0, 100000000)); + results[i]->expected = timespec_add (current_timespec (), t); + results[i]->intime = -1; + timer = start_atimer (ATIMER_RELATIVE, t, + debug_timer_callback, results[i]); + } + + /* Wait for 1s but process timers. */ + wait_reading_process_output (1, 0, 0, false, Qnil, NULL, 0); + /* Shut up the compiler by "using" this variable. */ + (void) timer; + + for (i = 0, ok = 0; i < MAXTIMERS; i++) + ok += results[i]->intime, xfree (results[i]); + + return ok == MAXTIMERS ? Qt : Qnil; +} + +#endif /* ENABLE_CHECKING */ void init_atimer (void) { - struct sigaction action; #ifdef HAVE_ITIMERSPEC - struct sigevent sigev; - sigev.sigev_notify = SIGEV_SIGNAL; - sigev.sigev_signo = SIGALRM; - sigev.sigev_value.sival_ptr = &alarm_timer; - alarm_timer_ok = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; +# ifdef HAVE_TIMERFD + /* Until this feature is considered stable, you can ask to not use it. */ + timerfd = (egetenv ("EMACS_IGNORE_TIMERFD") ? -1 : + timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC)); +# endif + if (timerfd < 0) + { + struct sigevent sigev; + sigev.sigev_notify = SIGEV_SIGNAL; + sigev.sigev_signo = SIGALRM; + sigev.sigev_value.sival_ptr = &alarm_timer; + alarm_timer_ok + = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; + } #endif free_atimers = stopped_atimers = atimers = NULL; - /* pending_signals is initialized in init_keyboard.*/ + + /* pending_signals is initialized in init_keyboard. */ + struct sigaction action; emacs_sigaction_init (&action, handle_alarm_signal); sigaction (SIGALRM, &action, 0); + +#ifdef ENABLE_CHECKING + defsubr (&Sdebug_timer_check); +#endif } diff --git a/src/atimer.h b/src/atimer.h index 379787abca7..2386977cf87 100644 --- a/src/atimer.h +++ b/src/atimer.h @@ -77,5 +77,8 @@ void init_atimer (void); void turn_on_atimers (bool); void stop_other_atimers (struct atimer *); void run_all_atimers (void); +#ifdef HAVE_TIMERFD +void timerfd_callback (int, void *); +#endif #endif /* EMACS_ATIMER_H */ diff --git a/src/bidi.c b/src/bidi.c index 53c2dad1b6b..d354aa796ae 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -76,6 +76,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ bidi_fetch_char -- fetch next character bidi_resolve_explicit -- resolve explicit levels and directions bidi_resolve_weak -- resolve weak types + bidi_resolve_brackets -- resolve "paired brackets" neutral types bidi_resolve_neutral -- resolve neutral types bidi_level_of_next_char -- resolve implicit levels @@ -247,7 +248,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ static bool bidi_initialized = 0; -static Lisp_Object bidi_type_table, bidi_mirror_table; +static Lisp_Object bidi_type_table, bidi_mirror_table, bidi_brackets_table; #define BIDI_EOB (-1) @@ -260,14 +261,6 @@ typedef enum { EXPLICIT_FORMATTING } bidi_category_t; -/* UAX#9 says to search only for L, AL, or R types of characters, and - ignore RLE, RLO, LRE, and LRO, when determining the base paragraph - level. Yudit indeed ignores them. This variable is therefore set - by default to ignore them, but clearing it will take them into - account. */ -extern bool bidi_ignore_explicit_marks_for_paragraph_level EXTERNALLY_VISIBLE; -bool bidi_ignore_explicit_marks_for_paragraph_level = 1; - static Lisp_Object paragraph_start_re, paragraph_separate_re; static Lisp_Object Qparagraph_start, Qparagraph_separate; @@ -305,14 +298,11 @@ bidi_get_type (int ch, bidi_dir_t override) case RLE: case RLO: case PDF: - return default_type; - /* FIXME: The isolate controls are treated as BN until we add - support for UBA v6.3. */ case LRI: case RLI: case FSI: case PDI: - return WEAK_BN; + return default_type; default: if (override == L2R) return STRONG_L; @@ -348,11 +338,6 @@ bidi_get_category (bidi_type_t type) case WEAK_CS: case WEAK_NSM: case WEAK_BN: - /* FIXME */ - case LRI: - case RLI: - case FSI: - case PDI: return WEAK; case NEUTRAL_B: case NEUTRAL_S: @@ -364,19 +349,22 @@ bidi_get_category (bidi_type_t type) case RLE: case RLO: case PDF: -#if 0 - /* FIXME: This awaits implementation of isolate support. */ case LRI: case RLI: case FSI: case PDI: -#endif return EXPLICIT_FORMATTING; default: emacs_abort (); } } +static bool +bidi_isolate_fmt_char (bidi_type_t ch_type) +{ + return (ch_type == LRI || ch_type == RLI || ch_type == PDI || ch_type == FSI); +} + /* Return the mirrored character of C, if it has one. If C has no mirrored counterpart, return C. Note: The conditions in UAX#9 clause L4 regarding the surrounding @@ -413,75 +401,124 @@ bidi_mirror_char (int c) return c; } -/* Determine the start-of-run (sor) directional type given the two +/* Return the Bidi_Paired_Bracket_Type property of the character C. */ +static bidi_bracket_type_t +bidi_paired_bracket_type (int c) +{ + if (c == BIDI_EOB) + return BIDI_BRACKET_NONE; + if (c < 0 || c > MAX_CHAR) + emacs_abort (); + + return (bidi_bracket_type_t) XINT (CHAR_TABLE_REF (bidi_brackets_table, c)); +} + +/* Determine the start-of-sequence (sos) directional type given the two embedding levels on either side of the run boundary. Also, update the saved info about previously seen characters, since that info is generally valid for a single level run. */ static void -bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after) +bidi_set_sos_type (struct bidi_it *bidi_it, int level_before, int level_after) { int higher_level = (level_before > level_after ? level_before : level_after); - /* The prev_was_pdf gork is required for when we have several PDFs - in a row. In that case, we want to compute the sor type for the - next level run only once: when we see the first PDF. That's - because the sor type depends only on the higher of the two levels - that we find on the two sides of the level boundary (see UAX#9, - clause X10), and so we don't need to know the final embedding - level to which we descend after processing all the PDFs. */ - if (!bidi_it->prev_was_pdf || level_before < level_after) - /* FIXME: should the default sor direction be user selectable? */ - bidi_it->sor = ((higher_level & 1) != 0 ? R2L : L2R); - if (level_before > level_after) - bidi_it->prev_was_pdf = 1; + /* FIXME: should the default sos direction be user selectable? */ + bidi_it->sos = ((higher_level & 1) != 0 ? R2L : L2R); /* X10 */ bidi_it->prev.type = UNKNOWN_BT; - bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 - = bidi_it->last_strong.orig_type = UNKNOWN_BT; - bidi_it->prev_for_neutral.type = (bidi_it->sor == R2L ? STRONG_R : STRONG_L); + bidi_it->last_strong.type = bidi_it->last_strong.orig_type = UNKNOWN_BT; + bidi_it->prev_for_neutral.type = (bidi_it->sos == R2L ? STRONG_R : STRONG_L); bidi_it->prev_for_neutral.charpos = bidi_it->charpos; - bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos; - bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 + bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; - bidi_it->ignore_bn_limit = -1; /* meaning it's unknown */ } /* Push the current embedding level and override status; reset the current level to LEVEL and the current override status to OVERRIDE. */ static void bidi_push_embedding_level (struct bidi_it *bidi_it, - int level, bidi_dir_t override) + int level, bidi_dir_t override, bool isolate_status) { + struct bidi_stack *st; + int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; + bidi_it->stack_idx++; - eassert (bidi_it->stack_idx < BIDI_MAXLEVEL); - bidi_it->level_stack[bidi_it->stack_idx].level = level; - bidi_it->level_stack[bidi_it->stack_idx].override = override; + eassert (bidi_it->stack_idx < BIDI_MAXDEPTH+2+1); + st = &bidi_it->level_stack[bidi_it->stack_idx]; + eassert (level <= (1 << 7)); + st->level = level; + st->override = override; + st->isolate_status = isolate_status; + if (isolate_status) + { + st->last_strong = bidi_it->last_strong; + st->prev_for_neutral = bidi_it->prev_for_neutral; + st->next_for_neutral = bidi_it->next_for_neutral; + st->sos = bidi_it->sos; + } + /* We've got a new isolating sequence, compute the directional type + of sos and initialize per-sequence variables (UAX#9, clause X10). */ + bidi_set_sos_type (bidi_it, prev_level, level); } -/* Pop the embedding level and directional override status from the - stack, and return the new level. */ +/* Pop from the stack the embedding level, the directional override + status, and optionally saved information for the isolating run + sequence. Return the new level. */ static int bidi_pop_embedding_level (struct bidi_it *bidi_it) { - /* UAX#9 says to ignore invalid PDFs. */ + int level; + + /* UAX#9 says to ignore invalid PDFs (X7, last bullet) + and PDIs (X6a, 2nd bullet). */ if (bidi_it->stack_idx > 0) - bidi_it->stack_idx--; - return bidi_it->level_stack[bidi_it->stack_idx].level; + { + bool isolate_status + = bidi_it->level_stack[bidi_it->stack_idx].isolate_status; + int old_level = bidi_it->level_stack[bidi_it->stack_idx].level; + + struct bidi_stack st; + + st = bidi_it->level_stack[bidi_it->stack_idx]; + if (isolate_status) + { + /* PREV is used in W1 for resolving WEAK_NSM. By the time + we get to an NSM, we must have gotten past at least one + character: the PDI that ends the isolate from which we + are popping here. So PREV will have been filled up by + the time we first use it. We initialize it here to + UNKNOWN_BT to be able to catch any blunders in this + logic. */ + bidi_it->prev.orig_type = bidi_it->prev.type = UNKNOWN_BT; + bidi_it->last_strong = st.last_strong; + bidi_it->prev_for_neutral = st.prev_for_neutral; + bidi_it->next_for_neutral = st.next_for_neutral; + bidi_it->sos = st.sos; + } + else + bidi_set_sos_type (bidi_it, old_level, + bidi_it->level_stack[bidi_it->stack_idx - 1].level); + + bidi_it->stack_idx--; + } + level = bidi_it->level_stack[bidi_it->stack_idx].level; + eassert (0 <= level && level <= BIDI_MAXDEPTH + 1); + return level; } /* Record in SAVED_INFO the information about the current character. */ static void bidi_remember_char (struct bidi_saved_info *saved_info, - struct bidi_it *bidi_it) + struct bidi_it *bidi_it, bool from_type) { saved_info->charpos = bidi_it->charpos; - saved_info->bytepos = bidi_it->bytepos; - saved_info->type = bidi_it->type; - bidi_check_type (bidi_it->type); - saved_info->type_after_w1 = bidi_it->type_after_w1; - bidi_check_type (bidi_it->type_after_w1); + if (from_type) + saved_info->type = bidi_it->type; + else + saved_info->type = bidi_it->type_after_wn; + bidi_check_type (saved_info->type); saved_info->orig_type = bidi_it->orig_type; - bidi_check_type (bidi_it->orig_type); + bidi_check_type (saved_info->orig_type); } /* Copy the bidi iterator from FROM to TO. To save cycles, this only @@ -501,6 +538,9 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) Caching the bidi iterator states ***********************************************************************/ +/* We allocate and de-allocate the cache in chunks of this size (in + characters). 200 was chosen as an upper limit for reasonably-long + lines in a text file/buffer. */ #define BIDI_CACHE_CHUNK 200 static struct bidi_it *bidi_cache; static ptrdiff_t bidi_cache_size = 0; @@ -567,7 +607,7 @@ bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it) } /* Find a cached state with a given CHARPOS and resolved embedding - level less or equal to LEVEL. if LEVEL is -1, disregard the + level less or equal to LEVEL. If LEVEL is -1, disregard the resolved levels in cached states. DIR, if non-zero, means search in that direction from the last cache hit. */ static ptrdiff_t @@ -698,7 +738,8 @@ bidi_cache_ensure_space (ptrdiff_t idx) } static void -bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved) +bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved, + bool update_only) { ptrdiff_t idx; @@ -707,6 +748,9 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved) emacs_abort (); idx = bidi_cache_search (bidi_it->charpos, -1, 1); + if (idx < 0 && update_only) + return; + if (idx < 0) { idx = bidi_cache_idx; @@ -734,19 +778,19 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved) costly copying of the entire struct. */ bidi_cache[idx].type = bidi_it->type; bidi_check_type (bidi_it->type); - bidi_cache[idx].type_after_w1 = bidi_it->type_after_w1; - bidi_check_type (bidi_it->type_after_w1); + bidi_cache[idx].type_after_wn = bidi_it->type_after_wn; + bidi_check_type (bidi_it->type_after_wn); if (resolved) bidi_cache[idx].resolved_level = bidi_it->resolved_level; else bidi_cache[idx].resolved_level = -1; bidi_cache[idx].invalid_levels = bidi_it->invalid_levels; - bidi_cache[idx].invalid_rl_levels = bidi_it->invalid_rl_levels; bidi_cache[idx].next_for_neutral = bidi_it->next_for_neutral; bidi_cache[idx].next_for_ws = bidi_it->next_for_ws; - bidi_cache[idx].ignore_bn_limit = bidi_it->ignore_bn_limit; bidi_cache[idx].disp_pos = bidi_it->disp_pos; bidi_cache[idx].disp_prop = bidi_it->disp_prop; + bidi_cache[idx].bracket_pairing_pos = bidi_it->bracket_pairing_pos; + bidi_cache[idx].bracket_enclosed_type = bidi_it->bracket_enclosed_type; } bidi_cache_last_idx = idx; @@ -754,12 +798,24 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved) bidi_cache_idx = idx + 1; } +/* Look for a cached iterator state that corresponds to CHARPOS. If + found, copy the cached state into BIDI_IT and return the type of + the cached entry. If not found, return UNKNOWN_BT. RESOLVED_ONLY + zero means it is OK to return cached states that were not fully + resolved yet. This can happen if the state was cached before it + was resolved in bidi_resolve_neutral. */ static bidi_type_t -bidi_cache_find (ptrdiff_t charpos, int level, struct bidi_it *bidi_it) +bidi_cache_find (ptrdiff_t charpos, bool resolved_only, struct bidi_it *bidi_it) { - ptrdiff_t i = bidi_cache_search (charpos, level, bidi_it->scan_dir); - - if (i >= bidi_cache_start) + ptrdiff_t i = bidi_cache_search (charpos, -1, bidi_it->scan_dir); + + if (i >= bidi_cache_start + && (!resolved_only + /* Callers that want only fully resolved states (and set + resolved_only = true) need to be sure that there's enough + info in the cached state to return the state as final, + and if not, they don't want the cached state. */ + || bidi_cache[i].resolved_level >= 0)) { bidi_dir_t current_scan_dir = bidi_it->scan_dir; @@ -956,6 +1012,11 @@ bidi_initialize (void) emacs_abort (); staticpro (&bidi_mirror_table); + bidi_brackets_table = uniprop_table (intern ("bracket-type")); + if (NILP (bidi_brackets_table)) + emacs_abort (); + staticpro (&bidi_brackets_table); + Qparagraph_start = intern ("paragraph-start"); staticpro (&Qparagraph_start); paragraph_start_re = Fsymbol_value (Qparagraph_start); @@ -981,7 +1042,7 @@ static void bidi_set_paragraph_end (struct bidi_it *bidi_it) { bidi_it->invalid_levels = 0; - bidi_it->invalid_rl_levels = -1; + bidi_it->invalid_isolates = 0; bidi_it->stack_idx = 0; bidi_it->resolved_level = bidi_it->level_stack[0].level; } @@ -998,28 +1059,24 @@ bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, bool frame_window_p, if (bytepos >= 0) bidi_it->bytepos = bytepos; bidi_it->frame_window_p = frame_window_p; - bidi_it->nchars = -1; /* to be computed in bidi_resolve_explicit_1 */ + bidi_it->nchars = -1; /* to be computed in bidi_resolve_explicit */ bidi_it->first_elt = 1; bidi_set_paragraph_end (bidi_it); bidi_it->new_paragraph = 1; bidi_it->separator_limit = -1; bidi_it->type = NEUTRAL_B; - bidi_it->type_after_w1 = NEUTRAL_B; + bidi_it->type_after_wn = NEUTRAL_B; bidi_it->orig_type = NEUTRAL_B; - bidi_it->prev_was_pdf = 0; - bidi_it->prev.type = bidi_it->prev.type_after_w1 - = bidi_it->prev.orig_type = UNKNOWN_BT; - bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 - = bidi_it->last_strong.orig_type = UNKNOWN_BT; + /* FIXME: Review this!!! */ + bidi_it->prev.type = bidi_it->prev.orig_type = UNKNOWN_BT; + bidi_it->last_strong.type = bidi_it->last_strong.orig_type = UNKNOWN_BT; bidi_it->next_for_neutral.charpos = -1; bidi_it->next_for_neutral.type - = bidi_it->next_for_neutral.type_after_w1 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; bidi_it->prev_for_neutral.charpos = -1; bidi_it->prev_for_neutral.type - = bidi_it->prev_for_neutral.type_after_w1 = bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; - bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ + bidi_it->sos = L2R; /* FIXME: should it be user-selectable? */ bidi_it->disp_pos = -1; /* invalid/unknown */ bidi_it->disp_prop = 0; /* We can only shrink the cache if we are at the bottom level of its @@ -1035,16 +1092,20 @@ static void bidi_line_init (struct bidi_it *bidi_it) { bidi_it->scan_dir = 1; /* FIXME: do we need to have control on this? */ + bidi_it->stack_idx = 0; bidi_it->resolved_level = bidi_it->level_stack[0].level; bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */ + bidi_it->level_stack[0].isolate_status = false; /* X1 */ bidi_it->invalid_levels = 0; - bidi_it->invalid_rl_levels = -1; + bidi_it->isolate_level = 0; /* X1 */ + bidi_it->invalid_isolates = 0; /* X1 */ /* Setting this to zero will force its recomputation the first time we need it for W5. */ bidi_it->next_en_pos = 0; bidi_it->next_en_type = UNKNOWN_BT; + bidi_it->next_for_ws.charpos = -1; bidi_it->next_for_ws.type = UNKNOWN_BT; - bidi_set_sor_type (bidi_it, + bidi_set_sos_type (bidi_it, (bidi_it->paragraph_dir == R2L ? 1 : 0), bidi_it->level_stack[0].level); /* X10 */ @@ -1244,6 +1305,50 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, return ch; } +/* Like bidi_fetch_char, but ignore any text between an isolate + initiator and its matching PDI or, if it has no matching PDI, the + end of the paragraph. If isolates were skipped, CH_LEN and NCHARS + are set to the number of bytes and characters between BYTEPOS/CHARPOS + and the character that was fetched after skipping the isolates. */ +static int +bidi_fetch_char_skip_isolates (ptrdiff_t charpos, ptrdiff_t bytepos, + ptrdiff_t *disp_pos, int *disp_prop, + struct bidi_string_data *string, + struct window *w, bool frame_window_p, + ptrdiff_t *ch_len, ptrdiff_t *nchars) +{ + ptrdiff_t orig_charpos = charpos, orig_bytepos = bytepos; + int ch = bidi_fetch_char (charpos, bytepos, disp_pos, disp_prop, string, w, + frame_window_p, ch_len, nchars); + bidi_type_t ch_type = bidi_get_type (ch, NEUTRAL_DIR); + ptrdiff_t level = 0; + + if (ch_type == LRI || ch_type == RLI || ch_type == FSI) + { + level++; + while (level > 0 && ch_type != NEUTRAL_B) + { + charpos += *nchars; + bytepos += *ch_len; + ch = bidi_fetch_char (charpos, bytepos, disp_pos, disp_prop, string, + w, frame_window_p, ch_len, nchars); + ch_type = bidi_get_type (ch, NEUTRAL_DIR); + /* A Note to P2 says to ignore max_depth limit. */ + if (ch_type == LRI || ch_type == RLI || ch_type == FSI) + level++; + else if (ch_type == PDI) + level--; + } + } + + /* Communicate to the caller how much did we skip, so it could get + past the last character position we examined. */ + *nchars += charpos - orig_charpos; + *ch_len += bytepos - orig_bytepos; + return ch; +} + + /*********************************************************************** Determining paragraph direction @@ -1378,6 +1483,72 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte) bidi_paragraph_init to less than 10 ms even on slow machines. */ #define MAX_STRONG_CHAR_SEARCH 100000 +/* Starting from POS, find the first strong (L, R, or AL) character, + while skipping over any characters between an isolate initiator and + its matching PDI. STOP_AT_PDI non-zero means stop at the PDI that + matches the isolate initiator at POS. Return the bidi type of the + character where the search stopped. Give up if after examining + MAX_STRONG_CHAR_SEARCH buffer or string positions no strong + character was found. */ +static bidi_type_t +find_first_strong_char (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t end, + ptrdiff_t *disp_pos, int *disp_prop, + struct bidi_string_data *string, struct window *w, + bool string_p, bool frame_window_p, + ptrdiff_t *ch_len, ptrdiff_t *nchars, bool stop_at_pdi) +{ + ptrdiff_t pos1; + bidi_type_t type; + int ch; + + if (stop_at_pdi) + { + /* If STOP_AT_PDI is non-zero, we must have been called with FSI + at POS. Get past it. */ +#ifdef ENABLE_CHECKING + ch = bidi_fetch_char (pos, bytepos, disp_pos, disp_prop, string, w, + frame_window_p, ch_len, nchars); + type = bidi_get_type (ch, NEUTRAL_DIR); + eassert (type == FSI /* || type == LRI || type == RLI */); +#endif + pos += *nchars; + bytepos += *ch_len; + } + ch = bidi_fetch_char_skip_isolates (pos, bytepos, disp_pos, disp_prop, string, + w, frame_window_p, ch_len, nchars); + type = bidi_get_type (ch, NEUTRAL_DIR); + + pos1 = pos; + for (pos += *nchars, bytepos += *ch_len; + bidi_get_category (type) != STRONG + /* If requested to stop at first PDI, stop there. */ + && !(stop_at_pdi && type == PDI) + /* Stop when searched too far into an abnormally large + paragraph full of weak or neutral characters. */ + && pos - pos1 < MAX_STRONG_CHAR_SEARCH; + type = bidi_get_type (ch, NEUTRAL_DIR)) + { + if (pos >= end) + { + /* Pretend there's a paragraph separator at end of + buffer/string. */ + type = NEUTRAL_B; + break; + } + if (!string_p + && type == NEUTRAL_B + && bidi_at_paragraph_end (pos, bytepos) >= -1) + break; + /* Fetch next character and advance to get past it. */ + ch = bidi_fetch_char_skip_isolates (pos, bytepos, disp_pos, disp_prop, + string, w, frame_window_p, + ch_len, nchars); + pos += *nchars; + bytepos += *ch_len; + } + return type; +} + /* Determine the base direction, a.k.a. base embedding level, of the paragraph we are about to iterate through. If DIR is either L2R or R2L, just use that. Otherwise, determine the paragraph direction @@ -1424,7 +1595,6 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) } else if (dir == NEUTRAL_DIR) /* P2 */ { - int ch; ptrdiff_t ch_len, nchars; ptrdiff_t pos, disp_pos = -1; int disp_prop = 0; @@ -1473,52 +1643,16 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) /* The following loop is run more than once only if NO_DEFAULT_P, and only if we are iterating on a buffer. */ do { - ptrdiff_t pos1; - bytepos = pstartbyte; if (!string_p) pos = BYTE_TO_CHAR (bytepos); - ch = bidi_fetch_char (pos, bytepos, &disp_pos, &disp_prop, - &bidi_it->string, bidi_it->w, - bidi_it->frame_window_p, &ch_len, &nchars); - type = bidi_get_type (ch, NEUTRAL_DIR); - - pos1 = pos; - for (pos += nchars, bytepos += ch_len; - ((bidi_get_category (type) != STRONG) - || (bidi_ignore_explicit_marks_for_paragraph_level - && (type == RLE || type == RLO - || type == LRE || type == LRO))) - /* Stop when searched too far into an abnormally large - paragraph full of weak or neutral characters. */ - && pos - pos1 < MAX_STRONG_CHAR_SEARCH; - type = bidi_get_type (ch, NEUTRAL_DIR)) - { - if (pos >= end) - { - /* Pretend there's a paragraph separator at end of - buffer/string. */ - type = NEUTRAL_B; - break; - } - if (!string_p - && type == NEUTRAL_B - && bidi_at_paragraph_end (pos, bytepos) >= -1) - break; - /* Fetch next character and advance to get past it. */ - ch = bidi_fetch_char (pos, bytepos, &disp_pos, - &disp_prop, &bidi_it->string, bidi_it->w, - bidi_it->frame_window_p, &ch_len, &nchars); - pos += nchars; - bytepos += ch_len; - } - if ((type == STRONG_R || type == STRONG_AL) /* P3 */ - || (!bidi_ignore_explicit_marks_for_paragraph_level - && (type == RLO || type == RLE))) + type = find_first_strong_char (pos, bytepos, end, &disp_pos, &disp_prop, + &bidi_it->string, bidi_it->w, + string_p, bidi_it->frame_window_p, + &ch_len, &nchars, false); + if (type == STRONG_R || type == STRONG_AL) /* P3 */ bidi_it->paragraph_dir = R2L; - else if (type == STRONG_L - || (!bidi_ignore_explicit_marks_for_paragraph_level - && (type == LRO || type == LRE))) + else if (type == STRONG_L) bidi_it->paragraph_dir = L2R; if (!string_p && no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR) @@ -1581,19 +1715,60 @@ bidi_explicit_dir_char (int ch) || ch_type == PDF); } -/* A helper function for bidi_resolve_explicit. It advances to the - next character in logical order and determines the new embedding - level and directional override, but does not take into account - empty embeddings. */ +/* Given an iterator state in BIDI_IT, advance one character position + in the buffer/string to the next character (in the logical order), + resolve any explicit embeddings, directional overrides, and isolate + initiators and terminators, and return the embedding level of the + character after resolving these explicit directives. */ static int -bidi_resolve_explicit_1 (struct bidi_it *bidi_it) +bidi_resolve_explicit (struct bidi_it *bidi_it) { int curchar; - bidi_type_t type; + bidi_type_t type, typ1, prev_type = UNKNOWN_BT; int current_level; int new_level; bidi_dir_t override; + bool isolate_status; bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring); + ptrdiff_t ch_len, nchars, disp_pos, end; + int disp_prop; + + /* Record the info about the previous character. */ + if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */ + && bidi_it->type != WEAK_BN) + { + /* This special case is needed in support of Unicode 8.0 + correction to N0, as implemented in bidi_resolve_weak/W1 + below. */ + if (bidi_it->type_after_wn == NEUTRAL_ON + && bidi_get_category (bidi_it->type) == STRONG + && bidi_paired_bracket_type (bidi_it->ch) == BIDI_BRACKET_CLOSE) + bidi_remember_char (&bidi_it->prev, bidi_it, 1); + else + bidi_remember_char (&bidi_it->prev, bidi_it, 0); + } + if (bidi_it->type_after_wn == STRONG_R + || bidi_it->type_after_wn == STRONG_L + || bidi_it->type_after_wn == STRONG_AL) + bidi_remember_char (&bidi_it->last_strong, bidi_it, 0); + if (bidi_it->type == STRONG_R || bidi_it->type == STRONG_L + || bidi_it->type == WEAK_EN || bidi_it->type == WEAK_AN) + bidi_remember_char (&bidi_it->prev_for_neutral, bidi_it, 1); + + /* If we overstepped the characters used for resolving neutrals + and whitespace, invalidate their info in the iterator. */ + if (bidi_it->charpos >= bidi_it->next_for_neutral.charpos) + bidi_it->next_for_neutral.type = UNKNOWN_BT; + if (bidi_it->next_en_pos >= 0 + && bidi_it->charpos >= bidi_it->next_en_pos) + { + bidi_it->next_en_pos = 0; + bidi_it->next_en_type = UNKNOWN_BT; + } + + /* Reset the bracket resolution info. */ + bidi_it->bracket_pairing_pos = -1; + bidi_it->bracket_enclosed_type = UNKNOWN_BT; /* If reseat()'ed, don't advance, so as to start iteration from the position where we were reseated. bidi_it->bytepos can be less @@ -1624,6 +1799,19 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) } eassert (bidi_it->bytepos == CHAR_TO_BYTE (bidi_it->charpos)); } + /* Determine the original bidi type of the previous character, + which is needed for handling isolate initiators and PDF. The + type of the previous character will be non-trivial only if + our caller moved through some previous text in + get_visually_first_element, in which case bidi_it->prev holds + the information we want. */ + if (bidi_it->first_elt && bidi_it->prev.type != UNKNOWN_BT) + { + eassert (bidi_it->prev.charpos == bidi_it->charpos - 1); + prev_type = bidi_it->prev.orig_type; + if (prev_type == FSI) + prev_type = bidi_it->type_after_wn; + } } /* Don't move at end of buffer/string. */ else if (bidi_it->charpos < (string_p ? bidi_it->string.schars : ZV)) @@ -1636,10 +1824,16 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) if (bidi_it->ch_len == 0) emacs_abort (); bidi_it->bytepos += bidi_it->ch_len; + prev_type = bidi_it->orig_type; + if (prev_type == FSI) + prev_type = bidi_it->type_after_wn; } + else /* EOB or end of string */ + prev_type = NEUTRAL_B; current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */ override = bidi_it->level_stack[bidi_it->stack_idx].override; + isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status; new_level = current_level; if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV)) @@ -1652,6 +1846,52 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) } else { + /* LRI, RLI, and FSI increment, and PDF decrements, the + embedding level of the _following_ characters, so we must + first look at the type of the previous character to support + that. */ + switch (prev_type) + { + case RLI: /* X5a */ + if (current_level < BIDI_MAXDEPTH + && bidi_it->invalid_levels == 0 + && bidi_it->invalid_isolates == 0) + { + new_level = ((current_level + 1) & ~1) + 1; + bidi_it->isolate_level++; + bidi_push_embedding_level (bidi_it, new_level, + NEUTRAL_DIR, true); + } + else + bidi_it->invalid_isolates++; + break; + case LRI: /* X5b */ + if (current_level < BIDI_MAXDEPTH - 1 + && bidi_it->invalid_levels == 0 + && bidi_it->invalid_isolates == 0) + { + new_level = ((current_level + 2) & ~1); + bidi_it->isolate_level++; + bidi_push_embedding_level (bidi_it, new_level, + NEUTRAL_DIR, true); + } + else + bidi_it->invalid_isolates++; + break; + case PDF: /* X7 */ + if (!bidi_it->invalid_isolates) + { + if (bidi_it->invalid_levels) + bidi_it->invalid_levels--; + else if (!isolate_status && bidi_it->stack_idx >= 1) + new_level = bidi_pop_embedding_level (bidi_it); + } + break; + default: + eassert (prev_type != FSI); + /* Nothing. */ + break; + } /* Fetch the character at BYTEPOS. If it is covered by a display string, treat the entire run of covered characters as a single character u+FFFC. */ @@ -1662,6 +1902,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) &bidi_it->ch_len, &bidi_it->nchars); } bidi_it->ch = curchar; + bidi_it->resolved_level = new_level; /* Don't apply directional override here, as all the types we handle below will not be affected by the override anyway, and we need @@ -1671,206 +1912,138 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) bidi_it->orig_type = type; bidi_check_type (bidi_it->orig_type); - if (type != PDF) - bidi_it->prev_was_pdf = 0; - - bidi_it->type_after_w1 = UNKNOWN_BT; + bidi_it->type_after_wn = UNKNOWN_BT; switch (type) { - case RLE: /* X2 */ - case RLO: /* X4 */ - bidi_it->type_after_w1 = type; - bidi_check_type (bidi_it->type_after_w1); - type = WEAK_BN; /* X9/Retaining */ - if (bidi_it->ignore_bn_limit <= -1) - { - if (current_level <= BIDI_MAXLEVEL - 4) - { - /* Compute the least odd embedding level greater than - the current level. */ - new_level = ((current_level + 1) & ~1) + 1; - if (bidi_it->type_after_w1 == RLE) - override = NEUTRAL_DIR; - else - override = R2L; - if (current_level == BIDI_MAXLEVEL - 4) - bidi_it->invalid_rl_levels = 0; - bidi_push_embedding_level (bidi_it, new_level, override); - } - else - { - bidi_it->invalid_levels++; - /* See the commentary about invalid_rl_levels below. */ - if (bidi_it->invalid_rl_levels < 0) - bidi_it->invalid_rl_levels = 0; - bidi_it->invalid_rl_levels++; - } - } - else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */ - || (bidi_it->next_en_pos > bidi_it->charpos - && bidi_it->next_en_type == WEAK_EN)) - type = WEAK_EN; - break; - case LRE: /* X3 */ - case LRO: /* X5 */ - bidi_it->type_after_w1 = type; - bidi_check_type (bidi_it->type_after_w1); - type = WEAK_BN; /* X9/Retaining */ - if (bidi_it->ignore_bn_limit <= -1) - { - if (current_level <= BIDI_MAXLEVEL - 5) - { - /* Compute the least even embedding level greater than - the current level. */ - new_level = ((current_level + 2) & ~1); - if (bidi_it->type_after_w1 == LRE) - override = NEUTRAL_DIR; - else - override = L2R; - bidi_push_embedding_level (bidi_it, new_level, override); - } - else - { - bidi_it->invalid_levels++; - /* invalid_rl_levels counts invalid levels encountered - while the embedding level was already too high for - LRE/LRO, but not for RLE/RLO. That is because - there may be exactly one PDF which we should not - ignore even though invalid_levels is non-zero. - invalid_rl_levels helps to know what PDF is - that. */ - if (bidi_it->invalid_rl_levels >= 0) - bidi_it->invalid_rl_levels++; - } - } - else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */ - || (bidi_it->next_en_pos > bidi_it->charpos - && bidi_it->next_en_type == WEAK_EN)) - type = WEAK_EN; - break; - case PDF: /* X7 */ - bidi_it->type_after_w1 = type; - bidi_check_type (bidi_it->type_after_w1); - type = WEAK_BN; /* X9/Retaining */ - if (bidi_it->ignore_bn_limit <= -1) - { - if (!bidi_it->invalid_rl_levels) - { - new_level = bidi_pop_embedding_level (bidi_it); - bidi_it->invalid_rl_levels = -1; - if (bidi_it->invalid_levels) - bidi_it->invalid_levels--; - /* else nothing: UAX#9 says to ignore invalid PDFs */ - } - if (!bidi_it->invalid_levels) - new_level = bidi_pop_embedding_level (bidi_it); - else - { - bidi_it->invalid_levels--; - bidi_it->invalid_rl_levels--; - } - } - else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */ - || (bidi_it->next_en_pos > bidi_it->charpos - && bidi_it->next_en_type == WEAK_EN)) - type = WEAK_EN; - break; - default: - /* Nothing. */ - break; - } - - bidi_it->type = type; - bidi_check_type (bidi_it->type); - - return new_level; -} - -/* Given an iterator state in BIDI_IT, advance one character position - in the buffer/string to the next character (in the logical order), - resolve any explicit embeddings and directional overrides, and - return the embedding level of the character after resolving - explicit directives and ignoring empty embeddings. */ -static int -bidi_resolve_explicit (struct bidi_it *bidi_it) -{ - int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; - int new_level = bidi_resolve_explicit_1 (bidi_it); - ptrdiff_t eob = bidi_it->string.s ? bidi_it->string.schars : ZV; - const unsigned char *s - = (STRINGP (bidi_it->string.lstring) - ? SDATA (bidi_it->string.lstring) - : bidi_it->string.s); - - if (prev_level < new_level - && bidi_it->type == WEAK_BN - && bidi_it->ignore_bn_limit == -1 /* only if not already known */ - && bidi_it->charpos < eob /* not already at EOB */ - && bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos - + bidi_it->ch_len, s, - bidi_it->string.unibyte))) - { - /* Avoid pushing and popping embedding levels if the level run - is empty, as this breaks level runs where it shouldn't. - UAX#9 removes all the explicit embedding and override codes, - so empty embeddings disappear without a trace. We need to - behave as if we did the same. */ - struct bidi_it saved_it; - int level = prev_level; - - bidi_copy_it (&saved_it, bidi_it); - - while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos - + bidi_it->ch_len, s, - bidi_it->string.unibyte))) + case RLE: /* X2 */ + case RLO: /* X4 */ + bidi_it->type_after_wn = type; + bidi_check_type (bidi_it->type_after_wn); + type = WEAK_BN; /* X9/Retaining */ + if (new_level < BIDI_MAXDEPTH + && bidi_it->invalid_levels == 0 + && bidi_it->invalid_isolates == 0) { - /* This advances to the next character, skipping any - characters covered by display strings. */ - level = bidi_resolve_explicit_1 (bidi_it); - /* If string.lstring was relocated inside bidi_resolve_explicit_1, - a pointer to its data is no longer valid. */ - if (STRINGP (bidi_it->string.lstring)) - s = SDATA (bidi_it->string.lstring); + /* Compute the least odd embedding level greater than + the current level. */ + new_level = ((new_level + 1) & ~1) + 1; + if (bidi_it->type_after_wn == RLE) + override = NEUTRAL_DIR; + else + override = R2L; + bidi_push_embedding_level (bidi_it, new_level, override, false); + bidi_it->resolved_level = new_level; } - - if (bidi_it->nchars <= 0) - emacs_abort (); - if (level == prev_level) /* empty embedding */ - saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars; - else /* this embedding is non-empty */ - saved_it.ignore_bn_limit = -2; - - bidi_copy_it (bidi_it, &saved_it); - if (bidi_it->ignore_bn_limit > -1) + else { - /* We pushed a level, but we shouldn't have. Undo that. */ - if (!bidi_it->invalid_rl_levels) - { - new_level = bidi_pop_embedding_level (bidi_it); - bidi_it->invalid_rl_levels = -1; - if (bidi_it->invalid_levels) - bidi_it->invalid_levels--; - } - if (!bidi_it->invalid_levels) - new_level = bidi_pop_embedding_level (bidi_it); + if (bidi_it->invalid_isolates == 0) + bidi_it->invalid_levels++; + } + break; + case LRE: /* X3 */ + case LRO: /* X5 */ + bidi_it->type_after_wn = type; + bidi_check_type (bidi_it->type_after_wn); + type = WEAK_BN; /* X9/Retaining */ + if (new_level < BIDI_MAXDEPTH - 1 + && bidi_it->invalid_levels == 0 + && bidi_it->invalid_isolates == 0) + { + /* Compute the least even embedding level greater than + the current level. */ + new_level = ((new_level + 2) & ~1); + if (bidi_it->type_after_wn == LRE) + override = NEUTRAL_DIR; else - { - bidi_it->invalid_levels--; - bidi_it->invalid_rl_levels--; - } + override = L2R; + bidi_push_embedding_level (bidi_it, new_level, override, false); + bidi_it->resolved_level = new_level; + } + else + { + if (bidi_it->invalid_isolates == 0) + bidi_it->invalid_levels++; + } + break; + case FSI: /* X5c */ + end = string_p ? bidi_it->string.schars : ZV; + disp_pos = bidi_it->disp_pos; + disp_prop = bidi_it->disp_prop; + nchars = bidi_it->nchars; + ch_len = bidi_it->ch_len; + typ1 = find_first_strong_char (bidi_it->charpos, + bidi_it->bytepos, end, + &disp_pos, &disp_prop, + &bidi_it->string, bidi_it->w, + string_p, bidi_it->frame_window_p, + &ch_len, &nchars, true); + if (typ1 != STRONG_R && typ1 != STRONG_AL) + { + type = LRI; + goto fsi_as_lri; + } + else + type = RLI; + /* FALLTHROUGH */ + case RLI: /* X5a */ + if (override == NEUTRAL_DIR) + bidi_it->type_after_wn = type; + else /* Unicode 8.0 correction. */ + bidi_it->type_after_wn = (override == L2R ? STRONG_L : STRONG_R); + bidi_check_type (bidi_it->type_after_wn); + break; + case LRI: /* X5b */ + fsi_as_lri: + if (override == NEUTRAL_DIR) + bidi_it->type_after_wn = type; + else /* Unicode 8.0 correction. */ + bidi_it->type_after_wn = (override == L2R ? STRONG_L : STRONG_R); + bidi_check_type (bidi_it->type_after_wn); + break; + case PDI: /* X6a */ + if (bidi_it->invalid_isolates) + bidi_it->invalid_isolates--; + else if (bidi_it->isolate_level > 0) + { + bidi_it->invalid_levels = 0; + while (!bidi_it->level_stack[bidi_it->stack_idx].isolate_status) + bidi_pop_embedding_level (bidi_it); + eassert (bidi_it->stack_idx > 0); + new_level = bidi_pop_embedding_level (bidi_it); + bidi_it->isolate_level--; } + bidi_it->resolved_level = new_level; + /* Unicode 8.0 correction. */ + if (bidi_it->level_stack[bidi_it->stack_idx].override == L2R) + bidi_it->type_after_wn = STRONG_L; + else if (bidi_it->level_stack[bidi_it->stack_idx].override == R2L) + bidi_it->type_after_wn = STRONG_R; + else + bidi_it->type_after_wn = type; + break; + case PDF: /* X7 */ + bidi_it->type_after_wn = type; + bidi_check_type (bidi_it->type_after_wn); + type = WEAK_BN; /* X9/Retaining */ + break; + default: + /* Nothing. */ + break; } + bidi_it->type = type; + bidi_check_type (bidi_it->type); + if (bidi_it->type == NEUTRAL_B) /* X8 */ { bidi_set_paragraph_end (bidi_it); /* This is needed by bidi_resolve_weak below, and in L1. */ - bidi_it->type_after_w1 = bidi_it->type; - bidi_check_type (bidi_it->type_after_w1); + bidi_it->type_after_wn = bidi_it->type; } - return new_level; + eassert (bidi_it->resolved_level >= 0); + return bidi_it->resolved_level; } /* Advance in the buffer/string, resolve weak types and return the @@ -1892,26 +2065,25 @@ bidi_resolve_weak (struct bidi_it *bidi_it) type = bidi_it->type; override = bidi_it->level_stack[bidi_it->stack_idx].override; - if (type == UNKNOWN_BT - || type == LRE - || type == LRO - || type == RLE - || type == RLO - || type == PDF) - emacs_abort (); + eassert (!(type == UNKNOWN_BT + || type == LRE + || type == LRO + || type == RLE + || type == RLO + || type == PDF)); - if (new_level != prev_level - || bidi_it->type == NEUTRAL_B) + eassert (prev_level >= 0); + if (bidi_it->type == NEUTRAL_B) { - /* We've got a new embedding level run, compute the directional - type of sor and initialize per-run variables (UAX#9, clause + /* We've got a new isolating sequence, compute the directional + type of sos and initialize per-run variables (UAX#9, clause X10). */ - bidi_set_sor_type (bidi_it, prev_level, new_level); + bidi_set_sos_type (bidi_it, prev_level, new_level); } - else if (type == NEUTRAL_S || type == NEUTRAL_WS - || type == WEAK_BN || type == STRONG_AL) - bidi_it->type_after_w1 = type; /* needed in L1 */ - bidi_check_type (bidi_it->type_after_w1); + if (type == NEUTRAL_S || type == NEUTRAL_WS + || type == WEAK_BN || type == STRONG_AL) + bidi_it->type_after_wn = type; /* needed in L1 */ + bidi_check_type (bidi_it->type_after_wn); /* Level and directional override status are already recorded in bidi_it, and do not need any change; see X6. */ @@ -1928,31 +2100,49 @@ bidi_resolve_weak (struct bidi_it *bidi_it) because then either the type of this NSM would have been also overridden, or the previous character is outside the current level run, and thus not relevant to this NSM. - This is why NSM gets the type_after_w1 of the previous + This is why NSM gets the type_after_wn of the previous character. */ - if (bidi_it->prev.type_after_w1 != UNKNOWN_BT - /* if type_after_w1 is NEUTRAL_B, this NSM is at sor */ - && bidi_it->prev.type_after_w1 != NEUTRAL_B) - type = bidi_it->prev.type_after_w1; - else if (bidi_it->sor == R2L) + /* bidi_set_sos_type sets type_after_wn to UNKNOWN_BT. */ + if (bidi_it->prev.type != UNKNOWN_BT + /* If type_after_wn is NEUTRAL_B, this NSM is at sos. */ + && bidi_it->prev.type != NEUTRAL_B) + { + if (bidi_isolate_fmt_char (bidi_it->prev.type)) + { + /* From W1: "Note that in an isolating run sequence, + an isolate initiator followed by an NSM or any + type other than PDI must be an overflow isolate + initiator." */ + eassert (bidi_it->invalid_isolates > 0); + type = NEUTRAL_ON; + } + else + { + /* This includes the Unicode 8.0 correction for N0, + due to how we set prev.type in bidi_resolve_explicit, + which see. */ + type = bidi_it->prev.type; + } + } + else if (bidi_it->sos == R2L) type = STRONG_R; - else if (bidi_it->sor == L2R) + else if (bidi_it->sos == L2R) type = STRONG_L; else /* shouldn't happen! */ emacs_abort (); } if (type == WEAK_EN /* W2 */ - && bidi_it->last_strong.type_after_w1 == STRONG_AL) + && bidi_it->last_strong.type == STRONG_AL) type = WEAK_AN; else if (type == STRONG_AL) /* W3 */ type = STRONG_R; else if ((type == WEAK_ES /* W4 */ - && bidi_it->prev.type_after_w1 == WEAK_EN + && bidi_it->prev.type == WEAK_EN && bidi_it->prev.orig_type == WEAK_EN) || (type == WEAK_CS - && ((bidi_it->prev.type_after_w1 == WEAK_EN + && ((bidi_it->prev.type == WEAK_EN && bidi_it->prev.orig_type == WEAK_EN) - || bidi_it->prev.type_after_w1 == WEAK_AN))) + || bidi_it->prev.type == WEAK_AN))) { const unsigned char *s = (STRINGP (bidi_it->string.lstring) @@ -1971,8 +2161,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it) bidi_copy_it (&saved_it, bidi_it); while (bidi_resolve_explicit (bidi_it) == new_level && bidi_it->type == WEAK_BN) - ; - type_of_next = bidi_it->type; + type_of_next = bidi_it->type; bidi_copy_it (bidi_it, &saved_it); } @@ -1982,11 +2171,11 @@ bidi_resolve_weak (struct bidi_it *bidi_it) should not be changed into EN. */ if (type == WEAK_ES && type_of_next == WEAK_EN - && bidi_it->last_strong.type_after_w1 != STRONG_AL) + && bidi_it->last_strong.type != STRONG_AL) type = WEAK_EN; else if (type == WEAK_CS) { - if (bidi_it->prev.type_after_w1 == WEAK_AN + if (bidi_it->prev.type == WEAK_AN && (type_of_next == WEAK_AN /* If the next character is EN, but the last strong-type character is AL, EN will be later @@ -1994,18 +2183,18 @@ bidi_resolve_weak (struct bidi_it *bidi_it) So in that case, this ES should not be changed into EN. */ || (type_of_next == WEAK_EN - && bidi_it->last_strong.type_after_w1 == STRONG_AL))) + && bidi_it->last_strong.type == STRONG_AL))) type = WEAK_AN; - else if (bidi_it->prev.type_after_w1 == WEAK_EN + else if (bidi_it->prev.type == WEAK_EN && type_of_next == WEAK_EN - && bidi_it->last_strong.type_after_w1 != STRONG_AL) + && bidi_it->last_strong.type != STRONG_AL) type = WEAK_EN; } } else if (type == WEAK_ET /* W5: ET with EN before or after it */ || type == WEAK_BN) /* W5/Retaining */ { - if (bidi_it->prev.type_after_w1 == WEAK_EN) /* ET/BN w/EN before it */ + if (bidi_it->prev.type == WEAK_EN) /* ET/BN w/EN before it */ type = WEAK_EN; else if (bidi_it->next_en_pos > bidi_it->charpos && bidi_it->next_en_type != WEAK_BN) @@ -2015,6 +2204,12 @@ bidi_resolve_weak (struct bidi_it *bidi_it) } else if (bidi_it->next_en_pos >=0) { + /* We overstepped the last known position for ET + resolution but there could be other such characters + in this paragraph (when we are sure there are no more + such positions, we set next_en_pos to a negative + value). Try to find the next position for ET + resolution. */ ptrdiff_t en_pos = bidi_it->charpos + bidi_it->nchars; const unsigned char *s = (STRINGP (bidi_it->string.lstring) ? SDATA (bidi_it->string.lstring) @@ -2037,9 +2232,20 @@ bidi_resolve_weak (struct bidi_it *bidi_it) while (bidi_resolve_explicit (bidi_it) == new_level && (bidi_it->type == WEAK_BN || bidi_it->type == WEAK_ET)) - ; - type_of_next = bidi_it->type; - en_pos = bidi_it->charpos; + type_of_next = bidi_it->type; + if (type == WEAK_BN + && bidi_it->charpos == saved_it.charpos + saved_it.nchars) + { + /* If we entered the above loop with a BN that + changes the level, the type of next + character, which is in a different level, is + not relevant to resolving this series of ET + and BN. */ + en_pos = saved_it.charpos; + type_of_next = type; + } + else + en_pos = bidi_it->charpos; bidi_copy_it (bidi_it, &saved_it); } /* Remember this position, to speed up processing of the @@ -2049,7 +2255,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it) { /* If the last strong character is AL, the EN we've found will become AN when we get to it (W2). */ - if (bidi_it->last_strong.type_after_w1 == STRONG_AL) + if (bidi_it->last_strong.type == STRONG_AL) type_of_next = WEAK_AN; else if (type == WEAK_BN) type = NEUTRAL_ON; /* W6/Retaining */ @@ -2069,23 +2275,23 @@ bidi_resolve_weak (struct bidi_it *bidi_it) if (type == WEAK_ES || type == WEAK_ET || type == WEAK_CS /* W6 */ || (type == WEAK_BN - && (bidi_it->prev.type_after_w1 == WEAK_CS /* W6/Retaining */ - || bidi_it->prev.type_after_w1 == WEAK_ES - || bidi_it->prev.type_after_w1 == WEAK_ET))) + && (bidi_it->prev.type == WEAK_CS /* W6/Retaining */ + || bidi_it->prev.type == WEAK_ES + || bidi_it->prev.type == WEAK_ET))) type = NEUTRAL_ON; /* Store the type we've got so far, before we clobber it with strong types in W7 and while resolving neutral types. But leave alone the original types that were recorded above, because we will need them for the L1 clause. */ - if (bidi_it->type_after_w1 == UNKNOWN_BT) - bidi_it->type_after_w1 = type; - bidi_check_type (bidi_it->type_after_w1); + if (bidi_it->type_after_wn == UNKNOWN_BT) + bidi_it->type_after_wn = type; + bidi_check_type (bidi_it->type_after_wn); if (type == WEAK_EN) /* W7 */ { - if ((bidi_it->last_strong.type_after_w1 == STRONG_L) - || (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sor == L2R)) + if ((bidi_it->last_strong.type == STRONG_L) + || (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sos == L2R)) type = STRONG_L; } @@ -2099,7 +2305,8 @@ bidi_resolve_weak (struct bidi_it *bidi_it) static bidi_type_t bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev) { - /* N1: European and Arabic numbers are treated as though they were R. */ + /* N1: "European and Arabic numbers act as if they were R in terms + of their influence on NIs." */ if (next_type == WEAK_EN || next_type == WEAK_AN) next_type = STRONG_R; if (prev_type == WEAK_EN || prev_type == WEAK_AN) @@ -2113,33 +2320,440 @@ bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev) return STRONG_R; } +#define FLAG_EMBEDDING_INSIDE 1 +#define FLAG_OPPOSITE_INSIDE 2 + +/* A data type used in the stack maintained by + bidi_find_bracket_pairs below. */ +typedef struct bpa_stack_entry { + int close_bracket_char; + int open_bracket_idx; +#ifdef ENABLE_CHECKING + ptrdiff_t open_bracket_pos; +#endif + unsigned flags : 2; +} bpa_stack_entry; + +/* With MAX_ALLOCA of 16KB, this should allow at least 1K slots in the + BPA stack, which should be more than enough for actual bidi text. */ +#define MAX_BPA_STACK (max (MAX_ALLOCA / sizeof (bpa_stack_entry), 1)) + +/* UAX#9 says to match opening brackets with the matching closing + brackets or their canonical equivalents. As of Unicode 7.0, there + are only 2 bracket characters that have canonical equivalence + decompositions: u+2329 and u+232A. So instead of accessing the + table in uni-decomposition.el, we just handle these 2 characters + with this simple macro. Note that ASCII characters don't have + canonical equivalents by definition. */ + +/* To find all the characters that need to be processed by + CANONICAL_EQU, first find all the characters which have + decompositions in UnicodeData.txt, with this Awk script: + + awk -F ";" " {if ($6 != \"\") print $1, $6}" UnicodeData.txt + + Then produce a list of all the bracket characters in BidiBrackets.txt: + + awk -F "[ ;]" " {if ($1 != \"#\" && $1 != \"\") print $1}" BidiBrackets.txt + + And finally, cross-reference these two: + + fgrep -w -f brackets.txt decompositions.txt + + where "decompositions.txt" was produced by the 1st script, and + "brackets.txt" by the 2nd script. In the output of fgrep, look + only for decompositions that don't begin with some compatibility + formatting tag, such as "<compat>". Only decompositions that + consist solely of character codepoints are relevant to bidi + brackets processing. */ + +#define CANONICAL_EQU(c) \ + ( ASCII_CHAR_P (c) ? c \ + : (c) == 0x2329 ? 0x3008 \ + : (c) == 0x232a ? 0x3009 \ + : c ) + +#ifdef ENABLE_CHECKING +# define STORE_BRACKET_CHARPOS \ + bpa_stack[bpa_sp].open_bracket_pos = bidi_it->charpos +#else +# define STORE_BRACKET_CHARPOS /* nothing */ +#endif + +#define PUSH_BPA_STACK \ + do { \ + int ch; \ + bpa_sp++; \ + if (bpa_sp >= MAX_BPA_STACK) \ + { \ + bpa_sp = MAX_BPA_STACK - 1; \ + goto bpa_give_up; \ + } \ + ch = CANONICAL_EQU (bidi_it->ch); \ + bpa_stack[bpa_sp].close_bracket_char = bidi_mirror_char (ch); \ + bpa_stack[bpa_sp].open_bracket_idx = bidi_cache_last_idx; \ + bpa_stack[bpa_sp].flags = 0; \ + STORE_BRACKET_CHARPOS; \ + } while (0) + + +/* This function implements BPA, the Bidi Parenthesis Algorithm, + described in BD16 and N0 of UAX#9. It finds all the bracket pairs + in the current isolating sequence, and records the enclosed type + and the position of the matching bracket in the cache. It returns + non-zero if called with the iterator on the opening bracket which + has a matching closing bracket in the current isolating sequence, + zero otherwise. */ +static bool +bidi_find_bracket_pairs (struct bidi_it *bidi_it) +{ + bidi_bracket_type_t btype; + bidi_type_t type = bidi_it->type; + bool retval = false; + + /* When scanning backwards, we don't expect any unresolved bidi + bracket characters. */ + if (bidi_it->scan_dir != 1) + emacs_abort (); + + btype = bidi_paired_bracket_type (bidi_it->ch); + if (btype == BIDI_BRACKET_OPEN) + { + bpa_stack_entry bpa_stack[MAX_BPA_STACK]; + int bpa_sp = -1; + struct bidi_it saved_it; + int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level; + bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L; + struct bidi_it tem_it; + + eassert (MAX_BPA_STACK >= 100); + bidi_copy_it (&saved_it, bidi_it); + /* bidi_cache_iterator_state refuses to cache on backward scans, + and bidi_cache_fetch_state doesn't bring scan_dir from the + cache, so we must initialize this explicitly. */ + tem_it.scan_dir = 1; + + while (1) + { + int old_sidx, new_sidx; + int current_level = bidi_it->level_stack[bidi_it->stack_idx].level; + + /* Mark every opening bracket character we've traversed by + putting its own position into bracket_pairing_pos. This + is examined in bidi_resolve_brackets to distinguish + brackets that were already resolved to stay NEUTRAL_ON, + and those that were not yet processed by this function + (because they were skipped when we skip higher embedding + levels below). */ + if (btype == BIDI_BRACKET_OPEN && bidi_it->bracket_pairing_pos == -1) + bidi_it->bracket_pairing_pos = bidi_it->charpos; + bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); + if (btype == BIDI_BRACKET_OPEN) + PUSH_BPA_STACK; + else if (btype == BIDI_BRACKET_CLOSE) + { + int sp = bpa_sp; + int curchar = CANONICAL_EQU (bidi_it->ch); + + eassert (sp >= 0); + while (sp >= 0 && bpa_stack[sp].close_bracket_char != curchar) + sp--; + if (sp >= 0) + { + /* Update and cache the corresponding opening bracket. */ + bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx, + &tem_it); +#ifdef ENABLE_CHECKING + eassert (bpa_stack[sp].open_bracket_pos == tem_it.charpos); +#endif + /* Determine the enclosed type for this bracket + pair's type resolution according to N0. */ + if (bpa_stack[sp].flags & FLAG_EMBEDDING_INSIDE) + tem_it.bracket_enclosed_type = embedding_type; /* N0b */ + else if (bpa_stack[sp].flags & FLAG_OPPOSITE_INSIDE) + tem_it.bracket_enclosed_type /* N0c */ + = (embedding_type == STRONG_L ? STRONG_R : STRONG_L); + else /* N0d */ + tem_it.bracket_enclosed_type = UNKNOWN_BT; + + /* Record the position of the matching closing + bracket, and update the cache. */ + tem_it.bracket_pairing_pos = bidi_it->charpos; + bidi_cache_iterator_state (&tem_it, 0, 1); + + /* Pop the BPA stack. */ + bpa_sp = sp - 1; + } + if (bpa_sp < 0) + { + retval = true; + break; + } + } + else if (bidi_get_category (bidi_it->type_after_wn) != NEUTRAL) + { + unsigned flag = 0; + int sp; + + /* Whenever we see a strong type, update the flags of + all the slots on the stack. */ + switch (bidi_it->type) + { + case STRONG_L: + flag = ((embedding_level & 1) == 0 + ? FLAG_EMBEDDING_INSIDE + : FLAG_OPPOSITE_INSIDE); + break; + case STRONG_R: + case WEAK_EN: + case WEAK_AN: + flag = ((embedding_level & 1) == 1 + ? FLAG_EMBEDDING_INSIDE + : FLAG_OPPOSITE_INSIDE); + break; + default: + break; + } + if (flag) + { + for (sp = bpa_sp; sp >= 0; sp--) + bpa_stack[sp].flags |= flag; + } + } + old_sidx = bidi_it->stack_idx; + type = bidi_resolve_weak (bidi_it); + /* Skip level runs excluded from this isolating run sequence. */ + new_sidx = bidi_it->stack_idx; + if (bidi_it->level_stack[new_sidx].level > current_level + && (bidi_it->level_stack[new_sidx].isolate_status + || (new_sidx > old_sidx + 1 + && bidi_it->level_stack[new_sidx - 1].isolate_status))) + { + while (bidi_it->level_stack[bidi_it->stack_idx].level + > current_level) + { + bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); + type = bidi_resolve_weak (bidi_it); + } + } + if (type == NEUTRAL_B + || (bidi_it->level_stack[bidi_it->stack_idx].level + != current_level)) + { + bpa_give_up: + /* We've marched all the way to the end of this + isolating run sequence, and didn't find matching + closing brackets for some opening brackets. Leave + their type unchanged. */ + break; + } + if (bidi_it->type_after_wn == NEUTRAL_ON) /* Unicode 8.0 correction */ + btype = bidi_paired_bracket_type (bidi_it->ch); + else + btype = BIDI_BRACKET_NONE; + } + + /* Restore bidi_it from the cache, which should have the bracket + resolution members set as determined by the above loop. */ + type = bidi_cache_find (saved_it.charpos, 0, bidi_it); + eassert (type == NEUTRAL_ON); + } + + return retval; +} + +static void +bidi_record_type_for_neutral (struct bidi_saved_info *info, int level, + bool nextp) +{ + int idx; + + for (idx = bidi_cache_last_idx + 1; idx < bidi_cache_idx; idx++) + { + int lev = bidi_cache[idx].level_stack[bidi_cache[idx].stack_idx].level; + + if (lev <= level) + { + eassert (lev == level); + if (nextp) + bidi_cache[idx].next_for_neutral = *info; + else + bidi_cache[idx].prev_for_neutral = *info; + break; + } + } +} + static bidi_type_t -bidi_resolve_neutral (struct bidi_it *bidi_it) +bidi_resolve_brackets (struct bidi_it *bidi_it) { int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; - bidi_type_t type = bidi_resolve_weak (bidi_it); - int current_level = bidi_it->level_stack[bidi_it->stack_idx].level; - - if (!(type == STRONG_R - || type == STRONG_L - || type == WEAK_BN - || type == WEAK_EN - || type == WEAK_AN - || type == NEUTRAL_B - || type == NEUTRAL_S - || type == NEUTRAL_WS - || type == NEUTRAL_ON)) - emacs_abort (); + bool resolve_bracket = false; + bidi_type_t type = UNKNOWN_BT; + int ch; + struct bidi_saved_info prev_for_neutral, next_for_neutral; + + /* Record the prev_for_neutral type either from the previous + character, if it was a strong or AN/EN, or from the + prev_for_neutral information recorded previously. */ + if (bidi_it->type == STRONG_L || bidi_it->type == STRONG_R + || bidi_it->type == WEAK_AN || bidi_it->type == WEAK_EN) + bidi_remember_char (&prev_for_neutral, bidi_it, 1); + else + prev_for_neutral = bidi_it->prev_for_neutral; + /* Record the next_for_neutral type information. */ + if (bidi_it->next_for_neutral.charpos > bidi_it->charpos) + next_for_neutral = bidi_it->next_for_neutral; + else + next_for_neutral.charpos = -1; + if (!bidi_it->first_elt) + { + type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 0, bidi_it); + ch = bidi_it->ch; + } + if (type == UNKNOWN_BT) + { + type = bidi_resolve_weak (bidi_it); + if (type == NEUTRAL_ON && bidi_find_bracket_pairs (bidi_it)) + resolve_bracket = true; + } + else + { + eassert (bidi_it->resolved_level == -1); + /* If the cached state shows an increase of embedding level due + to an isolate initiator, we need to update the 1st cached + state of the next run of the current isolating sequence with + the prev_for_neutral and next_for_neutral information, so + that it will be picked up when we advance to that next run. */ + if (bidi_it->level_stack[bidi_it->stack_idx].level > prev_level + && bidi_it->level_stack[bidi_it->stack_idx].isolate_status) + { + bidi_record_type_for_neutral (&prev_for_neutral, prev_level, 0); + bidi_record_type_for_neutral (&next_for_neutral, prev_level, 1); + } + if (type == NEUTRAL_ON + && bidi_paired_bracket_type (ch) == BIDI_BRACKET_OPEN) + { + if (bidi_it->bracket_pairing_pos > bidi_it->charpos) + { + /* A cached opening bracket that wasn't completely + resolved yet. */ + resolve_bracket = true; + } + else if (bidi_it->bracket_pairing_pos == -1) + { + /* Higher levels were not BPA-resolved yet, even if + cached by bidi_find_bracket_pairs. Force application + of BPA to the new level now. */ + if (bidi_find_bracket_pairs (bidi_it)) + resolve_bracket = true; + } + } + /* Keep track of the prev_for_neutral and next_for_neutral + types, needed for resolving brackets below and for resolving + neutrals in bidi_resolve_neutral. */ + if (bidi_it->level_stack[bidi_it->stack_idx].level == prev_level) + { + bidi_it->prev_for_neutral = prev_for_neutral; + if (next_for_neutral.charpos > 0) + bidi_it->next_for_neutral = next_for_neutral; + } + } + + /* If needed, resolve the bracket type according to N0. */ + if (resolve_bracket) + { + int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level; + bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L; + + eassert (bidi_it->prev_for_neutral.type != UNKNOWN_BT); + eassert (bidi_it->bracket_pairing_pos > bidi_it->charpos); + if (bidi_it->bracket_enclosed_type == embedding_type) /* N0b */ + type = embedding_type; + else + { + switch (bidi_it->prev_for_neutral.type) + { + case STRONG_R: + case WEAK_EN: + case WEAK_AN: + type = + (bidi_it->bracket_enclosed_type == STRONG_R) /* N0c */ + ? STRONG_R /* N0c1 */ + : embedding_type; /* N0c2 */ + break; + case STRONG_L: + type = + (bidi_it->bracket_enclosed_type == STRONG_L) /* N0c */ + ? STRONG_L /* N0c1 */ + : embedding_type; /* N0c2 */ + break; + default: + /* N0d: Do not set the type for that bracket pair. */ + break; + } + } + eassert (type == STRONG_L || type == STRONG_R || type == NEUTRAL_ON); + + /* Update the type of the paired closing bracket to the same + type as for the resolved opening bracket. */ + if (type != NEUTRAL_ON) + { + ptrdiff_t idx = bidi_cache_search (bidi_it->bracket_pairing_pos, + -1, 1); + + if (idx < bidi_cache_start) + emacs_abort (); + bidi_cache[idx].type = type; + } + } + + return type; +} + +static bidi_type_t +bidi_resolve_neutral (struct bidi_it *bidi_it) +{ + bidi_type_t type = bidi_resolve_brackets (bidi_it); + int current_level; + bool is_neutral; + + eassert (type == STRONG_R + || type == STRONG_L + || type == WEAK_BN + || type == WEAK_EN + || type == WEAK_AN + || type == NEUTRAL_B + || type == NEUTRAL_S + || type == NEUTRAL_WS + || type == NEUTRAL_ON + || type == LRI + || type == RLI + || type == PDI); + + current_level = bidi_it->level_stack[bidi_it->stack_idx].level; + eassert (current_level >= 0); + is_neutral = bidi_get_category (type) == NEUTRAL; if ((type != NEUTRAL_B /* Don't risk entering the long loop below if we are already at paragraph end. */ - && bidi_get_category (type) == NEUTRAL) - || (type == WEAK_BN && prev_level == current_level)) + && (is_neutral || bidi_isolate_fmt_char (type))) + /* N1-N2/Retaining */ + || (type == WEAK_BN && bidi_explicit_dir_char (bidi_it->ch))) { if (bidi_it->next_for_neutral.type != UNKNOWN_BT) - type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, - bidi_it->next_for_neutral.type, - current_level); + { + /* Make sure the data for resolving neutrals we are + about to use is valid. */ + eassert (bidi_it->next_for_neutral.charpos > bidi_it->charpos + /* PDI defines an eos, so it's OK for it to + serve as its own next_for_neutral. */ + || (bidi_it->next_for_neutral.charpos == bidi_it->charpos + && bidi_it->type == PDI)); + type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, + bidi_it->next_for_neutral.type, + current_level); + } /* The next two "else if" clauses are shortcuts for the important special case when we have a long sequence of neutral or WEAK_BN characters, such as whitespace or nulls or @@ -2155,7 +2769,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it) entering the expensive loop in the "else" clause. */ else if (current_level == 0 && bidi_it->prev_for_neutral.type == STRONG_L - && !bidi_explicit_dir_char (bidi_it->ch)) + && !bidi_explicit_dir_char (bidi_it->ch) + && !bidi_isolate_fmt_char (type)) type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, STRONG_L, current_level); else if (/* current level is 1 */ @@ -2167,7 +2782,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it) && (bidi_it->prev_for_neutral.type == STRONG_R || bidi_it->prev_for_neutral.type == WEAK_EN || bidi_it->prev_for_neutral.type == WEAK_AN) - && !bidi_explicit_dir_char (bidi_it->ch)) + && !bidi_explicit_dir_char (bidi_it->ch) + && !bidi_isolate_fmt_char (type)) type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, STRONG_R, current_level); else @@ -2182,85 +2798,107 @@ bidi_resolve_neutral (struct bidi_it *bidi_it) implementations! */ struct bidi_it saved_it; bidi_type_t next_type; - - if (bidi_it->scan_dir == -1) - emacs_abort (); + bool adjacent_to_neutrals = is_neutral; bidi_copy_it (&saved_it, bidi_it); /* Scan the text forward until we find the first non-neutral character, and then use that to resolve the neutral we are dealing with now. We also cache the scanned iterator states, to salvage some of the effort later. */ - bidi_cache_iterator_state (bidi_it, 0); do { - /* Record the info about the previous character, so that - it will be cached below with this state. */ - if (bidi_it->type_after_w1 != WEAK_BN /* W1/Retaining */ - && bidi_it->type != WEAK_BN) - bidi_remember_char (&bidi_it->prev, bidi_it); - type = bidi_resolve_weak (bidi_it); + int old_sidx, new_sidx; + /* Paragraph separators have their levels fully resolved at this point, so cache them as resolved. */ - bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B); - /* FIXME: implement L1 here, by testing for a newline and - resetting the level for any sequence of whitespace - characters adjacent to it. */ + bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); + old_sidx = bidi_it->stack_idx; + type = bidi_resolve_brackets (bidi_it); + /* Skip level runs excluded from this isolating run sequence. */ + new_sidx = bidi_it->stack_idx; + if (bidi_it->level_stack[new_sidx].level > current_level + && (bidi_it->level_stack[new_sidx].isolate_status + /* This is for when we have an isolate initiator + immediately followed by an embedding or + override initiator, in which case we get the + level stack pushed twice by the single call to + bidi_resolve_weak above. */ + || (new_sidx > old_sidx + 1 + && bidi_it->level_stack[new_sidx - 1].isolate_status))) + { + while (bidi_it->level_stack[bidi_it->stack_idx].level + > current_level) + { + bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); + type = bidi_resolve_brackets (bidi_it); + } + } + if (!adjacent_to_neutrals + && (bidi_get_category (type) == NEUTRAL + || bidi_isolate_fmt_char (type))) + adjacent_to_neutrals = true; } while (!(type == NEUTRAL_B || (type != WEAK_BN - && bidi_get_category (type) != NEUTRAL) + && bidi_get_category (type) != NEUTRAL + && !bidi_isolate_fmt_char (type)) /* This is all per level run, so stop when we reach the end of this level run. */ || (bidi_it->level_stack[bidi_it->stack_idx].level != current_level))); - bidi_remember_char (&saved_it.next_for_neutral, bidi_it); + /* Record the character we stopped at. */ + bidi_remember_char (&saved_it.next_for_neutral, bidi_it, 1); - switch (type) + if ((bidi_it->level_stack[bidi_it->stack_idx].level != current_level) + || type == NEUTRAL_B) { - case STRONG_L: - case STRONG_R: - case STRONG_AL: - /* Actually, STRONG_AL cannot happen here, because - bidi_resolve_weak converts it to STRONG_R, per W3. */ - eassert (type != STRONG_AL); - next_type = type; - break; - case WEAK_EN: - case WEAK_AN: - /* N1: ``European and Arabic numbers are treated as - though they were R.'' */ - next_type = STRONG_R; - break; - case WEAK_BN: - case NEUTRAL_ON: /* W6/Retaining */ - if (!bidi_explicit_dir_char (bidi_it->ch)) - emacs_abort (); /* can't happen: BNs are skipped */ - /* FALLTHROUGH */ - case NEUTRAL_B: - /* Marched all the way to the end of this level run. - We need to use the eor type, whose information is - stored by bidi_set_sor_type in the prev_for_neutral - member. */ - if (saved_it.type != WEAK_BN - || bidi_get_category (bidi_it->prev.type_after_w1) == NEUTRAL) - next_type = bidi_it->prev_for_neutral.type; - else - { - /* This is a BN which does not adjoin neutrals. - Leave its type alone. */ - bidi_copy_it (bidi_it, &saved_it); - return bidi_it->type; - } - break; - default: - emacs_abort (); + /* Marched all the way to the end of this level run. We + need to use the eos type, whose information is stored + by bidi_set_sos_type in the prev_for_neutral + member. */ + if (adjacent_to_neutrals) + next_type = bidi_it->prev_for_neutral.type; + else + { + /* This is a BN which does not adjoin neutrals. + Leave its type alone. */ + bidi_copy_it (bidi_it, &saved_it); + return bidi_it->type; + } + } + else + { + switch (type) + { + case STRONG_L: + case STRONG_R: + case STRONG_AL: + /* Actually, STRONG_AL cannot happen here, because + bidi_resolve_weak converts it to STRONG_R, per W3. */ + eassert (type != STRONG_AL); + next_type = type; + break; + case WEAK_EN: + case WEAK_AN: + /* N1: "European and Arabic numbers act as if they + were R in terms of their influence on NIs." */ + next_type = STRONG_R; + break; + default: + emacs_abort (); + break; + } } + /* Resolve the type of all the NIs found during the above loop. */ type = bidi_resolve_neutral_1 (saved_it.prev_for_neutral.type, next_type, current_level); + /* Update next_for_neutral with the resolved type, so we + could use it for all the other NIs up to the place where + we exited the loop. */ saved_it.next_for_neutral.type = next_type; + bidi_check_type (type); + /* Update the character which caused us to enter the above loop. */ saved_it.type = type; bidi_check_type (next_type); - bidi_check_type (type); bidi_copy_it (bidi_it, &saved_it); } } @@ -2280,14 +2918,6 @@ bidi_type_of_next_char (struct bidi_it *bidi_it) if (bidi_it->scan_dir != 1) emacs_abort (); - /* Reset the limit until which to ignore BNs if we step out of the - area where we found only empty levels. */ - if ((bidi_it->ignore_bn_limit > -1 - && bidi_it->ignore_bn_limit <= bidi_it->charpos) - || (bidi_it->ignore_bn_limit == -2 - && !bidi_explicit_dir_char (bidi_it->ch))) - bidi_it->ignore_bn_limit = -1; - type = bidi_resolve_neutral (bidi_it); return type; @@ -2300,9 +2930,8 @@ bidi_type_of_next_char (struct bidi_it *bidi_it) static int bidi_level_of_next_char (struct bidi_it *bidi_it) { - bidi_type_t type; - int level, prev_level = -1; - struct bidi_saved_info next_for_neutral; + bidi_type_t type = UNKNOWN_BT; + int level; ptrdiff_t next_char_pos = -2; if (bidi_it->scan_dir == 1) @@ -2311,54 +2940,23 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring)) ? bidi_it->string.schars : ZV); - /* There's no sense in trying to advance if we hit end of text. */ + /* There's no sense in trying to advance if we've already hit + the end of text. */ if (bidi_it->charpos >= eob) - return bidi_it->resolved_level; - - /* Record the info about the previous character. */ - if (bidi_it->type_after_w1 != WEAK_BN /* W1/Retaining */ - && bidi_it->type != WEAK_BN) - bidi_remember_char (&bidi_it->prev, bidi_it); - if (bidi_it->type_after_w1 == STRONG_R - || bidi_it->type_after_w1 == STRONG_L - || bidi_it->type_after_w1 == STRONG_AL) - bidi_remember_char (&bidi_it->last_strong, bidi_it); - /* FIXME: it sounds like we don't need both prev and - prev_for_neutral members, but I'm leaving them both for now. */ - if (bidi_it->type == STRONG_R || bidi_it->type == STRONG_L - || bidi_it->type == WEAK_EN || bidi_it->type == WEAK_AN) - bidi_remember_char (&bidi_it->prev_for_neutral, bidi_it); - - /* If we overstepped the characters used for resolving neutrals - and whitespace, invalidate their info in the iterator. */ - if (bidi_it->charpos >= bidi_it->next_for_neutral.charpos) - bidi_it->next_for_neutral.type = UNKNOWN_BT; - if (bidi_it->next_en_pos >= 0 - && bidi_it->charpos >= bidi_it->next_en_pos) { - bidi_it->next_en_pos = 0; - bidi_it->next_en_type = UNKNOWN_BT; + eassert (bidi_it->resolved_level >= 0); + return bidi_it->resolved_level; } - if (bidi_it->next_for_ws.type != UNKNOWN_BT - && bidi_it->charpos >= bidi_it->next_for_ws.charpos) - bidi_it->next_for_ws.type = UNKNOWN_BT; - - /* This must be taken before we fill the iterator with the info - about the next char. If we scan backwards, the iterator - state must be already cached, so there's no need to know the - embedding level of the previous character, since we will be - returning to our caller shortly. */ - prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; } - next_for_neutral = bidi_it->next_for_neutral; - /* Perhaps the character we want is already cached. If it is, the - call to bidi_cache_find below will return a type other than - UNKNOWN_BT. */ + /* Perhaps the character we want is already cached s fully resolved. + If it is, the call to bidi_cache_find below will return a type + other than UNKNOWN_BT. */ if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) { int bob = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring)) ? 0 : 1); + if (bidi_it->scan_dir > 0) { if (bidi_it->nchars <= 0) @@ -2372,29 +2970,15 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) cached at the beginning of the iteration. */ next_char_pos = bidi_it->charpos - 1; if (next_char_pos >= bob - 1) - type = bidi_cache_find (next_char_pos, -1, bidi_it); - else - type = UNKNOWN_BT; - } - else - type = UNKNOWN_BT; - if (type != UNKNOWN_BT) - { - /* Don't lose the information for resolving neutrals! The - cached states could have been cached before their - next_for_neutral member was computed. If we are on our way - forward, we can simply take the info from the previous - state. */ - if (bidi_it->scan_dir == 1 - && bidi_it->next_for_neutral.type == UNKNOWN_BT) - bidi_it->next_for_neutral = next_for_neutral; - - /* If resolved_level is -1, it means this state was cached - before it was completely resolved, so we cannot return - it. */ - if (bidi_it->resolved_level != -1) - return bidi_it->resolved_level; + type = bidi_cache_find (next_char_pos, 1, bidi_it); + if (type != UNKNOWN_BT) + { + /* We asked the cache for fully resolved states. */ + eassert (bidi_it->resolved_level >= 0); + return bidi_it->resolved_level; + } } + if (bidi_it->scan_dir == -1) /* If we are going backwards, the iterator state is already cached from previous scans, and should be fully resolved. */ @@ -2404,36 +2988,27 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) type = bidi_type_of_next_char (bidi_it); if (type == NEUTRAL_B) - return bidi_it->resolved_level; - - level = bidi_it->level_stack[bidi_it->stack_idx].level; - if ((bidi_get_category (type) == NEUTRAL /* && type != NEUTRAL_B */) - || (type == WEAK_BN && prev_level == level)) { - if (bidi_it->next_for_neutral.type == UNKNOWN_BT) - emacs_abort (); - - /* If the cached state shows a neutral character, it was not - resolved by bidi_resolve_neutral, so do it now. */ - type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, - bidi_it->next_for_neutral.type, - level); + eassert (bidi_it->resolved_level >= 0); + return bidi_it->resolved_level; } - if (!(type == STRONG_R - || type == STRONG_L - || type == WEAK_BN - || type == WEAK_EN - || type == WEAK_AN)) - emacs_abort (); + level = bidi_it->level_stack[bidi_it->stack_idx].level; + + eassert ((type == STRONG_R + || type == STRONG_L + || type == WEAK_BN + || type == WEAK_EN + || type == WEAK_AN)); bidi_it->type = type; bidi_check_type (bidi_it->type); /* For L1 below, we need to know, for each WS character, whether it belongs to a sequence of WS characters preceding a newline or a TAB or a paragraph separator. */ - if (bidi_it->orig_type == NEUTRAL_WS - && bidi_it->next_for_ws.type == UNKNOWN_BT) + if ((bidi_it->orig_type == NEUTRAL_WS + || bidi_isolate_fmt_char (bidi_it->orig_type)) + && bidi_it->next_for_ws.charpos < bidi_it->charpos) { int ch; ptrdiff_t clen = bidi_it->ch_len; @@ -2451,54 +3026,20 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) do { ch = bidi_fetch_char (cpos += nc, bpos += clen, &disp_pos, &dpp, &bs, bidi_it->w, fwp, &clen, &nc); - if (ch == '\n' || ch == BIDI_EOB) - chtype = NEUTRAL_B; - else - chtype = bidi_get_type (ch, NEUTRAL_DIR); + chtype = bidi_get_type (ch, NEUTRAL_DIR); } while (chtype == NEUTRAL_WS || chtype == WEAK_BN + || bidi_isolate_fmt_char (chtype) || bidi_explicit_dir_char (ch)); /* L1/Retaining */ bidi_it->next_for_ws.type = chtype; bidi_check_type (bidi_it->next_for_ws.type); bidi_it->next_for_ws.charpos = cpos; - bidi_it->next_for_ws.bytepos = bpos; } - /* Resolve implicit levels, with a twist: PDFs get the embedding - level of the embedding they terminate. See below for the - reason. */ - if (bidi_it->orig_type == PDF - /* Don't do this if this formatting code didn't change the - embedding level due to invalid or empty embeddings. */ - && prev_level != level) - { - /* Don't look in UAX#9 for the reason for this: it's our own - private quirk. The reason is that we want the formatting - codes to be delivered so that they bracket the text of their - embedding. For example, given the text - - {RLO}teST{PDF} - - we want it to be displayed as - - {PDF}STet{RLO} + /* Update the cache, but only if this state was already cached. */ + bidi_cache_iterator_state (bidi_it, 1, 1); - not as - - STet{RLO}{PDF} - - which will result because we bump up the embedding level as - soon as we see the RLO and pop it as soon as we see the PDF, - so RLO itself has the same embedding level as "teST", and - thus would be normally delivered last, just before the PDF. - The switch below fiddles with the level of PDF so that this - ugly side effect does not happen. - - (This is, of course, only important if the formatting codes - are actually displayed, but Emacs does need to display them - if the user wants to.) */ - level = prev_level; - } - else if (bidi_it->orig_type == NEUTRAL_B /* L1 */ + /* Resolve implicit levels. */ + if (bidi_it->orig_type == NEUTRAL_B /* L1 */ || bidi_it->orig_type == NEUTRAL_S || bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB || (bidi_it->orig_type == NEUTRAL_WS @@ -2560,10 +3101,10 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) if (end_flag) emacs_abort (); - bidi_cache_iterator_state (bidi_it, 1); + bidi_cache_iterator_state (bidi_it, 1, 0); do { new_level = bidi_level_of_next_char (bidi_it); - bidi_cache_iterator_state (bidi_it, 1); + bidi_cache_iterator_state (bidi_it, 1, 0); } while (new_level >= level); } } @@ -2607,7 +3148,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) sentinel.ch_len = 1; sentinel.nchars = 1; } - bidi_cache_iterator_state (&sentinel, 1); + bidi_cache_iterator_state (&sentinel, 1, 0); } old_level = bidi_it->resolved_level; @@ -2655,6 +3196,11 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) in the cache, which at this point should not happen. If it does, we will infloop. */ eassert (next_level >= 0); + /* If next_level is not consistent with incr, we might + infloop. */ + eassert (incr > 0 + ? next_level > expected_next_level + : next_level < expected_next_level); expected_next_level += incr; level_to_search += incr; bidi_find_other_level_edge (bidi_it, level_to_search, !ascending); @@ -2717,9 +3263,12 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) compromised: it assumes cached states correspond to buffer positions 1:1. */ else - bidi_cache_iterator_state (bidi_it, 1); + bidi_cache_iterator_state (bidi_it, 1, 0); } + eassert (bidi_it->resolved_level >= 0 + && bidi_it->resolved_level <= BIDI_MAXDEPTH + 2); + if (STRINGP (bidi_it->string.lstring)) UNGCPRO; } diff --git a/src/buffer.c b/src/buffer.c index 495f937d83f..80791a1fdb1 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,7 +1,6 @@ /* Buffer manipulation primitives for GNU Emacs. -Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, -Inc. +Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -42,6 +41,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "keymap.h" #include "frame.h" +#ifdef WINDOWSNT +#include "w32heap.h" /* for mmap_* */ +#endif + struct buffer *current_buffer; /* The current buffer. */ /* First buffer in chain of all buffers (in reverse order of creation). @@ -142,6 +145,10 @@ Lisp_Object Qmodification_hooks; Lisp_Object Qinsert_in_front_hooks; Lisp_Object Qinsert_behind_hooks; +Lisp_Object Qchoice, Qrange, Qleft, Qright; +Lisp_Object Qvertical_scroll_bar, Qhorizontal_scroll_bar; +static Lisp_Object Qoverwrite_mode, Qfraction; + static void alloc_buffer_text (struct buffer *, ptrdiff_t); static void free_buffer_text (struct buffer *b); static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay *); @@ -337,6 +344,11 @@ bset_scroll_bar_width (struct buffer *b, Lisp_Object val) b->INTERNAL_FIELD (scroll_bar_width) = val; } static void +bset_scroll_bar_height (struct buffer *b, Lisp_Object val) +{ + b->INTERNAL_FIELD (scroll_bar_height) = val; +} +static void bset_scroll_down_aggressively (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (scroll_down_aggressively) = val; @@ -362,6 +374,11 @@ bset_vertical_scroll_bar_type (struct buffer *b, Lisp_Object val) b->INTERNAL_FIELD (vertical_scroll_bar_type) = val; } static void +bset_horizontal_scroll_bar_type (struct buffer *b, Lisp_Object val) +{ + b->INTERNAL_FIELD (horizontal_scroll_bar_type) = val; +} +static void bset_word_wrap (struct buffer *b, Lisp_Object val) { b->INTERNAL_FIELD (word_wrap) = val; @@ -1117,10 +1134,7 @@ BUFFER defaults to the current buffer. Return nil if BUFFER has been killed. */) (register Lisp_Object buffer) { - if (NILP (buffer)) - return BVAR (current_buffer, name); - CHECK_BUFFER (buffer); - return BVAR (XBUFFER (buffer), name); + return BVAR (decode_buffer (buffer), name); } DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0, @@ -1128,10 +1142,7 @@ DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0, No argument or nil as argument means use the current buffer. */) (register Lisp_Object buffer) { - if (NILP (buffer)) - return BVAR (current_buffer, filename); - CHECK_BUFFER (buffer); - return BVAR (XBUFFER (buffer), filename); + return BVAR (decode_buffer (buffer), filename); } DEFUN ("buffer-base-buffer", Fbuffer_base_buffer, Sbuffer_base_buffer, @@ -1141,31 +1152,18 @@ If BUFFER is not indirect, return nil. BUFFER defaults to the current buffer. */) (register Lisp_Object buffer) { - struct buffer *base; - Lisp_Object base_buffer; - - if (NILP (buffer)) - base = current_buffer->base_buffer; - else - { - CHECK_BUFFER (buffer); - base = XBUFFER (buffer)->base_buffer; - } - - if (! base) - return Qnil; - XSETBUFFER (base_buffer, base); - return base_buffer; + struct buffer *base = decode_buffer (buffer)->base_buffer; + return base ? (XSETBUFFER (buffer, base), buffer) : Qnil; } DEFUN ("buffer-local-value", Fbuffer_local_value, Sbuffer_local_value, 2, 2, 0, doc: /* Return the value of VARIABLE in BUFFER. If VARIABLE does not have a buffer-local binding in BUFFER, the value -is the default binding of the variable. */) +is the default binding of the variable. */) (register Lisp_Object variable, register Lisp_Object buffer) { - register Lisp_Object result = buffer_local_value_1 (variable, buffer); + register Lisp_Object result = buffer_local_value (variable, buffer); if (EQ (result, Qunbound)) xsignal1 (Qvoid_variable, variable); @@ -1178,7 +1176,7 @@ is the default binding of the variable. */) locally unbound. */ Lisp_Object -buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer) +buffer_local_value (Lisp_Object variable, Lisp_Object buffer) { register struct buffer *buf; register Lisp_Object result; @@ -1278,20 +1276,10 @@ Most elements look like (SYMBOL . VALUE), describing one variable. For a symbol that is locally unbound, just the symbol appears in the value. Note that storing new VALUEs in these elements doesn't change the variables. No argument or nil as argument means use current buffer as BUFFER. */) - (register Lisp_Object buffer) + (Lisp_Object buffer) { - register struct buffer *buf; - register Lisp_Object result; - - if (NILP (buffer)) - buf = current_buffer; - else - { - CHECK_BUFFER (buffer); - buf = XBUFFER (buffer); - } - - result = buffer_lisp_local_variables (buf, 0); + struct buffer *buf = decode_buffer (buffer); + Lisp_Object result = buffer_lisp_local_variables (buf, 0); /* Add on all the variables stored in special slots. */ { @@ -1318,17 +1306,9 @@ DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p, 0, 1, 0, doc: /* Return t if BUFFER was modified since its file was last read or saved. No argument or nil as argument means use current buffer as BUFFER. */) - (register Lisp_Object buffer) + (Lisp_Object buffer) { - register struct buffer *buf; - if (NILP (buffer)) - buf = current_buffer; - else - { - CHECK_BUFFER (buffer); - buf = XBUFFER (buffer); - } - + struct buffer *buf = decode_buffer (buffer); return BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf) ? Qt : Qnil; } @@ -1383,7 +1363,6 @@ It is not ensured that mode lines will be updated to show the modified state of the current buffer. Use with care. */) (Lisp_Object flag) { -#ifdef CLASH_DETECTION Lisp_Object fn; /* If buffer becoming modified, lock the file. @@ -1403,7 +1382,6 @@ state of the current buffer. Use with care. */) else if (already && NILP (flag)) unlock_file (fn); } -#endif /* CLASH_DETECTION */ /* Here we have a problem. SAVE_MODIFF is used here to encode buffer-modified-p (as SAVE_MODIFF<MODIFF) as well as @@ -1436,16 +1414,7 @@ text in that buffer is changed. It wraps around occasionally. No argument or nil as argument means use current buffer as BUFFER. */) (register Lisp_Object buffer) { - register struct buffer *buf; - if (NILP (buffer)) - buf = current_buffer; - else - { - CHECK_BUFFER (buffer); - buf = XBUFFER (buffer); - } - - return make_number (BUF_MODIFF (buf)); + return make_number (BUF_MODIFF (decode_buffer (buffer))); } DEFUN ("buffer-chars-modified-tick", Fbuffer_chars_modified_tick, @@ -1460,16 +1429,7 @@ between these calls. No argument or nil as argument means use current buffer as BUFFER. */) (register Lisp_Object buffer) { - register struct buffer *buf; - if (NILP (buffer)) - buf = current_buffer; - else - { - CHECK_BUFFER (buffer); - buf = XBUFFER (buffer); - } - - return make_number (BUF_CHARS_MODIFF (buf)); + return make_number (BUF_CHARS_MODIFF (decode_buffer (buffer))); } DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2, @@ -1549,7 +1509,7 @@ frame's buffer list. The buffer is found by scanning the selected or specified frame's buffer list first, followed by the list of all buffers. If no other buffer exists, return the buffer `*scratch*' (creating it if necessary). */) - (register Lisp_Object buffer, Lisp_Object visible_ok, Lisp_Object frame) + (Lisp_Object buffer, Lisp_Object visible_ok, Lisp_Object frame) { struct frame *f = decode_any_frame (frame); Lisp_Object tail = f->buffer_list, pred = f->buffer_predicate; @@ -1592,10 +1552,11 @@ exists, return the buffer `*scratch*' (creating it if necessary). */) return notsogood; else { - buf = Fget_buffer (build_string ("*scratch*")); + AUTO_STRING (scratch, "*scratch*"); + buf = Fget_buffer (scratch); if (NILP (buf)) { - buf = Fget_buffer_create (build_string ("*scratch*")); + buf = Fget_buffer_create (scratch); Fset_buffer_major_mode (buf); } return buf; @@ -1615,10 +1576,11 @@ other_buffer_safely (Lisp_Object buffer) if (candidate_buffer (buf, buffer)) return buf; - buf = Fget_buffer (build_string ("*scratch*")); + AUTO_STRING (scratch, "*scratch*"); + buf = Fget_buffer (scratch); if (NILP (buf)) { - buf = Fget_buffer_create (build_string ("*scratch*")); + buf = Fget_buffer_create (scratch); Fset_buffer_major_mode (buf); } @@ -1823,10 +1785,8 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* Now there is no question: we can kill the buffer. */ -#ifdef CLASH_DETECTION /* Unlock this buffer's file, if it is locked. */ unlock_buffer (b); -#endif /* CLASH_DETECTION */ GCPRO1 (buffer); kill_buffer_processes (buffer); @@ -2430,6 +2390,14 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text, make_number (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))), XWINDOW (w)->contents); + /* Blindly copied from pointm part. */ + if (MARKERP (XWINDOW (w)->old_pointm) + && (EQ (XWINDOW (w)->contents, buf1) + || EQ (XWINDOW (w)->contents, buf2))) + Fset_marker (XWINDOW (w)->old_pointm, + make_number + (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))), + XWINDOW (w)->contents); if (MARKERP (XWINDOW (w)->start) && (EQ (XWINDOW (w)->contents, buf1) || EQ (XWINDOW (w)->contents, buf2))) @@ -2534,7 +2502,7 @@ current buffer is cleared. */) p = GAP_END_ADDR; stop = Z; } - if (ASCII_BYTE_P (*p)) + if (ASCII_CHAR_P (*p)) p++, pos++; else if (CHAR_BYTE8_HEAD_P (*p)) { @@ -2606,7 +2574,7 @@ current buffer is cleared. */) stop = Z; } - if (ASCII_BYTE_P (*p)) + if (ASCII_CHAR_P (*p)) p++, pos++; else if (EQ (flag, Qt) && ! CHAR_BYTE8_HEAD_P (*p) @@ -3087,13 +3055,15 @@ mouse_face_overlay_overlaps (Lisp_Object overlay) ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); ptrdiff_t n, i, size; Lisp_Object *v, tem; + Lisp_Object vbuf[10]; + USE_SAFE_ALLOCA; - size = 10; - v = alloca (size * sizeof *v); + size = ARRAYELTS (vbuf); + v = vbuf; n = overlays_in (start, end, 0, &v, &size, NULL, NULL); if (n > size) { - v = alloca (n * sizeof *v); + SAFE_NALLOCA (v, 1, n); overlays_in (start, end, 0, &v, &n, NULL, NULL); } @@ -3103,6 +3073,7 @@ mouse_face_overlay_overlaps (Lisp_Object overlay) !NILP (tem))) break; + SAFE_FREE (); return i < n; } @@ -4116,17 +4087,7 @@ BUFFER omitted or nil means delete all overlays of the current buffer. */) (Lisp_Object buffer) { - register struct buffer *buf; - - if (NILP (buffer)) - buf = current_buffer; - else - { - CHECK_BUFFER (buffer); - buf = XBUFFER (buffer); - } - - delete_all_overlays (buf); + delete_all_overlays (decode_buffer (buffer)); return Qnil; } @@ -4561,13 +4522,13 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, First copy the vector contents, in case some of these hooks do subsequent modification of the buffer. */ ptrdiff_t size = last_overlay_modification_hooks_used; - Lisp_Object *copy = alloca (size * sizeof *copy); + Lisp_Object *copy; ptrdiff_t i; + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (copy, size); memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents, size * word_size); - gcpro1.var = copy; - gcpro1.nvars = size; for (i = 0; i < size;) { @@ -4576,6 +4537,8 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, overlay_i = copy[i++]; call_overlay_mod_hooks (prop_i, overlay_i, after, arg1, arg2, arg3); } + + SAFE_FREE (); } UNGCPRO; } @@ -4640,7 +4603,8 @@ evaporate_overlays (ptrdiff_t pos) Allocation with mmap ***********************************************************************/ -#ifdef USE_MMAP_FOR_BUFFERS +/* Note: WINDOWSNT implements this stuff on w32heap.c. */ +#if defined USE_MMAP_FOR_BUFFERS && !defined WINDOWSNT #include <sys/mman.h> @@ -4706,11 +4670,6 @@ static struct mmap_region *mmap_regions; static int mmap_fd; -/* Temporary storage for mmap_set_vars, see there. */ - -static struct mmap_region *mmap_regions_1; -static int mmap_fd_1; - /* Page size on this system. */ static int mmap_page_size; @@ -4782,36 +4741,6 @@ mmap_init (void) mmap_page_size = getpagesize (); } -/* Return a region overlapping address range START...END, or null if - none. END is not including, i.e. the last byte in the range - is at END - 1. */ - -static struct mmap_region * -mmap_find (void *start, void *end) -{ - struct mmap_region *r; - char *s = start, *e = end; - - for (r = mmap_regions; r; r = r->next) - { - char *rstart = (char *) r; - char *rend = rstart + r->nbytes_mapped; - - if (/* First byte of range, i.e. START, in this region? */ - (s >= rstart && s < rend) - /* Last byte of range, i.e. END - 1, in this region? */ - || (e > rstart && e <= rend) - /* First byte of this region in the range? */ - || (rstart >= s && rstart < e) - /* Last byte of this region in the range? */ - || (rend > s && rend <= e)) - break; - } - - return r; -} - - /* Unmap a region. P is a pointer to the start of the user-araa of the region. */ @@ -4888,38 +4817,6 @@ mmap_enlarge (struct mmap_region *r, int npages) } -/* Set or reset variables holding references to mapped regions. - If not RESTORE_P, set all variables to null. If RESTORE_P, set all - variables to the start of the user-areas of mapped regions. - - This function is called from Fdump_emacs to ensure that the dumped - Emacs doesn't contain references to memory that won't be mapped - when Emacs starts. */ - -void -mmap_set_vars (bool restore_p) -{ - struct mmap_region *r; - - if (restore_p) - { - mmap_regions = mmap_regions_1; - mmap_fd = mmap_fd_1; - for (r = mmap_regions; r; r = r->next) - *r->var = MMAP_USER_AREA (r); - } - else - { - for (r = mmap_regions; r; r = r->next) - *r->var = NULL; - mmap_regions_1 = mmap_regions; - mmap_regions = NULL; - mmap_fd_1 = mmap_fd; - mmap_fd = -1; - } -} - - /* Allocate a block of storage large enough to hold NBYTES bytes of data. A pointer to the data is returned in *VAR. VAR is thus the address of some variable which will use the data area. @@ -5224,7 +5121,9 @@ init_buffer_once (void) bset_right_fringe_width (&buffer_defaults, Qnil); bset_fringes_outside_margins (&buffer_defaults, Qnil); bset_scroll_bar_width (&buffer_defaults, Qnil); + bset_scroll_bar_height (&buffer_defaults, Qnil); bset_vertical_scroll_bar_type (&buffer_defaults, Qt); + bset_horizontal_scroll_bar_type (&buffer_defaults, Qt); bset_indicate_empty_lines (&buffer_defaults, Qnil); bset_indicate_buffer_boundaries (&buffer_defaults, Qnil); bset_fringe_indicator_alist (&buffer_defaults, Qnil); @@ -5292,7 +5191,9 @@ init_buffer_once (void) XSETFASTINT (BVAR (&buffer_local_flags, right_fringe_width), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, fringes_outside_margins), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, scroll_bar_width), idx); ++idx; + XSETFASTINT (BVAR (&buffer_local_flags, scroll_bar_height), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, vertical_scroll_bar_type), idx); ++idx; + XSETFASTINT (BVAR (&buffer_local_flags, horizontal_scroll_bar_type), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, indicate_empty_lines), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, indicate_buffer_boundaries), idx); ++idx; XSETFASTINT (BVAR (&buffer_local_flags, fringe_indicator_alist), idx); ++idx; @@ -5337,26 +5238,61 @@ init_buffer_once (void) } void -init_buffer (void) +init_buffer (int initialized) { char *pwd; Lisp_Object temp; ptrdiff_t len; #ifdef USE_MMAP_FOR_BUFFERS - { - /* When using the ralloc implementation based on mmap(2), buffer - text pointers will have been set to null in the dumped Emacs. - Map new memory. */ - struct buffer *b; - - FOR_EACH_BUFFER (b) - if (b->text->beg == NULL) - enlarge_buffer_text (b, 0); - } + if (initialized) + { + struct buffer *b; + +#ifndef WINDOWSNT + /* These must be reset in the dumped Emacs, to avoid stale + references to mmap'ed memory from before the dump. + + WINDOWSNT doesn't need this because it doesn't track mmap'ed + regions by hand (see w32heap.c, which uses system APIs for + that purpose), and thus doesn't use mmap_regions. */ + mmap_regions = NULL; + mmap_fd = -1; +#endif + + /* The dumped buffers reference addresses of buffer text + recorded by temacs, that cannot be used by the dumped Emacs. + We map new memory for their text here. + + Implementation note: the buffers we carry from temacs are: + " prin1", "*scratch*", " *Minibuf-0*", "*Messages*", and + " *code-conversion-work*". They are created by + init_buffer_once and init_window_once (which are not called + in the dumped Emacs), and by the first call to coding.c routines. */ + FOR_EACH_BUFFER (b) + { + b->text->beg = NULL; + enlarge_buffer_text (b, 0); + } + } + else + { + struct buffer *b; + + /* Only buffers with allocated buffer text should be present at + this point in temacs. */ + FOR_EACH_BUFFER (b) + { + eassert (b->text->beg != NULL); + } + } +#else /* not USE_MMAP_FOR_BUFFERS */ + /* Avoid compiler warnings. */ + (void) initialized; #endif /* USE_MMAP_FOR_BUFFERS */ - Fset_buffer (Fget_buffer_create (build_string ("*scratch*"))); + AUTO_STRING (scratch, "*scratch*"); + Fset_buffer (Fget_buffer_create (scratch)); if (NILP (BVAR (&buffer_defaults, enable_multibyte_characters))) Fset_buffer_multibyte (Qnil); @@ -5393,9 +5329,12 @@ init_buffer (void) However, it is not necessary to turn / into /:/. So avoid doing that. */ && strcmp ("/", SSDATA (BVAR (current_buffer, directory)))) - bset_directory - (current_buffer, - concat2 (build_string ("/:"), BVAR (current_buffer, directory))); + { + AUTO_STRING (slash_colon, "/:"); + bset_directory (current_buffer, + concat2 (slash_colon, + BVAR (current_buffer, directory))); + } temp = get_minibuffer (0); bset_directory (XBUFFER (temp), BVAR (current_buffer, directory)); @@ -5458,6 +5397,11 @@ syms_of_buffer (void) staticpro (&Qpermanent_local); staticpro (&Qkill_buffer_hook); + DEFSYM (Qchoice, "choice"); + DEFSYM (Qleft, "left"); + DEFSYM (Qright, "right"); + DEFSYM (Qrange, "range"); + DEFSYM (Qpermanent_local_hook, "permanent-local-hook"); DEFSYM (Qoverlayp, "overlayp"); DEFSYM (Qevaporate, "evaporate"); @@ -5473,6 +5417,18 @@ syms_of_buffer (void) DEFSYM (Qafter_change_functions, "after-change-functions"); DEFSYM (Qkill_buffer_query_functions, "kill-buffer-query-functions"); + DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar"); + Fput (Qvertical_scroll_bar, Qchoice, list4 (Qnil, Qt, Qleft, Qright)); + DEFSYM (Qhorizontal_scroll_bar, "horizontal-scroll-bar"); + + DEFSYM (Qfraction, "fraction"); + Fput (Qfraction, Qrange, Fcons (make_float (0.0), make_float (1.0))); + + DEFSYM (Qoverwrite_mode, "overwrite-mode"); + Fput (Qoverwrite_mode, Qchoice, + list3 (Qnil, intern ("overwrite-mode-textual"), + intern ("overwrite-mode-binary"))); + Fput (Qprotected_field, Qerror_conditions, listn (CONSTYPE_PURE, 2, Qprotected_field, Qerror)); Fput (Qprotected_field, Qerror_message, @@ -5878,7 +5834,8 @@ in a file, save the ^M as a newline. */); Qnil, doc: /* Non-nil means display ... on previous line when a line is invisible. */); - DEFVAR_PER_BUFFER ("overwrite-mode", &BVAR (current_buffer, overwrite_mode), Qnil, + DEFVAR_PER_BUFFER ("overwrite-mode", &BVAR (current_buffer, overwrite_mode), + Qoverwrite_mode, doc: /* Non-nil if self-insertion should replace existing text. The value should be one of `overwrite-mode-textual', `overwrite-mode-binary', or nil. @@ -5968,11 +5925,16 @@ in a window. To make the change take effect, call `set-window-buffer'. */); DEFVAR_PER_BUFFER ("scroll-bar-width", &BVAR (current_buffer, scroll_bar_width), Qintegerp, - doc: /* Width of this buffer's scroll bars in pixels. + doc: /* Width of this buffer's vertical scroll bars in pixels. A value of nil means to use the scroll bar width from the window's frame. */); + DEFVAR_PER_BUFFER ("scroll-bar-height", &BVAR (current_buffer, scroll_bar_height), + Qintegerp, + doc: /* Height of this buffer's horizontal scroll bars in pixels. +A value of nil means to use the scroll bar height from the window's frame. */); + DEFVAR_PER_BUFFER ("vertical-scroll-bar", &BVAR (current_buffer, vertical_scroll_bar_type), - Qnil, + Qvertical_scroll_bar, doc: /* Position of this buffer's vertical scroll bar. The value takes effect whenever you tell a window to display this buffer; for instance, with `set-window-buffer' or when `display-buffer' displays it. @@ -5981,6 +5943,17 @@ A value of `left' or `right' means put the vertical scroll bar at that side of the window; a value of nil means don't show any vertical scroll bars. A value of t (the default) means do whatever the window's frame specifies. */); + DEFVAR_PER_BUFFER ("horizontal-scroll-bar", &BVAR (current_buffer, horizontal_scroll_bar_type), + Qnil, + doc: /* Position of this buffer's horizontal scroll bar. +The value takes effect whenever you tell a window to display this buffer; +for instance, with `set-window-buffer' or when `display-buffer' displays it. + +A value of `bottom' means put the horizontal scroll bar at the bottom of +the window; a value of nil means don't show any horizontal scroll bars. +A value of t (the default) means do whatever the window's frame +specifies. */); + DEFVAR_PER_BUFFER ("indicate-empty-lines", &BVAR (current_buffer, indicate_empty_lines), Qnil, doc: /* Visually indicate empty lines after the buffer end. @@ -6047,7 +6020,7 @@ BITMAP is the corresponding fringe bitmap shown for the logical cursor type. */); DEFVAR_PER_BUFFER ("scroll-up-aggressively", - &BVAR (current_buffer, scroll_up_aggressively), Qfloatp, + &BVAR (current_buffer, scroll_up_aggressively), Qfraction, doc: /* How far to scroll windows upward. If you move point off the bottom, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, @@ -6060,7 +6033,7 @@ window scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); DEFVAR_PER_BUFFER ("scroll-down-aggressively", - &BVAR (current_buffer, scroll_down_aggressively), Qfloatp, + &BVAR (current_buffer, scroll_down_aggressively), Qfraction, doc: /* How far to scroll windows downward. If you move point off the top, the window scrolls automatically. This variable controls how far it scrolls. The value nil, the default, diff --git a/src/buffer.h b/src/buffer.h index de117eb9c61..284cfa7b4a8 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -694,10 +694,12 @@ struct buffer othersize draw them between margin areas and text. */ Lisp_Object INTERNAL_FIELD (fringes_outside_margins); - /* Width and type of scroll bar areas for windows displaying + /* Width, height and types of scroll bar areas for windows displaying this buffer. */ Lisp_Object INTERNAL_FIELD (scroll_bar_width); + Lisp_Object INTERNAL_FIELD (scroll_bar_height); Lisp_Object INTERNAL_FIELD (vertical_scroll_bar_type); + Lisp_Object INTERNAL_FIELD (horizontal_scroll_bar_type); /* Non-nil means indicate lines not displaying text (in a style like vi). */ @@ -1079,13 +1081,21 @@ extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); extern void validate_region (Lisp_Object *, Lisp_Object *); extern void set_buffer_internal_1 (struct buffer *); extern void set_buffer_temp (struct buffer *); -extern Lisp_Object buffer_local_value_1 (Lisp_Object, Lisp_Object); +extern Lisp_Object buffer_local_value (Lisp_Object, Lisp_Object); extern void record_buffer (Lisp_Object); extern void fix_overlays_before (struct buffer *, ptrdiff_t, ptrdiff_t); extern void mmap_set_vars (bool); extern void restore_buffer (Lisp_Object); extern void set_buffer_if_live (Lisp_Object); +/* Return B as a struct buffer pointer, defaulting to the current buffer. */ + +INLINE struct buffer * +decode_buffer (Lisp_Object b) +{ + return NILP (b) ? current_buffer : (CHECK_BUFFER (b), XBUFFER (b)); +} + /* Set the current buffer to B. We previously set windows_or_buffers_changed here to invalidate @@ -1118,15 +1128,15 @@ record_unwind_current_buffer (void) #define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ do { \ ptrdiff_t maxlen = 40; \ - overlays = alloca (maxlen * sizeof *overlays); \ - noverlays = overlays_at (posn, false, &overlays, &maxlen, \ - nextp, NULL, chrq); \ - if (noverlays > maxlen) \ + SAFE_NALLOCA (overlays, 1, maxlen); \ + (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ + nextp, NULL, chrq); \ + if ((noverlays) > maxlen) \ { \ maxlen = noverlays; \ - overlays = alloca (maxlen * sizeof *overlays); \ - noverlays = overlays_at (posn, false, &overlays, &maxlen, \ - nextp, NULL, chrq); \ + SAFE_NALLOCA (overlays, 1, maxlen); \ + (noverlays) = overlays_at (posn, false, &(overlays), &maxlen, \ + nextp, NULL, chrq); \ } \ } while (false) @@ -1135,6 +1145,8 @@ extern Lisp_Object Qbefore_change_functions; extern Lisp_Object Qafter_change_functions; extern Lisp_Object Qfirst_change_hook; extern Lisp_Object Qpriority, Qbefore_string, Qafter_string; +extern Lisp_Object Qchoice, Qrange, Qleft, Qright; +extern Lisp_Object Qvertical_scroll_bar, Qhorizontal_scroll_bar; /* FOR_EACH_LIVE_BUFFER (LIST_VAR, BUF_VAR) followed by a statement is a `for' loop which iterates over the buffers from Vbuffer_alist. */ diff --git a/src/bytecode.c b/src/bytecode.c index f1bdfd9d9c5..d3c8b470cc3 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -36,8 +36,10 @@ by Hallvard: #include <config.h> #include "lisp.h" +#include "blockinput.h" #include "character.h" #include "buffer.h" +#include "keyboard.h" #include "syntax.h" #include "window.h" @@ -292,8 +294,6 @@ enum byte_code_op Bscan_buffer = 0153, /* No longer generated as of v18. */ Bset_mark = 0163, /* this loser is no longer generated as of v18 */ #endif - - B__dummy__ = 0 /* Pacify C89. */ }; /* Whether to maintain a `top' and `bottom' field in the stack frame. */ @@ -390,7 +390,11 @@ unmark_byte_stack (void) /* Fetch the next byte from the bytecode stream. */ +#ifdef BYTE_CODE_SAFE +#define FETCH (eassert (stack.byte_string_start == SDATA (stack.byte_string)), *stack.pc++) +#else #define FETCH *stack.pc++ +#endif /* Fetch two bytes from the bytecode stream and make a 16-bit number out of them. */ @@ -1104,9 +1108,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, goto pushhandler; CASE (Bpushconditioncase): /* New in 24.4. */ { - extern EMACS_INT lisp_eval_depth; - extern int poll_suppress_count; - extern int interrupt_input_blocked; struct handler *c; Lisp_Object tag; int dest; diff --git a/src/callint.c b/src/callint.c index 35411bf9b5c..9a4573c77be 100644 --- a/src/callint.c +++ b/src/callint.c @@ -29,7 +29,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "keymap.h" Lisp_Object Qminus, Qplus; -static Lisp_Object Qcall_interactively; +static Lisp_Object Qfuncall_interactively; static Lisp_Object Qcommand_debug_status; static Lisp_Object Qenable_recursive_minibuffers; @@ -38,8 +38,8 @@ static Lisp_Object Qread_number; Lisp_Object Qmouse_leave_buffer_hook; -static Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion, Qprogn, Qif; -Lisp_Object Qwhen; +static Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion, Qif; +Lisp_Object Qwhen, Qprogn; static Lisp_Object preserved_fns; /* Marker used within call-interactively to refer to point. */ @@ -233,6 +233,43 @@ fix_command (Lisp_Object input, Lisp_Object values) } } +/* Helper function to call `read-file-name' from C. */ + +static Lisp_Object +read_file_name (Lisp_Object default_filename, Lisp_Object mustmatch, + Lisp_Object initial, Lisp_Object predicate) +{ + struct gcpro gcpro1; + Lisp_Object args[7]; + + GCPRO1 (default_filename); + args[0] = intern ("read-file-name"); + args[1] = callint_message; + args[2] = Qnil; + args[3] = default_filename; + args[4] = mustmatch; + args[5] = initial; + args[6] = predicate; + RETURN_UNGCPRO (Ffuncall (7, args)); +} + +/* BEWARE: Calling this directly from C would defeat the purpose! */ +DEFUN ("funcall-interactively", Ffuncall_interactively, Sfuncall_interactively, + 1, MANY, 0, doc: /* Like `funcall' but marks the call as interactive. +I.e. arrange that within the called function `called-interactively-p' will +return non-nil. +usage: (funcall-interactively FUNCTION &rest ARGUMENTS) */) + (ptrdiff_t nargs, Lisp_Object *args) +{ + ptrdiff_t speccount = SPECPDL_INDEX (); + temporarily_switch_to_single_kboard (NULL); + + /* Nothing special to do here, all the work is inside + `called-interactively-p'. Which will look for us as a marker in the + backtrace. */ + return unbind_to (speccount, Ffuncall (nargs, args)); +} + DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0, doc: /* Call FUNCTION, providing args according to its interactive calling specs. Return the value FUNCTION returns. @@ -260,6 +297,7 @@ invoke it. If KEYS is omitted or nil, the return value of Lisp_Object teml; Lisp_Object up_event; Lisp_Object enable; + USE_SAFE_ALLOCA; ptrdiff_t speccount = SPECPDL_INDEX (); /* The index of the next element of this_command_keys to examine for @@ -329,12 +367,8 @@ invoke it. If KEYS is omitted or nil, the return value of wrong_type_argument (Qcommandp, function); } - /* If SPECS is set to a string, use it as an interactive prompt. */ - if (STRINGP (specs)) - /* Make a copy of string so that if a GC relocates specs, - `string' will still be valid. */ - string = xlispstrdupa (specs); - else + /* If SPECS is not a string, invent one. */ + if (! STRINGP (specs)) { Lisp_Object input; Lisp_Object funval = Findirect_function (function, Qt); @@ -374,10 +408,21 @@ invoke it. If KEYS is omitted or nil, the return value of Vreal_this_command = save_real_this_command; kset_last_command (current_kboard, save_last_command); - temporarily_switch_to_single_kboard (NULL); - return unbind_to (speccount, apply1 (function, specs)); + { + Lisp_Object args[3]; + args[0] = Qfuncall_interactively; + args[1] = function; + args[2] = specs; + Lisp_Object result = unbind_to (speccount, Fapply (3, args)); + SAFE_FREE (); + return result; + } } + /* SPECS is set to a string; use it as an interactive prompt. + Copy it so that STRING will be valid even if a GC relocates SPECS. */ + SAFE_ALLOCA_STRING (string, specs); + /* Here if function specifies a string to control parsing the defaults. */ /* Set next_event to point to the first event with parameters. */ @@ -446,10 +491,11 @@ invoke it. If KEYS is omitted or nil, the return value of else break; } - /* Count the number of arguments, which is one plus the number of arguments - the interactive spec would have us give to the function. */ + /* Count the number of arguments, which is two (the function itself and + `funcall-interactively') plus the number of arguments the interactive spec + would have us give to the function. */ tem = string; - for (nargs = 1; *tem; ) + for (nargs = 2; *tem; ) { /* 'r' specifications ("point and mark as 2 numeric args") produce *two* arguments. */ @@ -464,14 +510,15 @@ invoke it. If KEYS is omitted or nil, the return value of break; } - if (min (MOST_POSITIVE_FIXNUM, - min (PTRDIFF_MAX, SIZE_MAX) / word_size) - < nargs) + if (MOST_POSITIVE_FIXNUM < min (PTRDIFF_MAX, SIZE_MAX) / word_size + && MOST_POSITIVE_FIXNUM < nargs) memory_full (SIZE_MAX); - args = alloca (nargs * sizeof *args); - visargs = alloca (nargs * sizeof *visargs); - varies = alloca (nargs * sizeof *varies); + /* Allocate them all at one go. This wastes a bit of memory, but + it's OK to trade space for speed. */ + SAFE_NALLOCA (args, 3, nargs); + visargs = args + nargs; + varies = (signed char *) (visargs + nargs); for (i = 0; i < nargs; i++) { @@ -488,13 +535,13 @@ invoke it. If KEYS is omitted or nil, the return value of specbind (Qenable_recursive_minibuffers, Qt); tem = string; - for (i = 1; *tem; i++) + for (i = 2; *tem; i++) { - visargs[0] = make_string (tem + 1, strcspn (tem + 1, "\n")); - if (strchr (SSDATA (visargs[0]), '%')) - callint_message = Fformat (i, visargs); + visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n")); + if (strchr (SSDATA (visargs[1]), '%')) + callint_message = Fformat (i - 1, visargs + 1); else - callint_message = visargs[0]; + callint_message = visargs[1]; switch (*tem) { @@ -551,25 +598,21 @@ invoke it. If KEYS is omitted or nil, the return value of break; case 'D': /* Directory name. */ - args[i] = Fread_file_name (callint_message, Qnil, - BVAR (current_buffer, directory), Qlambda, Qnil, - Qfile_directory_p); + args[i] = read_file_name (BVAR (current_buffer, directory), Qlambda, Qnil, + Qfile_directory_p); break; case 'f': /* Existing file name. */ - args[i] = Fread_file_name (callint_message, - Qnil, Qnil, Qlambda, Qnil, Qnil); + args[i] = read_file_name (Qnil, Qlambda, Qnil, Qnil); break; case 'F': /* Possibly nonexistent file name. */ - args[i] = Fread_file_name (callint_message, - Qnil, Qnil, Qnil, Qnil, Qnil); + args[i] = read_file_name (Qnil, Qnil, Qnil, Qnil); break; case 'G': /* Possibly nonexistent file name, default to directory alone. */ - args[i] = Fread_file_name (callint_message, - Qnil, Qnil, Qnil, empty_unibyte_string, Qnil); + args[i] = read_file_name (Qnil, Qnil, empty_unibyte_string, Qnil); break; case 'i': /* Ignore an argument -- Does not do I/O. */ @@ -789,21 +832,22 @@ invoke it. If KEYS is omitted or nil, the return value of QUIT; - args[0] = function; + args[0] = Qfuncall_interactively; + args[1] = function; if (arg_from_tty || !NILP (record_flag)) { /* We don't need `visargs' any more, so let's recycle it since we need an array of just the same size. */ - visargs[0] = function; - for (i = 1; i < nargs; i++) + visargs[1] = function; + for (i = 2; i < nargs; i++) { if (varies[i] > 0) visargs[i] = list1 (intern (callint_argfuns[varies[i]])); else visargs[i] = quotify_arg (args[i]); } - Vcommand_history = Fcons (Flist (nargs, visargs), + Vcommand_history = Fcons (Flist (nargs - 1, visargs + 1), Vcommand_history); /* Don't keep command history around forever. */ if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0) @@ -816,7 +860,7 @@ invoke it. If KEYS is omitted or nil, the return value of /* If we used a marker to hold point, mark, or an end of the region, temporarily, convert it to an integer now. */ - for (i = 1; i < nargs; i++) + for (i = 2; i < nargs; i++) if (varies[i] >= 1 && varies[i] <= 4) XSETINT (args[i], marker_position (args[i])); @@ -829,13 +873,11 @@ invoke it. If KEYS is omitted or nil, the return value of kset_last_command (current_kboard, save_last_command); { - Lisp_Object val; - specbind (Qcommand_debug_status, Qnil); - - temporarily_switch_to_single_kboard (NULL); - val = Ffuncall (nargs, args); + Lisp_Object val = Ffuncall (nargs, args); UNGCPRO; - return unbind_to (speccount, val); + val = unbind_to (speccount, val); + SAFE_FREE (); + return val; } } @@ -888,7 +930,7 @@ syms_of_callint (void) DEFSYM (Qplus, "+"); DEFSYM (Qhandle_shift_selection, "handle-shift-selection"); DEFSYM (Qread_number, "read-number"); - DEFSYM (Qcall_interactively, "call-interactively"); + DEFSYM (Qfuncall_interactively, "funcall-interactively"); DEFSYM (Qcommand_debug_status, "command-debug-status"); DEFSYM (Qenable_recursive_minibuffers, "enable-recursive-minibuffers"); DEFSYM (Qmouse_leave_buffer_hook, "mouse-leave-buffer-hook"); @@ -946,5 +988,6 @@ a way to turn themselves off when a mouse command switches windows. */); defsubr (&Sinteractive); defsubr (&Scall_interactively); + defsubr (&Sfuncall_interactively); defsubr (&Sprefix_numeric_value); } diff --git a/src/callproc.c b/src/callproc.c index 7ba3e398b41..e3dcc7bbcca 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -105,29 +105,6 @@ enum static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t); - -#ifndef MSDOS -/* Block SIGCHLD. */ - -void -block_child_signal (void) -{ - sigset_t blocked; - sigemptyset (&blocked); - sigaddset (&blocked, SIGCHLD); - pthread_sigmask (SIG_BLOCK, &blocked, 0); -} - -/* Unblock SIGCHLD. */ - -void -unblock_child_signal (void) -{ - pthread_sigmask (SIG_SETMASK, &empty_mask, 0); -} - -#endif /* !MSDOS */ - /* Return the current buffer's working directory, or the home directory if it's unreachable, as a string suitable for a system call. Signal an error if the result would not be an accessible directory. */ @@ -152,7 +129,7 @@ encode_current_directory (void) if (STRING_MULTIBYTE (dir)) dir = ENCODE_FILE (dir); - if (! file_accessible_directory_p (SSDATA (dir))) + if (! file_accessible_directory_p (dir)) report_file_error ("Setting current directory", BVAR (current_buffer, directory)); @@ -167,7 +144,8 @@ void record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) { #ifndef MSDOS - block_child_signal (); + sigset_t oldset; + block_child_signal (&oldset); if (p->alive) { @@ -176,7 +154,7 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) kill (- p->pid, SIGKILL); } - unblock_child_signal (); + unblock_child_signal (&oldset); #endif /* !MSDOS */ } @@ -321,6 +299,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, char *tempfile = NULL; int pid; #else + sigset_t oldset; pid_t pid; #endif int child_errno; @@ -487,7 +466,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, && SREF (path, 1) == ':') path = Fsubstring (path, make_number (2), Qnil); - new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); + SAFE_NALLOCA (new_argv, 1, nargs < 4 ? 2 : nargs - 2); { struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; @@ -637,7 +616,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, #ifndef MSDOS block_input (); - block_child_signal (); + block_child_signal (&oldset); #ifdef WINDOWSNT pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); @@ -653,6 +632,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, int volatile fd_error_volatile = fd_error; int volatile filefd_volatile = filefd; ptrdiff_t volatile count_volatile = count; + ptrdiff_t volatile sa_avail_volatile = sa_avail; ptrdiff_t volatile sa_count_volatile = sa_count; char **volatile new_argv_volatile = new_argv; int volatile callproc_fd_volatile[CALLPROC_FDS]; @@ -669,6 +649,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, fd_error = fd_error_volatile; filefd = filefd_volatile; count = count_volatile; + sa_avail = sa_avail_volatile; sa_count = sa_count_volatile; new_argv = new_argv_volatile; @@ -679,7 +660,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, if (pid == 0) { - unblock_child_signal (); + unblock_child_signal (&oldset); setsid (); @@ -715,7 +696,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, } } - unblock_child_signal (); + unblock_child_signal (&oldset); unblock_input (); if (pid < 0) @@ -1003,7 +984,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args, count = SPECPDL_INDEX (); record_unwind_protect_nothing (); - fd = mkostemp (tempfile, O_CLOEXEC); + fd = mkostemp (tempfile, O_BINARY | O_CLOEXEC); if (fd < 0) report_file_error ("Failed to open temporary file using pattern", pattern); @@ -1172,6 +1153,39 @@ add_env (char **env, char **new_env, char *string) return new_env; } +#ifndef DOS_NT + +/* 'exec' failed inside a child running NAME, with error number ERR. + Possibly a vforked child needed to allocate a large vector on the + stack; such a child cannot fall back on malloc because that might + mess up the allocator's data structures in the parent. + Report the error and exit the child. */ + +static _Noreturn void +exec_failed (char const *name, int err) +{ + /* Avoid deadlock if the child's perror writes to a full pipe; the + pipe's reader is the parent, but with vfork the parent can't + run until the child exits. Truncate the diagnostic instead. */ + fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK); + + errno = err; + emacs_perror (name); + _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); +} + +#else + +/* Do nothing. There is no need to fail, as DOS_NT platforms do not + fork and exec, and handle alloca exhaustion in a different way. */ + +static void +exec_failed (char const *name, int err) +{ +} + +#endif + /* This is the last thing run in a newly forked inferior either synchronous or asynchronous. Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. @@ -1195,8 +1209,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, int cpid; HANDLE handles[3]; #else - int exec_errno; - pid_t pid = getpid (); #endif /* WINDOWSNT */ @@ -1217,11 +1229,13 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, on that. */ pwd_var = xmalloc (i + 5); #else + if (MAX_ALLOCA - 5 < i) + exec_failed (new_argv[0], ENOMEM); pwd_var = alloca (i + 5); #endif temp = pwd_var + 4; memcpy (pwd_var, "PWD=", 4); - strcpy (temp, SSDATA (current_dir)); + lispstpcpy (temp, current_dir); #ifndef DOS_NT /* We can't signal an Elisp error here; we're in a vfork. Since @@ -1283,6 +1297,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, } /* new_length + 2 to include PWD and terminating 0. */ + if (MAX_ALLOCA / sizeof *env - 2 < new_length) + exec_failed (new_argv[0], ENOMEM); env = new_env = alloca ((new_length + 2) * sizeof *env); /* If we have a PWD envvar, pass one down, but with corrected value. */ @@ -1291,7 +1307,11 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, if (STRINGP (display)) { - char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); + char *vdata; + + if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display)) + exec_failed (new_argv[0], ENOMEM); + vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); strcpy (vdata, "DISPLAY="); strcat (vdata, SSDATA (display)); new_env = add_env (env, new_env, vdata); @@ -1366,16 +1386,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, tcsetpgrp (0, pid); execve (new_argv[0], new_argv, env); - exec_errno = errno; - - /* Avoid deadlock if the child's perror writes to a full pipe; the - pipe's reader is the parent, but with vfork the parent can't - run until the child exits. Truncate the diagnostic instead. */ - fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK); - - errno = exec_errno; - emacs_perror (new_argv[0]); - _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); + exec_failed (new_argv[0], errno); #else /* MSDOS */ pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); @@ -1509,14 +1520,14 @@ If optional parameter ENV is a list, then search this list instead of } /* A version of getenv that consults the Lisp environment lists, - easily callable from C. */ + easily callable from C. This is usually called from egetenv. */ char * -egetenv (const char *var) +egetenv_internal (const char *var, ptrdiff_t len) { char *value; ptrdiff_t valuelen; - if (getenv_internal (var, strlen (var), &value, &valuelen, Qnil)) + if (getenv_internal (var, len, &value, &valuelen, Qnil)) return value; else return 0; @@ -1564,20 +1575,13 @@ init_callproc_1 (void) void init_callproc (void) { - char *data_dir = egetenv ("EMACSDATA"); + bool data_dir = egetenv ("EMACSDATA") != 0; - register char * sh; + char *sh; Lisp_Object tempdir; #ifdef HAVE_NS if (data_dir == 0) - { - const char *etc_dir = ns_etc_directory (); - if (etc_dir) - { - data_dir = alloca (strlen (etc_dir) + 1); - strcpy (data_dir, etc_dir); - } - } + data_dir = ns_etc_directory () != 0; #endif if (!NILP (Vinstallation_directory)) @@ -1628,13 +1632,13 @@ init_callproc (void) srcdir = Fexpand_file_name (build_string ("../src/"), lispdir); - tem = Fexpand_file_name (build_string ("GNU"), Vdata_directory); + tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory); tem1 = Ffile_exists_p (tem); if (!NILP (Fequal (srcdir, Vinvocation_directory)) || NILP (tem1)) { Lisp_Object newdir; newdir = Fexpand_file_name (build_string ("../etc/"), lispdir); - tem = Fexpand_file_name (build_string ("GNU"), newdir); + tem = Fexpand_file_name (build_string ("NEWS"), newdir); tem1 = Ffile_exists_p (tem); if (!NILP (tem1)) Vdata_directory = newdir; @@ -1646,12 +1650,12 @@ init_callproc (void) #endif { tempdir = Fdirectory_file_name (Vexec_directory); - if (! file_accessible_directory_p (SSDATA (tempdir))) + if (! file_accessible_directory_p (tempdir)) dir_warning ("arch-dependent data dir", Vexec_directory); } tempdir = Fdirectory_file_name (Vdata_directory); - if (! file_accessible_directory_p (SSDATA (tempdir))) + if (! file_accessible_directory_p (tempdir)) dir_warning ("arch-independent data dir", Vdata_directory); sh = getenv ("SHELL"); diff --git a/src/category.c b/src/category.c index 851ae1a4c24..a4610e4d358 100644 --- a/src/category.c +++ b/src/category.c @@ -96,7 +96,7 @@ those categories. */) (Lisp_Object categories) { Lisp_Object val; - int len; + ptrdiff_t len; CHECK_STRING (categories); val = MAKE_CATEGORY_SET; diff --git a/src/ccl.c b/src/ccl.c index 187f6027018..54093bf5677 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -2160,11 +2160,8 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY ASET (status, i, make_number (ccl.reg[i])); ASET (status, 8, make_number (ccl.ic)); - if (NILP (unibyte_p)) - val = make_multibyte_string ((char *) outbuf, produced_chars, - outp - outbuf); - else - val = make_unibyte_string ((char *) outbuf, produced_chars); + val = make_specified_string ((const char *) outbuf, produced_chars, + outp - outbuf, NILP (unibyte_p)); xfree (outbuf); return val; diff --git a/src/character.c b/src/character.c index 12a95203527..a8e48dfd774 100644 --- a/src/character.c +++ b/src/character.c @@ -233,32 +233,6 @@ translate_char (Lisp_Object table, int c) return c; } -/* Convert ASCII or 8-bit character C to unibyte. If C is none of - them, return (C & 0xFF). */ - -int -multibyte_char_to_unibyte (int c) -{ - if (c < 0x80) - return c; - if (CHAR_BYTE8_P (c)) - return CHAR_TO_BYTE8 (c); - return (c & 0xFF); -} - -/* Like multibyte_char_to_unibyte, but return -1 if C is not supported - by charset_unibyte. */ - -int -multibyte_char_to_unibyte_safe (int c) -{ - if (c < 0x80) - return c; - if (CHAR_BYTE8_P (c)) - return CHAR_TO_BYTE8 (c); - return -1; -} - DEFUN ("characterp", Fcharacterp, Scharacterp, 1, 2, 0, doc: /* Return non-nil if OBJECT is a character. In Emacs Lisp, characters are represented by character codes, which diff --git a/src/character.h b/src/character.h index 6f243a1392d..624f4fff3f0 100644 --- a/src/character.h +++ b/src/character.h @@ -67,20 +67,15 @@ INLINE_HEADER_BEGIN #define BYTE8_TO_CHAR(byte) ((byte) + 0x3FFF00) #define UNIBYTE_TO_CHAR(byte) \ - (ASCII_BYTE_P (byte) ? (byte) : BYTE8_TO_CHAR (byte)) + (ASCII_CHAR_P (byte) ? (byte) : BYTE8_TO_CHAR (byte)) /* Return the raw 8-bit byte for character C. */ -#define CHAR_TO_BYTE8(c) \ - (CHAR_BYTE8_P (c) \ - ? (c) - 0x3FFF00 \ - : multibyte_char_to_unibyte (c)) +#define CHAR_TO_BYTE8(c) (CHAR_BYTE8_P (c) ? (c) - 0x3FFF00 : (c & 0xFF)) /* Return the raw 8-bit byte for character C, or -1 if C doesn't correspond to a byte. */ -#define CHAR_TO_BYTE_SAFE(c) \ - (CHAR_BYTE8_P (c) \ - ? (c) - 0x3FFF00 \ - : multibyte_char_to_unibyte_safe (c)) +#define CHAR_TO_BYTE_SAFE(c) \ + (ASCII_CHAR_P (c) ? c : (CHAR_BYTE8_P (c) ? (c) - 0x3FFF00 : -1)) /* Nonzero iff BYTE is the 1st byte of a multibyte form of a character that corresponds to a raw 8-bit byte. */ @@ -101,13 +96,6 @@ INLINE_HEADER_BEGIN /* This is the maximum byte length of multibyte form. */ #define MAX_MULTIBYTE_LENGTH 5 -/* Return a Lisp character whose character code is C. Assumes C is - a valid character code. */ -#define make_char(c) make_number (c) - -/* Nonzero iff C is an ASCII byte. */ -#define ASCII_BYTE_P(c) UNSIGNED_CMP (c, <, 0x80) - /* Nonzero iff X is a character. */ #define CHARACTERP(x) (NATNUMP (x) && XFASTINT (x) <= MAX_CHAR) @@ -222,7 +210,7 @@ INLINE_HEADER_BEGIN /* Nonzero iff BYTE starts a character in a multibyte form. This is equivalent to: - (ASCII_BYTE_P (byte) || LEADING_CODE_P (byte)) */ + (ASCII_CHAR_P (byte) || LEADING_CODE_P (byte)) */ #define CHAR_HEAD_P(byte) (((byte) & 0xC0) != 0x80) /* How many bytes a character that starts with BYTE occupies in a @@ -656,8 +644,6 @@ extern int string_char (const unsigned char *, const unsigned char **, int *); extern int translate_char (Lisp_Object, int c); -extern void parse_str_as_multibyte (const unsigned char *, - ptrdiff_t, ptrdiff_t *, ptrdiff_t *); extern ptrdiff_t count_size_as_multibyte (const unsigned char *, ptrdiff_t); extern ptrdiff_t str_as_multibyte (unsigned char *, ptrdiff_t, ptrdiff_t, ptrdiff_t *); @@ -679,6 +665,20 @@ extern Lisp_Object string_escape_byte8 (Lisp_Object); #define GET_TRANSLATION_TABLE(id) \ (XCDR (XVECTOR (Vtranslation_table_vector)->contents[(id)])) +/* Look up the element in char table OBJ at index CH, and return it as + an integer. If the element is not a character, return CH itself. */ + +INLINE int +char_table_translate (Lisp_Object obj, int ch) +{ + /* This internal function is expected to be called with valid arguments, + so there is a eassert instead of CHECK_xxx for the sake of speed. */ + eassert (CHAR_VALID_P (ch)); + eassert (CHAR_TABLE_P (obj)); + obj = CHAR_TABLE_REF (obj, ch); + return CHARACTERP (obj) ? XINT (obj) : ch; +} + INLINE_HEADER_END #endif /* EMACS_CHARACTER_H */ diff --git a/src/charset.c b/src/charset.c index 3566b156736..171a00f23d1 100644 --- a/src/charset.c +++ b/src/charset.c @@ -389,12 +389,12 @@ load_charset_map (struct charset *charset, struct charset_map_entries *entries, { if (ascii_compatible_p) { - if (! ASCII_BYTE_P (from_c)) + if (! ASCII_CHAR_P (from_c)) { if (from_c < nonascii_min_char) nonascii_min_char = from_c; } - else if (! ASCII_BYTE_P (to_c)) + else if (! ASCII_CHAR_P (to_c)) { nonascii_min_char = 0x80; } @@ -485,14 +485,12 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, unsigned max_code = CHARSET_MAX_CODE (charset); int fd; FILE *fp; - Lisp_Object suffixes; struct charset_map_entries *head, *entries; int n_entries; - ptrdiff_t count; - - suffixes = list2 (build_string (".map"), build_string (".TXT")); - - count = SPECPDL_INDEX (); + AUTO_STRING (map, ".map"); + AUTO_STRING (txt, ".txt"); + AUTO_LIST2 (suffixes, map, txt); + ptrdiff_t count = SPECPDL_INDEX (); record_unwind_protect_nothing (); specbind (Qfile_name_handler_alist, Qnil); fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, false); @@ -667,12 +665,8 @@ map_charset_for_dump (void (*c_function) (Lisp_Object, Lisp_Object), { int from_idx = CODE_POINT_TO_INDEX (temp_charset_work->current, from); int to_idx = CODE_POINT_TO_INDEX (temp_charset_work->current, to); - Lisp_Object range; + Lisp_Object range = Fcons (Qnil, Qnil); int c, stop; - struct gcpro gcpro1; - - range = Fcons (Qnil, Qnil); - GCPRO1 (range); c = temp_charset_work->min_char; stop = (temp_charset_work->max_char < 0x20000 @@ -715,7 +709,6 @@ map_charset_for_dump (void (*c_function) (Lisp_Object, Lisp_Object), } c++; } - UNGCPRO; } void @@ -1400,6 +1393,32 @@ Optional third argument DEUNIFY, if non-nil, means to de-unify CHARSET. */) return Qnil; } +/* Check that DIMENSION, CHARS, and FINAL_CHAR specify a valid ISO charset. + Return true if it's a 96-character set, false if 94. */ + +static bool +check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, + Lisp_Object final_char) +{ + CHECK_NUMBER (dimension); + CHECK_NUMBER (chars); + CHECK_CHARACTER (final_char); + + if (! (1 <= XINT (dimension) && XINT (dimension) <= 3)) + error ("Invalid DIMENSION %"pI"d, it should be 1, 2, or 3", + XINT (dimension)); + + bool chars_flag = XINT (chars) == 96; + if (! (chars_flag || XINT (chars) == 94)) + error ("Invalid CHARS %"pI"d, it should be 94 or 96", XINT (chars)); + + int final_ch = XFASTINT (final_char); + if (! ('0' <= final_ch && final_ch <= '~')) + error ("Invalid FINAL-CHAR '%c', it should be '0'..'~'", final_ch); + + return chars_flag; +} + DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char, Sget_unused_iso_final_char, 2, 2, 0, doc: /* @@ -1412,35 +1431,12 @@ If there's no unused final char for the specified kind of charset, return nil. */) (Lisp_Object dimension, Lisp_Object chars) { - int final_char; - - CHECK_NUMBER (dimension); - CHECK_NUMBER (chars); - if (XINT (dimension) != 1 && XINT (dimension) != 2 && XINT (dimension) != 3) - args_out_of_range_3 (dimension, make_number (1), make_number (3)); - if (XINT (chars) != 94 && XINT (chars) != 96) - args_out_of_range_3 (chars, make_number (94), make_number (96)); - for (final_char = '0'; final_char <= '?'; final_char++) - if (ISO_CHARSET_TABLE (XINT (dimension), XINT (chars), final_char) < 0) - break; - return (final_char <= '?' ? make_number (final_char) : Qnil); -} - -static void -check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, Lisp_Object final_char) -{ - CHECK_NATNUM (dimension); - CHECK_NATNUM (chars); - CHECK_CHARACTER (final_char); - - if (XINT (dimension) > 3) - error ("Invalid DIMENSION %"pI"d, it should be 1, 2, or 3", - XINT (dimension)); - if (XINT (chars) != 94 && XINT (chars) != 96) - error ("Invalid CHARS %"pI"d, it should be 94 or 96", XINT (chars)); - if (XINT (final_char) < '0' || XINT (final_char) > '~') - error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", - (int)XINT (final_char)); + bool chars_flag = check_iso_charset_parameter (dimension, chars, + make_number ('0')); + for (int final_char = '0'; final_char <= '?'; final_char++) + if (ISO_CHARSET_TABLE (XINT (dimension), chars_flag, final_char) < 0) + return make_number (final_char); + return Qnil; } @@ -1454,12 +1450,10 @@ if CHARSET is designated instead. */) (Lisp_Object dimension, Lisp_Object chars, Lisp_Object final_char, Lisp_Object charset) { int id; - bool chars_flag; CHECK_CHARSET_GET_ID (charset, id); - check_iso_charset_parameter (dimension, chars, final_char); - chars_flag = XINT (chars) == 96; - ISO_CHARSET_TABLE (XINT (dimension), chars_flag, XINT (final_char)) = id; + bool chars_flag = check_iso_charset_parameter (dimension, chars, final_char); + ISO_CHARSET_TABLE (XINT (dimension), chars_flag, XFASTINT (final_char)) = id; return Qnil; } @@ -1522,7 +1516,7 @@ find_charsets_in_text (const unsigned char *ptr, ptrdiff_t nchars, if (!NILP (table)) c = translate_char (table, c); - if (ASCII_BYTE_P (c)) + if (ASCII_CHAR_P (c)) ASET (charsets, charset_ascii, Qt); else ASET (charsets, charset_eight_bit, Qt); @@ -2113,13 +2107,9 @@ See the documentation of the function `charset-info' for the meanings of DIMENSION, CHARS, and FINAL-CHAR. */) (Lisp_Object dimension, Lisp_Object chars, Lisp_Object final_char) { - int id; - bool chars_flag; - - check_iso_charset_parameter (dimension, chars, final_char); - chars_flag = XFASTINT (chars) == 96; - id = ISO_CHARSET_TABLE (XFASTINT (dimension), chars_flag, - XFASTINT (final_char)); + bool chars_flag = check_iso_charset_parameter (dimension, chars, final_char); + int id = ISO_CHARSET_TABLE (XINT (dimension), chars_flag, + XFASTINT (final_char)); return (id >= 0 ? CHARSET_NAME (CHARSET_FROM_ID (id)) : Qnil); } @@ -2298,7 +2288,7 @@ init_charset (void) { Lisp_Object tempdir; tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory); - if (! file_accessible_directory_p (SSDATA (tempdir))) + if (! file_accessible_directory_p (tempdir)) { /* This used to be non-fatal (dir_warning), but it should not happen, and if it does sooner or later it will cause some @@ -2386,7 +2376,7 @@ syms_of_charset (void) } charset_table = charset_table_init; - charset_table_size = sizeof charset_table_init / sizeof *charset_table_init; + charset_table_size = ARRAYELTS (charset_table_init); charset_table_used = 0; defsubr (&Scharsetp); diff --git a/src/charset.h b/src/charset.h index 32c624beff8..4176ce5ecc6 100644 --- a/src/charset.h +++ b/src/charset.h @@ -403,7 +403,7 @@ extern Lisp_Object Vchar_charset_set; Try some optimization before calling decode_char. */ #define DECODE_CHAR(charset, code) \ - ((ASCII_BYTE_P (code) && (charset)->ascii_compatible_p) \ + ((ASCII_CHAR_P (code) && (charset)->ascii_compatible_p) \ ? (code) \ : ((code) < (charset)->min_code || (code) > (charset)->max_code) \ ? -1 \ diff --git a/src/chartab.c b/src/chartab.c index 2a8bbc6983a..bfbbf798f0c 100644 --- a/src/chartab.c +++ b/src/chartab.c @@ -140,15 +140,11 @@ the char-table has no extra slot. */) static Lisp_Object make_sub_char_table (int depth, int min_char, Lisp_Object defalt) { - Lisp_Object table; - int size = (PSEUDOVECSIZE (struct Lisp_Sub_Char_Table, contents) - + chartab_size[depth]); - - table = Fmake_vector (make_number (size), defalt); - XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE); - XSUB_CHAR_TABLE (table)->depth = make_number (depth); - XSUB_CHAR_TABLE (table)->min_char = make_number (min_char); + int i; + Lisp_Object table = make_uninit_sub_char_table (depth, min_char); + for (i = 0; i < chartab_size[depth]; i++) + XSUB_CHAR_TABLE (table)->contents[i] = defalt; return table; } @@ -172,8 +168,8 @@ char_table_ascii (Lisp_Object table) static Lisp_Object copy_sub_char_table (Lisp_Object table) { - int depth = XINT (XSUB_CHAR_TABLE (table)->depth); - int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char); + int depth = XSUB_CHAR_TABLE (table)->depth; + int min_char = XSUB_CHAR_TABLE (table)->min_char; Lisp_Object copy = make_sub_char_table (depth, min_char, Qnil); int i; @@ -220,10 +216,8 @@ static Lisp_Object sub_char_table_ref (Lisp_Object table, int c, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); - int min_char = XINT (tbl->min_char); Lisp_Object val; - int idx = CHARTAB_IDX (c, depth, min_char); + int idx = CHARTAB_IDX (c, tbl->depth, tbl->min_char); val = tbl->contents[idx]; if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) @@ -265,8 +259,7 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp_Object defalt, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); - int min_char = XINT (tbl->min_char); + int depth = tbl->depth, min_char = tbl->min_char; int chartab_idx = CHARTAB_IDX (c, depth, min_char), idx; Lisp_Object val; @@ -402,8 +395,7 @@ static void sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT ((tbl)->depth); - int min_char = XINT ((tbl)->min_char); + int depth = tbl->depth, min_char = tbl->min_char; int i = CHARTAB_IDX (c, depth, min_char); Lisp_Object sub; @@ -458,8 +450,7 @@ sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT ((tbl)->depth); - int min_char = XINT ((tbl)->min_char); + int depth = tbl->depth, min_char = tbl->min_char; int chars_in_block = chartab_chars[depth]; int i, c, lim = chartab_size[depth]; @@ -672,26 +663,12 @@ or a character code. Return VALUE. */) return value; } -/* Look up the element in TABLE at index CH, and return it as an - integer. If the element is not a character, return CH itself. */ - -int -char_table_translate (Lisp_Object table, int ch) -{ - Lisp_Object value; - value = Faref (table, make_number (ch)); - if (! CHARACTERP (value)) - return ch; - return XINT (value); -} - static Lisp_Object optimize_sub_char_table (Lisp_Object table, Lisp_Object test) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); + int i, depth = tbl->depth; Lisp_Object elt, this; - int i; bool optimizable; elt = XSUB_CHAR_TABLE (table)->contents[0]; @@ -778,8 +755,8 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - depth = XINT (tbl->depth); - min_char = XINT (tbl->min_char); + depth = tbl->depth; + min_char = tbl->min_char; max_char = min_char + chartab_chars[depth - 1] - 1; } else @@ -973,12 +950,10 @@ map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object), unsigned from, unsigned to) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); - int c, i; + int i, c = tbl->min_char, depth = tbl->depth; if (depth < 3) - for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; - i++, c += chartab_chars[depth]) + for (i = 0; i < chartab_size[depth]; i++, c += chartab_chars[depth]) { Lisp_Object this; @@ -1000,7 +975,7 @@ map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object), } } else - for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++) + for (i = 0; i < chartab_size[depth]; i++, c++) { Lisp_Object this; unsigned code; @@ -1147,8 +1122,7 @@ static Lisp_Object uniprop_table_uncompress (Lisp_Object table, int idx) { Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[idx]; - int min_char = (XINT (XSUB_CHAR_TABLE (table)->min_char) - + chartab_chars[2] * idx); + int min_char = XSUB_CHAR_TABLE (table)->min_char + chartab_chars[2] * idx; Lisp_Object sub = make_sub_char_table (3, min_char, Qnil); const unsigned char *p, *pend; @@ -1221,9 +1195,7 @@ uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value) static uniprop_decoder_t uniprop_decoder [] = { uniprop_decode_value_run_length }; -static int uniprop_decoder_count - = (sizeof uniprop_decoder) / sizeof (uniprop_decoder[0]); - +static const int uniprop_decoder_count = ARRAYELTS (uniprop_decoder); /* Return the decoder of char-table TABLE or nil if none. */ @@ -1286,13 +1258,8 @@ uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value) break; value = make_number (i); if (i == size) - { - Lisp_Object args[2]; - - args[0] = XCHAR_TABLE (table)->extras[4]; - args[1] = Fmake_vector (make_number (1), value); - set_char_table_extras (table, 4, Fvconcat (2, args)); - } + set_char_table_extras (table, 4, Fvconcat (2, ((Lisp_Object []) { + XCHAR_TABLE (table)->extras[4], Fmake_vector (make_number (1), value) }))); return make_number (i); } @@ -1301,9 +1268,7 @@ static uniprop_encoder_t uniprop_encoder[] = uniprop_encode_value_run_length, uniprop_encode_value_numeric }; -static int uniprop_encoder_count - = (sizeof uniprop_encoder) / sizeof (uniprop_encoder[0]); - +static const int uniprop_encoder_count = ARRAYELTS (uniprop_encoder); /* Return the encoder of char-table TABLE or nil if none. */ @@ -1337,8 +1302,8 @@ uniprop_table (Lisp_Object prop) { struct gcpro gcpro1; GCPRO1 (val); - result = Fload (concat2 (build_string ("international/"), table), - Qt, Qt, Qt, Qt); + AUTO_STRING (intl, "international/"); + result = Fload (concat2 (intl, table), Qt, Qt, Qt, Qt); UNGCPRO; if (NILP (result)) return Qnil; diff --git a/src/cmds.c b/src/cmds.c index 1a510afa271..9a05218b77b 100644 --- a/src/cmds.c +++ b/src/cmds.c @@ -131,12 +131,7 @@ successfully moved (for the return value). */) count = XINT (n); } - if (count <= 0) - pos = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, count - 1, - &shortage, &pos_byte, 1); - else - pos = find_newline (PT, PT_BYTE, ZV, ZV_BYTE, count, - &shortage, &pos_byte, 1); + shortage = scan_newline_from_point (count, &pos, &pos_byte); SET_PT_BOTH (pos, pos_byte); @@ -315,7 +310,7 @@ At the end, it runs `post-self-insert-hook'. */) int val = internal_self_insert (character, XFASTINT (n)); if (val == 2) nonundocount = 0; - frame_make_pointer_invisible (); + frame_make_pointer_invisible (SELECTED_FRAME ()); } return Qnil; @@ -359,9 +354,7 @@ internal_self_insert (int c, EMACS_INT n) } else { - str[0] = (SINGLE_BYTE_CHAR_P (c) - ? c - : multibyte_char_to_unibyte (c)); + str[0] = SINGLE_BYTE_CHAR_P (c) ? c : CHAR_TO_BYTE8 (c); len = 1; } if (!NILP (overwrite) diff --git a/src/coding.c b/src/coding.c index b0a9f6ef4cb..e4b52f6db48 100644 --- a/src/coding.c +++ b/src/coding.c @@ -642,15 +642,6 @@ static enum coding_category coding_priorities[coding_category_max]; Nth coding category. */ static struct coding_system coding_categories[coding_category_max]; -/*** Commonly used macros and functions ***/ - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - /* Encode a flag that can be nil, something else, or t as -1, 0, 1. */ static int @@ -690,6 +681,14 @@ CHECK_NATNUM_CDR (Lisp_Object x) XSETCDR (x, tmp); } +/* True if CODING's destination can be grown. */ + +static bool +growable_destination (struct coding_system *coding) +{ + return STRINGP (coding->dst_object) || BUFFERP (coding->dst_object); +} + /* Safely get one byte from the source text pointed by SRC which ends at SRC_END, and set C to that byte. If there are not enough bytes @@ -1485,8 +1484,7 @@ decode_coding_utf_8 (struct coding_system *coding) src = src_base; consumed_chars = consumed_chars_base; ONE_MORE_BYTE (c); - *charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); - coding->errors++; + *charbuf++ = ASCII_CHAR_P (c) ? c : BYTE8_TO_CHAR (c); } no_more_source: @@ -1685,7 +1683,6 @@ decode_coding_utf_16 (struct coding_system *coding) /* The first two bytes are not BOM. Treat them as bytes for a normal character. */ src = src_base; - coding->errors++; } CODING_UTF_16_BOM (coding) = utf_without_bom; } @@ -1725,7 +1722,7 @@ decode_coding_utf_16 (struct coding_system *coding) ONE_MORE_BYTE (c2); if (c2 < 0) { - *charbuf++ = ASCII_BYTE_P (c1) ? c1 : BYTE8_TO_CHAR (c1); + *charbuf++ = ASCII_CHAR_P (c1) ? c1 : BYTE8_TO_CHAR (c1); *charbuf++ = -c2; continue; } @@ -1742,7 +1739,6 @@ decode_coding_utf_16 (struct coding_system *coding) c1 = surrogate & 0xFF, c2 = surrogate >> 8; *charbuf++ = c1; *charbuf++ = c2; - coding->errors++; if (UTF_16_HIGH_SURROGATE_P (c)) CODING_UTF_16_SURROGATE (coding) = surrogate = c; else @@ -2108,7 +2104,7 @@ emacs_mule_char (struct coding_system *coding, const unsigned char *src, case 1: code = c; - charset_ID = ASCII_BYTE_P (code) ? charset_ascii : charset_eight_bit; + charset_ID = ASCII_CHAR_P (code) ? charset_ascii : charset_eight_bit; break; default: @@ -2596,9 +2592,8 @@ decode_coding_emacs_mule (struct coding_system *coding) src = src_base; consumed_chars = consumed_chars_base; ONE_MORE_BYTE (c); - *charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); + *charbuf++ = ASCII_CHAR_P (c) ? c : BYTE8_TO_CHAR (c); char_offset++; - coding->errors++; } no_more_source: @@ -3591,7 +3586,7 @@ decode_coding_iso_2022 (struct coding_system *coding) if (CODING_ISO_EXTSEGMENT_LEN (coding) > 0) { - *charbuf++ = ASCII_BYTE_P (c1) ? c1 : BYTE8_TO_CHAR (c1); + *charbuf++ = ASCII_CHAR_P (c1) ? c1 : BYTE8_TO_CHAR (c1); char_offset++; CODING_ISO_EXTSEGMENT_LEN (coding)--; continue; @@ -3618,7 +3613,7 @@ decode_coding_iso_2022 (struct coding_system *coding) } else { - *charbuf++ = ASCII_BYTE_P (c1) ? c1 : BYTE8_TO_CHAR (c1); + *charbuf++ = ASCII_CHAR_P (c1) ? c1 : BYTE8_TO_CHAR (c1); char_offset++; } continue; @@ -3992,7 +3987,7 @@ decode_coding_iso_2022 (struct coding_system *coding) MAYBE_FINISH_COMPOSITION (); for (; src_base < src; src_base++, char_offset++) { - if (ASCII_BYTE_P (*src_base)) + if (ASCII_CHAR_P (*src_base)) *charbuf++ = *src_base; else *charbuf++ = BYTE8_TO_CHAR (*src_base); @@ -4022,9 +4017,8 @@ decode_coding_iso_2022 (struct coding_system *coding) src = src_base; consumed_chars = consumed_chars_base; ONE_MORE_BYTE (c); - *charbuf++ = c < 0 ? -c : ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); + *charbuf++ = c < 0 ? -c : ASCII_CHAR_P (c) ? c : BYTE8_TO_CHAR (c); char_offset++; - coding->errors++; /* Reset the invocation and designation status to the safest one; i.e. designate ASCII to the graphic register 0, and invoke that register to the graphic plane 0. This typically @@ -4855,7 +4849,6 @@ decode_coding_sjis (struct coding_system *coding) ONE_MORE_BYTE (c); *charbuf++ = c < 0 ? -c : BYTE8_TO_CHAR (c); char_offset++; - coding->errors++; } no_more_source: @@ -4951,7 +4944,6 @@ decode_coding_big5 (struct coding_system *coding) ONE_MORE_BYTE (c); *charbuf++ = c < 0 ? -c : BYTE8_TO_CHAR (c); char_offset++; - coding->errors++; } no_more_source: @@ -5658,9 +5650,8 @@ decode_coding_charset (struct coding_system *coding) src = src_base; consumed_chars = consumed_chars_base; ONE_MORE_BYTE (c); - *charbuf++ = c < 0 ? -c : ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); + *charbuf++ = c < 0 ? -c : ASCII_CHAR_P (c) ? c : BYTE8_TO_CHAR (c); char_offset++; - coding->errors++; } no_more_source: @@ -6893,6 +6884,11 @@ decode_eol (struct coding_system *coding) } +/* MAX_LOOKUP's maximum value. MAX_LOOKUP is an int and so cannot + exceed INT_MAX. Also, MAX_LOOKUP is multiplied by sizeof (int) for + alloca, so it cannot exceed MAX_ALLOCA / sizeof (int). */ +enum { MAX_LOOKUP_MAX = min (INT_MAX, MAX_ALLOCA / sizeof (int)) }; + /* Return a translation table (or list of them) from coding system attribute vector ATTRS for encoding (if ENCODEP) or decoding (if not ENCODEP). */ @@ -6945,7 +6941,7 @@ get_translation_table (Lisp_Object attrs, bool encodep, int *max_lookup) { val = XCHAR_TABLE (translation_table)->extras[1]; if (NATNUMP (val) && *max_lookup < XFASTINT (val)) - *max_lookup = XFASTINT (val); + *max_lookup = min (XFASTINT (val), MAX_LOOKUP_MAX); } else if (CONSP (translation_table)) { @@ -6957,7 +6953,7 @@ get_translation_table (Lisp_Object attrs, bool encodep, int *max_lookup) { Lisp_Object tailval = XCHAR_TABLE (XCAR (tail))->extras[1]; if (NATNUMP (tailval) && *max_lookup < XFASTINT (tailval)) - *max_lookup = XFASTINT (tailval); + *max_lookup = min (XFASTINT (tailval), MAX_LOOKUP_MAX); } } } @@ -7040,8 +7036,10 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, int *buf = coding->charbuf; int *buf_end = buf + coding->charbuf_used; - if (EQ (coding->src_object, coding->dst_object)) + if (EQ (coding->src_object, coding->dst_object) + && ! NILP (coding->dst_object)) { + eassert (growable_destination (coding)); coding_set_source (coding); dst_end = ((unsigned char *) coding->source) + coding->consumed; } @@ -7080,6 +7078,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars) { + eassert (growable_destination (coding)); if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf)) / MAX_MULTIBYTE_LENGTH) < to_nchars) @@ -7124,7 +7123,10 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, const unsigned char *src_end = src + coding->consumed; if (EQ (coding->dst_object, coding->src_object)) - dst_end = (unsigned char *) src; + { + eassert (growable_destination (coding)); + dst_end = (unsigned char *) src; + } if (coding->src_multibyte != coding->dst_multibyte) { if (coding->src_multibyte) @@ -7140,6 +7142,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, ONE_MORE_BYTE (c); if (dst == dst_end) { + eassert (growable_destination (coding)); if (EQ (coding->src_object, coding->dst_object)) dst_end = (unsigned char *) src; if (dst == dst_end) @@ -7170,6 +7173,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, if (dst >= dst_end - 1) { + eassert (growable_destination (coding)); if (EQ (coding->src_object, coding->dst_object)) dst_end = (unsigned char *) src; if (dst >= dst_end - 1) @@ -7283,16 +7287,20 @@ produce_charset (struct coding_system *coding, int *charbuf, ptrdiff_t pos) coding->dst_object); } +#define MAX_CHARBUF_SIZE 0x4000 +/* How many units decoding functions expect in coding->charbuf at + most. Currently, decode_coding_emacs_mule expects the following + size, and that is the largest value. */ +#define MAX_CHARBUF_EXTRA_SIZE ((MAX_ANNOTATION_LENGTH * 3) + 1) -#define CHARBUF_SIZE 0x4000 - -#define ALLOC_CONVERSION_WORK_AREA(coding) \ - do { \ - coding->charbuf = SAFE_ALLOCA (CHARBUF_SIZE * sizeof (int)); \ - coding->charbuf_size = CHARBUF_SIZE; \ +#define ALLOC_CONVERSION_WORK_AREA(coding, size) \ + do { \ + ptrdiff_t units = min ((size) + MAX_CHARBUF_EXTRA_SIZE, \ + MAX_CHARBUF_SIZE); \ + coding->charbuf = SAFE_ALLOCA (units * sizeof (int)); \ + coding->charbuf_size = units; \ } while (0) - static void produce_annotation (struct coding_system *coding, ptrdiff_t pos) { @@ -7389,9 +7397,8 @@ decode_coding (struct coding_system *coding) coding->produced = coding->produced_char = 0; coding->chars_at_source = 0; record_conversion_result (coding, CODING_RESULT_SUCCESS); - coding->errors = 0; - ALLOC_CONVERSION_WORK_AREA (coding); + ALLOC_CONVERSION_WORK_AREA (coding, coding->src_bytes); attrs = CODING_ID_ATTRS (coding->id); translation_table = get_translation_table (attrs, 0, NULL); @@ -7785,9 +7792,8 @@ encode_coding (struct coding_system *coding) coding->consumed = coding->consumed_char = 0; coding->produced = coding->produced_char = 0; record_conversion_result (coding, CODING_RESULT_SUCCESS); - coding->errors = 0; - ALLOC_CONVERSION_WORK_AREA (coding); + ALLOC_CONVERSION_WORK_AREA (coding, coding->src_chars); if (coding->encoder == encode_coding_ccl) { @@ -8461,11 +8467,11 @@ from_unicode (Lisp_Object str) } Lisp_Object -from_unicode_buffer (const wchar_t* wstr) +from_unicode_buffer (const wchar_t *wstr) { return from_unicode ( make_unibyte_string ( - (char*) wstr, + (char *) wstr, /* we get one of the two final 0 bytes for free. */ 1 + sizeof (wchar_t) * wcslen (wstr))); } @@ -9049,13 +9055,13 @@ DEFUN ("find-coding-systems-region-internal", p = pbeg = BYTE_POS_ADDR (start_byte); pend = p + (end_byte - start_byte); - while (p < pend && ASCII_BYTE_P (*p)) p++; - while (p < pend && ASCII_BYTE_P (*(pend - 1))) pend--; + while (p < pend && ASCII_CHAR_P (*p)) p++; + while (p < pend && ASCII_CHAR_P (*(pend - 1))) pend--; work_table = Fmake_char_table (Qnil, Qnil); while (p < pend) { - if (ASCII_BYTE_P (*p)) + if (ASCII_CHAR_P (*p)) p++; else { @@ -9109,8 +9115,7 @@ DEFUN ("find-coding-systems-region-internal", DEFUN ("unencodable-char-position", Funencodable_char_position, Sunencodable_char_position, 3, 5, 0, - doc: /* -Return position of first un-encodable character in a region. + doc: /* Return position of first un-encodable character in a region. START and END specify the region and CODING-SYSTEM specifies the encoding to check. Return nil if CODING-SYSTEM does encode the region. @@ -9120,8 +9125,9 @@ list of positions. If optional 5th argument STRING is non-nil, it is a string to search for un-encodable characters. In that case, START and END are indexes -to the string. */) - (Lisp_Object start, Lisp_Object end, Lisp_Object coding_system, Lisp_Object count, Lisp_Object string) +to the string and treated as in `substring'. */) + (Lisp_Object start, Lisp_Object end, Lisp_Object coding_system, + Lisp_Object count, Lisp_Object string) { EMACS_INT n; struct coding_system coding; @@ -9158,12 +9164,7 @@ to the string. */) else { CHECK_STRING (string); - CHECK_NATNUM (start); - CHECK_NATNUM (end); - if (! (XINT (start) <= XINT (end) && XINT (end) <= SCHARS (string))) - args_out_of_range_3 (string, start, end); - from = XINT (start); - to = XINT (end); + validate_subarray (string, start, end, SCHARS (string), &from, &to); if (! STRING_MULTIBYTE (string)) return Qnil; p = SDATA (string) + string_char_to_byte (string, from); @@ -9187,7 +9188,7 @@ to the string. */) int c; if (ascii_compatible) - while (p < stop && ASCII_BYTE_P (*p)) + while (p < stop && ASCII_CHAR_P (*p)) p++, from++; if (p >= stop) { @@ -9303,12 +9304,12 @@ is nil. */) p = pbeg = BYTE_POS_ADDR (start_byte); pend = p + (end_byte - start_byte); - while (p < pend && ASCII_BYTE_P (*p)) p++, pos++; - while (p < pend && ASCII_BYTE_P (*(pend - 1))) pend--; + while (p < pend && ASCII_CHAR_P (*p)) p++, pos++; + while (p < pend && ASCII_CHAR_P (*(pend - 1))) pend--; while (p < pend) { - if (ASCII_BYTE_P (*p)) + if (ASCII_CHAR_P (*p)) p++; else { @@ -9616,7 +9617,7 @@ Return the corresponding character. */) CHECK_CODING_SYSTEM_GET_SPEC (Vsjis_coding_system, spec); attrs = AREF (spec, 0); - if (ASCII_BYTE_P (ch) + if (ASCII_CHAR_P (ch) && ! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) return code; @@ -9697,7 +9698,7 @@ Return the corresponding character. */) CHECK_CODING_SYSTEM_GET_SPEC (Vbig5_coding_system, spec); attrs = AREF (spec, 0); - if (ASCII_BYTE_P (ch) + if (ASCII_CHAR_P (ch) && ! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) return code; @@ -9758,7 +9759,7 @@ DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_intern doc: /* Internal use only. */) (Lisp_Object coding_system, Lisp_Object terminal) { - struct terminal *term = get_terminal (terminal, 1); + struct terminal *term = decode_live_terminal (terminal); struct coding_system *terminal_coding = TERMINAL_TERMINAL_CODING (term); CHECK_SYMBOL (coding_system); setup_coding_system (Fcheck_coding_system (coding_system), terminal_coding); @@ -9799,7 +9800,7 @@ frame's terminal device. */) (Lisp_Object terminal) { struct coding_system *terminal_coding - = TERMINAL_TERMINAL_CODING (get_terminal (terminal, 1)); + = TERMINAL_TERMINAL_CODING (decode_live_terminal (terminal)); Lisp_Object coding_system = CODING_ID_NAME (terminal_coding->id); /* For backward compatibility, return nil if it is `undecided'. */ @@ -9811,7 +9812,7 @@ DEFUN ("set-keyboard-coding-system-internal", Fset_keyboard_coding_system_intern doc: /* Internal use only. */) (Lisp_Object coding_system, Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_live_terminal (terminal); CHECK_SYMBOL (coding_system); if (NILP (coding_system)) coding_system = Qno_conversion; @@ -9830,7 +9831,7 @@ DEFUN ("keyboard-coding-system", (Lisp_Object terminal) { return CODING_ID_NAME (TERMINAL_KEYBOARD_CODING - (get_terminal (terminal, 1))->id); + (decode_live_terminal (terminal))->id); } @@ -10040,7 +10041,8 @@ make_subsidiaries (Lisp_Object base) { Lisp_Object subsidiaries; ptrdiff_t base_name_len = SBYTES (SYMBOL_NAME (base)); - char *buf = alloca (base_name_len + 6); + USE_SAFE_ALLOCA; + char *buf = SAFE_ALLOCA (base_name_len + 6); int i; memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len); @@ -10050,6 +10052,7 @@ make_subsidiaries (Lisp_Object base) strcpy (buf + base_name_len, suffixes[i]); ASET (subsidiaries, i, intern (buf)); } + SAFE_FREE (); return subsidiaries; } diff --git a/src/coding.h b/src/coding.h index 4e8b1056e43..ffd839f4212 100644 --- a/src/coding.h +++ b/src/coding.h @@ -434,11 +434,37 @@ struct coding_system /* Flag bits of the coding system. The meaning of each bit is common to all types of coding systems. */ - int common_flags; + unsigned common_flags : 14; /* Mode bits of the coding system. See the comments of the macros CODING_MODE_XXX. */ - unsigned int mode; + unsigned mode : 5; + + /* The following two members specify how binary 8-bit code 128..255 + are represented in source and destination text respectively. True + means they are represented by 2-byte sequence, false means they are + represented by 1-byte as is (see the comment in character.h). */ + bool_bf src_multibyte : 1; + bool_bf dst_multibyte : 1; + + /* True if the source of conversion is not in the member + `charbuf', but at `src_object'. */ + bool_bf chars_at_source : 1; + + /* Nonzero if the result of conversion is in `destination' + buffer rather than in `dst_object'. */ + bool_bf raw_destination : 1; + + /* Set to true if charbuf contains an annotation. */ + bool_bf annotated : 1; + + /* Used internally in coding.c. See the comment of detect_ascii. */ + unsigned eol_seen : 3; + + /* Finish status of code conversion. */ + ENUM_BF (coding_result_code) result : 3; + + int max_charset_id; /* Detailed information specific to each type of coding system. */ union @@ -451,16 +477,8 @@ struct coding_system struct undecided_spec undecided; } spec; - int max_charset_id; unsigned char *safe_charsets; - /* The following two members specify how binary 8-bit code 128..255 - are represented in source and destination text respectively. True - means they are represented by 2-byte sequence, false means they are - represented by 1-byte as is (see the comment in character.h). */ - bool_bf src_multibyte : 1; - bool_bf dst_multibyte : 1; - /* How may heading bytes we can skip for decoding. This is set to -1 in setup_coding_system, and updated by detect_coding. So, when this is equal to the byte length of the text being @@ -472,21 +490,9 @@ struct coding_system sequence. Set by detect_coding_utf_8. */ ptrdiff_t detected_utf8_bytes, detected_utf8_chars; - /* Used internally in coding.c. See the comment of detect_ascii. */ - int eol_seen; - /* The following members are set by encoding/decoding routine. */ ptrdiff_t produced, produced_char, consumed, consumed_char; - /* Number of error source data found in a decoding routine. */ - ptrdiff_t errors; - - /* Store the positions of error source data. */ - ptrdiff_t *error_positions; - - /* Finish status of code conversion. */ - enum coding_result_code result; - ptrdiff_t src_pos, src_pos_byte, src_chars, src_bytes; Lisp_Object src_object; const unsigned char *source; @@ -510,17 +516,6 @@ struct coding_system int *charbuf; int charbuf_size, charbuf_used; - /* True if the source of conversion is not in the member - `charbuf', but at `src_object'. */ - bool_bf chars_at_source : 1; - - /* Nonzero if the result of conversion is in `destination' - buffer rather than in `dst_object'. */ - bool_bf raw_destination : 1; - - /* Set to true if charbuf contains an annotation. */ - bool_bf annotated : 1; - unsigned char carryover[64]; int carryover_bytes; @@ -743,7 +738,7 @@ extern wchar_t *to_unicode (Lisp_Object str, Lisp_Object *buf); extern Lisp_Object from_unicode (Lisp_Object str); /* Convert WSTR to an Emacs string. */ -extern Lisp_Object from_unicode_buffer (const wchar_t* wstr); +extern Lisp_Object from_unicode_buffer (const wchar_t *wstr); #endif /* WINDOWSNT || CYGWIN */ diff --git a/src/commands.h b/src/commands.h index 36e3518b5ea..1a09f683563 100644 --- a/src/commands.h +++ b/src/commands.h @@ -39,7 +39,3 @@ extern Lisp_Object unread_switch_frame; /* Nonzero if input is coming from the keyboard. */ #define INTERACTIVE (NILP (Vexecuting_kbd_macro) && !noninteractive) - -/* Set this nonzero to force reconsideration of mode line. */ - -extern int update_mode_lines; diff --git a/src/composite.c b/src/composite.c index fa882141908..8982c904096 100644 --- a/src/composite.c +++ b/src/composite.c @@ -921,17 +921,18 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, return unbind_to (count, lgstring); } -static Lisp_Object _work_val; - /* 1 iff the character C is composable. Characters of general category Z? or C? are not composable except for ZWNJ and ZWJ. */ -#define CHAR_COMPOSABLE_P(C) \ - ((C) > ' ' \ - && ((C) == 0x200C || (C) == 0x200D \ - || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \ - (INTEGERP (_work_val) \ - && (XINT (_work_val) <= UNICODE_CATEGORY_So))))) +static bool +char_composable_p (int c) +{ + Lisp_Object val; + return (c > ' ' + && (c == 0x200C || c == 0x200D + || (val = CHAR_TABLE_REF (Vunicode_category_table, c), + (INTEGERP (val) && (XINT (val) <= UNICODE_CATEGORY_So))))); +} /* Update cmp_it->stop_pos to the next position after CHARPOS (and BYTEPOS) where character composition may happen. If BYTEPOS is @@ -1015,24 +1016,19 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, val = CHAR_TABLE_REF (Vcomposition_function_table, c); if (! NILP (val)) { - Lisp_Object elt; - int ridx; - - for (ridx = 0; CONSP (val); val = XCDR (val), ridx++) + for (int ridx = 0; CONSP (val); val = XCDR (val), ridx++) { - elt = XCAR (val); + Lisp_Object elt = XCAR (val); if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1)) && charpos - 1 - XFASTINT (AREF (elt, 1)) >= start) - break; - } - if (CONSP (val)) - { - cmp_it->rule_idx = ridx; - cmp_it->lookback = XFASTINT (AREF (elt, 1)); - cmp_it->stop_pos = charpos - 1 - cmp_it->lookback; - cmp_it->ch = c; - return; + { + cmp_it->rule_idx = ridx; + cmp_it->lookback = XFASTINT (AREF (elt, 1)); + cmp_it->stop_pos = charpos - 1 - cmp_it->lookback; + cmp_it->ch = c; + return; + } } } } @@ -1067,7 +1063,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, p = SDATA (string) + bytepos; c = STRING_CHAR_AND_LENGTH (p, len); limit = bytepos + len; - while (CHAR_COMPOSABLE_P (c)) + while (char_composable_p (c)) { val = CHAR_TABLE_REF (Vcomposition_function_table, c); if (! NILP (val)) @@ -1144,7 +1140,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, /* Skip all uncomposable characters. */ if (NILP (string)) { - while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c)) + while (charpos - 1 > endpos && ! char_composable_p (c)) { DEC_BOTH (charpos, bytepos); c = FETCH_MULTIBYTE_CHAR (bytepos); @@ -1152,7 +1148,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, } else { - while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c)) + while (charpos - 1 > endpos && ! char_composable_p (c)) { p--; while (! CHAR_HEAD_P (*p)) @@ -1486,7 +1482,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, |-B-|-C-|--D--| Here, it is known that characters after positions 1 and 9 can - never be composed (i.e. ! CHAR_COMPOSABLE_P (CH)), and + never be composed (i.e. ! char_composable_p (CH)), and composition A is an invalid one because it's partially covered by the valid composition C. And to know whether a composition is valid or not, the only way is to start searching forward from a @@ -1510,7 +1506,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, while (1) { c = STRING_CHAR (cur.p); - if (! CHAR_COMPOSABLE_P (c)) + if (! char_composable_p (c)) { if (limit <= pos) /* case (1) */ { @@ -1519,7 +1515,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, return 0; BACKWARD_CHAR (cur, stop); c = STRING_CHAR (cur.p); - } while (! CHAR_COMPOSABLE_P (c)); + } while (! char_composable_p (c)); fore_check_limit = cur.pos + 1; } else /* case (2) */ @@ -1535,7 +1531,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, prev = cur; BACKWARD_CHAR (cur, stop); c = STRING_CHAR (cur.p); - if (! CHAR_COMPOSABLE_P (c)) + if (! char_composable_p (c)) { cur = prev; break; @@ -1683,9 +1679,10 @@ Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a frame, or nil for the selected frame's terminal device. If the optional 4th argument STRING is not nil, it is a string -containing the target characters between indices FROM and TO. -Otherwise FROM and TO are character positions in current buffer; -they can be in either order, and can be integers or markers. +containing the target characters between indices FROM and TO, +which are treated as in `substring'. Otherwise FROM and TO are +character positions in current buffer; they can be in either order, +and can be integers or markers. A glyph-string is a vector containing information about how to display a specific character sequence. The format is: @@ -1722,7 +1719,7 @@ should be ignored. */) if (! FONT_OBJECT_P (font_object)) { struct coding_system *coding; - struct terminal *terminal = get_terminal (font_object, 1); + struct terminal *terminal = decode_live_terminal (font_object); coding = ((TERMINAL_TERMINAL_CODING (terminal)->common_flags & CODING_REQUIRE_ENCODING_MASK) @@ -1741,15 +1738,10 @@ should be ignored. */) } else { - CHECK_NATNUM (from); - CHECK_NATNUM (to); CHECK_STRING (string); + validate_subarray (string, from, to, SCHARS (string), &frompos, &topos); if (! STRING_MULTIBYTE (string)) error ("Attempt to shape unibyte text"); - if (! (XINT (from) <= XINT (to) && XINT (to) <= SCHARS (string))) - args_out_of_range_3 (string, from, to); - frompos = XFASTINT (from); - topos = XFASTINT (to); frombyte = string_char_to_byte (string, frompos); } @@ -1794,21 +1786,18 @@ DEFUN ("compose-string-internal", Fcompose_string_internal, Scompose_string_internal, 3, 5, 0, doc: /* Internal use only. -Compose text between indices START and END of STRING. -Optional 4th and 5th arguments are COMPONENTS and MODIFICATION-FUNC +Compose text between indices START and END of STRING, where +START and END are treated as in `substring'. Optional 4th +and 5th arguments are COMPONENTS and MODIFICATION-FUNC for the composition. See `compose-string' for more details. */) - (Lisp_Object string, Lisp_Object start, Lisp_Object end, Lisp_Object components, Lisp_Object modification_func) + (Lisp_Object string, Lisp_Object start, Lisp_Object end, + Lisp_Object components, Lisp_Object modification_func) { - CHECK_STRING (string); - CHECK_NUMBER (start); - CHECK_NUMBER (end); + ptrdiff_t from, to; - if (XINT (start) < 0 || - XINT (start) > XINT (end) - || XINT (end) > SCHARS (string)) - args_out_of_range (start, end); - - compose_text (XINT (start), XINT (end), components, modification_func, string); + CHECK_STRING (string); + validate_subarray (string, start, end, SCHARS (string), &from, &to); + compose_text (from, to, components, modification_func, string); return string; } diff --git a/src/conf_post.h b/src/conf_post.h index 254e004d655..8667e2554cd 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -34,9 +34,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <stdbool.h> -/* The pre-C99 <stdbool.h> emulation doesn't work for bool bitfields. - Nor does compiling Objective-C with standard GCC. */ -#if __STDC_VERSION__ < 199901 || NS_IMPL_GNUSTEP +/* The type of bool bitfields. Needed to compile Objective-C with + standard GCC. It was also needed to port to pre-C99 compilers, + although we don't care about that any more. */ +#if NS_IMPL_GNUSTEP typedef unsigned int bool_bf; #else typedef bool bool_bf; @@ -79,6 +80,23 @@ typedef bool bool_bf; #define vfork fork #endif /* DARWIN_OS */ +/* If HYBRID_MALLOC is defined (e.g., on Cygwin), emacs will use + gmalloc before dumping and the system malloc after dumping. + hybrid_malloc and friends, defined in gmalloc.c, are wrappers that + accomplish this. */ +#ifdef HYBRID_MALLOC +#ifdef emacs +#define malloc hybrid_malloc +#define realloc hybrid_realloc +#define calloc hybrid_calloc +#define free hybrid_free +#if defined HAVE_GET_CURRENT_DIR_NAME && !defined BROKEN_GET_CURRENT_DIR_NAME +#define HYBRID_GET_CURRENT_DIR_NAME 1 +#define get_current_dir_name hybrid_get_current_dir_name +#endif +#endif +#endif /* HYBRID_MALLOC */ + /* We have to go this route, rather than the old hpux9 approach of renaming the functions via macros. The system's stdlib.h has fully prototyped declarations, which yields a conflicting definition of @@ -87,10 +105,6 @@ typedef bool bool_bf; #ifdef HPUX #undef srandom #undef random -/* We try to avoid checking for random and rint on hpux in - configure.ac, but some other configure test might check for them as - a dependency, so to be safe we also undefine them here. - */ #undef HAVE_RANDOM #undef HAVE_RINT #endif /* HPUX */ @@ -225,16 +239,30 @@ extern void _DebPrint (const char *fmt, ...); #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST +#if 3 <= __GNUC__ +# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +#else +# define ATTRIBUTE_MALLOC +#endif + +#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__) +# define ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args)) +#else +# define ATTRIBUTE_ALLOC_SIZE(args) +#endif + +#define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args) + /* Work around GCC bug 59600: when a function is inlined, the inlined code may have its addresses sanitized even if the function has the - no_sanitize_address attribute. This bug is present in GCC 4.8.2 - and clang 3.3, the latest releases as of December 2013, and the - only platforms known to support address sanitization. When the bug - is fixed the #if can be updated accordingly. */ -#if ADDRESS_SANITIZER -# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE + no_sanitize_address attribute. This bug is fixed in GCC 4.9.0 and + clang 3.4. */ +#if (! ADDRESS_SANITIZER \ + || ((4 < __GNUC__ + (9 <= __GNUC_MINOR__)) \ + || 3 < __clang_major__ + (4 <= __clang_minor__))) +# define ADDRESS_SANITIZER_WORKAROUND /* No workaround needed. */ #else -# define ADDRESS_SANITIZER_WORKAROUND +# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE #endif /* Attribute of functions whose code should not have addresses @@ -296,12 +324,10 @@ extern void _DebPrint (const char *fmt, ...); struct s { ...; t name[FLEXIBLE_ARRAY_MEMBER]; }; and allocate (offsetof (struct s, name) + N * sizeof (t)) bytes. IBM xlc 12.1 claims to do C99 but mishandles flexible array members. */ -#if 199901 <= __STDC_VERSION__ && !defined __IBMC__ -# define FLEXIBLE_ARRAY_MEMBER -#elif __GNUC__ && !defined __STRICT_ANSI__ -# define FLEXIBLE_ARRAY_MEMBER 0 -#else +#ifdef __IBMC__ # define FLEXIBLE_ARRAY_MEMBER 1 +#else +# define FLEXIBLE_ARRAY_MEMBER #endif /* Use this to suppress gcc's `...may be used before initialized' warnings. */ diff --git a/src/data.c b/src/data.c index f02b4588ad0..9977a3aaadd 100644 --- a/src/data.c +++ b/src/data.c @@ -727,6 +727,11 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, if (AUTOLOADP (function)) Fput (symbol, Qautoload, XCDR (function)); + /* Convert to eassert or remove after GC bug is found. In the + meantime, check unconditionally, at a slight perf hit. */ + if (valid_lisp_object_p (definition) < 1) + emacs_abort (); + set_symbol_function (symbol, definition); return definition; @@ -966,6 +971,51 @@ do_symval_forwarding (register union Lisp_Fwd *valcontents) } } +/* Used to signal a user-friendly error when symbol WRONG is + not a member of CHOICE, which should be a list of symbols. */ + +void +wrong_choice (Lisp_Object choice, Lisp_Object wrong) +{ + ptrdiff_t i = 0, len = XINT (Flength (choice)); + Lisp_Object obj, *args; + AUTO_STRING (one_of, "One of "); + AUTO_STRING (comma, ", "); + AUTO_STRING (or, " or "); + AUTO_STRING (should_be_specified, " should be specified"); + + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (args, len * 2 + 1); + + args[i++] = one_of; + + for (obj = choice; !NILP (obj); obj = XCDR (obj)) + { + args[i++] = SYMBOL_NAME (XCAR (obj)); + args[i++] = (NILP (XCDR (obj)) ? should_be_specified + : NILP (XCDR (XCDR (obj))) ? or : comma); + } + + obj = Fconcat (i, args); + SAFE_FREE (); + xsignal2 (Qerror, obj, wrong); +} + +/* Used to signal a user-friendly error if WRONG is not a number or + integer/floating-point number outsize of inclusive MIN..MAX range. */ + +static void +wrong_range (Lisp_Object min, Lisp_Object max, Lisp_Object wrong) +{ + AUTO_STRING (value_should_be_from, "Value should be from "); + AUTO_STRING (to, " to "); + xsignal2 (Qerror, + Fconcat (4, ((Lisp_Object []) + {value_should_be_from, Fnumber_to_string (min), + to, Fnumber_to_string (max)})), + wrong); +} + /* Store NEWVAL into SYMBOL, where VALCONTENTS is found in the value cell of SYMBOL. If SYMBOL is buffer-local, VALCONTENTS should be the buffer-independent contents of the value cell: forwarded just one @@ -1022,10 +1072,33 @@ store_symval_forwarding (union Lisp_Fwd *valcontents, register Lisp_Object newva int offset = XBUFFER_OBJFWD (valcontents)->offset; Lisp_Object predicate = XBUFFER_OBJFWD (valcontents)->predicate; - if (!NILP (predicate) && !NILP (newval) - && NILP (call1 (predicate, newval))) - wrong_type_argument (predicate, newval); + if (!NILP (newval)) + { + if (SYMBOLP (predicate)) + { + Lisp_Object prop; + + if ((prop = Fget (predicate, Qchoice), !NILP (prop))) + { + if (NILP (Fmemq (newval, prop))) + wrong_choice (prop, newval); + } + else if ((prop = Fget (predicate, Qrange), !NILP (prop))) + { + Lisp_Object min = XCAR (prop), max = XCDR (prop); + if (!NUMBERP (newval) + || !NILP (arithcompare (newval, min, ARITH_LESS)) + || !NILP (arithcompare (newval, max, ARITH_GRTR))) + wrong_range (min, max, newval); + } + else if (FUNCTIONP (predicate)) + { + if (NILP (call1 (predicate, newval))) + wrong_type_argument (predicate, newval); + } + } + } if (buf == NULL) buf = current_buffer; set_per_buffer_value (buf, offset, newval); @@ -1882,19 +1955,11 @@ DEFUN ("local-variable-p", Flocal_variable_p, Slocal_variable_p, 1, 2, 0, doc: /* Non-nil if VARIABLE has a local binding in buffer BUFFER. BUFFER defaults to the current buffer. */) - (register Lisp_Object variable, Lisp_Object buffer) + (Lisp_Object variable, Lisp_Object buffer) { - register struct buffer *buf; + struct buffer *buf = decode_buffer (buffer); struct Lisp_Symbol *sym; - if (NILP (buffer)) - buf = current_buffer; - else - { - CHECK_BUFFER (buffer); - buf = XBUFFER (buffer); - } - CHECK_SYMBOL (variable); sym = XSYMBOL (variable); @@ -2327,7 +2392,7 @@ arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args, ptrdiff_t argnum; for (argnum = 1; argnum < nargs; ++argnum) { - if (EQ (Qnil, arithcompare (args[argnum-1], args[argnum], comparison))) + if (EQ (Qnil, arithcompare (args[argnum - 1], args[argnum], comparison))) return Qnil; } return Qt; @@ -2379,24 +2444,6 @@ DEFUN ("/=", Fneq, Sneq, 2, 2, 0, { return arithcompare (num1, num2, ARITH_NOTEQUAL); } - -DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, - doc: /* Return t if NUMBER is zero. */) - (register Lisp_Object number) -{ - CHECK_NUMBER_OR_FLOAT (number); - - if (FLOATP (number)) - { - if (XFLOAT_DATA (number) == 0.0) - return Qt; - return Qnil; - } - - if (!XINT (number)) - return Qt; - return Qnil; -} /* Convert the cons-of-integers, integer, or float value C to an unsigned value with maximum value MAX. Signal an error if C does not @@ -2888,7 +2935,7 @@ In this case, the sign bit is duplicated. */) if (XINT (count) >= BITS_PER_EMACS_INT) XSETINT (val, 0); else if (XINT (count) > 0) - XSETINT (val, XINT (value) << XFASTINT (count)); + XSETINT (val, XUINT (value) << XFASTINT (count)); else if (XINT (count) <= -BITS_PER_EMACS_INT) XSETINT (val, XINT (value) < 0 ? -1 : 0); else @@ -3643,7 +3690,6 @@ syms_of_data (void) defsubr (&Sleq); defsubr (&Sgeq); defsubr (&Sneq); - defsubr (&Szerop); defsubr (&Splus); defsubr (&Sminus); defsubr (&Stimes); diff --git a/src/dbusbind.c b/src/dbusbind.c index 8ebc56c72c4..4852739d8e4 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -142,10 +142,7 @@ static bool xd_in_read_queued_messages = 0; } while (0) #else /* !DBUS_DEBUG */ -# if __STDC_VERSION__ < 199901 -# define XD_DEBUG_MESSAGE (void) /* Pre-C99 compilers cannot debug. */ -# else -# define XD_DEBUG_MESSAGE(...) \ +# define XD_DEBUG_MESSAGE(...) \ do { \ if (!NILP (Vdbus_debug)) \ { \ @@ -154,7 +151,6 @@ static bool xd_in_read_queued_messages = 0; message ("%s: %s", __func__, s); \ } \ } while (0) -# endif # define XD_DEBUG_VALID_LISP_OBJECT_P(object) #endif @@ -765,7 +761,7 @@ xd_append_arg (int dtype, Lisp_Object object, DBusMessageIter *iter) && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object))) && NILP (CDR_SAFE (XD_NEXT_VALUE (object)))) { - strcpy (signature, SSDATA (CAR_SAFE (XD_NEXT_VALUE (object)))); + lispstpcpy (signature, CAR_SAFE (XD_NEXT_VALUE (object))); object = CDR_SAFE (XD_NEXT_VALUE (object)); } @@ -1058,6 +1054,7 @@ xd_remove_watch (DBusWatch *watch, void *data) /* Unset session environment. */ #if 0 + /* This is buggy, since unsetenv is not thread-safe. */ if (XSYMBOL (QCdbus_session_bus) == data) { XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); @@ -1223,9 +1220,6 @@ this connection to those buses. */) XSETFASTINT (val, (intptr_t) connection); xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses); - /* We do not want to abort. */ - xputenv ("DBUS_FATAL_WARNINGS=0"); - /* Cleanup. */ dbus_error_free (&derror); } @@ -1742,6 +1736,13 @@ xd_read_queued_messages (int fd, void *data) void +init_dbusbind (void) +{ + /* We do not want to abort. */ + xputenv ("DBUS_FATAL_WARNINGS=0"); +} + +void syms_of_dbusbind (void) { diff --git a/src/decompress.c b/src/decompress.c index cd8a3d1e962..24ce852245c 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -60,10 +60,7 @@ init_zlib_functions (void) HMODULE library = w32_delayed_load (Qzlib_dll); if (!library) - { - message1 ("zlib library not found"); - return false; - } + return false; LOAD_ZLIB_FN (library, inflateInit2_); LOAD_ZLIB_FN (library, inflate); @@ -150,7 +147,10 @@ This function can be called only in unibyte buffers. */) if (!zlib_initialized) zlib_initialized = init_zlib_functions (); if (!zlib_initialized) - return Qnil; + { + message1 ("zlib library not found"); + return Qnil; + } #endif /* This is a unibyte buffer, so character positions and bytes are diff --git a/src/deps.mk b/src/deps.mk index 1d67d750983..3fdbbe6605f 100644 --- a/src/deps.mk +++ b/src/deps.mk @@ -1,7 +1,7 @@ ### deps.mk --- src/Makefile fragment for GNU Emacs -## Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2014 Free Software -## Foundation, Inc. +## Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2014 +## Free Software Foundation, Inc. ## This file is part of GNU Emacs. @@ -27,8 +27,6 @@ ## Eg callproc.c only depends on w32.h for WINDOWSNT builds. ## One way to fix this would be to replace w32.h (etc) by $(W32_H), ## a variable set by configure. Does not seem worth the trouble. -## Since the w32 build does not even use this file, you might ask -## why these dependencies are here at all... ## nsgui.h: In fact, every .o file depends directly or indirectly on ## dispextern.h and hence nsgui.h under NS. But the ones that actually diff --git a/src/dired.c b/src/dired.c index c2db1f02782..ba6a61a2f5b 100644 --- a/src/dired.c +++ b/src/dired.c @@ -995,7 +995,7 @@ file_attributes (int fd, char const *name, Lisp_Object id_format) values[10] = INTEGER_TO_CONS (s.st_ino); values[11] = INTEGER_TO_CONS (s.st_dev); - return Flist (sizeof (values) / sizeof (values[0]), values); + return Flist (ARRAYELTS (values), values); } DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0, diff --git a/src/dispextern.h b/src/dispextern.h index 576f22870c2..0dd0887c7e6 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -118,7 +118,8 @@ enum window_part ON_RIGHT_FRINGE, ON_LEFT_MARGIN, ON_RIGHT_MARGIN, - ON_SCROLL_BAR, + ON_VERTICAL_SCROLL_BAR, + ON_HORIZONTAL_SCROLL_BAR, ON_RIGHT_DIVIDER, ON_BOTTOM_DIVIDER }; @@ -444,8 +445,8 @@ struct glyph /* True means don't display cursor here. */ bool_bf avoid_cursor_p : 1; - /* Resolved bidirectional level of this character [0..63]. */ - unsigned resolved_level : 5; + /* Resolved bidirectional level of this character [0..127]. */ + unsigned resolved_level : 7; /* Resolved bidirectional type of this character, see enum bidi_type_t below. Note that according to UAX#9, only some @@ -1716,8 +1717,10 @@ struct face attributes except the font. */ struct face *ascii_face; +#ifdef HAVE_XFT /* Extra member that a font-driver uses privately. */ void *extra; +#endif }; @@ -1795,16 +1798,6 @@ struct face_cache bool_bf menu_face_changed_p : 1; }; - -/* Prepare face FACE for use on frame F. This must be called before - using X resources of FACE. */ - -#define PREPARE_FACE_FOR_DISPLAY(F, FACE) \ - do { \ - if ((FACE)->gc == 0) \ - prepare_face_for_display ((F), (FACE)); \ - } while (false) - /* Return a pointer to the face with ID on frame F, or null if such a face doesn't exist. */ @@ -1864,7 +1857,9 @@ GLYPH_CODE_P (Lisp_Object gc) extern int face_change_count; /* For reordering of bidirectional text. */ -#define BIDI_MAXLEVEL 64 + +/* UAX#9's max_depth value. */ +#define BIDI_MAXDEPTH 125 /* Data type for describing the bidirectional character types. The first 7 must be at the beginning, because they are the only values @@ -1901,23 +1896,39 @@ typedef enum { NEUTRAL_ON /* other neutrals */ } bidi_type_t; +/* Data type for describing the Bidi Paired Bracket Type of a character. + + The order of members must be in sync with the 8th element of the + member of unidata-prop-alist (in admin/unidata/unidata-gen.el) for + Unicode character property `bracket-type'. */ +typedef enum { + BIDI_BRACKET_NONE = 1, + BIDI_BRACKET_OPEN, + BIDI_BRACKET_CLOSE +} bidi_bracket_type_t; + /* The basic directionality data type. */ typedef enum { NEUTRAL_DIR, L2R, R2L } bidi_dir_t; /* Data type for storing information about characters we need to remember. */ struct bidi_saved_info { - ptrdiff_t bytepos, charpos; /* character's buffer position */ + ptrdiff_t charpos; /* character's buffer position */ bidi_type_t type; /* character's resolved bidi type */ - bidi_type_t type_after_w1; /* original type of the character, after W1 */ - bidi_type_t orig_type; /* type as we found it in the buffer */ + bidi_type_t orig_type; /* bidi type as we found it in the buffer */ }; -/* Data type for keeping track of saved embedding levels and override - status information. */ +/* Data type for keeping track of information about saved embedding + levels, override status, isolate status, and isolating sequence + runs. */ struct bidi_stack { - int level; - bidi_dir_t override; + struct bidi_saved_info last_strong; + struct bidi_saved_info next_for_neutral; + struct bidi_saved_info prev_for_neutral; + unsigned level : 7; + bool_bf isolate_status : 1; + unsigned override : 2; + unsigned sos : 2; }; /* Data type for storing information about a string being iterated on. */ @@ -1942,22 +1953,24 @@ struct bidi_it { ptrdiff_t nchars; /* its "length", usually 1; it's > 1 for a run of characters covered by a display string */ ptrdiff_t ch_len; /* its length in bytes */ - bidi_type_t type; /* bidi type of this character, after + bidi_type_t type; /* final bidi type of this character, after resolving weak and neutral types */ - bidi_type_t type_after_w1; /* original type, after overrides and W1 */ - bidi_type_t orig_type; /* original type, as found in the buffer */ - int resolved_level; /* final resolved level of this character */ - int invalid_levels; /* how many PDFs to ignore */ - int invalid_rl_levels; /* how many PDFs from RLE/RLO to ignore */ + bidi_type_t type_after_wn; /* bidi type after overrides and Wn */ + bidi_type_t orig_type; /* original bidi type, as found in the buffer */ + char resolved_level; /* final resolved level of this character */ + char isolate_level; /* count of isolate initiators unmatched by PDI */ + ptrdiff_t invalid_levels; /* how many PDFs to ignore */ + ptrdiff_t invalid_isolates; /* how many PDIs to ignore */ struct bidi_saved_info prev; /* info about previous character */ struct bidi_saved_info last_strong; /* last-seen strong directional char */ struct bidi_saved_info next_for_neutral; /* surrounding characters for... */ struct bidi_saved_info prev_for_neutral; /* ...resolving neutrals */ struct bidi_saved_info next_for_ws; /* character after sequence of ws */ + ptrdiff_t bracket_pairing_pos; /* position of pairing bracket */ + bidi_type_t bracket_enclosed_type; /* type for bracket resolution */ ptrdiff_t next_en_pos; /* pos. of next char for determining ET type */ bidi_type_t next_en_type; /* type of char at next_en_pos */ - ptrdiff_t ignore_bn_limit; /* position until which to ignore BNs */ - bidi_dir_t sor; /* direction of start-of-run in effect */ + bidi_dir_t sos; /* direction of start-of-sequence in effect */ int scan_dir; /* direction of text scan, 1: forw, -1: back */ ptrdiff_t disp_pos; /* position of display string after ch */ int disp_prop; /* if non-zero, there really is a @@ -1967,12 +1980,11 @@ struct bidi_it { /* Note: Everything from here on is not copied/saved when the bidi iterator state is saved, pushed, or popped. So only put here stuff that is not part of the bidi iterator's state! */ - struct bidi_stack level_stack[BIDI_MAXLEVEL]; /* stack of embedding levels */ + struct bidi_stack level_stack[BIDI_MAXDEPTH+2+1]; /* directional status stack */ struct bidi_string_data string; /* string to reorder */ struct window *w; /* the window being displayed */ bidi_dir_t paragraph_dir; /* current paragraph direction */ ptrdiff_t separator_limit; /* where paragraph separator should end */ - bool_bf prev_was_pdf : 1; /* if true, previous char was PDF */ bool_bf first_elt : 1; /* if true, examine current char first */ bool_bf new_paragraph : 1; /* if true, we expect a new paragraph */ bool_bf frame_window_p : 1; /* true if displaying on a GUI frame */ @@ -2831,45 +2843,51 @@ struct redisplay_interface int h, int wd); void (*destroy_fringe_bitmap) (int which); -/* Compute left and right overhang of glyph string S. - A NULL pointer if platform does not support this. */ + /* Compute left and right overhang of glyph string S. + A NULL pointer if platform does not support this. */ void (*compute_glyph_string_overhangs) (struct glyph_string *s); -/* Draw a glyph string S. */ + /* Draw a glyph string S. */ void (*draw_glyph_string) (struct glyph_string *s); -/* Define cursor CURSOR on frame F. */ + /* Define cursor CURSOR on frame F. */ void (*define_frame_cursor) (struct frame *f, Cursor cursor); -/* Clear the area at (X,Y,WIDTH,HEIGHT) of frame F. */ + /* Clear the area at (X,Y,WIDTH,HEIGHT) of frame F. */ void (*clear_frame_area) (struct frame *f, int x, int y, int width, int height); -/* Draw specified cursor CURSOR_TYPE of width CURSOR_WIDTH - at row GLYPH_ROW on window W if ON_P is true. If ON_P is - false, don't draw cursor. If ACTIVE_P is true, system caret - should track this cursor (when applicable). */ + /* Draw specified cursor CURSOR_TYPE of width CURSOR_WIDTH + at row GLYPH_ROW on window W if ON_P is true. If ON_P is + false, don't draw cursor. If ACTIVE_P is true, system caret + should track this cursor (when applicable). */ void (*draw_window_cursor) (struct window *w, struct glyph_row *glyph_row, int x, int y, enum text_cursor_kinds cursor_type, int cursor_width, bool on_p, bool active_p); -/* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */ + /* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */ void (*draw_vertical_window_border) (struct window *w, int x, int y_0, int y_1); -/* Draw window divider for window W from (X_0, Y_0) to (X_1, ,Y_1). */ + /* Draw window divider for window W from (X_0, Y_0) to (X_1, ,Y_1). */ void (*draw_window_divider) (struct window *w, int x_0, int x_1, int y_0, int y_1); -/* Shift display of frame F to make room for inserted glyphs. - The area at pixel (X,Y) of width WIDTH and height HEIGHT is - shifted right by SHIFT_BY pixels. */ + /* Shift display of frame F to make room for inserted glyphs. + The area at pixel (X,Y) of width WIDTH and height HEIGHT is + shifted right by SHIFT_BY pixels. */ void (*shift_glyphs_for_insert) (struct frame *f, int x, int y, int width, int height, int shift_by); + /* Start display hourglass cursor on frame F. */ + void (*show_hourglass) (struct frame *f); + + /* Cancel hourglass cursor on frame F. */ + void (*hide_hourglass) (struct frame *f); + #endif /* HAVE_WINDOW_SYSTEM */ }; @@ -3166,9 +3184,8 @@ int default_line_pixel_height (struct window *); int display_prop_intangible_p (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t); void resize_echo_area_exactly (void); int resize_mini_window (struct window *, int); -#if defined USE_TOOLKIT_SCROLL_BARS && !defined USE_GTK void set_vertical_scroll_bar (struct window *); -#endif +void set_horizontal_scroll_bar (struct window *); int try_window (Lisp_Object, struct text_pos, int); void window_box (struct window *, enum glyph_row_area, int *, int *, int *, int *); @@ -3178,7 +3195,6 @@ int window_box_width (struct window *, enum glyph_row_area); int window_box_left (struct window *, enum glyph_row_area); int window_box_left_offset (struct window *, enum glyph_row_area); int window_box_right (struct window *, enum glyph_row_area); -int window_box_right_offset (struct window *, enum glyph_row_area); int estimate_mode_line_height (struct frame *, enum face_id); int move_it_to (struct it *, ptrdiff_t, int, int, int, int); void pixel_to_glyph_coords (struct frame *, int, int, int *, int *, @@ -3241,9 +3257,7 @@ extern void draw_phys_cursor_glyph (struct window *, enum draw_glyphs_face); extern void get_phys_cursor_geometry (struct window *, struct glyph_row *, struct glyph *, int *, int *, int *); -#if HAVE_NTGUI extern void erase_phys_cursor (struct window *); -#endif extern void display_and_set_cursor (struct window *, bool, int, int, int, int); extern void x_update_cursor (struct frame *, bool); extern void x_clear_cursor (struct window *); @@ -3282,7 +3296,6 @@ void draw_fringe_bitmap (struct window *, struct glyph_row *, int); void draw_row_fringe_bitmaps (struct window *, struct glyph_row *); bool draw_window_fringes (struct window *, bool); bool update_window_fringes (struct window *, bool); -void compute_fringe_widths (struct frame *, bool); #ifdef HAVE_NTGUI void w32_init_fringe (struct redisplay_interface *); @@ -3357,13 +3370,13 @@ void update_face_from_frame_parameter (struct frame *, Lisp_Object, Lisp_Object); Lisp_Object tty_color_name (struct frame *, int); void clear_face_cache (int); -#ifdef MSDOS unsigned long load_color (struct frame *, struct face *, Lisp_Object, enum lface_attribute_index); -#endif char *choose_face_font (struct frame *, Lisp_Object *, Lisp_Object, int *); +#ifdef HAVE_WINDOW_SYSTEM void prepare_face_for_display (struct frame *, struct face *); +#endif int lookup_named_face (struct frame *, Lisp_Object, int); int lookup_basic_face (struct frame *, int); int smaller_face (struct frame *, int, int); @@ -3399,6 +3412,7 @@ void gamma_correct (struct frame *, COLORREF *); #ifdef HAVE_WINDOW_SYSTEM void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); +void x_change_tool_bar_height (struct frame *f, int); extern Lisp_Object tip_frame; extern Window tip_window; @@ -3406,14 +3420,6 @@ extern frame_parm_handler x_frame_parm_handlers[]; extern void start_hourglass (void); extern void cancel_hourglass (void); -extern bool hourglass_shown_p; -/* If non-null, an asynchronous timer that, when it expires, displays - an hourglass cursor on all frames. */ -extern struct atimer *hourglass_atimer; - -/* Each GUI implements these. FIXME: move into RIF. */ -extern void show_hourglass (struct atimer *); -extern void hide_hourglass (void); /* Returns the background color of IMG, calculating one heuristically if necessary. If non-zero, XIMG is an existing XImage object to use for @@ -3513,7 +3519,6 @@ extern void calculate_costs (struct frame *); extern void produce_glyphs (struct it *); extern bool tty_capable_p (struct tty_display_info *, unsigned); extern void set_tty_color_mode (struct tty_display_info *, struct frame *); -extern struct terminal *get_named_tty (const char *); extern void create_tty_output (struct frame *); extern struct terminal *init_tty (const char *, const char *, bool); extern void tty_append_glyph (struct it *); @@ -3521,13 +3526,13 @@ extern void tty_append_glyph (struct it *); /* Defined in scroll.c */ -extern int scrolling_max_lines_saved (int, int, int *, int *, int *); +extern int scrolling_max_lines_saved (int, int, unsigned *, unsigned *, int *); extern void do_line_insertion_deletion_costs (struct frame *, const char *, const char *, const char *, const char *, const char *, const char *, int); -void scrolling_1 (struct frame *, int, int, int, int *, int *, int *, - int *, int); +void scrolling_1 (struct frame *, int, int, int, int *, int *, unsigned *, + unsigned *, int); /* Defined in frame.c */ diff --git a/src/dispnew.c b/src/dispnew.c index 71345775045..3ab8bcf3e64 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -72,7 +72,6 @@ struct dim static void update_frame_line (struct frame *, int); static int required_matrix_height (struct window *); static int required_matrix_width (struct window *); -static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool, bool); static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t); static void build_frame_matrix_from_window_tree (struct glyph_matrix *, struct window *); @@ -1108,10 +1107,10 @@ prepare_desired_row (struct window *w, struct glyph_row *row, bool mode_line_p) /* Return a hash code for glyph row ROW, which may be from current or desired matrix of frame F. */ -static int +static unsigned line_hash_code (struct frame *f, struct glyph_row *row) { - int hash = 0; + unsigned hash = 0; if (row->enabled_p) { @@ -2015,12 +2014,12 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f) /* Size of frame matrices must equal size of frame. Note that we are called for X frames with window widths NOT equal to the frame width (from CHANGE_FRAME_SIZE_1). */ - if (matrix_dim.width != FRAME_COLS (f) - || matrix_dim.height != FRAME_LINES (f)) + if (matrix_dim.width != FRAME_TOTAL_COLS (f) + || matrix_dim.height != FRAME_TOTAL_LINES (f)) return; - eassert (matrix_dim.width == FRAME_COLS (f) - && matrix_dim.height == FRAME_LINES (f)); + eassert (matrix_dim.width == FRAME_TOTAL_COLS (f) + && matrix_dim.height == FRAME_TOTAL_LINES (f)); /* Pointers to glyph memory in glyph rows are exchanged during the update phase of redisplay, which means in general that a @@ -2122,11 +2121,11 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f) w->left_col = 0; w->pixel_top = FRAME_MENU_BAR_HEIGHT (f); w->top_line = FRAME_MENU_BAR_LINES (f); + w->total_cols = FRAME_TOTAL_COLS (f); w->pixel_width = (FRAME_PIXEL_WIDTH (f) - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); - w->total_cols = FRAME_TOTAL_COLS (f); - w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f); w->total_lines = FRAME_TOOL_BAR_LINES (f); + w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f); allocate_matrices_for_window_redisplay (w); } #endif @@ -2138,7 +2137,7 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f) static void adjust_decode_mode_spec_buffer (struct frame *f) { - ssize_t frame_message_buf_size = FRAME_MESSAGE_BUF_SIZE (f); + int frame_message_buf_size = FRAME_MESSAGE_BUF_SIZE (f); eassert (frame_message_buf_size >= 0); f->decode_mode_spec_buffer = xrealloc (f->decode_mode_spec_buffer, @@ -2687,7 +2686,8 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin int i; /* Make a copy of the original rows. */ - old_rows = alloca (nlines * sizeof *old_rows); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (old_rows, 1, nlines); memcpy (old_rows, new_rows, nlines * sizeof *old_rows); /* Assign new rows, maybe clear lines. */ @@ -2709,6 +2709,8 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin if (frame_matrix_frame) mirror_line_dance (XWINDOW (frame_matrix_frame->root_window), unchanged_at_top, nlines, copy_from, retained_p); + + SAFE_FREE (); } @@ -2801,7 +2803,8 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy struct glyph_row *old_rows; /* Make a copy of the original rows of matrix m. */ - old_rows = alloca (m->nrows * sizeof *old_rows); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (old_rows, 1, m->nrows); memcpy (old_rows, m->rows, m->nrows * sizeof *old_rows); for (i = 0; i < nlines; ++i) @@ -2877,6 +2880,8 @@ mirror_line_dance (struct window *w, int unchanged_at_top, int nlines, int *copy /* Check that no pointers are lost. */ CHECK_MATRIX (m); + + SAFE_FREE (); } /* Next window on same level. */ @@ -2958,7 +2963,7 @@ window_to_frame_vpos (struct window *w, int vpos) eassert (!FRAME_WINDOW_P (XFRAME (w->frame))); eassert (vpos >= 0 && vpos <= w->desired_matrix->nrows); vpos += WINDOW_TOP_EDGE_LINE (w); - eassert (vpos >= 0 && vpos <= FRAME_LINES (XFRAME (w->frame))); + eassert (vpos >= 0 && vpos <= FRAME_TOTAL_LINES (XFRAME (w->frame))); return vpos; } @@ -3423,7 +3428,7 @@ update_window (struct window *w, bool force_p) mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix); if (mode_line_row->mode_line_p && mode_line_row->enabled_p) { - mode_line_row->y = yb; + mode_line_row->y = yb + WINDOW_SCROLL_BAR_AREA_HEIGHT (w); update_window_line (w, MATRIX_ROW_VPOS (mode_line_row, desired_matrix), &mouse_face_overwritten_p); @@ -4539,7 +4544,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, } } - pause_p = 0 < i && i < FRAME_LINES (f) - 1; + pause_p = 0 < i && i < FRAME_TOTAL_LINES (f) - 1; /* Now just clean up termcap drivers and set cursor, etc. */ if (!pause_p && set_cursor_p) @@ -4572,7 +4577,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, cursor at the end of the prompt. If the mini-buffer is several lines high, find the last line that has any text on it. */ - row = FRAME_LINES (f); + row = FRAME_TOTAL_LINES (f); do { --row; @@ -4600,7 +4605,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, if (col >= FRAME_CURSOR_X_LIMIT (f)) { /* If we have another row, advance cursor into it. */ - if (row < FRAME_LINES (f) - 1) + if (row < FRAME_TOTAL_LINES (f) - 1) { col = FRAME_LEFT_SCROLL_BAR_COLS (f); row++; @@ -4650,14 +4655,19 @@ scrolling (struct frame *frame) int unchanged_at_top, unchanged_at_bottom; int window_size; int changed_lines; - int *old_hash = alloca (FRAME_LINES (frame) * sizeof (int)); - int *new_hash = alloca (FRAME_LINES (frame) * sizeof (int)); - int *draw_cost = alloca (FRAME_LINES (frame) * sizeof (int)); - int *old_draw_cost = alloca (FRAME_LINES (frame) * sizeof (int)); - register int i; - int free_at_end_vpos = FRAME_LINES (frame); + int i; + int height = FRAME_TOTAL_LINES (frame); + int free_at_end_vpos = height; struct glyph_matrix *current_matrix = frame->current_matrix; struct glyph_matrix *desired_matrix = frame->desired_matrix; + verify (sizeof (int) <= sizeof (unsigned)); + verify (alignof (unsigned) % alignof (int) == 0); + unsigned *old_hash; + USE_SAFE_ALLOCA; + SAFE_NALLOCA (old_hash, 4, height); + unsigned *new_hash = old_hash + height; + int *draw_cost = (int *) (new_hash + height); + int *old_draw_cost = draw_cost + height; eassert (current_matrix); @@ -4666,12 +4676,15 @@ scrolling (struct frame *frame) number of unchanged lines at the end. */ changed_lines = 0; unchanged_at_top = 0; - unchanged_at_bottom = FRAME_LINES (frame); - for (i = 0; i < FRAME_LINES (frame); i++) + unchanged_at_bottom = height; + for (i = 0; i < height; i++) { /* Give up on this scrolling if some old lines are not enabled. */ if (!MATRIX_ROW_ENABLED_P (current_matrix, i)) - return 0; + { + SAFE_FREE (); + return false; + } old_hash[i] = line_hash_code (frame, MATRIX_ROW (current_matrix, i)); if (! MATRIX_ROW_ENABLED_P (desired_matrix, i)) { @@ -4689,7 +4702,7 @@ scrolling (struct frame *frame) if (old_hash[i] != new_hash[i]) { changed_lines++; - unchanged_at_bottom = FRAME_LINES (frame) - i - 1; + unchanged_at_bottom = height - i - 1; } else if (i == unchanged_at_top) unchanged_at_top++; @@ -4699,10 +4712,13 @@ scrolling (struct frame *frame) /* If changed lines are few, don't allow preemption, don't scroll. */ if ((!FRAME_SCROLL_REGION_OK (frame) && changed_lines < baud_rate / 2400) - || unchanged_at_bottom == FRAME_LINES (frame)) - return 1; + || unchanged_at_bottom == height) + { + SAFE_FREE (); + return true; + } - window_size = (FRAME_LINES (frame) - unchanged_at_top + window_size = (height - unchanged_at_top - unchanged_at_bottom); if (FRAME_SCROLL_REGION_OK (frame)) @@ -4710,27 +4726,25 @@ scrolling (struct frame *frame) else if (FRAME_MEMORY_BELOW_FRAME (frame)) free_at_end_vpos = -1; - /* If large window, fast terminal and few lines in common between - current frame and desired frame, don't bother with i/d calc. */ - if (!FRAME_SCROLL_REGION_OK (frame) - && window_size >= 18 && baud_rate > 2400 - && (window_size >= - 10 * scrolling_max_lines_saved (unchanged_at_top, - FRAME_LINES (frame) - unchanged_at_bottom, - old_hash, new_hash, draw_cost))) - return 0; - - if (window_size < 2) - return 0; - - scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, - draw_cost + unchanged_at_top - 1, - old_draw_cost + unchanged_at_top - 1, - old_hash + unchanged_at_top - 1, - new_hash + unchanged_at_top - 1, - free_at_end_vpos - unchanged_at_top); - - return 0; + /* Do id/calc only if small window, or slow terminal, or many lines + in common between current frame and desired frame. But the + window size must be at least 2. */ + if ((FRAME_SCROLL_REGION_OK (frame) + || window_size < 18 || baud_rate <= 2400 + || (window_size + < 10 * scrolling_max_lines_saved (unchanged_at_top, + height - unchanged_at_bottom, + old_hash, new_hash, draw_cost))) + && 2 <= window_size) + scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, + draw_cost + unchanged_at_top - 1, + old_draw_cost + unchanged_at_top - 1, + old_hash + unchanged_at_top - 1, + new_hash + unchanged_at_top - 1, + free_at_end_vpos - unchanged_at_top); + + SAFE_FREE (); + return false; } @@ -5435,7 +5449,9 @@ handle_window_change_signal (int sig) /* Record the new sizes, but don't reallocate the data structures now. Let that be done later outside of the signal handler. */ - change_frame_size (XFRAME (frame), width, height, 0, 1, 0, 0); + change_frame_size (XFRAME (frame), width, + height - FRAME_MENU_BAR_LINES (XFRAME (frame)), + 0, 1, 0, 0); } } } @@ -5476,52 +5492,11 @@ do_pending_window_change (bool safe) } } -/* Change the frame height and/or width. Values may be given as zero to - indicate no change is to take place. - - new_height and new_width refer to the text portion of the frame. It - doesn't matter for new_height, since text and total portion are the - same in that case. But new_width must be enlarged to get the total - width of the frame. - - If DELAY, assume we're being called from a signal handler, and - queue the change for later - perhaps the next redisplay. - Since this tries to resize windows, we can't call it - from a signal handler. - - SAFE means this function is called from a place where it's - safe to change frame sizes while a redisplay is in progress. */ - -void -change_frame_size (struct frame *f, int new_width, int new_height, - bool pretend, bool delay, bool safe, bool pixelwise) -{ - Lisp_Object tail, frame; - - if (FRAME_MSDOS_P (f)) - { - /* On MS-DOS, all frames use the same screen, so a change in - size affects all frames. Termcap now supports multiple - ttys. */ - FOR_EACH_FRAME (tail, frame) - if (! FRAME_WINDOW_P (XFRAME (frame))) - change_frame_size_1 (XFRAME (frame), new_width, new_height, - pretend, delay, safe, pixelwise); - } - else - change_frame_size_1 (f, new_width, new_height, pretend, delay, safe, - pixelwise); -} static void change_frame_size_1 (struct frame *f, int new_width, int new_height, bool pretend, bool delay, bool safe, bool pixelwise) { - int new_text_width, new_text_height, new_root_width; - int old_root_width = WINDOW_PIXEL_WIDTH (XWINDOW (FRAME_ROOT_WINDOW (f))); - int new_cols, new_lines; - ptrdiff_t count = SPECPDL_INDEX (); - /* If we can't deal with the change now, queue it for later. */ if (delay || (redisplaying_p && !safe)) { @@ -5529,125 +5504,63 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height, f->new_height = new_height; f->new_pixelwise = pixelwise; delayed_size_change = 1; - return; - } - - /* This size-change overrides any pending one for this frame. */ - f->new_height = 0; - f->new_width = 0; - f->new_pixelwise = 0; - - /* If an argument is zero, set it to the current value. */ - if (pixelwise) - { - new_text_width = (new_width == 0) ? FRAME_TEXT_WIDTH (f) : new_width; - new_text_height = (new_height == 0) ? FRAME_TEXT_HEIGHT (f) : new_height; } else { - new_cols = (new_width == 0) ? FRAME_COLS (f) : new_width; - new_lines = (new_height == 0) ? FRAME_LINES (f) : new_height; - new_text_width = new_cols * FRAME_COLUMN_WIDTH (f); - new_text_height = new_lines * FRAME_LINE_HEIGHT (f); - } - - /* Compute width of windows in F. */ - /* Round up to the smallest acceptable size. */ - check_frame_size (f, &new_text_width, &new_text_height, 1); - /* Recompute the dimensions in character units, since - check_frame_size might have changed the pixel dimensions. */ - /* Consider rounding here: Currently, the root window can be - larger than the frame in terms of columns/lines. */ - new_cols = new_text_width / FRAME_COLUMN_WIDTH (f); - new_lines = new_text_height / FRAME_LINE_HEIGHT (f); - - /* This is the width of the frame without vertical scroll bars and - fringe columns. Do this after rounding - see discussion of - bug#9723. */ - new_root_width = (new_text_width - + FRAME_SCROLL_BAR_AREA_WIDTH (f) - + FRAME_TOTAL_FRINGE_WIDTH (f)); - /* If we're not changing the frame size, quit now. */ - /* Frame width may be unchanged but the text portion may change, for - example, fullscreen and remove/add scroll bar. */ - if (new_text_height == FRAME_TEXT_HEIGHT (f) - && new_text_width == FRAME_TEXT_WIDTH (f) - && new_root_width == old_root_width - && (FRAME_PIXEL_HEIGHT (f) == - FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height)) - && (FRAME_PIXEL_WIDTH (f) == - FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width))) - return; + /* This size-change overrides any pending one for this frame. */ + f->new_height = 0; + f->new_width = 0; + f->new_pixelwise = 0; - block_input (); - -#ifdef MSDOS - /* We only can set screen dimensions to certain values supported - by our video hardware. Try to find the smallest size greater - or equal to the requested dimensions. */ - dos_set_window_size (&new_lines, &new_cols); -#endif - - if (new_text_height != FRAME_TEXT_HEIGHT (f)) - { - resize_frame_windows (f, new_text_height, 0, 1); - - /* MSDOS frames cannot PRETEND, as they change frame size by - manipulating video hardware. */ - if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) - FrameRows (FRAME_TTY (f)) = new_lines; - } - - if (new_text_width != FRAME_TEXT_WIDTH (f) - || new_root_width != old_root_width) - { - resize_frame_windows (f, new_root_width, 1, 1); - - /* MSDOS frames cannot PRETEND, as they change frame size by - manipulating video hardware. */ - if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) - FrameCols (FRAME_TTY (f)) = new_cols; - -#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) - if (WINDOWP (f->tool_bar_window)) + /* If an argument is zero, set it to the current value. */ + if (pixelwise) { - XWINDOW (f->tool_bar_window)->total_cols = new_cols; - XWINDOW (f->tool_bar_window)->pixel_width = new_root_width; + new_width = (new_width <= 0) ? FRAME_TEXT_WIDTH (f) : new_width; + new_height = (new_height <= 0) ? FRAME_TEXT_HEIGHT (f) : new_height; + } + else + { + new_width = (((new_width <= 0) ? FRAME_COLS (f) : new_width) + * FRAME_COLUMN_WIDTH (f)); + new_height = (((new_height <= 0) ? FRAME_LINES (f) : new_height) + * FRAME_LINE_HEIGHT (f)); } -#endif - } - - SET_FRAME_COLS (f, new_cols); - FRAME_LINES (f) = new_lines; - FRAME_TEXT_WIDTH (f) = new_text_width; - FRAME_TEXT_HEIGHT (f) = new_text_height; - FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width); - FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height); - { - struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); - int text_area_x, text_area_y, text_area_width, text_area_height; - - window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width, - &text_area_height); - if (w->cursor.x >= text_area_x + text_area_width) - w->cursor.hpos = w->cursor.x = 0; - if (w->cursor.y >= text_area_y + text_area_height) - w->cursor.vpos = w->cursor.y = 0; - } + /* Adjust frame size but make sure x_set_window_size does not + get called. */ + adjust_frame_size (f, new_width, new_height, 5, pretend); + } +} - adjust_frame_glyphs (f); - calculate_costs (f); - SET_FRAME_GARBAGED (f); - f->resized_p = 1; - unblock_input (); +/* Change text height/width of frame F. Values may be given as zero to + indicate that no change is needed. - record_unwind_current_buffer (); + If DELAY, assume we're being called from a signal handler, and queue + the change for later - perhaps the next redisplay. Since this tries + to resize windows, we can't call it from a signal handler. - run_window_configuration_change_hook (f); + SAFE means this function is called from a place where it's safe to + change frame sizes while a redisplay is in progress. */ +void +change_frame_size (struct frame *f, int new_width, int new_height, + bool pretend, bool delay, bool safe, bool pixelwise) +{ + Lisp_Object tail, frame; - unbind_to (count, Qnil); + if (FRAME_MSDOS_P (f)) + { + /* On MS-DOS, all frames use the same screen, so a change in + size affects all frames. Termcap now supports multiple + ttys. */ + FOR_EACH_FRAME (tail, frame) + if (! FRAME_WINDOW_P (XFRAME (frame))) + change_frame_size_1 (XFRAME (frame), new_width, new_height, + pretend, delay, safe, pixelwise); + } + else + change_frame_size_1 (f, new_width, new_height, pretend, delay, safe, + pixelwise); } /*********************************************************************** @@ -5698,16 +5611,13 @@ the currently selected frame. In batch mode, STRING is sent to stdout when TERMINAL is nil. */) (Lisp_Object string, Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_live_terminal (terminal); FILE *out; /* ??? Perhaps we should do something special for multibyte strings here. */ CHECK_STRING (string); block_input (); - if (!t) - error ("Unknown terminal device"); - if (t->type == output_initial) out = stdout; else if (t->type != output_termcap && t->type != output_msdos_raw) @@ -6178,7 +6088,8 @@ init_display (void) t->display_info.tty->top_frame = selected_frame; change_frame_size (XFRAME (selected_frame), FrameCols (t->display_info.tty), - FrameRows (t->display_info.tty), 0, 0, 1, 0); + FrameRows (t->display_info.tty) + - FRAME_MENU_BAR_LINES (f), 0, 0, 1, 0); /* Delete the initial terminal. */ if (--initial_terminal->reference_count == 0 @@ -6186,21 +6097,18 @@ init_display (void) (*initial_terminal->delete_terminal_hook) (initial_terminal); /* Update frame parameters to reflect the new type. */ - Fmodify_frame_parameters - (selected_frame, list1 (Fcons (Qtty_type, - Ftty_type (selected_frame)))); - if (t->display_info.tty->name) - Fmodify_frame_parameters - (selected_frame, - list1 (Fcons (Qtty, build_string (t->display_info.tty->name)))); - else - Fmodify_frame_parameters (selected_frame, list1 (Fcons (Qtty, Qnil))); + AUTO_FRAME_ARG (tty_type_arg, Qtty_type, Ftty_type (selected_frame)); + Fmodify_frame_parameters (selected_frame, tty_type_arg); + AUTO_FRAME_ARG (tty_arg, Qtty, (t->display_info.tty->name + ? build_string (t->display_info.tty->name) + : Qnil)); + Fmodify_frame_parameters (selected_frame, tty_arg); } { struct frame *sf = SELECTED_FRAME (); int width = FRAME_TOTAL_COLS (sf); - int height = FRAME_LINES (sf); + int height = FRAME_TOTAL_LINES (sf); /* If these sizes are so big they cause overflow, just ignore the change. It's not clear what better we could do. The rest of diff --git a/src/doc.c b/src/doc.c index b6a4cd0a27b..1b87c23e949 100644 --- a/src/doc.c +++ b/src/doc.c @@ -121,8 +121,8 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) if (minsize < 8) minsize = 8; name = SAFE_ALLOCA (minsize + SCHARS (file) + 8); - strcpy (name, SSDATA (docdir)); - strcat (name, SSDATA (file)); + char *z = lispstpcpy (name, docdir); + strcpy (z, SSDATA (file)); } else { @@ -146,8 +146,9 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) if (fd < 0) { SAFE_FREE (); - return concat3 (build_string ("Cannot open doc string file \""), - file, build_string ("\"\n")); + AUTO_STRING (cannot_open, "Cannot open doc string file \""); + AUTO_STRING (quote_nl, "\"\n"); + return concat3 (cannot_open, file, quote_nl); } } count = SPECPDL_INDEX (); @@ -561,6 +562,8 @@ the same file name is found in the `doc-directory'. */) char *p, *name; bool skip_file = 0; ptrdiff_t count; + char const *dirname; + ptrdiff_t dirlen; /* Preloaded defcustoms using custom-initialize-delay are added to this list, but kept unbound. See http://debbugs.gnu.org/11565 */ Lisp_Object delayed_init = @@ -577,15 +580,21 @@ the same file name is found in the `doc-directory'. */) (0) #endif /* CANNOT_DUMP */ { - name = alloca (SCHARS (filename) + 14); - strcpy (name, "../etc/"); + static char const sibling_etc[] = "../etc/"; + dirname = sibling_etc; + dirlen = sizeof sibling_etc - 1; } else { CHECK_STRING (Vdoc_directory); - name = alloca (SCHARS (filename) + SCHARS (Vdoc_directory) + 1); - strcpy (name, SSDATA (Vdoc_directory)); + dirname = SSDATA (Vdoc_directory); + dirlen = SBYTES (Vdoc_directory); } + + count = SPECPDL_INDEX (); + USE_SAFE_ALLOCA; + name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1); + strcpy (name, dirname); strcat (name, SSDATA (filename)); /*** Add this line ***/ /* Vbuild_files is nil when temacs is run, and non-nil after that. */ @@ -595,7 +604,7 @@ the same file name is found in the `doc-directory'. */) { #include "buildobj.h" }; - int i = sizeof buildobj / sizeof *buildobj; + int i = ARRAYELTS (buildobj); while (0 <= --i) Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files); Vbuild_files = Fpurecopy (Vbuild_files); @@ -608,7 +617,6 @@ the same file name is found in the `doc-directory'. */) report_file_errno ("Opening doc string file", build_string (name), open_errno); } - count = SPECPDL_INDEX (); record_unwind_protect_int (close_file_unwind, fd); Vdoc_file_name = filename; filled = 0; @@ -637,7 +645,7 @@ the same file name is found in the `doc-directory'. */) && (end[-1] == 'o' || end[-1] == 'c')) { ptrdiff_t len = end - p - 2; - char *fromfile = alloca (len + 1); + char *fromfile = SAFE_ALLOCA (len + 1); memcpy (fromfile, &p[2], len); fromfile[len] = 0; if (fromfile[len-1] == 'c') @@ -688,6 +696,8 @@ the same file name is found in the `doc-directory'. */) filled -= end - buf; memmove (buf, end, filled); } + + SAFE_FREE (); return unbind_to (count, Qnil); } diff --git a/src/dosfns.c b/src/dosfns.c index 071d73ea16e..bdd296bf658 100644 --- a/src/dosfns.c +++ b/src/dosfns.c @@ -370,13 +370,6 @@ init_dosfns (void) Don't OR it with the previous value, so the value recorded at dump time, possibly with `preserve-case' flags set, won't get through. */ __opendir_flags = __OPENDIR_FIND_HIDDEN; - -#if __DJGPP_MINOR__ == 0 - /* Under LFN, preserve the case of files as recorded in the directory - (in DJGPP 2.01 and later this is automagically done by the library). */ - if (!NILP (Fmsdos_long_file_names ())) - __opendir_flags |= __OPENDIR_PRESERVE_CASE; -#endif /* __DJGPP_MINOR__ == 0 */ } #ifndef HAVE_X_WINDOWS @@ -402,7 +395,7 @@ msdos_stdcolor_idx (const char *name) { int i; - for (i = 0; i < sizeof (vga_colors) / sizeof (vga_colors[0]); i++) + for (i = 0; i < ARRAYELTS (vga_colors); i++) if (xstrcasecmp (name, vga_colors[i]) == 0) return i; @@ -422,7 +415,7 @@ msdos_stdcolor_name (int idx) return build_string (unspecified_fg); else if (idx == FACE_TTY_DEFAULT_BG_COLOR) return build_string (unspecified_bg); - else if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0])) + else if (idx >= 0 && idx < ARRAYELTS (vga_colors)) return build_string (vga_colors[idx]); else return Qunspecified; /* meaning the default */ @@ -641,6 +634,48 @@ system_process_attributes (Lisp_Object pid) return attrs; } +/* Support for memory-info. */ +int +dos_memory_info (unsigned long *totalram, unsigned long *freeram, + unsigned long *totalswap, unsigned long *freeswap) +{ + _go32_dpmi_meminfo info; + unsigned long mem1, mem2, freemem; + + _go32_dpmi_get_free_memory_information (&info); + /* DPMI server of Windows NT and its descendants reports in + info.available_memory a much lower amount that is really + available, which causes bogus "past 95% of memory limit" + warnings. Try to overcome that via circumstantial evidence. */ + mem1 = info.available_memory; + mem2 = info.available_physical_pages; + /* DPMI Spec: "Fields that are unavailable will hold -1." */ + if ((long)mem1 == -1L) + mem1 = 0; + if ((long)mem2 == -1L) + mem2 = 0; + else + mem2 *= 4096; + /* Surely, the available memory is at least what we have physically + available, right? */ + if (mem1 >= mem2) + freemem = mem1; + else + freemem = mem2; + *freeram = freemem; + *totalswap = + ((long)info.max_pages_in_paging_file == -1L) + ? 0 + : info.max_pages_in_paging_file * 4096; + *totalram = + ((long)info.total_physical_pages == -1L) + ? (freemem + (unsigned long)sbrk (0) + *totalswap) + : info.total_physical_pages * 4096; + *freeswap = 0; + return 0; +} + + void dos_cleanup (void) { diff --git a/src/dosfns.h b/src/dosfns.h index 3409b2247b7..f32e6342fc9 100644 --- a/src/dosfns.h +++ b/src/dosfns.h @@ -22,7 +22,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define DOS_COUNTRY_INFO 34 /* no of bytes returned by dos int 38h */ extern unsigned char dos_country_info[DOS_COUNTRY_INFO]; - +extern int dos_memory_info (unsigned long *, unsigned long *, + unsigned long *, unsigned long *); #ifndef HAVE_X_WINDOWS extern int msdos_stdcolor_idx (const char *); extern Lisp_Object msdos_stdcolor_name (int); diff --git a/src/editfns.c b/src/editfns.c index 9c1fcb0b790..376d8e3a0ea 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -64,11 +64,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ extern Lisp_Object w32_get_internal_run_time (void); #endif +static void set_time_zone_rule (char const *); static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec, bool, struct tm *); +static long int tm_gmtoff (struct tm *); static int tm_diff (struct tm *, struct tm *); static void update_buffer_properties (ptrdiff_t, ptrdiff_t); +#ifndef HAVE_TM_GMTOFF +# define HAVE_TM_GMTOFF false +#endif + static Lisp_Object Qbuffer_access_fontify_functions; /* Symbol for the text property used to mark fields. */ @@ -79,15 +85,12 @@ Lisp_Object Qfield; static Lisp_Object Qboundary; -/* The startup value of the TZ environment variable so it can be - restored if the user calls set-time-zone-rule with a nil - argument. If null, the TZ environment variable was unset. */ +/* The startup value of the TZ environment variable; null if unset. */ static char const *initial_tz; -/* True if the static variable tzvalbuf (defined in - set_time_zone_rule) is part of 'environ'. */ -static bool tzvalbuf_in_environ; - +/* A valid but unlikely setting for the TZ environment variable. + It is OK (though a bit slower) if the user chooses this value. */ +static char dump_tz_string[] = "TZ=UtC0"; void init_editfns (void) @@ -101,18 +104,43 @@ init_editfns (void) init_system_name (); #ifndef CANNOT_DUMP - /* Don't bother with this on initial start when just dumping out */ + /* When just dumping out, set the time zone to a known unlikely value + and skip the rest of this function. */ if (!initialized) - return; -#endif /* not CANNOT_DUMP */ + { +# ifdef HAVE_TZSET + xputenv (dump_tz_string); + tzset (); +# endif + return; + } +#endif - initial_tz = getenv ("TZ"); - tzvalbuf_in_environ = 0; + char *tz = getenv ("TZ"); + initial_tz = tz; + +#if !defined CANNOT_DUMP && defined HAVE_TZSET + /* If the execution TZ happens to be the same as the dump TZ, + change it to some other value and then change it back, + to force the underlying implementation to reload the TZ info. + This is needed on implementations that load TZ info from files, + since the TZ file contents may differ between dump and execution. */ + if (tz && strcmp (tz, &dump_tz_string[sizeof "TZ=" - 1]) == 0) + { + ++*tz; + tzset (); + --*tz; + } +#endif + + /* Call set_time_zone_rule now, so that its call to putenv is done + before multiple threads are active. */ + set_time_zone_rule (tz); pw = getpwuid (getuid ()); #ifdef MSDOS /* We let the real user name default to "root" because that's quite - accurate on MSDOG and because it lets Emacs find the init file. + accurate on MS-DOS and because it lets Emacs find the init file. (The DVX libraries override the Djgpp libraries here.) */ Vuser_real_login_name = build_string (pw ? pw->pw_name : "root"); #else @@ -376,13 +404,14 @@ at POSITION. */) set_buffer_temp (XBUFFER (object)); /* First try with room for 40 overlays. */ - noverlays = 40; - overlay_vec = alloca (noverlays * sizeof *overlay_vec); + Lisp_Object overlay_vecbuf[40]; + noverlays = ARRAYELTS (overlay_vecbuf); + overlay_vec = overlay_vecbuf; noverlays = overlays_around (posn, overlay_vec, noverlays); /* If there are more than 40, make enough space for all, and try again. */ - if (noverlays > 40) + if (ARRAYELTS (overlay_vecbuf) < noverlays) { SAFE_ALLOCA_LISP (overlay_vec, noverlays); noverlays = overlays_around (posn, overlay_vec, noverlays); @@ -758,26 +787,17 @@ boundaries, bind `inhibit-field-text-motion' to t. This function does not move point. */) (Lisp_Object n) { - ptrdiff_t orig, orig_byte, end; - ptrdiff_t count = SPECPDL_INDEX (); - specbind (Qinhibit_point_motion_hooks, Qt); + ptrdiff_t charpos, bytepos; if (NILP (n)) XSETFASTINT (n, 1); else CHECK_NUMBER (n); - orig = PT; - orig_byte = PT_BYTE; - Fforward_line (make_number (XINT (n) - 1)); - end = PT; - - SET_PT_BOTH (orig, orig_byte); - - unbind_to (count, Qnil); + scan_newline_from_point (XINT (n) - 1, &charpos, &bytepos); /* Return END constrained to the current input field. */ - return Fconstrain_to_field (make_number (end), make_number (orig), + return Fconstrain_to_field (make_number (charpos), make_number (PT), XINT (n) != 1 ? Qt : Qnil, Qt, Qnil); } @@ -1325,17 +1345,16 @@ name, or nil if there is no such user. */) /* Substitute the login name for the &, upcasing the first character. */ if (q) { - register char *r; - Lisp_Object login; - - login = Fuser_login_name (make_number (pw->pw_uid)); - r = alloca (strlen (p) + SCHARS (login) + 1); + Lisp_Object login = Fuser_login_name (make_number (pw->pw_uid)); + USE_SAFE_ALLOCA; + char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1); memcpy (r, p, q - p); r[q - p] = 0; strcat (r, SSDATA (login)); r[q - p] = upcase ((unsigned char) r[q - p]); strcat (r, q + 1); full = build_string (r); + SAFE_FREE (); } #endif /* AMPERSAND_FULL_NAME */ @@ -1373,6 +1392,30 @@ time_overflow (void) error ("Specified time is not representable"); } +/* A substitute for mktime_z on platforms that lack it. It's not + thread-safe, but should be good enough for Emacs in typical use. */ +#ifndef HAVE_TZALLOC +time_t +mktime_z (timezone_t tz, struct tm *tm) +{ + char *oldtz = getenv ("TZ"); + USE_SAFE_ALLOCA; + if (oldtz) + { + size_t oldtzsize = strlen (oldtz) + 1; + char *oldtzcopy = SAFE_ALLOCA (oldtzsize); + oldtz = strcpy (oldtzcopy, oldtz); + } + block_input (); + set_time_zone_rule (tz); + time_t t = mktime (tm); + set_time_zone_rule (oldtz); + unblock_input (); + SAFE_FREE (); + return t; +} +#endif + /* Return the upper part of the time T (everything but the bottom 16 bits). */ static EMACS_INT hi_time (time_t t) @@ -1516,7 +1559,8 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh, list, generate the corresponding time value. If RESULT is not null, store into *RESULT the converted time; - this can fail if the converted time does not fit into struct timespec. + if the converted time does not fit into struct timespec, + store an invalid timespec to indicate the overflow. If *DRESULT is not null, store into *DRESULT the number of seconds since the start of the POSIX Epoch. @@ -1529,7 +1573,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, EMACS_INT hi, lo, us, ps; if (! (INTEGERP (high) && INTEGERP (low) && INTEGERP (usec) && INTEGERP (psec))) - return 0; + return false; hi = XINT (high); lo = XINT (low); us = XINT (usec); @@ -1555,16 +1599,13 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, *result = make_timespec ((sec << 16) + lo, us * 1000 + ps / 1000); } else - { - /* Overflow in the highest-order component. */ - return 0; - } + *result = invalid_timespec (); } if (dresult) *dresult = (us * 1e6 + ps) / 1e12 + lo + hi * 65536.0; - return 1; + return true; } /* Decode a Lisp list SPECIFIED_TIME that represents a time. @@ -1576,22 +1617,23 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, struct timespec lisp_time_argument (Lisp_Object specified_time) { - struct timespec t; if (NILP (specified_time)) - t = current_timespec (); + return current_timespec (); else { Lisp_Object high, low, usec, psec; + struct timespec t; if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) && decode_time_components (high, low, usec, psec, &t, 0))) error ("Invalid time specification"); + if (! timespec_valid_p (t)) + time_overflow (); + return t; } - return t; } /* Like lisp_time_argument, except decode only the seconds part, - do not allow out-of-range time stamps, do not check the subseconds part, - and always round down. */ + and do not check the subseconds part. */ static time_t lisp_seconds_argument (Lisp_Object specified_time) { @@ -1605,6 +1647,8 @@ lisp_seconds_argument (Lisp_Object specified_time) && decode_time_components (high, low, make_number (0), make_number (0), &t, 0))) error ("Invalid time specification"); + if (! timespec_valid_p (t)) + time_overflow (); return t.tv_sec; } } @@ -1767,39 +1811,28 @@ format_time_string (char const *format, ptrdiff_t formatlen, size_t len; Lisp_Object bufstring; int ns = t.tv_nsec; - struct tm *tm; USE_SAFE_ALLOCA; - while (1) - { - time_t *taddr = &t.tv_sec; - block_input (); - - synchronize_system_time_locale (); - - tm = ut ? gmtime (taddr) : localtime (taddr); - if (! tm) - { - unblock_input (); - time_overflow (); - } - *tmp = *tm; + tmp = ut ? gmtime_r (&t.tv_sec, tmp) : localtime_r (&t.tv_sec, tmp); + if (! tmp) + time_overflow (); + synchronize_system_time_locale (); + while (true) + { buf[0] = '\1'; - len = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns); + len = emacs_nmemftime (buf, size, format, formatlen, tmp, ut, ns); if ((0 < len && len < size) || (len == 0 && buf[0] == '\0')) break; /* Buffer was too small, so make it bigger and try again. */ - len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tm, ut, ns); - unblock_input (); + len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tmp, ut, ns); if (STRING_BYTES_BOUND <= len) string_overflow (); size = len + 1; buf = SAFE_ALLOCA (size); } - unblock_input (); bufstring = make_unibyte_string (buf, len); SAFE_FREE (); return code_convert_string_norecord (bufstring, Vlocale_coding_system, 0); @@ -1823,38 +1856,30 @@ DOW and ZONE.) */) (Lisp_Object specified_time) { time_t time_spec = lisp_seconds_argument (specified_time); - struct tm save_tm; - struct tm *decoded_time; - Lisp_Object list_args[9]; + struct tm local_tm, gmt_tm; - block_input (); - decoded_time = localtime (&time_spec); - if (decoded_time) - save_tm = *decoded_time; - unblock_input (); - if (! (decoded_time - && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= save_tm.tm_year - && save_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)) + if (! (localtime_r (&time_spec, &local_tm) + && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year + && local_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)) time_overflow (); - XSETFASTINT (list_args[0], save_tm.tm_sec); - XSETFASTINT (list_args[1], save_tm.tm_min); - XSETFASTINT (list_args[2], save_tm.tm_hour); - XSETFASTINT (list_args[3], save_tm.tm_mday); - XSETFASTINT (list_args[4], save_tm.tm_mon + 1); - /* On 64-bit machines an int is narrower than EMACS_INT, thus the - cast below avoids overflow in int arithmetics. */ - XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) save_tm.tm_year); - XSETFASTINT (list_args[6], save_tm.tm_wday); - list_args[7] = save_tm.tm_isdst ? Qt : Qnil; - block_input (); - decoded_time = gmtime (&time_spec); - if (decoded_time == 0) - list_args[8] = Qnil; - else - XSETINT (list_args[8], tm_diff (&save_tm, decoded_time)); - unblock_input (); - return Flist (9, list_args); + /* Avoid overflow when INT_MAX < EMACS_INT_MAX. */ + EMACS_INT tm_year_base = TM_YEAR_BASE; + + return Flist (9, ((Lisp_Object []) + {make_number (local_tm.tm_sec), + make_number (local_tm.tm_min), + make_number (local_tm.tm_hour), + make_number (local_tm.tm_mday), + make_number (local_tm.tm_mon + 1), + make_number (local_tm.tm_year + tm_year_base), + make_number (local_tm.tm_wday), + local_tm.tm_isdst ? Qt : Qnil, + (HAVE_TM_GMTOFF + ? make_number (tm_gmtoff (&local_tm)) + : gmtime_r (&time_spec, &gmt_tm) + ? make_number (tm_diff (&local_tm, &gmt_tm)) + : Qnil)})); } /* Return OBJ - OFFSET, checking that OBJ is a valid fixnum and that @@ -1910,18 +1935,12 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) if (CONSP (zone)) zone = XCAR (zone); if (NILP (zone)) - { - block_input (); - value = mktime (&tm); - unblock_input (); - } + value = mktime (&tm); else { static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d"; char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)]; - char *old_tzstring; const char *tzstring; - USE_SAFE_ALLOCA; if (EQ (zone, Qt)) tzstring = "UTC0"; @@ -1938,29 +1957,13 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) tzstring = tzbuf; } else - error ("Invalid time zone specification"); - - old_tzstring = getenv ("TZ"); - if (old_tzstring) - { - char *buf = SAFE_ALLOCA (strlen (old_tzstring) + 1); - old_tzstring = strcpy (buf, old_tzstring); - } + tzstring = 0; - block_input (); - - /* Set TZ before calling mktime; merely adjusting mktime's returned - value doesn't suffice, since that would mishandle leap seconds. */ - set_time_zone_rule (tzstring); - - value = mktime (&tm); - - set_time_zone_rule (old_tzstring); -#ifdef LOCALTIME_CACHE - tzset (); -#endif - unblock_input (); - SAFE_FREE (); + timezone_t tz = tzstring ? tzalloc (tzstring) : 0; + if (! tz) + error ("Invalid time zone specification"); + value = mktime_z (tz, &tm); + tzfree (tz); } if (value == (time_t) -1) @@ -1986,34 +1989,27 @@ but this is considered obsolete. */) (Lisp_Object specified_time) { time_t value = lisp_seconds_argument (specified_time); - struct tm *tm; - char buf[sizeof "Mon Apr 30 12:49:17 " + INT_STRLEN_BOUND (int) + 1]; - int len IF_LINT (= 0); /* Convert to a string in ctime format, except without the trailing newline, and without the 4-digit year limit. Don't use asctime or ctime, as they might dump core if the year is outside the range -999 .. 9999. */ - block_input (); - tm = localtime (&value); - if (tm) - { - static char const wday_name[][4] = - { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - static char const mon_name[][4] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - printmax_t year_base = TM_YEAR_BASE; - - len = sprintf (buf, "%s %s%3d %02d:%02d:%02d %"pMd, - wday_name[tm->tm_wday], mon_name[tm->tm_mon], tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, - tm->tm_year + year_base); - } - unblock_input (); - if (! tm) + struct tm tm; + if (! localtime_r (&value, &tm)) time_overflow (); + static char const wday_name[][4] = + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + static char const mon_name[][4] = + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + printmax_t year_base = TM_YEAR_BASE; + char buf[sizeof "Mon Apr 30 12:49:17 " + INT_STRLEN_BOUND (int) + 1]; + int len = sprintf (buf, "%s %s%3d %02d:%02d:%02d %"pMd, + wday_name[tm.tm_wday], mon_name[tm.tm_mon], tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + year_base); + return make_unibyte_string (buf, len); } @@ -2040,6 +2036,17 @@ tm_diff (struct tm *a, struct tm *b) + (a->tm_sec - b->tm_sec)); } +/* Yield A's UTC offset, or an unspecified value if unknown. */ +static long int +tm_gmtoff (struct tm *a) +{ +#if HAVE_TM_GMTOFF + return a->tm_gmtoff; +#else + return 0; +#endif +} + DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0, doc: /* Return the offset and name for the local time zone. This returns a list of the form (OFFSET NAME). @@ -2058,32 +2065,30 @@ the data it can't find. */) (Lisp_Object specified_time) { struct timespec value; - int offset; - struct tm *t; - struct tm localtm; + struct tm local_tm, gmt_tm; Lisp_Object zone_offset, zone_name; zone_offset = Qnil; value = make_timespec (lisp_seconds_argument (specified_time), 0); - zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value, 0, &localtm); - block_input (); - t = gmtime (&value.tv_sec); - if (t) - offset = tm_diff (&localtm, t); - unblock_input (); + zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value, 0, &local_tm); - if (t) + if (HAVE_TM_GMTOFF || gmtime_r (&value.tv_sec, &gmt_tm)) { + long int offset = (HAVE_TM_GMTOFF + ? tm_gmtoff (&local_tm) + : tm_diff (&local_tm, &gmt_tm)); zone_offset = make_number (offset); if (SCHARS (zone_name) == 0) { /* No local time zone name is available; use "+-NNNN" instead. */ - int m = offset / 60; - int am = offset < 0 ? - m : m; - char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; - zone_name = make_formatted_string (buf, "%c%02d%02d", + long int m = offset / 60; + long int am = offset < 0 ? - m : m; + long int hour = am / 60; + int min = am % 60; + char buf[sizeof "+00" + INT_STRLEN_BOUND (long int)]; + zone_name = make_formatted_string (buf, "%c%02ld%02d", (offset < 0 ? '-' : '+'), - am / 60, am % 60); + hour, min); } } @@ -2122,12 +2127,12 @@ only the former. */) /* Set the local time zone rule to TZSTRING. - This function is not thread-safe, partly because putenv, unsetenv - and tzset are not, and partly because of the static storage it - updates. Other threads that invoke localtime etc. may be adversely - affected while this function is executing. */ + This function is not thread-safe, in theory because putenv is not, + but mostly because of the static storage it updates. Other threads + that invoke localtime etc. may be adversely affected while this + function is executing. */ -void +static void set_time_zone_rule (const char *tzstring) { /* A buffer holding a string of the form "TZ=value", intended @@ -2136,75 +2141,47 @@ set_time_zone_rule (const char *tzstring) static ptrdiff_t tzvalbufsize; int tzeqlen = sizeof "TZ=" - 1; + ptrdiff_t tzstringlen = tzstring ? strlen (tzstring) : 0; + char *tzval = tzvalbuf; + bool new_tzvalbuf = tzvalbufsize <= tzeqlen + tzstringlen; -#ifdef LOCALTIME_CACHE - /* These two values are known to load tz files in buggy implementations, - i.e., Solaris 1 executables running under either Solaris 1 or Solaris 2. - Their values shouldn't matter in non-buggy implementations. - We don't use string literals for these strings, - since if a string in the environment is in readonly - storage, it runs afoul of bugs in SVR4 and Solaris 2.3. - See Sun bugs 1113095 and 1114114, ``Timezone routines - improperly modify environment''. */ - - static char set_time_zone_rule_tz[][sizeof "TZ=GMT+0"] - = { "TZ=GMT+0", "TZ=GMT+1" }; - - /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like - "US/Pacific" that loads a tz file, then changes to a value like - "XXX0" that does not load a tz file, and then changes back to - its original value, the last change is (incorrectly) ignored. - Also, if TZ changes twice in succession to values that do - not load a tz file, tzset can dump core (see Sun bug#1225179). - The following code works around these bugs. */ + if (new_tzvalbuf) + { + /* Do not attempt to free the old tzvalbuf, since another thread + may be using it. In practice, the first allocation is large + enough and memory does not leak. */ + tzval = xpalloc (NULL, &tzvalbufsize, + tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1); + tzvalbuf = tzval; + tzval[1] = 'Z'; + tzval[2] = '='; + } if (tzstring) { - /* Temporarily set TZ to a value that loads a tz file - and that differs from tzstring. */ - bool eq0 = strcmp (tzstring, set_time_zone_rule_tz[0] + tzeqlen) == 0; - xputenv (set_time_zone_rule_tz[eq0]); + /* Modify TZVAL in place. Although this is dicey in a + multithreaded environment, we know of no portable alternative. + Calling putenv or setenv could crash some other thread. */ + tzval[0] = 'T'; + strcpy (tzval + tzeqlen, tzstring); } else { - /* The implied tzstring is unknown, so temporarily set TZ to - two different values that each load a tz file. */ - xputenv (set_time_zone_rule_tz[0]); - tzset (); - xputenv (set_time_zone_rule_tz[1]); + /* Turn 'TZ=whatever' into an empty environment variable 'tZ='. + Although this is also dicey, calling unsetenv here can crash Emacs. + See Bug#8705. */ + tzval[0] = 't'; + tzval[tzeqlen] = 0; } - tzset (); - tzvalbuf_in_environ = 0; -#endif - if (!tzstring) + if (new_tzvalbuf) { - unsetenv ("TZ"); - tzvalbuf_in_environ = 0; + /* Although this is not thread-safe, in practice this runs only + on startup when there is only one thread. */ + xputenv (tzval); } - else - { - ptrdiff_t tzstringlen = strlen (tzstring); - - if (tzvalbufsize <= tzeqlen + tzstringlen) - { - unsetenv ("TZ"); - tzvalbuf_in_environ = 0; - tzvalbuf = xpalloc (tzvalbuf, &tzvalbufsize, - tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1); - memcpy (tzvalbuf, "TZ=", tzeqlen); - } - - strcpy (tzvalbuf + tzeqlen, tzstring); - if (!tzvalbuf_in_environ) - { - xputenv (tzvalbuf); - tzvalbuf_in_environ = 1; - } - } - -#ifdef LOCALTIME_CACHE +#ifdef HAVE_TZSET tzset (); #endif } @@ -2238,7 +2215,7 @@ general_insert_function (void (*insert_func) len = CHAR_STRING (c, str); else { - str[0] = ASCII_CHAR_P (c) ? c : multibyte_char_to_unibyte (c); + str[0] = CHAR_TO_BYTE8 (c); len = 1; } (*insert_func) ((char *) str, len); @@ -2852,7 +2829,7 @@ Both characters must have the same length of multi-byte form. */) len = CHAR_STRING (fromc, fromstr); if (CHAR_STRING (toc, tostr) != len) error ("Characters in `subst-char-in-region' have different byte-lengths"); - if (!ASCII_BYTE_P (*tostr)) + if (!ASCII_CHAR_P (*tostr)) { /* If *TOSTR is in the range 0x80..0x9F and TOCHAR is not a complete multibyte character, it may be combined with the @@ -2945,7 +2922,7 @@ Both characters must have the same length of multi-byte form. */) : ((pos_byte_next < Z_BYTE && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte_next))) || (pos_byte > BEG_BYTE - && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))))) + && ! ASCII_CHAR_P (FETCH_BYTE (pos_byte - 1)))))) { Lisp_Object tem, string; @@ -3011,8 +2988,12 @@ static Lisp_Object check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end, Lisp_Object val) { - int buf_size = 16, buf_used = 0; - int *buf = alloca (sizeof (int) * buf_size); + int initial_buf[16]; + int *buf = initial_buf; + ptrdiff_t buf_size = ARRAYELTS (initial_buf); + int *bufalloc = 0; + ptrdiff_t buf_used = 0; + Lisp_Object result = Qnil; for (; CONSP (val); val = XCDR (val)) { @@ -3037,12 +3018,11 @@ check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end, if (buf_used == buf_size) { - int *newbuf; - - buf_size += 16; - newbuf = alloca (sizeof (int) * buf_size); - memcpy (newbuf, buf, sizeof (int) * buf_used); - buf = newbuf; + bufalloc = xpalloc (bufalloc, &buf_size, 1, -1, + sizeof *bufalloc); + if (buf == initial_buf) + memcpy (bufalloc, buf, sizeof initial_buf); + buf = bufalloc; } buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, len1); pos_byte += len1; @@ -3051,10 +3031,15 @@ check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end, break; } if (i == len) - return XCAR (val); + { + result = XCAR (val); + break; + } } } - return Qnil; + + xfree (bufalloc); + return result; } @@ -3126,7 +3111,7 @@ It returns the number of characters changed. */) else { nc = tt[oc]; - if (! ASCII_BYTE_P (nc) && multibyte) + if (! ASCII_CHAR_P (nc) && multibyte) { str_len = BYTE8_STRING (nc, buf); str = buf; @@ -3600,7 +3585,7 @@ specifier truncates the string to the given width. usage: (format STRING &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - ptrdiff_t n; /* The number of the next arg to substitute */ + ptrdiff_t n; /* The number of the next arg to substitute. */ char initial_buffer[4000]; char *buf = initial_buffer; ptrdiff_t bufsize = sizeof initial_buffer; @@ -3877,7 +3862,7 @@ usage: (format STRING &rest OBJECTS) */) if (p > buf && multibyte - && !ASCII_BYTE_P (*((unsigned char *) p - 1)) + && !ASCII_CHAR_P (*((unsigned char *) p - 1)) && STRING_MULTIBYTE (args[n]) && !CHAR_HEAD_P (SREF (args[n], 0))) maybe_combine_byte = 1; @@ -4167,7 +4152,7 @@ usage: (format STRING &rest OBJECTS) */) { /* Copy a whole multibyte character. */ if (p > buf - && !ASCII_BYTE_P (*((unsigned char *) p - 1)) + && !ASCII_CHAR_P (*((unsigned char *) p - 1)) && !CHAR_HEAD_P (*format)) maybe_combine_byte = 1; @@ -4181,7 +4166,7 @@ usage: (format STRING &rest OBJECTS) */) else { unsigned char uc = *format++; - if (! multibyte || ASCII_BYTE_P (uc)) + if (! multibyte || ASCII_CHAR_P (uc)) convbytes = 1; else { @@ -4353,11 +4338,8 @@ usage: (format STRING &rest OBJECTS) */) Lisp_Object format2 (const char *string1, Lisp_Object arg0, Lisp_Object arg1) { - Lisp_Object args[3]; - args[0] = build_string (string1); - args[1] = arg0; - args[2] = arg1; - return Fformat (3, args); + AUTO_STRING (format, string1); + return Fformat (3, (Lisp_Object []) {format, arg0, arg1}); } DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0, @@ -4616,11 +4598,11 @@ Transposing beyond buffer boundaries is an error. */) if (tmp_interval3) set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3); + USE_SAFE_ALLOCA; + /* First region smaller than second. */ if (len1_byte < len2_byte) { - USE_SAFE_ALLOCA; - temp = SAFE_ALLOCA (len2_byte); /* Don't precompute these addresses. We have to compute them @@ -4632,21 +4614,19 @@ Transposing beyond buffer boundaries is an error. */) memcpy (temp, start2_addr, len2_byte); memcpy (start1_addr + len2_byte, start1_addr, len1_byte); memcpy (start1_addr, temp, len2_byte); - SAFE_FREE (); } else /* First region not smaller than second. */ { - USE_SAFE_ALLOCA; - temp = SAFE_ALLOCA (len1_byte); start1_addr = BYTE_POS_ADDR (start1_byte); start2_addr = BYTE_POS_ADDR (start2_byte); memcpy (temp, start1_addr, len1_byte); memcpy (start1_addr, start2_addr, len2_byte); memcpy (start1_addr + len2_byte, temp, len1_byte); - SAFE_FREE (); } + + SAFE_FREE (); graft_intervals_into_buffer (tmp_interval1, start1 + len2, len1, current_buffer, 0); graft_intervals_into_buffer (tmp_interval2, start1, diff --git a/src/emacs.c b/src/emacs.c index fd93324de97..90182e53e70 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1,7 +1,7 @@ /* Fully extensible Emacs, running on Unix, intended for GNU. -Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2014 Free Software -Foundation, Inc. +Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2014 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -51,6 +51,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "cygw32.h" #endif +#ifdef MSDOS +#include <binary-io.h> +#endif + #ifdef HAVE_WINDOW_SYSTEM #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ @@ -79,7 +83,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "charset.h" #include "composite.h" #include "dispextern.h" +#include "regex.h" #include "syntax.h" +#include "sysselect.h" #include "systime.h" #ifdef HAVE_GNUTLS @@ -105,8 +111,9 @@ extern void moncontrol (int mode); #include <sys/personality.h> #endif -static const char emacs_version[] = VERSION; +static const char emacs_version[] = PACKAGE_VERSION; static const char emacs_copyright[] = COPYRIGHT; +static const char emacs_bugreport[] = PACKAGE_BUGREPORT; /* Empty lisp strings. To avoid having to build any others. */ Lisp_Object empty_unibyte_string, empty_multibyte_string; @@ -121,6 +128,9 @@ Lisp_Object Vlibrary_cache; on subsequent starts. */ bool initialized; +/* Set to true if this instance of Emacs might dump. */ +bool might_dump; + #ifdef DARWIN_OS extern void unexec_init_emacs_zone (void); #endif @@ -132,11 +142,11 @@ static void *malloc_state_ptr; /* From glibc, a routine that returns a copy of the malloc internal state. */ extern void *malloc_get_state (void); /* From glibc, a routine that overwrites the malloc internal state. */ -extern int malloc_set_state (void*); +extern int malloc_set_state (void *); /* True if the MALLOC_CHECK_ environment variable was set while dumping. Used to work around a bug in glibc's malloc. */ static bool malloc_using_checking; -#elif defined HAVE_PTHREAD && !defined SYSTEM_MALLOC +#elif defined HAVE_PTHREAD && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC extern void malloc_enable_thread (void); #endif @@ -210,7 +220,7 @@ int initial_argc; static void sort_args (int argc, char **argv); static void syms_of_emacs (void); -/* C89 needs each string be at most 509 characters, so the usage +/* C99 needs each string to be at most 4095 characters, and the usage strings below are split to not overflow this limit. */ static char const *const usage_message[] = { "\ @@ -321,7 +331,7 @@ abbreviation for a --option.\n\ Various environment variables and window system resources also affect\n\ the operation of Emacs. See the main documentation.\n\ \n\ -Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\ +Report bugs to " PACKAGE_BUGREPORT ". First, please see the Bugs\n\ section of the Emacs manual or the file BUGS.\n" }; @@ -386,10 +396,11 @@ terminate_due_to_signal (int sig, int backtrace_limit) static void init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd) { - register int i; + int i; Lisp_Object name, dir, handler; ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object raw_name; + AUTO_STRING (slash_colon, "/:"); initial_argv = argv; initial_argc = argc; @@ -413,7 +424,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd) if it would otherwise be treated as magic. */ handler = Ffind_file_name_handler (raw_name, Qt); if (! NILP (handler)) - raw_name = concat2 (build_string ("/:"), raw_name); + raw_name = concat2 (slash_colon, raw_name); Vinvocation_name = Ffile_name_nondirectory (raw_name); Vinvocation_directory = Ffile_name_directory (raw_name); @@ -431,7 +442,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd) if it would otherwise be treated as magic. */ handler = Ffind_file_name_handler (found, Qt); if (! NILP (handler)) - found = concat2 (build_string ("/:"), found); + found = concat2 (slash_colon, found); Vinvocation_directory = Ffile_name_directory (found); } } @@ -567,12 +578,6 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory, } -#ifdef HAVE_TZSET -/* A valid but unlikely value for the TZ environment value. - It is OK (though a bit slower) if the user actually chooses this value. */ -static char const dump_tz[] = "UtC0"; -#endif - /* Test whether the next argument in ARGV matches SSTR or a prefix of LSTR (at least MINLEN characters). If so, then if VALPTR is non-null (the argument is supposed to have a value) store in *VALPTR either @@ -725,18 +730,13 @@ main (int argc, char **argv) stack_base = &dummy; #endif -#ifdef G_SLICE_ALWAYS_MALLOC - /* This is used by the Cygwin build. It's not needed starting with - cygwin-1.7.24, but it doesn't do any harm. */ - xputenv ("G_SLICE=always-malloc"); +#ifndef CANNOT_DUMP + might_dump = !initialized; #endif #ifdef GNU_LINUX if (!initialized) { - extern char my_endbss[]; - extern char *my_endbss_static; - if (my_heap_start == 0) my_heap_start = sbrk (0); @@ -865,7 +865,6 @@ main (int argc, char **argv) && !getrlimit (RLIMIT_STACK, &rlim)) { long newlim; - extern size_t re_max_failures; /* Approximate the amount regex.c needs per unit of re_max_failures. */ int ratio = 20 * sizeof (char *); /* Then add 33% to cover the size of the smaller stacks that regex.c @@ -899,7 +898,7 @@ main (int argc, char **argv) clearerr (stdin); -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC /* Arrange to get warning messages as memory fills up. */ memory_warnings (0, malloc_warning); @@ -907,22 +906,12 @@ main (int argc, char **argv) Also call realloc and free for consistency. */ free (realloc (malloc (4), 4)); -#endif /* not SYSTEM_MALLOC */ - -#if defined (MSDOS) || defined (WINDOWSNT) - /* We do all file input/output as binary files. When we need to translate - newlines, we do that manually. */ - _fmode = O_BINARY; -#endif /* MSDOS || WINDOWSNT */ +#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */ #ifdef MSDOS - if (!isatty (fileno (stdin))) - setmode (fileno (stdin), O_BINARY); - if (!isatty (fileno (stdout))) - { - fflush (stdout); - setmode (fileno (stdout), O_BINARY); - } + SET_BINARY (fileno (stdin)); + fflush (stdout); + SET_BINARY (fileno (stdout)); #endif /* MSDOS */ /* Skip initial setlocale if LC_ALL is "C", as it's not needed in that case. @@ -1000,7 +989,7 @@ main (int argc, char **argv) { int i; printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); - for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++) + for (i = 0; i < ARRAYELTS (usage_message); i++) fputs (usage_message[i], stdout); exit (0); } @@ -1142,12 +1131,13 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #endif /* DOS_NT */ } -#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC +#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC \ + && !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC # ifndef CANNOT_DUMP /* Do not make gmalloc thread-safe when creating bootstrap-emacs, as - that causes an infinite recursive loop with FreeBSD. But do make - it thread-safe when creating emacs, otherwise bootstrap-emacs - fails on Cygwin. See Bug#14569. */ + that causes an infinite recursive loop with FreeBSD. See + Bug#14569. The part of this bug involving Cygwin is no longer + relevant, now that Cygwin defines HYBRID_MALLOC. */ if (!noninteractive || initialized) # endif malloc_enable_thread (); @@ -1368,7 +1358,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem xputenv ("LANG=C"); #endif - init_buffer (); /* Init default directory of main buffer. */ + /* Init buffer storage and default directory of main buffer. */ + init_buffer (initialized); init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */ @@ -1551,8 +1542,23 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_charset (); - init_editfns (); /* init_process_emacs uses Voperating_system_release. */ - init_process_emacs (); /* init_display uses add_keyboard_wait_descriptor. */ + /* This calls putenv and so must precede init_process_emacs. Also, + it sets Voperating_system_release, which init_process_emacs uses. */ + init_editfns (); + + /* These two call putenv. */ +#ifdef HAVE_DBUS + init_dbusbind (); +#endif +#ifdef USE_GTK + init_xterm (); +#endif + + /* This can create a thread that may call getenv, so it must follow + all calls to putenv and setenv. Also, this sets up + add_keyboard_wait_descriptor, which init_display uses. */ + init_process_emacs (); + init_keyboard (); /* This too must precede init_sys_modes. */ if (!noninteractive) init_display (); /* Determine terminal type. Calls init_sys_modes. */ @@ -1589,26 +1595,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem build_string ("loadup.el")); } - if (initialized) - { -#ifdef HAVE_TZSET - { - /* If the execution TZ happens to be the same as the dump TZ, - change it to some other value and then change it back, - to force the underlying implementation to reload the TZ info. - This is needed on implementations that load TZ info from files, - since the TZ file contents may differ between dump and execution. */ - char *tz = getenv ("TZ"); - if (tz && !strcmp (tz, dump_tz)) - { - ++*tz; - tzset (); - --*tz; - } - } -#endif - } - /* Set up for profiling. This is known to work on FreeBSD, GNU/Linux and MinGW. It might work on some other systems too. Give it a try and tell us if it works on your system. To compile @@ -1633,15 +1619,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem initialized = 1; -#ifdef LOCALTIME_CACHE - /* Some versions of localtime have a bug. They cache the value of the time - zone rather than looking it up every time. Since localtime() is - called to bolt the undumping time into the undumped emacs, this - results in localtime ignoring the TZ environment variable. - This flushes the new TZ value into localtime. */ - tzset (); -#endif /* defined (LOCALTIME_CACHE) */ - /* Enter editor command loop. This never returns. */ Frecursive_edit (); /* NOTREACHED */ @@ -1809,7 +1786,7 @@ sort_args (int argc, char **argv) } /* Look for a match with a known old-fashioned option. */ - for (i = 0; i < sizeof (standard_args) / sizeof (standard_args[0]); i++) + for (i = 0; i < ARRAYELTS (standard_args); i++) if (!strcmp (argv[from], standard_args[i].name)) { options[from] = standard_args[i].nargs; @@ -1831,8 +1808,7 @@ sort_args (int argc, char **argv) match = -1; - for (i = 0; - i < sizeof (standard_args) / sizeof (standard_args[0]); i++) + for (i = 0; i < ARRAYELTS (standard_args); i++) if (standard_args[i].longname && !strncmp (argv[from], standard_args[i].longname, thislen)) @@ -2025,9 +2001,7 @@ shut_down_emacs (int sig, Lisp_Object stuff) kill_buffer_processes (Qnil); Fdo_auto_save (Qt, Qnil); -#ifdef CLASH_DETECTION unlock_all_files (); -#endif /* There is a tendency for a SIGIO signal to arrive within exit, and cause a SIGHUP because the input descriptor is already closed. */ @@ -2082,6 +2056,9 @@ You must run Emacs in batch mode in order to dump it. */) if (! noninteractive) error ("Dumping Emacs works only in batch mode"); + if (!might_dump) + error ("Emacs can be dumped only once"); + #ifdef GNU_LINUX /* Warn if the gap between BSS end and heap start is larger than this. */ @@ -2122,38 +2099,22 @@ You must run Emacs in batch mode in order to dump it. */) tem = Vpurify_flag; Vpurify_flag = Qnil; -#ifdef HAVE_TZSET - set_time_zone_rule (dump_tz); -#ifndef LOCALTIME_CACHE - /* Force a tz reload, since set_time_zone_rule doesn't. */ - tzset (); -#endif -#endif - fflush (stdout); /* Tell malloc where start of impure now is. */ /* Also arrange for warnings when nearly out of space. */ -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC #ifndef WINDOWSNT /* On Windows, this was done before dumping, and that once suffices. Meanwhile, my_edata is not valid on Windows. */ - { - extern char my_edata[]; - memory_warnings (my_edata, malloc_warning); - } + memory_warnings (my_edata, malloc_warning); #endif /* not WINDOWSNT */ -#endif /* not SYSTEM_MALLOC */ +#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */ #ifdef DOUG_LEA_MALLOC malloc_state_ptr = malloc_get_state (); #endif -#ifdef USE_MMAP_FOR_BUFFERS - mmap_set_vars (0); -#endif unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0); -#ifdef USE_MMAP_FOR_BUFFERS - mmap_set_vars (1); -#endif + #ifdef DOUG_LEA_MALLOC free (malloc_state_ptr); #endif @@ -2335,7 +2296,10 @@ decode_env_path (const char *evarname, const char *defalt, bool empty) } if (! NILP (tem)) - element = concat2 (build_string ("/:"), element); + { + AUTO_STRING (slash_colon, "/:"); + element = concat2 (slash_colon, element); + } } /* !NILP (element) */ lpath = Fcons (element, lpath); @@ -2452,6 +2416,12 @@ Emacs is running. */); doc: /* String containing the configuration options Emacs was built with. */); Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS); + DEFVAR_LISP ("system-configuration-features", Vsystem_configuration_features, + doc: /* String listing some of the main features this Emacs was compiled with. +An element of the form \"FOO\" generally means that HAVE_FOO was +defined during the build. */); + Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES); + DEFVAR_BOOL ("noninteractive", noninteractive1, doc: /* Non-nil means Emacs is running without interactive terminal. */); @@ -2529,6 +2499,10 @@ This is nil during initialization. */); doc: /* Version numbers of this version of Emacs. */); Vemacs_version = build_string (emacs_version); + DEFVAR_LISP ("report-emacs-bug-address", Vreport_emacs_bug_address, + doc: /* Address of mailing list for GNU Emacs bugs. */); + Vreport_emacs_bug_address = build_string (emacs_bugreport); + DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist, doc: /* Alist of dynamic libraries vs external files implementing them. Each element is a list (LIBRARY FILE...), where the car is a symbol diff --git a/src/eval.c b/src/eval.c index 929b98e9f71..77b1db95397 100644 --- a/src/eval.c +++ b/src/eval.c @@ -27,11 +27,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "commands.h" #include "keyboard.h" #include "dispextern.h" -#include "frame.h" /* For XFRAME. */ - -#if HAVE_X_WINDOWS -#include "xterm.h" -#endif /* Chain of condition and catch handlers currently in effect. */ @@ -97,10 +92,8 @@ static EMACS_INT when_entered_debugger; /* FIXME: We should probably get rid of this! */ Lisp_Object Vsignaling_function; -/* If non-nil, Lisp code must not be run since some part of Emacs is - in an inconsistent state. Currently, x-create-frame uses this to - avoid triggering window-configuration-change-hook while the new - frame is half-initialized. */ +/* If non-nil, Lisp code must not be run since some part of Emacs is in + an inconsistent state. Currently unused. */ Lisp_Object inhibit_lisp_code; /* These would ordinarily be static, but they need to be visible to GDB. */ @@ -1273,7 +1266,10 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, { /* The first clause is the one that should be checked first, so it should be added to handlerlist last. So we build in `clauses' a table that - contains `handlers' but in reverse order. */ + contains `handlers' but in reverse order. SAFE_ALLOCA won't work + here due to the setjmp, so impose a MAX_ALLOCA limit. */ + if (MAX_ALLOCA / word_size < clausenb) + memory_full (SIZE_MAX); Lisp_Object *clauses = alloca (clausenb * sizeof *clauses); Lisp_Object *volatile clauses_volatile = clauses; int i = clausenb; @@ -1312,7 +1308,7 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, return val; } } - } + } val = eval_sub (bodyform); handlerlist = oldhandlerlist; @@ -2275,12 +2271,10 @@ Thus, (apply '+ 1 2 '(3 4)) returns 10. usage: (apply FUNCTION &rest ARGUMENTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - ptrdiff_t i; - EMACS_INT numargs; + ptrdiff_t i, numargs, funcall_nargs; register Lisp_Object spread_arg; register Lisp_Object *funcall_args; Lisp_Object fun, retval; - struct gcpro gcpro1; USE_SAFE_ALLOCA; fun = args [0]; @@ -2321,10 +2315,9 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) /* Avoid making funcall cons up a yet another new vector of arguments by explicitly supplying nil's for optional values. */ SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->max_args); - for (i = numargs; i < XSUBR (fun)->max_args;) + for (i = numargs; i < XSUBR (fun)->max_args; /* nothing */) funcall_args[++i] = Qnil; - GCPRO1 (*funcall_args); - gcpro1.nvars = 1 + XSUBR (fun)->max_args; + funcall_nargs = 1 + XSUBR (fun)->max_args; } } funcall: @@ -2333,8 +2326,7 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) if (!funcall_args) { SAFE_ALLOCA_LISP (funcall_args, 1 + numargs); - GCPRO1 (*funcall_args); - gcpro1.nvars = 1 + numargs; + funcall_nargs = 1 + numargs; } memcpy (funcall_args, args, nargs * word_size); @@ -2347,11 +2339,10 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) spread_arg = XCDR (spread_arg); } - /* By convention, the caller needs to gcpro Ffuncall's args. */ - retval = Ffuncall (gcpro1.nvars, funcall_args); - UNGCPRO; - SAFE_FREE (); + /* Ffuncall gcpro's all of its args. */ + retval = Ffuncall (funcall_nargs, funcall_args); + SAFE_FREE (); return retval; } @@ -2559,41 +2550,22 @@ run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args, void run_hook_with_args_2 (Lisp_Object hook, Lisp_Object arg1, Lisp_Object arg2) { - Lisp_Object temp[3]; - temp[0] = hook; - temp[1] = arg1; - temp[2] = arg2; - - Frun_hook_with_args (3, temp); + Frun_hook_with_args (3, ((Lisp_Object []) { hook, arg1, arg2 })); } - + /* Apply fn to arg. */ Lisp_Object apply1 (Lisp_Object fn, Lisp_Object arg) { - struct gcpro gcpro1; - - GCPRO1 (fn); - if (NILP (arg)) - RETURN_UNGCPRO (Ffuncall (1, &fn)); - gcpro1.nvars = 2; - { - Lisp_Object args[2]; - args[0] = fn; - args[1] = arg; - gcpro1.var = args; - RETURN_UNGCPRO (Fapply (2, args)); - } + return (NILP (arg) ? Ffuncall (1, &fn) + : Fapply (2, ((Lisp_Object []) { fn, arg }))); } /* Call function fn on no arguments. */ Lisp_Object call0 (Lisp_Object fn) { - struct gcpro gcpro1; - - GCPRO1 (fn); - RETURN_UNGCPRO (Ffuncall (1, &fn)); + return Ffuncall (1, &fn); } /* Call function fn with 1 argument arg1. */ @@ -2601,14 +2573,7 @@ call0 (Lisp_Object fn) Lisp_Object call1 (Lisp_Object fn, Lisp_Object arg1) { - struct gcpro gcpro1; - Lisp_Object args[2]; - - args[0] = fn; - args[1] = arg1; - GCPRO1 (args[0]); - gcpro1.nvars = 2; - RETURN_UNGCPRO (Ffuncall (2, args)); + return Ffuncall (2, ((Lisp_Object []) { fn, arg1 })); } /* Call function fn with 2 arguments arg1, arg2. */ @@ -2616,14 +2581,7 @@ call1 (Lisp_Object fn, Lisp_Object arg1) Lisp_Object call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) { - struct gcpro gcpro1; - Lisp_Object args[3]; - args[0] = fn; - args[1] = arg1; - args[2] = arg2; - GCPRO1 (args[0]); - gcpro1.nvars = 3; - RETURN_UNGCPRO (Ffuncall (3, args)); + return Ffuncall (3, ((Lisp_Object []) { fn, arg1, arg2 })); } /* Call function fn with 3 arguments arg1, arg2, arg3. */ @@ -2631,15 +2589,7 @@ call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) Lisp_Object call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) { - struct gcpro gcpro1; - Lisp_Object args[4]; - args[0] = fn; - args[1] = arg1; - args[2] = arg2; - args[3] = arg3; - GCPRO1 (args[0]); - gcpro1.nvars = 4; - RETURN_UNGCPRO (Ffuncall (4, args)); + return Ffuncall (4, ((Lisp_Object []) { fn, arg1, arg2, arg3 })); } /* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */ @@ -2648,16 +2598,7 @@ Lisp_Object call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4) { - struct gcpro gcpro1; - Lisp_Object args[5]; - args[0] = fn; - args[1] = arg1; - args[2] = arg2; - args[3] = arg3; - args[4] = arg4; - GCPRO1 (args[0]); - gcpro1.nvars = 5; - RETURN_UNGCPRO (Ffuncall (5, args)); + return Ffuncall (5, ((Lisp_Object []) { fn, arg1, arg2, arg3, arg4 })); } /* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */ @@ -2666,17 +2607,7 @@ Lisp_Object call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, Lisp_Object arg5) { - struct gcpro gcpro1; - Lisp_Object args[6]; - args[0] = fn; - args[1] = arg1; - args[2] = arg2; - args[3] = arg3; - args[4] = arg4; - args[5] = arg5; - GCPRO1 (args[0]); - gcpro1.nvars = 6; - RETURN_UNGCPRO (Ffuncall (6, args)); + return Ffuncall (6, ((Lisp_Object []) { fn, arg1, arg2, arg3, arg4, arg5 })); } /* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */ @@ -2685,18 +2616,8 @@ Lisp_Object call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6) { - struct gcpro gcpro1; - Lisp_Object args[7]; - args[0] = fn; - args[1] = arg1; - args[2] = arg2; - args[3] = arg3; - args[4] = arg4; - args[5] = arg5; - args[6] = arg6; - GCPRO1 (args[0]); - gcpro1.nvars = 7; - RETURN_UNGCPRO (Ffuncall (7, args)); + return Ffuncall (7, ((Lisp_Object []) + { fn, arg1, arg2, arg3, arg4, arg5, arg6 })); } /* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */ @@ -2705,19 +2626,8 @@ Lisp_Object call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7) { - struct gcpro gcpro1; - Lisp_Object args[8]; - args[0] = fn; - args[1] = arg1; - args[2] = arg2; - args[3] = arg3; - args[4] = arg4; - args[5] = arg5; - args[6] = arg6; - args[7] = arg7; - GCPRO1 (args[0]); - gcpro1.nvars = 8; - RETURN_UNGCPRO (Ffuncall (8, args)); + return Ffuncall (8, ((Lisp_Object []) + { fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7 })); } /* The caller should GCPRO all the elements of ARGS. */ @@ -2793,10 +2703,11 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) val = (XSUBR (fun)->function.aMANY) (numargs, args + 1); else { + Lisp_Object internal_argbuf[8]; if (XSUBR (fun)->max_args > numargs) { - internal_args = alloca (XSUBR (fun)->max_args - * sizeof *internal_args); + eassert (XSUBR (fun)->max_args <= ARRAYELTS (internal_argbuf)); + internal_args = internal_argbuf; memcpy (internal_args, args + 1, numargs * word_size); for (i = numargs; i < XSUBR (fun)->max_args; i++) internal_args[i] = Qnil; diff --git a/src/fileio.c b/src/fileio.c index b4653017b28..4ba1c5914e8 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -396,13 +396,6 @@ Otherwise return a directory name. Given a Unix syntax file name, returns a string ending in slash. */) (Lisp_Object filename) { -#ifndef DOS_NT - register const char *beg; -#else - register char *beg; - Lisp_Object tem_fn; -#endif - register const char *p; Lisp_Object handler; CHECK_STRING (filename); @@ -417,12 +410,8 @@ Given a Unix syntax file name, returns a string ending in slash. */) return STRINGP (handled_name) ? handled_name : Qnil; } -#ifdef DOS_NT - beg = xlispstrdupa (filename); -#else - beg = SSDATA (filename); -#endif - p = beg + SBYTES (filename); + char *beg = SSDATA (filename); + char const *p = beg + SBYTES (filename); while (p != beg && !IS_DIRECTORY_SEP (p[-1]) #ifdef DOS_NT @@ -438,6 +427,11 @@ Given a Unix syntax file name, returns a string ending in slash. */) return Qnil; #ifdef DOS_NT /* Expansion of "c:" to drive and default directory. */ + Lisp_Object tem_fn; + USE_SAFE_ALLOCA; + SAFE_ALLOCA_STRING (beg, filename); + p = beg + (p - SSDATA (filename)); + if (p[-1] == ':') { /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ @@ -481,6 +475,7 @@ Given a Unix syntax file name, returns a string ending in slash. */) dostounix_filename (beg); tem_fn = make_specified_string (beg, -1, p - beg, 0); } + SAFE_FREE (); return tem_fn; #else /* DOS_NT */ return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); @@ -847,8 +842,6 @@ probably use `make-temp-file' instead, except in three circumstances: return make_temp_name (prefix, 0); } - - DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, doc: /* Convert filename NAME to absolute, and canonicalize it. Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative @@ -878,7 +871,9 @@ filesystem tree, not (expand-file-name ".." dirname). */) /* These point to SDATA and need to be careful with string-relocation during GC (via DECODE_FILE). */ char *nm; + char *nmlim; const char *newdir; + const char *newdirlim; /* This should only point to alloca'd data. */ char *target; @@ -886,10 +881,10 @@ filesystem tree, not (expand-file-name ".." dirname). */) struct passwd *pw; #ifdef DOS_NT int drive = 0; - bool collapse_newdir = 1; + bool collapse_newdir = true; bool is_escaped = 0; #endif /* DOS_NT */ - ptrdiff_t length; + ptrdiff_t length, nbytes; Lisp_Object handler, result, handled_name; bool multibyte; Lisp_Object hdir; @@ -989,7 +984,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) { unsigned char *p = SDATA (name); - while (*p && ASCII_BYTE_P (*p)) + while (*p && ASCII_CHAR_P (*p)) p++; if (*p == '\0') { @@ -1018,8 +1013,9 @@ filesystem tree, not (expand-file-name ".." dirname). */) default_directory = Fdowncase (default_directory); #endif - /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ - nm = xlispstrdupa (name); + /* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */ + SAFE_ALLOCA_STRING (nm, name); + nmlim = nm + SBYTES (name); #ifdef DOS_NT /* Note if special escape prefix is present, but remove for now. */ @@ -1104,7 +1100,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (IS_DIRECTORY_SEP (nm[1])) { if (strcmp (nm, SSDATA (name)) != 0) - name = make_specified_string (nm, -1, strlen (nm), multibyte); + name = make_specified_string (nm, -1, nmlim - nm, multibyte); } else #endif @@ -1115,18 +1111,19 @@ filesystem tree, not (expand-file-name ".." dirname). */) name = make_specified_string (nm, -1, p - nm, multibyte); temp[0] = DRIVE_LETTER (drive); - name = concat2 (build_string (temp), name); + AUTO_STRING (drive_prefix, temp); + name = concat2 (drive_prefix, name); } #ifdef WINDOWSNT if (!NILP (Vw32_downcase_file_names)) name = Fdowncase (name); #endif - return name; #else /* not DOS_NT */ - if (strcmp (nm, SSDATA (name)) == 0) - return name; - return make_specified_string (nm, -1, strlen (nm), multibyte); + if (strcmp (nm, SSDATA (name)) != 0) + name = make_specified_string (nm, -1, nmlim - nm, multibyte); #endif /* not DOS_NT */ + SAFE_FREE (); + return name; } } @@ -1146,7 +1143,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) return an absolute name, if the final prefix is not absolute we append it to the current working directory. */ - newdir = 0; + newdir = newdirlim = 0; if (nm[0] == '~') /* prefix ~ */ { @@ -1156,7 +1153,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) Lisp_Object tem; if (!(newdir = egetenv ("HOME"))) - newdir = ""; + newdir = newdirlim = ""; nm++; /* `egetenv' may return a unibyte string, which will bite us since we expect the directory to be multibyte. */ @@ -1171,13 +1168,15 @@ filesystem tree, not (expand-file-name ".." dirname). */) else #endif tem = build_string (newdir); + newdirlim = newdir + SBYTES (tem); if (multibyte && !STRING_MULTIBYTE (tem)) { hdir = DECODE_FILE (tem); newdir = SSDATA (hdir); + newdirlim = newdir + SBYTES (hdir); } #ifdef DOS_NT - collapse_newdir = 0; + collapse_newdir = false; #endif } else /* ~user/filename */ @@ -1201,14 +1200,16 @@ filesystem tree, not (expand-file-name ".." dirname). */) bite us since we expect the directory to be multibyte. */ tem = build_string (newdir); + newdirlim = newdir + SBYTES (tem); if (multibyte && !STRING_MULTIBYTE (tem)) { hdir = DECODE_FILE (tem); newdir = SSDATA (hdir); + newdirlim = newdir + SBYTES (hdir); } nm = p; #ifdef DOS_NT - collapse_newdir = 0; + collapse_newdir = false; #endif } @@ -1234,8 +1235,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) Lisp_Object tem = build_string (adir); tem = DECODE_FILE (tem); + newdirlim = adir + SBYTES (tem); memcpy (adir, SSDATA (tem), SBYTES (tem) + 1); } + else + newdirlim = adir + strlen (adir); } if (!adir) { @@ -1245,6 +1249,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) adir[1] = ':'; adir[2] = '/'; adir[3] = 0; + newdirlim = adir + 3; } newdir = adir; } @@ -1265,6 +1270,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) && !newdir) { newdir = SSDATA (default_directory); + newdirlim = newdir + SBYTES (default_directory); #ifdef DOS_NT /* Note if special escape prefix is present, but remove for now. */ if (newdir[0] == '/' && newdir[1] == ':') @@ -1309,12 +1315,15 @@ filesystem tree, not (expand-file-name ".." dirname). */) } if (!IS_DIRECTORY_SEP (nm[0])) { - ptrdiff_t newlen = strlen (newdir); - char *tmp = alloca (newlen + file_name_as_directory_slop - + strlen (nm) + 1); - file_name_as_directory (tmp, newdir, newlen, multibyte); - strcat (tmp, nm); + ptrdiff_t nmlen = nmlim - nm; + ptrdiff_t newdirlen = newdirlim - newdir; + char *tmp = alloca (newdirlen + file_name_as_directory_slop + + nmlen + 1); + ptrdiff_t dlen = file_name_as_directory (tmp, newdir, newdirlen, + multibyte); + memcpy (tmp + dlen, nm, nmlen + 1); nm = tmp; + nmlim = nm + dlen + nmlen; } adir = alloca (adir_size); if (drive) @@ -1329,8 +1338,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) Lisp_Object tem = build_string (adir); tem = DECODE_FILE (tem); + newdirlim = adir + SBYTES (tem); memcpy (adir, SSDATA (tem), SBYTES (tem) + 1); } + else + newdirlim = adir + strlen (adir); newdir = adir; } @@ -1349,35 +1361,32 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]) && !IS_DIRECTORY_SEP (newdir[2])) { - char *adir = strcpy (alloca (strlen (newdir) + 1), newdir); + char *adir = strcpy (alloca (newdirlim - newdir + 1), newdir); char *p = adir + 2; while (*p && !IS_DIRECTORY_SEP (*p)) p++; p++; while (*p && !IS_DIRECTORY_SEP (*p)) p++; *p = 0; newdir = adir; + newdirlim = newdir + strlen (adir); } else #endif - newdir = ""; + newdir = newdirlim = ""; } } #endif /* DOS_NT */ - if (newdir) - { - /* Ignore any slash at the end of newdir, unless newdir is - just "/" or "//". */ - length = strlen (newdir); - while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) - && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0]))) - length--; - } - else - length = 0; + /* Ignore any slash at the end of newdir, unless newdir is + just "/" or "//". */ + length = newdirlim - newdir; + while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) + && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0]))) + length--; /* Now concatenate the directory and name to new space in the stack frame. */ - tlen = length + file_name_as_directory_slop + strlen (nm) + 1; + tlen = length + file_name_as_directory_slop + (nmlim - nm) + 1; + eassert (tlen > file_name_as_directory_slop + 1); #ifdef DOS_NT /* Reserve space for drive specifier and escape prefix, since either or both may need to be inserted. (The Microsoft x86 compiler @@ -1388,6 +1397,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) target = SAFE_ALLOCA (tlen); #endif /* not DOS_NT */ *target = 0; + nbytes = 0; if (newdir) { @@ -1405,13 +1415,14 @@ filesystem tree, not (expand-file-name ".." dirname). */) { memcpy (target, newdir, length); target[length] = 0; + nbytes = length; } } else - file_name_as_directory (target, newdir, length, multibyte); + nbytes = file_name_as_directory (target, newdir, length, multibyte); } - strcat (target, nm); + memcpy (target + nbytes, nm, nmlim - nm + 1); /* Now canonicalize by removing `//', `/.' and `/foo/..' if they appear. */ @@ -1717,7 +1728,8 @@ search_embedded_absfilename (char *nm, char *endp) for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++); if (p[0] == '~' && s > p + 1) /* We've got "/~something/". */ { - char *o = alloca (s - p + 1); + USE_SAFE_ALLOCA; + char *o = SAFE_ALLOCA (s - p + 1); struct passwd *pw; memcpy (o, p, s - p); o [s - p] = 0; @@ -1728,6 +1740,7 @@ search_embedded_absfilename (char *nm, char *endp) block_input (); pw = getpwnam (o + 1); unblock_input (); + SAFE_FREE (); if (pw) return p; } @@ -1776,7 +1789,8 @@ those `/' is discarded. */) /* Always work on a copy of the string, in case GC happens during decode of environment variables, causing the original Lisp_String data to be relocated. */ - nm = xlispstrdupa (filename); + USE_SAFE_ALLOCA; + SAFE_ALLOCA_STRING (nm, filename); #ifdef DOS_NT dostounix_filename (nm); @@ -1790,8 +1804,13 @@ those `/' is discarded. */) /* Start over with the new string, so we check the file-name-handler again. Important with filenames like "/home/foo//:/hello///there" which would substitute to "/:/hello///there" rather than "/there". */ - return Fsubstitute_in_file_name - (make_specified_string (p, -1, endp - p, multibyte)); + { + Lisp_Object result + = (Fsubstitute_in_file_name + (make_specified_string (p, -1, endp - p, multibyte))); + SAFE_FREE (); + return result; + } /* See if any variables are substituted into the string. */ @@ -1813,6 +1832,7 @@ those `/' is discarded. */) if (!NILP (Vw32_downcase_file_names)) filename = Fdowncase (filename); #endif + SAFE_FREE (); return filename; } @@ -1831,14 +1851,14 @@ those `/' is discarded. */) { Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte); - xname = Fdowncase (xname); - return xname; + filename = Fdowncase (xname); } else #endif - return (xnm == SSDATA (filename) - ? filename - : make_specified_string (xnm, -1, x - xnm, multibyte)); + if (xnm != SSDATA (filename)) + filename = make_specified_string (xnm, -1, x - xnm, multibyte); + SAFE_FREE (); + return filename; } /* A slightly faster and more convenient way to get @@ -2671,7 +2691,10 @@ emacs_readlinkat (int fd, char const *filename) val = build_unibyte_string (buf); if (buf[0] == '/' && strchr (buf, ':')) - val = concat2 (build_unibyte_string ("/:"), val); + { + AUTO_STRING (slash_colon, "/:"); + val = concat2 (slash_colon, val); + } if (buf != readlink_buf) xfree (buf); val = DECODE_FILE (val); @@ -2765,23 +2788,24 @@ searchable directory. */) } absname = ENCODE_FILE (absname); - return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil; + return file_accessible_directory_p (absname) ? Qt : Qnil; } /* If FILE is a searchable directory or a symlink to a searchable directory, return true. Otherwise return false and set errno to an error number. */ bool -file_accessible_directory_p (char const *file) +file_accessible_directory_p (Lisp_Object file) { #ifdef DOS_NT /* There's no need to test whether FILE is searchable, as the searchable/executable bit is invented on DOS_NT platforms. */ - return file_directory_p (file); + return file_directory_p (SSDATA (file)); #else /* On POSIXish platforms, use just one system call; this avoids a race and is typically faster. */ - ptrdiff_t len = strlen (file); + const char *data = SSDATA (file); + ptrdiff_t len = SBYTES (file); char const *dir; bool ok; int saved_errno; @@ -2793,15 +2817,15 @@ file_accessible_directory_p (char const *file) "/" and "//" are distinct on some platforms, whereas "/", "///", "////", etc. are all equivalent. */ if (! len) - dir = file; + dir = data; else { /* Just check for trailing '/' when deciding whether to append '/'. That's simpler than testing the two special cases "/" and "//", and it's a safe optimization here. */ char *buf = SAFE_ALLOCA (len + 3); - memcpy (buf, file, len); - strcpy (buf + len, &"/."[file[len - 1] == '/']); + memcpy (buf, data, len); + strcpy (buf + len, &"/."[data[len - 1] == '/']); dir = buf; } @@ -2910,7 +2934,7 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */) } #endif - return Flist (sizeof (values) / sizeof (values[0]), values); + return Flist (ARRAYELTS (values), values); } DEFUN ("set-file-selinux-context", Fset_file_selinux_context, @@ -3624,13 +3648,14 @@ by calling `format-decode', which see. */) report_file_error ("Read error", orig_filename); else if (nread > 0) { + AUTO_STRING (name, " *code-converting-work*"); struct buffer *prev = current_buffer; Lisp_Object workbuf; struct buffer *buf; record_unwind_current_buffer (); - workbuf = Fget_buffer_create (build_string (" *code-converting-work*")); + workbuf = Fget_buffer_create (name); buf = XBUFFER (workbuf); delete_all_overlays (buf); @@ -4082,13 +4107,11 @@ by calling `format-decode', which see. */) if (NILP (visit) && total > 0) { -#ifdef CLASH_DETECTION if (!NILP (BVAR (current_buffer, file_truename)) /* Make binding buffer-file-name to nil effective. */ && !NILP (BVAR (current_buffer, filename)) && SAVE_MODIFF >= MODIFF) we_locked_file = 1; -#endif /* CLASH_DETECTION */ prepare_to_modify_buffer (PT, PT, NULL); } @@ -4188,10 +4211,8 @@ by calling `format-decode', which see. */) if (inserted == 0) { -#ifdef CLASH_DETECTION if (we_locked_file) unlock_file (BVAR (current_buffer, file_truename)); -#endif Vdeactivate_mark = old_Vdeactivate_mark; } else @@ -4340,14 +4361,12 @@ by calling `format-decode', which see. */) SAVE_MODIFF = MODIFF; BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF; XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG); -#ifdef CLASH_DETECTION if (NILP (handler)) { if (!NILP (BVAR (current_buffer, file_truename))) unlock_file (BVAR (current_buffer, file_truename)); unlock_file (filename); } -#endif /* CLASH_DETECTION */ if (not_regular) xsignal2 (Qfile_error, build_string ("not a regular file"), orig_filename); @@ -4806,13 +4825,11 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, = choose_write_coding_system (start, end, filename, append, visit, lockname, &coding); -#ifdef CLASH_DETECTION if (open_and_close_file && !auto_saving) { lock_file (lockname); file_locked = 1; } -#endif /* CLASH_DETECTION */ encoded_filename = ENCODE_FILE (filename); fn = SSDATA (encoded_filename); @@ -4834,10 +4851,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, if (desc < 0) { int open_errno = errno; -#ifdef CLASH_DETECTION if (file_locked) unlock_file (lockname); -#endif /* CLASH_DETECTION */ UNGCPRO; report_file_errno ("Opening output file", filename, open_errno); } @@ -4852,10 +4867,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, if (ret < 0) { int lseek_errno = errno; -#ifdef CLASH_DETECTION if (file_locked) unlock_file (lockname); -#endif /* CLASH_DETECTION */ UNGCPRO; report_file_errno ("Lseek error", filename, lseek_errno); } @@ -4998,10 +5011,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, unbind_to (count, Qnil); -#ifdef CLASH_DETECTION if (file_locked) unlock_file (lockname); -#endif /* CLASH_DETECTION */ /* Do this before reporting IO error to avoid a "file has changed on disk" warning on @@ -5306,20 +5317,12 @@ If BUF is omitted or nil, it defaults to the current buffer. See Info node `(elisp)Modification Time' for more details. */) (Lisp_Object buf) { - struct buffer *b; + struct buffer *b = decode_buffer (buf); struct stat st; Lisp_Object handler; Lisp_Object filename; struct timespec mtime; - if (NILP (buf)) - b = current_buffer; - else - { - CHECK_BUFFER (buf); - b = XBUFFER (buf); - } - if (!STRINGP (BVAR (b, filename))) return Qt; if (b->modtime.tv_nsec == UNKNOWN_MODTIME_NSECS) return Qt; @@ -5413,7 +5416,7 @@ An argument specifies the modification time value to use static Lisp_Object auto_save_error (Lisp_Object error_val) { - Lisp_Object args[3], msg; + Lisp_Object msg; int i; struct gcpro gcpro1; @@ -5421,10 +5424,10 @@ auto_save_error (Lisp_Object error_val) ring_bell (XFRAME (selected_frame)); - args[0] = build_string ("Auto-saving %s: %s"); - args[1] = BVAR (current_buffer, name); - args[2] = Ferror_message_string (error_val); - msg = Fformat (3, args); + AUTO_STRING (format, "Auto-saving %s: %s"); + msg = Fformat (3, ((Lisp_Object []) + {format, BVAR (current_buffer, name), + Ferror_message_string (error_val)})); GCPRO1 (msg); for (i = 0; i < 3; ++i) @@ -5767,24 +5770,6 @@ before any other event (mouse or keypress) is handled. */) return Qnil; } -Lisp_Object -Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object initial, Lisp_Object predicate) -{ - struct gcpro gcpro1; - Lisp_Object args[7]; - - GCPRO1 (default_filename); - args[0] = intern ("read-file-name"); - args[1] = prompt; - args[2] = dir; - args[3] = default_filename; - args[4] = mustmatch; - args[5] = initial; - args[6] = predicate; - RETURN_UNGCPRO (Ffuncall (7, args)); -} - - void init_fileio (void) { diff --git a/src/filelock.c b/src/filelock.c index 5252db09104..f857c488143 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -55,8 +55,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "w32.h" /* for dostounix_filename */ #endif -#ifdef CLASH_DETECTION - #ifdef HAVE_UTMP_H #include <utmp.h> #endif @@ -773,7 +771,9 @@ DEFUN ("lock-buffer", Flock_buffer, Slock_buffer, 0, 1, 0, doc: /* Lock FILE, if current buffer is modified. FILE defaults to current buffer's visited file, -or else nothing is done if current buffer isn't visiting a file. */) +or else nothing is done if current buffer isn't visiting a file. + +If the option `create-lockfiles' is nil, this does nothing. */) (Lisp_Object file) { if (NILP (file)) @@ -837,8 +837,6 @@ t if it is locked by you, else a string saying which user has locked it. */) return ret; } -#endif /* CLASH_DETECTION */ - void syms_of_filelock (void) { @@ -850,9 +848,7 @@ syms_of_filelock (void) doc: /* Non-nil means use lockfiles to avoid editing collisions. */); create_lockfiles = 1; -#ifdef CLASH_DETECTION defsubr (&Sunlock_buffer); defsubr (&Slock_buffer); defsubr (&Sfile_locked_p); -#endif } diff --git a/src/fns.c b/src/fns.c index 499e4b490a6..e891fdbf1d5 100644 --- a/src/fns.c +++ b/src/fns.c @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <time.h> #include <intprops.h> +#include <vla.h> #include "lisp.h" #include "commands.h" @@ -41,6 +42,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif Lisp_Object Qstring_lessp; +static Lisp_Object Qstring_collate_lessp, Qstring_collate_equalp; static Lisp_Object Qprovide, Qrequire; static Lisp_Object Qyes_or_no_p_history; Lisp_Object Qcursor_in_echo_area; @@ -49,8 +51,10 @@ static Lisp_Object Qcodeset, Qdays, Qmonths, Qpaper; static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512; +static void sort_vector_copy (Lisp_Object, ptrdiff_t, + Lisp_Object [restrict], Lisp_Object [restrict]); static bool internal_equal (Lisp_Object, Lisp_Object, int, bool, Lisp_Object); - + DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, doc: /* Return the argument unchanged. */) (Lisp_Object arg) @@ -232,6 +236,7 @@ string STR1, compare the part between START1 (inclusive) and END1 \(exclusive). If START1 is nil, it defaults to 0, the beginning of the string; if END1 is nil, it defaults to the length of the string. Likewise, in string STR2, compare the part between START2 and END2. +Like in `substring', negative values are counted from the end. The strings are compared by the numeric values of their characters. For instance, STR1 is "less than" STR2 if its first differing @@ -244,75 +249,46 @@ If string STR1 is less, the value is a negative number N; - 1 - N is the number of characters that match at the beginning. If string STR1 is greater, the value is a positive number N; N - 1 is the number of characters that match at the beginning. */) - (Lisp_Object str1, Lisp_Object start1, Lisp_Object end1, Lisp_Object str2, Lisp_Object start2, Lisp_Object end2, Lisp_Object ignore_case) + (Lisp_Object str1, Lisp_Object start1, Lisp_Object end1, Lisp_Object str2, + Lisp_Object start2, Lisp_Object end2, Lisp_Object ignore_case) { - register ptrdiff_t end1_char, end2_char; - register ptrdiff_t i1, i1_byte, i2, i2_byte; + ptrdiff_t from1, to1, from2, to2, i1, i1_byte, i2, i2_byte; CHECK_STRING (str1); CHECK_STRING (str2); - if (NILP (start1)) - start1 = make_number (0); - if (NILP (start2)) - start2 = make_number (0); - CHECK_NATNUM (start1); - CHECK_NATNUM (start2); - if (! NILP (end1)) - CHECK_NATNUM (end1); - if (! NILP (end2)) - CHECK_NATNUM (end2); - - end1_char = SCHARS (str1); - if (! NILP (end1) && end1_char > XINT (end1)) - end1_char = XINT (end1); - if (end1_char < XINT (start1)) - args_out_of_range (str1, start1); - - end2_char = SCHARS (str2); - if (! NILP (end2) && end2_char > XINT (end2)) - end2_char = XINT (end2); - if (end2_char < XINT (start2)) - args_out_of_range (str2, start2); - - i1 = XINT (start1); - i2 = XINT (start2); + + /* For backward compatibility, silently bring too-large positive end + values into range. */ + if (INTEGERP (end1) && SCHARS (str1) < XINT (end1)) + end1 = make_number (SCHARS (str1)); + if (INTEGERP (end2) && SCHARS (str2) < XINT (end2)) + end2 = make_number (SCHARS (str2)); + + validate_subarray (str1, start1, end1, SCHARS (str1), &from1, &to1); + validate_subarray (str2, start2, end2, SCHARS (str2), &from2, &to2); + + i1 = from1; + i2 = from2; i1_byte = string_char_to_byte (str1, i1); i2_byte = string_char_to_byte (str2, i2); - while (i1 < end1_char && i2 < end2_char) + while (i1 < to1 && i2 < to2) { /* When we find a mismatch, we must compare the characters, not just the bytes. */ int c1, c2; - if (STRING_MULTIBYTE (str1)) - FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c1, str1, i1, i1_byte); - else - { - c1 = SREF (str1, i1++); - MAKE_CHAR_MULTIBYTE (c1); - } - - if (STRING_MULTIBYTE (str2)) - FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c2, str2, i2, i2_byte); - else - { - c2 = SREF (str2, i2++); - MAKE_CHAR_MULTIBYTE (c2); - } + FETCH_STRING_CHAR_AS_MULTIBYTE_ADVANCE (c1, str1, i1, i1_byte); + FETCH_STRING_CHAR_AS_MULTIBYTE_ADVANCE (c2, str2, i2, i2_byte); if (c1 == c2) continue; if (! NILP (ignore_case)) { - Lisp_Object tem; - - tem = Fupcase (make_number (c1)); - c1 = XINT (tem); - tem = Fupcase (make_number (c2)); - c2 = XINT (tem); + c1 = XINT (Fupcase (make_number (c1))); + c2 = XINT (Fupcase (make_number (c2))); } if (c1 == c2) @@ -322,15 +298,15 @@ If string STR1 is greater, the value is a positive number N; past the character that we are comparing; hence we don't add or subtract 1 here. */ if (c1 < c2) - return make_number (- i1 + XINT (start1)); + return make_number (- i1 + from1); else - return make_number (i1 - XINT (start1)); + return make_number (i1 - from1); } - if (i1 < end1_char) - return make_number (i1 - XINT (start1) + 1); - if (i2 < end2_char) - return make_number (- i1 + XINT (start1) - 1); + if (i1 < to1) + return make_number (i1 - from1 + 1); + if (i2 < to2) + return make_number (- i1 + from1 - 1); return Qt; } @@ -371,6 +347,100 @@ Symbols are also allowed; their print names are used instead. */) } return i1 < SCHARS (s2) ? Qt : Qnil; } + +DEFUN ("string-collate-lessp", Fstring_collate_lessp, Sstring_collate_lessp, 2, 4, 0, + doc: /* Return t if first arg string is less than second in collation order. +Symbols are also allowed; their print names are used instead. + +This function obeys the conventions for collation order in your +locale settings. For example, punctuation and whitespace characters +might be considered less significant for sorting: + +\(sort '\("11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp) + => \("11" "1 1" "1.1" "12" "1 2" "1.2") + +The optional argument LOCALE, a string, overrides the setting of your +current locale identifier for collation. The value is system +dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems, +while it would be, e.g., \"enu_USA.1252\" on MS-Windows systems. + +If IGNORE-CASE is non-nil, characters are converted to lower-case +before comparing them. + +To emulate Unicode-compliant collation on MS-Windows systems, +bind `w32-collate-ignore-punctuation' to a non-nil value, since +the codeset part of the locale cannot be \"UTF-8\" on MS-Windows. + +If your system does not support a locale environment, this function +behaves like `string-lessp'. */) + (Lisp_Object s1, Lisp_Object s2, Lisp_Object locale, Lisp_Object ignore_case) +{ +#if defined __STDC_ISO_10646__ || defined WINDOWSNT + /* Check parameters. */ + if (SYMBOLP (s1)) + s1 = SYMBOL_NAME (s1); + if (SYMBOLP (s2)) + s2 = SYMBOL_NAME (s2); + CHECK_STRING (s1); + CHECK_STRING (s2); + if (!NILP (locale)) + CHECK_STRING (locale); + + return (str_collate (s1, s2, locale, ignore_case) < 0) ? Qt : Qnil; + +#else /* !__STDC_ISO_10646__, !WINDOWSNT */ + return Fstring_lessp (s1, s2); +#endif /* !__STDC_ISO_10646__, !WINDOWSNT */ +} + +DEFUN ("string-collate-equalp", Fstring_collate_equalp, Sstring_collate_equalp, 2, 4, 0, + doc: /* Return t if two strings have identical contents. +Symbols are also allowed; their print names are used instead. + +This function obeys the conventions for collation order in your locale +settings. For example, characters with different coding points but +the same meaning might be considered as equal, like different grave +accent Unicode characters: + +\(string-collate-equalp \(string ?\\uFF40) \(string ?\\u1FEF)) + => t + +The optional argument LOCALE, a string, overrides the setting of your +current locale identifier for collation. The value is system +dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems, +while it would be \"enu_USA.1252\" on MS Windows systems. + +If IGNORE-CASE is non-nil, characters are converted to lower-case +before comparing them. + +To emulate Unicode-compliant collation on MS-Windows systems, +bind `w32-collate-ignore-punctuation' to a non-nil value, since +the codeset part of the locale cannot be \"UTF-8\" on MS-Windows. + +If your system does not support a locale environment, this function +behaves like `string-equal'. + +Do NOT use this function to compare file names for equality, only +for sorting them. */) + (Lisp_Object s1, Lisp_Object s2, Lisp_Object locale, Lisp_Object ignore_case) +{ +#if defined __STDC_ISO_10646__ || defined WINDOWSNT + /* Check parameters. */ + if (SYMBOLP (s1)) + s1 = SYMBOL_NAME (s1); + if (SYMBOLP (s2)) + s2 = SYMBOL_NAME (s2); + CHECK_STRING (s1); + CHECK_STRING (s2); + if (!NILP (locale)) + CHECK_STRING (locale); + + return (str_collate (s1, s2, locale, ignore_case) == 0) ? Qt : Qnil; + +#else /* !__STDC_ISO_10646__, !WINDOWSNT */ + return Fstring_equal (s1, s2); +#endif /* !__STDC_ISO_10646__, !WINDOWSNT */ +} static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args, enum Lisp_Type target_type, bool last_special); @@ -1127,7 +1197,48 @@ Elements of ALIST that are not conses are also shared. */) return alist; } -DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0, +/* Check that ARRAY can have a valid subarray [FROM..TO), + given that its size is SIZE. + If FROM is nil, use 0; if TO is nil, use SIZE. + Count negative values backwards from the end. + Set *IFROM and *ITO to the two indexes used. */ + +void +validate_subarray (Lisp_Object array, Lisp_Object from, Lisp_Object to, + ptrdiff_t size, ptrdiff_t *ifrom, ptrdiff_t *ito) +{ + EMACS_INT f, t; + + if (INTEGERP (from)) + { + f = XINT (from); + if (f < 0) + f += size; + } + else if (NILP (from)) + f = 0; + else + wrong_type_argument (Qintegerp, from); + + if (INTEGERP (to)) + { + t = XINT (to); + if (t < 0) + t += size; + } + else if (NILP (to)) + t = size; + else + wrong_type_argument (Qintegerp, to); + + if (! (0 <= f && f <= t && t <= size)) + args_out_of_range_3 (array, from, to); + + *ifrom = f; + *ito = t; +} + +DEFUN ("substring", Fsubstring, Ssubstring, 1, 3, 0, doc: /* Return a new string whose contents are a substring of STRING. The returned string consists of the characters between index FROM \(inclusive) and index TO (exclusive) of STRING. FROM and TO are @@ -1137,52 +1248,31 @@ to the end of STRING. The STRING argument may also be a vector. In that case, the return value is a new vector that contains the elements between index FROM -\(inclusive) and index TO (exclusive) of that vector argument. */) - (Lisp_Object string, register Lisp_Object from, Lisp_Object to) +\(inclusive) and index TO (exclusive) of that vector argument. + +With one argument, just copy STRING (with properties, if any). */) + (Lisp_Object string, Lisp_Object from, Lisp_Object to) { Lisp_Object res; - ptrdiff_t size; - EMACS_INT from_char, to_char; + ptrdiff_t size, ifrom, ito; - CHECK_VECTOR_OR_STRING (string); - CHECK_NUMBER (from); + size = CHECK_VECTOR_OR_STRING (string); + validate_subarray (string, from, to, size, &ifrom, &ito); if (STRINGP (string)) - size = SCHARS (string); - else - size = ASIZE (string); - - if (NILP (to)) - to_char = size; - else { - CHECK_NUMBER (to); - - to_char = XINT (to); - if (to_char < 0) - to_char += size; - } - - from_char = XINT (from); - if (from_char < 0) - from_char += size; - if (!(0 <= from_char && from_char <= to_char && to_char <= size)) - args_out_of_range_3 (string, make_number (from_char), - make_number (to_char)); - - if (STRINGP (string)) - { - ptrdiff_t to_byte = - (NILP (to) ? SBYTES (string) : string_char_to_byte (string, to_char)); - ptrdiff_t from_byte = string_char_to_byte (string, from_char); + ptrdiff_t from_byte + = !ifrom ? 0 : string_char_to_byte (string, ifrom); + ptrdiff_t to_byte + = ito == size ? SBYTES (string) : string_char_to_byte (string, ito); res = make_specified_string (SSDATA (string) + from_byte, - to_char - from_char, to_byte - from_byte, + ito - ifrom, to_byte - from_byte, STRING_MULTIBYTE (string)); - copy_text_properties (make_number (from_char), make_number (to_char), + copy_text_properties (make_number (ifrom), make_number (ito), string, make_number (0), res, Qnil); } else - res = Fvector (to_char - from_char, aref_addr (string, from_char)); + res = Fvector (ito - ifrom, aref_addr (string, ifrom)); return res; } @@ -1198,41 +1288,16 @@ If FROM or TO is negative, it counts from the end. With one argument, just copy STRING without its properties. */) (Lisp_Object string, register Lisp_Object from, Lisp_Object to) { - ptrdiff_t size; - EMACS_INT from_char, to_char; - ptrdiff_t from_byte, to_byte; + ptrdiff_t from_char, to_char, from_byte, to_byte, size; CHECK_STRING (string); size = SCHARS (string); + validate_subarray (string, from, to, size, &from_char, &to_char); - if (NILP (from)) - from_char = 0; - else - { - CHECK_NUMBER (from); - from_char = XINT (from); - if (from_char < 0) - from_char += size; - } - - if (NILP (to)) - to_char = size; - else - { - CHECK_NUMBER (to); - to_char = XINT (to); - if (to_char < 0) - to_char += size; - } - - if (!(0 <= from_char && from_char <= to_char && to_char <= size)) - args_out_of_range_3 (string, make_number (from_char), - make_number (to_char)); - - from_byte = NILP (from) ? 0 : string_char_to_byte (string, from_char); + from_byte = !from_char ? 0 : string_char_to_byte (string, from_char); to_byte = - NILP (to) ? SBYTES (string) : string_char_to_byte (string, to_char); + to_char == size ? SBYTES (string) : string_char_to_byte (string, to_char); return make_specified_string (SSDATA (string) + from_byte, to_char - from_char, to_byte - from_byte, STRING_MULTIBYTE (string)); @@ -1246,11 +1311,7 @@ substring_both (Lisp_Object string, ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t to, ptrdiff_t to_byte) { Lisp_Object res; - ptrdiff_t size; - - CHECK_VECTOR_OR_STRING (string); - - size = STRINGP (string) ? SCHARS (string) : ASIZE (string); + ptrdiff_t size = CHECK_VECTOR_OR_STRING (string); if (!(0 <= from && from <= to && to <= size)) args_out_of_range_3 (string, make_number (from), make_number (to)); @@ -1693,49 +1754,129 @@ changing the value of a sequence `foo'. */) } DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0, - doc: /* Reverse LIST by modifying cdr pointers. -Return the reversed list. Expects a properly nil-terminated list. */) - (Lisp_Object list) + doc: /* Reverse order of items in a list, vector or string SEQ. +If SEQ is a list, it should be nil-terminated. +This function may destructively modify SEQ to produce the value. */) + (Lisp_Object seq) { - register Lisp_Object prev, tail, next; + if (NILP (seq)) + return seq; + else if (STRINGP (seq)) + return Freverse (seq); + else if (CONSP (seq)) + { + Lisp_Object prev, tail, next; - if (NILP (list)) return list; - prev = Qnil; - tail = list; - while (!NILP (tail)) + for (prev = Qnil, tail = seq; !NILP (tail); tail = next) + { + QUIT; + CHECK_LIST_CONS (tail, tail); + next = XCDR (tail); + Fsetcdr (tail, prev); + prev = tail; + } + seq = prev; + } + else if (VECTORP (seq)) { - QUIT; - CHECK_LIST_CONS (tail, tail); - next = XCDR (tail); - Fsetcdr (tail, prev); - prev = tail; - tail = next; + ptrdiff_t i, size = ASIZE (seq); + + for (i = 0; i < size / 2; i++) + { + Lisp_Object tem = AREF (seq, i); + ASET (seq, i, AREF (seq, size - i - 1)); + ASET (seq, size - i - 1, tem); + } + } + else if (BOOL_VECTOR_P (seq)) + { + ptrdiff_t i, size = bool_vector_size (seq); + + for (i = 0; i < size / 2; i++) + { + bool tem = bool_vector_bitref (seq, i); + bool_vector_set (seq, i, bool_vector_bitref (seq, size - i - 1)); + bool_vector_set (seq, size - i - 1, tem); + } } - return prev; + else + wrong_type_argument (Qarrayp, seq); + return seq; } DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0, - doc: /* Reverse LIST, copying. Return the reversed list. + doc: /* Return the reversed copy of list, vector, or string SEQ. See also the function `nreverse', which is used more often. */) - (Lisp_Object list) + (Lisp_Object seq) { Lisp_Object new; - for (new = Qnil; CONSP (list); list = XCDR (list)) + if (NILP (seq)) + return Qnil; + else if (CONSP (seq)) { - QUIT; - new = Fcons (XCAR (list), new); + for (new = Qnil; CONSP (seq); seq = XCDR (seq)) + { + QUIT; + new = Fcons (XCAR (seq), new); + } + CHECK_LIST_END (seq, seq); + } + else if (VECTORP (seq)) + { + ptrdiff_t i, size = ASIZE (seq); + + new = make_uninit_vector (size); + for (i = 0; i < size; i++) + ASET (new, i, AREF (seq, size - i - 1)); } - CHECK_LIST_END (list, list); + else if (BOOL_VECTOR_P (seq)) + { + ptrdiff_t i; + EMACS_INT nbits = bool_vector_size (seq); + + new = make_uninit_bool_vector (nbits); + for (i = 0; i < nbits; i++) + bool_vector_set (new, i, bool_vector_bitref (seq, nbits - i - 1)); + } + else if (STRINGP (seq)) + { + ptrdiff_t size = SCHARS (seq), bytes = SBYTES (seq); + + if (size == bytes) + { + ptrdiff_t i; + + new = make_uninit_string (size); + for (i = 0; i < size; i++) + SSET (new, i, SREF (seq, size - i - 1)); + } + else + { + unsigned char *p, *q; + + new = make_uninit_multibyte_string (size, bytes); + p = SDATA (seq), q = SDATA (new) + bytes; + while (q > SDATA (new)) + { + int ch, len; + + ch = STRING_CHAR_AND_LENGTH (p, len); + p += len, q -= len; + CHAR_STRING (ch, q); + } + } + } + else + wrong_type_argument (Qsequencep, seq); return new; } - -DEFUN ("sort", Fsort, Ssort, 2, 2, 0, - doc: /* Sort LIST, stably, comparing elements using PREDICATE. -Returns the sorted list. LIST is modified by side effects. -PREDICATE is called with two elements of LIST, and should return non-nil -if the first element should sort before the second. */) - (Lisp_Object list, Lisp_Object predicate) + +/* Sort LIST using PREDICATE, preserving original order of elements + considered as equal. */ + +static Lisp_Object +sort_list (Lisp_Object list, Lisp_Object predicate) { Lisp_Object front, back; register Lisp_Object len, tem; @@ -1760,6 +1901,126 @@ if the first element should sort before the second. */) return merge (front, back, predicate); } +/* Using PRED to compare, return whether A and B are in order. + Compare stably when A appeared before B in the input. */ +static bool +inorder (Lisp_Object pred, Lisp_Object a, Lisp_Object b) +{ + return NILP (call2 (pred, b, a)); +} + +/* Using PRED to compare, merge from ALEN-length A and BLEN-length B + into DEST. Argument arrays must be nonempty and must not overlap, + except that B might be the last part of DEST. */ +static void +merge_vectors (Lisp_Object pred, + ptrdiff_t alen, Lisp_Object const a[restrict VLA_ELEMS (alen)], + ptrdiff_t blen, Lisp_Object const b[VLA_ELEMS (blen)], + Lisp_Object dest[VLA_ELEMS (alen + blen)]) +{ + eassume (0 < alen && 0 < blen); + Lisp_Object const *alim = a + alen; + Lisp_Object const *blim = b + blen; + + while (true) + { + if (inorder (pred, a[0], b[0])) + { + *dest++ = *a++; + if (a == alim) + { + if (dest != b) + memcpy (dest, b, (blim - b) * sizeof *dest); + return; + } + } + else + { + *dest++ = *b++; + if (b == blim) + { + memcpy (dest, a, (alim - a) * sizeof *dest); + return; + } + } + } +} + +/* Using PRED to compare, sort LEN-length VEC in place, using TMP for + temporary storage. LEN must be at least 2. */ +static void +sort_vector_inplace (Lisp_Object pred, ptrdiff_t len, + Lisp_Object vec[restrict VLA_ELEMS (len)], + Lisp_Object tmp[restrict VLA_ELEMS (len >> 1)]) +{ + eassume (2 <= len); + ptrdiff_t halflen = len >> 1; + sort_vector_copy (pred, halflen, vec, tmp); + if (1 < len - halflen) + sort_vector_inplace (pred, len - halflen, vec + halflen, vec); + merge_vectors (pred, halflen, tmp, len - halflen, vec + halflen, vec); +} + +/* Using PRED to compare, sort from LEN-length SRC into DST. + Len must be positive. */ +static void +sort_vector_copy (Lisp_Object pred, ptrdiff_t len, + Lisp_Object src[restrict VLA_ELEMS (len)], + Lisp_Object dest[restrict VLA_ELEMS (len)]) +{ + eassume (0 < len); + ptrdiff_t halflen = len >> 1; + if (halflen < 1) + dest[0] = src[0]; + else + { + if (1 < halflen) + sort_vector_inplace (pred, halflen, src, dest); + if (1 < len - halflen) + sort_vector_inplace (pred, len - halflen, src + halflen, dest); + merge_vectors (pred, halflen, src, len - halflen, src + halflen, dest); + } +} + +/* Sort VECTOR in place using PREDICATE, preserving original order of + elements considered as equal. */ + +static void +sort_vector (Lisp_Object vector, Lisp_Object predicate) +{ + ptrdiff_t len = ASIZE (vector); + if (len < 2) + return; + ptrdiff_t halflen = len >> 1; + Lisp_Object *tmp; + struct gcpro gcpro1, gcpro2; + GCPRO2 (vector, predicate); + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (tmp, halflen); + for (ptrdiff_t i = 0; i < halflen; i++) + tmp[i] = make_number (0); + sort_vector_inplace (predicate, len, XVECTOR (vector)->contents, tmp); + SAFE_FREE (); + UNGCPRO; +} + +DEFUN ("sort", Fsort, Ssort, 2, 2, 0, + doc: /* Sort SEQ, stably, comparing elements using PREDICATE. +Returns the sorted sequence. SEQ should be a list or vector. SEQ is +modified by side effects. PREDICATE is called with two elements of +SEQ, and should return non-nil if the first element should sort before +the second. */) + (Lisp_Object seq, Lisp_Object predicate) +{ + if (CONSP (seq)) + seq = sort_list (seq, predicate); + else if (VECTORP (seq)) + sort_vector (seq, predicate); + else if (!NILP (seq)) + wrong_type_argument (Qsequencep, seq); + return seq; +} + Lisp_Object merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) { @@ -1797,8 +2058,7 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) Fsetcdr (tail, l1); return value; } - tem = call2 (pred, Fcar (l2), Fcar (l1)); - if (NILP (tem)) + if (inorder (pred, Fcar (l1), Fcar (l2))) { tem = l1; l1 = Fcdr (l1); @@ -2446,8 +2706,7 @@ If dialog boxes are supported, a dialog box will be used if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */) (Lisp_Object prompt) { - register Lisp_Object ans; - Lisp_Object args[2]; + Lisp_Object ans; struct gcpro gcpro1; CHECK_STRING (prompt); @@ -2466,10 +2725,8 @@ if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */) return obj; } - args[0] = prompt; - args[1] = build_string ("(yes or no) "); - prompt = Fconcat (2, args); - + AUTO_STRING (yes_or_no, "(yes or no) "); + prompt = Fconcat (2, (Lisp_Object []) {prompt, yes_or_no}); GCPRO1 (prompt); while (1) @@ -3027,7 +3284,6 @@ into shorter lines. */) if (encoded_length < 0) { /* The encoding wasn't possible. */ - SAFE_FREE (); error ("Multibyte character in data for base64 encoding"); } @@ -3172,7 +3428,6 @@ If the region can't be decoded, signal an error and don't modify the buffer. */ if (decoded_length < 0) { /* The decoding wasn't possible. */ - SAFE_FREE (); error ("Invalid base64 data"); } @@ -3740,12 +3995,9 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) #ifdef ENABLE_CHECKING if (HASH_TABLE_P (Vpurify_flag) && XHASH_TABLE (Vpurify_flag) == h) - { - Lisp_Object args[2]; - args[0] = build_string ("Growing hash table to: %d"); - args[1] = make_number (new_size); - Fmessage (2, args); - } + Fmessage (2, ((Lisp_Object []) + { build_string ("Growing hash table to: %d"), + make_number (new_size) })); #endif set_hash_key_and_value (h, larger_vector (h->key_and_value, @@ -4032,6 +4284,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) current garbage collection. Remove weak tables that don't survive from Vweak_hash_tables. Called from gc_sweep. */ +NO_INLINE /* For better stack traces */ void sweep_weak_hash_tables (void) { @@ -4224,13 +4477,10 @@ sxhash (Lisp_Object obj, int depth) break; case Lisp_Misc: + case Lisp_Symbol: hash = XHASH (obj); break; - case Lisp_Symbol: - obj = SYMBOL_NAME (obj); - /* Fall through. */ - case Lisp_String: hash = sxhash_string (SSDATA (obj), SBYTES (obj)); break; @@ -4318,12 +4568,12 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */) { Lisp_Object test, size, rehash_size, rehash_threshold, weak; struct hash_table_test testdesc; - char *used; ptrdiff_t i; + USE_SAFE_ALLOCA; /* The vector `used' is used to keep track of arguments that have been consumed. */ - used = alloca (nargs * sizeof *used); + char *used = SAFE_ALLOCA (nargs * sizeof *used); memset (used, 0, nargs * sizeof *used); /* See if there's a `:test TEST' among the arguments. */ @@ -4390,6 +4640,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */) if (!used[i]) signal_error ("Invalid argument list", args[i]); + SAFE_FREE (); return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak); } @@ -4570,12 +4821,12 @@ returns nil, then (funcall TEST x1 x2) also returns nil. */) /* ALGORITHM is a symbol: md5, sha1, sha224 and so on. */ static Lisp_Object -secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror, Lisp_Object binary) +secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, + Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror, + Lisp_Object binary) { int i; - ptrdiff_t size; - EMACS_INT start_char = 0, end_char = 0; - ptrdiff_t start_byte, end_byte; + ptrdiff_t size, start_char = 0, start_byte, end_char = 0, end_byte; register EMACS_INT b, e; register struct buffer *bp; EMACS_INT temp; @@ -4612,36 +4863,12 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_ object = code_convert_string (object, coding_system, Qnil, 1, 0, 1); size = SCHARS (object); + validate_subarray (object, start, end, size, &start_char, &end_char); - if (!NILP (start)) - { - CHECK_NUMBER (start); - - start_char = XINT (start); - - if (start_char < 0) - start_char += size; - } - - if (NILP (end)) - end_char = size; - else - { - CHECK_NUMBER (end); - - end_char = XINT (end); - - if (end_char < 0) - end_char += size; - } - - if (!(0 <= start_char && start_char <= end_char && end_char <= size)) - args_out_of_range_3 (object, make_number (start_char), - make_number (end_char)); - - start_byte = NILP (start) ? 0 : string_char_to_byte (object, start_char); - end_byte = - NILP (end) ? SBYTES (object) : string_char_to_byte (object, end_char); + start_byte = !start_char ? 0 : string_char_to_byte (object, start_char); + end_byte = (end_char == size + ? SBYTES (object) + : string_char_to_byte (object, end_char)); } else { @@ -4898,6 +5125,8 @@ syms_of_fns (void) defsubr (&Sdefine_hash_table_test); DEFSYM (Qstring_lessp, "string-lessp"); + DEFSYM (Qstring_collate_lessp, "string-collate-lessp"); + DEFSYM (Qstring_collate_equalp, "string-collate-equalp"); DEFSYM (Qprovide, "provide"); DEFSYM (Qrequire, "require"); DEFSYM (Qyes_or_no_p_history, "yes-or-no-p-history"); @@ -4951,6 +5180,8 @@ this variable. */); defsubr (&Sstring_equal); defsubr (&Scompare_strings); defsubr (&Sstring_lessp); + defsubr (&Sstring_collate_lessp); + defsubr (&Sstring_collate_equalp); defsubr (&Sappend); defsubr (&Sconcat); defsubr (&Svconcat); diff --git a/src/font.c b/src/font.c index 95b22b2fceb..08a25455cf8 100644 --- a/src/font.c +++ b/src/font.c @@ -225,7 +225,35 @@ font_make_object (int size, Lisp_Object entity, int pixelsize) return font_object; } - +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) + +static int font_unparse_fcname (Lisp_Object, int, char *, int); + +/* Like above, but also set `type', `name' and `fullname' properties + of font-object. */ + +Lisp_Object +font_build_object (int vectorsize, Lisp_Object type, + Lisp_Object entity, double pixelsize) +{ + int len; + char name[256]; + Lisp_Object font_object = font_make_object (vectorsize, entity, pixelsize); + + ASET (font_object, FONT_TYPE_INDEX, type); + len = font_unparse_xlfd (entity, pixelsize, name, sizeof name); + if (len > 0) + ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); + len = font_unparse_fcname (entity, pixelsize, name, sizeof name); + if (len > 0) + ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); + else + ASET (font_object, FONT_FULLNAME_INDEX, + AREF (font_object, FONT_NAME_INDEX)); + return font_object; +} + +#endif /* HAVE_XFT || HAVE_FREETYPE || HAVE_NS */ static int font_pixel_size (struct frame *f, Lisp_Object); static Lisp_Object font_open_entity (struct frame *, Lisp_Object, int); @@ -245,10 +273,8 @@ static int num_font_drivers; Lisp_Object font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol) { - ptrdiff_t i; - Lisp_Object tem; - Lisp_Object obarray; - ptrdiff_t nbytes, nchars; + ptrdiff_t i, nbytes, nchars; + Lisp_Object tem, name, obarray; if (len == 1 && *str == '*') return Qnil; @@ -279,14 +305,11 @@ font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol) parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes); tem = oblookup (obarray, str, (len == nchars || len != nbytes) ? len : nchars, len); - if (SYMBOLP (tem)) return tem; - if (len == nchars || len != nbytes) - tem = make_unibyte_string (str, len); - else - tem = make_multibyte_string (str, nchars, len); - return Fintern (tem, obarray); + name = make_specified_string (str, nchars, len, + len != nchars && len == nbytes); + return intern_driver (name, obarray, XINT (tem)); } /* Return a pixel size of font-spec SPEC on frame F. */ @@ -340,7 +363,7 @@ font_style_to_value (enum font_property_index prop, Lisp_Object val, { int i, j; char *s; - Lisp_Object args[2], elt; + Lisp_Object elt; /* At first try exact match. */ for (i = 0; i < len; i++) @@ -372,9 +395,9 @@ font_style_to_value (enum font_property_index prop, Lisp_Object val, eassert (len < 255); elt = Fmake_vector (make_number (2), make_number (100)); ASET (elt, 1, val); - args[0] = table; - args[1] = Fmake_vector (make_number (1), elt); - ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args)); + ASET (font_style_table, prop - FONT_WEIGHT_INDEX, + Fvconcat (2, ((Lisp_Object []) + { table, Fmake_vector (make_number (1), elt) }))); return (100 << 8) | (i << 4); } else @@ -665,10 +688,6 @@ static const struct { &QCotf, font_prop_validate_otf } }; -/* Size (number of elements) of the above table. */ -#define FONT_PROPERTY_TABLE_SIZE \ - ((sizeof font_property_table) / (sizeof *font_property_table)) - /* Return an index number of font property KEY or -1 if KEY is not an already known property. */ @@ -677,7 +696,7 @@ get_font_prop_index (Lisp_Object key) { int i; - for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++) + for (i = 0; i < ARRAYELTS (font_property_table); i++) if (EQ (key, *font_property_table[i].key)) return i; return -1; @@ -1164,13 +1183,22 @@ font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font) { val = prop[XLFD_ENCODING_INDEX]; if (! NILP (val)) - val = concat2 (build_string ("*-"), SYMBOL_NAME (val)); + { + AUTO_STRING (star_dash, "*-"); + val = concat2 (star_dash, SYMBOL_NAME (val)); + } } else if (NILP (prop[XLFD_ENCODING_INDEX])) - val = concat2 (SYMBOL_NAME (val), build_string ("-*")); + { + AUTO_STRING (dash_star, "-*"); + val = concat2 (SYMBOL_NAME (val), dash_star); + } else - val = concat3 (SYMBOL_NAME (val), build_string ("-"), - SYMBOL_NAME (prop[XLFD_ENCODING_INDEX])); + { + AUTO_STRING (dash, "-"); + val = concat3 (SYMBOL_NAME (val), dash, + SYMBOL_NAME (prop[XLFD_ENCODING_INDEX])); + } if (! NILP (val)) ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil)); @@ -1277,6 +1305,9 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) val = AREF (font, FONT_SIZE_INDEX); eassert (NUMBERP (val) || NILP (val)); + char font_size_index_buf[sizeof "-*" + + max (INT_STRLEN_BOUND (EMACS_INT), + 1 + DBL_MAX_10_EXP + 1)]; if (INTEGERP (val)) { EMACS_INT v = XINT (val); @@ -1284,8 +1315,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) v = pixel_size; if (v > 0) { - f[XLFD_PIXEL_INDEX] = p = - alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT)); + f[XLFD_PIXEL_INDEX] = p = font_size_index_buf; sprintf (p, "%"pI"d-*", v); } else @@ -1294,21 +1324,22 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) else if (FLOATP (val)) { double v = XFLOAT_DATA (val) * 10; - f[XLFD_PIXEL_INDEX] = p = alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP + 1); + f[XLFD_PIXEL_INDEX] = p = font_size_index_buf; sprintf (p, "*-%.0f", v); } else f[XLFD_PIXEL_INDEX] = "*-*"; + char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)]; if (INTEGERP (AREF (font, FONT_DPI_INDEX))) { EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX)); - f[XLFD_RESX_INDEX] = p = - alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)); + f[XLFD_RESX_INDEX] = p = dpi_index_buf; sprintf (p, "%"pI"d-%"pI"d", v, v); } else f[XLFD_RESX_INDEX] = "*-*"; + if (INTEGERP (AREF (font, FONT_SPACING_INDEX))) { EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX)); @@ -1320,13 +1351,16 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes) } else f[XLFD_SPACING_INDEX] = "*"; + + char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)]; if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX))) { - f[XLFD_AVGWIDTH_INDEX] = p = alloca (INT_BUFSIZE_BOUND (EMACS_INT)); + f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf; sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX))); } else f[XLFD_AVGWIDTH_INDEX] = "*"; + len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s", f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX], f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX], @@ -1579,11 +1613,14 @@ font_parse_fcname (char *name, ptrdiff_t len, Lisp_Object font) return 0; } +#if defined HAVE_XFT || defined HAVE_FREETYPE || defined HAVE_NS + /* Store fontconfig's font name of FONT (font-spec or font-entity) in NAME (NBYTES length), and return the name length. If - FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */ + FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. + Return a negative value on error. */ -int +static int font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes) { Lisp_Object family, foundry; @@ -1704,6 +1741,8 @@ font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes) return (p - name); } +#endif + /* Parse NAME (null terminated) and store information in FONT (font-spec or font-entity). If NAME is successfully parsed, return 0. Otherwise return -1. */ @@ -1755,10 +1794,8 @@ font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Objec p1 = strchr (p0, '-'); if (! p1) { - if (SDATA (registry)[len - 1] == '*') - registry = concat2 (registry, build_string ("-*")); - else - registry = concat2 (registry, build_string ("*-*")); + AUTO_STRING (extra, ("*-*" + (len && p0[len - 1] == '*'))); + registry = concat2 (registry, extra); } registry = Fdowncase (registry); ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil)); @@ -2131,10 +2168,14 @@ font_score (Lisp_Object entity, Lisp_Object *spec_prop) lowest bit is set if the DPI is different. */ EMACS_INT diff; EMACS_INT pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]); + EMACS_INT entity_size = XINT (AREF (entity, FONT_SIZE_INDEX)); if (CONSP (Vface_font_rescale_alist)) pixel_size *= font_rescale_ratio (entity); - diff = eabs (pixel_size - XINT (AREF (entity, FONT_SIZE_INDEX))) << 1; + if (pixel_size * 2 < entity_size || entity_size * 2 < pixel_size) + /* This size is wrong by more than a factor 2: reject it! */ + return 0xFFFFFFFF; + diff = eabs (pixel_size - entity_size) << 1; if (! NILP (spec_prop[FONT_DPI_INDEX]) && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX))) diff |= 1; @@ -2154,13 +2195,17 @@ font_score (Lisp_Object entity, Lisp_Object *spec_prop) static Lisp_Object font_vconcat_entity_vectors (Lisp_Object list) { - int nargs = XINT (Flength (list)); - Lisp_Object *args = alloca (word_size * nargs); - int i; + EMACS_INT nargs = XFASTINT (Flength (list)); + Lisp_Object *args; + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (args, nargs); + ptrdiff_t i; for (i = 0; i < nargs; i++, list = XCDR (list)) args[i] = XCAR (list); - return Fvconcat (nargs, args); + Lisp_Object result = Fvconcat (nargs, args); + SAFE_FREE (); + return result; } @@ -2643,7 +2688,7 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size) { Lisp_Object entity, val; enum font_property_index prop; - int i; + ptrdiff_t i; for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--) { @@ -3188,9 +3233,10 @@ font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int val = attrs[LFACE_FAMILY_INDEX]; val = font_intern_prop (SSDATA (val), SBYTES (val), 1); } + Lisp_Object familybuf[3]; if (NILP (val)) { - family = alloca ((sizeof family[0]) * 2); + family = familybuf; family[0] = Qnil; family[1] = zero_vector; /* terminator. */ } @@ -3211,7 +3257,7 @@ font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int } else { - family = alloca ((sizeof family[0]) * 3); + family = familybuf; i = 0; family[i++] = val; if (NILP (AREF (spec, FONT_FAMILY_INDEX))) @@ -3344,7 +3390,6 @@ font_done_for_face (struct frame *f, struct face *face) { if (face->font->driver->done_face) face->font->driver->done_face (f, face); - face->extra = NULL; } @@ -3499,8 +3544,9 @@ font_update_drivers (struct frame *f, Lisp_Object new_drivers) struct font_driver_list **list_table, **next; Lisp_Object tail; int i; + USE_SAFE_ALLOCA; - list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1)); + SAFE_NALLOCA (list_table, 1, num_font_drivers + 1); for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail)) { for (list = f->font_driver_list; list; list = list->next) @@ -3521,6 +3567,7 @@ font_update_drivers (struct frame *f, Lisp_Object new_drivers) next = &(*next)->next; } *next = NULL; + SAFE_FREE (); if (! f->font_driver_list->on) { /* None of the drivers is enabled: enable them all. @@ -3546,53 +3593,40 @@ font_update_drivers (struct frame *f, Lisp_Object new_drivers) return active_drivers; } -int -font_put_frame_data (struct frame *f, struct font_driver *driver, void *data) +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) + +static void +fset_font_data (struct frame *f, Lisp_Object val) { - struct font_data_list *list, *prev; + f->font_data = val; +} - for (prev = NULL, list = f->font_data_list; list; - prev = list, list = list->next) - if (list->driver == driver) - break; - if (! data) - { - if (list) - { - if (prev) - prev->next = list->next; - else - f->font_data_list = list->next; - xfree (list); - } - return 0; - } +void +font_put_frame_data (struct frame *f, Lisp_Object driver, void *data) +{ + Lisp_Object val = assq_no_quit (driver, f->font_data); - if (! list) + if (!data) + fset_font_data (f, Fdelq (val, f->font_data)); + else { - list = xmalloc (sizeof *list); - list->driver = driver; - list->next = f->font_data_list; - f->font_data_list = list; + if (NILP (val)) + fset_font_data (f, Fcons (Fcons (driver, make_save_ptr (data)), + f->font_data)); + else + XSETCDR (val, make_save_ptr (data)); } - list->data = data; - return 0; } - void * -font_get_frame_data (struct frame *f, struct font_driver *driver) +font_get_frame_data (struct frame *f, Lisp_Object driver) { - struct font_data_list *list; - - for (list = f->font_data_list; list; list = list->next) - if (list->driver == driver) - break; - if (! list) - return NULL; - return list->data; + Lisp_Object val = assq_no_quit (driver, f->font_data); + + return NILP (val) ? NULL : XSAVE_POINTER (XCDR (val), 0); } +#endif /* HAVE_XFT || HAVE_FREETYPE */ /* Sets attributes on a font. Any properties that appear in ALIST and BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font. @@ -4235,7 +4269,7 @@ the consecutive wildcards are folded into one. */) { if (NILP (fold_wildcards)) return font_name; - strcpy (name, SSDATA (font_name)); + lispstpcpy (name, font_name); namelen = SBYTES (font_name); goto done; } @@ -4653,9 +4687,10 @@ DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0, doc: /* Return a vector of FONT-OBJECT's glyphs for the specified characters. FROM and TO are positions (integers or markers) specifying a region -of the current buffer. -If the optional fourth arg OBJECT is not nil, it is a string or a -vector containing the target characters. +of the current buffer, and can be in either order. If the optional +fourth arg OBJECT is not nil, it is a string or a vector containing +the target characters between indices FROM and TO, which are treated +as in `substring'. Each element is a vector containing information of a glyph in this format: [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT] @@ -4698,45 +4733,50 @@ the corresponding element is nil. */) else if (STRINGP (object)) { const unsigned char *p; + ptrdiff_t ifrom, ito; - CHECK_NUMBER (from); - CHECK_NUMBER (to); - if (XINT (from) < 0 || XINT (from) > XINT (to) - || XINT (to) > SCHARS (object)) - args_out_of_range_3 (object, from, to); - if (EQ (from, to)) + validate_subarray (object, from, to, SCHARS (object), &ifrom, &ito); + if (ifrom == ito) return Qnil; - len = XFASTINT (to) - XFASTINT (from); + len = ito - ifrom; SAFE_ALLOCA_LISP (chars, len); p = SDATA (object); if (STRING_MULTIBYTE (object)) - for (i = 0; i < len; i++) + { + int c; + + /* Skip IFROM characters from the beginning. */ + for (i = 0; i < ifrom; i++) + c = STRING_CHAR_ADVANCE (p); + + /* Now fetch an interesting characters. */ + for (i = 0; i < len; i++) { - int c = STRING_CHAR_ADVANCE (p); + c = STRING_CHAR_ADVANCE (p); chars[i] = make_number (c); } + } else for (i = 0; i < len; i++) - chars[i] = make_number (p[i]); + chars[i] = make_number (p[ifrom + i]); } - else + else if (VECTORP (object)) { - CHECK_VECTOR (object); - CHECK_NUMBER (from); - CHECK_NUMBER (to); - if (XINT (from) < 0 || XINT (from) > XINT (to) - || XINT (to) > ASIZE (object)) - args_out_of_range_3 (object, from, to); - if (EQ (from, to)) + ptrdiff_t ifrom, ito; + + validate_subarray (object, from, to, ASIZE (object), &ifrom, &ito); + if (ifrom == ito) return Qnil; - len = XFASTINT (to) - XFASTINT (from); + len = ito - ifrom; for (i = 0; i < len; i++) { - Lisp_Object elt = AREF (object, XFASTINT (from) + i); + Lisp_Object elt = AREF (object, ifrom + i); CHECK_CHARACTER (elt); } - chars = aref_addr (object, XFASTINT (from)); + chars = aref_addr (object, ifrom); } + else + wrong_type_argument (Qarrayp, object); vec = make_uninit_vector (len); for (i = 0; i < len; i++) @@ -4938,8 +4978,7 @@ If the named font is not yet loaded, return nil. */) #endif -#define BUILD_STYLE_TABLE(TBL) \ - build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry)) +#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL)) static Lisp_Object build_style_table (const struct table_entry *entry, int nelement) @@ -4989,7 +5028,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) if (FONTP (arg)) { Lisp_Object tail, elt; - Lisp_Object equalstr = build_string ("="); + AUTO_STRING (equal, "="); val = Ffont_xlfd_name (arg, Qt); for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail); @@ -4999,16 +5038,15 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) if (EQ (XCAR (elt), QCscript) && SYMBOLP (XCDR (elt))) val = concat3 (val, SYMBOL_NAME (QCscript), - concat2 (equalstr, SYMBOL_NAME (XCDR (elt)))); + concat2 (equal, SYMBOL_NAME (XCDR (elt)))); else if (EQ (XCAR (elt), QClang) && SYMBOLP (XCDR (elt))) val = concat3 (val, SYMBOL_NAME (QClang), - concat2 (equalstr, SYMBOL_NAME (XCDR (elt)))); + concat2 (equal, SYMBOL_NAME (XCDR (elt)))); else if (EQ (XCAR (elt), QCotf) && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt)))) val = concat3 (val, SYMBOL_NAME (QCotf), - concat2 (equalstr, - SYMBOL_NAME (XCAR (XCDR (elt))))); + concat2 (equal, SYMBOL_NAME (XCAR (XCDR (elt))))); } arg = val; } @@ -5022,8 +5060,11 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result) { val = Ffont_xlfd_name (result, Qt); if (! FONT_SPEC_P (result)) - val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)), - build_string (":"), val); + { + AUTO_STRING (colon, ":"); + val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)), + colon, val); + } result = val; } else if (CONSP (result)) diff --git a/src/font.h b/src/font.h index e2e36460583..52783419ebe 100644 --- a/src/font.h +++ b/src/font.h @@ -162,9 +162,6 @@ enum font_property_index /* List of font-objects opened from the font-entity. */ FONT_OBJLIST_INDEX = FONT_SPEC_MAX, - /* Font-entity from which the font-object is opened. */ - FONT_ENTITY_INDEX = FONT_SPEC_MAX, - /* This value is the length of font-entity vector. */ FONT_ENTITY_MAX, @@ -182,9 +179,6 @@ enum font_property_index is not available. */ FONT_FILE_INDEX, - /* Format of the font (symbol) or nil if unknown. */ - FONT_FORMAT_INDEX, - /* This value is the length of font-object vector. */ FONT_OBJECT_MAX }; @@ -442,15 +436,6 @@ struct font_bitmap #define FONT_OBJECT_P(x) \ (FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX) -/* True iff ENTITY can't be loaded. */ -#define FONT_ENTITY_NOT_LOADABLE(entity) \ - EQ (AREF (entity, FONT_OBJLIST_INDEX), Qt) - -/* Flag ENTITY not loadable. */ -#define FONT_ENTITY_SET_NOT_LOADABLE(entity) \ - ASET (entity, FONT_OBJLIST_INDEX, Qt) - - /* Check macros for various font-related objects. */ #define CHECK_FONT(x) \ @@ -564,11 +549,9 @@ struct font_driver /* Close FONT. NOTE: this can be called by GC. */ void (*close) (struct font *font); - /* Optional (if FACE->extra is not used). - Prepare FACE for displaying characters by FONT on frame F by - storing some data in FACE->extra. If successful, return 0. - Otherwise, return -1. */ - int (*prepare_face) (struct frame *f, struct face *face); + /* Prepare FACE for displaying characters by FONT on frame F by + storing some data in FACE->extra. */ + void (*prepare_face) (struct frame *f, struct face *face); /* Optional. Done FACE for displaying characters by FACE->font on frame F. */ @@ -587,9 +570,9 @@ struct font_driver /* Compute the total metrics of the NGLYPHS glyphs specified by the font FONT and the sequence of glyph codes CODE, and store the result in METRICS. */ - int (*text_extents) (struct font *font, - unsigned *code, int nglyphs, - struct font_metrics *metrics); + void (*text_extents) (struct font *font, + unsigned *code, int nglyphs, + struct font_metrics *metrics); #ifdef HAVE_WINDOW_SYSTEM @@ -616,15 +599,6 @@ struct font_driver #endif /* HAVE_WINDOW_SYSTEM */ /* Optional. - Return an outline data for glyph-code CODE of FONT. The format - of the outline data depends on the font-driver. */ - void *(*get_outline) (struct font *font, unsigned code); - - /* Optional. - Free OUTLINE (that is obtained by the above method). */ - void (*free_outline) (struct font *font, void *outline); - - /* Optional. Get coordinates of the INDEXth anchor point of the glyph whose code is CODE. Store the coordinates in *X and *Y. Return 0 if the operations was successful. Otherwise return -1. */ @@ -725,25 +699,14 @@ struct font_driver_list struct font_driver_list *next; }; - -/* Chain of arbitrary data specific to each font driver. - Each frame has its own font data list at F->font_data_list. */ - -struct font_data_list -{ - /* Pointer to the font driver. */ - struct font_driver *driver; - /* Data specific to the font driver. */ - void *data; - /* Pointer to the next element of the chain. */ - struct font_data_list *next; -}; - extern Lisp_Object copy_font_spec (Lisp_Object); extern Lisp_Object merge_font_spec (Lisp_Object, Lisp_Object); extern Lisp_Object font_make_entity (void); extern Lisp_Object font_make_object (int, Lisp_Object, int); +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) +extern Lisp_Object font_build_object (int, Lisp_Object, Lisp_Object, double); +#endif extern Lisp_Object find_font_encoding (Lisp_Object); extern int font_registry_charsets (Lisp_Object, struct charset **, @@ -789,8 +752,6 @@ extern void font_parse_family_registry (Lisp_Object family, extern int font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font); extern ptrdiff_t font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int bytes); -extern int font_unparse_fcname (Lisp_Object font, int pixel_size, - char *name, int bytes); extern void register_font_driver (struct font_driver *driver, struct frame *f); extern void free_font_driver_list (struct frame *f); #ifdef ENABLE_CHECKING @@ -811,11 +772,10 @@ extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object); extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val); -extern int font_put_frame_data (struct frame *f, - struct font_driver *driver, - void *data); -extern void *font_get_frame_data (struct frame *f, - struct font_driver *driver); +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) +extern void font_put_frame_data (struct frame *, Lisp_Object, void *); +extern void *font_get_frame_data (struct frame *f, Lisp_Object); +#endif /* HAVE_XFT || HAVE_FREETYPE */ extern void font_filter_properties (Lisp_Object font, Lisp_Object alist, @@ -834,7 +794,8 @@ extern void syms_of_ftxfont (void); extern Lisp_Object Qxft; extern struct font_driver xftfont_driver; extern void syms_of_xftfont (void); -#elif defined HAVE_FREETYPE +#endif +#if defined HAVE_FREETYPE || defined HAVE_XFT extern struct font_driver ftxfont_driver; #endif #ifdef HAVE_BDFFONT diff --git a/src/fontset.c b/src/fontset.c index 08413ae1571..c415fdfa8fd 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -209,27 +209,27 @@ set_fontset_name (Lisp_Object fontset, Lisp_Object name) set_char_table_extras (fontset, 1, name); } -#define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->extras[4] +#define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->extras[2] static void set_fontset_ascii (Lisp_Object fontset, Lisp_Object ascii) { - set_char_table_extras (fontset, 4, ascii); + set_char_table_extras (fontset, 2, ascii); } /* Access special values of (realized) FONTSET. */ -#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->extras[2] +#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->extras[3] static void set_fontset_base (Lisp_Object fontset, Lisp_Object base) { - set_char_table_extras (fontset, 2, base); + set_char_table_extras (fontset, 3, base); } -#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[3] +#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[4] static void set_fontset_frame (Lisp_Object fontset, Lisp_Object frame) { - set_char_table_extras (fontset, 3, frame); + set_char_table_extras (fontset, 4, frame); } #define FONTSET_NOFONT_FACE(fontset) XCHAR_TABLE (fontset)->extras[5] @@ -239,20 +239,20 @@ set_fontset_nofont_face (Lisp_Object fontset, Lisp_Object face) set_char_table_extras (fontset, 5, face); } -#define FONTSET_DEFAULT(fontset) XCHAR_TABLE (fontset)->extras[7] +#define FONTSET_DEFAULT(fontset) XCHAR_TABLE (fontset)->extras[6] static void set_fontset_default (Lisp_Object fontset, Lisp_Object def) { - set_char_table_extras (fontset, 7, def); + set_char_table_extras (fontset, 6, def); } /* For both base and realized fontset. */ -#define FONTSET_FALLBACK(fontset) XCHAR_TABLE (fontset)->extras[8] +#define FONTSET_FALLBACK(fontset) XCHAR_TABLE (fontset)->extras[7] static void set_fontset_fallback (Lisp_Object fontset, Lisp_Object fallback) { - set_char_table_extras (fontset, 8, fallback); + set_char_table_extras (fontset, 7, fallback); } #define BASE_FONTSET_P(fontset) (NILP (FONTSET_BASE (fontset))) @@ -852,21 +852,6 @@ fontset_ascii (int id) return elt; } -static void -free_realized_fontset (struct frame *f, Lisp_Object fontset) -{ -#if 0 - Lisp_Object tail; - - if (0) - for (tail = FONTSET_OBJLIST (fontset); CONSP (tail); tail = XCDR (tail)) - { - eassert (FONT_OBJECT_P (XCAR (tail))); - font_close_object (f, XCAR (tail)); - } -#endif -} - /* Free fontset of FACE defined on frame F. Called from free_realized_face. */ @@ -880,7 +865,6 @@ free_face_fontset (struct frame *f, struct face *face) return; eassert (! BASE_FONTSET_P (fontset)); eassert (f == XFRAME (FONTSET_FRAME (fontset))); - free_realized_fontset (f, fontset); ASET (Vfontset_table, face->fontset, Qnil); if (face->fontset < next_fontset_id) next_fontset_id = face->fontset; @@ -891,7 +875,6 @@ free_face_fontset (struct frame *f, struct face *face) fontset = AREF (Vfontset_table, id); eassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset)); eassert (f == XFRAME (FONTSET_FRAME (fontset))); - free_realized_fontset (f, fontset); ASET (Vfontset_table, id, Qnil); if (id < next_fontset_id) next_fontset_id = face->fontset; @@ -1096,10 +1079,11 @@ fontset_pattern_regexp (Lisp_Object pattern) /* If PATTERN is not full XLFD we convert "*" to ".*". Otherwise we convert "*" to "[^-]*" which is much faster in regular expression matching. */ - if (ndashes < 14) - p1 = regex = alloca (SBYTES (pattern) + 2 * nstars + 2 * nescs + 1); - else - p1 = regex = alloca (SBYTES (pattern) + 5 * nstars + 2 * nescs + 1); + ptrdiff_t regexsize = (SBYTES (pattern) + + (ndashes < 14 ? 2 : 5) * nstars + + 2 * nescs + 1); + USE_SAFE_ALLOCA; + p1 = regex = SAFE_ALLOCA (regexsize); *p1++ = '^'; for (p0 = SDATA (pattern); *p0; p0++) @@ -1127,6 +1111,7 @@ fontset_pattern_regexp (Lisp_Object pattern) Vcached_fontset_data = Fcons (build_string (SSDATA (pattern)), build_string ((char *) regex)); + SAFE_FREE (); } return CACHED_FONTSET_REGEX; @@ -1477,8 +1462,8 @@ appended. By default, FONT-SPEC overrides the previous settings. */) registry = AREF (font_spec, FONT_REGISTRY_INDEX); if (! NILP (registry)) registry = Fdowncase (SYMBOL_NAME (registry)); - encoding = find_font_encoding (concat3 (family, build_string ("-"), - registry)); + AUTO_STRING (dash, "-"); + encoding = find_font_encoding (concat3 (family, dash, registry)); if (NILP (encoding)) encoding = Qascii; @@ -1590,7 +1575,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */) if (ascii_changed) { - Lisp_Object tail, fr, alist; + Lisp_Object tail, fr; int fontset_id = XINT (FONTSET_ID (fontset)); set_fontset_ascii (fontset, fontname); @@ -1613,8 +1598,8 @@ appended. By default, FONT-SPEC overrides the previous settings. */) if (! NILP (font_object)) { update_auto_fontset_alist (font_object, fontset); - alist = list1 (Fcons (Qfont, Fcons (name, font_object))); - Fmodify_frame_parameters (fr, alist); + AUTO_FRAME_ARG (arg, Qfont, Fcons (name, font_object)); + Fmodify_frame_parameters (fr, arg); } } } @@ -1909,7 +1894,9 @@ format is the same as above. */) /* Recode fontsets realized on FRAME from the base fontset FONTSET in the table `realized'. */ - realized[0] = alloca (word_size * ASIZE (Vfontset_table)); + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (realized[0], 2 * ASIZE (Vfontset_table)); + realized[1] = realized[0] + ASIZE (Vfontset_table); for (i = j = 0; i < ASIZE (Vfontset_table); i++) { elt = FONTSET_FROM_ID (i); @@ -1920,7 +1907,6 @@ format is the same as above. */) } realized[0][j] = Qnil; - realized[1] = alloca (word_size * ASIZE (Vfontset_table)); for (i = j = 0; ! NILP (realized[0][i]); i++) { elt = FONTSET_DEFAULT (realized[0][i]); @@ -2012,6 +1998,7 @@ format is the same as above. */) break; } + SAFE_FREE (); return tables[0]; } @@ -2163,7 +2150,7 @@ void syms_of_fontset (void) { DEFSYM (Qfontset, "fontset"); - Fput (Qfontset, Qchar_table_extra_slots, make_number (9)); + Fput (Qfontset, Qchar_table_extra_slots, make_number (8)); DEFSYM (Qfontset_info, "fontset-info"); Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1)); diff --git a/src/frame.c b/src/frame.c index e894d218df7..8fac06e2af7 100644 --- a/src/frame.c +++ b/src/frame.c @@ -51,6 +51,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "msdos.h" #include "dosfns.h" #endif +#ifdef USE_X_TOOLKIT +#include "widget.h" +#endif #ifdef HAVE_NS Lisp_Object Qns_parse_geometry; @@ -75,7 +78,6 @@ Lisp_Object Qauto_raise, Qauto_lower; Lisp_Object Qborder_color, Qborder_width; Lisp_Object Qcursor_color, Qcursor_type; Lisp_Object Qheight, Qwidth; -Lisp_Object Qleft, Qright; Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name; Lisp_Object Qtooltip; Lisp_Object Qinternal_border_width; @@ -83,6 +85,7 @@ Lisp_Object Qright_divider_width, Qbottom_divider_width; Lisp_Object Qmouse_color; Lisp_Object Qminibuffer; Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars; +Lisp_Object Qscroll_bar_height, Qhorizontal_scroll_bars; Lisp_Object Qvisibility; Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background; Lisp_Object Qscreen_gamma; @@ -114,7 +117,7 @@ Lisp_Object Qface_set_after_frame_default; static Lisp_Object Qfocus_in_hook; static Lisp_Object Qfocus_out_hook; static Lisp_Object Qdelete_frame_functions; - +static Lisp_Object Qframe_windows_min_size; static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource; /* The currently selected frame. */ @@ -163,19 +166,16 @@ decode_any_frame (register Lisp_Object frame) return XFRAME (frame); } +#ifdef HAVE_WINDOW_SYSTEM + bool window_system_available (struct frame *f) { - if (f) - return FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f); - else -#ifdef HAVE_WINDOW_SYSTEM - return x_display_list != NULL; -#else - return 0; -#endif + return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL; } +#endif /* HAVE_WINDOW_SYSTEM */ + struct frame * decode_window_system_frame (Lisp_Object frame) { @@ -194,30 +194,32 @@ check_window_system (struct frame *f) : "Window system is not in use or not initialized"); } -static void -set_menu_bar_lines_1 (Lisp_Object window, int n) +/* Return the value of frame parameter PROP in frame FRAME. */ + +Lisp_Object +get_frame_param (register struct frame *frame, Lisp_Object prop) { - struct window *w = XWINDOW (window); - struct frame *f = XFRAME (WINDOW_FRAME (w)); - - w->top_line += n; - w->pixel_top += n * FRAME_LINE_HEIGHT (f); - w->total_lines -= n; - w->pixel_height -= n * FRAME_LINE_HEIGHT (f); - - /* Handle just the top child in a vertical split. */ - if (WINDOW_VERTICAL_COMBINATION_P (w)) - set_menu_bar_lines_1 (w->contents, n); - else if (WINDOW_HORIZONTAL_COMBINATION_P (w)) - /* Adjust all children in a horizontal split. */ - for (window = w->contents; !NILP (window); window = w->next) - { - w = XWINDOW (window); - set_menu_bar_lines_1 (window, n); - } + register Lisp_Object tem; + + tem = Fassq (prop, frame->param_alist); + if (EQ (tem, Qnil)) + return tem; + return Fcdr (tem); } -void +/* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen + state of frame F would be affected by a vertical (horizontal if + HORIZONTAL is true) resize. */ +bool +frame_inhibit_resize (struct frame *f, bool horizontal) +{ + + return (frame_inhibit_implied_resize + || !NILP (get_frame_param (f, Qfullscreen)) + || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)); +} + +static void set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { int nlines; @@ -238,11 +240,11 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) if (nlines != olines) { windows_or_buffers_changed = 14; - FRAME_WINDOW_SIZES_CHANGED (f) = 1; FRAME_MENU_BAR_LINES (f) = nlines; FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - set_menu_bar_lines_1 (f->root_window, nlines - olines); - adjust_frame_glyphs (f); + change_frame_size (f, FRAME_COLS (f), + FRAME_LINES (f) + olines - nlines, + 0, 1, 0, 0); } } @@ -325,6 +327,247 @@ predicates which report frame's specific UI-related capabilities. */) return type; } +static int +frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, Lisp_Object pixelwise) +{ + return XINT (call3 (Qframe_windows_min_size, frame, horizontal, pixelwise)); +} + + +/* Make sure windows sizes of frame F are OK. new_width and new_height + are in pixels. A value of -1 means no change is requested for that + size (but the frame may still have to be resized to accommodate + windows with their minimum sizes. + + The argument INHIBIT can assume the following values: + + 0 means to unconditionally call x_set_window_size even if sizes + apparently do not change. Fx_create_frame uses this to pass the + initial size to the window manager. + + 1 means to call x_set_window_size iff the pixel size really changes. + Fset_frame_size, Fset_frame_height, ... use this. + + 2 means to unconditionally call x_set_window_size provided + frame_inhibit_resize allows it. The menu bar code uses this. + + 3 means call x_set_window_size iff window minimum sizes must be + preserved or frame_inhibit_resize allows it, x_set_left_fringe, + x_set_scroll_bar_width, ... use this. + + 4 means call x_set_window_size iff window minimum sizes must be + preserved. x_set_tool_bar_lines, x_set_right_divider_width, ... use + this. BUT maybe the toolbar code shouldn't .... + + 5 means to never call x_set_window_size. change_frame_size uses + this. + + For 2 and 3 note that if frame_inhibit_resize inhibits resizing and + minimum sizes are not violated no internal resizing takes place + either. For 2, 3, 4 and 5 note that even if no x_set_window_size + call is issued, window sizes may have to be adjusted in order to + support minimum size constraints for the frame's windows. + + PRETEND is as for change_frame_size. */ +void +adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, bool pretend) +{ + int unit_width = FRAME_COLUMN_WIDTH (f); + int unit_height = FRAME_LINE_HEIGHT (f); + int old_pixel_width = FRAME_PIXEL_WIDTH (f); + int old_pixel_height = FRAME_PIXEL_HEIGHT (f); + int new_pixel_width, new_pixel_height; + /* The following two values are calculated from the old frame pixel + sizes and any "new" settings for tool bar, menu bar and internal + borders. We do it this way to detect whether we have to call + x_set_window_size as consequence of the new settings. */ + int windows_width = FRAME_WINDOWS_WIDTH (f); + int windows_height = FRAME_WINDOWS_HEIGHT (f); + int min_windows_width, min_windows_height; + /* These are a bit tedious, maybe we should use a macro. */ + struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f)); + int old_windows_width = WINDOW_PIXEL_WIDTH (r); + int old_windows_height + = (WINDOW_PIXEL_HEIGHT (r) + + (FRAME_HAS_MINIBUF_P (f) + ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f))) + : 0)); + int new_windows_width, new_windows_height; + int old_text_width = FRAME_TEXT_WIDTH (f); + int old_text_height = FRAME_TEXT_HEIGHT (f); + /* If a size is < 0 use the old value. */ + int new_text_width = (new_width >= 0) ? new_width : old_text_width; + int new_text_height = (new_height >= 0) ? new_height : old_text_height; + int new_cols, new_lines; + bool inhibit_horizontal, inhibit_vertical; + Lisp_Object frame; + + XSETFRAME (frame, f); + /* The following two values are calculated from the old window body + sizes and any "new" settings for scroll bars, dividers, fringes and + margins (though the latter should have been processed already). */ + min_windows_width = frame_windows_min_size (frame, Qt, Qt); + min_windows_height = frame_windows_min_size (frame, Qnil, Qt); + + if (inhibit >= 2 && inhibit <= 4) + /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay + within the limits and either frame_inhibit_resize tells us to do + so or INHIBIT equals 4. */ + { + inhibit_horizontal = ((windows_width >= min_windows_width + && (inhibit == 4 || frame_inhibit_resize (f, true))) + ? true : false); + inhibit_vertical = ((windows_height >= min_windows_height + && (inhibit == 4 || frame_inhibit_resize (f, false))) + ? true : false); + } + else + /* Otherwise inhibit if INHIBIT equals 5. */ + inhibit_horizontal = inhibit_vertical = inhibit == 5; + + new_pixel_width = ((inhibit_horizontal && (inhibit < 5)) + ? old_pixel_width + : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width), + min_windows_width + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); + new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f); + new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width); + new_cols = new_text_width / unit_width; + + new_pixel_height = ((inhibit_vertical && (inhibit < 5)) + ? old_pixel_height + : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height), + min_windows_height + + FRAME_TOP_MARGIN_HEIGHT (f) + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); + new_windows_height = (new_pixel_height + - FRAME_TOP_MARGIN_HEIGHT (f) + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height); + new_lines = new_text_height / unit_height; + +#ifdef HAVE_WINDOW_SYSTEM + if (FRAME_WINDOW_P (f) + && f->official + && ((!inhibit_horizontal + && (new_pixel_width != old_pixel_width + || inhibit == 0 || inhibit == 2)) + || (!inhibit_vertical + && (new_pixel_height != old_pixel_height + || inhibit == 0 || inhibit == 2)))) + /* We are either allowed to change the frame size or the minimum + sizes request such a change. Do not care for fixing minimum + sizes here, we do that eventually when we're called from + change_frame_size. */ + { + /* Make sure we respect fullheight and fullwidth. */ + if (inhibit_horizontal) + new_text_width = old_text_width; + else if (inhibit_vertical) + new_text_height = old_text_height; + + x_set_window_size (f, 0, new_text_width, new_text_height, 1); + f->resized_p = true; + + return; + } +#endif + + if (new_text_width == old_text_width + && new_text_height == old_text_height + && new_windows_width == old_windows_width + && new_windows_height == old_windows_height + && new_pixel_width == old_pixel_width + && new_pixel_height == old_pixel_height) + /* No change. Sanitize window sizes and return. */ + { + sanitize_window_sizes (frame, Qt); + sanitize_window_sizes (frame, Qnil); + + return; + } + + block_input (); + +#ifdef MSDOS + /* We only can set screen dimensions to certain values supported + by our video hardware. Try to find the smallest size greater + or equal to the requested dimensions. */ + dos_set_window_size (&new_lines, &new_cols); +#endif + + if (new_windows_width != old_windows_width) + { + resize_frame_windows (f, new_windows_width, 1, 1); + + /* MSDOS frames cannot PRETEND, as they change frame size by + manipulating video hardware. */ + if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) + FrameCols (FRAME_TTY (f)) = new_cols; + +#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) + if (WINDOWP (f->tool_bar_window)) + { + XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width; + XWINDOW (f->tool_bar_window)->total_cols + = new_windows_width / unit_width; + } +#endif + } + + if (new_windows_height != old_windows_height + /* When the top margin has changed we have to recalculate the top + edges of all windows. No such calculation is necessary for the + left edges. */ + || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f)) + { + resize_frame_windows (f, new_windows_height, 0, 1); + + /* MSDOS frames cannot PRETEND, as they change frame size by + manipulating video hardware. */ + if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) + FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f); + } + + /* Assign new sizes. */ + FRAME_TEXT_WIDTH (f) = new_text_width; + FRAME_TEXT_HEIGHT (f) = new_text_height; + FRAME_PIXEL_WIDTH (f) = new_pixel_width; + FRAME_PIXEL_HEIGHT (f) = new_pixel_height; + SET_FRAME_COLS (f, new_cols); + SET_FRAME_LINES (f, new_lines); + + { + struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); + int text_area_x, text_area_y, text_area_width, text_area_height; + + window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width, + &text_area_height); + if (w->cursor.x >= text_area_x + text_area_width) + w->cursor.hpos = w->cursor.x = 0; + if (w->cursor.y >= text_area_y + text_area_height) + w->cursor.vpos = w->cursor.y = 0; + } + + /* Sanitize window sizes. */ + sanitize_window_sizes (frame, Qt); + sanitize_window_sizes (frame, Qnil); + + adjust_frame_glyphs (f); + calculate_costs (f); + SET_FRAME_GARBAGED (f); + + /* A frame was "resized" if one of its pixelsizes changed, even if its + X window wasn't resized at all. */ + f->resized_p = (new_pixel_width != old_pixel_width + || new_pixel_height != old_pixel_height); + + unblock_input (); + + run_window_configuration_change_hook (f); +} + + struct frame * make_frame (bool mini_p) { @@ -337,9 +580,11 @@ make_frame (bool mini_p) f = allocate_frame (); XSETFRAME (frame, f); +#ifdef USE_GTK /* Initialize Lisp data. Note that allocate_frame initializes all Lisp data to nil, so do it only for slots which should not be nil. */ fset_tool_bar_position (f, Qtop); +#endif /* Initialize non-Lisp data. Note that allocate_frame zeroes out all non-Lisp data, so do it only for slots which should not be zero. @@ -348,11 +593,16 @@ make_frame (bool mini_p) f->wants_modeline = true; f->redisplay = true; f->garbaged = true; - f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->official = false; f->column_width = 1; /* !FRAME_WINDOW_P value. */ f->line_height = 1; /* !FRAME_WINDOW_P value. */ #ifdef HAVE_WINDOW_SYSTEM + f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->horizontal_scroll_bars = false; f->want_fullscreen = FULLSCREEN_NONE; +#if ! defined (USE_GTK) && ! defined (HAVE_NS) + f->last_tool_bar_item = -1; +#endif #endif root_window = make_window (); @@ -378,10 +628,10 @@ make_frame (bool mini_p) /* 10 is arbitrary, just so that there is "something there." - Correct size will be set up later with change_frame_size. */ + Correct size will be set up later with adjust_frame_size. */ SET_FRAME_COLS (f, 10); - FRAME_LINES (f) = 10; + SET_FRAME_LINES (f, 10); SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f)); SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f)); @@ -419,11 +669,15 @@ make_frame (bool mini_p) } if (mini_p) - set_window_buffer (mini_window, - (NILP (Vminibuffer_list) - ? get_minibuffer (0) - : Fcar (Vminibuffer_list)), - 0, 0); + { + set_window_buffer (mini_window, + (NILP (Vminibuffer_list) + ? get_minibuffer (0) + : Fcar (Vminibuffer_list)), + 0, 0); + /* No horizontal scroll bars in minibuffers. */ + wset_horizontal_scroll_bar (mw, Qnil); + } fset_root_window (f, root_window); fset_selected_window (f, root_window); @@ -567,7 +821,10 @@ make_initial_frame (void) FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR; FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; - FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; +#ifdef HAVE_WINDOW_SYSTEM + f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->horizontal_scroll_bars = false; +#endif /* The default value of menu-bar-mode is t. */ set_menu_bar_lines (f, make_number (1), Qnil); @@ -617,9 +874,15 @@ make_terminal_frame (struct terminal *terminal) FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; #endif /* not MSDOS */ - FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; +#ifdef HAVE_WINDOW_SYSTEM + f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->horizontal_scroll_bars = false; +#endif + FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1; + FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f); FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); + FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f); /* Set the top frame to the newly created frame. */ if (FRAMEP (FRAME_TTY (f)->top_frame) @@ -701,7 +964,7 @@ affects all frames on the same terminal device. */) if (CONSP (terminal)) { terminal = XCDR (terminal); - t = get_terminal (terminal, 1); + t = decode_live_terminal (terminal); } #ifdef MSDOS if (t && t != the_only_display_info.terminal) @@ -716,22 +979,24 @@ affects all frames on the same terminal device. */) { char *name = 0, *type = 0; Lisp_Object tty, tty_type; + USE_SAFE_ALLOCA; tty = get_future_frame_param (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame)) ? FRAME_TTY (XFRAME (selected_frame))->name : NULL)); if (!NILP (tty)) - name = xlispstrdupa (tty); + SAFE_ALLOCA_STRING (name, tty); tty_type = get_future_frame_param (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame)) ? FRAME_TTY (XFRAME (selected_frame))->type : NULL)); if (!NILP (tty_type)) - type = xlispstrdupa (tty_type); + SAFE_ALLOCA_STRING (type, tty_type); t = init_tty (name, type, 0); /* Errors are not fatal. */ + SAFE_FREE (); } f = make_terminal_frame (t); @@ -739,7 +1004,7 @@ affects all frames on the same terminal device. */) { int width, height; get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); - change_frame_size (f, width, height, 0, 0, 0, 0); + adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0); } adjust_frame_glyphs (f); @@ -870,8 +1135,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor frame's data. */ if (FRAME_COLS (f) != FrameCols (tty)) FrameCols (tty) = FRAME_COLS (f); - if (FRAME_LINES (f) != FrameRows (tty)) - FrameRows (tty) = FRAME_LINES (f); + if (FRAME_TOTAL_LINES (f) != FrameRows (tty)) + FrameRows (tty) = FRAME_TOTAL_LINES (f); } tty->top_frame = frame; } @@ -1365,7 +1630,9 @@ delete_frame (Lisp_Object frame, Lisp_Object force) fset_buried_buffer_list (f, Qnil); free_font_driver_list (f); +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) xfree (f->namebuf); +#endif xfree (f->decode_mode_spec_buffer); xfree (FRAME_INSERT_COST (f)); xfree (FRAME_DELETEN_COST (f)); @@ -1608,6 +1875,42 @@ and nil for X and Y. */) RETURN_UNGCPRO (retval); } +#ifdef HAVE_WINDOW_SYSTEM + +/* On frame F, convert character coordinates X and Y to pixel + coordinates *PIX_X and *PIX_Y. */ + +static void +frame_char_to_pixel_position (struct frame *f, int x, int y, + int *pix_x, int *pix_y) +{ + *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; + *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; + + if (*pix_x < 0) + *pix_x = 0; + if (*pix_x > FRAME_PIXEL_WIDTH (f)) + *pix_x = FRAME_PIXEL_WIDTH (f); + + if (*pix_y < 0) + *pix_y = 0; + if (*pix_y > FRAME_PIXEL_HEIGHT (f)) + *pix_y = FRAME_PIXEL_HEIGHT (f); +} + +/* On frame F, reposition mouse pointer to character coordinates X and Y. */ + +static void +frame_set_mouse_position (struct frame *f, int x, int y) +{ + int pix_x, pix_y; + + frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y); + frame_set_mouse_pixel_position (f, pix_x, pix_y); +} + +#endif /* HAVE_WINDOW_SYSTEM */ + DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0, doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME. Coordinates are relative to the frame, not a window, @@ -1633,7 +1936,7 @@ before calling this function on it, like this. #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (frame))) /* Warping the mouse will cause enternotify and focus events. */ - x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y)); + frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y)); #else #if defined (MSDOS) if (FRAME_MSDOS_P (XFRAME (frame))) @@ -1674,7 +1977,7 @@ before calling this function on it, like this. #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (frame))) /* Warping the mouse will cause enternotify and focus events. */ - x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y)); + frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y)); #else #if defined (MSDOS) if (FRAME_MSDOS_P (XFRAME (frame))) @@ -1942,24 +2245,6 @@ If there is no window system support, this function does nothing. */) } -/* Return the value of frame parameter PROP in frame FRAME. */ - -#ifdef HAVE_WINDOW_SYSTEM -#if !HAVE_NS && !HAVE_NTGUI -static -#endif -Lisp_Object -get_frame_param (register struct frame *frame, Lisp_Object prop) -{ - register Lisp_Object tem; - - tem = Fassq (prop, frame->param_alist); - if (EQ (tem, Qnil)) - return tem; - return Fcdr (tem); -} -#endif - /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */ void @@ -2043,20 +2328,6 @@ set_term_frame_name (struct frame *f, Lisp_Object name) update_mode_lines = 16; } -#ifdef HAVE_NTGUI -void -set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) -{ - register Lisp_Object old_alist_elt; - - old_alist_elt = Fassq (prop, f->param_alist); - if (EQ (old_alist_elt, Qnil)) - fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist)); - else - Fsetcdr (old_alist_elt, val); -} -#endif - void store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) { @@ -2148,6 +2419,18 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) } } +/* Return color matches UNSPEC on frame F or nil if UNSPEC + is not an unspecified foreground or background color. */ + +static Lisp_Object +frame_unspecified_color (struct frame *f, Lisp_Object unspec) +{ + return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec)) + ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)) + : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec)) + ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil)); +} + DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0, doc: /* Return the parameters-alist of frame FRAME. It is a list of elements of the form (PARM . VALUE), where PARM is a symbol. @@ -2168,8 +2451,6 @@ If FRAME is omitted or nil, return information on the currently selected frame. if (!FRAME_WINDOW_P (f)) { - int fg = FRAME_FOREGROUND_PIXEL (f); - int bg = FRAME_BACKGROUND_PIXEL (f); Lisp_Object elt; /* If the frame's parameter alist says the colors are @@ -2178,31 +2459,23 @@ If FRAME is omitted or nil, return information on the currently selected frame. elt = Fassq (Qforeground_color, alist); if (CONSP (elt) && STRINGP (XCDR (elt))) { - if (strncmp (SSDATA (XCDR (elt)), - unspecified_bg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg)); - else if (strncmp (SSDATA (XCDR (elt)), - unspecified_fg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg)); + elt = frame_unspecified_color (f, XCDR (elt)); + if (!NILP (elt)) + store_in_alist (&alist, Qforeground_color, elt); } else - store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg)); + store_in_alist (&alist, Qforeground_color, + tty_color_name (f, FRAME_FOREGROUND_PIXEL (f))); elt = Fassq (Qbackground_color, alist); if (CONSP (elt) && STRINGP (XCDR (elt))) { - if (strncmp (SSDATA (XCDR (elt)), - unspecified_fg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg)); - else if (strncmp (SSDATA (XCDR (elt)), - unspecified_bg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg)); + elt = frame_unspecified_color (f, XCDR (elt)); + if (!NILP (elt)) + store_in_alist (&alist, Qbackground_color, elt); } else - store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg)); + store_in_alist (&alist, Qbackground_color, + tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))); store_in_alist (&alist, intern ("font"), build_string (FRAME_MSDOS_P (f) ? "ms-dos" @@ -2282,29 +2555,7 @@ If FRAME is nil, describe the currently selected frame. */) important when param_alist's notion of colors is "unspecified". We need to do the same here. */ if (STRINGP (value) && !FRAME_WINDOW_P (f)) - { - const char *color_name; - ptrdiff_t csz; - - if (EQ (parameter, Qbackground_color)) - { - color_name = SSDATA (value); - csz = SCHARS (value); - if (strncmp (color_name, unspecified_bg, csz) == 0) - value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)); - else if (strncmp (color_name, unspecified_fg, csz) == 0) - value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)); - } - else if (EQ (parameter, Qforeground_color)) - { - color_name = SSDATA (value); - csz = SCHARS (value); - if (strncmp (color_name, unspecified_fg, csz) == 0) - value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)); - else if (strncmp (color_name, unspecified_bg, csz) == 0) - value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)); - } - } + value = frame_unspecified_color (f, value); } else value = Fcdr (Fassq (parameter, Fframe_parameters (frame))); @@ -2455,7 +2706,7 @@ to `frame-height'). */) return make_number (FRAME_PIXEL_HEIGHT (f)); else #endif - return make_number (FRAME_LINES (f)); + return make_number (FRAME_TOTAL_LINES (f)); } DEFUN ("frame-pixel-width", Fframe_pixel_width, @@ -2472,7 +2723,7 @@ If FRAME is omitted or nil, the selected frame is used. */) return make_number (FRAME_PIXEL_WIDTH (f)); else #endif - return make_number (FRAME_COLS (f)); + return make_number (FRAME_TOTAL_COLS (f)); } DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width, @@ -2507,12 +2758,19 @@ DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0, } DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0, - doc: /* Return total columns of FRAME. */) + doc: /* Return number of total columns of FRAME. */) (Lisp_Object frame) { return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame))); } +DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0, + doc: /* Return number of total lines of FRAME. */) + (Lisp_Object frame) +{ + return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame))); +} + DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0, doc: /* Return text area width of FRAME in pixels. */) (Lisp_Object frame) @@ -2534,6 +2792,13 @@ DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0, return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame))); } +DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0, + doc: /* Return scroll bar height of FRAME in pixels. */) + (Lisp_Object frame) +{ + return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame))); +} + DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0, doc: /* Return fringe width of FRAME in pixels. */) (Lisp_Object frame) @@ -2561,7 +2826,7 @@ DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_widt { return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame))); } - + DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0, doc: /* Specify that the frame FRAME has HEIGHT text lines. Optional third arg PRETEND non-nil means that redisplay should use @@ -2570,31 +2835,17 @@ not be changed. Optional fourth argument PIXELWISE non-nil means that FRAME should be HEIGHT pixels high. */) (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise) { - register struct frame *f = decode_live_frame (frame); + struct frame *f = decode_live_frame (frame); + int pixel_height; CHECK_TYPE_RANGED_INTEGER (int, height); - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - { - if (NILP (pixelwise)) - { - if (XINT (height) != FRAME_LINES (f)) - x_set_window_size (f, 1, FRAME_COLS (f), XINT (height), 0); + pixel_height = (!NILP (pixelwise) + ? XINT (height) + : XINT (height) * FRAME_LINE_HEIGHT (f)); + if (pixel_height != FRAME_TEXT_HEIGHT (f)) + adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend)); - do_pending_window_change (0); - } - else if (XINT (height) != FRAME_TEXT_HEIGHT (f)) - { - x_set_window_size (f, 1, FRAME_TEXT_WIDTH (f), XINT (height), 1); - do_pending_window_change (0); - } - } - else -#endif - change_frame_size (f, 0, XINT (height), !NILP (pretend), 0, 0, - NILP (pixelwise) ? 0 : 1); return Qnil; } @@ -2606,31 +2857,17 @@ be changed. Optional fourth argument PIXELWISE non-nil means that FRAME should be WIDTH pixels wide. */) (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise) { - register struct frame *f = decode_live_frame (frame); + struct frame *f = decode_live_frame (frame); + int pixel_width; CHECK_TYPE_RANGED_INTEGER (int, width); - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - { - if (NILP (pixelwise)) - { - if (XINT (width) != FRAME_COLS (f)) - x_set_window_size (f, 1, XINT (width), FRAME_LINES (f), 0); + pixel_width = (!NILP (pixelwise) + ? XINT (width) + : XINT (width) * FRAME_COLUMN_WIDTH (f)); + if (pixel_width != FRAME_TEXT_WIDTH (f)) + adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend)); - do_pending_window_change (0); - } - else if (XINT (width) != FRAME_TEXT_WIDTH (f)) - { - x_set_window_size (f, 1, XINT (width), FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); - } - } - else -#endif - change_frame_size (f, XINT (width), 0, !NILP (pretend), 0, 0, - NILP (pixelwise) ? 0 : 1); return Qnil; } @@ -2639,32 +2876,22 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0, Optional argument PIXELWISE non-nil means to measure in pixels. */) (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise) { - register struct frame *f = decode_live_frame (frame); + struct frame *f = decode_live_frame (frame); + int pixel_width, pixel_height; CHECK_TYPE_RANGED_INTEGER (int, width); CHECK_TYPE_RANGED_INTEGER (int, height); - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - { - if (!NILP (pixelwise) - ? (XINT (width) != FRAME_TEXT_WIDTH (f) - || XINT (height) != FRAME_TEXT_HEIGHT (f) - || f->new_height || f->new_width) - : (XINT (width) != FRAME_COLS (f) - || XINT (height) != FRAME_LINES (f) - || f->new_height || f->new_width)) - { - x_set_window_size (f, 1, XINT (width), XINT (height), - NILP (pixelwise) ? 0 : 1); - do_pending_window_change (0); - } - } - else -#endif - change_frame_size (f, XINT (width), XINT (height), 0, 0, 0, - NILP (pixelwise) ? 0 : 1); + pixel_width = (!NILP (pixelwise) + ? XINT (width) + : XINT (width) * FRAME_COLUMN_WIDTH (f)); + pixel_height = (!NILP (pixelwise) + ? XINT (height) + : XINT (height) * FRAME_LINE_HEIGHT (f)); + + if (pixel_width != FRAME_TEXT_WIDTH (f) + || pixel_height != FRAME_TEXT_HEIGHT (f)) + adjust_frame_size (f, pixel_width, pixel_height, 1, 0); return Qnil; } @@ -2729,9 +2956,11 @@ static const struct frame_parm_table frame_parms[] = {"mouse-color", &Qmouse_color}, {"name", &Qname}, {"scroll-bar-width", &Qscroll_bar_width}, + {"scroll-bar-height", &Qscroll_bar_height}, {"title", &Qtitle}, {"unsplittable", &Qunsplittable}, {"vertical-scroll-bars", &Qvertical_scroll_bars}, + {"horizontal-scroll-bars", &Qhorizontal_scroll_bars}, {"visibility", &Qvisibility}, {"tool-bar-lines", &Qtool_bar_lines}, {"scroll-bar-foreground", &Qscroll_bar_foreground}, @@ -2748,52 +2977,6 @@ static const struct frame_parm_table frame_parms[] = {"tool-bar-position", &Qtool_bar_position}, }; -#ifdef HAVE_NTGUI - -/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the - wanted positions of the WM window (not Emacs window). - Return in *WIDTH and *HEIGHT the wanted width and height of Emacs - window (FRAME_X_WINDOW). - */ - -void -x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos) -{ - int newwidth = FRAME_COLS (f); - int newheight = FRAME_LINES (f); - Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); - - *top_pos = f->top_pos; - *left_pos = f->left_pos; - - if (f->want_fullscreen & FULLSCREEN_HEIGHT) - { - int ph; - - ph = x_display_pixel_height (dpyinfo); - newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph); - ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff; - newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph); - *top_pos = 0; - } - - if (f->want_fullscreen & FULLSCREEN_WIDTH) - { - int pw; - - pw = x_display_pixel_width (dpyinfo); - newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw); - pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff; - newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw); - *left_pos = 0; - } - - *width = newwidth; - *height = newheight; -} - -#endif /* HAVE_NTGUI */ - #ifdef HAVE_WINDOW_SYSTEM /* Change the parameters of frame F as specified by ALIST. @@ -2810,7 +2993,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) /* If both of these parameters are present, it's more efficient to set them both at once. So we wait until we've looked at the entire list before we set them. */ - int width = 0, height = 0; + int width IF_LINT (= 0), height IF_LINT (= 0); bool width_change = 0, height_change = 0; /* Same here. */ @@ -2827,14 +3010,14 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) #ifdef HAVE_X_WINDOWS bool icon_left_no_change = 0, icon_top_no_change = 0; #endif - struct gcpro gcpro1, gcpro2; i = 0; for (tail = alist; CONSP (tail); tail = XCDR (tail)) i++; - parms = alloca (i * sizeof *parms); - values = alloca (i * sizeof *values); + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (parms, 2 * i); + values = parms + i; /* Extract parm names and values into those vectors. */ @@ -2851,10 +3034,6 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) /* TAIL and ALIST are not used again below here. */ alist = tail = Qnil; - GCPRO2 (*parms, *values); - gcpro1.nvars = i; - gcpro2.nvars = i; - /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP, because their values appear in VALUES and strings are not valid. */ top = left = Qunbound; @@ -2883,8 +3062,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) param_index = Fget (prop, Qx_frame_parameter); if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (param_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } @@ -2932,8 +3110,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) param_index = Fget (prop, Qx_frame_parameter); if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (param_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } @@ -2988,15 +3165,11 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) { Lisp_Object frame; - /* Make this 1, eventually. */ - check_frame_size (f, &width, &height, 1); - XSETFRAME (frame, f); - if ((width_change || height_change) - && (width != FRAME_TEXT_WIDTH (f) - || height != FRAME_TEXT_HEIGHT (f) - || f->new_height || f->new_width)) + if ((width_change && width != FRAME_TEXT_WIDTH (f)) + || (height_change && height != FRAME_TEXT_HEIGHT (f)) + || f->new_height || f->new_width) { /* If necessary provide default values for HEIGHT and WIDTH. Do that here since otherwise a size change implied by an @@ -3089,7 +3262,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) #endif /* HAVE_X_WINDOWS */ } - UNGCPRO; + SAFE_FREE (); } @@ -3141,6 +3314,14 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) for non-toolkit scroll bar. ruler-mode.el depends on this. */ : Qnil)); + store_in_alist (alistptr, Qscroll_bar_height, + (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) + ? make_number (0) + : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0 + ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f)) + /* nil means "use default height" + for non-toolkit scroll bar. */ + : Qnil)); /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on MS-Windows it returns a value whose type is HANDLE, which is actually a pointer. Explicit casting avoids compiler @@ -3170,7 +3351,7 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc); store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil)); store_in_alist (alistptr, Qparent_id, tem); - store_in_alist (alistptr, Qtool_bar_position, f->tool_bar_position); + store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)); } @@ -3244,8 +3425,7 @@ x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu { Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter); if (NATNUMP (parm_index) - && (XFASTINT (parm_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (parm_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)]) (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)]) (f, bgcolor, Qnil); @@ -3418,58 +3598,66 @@ x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu } } - void -x_set_fringe_width (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { - compute_fringe_widths (f, 1); -#ifdef HAVE_X_WINDOWS - /* Must adjust this so window managers report correct number of columns. */ - if (FRAME_X_WINDOW (f) != 0) - x_wm_set_size_hint (f, 0, 0); -#endif + int unit = FRAME_COLUMN_WIDTH (f); + int old_width = FRAME_LEFT_FRINGE_WIDTH (f); + int new_width; + + new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX) + ? eabs (XINT (new_value)) : 8); + + if (new_width != old_width) + { + FRAME_LEFT_FRINGE_WIDTH (f) = new_width; + FRAME_FRINGE_COLS (f) /* Round up. */ + = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit; + + if (FRAME_X_WINDOW (f) != 0) + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); + } } + void -x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { - CHECK_TYPE_RANGED_INTEGER (int, arg); + int unit = FRAME_COLUMN_WIDTH (f); + int old_width = FRAME_RIGHT_FRINGE_WIDTH (f); + int new_width; - if (XINT (arg) == f->border_width) - return; + new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX) + ? eabs (XINT (new_value)) : 8); - if (FRAME_X_WINDOW (f) != 0) - error ("Cannot change the border width of a frame"); + if (new_width != old_width) + { + FRAME_RIGHT_FRINGE_WIDTH (f) = new_width; + FRAME_FRINGE_COLS (f) /* Round up. */ + = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit; - f->border_width = XINT (arg); + if (FRAME_X_WINDOW (f) != 0) + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); + } } + void -x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - int old = FRAME_INTERNAL_BORDER_WIDTH (f); - CHECK_TYPE_RANGED_INTEGER (int, arg); - FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg); - if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0) - FRAME_INTERNAL_BORDER_WIDTH (f) = 0; - -#ifdef USE_X_TOOLKIT - if (FRAME_X_OUTPUT (f)->edit_widget) - widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget); -#endif - if (FRAME_INTERNAL_BORDER_WIDTH (f) == old) + if (XINT (arg) == f->border_width) return; if (FRAME_X_WINDOW (f) != 0) - { - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); - SET_FRAME_GARBAGED (f); - do_pending_window_change (0); - } - else - SET_FRAME_GARBAGED (f); + error ("Cannot change the border width of a frame"); + + f->border_width = XINT (arg); } void @@ -3481,18 +3669,13 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg); if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0) FRAME_RIGHT_DIVIDER_WIDTH (f) = 0; - - if (FRAME_RIGHT_DIVIDER_WIDTH (f) == old) - return; - - if (FRAME_X_WINDOW (f) != 0) + if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old) { - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); + adjust_frame_size (f, -1, -1, 4, 0); + adjust_frame_glyphs (f); SET_FRAME_GARBAGED (f); - do_pending_window_change (0); } - else - SET_FRAME_GARBAGED (f); + } void @@ -3504,18 +3687,12 @@ x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg); if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0) FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0; - - if (FRAME_BOTTOM_DIVIDER_WIDTH (f) == old) - return; - - if (FRAME_X_WINDOW (f) != 0) + if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old) { - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); + adjust_frame_size (f, -1, -1, 4, 0); + adjust_frame_glyphs (f); SET_FRAME_GARBAGED (f); - do_pending_window_change (0); } - else - SET_FRAME_GARBAGED (f); } void @@ -3556,7 +3733,7 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f)) - || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))) + || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))) { FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = (NILP (arg) @@ -3576,13 +3753,34 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval However, if the window hasn't been created yet, we shouldn't call x_set_window_size. */ if (FRAME_X_WINDOW (f)) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), - FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); } } void +x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ +#if USE_HORIZONTAL_SCROLL_BARS + if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)) + || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))) + { + f->horizontal_scroll_bars = NILP (arg) ? false : true; + + /* We set this parameter before creating the X window for the + frame, so we can get the geometry right from the start. + However, if the window hasn't been created yet, we shouldn't + call x_set_window_size. */ + if (FRAME_X_WINDOW (f)) + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); + } +#endif +} + +void x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { int unit = FRAME_COLUMN_WIDTH (f); @@ -3592,9 +3790,9 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) x_set_scroll_bar_default_width (f); if (FRAME_X_WINDOW (f)) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), - FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); } else if (RANGED_INTEGERP (1, arg, INT_MAX) && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f)) @@ -3602,19 +3800,47 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg); FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit; if (FRAME_X_WINDOW (f)) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), - FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); } - /* Eventually remove the following call. It should have been done by - x_set_window_size already. */ - change_frame_size (f, 0, 0, 0, 0, 0, 1); XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0; XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0; } void +x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ +#if USE_HORIZONTAL_SCROLL_BARS + int unit = FRAME_LINE_HEIGHT (f); + + if (NILP (arg)) + { + x_set_scroll_bar_default_height (f); + + if (FRAME_X_WINDOW (f)) + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); + } + else if (RANGED_INTEGERP (1, arg, INT_MAX) + && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f)) + { + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg); + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit; + if (FRAME_X_WINDOW (f)) + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); + } + + XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0; + XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0; +#endif +} + +void x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { double alpha = 1.0; @@ -3769,10 +3995,6 @@ validate_x_resource_name (void) static Lisp_Object xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass) { - register char *value; - char *name_key; - char *class_key; - CHECK_STRING (attribute); CHECK_STRING (class); @@ -3787,22 +4009,25 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li /* Allocate space for the components, the dots which separate them, and the final '\0'. Make them big enough for the worst case. */ - name_key = alloca (SBYTES (Vx_resource_name) - + (STRINGP (component) - ? SBYTES (component) : 0) - + SBYTES (attribute) - + 3); - - class_key = alloca (SBYTES (Vx_resource_class) - + SBYTES (class) - + (STRINGP (subclass) - ? SBYTES (subclass) : 0) - + 3); + ptrdiff_t name_keysize = (SBYTES (Vx_resource_name) + + (STRINGP (component) + ? SBYTES (component) : 0) + + SBYTES (attribute) + + 3); + + ptrdiff_t class_keysize = (SBYTES (Vx_resource_class) + + SBYTES (class) + + (STRINGP (subclass) + ? SBYTES (subclass) : 0) + + 3); + USE_SAFE_ALLOCA; + char *name_key = SAFE_ALLOCA (name_keysize + class_keysize); + char *class_key = name_key + name_keysize; /* Start with emacs.FRAMENAME for the name (the specific one) and with `Emacs' for the class key (the general one). */ - strcpy (name_key, SSDATA (Vx_resource_name)); - strcpy (class_key, SSDATA (Vx_resource_class)); + lispstpcpy (name_key, Vx_resource_name); + lispstpcpy (class_key, Vx_resource_class); strcat (class_key, "."); strcat (class_key, SSDATA (class)); @@ -3819,7 +4044,8 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li strcat (name_key, "."); strcat (name_key, SSDATA (attribute)); - value = x_get_string_resource (rdb, name_key, class_key); + char *value = x_get_string_resource (rdb, name_key, class_key); + SAFE_FREE(); if (value && *value) return build_string (value); @@ -3871,8 +4097,10 @@ x_get_resource_string (const char *attribute, const char *class) /* Allocate space for the components, the dots which separate them, and the final '\0'. */ - char *name_key = SAFE_ALLOCA (invocation_namelen + strlen (attribute) + 2); - char *class_key = alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2); + ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2; + ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2; + char *name_key = SAFE_ALLOCA (name_keysize + class_keysize); + char *class_key = name_key + name_keysize; esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute); sprintf (class_key, "%s.%s", EMACS_CLASS, class); @@ -3899,7 +4127,7 @@ Lisp_Object x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param, const char *attribute, const char *class, enum resource_types type) { - register Lisp_Object tem; + Lisp_Object tem; tem = Fassq (param, alist); @@ -3925,10 +4153,9 @@ x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param, { if (attribute && dpyinfo) { - tem = display_x_get_resource (dpyinfo, - build_string (attribute), - build_string (class), - Qnil, Qnil); + AUTO_STRING (at, attribute); + AUTO_STRING (cl, class); + tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil); if (NILP (tem)) return Qunbound; @@ -4038,7 +4265,8 @@ x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop, tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type); if (EQ (tem, Qunbound)) tem = deflt; - x_set_frame_parameters (f, list1 (Fcons (prop, tem))); + AUTO_FRAME_ARG (arg, prop, tem); + x_set_frame_parameters (f, arg); return tem; } @@ -4215,7 +4443,7 @@ On Nextstep, this just calls `ns-parse-geometry'. */) long x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) { - register Lisp_Object tem0, tem1, tem2; + Lisp_Object height, width, user_size, top, left, user_position; long window_prompting = 0; Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); @@ -4225,58 +4453,54 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f)); SET_FRAME_COLS (f, DEFAULT_COLS); SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f)); - FRAME_LINES (f) = DEFAULT_ROWS; + SET_FRAME_LINES (f, DEFAULT_ROWS); /* Window managers expect that if program-specified positions are not (0,0), they're intentional, not defaults. */ f->top_pos = 0; f->left_pos = 0; - /* Ensure that old new_width and new_height will not override the - values set here. */ - /* ++KFS: This was specific to W32, but seems ok for all platforms */ - f->new_width = f->new_height = f->new_pixelwise = 0; + /* Ensure that earlier new_width and new_height settings won't + override what we specify below. */ + f->new_width = f->new_height = 0; - tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); - tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); - tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER); - if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound)) + height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); + width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); + if (!EQ (width, Qunbound) || !EQ (height, Qunbound)) { - if (!EQ (tem0, Qunbound)) + if (!EQ (width, Qunbound)) { - CHECK_NUMBER (tem0); - if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX)) - xsignal1 (Qargs_out_of_range, tem0); - FRAME_LINES (f) = XINT (tem0); + CHECK_NUMBER (width); + if (! (0 <= XINT (width) && XINT (width) <= INT_MAX)) + xsignal1 (Qargs_out_of_range, width); + + SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f)); } - if (!EQ (tem1, Qunbound)) + + if (!EQ (height, Qunbound)) { - CHECK_NUMBER (tem1); - if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX)) - xsignal1 (Qargs_out_of_range, tem1); - SET_FRAME_COLS (f, XINT (tem1)); + CHECK_NUMBER (height); + if (! (0 <= XINT (height) && XINT (height) <= INT_MAX)) + xsignal1 (Qargs_out_of_range, height); + + SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f)); } - if (!NILP (tem2) && !EQ (tem2, Qunbound)) + + user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER); + if (!NILP (user_size) && !EQ (user_size, Qunbound)) window_prompting |= USSize; else window_prompting |= PSize; } - - /* This used to be done _before_ calling x_figure_window_size, but - since the height is reset here, this was really a no-op. I - assume that moving it here does what Gerd intended (although he - no longer can remember what that was... ++KFS, 2003-03-25. */ - - /* Add the tool-bar height to the initial frame height so that the - user gets a text display area of the size he specified with -g or - via .Xdefaults. Later changes of the tool-bar height don't - change the frame size. This is done so that users can create - tall Emacs frames without having to guess how tall the tool-bar - will get. */ - if (toolbar_p && FRAME_TOOL_BAR_HEIGHT (f)) + /* Add a tool bar height to the initial frame height so that the user + gets a text display area of the size he specified with -g or via + .Xdefaults. Later changes of the tool bar height don't change the + frame size. This is done so that users can create tall Emacs + frames without having to guess how tall the tool bar will get. */ + if (toolbar_p && FRAME_TOOL_BAR_LINES (f)) { - int margin, relief, bar_height; + int margin, relief; relief = (tool_bar_button_relief >= 0 ? tool_bar_button_relief @@ -4290,78 +4514,73 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) else margin = 0; - /* PXW: We should be able to not round here. */ - bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief; - FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f); + FRAME_TOOL_BAR_HEIGHT (f) + = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief; + Vframe_initial_frame_tool_bar_height = make_number (FRAME_TOOL_BAR_HEIGHT (f)); } - compute_fringe_widths (f, 0); - - SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f)); - SET_FRAME_HEIGHT(f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f)); - - tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER); - tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); - tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER); - if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound)) + top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER); + left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); + user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER); + if (! EQ (top, Qunbound) || ! EQ (left, Qunbound)) { - if (EQ (tem0, Qminus)) + if (EQ (top, Qminus)) { f->top_pos = 0; window_prompting |= YNegative; } - else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus) - && CONSP (XCDR (tem0)) - && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX)) + else if (CONSP (top) && EQ (XCAR (top), Qminus) + && CONSP (XCDR (top)) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX)) { - f->top_pos = - XINT (XCAR (XCDR (tem0))); + f->top_pos = - XINT (XCAR (XCDR (top))); window_prompting |= YNegative; } - else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus) - && CONSP (XCDR (tem0)) - && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0)))) + else if (CONSP (top) && EQ (XCAR (top), Qplus) + && CONSP (XCDR (top)) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top)))) { - f->top_pos = XINT (XCAR (XCDR (tem0))); + f->top_pos = XINT (XCAR (XCDR (top))); } - else if (EQ (tem0, Qunbound)) + else if (EQ (top, Qunbound)) f->top_pos = 0; else { - CHECK_TYPE_RANGED_INTEGER (int, tem0); - f->top_pos = XINT (tem0); + CHECK_TYPE_RANGED_INTEGER (int, top); + f->top_pos = XINT (top); if (f->top_pos < 0) window_prompting |= YNegative; } - if (EQ (tem1, Qminus)) + if (EQ (left, Qminus)) { f->left_pos = 0; window_prompting |= XNegative; } - else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus) - && CONSP (XCDR (tem1)) - && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX)) + else if (CONSP (left) && EQ (XCAR (left), Qminus) + && CONSP (XCDR (left)) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX)) { - f->left_pos = - XINT (XCAR (XCDR (tem1))); + f->left_pos = - XINT (XCAR (XCDR (left))); window_prompting |= XNegative; } - else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus) - && CONSP (XCDR (tem1)) - && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1)))) + else if (CONSP (left) && EQ (XCAR (left), Qplus) + && CONSP (XCDR (left)) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left)))) { - f->left_pos = XINT (XCAR (XCDR (tem1))); + f->left_pos = XINT (XCAR (XCDR (left))); } - else if (EQ (tem1, Qunbound)) + else if (EQ (left, Qunbound)) f->left_pos = 0; else { - CHECK_TYPE_RANGED_INTEGER (int, tem1); - f->left_pos = XINT (tem1); + CHECK_TYPE_RANGED_INTEGER (int, left); + f->left_pos = XINT (left); if (f->left_pos < 0) window_prompting |= XNegative; } - if (!NILP (tem2) && ! EQ (tem2, Qunbound)) + if (!NILP (user_position) && ! EQ (user_position, Qunbound)) window_prompting |= USPosition; else window_prompting |= PPosition; @@ -4392,16 +4611,11 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) #endif /* HAVE_WINDOW_SYSTEM */ void -frame_make_pointer_invisible (void) +frame_make_pointer_invisible (struct frame *f) { if (! NILP (Vmake_pointer_invisible)) { - struct frame *f; - if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))) - return; - - f = SELECTED_FRAME (); - if (f && !f->pointer_invisible + if (f && FRAME_LIVE_P (f) && !f->pointer_invisible && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook) { f->mouse_moved = 0; @@ -4412,17 +4626,11 @@ frame_make_pointer_invisible (void) } void -frame_make_pointer_visible (void) +frame_make_pointer_visible (struct frame *f) { /* We don't check Vmake_pointer_invisible here in case the pointer was invisible when Vmake_pointer_invisible was set to nil. */ - struct frame *f; - - if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))) - return; - - f = SELECTED_FRAME (); - if (f && f->pointer_invisible && f->mouse_moved + if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook) { FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0); @@ -4519,6 +4727,7 @@ syms_of_frame (void) { DEFSYM (Qframep, "framep"); DEFSYM (Qframe_live_p, "frame-live-p"); + DEFSYM (Qframe_windows_min_size, "frame-windows-min-size"); DEFSYM (Qexplicit_name, "explicit-name"); DEFSYM (Qheight, "height"); DEFSYM (Qicon, "icon"); @@ -4531,8 +4740,6 @@ syms_of_frame (void) DEFSYM (Qicon_left, "icon-left"); DEFSYM (Qicon_top, "icon-top"); DEFSYM (Qtooltip, "tooltip"); - DEFSYM (Qleft, "left"); - DEFSYM (Qright, "right"); DEFSYM (Quser_position, "user-position"); DEFSYM (Quser_size, "user-size"); DEFSYM (Qwindow_id, "window-id"); @@ -4579,7 +4786,7 @@ syms_of_frame (void) { int i; - for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++) + for (i = 0; i < ARRAYELTS (frame_parms); i++) { Lisp_Object v = intern_c_string (frame_parms[i].name); if (frame_parms[i].variable) @@ -4639,7 +4846,7 @@ Setting this variable does not affect existing frames, only new ones. */); Vdefault_frame_alist = Qnil; DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars, - doc: /* Default position of scroll bars on this window-system. */); + doc: /* Default position of vertical scroll bars on this window-system. */); #ifdef HAVE_WINDOW_SYSTEM #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)) /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by @@ -4728,6 +4935,10 @@ or call the function `tool-bar-mode'. */); Vtool_bar_mode = Qnil; #endif + DEFVAR_LISP ("frame-initial-frame-tool-bar-height", Vframe_initial_frame_tool_bar_height, + doc: /* Height of tool bar of initial frame. */); + Vframe_initial_frame_tool_bar_height = make_number (0); + DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame, doc: /* Minibufferless frames use this frame's minibuffer. Emacs cannot create minibufferless frames unless this is set to an @@ -4756,11 +4967,19 @@ current values of `frame-char-height' and `frame-char-width'. If this is non-nil, no rounding occurs, hence frame sizes can increase/decrease by one pixel. -With some window managers you have to set this to non-nil in order to -fully maximize frames. To resize your initial frame pixelwise, -set this option to a non-nil value in your init file. */); +With some window managers you may have to set this to non-nil in order +to fully maximize frames. To resize your initial frame pixelwise, set +this option to a non-nil value in your init file. */); frame_resize_pixelwise = 0; + DEFVAR_BOOL ("frame-inhibit-implied-resize", frame_inhibit_implied_resize, + doc: /* Non-nil means do not resize frame implicitly. +If this option is nil, setting default font, menubar mode, fringe width, +or scroll bar mode of a specific frame may resize the frame in order to +preserve the number of columns or lines it displays. If this option is +non-nil, no such resizing is done. */); + frame_inhibit_implied_resize = 0; + staticpro (&Vframe_list); defsubr (&Sframep); @@ -4803,9 +5022,11 @@ set this option to a non-nil value in your init file. */); defsubr (&Sframe_text_cols); defsubr (&Sframe_text_lines); defsubr (&Sframe_total_cols); + defsubr (&Sframe_total_lines); defsubr (&Sframe_text_width); defsubr (&Sframe_text_height); defsubr (&Sscroll_bar_width); + defsubr (&Sscroll_bar_height); defsubr (&Sfringe_width); defsubr (&Sborder_width); defsubr (&Sright_divider_width); diff --git a/src/frame.h b/src/frame.h index ff696df9eff..22f2fa7a24c 100644 --- a/src/frame.h +++ b/src/frame.h @@ -36,16 +36,22 @@ enum vertical_scroll_bar_type vertical_scroll_bar_right }; +#ifdef HAVE_WINDOW_SYSTEM + enum fullscreen_type { FULLSCREEN_NONE, - FULLSCREEN_WIDTH = 0x001, - FULLSCREEN_HEIGHT = 0x002, - FULLSCREEN_BOTH = 0x003, - FULLSCREEN_MAXIMIZED = 0x013, - FULLSCREEN_WAIT = 0x100 + FULLSCREEN_WIDTH = 0x1, + FULLSCREEN_HEIGHT = 0x2, + FULLSCREEN_BOTH = 0x3, /* Not a typo but means "width and height". */ + FULLSCREEN_MAXIMIZED = 0x4, +#ifdef HAVE_NTGUI + FULLSCREEN_WAIT = 0x8 +#endif }; +#endif /* HAVE_WINDOW_SYSTEM */ + /* The structure representing a frame. */ struct frame @@ -155,21 +161,41 @@ struct frame /* Desired and current tool-bar items. */ Lisp_Object tool_bar_items; - /* Where tool bar is, can be left, right, top or bottom. The native - tool bar only supports top. */ +#ifdef USE_GTK + /* Where tool bar is, can be left, right, top or bottom. + Except with GTK, the only supported position is `top'. */ Lisp_Object tool_bar_position; +#endif + +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) + /* List of data specific to font-driver and frame, but common to faces. */ + Lisp_Object font_data; +#endif /* Beyond here, there should be no more Lisp_Object components. */ /* Cache of realized faces. */ struct face_cache *face_cache; +#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) + /* Tool-bar item index of the item on which a mouse button was pressed. */ + int last_tool_bar_item; +#endif + /* Number of elements in `menu_bar_vector' that have meaningful data. */ int menu_bar_items_used; - /* A buffer to hold the frame's name. We can't use the Lisp - string's pointer (`name', above) because it might get relocated. */ +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) + /* A buffer to hold the frame's name. Since this is used by the + window system toolkit, we can't use the Lisp string's pointer + (`name', above) because it might get relocated. */ char *namebuf; +#endif + +#ifdef USE_X_TOOLKIT + /* Used to pass geometry parameters to toolkit functions. */ + char *shell_position; +#endif /* Glyph pool and matrix. */ struct glyph_pool *current_pool; @@ -177,6 +203,8 @@ struct frame struct glyph_matrix *desired_matrix; struct glyph_matrix *current_matrix; + /* Bitfield area begins here. Keep them together to avoid extra padding. */ + /* True means that glyphs on this frame have been initialized so it can be used for output. */ bool_bf glyphs_initialized_p : 1; @@ -218,10 +246,100 @@ struct frame /* True if it needs to be redisplayed. */ bool_bf redisplay : 1; - /* Margin at the top of the frame. Used to display the tool-bar. */ +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ + || defined (HAVE_NS) || defined (USE_GTK) + /* True means using a menu bar that comes from the X toolkit. */ + bool_bf external_menu_bar : 1; +#endif + + /* Next two bitfields are mutually exclusive. They might both be + zero if the frame has been made invisible without an icon. */ + + /* Nonzero if the frame is currently displayed; we check + it to see if we should bother updating the frame's contents. + + On ttys and on Windows NT/9X, to avoid wasting effort updating + visible frames that are actually completely obscured by other + windows on the display, we bend the meaning of visible slightly: + if equal to 2, then the frame is obscured - we still consider + it to be "visible" as seen from lisp, but we don't bother + updating it. */ + unsigned visible : 2; + + /* True if the frame is currently iconified. Do not + set this directly, use SET_FRAME_ICONIFIED instead. */ + bool_bf iconified : 1; + + /* True if this frame should be fully redisplayed. Disables all + optimizations while rebuilding matrices and redrawing. */ + bool_bf garbaged : 1; + + /* False means, if this frame has just one window, + show no modeline for that window. */ + bool_bf wants_modeline : 1; + + /* True means raise this frame to the top of the heap when selected. */ + bool_bf auto_raise : 1; + + /* True means lower this frame to the bottom of the stack when left. */ + bool_bf auto_lower : 1; + + /* True if frame's root window can't be split. */ + bool_bf no_split : 1; + + /* If this is set, then Emacs won't change the frame name to indicate + the current buffer, etcetera. If the user explicitly sets the frame + name, this gets set. If the user sets the name to Qnil, this is + cleared. */ + bool_bf explicit_name : 1; + + /* True if size of some window on this frame has changed. */ + bool_bf window_sizes_changed : 1; + + /* True if the mouse has moved on this display device + since the last time we checked. */ + bool_bf mouse_moved : 1; + + /* True means that the pointer is invisible. */ + bool_bf pointer_invisible : 1; + + /* True means that all windows except mini-window and + selected window on this frame have frozen window starts. */ + bool_bf frozen_window_starts : 1; + + /* The output method says how the contents of this frame are + displayed. It could be using termcap, or using an X window. + This must be the same as the terminal->type. */ + ENUM_BF (output_method) output_method : 3; + +#ifdef HAVE_WINDOW_SYSTEM + /* See FULLSCREEN_ enum on top. */ + ENUM_BF (fullscreen_type) want_fullscreen : 4; + + /* If not vertical_scroll_bar_none, we should actually + display the scroll bars of this type on this frame. */ + ENUM_BF (vertical_scroll_bar_type) vertical_scroll_bar_type : 2; + + /* Nonzero if we should actually display horizontal scroll bars on this frame. */ + bool_bf horizontal_scroll_bars : 1; +#endif /* HAVE_WINDOW_SYSTEM */ + + /* Whether new_height and new_width shall be interpreted + in pixels. */ + bool_bf new_pixelwise : 1; + + /* True if frame has been added to Vframe_list and is henceforth + considered official. For in-official frames we neither process + x_set_window_size requests nor do we allow running + window-configuration-change-hook when resizing windows. */ + bool_bf official : 1; + + /* Bitfield area ends here. */ + + /* Number of lines (rounded up) of tool bar. REMOVE THIS */ int tool_bar_lines; - /* Pixel height of tool bar. */ + /* Height of frame internal tool bar in pixels. */ int tool_bar_height; int n_tool_bar_rows; @@ -240,18 +358,22 @@ struct frame /* Cost of deleting n lines on this frame. */ int *delete_n_lines_cost; - /* Text width of this frame (excluding fringes, scroll bars and - internal border width) and text height (excluding internal border - width) in units of canonical characters. */ + /* Text width of this frame (excluding fringes, vertical scroll bar + and internal border widths) and text height (excluding menu bar, + tool bar, horizontal scroll bar and internal border widths) in + units of canonical characters. */ int text_cols, text_lines; - /* Total width of this frame (including fringes and scroll bars) in + /* Total width of this frame (including fringes, vertical scroll bar + and internal border widths) and total height (including menu bar, + tool bar, horizontal scroll bar and internal border widths) in units of canonical characters. */ - int total_cols; + int total_cols, total_lines; - /* Text width of this frame (excluding fringes, scroll bars and - internal border width) and text height (excluding internal border - width) in pixels. */ + /* Text width of this frame (excluding fringes, vertical scroll bar + and internal border widths) and text height (excluding menu bar, + tool bar, horizontal scroll bar and internal border widths) in + pixels. */ int text_width, text_height; /* New text height and width for pending size change. 0 if no change @@ -260,14 +382,12 @@ struct frame text width/height of the frame. */ int new_width, new_height; - /* Whether new_height and new_width shall be interpreted - in pixels. */ - bool new_pixelwise; - /* Pixel position of the frame window (x and y offsets in root window). */ int left_pos, top_pos; - /* Size of the frame window (including internal border widths) in + /* Total width of this frame (including fringes, vertical scroll bar + and internal border widths) and total height (including menu bar, + tool bar, horizontal scroll bar and internal border widths) in pixels. */ int pixel_width, pixel_height; @@ -289,9 +409,21 @@ struct frame a highlighting is displayed inside the internal border. */ int internal_border_width; - /* Width of borders between this frame's windows. */ - int right_divider_width; - int bottom_divider_width; + /* Widths of dividers between this frame's windows in pixels. */ + int right_divider_width, bottom_divider_width; + + /* Widths of fringes in pixels. */ + int left_fringe_width, right_fringe_width; + + /* Total width of fringes reserved for drawing truncation bitmaps, + continuation bitmaps and alike - REMOVE THIS !!!!. */ + int fringe_cols; + + /* Number of lines of menu bar. */ + int menu_bar_lines; + + /* Pixel height of menubar. */ + int menu_bar_height; /* Canonical X unit. Width of default font, in pixels. */ int column_width; @@ -299,11 +431,6 @@ struct frame /* Canonical Y unit. Height of a line, in pixels. */ int line_height; - /* The output method says how the contents of this frame are - displayed. It could be using termcap, or using an X window. - This must be the same as the terminal->type. */ - enum output_method output_method; - /* The terminal device that this frame uses. If this is NULL, then the frame has been deleted. */ struct terminal *terminal; @@ -323,98 +450,12 @@ struct frame /* List of font-drivers available on the frame. */ struct font_driver_list *font_driver_list; - /* List of data specific to font-driver and frame, but common to - faces. */ - struct font_data_list *font_data_list; - - /* Total width of fringes reserved for drawing truncation bitmaps, - continuation bitmaps and alike. The width is in canonical char - units of the frame. This must currently be the case because window - sizes aren't pixel values. If it weren't the case, we wouldn't be - able to split windows horizontally nicely. */ - int fringe_cols; - - /* The extra width (in pixels) currently allotted for fringes. */ - int left_fringe_width, right_fringe_width; - - /* See FULLSCREEN_ enum below. */ - enum fullscreen_type want_fullscreen; - - /* Number of lines of menu bar. */ - int menu_bar_lines; - - /* Pixel height of menubar. */ - int menu_bar_height; #if defined (HAVE_X_WINDOWS) /* Used by x_wait_for_event when watching for an X event on this frame. */ int wait_event_type; #endif -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ - || defined (HAVE_NS) || defined (USE_GTK) - /* True means using a menu bar that comes from the X toolkit. */ - bool_bf external_menu_bar : 1; -#endif - - /* Next two bitfields are mutually exclusive. They might both be - zero if the frame has been made invisible without an icon. */ - - /* Nonzero if the frame is currently displayed; we check - it to see if we should bother updating the frame's contents. - - On ttys and on Windows NT/9X, to avoid wasting effort updating - visible frames that are actually completely obscured by other - windows on the display, we bend the meaning of visible slightly: - if equal to 2, then the frame is obscured - we still consider - it to be "visible" as seen from lisp, but we don't bother - updating it. */ - unsigned visible : 2; - - /* True if the frame is currently iconified. Do not - set this directly, use SET_FRAME_ICONIFIED instead. */ - bool_bf iconified : 1; - - /* True if this frame should be fully redisplayed. Disables all - optimizations while rebuilding matrices and redrawing. */ - bool_bf garbaged : 1; - - /* False means, if this frame has just one window, - show no modeline for that window. */ - bool_bf wants_modeline : 1; - - /* True means raise this frame to the top of the heap when selected. */ - bool_bf auto_raise : 1; - - /* True means lower this frame to the bottom of the stack when left. */ - bool_bf auto_lower : 1; - - /* True if frame's root window can't be split. */ - bool_bf no_split : 1; - - /* If this is set, then Emacs won't change the frame name to indicate - the current buffer, etcetera. If the user explicitly sets the frame - name, this gets set. If the user sets the name to Qnil, this is - cleared. */ - bool_bf explicit_name : 1; - - /* True if size of some window on this frame has changed. */ - bool_bf window_sizes_changed : 1; - - /* True if the mouse has moved on this display device - since the last time we checked. */ - bool_bf mouse_moved : 1; - - /* True means that the pointer is invisible. */ - bool_bf pointer_invisible : 1; - - /* True means that all windows except mini-window and - selected window on this frame have frozen window starts. */ - bool_bf frozen_window_starts : 1; - - /* Nonzero if we should actually display the scroll bars on this frame. */ - enum vertical_scroll_bar_type vertical_scroll_bar_type; - /* What kind of text cursor should we draw in the future? This should always be filled_box_cursor or bar_cursor. */ enum text_cursor_kinds desired_cursor; @@ -437,6 +478,14 @@ struct frame int config_scroll_bar_width; int config_scroll_bar_cols; + /* Configured height of the scroll bar, in pixels and in characters. + config_scroll_bar_lines tracks config_scroll_bar_height if the + latter is positive; a zero value in config_scroll_bar_height means + to compute the actual width on the fly, using + config_scroll_bar_lines and the current font width. */ + int config_scroll_bar_height; + int config_scroll_bar_lines; + /* The baud rate that was used to calculate costs for this frame. */ int cost_calculation_baud_rate; @@ -543,11 +592,13 @@ fset_tool_bar_items (struct frame *f, Lisp_Object val) { f->tool_bar_items = val; } +#ifdef USE_GTK INLINE void fset_tool_bar_position (struct frame *f, Lisp_Object val) { f->tool_bar_position = val; } +#endif /* USE_GTK */ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) INLINE void fset_tool_bar_window (struct frame *f, Lisp_Object val) @@ -682,8 +733,7 @@ default_pixels_per_inch_y (void) /* Pixel width of frame F. */ #define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width) -/* Pixel height of frame F, including non-toolkit menu bar and - non-toolkit tool bar lines. */ +/* Pixel height of frame F. */ #define FRAME_PIXEL_HEIGHT(f) ((f)->pixel_height) /* Width of frame F, measured in canonical character columns, @@ -699,7 +749,7 @@ default_pixels_per_inch_y (void) #define FRAME_TEXT_WIDTH(f) (f)->text_width /* Height of frame F, measured in pixels not including the height - for internal borders. */ + for scroll bar and internal borders. */ #define FRAME_TEXT_HEIGHT(f) (f)->text_height /* Number of lines of frame F used for menu bar. @@ -719,6 +769,13 @@ default_pixels_per_inch_y (void) #define FRAME_EXTERNAL_TOOL_BAR(f) false #endif +/* This is really supported only with GTK. */ +#ifdef USE_GTK +#define FRAME_TOOL_BAR_POSITION(f) (f)->tool_bar_position +#else +#define FRAME_TOOL_BAR_POSITION(f) ((void) f, Qtop) +#endif + /* Number of lines of frame F used for the tool-bar. */ #define FRAME_TOOL_BAR_LINES(f) (f)->tool_bar_lines @@ -741,6 +798,8 @@ default_pixels_per_inch_y (void) #else #define FRAME_EXTERNAL_MENU_BAR(f) false #endif + +/* True if frame F is currently visible. */ #define FRAME_VISIBLE_P(f) (f)->visible /* True if frame F is currently visible but hidden. */ @@ -786,6 +845,8 @@ default_pixels_per_inch_y (void) #define FRAME_DELETEN_COST(f) (f)->delete_n_lines_cost #define FRAME_FOCUS_FRAME(f) f->focus_frame +#ifdef HAVE_WINDOW_SYSTEM + /* This frame slot says whether scroll bars are currently enabled for frame F, and which side they are on. */ #define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type) @@ -796,66 +857,108 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \ ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right) +#else /* not HAVE_WINDOW_SYSTEM */ + +/* If there is no window system, there are no scroll bars. */ +#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((void) f, vertical_scroll_bar_none) +#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) f, 0) +#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0) +#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0) + +#endif /* HAVE_WINDOW_SYSTEM */ + +/* Whether horizontal scroll bars are currently enabled for frame F. */ +#if USE_HORIZONTAL_SCROLL_BARS +#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \ + ((f)->horizontal_scroll_bars) +#else +#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) ((void) f, 0) +#endif + /* Width that a scroll bar in frame F should have, if there is one. Measured in pixels. If scroll bars are turned off, this is still nonzero. */ #define FRAME_CONFIG_SCROLL_BAR_WIDTH(f) ((f)->config_scroll_bar_width) +/* Height that a scroll bar in frame F should have, if there is one. + Measured in pixels. + If scroll bars are turned off, this is still nonzero. */ +#define FRAME_CONFIG_SCROLL_BAR_HEIGHT(f) ((f)->config_scroll_bar_height) + /* Width that a scroll bar in frame F should have, if there is one. Measured in columns (characters). If scroll bars are turned off, this is still nonzero. */ #define FRAME_CONFIG_SCROLL_BAR_COLS(f) ((f)->config_scroll_bar_cols) -/* Width of a scroll bar in frame F, measured in columns (characters), - but only if scroll bars are on the left. If scroll bars are on - the right in this frame, or there are no scroll bars, value is 0. */ - -#define FRAME_LEFT_SCROLL_BAR_COLS(f) \ - (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \ - ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \ - : 0) +/* Height that a scroll bar in frame F should have, if there is one. + Measured in lines (characters). + If scroll bars are turned off, this is still nonzero. */ +#define FRAME_CONFIG_SCROLL_BAR_LINES(f) ((f)->config_scroll_bar_lines) /* Width of a left scroll bar in frame F, measured in pixels */ - #define FRAME_LEFT_SCROLL_BAR_AREA_WIDTH(f) \ (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \ ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ : 0) -/* Width of a scroll bar in frame F, measured in columns (characters), - but only if scroll bars are on the right. If scroll bars are on - the left in this frame, or there are no scroll bars, value is 0. */ - -#define FRAME_RIGHT_SCROLL_BAR_COLS(f) \ - (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f) \ - ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \ - : 0) - /* Width of a right scroll bar area in frame F, measured in pixels */ - #define FRAME_RIGHT_SCROLL_BAR_AREA_WIDTH(f) \ (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f) \ ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ : 0) -/* Actual width of a scroll bar in frame F, measured in columns. */ +/* Width of a left scroll bar in frame F, measured in columns + (characters), but only if scroll bars are on the left. If scroll + bars are on the right in this frame, or there are no scroll bars, + value is 0. */ +#define FRAME_LEFT_SCROLL_BAR_COLS(f) \ + (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) \ + ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \ + : 0) -#define FRAME_SCROLL_BAR_COLS(f) \ - (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ +/* Width of a right scroll bar in frame F, measured in columns + (characters), but only if scroll bars are on the right. If scroll + bars are on the left in this frame, or there are no scroll bars, + value is 0. */ +#define FRAME_RIGHT_SCROLL_BAR_COLS(f) \ + (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f) \ ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \ : 0) -/* Actual width of a scroll bar area in frame F, measured in pixels. */ +/* Width of a vertical scroll bar area in frame F, measured in + pixels. */ +#define FRAME_SCROLL_BAR_AREA_WIDTH(f) \ + (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ + ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ + : 0) + +/* Height of horizontal scroll bar area in frame F, measured in + pixels. */ +#define FRAME_SCROLL_BAR_AREA_HEIGHT(f) \ + (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \ + ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) \ + : 0) -#define FRAME_SCROLL_BAR_AREA_WIDTH(f) \ - (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ - ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ +/* Width of vertical scroll bar in frame F, measured in columns. */ +#define FRAME_SCROLL_BAR_COLS(f) \ + (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ + ? FRAME_CONFIG_SCROLL_BAR_COLS (f) \ + : 0) + +/* Height of horizontal scroll bar in frame F, measured in lines. */ +#define FRAME_SCROLL_BAR_LINES(f) \ + (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \ + ? FRAME_CONFIG_SCROLL_BAR_LINES (f) \ : 0) /* Total width of frame F, in columns (characters), including the width used by scroll bars if any. */ #define FRAME_TOTAL_COLS(f) ((f)->total_cols) +/* Total height of frame F, in lines (characters), + including the height used by scroll bars if any. */ +#define FRAME_TOTAL_LINES(f) ((f)->total_lines) + /* Set the character widths of frame F. WIDTH specifies a nominal character text width. */ #define SET_FRAME_COLS(f, width) \ @@ -864,8 +967,16 @@ default_pixels_per_inch_y (void) + FRAME_SCROLL_BAR_COLS (f) \ + FRAME_FRINGE_COLS (f))) -/* Set the pixel widths of frame F. WIDTH specifies a nominal pixel - text width. */ +/* Set the character heights of frame F. HEIGHT specifies a nominal + character text height. */ +#define SET_FRAME_LINES(f, height) \ + ((f)->text_lines = (height), \ + (f)->total_lines = ((height) \ + + FRAME_TOP_MARGIN (f) \ + + FRAME_SCROLL_BAR_LINES (f))) + +/* Set the widths of frame F. WIDTH specifies a nominal pixel text + width. */ #define SET_FRAME_WIDTH(f, width) \ ((f)->text_width = (width), \ (f)->pixel_width = ((width) \ @@ -873,21 +984,23 @@ default_pixels_per_inch_y (void) + FRAME_TOTAL_FRINGE_WIDTH (f) \ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))) -/* Set the pixel heights of frame F. HEIGHT specifies a nominal pixel - text width. */ +/* Set the heights of frame F. HEIGHT specifies a nominal pixel text + height. */ #define SET_FRAME_HEIGHT(f, height) \ ((f)->text_height = (height), \ (f)->pixel_height = ((height) \ - + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))) + + FRAME_TOP_MARGIN_HEIGHT (f) \ + + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))) /* Maximum + 1 legitimate value for FRAME_CURSOR_X. */ - #define FRAME_CURSOR_X_LIMIT(f) \ (FRAME_COLS (f) + FRAME_LEFT_SCROLL_BAR_COLS (f)) +/* Nonzero if frame F has scroll bars. */ #define FRAME_SCROLL_BARS(f) (f->scroll_bars) - #define FRAME_CONDEMNED_SCROLL_BARS(f) (f->condemned_scroll_bars) + #define FRAME_MENU_BAR_ITEMS(f) (f->menu_bar_items) #define FRAME_COST_BAUD_RATE(f) ((f)->cost_calculation_baud_rate) @@ -947,6 +1060,11 @@ default_pixels_per_inch_y (void) } \ } while (false) +/* Handy macro to construct an argument to Fmodify_frame_parameters. */ + +#define AUTO_FRAME_ARG(name, parameter, value) \ + AUTO_LIST1 (name, AUTO_CONS_EXPR (parameter, value)) + /* False means there are no visible garbaged frames. */ extern bool frame_garbaged; @@ -981,7 +1099,6 @@ extern Lisp_Object Qtty_color_mode; extern Lisp_Object Qterminal; extern Lisp_Object Qnoelisp; -extern void set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object); extern struct frame *decode_window_system_frame (Lisp_Object); extern struct frame *decode_live_frame (Lisp_Object); extern struct frame *decode_any_frame (Lisp_Object); @@ -992,12 +1109,16 @@ extern struct frame *make_minibuffer_frame (void); extern struct frame *make_frame_without_minibuffer (Lisp_Object, struct kboard *, Lisp_Object); -#endif /* HAVE_WINDOW_SYSTEM */ extern bool window_system_available (struct frame *); +#else /* not HAVE_WINDOW_SYSTEM */ +#define window_system_available(f) ((void) (f), false) +#endif /* HAVE_WINDOW_SYSTEM */ extern void check_window_system (struct frame *); -extern void frame_make_pointer_invisible (void); -extern void frame_make_pointer_visible (void); +extern void frame_make_pointer_invisible (struct frame *); +extern void frame_make_pointer_visible (struct frame *); extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); +extern bool frame_inhibit_resize (struct frame *, bool); +extern void adjust_frame_size (struct frame *, int, int, int, bool); extern Lisp_Object Vframe_list; @@ -1018,12 +1139,10 @@ extern Lisp_Object Vframe_list; /* Canonical y-unit on frame F. This value currently equals the line height of the frame (which is the height of the default font of F). */ - #define FRAME_LINE_HEIGHT(F) ((F)->line_height) /* Canonical x-unit on frame F. This value currently equals the average width of the default font of F. */ - #define FRAME_COLUMN_WIDTH(F) ((F)->column_width) /* Pixel width of areas used to display truncation marks, continuation @@ -1036,7 +1155,6 @@ extern Lisp_Object Vframe_list; units of the frame. This must currently be the case because window sizes aren't pixel values. If it weren't the case, we wouldn't be able to split windows horizontally nicely. */ - #define FRAME_FRINGE_COLS(F) ((F)->fringe_cols) /* Pixel-width of the left and right fringe. */ @@ -1079,7 +1197,6 @@ extern Lisp_Object Vframe_list; /* Convert canonical value X to pixels. F is the frame whose canonical char width is to be used. X must be a Lisp integer or float. Value is a C integer. */ - #define FRAME_PIXEL_X_FROM_CANON_X(F, X) \ (INTEGERP (X) \ ? XINT (X) * FRAME_COLUMN_WIDTH (F) \ @@ -1088,7 +1205,6 @@ extern Lisp_Object Vframe_list; /* Convert canonical value Y to pixels. F is the frame whose canonical character height is to be used. X must be a Lisp integer or float. Value is a C integer. */ - #define FRAME_PIXEL_Y_FROM_CANON_Y(F, Y) \ (INTEGERP (Y) \ ? XINT (Y) * FRAME_LINE_HEIGHT (F) \ @@ -1098,7 +1214,6 @@ extern Lisp_Object Vframe_list; canonical character width is to be used. X is a C integer. Result is a Lisp float if X is not a multiple of the canon width, otherwise it's a Lisp integer. */ - #define FRAME_CANON_X_FROM_PIXEL_X(F, X) \ ((X) % FRAME_COLUMN_WIDTH (F) != 0 \ ? make_float ((double) (X) / FRAME_COLUMN_WIDTH (F)) \ @@ -1108,7 +1223,6 @@ extern Lisp_Object Vframe_list; canonical character height is to be used. Y is a C integer. Result is a Lisp float if Y is not a multiple of the canon width, otherwise it's a Lisp integer. */ - #define FRAME_CANON_Y_FROM_PIXEL_Y(F, Y) \ ((Y) % FRAME_LINE_HEIGHT (F) \ ? make_float ((double) (Y) / FRAME_LINE_HEIGHT (F)) \ @@ -1122,7 +1236,6 @@ extern Lisp_Object Vframe_list; Return the upper/left pixel position of the character cell on frame F at ROW/COL. */ - #define FRAME_LINE_TO_PIXEL_Y(f, row) \ (((row) < FRAME_TOP_MARGIN (f) ? 0 : FRAME_INTERNAL_BORDER_WIDTH (f)) \ + (row) * FRAME_LINE_HEIGHT (f)) @@ -1133,25 +1246,27 @@ extern Lisp_Object Vframe_list; /* Return the pixel width/height of frame F if it has COLS columns/LINES rows. */ - #define FRAME_TEXT_COLS_TO_PIXEL_WIDTH(f, cols) \ - (FRAME_COL_TO_PIXEL_X (f, cols) \ + ((cols) * FRAME_COLUMN_WIDTH (f) \ + FRAME_SCROLL_BAR_AREA_WIDTH (f) \ + FRAME_TOTAL_FRINGE_WIDTH (f) \ - + FRAME_INTERNAL_BORDER_WIDTH (f)) + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) #define FRAME_TEXT_LINES_TO_PIXEL_HEIGHT(f, lines) \ ((lines) * FRAME_LINE_HEIGHT (f) \ + + FRAME_TOP_MARGIN_HEIGHT (f) \ + + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) /* Return the row/column (zero-based) of the character cell containing the pixel on FRAME at Y/X. */ - #define FRAME_PIXEL_Y_TO_LINE(f, y) \ (((y) < FRAME_TOP_MARGIN_HEIGHT (f) \ ? (y) \ - : ((y) < FRAME_TOP_MARGIN_HEIGHT (f) + FRAME_INTERNAL_BORDER_WIDTH (f) \ - ? (y) - (FRAME_TOP_MARGIN_HEIGHT (f) + FRAME_INTERNAL_BORDER_WIDTH (f) \ + : ((y) < (FRAME_TOP_MARGIN_HEIGHT (f) \ + + FRAME_INTERNAL_BORDER_WIDTH (f)) \ + ? (y) - (FRAME_TOP_MARGIN_HEIGHT (f) \ + + FRAME_INTERNAL_BORDER_WIDTH (f) \ /* Arrange for the division to round down. */ \ + FRAME_LINE_HEIGHT (f) - 1) \ : (y) - FRAME_INTERNAL_BORDER_WIDTH (f))) \ @@ -1162,21 +1277,23 @@ extern Lisp_Object Vframe_list; / FRAME_COLUMN_WIDTH (f)) /* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on - frame F? */ - + frame F (so we round down)? */ #define FRAME_PIXEL_WIDTH_TO_TEXT_COLS(f, width) \ - (FRAME_PIXEL_X_TO_COL (f, ((width) \ - - FRAME_INTERNAL_BORDER_WIDTH (f) \ - - FRAME_TOTAL_FRINGE_WIDTH (f) \ - - FRAME_SCROLL_BAR_AREA_WIDTH (f)))) \ + (((width) \ + - FRAME_TOTAL_FRINGE_WIDTH (f) \ + - FRAME_SCROLL_BAR_AREA_WIDTH (f) \ + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) \ + / FRAME_COLUMN_WIDTH (f)) \ #define FRAME_PIXEL_HEIGHT_TO_TEXT_LINES(f, height) \ - (FRAME_PIXEL_Y_TO_LINE (f, ((height) \ - - FRAME_INTERNAL_BORDER_WIDTH (f)))) + (((height) \ + - FRAME_TOP_MARGIN_HEIGHT (f) \ + - FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) \ + / FRAME_LINE_HEIGHT (f)) /* Return the pixel width/height of frame F with a text size of width/height. */ - #define FRAME_TEXT_TO_PIXEL_WIDTH(f, width) \ ((width) \ + FRAME_SCROLL_BAR_AREA_WIDTH (f) \ @@ -1184,11 +1301,13 @@ extern Lisp_Object Vframe_list; + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) #define FRAME_TEXT_TO_PIXEL_HEIGHT(f, height) \ - ((height) + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) + ((height) \ + + FRAME_TOP_MARGIN_HEIGHT (f) \ + + FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) /* Return the text width/height of frame F with a pixel size of width/height. */ - #define FRAME_PIXEL_TO_TEXT_WIDTH(f, width) \ ((width) \ - FRAME_SCROLL_BAR_AREA_WIDTH (f) \ @@ -1196,15 +1315,26 @@ extern Lisp_Object Vframe_list; - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) #define FRAME_PIXEL_TO_TEXT_HEIGHT(f, height) \ - ((height) - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) + ((height) \ + - FRAME_TOP_MARGIN_HEIGHT (f) \ + - FRAME_SCROLL_BAR_AREA_HEIGHT (f) \ + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) -/* Value is the smallest width of any character in any font on frame F. */ +/* Return the width/height reserved for the windows of frame F. */ +#define FRAME_WINDOWS_WIDTH(f) \ + (FRAME_PIXEL_WIDTH (f) \ + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) + +#define FRAME_WINDOWS_HEIGHT(f) \ + (FRAME_PIXEL_HEIGHT (f) \ + - FRAME_TOP_MARGIN_HEIGHT (f) \ + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)) +/* Value is the smallest width of any character in any font on frame F. */ #define FRAME_SMALLEST_CHAR_WIDTH(f) \ FRAME_DISPLAY_INFO (f)->smallest_char_width /* Value is the smallest height of any font on frame F. */ - #define FRAME_SMALLEST_FONT_HEIGHT(f) \ FRAME_DISPLAY_INFO (f)->smallest_font_height @@ -1217,7 +1347,6 @@ extern Lisp_Object Qborder_color, Qborder_width; extern Lisp_Object Qbuffer_predicate; extern Lisp_Object Qcursor_color, Qcursor_type; extern Lisp_Object Qfont; -extern Lisp_Object Qbackground_color, Qforeground_color; extern Lisp_Object Qicon, Qicon_name, Qicon_type, Qicon_left, Qicon_top; extern Lisp_Object Qinternal_border_width; extern Lisp_Object Qright_divider_width, Qbottom_divider_width; @@ -1228,6 +1357,7 @@ extern Lisp_Object Qname, Qtitle; extern Lisp_Object Qparent_id; extern Lisp_Object Qunsplittable, Qvisibility; extern Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars; +extern Lisp_Object Qscroll_bar_height, Qhorizontal_scroll_bars; extern Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background; extern Lisp_Object Qscreen_gamma; extern Lisp_Object Qline_spacing; @@ -1247,7 +1377,7 @@ extern Lisp_Object Qdisplay_type; extern Lisp_Object Qx_resource_name; -extern Lisp_Object Qleft, Qright, Qtop, Qbox, Qbottom; +extern Lisp_Object Qtop, Qbox, Qbottom; extern Lisp_Object Qdisplay; extern Lisp_Object Qrun_hook_with_args; @@ -1257,33 +1387,21 @@ extern Lisp_Object Qrun_hook_with_args; /* The class of this X application. */ #define EMACS_CLASS "Emacs" -/* These are in xterm.c, w32term.c, etc. */ - extern void x_set_scroll_bar_default_width (struct frame *); +extern void x_set_scroll_bar_default_height (struct frame *); extern void x_set_offset (struct frame *, int, int, int); extern void x_wm_set_size_hint (struct frame *f, long flags, bool user_position); - extern Lisp_Object x_new_font (struct frame *, Lisp_Object, int); - - extern Lisp_Object Qface_set_after_frame_default; - -#ifdef HAVE_NTGUI -extern void x_fullscreen_adjust (struct frame *f, int *, int *, - int *, int *); -#endif - extern void x_set_frame_parameters (struct frame *, Lisp_Object); - extern void x_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_line_spacing (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_screen_gamma (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_font (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_font_backend (struct frame *, Lisp_Object, Lisp_Object); -extern void x_set_fringe_width (struct frame *, Lisp_Object, Lisp_Object); +extern void x_set_left_fringe (struct frame *, Lisp_Object, Lisp_Object); +extern void x_set_right_fringe (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_border_width (struct frame *, Lisp_Object, Lisp_Object); -extern void x_set_internal_border_width (struct frame *, Lisp_Object, - Lisp_Object); extern void x_set_right_divider_width (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_bottom_divider_width (struct frame *, Lisp_Object, @@ -1292,10 +1410,10 @@ extern void x_set_visibility (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_autoraise (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_autolower (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_unsplittable (struct frame *, Lisp_Object, Lisp_Object); -extern void x_set_vertical_scroll_bars (struct frame *, Lisp_Object, - Lisp_Object); -extern void x_set_scroll_bar_width (struct frame *, Lisp_Object, - Lisp_Object); +extern void x_set_vertical_scroll_bars (struct frame *, Lisp_Object, Lisp_Object); +extern void x_set_horizontal_scroll_bars (struct frame *, Lisp_Object, Lisp_Object); +extern void x_set_scroll_bar_width (struct frame *, Lisp_Object, Lisp_Object); +extern void x_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object); extern long x_figure_window_size (struct frame *, Lisp_Object, bool); @@ -1313,14 +1431,11 @@ extern void set_frame_menubar (struct frame *f, bool first_time, bool deep_p); extern void x_set_window_size (struct frame *f, int change_grav, int width, int height, bool pixelwise); extern Lisp_Object x_get_focus_frame (struct frame *); -extern void x_set_mouse_position (struct frame *f, int h, int v); -extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); +extern void frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); extern void x_make_frame_visible (struct frame *f); extern void x_make_frame_invisible (struct frame *f); extern void x_iconify_frame (struct frame *f); extern void x_set_frame_alpha (struct frame *f); -extern void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object); -extern void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object); extern void x_activate_menubar (struct frame *); extern void x_real_positions (struct frame *, int *, int *); extern void free_frame_menubar (struct frame *); @@ -1354,7 +1469,6 @@ x_set_bitmap_icon (struct frame *f) } #endif /* !HAVE_NS */ - #endif /* HAVE_WINDOW_SYSTEM */ INLINE void @@ -1390,4 +1504,11 @@ extern Lisp_Object make_monitor_attribute_list (struct MonitorInfo *monitors, INLINE_HEADER_END +/* Suppress -Wsuggest-attribute=const if there are no scroll bars. + This is for functions like x_set_horizontal_scroll_bars that have + no effect in this case. */ +#if ! USE_HORIZONTAL_SCROLL_BARS && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + #endif /* not EMACS_FRAME_H */ diff --git a/src/fringe.c b/src/fringe.c index 6325de4128e..3c0e883b2e9 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -474,15 +474,12 @@ static struct fringe_bitmap standard_bitmaps[] = #define NO_FRINGE_BITMAP 0 #define UNDEF_FRINGE_BITMAP 1 -#define MAX_STANDARD_FRINGE_BITMAPS (sizeof (standard_bitmaps)/sizeof (standard_bitmaps[0])) +#define MAX_STANDARD_FRINGE_BITMAPS ARRAYELTS (standard_bitmaps) static struct fringe_bitmap **fringe_bitmaps; static Lisp_Object *fringe_faces; static int max_fringe_bitmaps; -#ifndef HAVE_NS -static -#endif int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; @@ -637,7 +634,7 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o return; } - PREPARE_FACE_FOR_DISPLAY (f, p.face); + prepare_face_for_display (f, p.face); /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill the fringe. */ @@ -1332,98 +1329,6 @@ update_window_fringes (struct window *w, bool keep_current_p) } -/* Compute actual fringe widths for frame F. - - If REDRAW is 1, redraw F if the fringe settings was actually - modified and F is visible. - - Since the combined left and right fringe must occupy an integral - number of columns, we may need to add some pixels to each fringe. - Typically, we add an equal amount (+/- 1 pixel) to each fringe, - but a negative width value is taken literally (after negating it). - - We never make the fringes narrower than specified. -*/ - -void -compute_fringe_widths (struct frame *f, bool redraw_p) -{ - int o_left = FRAME_LEFT_FRINGE_WIDTH (f); - int o_right = FRAME_RIGHT_FRINGE_WIDTH (f); - int o_cols = FRAME_FRINGE_COLS (f); - - Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist); - Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist); - int left_fringe_width, right_fringe_width; - - if (!NILP (left_fringe)) - left_fringe = Fcdr (left_fringe); - if (!NILP (right_fringe)) - right_fringe = Fcdr (right_fringe); - - left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 : - XINT (left_fringe)); - right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 : - XINT (right_fringe)); - - if (left_fringe_width || right_fringe_width) - { - int left_wid = eabs (left_fringe_width); - int right_wid = eabs (right_fringe_width); - int conf_wid = left_wid + right_wid; - int font_wid = FRAME_COLUMN_WIDTH (f); - int cols = (left_wid + right_wid + font_wid-1) / font_wid; - int real_wid = cols * font_wid; - if (left_wid && right_wid) - { - if (left_fringe_width < 0) - { - /* Left fringe width is fixed, adjust right fringe if necessary */ - FRAME_LEFT_FRINGE_WIDTH (f) = left_wid; - FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid; - } - else if (right_fringe_width < 0) - { - /* Right fringe width is fixed, adjust left fringe if necessary */ - FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid; - FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid; - } - else - { - /* Adjust both fringes with an equal amount. - Note that we are doing integer arithmetic here, so don't - lose a pixel if the total width is an odd number. */ - int fill = real_wid - conf_wid; - FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2; - FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2; - } - } - else if (left_fringe_width) - { - FRAME_LEFT_FRINGE_WIDTH (f) = real_wid; - FRAME_RIGHT_FRINGE_WIDTH (f) = 0; - } - else - { - FRAME_LEFT_FRINGE_WIDTH (f) = 0; - FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid; - } - FRAME_FRINGE_COLS (f) = cols; - } - else - { - FRAME_LEFT_FRINGE_WIDTH (f) = 0; - FRAME_RIGHT_FRINGE_WIDTH (f) = 0; - FRAME_FRINGE_COLS (f) = 0; - } - - if (redraw_p && FRAME_VISIBLE_P (f)) - if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) || - o_right != FRAME_RIGHT_FRINGE_WIDTH (f) || - o_cols != FRAME_FRINGE_COLS (f)) - redraw_frame (f); -} - /* Free resources used by a user-defined bitmap. */ @@ -1574,13 +1479,7 @@ If BITMAP already exists, the existing definition is replaced. */) int fill1 = 0, fill2 = 0; CHECK_SYMBOL (bitmap); - - if (STRINGP (bits)) - h = SCHARS (bits); - else if (VECTORP (bits)) - h = ASIZE (bits); - else - wrong_type_argument (Qsequencep, bits); + h = CHECK_VECTOR_OR_STRING (bits); if (NILP (height)) fb.height = h; diff --git a/src/ftfont.c b/src/ftfont.c index 112adad8a10..4c12ef5d3af 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -24,6 +24,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <fontconfig/fontconfig.h> #include <fontconfig/fcfreetype.h> +#include <c-strcase.h> + #include "lisp.h" #include "dispextern.h" #include "frame.h" @@ -87,8 +89,6 @@ static Lisp_Object ftfont_lookup_cache (Lisp_Object, static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist); -Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object); - #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM)) static struct @@ -142,6 +142,12 @@ static struct { NULL } }; +static bool +matching_prefix (char const *str, ptrdiff_t len, char const *pat) +{ + return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0; +} + /* Dirty hack for handing ADSTYLE property. Fontconfig (actually the underlying FreeType) gives such ADSTYLE @@ -173,18 +179,10 @@ get_adstyle_property (FcPattern *p) return Qnil; str = (char *) fcstr; for (end = str; *end && *end != ' '; end++); - if (*end) - { - char *newstr = alloca (end - str + 1); - memcpy (newstr, str, end - str); - newstr[end - str] = '\0'; - end = newstr + (end - str); - str = newstr; - } - if (xstrcasecmp (str, "Regular") == 0 - || xstrcasecmp (str, "Bold") == 0 - || xstrcasecmp (str, "Oblique") == 0 - || xstrcasecmp (str, "Italic") == 0) + if (matching_prefix (str, end - str, "Regular") + || matching_prefix (str, end - str, "Bold") + || matching_prefix (str, end - str, "Oblique") + || matching_prefix (str, end - str, "Italic")) return Qnil; adstyle = font_intern_prop (str, end - str, 1); if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0) @@ -501,8 +499,8 @@ static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); static void ftfont_close (struct font *); static int ftfont_has_char (Lisp_Object, int); static unsigned ftfont_encode_char (struct font *, int); -static int ftfont_text_extents (struct font *, unsigned *, int, - struct font_metrics *); +static void ftfont_text_extents (struct font *, unsigned *, int, + struct font_metrics *); static int ftfont_get_bitmap (struct font *, unsigned, struct font_bitmap *, int); static int ftfont_anchor_point (struct font *, unsigned, int, @@ -540,8 +538,6 @@ struct font_driver ftfont_driver = NULL, /* draw */ ftfont_get_bitmap, NULL, /* free_bitmap */ - NULL, /* get_outline */ - NULL, /* free_outline */ ftfont_anchor_point, #ifdef HAVE_LIBOTF ftfont_otf_capability, @@ -577,7 +573,8 @@ static int ftfont_get_charset (Lisp_Object registry) { char *str = SSDATA (SYMBOL_NAME (registry)); - char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); + USE_SAFE_ALLOCA; + char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); Lisp_Object regexp; int i, j; @@ -593,6 +590,7 @@ ftfont_get_charset (Lisp_Object registry) } re[j] = '\0'; regexp = make_unibyte_string (re, j); + SAFE_FREE (); for (i = 0; fc_charset_table[i].name; i++) if (fast_c_string_match_ignore_case (regexp, fc_charset_table[i].name, @@ -806,7 +804,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots *otspec = ftfont_get_open_type_spec (val); if (! *otspec) return NULL; - strcat (otlayout, "otlayout:"); + strcpy (otlayout, "otlayout:"); OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9); script = (*otspec)->script; } @@ -1187,8 +1185,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) Lisp_Object val, filename, idx, cache, font_object; bool scalable; int spacing; - char name[256]; - int i, len; + int i; int upEM; val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); @@ -1225,19 +1222,9 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) return Qnil; } - font_object = font_make_object (VECSIZE (struct ftfont_info), entity, size); - ASET (font_object, FONT_TYPE_INDEX, Qfreetype); - len = font_unparse_xlfd (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); - len = font_unparse_fcname (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); - else - ASET (font_object, FONT_FULLNAME_INDEX, - AREF (font_object, FONT_NAME_INDEX)); + font_object = font_build_object (VECSIZE (struct ftfont_info), + Qfreetype, entity, size); ASET (font_object, FONT_FILE_INDEX, filename); - ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename)); font = XFONT_OBJECT (font_object); ftfont_info = (struct ftfont_info *) font; ftfont_info->ft_size = ft_face->size; @@ -1386,19 +1373,18 @@ ftfont_encode_char (struct font *font, int c) return (code > 0 ? code : FONT_INVALID_CODE); } -static int -ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics) +static void +ftfont_text_extents (struct font *font, unsigned int *code, + int nglyphs, struct font_metrics *metrics) { struct ftfont_info *ftfont_info = (struct ftfont_info *) font; FT_Face ft_face = ftfont_info->ft_size->face; - int width = 0; - int i; + int i, width = 0; bool first; if (ftfont_info->ft_size != ft_face->size) FT_Activate_Size (ftfont_info->ft_size); - if (metrics) - memset (metrics, 0, sizeof (struct font_metrics)); + for (i = 0, first = 1; i < nglyphs; i++) { if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0) @@ -1407,39 +1393,28 @@ ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct if (first) { - if (metrics) - { - metrics->lbearing = m->horiBearingX >> 6; - metrics->rbearing = (m->horiBearingX + m->width) >> 6; - metrics->ascent = m->horiBearingY >> 6; - metrics->descent = (m->height - m->horiBearingY) >> 6; - } + metrics->lbearing = m->horiBearingX >> 6; + metrics->rbearing = (m->horiBearingX + m->width) >> 6; + metrics->ascent = m->horiBearingY >> 6; + metrics->descent = (m->height - m->horiBearingY) >> 6; first = 0; } - if (metrics) - { - if (metrics->lbearing > width + (m->horiBearingX >> 6)) - metrics->lbearing = width + (m->horiBearingX >> 6); - if (metrics->rbearing - < width + ((m->horiBearingX + m->width) >> 6)) - metrics->rbearing - = width + ((m->horiBearingX + m->width) >> 6); - if (metrics->ascent < (m->horiBearingY >> 6)) - metrics->ascent = m->horiBearingY >> 6; - if (metrics->descent > ((m->height - m->horiBearingY) >> 6)) - metrics->descent = (m->height - m->horiBearingY) >> 6; - } + if (metrics->lbearing > width + (m->horiBearingX >> 6)) + metrics->lbearing = width + (m->horiBearingX >> 6); + if (metrics->rbearing + < width + ((m->horiBearingX + m->width) >> 6)) + metrics->rbearing + = width + ((m->horiBearingX + m->width) >> 6); + if (metrics->ascent < (m->horiBearingY >> 6)) + metrics->ascent = m->horiBearingY >> 6; + if (metrics->descent > ((m->height - m->horiBearingY) >> 6)) + metrics->descent = (m->height - m->horiBearingY) >> 6; width += m->horiAdvance >> 6; } else - { - width += font->space_width; - } + width += font->space_width; } - if (metrics) - metrics->width = width; - - return width; + metrics->width = width; } static int @@ -1715,7 +1690,8 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec) else if (! otf) return 0; for (n = 1; spec->features[i][n]; n++); - tags = alloca (sizeof (OTF_Tag) * n); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (tags, 1, n); for (n = 0, negative = 0; spec->features[i][n]; n++) { if (spec->features[i][n] == 0xFFFFFFFF) @@ -1725,16 +1701,17 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec) else tags[n] = spec->features[i][n]; } -#ifdef M17N_FLT_USE_NEW_FEATURE - if (OTF_check_features (otf, i == 0, spec->script, spec->langsys, - tags, n - negative) != 1) - return 0; -#else /* not M17N_FLT_USE_NEW_FEATURE */ - if (n - negative > 0 - && OTF_check_features (otf, i == 0, spec->script, spec->langsys, - tags, n - negative) != 1) + bool passed = true; +#ifndef M17N_FLT_USE_NEW_FEATURE + passed = n - negative > 0; +#endif + if (passed) + passed = (OTF_check_features (otf, i == 0, spec->script, + spec->langsys, tags, n - negative) + != 1); + SAFE_FREE (); + if (passed) return 0; -#endif /* not M17N_FLT_USE_NEW_FEATURE */ } return 1; #undef FEATURE_NONE @@ -1826,11 +1803,15 @@ ftfont_drive_otf (MFLTFont *font, if (len == 0) return from; OTF_tag_name (spec->script, script); + + char langsysbuf[5]; if (spec->langsys) { - langsys = alloca (5); + langsys = langsysbuf; OTF_tag_name (spec->langsys, langsys); } + + USE_SAFE_ALLOCA; for (i = 0; i < 2; i++) { char *p; @@ -1838,10 +1819,11 @@ ftfont_drive_otf (MFLTFont *font, if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) { for (j = 0; spec->features[i][j]; j++); + SAFE_NALLOCA (p, 6, j); if (i == 0) - p = gsub_features = alloca (6 * j); + gsub_features = p; else - p = gpos_features = alloca (6 * j); + gpos_features = p; for (j = 0; spec->features[i][j]; j++) { if (spec->features[i][j] == 0xFFFFFFFF) @@ -1873,7 +1855,10 @@ ftfont_drive_otf (MFLTFont *font, gsub_features) < 0) goto simple_copy; if (out->allocated < out->used + otf_gstring.used) - return -2; + { + SAFE_FREE (); + return -2; + } features = otf->gsub->FeatureList.Feature; for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) { @@ -1962,7 +1947,10 @@ ftfont_drive_otf (MFLTFont *font, else if (out) { if (out->allocated < out->used + len) - return -2; + { + SAFE_FREE (); + return -2; + } for (i = 0; i < len; i++) out->glyphs[out->used++] = in->glyphs[from + i]; } @@ -1974,7 +1962,10 @@ ftfont_drive_otf (MFLTFont *font, if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, gpos_features) < 0) - return to; + { + SAFE_FREE (); + return to; + } features = otf->gpos->FeatureList.Feature; x_ppem = ft_face->size->metrics.x_ppem; y_ppem = ft_face->size->metrics.y_ppem; @@ -2096,7 +2087,10 @@ ftfont_drive_otf (MFLTFont *font, { if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, gpos_features) < 0) - return to; + { + SAFE_FREE (); + return to; + } features = otf->gpos->FeatureList.Feature; for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++) @@ -2116,9 +2110,11 @@ ftfont_drive_otf (MFLTFont *font, } } } + SAFE_FREE (); return to; simple_copy: + SAFE_FREE (); if (! out) return to; if (out->allocated < out->used + len) @@ -2156,11 +2152,15 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (len == 0) return from; OTF_tag_name (spec->script, script); + + char langsysbuf[5]; if (spec->langsys) { - langsys = alloca (5); + langsys = langsysbuf; OTF_tag_name (spec->langsys, langsys); } + + USE_SAFE_ALLOCA; for (i = 0; i < 2; i++) { char *p; @@ -2168,10 +2168,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) { for (j = 0; spec->features[i][j]; j++); + SAFE_NALLOCA (p, 6, j); if (i == 0) - p = gsub_features = alloca (6 * j); + gsub_features = p; else - p = gpos_features = alloca (6 * j); + gpos_features = p; for (j = 0; spec->features[i][j]; j++) { if (spec->features[i][j] == 0xFFFFFFFF) @@ -2203,7 +2204,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, < 0) goto simple_copy; if (out->allocated < out->used + otf_gstring.used) - return -2; + { + SAFE_FREE (); + return -2; + } for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) { MFLTGlyph *g; @@ -2254,7 +2258,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, else { if (out->allocated < out->used + len) - return -2; + { + SAFE_FREE (); + return -2; + } for (i = 0; i < len; i++) out->glyphs[out->used++] = in->glyphs[from + i]; } @@ -2266,7 +2273,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features) < 0) - return to; + { + SAFE_FREE (); + return to; + } x_ppem = ft_face->size->metrics.x_ppem; y_ppem = ft_face->size->metrics.y_ppem; @@ -2376,9 +2386,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, base = g; } } + SAFE_FREE (); return to; simple_copy: + SAFE_FREE (); if (out->allocated < out->used + len) return -2; font->get_metrics (font, in, from, to); @@ -2601,46 +2613,6 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ #endif /* HAVE_LIBOTF */ -Lisp_Object -ftfont_font_format (FcPattern *pattern, Lisp_Object filename) -{ - FcChar8 *str; - -#ifdef FC_FONTFORMAT - if (pattern) - { - if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch) - return Qnil; - if (strcmp ((char *) str, "TrueType") == 0) - return intern ("truetype"); - if (strcmp ((char *) str, "Type 1") == 0) - return intern ("type1"); - if (strcmp ((char *) str, "PCF") == 0) - return intern ("pcf"); - if (strcmp ((char *) str, "BDF") == 0) - return intern ("bdf"); - } -#endif /* FC_FONTFORMAT */ - if (STRINGP (filename)) - { - int len = SBYTES (filename); - - if (len >= 4) - { - str = (FcChar8 *) (SDATA (filename) + len - 4); - if (xstrcasecmp ((char *) str, ".ttf") == 0) - return intern ("truetype"); - if (xstrcasecmp ((char *) str, ".pfb") == 0) - return intern ("type1"); - if (xstrcasecmp ((char *) str, ".pcf") == 0) - return intern ("pcf"); - if (xstrcasecmp ((char *) str, ".bdf") == 0) - return intern ("bdf"); - } - } - return intern ("unknown"); -} - static const char *const ftfont_booleans [] = { ":antialias", ":hinting", diff --git a/src/ftfont.h b/src/ftfont.h index 8c8674f3440..210b634c094 100644 --- a/src/ftfont.h +++ b/src/ftfont.h @@ -36,7 +36,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif /* HAVE_M17N_FLT */ #endif /* HAVE_LIBOTF */ -extern Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object); extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); #endif /* EMACS_FTFONT_H */ diff --git a/src/ftxfont.c b/src/ftxfont.c index 9db7cbceb66..7e4608b9b85 100644 --- a/src/ftxfont.c +++ b/src/ftxfont.c @@ -37,9 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ static Lisp_Object Qftx; -#if defined HAVE_XFT || !defined HAVE_FREETYPE -static -#endif struct font_driver ftxfont_driver; struct ftxfont_frame_data @@ -62,7 +59,7 @@ ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long backgr XColor color; XGCValues xgcv; int i; - struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver); + struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx); struct ftxfont_frame_data *prev = NULL, *this = NULL, *new; if (data) @@ -81,19 +78,11 @@ ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long backgr } } - new = malloc (sizeof *new); - if (! new) - return NULL; + new = xmalloc (sizeof *new); new->next = this; if (prev) - { prev->next = new; - } - else if (font_put_frame_data (f, &ftxfont_driver, new) < 0) - { - free (new); - return NULL; - } + font_put_frame_data (f, Qftx, new); new->colors[0].pixel = background; new->colors[1].pixel = foreground; @@ -126,8 +115,8 @@ ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long backgr if (prev) prev->next = new->next; else if (data) - font_put_frame_data (f, &ftxfont_driver, new->next); - free (new); + font_put_frame_data (f, Qftx, new->next); + xfree (new); return NULL; } return new->gcs; @@ -282,10 +271,11 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y, n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0; + USE_SAFE_ALLOCA; + SAFE_NALLOCA (code, 1, len); block_input (); if (with_background) ftxfont_draw_background (f, font, s->gc, x, y, s->width); - code = alloca (sizeof (unsigned) * len); for (i = 0; i < len; i++) code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) | XCHAR2B_BYTE2 (s->char2b + from + i)); @@ -333,6 +323,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y, } unblock_input (); + SAFE_FREE (); return len; } @@ -340,7 +331,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y, static int ftxfont_end_for_frame (struct frame *f) { - struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver); + struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx); block_input (); while (data) @@ -350,11 +341,11 @@ ftxfont_end_for_frame (struct frame *f) for (i = 0; i < 6; i++) XFreeGC (FRAME_X_DISPLAY (f), data->gcs[i]); - free (data); + xfree (data); data = next; } unblock_input (); - font_put_frame_data (f, &ftxfont_driver, NULL); + font_put_frame_data (f, Qftx, NULL); return 0; } diff --git a/src/gmalloc.c b/src/gmalloc.c index 0e90b5a3498..3456ff0ec6f 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -21,13 +21,18 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. #include <config.h> -#ifdef HAVE_PTHREAD +#if defined HAVE_PTHREAD && !defined HYBRID_MALLOC #define USE_PTHREAD #endif #include <string.h> #include <limits.h> #include <stdint.h> + +#ifdef HYBRID_GET_CURRENT_DIR_NAME +#undef get_current_dir_name +#endif + #include <unistd.h> #ifdef USE_PTHREAD @@ -42,6 +47,41 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. extern void emacs_abort (void); #endif +/* If HYBRID_MALLOC is defined, then temacs will use malloc, + realloc... as defined in this file (and renamed gmalloc, + grealloc... via the macros that follow). The dumped emacs, + however, will use the system malloc, realloc.... In other source + files, malloc, realloc... are renamed hybrid_malloc, + hybrid_realloc... via macros in conf_post.h. hybrid_malloc and + friends are wrapper functions defined later in this file. + aligned_alloc is defined as a macro only in alloc.c. + + As of this writing (August 2014), Cygwin is the only platform on + which HYBRID_MACRO is defined. Any other platform that wants to + define it will have to define the macros DUMPED and + ALLOCATED_BEFORE_DUMPING, defined below for Cygwin. */ +#ifdef HYBRID_MALLOC +#undef malloc +#undef realloc +#undef calloc +#undef free +#define malloc gmalloc +#define realloc grealloc +#define calloc gcalloc +#define aligned_alloc galigned_alloc +#define free gfree +#endif /* HYBRID_MALLOC */ + +#ifdef CYGWIN +extern void *bss_sbrk (ptrdiff_t size); +extern int bss_sbrk_did_unexec; +extern char bss_sbrk_buffer[]; +extern void *bss_sbrk_buffer_end; +#define DUMPED bss_sbrk_did_unexec +#define ALLOCATED_BEFORE_DUMPING(P) \ + ((P) < bss_sbrk_buffer_end && (P) >= (void *) bss_sbrk_buffer) +#endif + #ifdef __cplusplus extern "C" { @@ -51,12 +91,12 @@ extern "C" /* Allocate SIZE bytes of memory. */ -extern void *malloc (size_t size); +extern void *malloc (size_t size) ATTRIBUTE_MALLOC_SIZE ((1)); /* Re-allocate the previously allocated block in ptr, making the new block SIZE bytes long. */ -extern void *realloc (void *ptr, size_t size); +extern void *realloc (void *ptr, size_t size) ATTRIBUTE_ALLOC_SIZE ((2)); /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ -extern void *calloc (size_t nmemb, size_t size); +extern void *calloc (size_t nmemb, size_t size) ATTRIBUTE_MALLOC_SIZE ((1,2)); /* Free a block allocated by `malloc', `realloc' or `calloc'. */ extern void free (void *ptr); @@ -306,22 +346,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. #include <errno.h> -/* On Cygwin there are two heaps. temacs uses the static heap - (defined in sheap.c and managed with bss_sbrk), and the dumped - emacs uses the Cygwin heap (managed with sbrk). When emacs starts - on Cygwin, it reinitializes malloc, and we save the old info for - use by free and realloc if they're called with a pointer into the - static heap. - - Currently (2011-08-16) the Cygwin build doesn't use ralloc.c; if - this is changed in the future, we'll have to similarly deal with - reinitializing ralloc. */ -#ifdef CYGWIN -extern void *bss_sbrk (ptrdiff_t size); -extern int bss_sbrk_did_unexec; -char *bss_sbrk_heapbase; /* _heapbase for static heap */ -malloc_info *bss_sbrk_heapinfo; /* _heapinfo for static heap */ -#endif void *(*__morecore) (ptrdiff_t size) = __default_morecore; /* Debugging hook for `malloc'. */ @@ -490,18 +514,8 @@ register_heapinfo (void) } #ifdef USE_PTHREAD -/* On Cygwin prior to 1.7.31, pthread_mutexes were ERRORCHECK mutexes - by default. When the default changed to NORMAL in Cygwin-1.7.31, - deadlocks occurred (bug#18222). As a temporary workaround, we - explicitly set the mutexes to be of ERRORCHECK type, restoring the - previous behavior. */ -#ifdef CYGWIN -pthread_mutex_t _malloc_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; -pthread_mutex_t _aligned_blocks_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; -#else /* not CYGWIN */ pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif /* not CYGWIN */ int _malloc_thread_enabled_p; static void @@ -536,17 +550,8 @@ malloc_enable_thread (void) initialized mutexes when they are used first. To avoid such a situation, we initialize mutexes here while their use is disabled in malloc etc. */ -#ifdef CYGWIN - /* Use ERRORCHECK mutexes; see comment above. */ - pthread_mutexattr_t attr; - pthread_mutexattr_init (&attr); - pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK); - pthread_mutex_init (&_malloc_mutex, &attr); - pthread_mutex_init (&_aligned_blocks_mutex, &attr); -#else /* not CYGWIN */ pthread_mutex_init (&_malloc_mutex, NULL); pthread_mutex_init (&_aligned_blocks_mutex, NULL); -#endif /* not CYGWIN */ pthread_atfork (malloc_atfork_handler_prepare, malloc_atfork_handler_parent, malloc_atfork_handler_child); @@ -561,16 +566,6 @@ malloc_initialize_1 (void) mcheck (NULL); #endif -#ifdef CYGWIN - if (bss_sbrk_did_unexec) - /* we're reinitializing the dumped emacs */ - { - bss_sbrk_heapbase = _heapbase; - bss_sbrk_heapinfo = _heapinfo; - memset (_fraghead, 0, BLOCKLOG * sizeof (struct list)); - } -#endif - if (__malloc_initialize_hook) (*__malloc_initialize_hook) (); @@ -1027,12 +1022,6 @@ _free_internal_nolock (void *ptr) if (ptr == NULL) return; -#ifdef CYGWIN - if ((char *) ptr < _heapbase) - /* We're being asked to free something in the static heap. */ - return; -#endif - PROTECT_MALLOC_STATE (0); LOCK_ALIGNED_BLOCKS (); @@ -1314,30 +1303,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. or (US mail) as Mike Haertel c/o Free Software Foundation. */ #ifndef min -#define min(A, B) ((A) < (B) ? (A) : (B)) -#endif - -/* On Cygwin the dumped emacs may try to realloc storage allocated in - the static heap. We just malloc space in the new heap and copy the - data. */ -#ifdef CYGWIN -void * -special_realloc (void *ptr, size_t size) -{ - void *result; - int type; - size_t block, oldsize; - - block = ((char *) ptr - bss_sbrk_heapbase) / BLOCKSIZE + 1; - type = bss_sbrk_heapinfo[block].busy.type; - oldsize = - type == 0 ? bss_sbrk_heapinfo[block].busy.info.size * BLOCKSIZE - : (size_t) 1 << type; - result = _malloc_internal_nolock (size); - if (result) - return memcpy (result, ptr, min (oldsize, size)); - return result; -} +#define min(a, b) ((a) < (b) ? (a) : (b)) #endif /* Debugging hook for realloc. */ @@ -1364,12 +1330,6 @@ _realloc_internal_nolock (void *ptr, size_t size) else if (ptr == NULL) return _malloc_internal_nolock (size); -#ifdef CYGWIN - if ((char *) ptr < _heapbase) - /* ptr points into the static heap */ - return special_realloc (ptr, size); -#endif - block = BLOCK (ptr); PROTECT_MALLOC_STATE (0); @@ -1566,7 +1526,7 @@ __default_morecore (ptrdiff_t increment) { void *result; #if defined (CYGWIN) - if (!bss_sbrk_did_unexec) + if (!DUMPED) { return bss_sbrk (increment); } @@ -1689,6 +1649,9 @@ memalign (size_t alignment, size_t size) return aligned_alloc (alignment, size); } +/* If HYBRID_MALLOC is defined, we may want to use the system + posix_memalign below. */ +#ifndef HYBRID_MALLOC int posix_memalign (void **memptr, size_t alignment, size_t size) { @@ -1707,6 +1670,7 @@ posix_memalign (void **memptr, size_t alignment, size_t size) return 0; } +#endif /* Allocate memory on a page boundary. Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc. @@ -1747,6 +1711,113 @@ valloc (size_t size) return aligned_alloc (pagesize, size); } +#ifdef HYBRID_MALLOC +#undef malloc +#undef realloc +#undef calloc +#undef aligned_alloc +#undef free + +/* Declare system malloc and friends. */ +extern void *malloc (size_t size); +extern void *realloc (void *ptr, size_t size); +extern void *calloc (size_t nmemb, size_t size); +extern void free (void *ptr); +#ifdef HAVE_ALIGNED_ALLOC +extern void *aligned_alloc (size_t alignment, size_t size); +#elif defined HAVE_POSIX_MEMALIGN +extern int posix_memalign (void **memptr, size_t alignment, size_t size); +#endif + +/* See the comments near the beginning of this file for explanations + of the following functions. */ + +void * +hybrid_malloc (size_t size) +{ + if (DUMPED) + return malloc (size); + return gmalloc (size); +} + +void * +hybrid_calloc (size_t nmemb, size_t size) +{ + if (DUMPED) + return calloc (nmemb, size); + return gcalloc (nmemb, size); +} + +void +hybrid_free (void *ptr) +{ + if (!DUMPED) + gfree (ptr); + else if (!ALLOCATED_BEFORE_DUMPING (ptr)) + free (ptr); + /* Otherwise the dumped emacs is trying to free something allocated + before dumping; do nothing. */ + return; +} + +#if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN +void * +hybrid_aligned_alloc (size_t alignment, size_t size) +{ + if (!DUMPED) + return galigned_alloc (alignment, size); + /* The following is copied from alloc.c */ +#ifdef HAVE_ALIGNED_ALLOC + return aligned_alloc (alignment, size); +#else /* HAVE_POSIX_MEMALIGN */ + void *p; + return posix_memalign (&p, alignment, size) == 0 ? p : 0; +#endif +} +#endif + +void * +hybrid_realloc (void *ptr, size_t size) +{ + void *result; + int type; + size_t block, oldsize; + + if (!DUMPED) + return grealloc (ptr, size); + if (!ALLOCATED_BEFORE_DUMPING (ptr)) + return realloc (ptr, size); + + /* The dumped emacs is trying to realloc storage allocated before + dumping. We just malloc new space and copy the data. */ + if (size == 0 || ptr == NULL) + return malloc (size); + block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1; + type = _heapinfo[block].busy.type; + oldsize = + type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE + : (size_t) 1 << type; + result = malloc (size); + if (result) + return memcpy (result, ptr, min (oldsize, size)); + return result; +} + +#ifdef HYBRID_GET_CURRENT_DIR_NAME +/* Defined in sysdep.c. */ +char *gget_current_dir_name (void); + +char * +hybrid_get_current_dir_name (void) +{ + if (DUMPED) + return get_current_dir_name (); + return gget_current_dir_name (); +} +#endif + +#endif /* HYBRID_MALLOC */ + #ifdef GC_MCHECK /* Standard debugging hooks for `malloc'. diff --git a/src/gnutls.c b/src/gnutls.c index 03c29d03014..5d48f78a6d4 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -56,7 +56,7 @@ static Lisp_Object QCgnutls_bootprop_verify_error; static Lisp_Object QCgnutls_bootprop_callbacks_verify; static void gnutls_log_function (int, const char *); -static void gnutls_log_function2 (int, const char*, const char*); +static void gnutls_log_function2 (int, const char *, const char *); #ifdef HAVE_GNUTLS3 static void gnutls_audit_log_function (gnutls_session_t, const char *); #endif @@ -267,7 +267,7 @@ init_gnutls_functions (void) #ifdef HAVE_GNUTLS3 /* Function to log a simple audit message. */ static void -gnutls_audit_log_function (gnutls_session_t session, const char* string) +gnutls_audit_log_function (gnutls_session_t session, const char *string) { if (global_gnutls_log_level >= 1) { @@ -278,21 +278,21 @@ gnutls_audit_log_function (gnutls_session_t session, const char* string) /* Function to log a simple message. */ static void -gnutls_log_function (int level, const char* string) +gnutls_log_function (int level, const char *string) { message ("gnutls.c: [%d] %s", level, string); } /* Function to log a message and a string. */ static void -gnutls_log_function2 (int level, const char* string, const char* extra) +gnutls_log_function2 (int level, const char *string, const char *extra) { message ("gnutls.c: [%d] %s %s", level, string, extra); } /* Function to log a message and an integer. */ static void -gnutls_log_function2i (int level, const char* string, int extra) +gnutls_log_function2i (int level, const char *string, int extra) { message ("gnutls.c: [%d] %s %d", level, string, extra); } @@ -336,8 +336,8 @@ emacs_gnutls_handshake (struct Lisp_Process *proc) in. For an Emacs process socket, infd and outfd are the same but we use this two-argument version for clarity. */ fn_gnutls_transport_set_ptr2 (state, - (gnutls_transport_ptr_t) (long) proc->infd, - (gnutls_transport_ptr_t) (long) proc->outfd); + (void *) (intptr_t) proc->infd, + (void *) (intptr_t) proc->outfd); #endif proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; @@ -794,7 +794,7 @@ one trustfile (usually a CA bundle). */) Lisp_Object global_init; char const *priority_string_ptr = "NORMAL"; /* default priority string. */ unsigned int peer_verification; - char* c_hostname; + char *c_hostname; /* Placeholders for the property list elements. */ Lisp_Object priority_string; diff --git a/src/gtkutil.c b/src/gtkutil.c index cebff68614f..01360244c2e 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "blockinput.h" #include "syssignal.h" #include "window.h" +#include "buffer.h" #include "gtkutil.h" #include "termhooks.h" #include "keyboard.h" @@ -92,6 +93,16 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif #endif /* HAVE_FREETYPE */ +#if GTK_CHECK_VERSION (3, 10, 0) +#define XG_TEXT_CANCEL "Cancel" +#define XG_TEXT_OK "OK" +#define XG_TEXT_OPEN "Open" +#else +#define XG_TEXT_CANCEL GTK_STOCK_CANCEL +#define XG_TEXT_OK GTK_STOCK_OK +#define XG_TEXT_OPEN GTK_STOCK_OPEN +#endif + #ifndef HAVE_GTK3 #ifdef USE_GTK_TOOLTIP #define gdk_window_get_screen(w) gdk_drawable_get_screen (w) @@ -114,6 +125,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x)) static void update_theme_scrollbar_width (void); +static void update_theme_scrollbar_height (void); #define TB_INFO_KEY "xg_frame_tb_info" struct xg_frame_tb_info @@ -221,57 +233,6 @@ xg_display_close (Display *dpy) /*********************************************************************** Utility functions ***********************************************************************/ -/* The next two variables and functions are taken from lwlib. */ -static widget_value *widget_value_free_list; -static int malloc_cpt; - -/* Allocate a widget_value structure, either by taking one from the - widget_value_free_list or by malloc:ing a new one. - - Return a pointer to the allocated structure. */ - -widget_value * -malloc_widget_value (void) -{ - widget_value *wv; - if (widget_value_free_list) - { - wv = widget_value_free_list; - widget_value_free_list = wv->free_list; - wv->free_list = 0; - } - else - { - wv = xmalloc (sizeof *wv); - malloc_cpt++; - } - memset (wv, 0, sizeof (widget_value)); - return wv; -} - -/* This is analogous to free. It frees only what was allocated - by malloc_widget_value, and no substructures. */ - -void -free_widget_value (widget_value *wv) -{ - if (wv->free_list) - emacs_abort (); - - if (malloc_cpt > 25) - { - /* When the number of already allocated cells is too big, - We free it. */ - xfree (wv); - malloc_cpt--; - } - else - { - wv->free_list = widget_value_free_list; - widget_value_free_list = wv; - } -} - /* Create and return the cursor to be used for popup menus and scroll bars on display DPY. */ @@ -557,16 +518,16 @@ get_utf8_string (const char *str) && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE) { memcpy (up, p, bytes_written); - sprintf (up + bytes_written, "\\%03o", p[bytes_written]); - up += bytes_written+4; - p += bytes_written+1; + up += bytes_written; + up += sprintf (up, "\\%03o", p[bytes_written]); + p += bytes_written + 1; g_error_free (err); err = NULL; } if (cp) { - strcat (utf8_str, cp); + strcpy (up, cp); g_free (cp); } if (err) @@ -871,7 +832,7 @@ xg_set_geometry (struct frame *f) /* Clear under internal border if any. As we use a mix of Gtk+ and X calls and use a GtkFixed widget, this doesn't happen automatically. */ -static void +void xg_clear_under_internal_border (struct frame *f) { if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) @@ -933,6 +894,8 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) change_frame_size (f, width, height, 0, 1, 0, 1); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); + + do_pending_window_change (0); } } @@ -977,7 +940,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height) x_wait_for_event (f, ConfigureNotify); } else - change_frame_size (f, width, height, 0, 1, 0, 1); + adjust_frame_size (f, -1, -1, 5, 0); } /* Handle height/width changes (i.e. add/remove/move menu/toolbar). @@ -1067,6 +1030,7 @@ style_changed_cb (GObject *go, kbd_buffer_store_event (&event); update_theme_scrollbar_width (); + update_theme_scrollbar_height (); /* If scroll bar width changed, we need set the new size on all frames on this display. */ @@ -1081,6 +1045,7 @@ style_changed_cb (GObject *go, && FRAME_X_DISPLAY (f) == dpy) { x_set_scroll_bar_default_width (f); + x_set_scroll_bar_default_height (f); xg_frame_set_char_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f)); } } @@ -1364,13 +1329,12 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); - check_frame_size (f, &min_cols, &min_rows, 0); if (min_cols > 0) --min_cols; /* We used one col in base_width = ... 1); */ if (min_rows > 0) --min_rows; /* We used one row in base_height = ... 1); */ size_hints.base_width = base_width; size_hints.base_height = base_height; - size_hints.min_width = base_width + min_cols * FRAME_COLUMN_WIDTH (f);; + size_hints.min_width = base_width + min_cols * FRAME_COLUMN_WIDTH (f); size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f); /* These currently have a one to one mapping with the X values, but I @@ -1525,7 +1489,6 @@ create_dialog (widget_value *wv, int button_spacing = 10; GtkWidget *wdialog = gtk_dialog_new (); GtkDialog *wd = GTK_DIALOG (wdialog); - GtkBox *cur_box = GTK_BOX (gtk_dialog_get_action_area (wd)); widget_value *item; GtkWidget *whbox_down; @@ -1533,6 +1496,17 @@ create_dialog (widget_value *wv, instead. This looks better. */ bool make_two_rows = total_buttons > 4; +#if GTK_CHECK_VERSION (3, 12, 0) + GtkBuilder *gbld = gtk_builder_new (); + GObject *go = gtk_buildable_get_internal_child (GTK_BUILDABLE (wd), + gbld, + "action_area"); + GtkBox *cur_box = GTK_BOX (go); + g_object_unref (G_OBJECT (gbld)); +#else + GtkBox *cur_box = GTK_BOX (gtk_dialog_get_action_area (wd)); +#endif + if (right_buttons == 0) right_buttons = total_buttons/2; left_buttons = total_buttons - right_buttons; @@ -1578,8 +1552,12 @@ create_dialog (widget_value *wv, w = gtk_label_new (utf8_label); gtk_box_pack_start (wvbox, gtk_label_new (""), FALSE, FALSE, 0); gtk_box_pack_start (wvbox, w, TRUE, TRUE, 0); +#if GTK_CHECK_VERSION (3, 14, 0) + gtk_widget_set_halign (w, GTK_ALIGN_START); + gtk_widget_set_valign (w, GTK_ALIGN_CENTER); +#else gtk_misc_set_alignment (GTK_MISC (w), 0.1, 0.5); - +#endif /* Try to make dialog look better. Must realize first so the widget can calculate the size it needs. */ gtk_widget_realize (w); @@ -1587,6 +1565,7 @@ create_dialog (widget_value *wv, gtk_box_set_spacing (wvbox, req.height); if (item->value && strlen (item->value) > 0) button_spacing = 2*req.width/strlen (item->value); + if (button_spacing < 10) button_spacing = 10; } else { @@ -1603,11 +1582,6 @@ create_dialog (widget_value *wv, { if (make_two_rows) cur_box = GTK_BOX (whbox_down); - else - gtk_box_pack_start (cur_box, - gtk_label_new (""), - TRUE, TRUE, - button_spacing); } } @@ -1824,9 +1798,9 @@ xg_get_file_with_chooser (struct frame *f, action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; filewin = gtk_file_chooser_dialog_new (prompt, gwin, action, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + XG_TEXT_CANCEL, GTK_RESPONSE_CANCEL, (mustmatch_p || only_dir_p ? - GTK_STOCK_OPEN : GTK_STOCK_OK), + XG_TEXT_OPEN : XG_TEXT_OK), GTK_RESPONSE_OK, NULL); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (filewin), TRUE); @@ -2333,9 +2307,15 @@ make_widget_for_menu_item (const char *utf8_label, const char *utf8_key) wlbl = gtk_label_new (utf8_label); wkey = gtk_label_new (utf8_key); +#if GTK_CHECK_VERSION (3, 14, 0) + gtk_widget_set_halign (wlbl, GTK_ALIGN_START); + gtk_widget_set_valign (wlbl, GTK_ALIGN_CENTER); + gtk_widget_set_halign (wkey, GTK_ALIGN_START); + gtk_widget_set_valign (wkey, GTK_ALIGN_CENTER); +#else gtk_misc_set_alignment (GTK_MISC (wlbl), 0.0, 0.5); gtk_misc_set_alignment (GTK_MISC (wkey), 0.0, 0.5); - +#endif gtk_box_pack_start (GTK_BOX (wbox), wlbl, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (wbox), wkey, FALSE, FALSE, 0); @@ -2406,57 +2386,6 @@ make_menu_item (const char *utf8_label, return w; } -#ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW - -static int xg_detached_menus; - -/* Return true if there are detached menus. */ - -bool -xg_have_tear_offs (struct frame *f) -{ - /* If the frame's menubar height is zero, the menu bar is probably - being redirected outside the window to some kind of global menu; - this situation is the moral equivalent of a tear-off. */ - return FRAME_MENUBAR_HEIGHT (f) == 0 || xg_detached_menus > 0; -} - -/* Callback invoked when a detached menu window is removed. Here we - decrease the xg_detached_menus count. - WIDGET is the top level window that is removed (the parent of the menu). - CLIENT_DATA is not used. */ - -static void -tearoff_remove (GtkWidget *widget, gpointer client_data) -{ - if (xg_detached_menus > 0) --xg_detached_menus; -} - -/* Callback invoked when a menu is detached. It increases the - xg_detached_menus count. - WIDGET is the GtkTearoffMenuItem. - CLIENT_DATA is not used. */ - -static void -tearoff_activate (GtkWidget *widget, gpointer client_data) -{ - GtkWidget *menu = gtk_widget_get_parent (widget); - if (gtk_menu_get_tearoff_state (GTK_MENU (menu))) - { - ++xg_detached_menus; - g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)), - "destroy", - G_CALLBACK (tearoff_remove), 0); - } -} -#else /* ! HAVE_GTK_TEAROFF_MENU_ITEM_NEW */ -bool -xg_have_tear_offs (struct frame *f) -{ - return FRAME_MENUBAR_HEIGHT (f) == 0; -} -#endif /* ! HAVE_GTK_TEAROFF_MENU_ITEM_NEW */ - /* Create a menu item widget, and connect the callbacks. ITEM describes the menu item. F is the frame the created menu belongs to. @@ -2527,8 +2456,6 @@ xg_create_one_menuitem (widget_value *item, HIGHLIGHT_CB is the callback to call when entering/leaving menu items. If POP_UP_P, create a popup menu. If MENU_BAR_P, create a menu bar. - If ADD_TEAROFF_P, add a tearoff menu item. Ignored if MENU_BAR_P or - the Gtk+ version used does not have tearoffs. TOPMENU is the topmost GtkWidget that others shall be placed under. It may be NULL, in that case we create the appropriate widget (menu bar or menu item depending on POP_UP_P and MENU_BAR_P) @@ -2550,7 +2477,6 @@ create_menus (widget_value *data, GCallback highlight_cb, bool pop_up_p, bool menu_bar_p, - bool add_tearoff_p, GtkWidget *topmenu, xg_menu_cb_data *cl_data, const char *name) @@ -2601,17 +2527,6 @@ create_menus (widget_value *data, "selection-done", deactivate_cb, 0); } -#ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW - if (! menu_bar_p && add_tearoff_p) - { - GtkWidget *tearoff = gtk_tearoff_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (wmenu), tearoff); - - g_signal_connect (G_OBJECT (tearoff), "activate", - G_CALLBACK (tearoff_activate), 0); - } -#endif - for (item = data; item; item = item->next) { GtkWidget *w; @@ -2625,7 +2540,6 @@ create_menus (widget_value *data, group = NULL; utf8_label = get_utf8_string (item->name); - gtk_menu_set_title (GTK_MENU (wmenu), utf8_label); w = gtk_menu_item_new_with_label (utf8_label); gtk_widget_set_sensitive (w, FALSE); if (utf8_label) g_free (utf8_label); @@ -2656,7 +2570,6 @@ create_menus (widget_value *data, highlight_cb, 0, 0, - add_tearoff_p, 0, cl_data, 0); @@ -2714,7 +2627,6 @@ xg_create_widget (const char *type, const char *name, struct frame *f, highlight_cb, pop_up_p, menu_bar_p, - menu_bar_p, 0, 0, name); @@ -2824,7 +2736,7 @@ xg_update_menubar (GtkWidget *menubar, { /* Item(s) added. Add all new items in one call. */ create_menus (val, f, select_cb, deactivate_cb, highlight_cb, - 0, 1, 0, menubar, cl_data, 0); + 0, 1, menubar, cl_data, 0); /* All updated. */ val = 0; @@ -2897,7 +2809,6 @@ xg_update_menubar (GtkWidget *menubar, is up to date when leaving the minibuffer. */ GtkLabel *wlabel = GTK_LABEL (XG_BIN_CHILD (witem)); char *utf8_label = get_utf8_string (val->name); - GtkWidget *submenu = gtk_menu_item_get_submenu (witem); /* GTK menu items don't notice when their labels have been changed from underneath them, so we have to explicitly @@ -2905,16 +2816,9 @@ xg_update_menubar (GtkWidget *menubar, bridge that might be loaded) that the item's label has changed. */ gtk_label_set_text (wlabel, utf8_label); +#if GTK_CHECK_VERSION (2, 16, 0) g_object_notify (G_OBJECT (witem), "label"); - -#ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW - /* If this item has a submenu that has been detached, change - the title in the WM decorations also. */ - if (submenu && gtk_menu_get_tearoff_state (GTK_MENU (submenu))) - /* Set the title of the detached window. */ - gtk_menu_set_title (GTK_MENU (submenu), utf8_label); #endif - if (utf8_label) g_free (utf8_label); iter = g_list_next (iter); val = val->next; @@ -2941,7 +2845,7 @@ xg_update_menubar (GtkWidget *menubar, GtkWidget *submenu = create_menus (NULL, f, select_cb, deactivate_cb, highlight_cb, - 0, 0, 0, 0, cl_data, 0); + 0, 0, 0, cl_data, 0); gtk_widget_set_name (w, MENU_ITEM_NAME); gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), w, pos); @@ -3093,8 +2997,10 @@ xg_update_menu_item (widget_value *val, } } +#if GTK_CHECK_VERSION (2, 16, 0) if (label_changed) /* See comment in xg_update_menubar. */ g_object_notify (G_OBJECT (w), "label"); +#endif } /* Update the toggle menu item W so it corresponds to VAL. */ @@ -3138,7 +3044,6 @@ xg_update_submenu (GtkWidget *submenu, GList *list = 0; GList *iter; widget_value *cur; - bool has_tearoff_p = 0; GList *first_radio = 0; if (submenu) @@ -3150,17 +3055,6 @@ xg_update_submenu (GtkWidget *submenu, { GtkWidget *w = GTK_WIDGET (iter->data); -#ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW - /* Skip tearoff items, they have no counterpart in val. */ - if (GTK_IS_TEAROFF_MENU_ITEM (w)) - { - has_tearoff_p = 1; - iter = g_list_next (iter); - if (iter) w = GTK_WIDGET (iter->data); - else break; - } -#endif - /* Remember first radio button in a group. If we get a mismatch in a radio group we must rebuild the whole group so that the connections in GTK becomes correct. */ @@ -3248,7 +3142,6 @@ xg_update_submenu (GtkWidget *submenu, highlight_cb, 0, 0, - ! has_tearoff_p, submenu, cl_data, 0); @@ -3424,7 +3317,7 @@ xg_event_is_for_menubar (struct frame *f, const XEvent *event) if (! (event->xbutton.x >= 0 && event->xbutton.x < FRAME_PIXEL_WIDTH (f) && event->xbutton.y >= 0 - && event->xbutton.y < f->output_data.x->menubar_height + && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f) && event->xbutton.same_screen)) return 0; @@ -3469,9 +3362,9 @@ xg_event_is_for_menubar (struct frame *f, const XEvent *event) bool xg_ignore_gtk_scrollbar; -/* The width of the scroll bar for the current theme. */ - +/* Width and height of scroll bars for the current theme. */ static int scroll_bar_width_for_theme; +static int scroll_bar_height_for_theme; /* Xlib's `Window' fits in 32 bits. But we want to store pointers, and they may be larger than 32 bits. Keep a mapping from integer index to widget @@ -3574,12 +3467,41 @@ update_theme_scrollbar_width (void) scroll_bar_width_for_theme = w; } +static void +update_theme_scrollbar_height (void) +{ +#ifdef HAVE_GTK3 + GtkAdjustment *hadj; +#else + GtkObject *hadj; +#endif + GtkWidget *wscroll; + int w = 0, b = 0; + + hadj = gtk_adjustment_new (YG_SB_MIN, YG_SB_MIN, YG_SB_MAX, 0.1, 0.1, 0.1); + wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj)); + g_object_ref_sink (G_OBJECT (wscroll)); + gtk_widget_style_get (wscroll, "slider-width", &w, "trough-border", &b, NULL); + gtk_widget_destroy (wscroll); + g_object_unref (G_OBJECT (wscroll)); + w += 2*b; + if (w < 12) w = 12; + scroll_bar_height_for_theme = w; +} + int xg_get_default_scrollbar_width (void) { return scroll_bar_width_for_theme; } +int +xg_get_default_scrollbar_height (void) +{ + /* Apparently there's no default height for themes. */ + return scroll_bar_width_for_theme; +} + /* Return the scrollbar id for X Window WID on display DPY. Return -1 if WID not in id_to_widget. */ @@ -3678,6 +3600,74 @@ xg_create_scroll_bar (struct frame *f, xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); bar->x_window = scroll_id; + bar->horizontal = 0; +} + +/* Create a horizontal scroll bar widget for frame F. Store the scroll + bar in BAR. SCROLL_CALLBACK is the callback to invoke when the value + of the bar changes. END_CALLBACK is the callback to invoke when + scrolling ends. SCROLL_BAR_NAME is the name we use for the scroll + bar. Can be used to set resources for the widget. */ + +void +xg_create_horizontal_scroll_bar (struct frame *f, + struct scroll_bar *bar, + GCallback scroll_callback, + GCallback end_callback, + const char *scroll_bar_name) +{ + GtkWidget *wscroll; + GtkWidget *webox; + intptr_t scroll_id; +#ifdef HAVE_GTK3 + GtkAdjustment *hadj; +#else + GtkObject *hadj; +#endif + + /* Page, step increment values are not so important here, they + will be corrected in x_set_toolkit_scroll_bar_thumb. */ + hadj = gtk_adjustment_new (YG_SB_MIN, YG_SB_MIN, YG_SB_MAX, + 0.1, 0.1, 0.1); + + wscroll = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (hadj)); + webox = gtk_event_box_new (); + gtk_widget_set_name (wscroll, scroll_bar_name); +#ifndef HAVE_GTK3 + gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); +#endif + g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); + + scroll_id = xg_store_widget_in_map (wscroll); + + g_signal_connect (G_OBJECT (wscroll), + "destroy", + G_CALLBACK (xg_gtk_scroll_destroy), + (gpointer) scroll_id); + g_signal_connect (G_OBJECT (wscroll), + "change-value", + scroll_callback, + (gpointer) bar); + g_signal_connect (G_OBJECT (wscroll), + "button-release-event", + end_callback, + (gpointer) bar); + + /* The scroll bar widget does not draw on a window of its own. Instead + it draws on the parent window, in this case the edit widget. So + whenever the edit widget is cleared, the scroll bar needs to redraw + also, which causes flicker. Put an event box between the edit widget + and the scroll bar, so the scroll bar instead draws itself on the + event box window. */ + gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); + gtk_container_add (GTK_CONTAINER (webox), wscroll); + + + /* Set the cursor to an arrow. */ + xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); + + bar->x_window = scroll_id; + bar->horizontal = 1; } /* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ @@ -3760,6 +3750,73 @@ xg_update_scrollbar_pos (struct frame *f, } } + +/* Update the position of the horizontal scroll bar represented by SCROLLBAR_ID + in frame F. + TOP/LEFT are the new pixel positions where the bar shall appear. + WIDTH, HEIGHT is the size in pixels the bar shall have. */ + +void +xg_update_horizontal_scrollbar_pos (struct frame *f, + ptrdiff_t scrollbar_id, + int top, + int left, + int width, + int height) +{ + + GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); + + if (wscroll) + { + GtkWidget *wfixed = f->output_data.x->edit_widget; + GtkWidget *wparent = gtk_widget_get_parent (wscroll); + gint msl; + + /* Clear out old position. */ + int oldx = -1, oldy = -1, oldw, oldh; + if (gtk_widget_get_parent (wparent) == wfixed) + { + gtk_container_child_get (GTK_CONTAINER (wfixed), wparent, + "x", &oldx, "y", &oldy, NULL); + gtk_widget_get_size_request (wscroll, &oldw, &oldh); + } + + /* Move and resize to new values. */ + gtk_fixed_move (GTK_FIXED (wfixed), wparent, left, top); + gtk_widget_style_get (wscroll, "min-slider-length", &msl, NULL); + if (msl > width) + { + /* No room. Hide scroll bar as some themes output a warning if + the width is less than the min size. */ + gtk_widget_hide (wparent); + gtk_widget_hide (wscroll); + } + else + { + gtk_widget_show_all (wparent); + gtk_widget_set_size_request (wscroll, width, height); + } + gtk_widget_queue_draw (wfixed); + gdk_window_process_all_updates (); + if (oldx != -1 && oldw > 0 && oldh > 0) + /* Clear under old scroll bar position. This must be done after + the gtk_widget_queue_draw and gdk_window_process_all_updates + above. */ + x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + oldx, oldy, oldw, oldh); + + /* GTK does not redraw until the main loop is entered again, but + if there are no X events pending we will not enter it. So we sync + here to get some events. */ + + x_sync (f); + SET_FRAME_GARBAGED (f); + cancel_mouse_face (f); + } +} + + /* Get the current value of the range, truncated to an integer. */ static int @@ -3854,6 +3911,48 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, } } +/* Set the thumb size and position of horizontal scroll bar BAR. We are + currently displaying PORTION out of a whole WHOLE, and our position + POSITION. */ +void +xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, + int portion, + int position, + int whole) +{ + GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window); + + if (wscroll && bar->dragging == -1) + { + GtkAdjustment *adj; + int lower = 0; + int upper = max (whole - 1, 0); + int pagesize = min (upper, max (portion, 0)); + int value = max (0, min (position, upper - pagesize)); + /* These should be set to something more <portion, whole> + related. */ + int page_increment = 4; + int step_increment = 1; + + block_input (); + adj = gtk_range_get_adjustment (GTK_RANGE (wscroll)); +#if GTK_CHECK_VERSION (2, 3, 16) + gtk_adjustment_configure (adj, (gdouble) value, (gdouble) lower, + (gdouble) upper, (gdouble) step_increment, + (gdouble) page_increment, (gdouble) pagesize); +#else + gtk_adjustment_set_lower (adj, (gdouble) lower); + gtk_adjustment_set_upper (adj, (gdouble) upper); + gtk_adjustment_set_page_size (adj, (gdouble) pagesize); + gtk_adjustment_set_value (adj, (gdouble) value); + gtk_adjustment_set_page_increment (adj, (gdouble) page_increment); + gtk_adjustment_set_step_increment (adj, (gdouble) step_increment); +#endif + gtk_adjustment_changed (adj); + unblock_input (); + } +} + /* Return true if EVENT is for a scroll bar in frame F. When the same X window is used for several Gtk+ widgets, we cannot say for sure based on the X window alone if an event is for the @@ -3904,9 +4003,6 @@ xg_event_is_for_scrollbar (struct frame *f, const XEvent *event) get them. */ #define XG_TOOL_BAR_LAST_MODIFIER "emacs-tool-bar-modifier" -/* The key for storing the button widget in its proxy menu item. */ -#define XG_TOOL_BAR_PROXY_BUTTON "emacs-tool-bar-proxy-button" - /* The key for the data we put in the GtkImage widgets. The data is the stock name used by Emacs. We use this to see if we need to update the GtkImage with a new image. */ @@ -3979,41 +4075,6 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data) x_focus_frame (f); } -/* Callback function invoked when a tool bar item is pressed in a detached - tool bar or the overflow drop down menu. - We just call xg_tool_bar_callback. - W is the menu item widget that got pressed, - CLIENT_DATA is an integer that is the index of the button in the - tool bar. 0 is the first button. */ - -static void -xg_tool_bar_proxy_callback (GtkWidget *w, gpointer client_data) -{ - GtkWidget *wbutton = GTK_WIDGET (g_object_get_data (G_OBJECT (w), - XG_TOOL_BAR_PROXY_BUTTON)); - xg_tool_bar_callback (wbutton, client_data); -} - - -static gboolean -xg_tool_bar_help_callback (GtkWidget *w, - GdkEventCrossing *event, - gpointer client_data); - -/* This callback is called when a help is to be shown for an item in - the detached tool bar when the detached tool bar it is not expanded. */ - -static gboolean -xg_tool_bar_proxy_help_callback (GtkWidget *w, - GdkEventCrossing *event, - gpointer client_data) -{ - GtkWidget *wbutton = GTK_WIDGET (g_object_get_data (G_OBJECT (w), - XG_TOOL_BAR_PROXY_BUTTON)); - - return xg_tool_bar_help_callback (wbutton, event, client_data); -} - static GtkWidget * xg_get_tool_bar_widgets (GtkWidget *vb, GtkWidget **wimage) { @@ -4027,187 +4088,6 @@ xg_get_tool_bar_widgets (GtkWidget *vb, GtkWidget **wimage) } -/* This callback is called when a tool item should create a proxy item, - such as for the overflow menu. Also called when the tool bar is detached. - If we don't create a proxy menu item, the detached tool bar will be - blank. */ - -static gboolean -xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data) -{ - GtkButton *wbutton = GTK_BUTTON (XG_BIN_CHILD (XG_BIN_CHILD (toolitem))); - GtkWidget *vb = XG_BIN_CHILD (wbutton); - GtkWidget *c1; - GtkLabel *wlbl = GTK_LABEL (xg_get_tool_bar_widgets (vb, &c1)); - GtkImage *wimage = GTK_IMAGE (c1); - GtkWidget *wmenuitem = gtk_image_menu_item_new_with_label - (wlbl ? gtk_label_get_text (wlbl) : ""); - GtkWidget *wmenuimage; - - - if (gtk_button_get_use_stock (wbutton)) - wmenuimage = gtk_image_new_from_stock (gtk_button_get_label (wbutton), - GTK_ICON_SIZE_MENU); - else - { - GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (wbutton)); - GtkImageType store_type = gtk_image_get_storage_type (wimage); - - g_object_set (G_OBJECT (settings), "gtk-menu-images", TRUE, NULL); - - if (store_type == GTK_IMAGE_STOCK) - { - gchar *stock_id; - gtk_image_get_stock (wimage, &stock_id, NULL); - wmenuimage = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU); - } - else if (store_type == GTK_IMAGE_ICON_SET) - { - GtkIconSet *icon_set; - gtk_image_get_icon_set (wimage, &icon_set, NULL); - wmenuimage = gtk_image_new_from_icon_set (icon_set, - GTK_ICON_SIZE_MENU); - } - else if (store_type == GTK_IMAGE_PIXBUF) - { - gint width, height; - - if (settings && - gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, - &width, &height)) - { - GdkPixbuf *src_pixbuf, *dest_pixbuf; - - src_pixbuf = gtk_image_get_pixbuf (wimage); - dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height, - GDK_INTERP_BILINEAR); - - wmenuimage = gtk_image_new_from_pixbuf (dest_pixbuf); - } - else - { - fprintf (stderr, "internal error: GTK_IMAGE_PIXBUF failed\n"); - emacs_abort (); - } - } - else if (store_type == GTK_IMAGE_ICON_NAME) - { - const gchar *icon_name; - GtkIconSize icon_size; - - gtk_image_get_icon_name (wimage, &icon_name, &icon_size); - wmenuimage = gtk_image_new_from_icon_name (icon_name, - GTK_ICON_SIZE_MENU); - } - else - { - fprintf (stderr, "internal error: store_type is %d\n", store_type); - emacs_abort (); - } - } - if (wmenuimage) - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (wmenuitem), wmenuimage); - - g_signal_connect (G_OBJECT (wmenuitem), - "activate", - G_CALLBACK (xg_tool_bar_proxy_callback), - user_data); - - - g_object_set_data (G_OBJECT (wmenuitem), XG_TOOL_BAR_PROXY_BUTTON, - (gpointer) wbutton); - gtk_tool_item_set_proxy_menu_item (toolitem, "Emacs toolbar item", wmenuitem); - gtk_widget_set_sensitive (wmenuitem, - gtk_widget_get_sensitive (GTK_WIDGET (wbutton))); - - /* Use enter/leave notify to show help. We use the events - rather than the GtkButton specific signals "enter" and - "leave", so we can have only one callback. The event - will tell us what kind of event it is. */ - g_signal_connect (G_OBJECT (wmenuitem), - "enter-notify-event", - G_CALLBACK (xg_tool_bar_proxy_help_callback), - user_data); - g_signal_connect (G_OBJECT (wmenuitem), - "leave-notify-event", - G_CALLBACK (xg_tool_bar_proxy_help_callback), - user_data); - - return TRUE; -} - -/* This callback is called when a tool bar is detached. We must set - the height of the tool bar to zero when this happens so frame sizes - are correctly calculated. - WBOX is the handle box widget that enables detach/attach of the tool bar. - W is the tool bar widget. - CLIENT_DATA is a pointer to the frame the tool bar belongs to. */ - -static void -xg_tool_bar_detach_callback (GtkHandleBox *wbox, - GtkWidget *w, - gpointer client_data) -{ - struct frame *f = client_data; - - g_object_set (G_OBJECT (w), "show-arrow", !x_gtk_whole_detached_tool_bar, - NULL); - - if (f) - { - GtkRequisition req, req2; - - gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req); - gtk_widget_get_preferred_size (w, NULL, &req2); - req.width -= req2.width; - req.height -= req2.height; - if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0) - FRAME_TOOLBAR_TOP_HEIGHT (f) = req.height; - else if (FRAME_TOOLBAR_BOTTOM_HEIGHT (f) != 0) - FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = req.height; - else if (FRAME_TOOLBAR_RIGHT_WIDTH (f) != 0) - FRAME_TOOLBAR_RIGHT_WIDTH (f) = req.width; - else if (FRAME_TOOLBAR_LEFT_WIDTH (f) != 0) - FRAME_TOOLBAR_LEFT_WIDTH (f) = req.width; - xg_height_or_width_changed (f); - } -} - -/* This callback is called when a tool bar is reattached. We must set - the height of the tool bar when this happens so frame sizes - are correctly calculated. - WBOX is the handle box widget that enables detach/attach of the tool bar. - W is the tool bar widget. - CLIENT_DATA is a pointer to the frame the tool bar belongs to. */ - -static void -xg_tool_bar_attach_callback (GtkHandleBox *wbox, - GtkWidget *w, - gpointer client_data) -{ - struct frame *f = client_data; - g_object_set (G_OBJECT (w), "show-arrow", TRUE, NULL); - - if (f) - { - GtkRequisition req, req2; - - gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req); - gtk_widget_get_preferred_size (w, NULL, &req2); - req.width += req2.width; - req.height += req2.height; - if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0) - FRAME_TOOLBAR_TOP_HEIGHT (f) = req.height; - else if (FRAME_TOOLBAR_BOTTOM_HEIGHT (f) != 0) - FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = req.height; - else if (FRAME_TOOLBAR_RIGHT_WIDTH (f) != 0) - FRAME_TOOLBAR_RIGHT_WIDTH (f) = req.width; - else if (FRAME_TOOLBAR_LEFT_WIDTH (f) != 0) - FRAME_TOOLBAR_LEFT_WIDTH (f) = req.width; - xg_height_or_width_changed (f); - } -} - /* This callback is called when the mouse enters or leaves a tool bar item. It is used for displaying and hiding the help text. W is the tool bar item, a button. @@ -4287,12 +4167,6 @@ xg_tool_bar_item_expose_callback (GtkWidget *w, gtk_toolbar_set_orientation (GTK_TOOLBAR (w), o) #endif -#ifdef HAVE_GTK_HANDLE_BOX_NEW -#define TOOLBAR_TOP_WIDGET(x) ((x)->handlebox_widget) -#else -#define TOOLBAR_TOP_WIDGET(x) ((x)->toolbar_widget) -#endif - /* Attach a tool bar to frame F. */ static void @@ -4300,31 +4174,15 @@ xg_pack_tool_bar (struct frame *f, Lisp_Object pos) { struct x_output *x = f->output_data.x; bool into_hbox = EQ (pos, Qleft) || EQ (pos, Qright); - GtkWidget *top_widget = TOOLBAR_TOP_WIDGET (x); + GtkWidget *top_widget = x->toolbar_widget; toolbar_set_orientation (x->toolbar_widget, into_hbox ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); -#ifdef HAVE_GTK_HANDLE_BOX_NEW - if (!x->handlebox_widget) - { - top_widget = x->handlebox_widget = gtk_handle_box_new (); - g_signal_connect (G_OBJECT (x->handlebox_widget), "child-detached", - G_CALLBACK (xg_tool_bar_detach_callback), f); - g_signal_connect (G_OBJECT (x->handlebox_widget), "child-attached", - G_CALLBACK (xg_tool_bar_attach_callback), f); - gtk_container_add (GTK_CONTAINER (x->handlebox_widget), - x->toolbar_widget); - } -#endif if (into_hbox) { -#ifdef HAVE_GTK_HANDLE_BOX_NEW - gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (x->handlebox_widget), - GTK_POS_TOP); -#endif gtk_box_pack_start (GTK_BOX (x->hbox_widget), top_widget, FALSE, FALSE, 0); @@ -4337,10 +4195,6 @@ xg_pack_tool_bar (struct frame *f, Lisp_Object pos) else { bool vbox_pos = x->menubar_widget != 0; -#ifdef HAVE_GTK_HANDLE_BOX_NEW - gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (x->handlebox_widget), - GTK_POS_LEFT); -#endif gtk_box_pack_start (GTK_BOX (x->vbox_widget), top_widget, FALSE, FALSE, 0); @@ -4493,10 +4347,6 @@ xg_make_tool_item (struct frame *f, intptr_t ii = i; gpointer gi = (gpointer) ii; - g_signal_connect (G_OBJECT (ti), "create-menu-proxy", - G_CALLBACK (xg_tool_bar_menu_proxy), - gi); - g_signal_connect (G_OBJECT (wb), "clicked", G_CALLBACK (xg_tool_bar_callback), gi); @@ -4610,7 +4460,7 @@ xg_update_tool_bar_sizes (struct frame *f) struct x_output *x = f->output_data.x; GtkRequisition req; int nl = 0, nr = 0, nt = 0, nb = 0; - GtkWidget *top_widget = TOOLBAR_TOP_WIDGET (x); + GtkWidget *top_widget = x->toolbar_widget; gtk_widget_get_preferred_size (GTK_WIDGET (top_widget), NULL, &req); if (x->toolbar_in_hbox) @@ -4649,6 +4499,42 @@ xg_update_tool_bar_sizes (struct frame *f) return 0; } +static char * +find_icon_from_name (char *name, + GtkIconTheme *icon_theme, + char **icon_name) +{ +#if ! GTK_CHECK_VERSION (3, 10, 0) + GtkStockItem stock_item; +#endif + + if (name[0] == 'n' && name[1] == ':') + { + *icon_name = name + 2; + name = NULL; + + if (! gtk_icon_theme_has_icon (icon_theme, *icon_name)) + *icon_name = NULL; + } + +#if ! GTK_CHECK_VERSION (3, 10, 0) + else if (gtk_stock_lookup (name, &stock_item)) + *icon_name = NULL; +#endif + else if (gtk_icon_theme_has_icon (icon_theme, name)) + { + *icon_name = name; + name = NULL; + } + else + { + name = NULL; + *icon_name = NULL; + } + + return name; +} + /* Update the tool bar for frame F. Add new buttons and remove old. */ @@ -4664,6 +4550,9 @@ update_frame_tool_bar (struct frame *f) Lisp_Object style; bool text_image, horiz; struct xg_frame_tb_info *tbinfo; + GdkScreen *screen; + GtkIconTheme *icon_theme; + if (! FRAME_GTK_WIDGET (f)) return; @@ -4698,6 +4587,8 @@ update_frame_tool_bar (struct frame *f) dir = gtk_widget_get_direction (GTK_WIDGET (wtoolbar)); style = Ftool_bar_get_system_style (); + screen = gtk_widget_get_screen (GTK_WIDGET (wtoolbar)); + icon_theme = gtk_icon_theme_get_for_screen (screen); /* Are we up to date? */ tbinfo = g_object_get_data (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), @@ -4734,7 +4625,6 @@ update_frame_tool_bar (struct frame *f) struct image *img = NULL; Lisp_Object image; Lisp_Object stock = Qnil; - GtkStockItem stock_item; char *stock_name = NULL; char *icon_name = NULL; Lisp_Object rtl; @@ -4788,32 +4678,28 @@ update_frame_tool_bar (struct frame *f) if (!NILP (specified_file) && !NILP (Ffboundp (Qx_gtk_map_stock))) stock = call1 (Qx_gtk_map_stock, specified_file); - if (STRINGP (stock)) + if (CONSP (stock)) { - stock_name = SSDATA (stock); - if (stock_name[0] == 'n' && stock_name[1] == ':') - { - GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (wtoolbar)); - GtkIconTheme *icon_theme = gtk_icon_theme_get_for_screen (screen); - - icon_name = stock_name + 2; - stock_name = NULL; - stock = Qnil; - - if (! gtk_icon_theme_has_icon (icon_theme, icon_name)) - icon_name = NULL; - else - icon_size = gtk_toolbar_get_icon_size (wtoolbar); - } - else if (gtk_stock_lookup (SSDATA (stock), &stock_item)) - icon_size = gtk_toolbar_get_icon_size (wtoolbar); - else - { - stock = Qnil; - stock_name = NULL; - } + Lisp_Object tem; + for (tem = stock; CONSP (tem); tem = XCDR (tem)) + if (! NILP (tem) && STRINGP (XCAR (tem))) + { + stock_name = find_icon_from_name (SSDATA (XCAR (tem)), + icon_theme, + &icon_name); + if (stock_name || icon_name) break; + } + } + else if (STRINGP (stock)) + { + stock_name = find_icon_from_name (SSDATA (stock), + icon_theme, + &icon_name); } + if (stock_name || icon_name) + icon_size = gtk_toolbar_get_icon_size (wtoolbar); + if (stock_name == NULL && icon_name == NULL) { /* No stock image, or stock item not known. Try regular @@ -4874,7 +4760,12 @@ update_frame_tool_bar (struct frame *f) w = NULL; else if (stock_name) { + +#if GTK_CHECK_VERSION (3, 10, 0) + w = gtk_image_new_from_icon_name (stock_name, icon_size); +#else w = gtk_image_new_from_stock (stock_name, icon_size); +#endif g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME, (gpointer) xstrdup (stock_name), (GDestroyNotify) xfree); @@ -4893,7 +4784,17 @@ update_frame_tool_bar (struct frame *f) (gpointer)img->pixmap); } +#if GTK_CHECK_VERSION (3, 14, 0) + if (w) + { + gtk_widget_set_margin_start (w, hmargin); + gtk_widget_set_margin_end (w, hmargin); + gtk_widget_set_margin_top (w, vmargin); + gtk_widget_set_margin_bottom (w, vmargin); + } +#else if (w) gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); +#endif ti = xg_make_tool_item (f, w, &wbutton, label, i, horiz, text_image); gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j); } @@ -4915,8 +4816,8 @@ update_frame_tool_bar (struct frame *f) if (f->n_tool_bar_items != 0) { if (! x->toolbar_is_packed) - xg_pack_tool_bar (f, f->tool_bar_position); - gtk_widget_show_all (TOOLBAR_TOP_WIDGET (x)); + xg_pack_tool_bar (f, FRAME_TOOL_BAR_POSITION (f)); + gtk_widget_show_all (x->toolbar_widget); if (xg_update_tool_bar_sizes (f)) xg_height_or_width_changed (f); } @@ -4935,11 +4836,9 @@ free_frame_tool_bar (struct frame *f) if (x->toolbar_widget) { struct xg_frame_tb_info *tbinfo; - GtkWidget *top_widget = TOOLBAR_TOP_WIDGET (x); + GtkWidget *top_widget = x->toolbar_widget; block_input (); - /* We may have created the toolbar_widget in xg_create_tool_bar, but - not the x->handlebox_widget which is created in xg_pack_tool_bar. */ if (x->toolbar_is_packed) { if (x->toolbar_in_hbox) @@ -4953,7 +4852,7 @@ free_frame_tool_bar (struct frame *f) gtk_widget_destroy (x->toolbar_widget); x->toolbar_widget = 0; - TOOLBAR_TOP_WIDGET (x) = 0; + x->toolbar_widget = 0; x->toolbar_is_packed = false; FRAME_TOOLBAR_TOP_HEIGHT (f) = FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = 0; FRAME_TOOLBAR_LEFT_WIDTH (f) = FRAME_TOOLBAR_RIGHT_WIDTH (f) = 0; @@ -4978,7 +4877,7 @@ void xg_change_toolbar_position (struct frame *f, Lisp_Object pos) { struct x_output *x = f->output_data.x; - GtkWidget *top_widget = TOOLBAR_TOP_WIDGET (x); + GtkWidget *top_widget = x->toolbar_widget; if (! x->toolbar_widget || ! top_widget) return; @@ -5022,9 +4921,6 @@ xg_initialize (void) gdpy_def = NULL; xg_ignore_gtk_scrollbar = 0; -#ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW - xg_detached_menus = 0; -#endif xg_menu_cb_list.prev = xg_menu_cb_list.next = xg_menu_item_cb_list.prev = xg_menu_item_cb_list.next = 0; @@ -5060,6 +4956,7 @@ xg_initialize (void) gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK, "cancel", 0); update_theme_scrollbar_width (); + update_theme_scrollbar_height (); #ifdef HAVE_FREETYPE x_last_font_name = NULL; diff --git a/src/gtkutil.h b/src/gtkutil.h index 12bf461fd69..594c7a7382b 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #ifdef USE_GTK #include <gtk/gtk.h> +#include "../lwlib/lwlib-widget.h" #include "frame.h" #include "xterm.h" @@ -32,6 +33,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define XG_SB_MIN 1 #define XG_SB_MAX 10000000 #define XG_SB_RANGE (XG_SB_MAX-XG_SB_MIN) +#define YG_SB_MIN 1 +#define YG_SB_MAX 10000000 +#define YG_SB_RANGE (YG_SB_MAX-YG_SB_MIN) /* Key for data that is valid for menus and scroll bars in a frame */ #define XG_FRAME_DATA "emacs_frame" @@ -74,9 +78,6 @@ typedef struct xg_menu_item_cb_data_ } xg_menu_item_cb_data; -extern struct _widget_value *malloc_widget_value (void); -extern void free_widget_value (struct _widget_value *); - extern bool xg_uses_old_file_dialog (void) ATTRIBUTE_CONST; extern char *xg_get_file_name (struct frame *f, @@ -107,8 +108,6 @@ extern void xg_update_frame_menubar (struct frame *f); extern bool xg_event_is_for_menubar (struct frame *, const XEvent *); -extern bool xg_have_tear_offs (struct frame *f); - extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid); extern void xg_create_scroll_bar (struct frame *f, @@ -116,6 +115,11 @@ extern void xg_create_scroll_bar (struct frame *f, GCallback scroll_callback, GCallback end_callback, const char *scroll_bar_name); +extern void xg_create_horizontal_scroll_bar (struct frame *f, + struct scroll_bar *bar, + GCallback scroll_callback, + GCallback end_callback, + const char *scroll_bar_name); extern void xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id); extern void xg_update_scrollbar_pos (struct frame *f, @@ -124,18 +128,30 @@ extern void xg_update_scrollbar_pos (struct frame *f, int left, int width, int height); +extern void xg_update_horizontal_scrollbar_pos (struct frame *f, + ptrdiff_t scrollbar_id, + int top, + int left, + int width, + int height); extern void xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole); +extern void xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, + int portion, + int position, + int whole); extern bool xg_event_is_for_scrollbar (struct frame *, const XEvent *); extern int xg_get_default_scrollbar_width (void); +extern int xg_get_default_scrollbar_height (void); extern void update_frame_tool_bar (struct frame *f); extern void free_frame_tool_bar (struct frame *f); extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos); +extern void xg_clear_under_internal_border (struct frame *f); extern void xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight); @@ -164,7 +180,6 @@ extern bool xg_prepare_tooltip (struct frame *f, extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); extern bool xg_hide_tooltip (struct frame *f); - /* Mark all callback data that are Lisp_object:s during GC. */ extern void xg_mark_data (void); diff --git a/src/image.c b/src/image.c index b47a35dd713..4b73a5fe80c 100644 --- a/src/image.c +++ b/src/image.c @@ -21,13 +21,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "sysstdio.h" #include <unistd.h> -#ifdef HAVE_PNG -#if defined HAVE_LIBPNG_PNG_H -# include <libpng/png.h> -#else +/* Include this before including <setjmp.h> to work around bugs with + older libpng; see Bug#17429. */ +#if defined HAVE_PNG && !defined HAVE_NS # include <png.h> #endif -#endif #include <setjmp.h> #include <c-ctype.h> @@ -160,6 +158,7 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) /* Functions to access the contents of a bitmap, given an id. */ +#ifdef HAVE_X_WINDOWS static int x_bitmap_height (struct frame *f, ptrdiff_t id) { @@ -171,6 +170,7 @@ x_bitmap_width (struct frame *f, ptrdiff_t id) { return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].width; } +#endif #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) ptrdiff_t @@ -998,6 +998,11 @@ free_image (struct frame *f, struct image *img) c->images[img->id] = NULL; + /* Windows NT redefines 'free', but in this file, we need to + avoid the redefinition. */ +#ifdef WINDOWSNT +#undef free +#endif /* Free resources, then free IMG. */ img->type->free (f, img); xfree (img); @@ -1231,7 +1236,23 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D return img->background_transparent; } - +#if defined (HAVE_PNG) || defined (HAVE_NS) \ + || defined (HAVE_IMAGEMAGICK) || defined (HAVE_RSVG) + +/* Store F's background color into *BGCOLOR. */ +static void +x_query_frame_background_color (struct frame *f, XColor *bgcolor) +{ +#ifndef HAVE_NS + bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f); + x_query_color (f, bgcolor); +#else + ns_query_color (FRAME_BACKGROUND_COLOR (f), bgcolor, 1); +#endif +} + +#endif /* HAVE_PNG || HAVE_NS || HAVE_IMAGEMAGICK || HAVE_RSVG */ + /*********************************************************************** Helper functions for X image types ***********************************************************************/ @@ -3016,13 +3037,16 @@ xbm_load (struct frame *f, struct image *img) + SBYTES (data))); else { + USE_SAFE_ALLOCA; + if (VECTORP (data)) { int i; char *p; int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR; - p = bits = alloca (nbytes * img->height); + SAFE_NALLOCA (bits, nbytes, img->height); + p = bits; for (i = 0; i < img->height; ++i, p += nbytes) { Lisp_Object line = AREF (data, i); @@ -3043,9 +3067,8 @@ xbm_load (struct frame *f, struct image *img) int nbytes, i; /* Windows mono bitmaps are reversed compared with X. */ invertedBits = bits; - nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR - * img->height; - bits = alloca (nbytes); + nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR; + SAFE_NALLOCA (bits, nbytes, img->height); for (i = 0; i < nbytes; i++) bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]); } @@ -3067,6 +3090,8 @@ xbm_load (struct frame *f, struct image *img) img->spec, Qnil); x_clear_image (f, img); } + + SAFE_FREE (); } } @@ -3473,6 +3498,8 @@ xpm_load (struct frame *f, struct image *img) int rc; XpmAttributes attrs; Lisp_Object specified_file, color_symbols; + USE_SAFE_ALLOCA; + #ifdef HAVE_NTGUI HDC hdc; xpm_XImage * xpm_image = NULL, * xpm_mask = NULL; @@ -3515,7 +3542,7 @@ xpm_load (struct frame *f, struct image *img) { Lisp_Object tail; XpmColorSymbol *xpm_syms; - int i, size; + ptrdiff_t i, size; attrs.valuemask |= XpmColorSymbols; @@ -3525,8 +3552,8 @@ xpm_load (struct frame *f, struct image *img) ++attrs.numsymbols; /* Allocate an XpmColorSymbol array. */ + SAFE_NALLOCA (xpm_syms, 1, attrs.numsymbols); size = attrs.numsymbols * sizeof *xpm_syms; - xpm_syms = alloca (size); memset (xpm_syms, 0, size); attrs.colorsymbols = xpm_syms; @@ -3548,17 +3575,11 @@ xpm_load (struct frame *f, struct image *img) name = XCAR (XCAR (tail)); color = XCDR (XCAR (tail)); if (STRINGP (name)) - { - xpm_syms[i].name = alloca (SCHARS (name) + 1); - strcpy (xpm_syms[i].name, SSDATA (name)); - } + SAFE_ALLOCA_STRING (xpm_syms[i].name, name); else xpm_syms[i].name = empty_string; if (STRINGP (color)) - { - xpm_syms[i].value = alloca (SCHARS (color) + 1); - strcpy (xpm_syms[i].value, SSDATA (color)); - } + SAFE_ALLOCA_STRING (xpm_syms[i].value, color); else xpm_syms[i].value = empty_string; } @@ -3589,6 +3610,7 @@ xpm_load (struct frame *f, struct image *img) #ifdef ALLOC_XPM_COLORS xpm_free_color_cache (); #endif + SAFE_FREE (); return 0; } @@ -3619,6 +3641,7 @@ xpm_load (struct frame *f, struct image *img) #ifdef ALLOC_XPM_COLORS xpm_free_color_cache (); #endif + SAFE_FREE (); return 0; } #ifdef HAVE_NTGUI @@ -3761,6 +3784,7 @@ xpm_load (struct frame *f, struct image *img) #ifdef ALLOC_XPM_COLORS xpm_free_color_cache (); #endif + SAFE_FREE (); return rc == XpmSuccess; } @@ -3953,9 +3977,7 @@ xpm_str_to_color_key (const char *s) { int i; - for (i = 0; - i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0]; - i++) + for (i = 0; i < ARRAYELTS (xpm_color_key_strings); i++) if (strcmp (xpm_color_key_strings[i], s) == 0) return i; return -1; @@ -5506,7 +5528,7 @@ png_image_p (Lisp_Object object) #endif /* HAVE_PNG || HAVE_NS */ -#ifdef HAVE_PNG +#if defined HAVE_PNG && !defined HAVE_NS #ifdef WINDOWSNT /* PNG library details. */ @@ -5884,43 +5906,23 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) /* png_color_16 *image_bg; */ Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); - int shift = (bit_depth == 16) ? 0 : 8; + XColor color; - if (STRINGP (specified_bg)) + /* If the user specified a color, try to use it; if not, use the + current frame background, ignoring any default background + color set by the image. */ + if (STRINGP (specified_bg) + ? x_defined_color (f, SSDATA (specified_bg), &color, false) + : (x_query_frame_background_color (f, &color), true)) /* The user specified `:background', use that. */ { - XColor color; - if (x_defined_color (f, SSDATA (specified_bg), &color, 0)) - { - png_color_16 user_bg; - - memset (&user_bg, 0, sizeof user_bg); - user_bg.red = color.red >> shift; - user_bg.green = color.green >> shift; - user_bg.blue = color.blue >> shift; - - fn_png_set_background (png_ptr, &user_bg, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - } - } - else - { - /* We use the current frame background, ignoring any default - background color set by the image. */ -#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) - XColor color; - png_color_16 frame_background; + int shift = bit_depth == 16 ? 0 : 8; + png_color_16 bg = { 0 }; + bg.red = color.red >> shift; + bg.green = color.green >> shift; + bg.blue = color.blue >> shift; - color.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &color); - - memset (&frame_background, 0, sizeof frame_background); - frame_background.red = color.red >> shift; - frame_background.green = color.green >> shift; - frame_background.blue = color.blue >> shift; -#endif /* HAVE_X_WINDOWS */ - - fn_png_set_background (png_ptr, &frame_background, + fn_png_set_background (png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } @@ -6062,9 +6064,8 @@ png_load (struct frame *f, struct image *img) return png_load_body (f, img, &c); } -#else /* HAVE_PNG */ +#elif defined HAVE_NS -#ifdef HAVE_NS static bool png_load (struct frame *f, struct image *img) { @@ -6072,10 +6073,8 @@ png_load (struct frame *f, struct image *img) image_spec_value (img->spec, QCfile, NULL), image_spec_value (img->spec, QCdata, NULL)); } -#endif /* HAVE_NS */ - -#endif /* !HAVE_PNG */ +#endif /* HAVE_NS */ @@ -6466,7 +6465,6 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp) src->mgr.next_input_byte = NULL; } - /* Load image IMG for use on frame F. Patterned after example.c from the JPEG lib. */ @@ -6585,6 +6583,7 @@ jpeg_load_body (struct frame *f, struct image *img, colors generated, and mgr->cinfo.colormap is a two-dimensional array of color indices in the range 0..mgr->cinfo.actual_number_of_colors. No more than 255 colors will be generated. */ + USE_SAFE_ALLOCA; { int i, ir, ig, ib; @@ -6600,7 +6599,7 @@ jpeg_load_body (struct frame *f, struct image *img, a default color, and we don't have to care about which colors can be freed safely, and which can't. */ init_color_table (); - colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors); + SAFE_NALLOCA (colors, 1, mgr->cinfo.actual_number_of_colors); for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i) { @@ -6643,6 +6642,7 @@ jpeg_load_body (struct frame *f, struct image *img, /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); + SAFE_FREE (); return 1; } @@ -8064,7 +8064,6 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino) else composite_wand = cache->wand; - dest_width = MagickGetImageWidth (composite_wand); dest_height = MagickGetImageHeight (composite_wand); for (i = max (1, cache->index + 1); i <= ino; i++) @@ -8133,13 +8132,12 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino) { /* Sanity check. This shouldn't happen, but apparently also does in some pictures. */ - if (x + source_left > dest_width - 1) + if (x + source_left >= dest_width) break; /* Normally we only copy over non-transparent pixels, but if the disposal method is "Background", then we copy over all pixels. */ - if (dispose == BackgroundDispose || - PixelGetAlpha (source[x])) + if (dispose == BackgroundDispose || PixelGetAlpha (source[x])) { PixelGetMagickColor (source[x], &pixel); PixelSetMagickColor (dest[x + source_left], &pixel); @@ -8179,7 +8177,8 @@ imagemagick_load_image (struct frame *f, struct image *img, unsigned char *contents, unsigned int size, char *filename) { - size_t width, height; + int width, height; + size_t image_width, image_height; MagickBooleanType status; XImagePtr ximg; int x, y; @@ -8264,14 +8263,7 @@ imagemagick_load_image (struct frame *f, struct image *img, specified_bg = image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg) || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0)) - { -#ifndef HAVE_NS - bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &bgcolor); -#else - ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1); -#endif - } + x_query_frame_background_color (f, &bgcolor); bg_wand = NewPixelWand (); PixelSetRed (bg_wand, (double) bgcolor.red / 65535); @@ -8362,16 +8354,19 @@ imagemagick_load_image (struct frame *f, struct image *img, /* Finally we are done manipulating the image. Figure out the resulting width/height and transfer ownership to Emacs. */ - height = MagickGetImageHeight (image_wand); - width = MagickGetImageWidth (image_wand); + image_height = MagickGetImageHeight (image_wand); + image_width = MagickGetImageWidth (image_wand); - if (! (width <= INT_MAX && height <= INT_MAX - && check_image_size (f, width, height))) + if (! (image_width <= INT_MAX && image_height <= INT_MAX + && check_image_size (f, image_width, image_height))) { image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); goto imagemagick_error; } + width = image_width; + height = image_height; + /* We can now get a valid pixel buffer from the imagemagick file, if all went ok. */ @@ -8423,6 +8418,7 @@ imagemagick_load_image (struct frame *f, struct image *img, #endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */ { size_t image_height; + MagickRealType color_scale = 65535.0 / QuantumRange; /* Try to create a x pixmap to hold the imagemagick pixmap. */ if (!image_create_x_image_and_pixmap (f, img, width, height, 0, @@ -8455,17 +8451,19 @@ imagemagick_load_image (struct frame *f, struct image *img, image_height = MagickGetImageHeight (image_wand); for (y = 0; y < image_height; y++) { - pixels = PixelGetNextIteratorRow (iterator, &width); + size_t row_width; + pixels = PixelGetNextIteratorRow (iterator, &row_width); if (! pixels) break; - for (x = 0; x < (long) width; x++) + int xlim = min (row_width, width); + for (x = 0; x < xlim; x++) { PixelGetMagickColor (pixels[x], &pixel); XPutPixel (ximg, x, y, lookup_rgb_color (f, - pixel.red, - pixel.green, - pixel.blue)); + color_scale * pixel.red, + color_scale * pixel.green, + color_scale * pixel.blue)); } } DestroyPixelIterator (iterator); @@ -8566,7 +8564,6 @@ and `imagemagick-types-inhibit'. */) ExceptionInfo ex; char **imtypes; size_t i; - Lisp_Object Qimagemagicktype; GetExceptionInfo(&ex); imtypes = GetMagickList ("*", &numf, &ex); @@ -8574,8 +8571,8 @@ and `imagemagick-types-inhibit'. */) for (i = 0; i < numf; i++) { - Qimagemagicktype = intern (imtypes[i]); - typelist = Fcons (Qimagemagicktype, typelist); + Lisp_Object imagemagicktype = intern (imtypes[i]); + typelist = Fcons (imagemagicktype, typelist); imtypes[i] = MagickRelinquishMemory (imtypes[i]); } @@ -8687,7 +8684,6 @@ DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions, (RsvgHandle *, RsvgDimensionDat DEF_IMGLIB_FN (gboolean, rsvg_handle_write, (RsvgHandle *, const guchar *, gsize, GError **)); DEF_IMGLIB_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **)); DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *)); -DEF_IMGLIB_FN (void *, rsvg_handle_set_size_callback, (RsvgHandle *, RsvgSizeFunc, gpointer, GDestroyNotify)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_height, (const GdkPixbuf *)); @@ -8709,13 +8705,18 @@ Lisp_Object Qgdk_pixbuf, Qglib, Qgobject; static bool init_svg_functions (void) { - HMODULE library, gdklib, glib, gobject; + HMODULE library, gdklib = NULL, glib = NULL, gobject = NULL; if (!(glib = w32_delayed_load (Qglib)) || !(gobject = w32_delayed_load (Qgobject)) || !(gdklib = w32_delayed_load (Qgdk_pixbuf)) || !(library = w32_delayed_load (Qsvg))) - return 0; + { + if (gdklib) FreeLibrary (gdklib); + if (gobject) FreeLibrary (gobject); + if (glib) FreeLibrary (glib); + return 0; + } LOAD_IMGLIB_FN (library, rsvg_handle_new); LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions); @@ -8903,14 +8904,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * specified_bg = image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg) || !x_defined_color (f, SSDATA (specified_bg), &background, 0)) - { -#ifndef HAVE_NS - background.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &background); -#else - ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1); -#endif - } + x_query_frame_background_color (f, &background); /* SVG pixmaps specify transparency in the last byte, so right shift 8 bits to get rid of it, since emacs doesn't support diff --git a/src/indent.c b/src/indent.c index 026f44ccf9c..e6b267a3891 100644 --- a/src/indent.c +++ b/src/indent.c @@ -920,7 +920,7 @@ position_indentation (ptrdiff_t pos_byte) column += tab_width - column % tab_width; break; default: - if (ASCII_BYTE_P (p[-1]) + if (ASCII_CHAR_P (p[-1]) || NILP (BVAR (current_buffer, enable_multibyte_characters))) return column; { diff --git a/src/insdel.c b/src/insdel.c index 85526d46db1..463392dcada 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1,6 +1,6 @@ /* Buffer insertion/deletion and gap motion for GNU Emacs. - Copyright (C) 1985-1986, 1993-1995, 1997-2014 Free Software - Foundation, Inc. + +Copyright (C) 1985-1986, 1993-1995, 1997-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -203,6 +203,25 @@ gap_right (ptrdiff_t charpos, ptrdiff_t bytepos) QUIT; } +/* If the selected window's old pointm is adjacent or covered by the + region from FROM to TO, unsuspend auto hscroll in that window. */ + +static void +adjust_suspend_auto_hscroll (ptrdiff_t from, ptrdiff_t to) +{ + if (WINDOWP (selected_window)) + { + struct window *w = XWINDOW (selected_window); + + if (BUFFERP (w->contents) + && XBUFFER (w->contents) == current_buffer + && XMARKER (w->old_pointm)->charpos >= from + && XMARKER (w->old_pointm)->charpos <= to) + w->suspend_auto_hscroll = 0; + } +} + + /* Adjust all markers for a deletion whose range in bytes is FROM_BYTE to TO_BYTE. The range in charpos is FROM to TO. @@ -217,6 +236,7 @@ adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, struct Lisp_Marker *m; ptrdiff_t charpos; + adjust_suspend_auto_hscroll (from, to); for (m = BUF_MARKERS (current_buffer); m; m = m->next) { charpos = m->charpos; @@ -256,6 +276,7 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t nchars = to - from; ptrdiff_t nbytes = to_byte - from_byte; + adjust_suspend_auto_hscroll (from, to); for (m = BUF_MARKERS (current_buffer); m; m = m->next) { eassert (m->bytepos >= m->charpos @@ -321,6 +342,7 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t diff_chars = new_chars - old_chars; ptrdiff_t diff_bytes = new_bytes - old_bytes; + adjust_suspend_auto_hscroll (from, from + old_chars); for (m = BUF_MARKERS (current_buffer); m; m = m->next) { if (m->bytepos >= prev_to_byte) @@ -701,7 +723,7 @@ count_combining_after (const unsigned char *string, (2) POS is the last of the current buffer. (3) A character at POS can't be a following byte of multibyte character. */ - if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */ + if (length > 0 && ASCII_CHAR_P (string[length - 1])) /* case (1) */ return 0; if (pos_byte == Z_BYTE) /* case (2) */ return 0; @@ -1804,26 +1826,18 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, else base_buffer = current_buffer; -#ifdef CLASH_DETECTION + if (inhibit_modification_hooks) + return; + if (!NILP (BVAR (base_buffer, file_truename)) /* Make binding buffer-file-name to nil effective. */ && !NILP (BVAR (base_buffer, filename)) && SAVE_MODIFF >= MODIFF) lock_file (BVAR (base_buffer, file_truename)); -#else - /* At least warn if this file has changed on disk since it was visited. */ - if (!NILP (BVAR (base_buffer, filename)) - && SAVE_MODIFF >= MODIFF - && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ())) - && !NILP (Ffile_exists_p (BVAR (base_buffer, filename)))) - call1 (intern ("ask-user-about-supersession-threat"), - BVAR (base_buffer,filename)); -#endif /* not CLASH_DETECTION */ /* If `select-active-regions' is non-nil, save the region text. */ /* FIXME: Move this to Elisp (via before-change-functions). */ if (!NILP (BVAR (current_buffer, mark_active)) - && !inhibit_modification_hooks && XMARKER (BVAR (current_buffer, mark))->buffer && NILP (Vsaved_region_selection) && (EQ (Vselect_active_regions, Qonly) @@ -1962,9 +1976,6 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, ptrdiff_t count = SPECPDL_INDEX (); struct rvoe_arg rvoe_arg; - if (inhibit_modification_hooks) - return; - start = make_number (start_int); end = make_number (end_int); preserve_marker = Qnil; @@ -1975,7 +1986,7 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, specbind (Qinhibit_modification_hooks, Qt); /* If buffer is unmodified, run a special hook for that case. The - check for Vfirst_change_hook is just a minor optimization. */ + check for Vfirst_change_hook is just a minor optimization. */ if (SAVE_MODIFF >= MODIFF && !NILP (Vfirst_change_hook)) { diff --git a/src/intervals.h b/src/intervals.h index e901f99747d..4e7a177140e 100644 --- a/src/intervals.h +++ b/src/intervals.h @@ -278,10 +278,8 @@ extern Lisp_Object Qpoint_entered; extern Lisp_Object Qmodification_hooks; extern Lisp_Object Qcategory; extern Lisp_Object Qlocal_map; -extern Lisp_Object Qkeymap; /* Visual properties text (including strings) may have. */ -extern Lisp_Object Qfont; extern Lisp_Object Qinvisible, Qintangible; /* Sticky properties. */ diff --git a/src/keyboard.c b/src/keyboard.c index eb27d6fefab..e8143f26681 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -133,6 +133,19 @@ static ptrdiff_t this_single_command_key_start; static ptrdiff_t before_command_key_count; static ptrdiff_t before_command_echo_length; +#ifdef HAVE_STACK_OVERFLOW_HANDLING + +/* For longjmp to recover from C stack overflow. */ +sigjmp_buf return_to_command_loop; + +/* Message displayed by Vtop_level when recovering from C stack overflow. */ +static Lisp_Object recover_top_level_message; + +#endif /* HAVE_STACK_OVERFLOW_HANDLING */ + +/* Message normally displayed by Vtop_level. */ +static Lisp_Object regular_top_level_message; + /* For longjmp to where kbd input is being done. */ static sys_jmp_buf getcjmp; @@ -228,7 +241,7 @@ static Lisp_Object Qbackward_char; Lisp_Object Qundefined; static Lisp_Object Qtimer_event_handler; -/* read_key_sequence stores here the command definition of the +/* `read_key_sequence' stores here the command definition of the key sequence that it reads. */ static Lisp_Object read_key_sequence_cmd; static Lisp_Object read_key_sequence_remapped; @@ -348,7 +361,6 @@ static Lisp_Object Qmodifier_cache; Lisp_Object Qmode_line; Lisp_Object Qvertical_line; Lisp_Object Qright_divider, Qbottom_divider; -static Lisp_Object Qvertical_scroll_bar; Lisp_Object Qmenu_bar; static Lisp_Object Qecho_keystrokes; @@ -356,7 +368,6 @@ static Lisp_Object Qecho_keystrokes; static void recursive_edit_unwind (Lisp_Object buffer); static Lisp_Object command_loop (void); static Lisp_Object Qcommand_execute; -struct timespec timer_check (void); static void echo_now (void); static ptrdiff_t echo_length (void); @@ -377,12 +388,6 @@ bool interrupt_input; /* Nonzero while interrupts are temporarily deferred during redisplay. */ bool interrupts_deferred; -/* If we support a window system, turn on the code to poll periodically - to detect C-g. It isn't actually used when doing interrupt input. */ -#ifdef HAVE_WINDOW_SYSTEM -#define POLL_FOR_INPUT -#endif - /* The time when Emacs started being idle. */ static struct timespec timer_idleness_start_time; @@ -495,10 +500,12 @@ kset_system_key_syms (struct kboard *kb, Lisp_Object val) static void echo_add_key (Lisp_Object c) { - int size = KEY_DESCRIPTION_SIZE + 100; - char *buffer = alloca (size); + char initbuf[KEY_DESCRIPTION_SIZE + 100]; + ptrdiff_t size = sizeof initbuf; + char *buffer = initbuf; char *ptr = buffer; Lisp_Object echo_string; + USE_SAFE_ALLOCA; echo_string = KVAR (current_kboard, echo_string); @@ -510,13 +517,13 @@ echo_add_key (Lisp_Object c) else if (SYMBOLP (c)) { Lisp_Object name = SYMBOL_NAME (c); - int nbytes = SBYTES (name); + ptrdiff_t nbytes = SBYTES (name); if (size - (ptr - buffer) < nbytes) { - int offset = ptr - buffer; + ptrdiff_t offset = ptr - buffer; size = max (2 * size, size + nbytes); - buffer = alloca (size); + buffer = SAFE_ALLOCA (size); ptr = buffer + offset; } @@ -527,14 +534,14 @@ echo_add_key (Lisp_Object c) if ((NILP (echo_string) || SCHARS (echo_string) == 0) && help_char_p (c)) { - const char *text = " (Type ? for further options)"; - int len = strlen (text); + static const char text[] = " (Type ? for further options)"; + int len = sizeof text - 1; if (size - (ptr - buffer) < len) { - int offset = ptr - buffer; + ptrdiff_t offset = ptr - buffer; size += len; - buffer = alloca (size); + buffer = SAFE_ALLOCA (size); ptr = buffer + offset; } @@ -544,6 +551,7 @@ echo_add_key (Lisp_Object c) /* Replace a dash from echo_dash with a space, otherwise add a space at the end as a separator between keys. */ + AUTO_STRING (space, " "); if (STRINGP (echo_string) && SCHARS (echo_string) > 1) { Lisp_Object last_char, prev_char, idx; @@ -559,14 +567,15 @@ echo_add_key (Lisp_Object c) if (XINT (last_char) == '-' && XINT (prev_char) != ' ') Faset (echo_string, idx, make_number (' ')); else - echo_string = concat2 (echo_string, build_string (" ")); + echo_string = concat2 (echo_string, space); } else if (STRINGP (echo_string) && SCHARS (echo_string) > 0) - echo_string = concat2 (echo_string, build_string (" ")); + echo_string = concat2 (echo_string, space); kset_echo_string (current_kboard, concat2 (echo_string, make_string (buffer, ptr - buffer))); + SAFE_FREE (); } /* Add C to the echo string, if echoing is going on. C can be a @@ -622,9 +631,9 @@ echo_dash (void) /* Put a dash at the end of the buffer temporarily, but make it go away when the next character is added. */ - kset_echo_string - (current_kboard, - concat2 (KVAR (current_kboard, echo_string), build_string ("-"))); + AUTO_STRING (dash, "-"); + kset_echo_string (current_kboard, + concat2 (KVAR (current_kboard, echo_string), dash)); echo_now (); } @@ -1117,7 +1126,7 @@ Default value of `command-error-function'. */) { print_error_message (data, Qexternal_debugging_output, SSDATA (context), signal); - Fterpri (Qexternal_debugging_output); + Fterpri (Qexternal_debugging_output, Qnil); Fkill_emacs (make_number (-1)); } else @@ -1142,6 +1151,17 @@ static Lisp_Object top_level_1 (Lisp_Object); Lisp_Object command_loop (void) { +#ifdef HAVE_STACK_OVERFLOW_HANDLING + /* At least on GNU/Linux, saving signal mask is important here. */ + if (sigsetjmp (return_to_command_loop, 1) != 0) + { + /* Comes here from handle_sigsegv, see sysdep.c. */ + init_eval (); + Vinternal__top_level_message = recover_top_level_message; + } + else + Vinternal__top_level_message = regular_top_level_message; +#endif /* HAVE_STACK_OVERFLOW_HANDLING */ if (command_loop_level > 0 || minibuf_level > 0) { Lisp_Object val; @@ -1222,7 +1242,7 @@ user_error (const char *msg) xsignal1 (Quser_error, build_string (msg)); } -_Noreturn +/* _Noreturn will be added to prototype by make-docfile. */ DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "", doc: /* Exit from the innermost recursive edit or minibuffer. */) (void) @@ -1233,7 +1253,7 @@ DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, user_error ("No recursive edit is in progress"); } -_Noreturn +/* _Noreturn will be added to prototype by make-docfile. */ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "", doc: /* Abort the command that requested this recursive edit or minibuffer input. */) (void) @@ -1266,13 +1286,9 @@ tracking_off (Lisp_Object old_value) } } -DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0, - doc: /* Evaluate BODY with mouse movement events enabled. -Within a `track-mouse' form, mouse motion generates input events that -you can read with `read-event'. -Normally, mouse motion is ignored. -usage: (track-mouse BODY...) */) - (Lisp_Object args) +DEFUN ("internal--track-mouse", Ftrack_mouse, Strack_mouse, 1, 1, 0, + doc: /* Call BODYFUN with mouse movement events enabled. */) + (Lisp_Object bodyfun) { ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object val; @@ -1281,7 +1297,7 @@ usage: (track-mouse BODY...) */) do_mouse_tracking = Qt; - val = Fprogn (args); + val = call0 (bodyfun); return unbind_to (count, val); } @@ -1292,9 +1308,6 @@ usage: (track-mouse BODY...) */) If ignore_mouse_drag_p is non-zero, ignore (implicit) mouse movement after resizing the tool-bar window. */ -#if !defined HAVE_WINDOW_SYSTEM || defined USE_GTK || defined HAVE_NS -static -#endif bool ignore_mouse_drag_p; static struct frame * @@ -1323,14 +1336,11 @@ some_mouse_moved (void) static int read_key_sequence (Lisp_Object *, int, Lisp_Object, bool, bool, bool, bool); -void safe_run_hooks (Lisp_Object); static void adjust_point_for_property (ptrdiff_t, bool); /* The last boundary auto-added to buffer-undo-list. */ Lisp_Object last_undo_boundary; -extern Lisp_Object Qregion_extract_function; - /* FIXME: This is wrong rather than test window-system, we should call a new set-selection, which will then dispatch to x-set-selection, or tty-set-selection, or w32-set-selection, ... */ @@ -1449,7 +1459,7 @@ command_loop_1 (void) Vthis_command_keys_shift_translated = Qnil; /* Read next key sequence; i gets its length. */ - i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0], + i = read_key_sequence (keybuf, ARRAYELTS (keybuf), Qnil, 0, 1, 1, 0); /* A filter may have run while we were reading the input. */ @@ -1697,7 +1707,7 @@ read_menu_command (void) menus. */ specbind (Qecho_keystrokes, make_number (0)); - i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0], + i = read_key_sequence (keybuf, ARRAYELTS (keybuf), Qnil, 0, 1, 1, 1); unbind_to (count, Qnil); @@ -1866,30 +1876,27 @@ adjust_point_for_property (ptrdiff_t last_pt, bool modified) } } -/* Subroutine for safe_run_hooks: run the hook HOOK. */ +/* Subroutine for safe_run_hooks: run the hook, which is ARGS[1]. */ static Lisp_Object -safe_run_hooks_1 (void) +safe_run_hooks_1 (ptrdiff_t nargs, Lisp_Object *args) { - eassert (CONSP (Vinhibit_quit)); - return call0 (XCDR (Vinhibit_quit)); + eassert (nargs == 2); + return call0 (args[1]); } /* Subroutine for safe_run_hooks: handle an error by clearing out the function from the hook. */ static Lisp_Object -safe_run_hooks_error (Lisp_Object error_data) +safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object hook - = CONSP (Vinhibit_quit) ? XCAR (Vinhibit_quit) : Vinhibit_quit; - Lisp_Object fun = CONSP (Vinhibit_quit) ? XCDR (Vinhibit_quit) : Qnil; - Lisp_Object args[4]; - args[0] = build_string ("Error in %s (%S): %S"); - args[1] = hook; - args[2] = fun; - args[3] = error_data; - Fmessage (4, args); + eassert (nargs == 2); + AUTO_STRING (format, "Error in %s (%S): %S"); + Lisp_Object hook = args[0]; + Lisp_Object fun = args[1]; + Fmessage (4, (Lisp_Object []) {format, hook, fun, error}); + if (SYMBOLP (hook)) { Lisp_Object val; @@ -1921,13 +1928,14 @@ safe_run_hooks_error (Lisp_Object error_data) static Lisp_Object safe_run_hook_funcall (ptrdiff_t nargs, Lisp_Object *args) { - eassert (nargs == 1); - if (CONSP (Vinhibit_quit)) - XSETCDR (Vinhibit_quit, args[0]); - else - Vinhibit_quit = Fcons (Vinhibit_quit, args[0]); + Lisp_Object iargs[2]; - internal_condition_case (safe_run_hooks_1, Qt, safe_run_hooks_error); + eassert (nargs == 2); + /* Yes, run_hook_with_args works this way. */ + iargs[0] = args[1]; + iargs[1] = args[0]; + internal_condition_case_n (safe_run_hooks_1, 2, iargs, + Qt, safe_run_hooks_error); return Qnil; } @@ -1938,15 +1946,18 @@ safe_run_hook_funcall (ptrdiff_t nargs, Lisp_Object *args) void safe_run_hooks (Lisp_Object hook) { - /* FIXME: our `internal_condition_case' does not provide any way to pass data - to its body or to its handlers other than via globals such as - dynamically-bound variables ;-) */ + Lisp_Object args[2]; + struct gcpro gcpro1; ptrdiff_t count = SPECPDL_INDEX (); - specbind (Qinhibit_quit, hook); - run_hook_with_args (1, &hook, safe_run_hook_funcall); + args[0] = hook; + args[1] = hook; + GCPRO1 (hook); + specbind (Qinhibit_quit, Qt); + run_hook_with_args (2, args, safe_run_hook_funcall); unbind_to (count, Qnil); + UNGCPRO; } @@ -2091,16 +2102,13 @@ bind_polling_period (int n) /* Apply the control modifier to CHARACTER. */ -#ifndef HAVE_NTGUI -static -#endif int make_ctrl_char (int c) { /* Save the upper bits here. */ int upper = c & ~0177; - if (! ASCII_BYTE_P (c)) + if (! ASCII_CHAR_P (c)) return c |= ctrl_modifier; c &= 0177; @@ -2302,8 +2310,10 @@ read_decoded_event_from_main_queue (struct timespec *end_time, bool *used_mouse_menu) { #define MAX_ENCODED_BYTES 16 +#ifndef WINDOWSNT Lisp_Object events[MAX_ENCODED_BYTES]; int n = 0; +#endif while (true) { Lisp_Object nextevt @@ -2336,15 +2346,16 @@ read_decoded_event_from_main_queue (struct timespec *end_time, { /* An encoded byte sequence, let's try to decode it. */ struct coding_system *coding = TERMINAL_KEYBOARD_CODING (terminal); - unsigned char *src = alloca (n); + unsigned char src[MAX_ENCODED_BYTES]; + unsigned char dest[MAX_ENCODED_BYTES * MAX_MULTIBYTE_LENGTH]; int i; for (i = 0; i < n; i++) src[i] = XINT (events[i]); if (meta_key != 2) for (i = 0; i < n; i++) src[i] &= ~0x80; - coding->destination = alloca (n * 4); - coding->dst_bytes = n * 4; + coding->destination = dest; + coding->dst_bytes = sizeof dest; decode_coding_c_string (coding, src, n, Qnil); eassert (coding->produced_char <= n); if (coding->produced_char == 0) @@ -2374,6 +2385,13 @@ read_decoded_event_from_main_queue (struct timespec *end_time, } } +static bool +echo_keystrokes_p (void) +{ + return (FLOATP (Vecho_keystrokes) ? XFLOAT_DATA (Vecho_keystrokes) > 0.0 + : INTEGERP (Vecho_keystrokes) ? XINT (Vecho_keystrokes) > 0 : false); +} + /* Read a character from the keyboard; call the redisplay if needed. */ /* commandflag 0 means do not autosave, but do redisplay. -1 means do not redisplay, but do autosave. @@ -2431,7 +2449,6 @@ read_char (int commandflag, Lisp_Object map, retry: - reread = 0; if (CONSP (Vunread_post_input_method_events)) { c = XCAR (Vunread_post_input_method_events); @@ -2445,9 +2462,12 @@ read_char (int commandflag, Lisp_Object map, && NILP (XCDR (c))) c = XCAR (c); - reread = 1; + reread = true; goto reread_first; } + else + reread = false; + if (CONSP (Vunread_command_events)) { @@ -2456,17 +2476,13 @@ read_char (int commandflag, Lisp_Object map, c = XCAR (Vunread_command_events); Vunread_command_events = XCDR (Vunread_command_events); - reread = 1; - /* Undo what sit-for did when it unread additional keys inside universal-argument. */ - if (CONSP (c) - && EQ (XCAR (c), Qt)) - { - reread = 0; - c = XCDR (c); - } + if (CONSP (c) && EQ (XCAR (c), Qt)) + c = XCDR (c); + else + reread = true; /* Undo what read_char_x_menu_prompt did when it unread additional keys returned by Fx_popup_menu. */ @@ -2500,7 +2516,7 @@ read_char (int commandflag, Lisp_Object map, && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c))) && NILP (XCDR (c))) c = XCAR (c); - reread = 1; + reread = true; goto reread_for_input_method; } @@ -2655,6 +2671,7 @@ read_char (int commandflag, Lisp_Object map, /* We must have saved the outer value of getcjmp here, so restore it now. */ restore_getcjmp (save_jump); + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); unbind_to (jmpcount, Qnil); XSETINT (c, quit_char); internal_last_event_frame = selected_frame; @@ -2709,8 +2726,7 @@ read_char (int commandflag, Lisp_Object map, && !current_kboard->immediate_echo && this_command_key_count > 0 && ! noninteractive - && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes)) + && echo_keystrokes_p () && (/* No message. */ NILP (echo_area_buffer[0]) /* Or empty message. */ @@ -2841,6 +2857,11 @@ read_char (int commandflag, Lisp_Object map, { c = XCAR (Vunread_command_events); Vunread_command_events = XCDR (Vunread_command_events); + + if (CONSP (c) && EQ (XCAR (c), Qt)) + c = XCDR (c); + else + reread = true; } /* Read something from current KBOARD's side queue, if possible. */ @@ -2894,8 +2915,8 @@ read_char (int commandflag, Lisp_Object map, { c = read_decoded_event_from_main_queue (end_time, local_getcjmp, prev_event, used_mouse_menu); - if (NILP(c) && end_time && - timespec_cmp (*end_time, current_timespec ()) <= 0) + if (NILP (c) && end_time + && timespec_cmp (*end_time, current_timespec ()) <= 0) { goto exit; } @@ -3171,8 +3192,7 @@ read_char (int commandflag, Lisp_Object map, { /* Don't echo mouse motion events. */ - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes)) + if (echo_keystrokes_p () && ! (EVENT_HAS_PARAMETERS (c) && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement))) { @@ -3248,8 +3268,7 @@ record_menu_key (Lisp_Object c) #endif /* Don't echo mouse motion events. */ - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes))) + if (echo_keystrokes_p ()) { echo_char (c); @@ -3471,7 +3490,8 @@ readable_events (int flags) event->kind == FOCUS_IN_EVENT) #ifdef USE_TOOLKIT_SCROLL_BARS && !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) - && event->kind == SCROLL_BAR_CLICK_EVENT + && (event->kind == SCROLL_BAR_CLICK_EVENT + || event->kind == HORIZONTAL_SCROLL_BAR_CLICK_EVENT) && event->part == scroll_bar_handle && event->modifiers == 0) #endif @@ -3704,6 +3724,34 @@ kbd_buffer_unget_event (register struct input_event *event) } } +/* Limit help event positions to this range, to avoid overflow problems. */ +#define INPUT_EVENT_POS_MAX \ + ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ + MOST_POSITIVE_FIXNUM))) +#define INPUT_EVENT_POS_MIN (-1 - INPUT_EVENT_POS_MAX) + +/* Return a Time that encodes position POS. POS must be in range. */ + +static Time +position_to_Time (ptrdiff_t pos) +{ + eassert (INPUT_EVENT_POS_MIN <= pos && pos <= INPUT_EVENT_POS_MAX); + return pos; +} + +/* Return the position that ENCODED_POS encodes. + Avoid signed integer overflow. */ + +static ptrdiff_t +Time_to_position (Time encoded_pos) +{ + if (encoded_pos <= INPUT_EVENT_POS_MAX) + return encoded_pos; + Time encoded_pos_min = INPUT_EVENT_POS_MIN; + eassert (encoded_pos_min <= encoded_pos); + ptrdiff_t notpos = -1 - encoded_pos; + return -1 - notpos; +} /* Generate a HELP_EVENT input_event and store it in the keyboard buffer. @@ -3722,14 +3770,12 @@ gen_help_event (Lisp_Object help, Lisp_Object frame, Lisp_Object window, { struct input_event event; - EVENT_INIT (event); - event.kind = HELP_EVENT; event.frame_or_window = frame; event.arg = object; event.x = WINDOWP (window) ? window : frame; event.y = help; - event.code = pos; + event.timestamp = position_to_Time (pos); kbd_buffer_store_event (&event); } @@ -3746,7 +3792,7 @@ kbd_buffer_store_help_event (Lisp_Object frame, Lisp_Object help) event.arg = Qnil; event.x = Qnil; event.y = help; - event.code = 0; + event.timestamp = 0; kbd_buffer_store_event (&event); } @@ -3768,7 +3814,8 @@ discard_mouse_events (void) #ifdef HAVE_GPM || sp->kind == GPM_CLICK_EVENT #endif - || sp->kind == SCROLL_BAR_CLICK_EVENT) + || sp->kind == SCROLL_BAR_CLICK_EVENT + || sp->kind == HORIZONTAL_SCROLL_BAR_CLICK_EVENT) { sp->kind = NO_EVENT; } @@ -4060,7 +4107,7 @@ kbd_buffer_get_event (KBOARD **kbp, frame = event->frame_or_window; object = event->arg; - position = make_number (event->code); + position = make_number (Time_to_position (event->timestamp)); window = event->x; help = event->y; clear_event (event); @@ -4375,8 +4422,9 @@ decode_timer (Lisp_Object timer, struct timespec *result) if (! NILP (vector[0])) return 0; - return decode_time_components (vector[1], vector[2], vector[3], vector[8], - result, 0); + return (decode_time_components (vector[1], vector[2], vector[3], vector[8], + result, 0) + && timespec_valid_p (*result)); } @@ -5167,15 +5215,20 @@ static const char *const lispy_drag_n_drop_names[] = /* Scroll bar parts. */ static Lisp_Object Qabove_handle, Qhandle, Qbelow_handle; -Lisp_Object Qup, Qdown, Qbottom; +static Lisp_Object Qbefore_handle, Qhorizontal_handle, Qafter_handle; +Lisp_Object Qup, Qdown, Qtop, Qbottom; +static Lisp_Object Qleftmost, Qrightmost; static Lisp_Object Qend_scroll; -Lisp_Object Qtop; static Lisp_Object Qratio; -/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. */ +/* An array of scroll bar parts, indexed by an enum scroll_bar_part value. + Note that Qnil corresponds to scroll_bar_nowhere and should not appear + in Lisp events. */ static Lisp_Object *const scroll_bar_parts[] = { - &Qabove_handle, &Qhandle, &Qbelow_handle, - &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio + &Qnil, &Qabove_handle, &Qhandle, &Qbelow_handle, + &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio, + &Qbefore_handle, &Qhorizontal_handle, &Qafter_handle, + &Qleft, &Qright, &Qleftmost, &Qrightmost, &Qend_scroll, &Qratio }; /* A vector, indexed by button number, giving the down-going location @@ -5225,7 +5278,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, /* It's a click in window WINDOW at frame coordinates (X,Y) */ struct window *w = XWINDOW (window); Lisp_Object string_info = Qnil; - ptrdiff_t textpos = -1; + ptrdiff_t textpos = 0; int col = -1, row = -1; int dx = -1, dy = -1; int width = -1, height = -1; @@ -5260,9 +5313,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, &object, &dx, &dy, &width, &height); if (STRINGP (string)) string_info = Fcons (string, make_number (charpos)); - textpos = (w == XWINDOW (selected_window) - && current_buffer == XBUFFER (w->contents)) - ? PT : marker_position (w->pointm); + textpos = -1; xret = wx; yret = wy; @@ -5330,7 +5381,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, /* For clicks in the text area, fringes, or margins, call buffer_posn_from_coords to extract TEXTPOS, the buffer position nearest to the click. */ - if (textpos < 0) + if (!textpos) { Lisp_Object string2, object2 = Qnil; struct display_pos p; @@ -5381,15 +5432,15 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, } #endif - /* Object info */ + /* Object info. */ extra_info = list3 (object, Fcons (make_number (dx), make_number (dy)), Fcons (make_number (width), make_number (height))); - /* String info */ + /* String info. */ extra_info = Fcons (string_info, - Fcons (make_number (textpos), + Fcons (textpos < 0 ? Qnil : make_number (textpos), Fcons (Fcons (make_number (col), make_number (row)), extra_info))); @@ -5421,6 +5472,16 @@ toolkit_menubar_in_use (struct frame *f) #endif } +/* Build the part of Lisp event which represents scroll bar state from + EV. TYPE is one of Qvertical_scroll_bar or Qhorizontal_scroll_bar. */ + +static Lisp_Object +make_scroll_bar_position (struct input_event *ev, Lisp_Object type) +{ + return list5 (ev->frame_or_window, type, Fcons (ev->x, ev->y), + make_number (ev->timestamp), *scroll_bar_parts[ev->part]); +} + /* Given a struct input_event, build the lisp event which represents it. If EVENT is 0, build a mouse movement event from the mouse movement buffer, which should have a movement event in it. @@ -5480,14 +5541,13 @@ make_lispy_event (struct input_event *event) case NON_ASCII_KEYSTROKE_EVENT: button_down_time = 0; - for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++) + for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++) if (event->code == lispy_accent_codes[i]) return modify_event_symbol (i, event->modifiers, Qfunction_key, Qnil, lispy_accent_keys, &accent_key_syms, - (sizeof (lispy_accent_keys) - / sizeof (lispy_accent_keys[0]))); + ARRAYELTS (lispy_accent_keys)); #if 0 #ifdef XK_kana_A @@ -5496,8 +5556,7 @@ make_lispy_event (struct input_event *event) event->modifiers & ~shift_modifier, Qfunction_key, Qnil, lispy_kana_keys, &func_key_syms, - (sizeof (lispy_kana_keys) - / sizeof (lispy_kana_keys[0]))); + ARRAYELTS (lispy_kana_keys)); #endif /* XK_kana_A */ #endif /* 0 */ @@ -5508,47 +5567,40 @@ make_lispy_event (struct input_event *event) event->modifiers, Qfunction_key, Qnil, iso_lispy_function_keys, &func_key_syms, - (sizeof (iso_lispy_function_keys) - / sizeof (iso_lispy_function_keys[0]))); + ARRAYELTS (iso_lispy_function_keys)); #endif - /* Handle system-specific or unknown keysyms. */ - if (event->code & (1 << 28) - || event->code - FUNCTION_KEY_OFFSET < 0 - || (event->code - FUNCTION_KEY_OFFSET - >= sizeof lispy_function_keys / sizeof *lispy_function_keys) - || !lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) - { - /* We need to use an alist rather than a vector as the cache - since we can't make a vector long enough. */ - if (NILP (KVAR (current_kboard, system_key_syms))) - kset_system_key_syms (current_kboard, Fcons (Qnil, Qnil)); - return modify_event_symbol (event->code, - event->modifiers, - Qfunction_key, - KVAR (current_kboard, Vsystem_key_alist), - 0, &KVAR (current_kboard, system_key_syms), - PTRDIFF_MAX); - } - - return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET, + if ((FUNCTION_KEY_OFFSET <= event->code + && (event->code + < FUNCTION_KEY_OFFSET + ARRAYELTS (lispy_function_keys))) + && lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) + return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET, + event->modifiers, + Qfunction_key, Qnil, + lispy_function_keys, &func_key_syms, + ARRAYELTS (lispy_function_keys)); + + /* Handle system-specific or unknown keysyms. + We need to use an alist rather than a vector as the cache + since we can't make a vector long enough. */ + if (NILP (KVAR (current_kboard, system_key_syms))) + kset_system_key_syms (current_kboard, Fcons (Qnil, Qnil)); + return modify_event_symbol (event->code, event->modifiers, - Qfunction_key, Qnil, - lispy_function_keys, &func_key_syms, - (sizeof (lispy_function_keys) - / sizeof (lispy_function_keys[0]))); + Qfunction_key, + KVAR (current_kboard, Vsystem_key_alist), + 0, &KVAR (current_kboard, system_key_syms), + PTRDIFF_MAX); #ifdef HAVE_NTGUI case MULTIMEDIA_KEY_EVENT: - if (event->code < (sizeof (lispy_multimedia_keys) - / sizeof (lispy_multimedia_keys[0])) + if (event->code < ARRAYELTS (lispy_multimedia_keys) && event->code > 0 && lispy_multimedia_keys[event->code]) { return modify_event_symbol (event->code, event->modifiers, Qfunction_key, Qnil, lispy_multimedia_keys, &func_key_syms, - (sizeof (lispy_multimedia_keys) - / sizeof (lispy_multimedia_keys[0]))); + ARRAYELTS (lispy_multimedia_keys)); } return Qnil; #endif @@ -5561,6 +5613,7 @@ make_lispy_event (struct input_event *event) #endif #ifndef USE_TOOLKIT_SCROLL_BARS case SCROLL_BAR_CLICK_EVENT: + case HORIZONTAL_SCROLL_BAR_CLICK_EVENT: #endif { int button = event->code; @@ -5643,20 +5696,8 @@ make_lispy_event (struct input_event *event) } #ifndef USE_TOOLKIT_SCROLL_BARS else - { - /* It's a scrollbar click. */ - Lisp_Object window; - Lisp_Object portion_whole; - Lisp_Object part; - - window = event->frame_or_window; - portion_whole = Fcons (event->x, event->y); - part = *scroll_bar_parts[(int) event->part]; - - position = list5 (window, Qvertical_scroll_bar, - portion_whole, make_number (event->timestamp), - part); - } + /* It's a scrollbar click. */ + position = make_scroll_bar_position (event, Qvertical_scroll_bar); #endif /* not USE_TOOLKIT_SCROLL_BARS */ if (button >= ASIZE (button_down_location)) @@ -5933,14 +5974,34 @@ make_lispy_event (struct input_event *event) case SCROLL_BAR_CLICK_EVENT: { - Lisp_Object position, head, window, portion_whole, part; + Lisp_Object position, head; + + position = make_scroll_bar_position (event, Qvertical_scroll_bar); + + /* Always treat scroll bar events as clicks. */ + event->modifiers |= click_modifier; + event->modifiers &= ~up_modifier; + + if (event->code >= ASIZE (mouse_syms)) + mouse_syms = larger_vector (mouse_syms, + event->code - ASIZE (mouse_syms) + 1, + -1); + + /* Get the symbol we should use for the mouse click. */ + head = modify_event_symbol (event->code, + event->modifiers, + Qmouse_click, + Vlispy_mouse_stem, + NULL, &mouse_syms, + ASIZE (mouse_syms)); + return list2 (head, position); + } - window = event->frame_or_window; - portion_whole = Fcons (event->x, event->y); - part = *scroll_bar_parts[(int) event->part]; + case HORIZONTAL_SCROLL_BAR_CLICK_EVENT: + { + Lisp_Object position, head; - position = list5 (window, Qvertical_scroll_bar, portion_whole, - make_number (event->timestamp), part); + position = make_scroll_bar_position (event, Qhorizontal_scroll_bar); /* Always treat scroll bar events as clicks. */ event->modifiers |= click_modifier; @@ -6270,7 +6331,7 @@ static const char *const modifier_names[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "alt", "super", "hyper", "shift", "control", "meta" }; -#define NUM_MOD_NAMES (sizeof (modifier_names) / sizeof (modifier_names[0])) +#define NUM_MOD_NAMES ARRAYELTS (modifier_names) static Lisp_Object modifier_symbols; @@ -6878,6 +6939,20 @@ gobble_input (void) } } + /* If there was no error, make sure the pointer + is visible for all frames on this terminal. */ + if (nr >= 0) + { + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_TERMINAL (f) == t) + frame_make_pointer_visible (f); + } + } + if (hold_quit.kind != NO_EVENT) kbd_buffer_store_event (&hold_quit); } @@ -6888,8 +6963,6 @@ gobble_input (void) if (err && !nread) nread = -1; - frame_make_pointer_visible (); - return nread; } @@ -7295,7 +7368,7 @@ store_user_signal_events (void) } -static void menu_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*); +static void menu_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void *); static Lisp_Object menu_bar_one_keymap_changed_items; /* These variables hold the vector under construction within @@ -7305,7 +7378,7 @@ static Lisp_Object menu_bar_items_vector; static int menu_bar_items_index; -static const char* separator_names[] = { +static const char *separator_names[] = { "space", "no-line", "single-line", @@ -7369,11 +7442,14 @@ menu_bar_items (Lisp_Object old) in the current keymaps, or nil where it is not a prefix. */ Lisp_Object *maps; + Lisp_Object mapsbuf[3]; Lisp_Object def, tail; ptrdiff_t mapno; Lisp_Object oquit; + USE_SAFE_ALLOCA; + /* In order to build the menus, we need to call the keymap accessors. They all call QUIT. But this function is called during redisplay, during which a quit is fatal. So inhibit @@ -7402,7 +7478,7 @@ menu_bar_items (Lisp_Object old) && !NILP (Voverriding_local_map)) { /* Yes, use them (if non-nil) as well as the global map. */ - maps = alloca (3 * sizeof (maps[0])); + maps = mapsbuf; nmaps = 0; if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); @@ -7419,7 +7495,7 @@ menu_bar_items (Lisp_Object old) Lisp_Object tem; ptrdiff_t nminor; nminor = current_minor_maps (NULL, &tmaps); - maps = alloca ((nminor + 4) * sizeof *maps); + SAFE_NALLOCA (maps, 1, nminor + 4); nmaps = 0; tem = KVAR (current_kboard, Voverriding_terminal_local_map); if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) @@ -7480,8 +7556,8 @@ menu_bar_items (Lisp_Object old) { int i = menu_bar_items_index; if (i + 4 > ASIZE (menu_bar_items_vector)) - menu_bar_items_vector = - larger_vector (menu_bar_items_vector, 4, -1); + menu_bar_items_vector + = larger_vector (menu_bar_items_vector, 4, -1); /* Add this item. */ ASET (menu_bar_items_vector, i, Qnil); i++; ASET (menu_bar_items_vector, i, Qnil); i++; @@ -7491,6 +7567,7 @@ menu_bar_items (Lisp_Object old) } Vinhibit_quit = oquit; + SAFE_FREE (); return menu_bar_items_vector; } @@ -7806,11 +7883,12 @@ parse_menu_item (Lisp_Object item, int inmenubar) { /* This is a command. See if there is an equivalent key binding. */ Lisp_Object keyeq = AREF (item_properties, ITEM_PROPERTY_KEYEQ); + AUTO_STRING (space_space, " "); /* The previous code preferred :key-sequence to :keys, so we preserve this behavior. */ if (STRINGP (keyeq) && !CONSP (keyhint)) - keyeq = concat2 (build_string (" "), Fsubstitute_command_keys (keyeq)); + keyeq = concat2 (space_space, Fsubstitute_command_keys (keyeq)); else { Lisp_Object prefix = keyeq; @@ -7853,8 +7931,7 @@ parse_menu_item (Lisp_Object item, int inmenubar) if (STRINGP (XCDR (prefix))) tem = concat2 (tem, XCDR (prefix)); } - keyeq = concat2 (build_string (" "), tem); - /* keyeq = concat3(build_string(" ("),tem,build_string(")")); */ + keyeq = concat2 (space_space, tem); } else keyeq = Qnil; @@ -7913,7 +7990,8 @@ static Lisp_Object QCrtl; /* Function prototypes. */ static void init_tool_bar_items (Lisp_Object); -static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*); +static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, + void *); static bool parse_tool_bar_item (Lisp_Object, Lisp_Object); static void append_tool_bar_item (void); @@ -7926,9 +8004,11 @@ Lisp_Object tool_bar_items (Lisp_Object reuse, int *nitems) { Lisp_Object *maps; + Lisp_Object mapsbuf[3]; ptrdiff_t nmaps, i; Lisp_Object oquit; Lisp_Object *tmaps; + USE_SAFE_ALLOCA; *nitems = 0; @@ -7952,7 +8032,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) && !NILP (Voverriding_local_map)) { /* Yes, use them (if non-nil) as well as the global map. */ - maps = alloca (3 * sizeof *maps); + maps = mapsbuf; nmaps = 0; if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); @@ -7969,7 +8049,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) Lisp_Object tem; ptrdiff_t nminor; nminor = current_minor_maps (NULL, &tmaps); - maps = alloca ((nminor + 4) * sizeof *maps); + SAFE_NALLOCA (maps, 1, nminor + 4); nmaps = 0; tem = KVAR (current_kboard, Voverriding_terminal_local_map); if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) @@ -7998,6 +8078,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) Vinhibit_quit = oquit; *nitems = ntool_bar_items / TOOL_BAR_ITEM_NSLOTS; + SAFE_FREE (); return tool_bar_items_vector; } @@ -8436,7 +8517,7 @@ static Lisp_Object read_char_minibuf_menu_prompt (int commandflag, Lisp_Object map) { - register Lisp_Object name; + Lisp_Object name; ptrdiff_t nlength; /* FIXME: Use the minibuffer's frame width. */ ptrdiff_t width = FRAME_COLS (SELECTED_FRAME ()) - 4; @@ -8554,10 +8635,14 @@ read_char_minibuf_menu_prompt (int commandflag, /* Insert button prefix. */ Lisp_Object selected = AREF (item_properties, ITEM_PROPERTY_SELECTED); + AUTO_STRING (radio_yes, "(*) "); + AUTO_STRING (radio_no , "( ) "); + AUTO_STRING (check_yes, "[X] "); + AUTO_STRING (check_no , "[ ] "); if (EQ (tem, QCradio)) - tem = build_string (NILP (selected) ? "(*) " : "( ) "); + tem = NILP (selected) ? radio_yes : radio_no; else - tem = build_string (NILP (selected) ? "[X] " : "[ ] "); + tem = NILP (selected) ? check_yes : check_no; s = concat2 (tem, s); } @@ -8935,8 +9020,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, echo_now (); } else if (cursor_in_echo_area - && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes))) + && echo_keystrokes_p ()) /* This doesn't put in a dash if the echo buffer is empty, so you don't always see a dash hanging out in the minibuffer. */ echo_dash (); @@ -9068,8 +9152,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, { key = keybuf[t]; add_command_key (key); - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes)) + if (echo_keystrokes_p () && current_kboard->immediate_echo) { echo_add_key (key); @@ -9734,8 +9817,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, Better ideas? */ for (; t < mock_input; t++) { - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes))) + if (echo_keystrokes_p ()) echo_char (keybuf[t]); add_command_key (keybuf[t]); } @@ -9766,7 +9848,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo, memset (keybuf, 0, sizeof keybuf); GCPRO1 (keybuf[0]); - gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0])); + gcpro1.nvars = ARRAYELTS (keybuf); if (NILP (continue_echo)) { @@ -9780,7 +9862,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo, cancel_hourglass (); #endif - i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), + i = read_key_sequence (keybuf, ARRAYELTS (keybuf), prompt, ! NILP (dont_downcase_last), ! NILP (can_return_switch_frame), 0, 0); @@ -10182,7 +10264,9 @@ On such systems, Emacs starts a subshell instead of suspending. */) with a window system; but suspend should be disabled in that case. */ get_tty_size (fileno (CURTTY ()->input), &width, &height); if (width != old_width || height != old_height) - change_frame_size (SELECTED_FRAME (), width, height, 0, 0, 0, 0); + change_frame_size (SELECTED_FRAME (), width, + height - FRAME_MENU_BAR_LINES (SELECTED_FRAME ()), + 0, 0, 0, 0); /* Run suspend-resume-hook. */ hook = intern ("suspend-resume-hook"); @@ -10265,7 +10349,7 @@ static void handle_interrupt_signal (int sig) { /* See if we have an active terminal on our controlling tty. */ - struct terminal *terminal = get_named_tty ("/dev/tty"); + struct terminal *terminal = get_named_terminal ("/dev/tty"); if (!terminal) { /* If there are no frames there, let's pretend that we are a @@ -10319,7 +10403,7 @@ handle_interrupt (bool in_signal_handler) cancel_echoing (); /* XXX This code needs to be revised for multi-tty support. */ - if (!NILP (Vquit_flag) && get_named_tty ("/dev/tty")) + if (!NILP (Vquit_flag) && get_named_terminal ("/dev/tty")) { if (! in_signal_handler) { @@ -10531,9 +10615,10 @@ Emacs reads input in CBREAK mode; see `set-input-interrupt-mode'. See also `current-input-mode'. */) (Lisp_Object flow, Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_tty_terminal (terminal); struct tty_display_info *tty; - if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw)) + + if (!t) return Qnil; tty = t->display_info.tty; @@ -10573,11 +10658,11 @@ the currently selected frame. See also `current-input-mode'. */) (Lisp_Object meta, Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_tty_terminal (terminal); struct tty_display_info *tty; int new_meta; - if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw)) + if (!t) return Qnil; tty = t->display_info.tty; @@ -10614,9 +10699,10 @@ process. See also `current-input-mode'. */) (Lisp_Object quit) { - struct terminal *t = get_named_tty ("/dev/tty"); + struct terminal *t = get_named_terminal ("/dev/tty"); struct tty_display_info *tty; - if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw)) + + if (!t) return Qnil; tty = t->display_info.tty; @@ -10693,7 +10779,7 @@ The elements of this list correspond to the arguments of } XSETFASTINT (val[3], quit_char); - return Flist (sizeof (val) / sizeof (val[0]), val); + return Flist (ARRAYELTS (val), val); } DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 4, 0, @@ -10959,6 +11045,15 @@ syms_of_keyboard (void) Vlispy_mouse_stem = build_pure_c_string ("mouse"); staticpro (&Vlispy_mouse_stem); + regular_top_level_message = build_pure_c_string ("Back to top level"); +#ifdef HAVE_STACK_OVERFLOW_HANDLING + recover_top_level_message + = build_pure_c_string ("Re-entering top level after C stack overflow"); +#endif + DEFVAR_LISP ("internal--top-level-message", Vinternal__top_level_message, + doc: /* Message displayed by `normal-top-level'. */); + Vinternal__top_level_message = regular_top_level_message; + /* Tool-bars. */ DEFSYM (QCimage, ":image"); DEFSYM (Qhelp_echo, "help-echo"); @@ -11016,7 +11111,6 @@ syms_of_keyboard (void) DEFSYM (Qmode_line, "mode-line"); DEFSYM (Qvertical_line, "vertical-line"); - DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar"); DEFSYM (Qmenu_bar, "menu-bar"); DEFSYM (Qright_divider, "right-divider"); DEFSYM (Qbottom_divider, "bottom-divider"); @@ -11032,6 +11126,13 @@ syms_of_keyboard (void) DEFSYM (Qbottom, "bottom"); DEFSYM (Qend_scroll, "end-scroll"); DEFSYM (Qratio, "ratio"); + DEFSYM (Qbefore_handle, "before-handle"); + DEFSYM (Qhorizontal_handle, "horizontal-handle"); + DEFSYM (Qafter_handle, "after-handle"); + DEFSYM (Qleft, "left"); + DEFSYM (Qright, "right"); + DEFSYM (Qleftmost, "leftmost"); + DEFSYM (Qrightmost, "rightmost"); DEFSYM (Qevent_kind, "event-kind"); DEFSYM (Qevent_symbol_elements, "event-symbol-elements"); @@ -11061,7 +11162,7 @@ syms_of_keyboard (void) { int i; - int len = sizeof (head_table) / sizeof (head_table[0]); + int len = ARRAYELTS (head_table); for (i = 0; i < len; i++) { @@ -11077,14 +11178,13 @@ syms_of_keyboard (void) staticpro (&button_down_location); mouse_syms = Fmake_vector (make_number (5), Qnil); staticpro (&mouse_syms); - wheel_syms = Fmake_vector (make_number (sizeof (lispy_wheel_names) - / sizeof (lispy_wheel_names[0])), + wheel_syms = Fmake_vector (make_number (ARRAYELTS (lispy_wheel_names)), Qnil); staticpro (&wheel_syms); { int i; - int len = sizeof (modifier_names) / sizeof (modifier_names[0]); + int len = ARRAYELTS (modifier_names); modifier_symbols = Fmake_vector (make_number (len), Qnil); for (i = 0; i < len; i++) @@ -11403,6 +11503,7 @@ and tests the value when the command returns. Buffer modification stores t in this variable. */); Vdeactivate_mark = Qnil; DEFSYM (Qdeactivate_mark, "deactivate-mark"); + Fmake_variable_buffer_local (Qdeactivate_mark); DEFVAR_LISP ("pre-command-hook", Vpre_command_hook, doc: /* Normal hook run before each command is executed. diff --git a/src/keyboard.h b/src/keyboard.h index 8bb54dd86e0..da83b9b01ed 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -305,9 +305,7 @@ extern Lisp_Object menu_items; /* If non-nil, means that the global vars defined here are already in use. Used to detect cases where we try to re-enter this non-reentrant code. */ -#if defined USE_GTK || defined USE_MOTIF extern Lisp_Object menu_items_inuse; -#endif /* Number of slots currently allocated in menu_items. */ extern int menu_items_allocated; @@ -354,57 +352,6 @@ extern void unuse_menu_items (void); #define ENCODE_MENU_STRING(str) (str) #endif -#if defined (HAVE_NS) || defined (HAVE_NTGUI) || defined (USE_GTK) - -/* Definitions copied from lwlib.h */ - -enum button_type -{ - BUTTON_TYPE_NONE, - BUTTON_TYPE_TOGGLE, - BUTTON_TYPE_RADIO -}; - -/* This structure is based on the one in ../lwlib/lwlib.h, with unused portions - removed. No term uses these. */ -typedef struct _widget_value -{ - /* name of widget */ - Lisp_Object lname; - const char* name; - /* value (meaning depend on widget type) */ - const char* value; - /* keyboard equivalent. no implications for XtTranslations */ - Lisp_Object lkey; - const char* key; - /* Help string or nil if none. - GC finds this string through the frame's menu_bar_vector - or through menu_items. */ - Lisp_Object help; - /* true if enabled */ - unsigned char enabled; - /* true if selected */ - unsigned char selected; - /* The type of a button. */ - enum button_type button_type; -#if defined (HAVE_NTGUI) - /* true if menu title */ - unsigned char title; -#endif - /* Contents of the sub-widgets, also selected slot for checkbox */ - struct _widget_value* contents; - /* data passed to callback */ - void *call_data; - /* next one in the list */ - struct _widget_value* next; -#ifdef USE_GTK - struct _widget_value *free_list; -#endif -} widget_value; - -#endif /* HAVE_NS || HAVE_NTGUI */ - - /* Macros for dealing with lispy events. */ /* True if EVENT has data fields describing it (i.e. a mouse click). */ @@ -466,9 +413,7 @@ extern bool waiting_for_input; happens. */ extern struct timespec *input_available_clear_time; -#if defined HAVE_WINDOW_SYSTEM && !defined USE_GTK && !defined HAVE_NS extern bool ignore_mouse_drag_p; -#endif /* The primary selection. */ extern Lisp_Object QPRIMARY; @@ -518,9 +463,7 @@ extern bool input_polling_used (void); extern void clear_input_pending (void); extern bool requeued_events_pending_p (void); extern void bind_polling_period (int); -#if HAVE_NTGUI extern int make_ctrl_char (int) ATTRIBUTE_CONST; -#endif extern void stuff_buffered_input (Lisp_Object); extern void clear_waiting_for_input (void); extern void swallow_events (bool); diff --git a/src/keymap.c b/src/keymap.c index c1416f8a780..c7c7d196c22 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -727,11 +727,6 @@ get_keyelt (Lisp_Object object, bool autoload) /* This is really the value. */ return object; - /* If the keymap contents looks like (keymap ...) or (lambda ...) - then use itself. */ - else if (EQ (XCAR (object), Qkeymap) || EQ (XCAR (object), Qlambda)) - return object; - /* If the keymap contents looks like (menu-item name . DEFN) or (menu-item name DEFN ...) then use DEFN. This is a new format menu item. */ @@ -768,25 +763,8 @@ get_keyelt (Lisp_Object object, bool autoload) Keymap alist elements like (CHAR MENUSTRING . DEFN) will be used by HierarKey menus. */ else if (STRINGP (XCAR (object))) - { - object = XCDR (object); - /* Also remove a menu help string, if any, - following the menu item name. */ - if (CONSP (object) && STRINGP (XCAR (object))) - object = XCDR (object); - /* Also remove the sublist that caches key equivalences, if any. */ - if (CONSP (object) && CONSP (XCAR (object))) - { - Lisp_Object carcar; - carcar = XCAR (XCAR (object)); - if (NILP (carcar) || VECTORP (carcar)) - object = XCDR (object); - } - } + object = XCDR (object); - /* If the contents are (KEYMAP . ELEMENT), go indirect. */ - else if (KEYMAPP (XCAR (object))) - error ("Wow, indirect keymap entry!!"); else return object; } @@ -990,9 +968,6 @@ copy_keymap_item (Lisp_Object elt) if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) XSETCAR (elt, Fcopy_keymap (tem)); tem = XCDR (elt); - if (CONSP (tem) && CONSP (XCAR (tem))) - /* Delete cache for key equivalences. */ - XSETCDR (elt, XCDR (tem)); } } else @@ -1011,16 +986,6 @@ copy_keymap_item (Lisp_Object elt) elt = XCDR (elt); tem = XCDR (elt); } - /* There may also be a list that caches key equivalences. - Just delete it for the new keymap. */ - if (CONSP (tem) - && CONSP (XCAR (tem)) - && (NILP (XCAR (XCAR (tem))) - || VECTORP (XCAR (XCAR (tem))))) - { - XSETCDR (elt, XCDR (tem)); - tem = XCDR (tem); - } if (CONSP (tem) && EQ (XCAR (tem), Qkeymap)) XSETCDR (elt, Fcopy_keymap (tem)); } @@ -1127,9 +1092,7 @@ binding KEY to DEF is added at the front of KEYMAP. */) GCPRO3 (keymap, key, def); keymap = get_keymap (keymap, 1, 1); - CHECK_VECTOR_OR_STRING (key); - - length = XFASTINT (Flength (key)); + length = CHECK_VECTOR_OR_STRING (key); if (length == 0) RETURN_UNGCPRO (Qnil); @@ -1283,9 +1246,7 @@ recognize the default bindings, just as `read-key-sequence' does. */) GCPRO2 (keymap, key); keymap = get_keymap (keymap, 1, 1); - CHECK_VECTOR_OR_STRING (key); - - length = XFASTINT (Flength (key)); + length = CHECK_VECTOR_OR_STRING (key); if (length == 0) RETURN_UNGCPRO (keymap); @@ -1338,11 +1299,8 @@ define_as_prefix (Lisp_Object keymap, Lisp_Object c) static Lisp_Object append_key (Lisp_Object key_sequence, Lisp_Object key) { - Lisp_Object args[2]; - - args[0] = key_sequence; - args[1] = list1 (key); - return Fvconcat (2, args); + AUTO_LIST1 (key_list, key); + return Fvconcat (2, ((Lisp_Object []) { key_sequence, key_list })); } /* Given a event type C which is a symbol, @@ -1381,11 +1339,10 @@ silly_event_symbol_error (Lisp_Object c) *p = 0; c = reorder_modifiers (c); - keystring = concat2 (build_string (new_mods), XCDR (assoc)); + AUTO_STRING (new_mods_string, new_mods); + keystring = concat2 (new_mods_string, XCDR (assoc)); - error ((modifiers & ~meta_modifier - ? "To bind the key %s, use [?%s], not [%s]" - : "To bind the key %s, use \"%s\", not [%s]"), + error ("To bind the key %s, use [?%s], not [%s]", SDATA (SYMBOL_NAME (c)), SDATA (keystring), SDATA (SYMBOL_NAME (c))); } @@ -1894,7 +1851,7 @@ struct accessible_keymaps_data { static void accessible_keymaps_1 (Lisp_Object key, Lisp_Object cmd, Lisp_Object args, void *data) -/* Use void* data to be compatible with map_keymap_function_t. */ +/* Use void * data to be compatible with map_keymap_function_t. */ { struct accessible_keymaps_data *d = data; /* Cast! */ Lisp_Object maps = d->maps; @@ -2280,14 +2237,19 @@ Optional argument NO-ANGLES non-nil means don't put angle brackets around function keys and event symbols. */) (Lisp_Object key, Lisp_Object no_angles) { + USE_SAFE_ALLOCA; + if (CONSP (key) && lucid_event_type_list_p (key)) key = Fevent_convert_list (key); if (CONSP (key) && INTEGERP (XCAR (key)) && INTEGERP (XCDR (key))) /* An interval from a map-char-table. */ - return concat3 (Fsingle_key_description (XCAR (key), no_angles), - build_string (".."), - Fsingle_key_description (XCDR (key), no_angles)); + { + AUTO_STRING (dot_dot, ".."); + return concat3 (Fsingle_key_description (XCAR (key), no_angles), + dot_dot, + Fsingle_key_description (XCDR (key), no_angles)); + } key = EVENT_HEAD (key); @@ -2303,7 +2265,6 @@ around function keys and event symbols. */) if (NILP (no_angles)) { Lisp_Object result; - USE_SAFE_ALLOCA; char *buffer = SAFE_ALLOCA (sizeof "<>" + SBYTES (SYMBOL_NAME (key))); esprintf (buffer, "<%s>", SDATA (SYMBOL_NAME (key))); @@ -2574,9 +2535,8 @@ If FIRSTONLY has another non-nil value, prefer bindings that use the modifier key specified in `where-is-preferred-modifier' \(or their meta variants) and entirely reject menu bindings. -If optional 4th arg NOINDIRECT is non-nil, don't follow indirections -to other keymaps or slots. This makes it possible to search for an -indirect definition itself. +If optional 4th arg NOINDIRECT is non-nil, don't extract the commands inside +menu-items. This makes it possible to search for a menu-item itself. The optional 5th arg NO-REMAP alters how command remapping is handled: @@ -2925,13 +2885,14 @@ You type Translation\n\ if (!SYMBOLP (modes[i])) emacs_abort (); - p = title = alloca (42 + SCHARS (SYMBOL_NAME (modes[i]))); + USE_SAFE_ALLOCA; + p = title = SAFE_ALLOCA (42 + SBYTES (SYMBOL_NAME (modes[i]))); *p++ = '\f'; *p++ = '\n'; *p++ = '`'; memcpy (p, SDATA (SYMBOL_NAME (modes[i])), - SCHARS (SYMBOL_NAME (modes[i]))); - p += SCHARS (SYMBOL_NAME (modes[i])); + SBYTES (SYMBOL_NAME (modes[i]))); + p += SBYTES (SYMBOL_NAME (modes[i])); *p++ = '\''; memcpy (p, " Minor Mode Bindings", strlen (" Minor Mode Bindings")); p += strlen (" Minor Mode Bindings"); @@ -2940,6 +2901,7 @@ You type Translation\n\ describe_map_tree (maps[i], 1, shadow, prefix, title, nomenu, 0, 0, 0); shadow = Fcons (maps[i], shadow); + SAFE_FREE (); } start1 = get_local_map (BUF_PT (XBUFFER (buffer)), @@ -3226,10 +3188,10 @@ describe_map (Lisp_Object map, Lisp_Object prefix, /* These accumulate the values from sparse keymap bindings, so we can sort them and handle them in order. */ - int length_needed = 0; + ptrdiff_t length_needed = 0; struct describe_map_elt *vect; - int slots_used = 0; - int i; + ptrdiff_t slots_used = 0; + ptrdiff_t i; suppress = Qnil; @@ -3249,7 +3211,8 @@ describe_map (Lisp_Object map, Lisp_Object prefix, for (tail = map; CONSP (tail); tail = XCDR (tail)) length_needed++; - vect = alloca (length_needed * sizeof *vect); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (vect, 1, length_needed); for (tail = map; CONSP (tail); tail = XCDR (tail)) { @@ -3392,6 +3355,7 @@ describe_map (Lisp_Object map, Lisp_Object prefix, } } + SAFE_FREE (); UNGCPRO; } @@ -3400,7 +3364,7 @@ describe_vector_princ (Lisp_Object elt, Lisp_Object fun) { Findent_to (make_number (16), make_number (1)); call1 (fun, elt); - Fterpri (Qnil); + Fterpri (Qnil, Qnil); } DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0, @@ -3480,9 +3444,9 @@ describe_vector (Lisp_Object vector, Lisp_Object prefix, Lisp_Object args, /* Call Fkey_description first, to avoid GC bug for the other string. */ if (!NILP (prefix) && XFASTINT (Flength (prefix)) > 0) { - Lisp_Object tem; - tem = Fkey_description (prefix, Qnil); - elt_prefix = concat2 (tem, build_string (" ")); + Lisp_Object tem = Fkey_description (prefix, Qnil); + AUTO_STRING (space, " "); + elt_prefix = concat2 (tem, space); } prefix = Qnil; } diff --git a/src/keymap.h b/src/keymap.h index 4a408c6a2a0..b01886dfa61 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -46,7 +46,7 @@ extern void syms_of_keymap (void); extern void keys_of_keymap (void); typedef void (*map_keymap_function_t) - (Lisp_Object key, Lisp_Object val, Lisp_Object args, void* data); + (Lisp_Object key, Lisp_Object val, Lisp_Object args, void *data); extern void map_keymap (Lisp_Object, map_keymap_function_t, Lisp_Object, void *, bool); extern void map_keymap_canonical (Lisp_Object map, diff --git a/src/lastfile.c b/src/lastfile.c index a900e9541c8..84b28b0311b 100644 --- a/src/lastfile.c +++ b/src/lastfile.c @@ -36,6 +36,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> +#include "lisp.h" + char my_edata[] = "End of Emacs initialized data"; /* Help unexec locate the end of the .bss area used by Emacs (which diff --git a/src/lisp.h b/src/lisp.h index 0bcc0ec0e3f..d8809fd10d7 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -36,41 +36,15 @@ INLINE_HEADER_BEGIN /* Define a TYPE constant ID as an externally visible name. Use like this: - #define ID_val (some integer preprocessor expression) - #if ENUMABLE (ID_val) - DEFINE_GDB_SYMBOL_ENUM (ID) - #else DEFINE_GDB_SYMBOL_BEGIN (TYPE, ID) - # define ID ID_val + # define ID (some integer preprocessor expression of type TYPE) DEFINE_GDB_SYMBOL_END (ID) - #endif This hack is for the benefit of compilers that do not make macro - definitions visible to the debugger. It's used for symbols that - .gdbinit needs, symbols whose values may not fit in 'int' (where an - enum would suffice). + definitions or enums visible to the debugger. It's used for symbols + that .gdbinit needs. */ - Some GCC versions before GCC 4.2 omit enums in debugging output; - see GCC bug 23336. So don't use enums with older GCC. */ - -#if !defined __GNUC__ || 4 < __GNUC__ + (2 <= __GNUC_MINOR__) -# define ENUMABLE(val) (INT_MIN <= (val) && (val) <= INT_MAX) -#else -# define ENUMABLE(val) 0 -#endif - -/* On AIX 7.1 ENUMABLE should return true when possible, otherwise the - linker can optimize the symbols away, making it harder to debug. - This was discovered only late in the release process, so to play it - safe for now, non-AIX platforms do not use enums for debugging symbols. - FIXME: remove this comment and the following four lines of code. */ -#ifndef _AIX -# undef ENUMABLE -# define ENUMABLE(val) 0 -#endif - -#define DEFINE_GDB_SYMBOL_ENUM(id) enum { id = id##_val }; -#if defined MAIN_PROGRAM +#ifdef MAIN_PROGRAM # define DEFINE_GDB_SYMBOL_BEGIN(type, id) type const id EXTERNALLY_VISIBLE # define DEFINE_GDB_SYMBOL_END(id) = id; #else @@ -84,6 +58,27 @@ INLINE_HEADER_BEGIN #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) +/* Number of elements in an array. */ +#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) + +/* Number of bits in a Lisp_Object tag. */ +DEFINE_GDB_SYMBOL_BEGIN (int, GCTYPEBITS) +#define GCTYPEBITS 3 +DEFINE_GDB_SYMBOL_END (GCTYPEBITS) + +/* The number of bits needed in an EMACS_INT over and above the number + of bits in a pointer. This is 0 on systems where: + 1. We can specify multiple-of-8 alignment on static variables. + 2. We know malloc returns a multiple of 8. */ +#if (defined alignas \ + && (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \ + || defined DARWIN_OS || defined __sun || defined __MINGW32__ \ + || defined CYGWIN)) +# define NONPOINTER_BITS 0 +#else +# define NONPOINTER_BITS GCTYPEBITS +#endif + /* EMACS_INT - signed integer wide enough to hold an Emacs value EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if pI - printf length modifier for EMACS_INT @@ -91,16 +86,18 @@ INLINE_HEADER_BEGIN #ifndef EMACS_INT_MAX # if INTPTR_MAX <= 0 # error "INTPTR_MAX misconfigured" -# elif INTPTR_MAX <= INT_MAX && !defined WIDE_EMACS_INT +# elif INTPTR_MAX <= INT_MAX >> NONPOINTER_BITS && !defined WIDE_EMACS_INT typedef int EMACS_INT; typedef unsigned int EMACS_UINT; # define EMACS_INT_MAX INT_MAX # define pI "" -# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT +# elif INTPTR_MAX <= LONG_MAX >> NONPOINTER_BITS && !defined WIDE_EMACS_INT typedef long int EMACS_INT; typedef unsigned long EMACS_UINT; # define EMACS_INT_MAX LONG_MAX # define pI "l" +/* Check versus LLONG_MAX, not LLONG_MAX >> NONPOINTER_BITS. + In theory this is not safe, but in practice it seems to be OK. */ # elif INTPTR_MAX <= LLONG_MAX typedef long long int EMACS_INT; typedef unsigned long long int EMACS_UINT; @@ -119,7 +116,7 @@ enum { BOOL_VECTOR_BITS_PER_CHAR = }; /* An unsigned integer type representing a fixed-length bit sequence, - suitable for words in a Lisp bool vector. Normally it is size_t + suitable for bool vector words, GC mark bits, etc. Normally it is size_t for speed, but it is unsigned char on weird platforms. */ #if BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT typedef size_t bits_word; @@ -137,7 +134,6 @@ enum { BITS_PER_CHAR = CHAR_BIT, BITS_PER_SHORT = CHAR_BIT * sizeof (short), - BITS_PER_INT = CHAR_BIT * sizeof (int), BITS_PER_LONG = CHAR_BIT * sizeof (long int), BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) }; @@ -241,12 +237,6 @@ extern bool suppress_checking EXTERNALLY_VISIBLE; enum Lisp_Bits { - /* Number of bits in a Lisp_Object tag. This can be used in #if, - and for GDB's sake also as a regular symbol. */ - GCTYPEBITS = -#define GCTYPEBITS 3 - GCTYPEBITS, - /* 2**GCTYPEBITS. This must be a macro that expands to a literal integer constant, for MSVC. */ #define GCALIGNMENT 8 @@ -270,31 +260,19 @@ enum Lisp_Bits This can be used in #if, e.g., '#if VAL_MAX < UINTPTR_MAX' below. */ #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1)) -/* Unless otherwise specified, use USE_LSB_TAG on systems where: */ -#ifndef USE_LSB_TAG -/* 1. We know malloc returns a multiple of 8. */ -# if (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \ - || defined DARWIN_OS || defined __sun) -/* 2. We can specify multiple-of-8 alignment on static variables. */ -# ifdef alignas -/* 3. Pointers-as-ints exceed VAL_MAX. +/* Whether the least-significant bits of an EMACS_INT contain the tag. On hosts where pointers-as-ints do not exceed VAL_MAX, USE_LSB_TAG is: a. unnecessary, because the top bits of an EMACS_INT are unused, and b. slower, because it typically requires extra masking. - So, default USE_LSB_TAG to true only on hosts where it might be useful. */ -# if VAL_MAX < UINTPTR_MAX -# define USE_LSB_TAG true -# endif -# endif -# endif -#endif -#ifdef USE_LSB_TAG -# undef USE_LSB_TAG -enum enum_USE_LSB_TAG { USE_LSB_TAG = true }; -# define USE_LSB_TAG true -#else -enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; -# define USE_LSB_TAG false + So, USE_LSB_TAG is true only on hosts where it might be useful. */ +DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG) +#define USE_LSB_TAG (EMACS_INT_MAX >> GCTYPEBITS < INTPTR_MAX) +DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) + +#if !USE_LSB_TAG && !defined WIDE_EMACS_INT +# error "USE_LSB_TAG not supported on this platform; please report this." \ + "Try 'configure --with-wide-int' to work around the problem." +error !; #endif #ifndef alignas @@ -304,6 +282,11 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; # endif #endif +#ifdef HAVE_STRUCT_ATTRIBUTE_ALIGNED +# define GCALIGNED __attribute__ ((aligned (GCALIGNMENT))) +#else +# define GCALIGNED /* empty */ +#endif /* Some operations are so commonly executed that they are implemented as macros, not functions, because otherwise runtime performance would @@ -348,8 +331,8 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; #define lisp_h_CHECK_LIST_CONS(x, y) CHECK_TYPE (CONSP (x), Qlistp, y) #define lisp_h_CHECK_NUMBER(x) CHECK_TYPE (INTEGERP (x), Qintegerp, x) #define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x) -#define lisp_h_CHECK_TYPE(ok, Qxxxp, x) \ - ((ok) ? (void) 0 : (void) wrong_type_argument (Qxxxp, x)) +#define lisp_h_CHECK_TYPE(ok, predicate, x) \ + ((ok) ? (void) 0 : (void) wrong_type_argument (predicate, x)) #define lisp_h_CONSP(x) (XTYPE (x) == Lisp_Cons) #define lisp_h_EQ(x, y) (XLI (x) == XLI (y)) #define lisp_h_FLOATP(x) (XTYPE (x) == Lisp_Float) @@ -369,15 +352,15 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; #define lisp_h_XCONS(a) \ (eassert (CONSP (a)), (struct Lisp_Cons *) XUNTAG (a, Lisp_Cons)) #define lisp_h_XHASH(a) XUINT (a) -#define lisp_h_XPNTR(a) \ - ((void *) (intptr_t) ((XLI (a) & VALMASK) | (DATA_SEG_BITS & ~VALMASK))) +#define lisp_h_XPNTR(a) ((void *) (intptr_t) (XLI (a) & VALMASK)) #define lisp_h_XSYMBOL(a) \ (eassert (SYMBOLP (a)), (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol)) #ifndef GC_CHECK_CONS_LIST # define lisp_h_check_cons_list() ((void) 0) #endif #if USE_LSB_TAG -# define lisp_h_make_number(n) XIL ((EMACS_INT) (n) << INTTYPEBITS) +# define lisp_h_make_number(n) \ + XIL ((EMACS_INT) ((EMACS_UINT) (n) << INTTYPEBITS)) # define lisp_h_XFASTINT(a) XINT (a) # define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS) # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) @@ -395,7 +378,7 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; # define CHECK_LIST_CONS(x, y) lisp_h_CHECK_LIST_CONS (x, y) # define CHECK_NUMBER(x) lisp_h_CHECK_NUMBER (x) # define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x) -# define CHECK_TYPE(ok, Qxxxp, x) lisp_h_CHECK_TYPE (ok, Qxxxp, x) +# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x) # define CONSP(x) lisp_h_CONSP (x) # define EQ(x, y) lisp_h_EQ (x, y) # define FLOATP(x) lisp_h_FLOATP (x) @@ -597,25 +580,15 @@ LISP_MACRO_DEFUN (XIL, Lisp_Object, (EMACS_INT i), (i)) /* In the size word of a vector, this bit means the vector has been marked. */ -#define ARRAY_MARK_FLAG_val PTRDIFF_MIN -#if ENUMABLE (ARRAY_MARK_FLAG_val) -DEFINE_GDB_SYMBOL_ENUM (ARRAY_MARK_FLAG) -#else DEFINE_GDB_SYMBOL_BEGIN (ptrdiff_t, ARRAY_MARK_FLAG) -# define ARRAY_MARK_FLAG ARRAY_MARK_FLAG_val +# define ARRAY_MARK_FLAG PTRDIFF_MIN DEFINE_GDB_SYMBOL_END (ARRAY_MARK_FLAG) -#endif /* In the size word of a struct Lisp_Vector, this bit means it's really some other vector-like object. */ -#define PSEUDOVECTOR_FLAG_val (PTRDIFF_MAX - PTRDIFF_MAX / 2) -#if ENUMABLE (PSEUDOVECTOR_FLAG_val) -DEFINE_GDB_SYMBOL_ENUM (PSEUDOVECTOR_FLAG) -#else DEFINE_GDB_SYMBOL_BEGIN (ptrdiff_t, PSEUDOVECTOR_FLAG) -# define PSEUDOVECTOR_FLAG PSEUDOVECTOR_FLAG_val +# define PSEUDOVECTOR_FLAG (PTRDIFF_MAX - PTRDIFF_MAX / 2) DEFINE_GDB_SYMBOL_END (PSEUDOVECTOR_FLAG) -#endif /* In a pseudovector, the size field actually contains a word with one PSEUDOVECTOR_FLAG bit set, and one of the following values extracted @@ -641,18 +614,8 @@ enum pvec_type PVEC_FONT /* Should be last because it's used for range checking. */ }; -/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers - which were stored in a Lisp_Object. */ -#ifndef DATA_SEG_BITS -# define DATA_SEG_BITS 0 -#endif -enum { gdb_DATA_SEG_BITS = DATA_SEG_BITS }; -#undef DATA_SEG_BITS - enum More_Lisp_Bits { - DATA_SEG_BITS = gdb_DATA_SEG_BITS, - /* For convenience, we also store the number of elements in these bits. Note that this size is not necessarily the memory-footprint size, but only the number of Lisp_Object fields (that need to be traced by GC). @@ -678,14 +641,9 @@ enum More_Lisp_Bits that cons. */ /* Mask for the value (as opposed to the type bits) of a Lisp object. */ -#define VALMASK_val (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX) -#if ENUMABLE (VALMASK_val) -DEFINE_GDB_SYMBOL_ENUM (VALMASK) -#else DEFINE_GDB_SYMBOL_BEGIN (EMACS_INT, VALMASK) -# define VALMASK VALMASK_val +# define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX) DEFINE_GDB_SYMBOL_END (VALMASK) -#endif /* Largest and smallest representable fixnum values. These are the C values. They are macros for use in static initializers. */ @@ -714,7 +672,14 @@ LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type)) INLINE Lisp_Object make_number (EMACS_INT n) { - return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK); + if (USE_LSB_TAG) + { + EMACS_UINT u = n; + n = u << INTTYPEBITS; + } + else + n &= INTMASK; + return XIL (n); } /* Extract A's value as a signed integer. */ @@ -722,7 +687,12 @@ INLINE EMACS_INT XINT (Lisp_Object a) { EMACS_INT i = XLI (a); - return (USE_LSB_TAG ? i : i << INTTYPEBITS) >> INTTYPEBITS; + if (! USE_LSB_TAG) + { + EMACS_UINT u = i; + i = u << INTTYPEBITS; + } + return i >> INTTYPEBITS; } /* Like XINT (A), but may be faster. A must be nonnegative. @@ -828,7 +798,6 @@ INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object); /* Defined in chartab.c. */ extern Lisp_Object char_table_ref (Lisp_Object, int); extern void char_table_set (Lisp_Object, int, Lisp_Object); -extern int char_table_translate (Lisp_Object, int); /* Defined in data.c. */ extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p; @@ -837,10 +806,13 @@ extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qt, Qvectorp; extern Lisp_Object Qbool_vector_p; extern Lisp_Object Qvector_or_char_table_p, Qwholenump; extern Lisp_Object Qwindow; -extern Lisp_Object Ffboundp (Lisp_Object); extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object); +extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object); /* Defined in emacs.c. */ +extern bool might_dump; +/* True means Emacs has already been initialized. + Used during startup to detect startup of dumped Emacs. */ extern bool initialized; /* Defined in eval.c. */ @@ -1006,8 +978,9 @@ make_lisp_proc (struct Lisp_Process *p) /* Type checking. */ -LISP_MACRO_DEFUN_VOID (CHECK_TYPE, (int ok, Lisp_Object Qxxxp, Lisp_Object x), - (ok, Qxxxp, x)) +LISP_MACRO_DEFUN_VOID (CHECK_TYPE, + (int ok, Lisp_Object predicate, Lisp_Object x), + (ok, predicate, x)) /* Deprecated and will be removed soon. */ @@ -1017,7 +990,7 @@ LISP_MACRO_DEFUN_VOID (CHECK_TYPE, (int ok, Lisp_Object Qxxxp, Lisp_Object x), typedef struct interval *INTERVAL; -struct Lisp_Cons +struct GCALIGNED Lisp_Cons { /* Car of this cons cell. */ Lisp_Object car; @@ -1099,7 +1072,7 @@ CDR_SAFE (Lisp_Object c) /* In a string or vector, the sign bit of the `size' is the gc mark bit. */ -struct Lisp_String +struct GCALIGNED Lisp_String { ptrdiff_t size; ptrdiff_t size_byte; @@ -1201,12 +1174,6 @@ STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize) { XSTRING (string)->size = newsize; } -INLINE void -STRING_COPYIN (Lisp_Object string, ptrdiff_t index, char const *new, - ptrdiff_t count) -{ - memcpy (SDATA (string) + index, new, count); -} /* Header of vector-like objects. This documents the layout constraints on vectors and pseudovectors (objects of PVEC_xxx subtype). It also prevents @@ -1415,10 +1382,11 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) sense to handle a char-table with type struct Lisp_Vector. An element of a char table can be any Lisp objects, but if it is a sub char-table, we treat it a table that contains information of a - specific range of characters. A sub char-table has the same - structure as a vector. A sub char table appears only in an element - of a char-table, and there's no way to access it directly from - Emacs Lisp program. */ + specific range of characters. A sub char-table is like a vector but + with two integer fields between the header and Lisp data, which means + that it has to be marked with some precautions (see mark_char_table + in alloc.c). A sub char-table appears only in an element of a char-table, + and there's no way to access it directly from Emacs Lisp program. */ enum CHARTAB_SIZE_BITS { @@ -1473,10 +1441,10 @@ struct Lisp_Sub_Char_Table contains 32 elements, and each element covers 128 characters. A sub char-table of depth 3 contains 128 elements, and each element is for one character. */ - Lisp_Object depth; + int depth; /* Minimum character covered by the sub char-table. */ - Lisp_Object min_char; + int min_char; /* Use set_sub_char_table_contents to set this. */ Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER]; @@ -1547,12 +1515,16 @@ struct Lisp_Subr const char *doc; }; -/* This is the number of slots that every char table must have. This - counts the ordinary slots and the top, defalt, parent, and purpose - slots. */ -enum CHAR_TABLE_STANDARD_SLOTS +enum char_table_specials { - CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras) + /* This is the number of slots that every char table must have. This + counts the ordinary slots and the top, defalt, parent, and purpose + slots. */ + CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras), + + /* This is an index of first Lisp_Object field in Lisp_Sub_Char_Table + when the latter is treated as an ordinary Lisp_Vector. */ + SUB_CHAR_TABLE_OFFSET = PSEUDOVECSIZE (struct Lisp_Sub_Char_Table, contents) }; /* Return the number of "extra" slots in the char table CT. */ @@ -1564,7 +1536,11 @@ CHAR_TABLE_EXTRA_SLOTS (struct Lisp_Char_Table *ct) - CHAR_TABLE_STANDARD_SLOTS); } - +/* Make sure that sub char-table contents slot + is aligned on a multiple of Lisp_Objects. */ +verify ((offsetof (struct Lisp_Sub_Char_Table, contents) + - offsetof (struct Lisp_Sub_Char_Table, depth)) % word_size == 0); + /*********************************************************************** Symbols ***********************************************************************/ @@ -2555,15 +2531,20 @@ CHECK_BOOL_VECTOR (Lisp_Object x) { CHECK_TYPE (BOOL_VECTOR_P (x), Qbool_vector_p, x); } -INLINE void +/* This is a bit special because we always need size afterwards. */ +INLINE ptrdiff_t CHECK_VECTOR_OR_STRING (Lisp_Object x) { - CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x); + if (VECTORP (x)) + return ASIZE (x); + if (STRINGP (x)) + return SCHARS (x); + wrong_type_argument (Qarrayp, x); } INLINE void -CHECK_ARRAY (Lisp_Object x, Lisp_Object Qxxxp) +CHECK_ARRAY (Lisp_Object x, Lisp_Object predicate) { - CHECK_TYPE (ARRAYP (x), Qxxxp, x); + CHECK_TYPE (ARRAYP (x), predicate, x); } INLINE void CHECK_BUFFER (Lisp_Object x) @@ -2690,16 +2671,10 @@ CHECK_NUMBER_CDR (Lisp_Object x) minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #else /* not _MSC_VER */ -# if __STDC_VERSION__ < 199901 -# define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname -# else -# define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname -# endif #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ - Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ - { DEFUN_FUNCTION_INIT (fnname, maxargs) }, \ + { .a ## maxargs = fnname }, \ minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #endif @@ -3036,6 +3011,16 @@ struct gcpro ptrdiff_t nvars; #ifdef DEBUG_GCPRO + /* File name where this record is used. */ + const char *name; + + /* Line number in this file. */ + int lineno; + + /* Index in the local chain of records. */ + int idx; + + /* Nesting level. */ int level; #endif }; @@ -3091,122 +3076,150 @@ struct gcpro #ifndef DEBUG_GCPRO -#define GCPRO1(varname) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname; gcpro1.nvars = 1; \ - gcprolist = &gcpro1; } - -#define GCPRO2(varname1, varname2) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcprolist = &gcpro2; } - -#define GCPRO3(varname1, varname2, varname3) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcprolist = &gcpro3; } - -#define GCPRO4(varname1, varname2, varname3, varname4) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcprolist = &gcpro4; } +#define GCPRO1(a) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcprolist = &gcpro1; } + +#define GCPRO2(a, b) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcprolist = &gcpro2; } + +#define GCPRO3(a, b, c) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcprolist = &gcpro3; } + +#define GCPRO4(a, b, c, d) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcprolist = &gcpro4; } + +#define GCPRO5(a, b, c, d, e) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ + gcprolist = &gcpro5; } + +#define GCPRO6(a, b, c, d, e, f) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ + gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \ + gcprolist = &gcpro6; } -#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcprolist = &gcpro5; } - -#define GCPRO6(varname1, varname2, varname3, varname4, varname5, varname6) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcpro6.next = &gcpro5; gcpro6.var = &varname6; gcpro6.nvars = 1; \ - gcprolist = &gcpro6; } - -#define GCPRO7(a, b, c, d, e, f, g) \ - {gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ - gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \ - gcpro7.next = &gcpro6; gcpro7.var = &(g); gcpro7.nvars = 1; \ - gcprolist = &gcpro7; } +#define GCPRO7(a, b, c, d, e, f, g) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ + gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \ + gcpro7.next = &gcpro6; gcpro7.var = &(g); gcpro7.nvars = 1; \ + gcprolist = &gcpro7; } #define UNGCPRO (gcprolist = gcpro1.next) -#else +#else /* !DEBUG_GCPRO */ extern int gcpro_level; -#define GCPRO1(varname) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level++; \ - gcprolist = &gcpro1; } - -#define GCPRO2(varname1, varname2) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro2.level = gcpro_level++; \ - gcprolist = &gcpro2; } - -#define GCPRO3(varname1, varname2, varname3) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro3.level = gcpro_level++; \ - gcprolist = &gcpro3; } - -#define GCPRO4(varname1, varname2, varname3, varname4) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro4.level = gcpro_level++; \ - gcprolist = &gcpro4; } - -#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcpro5.level = gcpro_level++; \ - gcprolist = &gcpro5; } - -#define GCPRO6(varname1, varname2, varname3, varname4, varname5, varname6) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcpro6.next = &gcpro5; gcpro6.var = &varname6; gcpro6.nvars = 1; \ - gcpro6.level = gcpro_level++; \ - gcprolist = &gcpro6; } +#define GCPRO1(a) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level++; \ + gcprolist = &gcpro1; } + +#define GCPRO2(a, b) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro2.name = __FILE__; gcpro2.lineno = __LINE__; gcpro2.idx = 2; \ + gcpro2.level = gcpro_level++; \ + gcprolist = &gcpro2; } + +#define GCPRO3(a, b, c) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro2.name = __FILE__; gcpro2.lineno = __LINE__; gcpro2.idx = 2; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro3.name = __FILE__; gcpro3.lineno = __LINE__; gcpro3.idx = 3; \ + gcpro3.level = gcpro_level++; \ + gcprolist = &gcpro3; } + +#define GCPRO4(a, b, c, d) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro2.name = __FILE__; gcpro2.lineno = __LINE__; gcpro2.idx = 2; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro3.name = __FILE__; gcpro3.lineno = __LINE__; gcpro3.idx = 3; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro4.name = __FILE__; gcpro4.lineno = __LINE__; gcpro4.idx = 4; \ + gcpro4.level = gcpro_level++; \ + gcprolist = &gcpro4; } + +#define GCPRO5(a, b, c, d, e) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro2.name = __FILE__; gcpro2.lineno = __LINE__; gcpro2.idx = 2; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro3.name = __FILE__; gcpro3.lineno = __LINE__; gcpro3.idx = 3; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro4.name = __FILE__; gcpro4.lineno = __LINE__; gcpro4.idx = 4; \ + gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ + gcpro5.name = __FILE__; gcpro5.lineno = __LINE__; gcpro5.idx = 5; \ + gcpro5.level = gcpro_level++; \ + gcprolist = &gcpro5; } + +#define GCPRO6(a, b, c, d, e, f) \ + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro2.name = __FILE__; gcpro2.lineno = __LINE__; gcpro2.idx = 2; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro3.name = __FILE__; gcpro3.lineno = __LINE__; gcpro3.idx = 3; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro4.name = __FILE__; gcpro4.lineno = __LINE__; gcpro4.idx = 4; \ + gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ + gcpro5.name = __FILE__; gcpro5.lineno = __LINE__; gcpro5.idx = 5; \ + gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \ + gcpro6.name = __FILE__; gcpro6.lineno = __LINE__; gcpro6.idx = 6; \ + gcpro6.level = gcpro_level++; \ + gcprolist = &gcpro6; } #define GCPRO7(a, b, c, d, e, f, g) \ - {gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ - gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \ - gcpro7.next = &gcpro6; gcpro7.var = &(g); gcpro7.nvars = 1; \ - gcpro7.level = gcpro_level++; \ - gcprolist = &gcpro7; } + { gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \ + gcpro1.name = __FILE__; gcpro1.lineno = __LINE__; gcpro1.idx = 1; \ + gcpro1.level = gcpro_level; \ + gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \ + gcpro2.name = __FILE__; gcpro2.lineno = __LINE__; gcpro2.idx = 2; \ + gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \ + gcpro3.name = __FILE__; gcpro3.lineno = __LINE__; gcpro3.idx = 3; \ + gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \ + gcpro4.name = __FILE__; gcpro4.lineno = __LINE__; gcpro4.idx = 4; \ + gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \ + gcpro5.name = __FILE__; gcpro5.lineno = __LINE__; gcpro5.idx = 5; \ + gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \ + gcpro6.name = __FILE__; gcpro6.lineno = __LINE__; gcpro6.idx = 6; \ + gcpro7.next = &gcpro6; gcpro7.var = &(g); gcpro7.nvars = 1; \ + gcpro7.name = __FILE__; gcpro7.lineno = __LINE__; gcpro7.idx = 7; \ + gcpro7.level = gcpro_level++; \ + gcprolist = &gcpro7; } #define UNGCPRO \ (--gcpro_level != gcpro1.level \ @@ -3359,7 +3372,7 @@ set_sub_char_table_contents (Lisp_Object table, ptrdiff_t idx, Lisp_Object val) } /* Defined in data.c. */ -extern Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound; +extern Lisp_Object Qquote, Qunbound; extern Lisp_Object Qerror_conditions, Qerror_message, Qtop_level; extern Lisp_Object Qerror, Qquit, Qargs_out_of_range; extern Lisp_Object Qvoid_variable, Qvoid_function; @@ -3370,26 +3383,18 @@ extern Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only; extern Lisp_Object Qtext_read_only; extern Lisp_Object Qinteractive_form; extern Lisp_Object Qcircular_list; -extern Lisp_Object Qintegerp, Qwholenump, Qsymbolp, Qlistp, Qconsp; -extern Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp; -extern Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; -extern Lisp_Object Qbuffer_or_string_p; +extern Lisp_Object Qsequencep; +extern Lisp_Object Qchar_or_string_p, Qinteger_or_marker_p; extern Lisp_Object Qfboundp; -extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p; extern Lisp_Object Qcdr; extern Lisp_Object Qrange_error, Qoverflow_error; -extern Lisp_Object Qfloatp; -extern Lisp_Object Qnumberp, Qnumber_or_marker_p; +extern Lisp_Object Qnumber_or_marker_p; extern Lisp_Object Qbuffer, Qinteger, Qsymbol; -extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object; - -EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST; - /* Defined in data.c. */ extern Lisp_Object indirect_function (Lisp_Object); extern Lisp_Object find_symbol_value (Lisp_Object); @@ -3436,7 +3441,6 @@ extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *); extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object); extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); -extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object); extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *); extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object, bool); extern void syms_of_data (void); @@ -3455,11 +3459,8 @@ extern void init_coding_once (void); extern void syms_of_coding (void); /* Defined in character.c. */ -EXFUN (Fmax_char, 0) ATTRIBUTE_CONST; extern ptrdiff_t chars_in_text (const unsigned char *, ptrdiff_t); extern ptrdiff_t multibyte_chars_in_text (const unsigned char *, ptrdiff_t); -extern int multibyte_char_to_unibyte (int) ATTRIBUTE_CONST; -extern int multibyte_char_to_unibyte_safe (int) ATTRIBUTE_CONST; extern void syms_of_character (void); /* Defined in charset.c. */ @@ -3469,9 +3470,6 @@ extern void syms_of_charset (void); /* Structure forward declarations. */ struct charset; -/* Defined in composite.c. */ -extern void syms_of_composite (void); - /* Defined in syntax.c. */ extern void init_syntax_once (void); extern void syms_of_syntax (void); @@ -3479,7 +3477,6 @@ extern void syms_of_syntax (void); /* Defined in fns.c. */ extern Lisp_Object QCrehash_size, QCrehash_threshold; enum { NEXT_ALMOST_PRIME_LIMIT = 11 }; -EXFUN (Fidentity, 1) ATTRIBUTE_CONST; extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST; extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t); extern void sweep_weak_hash_tables (void); @@ -3494,7 +3491,8 @@ ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *); ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, EMACS_UINT); extern struct hash_table_test hashtest_eql, hashtest_equal; - +extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object, + ptrdiff_t, ptrdiff_t *, ptrdiff_t *); extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object); @@ -3512,7 +3510,6 @@ extern Lisp_Object string_make_unibyte (Lisp_Object); extern void syms_of_fns (void); /* Defined in floatfns.c. */ -extern double extract_float (Lisp_Object); extern void syms_of_floatfns (void); extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y); @@ -3533,6 +3530,7 @@ extern void syms_of_image (void); /* Defined in insdel.c. */ extern Lisp_Object Qinhibit_modification_hooks; +extern Lisp_Object Qregion_extract_function; extern void move_gap_both (ptrdiff_t, ptrdiff_t); extern _Noreturn void buffer_overflow (void); extern void make_gap (ptrdiff_t); @@ -3585,18 +3583,16 @@ _Noreturn void __executable_start (void); #endif extern Lisp_Object Vwindow_system; extern Lisp_Object sit_for (Lisp_Object, bool, int); -extern void init_display (void); -extern void syms_of_display (void); /* Defined in xdisp.c. */ extern Lisp_Object Qinhibit_point_motion_hooks; -extern Lisp_Object Qinhibit_redisplay, Qdisplay; +extern Lisp_Object Qinhibit_redisplay; extern Lisp_Object Qmenu_bar_update_hook; extern Lisp_Object Qwindow_scroll_functions; extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; -extern Lisp_Object Qimage, Qtext, Qboth, Qboth_horiz, Qtext_image_horiz; +extern Lisp_Object Qtext, Qboth, Qboth_horiz, Qtext_image_horiz; extern Lisp_Object Qspace, Qcenter, QCalign_to; -extern Lisp_Object Qbar, Qhbar, Qbox, Qhollow; +extern Lisp_Object Qbar, Qhbar, Qhollow; extern Lisp_Object Qleft_margin, Qright_margin; extern Lisp_Object QCdata, QCfile; extern Lisp_Object QCmap; @@ -3623,7 +3619,6 @@ extern void message_log_maybe_newline (void); extern void update_echo_area (void); extern void truncate_echo_area (ptrdiff_t); extern void redisplay (void); -extern void redisplay_preserve_echo_area (int); void set_frame_cursor_types (struct frame *, Lisp_Object); extern void syms_of_xdisp (void); @@ -3638,6 +3633,10 @@ extern void syms_of_xsettings (void); /* Defined in vm-limit.c. */ extern void memory_warnings (void *, void (*warnfun) (const char *)); +/* Defined in character.c. */ +extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t, + ptrdiff_t *, ptrdiff_t *); + /* Defined in alloc.c. */ extern void check_pure_size (void); extern void free_misc (Lisp_Object); @@ -3647,7 +3646,7 @@ extern _Noreturn void memory_full (size_t); extern _Noreturn void buffer_memory_full (ptrdiff_t); extern bool survives_gc_p (Lisp_Object); extern void mark_object (Lisp_Object); -#if defined REL_ALLOC && !defined SYSTEM_MALLOC +#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC extern void refill_memory_reserve (void); #endif extern const char *pending_malloc_warning; @@ -3755,6 +3754,20 @@ make_uninit_vector (ptrdiff_t size) return v; } +/* Like above, but special for sub char-tables. */ + +INLINE Lisp_Object +make_uninit_sub_char_table (int depth, int min_char) +{ + int slots = SUB_CHAR_TABLE_OFFSET + chartab_size[depth]; + Lisp_Object v = make_uninit_vector (slots); + + XSETPVECTYPE (XVECTOR (v), PVEC_SUB_CHAR_TABLE); + XSUB_CHAR_TABLE (v)->depth = depth; + XSUB_CHAR_TABLE (v)->min_char = min_char; + return v; +} + extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type); #define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ ((typ*) \ @@ -3788,6 +3801,7 @@ extern void init_alloc (void); extern void syms_of_alloc (void); extern struct buffer * allocate_buffer (void); extern int valid_lisp_object_p (Lisp_Object); +extern int relocatable_string_data_p (const char *); #ifdef GC_CHECK_CONS_LIST extern void check_cons_list (void); #else @@ -3796,21 +3810,18 @@ INLINE void (check_cons_list) (void) { lisp_h_check_cons_list (); } #ifdef REL_ALLOC /* Defined in ralloc.c. */ -extern void *r_alloc (void **, size_t); +extern void *r_alloc (void **, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void r_alloc_free (void **); -extern void *r_re_alloc (void **, size_t); +extern void *r_re_alloc (void **, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void r_alloc_reset_variable (void **, void **); extern void r_alloc_inhibit_buffer_relocation (int); #endif /* Defined in chartab.c. */ extern Lisp_Object copy_char_table (Lisp_Object); -extern Lisp_Object char_table_ref (Lisp_Object, int); extern Lisp_Object char_table_ref_and_range (Lisp_Object, int, int *, int *); -extern void char_table_set (Lisp_Object, int, Lisp_Object); extern void char_table_set_range (Lisp_Object, int, int, Lisp_Object); -extern int char_table_translate (Lisp_Object, int); extern void map_char_table (void (*) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object); @@ -3858,6 +3869,7 @@ extern Lisp_Object Qlexical_binding; extern Lisp_Object check_obarray (Lisp_Object); extern Lisp_Object intern_1 (const char *, ptrdiff_t); extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t); +extern Lisp_Object intern_driver (Lisp_Object, Lisp_Object, ptrdiff_t); extern Lisp_Object oblookup (Lisp_Object, const char *, ptrdiff_t, ptrdiff_t); INLINE void LOADHIST_ATTACH (Lisp_Object x) @@ -3888,7 +3900,8 @@ intern_c_string (const char *str) } /* Defined in eval.c. */ -extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qmacro; +extern EMACS_INT lisp_eval_depth; +extern Lisp_Object Qexit, Qinteractive, Qcommandp, Qmacro; extern Lisp_Object Qinhibit_quit, Qinternal_interpreter_environment, Qclosure; extern Lisp_Object Qand_rest; extern Lisp_Object Vautoload_queue; @@ -3977,7 +3990,6 @@ extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool); extern void init_editfns (void); extern void syms_of_editfns (void); -extern void set_time_zone_rule (const char *); /* Defined in buffer.c. */ extern bool mouse_face_overlay_overlaps (Lisp_Object); @@ -3991,7 +4003,7 @@ extern bool overlay_touches_p (ptrdiff_t); extern Lisp_Object other_buffer_safely (Lisp_Object); extern Lisp_Object get_truename_buffer (Lisp_Object); extern void init_buffer_once (void); -extern void init_buffer (void); +extern void init_buffer (int); extern void syms_of_buffer (void); extern void keys_of_buffer (void); @@ -4022,7 +4034,6 @@ extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int); -EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ extern void close_file_unwind (int); extern void fclose_unwind (void *); extern void restore_point_unwind (Lisp_Object); @@ -4031,7 +4042,7 @@ extern _Noreturn void report_file_error (const char *, Lisp_Object); extern bool internal_delete_file (Lisp_Object); extern Lisp_Object emacs_readlinkat (int, const char *); extern bool file_directory_p (const char *); -extern bool file_accessible_directory_p (const char *); +extern bool file_accessible_directory_p (Lisp_Object); extern void init_fileio (void); extern void syms_of_fileio (void); extern Lisp_Object make_temp_name (Lisp_Object, bool); @@ -4055,6 +4066,7 @@ extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool); extern ptrdiff_t scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool); +extern ptrdiff_t scan_newline_from_point (ptrdiff_t, ptrdiff_t *, ptrdiff_t *); extern ptrdiff_t find_newline_no_quit (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t *); extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, @@ -4074,6 +4086,7 @@ extern void syms_of_minibuf (void); /* Defined in callint.c. */ extern Lisp_Object Qminus, Qplus; +extern Lisp_Object Qprogn; extern Lisp_Object Qwhen; extern Lisp_Object Qmouse_leave_buffer_hook; extern void syms_of_callint (void); @@ -4095,10 +4108,12 @@ extern Lisp_Object echo_message_buffer; extern struct kboard *echo_kboard; extern void cancel_echoing (void); extern Lisp_Object Qdisabled, QCfilter; -extern Lisp_Object Qup, Qdown, Qbottom; -extern Lisp_Object Qtop; +extern Lisp_Object Qup, Qdown; extern Lisp_Object last_undo_boundary; extern bool input_pending; +#ifdef HAVE_STACK_OVERFLOW_HANDLING +extern sigjmp_buf return_to_command_loop; +#endif extern Lisp_Object menu_bar_items (Lisp_Object); extern Lisp_Object tool_bar_items (Lisp_Object, int *); extern void discard_mouse_events (void); @@ -4128,14 +4143,10 @@ extern void syms_of_indent (void); /* Defined in frame.c. */ extern Lisp_Object Qonly, Qnone; -extern Lisp_Object Qvisible; -extern void set_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object); extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object); -#if HAVE_NS || HAVE_NTGUI extern Lisp_Object get_frame_param (struct frame *, Lisp_Object); -#endif extern void frames_discard_buffer (Lisp_Object); extern void syms_of_frame (void); @@ -4186,10 +4197,8 @@ extern bool running_asynch_code; /* Defined in process.c. */ extern Lisp_Object QCtype, Qlocal; extern void kill_buffer_processes (Lisp_Object); -extern bool wait_reading_process_output (intmax_t, int, int, bool, - Lisp_Object, - struct Lisp_Process *, - int); +extern int wait_reading_process_output (intmax_t, int, int, bool, Lisp_Object, + struct Lisp_Process *, int); /* Max value for the first argument of wait_reading_process_output. */ #if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) /* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3. @@ -4198,6 +4207,9 @@ extern bool wait_reading_process_output (intmax_t, int, int, bool, #else # define WAIT_READING_MAX INTMAX_MAX #endif +#ifdef HAVE_TIMERFD +extern void add_timer_wait_descriptor (int); +#endif extern void add_keyboard_wait_descriptor (int); extern void delete_keyboard_wait_descriptor (int); #ifdef HAVE_GPM @@ -4252,9 +4264,8 @@ extern void record_property_change (ptrdiff_t, ptrdiff_t, Lisp_Object); extern void syms_of_undo (void); /* Defined in textprop.c. */ -extern Lisp_Object Qfont, Qmouse_face; +extern Lisp_Object Qmouse_face; extern Lisp_Object Qinsert_in_front_hooks, Qinsert_behind_hooks; -extern Lisp_Object Qfront_sticky, Qrear_nonsticky; extern Lisp_Object Qminibuffer_prompt; extern void report_interval_modification (Lisp_Object, Lisp_Object); @@ -4277,12 +4288,9 @@ extern char *get_current_dir_name (void); #endif extern void stuff_char (char c); extern void init_foreground_group (void); -extern void init_sigio (int); extern void sys_subshell (void); extern void sys_suspend (void); extern void discard_tty_input (void); -extern void block_tty_out_signal (void); -extern void unblock_tty_out_signal (void); extern void init_sys_modes (struct tty_display_info *); extern void reset_sys_modes (struct tty_display_info *); extern void init_all_sys_modes (void); @@ -4308,6 +4316,7 @@ extern void lock_file (Lisp_Object); extern void unlock_file (Lisp_Object); extern void unlock_buffer (struct buffer *); extern void syms_of_filelock (void); +extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); /* Defined in sound.c. */ extern void syms_of_sound (void); @@ -4364,8 +4373,8 @@ extern void syms_of_w32notify (void); #endif /* Defined in xfaces.c. */ -extern Lisp_Object Qdefault, Qtool_bar, Qfringe; -extern Lisp_Object Qheader_line, Qscroll_bar, Qcursor; +extern Lisp_Object Qdefault, Qfringe; +extern Lisp_Object Qscroll_bar, Qcursor; extern Lisp_Object Qmode_line_inactive; extern Lisp_Object Qface; extern Lisp_Object Qnormal; @@ -4389,6 +4398,7 @@ extern void syms_of_xsmfns (void); extern void syms_of_xselect (void); /* Defined in xterm.c. */ +extern void init_xterm (void); extern void syms_of_xterm (void); #endif /* HAVE_X_WINDOWS */ @@ -4410,6 +4420,7 @@ extern void syms_of_decompress (void); #ifdef HAVE_DBUS /* Defined in dbusbind.c. */ +void init_dbusbind (void); void syms_of_dbusbind (void); #endif @@ -4424,34 +4435,49 @@ extern void syms_of_profiler (void); /* Defined in msdos.c, w32.c. */ extern char *emacs_root_dir (void); #endif /* DOS_NT */ - -/* True means Emacs has already been initialized. - Used during startup to detect startup of dumped Emacs. */ -extern bool initialized; + +/* Defined in lastfile.c. */ +extern char my_edata[]; +extern char my_endbss[]; +extern char *my_endbss_static; /* True means ^G can quit instantly. */ extern bool immediate_quit; -extern void *xmalloc (size_t); -extern void *xzalloc (size_t); -extern void *xrealloc (void *, size_t); +extern void *xmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); +extern void *xzalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); +extern void *xrealloc (void *, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void xfree (void *); -extern void *xnmalloc (ptrdiff_t, ptrdiff_t); -extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t); +extern void *xnmalloc (ptrdiff_t, ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1,2)); +extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t) + ATTRIBUTE_ALLOC_SIZE ((2,3)); extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t); -extern char *xstrdup (const char *); -extern char *xlispstrdup (Lisp_Object); +extern char *xstrdup (const char *) ATTRIBUTE_MALLOC; +extern char *xlispstrdup (Lisp_Object) ATTRIBUTE_MALLOC; extern void dupstring (char **, char const *); -extern void xputenv (const char *); -extern char *egetenv (const char *); +/* Make DEST a copy of STRING's data. Return a pointer to DEST's terminating + null byte. This is like stpcpy, except the source is a Lisp string. */ -/* Copy Lisp string to temporary (allocated on stack) C string. */ +INLINE char * +lispstpcpy (char *dest, Lisp_Object string) +{ + ptrdiff_t len = SBYTES (string); + memcpy (dest, SDATA (string), len + 1); + return dest + len; +} + +extern void xputenv (const char *); -#define xlispstrdupa(string) \ - memcpy (alloca (SBYTES (string) + 1), \ - SSDATA (string), SBYTES (string) + 1) +extern char *egetenv_internal (const char *, ptrdiff_t); + +INLINE char * +egetenv (const char *var) +{ + /* When VAR is a string literal, strlen can be optimized away. */ + return egetenv_internal (var, strlen (var)); +} /* Set up the name of the machine we're running on. */ extern void init_system_name (void); @@ -4473,15 +4499,18 @@ extern void init_system_name (void); enum MAX_ALLOCA { MAX_ALLOCA = 16 * 1024 }; -extern void *record_xmalloc (size_t); +extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1)); #define USE_SAFE_ALLOCA \ + ptrdiff_t sa_avail = MAX_ALLOCA; \ ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = false +#define AVAIL_ALLOCA(size) (sa_avail -= (size), alloca (size)) + /* SAFE_ALLOCA allocates a simple buffer. */ -#define SAFE_ALLOCA(size) ((size) < MAX_ALLOCA \ - ? alloca (size) \ +#define SAFE_ALLOCA(size) ((size) <= sa_avail \ + ? AVAIL_ALLOCA (size) \ : (sa_must_free = true, record_xmalloc (size))) /* SAFE_NALLOCA sets BUF to a newly allocated array of MULTIPLIER * @@ -4490,8 +4519,8 @@ extern void *record_xmalloc (size_t); #define SAFE_NALLOCA(buf, multiplier, nitems) \ do { \ - if ((nitems) <= MAX_ALLOCA / sizeof *(buf) / (multiplier)) \ - (buf) = alloca (sizeof *(buf) * (multiplier) * (nitems)); \ + if ((nitems) <= sa_avail / sizeof *(buf) / (multiplier)) \ + (buf) = AVAIL_ALLOCA (sizeof *(buf) * (multiplier) * (nitems)); \ else \ { \ (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \ @@ -4500,6 +4529,14 @@ extern void *record_xmalloc (size_t); } \ } while (false) +/* SAFE_ALLOCA_STRING allocates a C copy of a Lisp string. */ + +#define SAFE_ALLOCA_STRING(ptr, string) \ + do { \ + (ptr) = SAFE_ALLOCA (SBYTES (string) + 1); \ + memcpy (ptr, SDATA (string), SBYTES (string) + 1); \ + } while (false) + /* SAFE_FREE frees xmalloced memory and enables GC as needed. */ #define SAFE_FREE() \ @@ -4511,13 +4548,29 @@ extern void *record_xmalloc (size_t); } while (false) +/* Return floor (NBYTES / WORD_SIZE). */ + +INLINE ptrdiff_t +lisp_word_count (ptrdiff_t nbytes) +{ + if (-1 >> 1 == -1) + switch (word_size) + { + case 2: return nbytes >> 1; + case 4: return nbytes >> 2; + case 8: return nbytes >> 3; + case 16: return nbytes >> 4; + } + return nbytes / word_size - (nbytes % word_size < 0); +} + /* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects. */ #define SAFE_ALLOCA_LISP(buf, nelt) \ do { \ - if ((nelt) < MAX_ALLOCA / word_size) \ - (buf) = alloca ((nelt) * word_size); \ - else if ((nelt) < min (PTRDIFF_MAX, SIZE_MAX) / word_size) \ + if ((nelt) <= lisp_word_count (sa_avail)) \ + (buf) = AVAIL_ALLOCA ((nelt) * word_size); \ + else if ((nelt) <= min (PTRDIFF_MAX, SIZE_MAX) / word_size) \ { \ Lisp_Object arg_; \ (buf) = xmalloc ((nelt) * word_size); \ @@ -4529,6 +4582,107 @@ extern void *record_xmalloc (size_t); memory_full (SIZE_MAX); \ } while (false) + +/* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate + block-scoped conses and strings. These objects are not + managed by the garbage collector, so they are dangerous: passing them + out of their scope (e.g., to user code) results in undefined behavior. + Conversely, they have better performance because GC is not involved. + + This feature is experimental and requires careful debugging. + Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it. */ + +#ifndef USE_STACK_LISP_OBJECTS +# define USE_STACK_LISP_OBJECTS true +#endif + +/* USE_STACK_LISP_OBJECTS requires GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS. */ + +#if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS +# undef USE_STACK_LISP_OBJECTS +# define USE_STACK_LISP_OBJECTS false +#endif + +/* Struct inside unions that are typically no larger and aligned enough. */ + +union Aligned_Cons +{ + struct Lisp_Cons s; + double d; intmax_t i; void *p; +}; + +union Aligned_String +{ + struct Lisp_String s; + double d; intmax_t i; void *p; +}; + +/* True for stack-based cons and string implementations, respectively. + Use stack-based strings only if stack-based cons also works. + Otherwise, STACK_CONS would create heap-based cons cells that + could point to stack-based strings, which is a no-no. */ + +enum + { + USE_STACK_CONS = (USE_STACK_LISP_OBJECTS + && alignof (union Aligned_Cons) % GCALIGNMENT == 0), + USE_STACK_STRING = (USE_STACK_CONS + && alignof (union Aligned_String) % GCALIGNMENT == 0) + }; + +/* Auxiliary macros used for auto allocation of Lisp objects. Please + use these only in macros like AUTO_CONS that declare a local + variable whose lifetime will be clear to the programmer. */ +#define STACK_CONS(a, b) \ + make_lisp_ptr (&(union Aligned_Cons) { { a, { b } } }.s, Lisp_Cons) +#define AUTO_CONS_EXPR(a, b) \ + (USE_STACK_CONS ? STACK_CONS (a, b) : Fcons (a, b)) + +/* Declare NAME as an auto Lisp cons or short list if possible, a + GC-based one otherwise. This is in the sense of the C keyword + 'auto'; i.e., the object has the lifetime of the containing block. + The resulting object should not be made visible to user Lisp code. */ + +#define AUTO_CONS(name, a, b) Lisp_Object name = AUTO_CONS_EXPR (a, b) +#define AUTO_LIST1(name, a) \ + Lisp_Object name = (USE_STACK_CONS ? STACK_CONS (a, Qnil) : list1 (a)) +#define AUTO_LIST2(name, a, b) \ + Lisp_Object name = (USE_STACK_CONS \ + ? STACK_CONS (a, STACK_CONS (b, Qnil)) \ + : list2 (a, b)) +#define AUTO_LIST3(name, a, b, c) \ + Lisp_Object name = (USE_STACK_CONS \ + ? STACK_CONS (a, STACK_CONS (b, STACK_CONS (c, Qnil))) \ + : list3 (a, b, c)) +#define AUTO_LIST4(name, a, b, c, d) \ + Lisp_Object name \ + = (USE_STACK_CONS \ + ? STACK_CONS (a, STACK_CONS (b, STACK_CONS (c, \ + STACK_CONS (d, Qnil)))) \ + : list4 (a, b, c, d)) + +/* Check whether stack-allocated strings are ASCII-only. */ + +#if defined (ENABLE_CHECKING) && USE_STACK_LISP_OBJECTS +extern const char *verify_ascii (const char *); +#else +# define verify_ascii(str) (str) +#endif + +/* Declare NAME as an auto Lisp string if possible, a GC-based one if not. + Take its value from STR. STR is not necessarily copied and should + contain only ASCII characters. The resulting Lisp string should + not be modified or made visible to user code. */ + +#define AUTO_STRING(name, str) \ + Lisp_Object name = \ + (USE_STACK_STRING \ + ? (make_lisp_ptr \ + ((&(union Aligned_String) \ + {{strlen (str), -1, 0, (unsigned char *) verify_ascii (str)}}.s), \ + Lisp_String)) \ + : build_string (verify_ascii (str))) + /* Loop over all tails of a list, checking for cycles. FIXME: Make tortoise and n internal declarations. FIXME: Unroll the loop body so we don't need `n'. */ diff --git a/src/lisp.mk b/src/lisp.mk index 59d5b86c33a..675df2b66e6 100644 --- a/src/lisp.mk +++ b/src/lisp.mk @@ -132,6 +132,7 @@ lisp = \ $(lispsource)/textmodes/paragraphs.elc \ $(lispsource)/progmodes/prog-mode.elc \ $(lispsource)/emacs-lisp/lisp-mode.elc \ + $(lispsource)/progmodes/elisp-mode.elc \ $(lispsource)/textmodes/text-mode.elc \ $(lispsource)/textmodes/fill.elc \ $(lispsource)/newcomment.elc \ @@ -152,7 +153,6 @@ lisp = \ $(lispsource)/term/w32-win.elc \ $(lispsource)/ls-lisp.elc \ $(lispsource)/disp-table.elc \ - $(lispsource)/w32-common-fns.elc \ $(lispsource)/dos-w32.elc \ $(lispsource)/w32-fns.elc \ $(lispsource)/dos-fns.elc \ @@ -165,6 +165,7 @@ lisp = \ $(lispsource)/vc/vc-hooks.elc \ $(lispsource)/vc/ediff-hook.elc \ $(lispsource)/electric.elc \ + $(lispsource)/emacs-lisp/eldoc.elc \ $(lispsource)/uniquify.elc \ $(lispsource)/tooltip.elc diff --git a/src/lread.c b/src/lread.c index 4990d25eda1..171a51acb3f 100644 --- a/src/lread.c +++ b/src/lread.c @@ -213,7 +213,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) else { c = BUF_FETCH_BYTE (inbuffer, pt_byte); - if (! ASCII_BYTE_P (c)) + if (! ASCII_CHAR_P (c)) c = BYTE8_TO_CHAR (c); pt_byte++; } @@ -242,7 +242,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) else { c = BUF_FETCH_BYTE (inbuffer, bytepos); - if (! ASCII_BYTE_P (c)) + if (! ASCII_CHAR_P (c)) c = BYTE8_TO_CHAR (c); bytepos++; } @@ -324,7 +324,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) return c; if (multibyte) *multibyte = 1; - if (ASCII_BYTE_P (c)) + if (ASCII_CHAR_P (c)) return c; if (emacs_mule_encoding) return read_emacs_mule_char (c, readbyte, readcharfun); @@ -970,10 +970,8 @@ load_warn_old_style_backquotes (Lisp_Object file) { if (!NILP (Vold_style_backquotes)) { - Lisp_Object args[2]; - args[0] = build_string ("Loading `%s': old-style backquotes detected!"); - args[1] = file; - Fmessage (2, args); + AUTO_STRING (format, "Loading `%s': old-style backquotes detected!"); + Fmessage (2, (Lisp_Object []) {format, file}); } } @@ -1473,6 +1471,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, ptrdiff_t max_suffix_len = 0; int last_errno = ENOENT; int save_fd = -1; + USE_SAFE_ALLOCA; /* The last-modified time of the newest matching file found. Initialize it to something less than all valid timestamps. */ @@ -1513,7 +1512,10 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, this path element/specified file name and any possible suffix. */ want_length = max_suffix_len + SBYTES (filename); if (fn_size <= want_length) - fn = alloca (fn_size = 100 + want_length); + { + fn_size = 100 + want_length; + fn = SAFE_ALLOCA (fn_size); + } /* Loop over suffixes. */ for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes; @@ -1579,6 +1581,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, /* We succeeded; return this descriptor and filename. */ if (storeptr) *storeptr = string; + SAFE_FREE (); UNGCPRO; return -2; } @@ -1651,6 +1654,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, /* We succeeded; return this descriptor and filename. */ if (storeptr) *storeptr = string; + SAFE_FREE (); UNGCPRO; return fd; } @@ -1661,6 +1665,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, { if (storeptr) *storeptr = save_string; + SAFE_FREE (); UNGCPRO; return save_fd; } @@ -1670,6 +1675,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, break; } + SAFE_FREE (); UNGCPRO; errno = last_errno; return -1; @@ -1763,6 +1769,31 @@ end_of_file_error (void) xsignal0 (Qend_of_file); } +static Lisp_Object +readevalloop_eager_expand_eval (Lisp_Object val, Lisp_Object macroexpand) +{ + /* If we macroexpand the toplevel form non-recursively and it ends + up being a `progn' (or if it was a progn to start), treat each + form in the progn as a top-level form. This way, if one form in + the progn defines a macro, that macro is in effect when we expand + the remaining forms. See similar code in bytecomp.el. */ + val = call2 (macroexpand, val, Qnil); + if (EQ (CAR_SAFE (val), Qprogn)) + { + struct gcpro gcpro1; + Lisp_Object subforms = XCDR (val); + + GCPRO1 (subforms); + for (val = Qnil; CONSP (subforms); subforms = XCDR (subforms)) + val = readevalloop_eager_expand_eval (XCAR (subforms), + macroexpand); + UNGCPRO; + } + else + val = eval_sub (call2 (macroexpand, val, Qt)); + return val; +} + /* UNIBYTE specifies how to set load_convert_to_unibyte for this invocation. READFUN, if non-nil, is used instead of `read'. @@ -1930,8 +1961,9 @@ readevalloop (Lisp_Object readcharfun, /* Now eval what we just read. */ if (!NILP (macroexpand)) - val = call1 (macroexpand, val); - val = eval_sub (val); + val = readevalloop_eager_expand_eval (val, macroexpand); + else + val = eval_sub (val); if (printflag) { @@ -2064,9 +2096,10 @@ DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0, doc: /* Read one Lisp expression which is represented as text by STRING. Returns a cons: (OBJECT-READ . FINAL-STRING-INDEX). FINAL-STRING-INDEX is an integer giving the position of the next - remaining character in STRING. -START and END optionally delimit a substring of STRING from which to read; - they default to 0 and (length STRING) respectively. */) +remaining character in STRING. START and END optionally delimit +a substring of STRING from which to read; they default to 0 and +(length STRING) respectively. Negative values are counted from +the end of STRING. */) (Lisp_Object string, Lisp_Object start, Lisp_Object end) { Lisp_Object ret; @@ -2077,10 +2110,9 @@ START and END optionally delimit a substring of STRING from which to read; } /* Function to set up the global context we need in toplevel read - calls. */ + calls. START and END only used when STREAM is a string. */ static Lisp_Object read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end) -/* `start', `end' only used when stream is a string. */ { Lisp_Object retval; @@ -2102,25 +2134,9 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end) else string = XCAR (stream); - if (NILP (end)) - endval = SCHARS (string); - else - { - CHECK_NUMBER (end); - if (! (0 <= XINT (end) && XINT (end) <= SCHARS (string))) - args_out_of_range (string, end); - endval = XINT (end); - } + validate_subarray (string, start, end, SCHARS (string), + &startval, &endval); - if (NILP (start)) - startval = 0; - else - { - CHECK_NUMBER (start); - if (! (0 <= XINT (start) && XINT (start) <= endval)) - args_out_of_range (string, start); - startval = XINT (start); - } read_from_string_index = startval; read_from_string_index_byte = string_char_to_byte (string, startval); read_from_string_limit = endval; @@ -2595,21 +2611,38 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) c = READCHAR; if (c == '[') { - Lisp_Object tmp; - int depth; - ptrdiff_t size; + /* Sub char-table can't be read as a regular + vector because of a two C integer fields. */ + Lisp_Object tbl, tmp = read_list (1, readcharfun); + ptrdiff_t size = XINT (Flength (tmp)); + int i, depth, min_char; + struct Lisp_Cons *cell; - tmp = read_vector (readcharfun, 0); - size = ASIZE (tmp); if (size == 0) - error ("Invalid size char-table"); - if (! RANGED_INTEGERP (1, AREF (tmp, 0), 3)) - error ("Invalid depth in char-table"); - depth = XINT (AREF (tmp, 0)); + error ("Zero-sized sub char-table"); + + if (! RANGED_INTEGERP (1, XCAR (tmp), 3)) + error ("Invalid depth in sub char-table"); + depth = XINT (XCAR (tmp)); if (chartab_size[depth] != size - 2) - error ("Invalid size char-table"); - XSETPVECTYPE (XVECTOR (tmp), PVEC_SUB_CHAR_TABLE); - return tmp; + error ("Invalid size in sub char-table"); + cell = XCONS (tmp), tmp = XCDR (tmp), size--; + free_cons (cell); + + if (! RANGED_INTEGERP (0, XCAR (tmp), MAX_CHAR)) + error ("Invalid minimum character in sub-char-table"); + min_char = XINT (XCAR (tmp)); + cell = XCONS (tmp), tmp = XCDR (tmp), size--; + free_cons (cell); + + tbl = make_uninit_sub_char_table (depth, min_char); + for (i = 0; i < size; i++) + { + XSUB_CHAR_TABLE (tbl)->contents[i] = XCAR (tmp); + cell = XCONS (tmp), tmp = XCDR (tmp); + free_cons (cell); + } + return tbl; } invalid_syntax ("#^^"); } @@ -2840,11 +2873,8 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) if (c == '=') { /* Make a placeholder for #n# to use temporarily. */ - Lisp_Object placeholder; - Lisp_Object cell; - - placeholder = Fcons (Qnil, Qnil); - cell = Fcons (make_number (n), placeholder); + AUTO_CONS (placeholder, Qnil, Qnil); + Lisp_Object cell = Fcons (make_number (n), placeholder); read_objects = Fcons (cell, read_objects); /* Read the object itself. */ @@ -3323,7 +3353,7 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj substitute_in_interval contains part of the logic. */ INTERVAL root_interval = string_intervals (subtree); - Lisp_Object arg = Fcons (object, placeholder); + AUTO_CONS (arg, object, placeholder); traverse_intervals_noorder (root_interval, &substitute_in_interval, arg); @@ -3630,8 +3660,10 @@ read_list (bool flag, Lisp_Object readcharfun) in the installed Lisp directory. We don't use Fexpand_file_name because that would make the directory absolute now. */ - elt = concat2 (build_string ("../lisp/"), - Ffile_name_nondirectory (elt)); + { + AUTO_STRING (dot_dot_lisp, "../lisp/"); + elt = concat2 (dot_dot_lisp, Ffile_name_nondirectory (elt)); + } } else if (EQ (elt, Vload_file_name) && ! NILP (elt) @@ -3759,6 +3791,30 @@ check_obarray (Lisp_Object obarray) return obarray; } +/* Intern a symbol with name STRING in OBARRAY using bucket INDEX. */ + +Lisp_Object +intern_driver (Lisp_Object string, Lisp_Object obarray, ptrdiff_t index) +{ + Lisp_Object *ptr, sym = Fmake_symbol (string); + + XSYMBOL (sym)->interned = (EQ (obarray, initial_obarray) + ? SYMBOL_INTERNED_IN_INITIAL_OBARRAY + : SYMBOL_INTERNED); + + if ((SREF (string, 0) == ':') && EQ (obarray, initial_obarray)) + { + XSYMBOL (sym)->constant = 1; + XSYMBOL (sym)->redirect = SYMBOL_PLAINVAL; + SET_SYMBOL_VAL (XSYMBOL (sym), sym); + } + + ptr = aref_addr (obarray, index); + set_symbol_next (sym, SYMBOLP (*ptr) ? XSYMBOL (*ptr) : NULL); + *ptr = sym; + return sym; +} + /* Intern the C string STR: return a symbol with that name, interned in the current obarray. */ @@ -3768,7 +3824,8 @@ intern_1 (const char *str, ptrdiff_t len) Lisp_Object obarray = check_obarray (Vobarray); Lisp_Object tem = oblookup (obarray, str, len, len); - return SYMBOLP (tem) ? tem : Fintern (make_string (str, len), obarray); + return SYMBOLP (tem) ? tem : intern_driver (make_string (str, len), + obarray, XINT (tem)); } Lisp_Object @@ -3777,16 +3834,14 @@ intern_c_string_1 (const char *str, ptrdiff_t len) Lisp_Object obarray = check_obarray (Vobarray); Lisp_Object tem = oblookup (obarray, str, len, len); - if (SYMBOLP (tem)) - return tem; - - if (NILP (Vpurify_flag)) - /* Creating a non-pure string from a string literal not - implemented yet. We could just use make_string here and live - with the extra copy. */ - emacs_abort (); - - return Fintern (make_pure_c_string (str, len), obarray); + if (!SYMBOLP (tem)) + { + /* Creating a non-pure string from a string literal not implemented yet. + We could just use make_string here and live with the extra copy. */ + eassert (!NILP (Vpurify_flag)); + tem = intern_driver (make_pure_c_string (str, len), obarray, XINT (tem)); + } + return tem; } DEFUN ("intern", Fintern, Sintern, 1, 2, 0, @@ -3796,43 +3851,16 @@ A second optional argument specifies the obarray to use; it defaults to the value of `obarray'. */) (Lisp_Object string, Lisp_Object obarray) { - register Lisp_Object tem, sym, *ptr; - - if (NILP (obarray)) obarray = Vobarray; - obarray = check_obarray (obarray); + Lisp_Object tem; + obarray = check_obarray (NILP (obarray) ? Vobarray : obarray); CHECK_STRING (string); - tem = oblookup (obarray, SSDATA (string), - SCHARS (string), - SBYTES (string)); - if (!INTEGERP (tem)) - return tem; - - if (!NILP (Vpurify_flag)) - string = Fpurecopy (string); - sym = Fmake_symbol (string); - - if (EQ (obarray, initial_obarray)) - XSYMBOL (sym)->interned = SYMBOL_INTERNED_IN_INITIAL_OBARRAY; - else - XSYMBOL (sym)->interned = SYMBOL_INTERNED; - - if ((SREF (string, 0) == ':') - && EQ (obarray, initial_obarray)) - { - XSYMBOL (sym)->constant = 1; - XSYMBOL (sym)->redirect = SYMBOL_PLAINVAL; - SET_SYMBOL_VAL (XSYMBOL (sym), sym); - } - - ptr = aref_addr (obarray, XINT(tem)); - if (SYMBOLP (*ptr)) - set_symbol_next (sym, XSYMBOL (*ptr)); - else - set_symbol_next (sym, NULL); - *ptr = sym; - return sym; + tem = oblookup (obarray, SSDATA (string), SCHARS (string), SBYTES (string)); + if (!SYMBOLP (tem)) + tem = intern_driver (NILP (Vpurify_flag) ? string + : Fpurecopy (string), obarray, XINT (tem)); + return tem; } DEFUN ("intern-soft", Fintern_soft, Sintern_soft, 1, 2, 0, @@ -4172,7 +4200,7 @@ load_path_check (Lisp_Object lpath) if (STRINGP (dirfile)) { dirfile = Fdirectory_file_name (dirfile); - if (! file_accessible_directory_p (SSDATA (dirfile))) + if (! file_accessible_directory_p (dirfile)) dir_warning ("Lisp directory", XCAR (path_tail)); } } diff --git a/src/macfont.h b/src/macfont.h index 7421cd63a79..e6e45ab152c 100644 --- a/src/macfont.h +++ b/src/macfont.h @@ -57,11 +57,7 @@ typedef CTCharacterCollection CharacterCollection; #define MAC_FONT_CASCADE_LIST_ATTRIBUTE kCTFontCascadeListAttribute #define MAC_FONT_CHARACTER_SET_ATTRIBUTE kCTFontCharacterSetAttribute #define MAC_FONT_LANGUAGES_ATTRIBUTE kCTFontLanguagesAttribute -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 #define MAC_FONT_FORMAT_ATTRIBUTE kCTFontFormatAttribute -#else -#define MAC_FONT_FORMAT_ATTRIBUTE (CFSTR ("NSCTFontFormatAttribute")) -#endif #define MAC_FONT_SYMBOLIC_TRAIT kCTFontSymbolicTrait #define MAC_FONT_WEIGHT_TRAIT kCTFontWeightTrait #define MAC_FONT_WIDTH_TRAIT kCTFontWidthTrait @@ -79,11 +75,7 @@ enum { }; enum { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 MAC_FONT_FORMAT_BITMAP = kCTFontFormatBitmap -#else - MAC_FONT_FORMAT_BITMAP = 5 -#endif }; enum { @@ -112,13 +104,8 @@ enum { #define mac_font_get_underline_position CTFontGetUnderlinePosition #define mac_font_get_underline_thickness CTFontGetUnderlineThickness #define mac_font_copy_graphics_font(font) CTFontCopyGraphicsFont (font, NULL) -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 #define mac_font_copy_non_synthetic_table(font, table) \ CTFontCopyTable (font, table, kCTFontTableOptionNoOptions) -#else -#define mac_font_copy_non_synthetic_table(font, table) \ - CTFontCopyTable (font, table, kCTFontTableOptionExcludeSynthetic) -#endif #define mac_font_create_preferred_family_for_attributes \ mac_ctfont_create_preferred_family_for_attributes diff --git a/src/macfont.m b/src/macfont.m index 69bde9f66a7..366d087f8c2 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -36,13 +36,11 @@ Original author: YAMAMOTO Mitsuharu #include "macfont.h" #include "macuvs.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 - #include <libkern/OSByteOrder.h> static struct font_driver macfont_driver; -/* Core Text, for Mac OS X 10.5 and later. */ +/* Core Text, for Mac OS X. */ static Lisp_Object Qmac_ct; static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph); @@ -50,25 +48,25 @@ static CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef, CGGlyph); static CFArrayRef mac_ctfont_create_available_families (void); static Boolean mac_ctfont_equal_in_postscript_name (CTFontRef, CTFontRef); static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef, - CTFontRef); + CTFontRef); static CFComparisonResult mac_font_family_compare (const void *, - const void *, void *); + const void *, void *); static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef, - CFArrayRef); + CFArrayRef); static CFStringRef mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef); static CFIndex mac_ctfont_shape (CTFontRef, CFStringRef, - struct mac_glyph_layout *, CFIndex); + struct mac_glyph_layout *, CFIndex); static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef language); static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset, - CFArrayRef languages); + CFArrayRef languages); #if USE_CT_GLYPH_INFO static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, - CTCharacterCollection, - CGFontIndex); + CTCharacterCollection, + CGFontIndex); #endif /* The font property key specifying the font design destination. The @@ -129,26 +127,26 @@ static const CGAffineTransform synthetic_italic_atfm = {1, 0, 0.25, 1, 0, 0}; static const CGFloat synthetic_bold_factor = 0.024; static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef, - FontSymbolicTraits *); + FontSymbolicTraits *); static void macfont_store_descriptor_attributes (FontDescriptorRef, - Lisp_Object); + Lisp_Object); static Lisp_Object macfont_descriptor_entity (FontDescriptorRef, - Lisp_Object, - FontSymbolicTraits); + Lisp_Object, + FontSymbolicTraits); static CFStringRef macfont_create_family_with_symbol (Lisp_Object); static int macfont_glyph_extents (struct font *, CGGlyph, - struct font_metrics *, CGFloat *, int); + struct font_metrics *, CGFloat *, int); static CFMutableDictionaryRef macfont_create_attributes_with_spec (Lisp_Object); static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef, - CFCharacterSetRef, - Lisp_Object, - CFArrayRef); -static CFIndex macfont_closest_traits_index (CFArrayRef, - FontSymbolicTraits); + CFCharacterSetRef, + Lisp_Object, + CFArrayRef); +static Boolean macfont_closest_traits_index_p (CFArrayRef, FontSymbolicTraits, + CFIndex); static CFDataRef mac_font_copy_uvs_table (FontRef); static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, - const UTF32Char [], - CGGlyph [], CFIndex); + const UTF32Char [], + CGGlyph [], CFIndex); /* From CFData to a lisp string. Always returns a unibyte string. */ @@ -180,15 +178,15 @@ cfstring_to_lisp_nodecode (CFStringRef string) CFIndex i, length = CFStringGetLength (string); for (i = 0; i < length; i++) - if (CFStringGetCharacterAtIndex (string, i) == 0) - break; + if (CFStringGetCharacterAtIndex (string, i) == 0) + break; if (i == length) - return make_unibyte_string (s, strlen (s)); + return make_unibyte_string (s, strlen (s)); } data = CFStringCreateExternalRepresentation (NULL, string, - kCFStringEncodingUTF8, '?'); + kCFStringEncodingUTF8, '?'); if (data) { result = cfdata_to_lisp (data); @@ -206,12 +204,12 @@ static CFStringRef cfstring_create_with_string_noencode (Lisp_Object s) { CFStringRef string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s), - kCFStringEncodingUTF8, false); + kCFStringEncodingUTF8, false); if (string == NULL) /* Failed to interpret as UTF 8. Fall back on Mac Roman. */ string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s), - kCFStringEncodingMacRoman, false); + kCFStringEncodingMacRoman, false); return string; } @@ -226,7 +224,7 @@ mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph) static CGGlyph mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection, - CGFontIndex cid) + CGFontIndex cid) { #if USE_CT_GLYPH_INFO return mac_ctfont_get_glyph_for_cid ((CTFontRef) font, collection, cid); @@ -237,18 +235,17 @@ mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection, unichar characters[] = {0xfffd}; NSString *string = [NSString stringWithCharacters:characters - length:(sizeof (characters) - / sizeof (characters[0]))]; + length:ARRAYELTS (characters)]; NSGlyphInfo *glyphInfo = [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid - collection:collection - baseString:string]; + collection:collection + baseString:string]; NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:nsFont,NSFontAttributeName, - glyphInfo,NSGlyphInfoAttributeName,nil]; + glyphInfo,NSGlyphInfoAttributeName,nil]; NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:string - attributes:attributes]; + attributes:attributes]; NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; NSTextContainer *textContainer = [[NSTextContainer alloc] init]; NSFont *fontInTextStorage; @@ -262,14 +259,14 @@ mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection, (void) [layoutManager glyphRangeForTextContainer:textContainer]; fontInTextStorage = [textStorage attribute:NSFontAttributeName atIndex:0 - effectiveRange:NULL]; + effectiveRange:NULL]; if (fontInTextStorage == nsFont - || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]]) + || [[fontInTextStorage fontName] isEqualToString:[nsFont fontName]]) { - NSGlyph glyph = [layoutManager glyphAtIndex:0]; + NSGlyph glyph = [layoutManager glyphAtIndex:0]; - if (glyph < [nsFont numberOfGlyphs]) - result = glyph; + if (glyph < [nsFont numberOfGlyphs]) + result = glyph; } [textStorage release]; @@ -293,7 +290,7 @@ mac_screen_font_create_with_name (CFStringRef name, CGFloat size) static Boolean mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent, - CGFloat *descent, CGFloat *leading) + CGFloat *descent, CGFloat *leading) { NSFont *nsFont = [(NSFont *)font printerFont]; NSTextStorage *textStorage; @@ -324,7 +321,7 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent, } usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:0 - effectiveRange:NULL]; + effectiveRange:NULL]; spaceLocation = [layoutManager locationForGlyphAtIndex:0]; [textStorage release]; @@ -343,8 +340,8 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent, static CFIndex mac_font_shape_1 (NSFont *font, NSString *string, - struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len, - BOOL screen_font_p) + struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len, + BOOL screen_font_p) { NSUInteger i; CFIndex result = 0; @@ -361,7 +358,7 @@ mac_font_shape_1 (NSFont *font, NSString *string, /* Append a trailing space to measure baseline position. */ [textStorage appendAttributedString:([[[NSAttributedString alloc] - initWithString:@" "] autorelease])]; + initWithString:@" "] autorelease])]; [textStorage setFont:font]; [textContainer setLineFragmentPadding:0]; [layoutManager setUsesScreenFonts:screen_font_p]; @@ -397,13 +394,13 @@ mac_font_shape_1 (NSFont *font, NSString *string, { NSRange range; NSFont *fontInTextStorage = - [textStorage attribute:NSFontAttributeName atIndex:i - longestEffectiveRange:&range - inRange:(NSMakeRange (0, stringLength))]; + [textStorage attribute:NSFontAttributeName atIndex:i + longestEffectiveRange:&range + inRange:(NSMakeRange (0, stringLength))]; if (!(fontInTextStorage == font - || [[fontInTextStorage fontName] isEqualToString:[font fontName]])) - break; + || [[fontInTextStorage fontName] isEqualToString:[font fontName]])) + break; i = NSMaxRange (range); } if (i < stringLength) @@ -415,12 +412,12 @@ mac_font_shape_1 (NSFont *font, NSString *string, NSRange range = NSMakeRange (0, stringLength); range = [layoutManager glyphRangeForCharacterRange:range - actualCharacterRange:NULL]; + actualCharacterRange:NULL]; numberOfGlyphs = NSMaxRange (range); used = numberOfGlyphs; for (i = 0; i < numberOfGlyphs; i++) - if ([layoutManager notShownAttributeForGlyphAtIndex:i]) - used--; + if ([layoutManager notShownAttributeForGlyphAtIndex:i]) + used--; } if (0 < used && used <= glyph_len) @@ -433,186 +430,186 @@ mac_font_shape_1 (NSFont *font, NSString *string, glyphIndex = 0; while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex]) - glyphIndex++; + glyphIndex++; /* For now we assume the direction is not changed within the - string. */ + string. */ [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1)) - glyphs:NULL characterIndexes:NULL - glyphInscriptions:NULL elasticBits:NULL - bidiLevels:&bidiLevel]; + glyphs:NULL characterIndexes:NULL + glyphInscriptions:NULL elasticBits:NULL + bidiLevels:&bidiLevel]; if (bidiLevel & 1) - permutation = xmalloc (sizeof (NSUInteger) * used); + permutation = xmalloc (sizeof (NSUInteger) * used); else - permutation = NULL; + permutation = NULL; #define RIGHT_TO_LEFT_P permutation /* Fill the `comp_range' member of struct mac_glyph_layout, and - setup a permutation for right-to-left text. */ + setup a permutation for right-to-left text. */ compRange = NSMakeRange (0, 0); for (range = NSMakeRange (0, 0); NSMaxRange (range) < used; - range.length++) - { - struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range); - NSUInteger characterIndex = - [layoutManager characterIndexForGlyphAtIndex:glyphIndex]; - - gl->string_index = characterIndex; - - if (characterIndex >= NSMaxRange (compRange)) - { - compRange.location = NSMaxRange (compRange); - do - { - NSRange characterRange = - [string - rangeOfComposedCharacterSequenceAtIndex:characterIndex]; - - compRange.length = - NSMaxRange (characterRange) - compRange.location; - [layoutManager glyphRangeForCharacterRange:compRange - actualCharacterRange:&characterRange]; - characterIndex = NSMaxRange (characterRange) - 1; - } - while (characterIndex >= NSMaxRange (compRange)); - - if (RIGHT_TO_LEFT_P) - for (i = 0; i < range.length; i++) - permutation[range.location + i] = NSMaxRange (range) - i - 1; - - range = NSMakeRange (NSMaxRange (range), 0); - } - - gl->comp_range.location = compRange.location; - gl->comp_range.length = compRange.length; - - while (++glyphIndex < numberOfGlyphs) - if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex]) - break; - } + range.length++) + { + struct mac_glyph_layout *gl = glyph_layouts + NSMaxRange (range); + NSUInteger characterIndex = + [layoutManager characterIndexForGlyphAtIndex:glyphIndex]; + + gl->string_index = characterIndex; + + if (characterIndex >= NSMaxRange (compRange)) + { + compRange.location = NSMaxRange (compRange); + do + { + NSRange characterRange = + [string + rangeOfComposedCharacterSequenceAtIndex:characterIndex]; + + compRange.length = + NSMaxRange (characterRange) - compRange.location; + [layoutManager glyphRangeForCharacterRange:compRange + actualCharacterRange:&characterRange]; + characterIndex = NSMaxRange (characterRange) - 1; + } + while (characterIndex >= NSMaxRange (compRange)); + + if (RIGHT_TO_LEFT_P) + for (i = 0; i < range.length; i++) + permutation[range.location + i] = NSMaxRange (range) - i - 1; + + range = NSMakeRange (NSMaxRange (range), 0); + } + + gl->comp_range.location = compRange.location; + gl->comp_range.length = compRange.length; + + while (++glyphIndex < numberOfGlyphs) + if (![layoutManager notShownAttributeForGlyphAtIndex:glyphIndex]) + break; + } if (RIGHT_TO_LEFT_P) - for (i = 0; i < range.length; i++) - permutation[range.location + i] = NSMaxRange (range) - i - 1; + for (i = 0; i < range.length; i++) + permutation[range.location + i] = NSMaxRange (range) - i - 1; /* Then fill the remaining members. */ glyphIndex = prevGlyphIndex = 0; while ([layoutManager notShownAttributeForGlyphAtIndex:glyphIndex]) - glyphIndex++; + glyphIndex++; if (!RIGHT_TO_LEFT_P) - totalAdvance = 0; + totalAdvance = 0; else - { - NSUInteger nrects; - NSRect *glyphRects = - [layoutManager - rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs)) - withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0)) - inTextContainer:textContainer rectCount:&nrects]; - - totalAdvance = NSMaxX (glyphRects[0]); - } + { + NSUInteger nrects; + NSRect *glyphRects = + [layoutManager + rectArrayForGlyphRange:(NSMakeRange (0, numberOfGlyphs)) + withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0)) + inTextContainer:textContainer rectCount:&nrects]; + + totalAdvance = NSMaxX (glyphRects[0]); + } for (i = 0; i < used; i++) - { - struct mac_glyph_layout *gl; - NSPoint location; - NSUInteger nextGlyphIndex; - NSRange glyphRange; - NSRect *glyphRects; - NSUInteger nrects; - - if (!RIGHT_TO_LEFT_P) - gl = glyph_layouts + i; - else - { - NSUInteger dest = permutation[i]; - - gl = glyph_layouts + dest; - if (i < dest) - { - CFIndex tmp = gl->string_index; - - gl->string_index = glyph_layouts[i].string_index; - glyph_layouts[i].string_index = tmp; - } - } - gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex]; - - location = [layoutManager locationForGlyphAtIndex:glyphIndex]; - gl->baseline_delta = spaceLocation.y - location.y; - - for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs; - nextGlyphIndex++) - if (![layoutManager - notShownAttributeForGlyphAtIndex:nextGlyphIndex]) - break; - - if (!RIGHT_TO_LEFT_P) - { - CGFloat maxX; - - if (prevGlyphIndex == 0) - glyphRange = NSMakeRange (0, nextGlyphIndex); - else - glyphRange = NSMakeRange (glyphIndex, - nextGlyphIndex - glyphIndex); - glyphRects = - [layoutManager - rectArrayForGlyphRange:glyphRange - withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0)) - inTextContainer:textContainer rectCount:&nrects]; - maxX = max (NSMaxX (glyphRects[0]), totalAdvance); - gl->advance_delta = location.x - totalAdvance; - gl->advance = maxX - totalAdvance; - totalAdvance = maxX; - } - else - { - CGFloat minX; - - if (nextGlyphIndex == numberOfGlyphs) - glyphRange = NSMakeRange (prevGlyphIndex, - numberOfGlyphs - prevGlyphIndex); - else - glyphRange = NSMakeRange (prevGlyphIndex, - glyphIndex + 1 - prevGlyphIndex); - glyphRects = - [layoutManager - rectArrayForGlyphRange:glyphRange - withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0)) - inTextContainer:textContainer rectCount:&nrects]; - minX = min (NSMinX (glyphRects[0]), totalAdvance); - gl->advance = totalAdvance - minX; - totalAdvance = minX; - gl->advance_delta = location.x - totalAdvance; - } - - prevGlyphIndex = glyphIndex + 1; - glyphIndex = nextGlyphIndex; - } + { + struct mac_glyph_layout *gl; + NSPoint location; + NSUInteger nextGlyphIndex; + NSRange glyphRange; + NSRect *glyphRects; + NSUInteger nrects; + + if (!RIGHT_TO_LEFT_P) + gl = glyph_layouts + i; + else + { + NSUInteger dest = permutation[i]; + + gl = glyph_layouts + dest; + if (i < dest) + { + CFIndex tmp = gl->string_index; + + gl->string_index = glyph_layouts[i].string_index; + glyph_layouts[i].string_index = tmp; + } + } + gl->glyph_id = [layoutManager glyphAtIndex:glyphIndex]; + + location = [layoutManager locationForGlyphAtIndex:glyphIndex]; + gl->baseline_delta = spaceLocation.y - location.y; + + for (nextGlyphIndex = glyphIndex + 1; nextGlyphIndex < numberOfGlyphs; + nextGlyphIndex++) + if (![layoutManager + notShownAttributeForGlyphAtIndex:nextGlyphIndex]) + break; + + if (!RIGHT_TO_LEFT_P) + { + CGFloat maxX; + + if (prevGlyphIndex == 0) + glyphRange = NSMakeRange (0, nextGlyphIndex); + else + glyphRange = NSMakeRange (glyphIndex, + nextGlyphIndex - glyphIndex); + glyphRects = + [layoutManager + rectArrayForGlyphRange:glyphRange + withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0)) + inTextContainer:textContainer rectCount:&nrects]; + maxX = max (NSMaxX (glyphRects[0]), totalAdvance); + gl->advance_delta = location.x - totalAdvance; + gl->advance = maxX - totalAdvance; + totalAdvance = maxX; + } + else + { + CGFloat minX; + + if (nextGlyphIndex == numberOfGlyphs) + glyphRange = NSMakeRange (prevGlyphIndex, + numberOfGlyphs - prevGlyphIndex); + else + glyphRange = NSMakeRange (prevGlyphIndex, + glyphIndex + 1 - prevGlyphIndex); + glyphRects = + [layoutManager + rectArrayForGlyphRange:glyphRange + withinSelectedGlyphRange:(NSMakeRange (NSNotFound, 0)) + inTextContainer:textContainer rectCount:&nrects]; + minX = min (NSMinX (glyphRects[0]), totalAdvance); + gl->advance = totalAdvance - minX; + totalAdvance = minX; + gl->advance_delta = location.x - totalAdvance; + } + + prevGlyphIndex = glyphIndex + 1; + glyphIndex = nextGlyphIndex; + } if (RIGHT_TO_LEFT_P) - xfree (permutation); + xfree (permutation); #undef RIGHT_TO_LEFT_P result = used; - } - [textStorage release]; + } + [textStorage release]; return result; } static CFIndex mac_screen_font_shape (ScreenFontRef font, CFStringRef string, - struct mac_glyph_layout *glyph_layouts, - CFIndex glyph_len) + struct mac_glyph_layout *glyph_layouts, + CFIndex glyph_len) { return mac_font_shape_1 ([(NSFont *)font printerFont], - (NSString *) string, - glyph_layouts, glyph_len, YES); + (NSString *) string, + glyph_layouts, glyph_len, YES); } static CGColorRef @@ -650,6 +647,7 @@ get_cgcolor(unsigned long idx, struct frame *f) CGColorRelease (refcol_); \ } while (0) + /* Mac font driver. */ @@ -712,17 +710,17 @@ static const struct CFStringRef font_names[3]; } macfont_language_default_font_names[] = { { CFSTR ("ja"), { CFSTR ("HiraKakuProN-W3"), /* 10.5 - 10.9 */ - CFSTR ("HiraKakuPro-W3"), /* 10.4 */ - NULL }}, + CFSTR ("HiraKakuPro-W3"), /* 10.4 */ + NULL }}, { CFSTR ("ko"), { CFSTR ("AppleSDGothicNeo-Regular"), /* 10.8 - 10.9 */ - CFSTR ("AppleGothic"), /* 10.4 - 10.7 */ - NULL }}, + CFSTR ("AppleGothic"), /* 10.4 - 10.7 */ + NULL }}, { CFSTR ("zh-Hans"), { CFSTR ("STHeitiSC-Light"), /* 10.6 - 10.9 */ - CFSTR ("STXihei"), /* 10.4 - 10.5 */ - NULL }}, + CFSTR ("STXihei"), /* 10.4 - 10.5 */ + NULL }}, { CFSTR ("zh-Hant"), { CFSTR ("STHeitiTC-Light"), /* 10.6 - 10.9 */ - CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */ - NULL }}, + CFSTR ("LiHeiPro"), /* 10.4 - 10.5 */ + NULL }}, { NULL } }; #endif @@ -737,8 +735,8 @@ macfont_update_antialias_threshold (void) threshold = CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"), - kCFPreferencesCurrentApplication, - &valid_p); + kCFPreferencesCurrentApplication, + &valid_p); if (valid_p) macfont_antialias_threshold = threshold; } @@ -772,12 +770,12 @@ macfont_store_utf32char_to_unichars (UTF32Char c, UniChar *unichars) static Boolean cfnumber_get_font_symbolic_traits_value (CFNumberRef number, - FontSymbolicTraits *sym_traits) + FontSymbolicTraits *sym_traits) { SInt64 sint64_value; /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac - OS 10.6 when the value is greater than or equal to 1 << 31. */ + OS X 10.6 when the value is greater than or equal to 1 << 31. */ if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value)) { *sym_traits = (FontSymbolicTraits) sint64_value; @@ -790,7 +788,7 @@ cfnumber_get_font_symbolic_traits_value (CFNumberRef number, static void macfont_store_descriptor_attributes (FontDescriptorRef desc, - Lisp_Object spec_or_entity) + Lisp_Object spec_or_entity) { CFStringRef str; CFDictionaryRef dict; @@ -798,66 +796,66 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc, CGFloat floatval; str = mac_font_descriptor_copy_attribute (desc, - MAC_FONT_FAMILY_NAME_ATTRIBUTE); + MAC_FONT_FAMILY_NAME_ATTRIBUTE); if (str) { ASET (spec_or_entity, FONT_FAMILY_INDEX, - macfont_intern_prop_cfstring (str)); + macfont_intern_prop_cfstring (str)); CFRelease (str); } dict = mac_font_descriptor_copy_attribute (desc, MAC_FONT_TRAITS_ATTRIBUTE); if (dict) { struct { - enum font_property_index index; - CFStringRef trait; - CGPoint points[6]; + enum font_property_index index; + CFStringRef trait; + CGPoint points[6]; } numeric_traits[] = - {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT, - {{-0.4, 50}, /* light */ - {-0.24, 87.5}, /* (semi-light + normal) / 2 */ - {0, 100}, /* normal */ - {0.24, 140}, /* (semi-bold + normal) / 2 */ - {0.4, 200}, /* bold */ - {CGFLOAT_MAX, CGFLOAT_MAX}}}, - {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT, - {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}, - {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT, - {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}}; + {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT, + {{-0.4, 50}, /* light */ + {-0.24, 87.5}, /* (semi-light + normal) / 2 */ + {0, 100}, /* normal */ + {0.24, 140}, /* (semi-bold + normal) / 2 */ + {0.4, 200}, /* bold */ + {CGFLOAT_MAX, CGFLOAT_MAX}}}, + {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT, + {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}, + {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT, + {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}}; int i; - for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++) - { - num = CFDictionaryGetValue (dict, numeric_traits[i].trait); - if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval)) - { - CGPoint *point = numeric_traits[i].points; - - while (point->x < floatval) - point++; - if (point == numeric_traits[i].points) - point++; - else if (point->x == CGFLOAT_MAX) - point--; - floatval = (point - 1)->y + ((floatval - (point - 1)->x) - * ((point->y - (point - 1)->y) - / (point->x - (point - 1)->x))); - FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index, - make_number (lround (floatval))); - } - } + for (i = 0; i < ARRAYELTS (numeric_traits); i++) + { + num = CFDictionaryGetValue (dict, numeric_traits[i].trait); + if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval)) + { + CGPoint *point = numeric_traits[i].points; + + while (point->x < floatval) + point++; + if (point == numeric_traits[i].points) + point++; + else if (point->x == CGFLOAT_MAX) + point--; + floatval = (point - 1)->y + ((floatval - (point - 1)->x) + * ((point->y - (point - 1)->y) + / (point->x - (point - 1)->x))); + FONT_SET_STYLE (spec_or_entity, numeric_traits[i].index, + make_number (lround (floatval))); + } + } num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT); if (num) - { - FontSymbolicTraits sym_traits; - int spacing; + { + FontSymbolicTraits sym_traits; + int spacing; - cfnumber_get_font_symbolic_traits_value (num, &sym_traits); - spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE - ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL); - ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing)); - } + cfnumber_get_font_symbolic_traits_value (num, &sym_traits); + spacing = (sym_traits & MAC_FONT_TRAIT_MONO_SPACE + ? FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL); + ASET (spec_or_entity, FONT_SPACING_INDEX, make_number (spacing)); + } CFRelease (dict); } @@ -872,7 +870,7 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc, static Lisp_Object macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra, - FontSymbolicTraits synth_sym_traits) + FontSymbolicTraits synth_sym_traits) { Lisp_Object entity; CFDictionaryRef dict; @@ -892,7 +890,7 @@ macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra, CFNumberRef num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT); if (num) - cfnumber_get_font_symbolic_traits_value (num, &sym_traits); + cfnumber_get_font_symbolic_traits_value (num, &sym_traits); CFRelease (dict); } if (EQ (AREF (entity, FONT_SIZE_INDEX), make_number (0))) @@ -900,16 +898,16 @@ macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra, ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra)); name = mac_font_descriptor_copy_attribute (desc, MAC_FONT_NAME_ATTRIBUTE); font_put_extra (entity, QCfont_entity, - make_save_ptr_int ((void *) name, sym_traits)); + make_save_ptr_int ((void *) name, sym_traits)); if (synth_sym_traits & MAC_FONT_TRAIT_ITALIC) FONT_SET_STYLE (entity, FONT_SLANT_INDEX, - make_number (FONT_SLANT_SYNTHETIC_ITALIC)); + make_number (FONT_SLANT_SYNTHETIC_ITALIC)); if (synth_sym_traits & MAC_FONT_TRAIT_BOLD) FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, - make_number (FONT_WEIGHT_SYNTHETIC_BOLD)); + make_number (FONT_WEIGHT_SYNTHETIC_BOLD)); if (synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE) ASET (entity, FONT_SPACING_INDEX, - make_number (FONT_SPACING_SYNTHETIC_MONO)); + make_number (FONT_SPACING_SYNTHETIC_MONO)); return entity; } @@ -926,22 +924,9 @@ macfont_create_family_with_symbol (Lisp_Object symbol) if (family_name == NULL) return NULL; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - if (CTFontManagerCompareFontFamilyNames != NULL) -#endif { family_name_comparator = CTFontManagerCompareFontFamilyNames; } -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - else /* CTFontManagerCompareFontFamilyNames == NULL */ -#endif -#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */ -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - { - family_name_comparator = mac_font_family_compare; - } -#endif if ((*family_name_comparator) (family_name, CFSTR ("LastResort"), NULL) == kCFCompareEqualTo) @@ -949,36 +934,36 @@ macfont_create_family_with_symbol (Lisp_Object symbol) else while (1) { - CFIndex i, count; - - if (families == NULL) - { - families = mac_font_create_available_families (); - using_cache_p = 0; - if (families == NULL) - break; - } - - count = CFArrayGetCount (families); - i = CFArrayBSearchValues (families, CFRangeMake (0, count), - (const void *) family_name, - family_name_comparator, NULL); - if (i < count) - { - CFStringRef name = CFArrayGetValueAtIndex (families, i); - - if ((*family_name_comparator) (name, family_name, NULL) - == kCFCompareEqualTo) - result = CFRetain (name); - } - - if (result || !using_cache_p) - break; - else - { - CFRelease (families); - families = NULL; - } + CFIndex i, count; + + if (families == NULL) + { + families = mac_font_create_available_families (); + using_cache_p = 0; + if (families == NULL) + break; + } + + count = CFArrayGetCount (families); + i = CFArrayBSearchValues (families, CFRangeMake (0, count), + (const void *) family_name, + family_name_comparator, NULL); + if (i < count) + { + CFStringRef name = CFArrayGetValueAtIndex (families, i); + + if ((*family_name_comparator) (name, family_name, NULL) + == kCFCompareEqualTo) + result = CFRetain (name); + } + + if (result || !using_cache_p) + break; + else + { + CFRelease (families); + families = NULL; + } } CFRelease (family_name); @@ -1005,23 +990,23 @@ struct macfont_metrics signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS; }; -#define METRICS_VALUE(metrics, member) \ +#define METRICS_VALUE(metrics, member) \ (((metrics)->member##_high << 8) | (metrics)->member##_low) -#define METRICS_SET_VALUE(metrics, member, value) \ - do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \ - (metrics)->member##_high = tmp >> 8;} while (0) +#define METRICS_SET_VALUE(metrics, member, value) \ + do {short tmp = (value); (metrics)->member##_low = tmp & 0xff; \ + (metrics)->member##_high = tmp >> 8;} while (0) enum metrics_status - { - METRICS_INVALID = -1, /* metrics entry is invalid */ - METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */ - }; +{ + METRICS_INVALID = -1, /* metrics entry is invalid */ + METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */ +}; -#define METRICS_STATUS(metrics) \ +#define METRICS_STATUS(metrics) \ (METRICS_VALUE (metrics, ascent) + METRICS_VALUE (metrics, descent)) -#define METRICS_SET_STATUS(metrics, status) \ - do {METRICS_SET_VALUE (metrics, ascent, 0); \ - METRICS_SET_VALUE (metrics, descent, status);} while (0) +#define METRICS_SET_STATUS(metrics, status) \ + do {METRICS_SET_VALUE (metrics, ascent, 0); \ + METRICS_SET_VALUE (metrics, descent, status);} while (0) #define METRICS_NCOLS_PER_ROW (128) #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f) @@ -1029,8 +1014,8 @@ enum metrics_status static int macfont_glyph_extents (struct font *font, CGGlyph glyph, - struct font_metrics *metrics, CGFloat *advance_delta, - int force_integral_p) + struct font_metrics *metrics, CGFloat *advance_delta, + int force_integral_p) { struct macfont_info *macfont_info = (struct macfont_info *) font; FontRef macfont = macfont_info->macfont; @@ -1043,11 +1028,11 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph, if (row >= macfont_info->metrics_nrows) { macfont_info->metrics = - xrealloc (macfont_info->metrics, - sizeof (struct macfont_metrics *) * (row + 1)); + xrealloc (macfont_info->metrics, + sizeof (struct macfont_metrics *) * (row + 1)); memset (macfont_info->metrics + macfont_info->metrics_nrows, 0, - (sizeof (struct macfont_metrics *) - * (row + 1 - macfont_info->metrics_nrows))); + (sizeof (struct macfont_metrics *) + * (row + 1 - macfont_info->metrics_nrows))); macfont_info->metrics_nrows = row + 1; } if (macfont_info->metrics[row] == NULL) @@ -1057,7 +1042,7 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph, new = xmalloc (sizeof (struct macfont_metrics) * METRICS_NCOLS_PER_ROW); for (i = 0; i < METRICS_NCOLS_PER_ROW; i++) - METRICS_SET_STATUS (new + i, METRICS_INVALID); + METRICS_SET_STATUS (new + i, METRICS_INVALID); macfont_info->metrics[row] = new; } cache = macfont_info->metrics[row] + col; @@ -1067,17 +1052,17 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph, CGFloat fwidth; if (macfont_info->screen_font) - fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph); + fwidth = mac_screen_font_get_advance_width_for_glyph (macfont_info->screen_font, glyph); else - fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph); + fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph); /* For synthetic mono fonts, cache->width_{int,frac} holds the - advance delta value. */ + advance delta value. */ if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO) - fwidth = (font->pixel_size - fwidth) / 2; + fwidth = (font->pixel_size - fwidth) / 2; cache->width_int = lround (fwidth); cache->width_frac = lround ((fwidth - cache->width_int) - * WIDTH_FRAC_SCALE); + * WIDTH_FRAC_SCALE); METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID); } if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO) @@ -1088,52 +1073,52 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph, if (metrics) { if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID) - { - CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph); - - if (macfont_info->synthetic_italic_p) - { - /* We assume the members a, b, c, and d in - synthetic_italic_atfm are non-negative. */ - bounds.origin = - CGPointApplyAffineTransform (bounds.origin, - synthetic_italic_atfm); - bounds.size = - CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm); - } - if (macfont_info->synthetic_bold_p) - { - CGFloat d = - - synthetic_bold_factor * mac_font_get_size (macfont) / 2; - - bounds = CGRectInset (bounds, d, d); - } - switch (macfont_info->spacing) - { - case MACFONT_SPACING_PROPORTIONAL: - bounds.origin.x += - (cache->width_frac - / (CGFloat) (WIDTH_FRAC_SCALE * 2)); - break; - case MACFONT_SPACING_MONO: - break; - case MACFONT_SPACING_SYNTHETIC_MONO: - bounds.origin.x += (cache->width_int - + (cache->width_frac - / (CGFloat) WIDTH_FRAC_SCALE)); - break; - } - if (bounds.size.width > 0) - { - bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN; - bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN - + LCD_FONT_SMOOTHING_RIGHT_MARGIN); - } - bounds = CGRectIntegral (bounds); - METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds)); - METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds)); - METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds)); - METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds)); - } + { + CGRect bounds = mac_font_get_bounding_rect_for_glyph (macfont, glyph); + + if (macfont_info->synthetic_italic_p) + { + /* We assume the members a, b, c, and d in + synthetic_italic_atfm are non-negative. */ + bounds.origin = + CGPointApplyAffineTransform (bounds.origin, + synthetic_italic_atfm); + bounds.size = + CGSizeApplyAffineTransform (bounds.size, synthetic_italic_atfm); + } + if (macfont_info->synthetic_bold_p) + { + CGFloat d = + - synthetic_bold_factor * mac_font_get_size (macfont) / 2; + + bounds = CGRectInset (bounds, d, d); + } + switch (macfont_info->spacing) + { + case MACFONT_SPACING_PROPORTIONAL: + bounds.origin.x += - (cache->width_frac + / (CGFloat) (WIDTH_FRAC_SCALE * 2)); + break; + case MACFONT_SPACING_MONO: + break; + case MACFONT_SPACING_SYNTHETIC_MONO: + bounds.origin.x += (cache->width_int + + (cache->width_frac + / (CGFloat) WIDTH_FRAC_SCALE)); + break; + } + if (bounds.size.width > 0) + { + bounds.origin.x -= LCD_FONT_SMOOTHING_LEFT_MARGIN; + bounds.size.width += (LCD_FONT_SMOOTHING_LEFT_MARGIN + + LCD_FONT_SMOOTHING_RIGHT_MARGIN); + } + bounds = CGRectIntegral (bounds); + METRICS_SET_VALUE (cache, lbearing, CGRectGetMinX (bounds)); + METRICS_SET_VALUE (cache, rbearing, CGRectGetMaxX (bounds)); + METRICS_SET_VALUE (cache, ascent, CGRectGetMaxY (bounds)); + METRICS_SET_VALUE (cache, descent, -CGRectGetMinY (bounds)); + } metrics->lbearing = METRICS_VALUE (cache, lbearing); metrics->rbearing = METRICS_VALUE (cache, rbearing); metrics->width = width; @@ -1144,22 +1129,22 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph, if (advance_delta) { switch (macfont_info->spacing) - { - case MACFONT_SPACING_PROPORTIONAL: - *advance_delta = (force_integral_p ? 0 - : - (cache->width_frac - / (CGFloat) (WIDTH_FRAC_SCALE * 2))); - break; - case MACFONT_SPACING_MONO: - *advance_delta = 0; - break; - case MACFONT_SPACING_SYNTHETIC_MONO: - *advance_delta = (force_integral_p ? cache->width_int - : (cache->width_int - + (cache->width_frac - / (CGFloat) WIDTH_FRAC_SCALE))); - break; - } + { + case MACFONT_SPACING_PROPORTIONAL: + *advance_delta = (force_integral_p ? 0 + : - (cache->width_frac + / (CGFloat) (WIDTH_FRAC_SCALE * 2))); + break; + case MACFONT_SPACING_MONO: + *advance_delta = 0; + break; + case MACFONT_SPACING_SYNTHETIC_MONO: + *advance_delta = (force_integral_p ? cache->width_int + : (cache->width_int + + (cache->width_frac + / (CGFloat) WIDTH_FRAC_SCALE))); + break; + } } return width; @@ -1221,7 +1206,7 @@ static CFCharacterSetRef macfont_get_cf_charset (struct font *); static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef); static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char); static CGGlyph macfont_get_glyph_for_cid (struct font *font, - CharacterCollection, CGFontIndex); + CharacterCollection, CGFontIndex); static CFDataRef macfont_get_uvs_table (struct font *, CharacterCollection *); static struct macfont_cache * @@ -1232,40 +1217,39 @@ macfont_lookup_cache (CFStringRef key) if (macfont_cache_dictionary == NULL) { macfont_cache_dictionary = - CFDictionaryCreateMutable (NULL, 0, - &kCFTypeDictionaryKeyCallBacks, NULL); + CFDictionaryCreateMutable (NULL, 0, + &kCFTypeDictionaryKeyCallBacks, NULL); cache = NULL; } else cache = ((struct macfont_cache *) - CFDictionaryGetValue (macfont_cache_dictionary, key)); + CFDictionaryGetValue (macfont_cache_dictionary, key)); if (cache == NULL) { FontRef macfont = mac_font_create_with_name (key, 0); if (macfont) - { - cache = xzalloc (sizeof (struct macfont_cache)); - /* Treat the LastResort font as if it contained glyphs for - all characters. This may look too rough, but neither - CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet] - for this font is correct for non-BMP characters on Mac OS - X 10.5, anyway. */ - if (CFStringCompare (key, CFSTR ("LastResort"), 0) - == kCFCompareEqualTo) - { - CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1); - - cache->cf_charset = - CFCharacterSetCreateWithCharactersInRange (NULL, range); - } - if (cache->cf_charset == NULL) - cache->cf_charset = mac_font_copy_character_set (macfont); - CFDictionaryAddValue (macfont_cache_dictionary, key, - (const void *) cache); - CFRelease (macfont); - } + { + cache = xzalloc (sizeof (struct macfont_cache)); + /* Treat the LastResort font as if it contained glyphs for + all characters. This may look too rough, but neither + CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet] + for this font is correct for non-BMP characters on Mac OS + X 10.5, anyway. */ + if (CFEqual (key, CFSTR ("LastResort"))) + { + CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1); + + cache->cf_charset = + CFCharacterSetCreateWithCharactersInRange (NULL, range); + } + if (cache->cf_charset == NULL) + cache->cf_charset = mac_font_copy_character_set (macfont); + CFDictionaryAddValue (macfont_cache_dictionary, key, + (const void *) cache); + CFRelease (macfont); + } } return cache; @@ -1287,13 +1271,13 @@ macfont_release_cache (struct macfont_cache *cache) int i; for (i = 0; i < cache->glyph.nrows; i++) - xfree (cache->glyph.matrix[i]); + xfree (cache->glyph.matrix[i]); xfree (cache->glyph.matrix); if (cache->glyph.dictionary) - CFRelease (cache->glyph.dictionary); + CFRelease (cache->glyph.dictionary); memset (&cache->glyph, 0, sizeof (cache->glyph)); if (cache->uvs.table) - CFRelease (cache->uvs.table); + CFRelease (cache->uvs.table); memset (&cache->uvs, 0, sizeof (cache->uvs)); } } @@ -1327,124 +1311,114 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c) int nkeys_or_perm = cache->glyph.row_nkeys_or_perm[row]; if (nkeys_or_perm < ROW_PERM_OFFSET) - { - UniChar unichars[256], ch; - CGGlyph *glyphs; - int i, len; - int nrows; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - dispatch_queue_t queue; - dispatch_group_t group = NULL; -#else - int nkeys; -#endif - - if (row != 0) - { - CFMutableDictionaryRef dictionary; - uintptr_t key, value; - int nshifts; - CGGlyph glyph; - - if (cache->glyph.dictionary == NULL) - cache->glyph.dictionary = - CFDictionaryCreateMutable (NULL, 0, NULL, NULL); - dictionary = cache->glyph.dictionary; - key = c / NGLYPHS_IN_VALUE; - nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8); - value = ((uintptr_t) - CFDictionaryGetValue (dictionary, (const void *) key)); - glyph = (value >> nshifts); - if (glyph) - return glyph; - - if (nkeys_or_perm + 1 != ROW_PERM_OFFSET) - { - ch = c; - if (!mac_font_get_glyphs_for_characters (macfont, &ch, - &glyph, 1) - || glyph == 0) - glyph = kCGFontIndexInvalid; - - if (value == 0) - cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1; - value |= ((uintptr_t) glyph << nshifts); - CFDictionarySetValue (dictionary, (const void *) key, - (const void *) value); - - return glyph; - } - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - queue = - dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - group = dispatch_group_create (); - dispatch_group_async (group, queue, ^{ - int nkeys; - uintptr_t key; -#endif - nkeys = nkeys_or_perm; - for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++) - if (CFDictionaryContainsKey (dictionary, - (const void *) key)) - { - CFDictionaryRemoveValue (dictionary, - (const void *) key); - if (--nkeys == 0) - break; - } -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - }); -#endif - } - - len = 0; - for (i = 0; i < 256; i++) - { - ch = row * 256 + i; - if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch)) - unichars[len++] = ch; - } - - glyphs = xmalloc (sizeof (CGGlyph) * 256); - if (len > 0) - { - mac_font_get_glyphs_for_characters (macfont, unichars, - glyphs, len); - while (i > len) - { - int next = unichars[len - 1] % 256; - - while (--i > next) - glyphs[i] = kCGFontIndexInvalid; - - len--; - glyphs[i] = glyphs[len]; - if (len == 0) - break; - } - } - if (i > len) - while (i-- > 0) - glyphs[i] = kCGFontIndexInvalid; - - nrows = cache->glyph.nrows; - nkeys_or_perm = nrows + ROW_PERM_OFFSET; - cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm; - nrows++; - cache->glyph.matrix = xrealloc (cache->glyph.matrix, - sizeof (CGGlyph *) * nrows); - cache->glyph.matrix[nrows - 1] = glyphs; - cache->glyph.nrows = nrows; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - if (group) - { - dispatch_group_wait (group, DISPATCH_TIME_FOREVER); - dispatch_release (group); - } -#endif - } + { + UniChar unichars[256], ch; + CGGlyph *glyphs; + int i, len; + int nrows; + dispatch_queue_t queue; + dispatch_group_t group = NULL; + + if (row != 0) + { + CFMutableDictionaryRef dictionary; + uintptr_t key, value; + int nshifts; + CGGlyph glyph; + + if (cache->glyph.dictionary == NULL) + cache->glyph.dictionary = + CFDictionaryCreateMutable (NULL, 0, NULL, NULL); + dictionary = cache->glyph.dictionary; + key = c / NGLYPHS_IN_VALUE; + nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8); + value = ((uintptr_t) + CFDictionaryGetValue (dictionary, (const void *) key)); + glyph = (value >> nshifts); + if (glyph) + return glyph; + + if (nkeys_or_perm + 1 != ROW_PERM_OFFSET) + { + ch = c; + if (!mac_font_get_glyphs_for_characters (macfont, &ch, + &glyph, 1) + || glyph == 0) + glyph = kCGFontIndexInvalid; + + if (value == 0) + cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm + 1; + value |= ((uintptr_t) glyph << nshifts); + CFDictionarySetValue (dictionary, (const void *) key, + (const void *) value); + + return glyph; + } + + queue = + dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + group = dispatch_group_create (); + dispatch_group_async (group, queue, ^{ + int nkeys; + uintptr_t key; + nkeys = nkeys_or_perm; + for (key = row * (256 / NGLYPHS_IN_VALUE); ; key++) + if (CFDictionaryContainsKey (dictionary, + (const void *) key)) + { + CFDictionaryRemoveValue (dictionary, + (const void *) key); + if (--nkeys == 0) + break; + } + }); + } + + len = 0; + for (i = 0; i < 256; i++) + { + ch = row * 256 + i; + if (CFCharacterSetIsLongCharacterMember (cache->cf_charset, ch)) + unichars[len++] = ch; + } + + glyphs = xmalloc (sizeof (CGGlyph) * 256); + if (len > 0) + { + mac_font_get_glyphs_for_characters (macfont, unichars, + glyphs, len); + while (i > len) + { + int next = unichars[len - 1] % 256; + + while (--i > next) + glyphs[i] = kCGFontIndexInvalid; + + len--; + glyphs[i] = glyphs[len]; + if (len == 0) + break; + } + } + if (i > len) + while (i-- > 0) + glyphs[i] = kCGFontIndexInvalid; + + nrows = cache->glyph.nrows; + nkeys_or_perm = nrows + ROW_PERM_OFFSET; + cache->glyph.row_nkeys_or_perm[row] = nkeys_or_perm; + nrows++; + cache->glyph.matrix = xrealloc (cache->glyph.matrix, + sizeof (CGGlyph *) * nrows); + cache->glyph.matrix[nrows - 1] = glyphs; + cache->glyph.nrows = nrows; + + if (group) + { + dispatch_group_wait (group, DISPATCH_TIME_FOREVER); + dispatch_release (group); + } + } return cache->glyph.matrix[nkeys_or_perm - ROW_PERM_OFFSET][c % 256]; } @@ -1455,29 +1429,29 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c) CGGlyph glyph; if (cache->glyph.dictionary == NULL) - cache->glyph.dictionary = - CFDictionaryCreateMutable (NULL, 0, NULL, NULL); + cache->glyph.dictionary = + CFDictionaryCreateMutable (NULL, 0, NULL, NULL); key = c / NGLYPHS_IN_VALUE; nshifts = ((c % NGLYPHS_IN_VALUE) * sizeof (CGGlyph) * 8); value = (uintptr_t) CFDictionaryGetValue (cache->glyph.dictionary, - (const void *) key); + (const void *) key); glyph = (value >> nshifts); if (glyph == 0) - { - UniChar unichars[2]; - CGGlyph glyphs[2]; - CFIndex count = macfont_store_utf32char_to_unichars (c, unichars); - - if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs, - count)) - glyph = glyphs[0]; - if (glyph == 0) - glyph = kCGFontIndexInvalid; - - value |= ((uintptr_t) glyph << nshifts); - CFDictionarySetValue (cache->glyph.dictionary, - (const void *) key, (const void *) value); - } + { + UniChar unichars[2]; + CGGlyph glyphs[2]; + CFIndex count = macfont_store_utf32char_to_unichars (c, unichars); + + if (mac_font_get_glyphs_for_characters (macfont, unichars, glyphs, + count)) + glyph = glyphs[0]; + if (glyph == 0) + glyph = kCGFontIndexInvalid; + + value |= ((uintptr_t) glyph << nshifts); + CFDictionarySetValue (cache->glyph.dictionary, + (const void *) key, (const void *) value); + } return glyph; } @@ -1485,7 +1459,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c) static CGGlyph macfont_get_glyph_for_cid (struct font *font, CharacterCollection collection, - CGFontIndex cid) + CGFontIndex cid) { struct macfont_info *macfont_info = (struct macfont_info *) font; FontRef macfont = macfont_info->macfont; @@ -1506,34 +1480,34 @@ macfont_get_uvs_table (struct font *font, CharacterCollection *collection) { CFDataRef uvs_table = mac_font_copy_uvs_table (macfont); CharacterCollection uvs_collection = - MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING; + MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING; if (uvs_table == NULL - && mac_font_get_glyph_for_cid (macfont, - MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1, - 6480) != kCGFontIndexInvalid) - { - /* If the glyph for U+4E55 is accessible via its CID 6480, - then we use the Adobe-Japan1 UVS table, which maps a - variation sequence to a CID, as a fallback. */ - static CFDataRef mac_uvs_table_adobe_japan1 = NULL; - - if (mac_uvs_table_adobe_japan1 == NULL) - mac_uvs_table_adobe_japan1 = - CFDataCreateWithBytesNoCopy (NULL, - mac_uvs_table_adobe_japan1_bytes, - sizeof (mac_uvs_table_adobe_japan1_bytes), - kCFAllocatorNull); - if (mac_uvs_table_adobe_japan1) - { - uvs_table = CFRetain (mac_uvs_table_adobe_japan1); - uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1; - } - } + && mac_font_get_glyph_for_cid (macfont, + MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1, + 6480) != kCGFontIndexInvalid) + { + /* If the glyph for U+4E55 is accessible via its CID 6480, + then we use the Adobe-Japan1 UVS table, which maps a + variation sequence to a CID, as a fallback. */ + static CFDataRef mac_uvs_table_adobe_japan1 = NULL; + + if (mac_uvs_table_adobe_japan1 == NULL) + mac_uvs_table_adobe_japan1 = + CFDataCreateWithBytesNoCopy (NULL, + mac_uvs_table_adobe_japan1_bytes, + sizeof (mac_uvs_table_adobe_japan1_bytes), + kCFAllocatorNull); + if (mac_uvs_table_adobe_japan1) + { + uvs_table = CFRetain (mac_uvs_table_adobe_japan1); + uvs_collection = MAC_CHARACTER_COLLECTION_ADOBE_JAPAN1; + } + } if (uvs_table == NULL) - cache->uvs.table = kCFNull; + cache->uvs.table = kCFNull; else - cache->uvs.table = uvs_table; + cache->uvs.table = uvs_table; cache->uvs.collection = uvs_collection; } @@ -1555,12 +1529,12 @@ static Lisp_Object macfont_open (struct frame *, Lisp_Object, int); static void macfont_close (struct font *); static int macfont_has_char (Lisp_Object, int); static unsigned macfont_encode_char (struct font *, int); -static int macfont_text_extents (struct font *, unsigned int *, int, - struct font_metrics *); +static void macfont_text_extents (struct font *, unsigned int *, int, + struct font_metrics *); static int macfont_draw (struct glyph_string *, int, int, int, int, bool); static Lisp_Object macfont_shape (Lisp_Object); static int macfont_variation_glyphs (struct font *, int c, - unsigned variations[256]); + unsigned variations[256]); static void macfont_filter_properties (Lisp_Object, Lisp_Object); static struct font_driver macfont_driver = @@ -1582,8 +1556,6 @@ static struct font_driver macfont_driver = macfont_draw, NULL, /* get_bitmap */ NULL, /* free_bitmap */ - NULL, /* get_outline */ - NULL, /* free_outline */ NULL, /* anchor_point */ NULL, /* otf_capability */ NULL, /* otf_drive */ @@ -1614,19 +1586,19 @@ macfont_get_charset (Lisp_Object registry) for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++) { if (str[i] == '.') - re[j++] = '\\'; + re[j++] = '\\'; else if (str[i] == '*') - re[j++] = '.'; + re[j++] = '.'; re[j] = str[i]; if (re[j] == '?') - re[j] = '.'; + re[j] = '.'; } re[j] = '\0'; regexp = make_unibyte_string (re, j); for (i = 0; cf_charset_table[i].name; i++) if (fast_c_string_match_ignore_case - (regexp, cf_charset_table[i].name, - strlen (cf_charset_table[i].name)) >= 0) + (regexp, cf_charset_table[i].name, + strlen (cf_charset_table[i].name)) >= 0) break; if (! cf_charset_table[i].name) return -1; @@ -1639,27 +1611,27 @@ macfont_get_charset (Lisp_Object registry) CFMutableCharacterSetRef charset = CFCharacterSetCreateMutable (NULL); if (! charset) - return -1; + return -1; for (j = 0; uniquifier[j]; j++) - { - count += macfont_store_utf32char_to_unichars (uniquifier[j], - unichars + count); - CFCharacterSetAddCharactersInRange (charset, - CFRangeMake (uniquifier[j], 1)); - } + { + count += macfont_store_utf32char_to_unichars (uniquifier[j], + unichars + count); + CFCharacterSetAddCharactersInRange (charset, + CFRangeMake (uniquifier[j], 1)); + } string = CFStringCreateWithCharacters (NULL, unichars, count); if (! string) - { - CFRelease (charset); - return -1; - } + { + CFRelease (charset); + return -1; + } cf_charset_table[i].cf_charset = CFCharacterSetCreateCopy (NULL, - charset); + charset); CFRelease (charset); /* CFCharacterSetCreateWithCharactersInString does not handle - surrogate pairs properly as of Mac OS X 10.5. */ - cf_charset_table[i].cf_charset_string = string; + surrogate pairs properly as of Mac OS X 10.5. */ + cf_charset_table[i].cf_charset_string = string; } return i; } @@ -1672,19 +1644,19 @@ struct OpenTypeSpec unsigned int *features[2]; }; -#define OTF_SYM_TAG(SYM, TAG) \ - do { \ - unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \ +#define OTF_SYM_TAG(SYM, TAG) \ + do { \ + unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \ TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \ } while (0) -#define OTF_TAG_STR(TAG, P) \ - do { \ - (P)[0] = (char) (TAG >> 24); \ - (P)[1] = (char) ((TAG >> 16) & 0xFF); \ - (P)[2] = (char) ((TAG >> 8) & 0xFF); \ - (P)[3] = (char) (TAG & 0xFF); \ - (P)[4] = '\0'; \ +#define OTF_TAG_STR(TAG, P) \ + do { \ + (P)[0] = (char) (TAG >> 24); \ + (P)[1] = (char) ((TAG >> 16) & 0xFF); \ + (P)[2] = (char) ((TAG >> 8) & 0xFF); \ + (P)[3] = (char) (TAG & 0xFF); \ + (P)[4] = '\0'; \ } while (0) static struct OpenTypeSpec * @@ -1703,9 +1675,9 @@ macfont_get_open_type_spec (Lisp_Object otf_spec) OTF_SYM_TAG (spec->script, spec->script_tag); val = assq_no_quit (spec->script, Votf_script_alist); if (CONSP (val) && SYMBOLP (XCDR (val))) - spec->script = XCDR (val); + spec->script = XCDR (val); else - spec->script = Qnil; + spec->script = Qnil; } else spec->script_tag = 0x44464C54; /* "DFLT" */ @@ -1715,7 +1687,7 @@ macfont_get_open_type_spec (Lisp_Object otf_spec) { val = XCAR (otf_spec); if (! NILP (val)) - OTF_SYM_TAG (val, spec->langsys_tag); + OTF_SYM_TAG (val, spec->langsys_tag); otf_spec = XCDR (otf_spec); } spec->nfeatures[0] = spec->nfeatures[1] = 0; @@ -1725,31 +1697,31 @@ macfont_get_open_type_spec (Lisp_Object otf_spec) val = XCAR (otf_spec); if (NILP (val)) - continue; + continue; len = Flength (val); spec->features[i] = - (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len) - ? 0 - : malloc (XINT (len) * sizeof *spec->features[i])); + (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len) + ? 0 + : malloc (XINT (len) * sizeof *spec->features[i])); if (! spec->features[i]) - { - if (i > 0 && spec->features[0]) - free (spec->features[0]); - free (spec); - return NULL; - } + { + if (i > 0 && spec->features[0]) + free (spec->features[0]); + free (spec); + return NULL; + } for (j = 0, negative = 0; CONSP (val); val = XCDR (val)) - { - if (NILP (XCAR (val))) - negative = 1; - else - { - unsigned int tag; - - OTF_SYM_TAG (XCAR (val), tag); - spec->features[i][j++] = negative ? tag & 0x80000000 : tag; - } - } + { + if (NILP (XCAR (val))) + negative = 1; + else + { + unsigned int tag; + + OTF_SYM_TAG (XCAR (val), tag); + spec->features[i][j++] = negative ? tag & 0x80000000 : tag; + } + } spec->nfeatures[i] = j; } return spec; @@ -1773,16 +1745,16 @@ macfont_create_attributes_with_spec (Lisp_Object spec) CGPoint points[6]; } numeric_traits[] = {{FONT_WEIGHT_INDEX, MAC_FONT_WEIGHT_TRAIT, - {{-0.4, 50}, /* light */ - {-0.24, 87.5}, /* (semi-light + normal) / 2 */ - {0, 100}, /* normal */ - {0.24, 140}, /* (semi-bold + normal) / 2 */ - {0.4, 200}, /* bold */ - {CGFLOAT_MAX, CGFLOAT_MAX}}}, + {{-0.4, 50}, /* light */ + {-0.24, 87.5}, /* (semi-light + normal) / 2 */ + {0, 100}, /* normal */ + {0.24, 140}, /* (semi-bold + normal) / 2 */ + {0.4, 200}, /* bold */ + {CGFLOAT_MAX, CGFLOAT_MAX}}}, {FONT_SLANT_INDEX, MAC_FONT_SLANT_TRAIT, - {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}, + {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}, {FONT_WIDTH_INDEX, MAC_FONT_WIDTH_TRAIT, - {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}}; + {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}}; registry = AREF (spec, FONT_REGISTRY_INDEX); if (NILP (registry) @@ -1796,17 +1768,17 @@ macfont_create_attributes_with_spec (Lisp_Object spec) cf_charset_idx = macfont_get_charset (registry); if (cf_charset_idx < 0) - goto err; + goto err; charset = cf_charset_table[cf_charset_idx].cf_charset; charset_string = cf_charset_table[cf_charset_idx].cf_charset_string; lang = cf_charset_table[cf_charset_idx].lang; if (lang) - { - langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); - if (! langarray) - goto err; - CFArrayAppendValue (langarray, lang); - } + { + langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); + if (! langarray) + goto err; + CFArrayAppendValue (langarray, lang); + } } for (extra = AREF (spec, FONT_EXTRA_INDEX); @@ -1817,35 +1789,35 @@ macfont_create_attributes_with_spec (Lisp_Object spec) tmp = XCAR (extra); key = XCAR (tmp), val = XCDR (tmp); if (EQ (key, QClang)) - { - if (! langarray) - langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); - if (! langarray) - goto err; - if (SYMBOLP (val)) - val = list1 (val); - for (; CONSP (val); val = XCDR (val)) - if (SYMBOLP (XCAR (val))) - { - CFStringRef lang = - cfstring_create_with_string_noencode (SYMBOL_NAME - (XCAR (val))); - - if (lang == NULL) - goto err; - CFArrayAppendValue (langarray, lang); - CFRelease (lang); - } - } + { + if (! langarray) + langarray = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); + if (! langarray) + goto err; + if (SYMBOLP (val)) + val = list1 (val); + for (; CONSP (val); val = XCDR (val)) + if (SYMBOLP (XCAR (val))) + { + CFStringRef lang = + cfstring_create_with_string_noencode (SYMBOL_NAME + (XCAR (val))); + + if (lang == NULL) + goto err; + CFArrayAppendValue (langarray, lang); + CFRelease (lang); + } + } else if (EQ (key, QCotf)) - { - otspec = macfont_get_open_type_spec (val); - if (! otspec) - goto err; - script = otspec->script; - } + { + otspec = macfont_get_open_type_spec (val); + if (! otspec) + goto err; + script = otspec->script; + } else if (EQ (key, QCscript)) - script = val; + script = val; } if (! NILP (script) && ! charset) @@ -1853,40 +1825,40 @@ macfont_create_attributes_with_spec (Lisp_Object spec) Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars); if (CONSP (chars) && CONSP (CDR (chars))) - { - CFMutableStringRef string = CFStringCreateMutable (NULL, 0); - CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL); - - if (! string || !cs) - { - if (string) - CFRelease (string); - else if (cs) - CFRelease (cs); - goto err; - } - for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars)) - if (CHARACTERP (XCAR (chars))) - { - UniChar unichars[2]; - CFIndex count = - macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)), - unichars); - CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1); - - CFStringAppendCharacters (string, unichars, count); - CFCharacterSetAddCharactersInRange (cs, range); - } - charset = cs; - /* CFCharacterSetCreateWithCharactersInString does not - handle surrogate pairs properly as of Mac OS X 10.5. */ - charset_string = string; - } + { + CFMutableStringRef string = CFStringCreateMutable (NULL, 0); + CFMutableCharacterSetRef cs = CFCharacterSetCreateMutable (NULL); + + if (! string || !cs) + { + if (string) + CFRelease (string); + else if (cs) + CFRelease (cs); + goto err; + } + for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars)) + if (CHARACTERP (XCAR (chars))) + { + UniChar unichars[2]; + CFIndex count = + macfont_store_utf32char_to_unichars (XFASTINT (XCAR (chars)), + unichars); + CFRange range = CFRangeMake (XFASTINT (XCAR (chars)), 1); + + CFStringAppendCharacters (string, unichars, count); + CFCharacterSetAddCharactersInRange (cs, range); + } + charset = cs; + /* CFCharacterSetCreateWithCharactersInString does not + handle surrogate pairs properly as of Mac OS X 10.5. */ + charset_string = string; + } } attributes = CFDictionaryCreateMutable (NULL, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); if (! attributes) goto err; @@ -1896,56 +1868,56 @@ macfont_create_attributes_with_spec (Lisp_Object spec) CFStringRef family = macfont_create_family_with_symbol (tmp); if (! family) - goto err; + goto err; CFDictionaryAddValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE, - family); + family); CFRelease (family); } traits = CFDictionaryCreateMutable (NULL, 4, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); if (! traits) goto err; - for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++) + for (i = 0; i < ARRAYELTS (numeric_traits); i++) { tmp = AREF (spec, numeric_traits[i].index); if (INTEGERP (tmp)) - { - CGPoint *point = numeric_traits[i].points; - CGFloat floatval = (XINT (tmp) >> 8); // XXX - CFNumberRef num; - - while (point->y < floatval) - point++; - if (point == numeric_traits[i].points) - point++; - else if (point->y == CGFLOAT_MAX) - point--; - floatval = (point - 1)->x + ((floatval - (point - 1)->y) - * ((point->x - (point - 1)->x) - / (point->y - (point - 1)->y))); - if (floatval > 1.0) - floatval = 1.0; - else if (floatval < -1.0) - floatval = -1.0; - num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval); - if (! num) - goto err; - CFDictionaryAddValue (traits, numeric_traits[i].trait, num); - CFRelease (num); - } + { + CGPoint *point = numeric_traits[i].points; + CGFloat floatval = (XINT (tmp) >> 8); // XXX + CFNumberRef num; + + while (point->y < floatval) + point++; + if (point == numeric_traits[i].points) + point++; + else if (point->y == CGFLOAT_MAX) + point--; + floatval = (point - 1)->x + ((floatval - (point - 1)->y) + * ((point->x - (point - 1)->x) + / (point->y - (point - 1)->y))); + if (floatval > 1.0) + floatval = 1.0; + else if (floatval < -1.0) + floatval = -1.0; + num = CFNumberCreate (NULL, kCFNumberCGFloatType, &floatval); + if (! num) + goto err; + CFDictionaryAddValue (traits, numeric_traits[i].trait, num); + CFRelease (num); + } } if (CFDictionaryGetCount (traits)) CFDictionaryAddValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE, traits); if (charset) CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_ATTRIBUTE, - charset); + charset); if (charset_string) CFDictionaryAddValue (attributes, MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE, - charset_string); + charset_string); if (langarray) CFDictionaryAddValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE, langarray); @@ -1966,9 +1938,9 @@ macfont_create_attributes_with_spec (Lisp_Object spec) if (otspec) { if (otspec->nfeatures[0] > 0) - free (otspec->features[0]); + free (otspec->features[0]); if (otspec->nfeatures[1] > 0) - free (otspec->features[1]); + free (otspec->features[1]); free (otspec); } @@ -1977,38 +1949,38 @@ macfont_create_attributes_with_spec (Lisp_Object spec) static Boolean macfont_supports_charset_and_languages_p (FontDescriptorRef desc, - CFCharacterSetRef charset, - Lisp_Object chars, - CFArrayRef languages) + CFCharacterSetRef charset, + Lisp_Object chars, + CFArrayRef languages) { Boolean result = true; if (charset || VECTORP (chars)) { CFCharacterSetRef desc_charset = - mac_font_descriptor_copy_attribute (desc, - MAC_FONT_CHARACTER_SET_ATTRIBUTE); + mac_font_descriptor_copy_attribute (desc, + MAC_FONT_CHARACTER_SET_ATTRIBUTE); if (desc_charset == NULL) - result = false; + result = false; else - { - if (charset) - result = CFCharacterSetIsSupersetOfSet (desc_charset, charset); - else /* VECTORP (chars) */ - { - ptrdiff_t j; - - for (j = 0; j < ASIZE (chars); j++) - if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j)) - && CFCharacterSetIsLongCharacterMember (desc_charset, - XFASTINT (AREF (chars, j)))) - break; - if (j == ASIZE (chars)) - result = false; - } - CFRelease (desc_charset); - } + { + if (charset) + result = CFCharacterSetIsSupersetOfSet (desc_charset, charset); + else /* VECTORP (chars) */ + { + ptrdiff_t j; + + for (j = 0; j < ASIZE (chars); j++) + if (TYPE_RANGED_INTEGERP (UTF32Char, AREF (chars, j)) + && CFCharacterSetIsLongCharacterMember (desc_charset, + XFASTINT (AREF (chars, j)))) + break; + if (j == ASIZE (chars)) + result = false; + } + CFRelease (desc_charset); + } } if (result && languages) result = mac_font_descriptor_supports_languages (desc, languages); @@ -2016,38 +1988,49 @@ macfont_supports_charset_and_languages_p (FontDescriptorRef desc, return result; } -static CFIndex -macfont_closest_traits_index (CFArrayRef traits_array, - FontSymbolicTraits target) +static int +macfont_traits_distance (FontSymbolicTraits sym_traits1, + FontSymbolicTraits sym_traits2) +{ + FontSymbolicTraits diff = (sym_traits1 ^ sym_traits2); + int distance = 0; + + /* We prefer synthetic bold of italic to synthetic italic of bold + when both bold and italic are available but bold-italic is not + available. */ + if (diff & MAC_FONT_TRAIT_BOLD) + distance |= (1 << 0); + if (diff & MAC_FONT_TRAIT_ITALIC) + distance |= (1 << 1); + if (diff & MAC_FONT_TRAIT_MONO_SPACE) + distance |= (1 << 2); + + return distance; +} + +static Boolean +macfont_closest_traits_index_p (CFArrayRef traits_array, + FontSymbolicTraits target, + CFIndex index) { - CFIndex i, result = -1, count = CFArrayGetCount (traits_array); - int min_distance = (1 << 3); + CFIndex i, count = CFArrayGetCount (traits_array); + FontSymbolicTraits traits; + int my_distance; + + traits = ((FontSymbolicTraits) (uintptr_t) + CFArrayGetValueAtIndex (traits_array, index)); + my_distance = macfont_traits_distance (target, traits); for (i = 0; i < count; i++) - { - FontSymbolicTraits traits, diff; - int distance = 0; - - traits = ((FontSymbolicTraits) (uintptr_t) - CFArrayGetValueAtIndex (traits_array, i)); - diff = (target ^ traits); - /* We prefer synthetic bold of italic to synthetic italic of - bold when both bold and italic are available but bold-italic - is not available. */ - if (diff & MAC_FONT_TRAIT_BOLD) - distance |= (1 << 0); - if (diff & MAC_FONT_TRAIT_ITALIC) - distance |= (1 << 1); - if (diff & MAC_FONT_TRAIT_MONO_SPACE) - distance |= (1 << 2); - if (distance < min_distance) - { - min_distance = distance; - result = i; - } - } + if (i != index) + { + traits = ((FontSymbolicTraits) (uintptr_t) + CFArrayGetValueAtIndex (traits_array, i)); + if (macfont_traits_distance (target, traits) < my_distance) + return false; + } - return result; + return true; } static Lisp_Object @@ -2072,7 +2055,7 @@ macfont_list (struct frame *f, Lisp_Object spec) { family_name = macfont_create_family_with_symbol (family); if (family_name == NULL) - goto finish; + goto finish; } attributes = macfont_create_attributes_with_spec (spec); @@ -2085,14 +2068,14 @@ macfont_list (struct frame *f, Lisp_Object spec) spacing = XINT (AREF (spec, FONT_SPACING_INDEX)); traits = ((CFMutableDictionaryRef) - CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE)); + CFDictionaryGetValue (attributes, MAC_FONT_TRAITS_ATTRIBUTE)); n = FONT_SLANT_NUMERIC (spec); if (n < 0 || n == FONT_SLANT_SYNTHETIC_ITALIC) { synth_sym_traits |= MAC_FONT_TRAIT_ITALIC; if (traits) - CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT); + CFDictionaryRemoveValue (traits, MAC_FONT_SLANT_TRAIT); } n = FONT_WEIGHT_NUMERIC (spec); @@ -2100,7 +2083,7 @@ macfont_list (struct frame *f, Lisp_Object spec) { synth_sym_traits |= MAC_FONT_TRAIT_BOLD; if (traits) - CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT); + CFDictionaryRemoveValue (traits, MAC_FONT_WEIGHT_TRAIT); } if (languages @@ -2109,15 +2092,15 @@ macfont_list (struct frame *f, Lisp_Object spec) CFStringRef language = CFArrayGetValueAtIndex (languages, 0); if (CFStringHasPrefix (language, CFSTR ("ja")) - || CFStringHasPrefix (language, CFSTR ("ko")) - || CFStringHasPrefix (language, CFSTR ("zh"))) - synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE; + || CFStringHasPrefix (language, CFSTR ("ko")) + || CFStringHasPrefix (language, CFSTR ("zh"))) + synth_sym_traits |= MAC_FONT_TRAIT_MONO_SPACE; } /* Create array of families. */ if (family_name) families = CFArrayCreate (NULL, (const void **) &family_name, - 1, &kCFTypeArrayCallBacks); + 1, &kCFTypeArrayCallBacks); else { CFStringRef pref_family; @@ -2125,46 +2108,46 @@ macfont_list (struct frame *f, Lisp_Object spec) families = mac_font_create_available_families (); if (families == NULL) - goto err; + goto err; families_count = CFArrayGetCount (families); /* Move preferred family to the front if exists. */ pref_family = - mac_font_create_preferred_family_for_attributes (attributes); + mac_font_create_preferred_family_for_attributes (attributes); if (pref_family) - { - pref_family_index = - CFArrayGetFirstIndexOfValue (families, - CFRangeMake (0, families_count), - pref_family); - CFRelease (pref_family); - } + { + pref_family_index = + CFArrayGetFirstIndexOfValue (families, + CFRangeMake (0, families_count), + pref_family); + CFRelease (pref_family); + } if (pref_family_index > 0) - { - CFMutableArrayRef mutable_families = - CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks); - - if (mutable_families) - { - CFArrayAppendValue (mutable_families, - CFArrayGetValueAtIndex (families, - pref_family_index)); - CFArrayAppendArray (mutable_families, families, - CFRangeMake (0, pref_family_index)); - if (pref_family_index + 1 < families_count) - CFArrayAppendArray (mutable_families, families, - CFRangeMake (pref_family_index + 1, - families_count - - (pref_family_index + 1))); - CFRelease (families); - families = mutable_families; - } - } + { + CFMutableArrayRef mutable_families = + CFArrayCreateMutable (NULL, families_count, &kCFTypeArrayCallBacks); + + if (mutable_families) + { + CFArrayAppendValue (mutable_families, + CFArrayGetValueAtIndex (families, + pref_family_index)); + CFArrayAppendArray (mutable_families, families, + CFRangeMake (0, pref_family_index)); + if (pref_family_index + 1 < families_count) + CFArrayAppendArray (mutable_families, families, + CFRangeMake (pref_family_index + 1, + families_count + - (pref_family_index + 1))); + CFRelease (families); + families = mutable_families; + } + } } charset = CFDictionaryGetValue (attributes, - MAC_FONT_CHARACTER_SET_ATTRIBUTE); + MAC_FONT_CHARACTER_SET_ATTRIBUTE); if (charset) { CFRetain (charset); @@ -2174,11 +2157,11 @@ macfont_list (struct frame *f, Lisp_Object spec) { val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX)); if (! NILP (val)) - { - val = assq_no_quit (XCDR (val), Vscript_representative_chars); - if (CONSP (val) && VECTORP (XCDR (val))) - chars = XCDR (val); - } + { + val = assq_no_quit (XCDR (val), Vscript_representative_chars); + if (CONSP (val) && VECTORP (XCDR (val))) + chars = XCDR (val); + } val = Qnil; } @@ -2202,152 +2185,152 @@ macfont_list (struct frame *f, Lisp_Object spec) int j; CFDictionarySetValue (attributes, MAC_FONT_FAMILY_NAME_ATTRIBUTE, - family_name); + family_name); pat_desc = mac_font_descriptor_create_with_attributes (attributes); if (! pat_desc) - goto err; + goto err; /* CTFontDescriptorCreateMatchingFontDescriptors on Mac OS X - 10.7 returns NULL if pat_desc represents the LastResort font. - So we use CTFontDescriptorCreateMatchingFontDescriptor (no - trailing "s") for such a font. */ - if (CFStringCompare (family_name, CFSTR ("LastResort"), 0) - != kCFCompareEqualTo) - descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc, - NULL); + 10.7 returns NULL if pat_desc represents the LastResort font. + So we use CTFontDescriptorCreateMatchingFontDescriptor (no + trailing "s") for such a font. */ + if (!CFEqual (family_name, CFSTR ("LastResort"))) + descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc, + NULL); else - { - FontDescriptorRef lr_desc = - mac_font_descriptor_create_matching_font_descriptor (pat_desc, - NULL); - if (lr_desc) - { - descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1, - &kCFTypeArrayCallBacks); - CFRelease (lr_desc); - } - else - descs = NULL; - } + { + FontDescriptorRef lr_desc = + mac_font_descriptor_create_matching_font_descriptor (pat_desc, + NULL); + if (lr_desc) + { + descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1, + &kCFTypeArrayCallBacks); + CFRelease (lr_desc); + } + else + descs = NULL; + } CFRelease (pat_desc); if (! descs) - goto err; + goto err; descs_count = CFArrayGetCount (descs); if (descs_count == 0 - || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0), - charset, chars, - languages)) - { - CFRelease (descs); - continue; - } + || !macfont_supports_charset_and_languages_p (CFArrayGetValueAtIndex (descs, 0), + charset, chars, + languages)) + { + CFRelease (descs); + continue; + } filtered_descs = - CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks); + CFArrayCreateMutable (NULL, descs_count, &kCFTypeArrayCallBacks); traits_array = CFArrayCreateMutable (NULL, descs_count, NULL); for (j = 0; j < descs_count; j++) - { - FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j); - CFDictionaryRef dict; - CFNumberRef num; - FontSymbolicTraits sym_traits; - - dict = mac_font_descriptor_copy_attribute (desc, - MAC_FONT_TRAITS_ATTRIBUTE); - if (dict == NULL) - continue; - - num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT); - CFRelease (dict); - if (num == NULL - || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits)) - continue; - - if (spacing >= 0 - && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE) - && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0) - != (spacing >= FONT_SPACING_MONO))) - continue; - - /* Don't use a color bitmap font unless its family is - explicitly specified. */ - if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family)) - continue; - - if (j > 0 - && !macfont_supports_charset_and_languages_p (desc, charset, - chars, languages)) - continue; - - CFArrayAppendValue (filtered_descs, desc); - CFArrayAppendValue (traits_array, - (const void *) (uintptr_t) sym_traits); - } + { + FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j); + CFDictionaryRef dict; + CFNumberRef num; + FontSymbolicTraits sym_traits; + + dict = mac_font_descriptor_copy_attribute (desc, + MAC_FONT_TRAITS_ATTRIBUTE); + if (dict == NULL) + continue; + + num = CFDictionaryGetValue (dict, MAC_FONT_SYMBOLIC_TRAIT); + CFRelease (dict); + if (num == NULL + || !cfnumber_get_font_symbolic_traits_value (num, &sym_traits)) + continue; + + if (spacing >= 0 + && !(synth_sym_traits & MAC_FONT_TRAIT_MONO_SPACE) + && (((sym_traits & MAC_FONT_TRAIT_MONO_SPACE) != 0) + != (spacing >= FONT_SPACING_MONO))) + continue; + + /* Don't use a color bitmap font unless its family is + explicitly specified. */ + if ((sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) && NILP (family)) + continue; + + if (j > 0 + && !macfont_supports_charset_and_languages_p (desc, charset, + chars, languages)) + continue; + + CFArrayAppendValue (filtered_descs, desc); + CFArrayAppendValue (traits_array, + (const void *) (uintptr_t) sym_traits); + } CFRelease (descs); descs = filtered_descs; descs_count = CFArrayGetCount (descs); for (j = 0; j < descs_count; j++) - { - FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j); - FontSymbolicTraits sym_traits = - ((FontSymbolicTraits) (uintptr_t) - CFArrayGetValueAtIndex (traits_array, j)); - FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask; - - mask_min = ((synth_sym_traits ^ sym_traits) - & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD)); - if (FONT_SLANT_NUMERIC (spec) < 0) - mask_min &= ~MAC_FONT_TRAIT_ITALIC; - if (FONT_WEIGHT_NUMERIC (spec) < 0) - mask_min &= ~MAC_FONT_TRAIT_BOLD; - - mask_max = (synth_sym_traits & ~sym_traits); - /* Synthetic bold does not work for bitmap-only fonts on Mac - OS X 10.6. */ - if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD) - { - CFNumberRef format = - mac_font_descriptor_copy_attribute (desc, - MAC_FONT_FORMAT_ATTRIBUTE); - - if (format) - { - uint32_t format_val; - - if (CFNumberGetValue (format, kCFNumberSInt32Type, - &format_val) - && format_val == MAC_FONT_FORMAT_BITMAP) - mask_max &= ~MAC_FONT_TRAIT_BOLD; - } - } - if (spacing >= 0) - mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE); - - for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE); - mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE); - mmask += MAC_FONT_TRAIT_MONO_SPACE) - for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD); - bmask <= (mask_max & MAC_FONT_TRAIT_BOLD); - bmask += MAC_FONT_TRAIT_BOLD) - for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC); - imask <= (mask_max & MAC_FONT_TRAIT_ITALIC); - imask += MAC_FONT_TRAIT_ITALIC) - { - FontSymbolicTraits synth = (imask | bmask | mmask); - - if (synth == 0 - || j == macfont_closest_traits_index (traits_array, - (sym_traits | synth))) - { - entity = macfont_descriptor_entity (desc, extra, synth); - if (! NILP (entity)) - val = Fcons (entity, val); - } - } - } + { + FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, j); + FontSymbolicTraits sym_traits = + ((FontSymbolicTraits) (uintptr_t) + CFArrayGetValueAtIndex (traits_array, j)); + FontSymbolicTraits mask_min, mask_max, imask, bmask, mmask; + + mask_min = ((synth_sym_traits ^ sym_traits) + & (MAC_FONT_TRAIT_ITALIC | MAC_FONT_TRAIT_BOLD)); + if (FONT_SLANT_NUMERIC (spec) < 0) + mask_min &= ~MAC_FONT_TRAIT_ITALIC; + if (FONT_WEIGHT_NUMERIC (spec) < 0) + mask_min &= ~MAC_FONT_TRAIT_BOLD; + + mask_max = (synth_sym_traits & ~sym_traits); + /* Synthetic bold does not work for bitmap-only fonts on Mac + OS X 10.6. */ + if ((mask_min ^ mask_max) & MAC_FONT_TRAIT_BOLD) + { + CFNumberRef format = + mac_font_descriptor_copy_attribute (desc, + MAC_FONT_FORMAT_ATTRIBUTE); + + if (format) + { + uint32_t format_val; + + if (CFNumberGetValue (format, kCFNumberSInt32Type, + &format_val) + && format_val == MAC_FONT_FORMAT_BITMAP) + mask_max &= ~MAC_FONT_TRAIT_BOLD; + } + } + if (spacing >= 0) + mask_min |= (mask_max & MAC_FONT_TRAIT_MONO_SPACE); + + for (mmask = (mask_min & MAC_FONT_TRAIT_MONO_SPACE); + mmask <= (mask_max & MAC_FONT_TRAIT_MONO_SPACE); + mmask += MAC_FONT_TRAIT_MONO_SPACE) + for (bmask = (mask_min & MAC_FONT_TRAIT_BOLD); + bmask <= (mask_max & MAC_FONT_TRAIT_BOLD); + bmask += MAC_FONT_TRAIT_BOLD) + for (imask = (mask_min & MAC_FONT_TRAIT_ITALIC); + imask <= (mask_max & MAC_FONT_TRAIT_ITALIC); + imask += MAC_FONT_TRAIT_ITALIC) + { + FontSymbolicTraits synth = (imask | bmask | mmask); + + if (synth == 0 + || macfont_closest_traits_index_p (traits_array, + (sym_traits | synth), + j)) + { + entity = macfont_descriptor_entity (desc, extra, synth); + if (! NILP (entity)) + val = Fcons (entity, val); + } + } + } CFRelease (traits_array); CFRelease (descs); @@ -2389,13 +2372,13 @@ macfont_match (struct frame * frame, Lisp_Object spec) if (pat_desc) { desc = mac_font_descriptor_create_matching_font_descriptor (pat_desc, - NULL); + NULL); CFRelease (pat_desc); } if (desc) { entity = macfont_descriptor_entity (desc, AREF (spec, FONT_EXTRA_INDEX), - 0); + 0); CFRelease (desc); } unblock_input (); @@ -2418,7 +2401,7 @@ macfont_list_family (struct frame *frame) CFIndex i, count = CFArrayGetCount (families); for (i = 0; i < count; i++) - list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list); + list = Fcons (macfont_intern_prop_cfstring (CFArrayGetValueAtIndex (families, i)), list); CFRelease (families); } @@ -2431,7 +2414,7 @@ static void macfont_free_entity (Lisp_Object entity) { Lisp_Object val = assq_no_quit (QCfont_entity, - AREF (entity, FONT_EXTRA_INDEX)); + AREF (entity, FONT_EXTRA_INDEX)); CFStringRef name = XSAVE_POINTER (XCDR (val), 0); block_input (); @@ -2477,17 +2460,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) if (! macfont) return Qnil; - font_object = font_make_object (VECSIZE (struct macfont_info), entity, size); - ASET (font_object, FONT_TYPE_INDEX, macfont_driver.type); - len = font_unparse_xlfd (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); - len = font_unparse_fcname (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); - else - ASET (font_object, FONT_FULLNAME_INDEX, - AREF (font_object, FONT_NAME_INDEX)); + font_object = font_build_object (VECSIZE (struct macfont_info), + Qmac_ct, entity, size); font = XFONT_OBJECT (font_object); font->pixel_size = size; font->driver = &macfont_driver; @@ -2502,7 +2476,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX)); if (CONSP (val) && EQ (XCDR (val), make_number (1))) macfont_info->screen_font = mac_screen_font_create_with_name (font_name, - size); + size); else macfont_info->screen_font = NULL; macfont_info->cache = macfont_lookup_cache (font_name); @@ -2522,8 +2496,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) if (sym_traits & MAC_FONT_TRAIT_MONO_SPACE) macfont_info->spacing = MACFONT_SPACING_MONO; else if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)) - && (XINT (AREF (entity, FONT_SPACING_INDEX)) - == FONT_SPACING_SYNTHETIC_MONO)) + && (XINT (AREF (entity, FONT_SPACING_INDEX)) + == FONT_SPACING_SYNTHETIC_MONO)) macfont_info->spacing = MACFONT_SPACING_SYNTHETIC_MONO; if (macfont_info->synthetic_italic_p || macfont_info->synthetic_bold_p) macfont_info->antialias = MACFONT_ANTIALIAS_ON; @@ -2531,8 +2505,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) { val = assq_no_quit (QCantialias, AREF (entity, FONT_EXTRA_INDEX)); if (CONSP (val)) - macfont_info->antialias = - NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON; + macfont_info->antialias = + NILP (XCDR (val)) ? MACFONT_ANTIALIAS_OFF : MACFONT_ANTIALIAS_ON; } macfont_info->color_bitmap_p = 0; if (sym_traits & MAC_FONT_TRAIT_COLOR_GLYPHS) @@ -2550,7 +2524,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) { glyph = macfont_get_glyph_for_character (font, ' ' + i); if (glyph == kCGFontIndexInvalid) - break; + break; total_width += macfont_glyph_extents (font, glyph, NULL, NULL, 0); } if (i == 95) @@ -2559,8 +2533,8 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) font->average_width = font->space_width; /* XXX */ if (!(macfont_info->screen_font - && mac_screen_font_get_metrics (macfont_info->screen_font, - &ascent, &descent, &leading))) + && mac_screen_font_get_metrics (macfont_info->screen_font, + &ascent, &descent, &leading))) { CFStringRef family_name; @@ -2568,24 +2542,21 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) descent = mac_font_get_descent (macfont); leading = mac_font_get_leading (macfont); /* AppKit and WebKit do some adjustment to the heights of - Courier, Helvetica, and Times. */ + Courier, Helvetica, and Times. */ family_name = mac_font_copy_family_name (macfont); if (family_name) - { - if ((CFStringCompare (family_name, CFSTR ("Courier"), 0) - == kCFCompareEqualTo) - || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0) - == kCFCompareEqualTo) - || (CFStringCompare (family_name, CFSTR ("Times"), 0) - == kCFCompareEqualTo)) - ascent += (ascent + descent) * .15f; - else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino"))) - { - leading *= .25f; - ascent += leading; - } - CFRelease (family_name); - } + { + if (CFEqual (family_name, CFSTR ("Courier")) + || CFEqual (family_name, CFSTR ("Helvetica")) + || CFEqual (family_name, CFSTR ("Times"))) + ascent += (ascent + descent) * .15f; + else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino"))) + { + leading *= .25f; + ascent += leading; + } + CFRelease (family_name); + } } font->ascent = ascent + 0.5f; val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX)); @@ -2625,13 +2596,13 @@ macfont_close (struct font *font) CFRelease (macfont_info->macfont); CGFontRelease (macfont_info->cgfont); if (macfont_info->screen_font) - CFRelease (macfont_info->screen_font); + CFRelease (macfont_info->screen_font); macfont_release_cache (macfont_info->cache); for (i = 0; i < macfont_info->metrics_nrows; i++) - if (macfont_info->metrics[i]) - xfree (macfont_info->metrics[i]); + if (macfont_info->metrics[i]) + xfree (macfont_info->metrics[i]); if (macfont_info->metrics) - xfree (macfont_info->metrics); + xfree (macfont_info->metrics); macfont_info->cache = NULL; unblock_input (); } @@ -2676,9 +2647,9 @@ macfont_encode_char (struct font *font, int c) return glyph != kCGFontIndexInvalid ? glyph : FONT_INVALID_CODE; } -static int +static void macfont_text_extents (struct font *font, unsigned int *code, int nglyphs, - struct font_metrics *metrics) + struct font_metrics *metrics) { int width, i; @@ -2688,143 +2659,139 @@ macfont_text_extents (struct font *font, unsigned int *code, int nglyphs, { struct font_metrics m; int w = macfont_glyph_extents (font, code[i], metrics ? &m : NULL, - NULL, 0); + NULL, 0); if (metrics) - { - if (width + m.lbearing < metrics->lbearing) - metrics->lbearing = width + m.lbearing; - if (width + m.rbearing > metrics->rbearing) - metrics->rbearing = width + m.rbearing; - if (m.ascent > metrics->ascent) - metrics->ascent = m.ascent; - if (m.descent > metrics->descent) - metrics->descent = m.descent; - } + { + if (width + m.lbearing < metrics->lbearing) + metrics->lbearing = width + m.lbearing; + if (width + m.rbearing > metrics->rbearing) + metrics->rbearing = width + m.rbearing; + if (m.ascent > metrics->ascent) + metrics->ascent = m.ascent; + if (m.descent > metrics->descent) + metrics->descent = m.descent; + } width += w; } unblock_input (); if (metrics) metrics->width = width; - - return width; } static int macfont_draw (struct glyph_string *s, int from, int to, int x, int y, - bool with_background) + bool with_background) { struct frame * f = s->f; struct macfont_info *macfont_info = (struct macfont_info *) s->font; - FontRef macfont = macfont_info->macfont; - CGContextRef context; - BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; - int end = isComposite ? s->cmp_to : s->nchars; - int len = end - s->cmp_from; + CGRect background_rect; + CGPoint text_position; + CGGlyph *glyphs; + CGPoint *positions; + CGFloat font_size = mac_font_get_size (macfont_info->macfont); + bool no_antialias_p = + (macfont_info->antialias == MACFONT_ANTIALIAS_OFF + || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT + && font_size <= macfont_antialias_threshold)); + int len = to - from; struct face *face = s->face; - int i; + CGContextRef context; block_input (); - context = [[NSGraphicsContext currentContext] graphicsPort]; - CGContextSaveGState (context); + if (with_background) + background_rect = CGRectMake (x, y - FONT_BASE (s->font), + s->width, FONT_HEIGHT (s->font)); + else + background_rect = CGRectNull; -#if 0 - if (s->num_clips > 0) - { - CGRect clips[2]; + text_position = CGPointMake (x, -y); + glyphs = xmalloc (sizeof (CGGlyph) * len); + { + CGFloat advance_delta = 0; + int i; + CGFloat total_width = 0; - for (i = 0; i < s->num_clips; i++) - clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top, - s->clip[i].right - s->clip[i].left, - s->clip[i].bottom - s->clip[i].top); - CGContextClipToRects (context, clips, s->num_clips); - } -#endif + positions = xmalloc (sizeof (CGPoint) * len); + for (i = 0; i < len; i++) + { + int width; + + glyphs[i] = s->char2b[from + i]; + width = (s->padding_p ? 1 + : macfont_glyph_extents (s->font, glyphs[i], + NULL, &advance_delta, + no_antialias_p)); + positions[i].x = total_width + advance_delta; + positions[i].y = 0; + total_width += width; + } + } - if (with_background) + context = [[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState (context); + + if (!CGRectIsNull (background_rect)) { - if (s->hl == DRAW_MOUSE_FACE) + if (s->hl == DRAW_MOUSE_FACE) { face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); if (!face) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); } - CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f); - CGContextFillRect (context, - CGRectMake (x, y, - s->width, FONT_HEIGHT (s->font))); + CGContextFillRects (context, &background_rect, 1); } if (macfont_info->cgfont) { - CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len); - CGPoint *positions = alloca (sizeof (CGPoint) * len); - CGFloat total_width = 0; - CGFloat font_size = mac_font_get_size (macfont); CGAffineTransform atfm; - CGFloat advance_delta = 0; - int y_draw = -s->ybase; - int no_antialias_p = - (macfont_info->antialias == MACFONT_ANTIALIAS_OFF - || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT - && font_size <= macfont_antialias_threshold)); - - for (i = 0; i < len; i++) - { - int width; - - glyphs[i] = *(s->char2b + s->cmp_from + i); - width = (s->padding_p ? 1 - : macfont_glyph_extents (s->font, glyphs[i], - NULL, &advance_delta, - no_antialias_p)); - positions[i].x = total_width + advance_delta; - positions[i].y = 0; - total_width += width; - } CGContextScaleCTM (context, 1, -1); CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f); if (macfont_info->synthetic_italic_p) - atfm = synthetic_italic_atfm; + atfm = synthetic_italic_atfm; else - atfm = CGAffineTransformIdentity; + atfm = CGAffineTransformIdentity; if (macfont_info->synthetic_bold_p) - { - CGContextSetTextDrawingMode (context, kCGTextFillStroke); - CGContextSetLineWidth (context, synthetic_bold_factor * font_size); - CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f); - } + { + CGContextSetTextDrawingMode (context, kCGTextFillStroke); + CGContextSetLineWidth (context, synthetic_bold_factor * font_size); + CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f); + } if (no_antialias_p) - CGContextSetShouldAntialias (context, false); + CGContextSetShouldAntialias (context, false); CGContextSetTextMatrix (context, atfm); - CGContextSetTextPosition (context, x, y_draw); + CGContextSetTextPosition (context, text_position.x, text_position.y); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (macfont_info->color_bitmap_p #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 - && CTFontDrawGlyphs != NULL + && CTFontDrawGlyphs != NULL #endif - ) - { - if (len > 0) - { - CTFontDrawGlyphs (macfont, glyphs, positions, len, context); - } - } + ) + { + if (len > 0) + { + CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len, + context); + } + } else #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ - { - CGContextSetFont (context, macfont_info->cgfont); - CGContextSetFontSize (context, font_size); - CGContextShowGlyphsAtPositions (context, glyphs, positions, len); - } + { + CGContextSetFont (context, macfont_info->cgfont); + CGContextSetFontSize (context, font_size); + CGContextShowGlyphsAtPositions (context, glyphs, positions, len); + } } + + xfree (glyphs); + xfree (positions); CGContextRestoreGState (context); unblock_input (); @@ -2857,9 +2824,9 @@ macfont_shape (Lisp_Object lgstring) Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); if (NILP (lglyph)) - break; + break; if (LGLYPH_CHAR (lglyph) >= 0x10000) - nonbmp_len++; + nonbmp_len++; } len = i; @@ -2874,25 +2841,25 @@ macfont_shape (Lisp_Object lgstring) UTF32Char c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i)); if (macfont_store_utf32char_to_unichars (c, unichars + i + j) > 1) - { - nonbmp_indices[j] = i + j; - j++; - } + { + nonbmp_indices[j] = i + j; + j++; + } } nonbmp_indices[j] = len + j; /* sentinel */ block_input (); string = CFStringCreateWithCharactersNoCopy (NULL, unichars, len + nonbmp_len, - kCFAllocatorNull); + kCFAllocatorNull); if (string) { glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len); if (macfont_info->screen_font) - used = mac_screen_font_shape (macfont_info->screen_font, string, - glyph_layouts, glyph_len); + used = mac_screen_font_shape (macfont_info->screen_font, string, + glyph_layouts, glyph_len); else - used = mac_font_shape (macfont, string, glyph_layouts, glyph_len); + used = mac_font_shape (macfont, string, glyph_layouts, glyph_len); CFRelease (string); } @@ -2912,40 +2879,40 @@ macfont_shape (Lisp_Object lgstring) int xoff, yoff, wadjust; if (NILP (lglyph)) - { - lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); - LGSTRING_SET_GLYPH (lgstring, i, lglyph); - } + { + lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); + LGSTRING_SET_GLYPH (lgstring, i, lglyph); + } from = gl->comp_range.location; /* Convert UTF-16 index to UTF-32. */ j = 0; while (nonbmp_indices[j] < from) - j++; + j++; from -= j; LGLYPH_SET_FROM (lglyph, from); to = gl->comp_range.location + gl->comp_range.length; /* Convert UTF-16 index to UTF-32. */ while (nonbmp_indices[j] < to) - j++; + j++; to -= j; LGLYPH_SET_TO (lglyph, to - 1); /* LGLYPH_CHAR is used in `describe-char' for checking whether - the composition is trivial. */ + the composition is trivial. */ { - UTF32Char c; - - if (unichars[gl->string_index] >= 0xD800 - && unichars[gl->string_index] < 0xDC00) - c = (((unichars[gl->string_index] - 0xD800) << 10) - + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000); - else - c = unichars[gl->string_index]; - if (macfont_get_glyph_for_character (font, c) != gl->glyph_id) - c = 0; - LGLYPH_SET_CHAR (lglyph, c); + UTF32Char c; + + if (unichars[gl->string_index] >= 0xD800 + && unichars[gl->string_index] < 0xDC00) + c = (((unichars[gl->string_index] - 0xD800) << 10) + + (unichars[gl->string_index + 1] - 0xDC00) + 0x10000); + else + c = unichars[gl->string_index]; + if (macfont_get_glyph_for_character (font, c) != gl->glyph_id) + c = 0; + LGLYPH_SET_CHAR (lglyph, c); } { @@ -2964,15 +2931,15 @@ macfont_shape (Lisp_Object lgstring) yoff = lround (- gl->baseline_delta); wadjust = lround (gl->advance); if (xoff != 0 || yoff != 0 || wadjust != metrics.width) - { - Lisp_Object vec; + { + Lisp_Object vec; - vec = Fmake_vector (make_number (3), Qnil); - ASET (vec, 0, make_number (xoff)); - ASET (vec, 1, make_number (yoff)); - ASET (vec, 2, make_number (wadjust)); - LGLYPH_SET_ADJUSTMENT (lglyph, vec); - } + vec = Fmake_vector (make_number (3), Qnil); + ASET (vec, 0, make_number (xoff)); + ASET (vec, 1, make_number (yoff)); + ASET (vec, 2, make_number (wadjust)); + LGLYPH_SET_ADJUSTMENT (lglyph, vec); + } } unblock_input (); @@ -2995,7 +2962,7 @@ struct uvs_table UInt32 length, num_var_selector_records; struct variation_selector_record variation_selector_records[1]; }; -#define SIZEOF_UVS_TABLE_HEADER \ +#define SIZEOF_UVS_TABLE_HEADER \ (sizeof (struct uvs_table) - sizeof (struct variation_selector_record)) struct unicode_value_range @@ -3007,7 +2974,7 @@ struct default_uvs_table { UInt32 num_unicode_value_ranges; struct unicode_value_range unicode_value_ranges[1]; }; -#define SIZEOF_DEFAULT_UVS_TABLE_HEADER \ +#define SIZEOF_DEFAULT_UVS_TABLE_HEADER \ (sizeof (struct default_uvs_table) - sizeof (struct unicode_value_range)) struct uvs_mapping @@ -3020,7 +2987,7 @@ struct non_default_uvs_table UInt32 num_uvs_mappings; struct uvs_mapping uvs_mappings[1]; }; -#define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \ +#define SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER \ (sizeof (struct non_default_uvs_table) - sizeof (struct uvs_mapping)) #pragma pack(pop) @@ -3052,98 +3019,98 @@ mac_font_copy_uvs_table (FontRef font) #if __LP64__ if (CFDataGetLength (cmap_table) > UINT32_MAX) - goto finish; + goto finish; #endif cmap_len = CFDataGetLength (cmap_table); if (sizeof_sfntCMapHeader > cmap_len) - goto finish; + goto finish; ntables = BUINT16_VALUE (cmap->numTables); if (ntables > ((cmap_len - sizeof_sfntCMapHeader) - / sizeof_sfntCMapEncoding)) - goto finish; + / sizeof_sfntCMapEncoding)) + goto finish; for (i = 0; i < ntables; i++) - if ((BUINT16_VALUE (cmap->encoding[i].platformID) - == kFontUnicodePlatform) - && (BUINT16_VALUE (cmap->encoding[i].scriptID) - == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */ - { - uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset); - break; - } + if ((BUINT16_VALUE (cmap->encoding[i].platformID) + == kFontUnicodePlatform) + && (BUINT16_VALUE (cmap->encoding[i].scriptID) + == 5)) /* kFontUnicodeV4_0VariationSequenceSemantics */ + { + uvs_offset = BUINT32_VALUE (cmap->encoding[i].offset); + break; + } if (i == ntables - || uvs_offset > cmap_len - || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset) - goto finish; + || uvs_offset > cmap_len + || SIZEOF_UVS_TABLE_HEADER > cmap_len - uvs_offset) + goto finish; uvs = (struct uvs_table *) ((UInt8 *) cmap + uvs_offset); uvs_len = BUINT32_VALUE (uvs->length); if (uvs_len > cmap_len - uvs_offset - || SIZEOF_UVS_TABLE_HEADER > uvs_len) - goto finish; + || SIZEOF_UVS_TABLE_HEADER > uvs_len) + goto finish; if (BUINT16_VALUE (uvs->format) != 14) - goto finish; + goto finish; nrecords = BUINT32_VALUE (uvs->num_var_selector_records); if (nrecords > ((uvs_len - SIZEOF_UVS_TABLE_HEADER) - / sizeof (struct variation_selector_record))) - goto finish; + / sizeof (struct variation_selector_record))) + goto finish; records = uvs->variation_selector_records; for (i = 0; i < nrecords; i++) - { - UInt32 default_uvs_offset, non_default_uvs_offset; - - default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset); - if (default_uvs_offset) - { - struct default_uvs_table *default_uvs; - UInt32 nranges; - - if (default_uvs_offset > uvs_len - || (SIZEOF_DEFAULT_UVS_TABLE_HEADER - > uvs_len - default_uvs_offset)) - goto finish; - - default_uvs = ((struct default_uvs_table *) - ((UInt8 *) uvs + default_uvs_offset)); - nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges); - if (nranges > ((uvs_len - default_uvs_offset - - SIZEOF_DEFAULT_UVS_TABLE_HEADER) - / sizeof (struct unicode_value_range))) - goto finish; - /* Now 2 * nranges can't overflow, so we can safely use - `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in - mac_font_get_glyphs_for_variants. */ - } - - non_default_uvs_offset = - BUINT32_VALUE (records[i].non_default_uvs_offset); - if (non_default_uvs_offset) - { - struct non_default_uvs_table *non_default_uvs; - UInt32 nmappings; - - if (non_default_uvs_offset > uvs_len - || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER - > uvs_len - non_default_uvs_offset)) - goto finish; - - non_default_uvs = ((struct non_default_uvs_table *) - ((UInt8 *) uvs + non_default_uvs_offset)); - nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings); - if (nmappings > ((uvs_len - non_default_uvs_offset - - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER) - / sizeof (struct uvs_mapping))) - goto finish; - /* Now 2 * nmappings can't overflow, so we can safely - use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' - in mac_font_get_glyphs_for_variants. */ - } - } + { + UInt32 default_uvs_offset, non_default_uvs_offset; + + default_uvs_offset = BUINT32_VALUE (records[i].default_uvs_offset); + if (default_uvs_offset) + { + struct default_uvs_table *default_uvs; + UInt32 nranges; + + if (default_uvs_offset > uvs_len + || (SIZEOF_DEFAULT_UVS_TABLE_HEADER + > uvs_len - default_uvs_offset)) + goto finish; + + default_uvs = ((struct default_uvs_table *) + ((UInt8 *) uvs + default_uvs_offset)); + nranges = BUINT32_VALUE (default_uvs->num_unicode_value_ranges); + if (nranges > ((uvs_len - default_uvs_offset + - SIZEOF_DEFAULT_UVS_TABLE_HEADER) + / sizeof (struct unicode_value_range))) + goto finish; + /* Now 2 * nranges can't overflow, so we can safely use + `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' in + mac_font_get_glyphs_for_variants. */ + } + + non_default_uvs_offset = + BUINT32_VALUE (records[i].non_default_uvs_offset); + if (non_default_uvs_offset) + { + struct non_default_uvs_table *non_default_uvs; + UInt32 nmappings; + + if (non_default_uvs_offset > uvs_len + || (SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER + > uvs_len - non_default_uvs_offset)) + goto finish; + + non_default_uvs = ((struct non_default_uvs_table *) + ((UInt8 *) uvs + non_default_uvs_offset)); + nmappings = BUINT32_VALUE (non_default_uvs->num_uvs_mappings); + if (nmappings > ((uvs_len - non_default_uvs_offset + - SIZEOF_NON_DEFAULT_UVS_TABLE_HEADER) + / sizeof (struct uvs_mapping))) + goto finish; + /* Now 2 * nmappings can't overflow, so we can safely + use `(lo + hi) / 2' instead of `lo + (hi - lo) / 2' + in mac_font_get_glyphs_for_variants. */ + } + } uvs_table = CFDataCreate (NULL, (UInt8 *) uvs, uvs_len); @@ -3166,18 +3133,16 @@ mac_font_copy_uvs_table (FontRef font) static void mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c, - const UTF32Char selectors[], CGGlyph glyphs[], - CFIndex count) + const UTF32Char selectors[], CGGlyph glyphs[], + CFIndex count) { struct uvs_table *uvs = (struct uvs_table *) CFDataGetBytePtr (uvs_table); struct variation_selector_record *records = uvs->variation_selector_records; CFIndex i; UInt32 ir, nrecords; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 dispatch_queue_t queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create (); -#endif nrecords = BUINT32_VALUE (uvs->num_var_selector_records); i = 0; @@ -3187,86 +3152,80 @@ mac_font_get_glyphs_for_variants (CFDataRef uvs_table, UTF32Char c, UInt32 default_uvs_offset, non_default_uvs_offset; if (selectors[i] < BUINT24_VALUE (records[ir].var_selector)) - { - glyphs[i++] = kCGFontIndexInvalid; - continue; - } + { + glyphs[i++] = kCGFontIndexInvalid; + continue; + } else if (selectors[i] > BUINT24_VALUE (records[ir].var_selector)) - { - ir++; - continue; - } + { + ir++; + continue; + } /* selectors[i] == BUINT24_VALUE (records[ir].var_selector) */ default_uvs_offset = BUINT32_VALUE (records[ir].default_uvs_offset); non_default_uvs_offset = - BUINT32_VALUE (records[ir].non_default_uvs_offset); -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 + BUINT32_VALUE (records[ir].non_default_uvs_offset); dispatch_group_async (group, queue, ^{ -#endif - glyphs[i] = kCGFontIndexInvalid; - - if (default_uvs_offset) - { - struct default_uvs_table *default_uvs = - (struct default_uvs_table *) ((UInt8 *) uvs - + default_uvs_offset); - struct unicode_value_range *ranges = - default_uvs->unicode_value_ranges; - UInt32 lo, hi; - - lo = 0; - hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges); - while (lo < hi) - { - UInt32 mid = (lo + hi) / 2; - - if (c < BUINT24_VALUE (ranges[mid].start_unicode_value)) - hi = mid; - else - lo = mid + 1; - } - if (hi > 0 - && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value) - + BUINT8_VALUE (ranges[hi - 1].additional_count)))) - glyphs[i] = 0; - } - - if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset) - { - struct non_default_uvs_table *non_default_uvs = - (struct non_default_uvs_table *) ((UInt8 *) uvs - + non_default_uvs_offset); - struct uvs_mapping *mappings = non_default_uvs->uvs_mappings; - UInt32 lo, hi; - - lo = 0; - hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings); - while (lo < hi) - { - UInt32 mid = (lo + hi) / 2; - - if (c < BUINT24_VALUE (mappings[mid].unicode_value)) - hi = mid; - else - lo = mid + 1; - } - if (hi > 0 && - BUINT24_VALUE (mappings[hi - 1].unicode_value) == c) - glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id); - } -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - }); -#endif + glyphs[i] = kCGFontIndexInvalid; + + if (default_uvs_offset) + { + struct default_uvs_table *default_uvs = + (struct default_uvs_table *) ((UInt8 *) uvs + + default_uvs_offset); + struct unicode_value_range *ranges = + default_uvs->unicode_value_ranges; + UInt32 lo, hi; + + lo = 0; + hi = BUINT32_VALUE (default_uvs->num_unicode_value_ranges); + while (lo < hi) + { + UInt32 mid = (lo + hi) / 2; + + if (c < BUINT24_VALUE (ranges[mid].start_unicode_value)) + hi = mid; + else + lo = mid + 1; + } + if (hi > 0 + && (c <= (BUINT24_VALUE (ranges[hi - 1].start_unicode_value) + + BUINT8_VALUE (ranges[hi - 1].additional_count)))) + glyphs[i] = 0; + } + + if (glyphs[i] == kCGFontIndexInvalid && non_default_uvs_offset) + { + struct non_default_uvs_table *non_default_uvs = + (struct non_default_uvs_table *) ((UInt8 *) uvs + + non_default_uvs_offset); + struct uvs_mapping *mappings = non_default_uvs->uvs_mappings; + UInt32 lo, hi; + + lo = 0; + hi = BUINT32_VALUE (non_default_uvs->num_uvs_mappings); + while (lo < hi) + { + UInt32 mid = (lo + hi) / 2; + + if (c < BUINT24_VALUE (mappings[mid].unicode_value)) + hi = mid; + else + lo = mid + 1; + } + if (hi > 0 && + BUINT24_VALUE (mappings[hi - 1].unicode_value) == c) + glyphs[i] = BUINT16_VALUE (mappings[hi - 1].glyph_id); + } + }); i++; ir++; } while (i < count) glyphs[i++] = kCGFontIndexInvalid; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 dispatch_group_wait (group, DISPATCH_TIME_FOREVER); dispatch_release (group); -#endif } static int @@ -3285,26 +3244,26 @@ macfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) CGGlyph glyphs[256]; for (i = 0; i < 16; i++) - selectors[i] = 0xFE00 + i; + selectors[i] = 0xFE00 + i; for (; i < 256; i++) - selectors[i] = 0xE0100 + (i - 16); + selectors[i] = 0xE0100 + (i - 16); mac_font_get_glyphs_for_variants (uvs_table, c, selectors, glyphs, 256); for (i = 0; i < 256; i++) - { - CGGlyph glyph = glyphs[i]; - - if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING - && glyph != kCGFontIndexInvalid) - glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph); - if (glyph == kCGFontIndexInvalid) - variations[i] = 0; - else - { - variations[i] = (glyph ? glyph - : macfont_get_glyph_for_character (font, c)); - n++; - } - } + { + CGGlyph glyph = glyphs[i]; + + if (uvs_collection != MAC_CHARACTER_COLLECTION_IDENTITY_MAPPING + && glyph != kCGFontIndexInvalid) + glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph); + if (glyph == kCGFontIndexInvalid) + variations[i] = 0; + else + { + variations[i] = (glyph ? glyph + : macfont_get_glyph_for_character (font, c)); + n++; + } + } } unblock_input (); @@ -3332,7 +3291,7 @@ macfont_filter_properties (Lisp_Object font, Lisp_Object alist) static Boolean mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor, - CFArrayRef languages) + CFArrayRef languages) { Boolean result = true; CFArrayRef desc_languages = @@ -3347,13 +3306,13 @@ mac_ctfont_descriptor_supports_languages (CTFontDescriptorRef descriptor, desc_languages_count = CFArrayGetCount (desc_languages); languages_count = CFArrayGetCount (languages); for (i = 0; i < languages_count; i++) - if (!CFArrayContainsValue (desc_languages, - CFRangeMake (0, desc_languages_count), - CFArrayGetValueAtIndex (languages, i))) - { - result = false; - break; - } + if (!CFArrayContainsValue (desc_languages, + CFRangeMake (0, desc_languages_count), + CFArrayGetValueAtIndex (languages, i))) + { + result = false; + break; + } CFRelease (desc_languages); } @@ -3371,79 +3330,79 @@ mac_ctfont_create_preferred_family_for_attributes (CFDictionaryRef attributes) { CFStringRef keys[] = { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 - kCTLanguageAttributeName + kCTLanguageAttributeName #else - CFSTR ("NSLanguage") + CFSTR ("NSLanguage") #endif }; CFTypeRef values[] = {NULL}; CFIndex num_values = 0; CFArrayRef languages - = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE); + = CFDictionaryGetValue (attributes, MAC_FONT_LANGUAGES_ATTRIBUTE); if (languages && CFArrayGetCount (languages) > 0) - { - if (CTGetCoreTextVersion () >= kCTVersionNumber10_9) - values[num_values++] = CFArrayGetValueAtIndex (languages, 0); - else - { - CFCharacterSetRef charset = - CFDictionaryGetValue (attributes, - MAC_FONT_CHARACTER_SET_ATTRIBUTE); - - result = mac_font_copy_default_name_for_charset_and_languages (charset, languages); - } - } + { + if (CTGetCoreTextVersion () >= kCTVersionNumber10_9) + values[num_values++] = CFArrayGetValueAtIndex (languages, 0); + else + { + CFCharacterSetRef charset = + CFDictionaryGetValue (attributes, + MAC_FONT_CHARACTER_SET_ATTRIBUTE); + + result = mac_font_copy_default_name_for_charset_and_languages (charset, languages); + } + } if (result == NULL) - { - CFAttributedStringRef attr_string = NULL; - CTLineRef ctline = NULL; - CFDictionaryRef attrs - = CFDictionaryCreate (NULL, (const void **) keys, - (const void **) values, num_values, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (attrs) - { - attr_string = CFAttributedStringCreate (NULL, charset_string, - attrs); - CFRelease (attrs); - } - if (attr_string) - { - ctline = CTLineCreateWithAttributedString (attr_string); - CFRelease (attr_string); - } - if (ctline) - { - CFArrayRef runs = CTLineGetGlyphRuns (ctline); - CFIndex i, nruns = CFArrayGetCount (runs); - CTFontRef font; - - for (i = 0; i < nruns; i++) - { - CTRunRef run = CFArrayGetValueAtIndex (runs, i); - CFDictionaryRef attributes = CTRunGetAttributes (run); - CTFontRef font_in_run; - - if (attributes == NULL) - break; - font_in_run = - CFDictionaryGetValue (attributes, kCTFontAttributeName); - if (font_in_run == NULL) - break; - if (i == 0) - font = font_in_run; - else if (!mac_ctfont_equal_in_postscript_name (font, - font_in_run)) - break; - } - if (nruns > 0 && i == nruns) - result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute); - CFRelease (ctline); - } - } + { + CFAttributedStringRef attr_string = NULL; + CTLineRef ctline = NULL; + CFDictionaryRef attrs + = CFDictionaryCreate (NULL, (const void **) keys, + (const void **) values, num_values, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (attrs) + { + attr_string = CFAttributedStringCreate (NULL, charset_string, + attrs); + CFRelease (attrs); + } + if (attr_string) + { + ctline = CTLineCreateWithAttributedString (attr_string); + CFRelease (attr_string); + } + if (ctline) + { + CFArrayRef runs = CTLineGetGlyphRuns (ctline); + CFIndex i, nruns = CFArrayGetCount (runs); + CTFontRef font; + + for (i = 0; i < nruns; i++) + { + CTRunRef run = CFArrayGetValueAtIndex (runs, i); + CFDictionaryRef attributes = CTRunGetAttributes (run); + CTFontRef font_in_run; + + if (attributes == NULL) + break; + font_in_run = + CFDictionaryGetValue (attributes, kCTFontAttributeName); + if (font_in_run == NULL) + break; + if (i == 0) + font = font_in_run; + else if (!mac_ctfont_equal_in_postscript_name (font, + font_in_run)) + break; + } + if (nruns > 0 && i == nruns) + result = CTFontCopyAttribute (font, kCTFontFamilyNameAttribute); + CFRelease (ctline); + } + } } return result; @@ -3453,14 +3412,14 @@ static inline double mac_ctfont_get_advance_width_for_glyph (CTFontRef font, CGGlyph glyph) { return CTFontGetAdvancesForGlyphs (font, kCTFontDefaultOrientation, - &glyph, NULL, 1); + &glyph, NULL, 1); } static inline CGRect mac_ctfont_get_bounding_rect_for_glyph (CTFontRef font, CGGlyph glyph) { return CTFontGetBoundingRectsForGlyphs (font, kCTFontDefaultOrientation, - &glyph, NULL, 1); + &glyph, NULL, 1); } static CFArrayRef @@ -3468,83 +3427,31 @@ mac_ctfont_create_available_families (void) { CFMutableArrayRef families = NULL; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - if (CTFontManagerCopyAvailableFontFamilyNames != NULL) -#endif { CFArrayRef orig_families = CTFontManagerCopyAvailableFontFamilyNames (); if (orig_families) - { - CFIndex i, count = CFArrayGetCount (orig_families); - - families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks); - if (families) - for (i = 0; i < count; i++) - { - CFStringRef family = CFArrayGetValueAtIndex (orig_families, i); - - if (!CFStringHasPrefix (family, CFSTR (".")) - && (CTFontManagerCompareFontFamilyNames (family, - CFSTR ("LastResort"), - NULL) - != kCFCompareEqualTo)) - CFArrayAppendValue (families, family); - } - CFRelease (orig_families); - } - } -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - else /* CTFontManagerCopyAvailableFontFamilyNames == NULL */ -#endif -#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */ -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - { - CTFontCollectionRef collection; - CFArrayRef descs = NULL; - - collection = CTFontCollectionCreateFromAvailableFonts (NULL); - if (collection) - { - descs = CTFontCollectionCreateMatchingFontDescriptors (collection); - CFRelease (collection); - } - if (descs) - { - CFIndex i, count = CFArrayGetCount (descs); - - families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks); - if (families) - for (i = 0; i < count; i++) - { - FontDescriptorRef desc = CFArrayGetValueAtIndex (descs, i); - CFStringRef name = - mac_font_descriptor_copy_attribute (desc, - MAC_FONT_FAMILY_NAME_ATTRIBUTE); - - if (name) - { - CFIndex p, limit = CFArrayGetCount (families); - - p = CFArrayBSearchValues (families, CFRangeMake (0, limit), - (const void *) name, - mac_font_family_compare, NULL); - if (p >= limit) - CFArrayAppendValue (families, name); - else if (mac_font_family_compare - (CFArrayGetValueAtIndex (families, p), - name, NULL) != kCFCompareEqualTo) - CFArrayInsertValueAtIndex (families, p, name); - CFRelease (name); - } - } - CFRelease (descs); - } + { + CFIndex i, count = CFArrayGetCount (orig_families); + + families = CFArrayCreateMutable (NULL, count, &kCFTypeArrayCallBacks); + if (families) + for (i = 0; i < count; i++) + { + CFStringRef family = CFArrayGetValueAtIndex (orig_families, i); + + if (!CFStringHasPrefix (family, CFSTR (".")) + && (CTFontManagerCompareFontFamilyNames (family, + CFSTR ("LastResort"), + NULL) + != kCFCompareEqualTo)) + CFArrayAppendValue (families, family); + } + CFRelease (orig_families); + } } -#endif - return families; + return families; } static Boolean @@ -3562,10 +3469,10 @@ mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2) { name2 = CTFontCopyPostScriptName (font2); if (name2) - { - result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo); - CFRelease (name2); - } + { + result = CFEqual (name1, name2); + CFRelease (name2); + } CFRelease (name1); } @@ -3574,7 +3481,7 @@ mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2) static CTLineRef mac_ctfont_create_line_with_string_and_font (CFStringRef string, - CTFontRef macfont) + CTFontRef macfont) { CFStringRef keys[] = {kCTFontAttributeName, kCTKernAttributeName}; CFTypeRef values[] = {NULL, NULL}; @@ -3588,10 +3495,10 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string, if (values[1]) { attributes = CFDictionaryCreate (NULL, (const void **) keys, - (const void **) values, - sizeof (keys) / sizeof (keys[0]), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + (const void **) values, + ARRAYELTS (keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); CFRelease (values[1]); } if (attributes) @@ -3607,30 +3514,30 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string, if (ctline) { /* Abandon if ctline contains some fonts other than the - specified one. */ + specified one. */ CFArrayRef runs = CTLineGetGlyphRuns (ctline); CFIndex i, nruns = CFArrayGetCount (runs); for (i = 0; i < nruns; i++) - { - CTRunRef run = CFArrayGetValueAtIndex (runs, i); - CFDictionaryRef attributes = CTRunGetAttributes (run); - CTFontRef font_in_run; - - if (attributes == NULL) - break; - font_in_run = - CFDictionaryGetValue (attributes, kCTFontAttributeName); - if (font_in_run == NULL) - break; - if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run)) - break; - } + { + CTRunRef run = CFArrayGetValueAtIndex (runs, i); + CFDictionaryRef attributes = CTRunGetAttributes (run); + CTFontRef font_in_run; + + if (attributes == NULL) + break; + font_in_run = + CFDictionaryGetValue (attributes, kCTFontAttributeName); + if (font_in_run == NULL) + break; + if (!mac_ctfont_equal_in_postscript_name (macfont, font_in_run)) + break; + } if (i < nruns) - { - CFRelease (ctline); - ctline = NULL; - } + { + CFRelease (ctline); + ctline = NULL; + } } return ctline; @@ -3638,7 +3545,7 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string, static CFIndex mac_ctfont_shape (CTFontRef font, CFStringRef string, - struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) + struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) { CFIndex used, result = 0; CTLineRef ctline = mac_ctfont_create_line_with_string_and_font (string, font); @@ -3655,128 +3562,128 @@ mac_ctfont_shape (CTFontRef font, CFStringRef string, CFIndex total_glyph_count = 0; for (k = 0; k < ctrun_count; k++) - { - CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k); - CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun); - struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count; - CFRange string_range, comp_range, range; - CFIndex *permutation; - - if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft) - permutation = xmalloc (sizeof (CFIndex) * glyph_count); - else - permutation = NULL; + { + CTRunRef ctrun = CFArrayGetValueAtIndex (ctruns, k); + CFIndex i, min_location, glyph_count = CTRunGetGlyphCount (ctrun); + struct mac_glyph_layout *glbuf = glyph_layouts + total_glyph_count; + CFRange string_range, comp_range, range; + CFIndex *permutation; + + if (CTRunGetStatus (ctrun) & kCTRunStatusRightToLeft) + permutation = xmalloc (sizeof (CFIndex) * glyph_count); + else + permutation = NULL; #define RIGHT_TO_LEFT_P permutation - /* Now the `comp_range' member of struct mac_glyph_layout is - temporarily used as a work area such that: - glbuf[i].comp_range.location = - min {compRange[i + 1].location, ..., + /* Now the `comp_range' member of struct mac_glyph_layout is + temporarily used as a work area such that: + glbuf[i].comp_range.location = + min {compRange[i + 1].location, ..., compRange[glyph_count - 1].location, maxRange (stringRangeForCTRun)} - glbuf[i].comp_range.length = maxRange (compRange[i]) - where compRange[i] is the range of composed characters - containing i-th glyph. */ - string_range = CTRunGetStringRange (ctrun); - min_location = string_range.location + string_range.length; - for (i = 0; i < glyph_count; i++) - { - struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1; - CFIndex glyph_index; - CFRange rng; - - if (!RIGHT_TO_LEFT_P) - glyph_index = glyph_count - i - 1; - else - glyph_index = i; - CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1), - &gl->string_index); - rng = - CFStringGetRangeOfComposedCharactersAtIndex (string, - gl->string_index); - gl->comp_range.location = min_location; - gl->comp_range.length = rng.location + rng.length; - if (rng.location < min_location) - min_location = rng.location; - } - - /* Fill the `comp_range' member of struct mac_glyph_layout, - and setup a permutation for right-to-left text. */ - comp_range = CFRangeMake (string_range.location, 0); - range = CFRangeMake (0, 0); - while (1) - { - struct mac_glyph_layout *gl = - glbuf + range.location + range.length; - - if (gl->comp_range.length - > comp_range.location + comp_range.length) - comp_range.length = gl->comp_range.length - comp_range.location; - min_location = gl->comp_range.location; - range.length++; - - if (min_location >= comp_range.location + comp_range.length) - { - comp_range.length = min_location - comp_range.location; - for (i = 0; i < range.length; i++) - { - glbuf[range.location + i].comp_range = comp_range; - if (RIGHT_TO_LEFT_P) - permutation[range.location + i] = - range.location + range.length - i - 1; - } - - comp_range = CFRangeMake (min_location, 0); - range.location += range.length; - range.length = 0; - if (range.location == glyph_count) - break; - } - } - - /* Then fill the remaining members. */ - for (range = CFRangeMake (0, 1); range.location < glyph_count; - range.location++) - { - struct mac_glyph_layout *gl; - CGPoint position; - - if (!RIGHT_TO_LEFT_P) - gl = glbuf + range.location; - else - { - CFIndex src, dest; - - src = glyph_count - 1 - range.location; - dest = permutation[src]; - gl = glbuf + dest; - if (src < dest) - { - CFIndex tmp = gl->string_index; - - gl->string_index = glbuf[src].string_index; - glbuf[src].string_index = tmp; - } - } - CTRunGetGlyphs (ctrun, range, &gl->glyph_id); - - CTRunGetPositions (ctrun, range, &position); - gl->advance_delta = position.x - total_advance; - gl->baseline_delta = position.y; - gl->advance = (gl->advance_delta - + CTRunGetTypographicBounds (ctrun, range, - NULL, NULL, NULL)); - total_advance += gl->advance; - } - - if (RIGHT_TO_LEFT_P) - xfree (permutation); + glbuf[i].comp_range.length = maxRange (compRange[i]) + where compRange[i] is the range of composed characters + containing i-th glyph. */ + string_range = CTRunGetStringRange (ctrun); + min_location = string_range.location + string_range.length; + for (i = 0; i < glyph_count; i++) + { + struct mac_glyph_layout *gl = glbuf + glyph_count - i - 1; + CFIndex glyph_index; + CFRange rng; + + if (!RIGHT_TO_LEFT_P) + glyph_index = glyph_count - i - 1; + else + glyph_index = i; + CTRunGetStringIndices (ctrun, CFRangeMake (glyph_index, 1), + &gl->string_index); + rng = + CFStringGetRangeOfComposedCharactersAtIndex (string, + gl->string_index); + gl->comp_range.location = min_location; + gl->comp_range.length = rng.location + rng.length; + if (rng.location < min_location) + min_location = rng.location; + } + + /* Fill the `comp_range' member of struct mac_glyph_layout, + and setup a permutation for right-to-left text. */ + comp_range = CFRangeMake (string_range.location, 0); + range = CFRangeMake (0, 0); + while (1) + { + struct mac_glyph_layout *gl = + glbuf + range.location + range.length; + + if (gl->comp_range.length + > comp_range.location + comp_range.length) + comp_range.length = gl->comp_range.length - comp_range.location; + min_location = gl->comp_range.location; + range.length++; + + if (min_location >= comp_range.location + comp_range.length) + { + comp_range.length = min_location - comp_range.location; + for (i = 0; i < range.length; i++) + { + glbuf[range.location + i].comp_range = comp_range; + if (RIGHT_TO_LEFT_P) + permutation[range.location + i] = + range.location + range.length - i - 1; + } + + comp_range = CFRangeMake (min_location, 0); + range.location += range.length; + range.length = 0; + if (range.location == glyph_count) + break; + } + } + + /* Then fill the remaining members. */ + for (range = CFRangeMake (0, 1); range.location < glyph_count; + range.location++) + { + struct mac_glyph_layout *gl; + CGPoint position; + + if (!RIGHT_TO_LEFT_P) + gl = glbuf + range.location; + else + { + CFIndex src, dest; + + src = glyph_count - 1 - range.location; + dest = permutation[src]; + gl = glbuf + dest; + if (src < dest) + { + CFIndex tmp = gl->string_index; + + gl->string_index = glbuf[src].string_index; + glbuf[src].string_index = tmp; + } + } + CTRunGetGlyphs (ctrun, range, &gl->glyph_id); + + CTRunGetPositions (ctrun, range, &position); + gl->advance_delta = position.x - total_advance; + gl->baseline_delta = position.y; + gl->advance = (gl->advance_delta + + CTRunGetTypographicBounds (ctrun, range, + NULL, NULL, NULL)); + total_advance += gl->advance; + } + + if (RIGHT_TO_LEFT_P) + xfree (permutation); #undef RIGHT_TO_LEFT_P - total_glyph_count += glyph_count; - } + total_glyph_count += glyph_count; + } result = used; } @@ -3791,7 +3698,7 @@ mac_ctfont_shape (CTFontRef font, CFStringRef string, #if USE_CT_GLYPH_INFO static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, - CGFontIndex cid) + CGFontIndex cid) { CGGlyph result = kCGFontIndexInvalid; UniChar characters[] = {0xfffd}; @@ -3800,32 +3707,32 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, CTLineRef ctline = NULL; string = CFStringCreateWithCharacters (NULL, characters, - sizeof (characters) - / sizeof (characters[0])); + ARRAYELTS (characters)); + if (string) { CTGlyphInfoRef glyph_info = - CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string); + CTGlyphInfoCreateWithCharacterIdentifier (cid, collection, string); CFDictionaryRef attributes = NULL; if (glyph_info) - { - CFStringRef keys[] = {kCTFontAttributeName, - kCTGlyphInfoAttributeName}; - CFTypeRef values[] = {font, glyph_info}; - - attributes = CFDictionaryCreate (NULL, (const void **) keys, - (const void **) values, - sizeof (keys) / sizeof (keys[0]), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFRelease (glyph_info); - } + { + CFStringRef keys[] = {kCTFontAttributeName, + kCTGlyphInfoAttributeName}; + CFTypeRef values[] = {font, glyph_info}; + + attributes = CFDictionaryCreate (NULL, (const void **) keys, + (const void **) values, + ARRAYELTS (keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease (glyph_info); + } if (attributes) - { - attr_string = CFAttributedStringCreate (NULL, string, attributes); - CFRelease (attributes); - } + { + attr_string = CFAttributedStringCreate (NULL, string, attributes); + CFRelease (attributes); + } CFRelease (string); } if (attr_string) @@ -3838,24 +3745,24 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, CFArrayRef runs = CTLineGetGlyphRuns (ctline); if (CFArrayGetCount (runs) > 0) - { - CTRunRef run = CFArrayGetValueAtIndex (runs, 0); - CFDictionaryRef attributes = CTRunGetAttributes (run); - - if (attributes) - { - CTFontRef font_in_run = - CFDictionaryGetValue (attributes, kCTFontAttributeName); - - if (font_in_run - && mac_ctfont_equal_in_postscript_name (font_in_run, font)) - { - CTRunGetGlyphs (run, CFRangeMake (0, 1), &result); - if (result >= CTFontGetGlyphCount (font)) - result = kCGFontIndexInvalid; - } - } - } + { + CTRunRef run = CFArrayGetValueAtIndex (runs, 0); + CFDictionaryRef attributes = CTRunGetAttributes (run); + + if (attributes) + { + CTFontRef font_in_run = + CFDictionaryGetValue (attributes, kCTFontAttributeName); + + if (font_in_run + && mac_ctfont_equal_in_postscript_name (font_in_run, font)) + { + CTRunGetGlyphs (run, CFRangeMake (0, 1), &result); + if (result >= CTFontGetGlyphCount (font)) + result = kCGFontIndexInvalid; + } + } + } CFRelease (ctline); } @@ -3863,41 +3770,6 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, } #endif -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 -static inline int -mac_font_family_group (CFStringRef family) -{ - if (CFStringHasPrefix (family, CFSTR ("#"))) - return 2; - else - { - CFRange range; - - range = CFStringFind (family, CFSTR ("Apple"), - kCFCompareCaseInsensitive | kCFCompareAnchored); - if (range.location != kCFNotFound) - return 1; - - return 0; - } -} - -static CFComparisonResult -mac_font_family_compare (const void *val1, const void *val2, void *context) -{ - CFStringRef family1 = (CFStringRef) val1, family2 = (CFStringRef) val2; - int group1, group2; - - group1 = mac_font_family_group (family1); - group2 = mac_font_family_group (family2); - if (group1 < group2) - return kCFCompareLessThan; - if (group1 > group2) - return kCFCompareGreaterThan; - return CFStringCompare (family1, family2, kCFCompareCaseInsensitive); -} -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */ - static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef language) { @@ -3909,22 +3781,22 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language) #endif { CTFontRef user_font = - CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language); + CTFontCreateUIFontForLanguage (kCTFontUserFontType, 0, language); if (user_font) - { - CFArrayRef languages = - CFArrayCreate (NULL, (const void **) &language, 1, - &kCFTypeArrayCallBacks); - - if (languages) - { - result = CTFontCopyDefaultCascadeListForLanguages (user_font, - languages); - CFRelease (languages); - } - CFRelease (user_font); - } + { + CFArrayRef languages = + CFArrayCreate (NULL, (const void **) &language, 1, + &kCFTypeArrayCallBacks); + + if (languages) + { + result = CTFontCopyDefaultCascadeListForLanguages (user_font, + languages); + CFRelease (languages); + } + CFRelease (user_font); + } } #if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 else /* CTFontCopyDefaultCascadeListForLanguages == NULL */ @@ -3935,55 +3807,55 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language) CFIndex i; for (i = 0; macfont_language_default_font_names[i].language; i++) - { - if (CFStringCompare (macfont_language_default_font_names[i].language, - language, 0) == kCFCompareEqualTo) - { - CFMutableArrayRef descriptors = - CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); - - if (descriptors) - { - CFIndex j; - - for (j = 0; - macfont_language_default_font_names[i].font_names[j]; - j++) - { - CFDictionaryRef attributes = - CFDictionaryCreate (NULL, - ((const void **) - &MAC_FONT_NAME_ATTRIBUTE), - ((const void **) - &macfont_language_default_font_names[i].font_names[j]), - 1, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (attributes) - { - FontDescriptorRef pat_desc = - mac_font_descriptor_create_with_attributes (attributes); - - if (pat_desc) - { - FontDescriptorRef descriptor = - mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL); - - if (descriptor) - { - CFArrayAppendValue (descriptors, descriptor); - CFRelease (descriptor); - } - CFRelease (pat_desc); - } - CFRelease (attributes); - } - } - result = descriptors; - } - break; - } - } + { + if (CFEqual (macfont_language_default_font_names[i].language, + language)) + { + CFMutableArrayRef descriptors = + CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); + + if (descriptors) + { + CFIndex j; + + for (j = 0; + macfont_language_default_font_names[i].font_names[j]; + j++) + { + CFDictionaryRef attributes = + CFDictionaryCreate (NULL, + ((const void **) + &MAC_FONT_NAME_ATTRIBUTE), + ((const void **) + &macfont_language_default_font_names[i].font_names[j]), + 1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (attributes) + { + FontDescriptorRef pat_desc = + mac_font_descriptor_create_with_attributes (attributes); + + if (pat_desc) + { + FontDescriptorRef descriptor = + mac_font_descriptor_create_matching_font_descriptor (pat_desc, NULL); + + if (descriptor) + { + CFArrayAppendValue (descriptors, descriptor); + CFRelease (descriptor); + } + CFRelease (pat_desc); + } + CFRelease (attributes); + } + } + result = descriptors; + } + break; + } + } } #endif @@ -3992,7 +3864,7 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language) static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset, - CFArrayRef languages) + CFArrayRef languages) { CFStringRef result = NULL; CFStringRef language = CFArrayGetValueAtIndex (languages, 0); @@ -4004,30 +3876,29 @@ mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset, CFIndex i, count = CFArrayGetCount (descriptors); for (i = 0; i < count; i++) - { - FontDescriptorRef descriptor = - CFArrayGetValueAtIndex (descriptors, i); - - if (macfont_supports_charset_and_languages_p (descriptor, charset, - Qnil, languages)) - { - CFStringRef family = - mac_font_descriptor_copy_attribute (descriptor, - MAC_FONT_FAMILY_NAME_ATTRIBUTE); - if (family) - { - if (!CFStringHasPrefix (family, CFSTR (".")) - && (CFStringCompare (family, CFSTR ("LastResort"), 0) - != kCFCompareEqualTo)) - { - result = family; - break; - } - else - CFRelease (family); - } - } - } + { + FontDescriptorRef descriptor = + CFArrayGetValueAtIndex (descriptors, i); + + if (macfont_supports_charset_and_languages_p (descriptor, charset, + Qnil, languages)) + { + CFStringRef family = + mac_font_descriptor_copy_attribute (descriptor, + MAC_FONT_FAMILY_NAME_ATTRIBUTE); + if (family) + { + if (!CFStringHasPrefix (family, CFSTR (".")) + && !CFEqual (family, CFSTR ("LastResort"))) + { + result = family; + break; + } + else + CFRelease (family); + } + } + } CFRelease (descriptors); } @@ -4049,13 +3920,10 @@ mac_register_font_driver (struct frame *f) register_font_driver (&macfont_driver, f); } -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 - void syms_of_macfont (void) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 static struct font_driver mac_font_driver; DEFSYM (Qmac_ct, "mac-ct"); @@ -4064,5 +3932,4 @@ syms_of_macfont (void) DEFSYM (QCdestination, ":destination"); DEFSYM (QCminspace, ":minspace"); -#endif } diff --git a/src/macros.c b/src/macros.c index 5bed625ff41..c3d26d0d5c2 100644 --- a/src/macros.c +++ b/src/macros.c @@ -45,8 +45,6 @@ EMACS_INT executing_kbd_macro_iterations; Lisp_Object executing_kbd_macro; -Lisp_Object Fexecute_kbd_macro (Lisp_Object macro, Lisp_Object count, Lisp_Object loopfunc); - DEFUN ("start-kbd-macro", Fstart_kbd_macro, Sstart_kbd_macro, 1, 2, "P", doc: /* Record subsequent keyboard input, defining a keyboard macro. The commands are recorded even as they are executed. @@ -84,28 +82,21 @@ macro before appending to it. */) } else { - ptrdiff_t i; - EMACS_INT len; + int incr = 30; + ptrdiff_t i, len; bool cvt; /* Check the type of last-kbd-macro in case Lisp code changed it. */ - CHECK_VECTOR_OR_STRING (KVAR (current_kboard, Vlast_kbd_macro)); - - len = XINT (Flength (KVAR (current_kboard, Vlast_kbd_macro))); + len = CHECK_VECTOR_OR_STRING (KVAR (current_kboard, Vlast_kbd_macro)); /* Copy last-kbd-macro into the buffer, in case the Lisp code has put another macro there. */ - if (current_kboard->kbd_macro_bufsize < len + 30) - { - if (PTRDIFF_MAX < MOST_POSITIVE_FIXNUM + 30 - && PTRDIFF_MAX < len + 30) - memory_full (SIZE_MAX); - current_kboard->kbd_macro_buffer = - xpalloc (current_kboard->kbd_macro_buffer, - ¤t_kboard->kbd_macro_bufsize, - len + 30 - current_kboard->kbd_macro_bufsize, -1, - sizeof *current_kboard->kbd_macro_buffer); - } + if (current_kboard->kbd_macro_bufsize - incr < len) + current_kboard->kbd_macro_buffer = + xpalloc (current_kboard->kbd_macro_buffer, + ¤t_kboard->kbd_macro_bufsize, + len - current_kboard->kbd_macro_bufsize + incr, -1, + sizeof *current_kboard->kbd_macro_buffer); /* Must convert meta modifier when copying string to vector. */ cvt = STRINGP (KVAR (current_kboard, Vlast_kbd_macro)); diff --git a/src/marker.c b/src/marker.c index 91fcea5f25f..d377efbc4fa 100644 --- a/src/marker.c +++ b/src/marker.c @@ -455,21 +455,8 @@ attach_marker (struct Lisp_Marker *m, struct buffer *b, static struct buffer * live_buffer (Lisp_Object buffer) { - struct buffer *b; - - if (NILP (buffer)) - { - b = current_buffer; - eassert (BUFFER_LIVE_P (b)); - } - else - { - CHECK_BUFFER (buffer); - b = XBUFFER (buffer); - if (!BUFFER_LIVE_P (b)) - b = NULL; - } - return b; + struct buffer *b = decode_buffer (buffer); + return BUFFER_LIVE_P (b) ? b : NULL; } /* Internal function to set MARKER in BUFFER at POSITION. Non-zero diff --git a/src/menu.c b/src/menu.c index 654be0db9c7..61163ae0216 100644 --- a/src/menu.c +++ b/src/menu.c @@ -66,9 +66,6 @@ Lisp_Object menu_items; /* If non-nil, means that the global vars defined here are already in use. Used to detect cases where we try to re-enter this non-reentrant code. */ -#if ! (defined USE_GTK || defined USE_MOTIF) -static -#endif Lisp_Object menu_items_inuse; /* Number of slots currently allocated in menu_items. */ @@ -357,7 +354,7 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk front of them. */ if (!have_boxes ()) { - Lisp_Object prefix = Qnil; + char const *prefix = 0; Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE); if (!NILP (type)) { @@ -392,8 +389,11 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk { if (!submenu && SREF (tem, 0) != '\0' && SREF (tem, 0) != '-') - ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME, - concat2 (build_string (" "), tem)); + { + AUTO_STRING (spaces, " "); + ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME, + concat2 (spaces, tem)); + } idx += MENU_ITEMS_ITEM_LENGTH; } } @@ -402,24 +402,30 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk /* Calculate prefix, if any, for this item. */ if (EQ (type, QCtoggle)) - prefix = build_string (NILP (selected) ? "[ ] " : "[X] "); + prefix = NILP (selected) ? "[ ] " : "[X] "; else if (EQ (type, QCradio)) - prefix = build_string (NILP (selected) ? "( ) " : "(*) "); + prefix = NILP (selected) ? "( ) " : "(*) "; } /* Not a button. If we have earlier buttons, then we need a prefix. */ else if (!skp->notbuttons && SREF (item_string, 0) != '\0' && SREF (item_string, 0) != '-') - prefix = build_string (" "); + prefix = " "; - if (!NILP (prefix)) - item_string = concat2 (prefix, item_string); + if (prefix) + { + AUTO_STRING (prefix_obj, prefix); + item_string = concat2 (prefix_obj, item_string); + } } if ((FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame)) || FRAME_MSDOS_P (XFRAME (Vmenu_updating_frame))) && !NILP (map)) /* Indicate visually that this is a submenu. */ - item_string = concat2 (item_string, build_string (" >")); + { + AUTO_STRING (space_gt, " >"); + item_string = concat2 (item_string, space_gt); + } push_menu_item (item_string, enabled, key, AREF (item_properties, ITEM_PROPERTY_DEF), @@ -576,21 +582,26 @@ parse_single_submenu (Lisp_Object item_key, Lisp_Object item_name, #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI) -/* Allocate a widget_value, blocking input. */ +/* Allocate and basically initialize widget_value, blocking input. */ widget_value * -xmalloc_widget_value (void) +make_widget_value (const char *name, char *value, + bool enabled, Lisp_Object help) { - widget_value *value; + widget_value *wv; block_input (); - value = malloc_widget_value (); + wv = xzalloc (sizeof (widget_value)); unblock_input (); - return value; + wv->name = (char *) name; + wv->value = value; + wv->enabled = enabled; + wv->help = help; + return wv; } -/* This recursively calls free_widget_value on the tree of widgets. +/* This recursively calls xfree on the tree of widgets. It must free all data that was malloc'ed for these widget_values. In Emacs, many slots are pointers into the data of Lisp_Strings, and must be left alone. */ @@ -613,7 +624,7 @@ free_menubar_widget_value_tree (widget_value *wv) wv->next = (widget_value *) 0xDEADBEEF; } block_input (); - free_widget_value (wv); + xfree (wv); unblock_input (); } @@ -630,14 +641,11 @@ digest_single_submenu (int start, int end, bool top_level_items) widget_value **submenu_stack; bool panes_seen = 0; struct frame *f = XFRAME (Vmenu_updating_frame); + USE_SAFE_ALLOCA; - submenu_stack = alloca (menu_items_used * sizeof *submenu_stack); - wv = xmalloc_widget_value (); - wv->name = "menu"; - wv->value = 0; - wv->enabled = 1; + SAFE_NALLOCA (submenu_stack, 1, menu_items_used); + wv = make_widget_value ("menu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; save_wv = 0; prev_wv = 0; @@ -721,17 +729,14 @@ digest_single_submenu (int start, int end, bool top_level_items) with its items as a submenu beneath it. */ if (strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + /* Set value to 1 so update_submenu_strings can handle '@'. */ + wv = make_widget_value (NULL, (char *) 1, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; wv->lname = pane_name; - /* Set value to 1 so update_submenu_strings can handle '@' */ - wv->value = (char *)1; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; } else @@ -805,7 +810,8 @@ digest_single_submenu (int start, int end, bool top_level_items) #endif } - wv = xmalloc_widget_value (); + wv = make_widget_value (NULL, NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else @@ -814,11 +820,9 @@ digest_single_submenu (int start, int end, bool top_level_items) wv->lname = item_name; if (!NILP (descrip)) wv->lkey = descrip; - wv->value = 0; /* The intptr_t cast avoids a warning. There's no problem as long as pointers have enough bits to hold small integers. */ wv->call_data = (!NILP (def) ? (void *) (intptr_t) i : 0); - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -830,10 +834,6 @@ digest_single_submenu (int start, int end, bool top_level_items) emacs_abort (); wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; prev_wv = wv; @@ -845,11 +845,12 @@ digest_single_submenu (int start, int end, bool top_level_items) that was originally a button, return it by itself. */ if (top_level_items && first_wv->contents && first_wv->contents->next == 0) { - wv = first_wv->contents; - free_widget_value (first_wv); - return wv; + wv = first_wv; + first_wv = first_wv->contents; + xfree (wv); } + SAFE_FREE (); return first_wv; } @@ -900,9 +901,10 @@ find_and_call_menu_selection (struct frame *f, int menu_bar_items_used, Lisp_Object *subprefix_stack; int submenu_depth = 0; int i; + USE_SAFE_ALLOCA; entry = Qnil; - subprefix_stack = alloca (menu_bar_items_used * sizeof *subprefix_stack); + SAFE_NALLOCA (subprefix_stack, 1, menu_bar_items_used); prefix = Qnil; i = 0; @@ -964,11 +966,13 @@ find_and_call_menu_selection (struct frame *f, int menu_bar_items_used, buf.arg = entry; kbd_buffer_store_event (&buf); - return; + break; } i += MENU_ITEMS_ITEM_LENGTH; } } + + SAFE_FREE (); } #endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */ @@ -983,10 +987,11 @@ find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data int i; Lisp_Object *subprefix_stack; int submenu_depth = 0; + USE_SAFE_ALLOCA; prefix = entry = Qnil; i = 0; - subprefix_stack = alloca (menu_items_used * word_size); + SAFE_ALLOCA_LISP (subprefix_stack, menu_items_used); while (i < menu_items_used) { @@ -1028,11 +1033,13 @@ find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data if (!NILP (subprefix_stack[j])) entry = Fcons (subprefix_stack[j], entry); } + SAFE_FREE (); return entry; } i += MENU_ITEMS_ITEM_LENGTH; } } + SAFE_FREE (); return Qnil; } #endif /* HAVE_NS */ @@ -1168,9 +1175,7 @@ no quit occurs and `x-popup-menu' returns nil. */) Lisp_Object selection = Qnil; struct frame *f = NULL; Lisp_Object x, y, window; - bool keymaps = 0; - bool for_click = 0; - bool kbd_menu_navigation = 0; + int menuflags = 0; ptrdiff_t specpdl_count = SPECPDL_INDEX (); struct gcpro gcpro1; @@ -1200,12 +1205,12 @@ no quit occurs and `x-popup-menu' returns nil. */) } else { - for_click = 1; + menuflags |= MENU_FOR_CLICK; tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ window = Fcar (tem); /* POSN_WINDOW (tem) */ tem2 = Fcar (Fcdr (tem)); /* POSN_POSN (tem) */ - /* The kbd_menu_navigation flag is set when the menu was - invoked by F10, which probably means they have no + /* The MENU_KBD_NAVIGATION field is set when the menu + was invoked by F10, which probably means they have no mouse. In that case, we let them switch between top-level menu-bar menus by using C-f/C-b and horizontal arrow keys, since they cannot click the @@ -1218,7 +1223,7 @@ no quit occurs and `x-popup-menu' returns nil. */) if (!EQ (POSN_POSN (last_nonmenu_event), POSN_POSN (position)) && CONSP (tem2) && EQ (Fcar (tem2), Qmenu_bar)) - kbd_menu_navigation = 1; + menuflags |= MENU_KBD_NAVIGATION; tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */ x = Fcar (tem); y = Fcdr (tem); @@ -1245,7 +1250,7 @@ no quit occurs and `x-popup-menu' returns nil. */) { int cur_x, cur_y; - mouse_position_for_popup (new_f, &cur_x, &cur_y); + x_relative_mouse_position (new_f, &cur_x, &cur_y); /* cur_x/y may be negative, so use make_number. */ x = make_number (cur_x); y = make_number (cur_y); @@ -1347,7 +1352,7 @@ no quit occurs and `x-popup-menu' returns nil. */) if (!NILP (prompt) && menu_items_n_panes >= 0) ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt); - keymaps = 1; + menuflags |= MENU_KEYMAPS; } else if (CONSP (menu) && KEYMAPP (XCAR (menu))) { @@ -1380,7 +1385,7 @@ no quit occurs and `x-popup-menu' returns nil. */) if (!NILP (title) && menu_items_n_panes >= 0) ASET (menu_items, MENU_ITEMS_PANE_NAME, title); - keymaps = 1; + menuflags |= MENU_KEYMAPS; SAFE_FREE (); } @@ -1392,7 +1397,7 @@ no quit occurs and `x-popup-menu' returns nil. */) list_of_panes (Fcdr (menu)); - keymaps = 0; + menuflags &= ~MENU_KEYMAPS; } unbind_to (specpdl_count, Qnil); @@ -1422,40 +1427,12 @@ no quit occurs and `x-popup-menu' returns nil. */) record_unwind_protect_void (discard_menu_items); #endif - /* Display them in a menu. */ - - /* FIXME: Use a terminal hook! */ -#if defined HAVE_NTGUI - if (FRAME_W32_P (f)) - selection = w32_menu_show (f, xpos, ypos, for_click, - keymaps, title, &error_name); - else -#endif -#if defined HAVE_NS - if (FRAME_NS_P (f)) - selection = ns_menu_show (f, xpos, ypos, for_click, - keymaps, title, &error_name); - else -#endif -#if (defined (HAVE_X_WINDOWS) || defined (MSDOS)) - if (FRAME_X_P (f) || FRAME_MSDOS_P (f)) - selection = xmenu_show (f, xpos, ypos, for_click, - keymaps, title, &error_name); - else -#endif -#ifndef MSDOS - if (FRAME_TERMCAP_P (f)) - { - ptrdiff_t count1 = SPECPDL_INDEX (); - - /* Avoid crashes if, e.g., another client will connect while we - are in a menu. */ - temporarily_switch_to_single_kboard (f); - selection = tty_menu_show (f, xpos, ypos, for_click, keymaps, title, - kbd_menu_navigation, &error_name); - unbind_to (count1, Qnil); - } -#endif + /* Display them in a menu, but not if F is the initial frame that + doesn't have its hooks set (e.g., in a batch session), because + such a frame cannot display menus. */ + if (!FRAME_INITIAL_P (f)) + selection = FRAME_TERMINAL (f)->menu_show_hook (f, xpos, ypos, menuflags, + title, &error_name); #ifdef HAVE_NS unbind_to (specpdl_count, Qnil); @@ -1474,6 +1451,38 @@ no quit occurs and `x-popup-menu' returns nil. */) return selection; } +/* If F's terminal is not capable of displaying a popup dialog, + emulate it with a menu. */ + +static Lisp_Object +emulate_dialog_with_menu (struct frame *f, Lisp_Object contents) +{ + Lisp_Object x, y, frame, newpos, prompt = Fcar (contents); + int x_coord, y_coord; + + if (FRAME_WINDOW_P (f)) + { + x_coord = FRAME_PIXEL_WIDTH (f); + y_coord = FRAME_PIXEL_HEIGHT (f); + } + else + { + x_coord = FRAME_COLS (f); + /* Center the title at frame middle. (TTY menus have + their upper-left corner at the given position.) */ + if (STRINGP (prompt)) + x_coord -= SCHARS (prompt); + y_coord = FRAME_TOTAL_LINES (f); + } + + XSETFRAME (frame, f); + XSETINT (x, x_coord / 2); + XSETINT (y, y_coord / 2); + newpos = list2 (list2 (x, y), frame); + + return Fx_popup_menu (newpos, list2 (prompt, contents)); +} + DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, doc: /* Pop up a dialog box and return user's selection. POSITION specifies which frame to use. @@ -1506,24 +1515,7 @@ for instance using the window manager, then this produces a quit and if (EQ (position, Qt) || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) || EQ (XCAR (position), Qtool_bar)))) - { -#if 0 /* Using the frame the mouse is on may not be right. */ - /* Use the mouse's current position. */ - struct frame *new_f = SELECTED_FRAME (); - Lisp_Object bar_window; - enum scroll_bar_part part; - Time time; - Lisp_Object x, y; - - (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time); - - if (new_f != 0) - XSETFRAME (window, new_f); - else - window = selected_window; -#endif - window = selected_window; - } + window = selected_window; else if (CONSP (position)) { Lisp_Object tem = XCAR (position); @@ -1570,51 +1562,21 @@ for instance using the window manager, then this produces a quit and string contents, because Fredisplay may GC and relocate them. */ Fredisplay (Qt); -#if defined USE_X_TOOLKIT || defined USE_GTK - if (FRAME_WINDOW_P (f)) - return xw_popup_dialog (f, header, contents); -#endif -#ifdef HAVE_NTGUI - if (FRAME_W32_P (f)) + /* Display the popup dialog by a terminal-specific hook ... */ + if (FRAME_TERMINAL (f)->popup_dialog_hook) { - Lisp_Object selection = w32_popup_dialog (f, header, contents); - + Lisp_Object selection + = FRAME_TERMINAL (f)->popup_dialog_hook (f, header, contents); +#ifdef HAVE_NTGUI + /* NTGUI supports only simple dialogs with Yes/No choices. For + other dialogs, it returns the symbol 'unsupported--w32-dialog', + as a signal for the caller to fall back to the emulation code. */ if (!EQ (selection, Qunsupported__w32_dialog)) +#endif return selection; } -#endif -#ifdef HAVE_NS - if (FRAME_NS_P (f)) - return ns_popup_dialog (position, header, contents); -#endif - /* Display a menu with these alternatives - in the middle of frame F. */ - { - Lisp_Object x, y, frame, newpos, prompt; - int x_coord, y_coord; - - prompt = Fcar (contents); - if (FRAME_WINDOW_P (f)) - { - x_coord = FRAME_PIXEL_WIDTH (f); - y_coord = FRAME_PIXEL_HEIGHT (f); - } - else - { - x_coord = FRAME_COLS (f); - /* Center the title at frame middle. (TTY menus have their - upper-left corner at the given position.) */ - if (STRINGP (prompt)) - x_coord -= SCHARS (prompt); - y_coord = FRAME_LINES (f); - } - XSETFRAME (frame, f); - XSETINT (x, x_coord / 2); - XSETINT (y, y_coord / 2); - newpos = list2 (list2 (x, y), frame); - - return Fx_popup_menu (newpos, list2 (prompt, contents)); - } + /* ... or emulate it with a menu. */ + return emulate_dialog_with_menu (f, contents); } void diff --git a/src/menu.h b/src/menu.h index 429dcfa6221..4dd7f17dca6 100644 --- a/src/menu.h +++ b/src/menu.h @@ -20,14 +20,19 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define MENU_H #include "systime.h" /* for Time */ +#include "../lwlib/lwlib-widget.h" #ifdef HAVE_NTGUI extern Lisp_Object Qunsupported__w32_dialog; #endif -extern void x_set_menu_bar_lines (struct frame *f, - Lisp_Object value, - Lisp_Object oldval); +/* Bit fields used by terminal-specific menu_show_hook. */ + +enum { + MENU_KEYMAPS = 0x1, + MENU_FOR_CLICK = 0x2, + MENU_KBD_NAVIGATION = 0x4 +}; extern void init_menu_items (void); extern void finish_menu_items (void) ATTRIBUTE_CONST; @@ -41,21 +46,23 @@ extern void free_menubar_widget_value_tree (widget_value *); extern void update_submenu_strings (widget_value *); extern void find_and_call_menu_selection (struct frame *, int, Lisp_Object, void *); -extern widget_value *xmalloc_widget_value (void); +extern widget_value *make_widget_value (const char *, char *, bool, Lisp_Object); extern widget_value *digest_single_submenu (int, int, bool); #endif -#ifdef HAVE_X_WINDOWS -extern void mouse_position_for_popup (struct frame *f, int *x, int *y); +#if defined (HAVE_X_WINDOWS) || defined (MSDOS) +extern Lisp_Object x_menu_show (struct frame *, int, int, int, + Lisp_Object, const char **); #endif - -extern Lisp_Object w32_menu_show (struct frame *, int, int, int, int, +#ifdef HAVE_NTGUI +extern Lisp_Object w32_menu_show (struct frame *, int, int, int, Lisp_Object, const char **); -extern Lisp_Object ns_menu_show (struct frame *, int, int, bool, bool, +#endif +#ifdef HAVE_NS +extern Lisp_Object ns_menu_show (struct frame *, int, int, int, Lisp_Object, const char **); -extern Lisp_Object xmenu_show (struct frame *, int, int, bool, bool, - Lisp_Object, const char **); -extern Lisp_Object tty_menu_show (struct frame *, int, int, bool, bool, - Lisp_Object, bool, const char **); +#endif +extern Lisp_Object tty_menu_show (struct frame *, int, int, int, + Lisp_Object, const char **); extern ptrdiff_t menu_item_width (const unsigned char *); #endif /* MENU_H */ diff --git a/src/minibuf.c b/src/minibuf.c index c3fcbeb59c7..0b455157d52 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -22,6 +22,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <errno.h> #include <stdio.h> +#include <binary-io.h> + #include "lisp.h" #include "commands.h" #include "character.h" @@ -34,6 +36,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "intervals.h" #include "keymap.h" #include "termhooks.h" +#include "systty.h" /* List of buffers for use as minibuffers. The first element of the list is used for the outermost minibuffer @@ -224,6 +227,22 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, char *line; Lisp_Object val; int c; + unsigned char hide_char = 0; + struct emacs_tty etty; + bool etty_valid; + + /* Check, whether we need to suppress echoing. */ + if (CHARACTERP (Vread_hide_char)) + hide_char = XFASTINT (Vread_hide_char); + + /* Manipulate tty. */ + if (hide_char) + { + etty_valid = emacs_get_tty (fileno (stdin), &etty) == 0; + if (etty_valid) + set_binary_mode (fileno (stdin), O_BINARY); + suppress_echo_on_tty (fileno (stdin)); + } fprintf (stdout, "%s", SDATA (prompt)); fflush (stdout); @@ -233,7 +252,7 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, len = 0; line = xmalloc (size); - while ((c = getchar ()) != '\n') + while ((c = getchar ()) != '\n' && c != '\r') { if (c == EOF) { @@ -242,6 +261,8 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, } else { + if (hide_char) + fprintf (stdout, "%c", hide_char); if (len == size) { if (STRING_BYTES_BOUND / 2 < size) @@ -253,7 +274,18 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, } } - if (len || c == '\n') + /* Reset tty. */ + if (hide_char) + { + fprintf (stdout, "\n"); + if (etty_valid) + { + emacs_set_tty (fileno (stdin), &etty, 0); + set_binary_mode (fileno (stdin), O_TEXT); + } + } + + if (len || c == '\n' || c == '\r') { val = make_string (line, len); xfree (line); @@ -619,6 +651,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, set_window_buffer (minibuf_window, Fcurrent_buffer (), 0, 0); Fselect_window (minibuf_window, Qnil); XWINDOW (minibuf_window)->hscroll = 0; + XWINDOW (minibuf_window)->suspend_auto_hscroll = 0; Fmake_local_variable (Qprint_escape_newlines); print_escape_newlines = 1; @@ -1090,7 +1123,7 @@ If `read-buffer-function' is non-nil, this works by calling it as a function, instead of the usual behavior. */) (Lisp_Object prompt, Lisp_Object def, Lisp_Object require_match) { - Lisp_Object args[4], result; + Lisp_Object result; char *s; ptrdiff_t len; ptrdiff_t count = SPECPDL_INDEX (); @@ -1124,10 +1157,10 @@ function, instead of the usual behavior. */) STRING_MULTIBYTE (prompt)); } - args[0] = build_string ("%s (default %s): "); - args[1] = prompt; - args[2] = CONSP (def) ? XCAR (def) : def; - prompt = Fformat (3, args); + AUTO_STRING (format, "%s (default %s): "); + prompt = Fformat (3, ((Lisp_Object []) + {format, prompt, + CONSP (def) ? XCAR (def) : def})); } result = Fcompleting_read (prompt, intern ("internal-complete-buffer"), @@ -1135,13 +1168,8 @@ function, instead of the usual behavior. */) Qbuffer_name_history, def, Qnil); } else - { - args[0] = Vread_buffer_function; - args[1] = prompt; - args[2] = def; - args[3] = require_match; - result = Ffuncall (4, args); - } + result = Ffuncall (4, ((Lisp_Object []) + { Vread_buffer_function, prompt, def, require_match })); return unbind_to (count, result); } @@ -1970,7 +1998,7 @@ A value of t means no truncation. This variable only affects history lists that don't specify their own maximum lengths. Setting the `history-length' property of a history variable overrides this default. */); - XSETFASTINT (Vhistory_length, 30); + XSETFASTINT (Vhistory_length, 100); DEFVAR_BOOL ("history-delete-duplicates", history_delete_duplicates, doc: /* Non-nil means to delete duplicates in history. @@ -2079,6 +2107,12 @@ properties. */); initialization-order problems. */ Vminibuffer_prompt_properties = list2 (intern_c_string ("read-only"), Qt); + DEFVAR_LISP ("read-hide-char", Vread_hide_char, + doc: /* Whether to hide input characters in noninteractive mode. +It must be a character, which will be used to mask the input +characters. This variable should never be set globally. */); + Vread_hide_char = Qnil; + defsubr (&Sactive_minibuffer_window); defsubr (&Sset_minibuffer_window); defsubr (&Sread_from_minibuffer); diff --git a/src/msdos.c b/src/msdos.c index 010a0a3746c..14c2624114d 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -71,6 +71,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "coding.h" #include "disptab.h" #include "window.h" +#include "menu.h" #include "buffer.h" #include "commands.h" #include "blockinput.h" @@ -566,7 +567,7 @@ dos_set_window_size (int *rows, int *cols) }; int i = 0; - while (i < sizeof (std_dimension) / sizeof (std_dimension[0])) + while (i < ARRAYELTS (std_dimension)) { if (std_dimension[i].need_vga <= have_vga && std_dimension[i].rows >= *rows) @@ -1791,7 +1792,7 @@ internal_terminal_init (void) } Vinitial_window_system = Qpc; - Vwindow_system_version = make_number (24); /* RE Emacs version */ + Vwindow_system_version = make_number (25); /* RE Emacs version */ tty->terminal->type = output_msdos_raw; /* If Emacs was dumped on DOS/V machine, forget the stale VRAM @@ -1863,6 +1864,7 @@ initialize_msdos_display (struct terminal *term) term->update_end_hook = IT_update_end; term->frame_up_to_date_hook = IT_frame_up_to_date; term->mouse_position_hook = 0; /* set later by dos_ttraw */ + term->menu_show_hook = x_menu_show; term->frame_rehighlight_hook = 0; term->frame_raise_lower_hook = 0; term->set_vertical_scroll_bar_hook = 0; @@ -3455,7 +3457,7 @@ init_environment (int argc, char **argv, int skip_args) static const char * const tempdirs[] = { "$TMPDIR", "$TEMP", "$TMP", "c:/" }; - const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]); + const int imax = ARRAYELTS (tempdirs); /* Make sure they have a usable $TMPDIR. Many Emacs functions use temporary files and assume "/tmp" if $TMPDIR is unset, which @@ -4015,103 +4017,6 @@ unsetenv (const char *name) #endif -#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2 - -/* Augment DJGPP library POSIX signal functions. This is needed - as of DJGPP v2.01, but might be in the library in later releases. */ - -#include <libc/bss.h> - -/* A counter to know when to re-initialize the static sets. */ -static int sigprocmask_count = -1; - -/* Which signals are currently blocked (initially none). */ -static sigset_t current_mask; - -/* Which signals are pending (initially none). */ -static sigset_t msdos_pending_signals; - -/* Previous handlers to restore when the blocked signals are unblocked. */ -typedef void (*sighandler_t)(int); -static sighandler_t prev_handlers[320]; - -/* A signal handler which just records that a signal occurred - (it will be raised later, if and when the signal is unblocked). */ -static void -sig_suspender (int signo) -{ - sigaddset (&msdos_pending_signals, signo); -} - -int -sigprocmask (int how, const sigset_t *new_set, sigset_t *old_set) -{ - int signo; - sigset_t new_mask; - - /* If called for the first time, initialize. */ - if (sigprocmask_count != __bss_count) - { - sigprocmask_count = __bss_count; - sigemptyset (&msdos_pending_signals); - sigemptyset (¤t_mask); - for (signo = 0; signo < 320; signo++) - prev_handlers[signo] = SIG_ERR; - } - - if (old_set) - *old_set = current_mask; - - if (new_set == 0) - return 0; - - if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) - { - errno = EINVAL; - return -1; - } - - sigemptyset (&new_mask); - - /* DJGPP supports upto 320 signals. */ - for (signo = 0; signo < 320; signo++) - { - if (sigismember (¤t_mask, signo)) - sigaddset (&new_mask, signo); - else if (sigismember (new_set, signo) && how != SIG_UNBLOCK) - { - sigaddset (&new_mask, signo); - - /* SIGKILL is silently ignored, as on other platforms. */ - if (signo != SIGKILL && prev_handlers[signo] == SIG_ERR) - prev_handlers[signo] = signal (signo, sig_suspender); - } - if (( how == SIG_UNBLOCK - && sigismember (&new_mask, signo) - && sigismember (new_set, signo)) - || (how == SIG_SETMASK - && sigismember (&new_mask, signo) - && !sigismember (new_set, signo))) - { - sigdelset (&new_mask, signo); - if (prev_handlers[signo] != SIG_ERR) - { - signal (signo, prev_handlers[signo]); - prev_handlers[signo] = SIG_ERR; - } - if (sigismember (&msdos_pending_signals, signo)) - { - sigdelset (&msdos_pending_signals, signo); - raise (signo); - } - } - } - current_mask = new_mask; - return 0; -} - -#endif /* not __DJGPP_MINOR__ < 2 */ - #ifndef HAVE_SELECT #include "sysselect.h" @@ -4258,15 +4163,7 @@ msdos_abort (void) dos_ttcooked (); ScreenSetCursor (10, 0); cputs ("\r\n\nEmacs aborted!\r\n"); -#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2 - if (screen_virtual_segment) - dosv_refresh_virtual_screen (2 * 10 * screen_size_X, 4 * screen_size_X); - /* Generate traceback, so we could tell whodunit. */ - signal (SIGINT, SIG_DFL); - __asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception"); -#else /* __DJGPP_MINOR__ >= 2 */ raise (SIGABRT); -#endif /* __DJGPP_MINOR__ >= 2 */ exit (2); } diff --git a/src/nsfns.m b/src/nsfns.m index 58746aed9fa..a93b2724403 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -46,10 +46,8 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #ifdef NS_IMPL_COCOA #include <IOKit/graphics/IOGraphicsLib.h> -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 #include "macfont.h" #endif -#endif #if 0 int fns_trace_num = 1; @@ -73,15 +71,15 @@ extern Lisp_Object Qicon_type; extern Lisp_Object Qicon_name; extern Lisp_Object Qicon_left; extern Lisp_Object Qicon_top; -extern Lisp_Object Qleft; -extern Lisp_Object Qright; extern Lisp_Object Qtop; extern Lisp_Object Qdisplay; extern Lisp_Object Qvertical_scroll_bars; +extern Lisp_Object Qhorizontal_scroll_bars; extern Lisp_Object Qauto_raise; extern Lisp_Object Qauto_lower; extern Lisp_Object Qbox; extern Lisp_Object Qscroll_bar_width; +extern Lisp_Object Qscroll_bar_height; extern Lisp_Object Qx_resource_name; extern Lisp_Object Qface_set_after_frame_default; extern Lisp_Object Qunderline, Qundefined; @@ -135,7 +133,7 @@ check_ns_display_info (Lisp_Object object) } else if (TERMINALP (object)) { - struct terminal *t = get_terminal (object, 1); + struct terminal *t = decode_live_terminal (object); if (t->type != output_ns) error ("Terminal %d is not a Nextstep display", t->id); @@ -197,7 +195,7 @@ ns_display_info_for_name (Lisp_Object name) static NSString * ns_filename_from_panel (NSSavePanel *panel) { -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA NSURL *url = [panel URL]; NSString *str = [url path]; return str; @@ -209,7 +207,7 @@ ns_filename_from_panel (NSSavePanel *panel) static NSString * ns_directory_from_panel (NSSavePanel *panel) { -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA NSURL *url = [panel directoryURL]; NSString *str = [url path]; return str; @@ -707,6 +705,26 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } +void +x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + int old_width = FRAME_INTERNAL_BORDER_WIDTH (f); + + CHECK_TYPE_RANGED_INTEGER (int, arg); + FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg); + if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0) + FRAME_INTERNAL_BORDER_WIDTH (f) = 0; + + if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width) + return; + + if (FRAME_X_WINDOW (f) != 0) + adjust_frame_size (f, -1, -1, 3, 0); + + SET_FRAME_GARBAGED (f); +} + + static void ns_implicitly_set_icon_type (struct frame *f) { @@ -873,12 +891,16 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) static Lisp_Object ns_appkit_version_str (void) { - char tmp[80]; + char tmp[256]; #ifdef NS_IMPL_GNUSTEP sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION)); #elif defined (NS_IMPL_COCOA) - sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber); + NSString *osversion + = [[NSProcessInfo processInfo] operatingSystemVersionString]; + sprintf(tmp, "appkit-%.2f %s", + NSAppKitVersionNumber, + [osversion UTF8String]); #else tmp = "ns-unknown"; #endif @@ -952,17 +974,19 @@ frame_parm_handler ns_frame_parm_handlers[] = x_set_mouse_color, x_explicitly_set_name, x_set_scroll_bar_width, /* generic OK */ + x_set_scroll_bar_height, /* generic OK */ x_set_title, x_set_unsplittable, /* generic OK */ x_set_vertical_scroll_bars, /* generic OK */ + x_set_horizontal_scroll_bars, /* generic OK */ x_set_visibility, /* generic OK */ x_set_tool_bar_lines, 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */ 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */ x_set_screen_gamma, /* generic OK */ x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ - x_set_fringe_width, /* generic OK */ - x_set_fringe_width, /* generic OK */ + x_set_left_fringe, /* generic OK */ + x_set_right_fringe, /* generic OK */ 0, /* x_set_wait_for_wm, will ignore */ x_set_fullscreen, /* generic OK */ x_set_font_backend, /* generic OK */ @@ -1024,7 +1048,7 @@ get_geometry_from_preferences (struct ns_display_info *dpyinfo, }; int i; - for (i = 0; i < sizeof (r)/sizeof (r[0]); ++i) + for (i = 0; i < ARRAYELTS (r); ++i) { if (NILP (Fassq (r[i].tem, parms))) { @@ -1171,13 +1195,10 @@ This function is an internal primitive--use `make-frame' instead. */) block_input (); #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - if (CTGetCoreTextVersion != NULL - && CTGetCoreTextVersion () >= kCTVersionNumber10_5) mac_register_font_driver (f); +#else + register_font_driver (&nsfont_driver, f); #endif -#endif - register_font_driver (&nsfont_driver, f); x_default_parameter (f, parms, Qfont_backend, Qnil, "fontBackend", "FontBackend", RES_TYPE_STRING); @@ -1206,7 +1227,7 @@ This function is an internal primitive--use `make-frame' instead. */) "internalBorderWidth", "InternalBorderWidth", RES_TYPE_NUMBER); - /* default scrollbars on right on Mac */ + /* default vertical scrollbars on right on Mac */ { Lisp_Object spos #ifdef NS_IMPL_GNUSTEP @@ -1218,6 +1239,9 @@ This function is an internal primitive--use `make-frame' instead. */) "verticalScrollBars", "VerticalScrollBars", RES_TYPE_SYMBOL); } + x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, + "horizontalScrollBars", "HorizontalScrollBars", + RES_TYPE_SYMBOL); x_default_parameter (f, parms, Qforeground_color, build_string ("Black"), "foreground", "Foreground", RES_TYPE_STRING); x_default_parameter (f, parms, Qbackground_color, build_string ("White"), @@ -1238,11 +1262,8 @@ This function is an internal primitive--use `make-frame' instead. */) init_frame_faces (f); /* Read comment about this code in corresponding place in xfns.c. */ - width = FRAME_TEXT_WIDTH (f); - height = FRAME_TEXT_HEIGHT (f); - FRAME_TEXT_HEIGHT (f) = 0; - SET_FRAME_WIDTH (f, 0); - change_frame_size (f, width, height, 1, 0, 0, 1); + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1); /* The resources controlling the menu-bar and tool-bar are processed specially at startup, and reflected in the mode @@ -1278,6 +1299,8 @@ This function is an internal primitive--use `make-frame' instead. */) f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor]; FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor = [NSCursor arrowCursor]; + FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor + = [NSCursor arrowCursor]; f->output_data.ns->current_pointer = f->output_data.ns->text_cursor; [[EmacsView alloc] initFrameFromEmacs: f]; @@ -1303,16 +1326,18 @@ This function is an internal primitive--use `make-frame' instead. */) x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qscroll_bar_height, Qnil, + "scrollBarHeight", "ScrollBarHeight", + RES_TYPE_NUMBER); x_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); x_default_parameter (f, parms, Qfullscreen, Qnil, "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); - width = FRAME_TEXT_WIDTH (f); - height = FRAME_TEXT_HEIGHT (f); - FRAME_TEXT_HEIGHT (f) = 0; - SET_FRAME_WIDTH (f, 0); - change_frame_size (f, width, height, 1, 0, 0, 1); + /* Consider frame official, now. */ + f->official = true; + + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1); if (! f->output_data.ns->explicit_parent) { @@ -1384,11 +1409,11 @@ DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel, id fm = [NSFontManager sharedFontManager]; struct font *font = f->output_data.ns->font; NSFont *nsfont; - if (EQ (font->driver->type, Qns)) - nsfont = ((struct nsfont_info *)font)->nsfont; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - else - nsfont = (NSFont *) macfont_get_nsctfont (font); +#ifdef NS_IMPL_GNUSTEP + nsfont = ((struct nsfont_info *)font)->nsfont; +#endif +#ifdef NS_IMPL_COCOA + nsfont = (NSFont *) macfont_get_nsctfont (font); #endif [fm setSelectedFont: nsfont isMultiple: NO]; [fm orderFrontFontPanel: NSApp]; @@ -1410,8 +1435,7 @@ static struct { id panel; BOOL ret; -#if ! defined (NS_IMPL_COCOA) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_GNUSTEP NSString *dirS, *initS; BOOL no_types; #endif @@ -1421,8 +1445,7 @@ void ns_run_file_dialog (void) { if (ns_fd_data.panel == nil) return; -#if defined (NS_IMPL_COCOA) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA ns_fd_data.ret = [ns_fd_data.panel runModal]; #else if (ns_fd_data.no_types) @@ -1502,8 +1525,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) block_input (); ns_fd_data.panel = panel; ns_fd_data.ret = NO; -#if defined (NS_IMPL_COCOA) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA if (! NILP (mustmatch) || ! NILP (dir_only_p)) [panel setAllowedFileTypes: nil]; if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]]; @@ -1963,7 +1985,7 @@ DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0, doc: /* List available Nextstep services by querying NSApp. */) (void) { -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA /* You can't get services like this in 10.6+. */ return Qnil; #else @@ -2096,7 +2118,6 @@ ns_do_applescript (Lisp_Object script, Lisp_Object *result) returnDescriptor = [scriptObject executeAndReturnError: &errorDict]; [scriptObject release]; - *result = Qnil; if (returnDescriptor != NULL) @@ -2157,6 +2178,7 @@ In case the execution fails, an error is signaled. */) Lisp_Object result; int status; NSEvent *nxev; + struct input_event ev; CHECK_STRING (script); check_window_system (NULL); @@ -2184,8 +2206,10 @@ In case the execution fails, an error is signaled. */) // If there are other events, the event loop may exit. Keep running // until the script has been handled. */ + ns_init_events (&ev); while (! NILP (as_script)) [NSApp run]; + ns_finish_events (); status = as_status; as_status = 0; @@ -2225,6 +2249,15 @@ x_set_scroll_bar_default_width (struct frame *f) wid - 1) / wid; } +void +x_set_scroll_bar_default_height (struct frame *f) +{ + int height = FRAME_LINE_HEIGHT (f); + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = NS_SCROLL_BAR_WIDTH_DEFAULT; + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + + height - 1) / height; +} + /* terms impl this instead of x-get-resource directly */ char * x_get_string_resource (XrmDatabase rdb, const char *name, const char *class) @@ -2508,7 +2541,7 @@ the attributes: Internal use only, use `display-monitor-attributes-list' instead. */) (Lisp_Object terminal) { - struct terminal *term = get_terminal (terminal, 1); + struct terminal *term = decode_live_terminal (terminal); NSArray *screens; NSUInteger i, n_monitors; struct MonitorInfo *monitors; diff --git a/src/nsfont.m b/src/nsfont.m index 14e24c270e8..13c7b0bce2c 100644 --- a/src/nsfont.m +++ b/src/nsfont.m @@ -627,8 +627,8 @@ static Lisp_Object nsfont_open (struct frame *f, Lisp_Object font_entity, static void nsfont_close (struct font *font); static int nsfont_has_char (Lisp_Object entity, int c); static unsigned int nsfont_encode_char (struct font *font, int c); -static int nsfont_text_extents (struct font *font, unsigned int *code, - int nglyphs, struct font_metrics *metrics); +static void nsfont_text_extents (struct font *font, unsigned int *code, + int nglyphs, struct font_metrics *metrics); static int nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background); @@ -649,7 +649,7 @@ struct font_driver nsfont_driver = nsfont_encode_char, nsfont_text_extents, nsfont_draw, - /* excluded: get_bitmap, free_bitmap, get_outline, free_outline, + /* excluded: get_bitmap, free_bitmap, anchor_point, otf_capability, otf_driver, start_for_frame, end_for_frame, shape */ }; @@ -830,9 +830,6 @@ nsfont_open (struct frame *f, Lisp_Object font_entity, int pixel_size) font->baseline_offset = 0; font->relative_compose = 0; - font->props[FONT_FORMAT_INDEX] = Qns; - font->props[FONT_FILE_INDEX] = Qnil; - { const char *fontName = [[nsfont fontName] UTF8String]; @@ -945,6 +942,8 @@ nsfont_close (struct font *font) xfree (font_info->glyphs[i]); xfree (font_info->metrics[i]); } + xfree (font_info->glyphs); + xfree (font_info->metrics); [font_info->nsfont release]; #ifdef NS_IMPL_COCOA CGFontRelease (font_info->cgfont); @@ -989,9 +988,9 @@ nsfont_encode_char (struct font *font, int c) /* Perform the size computation of glyphs of FONT and fill in members of METRICS. The glyphs are specified by their glyph codes in CODE (length NGLYPHS). */ -static int -nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, - struct font_metrics *metrics) +static void +nsfont_text_extents (struct font *font, unsigned int *code, + int nglyphs, struct font_metrics *metrics) { struct nsfont_info *font_info = (struct nsfont_info *)font; struct font_metrics *pcm; @@ -1001,7 +1000,7 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, memset (metrics, 0, sizeof (struct font_metrics)); - for (i =0; i<nglyphs; i++) + for (i = 0; i < nglyphs; i++) { /* get metrics for this glyph, filling cache if need be */ /* TODO: get metrics for whole string from an NSLayoutManager @@ -1025,8 +1024,6 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, } metrics->width = totalWidth; - - return totalWidth; /* not specified in doc, but xfont.c does it */ } @@ -1037,14 +1034,18 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, static int nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background) -/* NOTE: focus and clip must be set - also, currently assumed (true in nsterm.m call) from ==0, to ==nchars */ +/* NOTE: focus and clip must be set */ { static unsigned char cbuf[1024]; unsigned char *c = cbuf; #ifdef NS_IMPL_GNUSTEP +#if GNUSTEP_GUI_MAJOR_VERSION > 0 || GNUSTEP_GUI_MINOR_VERSION > 22 + static CGFloat advances[1024]; + CGFloat *adv = advances; +#else static float advances[1024]; float *adv = advances; +#endif #else static CGSize advances[1024]; CGSize *adv = advances; @@ -1056,7 +1057,6 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, unsigned short *t = s->char2b; int i, len, flags; char isComposite = s->first_glyph->type == COMPOSITE_GLYPH; - int end = isComposite ? s->cmp_to : s->nchars; block_input (); @@ -1098,8 +1098,8 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, int cwidth, twidth = 0; int hi, lo; /* FIXME: composition: no vertical displacement is considered. */ - t += s->cmp_from; /* advance into composition */ - for (i = s->cmp_from; i < end; i++, t++) + t += from; /* advance into composition */ + for (i = from; i < to; i++, t++) { hi = (*t & 0xFF00) >> 8; lo = *t & 0x00FF; @@ -1193,7 +1193,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, /* set up for character rendering */ - r.origin.y = s->ybase; + r.origin.y = y; col = (NS_FACE_FOREGROUND (face) != 0 ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f) @@ -1275,13 +1275,13 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, [col set]; CGContextSetTextPosition (gcontext, r.origin.x, r.origin.y); - CGContextShowGlyphsWithAdvances (gcontext, s->char2b + s->cmp_from, + CGContextShowGlyphsWithAdvances (gcontext, s->char2b + from, advances, len); if (face->overstrike) { CGContextSetTextPosition (gcontext, r.origin.x+0.5, r.origin.y); - CGContextShowGlyphsWithAdvances (gcontext, s->char2b + s->cmp_from, + CGContextShowGlyphsWithAdvances (gcontext, s->char2b + from, advances, len); } diff --git a/src/nsgui.h b/src/nsgui.h index 5935531fa48..0f963f69e2b 100644 --- a/src/nsgui.h +++ b/src/nsgui.h @@ -48,11 +48,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #undef _GL_VERIFY_H #include <verify.h> -/* menu-related */ -#define free_widget_value(wv) xfree (wv) -#define malloc_widget_value() ((widget_value *) memset (xmalloc \ - (sizeof (widget_value)), 0, sizeof (widget_value))) - /* Emulate XCharStruct. */ typedef struct _XCharStruct { @@ -73,10 +68,10 @@ typedef unichar XChar2b; (*(chp) = ((XChar2b)((((b1) & 0x00ff) << 8) | ((b2) & 0x00ff)))) #define XCHAR2B_BYTE1(chp) \ - (((*chp) & 0xff00) >> 8) + ((*(chp) & 0xff00) >> 8) #define XCHAR2B_BYTE2(chp) \ - ((*chp) & 0x00ff) + (*(chp) & 0x00ff) /* XXX: xfaces requires these structures, but the question is are we diff --git a/src/nsimage.m b/src/nsimage.m index 6b68072b87a..71e5f8aa5c6 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -188,7 +188,7 @@ static EmacsImage *ImageList = nil; image = [[EmacsImage alloc] initByReferencingFile: [NSString stringWithUTF8String: SSDATA (found)]]; -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA imgRep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]]; #else imgRep = [image bestRepresentationForDevice: nil]; diff --git a/src/nsmenu.m b/src/nsmenu.m index 24842241f37..a90cb970874 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -266,12 +266,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) /* parse stage 2: insert into lucid 'widget_value' structures [comments in other terms say not to evaluate lisp code here] */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; i < 4*n; i += 4) @@ -378,12 +374,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) int n; Lisp_Object string; - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; /* Make widget-value tree w/ just the top level menu bar strings */ @@ -439,12 +431,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) memcpy (previous_strings[i/4], SDATA (string), min (10, SBYTES (string) + 1)); - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; wv->call_data = (void *) (intptr_t) (-1); #ifdef NS_IMPL_COCOA @@ -504,11 +492,9 @@ void x_activate_menubar (struct frame *f) { #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 ns_update_menubar (f, true, nil); ns_check_pending_open_menu (); #endif -#endif } @@ -554,23 +540,14 @@ x_activate_menubar (struct frame *f) } #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 -extern NSString *NSMenuDidBeginTrackingNotification; -#endif -#endif - -#ifdef NS_IMPL_COCOA -(void)trackingNotification:(NSNotification *)notification { /* Update menu in menuNeedsUpdate only while tracking menus. */ trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification ? 1 : 0); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (! trackingMenu) ns_check_menu_open (nil); -#endif } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - (void)menuWillOpen:(NSMenu *)menu { ++trackingMenu; @@ -591,7 +568,6 @@ extern NSString *NSMenuDidBeginTrackingNotification; { --trackingMenu; } -#endif /* OSX >= 10.5 */ #endif /* NS_IMPL_COCOA */ @@ -620,8 +596,7 @@ extern NSString *NSMenuDidBeginTrackingNotification; if (trackingMenu == 0) return; /*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */ -#if (! defined (NS_IMPL_COCOA) \ - || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) +#ifdef NS_IMPL_GNUSTEP /* Don't know how to do this for anything other than OSX >= 10.5 This is wrong, as it might run Lisp code in the event loop. */ ns_update_menubar (frame, true, self); @@ -718,9 +693,7 @@ extern NSString *NSMenuDidBeginTrackingNotification; { NSMenuItem *item = [self itemAtIndex: n]; NSString *title = [item title]; - if (([title length] == 0 /* OSX 10.5 */ - || [ns_app_name isEqualToString: title] /* from 10.6 on */ - || [@"Apple" isEqualToString: title]) /* older */ + if ([ns_app_name isEqualToString: title] && ![item isSeparatorItem]) continue; [self removeItemAtIndex: n]; @@ -824,7 +797,7 @@ extern NSString *NSMenuDidBeginTrackingNotification; ========================================================================== */ Lisp_Object -ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, +ns_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error) { EmacsMenu *pmenu; @@ -832,18 +805,15 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, Lisp_Object tem; ptrdiff_t specpdl_count = SPECPDL_INDEX (); widget_value *wv, *first_wv = 0; + bool keymaps = (menuflags & MENU_KEYMAPS); block_input (); p.x = x; p.y = y; /* now parse stage 2 as in ns_update_menubar */ - wv = xmalloc_widget_value (); - wv->name = "contextmenu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("contextmenu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; #if 0 @@ -914,18 +884,14 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, with its items as a submenu beneath it. */ if (!keymaps && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = pane_string; if (keymaps && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -963,20 +929,18 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, } #endif /* not HAVE_MULTILINGUAL_MENU */ - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* If this item has a null value, make the call_data null so that it won't display a box when the mouse is on it. */ wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -989,11 +953,6 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -1004,24 +963,19 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil); /* Maybe replace this separator with a bitmap or owner-draw item so that it looks better. Having two separators looks odd. */ - wv_sep->name = "--"; wv_sep->next = first_wv->contents; - wv_sep->help = Qnil; #ifndef HAVE_MULTILINGUAL_MENU if (STRING_MULTIBYTE (title)) title = ENCODE_MENU_STRING (title); #endif - - wv_title->name = SSDATA (title); - wv_title->enabled = NO; + wv_title = make_widget_value (SSDATA (title), NULL, false, Qnil); wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep; first_wv->contents = wv_title; } @@ -1183,7 +1137,10 @@ update_frame_tool_bar (struct frame *f) FRAME_TOOLBAR_HEIGHT (f) = 0; if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0) + { + view->wait_for_tool_bar = NO; [view setNeedsDisplay: YES]; + } unblock_input (); } @@ -1459,11 +1416,10 @@ pop_down_menu (void *arg) Lisp_Object -ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents) +ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) { id dialog; Lisp_Object window, tem, title; - struct frame *f; NSPoint p; BOOL isQ; NSAutoreleasePool *pool; @@ -1472,41 +1428,6 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents) isQ = NILP (header); - if (EQ (position, Qt) - || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) - { - window = selected_window; - } - else if (CONSP (position)) - { - Lisp_Object tem; - tem = Fcar (position); - if (XTYPE (tem) == Lisp_Cons) - window = Fcar (Fcdr (position)); - else - { - tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ - window = Fcar (tem); /* POSN_WINDOW (tem) */ - } - } - else if (WINDOWP (position) || FRAMEP (position)) - { - window = position; - } - else - window = Qnil; - - if (FRAMEP (window)) - f = XFRAME (window); - else if (WINDOWP (window)) - { - CHECK_LIVE_WINDOW (window); - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - } - else - CHECK_WINDOW (window); - check_window_system (f); p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2; diff --git a/src/nsselect.m b/src/nsselect.m index 038849c0aed..3712ba064e7 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -328,19 +328,14 @@ ns_string_to_pasteboard (id pb, Lisp_Object str) ========================================================================== */ -DEFUN ("x-own-selection-internal", Fx_own_selection_internal, - Sx_own_selection_internal, 2, 3, 0, +DEFUN ("ns-own-selection-internal", Fns_own_selection_internal, + Sns_own_selection_internal, 2, 2, 0, doc: /* Assert an X selection of type SELECTION and value VALUE. SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. \(Those are literal upper-case symbol names, since that's what X expects.) VALUE is typically a string, or a cons of two markers, but may be -anything that the functions on `selection-converter-alist' know about. - -FRAME should be a frame that should own the selection. If omitted or -nil, it defaults to the selected frame. - -On Nextstep, FRAME is unused. */) - (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) +anything that the functions on `selection-converter-alist' know about. */) + (Lisp_Object selection, Lisp_Object value) { id pb; Lisp_Object old_value, new_value; @@ -385,21 +380,11 @@ On Nextstep, FRAME is unused. */) } -DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal, - Sx_disown_selection_internal, 1, 3, 0, +DEFUN ("ns-disown-selection-internal", Fns_disown_selection_internal, + Sns_disown_selection_internal, 1, 1, 0, doc: /* If we own the selection SELECTION, disown it. -Disowning it means there is no such selection. - -Sets the last-change time for the selection to TIME-OBJECT (by default -the time of the last event). - -TERMINAL should be a terminal object or a frame specifying the X -server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. - -On Nextstep, the TIME-OBJECT and TERMINAL arguments are unused. -On MS-DOS, all this does is return non-nil if we own the selection. */) - (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) +Disowning it means there is no such selection. */) + (Lisp_Object selection) { id pb; check_window_system (NULL); @@ -443,7 +428,7 @@ On Nextstep, TERMINAL is unused. */) } -DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p, +DEFUN ("ns-selection-owner-p", Fns_selection_owner_p, Sns_selection_owner_p, 0, 2, 0, doc: /* Whether the current Emacs process owns the given X Selection. The arg should be the name of the selection in question, typically one of @@ -507,7 +492,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */) DEFUN ("ns-get-selection-internal", Fns_get_selection_internal, Sns_get_selection_internal, 1, 1, 0, doc: /* Returns the value of SELECTION as a string. -SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. */) +SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. */) (Lisp_Object selection) { id pb; @@ -520,7 +505,7 @@ SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. */) DEFUN ("ns-store-selection-internal", Fns_store_selection_internal, Sns_store_selection_internal, 2, 2, 0, doc: /* Sets the string value of SELECTION. -SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. */) +SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. */) (Lisp_Object selection, Lisp_Object string) { id pb; @@ -546,11 +531,11 @@ syms_of_nsselect (void) QTEXT = intern_c_string ("TEXT"); staticpro (&QTEXT); QFILE_NAME = intern_c_string ("FILE_NAME"); staticpro (&QFILE_NAME); - defsubr (&Sx_disown_selection_internal); + defsubr (&Sns_disown_selection_internal); defsubr (&Sx_get_selection_internal); - defsubr (&Sx_own_selection_internal); + defsubr (&Sns_own_selection_internal); defsubr (&Sx_selection_exists_p); - defsubr (&Sx_selection_owner_p); + defsubr (&Sns_selection_owner_p); defsubr (&Sns_get_selection_internal); defsubr (&Sns_store_selection_internal); diff --git a/src/nsterm.h b/src/nsterm.h index 8c3e4e5c314..f59405fe9af 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -27,12 +27,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_NS #ifdef NS_IMPL_COCOA -#ifndef MAC_OS_X_VERSION_10_4 -#define MAC_OS_X_VERSION_10_4 1040 -#endif -#ifndef MAC_OS_X_VERSION_10_5 -#define MAC_OS_X_VERSION_10_5 1050 -#endif #ifndef MAC_OS_X_VERSION_10_6 #define MAC_OS_X_VERSION_10_6 1060 #endif @@ -58,21 +52,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ versions. On Cocoa >= 10.5, functions expect CGFloat*. Make compatible type. */ #ifdef NS_IMPL_COCOA - -#ifndef NS_HAVE_NSINTEGER -#if defined (__LP64__) && __LP64__ -typedef double CGFloat; -typedef long NSInteger; -typedef unsigned long NSUInteger; -#else -typedef float CGFloat; -typedef int NSInteger; -typedef unsigned int NSUInteger; -#endif /* not LP64 */ -#endif /* not NS_HAVE_NSINTEGER */ - typedef CGFloat EmacsCGFloat; - #elif GNUSTEP_GUI_MAJOR_VERSION > 0 || GNUSTEP_GUI_MINOR_VERSION >= 22 typedef CGFloat EmacsCGFloat; #else @@ -100,7 +80,7 @@ typedef float EmacsCGFloat; /* We override sendEvent: as a means to stop/start the event loop */ @interface EmacsApp : NSApplication { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#ifdef NS_IMPL_COCOA BOOL shouldKeepRunning; BOOL isFirst; #endif @@ -139,7 +119,7 @@ typedef float EmacsCGFloat; @class EmacsToolbar; -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA @interface EmacsView : NSView <NSTextInput, NSWindowDelegate> #else @interface EmacsView : NSView <NSTextInput> @@ -217,7 +197,7 @@ typedef float EmacsCGFloat; ========================================================================== */ -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA @interface EmacsMenu : NSMenu <NSMenuDelegate> #else @interface EmacsMenu : NSMenu @@ -249,7 +229,7 @@ typedef float EmacsCGFloat; @class EmacsImage; -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA @interface EmacsToolbar : NSToolbar <NSToolbarDelegate> #else @interface EmacsToolbar : NSToolbar @@ -305,7 +285,7 @@ typedef float EmacsCGFloat; - (void)timeout_handler: (NSTimer *)timedEntry; @end -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA @interface EmacsTooltip : NSObject <NSWindowDelegate> #else @interface EmacsTooltip : NSObject @@ -401,7 +381,7 @@ typedef float EmacsCGFloat; CGFloat last_mouse_offset; float min_portion; int pixel_height; - int last_hit_part; + enum scroll_bar_part last_hit_part; BOOL condemned; @@ -413,7 +393,6 @@ typedef float EmacsCGFloat; - initFrame: (NSRect )r window: (Lisp_Object)win; - (void)setFrame: (NSRect)r; -- (void)dealloc; - setPosition: (int) position portion: (int) portion whole: (int) whole; - (int) checkSamePosition: (int)position portion: (int)portion @@ -607,6 +586,9 @@ struct ns_display_info /* The cursor to use for vertical scroll bars. */ Cursor vertical_scroll_bar_cursor; + /* The cursor to use for horizontal scroll bars. */ + Cursor horizontal_scroll_bar_cursor; + /* Information about the range of text currently shown in mouse-face. */ Mouse_HLInfo mouse_highlight; @@ -747,12 +729,20 @@ struct x_output #endif /* Compute pixel size for vertical scroll bars */ -#define NS_SCROLL_BAR_WIDTH(f) \ -(FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ - ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \ - ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ - : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \ - : 0) +#define NS_SCROLL_BAR_WIDTH(f) \ + (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ + ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \ + ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ + : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \ + : 0) + +/* Compute pixel size for horizontal scroll bars */ +#define NS_SCROLL_BAR_HEIGHT(f) \ + (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \ + ? rint (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0 \ + ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) \ + : (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f))) \ + : 0) /* Difference btwn char-column-calculated and actual SB widths. This is only a concern for rendering when SB on left. */ @@ -761,6 +751,13 @@ struct x_output (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) \ - NS_SCROLL_BAR_WIDTH (f)) : 0) +/* Difference btwn char-line-calculated and actual SB heights. + This is only a concern for rendering when SB on top. */ +#define NS_SCROLL_BAR_ADJUST_HORIZONTALLY(w, f) \ + (WINDOW_HAS_HORIZONTAL_SCROLL_BARS (w) ? \ + (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \ + - NS_SCROLL_BAR_HEIGHT (f)) : 0) + /* XXX: fix for GNUstep inconsistent accounting for titlebar */ #ifdef NS_IMPL_GNUSTEP #define NS_TOP_POS(f) ((f)->top_pos + 18) @@ -778,8 +775,8 @@ struct x_output /* First position where characters can be shown (instead of scrollbar, if it is on left. */ -#define FIRST_CHAR_POSITION(f) \ - (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \ +#define FIRST_CHAR_POSITION(f) \ + (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \ : FRAME_SCROLL_BAR_COLS (f)) extern struct ns_display_info *ns_term_init (Lisp_Object display_name); @@ -856,7 +853,7 @@ extern void find_and_call_menu_selection (struct frame *f, extern Lisp_Object find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data); -extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object header, +extern Lisp_Object ns_popup_dialog (struct frame *, Lisp_Object header, Lisp_Object contents); #define NSAPP_DATA2_RUNASSCRIPT 10 @@ -897,6 +894,9 @@ extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, extern unsigned long ns_get_rgb_color (struct frame *f, float r, float g, float b, float a); +extern void ns_init_events (); +extern void ns_finish_events (); + /* From nsterm.m, needed in nsfont.m. */ #ifdef __OBJC__ extern void @@ -916,6 +916,7 @@ extern char gnustep_base_version[]; /* version tracking */ #define SCREENMAX 16000 #define NS_SCROLL_BAR_WIDTH_DEFAULT [EmacsScroller scrollerWidth] +#define NS_SCROLL_BAR_HEIGHT_DEFAULT [EmacsScroller scrollerHeight] /* This is to match emacs on other platforms, ugly though it is. */ #define NS_SELECTION_BG_COLOR_DEFAULT @"LightGoldenrod2"; #define NS_SELECTION_FG_COLOR_DEFAULT @"Black"; diff --git a/src/nsterm.m b/src/nsterm.m index 833b8e389a9..3ae4146dc20 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -54,7 +54,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include "termhooks.h" #include "termchar.h" - +#include "menu.h" #include "window.h" #include "keyboard.h" #include "buffer.h" @@ -65,10 +65,8 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #endif #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 #include "macfont.h" #endif -#endif /* call tracing */ #if 0 @@ -229,7 +227,7 @@ static unsigned convert_ns_to_X_keysym[] = static Lisp_Object Qmodifier_value; Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; -extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft; +extern Lisp_Object Qcursor_color, Qcursor_type, Qns; static Lisp_Object QUTF8_STRING; static Lisp_Object Qcocoa, Qgnustep; @@ -283,6 +281,11 @@ static NSMutableArray *ns_pending_files, *ns_pending_service_names, static BOOL ns_do_open_file = NO; static BOOL ns_last_use_native_fullscreen; +/* Non-zero means that a HELP_EVENT has been generated since Emacs + start. */ + +static BOOL any_help_event_p = NO; + static struct { struct input_event *q; int nr, cap; @@ -396,6 +399,19 @@ void x_set_frame_alpha (struct frame *f); ========================================================================== */ +void +ns_init_events (struct input_event* ev) +{ + EVENT_INIT (*ev); + emacs_event = ev; +} + +void +ns_finish_events () +{ + emacs_event = NULL; +} + static void hold_event (struct input_event *event) { @@ -688,7 +704,6 @@ static void ns_update_auto_hide_menu_bar (void) { #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 block_input (); NSTRACE (ns_update_auto_hide_menu_bar); @@ -721,7 +736,6 @@ ns_update_auto_hide_menu_bar (void) unblock_input (); #endif -#endif } @@ -1324,10 +1338,6 @@ x_set_window_size (struct frame *f, block_input (); - check_frame_size (f, &width, &height, pixelwise); - - compute_fringe_widths (f, 0); - if (pixelwise) { pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); @@ -1399,6 +1409,8 @@ x_set_window_size (struct frame *f, cancel_mouse_face (f); unblock_input (); + + do_pending_window_change (0); } @@ -1799,12 +1811,12 @@ x_set_frame_alpha (struct frame *f) void -x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) /* -------------------------------------------------------------------------- Programmatically reposition mouse pointer in pixel coordinates -------------------------------------------------------------------------- */ { - NSTRACE (x_set_mouse_pixel_position); + NSTRACE (frame_set_mouse_pixel_position); ns_raise_frame (f); #if 0 /* FIXME: this does not work, and what about GNUstep? */ @@ -1816,28 +1828,6 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) #endif } - -void -x_set_mouse_position (struct frame *f, int h, int v) -/* -------------------------------------------------------------------------- - Programmatically reposition mouse pointer in character coordinates - -------------------------------------------------------------------------- */ -{ - int pix_x, pix_y; - - pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2; - pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2; - - if (pix_x < 0) pix_x = 0; - if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); - - if (pix_y < 0) pix_y = 0; - if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); - - x_set_mouse_pixel_position (f, pix_x, pix_y); -} - - static int note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y) /* ------------------------------------------------------------------------ @@ -1936,10 +1926,9 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, position = [view convertPoint: position fromView: nil]; remember_mouse_glyph (f, position.x, position.y, &dpyinfo->last_mouse_glyph); -/*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */ if (bar_window) *bar_window = Qnil; - if (part) *part = 0; /*scroll_bar_handle; */ + if (part) *part = scroll_bar_above_handle; if (x) XSETINT (*x, lrint (position.x)); if (y) XSETINT (*y, lrint (position.y)); @@ -2012,8 +2001,7 @@ ns_convert_key (unsigned code) Internal call used by NSView-keyDown. -------------------------------------------------------------------------- */ { - const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) - / sizeof (convert_ns_to_X_keysym[0])); + const unsigned last_keysym = ARRAYELTS (convert_ns_to_X_keysym); unsigned keysym; /* An array would be faster, but less easy to read. */ for (keysym = 0; keysym < last_keysym; keysym += 2) @@ -2320,52 +2308,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, { int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; - /* If the fringe is adjacent to the left (right) scroll bar of a - leftmost (rightmost, respectively) window, then extend its - background to the gap between the fringe and the bar. */ - if ((WINDOW_LEFTMOST_P (w) - && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) - || (WINDOW_RIGHTMOST_P (w) - && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))) - { - int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w); - - if (sb_width > 0) - { - int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w); - int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w) - * FRAME_COLUMN_WIDTH (f)); - - if (bx < 0) - { - /* Bitmap fills the fringe. */ - if (bar_area_x + bar_area_width == p->x) - bx = bar_area_x + sb_width; - else if (p->x + p->wd == bar_area_x) - bx = bar_area_x; - if (bx >= 0) - { - int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); - - nx = bar_area_width - sb_width; - by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, - row->y)); - ny = row->visible_height; - } - } - else - { - if (bar_area_x + bar_area_width == bx) - { - bx = bar_area_x + sb_width; - nx += bar_area_width - sb_width; - } - else if (bx + nx == bar_area_x) - nx += bar_area_width - sb_width; - } - } - } - if (bx >= 0 && nx > 0) { NSRect r = NSMakeRect (bx, by, nx, ny); @@ -2400,8 +2342,19 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, to erase the whole background. */ [ns_lookup_indexed_color(face->background, f) set]; NSRectFill (r); - [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)]; -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + + { + NSColor *bm_color; + if (!p->cursor_p) + bm_color = ns_lookup_indexed_color(face->foreground, f); + else if (p->overlay_p) + bm_color = ns_lookup_indexed_color(face->background, f); + else + bm_color = f->output_data.ns->cursor_color; + [img setXBMColor: bm_color]; + } + +#ifdef NS_IMPL_COCOA [img drawInRect: r fromRect: NSZeroRect operation: NSCompositeSourceOver @@ -2484,7 +2437,10 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, else if (cursor_type == HBAR_CURSOR) { cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width; - fy += h - cursor_height; + if (cursor_height > glyph_row->height) + cursor_height = glyph_row->height; + if (h > cursor_height) // Cursor smaller than line height, move down + fy += h - cursor_height; h = cursor_height; } @@ -2599,38 +2555,18 @@ ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) ns_unfocus (f); } - -void -show_hourglass (struct atimer *timer) +static void +ns_show_hourglass (struct frame *f) { - if (hourglass_shown_p) - return; - - block_input (); - - /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */ - - hourglass_shown_p = 1; - unblock_input (); + /* TODO: add NSProgressIndicator to all frames. */ } - -void -hide_hourglass (void) +static void +ns_hide_hourglass (struct frame *f) { - if (!hourglass_shown_p) - return; - - block_input (); - - /* TODO: remove NSProgressIndicator from all frames */ - - hourglass_shown_p = 0; - unblock_input (); + /* TODO: remove NSProgressIndicator from all frames. */ } - - /* ========================================================================== Glyph drawing operations @@ -3097,7 +3033,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) /* Draw the image.. do we need to draw placeholder if img ==nil? */ if (img != nil) { -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height); NSRect ir = NSMakeRect (s->slice.x, s->slice.y, s->slice.width, s->slice.height); @@ -3356,10 +3292,16 @@ ns_draw_glyph_string (struct glyph_string *s) NS_FACE_FOREGROUND (s->face) = tmp; } - font->driver->draw - (s, 0, s->nchars, s->x, s->y, - (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) - || flags == NS_DUMPGLYPH_MOUSEFACE); + { + BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; + int end = isComposite ? s->cmp_to : s->nchars; + + font->driver->draw + (s, s->cmp_from, end, s->x, s->ybase, + (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) + || flags == NS_DUMPGLYPH_MOUSEFACE); + + } { NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0 @@ -3503,9 +3445,8 @@ check_native_fs () } #endif -/* GNUstep and OSX <= 10.4 does not have cancelTracking. */ -#if defined (NS_IMPL_COCOA) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +/* GNUstep does not have cancelTracking. */ +#ifdef NS_IMPL_COCOA /* Check if menu open should be canceled or continued as normal. */ void ns_check_menu_open (NSMenu *menu) @@ -3568,7 +3509,16 @@ ns_check_pending_open_menu () menu_will_open_state = MENU_OPENING; } } -#endif /* NS_IMPL_COCOA) && >= MAC_OS_X_VERSION_10_5 */ +#endif /* NS_IMPL_COCOA */ + +static void +unwind_apploopnr (Lisp_Object not_used) +{ + --apploopnr; + n_emacs_events_pending = 0; + ns_finish_events (); + q_event_ptr = NULL; +} static int ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) @@ -3601,8 +3551,7 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) block_input (); n_emacs_events_pending = 0; - EVENT_INIT (ev); - emacs_event = &ev; + ns_init_events (&ev); q_event_ptr = hold_quit; /* we manage autorelease pools by allocate/reallocate each time around @@ -3628,6 +3577,7 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) } else { + ptrdiff_t specpdl_count = SPECPDL_INDEX (); /* Run and wait for events. We must always send one NX_APPDEFINED event to ourself, otherwise [NXApp run] will never exit. */ send_appdefined = YES; @@ -3637,13 +3587,15 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) { emacs_abort (); } + record_unwind_protect (unwind_apploopnr, Qt); [NSApp run]; - --apploopnr; + unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */ } nevents = n_emacs_events_pending; n_emacs_events_pending = 0; - emacs_event = q_event_ptr = NULL; + ns_finish_events (); + q_event_ptr = NULL; unblock_input (); return nevents; @@ -3738,16 +3690,21 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, ns_send_appdefined (-1); } - EVENT_INIT (event); block_input (); - emacs_event = &event; + ns_init_events (&event); if (++apploopnr != 1) { emacs_abort (); } - [NSApp run]; - --apploopnr; - emacs_event = NULL; + + { + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + record_unwind_protect (unwind_apploopnr, Qt); + [NSApp run]; + unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */ + } + + ns_finish_events (); if (nr > 0 && readfds) { c = 's'; @@ -3812,10 +3769,9 @@ ns_set_vertical_scroll_bar (struct window *window, NSRect r, v; struct frame *f = XFRAME (WINDOW_FRAME (window)); EmacsView *view = FRAME_NS_VIEW (f); - int window_y, window_height; - int top, left, height, width, sb_width, sb_left; EmacsScroller *bar; - BOOL fringe_extended_p; + int window_y, window_height; + int top, left, height, width; /* optimization; display engine sends WAY too many of these.. */ if (!NILP (window->vertical_scroll_bar)) @@ -3842,18 +3798,11 @@ ns_set_vertical_scroll_bar (struct window *window, width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f); left = WINDOW_SCROLL_BAR_AREA_X (window); - /* allow for displaying a skinnier scrollbar than char area allotted */ - sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ? - WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width; - sb_left = left; - - r = NSMakeRect (sb_left, top, sb_width, height); + r = NSMakeRect (left, top, width, height); /* the parent view is flipped, so we need to flip y value */ v = [view frame]; r.origin.y = (v.size.height - r.size.height - r.origin.y); - fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (window); - XSETWINDOW (win, window); block_input (); @@ -3866,7 +3815,7 @@ ns_set_vertical_scroll_bar (struct window *window, [bar removeFromSuperview]; wset_vertical_scroll_bar (window, Qnil); } - ns_clear_frame_area (f, sb_left, top, width, height); + ns_clear_frame_area (f, left, top, width, height); unblock_input (); return; } @@ -3874,12 +3823,7 @@ ns_set_vertical_scroll_bar (struct window *window, if (NILP (window->vertical_scroll_bar)) { if (width > 0 && height > 0) - { - if (fringe_extended_p) - ns_clear_frame_area (f, sb_left, top, sb_width, height); - else - ns_clear_frame_area (f, left, top, width, height); - } + ns_clear_frame_area (f, left, top, width, height); bar = [[EmacsScroller alloc] initFrame: r window: win]; wset_vertical_scroll_bar (window, make_save_ptr (bar)); @@ -3893,7 +3837,97 @@ ns_set_vertical_scroll_bar (struct window *window, if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r)) { if (oldRect.origin.x != r.origin.x) - ns_clear_frame_area (f, sb_left, top, width, height); + ns_clear_frame_area (f, left, top, width, height); + [bar setFrame: r]; + } + } + + [bar setPosition: position portion: portion whole: whole]; + unblock_input (); +} + + +static void +ns_set_horizontal_scroll_bar (struct window *window, + int portion, int whole, int position) +/* -------------------------------------------------------------------------- + External (hook): Update or add scrollbar + -------------------------------------------------------------------------- */ +{ + Lisp_Object win; + NSRect r, v; + struct frame *f = XFRAME (WINDOW_FRAME (window)); + EmacsView *view = FRAME_NS_VIEW (f); + EmacsScroller *bar; + int top, height, left, width; + int window_x, window_width; + int pixel_width = WINDOW_PIXEL_WIDTH (window); + + /* optimization; display engine sends WAY too many of these.. */ + if (!NILP (window->horizontal_scroll_bar)) + { + bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); + if ([bar checkSamePosition: position portion: portion whole: whole]) + { + if (view->scrollbarsNeedingUpdate == 0) + { + if (!windows_or_buffers_changed) + return; + } + else + view->scrollbarsNeedingUpdate--; + } + } + + NSTRACE (ns_set_horizontal_scroll_bar); + + /* Get dimensions. */ + window_box (window, ANY_AREA, 0, &window_x, &window_width, 0); + left = window_x; + width = window_width; + height = WINDOW_CONFIG_SCROLL_BAR_LINES (window) * FRAME_LINE_HEIGHT (f); + top = WINDOW_SCROLL_BAR_AREA_Y (window); + + r = NSMakeRect (left, top, width, height); + /* the parent view is flipped, so we need to flip y value */ + v = [view frame]; + /* ??????? PXW/scrollbars !!!!!!!!!!!!!!!!!!!! */ + r.origin.y = (v.size.height - r.size.height - r.origin.y); + + XSETWINDOW (win, window); + block_input (); + + if (WINDOW_TOTAL_COLS (window) < 5) + { + if (!NILP (window->horizontal_scroll_bar)) + { + bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); + [bar removeFromSuperview]; + wset_horizontal_scroll_bar (window, Qnil); + } + ns_clear_frame_area (f, left, top, width, height); + unblock_input (); + return; + } + + if (NILP (window->horizontal_scroll_bar)) + { + if (width > 0 && height > 0) + ns_clear_frame_area (f, left, top, width, height); + + bar = [[EmacsScroller alloc] initFrame: r window: win]; + wset_horizontal_scroll_bar (window, make_save_ptr (bar)); + } + else + { + NSRect oldRect; + bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); + oldRect = [bar frame]; + r.size.width = oldRect.size.width; + if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r)) + { + if (oldRect.origin.x != r.origin.x) + ns_clear_frame_area (f, left, top, width, height); [bar setFrame: r]; } } @@ -3939,6 +3973,12 @@ ns_redeem_scroll_bar (struct window *window) bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); [bar reprieve]; } + + if (!NILP (window->horizontal_scroll_bar)) + { + bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); + [bar reprieve]; + } } @@ -4114,7 +4154,9 @@ static struct redisplay_interface ns_redisplay_interface = ns_draw_window_cursor, ns_draw_vertical_window_border, ns_draw_window_divider, - ns_shift_glyphs_for_insert + ns_shift_glyphs_for_insert, + ns_show_hourglass, + ns_hide_hourglass }; @@ -4154,38 +4196,30 @@ ns_create_terminal (struct ns_display_info *dpyinfo) NSTRACE (ns_create_terminal); - terminal = create_terminal (); + terminal = create_terminal (output_ns, &ns_redisplay_interface); - terminal->type = output_ns; terminal->display_info.ns = dpyinfo; dpyinfo->terminal = terminal; - terminal->rif = &ns_redisplay_interface; - terminal->clear_frame_hook = ns_clear_frame; - terminal->ins_del_lines_hook = 0; /* XXX vestigial? */ - terminal->delete_glyphs_hook = 0; /* XXX vestigial? */ terminal->ring_bell_hook = ns_ring_bell; - terminal->reset_terminal_modes_hook = NULL; - terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = ns_update_begin; terminal->update_end_hook = ns_update_end; - terminal->set_terminal_window_hook = NULL; /* XXX vestigial? */ terminal->read_socket_hook = ns_read_socket; terminal->frame_up_to_date_hook = ns_frame_up_to_date; terminal->mouse_position_hook = ns_mouse_position; terminal->frame_rehighlight_hook = ns_frame_rehighlight; terminal->frame_raise_lower_hook = ns_frame_raise_lower; - terminal->fullscreen_hook = ns_fullscreen_hook; - + terminal->menu_show_hook = ns_menu_show; + terminal->popup_dialog_hook = ns_popup_dialog; terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar; terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars; terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar; terminal->judge_scroll_bars_hook = ns_judge_scroll_bars; - terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = ns_delete_terminal; + /* Other hooks are NULL by default. */ return terminal; } @@ -4466,7 +4500,7 @@ ns_term_shutdown (int sig) { if (self = [super init]) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#ifdef NS_IMPL_COCOA self->isFirst = YES; #endif #ifdef NS_IMPL_GNUSTEP @@ -4477,30 +4511,40 @@ ns_term_shutdown (int sig) return self; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#ifdef NS_IMPL_COCOA - (void)run { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +#ifndef NSAppKitVersionNumber10_8 +#define NSAppKitVersionNumber10_8 1187 +#endif - if (isFirst) [self finishLaunching]; - isFirst = NO; + if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_8) + { + [super run]; + return; + } - shouldKeepRunning = YES; - do - { - [pool release]; - pool = [[NSAutoreleasePool alloc] init]; - - NSEvent *event = - [self nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - [self sendEvent:event]; - [self updateWindows]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if (isFirst) [self finishLaunching]; + isFirst = NO; + + shouldKeepRunning = YES; + do + { + [pool release]; + pool = [[NSAutoreleasePool alloc] init]; + + NSEvent *event = + [self nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantFuture] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + [self sendEvent:event]; + [self updateWindows]; } while (shouldKeepRunning); - [pool release]; + [pool release]; } - (void)stop: (id)sender @@ -4510,7 +4554,7 @@ ns_term_shutdown (int sig) // The file dialog still leaks 7k - 10k on 10.9 though. [super stop:sender]; } -#endif +#endif /* NS_IMPL_COCOA */ - (void)logNotification: (NSNotification *)notification { @@ -4671,14 +4715,12 @@ ns_term_shutdown (int sig) [self antialiasThresholdDidChange:nil]; #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(antialiasThresholdDidChange:) name:NSAntialiasThresholdChangedNotification object:nil]; #endif -#endif ns_send_appdefined (-2); } @@ -4686,10 +4728,8 @@ ns_term_shutdown (int sig) - (void)antialiasThresholdDidChange:(NSNotification *)notification { #ifdef NS_IMPL_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 macfont_update_antialias_threshold (); #endif -#endif } @@ -5029,11 +5069,11 @@ not_in_argv (NSString *arg) if (!emacs_event) return; - if (EQ (font->driver->type, Qns)) - nsfont = ((struct nsfont_info *)font)->nsfont; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - else - nsfont = (NSFont *) macfont_get_nsctfont (font); +#ifdef NS_IMPL_GNUSTEP + nsfont = ((struct nsfont_info *)font)->nsfont; +#endif +#ifdef NS_IMPL_COCOA + nsfont = (NSFont *) macfont_get_nsctfont (font); #endif if ((newFont = [sender convertFont: nsfont])) @@ -5085,7 +5125,7 @@ not_in_argv (NSString *arg) int code; unsigned fnKeysym = 0; static NSMutableArray *nsEvArray; -#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_GNUSTEP static BOOL firstTime = YES; #endif int left_is_none; @@ -5316,7 +5356,7 @@ not_in_argv (NSString *arg) } -#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_GNUSTEP /* if we get here we should send the key for input manager processing */ /* Disable warning, there is nothing a user can do about it anyway, and it does not seem to matter. */ @@ -5712,14 +5752,10 @@ not_in_argv (NSString *arg) /* NOTE: help_echo_{window,pos,object} are set in xdisp.c (note_mouse_highlight), which is called through the note_mouse_movement () call above */ + any_help_event_p = YES; gen_help_event (help_echo_string, frame, help_echo_window, help_echo_object, help_echo_pos); } - else - { - help_echo_string = Qnil; - gen_help_event (Qnil, frame, Qnil, Qnil, 0); - } if (emacsframe->mouse_moved && send_appdefined) ns_send_appdefined (-1); @@ -5780,7 +5816,8 @@ not_in_argv (NSString *arg) { #ifdef NS_IMPL_GNUSTEP // GNUstep does not always update the tool bar height. Force it. - if (toolbar) update_frame_tool_bar (emacsframe); + if (toolbar && [toolbar isVisible]) + update_frame_tool_bar (emacsframe); #endif extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe) @@ -6000,6 +6037,14 @@ if (cols > 0 && rows > 0) x_set_frame_alpha (emacsframe); } + if (any_help_event_p) + { + Lisp_Object frame; + XSETFRAME (frame, emacsframe); + help_echo_string = Qnil; + gen_help_event (Qnil, frame, Qnil, Qnil, 0); + } + if (emacs_event && is_focus_frame) { [self deleteWorkingText]; @@ -6453,8 +6498,7 @@ if (cols > 0 && rows > 0) /* Hide dock and menubar if we are on the primary screen. */ if (onFirstScreen) { -#if defined (NS_IMPL_COCOA) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA NSApplicationPresentationOptions options = NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar; @@ -6494,7 +6538,7 @@ if (cols > 0 && rows > 0) [fw makeFirstResponder:self]; [w orderOut:self]; r = [fw frameRectForContentRect:[screen frame]]; - [fw setFrame: r display:YES animate:YES]; + [fw setFrame: r display:YES animate:ns_use_fullscreen_animation]; [self windowDidEnterFullScreen:nil]; [fw display]; } @@ -6506,8 +6550,7 @@ if (cols > 0 && rows > 0) if (onFirstScreen) { -#if defined (NS_IMPL_COCOA) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#ifdef NS_IMPL_COCOA [NSApp setPresentationOptions: NSApplicationPresentationDefault]; #else [NSMenu setMenuBarVisible:YES]; @@ -6526,7 +6569,7 @@ if (cols > 0 && rows > 0) FRAME_TOOLBAR_HEIGHT (f) = tobar_height; [self windowWillExitFullScreen:nil]; - [fw setFrame: [w frame] display:YES animate:YES]; + [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation]; [fw close]; [w makeKeyAndOrderFront:NSApp]; [self windowDidExitFullScreen:nil]; @@ -6832,7 +6875,7 @@ if (cols > 0 && rows > 0) } else { - error ("Invalid data type in dragging pasteboard"); + fprintf (stderr, "Invalid data type in dragging pasteboard"); return NO; } } @@ -7022,7 +7065,7 @@ if (cols > 0 && rows > 0) #endif #endif - for (i = 0; i < nr_screens; ++i) + for (i = 0; i < nr_screens; ++i) { NSScreen *s = [screens objectAtIndex: i]; NSRect scrrect = [s frame]; @@ -7034,7 +7077,7 @@ if (cols > 0 && rows > 0) if (nr_eff_screens == 1) return [super constrainFrameRect:frameRect toScreen:screen]; - + /* The default implementation does two things 1) ensure that the top of the rectangle is below the menu bar (or below the top of the screen) and 2) resizes windows larger than the screen. As we @@ -7162,15 +7205,6 @@ if (cols > 0 && rows > 0) } -- (void)dealloc -{ - NSTRACE (EmacsScroller_dealloc); - if (!NILP (win)) - wset_vertical_scroll_bar (XWINDOW (win), Qnil); - [super dealloc]; -} - - - condemn { NSTRACE (condemn); @@ -7198,6 +7232,9 @@ if (cols > 0 && rows > 0) view = (EmacsView *)FRAME_NS_VIEW (frame); if (view != nil) view->scrollbarsNeedingUpdate++; + if (!NILP (win)) + wset_vertical_scroll_bar (XWINDOW (win), Qnil); + win = Qnil; [self removeFromSuperview]; [self release]; unblock_input (); @@ -7235,7 +7272,7 @@ if (cols > 0 && rows > 0) if (portion >= whole) { -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 +#ifdef NS_IMPL_COCOA [self setKnobProportion: 1.0]; [self setDoubleValue: 1.0]; #else @@ -7249,7 +7286,7 @@ if (cols > 0 && rows > 0) portion = max ((float)whole*min_portion/pixel_height, portion); pos = (float)position / (whole - portion); por = (CGFloat)portion/whole; -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 +#ifdef NS_IMPL_COCOA [self setKnobProportion: por]; [self setDoubleValue: pos]; #else @@ -7475,7 +7512,7 @@ if (cols > 0 && rows > 0) [scroll_repeat_entry release]; scroll_repeat_entry = nil; } - last_hit_part = 0; + last_hit_part = scroll_bar_above_handle; } @@ -7525,8 +7562,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_COLUMN_WIDTH (f) = font->average_width; FRAME_LINE_HEIGHT (f) = font->height; - compute_fringe_widths (f, 1); - /* Compute the scroll bar width in character columns. */ if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) { @@ -7540,6 +7575,19 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; } + /* Compute the scroll bar height in character lines. */ + if (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0) + { + int height = FRAME_LINE_HEIGHT (f); + FRAME_CONFIG_SCROLL_BAR_LINES (f) + = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height; + } + else + { + int height = FRAME_LINE_HEIGHT (f); + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height; + } + /* Now make the frame display the given font. */ if (FRAME_NS_WINDOW (f) != 0 && ! [view isFullscreen]) x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), @@ -7725,6 +7773,12 @@ Default is t for OSX >= 10.7, nil otherwise. */); #endif ns_last_use_native_fullscreen = ns_use_native_fullscreen; + DEFVAR_BOOL ("ns-use-fullscreen-animation", ns_use_fullscreen_animation, + doc: /*Non-nil means use animation on non-native fullscreen. +For native fullscreen, this does nothing. +Default is nil. */); + ns_use_fullscreen_animation = NO; + DEFVAR_BOOL ("ns-use-srgb-colorspace", ns_use_srgb_colorspace, doc: /*Non-nil means to use sRGB colorspace on OSX >= 10.7. Note that this does not apply to images. @@ -7762,14 +7816,12 @@ baseline level. The default value is nil. */); DEFSYM (Qcocoa, "cocoa"); DEFSYM (Qgnustep, "gnustep"); - syms_of_nsfont (); #ifdef NS_IMPL_COCOA Fprovide (Qcocoa, Qnil); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 syms_of_macfont (); -#endif #else Fprovide (Qgnustep, Qnil); + syms_of_nsfont (); #endif } diff --git a/src/print.c b/src/print.c index 475be9ec285..49331ef0984 100644 --- a/src/print.c +++ b/src/print.c @@ -58,6 +58,9 @@ static ptrdiff_t new_backquote_output; #define PRINT_CIRCLE 200 static Lisp_Object being_printed[PRINT_CIRCLE]; +/* Last char printed to stdout by printchar. */ +static unsigned int printchar_stdout_last; + /* When printing into a buffer, first we put the text in this block, then insert it all at once. */ static char *print_buffer; @@ -169,11 +172,13 @@ bool print_output_debug_flag EXTERNALLY_VISIBLE = 1; if (print_buffer_pos != print_buffer_pos_byte \ && NILP (BVAR (current_buffer, enable_multibyte_characters)))\ { \ - unsigned char *temp = alloca (print_buffer_pos + 1); \ + USE_SAFE_ALLOCA; \ + unsigned char *temp = SAFE_ALLOCA (print_buffer_pos + 1); \ copy_text ((unsigned char *) print_buffer, temp, \ print_buffer_pos_byte, 1, 0); \ insert_1_both ((char *) temp, print_buffer_pos, \ print_buffer_pos, 0, 1, 0); \ + SAFE_FREE (); \ } \ else \ insert_1_both (print_buffer, print_buffer_pos, \ @@ -236,6 +241,7 @@ printchar (unsigned int ch, Lisp_Object fun) } else if (noninteractive) { + printchar_stdout_last = ch; fwrite (str, 1, len, stdout); noninteractive_need_newline = 1; } @@ -513,19 +519,33 @@ static void print_preprocess (Lisp_Object); static void print_preprocess_string (INTERVAL, Lisp_Object); static void print_object (Lisp_Object, Lisp_Object, bool); -DEFUN ("terpri", Fterpri, Sterpri, 0, 1, 0, +DEFUN ("terpri", Fterpri, Sterpri, 0, 2, 0, doc: /* Output a newline to stream PRINTCHARFUN. +If ENSURE is non-nil only output a newline if not already at the +beginning of a line. Value is non-nil if a newline is printed. If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used. */) - (Lisp_Object printcharfun) + (Lisp_Object printcharfun, Lisp_Object ensure) { - PRINTDECLARE; + Lisp_Object val = Qnil; + PRINTDECLARE; if (NILP (printcharfun)) printcharfun = Vstandard_output; PRINTPREPARE; - PRINTCHAR ('\n'); + + if (NILP (ensure)) + val = Qt; + /* Difficult to check if at line beginning so abort. */ + else if (FUNCTIONP (printcharfun)) + signal_error ("Unsupported function argument", printcharfun); + else if (noninteractive && !NILP (printcharfun)) + val = printchar_stdout_last == 10 ? Qnil : Qt; + else if (NILP (Fbolp ())) + val = Qt; + + if (!NILP (val)) PRINTCHAR ('\n'); PRINTFINISH; - return Qt; + return val; } DEFUN ("prin1", Fprin1, Sprin1, 1, 2, 0, @@ -581,7 +601,6 @@ A printed representation of an object is text which describes that object. */) { Lisp_Object printcharfun; bool prev_abort_on_gc; - /* struct gcpro gcpro1, gcpro2; */ Lisp_Object save_deactivate_mark; ptrdiff_t count = SPECPDL_INDEX (); struct buffer *previous; @@ -595,7 +614,6 @@ A printed representation of an object is text which describes that object. */) but we don't want to deactivate the mark just for that. No need for specbind, since errors deactivate the mark. */ save_deactivate_mark = Vdeactivate_mark; - /* GCPRO2 (object, save_deactivate_mark); */ prev_abort_on_gc = abort_on_gc; abort_on_gc = 1; @@ -619,7 +637,6 @@ A printed representation of an object is text which describes that object. */) set_buffer_internal (previous); Vdeactivate_mark = save_deactivate_mark; - /* UNGCPRO; */ abort_on_gc = prev_abort_on_gc; return unbind_to (count, object); @@ -1228,7 +1245,8 @@ print_preprocess (Lisp_Object obj) size = ASIZE (obj); if (size & PSEUDOVECTOR_FLAG) size &= PSEUDOVECTOR_SIZE_MASK; - for (i = 0; i < size; i++) + for (i = (SUB_CHAR_TABLE_P (obj) + ? SUB_CHAR_TABLE_OFFSET : 0); i < size; i++) print_preprocess (AREF (obj, i)); if (HASH_TABLE_P (obj)) { /* For hash tables, the key_and_value slot is past @@ -1472,7 +1490,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) strout (outbuf, len, len, printcharfun); } else if (! multibyte - && SINGLE_BYTE_CHAR_P (c) && ! ASCII_BYTE_P (c) + && SINGLE_BYTE_CHAR_P (c) && ! ASCII_CHAR_P (c) && print_escape_nonascii) { /* When printing in a multibyte buffer @@ -1968,7 +1986,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) Otherwise we'll make a line extremely long, which results in slow redisplay. */ if (SUB_CHAR_TABLE_P (obj) - && XINT (XSUB_CHAR_TABLE (obj)->depth) == 3) + && XSUB_CHAR_TABLE (obj)->depth == 3) PRINTCHAR ('\n'); PRINTCHAR ('#'); PRINTCHAR ('^'); @@ -1981,16 +1999,24 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) PRINTCHAR ('['); { - register int i; + int i, idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0; register Lisp_Object tem; ptrdiff_t real_size = size; + /* For a sub char-table, print heading non-Lisp data first. */ + if (SUB_CHAR_TABLE_P (obj)) + { + i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth, + XSUB_CHAR_TABLE (obj)->min_char); + strout (buf, i, i, printcharfun); + } + /* Don't print more elements than the specified maximum. */ if (NATNUMP (Vprint_length) && XFASTINT (Vprint_length) < size) size = XFASTINT (Vprint_length); - for (i = 0; i < size; i++) + for (i = idx; i < size; i++) { if (i) PRINTCHAR (' '); tem = AREF (obj, i); diff --git a/src/process.c b/src/process.c index 178fba8887e..06fc918cf54 100644 --- a/src/process.c +++ b/src/process.c @@ -227,8 +227,9 @@ static EMACS_INT update_tick; /* Only W32 has this, it really means that select can't take write mask. */ #ifdef BROKEN_NON_BLOCKING_CONNECT #undef NON_BLOCKING_CONNECT -#define SELECT_CANT_DO_WRITE_MASK +enum { SELECT_CAN_DO_WRITE_MASK = false }; #else +enum { SELECT_CAN_DO_WRITE_MASK = true }; #ifndef NON_BLOCKING_CONNECT #ifdef HAVE_SELECT #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX) @@ -284,17 +285,11 @@ static void create_process (Lisp_Object, char **, Lisp_Object); static bool keyboard_bit_set (fd_set *); #endif static void deactivate_process (Lisp_Object); -static void status_notify (struct Lisp_Process *); +static int status_notify (struct Lisp_Process *, struct Lisp_Process *); static int read_process_output (Lisp_Object, int); static void handle_child_signal (int); static void create_pty (Lisp_Object); -/* If we support a window system, turn on the code to poll periodically - to detect C-g. It isn't actually used when doing interrupt input. */ -#ifdef HAVE_WINDOW_SYSTEM -#define POLL_FOR_INPUT -#endif - static Lisp_Object get_process (register Lisp_Object name); static void exec_sentinel (Lisp_Object proc, Lisp_Object reason); @@ -471,7 +466,6 @@ static struct fd_callback_data void add_read_fd (int fd, fd_callback func, void *data) { - eassert (fd < FD_SETSIZE); add_keyboard_wait_descriptor (fd); fd_callback_info[fd].func = func; @@ -484,7 +478,6 @@ add_read_fd (int fd, fd_callback func, void *data) void delete_read_fd (int fd) { - eassert (fd < FD_SETSIZE); delete_keyboard_wait_descriptor (fd); fd_callback_info[fd].condition &= ~FOR_READ; @@ -501,7 +494,6 @@ delete_read_fd (int fd) void add_write_fd (int fd, fd_callback func, void *data) { - eassert (fd < FD_SETSIZE); FD_SET (fd, &write_mask); if (fd > max_input_desc) max_input_desc = fd; @@ -532,7 +524,6 @@ delete_input_desc (int fd) void delete_write_fd (int fd) { - eassert (fd < FD_SETSIZE); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; if (fd_callback_info[fd].condition == 0) @@ -608,7 +599,7 @@ status_message (struct Lisp_Process *p) Lisp_Object symbol; int code; bool coredump; - Lisp_Object string, string2; + Lisp_Object string; decode_status (status, &symbol, &code, &coredump); @@ -632,8 +623,8 @@ status_message (struct Lisp_Process *p) if (c1 != c2) Faset (string, make_number (0), make_number (c2)); } - string2 = build_string (coredump ? " (core dumped)\n" : "\n"); - return concat2 (string, string2); + AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n"); + return concat2 (string, suffix); } else if (EQ (symbol, Qexit)) { @@ -641,17 +632,17 @@ status_message (struct Lisp_Process *p) return build_string (code == 0 ? "deleted\n" : "connection broken by remote peer\n"); if (code == 0) return build_string ("finished\n"); + AUTO_STRING (prefix, "exited abnormally with code "); string = Fnumber_to_string (make_number (code)); - string2 = build_string (coredump ? " (core dumped)\n" : "\n"); - return concat3 (build_string ("exited abnormally with code "), - string, string2); + AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n"); + return concat3 (prefix, string, suffix); } else if (EQ (symbol, Qfailed)) { + AUTO_STRING (prefix, "failed with code "); string = Fnumber_to_string (make_number (code)); - string2 = build_string ("\n"); - return concat3 (build_string ("failed with code "), - string, string2); + AUTO_STRING (suffix, "\n"); + return concat3 (prefix, string, suffix); } else return Fcopy_sequence (Fsymbol_name (symbol)); @@ -873,7 +864,7 @@ nil, indicating the current buffer's process. */) { pset_status (p, list2 (Qexit, make_number (0))); p->tick = ++process_tick; - status_notify (p); + status_notify (p, NULL); redisplay_preserve_echo_area (13); } else @@ -893,7 +884,7 @@ nil, indicating the current buffer's process. */) pset_status (p, list2 (Qsignal, make_number (SIGKILL))); p->tick = ++process_tick; - status_notify (p); + status_notify (p, NULL); redisplay_preserve_echo_area (13); } } @@ -1314,30 +1305,34 @@ Returns nil if format of ADDRESS is invalid. */) ptrdiff_t size = p->header.size; Lisp_Object args[10]; int nargs, i; + char const *format; if (size == 4 || (size == 5 && !NILP (omit_port))) { - args[0] = build_string ("%d.%d.%d.%d"); + format = "%d.%d.%d.%d"; nargs = 4; } else if (size == 5) { - args[0] = build_string ("%d.%d.%d.%d:%d"); + format = "%d.%d.%d.%d:%d"; nargs = 5; } else if (size == 8 || (size == 9 && !NILP (omit_port))) { - args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); + format = "%x:%x:%x:%x:%x:%x:%x:%x"; nargs = 8; } else if (size == 9) { - args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d"); + format = "[%x:%x:%x:%x:%x:%x:%x:%x]:%d"; nargs = 9; } else return Qnil; + AUTO_STRING (format_obj, format); + args[0] = format_obj; + for (i = 0; i < nargs; i++) { if (! RANGED_INTEGERP (0, p->contents[i], 65535)) @@ -1351,15 +1346,13 @@ Returns nil if format of ADDRESS is invalid. */) args[i+1] = p->contents[i]; } - return Fformat (nargs+1, args); + return Fformat (nargs + 1, args); } if (CONSP (address)) { - Lisp_Object args[2]; - args[0] = build_string ("<Family %d>"); - args[1] = Fcar (address); - return Fformat (2, args); + AUTO_STRING (format, "<Family %d>"); + return Fformat (2, (Lisp_Object []) {format, Fcar (address)}); } return Qnil; @@ -1398,9 +1391,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { Lisp_Object buffer, name, program, proc, current_dir, tem; - register unsigned char **new_argv; + unsigned char **new_argv; ptrdiff_t i; ptrdiff_t count = SPECPDL_INDEX (); + USE_SAFE_ALLOCA; buffer = args[1]; if (!NILP (buffer)) @@ -1476,7 +1470,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) val = Vcoding_system_for_read; if (NILP (val)) { - args2 = alloca ((nargs + 1) * sizeof *args2); + SAFE_ALLOCA_LISP (args2, nargs + 1); args2[0] = Qstart_process; for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; GCPRO2 (proc, current_dir); @@ -1495,7 +1489,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) { if (EQ (coding_systems, Qt)) { - args2 = alloca ((nargs + 1) * sizeof *args2); + SAFE_ALLOCA_LISP (args2, nargs + 1); args2[0] = Qstart_process; for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; GCPRO2 (proc, current_dir); @@ -1590,7 +1584,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) /* Now that everything is encoded we can collect the strings into NEW_ARGV. */ - new_argv = alloca ((nargs - 1) * sizeof *new_argv); + SAFE_NALLOCA (new_argv, 1, nargs - 1); new_argv[nargs - 2] = 0; for (i = nargs - 2; i-- != 0; ) @@ -1604,6 +1598,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) else create_pty (proc); + SAFE_FREE (); return unbind_to (count, proc); } @@ -1666,6 +1661,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; Lisp_Object lisp_pty_name = Qnil; + sigset_t oldset; inchannel = outchannel = -1; @@ -1731,7 +1727,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) setup_process_coding_systems (process); block_input (); - block_child_signal (); + block_child_signal (&oldset); #ifndef WINDOWSNT /* vfork, and prevent local vars from being clobbered by the vfork. */ @@ -1855,7 +1851,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) signal (SIGPIPE, SIG_DFL); /* Stop blocking SIGCHLD in the child. */ - unblock_child_signal (); + unblock_child_signal (&oldset); if (pty_flag) child_setup_tty (xforkout); @@ -1874,7 +1870,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) p->alive = 1; /* Stop blocking in the parent. */ - unblock_child_signal (); + unblock_child_signal (&oldset); unblock_input (); if (pid < 0) @@ -1969,9 +1965,6 @@ create_pty (Lisp_Object process) /* Convert an internal struct sockaddr to a lisp object (vector or string). The address family of sa is not included in the result. */ -#ifndef WINDOWSNT -static -#endif Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *sa, int len) { @@ -2024,11 +2017,11 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len) terminator, however. */ if (name_length > 0 && sockun->sun_path[0] != '\0') { - const char* terminator = - memchr (sockun->sun_path, '\0', name_length); + const char *terminator + = memchr (sockun->sun_path, '\0', name_length); if (terminator) - name_length = terminator - (const char*) sockun->sun_path; + name_length = terminator - (const char *) sockun->sun_path; } return make_unibyte_string (sockun->sun_path, name_length); @@ -2085,8 +2078,10 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp) && VECTORP (XCDR (address))) { struct sockaddr *sa; - *familyp = XINT (XCAR (address)); p = XVECTOR (XCDR (address)); + if (MAX_ALLOCA - sizeof sa->sa_family < p->header.size) + return 0; + *familyp = XINT (XCAR (address)); return p->header.size + sizeof (sa->sa_family); } return 0; @@ -2858,7 +2853,7 @@ usage: (make-network-process &rest ARGS) */) struct gcpro gcpro1; ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count1; - Lisp_Object QCaddress; /* one of QClocal or QCremote */ + Lisp_Object colon_address; /* Either QClocal or QCremote. */ Lisp_Object tem; Lisp_Object name, buffer, host, service, address; Lisp_Object filter, sentinel; @@ -2906,8 +2901,8 @@ usage: (make-network-process &rest ARGS) */) backlog = XINT (tem); } - /* Make QCaddress an alias for :local (server) or :remote (client). */ - QCaddress = is_server ? QClocal : QCremote; + /* Make colon_address an alias for :local (server) or :remote (client). */ + colon_address = is_server ? QClocal : QCremote; /* :nowait BOOL */ if (!is_server && socktype != SOCK_DGRAM @@ -2934,7 +2929,7 @@ usage: (make-network-process &rest ARGS) */) res = &ai; /* :local ADDRESS or :remote ADDRESS */ - address = Fplist_get (contact, QCaddress); + address = Fplist_get (contact, colon_address); if (!NILP (address)) { host = service = Qnil; @@ -3003,7 +2998,7 @@ usage: (make-network-process &rest ARGS) */) address_un.sun_family = AF_LOCAL; if (sizeof address_un.sun_path <= SBYTES (service)) error ("Service name too long"); - strcpy (address_un.sun_path, SSDATA (service)); + lispstpcpy (address_un.sun_path, service); ai.ai_addr = (struct sockaddr *) &address_un; ai.ai_addrlen = sizeof address_un; goto open_socket; @@ -3321,7 +3316,7 @@ usage: (make-network-process &rest ARGS) */) memcpy (datagram_address[s].sa, lres->ai_addr, lres->ai_addrlen); } #endif - contact = Fplist_put (contact, QCaddress, + contact = Fplist_put (contact, colon_address, conv_sockaddr_to_lisp (lres->ai_addr, lres->ai_addrlen)); #ifdef HAVE_GETSOCKNAME if (!is_server) @@ -3694,7 +3689,7 @@ network_interface_info (Lisp_Object ifname) if (sizeof rq.ifr_name <= SBYTES (ifname)) error ("interface name too long"); - strcpy (rq.ifr_name, SSDATA (ifname)); + lispstpcpy (rq.ifr_name, ifname); s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) @@ -3936,19 +3931,20 @@ DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output, 0, 4, 0, doc: /* Allow any pending output from subprocesses to be read by Emacs. It is given to their filter functions. -Non-nil arg PROCESS means do not return until some output has been received -from PROCESS. +Optional argument PROCESS means do not return until output has been +received from PROCESS. -Non-nil second arg SECONDS and third arg MILLISEC are number of seconds -and milliseconds to wait; return after that much time whether or not -there is any subprocess output. If SECONDS is a floating point number, +Optional second argument SECONDS and third argument MILLISEC +specify a timeout; return after that much time even if there is +no subprocess output. If SECONDS is a floating point number, it specifies a fractional number of seconds to wait. The MILLISEC argument is obsolete and should be avoided. -If optional fourth arg JUST-THIS-ONE is non-nil, only accept output -from PROCESS, suspending reading output from other processes. +If optional fourth argument JUST-THIS-ONE is non-nil, accept output +from PROCESS only, suspending reading output from other processes. If JUST-THIS-ONE is an integer, don't run any timers either. -Return non-nil if we received any output before the timeout expired. */) +Return non-nil if we received any output from PROCESS (or, if PROCESS +is nil, from any process) before the timeout expired. */) (register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one) { intmax_t secs; @@ -4000,12 +3996,13 @@ Return non-nil if we received any output before the timeout expired. */) nsecs = 0; return - (wait_reading_process_output (secs, nsecs, 0, 0, + ((wait_reading_process_output (secs, nsecs, 0, 0, Qnil, !NILP (process) ? XPROCESS (process) : NULL, NILP (just_this_one) ? 0 : !INTEGERP (just_this_one) ? 1 : -1) - ? Qt : Qnil); + <= 0) + ? Qnil : Qt); } /* Accept a connection for server process SERVER on CHANNEL. */ @@ -4069,20 +4066,15 @@ server_accept_connection (Lisp_Object server, int channel) { case AF_INET: { - Lisp_Object args[5]; unsigned char *ip = (unsigned char *)&saddr.in.sin_addr.s_addr; - args[0] = build_string ("%d.%d.%d.%d"); - args[1] = make_number (*ip++); - args[2] = make_number (*ip++); - args[3] = make_number (*ip++); - args[4] = make_number (*ip++); - host = Fformat (5, args); - service = make_number (ntohs (saddr.in.sin_port)); - args[0] = build_string (" <%s:%d>"); - args[1] = host; - args[2] = service; - caller = Fformat (3, args); + AUTO_STRING (ipv4_format, "%d.%d.%d.%d"); + host = Fformat (5, ((Lisp_Object []) + { ipv4_format, make_number (ip[0]), + make_number (ip[1]), make_number (ip[2]), make_number (ip[3]) })); + service = make_number (ntohs (saddr.in.sin_port)); + AUTO_STRING (caller_format, " <%s:%d>"); + caller = Fformat (3, (Lisp_Object []) {caller_format, host, service}); } break; @@ -4092,16 +4084,15 @@ server_accept_connection (Lisp_Object server, int channel) Lisp_Object args[9]; uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr; int i; - args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); + + AUTO_STRING (ipv6_format, "%x:%x:%x:%x:%x:%x:%x:%x"); + args[0] = ipv6_format; for (i = 0; i < 8; i++) - args[i+1] = make_number (ntohs (ip6[i])); + args[i + 1] = make_number (ntohs (ip6[i])); host = Fformat (9, args); service = make_number (ntohs (saddr.in.sin_port)); - - args[0] = build_string (" <[%s]:%d>"); - args[1] = host; - args[2] = service; - caller = Fformat (3, args); + AUTO_STRING (caller_format, " <[%s]:%d>"); + caller = Fformat (3, (Lisp_Object []) {caller_format, host, service}); } break; #endif @@ -4111,7 +4102,9 @@ server_accept_connection (Lisp_Object server, int channel) #endif default: caller = Fnumber_to_string (make_number (connect_counter)); - caller = concat3 (build_string (" <"), caller, build_string (">")); + AUTO_STRING (space_less_than, " <"); + AUTO_STRING (greater_than, ">"); + caller = concat3 (space_less_than, caller, greater_than); break; } @@ -4208,16 +4201,18 @@ server_accept_connection (Lisp_Object server, int channel) p->inherit_coding_system_flag = (NILP (buffer) ? 0 : ps->inherit_coding_system_flag); + AUTO_STRING (dash, "-"); + AUTO_STRING (nl, "\n"); + Lisp_Object host_string = STRINGP (host) ? host : dash; + if (!NILP (ps->log)) - call3 (ps->log, server, proc, - concat3 (build_string ("accept from "), - (STRINGP (host) ? host : build_string ("-")), - build_string ("\n"))); + { + AUTO_STRING (accept_from, "accept from "); + call3 (ps->log, server, proc, concat3 (accept_from, host_string, nl)); + } - exec_sentinel (proc, - concat3 (build_string ("open from "), - (STRINGP (host) ? host : build_string ("-")), - build_string ("\n"))); + AUTO_STRING (open_from, "open from "); + exec_sentinel (proc, concat3 (open_from, host_string, nl)); } /* This variable is different from waiting_for_input in keyboard.c. @@ -4270,18 +4265,17 @@ wait_reading_process_output_1 (void) (and gobble terminal input into the buffer if any arrives). If WAIT_PROC is specified, wait until something arrives from that - process. The return value is true if we read some input from - that process. + process. If JUST_WAIT_PROC is nonzero, handle only output from WAIT_PROC (suspending output from other processes). A negative value means don't run any timers either. - If WAIT_PROC is specified, then the function returns true if we - received input from that process before the timeout elapsed. - Otherwise, return true if we received input from any process. */ + Return positive if we received input from WAIT_PROC (or from any + process if WAIT_PROC is null), zero if we attempted to receive + input but got none, and negative if we didn't even try. */ -bool +int wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -4296,8 +4290,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, int xerrno; Lisp_Object proc; struct timespec timeout, end_time; - int wait_channel = -1; - bool got_some_input = 0; + int got_some_input = -1; ptrdiff_t count = SPECPDL_INDEX (); FD_ZERO (&Available); @@ -4308,10 +4301,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && EQ (XCAR (wait_proc->status), Qexit))) message1 ("Blocking call to accept-process-output with quit inhibited!!"); - /* If wait_proc is a process to watch, set wait_channel accordingly. */ - if (wait_proc != NULL) - wait_channel = wait_proc->infd; - record_unwind_protect_int (wait_reading_process_output_unwind, waiting_for_user_input_p); waiting_for_user_input_p = read_kbd; @@ -4348,6 +4337,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) break; + /* After reading input, vacuum up any leftovers without waiting. */ + if (0 <= got_some_input) + nsecs = -1; + /* Compute time from now till when time limit is up. */ /* Exit if already run out. */ if (nsecs < 0) @@ -4466,7 +4459,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* It's okay for us to do this and then continue with the loop, since timeout has already been zeroed out. */ clear_waiting_for_input (); - status_notify (NULL); + got_some_input = status_notify (NULL, wait_proc); if (do_display) redisplay_preserve_echo_area (13); } } @@ -4476,6 +4469,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (wait_proc && wait_proc->raw_status_new) update_status (wait_proc); if (wait_proc + && wait_proc->infd >= 0 && ! EQ (wait_proc->status, Qrun) && ! EQ (wait_proc->status, Qconnect)) { @@ -4485,21 +4479,26 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, XSETPROCESS (proc, wait_proc); /* Read data from the process, until we exhaust it. */ - while (wait_proc->infd >= 0) + while (true) { int nread = read_process_output (proc, wait_proc->infd); - - if (nread == 0) - break; - - if (nread > 0) - got_some_input = read_some_bytes = 1; - else if (nread == -1 && (errno == EIO || errno == EAGAIN)) - break; + if (nread < 0) + { + if (errno == EIO || errno == EAGAIN) + break; #ifdef EWOULDBLOCK - else if (nread == -1 && EWOULDBLOCK == errno) - break; + if (errno == EWOULDBLOCK) + break; #endif + } + else + { + if (got_some_input < nread) + got_some_input = nread; + if (nread == 0) + break; + read_some_bytes = true; + } } if (read_some_bytes && do_display) redisplay_preserve_echo_area (10); @@ -4530,12 +4529,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, else Available = input_wait_mask; Writeok = write_mask; -#ifdef SELECT_CANT_DO_WRITE_MASK - check_write = 0; -#else - check_write = 1; -#endif - check_delay = wait_channel >= 0 ? 0 : process_output_delay_count; + check_delay = wait_proc ? 0 : process_output_delay_count; + check_write = SELECT_CAN_DO_WRITE_MASK; } /* If frame size has changed or the window is newly mapped, @@ -4561,6 +4556,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { nfds = read_kbd ? 0 : 1; no_avail = 1; + FD_ZERO (&Available); } if (!no_avail) @@ -4570,7 +4566,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* Set the timeout for adaptive read buffering if any process has non-zero read_output_skip and non-zero read_output_delay, and we are not reading output for a - specific wait_channel. It is not executed if + specific process. It is not executed if Vprocess_adaptive_read_buffering is nil. */ if (process_output_skip && check_delay > 0) { @@ -4632,12 +4628,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { struct Lisp_Process *p = XPROCESS (chan_process[channel]); - if (p && p->gnutls_p && p->gnutls_state && p->infd + if (p && p->gnutls_p && p->gnutls_state && ((emacs_gnutls_record_check_pending (p->gnutls_state)) > 0)) { nfds++; + eassert (p->infd == channel); FD_SET (p->infd, &Available); } } @@ -4653,6 +4650,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, > 0)) { nfds = 1; + eassert (0 <= wait_proc->infd); /* Set to Available. */ FD_SET (wait_proc->infd, &Available); } @@ -4682,12 +4680,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, report_file_errno ("Failed select", Qnil, xerrno); } - if (no_avail) - { - FD_ZERO (&Available); - check_write = 0; - } - /* Check for keyboard input */ /* If there is any, return immediately to give it higher priority than subprocesses */ @@ -4754,9 +4746,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, handle_input_available_signal (SIGIO); #endif - if (! wait_proc) - got_some_input |= nfds > 0; - /* If checking input just got us a size-change event from X, obey it now if we should. */ if (read_kbd || ! NILP (wait_for_cell)) @@ -4788,12 +4777,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* If waiting for this channel, arrange to return as soon as no more input to be processed. No more waiting. */ - if (wait_channel == channel) - { - wait_channel = -1; - nsecs = -1; - got_some_input = 1; - } proc = chan_process[channel]; if (NILP (proc)) continue; @@ -4809,6 +4792,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, buffered-ahead character if we have one. */ nread = read_process_output (proc, channel); + if ((!wait_proc || wait_proc == XPROCESS (proc)) && got_some_input < nread) + got_some_input = nread; if (nread > 0) { /* Since read_process_output can run a filter, @@ -4933,7 +4918,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, status_notify to do it later, it will read input from the process before calling the sentinel. */ exec_sentinel (proc, build_string ("open\n")); - if (!EQ (p->filter, Qt) && !EQ (p->command, Qt)) + if (0 <= p->infd && !EQ (p->filter, Qt) + && !EQ (p->command, Qt)) { FD_SET (p->infd, &input_wait_mask); FD_SET (p->infd, &non_keyboard_wait_mask); @@ -4994,18 +4980,17 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, for decoding. */ static int -read_process_output (Lisp_Object proc, register int channel) +read_process_output (Lisp_Object proc, int channel) { - register ssize_t nbytes; - char *chars; - register struct Lisp_Process *p = XPROCESS (proc); + ssize_t nbytes; + struct Lisp_Process *p = XPROCESS (proc); struct coding_system *coding = proc_decode_coding_system[channel]; int carryover = p->decoding_carryover; - int readmax = 4096; + enum { readmax = 4096 }; ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object odeactivate; + char chars[sizeof coding->carryover + readmax]; - chars = alloca (carryover + readmax); if (carryover) /* See the comment above. */ memcpy (chars, SDATA (p->decoding_buf), carryover); @@ -5155,7 +5140,7 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, proc_encode_coding_system[p->outfd] surely points to a valid memory because p->outfd will be changed once EOF is sent to the process. */ - if (NILP (p->encode_coding_system) + if (NILP (p->encode_coding_system) && p->outfd >= 0 && proc_encode_coding_system[p->outfd]) { pset_encode_coding_system @@ -5829,36 +5814,31 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, p->tick = ++process_tick; if (!nomsg) { - status_notify (NULL); + status_notify (NULL, NULL); redisplay_preserve_echo_area (13); } } #endif +#ifdef TIOCSIGSEND + /* Work around a HP-UX 7.0 bug that mishandles signals to subjobs. + We don't know whether the bug is fixed in later HP-UX versions. */ + if (! NILP (current_group) && ioctl (p->infd, TIOCSIGSEND, signo) != -1) + return; +#endif + /* If we don't have process groups, send the signal to the immediate subprocess. That isn't really right, but it's better than any obvious alternative. */ - if (no_pgrp) - { - kill (p->pid, signo); - return; - } + pid_t pid = no_pgrp ? gid : - gid; - /* gid may be a pid, or minus a pgrp's number */ -#ifdef TIOCSIGSEND - if (!NILP (current_group)) - { - if (ioctl (p->infd, TIOCSIGSEND, signo) == -1) - kill (-gid, signo); - } - else - { - gid = - p->pid; - kill (gid, signo); - } -#else /* ! defined (TIOCSIGSEND) */ - kill (-gid, signo); -#endif /* ! defined (TIOCSIGSEND) */ + /* Do not kill an already-reaped process, as that could kill an + innocent bystander that happens to have the same process ID. */ + sigset_t oldset; + block_child_signal (&oldset); + if (p->alive) + kill (pid, signo); + unblock_child_signal (&oldset); } DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0, @@ -6100,8 +6080,8 @@ process has been transmitted to the serial port. */) for communication with the subprocess, call shutdown to cause EOF. (In some old system, shutdown to socketpair doesn't work. Then we just can't win.) */ - if (EQ (p->type, Qnetwork) - || p->infd == old_outfd) + if (0 <= old_outfd + && (EQ (p->type, Qnetwork) || p->infd == old_outfd)) shutdown (old_outfd, 1); #endif close_process_fd (&p->open_fd[WRITE_TO_SUBPROCESS]); @@ -6357,14 +6337,20 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason) /* Report all recent events of a change in process status (either run the sentinel or output a message). This is usually done while Emacs is waiting for keyboard input - but can be done at other times. */ + but can be done at other times. -static void -status_notify (struct Lisp_Process *deleting_process) + Return positive if any input was received from WAIT_PROC (or from + any process if WAIT_PROC is null), zero if input was attempted but + none received, and negative if we didn't even try. */ + +static int +status_notify (struct Lisp_Process *deleting_process, + struct Lisp_Process *wait_proc) { - register Lisp_Object proc; + Lisp_Object proc; Lisp_Object tail, msg; struct gcpro gcpro1, gcpro2; + int got_some_input = -1; tail = Qnil; msg = Qnil; @@ -6394,8 +6380,14 @@ status_notify (struct Lisp_Process *deleting_process) /* Network or serial process not stopped: */ && ! EQ (p->command, Qt) && p->infd >= 0 - && p != deleting_process - && read_process_output (proc, p->infd) > 0); + && p != deleting_process) + { + int nread = read_process_output (proc, p->infd); + if (got_some_input < nread) + got_some_input = nread; + if (nread <= 0) + break; + } /* Get the text to use for the message. */ if (p->raw_status_new) @@ -6427,6 +6419,7 @@ status_notify (struct Lisp_Process *deleting_process) update_mode_lines = 24; /* In case buffers use %s in mode-line-format. */ UNGCPRO; + return got_some_input; } DEFUN ("internal-default-process-sentinel", Finternal_default_process_sentinel, @@ -6562,6 +6555,8 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p, CHECK_PROCESS (process); p = XPROCESS (process); + if (p->infd < 0) + return Qnil; coding = proc_decode_coding_system[p->infd]; return (CODING_FOR_UNIBYTE (coding) ? Qnil : Qt); } @@ -6606,7 +6601,7 @@ keyboard_bit_set (fd_set *mask) #else /* not subprocesses */ -/* Defined on msdos.c. */ +/* Defined in msdos.c. */ extern int sys_select (int, fd_set *, fd_set *, fd_set *, struct timespec *, void *); @@ -6638,9 +6633,11 @@ extern int sys_select (int, fd_set *, fd_set *, fd_set *, DO_DISPLAY means redisplay should be done to show subprocess output that arrives. - Return true if we received input from any process. */ + Return positive if we received input from WAIT_PROC (or from any + process if WAIT_PROC is null), zero if we attempted to receive + input but got none, and negative if we didn't even try. */ -bool +int wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -6828,7 +6825,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, start_polling (); - return 0; + return -1; } #endif /* not subprocesses */ @@ -6836,6 +6833,26 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* The following functions are needed even if async subprocesses are not supported. Some of them are no-op stubs in that case. */ +#ifdef HAVE_TIMERFD + +/* Add FD, which is a descriptor returned by timerfd_create, + to the set of non-keyboard input descriptors. */ + +void +add_timer_wait_descriptor (int fd) +{ + FD_SET (fd, &input_wait_mask); + FD_SET (fd, &non_keyboard_wait_mask); + FD_SET (fd, &non_process_wait_mask); + fd_callback_info[fd].func = timerfd_callback; + fd_callback_info[fd].data = NULL; + fd_callback_info[fd].condition |= FOR_READ; + if (fd > max_input_desc) + max_input_desc = fd; +} + +#endif /* HAVE_TIMERFD */ + /* Add DESC to the set of keyboard input descriptors. */ void @@ -7067,15 +7084,13 @@ integer or floating point values. futz with the SIGCHLD handler, but before Emacs forks any children. This function's caller should block SIGCHLD. */ -#ifndef NS_IMPL_GNUSTEP -static -#endif void catch_child_signal (void) { struct sigaction action, old_action; + sigset_t oldset; emacs_sigaction_init (&action, deliver_child_signal); - block_child_signal (); + block_child_signal (&oldset); sigaction (SIGCHLD, &action, &old_action); eassert (! (old_action.sa_flags & SA_SIGINFO)); @@ -7084,7 +7099,7 @@ catch_child_signal (void) = (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN ? dummy_handler : old_action.sa_handler); - unblock_child_signal (); + unblock_child_signal (&oldset); } #endif /* subprocesses */ diff --git a/src/process.h b/src/process.h index c3481f295f5..273ad9267d6 100644 --- a/src/process.h +++ b/src/process.h @@ -213,8 +213,6 @@ enum /* Defined in callproc.c. */ -extern void block_child_signal (void); -extern void unblock_child_signal (void); extern Lisp_Object encode_current_directory (void); extern void record_kill_process (struct Lisp_Process *, Lisp_Object); @@ -227,9 +225,7 @@ extern Lisp_Object system_process_attributes (Lisp_Object); extern void record_deleted_pid (pid_t, Lisp_Object); struct sockaddr; -#ifdef WINDOWSNT extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, int); -#endif extern void hold_keyboard_input (void); extern void unhold_keyboard_input (void); extern bool kbd_on_hold_p (void); @@ -240,9 +236,7 @@ extern void add_read_fd (int fd, fd_callback func, void *data); extern void delete_read_fd (int fd); extern void add_write_fd (int fd, fd_callback func, void *data); extern void delete_write_fd (int fd); -#ifdef NS_IMPL_GNUSTEP extern void catch_child_signal (void); -#endif #ifdef WINDOWSNT extern Lisp_Object network_interface_list (void); diff --git a/src/profiler.c b/src/profiler.c index fff7c6b0ff6..919aabc92af 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -294,7 +294,7 @@ setup_cpu_timer (Lisp_Object sampling_interval) sigev.sigev_signo = SIGPROF; sigev.sigev_notify = SIGEV_SIGNAL; - for (i = 0; i < sizeof system_clock / sizeof *system_clock; i++) + for (i = 0; i < ARRAYELTS (system_clock); i++) if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) { profiler_timer_ok = 1; diff --git a/src/puresize.h b/src/puresize.h index ad591c75672..376b11cf75b 100644 --- a/src/puresize.h +++ b/src/puresize.h @@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif #ifndef BASE_PURESIZE -#define BASE_PURESIZE (1720000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) +#define BASE_PURESIZE (1800000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) #endif /* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ diff --git a/src/ralloc.c b/src/ralloc.c index c82cd4548d2..e63ed34c89b 100644 --- a/src/ralloc.c +++ b/src/ralloc.c @@ -35,9 +35,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define M_TOP_PAD -2 extern int mallopt (int, int); #else /* not DOUG_LEA_MALLOC */ -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC extern size_t __malloc_extra_blocks; -#endif /* SYSTEM_MALLOC */ +#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */ #endif /* not DOUG_LEA_MALLOC */ #else /* not emacs */ @@ -95,7 +95,7 @@ static int extra_bytes; /* The hook `malloc' uses for the function which gets more space from the system. */ -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC extern void *(*__morecore) (ptrdiff_t); #endif @@ -1179,7 +1179,7 @@ r_alloc_init (void) r_alloc_initialized = 1; page_size = PAGE; -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC real_morecore = __morecore; __morecore = r_alloc_sbrk; @@ -1198,7 +1198,7 @@ r_alloc_init (void) mallopt (M_TOP_PAD, 64 * 4096); unblock_input (); #else -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC /* Give GNU malloc's morecore some hysteresis so that we move all the relocatable blocks much less often. The number used to be 64, but alloc.c would override that with 32 in code that was @@ -1211,7 +1211,7 @@ r_alloc_init (void) #endif #endif -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC first_heap->end = (void *) PAGE_ROUNDUP (first_heap->start); /* The extra call to real_morecore guarantees that the end of the diff --git a/src/regex.c b/src/regex.c index 244924058a0..766ad26e709 100644 --- a/src/regex.c +++ b/src/regex.c @@ -457,11 +457,17 @@ init_syntax_once (void) # endif /* not alloca */ -# define REGEX_ALLOCATE alloca +# ifdef emacs +# define REGEX_USE_SAFE_ALLOCA USE_SAFE_ALLOCA +# define REGEX_SAFE_FREE() SAFE_FREE () +# define REGEX_ALLOCATE SAFE_ALLOCA +# else +# define REGEX_ALLOCATE alloca +# endif /* Assumes a `char *destination' variable. */ # define REGEX_REALLOCATE(source, osize, nsize) \ - (destination = alloca (nsize), \ + (destination = REGEX_ALLOCATE (nsize), \ memcpy (destination, source, osize)) /* No need to do anything to free, after alloca. */ @@ -469,6 +475,11 @@ init_syntax_once (void) #endif /* not REGEX_MALLOC */ +#ifndef REGEX_USE_SAFE_ALLOCA +# define REGEX_USE_SAFE_ALLOCA ((void) 0) +# define REGEX_SAFE_FREE() ((void) 0) +#endif + /* Define how to allocate the failure stack. */ #if defined REL_ALLOC && defined REGEX_MALLOC @@ -482,22 +493,10 @@ init_syntax_once (void) #else /* not using relocating allocator */ -# ifdef REGEX_MALLOC - -# define REGEX_ALLOCATE_STACK malloc -# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) -# define REGEX_FREE_STACK free - -# else /* not REGEX_MALLOC */ +# define REGEX_ALLOCATE_STACK(size) REGEX_ALLOCATE (size) +# define REGEX_REALLOCATE_STACK(source, o, n) REGEX_REALLOCATE (source, o, n) +# define REGEX_FREE_STACK(ptr) REGEX_FREE (ptr) -# define REGEX_ALLOCATE_STACK alloca - -# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ - REGEX_REALLOCATE (source, osize, nsize) -/* No need to explicitly free anything. */ -# define REGEX_FREE_STACK(arg) ((void)0) - -# endif /* not REGEX_MALLOC */ #endif /* not using relocating allocator */ @@ -516,10 +515,12 @@ init_syntax_once (void) #define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) -#undef MAX -#undef MIN -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#ifndef emacs +# undef max +# undef min +# define max(a, b) ((a) > (b) ? (a) : (b)) +# define min(a, b) ((a) < (b) ? (a) : (b)) +#endif /* Type of source-pattern and string chars. */ #ifdef _MSC_VER @@ -713,7 +714,8 @@ typedef enum static int extract_number (re_char *source) { - return (SIGN_EXTEND_CHAR (source[1]) << 8) + source[0]; + unsigned leading_byte = SIGN_EXTEND_CHAR (source[1]); + return (leading_byte << 8) + source[0]; } /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. @@ -1189,12 +1191,7 @@ print_double_string (re_char *where, re_char *string1, ssize_t size1, # define assert(e) # define DEBUG_STATEMENT(e) -# if __STDC_VERSION__ < 199901L -# define DEBUG_COMPILES_ARGUMENTS -# define DEBUG_PRINT /* 'DEBUG_PRINT (x, y)' discards X and Y. */ (void) -# else -# define DEBUG_PRINT(...) -# endif +# define DEBUG_PRINT(...) # define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) # define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) @@ -1399,14 +1396,14 @@ typedef struct : ((fail_stack).stack \ = REGEX_REALLOCATE_STACK ((fail_stack).stack, \ (fail_stack).size * sizeof (fail_stack_elt_t), \ - MIN (re_max_failures * TYPICAL_FAILURE_SIZE, \ + min (re_max_failures * TYPICAL_FAILURE_SIZE, \ ((fail_stack).size * sizeof (fail_stack_elt_t) \ * FAIL_STACK_GROWTH_FACTOR))), \ \ (fail_stack).stack == NULL \ ? 0 \ : ((fail_stack).size \ - = (MIN (re_max_failures * TYPICAL_FAILURE_SIZE, \ + = (min (re_max_failures * TYPICAL_FAILURE_SIZE, \ ((fail_stack).size * sizeof (fail_stack_elt_t) \ * FAIL_STACK_GROWTH_FACTOR)) \ / sizeof (fail_stack_elt_t)), \ @@ -2314,8 +2311,8 @@ set_image_of_range (struct range_table_work_area *work_area, cmin = c, cmax = c; else { - cmin = MIN (cmin, c); - cmax = MAX (cmax, c); + cmin = min (cmin, c); + cmax = max (cmax, c); } } } @@ -2994,7 +2991,7 @@ regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax, #else /* emacs */ if (c < 128) { - ch = MIN (127, c1); + ch = min (127, c1); SETUP_ASCII_RANGE (range_table_work, c, ch); c = ch + 1; if (CHAR_BYTE8_P (c1)) @@ -4346,8 +4343,7 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1, size_t size1, if (range > 0) /* Searching forwards. */ { - register int lim = 0; - ssize_t irange = range; + ssize_t irange = range, lim = 0; if (startpos < size1 && startpos + range >= size1) lim = range - (size1 - startpos); @@ -4584,6 +4580,7 @@ static int bcmp_translate (re_char *s1, re_char *s2, FREE_VAR (regend); \ FREE_VAR (best_regstart); \ FREE_VAR (best_regend); \ + REGEX_SAFE_FREE (); \ } while (0) #else # define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ @@ -5023,6 +5020,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1, DEBUG_PRINT ("\n\nEntering re_match_2.\n"); + REGEX_USE_SAFE_ALLOCA; + INIT_FAIL_STACK (); #ifdef MATCH_MAY_ALLOCATE @@ -5213,7 +5212,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1, { /* No. So allocate them with malloc. We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ - regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->num_regs = max (RE_NREGS, num_regs + 1); regs->start = TALLOC (regs->num_regs, regoff_t); regs->end = TALLOC (regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) @@ -5257,7 +5256,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1, /* Go through the first `min (num_regs, regs->num_regs)' registers, since that is all we initialized. */ - for (reg = 1; reg < MIN (num_regs, regs->num_regs); reg++) + for (reg = 1; reg < min (num_regs, regs->num_regs); reg++) { if (REG_UNSET (regstart[reg]) || REG_UNSET (regend[reg])) regs->start[reg] = regs->end[reg] = -1; diff --git a/src/regex.h b/src/regex.h index 1b064987eb7..0e25723a85e 100644 --- a/src/regex.h +++ b/src/regex.h @@ -172,6 +172,9 @@ extern reg_syntax_t re_syntax_options; extern Lisp_Object re_match_object; #endif +/* Roughly the maximum number of failure points on the stack. */ +extern size_t re_max_failures; + /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so diff --git a/src/scroll.c b/src/scroll.c index 3da236ca8a6..7cb683c4577 100644 --- a/src/scroll.c +++ b/src/scroll.c @@ -90,7 +90,7 @@ calculate_scrolling (struct frame *frame, /* matrix is of size window_size + 1 on each side. */ struct matrix_elt *matrix, int window_size, int lines_below, - int *draw_cost, int *old_hash, int *new_hash, + int *draw_cost, unsigned *old_hash, unsigned *new_hash, int free_at_end) { register int i, j; @@ -245,18 +245,20 @@ do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, { struct matrix_elt *p; int i, j, k; + USE_SAFE_ALLOCA; /* True if we have set a terminal window with set_terminal_window. */ bool terminal_window_p = 0; /* A queue for line insertions to be done. */ struct queue { int count, pos; }; - struct queue *queue_start - = alloca (current_matrix->nrows * sizeof *queue_start); + struct queue *queue_start; + SAFE_NALLOCA (queue_start, 1, current_matrix->nrows); struct queue *queue = queue_start; - char *retained_p = alloca (window_size * sizeof *retained_p); - int *copy_from = alloca (window_size * sizeof *copy_from); + char *retained_p = SAFE_ALLOCA (window_size); + int *copy_from; + SAFE_NALLOCA (copy_from, 1, window_size); /* Zero means line is empty. */ memset (retained_p, 0, window_size * sizeof (char)); @@ -378,6 +380,7 @@ do_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, if (terminal_window_p) set_terminal_window (frame, 0); + SAFE_FREE (); } @@ -427,7 +430,7 @@ calculate_direct_scrolling (struct frame *frame, struct matrix_elt *matrix, int window_size, int lines_below, int *draw_cost, int *old_draw_cost, - int *old_hash, int *new_hash, + unsigned *old_hash, unsigned *new_hash, int free_at_end) { register int i, j; @@ -649,10 +652,12 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, { struct matrix_elt *p; int i, j; + USE_SAFE_ALLOCA; /* A queue of deletions and insertions to be performed. */ struct alt_queue { int count, pos, window; }; - struct alt_queue *queue_start = alloca (window_size * sizeof *queue_start); + struct alt_queue *queue_start; + SAFE_NALLOCA (queue_start, 1, window_size); struct alt_queue *queue = queue_start; /* True if a terminal window has been set with set_terminal_window. */ @@ -667,11 +672,12 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, bool write_follows_p = 1; /* For each row in the new matrix what row of the old matrix it is. */ - int *copy_from = alloca (window_size * sizeof *copy_from); + int *copy_from; + SAFE_NALLOCA (copy_from, 1, window_size); /* Non-zero for each row in the new matrix that is retained from the old matrix. Lines not retained are empty. */ - char *retained_p = alloca (window_size * sizeof *retained_p); + char *retained_p = SAFE_ALLOCA (window_size); memset (retained_p, 0, window_size * sizeof (char)); @@ -787,6 +793,7 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, if (terminal_window_p) set_terminal_window (frame, 0); + SAFE_FREE (); } @@ -794,10 +801,11 @@ do_direct_scrolling (struct frame *frame, struct glyph_matrix *current_matrix, void scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top, int unchanged_at_bottom, int *draw_cost, int *old_draw_cost, - int *old_hash, int *new_hash, int free_at_end) + unsigned *old_hash, unsigned *new_hash, int free_at_end) { - struct matrix_elt *matrix - = alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix); + USE_SAFE_ALLOCA; + struct matrix_elt *matrix; + SAFE_NALLOCA (matrix, window_size + 1, window_size + 1); if (FRAME_SCROLL_REGION_OK (frame)) { @@ -817,6 +825,8 @@ scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top, frame->current_matrix, matrix, window_size, unchanged_at_top); } + + SAFE_FREE (); } @@ -829,12 +839,14 @@ scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top, int scrolling_max_lines_saved (int start, int end, - int *oldhash, int *newhash, + unsigned *oldhash, unsigned *newhash, int *cost) { - struct { int hash; int count; } lines[01000]; - register int i, h; - register int matchcount = 0; + enum { LOG2_NLINES = 9 }; + enum { NLINES = 1 << LOG2_NLINES }; + struct { unsigned hash; int count; } lines[NLINES]; + int i, h; + int matchcount = 0; int avg_length = 0; int threshold; @@ -855,7 +867,7 @@ scrolling_max_lines_saved (int start, int end, { if (cost[i] > threshold) { - h = newhash[i] & 0777; + h = newhash[i] & (NLINES - 1); lines[h].hash = newhash[i]; lines[h].count++; } @@ -865,7 +877,7 @@ scrolling_max_lines_saved (int start, int end, matches between old lines and new. */ for (i = start; i < end; i++) { - h = oldhash[i] & 0777; + h = oldhash[i] & (NLINES - 1); if (oldhash[i] == lines[h].hash) { matchcount++; diff --git a/src/search.c b/src/search.c index 0a693daa15e..c6ae9d7e922 100644 --- a/src/search.c +++ b/src/search.c @@ -985,6 +985,24 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, return shortage; } +/* Like above, but always scan from point and report the + resulting position in *CHARPOS and *BYTEPOS. */ + +ptrdiff_t +scan_newline_from_point (ptrdiff_t count, ptrdiff_t *charpos, + ptrdiff_t *bytepos) +{ + ptrdiff_t shortage; + + if (count <= 0) + *charpos = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, count - 1, + &shortage, bytepos, 1); + else + *charpos = find_newline (PT, PT_BYTE, ZV, ZV_BYTE, count, + &shortage, bytepos, 1); + return shortage; +} + /* Like find_newline, but doesn't allow QUITting and doesn't return SHORTAGE. */ ptrdiff_t @@ -1318,6 +1336,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, translation. Otherwise set to zero later. */ int char_base = -1; bool boyer_moore_ok = 1; + USE_SAFE_ALLOCA; /* MULTIBYTE says whether the text to be searched is multibyte. We must convert PATTERN to match that, or we will not really @@ -1335,7 +1354,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, raw_pattern_size_byte = count_size_as_multibyte (SDATA (string), raw_pattern_size); - raw_pattern = alloca (raw_pattern_size_byte + 1); + raw_pattern = SAFE_ALLOCA (raw_pattern_size_byte + 1); copy_text (SDATA (string), raw_pattern, SCHARS (string), 0, 1); } @@ -1349,7 +1368,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, the chosen single-byte character set can possibly match. */ raw_pattern_size = SCHARS (string); raw_pattern_size_byte = SCHARS (string); - raw_pattern = alloca (raw_pattern_size + 1); + raw_pattern = SAFE_ALLOCA (raw_pattern_size + 1); copy_text (SDATA (string), raw_pattern, SBYTES (string), 1, 0); } @@ -1357,7 +1376,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, /* Copy and optionally translate the pattern. */ len = raw_pattern_size; len_byte = raw_pattern_size_byte; - patbuf = alloca (len * MAX_MULTIBYTE_LENGTH); + SAFE_NALLOCA (patbuf, MAX_MULTIBYTE_LENGTH, len); pat = patbuf; base_pat = raw_pattern; if (multibyte) @@ -1416,7 +1435,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, while (boyer_moore_ok) { - if (ASCII_BYTE_P (inverse)) + if (ASCII_CHAR_P (inverse)) { if (this_char_base > 0) boyer_moore_ok = 0; @@ -1497,13 +1516,15 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, len_byte = pat - patbuf; pat = base_pat = patbuf; - if (boyer_moore_ok) - return boyer_moore (n, pat, len_byte, trt, inverse_trt, - pos_byte, lim_byte, - char_base); - else - return simple_search (n, pat, raw_pattern_size, len_byte, trt, - pos, pos_byte, lim, lim_byte); + EMACS_INT result + = (boyer_moore_ok + ? boyer_moore (n, pat, len_byte, trt, inverse_trt, + pos_byte, lim_byte, + char_base) + : simple_search (n, pat, raw_pattern_size, len_byte, trt, + pos, pos_byte, lim, lim_byte)); + SAFE_FREE (); + return result; } } @@ -1827,7 +1848,7 @@ boyer_moore (EMACS_INT n, unsigned char *base_pat, matching with CHAR_BASE are to be checked. */ int ch = -1; - if (ASCII_BYTE_P (*ptr) || ! multibyte) + if (ASCII_CHAR_P (*ptr) || ! multibyte) ch = *ptr; else if (char_base && ((pat_end - ptr) == 1 || CHAR_HEAD_P (ptr[1]))) @@ -2596,7 +2617,7 @@ since only regular expressions have distinguished subexpressions. */) { FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, newtext, pos, pos_byte); if (!buf_multibyte) - c = multibyte_char_to_unibyte (c); + c = CHAR_TO_BYTE8 (c); } else { @@ -2619,7 +2640,7 @@ since only regular expressions have distinguished subexpressions. */) FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, newtext, pos, pos_byte); if (!buf_multibyte && !ASCII_CHAR_P (c)) - c = multibyte_char_to_unibyte (c); + c = CHAR_TO_BYTE8 (c); } else { @@ -2679,18 +2700,8 @@ since only regular expressions have distinguished subexpressions. */) } if (really_changed) - { - if (buf_multibyte) - { - ptrdiff_t nchars = - multibyte_chars_in_text (substed, substed_len); - - newtext = make_multibyte_string ((char *) substed, nchars, - substed_len); - } - else - newtext = make_unibyte_string ((char *) substed, substed_len); - } + newtext = make_specified_string ((const char *) substed, -1, + substed_len, buf_multibyte); xfree (substed); } @@ -2819,7 +2830,8 @@ Return value is undefined if the last search failed. */) prev = Qnil; - data = alloca ((2 * search_regs.num_regs + 1) * sizeof *data); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (data, 1, 2 * search_regs.num_regs + 1); len = 0; for (i = 0; i < search_regs.num_regs; i++) @@ -2862,25 +2874,28 @@ Return value is undefined if the last search failed. */) /* If REUSE is not usable, cons up the values and return them. */ if (! CONSP (reuse)) - return Flist (len, data); - - /* If REUSE is a list, store as many value elements as will fit - into the elements of REUSE. */ - for (i = 0, tail = reuse; CONSP (tail); - i++, tail = XCDR (tail)) + reuse = Flist (len, data); + else { + /* If REUSE is a list, store as many value elements as will fit + into the elements of REUSE. */ + for (i = 0, tail = reuse; CONSP (tail); + i++, tail = XCDR (tail)) + { + if (i < len) + XSETCAR (tail, data[i]); + else + XSETCAR (tail, Qnil); + prev = tail; + } + + /* If we couldn't fit all value elements into REUSE, + cons up the rest of them and add them to the end of REUSE. */ if (i < len) - XSETCAR (tail, data[i]); - else - XSETCAR (tail, Qnil); - prev = tail; + XSETCDR (prev, Flist (len - i, data + i)); } - /* If we couldn't fit all value elements into REUSE, - cons up the rest of them and add them to the end of REUSE. */ - if (i < len) - XSETCDR (prev, Flist (len - i, data + i)); - + SAFE_FREE (); return reuse; } @@ -3085,7 +3100,8 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0, CHECK_STRING (string); - temp = alloca (SBYTES (string) * 2); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (temp, 2, SBYTES (string)); /* Now copy the data into the new string, inserting escapes. */ @@ -3103,10 +3119,13 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0, *out++ = *in; } - return make_specified_string (temp, - SCHARS (string) + backslashes_added, - out - temp, - STRING_MULTIBYTE (string)); + Lisp_Object result + = make_specified_string (temp, + SCHARS (string) + backslashes_added, + out - temp, + STRING_MULTIBYTE (string)); + SAFE_FREE (); + return result; } /* Like find_newline, but doesn't use the cache, and only searches forward. */ diff --git a/src/sheap.c b/src/sheap.c index 5069744435b..956faa36aa1 100644 --- a/src/sheap.c +++ b/src/sheap.c @@ -44,6 +44,8 @@ int debug_sheap = 0; #define BLOCKSIZE 4096 char bss_sbrk_buffer[STATIC_HEAP_SIZE]; +/* The following is needed in gmalloc.c */ +void *bss_sbrk_buffer_end = bss_sbrk_buffer + STATIC_HEAP_SIZE; char *bss_sbrk_ptr; char *max_bss_sbrk_ptr; int bss_sbrk_did_unexec; diff --git a/src/sound.c b/src/sound.c index 552f75b68e8..b49348f1256 100644 --- a/src/sound.c +++ b/src/sound.c @@ -86,10 +86,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* BEGIN: Windows Specific Includes */ #include <stdio.h> #include <limits.h> +#include <mbstring.h> #include <windows.h> #include <mmsystem.h> #include "coding.h" +#include "w32common.h" #include "w32.h" /* END: Windows Specific Includes */ @@ -567,12 +569,11 @@ wav_play (struct sound *s, struct sound_device *sd) SBYTES (s->data) - sizeof *header); else { - char *buffer; ptrdiff_t nbytes = 0; ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048; ptrdiff_t data_left = header->data_length; - - buffer = alloca (blksize); + USE_SAFE_ALLOCA; + char *buffer = SAFE_ALLOCA (blksize); lseek (s->fd, sizeof *header, SEEK_SET); while (data_left > 0 && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0) @@ -585,6 +586,7 @@ wav_play (struct sound *s, struct sound_device *sd) if (nbytes < 0) sound_perror ("Error reading sound file"); + SAFE_FREE (); } } @@ -659,19 +661,20 @@ au_play (struct sound *s, struct sound_device *sd) else { ptrdiff_t blksize = sd->period_size ? sd->period_size (sd) : 2048; - char *buffer; ptrdiff_t nbytes; /* Seek */ lseek (s->fd, header->data_offset, SEEK_SET); /* Copy sound data to the device. */ - buffer = alloca (blksize); + USE_SAFE_ALLOCA; + char *buffer = SAFE_ALLOCA (blksize); while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0) sd->write (sd, buffer, nbytes); if (nbytes < 0) sound_perror ("Error reading sound file"); + SAFE_FREE (); } } @@ -705,7 +708,7 @@ vox_configure (struct sound_device *sd) { int val; #ifdef USABLE_SIGIO - sigset_t blocked; + sigset_t oldset, blocked; #endif eassert (sd->fd >= 0); @@ -717,7 +720,7 @@ vox_configure (struct sound_device *sd) #ifdef USABLE_SIGIO sigemptyset (&blocked); sigaddset (&blocked, SIGIO); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + pthread_sigmask (SIG_BLOCK, &blocked, &oldset); #endif val = sd->format; @@ -751,7 +754,7 @@ vox_configure (struct sound_device *sd) turn_on_atimers (1); #ifdef USABLE_SIGIO - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &oldset, 0); #endif } @@ -767,10 +770,10 @@ vox_close (struct sound_device *sd) be interrupted by a signal. Block the ones we know to cause troubles. */ #ifdef USABLE_SIGIO - sigset_t blocked; + sigset_t blocked, oldset; sigemptyset (&blocked); sigaddset (&blocked, SIGIO); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + pthread_sigmask (SIG_BLOCK, &blocked, &oldset); #endif turn_on_atimers (0); @@ -779,7 +782,7 @@ vox_close (struct sound_device *sd) turn_on_atimers (1); #ifdef USABLE_SIGIO - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &oldset, 0); #endif /* Close the device. */ @@ -1206,38 +1209,83 @@ alsa_init (struct sound_device *sd) /* BEGIN: Windows specific functions */ -#define SOUND_WARNING(fun, error, text) \ - { \ - char buf[1024]; \ - char err_string[MAXERRORLENGTH]; \ - fun (error, err_string, sizeof (err_string)); \ - _snprintf (buf, sizeof (buf), "%s\nError: %s", \ - text, err_string); \ - sound_warning (buf); \ - } +#define SOUND_WARNING(func, error, text) \ + do { \ + char buf[1024]; \ + char err_string[MAXERRORLENGTH]; \ + func (error, err_string, sizeof (err_string)); \ + _snprintf (buf, sizeof (buf), "%s\nMCI Error: %s", \ + text, err_string); \ + message_with_string ("%s", build_string (buf), 1); \ + } while (0) static int do_play_sound (const char *psz_file, unsigned long ui_volume) { int i_result = 0; MCIERROR mci_error = 0; - char sz_cmd_buf[520] = {0}; - char sz_ret_buf[520] = {0}; + char sz_cmd_buf_a[520]; + char sz_ret_buf_a[520]; MMRESULT mm_result = MMSYSERR_NOERROR; unsigned long ui_volume_org = 0; BOOL b_reset_volume = FALSE; + char warn_text[560]; + + /* Since UNICOWS.DLL includes only a stub for mciSendStringW, we + need to encode the file in the ANSI codepage on Windows 9X even + if w32_unicode_filenames is non-zero. */ + if (w32_major_version <= 4 || !w32_unicode_filenames) + { + char fname_a[MAX_PATH], shortname[MAX_PATH], *fname_to_use; + + filename_to_ansi (psz_file, fname_a); + fname_to_use = fname_a; + /* If the file name is not encodable in ANSI, try its short 8+3 + alias. This will only work if w32_unicode_filenames is + non-zero. */ + if (_mbspbrk ((const unsigned char *)fname_a, + (const unsigned char *)"?")) + { + if (w32_get_short_filename (psz_file, shortname, MAX_PATH)) + fname_to_use = shortname; + else + mci_error = MCIERR_FILE_NOT_FOUND; + } - memset (sz_cmd_buf, 0, sizeof (sz_cmd_buf)); - memset (sz_ret_buf, 0, sizeof (sz_ret_buf)); - sprintf (sz_cmd_buf, - "open \"%s\" alias GNUEmacs_PlaySound_Device wait", - psz_file); - mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, sizeof (sz_ret_buf), NULL); + if (!mci_error) + { + memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a)); + memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a)); + sprintf (sz_cmd_buf_a, + "open \"%s\" alias GNUEmacs_PlaySound_Device wait", + fname_to_use); + mci_error = mciSendStringA (sz_cmd_buf_a, + sz_ret_buf_a, sizeof (sz_ret_buf_a), NULL); + } + } + else + { + wchar_t sz_cmd_buf_w[520]; + wchar_t sz_ret_buf_w[520]; + wchar_t fname_w[MAX_PATH]; + + filename_to_utf16 (psz_file, fname_w); + memset (sz_cmd_buf_w, 0, sizeof (sz_cmd_buf_w)); + memset (sz_ret_buf_w, 0, sizeof (sz_ret_buf_w)); + /* _swprintf is not available on Windows 9X, so we construct the + UTF-16 command string by hand. */ + wcscpy (sz_cmd_buf_w, L"open \""); + wcscat (sz_cmd_buf_w, fname_w); + wcscat (sz_cmd_buf_w, L"\" alias GNUEmacs_PlaySound_Device wait"); + mci_error = mciSendStringW (sz_cmd_buf_w, + sz_ret_buf_w, ARRAYELTS (sz_ret_buf_w) , NULL); + } if (mci_error != 0) { - SOUND_WARNING (mciGetErrorString, mci_error, - "The open mciSendString command failed to open " - "the specified sound file."); + strcpy (warn_text, + "mciSendString: 'open' command failed to open sound file "); + strcat (warn_text, psz_file); + SOUND_WARNING (mciGetErrorString, mci_error, warn_text); i_result = (int) mci_error; return i_result; } @@ -1251,44 +1299,47 @@ do_play_sound (const char *psz_file, unsigned long ui_volume) if (mm_result != MMSYSERR_NOERROR) { SOUND_WARNING (waveOutGetErrorText, mm_result, - "waveOutSetVolume failed to set the volume level " - "of the WAVE_MAPPER device.\n" - "As a result, the user selected volume level will " - "not be used."); + "waveOutSetVolume: failed to set the volume level" + " of the WAVE_MAPPER device.\n" + "As a result, the user selected volume level will" + " not be used."); } } else { SOUND_WARNING (waveOutGetErrorText, mm_result, - "waveOutGetVolume failed to obtain the original " - "volume level of the WAVE_MAPPER device.\n" - "As a result, the user selected volume level will " - "not be used."); + "waveOutGetVolume: failed to obtain the original" + " volume level of the WAVE_MAPPER device.\n" + "As a result, the user selected volume level will" + " not be used."); } } - memset (sz_cmd_buf, 0, sizeof (sz_cmd_buf)); - memset (sz_ret_buf, 0, sizeof (sz_ret_buf)); - strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait"); - mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, sizeof (sz_ret_buf), NULL); + memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a)); + memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a)); + strcpy (sz_cmd_buf_a, "play GNUEmacs_PlaySound_Device wait"); + mci_error = mciSendStringA (sz_cmd_buf_a, sz_ret_buf_a, sizeof (sz_ret_buf_a), + NULL); if (mci_error != 0) { - SOUND_WARNING (mciGetErrorString, mci_error, - "The play mciSendString command failed to play the " - "opened sound file."); + strcpy (warn_text, + "mciSendString: 'play' command failed to play sound file "); + strcat (warn_text, psz_file); + SOUND_WARNING (mciGetErrorString, mci_error, warn_text); i_result = (int) mci_error; } - memset (sz_cmd_buf, 0, sizeof (sz_cmd_buf)); - memset (sz_ret_buf, 0, sizeof (sz_ret_buf)); - strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait"); - mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, sizeof (sz_ret_buf), NULL); + memset (sz_cmd_buf_a, 0, sizeof (sz_cmd_buf_a)); + memset (sz_ret_buf_a, 0, sizeof (sz_ret_buf_a)); + strcpy (sz_cmd_buf_a, "close GNUEmacs_PlaySound_Device wait"); + mci_error = mciSendStringA (sz_cmd_buf_a, sz_ret_buf_a, sizeof (sz_ret_buf_a), + NULL); if (b_reset_volume == TRUE) { mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org); if (mm_result != MMSYSERR_NOERROR) { SOUND_WARNING (waveOutGetErrorText, mm_result, - "waveOutSetVolume failed to reset the original volume " - "level of the WAVE_MAPPER device."); + "waveOutSetVolume: failed to reset the original" + " volume level of the WAVE_MAPPER device."); } } return i_result; @@ -1306,13 +1357,11 @@ Internal use only, use `play-sound' instead. */) { Lisp_Object attrs[SOUND_ATTR_SENTINEL]; ptrdiff_t count = SPECPDL_INDEX (); - -#ifndef WINDOWSNT Lisp_Object file; - struct gcpro gcpro1, gcpro2; Lisp_Object args[2]; -#else /* WINDOWSNT */ - Lisp_Object lo_file; + struct gcpro gcpro1, gcpro2; + +#ifdef WINDOWSNT unsigned long ui_volume_tmp = UINT_MAX; unsigned long ui_volume = UINT_MAX; #endif /* WINDOWSNT */ @@ -1327,7 +1376,8 @@ Internal use only, use `play-sound' instead. */) current_sound_device = xzalloc (sizeof *current_sound_device); current_sound = xzalloc (sizeof *current_sound); record_unwind_protect_void (sound_cleanup); - current_sound->header = alloca (MAX_SOUND_HEADER_BYTES); + char headerbuf[MAX_SOUND_HEADER_BYTES]; + current_sound->header = headerbuf; if (STRINGP (attrs[SOUND_FILE])) { @@ -1384,11 +1434,8 @@ Internal use only, use `play-sound' instead. */) #else /* WINDOWSNT */ - lo_file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory); - lo_file = ENCODE_FILE (lo_file); - /* Since UNICOWS.DLL includes only a stub for mciSendStringW, we - need to encode the file in the ANSI codepage. */ - lo_file = ansi_encode_filename (lo_file); + file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory); + file = ENCODE_FILE (file); if (INTEGERP (attrs[SOUND_VOLUME])) { ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]); @@ -1397,6 +1444,13 @@ Internal use only, use `play-sound' instead. */) { ui_volume_tmp = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100; } + + GCPRO2 (sound, file); + + args[0] = Qplay_sound_functions; + args[1] = sound; + Frun_hook_with_args (2, args); + /* Based on some experiments I have conducted, a value of 100 or less for the sound volume is much too low. You cannot even hear it. @@ -1410,7 +1464,9 @@ Internal use only, use `play-sound' instead. */) { ui_volume = ui_volume_tmp * (UINT_MAX / 100); } - do_play_sound (SDATA (lo_file), ui_volume); + (void)do_play_sound (SSDATA (file), ui_volume); + + UNGCPRO; #endif /* WINDOWSNT */ diff --git a/src/syntax.c b/src/syntax.c index 5e697d350ff..9f5ef754e2a 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -835,12 +835,10 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, from_byte = comstart_byte; UPDATE_SYNTAX_TABLE_FORWARD (from - 1); } - else + else lossage: { struct lisp_parse_state state; - bool adjusted; - lossage: - adjusted = true; + bool adjusted = true; /* We had two kinds of string delimiters mixed up together. Decode this going forwards. Scan fwd from a known safe place (beginning-of-defun) @@ -1233,7 +1231,7 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value, syntax_code = XINT (first) & INT_MAX; code = syntax_code & 0377; start1 = SYNTAX_FLAGS_COMSTART_FIRST (syntax_code); - start2 = SYNTAX_FLAGS_COMSTART_SECOND (syntax_code);; + start2 = SYNTAX_FLAGS_COMSTART_SECOND (syntax_code); end1 = SYNTAX_FLAGS_COMEND_FIRST (syntax_code); end2 = SYNTAX_FLAGS_COMEND_SECOND (syntax_code); prefix = SYNTAX_FLAGS_PREFIX (syntax_code); @@ -1569,6 +1567,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim, const unsigned char *str; int len; Lisp_Object iso_classes; + USE_SAFE_ALLOCA; CHECK_STRING (string); iso_classes = Qnil; @@ -1701,7 +1700,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim, memcpy (himap, fastmap + 0200, 0200); himap[0200] = 0; memset (fastmap + 0200, 0, 0200); - char_ranges = alloca (sizeof *char_ranges * 128 * 2); + SAFE_NALLOCA (char_ranges, 2, 128); i = 0; while ((p1 = memchr (himap + i, 1, 0200 - i))) @@ -1725,7 +1724,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim, } else /* STRING is multibyte */ { - char_ranges = alloca (sizeof *char_ranges * SCHARS (string) * 2); + SAFE_NALLOCA (char_ranges, 2, SCHARS (string)); while (i_byte < size_byte) { @@ -2034,6 +2033,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim, SET_PT_BOTH (pos, pos_byte); immediate_quit = 0; + SAFE_FREE (); return make_number (PT - start_point); } } diff --git a/src/sysdep.c b/src/sysdep.c index 3870b8d35ce..24cc5cb0b40 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -19,6 +19,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> +/* If HYBRID_GET_CURRENT_DIR_NAME is defined in conf_post.h, then we + need the following before including unistd.h, in order to pick up + the right prototype for gget_current_dir_name. */ +#ifdef HYBRID_GET_CURRENT_DIR_NAME +#undef get_current_dir_name +#define get_current_dir_name gget_current_dir_name +#endif + #include <execinfo.h> #include "sysstdio.h" #ifdef HAVE_PWD_H @@ -46,7 +54,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ # include <sys/user.h> # undef frame -# include <sys/resource.h> # include <math.h> #endif @@ -72,6 +79,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "msdos.h" #endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif #include <sys/param.h> #include <sys/file.h> #include <fcntl.h> @@ -105,9 +115,6 @@ int _cdecl _getpid (void); #include "syssignal.h" #include "systime.h" -static void emacs_get_tty (int, struct emacs_tty *); -static int emacs_set_tty (int, struct emacs_tty *, bool); - /* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */ #ifndef ULLONG_MAX #define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int) @@ -122,13 +129,12 @@ static const int baud_convert[] = 1800, 2400, 4800, 9600, 19200, 38400 }; - -#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME) - +#if !defined HAVE_GET_CURRENT_DIR_NAME || defined BROKEN_GET_CURRENT_DIR_NAME \ + || (defined HYBRID_GET_CURRENT_DIR_NAME) /* Return the current working directory. Returns NULL on errors. Any other returned value must be freed with free. This is used only when get_current_dir_name is not defined on the system. */ -char* +char * get_current_dir_name (void) { char *buf; @@ -222,7 +228,9 @@ discard_tty_input (void) void stuff_char (char c) { - if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) + if (! (FRAMEP (selected_frame) + && FRAME_LIVE_P (XFRAME (selected_frame)) + && FRAME_TERMCAP_P (XFRAME (selected_frame)))) return; /* Should perhaps error if in batch mode */ @@ -255,7 +263,7 @@ init_baud_rate (int fd) #endif /* not DOS_NT */ } - baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0] + baud_rate = (emacs_ospeed < ARRAYELTS (baud_convert) ? baud_convert[emacs_ospeed] : 9600); if (baud_rate == 0) baud_rate = 1200; @@ -603,6 +611,7 @@ init_sigio (int fd) #endif } +#ifndef DOS_NT static void reset_sigio (int fd) { @@ -610,6 +619,7 @@ reset_sigio (int fd) fcntl (fd, F_SETFL, old_fcntl_flags[fd]); #endif } +#endif void request_sigio (void) @@ -657,7 +667,29 @@ ignore_sigio (void) signal (SIGIO, SIG_IGN); #endif } + +#ifndef MSDOS +/* Block SIGCHLD. */ + +void +block_child_signal (sigset_t *oldset) +{ + sigset_t blocked; + sigemptyset (&blocked); + sigaddset (&blocked, SIGCHLD); + sigaddset (&blocked, SIGINT); + pthread_sigmask (SIG_BLOCK, &blocked, oldset); +} + +/* Unblock SIGCHLD. */ + +void +unblock_child_signal (sigset_t const *oldset) +{ + pthread_sigmask (SIG_SETMASK, oldset, 0); +} +#endif /* !MSDOS */ /* Saving and restoring the process group of Emacs's terminal. */ @@ -692,21 +724,21 @@ init_foreground_group (void) /* Block and unblock SIGTTOU. */ void -block_tty_out_signal (void) +block_tty_out_signal (sigset_t *oldset) { #ifdef SIGTTOU sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGTTOU); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + pthread_sigmask (SIG_BLOCK, &blocked, oldset); #endif } void -unblock_tty_out_signal (void) +unblock_tty_out_signal (sigset_t const *oldset) { #ifdef SIGTTOU - pthread_sigmask (SIG_SETMASK, &empty_mask, 0); + pthread_sigmask (SIG_SETMASK, oldset, 0); #endif } @@ -721,10 +753,11 @@ static void tcsetpgrp_without_stopping (int fd, pid_t pgid) { #ifdef SIGTTOU + sigset_t oldset; block_input (); - block_tty_out_signal (); + block_tty_out_signal (&oldset); tcsetpgrp (fd, pgid); - unblock_tty_out_signal (); + unblock_tty_out_signal (&oldset); unblock_input (); #endif } @@ -751,15 +784,28 @@ widen_foreground_group (int fd) /* Getting and setting emacs_tty structures. */ /* Set *TC to the parameters associated with the terminal FD, - or clear it if the parameters are not available. */ -static void + or clear it if the parameters are not available. + Return 0 on success, -1 on failure. */ +int emacs_get_tty (int fd, struct emacs_tty *settings) { /* Retrieve the primary parameters - baud rate, character size, etcetera. */ -#ifndef DOS_NT - /* We have those nifty POSIX tcmumbleattr functions. */ memset (&settings->main, 0, sizeof (settings->main)); - tcgetattr (fd, &settings->main); +#ifdef DOS_NT +#ifdef WINDOWSNT + HANDLE h = (HANDLE)_get_osfhandle (fd); + DWORD console_mode; + + if (h && h != INVALID_HANDLE_VALUE && GetConsoleMode (h, &console_mode)) + { + settings->main = console_mode; + return 0; + } +#endif /* WINDOWSNT */ + return -1; +#else /* !DOS_NT */ + /* We have those nifty POSIX tcmumbleattr functions. */ + return tcgetattr (fd, &settings->main); #endif } @@ -768,11 +814,26 @@ emacs_get_tty (int fd, struct emacs_tty *settings) *SETTINGS. If FLUSHP, discard input. Return 0 if all went well, and -1 (setting errno) if anything failed. */ -static int +int emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp) { /* Set the primary parameters - baud rate, character size, etcetera. */ -#ifndef DOS_NT +#ifdef DOS_NT +#ifdef WINDOWSNT + HANDLE h = (HANDLE)_get_osfhandle (fd); + + if (h && h != INVALID_HANDLE_VALUE) + { + DWORD new_mode; + + /* Assume the handle is open for input. */ + if (flushp) + FlushConsoleInputBuffer (h); + new_mode = settings->main; + SetConsoleMode (h, new_mode); + } +#endif /* WINDOWSNT */ +#else /* !DOS_NT */ int i; /* We have those nifty POSIX tcmumbleattr functions. William J. Smith <wjs@wiis.wang.com> writes: @@ -1113,6 +1174,24 @@ tabs_safe_p (int fd) return 0; #endif /* DOS_NT */ } + +/* Discard echoing. */ + +void +suppress_echo_on_tty (int fd) +{ + struct emacs_tty etty; + + emacs_get_tty (fd, &etty); +#ifdef DOS_NT + /* Set raw input mode. */ + etty.main = 0; +#else + etty.main.c_lflag &= ~ICANON; /* Disable buffering */ + etty.main.c_lflag &= ~ECHO; /* Disable echoing */ +#endif /* ! WINDOWSNT */ + emacs_set_tty (fd, &etty, 0); +} /* Get terminal size from system. Store number of lines into *HEIGHTP and width into *WIDTHP. @@ -1527,9 +1606,6 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler) #endif } - if (! IEEE_FLOATING_POINT) - sigaddset (&action->sa_mask, SIGFPE); - action->sa_handler = handler; action->sa_flags = emacs_sigaction_flags (); } @@ -1649,6 +1725,83 @@ handle_arith_signal (int sig) xsignal0 (Qarith_error); } +#ifdef HAVE_STACK_OVERFLOW_HANDLING + +/* -1 if stack grows down as expected on most OS/ABI variants, 1 otherwise. */ + +static int stack_direction; + +/* Alternate stack used by SIGSEGV handler below. */ + +static unsigned char sigsegv_stack[SIGSTKSZ]; + +/* Attempt to recover from SIGSEGV caused by C stack overflow. */ + +static void +handle_sigsegv (int sig, siginfo_t *siginfo, void *arg) +{ + /* Hard GC error may lead to stack overflow caused by + too nested calls to mark_object. No way to survive. */ + if (!gc_in_progress) + { + struct rlimit rlim; + + if (!getrlimit (RLIMIT_STACK, &rlim)) + { + enum { STACK_DANGER_ZONE = 16 * 1024 }; + char *beg, *end, *addr; + + beg = stack_bottom; + end = stack_bottom + stack_direction * rlim.rlim_cur; + if (beg > end) + addr = beg, beg = end, end = addr; + addr = (char *) siginfo->si_addr; + /* If we're somewhere on stack and too close to + one of its boundaries, most likely this is it. */ + if (beg < addr && addr < end + && (addr - beg < STACK_DANGER_ZONE + || end - addr < STACK_DANGER_ZONE)) + siglongjmp (return_to_command_loop, 1); + } + } + + /* Otherwise we can't do anything with this. */ + deliver_fatal_thread_signal (sig); +} + +/* Return true if we have successfully set up SIGSEGV handler on alternate + stack. Otherwise we just treat SIGSEGV among the rest of fatal signals. */ + +static bool +init_sigsegv (void) +{ + struct sigaction sa; + stack_t ss; + + stack_direction = ((char *) &ss < stack_bottom) ? -1 : 1; + + ss.ss_sp = sigsegv_stack; + ss.ss_size = sizeof (sigsegv_stack); + ss.ss_flags = 0; + if (sigaltstack (&ss, NULL) < 0) + return 0; + + sigfillset (&sa.sa_mask); + sa.sa_sigaction = handle_sigsegv; + sa.sa_flags = SA_SIGINFO | SA_ONSTACK | emacs_sigaction_flags (); + return sigaction (SIGSEGV, &sa, NULL) < 0 ? 0 : 1; +} + +#else /* not HAVE_STACK_OVERFLOW_HANDLING */ + +static bool +init_sigsegv (void) +{ + return 0; +} + +#endif /* HAVE_STACK_OVERFLOW_HANDLING */ + static void deliver_arith_signal (int sig) { @@ -1915,7 +2068,8 @@ init_signals (bool dumping) #ifdef SIGBUS sigaction (SIGBUS, &thread_fatal_action, 0); #endif - sigaction (SIGSEGV, &thread_fatal_action, 0); + if (!init_sigsegv ()) + sigaction (SIGSEGV, &thread_fatal_action, 0); #ifdef SIGSYS sigaction (SIGSYS, &thread_fatal_action, 0); #endif @@ -2133,6 +2287,7 @@ emacs_abort (void) #endif /* Open FILE for Emacs use, using open flags OFLAG and mode MODE. + Use binary I/O on systems that care about text vs binary I/O. Arrange for subprograms to not inherit the file descriptor. Prefer a method that is multithread-safe, if available. Do not fail merely because the open was interrupted by a signal. @@ -2142,6 +2297,8 @@ int emacs_open (const char *file, int oflags, int mode) { int fd; + if (! (oflags & O_TEXT)) + oflags |= O_BINARY; oflags |= O_CLOEXEC; while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) QUIT; @@ -2189,7 +2346,7 @@ emacs_pipe (int fd[2]) #ifdef MSDOS return pipe (fd); #else /* !MSDOS */ - int result = pipe2 (fd, O_CLOEXEC); + int result = pipe2 (fd, O_BINARY | O_CLOEXEC); if (! O_CLOEXEC && result == 0) { fcntl (fd[0], F_SETFD, FD_CLOEXEC); @@ -3443,3 +3600,208 @@ system_process_attributes (Lisp_Object pid) } #endif /* !defined (WINDOWSNT) */ + +/* Wide character string collation. */ + +#ifdef __STDC_ISO_10646__ +# include <wchar.h> +# include <wctype.h> + +# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE +# include <locale.h> +# endif +# ifndef LC_COLLATE +# define LC_COLLATE 0 +# endif +# ifndef LC_COLLATE_MASK +# define LC_COLLATE_MASK 0 +# endif +# ifndef LC_CTYPE +# define LC_CTYPE 0 +# endif +# ifndef LC_CTYPE_MASK +# define LC_CTYPE_MASK 0 +# endif + +# ifndef HAVE_NEWLOCALE +# undef freelocale +# undef locale_t +# undef newlocale +# undef wcscoll_l +# undef towlower_l +# define freelocale emacs_freelocale +# define locale_t emacs_locale_t +# define newlocale emacs_newlocale +# define wcscoll_l emacs_wcscoll_l +# define towlower_l emacs_towlower_l + +typedef char const *locale_t; + +static locale_t +newlocale (int category_mask, char const *locale, locale_t loc) +{ + return locale; +} + +static void +freelocale (locale_t loc) +{ +} + +static char * +emacs_setlocale (int category, char const *locale) +{ +# ifdef HAVE_SETLOCALE + errno = 0; + char *loc = setlocale (category, locale); + if (loc || errno) + return loc; + errno = EINVAL; +# else + errno = ENOTSUP; +# endif + return 0; +} + +static int +wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc) +{ + int result = 0; + char *oldloc = emacs_setlocale (LC_COLLATE, NULL); + int err; + + if (! oldloc) + err = errno; + else + { + USE_SAFE_ALLOCA; + char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1); + strcpy (oldcopy, oldloc); + if (! emacs_setlocale (LC_COLLATE, loc)) + err = errno; + else + { + errno = 0; + result = wcscoll (a, b); + err = errno; + if (! emacs_setlocale (LC_COLLATE, oldcopy)) + err = errno; + } + SAFE_FREE (); + } + + errno = err; + return result; +} + +static wint_t +towlower_l (wint_t wc, locale_t loc) +{ + wint_t result = wc; + char *oldloc = emacs_setlocale (LC_CTYPE, NULL); + + if (oldloc) + { + USE_SAFE_ALLOCA; + char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1); + strcpy (oldcopy, oldloc); + if (emacs_setlocale (LC_CTYPE, loc)) + { + result = towlower (wc); + emacs_setlocale (LC_COLLATE, oldcopy); + } + SAFE_FREE (); + } + + return result; +} +# endif + +int +str_collate (Lisp_Object s1, Lisp_Object s2, + Lisp_Object locale, Lisp_Object ignore_case) +{ + int res, err; + ptrdiff_t len, i, i_byte; + wchar_t *p1, *p2; + + USE_SAFE_ALLOCA; + + /* Convert byte stream to code points. */ + len = SCHARS (s1); i = i_byte = 0; + SAFE_NALLOCA (p1, 1, len + 1); + while (i < len) + FETCH_STRING_CHAR_ADVANCE (*(p1+i-1), s1, i, i_byte); + *(p1+len) = 0; + + len = SCHARS (s2); i = i_byte = 0; + SAFE_NALLOCA (p2, 1, len + 1); + while (i < len) + FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte); + *(p2+len) = 0; + + if (STRINGP (locale)) + { + locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK, + SSDATA (locale), 0); + if (!loc) + error ("Invalid locale %s: %s", SSDATA (locale), strerror (errno)); + + if (! NILP (ignore_case)) + for (int i = 1; i < 3; i++) + { + wchar_t *p = (i == 1) ? p1 : p2; + for (; *p; p++) + *p = towlower_l (*p, loc); + } + + errno = 0; + res = wcscoll_l (p1, p2, loc); + err = errno; + freelocale (loc); + } + else + { + if (! NILP (ignore_case)) + for (int i = 1; i < 3; i++) + { + wchar_t *p = (i == 1) ? p1 : p2; + for (; *p; p++) + *p = towlower (*p); + } + + errno = 0; + res = wcscoll (p1, p2); + err = errno; + } +# ifndef HAVE_NEWLOCALE + if (err) + error ("Invalid locale or string for collation: %s", strerror (err)); +# else + if (err) + error ("Invalid string for collation: %s", strerror (err)); +# endif + + SAFE_FREE (); + return res; +} +#endif /* __STDC_ISO_10646__ */ + +#ifdef WINDOWSNT +int +str_collate (Lisp_Object s1, Lisp_Object s2, + Lisp_Object locale, Lisp_Object ignore_case) +{ + + char *loc = STRINGP (locale) ? SSDATA (locale) : NULL; + int res, err = errno; + + errno = 0; + res = w32_compare_strings (SDATA (s1), SDATA (s2), loc, !NILP (ignore_case)); + if (errno) + error ("Invalid string for collation: %s", strerror (errno)); + + errno = err; + return res; +} +#endif /* WINDOWSNT */ diff --git a/src/sysselect.h b/src/sysselect.h index b76e71a3a75..db6438ed1f8 100644 --- a/src/sysselect.h +++ b/src/sysselect.h @@ -16,6 +16,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef SYSSELECT_H +#define SYSSELECT_H 1 + #ifndef DOS_NT #include <sys/select.h> #endif @@ -47,3 +50,42 @@ typedef int fd_set; #ifdef MSDOS #define pselect sys_select #endif + +#ifndef WINDOWSNT +INLINE_HEADER_BEGIN + +/* Check for out-of-range errors if ENABLE_CHECKING is defined. */ + +INLINE void +fd_CLR (int fd, fd_set *set) +{ + eassume (0 <= fd && fd < FD_SETSIZE); + FD_CLR (fd, set); +} + +INLINE bool +fd_ISSET (int fd, fd_set *set) +{ + eassume (0 <= fd && fd < FD_SETSIZE); + return FD_ISSET (fd, set) != 0; +} + +INLINE void +fd_SET (int fd, fd_set *set) +{ + eassume (0 <= fd && fd < FD_SETSIZE); + FD_SET (fd, set); +} + +#undef FD_CLR +#undef FD_ISSET +#undef FD_SET +#define FD_CLR(fd, set) fd_CLR (fd, set) +#define FD_ISSET(fd, set) fd_ISSET (fd, set) +#define FD_SET(fd, set) fd_SET (fd, set) + +INLINE_HEADER_END + +#endif /* !WINDOWSNT */ + +#endif diff --git a/src/syssignal.h b/src/syssignal.h index 477ddfc2086..3fd9730e665 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -20,6 +20,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <signal.h> extern void init_signals (bool); +extern void block_child_signal (sigset_t *); +extern void unblock_child_signal (sigset_t const *); +extern void block_tty_out_signal (sigset_t *); +extern void unblock_tty_out_signal (sigset_t const *); #ifdef HAVE_PTHREAD #include <pthread.h> diff --git a/src/systime.h b/src/systime.h index a834bce76dc..8f018044660 100644 --- a/src/systime.h +++ b/src/systime.h @@ -93,6 +93,22 @@ extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, extern struct timespec lisp_time_argument (Lisp_Object); #endif +#ifndef HAVE_TZALLOC +# undef mktime_z +# undef timezone_t +# undef tzalloc +# undef tzfree +# define mktime_z emacs_mktime_z +# define timezone_t emacs_timezone_t +# define tzalloc emacs_tzalloc +# define tzfree emacs_tzfree +typedef char const *timezone_t; +INLINE timezone_t tzalloc (char const *name) { return name; } +INLINE void tzfree (timezone_t tz) { } +/* Defined in editfns.c. */ +extern time_t mktime_z (timezone_t, struct tm *); +#endif + INLINE_HEADER_END #endif /* EMACS_SYSTIME_H */ diff --git a/src/systty.h b/src/systty.h index 6eb0c11ef6e..a29c4933d7b 100644 --- a/src/systty.h +++ b/src/systty.h @@ -23,6 +23,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <fcntl.h> #endif /* not DOS_NT */ +#include <stdbool.h> #include <sys/ioctl.h> #ifdef HPUX @@ -74,10 +75,13 @@ struct emacs_tty { #ifndef DOS_NT struct termios main; #else /* DOS_NT */ - int main; + unsigned main; #endif /* DOS_NT */ }; /* From sysdep.c or w32.c */ +extern int emacs_get_tty (int, struct emacs_tty *) EXTERNALLY_VISIBLE; +extern int emacs_set_tty (int, struct emacs_tty *, bool) EXTERNALLY_VISIBLE; +extern void suppress_echo_on_tty (int); extern int serial_open (Lisp_Object); extern void serial_configure (struct Lisp_Process *, Lisp_Object); diff --git a/src/term.c b/src/term.c index 8661cba1160..04f6e3318a0 100644 --- a/src/term.c +++ b/src/term.c @@ -77,7 +77,6 @@ static void tty_turn_off_highlight (struct tty_display_info *); static void tty_show_cursor (struct tty_display_info *); static void tty_hide_cursor (struct tty_display_info *); static void tty_background_highlight (struct tty_display_info *tty); -static struct terminal *get_tty_terminal (Lisp_Object, bool); static void clear_tty_hooks (struct terminal *terminal); static void set_tty_hooks (struct terminal *terminal); static void dissociate_if_controlling_tty (int fd); @@ -91,7 +90,7 @@ static _Noreturn void vfatal (const char *str, va_list ap) #define OUTPUT(tty, a) \ emacs_tputs ((tty), a, \ - FRAME_LINES (XFRAME (selected_frame)) - curY (tty), \ + FRAME_TOTAL_LINES (XFRAME (selected_frame)) - curY (tty), \ cmputc) #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc) @@ -105,9 +104,9 @@ static _Noreturn void vfatal (const char *str, va_list ap) #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0) -/* Display space properties */ +/* Display space properties. */ -/* Chain of all tty device parameters. */ +/* Chain of all tty device parameters. */ struct tty_display_info *tty_list; /* Meaning of bits in no_color_video. Each bit set means that the @@ -131,6 +130,9 @@ enum no_color_bit static int max_frame_cols; +static Lisp_Object Qtty_mode_set_strings; +static Lisp_Object Qtty_mode_reset_strings; + #ifdef HAVE_GPM @@ -162,6 +164,28 @@ tty_ring_bell (struct frame *f) /* Set up termcap modes for Emacs. */ static void +tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym) +{ + Lisp_Object lisp_terminal; + Lisp_Object extra_codes; + struct tty_display_info *tty = terminal->display_info.tty; + + XSETTERMINAL (lisp_terminal, terminal); + for (extra_codes = Fterminal_parameter (lisp_terminal, sym); + CONSP (extra_codes); + extra_codes = XCDR (extra_codes)) + { + Lisp_Object string = XCAR (extra_codes); + if (STRINGP (string)) + { + fwrite (SDATA (string), 1, SBYTES (string), tty->output); + if (tty->termscript) + fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); + } + } +} + +static void tty_set_terminal_modes (struct terminal *terminal) { struct tty_display_info *tty = terminal->display_info.tty; @@ -176,13 +200,14 @@ tty_set_terminal_modes (struct terminal *terminal) off the screen, so it won't be overwritten and lost. */ int i; current_tty = tty; - for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++) + for (i = 0; i < FRAME_TOTAL_LINES (XFRAME (selected_frame)); i++) cmputc ('\n'); } OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal); OUTPUT_IF (tty, tty->TS_keypad_mode); losecursor (tty); + tty_send_additional_strings (terminal, Qtty_mode_set_strings); fflush (tty->output); } } @@ -196,6 +221,7 @@ tty_reset_terminal_modes (struct terminal *terminal) if (tty->output) { + tty_send_additional_strings (terminal, Qtty_mode_reset_strings); tty_turn_off_highlight (tty); tty_turn_off_insert (tty); OUTPUT_IF (tty, tty->TS_end_keypad_mode); @@ -230,7 +256,7 @@ tty_set_terminal_window (struct frame *f, int size) { struct tty_display_info *tty = FRAME_TTY (f); - tty->specified_window = size ? size : FRAME_LINES (f); + tty->specified_window = size ? size : FRAME_TOTAL_LINES (f); if (FRAME_SCROLL_REGION_OK (f)) tty_set_scroll_region (f, 0, tty->specified_window); } @@ -245,9 +271,9 @@ tty_set_scroll_region (struct frame *f, int start, int stop) buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1, 0, 0); else if (tty->TS_set_scroll_region_1) buf = tparam (tty->TS_set_scroll_region_1, 0, 0, - FRAME_LINES (f), start, - FRAME_LINES (f) - stop, - FRAME_LINES (f)); + FRAME_TOTAL_LINES (f), start, + FRAME_TOTAL_LINES (f) - stop, + FRAME_TOTAL_LINES (f)); else buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f)); @@ -419,7 +445,7 @@ tty_clear_to_end (struct frame *f) } else { - for (i = curY (tty); i < FRAME_LINES (f); i++) + for (i = curY (tty); i < FRAME_TOTAL_LINES (f); i++) { cursor_to (f, i, 0); clear_end_of_line (f, FRAME_COLS (f)); @@ -500,9 +526,6 @@ static ptrdiff_t encode_terminal_dst_size; Set CODING->produced to the byte-length of the resulting byte sequence, and return a pointer to that byte sequence. */ -#ifndef DOS_NT -static -#endif unsigned char * encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding) @@ -724,7 +747,7 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len) since that would scroll the whole frame on some terminals. */ if (AutoWrap (tty) - && curY (tty) + 1 == FRAME_LINES (f) + && curY (tty) + 1 == FRAME_TOTAL_LINES (f) && (curX (tty) + len) == FRAME_COLS (f)) len --; if (len <= 0) @@ -796,7 +819,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str since that would scroll the whole frame on some terminals. */ if (AutoWrap (tty) - && curY (tty) + 1 == FRAME_LINES (f) + && curY (tty) + 1 == FRAME_TOTAL_LINES (f) && (curX (tty) + len) == FRAME_COLS (f)) len --; if (len <= 0) @@ -985,7 +1008,7 @@ tty_ins_del_lines (struct frame *f, int vpos, int n) && vpos + i >= tty->specified_window) return; if (!FRAME_MEMORY_BELOW_FRAME (f) - && vpos + i >= FRAME_LINES (f)) + && vpos + i >= FRAME_TOTAL_LINES (f)) return; if (multi) @@ -1022,7 +1045,7 @@ tty_ins_del_lines (struct frame *f, int vpos, int n) && FRAME_MEMORY_BELOW_FRAME (f) && n < 0) { - cursor_to (f, FRAME_LINES (f) + n, 0); + cursor_to (f, FRAME_TOTAL_LINES (f) + n, 0); clear_to_end (f); } } @@ -1339,7 +1362,7 @@ term_get_fkeys_1 (void) if (!KEYMAPP (KVAR (kboard, Vinput_decode_map))) kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil)); - for (i = 0; i < (sizeof (keys) / sizeof (keys[0])); i++) + for (i = 0; i < ARRAYELTS (keys); i++) { char *sequence = tgetstr (keys[i].cap, address); if (sequence) @@ -1490,8 +1513,7 @@ append_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -1687,8 +1709,7 @@ append_composite_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -1772,8 +1793,7 @@ append_glyphless_glyph (struct it *it, int face_id, const char *str) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -1837,7 +1857,7 @@ produce_glyphless_glyph (struct it *it, Lisp_Object acronym) acronym = XCDR (acronym); buf[0] = '['; str = STRINGP (acronym) ? SSDATA (acronym) : ""; - for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++) + for (len = 0; len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++) buf[1 + len] = str[len]; buf[1 + len] = ']'; len += 2; @@ -2008,11 +2028,9 @@ selected frame's terminal). This function always returns nil if TERMINAL does not refer to a text terminal. */) (Lisp_Object terminal) { - struct terminal *t = get_tty_terminal (terminal, 0); - if (!t) - return Qnil; - else - return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil; + struct terminal *t = decode_tty_terminal (terminal); + + return (t && t->display_info.tty->TN_max_colors > 0) ? Qt : Qnil; } /* Return the number of supported colors. */ @@ -2025,11 +2043,9 @@ selected frame's terminal). This function always returns 0 if TERMINAL does not refer to a text terminal. */) (Lisp_Object terminal) { - struct terminal *t = get_tty_terminal (terminal, 0); - if (!t) - return make_number (0); - else - return make_number (t->display_info.tty->TN_max_colors); + struct terminal *t = decode_tty_terminal (terminal); + + return make_number (t ? t->display_info.tty->TN_max_colors : 0); } #ifndef DOS_NT @@ -2144,52 +2160,6 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f) #endif /* !DOS_NT */ - - -/* Return the tty display object specified by TERMINAL. */ - -static struct terminal * -get_tty_terminal (Lisp_Object terminal, bool throw) -{ - struct terminal *t = get_terminal (terminal, throw); - - if (t && t->type != output_termcap && t->type != output_msdos_raw) - { - if (throw) - error ("Device %d is not a termcap terminal device", t->id); - else - return NULL; - } - - return t; -} - -/* Return an active termcap device that uses the tty device with the - given name. - - This function ignores suspended devices. - - Returns NULL if the named terminal device is not opened. */ - -struct terminal * -get_named_tty (const char *name) -{ - struct terminal *t; - - eassert (name); - - for (t = terminal_list; t; t = t->next_terminal) - { - if ((t->type == output_termcap || t->type == output_msdos_raw) - && !strcmp (t->display_info.tty->name, name) - && TERMINAL_ACTIVE_P (t)) - return t; - } - - return 0; -} - - DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0, doc: /* Return the type of the tty device that TERMINAL uses. Returns nil if TERMINAL is not on a tty device. @@ -2198,15 +2168,10 @@ TERMINAL can be a terminal object, a frame, or nil (meaning the selected frame's terminal). */) (Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); - - if (t->type != output_termcap && t->type != output_msdos_raw) - return Qnil; + struct terminal *t = decode_tty_terminal (terminal); - if (t->display_info.tty->type) - return build_string (t->display_info.tty->type); - else - return Qnil; + return (t && t->display_info.tty->type + ? build_string (t->display_info.tty->type) : Qnil); } DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0, @@ -2217,13 +2182,9 @@ selected frame's terminal). This function always returns nil if TERMINAL is not on a tty device. */) (Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_tty_terminal (terminal); - if ((t->type != output_termcap && t->type != output_msdos_raw) - || strcmp (t->display_info.tty->name, DEV_TTY) != 0) - return Qnil; - else - return Qt; + return (t && !strcmp (t->display_info.tty->name, DEV_TTY) ? Qt : Qnil); } DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0, @@ -2237,7 +2198,7 @@ selected frame's terminal). This function always returns nil if TERMINAL does not refer to a text terminal. */) (Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_live_terminal (terminal); if (t->type == output_termcap) t->display_info.tty->TS_enter_underline_mode = 0; @@ -2252,7 +2213,7 @@ does not refer to a text terminal. Otherwise, it returns the top-most frame on the text terminal. */) (Lisp_Object terminal) { - struct terminal *t = get_terminal (terminal, 1); + struct terminal *t = decode_live_terminal (terminal); if (t->type == output_termcap) return t->display_info.tty->top_frame; @@ -2282,11 +2243,11 @@ suspended. A suspended tty may be resumed by calling `resume-tty' on it. */) (Lisp_Object tty) { - struct terminal *t = get_tty_terminal (tty, 1); + struct terminal *t = decode_tty_terminal (tty); FILE *f; if (!t) - error ("Unknown tty device"); + error ("Attempt to suspend a non-text terminal device"); f = t->display_info.tty->input; @@ -2342,15 +2303,15 @@ TTY may be a terminal object, a frame, or nil (meaning the selected frame's terminal). */) (Lisp_Object tty) { - struct terminal *t = get_tty_terminal (tty, 1); + struct terminal *t = decode_tty_terminal (tty); int fd; if (!t) - error ("Unknown tty device"); + error ("Attempt to resume a non-text terminal device"); if (!t->display_info.tty->input) { - if (get_named_tty (t->display_info.tty->name)) + if (get_named_terminal (t->display_info.tty->name)) error ("Cannot resume display while another display is active on the same device"); #ifdef MSDOS @@ -2381,13 +2342,14 @@ frame's terminal). */) struct frame *f = XFRAME (t->display_info.tty->top_frame); int width, height; int old_height = FRAME_COLS (f); - int old_width = FRAME_LINES (f); + int old_width = FRAME_TOTAL_LINES (f); /* Check if terminal/window size has changed while the frame was suspended. */ get_tty_size (fileno (t->display_info.tty->input), &width, &height); if (width != old_width || height != old_height) - change_frame_size (f, width, height, 0, 0, 0, 0); + change_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), + 0, 0, 0, 0); SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); } @@ -2515,7 +2477,7 @@ term_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, (*fp)->mouse_moved = 0; *bar_window = Qnil; - *part = 0; + *part = scroll_bar_above_handle; XSETINT (*x, last_mouse_x); XSETINT (*y, last_mouse_y); @@ -2870,7 +2832,7 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces, /* Don't try to display more menu items than the console can display using the available screen lines. Exclude the echo area line, as it will be overwritten by the help-echo anyway. */ - int max_items = min (menu->count - first_item, FRAME_LINES (sf) - 1 - y); + int max_items = min (menu->count - first_item, FRAME_TOTAL_LINES (sf) - 1 - y); menu_help_message = NULL; @@ -2918,7 +2880,6 @@ static int tty_menu_add_pane (tty_menu *menu, const char *txt) { int len; - const unsigned char *p; tty_menu_make_room (menu); menu->submenu[menu->count] = tty_menu_create (); @@ -2928,15 +2889,7 @@ tty_menu_add_pane (tty_menu *menu, const char *txt) menu->count++; /* Update the menu width, if necessary. */ - for (len = 0, p = (unsigned char *) txt; *p; ) - { - int ch_len; - int ch = STRING_CHAR_AND_LENGTH (p, ch_len); - - len += CHAR_WIDTH (ch); - p += ch_len; - } - + len = menu_item_width ((const unsigned char *) txt); if (len > menu->width) menu->width = len; @@ -2950,7 +2903,6 @@ tty_menu_add_selection (tty_menu *menu, int pane, char *txt, bool enable, char const *help_text) { int len; - unsigned char *p; if (pane) { @@ -2966,15 +2918,7 @@ tty_menu_add_selection (tty_menu *menu, int pane, menu->count++; /* Update the menu width, if necessary. */ - for (len = 0, p = (unsigned char *) txt; *p; ) - { - int ch_len; - int ch = STRING_CHAR_AND_LENGTH (p, ch_len); - - len += CHAR_WIDTH (ch); - p += ch_len; - } - + len = menu_item_width ((const unsigned char *) txt); if (len > menu->width) menu->width = len; @@ -3184,6 +3128,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, Lisp_Object selectface; int first_item = 0; int col, row; + USE_SAFE_ALLOCA; /* Don't allow non-positive x0 and y0, lest the menu will wrap around the display. */ @@ -3192,7 +3137,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, if (y0 <= 0) y0 = 1; - state = alloca (menu->panecount * sizeof (struct tty_menu_state)); + SAFE_NALLOCA (state, 1, menu->panecount); memset (state, 0, sizeof (*state)); faces[0] = lookup_derived_face (sf, intern ("tty-menu-disabled-face"), @@ -3268,7 +3213,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, { mi_result input_status; int min_y = state[0].y; - int max_y = min (min_y + state[0].menu->count, FRAME_LINES (sf) - 1) - 1; + int max_y = min (min_y + state[0].menu->count, FRAME_TOTAL_LINES (sf) - 1) - 1; input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time); if (input_status) @@ -3414,6 +3359,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, discard_mouse_events (); if (!kbd_buffer_events_waiting ()) clear_input_pending (); + SAFE_FREE (); return result; } @@ -3555,9 +3501,10 @@ tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y) } } +/* WINDOWSNT uses this as menu_show_hook, see w32console.c. */ Lisp_Object -tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, - Lisp_Object title, bool kbd_navigation, const char **error_name) +tty_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) { tty_menu *menu; int pane, selidx, lpane, status; @@ -3584,21 +3531,21 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* Make the menu on that window. */ menu = tty_menu_create (); - if (menu == NULL) - { - *error_name = "Can't create menu"; - return Qnil; - } /* Don't GC while we prepare and show the menu, because we give the menu functions pointers to the contents of strings. */ specpdl_count = inhibit_garbage_collection (); + /* Avoid crashes if, e.g., another client will connect while we + are in a menu. */ + temporarily_switch_to_single_kboard (f); + /* Adjust coordinates to be root-window-relative. */ item_x = x += f->left_pos; item_y = y += f->top_pos; /* Create all the necessary panes and their items. */ + USE_SAFE_ALLOCA; maxwidth = maxlines = lines = i = 0; lpane = TTYM_FAILURE; while (i < menu_items_used) @@ -3615,7 +3562,7 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) pane_string++; lpane = tty_menu_add_pane (menu, pane_string); @@ -3667,9 +3614,7 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (!NILP (descrip)) { - /* If alloca is fast, use that to make the space, - to reduce gc needs. */ - item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1); + item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1); memcpy (item_data, SSDATA (item_name), SBYTES (item_name)); for (j = SCHARS (item_name); j < maxwidth; j++) item_data[j] = ' '; @@ -3755,7 +3700,8 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, specbind (Qoverriding_terminal_local_map, Fsymbol_value (Qtty_menu_navigation_map)); status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap, - tty_menu_help_callback, kbd_navigation); + tty_menu_help_callback, + menuflags & MENU_KBD_NAVIGATION); entry = pane_prefix = Qnil; switch (status) @@ -3781,7 +3727,7 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, { entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); - if (keymaps != 0) + if (menuflags & MENU_KEYMAPS) { entry = Fcons (entry, Qnil); if (!NILP (pane_prefix)) @@ -3814,13 +3760,14 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, Ftop_level (); /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means the menu was invoked with a mouse event as POSITION). */ - if (! for_click) + if (!(menuflags & MENU_FOR_CLICK)) Fsignal (Qquit, Qnil); break; } tty_menu_end: + SAFE_FREE (); unbind_to (specpdl_count, Qnil); return entry; } @@ -3895,7 +3842,9 @@ clear_tty_hooks (struct terminal *terminal) terminal->frame_rehighlight_hook = 0; terminal->frame_raise_lower_hook = 0; terminal->fullscreen_hook = 0; + terminal->menu_show_hook = 0; terminal->set_vertical_scroll_bar_hook = 0; + terminal->set_horizontal_scroll_bar_hook = 0; terminal->condemn_scroll_bars_hook = 0; terminal->redeem_scroll_bar_hook = 0; terminal->judge_scroll_bars_hook = 0; @@ -3913,43 +3862,29 @@ clear_tty_hooks (struct terminal *terminal) static void set_tty_hooks (struct terminal *terminal) { - terminal->rif = 0; /* ttys don't support window-based redisplay. */ - terminal->cursor_to_hook = &tty_cursor_to; terminal->raw_cursor_to_hook = &tty_raw_cursor_to; - terminal->clear_to_end_hook = &tty_clear_to_end; terminal->clear_frame_hook = &tty_clear_frame; terminal->clear_end_of_line_hook = &tty_clear_end_of_line; - terminal->ins_del_lines_hook = &tty_ins_del_lines; - terminal->insert_glyphs_hook = &tty_insert_glyphs; terminal->write_glyphs_hook = &tty_write_glyphs; terminal->delete_glyphs_hook = &tty_delete_glyphs; - terminal->ring_bell_hook = &tty_ring_bell; - terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes; terminal->set_terminal_modes_hook = &tty_set_terminal_modes; - terminal->update_begin_hook = 0; /* Not needed. */ terminal->update_end_hook = &tty_update_end; +#ifdef MSDOS + terminal->menu_show_hook = &x_menu_show; +#else + terminal->menu_show_hook = &tty_menu_show; +#endif terminal->set_terminal_window_hook = &tty_set_terminal_window; - - terminal->mouse_position_hook = 0; /* Not needed. */ - terminal->frame_rehighlight_hook = 0; /* Not needed. */ - terminal->frame_raise_lower_hook = 0; /* Not needed. */ - - terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */ - terminal->condemn_scroll_bars_hook = 0; /* Not needed. */ - terminal->redeem_scroll_bar_hook = 0; /* Not needed. */ - terminal->judge_scroll_bars_hook = 0; /* Not needed. */ - terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ - terminal->frame_up_to_date_hook = 0; /* Not needed. */ - terminal->delete_frame_hook = &tty_free_frame_resources; terminal->delete_terminal_hook = &delete_tty; + /* Other hooks are NULL by default. */ } /* If FD is the controlling terminal, drop it. */ @@ -3964,9 +3899,10 @@ dissociate_if_controlling_tty (int fd) /* setsid failed, presumably because Emacs is already a process group leader. Fall back on the obsolescent way to dissociate a controlling tty. */ - block_tty_out_signal (); + sigset_t oldset; + block_tty_out_signal (&oldset); ioctl (fd, TIOCNOTTY, 0); - unblock_tty_out_signal (); + unblock_tty_out_signal (&oldset); #endif } } @@ -3990,6 +3926,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) int status; struct tty_display_info *tty = NULL; struct terminal *terminal = NULL; + sigset_t oldset; bool ctty = false; /* True if asked to open controlling tty. */ if (!terminal_type) @@ -4007,11 +3944,11 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) /* XXX Perhaps this should be made explicit by having init_tty always create a new terminal and separating terminal and frame creation on Lisp level. */ - terminal = get_named_tty (name); + terminal = get_named_terminal (name); if (terminal) return terminal; - terminal = create_terminal (); + terminal = create_terminal (output_termcap, NULL); #ifdef MSDOS if (been_here > 0) maybe_fatal (0, 0, "Attempt to create another terminal %s", "", @@ -4025,7 +3962,6 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) tty->next = tty_list; tty_list = tty; - terminal->type = output_termcap; terminal->display_info.tty = tty; tty->terminal = terminal; @@ -4051,12 +3987,15 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) open a frame on the same terminal. */ int flags = O_RDWR | O_NOCTTY | (ctty ? 0 : O_IGNORE_CTTY); int fd = emacs_open (name, flags, 0); - tty->input = tty->output = fd < 0 || ! isatty (fd) ? 0 : fdopen (fd, "w+"); + tty->input = tty->output + = ((fd < 0 || ! isatty (fd)) + ? NULL + : fdopen (fd, "w+")); if (! tty->input) { char const *diagnostic - = tty->input ? "Not a tty device: %s" : "Could not open file: %s"; + = (fd < 0) ? "Could not open file: %s" : "Not a tty device: %s"; emacs_close (fd); maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name); } @@ -4076,11 +4015,11 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) /* On some systems, tgetent tries to access the controlling terminal. */ - block_tty_out_signal (); + block_tty_out_signal (&oldset); status = tgetent (tty->termcap_term_buffer, terminal_type); if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1]) emacs_abort (); - unblock_tty_out_signal (); + unblock_tty_out_signal (&oldset); if (status < 0) { @@ -4231,6 +4170,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ tty->specified_window = height; FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; + FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = 0; tty->char_ins_del_ok = 1; baud_rate = 19200; } @@ -4466,7 +4406,7 @@ fatal (const char *str, ...) -/* Delete the given tty terminal, closing all frames on it. */ +/* Delete the given tty terminal, closing all frames on it. */ static void delete_tty (struct terminal *terminal) @@ -4491,7 +4431,7 @@ delete_tty (struct terminal *terminal) ; if (! p) - /* This should not happen. */ + /* This should not happen. */ emacs_abort (); p->next = tty->next; @@ -4499,7 +4439,7 @@ delete_tty (struct terminal *terminal) } /* reset_sys_modes needs a valid device, so this call needs to be - before delete_terminal. */ + before delete_terminal. */ reset_sys_modes (tty); delete_terminal (terminal); @@ -4577,6 +4517,9 @@ bigger, or it may make it blink, or it may do nothing at all. */); encode_terminal_src = NULL; encode_terminal_dst = NULL; + DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings"); + DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings"); + #ifndef MSDOS DEFSYM (Qtty_menu_next_item, "tty-menu-next-item"); DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item"); diff --git a/src/termcap.c b/src/termcap.c index 8c766bd1994..26c6de06f88 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -520,7 +520,7 @@ scan_file (char *str, int fd, struct termcap_buffer *bufp) bufp->ateof = 0; *bufp->ptr = '\0'; - lseek (fd, 0L, 0); + lseek (fd, 0, 0); while (!bufp->ateof) { diff --git a/src/termhooks.h b/src/termhooks.h index 708351da83d..9cab853ed3d 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -28,7 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ INLINE_HEADER_BEGIN enum scroll_bar_part { - scroll_bar_nowhere = -1, + scroll_bar_nowhere, scroll_bar_above_handle, scroll_bar_handle, scroll_bar_below_handle, @@ -37,7 +37,14 @@ enum scroll_bar_part { scroll_bar_to_top, scroll_bar_to_bottom, scroll_bar_end_scroll, - scroll_bar_move_ratio + scroll_bar_move_ratio, + scroll_bar_before_handle, + scroll_bar_horizontal_handle, + scroll_bar_after_handle, + scroll_bar_left_arrow, + scroll_bar_right_arrow, + scroll_bar_to_leftmost, + scroll_bar_to_rightmost }; /* Output method of a terminal (and frames on this terminal, respectively). */ @@ -130,6 +137,19 @@ enum event_kind whose scroll bar was clicked in. .timestamp gives a timestamp (in milliseconds) for the click. */ + HORIZONTAL_SCROLL_BAR_CLICK_EVENT, /* .code gives the number of the mouse button + that was clicked. + .modifiers holds the state of the modifier + keys. + .part is a lisp symbol indicating which + part of the scroll bar got clicked. + .x gives the distance from the start of the + scroll bar of the click; .y gives the total + length of the scroll bar. + .frame_or_window gives the window + whose scroll bar was clicked in. + .timestamp gives a timestamp (in + milliseconds) for the click. */ SELECTION_REQUEST_EVENT, /* Another X client wants a selection from us. See `struct selection_input_event'. */ SELECTION_CLEAR_EVENT, /* Another X client cleared our selection. */ @@ -235,28 +255,36 @@ enum event_kind struct input_event { /* What kind of event was this? */ - enum event_kind kind; + ENUM_BF (event_kind) kind : 16; + + /* Used in scroll back click events. */ + ENUM_BF (scroll_bar_part) part : 16; /* For an ASCII_KEYSTROKE_EVENT and MULTIBYTE_CHAR_KEYSTROKE_EVENT, this is the character. For a NON_ASCII_KEYSTROKE_EVENT, this is the keysym code. - For a mouse event, this is the button number. - For a HELP_EVENT, this is the position within the object - (stored in ARG below) where the help was found. */ - ptrdiff_t code; - enum scroll_bar_part part; + For a mouse event, this is the button number. */ + unsigned code; - int modifiers; /* See enum below for interpretation. */ + /* See enum below for interpretation. */ + unsigned modifiers; + /* One would prefer C integers, but HELP_EVENT uses these to + record frame or window object and a help form, respectively. */ Lisp_Object x, y; + + /* Usually a time as reported by window system-specific event loop. + For a HELP_EVENT, this is the position within the object (stored + in ARG below) where the help was found. */ Time timestamp; /* This field is copied into a vector while the event is in the queue, so that garbage collections won't kill it. */ Lisp_Object frame_or_window; - /* Additional event argument. This is used for TOOL_BAR_EVENTs and - HELP_EVENTs and avoids calling Fcons during signal handling. */ + /* This additional argument is used in attempt to avoid extra consing + when building events. Unfortunately some events have to pass much + more data than it's reasonable to pack directly into this structure. */ Lisp_Object arg; }; @@ -478,7 +506,14 @@ struct terminal may do something OS dependent, like extended window manager hints on X11. */ void (*fullscreen_hook) (struct frame *f); - + /* This hook is called to display menus. */ + Lisp_Object (*menu_show_hook) (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name); + + /* This hook is called to display popup dialog. */ + Lisp_Object (*popup_dialog_hook) (struct frame *f, Lisp_Object header, + Lisp_Object contents); + /* Scroll bar hooks. */ /* The representation of scroll bars is determined by the code which @@ -511,6 +546,16 @@ struct terminal int position); + /* Set the horizontal scroll bar for WINDOW to have its upper left + corner at (TOP, LEFT), and be LENGTH rows high. Set its handle to + indicate that we are displaying PORTION characters out of a total + of WHOLE characters, starting at POSITION. If WINDOW doesn't yet + have a scroll bar, create one for it. */ + void (*set_horizontal_scroll_bar_hook) (struct window *window, + int portion, int whole, + int position); + + /* The following three hooks are used when we're doing a thorough redisplay of the frame. We don't explicitly know which scroll bars are going to be deleted, because keeping track of when windows go @@ -636,17 +681,18 @@ extern struct terminal *terminal_list; (t->type == output_ns ? t->display_info.ns->name_list_element : Qnil) #endif -extern struct terminal *get_terminal (Lisp_Object terminal, bool); -extern struct terminal *create_terminal (void); +extern struct terminal *decode_live_terminal (Lisp_Object); +extern struct terminal *decode_tty_terminal (Lisp_Object); +extern struct terminal *get_named_terminal (const char *); +extern struct terminal *create_terminal (enum output_method, + struct redisplay_interface *); extern void delete_terminal (struct terminal *); /* The initial terminal device, created by initial_term_init. */ extern struct terminal *initial_terminal; -#ifdef DOS_NT extern unsigned char *encode_terminal_code (struct glyph *, int, struct coding_system *); -#endif #ifdef HAVE_GPM extern void close_gpm (int gpm_fd); diff --git a/src/terminal.c b/src/terminal.c index d0a38b97bb4..0cd6a0bf602 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -28,16 +28,18 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "coding.h" #include "keyboard.h" -/* Chain of all terminals currently in use. */ +/* Chain of all terminals currently in use. */ struct terminal *terminal_list; -/* The first unallocated terminal id. */ +/* The first unallocated terminal id. */ static int next_terminal_id; -/* The initial terminal device, created by initial_term_init. */ +/* The initial terminal device, created by initial_term_init. */ struct terminal *initial_terminal; +Lisp_Object Qrun_hook_with_args; static Lisp_Object Qterminal_live_p; +static Lisp_Object Qdelete_terminal_functions; static void delete_initial_terminal (struct terminal *); @@ -121,9 +123,9 @@ raw_cursor_to (struct frame *f, int row, int col) (*FRAME_TERMINAL (f)->raw_cursor_to_hook) (f, row, col); } -/* Erase operations */ +/* Erase operations. */ -/* Clear from cursor to end of frame. */ +/* Clear from cursor to end of frame. */ void clear_to_end (struct frame *f) { @@ -131,7 +133,7 @@ clear_to_end (struct frame *f) (*FRAME_TERMINAL (f)->clear_to_end_hook) (f); } -/* Clear entire frame */ +/* Clear entire frame. */ void clear_frame (struct frame *f) @@ -194,49 +196,81 @@ ins_del_lines (struct frame *f, int vpos, int n) (*FRAME_TERMINAL (f)->ins_del_lines_hook) (f, vpos, n); } +/* Return the terminal object specified by TERMINAL. TERMINAL may + be a terminal object, a frame, or nil for the terminal device of + the current frame. If TERMINAL is neither from the above or the + resulting terminal object is deleted, return NULL. */ - - -/* Return the terminal object specified by TERMINAL. TERMINAL may be - a terminal object, a frame, or nil for the terminal device of the - current frame. If THROW is false, return NULL for failure, - otherwise throw an error. */ - -struct terminal * -get_terminal (Lisp_Object terminal, bool throw) +static struct terminal * +decode_terminal (Lisp_Object terminal) { - struct terminal *result = NULL; + struct terminal *t; if (NILP (terminal)) terminal = selected_frame; + t = (TERMINALP (terminal) + ? XTERMINAL (terminal) + : FRAMEP (terminal) ? FRAME_TERMINAL (XFRAME (terminal)) : NULL); + return t && t->name ? t : NULL; +} - if (TERMINALP (terminal)) - result = XTERMINAL (terminal); - else if (FRAMEP (terminal)) - result = FRAME_TERMINAL (XFRAME (terminal)); +/* Like above, but throw an error if TERMINAL is not valid or deleted. */ - if (result && !result->name) - result = NULL; +struct terminal * +decode_live_terminal (Lisp_Object terminal) +{ + struct terminal *t = decode_terminal (terminal); - if (result == NULL && throw) + if (!t) wrong_type_argument (Qterminal_live_p, terminal); + return t; +} + +/* Like decode_terminal, but ensure that the resulting terminal object refers + to a text-based terminal device. */ + +struct terminal * +decode_tty_terminal (Lisp_Object terminal) +{ + struct terminal *t = decode_live_terminal (terminal); - return result; + return (t->type == output_termcap || t->type == output_msdos_raw) ? t : NULL; } - +/* Return an active (not suspended) text-based terminal device that uses + the tty device with the given NAME, or NULL if the named terminal device + is not opened. */ + +struct terminal * +get_named_terminal (const char *name) +{ + struct terminal *t; + + eassert (name); + + for (t = terminal_list; t; t = t->next_terminal) + { + if ((t->type == output_termcap || t->type == output_msdos_raw) + && !strcmp (t->display_info.tty->name, name) + && TERMINAL_ACTIVE_P (t)) + return t; + } + return NULL; +} -/* Create a new terminal object and add it to the terminal list. */ +/* Create a new terminal object of TYPE and add it to the terminal list. RIF + may be NULL if this terminal type doesn't support window-based redisplay. */ struct terminal * -create_terminal (void) +create_terminal (enum output_method type, struct redisplay_interface *rif) { struct terminal *terminal = allocate_terminal (); Lisp_Object terminal_coding, keyboard_coding; terminal->next_terminal = terminal_list; terminal_list = terminal; - + terminal->type = type; + terminal->rif = rif; terminal->id = next_terminal_id++; terminal->keyboard_coding = xmalloc (sizeof (struct coding_system)); @@ -308,8 +342,6 @@ delete_terminal (struct terminal *terminal) } } -Lisp_Object Qrun_hook_with_args; -static Lisp_Object Qdelete_terminal_functions; DEFUN ("delete-terminal", Fdelete_terminal, Sdelete_terminal, 0, 2, 0, doc: /* Delete TERMINAL by deleting all frames on it and closing the terminal. TERMINAL may be a terminal object, a frame, or nil (meaning the @@ -319,7 +351,7 @@ Normally, you may not delete a display if all other displays are suspended, but if the second argument FORCE is non-nil, you may do so. */) (Lisp_Object terminal, Lisp_Object force) { - struct terminal *t = get_terminal (terminal, 0); + struct terminal *t = decode_terminal (terminal); if (!t) return Qnil; @@ -380,9 +412,7 @@ sort of output terminal it uses. See the documentation of `framep' for possible return values. */) (Lisp_Object object) { - struct terminal *t; - - t = get_terminal (object, 0); + struct terminal *t = decode_terminal (object); if (!t) return Qnil; @@ -429,8 +459,7 @@ TERMINAL may be a terminal object, a frame, or nil (meaning the selected frame's terminal). */) (Lisp_Object terminal) { - struct terminal *t - = TERMINALP (terminal) ? XTERMINAL (terminal) : get_terminal (terminal, 1); + struct terminal *t = decode_live_terminal (terminal); return t->name ? build_string (t->name) : Qnil; } @@ -467,9 +496,7 @@ TERMINAL can be a terminal object, a frame, or nil (meaning the selected frame's terminal). */) (Lisp_Object terminal) { - struct terminal *t - = TERMINALP (terminal) ? XTERMINAL (terminal) : get_terminal (terminal, 1); - return Fcopy_alist (t->param_alist); + return Fcopy_alist (decode_live_terminal (terminal)->param_alist); } DEFUN ("terminal-parameter", Fterminal_parameter, Sterminal_parameter, 2, 2, 0, @@ -478,12 +505,8 @@ TERMINAL can be a terminal object, a frame, or nil (meaning the selected frame's terminal). */) (Lisp_Object terminal, Lisp_Object parameter) { - Lisp_Object value; - struct terminal *t - = TERMINALP (terminal) ? XTERMINAL (terminal) : get_terminal (terminal, 1); CHECK_SYMBOL (parameter); - value = Fcdr (Fassq (parameter, t->param_alist)); - return value; + return Fcdr (Fassq (parameter, decode_live_terminal (terminal)->param_alist)); } DEFUN ("set-terminal-parameter", Fset_terminal_parameter, @@ -495,9 +518,7 @@ TERMINAL can be a terminal object, a frame or nil (meaning the selected frame's terminal). */) (Lisp_Object terminal, Lisp_Object parameter, Lisp_Object value) { - struct terminal *t - = TERMINALP (terminal) ? XTERMINAL (terminal) : get_terminal (terminal, 1); - return store_terminal_param (t, parameter, value); + return store_terminal_param (decode_live_terminal (terminal), parameter, value); } /* Initial frame has no device-dependent output data, but has @@ -519,13 +540,12 @@ init_initial_terminal (void) if (initialized || terminal_list || tty_list) emacs_abort (); - initial_terminal = create_terminal (); - initial_terminal->type = output_initial; + initial_terminal = create_terminal (output_initial, NULL); initial_terminal->name = xstrdup ("initial_terminal"); initial_terminal->kboard = initial_kboard; initial_terminal->delete_terminal_hook = &delete_initial_terminal; initial_terminal->delete_frame_hook = &initial_free_frame_resources; - /* All other hooks are NULL. */ + /* Other hooks are NULL by default. */ return initial_terminal; } diff --git a/src/textprop.c b/src/textprop.c index bd09304ba3b..91ade8ae298 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -660,6 +660,7 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop, set_buffer_temp (XBUFFER (object)); + USE_SAFE_ALLOCA; GET_OVERLAYS_AT (XINT (position), overlay_vec, noverlays, NULL, 0); noverlays = sort_overlays (overlay_vec, noverlays, w); @@ -674,9 +675,11 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop, if (overlay) /* Return the overlay we got the property from. */ *overlay = overlay_vec[noverlays]; + SAFE_FREE (); return tem; } } + SAFE_FREE (); } if (overlay) @@ -1314,9 +1317,11 @@ specify the property to add. If the optional fifth argument OBJECT is a buffer (or nil, which means the current buffer), START and END are buffer positions (integers or markers). If OBJECT is a string, START and END are 0-based indices into it. */) - (Lisp_Object start, Lisp_Object end, Lisp_Object property, Lisp_Object value, Lisp_Object object) + (Lisp_Object start, Lisp_Object end, Lisp_Object property, + Lisp_Object value, Lisp_Object object) { - Fadd_text_properties (start, end, list2 (property, value), object); + AUTO_LIST2 (properties, property, value); + Fadd_text_properties (start, end, properties, object); return Qnil; } @@ -1357,7 +1362,8 @@ into it. */) (Lisp_Object start, Lisp_Object end, Lisp_Object face, Lisp_Object append, Lisp_Object object) { - add_text_properties_1 (start, end, list2 (Qface, face), object, + AUTO_LIST2 (properties, Qface, face); + add_text_properties_1 (start, end, properties, object, (NILP (append) ? TEXT_PROPERTY_PREPEND : TEXT_PROPERTY_APPEND)); @@ -1906,7 +1912,8 @@ text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer) /* Note this can GC when DEST is a buffer. */ Lisp_Object -copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_Object pos, Lisp_Object dest, Lisp_Object prop) +copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, + Lisp_Object pos, Lisp_Object dest, Lisp_Object prop) { INTERVAL i; Lisp_Object res; @@ -1959,12 +1966,10 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_ plist = Fcdr (Fcdr (plist)); } if (! NILP (plist)) - { - /* Must defer modifications to the interval tree in case src - and dest refer to the same string or buffer. */ - stuff = Fcons (list3 (make_number (p), make_number (p + len), plist), - stuff); - } + /* Must defer modifications to the interval tree in case + src and dest refer to the same string or buffer. */ + stuff = Fcons (list3 (make_number (p), make_number (p + len), plist), + stuff); i = next_interval (i); if (!i) diff --git a/src/unexcoff.c b/src/unexcoff.c index 043f3348d16..0e47bdd8656 100644 --- a/src/unexcoff.c +++ b/src/unexcoff.c @@ -122,7 +122,7 @@ static int pagemask; into an int which is the number of a byte. This is a no-op on ordinary machines, but not on all. */ -#define ADDR_CORRECT(x) ((char *)(x) - (char*)0) +#define ADDR_CORRECT(x) ((char *) (x) - (char *) 0) #include "lisp.h" diff --git a/src/unexcw.c b/src/unexcw.c index fcca5e5cbf2..cdeb899fd30 100644 --- a/src/unexcw.c +++ b/src/unexcw.c @@ -34,12 +34,6 @@ extern void report_sheap_usage (int); extern int bss_sbrk_did_unexec; -extern int __malloc_initialized; - -/* emacs symbols that indicate where bss and data end for emacs internals */ -extern char my_endbss[]; -extern char my_edata[]; - /* ** header for Windows executable files */ @@ -81,8 +75,7 @@ read_exe_header (int fd, exe_header_t * exe_header_buffer) #endif assert (exe_header_buffer->file_header.f_nscns > 0); assert (exe_header_buffer->file_header.f_nscns <= - sizeof (exe_header_buffer->section_header) / - sizeof (exe_header_buffer->section_header[0])); + ARRAYELTS (exe_header_buffer->section_header)); assert (exe_header_buffer->file_header.f_opthdr > 0); ret = @@ -234,12 +227,9 @@ fixup_executable (int fd) lseek (fd, (long) (exe_header->section_header[i].s_scnptr), SEEK_SET); assert (ret != -1); - /* force the dumped emacs to reinitialize malloc */ - __malloc_initialized = 0; ret = write (fd, (char *) start_address, my_endbss - (char *) start_address); - __malloc_initialized = 1; assert (ret == (my_endbss - (char *) start_address)); if (debug_unexcw) printf (" .bss, mem start %#lx mem length %d\n", @@ -286,13 +276,6 @@ unexec (const char *outfile, const char *infile) int ret; int ret2; - if (bss_sbrk_did_unexec) - { - /* can only dump once */ - printf ("You can only dump Emacs once on this platform.\n"); - return; - } - report_sheap_usage (1); infile = add_exe_suffix_if_necessary (infile, infile_buffer); diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c index 55db8071b76..cbf1835b9ee 100644 --- a/src/unexhp9k800.c +++ b/src/unexhp9k800.c @@ -72,7 +72,6 @@ run_time_remap (char *ignored) #undef roundup #define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1)) /* n is power of 2 */ -#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Report a fatal error and exit. */ static _Noreturn void diff --git a/src/unexmacosx.c b/src/unexmacosx.c index 7d4762fdab2..2e1ac880d2a 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c @@ -107,9 +107,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <mach/mach.h> #include <mach-o/loader.h> #include <mach-o/reloc.h> -#if defined (__ppc__) -#include <mach-o/ppc/reloc.h> -#endif #ifdef HAVE_MALLOC_MALLOC_H #include <malloc/malloc.h> #else @@ -826,7 +823,6 @@ copy_data_segment (struct load_command *lc) file. */ if (strncmp (sectp->sectname, SECT_DATA, 16) == 0) { - extern char my_edata[]; unsigned long my_size; /* The __data section is basically dumped from memory. But @@ -857,7 +853,6 @@ copy_data_segment (struct load_command *lc) } else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0) { - extern char *my_endbss_static; unsigned long my_size; sectp->flags = S_REGULAR; @@ -881,6 +876,27 @@ copy_data_segment (struct load_command *lc) if (!unexec_write (header_offset, sectp, sizeof (struct section))) unexec_error ("cannot write section %.16s's header", sectp->sectname); } + else if (strncmp (sectp->sectname, "__bss", 5) == 0 + || strncmp (sectp->sectname, "__pu_bss", 8) == 0) + { + sectp->flags = S_REGULAR; + + /* These sections are produced by GCC 4.6+. + + FIXME: We possibly ought to clear uninitialized local + variables in statically linked libraries like for + SECT_BSS (__bss) above, but setting up the markers we + need in lastfile.c would be rather messy. See + darwin_output_aligned_bss () in gcc/config/darwin.c for + the root of the problem, keeping in mind that the + sections are numbered by their alignment in GCC 4.6, but + by log2(alignment) in GCC 4.7. */ + + if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) + unexec_error ("cannot copy section %.16s", sectp->sectname); + if (!unexec_write (header_offset, sectp, sizeof (struct section))) + unexec_error ("cannot write section %.16s's header", sectp->sectname); + } else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0 || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0 || strncmp (sectp->sectname, "__got", 16) == 0 @@ -892,6 +908,7 @@ copy_data_segment (struct load_command *lc) || strncmp (sectp->sectname, "__program_vars", 16) == 0 || strncmp (sectp->sectname, "__mod_init_func", 16) == 0 || strncmp (sectp->sectname, "__mod_term_func", 16) == 0 + || strncmp (sectp->sectname, "__static_data", 16) == 0 || strncmp (sectp->sectname, "__objc_", 7) == 0) { if (!unexec_copy (sectp->offset, old_file_offset, sectp->size)) @@ -1013,17 +1030,8 @@ unrelocate (const char *name, off_t reloff, int nrel, vm_address_t base) name, i, reloc_info.r_type); } else - switch (sc_reloc_info->r_type) - { -#if defined (__ppc__) - case PPC_RELOC_PB_LA_PTR: - /* nothing to do for prebound lazy pointer */ - break; -#endif - default: - unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d", - name, i, sc_reloc_info->r_type); - } + unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d", + name, i, sc_reloc_info->r_type); } if (nrel > 0) @@ -1031,35 +1039,6 @@ unrelocate (const char *name, off_t reloff, int nrel, vm_address_t base) unreloc_count, nrel, name); } -#if __ppc64__ -/* Rebase r_address in the relocation table. */ -static void -rebase_reloc_address (off_t reloff, int nrel, long linkedit_delta, long diff) -{ - int i; - struct relocation_info reloc_info; - struct scattered_relocation_info *sc_reloc_info - = (struct scattered_relocation_info *) &reloc_info; - - for (i = 0; i < nrel; i++, reloff += sizeof (reloc_info)) - { - if (lseek (infd, reloff - linkedit_delta, L_SET) - != reloff - linkedit_delta) - unexec_error ("rebase_reloc_table: cannot seek to reloc_info"); - if (!unexec_read (&reloc_info, sizeof (reloc_info))) - unexec_error ("rebase_reloc_table: cannot read reloc_info"); - - if (sc_reloc_info->r_scattered == 0 - && reloc_info.r_type == GENERIC_RELOC_VANILLA) - { - reloc_info.r_address -= diff; - if (!unexec_write (reloff, &reloc_info, sizeof (reloc_info))) - unexec_error ("rebase_reloc_table: cannot write reloc_info"); - } - } -} -#endif - /* Copy a LC_DYSYMTAB load command from the input file to the output file, adjusting the file offset fields. */ static void @@ -1069,28 +1048,8 @@ copy_dysymtab (struct load_command *lc, long delta) vm_address_t base; #ifdef _LP64 -#if __ppc64__ - { - int i; - - base = 0; - for (i = 0; i < nlc; i++) - if (lca[i]->cmd == LC_SEGMENT) - { - struct segment_command *scp = (struct segment_command *) lca[i]; - - if (scp->vmaddr + scp->vmsize > 0x100000000 - && (scp->initprot & VM_PROT_WRITE) != 0) - { - base = data_segment_scp->vmaddr; - break; - } - } - } -#else /* First writable segment address. */ base = data_segment_scp->vmaddr; -#endif #else /* First segment address in the file (unless MH_SPLIT_SEGS set). */ base = 0; @@ -1116,29 +1075,6 @@ copy_dysymtab (struct load_command *lc, long delta) unexec_error ("cannot write symtab command to header"); curr_header_offset += lc->cmdsize; - -#if __ppc64__ - /* Check if the relocation base needs to be changed. */ - if (base == 0) - { - vm_address_t newbase = 0; - int i; - - for (i = 0; i < num_unexec_regions; i++) - if (unexec_regions[i].range.address + unexec_regions[i].range.size - > 0x100000000) - { - newbase = data_segment_scp->vmaddr; - break; - } - - if (newbase) - { - rebase_reloc_address (dstp->locreloff, dstp->nlocrel, delta, newbase); - rebase_reloc_address (dstp->extreloff, dstp->nextrel, delta, newbase); - } - } -#endif } /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output diff --git a/src/unexw32.c b/src/unexw32.c index f70cdd79478..5c1c1f3f391 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -43,19 +43,11 @@ PIMAGE_NT_HEADERS extern BOOL ctrl_c_handler (unsigned long type); extern char my_begdata[]; -extern char my_edata[]; extern char my_begbss[]; -extern char my_endbss[]; extern char *my_begbss_static; -extern char *my_endbss_static; #include "w32heap.h" -#undef min -#undef max -#define min(x, y) (((x) < (y)) ? (x) : (y)) -#define max(x, y) (((x) > (y)) ? (x) : (y)) - /* Basically, our "initialized" flag. */ BOOL using_dynamic_heap = FALSE; @@ -83,8 +75,6 @@ PCHAR bss_start_static = 0; DWORD_PTR bss_size_static = 0; DWORD_PTR extra_bss_size_static = 0; -PIMAGE_SECTION_HEADER heap_section; - /* MinGW64 doesn't add a leading underscore to external symbols, whereas configure.ac sets up LD_SWITCH_SYSTEM_TEMACS to force the entry point at __start, with two underscores. */ @@ -475,8 +465,6 @@ get_section_info (file_data *p_infile) bss_section_static = 0; extra_bss_size_static = 0; } - - heap_section = rva_to_section (PTR_TO_RVA (get_heap_start ()), nt_header); } @@ -518,9 +506,11 @@ copy_executable_and_dump_data (file_data *p_infile, if (verbose) \ { \ printf ("%s\n", (message)); \ - printf ("\t0x%08x Address in process.\n", s); \ - printf ("\t0x%08x Offset in output file.\n", dst - p_outfile->file_base); \ - printf ("\t0x%08x Size in bytes.\n", count); \ + printf ("\t0x%p Address in process.\n", s); \ + printf ("\t0x%p Base output file.\n", p_outfile->file_base); \ + printf ("\t0x%p Offset in output file.\n", dst - p_outfile->file_base); \ + printf ("\t0x%p Address in output file.\n", dst); \ + printf ("\t0x%p Size in bytes.\n", count); \ } \ memcpy (dst, s, count); \ dst += count; \ @@ -629,34 +619,6 @@ copy_executable_and_dump_data (file_data *p_infile, dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA; dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; } - if (section == heap_section) - { - DWORD_PTR heap_start = (DWORD_PTR) get_heap_start (); - DWORD_PTR heap_size = get_committed_heap_size (); - - /* Dump the used portion of the predump heap, adjusting the - section's size to the appropriate size. */ - dst = dst_save - + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (heap_start), dst_section); - COPY_PROC_CHUNK ("Dumping heap...", heap_start, heap_size, - be_verbose); - ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); - dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile); - /* Determine new size of raw data area. */ - dst = max (dst, dst_save + dst_section->SizeOfRawData); - dst_section->SizeOfRawData = dst - dst_save; - /* Reduce the size of the heap section to fit (must be last - section). */ - dst_nt_header->OptionalHeader.SizeOfImage -= - dst_section->Misc.VirtualSize - - ROUND_UP (dst_section->SizeOfRawData, - dst_nt_header->OptionalHeader.SectionAlignment); - dst_section->Misc.VirtualSize = - ROUND_UP (dst_section->SizeOfRawData, - dst_nt_header->OptionalHeader.SectionAlignment); - dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA; - dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; - } /* Align the section's raw data area. */ ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); @@ -758,6 +720,10 @@ unexec (const char *new_name, const char *old_name) abort (); strcpy (p, q); +#ifdef ENABLE_CHECKING + report_temacs_memory_usage (); +#endif + /* Make sure that the output filename has the ".exe" extension...patch it up if not. */ p = out_filename + strlen (out_filename) - 4; @@ -767,9 +733,6 @@ unexec (const char *new_name, const char *old_name) printf ("Dumping from %s\n", in_filename); printf (" to %s\n", out_filename); - /* We need to round off our heap to NT's page size. */ - round_heap (get_page_size ()); - /* Open the undumped executable file. */ if (!open_input_file (&in_file, in_filename)) { @@ -784,7 +747,6 @@ unexec (const char *new_name, const char *old_name) /* The size of the dumped executable is the size of the original executable plus the size of the heap and the size of the .bss section. */ size = in_file.size + - get_committed_heap_size () + extra_bss_size + extra_bss_size_static; if (!open_output_file (&out_file, out_filename, size)) @@ -799,6 +761,10 @@ unexec (const char *new_name, const char *old_name) copy_executable_and_dump_data (&in_file, &out_file); + /* Unset it because it is plain wrong to keep it after dumping. + Malloc can still occur! */ + using_dynamic_heap = FALSE; + /* Patch up header fields; profiler is picky about this. */ { PIMAGE_DOS_HEADER dos_header; diff --git a/src/vm-limit.c b/src/vm-limit.c index bad1d61e611..015f3ee2111 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c @@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "lisp.h" #ifdef MSDOS -#include <dpmi.h> +#include "dosfns.h" extern int etext; #endif @@ -51,6 +51,15 @@ char data_start[1] = { 1 }; # endif #endif +/* From gmalloc.c. */ +extern void (* __after_morecore_hook) (void); +extern void *(*__morecore) (ptrdiff_t); + +/* From ralloc.c. */ +#ifdef REL_ALLOC +extern void *(*real_morecore) (ptrdiff_t); +#endif + /* Level number of warnings already issued. 0 -- no warnings issued. @@ -71,15 +80,6 @@ static char *data_space_start; /* Number of bytes of writable memory we can expect to be able to get. */ static size_t lim_data; -/* Return true if PTR cannot be represented as an Emacs Lisp object. */ -static bool -exceeds_lisp_ptr (void *ptr) -{ - return (! USE_LSB_TAG - && VAL_MAX < UINTPTR_MAX - && ((uintptr_t) ptr & ~DATA_SEG_BITS) >> VALBITS != 0); -} - #ifdef HAVE_GETRLIMIT # ifndef RLIMIT_AS @@ -115,29 +115,10 @@ get_lim_data (void) void get_lim_data (void) { - _go32_dpmi_meminfo info; - unsigned long lim1, lim2; - - _go32_dpmi_get_free_memory_information (&info); - /* DPMI server of Windows NT and its descendants reports in - info.available_memory a much lower amount that is really - available, which causes bogus "past 95% of memory limit" - warnings. Try to overcome that via circumstantial evidence. */ - lim1 = info.available_memory; - lim2 = info.available_physical_pages; - /* DPMI Spec: "Fields that are unavailable will hold -1." */ - if ((long)lim1 == -1L) - lim1 = 0; - if ((long)lim2 == -1L) - lim2 = 0; - else - lim2 *= 4096; - /* Surely, the available memory is at least what we have physically - available, right? */ - if (lim1 >= lim2) - lim_data = lim1; - else - lim_data = lim2; + unsigned long totalram, freeram, totalswap, freeswap; + + dos_memory_info (&totalram, &freeram, &totalswap, &freeswap); + lim_data = freeram; /* Don't believe they will give us more that 0.5 GB. */ if (lim_data > 512U * 1024U * 1024U) lim_data = 512U * 1024U * 1024U; @@ -158,12 +139,9 @@ ret_lim_data (void) static void check_memory_limits (void) { -#ifdef REL_ALLOC - extern void *(*real_morecore) (ptrdiff_t); -#else +#ifndef REL_ALLOC void *(*real_morecore) (ptrdiff_t) = 0; #endif - extern void *(*__morecore) (ptrdiff_t); char *cp; size_t five_percent; @@ -222,9 +200,6 @@ check_memory_limits (void) else if (warnlevel > warned_85 && data_size < five_percent * 18) warnlevel = warned_85; } - - if (exceeds_lisp_ptr (cp)) - (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); } /* Enable memory usage warnings. @@ -234,8 +209,6 @@ check_memory_limits (void) void memory_warnings (void *start, void (*warnfun) (const char *)) { - extern void (* __after_morecore_hook) (void); /* From gmalloc.c */ - data_space_start = start ? start : data_start; warn_function = warnfun; diff --git a/src/w32.c b/src/w32.c index aba0b5a81f9..f014cd73a76 100644 --- a/src/w32.c +++ b/src/w32.c @@ -73,9 +73,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <grp.h> /* MinGW64 (_W64) defines these in its _mingw.h. */ -#if defined(__GNUC__) && !defined(_W64) -#define _ANONYMOUS_UNION -#define _ANONYMOUS_STRUCT +#ifndef _ANONYMOUS_UNION +# define _ANONYMOUS_UNION +#endif +#ifndef _ANONYMOUS_STRUCT +# define _ANONYMOUS_STRUCT #endif #include <windows.h> /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we @@ -307,6 +309,8 @@ static BOOL g_b_init_set_named_security_info_w; static BOOL g_b_init_set_named_security_info_a; static BOOL g_b_init_get_adapters_info; +BOOL g_b_init_compare_string_w; + /* BEGIN: Wrapper functions around OpenProcessToken and other functions in advapi32.dll that are only @@ -880,7 +884,7 @@ set_named_security_info (LPCTSTR lpObjectName, g_b_init_set_named_security_info_a = 1; hm_advapi32 = LoadLibrary ("Advapi32.dll"); s_pfn_Set_Named_Security_InfoA = - (SetNamedSecurityInfoA_Proc) GetProcAddress (hm_advapi32, + (SetNamedSecurityInfoA_Proc) GetProcAddress (hm_advapi32, "SetNamedSecurityInfoA"); } if (s_pfn_Set_Named_Security_InfoA == NULL) @@ -1707,7 +1711,7 @@ static unsigned num_of_processors; /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */ static struct load_sample samples[16*60]; static int first_idx = -1, last_idx = -1; -static int max_idx = sizeof (samples) / sizeof (samples[0]); +static int max_idx = ARRAYELTS (samples); static int buf_next (int from) @@ -2290,7 +2294,7 @@ get_long_basename (char * name, char * buf, int size) /* Get long name for file, if possible (assumed to be absolute). */ BOOL -w32_get_long_filename (char * name, char * buf, int size) +w32_get_long_filename (const char * name, char * buf, int size) { char * o = buf; char * p; @@ -2341,7 +2345,7 @@ w32_get_long_filename (char * name, char * buf, int size) } unsigned int -w32_get_short_filename (char * name, char * buf, int size) +w32_get_short_filename (const char * name, char * buf, int size) { if (w32_unicode_filenames) { @@ -2415,7 +2419,6 @@ unsetenv (const char *name) { char *var; size_t name_len; - int retval; if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { @@ -2514,7 +2517,7 @@ init_environment (char ** argv) int i; - const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]); + const int imax = ARRAYELTS (tempdirs); /* Implementation note: This function explicitly works with ANSI file names, not with UTF-8 encoded file names. This is because @@ -2587,7 +2590,7 @@ init_environment (char ** argv) {"LANG", NULL}, }; -#define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0]) +#define N_ENV_VARS ARRAYELTS (dflt_envvars) /* We need to copy dflt_envvars[] and work on the copy because we don't want the dumped Emacs to inherit the values of @@ -6956,6 +6959,35 @@ system_process_attributes (Lisp_Object pid) return attrs; } +int +w32_memory_info (unsigned long long *totalram, unsigned long long *freeram, + unsigned long long *totalswap, unsigned long long *freeswap) +{ + MEMORYSTATUS memst; + MEMORY_STATUS_EX memstex; + + /* Use GlobalMemoryStatusEx if available, as it can report more than + 2GB of memory. */ + if (global_memory_status_ex (&memstex)) + { + *totalram = memstex.ullTotalPhys; + *freeram = memstex.ullAvailPhys; + *totalswap = memstex.ullTotalPageFile; + *freeswap = memstex.ullAvailPageFile; + return 0; + } + else if (global_memory_status (&memst)) + { + *totalram = memst.dwTotalPhys; + *freeram = memst.dwAvailPhys; + *totalswap = memst.dwTotalPageFile; + *freeswap = memst.dwAvailPageFile; + return 0; + } + else + return -1; +} + /* Wrappers for winsock functions to map between our file descriptors and winsock's handles; also set h_errno for convenience. @@ -7860,7 +7892,7 @@ pipe2 (int * phandles, int pipe2_flags) int rc; unsigned flags; - eassert (pipe2_flags == O_CLOEXEC); + eassert (pipe2_flags == (O_BINARY | O_CLOEXEC)); /* make pipe handles non-inheritable; when we spawn a child, we replace the relevant handle with an inheritable one. Also put @@ -8233,6 +8265,7 @@ int sys_write (int fd, const void * buffer, unsigned int count) { int nchars; + USE_SAFE_ALLOCA; if (fd < 0) { @@ -8251,30 +8284,33 @@ sys_write (int fd, const void * buffer, unsigned int count) /* Perform text mode translation if required. */ if ((fd_info[fd].flags & FILE_BINARY) == 0) { - char * tmpbuf = alloca (count * 2); - unsigned char * src = (void *)buffer; - unsigned char * dst = tmpbuf; + char * tmpbuf; + const unsigned char * src = buffer; + unsigned char * dst; int nbytes = count; + SAFE_NALLOCA (tmpbuf, 2, count); + dst = tmpbuf; + while (1) { unsigned char *next; - /* copy next line or remaining bytes */ + /* Copy next line or remaining bytes. */ next = _memccpy (dst, src, '\n', nbytes); if (next) { - /* copied one line ending with '\n' */ + /* Copied one line ending with '\n'. */ int copied = next - dst; nbytes -= copied; src += copied; - /* insert '\r' before '\n' */ + /* Insert '\r' before '\n'. */ next[-1] = '\r'; next[0] = '\n'; dst = next + 1; count++; } else - /* copied remaining partial line -> now finished */ + /* Copied remaining partial line -> now finished. */ break; } buffer = tmpbuf; @@ -8288,31 +8324,44 @@ sys_write (int fd, const void * buffer, unsigned int count) HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent }; DWORD active = 0; + /* This is async (a.k.a. "overlapped") I/O, so the return value + of FALSE from WriteFile means either an error or the output + will be completed asynchronously (ERROR_IO_PENDING). */ if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl)) { if (GetLastError () != ERROR_IO_PENDING) { errno = EIO; - return -1; + nchars = -1; } - if (detect_input_pending ()) - active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE, - QS_ALLINPUT); else - active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE); - if (active == WAIT_OBJECT_0) - { /* User pressed C-g, cancel write, then leave. Don't bother - cleaning up as we may only get stuck in buggy drivers. */ - PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR); - CancelIo (hnd); - errno = EIO; - return -1; - } - if (active == WAIT_OBJECT_0 + 1 - && !GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE)) { - errno = EIO; - return -1; + /* Wait for the write to complete, and watch C-g while + at that. */ + if (detect_input_pending ()) + active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE, + INFINITE, QS_ALLINPUT); + else + active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE); + switch (active) + { + case WAIT_OBJECT_0: + /* User pressed C-g, cancel write, then leave. + Don't bother cleaning up as we may only get stuck + in buggy drivers. */ + PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR); + CancelIo (hnd); + errno = EIO; /* Why not EINTR? */ + nchars = -1; + break; + case WAIT_OBJECT_0 + 1: + if (!GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE)) + { + errno = EIO; + nchars = -1; + } + break; + } } } } @@ -8389,6 +8438,7 @@ sys_write (int fd, const void * buffer, unsigned int count) } } + SAFE_FREE (); return nchars; } @@ -8738,6 +8788,13 @@ w32_delayed_load (Lisp_Object library_id) /* Possibly truncated */ ? make_specified_string (name, -1, len, 1) : Qnil); + /* This prevents thread start and end notifications + from being sent to the DLL, for every thread we + start. We don't need those notifications because + threads we create never use any of these DLLs, only + the main thread uses them. This is supposed to + speed up thread creation. */ + DisableThreadLibraryCalls (dll_handle); break; } } @@ -9071,6 +9128,7 @@ globals_of_w32 (void) g_b_init_set_named_security_info_w = 0; g_b_init_set_named_security_info_a = 0; g_b_init_get_adapters_info = 0; + g_b_init_compare_string_w = 0; num_of_processors = 0; /* The following sets a handler for shutdown notifications for console apps. This actually applies to Emacs in both console and @@ -9290,8 +9348,6 @@ ssize_t emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz) { int n, err; - SELECT_TYPE fdset; - struct timespec timeout; struct Lisp_Process *process = (struct Lisp_Process *)p; int fd = process->infd; diff --git a/src/w32.h b/src/w32.h index 33fd2709a71..e0aedcbffa2 100644 --- a/src/w32.h +++ b/src/w32.h @@ -144,10 +144,10 @@ extern char * w32_strerror (int error_no); extern int w32_valid_pointer_p (void *, int); /* Get long (aka "true") form of file name, if it exists. */ -extern BOOL w32_get_long_filename (char * name, char * buf, int size); +extern BOOL w32_get_long_filename (const char * name, char * buf, int size); /* Get the short (a.k.a. "8+3") form of a file name. */ -extern unsigned int w32_get_short_filename (char *, char *, int); +extern unsigned int w32_get_short_filename (const char *, char *, int); /* Prepare our standard handles for proper inheritance by child processes. */ extern void prepare_standard_handles (int in, int out, @@ -206,6 +206,13 @@ extern void register_child (pid_t, int); extern void sys_sleep (int); extern int sys_link (const char *, const char *); +/* Return total and free memory info. */ +extern int w32_memory_info (unsigned long long *, unsigned long long *, + unsigned long long *, unsigned long long *); + +/* Compare 2 UTF-8 strings in locale-dependent fashion. */ +extern int w32_compare_strings (const char *, const char *, char *, int); + #ifdef HAVE_GNUTLS #include <gnutls/gnutls.h> diff --git a/src/w32console.c b/src/w32console.c index e3ca2f86b8d..82a7c041900 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -36,8 +36,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "termhooks.h" #include "termchar.h" #include "dispextern.h" +#include "menu.h" /* for tty_menu_show */ #include "w32term.h" -#include "w32common.h" /* for os_subtype */ +#include "w32common.h" /* for os_subtype */ #include "w32inevt.h" /* from window.c */ @@ -117,7 +118,7 @@ static void w32con_clear_to_end (struct frame *f) { w32con_clear_end_of_line (f, FRAME_COLS (f) - 1); - w32con_ins_del_lines (f, cursor_coords.Y, FRAME_LINES (f) - cursor_coords.Y - 1); + w32con_ins_del_lines (f, cursor_coords.Y, FRAME_TOTAL_LINES (f) - cursor_coords.Y - 1); } /* Clear the frame. */ @@ -132,7 +133,7 @@ w32con_clear_frame (struct frame *f) GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info); /* Remember that the screen buffer might be wider than the window. */ - n = FRAME_LINES (f) * info.dwSize.X; + n = FRAME_TOTAL_LINES (f) * info.dwSize.X; dest.X = dest.Y = 0; FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r); @@ -174,18 +175,18 @@ w32con_ins_del_lines (struct frame *f, int vpos, int n) if (n < 0) { scroll.Top = vpos - n; - scroll.Bottom = FRAME_LINES (f); + scroll.Bottom = FRAME_TOTAL_LINES (f); dest.Y = vpos; } else { scroll.Top = vpos; - scroll.Bottom = FRAME_LINES (f) - n; + scroll.Bottom = FRAME_TOTAL_LINES (f) - n; dest.Y = vpos + n; } clip.Top = clip.Left = scroll.Left = 0; clip.Right = scroll.Right = FRAME_COLS (f); - clip.Bottom = FRAME_LINES (f); + clip.Bottom = FRAME_TOTAL_LINES (f); dest.X = 0; @@ -650,11 +651,13 @@ initialize_w32_display (struct terminal *term, int *width, int *height) term->read_socket_hook = w32_console_read_socket; term->mouse_position_hook = w32_console_mouse_position; + term->menu_show_hook = tty_menu_show; /* The following are not used on the console. */ term->frame_rehighlight_hook = 0; term->frame_raise_lower_hook = 0; term->set_vertical_scroll_bar_hook = 0; + term->set_horizontal_scroll_bar_hook = 0; term->condemn_scroll_bars_hook = 0; term->redeem_scroll_bar_hook = 0; term->judge_scroll_bars_hook = 0; diff --git a/src/w32fns.c b/src/w32fns.c index bc95005f52a..05da2a5c1d1 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -89,14 +89,10 @@ extern void w32_free_menu_strings (HWND); extern const char *map_w32_filename (const char *, const char **); extern char * w32_strerror (int error_no); -/* If non-NULL, a handle to a frame where to display the hourglass cursor. */ -static HWND hourglass_hwnd = NULL; - #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif -Lisp_Object Qsuppress_icon; Lisp_Object Qundefined_color; Lisp_Object Qcancel_timer; Lisp_Object Qfont_param; @@ -228,16 +224,12 @@ static int w32_unicode_gui; /* From w32menu.c */ extern HMENU current_popup_menu; -static int menubar_in_use = 0; +int menubar_in_use = 0; /* From w32uniscribe.c */ extern void syms_of_w32uniscribe (void); extern int uniscribe_available; -/* Function prototypes for hourglass support. */ -static void w32_show_hourglass (struct frame *); -static void w32_hide_hourglass (void); - #ifdef WINDOWSNT /* From w32inevt.c */ extern int faked_key; @@ -271,9 +263,9 @@ static unsigned int sound_type = 0xFFFFFFFF; the first display on the list. */ struct w32_display_info * -check_x_display_info (Lisp_Object frame) +check_x_display_info (Lisp_Object object) { - if (NILP (frame)) + if (NILP (object)) { struct frame *sf = XFRAME (selected_frame); @@ -282,14 +274,23 @@ check_x_display_info (Lisp_Object frame) else return &one_w32_display_info; } - else if (STRINGP (frame)) - return x_display_info_for_name (frame); + else if (TERMINALP (object)) + { + struct terminal *t = decode_live_terminal (object); + + if (t->type != output_w32) + error ("Terminal %d is not a W32 display", t->id); + + return t->display_info.w32; + } + else if (STRINGP (object)) + return x_display_info_for_name (object); else { struct frame *f; - CHECK_LIVE_FRAME (frame); - f = XFRAME (frame); + CHECK_LIVE_FRAME (object); + f = XFRAME (object); if (! FRAME_W32_P (f)) error ("Non-W32 frame used"); return FRAME_DISPLAY_INFO (f); @@ -336,8 +337,7 @@ void x_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object); void x_set_title (struct frame *, Lisp_Object, Lisp_Object); void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object); - - +void x_set_internal_border_width (struct frame *f, Lisp_Object, Lisp_Object); /* Store the screen positions of frame F into XPTR and YPTR. @@ -723,8 +723,7 @@ w32_default_color_map (void) cmap = Qnil; - for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]); - pc++, i++) + for (i = 0; i < ARRAYELTS (w32_color_map); pc++, i++) cmap = Fcons (Fcons (build_string (pc->name), make_number (pc->colorref)), cmap); @@ -1370,23 +1369,23 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { CHECK_NUMBER (Vx_window_horizontal_drag_shape); horizontal_drag_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), + = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_window_horizontal_drag_shape)); } else horizontal_drag_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow); + = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow); if (!NILP (Vx_window_vertical_drag_shape)) { CHECK_NUMBER (Vx_window_vertical_drag_shape); vertical_drag_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), + = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_window_vertical_drag_shape)); } else vertical_drag_cursor - = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_v_double_arrow); + = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_v_double_arrow); /* Check and report errors with the above calls. */ x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s"); @@ -1608,9 +1607,54 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) unblock_input (); #endif } - void +x_clear_under_internal_border (struct frame *f) +{ + int border = FRAME_INTERNAL_BORDER_WIDTH (f); + + /* Clear border if it's larger than before. */ + if (border != 0) + { + HDC hdc = get_frame_dc (f); + int width = FRAME_PIXEL_WIDTH (f); + int height = FRAME_PIXEL_HEIGHT (f); + + block_input (); + w32_clear_area (f, hdc, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border); + w32_clear_area (f, hdc, 0, 0, border, height); + w32_clear_area (f, hdc, width - border, 0, border, height); + w32_clear_area (f, hdc, 0, height - border, width, border); + release_frame_dc (f, hdc); + unblock_input (); + } +} + + +void +x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + int border; + + CHECK_TYPE_RANGED_INTEGER (int, arg); + border = max (XINT (arg), 0); + + if (border != FRAME_INTERNAL_BORDER_WIDTH (f)) + { + FRAME_INTERNAL_BORDER_WIDTH (f) = border; + + if (FRAME_X_WINDOW (f) != 0) + { + adjust_frame_size (f, -1, -1, 3, 0); + + if (FRAME_VISIBLE_P (f)) + x_clear_under_internal_border (f); + } + } +} + + +void x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { int nlines; @@ -1630,7 +1674,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) FRAME_MENU_BAR_LINES (f) = 0; FRAME_MENU_BAR_HEIGHT (f) = 0; if (nlines) - FRAME_EXTERNAL_MENU_BAR (f) = 1; + { + FRAME_EXTERNAL_MENU_BAR (f) = 1; + windows_or_buffers_changed = 23; + } else { if (FRAME_EXTERNAL_MENU_BAR (f) == 1) @@ -1639,11 +1686,16 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) /* Adjust the frame size so that the client (text) dimensions remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being - set correctly. */ - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + set correctly. Note that we resize twice: The first time upon + a request from the window manager who wants to keep the height + of the outer rectangle (including decorations) unchanged, and a + second time because we want to keep the height of the inner + rectangle (without the decorations unchanged). */ + adjust_frame_size (f, -1, -1, 2, 1); + + /* Not sure whether this is needed. */ + x_clear_under_internal_border (f); } - adjust_frame_glyphs (f); } @@ -1657,8 +1709,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) void x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { - int delta, nlines, root_height; - int unit = FRAME_LINE_HEIGHT (f); + int nlines; /* Treat tool bars like menu bars. */ if (FRAME_MINIBUF_ONLY_P (f)) @@ -1670,66 +1721,50 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) else nlines = 0; - /* Make sure we redisplay all windows in this frame. */ - windows_or_buffers_changed = 23; + x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f)); +} - /* DELTA is in pixels now. */ - delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit; - /* Don't resize the tool-bar to more than we have room for. Note: The - calculations below and the subsequent call to resize_frame_windows - are inherently flawed because they can make the toolbar higher than - the containing frame. */ - if (delta > 0) - { - root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f))); - if (root_height - delta < unit) - { - delta = root_height - unit; - /* When creating a new frame and toolbar mode is enabled, we - need at least one toolbar line. */ - nlines = max (FRAME_TOOL_BAR_LINES (f) + delta / unit, 1); - } - } +/* Set the pixel height of the tool bar of frame F to HEIGHT. */ +void +x_change_tool_bar_height (struct frame *f, int height) +{ + Lisp_Object frame; + int unit = FRAME_LINE_HEIGHT (f); + int old_height = FRAME_TOOL_BAR_HEIGHT (f); + int lines = (height + unit - 1) / unit; + int old_text_height = FRAME_TEXT_HEIGHT (f); - FRAME_TOOL_BAR_LINES (f) = nlines; - FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - ++windows_or_buffers_changed; - resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1); - adjust_frame_glyphs (f); + /* Make sure we redisplay all windows in this frame. */ + windows_or_buffers_changed = 23; + + /* Recalculate tool bar and frame text sizes. */ + FRAME_TOOL_BAR_HEIGHT (f) = height; + FRAME_TOOL_BAR_LINES (f) = lines; + FRAME_TEXT_HEIGHT (f) + = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f)); + FRAME_LINES (f) + = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f)); + /* Store the `tool-bar-lines' and `height' frame parameters. */ + store_frame_param (f, Qtool_bar_lines, make_number (lines)); + store_frame_param (f, Qheight, make_number (FRAME_LINES (f))); - /* We also have to make sure that the internal border at the top of - the frame, below the menu bar or tool bar, is redrawn when the - tool bar disappears. This is so because the internal border is - below the tool bar if one is displayed, but is below the menu bar - if there isn't a tool bar. The tool bar draws into the area - below the menu bar. */ if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0) { clear_frame (f); clear_current_matrices (f); } - /* If the tool bar gets smaller, the internal border below it - has to be cleared. It was formerly part of the display - of the larger tool bar, and updating windows won't clear it. */ - if (FRAME_INTERNAL_BORDER_WIDTH (f) != 0 && FRAME_VISIBLE_P (f)) - { - int height = FRAME_INTERNAL_BORDER_WIDTH (f); - int width = FRAME_PIXEL_WIDTH (f); - int y = nlines * unit; - HDC hdc = get_frame_dc (f); + if ((height < old_height) && WINDOWP (f->tool_bar_window)) + clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); - block_input (); - w32_clear_area (f, hdc, 0, y, width, height); - release_frame_dc (f, hdc); - unblock_input (); - } + /* Recalculate toolbar height. */ + f->n_tool_bar_rows = 0; - if (delta < 0 && WINDOWP (f->tool_bar_window)) - clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); + adjust_frame_size (f, -1, -1, 4, 0); - run_window_configuration_change_hook (f); + if (FRAME_X_WINDOW (f)) + x_clear_under_internal_border (f); } @@ -1848,6 +1883,16 @@ x_set_scroll_bar_default_width (struct frame *f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit; } + +void +x_set_scroll_bar_default_height (struct frame *f) +{ + int unit = FRAME_LINE_HEIGHT (f); + + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL); + FRAME_CONFIG_SCROLL_BAR_LINES (f) + = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit; +} /* Subroutines for creating a frame. */ @@ -1902,7 +1947,7 @@ w32_init_class (HINSTANCE hinst) } static HWND -w32_createscrollbar (struct frame *f, struct scroll_bar * bar) +w32_createvscrollbar (struct frame *f, struct scroll_bar * bar) { return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE, /* Position and size of scroll bar. */ @@ -1910,6 +1955,15 @@ w32_createscrollbar (struct frame *f, struct scroll_bar * bar) FRAME_W32_WINDOW (f), NULL, hinst, NULL); } +static HWND +w32_createhscrollbar (struct frame *f, struct scroll_bar * bar) +{ + return CreateWindow ("SCROLLBAR", "", SBS_HORZ | WS_CHILD | WS_VISIBLE, + /* Position and size of scroll bar. */ + bar->left, bar->top, bar->width, bar->height, + FRAME_W32_WINDOW (f), NULL, hinst, NULL); +} + static void w32_createwindow (struct frame *f, int *coords) { @@ -1956,7 +2010,8 @@ w32_createwindow (struct frame *f, int *coords) SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); - SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f)); + SetWindowLong (hwnd, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f)); + SetWindowLong (hwnd, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f)); SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f)); /* Enable drag-n-drop. */ @@ -2371,7 +2426,8 @@ w32_name_of_message (UINT msg) M (WM_EMACS_KILL), M (WM_EMACS_CREATEWINDOW), M (WM_EMACS_DONE), - M (WM_EMACS_CREATESCROLLBAR), + M (WM_EMACS_CREATEVSCROLLBAR), + M (WM_EMACS_CREATEHSCROLLBAR), M (WM_EMACS_SHOWWINDOW), M (WM_EMACS_SETWINDOWPOS), M (WM_EMACS_DESTROYWINDOW), @@ -2388,6 +2444,7 @@ w32_name_of_message (UINT msg) M (WM_EMACS_SHOW_CARET), M (WM_EMACS_HIDE_CARET), M (WM_EMACS_SETCURSOR), + M (WM_EMACS_SHOWCURSOR), M (WM_EMACS_PAINT), M (WM_CHAR), #undef M @@ -3446,6 +3503,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) track_mouse_event_fn (&tme); track_mouse_window = hwnd; } + case WM_HSCROLL: case WM_VSCROLL: if (w32_mouse_move_interval <= 0 || (msg == WM_MOUSEMOVE && button_state == 0)) @@ -3784,10 +3842,14 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; case WM_WINDOWPOSCHANGING: - /* Don't restrict the sizing of tip frames. */ - if (frame_resize_pixelwise || hwnd == tip_window) - return 0; + /* Don't restrict the sizing of any kind of frames. If the window + manager doesn't, there's no reason to do it ourselves. */ +#if 0 + if (frame_resize_pixelwise || hwnd == tip_window) +#endif + return 0; +#if 0 /* Don't restrict the sizing of fullscreened frames, allowing them to be flush with the sides of the screen. */ f = x_window_to_frame (dpyinfo, hwnd); @@ -3810,7 +3872,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) DWORD font_width; DWORD line_height; DWORD internal_border; - DWORD scrollbar_extra; + DWORD vscrollbar_extra; + DWORD hscrollbar_extra; RECT wr; wp.length = sizeof (wp); @@ -3821,7 +3884,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX); line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX); internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX); - scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX); + vscrollbar_extra = GetWindowLong (hwnd, WND_VSCROLLBAR_INDEX); + hscrollbar_extra = GetWindowLong (hwnd, WND_HSCROLLBAR_INDEX); leave_crit (); @@ -3832,10 +3896,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Force width and height of client area to be exact multiples of the character cell dimensions. */ wdiff = (lppos->cx - (rect.right - rect.left) - - 2 * internal_border - scrollbar_extra) + - 2 * internal_border - vscrollbar_extra) % font_width; hdiff = (lppos->cy - (rect.bottom - rect.top) - - 2 * internal_border) + - 2 * internal_border - hscrollbar_extra) % line_height; if (wdiff || hdiff) @@ -3870,6 +3934,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } goto dflt; +#endif case WM_GETMINMAXINFO: /* Hack to allow resizing the Emacs frame above the screen size. @@ -3904,9 +3969,20 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; } - case WM_EMACS_CREATESCROLLBAR: - return (LRESULT) w32_createscrollbar ((struct frame *) wParam, - (struct scroll_bar *) lParam); + case WM_EMACS_SHOWCURSOR: + { + ShowCursor ((BOOL) wParam); + + return 0; + } + + case WM_EMACS_CREATEVSCROLLBAR: + return (LRESULT) w32_createvscrollbar ((struct frame *) wParam, + (struct scroll_bar *) lParam); + + case WM_EMACS_CREATEHSCROLLBAR: + return (LRESULT) w32_createhscrollbar ((struct frame *) wParam, + (struct scroll_bar *) lParam); case WM_EMACS_SHOWWINDOW: return ShowWindow ((HWND) wParam, (WPARAM) lParam); @@ -4126,7 +4202,8 @@ my_create_tip_window (struct frame *f) SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f)); /* Tip frames have no scrollbars. */ - SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0); + SetWindowLong (tip_window, WND_VSCROLLBAR_INDEX, 0); + SetWindowLong (tip_window, WND_HSCROLLBAR_INDEX, 0); /* Do this to discard the default setting specified by our parent. */ ShowWindow (tip_window, SW_HIDE); @@ -4358,7 +4435,6 @@ This function is an internal primitive--use `make-frame' instead. */) Lisp_Object name; int minibuffer_only = 0; long window_prompting = 0; - int width, height; ptrdiff_t count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; Lisp_Object display; @@ -4426,8 +4502,9 @@ This function is an internal primitive--use `make-frame' instead. */) XSETFRAME (frame, f); - /* By default, make scrollbars the system standard width. */ - x_set_scroll_bar_default_width (f); + /* By default, make scrollbars the system standard width and height. */ + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL); f->terminal = dpyinfo->terminal; @@ -4453,7 +4530,6 @@ This function is an internal primitive--use `make-frame' instead. */) #endif /* GLYPH_DEBUG */ /* Specify the parent under which to make this window. */ - if (!NILP (parent)) { f->output_data.w32->parent_desc = (Window) XFASTINT (parent); @@ -4476,7 +4552,7 @@ This function is an internal primitive--use `make-frame' instead. */) { fset_name (f, name); f->explicit_name = 1; - /* use the frame's title when getting resources for this frame. */ + /* Use the frame's title when getting resources for this frame. */ specbind (Qx_resource_name, name); } @@ -4486,9 +4562,11 @@ This function is an internal primitive--use `make-frame' instead. */) x_default_parameter (f, parameters, Qfont_backend, Qnil, "fontBackend", "FontBackend", RES_TYPE_STRING); + /* Extract the window parameters from the supplied values that are needed to determine window geometry. */ x_default_font_parameter (f, parameters); + x_default_parameter (f, parameters, Qborder_width, make_number (2), "borderWidth", "BorderWidth", RES_TYPE_NUMBER); @@ -4502,7 +4580,7 @@ This function is an internal primitive--use `make-frame' instead. */) "internalBorder", "InternalBorder", RES_TYPE_NUMBER); if (! EQ (value, Qunbound)) parameters = Fcons (Fcons (Qinternal_border_width, value), - parameters); + parameters); } /* Default internalBorderWidth to 0 on Windows to match other programs. */ x_default_parameter (f, parameters, Qinternal_border_width, make_number (0), @@ -4513,6 +4591,8 @@ This function is an internal primitive--use `make-frame' instead. */) NULL, NULL, RES_TYPE_NUMBER); x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright, "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); + x_default_parameter (f, parameters, Qhorizontal_scroll_bars, Qnil, + "horizontalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); /* Also do the stuff which must be set before the window exists. */ x_default_parameter (f, parameters, Qforeground_color, build_string ("black"), @@ -4533,57 +4613,42 @@ This function is an internal primitive--use `make-frame' instead. */) "rightFringe", "RightFringe", RES_TYPE_NUMBER); /* Process alpha here (Bug#16619). */ x_default_parameter (f, parameters, Qalpha, Qnil, - "alpha", "Alpha", RES_TYPE_NUMBER); + "alpha", "Alpha", RES_TYPE_NUMBER); - /* Init faces before x_default_parameter is called for scroll-bar - parameters because that function calls x_set_scroll_bar_width, - which calls change_frame_size, which calls Fset_window_buffer, - which runs hooks, which call Fvertical_motion. At the end, we - end up in init_iterator with a null face cache, which should not - happen. */ + /* Init faces first since we need the frame's column width/line + height in various occasions. */ init_frame_faces (f); - /* Avoid calling window-configuration-change-hook; otherwise we - could get an infloop in next_frame since the frame is not yet in - Vframe_list. */ - { - ptrdiff_t count2 = SPECPDL_INDEX (); - - record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code); - inhibit_lisp_code = Qt; - - /* PXW: This is a duplicate from below. We have to do it here since - otherwise x_set_tool_bar_lines will work with the character sizes - installed by init_frame_faces while the frame's pixel size is still - calculated from a character size of 1 and we subsequently hit the - eassert (height >= 0) assertion in window_box_height. The - non-pixelwise code apparently worked around this because it had one - frame line vs one toolbar line which left us with a zero root - window height which was obviously wrong as well ... */ - change_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), - FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1, 0, 0, 1); - - /* The X resources controlling the menu-bar and tool-bar are - processed specially at startup, and reflected in the mode - variables; ignore them here. */ - x_default_parameter (f, parameters, Qmenu_bar_lines, - NILP (Vmenu_bar_mode) - ? make_number (0) : make_number (1), - NULL, NULL, RES_TYPE_NUMBER); - x_default_parameter (f, parameters, Qtool_bar_lines, - NILP (Vtool_bar_mode) - ? make_number (0) : make_number (1), - NULL, NULL, RES_TYPE_NUMBER); - - unbind_to (count2, Qnil); - } + /* The following call of change_frame_size is needed since otherwise + x_set_tool_bar_lines will already work with the character sizes + installed by init_frame_faces while the frame's pixel size is + still calculated from a character size of 1 and we subsequently + hit the (height >= 0) assertion in window_box_height. + + The non-pixelwise code apparently worked around this because it + had one frame line vs one toolbar line which left us with a zero + root window height which was obviously wrong as well ... */ + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1); + + /* The X resources controlling the menu-bar and tool-bar are + processed specially at startup, and reflected in the mode + variables; ignore them here. */ + x_default_parameter (f, parameters, Qmenu_bar_lines, + NILP (Vmenu_bar_mode) + ? make_number (0) : make_number (1), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parameters, Qtool_bar_lines, + NILP (Vtool_bar_mode) + ? make_number (0) : make_number (1), + NULL, NULL, RES_TYPE_NUMBER); x_default_parameter (f, parameters, Qbuffer_predicate, Qnil, "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL); x_default_parameter (f, parameters, Qtitle, Qnil, "title", "Title", RES_TYPE_STRING); x_default_parameter (f, parameters, Qfullscreen, Qnil, - "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); + "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW; f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; @@ -4626,15 +4691,13 @@ This function is an internal primitive--use `make-frame' instead. */) "cursorType", "CursorType", RES_TYPE_SYMBOL); x_default_parameter (f, parameters, Qscroll_bar_width, Qnil, "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER); + x_default_parameter (f, parameters, Qscroll_bar_height, Qnil, + "scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER); + + /* Consider frame official, now. */ + f->official = true; - /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. - Change will not be effected unless different from the current - FRAME_LINES (f). */ - width = FRAME_TEXT_WIDTH (f); - height = FRAME_TEXT_HEIGHT (f); - FRAME_TEXT_HEIGHT (f) = 0; - SET_FRAME_WIDTH (f, 0); - change_frame_size (f, width, height, 1, 0, 0, 1); + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1); /* Tell the server what size and position, etc, we want, and how badly we want them. This should be done after we have the menu @@ -4971,7 +5034,7 @@ If omitted or nil, that stands for the selected frame's display. */) return Qnil; } -static BOOL CALLBACK +static BOOL CALLBACK ALIGN_STACK w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData) { Lisp_Object *monitor_list = (Lisp_Object *) dwData; @@ -5298,7 +5361,7 @@ terminate Emacs if we can't open the connection. { char basename[ MAX_PATH ], *str; - strcpy (basename, SDATA (Vinvocation_name)); + lispstpcpy (basename, Vinvocation_name); str = strrchr (basename, '.'); if (str) *str = 0; Vinvocation_name = build_string (basename); @@ -5510,100 +5573,6 @@ no value of TYPE (always string in the MS Windows case). */) #endif /* TODO */ - -/*********************************************************************** - Busy cursor - ***********************************************************************/ - -void -w32_note_current_window (void) -{ - struct frame * f = SELECTED_FRAME (); - - if (!FRAME_W32_P (f)) - return; - - hourglass_hwnd = FRAME_W32_WINDOW (f); -} - -void -show_hourglass (struct atimer *timer) -{ - struct frame *f; - - hourglass_atimer = NULL; - - block_input (); - f = x_window_to_frame (&one_w32_display_info, - hourglass_hwnd); - - if (f) - f->output_data.w32->hourglass_p = 0; - else - f = SELECTED_FRAME (); - - if (!FRAME_W32_P (f)) - { - unblock_input (); - return; - } - - w32_show_hourglass (f); - unblock_input (); -} - -void -hide_hourglass (void) -{ - block_input (); - w32_hide_hourglass (); - unblock_input (); -} - - -/* Display an hourglass cursor. Set the hourglass_p flag in display info - to indicate that an hourglass cursor is shown. */ - -static void -w32_show_hourglass (struct frame *f) -{ - if (!hourglass_shown_p) - { - f->output_data.w32->hourglass_p = 1; - if (!menubar_in_use && !current_popup_menu) - SetCursor (f->output_data.w32->hourglass_cursor); - hourglass_shown_p = 1; - } -} - - -/* Hide the hourglass cursor on all frames, if it is currently shown. */ - -static void -w32_hide_hourglass (void) -{ - if (hourglass_shown_p) - { - struct frame *f = x_window_to_frame (&one_w32_display_info, - hourglass_hwnd); - if (f) - f->output_data.w32->hourglass_p = 0; - else - /* If frame was deleted, restore to selected frame's cursor. */ - f = SELECTED_FRAME (); - - if (FRAME_W32_P (f)) - SetCursor (f->output_data.w32->current_cursor); - else - /* No cursors on non GUI frames - restore to stock arrow cursor. */ - SetCursor (w32_load_cursor (IDC_ARROW)); - - hourglass_shown_p = 0; - } -} - - - /*********************************************************************** Tool tips ***********************************************************************/ @@ -5693,7 +5662,8 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, f->wants_modeline = 0; XSETFRAME (frame, f); - buffer = Fget_buffer_create (build_string (" *tip*")); + AUTO_STRING (tip, " *tip*"); + buffer = Fget_buffer_create (tip); /* Use set_window_buffer instead of Fset_window_buffer (see discussion of bug#11984, bug#12025, bug#12026). */ set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, 0, 0); @@ -5788,13 +5758,12 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, "cursorColor", "Foreground", RES_TYPE_STRING); x_default_parameter (f, parms, Qborder_color, build_string ("black"), "borderColor", "BorderColor", RES_TYPE_STRING); + x_default_parameter (f, parms, Qalpha, Qnil, + "alpha", "Alpha", RES_TYPE_NUMBER); - /* Init faces before x_default_parameter is called for scroll-bar - parameters because that function calls x_set_scroll_bar_width, - which calls change_frame_size, which calls Fset_window_buffer, - which runs hooks, which call Fvertical_motion. At the end, we - end up in init_iterator with a null face cache, which should not - happen. */ + /* Init faces before x_default_parameter is called for the + scroll-bar-width parameter because otherwise we end up in + init_iterator with a null face cache, which should not happen. */ init_frame_faces (f); f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED; @@ -5825,9 +5794,10 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, from the current FRAME_LINES (f). */ width = FRAME_COLS (f); height = FRAME_LINES (f); - FRAME_LINES (f) = 0; SET_FRAME_COLS (f, 0); - change_frame_size (f, width, height, 1, 0, 0, 0); + SET_FRAME_LINES (f, 0); + adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), + height * FRAME_LINE_HEIGHT (f), 0, 1); /* Add `tooltip' frame parameter's default value. */ if (NILP (Fframe_parameter (frame, Qtooltip))) @@ -5872,6 +5842,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, below. And the frame needs to be on Vframe_list or making it visible won't work. */ Vframe_list = Fcons (frame, Vframe_list); + f->official = true; /* Setting attributes of faces of the tooltip frame from resources and similar will increment face_change_count, which leads to the @@ -6900,24 +6871,33 @@ operations: specified DOCUMENT. \"find\" - initiate search starting from DOCUMENT, which must specify a directory. + \"delete\" - move DOCUMENT, a file or a directory, to Recycle Bin. + \"copy\" - copy DOCUMENT, which must be a file or a directory, into + the clipboard. + \"cut\" - move DOCUMENT, a file or a directory, into the clipboard. + \"paste\" - paste the file whose name is in the clipboard into DOCUMENT, + which must be a directory. + \"pastelink\" + - create a shortcut in DOCUMENT (which must be a directory) + the file or directory whose name is in the clipboard. \"runas\" - run DOCUMENT, which must be an excutable file, with elevated privileges (a.k.a. \"as Administrator\"). \"properties\" - - open the the property sheet dialog for DOCUMENT; works - for *.lnk desktop shortcuts, and little or nothing else. + - open the property sheet dialog for DOCUMENT. nil - invoke the default OPERATION, or \"open\" if default is not defined or unavailable. DOCUMENT is typically the name of a document file or a URL, but can also be an executable program to run, or a directory to open in the -Windows Explorer. If it is a file, it must be a local one; this -function does not support remote file names. +Windows Explorer. If it is a file or a directory, it must be a local +one; this function does not support remote file names. If DOCUMENT is an executable program, the optional third arg PARAMETERS -can be a string containing command line parameters that will be passed -to the program. Some values of OPERATION also require parameters (e.g., -\"printto\" requires the printer address). Otherwise, PARAMETERS should -be nil or unspecified. +can be a string containing command line parameters, separated by blanks, +that will be passed to the program. Some values of OPERATION also require +parameters (e.g., \"printto\" requires the printer address). Otherwise, +PARAMETERS should be nil or unspecified. Note that double quote characters +in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\". Optional fourth argument SHOW-FLAG can be used to control how the application will be displayed when it is invoked. If SHOW-FLAG is nil @@ -6935,11 +6915,13 @@ a ShowWindow flag: char *errstr; Lisp_Object current_dir = BVAR (current_buffer, directory);; wchar_t *doc_w = NULL, *params_w = NULL, *ops_w = NULL; +#ifdef CYGWIN intptr_t result; -#ifndef CYGWIN +#else int use_unicode = w32_unicode_filenames; char *doc_a = NULL, *params_a = NULL, *ops_a = NULL; Lisp_Object absdoc, handler; + BOOL success; struct gcpro gcpro1; #endif @@ -6967,7 +6949,48 @@ a ShowWindow flag: GUI_SDATA (current_dir), (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT)); + + if (result > 32) + return Qt; + + switch (result) + { + case SE_ERR_ACCESSDENIED: + errstr = w32_strerror (ERROR_ACCESS_DENIED); + break; + case SE_ERR_ASSOCINCOMPLETE: + case SE_ERR_NOASSOC: + errstr = w32_strerror (ERROR_NO_ASSOCIATION); + break; + case SE_ERR_DDEBUSY: + case SE_ERR_DDEFAIL: + errstr = w32_strerror (ERROR_DDE_FAIL); + break; + case SE_ERR_DDETIMEOUT: + errstr = w32_strerror (ERROR_TIMEOUT); + break; + case SE_ERR_DLLNOTFOUND: + errstr = w32_strerror (ERROR_DLL_NOT_FOUND); + break; + case SE_ERR_FNF: + errstr = w32_strerror (ERROR_FILE_NOT_FOUND); + break; + case SE_ERR_OOM: + errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY); + break; + case SE_ERR_PNF: + errstr = w32_strerror (ERROR_PATH_NOT_FOUND); + break; + case SE_ERR_SHARE: + errstr = w32_strerror (ERROR_SHARING_VIOLATION); + break; + default: + errstr = w32_strerror (0); + break; + } + #else /* !CYGWIN */ + current_dir = ENCODE_FILE (current_dir); /* We have a situation here. If DOCUMENT is a relative file name, but its name includes leading directories, i.e. it lives not in @@ -6997,6 +7020,7 @@ a ShowWindow flag: if (use_unicode) { wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH]; + SHELLEXECUTEINFOW shexinfo_w; /* Encode filename, current directory and parameters, and convert operation to UTF-16. */ @@ -7030,14 +7054,28 @@ a ShowWindow flag: *d++ = *s++; *d = 0; } - result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w, - current_dir_w, - (INTEGERP (show_flag) - ? XINT (show_flag) : SW_SHOWDEFAULT)); + + /* Using ShellExecuteEx and setting the SEE_MASK_INVOKEIDLIST + flag succeeds with more OPERATIONs (a.k.a. "verbs"), as it is + able to invoke verbs from shortcut menu extensions, not just + static verbs listed in the Registry. */ + memset (&shexinfo_w, 0, sizeof (shexinfo_w)); + shexinfo_w.cbSize = sizeof (shexinfo_w); + shexinfo_w.fMask = + SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; + shexinfo_w.hwnd = NULL; + shexinfo_w.lpVerb = ops_w; + shexinfo_w.lpFile = doc_w; + shexinfo_w.lpParameters = params_w; + shexinfo_w.lpDirectory = current_dir_w; + shexinfo_w.nShow = + (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT); + success = ShellExecuteExW (&shexinfo_w); } else { char document_a[MAX_PATH], current_dir_a[MAX_PATH]; + SHELLEXECUTEINFOA shexinfo_a; filename_to_ansi (SSDATA (current_dir), current_dir_a); filename_to_ansi (SSDATA (document), document_a); @@ -7052,51 +7090,27 @@ a ShowWindow flag: /* Assume OPERATION is pure ASCII. */ ops_a = SSDATA (operation); } - result = (intptr_t) ShellExecuteA (NULL, ops_a, doc_a, params_a, - current_dir_a, - (INTEGERP (show_flag) - ? XINT (show_flag) : SW_SHOWDEFAULT)); + memset (&shexinfo_a, 0, sizeof (shexinfo_a)); + shexinfo_a.cbSize = sizeof (shexinfo_a); + shexinfo_a.fMask = + SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; + shexinfo_a.hwnd = NULL; + shexinfo_a.lpVerb = ops_a; + shexinfo_a.lpFile = doc_a; + shexinfo_a.lpParameters = params_a; + shexinfo_a.lpDirectory = current_dir_a; + shexinfo_a.nShow = + (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT); + success = ShellExecuteExA (&shexinfo_a); } -#endif /* !CYGWIN */ - if (result > 32) + if (success) return Qt; - switch (result) - { - case SE_ERR_ACCESSDENIED: - errstr = w32_strerror (ERROR_ACCESS_DENIED); - break; - case SE_ERR_ASSOCINCOMPLETE: - case SE_ERR_NOASSOC: - errstr = w32_strerror (ERROR_NO_ASSOCIATION); - break; - case SE_ERR_DDEBUSY: - case SE_ERR_DDEFAIL: - errstr = w32_strerror (ERROR_DDE_FAIL); - break; - case SE_ERR_DDETIMEOUT: - errstr = w32_strerror (ERROR_TIMEOUT); - break; - case SE_ERR_DLLNOTFOUND: - errstr = w32_strerror (ERROR_DLL_NOT_FOUND); - break; - case SE_ERR_FNF: - errstr = w32_strerror (ERROR_FILE_NOT_FOUND); - break; - case SE_ERR_OOM: - errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY); - break; - case SE_ERR_PNF: - errstr = w32_strerror (ERROR_PATH_NOT_FOUND); - break; - case SE_ERR_SHARE: - errstr = w32_strerror (ERROR_SHARING_VIOLATION); - break; - default: - errstr = w32_strerror (0); - break; - } + errstr = w32_strerror (0); + +#endif /* !CYGWIN */ + /* The error string might be encoded in the locale's encoding. */ if (!NILP (Vlocale_coding_system)) { @@ -7516,8 +7530,8 @@ If the underlying system call fails, value is nil. */) (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = GetProcAddress (hKernel, "GetDiskFreeSpaceExA"); bool have_pfn_GetDiskFreeSpaceEx = - (w32_unicode_filenames && pfn_GetDiskFreeSpaceExW - || !w32_unicode_filenames && pfn_GetDiskFreeSpaceExA); + ((w32_unicode_filenames && pfn_GetDiskFreeSpaceExW) + || (!w32_unicode_filenames && pfn_GetDiskFreeSpaceExA)); /* On Windows, we may need to specify the root directory of the volume holding FILENAME. */ @@ -8039,17 +8053,19 @@ frame_parm_handler w32_frame_parm_handlers[] = x_set_mouse_color, x_explicitly_set_name, x_set_scroll_bar_width, + x_set_scroll_bar_height, x_set_title, x_set_unsplittable, x_set_vertical_scroll_bars, + x_set_horizontal_scroll_bars, x_set_visibility, x_set_tool_bar_lines, 0, /* x_set_scroll_bar_foreground, */ 0, /* x_set_scroll_bar_background, */ x_set_screen_gamma, x_set_line_spacing, - x_set_fringe_width, - x_set_fringe_width, + x_set_left_fringe, + x_set_right_fringe, 0, /* x_set_wait_for_wm, */ x_set_fullscreen, x_set_font_backend, @@ -8066,7 +8082,6 @@ syms_of_w32fns (void) w32_visible_system_caret_hwnd = NULL; - DEFSYM (Qsuppress_icon, "suppress-icon"); DEFSYM (Qundefined_color, "undefined-color"); DEFSYM (Qcancel_timer, "cancel-timer"); DEFSYM (Qhyper, "hyper"); @@ -8081,8 +8096,6 @@ syms_of_w32fns (void) DEFSYM (Qworkarea, "workarea"); DEFSYM (Qmm_size, "mm-size"); DEFSYM (Qframes, "frames"); - /* This is the end of symbol initialization. */ - Fput (Qundefined_color, Qerror_conditions, listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); @@ -8394,9 +8407,6 @@ only be necessary if the default setting causes problems. */); #endif defsubr (&Sset_message_beep); - - hourglass_hwnd = NULL; - defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); tip_timer = Qnil; diff --git a/src/w32font.c b/src/w32font.c index 5262f38663f..895931843ba 100644 --- a/src/w32font.c +++ b/src/w32font.c @@ -115,15 +115,15 @@ static void compute_metrics (HDC, struct w32font_info *, unsigned int, static Lisp_Object w32_registry (LONG, DWORD); /* EnumFontFamiliesEx callbacks. */ -static int CALLBACK add_font_entity_to_list (ENUMLOGFONTEX *, - NEWTEXTMETRICEX *, - DWORD, LPARAM); -static int CALLBACK add_one_font_entity_to_list (ENUMLOGFONTEX *, - NEWTEXTMETRICEX *, - DWORD, LPARAM); -static int CALLBACK add_font_name_to_list (ENUMLOGFONTEX *, - NEWTEXTMETRICEX *, - DWORD, LPARAM); +static int CALLBACK ALIGN_STACK add_font_entity_to_list (ENUMLOGFONTEX *, + NEWTEXTMETRICEX *, + DWORD, LPARAM); +static int CALLBACK ALIGN_STACK add_one_font_entity_to_list (ENUMLOGFONTEX *, + NEWTEXTMETRICEX *, + DWORD, LPARAM); +static int CALLBACK ALIGN_STACK add_font_name_to_list (ENUMLOGFONTEX *, + NEWTEXTMETRICEX *, + DWORD, LPARAM); /* struct passed in as LPARAM arg to EnumFontFamiliesEx, for keeping track of what we really want. */ @@ -287,11 +287,11 @@ Lisp_Object intern_font_name (char * string) { Lisp_Object str = DECODE_SYSTEM (build_string (string)); - int len = SCHARS (str); + ptrdiff_t len = SCHARS (str); Lisp_Object obarray = check_obarray (Vobarray); Lisp_Object tem = oblookup (obarray, SDATA (str), len, len); /* This code is similar to intern function from lread.c. */ - return SYMBOLP (tem) ? tem : Fintern (str, obarray); + return SYMBOLP (tem) ? tem : intern_driver (str, obarray, XINT (tem)); } /* w32 implementation of get_cache for font backend. @@ -473,7 +473,7 @@ w32font_encode_char (struct font *font, int c) of METRICS. The glyphs are specified by their glyph codes in CODE (length NGLYPHS). Apparently metrics can be NULL, in this case just return the overall width. */ -int +void w32font_text_extents (struct font *font, unsigned *code, int nglyphs, struct font_metrics *metrics) { @@ -487,84 +487,80 @@ w32font_text_extents (struct font *font, unsigned *code, struct w32font_info *w32_font = (struct w32font_info *) font; - if (metrics) - { - memset (metrics, 0, sizeof (struct font_metrics)); - metrics->ascent = font->ascent; - metrics->descent = font->descent; + memset (metrics, 0, sizeof (struct font_metrics)); + metrics->ascent = font->ascent; + metrics->descent = font->descent; - for (i = 0; i < nglyphs; i++) - { - struct w32_metric_cache *char_metric; - int block = *(code + i) / CACHE_BLOCKSIZE; - int pos_in_block = *(code + i) % CACHE_BLOCKSIZE; - - if (block >= w32_font->n_cache_blocks) - { - if (!w32_font->cached_metrics) - w32_font->cached_metrics - = xmalloc ((block + 1) - * sizeof (struct w32_metric_cache *)); - else - w32_font->cached_metrics - = xrealloc (w32_font->cached_metrics, - (block + 1) - * sizeof (struct w32_metric_cache *)); - memset (w32_font->cached_metrics + w32_font->n_cache_blocks, 0, - ((block + 1 - w32_font->n_cache_blocks) - * sizeof (struct w32_metric_cache *))); - w32_font->n_cache_blocks = block + 1; - } + for (i = 0; i < nglyphs; i++) + { + struct w32_metric_cache *char_metric; + int block = *(code + i) / CACHE_BLOCKSIZE; + int pos_in_block = *(code + i) % CACHE_BLOCKSIZE; - if (!w32_font->cached_metrics[block]) - { - w32_font->cached_metrics[block] - = xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache)); - } + if (block >= w32_font->n_cache_blocks) + { + if (!w32_font->cached_metrics) + w32_font->cached_metrics + = xmalloc ((block + 1) + * sizeof (struct w32_metric_cache *)); + else + w32_font->cached_metrics + = xrealloc (w32_font->cached_metrics, + (block + 1) + * sizeof (struct w32_metric_cache *)); + memset (w32_font->cached_metrics + w32_font->n_cache_blocks, 0, + ((block + 1 - w32_font->n_cache_blocks) + * sizeof (struct w32_metric_cache *))); + w32_font->n_cache_blocks = block + 1; + } - char_metric = w32_font->cached_metrics[block] + pos_in_block; + if (!w32_font->cached_metrics[block]) + { + w32_font->cached_metrics[block] + = xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache)); + } - if (char_metric->status == W32METRIC_NO_ATTEMPT) - { - if (dc == NULL) - { - /* TODO: Frames can come and go, and their fonts - outlive them. So we can't cache the frame in the - font structure. Use selected_frame until the API - is updated to pass in a frame. */ - f = XFRAME (selected_frame); - - dc = get_frame_dc (f); - old_font = SelectObject (dc, w32_font->hfont); - } - compute_metrics (dc, w32_font, *(code + i), char_metric); - } + char_metric = w32_font->cached_metrics[block] + pos_in_block; - if (char_metric->status == W32METRIC_SUCCESS) + if (char_metric->status == W32METRIC_NO_ATTEMPT) + { + if (dc == NULL) { - metrics->lbearing = min (metrics->lbearing, - metrics->width + char_metric->lbearing); - metrics->rbearing = max (metrics->rbearing, - metrics->width + char_metric->rbearing); - metrics->width += char_metric->width; + /* TODO: Frames can come and go, and their fonts + outlive them. So we can't cache the frame in the + font structure. Use selected_frame until the API + is updated to pass in a frame. */ + f = XFRAME (selected_frame); + + dc = get_frame_dc (f); + old_font = SelectObject (dc, w32_font->hfont); } - else - /* If we couldn't get metrics for a char, - use alternative method. */ - break; + compute_metrics (dc, w32_font, *(code + i), char_metric); } - /* If we got through everything, return. */ - if (i == nglyphs) - { - if (dc != NULL) - { - /* Restore state and release DC. */ - SelectObject (dc, old_font); - release_frame_dc (f, dc); - } - return metrics->width; - } + if (char_metric->status == W32METRIC_SUCCESS) + { + metrics->lbearing = min (metrics->lbearing, + metrics->width + char_metric->lbearing); + metrics->rbearing = max (metrics->rbearing, + metrics->width + char_metric->rbearing); + metrics->width += char_metric->width; + } + else + /* If we couldn't get metrics for a char, + use alternative method. */ + break; + } + /* If we got through everything, return. */ + if (i == nglyphs) + { + if (dc != NULL) + { + /* Restore state and release DC. */ + SelectObject (dc, old_font); + release_frame_dc (f, dc); + } + return; } /* For non-truetype fonts, GetGlyphOutlineW is not supported, so @@ -620,18 +616,13 @@ w32font_text_extents (struct font *font, unsigned *code, } /* Give our best estimate of the metrics, based on what we know. */ - if (metrics) - { - metrics->width = total_width - w32_font->metrics.tmOverhang; - metrics->lbearing = 0; - metrics->rbearing = total_width; - } + metrics->width = total_width - w32_font->metrics.tmOverhang; + metrics->lbearing = 0; + metrics->rbearing = total_width; /* Restore state and release DC. */ SelectObject (dc, old_font); release_frame_dc (f, dc); - - return total_width; } /* w32 implementation of draw for font backend. @@ -757,19 +748,6 @@ w32font_get_bitmap (struct font *font, unsigned code, static void w32font_free_bitmap (struct font *font, struct font_bitmap *bitmap); */ -/* w32 implementation of get_outline for font backend. - Optional. - Return an outline data for glyph-code CODE of FONT. The format - of the outline data depends on the font-driver. -static void * -w32font_get_outline (struct font *font, unsigned code); - */ -/* w32 implementation of free_outline for font backend. - Optional. - Free OUTLINE (that is obtained by the above method). -static void -w32font_free_outline (struct font *font, void *outline); - */ /* w32 implementation of anchor_point for font backend. Optional. Get coordinates of the INDEXth anchor point of the glyph whose @@ -899,7 +877,7 @@ w32font_open_internal (struct frame *f, Lisp_Object font_entity, LOGFONT logfont; HDC dc; HFONT hfont, old_font; - Lisp_Object val, extra; + Lisp_Object val; struct w32font_info *w32_font; struct font * font; OUTLINETEXTMETRICW* metrics = NULL; @@ -992,21 +970,6 @@ w32font_open_internal (struct frame *f, Lisp_Object font_entity, font->default_ascent = w32_font->metrics.tmAscent; font->pixel_size = size; font->driver = &w32font_driver; - /* Use format cached during list, as the information we have access to - here is incomplete. */ - extra = AREF (font_entity, FONT_EXTRA_INDEX); - if (CONSP (extra)) - { - val = assq_no_quit (QCformat, extra); - if (CONSP (val)) - font->props[FONT_FORMAT_INDEX] = XCDR (val); - else - font->props[FONT_FORMAT_INDEX] = Qunknown; - } - else - font->props[FONT_FORMAT_INDEX] = Qunknown; - - font->props[FONT_FILE_INDEX] = Qnil; font->encoding_charset = -1; font->repertory_charset = -1; /* TODO: do we really want the minimum width here, which could be negative? */ @@ -1037,7 +1000,7 @@ w32font_open_internal (struct frame *f, Lisp_Object font_entity, /* Callback function for EnumFontFamiliesEx. * Adds the name of a font to a Lisp list (passed in as the lParam arg). */ -static int CALLBACK +static int CALLBACK ALIGN_STACK add_font_name_to_list (ENUMLOGFONTEX *logical_font, NEWTEXTMETRICEX *physical_font, DWORD font_type, LPARAM list_object) @@ -1483,7 +1446,7 @@ check_face_name (LOGFONT *font, char *full_name) * and if so, adds it to a list. Both the data we are checking against * and the list to which the fonts are added are passed in via the * lparam argument, in the form of a font_callback_data struct. */ -static int CALLBACK +static int CALLBACK ALIGN_STACK add_font_entity_to_list (ENUMLOGFONTEX *logical_font, NEWTEXTMETRICEX *physical_font, DWORD font_type, LPARAM lParam) @@ -1602,7 +1565,7 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font, /* Callback function for EnumFontFamiliesEx. * Terminates the search once we have a match. */ -static int CALLBACK +static int CALLBACK ALIGN_STACK add_one_font_entity_to_list (ENUMLOGFONTEX *logical_font, NEWTEXTMETRICEX *physical_font, DWORD font_type, LPARAM lParam) @@ -2557,8 +2520,6 @@ struct font_driver w32font_driver = w32font_draw, NULL, /* get_bitmap */ NULL, /* free_bitmap */ - NULL, /* get_outline */ - NULL, /* free_outline */ NULL, /* anchor_point */ NULL, /* otf_capability */ NULL, /* otf_drive */ diff --git a/src/w32font.h b/src/w32font.h index 1be49bb91c2..5ce3ac7a5f9 100644 --- a/src/w32font.h +++ b/src/w32font.h @@ -74,8 +74,8 @@ int w32font_open_internal (struct frame *f, Lisp_Object font_entity, int pixel_size, Lisp_Object font_object); void w32font_close (struct font *font); int w32font_has_char (Lisp_Object entity, int c); -int w32font_text_extents (struct font *font, unsigned *code, int nglyphs, - struct font_metrics *metrics); +void w32font_text_extents (struct font *font, unsigned *code, int nglyphs, + struct font_metrics *metrics); int w32font_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background); diff --git a/src/w32gui.h b/src/w32gui.h index b8c8557357a..d04ce625d1d 100644 --- a/src/w32gui.h +++ b/src/w32gui.h @@ -22,14 +22,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "systime.h" /* for Time */ -/* Local memory management for menus. */ +/* FIXME: old local memory management for menus. */ #define local_heap (GetProcessHeap ()) #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n))) #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p)))) -#define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value))) -#define free_widget_value(wv) (local_free ((wv))) - /* Emulate X GC's by keeping color and font info in a structure. */ typedef struct _XGCValues { diff --git a/src/w32heap.c b/src/w32heap.c index 8ab2f58c6e7..c431b87e0c2 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -1,256 +1,701 @@ -/* Heap management routines for GNU Emacs on the Microsoft Windows API. - Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc. +/* Heap management routines for GNU Emacs on the Microsoft Windows + API. Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc. -This file is part of GNU Emacs. + This file is part of GNU Emacs. -GNU Emacs is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + GNU Emacs is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GNU Emacs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public License + along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* - Geoff Voelker (voelker@cs.washington.edu) 7-29-94 + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ +/* + Heavily modified by Fabrice Popineau (fabrice.popineau@gmail.com) 28-02-2014 +*/ + +/* + Memory allocation scheme for w32/w64: + + - Buffers are mmap'ed using a very simple emulation of mmap/munmap + - During the temacs phase: + * we use a private heap declared to be stored into the `dumped_data' + * unfortunately, this heap cannot be made growable, so the size of + blocks it can allocate is limited to (0x80000 - pagesize) + * the blocks that are larger than this are allocated from the end + of the `dumped_data' array; there are not so many of them. + We use a very simple first-fit scheme to reuse those blocks. + * we check that the private heap does not cross the area used + by the bigger chunks. + - During the emacs phase: + * we create a private heap for new memory blocks + * we make sure that we never free a block that has been dumped. + Freeing a dumped block could work in principle, but may prove + unreliable if we distribute binaries of emacs.exe: MS does not + guarantee that the heap data structures are the same across all + versions of their OS, even though the API is available since XP. */ + #include <config.h> #include <stdio.h> +#include <errno.h> +#include <sys/mman.h> #include "w32common.h" #include "w32heap.h" #include "lisp.h" /* for VALMASK */ -#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD_PTR)(rva) + (DWORD_PTR)GetModuleHandle (NULL))) - -/* Emulate getpagesize. */ -int -getpagesize (void) -{ - return sysinfo_cache.dwPageSize; -} +/* We chose to leave those declarations here. They are used only in + this file. The RtlCreateHeap is available since XP. It is located + in ntdll.dll and is available with the DDK. People often + complained that HeapCreate doesn't offer the ability to create a + heap at a given place, which we need here, and which RtlCreateHeap + provides. We reproduce here the definitions available with the + DDK. */ + +typedef PVOID (WINAPI * RtlCreateHeap_Proc) ( + /* _In_ */ ULONG Flags, + /* _In_opt_ */ PVOID HeapBase, + /* _In_opt_ */ SIZE_T ReserveSize, + /* _In_opt_ */ SIZE_T CommitSize, + /* _In_opt_ */ PVOID Lock, + /* _In_opt_ */ PVOID Parameters + ); + +typedef LONG NTSTATUS; + +typedef NTSTATUS +(NTAPI * PRTL_HEAP_COMMIT_ROUTINE)( + IN PVOID Base, + IN OUT PVOID *CommitAddress, + IN OUT PSIZE_T CommitSize + ); + +typedef struct _RTL_HEAP_PARAMETERS { + ULONG Length; + SIZE_T SegmentReserve; + SIZE_T SegmentCommit; + SIZE_T DeCommitFreeBlockThreshold; + SIZE_T DeCommitTotalFreeThreshold; + SIZE_T MaximumAllocationSize; + SIZE_T VirtualMemoryThreshold; + SIZE_T InitialCommit; + SIZE_T InitialReserve; + PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; + SIZE_T Reserved[ 2 ]; +} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; + +/* We reserve space for dumping emacs lisp byte-code inside a static + array. By storing it in an array, the generic mechanism in + unexecw32.c will be able to dump it without the need to add a + special segment to the executable. In order to be able to do this + without losing too much space, we need to create a Windows heap at + the specific address of the static array. The RtlCreateHeap + available inside the NT kernel since XP will do this. It allows to + create a non-growable heap at a specific address. So before + dumping, we create a non-growable heap at the address of the + dumped_data[] array. After dumping, we reuse memory allocated + there without being able to free it (but most of it is not meant to + be freed anyway), and we use a new private heap for all new + allocations. */ + +/* FIXME: Most of the space reserved for dumped_data[] is only used by + the 1st bootstrap-emacs.exe built while bootstrapping. Once the + preloaded Lisp files are byte-compiled, the next loadup uses less + than half of the size stated below. It would be nice to find a way + to build only the first bootstrap-emacs.exe with the large size, + and reset that to a lower value afterwards. */ +#ifdef _WIN64 +# define DUMPED_HEAP_SIZE (18*1024*1024) +#else +# define DUMPED_HEAP_SIZE (11*1024*1024) +#endif -/* Info for managing our preload heap, which is essentially a fixed size - data area in the executable. */ -PIMAGE_SECTION_HEADER preload_heap_section; +static unsigned char dumped_data[DUMPED_HEAP_SIZE]; -/* Info for keeping track of our heap. */ +/* Info for keeping track of our dynamic heap used after dumping. */ unsigned char *data_region_base = NULL; unsigned char *data_region_end = NULL; -unsigned char *real_data_region_end = NULL; -size_t reserved_heap_size = 0; +static DWORD_PTR committed = 0; -/* The start of the data segment. */ -unsigned char * -get_data_start (void) -{ - return data_region_base; -} +/* The maximum block size that can be handled by a non-growable w32 + heap is limited by the MaxBlockSize value below. + + This point deserves and explanation. + + The W32 heap allocator can be used for a growable + heap or a non-growable one. + + A growable heap is not compatible with a fixed base address for the + heap. Only a non-growable one is. One drawback of non-growable + heaps is that they can hold only objects smaller than a certain + size (the one defined below). Most of the largest blocks are GC'ed + before dumping. In any case and to be safe, we implement a simple + first-fit allocation algorithm starting at the end of the + dumped_data[] array like depicted below: + + ---------------------------------------------- + | | | | + | Private heap |-> <-| Big chunks | + | | | | + ---------------------------------------------- + ^ ^ ^ + dumped_data dumped_data bc_limit + + committed -/* The end of the data segment. */ -unsigned char * -get_data_end (void) +*/ + +/* Info for managing our preload heap, which is essentially a fixed size + data area in the executable. */ +#define PAGE_SIZE 0x1000 +#define MaxBlockSize (0x80000 - PAGE_SIZE) + +#define MAX_BLOCKS 0x40 + +static struct { - return data_region_end; -} + unsigned char *address; + size_t size; + DWORD occupied; +} blocks[MAX_BLOCKS]; + +static DWORD blocks_number = 0; +static unsigned char *bc_limit; + +/* Handle for the private heap: + - inside the dumped_data[] array before dump, + - outside of it after dump. +*/ +HANDLE heap = NULL; -#if !USE_LSB_TAG -static char * -allocate_heap (void) +/* We redirect the standard allocation functions. */ +malloc_fn the_malloc_fn; +realloc_fn the_realloc_fn; +free_fn the_free_fn; + +/* It doesn't seem to be useful to allocate from a file mapping. + It would be if the memory was shared. + http://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */ + +/* This is the function to commit memory when the heap allocator + claims for new memory. Before dumping, we allocate space + from the fixed size dumped_data[] array. +*/ +NTSTATUS NTAPI +dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize) { - /* Try to get as much as possible of the address range from the end of - the preload heap section up to the usable address limit. Since GNU - malloc can handle gaps in the memory it gets from sbrk, we can - simply set the sbrk pointer to the base of the new heap region. */ - DWORD_PTR base = - ROUND_UP ((RVA_TO_PTR (preload_heap_section->VirtualAddress) - + preload_heap_section->Misc.VirtualSize), - get_allocation_unit ()); - DWORD_PTR end = ((unsigned __int64)1) << VALBITS; /* 256MB */ - void *ptr = NULL; - - while (!ptr && (base < end)) + /* This is used before dumping. + + The private heap is stored at dumped_data[] address. + We commit contiguous areas of the dumped_data array + as requests arrive. */ + *CommitAddress = data_region_base + committed; + committed += *CommitSize; + /* Check that the private heap area does not overlap the big chunks area. */ + if (((unsigned char *)(*CommitAddress)) + *CommitSize >= bc_limit) { -#ifdef _WIN64 - reserved_heap_size = min(end - base, 0x4000000000ull); /* Limit to 256Gb */ -#else - reserved_heap_size = end - base; -#endif - ptr = VirtualAlloc ((void *) base, - get_reserved_heap_size (), - MEM_RESERVE, - PAGE_NOACCESS); - base += 0x00100000; /* 1MB increment */ + fprintf (stderr, + "dumped_data_commit: memory exhausted.\nEnlarge dumped_data[]!\n"); + exit (-1); } - - return ptr; + return 0; } -#else /* USE_LSB_TAG */ -static char * -allocate_heap (void) + +/* Heap creation. */ + +/* We want to turn on Low Fragmentation Heap for XP and older systems. + MinGW32 lacks those definitions. */ +#ifndef _W64 +typedef enum _HEAP_INFORMATION_CLASS { + HeapCompatibilityInformation +} HEAP_INFORMATION_CLASS; + +typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T); +#endif + +void +init_heap (void) { -#ifdef _WIN64 - size_t size = 0x4000000000ull; /* start by asking for 32GB */ -#else - /* We used to start with 2GB here, but on Windows 7 that would leave - too little room in the address space for threads started by - Windows on our behalf, e.g. when we pop up the file selection - dialog. */ - size_t size = 0x68000000; /* start by asking for 1.7GB */ + if (using_dynamic_heap) + { + unsigned long enable_lfh = 2; + + /* After dumping, use a new private heap. We explicitly enable + the low fragmentation heap (LFH) here, for the sake of pre + Vista versions. Note: this will harmlessly fail on Vista and + later, where the low-fragmentation heap is enabled by + default. It will also fail on pre-Vista versions when Emacs + is run under a debugger; set _NO_DEBUG_HEAP=1 in the + environment before starting GDB to get low fragmentation heap + on XP and older systems, for the price of losing "certain + heap debug options"; for the details see + http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */ + data_region_end = data_region_base; + + /* Create the private heap. */ + heap = HeapCreate (0, 0, 0); + +#ifndef _W64 + /* Set the low-fragmentation heap for OS before Vista. */ + HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll"); + HeapSetInformation_Proc s_pfn_Heap_Set_Information = (HeapSetInformation_Proc) GetProcAddress (hm_kernel32dll, "HeapSetInformation"); + if (s_pfn_Heap_Set_Information != NULL) + { + if (s_pfn_Heap_Set_Information ((PVOID) heap, + HeapCompatibilityInformation, + &enable_lfh, sizeof(enable_lfh)) == 0) + DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n", + GetLastError ())); + } #endif - void *ptr = NULL; - while (!ptr && size > 0x00100000) + the_malloc_fn = malloc_after_dump; + the_realloc_fn = realloc_after_dump; + the_free_fn = free_after_dump; + } + else { - reserved_heap_size = size; - ptr = VirtualAlloc (NULL, - get_reserved_heap_size (), - MEM_RESERVE, - PAGE_NOACCESS); - size -= 0x00800000; /* if failed, decrease request by 8MB */ + /* Find the RtlCreateHeap function. Headers for this function + are provided with the w32 ddk, but the function is available + in ntdll.dll since XP. */ + HMODULE hm_ntdll = LoadLibrary ("ntdll.dll"); + RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap + = (RtlCreateHeap_Proc) GetProcAddress (hm_ntdll, "RtlCreateHeap"); + /* Specific parameters for the private heap. */ + RTL_HEAP_PARAMETERS params; + ZeroMemory (¶ms, sizeof(params)); + params.Length = sizeof(RTL_HEAP_PARAMETERS); + + data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000); + data_region_end = bc_limit = dumped_data + DUMPED_HEAP_SIZE; + + params.InitialCommit = committed = 0x1000; + params.InitialReserve = sizeof(dumped_data); + /* Use our own routine to commit memory from the dumped_data + array. */ + params.CommitRoutine = &dumped_data_commit; + + /* Create the private heap. */ + if (s_pfn_Rtl_Create_Heap == NULL) + { + fprintf (stderr, "Cannot build Emacs without RtlCreateHeap being available; exiting.\n"); + exit (-1); + } + heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, ¶ms); + the_malloc_fn = malloc_before_dump; + the_realloc_fn = realloc_before_dump; + the_free_fn = free_before_dump; } - return ptr; + /* Update system version information to match current system. */ + cache_system_info (); } -#endif /* USE_LSB_TAG */ +#undef malloc +#undef realloc +#undef free + +/* FREEABLE_P checks if the block can be safely freed. */ +#define FREEABLE_P(addr) \ + ((unsigned char *)(addr) < dumped_data \ + || (unsigned char *)(addr) >= dumped_data + DUMPED_HEAP_SIZE) -/* Emulate Unix sbrk. Note that ralloc.c expects the return value to - be the address of the _start_ (not end) of the new block in case of - success, and zero (not -1) in case of failure. */ void * -sbrk (ptrdiff_t increment) +malloc_after_dump (size_t size) { - void *result; - ptrdiff_t size = increment; + /* Use the new private heap. */ + void *p = HeapAlloc (heap, 0, size); + + /* After dump, keep track of the "brk value" for sbrk(0). */ + if (p) + { + unsigned char *new_brk = (unsigned char *)p + size; + + if (new_brk > data_region_end) + data_region_end = new_brk; + } + else + errno = ENOMEM; + return p; +} - result = data_region_end; +void * +malloc_before_dump (size_t size) +{ + void *p; - /* If size is negative, shrink the heap by decommitting pages. */ - if (size < 0) + /* Before dumping. The private heap can handle only requests for + less than MaxBlockSize. */ + if (size < MaxBlockSize) + { + /* Use the private heap if possible. */ + p = HeapAlloc (heap, 0, size); + if (!p) + errno = ENOMEM; + } + else { - ptrdiff_t new_size; - unsigned char *new_data_region_end; - - size = -size; - - /* Sanity checks. */ - if ((data_region_end - size) < data_region_base) - return NULL; - - /* We can only decommit full pages, so allow for - partial deallocation [cga]. */ - new_data_region_end = (data_region_end - size); - new_data_region_end = (unsigned char *) - ((DWORD_PTR) (new_data_region_end + syspage_mask) & ~syspage_mask); - new_size = real_data_region_end - new_data_region_end; - real_data_region_end = new_data_region_end; - if (new_size > 0) + /* Find the first big chunk that can hold the requested size. */ + int i = 0; + + for (i = 0; i < blocks_number; i++) + { + if (blocks[i].occupied == 0 && blocks[i].size >= size) + break; + } + if (i < blocks_number) { - /* Decommit size bytes from the end of the heap. */ - if (using_dynamic_heap - && !VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT)) - return NULL; - } + /* If found, use it. */ + p = blocks[i].address; + blocks[i].occupied = TRUE; + } + else + { + /* Allocate a new big chunk from the end of the dumped_data + array. */ + if (blocks_number >= MAX_BLOCKS) + { + fprintf (stderr, + "malloc_before_dump: no more big chunks available.\nEnlarge MAX_BLOCKS!\n"); + exit (-1); + } + bc_limit -= size; + bc_limit = (unsigned char *)ROUND_DOWN (bc_limit, 0x10); + p = bc_limit; + blocks[blocks_number].address = p; + blocks[blocks_number].size = size; + blocks[blocks_number].occupied = TRUE; + blocks_number++; + /* Check that areas do not overlap. */ + if (bc_limit < dumped_data + committed) + { + fprintf (stderr, + "malloc_before_dump: memory exhausted.\nEnlarge dumped_data[]!\n"); + exit (-1); + } + } + } + return p; +} - data_region_end -= size; +/* Re-allocate the previously allocated block in ptr, making the new + block SIZE bytes long. */ +void * +realloc_after_dump (void *ptr, size_t size) +{ + void *p; + + /* After dumping. */ + if (FREEABLE_P (ptr)) + { + /* Reallocate the block since it lies in the new heap. */ + p = HeapReAlloc (heap, 0, ptr, size); + if (!p) + errno = ENOMEM; } - /* If size is positive, grow the heap by committing reserved pages. */ - else if (size > 0) + else { - /* Sanity checks. */ - if ((data_region_end + size) > - (data_region_base + get_reserved_heap_size ())) - return NULL; - - /* Commit more of our heap. */ - if (using_dynamic_heap - && VirtualAlloc (data_region_end, size, MEM_COMMIT, - PAGE_READWRITE) == NULL) - return NULL; - data_region_end += size; - - /* We really only commit full pages, so record where - the real end of committed memory is [cga]. */ - real_data_region_end = (unsigned char *) - ((DWORD_PTR) (data_region_end + syspage_mask) & ~syspage_mask); + /* If the block lies in the dumped data, do not free it. Only + allocate a new one. */ + p = HeapAlloc (heap, 0, size); + if (p) + CopyMemory (p, ptr, size); + else + errno = ENOMEM; } + /* After dump, keep track of the "brk value" for sbrk(0). */ + if (p) + { + unsigned char *new_brk = (unsigned char *)p + size; - return result; + if (new_brk > data_region_end) + data_region_end = new_brk; + } + return p; } -/* Initialize the internal heap variables used by sbrk. When running in - preload phase (ie. in the undumped executable), we rely entirely on a - fixed size heap section included in the .exe itself; this is - preserved during dumping, and truncated to the size actually used. - - When running in the dumped executable, we reserve as much as possible - of the address range that is addressable by Lisp object pointers, to - supplement what is left of the preload heap. Although we cannot rely - on the dynamically allocated arena being contiguous with the static - heap area, it is not a problem because sbrk can pretend that the gap - was allocated by something else; GNU malloc detects when there is a - jump in the sbrk values, and starts a new heap block. */ -void -init_heap (void) +void * +realloc_before_dump (void *ptr, size_t size) { - PIMAGE_DOS_HEADER dos_header; - PIMAGE_NT_HEADERS nt_header; - - dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0); - nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) + - dos_header->e_lfanew); - preload_heap_section = find_section ("EMHEAP", nt_header); + void *p; - if (using_dynamic_heap) + /* Before dumping. */ + if (dumped_data < (unsigned char *)ptr + && (unsigned char *)ptr < bc_limit && size <= MaxBlockSize) { - data_region_base = allocate_heap (); - if (!data_region_base) + p = HeapReAlloc (heap, 0, ptr, size); + if (!p) + errno = ENOMEM; + } + else + { + /* In this case, either the new block is too large for the heap, + or the old block was already too large. In both cases, + malloc_before_dump() and free_before_dump() will take care of + reallocation. */ + p = malloc_before_dump (size); + /* If SIZE is below MaxBlockSize, malloc_before_dump will try to + allocate it in the fixed heap. If that fails, we could have + kept the block in its original place, above bc_limit, instead + of failing the call as below. But this doesn't seem to be + worth the added complexity, as loadup allocates only a very + small number of large blocks, and never reallocates them. */ + if (p) { - printf ("Error: Could not reserve dynamic heap area.\n"); - exit (1); + CopyMemory (p, ptr, size); + free_before_dump (ptr); } + } + return p; +} -#if !USE_LSB_TAG - /* Ensure that the addresses don't use the upper tag bits since - the Lisp type goes there. */ - if (((DWORD_PTR) data_region_base & ~VALMASK) != 0) +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +void +free_after_dump (void *ptr) +{ + /* After dumping. */ + if (FREEABLE_P (ptr)) + { + /* Free the block if it is in the new private heap. */ + HeapFree (heap, 0, ptr); + } +} + +void +free_before_dump (void *ptr) +{ + /* Before dumping. */ + if (dumped_data < (unsigned char *)ptr + && (unsigned char *)ptr < bc_limit) + { + /* Free the block if it is allocated in the private heap. */ + HeapFree (heap, 0, ptr); + } + else + { + /* Look for the big chunk. */ + int i; + + for (i = 0; i < blocks_number; i++) { - printf ("Error: The heap was allocated in upper memory.\n"); - exit (1); + if (blocks[i].address == ptr) + { + /* Reset block occupation if found. */ + blocks[i].occupied = 0; + break; + } + /* What if the block is not found? We should trigger an + error here. */ + eassert (i < blocks_number); } + } +} + +#ifdef ENABLE_CHECKING +void +report_temacs_memory_usage (void) +{ + DWORD blocks_used = 0; + size_t large_mem_used = 0; + int i; + + for (i = 0; i < blocks_number; i++) + if (blocks[i].occupied) + { + blocks_used++; + large_mem_used += blocks[i].size; + } + + /* Emulate 'message', which writes to stderr in non-interactive + sessions. */ + fprintf (stderr, + "Dump memory usage: Heap: %" PRIu64 " Large blocks(%lu/%lu): %" PRIu64 "/%" PRIu64 "\n", + (unsigned long long)committed, blocks_used, blocks_number, + (unsigned long long)large_mem_used, + (unsigned long long)(dumped_data + DUMPED_HEAP_SIZE - bc_limit)); +} #endif - data_region_end = data_region_base; - real_data_region_end = data_region_end; + +/* Emulate getpagesize. */ +int +getpagesize (void) +{ + return sysinfo_cache.dwPageSize; +} + +void * +sbrk (ptrdiff_t increment) +{ + /* data_region_end is the address beyond the last allocated byte. + The sbrk() function is not emulated at all, except for a 0 value + of its parameter. This is needed by the Emacs Lisp function + `memory-limit'. */ + eassert (increment == 0); + return data_region_end; +} + +#define MAX_BUFFER_SIZE (512 * 1024 * 1024) + +/* MMAP allocation for buffers. */ +void * +mmap_alloc (void **var, size_t nbytes) +{ + void *p = NULL; + + /* We implement amortized allocation. We start by reserving twice + the size requested and commit only the size requested. Then + realloc could proceed and use the reserved pages, reallocating + only if needed. Buffer shrink would happen only so that we stay + in the 2x range. This is a big win when visiting compressed + files, where the final size of the buffer is not known in + advance, and the buffer is enlarged several times as the data is + decompressed on the fly. */ + if (nbytes < MAX_BUFFER_SIZE) + p = VirtualAlloc (NULL, (nbytes * 2), MEM_RESERVE, PAGE_READWRITE); + + /* If it fails, or if the request is above 512MB, try with the + requested size. */ + if (p == NULL) + p = VirtualAlloc (NULL, nbytes, MEM_RESERVE, PAGE_READWRITE); + + if (p != NULL) + { + /* Now, commit pages for NBYTES. */ + *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); } - else + + if (!p) { - data_region_base = RVA_TO_PTR (preload_heap_section->VirtualAddress); - data_region_end = data_region_base; - real_data_region_end = data_region_end; - reserved_heap_size = preload_heap_section->Misc.VirtualSize; + if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY) + errno = ENOMEM; + else + { + DebPrint (("mmap_alloc: error %ld\n", GetLastError ())); + errno = EINVAL; + } } - /* Update system version information to match current system. */ - cache_system_info (); + return *var = p; } -/* Round the heap up to the given alignment. */ void -round_heap (size_t align) +mmap_free (void **var) { - DWORD_PTR needs_to_be; - DWORD_PTR need_to_alloc; + if (*var) + { + if (VirtualFree (*var, 0, MEM_RELEASE) == 0) + DebPrint (("mmap_free: error %ld\n", GetLastError ())); + *var = NULL; + } +} + +void * +mmap_realloc (void **var, size_t nbytes) +{ + MEMORY_BASIC_INFORMATION memInfo, m2; + + if (*var == NULL) + return mmap_alloc (var, nbytes); + + /* This case happens in init_buffer(). */ + if (nbytes == 0) + { + mmap_free (var); + return mmap_alloc (var, nbytes); + } - needs_to_be = (DWORD_PTR) ROUND_UP (get_heap_end (), align); - need_to_alloc = needs_to_be - (DWORD_PTR) get_heap_end (); + if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) + DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ())); + + /* We need to enlarge the block. */ + if (memInfo.RegionSize < nbytes) + { + if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) + DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", + GetLastError ())); + /* If there is enough room in the current reserved area, then + commit more pages as needed. */ + if (m2.State == MEM_RESERVE + && nbytes <= memInfo.RegionSize + m2.RegionSize) + { + void *p; + + p = VirtualAlloc (*var + memInfo.RegionSize, + nbytes - memInfo.RegionSize, + MEM_COMMIT, PAGE_READWRITE); + if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) + { + DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", + GetLastError ())); + errno = ENOMEM; + } + return *var; + } + else + { + /* Else we must actually enlarge the block by allocating a + new one and copying previous contents from the old to the + new one. */ + void *old_ptr = *var; + + if (mmap_alloc (var, nbytes)) + { + CopyMemory (*var, old_ptr, memInfo.RegionSize); + mmap_free (&old_ptr); + return *var; + } + else + { + /* We failed to enlarge the buffer. */ + *var = old_ptr; + return NULL; + } + } + } + + /* If we are shrinking by more than one page... */ + if (memInfo.RegionSize > nbytes + getpagesize()) + { + /* If we are shrinking a lot... */ + if ((memInfo.RegionSize / 2) > nbytes) + { + /* Let's give some memory back to the system and release + some pages. */ + void *old_ptr = *var; + + if (mmap_alloc (var, nbytes)) + { + CopyMemory (*var, old_ptr, nbytes); + mmap_free (&old_ptr); + return *var; + } + else + { + /* In case we fail to shrink, try to go on with the old block. + But that means there is a lot of memory pressure. + We could also decommit pages. */ + *var = old_ptr; + return *var; + } + } + + /* We still can decommit pages. */ + if (VirtualFree (*var + nbytes + get_page_size(), + memInfo.RegionSize - nbytes - get_page_size(), + MEM_DECOMMIT) == 0) + DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError ())); + return *var; + } - if (need_to_alloc) - sbrk (need_to_alloc); + /* Not enlarging, not shrinking by more than one page. */ + return *var; } diff --git a/src/w32heap.h b/src/w32heap.h index d5791a3a23c..787fe9ade5f 100644 --- a/src/w32heap.h +++ b/src/w32heap.h @@ -27,15 +27,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. /* * Heap related stuff. */ -#define get_reserved_heap_size() reserved_heap_size -#define get_committed_heap_size() (get_data_end () - get_data_start ()) -#define get_heap_start() get_data_start () -#define get_heap_end() get_data_end () extern unsigned char *get_data_start (void); extern unsigned char *get_data_end (void); extern size_t reserved_heap_size; -extern BOOL using_dynamic_heap; +extern BOOL using_dynamic_heap; + +extern void *mmap_realloc (void **, size_t); +extern void mmap_free (void **); +extern void *mmap_alloc (void **, size_t); + +extern void report_temacs_memory_usage (void); /* Emulation of Unix sbrk(). */ extern void *sbrk (ptrdiff_t size); @@ -43,11 +45,8 @@ extern void *sbrk (ptrdiff_t size); /* Initialize heap structures for sbrk on startup. */ extern void init_heap (void); -/* Round the heap to this size. */ -extern void round_heap (size_t size); - /* ----------------------------------------------------------------- */ -/* Useful routines for manipulating memory-mapped files. */ +/* Useful routines for manipulating memory-mapped files. */ typedef struct file_data { char *name; @@ -61,11 +60,11 @@ int open_input_file (file_data *p_file, char *name); int open_output_file (file_data *p_file, char *name, unsigned long size); void close_file_data (file_data *p_file); -/* Return pointer to section header for named section. */ +/* Return pointer to section header for named section. */ IMAGE_SECTION_HEADER * find_section (char * name, IMAGE_NT_HEADERS * nt_header); /* Return pointer to section header for section containing the given - relative virtual address. */ + relative virtual address. */ IMAGE_SECTION_HEADER * rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header); #endif /* NTHEAP_H_ */ diff --git a/src/w32inevt.c b/src/w32inevt.c index 50538c5b4ba..7d10d88155c 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -411,7 +411,7 @@ w32_console_mouse_position (struct frame **f, *f = get_frame (); *bar_window = Qnil; - *part = 0; + *part = scroll_bar_above_handle; SELECTED_FRAME ()->mouse_moved = 0; XSETINT (*x, movement_pos.X); @@ -587,7 +587,8 @@ resize_event (WINDOW_BUFFER_SIZE_RECORD *event) { struct frame *f = get_frame (); - change_frame_size (f, event->dwSize.X, event->dwSize.Y, 0, 1, 0, 0); + change_frame_size (f, event->dwSize.X, event->dwSize.Y + - FRAME_MENU_BAR_LINES (f), 0, 1, 0, 0); SET_FRAME_GARBAGED (f); } @@ -603,8 +604,8 @@ maybe_generate_resize_event (void) if the size hasn't actually changed. */ change_frame_size (f, 1 + info.srWindow.Right - info.srWindow.Left, - 1 + info.srWindow.Bottom - info.srWindow.Top, - 0, 0, 0, 0); + 1 + info.srWindow.Bottom - info.srWindow.Top + - FRAME_MENU_BAR_LINES (f), 0, 1, 0, 0); } #if HAVE_W32NOTIFY diff --git a/src/w32inevt.h b/src/w32inevt.h index 9117453e721..c4836211bc9 100644 --- a/src/w32inevt.h +++ b/src/w32inevt.h @@ -27,6 +27,6 @@ extern void w32_console_mouse_position (struct frame **f, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, - unsigned long *time); + Time *time); #endif /* EMACS_W32INEVT_H */ diff --git a/src/w32menu.c b/src/w32menu.c index a4acdfd9e91..9f777167bf0 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -103,7 +103,7 @@ Lisp_Object Qdebug_on_next_call, Qunsupported__w32_dialog; void set_frame_menubar (struct frame *, bool, bool); #ifdef HAVE_DIALOGS -static Lisp_Object w32_dialog_show (struct frame *, int, Lisp_Object, char**); +static Lisp_Object w32_dialog_show (struct frame *, Lisp_Object, Lisp_Object, char **); #else static int is_simple_dialog (Lisp_Object); static Lisp_Object simple_dialog_show (struct frame *, Lisp_Object, Lisp_Object); @@ -141,7 +141,7 @@ w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) /* Display them in a dialog box. */ block_input (); - selection = w32_dialog_show (f, 0, title, header, &error_name); + selection = w32_dialog_show (f, title, header, &error_name); unblock_input (); discard_menu_items (); @@ -376,12 +376,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Convert menu_items into widget_value trees to display the menu. This cannot evaluate Lisp code. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; i < last_i; i += 4) @@ -444,12 +440,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Make a widget-value tree containing just the top level menu bar strings. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; items = FRAME_MENU_BAR_ITEMS (f); @@ -461,12 +453,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) if (NILP (string)) break; - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; /* This prevents lwlib from assuming this menu item is really supposed to be empty. */ /* The EMACS_INT cast avoids a warning. @@ -515,7 +503,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Force the window size to be recomputed so that the frame's text area remains the same, if menubar has just been created. */ if (old_widget == NULL) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), + FRAME_TEXT_HEIGHT (f), 2, 0); } unblock_input (); @@ -561,8 +550,9 @@ free_frame_menubar (struct frame *f) /* F is the frame the menu is for. X and Y are the frame-relative specified position, relative to the inside upper left corner of the frame F. - FOR_CLICK is nonzero if this menu was invoked for a mouse click. - KEYMAPS is 1 if this menu was specified with keymaps; + Bitfield MENUFLAGS bits are: + MENU_FOR_CLICK is set if this menu was invoked for a mouse click. + MENU_KEYMAPS is set if this menu was specified with keymaps; in that case, we return a list containing the chosen item's value and perhaps also the pane's prefix. TITLE is the specified menu title. @@ -570,7 +560,7 @@ free_frame_menubar (struct frame *f) (We return nil on failure, but the value doesn't actually matter.) */ Lisp_Object -w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, +w32_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error) { int i; @@ -600,12 +590,8 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, /* Create a tree of widget_value objects representing the panes and their items. */ - wv = xmalloc_widget_value (); - wv->name = "menu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; first_pane = 1; @@ -663,20 +649,16 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, /* If the pane has a meaningful name, make the pane a top-level menu item with its items as a submenu beneath it. */ - if (!keymaps && strcmp (pane_string, "")) + if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = pane_string; - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -717,19 +699,17 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); } - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* Use the contents index as call_data, since we are restricted to 16-bits. */ wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -742,11 +722,6 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, wv->selected = !NILP (selected); - if (!STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -756,25 +731,21 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, /* Deal with the title, if it is non-nil. */ if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil); /* Maybe replace this separator with a bitmap or owner-draw item so that it looks better. Having two separators looks odd. */ - wv_sep->name = "--"; wv_sep->next = first_wv->contents; - wv_sep->help = Qnil; if (unicode_append_menu) title = ENCODE_UTF_8 (title); else if (STRING_MULTIBYTE (title)) title = ENCODE_SYSTEM (title); - wv_title->name = SSDATA (title); - wv_title->enabled = TRUE; + wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil); wv_title->title = TRUE; wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep; first_wv->contents = wv_title; } @@ -842,10 +813,10 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, i += 1; else { - entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == i) { - if (keymaps != 0) + if (menuflags & MENU_KEYMAPS) { int j; @@ -863,7 +834,7 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, } } } - else if (!for_click) + else if (!(menuflags & MENU_FOR_CLICK)) { unblock_input (); /* Make "Cancel" equivalent to C-g. */ @@ -904,9 +875,8 @@ static char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -w32_dialog_show (struct frame *f, int keymaps, - Lisp_Object title, Lisp_Object header, - char **error) +w32_dialog_show (struct frame *f, Lisp_Object title, + Lisp_Object header, char **error) { int i, nb_buttons = 0; char dialog_name[6]; @@ -930,19 +900,12 @@ w32_dialog_show (struct frame *f, int keymaps, /* Create a tree of widget_value objects representing the text label and buttons. */ { - Lisp_Object pane_name, prefix; + Lisp_Object pane_name; char *pane_string; pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); - prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - prev_wv = xmalloc_widget_value (); - prev_wv->value = pane_string; - if (keymaps && !NILP (prefix)) - prev_wv->name++; - prev_wv->enabled = 1; - prev_wv->name = "message"; - prev_wv->help = Qnil; + prev_wv = make_widget_value ("message", pane_string, true, Qnil); first_wv = prev_wv; /* Loop over all panes and items, filling in the tree. */ @@ -979,15 +942,13 @@ w32_dialog_show (struct frame *f, int keymaps, return Qnil; } - wv = xmalloc_widget_value (); + wv = make_widget_value (button_names[nb_buttons], + SSDATA (item_name), + !NILP (enable), Qnil); prev_wv->next = wv; - wv->name = (char *) button_names[nb_buttons]; if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = SSDATA (item_name); wv->call_data = aref_addr (menu_items, i); - wv->enabled = !NILP (enable); - wv->help = Qnil; prev_wv = wv; if (! boundary_seen) @@ -1002,9 +963,7 @@ w32_dialog_show (struct frame *f, int keymaps, if (! boundary_seen) left_count = nb_buttons - nb_buttons / 2; - wv = xmalloc_widget_value (); - wv->name = dialog_name; - wv->help = Qnil; + wv = make_widget_value (dialog_name, NULL, false, Qnil); /* Frame title: 'Q' = Question, 'I' = Information. Can also have 'E' = Error if, one day, we want @@ -1052,32 +1011,18 @@ w32_dialog_show (struct frame *f, int keymaps, the proper value. */ if (menu_item_selection != 0) { - Lisp_Object prefix; - - prefix = Qnil; i = 0; while (i < menu_items_used) { Lisp_Object entry; if (EQ (AREF (menu_items, i), Qt)) - { - prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); - i += MENU_ITEMS_PANE_LENGTH; - } + i += MENU_ITEMS_PANE_LENGTH; else { - entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == i) - { - if (keymaps != 0) - { - entry = Fcons (entry, Qnil); - if (!NILP (prefix)) - entry = Fcons (prefix, entry); - } - return entry; - } + return entry; i += MENU_ITEMS_ITEM_LENGTH; } } diff --git a/src/w32notify.c b/src/w32notify.c index 7155f16f3b0..86412b8a974 100644 --- a/src/w32notify.c +++ b/src/w32notify.c @@ -247,7 +247,6 @@ watch_worker (LPVOID arg) do { BOOL status; - DWORD sleep_result; DWORD bytes_ret = 0; if (dirwatch->dir) @@ -275,7 +274,7 @@ watch_worker (LPVOID arg) /* Sleep indefinitely until awoken by the I/O completion, which could be either a change notification or a cancellation of the watch. */ - sleep_result = SleepEx (INFINITE, TRUE); + SleepEx (INFINITE, TRUE); } while (!dirwatch->terminate); return 0; @@ -287,7 +286,6 @@ static struct notification * start_watching (const char *file, HANDLE hdir, BOOL subdirs, DWORD flags) { struct notification *dirwatch = xzalloc (sizeof (struct notification)); - HANDLE thr; dirwatch->signature = DIRWATCH_SIGNATURE; dirwatch->buf = xmalloc (16384); diff --git a/src/w32proc.c b/src/w32proc.c index 96f11657892..38452917add 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <signal.h> #include <sys/file.h> #include <mbstring.h> +#include <locale.h> /* must include CRT headers *before* config.h */ #include <config.h> @@ -1604,6 +1605,15 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) program = ENCODE_FILE (full); cmdname = SDATA (program); } + else + { + char *p = alloca (strlen (cmdname) + 1); + + /* Don't change the command name we were passed by our caller + (unixtodos_filename below will destructively mirror forward + slashes). */ + cmdname = strcpy (p, cmdname); + } /* make sure argv[0] and cmdname are both in DOS format */ unixtodos_filename (cmdname); @@ -1646,7 +1656,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) strcpy (cmdname, egetenv ("CMDPROXY")); else { - strcpy (cmdname, SDATA (Vinvocation_directory)); + lispstpcpy (cmdname, Vinvocation_directory); strcat (cmdname, "cmdproxy.exe"); } @@ -1772,12 +1782,12 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) if (need_quotes) { int escape_char_run = 0; - char * first; - char * last; + /* char * first; */ + /* char * last; */ p = *targ; - first = p; - last = p + strlen (p) - 1; + /* first = p; */ + /* last = p + strlen (p) - 1; */ *parg++ = '"'; #if 0 /* This version does not escape quotes if they occur at the @@ -2249,10 +2259,9 @@ static BOOL CALLBACK find_child_console (HWND hwnd, LPARAM arg) { child_process * cp = (child_process *) arg; - DWORD thread_id; DWORD process_id; - thread_id = GetWindowThreadProcessId (hwnd, &process_id); + GetWindowThreadProcessId (hwnd, &process_id); if (process_id == cp->procinfo.dwProcessId) { char window_class[32]; @@ -2909,7 +2918,7 @@ int_from_hex (char * s) function isn't given a context pointer. */ Lisp_Object Vw32_valid_locale_ids; -static BOOL CALLBACK +static BOOL CALLBACK ALIGN_STACK enum_locale_fn (LPTSTR localeNum) { DWORD id = int_from_hex (localeNum); @@ -2973,7 +2982,7 @@ If successful, the new locale id is returned, otherwise nil. */) function isn't given a context pointer. */ Lisp_Object Vw32_valid_codepages; -static BOOL CALLBACK +static BOOL CALLBACK ALIGN_STACK enum_codepage_fn (LPTSTR codepageNum) { DWORD id = atoi (codepageNum); @@ -3145,6 +3154,190 @@ If successful, the new layout id is returned, otherwise nil. */) return Fw32_get_keyboard_layout (); } +/* Two variables to interface between get_lcid and the EnumLocales + callback function below. */ +#ifndef LOCALE_NAME_MAX_LENGTH +# define LOCALE_NAME_MAX_LENGTH 85 +#endif +static LCID found_lcid; +static char lname[3 * LOCALE_NAME_MAX_LENGTH + 1 + 1]; + +/* Callback function for EnumLocales. */ +static BOOL CALLBACK +get_lcid_callback (LPTSTR locale_num_str) +{ + char *endp; + char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1]; + LCID try_lcid = strtoul (locale_num_str, &endp, 16); + + if (GetLocaleInfo (try_lcid, LOCALE_SABBREVLANGNAME, + locval, LOCALE_NAME_MAX_LENGTH)) + { + /* This is for when they only specify the language, as in "ENU". */ + if (stricmp (locval, lname) == 0) + { + found_lcid = try_lcid; + return FALSE; + } + strcat (locval, "_"); + if (GetLocaleInfo (try_lcid, LOCALE_SABBREVCTRYNAME, + locval + strlen (locval), LOCALE_NAME_MAX_LENGTH)) + { + size_t locval_len = strlen (locval); + + if (strnicmp (locval, lname, locval_len) == 0 + && (lname[locval_len] == '.' + || lname[locval_len] == '\0')) + { + found_lcid = try_lcid; + return FALSE; + } + } + } + return TRUE; +} + +/* Return the Locale ID (LCID) number given the locale's name, a + string, in LOCALE_NAME. This works by enumerating all the locales + supported by the system, until we find one whose name matches + LOCALE_NAME. */ +static LCID +get_lcid (const char *locale_name) +{ + /* A simple cache. */ + static LCID last_lcid; + static char last_locale[1000]; + + /* The code below is not thread-safe, as it uses static variables. + But this function is called only from the Lisp thread. */ + if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0) + return last_lcid; + + strncpy (lname, locale_name, sizeof (lname) - 1); + lname[sizeof (lname) - 1] = '\0'; + found_lcid = 0; + EnumSystemLocales (get_lcid_callback, LCID_SUPPORTED); + if (found_lcid > 0) + { + last_lcid = found_lcid; + strcpy (last_locale, locale_name); + } + return found_lcid; +} + +#ifndef _NSLCMPERROR +# define _NSLCMPERROR INT_MAX +#endif +#ifndef LINGUISTIC_IGNORECASE +# define LINGUISTIC_IGNORECASE 0x00000010 +#endif + +int +w32_compare_strings (const char *s1, const char *s2, char *locname, + int ignore_case) +{ + LCID lcid = GetThreadLocale (); + wchar_t *string1_w, *string2_w; + int val, needed; + extern BOOL g_b_init_compare_string_w; + static int (WINAPI *pCompareStringW)(LCID, DWORD, LPCWSTR, int, LPCWSTR, int); + DWORD flags = 0; + + USE_SAFE_ALLOCA; + + /* The LCID machinery doesn't seem to support the "C" locale, so we + need to do that by hand. */ + if (locname + && ((locname[0] == 'C' && (locname[1] == '\0' || locname[1] == '.')) + || strcmp (locname, "POSIX") == 0)) + return (ignore_case ? stricmp (s1, s2) : strcmp (s1, s2)); + + if (!g_b_init_compare_string_w) + { + if (os_subtype == OS_9X) + { + pCompareStringW = GetProcAddress (LoadLibrary ("Unicows.dll"), + "CompareStringW"); + if (!pCompareStringW) + { + errno = EINVAL; + /* This return value is compatible with wcscoll and + other MS CRT functions. */ + return _NSLCMPERROR; + } + } + else + pCompareStringW = CompareStringW; + + g_b_init_compare_string_w = 1; + } + + needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s1, -1, NULL, 0); + if (needed > 0) + { + SAFE_NALLOCA (string1_w, 1, needed + 1); + pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s1, -1, + string1_w, needed); + } + else + { + errno = EINVAL; + return _NSLCMPERROR; + } + + needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s2, -1, NULL, 0); + if (needed > 0) + { + SAFE_NALLOCA (string2_w, 1, needed + 1); + pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s2, -1, + string2_w, needed); + } + else + { + SAFE_FREE (); + errno = EINVAL; + return _NSLCMPERROR; + } + + if (locname) + { + /* Convert locale name string to LCID. We don't want to use + LocaleNameToLCID because (a) it is only available since + Vista, and (b) it doesn't accept locale names returned by + 'setlocale' and 'GetLocaleInfo'. */ + LCID new_lcid = get_lcid (locname); + + if (new_lcid > 0) + lcid = new_lcid; + else + error ("Invalid locale %s: Invalid argument", locname); + } + + if (ignore_case) + { + /* NORM_IGNORECASE ignores any tertiary distinction, not just + case variants. LINGUISTIC_IGNORECASE is more selective, and + is sensitive to the locale's language, but it is not + available before Vista. */ + if (w32_major_version >= 6) + flags |= LINGUISTIC_IGNORECASE; + else + flags |= NORM_IGNORECASE; + } + /* This approximates what glibc collation functions do when the + locale's codeset is UTF-8. */ + if (!NILP (Vw32_collate_ignore_punctuation)) + flags |= NORM_IGNORESYMBOLS; + val = pCompareStringW (lcid, flags, string1_w, -1, string2_w, -1); + SAFE_FREE (); + if (!val) + { + errno = EINVAL; + return _NSLCMPERROR; + } + return val - 2; +} + void syms_of_ntproc (void) @@ -3255,6 +3448,20 @@ Any other non-nil value means do this even on remote and removable drives where the performance impact may be noticeable even on modern hardware. */); Vw32_get_true_file_attributes = Qlocal; + DEFVAR_LISP ("w32-collate-ignore-punctuation", + Vw32_collate_ignore_punctuation, + doc: /* Non-nil causes string collation functions ignore punctuation on MS-Windows. +On Posix platforms, `string-collate-lessp' and `string-collate-equalp' +ignore punctuation characters when they compare strings, if the +locale's codeset is UTF-8, as in \"en_US.UTF-8\". Binding this option +to a non-nil value will achieve a similar effect on MS-Windows, where +locales with UTF-8 codeset are not supported. + +Note that setting this to non-nil will also ignore blanks and symbols +in the strings. So do NOT use this option when comparing file names +for equality, only when you need to sort them. */); + Vw32_collate_ignore_punctuation = Qnil; + staticpro (&Vw32_valid_locale_ids); staticpro (&Vw32_valid_codepages); } diff --git a/src/w32select.c b/src/w32select.c index 7c21dde01a5..9fa84ca5c54 100644 --- a/src/w32select.c +++ b/src/w32select.c @@ -95,8 +95,8 @@ static Lisp_Object render_locale (void); static Lisp_Object render_all (Lisp_Object ignore); static void run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg); static Lisp_Object lisp_error_handler (Lisp_Object error); -static LRESULT CALLBACK owner_callback (HWND win, UINT msg, - WPARAM wp, LPARAM lp); +static LRESULT CALLBACK ALIGN_STACK owner_callback (HWND win, UINT msg, + WPARAM wp, LPARAM lp); static HWND create_owner (void); static void setup_config (void); @@ -420,7 +420,7 @@ lisp_error_handler (Lisp_Object error) } -static LRESULT CALLBACK +static LRESULT CALLBACK ALIGN_STACK owner_callback (HWND win, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) diff --git a/src/w32term.c b/src/w32term.c index 66cdbfaecb0..e8bcf3ef639 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -50,6 +50,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "process.h" #include "atimer.h" #include "keymap.h" +#include "menu.h" #ifdef WINDOWSNT #include "w32.h" /* for filename_from_utf16, filename_from_ansi */ @@ -157,8 +158,11 @@ DWORD dwMainThreadId = 0; HANDLE hMainThread = NULL; int vertical_scroll_bar_min_handle; +int horizontal_scroll_bar_min_handle; int vertical_scroll_bar_top_border; int vertical_scroll_bar_bottom_border; +int horizontal_scroll_bar_left_border; +int horizontal_scroll_bar_right_border; int last_scroll_bar_drag_pos; @@ -454,7 +458,7 @@ x_set_frame_alpha (struct frame *f) if (!pfnSetLayeredWindowAttributes) return; - if (dpyinfo->x_highlight_frame == f) + if (dpyinfo->w32_focus_frame == f) alpha = f->alpha[0]; else alpha = f->alpha[1]; @@ -999,7 +1003,7 @@ x_set_mouse_face_gc (struct glyph_string *s) else face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); s->face = FACE_FROM_ID (s->f, face_id); - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); /* If font in this face is same as S->font, use it. */ if (s->font == s->face->font) @@ -1049,7 +1053,7 @@ x_set_mode_line_face_gc (struct glyph_string *s) static inline void x_set_glyph_string_gc (struct glyph_string *s) { - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); if (s->hl == DRAW_NORMAL_TEXT) { @@ -1078,10 +1082,7 @@ x_set_glyph_string_gc (struct glyph_string *s) s->stippled_p = s->face->stipple != 0; } else - { - s->gc = s->face->gc; - s->stippled_p = s->face->stipple != 0; - } + emacs_abort (); /* GC must have been set. */ eassert (s->gc != 0); @@ -3339,11 +3340,15 @@ note_mouse_movement (struct frame *frame, MSG *msg) Mouse Face ************************************************************************/ -static struct scroll_bar *x_window_to_scroll_bar (Window); +static struct scroll_bar *x_window_to_scroll_bar (Window, int); static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, enum scroll_bar_part *, Lisp_Object *, Lisp_Object *, - unsigned long *); + Time *); +static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *, + enum scroll_bar_part *, + Lisp_Object *, Lisp_Object *, + Time *); static void x_check_fullscreen (struct frame *); static void @@ -3351,6 +3356,7 @@ w32_define_cursor (Window window, Cursor cursor) { PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0); } + /* Return the current position of the mouse. *fp should be a frame which indicates which display to ask about. @@ -3374,7 +3380,7 @@ w32_define_cursor (Window window, Cursor cursor) static void w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, - unsigned long *time) + Time *time) { struct frame *f1; struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); @@ -3382,7 +3388,14 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, block_input (); if (dpyinfo->last_mouse_scroll_bar && insist == 0) - x_scroll_bar_report_motion (fp, bar_window, part, x, y, time); + { + struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar; + + if (bar->horizontal) + x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, time); + else + x_scroll_bar_report_motion (fp, bar_window, part, x, y, time); + } else { POINT pt; @@ -3410,7 +3423,7 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, if (! f1) { struct scroll_bar *bar - = x_window_to_scroll_bar (WindowFromPoint (pt)); + = x_window_to_scroll_bar (WindowFromPoint (pt), 2); if (bar) f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); @@ -3435,7 +3448,7 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, dpyinfo->last_mouse_glyph_frame = f1; *bar_window = Qnil; - *part = 0; + *part = scroll_bar_above_handle; *fp = f1; XSETINT (*x, pt.x); XSETINT (*y, pt.y); @@ -3477,12 +3490,12 @@ w32_handle_tool_bar_click (struct frame *f, struct input_event *button_event) /* Scroll bar support. */ -/* Given a window ID, find the struct scroll_bar which manages it. - This can be called in GC, so we have to make sure to strip off mark - bits. */ +/* Given a window ID, find the struct scroll_bar which manages it + vertically. This can be called in GC, so we have to make sure to + strip off mark bits. */ static struct scroll_bar * -x_window_to_scroll_bar (Window window_id) +x_window_to_scroll_bar (Window window_id, int type) { Lisp_Object tail, frame; @@ -3500,7 +3513,10 @@ x_window_to_scroll_bar (Window window_id) condemned = Qnil, ! NILP (bar)); bar = XSCROLL_BAR (bar)->next) - if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id) + if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id + && (type = 2 + || (type == 1 && XSCROLL_BAR (bar)->horizontal) + || (type == 0 && !XSCROLL_BAR (bar)->horizontal))) return XSCROLL_BAR (bar); } @@ -3509,7 +3525,7 @@ x_window_to_scroll_bar (Window window_id) -/* Set the thumb size and position of scroll bar BAR. We are currently +/* Set the thumb size and position of vertical scroll bar BAR. We are currently displaying PORTION out of a whole WHOLE, and our position POSITION. */ static void @@ -3583,16 +3599,49 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar, unblock_input (); } +/* Set the thumb size and position of horizontal scroll bar BAR. We are currently + displaying PORTION out of a whole WHOLE, and our position POSITION. */ + +static void +w32_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar, + int portion, int position, int whole) +{ + Window w = SCROLL_BAR_W32_WINDOW (bar); + SCROLLINFO si; + + block_input (); + + si.cbSize = sizeof (si); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + si.nMin = 0; + si.nMax = whole; + /* Allow nPage to be one larger than nPos so we don't allow to scroll + an already fully visible buffer. */ + si.nPage = min (portion, si.nMax) + 1; + si.nPos = min (position, si.nMax); + SetScrollInfo (w, SB_CTL, &si, TRUE); + + unblock_input (); +} + /************************************************************************ Scroll bars, general ************************************************************************/ static HWND -my_create_scrollbar (struct frame * f, struct scroll_bar * bar) +my_create_vscrollbar (struct frame * f, struct scroll_bar * bar) +{ + return (HWND) SendMessage (FRAME_W32_WINDOW (f), + WM_EMACS_CREATEVSCROLLBAR, (WPARAM) f, + (LPARAM) bar); +} + +static HWND +my_create_hscrollbar (struct frame * f, struct scroll_bar * bar) { return (HWND) SendMessage (FRAME_W32_WINDOW (f), - WM_EMACS_CREATESCROLLBAR, (WPARAM) f, + WM_EMACS_CREATEHSCROLLBAR, (WPARAM) f, (LPARAM) bar); } @@ -3662,7 +3711,7 @@ my_bring_window_to_top (HWND hwnd) scroll bar. */ static struct scroll_bar * -x_scroll_bar_create (struct window *w, int top, int left, int width, int height) +x_scroll_bar_create (struct window *w, int left, int top, int width, int height, bool horizontal) { struct frame *f = XFRAME (WINDOW_FRAME (w)); HWND hwnd; @@ -3681,16 +3730,24 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) bar->start = 0; bar->end = 0; bar->dragging = 0; + bar->horizontal = horizontal; /* Requires geometry to be set before call to create the real window */ - hwnd = my_create_scrollbar (f, bar); + if (horizontal) + hwnd = my_create_hscrollbar (f, bar); + else + hwnd = my_create_vscrollbar (f, bar); si.cbSize = sizeof (si); si.fMask = SIF_ALL; si.nMin = 0; - si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) - + VERTICAL_SCROLL_BAR_MIN_HANDLE; + if (horizontal) + si.nMax = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width) + + HORIZONTAL_SCROLL_BAR_MIN_HANDLE; + else + si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) + + VERTICAL_SCROLL_BAR_MIN_HANDLE; si.nPage = si.nMax; si.nPos = 0; @@ -3726,15 +3783,18 @@ x_scroll_bar_remove (struct scroll_bar *bar) my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar)); /* Dissociate this scroll bar from its window. */ - wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); + if (bar->horizontal) + wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil); + else + wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); unblock_input (); } -/* Set the handle of the vertical scroll bar for WINDOW to indicate - that we are displaying PORTION characters out of a total of WHOLE - characters, starting at POSITION. If WINDOW has no scroll bar, - create one. */ +/* Set the handle of the vertical scroll bar for WINDOW to indicate that + we are displaying PORTION characters out of a total of WHOLE + characters, starting at POSITION. If WINDOW has no vertical scroll + bar, create one. */ static void w32_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position) @@ -3767,7 +3827,7 @@ w32_set_vertical_scroll_bar (struct window *w, } unblock_input (); - bar = x_scroll_bar_create (w, top, left, width, height); + bar = x_scroll_bar_create (w, left, top, width, height, 0); } else { @@ -3831,6 +3891,106 @@ w32_set_vertical_scroll_bar (struct window *w, wset_vertical_scroll_bar (w, barobj); } +/* Set the handle of the horizontal scroll bar for WINDOW to indicate + that we are displaying PORTION characters out of a total of WHOLE + characters, starting at POSITION. If WINDOW has no horizontal scroll + bar, create one. */ +static void +w32_set_horizontal_scroll_bar (struct window *w, + int portion, int whole, int position) +{ + struct frame *f = XFRAME (w->frame); + Lisp_Object barobj; + struct scroll_bar *bar; + int top, height, left, width; + int window_x, window_width; + int clear_left = WINDOW_LEFT_EDGE_X (w); + int clear_width = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w); + + /* Get window dimensions. */ + window_box (w, ANY_AREA, &window_x, 0, &window_width, 0); + left = window_x; + height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w); + width = window_width; + top = WINDOW_SCROLL_BAR_AREA_Y (w); + + /* Does the scroll bar exist yet? */ + if (NILP (w->horizontal_scroll_bar)) + { + HDC hdc; + block_input (); + if (width > 0 && height > 0) + { + hdc = get_frame_dc (f); + w32_clear_area (f, hdc, clear_left, top, clear_width, height); + release_frame_dc (f, hdc); + } + unblock_input (); + + bar = x_scroll_bar_create (w, left, top, width, height, 1); + } + else + { + /* It may just need to be moved and resized. */ + HWND hwnd; + + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + hwnd = SCROLL_BAR_W32_WINDOW (bar); + + /* If already correctly positioned, do nothing. */ + if (bar->left == left && bar->top == top + && bar->width == width && bar->height == height) + { + /* Redraw after clear_frame. */ + if (!my_show_window (f, hwnd, SW_NORMAL)) + InvalidateRect (hwnd, NULL, FALSE); + } + else + { + HDC hdc; + SCROLLINFO si; + + block_input (); + if (width && height) + { + hdc = get_frame_dc (f); + /* Since Windows scroll bars are smaller than the space reserved + for them on the frame, we have to clear "under" them. */ + w32_clear_area (f, hdc, clear_left, top, clear_width, height); + release_frame_dc (f, hdc); + } + /* Make sure scroll bar is "visible" before moving, to ensure the + area of the parent window now exposed will be refreshed. */ + my_show_window (f, hwnd, SW_HIDE); + MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); + + /* +++ SetScrollInfo +++ */ + si.cbSize = sizeof (si); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + si.nMin = 0; + si.nMax = whole; + si.nPage = min (portion, si.nMax) + 1; + si.nPos = min (position, si.nMax); + SetScrollInfo (hwnd, SB_CTL, &si, FALSE); + + my_show_window (f, hwnd, SW_NORMAL); + /* InvalidateRect (w, NULL, FALSE); */ + + /* Remember new settings. */ + bar->left = left; + bar->top = top; + bar->width = width; + bar->height = height; + + unblock_input (); + } + } + + w32_set_horizontal_scroll_bar_thumb (bar, portion, position, whole); + XSETVECTOR (barobj, bar); + wset_horizontal_scroll_bar (w, barobj); +} + /* The following three hooks are used when we're doing a thorough redisplay of the frame. We don't explicitly know which scroll bars @@ -3847,17 +4007,22 @@ w32_set_vertical_scroll_bar (struct window *w, static void w32_condemn_scroll_bars (struct frame *frame) { - /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ - while (! NILP (FRAME_SCROLL_BARS (frame))) + if (!NILP (FRAME_SCROLL_BARS (frame))) { - Lisp_Object bar; - bar = FRAME_SCROLL_BARS (frame); - fset_scroll_bars (frame, XSCROLL_BAR (bar)->next); - XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); - XSCROLL_BAR (bar)->prev = Qnil; - if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) - XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; - fset_condemned_scroll_bars (frame, bar); + if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) + { + /* Prepend scrollbars to already condemned ones. */ + Lisp_Object last = FRAME_SCROLL_BARS (frame); + + while (!NILP (XSCROLL_BAR (last)->next)) + last = XSCROLL_BAR (last)->next; + + XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); + XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last; + } + + fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame)); + fset_scroll_bars (frame, Qnil); } } @@ -3866,47 +4031,84 @@ w32_condemn_scroll_bars (struct frame *frame) Note that WINDOW isn't necessarily condemned at all. */ static void -w32_redeem_scroll_bar (struct window *window) +w32_redeem_scroll_bar (struct window *w) { struct scroll_bar *bar; Lisp_Object barobj; struct frame *f; /* We can't redeem this window's scroll bar if it doesn't have one. */ - if (NILP (window->vertical_scroll_bar)) + if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar)) emacs_abort (); - bar = XSCROLL_BAR (window->vertical_scroll_bar); - - /* Unlink it from the condemned list. */ - f = XFRAME (WINDOW_FRAME (window)); - if (NILP (bar->prev)) + if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) { - /* If the prev pointer is nil, it must be the first in one of - the lists. */ - if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar)) - /* It's not condemned. Everything's fine. */ - return; - else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), - window->vertical_scroll_bar)) - fset_condemned_scroll_bars (f, bar->next); + bar = XSCROLL_BAR (w->vertical_scroll_bar); + /* Unlink it from the condemned list. */ + f = XFRAME (WINDOW_FRAME (w)); + if (NILP (bar->prev)) + { + /* If the prev pointer is nil, it must be the first in one of + the lists. */ + if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar)) + /* It's not condemned. Everything's fine. */ + goto horizontal; + else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), + w->vertical_scroll_bar)) + fset_condemned_scroll_bars (f, bar->next); + else + /* If its prev pointer is nil, it must be at the front of + one or the other! */ + emacs_abort (); + } else - /* If its prev pointer is nil, it must be at the front of - one or the other! */ - emacs_abort (); + XSCROLL_BAR (bar->prev)->next = bar->next; + + if (! NILP (bar->next)) + XSCROLL_BAR (bar->next)->prev = bar->prev; + + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (! NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); } - else - XSCROLL_BAR (bar->prev)->next = bar->next; - if (! NILP (bar->next)) - XSCROLL_BAR (bar->next)->prev = bar->prev; + horizontal: + if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) + { + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + /* Unlink it from the condemned list. */ + f = XFRAME (WINDOW_FRAME (w)); + if (NILP (bar->prev)) + { + /* If the prev pointer is nil, it must be the first in one of + the lists. */ + if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar)) + /* It's not condemned. Everything's fine. */ + return; + else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), + w->horizontal_scroll_bar)) + fset_condemned_scroll_bars (f, bar->next); + else + /* If its prev pointer is nil, it must be at the front of + one or the other! */ + emacs_abort (); + } + else + XSCROLL_BAR (bar->prev)->next = bar->next; - bar->next = FRAME_SCROLL_BARS (f); - bar->prev = Qnil; - XSETVECTOR (barobj, bar); - fset_scroll_bars (f, barobj); - if (! NILP (bar->next)) - XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + if (! NILP (bar->next)) + XSCROLL_BAR (bar->next)->prev = bar->prev; + + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (! NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + } } /* Remove all scroll bars on FRAME that haven't been saved since the @@ -3937,8 +4139,9 @@ w32_judge_scroll_bars (struct frame *f) and they should get garbage-collected. */ } -/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind - is set to something other than NO_EVENT, it is enqueued. +/* Handle a mouse click on the vertical scroll bar BAR. If + *EMACS_EVENT's kind is set to something other than NO_EVENT, it is + enqueued. This may be called from a signal handler, so we have to ignore GC mark bits. */ @@ -3963,17 +4166,24 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg, int y; int dragging = bar->dragging; SCROLLINFO si; + int sb_event = LOWORD (msg->msg.wParam); si.cbSize = sizeof (si); - si.fMask = SIF_POS; + if (sb_event == SB_THUMBTRACK) + si.fMask = SIF_TRACKPOS; + else + si.fMask = SIF_POS; GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si); - y = si.nPos; + if (sb_event == SB_THUMBTRACK) + y = si.nTrackPos; + else + y = si.nPos; bar->dragging = 0; FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam; - switch (LOWORD (msg->msg.wParam)) + switch (sb_event) { case SB_LINEDOWN: emacs_event->part = scroll_bar_down_arrow; @@ -3997,8 +4207,6 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg, break; case SB_THUMBTRACK: case SB_THUMBPOSITION: - if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height) <= 0xffff) - y = HIWORD (msg->msg.wParam); bar->dragging = 1; /* ??????? */ emacs_event->part = scroll_bar_handle; @@ -4045,14 +4253,128 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg, } } -/* Return information to the user about the current position of the mouse - on the scroll bar. */ +/* Handle a mouse click on the horizontal scroll bar BAR. If + *EMACS_EVENT's kind is set to something other than NO_EVENT, it is + enqueued. + + This may be called from a signal handler, so we have to ignore GC + mark bits. */ + +static int +w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg, + struct input_event *emacs_event) +{ + if (! WINDOWP (bar->window)) + emacs_abort (); + emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT; + emacs_event->code = 0; + /* not really meaningful to distinguish left/right */ + emacs_event->modifiers = msg->dwModifiers; + emacs_event->frame_or_window = bar->window; + emacs_event->arg = Qnil; + emacs_event->timestamp = msg->msg.time; + + { + int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width); + int x, y; + int dragging = bar->dragging; + SCROLLINFO si; + int sb_event = LOWORD (msg->msg.wParam); + + si.cbSize = sizeof (si); + if (sb_event == SB_THUMBTRACK) + si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE; + else + si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; + + GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si); + if (sb_event == SB_THUMBTRACK) + x = si.nTrackPos; + else + x = si.nPos; + y = si.nMax - si.nPage; + + bar->dragging = 0; + FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam; + + switch (sb_event) + { + case SB_LINELEFT: + emacs_event->part = scroll_bar_left_arrow; + break; + case SB_LINERIGHT: + emacs_event->part = scroll_bar_right_arrow; + break; + case SB_PAGELEFT: + emacs_event->part = scroll_bar_before_handle; + break; + case SB_PAGERIGHT: + emacs_event->part = scroll_bar_after_handle; + break; + case SB_LEFT: + emacs_event->part = scroll_bar_horizontal_handle; + x = 0; + break; + case SB_RIGHT: + emacs_event->part = scroll_bar_horizontal_handle; + x = left_range; + break; + case SB_THUMBTRACK: + case SB_THUMBPOSITION: + bar->dragging = 1; + emacs_event->part = scroll_bar_horizontal_handle; + + /* "Silently" update current position. */ + { + SCROLLINFO si; + + si.cbSize = sizeof (si); + si.fMask = SIF_POS; + si.nPos = min (x, XWINDOW (bar->window)->hscroll_whole - 1); + /* Remember apparent position (we actually lag behind the real + position, so don't set that directly). */ + last_scroll_bar_drag_pos = x; + + SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE); + } + break; + case SB_ENDSCROLL: + /* If this is the end of a drag sequence, then reset the scroll + handle size to normal and do a final redraw. Otherwise do + nothing. */ + if (dragging) + { + SCROLLINFO si; + int start = bar->start; + int end = bar->end; + + si.cbSize = sizeof (si); + si.fMask = SIF_POS; + si.nPos = min (last_scroll_bar_drag_pos, + XWINDOW (bar->window)->hscroll_whole - 1); + SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE); + } + /* fall through */ + default: + emacs_event->kind = NO_EVENT; + return FALSE; + } + + XSETINT (emacs_event->x, x); + XSETINT (emacs_event->y, y); + + return TRUE; + } +} + +/* Return information to the user about the current position of the mouse + on the vertical scroll bar. */ static void x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, - unsigned long *time) + Time *time) { struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar; @@ -4061,6 +4383,7 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, int pos; int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); SCROLLINFO si; + int sb_event = LOWORD (dpyinfo->last_mouse_scroll_bar_pos); block_input (); @@ -4068,28 +4391,21 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, *bar_window = bar->window; si.cbSize = sizeof (si); - si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; + if (sb_event == SB_THUMBTRACK) + si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE; + else + si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; GetScrollInfo (w, SB_CTL, &si); - pos = si.nPos; + if (sb_event == SB_THUMBTRACK) + pos = si.nTrackPos; + else + pos = si.nPos; top_range = si.nMax - si.nPage + 1; - switch (LOWORD (dpyinfo->last_mouse_scroll_bar_pos)) - { - case SB_THUMBPOSITION: - case SB_THUMBTRACK: - *part = scroll_bar_handle; - if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height) <= 0xffff) - pos = HIWORD (dpyinfo->last_mouse_scroll_bar_pos); - break; - case SB_LINEDOWN: - *part = scroll_bar_handle; - pos++; - break; - default: - *part = scroll_bar_handle; - break; - } + *part = scroll_bar_handle; + if (sb_event == SB_LINEDOWN) + pos++; XSETINT (*x, pos); XSETINT (*y, top_range); @@ -4102,6 +4418,57 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, unblock_input (); } +/* Return information to the user about the current position of the mouse + on the horizontal scroll bar. */ +static void +x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, + enum scroll_bar_part *part, + Lisp_Object *x, Lisp_Object *y, + Time *time) +{ + struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); + struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar; + Window w = SCROLL_BAR_W32_WINDOW (bar); + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + int pos; + int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width); + SCROLLINFO si; + int sb_event = LOWORD (dpyinfo->last_mouse_scroll_bar_pos); + + block_input (); + + *fp = f; + *bar_window = bar->window; + + si.cbSize = sizeof (si); + if (sb_event == SB_THUMBTRACK) + si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE; + else + si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; + + GetScrollInfo (w, SB_CTL, &si); + if (sb_event == SB_THUMBTRACK) + pos = si.nTrackPos; + else + pos = si.nPos; + left_range = si.nMax - si.nPage + 1; + + *part = scroll_bar_handle; + if (sb_event == SB_LINERIGHT) + pos++; + + + XSETINT (*y, pos); + XSETINT (*x, left_range); + + f->mouse_moved = 0; + dpyinfo->last_mouse_scroll_bar = NULL; + + *time = dpyinfo->last_mouse_movement_time; + + unblock_input (); +} + /* The screen has been cleared so we may have changed foreground or background colors, and the scroll bars may need to be redrawn. @@ -4116,7 +4483,8 @@ x_scroll_bar_clear (struct frame *f) /* We can have scroll bars even if this is 0, if we just turned off scroll bar mode. But in that case we should not clear them. */ - if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) + if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) + || FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)) for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); bar = XSCROLL_BAR (bar)->next) { @@ -4137,7 +4505,18 @@ x_scroll_bar_clear (struct frame *f) } } - +static void +set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) +{ + register Lisp_Object old_alist_elt; + + old_alist_elt = Fassq (prop, f->param_alist); + if (EQ (old_alist_elt, Qnil)) + fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist)); + else + Fsetcdr (old_alist_elt, val); +} + /* The main W32 event-reading loop - w32_read_socket. */ /* Record the last 100 characters stored @@ -4538,10 +4917,11 @@ w32_read_socket (struct terminal *terminal, Emacs events should reflect only motion after the ButtonPress. */ if (f != 0) - f->mouse_moved = 0; - - if (!tool_bar_p) - last_tool_bar_item = -1; + { + f->mouse_moved = 0; + if (!tool_bar_p) + f->last_tool_bar_item = -1; + } } break; } @@ -4566,9 +4946,9 @@ w32_read_socket (struct terminal *terminal, should reflect only motion after the ButtonPress. */ f->mouse_moved = 0; + f->last_tool_bar_item = -1; } dpyinfo->last_mouse_frame = f; - last_tool_bar_item = -1; } break; @@ -4579,10 +4959,20 @@ w32_read_socket (struct terminal *terminal, construct_drag_n_drop (&inev, &msg, f); break; + case WM_HSCROLL: + { + struct scroll_bar *bar = + x_window_to_scroll_bar ((HWND)msg.msg.lParam, 1); + + if (bar) + w32_horizontal_scroll_bar_handle_click (bar, &msg, &inev); + break; + } + case WM_VSCROLL: { struct scroll_bar *bar = - x_window_to_scroll_bar ((HWND)msg.msg.lParam); + x_window_to_scroll_bar ((HWND)msg.msg.lParam, 0); if (bar) w32_scroll_bar_handle_click (bar, &msg, &inev); @@ -4767,8 +5157,8 @@ w32_read_socket (struct terminal *terminal, width = rect.right - rect.left; text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width); text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height); - rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); - columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); + /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */ + /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */ /* TODO: Clip size to the screen dimensions. */ @@ -4784,10 +5174,6 @@ w32_read_socket (struct terminal *terminal, change_frame_size (f, text_width, text_height, 0, 1, 0, 1); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); - /* Do we want to set these here ???? */ - /** FRAME_PIXEL_WIDTH (f) = width; **/ - /** FRAME_TEXT_WIDTH (f) = text_width; **/ - /** FRAME_PIXEL_HEIGHT (f) = height; **/ f->win_gravity = NorthWestGravity; } } @@ -5437,8 +5823,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_COLUMN_WIDTH (f) = unit = font->average_width; FRAME_LINE_HEIGHT (f) = font->height; - compute_fringe_widths (f, 1); - /* Compute number of scrollbar columns. */ unit = FRAME_COLUMN_WIDTH (f); if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) @@ -5458,8 +5842,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) doing it because it's done in Fx_show_tip, and it leads to problems because the tip frame has no widget. */ if (NILP (tip_frame) || XFRAME (tip_frame) != f) - x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), - FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1); + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, 0); } /* X version sets font of input methods here also. */ @@ -5579,6 +5963,47 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, unblock_input (); } +/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the + wanted positions of the WM window (not Emacs window). + Return in *WIDTH and *HEIGHT the wanted width and height of Emacs + window (FRAME_X_WINDOW). + */ + +static void +x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos) +{ + int newwidth = FRAME_COLS (f); + int newheight = FRAME_LINES (f); + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); + + *top_pos = f->top_pos; + *left_pos = f->left_pos; + + if (f->want_fullscreen & FULLSCREEN_HEIGHT) + { + int ph; + + ph = x_display_pixel_height (dpyinfo); + newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph); + ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff; + newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph); + *top_pos = 0; + } + + if (f->want_fullscreen & FULLSCREEN_WIDTH) + { + int pw; + + pw = x_display_pixel_width (dpyinfo); + newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw); + pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff; + newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw); + *left_pos = 0; + } + + *width = newwidth; + *height = newheight; +} /* Check if we need to resize the frame due to a fullscreen request. If so needed, resize the frame. */ @@ -5615,6 +6040,7 @@ w32fullscreen_hook (struct frame *f) HWND hwnd = FRAME_W32_WINDOW(f); DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE); RECT rect; + enum fullscreen_type prev_fsmode = FRAME_PREV_FSMODE (f); block_input(); f->want_fullscreen &= ~FULLSCREEN_WAIT; @@ -5636,7 +6062,14 @@ w32fullscreen_hook (struct frame *f) if (f->want_fullscreen == FULLSCREEN_NONE) ShowWindow (hwnd, SW_SHOWNORMAL); else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED) - ShowWindow (hwnd, SW_MAXIMIZE); + { + if (prev_fsmode == FULLSCREEN_BOTH || prev_fsmode == FULLSCREEN_WIDTH + || prev_fsmode == FULLSCREEN_HEIGHT) + /* Make window normal since otherwise the subsequent + maximization might fail in some cases. */ + ShowWindow (hwnd, SW_SHOWNORMAL); + ShowWindow (hwnd, SW_MAXIMIZE); + } else if (f->want_fullscreen == FULLSCREEN_BOTH) { w32_fullscreen_rect (hwnd, f->want_fullscreen, @@ -5671,70 +6104,40 @@ void x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise) { int pixelwidth, pixelheight; + RECT rect; block_input (); - check_frame_size (f, &width, &height, pixelwise); - - compute_fringe_widths (f, 0); - - if (frame_resize_pixelwise) + if (pixelwise) { - if (pixelwise) - { - pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); - } - else - { - pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); - pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); - } + pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); + pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); } else { - /* If we don't resize frames pixelwise, round sizes to multiples - of character sizes here. Otherwise, when enforcing size hints - while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might - clip our frame rectangle to a multiple of the frame's character - size and subsequently lose our mode line or scroll bar. - Bug#16923 could be one possible consequence of this. Carefully - reverse-engineer what WM_WINDOWPOSCHANGING does here since - otherwise we might make our frame too small, see Bug#17077. */ - int unit_width = FRAME_COLUMN_WIDTH (f); - int unit_height = FRAME_LINE_HEIGHT (f); - - pixelwidth = (((((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f))) - + FRAME_TOTAL_FRINGE_WIDTH (f)) - / unit_width) * unit_width) - + FRAME_SCROLL_BAR_AREA_WIDTH (f) - + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); - - pixelheight = ((((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f))) - / unit_height) * unit_height) - + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); + pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); } f->win_gravity = NorthWestGravity; x_wm_set_size_hint (f, (long) 0, 0); - { - RECT rect; + f->want_fullscreen = FULLSCREEN_NONE; + w32fullscreen_hook (f); - rect.left = rect.top = 0; - rect.right = pixelwidth; - rect.bottom = pixelheight; + rect.left = rect.top = 0; + rect.right = pixelwidth; + rect.bottom = pixelheight; - AdjustWindowRect (&rect, f->output_data.w32->dwStyle, - FRAME_EXTERNAL_MENU_BAR (f)); + AdjustWindowRect (&rect, f->output_data.w32->dwStyle, + FRAME_EXTERNAL_MENU_BAR (f)); - my_set_window_pos (FRAME_W32_WINDOW (f), - NULL, - 0, 0, - rect.right - rect.left, - rect.bottom - rect.top, - SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); - } + my_set_window_pos (FRAME_W32_WINDOW (f), + NULL, + 0, 0, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); /* If w32_enable_frame_resize_hack is non-nil, immediately apply the new pixel sizes to the frame and its subwindows. @@ -5783,31 +6186,14 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b } unblock_input (); + + do_pending_window_change (0); } /* Mouse warping. */ -void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); - void -x_set_mouse_position (struct frame *f, int x, int y) -{ - int pix_x, pix_y; - - pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; - pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; - - if (pix_x < 0) pix_x = 0; - if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); - - if (pix_y < 0) pix_y = 0; - if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); - - x_set_mouse_pixel_position (f, pix_x, pix_y); -} - -void -x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) { RECT rect; POINT pt; @@ -5830,7 +6216,9 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) void x_focus_frame (struct frame *f) { +#if 0 struct w32_display_info *dpyinfo = &one_w32_display_info; +#endif /* Give input focus to frame. */ block_input (); @@ -6139,7 +6527,8 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); - SetWindowLong (window, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f)); + SetWindowLong (window, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f)); + SetWindowLong (window, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f)); leave_crit (); } @@ -6163,8 +6552,40 @@ x_check_font (struct frame *f, struct font *font) #endif /* GLYPH_DEBUG */ +/* Show hourglass cursor on frame F. */ + +static void +w32_show_hourglass (struct frame *f) +{ + if (!menubar_in_use && !current_popup_menu) + { + struct w32_output *w32 = FRAME_X_OUTPUT (f); + + w32->hourglass_p = 1; + SetCursor (w32->hourglass_cursor); + } +} + +/* Hide hourglass cursor on frame F. */ + +static void +w32_hide_hourglass (struct frame *f) +{ + struct w32_output *w32 = FRAME_X_OUTPUT (f); + + w32->hourglass_p = 0; + SetCursor (w32->current_cursor); +} + +/* FIXME: old code did that, but I don't know why. Anyway, + this is used for non-GUI frames (see cancel_hourglass). */ + +void +w32_arrow_cursor (void) +{ + SetCursor (w32_load_cursor (IDC_ARROW)); +} - /*********************************************************************** Initialization ***********************************************************************/ @@ -6194,6 +6615,7 @@ w32_initialize_display_info (Lisp_Object display_name) dpyinfo->smallest_font_height = 1; dpyinfo->smallest_char_width = 1; dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW); + dpyinfo->horizontal_scroll_bar_cursor = w32_load_cursor (IDC_ARROW); /* TODO: dpyinfo->gray */ reset_mouse_highlight (&dpyinfo->mouse_highlight); @@ -6280,7 +6702,9 @@ static struct redisplay_interface w32_redisplay_interface = w32_draw_window_cursor, w32_draw_vertical_window_border, w32_draw_window_divider, - w32_shift_glyphs_for_insert + w32_shift_glyphs_for_insert, + w32_show_hourglass, + w32_hide_hourglass }; static void x_delete_terminal (struct terminal *term); @@ -6290,9 +6714,8 @@ w32_create_terminal (struct w32_display_info *dpyinfo) { struct terminal *terminal; - terminal = create_terminal (); + terminal = create_terminal (output_w32, &w32_redisplay_interface); - terminal->type = output_w32; terminal->display_info.w32 = dpyinfo; dpyinfo->terminal = terminal; @@ -6302,26 +6725,24 @@ w32_create_terminal (struct w32_display_info *dpyinfo) terminal->ins_del_lines_hook = x_ins_del_lines; terminal->delete_glyphs_hook = x_delete_glyphs; terminal->ring_bell_hook = w32_ring_bell; - terminal->reset_terminal_modes_hook = NULL; - terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = x_update_begin; terminal->update_end_hook = x_update_end; - terminal->set_terminal_window_hook = NULL; terminal->read_socket_hook = w32_read_socket; terminal->frame_up_to_date_hook = w32_frame_up_to_date; terminal->mouse_position_hook = w32_mouse_position; terminal->frame_rehighlight_hook = w32_frame_rehighlight; terminal->frame_raise_lower_hook = w32_frame_raise_lower; terminal->fullscreen_hook = w32fullscreen_hook; + terminal->menu_show_hook = w32_menu_show; + terminal->popup_dialog_hook = w32_popup_dialog; terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar; + terminal->set_horizontal_scroll_bar_hook = w32_set_horizontal_scroll_bar; terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars; terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar; terminal->judge_scroll_bars_hook = w32_judge_scroll_bars; - terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = x_delete_terminal; - - terminal->rif = &w32_redisplay_interface; + /* Other hooks are NULL by default. */ /* We don't yet support separate terminals on W32, so don't try to share keyboards between virtual terminals that are on the same physical @@ -6443,12 +6864,6 @@ x_delete_display (struct w32_display_info *dpyinfo) if (dpyinfo->palette) DeleteObject (dpyinfo->palette); } - /* Avoid freeing dpyinfo->w32_id_name more than once if emacs is - running as a daemon; see bug#17510. */ -#ifndef CYGWIN - xfree (dpyinfo->w32_id_name); -#endif - w32_reset_fringes (); } @@ -6500,7 +6915,6 @@ w32_initialize (void) &w32_use_visible_system_caret, 0)) w32_use_visible_system_caret = 0; - last_tool_bar_item = -1; any_help_event_p = 0; /* Initialize input mode: interrupt_input off, no flow control, allow @@ -6555,13 +6969,16 @@ w32_initialize (void) #undef LOAD_PROC - /* Ensure scrollbar handle is at least 5 pixels. */ + /* Ensure scrollbar handles are at least 5 pixels. */ vertical_scroll_bar_min_handle = 5; + horizontal_scroll_bar_min_handle = 5; /* For either kind of scroll bar, take account of the arrows; these effectively form the border of the main scroll bar range. */ vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border = GetSystemMetrics (SM_CYVSCROLL); + horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border + = GetSystemMetrics (SM_CYHSCROLL); } } diff --git a/src/w32term.h b/src/w32term.h index e3b65f0ffaf..fb37550100e 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -22,6 +22,22 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "frame.h" #include "atimer.h" +/* Stack alignment stuff. Every CALLBACK function should have the + ALIGN_STACK attribute if it manipulates Lisp objects, because + Windows x86 32-bit ABI only guarantees 4-byte stack alignment, and + that is what we will get when a Windows function calls us. The + ALIGN_STACK attribute forces GCC to emit a preamble code to + re-align the stack at function entry. Further details about this + can be found in http://www.peterstock.co.uk/games/mingw_sse/. */ +#ifdef __GNUC__ +# if USE_STACK_LISP_OBJECTS && !defined _WIN64 && !defined __x86_64__ \ + && __GNUC__ + (__GNUC_MINOR__ > 1) >= 5 +# define ALIGN_STACK __attribute__((force_align_arg_pointer)) +# else +# define ALIGN_STACK +# endif /* USE_STACK_LISP_OBJECTS */ +#endif + #define BLACK_PIX_DEFAULT(f) PALETTERGB(0,0,0) #define WHITE_PIX_DEFAULT(f) PALETTERGB(255,255,255) @@ -99,6 +115,9 @@ struct w32_display_info /* The cursor to use for vertical scroll bars. */ Cursor vertical_scroll_bar_cursor; + /* The cursor to use for horizontal scroll bars. */ + Cursor horizontal_scroll_bar_cursor; + /* Resource data base */ XrmDatabase xrdb; @@ -194,12 +213,19 @@ struct w32_display_info /* Time of last mouse movement. */ Time last_mouse_movement_time; + + /* Value returned by last call of ShowCursor. */ + int cursor_display_counter; }; /* This is a chain of structures for all the displays currently in use. */ extern struct w32_display_info *x_display_list; extern struct w32_display_info one_w32_display_info; +/* These 2 are set by w32fns.c and examined in w32term.c. */ +extern HMENU current_popup_menu; +extern int menubar_in_use; + extern struct frame *x_window_to_frame (struct w32_display_info *, HWND); struct w32_display_info *x_display_info_for_name (Lisp_Object); @@ -219,8 +245,6 @@ extern void x_set_window_size (struct frame *f, int change_grav, extern int x_display_pixel_height (struct w32_display_info *); extern int x_display_pixel_width (struct w32_display_info *); extern Lisp_Object x_get_focus_frame (struct frame *); -extern void x_set_mouse_position (struct frame *f, int h, int v); -extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); extern void x_make_frame_visible (struct frame *f); extern void x_make_frame_invisible (struct frame *f); extern void x_iconify_frame (struct frame *f); @@ -229,6 +253,9 @@ extern void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval); +extern void x_set_internal_border_width (struct frame *f, + Lisp_Object value, + Lisp_Object oldval); extern void x_activate_menubar (struct frame *); extern int x_bitmap_icon (struct frame *, Lisp_Object); extern void initialize_frame_menubar (struct frame *); @@ -449,6 +476,9 @@ struct scroll_bar { place where the user grabbed it. If the handle isn't currently being dragged, this is Qnil. */ int dragging; + + /* true if the scroll bar is horizontal. */ + bool horizontal; }; /* Turning a lisp vector value into a pointer to a struct scroll_bar. */ @@ -482,9 +512,9 @@ struct scroll_bar { /* Return the inside width of a vertical scroll bar, given the outside width. */ -#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \ - ((width) \ - - VERTICAL_SCROLL_BAR_LEFT_BORDER \ +#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \ + ((width) \ + - VERTICAL_SCROLL_BAR_LEFT_BORDER \ - VERTICAL_SCROLL_BAR_RIGHT_BORDER) /* Return the length of the rectangle within which the top of the @@ -494,14 +524,36 @@ struct scroll_bar { This is the real range of motion for the scroll bar, so when we're scaling buffer positions to scroll bar positions, we use this, not VERTICAL_SCROLL_BAR_INSIDE_HEIGHT. */ -#define VERTICAL_SCROLL_BAR_TOP_RANGE(f,height) \ +#define VERTICAL_SCROLL_BAR_TOP_RANGE(f,height) \ (VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, height) - VERTICAL_SCROLL_BAR_MIN_HANDLE) /* Return the inside height of vertical scroll bar, given the outside height. See VERTICAL_SCROLL_BAR_TOP_RANGE too. */ -#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \ +#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \ ((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER) +/* Return the inside height of a horizontal scroll bar, given the + outside height. */ +#define HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \ + ((height) \ + - HORIZONTAL_SCROLL_BAR_TOP_BORDER \ + - HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER) + +/* Return the length of the rectangle within which the left of the + handle must stay. This isn't equivalent to the inside width, + because the scroll bar handle has a minimum width. + + This is the real range of motion for the scroll bar, so when we're + scaling buffer positions to scroll bar positions, we use this, not + HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH. */ +#define HORIZONTAL_SCROLL_BAR_LEFT_RANGE(f,width) \ + (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH (f, width) - HORIZONTAL_SCROLL_BAR_MIN_HANDLE) + +/* Return the inside width of horizontal scroll bar, given the outside + width. See HORIZONTAL_SCROLL_BAR_LEFT_RANGE too. */ +#define HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \ + ((width) - HORIZONTAL_SCROLL_BAR_LEFT_BORDER - HORIZONTAL_SCROLL_BAR_RIGHT_BORDER) + /* Border widths for scroll bars. @@ -519,8 +571,14 @@ struct scroll_bar { #define VERTICAL_SCROLL_BAR_TOP_BORDER (vertical_scroll_bar_top_border) #define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (vertical_scroll_bar_bottom_border) +#define HORIZONTAL_SCROLL_BAR_LEFT_BORDER (horizontal_scroll_bar_left_border) +#define HORIZONTAL_SCROLL_BAR_RIGHT_BORDER (horizontal_scroll_bar_right_border) +#define HORIZONTAL_SCROLL_BAR_TOP_BORDER (0) +#define HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER (0) + /* Minimum lengths for scroll bar handles, in pixels. */ #define VERTICAL_SCROLL_BAR_MIN_HANDLE (vertical_scroll_bar_min_handle) +#define HORIZONTAL_SCROLL_BAR_MIN_HANDLE (horizontal_scroll_bar_min_handle) struct frame; /* from frame.h */ @@ -582,35 +640,38 @@ do { \ #define WM_EMACS_KILL (WM_EMACS_START + 0) #define WM_EMACS_CREATEWINDOW (WM_EMACS_START + 1) #define WM_EMACS_DONE (WM_EMACS_START + 2) -#define WM_EMACS_CREATESCROLLBAR (WM_EMACS_START + 3) -#define WM_EMACS_SHOWWINDOW (WM_EMACS_START + 4) -#define WM_EMACS_SETWINDOWPOS (WM_EMACS_START + 5) -#define WM_EMACS_DESTROYWINDOW (WM_EMACS_START + 6) -#define WM_EMACS_TRACKPOPUPMENU (WM_EMACS_START + 7) -#define WM_EMACS_SETFOCUS (WM_EMACS_START + 8) -#define WM_EMACS_SETFOREGROUND (WM_EMACS_START + 9) -#define WM_EMACS_SETLOCALE (WM_EMACS_START + 10) -#define WM_EMACS_SETKEYBOARDLAYOUT (WM_EMACS_START + 11) -#define WM_EMACS_REGISTER_HOT_KEY (WM_EMACS_START + 12) -#define WM_EMACS_UNREGISTER_HOT_KEY (WM_EMACS_START + 13) -#define WM_EMACS_TOGGLE_LOCK_KEY (WM_EMACS_START + 14) -#define WM_EMACS_TRACK_CARET (WM_EMACS_START + 15) -#define WM_EMACS_DESTROY_CARET (WM_EMACS_START + 16) -#define WM_EMACS_SHOW_CARET (WM_EMACS_START + 17) -#define WM_EMACS_HIDE_CARET (WM_EMACS_START + 18) -#define WM_EMACS_SETCURSOR (WM_EMACS_START + 19) -#define WM_EMACS_PAINT (WM_EMACS_START + 20) -#define WM_EMACS_BRINGTOTOP (WM_EMACS_START + 21) -#define WM_EMACS_INPUT_READY (WM_EMACS_START + 22) -#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 23) -#define WM_EMACS_END (WM_EMACS_START + 24) +#define WM_EMACS_CREATEVSCROLLBAR (WM_EMACS_START + 3) +#define WM_EMACS_CREATEHSCROLLBAR (WM_EMACS_START + 4) +#define WM_EMACS_SHOWWINDOW (WM_EMACS_START + 5) +#define WM_EMACS_SETWINDOWPOS (WM_EMACS_START + 6) +#define WM_EMACS_DESTROYWINDOW (WM_EMACS_START + 7) +#define WM_EMACS_TRACKPOPUPMENU (WM_EMACS_START + 8) +#define WM_EMACS_SETFOCUS (WM_EMACS_START + 9) +#define WM_EMACS_SETFOREGROUND (WM_EMACS_START + 10) +#define WM_EMACS_SETLOCALE (WM_EMACS_START + 11) +#define WM_EMACS_SETKEYBOARDLAYOUT (WM_EMACS_START + 12) +#define WM_EMACS_REGISTER_HOT_KEY (WM_EMACS_START + 13) +#define WM_EMACS_UNREGISTER_HOT_KEY (WM_EMACS_START + 14) +#define WM_EMACS_TOGGLE_LOCK_KEY (WM_EMACS_START + 15) +#define WM_EMACS_TRACK_CARET (WM_EMACS_START + 16) +#define WM_EMACS_DESTROY_CARET (WM_EMACS_START + 17) +#define WM_EMACS_SHOW_CARET (WM_EMACS_START + 18) +#define WM_EMACS_HIDE_CARET (WM_EMACS_START + 19) +#define WM_EMACS_SETCURSOR (WM_EMACS_START + 20) +#define WM_EMACS_SHOWCURSOR (WM_EMACS_START + 21) +#define WM_EMACS_PAINT (WM_EMACS_START + 22) +#define WM_EMACS_BRINGTOTOP (WM_EMACS_START + 23) +#define WM_EMACS_INPUT_READY (WM_EMACS_START + 24) +#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 25) +#define WM_EMACS_END (WM_EMACS_START + 26) #define WND_FONTWIDTH_INDEX (0) #define WND_LINEHEIGHT_INDEX (4) #define WND_BORDER_INDEX (8) -#define WND_SCROLLBAR_INDEX (12) -#define WND_BACKGROUND_INDEX (16) -#define WND_LAST_INDEX (20) +#define WND_VSCROLLBAR_INDEX (12) +#define WND_HSCROLLBAR_INDEX (16) +#define WND_BACKGROUND_INDEX (20) +#define WND_LAST_INDEX (24) #define WND_EXTRA_BYTES (WND_LAST_INDEX) @@ -782,6 +843,7 @@ typedef char guichar_t; #define GUI_SDATA(x) ((guichar_t*) SDATA (x)) extern Lisp_Object w32_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); +extern void w32_arrow_cursor (void); extern void syms_of_w32term (void); extern void syms_of_w32menu (void); diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index 5bb444f519a..1c7b256988c 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -52,9 +52,9 @@ extern Lisp_Object Quniscribe; extern Lisp_Object Qopentype; /* EnumFontFamiliesEx callback. */ -static int CALLBACK add_opentype_font_name_to_list (ENUMLOGFONTEX *, - NEWTEXTMETRICEX *, - DWORD, LPARAM); +static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *, + NEWTEXTMETRICEX *, + DWORD, LPARAM); /* Used by uniscribe_otf_capability. */ static Lisp_Object otf_features (HDC context, char *table); @@ -127,8 +127,6 @@ uniscribe_open (struct frame *f, Lisp_Object font_entity, int pixel_size) /* Uniscribe backend uses glyph indices. */ uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX; - /* Mark the format as opentype */ - uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype; uniscribe_font->w32_font.font.driver = &uniscribe_font_driver; return font_object; @@ -593,8 +591,8 @@ uniscribe_encode_char (struct font *font, int c) Lisp_Object uniscribe_get_cache (Lisp_Object frame); void uniscribe_free_entity (Lisp_Object font_entity); int uniscribe_has_char (Lisp_Object entity, int c); - int uniscribe_text_extents (struct font *font, unsigned *code, - int nglyphs, struct font_metrics *metrics); + void uniscribe_text_extents (struct font *font, unsigned *code, + int nglyphs, struct font_metrics *metrics); int uniscribe_draw (struct glyph_string *s, int from, int to, int x, int y, int with_background); @@ -604,8 +602,6 @@ uniscribe_encode_char (struct font *font, int c) int uniscribe_get_bitmap (struct font *font, unsigned code, struct font_bitmap *bitmap, int bits_per_pixel); void uniscribe_free_bitmap (struct font *font, struct font_bitmap *bitmap); - void * uniscribe_get_outline (struct font *font, unsigned code); - void uniscribe_free_outline (struct font *font, void *outline); int uniscribe_anchor_point (struct font *font, unsigned code, int index, int *x, int *y); int uniscribe_start_for_frame (struct frame *f); @@ -617,7 +613,7 @@ uniscribe_encode_char (struct font *font, int c) /* Callback function for EnumFontFamiliesEx. Adds the name of opentype fonts to a Lisp list (passed in as the lParam arg). */ -static int CALLBACK +static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *logical_font, NEWTEXTMETRICEX *physical_font, DWORD font_type, LPARAM list_object) @@ -981,8 +977,6 @@ struct font_driver uniscribe_font_driver = w32font_draw, NULL, /* get_bitmap */ NULL, /* free_bitmap */ - NULL, /* get_outline */ - NULL, /* free_outline */ NULL, /* anchor_point */ uniscribe_otf_capability, /* Defined so (font-get FONTOBJ :otf) works. */ NULL, /* otf_drive - use shape instead. */ diff --git a/src/widget.c b/src/widget.c index bd0fe826e68..baa6a2ab917 100644 --- a/src/widget.c +++ b/src/widget.c @@ -53,30 +53,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "character.h" #include "font.h" -/* This sucks: this is the first default that x-faces.el tries. This won't - be used unless neither the "Emacs.EmacsFrame" resource nor the - "Emacs.EmacsFrame" resource is set; the frame - may have the wrong default size if this font doesn't exist, but some other - font that x-faces.el does. The workaround is to specify some font in the - resource database; I don't know a solution other than duplicating the font- - searching code from x-faces.el in this file. - - This also means that if "Emacs.EmacsFrame" is specified as a non- - existent font, then Xt is going to substitute "XtDefaultFont" for it, - which is a different size than this one. The solution for this is to - make x-faces.el try to use XtDefaultFont. The problem with that is that - XtDefaultFont is almost certainly variable-width. - - #### Perhaps we could have this code explicitly set XtDefaultFont to this? - */ -#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*" - static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2); static void EmacsFrameDestroy (Widget widget); static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs); static void EmacsFrameResize (Widget widget); -static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2); static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result); @@ -102,8 +83,6 @@ static XtResource resources[] = { offset (internal_border_width), XtRImmediate, (XtPointer)4}, {XtNinterline, XtCInterline, XtRInt, sizeof (int), offset (interline), XtRImmediate, (XtPointer)0}, - {XtNfont, XtCFont, XtRFontStruct, sizeof (struct font *), - offset (font),XtRString, DEFAULT_FACE_FONT}, {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), offset (foreground_pixel), XtRString, "XtDefaultForeground"}, {XtNcursorColor, XtCForeground, XtRPixel, sizeof (Pixel), @@ -157,7 +136,10 @@ static EmacsFrameClassRec emacsFrameClassRec = { /* destroy */ EmacsFrameDestroy, /* resize */ EmacsFrameResize, /* expose */ XtInheritExpose, - /* set_values */ EmacsFrameSetValues, + + /* Emacs never does XtSetvalues on this widget, so we have no code + for it. */ + /* set_values */ 0, /* Not supported */ /* set_values_hook */ 0, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ 0, @@ -404,7 +386,6 @@ set_frame_size (EmacsFrame ew) } #endif /* 0 */ { - struct frame *f = ew->emacs_frame.frame; Dimension pixel_width, pixel_height; /* Take into account the size of the scrollbar. Always use the @@ -413,8 +394,6 @@ set_frame_size (EmacsFrame ew) frame's character width which is bad for vertically split windows. */ - compute_fringe_widths (f, 0); - #if 0 /* This can run Lisp code, and it is dangerous to give out the frame to Lisp code before it officially exists. This is handled in Fx_create_frame so not needed here. */ @@ -472,10 +451,6 @@ update_wm_hints (EmacsFrame ew) /* This happens when the frame is just created. */ if (! wmshell) return; -#if 0 - check_frame_size (ew->emacs_frame.frame, &min_cols, &min_rows, 0); -#endif - pixel_to_char_size (ew, ew->core.width, ew->core.height, &char_width, &char_height); char_to_pixel_size (ew, char_width, char_height, @@ -509,91 +484,6 @@ widget_update_wm_size_hints (Widget widget) update_wm_hints (ew); } -static char setup_frame_cursor_bits[] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void -setup_frame_gcs (EmacsFrame ew) -{ - XGCValues gc_values; - struct frame* s = ew->emacs_frame.frame; - Pixmap blank_stipple, blank_tile; - unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures - | GCStipple | GCTile); - Lisp_Object font; - - XSETFONT (font, ew->emacs_frame.font); - font = Ffont_xlfd_name (font, Qnil); - if (STRINGP (font)) - { - XFontStruct *xfont = XLoadQueryFont (FRAME_DISPLAY_INFO (s)->display, - SSDATA (font)); - if (xfont) - { - gc_values.font = xfont->fid; - valuemask |= GCFont; - } - } - - /* We have to initialize all of our GCs to have a stipple/tile, otherwise - XGetGCValues returns uninitialized data when we query the stipple - (instead of None or something sensible) and it makes things hard. - - This should be fixed for real by not querying the GCs but instead having - some GC-based cache instead of the current face-based cache which doesn't - effectively cache all of the GC settings we need to use. - */ - - blank_stipple - = XCreateBitmapFromData (XtDisplay (ew), - RootWindowOfScreen (XtScreen (ew)), - setup_frame_cursor_bits, 2, 2); - - /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should - never actually get used as a background tile! - */ - blank_tile - = XCreatePixmapFromBitmapData (XtDisplay (ew), - RootWindowOfScreen (XtScreen (ew)), - setup_frame_cursor_bits, 2, 2, - 0, 1, ew->core.depth); - - /* Normal video */ - gc_values.foreground = ew->emacs_frame.foreground_pixel; - gc_values.background = ew->core.background_pixel; - gc_values.graphics_exposures = False; - gc_values.stipple = blank_stipple; - gc_values.tile = blank_tile; - XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc, - valuemask, &gc_values); - - /* Reverse video style. */ - gc_values.foreground = ew->core.background_pixel; - gc_values.background = ew->emacs_frame.foreground_pixel; - gc_values.graphics_exposures = False; - gc_values.stipple = blank_stipple; - gc_values.tile = blank_tile; - XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc, - valuemask, &gc_values); - - /* Cursor has to have an empty stipple. */ - gc_values.foreground = ew->core.background_pixel; - gc_values.background = ew->emacs_frame.cursor_color; - gc_values.graphics_exposures = False; - gc_values.tile = blank_tile; - gc_values.stipple - = XCreateBitmapFromData (XtDisplay (ew), - RootWindowOfScreen (XtScreen (ew)), - setup_frame_cursor_bits, 16, 16); - XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc, - valuemask, &gc_values); -} - static void update_various_frame_slots (EmacsFrame ew) { @@ -621,7 +511,6 @@ update_from_various_frame_slots (EmacsFrame ew) ew->core.width = FRAME_PIXEL_WIDTH (f); ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f); ew->emacs_frame.internal_border_width = f->internal_border_width; - ew->emacs_frame.font = x->font; ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f); ew->emacs_frame.cursor_color = x->cursor_pixel; ew->core.border_pixel = x->border_pixel; @@ -719,80 +608,6 @@ EmacsFrameResize (Widget widget) } } -static Boolean -EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2) -{ - EmacsFrame cur = (EmacsFrame)cur_widget; - EmacsFrame new = (EmacsFrame)new_widget; - - Boolean needs_a_refresh = False; - Boolean has_to_recompute_size; - Boolean has_to_recompute_gcs; - Boolean has_to_update_hints; - - int char_width, char_height; - Dimension pixel_width; - Dimension pixel_height; - - /* AFAIK, this function is never called. -- Jan D, Oct 2009. */ - has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font - || (cur->emacs_frame.foreground_pixel - != new->emacs_frame.foreground_pixel) - || (cur->core.background_pixel - != new->core.background_pixel) - ); - - has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font - && cur->core.width == new->core.width - && cur->core.height == new->core.height); - - has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font); - - if (has_to_recompute_gcs) - { - setup_frame_gcs (new); - needs_a_refresh = True; - } - - if (has_to_recompute_size) - { - /* Don't do this pixelwise, hopefully. */ - pixel_width = new->core.width; - pixel_height = new->core.height; - pixel_to_char_size (new, pixel_width, pixel_height, &char_width, - &char_height); - char_to_pixel_size (new, char_width, char_height, &pixel_width, - &pixel_height); - new->core.width = pixel_width; - new->core.height = pixel_height; - - change_frame_size (new->emacs_frame.frame, char_width, char_height, - 1, 0, 0, 0); - needs_a_refresh = True; - } - - if (has_to_update_hints) - update_wm_hints (new); - - update_various_frame_slots (new); - - /* #### This doesn't work, I haven't been able to find ANY kludge that - will let (x-create-frame '((iconic . t))) work. It seems that changes - to wm_shell's iconic slot have no effect after it has been realized, - and calling XIconifyWindow doesn't work either (even though the window - has been created.) Perhaps there is some property we could smash - directly, but I'm sick of this for now. - */ - if (cur->emacs_frame.iconic != new->emacs_frame.iconic) - { - Widget wmshell = get_wm_shell ((Widget) cur); - XtVaSetValues (wmshell, XtNiconic, - (XtArgVal) new->emacs_frame.iconic, NULL); - } - - return needs_a_refresh; -} - static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result) { @@ -829,7 +644,8 @@ EmacsFrameSetCharSize (Widget widget, int columns, int rows) EmacsFrame ew = (EmacsFrame) widget; struct frame *f = ew->emacs_frame.frame; - x_set_window_size (f, 0, columns, rows, 0); + if (!frame_inhibit_resize (f, 0) && !frame_inhibit_resize (f, 1)) + x_set_window_size (f, 0, columns, rows, 0); } diff --git a/src/widgetprv.h b/src/widgetprv.h index c0a5238743e..f5e2eb549a1 100644 --- a/src/widgetprv.h +++ b/src/widgetprv.h @@ -43,7 +43,6 @@ typedef struct { int internal_border_width; /* internal borders */ int interline; /* skips between lines */ - struct font* font; /* font */ Pixel foreground_pixel; /* foreground */ Pixel cursor_color; /* text cursor color */ diff --git a/src/window.c b/src/window.c index 2210d5bc868..0b0f2140a58 100644 --- a/src/window.c +++ b/src/window.c @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "buffer.h" #include "keyboard.h" #include "keymap.h" +#include "menu.h" #include "frame.h" #include "window.h" #include "commands.h" @@ -51,6 +52,7 @@ static Lisp_Object Qrecord_window_buffer; static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer; static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window; static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically; +static Lisp_Object Qwindow_sanitize_window_sizes; static Lisp_Object Qwindow_pixel_to_total; static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command; static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of; @@ -86,7 +88,7 @@ static struct window *set_window_fringes (struct window *, Lisp_Object, static struct window *set_window_margins (struct window *, Lisp_Object, Lisp_Object); static struct window *set_window_scroll_bars (struct window *, Lisp_Object, - Lisp_Object, Lisp_Object); + Lisp_Object, Lisp_Object, Lisp_Object); static void apply_window_adjustment (struct window *); /* This is the window in which the terminal's cursor should @@ -119,9 +121,6 @@ static Lisp_Object Qtemp_buffer_show_hook; /* Incremented for each window created. */ static int sequence_number; -/* Nonzero after init_window_once has finished. */ -static int window_initialized; - /* Hook to run when window config changes. */ static Lisp_Object Qwindow_configuration_change_hook; @@ -145,66 +144,85 @@ wset_combination_limit (struct window *w, Lisp_Object val) { w->combination_limit = val; } + static void wset_dedicated (struct window *w, Lisp_Object val) { w->dedicated = val; } + static void wset_display_table (struct window *w, Lisp_Object val) { w->display_table = val; } + static void wset_new_normal (struct window *w, Lisp_Object val) { w->new_normal = val; } + static void wset_new_total (struct window *w, Lisp_Object val) { w->new_total = val; } + static void wset_normal_cols (struct window *w, Lisp_Object val) { w->normal_cols = val; } + static void wset_normal_lines (struct window *w, Lisp_Object val) { w->normal_lines = val; } + static void wset_parent (struct window *w, Lisp_Object val) { w->parent = val; } + static void wset_pointm (struct window *w, Lisp_Object val) { w->pointm = val; } + +static void +wset_old_pointm (struct window *w, Lisp_Object val) +{ + w->old_pointm = val; +} + static void wset_start (struct window *w, Lisp_Object val) { w->start = val; } + static void wset_temslot (struct window *w, Lisp_Object val) { w->temslot = val; } + static void wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val) { w->vertical_scroll_bar_type = val; } + static void wset_window_parameters (struct window *w, Lisp_Object val) { w->window_parameters = val; } + static void wset_combination (struct window *w, bool horflag, Lisp_Object val) { @@ -905,6 +923,9 @@ window_body_height (struct window *w, bool pixelwise) { int height = (w->pixel_height - WINDOW_HEADER_LINE_HEIGHT (w) + - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w) + ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w) + : 0) - WINDOW_MODE_LINE_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w)); @@ -1025,6 +1046,15 @@ WINDOW must be a live window and defaults to the selected one. */) return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window)))); } +DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height, + Swindow_scroll_bar_height, 0, 1, 0, + doc: /* Return the height in pixels of WINDOW's horizontal scrollbar. +WINDOW must be a live window and defaults to the selected one. */) + (Lisp_Object window) +{ + return (make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window)))); +} + DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0, doc: /* Return the number of columns by which WINDOW is scrolled from left margin. WINDOW must be a live window and defaults to the selected one. */) @@ -1052,6 +1082,8 @@ set_window_hscroll (struct window *w, EMACS_INT hscroll) XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1; w->hscroll = new_hscroll; + w->suspend_auto_hscroll = 1; + return make_number (new_hscroll); } @@ -1201,12 +1233,16 @@ display margins, fringes, header line, and/or mode line. */) return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w) + WINDOW_LEFT_MARGIN_COLS (w) - + WINDOW_LEFT_FRINGE_COLS (w)), + + ((WINDOW_LEFT_FRINGE_WIDTH (w) + + WINDOW_FRAME_COLUMN_WIDTH (w) - 1) + / WINDOW_FRAME_COLUMN_WIDTH (w))), (WINDOW_TOP_EDGE_LINE (w) + WINDOW_HEADER_LINE_LINES (w)), (WINDOW_BOX_RIGHT_EDGE_COL (w) - WINDOW_RIGHT_MARGIN_COLS (w) - - WINDOW_RIGHT_FRINGE_COLS (w)), + - ((WINDOW_RIGHT_FRINGE_WIDTH (w) + + WINDOW_FRAME_COLUMN_WIDTH (w) - 1) + / WINDOW_FRAME_COLUMN_WIDTH (w))), (WINDOW_BOTTOM_EDGE_LINE (w) - WINDOW_MODE_LINE_LINES (w))); } @@ -1320,6 +1356,17 @@ coordinates_in_window (register struct window *w, int x, int y) && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w) && x <= right_x) return ON_RIGHT_DIVIDER; + /* On the horizontal scroll bar? (Including the empty space at its + right!) */ + else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w) + && y >= (bottom_y + - WINDOW_SCROLL_BAR_AREA_HEIGHT (w) + - CURRENT_MODE_LINE_HEIGHT (w) + - WINDOW_BOTTOM_DIVIDER_WIDTH (w)) + && y <= (bottom_y + - CURRENT_MODE_LINE_HEIGHT (w) + - WINDOW_BOTTOM_DIVIDER_WIDTH (w)))) + return ON_HORIZONTAL_SCROLL_BAR; /* On the mode or header line? */ else if ((WINDOW_WANTS_MODELINE_P (w) && y >= (bottom_y @@ -1363,7 +1410,7 @@ coordinates_in_window (register struct window *w, int x, int y) /* Outside any interesting column? */ if (x < left_x || x > right_x) - return ON_SCROLL_BAR; + return ON_VERTICAL_SCROLL_BAR; lmargin_width = window_box_width (w, LEFT_MARGIN_AREA); rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA); @@ -1527,10 +1574,13 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\ case ON_RIGHT_MARGIN: return Qright_margin; - case ON_SCROLL_BAR: + case ON_VERTICAL_SCROLL_BAR: /* Historically we are supposed to return nil in this case. */ return Qnil; + case ON_HORIZONTAL_SCROLL_BAR: + return Qnil; + case ON_RIGHT_DIVIDER: return Qright_divider; @@ -1671,6 +1721,14 @@ correct to return the top-level value of `point', outside of any return Fmarker_position (w->pointm); } +DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0, + doc: /* Return old value of point in WINDOW. +WINDOW must be a live window and defaults to the selected one. */) + (Lisp_Object window) +{ + return Fmarker_position (decode_live_window (window)->old_pointm); +} + DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0, doc: /* Return position at which display currently starts in WINDOW. WINDOW must be a live window and defaults to the selected one. @@ -2949,6 +3007,7 @@ selected frame and no others. */) return Qnil; } + static Lisp_Object resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise) { @@ -2956,10 +3015,17 @@ resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizonta } +Lisp_Object +sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal) +{ + return call2 (Qwindow_sanitize_window_sizes, frame, horizontal); +} + + static Lisp_Object window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal) { - return call2(Qwindow_pixel_to_total, frame, horizontal); + return call2 (Qwindow_pixel_to_total, frame, horizontal); } @@ -3238,89 +3304,6 @@ replace_buffer_in_windows_safely (Lisp_Object buffer) window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame); } } - -/* If *HEIGHT or *WIDTH are too small a size for FRAME, set them to the - minimum allowable size. PIXELWISE means interpret these as pixel - sizes. */ - -void -check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise) -{ - /* For height, we have to see: - how many windows the frame has at minimum (one or two), - and whether it has a menu bar or other special stuff at the top. */ - if (pixelwise) - { - int min_height = MIN_SAFE_WINDOW_HEIGHT * FRAME_LINE_HEIGHT (frame); - int min_width = MIN_SAFE_WINDOW_WIDTH * FRAME_COLUMN_WIDTH (frame); - - if (!FRAME_MINIBUF_ONLY_P (frame) && FRAME_HAS_MINIBUF_P (frame)) - min_height = 2 * min_height; - - min_height += FRAME_TOP_MARGIN_HEIGHT (frame); - min_height += FRAME_INTERNAL_BORDER_WIDTH (frame); - - if (*height < min_height) - *height = min_height; - if (*width < min_width) - *width = min_width; - } - else - { - int min_height - = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame)) - ? MIN_SAFE_WINDOW_HEIGHT - : 2 * MIN_SAFE_WINDOW_HEIGHT); - - if (FRAME_TOP_MARGIN (frame) > 0) - min_height += FRAME_TOP_MARGIN (frame); - - if (*height < min_height) - *height = min_height; - if (*width < MIN_SAFE_WINDOW_WIDTH) - *width = MIN_SAFE_WINDOW_WIDTH; - } -} - -/* Adjust the margins of window W if text area is too small. - Return 1 if window width is ok after adjustment; 0 if window - is still too narrow. */ - -static int -adjust_window_margins (struct window *w) -{ - int box_width = (WINDOW_PIXEL_WIDTH (w) - - WINDOW_FRINGES_WIDTH (w) - - WINDOW_SCROLL_BAR_AREA_WIDTH (w)); - int margin_width = WINDOW_MARGINS_WIDTH (w); - - if (box_width - margin_width >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w)) - return 1; - - if (margin_width < 0 || box_width < MIN_SAFE_WINDOW_PIXEL_WIDTH (w)) - return 0; - else - /* Window's text area is too narrow, but reducing the window - margins will fix that. */ - { - int unit = WINDOW_FRAME_COLUMN_WIDTH (w); - - margin_width = box_width - MIN_SAFE_WINDOW_PIXEL_WIDTH (w); - - if (WINDOW_RIGHT_MARGIN_WIDTH (w) > 0) - { - if (WINDOW_LEFT_MARGIN_WIDTH (w) > 0) - w->left_margin_cols = w->right_margin_cols = - margin_width / (2 * unit); - else - w->right_margin_cols = margin_width / unit; - } - else - w->left_margin_cols = margin_width / unit; - - return 1; - } -} /* The following three routines are needed for running a window's configuration change hook. */ @@ -3354,7 +3337,7 @@ run_window_configuration_change_hook (struct frame *f) = Fdefault_value (Qwindow_configuration_change_hook); XSETFRAME (frame, f); - if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code)) + if (NILP (Vrun_hooks) || !(f->official)) return; /* Use the right buffer. Matters when running the local hooks. */ @@ -3449,17 +3432,21 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, w->last_cursor_vpos = 0; if (!(keep_margins_p && samebuf)) - { /* If we're not actually changing the buffer, don't reset hscroll and - vscroll. This case happens for example when called from + { /* If we're not actually changing the buffer, don't reset hscroll + and vscroll. This case happens for example when called from change_frame_size_1, where we use a dummy call to - Fset_window_buffer on the frame's selected window (and no other) - just in order to run window-configuration-change-hook. - Resetting hscroll and vscroll here is problematic for things like - image-mode and doc-view-mode since it resets the image's position - whenever we resize the frame. */ - w->hscroll = w->min_hscroll = 0; + Fset_window_buffer on the frame's selected window (and no + other) just in order to run window-configuration-change-hook + (no longer true since change_frame_size_1 directly calls + run_window_configuration_change_hook). Resetting hscroll and + vscroll here is problematic for things like image-mode and + doc-view-mode since it resets the image's position whenever we + resize the frame. */ + w->hscroll = w->min_hscroll = w->hscroll_whole = 0; + w->suspend_auto_hscroll = 0; w->vscroll = 0; set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b)); + set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b)); set_marker_restricted (w->start, make_number (b->last_window_start), buffer); @@ -3471,16 +3458,13 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, wset_redisplay (w); w->update_mode_line = true; - /* We must select BUFFER for running the window-scroll-functions. */ - /* We can't check ! NILP (Vwindow_scroll_functions) here - because that might itself be a local variable. */ - if (window_initialized) - { - record_unwind_current_buffer (); - Fset_buffer (buffer); - } + /* We must select BUFFER to run the window-scroll-functions and to look up + the buffer-local value of Vwindow_point_insertion_type. */ + record_unwind_current_buffer (); + Fset_buffer (buffer); XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type); + XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type); if (!keep_margins_p) { @@ -3489,7 +3473,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, BVAR (b, right_fringe_width), BVAR (b, fringes_outside_margins)); set_window_scroll_bars (w, BVAR (b, scroll_bar_width), - BVAR (b, vertical_scroll_bar_type), Qnil); + BVAR (b, vertical_scroll_bar_type), + BVAR (b, scroll_bar_height), + BVAR (b, horizontal_scroll_bar_type)); set_window_margins (w, BVAR (b, left_margin_cols), BVAR (b, right_margin_cols)); apply_window_adjustment (w); @@ -3635,10 +3621,11 @@ temp_output_buffer_show (register Lisp_Object buf) Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window))); Vminibuf_scroll_window = window; w = XWINDOW (window); - w->hscroll = 0; - w->min_hscroll = 0; + w->hscroll = w->min_hscroll = w->hscroll_whole = 0; + w->suspend_auto_hscroll = 0; set_marker_restricted_both (w->start, buf, BEG, BEG); set_marker_restricted_both (w->pointm, buf, BEG, BEG); + set_marker_restricted_both (w->old_pointm, buf, BEG, BEG); /* Run temp-buffer-show-hook, with the chosen window selected and its buffer current. */ @@ -3690,6 +3677,7 @@ make_parent_window (Lisp_Object window, bool horflag) /* ...but now P becomes an internal window. */ wset_start (p, Qnil); wset_pointm (p, Qnil); + wset_old_pointm (p, Qnil); wset_buffer (p, Qnil); wset_combination (p, horflag, window); wset_combination_limit (p, Qnil); @@ -3713,7 +3701,9 @@ make_window (void) wset_new_pixel (w, make_number (0)); wset_start (w, Fmake_marker ()); wset_pointm (w, Fmake_marker ()); + wset_old_pointm (w, Fmake_marker ()); wset_vertical_scroll_bar_type (w, Qt); + wset_horizontal_scroll_bar_type (w, Qt); /* These Lisp fields are marked specially so they're not set to nil by allocate_window. */ wset_prev_buffers (w, Qnil); @@ -3730,8 +3720,8 @@ make_window (void) #endif w->sequence_number = ++sequence_number; w->scroll_bar_width = -1; + w->scroll_bar_height = -1; w->column_number_displayed = -1; - /* Reset window_list. */ Vwindow_list = Qnil; /* Return window. */ @@ -3992,11 +3982,8 @@ window_resize_apply (struct window *w, bool horflag) } } else - { - adjust_window_margins (w); - /* Bug#15957. */ - w->window_end_valid = 0; - } + /* Bug#15957. */ + w->window_end_valid = 0; } @@ -4161,6 +4148,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) /* old_size is the old size of the frame's root window. */ int old_size = horflag ? r->total_cols : r->total_lines; int old_pixel_size = horflag ? r->pixel_width : r->pixel_height; + int old_pixel_top = r->pixel_top; /* new_size is the new size of the frame's root window. */ int new_size, new_pixel_size; int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f); @@ -4175,7 +4163,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) new_pixel_size = max (horflag ? size : (size - - FRAME_TOP_MARGIN_HEIGHT (f) - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) ? FRAME_LINE_HEIGHT (f) : 0)), @@ -4187,7 +4174,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) new_size = max (horflag ? size : (size - - FRAME_TOP_MARGIN (f) - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) ? 1 : 0)), @@ -4198,7 +4184,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) r->top_line = FRAME_TOP_MARGIN (f); r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f); - if (new_pixel_size == old_pixel_size) + if (new_pixel_size == old_pixel_size + && r->pixel_top == old_pixel_top) ; else if (WINDOW_LEAF_P (r)) /* For a leaf root window just set the size. */ @@ -4240,6 +4227,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) { window_resize_apply (r, horflag); window_pixel_to_total (r->frame, horflag ? Qt : Qnil); +#if 0 /* Let's try without safe sizes and/or killing other windows. */ } else { @@ -4252,7 +4240,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) window_resize_apply (r, horflag); window_pixel_to_total (r->frame, horflag ? Qt : Qnil); } -#if 0 /* Let's try without killing other windows. */ else { /* We lost. Delete all windows but the frame's @@ -4456,7 +4443,9 @@ set correctly. See the code of `split-window' for how this is done. */) n->right_fringe_width = r->right_fringe_width; n->fringes_outside_margins = r->fringes_outside_margins; n->scroll_bar_width = r->scroll_bar_width; + n->scroll_bar_height = r->scroll_bar_height; wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type); + wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type); /* Directly assign orthogonal coordinates and sizes. */ if (horflag) @@ -4600,6 +4589,7 @@ Signal an error when WINDOW is the only window on its frame. */) { unshow_buffer (w); unchain_marker (XMARKER (w->pointm)); + unchain_marker (XMARKER (w->old_pointm)); unchain_marker (XMARKER (w->start)); wset_buffer (w, Qnil); } @@ -4861,6 +4851,7 @@ window_internal_height (struct window *w) return ht; } + /************************************************************************ Window Scrolling @@ -4911,6 +4902,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) void *itdata = NULL; int window_total_lines; int frame_line_height = default_line_pixel_height (w); + bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window), + Fwindow_old_point (window))); SET_TEXT_POS_FROM_MARKER (start, w->start); /* Scrolling a minibuffer window via scroll bar when the echo area @@ -4922,7 +4915,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) /* If PT is not visible in WINDOW, move back one half of the screen. Allow PT to be partially visible, otherwise something like (scroll-down 1) with PT in the line before - the partially visible one would recenter. */ + the partially visible one would recenter. */ if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos)) { @@ -4951,7 +4944,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) } else if (auto_window_vscroll_p) { - if (rtop || rbot) /* partially visible */ + if (rtop || rbot) /* Partially visible. */ { int px; int dy = frame_line_height; @@ -5039,6 +5032,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) { ptrdiff_t start_pos = IT_CHARPOS (it); int dy = frame_line_height; + dy = max ((window_box_height (w) - next_screen_context_lines * dy), dy) * n; @@ -5282,6 +5276,13 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) } } bidi_unshelve_cache (itdata, 0); + + if (adjust_old_pointm) + Fset_marker (w->old_pointm, + ((w == XWINDOW (selected_window)) + ? make_number (BUF_PT (XBUFFER (w->contents))) + : Fmarker_position (w->pointm)), + w->contents); } @@ -5306,6 +5307,8 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror) ptrdiff_t startpos = marker_position (w->start); ptrdiff_t startbyte = marker_byte_position (w->start); Lisp_Object original_pos = Qnil; + bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window), + Fwindow_old_point (window))); /* If scrolling screen-fulls, compute the number of lines to scroll from the window's height. */ @@ -5321,6 +5324,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror) struct position posit = *compute_motion (startpos, startbyte, 0, 0, 0, PT, ht, 0, -1, w->hscroll, 0, w); + window_scroll_preserve_vpos = posit.vpos; window_scroll_preserve_hpos = posit.hpos + w->hscroll; } @@ -5436,6 +5440,13 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror) else xsignal0 (Qend_of_buffer); } + + if (adjust_old_pointm) + Fset_marker (w->old_pointm, + ((w == XWINDOW (selected_window)) + ? make_number (BUF_PT (XBUFFER (w->contents))) + : Fmarker_position (w->pointm)), + w->contents); } @@ -5572,6 +5583,7 @@ specifies the window to scroll. This takes precedence over Fset_buffer (w->contents); SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm)); + SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm)); if (NILP (arg)) window_scroll (window, 1, 1, 1); @@ -5586,6 +5598,7 @@ specifies the window to scroll. This takes precedence over } set_marker_both (w->pointm, Qnil, PT, PT_BYTE); + set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE); unbind_to (count, Qnil); return Qnil; @@ -5611,6 +5624,8 @@ by this function. This happens in an interactive call. */) if (!NILP (set_minimum)) w->min_hscroll = w->hscroll; + w->suspend_auto_hscroll = 1; + return result; } @@ -5634,6 +5649,8 @@ by this function. This happens in an interactive call. */) if (!NILP (set_minimum)) w->min_hscroll = w->hscroll; + w->suspend_auto_hscroll = 1; + return result; } @@ -5724,14 +5741,16 @@ and redisplay normally--don't erase and redraw the frame. */) { struct window *w = XWINDOW (selected_window); struct buffer *buf = XBUFFER (w->contents); - struct buffer *obuf = current_buffer; bool center_p = 0; ptrdiff_t charpos, bytepos; EMACS_INT iarg IF_LINT (= 0); int this_scroll_margin; + if (buf != current_buffer) + error ("`recenter'ing a window that does not display current-buffer."); + /* If redisplay is suppressed due to an error, try again. */ - obuf->display_error_modiff = 0; + buf->display_error_modiff = 0; if (NILP (arg)) { @@ -5753,7 +5772,7 @@ and redisplay normally--don't erase and redraw the frame. */) center_p = 1; } - else if (CONSP (arg)) /* Just C-u. */ + else if (CONSP (arg)) /* Just C-u. */ center_p = 1; else { @@ -5762,12 +5781,10 @@ and redisplay normally--don't erase and redraw the frame. */) iarg = XINT (arg); } - set_buffer_internal (buf); - /* Do this after making BUF current in case scroll_margin is buffer-local. */ - this_scroll_margin = - max (0, min (scroll_margin, w->total_lines / 4)); + this_scroll_margin + = max (0, min (scroll_margin, w->total_lines / 4)); /* Handle centering on a graphical frame specially. Such frames can have variable-height lines and centering point on the basis of @@ -5815,7 +5832,7 @@ and redisplay normally--don't erase and redraw the frame. */) h -= it.current_y; else { - /* Last line has no newline */ + /* Last line has no newline. */ h -= line_bottom_y (&it); it.vpos++; } @@ -5894,44 +5911,55 @@ and redisplay normally--don't erase and redraw the frame. */) w->optional_new_start = 1; - w->start_at_line_beg = (bytepos == BEGV_BYTE || - FETCH_BYTE (bytepos - 1) == '\n'); + w->start_at_line_beg = (bytepos == BEGV_BYTE + || FETCH_BYTE (bytepos - 1) == '\n'); wset_redisplay (w); - set_buffer_internal (obuf); return Qnil; } DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width, - 0, 1, 0, + 0, 2, 0, doc: /* Return the width in columns of the text display area of WINDOW. WINDOW must be a live window and defaults to the selected one. The returned width does not include dividers, scrollbars, margins, fringes, nor any partial-width columns at the right of the text -area. */) - (Lisp_Object window) +area. + +Optional argument PIXELWISE non-nil, means to return the width in +pixels. */) + (Lisp_Object window, Lisp_Object pixelwise) { struct window *w = decode_live_window (window); - return make_number (window_box_width (w, TEXT_AREA) - / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))); + if (NILP (pixelwise)) + return make_number (window_box_width (w, TEXT_AREA) + / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))); + else + return make_number (window_box_width (w, TEXT_AREA)); } DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height, - 0, 1, 0, + 0, 2, 0, doc: /* Return the height in lines of the text display area of WINDOW. WINDOW must be a live window and defaults to the selected one. The returned height does not include dividers, the mode line, any header -line, nor any partial-height lines at the bottom of the text area. */) - (Lisp_Object window) +line, nor any partial-height lines at the bottom of the text area. + +Optional argument PIXELWISE non-nil, means to return the height in +pixels. */) + (Lisp_Object window, Lisp_Object pixelwise) { struct window *w = decode_live_window (window); - return make_number (window_box_height (w) - / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w))); + if (NILP (pixelwise)) + return make_number (window_box_height (w) + / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w))); + else + return make_number (window_box_height (w)); } DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line, @@ -6036,22 +6064,23 @@ struct save_window_data int frame_menu_bar_height, frame_tool_bar_height; }; -/* This is saved as a Lisp_Vector */ +/* This is saved as a Lisp_Vector. */ struct saved_window { struct vectorlike_header header; - Lisp_Object window, buffer, start, pointm, mark; + Lisp_Object window, buffer, start, pointm, old_pointm; Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; - Lisp_Object hscroll, min_hscroll; + Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; Lisp_Object parent, prev; Lisp_Object start_at_line_beg; Lisp_Object display_table; Lisp_Object left_margin_cols, right_margin_cols; Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins; Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated; + Lisp_Object scroll_bar_height, horizontal_scroll_bar_type; Lisp_Object combination_limit, window_parameters; }; @@ -6079,13 +6108,6 @@ DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_config return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame; } -/* From Chong's unwind_create_frame_1. */ -static void -unwind_change_frame (Lisp_Object val) -{ - inhibit_lisp_code = val; -} - DEFUN ("set-window-configuration", Fset_window_configuration, Sset_window_configuration, 1, 1, 0, doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION. @@ -6102,6 +6124,7 @@ the return value is nil. Otherwise the value is t. */) Lisp_Object frame; struct frame *f; ptrdiff_t old_point = -1; + USE_SAFE_ALLOCA; CHECK_WINDOW_CONFIGURATION (configuration); @@ -6165,19 +6188,6 @@ the return value is nil. Otherwise the value is t. */) int n_leaf_windows; ptrdiff_t k; int i, n; - ptrdiff_t count = SPECPDL_INDEX (); - /* If the frame has been resized since this window configuration was - made, we change the frame to the size specified in the - configuration, restore the configuration, and then resize it - back. We keep track of the prevailing height in these variables. */ - int previous_frame_text_height = FRAME_TEXT_HEIGHT (f); - int previous_frame_text_width = FRAME_TEXT_WIDTH (f); - /* int previous_frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f); */ - /* int previous_frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f); */ - /* int previous_frame_lines = FRAME_LINES (f); */ - /* int previous_frame_cols = FRAME_COLS (f); */ - int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f); - int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f); /* Don't do this within the main loop below: This may call Lisp code and is thus potentially unsafe while input is blocked. */ @@ -6194,36 +6204,12 @@ the return value is nil. Otherwise the value is t. */) call1 (Qrecord_window_buffer, window); } - /* Don't run lisp in the following segment since the frame is in a - completely inconsistent state. See Bug#16207. */ - record_unwind_protect (unwind_change_frame, inhibit_lisp_code); - inhibit_lisp_code = Qt; + /* Consider frame unofficial, temporarily. */ + f->official = false; /* The mouse highlighting code could get screwed up if it runs during this. */ block_input (); - if (data->frame_text_width != previous_frame_text_width - || data->frame_text_height != previous_frame_text_height) - change_frame_size (f, data->frame_text_width, - data->frame_text_height, 0, 0, 0, 1); - - if (data->frame_menu_bar_lines != previous_frame_menu_bar_lines) - { -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines), - make_number (0)); - else /* TTY or MSDOS */ -#endif - set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines), - make_number (0)); - } -#ifdef HAVE_WINDOW_SYSTEM - if (data->frame_tool_bar_lines != previous_frame_tool_bar_lines) - x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines), - make_number (0)); -#endif - /* "Swap out" point from the selected window's buffer into the window itself. (Normally the pointm of the selected window holds garbage.) We do this now, before @@ -6246,8 +6232,8 @@ the return value is nil. Otherwise the value is t. */) really like to do is to free only those matrices not reused below. */ root_window = XWINDOW (FRAME_ROOT_WINDOW (f)); - leaf_windows = alloca (count_windows (root_window) - * sizeof *leaf_windows); + int nwindows = count_windows (root_window); + SAFE_NALLOCA (leaf_windows, 1, nwindows); n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0); /* Kludge Alert! @@ -6302,7 +6288,9 @@ the return value is nil. Otherwise the value is t. */) wset_normal_cols (w, p->normal_cols); wset_normal_lines (w, p->normal_lines); w->hscroll = XFASTINT (p->hscroll); + w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll); w->min_hscroll = XFASTINT (p->min_hscroll); + w->hscroll_whole = XFASTINT (p->hscroll_whole); wset_display_table (w, p->display_table); w->left_margin_cols = XINT (p->left_margin_cols); w->right_margin_cols = XINT (p->right_margin_cols); @@ -6310,7 +6298,9 @@ the return value is nil. Otherwise the value is t. */) w->right_fringe_width = XINT (p->right_fringe_width); w->fringes_outside_margins = !NILP (p->fringes_outside_margins); w->scroll_bar_width = XINT (p->scroll_bar_width); + w->scroll_bar_height = XINT (p->scroll_bar_height); wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type); + wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type); wset_dedicated (w, p->dedicated); wset_combination_limit (w, p->combination_limit); /* Restore any window parameters that have been saved. @@ -6341,18 +6331,15 @@ the return value is nil. Otherwise the value is t. */) wset_buffer (w, p->buffer); w->start_at_line_beg = !NILP (p->start_at_line_beg); set_marker_restricted (w->start, p->start, w->contents); - set_marker_restricted (w->pointm, p->pointm, - w->contents); - Fset_marker (BVAR (XBUFFER (w->contents), mark), - p->mark, w->contents); - + set_marker_restricted (w->pointm, p->pointm, w->contents); + set_marker_restricted (w->old_pointm, p->old_pointm, w->contents); /* As documented in Fcurrent_window_configuration, don't restore the location of point in the buffer which was current when the window configuration was recorded. */ if (!EQ (p->buffer, new_current_buffer) && XBUFFER (p->buffer) == current_buffer) Fgoto_char (w->pointm); - } + } else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents))) /* Keep window's old buffer; make sure the markers are real. */ { @@ -6364,20 +6351,26 @@ the return value is nil. Otherwise the value is t. */) (w->pointm, w->contents, BUF_PT (XBUFFER (w->contents)), BUF_PT_BYTE (XBUFFER (w->contents))); + if (XMARKER (w->old_pointm)->buffer == 0) + set_marker_restricted_both + (w->old_pointm, w->contents, + BUF_PT (XBUFFER (w->contents)), + BUF_PT_BYTE (XBUFFER (w->contents))); w->start_at_line_beg = 1; } else if (!NILP (w->start)) /* Leaf window has no live buffer, get one. */ { /* Get the buffer via other_buffer_safely in order to - avoid showing an unimportant buffer and, if necessary, to - recreate *scratch* in the course (part of Juanma's bs-show - scenario from March 2011). */ + avoid showing an unimportant buffer and, if necessary, to + recreate *scratch* in the course (part of Juanma's bs-show + scenario from March 2011). */ wset_buffer (w, other_buffer_safely (Fcurrent_buffer ())); /* This will set the markers to beginning of visible range. */ set_marker_restricted_both (w->start, w->contents, 0, 0); set_marker_restricted_both (w->pointm, w->contents, 0, 0); + set_marker_restricted_both (w->old_pointm, w->contents, 0, 0); w->start_at_line_beg = 1; if (!NILP (w->dedicated)) /* Record this window as dead. */ @@ -6412,30 +6405,6 @@ the return value is nil. Otherwise the value is t. */) && FRAME_LIVE_P (XFRAME (data->focus_frame)))) Fredirect_frame_focus (frame, data->focus_frame); - /* Set the frame size to the value it had before this function. */ - if (previous_frame_text_width != FRAME_TEXT_WIDTH (f) - || previous_frame_text_height != FRAME_TEXT_HEIGHT (f)) - change_frame_size (f, previous_frame_text_width, - previous_frame_text_height, 0, 0, 0, 1); - - if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f)) - { -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - x_set_menu_bar_lines (f, - make_number (previous_frame_menu_bar_lines), - make_number (0)); - else /* TTY or MSDOS */ -#endif - set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines), - make_number (0)); - } -#ifdef HAVE_WINDOW_SYSTEM - if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f)) - x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines), - make_number (0)); -#endif - /* Now, free glyph matrices in windows that were not reused. */ for (i = n = 0; i < n_leaf_windows; ++i) { @@ -6445,9 +6414,13 @@ the return value is nil. Otherwise the value is t. */) ++n; } + /* Make frame official again and apply frame size changes if + needed. */ + f->official = true; + adjust_frame_size (f, -1, -1, 1, 0); + adjust_frame_glyphs (f); unblock_input (); - unbind_to (count, Qnil); /* Scan dead buffer windows. */ for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows)) @@ -6484,9 +6457,11 @@ the return value is nil. Otherwise the value is t. */) Vminibuf_scroll_window = data->minibuf_scroll_window; minibuf_selected_window = data->minibuf_selected_window; + SAFE_FREE (); return (FRAME_LIVE_P (f) ? Qt : Qnil); } + void restore_window_configuration (Lisp_Object configuration) { @@ -6518,6 +6493,7 @@ delete_all_child_windows (Lisp_Object window) { unshow_buffer (w); unchain_marker (XMARKER (w->pointm)); + unchain_marker (XMARKER (w->old_pointm)); unchain_marker (XMARKER (w->start)); /* Since combination limit makes sense for an internal windows only, we use this slot to save the buffer for the sake of @@ -6624,7 +6600,9 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) p->normal_cols = w->normal_cols; p->normal_lines = w->normal_lines; XSETFASTINT (p->hscroll, w->hscroll); + p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil; XSETFASTINT (p->min_hscroll, w->min_hscroll); + XSETFASTINT (p->hscroll_whole, w->hscroll_whole); p->display_table = w->display_table; p->left_margin_cols = make_number (w->left_margin_cols); p->right_margin_cols = make_number (w->right_margin_cols); @@ -6632,7 +6610,9 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) p->right_fringe_width = make_number (w->right_fringe_width); p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil; p->scroll_bar_width = make_number (w->scroll_bar_width); + p->scroll_bar_height = make_number (w->scroll_bar_height); p->vertical_scroll_bar_type = w->vertical_scroll_bar_type; + p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type; p->dedicated = w->dedicated; p->combination_limit = w->combination_limit; p->window_parameters = Qnil; @@ -6694,33 +6674,27 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) BUF_PT_BYTE (XBUFFER (w->contents))); else p->pointm = Fcopy_marker (w->pointm, Qnil); + p->old_pointm = Fcopy_marker (w->old_pointm, Qnil); XMARKER (p->pointm)->insertion_type - = !NILP (buffer_local_value_1 /* Don't signal error if void. */ + = !NILP (buffer_local_value /* Don't signal error if void. */ + (Qwindow_point_insertion_type, w->contents)); + XMARKER (p->old_pointm)->insertion_type + = !NILP (buffer_local_value /* Don't signal error if void. */ (Qwindow_point_insertion_type, w->contents)); p->start = Fcopy_marker (w->start, Qnil); p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil; - - tem = BVAR (XBUFFER (w->contents), mark); - p->mark = Fcopy_marker (tem, Qnil); } else { p->pointm = Qnil; + p->old_pointm = Qnil; p->start = Qnil; - p->mark = Qnil; p->start_at_line_beg = Qnil; } - if (NILP (w->parent)) - p->parent = Qnil; - else - p->parent = XWINDOW (w->parent)->temslot; - - if (NILP (w->prev)) - p->prev = Qnil; - else - p->prev = XWINDOW (w->prev)->temslot; + p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot; + p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot; if (WINDOWP (w->contents)) i = save_window_save (w->contents, vector, i); @@ -6734,8 +6708,8 @@ DEFUN ("current-window-configuration", Fcurrent_window_configuration, doc: /* Return an object representing the current window configuration of FRAME. If FRAME is nil or omitted, use the selected frame. This describes the number of windows, their sizes and current buffers, -and for each displayed buffer, where display starts, and the positions of -point and mark. An exception is made for point in the current buffer: +and for each displayed buffer, where display starts, and the position of +point. An exception is made for point in the current buffer: its value is -not- saved. This also records the currently selected frame, and FRAME's focus redirection (see `redirect-frame-focus'). The variable @@ -6784,7 +6758,6 @@ static void apply_window_adjustment (struct window *w) { eassert (w); - adjust_window_margins (w); clear_glyph_matrix (w->current_matrix); w->window_end_valid = 0; windows_or_buffers_changed = 30; @@ -6802,8 +6775,8 @@ set_window_margins (struct window *w, Lisp_Object left_width, Lisp_Object right_width) { int left, right; + int unit = WINDOW_FRAME_COLUMN_WIDTH (w); - /* FIXME: what about margins that are too wide? */ left = (NILP (left_width) ? 0 : (CHECK_NATNUM (left_width), XINT (left_width))); right = (NILP (right_width) ? 0 @@ -6811,11 +6784,23 @@ set_window_margins (struct window *w, Lisp_Object left_width, if (w->left_margin_cols != left || w->right_margin_cols != right) { - w->left_margin_cols = left; - w->right_margin_cols = right; - return w; + /* Don't change anything if new margins won't fit. */ + if ((WINDOW_PIXEL_WIDTH (w) + - WINDOW_FRINGES_WIDTH (w) + - WINDOW_SCROLL_BAR_AREA_WIDTH (w) + - (left + right) * unit) + >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w)) + { + w->left_margin_cols = left; + w->right_margin_cols = right; + + return w; + } + else + return NULL; } - return NULL; + else + return NULL; } DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins, @@ -6877,12 +6862,25 @@ set_window_fringes (struct window *w, Lisp_Object left_width, || w->right_fringe_width != right || w->fringes_outside_margins != outside)) { + if (left > 0 || right > 0) + { + /* Don't change anything if new fringes don't fit. */ + if ((WINDOW_PIXEL_WIDTH (w) + - WINDOW_MARGINS_WIDTH (w) + - WINDOW_SCROLL_BAR_AREA_WIDTH (w) + - max (left, 0) - max (right, 0)) + < MIN_SAFE_WINDOW_PIXEL_WIDTH (w)) + return NULL; + } + w->left_fringe_width = left; w->right_fringe_width = right; w->fringes_outside_margins = outside; + return w; } - return NULL; + else + return NULL; } DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes, @@ -6933,9 +6931,11 @@ Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */) static struct window * set_window_scroll_bars (struct window *w, Lisp_Object width, - Lisp_Object vertical_type, Lisp_Object horizontal_type) + Lisp_Object vertical_type, Lisp_Object height, + Lisp_Object horizontal_type) { int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width))); + bool changed = 0; if (iwidth == 0) vertical_type = Qnil; @@ -6949,32 +6949,78 @@ set_window_scroll_bars (struct window *w, Lisp_Object width, if (w->scroll_bar_width != iwidth || !EQ (w->vertical_scroll_bar_type, vertical_type)) { - w->scroll_bar_width = iwidth; - wset_vertical_scroll_bar_type (w, vertical_type); - return w; + /* Don't change anything if new scroll bar won't fit. */ + if ((WINDOW_PIXEL_WIDTH (w) + - WINDOW_MARGINS_WIDTH (w) + - WINDOW_FRINGES_WIDTH (w) + - max (iwidth, 0)) + >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w)) + { + w->scroll_bar_width = iwidth; + wset_vertical_scroll_bar_type (w, vertical_type); + changed = 1; + } } - return NULL; + +#if USE_HORIZONTAL_SCROLL_BARS + { + int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height))); + + if (MINI_WINDOW_P (w) || iheight == 0) + horizontal_type = Qnil; + + if (!(NILP (horizontal_type) + || EQ (horizontal_type, Qbottom) + || EQ (horizontal_type, Qt))) + error ("Invalid type of horizontal scroll bar"); + + if (w->scroll_bar_height != iheight + || !EQ (w->horizontal_scroll_bar_type, horizontal_type)) + { + /* Don't change anything if new scroll bar won't fit. */ + if ((WINDOW_PIXEL_HEIGHT (w) + - WINDOW_HEADER_LINE_HEIGHT (w) + - WINDOW_MODE_LINE_HEIGHT (w) + - max (iheight, 0)) + >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w)) + { + w->scroll_bar_height = iheight; + wset_horizontal_scroll_bar_type (w, horizontal_type); + changed = 1; + } + } + } +#else + wset_horizontal_scroll_bar_type (w, Qnil); +#endif + + return changed ? w : NULL; } DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, - Sset_window_scroll_bars, 2, 4, 0, + Sset_window_scroll_bars, 1, 5, 0, doc: /* Set width and type of scroll bars of window WINDOW. WINDOW must be a live window and defaults to the selected one. -Second parameter WIDTH specifies the pixel width for the scroll bar. +Second parameter WIDTH specifies the pixel width for the vertical scroll +bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame. Third parameter VERTICAL-TYPE specifies the type of the vertical scroll -bar: left, right, or nil. -If WIDTH is nil, use the frame's scroll-bar width. -If VERTICAL-TYPE is t, use the frame's scroll-bar type. -Fourth parameter HORIZONTAL-TYPE is currently unused. +bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the +frame's scroll-bar type. + +Fourth parameter HEIGHT specifies the pixel height for the horizontal +scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's +frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the +horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this +means to use the frame's horizontal scroll-bar type. Return t if scroll bars were actually changed and nil otherwise. */) - (Lisp_Object window, Lisp_Object width, - Lisp_Object vertical_type, Lisp_Object horizontal_type) + (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, + Lisp_Object height, Lisp_Object horizontal_type) { struct window *w = set_window_scroll_bars (decode_live_window (window), - width, vertical_type, horizontal_type); + width, vertical_type, height, horizontal_type); return w ? (apply_window_adjustment (w), Qt) : Qnil; } @@ -6984,19 +7030,25 @@ DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars, doc: /* Get width and type of scroll bars of window WINDOW. WINDOW must be a live window and defaults to the selected one. -Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE). -If WIDTH is nil or TYPE is t, the window is using the frame's corresponding +Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES +HORIZONTAL-TYPE). If WIDTH or HEIGHT is nil or VERTICAL-TYPE or +HORIZONTAL-TYPE is t, the window is using the frame's corresponding value. */) (Lisp_Object window) { struct window *w = decode_live_window (window); - return list4 (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)), - make_number (WINDOW_SCROLL_BAR_COLS (w)), - w->vertical_scroll_bar_type, Qnil); + return Fcons (((w->scroll_bar_width >= 0) + ? make_number (w->scroll_bar_width) + : Qnil), + list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)), + w->vertical_scroll_bar_type, + ((w->scroll_bar_height >= 0) + ? make_number (w->scroll_bar_height) + : Qnil), + make_number (WINDOW_SCROLL_BAR_LINES (w)), + w->horizontal_scroll_bar_type)); } - - /*********************************************************************** Smooth scrolling @@ -7179,15 +7231,16 @@ compare_window_configurations (Lisp_Object configuration1, || !EQ (sw1->min_hscroll, sw2->min_hscroll) || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg) || NILP (Fequal (sw1->start, sw2->start)) - || NILP (Fequal (sw1->pointm, sw2->pointm)) - || NILP (Fequal (sw1->mark, sw2->mark)))) + || NILP (Fequal (sw1->pointm, sw2->pointm)))) || !EQ (sw1->left_margin_cols, sw2->left_margin_cols) || !EQ (sw1->right_margin_cols, sw2->right_margin_cols) || !EQ (sw1->left_fringe_width, sw2->left_fringe_width) || !EQ (sw1->right_fringe_width, sw2->right_fringe_width) || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins) || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width) - || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)) + || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height) + || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type) + || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type)) return 0; } @@ -7197,7 +7250,7 @@ compare_window_configurations (Lisp_Object configuration1, DEFUN ("compare-window-configurations", Fcompare_window_configurations, Scompare_window_configurations, 2, 2, 0, doc: /* Compare two window configurations as regards the structure of windows. -This function ignores details such as the values of point and mark +This function ignores details such as the values of point and scrolling positions. */) (Lisp_Object x, Lisp_Object y) { @@ -7214,8 +7267,6 @@ init_window_once (void) Vterminal_frame = selected_frame; minibuf_window = f->minibuffer_window; selected_window = f->selected_window; - - window_initialized = 1; } void @@ -7243,6 +7294,7 @@ syms_of_window (void) DEFSYM (Qdelete_window, "delete-window"); DEFSYM (Qwindow_resize_root_window, "window--resize-root-window"); DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically"); + DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes"); DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total"); DEFSYM (Qsafe, "safe"); DEFSYM (Qdisplay_buffer, "display-buffer"); @@ -7469,12 +7521,14 @@ pixelwise even if this option is nil. */); defsubr (&Swindow_right_divider_width); defsubr (&Swindow_bottom_divider_width); defsubr (&Swindow_scroll_bar_width); + defsubr (&Swindow_scroll_bar_height); defsubr (&Swindow_inside_edges); defsubr (&Swindow_inside_pixel_edges); defsubr (&Swindow_inside_absolute_pixel_edges); defsubr (&Scoordinates_in_window_p); defsubr (&Swindow_at); defsubr (&Swindow_point); + defsubr (&Swindow_old_point); defsubr (&Swindow_start); defsubr (&Swindow_end); defsubr (&Sset_window_point); diff --git a/src/window.h b/src/window.h index b9c2b1f5ba8..ea5dddc9fc8 100644 --- a/src/window.h +++ b/src/window.h @@ -128,21 +128,37 @@ struct window each one can have its own value of point. */ Lisp_Object pointm; + /* A marker pointing to where in the text point was in this window + at the time of last redisplay. The value is saved for the + selected window too. */ + Lisp_Object old_pointm; + /* No permanent meaning; used by save-window-excursion's bookkeeping. */ Lisp_Object temslot; - /* This window's vertical scroll bar. This field is only for use - by the window-system-dependent code which implements the - scroll bars; it can store anything it likes here. If this - window is newly created and we haven't displayed a scroll bar in - it yet, or if the frame doesn't have any scroll bars, this is nil. */ + /* This window's vertical scroll bar. This field is only for use by + the window-system-dependent code which implements the scroll + bars; it can store anything it likes here. If this window is + newly created and we haven't displayed a scroll bar in it yet, or + if the frame doesn't have any scroll bars, this is nil. */ Lisp_Object vertical_scroll_bar; /* Type of vertical scroll bar. A value of nil means no scroll bar. A value of t means use frame value. */ Lisp_Object vertical_scroll_bar_type; + /* This window's horizontal scroll bar. This field is only for use + by the window-system-dependent code which implements the scroll + bars; it can store anything it likes here. If this window is + newly created and we haven't displayed a scroll bar in it yet, or + if the frame doesn't have any scroll bars, this is nil. */ + Lisp_Object horizontal_scroll_bar; + + /* Type of horizontal scroll bar. A value of nil means + no scroll bar. A value of t means use frame value. */ + Lisp_Object horizontal_scroll_bar_type; + /* Display-table to use for displaying chars in this window. Nil means use the buffer's own display-table. */ Lisp_Object display_table; @@ -209,6 +225,10 @@ struct window the user has set, by set-window-hscroll for example. */ ptrdiff_t min_hscroll; + /* Maximum line length in pixels within window bound by size of + window (set up by set_horizontal_scroll_bar). */ + ptrdiff_t hscroll_whole; + /* Displayed buffer's text modification events counter as of last time display completed. */ EMACS_INT last_modified; @@ -282,6 +302,10 @@ struct window A value of -1 means use frame values. */ int scroll_bar_width; + /* Pixel height of scroll bars. + A value of -1 means use frame values. */ + int scroll_bar_height; + /* Effective height of the mode line, or -1 if not known. */ int mode_line_height; @@ -355,6 +379,10 @@ struct window /* True if it needs to be redisplayed. */ bool_bf redisplay : 1; + /* True if auto hscrolling is currently suspended in this + window. */ + bool_bf suspend_auto_hscroll : 1; + /* Amount by which lines of this window are scrolled in y-direction (smooth scrolling). */ int vscroll; @@ -403,6 +431,18 @@ wset_vertical_scroll_bar (struct window *w, Lisp_Object val) } INLINE void +wset_horizontal_scroll_bar (struct window *w, Lisp_Object val) +{ + w->horizontal_scroll_bar = val; +} + +INLINE void +wset_horizontal_scroll_bar_type (struct window *w, Lisp_Object val) +{ + w->horizontal_scroll_bar_type = val; +} + +INLINE void wset_prev_buffers (struct window *w, Lisp_Object val) { w->prev_buffers = val; @@ -415,8 +455,17 @@ wset_next_buffers (struct window *w, Lisp_Object val) } /* True if W is a minibuffer window. */ +#define MINI_WINDOW_P(W) ((W)->mini) + +/* 1 if W is a non-only minibuffer window. */ +/* The first check is redundant and the second overly complicated. */ +#define MINI_NON_ONLY_WINDOW_P(W) \ + (MINI_WINDOW_P (W) \ + && (EQ (W->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))))) -#define MINI_WINDOW_P(W) ((W)->mini) +/* 1 if W is a minibuffer-only window. */ +#define MINI_ONLY_WINDOW_P(W) \ + (MINI_WINDOW_P (W) && NILP (W->prev)) /* General window layout: @@ -460,16 +509,17 @@ wset_next_buffers (struct window *w, Lisp_Object val) #define WINDOW_VERTICAL_COMBINATION_P(W) \ (WINDOWP ((W)->contents) && !(W)->horizontal) -#define WINDOW_XFRAME(W) \ - (XFRAME (WINDOW_FRAME ((W)))) +/* WINDOW's XFRAME. */ +#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) -/* Return the canonical column width of the frame of window W. */ +/* Whether WINDOW is a pseudo window. */ +#define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p) +/* Return the canonical column width of the frame of window W. */ #define WINDOW_FRAME_COLUMN_WIDTH(W) \ (FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W)))) /* Return the canonical column width of the frame of window W. */ - #define WINDOW_FRAME_LINE_HEIGHT(W) \ (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W)))) @@ -613,6 +663,10 @@ wset_next_buffers (struct window *w, Lisp_Object val) #define WINDOW_LEFTMOST_P(W) \ (WINDOW_LEFT_PIXEL_EDGE (W) == 0) +/* True if window W's has no other windows above in its frame. */ +#define WINDOW_TOPMOST_P(W) \ + (WINDOW_TOP_PIXEL_EDGE (W) == 0) + /* True if window W's has no other windows to its right in its frame. */ #define WINDOW_RIGHTMOST_P(W) \ (WINDOW_RIGHT_PIXEL_EDGE (W) \ @@ -629,7 +683,6 @@ wset_next_buffers (struct window *w, Lisp_Object val) /* Return the frame column at which the text (or left fringe) in window W starts. This is different from the `LEFT_EDGE' because it does not include a left-hand scroll bar if any. */ - #define WINDOW_BOX_LEFT_EDGE_COL(W) \ (WINDOW_LEFT_EDGE_COL (W) \ + WINDOW_LEFT_SCROLL_BAR_COLS (W)) @@ -644,7 +697,6 @@ wset_next_buffers (struct window *w, Lisp_Object val) /* Return the window column before which the text in window W ends. This is different from WINDOW_RIGHT_EDGE_COL because it does not include a scroll bar or window-separating line on the right edge. */ - #define WINDOW_BOX_RIGHT_EDGE_COL(W) \ (WINDOW_RIGHT_EDGE_COL (W) \ - WINDOW_RIGHT_SCROLL_BAR_COLS (W)) @@ -706,114 +758,116 @@ wset_next_buffers (struct window *w, Lisp_Object val) #define WINDOW_FRINGES_WIDTH(W) \ (WINDOW_LEFT_FRINGE_WIDTH (W) + WINDOW_RIGHT_FRINGE_WIDTH (W)) -/* Widths of fringes in columns. */ -#define WINDOW_FRINGE_COLS(W) \ - ((W->left_fringe_width >= 0 \ - && W->right_fringe_width >= 0) \ - ? ((WINDOW_FRINGES_WIDTH (W) \ - + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \ - / WINDOW_FRAME_COLUMN_WIDTH (W)) \ - : FRAME_FRINGE_COLS (WINDOW_XFRAME (W))) - -#define WINDOW_LEFT_FRINGE_COLS(W) \ - ((WINDOW_LEFT_FRINGE_WIDTH ((W)) \ - + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \ - / WINDOW_FRAME_COLUMN_WIDTH (W)) - -#define WINDOW_RIGHT_FRINGE_COLS(W) \ - ((WINDOW_RIGHT_FRINGE_WIDTH ((W)) \ - + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \ - / WINDOW_FRAME_COLUMN_WIDTH (W)) - /* Are fringes outside display margins in window W. */ #define WINDOW_HAS_FRINGES_OUTSIDE_MARGINS(W) \ ((W)->fringes_outside_margins) -/* Say whether scroll bars are currently enabled for window W, +/* Say whether vertical scroll bars are currently enabled for window W, and which side they are on. */ -#define WINDOW_VERTICAL_SCROLL_BAR_TYPE(w) \ - (EQ (w->vertical_scroll_bar_type, Qt) \ - ? FRAME_VERTICAL_SCROLL_BAR_TYPE (WINDOW_XFRAME (w)) \ - : EQ (w->vertical_scroll_bar_type, Qleft) \ +#define WINDOW_VERTICAL_SCROLL_BAR_TYPE(W) \ + (WINDOW_PSEUDO_P (W) \ + ? vertical_scroll_bar_none \ + : EQ (W->vertical_scroll_bar_type, Qt) \ + ? FRAME_VERTICAL_SCROLL_BAR_TYPE (WINDOW_XFRAME (W)) \ + : EQ (W->vertical_scroll_bar_type, Qleft) \ ? vertical_scroll_bar_left \ - : EQ (w->vertical_scroll_bar_type, Qright) \ + : EQ (W->vertical_scroll_bar_type, Qright) \ ? vertical_scroll_bar_right \ - : vertical_scroll_bar_none) \ + : vertical_scroll_bar_none) + +#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT(W) \ + (WINDOW_VERTICAL_SCROLL_BAR_TYPE (W) == vertical_scroll_bar_left) -#define WINDOW_HAS_VERTICAL_SCROLL_BAR(w) \ - (EQ (w->vertical_scroll_bar_type, Qt) \ - ? FRAME_HAS_VERTICAL_SCROLL_BARS (WINDOW_XFRAME (w)) \ - : !NILP (w->vertical_scroll_bar_type)) +#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT(W) \ + (WINDOW_VERTICAL_SCROLL_BAR_TYPE (W) == vertical_scroll_bar_right) -#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT(w) \ - (EQ (w->vertical_scroll_bar_type, Qt) \ - ? FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (WINDOW_XFRAME (w)) \ - : EQ (w->vertical_scroll_bar_type, Qleft)) +#define WINDOW_HAS_VERTICAL_SCROLL_BAR(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (W) \ + || WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W)) -#define WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT(w) \ - (EQ (w->vertical_scroll_bar_type, Qt) \ - ? FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (WINDOW_XFRAME (w)) \ - : EQ (w->vertical_scroll_bar_type, Qright)) +#if (defined (HAVE_WINDOW_SYSTEM) \ + && ((defined (USE_TOOLKIT_SCROLL_BARS) && !defined (HAVE_NS)) \ + || defined (HAVE_NTGUI))) +# define USE_HORIZONTAL_SCROLL_BARS true +#else +# define USE_HORIZONTAL_SCROLL_BARS false +#endif + +/* Say whether horizontal scroll bars are currently enabled for window + W. Horizontal scrollbars exist for toolkit versions only. */ +#if USE_HORIZONTAL_SCROLL_BARS +#define WINDOW_HAS_HORIZONTAL_SCROLL_BAR(W) \ + ((WINDOW_PSEUDO_P (W) || MINI_NON_ONLY_WINDOW_P (W)) \ + ? false \ + : EQ (W->horizontal_scroll_bar_type, Qt) \ + ? FRAME_HAS_HORIZONTAL_SCROLL_BARS (WINDOW_XFRAME (W)) \ + : EQ (W->horizontal_scroll_bar_type, Qbottom) \ + ? true \ + : false) +#else +#define WINDOW_HAS_HORIZONTAL_SCROLL_BAR(W) false +#endif /* Width that a scroll bar in window W should have, if there is one. Measured in pixels. If scroll bars are turned off, this is still nonzero. */ -#define WINDOW_CONFIG_SCROLL_BAR_WIDTH(w) \ - (w->scroll_bar_width >= 0 \ - ? w->scroll_bar_width \ - : FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w))) +#define WINDOW_CONFIG_SCROLL_BAR_WIDTH(W) \ + (W->scroll_bar_width >= 0 \ + ? W->scroll_bar_width \ + : FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (W))) /* Width that a scroll bar in window W should have, if there is one. Measured in columns (characters). If scroll bars are turned off, this is still nonzero. */ -#define WINDOW_CONFIG_SCROLL_BAR_COLS(w) \ - (w->scroll_bar_width >= 0 \ - ? ((w->scroll_bar_width \ - + WINDOW_FRAME_COLUMN_WIDTH (w) - 1) \ - / WINDOW_FRAME_COLUMN_WIDTH (w)) \ - : FRAME_CONFIG_SCROLL_BAR_COLS (WINDOW_XFRAME (w))) +#define WINDOW_CONFIG_SCROLL_BAR_COLS(W) \ + (W->scroll_bar_width >= 0 \ + ? ((W->scroll_bar_width \ + + WINDOW_FRAME_COLUMN_WIDTH (W) - 1) \ + / WINDOW_FRAME_COLUMN_WIDTH (W)) \ + : FRAME_CONFIG_SCROLL_BAR_COLS (WINDOW_XFRAME (W))) /* Width of left scroll bar in window W, measured in columns (characters). If scroll bars are on the right in this frame, or there are no scroll bars, value is 0. */ -#define WINDOW_LEFT_SCROLL_BAR_COLS(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) \ - ? (WINDOW_CONFIG_SCROLL_BAR_COLS (w)) \ +#define WINDOW_LEFT_SCROLL_BAR_COLS(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (W) \ + ? (WINDOW_CONFIG_SCROLL_BAR_COLS (W)) \ : 0) /* Width of right scroll bar in window W, measured in columns (characters). If scroll bars are on the left in this frame, or there are no scroll bars, value is 0. */ -#define WINDOW_RIGHT_SCROLL_BAR_COLS(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w) \ - ? WINDOW_CONFIG_SCROLL_BAR_COLS (w) \ +#define WINDOW_RIGHT_SCROLL_BAR_COLS(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_COLS (W) \ : 0) /* Width of a scroll bar in window W, measured in columns. */ -#define WINDOW_SCROLL_BAR_COLS(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) \ - ? WINDOW_CONFIG_SCROLL_BAR_COLS (w) \ +#define WINDOW_SCROLL_BAR_COLS(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_COLS (W) \ : 0) /* Width of a left scroll bar area in window W, measured in pixels. */ -#define WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) \ - ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) \ +#define WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \ : 0) /* Width of a right scroll bar area in window W, measured in pixels. */ -#define WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w) \ - ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) \ +#define WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \ : 0) /* Width of scroll bar area in window W, measured in pixels. */ -#define WINDOW_SCROLL_BAR_AREA_WIDTH(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) \ - ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) \ +#define WINDOW_SCROLL_BAR_AREA_WIDTH(W) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \ : 0) -/* Return the frame position where the scroll bar of window W starts. */ +/* Return the frame position where the vertical scroll bar of window W + starts. */ #define WINDOW_SCROLL_BAR_AREA_X(W) \ (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \ ? WINDOW_BOX_RIGHT_EDGE_X (W) \ @@ -829,6 +883,36 @@ wset_next_buffers (struct window *w, Lisp_Object val) ? 0 \ : FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W))) +/* Height that a scroll bar in window W should have, if there is one. + Measured in pixels. If scroll bars are turned off, this is still + nonzero. */ +#define WINDOW_CONFIG_SCROLL_BAR_HEIGHT(W) \ + (W->scroll_bar_height >= 0 \ + ? W->scroll_bar_height \ + : FRAME_CONFIG_SCROLL_BAR_HEIGHT (WINDOW_XFRAME (W))) + +/* Height that a scroll bar in window W should have, if there is one. + Measured in lines (characters). If scroll bars are turned off, this + is still nonzero. */ +#define WINDOW_CONFIG_SCROLL_BAR_LINES(W) \ + (W->scroll_bar_height >= 0 \ + ? ((W->scroll_bar_height \ + + WINDOW_FRAME_LINE_HEIGHT (W) - 1) \ + / WINDOW_FRAME_LINE_HEIGHT (W)) \ + : FRAME_CONFIG_SCROLL_BAR_LINES (WINDOW_XFRAME (W))) + +/* Height of a scroll bar in window W, measured in columns. */ +#define WINDOW_SCROLL_BAR_LINES(W) \ + (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_LINES (W) \ + : 0) + +/* Height of scroll bar area in window W, measured in pixels. */ +#define WINDOW_SCROLL_BAR_AREA_HEIGHT(W) \ + (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (W) \ + ? WINDOW_CONFIG_SCROLL_BAR_HEIGHT (W) \ + : 0) + /* Height in pixels, and in lines, of the mode line. May be zero if W doesn't have a mode line. */ #define WINDOW_MODE_LINE_HEIGHT(W) \ @@ -837,67 +921,63 @@ wset_next_buffers (struct window *w, Lisp_Object val) : 0) #define WINDOW_MODE_LINE_LINES(W) \ - (!! WINDOW_WANTS_MODELINE_P ((W))) + (!! WINDOW_WANTS_MODELINE_P (W)) /* Height in pixels, and in lines, of the header line. Zero if W doesn't have a header line. */ #define WINDOW_HEADER_LINE_HEIGHT(W) \ - (WINDOW_WANTS_HEADER_LINE_P ((W)) \ + (WINDOW_WANTS_HEADER_LINE_P (W) \ ? CURRENT_HEADER_LINE_HEIGHT (W) \ : 0) #define WINDOW_HEADER_LINE_LINES(W) \ - (!! WINDOW_WANTS_HEADER_LINE_P ((W))) + (!! WINDOW_WANTS_HEADER_LINE_P (W)) -/* Pixel height of window W without mode line and bottom divider. */ +/* Pixel height of window W without mode line, bottom scroll bar and + bottom divider. */ #define WINDOW_BOX_HEIGHT_NO_MODE_LINE(W) \ - (WINDOW_PIXEL_HEIGHT ((W)) \ + (WINDOW_PIXEL_HEIGHT (W) \ - WINDOW_BOTTOM_DIVIDER_WIDTH (W) \ - - WINDOW_MODE_LINE_HEIGHT ((W))) + - WINDOW_SCROLL_BAR_AREA_HEIGHT (W) \ + - WINDOW_MODE_LINE_HEIGHT (W)) /* Pixel height of window W without mode and header line and bottom divider. */ #define WINDOW_BOX_TEXT_HEIGHT(W) \ (WINDOW_PIXEL_HEIGHT ((W)) \ - WINDOW_BOTTOM_DIVIDER_WIDTH (W) \ - - WINDOW_MODE_LINE_HEIGHT ((W)) \ - - WINDOW_HEADER_LINE_HEIGHT ((W))) + - WINDOW_SCROLL_BAR_AREA_HEIGHT (W) \ + - WINDOW_MODE_LINE_HEIGHT (W) \ + - WINDOW_HEADER_LINE_HEIGHT (W)) + +/* Return the frame position where the horizontal scroll bar of window W + starts. */ +#define WINDOW_SCROLL_BAR_AREA_Y(W) \ + (WINDOW_TOP_EDGE_Y (W) \ + + (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (W) \ + ? WINDOW_BOX_HEIGHT_NO_MODE_LINE (W) : 0)) /* Convert window W relative pixel X to frame pixel coordinates. */ #define WINDOW_TO_FRAME_PIXEL_X(W, X) \ ((X) + WINDOW_BOX_LEFT_EDGE_X ((W))) /* Convert window W relative pixel Y to frame pixel coordinates. */ -#define WINDOW_TO_FRAME_PIXEL_Y(W, Y) \ - ((Y) + WINDOW_TOP_EDGE_Y ((W))) +#define WINDOW_TO_FRAME_PIXEL_Y(W, Y) \ + ((Y) + WINDOW_TOP_EDGE_Y (W)) /* Convert frame relative pixel X to window relative pixel X. */ -#define FRAME_TO_WINDOW_PIXEL_X(W, X) \ +#define FRAME_TO_WINDOW_PIXEL_X(W, X) \ ((X) - WINDOW_BOX_LEFT_EDGE_X ((W))) /* Convert frame relative pixel Y to window relative pixel Y. */ -#define FRAME_TO_WINDOW_PIXEL_Y(W, Y) \ - ((Y) - WINDOW_TOP_EDGE_Y ((W))) +#define FRAME_TO_WINDOW_PIXEL_Y(W, Y) \ + ((Y) - WINDOW_TOP_EDGE_Y (W)) /* Convert a text area relative x-position in window W to frame X pixel coordinates. */ #define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X) \ (window_box_left ((W), TEXT_AREA) + (X)) -/* True if the background of the window W's fringe that is adjacent to - a scroll bar is extended to the gap between the fringe and the bar. */ - -#define WINDOW_FRINGE_EXTENDED_P(w) \ - (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) \ - ? (WINDOW_LEFTMOST_P (w) \ - && WINDOW_LEFT_FRINGE_WIDTH (w) \ - && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) \ - || WINDOW_LEFT_MARGIN_COLS (w) == 0)) \ - : (WINDOW_RIGHTMOST_P (w) \ - && WINDOW_RIGHT_FRINGE_WIDTH (w) \ - && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) \ - || WINDOW_RIGHT_MARGIN_COLS (w) == 0))) - /* This is the window in which the terminal's cursor should be left when nothing is being done with it. This must always be a leaf window, and its buffer is selected by the top level editing loop at the end of each command. @@ -981,11 +1061,6 @@ extern void bset_update_mode_line (struct buffer *b); above already does it, so it's only needed in unusual cases. */ extern void redisplay_other_windows (void); -/* If *ROWS or *COLS are too small a size for FRAME, set them to the - minimum allowable size. */ - -extern void check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise); - /* Return a pointer to the glyph W's physical cursor is on. Value is null if W's current matrix is invalid, so that no meaningful glyph can be returned. */ @@ -1010,7 +1085,6 @@ struct glyph *get_phys_cursor_glyph (struct window *w); CHECK_TYPE (WINDOW_LIVE_P (WINDOW), Qwindow_live_p, WINDOW) /* These used to be in lisp.h. */ - extern Lisp_Object Qwindow_live_p; extern Lisp_Object Vwindow_list; @@ -1024,6 +1098,7 @@ extern int window_body_width (struct window *w, bool); extern void temp_output_buffer_show (Lisp_Object); extern void replace_buffer_in_windows (Lisp_Object); extern void replace_buffer_in_windows_safely (Lisp_Object); +extern Lisp_Object sanitize_window_sizes (Lisp_Object, Lisp_Object); /* This looks like a setter, but it is a bit special. */ extern void wset_buffer (struct window *, Lisp_Object); extern bool window_outdated (struct window *); diff --git a/src/xdisp.c b/src/xdisp.c index 80d4d52531a..ad28dacf4e5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -816,11 +816,11 @@ Lisp_Object previous_help_echo_string; #ifdef HAVE_WINDOW_SYSTEM /* Non-zero means an hourglass cursor is currently shown. */ -bool hourglass_shown_p; +static bool hourglass_shown_p; /* If non-null, an asynchronous timer that, when it expires, displays an hourglass cursor on all frames. */ -struct atimer *hourglass_atimer; +static struct atimer *hourglass_atimer; #endif /* HAVE_WINDOW_SYSTEM */ @@ -1024,6 +1024,8 @@ window_text_bottom_y (struct window *w) if (WINDOW_WANTS_MODELINE_P (w)) height -= CURRENT_MODE_LINE_HEIGHT (w); + height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w); + return height; } @@ -1068,6 +1070,7 @@ window_box_height (struct window *w) eassert (height >= 0); height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w); + height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w); /* Note: the code below that determines the mode-line/header-line height is essentially the same as that contained in the macro @@ -1141,7 +1144,7 @@ window_box_left_offset (struct window *w, enum glyph_row_area area) area AREA of window W. ANY_AREA means return the right edge of the whole window, to the left of the right fringe of W. */ -int +static int window_box_right_offset (struct window *w, enum glyph_row_area area) { /* Don't return more than the window's pixel width. */ @@ -1957,8 +1960,8 @@ pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y, if (pix_y < 0) pix_y = 0; - else if (pix_y > FRAME_LINES (f)) - pix_y = FRAME_LINES (f); + else if (pix_y > FRAME_TOTAL_LINES (f)) + pix_y = FRAME_TOTAL_LINES (f); } } #endif @@ -2174,7 +2177,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int if (s->x > r.x) { - r.width -= s->x - r.x; + if (r.width >= s->x - r.x) + r.width -= s->x - r.x; + else /* R2L hscrolled row with cursor outside text area */ + r.width = 0; r.x = s->x; } r.width = min (r.width, glyph->pixel_width); @@ -2296,10 +2302,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row, glyph, and `x-stretch-block-cursor' is nil, don't draw a rectangle as wide as the glyph, but use a canonical character width instead. */ - wd = glyph->pixel_width - 1; -#if defined (HAVE_NTGUI) || defined (HAVE_NS) - wd++; /* Why? */ -#endif + wd = glyph->pixel_width; x = w->phys_cursor.x; if (x < 0) @@ -2501,7 +2504,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) gx = WINDOW_PIXEL_WIDTH (w) - width; goto row_glyph; - case ON_SCROLL_BAR: + case ON_VERTICAL_SCROLL_BAR: gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) ? 0 : (window_box_right_offset (w, RIGHT_MARGIN_AREA) @@ -2535,7 +2538,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) gy = 0; /* The bottom divider prevails. */ height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); - goto add_edge;; + goto add_edge; case ON_BOTTOM_DIVIDER: gx = 0; @@ -2623,15 +2626,14 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap) { ptrdiff_t i; ptrdiff_t count = SPECPDL_INDEX (); - struct gcpro gcpro1; - Lisp_Object *args = alloca (nargs * word_size); + Lisp_Object *args; + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (args, nargs); args[0] = func; for (i = 1; i < nargs; i++) args[i] = va_arg (ap, Lisp_Object); - GCPRO1 (args[0]); - gcpro1.nvars = nargs; specbind (Qinhibit_redisplay, Qt); if (inhibit_quit) specbind (Qinhibit_quit, Qt); @@ -2639,7 +2641,7 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap) so there is no possibility of wanting to redisplay. */ val = internal_condition_case_n (Ffuncall, nargs, args, Qt, safe_eval_handler); - UNGCPRO; + SAFE_FREE (); val = unbind_to (count, val); } @@ -2971,10 +2973,6 @@ init_iterator (struct it *it, struct window *w, it->glyph_row = row; it->area = TEXT_AREA; - /* Forget any previous info about this row being reversed. */ - if (it->glyph_row) - it->glyph_row->reversed_p = 0; - /* Get the dimensions of the display area. The display area consists of the visible window area plus a horizontally scrolled part to the left of the window. All x-values are relative to the @@ -3669,6 +3667,7 @@ next_overlay_change (ptrdiff_t pos) ptrdiff_t i, noverlays; ptrdiff_t endpos; Lisp_Object *overlays; + USE_SAFE_ALLOCA; /* Get all overlays at the given position. */ GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1); @@ -3685,6 +3684,7 @@ next_overlay_change (ptrdiff_t pos) endpos = min (endpos, oendpos); } + SAFE_FREE (); return endpos; } @@ -5130,7 +5130,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, if (it) { - int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);; + int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); if (CONSP (XCDR (XCDR (spec)))) { @@ -5745,10 +5745,11 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) Lisp_Object overlay, window, str, invisible; struct Lisp_Overlay *ov; ptrdiff_t start, end; - ptrdiff_t size = 20; ptrdiff_t n = 0, i, j; int invis_p; - struct overlay_entry *entries = alloca (size * sizeof *entries); + struct overlay_entry entriesbuf[20]; + ptrdiff_t size = ARRAYELTS (entriesbuf); + struct overlay_entry *entries = entriesbuf; USE_SAFE_ALLOCA; if (charpos <= 0) @@ -6931,7 +6932,8 @@ get_next_display_element (struct it *it) is R..." */ /* FIXME: Do we need an exception for characters from display tables? */ - if (it->bidi_p && it->bidi_it.type == STRONG_R) + if (it->bidi_p && it->bidi_it.type == STRONG_R + && !inhibit_bidi_mirroring) it->c = bidi_mirror_char (it->c); /* Map via display table or translate control characters. IT->c, IT->len etc. have been set to the next character by @@ -8344,7 +8346,7 @@ next_element_from_buffer (struct it *it) /* Get the next character, maybe multibyte. */ p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); - if (it->multibyte_p && !ASCII_BYTE_P (*p)) + if (it->multibyte_p && !ASCII_CHAR_P (*p)) it->c = STRING_CHAR_AND_LENGTH (p, it->len); else it->c = *p, it->len = 1; @@ -10027,9 +10029,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte) for (i = 0; i < nbytes; i += char_bytes) { c = string_char_and_length (msg + i, &char_bytes); - work[0] = (ASCII_CHAR_P (c) - ? c - : multibyte_char_to_unibyte (c)); + work[0] = CHAR_TO_BYTE8 (c); insert_1_both (work, 1, 1, 1, 0, 0); } } @@ -10204,9 +10204,9 @@ message3 (Lisp_Object m) { ptrdiff_t nbytes = SBYTES (m); bool multibyte = STRING_MULTIBYTE (m); + char *buffer; USE_SAFE_ALLOCA; - char *buffer = SAFE_ALLOCA (nbytes); - memcpy (buffer, SDATA (m), nbytes); + SAFE_ALLOCA_STRING (buffer, m); message_dolog (buffer, nbytes, 1, multibyte); SAFE_FREE (); } @@ -10311,19 +10311,17 @@ message_with_string (const char *m, Lisp_Object string, int log) { if (m) { - /* ENCODE_SYSTEM below can GC and/or relocate the Lisp - String whose data pointer might be passed to us in M. So - we use a local copy. */ - char *fmt = xstrdup (m); + /* ENCODE_SYSTEM below can GC and/or relocate the + Lisp data, so make sure we don't use it here. */ + eassert (relocatable_string_data_p (m) != 1); if (noninteractive_need_newline) putc ('\n', stderr); noninteractive_need_newline = 0; - fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string))); + fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string))); if (!cursor_in_echo_area) fprintf (stderr, "\n"); fflush (stderr); - xfree (fmt); } } else if (INTERACTIVE) @@ -10410,11 +10408,13 @@ vmessage (const char *m, va_list ap) { ptrdiff_t len; ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f); - char *message_buf = alloca (maxsize + 1); + USE_SAFE_ALLOCA; + char *message_buf = SAFE_ALLOCA (maxsize + 1); len = doprnt (message_buf, maxsize, m, 0, ap); message3 (make_string (message_buf, len)); + SAFE_FREE (); } else message1 (0); @@ -10580,6 +10580,7 @@ with_echo_area_buffer (struct window *w, int which, { wset_buffer (w, buffer); set_marker_both (w->pointm, buffer, BEG, BEG_BYTE); + set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE); } bset_undo_list (current_buffer, Qt); @@ -10618,7 +10619,7 @@ with_echo_area_buffer_unwind_data (struct window *w) Vwith_echo_area_save_vector = Qnil; if (NILP (vector)) - vector = Fmake_vector (make_number (9), Qnil); + vector = Fmake_vector (make_number (11), Qnil); XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i; ASET (vector, i, Vdeactivate_mark); ++i; @@ -10630,12 +10631,14 @@ with_echo_area_buffer_unwind_data (struct window *w) ASET (vector, i, w->contents); ++i; ASET (vector, i, make_number (marker_position (w->pointm))); ++i; ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i; + ASET (vector, i, make_number (marker_position (w->old_pointm))); ++i; + ASET (vector, i, make_number (marker_byte_position (w->old_pointm))); ++i; ASET (vector, i, make_number (marker_position (w->start))); ++i; ASET (vector, i, make_number (marker_byte_position (w->start))); ++i; } else { - int end = i + 6; + int end = i + 8; for (; i < end; ++i) ASET (vector, i, Qnil); } @@ -10667,9 +10670,12 @@ unwind_with_echo_area_buffer (Lisp_Object vector) set_marker_both (w->pointm, buffer, XFASTINT (AREF (vector, 5)), XFASTINT (AREF (vector, 6))); - set_marker_both (w->start, buffer, + set_marker_both (w->old_pointm, buffer, XFASTINT (AREF (vector, 7)), XFASTINT (AREF (vector, 8))); + set_marker_both (w->start, buffer, + XFASTINT (AREF (vector, 9)), + XFASTINT (AREF (vector, 10))); } Vwith_echo_area_save_vector = vector; @@ -11918,11 +11924,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) #ifdef HAVE_WINDOW_SYSTEM -/* Tool-bar item index of the item on which a mouse button was pressed - or -1. */ - -int last_tool_bar_item; - /* Select `frame' temporarily without running all the code in do_switch_frame. FIXME: Maybe do_switch_frame should be trimmed down similarly @@ -11949,7 +11950,7 @@ update_tool_bar (struct frame *f, int save_match_data) int do_update = FRAME_EXTERNAL_TOOL_BAR (f); #else int do_update = (WINDOWP (f->tool_bar_window) - && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0); + && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0); #endif if (do_update) @@ -12045,11 +12046,11 @@ static void build_desired_tool_bar_string (struct frame *f) { int i, size, size_needed; - struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object image, plist, props; + struct gcpro gcpro1, gcpro2; + Lisp_Object image, plist; - image = plist = props = Qnil; - GCPRO3 (image, plist, props); + image = plist = Qnil; + GCPRO2 (image, plist); /* Prepare F->desired_tool_bar_string. If we can reuse it, do so. Otherwise, make a new string. */ @@ -12068,9 +12069,12 @@ build_desired_tool_bar_string (struct frame *f) (f, Fmake_string (make_number (size_needed), make_number (' '))); else { - props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil); + AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil); + struct gcpro gcpro1; + GCPRO1 (props); Fremove_text_properties (make_number (0), make_number (size), props, f->desired_tool_bar_string); + UNGCPRO; } /* Put a `display' property on the string for the images to display, @@ -12181,8 +12185,10 @@ build_desired_tool_bar_string (struct frame *f) the start of this item's properties in the tool-bar items vector. */ image = Fcons (Qimage, plist); - props = list4 (Qdisplay, image, - Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)); + AUTO_LIST4 (props, Qdisplay, image, Qmenu_item, + make_number (i * TOOL_BAR_ITEM_NSLOTS)); + struct gcpro gcpro1; + GCPRO1 (props); /* Let the last image hide all remaining spaces in the tool bar string. The string can be longer than needed when we reuse a @@ -12193,6 +12199,7 @@ build_desired_tool_bar_string (struct frame *f) end = i + 1; Fadd_text_properties (make_number (i), make_number (end), props, f->desired_tool_bar_string); + UNGCPRO; #undef PROP } @@ -12333,16 +12340,9 @@ display_tool_bar_line (struct it *it, int height) } -/* Max tool-bar height. Basically, this is what makes all other windows - disappear when the frame gets too small. Rethink this! */ - -#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \ - ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f))) - /* Value is the number of pixels needed to make all tool-bar items of frame F visible. The actual number of glyph rows needed is returned in *N_ROWS if non-NULL. */ - static int tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) { @@ -12356,6 +12356,7 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) /* Initialize an iterator for iteration over F->desired_tool_bar_string in the tool-bar window of frame F. */ init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID); + temp_row->reversed_p = false; it.first_visible_x = 0; it.last_visible_x = WINDOW_PIXEL_WIDTH (w); reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); @@ -12381,11 +12382,6 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) #endif /* !USE_GTK && !HAVE_NS */ -#if defined USE_GTK || defined HAVE_NS -EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST; -EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST; -#endif - DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height, 0, 2, 0, doc: /* Return the number of lines occupied by the tool bar of FRAME. @@ -12416,7 +12412,6 @@ PIXELWISE non-nil means return the height of the tool bar in pixels. */) /* Display the tool-bar of frame F. Value is non-zero if tool-bar's height should be changed. */ - static int redisplay_tool_bar (struct frame *f) { @@ -12438,7 +12433,7 @@ redisplay_tool_bar (struct frame *f) can turn off tool-bars by specifying tool-bar-lines zero. */ if (!WINDOWP (f->tool_bar_window) || (w = XWINDOW (f->tool_bar_window), - WINDOW_PIXEL_HEIGHT (w) == 0)) + WINDOW_TOTAL_LINES (w) == 0)) return 0; /* Set up an iterator for the tool-bar window. */ @@ -12446,6 +12441,7 @@ redisplay_tool_bar (struct frame *f) it.first_visible_x = 0; it.last_visible_x = WINDOW_PIXEL_WIDTH (w); row = it.glyph_row; + row->reversed_p = false; /* Build a string that represents the contents of the tool-bar. */ build_desired_tool_bar_string (f); @@ -12465,14 +12461,7 @@ redisplay_tool_bar (struct frame *f) if (new_height != WINDOW_PIXEL_HEIGHT (w)) { - Lisp_Object frame; - int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1) - / FRAME_LINE_HEIGHT (f)); - - XSETFRAME (frame, f); - Fmodify_frame_parameters (frame, - list1 (Fcons (Qtool_bar_lines, - make_number (new_lines)))); + x_change_tool_bar_height (f, new_height); /* Always do that now. */ clear_glyph_matrix (w->desired_matrix); f->fonts_changed = 1; @@ -12525,14 +12514,11 @@ redisplay_tool_bar (struct frame *f) if (!NILP (Vauto_resize_tool_bars)) { - /* Do we really allow the toolbar to occupy the whole frame? */ - int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f); int change_height_p = 0; /* If we couldn't display everything, change the tool-bar's height if there is room for more. */ - if (IT_STRING_CHARPOS (it) < it.end_charpos - && it.current_y < max_tool_bar_height) + if (IT_STRING_CHARPOS (it) < it.end_charpos) change_height_p = 1; /* We subtract 1 because display_tool_bar_line advances the @@ -12551,15 +12537,13 @@ redisplay_tool_bar (struct frame *f) /* If row displays tool-bar items, but is partially visible, change the tool-bar's height. */ if (MATRIX_ROW_DISPLAYS_TEXT_P (row) - && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y - && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height) + && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y) change_height_p = 1; /* Resize windows as needed by changing the `tool-bar-lines' frame parameter. */ if (change_height_p) { - Lisp_Object frame; int nrows; int new_height = tool_bar_height (f, &nrows, 1); @@ -12571,35 +12555,12 @@ redisplay_tool_bar (struct frame *f) if (change_height_p) { - /* Current size of the tool-bar window in canonical line - units. */ - int old_lines = WINDOW_TOTAL_LINES (w); - /* Required size of the tool-bar window in canonical - line units. */ - int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1) - / FRAME_LINE_HEIGHT (f)); - /* Maximum size of the tool-bar window in canonical line - units that this frame can allow. */ - int max_lines = - WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1; - - /* Don't try to change the tool-bar window size and set - the fonts_changed flag unless really necessary. That - flag causes redisplay to give up and retry - redisplaying the frame from scratch, so setting it - unnecessarily can lead to nasty redisplay loops. */ - if (new_lines <= max_lines - && eabs (new_lines - old_lines) >= 1) - { - XSETFRAME (frame, f); - Fmodify_frame_parameters (frame, - list1 (Fcons (Qtool_bar_lines, - make_number (new_lines)))); - clear_glyph_matrix (w->desired_matrix); - f->n_tool_bar_rows = nrows; - f->fonts_changed = 1; - return 1; - } + x_change_tool_bar_height (f, new_height); + clear_glyph_matrix (w->desired_matrix); + f->n_tool_bar_rows = nrows; + f->fonts_changed = 1; + + return 1; } } } @@ -12724,7 +12685,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, where the button was pressed, disregarding where it was released. */ if (NILP (Vmouse_highlight) && !down_p) - prop_idx = last_tool_bar_item; + prop_idx = f->last_tool_bar_item; /* If item is disabled, do nothing. */ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); @@ -12736,7 +12697,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, /* Show item in pressed state. */ if (!NILP (Vmouse_highlight)) show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); - last_tool_bar_item = prop_idx; + f->last_tool_bar_item = prop_idx; } else { @@ -12761,7 +12722,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, event.arg = key; event.modifiers = modifiers; kbd_buffer_store_event (&event); - last_tool_bar_item = -1; + f->last_tool_bar_item = -1; } } @@ -12811,8 +12772,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) mouse_down_p = (x_mouse_grabbed (dpyinfo) && f == dpyinfo->last_mouse_frame); - if (mouse_down_p - && last_tool_bar_item != prop_idx) + if (mouse_down_p && f->last_tool_bar_item != prop_idx) return; draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; @@ -12934,7 +12894,20 @@ hscroll_window_tree (Lisp_Object window) /* Scroll when cursor is inside this scroll margin. */ h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w); + /* If the position of this window's point has explicitly + changed, no more suspend auto hscrolling. */ + if (NILP (Fequal (Fwindow_point (window), Fwindow_old_point (window)))) + w->suspend_auto_hscroll = 0; + + /* Remember window point. */ + Fset_marker (w->old_pointm, + ((w == XWINDOW (selected_window)) + ? make_number (BUF_PT (XBUFFER (w->contents))) + : Fmarker_position (w->pointm)), + w->contents); + if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents)) + && w->suspend_auto_hscroll == 0 /* In some pathological cases, like restoring a window configuration into a frame that is much smaller than the one from which the configuration was saved, we @@ -12947,8 +12920,7 @@ hscroll_window_tree (Lisp_Object window) inside the left margin and the window is already hscrolled. */ && ((!row_r2l_p - && ((w->hscroll - && w->cursor.x <= h_margin) + && ((w->hscroll && w->cursor.x <= h_margin) || (cursor_row->enabled_p && cursor_row->truncated_on_right_p && (w->cursor.x >= text_area_width - h_margin)))) @@ -15839,9 +15811,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste return rc; } -#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK -static -#endif + void set_vertical_scroll_bar (struct window *w) { @@ -15880,6 +15850,71 @@ set_vertical_scroll_bar (struct window *w) } +void +set_horizontal_scroll_bar (struct window *w) +{ + int start, end, whole, portion; + + if (!MINI_WINDOW_P (w) + || (w == XWINDOW (minibuf_window) + && NILP (echo_area_buffer[0]))) + { + struct buffer *b = XBUFFER (w->contents); + struct buffer *old_buffer = NULL; + struct it it; + struct text_pos startp; + + if (b != current_buffer) + { + old_buffer = current_buffer; + set_buffer_internal (b); + } + + SET_TEXT_POS_FROM_MARKER (startp, w->start); + start_display (&it, w, startp); + it.last_visible_x = INT_MAX; + whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1, + MOVE_TO_X | MOVE_TO_Y); + /* whole = move_it_to (&it, w->window_end_pos, INT_MAX, + window_box_height (w), -1, + MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); */ + + start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)); + end = start + window_box_width (w, TEXT_AREA); + portion = end - start; + /* After enlarging a horizontally scrolled window such that it + gets at least as wide as the text it contains, make sure that + the thumb doesn't fill the entire scroll bar so we can still + drag it back to see the entire text. */ + whole = max (whole, end); + + if (it.bidi_p) + { + Lisp_Object pdir; + + pdir = Fcurrent_bidi_paragraph_direction (Qnil); + if (EQ (pdir, Qright_to_left)) + { + start = whole - end; + end = start + portion; + } + } + + if (old_buffer) + set_buffer_internal (old_buffer); + } + else + start = end = whole = portion = 0; + + w->hscroll_whole = whole; + + /* Indicate what this scroll bar ought to be displaying now. */ + if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook) + (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook) + (w, portion, whole, start); +} + + /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only selected_window is redisplayed. @@ -16093,6 +16128,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) { ptrdiff_t new_pt = marker_position (w->pointm); ptrdiff_t new_pt_byte = marker_byte_position (w->pointm); + if (new_pt < BEGV) { new_pt = BEGV; @@ -16866,7 +16902,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) redisplay_tool_bar (f); #else if (WINDOWP (f->tool_bar_window) - && (FRAME_TOOL_BAR_HEIGHT (f) > 0 + && (FRAME_TOOL_BAR_LINES (f) > 0 || !NILP (Vauto_resize_tool_bars)) && redisplay_tool_bar (f)) ignore_mouse_drag_p = 1; @@ -16906,10 +16942,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) ; finish_scroll_bars: - if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) + if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) { - /* Set the thumb's position and size. */ - set_vertical_scroll_bar (w); + if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) + /* Set the thumb's position and size. */ + set_vertical_scroll_bar (w); + + if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) + /* Set the thumb's position and size. */ + set_horizontal_scroll_bar (w); /* Note that we actually used the scroll bar attached to this window, so it shouldn't be deleted at the end of redisplay. */ @@ -16965,6 +17006,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) /* Initialize iterator and info to start at POS. */ start_display (&it, w, pos); + it.glyph_row->reversed_p = false; /* Display all lines of W. */ while (it.current_y < it.last_visible_y) @@ -17148,6 +17190,7 @@ try_window_reusing_current_matrix (struct window *w) && it.current.dpvec_index < 0) break; + it.glyph_row->reversed_p = false; if (display_line (&it)) last_text_row = it.glyph_row - 1; @@ -18168,6 +18211,11 @@ try_window_id (struct window *w) w->cursor.vpos = -1; last_text_row = NULL; overlay_arrow_seen = 0; + if (it.current_y < it.last_visible_y + && !f->fonts_changed + && (first_unchanged_at_end_row == NULL + || IT_CHARPOS (it) < stop_pos)) + it.glyph_row->reversed_p = false; while (it.current_y < it.last_visible_y && !f->fonts_changed && (first_unchanged_at_end_row == NULL @@ -18712,10 +18760,10 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs) else if (glyphs == 1) { int area; + char s[SHRT_MAX + 4]; for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) { - char *s = alloca (row->used[area] + 4); int i; for (i = 0; i < row->used[area]; ++i) @@ -18868,7 +18916,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) struct buffer *buffer = XBUFFER (w->contents); struct buffer *old = current_buffer; const unsigned char *arrow_string = SDATA (overlay_arrow_string); - int arrow_len = SCHARS (overlay_arrow_string); + ptrdiff_t arrow_len = SCHARS (overlay_arrow_string); const unsigned char *arrow_end = arrow_string + arrow_len; const unsigned char *p; struct it it; @@ -18877,6 +18925,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) set_buffer_temp (buffer); init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID); + scratch_glyph_row.reversed_p = false; it.glyph_row->used[TEXT_AREA] = 0; SET_TEXT_POS (it.position, 0, 0); @@ -20915,7 +20964,8 @@ See also `bidi-paragraph-direction'. */) the previous non-empty line. */ if (pos >= ZV && pos > BEGV) DEC_BOTH (pos, bytepos); - if (fast_looking_at (build_string ("[\f\t ]*\n"), + AUTO_STRING (trailing_white_space, "[\f\t ]*\n"); + if (fast_looking_at (trailing_white_space, pos, bytepos, ZV, ZV_BYTE, Qnil) > 0) { while ((c = FETCH_BYTE (bytepos)) == '\n' @@ -21026,7 +21076,7 @@ Value is the new character position of point. */) if ((gpt->resolved_level - row->reversed_p) % 2 == 0) new_pos += (row->reversed_p ? -dir : dir); else - new_pos -= (row->reversed_p ? -dir : dir);; + new_pos -= (row->reversed_p ? -dir : dir); } else if (BUFFERP (g->object)) new_pos = g->charpos; @@ -21416,6 +21466,114 @@ Value is the new character position of point. */) #undef ROW_GLYPH_NEWLINE_P } +DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels, + Sbidi_resolved_levels, 0, 1, 0, + doc: /* Return the resolved bidirectional levels of characters at VPOS. + +The resolved levels are produced by the Emacs bidi reordering engine +that implements the UBA, the Unicode Bidirectional Algorithm. Please +read the Unicode Standard Annex 9 (UAX#9) for background information +about these levels. + +VPOS is the zero-based number of the current window's screen line +for which to produce the resolved levels. If VPOS is nil or omitted, +it defaults to the screen line of point. If the window displays a +header line, VPOS of zero will report on the header line, and first +line of text in the window will have VPOS of 1. + +Value is an array of resolved levels, indexed by glyph number. +Glyphs are numbered from zero starting from the beginning of the +screen line, i.e. the left edge of the window for left-to-right lines +and from the right edge for right-to-left lines. The resolved levels +are produced only for the window's text area; text in display margins +is not included. + +If the selected window's display is not up-to-date, or if the specified +screen line does not display text, this function returns nil. It is +highly recommended to bind this function to some simple key, like F8, +in order to avoid these problems. + +This function exists mainly for testing the correctness of the +Emacs UBA implementation, in particular with the test suite. */) + (Lisp_Object vpos) +{ + struct window *w = XWINDOW (selected_window); + struct buffer *b = XBUFFER (w->contents); + int nrow; + struct glyph_row *row; + + if (NILP (vpos)) + { + int d1, d2, d3, d4, d5; + + pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow); + } + else + { + CHECK_NUMBER_COERCE_MARKER (vpos); + nrow = XINT (vpos); + } + + /* We require up-to-date glyph matrix for this window. */ + if (w->window_end_valid + && !windows_or_buffers_changed + && b + && !b->clip_changed + && !b->prevent_redisplay_optimizations_p + && !window_outdated (w) + && nrow >= 0 + && nrow < w->current_matrix->nrows + && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p + && MATRIX_ROW_DISPLAYS_TEXT_P (row)) + { + struct glyph *g, *e, *g1; + int nglyphs, i; + Lisp_Object levels; + + if (!row->reversed_p) /* Left-to-right glyph row. */ + { + g = g1 = row->glyphs[TEXT_AREA]; + e = g + row->used[TEXT_AREA]; + + /* Skip over glyphs at the start of the row that was + generated by redisplay for its own needs. */ + while (g < e + && INTEGERP (g->object) + && g->charpos < 0) + g++; + g1 = g; + + /* Count the "interesting" glyphs in this row. */ + for (nglyphs = 0; g < e && !INTEGERP (g->object); g++) + nglyphs++; + + /* Create and fill the array. */ + levels = make_uninit_vector (nglyphs); + for (i = 0; g1 < g; i++, g1++) + ASET (levels, i, make_number (g1->resolved_level)); + } + else /* Right-to-left glyph row. */ + { + g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1; + e = row->glyphs[TEXT_AREA] - 1; + while (g > e + && INTEGERP (g->object) + && g->charpos < 0) + g--; + g1 = g; + for (nglyphs = 0; g > e && !INTEGERP (g->object); g--) + nglyphs++; + levels = make_uninit_vector (nglyphs); + for (i = 0; g1 > g; i++, g1--) + ASET (levels, i, make_number (g1->resolved_level)); + } + return levels; + } + else + return Qnil; +} + + /*********************************************************************** Menu Bar @@ -21494,6 +21652,7 @@ display_menu_bar (struct window *w) clear_glyph_row (row); row->enabled_p = true; row->full_width_p = 1; + row->reversed_p = false; } /* Display all items of the menu bar. */ @@ -22727,10 +22886,8 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_ } else if (CHARACTERP (eoltype)) { - unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH); int c = XFASTINT (eoltype); - eol_str_len = CHAR_STRING (c, tmp); - eol_str = tmp; + return buf + CHAR_STRING (c, (unsigned char *) buf); } else { @@ -22866,7 +23023,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, } case 'e': -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC { if (NILP (Vmemory_full)) return ""; @@ -23007,7 +23164,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, return decode_mode_spec_buf; no_value: { - char* p = decode_mode_spec_buf; + char *p = decode_mode_spec_buf; int pad = width - 2; while (pad-- > 0) *p++ = ' '; @@ -23759,7 +23916,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)); } - prop = buffer_local_value_1 (prop, it->w->contents); + prop = buffer_local_value (prop, it->w->contents); if (EQ (prop, Qunbound)) prop = Qnil; } @@ -23811,7 +23968,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (pixels); } - car = buffer_local_value_1 (car, it->w->contents); + car = buffer_local_value (car, it->w->contents); if (EQ (car, Qunbound)) car = Qnil; } @@ -23988,7 +24145,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id, #endif { eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); } return face; @@ -24011,7 +24168,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, /* Make sure X resources of the face are allocated. */ eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); if (two_byte_p) *two_byte_p = 0; @@ -24328,7 +24485,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end) s->ybase += voffset; /* The case that face->gc == 0 is handled when drawing the glyph - string by calling PREPARE_FACE_FOR_DISPLAY. */ + string by calling prepare_face_for_display. */ eassert (s->face); return glyph - s->row->glyphs[s->area]; } @@ -24646,7 +24803,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) face_id = (row)->glyphs[area][START].face_id; \ \ s = alloca (sizeof *s); \ - char2b = alloca ((END - START) * sizeof *char2b); \ + SAFE_NALLOCA (char2b, 1, (END) - (START)); \ INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&HEAD, &TAIL, s); \ s->x = (X); \ @@ -24674,7 +24831,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) struct glyph_string *first_s = NULL; \ int n; \ \ - char2b = alloca (cmp->glyph_len * sizeof *char2b); \ + SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \ \ /* Make glyph_strings for each glyph sequence that is drawable by \ the same face, and append them to HEAD/TAIL. */ \ @@ -24709,7 +24866,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) gstring = (composition_gstring_from_id \ ((row)->glyphs[area][START].u.cmp.id)); \ s = alloca (sizeof *s); \ - char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b); \ + SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \ INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&(HEAD), &(TAIL), s); \ s->x = (X); \ @@ -24861,6 +25018,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, BUILD_GLYPH_STRINGS will modify its start parameter. That's the reason we use a separate variable `i'. */ i = start; + USE_SAFE_ALLOCA; BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x); if (tail) x_reached = tail->x + tail->background_width; @@ -24926,13 +25084,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_head = head; j = i; BUILD_GLYPH_STRINGS (j, start, h, t, overlap_hl, dummy_x, last_x); start = i; compute_overhangs_and_x (t, head->x, 1); prepend_glyph_string_lists (&head, &tail, h, t); - clip_head = head; + if (clip_head == NULL) + clip_head = head; } /* Prepend glyph strings for glyphs in front of the first glyph @@ -24953,7 +25114,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_head = head; + if (hl == overlap_hl || clip_head == NULL) + clip_head = head; BUILD_GLYPH_STRINGS (i, start, h, t, overlap_hl, dummy_x, last_x); for (s = h; s; s = s->next) @@ -24977,13 +25139,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_tail = tail; BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); /* Because BUILD_GLYPH_STRINGS updates the first argument, we don't have `end = i;' here. */ compute_overhangs_and_x (h, tail->x + tail->width, 0); append_glyph_string_lists (&head, &tail, h, t); - clip_tail = tail; + if (clip_tail == NULL) + clip_tail = tail; } /* Append glyph strings for glyphs following the last glyph @@ -25001,7 +25166,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_tail = tail; + if (hl == overlap_hl || clip_tail == NULL) + clip_tail = tail; i++; /* We must include the Ith glyph. */ BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); @@ -25052,6 +25218,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, RELEASE_HDC (hdc, f); + SAFE_FREE (); return x_reached; } @@ -25137,8 +25304,7 @@ append_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -25221,8 +25387,7 @@ append_composite_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } ++it->glyph_row->used[area]; @@ -25269,7 +25434,7 @@ produce_image_glyph (struct it *it) face = FACE_FROM_ID (it->f, it->face_id); eassert (face); /* Make sure X resources of the face is loaded. */ - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->image_id < 0) { @@ -25410,8 +25575,7 @@ produce_image_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } ++it->glyph_row->used[area]; @@ -25499,8 +25663,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object, if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -25565,7 +25728,7 @@ produce_stretch_glyph (struct it *it) { struct face *face = FACE_FROM_ID (it->f, it->face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); } #endif @@ -25959,8 +26122,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len, if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } ++it->glyph_row->used[area]; @@ -26028,7 +26190,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) face = FACE_FROM_ID (it->f, face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) { @@ -26044,7 +26206,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c); str = buf; } - for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++) + for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++) code[len] = font->driver->encode_char (font, str[len]); upper_len = (len + 1) / 2; font->driver->text_extents (font, code, upper_len, @@ -27369,9 +27531,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row, /* Erase the image of a cursor of window W from the screen. */ -#ifndef HAVE_NTGUI -static -#endif void erase_phys_cursor (struct window *w) { @@ -27451,7 +27610,7 @@ erase_phys_cursor (struct window *w) /* Maybe clear the display under the cursor. */ if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) { - int x, y, left_x; + int x, y; int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); int width; @@ -27460,13 +27619,15 @@ erase_phys_cursor (struct window *w) goto mark_cursor_off; width = cursor_glyph->pixel_width; - left_x = window_box_left_offset (w, TEXT_AREA); x = w->phys_cursor.x; - if (x < left_x) - width -= left_x - x; + if (x < 0) + { + width += x; + x = 0; + } width = min (width, window_box_width (w, TEXT_AREA) - x); y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y)); - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x)); + x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x); if (width > 0) FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height); @@ -28901,8 +29062,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, else if (area == ON_MODE_LINE) { Lisp_Object default_help - = buffer_local_value_1 (Qmode_line_default_help_echo, - w->contents); + = buffer_local_value (Qmode_line_default_help_echo, + w->contents); if (STRINGP (default_help)) { @@ -29196,7 +29357,8 @@ note_mouse_highlight (struct frame *f, int x, int y) else cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE - || part == ON_SCROLL_BAR) + || part == ON_VERTICAL_SCROLL_BAR + || part == ON_HORIZONTAL_SCROLL_BAR) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else cursor = FRAME_X_OUTPUT (f)->text_cursor; @@ -29319,6 +29481,8 @@ note_mouse_highlight (struct frame *f, int x, int y) /* Is this char mouse-active or does it have help-echo? */ position = make_number (pos); + USE_SAFE_ALLOCA; + if (BUFFERP (object)) { /* Put all the overlays we want in a vector in overlay_vec. */ @@ -29600,6 +29764,7 @@ note_mouse_highlight (struct frame *f, int x, int y) BEGV = obegv; ZV = ozv; current_buffer = obuf; + SAFE_FREE (); } set_cursor: @@ -30117,8 +30282,8 @@ expose_frame (struct frame *f, int x, int y, int w, int h) if (w == 0 || h == 0) { r.x = r.y = 0; - r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f); - r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f); + r.width = FRAME_TEXT_WIDTH (f); + r.height = FRAME_TEXT_HEIGHT (f); } else { @@ -30373,6 +30538,7 @@ syms_of_xdisp (void) DEFSYM (Qright_to_left, "right-to-left"); DEFSYM (Qleft_to_right, "left-to-right"); + defsubr (&Sbidi_resolved_levels); #ifdef HAVE_WINDOW_SYSTEM DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p, @@ -30404,8 +30570,9 @@ A value of nil means no special handling of these characters. */); DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer, doc: /* The pointer shape to show in void text areas. -A value of nil means to show the text pointer. Other options are `arrow', -`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'. */); +A value of nil means to show the text pointer. Other options are +`arrow', `text', `hand', `vdrag', `hdrag', `nhdrag', `modeline', and +`hourglass'. */); Vvoid_text_area_pointer = Qarrow; DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay, @@ -30778,6 +30945,12 @@ To add a prefix to continuation lines, use `wrap-prefix'. */); doc: /* Non-nil means don't free realized faces. Internal use only. */); inhibit_free_realized_faces = 0; + DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring, + doc: /* Non-nil means don't mirror characters even when bidi context requires that. +Intended for use during debugging and for testing bidi display; +see biditest.el in the test suite. */); + inhibit_bidi_mirroring = 0; + #ifdef GLYPH_DEBUG DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id, doc: /* Inhibit try_window_id display optimization. */); @@ -30900,10 +31073,10 @@ init_xdisp (void) r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f); r->total_cols = FRAME_COLS (f); r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f); - r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f); + r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f); r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f); - m->top_line = FRAME_LINES (f) - 1; + m->top_line = FRAME_TOTAL_LINES (f) - 1; m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f); m->total_cols = FRAME_COLS (f); m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f); @@ -30936,7 +31109,38 @@ init_xdisp (void) /* Platform-independent portion of hourglass implementation. */ +/* Timer function of hourglass_atimer. */ + +static void +show_hourglass (struct atimer *timer) +{ + /* The timer implementation will cancel this timer automatically + after this function has run. Set hourglass_atimer to null + so that we know the timer doesn't have to be canceled. */ + hourglass_atimer = NULL; + + if (!hourglass_shown_p) + { + Lisp_Object tail, frame; + + block_input (); + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f) + && FRAME_RIF (f)->show_hourglass) + FRAME_RIF (f)->show_hourglass (f); + } + + hourglass_shown_p = 1; + unblock_input (); + } +} + /* Cancel a currently active hourglass timer, and start a new one. */ + void start_hourglass (void) { @@ -30955,20 +31159,13 @@ start_hourglass (void) else delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0); -#ifdef HAVE_NTGUI - { - extern void w32_note_current_window (void); - w32_note_current_window (); - } -#endif /* HAVE_NTGUI */ - hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay, show_hourglass, NULL); } - /* Cancel the hourglass cursor timer if active, hide a busy cursor if shown. */ + void cancel_hourglass (void) { @@ -30979,7 +31176,28 @@ cancel_hourglass (void) } if (hourglass_shown_p) - hide_hourglass (); + { + Lisp_Object tail, frame; + + block_input (); + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f) + && FRAME_RIF (f)->hide_hourglass) + FRAME_RIF (f)->hide_hourglass (f); +#ifdef HAVE_NTGUI + /* No cursors on non GUI frames - restore to stock arrow cursor. */ + else if (!FRAME_W32_P (f)) + w32_arrow_cursor (); +#endif + } + + hourglass_shown_p = 0; + unblock_input (); + } } #endif /* HAVE_WINDOW_SYSTEM */ diff --git a/src/xfaces.c b/src/xfaces.c index 1dc068cf18a..6afa0a2953d 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -273,10 +273,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface) -/* Value is the number of elements of VECTOR. */ - -#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR)) - /* Size of hash table of realized faces in face caches (should be a prime number). */ @@ -515,7 +511,7 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0, fputc ('\n', stderr); - for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i) + for (i = n = 0; i < ARRAYELTS (color_count); ++i) if (color_count[i]) { fprintf (stderr, "%3d: %5d", i, color_count[i]); @@ -1072,7 +1068,7 @@ tty_color_name (struct frame *f, int idx) return XCAR (coldesc); } #ifdef MSDOS - /* We can have an MSDOG frame under -nw for a short window of + /* We can have an MS-DOS frame under -nw for a short window of opportunity before internal_terminal_init is called. DTRT. */ if (FRAME_MSDOS_P (f) && !inhibit_window_system) return msdos_stdcolor_name (idx); @@ -1242,9 +1238,6 @@ load_color2 (struct frame *f, struct face *face, Lisp_Object name, record that fact in flags of the face so that we don't try to free these colors. */ -#ifndef MSDOS -static -#endif unsigned long load_color (struct frame *f, struct face *face, Lisp_Object name, enum lface_attribute_index target_index) @@ -3124,8 +3117,7 @@ FRAME 0 means change the face on all frames, and change the default If frame is t, and selected frame is a tty frame, the font can't be realized. An improvement would be to loop over frames for a non-tty frame and use that. See discussion in - bug#18573. - */ + bug#18573. */ if (f->terminal->type != output_termcap) { if (! FONT_OBJECT_P (value)) @@ -3415,7 +3407,8 @@ set_font_frame_param (Lisp_Object frame, Lisp_Object lface) ASET (lface, LFACE_FONT_INDEX, font); } f->default_face_done_p = 0; - Fmodify_frame_parameters (frame, list1 (Fcons (Qfont, font))); + AUTO_FRAME_ARG (arg, Qfont, font); + Fmodify_frame_parameters (frame, arg); } } @@ -3804,18 +3797,23 @@ Default face attributes override any local face attributes. */) && newface->font) { Lisp_Object name = newface->font->props[FONT_NAME_INDEX]; - Fmodify_frame_parameters (frame, list1 (Fcons (Qfont, name))); + AUTO_FRAME_ARG (arg, Qfont, name); + Fmodify_frame_parameters (frame, arg); } if (STRINGP (gvec[LFACE_FOREGROUND_INDEX])) - Fmodify_frame_parameters (frame, - list1 (Fcons (Qforeground_color, - gvec[LFACE_FOREGROUND_INDEX]))); + { + AUTO_FRAME_ARG (arg, Qforeground_color, + gvec[LFACE_FOREGROUND_INDEX]); + Fmodify_frame_parameters (frame, arg); + } if (STRINGP (gvec[LFACE_BACKGROUND_INDEX])) - Fmodify_frame_parameters (frame, - list1 (Fcons (Qbackground_color, - gvec[LFACE_BACKGROUND_INDEX]))); + { + AUTO_FRAME_ARG (arg, Qbackground_color, + gvec[LFACE_BACKGROUND_INDEX]); + Fmodify_frame_parameters (frame, arg); + } } } @@ -4105,15 +4103,15 @@ free_realized_face (struct frame *f, struct face *face) } } +#ifdef HAVE_WINDOW_SYSTEM -/* Prepare face FACE for subsequent display on frame F. This - allocated GCs if they haven't been allocated yet or have been freed - by clearing the face cache. */ +/* Prepare face FACE for subsequent display on frame F. This must be called + before using X resources of FACE to allocate GCs if they haven't been + allocated yet or have been freed by clearing the face cache. */ void prepare_face_for_display (struct frame *f, struct face *face) { -#ifdef HAVE_WINDOW_SYSTEM eassert (FRAME_WINDOW_P (f)); if (face->gc == 0) @@ -4141,10 +4139,10 @@ prepare_face_for_display (struct frame *f, struct face *face) font_prepare_for_face (f, face); unblock_input (); } -#endif /* HAVE_WINDOW_SYSTEM */ } - +#endif /* HAVE_WINDOW_SYSTEM */ + /* Returns the `distance' between the colors X and Y. */ static int @@ -5093,14 +5091,14 @@ Value is ORDER. */) { Lisp_Object list; int i; - int indices[DIM (font_sort_order)]; + int indices[ARRAYELTS (font_sort_order)]; CHECK_LIST (order); memset (indices, 0, sizeof indices); i = 0; for (list = order; - CONSP (list) && i < DIM (indices); + CONSP (list) && i < ARRAYELTS (indices); list = XCDR (list), ++i) { Lisp_Object attr = XCAR (list); @@ -5122,9 +5120,9 @@ Value is ORDER. */) indices[i] = xlfd; } - if (!NILP (list) || i != DIM (indices)) + if (!NILP (list) || i != ARRAYELTS (indices)) signal_error ("Invalid font sort order", order); - for (i = 0; i < DIM (font_sort_order); ++i) + for (i = 0; i < ARRAYELTS (font_sort_order); ++i) if (indices[i] == 0) signal_error ("Invalid font sort order", order); @@ -5490,7 +5488,6 @@ realize_non_ascii_face (struct frame *f, Lisp_Object font_object, face = xmalloc (sizeof *face); *face = *base_face; face->gc = 0; - face->extra = NULL; face->overstrike = (! NILP (font_object) && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100 @@ -5565,7 +5562,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]) } if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) attrs[LFACE_FONT_INDEX] - = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]); + = font_load_for_lface (f, attrs, Ffont_spec (0, NULL)); if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) { face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]); @@ -5998,6 +5995,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, endpos = XINT (end); /* Look at properties from overlays. */ + USE_SAFE_ALLOCA; { ptrdiff_t next_overlay; @@ -6024,7 +6022,10 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, /* Optimize common cases where we can use the default face. */ if (noverlays == 0 && NILP (prop)) - return default_face->id; + { + SAFE_FREE (); + return default_face->id; + } /* Begin with attributes from the default face. */ memcpy (attrs, default_face->lface, sizeof attrs); @@ -6052,6 +6053,8 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, *endptr = endpos; + SAFE_FREE (); + /* Look up a realized face with the given face attributes, or realize a new one for ASCII characters. */ return lookup_face (f, attrs); @@ -6317,7 +6320,7 @@ dump_realized_face (struct face *face) { fprintf (stderr, "ID: %d\n", face->id); #ifdef HAVE_X_WINDOWS - fprintf (stderr, "gc: %ld\n", (long) face->gc); + fprintf (stderr, "gc: %p\n", face->gc); #endif fprintf (stderr, "foreground: 0x%lx (%s)\n", face->foreground, @@ -6348,7 +6351,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */) int i; fprintf (stderr, "font selection order: "); - for (i = 0; i < DIM (font_sort_order); ++i) + for (i = 0; i < ARRAYELTS (font_sort_order); ++i) fprintf (stderr, "%d ", font_sort_order[i]); fprintf (stderr, "\n"); diff --git a/src/xfns.c b/src/xfns.c index 96a4b07b150..8f5a06c0330 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "lisp.h" #include "xterm.h" +#include "menu.h" #include "frame.h" #include "window.h" #include "character.h" @@ -124,7 +125,6 @@ extern LWLIB_ID widget_id_tick; #define MAXREQUEST(dpy) (XMaxRequestSize (dpy)) -static Lisp_Object Qsuppress_icon; static Lisp_Object Qundefined_color; static Lisp_Object Qcompound_text, Qcancel_timer; Lisp_Object Qfont_param; @@ -159,7 +159,7 @@ check_x_display_info (Lisp_Object object) } else if (TERMINALP (object)) { - struct terminal *t = get_terminal (object, 1); + struct terminal *t = decode_live_terminal (object); if (t->type != output_x_window) error ("Terminal %d is not an X display", t->id); @@ -329,8 +329,43 @@ x_real_positions (struct frame *f, int *xptr, int *yptr) *yptr = real_y; } - +/* Get the mouse position in frame relative coordinates. */ + +void +x_relative_mouse_position (struct frame *f, int *x, int *y) +{ + Window root, dummy_window; + int dummy; + + eassert (FRAME_X_P (f)); + + block_input (); + + XQueryPointer (FRAME_X_DISPLAY (f), + DefaultRootWindow (FRAME_X_DISPLAY (f)), + + /* The root window which contains the pointer. */ + &root, + /* Window pointer is on, not used */ + &dummy_window, + + /* The position on that root window. */ + x, y, + + /* x/y in dummy_window coordinates, not used. */ + &dummy, &dummy, + + /* Modifier keys and pointer buttons, about which + we don't care. */ + (unsigned int *) &dummy); + + unblock_input (); + + /* Translate root window coordinates to window coordinates. */ + *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); + *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); +} /* Gamma-correct COLOR on frame F. */ @@ -422,15 +457,23 @@ x_set_tool_bar_position (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { - if (! EQ (new_value, Qleft) && ! EQ (new_value, Qright) - && ! EQ (new_value, Qbottom) && ! EQ (new_value, Qtop)) - return; - if (EQ (new_value, old_value)) return; + Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom); + if (!NILP (Fmemq (new_value, choice))) + { #ifdef USE_GTK - xg_change_toolbar_position (f, new_value); - fset_tool_bar_position (f, new_value); + if (!EQ (new_value, old_value)) + { + xg_change_toolbar_position (f, new_value); + fset_tool_bar_position (f, new_value); + } +#else + if (!EQ (new_value, Qtop)) + error ("The only supported tool bar position is top"); #endif + } + else + wrong_choice (choice, new_value); } #ifdef USE_GTK @@ -577,35 +620,6 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) } } -static Cursor -make_invisible_cursor (struct frame *f) -{ - Display *dpy = FRAME_X_DISPLAY (f); - static char const no_data[] = { 0 }; - Pixmap pix; - XColor col; - Cursor c = 0; - - x_catch_errors (dpy); - pix = XCreateBitmapFromData (dpy, FRAME_DISPLAY_INFO (f)->root_window, - no_data, 1, 1); - if (! x_had_errors_p (dpy) && pix != None) - { - Cursor pixc; - col.pixel = 0; - col.red = col.green = col.blue = 0; - col.flags = DoRed | DoGreen | DoBlue; - pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0); - if (! x_had_errors_p (dpy) && pixc != None) - c = pixc; - XFreePixmap (dpy, pix); - } - - x_uncatch_errors (); - - return c; -} - static void x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -723,9 +737,6 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) XDefineCursor (dpy, FRAME_X_WINDOW (f), f->output_data.x->current_cursor = cursor); - if (FRAME_DISPLAY_INFO (f)->invisible_cursor == 0) - FRAME_DISPLAY_INFO (f)->invisible_cursor = make_invisible_cursor (f); - if (cursor != x->text_cursor && x->text_cursor != 0) XFreeCursor (dpy, x->text_cursor); @@ -954,7 +965,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) } -void +static void x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { int nlines; @@ -998,7 +1009,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) #else /* not USE_X_TOOLKIT && not USE_GTK */ FRAME_MENU_BAR_LINES (f) = nlines; FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1); + adjust_frame_size (f, -1, -1, 2, 1); if (FRAME_X_WINDOW (f)) x_clear_under_internal_border (f); @@ -1049,14 +1060,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) height of all windows on frame F to match the new tool bar height. The frame's height doesn't change. */ -void +static void x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { int nlines; -#if ! defined (USE_GTK) - int delta, root_height; - int unit = FRAME_LINE_HEIGHT (f); -#endif /* Treat tool bars like menu bars. */ if (FRAME_MINIBUF_ONLY_P (f)) @@ -1068,11 +1075,18 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) else nlines = 0; -#ifdef USE_GTK + x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f)); +} + +/* Set the pixel height of the tool bar of frame F to HEIGHT. */ +void +x_change_tool_bar_height (struct frame *f, int height) +{ +#ifdef USE_GTK FRAME_TOOL_BAR_LINES (f) = 0; FRAME_TOOL_BAR_HEIGHT (f) = 0; - if (nlines) + if (height) { FRAME_EXTERNAL_TOOL_BAR (f) = 1; if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0) @@ -1086,39 +1100,25 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) free_frame_tool_bar (f); FRAME_EXTERNAL_TOOL_BAR (f) = 0; } - #else /* !USE_GTK */ + int unit = FRAME_LINE_HEIGHT (f); + int old_height = FRAME_TOOL_BAR_HEIGHT (f); + int lines = (height + unit - 1) / unit; /* Make sure we redisplay all windows in this frame. */ windows_or_buffers_changed = 60; - /* DELTA is in pixels now. */ - delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit; - - /* Don't resize the tool-bar to more than we have room for. Note: The - calculations below and the subsequent call to resize_frame_windows - are inherently flawed because they can make the toolbar higher than - the containing frame. */ - if (delta > 0) - { - root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f))); - if (root_height - delta < unit) - { - delta = root_height - unit; - /* When creating a new frame and toolbar mode is enabled, we - need at least one toolbar line. */ - nlines = max (FRAME_TOOL_BAR_LINES (f) + delta / unit, 1); - } - } - FRAME_TOOL_BAR_LINES (f) = nlines; - FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1); -#if !defined USE_X_TOOLKIT && !defined USE_GTK - if (FRAME_X_WINDOW (f)) - x_clear_under_internal_border (f); -#endif - adjust_frame_glyphs (f); + /* Recalculate tool bar and frame text sizes. */ + FRAME_TOOL_BAR_HEIGHT (f) = height; + FRAME_TOOL_BAR_LINES (f) = lines; + FRAME_TEXT_HEIGHT (f) + = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f)); + FRAME_LINES (f) + = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f)); + /* Store the `tool-bar-lines' and `height' frame parameters. */ + store_frame_param (f, Qtool_bar_lines, make_number (lines)); + store_frame_param (f, Qheight, make_number (FRAME_LINES (f))); /* We also have to make sure that the internal border at the top of the frame, below the menu bar or tool bar, is redrawn when the @@ -1132,30 +1132,50 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) clear_current_matrices (f); } - /* If the tool bar gets smaller, the internal border below it - has to be cleared. It was formerly part of the display - of the larger tool bar, and updating windows won't clear it. */ - if (delta < 0) + if ((height < old_height) && WINDOWP (f->tool_bar_window)) + clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); + + /* Recalculate toolbar height. */ + f->n_tool_bar_rows = 0; + + adjust_frame_size (f, -1, -1, 4, 0); + + if (FRAME_X_WINDOW (f)) + x_clear_under_internal_border (f); + +#endif /* USE_GTK */ +} + + +static void +x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + int border; + + CHECK_TYPE_RANGED_INTEGER (int, arg); + border = max (XINT (arg), 0); + + if (border != FRAME_INTERNAL_BORDER_WIDTH (f)) { - int height = FRAME_INTERNAL_BORDER_WIDTH (f); - int width = FRAME_PIXEL_WIDTH (f); - int y = nlines * unit; + FRAME_INTERNAL_BORDER_WIDTH (f) = border; - /* height can be zero here. */ - if (height > 0 && width > 0) +#ifdef USE_X_TOOLKIT + if (FRAME_X_OUTPUT (f)->edit_widget) + widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget); +#endif + + if (FRAME_X_WINDOW (f) != 0) { - block_input (); - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - 0, y, width, height); - unblock_input (); - } + adjust_frame_size (f, -1, -1, 3, 0); - if (WINDOWP (f->tool_bar_window)) - clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); +#ifdef USE_GTK + xg_clear_under_internal_border (f); +#else + x_clear_under_internal_border (f); +#endif + } } - run_window_configuration_change_hook (f); -#endif /* USE_GTK */ } @@ -1210,7 +1230,7 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old if (f->output_data.x->scroll_bar_background_pixel != -1) unload_color (f, f->output_data.x->scroll_bar_background_pixel); -#ifdef USE_TOOLKIT_SCROLL_BARS +#if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS) /* Scrollbar shadow colors. */ if (f->output_data.x->scroll_bar_top_shadow_pixel != -1) { @@ -1222,7 +1242,7 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel); f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; } -#endif /* USE_TOOLKIT_SCROLL_BARS */ +#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */ f->output_data.x->scroll_bar_background_pixel = pixel; if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f)) @@ -1249,10 +1269,6 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old CODING_SYSTEM, and return a newly allocated memory area which should be freed by `xfree' by a caller. - SELECTIONP non-zero means the string is being encoded for an X - selection, so it is safe to run pre-write conversions (which - may run Lisp code). - Store the byte length of resulting text in *TEXT_BYTES. If the text contains only ASCII and Latin-1, store 1 in *STRING_P, @@ -1261,8 +1277,8 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old the result should be `COMPOUND_TEXT'. */ static unsigned char * -x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp, - ptrdiff_t *text_bytes, int *stringp, int *freep) +x_encode_text (Lisp_Object string, Lisp_Object coding_system, + ptrdiff_t *text_bytes, int *stringp, bool *freep) { int result = string_xstring_p (string); struct coding_system coding; @@ -1305,7 +1321,7 @@ x_set_name_internal (struct frame *f, Lisp_Object name) XTextProperty text, icon; ptrdiff_t bytes; int stringp; - int do_free_icon_value = 0, do_free_text_value = 0; + bool do_free_icon_value = 0, do_free_text_value = 0; Lisp_Object coding_system; Lisp_Object encoded_name; Lisp_Object encoded_icon_name; @@ -1337,14 +1353,12 @@ x_set_name_internal (struct frame *f, Lisp_Object name) properties. Per the EWMH specification, those two properties are always UTF8_STRING. This matches what gtk_window_set_title() does in the USE_GTK case. */ - text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp, - &do_free_text_value); + text.value = x_encode_text (name, coding_system, &bytes, + &stringp, &do_free_text_value); text.encoding = (stringp ? XA_STRING : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); text.format = 8; text.nitems = bytes; - if (text.nitems != bytes) - error ("Window name too large"); if (!STRINGP (f->icon_name)) { @@ -1354,14 +1368,12 @@ x_set_name_internal (struct frame *f, Lisp_Object name) else { /* See the above comment "Note: Encoding strategy". */ - icon.value = x_encode_text (f->icon_name, coding_system, 0, - &bytes, &stringp, &do_free_icon_value); + icon.value = x_encode_text (f->icon_name, coding_system, &bytes, + &stringp, &do_free_icon_value); icon.encoding = (stringp ? XA_STRING : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); icon.format = 8; icon.nitems = bytes; - if (icon.nitems != bytes) - error ("Icon name too large"); encoded_icon_name = ENCODE_UTF_8 (f->icon_name); } @@ -1399,16 +1411,16 @@ x_set_name_internal (struct frame *f, Lisp_Object name) /* Change the name of frame F to NAME. If NAME is nil, set F's name to x_id_name. - If EXPLICIT is non-zero, that indicates that lisp code is setting the + If EXPLICIT is true, that indicates that lisp code is setting the name; if NAME is a string, set F's name to NAME and set F->explicit_name; if NAME is Qnil, then clear F->explicit_name. - If EXPLICIT is zero, that indicates that Emacs redisplay code is + If EXPLICIT is false, that indicates that Emacs redisplay code is suggesting a new name, which lisp code should override; if F->explicit_name is set, ignore the new name; otherwise, set it. */ static void -x_set_name (struct frame *f, Lisp_Object name, int explicit) +x_set_name (struct frame *f, Lisp_Object name, bool explicit) { /* Make sure that requests from lisp code override requests from Emacs redisplay code. */ @@ -1505,14 +1517,36 @@ x_set_scroll_bar_default_width (struct frame *f) FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit; FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw; #else - /* The width of a non-toolkit scrollbar is at least 14 pixels and a - multiple of the frame's character width. */ + /* The width of a non-toolkit scrollbar is 14 pixels. */ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit; FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit; #endif } +void +x_set_scroll_bar_default_height (struct frame *f) +{ + int height = FRAME_LINE_HEIGHT (f); +#ifdef USE_TOOLKIT_SCROLL_BARS +#ifdef USE_GTK + int min_height = xg_get_default_scrollbar_height (); +#else + int min_height = 16; +#endif + /* A minimum height of 14 doesn't look good for toolkit scroll bars. */ + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height; + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height; +#else + /* The height of a non-toolkit scrollbar is 14 pixels. */ + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height; + + /* Use all of that space (aside from required margins) for the + scroll bar. */ + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14; +#endif +} + /* Record in frame F the specified or default value according to ALIST of the parameter named PROP (a Lisp symbol). If no value is @@ -1535,13 +1569,14 @@ x_default_scroll_bar_color_parameter (struct frame *f, /* See if an X resource for the scroll bar color has been specified. */ - tem = display_x_get_resource (dpyinfo, - build_string (foreground_p - ? "foreground" - : "background"), - empty_unibyte_string, - build_string ("verticalScrollBar"), - empty_unibyte_string); + AUTO_STRING (foreground, "foreground"); + AUTO_STRING (background, "foreground"); + AUTO_STRING (verticalScrollBar, "verticalScrollBar"); + tem = (display_x_get_resource + (dpyinfo, foreground_p ? foreground : background, + empty_unibyte_string, + verticalScrollBar, + empty_unibyte_string)); if (!STRINGP (tem)) { /* If nothing has been specified, scroll bars will use a @@ -1559,7 +1594,8 @@ x_default_scroll_bar_color_parameter (struct frame *f, #endif /* not USE_TOOLKIT_SCROLL_BARS */ } - x_set_frame_parameters (f, list1 (Fcons (prop, tem))); + AUTO_FRAME_ARG (arg, prop, tem); + x_set_frame_parameters (f, arg); return tem; } @@ -1592,7 +1628,7 @@ hack_wm_protocols (struct frame *f, Widget widget) if ((XGetWindowProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols, - (long)0, (long)100, False, XA_ATOM, + 0, 100, False, XA_ATOM, &type, &format, &nitems, &bytes_after, &catoms) == Success) @@ -1750,7 +1786,7 @@ xic_create_fontsetname (const char *base_fontname, int motif) len = p - base_fontname + strlen (allcs) + 1; font_allcs = alloca (len); memcpy (font_allcs, base_fontname, p - base_fontname); - strcat (font_allcs, allcs); + strcpy (font_allcs + (p - base_fontname), allcs); /* Build the font spec that matches all families and add-styles. */ @@ -1758,7 +1794,7 @@ xic_create_fontsetname (const char *base_fontname, int motif) font_allfamilies = alloca (len); strcpy (font_allfamilies, allfamilies); memcpy (font_allfamilies + strlen (allfamilies), p1, p - p1); - strcat (font_allfamilies, allcs); + strcpy (font_allfamilies + strlen (allfamilies) + (p - p1), allcs); /* Build the font spec that matches all. */ len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1; @@ -1766,7 +1802,8 @@ xic_create_fontsetname (const char *base_fontname, int motif) strcpy (font_all, allfamilies); strcat (font_all, all); memcpy (font_all + strlen (all) + strlen (allfamilies), p2, p - p2); - strcat (font_all, allcs); + strcpy (font_all + strlen (all) + strlen (allfamilies) + (p - p2), + allcs); /* Build the actual font set name. */ len = strlen (base_fontname) + strlen (font_allcs) @@ -1944,8 +1981,7 @@ static XIMStyle best_xim_style (XIMStyles *xim) { int i, j; - int nr_supported = - sizeof (supported_xim_styles) / sizeof (supported_xim_styles[0]); + int nr_supported = ARRAYELTS (supported_xim_styles); for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) @@ -2253,8 +2289,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) /* Do some needed geometry management. */ { - char *tem, shell_position[sizeof "=x++" + 4 * INT_STRLEN_BOUND (int)]; - Arg gal[10]; + Arg gal[3]; int gac = 0; int extra_borders = 0; int menubar_size @@ -2273,7 +2308,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) } #endif - f->output_data.x->menubar_height = menubar_size; + FRAME_MENUBAR_HEIGHT (f) = menubar_size; #ifndef USE_LUCID /* Motif seems to need this amount added to the sizes @@ -2284,6 +2319,8 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) extra_borders *= 2; #endif + f->shell_position = xmalloc (sizeof "=x++" + 4 * INT_STRLEN_BOUND (int)); + /* Convert our geometry parameters into a geometry string and specify it. Note that we do not specify here whether the position @@ -2300,14 +2337,14 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) top = -top; if (window_prompting & USPosition) - sprintf (shell_position, "=%dx%d%c%d%c%d", + sprintf (f->shell_position, "=%dx%d%c%d%c%d", FRAME_PIXEL_WIDTH (f) + extra_borders, FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders, (xneg ? '-' : '+'), left, (yneg ? '-' : '+'), top); else { - sprintf (shell_position, "=%dx%d", + sprintf (f->shell_position, "=%dx%d", FRAME_PIXEL_WIDTH (f) + extra_borders, FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders); @@ -2321,12 +2358,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) } } - /* We don't free this because we don't know whether - it is safe to free it while the frame exists. - It isn't worth the trouble of arranging to free it - when the frame is deleted. */ - tem = xstrdup (shell_position); - XtSetArg (gal[gac], XtNgeometry, tem); gac++; + XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++; XtSetValues (shell_widget, gal, gac); } @@ -2395,7 +2427,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) the X server hasn't been told. */ { Lisp_Object name; - int explicit = f->explicit_name; + bool explicit = f->explicit_name; f->explicit_name = 0; name = f->name; @@ -2509,10 +2541,6 @@ x_window (struct frame *f) class_hints.res_class = SSDATA (Vx_resource_class); XSetClassHint (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &class_hints); - /* The menubar is part of the ordinary display; - it does not count in addition to the height of the window. */ - f->output_data.x->menubar_height = 0; - /* This indicates that we use the "Passive Input" input model. Unless we do this, we don't get the Focus{In,Out} events that we need to draw the cursor correctly. Accursed bureaucrats. @@ -2538,7 +2566,7 @@ x_window (struct frame *f) the X server hasn't been told. */ { Lisp_Object name; - int explicit = f->explicit_name; + bool explicit = f->explicit_name; f->explicit_name = 0; name = f->name; @@ -2762,12 +2790,6 @@ do_unwind_create_frame (Lisp_Object frame) } static void -unwind_create_frame_1 (Lisp_Object val) -{ - inhibit_lisp_code = val; -} - -static void x_default_font_parameter (struct frame *f, Lisp_Object parms) { struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); @@ -2825,7 +2847,8 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) { /* Remember the explicit font parameter, so we can re-apply it after we've applied the `default' face settings. */ - x_set_frame_parameters (f, list1 (Fcons (Qfont_param, font_param))); + AUTO_FRAME_ARG (arg, Qfont_param, font_param); + x_set_frame_parameters (f, arg); } /* This call will make X resources override any system font setting. */ @@ -2851,29 +2874,31 @@ Signal error if FRAME is not an X frame. */) static void set_machine_and_pid_properties (struct frame *f) { - long pid = (long) getpid (); - /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME. */ XSetWMProperties (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), NULL, NULL, NULL, 0, NULL, NULL, NULL); - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_OUTER_WINDOW (f), - XInternAtom (FRAME_X_DISPLAY (f), - "_NET_WM_PID", - False), - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &pid, 1); + pid_t pid = getpid (); + if (pid <= 0xffffffffu) + { + unsigned long xpid = pid; + XChangeProperty (FRAME_X_DISPLAY (f), + FRAME_OUTER_WINDOW (f), + XInternAtom (FRAME_X_DISPLAY (f), + "_NET_WM_PID", + False), + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &xpid, 1); + } } DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 1, 1, 0, doc: /* Make a new X window, which is called a "frame" in Emacs terms. -Return an Emacs frame object. -PARMS is an alist of frame parameters. +Return an Emacs frame object. PARMS is an alist of frame parameters. If the parameters specify that the frame should not have a minibuffer, -and do not specify a specific minibuffer window to use, -then `default-minibuffer-frame' must be a frame whose minibuffer can -be shared by the new frame. +and do not specify a specific minibuffer window to use, then +`default-minibuffer-frame' must be a frame whose minibuffer can be +shared by the new frame. This function is an internal primitive--use `make-frame' instead. */) (Lisp_Object parms) @@ -2883,8 +2908,7 @@ This function is an internal primitive--use `make-frame' instead. */) Lisp_Object name; int minibuffer_only = 0; long window_prompting = 0; - int width, height; - ptrdiff_t count = SPECPDL_INDEX (), count2; + ptrdiff_t count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; Lisp_Object display; struct x_display_info *dpyinfo = NULL; @@ -2953,10 +2977,10 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_FONTSET (f) = -1; f->output_data.x->scroll_bar_foreground_pixel = -1; f->output_data.x->scroll_bar_background_pixel = -1; -#ifdef USE_TOOLKIT_SCROLL_BARS +#if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS) f->output_data.x->scroll_bar_top_shadow_pixel = -1; f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; -#endif /* USE_TOOLKIT_SCROLL_BARS */ +#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */ f->output_data.x->white_relief.pixel = -1; f->output_data.x->black_relief.pixel = -1; @@ -3005,7 +3029,6 @@ This function is an internal primitive--use `make-frame' instead. */) } /* Specify the parent under which to make this X window. */ - if (!NILP (parent)) { f->output_data.x->parent_desc = (Window) XFASTINT (parent); @@ -3028,7 +3051,7 @@ This function is an internal primitive--use `make-frame' instead. */) { fset_name (f, name); f->explicit_name = 1; - /* use the frame's title when getting resources for this frame. */ + /* Use the frame's title when getting resources for this frame. */ specbind (Qx_resource_name, name); } @@ -3091,7 +3114,9 @@ This function is an internal primitive--use `make-frame' instead. */) #endif "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); - + x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, + "horizontalScrollBars", "ScrollBars", + RES_TYPE_SYMBOL); /* Also do the stuff which must be set before the window exists. */ x_default_parameter (f, parms, Qforeground_color, build_string ("black"), "foreground", "Foreground", RES_TYPE_STRING); @@ -3123,32 +3148,22 @@ This function is an internal primitive--use `make-frame' instead. */) dpyinfo_refcount = dpyinfo->reference_count; #endif /* GLYPH_DEBUG */ - /* Init faces before x_default_parameter is called for scroll-bar - parameters because that function calls x_set_scroll_bar_width, - which calls change_frame_size, which calls Fset_window_buffer, - which runs hooks, which call Fvertical_motion. At the end, we - end up in init_iterator with a null face cache, which should not - happen. */ + /* Init faces before x_default_parameter is called for the + scroll-bar-width parameter because otherwise we end up in + init_iterator with a null face cache, which should not happen. */ init_frame_faces (f); - - /* Temporary disable window-configuration-change-hook to avoid - an infloop in next_frame and access to uninitialized frame - from Lisp code (Bug#18161). */ - - count2 = SPECPDL_INDEX (); - record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code); - inhibit_lisp_code = Qt; - - /* PXW: This is a duplicate from below. We have to do it here since - otherwise x_set_tool_bar_lines will work with the character sizes - installed by init_frame_faces while the frame's pixel size is still - calculated from a character size of 1 and we subsequently hit the - eassert (height >= 0) assertion in window_box_height. The - non-pixelwise code apparently worked around this because it had one - frame line vs one toolbar line which left us with a zero root - window height which was obviously wrong as well ... */ - change_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), - FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1, 0, 0, 1); + + /* The following call of change_frame_size is needed since otherwise + x_set_tool_bar_lines will already work with the character sizes + installed by init_frame_faces while the frame's pixel size is + still calculated from a character size of 1 and we subsequently + hit the (height >= 0) assertion in window_box_height. + + The non-pixelwise code apparently worked around this because it + had one frame line vs one toolbar line which left us with a zero + root window height which was obviously wrong as well ... */ + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1); /* Set the menu-bar-lines and tool-bar-lines parameters. We don't look up the X resources controlling the menu-bar and tool-bar @@ -3164,8 +3179,6 @@ This function is an internal primitive--use `make-frame' instead. */) ? make_number (0) : make_number (1), NULL, NULL, RES_TYPE_NUMBER); - unbind_to (count2, Qnil); - x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL); @@ -3174,9 +3187,9 @@ This function is an internal primitive--use `make-frame' instead. */) x_default_parameter (f, parms, Qwait_for_wm, Qt, "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); x_default_parameter (f, parms, Qfullscreen, Qnil, - "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); + "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); x_default_parameter (f, parms, Qtool_bar_position, - f->tool_bar_position, 0, 0, RES_TYPE_SYMBOL); + FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); /* Compute the size of the X window. */ window_prompting = x_figure_window_size (f, parms, 1); @@ -3215,17 +3228,16 @@ This function is an internal primitive--use `make-frame' instead. */) x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qscroll_bar_height, Qnil, + "scrollBarHeight", "ScrollBarHeight", + RES_TYPE_NUMBER); x_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); - /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. - Change will not be effected unless different from the current - FRAME_LINES (f). */ - width = FRAME_TEXT_WIDTH (f); - height = FRAME_TEXT_HEIGHT (f); - FRAME_TEXT_HEIGHT (f) = 0; - SET_FRAME_WIDTH (f, 0); - change_frame_size (f, width, height, 1, 0, 0, 1); + /* Consider frame official, now. */ + f->official = true; + + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1); #if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Create the menu bar. */ @@ -4263,13 +4275,13 @@ select_visual (struct x_display_info *dpyinfo) { Display *dpy = dpyinfo->display; Screen *screen = dpyinfo->screen; - Lisp_Object value; /* See if a visual is specified. */ - value = display_x_get_resource (dpyinfo, - build_string ("visualClass"), - build_string ("VisualClass"), - Qnil, Qnil); + AUTO_STRING (visualClass, "visualClass"); + AUTO_STRING (VisualClass, "VisualClass"); + Lisp_Object value = display_x_get_resource (dpyinfo, visualClass, + VisualClass, Qnil, Qnil); + if (STRINGP (value)) { /* VALUE should be of the form CLASS-DEPTH, where CLASS is one @@ -4280,7 +4292,7 @@ select_visual (struct x_display_info *dpyinfo) int i, class = -1; XVisualInfo vinfo; - strcpy (s, SSDATA (value)); + lispstpcpy (s, value); dash = strchr (s, '-'); if (dash) { @@ -4582,75 +4594,43 @@ FRAME nil or omitted means use the selected frame. Value is PROP. */) } -DEFUN ("x-window-property", Fx_window_property, Sx_window_property, - 1, 6, 0, - doc: /* Value is the value of window property PROP on FRAME. -If FRAME is nil or omitted, use the selected frame. - -On X Windows, the following optional arguments are also accepted: -If TYPE is nil or omitted, get the property as a string. -Otherwise TYPE is the name of the atom that denotes the type expected. -If SOURCE is non-nil, get the property on that window instead of from -FRAME. The number 0 denotes the root window. -If DELETE-P is non-nil, delete the property after retrieving it. -If VECTOR-RET-P is non-nil, don't return a string but a vector of values. - -On MS Windows, this function accepts but ignores those optional arguments. - -Value is nil if FRAME hasn't a property with name PROP or if PROP has -no value of TYPE (always string in the MS Windows case). */) - (Lisp_Object prop, Lisp_Object frame, Lisp_Object type, - Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p) +static Lisp_Object +x_window_property_intern (struct frame *f, + Window target_window, + Atom prop_atom, + Atom target_type, + Lisp_Object delete_p, + Lisp_Object vector_ret_p, + bool *found) { - struct frame *f = decode_window_system_frame (frame); - Atom prop_atom; - int rc; - Lisp_Object prop_value = Qnil; unsigned char *tmp_data = NULL; + Lisp_Object prop_value = Qnil; Atom actual_type; - Atom target_type = XA_STRING; int actual_format; unsigned long actual_size, bytes_remaining; - Window target_window = FRAME_X_WINDOW (f); + int rc; struct gcpro gcpro1; GCPRO1 (prop_value); - CHECK_STRING (prop); - - if (! NILP (source)) - { - CONS_TO_INTEGER (source, Window, target_window); - if (! target_window) - target_window = FRAME_DISPLAY_INFO (f)->root_window; - } - - block_input (); - if (STRINGP (type)) - { - if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) - target_type = AnyPropertyType; - else - target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); - } - prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, prop_atom, 0, 0, False, target_type, &actual_type, &actual_format, &actual_size, &bytes_remaining, &tmp_data); - if (rc == Success) - { - int size = bytes_remaining; + *found = actual_format != 0; + + if (rc == Success && *found) + { XFree (tmp_data); tmp_data = NULL; rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, - prop_atom, 0, bytes_remaining, - ! NILP (delete_p), target_type, - &actual_type, &actual_format, - &actual_size, &bytes_remaining, - &tmp_data); + prop_atom, 0, bytes_remaining, + ! NILP (delete_p), target_type, + &actual_type, &actual_format, + &actual_size, &bytes_remaining, + &tmp_data); if (rc == Success && tmp_data) { /* The man page for XGetWindowProperty says: @@ -4678,7 +4658,7 @@ no value of TYPE (always string in the MS Windows case). */) } if (NILP (vector_ret_p)) - prop_value = make_string ((char *) tmp_data, size); + prop_value = make_string ((char *) tmp_data, actual_size); else prop_value = x_property_data_to_lisp (f, tmp_data, @@ -4690,121 +4670,85 @@ no value of TYPE (always string in the MS Windows case). */) if (tmp_data) XFree (tmp_data); } - unblock_input (); UNGCPRO; return prop_value; } +DEFUN ("x-window-property", Fx_window_property, Sx_window_property, + 1, 6, 0, + doc: /* Value is the value of window property PROP on FRAME. +If FRAME is nil or omitted, use the selected frame. - -/*********************************************************************** - Busy cursor - ***********************************************************************/ - -/* Timer function of hourglass_atimer. TIMER is equal to - hourglass_atimer. +On X Windows, the following optional arguments are also accepted: +If TYPE is nil or omitted, get the property as a string. +Otherwise TYPE is the name of the atom that denotes the type expected. +If SOURCE is non-nil, get the property on that window instead of from +FRAME. The number 0 denotes the root window. +If DELETE-P is non-nil, delete the property after retrieving it. +If VECTOR-RET-P is non-nil, don't return a string but a vector of values. - Display an hourglass pointer on all frames by mapping the frames' - hourglass_window. Set the hourglass_p flag in the frames' - output_data.x structure to indicate that an hourglass cursor is - shown on the frames. */ +On MS Windows, this function accepts but ignores those optional arguments. -void -show_hourglass (struct atimer *timer) +Value is nil if FRAME hasn't a property with name PROP or if PROP has +no value of TYPE (always string in the MS Windows case). */) + (Lisp_Object prop, Lisp_Object frame, Lisp_Object type, + Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p) { - /* The timer implementation will cancel this timer automatically - after this function has run. Set hourglass_atimer to null - so that we know the timer doesn't have to be canceled. */ - hourglass_atimer = NULL; - - if (!hourglass_shown_p) - { - Lisp_Object rest, frame; - - block_input (); - - FOR_EACH_FRAME (rest, frame) - { - struct frame *f = XFRAME (frame); - - if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f)) - { - Display *dpy = FRAME_X_DISPLAY (f); - -#ifdef USE_X_TOOLKIT - if (f->output_data.x->widget) -#else - if (FRAME_OUTER_WINDOW (f)) -#endif - { - f->output_data.x->hourglass_p = 1; + struct frame *f = decode_window_system_frame (frame); + Atom prop_atom; + Lisp_Object prop_value = Qnil; + Atom target_type = XA_STRING; + Window target_window = FRAME_X_WINDOW (f); + struct gcpro gcpro1; + bool found; - if (!f->output_data.x->hourglass_window) - { - unsigned long mask = CWCursor; - XSetWindowAttributes attrs; -#ifdef USE_GTK - Window parent = FRAME_X_WINDOW (f); -#else - Window parent = FRAME_OUTER_WINDOW (f); -#endif - attrs.cursor = f->output_data.x->hourglass_cursor; - - f->output_data.x->hourglass_window - = XCreateWindow (dpy, parent, - 0, 0, 32000, 32000, 0, 0, - InputOnly, - CopyFromParent, - mask, &attrs); - } - - XMapRaised (dpy, f->output_data.x->hourglass_window); - XFlush (dpy); - } - } - } + GCPRO1 (prop_value); + CHECK_STRING (prop); - hourglass_shown_p = 1; - unblock_input (); + if (! NILP (source)) + { + CONS_TO_INTEGER (source, Window, target_window); + if (! target_window) + target_window = FRAME_DISPLAY_INFO (f)->root_window; } -} - -/* Hide the hourglass pointer on all frames, if it is currently - shown. */ - -void -hide_hourglass (void) -{ - if (hourglass_shown_p) + block_input (); + if (STRINGP (type)) { - Lisp_Object rest, frame; + if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) + target_type = AnyPropertyType; + else + target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); + } - block_input (); - FOR_EACH_FRAME (rest, frame) - { - struct frame *f = XFRAME (frame); + prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); + prop_value = x_window_property_intern (f, + target_window, + prop_atom, + target_type, + delete_p, + vector_ret_p, + &found); + if (NILP (prop_value) + && ! found + && NILP (source) + && target_window != FRAME_OUTER_WINDOW (f)) + { + prop_value = x_window_property_intern (f, + FRAME_OUTER_WINDOW (f), + prop_atom, + target_type, + delete_p, + vector_ret_p, + &found); + } - if (FRAME_X_P (f) - /* Watch out for newly created frames. */ - && f->output_data.x->hourglass_window) - { - XUnmapWindow (FRAME_X_DISPLAY (f), - f->output_data.x->hourglass_window); - /* Sync here because XTread_socket looks at the - hourglass_p flag that is reset to zero below. */ - XSync (FRAME_X_DISPLAY (f), False); - f->output_data.x->hourglass_p = 0; - } - } - hourglass_shown_p = 0; - unblock_input (); - } + unblock_input (); + UNGCPRO; + return prop_value; } - - /*********************************************************************** Tool tips ***********************************************************************/ @@ -4885,7 +4829,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, f = make_frame (1); XSETFRAME (frame, f); - buffer = Fget_buffer_create (build_string (" *tip*")); + AUTO_STRING (tip, " *tip*"); + buffer = Fget_buffer_create (tip); /* Use set_window_buffer instead of Fset_window_buffer (see discussion of bug#11984, bug#12025, bug#12026). */ set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, 0, 0); @@ -4912,10 +4857,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo, FRAME_FONTSET (f) = -1; f->output_data.x->scroll_bar_foreground_pixel = -1; f->output_data.x->scroll_bar_background_pixel = -1; -#ifdef USE_TOOLKIT_SCROLL_BARS +#if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS) f->output_data.x->scroll_bar_top_shadow_pixel = -1; f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; -#endif /* USE_TOOLKIT_SCROLL_BARS */ +#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */ f->output_data.x->white_relief.pixel = -1; f->output_data.x->black_relief.pixel = -1; @@ -5031,12 +4976,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, dpyinfo_refcount = dpyinfo->reference_count; #endif /* GLYPH_DEBUG */ - /* Init faces before x_default_parameter is called for scroll-bar - parameters because that function calls x_set_scroll_bar_width, - which calls change_frame_size, which calls Fset_window_buffer, - which runs hooks, which call Fvertical_motion. At the end, we - end up in init_iterator with a null face cache, which should not - happen. */ + /* Init faces before x_default_parameter is called for the + scroll-bar-width parameter because otherwise we end up in + init_iterator with a null face cache, which should not happen. */ init_frame_faces (f); f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; @@ -5093,12 +5035,15 @@ x_create_tip_frame (struct x_display_info *dpyinfo, width = FRAME_COLS (f); height = FRAME_LINES (f); SET_FRAME_COLS (f, 0); - FRAME_LINES (f) = 0; + SET_FRAME_LINES (f, 0); change_frame_size (f, width, height, 1, 0, 0, 0); /* Add `tooltip' frame parameter's default value. */ if (NILP (Fframe_parameter (frame, Qtooltip))) - Fmodify_frame_parameters (frame, list1 (Fcons (Qtooltip, Qt))); + { + AUTO_FRAME_ARG (arg, Qtooltip, Qt); + Fmodify_frame_parameters (frame, arg); + } /* FIXME - can this be done in a similar way to normal frames? http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */ @@ -5116,7 +5061,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo, disptype = intern ("color"); if (NILP (Fframe_parameter (frame, Qdisplay_type))) - Fmodify_frame_parameters (frame, list1 (Fcons (Qdisplay_type, disptype))); + { + AUTO_FRAME_ARG (arg, Qdisplay_type, disptype); + Fmodify_frame_parameters (frame, arg); + } } /* Set up faces after all frame parameters are known. This call @@ -5135,7 +5083,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo, call2 (Qface_set_after_frame_default, frame, Qnil); if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) - Fmodify_frame_parameters (frame, list1 (Fcons (Qbackground_color, bg))); + { + AUTO_FRAME_ARG (arg, Qbackground_color, bg); + Fmodify_frame_parameters (frame, arg); + } } f->no_split = 1; @@ -5151,7 +5102,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, below. And the frame needs to be on Vframe_list or making it visible won't work. */ Vframe_list = Fcons (frame, Vframe_list); - + f->official = true; /* Setting attributes of faces of the tooltip frame from resources and similar will increment face_change_count, which leads to the @@ -6035,7 +5986,11 @@ present and mapped to the usual X keysyms. */) XkbFreeNames (kb, 0, True); } - XkbFreeClientMap (kb, 0, True); + /* As of libX11-1.6.2, XkbGetMap manual says that you should use + XkbFreeClientMap to free the data returned by XkbGetMap. But + this function just frees the data referenced from KB and not + KB itself. To free KB as well, call XkbFreeKeyboard. */ + XkbFreeKeyboard (kb, XkbAllMapComponentsMask, True); if (delete_keycode && backspace_keycode @@ -6077,17 +6032,19 @@ frame_parm_handler x_frame_parm_handlers[] = x_set_mouse_color, x_explicitly_set_name, x_set_scroll_bar_width, + x_set_scroll_bar_height, x_set_title, x_set_unsplittable, x_set_vertical_scroll_bars, + x_set_horizontal_scroll_bars, x_set_visibility, x_set_tool_bar_lines, x_set_scroll_bar_foreground, x_set_scroll_bar_background, x_set_screen_gamma, x_set_line_spacing, - x_set_fringe_width, - x_set_fringe_width, + x_set_left_fringe, + x_set_right_fringe, x_set_wait_for_wm, x_set_fullscreen, x_set_font_backend, @@ -6099,15 +6056,10 @@ frame_parm_handler x_frame_parm_handlers[] = void syms_of_xfns (void) { - /* The section below is built by the lisp expression at the top of the file, - just above where these variables are declared. */ - /*&&& init symbols here &&&*/ - DEFSYM (Qsuppress_icon, "suppress-icon"); DEFSYM (Qundefined_color, "undefined-color"); DEFSYM (Qcompound_text, "compound-text"); DEFSYM (Qcancel_timer, "cancel-timer"); DEFSYM (Qfont_param, "font-parameter"); - /* This is the end of symbol initialization. */ Fput (Qundefined_color, Qerror_conditions, listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); @@ -6210,12 +6162,6 @@ If more space for files in the file chooser dialog is wanted, set this to nil to turn the additional text off. */); x_gtk_file_dialog_help_text = 1; - DEFVAR_BOOL ("x-gtk-whole-detached-tool-bar", x_gtk_whole_detached_tool_bar, - doc: /* If non-nil, a detached tool bar is shown in full. -The default is to just show an arrow and pressing on that arrow shows -the tool bar buttons. */); - x_gtk_whole_detached_tool_bar = 0; - DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips, doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used. Otherwise use Emacs own tooltip implementation. diff --git a/src/xfont.c b/src/xfont.c index 525f00031c5..5e8dd370120 100644 --- a/src/xfont.c +++ b/src/xfont.c @@ -121,11 +121,11 @@ static Lisp_Object xfont_match (struct frame *, Lisp_Object); static Lisp_Object xfont_list_family (struct frame *); static Lisp_Object xfont_open (struct frame *, Lisp_Object, int); static void xfont_close (struct font *); -static int xfont_prepare_face (struct frame *, struct face *); +static void xfont_prepare_face (struct frame *, struct face *); static int xfont_has_char (Lisp_Object, int); static unsigned xfont_encode_char (struct font *, int); -static int xfont_text_extents (struct font *, unsigned *, int, - struct font_metrics *); +static void xfont_text_extents (struct font *, unsigned *, int, + struct font_metrics *); static int xfont_draw (struct glyph_string *, int, int, int, int, bool); static int xfont_check (struct frame *, struct font *); @@ -146,7 +146,7 @@ struct font_driver xfont_driver = xfont_encode_char, xfont_text_extents, xfont_draw, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, xfont_check, NULL, /* get_variation_glyphs */ NULL, /* filter_properties */ @@ -541,7 +541,7 @@ xfont_list (struct frame *f, Lisp_Object spec) if (STRINGP (XCAR (alter)) && ((r - name) + SBYTES (XCAR (alter))) < 256) { - strcpy (r, SSDATA (XCAR (alter))); + lispstpcpy (r, XCAR (alter)); list = xfont_list_pattern (display, name, registry, script); if (! NILP (list)) break; @@ -804,8 +804,6 @@ xfont_open (struct frame *f, Lisp_Object entity, int pixel_size) ASET (font_object, FONT_NAME_INDEX, make_string (buf, len)); } ASET (font_object, FONT_FULLNAME_INDEX, fullname); - ASET (font_object, FONT_FILE_INDEX, Qnil); - ASET (font_object, FONT_FORMAT_INDEX, Qx); font = XFONT_OBJECT (font_object); ((struct xfont_info *) font)->xfont = xfont; ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f); @@ -916,15 +914,13 @@ xfont_close (struct font *font) } } -static int +static void xfont_prepare_face (struct frame *f, struct face *face) { block_input (); XSetFont (FRAME_X_DISPLAY (f), face->gc, ((struct xfont_info *) face->font)->xfont->fid); unblock_input (); - - return 0; } static int @@ -979,15 +975,14 @@ xfont_encode_char (struct font *font, int c) return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE); } -static int -xfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics) +static void +xfont_text_extents (struct font *font, unsigned int *code, + int nglyphs, struct font_metrics *metrics) { XFontStruct *xfont = ((struct xfont_info *) font)->xfont; - int width = 0; - int i, first; + int i, width = 0; + bool first; - if (metrics) - memset (metrics, 0, sizeof (struct font_metrics)); for (i = 0, first = 1; i < nglyphs; i++) { XChar2b char2b; @@ -1001,34 +996,27 @@ xfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct f continue; if (first) { - if (metrics) - { - metrics->lbearing = pcm->lbearing; - metrics->rbearing = pcm->rbearing; - metrics->ascent = pcm->ascent; - metrics->descent = pcm->descent; - } + metrics->lbearing = pcm->lbearing; + metrics->rbearing = pcm->rbearing; + metrics->ascent = pcm->ascent; + metrics->descent = pcm->descent; first = 0; } else { - if (metrics) - { - if (metrics->lbearing > width + pcm->lbearing) - metrics->lbearing = width + pcm->lbearing; - if (metrics->rbearing < width + pcm->rbearing) - metrics->rbearing = width + pcm->rbearing; - if (metrics->ascent < pcm->ascent) - metrics->ascent = pcm->ascent; - if (metrics->descent < pcm->descent) - metrics->descent = pcm->descent; - } + if (metrics->lbearing > width + pcm->lbearing) + metrics->lbearing = width + pcm->lbearing; + if (metrics->rbearing < width + pcm->rbearing) + metrics->rbearing = width + pcm->rbearing; + if (metrics->ascent < pcm->ascent) + metrics->ascent = pcm->ascent; + if (metrics->descent < pcm->descent) + metrics->descent = pcm->descent; } width += pcm->width; } - if (metrics) - metrics->width = width; - return width; + + metrics->width = width; } static int diff --git a/src/xftfont.c b/src/xftfont.c index 18c180f906a..0a883a7b87b 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -270,8 +270,7 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) double size = 0; XftFont *xftfont = NULL; int spacing; - char name[256]; - int len, i; + int i; XGlyphInfo extents; FT_Face ft_face; FcMatrix *matrix; @@ -322,16 +321,6 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) block_input (); - /* Make sure that the Xrender extension is added before the Xft one. - Otherwise, the close-display hook set by Xft is called after the - one for Xrender, and the former tries to re-add the latter. This - results in inconsistency of internal states and leads to X - protocol error when one reconnects to the same X server. - (Bug#1696) */ - { - int event_base, error_base; - XRenderQueryExtension (display, &event_base, &error_base); - } /* Substitute in values from X resources and XftDefaultSet. */ XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); @@ -351,20 +340,9 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) /* We should not destroy PAT here because it is kept in XFTFONT and destroyed automatically when XFTFONT is closed. */ - font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size); - ASET (font_object, FONT_TYPE_INDEX, Qxft); - len = font_unparse_xlfd (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); - len = font_unparse_fcname (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); - else - ASET (font_object, FONT_FULLNAME_INDEX, - AREF (font_object, FONT_NAME_INDEX)); + font_object = font_build_object (VECSIZE (struct xftfont_info), + Qxft, entity, size); ASET (font_object, FONT_FILE_INDEX, filename); - ASET (font_object, FONT_FORMAT_INDEX, - ftfont_font_format (xftfont->pattern, filename)); font = XFONT_OBJECT (font_object); font->pixel_size = size; font->driver = &xftfont_driver; @@ -507,7 +485,7 @@ xftfont_close (struct font *font) } } -static int +static void xftfont_prepare_face (struct frame *f, struct face *face) { struct xftface_info *xftface_info; @@ -517,17 +495,14 @@ xftfont_prepare_face (struct frame *f, struct face *face) if (face != face->ascii_face) { face->extra = face->ascii_face->extra; - return 0; + return; } #endif - xftface_info = malloc (sizeof *xftface_info); - if (! xftface_info) - return -1; + xftface_info = xmalloc (sizeof *xftface_info); xftfont_get_colors (f, face, face->gc, NULL, &xftface_info->xft_fg, &xftface_info->xft_bg); face->extra = xftface_info; - return 0; } static void @@ -545,7 +520,7 @@ xftfont_done_face (struct frame *f, struct face *face) xftface_info = (struct xftface_info *) face->extra; if (xftface_info) { - free (xftface_info); + xfree (xftface_info); face->extra = NULL; } } @@ -582,8 +557,9 @@ xftfont_encode_char (struct font *font, int c) return (code ? code : FONT_INVALID_CODE); } -static int -xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics) +static void +xftfont_text_extents (struct font *font, unsigned int *code, + int nglyphs, struct font_metrics *metrics) { struct xftfont_info *xftfont_info = (struct xftfont_info *) font; XGlyphInfo extents; @@ -592,21 +568,18 @@ xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs, &extents); unblock_input (); - if (metrics) - { - metrics->lbearing = - extents.x; - metrics->rbearing = - extents.x + extents.width; - metrics->width = extents.xOff; - metrics->ascent = extents.y; - metrics->descent = extents.height - extents.y; - } - return extents.xOff; + + metrics->lbearing = - extents.x; + metrics->rbearing = - extents.x + extents.width; + metrics->width = extents.xOff; + metrics->ascent = extents.y; + metrics->descent = extents.height - extents.y; } static XftDraw * xftfont_get_xft_draw (struct frame *f) { - XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver); + XftDraw *xft_draw = font_get_frame_data (f, Qxft); if (! xft_draw) { @@ -617,7 +590,7 @@ xftfont_get_xft_draw (struct frame *f) FRAME_X_COLORMAP (f)); unblock_input (); eassert (xft_draw != NULL); - font_put_frame_data (f, &xftfont_driver, xft_draw); + font_put_frame_data (f, Qxft, xft_draw); } return xft_draw; } @@ -693,14 +666,14 @@ xftfont_end_for_frame (struct frame *f) /* Don't do anything if display is dead */ if (FRAME_X_DISPLAY (f) == NULL) return 0; - xft_draw = font_get_frame_data (f, &xftfont_driver); + xft_draw = font_get_frame_data (f, Qxft); if (xft_draw) { block_input (); XftDrawDestroy (xft_draw); unblock_input (); - font_put_frame_data (f, &xftfont_driver, NULL); + font_put_frame_data (f, Qxft, NULL); } return 0; } diff --git a/src/xgselect.c b/src/xgselect.c index 42fdfed0d34..bf889a90e97 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -53,7 +53,7 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, int have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; - int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; + int gfds_size = ARRAYELTS (gfds_buf); int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; int i, nfds, tmo_in_millisec; bool need_to_dispatch; diff --git a/src/xmenu.c b/src/xmenu.c index 9b1ac540c21..eb783fe5070 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -110,11 +110,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ static Lisp_Object Qdebug_on_next_call; -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) -static Lisp_Object xdialog_show (struct frame *, bool, Lisp_Object, Lisp_Object, - const char **); -#endif - /* Flag which when set indicates a dialog or menu has been posted by Xt on behalf of one of the widget sets. */ static int popup_activated_flag; @@ -122,7 +117,7 @@ static int popup_activated_flag; #ifdef USE_X_TOOLKIT -static int next_menubar_widget_id; +static LWLIB_ID next_menubar_widget_id; /* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */ @@ -144,53 +139,6 @@ menubar_id_to_frame (LWLIB_ID id) } #endif - -#ifdef HAVE_X_WINDOWS -/* Return the mouse position in *X and *Y. The coordinates are window - relative for the edit window in frame F. - This is for Fx_popup_menu. The mouse_position_hook can not - be used for X, as it returns window relative coordinates - for the window where the mouse is in. This could be the menu bar, - the scroll bar or the edit window. Fx_popup_menu needs to be - sure it is the edit window. */ -void -mouse_position_for_popup (struct frame *f, int *x, int *y) -{ - Window root, dummy_window; - int dummy; - - eassert (FRAME_X_P (f)); - - block_input (); - - XQueryPointer (FRAME_X_DISPLAY (f), - DefaultRootWindow (FRAME_X_DISPLAY (f)), - - /* The root window which contains the pointer. */ - &root, - - /* Window pointer is on, not used */ - &dummy_window, - - /* The position on that root window. */ - x, y, - - /* x/y in dummy_window coordinates, not used. */ - &dummy, &dummy, - - /* Modifier keys and pointer buttons, about which - we don't care. */ - (unsigned int *) &dummy); - - unblock_input (); - - /* xmenu_show expects window coordinates, not root window - coordinates. Translate. */ - *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); - *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); -} - -#endif /* HAVE_X_WINDOWS */ #ifndef MSDOS @@ -213,9 +161,6 @@ x_menu_set_in_use (int in_use) /* Wait for an X event to arrive or for a timer to expire. */ -#ifndef USE_MOTIF -static -#endif void x_menu_wait_for_event (void *data) { @@ -682,7 +627,6 @@ update_frame_menubar (struct frame *f) xg_update_frame_menubar (f); #else struct x_output *x; - int columns, rows; eassert (FRAME_X_P (f)); @@ -692,10 +636,6 @@ update_frame_menubar (struct frame *f) return; block_input (); - /* Save the size of the frame because the pane widget doesn't accept - to resize itself. So force it. */ - columns = FRAME_COLS (f); - rows = FRAME_LINES (f); /* Do the voodoo which means "I'm changing lots of things, don't try to refigure sizes until I'm done." */ @@ -716,8 +656,8 @@ update_frame_menubar (struct frame *f) XtManageChild (x->edit_widget); lw_refigure_widget (x->column_widget, True); - /* Force the pane widget to resize itself with the right values. */ - EmacsFrameSetCharSize (x->edit_widget, columns, rows); + /* Force the pane widget to resize itself. */ + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 2, 0); unblock_input (); #endif } @@ -760,7 +700,7 @@ apply_systemfont_to_menu (struct frame *f, Widget w) void set_frame_menubar (struct frame *f, bool first_time, bool deep_p) { - xt_or_gtk_widget menubar_widget; + xt_or_gtk_widget menubar_widget, old_widget; #ifdef USE_X_TOOLKIT LWLIB_ID id; #endif @@ -773,7 +713,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) eassert (FRAME_X_P (f)); - menubar_widget = f->output_data.x->menubar_widget; + menubar_widget = old_widget = f->output_data.x->menubar_widget; XSETFRAME (Vmenu_updating_frame, f); @@ -793,12 +733,6 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) f->output_data.x->saved_menu_event->type = 0; } -#ifdef USE_GTK - /* If we have detached menus, we must update deep so detached menus - also gets updated. */ - deep_p = deep_p || xg_have_tear_offs (f); -#endif - if (deep_p) { /* Make a widget-value tree representing the entire menu trees. */ @@ -887,12 +821,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Convert menu_items into widget_value trees to display the menu. This cannot evaluate Lisp code. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; submenu_start[i] >= 0; i++) @@ -957,12 +887,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Make a widget-value tree containing just the top level menu bar strings. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; items = FRAME_MENU_BAR_ITEMS (f); @@ -974,12 +900,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) if (NILP (string)) break; - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; /* This prevents lwlib from assuming this menu item is really supposed to be empty. */ /* The intptr_t cast avoids a warning. @@ -1090,7 +1012,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) #endif /* USE_LUCID */ #endif /* 1 */ - f->output_data.x->menubar_height = menubar_size; + FRAME_MENUBAR_HEIGHT (f) = menubar_size; } #endif /* not USE_GTK */ @@ -1133,7 +1055,7 @@ free_frame_menubar (struct frame *f) menubar_widget = f->output_data.x->menubar_widget; - f->output_data.x->menubar_height = 0; + FRAME_MENUBAR_HEIGHT (f) = 0; if (menubar_widget) { @@ -1166,7 +1088,15 @@ free_frame_menubar (struct frame *f) if (x1 == 0 && y1 == 0) XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL); #endif - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), + FRAME_TEXT_HEIGHT (f), 2, 0); + /* + if (frame_inhibit_resize (f, 0)) + change_frame_size (f, 0, 0, 0, 0, 0, 1); + else + x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), + FRAME_TEXT_HEIGHT (f), 1); + */ } unblock_input (); } @@ -1175,16 +1105,17 @@ free_frame_menubar (struct frame *f) #endif /* USE_X_TOOLKIT || USE_GTK */ -/* xmenu_show actually displays a menu using the panes and items in menu_items +/* x_menu_show actually displays a menu using the panes and items in menu_items and returns the value selected from it. - There are two versions of xmenu_show, one for Xt and one for Xlib. + There are two versions of x_menu_show, one for Xt and one for Xlib. Both assume input is blocked by the caller. */ /* F is the frame the menu is for. X and Y are the frame-relative specified position, relative to the inside upper left corner of the frame F. - FOR_CLICK is true if this menu was invoked for a mouse click. - KEYMAPS is true if this menu was specified with keymaps; + Bitfield MENUFLAGS bits are: + MENU_FOR_CLICK is set if this menu was invoked for a mouse click. + MENU_KEYMAPS is set if this menu was specified with keymaps; in that case, we return a list containing the chosen item's value and perhaps also the pane's prefix. TITLE is the specified menu title. @@ -1339,8 +1270,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, /* We need a unique id for each widget handled by the Lucid Widget library. - For the main windows, and popup menus, we use this counter, - which we increment each time after use. This starts from 1<<16. + For the main windows, and popup menus, we use this counter, which we + increment each time after use. This starts from WIDGET_ID_TICK_START. For menu bars, we use numbers starting at 0, counted in next_menubar_widget_id. */ @@ -1352,17 +1283,13 @@ popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data) menu_item_selection = client_data; } -/* ARG is the LWLIB ID of the dialog box, represented - as a Lisp object as (HIGHPART . LOWPART). */ +/* ID is the LWLIB ID of the dialog box. */ static void -pop_down_menu (Lisp_Object arg) +pop_down_menu (int id) { - LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID) - | XINT (XCDR (arg))); - block_input (); - lw_destroy_all_widgets (id); + lw_destroy_all_widgets ((LWLIB_ID) id); unblock_input (); popup_activated_flag = 0; } @@ -1428,11 +1355,9 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, x_activate_timeout_atimer (); { - int fact = 4 * sizeof (LWLIB_ID); ptrdiff_t specpdl_count = SPECPDL_INDEX (); - record_unwind_protect (pop_down_menu, - Fcons (make_number (menu_id >> (fact)), - make_number (menu_id & ~(-1 << (fact))))); + + record_unwind_protect_int (pop_down_menu, (int) menu_id); /* Process events that apply to the menu. */ popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1); @@ -1450,8 +1375,8 @@ cleanup_widget_value_tree (void *arg) } Lisp_Object -xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, - Lisp_Object title, const char **error_name) +x_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) { int i; widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; @@ -1479,12 +1404,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* Create a tree of widget_value objects representing the panes and their items. */ - wv = xmalloc_widget_value (); - wv->name = "menu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help =Qnil; first_wv = wv; first_pane = 1; @@ -1540,20 +1461,16 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* If the pane has a meaningful name, make the pane a top-level menu item with its items as a submenu beneath it. */ - if (!keymaps && strcmp (pane_string, "")) + if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = (char *) pane_string; - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -1591,20 +1508,18 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, } #endif /* not HAVE_MULTILINGUAL_MENU */ - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* If this item has a null value, make the call_data null so that it won't display a box when the mouse is on it. */ wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -1617,11 +1532,6 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -1631,27 +1541,20 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* Deal with the title, if it is non-nil. */ if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep1 = xmalloc_widget_value (); - widget_value *wv_sep2 = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep1 = make_widget_value ("--", NULL, false, Qnil); + widget_value *wv_sep2 = make_widget_value ("--", NULL, false, Qnil); - wv_sep2->name = "--"; wv_sep2->next = first_wv->contents; - wv_sep2->help = Qnil; - - wv_sep1->name = "--"; wv_sep1->next = wv_sep2; - wv_sep1->help = Qnil; #ifndef HAVE_MULTILINGUAL_MENU if (STRING_MULTIBYTE (title)) title = ENCODE_MENU_STRING (title); #endif - wv_title->name = SSDATA (title); - wv_title->enabled = true; + wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil); wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep1; first_wv->contents = wv_title; } @@ -1664,7 +1567,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv); /* Actually create and show the menu until popped down. */ - create_and_show_popup_menu (f, first_wv, x, y, for_click); + create_and_show_popup_menu (f, first_wv, x, y, + menuflags & MENU_FOR_CLICK); unbind_to (specpdl_count, Qnil); @@ -1705,7 +1609,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == aref_addr (menu_items, i)) { - if (keymaps) + if (menuflags & MENU_KEYMAPS) { int j; @@ -1723,7 +1627,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, } } } - else if (!for_click) + else if (!(menuflags & MENU_FOR_CLICK)) { unblock_input (); /* Make "Cancel" equivalent to C-g. */ @@ -1819,12 +1723,10 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv) Also handle timers. */ { ptrdiff_t count = SPECPDL_INDEX (); - int fact = 4 * sizeof (LWLIB_ID); /* xdialog_show_unwind is responsible for popping the dialog box down. */ - record_unwind_protect (pop_down_menu, - Fcons (make_number (dialog_id >> (fact)), - make_number (dialog_id & ~(-1 << (fact))))); + + record_unwind_protect_int (pop_down_menu, (int) dialog_id); popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1); @@ -1839,11 +1741,8 @@ static const char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -xdialog_show (struct frame *f, - bool keymaps, - Lisp_Object title, - Lisp_Object header, - const char **error_name) +x_dialog_show (struct frame *f, Lisp_Object title, + Lisp_Object header, const char **error_name) { int i, nb_buttons=0; char dialog_name[6]; @@ -1870,19 +1769,12 @@ xdialog_show (struct frame *f, /* Create a tree of widget_value objects representing the text label and buttons. */ { - Lisp_Object pane_name, prefix; + Lisp_Object pane_name; const char *pane_string; pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); - prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - prev_wv = xmalloc_widget_value (); - prev_wv->value = (char *) pane_string; - if (keymaps && !NILP (prefix)) - prev_wv->name++; - prev_wv->enabled = 1; - prev_wv->name = "message"; - prev_wv->help = Qnil; + prev_wv = make_widget_value ("message", (char *) pane_string, true, Qnil); first_wv = prev_wv; /* Loop over all panes and items, filling in the tree. */ @@ -1918,15 +1810,13 @@ xdialog_show (struct frame *f, return Qnil; } - wv = xmalloc_widget_value (); + wv = make_widget_value (button_names[nb_buttons], + SSDATA (item_name), + !NILP (enable), Qnil); prev_wv->next = wv; - wv->name = (char *) button_names[nb_buttons]; if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = SSDATA (item_name); wv->call_data = aref_addr (menu_items, i); - wv->enabled = !NILP (enable); - wv->help = Qnil; prev_wv = wv; if (! boundary_seen) @@ -1941,9 +1831,7 @@ xdialog_show (struct frame *f, if (! boundary_seen) left_count = nb_buttons - nb_buttons / 2; - wv = xmalloc_widget_value (); - wv->name = dialog_name; - wv->help = Qnil; + wv = make_widget_value (dialog_name, NULL, false, Qnil); /* Frame title: 'Q' = Question, 'I' = Information. Can also have 'E' = Error if, one day, we want @@ -1982,20 +1870,13 @@ xdialog_show (struct frame *f, the proper value. */ if (menu_item_selection != 0) { - Lisp_Object prefix; - - prefix = Qnil; i = 0; while (i < menu_items_used) { Lisp_Object entry; if (EQ (AREF (menu_items, i), Qt)) - { - prefix - = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); - i += MENU_ITEMS_PANE_LENGTH; - } + i += MENU_ITEMS_PANE_LENGTH; else if (EQ (AREF (menu_items, i), Qquote)) { /* This is the boundary between left-side elts and @@ -2007,15 +1888,7 @@ xdialog_show (struct frame *f, entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == aref_addr (menu_items, i)) - { - if (keymaps != 0) - { - entry = list1 (entry); - if (!NILP (prefix)) - entry = Fcons (prefix, entry); - } - return entry; - } + return entry; i += MENU_ITEMS_ITEM_LENGTH; } } @@ -2052,7 +1925,7 @@ xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) /* Display them in a dialog box. */ block_input (); - selection = xdialog_show (f, 0, title, header, &error_name); + selection = x_dialog_show (f, title, header, &error_name); unblock_input (); unbind_to (specpdl_count, Qnil); @@ -2090,7 +1963,7 @@ menu_help_callback (char const *help_string, int pane, int item) if (EQ (first_item[0], Qt)) pane_name = first_item[MENU_ITEMS_PANE_NAME]; else if (EQ (first_item[0], Qquote)) - /* This shouldn't happen, see xmenu_show. */ + /* This shouldn't happen, see x_menu_show. */ pane_name = empty_unibyte_string; else pane_name = first_item[MENU_ITEMS_ITEM_NAME]; @@ -2132,13 +2005,14 @@ pop_down_menu (Lisp_Object arg) Lisp_Object -xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, - Lisp_Object title, const char **error_name) +x_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) { Window root; XMenu *menu; int pane, selidx, lpane, status; - Lisp_Object entry, pane_prefix; + Lisp_Object entry = Qnil; + Lisp_Object pane_prefix; char *datap; int ulx, uly, width, height; int dispwidth, dispheight; @@ -2160,6 +2034,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, return Qnil; } + USE_SAFE_ALLOCA; block_input (); /* Figure out which root window F is on. */ @@ -2172,8 +2047,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (menu == NULL) { *error_name = "Can't create menu"; - unblock_input (); - return Qnil; + goto return_entry; } /* Don't GC while we prepare and show the menu, @@ -2208,7 +2082,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) pane_string++; lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, TRUE); @@ -2216,8 +2090,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, { XMenuDestroy (FRAME_X_DISPLAY (f), menu); *error_name = "Can't create pane"; - unblock_input (); - return Qnil; + goto return_entry; } i += MENU_ITEMS_PANE_LENGTH; @@ -2261,9 +2134,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (!NILP (descrip)) { - /* if alloca is fast, use that to make the space, - to reduce gc needs. */ - item_data = alloca (maxwidth + SBYTES (descrip) + 1); + item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1); memcpy (item_data, SSDATA (item_name), SBYTES (item_name)); for (j = SCHARS (item_name); j < maxwidth; j++) item_data[j] = ' '; @@ -2281,8 +2152,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, { XMenuDestroy (FRAME_X_DISPLAY (f), menu); *error_name = "Can't add selection to menu"; - unblock_input (); - return Qnil; + goto return_entry; } i += MENU_ITEMS_ITEM_LENGTH; lines++; @@ -2331,7 +2201,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (ulx < 0) x -= ulx; if (uly < 0) y -= uly; - if (! for_click) + if (!(menuflags & MENU_FOR_CLICK)) { /* If position was not given by a mouse click, adjust so upper left corner of the menu as a whole ends up at given coordinates. This @@ -2356,7 +2226,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx, x, y, ButtonReleaseMask, &datap, menu_help_callback); - entry = pane_prefix = Qnil; + pane_prefix = Qnil; switch (status) { @@ -2385,7 +2255,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, { entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); - if (keymaps) + if (menuflags & MENU_KEYMAPS) { entry = list1 (entry); if (!NILP (pane_prefix)) @@ -2407,7 +2277,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, case XM_NO_SELECT: /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means the menu was invoked with a mouse event as POSITION). */ - if (! for_click) + if (!(menuflags & MENU_FOR_CLICK)) { unblock_input (); Fsignal (Qquit, Qnil); @@ -2415,10 +2285,10 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, break; } + return_entry: unblock_input (); - unbind_to (specpdl_count, Qnil); - - return entry; + SAFE_FREE (); + return unbind_to (specpdl_count, entry); } #endif /* not USE_X_TOOLKIT */ @@ -2446,13 +2316,13 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ void syms_of_xmenu (void) { - DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); - #ifdef USE_X_TOOLKIT - widget_id_tick = (1<<16); + enum { WIDGET_ID_TICK_START = 1 << 16 }; + widget_id_tick = WIDGET_ID_TICK_START; next_menubar_widget_id = 1; #endif + DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); defsubr (&Smenu_or_popup_active_p); #if defined (USE_GTK) || defined (USE_X_TOOLKIT) diff --git a/src/xrdb.c b/src/xrdb.c index 107a8fca4e1..32ad3c7f01e 100644 --- a/src/xrdb.c +++ b/src/xrdb.c @@ -452,6 +452,10 @@ x_load_resources (Display *display, const char *xrm_string, XrmPutLineResource (&rdb, line); sprintf (line, "%s*verticalScrollBar.troughColor: grey75", myclass); XrmPutLineResource (&rdb, line); + sprintf (line, "%s*horizontalScrollBar.background: grey75", myclass); + XrmPutLineResource (&rdb, line); + sprintf (line, "%s*horizontalScrollBar.troughColor: grey75", myclass); + XrmPutLineResource (&rdb, line); sprintf (line, "%s.dialog*.background: grey75", myclass); XrmPutLineResource (&rdb, line); sprintf (line, "%s*fsb.Text.background: white", myclass); @@ -499,6 +503,8 @@ x_load_resources (Display *display, const char *xrm_string, XrmPutLineResource (&rdb, line); sprintf (line, "Emacs*verticalScrollBar.background: grey75"); XrmPutLineResource (&rdb, line); + sprintf (line, "Emacs*horizontalScrollBar.background: grey75"); + XrmPutLineResource (&rdb, line); #endif /* not USE_MOTIF */ diff --git a/src/xselect.c b/src/xselect.c index 28f2d770a77..92e89822293 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -53,15 +53,14 @@ static struct prop_location *expect_property_change (Display *, Window, Atom, int); static void unexpect_property_change (struct prop_location *); static void wait_for_property_change (struct prop_location *); -static Lisp_Object x_get_window_property_as_lisp_data (Display *, +static Lisp_Object x_get_window_property_as_lisp_data (struct x_display_info *, Window, Atom, Lisp_Object, Atom); -static Lisp_Object selection_data_to_lisp_data (Display *, +static Lisp_Object selection_data_to_lisp_data (struct x_display_info *, const unsigned char *, ptrdiff_t, Atom, int); -static void lisp_data_to_selection_data (Display *, Lisp_Object, - unsigned char **, Atom *, - ptrdiff_t *, int *, int *); +static void lisp_data_to_selection_data (struct x_display_info *, Lisp_Object, + struct selection_data *); /* Printing traces to stderr. */ @@ -97,13 +96,6 @@ static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions; is not necessarily sizeof (long). */ #define X_LONG_SIZE 4 -/* Extreme 'short' and 'long' values suitable for libX11. */ -#define X_SHRT_MAX 0x7fff -#define X_SHRT_MIN (-1 - X_SHRT_MAX) -#define X_LONG_MAX 0x7fffffff -#define X_LONG_MIN (-1 - X_LONG_MAX) -#define X_ULONG_MAX 0xffffffffUL - /* If this is a smaller number than the max-request-size of the display, emacs will use INCR selection transfer when the selection is larger than this. The max-request-size is usually around 64k, so if you want @@ -245,9 +237,8 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) and calls to intern whenever possible. */ static Lisp_Object -x_atom_to_symbol (Display *dpy, Atom atom) +x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) { - struct x_display_info *dpyinfo; char *str; Lisp_Object val; @@ -268,7 +259,6 @@ x_atom_to_symbol (Display *dpy, Atom atom) return QATOM; } - dpyinfo = x_display_info_for_display (dpy); if (dpyinfo == NULL) return Qnil; if (atom == dpyinfo->Xatom_CLIPBOARD) @@ -295,7 +285,7 @@ x_atom_to_symbol (Display *dpy, Atom atom) return QNULL; block_input (); - str = XGetAtomName (dpy, atom); + str = XGetAtomName (dpyinfo->display, atom); unblock_input (); TRACE1 ("XGetAtomName --> %s", str); if (! str) return Qnil; @@ -458,7 +448,7 @@ x_decline_selection_request (struct input_event *event) died in the meantime. Handle that case. */ block_input (); x_catch_errors (reply->display); - XSendEvent (reply->display, reply->requestor, False, 0L, &reply_base); + XSendEvent (reply->display, reply->requestor, False, 0, &reply_base); XFlush (reply->display); x_uncatch_errors (); unblock_input (); @@ -632,7 +622,7 @@ x_reply_selection_request (struct input_event *event, } /* Now issue the SelectionNotify event. */ - XSendEvent (display, window, False, 0L, &reply_base); + XSendEvent (display, window, False, 0, &reply_base); XFlush (display); #ifdef TRACE_SELECTION @@ -710,7 +700,7 @@ x_reply_selection_request (struct input_event *event, requestor that we're done. */ block_input (); if (! waiting_for_other_props_on_window (display, window)) - XSelectInput (display, window, 0L); + XSelectInput (display, window, 0); TRACE1 ("Set %s to a 0-length chunk to indicate EOF", XGetAtomName (display, cs->property)); @@ -750,12 +740,11 @@ x_handle_selection_request (struct input_event *event) struct gcpro gcpro1, gcpro2; Time local_selection_time; - Display *display = SELECTION_EVENT_DISPLAY (event); - struct x_display_info *dpyinfo = x_display_info_for_display (display); + struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); Atom selection = SELECTION_EVENT_SELECTION (event); - Lisp_Object selection_symbol = x_atom_to_symbol (display, selection); + Lisp_Object selection_symbol = x_atom_to_symbol (dpyinfo, selection); Atom target = SELECTION_EVENT_TARGET (event); - Lisp_Object target_symbol = x_atom_to_symbol (display, target); + Lisp_Object target_symbol = x_atom_to_symbol (dpyinfo, target); Atom property = SELECTION_EVENT_PROPERTY (event); Lisp_Object local_selection_data; int success = 0; @@ -800,7 +789,7 @@ x_handle_selection_request (struct input_event *event) if (property == None) goto DONE; multprop - = x_get_window_property_as_lisp_data (display, requestor, property, + = x_get_window_property_as_lisp_data (dpyinfo, requestor, property, QMULTIPLE, selection); if (!VECTORP (multprop) || ASIZE (multprop) % 2) @@ -904,11 +893,7 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol, cs->wait_object = NULL; cs->next = converted_selections; converted_selections = cs; - lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event), - lisp_selection, - &(cs->data), &(cs->type), - &(cs->size), &(cs->format), - &(cs->nofree)); + lisp_data_to_selection_data (dpyinfo, lisp_selection, cs); UNGCPRO; return 1; } @@ -920,20 +905,19 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol, static void x_handle_selection_clear (struct input_event *event) { - Display *display = SELECTION_EVENT_DISPLAY (event); Atom selection = SELECTION_EVENT_SELECTION (event); Time changed_owner_time = SELECTION_EVENT_TIME (event); Lisp_Object selection_symbol, local_selection_data; Time local_selection_time; - struct x_display_info *dpyinfo = x_display_info_for_display (display); + struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); Lisp_Object Vselection_alist; TRACE0 ("x_handle_selection_clear"); if (!dpyinfo) return; - selection_symbol = x_atom_to_symbol (display, selection); + selection_symbol = x_atom_to_symbol (dpyinfo, selection); local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); /* Well, we already believe that we don't own it, so that's just fine. */ @@ -1070,20 +1054,18 @@ expect_property_change (Display *display, Window window, static void unexpect_property_change (struct prop_location *location) { - struct prop_location *prev = 0, *rest = property_change_wait_list; - while (rest) + struct prop_location *prop, **pprev = &property_change_wait_list; + + for (prop = property_change_wait_list; prop; prop = *pprev) { - if (rest == location) + if (prop == location) { - if (prev) - prev->next = rest->next; - else - property_change_wait_list = rest->next; - xfree (rest); - return; + *pprev = prop->next; + xfree (prop); + break; } - prev = rest; - rest = rest->next; + else + pprev = &prop->next; } } @@ -1245,7 +1227,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, /* Otherwise, the selection is waiting for us on the requested property. */ return - x_get_window_property_as_lisp_data (display, requestor_window, + x_get_window_property_as_lisp_data (dpyinfo, requestor_window, target_property, target_type, selection_atom); } @@ -1283,7 +1265,7 @@ x_get_window_property (Display *display, Window window, Atom property, /* First probe the thing to find out how big it is. */ result = XGetWindowProperty (display, window, property, - 0L, 0L, False, AnyPropertyType, + 0, 0, False, AnyPropertyType, actual_type_ret, actual_format_ret, actual_size_ret, &bytes_remaining, &tmp_data); @@ -1299,9 +1281,7 @@ x_get_window_property (Display *display, Window window, Atom property, if (total_size_max < bytes_remaining) goto size_overflow; total_size = bytes_remaining; - data = malloc (total_size + 1); - if (! data) - goto memory_exhausted; + data = xmalloc (total_size + 1); /* Now read, until we've gotten it all. */ while (bytes_remaining) @@ -1352,9 +1332,7 @@ x_get_window_property (Display *display, Window window, Atom property, if (remaining_lim < 0 || remaining_lim < bytes_remaining) goto size_overflow; total_size = offset + bytes_gotten + bytes_remaining; - data1 = realloc (data, total_size + 1); - if (! data1) - goto memory_exhausted; + data1 = xrealloc (data, total_size + 1); data = data1; } @@ -1386,20 +1364,17 @@ x_get_window_property (Display *display, Window window, Atom property, return; size_overflow: - free (data); + if (data) + xfree (data); unblock_input (); memory_full (SIZE_MAX); - - memory_exhausted: - free (data); - unblock_input (); - memory_full (total_size + 1); } /* Use xfree, not XFree, to free the data obtained with this function. */ static void -receive_incremental_selection (Display *display, Window window, Atom property, +receive_incremental_selection (struct x_display_info *dpyinfo, + Window window, Atom property, Lisp_Object target_type, unsigned int min_size_bytes, unsigned char **data_ret, @@ -1409,6 +1384,8 @@ receive_incremental_selection (Display *display, Window window, Atom property, { ptrdiff_t offset = 0; struct prop_location *wait_object; + Display *display = dpyinfo->display; + if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes) memory_full (SIZE_MAX); *data_ret = xmalloc (min_size_bytes); @@ -1427,10 +1404,10 @@ receive_incremental_selection (Display *display, Window window, Atom property, block_input (); XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); TRACE1 (" Delete property %s", - SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property)))); + SDATA (SYMBOL_NAME (x_atom_to_symbol (dpyinfo, property)))); XDeleteProperty (display, window, property); TRACE1 (" Expect new value of property %s", - SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property)))); + SDATA (SYMBOL_NAME (x_atom_to_symbol (dpyinfo, property)))); wait_object = expect_property_change (display, window, property, PropertyNewValue); XFlush (display); @@ -1495,8 +1472,8 @@ receive_incremental_selection (Display *display, Window window, Atom property, if this fails. */ static Lisp_Object -x_get_window_property_as_lisp_data (Display *display, Window window, - Atom property, +x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo, + Window window, Atom property, Lisp_Object target_type, Atom selection_atom) { @@ -1506,7 +1483,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, unsigned char *data = 0; ptrdiff_t bytes = 0; Lisp_Object val; - struct x_display_info *dpyinfo = x_display_info_for_display (display); + Display *display = dpyinfo->display; TRACE0 ("Reading selection data"); @@ -1523,11 +1500,11 @@ x_get_window_property_as_lisp_data (Display *display, Window window, signal_error ("Selection owner couldn't convert", actual_type ? list2 (target_type, - x_atom_to_symbol (display, actual_type)) + x_atom_to_symbol (dpyinfo, actual_type)) : target_type); else signal_error ("No selection", - x_atom_to_symbol (display, selection_atom)); + x_atom_to_symbol (dpyinfo, selection_atom)); } if (actual_type == dpyinfo->Xatom_INCR) @@ -1540,7 +1517,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, calls xmalloc itself. */ xfree (data); unblock_input (); - receive_incremental_selection (display, window, property, target_type, + receive_incremental_selection (dpyinfo, window, property, target_type, min_size_bytes, &data, &bytes, &actual_type, &actual_format, &actual_size); @@ -1554,7 +1531,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, /* It's been read. Now convert it to a lisp object in some semi-rational manner. */ - val = selection_data_to_lisp_data (display, data, bytes, + val = selection_data_to_lisp_data (dpyinfo, data, bytes, actual_type, actual_format); /* Use xfree, not XFree, because x_get_window_property @@ -1595,11 +1572,10 @@ x_get_window_property_as_lisp_data (Display *display, Window window, static Lisp_Object -selection_data_to_lisp_data (Display *display, const unsigned char *data, +selection_data_to_lisp_data (struct x_display_info *dpyinfo, + const unsigned char *data, ptrdiff_t size, Atom type, int format) { - struct x_display_info *dpyinfo = x_display_info_for_display (display); - if (type == dpyinfo->Xatom_NULL) return QNULL; @@ -1637,13 +1613,13 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, int *idata = (int *) data; if (size == sizeof (int)) - return x_atom_to_symbol (display, (Atom) idata[0]); + return x_atom_to_symbol (dpyinfo, (Atom) idata[0]); else { Lisp_Object v = make_uninit_vector (size / sizeof (int)); for (i = 0; i < size / sizeof (int); i++) - ASET (v, i, x_atom_to_symbol (display, (Atom) idata[i])); + ASET (v, i, x_atom_to_symbol (dpyinfo, (Atom) idata[i])); return v; } } @@ -1705,15 +1681,13 @@ cons_to_x_long (Lisp_Object obj) /* Use xfree, not XFree, to free the data obtained with this function. */ static void -lisp_data_to_selection_data (Display *display, Lisp_Object obj, - unsigned char **data_ret, Atom *type_ret, - ptrdiff_t *size_ret, - int *format_ret, int *nofree_ret) +lisp_data_to_selection_data (struct x_display_info *dpyinfo, + Lisp_Object obj, struct selection_data *cs) { Lisp_Object type = Qnil; - struct x_display_info *dpyinfo = x_display_info_for_display (display); - *nofree_ret = 0; + eassert (cs != NULL); + cs->nofree = 0; if (CONSP (obj) && SYMBOLP (XCAR (obj))) { @@ -1725,9 +1699,9 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, if (EQ (obj, QNULL) || (EQ (type, QNULL))) { /* This is not the same as declining */ - *format_ret = 32; - *size_ret = 0; - *data_ret = 0; + cs->format = 32; + cs->size = 0; + cs->data = NULL; type = QNULL; } else if (STRINGP (obj)) @@ -1737,19 +1711,19 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, signal_error ("Non-ASCII string must be encoded in advance", obj); if (NILP (type)) type = QSTRING; - *format_ret = 8; - *size_ret = SBYTES (obj); - *data_ret = SDATA (obj); - *nofree_ret = 1; + cs->format = 8; + cs->size = SBYTES (obj); + cs->data = SDATA (obj); + cs->nofree = 1; } else if (SYMBOLP (obj)) { void *data = xmalloc (sizeof (Atom) + 1); Atom *x_atom_ptr = data; - *data_ret = data; - *format_ret = 32; - *size_ret = 1; - (*data_ret) [sizeof (Atom)] = 0; + cs->data = data; + cs->format = 32; + cs->size = 1; + cs->data[sizeof (Atom)] = 0; *x_atom_ptr = symbol_to_x_atom (dpyinfo, obj); if (NILP (type)) type = QATOM; } @@ -1757,10 +1731,10 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, { void *data = xmalloc (sizeof (short) + 1); short *short_ptr = data; - *data_ret = data; - *format_ret = 16; - *size_ret = 1; - (*data_ret) [sizeof (short)] = 0; + cs->data = data; + cs->format = 16; + cs->size = 1; + cs->data[sizeof (short)] = 0; *short_ptr = XINT (obj); if (NILP (type)) type = QINTEGER; } @@ -1772,10 +1746,10 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, { void *data = xmalloc (sizeof (unsigned long) + 1); unsigned long *x_long_ptr = data; - *data_ret = data; - *format_ret = 32; - *size_ret = 1; - (*data_ret) [sizeof (unsigned long)] = 0; + cs->data = data; + cs->format = 32; + cs->size = 1; + cs->data[sizeof (unsigned long)] = 0; *x_long_ptr = cons_to_x_long (obj); if (NILP (type)) type = QINTEGER; } @@ -1798,10 +1772,10 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, if (!SYMBOLP (AREF (obj, i))) signal_error ("All elements of selection vector must have same type", obj); - *data_ret = data = xnmalloc (size, sizeof *x_atoms); + cs->data = data = xnmalloc (size, sizeof *x_atoms); x_atoms = data; - *format_ret = 32; - *size_ret = size; + cs->format = 32; + cs->size = size; for (i = 0; i < size; i++) x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i)); } @@ -1827,11 +1801,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, break; } } - *data_ret = data = xnmalloc (size, data_size); + cs->data = data = xnmalloc (size, data_size); x_atoms = data; shorts = data; - *format_ret = format; - *size_ret = size; + cs->format = format; + cs->size = size; for (i = 0; i < size; i++) { if (format == 32) @@ -1844,7 +1818,7 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, else signal_error (/* Qselection_error */ "Unrecognized selection data", obj); - *type_ret = symbol_to_x_atom (dpyinfo, type); + cs->type = symbol_to_x_atom (dpyinfo, type); } static Lisp_Object @@ -1927,7 +1901,7 @@ frame_for_x_selection (Lisp_Object object) } else if (TERMINALP (object)) { - struct terminal *t = get_terminal (object, 1); + struct terminal *t = decode_live_terminal (object); if (t->type == output_x_window) FOR_EACH_FRAME (tail, frame) @@ -2077,7 +2051,7 @@ On MS-DOS, all this does is return non-nil if we own the selection. */) the selection owner to None. The NCD server does, the MIT Sun4 server doesn't. So we synthesize one; this means we might get two, but that's ok, because the second one won't have any effect. */ - SELECTION_EVENT_DISPLAY (&event.sie) = dpyinfo->display; + SELECTION_EVENT_DPYINFO (&event.sie) = dpyinfo; SELECTION_EVENT_SELECTION (&event.sie) = selection_atom; SELECTION_EVENT_TIME (&event.sie) = timestamp; x_handle_selection_clear (&event.ie); @@ -2178,11 +2152,9 @@ x_clipboard_manager_save (Lisp_Object frame) static Lisp_Object x_clipboard_manager_error_1 (Lisp_Object err) { - Lisp_Object args[2]; - args[0] = build_string ("X clipboard manager error: %s\n\ + AUTO_STRING (format, "X clipboard manager error: %s\n\ If the problem persists, set `x-select-enable-clipboard-manager' to nil."); - args[1] = CAR (CDR (err)); - Fmessage (2, args); + Fmessage (2, (Lisp_Object []) {format, CAR (CDR (err))}); return Qnil; } @@ -2249,10 +2221,8 @@ x_clipboard_manager_save_all (void) local_frame = XCAR (XCDR (XCDR (XCDR (local_selection)))); if (FRAME_LIVE_P (XFRAME (local_frame))) { - Lisp_Object args[1]; - args[0] = build_string ("Saving clipboard to X clipboard manager..."); - Fmessage (1, args); - + AUTO_STRING (saving, "Saving clipboard to X clipboard manager..."); + Fmessage (1, &saving); internal_condition_case_1 (x_clipboard_manager_save, local_frame, Qt, x_clipboard_manager_error_2); } @@ -2307,10 +2277,10 @@ x_check_property_data (Lisp_Object data) void x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format) { - long val; - long *d32 = (long *) ret; - short *d16 = (short *) ret; - char *d08 = (char *) ret; + unsigned long val; + unsigned long *d32 = (unsigned long *) ret; + unsigned short *d16 = (unsigned short *) ret; + unsigned char *d08 = (unsigned char *) ret; Lisp_Object iter; for (iter = data; CONSP (iter); iter = XCDR (iter)) @@ -2318,11 +2288,26 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format) Lisp_Object o = XCAR (iter); if (INTEGERP (o) || FLOATP (o) || CONSP (o)) - val = cons_to_signed (o, LONG_MIN, LONG_MAX); + { + if (CONSP (o) + && RANGED_INTEGERP (X_LONG_MIN >> 16, XCAR (o), X_LONG_MAX >> 16) + && RANGED_INTEGERP (- (1 << 15), XCDR (o), -1)) + { + /* cons_to_x_long does not handle negative values for v2. + For XDnd, v2 might be y of a window, and can be negative. + The XDnd spec. is not explicit about negative values, + but let's assume negative v2 is sent modulo 2**16. */ + unsigned long v1 = XINT (XCAR (o)) & 0xffff; + unsigned long v2 = XINT (XCDR (o)) & 0xffff; + val = (v1 << 16) | v2; + } + else + val = cons_to_x_long (o); + } else if (STRINGP (o)) { block_input (); - val = (long) XInternAtom (dpy, SSDATA (o), False); + val = XInternAtom (dpy, SSDATA (o), False); unblock_input (); } else @@ -2330,17 +2315,15 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format) if (format == 8) { - if (CHAR_MIN <= val && val <= CHAR_MAX) - *d08++ = val; - else + if ((1 << 8) < val && val <= X_ULONG_MAX - (1 << 7)) error ("Out of 'char' range"); + *d08++ = val; } else if (format == 16) { - if (SHRT_MIN <= val && val <= SHRT_MAX) - *d16++ = val; - else + if ((1 << 16) < val && val <= X_ULONG_MAX - (1 << 15)) error ("Out of 'short' range"); + *d16++ = val; } else *d32++ = val; @@ -2369,45 +2352,8 @@ x_property_data_to_lisp (struct frame *f, const unsigned char *data, ptrdiff_t format_bytes = format >> 3; if (PTRDIFF_MAX / format_bytes < size) memory_full (SIZE_MAX); - return selection_data_to_lisp_data (FRAME_X_DISPLAY (f), - data, size * format_bytes, type, format); -} - -/* Get the mouse position in frame relative coordinates. */ - -static void -mouse_position_for_drop (struct frame *f, int *x, int *y) -{ - Window root, dummy_window; - int dummy; - - block_input (); - - XQueryPointer (FRAME_X_DISPLAY (f), - DefaultRootWindow (FRAME_X_DISPLAY (f)), - - /* The root window which contains the pointer. */ - &root, - - /* Window pointer is on, not used */ - &dummy_window, - - /* The position on that root window. */ - x, y, - - /* x/y in dummy_window coordinates, not used. */ - &dummy, &dummy, - - /* Modifier keys and pointer buttons, about which - we don't care. */ - (unsigned int *) &dummy); - - - /* Absolute to relative. */ - *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); - *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); - - unblock_input (); + return selection_data_to_lisp_data (FRAME_DISPLAY_INFO (f), data, + size * format_bytes, type, format); } DEFUN ("x-get-atom-name", Fx_get_atom_name, @@ -2519,7 +2465,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, } vec = Fmake_vector (make_number (4), Qnil); - ASET (vec, 0, SYMBOL_NAME (x_atom_to_symbol (FRAME_X_DISPLAY (f), + ASET (vec, 0, SYMBOL_NAME (x_atom_to_symbol (FRAME_DISPLAY_INFO (f), event->message_type))); ASET (vec, 1, frame); ASET (vec, 2, make_number (event->format)); @@ -2529,7 +2475,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, event->format, size)); - mouse_position_for_drop (f, &x, &y); + x_relative_mouse_position (f, &x, &y); bufp->kind = DRAG_N_DROP_EVENT; bufp->frame_or_window = frame; bufp->timestamp = CurrentTime; @@ -2683,12 +2629,14 @@ syms_of_xselect (void) converted_selections = NULL; conversion_fail_tag = None; + /* FIXME: Duplicate definition in nsselect.c. */ DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist, doc: /* An alist associating X Windows selection-types with functions. These functions are called to convert the selection, with three args: the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD'); a desired type to which the selection should be converted; -and the local selection value (whatever was given to `x-own-selection'). +and the local selection value (whatever was given to +`x-own-selection-internal'). The function should return the value to send to the X server \(typically a string). A return value of nil diff --git a/src/xsmfns.c b/src/xsmfns.c index 9a31f518f30..cd4f9ce57fa 100644 --- a/src/xsmfns.c +++ b/src/xsmfns.c @@ -49,7 +49,7 @@ static struct input_event emacs_event; /* The descriptor that we use to check for data from the session manager. */ -static int ice_fd; +static int ice_fd = -1; /* A flag that says if we are in shutdown interactions or not. */ @@ -395,7 +395,7 @@ x_session_initialize (struct x_display_info *dpyinfo) { #define SM_ERRORSTRING_LEN 512 char errorstring[SM_ERRORSTRING_LEN]; - char* previous_id = NULL; + char *previous_id = NULL; SmcCallbacks callbacks; ptrdiff_t name_len = 0; @@ -415,11 +415,11 @@ x_session_initialize (struct x_display_info *dpyinfo) /* This malloc will not be freed, but it is only done once, and hopefully not very large */ emacs_program = xmalloc (name_len + 1); - emacs_program[0] = '\0'; + char *z = emacs_program; if (! EQ (Vinvocation_directory, Qnil)) - strcpy (emacs_program, SSDATA (Vinvocation_directory)); - strcat (emacs_program, SSDATA (Vinvocation_name)); + z = lispstpcpy (z, Vinvocation_directory); + lispstpcpy (z, Vinvocation_name); /* The SM protocol says all callbacks are mandatory, so set up all here and in the mask passed to SmcOpenConnection. */ diff --git a/src/xterm.c b/src/xterm.c index b6430ad11b0..53eb7b3625d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -32,6 +32,16 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "xterm.h" #include <X11/cursorfont.h> +/* If we have Xfixes extension, use it for pointer blanking. */ +#ifdef HAVE_XFIXES +#include <X11/extensions/Xfixes.h> +#endif + +/* Using Xft implies that XRender is available. */ +#ifdef HAVE_XFT +#include <X11/extensions/Xrender.h> +#endif + /* Load sys/types.h if not already loaded. In some systems loading it twice is suicidal. */ #ifndef makedev @@ -70,6 +80,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "xsettings.h" #include "xgselect.h" #include "sysselect.h" +#include "menu.h" #ifdef USE_X_TOOLKIT #include <X11/Shell.h> @@ -215,7 +226,6 @@ static void x_lower_frame (struct frame *); static const XColor *x_color_cells (Display *, int *); static int x_io_error_quitter (Display *); static struct terminal *x_create_terminal (struct x_display_info *); -void x_delete_terminal (struct terminal *); static void x_update_end (struct frame *); static void XTframe_up_to_date (struct frame *); static void x_clear_frame (struct frame *); @@ -236,11 +246,15 @@ static void x_clip_to_row (struct window *, struct glyph_row *, static void x_flush (struct frame *f); static void x_update_begin (struct frame *); static void x_update_window_begin (struct window *); -static struct scroll_bar *x_window_to_scroll_bar (Display *, Window); +static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int); static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, enum scroll_bar_part *, Lisp_Object *, Lisp_Object *, Time *); +static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *, + enum scroll_bar_part *, + Lisp_Object *, Lisp_Object *, + Time *); static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *); static void x_check_fullscreen (struct frame *); static void x_check_expected_move (struct frame *, int, int); @@ -258,6 +272,7 @@ static void x_wm_set_window_state (struct frame *, int); static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t); static void x_initialize (void); +static int get_current_wm_state (struct frame *, Window, int *, int *); /* Flush display of frame F. */ @@ -308,7 +323,7 @@ int event_record_index; void record_event (char *locus, int type) { - if (event_record_index == sizeof (event_record) / sizeof (struct record)) + if (event_record_index == ARRAYELTS (event_record)) event_record_index = 0; event_record[event_record_index].locus = locus; @@ -348,8 +363,10 @@ x_find_topmost_parent (struct frame *f) unsigned int nchildren; win = wi; - XQueryTree (dpy, win, &root, &wi, &children, &nchildren); - XFree (children); + if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren)) + XFree (children); + else + break; } return win; @@ -398,7 +415,7 @@ x_set_frame_alpha (struct frame *f) if (parent != None) XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &opac, 1L); + (unsigned char *) &opac, 1); /* return unless necessary */ { @@ -408,7 +425,7 @@ x_set_frame_alpha (struct frame *f) unsigned long n, left; rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, - 0L, 1L, False, XA_CARDINAL, + 0, 1, False, XA_CARDINAL, &actual, &format, &n, &left, &data); @@ -426,23 +443,10 @@ x_set_frame_alpha (struct frame *f) XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &opac, 1L); + (unsigned char *) &opac, 1); x_uncatch_errors (); } -int -x_display_pixel_height (struct x_display_info *dpyinfo) -{ - return HeightOfScreen (dpyinfo->screen); -} - -int -x_display_pixel_width (struct x_display_info *dpyinfo) -{ - return WidthOfScreen (dpyinfo->screen); -} - - /*********************************************************************** Starting and ending an update ***********************************************************************/ @@ -635,10 +639,8 @@ XTframe_up_to_date (struct frame *f) } -/* Clear under internal border if any for non-toolkit builds. */ - - -#if !defined USE_X_TOOLKIT && !defined USE_GTK +/* Clear under internal border if any (GTK has its own version). */ +#ifndef USE_GTK void x_clear_under_internal_border (struct frame *f) { @@ -897,7 +899,7 @@ x_set_mouse_face_gc (struct glyph_string *s) else face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); s->face = FACE_FROM_ID (s->f, face_id); - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); if (s->font == s->face->font) s->gc = s->face->gc; @@ -945,7 +947,7 @@ x_set_mode_line_face_gc (struct glyph_string *s) static void x_set_glyph_string_gc (struct glyph_string *s) { - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); if (s->hl == DRAW_NORMAL_TEXT) { @@ -974,10 +976,7 @@ x_set_glyph_string_gc (struct glyph_string *s) s->stippled_p = s->face->stipple != 0; } else - { - s->gc = s->face->gc; - s->stippled_p = s->face->stipple != 0; - } + emacs_abort (); /* GC must have been set. */ eassert (s->gc != 0); @@ -2956,8 +2955,64 @@ x_clear_frame (struct frame *f) unblock_input (); } +/* RIF: Show hourglass cursor on frame F. */ + +static void +x_show_hourglass (struct frame *f) +{ + Display *dpy = FRAME_X_DISPLAY (f); + + if (dpy) + { + struct x_output *x = FRAME_X_OUTPUT (f); +#ifdef USE_X_TOOLKIT + if (x->widget) +#else + if (FRAME_OUTER_WINDOW (f)) +#endif + { + x->hourglass_p = 1; + + if (!x->hourglass_window) + { + unsigned long mask = CWCursor; + XSetWindowAttributes attrs; +#ifdef USE_GTK + Window parent = FRAME_X_WINDOW (f); +#else + Window parent = FRAME_OUTER_WINDOW (f); +#endif + attrs.cursor = x->hourglass_cursor; + + x->hourglass_window = XCreateWindow + (dpy, parent, 0, 0, 32000, 32000, 0, 0, + InputOnly, CopyFromParent, mask, &attrs); + } + + XMapRaised (dpy, x->hourglass_window); + XFlush (dpy); + } + } +} + +/* RIF: Cancel hourglass cursor on frame F. */ + +static void +x_hide_hourglass (struct frame *f) +{ + struct x_output *x = FRAME_X_OUTPUT (f); + + /* Watch out for newly created frames. */ + if (x->hourglass_window) + { + XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window); + /* Sync here because XTread_socket looks at the + hourglass_p flag that is reset to zero below. */ + XSync (FRAME_X_DISPLAY (f), False); + x->hourglass_p = 0; + } +} - /* Invert the middle quarter of the frame for .15 sec. */ static void @@ -3105,16 +3160,7 @@ static void XTtoggle_invisible_pointer (struct frame *f, int invisible) { block_input (); - if (invisible) - { - if (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0) - XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->invisible_cursor); - } - else - XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - f->output_data.x->current_cursor); - f->pointer_invisible = invisible; + FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible); unblock_input (); } @@ -3931,7 +3977,14 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, block_input (); if (dpyinfo->last_mouse_scroll_bar && insist == 0) - x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp); + { + struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar; + + if (bar->horizontal) + x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp); + else + x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp); + } else { Window root; @@ -4075,7 +4128,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, { struct scroll_bar *bar; - bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win); + bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2); if (bar) { @@ -4104,7 +4157,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, dpyinfo->last_mouse_glyph_frame = f1; *bar_window = Qnil; - *part = 0; + *part = scroll_bar_above_handle; *fp = f1; XSETINT (*x, win_x); XSETINT (*y, win_y); @@ -4130,7 +4183,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, bits. */ static struct scroll_bar * -x_window_to_scroll_bar (Display *display, Window window_id) +x_window_to_scroll_bar (Display *display, Window window_id, int type) { Lisp_Object tail, frame; @@ -4155,8 +4208,11 @@ x_window_to_scroll_bar (Display *display, Window window_id) condemned = Qnil, ! NILP (bar)); bar = XSCROLL_BAR (bar)->next) - if (XSCROLL_BAR (bar)->x_window == window_id && - FRAME_X_DISPLAY (XFRAME (frame)) == display) + if (XSCROLL_BAR (bar)->x_window == window_id + && FRAME_X_DISPLAY (XFRAME (frame)) == display + && (type = 2 + || (type == 1 && XSCROLL_BAR (bar)->horizontal) + || (type == 0 && !XSCROLL_BAR (bar)->horizontal))) return XSCROLL_BAR (bar); } @@ -4194,7 +4250,8 @@ x_window_to_menu_bar (Window window) #ifdef USE_TOOLKIT_SCROLL_BARS -static void x_send_scroll_bar_event (Lisp_Object, int, int, int); +static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part, + int, int, bool); /* Lisp window being scrolled. Set when starting to interact with a toolkit scroll bar, reset to nil when ending the interaction. */ @@ -4208,6 +4265,7 @@ static Lisp_Object window_being_scrolled; /* Id of action hook installed for scroll bars. */ static XtActionHookId action_hook_id; +static XtActionHookId horizontal_action_hook_id; static Boolean xaw3d_arrow_scroll; @@ -4245,7 +4303,7 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name, struct scroll_bar *bar; x_send_scroll_bar_event (window_being_scrolled, - scroll_bar_end_scroll, 0, 0); + scroll_bar_end_scroll, 0, 0, 0); w = XWINDOW (window_being_scrolled); bar = XSCROLL_BAR (w->vertical_scroll_bar); @@ -4263,6 +4321,49 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name, toolkit_scroll_bar_interaction = 0; } } + + +static void +xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name, + XEvent *event, String *params, Cardinal *num_params) +{ + int scroll_bar_p; + const char *end_action; + +#ifdef USE_MOTIF + scroll_bar_p = XmIsScrollBar (widget); + end_action = "Release"; +#else /* !USE_MOTIF i.e. use Xaw */ + scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass); + end_action = "EndScroll"; +#endif /* USE_MOTIF */ + + if (scroll_bar_p + && strcmp (action_name, end_action) == 0 + && WINDOWP (window_being_scrolled)) + { + struct window *w; + struct scroll_bar *bar; + + x_send_scroll_bar_event (window_being_scrolled, + scroll_bar_end_scroll, 0, 0, 1); + w = XWINDOW (window_being_scrolled); + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + + if (bar->dragging != -1) + { + bar->dragging = -1; + /* The thumb size is incorrect while dragging: fix it. */ + set_horizontal_scroll_bar (w); + } + window_being_scrolled = Qnil; +#if defined (USE_LUCID) + bar->last_seen_part = scroll_bar_nowhere; +#endif + /* Xt timeouts no longer needed. */ + toolkit_scroll_bar_interaction = 0; + } +} #endif /* not USE_GTK */ /* Send a client message with message type Xatom_Scrollbar for a @@ -4271,7 +4372,8 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name, amount to scroll of a whole of WHOLE. */ static void -x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) +x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part, + int portion, int whole, bool horizontal) { XEvent event; XClientMessageEvent *ev = &event.xclient; @@ -4286,7 +4388,9 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) /* Construct a ClientMessage event to send to the frame. */ ev->type = ClientMessage; - ev->message_type = FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar; + ev->message_type = (horizontal + ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar + : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar); ev->display = FRAME_X_DISPLAY (f); ev->window = FRAME_X_WINDOW (f); ev->format = 32; @@ -4351,6 +4455,41 @@ x_scroll_bar_to_input_event (const XEvent *event, ievent->modifiers = 0; } +/* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs + input event in *IEVENT. */ + +static void +x_horizontal_scroll_bar_to_input_event (const XEvent *event, + struct input_event *ievent) +{ + const XClientMessageEvent *ev = &event->xclient; + Lisp_Object window; + struct window *w; + + /* See the comment in the function above. */ + intptr_t iw0 = ev->data.l[0]; + intptr_t iw1 = ev->data.l[1]; + intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu); + w = (struct window *) iw; + + XSETWINDOW (window, w); + + ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT; + ievent->frame_or_window = window; + ievent->arg = Qnil; +#ifdef USE_GTK + ievent->timestamp = CurrentTime; +#else + ievent->timestamp = + XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame))); +#endif + ievent->code = 0; + ievent->part = ev->data.l[2]; + ievent->x = make_number (ev->data.l[3]); + ievent->y = make_number (ev->data.l[4]); + ievent->modifiers = 0; +} + #ifdef USE_MOTIF @@ -4358,7 +4497,6 @@ x_scroll_bar_to_input_event (const XEvent *event, #define XM_SB_MAX 10000000 - /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the scroll_bar structure. CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */ @@ -4368,52 +4506,63 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) { struct scroll_bar *bar = client_data; XmScrollBarCallbackStruct *cs = call_data; - int part = -1, whole = 0, portion = 0; + enum scroll_bar_part part = scroll_bar_nowhere; + int horizontal = bar->horizontal, whole = 0, portion = 0; switch (cs->reason) { case XmCR_DECREMENT: bar->dragging = -1; - part = scroll_bar_up_arrow; + part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow; break; case XmCR_INCREMENT: bar->dragging = -1; - part = scroll_bar_down_arrow; + part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow; break; case XmCR_PAGE_DECREMENT: bar->dragging = -1; - part = scroll_bar_above_handle; + part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle; break; case XmCR_PAGE_INCREMENT: bar->dragging = -1; - part = scroll_bar_below_handle; + part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle; break; case XmCR_TO_TOP: bar->dragging = -1; - part = scroll_bar_to_top; + part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top; break; case XmCR_TO_BOTTOM: bar->dragging = -1; - part = scroll_bar_to_bottom; + part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom; break; case XmCR_DRAG: { int slider_size; - /* Get the slider size. */ block_input (); XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL); unblock_input (); - whole = XM_SB_MAX - slider_size; - portion = min (cs->value, whole); - part = scroll_bar_handle; + if (horizontal) + { + portion = bar->whole * ((float)cs->value / XM_SB_MAX); + whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX); + portion = min (portion, whole); + part = scroll_bar_horizontal_handle; + } + else + { + whole = XM_SB_MAX - slider_size; + portion = min (cs->value, whole); + part = scroll_bar_handle; + } + bar->dragging = cs->value; } break; @@ -4422,10 +4571,10 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) break; }; - if (part >= 0) + if (part != scroll_bar_nowhere) { window_being_scrolled = bar->window; - x_send_scroll_bar_event (bar->window, part, portion, whole); + x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal); } } @@ -4440,8 +4589,9 @@ xg_scroll_callback (GtkRange *range, gdouble value, gpointer user_data) { + int whole = 0, portion = 0; struct scroll_bar *bar = user_data; - int part = -1, whole = 0, portion = 0; + enum scroll_bar_part part = scroll_bar_nowhere; GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range)); struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA); @@ -4454,35 +4604,50 @@ xg_scroll_callback (GtkRange *range, if (FRAME_DISPLAY_INFO (f)->grabbed != 0 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4)) { - part = scroll_bar_handle; - whole = gtk_adjustment_get_upper (adj) - - gtk_adjustment_get_page_size (adj); - portion = min ((int)value, whole); - bar->dragging = portion; - } + if (bar->horizontal) + { + part = scroll_bar_horizontal_handle; + whole = (int)(gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj)); + portion = min ((int)value, whole); + bar->dragging = portion; + } + else + { + part = scroll_bar_handle; + whole = gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj); + portion = min ((int)value, whole); + bar->dragging = portion; + } + } break; case GTK_SCROLL_STEP_BACKWARD: - part = scroll_bar_up_arrow; + part = (bar->horizontal + ? scroll_bar_left_arrow : scroll_bar_up_arrow); bar->dragging = -1; break; case GTK_SCROLL_STEP_FORWARD: - part = scroll_bar_down_arrow; + part = (bar->horizontal + ? scroll_bar_right_arrow : scroll_bar_down_arrow); bar->dragging = -1; break; case GTK_SCROLL_PAGE_BACKWARD: - part = scroll_bar_above_handle; + part = (bar->horizontal + ? scroll_bar_before_handle : scroll_bar_above_handle); bar->dragging = -1; break; case GTK_SCROLL_PAGE_FORWARD: - part = scroll_bar_below_handle; + part = (bar->horizontal + ? scroll_bar_after_handle : scroll_bar_below_handle); bar->dragging = -1; break; } - if (part >= 0) + if (part != scroll_bar_nowhere) { window_being_scrolled = bar->window; - x_send_scroll_bar_event (bar->window, part, portion, whole); + x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal); } return FALSE; @@ -4500,7 +4665,7 @@ xg_end_scroll_callback (GtkWidget *widget, if (WINDOWP (window_being_scrolled)) { x_send_scroll_bar_event (window_being_scrolled, - scroll_bar_end_scroll, 0, 0); + scroll_bar_end_scroll, 0, 0, bar->horizontal); window_being_scrolled = Qnil; } @@ -4522,31 +4687,56 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data) float *top_addr = call_data; float top = *top_addr; float shown; - int whole, portion, height; + int whole, portion, height, width; enum scroll_bar_part part; + int horizontal = bar->horizontal; - /* Get the size of the thumb, a value between 0 and 1. */ - block_input (); - XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL); - unblock_input (); - whole = 10000000; - portion = shown < 1 ? top * whole : 0; + if (horizontal) + { + /* Get the size of the thumb, a value between 0 and 1. */ + block_input (); + XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL); + unblock_input (); - if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height)) - /* Some derivatives of Xaw refuse to shrink the thumb when you reach - the bottom, so we force the scrolling whenever we see that we're - too close to the bottom (in x_set_toolkit_scroll_bar_thumb - we try to ensure that we always stay two pixels away from the - bottom). */ - part = scroll_bar_down_arrow; + if (shown < 1) + { + whole = bar->whole - (shown * bar->whole); + portion = min (top * bar->whole, whole); + } + else + { + whole = bar->whole; + portion = 0; + } + + part = scroll_bar_horizontal_handle; + } else - part = scroll_bar_handle; + { + /* Get the size of the thumb, a value between 0 and 1. */ + block_input (); + XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL); + unblock_input (); + + whole = 10000000; + portion = shown < 1 ? top * whole : 0; + + if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height)) + /* Some derivatives of Xaw refuse to shrink the thumb when you reach + the bottom, so we force the scrolling whenever we see that we're + too close to the bottom (in x_set_toolkit_scroll_bar_thumb + we try to ensure that we always stay two pixels away from the + bottom). */ + part = scroll_bar_down_arrow; + else + part = scroll_bar_handle; + } window_being_scrolled = bar->window; bar->dragging = portion; bar->last_seen_part = part; - x_send_scroll_bar_event (bar->window, part, portion, whole); + x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal); } @@ -4564,33 +4754,60 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data) struct scroll_bar *bar = client_data; /* The position really is stored cast to a pointer. */ int position = (intptr_t) call_data; - Dimension height; + Dimension height, width; enum scroll_bar_part part; - /* Get the height of the scroll bar. */ - block_input (); - XtVaGetValues (widget, XtNheight, &height, NULL); - unblock_input (); + if (bar->horizontal) + { + /* Get the width of the scroll bar. */ + block_input (); + XtVaGetValues (widget, XtNwidth, &width, NULL); + unblock_input (); - if (eabs (position) >= height) - part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle; + if (eabs (position) >= width) + part = (position < 0) ? scroll_bar_before_handle : scroll_bar_after_handle; - /* If Xaw3d was compiled with ARROW_SCROLLBAR, - it maps line-movement to call_data = max(5, height/20). */ - else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20)) - part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow; + /* If Xaw3d was compiled with ARROW_SCROLLBAR, + it maps line-movement to call_data = max(5, height/20). */ + else if (xaw3d_arrow_scroll && eabs (position) <= max (5, width / 20)) + part = (position < 0) ? scroll_bar_left_arrow : scroll_bar_right_arrow; + else + part = scroll_bar_move_ratio; + + window_being_scrolled = bar->window; + bar->dragging = -1; + bar->last_seen_part = part; + x_send_scroll_bar_event (bar->window, part, position, width, bar->horizontal); + } else - part = scroll_bar_move_ratio; + { - window_being_scrolled = bar->window; - bar->dragging = -1; - bar->last_seen_part = part; - x_send_scroll_bar_event (bar->window, part, position, height); + /* Get the height of the scroll bar. */ + block_input (); + XtVaGetValues (widget, XtNheight, &height, NULL); + unblock_input (); + + if (eabs (position) >= height) + part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle; + + /* If Xaw3d was compiled with ARROW_SCROLLBAR, + it maps line-movement to call_data = max(5, height/20). */ + else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20)) + part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow; + else + part = scroll_bar_move_ratio; + + window_being_scrolled = bar->window; + bar->dragging = -1; + bar->last_seen_part = part; + x_send_scroll_bar_event (bar->window, part, position, height, bar->horizontal); + } } #endif /* not USE_GTK and not USE_MOTIF */ #define SCROLL_BAR_NAME "verticalScrollBar" +#define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar" /* Create the widget for scroll bar BAR on frame F. Record the widget and X window of the scroll bar in BAR. */ @@ -4608,6 +4825,18 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) unblock_input (); } +static void +x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) +{ + const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME; + + block_input (); + xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback), + G_CALLBACK (xg_end_scroll_callback), + scroll_bar_name); + unblock_input (); +} + #else /* not USE_GTK */ static void @@ -4803,6 +5032,208 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) SET_SCROLL_BAR_X_WIDGET (bar, widget); xwindow = XtWindow (widget); bar->x_window = xwindow; + bar->whole = 1; + bar->horizontal = 0; + + unblock_input (); +} + +static void +x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) +{ + Window xwindow; + Widget widget; + Arg av[20]; + int ac = 0; + const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME; + unsigned long pixel; + + block_input (); + +#ifdef USE_MOTIF + /* Set resources. Create the widget. */ + XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac; + XtSetArg (av[ac], XmNminimum, 0); ++ac; + XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac; + XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac; + XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac; + XtSetArg (av[ac], XmNincrement, 1); ++ac; + XtSetArg (av[ac], XmNpageIncrement, 1); ++ac; + + pixel = f->output_data.x->scroll_bar_foreground_pixel; + if (pixel != -1) + { + XtSetArg (av[ac], XmNforeground, pixel); + ++ac; + } + + pixel = f->output_data.x->scroll_bar_background_pixel; + if (pixel != -1) + { + XtSetArg (av[ac], XmNbackground, pixel); + ++ac; + } + + widget = XmCreateScrollBar (f->output_data.x->edit_widget, + (char *) scroll_bar_name, av, ac); + + /* Add one callback for everything that can happen. */ + XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback, + (XtPointer) bar); + XtAddCallback (widget, XmNdragCallback, xm_scroll_callback, + (XtPointer) bar); + XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback, + (XtPointer) bar); + XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback, + (XtPointer) bar); + XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback, + (XtPointer) bar); + XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback, + (XtPointer) bar); + XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback, + (XtPointer) bar); + + /* Realize the widget. Only after that is the X window created. */ + XtRealizeWidget (widget); + + /* Set the cursor to an arrow. I didn't find a resource to do that. + And I'm wondering why it hasn't an arrow cursor by default. */ + XDefineCursor (XtDisplay (widget), XtWindow (widget), + f->output_data.x->nontext_cursor); + +#else /* !USE_MOTIF i.e. use Xaw */ + + /* Set resources. Create the widget. The background of the + Xaw3d scroll bar widget is a little bit light for my taste. + We don't alter it here to let users change it according + to their taste with `emacs*verticalScrollBar.background: xxx'. */ + XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac; + XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac; + /* For smoother scrolling with Xaw3d -sm */ + /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */ + + pixel = f->output_data.x->scroll_bar_foreground_pixel; + if (pixel != -1) + { + XtSetArg (av[ac], XtNforeground, pixel); + ++ac; + } + + pixel = f->output_data.x->scroll_bar_background_pixel; + if (pixel != -1) + { + XtSetArg (av[ac], XtNbackground, pixel); + ++ac; + } + + /* Top/bottom shadow colors. */ + + /* Allocate them, if necessary. */ + if (f->output_data.x->scroll_bar_top_shadow_pixel == -1) + { + pixel = f->output_data.x->scroll_bar_background_pixel; + if (pixel != -1) + { + if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), + FRAME_X_COLORMAP (f), + &pixel, 1.2, 0x8000)) + pixel = -1; + f->output_data.x->scroll_bar_top_shadow_pixel = pixel; + } + } + if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1) + { + pixel = f->output_data.x->scroll_bar_background_pixel; + if (pixel != -1) + { + if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), + FRAME_X_COLORMAP (f), + &pixel, 0.6, 0x4000)) + pixel = -1; + f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel; + } + } + +#ifdef XtNbeNiceToColormap + /* Tell the toolkit about them. */ + if (f->output_data.x->scroll_bar_top_shadow_pixel == -1 + || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1) + /* We tried to allocate a color for the top/bottom shadow, and + failed, so tell Xaw3d to use dithering instead. */ + /* But only if we have a small colormap. Xaw3d can allocate nice + colors itself. */ + { + XtSetArg (av[ac], XtNbeNiceToColormap, + DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16); + ++ac; + } + else + /* Tell what colors Xaw3d should use for the top/bottom shadow, to + be more consistent with other emacs 3d colors, and since Xaw3d is + not good at dealing with allocation failure. */ + { + /* This tells Xaw3d to use real colors instead of dithering for + the shadows. */ + XtSetArg (av[ac], XtNbeNiceToColormap, False); + ++ac; + + /* Specify the colors. */ + pixel = f->output_data.x->scroll_bar_top_shadow_pixel; + if (pixel != -1) + { + XtSetArg (av[ac], XtNtopShadowPixel, pixel); + ++ac; + } + pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel; + if (pixel != -1) + { + XtSetArg (av[ac], XtNbottomShadowPixel, pixel); + ++ac; + } + } +#endif + + widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass, + f->output_data.x->edit_widget, av, ac); + + { + char const *initial = ""; + char const *val = initial; + XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val, +#ifdef XtNarrowScrollbars + XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll, +#endif + XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL); + if (xaw3d_arrow_scroll || val == initial) + { /* ARROW_SCROLL */ + xaw3d_arrow_scroll = True; + /* Isn't that just a personal preference ? --Stef */ + XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL); + } + } + + /* Define callbacks. */ + XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar); + XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback, + (XtPointer) bar); + + /* Realize the widget. Only after that is the X window created. */ + XtRealizeWidget (widget); + +#endif /* !USE_MOTIF */ + + /* Install an action hook that lets us detect when the user + finishes interacting with a scroll bar. */ + if (horizontal_action_hook_id == 0) + horizontal_action_hook_id + = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0); + + /* Remember X window and widget in the scroll bar vector. */ + SET_SCROLL_BAR_X_WIDGET (bar, widget); + xwindow = XtWindow (widget); + bar->x_window = xwindow; + bar->whole = 1; + bar->horizontal = 1; unblock_input (); } @@ -4819,6 +5250,12 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); } +static void +x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) +{ + xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole); +} + #else /* not USE_GTK */ static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, @@ -4931,6 +5368,89 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio unblock_input (); } + +static void +x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, + int whole) +{ + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); + float top, shown; + + block_input (); + +#ifdef USE_MOTIF + bar->whole = whole; + shown = (float) portion / whole; + top = (float) position / (whole - portion); + { + int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX); + int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size); + + XmScrollBarSetValues (widget, value, size, 0, 0, False); + } +#else /* !USE_MOTIF i.e. use Xaw */ + bar->whole = whole; + if (whole == 0) + top = 0, shown = 1; + else + { + top = (float) position / whole; + shown = (float) portion / whole; + } + + { + float old_top, old_shown; + Dimension height; + XtVaGetValues (widget, + XtNtopOfThumb, &old_top, + XtNshown, &old_shown, + XtNheight, &height, + NULL); + +#if 0 + /* Massage the top+shown values. */ + if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow) + top = max (0, min (1, top)); + else + top = old_top; +#if ! defined (HAVE_XAW3D) + /* With Xaw, 'top' values too closer to 1.0 may + cause the thumb to disappear. Fix that. */ + top = min (top, 0.99f); +#endif + /* Keep two pixels available for moving the thumb down. */ + shown = max (0, min (1 - top - (2.0f / height), shown)); +#if ! defined (HAVE_XAW3D) + /* Likewise with too small 'shown'. */ + shown = max (shown, 0.01f); +#endif +#endif + + /* If the call to XawScrollbarSetThumb below doesn't seem to + work, check that 'NARROWPROTO' is defined in src/config.h. + If this is not so, most likely you need to fix configure. */ + XawScrollbarSetThumb (widget, top, shown); +#if 0 + if (top != old_top || shown != old_shown) + { + if (bar->dragging == -1) + XawScrollbarSetThumb (widget, top, shown); + else + { + /* Try to make the scrolling a tad smoother. */ + if (!xaw3d_pick_top) + shown = min (shown, old_shown); + + XawScrollbarSetThumb (widget, top, shown); + } + } +#endif + } +#endif /* !USE_MOTIF */ + + unblock_input (); +} #endif /* not USE_GTK */ #endif /* USE_TOOLKIT_SCROLL_BARS */ @@ -4947,7 +5467,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio scroll bar. */ static struct scroll_bar * -x_scroll_bar_create (struct window *w, int top, int left, int width, int height) +x_scroll_bar_create (struct window *w, int top, int left, int width, int height, bool horizontal) { struct frame *f = XFRAME (w->frame); struct scroll_bar *bar @@ -4957,7 +5477,10 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) block_input (); #ifdef USE_TOOLKIT_SCROLL_BARS - x_create_toolkit_scroll_bar (f, bar); + if (horizontal) + x_create_horizontal_toolkit_scroll_bar (f, bar); + else + x_create_toolkit_scroll_bar (f, bar); #else /* not USE_TOOLKIT_SCROLL_BARS */ { XSetWindowAttributes a; @@ -5004,6 +5527,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) bar->start = 0; bar->end = 0; bar->dragging = -1; + bar->horizontal = horizontal; #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID) bar->last_seen_part = scroll_bar_nowhere; #endif @@ -5020,8 +5544,12 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height) #ifdef USE_TOOLKIT_SCROLL_BARS { #ifdef USE_GTK - xg_update_scrollbar_pos (f, bar->x_window, top, - left,width, max (height, 1)); + if (horizontal) + xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, + left, width, max (height, 1)); + else + xg_update_scrollbar_pos (f, bar->x_window, top, + left, width, max (height, 1)); #else /* not USE_GTK */ Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0); @@ -5105,7 +5633,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild /* Draw the empty space above the handle. Note that we can't clear zero-height areas; that means "clear to end of window." */ - if (start > 0) + if ((inside_width > 0) && (start > 0)) x_clear_area (FRAME_X_DISPLAY (f), w, VERTICAL_SCROLL_BAR_LEFT_BORDER, VERTICAL_SCROLL_BAR_TOP_BORDER, @@ -5130,7 +5658,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild /* Draw the empty space below the handle. Note that we can't clear zero-height areas; that means "clear to end of window." */ - if (end < inside_height) + if ((inside_width > 0) && (end < inside_height)) x_clear_area (FRAME_X_DISPLAY (f), w, VERTICAL_SCROLL_BAR_LEFT_BORDER, VERTICAL_SCROLL_BAR_TOP_BORDER + end, @@ -5162,7 +5690,10 @@ x_scroll_bar_remove (struct scroll_bar *bar) #endif /* Dissociate this scroll bar from its window. */ - wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); + if (bar->horizontal) + wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil); + else + wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); unblock_input (); } @@ -5186,8 +5717,6 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); top = window_y; height = window_height; - - /* Compute the left edge and the width of the scroll bar area. */ left = WINDOW_SCROLL_BAR_AREA_X (w); width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); @@ -5202,7 +5731,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio unblock_input (); } - bar = x_scroll_bar_create (w, top, left, width, max (height, 1)); + bar = x_scroll_bar_create (w, top, left, width, max (height, 1), 0); } else { @@ -5291,6 +5820,138 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio } +static void +XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position) +{ + struct frame *f = XFRAME (w->frame); + Lisp_Object barobj; + struct scroll_bar *bar; + int top, height, left, width; + int window_x, window_width; + int pixel_width = WINDOW_PIXEL_WIDTH (w); + + /* Get window dimensions. */ + window_box (w, ANY_AREA, &window_x, 0, &window_width, 0); + left = window_x; + width = window_width; + top = WINDOW_SCROLL_BAR_AREA_Y (w); + height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w); + + /* Does the scroll bar exist yet? */ + if (NILP (w->horizontal_scroll_bar)) + { + if (width > 0 && height > 0) + { + block_input (); + + /* Clear also part between window_width and + WINDOW_PIXEL_WIDTH. */ + x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + left, top, pixel_width, height); + unblock_input (); + } + + bar = x_scroll_bar_create (w, top, left, width, height, 1); + } + else + { + /* It may just need to be moved and resized. */ + unsigned int mask = 0; + + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + + block_input (); + + if (left != bar->left) + mask |= CWX; + if (top != bar->top) + mask |= CWY; + if (width != bar->width) + mask |= CWWidth; + if (height != bar->height) + mask |= CWHeight; + +#ifdef USE_TOOLKIT_SCROLL_BARS + /* Move/size the scroll bar widget. */ + if (mask) + { + /* Since toolkit scroll bars are smaller than the space reserved + for them on the frame, we have to clear "under" them. */ + if (width > 0 && height > 0) + x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + WINDOW_LEFT_EDGE_X (w), top, + pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height); +#ifdef USE_GTK + xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left, + width, height); +#else /* not USE_GTK */ + XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar), + left, top, width, height, 0); +#endif /* not USE_GTK */ + } +#else /* not USE_TOOLKIT_SCROLL_BARS */ + + /* Clear areas not covered by the scroll bar because it's not as + wide as the area reserved for it. This makes sure a + previous mode line display is cleared after C-x 2 C-x 1, for + example. */ + { + int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w); + int rest = area_height - height; + if (rest > 0 && width > 0) + x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + left, top, width, rest); + } + + /* Move/size the scroll bar window. */ + if (mask) + { + XWindowChanges wc; + + wc.x = left; + wc.y = top; + wc.width = width; + wc.height = height; + XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window, + mask, &wc); + } + +#endif /* not USE_TOOLKIT_SCROLL_BARS */ + + /* Remember new settings. */ + bar->left = left; + bar->top = top; + bar->width = width; + bar->height = height; + + unblock_input (); + } + +#ifdef USE_TOOLKIT_SCROLL_BARS + x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole); +#else /* not USE_TOOLKIT_SCROLL_BARS */ + /* Set the scroll bar's current state, unless we're currently being + dragged. */ + if (bar->dragging == -1) + { + int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width); + + if (whole == 0) + x_scroll_bar_set_handle (bar, 0, left_range, 0); + else + { + int start = ((double) position * left_range) / whole; + int end = ((double) (position + portion) * left_range) / whole; + x_scroll_bar_set_handle (bar, start, end, 0); + } + } +#endif /* not USE_TOOLKIT_SCROLL_BARS */ + + XSETVECTOR (barobj, bar); + wset_horizontal_scroll_bar (w, barobj); +} + + /* The following three hooks are used when we're doing a thorough redisplay of the frame. We don't explicitly know which scroll bars are going to be deleted, because keeping track of when windows go @@ -5306,17 +5967,22 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio static void XTcondemn_scroll_bars (struct frame *frame) { - /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ - while (! NILP (FRAME_SCROLL_BARS (frame))) + if (!NILP (FRAME_SCROLL_BARS (frame))) { - Lisp_Object bar; - bar = FRAME_SCROLL_BARS (frame); - fset_scroll_bars (frame, XSCROLL_BAR (bar)->next); - XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); - XSCROLL_BAR (bar)->prev = Qnil; - if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) - XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; - fset_condemned_scroll_bars (frame, bar); + if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) + { + /* Prepend scrollbars to already condemned ones. */ + Lisp_Object last = FRAME_SCROLL_BARS (frame); + + while (!NILP (XSCROLL_BAR (last)->next)) + last = XSCROLL_BAR (last)->next; + + XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); + XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last; + } + + fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame)); + fset_scroll_bars (frame, Qnil); } } @@ -5325,47 +5991,84 @@ XTcondemn_scroll_bars (struct frame *frame) Note that WINDOW isn't necessarily condemned at all. */ static void -XTredeem_scroll_bar (struct window *window) +XTredeem_scroll_bar (struct window *w) { struct scroll_bar *bar; - struct frame *f; Lisp_Object barobj; + struct frame *f; /* We can't redeem this window's scroll bar if it doesn't have one. */ - if (NILP (window->vertical_scroll_bar)) + if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar)) emacs_abort (); - bar = XSCROLL_BAR (window->vertical_scroll_bar); - - /* Unlink it from the condemned list. */ - f = XFRAME (WINDOW_FRAME (window)); - if (NILP (bar->prev)) + if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) { - /* If the prev pointer is nil, it must be the first in one of - the lists. */ - if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar)) - /* It's not condemned. Everything's fine. */ - return; - else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), - window->vertical_scroll_bar)) - fset_condemned_scroll_bars (f, bar->next); + bar = XSCROLL_BAR (w->vertical_scroll_bar); + /* Unlink it from the condemned list. */ + f = XFRAME (WINDOW_FRAME (w)); + if (NILP (bar->prev)) + { + /* If the prev pointer is nil, it must be the first in one of + the lists. */ + if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar)) + /* It's not condemned. Everything's fine. */ + goto horizontal; + else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), + w->vertical_scroll_bar)) + fset_condemned_scroll_bars (f, bar->next); + else + /* If its prev pointer is nil, it must be at the front of + one or the other! */ + emacs_abort (); + } else - /* If its prev pointer is nil, it must be at the front of - one or the other! */ - emacs_abort (); + XSCROLL_BAR (bar->prev)->next = bar->next; + + if (! NILP (bar->next)) + XSCROLL_BAR (bar->next)->prev = bar->prev; + + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (! NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); } - else - XSCROLL_BAR (bar->prev)->next = bar->next; - if (! NILP (bar->next)) - XSCROLL_BAR (bar->next)->prev = bar->prev; + horizontal: + if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) + { + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + /* Unlink it from the condemned list. */ + f = XFRAME (WINDOW_FRAME (w)); + if (NILP (bar->prev)) + { + /* If the prev pointer is nil, it must be the first in one of + the lists. */ + if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar)) + /* It's not condemned. Everything's fine. */ + return; + else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), + w->horizontal_scroll_bar)) + fset_condemned_scroll_bars (f, bar->next); + else + /* If its prev pointer is nil, it must be at the front of + one or the other! */ + emacs_abort (); + } + else + XSCROLL_BAR (bar->prev)->next = bar->next; - bar->next = FRAME_SCROLL_BARS (f); - bar->prev = Qnil; - XSETVECTOR (barobj, bar); - fset_scroll_bars (f, barobj); - if (! NILP (bar->next)) - XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + if (! NILP (bar->next)) + XSCROLL_BAR (bar->next)->prev = bar->prev; + + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (! NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + } } /* Remove all scroll bars on FRAME that haven't been saved since the @@ -5450,7 +6153,9 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, if (! WINDOWP (bar->window)) emacs_abort (); - emacs_event->kind = SCROLL_BAR_CLICK_EVENT; + emacs_event->kind = (bar->horizontal + ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT + : SCROLL_BAR_CLICK_EVENT); emacs_event->code = event->xbutton.button - Button1; emacs_event->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO @@ -5462,36 +6167,68 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, emacs_event->frame_or_window = bar->window; emacs_event->arg = Qnil; emacs_event->timestamp = event->xbutton.time; - { - int top_range - = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); - int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER; + if (bar->horizontal) + { + int left_range + = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width); + int x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER; - if (y < 0) y = 0; - if (y > top_range) y = top_range; + if (x < 0) x = 0; + if (x > left_range) x = left_range; - if (y < bar->start) - emacs_event->part = scroll_bar_above_handle; - else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE) - emacs_event->part = scroll_bar_handle; - else - emacs_event->part = scroll_bar_below_handle; + if (x < bar->start) + emacs_event->part = scroll_bar_before_handle; + else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE) + emacs_event->part = scroll_bar_horizontal_handle; + else + emacs_event->part = scroll_bar_after_handle; #ifndef USE_TOOLKIT_SCROLL_BARS - /* If the user has released the handle, set it to its final position. */ - if (event->type == ButtonRelease && bar->dragging != -1) - { - int new_start = y - bar->dragging; - int new_end = new_start + bar->end - bar->start; + /* If the user has released the handle, set it to its final position. */ + if (event->type == ButtonRelease && bar->dragging != -1) + { + int new_start = - bar->dragging; + int new_end = new_start + bar->end - bar->start; - x_scroll_bar_set_handle (bar, new_start, new_end, 0); - bar->dragging = -1; - } + x_scroll_bar_set_handle (bar, new_start, new_end, 0); + bar->dragging = -1; + } #endif - XSETINT (emacs_event->x, y); - XSETINT (emacs_event->y, top_range); - } + XSETINT (emacs_event->x, left_range); + XSETINT (emacs_event->y, x); + } + else + { + int top_range + = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); + int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER; + + if (y < 0) y = 0; + if (y > top_range) y = top_range; + + if (y < bar->start) + emacs_event->part = scroll_bar_above_handle; + else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE) + emacs_event->part = scroll_bar_handle; + else + emacs_event->part = scroll_bar_below_handle; + +#ifndef USE_TOOLKIT_SCROLL_BARS + /* If the user has released the handle, set it to its final position. */ + if (event->type == ButtonRelease && bar->dragging != -1) + { + int new_start = y - bar->dragging; + int new_end = new_start + bar->end - bar->start; + + x_scroll_bar_set_handle (bar, new_start, new_end, 0); + bar->dragging = -1; + } +#endif + + XSETINT (emacs_event->x, y); + XSETINT (emacs_event->y, top_range); + } } #ifndef USE_TOOLKIT_SCROLL_BARS @@ -5598,6 +6335,75 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, } +/* Return information to the user about the current position of the mouse + on the scroll bar. */ + +static void +x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, + enum scroll_bar_part *part, Lisp_Object *x, + Lisp_Object *y, Time *timestamp) +{ + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); + struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar; + Window w = bar->x_window; + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + int win_x, win_y; + Window dummy_window; + int dummy_coord; + unsigned int dummy_mask; + + block_input (); + + /* Get the mouse's position relative to the scroll bar window, and + report that. */ + if (XQueryPointer (FRAME_X_DISPLAY (f), w, + + /* Root, child, root x and root y. */ + &dummy_window, &dummy_window, + &dummy_coord, &dummy_coord, + + /* Position relative to scroll bar. */ + &win_x, &win_y, + + /* Mouse buttons and modifier keys. */ + &dummy_mask)) + { + int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width); + + win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER; + + if (bar->dragging != -1) + win_x -= bar->dragging; + + if (win_x < 0) + win_x = 0; + if (win_x > left_range) + win_x = left_range; + + *fp = f; + *bar_window = bar->window; + + if (bar->dragging != -1) + *part = scroll_bar_horizontal_handle; + else if (win_x < bar->start) + *part = scroll_bar_before_handle; + else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE) + *part = scroll_bar_handle; + else + *part = scroll_bar_after_handle; + + XSETINT (*y, win_x); + XSETINT (*x, left_range); + + f->mouse_moved = 0; + dpyinfo->last_mouse_scroll_bar = NULL; + *timestamp = dpyinfo->last_mouse_movement_time; + } + + unblock_input (); +} + + /* The screen has been cleared so we may have changed foreground or background colors, and the scroll bars may need to be redrawn. Clear out the scroll bars, and ask for expose events, so we can @@ -5630,7 +6436,7 @@ static int temp_index; static short temp_buffer[100]; #define STORE_KEYSYM_FOR_DEBUG(keysym) \ - if (temp_index == sizeof temp_buffer / sizeof (short)) \ + if (temp_index == ARRAYELTS (temp_buffer)) \ temp_index = 0; \ temp_buffer[temp_index++] = (keysym) @@ -5740,6 +6546,35 @@ static void xembed_send_message (struct frame *f, Time, enum xembed_message, long detail, long data1, long data2); +static void +x_net_wm_state (struct frame *f, Window window) +{ + int value = FULLSCREEN_NONE; + Lisp_Object lval = Qnil; + int sticky = 0; + + (void)get_current_wm_state (f, window, &value, &sticky); + + switch (value) + { + case FULLSCREEN_WIDTH: + lval = Qfullwidth; + break; + case FULLSCREEN_HEIGHT: + lval = Qfullheight; + break; + case FULLSCREEN_BOTH: + lval = Qfullboth; + break; + case FULLSCREEN_MAXIMIZED: + lval = Qmaximized; + break; + } + + store_frame_param (f, Qfullscreen, lval); +/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/ +} + /* Handles the XEvent EVENT on display DPYINFO. *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. @@ -5937,6 +6772,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, *finish = X_EVENT_GOTO_OUT; goto done; } + else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar) + { + x_horizontal_scroll_bar_to_input_event (event, &inev.ie); + *finish = X_EVENT_GOTO_OUT; + goto done; + } #endif /* USE_TOOLKIT_SCROLL_BARS */ /* XEmbed messages from the embedder (if any). */ @@ -5961,7 +6802,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, break; case SelectionNotify: - dpyinfo->last_user_time = event->xselection.time; + x_display_set_last_user_time (dpyinfo, event->xselection.time); #ifdef USE_X_TOOLKIT if (! x_window_to_frame (dpyinfo, event->xselection.requestor)) goto OTHER; @@ -5970,7 +6811,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, break; case SelectionClear: /* Someone has grabbed ownership. */ - dpyinfo->last_user_time = event->xselectionclear.time; + x_display_set_last_user_time (dpyinfo, event->xselectionclear.time); #ifdef USE_X_TOOLKIT if (! x_window_to_frame (dpyinfo, event->xselectionclear.window)) goto OTHER; @@ -5979,14 +6820,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, const XSelectionClearEvent *eventp = &event->xselectionclear; inev.ie.kind = SELECTION_CLEAR_EVENT; - SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; + SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; SELECTION_EVENT_TIME (&inev.sie) = eventp->time; } break; case SelectionRequest: /* Someone wants our selection. */ - dpyinfo->last_user_time = event->xselectionrequest.time; + x_display_set_last_user_time (dpyinfo, event->xselectionrequest.time); #ifdef USE_X_TOOLKIT if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner)) goto OTHER; @@ -5995,7 +6836,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, const XSelectionRequestEvent *eventp = &event->xselectionrequest; inev.ie.kind = SELECTION_REQUEST_EVENT; - SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; + SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor; SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; SELECTION_EVENT_TARGET (&inev.sie) = eventp->target; @@ -6005,23 +6846,30 @@ handle_one_xevent (struct x_display_info *dpyinfo, break; case PropertyNotify: - dpyinfo->last_user_time = event->xproperty.time; + x_display_set_last_user_time (dpyinfo, event->xproperty.time); f = x_top_window_to_frame (dpyinfo, event->xproperty.window); if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state) - if (x_handle_net_wm_state (f, &event->xproperty) - && FRAME_ICONIFIED_P (f) - && f->output_data.x->net_wm_state_hidden_seen) - { - /* Gnome shell does not iconify us when C-z is pressed. - It hides the frame. So if our state says we aren't - hidden anymore, treat it as deiconified. */ - SET_FRAME_VISIBLE (f, 1); - SET_FRAME_ICONIFIED (f, 0); - f->output_data.x->has_been_visible = 1; - f->output_data.x->net_wm_state_hidden_seen = 0; - inev.ie.kind = DEICONIFY_EVENT; - XSETFRAME (inev.ie.frame_or_window, f); - } + { + int not_hidden = x_handle_net_wm_state (f, &event->xproperty); + if (not_hidden && FRAME_ICONIFIED_P (f)) + { + /* Gnome shell does not iconify us when C-z is pressed. + It hides the frame. So if our state says we aren't + hidden anymore, treat it as deiconified. */ + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, 0); + f->output_data.x->has_been_visible = 1; + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + else if (! not_hidden && ! FRAME_ICONIFIED_P (f)) + { + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 1); + inev.ie.kind = ICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + } x_handle_property_notify (&event->xproperty); xft_settings_event (dpyinfo, event); @@ -6088,7 +6936,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; #else /* not USE_TOOLKIT_SCROLL_BARS */ bar = x_window_to_scroll_bar (event->xexpose.display, - event->xexpose.window); + event->xexpose.window, 2); if (bar) x_scroll_bar_expose (bar, event); @@ -6193,7 +7041,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case KeyPress: - dpyinfo->last_user_time = event->xkey.time; + x_display_set_last_user_time (dpyinfo, event->xkey.time); ignore_next_mouse_click_timeout = 0; #if defined (USE_X_TOOLKIT) || defined (USE_GTK) @@ -6460,7 +7308,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, for (i = 0, nchars = 0; i < nbytes; i++) { - if (ASCII_BYTE_P (copy_bufptr[i])) + if (ASCII_CHAR_P (copy_bufptr[i])) nchars++; STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); } @@ -6527,7 +7375,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif case KeyRelease: - dpyinfo->last_user_time = event->xkey.time; + x_display_set_last_user_time (dpyinfo, event->xkey.time); #ifdef HAVE_X_I18N /* Don't dispatch this event since XtDispatchEvent calls XFilterEvent, and two calls in a row may freeze the @@ -6538,7 +7386,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif case EnterNotify: - dpyinfo->last_user_time = event->xcrossing.time; + x_display_set_last_user_time (dpyinfo, event->xcrossing.time); x_detect_focus_change (dpyinfo, any, event, &inev.ie); f = any; @@ -6563,7 +7411,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; case LeaveNotify: - dpyinfo->last_user_time = event->xcrossing.time; + x_display_set_last_user_time (dpyinfo, event->xcrossing.time); x_detect_focus_change (dpyinfo, any, event, &inev.ie); f = x_top_window_to_frame (dpyinfo, event->xcrossing.window); @@ -6597,7 +7445,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case MotionNotify: { - dpyinfo->last_user_time = event->xmotion.time; + x_display_set_last_user_time (dpyinfo, event->xmotion.time); previous_help_echo_string = help_echo_string; help_echo_string = Qnil; @@ -6652,7 +7500,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #ifndef USE_TOOLKIT_SCROLL_BARS struct scroll_bar *bar = x_window_to_scroll_bar (event->xmotion.display, - event->xmotion.window); + event->xmotion.window, 2); if (bar) x_scroll_bar_note_movement (bar, &event->xmotion); @@ -6685,6 +7533,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif if (f) { + x_net_wm_state (f, event->xconfigure.window); + #ifndef USE_X_TOOLKIT #ifndef USE_GTK int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width); @@ -6707,9 +7557,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, SET_FRAME_GARBAGED (f); cancel_mouse_face (f); } - -/** FRAME_PIXEL_WIDTH (f) = event->xconfigure.width; **/ -/** FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height; **/ #endif /* not USE_GTK */ #endif @@ -6738,7 +7585,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, memset (&compose_status, 0, sizeof (compose_status)); dpyinfo->last_mouse_glyph_frame = NULL; - dpyinfo->last_user_time = event->xbutton.time; + x_display_set_last_user_time (dpyinfo, event->xbutton.time); f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame : x_window_to_frame (dpyinfo, event->xbutton.window)); @@ -6795,7 +7642,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { struct scroll_bar *bar = x_window_to_scroll_bar (event->xbutton.display, - event->xbutton.window); + event->xbutton.window, 2); #ifdef USE_TOOLKIT_SCROLL_BARS /* Make the "Ctrl-Mouse-2 splits window" work for toolkit @@ -6815,9 +7662,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, { dpyinfo->grabbed |= (1 << event->xbutton.button); dpyinfo->last_mouse_frame = f; - - if (!tool_bar_p) - last_tool_bar_item = -1; +#if ! defined (USE_GTK) + if (f && !tool_bar_p) + f->last_tool_bar_item = -1; +#endif /* not USE_GTK */ } else dpyinfo->grabbed &= ~(1 << event->xbutton.button); @@ -6846,7 +7694,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, && event->xbutton.x >= 0 && event->xbutton.x < FRAME_PIXEL_WIDTH (f) && event->xbutton.y >= 0 - && event->xbutton.y < f->output_data.x->menubar_height + && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f) && event->xbutton.same_screen) { if (!f->output_data.x->saved_menu_event) @@ -7114,7 +7962,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) /* Compute frame-relative coordinates for phys cursor. */ get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); - wd = w->phys_cursor_width; + wd = w->phys_cursor_width - 1; /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ @@ -7130,9 +7978,9 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) glyph, unless the cursor box is as wide as the glyph or wider (the latter happens when x-stretch-cursor is non-nil). */ if ((cursor_glyph->resolved_level & 1) != 0 - && cursor_glyph->pixel_width > w->phys_cursor_width) + && cursor_glyph->pixel_width > wd) { - x += cursor_glyph->pixel_width - w->phys_cursor_width; + x += cursor_glyph->pixel_width - wd; if (wd > 0) wd -= 1; } @@ -7235,12 +8083,12 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text &dummy_y, &dummy_h); if ((cursor_glyph->resolved_level & 1) != 0 - && cursor_glyph->pixel_width > w->phys_cursor_width) - x += cursor_glyph->pixel_width - w->phys_cursor_width; + && cursor_glyph->pixel_width > w->phys_cursor_width - 1) + x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; XFillRectangle (dpy, window, gc, x, WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + row->height - width), - w->phys_cursor_width, width); + w->phys_cursor_width - 1, width); } XSetClipMask (dpy, gc, None); @@ -7373,9 +8221,13 @@ x_bitmap_icon (struct frame *f, Lisp_Object file) #ifdef USE_GTK - if (xg_set_icon (f, xg_default_icon_file) - || xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) - return 0; + if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id == -2 + || xg_set_icon (f, xg_default_icon_file) + || xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + { + FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2; + return 0; + } #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) @@ -7789,10 +8641,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_COLUMN_WIDTH (f) = font->average_width; FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font); - FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); +#ifndef USE_X_TOOLKIT FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); - - compute_fringe_widths (f, 1); +#endif /* Compute character columns occupied by scrollbar. @@ -7868,11 +8719,6 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data) #endif /* HAVE_X11R6 */ -#ifdef HAVE_X11R6 -/* This isn't prototyped in OSF 5.0 or 5.1a. */ -extern char *XSetIMValues (XIM, ...); -#endif - /* Open the connection to the XIM server on display DPYINFO. RESOURCE_NAME is the resource name Emacs uses. */ @@ -8107,7 +8953,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_ x_calc_absolute_position (f); block_input (); - x_wm_set_size_hint (f, (long) 0, 0); + x_wm_set_size_hint (f, 0, 0); modified_left = f->left_pos; modified_top = f->top_pos; @@ -8316,7 +9162,6 @@ get_current_wm_state (struct frame *f, if (a == dpyinfo->Xatom_net_wm_state_hidden) { is_hidden = 1; - f->output_data.x->net_wm_state_hidden_seen = 1; } else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz) { @@ -8575,7 +9420,7 @@ x_sync_with_move (struct frame *f, int left, int top, int fuzzy) if (eabs (current_left - left) <= 10 && eabs (current_top - top) <= 40) return; - } + } else if (current_left == left && current_top == top) return; } @@ -8583,7 +9428,7 @@ x_sync_with_move (struct frame *f, int left, int top, int fuzzy) /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry will then return up-to-date position info. */ - wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0); + wait_reading_process_output (0, 500000000, 0, 0, Qnil, NULL, 0); } @@ -8628,7 +9473,7 @@ x_wait_for_event (struct frame *f, int eventtype) } -/* Change the size of frame F's X window to COLS/ROWS in the case F +/* Change the size of frame F's X window to WIDTH/HEIGHT in the case F doesn't have a widget. If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity for this size change and subsequent size changes. Otherwise we leave the window gravity unchanged. */ @@ -8638,23 +9483,17 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, { int pixelwidth, pixelheight; - check_frame_size (f, &width, &height, pixelwise); - - compute_fringe_widths (f, 0); - - pixelwidth = ((pixelwise - ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width) - : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width)) - + FRAME_TOOLBAR_WIDTH (f)); + pixelwidth = (pixelwise + ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width) + : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width)); pixelheight = ((pixelwise ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height) - : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)) - + FRAME_MENUBAR_HEIGHT (f) - + FRAME_TOOLBAR_HEIGHT (f)); + : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))); + if (change_gravity) f->win_gravity = NorthWestGravity; - x_wm_set_size_hint (f, (long) 0, 0); + x_wm_set_size_hint (f, 0, 0); XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - pixelwidth, pixelheight); + pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f)); /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to @@ -8684,7 +9523,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, x_wait_for_event (f, ConfigureNotify); else { - change_frame_size (f, width, height, 0, 1, 0, 1); + change_frame_size (f, pixelwidth, pixelheight, 0, 1, 0, 1); x_sync (f); } } @@ -8700,8 +9539,9 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b { block_input (); - check_frame_size (f, &width, &height, pixelwise); - + /* The following breaks our calculations. If it's really needed, + think of something else. */ +#if 0 if (NILP (tip_frame) || XFRAME (tip_frame) != f) { int text_width, text_height; @@ -8724,6 +9564,7 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b change_frame_size (f, text_width, text_height, 0, 1, 0, 1); } +#endif #ifdef USE_GTK if (FRAME_GTK_WIDGET (f)) @@ -8737,9 +9578,7 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b #else /* not USE_GTK */ x_set_window_size_1 (f, change_gravity, width, height, pixelwise); -#if !defined USE_X_TOOLKIT x_clear_under_internal_border (f); -#endif #endif /* not USE_GTK */ @@ -8753,35 +9592,14 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b cancel_mouse_face (f); unblock_input (); -} - -/* Mouse warping. */ - -void -x_set_mouse_position (struct frame *f, int x, int y) -{ - int pix_x, pix_y; - - pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; - pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; - - if (pix_x < 0) pix_x = 0; - if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); - - if (pix_y < 0) pix_y = 0; - if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); - - block_input (); - XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f), - 0, 0, 0, 0, pix_x, pix_y); - unblock_input (); + do_pending_window_change (0); } /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */ void -x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) { block_input (); @@ -9082,7 +9900,7 @@ x_make_frame_invisible (struct frame *f) program-specified, so that when the window is mapped again, it will be placed at the same location, without forcing the user to position it by hand again (they have already done that once for this window.) */ - x_wm_set_size_hint (f, (long) 0, 1); + x_wm_set_size_hint (f, 0, 1); #ifdef USE_GTK if (FRAME_GTK_OUTER_WIDGET (f)) @@ -9252,6 +10070,11 @@ x_free_frame_resources (struct frame *f) commands to the X server. */ if (dpyinfo->display) { + /* Always exit with visible pointer to avoid weird issue + with Xfixes (Bug#17609). */ + if (f->pointer_invisible) + FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, 0); + /* We must free faces before destroying windows because some font-driver (e.g. xft) access a window while finishing a face. */ @@ -9289,6 +10112,9 @@ x_free_frame_resources (struct frame *f) XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); free_frame_menubar (f); + + if (f->shell_position) + xfree (f->shell_position); #else /* !USE_X_TOOLKIT */ #ifdef USE_GTK @@ -9310,13 +10136,13 @@ x_free_frame_resources (struct frame *f) unload_color (f, f->output_data.x->scroll_bar_background_pixel); if (f->output_data.x->scroll_bar_foreground_pixel != -1) unload_color (f, f->output_data.x->scroll_bar_foreground_pixel); -#ifdef USE_TOOLKIT_SCROLL_BARS +#if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS) /* Scrollbar shadow colors. */ if (f->output_data.x->scroll_bar_top_shadow_pixel != -1) unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel); if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1) unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel); -#endif /* USE_TOOLKIT_SCROLL_BARS */ +#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */ if (f->output_data.x->white_relief.pixel != -1) unload_color (f, f->output_data.x->white_relief.pixel); if (f->output_data.x->black_relief.pixel != -1) @@ -9404,6 +10230,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) XSizeHints size_hints; Window window = FRAME_OUTER_WINDOW (f); + if (!window) + return; + #ifdef USE_X_TOOLKIT if (f->output_data.x->widget) { @@ -9437,8 +10266,6 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); - check_frame_size (f, &min_cols, &min_rows, 0); - if (frame_resize_pixelwise) /* Needed to prevent a bad protocol error crash when making the frame size very small. */ @@ -9735,6 +10562,96 @@ my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, } #endif +/* Create invisible cursor on X display referred by DPYINFO. */ + +static Cursor +make_invisible_cursor (struct x_display_info *dpyinfo) +{ + Display *dpy = dpyinfo->display; + static char const no_data[] = { 0 }; + Pixmap pix; + XColor col; + Cursor c = 0; + + x_catch_errors (dpy); + pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1); + if (! x_had_errors_p (dpy) && pix != None) + { + Cursor pixc; + col.pixel = 0; + col.red = col.green = col.blue = 0; + col.flags = DoRed | DoGreen | DoBlue; + pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0); + if (! x_had_errors_p (dpy) && pixc != None) + c = pixc; + XFreePixmap (dpy, pix); + } + + x_uncatch_errors (); + + return c; +} + +/* True if DPY supports Xfixes extension >= 4. */ + +static bool +x_probe_xfixes_extension (Display *dpy) +{ +#ifdef HAVE_XFIXES + int major, minor; + return XFixesQueryVersion (dpy, &major, &minor) && major >= 4; +#else + return false; +#endif /* HAVE_XFIXES */ +} + +/* Toggle mouse pointer visibility on frame F by using Xfixes functions. */ + +static void +xfixes_toggle_visible_pointer (struct frame *f, bool invisible) +{ +#ifdef HAVE_XFIXES + if (invisible) + XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + else + XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + f->pointer_invisible = invisible; +#else + emacs_abort (); +#endif /* HAVE_XFIXES */ +} + +/* Toggle mouse pointer visibility on frame F by using invisible cursor. */ + +static void +x_toggle_visible_pointer (struct frame *f, bool invisible) +{ + eassert (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0); + if (invisible) + XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->invisible_cursor); + else + XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + f->output_data.x->current_cursor); + f->pointer_invisible = invisible; +} + +/* Setup pointer blanking, prefer Xfixes if available. */ + +static void +x_setup_pointer_blanking (struct x_display_info *dpyinfo) +{ + /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting + X server bug, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */ + if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo->display)) + dpyinfo->toggle_visible_pointer = xfixes_toggle_visible_pointer; + else + { + dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer; + dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); + } +} + /* Current X display connection identifier. Incremented for each next connection established. */ static unsigned x_display_id; @@ -9746,7 +10663,6 @@ static unsigned x_display_id; struct x_display_info * x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) { - int connection; Display *dpy; struct terminal *terminal; struct x_display_info *dpyinfo; @@ -9798,10 +10714,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) XSetLocaleModifiers (""); - /* Emacs can only handle core input events, so make sure - Gtk doesn't use Xinput or Xinput2 extensions. */ - xputenv ("GDK_CORE_DEVICE_EVENTS=1"); - /* Work around GLib bug that outputs a faulty warning. See https://bugzilla.gnome.org/show_bug.cgi?id=563627. */ id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL @@ -9960,8 +10872,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->x_id = ++x_display_id; dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name) + SBYTES (Vsystem_name) + 2); - strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"), - SSDATA (Vsystem_name)); + char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name); + *nametail++ = '@'; + lispstpcpy (nametail, Vsystem_name); /* Figure out which modifier bits mean what. */ x_find_modifier_meanings (dpyinfo); @@ -9975,6 +10888,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->vertical_scroll_bar_cursor = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow); + dpyinfo->horizontal_scroll_bar_cursor + = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow); + xrdb = x_load_resources (dpyinfo->display, xrm_option, resource_name, EMACS_CLASS); #ifdef HAVE_XRMSETDATABASE @@ -10012,11 +10928,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) { if (dpyinfo->visual->class == PseudoColor) { - Lisp_Object value; - value = display_x_get_resource (dpyinfo, - build_string ("privateColormap"), - build_string ("PrivateColormap"), - Qnil, Qnil); + AUTO_STRING (privateColormap, "privateColormap"); + AUTO_STRING (PrivateColormap, "PrivateColormap"); + Lisp_Object value + = display_x_get_resource (dpyinfo, privateColormap, + PrivateColormap, Qnil, Qnil); if (STRINGP (value) && (!strcmp (SSDATA (value), "true") || !strcmp (SSDATA (value), "on"))) @@ -10029,14 +10945,27 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #ifdef HAVE_XFT { - /* If we are using Xft, check dpi value in X resources. - It is better we use it as well, since Xft will use it, as will all - Gnome applications. If our real DPI is smaller or larger than the - one Xft uses, our font will look smaller or larger than other - for other applications, even if it is the same font name (monospace-10 - for example). */ - char *v = XGetDefault (dpyinfo->display, "Xft", "dpi"); + /* If we are using Xft, the following precautions should be made: + + 1. Make sure that the Xrender extension is added before the Xft one. + Otherwise, the close-display hook set by Xft is called after the one + for Xrender, and the former tries to re-add the latter. This results + in inconsistency of internal states and leads to X protocol error when + one reconnects to the same X server (Bug#1696). + + 2. Check dpi value in X resources. It is better we use it as well, + since Xft will use it, as will all Gnome applications. If our real DPI + is smaller or larger than the one Xft uses, our font will look smaller + or larger than other for other applications, even if it is the same + font name (monospace-10 for example). */ + + int event_base, error_base; + char *v; double d; + + XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); + + v = XGetDefault (dpyinfo->display, "Xft", "dpi"); if (v != NULL && sscanf (v, "%lf", &d) == 1) dpyinfo->resy = dpyinfo->resx = d; } @@ -10097,6 +11026,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) ATOM_REFS_INIT ("DONE", Xatom_DONE) ATOM_REFS_INIT ("PAGE", Xatom_PAGE) ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar) + ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar) ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED) /* EWMH */ ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state) @@ -10126,11 +11056,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) }; int i; - const int atom_count = sizeof (atom_refs) / sizeof (atom_refs[0]); - /* 1 for _XSETTINGS_SN */ - const int total_atom_count = 1 + atom_count; - Atom *atoms_return = xmalloc (total_atom_count * sizeof *atoms_return); - char **atom_names = xmalloc (total_atom_count * sizeof *atom_names); + enum { atom_count = ARRAYELTS (atom_refs) }; + /* 1 for _XSETTINGS_SN. */ + enum { total_atom_count = 1 + atom_count }; + Atom atoms_return[total_atom_count]; + char *atom_names[total_atom_count]; static char const xsettings_fmt[] = "_XSETTINGS_S%d"; char xsettings_atom_name[sizeof xsettings_fmt - 2 + INT_STRLEN_BOUND (int)]; @@ -10138,7 +11068,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) for (i = 0; i < atom_count; i++) atom_names[i] = (char *) atom_refs[i].name; - /* Build _XSETTINGS_SN atom name */ + /* Build _XSETTINGS_SN atom name. */ sprintf (xsettings_atom_name, xsettings_fmt, XScreenNumberOfScreen (dpyinfo->screen)); atom_names[i] = xsettings_atom_name; @@ -10149,11 +11079,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) for (i = 0; i < atom_count; i++) *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i]; - /* Manual copy of last atom */ + /* Manually copy last atom. */ dpyinfo->Xatom_xsettings_sel = atoms_return[i]; - - xfree (atom_names); - xfree (atoms_return); } dpyinfo->x_dnd_atoms_size = 8; @@ -10164,24 +11091,24 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) gray_bits, gray_width, gray_height, 1, 0, 1); + x_setup_pointer_blanking (dpyinfo); + #ifdef HAVE_X_I18N xim_initialize (dpyinfo, resource_name); #endif xsettings_initialize (dpyinfo); - connection = ConnectionNumber (dpyinfo->display); - /* This is only needed for distinguishing keyboard and process input. */ - if (connection != 0) - add_keyboard_wait_descriptor (connection); + if (dpyinfo->connection != 0) + add_keyboard_wait_descriptor (dpyinfo->connection); #ifdef F_SETOWN - fcntl (connection, F_SETOWN, getpid ()); + fcntl (dpyinfo->connection, F_SETOWN, getpid ()); #endif /* ! defined (F_SETOWN) */ if (interrupt_input) - init_sigio (connection); + init_sigio (dpyinfo->connection); #ifdef USE_LUCID { @@ -10200,6 +11127,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) emacs_abort (); if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); + /* Do not free XFontStruct returned by the above call to XQueryFont. + This leads to X protocol errors at XtCloseDisplay (Bug#18403). */ x_uncatch_errors (); } #endif @@ -10207,11 +11136,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) /* See if we should run in synchronous mode. This is useful for debugging X code. */ { - Lisp_Object value; - value = display_x_get_resource (dpyinfo, - build_string ("synchronous"), - build_string ("Synchronous"), - Qnil, Qnil); + AUTO_STRING (synchronous, "synchronous"); + AUTO_STRING (Synchronous, "Synchronous"); + Lisp_Object value = display_x_get_resource (dpyinfo, synchronous, + Synchronous, Qnil, Qnil); if (STRINGP (value) && (!strcmp (SSDATA (value), "true") || !strcmp (SSDATA (value), "on"))) @@ -10219,11 +11147,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } { - Lisp_Object value; - value = display_x_get_resource (dpyinfo, - build_string ("useXIM"), - build_string ("UseXIM"), - Qnil, Qnil); + AUTO_STRING (useXIM, "useXIM"); + AUTO_STRING (UseXIM, "UseXIM"); + Lisp_Object value = display_x_get_resource (dpyinfo, useXIM, UseXIM, + Qnil, Qnil); #ifdef USE_XIM if (STRINGP (value) && (!strcmp (SSDATA (value), "false") @@ -10240,8 +11167,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #ifdef HAVE_X_SM /* Only do this for the very first display in the Emacs session. Ignore X session management when Emacs was first started on a - tty. */ - if (terminal->id == 1) + tty or started as a daemon. */ + if (terminal->id == 1 && ! IS_DAEMON) x_session_initialize (dpyinfo); #endif @@ -10365,7 +11292,9 @@ static struct redisplay_interface x_redisplay_interface = x_draw_window_cursor, x_draw_vertical_window_border, x_draw_window_divider, - x_shift_glyphs_for_insert + x_shift_glyphs_for_insert, + x_show_hourglass, + x_hide_hourglass }; @@ -10430,15 +11359,17 @@ x_delete_terminal (struct terminal *terminal) XCloseDisplay (dpyinfo->display); #endif #endif /* ! USE_GTK */ - } - /* No more input on this descriptor. */ - if (0 <= dpyinfo->connection) - delete_keyboard_wait_descriptor (dpyinfo->connection); + /* No more input on this descriptor. Do not close it because + it's already closed by X(t)CloseDisplay (Bug#18403). */ + eassert (0 <= dpyinfo->connection); + delete_keyboard_wait_descriptor (dpyinfo->connection); + + /* Mark as dead. */ + dpyinfo->display = NULL; + dpyinfo->connection = -1; + } - /* Mark as dead. */ - dpyinfo->display = NULL; - dpyinfo->connection = -1; x_delete_display (dpyinfo); unblock_input (); } @@ -10451,9 +11382,8 @@ x_create_terminal (struct x_display_info *dpyinfo) { struct terminal *terminal; - terminal = create_terminal (); + terminal = create_terminal (output_x_window, &x_redisplay_interface); - terminal->type = output_x_window; terminal->display_info.x = dpyinfo; dpyinfo->terminal = terminal; @@ -10464,37 +11394,36 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->delete_glyphs_hook = x_delete_glyphs; terminal->ring_bell_hook = XTring_bell; terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer; - terminal->reset_terminal_modes_hook = NULL; - terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = x_update_begin; terminal->update_end_hook = x_update_end; - terminal->set_terminal_window_hook = NULL; terminal->read_socket_hook = XTread_socket; terminal->frame_up_to_date_hook = XTframe_up_to_date; terminal->mouse_position_hook = XTmouse_position; terminal->frame_rehighlight_hook = XTframe_rehighlight; terminal->frame_raise_lower_hook = XTframe_raise_lower; terminal->fullscreen_hook = XTfullscreen_hook; + terminal->menu_show_hook = x_menu_show; +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) + terminal->popup_dialog_hook = xw_popup_dialog; +#endif terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; + terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar; terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars; terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar; terminal->judge_scroll_bars_hook = XTjudge_scroll_bars; - terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = x_delete_terminal; - - terminal->rif = &x_redisplay_interface; + /* Other hooks are NULL by default. */ return terminal; } -void +static void x_initialize (void) { baud_rate = 19200; x_noop_count = 0; - last_tool_bar_item = -1; any_help_event_p = 0; ignore_next_mouse_click_timeout = 0; @@ -10534,6 +11463,15 @@ x_initialize (void) XSetIOErrorHandler (x_io_error_quitter); } +#ifdef USE_GTK +void +init_xterm (void) +{ + /* Emacs can handle only core input events, so make sure + Gtk doesn't use Xinput or Xinput2 extensions. */ + xputenv ("GDK_CORE_DEVICE_EVENTS=1"); +} +#endif void syms_of_xterm (void) diff --git a/src/xterm.h b/src/xterm.h index 2bed0d1d5d1..23dd43678d6 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -47,7 +47,6 @@ typedef Widget xt_or_gtk_widget; /* Some definitions to reduce conditionals. */ typedef GtkWidget *xt_or_gtk_widget; -#define XtParent(x) (gtk_widget_get_parent (x)) #undef XSync #define XSync(d, b) do { gdk_window_process_all_updates (); \ XSync (d, b); } while (false) @@ -78,6 +77,8 @@ typedef GtkWidget *xt_or_gtk_widget; #include "dispextern.h" #include "termhooks.h" +INLINE_HEADER_BEGIN + /* Black and white pixel values for the screen which frame F is on. */ #define BLACK_PIX_DEFAULT(f) \ BlackPixel (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f)) @@ -177,9 +178,16 @@ struct x_display_info /* The cursor to use for vertical scroll bars. */ Cursor vertical_scroll_bar_cursor; - /* The invisible cursor used for pointer blanking. */ + /* The cursor to use for horizontal scroll bars. */ + Cursor horizontal_scroll_bar_cursor; + + /* The invisible cursor used for pointer blanking. + Unused if this display supports Xfixes extension. */ Cursor invisible_cursor; + /* Function used to toggle pointer visibility on this display. */ + void (*toggle_visible_pointer) (struct frame *, bool); + #ifdef USE_GTK /* The GDK cursor for scroll bars and popup menus. */ GdkCursor *xg_cursor; @@ -277,8 +285,8 @@ struct x_display_info /* More atoms for Ghostscript support. */ Atom Xatom_DONE, Xatom_PAGE; - /* Atom used in toolkit scroll bar client messages. */ - Atom Xatom_Scrollbar; + /* Atoms used in toolkit scroll bar client messages. */ + Atom Xatom_Scrollbar, Xatom_Horizontal_Scrollbar; /* Atom used in XEmbed client messages. */ Atom Xatom_XEMBED, Xatom_XEMBED_INFO; @@ -426,11 +434,11 @@ extern void select_visual (struct x_display_info *); struct x_output { - /* Height of menu bar widget, in pixels. - Zero if not using the X toolkit. - When using the toolkit, this value is not meaningful - if the menubar is turned off. */ +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) + /* Height of menu bar widget, in pixels. This value + is not meaningful if the menubar is turned off. */ int menubar_height; +#endif /* Height of tool bar widget, in pixels. top_height is used if tool bar at top, bottom_height if tool bar is at the bottom. @@ -491,10 +499,6 @@ struct x_output GtkWidget *menubar_widget; /* The tool bar in this frame */ GtkWidget *toolbar_widget; -#ifdef HAVE_GTK_HANDLE_BOX_NEW -/* The handle box that makes the tool bar detachable. */ - GtkWidget *handlebox_widget; -#endif /* True if tool bar is packed into the hbox widget (i.e. vertical). */ bool_bf toolbar_in_hbox : 1; bool_bf toolbar_is_packed : 1; @@ -539,10 +543,12 @@ struct x_output bars). */ unsigned long scroll_bar_background_pixel; - /* Top and bottom shadow colors for 3d toolkit scrollbars. -1 means - let the scroll compute them itself. */ +#if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS) + /* Top and bottom shadow colors for 3D Lucid scrollbars. + -1 means let the scroll compute them itself. */ unsigned long scroll_bar_top_shadow_pixel; unsigned long scroll_bar_bottom_shadow_pixel; +#endif /* Descriptor for the cursor in use for this window. */ Cursor text_cursor; @@ -603,9 +609,6 @@ struct x_output false, tell Xt not to wait. */ bool_bf wait_for_wm : 1; - /* True if _NET_WM_STATE_HIDDEN is set for this frame. */ - bool_bf net_wm_state_hidden_seen : 1; - #ifdef HAVE_X_I18N /* Input context (currently, this means Compose key handler setup). */ XIC xic; @@ -644,6 +647,13 @@ struct x_output int move_offset_left; }; +/* Extreme 'short' and 'long' values suitable for libX11. */ +#define X_SHRT_MAX 0x7fff +#define X_SHRT_MIN (-1 - X_SHRT_MAX) +#define X_LONG_MAX 0x7fffffff +#define X_LONG_MIN (-1 - X_LONG_MAX) +#define X_ULONG_MAX 0xffffffffUL + #define No_Cursor (None) enum @@ -712,10 +722,14 @@ enum #endif /* !USE_GTK */ #endif +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) +#define FRAME_MENUBAR_HEIGHT(f) ((f)->output_data.x->menubar_height) +#else +#define FRAME_MENUBAR_HEIGHT(f) ((void) f, 0) +#endif /* USE_X_TOOLKIT || USE_GTK */ #define FRAME_FONT(f) ((f)->output_data.x->font) #define FRAME_FONTSET(f) ((f)->output_data.x->fontset) -#define FRAME_MENUBAR_HEIGHT(f) ((f)->output_data.x->menubar_height) #define FRAME_TOOLBAR_TOP_HEIGHT(f) ((f)->output_data.x->toolbar_top_height) #define FRAME_TOOLBAR_BOTTOM_HEIGHT(f) \ ((f)->output_data.x->toolbar_bottom_height) @@ -814,6 +828,14 @@ struct scroll_bar /* Last scroll bar part seen in xaw_jump_callback and xaw_scroll_callback. */ enum scroll_bar_part last_seen_part; #endif + +#if defined (USE_TOOLKIT_SCROLL_BARS) && !defined (USE_GTK) + /* Last value of whole for horizontal scrollbars. */ + int whole; +#endif + + /* 1 if the scroll bar is horizontal. */ + bool horizontal; }; /* Turning a lisp vector value into a pointer to a struct scroll_bar. */ @@ -860,6 +882,28 @@ struct scroll_bar #define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f, height) \ ((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER) +/* Return the inside height of a horizontal scroll bar, given the outside + height. */ +#define HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT(f, height) \ + ((height) \ + - HORIZONTAL_SCROLL_BAR_TOP_BORDER \ + - HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER) + +/* Return the length of the rectangle within which the left part of the + handle must stay. This isn't equivalent to the inside width, because + the scroll bar handle has a minimum width. + + This is the real range of motion for the scroll bar, so when we're + scaling buffer positions to scroll bar positions, we use this, not + HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH. */ +#define HORIZONTAL_SCROLL_BAR_LEFT_RANGE(f, width) \ + (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH (f, width) - HORIZONTAL_SCROLL_BAR_MIN_HANDLE) + +/* Return the inside width of horizontal scroll bar, given the outside + width. See HORIZONTAL_SCROLL_BAR_LEFT_RANGE too. */ +#define HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH(f, width) \ + ((width) - HORIZONTAL_SCROLL_BAR_LEFT_BORDER - HORIZONTAL_SCROLL_BAR_LEFT_BORDER) + /* Border widths for scroll bars. @@ -877,8 +921,14 @@ struct scroll_bar #define VERTICAL_SCROLL_BAR_TOP_BORDER (2) #define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (2) +#define HORIZONTAL_SCROLL_BAR_LEFT_BORDER (2) +#define HORIZONTAL_SCROLL_BAR_RIGHT_BORDER (2) +#define HORIZONTAL_SCROLL_BAR_TOP_BORDER (2) +#define HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER (2) + /* Minimum lengths for scroll bar handles, in pixels. */ #define VERTICAL_SCROLL_BAR_MIN_HANDLE (5) +#define HORIZONTAL_SCROLL_BAR_MIN_HANDLE (5) /* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT or SELECTION_CLEAR_EVENT, then its contents are really described @@ -890,15 +940,21 @@ struct scroll_bar struct selection_input_event { int kind; - Display *display; + struct x_display_info *dpyinfo; /* We spell it with an "o" here because X does. */ Window requestor; Atom selection, target, property; Time time; }; -#define SELECTION_EVENT_DISPLAY(eventp) \ - (((struct selection_input_event *) (eventp))->display) +/* Unlike macros below, this can't be used as an lvalue. */ +INLINE Display * +SELECTION_EVENT_DISPLAY (struct input_event *ev) +{ + return ((struct selection_input_event *) ev)->dpyinfo->display; +} +#define SELECTION_EVENT_DPYINFO(eventp) \ + (((struct selection_input_event *) (eventp))->dpyinfo) /* We spell it with an "o" here because X does. */ #define SELECTION_EVENT_REQUESTOR(eventp) \ (((struct selection_input_event *) (eventp))->requestor) @@ -914,6 +970,7 @@ struct selection_input_event /* From xfns.c. */ extern void x_free_gcs (struct frame *); +extern void x_relative_mouse_position (struct frame *, int *, int *); /* From xrdb.c. */ @@ -929,9 +986,6 @@ extern void x_check_errors (Display *, const char *) extern bool x_had_errors_p (Display *); extern void x_uncatch_errors (void); extern void x_clear_errors (Display *); -extern void x_set_window_size (struct frame *, int, int, int, bool); -extern void x_set_mouse_position (struct frame *, int, int); -extern void x_set_mouse_pixel_position (struct frame *, int, int); extern void xembed_request_focus (struct frame *); extern void x_ewmh_activate_frame (struct frame *); extern void x_delete_terminal (struct terminal *terminal); @@ -946,7 +1000,6 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap, double, int); #endif extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); -extern void x_query_color (struct frame *f, XColor *); extern void x_clear_area (Display *, Window, int, int, int, int); #if !defined USE_X_TOOLKIT && !defined USE_GTK extern void x_mouse_leave (struct x_display_info *); @@ -956,11 +1009,31 @@ extern void x_mouse_leave (struct x_display_info *); extern int x_dispatch_event (XEvent *, Display *); #endif extern int x_x_to_emacs_modifiers (struct x_display_info *, int); -extern int x_display_pixel_height (struct x_display_info *); -extern int x_display_pixel_width (struct x_display_info *); + +INLINE int +x_display_pixel_height (struct x_display_info *dpyinfo) +{ + return HeightOfScreen (dpyinfo->screen); +} + +INLINE int +x_display_pixel_width (struct x_display_info *dpyinfo) +{ + return WidthOfScreen (dpyinfo->screen); +} + +INLINE void +x_display_set_last_user_time (struct x_display_info *dpyinfo, Time t) +{ +#ifdef ENABLE_CHECKING + eassert (t <= X_ULONG_MAX); +#endif + dpyinfo->last_user_time = t; +} extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); extern void x_wait_for_event (struct frame *, int); +extern void x_clear_under_internal_border (struct frame *f); /* Defined in xselect.c. */ @@ -993,16 +1066,11 @@ extern Lisp_Object x_property_data_to_lisp (struct frame *, extern void x_clipboard_manager_save_frame (Lisp_Object); extern void x_clipboard_manager_save_all (void); -/* Defined in xfns.c */ - -extern Lisp_Object x_get_focus_frame (struct frame *); - #ifdef USE_GTK extern int xg_set_icon (struct frame *, Lisp_Object); -extern int xg_set_icon_from_xpm_data (struct frame *, const char**); +extern int xg_set_icon_from_xpm_data (struct frame *, const char **); #endif /* USE_GTK */ -extern void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); extern void xic_free_xfontset (struct frame *); extern void create_frame_xic (struct frame *); extern void destroy_frame_xic (struct frame *); @@ -1033,18 +1101,9 @@ extern Lisp_Object xw_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); #if defined USE_GTK || defined USE_MOTIF extern void x_menu_set_in_use (int); #endif -#ifdef USE_MOTIF extern void x_menu_wait_for_event (void *data); -#endif -extern int popup_activated (void); extern void initialize_frame_menubar (struct frame *); -/* Defined in widget.c */ - -#ifdef USE_X_TOOLKIT -extern void widget_store_internal_border (Widget); -#endif - /* Defined in xsmfns.c */ #ifdef HAVE_X_SM extern void x_session_initialize (struct x_display_info *dpyinfo); @@ -1056,10 +1115,6 @@ extern void x_session_close (void); extern Lisp_Object Qx_gtk_map_stock; -#if !defined USE_X_TOOLKIT && !defined USE_GTK -extern void x_clear_under_internal_border (struct frame *f); -#endif - /* Is the frame embedded into another application? */ #define FRAME_X_EMBEDDED_P(f) (FRAME_X_OUTPUT(f)->explicit_parent != 0) @@ -1079,4 +1134,6 @@ extern void x_clear_under_internal_border (struct frame *f); (nr).width = (rwidth), \ (nr).height = (rheight)) +INLINE_HEADER_END + #endif /* XTERM_H */ |