summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit53
-rw-r--r--src/ChangeLog6199
-rw-r--r--src/ChangeLog.102
-rw-r--r--src/ChangeLog.81266
-rw-r--r--src/Makefile.in228
-rw-r--r--src/alloc.c1663
-rw-r--r--src/atimer.c221
-rw-r--r--src/atimer.h3
-rw-r--r--src/bidi.c2037
-rw-r--r--src/buffer.c578
-rw-r--r--src/buffer.h32
-rw-r--r--src/bytecode.c12
-rw-r--r--src/callint.c150
-rw-r--r--src/callproc.c157
-rw-r--r--src/casefiddle.c2
-rw-r--r--src/casetab.c1
-rw-r--r--src/category.c4
-rw-r--r--src/ccl.c31
-rw-r--r--src/ccl.h2
-rw-r--r--src/character.c38
-rw-r--r--src/character.h39
-rw-r--r--src/charset.c146
-rw-r--r--src/charset.h8
-rw-r--r--src/chartab.c87
-rw-r--r--src/cmds.c26
-rw-r--r--src/coding.c299
-rw-r--r--src/coding.h82
-rw-r--r--src/commands.h4
-rw-r--r--src/composite.c133
-rw-r--r--src/composite.h3
-rw-r--r--src/conf_post.h70
-rw-r--r--src/data.c214
-rw-r--r--src/dbusbind.c67
-rw-r--r--src/decompress.c63
-rw-r--r--src/deps.mk2
-rw-r--r--src/dired.c93
-rw-r--r--src/dispextern.h194
-rw-r--r--src/dispnew.c385
-rw-r--r--src/disptab.h3
-rw-r--r--src/doc.c72
-rw-r--r--src/dosfns.c55
-rw-r--r--src/dosfns.h3
-rw-r--r--src/editfns.c964
-rw-r--r--src/emacs.c197
-rw-r--r--src/eval.c255
-rw-r--r--src/fileio.c600
-rw-r--r--src/filelock.c29
-rw-r--r--src/fns.c764
-rw-r--r--src/font.c483
-rw-r--r--src/font.h200
-rw-r--r--src/fontset.c120
-rw-r--r--src/fontset.h1
-rw-r--r--src/frame.c1507
-rw-r--r--src/frame.h599
-rw-r--r--src/fringe.c120
-rw-r--r--src/ftfont.c258
-rw-r--r--src/ftfont.h1
-rw-r--r--src/ftxfont.c33
-rw-r--r--src/gfilenotify.c56
-rw-r--r--src/gmalloc.c243
-rw-r--r--src/gnutls.c1027
-rw-r--r--src/gtkutil.c853
-rw-r--r--src/gtkutil.h29
-rw-r--r--src/image.c1276
-rw-r--r--src/indent.c4
-rw-r--r--src/inotify.c81
-rw-r--r--src/insdel.c79
-rw-r--r--src/intervals.h19
-rw-r--r--src/keyboard.c938
-rw-r--r--src/keyboard.h88
-rw-r--r--src/keymap.c126
-rw-r--r--src/keymap.h5
-rw-r--r--src/lastfile.c2
-rw-r--r--src/lisp.h1396
-rw-r--r--src/lisp.mk3
-rw-r--r--src/lread.c319
-rw-r--r--src/macfont.h13
-rw-r--r--src/macfont.m3387
-rw-r--r--src/macros.c32
-rw-r--r--src/marker.c17
-rw-r--r--src/menu.c256
-rw-r--r--src/menu.h35
-rw-r--r--src/minibuf.c117
-rw-r--r--src/msdos.c113
-rw-r--r--src/nsfns.m147
-rw-r--r--src/nsfont.m49
-rw-r--r--src/nsgui.h9
-rw-r--r--src/nsimage.m4
-rw-r--r--src/nsmenu.m124
-rw-r--r--src/nsselect.m250
-rw-r--r--src/nsterm.h72
-rw-r--r--src/nsterm.m503
-rw-r--r--src/print.c87
-rw-r--r--src/process.c582
-rw-r--r--src/process.h20
-rw-r--r--src/profiler.c3
-rw-r--r--src/puresize.h2
-rw-r--r--src/ralloc.c12
-rw-r--r--src/regex.c89
-rw-r--r--src/regex.h3
-rw-r--r--src/scroll.c48
-rw-r--r--src/search.c153
-rw-r--r--src/sheap.c2
-rw-r--r--src/sound.c200
-rw-r--r--src/syntax.c22
-rw-r--r--src/sysdep.c550
-rw-r--r--src/sysselect.h42
-rw-r--r--src/syssignal.h4
-rw-r--r--src/systime.h31
-rw-r--r--src/systty.h6
-rw-r--r--src/term.c312
-rw-r--r--src/termcap.c2
-rw-r--r--src/termhooks.h86
-rw-r--r--src/terminal.c129
-rw-r--r--src/textprop.c52
-rw-r--r--src/tparam.c4
-rw-r--r--src/undo.c8
-rw-r--r--src/unexaix.c27
-rw-r--r--src/unexcoff.c29
-rw-r--r--src/unexcw.c19
-rw-r--r--src/unexelf.c12
-rw-r--r--src/unexhp9k800.c1
-rw-r--r--src/unexmacosx.c92
-rw-r--r--src/unexw32.c60
-rw-r--r--src/vm-limit.c57
-rw-r--r--src/w16select.c6
-rw-r--r--src/w32.c145
-rw-r--r--src/w32.h25
-rw-r--r--src/w32console.c15
-rw-r--r--src/w32fns.c935
-rw-r--r--src/w32font.c252
-rw-r--r--src/w32font.h4
-rw-r--r--src/w32gui.h5
-rw-r--r--src/w32heap.c815
-rw-r--r--src/w32heap.h21
-rw-r--r--src/w32inevt.c12
-rw-r--r--src/w32inevt.h2
-rw-r--r--src/w32menu.c176
-rw-r--r--src/w32notify.c15
-rw-r--r--src/w32proc.c253
-rw-r--r--src/w32select.c24
-rw-r--r--src/w32term.c993
-rw-r--r--src/w32term.h136
-rw-r--r--src/w32uniscribe.c30
-rw-r--r--src/widget.c197
-rw-r--r--src/widgetprv.h1
-rw-r--r--src/window.c696
-rw-r--r--src/window.h300
-rw-r--r--src/xdisp.c1149
-rw-r--r--src/xfaces.c782
-rw-r--r--src/xfns.c1118
-rw-r--r--src/xfont.c88
-rw-r--r--src/xftfont.c98
-rw-r--r--src/xgselect.c10
-rw-r--r--src/xmenu.c413
-rw-r--r--src/xml.c166
-rw-r--r--src/xrdb.c53
-rw-r--r--src/xselect.c420
-rw-r--r--src/xsettings.c98
-rw-r--r--src/xsmfns.c44
-rw-r--r--src/xterm.c2128
-rw-r--r--src/xterm.h170
162 files changed, 28306 insertions, 18765 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index ea65ad6b4d5..91beaef8d73 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
@@ -70,6 +70,20 @@ define xgettype
set $type = (enum Lisp_Type) (USE_LSB_TAG ? $bugfix & (1 << GCTYPEBITS) - 1 : (EMACS_UINT) $bugfix >> VALBITS)
end
+define xgetsym
+ xgetptr $arg0
+ if (!USE_LSB_TAG)
+ set $ptr = ($ptr << GCTYPEBITS)
+ end
+ set $ptr = ((struct Lisp_Symbol *) ((char *)lispsym + $ptr))
+end
+
+# Access the name of a symbol
+define xsymname
+ xgetsym $arg0
+ set $symname = $ptr->name
+end
+
# Set up something to print out s-expressions.
# We save and restore print_output_debug_flag to prevent the w32 port
# from calling OutputDebugString, which causes GDB to display each
@@ -468,18 +482,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 +512,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
@@ -750,7 +764,7 @@ end
define xsymbol
set $sym = $
- xgetptr $sym
+ xgetsym $sym
print (struct Lisp_Symbol *) $ptr
xprintsym $sym
echo \n
@@ -862,10 +876,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.
@@ -1074,9 +1086,8 @@ define xprintstr
end
define xprintsym
- xgetptr $arg0
- set $sym = (struct Lisp_Symbol *) $ptr
- xgetptr $sym->name
+ xsymname $arg0
+ xgetptr $symname
set $sym_name = (struct Lisp_String *) $ptr
xprintstr $sym_name
end
@@ -1085,8 +1096,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 +1109,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
@@ -1260,8 +1271,8 @@ tbreak init_sys_modes
commands
silent
xgetptr globals.f_Vinitial_window_system
- set $tem = (struct Lisp_Symbol *) $ptr
- xgetptr $tem->name
+ xsymname $ptr
+ xgetptr $symname
set $tem = (struct Lisp_String *) $ptr
set $tem = (char *) $tem->data
# If we are running in synchronous mode, we want a chance to look
diff --git a/src/ChangeLog b/src/ChangeLog
index 7e6a7c4c9e7..8e5166e22be 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,14 +1,911 @@
-2014-12-30 Eli Zaretskii <eliz@gnu.org>
+2015-01-27 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xfaces.c
+ * dispextern.h: Adjust to signature changes.
+ * font.c (font_at, font_range):
+ * fontset.c (Finternal_char_font):
+ * fringe.c (draw_fringe_bitmap_1):
+ * xdisp.c (handle_face_prop, face_before_or_after_it_pos)
+ (get_next_display_element, highlight_trailing_whitespace)
+ (display_string, calc_line_height_property)
+ (note_mode_line_or_margin_highlight, note_mouse_highlight):
+ * xfaces.c (tty_suppress_bold_inverse_default_colors_p)
+ (menu_face_changed_default, recompute_basic_faces)
+ (Fbitmap_spec_p, parse_rgb_list, tty_lookup_color)
+ (tty_defined_color, defined_color, face_color_gray_p)
+ (face_color_supported_p, load_color2, load_face_colors)
+ (Fx_list_fonts, LFACEP, push_named_merge_point)
+ (resolve_face_name, lface_from_face_name_no_resolve)
+ (lface_from_face_name, get_lface_attributes_no_remap)
+ (get_lface_attributes, lface_fully_specified_p)
+ (set_lface_from_font, merge_face_vectors, merge_named_face)
+ (merge_face_ref, Finternal_make_lisp_face)
+ (Finternal_lisp_face_p, Finternal_copy_lisp_face)
+ (Finternal_set_lisp_face_attribute)
+ (update_face_from_frame_parameter, set_font_frame_param)
+ (face_boolean_x_resource_value)
+ (Finternal_set_lisp_face_attribute_from_resource)
+ (x_update_menu_appearance, Finternal_get_lisp_face_attribute)
+ (Finternal_merge_in_global_face, Fface_font, face_attr_equal_p)
+ (lface_equal_p, Finternal_lisp_face_equal_p)
+ (Finternal_lisp_face_empty_p, lface_same_font_attributes_p)
+ (Fcolor_distance, lookup_named_face, lookup_basic_face)
+ (lookup_derived_face, Fface_attributes_as_vector)
+ (x_supports_face_attributes_p, tty_supports_face_attributes_p)
+ (Fdisplay_supports_face_attributes_p, realize_basic_faces)
+ (realize_default_face, realize_named_face)
+ (realize_non_ascii_face, realize_x_face, map_tty_color)
+ (realize_tty_face, compute_char_face, face_at_buffer_position)
+ (face_for_overlay_string, face_at_string_position):
+ Use bool for boolean.
+ * xfaces.c (set_lface_from_font):
+ Return void, since callers never use the result.
+
+2015-01-26 Andreas Schwab <schwab@linux-m68k.org>
+
+ * image.c (lookup_pixel_color): Reorder conditions that are
+ written backwards.
+ (x_to_xcolors): Likewise.
+ (x_detect_edges): Likewise.
+ (png_load_body): Likewise.
+ (gif_close): Likewise.
+ (gif_load): Likewise.
+
+2015-01-25 Eli Zaretskii <eliz@gnu.org>
+
+ Use bool for boolean in w32term.c
+ * w32term.c (x_update_window_begin, x_update_window_end)
+ (x_update_end, x_after_update_window_line)
+ (x_set_glyph_string_gc, x_draw_glyph_string_background)
+ (x_draw_glyph_string_foreground)
+ (x_draw_composite_glyph_string_foreground)
+ (x_draw_glyphless_glyph_string_foreground)
+ (x_draw_image_glyph_string, x_draw_glyph_string)
+ (x_draw_stretch_glyph_string, note_mouse_movement)
+ (w32_mouse_position, x_scroll_bar_report_motion)
+ (x_horizontal_scroll_bar_report_motion, w32_read_socket)
+ (w32_set_vertical_scroll_bar, w32_set_horizontal_scroll_bar)
+ (w32_draw_window_cursor, x_new_font, x_set_offset)
+ (x_set_window_size, x_make_frame_invisible, x_iconify_frame): Use
+ bool where appropriate.
+
+ Use bool for boolean in w32fns.c
+ * w32fns.c (w32_defined_color, x_decode_color)
+ (Fxw_color_defined_p, Fxw_color_values, x_set_icon_type)
+ (x_set_menu_bar_lines, x_change_tool_bar_height)
+ (x_set_internal_border_width, x_explicitly_set_name)
+ (x_implicitly_set_name, Fx_create_frame, w32_window)
+ (x_create_tip_frame, Fx_show_tip): Use bool where appropriate.
+
+2015-01-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xfns.c
+ * xfaces.c (x_update_menu_appearance):
+ * xfns.c (x_real_positions, x_defined_color, x_decode_color)
+ (xg_set_icon, xg_set_icon_from_xpm_data, x_set_cursor_color)
+ (x_set_icon_type, x_set_icon_name, x_set_menu_bar_lines)
+ (x_change_tool_bar_height, x_set_internal_border_width)
+ (x_encode_text, x_set_name_internal, x_explicitly_set_name)
+ (x_implicitly_set_name, x_default_scroll_bar_color_parameter)
+ (hack_wm_protocols, xic_create_fontsetname, xic_free_xfontset)
+ (x_window, x_icon, Fx_wm_set_size_hint, Fx_create_frame)
+ (Fxw_color_defined_p, Fxw_color_values, x_create_tip_frame)
+ (Fx_show_tip, clean_up_file_dialog, Fx_file_dialog)
+ (clean_up_dialog, syms_of_xfns):
+ * xterm.h (xg_set_icon, xg_set_icon_from_xpm_data)
+ (xic_create_fontsetname):
+ Use bool for boolean.
+ * xfns.c: Include bitmaps/gray.xbm unconditionally.
+
+ Count MANY function args more reliably
+ * alloc.c (Fgc_status, purecopy, unbind_to, garbage_collect_1):
+ * buffer.c (Fbuffer_list, Fkill_buffer):
+ * callint.c (read_file_name, Fcall_interactively):
+ * charset.c (Fset_charset_priority, syms_of_charset):
+ * chartab.c (uniprop_encode_value_numeric):
+ * coding.c (syms_of_coding):
+ * composite.c (syms_of_composite):
+ * data.c (wrong_range):
+ * dbusbind.c (syms_of_dbusbind):
+ * dired.c (file_attributes):
+ * editfns.c (Fdecode_time, update_buffer_properties, format2):
+ * eval.c (run_hook_with_args_2, apply1, call1, call2, call3)
+ (call4, call5, call6, call7):
+ * fileio.c (Finsert_file_contents, choose_write_coding_system)
+ (Fcar_less_than_car, build_annotations, auto_save_error):
+ * filelock.c (get_boot_time):
+ * fns.c (internal_equal, nconc2, Fyes_or_no_p, Fwidget_apply):
+ (maybe_resize_hash_table, secure_hash):
+ * font.c (font_style_to_value, font_open_by_name, Flist_fonts):
+ * fontset.c (fontset_add, Fset_fontset_font):
+ * ftfont.c (ftfont_lookup_cache):
+ * gtkutil.c (xg_get_font):
+ * insdel.c (signal_before_change, signal_after_change):
+ * keymap.c (append_key):
+ * lread.c (load_warn_old_style_backquotes, Fload, init_lread):
+ * minibuf.c (Fread_buffer):
+ * print.c (print_preprocess):
+ * process.c (Fformat_network_address, Fmake_network_process)
+ (server_accept_connection):
+ * sound.c (Fplay_sound_internal):
+ * term.c (Fsuspend_tty, Fresume_tty):
+ * window.c (window_list):
+ * xdisp.c (run_redisplay_end_trigger_hook, add_to_log)
+ (message_with_string):
+ * xfaces.c (Fx_list_fonts):
+ * xfont.c (syms_of_xfont):
+ * xselect.c (x_handle_selection_request)
+ (x_handle_selection_clear, x_clear_frame_selections)
+ (x_clipboard_manager_error_1):
+ Prefer CALLMANY and CALLN to counting args by hand.
+ * doc.c (reread_doc_file): Remove unused code.
+ * fns.c (concat2, concat3): Redo to avoid need for local-var vector.
+ (cmpfn_user_defined, hashfn_user_defined, Fmaphash):
+ Prefer call1 and call2 to Ffuncall.
+ * keyboard.c (safe_run_hook_funcall, safe_run_hooks):
+ Use struct literal rather than a local var, for simplicity.
+ * keymap.c (where_is_internal): Use NULL rather than a pointer
+ to unused args.
+ * lisp.h (CALLMANY, CALLN): New macros.
+ * sound.c (Fplay_sound_internal): Coalesce duplicate code.
+ Fixes: bug#19634
+
+ Use gnustep-config if available
+ * emacs.c [NS_IMPL_GNUSTEP]: Don't include <GNUstepBase/GSConfig.h>.
+ It doesn't appear to be needed, and the inclusion breaks on
+ Ubuntu 14.10 when 'configure' uses 'gnustep-config'.
+
+2015-01-22 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (init_iterator): Restore a comment lost in transition.
+
+2015-01-22 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xfont.c, xftfont.c, xgselect.c
+ * xfont.c (xfont_driver, xfont_chars_supported)
+ (xfont_text_extents):
+ * xftfont.c (xftfont_get_colors, xftfont_open)
+ (xftfont_prepare_face, xftfont_done_face)
+ (xftfont_cached_font_ok):
+ * xgselect.c (xg_select):
+ Use bool for boolean.
+
+ Don't downcase system diagnostics' first letters
+ * fileio.c (report_file_errno): Don't downcase, and simplify.
+ Fixes: bug#19642
+
+ Isolate NIL_IS_ZERO-assuming code better
+ Suggested by Stefan Monnier in:
+ http://lists.gnu.org/archive/html/emacs-devel/2015-01/msg00588.html
+ * alloc.c (allocate_pseudovector):
+ Use memclear, not memsetnil, to remove a 'verify'.
+ * callint.c (Fcall_interactively):
+ * dispnew.c (realloc_glyph_pool):
+ * xdisp.c (init_iterator):
+ Use memclear, not memset, to remove a 'verify'.
+ * lisp.h (memclear): Rename from memsetnil, and take a byte
+ count rather than a word count. All callers changed.
+
+2015-01-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ Undo port to hypothetical nonzero Qnil case
+ This mostly undoes the previous change in this area. See:
+ http://lists.gnu.org/archive/html/emacs-devel/2015-01/msg00570.html
+ * alloc.c (allocate_pseudovector):
+ * callint.c (Fcall_interactively):
+ * dispnew.c (realloc_glyph_pool):
+ * fringe.c (init_fringe):
+ * lisp.h (memsetnil):
+ * xdisp.c (init_iterator):
+ Simplify by assuming that Qnil is zero, but verify the assumption.
+ * lisp.h (NIL_IS_ZERO): Revert back to this symbol, removing
+ NIL_IS_NONZERO. All uses changed.
+
+2015-01-20 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (EV_TRAILER2): Set Vinhibit_quit to Qt (Bug#19531).
+
+2015-01-20 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Prefer xlispstrdup to avoid dumb calls to strlen.
+ * nsfont.m (ns_get_family):
+ * nsterm.m (ns_term_init):
+ * w32fns.c (w32_window):
+ * xfns.c (x_window, Fx_select_font): Use xlispstrdup.
+
+2015-01-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ Correct an old fix for GTK font selection
+ * gtkutil.c (xg_get_font): Fix off-by-2 typo.
+ Fixes: bug#3228
+
+ Fix minor bugs with printing null bytes
+ * minibuf.c (read_minibuf_noninteractive):
+ * xdisp.c (Ftrace_to_stderr) [GLYPH_DEBUG]:
+ Work even if the Lisp string contains a null byte.
+
+ Port to hypothetical case where Qnil is nonzero
+ * alloc.c (allocate_pseudovector):
+ * callint.c (Fcall_interactively):
+ * coding.c (syms_of_coding):
+ * dispnew.c (realloc_glyph_pool):
+ * fringe.c (init_fringe):
+ * lisp.h (memsetnil):
+ * xdisp.c (init_iterator):
+ Port to the currently-hypothetical case where Qnil is nonzero.
+ * dispnew.c (adjust_glyph_matrix): Remove unnecessary verification,
+ as there are no Lisp_Object values in the data here.
+ * lisp.h (NIL_IS_NONZERO): New symbol, replacing NIL_IS_ZERO.
+ All uses changed. Define only if not already defined, so that one
+ can debug with -DNIL_IS_NONZERO.
+ * xdisp.c (init_iterator): Remove unnecessary initializations to 0.
+
+2015-01-19 Eli Zaretskii <eliz@gnu.org>
+
+ * dispnew.c (adjust_glyph_matrix, realloc_glyph_pool): Verify that
+ Qnil is represented as zero, before using that to initialize parts
+ of the glyph structure.
+
+ * xdisp.c (init_iterator): Verify that Qnil is represented as
+ zero, before using that to initialize parts of the iterator
+ structure.
+
+2015-01-19 Paul Eggert <eggert@cs.ucla.edu>
+
+ Prefer memset to repeatedly assigning Qnil
+ * alloc.c (allocate_pseudovector): Catch more bogus values.
+ * alloc.c (allocate_pseudovector):
+ * callint.c (Fcall_interactively):
+ * coding.c (syms_of_coding):
+ * fringe.c (init_fringe):
+ Verify that Qnil == 0.
+ * callint.c (Fcall_interactively):
+ * eval.c (Fapply, Ffuncall):
+ * fns.c (mapcar1, larger_vector):
+ * font.c (font_expand_wildcards):
+ * fringe.c (init_fringe):
+ Prefer memset to assigning zeros by hand.
+ * callint.c (Fcall_interactively):
+ Remove duplicate assignment of Qnil to args[i].
+ * coding.c (syms_of_coding):
+ Prefer LISP_INITIALLY_ZERO to assigning zeros by hand.
+ * fileio.c (Ffile_selinux_context):
+ Rewrite to avoid need for Lisp_Object array.
+ * lisp.h (XLI_BUILTIN_LISPSYM): New macro.
+ (DEFINE_LISP_SYMBOL_END): Use it.
+ (NIL_IS_ZERO): New constant.
+ (memsetnil): New function.
+
+2015-01-16 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Tune pseudovector allocation assuming Qnil == 0.
+ * alloc.c (allocate_pseudovector): Use memset for both
+ Lisp_Objects and regular slots. Add zerolen arg.
+ * lisp.h (allocate_pseudovector): Adjust prototype.
+ (ALLOCATE_PSEUDOVECTOR): Adjust user.
+ (ALLOCATE_ZEROED_PSEUDOVECTOR): New macro.
+ (allocate_hash_table, allocate_window, allocate_frame)
+ (allocate_process, allocate_terminal): Remove prototypes.
+ * fns.c (allocate_hash_table): Now static here.
+ * frame.c (allocate_frame):
+ * process.c (allocate_process):
+ * terminal.c (allocate_terminal):
+ * window.c (allocate_window): Now static here.
+ Use ALLOCATE_ZEROED_PSEUDOVECTOR. Add comment.
+
+ * lisp.h (XTERMINAL): Add eassert.
+ * process.c (make_lisp_proc): Now static here.
+
+ Prefer INLINE functions in font.h to match style used in lisp.h.
+ * font.h (FONTP, FONT_SPEC_P, FONT_ENTITY_P, FONT_OBJECT_P)
+ (CHECK_FONT, CHECK_FONT_SPEC, CHECK_FONT_ENTITY, CHECK_FONT_OBJECT)
+ (XFONT_SPEC, XFONT_ENTITY, XFONT_OBJECT, CHECK_FONT_GET_OBJECT):
+ Now functions.
+ * font.c (Ffont_otf_alternates, Fquery_font, Ffont_get_glyphs):
+ * ftfont.c (ftfont_shape):
+ * macfont.m (macfont_shape):
+ * w32uniscribe.c (uniscribe_shape):
+ * xftfont.c (xftfont_shape): Adjust CHECK_FONT_GET_OBJECT users.
+
+2015-01-16 Paul Eggert <eggert@cs.ucla.edu>
+
+ Give up on -Wsuggest-attribute=const
+ * decompress.c (Fzlib_available_p):
+ * gnutls.c (Fgnutls_available_p):
+ * gtkutil.h (xg_uses_old_file_dialog):
+ * xdisp.c (Ftool_bar_height):
+ * xmenu.c (popup_activated):
+ No longer const, since it's not const on at lest some
+ configurations, and we shouldn't lie to the compiler.
+
+2015-01-15 Eli Zaretskii <eliz@gnu.org>
+
+ * fileio.c: Include binary-io.h.
+ (Fset_binary_mode): New function.
+ (syms_of_fileio): Defsubr it.
+ (syms_of_fileio) <Qstdin, Qstdout, Qstderr>: DEFSYM them.
+
+2015-01-15 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnutls.c (init_gnutls_functions): Import gnutls_x509_crt_check_issuer.
+ (Fgnutls_peer_status): Use it to set the :self-signed flag.
+ Rename the previous :self-signed to :unknown-ca. (Bug#19404)
+ (Fgnutls_peer_status_warning_describe): Explain :unknown-ca flag.
+
+2015-01-14 Eli Zaretskii <eliz@gnu.org>
+
+ * w32fns.c (w32_wnd_proc): Ignore MENUITEMINFO's dwItemData data
+ when FLAGS indicate the item is not highlighted. (Bug#19596)
+
+2015-01-14 Martin Rudalics <rudalics@gmx.at>
+
+ * xmenu.c (update_frame_menubar): Remove garbaged code.
+
+2015-01-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ remove_slash_colon need not be inline
+ * process.c, process.h (remove_slash_colon): No longer inline.
+ This saves text bytes without hurting runtime performance.
+
+2015-01-14 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Avoid extra multibyteness check in ENCODE_FILE users.
+ * callproc.c (encode_current_directory, Fcall_process, call_process):
+ * dired.c (directory_files_internal, file_name_completion):
+ Do not check for STRING_MULTIBYTE because encode_file_name
+ is a no-op for unibyte strings.
+
+ * process.h (remove_slash_colon): New function.
+ * callproc.c (encode_current_directory, call_process):
+ * process.c (Fstart_process): Use it.
+
+ Consistently handle time zone specification.
+ * editfns.c (decode_time_zone): New function, refactored out from ...
+ (Fencode_time): ... adjusted user.
+ (Fset_time_zone_rule): Use decode_time_zone.
+
+ * editfns.c (make_buffer_string_both): If requested range intersects
+ the gap, don't move the latter but copy in two regions, thus avoiding
+ unnecessary relocation of buffer data.
+
+2015-01-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xmenu.c, xml.c
+ * xmenu.c (x_menu_set_in_use, popup_get_selection)
+ (Fx_menu_bar_open_internal, popup_widget_loop)
+ (x_activate_menubar, xg_crazy_callback_abort)
+ (update_frame_menubar, set_frame_menubar)
+ (initialize_frame_menubar, free_frame_menubar)
+ (create_and_show_popup_menu, x_menu_show)
+ (create_and_show_dialog, x_dialog_show):
+ * xml.c (libxml2_loaded_p, init_libxml2_functions, parse_region)
+ (Flibxml_parse_html_region, Flibxml_parse_xml_region):
+ * xrdb.c (main) [TESTRM]:
+ * xsettings.c (init_gsettings):
+ * xterm.c (XFillRectangle, xg_scroll_callback)
+ (xg_end_scroll_callback):
+ * xterm.h (x_menu_set_in_use) [USE_GTK || USE_MOTIF]:
+ Use bool for boolean.
+ * xmenu.c (TRUE): Remove; no longer used.
+ (show_help_event): Remove long-unused code.
+ (set_frame_menubar): Remove "#if 1" and corresponding "#endif" lines.
+
+2015-01-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ Don't say Fnext_read_file_uses_dialog_p is const
+ It's const only if a windowing system is not used; don't say it's
+ const otherwise. See:
+ http://lists.gnu.org/archive/html/emacs-devel/2015-01/msg00310.html
+ * fileio.c (next_read_file_uses_dialog_p): Remove.
+ Move guts back to ...
+ (Fnext_read_file_uses_dialog_p): ... here.
+ Don't declare as const, as make-docfile.c now has a special case
+ for this function. This is an ugly hack, but it's better than
+ lying to the compiler.
+
+ Remove now-unnecessary forward XTYPE decl
+ * lisp.h (XTYPE): Remove forward declaration. The recent merge
+ from emacs-24 fixed the problem in a better way, by moving XPNTR's
+ definition to after XTYPE's.
+
+2015-01-13 Eli Zaretskii <eliz@gnu.org>
+
+ Fix problems with 32-bit wide-int build exposed by MinGW.
+ * lisp.h (XPNTR): Move definition to after XTYPE, to avoid
+ compilation error in an unoptimized build when !USE_LSB_TAG.
+
+ * w32heap.c (DUMPED_HEAP_SIZE): For 32-bit wide-int build, use the
+ same larger value as for the 64-bit build.
+
+ * w32term.h (SCROLL_BAR_PACK): Cast the result to UINT_PTR to
+ avoid compiler warnings.
+
+ * w32proc.c (Fw32_get_codepage_charset, Fw32_set_keyboard_layout):
+ Avoid compiler warnings about cast from integer to pointer of
+ different size.
+
+ * w32menu.c (menubar_selection_callback, w32_menu_show): Cast to
+ UINT_PTR instead of EMACS_INT, to avoid compiler warnings about
+ casting from integer to pointer of different size.
+ (add_menu_item): Pass the help-echo string as a pointer to
+ Lisp_String, not as a Lisp_Object.
+ (w32_menu_display_help): Use make_lisp_ptr to reconstruct a Lisp
+ string object from its C pointer.
+
+ * w32fns.c (w32_msg_pump) <WM_EMACS_UNREGISTER_HOT_KEY>: Use
+ make_lisp_ptr instead of XIL, to reconstruct a Lisp_Cons from its
+ C pointer.
+ <WM_EMACS_TOGGLE_LOCK_KEY>: msg.lparam is now a C integer.
+ (Fx_create_frame): Type-cast the result of XFASTINT to avoild
+ compiler warnings about size differences.
+ (Fw32_unregister_hot_key): Pass the tail of w32_grabbed_keys as a
+ pointer to a Lisp_Cons struct, not as a disguised EMACS_INT.
+ (Fw32_toggle_lock_key): Pass the new state of the key as a C
+ integer; use -1 for nil. Doc fix.
+
+ * .gdbinit (xgetsym): New subroutine.
+ (xsymname, xsymbol): Use it.
+ (xprintsym): No need to call xgetptr.
+
+2015-01-13 Martin Rudalics <rudalics@gmx.at>
+
+ * frame.c (adjust_frame_size): Make sure new numbers of
+ lines/columns get installed after font size change (Bug#19575).
+
+2015-01-13 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Add DEFUN attributes.
+ * callint.c (Finteractive):
+ * character.c (Fcharacterp, Fmax_char):
+ * data.c (Feq, Fnull, Fconsp, Fatom, Flistp, Fnlistp, Fsymbolp)
+ (Fstringp, Fchar_or_string_p, Fintegerp, Fnatnump, Fnumberp)
+ (Ffloatp, Fbyteorder):
+ * decompress.c (Fzlib_available_p):
+ * fns.c (Fidentity):
+ * frame.c (Fframe_windows_min_size):
+ * gnutls.c (Fgnutls_error_p, Fgnutls_available_p):
+ * window.c (Fwindow__sanitize_window_sizes):
+ * xdisp.c (Ftool_bar_height):
+ * xfaces.c (Fface_attribute_relative_p): Add const attribute.
+ * emacs.c (Fkill_emacs):
+ * eval.c (Fthrow):
+ * keyboard.c (Ftop_level, Fexit_recursive_edit)
+ (Fabor_recursive_edit): Add noreturn attribute.
+
+ * search.c (fast_string_match_internal): New function,
+ consolidated from...
+ (fast_string_match, fast_string_match_ignore_case): ...functions
+ which are...
+ * lisp.h (fast_string_match, fast_string_match_ignore_case):
+ inlined from here now.
+ (fast_string_match_internal): Add prototype.
+ * dired.c (file_name_completion): Use fast_string_match_internal.
+
+ * fileio.c (next_read_file_uses_dialog_p): New workaround ...
+ (Fnext_read_file_uses_dialog_p): ... called from here to avoid
+ ATTRIBUTE_CONST dependency from #ifdefs. For details, see
+ http://lists.gnu.org/archive/html/emacs-devel/2015-01/msg00289.html.
+
+2015-01-12 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port to 32-bit MingGW --with-wide-int
+ Problem reported by Eli Zaretskii in:
+ http://lists.gnu.org/archive/html/emacs-devel/2015-01/msg00265.html
+ * lisp.h (struct Lisp_Sub_Char_Table): Check that offset matches
+ what we think it is, rather than checking only its alignment (and
+ doing so incorrectly on MinGW).
+
+2015-01-12 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * fileio.c (Ffile_name_as_directory, Fdirectory_file_name):
+ Remove dead NILP check.
+ * image.c (Flookup_image): Use regular format for docstring.
+ * keyboard.c (apply_modifiers_uncached): Use stpcpy.
+
+2015-01-12 Martin Rudalics <rudalics@gmx.at>
+
+ * dispnew.c (change_frame_size_1): Pass Qchange_frame_size to
+ adjust_frame_size.
+ * frame.c (frame_default_tool_bar_height): New variable.
+ (adjust_frame_size): Possibly add requested adjustment to
+ Vframe_adjust_size_history.
+ (make_frame): Initialize tool_bar_redisplayed_once slot.
+ (Fset_frame_height, Fset_frame_width, Fset_frame_size): Clarify
+ doc-string. Call adjust_frame_size unconditionally (the frame's
+ text size may remain unaltered but the pixel size may change).
+ (x_figure_window_size): If frame_default_tool_bar_height was
+ set, use it instead of calculating the tool bar height from
+ DEFAULT_TOOL_BAR_IMAGE_HEIGHT. Don't set
+ Vframe_initial_frame_tool_bar_height.
+ (Qchange_frame_size, Qxg_frame_set_char_size)
+ (Qset_window_configuration, Qx_create_frame_1)
+ (Qx_create_frame_2): New symbols.
+ (Vframe_initial_frame_tool_bar_height): Remove.
+ (Vframe_adjust_size_history): New history variable for debugging
+ frame size adjustments.
+ * frame.h (struct frame): New boolean slot
+ tool_bar_redisplayed_once.
+ (frame_default_tool_bar_height): Extern.
+ * gtkutil.c (xg_frame_set_char_size): Pass Qxg_frame_set_char_size
+ to adjust_frame_size.
+ * nsfns.m (Fx_create_frame): Pass Pass Qx_create_frame_1 and
+ Qx_create_frame_2 to adjust_frame_size.
+ * w32fns.c (x_change_tool_bar_height): Call adjust_frame_size with
+ inhibit 1 when we have not redisplayed the tool bar yet.
+ (Fx_create_frame): Pass Pass Qx_create_frame_1 and
+ Qx_create_frame_2 to adjust_frame_size.
+ * w32menu.c (set_frame_menubar): Simplify adjust_frame_size
+ call.
+ * window.c (Fset_window_configuration): Pass
+ Qset_window_configuration to adjust_frame_size.
+ * xdisp.c (redisplay_tool_bar): Assign new height to
+ frame_default_tool_bar_height.
+ (redisplay_internal): If we haven't redisplayed this frame's
+ tool bar, call redisplay_tool_bar early so we can adjust the
+ frame size accordingly.
+ * xfns.c (x_change_tool_bar_height): Call adjust_frame_size with
+ inhibit 1 when we have not redisplayed the tool bar yet.
+ (Fx_create_frame): Pass Pass Qx_create_frame_1 and
+ Qx_create_frame_2 to adjust_frame_size.
+
+2015-01-12 Paul Eggert <eggert@cs.ucla.edu>
+
+ Have 'make' output better GEN names
+ * Makefile.in (gl-stamp, globals.h): Simplify by putting the new
+ contents of globals.h into gl-stamp. This lets us use AM_V_GEN
+ more naturally so that 'make' can output more-accurate names.
+
+2015-01-11 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * buffer.c (init_buffer_once): Initialize buffer_local_flags before
+ calling reset_buffer_local_variables, and make sure we initialize
+ it completely.
+
+2015-01-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * coding.c (Fcoding_system_plist): Use common style for docstring.
+
+2015-01-11 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port to MSB hosts without optimization
+ E.g., when configuring --with-wide-int CFLAGS='-O0' on x86,
+ the inline function XTYPE needs to be declared before being used.
+ * lisp.h (XTYPE): New forward declaration.
+
+2015-01-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port to 32-bit --with-wide-int
+ Prefer symbol indexes to struct Lisp_Symbol * casted and then
+ widened, as the latter had trouble with GCC on Fedora 21 when
+ configured --with-wide-int and when used in static initializers.
+ * alloc.c (garbage_collect_1, which_symbols):
+ * lread.c (init_obarray):
+ Prefer builtin_lisp_symbol when it can be used.
+ * dispextern.h (struct image_type.type):
+ * font.c (font_property_table.key):
+ * frame.c (struct frame_parm_table.sym):
+ * keyboard.c (scroll_bar_parts, struct event_head):
+ * xdisp.c (struct props.name):
+ Use the index of a builtin symbol rather than its address.
+ All uses changed.
+ * lisp.h (TAG_SYMPTR, XSYMBOL_INIT): Remove, replacing with ...
+ (TAG_SYMOFFSET, SYMBOL_INDEX): ... new macros that deal with
+ symbol indexes rather than pointers, and which work better on MSB
+ hosts because they shift right before tagging. All uses changed.
+ (DEFINE_LISP_SYMBOL_BEGIN, DEFINE_LISP_SYMBOL_END):
+ No longer noops on wide-int hosts, since they work now.
+ (builtin_lisp_symbol): New function.
+
+ Port to HAVE_FREETYPE && !HAVE_XFT
+ * dispextern.h (struct face.extra) [HAVE_FREETYPE && !HAVE_XFT]:
+ * font.h (syms_of_xftfont) [HAVE_FREETYPE && !HAVE_XFT]:
+ Declare in this case too.
+
+2015-01-10 Eli Zaretskii <eliz@gnu.org>
+
+ * w32fns.c (Fw32_register_hot_key): Use XINT instead of XLI.
+
+ * w32notify.c (Fw32notify_add_watch, w32_get_watch_object): Use
+ make_pointer_integer instead of XIL.
+ (Fw32notify_rm_watch): Use XINTPTR instead of XLI.
+
+ * w32inevt.c (handle_file_notifications): Use make_pointer_integer
+ instead of XIL. Put a list of the descriptor, action, and file
+ name in event->arg, instead of spreading them between event->code
+ and event->arg.
+
+ * w32term.c (queue_notifications): Use make_pointer_integer
+ instead of XIL. Put a list of the descriptor, action, and file
+ name in event->arg, instead of spreading them between event->code
+ and event->arg.
+
+ * keyboard.c (kbd_buffer_get_event) [HAVE_W32NOTIFY]: Adjust Lisp
+ event creation to changes in w32term.c and w32inevt.c above.
+
+2015-01-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port Qnil==0 changes to 32-bit --with-wide-int
+ * lisp.h (lisp_h_XSYMBOL, XSYMBOL): Assume USE_LSB_TAG in the
+ macro-implemented version. For the non-USE_LSB_TAG case, supply
+ a new inline function that is the inverse of the new TAG_SYMPTR.
+ (lisp_h_XUNTAGBASE, XUNTAGBASE): Remove. All uses removed.
+ (TAG_SYMPTR) [!USE_LSB_TAG]: If the pointer subtraction yields a
+ negative number, don't allow sign bits to bleed into the encoded
+ value. Shift in zero bits instead.
+
+ Refactor pointer-to-integer conversion
+ * gfilenotify.c (monitor_to_lisp, lisp_to_monitor):
+ Rename and move to lisp.h. All uses changed.
+ * lisp.h (XINTPTR, make_pointer_integer): New inline functions,
+ which are renamed from gfilenotify.c's lisp_to_monitor and
+ monitor_to_lisp, and with more-generic void * signatures.
+
+2015-01-08 Eli Zaretskii <eliz@gnu.org>
+
+ * dispnew.c (buffer_posn_from_coords): Fix the value of the column
+ returned for right-to-left screen lines. (Before the change on
+ 2014-12-30, the incorrectly-computed X pixel coordinate concealed
+ this bug.)
+
+ * .gdbinit (xsymname): New subroutine.
+ (xprintsym, initial-tbreak): Use it to access the name of a symbol
+ in a way that doesn't cause GDB to barf when it tries to
+ dereference a NULL pointer.
+
+ * xdisp.c (next_element_from_c_string): Use Lisp integer zero as
+ the object.
+ (set_cursor_from_row, try_cursor_movement, dump_glyph)
+ (insert_left_trunc_glyphs, append_space_for_newline)
+ (extend_face_to_end_of_line, highlight_trailing_whitespace)
+ (find_row_edges, ROW_GLYPH_NEWLINE_P, Fmove_point_visually)
+ (Fbidi_resolved_levels, produce_special_glyphs)
+ (rows_from_pos_range, mouse_face_from_buffer_pos)
+ (note_mouse_highlight): Use nil as the object for glyphs inserted
+ by the display engine, and test with NILP instead of INTEGERP.
+ (Bug#19535)
+
+ * w32fns.c (Fx_show_tip): Use NILP to test for glyphs inserted by
+ the display engine.
+
+ * xfns.c (Fx_show_tip): Use NILP to test for glyphs inserted by
+ the display engine.
+
+ * dispextern.h (struct glyph, struct it): Update comments for the
+ OBJECT members.
+
+2015-01-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port new Lisp symbol init to x86 --with-wide-int
+ * lisp.h (DEFINE_LISP_SYMBOL_BEGIN, DEFINE_LISP_SYMBOL_END):
+ Define to empty on platforms where EMACS_INT_MAX != INTPTR_MAX, as
+ GCC (at least) does not allow a constant initializer to widen an
+ address constant.
+
+ * lisp.h (TAG_SYMPTR): Don't do arithmetic on NULL.
+ This is a followup to the "Port Qnil==0 XUNTAG to clang" patch.
+ Although clang doesn't need it, some other compiler might, and
+ it's easy enough to be safe.
+
+ * conf_post.h (ATTRIBUTE_ALLOC_SIZE): Port to clang 3.5.0.
+ Apparently clang removed support for the alloc_size attribute.
+
+ Port Qnil==0 XUNTAG to clang
+ clang has undefined behavior if the program subtracts an integer
+ from (char *) 0. Problem reported by YAMAMOTO Mitsuharu in:
+ http://lists.gnu.org/archive/html/emacs-devel/2015-01/msg00132.html
+ * lisp.h (lisp_h_XUNTAG) [USE_LSB_TAG]:
+ (XUNTAG) [!USE_LSB_TAG]: Port to clang 3.5.0.
+
+ Port GFileMonitor * hack to Qnil==0 platforms
+ Reported by Glenn Morris in: http://bugs.gnu.org/15880#112
+ * gfilenotify.c (monitor_to_lisp, lisp_to_monitor): New functions.
+ (dir_monitor_callback, Fgfile_add_watch, Fgfile_rm_watch): Use them.
+
+2015-01-06 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (x_set_window_size): Call updateFrameSize to get real
+ size instead of using widht/height. The frame may be constrained.
+
+2015-01-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ * lisp.h (XSYMBOL): Parenthesize id in forward decl.
+ Needed when neither optimizing nor inlining.
+ Also, sort decls alphabetically.
+
+2015-01-05 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c, w32.h, w32fns.c, w32font.c, w32menu.c, w32notify.c:
+ * w32proc.c, w32select.c, w32term.c, w32uniscribe.c: Remove
+ declarations of Q* variables that represent symbols.
+
+2015-01-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use 0 for Qnil
+ Fixes Bug#15880.
+ If USE_LSB_TAG, arrange for the representation of Qnil to be zero so
+ that NILP (x) is equivalent to testing whether x is 0 at the
+ machine level. The overall effects of this and the previous patch
+ shrink the size of the text segment by 2.3% and speeds up
+ compilation of all the .elc files by about 0.5% on my platform,
+ which is Fedora 20 x86-64.
+ * lisp.h (lisp_h_XPNTR, lisp_h_XSYMBOL, lisp_h_XUNTAG)
+ (make_lisp_symbol) [USE_LSB_TAG]:
+ Symbols now tag the difference from lispsym, not the pointer.
+ (lisp_h_XUNTAGBASE, TAG_SYMPTR): New macros.
+ (Lisp_Int0, Lisp_Int1, Lisp_Symbol, Lisp_Misc, Lisp_String, Lisp_Cons):
+ Renumber so that Lisp_Symbol is 0, so that Qnil is zero.
+ (XSYMBOL): New forward decl.
+ (XUNTAGBASE): New function.
+ (XUNTAG): Use it.
+
+ Compute C decls for DEFSYMs automatically
+ Fixes Bug#15880.
+ This patch also makes Q constants (e.g., Qnil) constant addresses
+ from the C point of view.
+ * alloc.c, bidi.c, buffer.c, bytecode.c, callint.c, casefiddle.c:
+ * casetab.c, category.c, ccl.c, charset.c, chartab.c, cmds.c, coding.c:
+ * composite.c, data.c, dbusbind.c, decompress.c, dired.c, dispnew.c:
+ * doc.c, editfns.c, emacs.c, eval.c, fileio.c, fns.c, font.c, fontset.c:
+ * frame.c, fringe.c, ftfont.c, ftxfont.c, gfilenotify.c, gnutls.c:
+ * image.c, inotify.c, insdel.c, keyboard.c, keymap.c, lread.c:
+ * macfont.m, macros.c, minibuf.c, nsfns.m, nsfont.m, nsimage.m:
+ * nsmenu.m, nsselect.m, nsterm.m, print.c, process.c, profiler.c:
+ * search.c, sound.c, syntax.c, term.c, terminal.c, textprop.c, undo.c:
+ * window.c, xdisp.c, xfaces.c, xfns.c, xftfont.c, xmenu.c, xml.c:
+ * xselect.c, xsettings.c, xterm.c:
+ Remove Q vars that represent symbols (e.g., Qnil, Qt, Qemacs).
+ These names are now defined automatically by make-docfile.
+ * alloc.c (init_symbol): New function.
+ (Fmake_symbol): Use it.
+ (c_symbol_p): New function.
+ (valid_lisp_object_p, purecopy): Use it.
+ * alloc.c (marked_pinned_symbols):
+ Use make_lisp_symbol instead of make_lisp_ptr.
+ (garbage_collect_1): Mark lispsym symbols.
+ (CHECK_ALLOCATED_AND_LIVE_SYMBOL): New macro.
+ (mark_object): Use it.
+ (sweep_symbols): Sweep lispsym symbols.
+ (symbol_uses_obj): New function.
+ (which_symbols): Use it. Work for lispsym symbols, too.
+ (init_alloc_once): Initialize Vpurify_flag here; no need to wait,
+ since Qt's address is already known now.
+ (syms_of_alloc): Add lispsym count to symbols_consed.
+ * buffer.c (init_buffer_once): Compare to Qnil, not to make_number (0),
+ when testing whether storage is all bits zero.
+ * dispextern.h (struct image_type):
+ * font.c (font_property_table):
+ * frame.c (struct frame_parm_table, frame_parms):
+ * keyboard.c (scroll_bar_parts, struct event_head):
+ * xdisp.c (struct props):
+ Use XSYMBOL_INIT (Qfoo) and struct Lisp_Symbol * rather than &Qfoo and
+ Lisp_Object *, since Qfoo is no longer an object whose address can be
+ taken. All uses changed.
+ * eval.c (run_hook): New function. Most uses of Frun_hooks changed to
+ use it, so that they no longer need to take the address of a Lisp sym.
+ (syms_of_eval): Don't use DEFSYM on Vrun_hooks, as it's a variable.
+ * frame.c (syms_of_frame): Add defsyms for the frame_parms table.
+ * keyboard.c (syms_of_keyboard): Don't DEFSYM Qmenu_bar here.
+ DEFSYM Qdeactivate_mark before the corresponding var.
+ * keymap.c (syms_of_keymap): Use DEFSYM for Qmenu_bar and Qmode_line
+ instead of interning their symbols; this avoids duplicates.
+ (LISP_INITIALLY, TAG_PTR)
+ (DEFINE_LISP_SYMBOL_BEGIN, DEFINE_LISP_SYMBOL_END, XSYMBOL_INIT):
+ New macros.
+ (LISP_INITIALLY_ZERO): Use it.
+ (enum symbol_interned, enum symbol_redirect, struct Lisp_Symbol)
+ (EXFUN, DEFUN_ARGS_MANY, DEFUN_ARGS_UNEVALLED, DEFUN_ARGS_*):
+ Move decls up, to avoid forward uses. Include globals.h earlier, too.
+ (make_lisp_symbol): New function.
+ (XSETSYMBOL): Use it.
+ (DEFSYM): Now just a placeholder for make-docfile.
+ * lread.c (DEFINE_SYMBOLS): Define, for globals.h.
+ (intern_sym): New function, with body taken from old intern_driver.
+ (intern_driver): Use it. Last arg is now Lisp integer, not ptrdiff_t.
+ All uses changed.
+ (define_symbol): New function.
+ (init_obarray): Define the C symbols taken from lispsym.
+ Use plain DEFSYM for Qt and Qnil.
+ * syntax.c (init_syntax_once): No need to worry about
+ Qchar_table_extra_slots.
+
+2015-01-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ 'temacs -nw' should not call missing functions
+ Without this patch, "temacs -nw" fails with the diagnostic
+ "emacs: Symbol's function definition is void: frame-windows-min-size"
+ and messes up the tty's state.
+ * frame.c (Fframe_windows_min_size): New placeholder function.
+ (syms_of_frame): Define it.
+ * window.c (Fwindow__sanitize_window_sizes): New placeholder.
+ (syms_of_window): Define it.
+
+ Less 'make' chatter for lisp dir
+ * Makefile.in (%.elc): Adjust to compile-onefile change in
+ ../lisp/Makefile.in.
+
+ batch write-region no longer says "Wrote FOO"
+ This cuts down on 'make' chatter a bit.
+ * fileio.c (Fwrite_region):
+ Don't output "Wrote /whatever/foo.elc" if noninteractive.
+
+2015-01-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Revert previous change to produce_composite_glyph
+ * term.c (produce_composite_glyph): Revert previous change (Bug#19496).
+
+ Pacify gcc -Wparentheses
+ * frame.c (x_set_frame_parameters): Add parens (Bug#19428).
+
+2015-01-03 Martin Rudalics <rudalics@gmx.at>
+
+ * frame.c (x_set_frame_parameters): Call Fset_frame_size only if
+ f->can_x_set_window_size is true.
+ * xterm.c (x_set_window_size_1): Call change_frame_size with
+ text sizes instead of pixel sizes (Bug#19428).
+
+2015-01-01 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (pos_visible_p): Fix up the X coordinate for
right-to-left screen lines. (Bug#19473)
-2014-12-28 Eli Zaretskii <eliz@gnu.org>
+2015-01-01 Eli Zaretskii <eliz@gnu.org>
* w32proc.c (Fw32_get_codepage_charset): Doc fix. (Bug#19458)
+2014-12-31 Paul Eggert <eggert@cs.ucla.edu>
+
+ Simplify setfattr use by assuming GNU make
+ * Makefile.in (PAXCTL_if_present, SETFATTR_if_present): New macros.
+ (emacs$(EXEEXT), temacs$(EXEEXT), bootstrap-emacs$(EXEEXT)): Use them.
+ Simplify by using GNU make rather than shell conditionals,
+ by using ln -f rather than rm -f followed by ln,
+ and by preferring $@ to spelling out the destination.
+
+2014-12-29 Eli Zaretskii <eliz@gnu.org>
+
+ * sysdep.c [WINDOWSNT]: Include sys/socket.h, without which this
+ file doesn't compile on MS-Windows.
+
+2014-12-29 Paul Eggert <eggert@cs.ucla.edu>
+
+ Allow return value of system-name to vary. (Bug#19438)
+ * filelock.c (current_lock_owner):
+ * xrdb.c (get_environ_db):
+ * xterm.c (same_x_server):
+ * xterm.c (x_term_init):
+ Prefer (system-name) to system-name, and avoid naming
+ locals 'system-name'.
+ * editfns.c (cached_system_name): New static var.
+ (init_and_cache_system_name): New function.
+ (init_editfns, Fsystem_name): Use it.
+ (syms_of_editfns): Initialize it and Vsystem_name to the same value.
+ * sysdep.c [HAVE_SOCKETS]: Don't include <sys/socket.h>, <netdb.h>.
+ (h_errno) [TRY_AGAIN && !HAVE_H_ERRNO]: Remove decl.
+ (init_system_name) [HAVE_SOCKETS]: Don't canonicalize the name.
+ Don't create a new string if the current value is already correct.
+
+2014-12-28 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix produce_composite_width typo
+ * term.c (produce_composite_glyph):
+ Fix typo that confused number of columns for pixel width.
+
2014-12-28 Paul Eggert <eggert@Penguin.CS.UCLA.EDU>
+ Wrap dll functions more simply
+ * decompress.c, gnutls.c, image.c, xml.c:
+ If WINDOWSNT, use '#define FOO fn_FOO' to wrap dll functions,
+ rather than the inverse when not WINDOWSNT. This isolates the
+ fn_* business into the WINDOWSNT-specific section of the code,
+ which makes it easier to maintain the generic code.
+ * decompress.c (DEF_ZLIB_FN, LOAD_ZLIB_FN):
+ * gnutls.c (DEF_GNUTLS_FN, LOAD_GNUTLS_FN):
+ * image.c (DEF_IMGLIB_FN, LOAD_IMGLIB_FN):
+ * xml.c (DEF_XML2_FN, LOAD_XML2_FN):
+ Remove. All uses replaced by DEF_DLL_FN.
+ * decompress.c (inflateInit2): Remove; no longer needed.
+ * w32.h (DEF_DLL_FN, LOAD_DLL_FN): New macros.
+
Port memory-full checking to GnuTLS 3.3
Instead of using gnutls_global_set_mem_functions, check every call
to a GnuTLS function that might return an indication of memory
@@ -20,10 +917,19 @@
All uses removed.
(check_memory_full): New function.
(emacs_gnutls_handshake, emacs_gnutls_handle_error)
- (gnutls_make_error, Fgnutls_boot): Use it.
+ (gnutls_make_error, gnutls_certificate_details, Fgnutls_peer_status)
+ (Fgnutls_boot): Use it.
(emacs_gnutls_global_init): Avoid gnutls_global_set_mem_functions.
-2014-12-25 Eli Zaretskii <eliz@gnu.org>
+2014-12-27 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix parse_settings to match internal documentation
+ * xsettings.c (parse_settings): Return the number of settings seen.
+ Count the settings changes accurately.
+ (read_settings): Don't confuse number of settings changes with
+ the return code from XGetWindowProperty.
+
+2014-12-27 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (set_iterator_to_next) <GET_FROM_STRING>: Limit search in
composition_compute_stop_pos to the number of characters in the
@@ -36,7 +942,7 @@
* dispextern.h (struct it) <end_charpos>: Improve commentary.
-2014-12-24 Jan Djärv <jan.h.d@swipnet.se>
+2014-12-27 Jan Djärv <jan.h.d@swipnet.se>
* nsimage.m (allocInitFromFile:): Initialize bmRep.
(dealloc): Release bmRep.
@@ -45,41 +951,304 @@
(setPixmapData): Rename local variable bmRep to avoid compiler
warning.
-2014-12-24 Jan Djärv <jan.h.d@swipnet.se>
+2014-12-27 Jan Djärv <jan.h.d@swipnet.se>
- * nsterm.h (EmacsImage): Remove imageListNext, refCount, reference,
- imageListSetNext, imageListNext.
+ * xterm.c (do_ewmh_fullscreen): Don't remove maximized_horz/vert
+ when going to fullscreen (Bug#0x180004f).
- * nsimage.m (ImageList, imageListNext, imageListSetNext:)
- (reference): Remove.
- (allocInitFromFile:): Remove searching ImageList and calling
- reference (Bug#18918).
- (dealloc): Remove handling if ImageList.
+2014-12-27 Eli Zaretskii <eliz@gnu.org>
+
+ * window.c (Fwindow_body_width): Doc fix. (Bug#19395)
+
+2014-12-27 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * buffer.c (syms_of_buffer) <Vafter_change_functions>: fix docstring.
+
+2014-12-27 Eli Zaretskii <eliz@gnu.org>
+
+ * gnutls.c (gnutls_init): Fix deprecation warning from GCC.
+
+2014-12-26 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xselect.c, xsettings.c
+ * xselect.c (x_get_local_selection, struct selection_data)
+ (x_selection_request_lisp_error, struct prop_location)
+ (x_handle_selection_request, x_convert_selection)
+ (waiting_for_other_props_on_window, expect_property_change)
+ (wait_for_property_change, x_handle_property_notify)
+ (x_get_foreign_selection, x_get_window_property)
+ (receive_incremental_selection)
+ (x_get_window_property_as_lisp_data)
+ (lisp_data_to_selection_data, Fx_get_selection_internal)
+ (x_send_client_event):
+ * xselect.c, xterm.h (x_handle_dnd_message):
+ * xsettings.c (dpyinfo_valid, parse_settings, read_settings)
+ (apply_xft_settings, read_and_apply_settings)
+ (xft_settings_event, init_gsettings, init_xsettings)
+ (syms_of_xsettings):
+ Use bool for boolean.
+ * xselect.c (x_get_window_property): Omit last arg, which was an
+ unused boolean.
+ * xsettings.c (apply_xft_settings): Remove 2nd arg, which was
+ always true. All callers changed.
+
+2014-12-26 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (sys_spawnve, get_lcid_callback): Use strcpy instead
+ of strcat.
+
+ * w32menu.c (add_menu_item): Use stpcpy instead of strcat.
+
+ * w32.c (sys_readdir, stat_worker, symlink): Use strcpy instead of
+ strcat.
+
+2014-12-26 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xsmfns.c
+ * xsmfns.c, xterm.h (x_session_have_connection):
+ * xsmfns.c (doing_interact, smc_interact_CB, Fhandle_save_session):
+ Use bool for boolean.
+ (x_session_initialize, Fhandle_save_session):
+ Prefer NILP (x) to EQ (x, Qnil).
+
+2014-12-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ * callproc.c (child_setup):
+ * dbusbind.c (xd_signature_cat):
+ * doc.c (get_doc_string, Fsnarf_documentation):
+ * editfns.c (Fuser_full_name):
+ * frame.c (xrdb_get_resource):
+ * gtkutil.c (xg_get_file_with_chooser):
+ * tparam.c (tparam1):
+ * xfns.c (xic_create_fontsetname):
+ * xrdb.c (gethomedir, get_user_db, get_environ_db):
+ * xsmfns.c (smc_save_yourself_CB):
+ Rewrite to avoid the need for strcat, typically by using stpcpy
+ and/or lispstpcpy. strcat tends to be part of O(N**2) algorithms.
+ * doc.c (sibling_etc):
+ * xrdb.c (xdefaults):
+ Now a top-level static constant.
+
+2014-12-23 Didier Verna <didier@didierverna.net> (tiny change).
+
+ * nsselect.m (Fns_selection_owner_p): Return a Lisp boolean, not a
+ C one (Bug#19396).
2014-12-22 Jan Djärv <jan.h.d@swipnet.se>
- * xterm.c (do_ewmh_fullscreen): Don't remove maximized_horz/vert
- when going to fullscreen (Bug#19427).
+ * xterm.c (x_bitmap_icon): Partly revert change from 2014-03-21 which
+ breaks icon setting for Gtk+ except for initial frame (Bug#19403).
+
+2014-12-22 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for boolean in xterm.c
+ * frame.h, nsterm.m, w32term.c, w32term.h, xterm.c:
+ (x_set_window_size, x_bitmap_icon):
+ * nsterm.m (ns_frame_raise_lower, x_new_font):
+ * termhooks.h (struct terminal.toggle_invisible_pointer_hook)
+ (struct terminal.frame_raise_lower_hook):
+ * w32term.c (w32_frame_raise_lower):
+ * xterm.c, xterm.h (x_text_icon):
+ * xterm.c (x_update_window_begin, x_update_window_end)
+ (x_update_end, x_after_update_window_line)
+ (x_set_glyph_string_gc, x_draw_glyph_string_background)
+ (x_draw_glyph_string_foreground)
+ (x_draw_composite_glyph_string_foreground)
+ (x_alloc_lighter_color, x_draw_relief_rect)
+ (x_draw_glyph_string_box, x_draw_image_relief)
+ (x_draw_image_glyph_string, x_draw_stretch_glyph_string)
+ (x_draw_underwave, x_draw_glyph_string, x_show_hourglass)
+ (x_hide_hourglass):
+ (XFillRectangle) [HAVE_GTK3]:
+ (XTtoggle_invisible_pointer, frame_highlight, frame_unhighlight)
+ (x_focus_changed, x_find_modifier_meanings, note_mouse_movement)
+ (XTmouse_position, xt_action_hook, xt_horizontal_action_hook)
+ (x_send_scroll_bar_event, xm_scroll_callback)
+ (xg_scroll_callback, xaw_jump_callback, xaw_scroll_callback)
+ (x_create_toolkit_scroll_bar)
+ (x_create_horizontal_toolkit_scroll_bar)
+ (x_set_toolkit_horizontal_scroll_bar_thumb, x_scroll_bar_create)
+ (x_scroll_bar_set_handle, XTset_vertical_scroll_bar)
+ (XTset_horizontal_scroll_bar, x_scroll_bar_expose)
+ (x_scroll_bar_handle_click, x_scroll_bar_note_movement)
+ (x_scroll_bar_report_motion)
+ (x_horizontal_scroll_bar_report_motion, x_net_wm_state)
+ (handle_one_xevent, XTread_socket, x_draw_bar_cursor)
+ (x_draw_window_cursor, x_clear_errors)
+ (x_trace_wire, x_new_font, x_set_offset, wm_supports)
+ (set_wm_state, x_set_sticky, get_current_wm_state)
+ (do_ewmh_fullscreen, x_handle_net_wm_state)
+ (x_check_expected_move, x_sync_with_move, x_wait_for_event)
+ (x_set_window_size_1, XTframe_raise_lower)
+ (x_make_frame_visible, x_iconify_frame)
+ (x_timeout_atimer_activated_flag, same_x_server, x_display_ok)
+ (x_term_init, x_process_timeouts, x_activate_timeout_atimer)
+ (x_delete_terminal, x_initialize, syms_of_xterm):
+ Use bool for boolean.
+
+2014-12-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ * composite.h (struct composition.width): Now int
+ instead of unsigned short, as we prefer signed integers.
+
+ Let charset tick grow past USHRT_MAX
+ * charset.c, charset.h (charset_ordered_list_tick):
+ Now EMACS_UINT, not unsigned short.
+ * fontset.c (reorder_font_vector): Allow the tick to grow to the
+ maximum representable Emacs integer value before wrapping it around.
+
+ Simplify unexec file mode setting
+ * unexaix.c, unexcoff.c, unexelf.c, unexmacosx.c:
+ Don't include <sys/stat.h> when no longer needed.
+ (unexec): Create file with correct mode in the first place,
+ rather than overwriting the mode later and fiddling with the
+ global umask in the mean time. Avoid bogus usage like
+ 'umask (777)', which should have been 'umask (0777)'.
+ (mark_x): Remove. All callers removed.
+
+2014-12-19 Paul Eggert <eggert@cs.ucla.edu>
+
+ Minor cleanups for Lisp objects and symbols
+ * alloc.c (next_vector, set_next_vector):
+ * lisp.h (lisp_h_INTEGERP, make_number, XFASTINT, make_natnum):
+ (lisp_h_make_number) [USE_LSB_TAG]:
+ Use Lisp_Int0 instead of the mystery constant 0.
+ * alloc.c (mark_object): Always set and use po; that's simpler.
+ (CHECK_LIVE, CHECK_ALLOCATED_AND_LIVE):
+ Properly parenthesize definientia.
+ * bidi.c (bidi_initialize):
+ * buffer.c (init_buffer_once):
+ * nsfns.m (syms_of_nsfns):
+ * nsmenu.m (syms_of_nsmenu):
+ * nsselect.m (syms_of_nsselect):
+ Prefer DEFSYM to defining by hand.
+ * buffer.c (syms_of_buffer): Omit unneeded staticpros.
+ * data.c: Fix too-long line.
+ * lisp.h (DECLARE_GDB_SYM): New macro.
+ (DEFINE_GDB_SYMBOL_BEGIN): Use it.
+ (DEFINE_GDB_SYMBOL_BEGIN, DEFINE_GDB_SYMBOL_END) [!MAIN_PROGRAM]:
+ Declare the symbol, so it's visible to everywhere lisp.h is included.
+ Move forward decls as far forward as they can go,
+ to allow future changes to use them.
+
+2014-12-18 Paul Eggert <eggert@cs.ucla.edu>
+
+ * gnutls.c: Include gnutls.h.
+ This to check syms_of_gnutls's API even when !HAVE_GNUTLS.
+ * image.c (svg_load): Fix pointer signedness.
+
+2014-12-18 Martin Rudalics <rudalics@gmx.at>
+
+ * frame.c (frame_windows_min_size): New argument IGNORE.
+ (adjust_frame_size): When called from change_frame_size call
+ frame_windows_min_size with IGNORE Qt so we can ignore size
+ restrictions.
2014-12-18 Eli Zaretskii <eliz@gnu.org>
- * window.c (Fwindow_body_width): Doc fix. (Bug#19395)
+ * font.c (Ffont_info): Add more font information to the vector
+ returned by the function, inspired by query-font. Doc fix.
+ (Bug#19395)
+
+2014-12-18 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * keyboard.c (input_was_pending): New var.
+ (read_char): Use it to make sure we only skip redisplay when we can't
+ keep up with the repeat rate.
+
+2014-12-17 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * keyboard.c (swallow_events): Don't redisplay if there's input pending.
+
+2014-12-17 Ulf Jasper <ulf.jasper@web.de>
+
+ * image.c (svg_load): Watch out for nil value of current buffer's
+ filename. Re-enable filename thing for not-a-file case.
+
+2014-12-17 Ulf Jasper <ulf.jasper@web.de>
+
+ Partially disabled previous change.
+
+ * image.c (svg_load): Temporarily disabled filename thing for
+ not-a-file case as it can cause crashs.
+
+2014-12-17 Ulf Jasper <ulf.jasper@web.de>
+
+ Fix problem with images referenced within svg files. (bug#19373)
+
+ * image.c: Additional parameter 'filename' for
+ svg_load_image. Include "buffer.h". Define library function
+ rsvg_handle_set_base_uri for WINDOWSNT.
+ (init_svg_functions): Initialize rsvg_handle_set_base_uri.
+ (fn_rsvg_handle_set_base_uri): Define fn_rsvg_handle_set_base_uri.
+ (svg_load): Pass a filename to svg_load_image: either name of
+ actual file or of current buffer's file.
+ (svg_load_image): New parameter 'filename', used for setting
+ base_uri, necessary for loading referenced images. (bug#19373)
+
+2014-12-16 Paul Eggert <eggert@cs.ucla.edu>
+
+ * lread.c (init_obarray): Declare Qt as special.
+ This fixes a typo in the 2012-05-15 patch that
+ tried to declare Qt as special.
2014-12-15 Stefan Monnier <monnier@iro.umontreal.ca>
- * buffer.c (syms_of_buffer) <Vafter_change_functions>: fix docstring.
+ Various fixes to use bool type and constants.
+ * dispnew.c (update_single_window): Remove arg `force_p' since it's
+ always true.
+ * xfaces.c (clear_face_cache): Use bool for the argument type.
-2014-12-13 Eli Zaretskii <eliz@gnu.org>
+2014-12-15 Paul Eggert <eggert@cs.ucla.edu>
- * gnutls.c (gnutls_init): Fix deprecation warning from GCC.
+ Correct same_at_end when restoring window points
+ * fileio.c (Finsert_file_contents): Compute same_at_end character
+ position using the old buffer size, not the new one, since
+ restore_window_points wants the old size.
+ Fixes: debbugs:19161
+
+2014-12-14 Alan Mackenzie <acm@muc.de>
+
+ New feature optionally to accelerate auto-repeated scrolling.
+
+ * xdisp.c: Remove "static" from declaration of Qfontification_functions.
+
+ * window.c (window_scroll): Bind fontification-functions to nil
+ when scrolling by whole screens and
+ fast-but-imprecise-scrolling is non-nil.
+ (syms_of_window): New DEFVAR_BOOL fast-but-imprecise-scrolling.
+
+ * lisp.h (bool): Declare Qfontification_functions extern.
-2014-12-12 Eli Zaretskii <eliz@gnu.org>
+2014-12-14 Eli Zaretskii <eliz@gnu.org>
+
+ Load system's default trusted Certificate Authorities if available.
+ * gnutls.c (gnutls_certificate_set_x509_system_trust)
+ [GNUTLS >= 3.0.20]: Declare for WINDOWSNT.
+ (init_gnutls_functions)(gnutls_certificate_set_x509_system_trust)
+ [GNUTLS >= 3.0.20]: Load from shared library for WINDOWSNT.
+ (fn_gnutls_certificate_set_x509_system_trust) [!WINDOWSNT]:
+ Define new macro.
+ (Fgnutls_boot) [GNUTLS >= 3.0.20]:
+ Call gnutls_certificate_set_x509_system_trust. Log an error message if
+ it fails.
+
+2014-12-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ * regex.c (analyze_first): Rename from analyze_first.
+
+2014-12-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ * alloc.c (XMALLOC_BASE_ALIGNMENT): Use max_align_t instead of
+ a hack involving a union.
+
+2014-12-13 Eli Zaretskii <eliz@gnu.org>
* gnutls.c (Fgnutls_available_p, syms_of_gnutls):
Move gnutls-available-p out of the HAVE_GNUTLS conditional, and define
them only once.
-2014-12-11 Teodor Zlatanov <tzz@lifelogs.com>
+2014-12-13 Teodor Zlatanov <tzz@lifelogs.com>
* emacs.c (main): Always include gnutls.h and run syms_of_gnutls.
@@ -90,18 +1259,107 @@
integration is not available, instead of erroring out.
(Bug#19346)
-2014-12-10 Eli Zaretskii <eliz@gnu.org>
+2014-12-13 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (move_it_in_display_line_to, display_line):
Don't disallow overflow-newline-into-fringe when word-wrap is in
effect. (Bug#19300)
-2014-12-04 Lee Duhem <lee.duhem@gmail.com> (tiny change)
+2014-12-11 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * fileio.c: Better preserve window-points during revert (bug#19161).
+ (Qget_buffer_window_list): New var.
+ (get_window_points_and_markers, restore_window_points): New functions.
+ (Finsert_file_contents): Use them to save and restore window-points.
+
+2014-12-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xterm.c (x_delete_terminal): Call emacs_close for X connection
+ descriptor if called from x_connection_closed and always delete
+ this descriptor from keyboard waiting set (Bug#19147).
+
+2014-12-10 Eli Zaretskii <eliz@gnu.org>
+
+ * bidi.c (BIDI_CACHE_MAX_ELTS_PER_SLOT): New macro.
+ (bidi_cache_max_elts): New global variable.
+ (bidi_shelve_header_size): Add the sizeof bidi_cache_max_elts.
+ (bidi_cache_shrink, bidi_initialize): Reset bidi_cache_max_elts to
+ its initial value.
+ (bidi_cache_search): Handle overflown cache. Improve commentary.
+ (bidi_cache_ensure_space): Limit allocations to the current value
+ of bidi_cache_max_elts. Force xpalloc not to over-allocate.
+ If less than a full BIDI_CACHE_CHUNK is left to the limit, decrease
+ the increment to not exceed the limit.
+ (bidi_cache_iterator_state): Now returns non-zero if succeeded to
+ cache, zero otherwise (meaning the cache overflowed). In the
+ latter case, set bidi_cache_last_idx to -1.
+ (bidi_peek_at_next_level): Handle overflown cache.
+ (bidi_push_it): Increase the cache limit for iterating the new object.
+ (bidi_pop_it): Decrease the cache limit back to previous value.
+ (bidi_shelve_cache): Shelve the current value of the cache limit.
+ (bidi_unshelve_cache): Restore the value of cache limit.
+ (bidi_find_bracket_pairs): If the cache overflows while looking
+ for the paired bracket, give up and let bidi_resolve_neutrals
+ process the bracket as a simple neutral. (Bug#19322)
+ (bidi_find_other_level_edge): If the cache overflows, fall back on
+ Plan B, which effectively stops the reordering and restarts it on
+ the next character (after resetting the cache).
+ (bidi_move_to_visually_next): When the cache overflows, reset it
+ after processing the last cached character.
+
+2014-12-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix glitches in gnutls.c, mostly memory-related
+ * gnutls.c: Sort macro definitions by name.
+ (fn_gnutls_transport_set_errno): Omit unreachable definition.
+ (fn_gnutls_x509_crt_get_signature): Omit unused symbol.
+ (gnutls_hex_string): Arg is now unsigned char *, to avoid a cast.
+ Prefer ptrdiff_t for sizes. Check for arithmetic overflow when
+ calculating string length. Use make_uninit_string, to avoid
+ copying the string. Cast the char, not the pointer.
+ (gnutls_certificate_details): Use xmalloc and xfree, not malloc
+ and free. Work even for dates past the year 9999. Use void *
+ for buffers, to avoid casts.
+
+2014-12-09 Andy Moreton <andrewjmoreton@gmail.com> (tiny change)
+
+ * gnutls.c (gnutls_protocol_get_name): Fix a copy/paste typo.
+
+2014-12-08 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnutls.c (Fgnutls_peer_status): Return the key exchange, cipher
+ and MAC algorithms.
+
+2014-12-08 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * process.c: Whitespace and line-break nitpicks.
+
+2014-12-08 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnutls.c (gnutls_certificate_details): The :signature isn't
+ that useful, so remove it.
+ (gnutls_certificate_details): Clean up whitespace slightly.
+ (Fgnutls_peer_status): Return the Diffie-Hellman prime bits for
+ the connection.
+ (gnutls_certificate_details): Put :signature-algorithm back again,
+ which was removed by mistake.
+ (emacs_gnutls_handle_error): Fatal errors should be on level 1, so
+ that they are not messaged by default (bug#16253).
+ (Fgnutls_error_fatalp): Doc fix (bug#18210).
+
+ * gnutls.c: Add Windows specs for gnutls_dh_get_prime_bits.
+
+2014-12-07 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsimage.m (setPixmapData): Make bmRep local so class member is not
+ set (Bug#19133).
+
+2014-12-05 Lee Duhem <lee.duhem@gmail.com> (tiny change)
* eval.c (Fsignal): Remove duplicate test.
(Fautoload_do_load): Fix up docstring.
-2014-12-02 Jan Djärv <jan.h.d@swipnet.se>
+2014-12-05 Jan Djärv <jan.h.d@swipnet.se>
* nsterm.m (represented_filename, represented_frame): New variables.
(ns_set_represented_filename): New function.
@@ -113,67 +1371,291 @@
* nsfns.m (ns_set_name_as_filename): Don't set represented filename
at once, call ns_set_represented_filename instead.
-2014-11-27 Eli Zaretskii <eliz@gnu.org>
+2014-12-05 Eli Zaretskii <eliz@gnu.org>
+
+ * dispextern.h (enum bidi_dir_t): Force NEUTRAL_DIR to be zero.
+ (struct bidi_stack): Reduce size by using bit fields and by
+ packing sos, override, and isolate_status into a single 8-bit
+ byte called 'flags'.
+
+ * bidi.c (ISOLATE_STATUS, OVERRIDE): New macros.
+ (bidi_push_embedding_level): Construct flags from individual
+ bits. Adapt to changes in prev_for_neutral and next_for_neutral
+ members.
+ (bidi_pop_embedding_level): Use ISOLATE_STATUS. Extract 'sos'
+ from flags. Adapt to changes in prev_for_neutral,
+ next_for_neutral, and last_strong members.
+ (bidi_line_init): Initialize flags to zero.
+ (bidi_resolve_explicit, bidi_resolve_weak, bidi_resolve_brackets)
+ (bidi_resolve_neutral): Use ISOLATE_STATUS and OVERRIDE.
+
+2014-12-04 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * eval.c (backtrace_eval_unrewind): Rewind also the excursions.
+ (Fapply): Try and simplify the control flow.
+
+2014-12-03 Chris Zheng <chriszheng99@gmail.com> (tiny change)
+
+ * gnutls.c (init_gnutls_functions, gnutls_certificate_details):
+ Use gnutls_sign_get_name directly because
+ gnutls_sign_algorithm_get_name is a macro on MinGW (bug#19231).
+ (init_gnutls_functions): Load missing gnutls_server_name_set.
+
+2014-12-02 Eli Zaretskii <eliz@gnu.org>
+
+ * bidi.c (bidi_find_first_overridden): New function.
+
+ * xdisp.c (Fbidi_find_overridden_directionality): New function.
+ (syms_of_xdisp): Defsubr it.
+
+ * dispextern.h (bidi_find_first_overridden): Add prototype.
+
+2014-12-02 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsimage.m (initFromSkipXBM:width:height:flip:length:): Set bmRep
+ to nil after release (Bug#9133).
+
+2014-11-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port better to AddressSanitizer.
+ These changes suffice for temacs on x86-64 with GCC 4.9.2 and
+ -fsanitize=address.
+ * alloc.c (valid_pointer_p) [ADDRESS_SANITIZER]:
+ Return -1 or 0, as the pipe trick doesn't work.
+ * alloc.c (relocatable_string_data_p, mark_object, sweep_symbols):
+ * data.c (Ffset):
+ * print.c (print_object):
+ When a pointer-check primitive returns -1, do not assume this
+ means the pointer is valid or that the underlying system has failed.
+ It could just be that addresses are being sanitized so Emacs can't
+ test for pointer validity.
+ * lisp.h (defined_GC_CHECK_STRING_BYTES): New constant.
+ (USE_STACK_STRING) [GC_CHECK_STRING_BYTES]: Now false, since the
+ string validity checker doesn't work on stack-based strings.
+
+2014-11-29 Paul Eggert <eggert@cs.ucla.edu>
+
+ Improve clarity of USE_LSB_TAG definition.
+ Reported by Lee Duhem. Suggested by Andreas Schwab in:
+ http://lists.gnu.org/archive/html/emacs-devel/2014-11/msg02222.html
+ * lisp.h (USE_LSB_TAG): Define in terms of the (simpler)
+ VAL_MAX / 2 rather than in terms of the (more complicated)
+ EMACS_INT_MAX >> GCTYPEBITS, and adjust commentary to match.
+
+2014-11-29 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (handle_single_display_spec): When ignoring a fringe
bitmap display, reset the ignore_overlay_strings_at_pos_p flag.
(next_element_from_buffer): When done with overlays, reset the
ignore_overlay_strings_at_pos_p flag. (Bug#19201)
-2014-11-25 Eli Zaretskii <eliz@gnu.org>
+2014-11-29 Eli Zaretskii <eliz@gnu.org>
* w32fns.c (Fw32_shell_execute): Convert forward slashes in
DOCUMENT to backslashes, if DOCUMENT is a file. (Bug#19141)
-2014-11-25 Ulrich Müller <ulm@gentoo.org>
+2014-11-29 Ulrich Müller <ulm@gentoo.org>
* Makefile.in (temacs$(EXEEXT)): Use consistent flag settings
for paxctl and setfattr. Fixes temacs startup failure with
grsecurity/PaX enabled Linux kernel (bug#19067).
-2014-11-17 Oscar Fuentes <ofv@wanadoo.es>
-
- * src/w32.c: Use MINGW_W64 instead of _W64.
+2014-11-27 Oscar Fuentes <ofv@wanadoo.es>
- * src/w32term.c: Likewise.
+ * w32.c, w32heap.c, w32term.c:
+ Use MINGW_W64 instead of _W64.
-2014-11-16 Stefan Monnier <monnier@iro.umontreal.ca>
+2014-11-27 Stefan Monnier <monnier@iro.umontreal.ca>
* frame.c (Fhandle_switch_frame): Deactivate shift-region (bug#19003).
-2014-11-15 Jan Djärv <jan.h.d@swipnet.se>
+2014-11-26 Lars Magne Ingebrigtsen <larsi@gnus.org>
- * nsterm.m (ns_send_appdefined): Check for application defined
- event on Cocoa (Bug#18993). Backport from trunk.
+ * gnutls.c (gnutls_ip_address_p): New function.
+ (Fgnutls_boot): Only send SNI if the host name is not an IP address.
+
+2014-11-26 Toke Høiland-Jørgensen <toke@toke.dk> (tiny change)
+
+ * gnutls.c (Fgnutls_boot): Send the server name over (bug#18208).
+
+2014-11-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix gnutls problems caught by static checking.
+ * gnutls.c (Fgnutls_boot): Remove unused local.
+ (Fgnutls_boot): Fix pointer signedness.
+
+2014-11-25 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnutls.c (gnutls_certificate_details): Don't include certain
+ certificate details on older gnutls versions (bug#19168).
+ (syms_of_gnutls): Export gnutls_peer_status_warning_describe.
+ (gnutls_certificate_details): Reversed check in last checkin.
+
+2014-11-25 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnutls.c (Fgnutls_peer_status): Check GNUTLS_INITSTAGE, not gnutls_p.
+ (Fgnutls_peer_status_warning_describe): Add function to describe a
+ peer verification warning symbol.
+ (Fgnutls_peer_status): Use it.
+ (Fgnutls_boot): Use it. Minor logging fixes.
+
+2014-11-24 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnutls.c: Fix compilation warnings given fix --enable-gcc-warnings.
+
+2014-11-24 Glenn Morris <rgm@gnu.org>
+
+ * emacs.c (main) <--version>: Make use of PACKAGE_NAME.
+
+ * Makefile.in (emacs.res): Use ../nt rule, rather than duplicating it.
+ (ntsource, WINDRES, EMACS_MANIFEST): Remove, now unused.
+
+2014-11-23 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * gnutls.c: Fix Windows function definition of
+ gnutls_x509_crt_get_fingerprint.
+
+ * gnutls.c: Fix Windows return value for gnutls_pk_algorithm_get_name.
+
+ * gnutls.c (Fgnutls_boot): Save certificate for later inspection.
+
+ * process.h: Added more fields to Lisp_Process to track
+ certificate details.
+
+ * gnutls.c (gnutls_hex_string, gnutls_certificate_details)
+ (Fgnutls_peer_status): New functions to export TLS certificate
+ details to Emacs Lisp.
+
+2014-11-23 Jan Djärv <jan.h.d@swipnet.se>
+
+ * gtkutil.c (gtk_adjustment_configure): Define for Gtk+ < 2.14.
+ (xg_set_toolkit_horizontal_scroll_bar_thumb): Remove wrong version
+ check for gtk_adjustment_configure (Bug#19149).
+ (gtk_adjustment_configure): Don't use 2.14 functions (Bug#19149).
-2014-11-15 Eli Zaretskii <eliz@gnu.org>
+2014-11-22 Glenn Morris <rgm@gnu.org>
+
+ * Makefile.in (emacs.res): Add dependency on icons/hand.cur. Use $<.
+
+2014-11-22 Martin Rudalics <rudalics@gmx.at>
+
+ Don't shrink frame when using desktop-save-mode (Bug#19048).
+ * w32fns.c (x_set_tool_bar_lines): Always call
+ x_change_tool_bar_height (Bug#19048).
+ (x_change_tool_bar_height): Mark frame as garbaged since
+ adjust_frame_size might not have done that.
+ * xfns.c (x_set_tool_bar_lines): Always call
+ x_change_tool_bar_height (Bug#19048).
+ (x_change_tool_bar_height): Mark frame as garbaged since
+ adjust_frame_size might not have done that.
+
+2014-11-21 Ulf Jasper <ulf.jasper@web.de>
+
+ * xml.c (parse_region): Take care of new optional parameter
+ 'discard-comments' of 'libxml-parse(html|xml)-region'.
+ (Flibxml_parse_html_region, Flibxml_parse_xml_region):
+ New optional parameter 'discard-comments'.
+
+2014-11-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ Improve time stamp handling, and be more consistent about it.
+ * editfns.c (invalid_time): New function.
+ Use it instead of 'error ("Invalid time specification")'.
+ (time_add, time_subtract, time_arith, Ftime_add, Ftime_less_p)
+ (decode_float_time, lisp_to_timespec, lisp_time_struct):
+ New functions.
+ (make_time_tail, make_time): Remove. All uses changed to use
+ new functions or plain list4i.
+ (disassemble_lisp_time): Return effective length if successful.
+ Check that LOW is an integer, if it's combined with other components.
+ (decode_time_components): Decode into struct lisp_time, not
+ struct timespec, so that we can support a wide set of times
+ regardless of whether time_t is signed. Decode plain numbers
+ as seconds since the Epoch, and nil as the current time.
+ (lisp_time_argument, lisp_seconds_argument, Ffloat_time):
+ Reimplement in terms of new functions.
+ (Fencode_time): Just use list2i.
+ (syms_of_editfns): Add time-add, time-subtract, time-less-p.
+ * keyboard.c (decode_timer): Don't allow the new formats (floating
+ point or nil) in timers.
+ * systime.h (LO_TIME_BITS): New constant. Use it everywhere in
+ place of the magic number '16'.
+ (struct lisp_time): New type.
+ (decode_time_components): Use it.
+ (lisp_to_timespec): New decl.
+
+2014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org>
+
+ * intervals.h (INTERVAL_WRITABLE_P): Check the `inhibit-read-only'
+ text property.
+
+ * callint.c (Fcall_interactively): Pass in nil as argument to
+ Fbarf_if_buffer_read_only.
+
+ * fileio.c (Finsert_file_contents): Ditto.
+
+ * insdel.c (prepare_to_modify_buffer_1): Pass start region in.
+
+ * textprop.c (verify_interval_modification): Check buffer
+ readedness after the last interval.
+
+ * buffer.c (Fbarf_if_buffer_read_only): Don't raise an error if
+ the text at POSITION (new optional argument) has the
+ `inhibit-read-only' text property set.
+
+2014-11-16 Eli Zaretskii <eliz@gnu.org>
* window.c (window_scroll_pixel_based): Avoid truncation/rounding
errors in computing the number of pixels to scroll.
Suggested by Kelly Dean <kelly@prtime.org>. (Bug#19060)
-2014-11-15 Jan Djärv <jan.h.d@swipnet.se>
+2014-11-16 Jan Djärv <jan.h.d@swipnet.se>
* nsmenu.m (update_frame_tool_bar): If tool bar changes height,
call updateFrameSize.
* nsterm.m (setFrame:): Remove call to display (Bug#18757).
-2014-11-14 Jan Djärv <jan.h.d@swipnet.se>
+2014-11-16 Jan Djärv <jan.h.d@swipnet.se>
* nsfns.m (x_set_foreground_color, x_set_background_color)
(x_set_cursor_color, Fxw_color_values): Block/unblock input,
use SET_FRAME_GARBAGED instead of redraw_frame (Bug#19036).
-2014-11-09 Eli Zaretskii <eliz@gnu.org>
+2014-11-15 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_send_appdefined): Check for application defined
+ event on Cocoa (Bug#18993).
+ (run): Restore code before the previous 18993 fix.
+
+2014-11-14 David Reitter <david.reitter@gmail.com>
+
+ * nsterm.m (run): Set timeout for event loop to prevent hang.
+ (Bug#18993)
+
+2014-11-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ * .gitignore: Add emacs-[1-9]*, to ignore files like emacs-25.0.50.1.
+
+2014-11-14 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xfont.c (xfont_list_pattern): Do not allocate font entity object
+ for each candidate font but attempt to reuse it from previous improper
+ candidate, if any.
+
+2014-11-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ Avoid undefined behavior in color table hashing.
+ * image.c (CT_HASH_RGB) [COLOR_TABLE_SUPPORT]: Remove, replacing with ...
+ (ct_hash_rgb) [COLOR_TABLE_SUPPORT]: New function. All uses changed.
+ This function avoids undefined behavior with signed shift overflow.
+
+2014-11-10 Eli Zaretskii <eliz@gnu.org>
* fileio.c (Finsert_file_contents): Invalidate buffer caches also
when the inserted text does not need decoding. (Bug#18982)
- * w32heap.c (allocate_heap): Set the lower limit of heap at 8MB.
- (Bug#18995)
-
-2014-11-09 Jan Djärv <jan.h.d@swipnet.se>
+2014-11-10 Jan Djärv <jan.h.d@swipnet.se>
* nsterm.h (EmacsScroller): judge returns bool.
@@ -182,32 +1664,144 @@
(judge): Returns bool == condemned. Remove self from window.
(setPosition:portion:whole:): Remove raise SIGIO (Bug#18757).
+2014-11-10 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * keyboard.c (command_loop_1): Record this-command in recent-keys.
+ (Frecent_keys): Rewrite. and add optional `include-cmds' arg.
+
+2014-11-09 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_set_vertical_scroll_bar)
+ (ns_set_horizontal_scroll_bar): Cleanup merge error.
+
+2014-11-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ * xgselect.c (xg_select): Don't assume n_gfds is nonnegative
+ merely because tmo_in_millisec is nonnegative. The 1st call
+ to g_main_context_query could succeed while the 2nd one fails.
+
+ * frame.c (Fcan_run_window_configuration_change_hook): Return a value.
+
2014-11-08 Jan Djärv <jan.h.d@swipnet.se>
- * nsterm.m (init): Replace OSX 10.9 check with IMPL_COCOA.
- (run): Ditto. Only use non-system event loop if OSX version is
+ * nsterm.m (run): Only use non-system event loop if OSX version is
exactly 10.9 (Bug#18993).
(ns_set_vertical_scroll_bar): Don't call bar setPosition: unless
needed (Bug#18757).
-2014-11-07 Michael Albinus <michael.albinus@gmx.de>
+2014-11-08 Michael Albinus <michael.albinus@gmx.de>
* callproc.c (encode_current_directory): Support handling of file
names prepended by "/:". (Bug#18891)
-2014-11-06 Alan Mackenzie <acm@muc.de>
+2014-11-08 Alan Mackenzie <acm@muc.de>
* syntax.c (back_comment): Fix off-by-one error (bug#18022).
-2014-11-06 Dima Kogan <dima@secretsauce.net>
+2014-11-08 Dima Kogan <dima@secretsauce.net>
* xgselect.c (xg_select): Use g_main_context_acquire (bug#18861).
-2014-11-05 Michael Albinus <michael.albinus@gmx.de>
+2014-11-08 Michael Albinus <michael.albinus@gmx.de>
* dired.c (Ffile_attributes): Return Qnil, if Fexpand_file_name
raises an error. (Bug#18891)
+2014-11-08 Martin Rudalics <rudalics@gmx.at>
+
+ * frame.c (adjust_frame_size): Call x_set_window_size only if
+ f->can_x_set_window_size is set.
+ (make_frame): Initialize f->can_x_set_window_size and
+ f->can_run_window_configuration_change_hook.
+ (Fcan_run_window_configuration_change_hook): New function.
+ * frame.h (frame): Split `official' into `can_x_set_window_size'
+ and `can_run_window_configuration_change_hook'.
+ * nsfns.m (Fx_create_frame): Set f->can_x_set_window_size.
+ * w32fns.c (Fx_create_frame, x_create_tip_frame):
+ Set f->can_x_set_window_size.
+ * window.c (run_window_configuration_change_hook):
+ Return immediately if either f->can_x_set_window_size or
+ f->can_run_window_configuration_change_hook are false.
+ (Fset_window_configuration): Instead of f->official set
+ f->can_x_set_window_size.
+ * xfns.c (Fx_create_frame, x_create_tip_frame):
+ Set f->can_x_set_window_size.
+
+2014-11-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (EmacsScroller.dealloc): Reinstate, removed at merge
+ cleanup from 2014-11-01 (Bug#18972).
+
+2014-11-07 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * keyboard.c: Call gui-set-selection instead of x-set-selection.
+ * xdisp.c (window-scroll-functions): Improve docstring.
+
+2014-11-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ Uniquify the 'size' symbol.
+ * frame.c (Qsize):
+ * w32notify.c (Qsize): Remove.
+ * lisp.h (Qsize): New decl.
+ * lread.c (Qsize): Now extern.
+ * w32notify.c (syms_of_w32notify): No need to defsym.
+
+2014-11-07 Martin Rudalics <rudalics@gmx.at>
+
+ * dispnew.c (change_frame_size_1): Fix call of
+ adjust_frame_size.
+ * frame.c (Qsize, Qframe_position, Qframe_outer_size)
+ (Qframe_inner_size, Qexternal_border_size, Qtitle_height)
+ (Qmenu_bar_external, Qmenu_bar_size, Qtool_bar_external)
+ (Qtool_bar_size): New constants.
+ (frame_inhibit_resize, adjust_frame_size): New argument to
+ handle case where frame_inhibit_implied_resize is a list.
+ (Fmake_terminal_frame, Fset_frame_height, Fset_frame_width)
+ (Fset_frame_size, x_set_left_fringe, x_set_right_fringe)
+ (x_set_right_divider_width, x_set_bottom_divider_width)
+ (x_set_vertical_scroll_bars, x_set_horizontal_scroll_bars)
+ (x_set_scroll_bar_width, x_set_scroll_bar_height):
+ Update callers.
+ (frame-inhibit-implied-resize): Rewrite doc-string.
+ * frame.h (frame_inhibit_resize, adjust_frame_size):
+ Fix external declarations.
+ (Qframe_position, Qframe_outer_size)
+ (Qframe_inner_size, Qexternal_border_size, Qtitle_height)
+ (Qmenu_bar_external, Qmenu_bar_size, Qtool_bar_external)
+ (Qtool_bar_size): Extern them.
+ * gtkutil.c (FRAME_TOTAL_PIXEL_HEIGHT, FRAME_TOTAL_PIXEL_WIDTH)
+ (xg_height_or_width_changed): Remove.
+ (xg_frame_set_char_size): Adjust adjust_frame_size calls.
+ (menubar_map_cb, xg_update_frame_menubar, free_frame_menubar)
+ (tb_size_cb, update_frame_tool_bar, free_frame_tool_bar)
+ (xg_change_toolbar_position): Call adjust_frame_size directly.
+ * nsfns.m (x_set_internal_border_width, Fx_create_frame):
+ Fix calls of adjust_frame_size.
+ * w32fns.c (x_set_internal_border_width, x_set_menu_bar_lines)
+ (Fx_create_frame, x_create_tip_frame): Adjust adjust_frame_size calls.
+ (x_set_tool_bar_lines, x_change_tool_bar_height): Make sure that
+ frame can get resized when tool-bar-lines parameter changes from
+ or to zero.
+ (Fw32_frame_menu_bar_size): Return fourth value.
+ (Fw32_frame_rect): Block input around system calls
+ (Fx_frame_geometry): New function.
+ * w32menu.c (set_frame_menubar): Adjust adjust_frame_size call.
+ * w32term.c (x_new_font): Adjust adjust_frame_size call.
+ * widget.c (EmacsFrameSetCharSize): Adjust frame_inhibit_resize call.
+ * window.c (Fset_window_configuration): Adjust adjust_frame_size call.
+ * xfns.c (x_set_menu_bar_lines, x_set_internal_border_width)
+ (Fx_create_frame): Adjust adjust_frame_size calls.
+ (x_set_tool_bar_lines, x_change_tool_bar_height): Make sure that
+ frame can get resized when tool-bar-lines parameter changes from
+ or to zero.
+ (Fx_frame_geometry): New function.
+ * xmenu.c (update_frame_menubar): On Lucid call
+ adjust_frame_size with one pixel less height to avoid that
+ repeatedly adding/removing the menu bar grows the frame.
+ (free_frame_menubar): On Motif arrange to optionally preserve
+ the old frame height when removing the menu bar.
+ * xterm.c (x_new_font): Adjust adjust_frame_size call.
+
2014-11-03 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (Fdump_glyph_matrix, Fdump_frame_glyph_matrix): Doc fix.
@@ -218,18 +1812,37 @@
* nsfns.m (ns_set_doc_edited): Check for FRAME_NS (Bug#18925).
-2014-10-31 Jan Djärv <jan.h.d@swipnet.se>
+2014-11-02 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsimage.m (allocInitFromFile:): Initialize bmRep.
+ (dealloc): Release bmRep.
+
+ * nsterm.h (EmacsImage): Remove imageListNext, refCount, reference,
+ imageListSetNext, imageListNext.
+
+ * nsimage.m (ImageList, imageListNext, imageListSetNext:)
+ (reference): Remove.
+ (allocInitFromFile:): Remove searching ImageList and calling
+ reference (Bug#18918).
+ (dealloc): Remove handling if ImageList.
+
+2014-11-02 Andreas Schwab <schwab@linux-m68k.org>
+
+ * process.c (catch_child_signal): Fix incorrect assertion.
+
+2014-11-01 Jan Djärv <jan.h.d@swipnet.se>
+
+ * macfont.m (macfont_draw):
+ * nsterm.m (ns_mouse_position, judge): Clean up merge conflict.
- * macfont.m (macfont_glyph_extents): Turn off syntetic bold
+ * macfont.m (macfont_glyph_extents): Turn off synthetic bold
if force_integral_p (i.e. no antialias).
- (macfont_draw): Check ns_antialias_text, also turn off syntetic
+ (macfont_draw): Check ns_antialias_text, also turn off synthetic
bold if no antialias (Bug#18876).
* emacs.c (main): Don't chdir to $HOME on Cocoa if --chdir
was given (Bug#18846).
-2014-10-30 Jan Djärv <jan.h.d@swipnet.se>
-
* nsterm.h (ns_set_doc_edited): Declare taking no args.
* nsfns.m (ns_set_doc_edited): Do all logic (check frames) here
@@ -250,41 +1863,248 @@
(getMouseMotionPart:window:x:y:): Remove, unused.
(sendScrollEventAtLoc:fromEvent:): Make Lisp_Object win from window.
-2014-10-30 Samuel Bronson <naesten@gmail.com>
+2014-11-01 Eli Zaretskii <eliz@gnu.org>
- * unexmacosx.c (copy_data_segment): Port to GCC 4.6+ (Bug#9927).
+ * keyboard.c (readable_events): When FLAGS include
+ READABLE_EVENTS_FILTER_EVENTS, ignore BUFFER_SWITCH_EVENT events.
+ This avoids returning non-nil from input-pending-p when only such
+ events are in the queue. (Bug#18856)
+
+2014-11-01 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsselect.m (QCLIPBOARD, QSECONDARY, QTEXT, QFILE_NAME)
+ (NXPrimaryPboard, NXSecondaryPboard): Declare static.
+ (Qforeign_selection): Remove.
+ (ns_get_local_selection): Identation fix.
+ (syms_of_nsselect): Remove Qforeign_selection, ns-lost-selection-hooks
+
+ * nsselect.m (ns_get_local_selection): Remove calling of
+ functions in Vselection_converter_alist (Bug#18911).
+ (syms_of_nsselect): Remove Vselection_converter_alist.
+
+2014-10-31 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * font.c (copy_font_spec): Redesign to avoid Fcopy_alist
+ and unnecessary initialization. Adjust comments.
+
+2014-10-30 Eli Zaretskii <eliz@gnu.org>
-2014-10-28 Eli Zaretskii <eliz@gnu.org>
+ * bidi.c (bidi_cache_reset_to): Invalidate bidi_cache_last_idx by
+ setting it to -1.
+ (bidi_find_bracket_pairs): Pass to bidi_cache_reset_to a relative
+ index, not an absolute one, as that's what the function expects.
+
+2014-10-30 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xfaces.c (Finternal_set_lisp_face_attribute): Don't try to realize
+ font on an initial frame when running as a daemon (Bug#18869).
+
+ * fontset.c (toplevel): Adjust comment to match 2014-06-19 change.
+
+2014-10-30 Eli Zaretskii <eliz@gnu.org>
* fileio.c (Fexpand_file_name): Use make_unibyte_string, not
build_string, when importing a home directory. (Bug#18873)
-2014-10-26 Eli Zaretskii <eliz@gnu.org>
+2014-12-27 Eli Zaretskii <eliz@gnu.org>
* dispnew.c (buffer_posn_from_coords):
Use WINDOW_WANTS_HEADER_LINE_P, not WINDOW_WANTS_MODELINE_P, to
account for the header-line height. (Bug#18839)
-2014-10-22 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
+2014-10-28 Ulf Jasper <ulf.jasper@web.de>
- * xdisp.c (draw_glyphs): Set clipping to highlight boundaries.
- [Backport]
- (erase_phys_cursor): Fix confusion between window-relative and
- text area-relative x-coordinates. [Backport]
+ * xml.c (parse_region): Do not forget the first document child.
-2014-10-20 Glenn Morris <rgm@gnu.org>
+2014-10-25 Jan Djärv <jan.h.d@swipnet.se>
- * minibuf.c (history-length): Increase default from 30 to 100.
- [Backport]
+ * nsselect.m: pasteboard_changecount is new.
+ (ns_store_pb_change_count, ns_get_pb_change_count)
+ (ns_get_our_change_count_for): New functions.
+ (ns_string_to_pasteboard_internal): Correct comment.
+ type => gtype in eassert, Call ns_store_pb_change_count.
+ (Fns_own_selection_internal): Remove data, use value (Bug#18799).
+ (Fns_disown_selection_internal, Fns_selection_owner_p):
+ Replace Vselection_alist check, with change count check.
+ (Fns_get_selection): Initialize val to Qnil. Only get local
+ selection if change counts match (Bug#18799).
+ (nxatoms_of_nsselect): Initialize pasteboard_changecount.
+
+2014-10-25 Noam Postavsky <npostavs@users.sourceforget.net>
-2014-10-20 Stefan Monnier <monnier@iro.umontreal.ca>
+ * w32proc.c (create_child): If calling a quoted batch file,
+ pass NULL for exe. (Bug#18745)
+
+2014-10-24 Eli Zaretskii <eliz@gnu.org>
+
+ * bidi.c (bidi_resolve_explicit, bidi_find_bracket_pairs)
+ (bidi_resolve_brackets): Use end of string position rather than ZV
+ when iterating over a string. (Bug#18815)
+
+2014-10-24 Martin Rudalics <rudalics@gmx.at>
+
+ * keyboard.c (make_lispy_position): Return coordinates also when
+ on scroll bars, fringes, margins or not in a window.
+ * xdisp.c (show_mouse_face): Don't change cursor face during
+ mouse tracking.
+
+2014-10-23 Martin Rudalics <rudalics@gmx.at>
+
+ * frame.c (Fset_frame_height, Fset_frame_width, Fset_frame_size)
+ (frame_resize_pixelwise, frame_inhibit_implied_resize):
+ Fix doc-strings (Bug#18789).
+
+2014-10-23 Paul Eggert <eggert@cs.ucla.edu>
+
+ * Makefile.in (ACLOCAL_INPUTS): Omit unnecessary use of 'wildcard'.
+
+2014-10-22 Eli Zaretskii <eliz@gnu.org>
+
+ Optimize redisplay of simple bracketed text.
+ * bidi.c (bidi_cache_reset_to): New function.
+ (bidi_cache_reset): Call it.
+ (bidi_init_it, bidi_line_init): Initialize the bracket_pairing_pos
+ member to -1.
+ (bidi_resolve_explicit): Reset bracket_pairing_pos and
+ bracket_enclosed_type only if bracket_pairing_pos's value is not
+ ZV.
+ (MAX_BPA_STACK): Make sure the value is signed.
+ (PUSH_BPA_STACK): If the BPA stack overflows, don't bail out, but
+ stop pushing values onto the stack.
+ (bidi_find_bracket_pairs): If the bracketed text is only on the
+ base embedding level, remove all the states cached by this
+ function from the cache, and return zero, so that the brackets in
+ this segment of text are processed as normal neutrals.
+ (bidi_resolve_brackets): Detect the brackets that are to be
+ processed as neutrals, and don't call bidi_find_bracket_pairs on
+ them. (Bug#18778)
+
+2014-10-21 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * w32select.c (Fw32_selection_exists_p): Rename from
+ Fx_selection_exists_p.
+ (syms_of_w32select): Adjust accordingly.
+
+ * w16select.c (Fw16_selection_exists_p): Rename from
+ Fx_selection_exists_p.
+ (syms_of_win16select): Adjust accordingly.
+
+ * nsselect.m (ns_get_local_selection): Signal error rather than `quit'.
+ (Fns_own_selection_internal): Tighten scoping.
+ (Fns_selection_exists_p): Rename from Fx_selection_exists_p.
+ (Fns_get_selection): Rename from Fx_get_selection_internal.
+ (Fns_get_selection_internal, Fns_store_selection_internal):
+ Remove functions.
+ (syms_of_nsselect): Adjust accordingly.
+
+2014-10-21 Martin Rudalics <rudalics@gmx.at>
+
+ * w32fns.c (Fw32_frame_menu_bar_size): New function.
+ * w32term.c (x_set_window_size): Account for wrapped menu bar
+ lines when setting up frame height (Bug#15174 and Bug#18720).
+ (w32_add_wrapped_menu_bar_lines): New variable.
+
+2014-10-21 Stefan Monnier <monnier@iro.umontreal.ca>
* xdisp.c (redisplay_window): Re-run pre-redisplay-function after we
move point.
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>
@@ -293,52 +2113,440 @@
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.
+ 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): 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>
* w32fns.c (w32_createwindow): Accept an additional argument, an
array of 2 values specifying the coordinates of the frame's
top-left corner. Use these values instead of calling x_get_arg,
which can cons Lisp objects, and therefore cannot be called except
- from the main thread. Remove redundant tests for the default values.
+ from the main thread. Remove redundant tests for the default
+ 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
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
@@ -351,7 +2559,7 @@
* 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)
@@ -364,22 +2572,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.
+ 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)
@@ -387,7 +2901,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
@@ -401,7 +2915,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.
@@ -418,7 +2932,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
@@ -432,17 +2946,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>
+
+ 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.
- * w32.c (fcntl): Support O_NONBLOCK fcntl on the write side of
- pipes.
+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
@@ -454,77 +3120,603 @@
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.
+ 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.
+ 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-18 Eli Zaretskii <eliz@gnu.org>
+2014-08-31 Ken Brown <kbrown@cornell.edu>
- * xdisp.c (handle_stop): Improve commentary.
+ * 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-28 Eli Zaretskii <eliz@gnu.org>
+
+ * 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.
@@ -535,11 +3727,184 @@
* 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
@@ -549,42 +3914,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
@@ -597,6 +4056,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.
@@ -610,30 +4105,599 @@
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).
@@ -645,7 +4709,7 @@
* 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
@@ -663,17 +4727,180 @@
row has zero buffer position as their start position.
Reported by martin rudalics <rudalics@gmx.at>.
-2014-07-16 Eli Zaretskii <eliz@gnu.org>
-
* 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
@@ -686,39 +4913,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
@@ -733,7 +5055,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
@@ -746,26 +5170,168 @@
* 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>
+
+ 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.
- * puresize.h (BASE_PURESIZE): Increase a bit. (Bug#17846)
+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>
@@ -781,17 +5347,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
@@ -801,46 +5367,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.
@@ -851,30 +5625,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.
+ 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.
@@ -883,7 +5820,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)
@@ -894,11 +5831,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.
@@ -906,13 +5843,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
@@ -923,35 +5860,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.
@@ -959,67 +6109,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>
@@ -1032,14 +6330,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):
@@ -1072,7 +6362,7 @@
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.
(tty_menu_activate): Return the cursor to the active menu item
@@ -1081,16 +6371,57 @@
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.
@@ -1107,42 +6438,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
@@ -1210,44 +6560,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
@@ -1258,8 +6621,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.
@@ -1267,10 +6628,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'.
@@ -1286,58 +6670,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.
+ 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
@@ -1345,7 +6854,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.
@@ -1373,38 +6882,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.
@@ -1417,6 +7022,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.
@@ -1426,8 +7058,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.
@@ -2169,7 +7800,7 @@
2014-01-20 Paul Eggert <eggert@cs.ucla.edu>
Avoid undefined behavior by initializing buffer redisplay bit.
- Problem reported by Dmitry Antipov in
+ Reported by Dmitry Antipov in
<http://lists.gnu.org/archive/html/emacs-devel/2014-01/msg01756.html>.
* buffer.c (Fget_buffer_create): Initialize redisplay bit.
@@ -4010,7 +9641,7 @@
2013-11-21 Paul Eggert <eggert@cs.ucla.edu>
Fix some dependency problems that cause unnecessary recompiles.
- Problem reported by RMS in
+ Reported by RMS in
<http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg00421.html>.
* Makefile.in (OLDXMENU_TARGET, OLDXMENU, OLDXMENU_DEPS)
(really-lwlib, really-oldXMenu, stamp-oldxmenu)
@@ -4755,8 +10386,7 @@
2013-10-23 Paul Eggert <eggert@cs.ucla.edu>
- Port to Solaris 10 and its bundled GCC.
- Problem reported by Timothy C. Burt.
+ Port to Solaris 10 and its bundled GCC. Reported by Timothy C. Burt.
* floatfns.c (isfinite, isnan): Redefine unconditionally.
2013-10-21 Dmitry Antipov <dmantipov@yandex.ru>
@@ -5160,7 +10790,7 @@
so it shouldn't be used all the time. Perhaps we need two
flavors of 'eassert', one for where 'assume' is far more likely
to help or to hurt; but that can be done later.
- Problem reported by Dmitry Antipov in
+ Reported by Dmitry Antipov in
<http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00276.html>.
Also, don't include <verify.h>; no longer needed.
@@ -7066,7 +12696,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>
@@ -8888,8 +14518,7 @@
2013-07-07 Paul Eggert <eggert@cs.ucla.edu>
- Port to Ubuntu 10 (Bug#14803).
- Problem reported by T.V. Raman.
+ Port to Ubuntu 10 (Bug#14803). Reported by T.V. Raman.
* process.c (close_on_exec, accept4, process_socket):
Define these if !HAVE_ACCEPT4, not if !SOCK_CLOEXEC.
@@ -9154,7 +14783,7 @@
* emacs.c (malloc_enable_thread): Hoist extern decl to top level.
(main) [HAVE_PTHREAD && !SYSTEM_MALLOC && !DOUG_LEA_MALLOC]:
Invoke malloc_enable_thread even when not interactive.
- Problem reported by Ken Brown in <http://bugs.gnu.org/14569#275>.
+ Reported by Ken Brown in <http://bugs.gnu.org/14569#275>.
* process.c (init_process_emacs) [CYGWIN]: Tickle glib even
in this case, since the underlying bug has now been fixed.
@@ -10379,7 +16008,7 @@
* unexelf.c: Don't assume ElfW (Half) fits in int.
(entry_address, find_section, unexec): Use ptrdiff_t, not int,
when dealing with ElfW (Half) values, since they can exceed 2**31
- on 64-bit OpenBSD hosts. Problem reported privately by Han Boetes.
+ on 64-bit OpenBSD hosts. Reported by Han Boetes (privately).
(entry_address): Omit unused NUM arg. All uses changed.
2013-05-07 Juri Linkov <juri@jurta.org>
diff --git a/src/ChangeLog.10 b/src/ChangeLog.10
index e77b5b33028..6eba7f06b9c 100644
--- a/src/ChangeLog.10
+++ b/src/ChangeLog.10
@@ -20769,7 +20769,7 @@
* fontset.c (syms_of_fontset): Setup Vfont_encoding_alist here.
- * editfns.c (Fformat): Convert an unibyte char argument that is
+ * editfns.c (Fformat): Convert a unibyte char argument that is
formatted by "%c" to multibyte if the total result must be a
multibyte string.
diff --git a/src/ChangeLog.8 b/src/ChangeLog.8
index c24e55fde32..aa331eafc00 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 c087f966d61..2ac34f5c44d 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -28,12 +28,11 @@ 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
VPATH = $(srcdir)
CC = @CC@
-WINDRES = @WINDRES@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
@@ -48,7 +47,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 +76,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
@@ -114,6 +114,8 @@ TEMACS_LDFLAGS = $(LD_SWITCH_SYSTEM) $(LD_SWITCH_SYSTEM_TEMACS)
## around this, newer ones setfattr. See Bug#11398 and Bug#16343.
PAXCTL = @PAXCTL@
SETFATTR = @SETFATTR@
+PAXCTL_if_present = $(or $(PAXCTL),: paxctl)
+SETFATTR_if_present = $(or $(SETFATTR),: setfattr)
## Some systems define this to request special libraries.
LIBS_SYSTEM=@LIBS_SYSTEM@
@@ -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@
@@ -259,8 +264,6 @@ W32_LIBS=@W32_LIBS@
## emacs.res if HAVE_W32
EMACSRES = @EMACSRES@
-## emacs-*.manifest if HAVE_W32
-EMACS_MANIFEST = @EMACS_MANIFEST@
## If HAVE_W32, compiler arguments for including
## the resource file in the binary.
## Cygwin: -Wl,emacs.res
@@ -286,26 +289,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 +338,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 +352,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,40 +422,42 @@ 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 \
- rm -f emacs$(EXEEXT); \
- ln temacs$(EXEEXT) emacs$(EXEEXT); \
- 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); \
- ln emacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \
- fi
+ifeq ($(CANNOT_DUMP),yes)
+ ln -f temacs$(EXEEXT) $@
+else
+ LC_ALL=C $(RUN_TEMACS) -batch -l loadup dump
+ $(PAXCTL_if_present) -zex $@
+ ln -f $@ bootstrap-emacs$(EXEEXT)
+endif
## We run make-docfile twice because the command line may get too long
## on some systems. The sed command operating on lisp.mk also reduces
@@ -455,34 +474,36 @@ 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 $@
-
-globals.h: gl-stamp; @true
+ $(AM_V_at)mv $@.tmp $@
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) >$@
+
+globals.h: gl-stamp
+ $(AM_V_GEN)cmp $< $@ >/dev/null || cp $< $@
$(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,49 +511,48 @@ $(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)" || \
- $(SETFATTR) -n user.pax.flags -v er $@
+ifneq ($(CANNOT_DUMP),yes)
+ $(PAXCTL_if_present) -r $@
+ $(SETFATTR_if_present) -n user.pax.flags -v er $@
+endif
## 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 $(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 \
- -o $@ $(ntsource)/emacs.rc
+emacs.res: FORCE
+ $(MAKE) -C ../nt ../src/emacs.res
+.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 +605,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,57 +621,43 @@ 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 EMACS="$(bootstrap_exe)" THEFILE=$< $<c
## 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
- if test "$(CANNOT_DUMP)" = "yes"; then \
- rm -f bootstrap-emacs$(EXEEXT); \
- ln temacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \
- else \
- $(RUN_TEMACS) --batch --load loadup bootstrap || exit 1; \
- test "X$(PAXCTL)" = X || $(PAXCTL) -zex emacs$(EXEEXT); \
- mv -f emacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \
- fi
+ $(MAKE) -C ../lisp update-subdirs
+ifeq ($(CANNOT_DUMP),yes)
+ ln -f temacs$(EXEEXT) $@
+else
+ $(RUN_TEMACS) --batch --load loadup bootstrap
+ $(PAXCTL_if_present) -zex emacs$(EXEEXT)
+ mv -f emacs$(EXEEXT) $@
+endif
@: 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 1c93d6d02b1..9aa94b8a559 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
@@ -225,29 +263,12 @@ no_sanitize_memcpy (void *dest, void const *src, size_t size)
#endif /* MAX_SAVE_STACK > 0 */
-static Lisp_Object Qconses;
-static Lisp_Object Qsymbols;
-static Lisp_Object Qmiscs;
-static Lisp_Object Qstrings;
-static Lisp_Object Qvectors;
-static Lisp_Object Qfloats;
-static Lisp_Object Qintervals;
-static Lisp_Object Qbuffers;
-static Lisp_Object Qstring_bytes, Qvector_slots, Qheap;
-static Lisp_Object Qgc_cons_threshold;
-Lisp_Object Qautomatic_gc;
-Lisp_Object Qchar_table_extra_slots;
-
-/* Hook run after GC has finished. */
-
-static Lisp_Object Qpost_gc_hook;
-
static void mark_terminals (void);
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 +424,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
@@ -479,8 +517,7 @@ buffer_memory_full (ptrdiff_t nbytes)
/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to
hold a size_t value and (2) the header size is a multiple of the
alignment that Emacs needs for C types and for USE_LSB_TAG. */
-#define XMALLOC_BASE_ALIGNMENT \
- alignof (union { long double d; intmax_t i; void *p; })
+#define XMALLOC_BASE_ALIGNMENT alignof (max_align_t)
#if USE_LSB_TAG
# define XMALLOC_HEADER_ALIGNMENT \
@@ -959,10 +996,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 +1117,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 +1139,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 +1775,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 +1844,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 +2128,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 +2171,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,8 +2208,7 @@ make_string (const char *contents, ptrdiff_t nbytes)
return val;
}
-
-/* Make an unibyte string from LENGTH bytes at CONTENTS. */
+/* Make a unibyte string from LENGTH bytes at CONTENTS. */
Lisp_Object
make_unibyte_string (const char *contents, ptrdiff_t length)
@@ -2228,7 +2277,7 @@ make_specified_string (const char *contents,
}
-/* Return an unibyte Lisp_String set up to hold LENGTH characters
+/* Return a unibyte Lisp_String set up to hold LENGTH characters
occupying LENGTH bytes. */
Lisp_Object
@@ -2294,21 +2343,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 +2369,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 +2450,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 +2463,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 +2599,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 +2699,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);
+ return XUNTAG (v->contents[0], Lisp_Int0);
}
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, Lisp_Int0);
}
/* This value is balanced well enough to avoid too much internal overhead
@@ -2920,6 +2964,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 +2984,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 +3039,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 +3109,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 +3127,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;
}
@@ -3116,20 +3163,19 @@ allocate_vector (EMACS_INT len)
/* Allocate other vector-like structures. */
struct Lisp_Vector *
-allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag)
+allocate_pseudovector (int memlen, int lisplen,
+ int zerolen, enum pvec_type tag)
{
struct Lisp_Vector *v = allocate_vectorlike (memlen);
- int i;
/* Catch bogus values. */
- eassert (tag <= PVEC_FONT);
+ eassert (0 <= tag && tag <= PVEC_FONT);
+ eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen);
eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
- /* Only the first lisplen slots will be traced normally by the GC. */
- for (i = 0; i < lisplen; ++i)
- v->contents[i] = Qnil;
-
+ /* Only the first LISPLEN slots will be traced normally by the GC. */
+ memclear (v->contents, zerolen * word_size);
XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
return v;
}
@@ -3147,60 +3193,6 @@ allocate_buffer (void)
return b;
}
-struct Lisp_Hash_Table *
-allocate_hash_table (void)
-{
- return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table, count, PVEC_HASH_TABLE);
-}
-
-struct window *
-allocate_window (void)
-{
- struct window *w;
-
- w = ALLOCATE_PSEUDOVECTOR (struct window, current_matrix, PVEC_WINDOW);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&w->current_matrix, 0,
- sizeof (*w) - offsetof (struct window, current_matrix));
- return w;
-}
-
-struct terminal *
-allocate_terminal (void)
-{
- struct terminal *t;
-
- t = ALLOCATE_PSEUDOVECTOR (struct terminal, next_terminal, PVEC_TERMINAL);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&t->next_terminal, 0,
- sizeof (*t) - offsetof (struct terminal, next_terminal));
- return t;
-}
-
-struct frame *
-allocate_frame (void)
-{
- struct frame *f;
-
- f = ALLOCATE_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&f->face_cache, 0,
- sizeof (*f) - offsetof (struct frame, face_cache));
- return f;
-}
-
-struct Lisp_Process *
-allocate_process (void)
-{
- struct Lisp_Process *p;
-
- p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&p->pid, 0,
- sizeof (*p) - offsetof (struct Lisp_Process, pid));
- return p;
-}
-
DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
doc: /* Return a newly created vector of length LENGTH, with each element being INIT.
See also the function `vector'. */)
@@ -3222,7 +3214,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.
@@ -3347,13 +3338,29 @@ set_symbol_name (Lisp_Object sym, Lisp_Object name)
XSYMBOL (sym)->name = name;
}
+void
+init_symbol (Lisp_Object val, Lisp_Object name)
+{
+ struct Lisp_Symbol *p = XSYMBOL (val);
+ set_symbol_name (val, name);
+ set_symbol_plist (val, Qnil);
+ p->redirect = SYMBOL_PLAINVAL;
+ SET_SYMBOL_VAL (p, Qunbound);
+ set_symbol_function (val, Qnil);
+ set_symbol_next (val, NULL);
+ p->gcmarkbit = false;
+ p->interned = SYMBOL_UNINTERNED;
+ p->constant = 0;
+ p->declared_special = false;
+ p->pinned = false;
+}
+
DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
doc: /* Return a newly allocated uninterned symbol whose name is NAME.
Its value is void, and its function definition and property list are nil. */)
(Lisp_Object name)
{
- register Lisp_Object val;
- register struct Lisp_Symbol *p;
+ Lisp_Object val;
CHECK_STRING (name);
@@ -3381,18 +3388,7 @@ Its value is void, and its function definition and property list are nil. */)
MALLOC_UNBLOCK_INPUT;
- p = XSYMBOL (val);
- set_symbol_name (val, name);
- set_symbol_plist (val, Qnil);
- p->redirect = SYMBOL_PLAINVAL;
- SET_SYMBOL_VAL (p, Qunbound);
- set_symbol_function (val, Qnil);
- set_symbol_next (val, NULL);
- p->gcmarkbit = false;
- p->interned = SYMBOL_UNINTERNED;
- p->constant = 0;
- p->declared_special = false;
- p->pinned = false;
+ init_symbol (val, name);
consing_since_gc += sizeof (struct Lisp_Symbol);
symbols_consed++;
total_free_symbols--;
@@ -3741,7 +3737,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 +3765,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)
@@ -4412,19 +4408,17 @@ DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "",
doc: /* Show information about live and zombie objects. */)
(void)
{
- Lisp_Object args[8], zombie_list = Qnil;
- EMACS_INT i;
- for (i = 0; i < min (MAX_ZOMBIES, nzombies); i++)
+ Lisp_Object zombie_list = Qnil;
+ for (int i = 0; i < min (MAX_ZOMBIES, nzombies); i++)
zombie_list = Fcons (zombies[i], zombie_list);
- args[0] = build_string ("%d GCs, avg live/zombies = %.2f/%.2f (%f%%), max %d/%d\nzombies: %S");
- args[1] = make_number (ngcs);
- args[2] = make_float (avg_live);
- args[3] = make_float (avg_zombies);
- args[4] = make_float (avg_zombies / avg_live / 100);
- args[5] = make_number (max_live);
- args[6] = make_number (max_zombies);
- args[7] = zombie_list;
- return Fmessage (8, args);
+ return CALLN (Fmessage,
+ build_string ("%d GCs, avg live/zombies = %.2f/%.2f"
+ " (%f%%), max %d/%d\nzombies: %S"),
+ make_number (ngcs), make_float (avg_live),
+ make_float (avg_zombies),
+ make_float (avg_zombies / avg_live / 100),
+ make_number (max_live), make_number (max_zombies),
+ zombie_list);
}
#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */
@@ -4502,6 +4496,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 +4519,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 +4831,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
@@ -4909,6 +4856,14 @@ mark_stack (void)
#endif /* GC_MARK_STACK != 0 */
+static bool
+c_symbol_p (struct Lisp_Symbol *sym)
+{
+ char *lispsym_ptr = (char *) lispsym;
+ char *sym_ptr = (char *) sym;
+ ptrdiff_t lispsym_offset = sym_ptr - lispsym_ptr;
+ return 0 <= lispsym_offset && lispsym_offset < sizeof lispsym;
+}
/* Determine whether it is safe to access memory at address P. */
static int
@@ -4917,6 +4872,10 @@ valid_pointer_p (void *p)
#ifdef WINDOWSNT
return w32_valid_pointer_p (p, 16);
#else
+
+ if (ADDRESS_SANITIZER)
+ return p ? -1 : 0;
+
int fd[2];
/* Obviously, we cannot just access it (we would SEGV trying), so we
@@ -4932,7 +4891,7 @@ valid_pointer_p (void *p)
return valid;
}
- return -1;
+ return -1;
#endif
}
@@ -4958,6 +4917,9 @@ valid_lisp_object_p (Lisp_Object obj)
if (PURE_POINTER_P (p))
return 1;
+ if (SYMBOLP (obj) && c_symbol_p (p))
+ return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
+
if (p == &buffer_defaults || p == &buffer_local_symbols)
return 2;
@@ -5015,9 +4977,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 (0 < valid_pointer_p (sdata)
+ && 0 < 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
***********************************************************************/
@@ -5298,7 +5285,7 @@ purecopy (Lisp_Object obj)
}
else if (SYMBOLP (obj))
{
- if (!XSYMBOL (obj)->pinned)
+ if (!XSYMBOL (obj)->pinned && !c_symbol_p (XSYMBOL (obj)))
{ /* We can't purify them, but they appear in many pure objects.
Mark them as `pinned' so we know to mark them at every GC cycle. */
XSYMBOL (obj)->pinned = true;
@@ -5308,10 +5295,8 @@ purecopy (Lisp_Object obj)
}
else
{
- Lisp_Object args[2];
- args[0] = build_pure_c_string ("Don't know how to purify: %S");
- args[1] = obj;
- Fsignal (Qerror, (Fcons (Fformat (2, args), Qnil)));
+ Lisp_Object fmt = build_pure_c_string ("Don't know how to purify: %S");
+ Fsignal (Qerror, list1 (CALLN (Fformat, fmt, obj)));
}
if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
@@ -5487,28 +5472,21 @@ mark_pinned_symbols (void)
union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim;
for (; sym < end; ++sym)
if (sym->s.pinned)
- mark_object (make_lisp_ptr (&sym->s, Lisp_Symbol));
+ mark_object (make_lisp_symbol (&sym->s));
lim = SYMBOL_BLOCK_SIZE;
}
}
-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;
@@ -5528,7 +5506,7 @@ See Info node `(elisp)Garbage Collection'. */)
return Qnil;
/* Record this function, so it appears on the profiler's backtraces. */
- record_in_backtrace (Qautomatic_gc, &Qnil, 0);
+ record_in_backtrace (Qautomatic_gc, 0, 0);
check_cons_list ();
@@ -5592,6 +5570,9 @@ See Info node `(elisp)Garbage Collection'. */)
mark_buffer (&buffer_defaults);
mark_buffer (&buffer_local_symbols);
+ for (i = 0; i < ARRAYELTS (lispsym); i++)
+ mark_object (builtin_lisp_symbol (i));
+
for (i = 0; i < staticidx; i++)
mark_object (*staticvec[i]);
@@ -5606,7 +5587,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 +5610,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
@@ -5693,56 +5674,44 @@ See Info node `(elisp)Garbage Collection'. */)
}
unbind_to (count, Qnil);
- {
- Lisp_Object total[11];
- int total_size = 10;
-
- total[0] = list4 (Qconses, make_number (sizeof (struct Lisp_Cons)),
- bounded_number (total_conses),
- bounded_number (total_free_conses));
- total[1] = list4 (Qsymbols, make_number (sizeof (struct Lisp_Symbol)),
- bounded_number (total_symbols),
- bounded_number (total_free_symbols));
-
- total[2] = list4 (Qmiscs, make_number (sizeof (union Lisp_Misc)),
- bounded_number (total_markers),
- bounded_number (total_free_markers));
-
- total[3] = list4 (Qstrings, make_number (sizeof (struct Lisp_String)),
- bounded_number (total_strings),
- bounded_number (total_free_strings));
-
- total[4] = list3 (Qstring_bytes, make_number (1),
- bounded_number (total_string_bytes));
-
- total[5] = list3 (Qvectors,
- make_number (header_size + sizeof (Lisp_Object)),
- bounded_number (total_vectors));
-
- total[6] = list4 (Qvector_slots, make_number (word_size),
- bounded_number (total_vector_slots),
- bounded_number (total_free_vector_slots));
-
- total[7] = list4 (Qfloats, make_number (sizeof (struct Lisp_Float)),
- bounded_number (total_floats),
- bounded_number (total_free_floats));
-
- total[8] = list4 (Qintervals, make_number (sizeof (struct interval)),
- bounded_number (total_intervals),
- bounded_number (total_free_intervals));
-
- total[9] = list3 (Qbuffers, make_number (sizeof (struct buffer)),
- bounded_number (total_buffers));
+ Lisp_Object total[] = {
+ list4 (Qconses, make_number (sizeof (struct Lisp_Cons)),
+ bounded_number (total_conses),
+ bounded_number (total_free_conses)),
+ list4 (Qsymbols, make_number (sizeof (struct Lisp_Symbol)),
+ bounded_number (total_symbols),
+ bounded_number (total_free_symbols)),
+ list4 (Qmiscs, make_number (sizeof (union Lisp_Misc)),
+ bounded_number (total_markers),
+ bounded_number (total_free_markers)),
+ list4 (Qstrings, make_number (sizeof (struct Lisp_String)),
+ bounded_number (total_strings),
+ bounded_number (total_free_strings)),
+ list3 (Qstring_bytes, make_number (1),
+ bounded_number (total_string_bytes)),
+ list3 (Qvectors,
+ make_number (header_size + sizeof (Lisp_Object)),
+ bounded_number (total_vectors)),
+ list4 (Qvector_slots, make_number (word_size),
+ bounded_number (total_vector_slots),
+ bounded_number (total_free_vector_slots)),
+ list4 (Qfloats, make_number (sizeof (struct Lisp_Float)),
+ bounded_number (total_floats),
+ bounded_number (total_free_floats)),
+ list4 (Qintervals, make_number (sizeof (struct interval)),
+ bounded_number (total_intervals),
+ bounded_number (total_free_intervals)),
+ list3 (Qbuffers, make_number (sizeof (struct buffer)),
+ bounded_number (total_buffers)),
#ifdef DOUG_LEA_MALLOC
- total_size++;
- total[10] = list4 (Qheap, make_number (1024),
- bounded_number ((mallinfo ().uordblks + 1023) >> 10),
- bounded_number ((mallinfo ().fordblks + 1023) >> 10));
+ list4 (Qheap, make_number (1024),
+ bounded_number ((mallinfo ().uordblks + 1023) >> 10),
+ bounded_number ((mallinfo ().fordblks + 1023) >> 10)),
#endif
- retval = Flist (total_size, total);
- }
+ };
+ retval = CALLMANY (Flist, total);
#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
{
@@ -5789,6 +5758,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 +5904,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 +5921,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 +5949,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 +5982,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 +6005,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,21 +6074,28 @@ 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)
{
register Lisp_Object obj = arg;
-#ifdef GC_CHECK_MARKED_OBJECTS
void *po;
+#ifdef GC_CHECK_MARKED_OBJECTS
struct mem_node *m;
#endif
ptrdiff_t cdr_count = 0;
loop:
- if (PURE_POINTER_P (XPNTR (obj)))
+ po = XPNTR (obj);
+ if (PURE_POINTER_P (po))
return;
last_marked[last_marked_index++] = obj;
@@ -5992,8 +6107,6 @@ mark_object (Lisp_Object arg)
by ~80%, and requires compilation with GC_MARK_STACK != 0. */
#ifdef GC_CHECK_MARKED_OBJECTS
- po = (void *) XPNTR (obj);
-
/* Check that the object pointed to by PO is known to be a Lisp
structure allocated from the heap. */
#define CHECK_ALLOCATED() \
@@ -6011,17 +6124,28 @@ mark_object (Lisp_Object arg)
emacs_abort (); \
} while (0)
- /* Check both of the above conditions. */
+ /* Check both of the above conditions, for non-symbols. */
#define CHECK_ALLOCATED_AND_LIVE(LIVEP) \
do { \
CHECK_ALLOCATED (); \
CHECK_LIVE (LIVEP); \
} while (0) \
+ /* Check both of the above conditions, for symbols. */
+#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() \
+ do { \
+ if (!c_symbol_p (ptr)) \
+ { \
+ CHECK_ALLOCATED (); \
+ CHECK_LIVE (live_symbol_p); \
+ } \
+ } while (0) \
+
#else /* not GC_CHECK_MARKED_OBJECTS */
-#define CHECK_LIVE(LIVEP) (void) 0
-#define CHECK_ALLOCATED_AND_LIVE(LIVEP) (void) 0
+#define CHECK_LIVE(LIVEP) ((void) 0)
+#define CHECK_ALLOCATED_AND_LIVE(LIVEP) ((void) 0)
+#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
#endif /* not GC_CHECK_MARKED_OBJECTS */
@@ -6083,22 +6207,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 +6278,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 +6302,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);
+ CHECK_ALLOCATED_AND_LIVE_SYMBOL ();
ptr->gcmarkbit = 1;
+ /* Attempt to catch bogus objects. */
+ eassert (valid_lisp_object_p (ptr->function));
mark_object (ptr->function);
mark_object (ptr->plist);
switch (ptr->redirect)
@@ -6205,21 +6322,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 +6335,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 +6359,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 +6479,400 @@ 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 ();
-
- sweep_strings ();
- check_string_bytes (!noninteractive);
+ struct cons_block *cblk;
+ struct cons_block **cprev = &cons_block;
+ int lim = cons_block_index;
+ EMACS_INT num_free = 0, num_used = 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;
+ 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)
+{
+ struct symbol_block *sblk;
+ struct symbol_block **sprev = &symbol_block;
+ int lim = symbol_block_index;
+ EMACS_INT num_free = 0, num_used = ARRAYELTS (lispsym);
- 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 (int i = 0; i < ARRAYELTS (lispsym); i++)
+ lispsym[i].gcmarkbit = 0;
- 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 (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;
#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));
+ }
+ }
- 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,
@@ -6771,6 +6919,21 @@ Frames, windows, buffers, and subprocesses count as vectors
bounded_number (strings_consed));
}
+static bool
+symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj)
+{
+ struct Lisp_Symbol *sym = XSYMBOL (symbol);
+ Lisp_Object val = find_symbol_value (symbol);
+ return (EQ (val, obj)
+ || EQ (sym->function, obj)
+ || (!NILP (sym->function)
+ && COMPILEDP (sym->function)
+ && EQ (AREF (sym->function, COMPILED_BYTECODE), obj))
+ || (!NILP (val)
+ && COMPILEDP (val)
+ && EQ (AREF (val, COMPILED_BYTECODE), obj)));
+}
+
/* Find at most FIND_MAX symbols which have OBJ as their value or
function. This is used in gdbinit's `xwhichsymbols' command. */
@@ -6783,6 +6946,17 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
if (! DEADP (obj))
{
+ for (int i = 0; i < ARRAYELTS (lispsym); i++)
+ {
+ Lisp_Object sym = builtin_lisp_symbol (i);
+ if (symbol_uses_obj (sym, obj))
+ {
+ found = Fcons (sym, found);
+ if (--find_max == 0)
+ goto out;
+ }
+ }
+
for (sblk = symbol_block; sblk; sblk = sblk->next)
{
union aligned_Lisp_Symbol *aligned_sym = sblk->symbols;
@@ -6790,25 +6964,13 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++)
{
- struct Lisp_Symbol *sym = &aligned_sym->s;
- Lisp_Object val;
- Lisp_Object tem;
-
if (sblk == symbol_block && bn >= symbol_block_index)
break;
- XSETSYMBOL (tem, sym);
- val = find_symbol_value (tem);
- if (EQ (val, obj)
- || EQ (sym->function, obj)
- || (!NILP (sym->function)
- && COMPILEDP (sym->function)
- && EQ (AREF (sym->function, COMPILED_BYTECODE), obj))
- || (!NILP (val)
- && COMPILEDP (val)
- && EQ (AREF (val, COMPILED_BYTECODE), obj)))
+ Lisp_Object sym = make_lisp_symbol (&aligned_sym->s);
+ if (symbol_uses_obj (sym, obj))
{
- found = Fcons (tem, found);
+ found = Fcons (sym, found);
if (--find_max == 0)
goto out;
}
@@ -6821,6 +6983,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,17 +7066,61 @@ 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
init_alloc_once (void)
{
- /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */
+ /* Even though Qt's contents are not set up, its address is known. */
+ Vpurify_flag = Qt;
+
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);
@@ -6913,6 +7191,7 @@ If this portion is smaller than `gc-cons-threshold', this is ignored. */);
DEFVAR_INT ("symbols-consed", symbols_consed,
doc: /* Number of symbols that have been consed so far. */);
+ symbols_consed += ARRAYELTS (lispsym);
DEFVAR_INT ("string-chars-consed", string_chars_consed,
doc: /* Number of string characters that have been consed so far. */);
@@ -6980,6 +7259,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 +7270,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 +7287,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 e8216b18c5e..8ff9bb89757 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 0691f78bd54..d08cd7fcb24 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 1cf56dd5c81..cbc1820c2a5 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,16 +261,7 @@ 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 +297,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 +337,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 +348,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 +400,128 @@ 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 */
}
+#define ISOLATE_STATUS(BIDI_IT, IDX) ((BIDI_IT)->level_stack[IDX].flags & 1)
+#define OVERRIDE(BIDI_IT, IDX) (((BIDI_IT)->level_stack[IDX].flags >> 1) & 3)
+
/* 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->flags = (((override & 3) << 1) | (isolate_status != 0));
+ if (isolate_status)
+ {
+ st->last_strong_type = bidi_it->last_strong.type;
+ st->prev_for_neutral_type = bidi_it->prev_for_neutral.type;
+ st->next_for_neutral_type = bidi_it->next_for_neutral.type;
+ st->next_for_neutral_pos = bidi_it->next_for_neutral.charpos;
+ st->flags |= ((bidi_it->sos == L2R ? 0 : 1) << 3);
+ }
+ /* 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 = ISOLATE_STATUS (bidi_it, bidi_it->stack_idx);
+ 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)
+ {
+ bidi_dir_t sos = ((st.flags >> 3) & 1);
+ /* 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.type = st.last_strong_type;
+ bidi_it->prev_for_neutral.type = st.prev_for_neutral_type;
+ bidi_it->next_for_neutral.type = st.next_for_neutral_type;
+ bidi_it->next_for_neutral.charpos = st.next_for_neutral_pos;
+ bidi_it->sos = (sos == 0 ? L2R : R2L);
+ }
+ 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,7 +541,34 @@ 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
+/* Maximum size we allow the cache to become, per iterator stack slot,
+ in units of struct bidi_it size. If we allow unlimited growth, we
+ could run out of memory for pathologically long bracketed text or
+ very long text lines that need to be reordered. This is aggravated
+ when word-wrap is in effect, since then functions display_line and
+ move_it_in_display_line_to need to keep up to 4 copies of the
+ cache.
+
+ This limitation means there can be no more than that amount of
+ contiguous RTL text on any single physical line in a LTR paragraph,
+ and similarly with contiguous LTR + numeric text in a RTL
+ paragraph. (LTR text in a LTR paragraph and RTL text in a RTL
+ paragraph are not reordered, and so don't need the cache, and
+ cannot hit this limit.) More importantly, no single line can have
+ text longer than this inside paired brackets (because bracket pairs
+ resolution uses the cache). If the limit is exceeded, the fallback
+ code will produce visual order that will be incorrect if there are
+ RTL characters in the offending line of text. */
+/* Do we need to allow customization of this limit? */
+#define BIDI_CACHE_MAX_ELTS_PER_SLOT 50000
+#if BIDI_CACHE_CHUNK >= BIDI_CACHE_MAX_ELTS_PER_SLOT
+# error BIDI_CACHE_CHUNK must be less than BIDI_CACHE_MAX_ELTS_PER_SLOT
+#endif
+static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT;
static struct bidi_it *bidi_cache;
static ptrdiff_t bidi_cache_size = 0;
enum { elsz = sizeof (struct bidi_it) };
@@ -522,9 +589,19 @@ enum
bidi_shelve_header_size
= (sizeof (bidi_cache_idx) + sizeof (bidi_cache_start_stack)
+ sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
- + sizeof (bidi_cache_last_idx))
+ + sizeof (bidi_cache_last_idx) + sizeof (bidi_cache_max_elts))
};
+/* Effectively remove the cached states beyond the Nth state from the
+ part of the cache relevant to iteration of the current object
+ (buffer or string). */
+static void
+bidi_cache_reset_to (int n)
+{
+ bidi_cache_idx = bidi_cache_start + n;
+ bidi_cache_last_idx = -1;
+}
+
/* Reset the cache state to the empty state. We only reset the part
of the cache relevant to iteration of the current object. Previous
objects, which are pushed on the display iterator's stack, are left
@@ -534,8 +611,7 @@ enum
static void
bidi_cache_reset (void)
{
- bidi_cache_idx = bidi_cache_start;
- bidi_cache_last_idx = -1;
+ bidi_cache_reset_to (0);
}
/* Shrink the cache to its minimal size. Called when we init the bidi
@@ -551,6 +627,7 @@ bidi_cache_shrink (void)
bidi_cache_size = BIDI_CACHE_CHUNK;
}
bidi_cache_reset ();
+ bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT;
}
static void
@@ -567,9 +644,11 @@ 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. */
+ in that direction from the last cache hit.
+
+ Value is the index of the cached state, or -1 if not found. */
static ptrdiff_t
bidi_cache_search (ptrdiff_t charpos, int level, int dir)
{
@@ -643,7 +722,8 @@ bidi_cache_find_level_change (int level, int dir, bool before)
ptrdiff_t i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1;
int incr = before ? 1 : 0;
- eassert (!dir || bidi_cache_last_idx >= 0);
+ if (i < 0) /* cache overflowed? */
+ i = 0;
if (!dir)
dir = -1;
@@ -681,24 +761,39 @@ bidi_cache_ensure_space (ptrdiff_t idx)
/* Enlarge the cache as needed. */
if (idx >= bidi_cache_size)
{
- /* The bidi cache cannot be larger than the largest Lisp string
- or buffer. */
- ptrdiff_t string_or_buffer_bound
- = max (BUF_BYTES_MAX, STRING_BYTES_BOUND);
+ ptrdiff_t chunk_size = BIDI_CACHE_CHUNK;
- /* Also, it cannot be larger than what C can represent. */
- ptrdiff_t c_bound
- = (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz;
+ if (bidi_cache_size > bidi_cache_max_elts - chunk_size)
+ chunk_size = bidi_cache_max_elts - bidi_cache_size;
- bidi_cache
- = xpalloc (bidi_cache, &bidi_cache_size,
- max (BIDI_CACHE_CHUNK, idx - bidi_cache_size + 1),
- min (string_or_buffer_bound, c_bound), elsz);
+ if (max (idx + 1,
+ bidi_cache_size + chunk_size) <= bidi_cache_max_elts)
+ {
+ /* The bidi cache cannot be larger than the largest Lisp
+ string or buffer. */
+ ptrdiff_t string_or_buffer_bound
+ = max (BUF_BYTES_MAX, STRING_BYTES_BOUND);
+
+ /* Also, it cannot be larger than what C can represent. */
+ ptrdiff_t c_bound
+ = (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz;
+ ptrdiff_t max_elts = bidi_cache_max_elts;
+
+ max_elts = min (max_elts, min (string_or_buffer_bound, c_bound));
+
+ /* Force xpalloc not to over-allocate by passing it MAX_ELTS
+ as its 4th argument. */
+ bidi_cache = xpalloc (bidi_cache, &bidi_cache_size,
+ max (chunk_size, idx - bidi_cache_size + 1),
+ max_elts, elsz);
+ eassert (bidi_cache_size > idx);
+ }
}
}
-static void
-bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
+static int
+bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved,
+ bool update_only)
{
ptrdiff_t idx;
@@ -707,6 +802,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 0;
+
if (idx < 0)
{
idx = bidi_cache_idx;
@@ -714,19 +812,23 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
/* Character positions should correspond to cache positions 1:1.
If we are outside the range of cached positions, the cache is
useless and must be reset. */
- if (idx > bidi_cache_start &&
- (bidi_it->charpos > (bidi_cache[idx - 1].charpos
- + bidi_cache[idx - 1].nchars)
- || bidi_it->charpos < bidi_cache[bidi_cache_start].charpos))
+ if (bidi_cache_start < idx && idx < bidi_cache_size
+ && (bidi_it->charpos > (bidi_cache[idx - 1].charpos
+ + bidi_cache[idx - 1].nchars)
+ || bidi_it->charpos < bidi_cache[bidi_cache_start].charpos))
{
bidi_cache_reset ();
idx = bidi_cache_start;
}
if (bidi_it->nchars <= 0)
emacs_abort ();
- bidi_copy_it (&bidi_cache[idx], bidi_it);
- if (!resolved)
- bidi_cache[idx].resolved_level = -1;
+ /* Don't cache if no available space in the cache. */
+ if (bidi_cache_size > idx)
+ {
+ bidi_copy_it (&bidi_cache[idx], bidi_it);
+ if (!resolved)
+ bidi_cache[idx].resolved_level = -1;
+ }
}
else
{
@@ -734,32 +836,54 @@ 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;
- if (idx >= bidi_cache_idx)
- bidi_cache_idx = idx + 1;
+ if (bidi_cache_size > idx)
+ {
+ bidi_cache_last_idx = idx;
+ if (idx >= bidi_cache_idx)
+ bidi_cache_idx = idx + 1;
+ return 1;
+ }
+ else
+ {
+ /* The cache overflowed. */
+ bidi_cache_last_idx = -1;
+ return 0;
+ }
}
+/* 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;
@@ -777,8 +901,13 @@ bidi_cache_find (ptrdiff_t charpos, int level, struct bidi_it *bidi_it)
static int
bidi_peek_at_next_level (struct bidi_it *bidi_it)
{
- if (bidi_cache_idx == bidi_cache_start || bidi_cache_last_idx == -1)
+ if (bidi_cache_idx == bidi_cache_start)
emacs_abort ();
+ /* If the cache overflowed, return the level of the last cached
+ character. */
+ if (bidi_cache_last_idx == -1
+ || (bidi_cache_last_idx >= bidi_cache_idx - 1 && bidi_it->scan_dir > 0))
+ return bidi_cache[bidi_cache_idx - 1].resolved_level;
return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level;
}
@@ -795,6 +924,8 @@ bidi_peek_at_next_level (struct bidi_it *bidi_it)
void
bidi_push_it (struct bidi_it *bidi_it)
{
+ /* Give this stack slot its cache room. */
+ bidi_cache_max_elts += BIDI_CACHE_MAX_ELTS_PER_SLOT;
/* Save the current iterator state in its entirety after the last
used cache slot. */
bidi_cache_ensure_space (bidi_cache_idx);
@@ -831,6 +962,9 @@ bidi_pop_it (struct bidi_it *bidi_it)
/* Invalidate the last-used cache slot data. */
bidi_cache_last_idx = -1;
+
+ bidi_cache_max_elts -= BIDI_CACHE_MAX_ELTS_PER_SLOT;
+ eassert (bidi_cache_max_elts > 0);
}
static ptrdiff_t bidi_cache_total_alloc;
@@ -870,6 +1004,11 @@ bidi_shelve_cache (void)
+ sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ sizeof (bidi_cache_start),
&bidi_cache_last_idx, sizeof (bidi_cache_last_idx));
+ memcpy (databuf + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx),
+ &bidi_cache_max_elts, sizeof (bidi_cache_max_elts));
return databuf;
}
@@ -891,6 +1030,7 @@ bidi_unshelve_cache (void *databuf, bool just_free)
/* A NULL pointer means an empty cache. */
bidi_cache_start = 0;
bidi_cache_sp = 0;
+ bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT;
bidi_cache_reset ();
}
}
@@ -930,6 +1070,12 @@ bidi_unshelve_cache (void *databuf, bool just_free)
+ sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ sizeof (bidi_cache_start),
sizeof (bidi_cache_last_idx));
+ memcpy (&bidi_cache_max_elts,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx),
+ sizeof (bidi_cache_max_elts));
bidi_cache_total_alloc
-= (bidi_shelve_header_size
+ bidi_cache_idx * sizeof (struct bidi_it));
@@ -956,14 +1102,17 @@ bidi_initialize (void)
emacs_abort ();
staticpro (&bidi_mirror_table);
- Qparagraph_start = intern ("paragraph-start");
- staticpro (&Qparagraph_start);
+ bidi_brackets_table = uniprop_table (intern ("bracket-type"));
+ if (NILP (bidi_brackets_table))
+ emacs_abort ();
+ staticpro (&bidi_brackets_table);
+
+ DEFSYM (Qparagraph_start, "paragraph-start");
paragraph_start_re = Fsymbol_value (Qparagraph_start);
if (!STRINGP (paragraph_start_re))
paragraph_start_re = build_string ("\f\\|[ \t]*$");
staticpro (&paragraph_start_re);
- Qparagraph_separate = intern ("paragraph-separate");
- staticpro (&Qparagraph_separate);
+ DEFSYM (Qparagraph_separate, "paragraph-separate");
paragraph_separate_re = Fsymbol_value (Qparagraph_separate);
if (!STRINGP (paragraph_separate_re))
paragraph_separate_re = build_string ("[ \t\f]*$");
@@ -971,6 +1120,7 @@ bidi_initialize (void)
bidi_cache_sp = 0;
bidi_cache_total_alloc = 0;
+ bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT;
bidi_initialized = 1;
}
@@ -981,7 +1131,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 +1148,25 @@ 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->bracket_pairing_pos = -1;
+ 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 +1182,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].flags = 0; /* NEUTRAL_DIR, false per 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_it->bracket_pairing_pos = -1;
+ bidi_set_sos_type (bidi_it,
(bidi_it->paragraph_dir == R2L ? 1 : 0),
bidi_it->level_stack[0].level); /* X10 */
@@ -1244,6 +1395,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 +1573,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 +1685,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 +1733,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 +1805,75 @@ 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;
+ ptrdiff_t eob
+ = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
+ ? bidi_it->string.schars : ZV);
+
+ /* 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 needed, reset the "magical" value of pairing bracket
+ position, so that bidi_resolve_brackets will resume
+ resolution of brackets according to BPA. */
+ if (bidi_it->bracket_pairing_pos == eob)
+ bidi_it->bracket_pairing_pos = -1;
+ }
+ 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, unless we previously decided
+ (in bidi_find_bracket_pairs) that brackets in this level run
+ should be resolved as neutrals. */
+ if (bidi_it->bracket_pairing_pos != eob)
+ {
+ 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 +1904,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 +1929,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 = ISOLATE_STATUS (bidi_it, bidi_it->stack_idx);
+ override = OVERRIDE (bidi_it, bidi_it->stack_idx);
new_level = current_level;
if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV))
@@ -1652,6 +1951,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 +2007,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 +2017,141 @@ 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 (!ISOLATE_STATUS (bidi_it, bidi_it->stack_idx))
+ 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. */
+ {
+ bidi_dir_t stack_override = OVERRIDE (bidi_it, bidi_it->stack_idx);
+ if (stack_override == L2R)
+ bidi_it->type_after_wn = STRONG_L;
+ else if (stack_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
@@ -1890,28 +2171,27 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
? bidi_it->string.schars : ZV);
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 ();
+ override = OVERRIDE (bidi_it, bidi_it->stack_idx);
+
+ 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 +2208,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 +2269,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 +2279,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 +2291,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 +2312,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 +2340,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 +2363,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 +2383,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 +2413,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 +2428,536 @@ 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 ((int)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; \
+ if (bpa_sp < MAX_BPA_STACK - 1) \
+ { \
+ bpa_sp++; \
+ 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 base_level = bidi_it->level_stack[0].level;
+ int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level;
+ int maxlevel = embedding_level;
+ bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L;
+ struct bidi_it tem_it;
+ bool l2r_seen = false, r2l_seen = false;
+ ptrdiff_t pairing_pos;
+ int idx_at_entry = bidi_cache_idx;
+
+ 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;
+
+ if (maxlevel < current_level)
+ maxlevel = current_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;
+ if (!bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0))
+ {
+ /* No more space in cache -- give up and let the opening
+ bracket that started this be processed as a
+ NEUTRAL_ON. */
+ bidi_cache_reset_to (idx_at_entry - bidi_cache_start);
+ bidi_copy_it (bidi_it, &saved_it);
+ goto give_up;
+ }
+ 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);
+ l2r_seen = true;
+ break;
+ case STRONG_R:
+ case WEAK_EN:
+ case WEAK_AN:
+ flag = ((embedding_level & 1) == 1
+ ? FLAG_EMBEDDING_INSIDE
+ : FLAG_OPPOSITE_INSIDE);
+ r2l_seen = true;
+ 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
+ && (ISOLATE_STATUS (bidi_it, new_sidx)
+ || (new_sidx > old_sidx + 1
+ && ISOLATE_STATUS (bidi_it, new_sidx - 1))))
+ {
+ while (bidi_it->level_stack[bidi_it->stack_idx].level
+ > current_level)
+ {
+ if (maxlevel < bidi_it->level_stack[bidi_it->stack_idx].level)
+ maxlevel = bidi_it->level_stack[bidi_it->stack_idx].level;
+ if (!bidi_cache_iterator_state (bidi_it,
+ type == NEUTRAL_B, 0))
+ {
+ /* No more space in cache -- give up and let the
+ opening bracket that started this be
+ processed as any other NEUTRAL_ON. */
+ bidi_cache_reset_to (idx_at_entry - bidi_cache_start);
+ bidi_copy_it (bidi_it, &saved_it);
+ goto give_up;
+ }
+ type = bidi_resolve_weak (bidi_it);
+ }
+ }
+ if (type == NEUTRAL_B
+ || (bidi_it->level_stack[bidi_it->stack_idx].level
+ != current_level))
+ {
+ /* 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. */
+ pairing_pos = bidi_it->charpos;
+ 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);
+
+ /* The following is an optimization for bracketed text that has
+ only one level which is equal to the paragraph's base
+ embedding level. That is, only L2R and weak/neutral
+ characters in a L2R paragraph, or only R2L and weak/neutral
+ characters in a R2L paragraph. Such brackets can be resolved
+ by bidi_resolve_neutral, which has a further shortcut for
+ this case. So we pretend we did not resolve the brackets in
+ this case, set up next_for_neutral for the entire bracketed
+ text, and reset the cache to the character before the opening
+ bracket. The upshot is to allow bidi_move_to_visually_next
+ reset the cache when it returns this opening bracket, thus
+ cutting significantly on the size of the cache, which is
+ important with long lines, especially if word-wrap is non-nil
+ (which requires the display engine to copy the cache back and
+ forth many times). */
+ if (maxlevel == base_level
+ && ((base_level == 0 && !r2l_seen)
+ || (base_level == 1 && !l2r_seen)))
+ {
+ ptrdiff_t eob
+ = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
+ ? bidi_it->string.schars : ZV);
+
+ if (retval)
+ pairing_pos = bidi_it->bracket_pairing_pos;
+
+ /* This special value (which cannot possibly happen when
+ brackets are resolved, since there's no character at ZV)
+ will be noticed by bidi_resolve_explicit, and will be
+ copied to the following iterator states, instead of being
+ reset to -1. */
+ bidi_it->bracket_pairing_pos = eob;
+ /* This type value will be used for resolving the outermost
+ closing bracket in bidi_resolve_brackets. */
+ bidi_it->bracket_enclosed_type = embedding_type;
+ /* bidi_cache_last_idx is set to the index of the current
+ state, because we just called bidi_cache_find above.
+ That state describes the outermost opening bracket, the
+ one with which we entered this function. Force the cache
+ to "forget" all the cached states starting from that state. */
+ bidi_cache_reset_to (bidi_cache_last_idx - bidi_cache_start);
+ /* Set up the next_for_neutral member, to help
+ bidi_resolve_neutral. */
+ bidi_it->next_for_neutral.type = embedding_type;
+ bidi_it->next_for_neutral.charpos = pairing_pos;
+ /* Pretend we didn't resolve this bracket. */
+ retval = false;
+ }
+ }
+
+ give_up:
+ 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;
+ ptrdiff_t eob
+ = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
+ ? bidi_it->string.schars : ZV);
+
+ /* 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)
+ {
+ /* bracket_pairing_pos == eob means this bracket does not
+ need to be resolved as a bracket, but as a neutral, see
+ the optimization trick we play near the end of
+ bidi_find_bracket_pairs. */
+ if (bidi_it->bracket_pairing_pos == eob)
+ {
+ /* If this is the outermost closing bracket of a run of
+ characters in which we decided to resolve brackets as
+ neutrals, use the embedding level's type, recorded in
+ bracket_enclosed_type, to resolve the bracket. */
+ if (bidi_it->next_for_neutral.charpos == bidi_it->charpos
+ && bidi_paired_bracket_type (bidi_it->ch) == BIDI_BRACKET_CLOSE)
+ type = bidi_it->bracket_enclosed_type;
+ }
+ else if (bidi_find_bracket_pairs (bidi_it))
+ resolve_bracket = true;
+ }
+ }
+ else if (bidi_it->bracket_pairing_pos != eob)
+ {
+ 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
+ && ISOLATE_STATUS (bidi_it, bidi_it->stack_idx))
+ {
+ 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 +2973,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 +2986,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 +3002,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
+ && (ISOLATE_STATUS (bidi_it, new_sidx)
+ /* 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
+ && ISOLATE_STATUS (bidi_it, new_sidx - 1))))
+ {
+ 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 +3122,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 +3134,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 +3144,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 +3174,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 +3192,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 +3230,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}
-
- 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.
+ /* Update the cache, but only if this state was already cached. */
+ bidi_cache_iterator_state (bidi_it, 1, 1);
- (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 +3305,35 @@ 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);
+ if (!bidi_cache_iterator_state (bidi_it, 1, 0))
+ {
+ /* Can't happen: if the cache needs to grow, it means we
+ were at base embedding level, so the cache should have
+ been either empty or already large enough to cover this
+ character position. */
+ emacs_abort ();
+ }
do {
new_level = bidi_level_of_next_char (bidi_it);
- bidi_cache_iterator_state (bidi_it, 1);
+ /* If the cache is full, perform an emergency return by
+ pretending that the level ended. */
+ if (!bidi_cache_iterator_state (bidi_it, 1, 0))
+ {
+ new_level = level - 1;
+ /* Since the cache should only grow when we are scanning
+ forward looking for the edge of the level that is one
+ above the base embedding level, we can only have this
+ contingency when LEVEL - 1 is the base embedding
+ level. */
+ eassert (new_level == bidi_it->level_stack[0].level);
+ /* Plan B, for when the cache overflows: Back up to the
+ previous character by fetching the last cached state,
+ and force the resolved level of that character be the
+ base embedding level. */
+ bidi_cache_fetch_state (bidi_cache_idx - 1, bidi_it);
+ bidi_it->resolved_level = new_level;
+ bidi_cache_iterator_state (bidi_it, 1, 1);
+ }
} while (new_level >= level);
}
}
@@ -2607,7 +3377,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 +3425,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);
@@ -2712,18 +3487,54 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
&& bidi_it->charpos > (bidi_cache[bidi_cache_idx - 1].charpos
+ bidi_cache[bidi_cache_idx - 1].nchars - 1))
bidi_cache_reset ();
+ /* Also reset the cache if it overflowed and we have just
+ emergency-exited using Plan B. */
+ else if (bidi_it->resolved_level == bidi_it->level_stack[0].level
+ && bidi_cache_idx >= bidi_cache_size
+ && bidi_it->charpos == bidi_cache[bidi_cache_idx - 1].charpos)
+ bidi_cache_reset ();
/* But as long as we are caching during forward scan, we must
cache each state, or else the cache integrity will be
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;
}
+/* Utility function for looking for strong directional characters
+ whose bidi type was overridden by a directional override. */
+ptrdiff_t
+bidi_find_first_overridden (struct bidi_it *bidi_it)
+{
+ ptrdiff_t found_pos = ZV;
+
+ do
+ {
+ /* Need to call bidi_resolve_weak, not bidi_resolve_explicit,
+ because the directional overrides are applied by the
+ former. */
+ bidi_type_t type = bidi_resolve_weak (bidi_it);
+
+ if ((type == STRONG_R && bidi_it->orig_type == STRONG_L)
+ || (type == STRONG_L
+ && (bidi_it->orig_type == STRONG_R
+ || bidi_it->orig_type == STRONG_AL)))
+ found_pos = bidi_it->charpos;
+ } while (found_pos == ZV
+ && bidi_it->charpos < ZV
+ && bidi_it->ch != BIDI_EOB
+ && bidi_it->ch != '\n');
+
+ return found_pos;
+}
+
/* This is meant to be called from within the debugger, whenever you
wish to examine the cache contents. */
void bidi_dump_cached_states (void) EXTERNALLY_VISIBLE;
diff --git a/src/buffer.c b/src/buffer.c
index 250d8d24d7b..67eda3ee89e 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -42,6 +42,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).
@@ -111,37 +115,8 @@ static void reset_buffer_local_variables (struct buffer *, bool);
due to user rplac'ing this alist or its elements. */
Lisp_Object Vbuffer_alist;
-static Lisp_Object Qkill_buffer_query_functions;
-
-/* Hook run before changing a major mode. */
-static Lisp_Object Qchange_major_mode_hook;
-
-Lisp_Object Qfirst_change_hook;
-Lisp_Object Qbefore_change_functions;
-Lisp_Object Qafter_change_functions;
-
-static Lisp_Object Qfundamental_mode, Qmode_class, Qpermanent_local;
-static Lisp_Object Qpermanent_local_hook;
-
-static Lisp_Object Qprotected_field;
-
static Lisp_Object QSFundamental; /* A string "Fundamental". */
-static Lisp_Object Qkill_buffer_hook;
-static Lisp_Object Qbuffer_list_update_hook;
-
-static Lisp_Object Qget_file_buffer;
-
-static Lisp_Object Qoverlayp;
-
-Lisp_Object Qpriority, Qbefore_string, Qafter_string;
-
-static Lisp_Object Qevaporate;
-
-Lisp_Object Qmodification_hooks;
-Lisp_Object Qinsert_in_front_hooks;
-Lisp_Object Qinsert_behind_hooks;
-
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 +312,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 +342,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;
@@ -402,7 +387,6 @@ followed by the rest of the buffers. */)
if (FRAMEP (frame))
{
Lisp_Object framelist, prevlist, tail;
- Lisp_Object args[3];
framelist = Fcopy_sequence (XFRAME (frame)->buffer_list);
prevlist = Fnreverse (Fcopy_sequence
@@ -423,10 +407,7 @@ followed by the rest of the buffers. */)
tail = XCDR (tail);
}
- args[0] = framelist;
- args[1] = general;
- args[2] = prevlist;
- return Fnconc (3, args);
+ return CALLN (Fnconc, framelist, general, prevlist);
}
else
return general;
@@ -1117,10 +1098,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 +1106,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 +1116,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 +1140,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 +1240,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 +1270,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 +1327,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 +1346,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 +1378,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 +1393,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 +1473,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 +1516,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 +1540,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);
}
@@ -1724,15 +1650,14 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Run hooks with the buffer to be killed the current buffer. */
{
ptrdiff_t count = SPECPDL_INDEX ();
- Lisp_Object arglist[1];
record_unwind_protect (save_excursion_restore, save_excursion_save ());
set_buffer_internal (b);
/* First run the query functions; if any query is answered no,
don't kill the buffer. */
- arglist[0] = Qkill_buffer_query_functions;
- tem = Frun_hook_with_args_until_failure (1, arglist);
+ tem = CALLN (Frun_hook_with_args_until_failure,
+ Qkill_buffer_query_functions);
if (NILP (tem))
return unbind_to (count, Qnil);
@@ -1753,7 +1678,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
return unbind_to (count, Qt);
/* Then run the hooks. */
- Frun_hooks (1, &Qkill_buffer_hook);
+ run_hook (Qkill_buffer_hook);
unbind_to (count, Qnil);
}
@@ -1823,10 +1748,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);
@@ -2224,12 +2147,20 @@ set_buffer_if_live (Lisp_Object buffer)
}
DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
- Sbarf_if_buffer_read_only, 0, 0, 0,
- doc: /* Signal a `buffer-read-only' error if the current buffer is read-only. */)
- (void)
+ Sbarf_if_buffer_read_only, 0, 1, 0,
+ doc: /* Signal a `buffer-read-only' error if the current buffer is read-only.
+If the text under POSITION (which defaults to point) has the
+`inhibit-read-only' text property set, the error will not be raised. */)
+ (Lisp_Object pos)
{
+ if (NILP (pos))
+ XSETFASTINT (pos, PT);
+ else
+ CHECK_NUMBER (pos);
+
if (!NILP (BVAR (current_buffer, read_only))
- && NILP (Vinhibit_read_only))
+ && NILP (Vinhibit_read_only)
+ && NILP (Fget_text_property (pos, Qinhibit_read_only, Qnil)))
xsignal1 (Qbuffer_read_only, Fcurrent_buffer ());
return Qnil;
}
@@ -2430,6 +2361,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 +2473,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 +2545,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)
@@ -2763,7 +2702,7 @@ The first thing this function does is run
the normal hook `change-major-mode-hook'. */)
(void)
{
- Frun_hooks (1, &Qchange_major_mode_hook);
+ run_hook (Qchange_major_mode_hook);
/* Make sure none of the bindings in local_var_alist
remain swapped in, in their symbols. */
@@ -3087,13 +3026,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 +3044,7 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
!NILP (tem)))
break;
+ SAFE_FREE ();
return i < n;
}
@@ -4116,17 +4058,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 +4493,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 +4508,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 +4574,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 +4641,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 +4712,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 +4788,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.
@@ -5154,12 +5022,99 @@ init_buffer_once (void)
memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags);
+ /* 0 means not a lisp var, -1 means always local, else mask. */
+ memset (&buffer_local_flags, 0, sizeof buffer_local_flags);
+ bset_filename (&buffer_local_flags, make_number (-1));
+ bset_directory (&buffer_local_flags, make_number (-1));
+ bset_backed_up (&buffer_local_flags, make_number (-1));
+ bset_save_length (&buffer_local_flags, make_number (-1));
+ bset_auto_save_file_name (&buffer_local_flags, make_number (-1));
+ bset_read_only (&buffer_local_flags, make_number (-1));
+ bset_major_mode (&buffer_local_flags, make_number (-1));
+ bset_mode_name (&buffer_local_flags, make_number (-1));
+ bset_undo_list (&buffer_local_flags, make_number (-1));
+ bset_mark_active (&buffer_local_flags, make_number (-1));
+ bset_point_before_scroll (&buffer_local_flags, make_number (-1));
+ bset_file_truename (&buffer_local_flags, make_number (-1));
+ bset_invisibility_spec (&buffer_local_flags, make_number (-1));
+ bset_file_format (&buffer_local_flags, make_number (-1));
+ bset_auto_save_file_format (&buffer_local_flags, make_number (-1));
+ bset_display_count (&buffer_local_flags, make_number (-1));
+ bset_display_time (&buffer_local_flags, make_number (-1));
+ bset_enable_multibyte_characters (&buffer_local_flags, make_number (-1));
+
+ /* These used to be stuck at 0 by default, but now that the all-zero value
+ means Qnil, we have to initialize them explicitly. */
+ bset_name (&buffer_local_flags, make_number (0));
+ bset_mark (&buffer_local_flags, make_number (0));
+ bset_local_var_alist (&buffer_local_flags, make_number (0));
+ bset_keymap (&buffer_local_flags, make_number (0));
+ bset_downcase_table (&buffer_local_flags, make_number (0));
+ bset_upcase_table (&buffer_local_flags, make_number (0));
+ bset_case_canon_table (&buffer_local_flags, make_number (0));
+ bset_case_eqv_table (&buffer_local_flags, make_number (0));
+ bset_minor_modes (&buffer_local_flags, make_number (0));
+ bset_width_table (&buffer_local_flags, make_number (0));
+ bset_pt_marker (&buffer_local_flags, make_number (0));
+ bset_begv_marker (&buffer_local_flags, make_number (0));
+ bset_zv_marker (&buffer_local_flags, make_number (0));
+ bset_last_selected_window (&buffer_local_flags, make_number (0));
+
+ idx = 1;
+ XSETFASTINT (BVAR (&buffer_local_flags, mode_line_format), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, abbrev_mode), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, overwrite_mode), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, case_fold_search), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, auto_fill_function), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, selective_display), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, selective_display_ellipses), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, tab_width), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, truncate_lines), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, word_wrap), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, ctl_arrow), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, fill_column), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, left_margin), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, abbrev_table), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, cache_long_scans), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, buffer_file_coding_system), idx);
+ /* Make this one a permanent local. */
+ buffer_permanent_local_flags[idx++] = 1;
+ XSETFASTINT (BVAR (&buffer_local_flags, left_margin_cols), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, right_margin_cols), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, left_fringe_width), idx); ++idx;
+ 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;
+ XSETFASTINT (BVAR (&buffer_local_flags, fringe_cursor_alist), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, scroll_up_aggressively), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, scroll_down_aggressively), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, header_line_format), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, cursor_type), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, extra_line_spacing), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, cursor_in_non_selected_windows), idx); ++idx;
+
+ /* Need more room? */
+ if (idx >= MAX_PER_BUFFER_VARS)
+ emacs_abort ();
+ last_per_buffer_idx = idx;
+
/* Make sure all markable slots in buffer_defaults
are initialized reasonably, so mark_buffer won't choke. */
reset_buffer (&buffer_defaults);
- eassert (EQ (BVAR (&buffer_defaults, name), make_number (0)));
+ eassert (NILP (BVAR (&buffer_defaults, name)));
reset_buffer_local_variables (&buffer_defaults, 1);
- eassert (EQ (BVAR (&buffer_local_symbols, name), make_number (0)));
+ eassert (NILP (BVAR (&buffer_local_symbols, name)));
reset_buffer (&buffer_local_symbols);
reset_buffer_local_variables (&buffer_local_symbols, 1);
/* Prevent GC from getting confused. */
@@ -5224,7 +5179,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);
@@ -5238,96 +5195,26 @@ init_buffer_once (void)
to say that it has its own local value for the slot.
The local flag bits are in the local_var_flags slot of the buffer. */
- /* Nothing can work if this isn't true */
+ /* Nothing can work if this isn't true. */
{ verify (sizeof (EMACS_INT) == word_size); }
- /* 0 means not a lisp var, -1 means always local, else mask */
- memset (&buffer_local_flags, 0, sizeof buffer_local_flags);
- bset_filename (&buffer_local_flags, make_number (-1));
- bset_directory (&buffer_local_flags, make_number (-1));
- bset_backed_up (&buffer_local_flags, make_number (-1));
- bset_save_length (&buffer_local_flags, make_number (-1));
- bset_auto_save_file_name (&buffer_local_flags, make_number (-1));
- bset_read_only (&buffer_local_flags, make_number (-1));
- bset_major_mode (&buffer_local_flags, make_number (-1));
- bset_mode_name (&buffer_local_flags, make_number (-1));
- bset_undo_list (&buffer_local_flags, make_number (-1));
- bset_mark_active (&buffer_local_flags, make_number (-1));
- bset_point_before_scroll (&buffer_local_flags, make_number (-1));
- bset_file_truename (&buffer_local_flags, make_number (-1));
- bset_invisibility_spec (&buffer_local_flags, make_number (-1));
- bset_file_format (&buffer_local_flags, make_number (-1));
- bset_auto_save_file_format (&buffer_local_flags, make_number (-1));
- bset_display_count (&buffer_local_flags, make_number (-1));
- bset_display_time (&buffer_local_flags, make_number (-1));
- bset_enable_multibyte_characters (&buffer_local_flags, make_number (-1));
-
- idx = 1;
- XSETFASTINT (BVAR (&buffer_local_flags, mode_line_format), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, abbrev_mode), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, overwrite_mode), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, case_fold_search), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, auto_fill_function), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, selective_display), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, selective_display_ellipses), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, tab_width), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, truncate_lines), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, word_wrap), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, ctl_arrow), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, fill_column), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, left_margin), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, abbrev_table), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, cache_long_scans), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, buffer_file_coding_system), idx);
- /* Make this one a permanent local. */
- buffer_permanent_local_flags[idx++] = 1;
- XSETFASTINT (BVAR (&buffer_local_flags, left_margin_cols), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, right_margin_cols), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, left_fringe_width), idx); ++idx;
- 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, vertical_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;
- XSETFASTINT (BVAR (&buffer_local_flags, fringe_cursor_alist), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, scroll_up_aggressively), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, scroll_down_aggressively), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, header_line_format), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, cursor_type), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, extra_line_spacing), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, cursor_in_non_selected_windows), idx); ++idx;
-
- /* Need more room? */
- if (idx >= MAX_PER_BUFFER_VARS)
- emacs_abort ();
- last_per_buffer_idx = idx;
-
Vbuffer_alist = Qnil;
current_buffer = 0;
all_buffers = 0;
QSFundamental = build_pure_c_string ("Fundamental");
- Qfundamental_mode = intern_c_string ("fundamental-mode");
+ DEFSYM (Qfundamental_mode, "fundamental-mode");
bset_major_mode (&buffer_defaults, Qfundamental_mode);
- Qmode_class = intern_c_string ("mode-class");
-
- Qprotected_field = intern_c_string ("protected-field");
+ DEFSYM (Qmode_class, "mode-class");
+ DEFSYM (Qprotected_field, "protected-field");
- Qpermanent_local = intern_c_string ("permanent-local");
-
- Qkill_buffer_hook = intern_c_string ("kill-buffer-hook");
+ DEFSYM (Qpermanent_local, "permanent-local");
+ DEFSYM (Qkill_buffer_hook, "kill-buffer-hook");
Fput (Qkill_buffer_hook, Qpermanent_local, Qt);
- /* super-magic invisible buffer */
+ /* Super-magic invisible buffer. */
Vprin1_to_string_buffer = Fget_buffer_create (build_pure_c_string (" prin1"));
Vbuffer_alist = Qnil;
@@ -5337,26 +5224,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 +5315,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));
@@ -5450,13 +5375,13 @@ syms_of_buffer (void)
last_overlay_modification_hooks
= Fmake_vector (make_number (10), Qnil);
- staticpro (&Qfundamental_mode);
- staticpro (&Qmode_class);
staticpro (&QSFundamental);
staticpro (&Vbuffer_alist);
- staticpro (&Qprotected_field);
- 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");
@@ -5473,6 +5398,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 +5815,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 +5906,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 +5924,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 +6001,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 +6014,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 f1fbb24c454..81852cae505 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,23 +1128,19 @@ 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)
extern Lisp_Object Vbuffer_alist;
-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;
/* 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 95c3ce2f3f2..b4583676835 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"
@@ -67,7 +69,6 @@ by Hallvard:
#ifdef BYTE_CODE_METER
-Lisp_Object Qbyte_code_meter;
#define METER_2(code1, code2) AREF (AREF (Vbyte_code_meter, code1), code2)
#define METER_1(code) METER_2 (0, code)
@@ -292,8 +293,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 +389,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 +1107,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 1a2138d5c7e..60021fdfc82 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -28,18 +28,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "window.h"
#include "keymap.h"
-Lisp_Object Qminus, Qplus;
-static Lisp_Object Qcall_interactively;
-static Lisp_Object Qcommand_debug_status;
-static Lisp_Object Qenable_recursive_minibuffers;
-
-static Lisp_Object Qhandle_shift_selection;
-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 preserved_fns;
/* Marker used within call-interactively to refer to point. */
@@ -113,7 +101,8 @@ If the string begins with `^' and `shift-select-mode' is non-nil,
Emacs first calls the function `handle-shift-selection'.
You may use `@', `*', and `^' together. They are processed in the
order that they appear, before reading any arguments.
-usage: (interactive &optional ARGS) */)
+usage: (interactive &optional ARGS) */
+ attributes: const)
(Lisp_Object args)
{
return Qnil;
@@ -233,6 +222,36 @@ 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;
+ GCPRO1 (default_filename);
+ RETURN_UNGCPRO (CALLN (Ffuncall, intern ("read-file-name"),
+ callint_message, Qnil, default_filename,
+ mustmatch, initial, predicate));
+}
+
+/* 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 +279,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 +349,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 +390,17 @@ 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 result
+ = unbind_to (speccount, CALLN (Fapply, Qfuncall_interactively,
+ function, specs));
+ 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. */
@@ -403,13 +426,13 @@ invoke it. If KEYS is omitted or nil, the return value of
{
if (! (*p == 'r' || *p == 'p' || *p == 'P'
|| *p == '\n'))
- Fbarf_if_buffer_read_only ();
+ Fbarf_if_buffer_read_only (Qnil);
p++;
}
record_then_fail = 1;
}
else
- Fbarf_if_buffer_read_only ();
+ Fbarf_if_buffer_read_only (Qnil);
}
}
/* Ignore this for semi-compatibility with Lucid. */
@@ -432,7 +455,7 @@ invoke it. If KEYS is omitted or nil, the return value of
error ("Attempt to select inactive minibuffer window");
/* If the current buffer wants to clean up, let it. */
- Frun_hooks (1, &Qmouse_leave_buffer_hook);
+ run_hook (Qmouse_leave_buffer_hook);
Fselect_window (w, Qnil);
}
@@ -446,10 +469,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,21 +488,17 @@ 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++)
- {
- args[i] = Qnil;
- visargs[i] = Qnil;
- varies[i] = 0;
- }
+ memclear (args, nargs * (2 * word_size + 1));
GCPRO5 (prefix_arg, function, *args, *visargs, up_event);
gcpro3.nvars = nargs;
@@ -488,13 +508,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 +571,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. */
@@ -749,7 +765,7 @@ invoke it. If KEYS is omitted or nil, the return value of
argument if no prefix. */
if (NILP (prefix_arg))
{
- args[i] = Qnil;
+ /* args[i] = Qnil; */
varies[i] = -1;
}
else
@@ -789,21 +805,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,12 +833,12 @@ 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]));
if (record_then_fail)
- Fbarf_if_buffer_read_only ();
+ Fbarf_if_buffer_read_only (Qnil);
Vthis_command = save_this_command;
Vthis_original_command = save_this_original_command;
@@ -829,13 +846,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 +903,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 +961,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 6328ba8349c..63ab9bf70db 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. */
@@ -154,12 +131,12 @@ encode_current_directory (void)
report_file_error ("Setting current directory",
BVAR (current_buffer, directory));
- /* Remove "/:" from dir. */
- if (! NILP (Fstring_match (build_string ("^/:"), dir, Qnil)))
- dir = Fsubstring (dir, make_number (2), Qnil);
+ /* Remove "/:" from DIR and encode it. */
+ dir = ENCODE_FILE (remove_slash_colon (dir));
- if (STRING_MULTIBYTE (dir))
- dir = ENCODE_FILE (dir);
+ if (! file_accessible_directory_p (dir))
+ report_file_error ("Setting current directory",
+ BVAR (current_buffer, directory));
RETURN_UNGCPRO (dir);
}
@@ -172,7 +149,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)
{
@@ -181,7 +159,7 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile)
kill (- p->pid, SIGKILL);
}
- unblock_child_signal ();
+ unblock_child_signal (&oldset);
#endif /* !MSDOS */
}
@@ -286,7 +264,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
infile = build_string (NULL_DEVICE);
GCPRO1 (infile);
- encoded_infile = STRING_MULTIBYTE (infile) ? ENCODE_FILE (infile) : infile;
+ encoded_infile = ENCODE_FILE (infile);
filefd = emacs_open (SSDATA (encoded_infile), O_RDONLY, 0);
if (filefd < 0)
@@ -326,6 +304,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;
@@ -457,9 +436,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
GCPRO4 (buffer, current_dir, error_file, output_file);
- if (STRINGP (error_file) && STRING_MULTIBYTE (error_file))
+ if (STRINGP (error_file))
error_file = ENCODE_FILE (error_file);
- if (STRINGP (output_file) && STRING_MULTIBYTE (output_file))
+ if (STRINGP (output_file))
output_file = ENCODE_FILE (output_file);
UNGCPRO;
}
@@ -486,13 +465,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
report_file_error ("Searching for program", args[0]);
}
- /* If program file name starts with /: for quoting a magic name,
- discard that. */
- if (SBYTES (path) > 2 && SREF (path, 0) == '/'
- && SREF (path, 1) == ':')
- path = Fsubstring (path, make_number (2), Qnil);
+ /* Remove "/:" from PATH. */
+ path = remove_slash_colon (path);
- 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;
@@ -516,8 +492,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
}
else
new_argv[1] = 0;
- if (STRING_MULTIBYTE (path))
- path = ENCODE_FILE (path);
+ path = ENCODE_FILE (path);
new_argv[0] = SSDATA (path);
UNGCPRO;
}
@@ -642,7 +617,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);
@@ -658,6 +633,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];
@@ -674,6 +650,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;
@@ -684,7 +661,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
if (pid == 0)
{
- unblock_child_signal ();
+ unblock_child_signal (&oldset);
setsid ();
@@ -720,7 +697,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
}
}
- unblock_child_signal ();
+ unblock_child_signal (&oldset);
unblock_input ();
if (pid < 0)
@@ -868,7 +845,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
(process_coding.dst_pos_byte
+ process_coding.produced),
0);
- display_on_the_fly = 0;
+ display_on_the_fly = false;
process_coding = saved_coding;
carryover = nread;
/* Make the above condition always fail in the future. */
@@ -900,9 +877,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
/* This variable might have been set to 0 for code
detection. In that case, set it back to 1 because
we should have already detected a coding system. */
- display_on_the_fly = 1;
+ display_on_the_fly = true;
}
- immediate_quit = 1;
+ immediate_quit = true;
QUIT;
}
give_up: ;
@@ -1008,7 +985,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);
@@ -1177,6 +1154,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.
@@ -1200,8 +1210,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 */
@@ -1222,11 +1230,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
@@ -1288,6 +1298,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. */
@@ -1296,9 +1308,10 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
if (STRINGP (display))
{
+ if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
+ exec_failed (new_argv[0], ENOMEM);
char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
- strcpy (vdata, "DISPLAY=");
- strcat (vdata, SSDATA (display));
+ lispstpcpy (stpcpy (vdata, "DISPLAY="), display);
new_env = add_env (env, new_env, vdata);
}
@@ -1371,16 +1384,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);
@@ -1514,14 +1518,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;
@@ -1569,20 +1573,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))
@@ -1633,13 +1630,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;
@@ -1651,12 +1648,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/casefiddle.c b/src/casefiddle.c
index 22680032c0d..8755353240a 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -30,8 +30,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keymap.h"
enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
-
-Lisp_Object Qidentity;
static Lisp_Object
casify_object (enum case_action flag, Lisp_Object obj)
diff --git a/src/casetab.c b/src/casetab.c
index 4bedc1771ce..b086abc0125 100644
--- a/src/casetab.c
+++ b/src/casetab.c
@@ -24,7 +24,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "character.h"
#include "buffer.h"
-static Lisp_Object Qcase_table_p, Qcase_table;
Lisp_Object Vascii_downcase_table;
static Lisp_Object Vascii_upcase_table;
Lisp_Object Vascii_canon_table;
diff --git a/src/category.c b/src/category.c
index 45c944f88aa..b20493e5949 100644
--- a/src/category.c
+++ b/src/category.c
@@ -53,8 +53,6 @@ bset_category_table (struct buffer *b, Lisp_Object val)
For the moment, we are not using this feature. */
static int category_table_version;
-
-static Lisp_Object Qcategory_table, Qcategoryp, Qcategorysetp, Qcategory_table_p;
/* Category set staff. */
@@ -96,7 +94,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 938fba4eae1..053544c8274 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -34,21 +34,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "ccl.h"
#include "coding.h"
-Lisp_Object Qccl, Qcclp;
-
-/* This symbol is a property which associates with ccl program vector.
- Ex: (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector. */
-static Lisp_Object Qccl_program;
-
-/* These symbols are properties which associate with code conversion
- map and their ID respectively. */
-static Lisp_Object Qcode_conversion_map;
-static Lisp_Object Qcode_conversion_map_id;
-
-/* Symbols of ccl program have this property, a value of the property
- is an index for Vccl_program_table. */
-static Lisp_Object Qccl_program_idx;
-
/* Table of registered CCL programs. Each element is a vector of
NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the
name of the program, CCL_PROG (vector) is the compiled code of the
@@ -2160,11 +2145,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;
@@ -2300,8 +2282,17 @@ syms_of_ccl (void)
DEFSYM (Qccl, "ccl");
DEFSYM (Qcclp, "cclp");
+
+ /* This symbol is a property which associates with ccl program vector.
+ Ex: (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector. */
DEFSYM (Qccl_program, "ccl-program");
+
+ /* Symbols of ccl program have this property, a value of the property
+ is an index for Vccl_program_table. */
DEFSYM (Qccl_program_idx, "ccl-program-idx");
+
+ /* These symbols are properties which associate with code conversion
+ map and their ID respectively. */
DEFSYM (Qcode_conversion_map, "code-conversion-map");
DEFSYM (Qcode_conversion_map_id, "code-conversion-map-id");
diff --git a/src/ccl.h b/src/ccl.h
index b01a73f3a2d..7b72dc74104 100644
--- a/src/ccl.h
+++ b/src/ccl.h
@@ -81,8 +81,6 @@ extern bool setup_ccl_program (struct ccl_program *, Lisp_Object);
extern void ccl_driver (struct ccl_program *, int *, int *, int, int,
Lisp_Object);
-extern Lisp_Object Qccl, Qcclp;
-
#define CHECK_CCL_PROGRAM(x) \
do { \
if (NILP (Fccl_program_p (x))) \
diff --git a/src/character.c b/src/character.c
index 1ebc64ae0d7..39d32c9d41a 100644
--- a/src/character.c
+++ b/src/character.c
@@ -48,16 +48,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif /* emacs */
-Lisp_Object Qcharacterp;
-
-static Lisp_Object Qauto_fill_chars;
-
/* Char-table of information about which character to unify to which
Unicode character. Mainly used by the macro MAYBE_UNIFY_CHAR. */
Lisp_Object Vchar_unify_table;
-static Lisp_Object Qchar_script_table;
-
/* If character code C has modifier masks, reflect them to the
@@ -233,45 +227,21 @@ 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
are non-negative integers. The function `max-char' returns the
maximum character code.
-usage: (characterp OBJECT) */)
+usage: (characterp OBJECT) */
+ attributes: const)
(Lisp_Object object, Lisp_Object ignore)
{
return (CHARACTERP (object) ? Qt : Qnil);
}
DEFUN ("max-char", Fmax_char, Smax_char, 0, 0, 0,
- doc: /* Return the character of the maximum code. */)
+ doc: /* Return the character of the maximum code. */
+ attributes: const)
(void)
{
return make_number (MAX_CHAR);
diff --git a/src/character.h b/src/character.h
index 6f243a1392d..5043880cb42 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 *);
@@ -671,7 +657,6 @@ extern ptrdiff_t c_string_width (const unsigned char *, ptrdiff_t, int,
extern ptrdiff_t lisp_string_width (Lisp_Object, ptrdiff_t,
ptrdiff_t *, ptrdiff_t *);
-extern Lisp_Object Qcharacterp;
extern Lisp_Object Vchar_unify_table;
extern Lisp_Object string_escape_byte8 (Lisp_Object);
@@ -679,6 +664,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 be36cbb546b..908084074fd 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -66,16 +66,7 @@ struct charset *charset_table;
static ptrdiff_t charset_table_size;
static int charset_table_used;
-Lisp_Object Qcharsetp;
-
-/* Special charset symbols. */
-Lisp_Object Qascii;
-static Lisp_Object Qeight_bit;
-static Lisp_Object Qiso_8859_1;
-static Lisp_Object Qunicode;
-static Lisp_Object Qemacs;
-
-/* The corresponding charsets. */
+/* Special charsets corresponding to symbols. */
int charset_ascii;
int charset_eight_bit;
static int charset_iso_8859_1;
@@ -88,9 +79,6 @@ int charset_jisx0208_1978;
int charset_jisx0208;
int charset_ksc5601;
-/* Value of charset attribute `charset-iso-plane'. */
-static Lisp_Object Qgl, Qgr;
-
/* Charset of unibyte characters. */
int charset_unibyte;
@@ -101,10 +89,9 @@ Lisp_Object Vcharset_ordered_list;
charsets. */
Lisp_Object Vcharset_non_preferred_head;
-/* Incremented everytime we change Vcharset_ordered_list. This is
- unsigned short so that it fits in Lisp_Int and never matches
- -1. */
-unsigned short charset_ordered_list_tick;
+/* Incremented every time we change the priority of charsets.
+ Wraps around. */
+EMACS_UINT charset_ordered_list_tick;
/* List of iso-2022 charsets. */
Lisp_Object Viso_2022_charset_list;
@@ -389,12 +376,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 +472,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 +652,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 +696,6 @@ map_charset_for_dump (void (*c_function) (Lisp_Object, Lisp_Object),
}
c++;
}
- UNGCPRO;
}
void
@@ -1400,6 +1380,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 +1418,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 +1437,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 +1503,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 +2094,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);
}
@@ -2169,7 +2146,7 @@ DEFUN ("set-charset-priority", Fset_charset_priority, Sset_charset_priority,
usage: (set-charset-priority &rest charsets) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- Lisp_Object new_head, old_list, arglist[2];
+ Lisp_Object new_head, old_list;
Lisp_Object list_2022, list_emacs_mule;
ptrdiff_t i;
int id;
@@ -2185,9 +2162,9 @@ usage: (set-charset-priority &rest charsets) */)
new_head = Fcons (make_number (id), new_head);
}
}
- arglist[0] = Fnreverse (new_head);
- arglist[1] = Vcharset_non_preferred_head = old_list;
- Vcharset_ordered_list = Fnconc (2, arglist);
+ Vcharset_non_preferred_head = old_list;
+ Vcharset_ordered_list = CALLN (Fnconc, Fnreverse (new_head), old_list);
+
charset_ordered_list_tick++;
charset_unibyte = -1;
@@ -2298,7 +2275,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
@@ -2355,12 +2332,14 @@ syms_of_charset (void)
{
DEFSYM (Qcharsetp, "charsetp");
+ /* Special charset symbols. */
DEFSYM (Qascii, "ascii");
DEFSYM (Qunicode, "unicode");
DEFSYM (Qemacs, "emacs");
DEFSYM (Qeight_bit, "eight-bit");
DEFSYM (Qiso_8859_1, "iso-8859-1");
+ /* Value of charset attribute `charset-iso-plane'. */
DEFSYM (Qgl, "gl");
DEFSYM (Qgr, "gr");
@@ -2373,20 +2352,11 @@ syms_of_charset (void)
staticpro (&Vemacs_mule_charset_list);
Vemacs_mule_charset_list = Qnil;
- /* Don't staticpro them here. It's done in syms_of_fns. */
- QCtest = intern_c_string (":test");
- Qeq = intern_c_string ("eq");
-
staticpro (&Vcharset_hash_table);
- {
- Lisp_Object args[2];
- args[0] = QCtest;
- args[1] = Qeq;
- Vcharset_hash_table = Fmake_hash_table (2, args);
- }
+ Vcharset_hash_table = CALLN (Fmake_hash_table, QCtest, Qeq);
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 09235322da7..f6575985a47 100644
--- a/src/charset.h
+++ b/src/charset.h
@@ -253,8 +253,7 @@ extern struct charset *charset_table;
extern Lisp_Object Vcharset_ordered_list;
extern Lisp_Object Vcharset_non_preferred_head;
-/* Incremented everytime we change the priority of charsets. */
-extern unsigned short charset_ordered_list_tick;
+extern EMACS_UINT charset_ordered_list_tick;
extern Lisp_Object Viso_2022_charset_list;
extern Lisp_Object Vemacs_mule_charset_list;
@@ -403,7 +402,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 \
@@ -520,9 +519,6 @@ extern int iso_charset_table[ISO_MAX_DIMENSION][ISO_MAX_CHARS][ISO_MAX_FINAL];
-extern Lisp_Object Qcharsetp;
-
-extern Lisp_Object Qascii;
extern int charset_ascii, charset_eight_bit;
extern int charset_unicode;
extern int charset_jisx0201_roman;
diff --git a/src/chartab.c b/src/chartab.c
index 2a8bbc6983a..acaabce54a7 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -57,9 +57,6 @@ static const int chartab_bits[4] =
/* Preamble for uniprop (Unicode character property) tables. See the
comment of "Unicode character property tables". */
-/* Purpose of uniprop tables. */
-static Lisp_Object Qchar_code_property_table;
-
/* Types of decoder and encoder functions for uniprop values. */
typedef Lisp_Object (*uniprop_decoder_t) (Lisp_Object, Lisp_Object);
typedef Lisp_Object (*uniprop_encoder_t) (Lisp_Object, Lisp_Object);
@@ -140,15 +137,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 +165,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 +213,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 +256,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 +392,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 +447,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 +660,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 +752,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 +947,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 +972,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 +1119,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 +1192,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 +1255,10 @@ 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,
+ CALLN (Fvconcat,
+ XCHAR_TABLE (table)->extras[4],
+ Fmake_vector (make_number (1), value)));
return make_number (i);
}
@@ -1301,9 +1267,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 +1301,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;
@@ -1413,6 +1377,7 @@ CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
void
syms_of_chartab (void)
{
+ /* Purpose of uniprop tables. */
DEFSYM (Qchar_code_property_table, "char-code-property-table");
defsubr (&Smake_char_table);
diff --git a/src/cmds.c b/src/cmds.c
index d64784bd6fe..270fc39cabc 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -31,11 +31,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "dispextern.h"
#include "frame.h"
-static Lisp_Object Qkill_forward_chars, Qkill_backward_chars;
-
-/* A possible value for a buffer's overwrite-mode variable. */
-static Lisp_Object Qoverwrite_mode_binary;
-
static int internal_self_insert (int, EMACS_INT);
DEFUN ("forward-point", Fforward_point, Sforward_point, 1, 1, 0,
@@ -131,12 +126,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 +305,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;
@@ -327,9 +317,6 @@ At the end, it runs `post-self-insert-hook'. */)
return 0. A value of 1 indicates this *might* not have been simple.
A value of 2 means this did things that call for an undo boundary. */
-static Lisp_Object Qexpand_abbrev;
-static Lisp_Object Qpost_self_insert_hook;
-
static int
internal_self_insert (int c, EMACS_INT n)
{
@@ -359,9 +346,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)
@@ -514,7 +499,7 @@ internal_self_insert (int c, EMACS_INT n)
}
/* Run hooks for electric keys. */
- Frun_hooks (1, &Qpost_self_insert_hook);
+ run_hook (Qpost_self_insert_hook);
return hairy;
}
@@ -526,7 +511,10 @@ syms_of_cmds (void)
{
DEFSYM (Qkill_backward_chars, "kill-backward-chars");
DEFSYM (Qkill_forward_chars, "kill-forward-chars");
+
+ /* A possible value for a buffer's overwrite-mode variable. */
DEFSYM (Qoverwrite_mode_binary, "overwrite-mode-binary");
+
DEFSYM (Qexpand_abbrev, "expand-abbrev");
DEFSYM (Qpost_self_insert_hook, "post-self-insert-hook");
diff --git a/src/coding.c b/src/coding.c
index 77583d0d950..54811588c6a 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -303,35 +303,6 @@ encode_coding_XXX (struct coding_system *coding)
Lisp_Object Vcoding_system_hash_table;
-static Lisp_Object Qcoding_system, Qeol_type;
-static Lisp_Object Qcoding_aliases;
-Lisp_Object Qunix, Qdos;
-static Lisp_Object Qmac;
-Lisp_Object Qbuffer_file_coding_system;
-static Lisp_Object Qpost_read_conversion, Qpre_write_conversion;
-static Lisp_Object Qdefault_char;
-Lisp_Object Qno_conversion, Qundecided;
-Lisp_Object Qcharset, Qutf_8;
-static Lisp_Object Qiso_2022;
-static Lisp_Object Qutf_16, Qshift_jis, Qbig5;
-static Lisp_Object Qbig, Qlittle;
-static Lisp_Object Qcoding_system_history;
-static Lisp_Object Qvalid_codes;
-static Lisp_Object QCcategory, QCmnemonic, QCdefault_char;
-static Lisp_Object QCdecode_translation_table, QCencode_translation_table;
-static Lisp_Object QCpost_read_conversion, QCpre_write_conversion;
-static Lisp_Object QCascii_compatible_p;
-
-Lisp_Object Qcall_process, Qcall_process_region;
-Lisp_Object Qstart_process, Qopen_network_stream;
-static Lisp_Object Qtarget_idx;
-
-static Lisp_Object Qinsufficient_source, Qinvalid_source, Qinterrupted;
-
-/* If a symbol has this property, evaluate the value to define the
- symbol as a coding system. */
-static Lisp_Object Qcoding_system_define_form;
-
/* Format of end-of-line decided by system. This is Qunix on
Unix and Mac, Qdos on DOS/Windows.
This has an effect only for external encoding (i.e. for output to
@@ -340,17 +311,6 @@ static Lisp_Object system_eol_type;
#ifdef emacs
-Lisp_Object Qcoding_system_p, Qcoding_system_error;
-
-/* Coding system emacs-mule and raw-text are for converting only
- end-of-line format. */
-Lisp_Object Qemacs_mule, Qraw_text;
-Lisp_Object Qutf_8_emacs;
-
-#if defined (WINDOWSNT) || defined (CYGWIN)
-static Lisp_Object Qutf_16le;
-#endif
-
/* Coding-systems are handed between Emacs Lisp programs and C internal
routines by the following three variables. */
/* Coding system to be used to encode text for terminal display when
@@ -359,11 +319,6 @@ struct coding_system safe_terminal_coding;
#endif /* emacs */
-Lisp_Object Qtranslation_table;
-Lisp_Object Qtranslation_table_id;
-static Lisp_Object Qtranslation_table_for_decode;
-static Lisp_Object Qtranslation_table_for_encode;
-
/* Two special coding systems. */
static Lisp_Object Vsjis_coding_system;
static Lisp_Object Vbig5_coding_system;
@@ -642,15 +597,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 +636,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 +1439,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 +1638,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 +1677,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 +1694,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 +2059,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 +2547,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 +3541,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 +3568,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 +3942,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 +3972,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 +4804,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 +4899,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 +5605,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 +6839,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 +6896,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 +6908,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 +6991,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 +7033,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 +7078,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 +7097,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 +7128,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 +7242,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 +7352,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 +7747,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 +8422,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 +9010,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 +9070,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 +9080,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 +9119,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 +9143,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 +9259,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 +9572,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 +9653,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 +9714,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 +9755,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 +9767,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 +9786,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 +9996,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 +10007,7 @@ make_subsidiaries (Lisp_Object base)
strcpy (buf + base_name_len, suffixes[i]);
ASET (subsidiaries, i, intern (buf));
}
+ SAFE_FREE ();
return subsidiaries;
}
@@ -10713,7 +10671,7 @@ Any alias or subsidiary coding system is not a base coding system. */)
DEFUN ("coding-system-plist", Fcoding_system_plist, Scoding_system_plist,
1, 1, 0,
- doc: "Return the property list of CODING-SYSTEM.")
+ doc: /* Return the property list of CODING-SYSTEM. */)
(Lisp_Object coding_system)
{
Lisp_Object spec, attrs;
@@ -10818,12 +10776,7 @@ void
syms_of_coding (void)
{
staticpro (&Vcoding_system_hash_table);
- {
- Lisp_Object args[2];
- args[0] = QCtest;
- args[1] = Qeq;
- Vcoding_system_hash_table = Fmake_hash_table (2, args);
- }
+ Vcoding_system_hash_table = CALLN (Fmake_hash_table, QCtest, Qeq);
staticpro (&Vsjis_coding_system);
Vsjis_coding_system = Qnil;
@@ -10900,6 +10853,7 @@ syms_of_coding (void)
DEFSYM (Qcoding_system_p, "coding-system-p");
+ /* Error signaled when there's a problem with detecting a coding system. */
DEFSYM (Qcoding_system_error, "coding-system-error");
Fput (Qcoding_system_error, Qerror_conditions,
listn (CONSTYPE_PURE, 2, Qcoding_system_error, Qerror));
@@ -10914,6 +10868,8 @@ syms_of_coding (void)
DEFSYM (Qvalid_codes, "valid-codes");
+ /* Coding system emacs-mule and raw-text are for converting only
+ end-of-line format. */
DEFSYM (Qemacs_mule, "emacs-mule");
DEFSYM (QCcategory, ":category");
@@ -10976,6 +10932,9 @@ syms_of_coding (void)
DEFSYM (Qinsufficient_source, "insufficient-source");
DEFSYM (Qinvalid_source, "invalid-source");
DEFSYM (Qinterrupted, "interrupted");
+
+ /* If a symbol has this property, evaluate the value to define the
+ symbol as a coding system. */
DEFSYM (Qcoding_system_define_form, "coding-system-define-form");
defsubr (&Scoding_system_p);
@@ -11305,63 +11264,59 @@ See also `keyboard-translate-table'.
Use of this variable for character code unification was rendered
obsolete in Emacs 23.1 and later, since Unicode is now the basis of
internal character representation. */);
- Vtranslation_table_for_input = Qnil;
-
- {
- Lisp_Object args[coding_arg_undecided_max];
- Lisp_Object plist[16];
- int i;
-
- for (i = 0; i < coding_arg_undecided_max; i++)
- args[i] = Qnil;
-
- plist[0] = intern_c_string (":name");
- plist[1] = args[coding_arg_name] = Qno_conversion;
- plist[2] = intern_c_string (":mnemonic");
- plist[3] = args[coding_arg_mnemonic] = make_number ('=');
- plist[4] = intern_c_string (":coding-type");
- plist[5] = args[coding_arg_coding_type] = Qraw_text;
- plist[6] = intern_c_string (":ascii-compatible-p");
- plist[7] = args[coding_arg_ascii_compatible_p] = Qt;
- plist[8] = intern_c_string (":default-char");
- plist[9] = args[coding_arg_default_char] = make_number (0);
- plist[10] = intern_c_string (":for-unibyte");
- plist[11] = args[coding_arg_for_unibyte] = Qt;
- plist[12] = intern_c_string (":docstring");
- plist[13] = build_pure_c_string ("Do no conversion.\n\
-\n\
-When you visit a file with this coding, the file is read into a\n\
-unibyte buffer as is, thus each byte of a file is treated as a\n\
-character.");
- plist[14] = intern_c_string (":eol-type");
- plist[15] = args[coding_arg_eol_type] = Qunix;
- args[coding_arg_plist] = Flist (16, plist);
- Fdefine_coding_system_internal (coding_arg_max, args);
-
- plist[1] = args[coding_arg_name] = Qundecided;
- plist[3] = args[coding_arg_mnemonic] = make_number ('-');
- plist[5] = args[coding_arg_coding_type] = Qundecided;
- /* This is already set.
- plist[7] = args[coding_arg_ascii_compatible_p] = Qt; */
- plist[8] = intern_c_string (":charset-list");
- plist[9] = args[coding_arg_charset_list] = Fcons (Qascii, Qnil);
- plist[11] = args[coding_arg_for_unibyte] = Qnil;
- plist[13] = build_pure_c_string ("No conversion on encoding, automatic conversion on decoding.");
- plist[15] = args[coding_arg_eol_type] = Qnil;
- args[coding_arg_plist] = Flist (16, plist);
- args[coding_arg_undecided_inhibit_null_byte_detection] = make_number (0);
- args[coding_arg_undecided_inhibit_iso_escape_detection] = make_number (0);
- Fdefine_coding_system_internal (coding_arg_undecided_max, args);
- }
+ Vtranslation_table_for_input = Qnil;
+
+ Lisp_Object args[coding_arg_undecided_max];
+ memclear (args, sizeof args);
+
+ Lisp_Object plist[] =
+ {
+ intern_c_string (":name"),
+ args[coding_arg_name] = Qno_conversion,
+ intern_c_string (":mnemonic"),
+ args[coding_arg_mnemonic] = make_number ('='),
+ intern_c_string (":coding-type"),
+ args[coding_arg_coding_type] = Qraw_text,
+ intern_c_string (":ascii-compatible-p"),
+ args[coding_arg_ascii_compatible_p] = Qt,
+ intern_c_string (":default-char"),
+ args[coding_arg_default_char] = make_number (0),
+ intern_c_string (":for-unibyte"),
+ args[coding_arg_for_unibyte] = Qt,
+ intern_c_string (":docstring"),
+ (build_pure_c_string
+ ("Do no conversion.\n"
+ "\n"
+ "When you visit a file with this coding, the file is read into a\n"
+ "unibyte buffer as is, thus each byte of a file is treated as a\n"
+ "character.")),
+ intern_c_string (":eol-type"),
+ args[coding_arg_eol_type] = Qunix,
+ };
+ args[coding_arg_plist] = CALLMANY (Flist, plist);
+ Fdefine_coding_system_internal (coding_arg_max, args);
+
+ plist[1] = args[coding_arg_name] = Qundecided;
+ plist[3] = args[coding_arg_mnemonic] = make_number ('-');
+ plist[5] = args[coding_arg_coding_type] = Qundecided;
+ /* This is already set.
+ plist[7] = args[coding_arg_ascii_compatible_p] = Qt; */
+ plist[8] = intern_c_string (":charset-list");
+ plist[9] = args[coding_arg_charset_list] = Fcons (Qascii, Qnil);
+ plist[11] = args[coding_arg_for_unibyte] = Qnil;
+ plist[13] = build_pure_c_string ("No conversion on encoding, "
+ "automatic conversion on decoding.");
+ plist[15] = args[coding_arg_eol_type] = Qnil;
+ args[coding_arg_plist] = CALLMANY (Flist, plist);
+ args[coding_arg_undecided_inhibit_null_byte_detection] = make_number (0);
+ args[coding_arg_undecided_inhibit_iso_escape_detection] = make_number (0);
+ Fdefine_coding_system_internal (coding_arg_undecided_max, args);
setup_coding_system (Qno_conversion, &safe_terminal_coding);
- {
- int i;
+ for (int i = 0; i < coding_category_max; i++)
+ Fset (AREF (Vcoding_category_table, i), Qno_conversion);
- for (i = 0; i < coding_category_max; i++)
- Fset (AREF (Vcoding_category_table, i), Qno_conversion);
- }
#if defined (DOS_NT)
system_eol_type = Qdos;
#else
diff --git a/src/coding.h b/src/coding.h
index a2f9cbc578f..d49d786e6dd 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 */
@@ -768,23 +763,7 @@ extern Lisp_Object from_unicode_buffer (const wchar_t* wstr);
extern Lisp_Object preferred_coding_system (void);
-extern Lisp_Object Qutf_8, Qutf_8_emacs;
-
-extern Lisp_Object Qcoding_category_index;
-extern Lisp_Object Qcoding_system_p;
-extern Lisp_Object Qraw_text, Qemacs_mule, Qno_conversion, Qundecided;
-extern Lisp_Object Qbuffer_file_coding_system;
-
-extern Lisp_Object Qunix, Qdos;
-
-extern Lisp_Object Qtranslation_table;
-extern Lisp_Object Qtranslation_table_id;
-
#ifdef emacs
-extern Lisp_Object Qfile_coding_system;
-extern Lisp_Object Qcall_process, Qcall_process_region;
-extern Lisp_Object Qstart_process, Qopen_network_stream;
-extern Lisp_Object Qwrite_region;
extern char *emacs_strerror (int);
@@ -794,9 +773,6 @@ extern struct coding_system safe_terminal_coding;
#endif
-/* Error signaled when there's a problem with detecting coding system */
-extern Lisp_Object Qcoding_system_error;
-
extern char emacs_mule_bytes[256];
#endif /* EMACS_CODING_H */
diff --git a/src/commands.h b/src/commands.h
index 86ccb95bc51..19cd2e49890 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 8a93687aa00..577b97920f4 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -134,8 +134,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
*/
-Lisp_Object Qcomposition;
-
/* Table of pointers to the structure `composition' indexed by
COMPOSITION-ID. This structure is for storing information about
each composition except for COMPONENTS-VEC. */
@@ -152,8 +150,6 @@ ptrdiff_t n_compositions;
COMPOSITION-ID. */
Lisp_Object composition_hash_table;
-static Lisp_Object Qauto_composed;
-static Lisp_Object Qauto_composition_function;
/* Maximum number of characters to look back for
auto-compositions. */
#define MAX_AUTO_COMPOSITION_LOOKBACK 3
@@ -921,17 +917,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 +1012,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;
+ }
}
}
}
@@ -1068,7 +1060,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))
@@ -1145,7 +1137,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);
@@ -1153,7 +1145,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))
@@ -1487,7 +1479,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
@@ -1511,7 +1503,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) */
{
@@ -1520,7 +1512,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) */
@@ -1536,7 +1528,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;
@@ -1684,9 +1676,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:
@@ -1723,7 +1716,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)
@@ -1742,15 +1735,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);
}
@@ -1795,21 +1783,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;
}
@@ -1906,36 +1891,18 @@ syms_of_composite (void)
DEFSYM (Qcomposition, "composition");
/* Make a hash table for static composition. */
- {
- Lisp_Object args[6];
-
- args[0] = QCtest;
- args[1] = Qequal;
- args[2] = QCweakness;
- /* We used to make the hash table weak so that unreferenced
- compositions can be garbage-collected. But, usually once
- created compositions are repeatedly used in an Emacs session,
- and thus it's not worth to save memory in such a way. So, we
- make the table not weak. */
- args[3] = Qnil;
- args[4] = QCsize;
- args[5] = make_number (311);
- composition_hash_table = Fmake_hash_table (6, args);
- staticpro (&composition_hash_table);
- }
+ /* We used to make the hash table weak so that unreferenced
+ compositions can be garbage-collected. But, usually once
+ created compositions are repeatedly used in an Emacs session,
+ and thus it's not worth to save memory in such a way. So, we
+ make the table not weak. */
+ Lisp_Object args[] = {QCtest, Qequal, QCsize, make_number (311)};
+ composition_hash_table = CALLMANY (Fmake_hash_table, args);
+ staticpro (&composition_hash_table);
/* Make a hash table for glyph-string. */
- {
- Lisp_Object args[6];
- args[0] = QCtest;
- args[1] = Qequal;
- args[2] = QCweakness;
- args[3] = Qnil;
- args[4] = QCsize;
- args[5] = make_number (311);
- gstring_hash_table = Fmake_hash_table (6, args);
- staticpro (&gstring_hash_table);
- }
+ gstring_hash_table = CALLMANY (Fmake_hash_table, args);
+ staticpro (&gstring_hash_table);
staticpro (&gstring_work_headers);
gstring_work_headers = make_uninit_vector (8);
diff --git a/src/composite.h b/src/composite.h
index 95e614ff104..fb9f9eb8655 100644
--- a/src/composite.h
+++ b/src/composite.h
@@ -156,7 +156,7 @@ struct composition {
/* How many columns the overall glyphs occupy on the screen. This
gives an approximate value for column calculation in
Fcurrent_column, and etc. */
- unsigned short width;
+ int width;
/* Method of the composition. */
enum composition_method method;
@@ -190,7 +190,6 @@ extern ptrdiff_t n_compositions;
#define CHECK_BORDER (CHECK_HEAD | CHECK_TAIL)
#define CHECK_ALL (CHECK_BORDER | CHECK_INSIDE)
-extern Lisp_Object Qcomposition;
extern Lisp_Object composition_hash_table;
extern ptrdiff_t get_composition_id (ptrdiff_t, ptrdiff_t, ptrdiff_t,
Lisp_Object, Lisp_Object);
diff --git a/src/conf_post.h b/src/conf_post.h
index 246739d457b..1a080fad635 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,32 @@ 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 (__clang__ \
+ ? __has_attribute (alloc_size) \
+ : 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
@@ -281,8 +311,8 @@ extern void _DebPrint (const char *fmt, ...);
Other .c files should not define INLINE.
C99 compilers compile functions like 'incr' as C99-style extern
- inline functions. Pre-C99 GCCs do something similar with
- GNU-specific keywords. Pre-C99 non-GCC compilers use static
+ inline functions. Buggy GCC implementations do something similar with
+ GNU-specific keywords. Buggy non-GCC compilers use static
functions, which bloats the code but is good enough. */
#ifndef INLINE
@@ -296,12 +326,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 9ea7636f368..d06b9916b3a 100644
--- a/src/data.c
+++ b/src/data.c
@@ -37,59 +37,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "font.h"
#include "keymap.h"
-Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound;
-static Lisp_Object Qsubr;
-Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
-Lisp_Object Qerror, Quser_error, Qquit, Qargs_out_of_range;
-static Lisp_Object Qwrong_length_argument;
-static Lisp_Object Qwrong_type_argument;
-Lisp_Object Qvoid_variable, Qvoid_function;
-static Lisp_Object Qcyclic_function_indirection;
-static Lisp_Object Qcyclic_variable_indirection;
-Lisp_Object Qcircular_list;
-static Lisp_Object Qsetting_constant;
-Lisp_Object Qinvalid_read_syntax;
-Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch;
-Lisp_Object Qend_of_file, Qarith_error, Qmark_inactive;
-Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only;
-Lisp_Object Qtext_read_only;
-
-Lisp_Object Qintegerp, Qwholenump, Qsymbolp, Qlistp, Qconsp;
-static Lisp_Object Qnatnump;
-Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
-Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
-Lisp_Object Qbool_vector_p;
-Lisp_Object Qbuffer_or_string_p;
-static Lisp_Object Qkeywordp, Qboundp;
-Lisp_Object Qfboundp;
-Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
-
-Lisp_Object Qcdr;
-static Lisp_Object Qad_advice_info, Qad_activate_internal;
-
-static Lisp_Object Qdomain_error, Qsingularity_error, Qunderflow_error;
-Lisp_Object Qrange_error, Qoverflow_error;
-
-Lisp_Object Qfloatp;
-Lisp_Object Qnumberp, Qnumber_or_marker_p;
-
-Lisp_Object Qinteger, Qsymbol;
-static Lisp_Object Qcons, Qfloat, Qmisc, Qstring, Qvector;
-Lisp_Object Qwindow;
-static Lisp_Object Qoverlay, Qwindow_configuration;
-static Lisp_Object Qprocess, Qmarker;
-static Lisp_Object Qcompiled_function, Qframe;
-Lisp_Object Qbuffer;
-static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
-static Lisp_Object Qsubrp;
-static Lisp_Object Qmany, Qunevalled;
-Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
-static Lisp_Object Qdefun;
-
-Lisp_Object Qinteractive_form;
-static Lisp_Object Qdefalias_fset_function;
-
-static void swap_in_symval_forwarding (struct Lisp_Symbol *, struct Lisp_Buffer_Local_Value *);
+static void swap_in_symval_forwarding (struct Lisp_Symbol *,
+ struct Lisp_Buffer_Local_Value *);
static bool
BOOLFWDP (union Lisp_Fwd *a)
@@ -227,7 +176,8 @@ args_out_of_range_3 (Lisp_Object a1, Lisp_Object a2, Lisp_Object a3)
/* Data type predicates. */
DEFUN ("eq", Feq, Seq, 2, 2, 0,
- doc: /* Return t if the two args are the same Lisp object. */)
+ doc: /* Return t if the two args are the same Lisp object. */
+ attributes: const)
(Lisp_Object obj1, Lisp_Object obj2)
{
if (EQ (obj1, obj2))
@@ -236,7 +186,8 @@ DEFUN ("eq", Feq, Seq, 2, 2, 0,
}
DEFUN ("null", Fnull, Snull, 1, 1, 0,
- doc: /* Return t if OBJECT is nil. */)
+ doc: /* Return t if OBJECT is nil. */
+ attributes: const)
(Lisp_Object object)
{
if (NILP (object))
@@ -314,7 +265,8 @@ for example, (type-of 1) returns `integer'. */)
}
DEFUN ("consp", Fconsp, Sconsp, 1, 1, 0,
- doc: /* Return t if OBJECT is a cons cell. */)
+ doc: /* Return t if OBJECT is a cons cell. */
+ attributes: const)
(Lisp_Object object)
{
if (CONSP (object))
@@ -323,7 +275,8 @@ DEFUN ("consp", Fconsp, Sconsp, 1, 1, 0,
}
DEFUN ("atom", Fatom, Satom, 1, 1, 0,
- doc: /* Return t if OBJECT is not a cons cell. This includes nil. */)
+ doc: /* Return t if OBJECT is not a cons cell. This includes nil. */
+ attributes: const)
(Lisp_Object object)
{
if (CONSP (object))
@@ -333,7 +286,8 @@ DEFUN ("atom", Fatom, Satom, 1, 1, 0,
DEFUN ("listp", Flistp, Slistp, 1, 1, 0,
doc: /* Return t if OBJECT is a list, that is, a cons cell or nil.
-Otherwise, return nil. */)
+Otherwise, return nil. */
+ attributes: const)
(Lisp_Object object)
{
if (CONSP (object) || NILP (object))
@@ -342,7 +296,8 @@ Otherwise, return nil. */)
}
DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0,
- doc: /* Return t if OBJECT is not a list. Lists include nil. */)
+ doc: /* Return t if OBJECT is not a list. Lists include nil. */
+ attributes: const)
(Lisp_Object object)
{
if (CONSP (object) || NILP (object))
@@ -351,7 +306,8 @@ DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0,
}
DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0,
- doc: /* Return t if OBJECT is a symbol. */)
+ doc: /* Return t if OBJECT is a symbol. */
+ attributes: const)
(Lisp_Object object)
{
if (SYMBOLP (object))
@@ -384,7 +340,8 @@ DEFUN ("vectorp", Fvectorp, Svectorp, 1, 1, 0,
}
DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0,
- doc: /* Return t if OBJECT is a string. */)
+ doc: /* Return t if OBJECT is a string. */
+ attributes: const)
(Lisp_Object object)
{
if (STRINGP (object))
@@ -487,7 +444,8 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
}
DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
- doc: /* Return t if OBJECT is a character or a string. */)
+ doc: /* Return t if OBJECT is a character or a string. */
+ attributes: const)
(register Lisp_Object object)
{
if (CHARACTERP (object) || STRINGP (object))
@@ -496,7 +454,8 @@ DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
}
DEFUN ("integerp", Fintegerp, Sintegerp, 1, 1, 0,
- doc: /* Return t if OBJECT is an integer. */)
+ doc: /* Return t if OBJECT is an integer. */
+ attributes: const)
(Lisp_Object object)
{
if (INTEGERP (object))
@@ -514,7 +473,8 @@ DEFUN ("integer-or-marker-p", Finteger_or_marker_p, Sinteger_or_marker_p, 1, 1,
}
DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0,
- doc: /* Return t if OBJECT is a nonnegative integer. */)
+ doc: /* Return t if OBJECT is a nonnegative integer. */
+ attributes: const)
(Lisp_Object object)
{
if (NATNUMP (object))
@@ -523,7 +483,8 @@ DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0,
}
DEFUN ("numberp", Fnumberp, Snumberp, 1, 1, 0,
- doc: /* Return t if OBJECT is a number (floating point or integer). */)
+ doc: /* Return t if OBJECT is a number (floating point or integer). */
+ attributes: const)
(Lisp_Object object)
{
if (NUMBERP (object))
@@ -543,7 +504,8 @@ DEFUN ("number-or-marker-p", Fnumber_or_marker_p,
}
DEFUN ("floatp", Ffloatp, Sfloatp, 1, 1, 0,
- doc: /* Return t if OBJECT is a floating point number. */)
+ doc: /* Return t if OBJECT is a floating point number. */
+ attributes: const)
(Lisp_Object object)
{
if (FLOATP (object))
@@ -727,6 +689,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))
+ emacs_abort ();
+
set_symbol_function (symbol, definition);
return definition;
@@ -966,6 +933,50 @@ 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,
+ CALLN (Fconcat, 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 +1033,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 +1916,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 +2353,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 +2405,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 +2896,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
@@ -2958,7 +2966,8 @@ DEFUN ("lognot", Flognot, Slognot, 1, 1, 0,
DEFUN ("byteorder", Fbyteorder, Sbyteorder, 0, 0, 0,
doc: /* Return the byteorder for the machine.
Returns 66 (ASCII uppercase B) for big endian machines or 108 (ASCII
-lowercase l) for small endian machines. */)
+lowercase l) for small endian machines. */
+ attributes: const)
(void)
{
unsigned i = 0x04030201;
@@ -3536,10 +3545,6 @@ syms_of_data (void)
PUT_ERROR (Qunderflow_error, Fcons (Qdomain_error, arith_tail),
"Arithmetic underflow error");
- staticpro (&Qnil);
- staticpro (&Qt);
- staticpro (&Qunbound);
-
/* Types that type-of returns. */
DEFSYM (Qinteger, "integer");
DEFSYM (Qsymbol, "symbol");
@@ -3643,7 +3648,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 40e2b370456..54e92cce16e 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -41,37 +41,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif
-/* Subroutines. */
-static Lisp_Object Qdbus__init_bus;
-static Lisp_Object Qdbus_get_unique_name;
-static Lisp_Object Qdbus_message_internal;
-
-/* D-Bus error symbol. */
-static Lisp_Object Qdbus_error;
-
-/* Lisp symbols of the system and session buses. */
-static Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
-
-/* Lisp symbol for method call timeout. */
-static Lisp_Object QCdbus_timeout;
-
-/* Lisp symbols of D-Bus types. */
-static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
-static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
-static Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
-static Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
-static Lisp_Object QCdbus_type_double, QCdbus_type_string;
-static Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
-#ifdef DBUS_TYPE_UNIX_FD
-static Lisp_Object QCdbus_type_unix_fd;
-#endif
-static Lisp_Object QCdbus_type_array, QCdbus_type_variant;
-static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
-
-/* Lisp symbols of objects in `dbus-registered-objects-table'. */
-static Lisp_Object QCdbus_registered_serial, QCdbus_registered_method;
-static Lisp_Object QCdbus_registered_signal;
-
/* Alist of D-Bus buses we are polling for messages.
The key is the symbol or string of the bus, and the value is the
connection address. */
@@ -142,10 +111,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 +120,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
@@ -361,7 +326,7 @@ xd_signature_cat (char *signature, char const *x)
ptrdiff_t xlen = strlen (x);
if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen)
string_overflow ();
- strcat (signature, x);
+ strcpy (signature + siglen, x);
}
/* Compute SIGNATURE of OBJECT. It must have a form that it can be
@@ -765,7 +730,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 +1023,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 +1189,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 +1705,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)
{
@@ -1754,15 +1724,21 @@ syms_of_dbusbind (void)
DEFSYM (Qdbus_message_internal, "dbus-message-internal");
defsubr (&Sdbus_message_internal);
+ /* D-Bus error symbol. */
DEFSYM (Qdbus_error, "dbus-error");
Fput (Qdbus_error, Qerror_conditions,
list2 (Qdbus_error, Qerror));
Fput (Qdbus_error, Qerror_message,
build_pure_c_string ("D-Bus error"));
+ /* Lisp symbols of the system and session buses. */
DEFSYM (QCdbus_system_bus, ":system");
DEFSYM (QCdbus_session_bus, ":session");
+
+ /* Lisp symbol for method call timeout. */
DEFSYM (QCdbus_timeout, ":timeout");
+
+ /* Lisp symbols of D-Bus types. */
DEFSYM (QCdbus_type_byte, ":byte");
DEFSYM (QCdbus_type_boolean, ":boolean");
DEFSYM (QCdbus_type_int16, ":int16");
@@ -1782,6 +1758,8 @@ syms_of_dbusbind (void)
DEFSYM (QCdbus_type_variant, ":variant");
DEFSYM (QCdbus_type_struct, ":struct");
DEFSYM (QCdbus_type_dict_entry, ":dict-entry");
+
+ /* Lisp symbols of objects in `dbus-registered-objects-table'. */
DEFSYM (QCdbus_registered_serial, ":serial");
DEFSYM (QCdbus_registered_method, ":method");
DEFSYM (QCdbus_registered_signal, ":signal");
@@ -1871,12 +1849,7 @@ string denoting the bus address. SERIAL is the serial number of the
non-blocking method call, a reply is expected. Both arguments must
not be nil. The value in the hash table is HANDLER, the function to
be called when the D-Bus reply message arrives. */);
- {
- Lisp_Object args[2];
- args[0] = QCtest;
- args[1] = Qequal;
- Vdbus_registered_objects_table = Fmake_hash_table (2, args);
- }
+ Vdbus_registered_objects_table = CALLN (Fmake_hash_table, QCtest, Qequal);
DEFVAR_LISP ("dbus-debug", Vdbus_debug,
doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
diff --git a/src/decompress.c b/src/decompress.c
index 0e4209b655b..b14f0a2cd79 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -28,29 +28,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <verify.h>
-static Lisp_Object Qzlib_dll;
-
#ifdef WINDOWSNT
-#include <windows.h>
-#include "w32.h"
-
-/* Macro for defining functions that will be loaded from the zlib DLL. */
-#define DEF_ZLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
-
-/* Macro for loading zlib functions from the library. */
-#define LOAD_ZLIB_FN(lib,func) { \
- fn_##func = (void *) GetProcAddress (lib, #func); \
- if (!fn_##func) return false; \
- }
-
-DEF_ZLIB_FN (int, inflateInit2_,
- (z_streamp strm, int windowBits, const char *version, int stream_size));
+# include <windows.h>
+# include "w32.h"
-DEF_ZLIB_FN (int, inflate,
- (z_streamp strm, int flush));
-
-DEF_ZLIB_FN (int, inflateEnd,
- (z_streamp strm));
+DEF_DLL_FN (int, inflateInit2_,
+ (z_streamp strm, int windowBits, const char *version,
+ int stream_size));
+DEF_DLL_FN (int, inflate, (z_streamp strm, int flush));
+DEF_DLL_FN (int, inflateEnd, (z_streamp strm));
static bool zlib_initialized;
@@ -60,25 +46,21 @@ 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);
- LOAD_ZLIB_FN (library, inflateEnd);
+ LOAD_DLL_FN (library, inflateInit2_);
+ LOAD_DLL_FN (library, inflate);
+ LOAD_DLL_FN (library, inflateEnd);
return true;
}
-#define fn_inflateInit2(strm, windowBits) \
- fn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
-
-#else /* !WINDOWSNT */
+# undef inflate
+# undef inflateEnd
+# undef inflateInit2_
-#define fn_inflateInit2 inflateInit2
-#define fn_inflate inflate
-#define fn_inflateEnd inflateEnd
+# define inflate fn_inflate
+# define inflateEnd fn_inflateEnd
+# define inflateInit2_ fn_inflateInit2_
#endif /* WINDOWSNT */
@@ -93,7 +75,7 @@ static void
unwind_decompress (void *ddata)
{
struct decompress_unwind_data *data = ddata;
- fn_inflateEnd (data->stream);
+ inflateEnd (data->stream);
/* Delete any uncompressed data already inserted on error. */
if (data->start)
@@ -150,7 +132,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
@@ -167,7 +152,7 @@ This function can be called only in unibyte buffers. */)
/* The magic number 32 apparently means "autodetect both the gzip and
zlib formats" according to zlib.h. */
- if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK)
+ if (inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK)
return Qnil;
unwind_data.start = iend;
@@ -197,7 +182,7 @@ This function can be called only in unibyte buffers. */)
stream.avail_in = avail_in;
stream.next_out = GPT_ADDR;
stream.avail_out = avail_out;
- inflate_status = fn_inflate (&stream, Z_NO_FLUSH);
+ inflate_status = inflate (&stream, Z_NO_FLUSH);
pos_byte += avail_in - stream.avail_in;
decompressed = avail_out - stream.avail_out;
insert_from_gap (decompressed, decompressed, 0);
diff --git a/src/deps.mk b/src/deps.mk
index 2ba214f82a8..71a5f42d22e 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -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 5d7977bf024..e31fdf87ac2 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -51,13 +51,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "msdos.h" /* for fstatat */
#endif
-static Lisp_Object Qdirectory_files;
-static Lisp_Object Qdirectory_files_and_attributes;
-static Lisp_Object Qfile_name_completion;
-static Lisp_Object Qfile_name_all_completions;
-static Lisp_Object Qfile_attributes;
-static Lisp_Object Qfile_attributes_lessp;
-
static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
static Lisp_Object file_attributes (int, char const *, Lisp_Object);
@@ -183,10 +176,8 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
/* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
run_pre_post_conversion_on_str which calls Lisp directly and
indirectly. */
- if (STRING_MULTIBYTE (dirfilename))
- dirfilename = ENCODE_FILE (dirfilename);
- encoded_directory = (STRING_MULTIBYTE (directory)
- ? ENCODE_FILE (directory) : directory);
+ dirfilename = ENCODE_FILE (dirfilename);
+ encoded_directory = ENCODE_FILE (directory);
/* Now *bufp is the compiled form of MATCH; don't call anything
which might compile a new regexp until we're done with the loop! */
@@ -450,7 +441,6 @@ These are all file names in directory DIRECTORY which begin with FILE. */)
}
static int file_name_completion_stat (int, struct dirent *, struct stat *);
-static Lisp_Object Qdefault_directory;
static Lisp_Object
file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
@@ -490,7 +480,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
/* Actually, this is not quite true any more: we do most of the completion
work with decoded file names, but we still do some filtering based
on the encoded file name. */
- encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
+ encoded_file = ENCODE_FILE (file);
encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname));
@@ -642,23 +632,14 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
name = DECODE_FILE (name);
{
- Lisp_Object regexps;
+ Lisp_Object regexps, table = (completion_ignore_case
+ ? Vascii_canon_table : Qnil);
/* Ignore this element if it fails to match all the regexps. */
- if (completion_ignore_case)
- {
- for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCDR (regexps))
- if (fast_string_match_ignore_case (XCAR (regexps), name) < 0)
- break;
- }
- else
- {
- for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCDR (regexps))
- if (fast_string_match (XCAR (regexps), name) < 0)
- break;
- }
+ for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+ regexps = XCDR (regexps))
+ if (fast_string_match_internal (XCAR (regexps), name, table) < 0)
+ break;
if (CONSP (regexps))
continue;
@@ -933,7 +914,6 @@ so last access time will always be midnight of that day. */)
static Lisp_Object
file_attributes (int fd, char const *name, Lisp_Object id_format)
{
- Lisp_Object values[12];
struct stat s;
int lstat_result;
@@ -960,10 +940,6 @@ file_attributes (int fd, char const *name, Lisp_Object id_format)
if (lstat_result < 0)
return Qnil;
- values[0] = (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name)
- : S_ISDIR (s.st_mode) ? Qt : Qnil);
- values[1] = make_number (s.st_nlink);
-
if (!(NILP (id_format) || EQ (id_format, Qinteger)))
{
block_input ();
@@ -971,34 +947,35 @@ file_attributes (int fd, char const *name, Lisp_Object id_format)
gname = stat_gname (&s);
unblock_input ();
}
- if (uname)
- values[2] = DECODE_SYSTEM (build_unibyte_string (uname));
- else
- values[2] = make_fixnum_or_float (s.st_uid);
- if (gname)
- values[3] = DECODE_SYSTEM (build_unibyte_string (gname));
- else
- values[3] = make_fixnum_or_float (s.st_gid);
-
- values[4] = make_lisp_time (get_stat_atime (&s));
- values[5] = make_lisp_time (get_stat_mtime (&s));
- values[6] = make_lisp_time (get_stat_ctime (&s));
-
- /* If the file size is a 4-byte type, assume that files of sizes in
- the 2-4 GiB range wrap around to negative values, as this is a
- common bug on older 32-bit platforms. */
- if (sizeof (s.st_size) == 4)
- values[7] = make_fixnum_or_float (s.st_size & 0xffffffffu);
- else
- values[7] = make_fixnum_or_float (s.st_size);
filemodestring (&s, modes);
- values[8] = make_string (modes, 10);
- values[9] = Qt;
- 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 CALLN (Flist,
+ (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name)
+ : S_ISDIR (s.st_mode) ? Qt : Qnil),
+ make_number (s.st_nlink),
+ (uname
+ ? DECODE_SYSTEM (build_unibyte_string (uname))
+ : make_fixnum_or_float (s.st_uid)),
+ (gname
+ ? DECODE_SYSTEM (build_unibyte_string (gname))
+ : make_fixnum_or_float (s.st_gid)),
+ make_lisp_time (get_stat_atime (&s)),
+ make_lisp_time (get_stat_mtime (&s)),
+ make_lisp_time (get_stat_ctime (&s)),
+
+ /* If the file size is a 4-byte type, assume that
+ files of sizes in the 2-4 GiB range wrap around to
+ negative values, as this is a common bug on older
+ 32-bit platforms. */
+ make_fixnum_or_float (sizeof (s.st_size) == 4
+ ? s.st_size & 0xffffffffu
+ : s.st_size),
+
+ make_string (modes, 10),
+ Qt,
+ INTEGER_TO_CONS (s.st_ino),
+ INTEGER_TO_CONS (s.st_dev));
}
DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0,
diff --git a/src/dispextern.h b/src/dispextern.h
index d6bbb0b4c6c..31e7262d6ec 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
};
@@ -388,10 +389,9 @@ struct glyph
/* Lisp object source of this glyph. Currently either a buffer or a
string, if the glyph was produced from characters which came from
- a buffer or a string; or Lisp integer zero (a.k.a. "null object")
- if the glyph was inserted by redisplay for its own purposes, such
- as padding or truncation/continuation glyphs, or the
- overlay-arrow glyphs on TTYs. */
+ a buffer or a string; or nil if the glyph was inserted by
+ redisplay for its own purposes, such as padding, truncation, or
+ continuation glyphs, or the overlay-arrow glyphs on TTYs. */
Lisp_Object object;
/* Width in pixels. */
@@ -444,8 +444,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 +1716,10 @@ struct face
attributes except the font. */
struct face *ascii_face;
- /* Extra member that a font-driver uses privately. */
+#if defined HAVE_XFT || defined HAVE_FREETYPE
+/* Extra member that a font-driver uses privately. */
void *extra;
+#endif
};
@@ -1795,16 +1797,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 +1856,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 +1895,40 @@ 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;
+typedef enum { NEUTRAL_DIR = 0, 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. This should be as tightly packed as possible, because there
+ are 127 such entries in each iterator state, and so the size of
+ cache is directly affected by the size of this struct. */
struct bidi_stack {
- int level;
- bidi_dir_t override;
+ ptrdiff_t next_for_neutral_pos;
+ unsigned next_for_neutral_type : 3;
+ unsigned last_strong_type : 3;
+ unsigned prev_for_neutral_type : 3;
+ unsigned char level;
+ unsigned char flags; /* sos, override, isolate_status */
};
/* 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 */
@@ -2512,11 +2524,11 @@ struct it
Object is normally the buffer which is being rendered, but it can
also be a Lisp string in case the current display element comes
from an overlay string or from a display string (before- or
- after-string). It may also be nil when a C string is being
- rendered, e.g., during mode-line or header-line update. It can
- also be a cons cell of the form `(space ...)', when we produce a
- stretch glyph from a `display' specification. Finally, it can be
- a zero-valued Lisp integer, but only temporarily, when we are
+ after-string). It may also be a zero-valued Lisp integer when a
+ C string is being rendered, e.g., during mode-line or header-line
+ update. It can also be a cons cell of the form `(space ...)',
+ when we produce a stretch glyph from a `display' specification.
+ Finally, it can be nil, but only temporarily, when we are
producing special glyphs for display purposes, like truncation
and continuation glyphs, or blanks that extend each line to the
edge of the window on a TTY.
@@ -2834,45 +2846,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 */
};
@@ -2888,8 +2906,8 @@ struct redisplay_interface
struct image_type
{
- /* A symbol uniquely identifying the image type, .e.g `jpeg'. */
- Lisp_Object *type;
+ /* Index of a symbol uniquely identifying the image type, e.g., 'jpeg'. */
+ int type;
/* Check that SPEC is a valid image specification for the given
image type. Value is true if SPEC is valid. */
@@ -3158,6 +3176,7 @@ extern void bidi_push_it (struct bidi_it *);
extern void bidi_pop_it (struct bidi_it *);
extern void *bidi_shelve_cache (void);
extern void bidi_unshelve_cache (void *, bool);
+extern ptrdiff_t bidi_find_first_overridden (struct bidi_it *);
/* Defined in xdisp.c */
@@ -3169,9 +3188,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 *);
@@ -3181,7 +3199,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 *,
@@ -3204,7 +3221,6 @@ void move_it_in_display_line (struct it *it,
enum move_operation_enum op);
bool in_display_vector_p (struct it *);
int frame_mode_line_height (struct frame *);
-extern Lisp_Object Qtool_bar;
extern bool redisplaying_p;
extern bool help_echo_showing_p;
extern Lisp_Object help_echo_string, help_echo_window;
@@ -3244,9 +3260,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 *);
@@ -3285,7 +3299,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 *);
@@ -3359,35 +3372,31 @@ void x_free_colors (struct frame *, unsigned long *, int);
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
+void clear_face_cache (bool);
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 *);
-int lookup_named_face (struct frame *, Lisp_Object, int);
+#endif
+int lookup_named_face (struct frame *, Lisp_Object, bool);
int lookup_basic_face (struct frame *, int);
int smaller_face (struct frame *, int, int);
int face_with_height (struct frame *, int, int);
-int lookup_derived_face (struct frame *, Lisp_Object, int, int);
+int lookup_derived_face (struct frame *, Lisp_Object, int, bool);
void init_frame_faces (struct frame *);
void free_frame_faces (struct frame *);
void recompute_basic_faces (struct frame *);
-int face_at_buffer_position (struct window *w, ptrdiff_t pos,
- ptrdiff_t *endptr, ptrdiff_t limit,
- int mouse, int base_face_id);
-int face_for_overlay_string (struct window *w, ptrdiff_t pos,
- ptrdiff_t *endptr, ptrdiff_t limit,
- int mouse, Lisp_Object overlay);
-int face_at_string_position (struct window *w, Lisp_Object string,
- ptrdiff_t pos, ptrdiff_t bufpos,
- ptrdiff_t *endptr, enum face_id, int mouse);
+int face_at_buffer_position (struct window *, ptrdiff_t, ptrdiff_t *, ptrdiff_t,
+ bool, int);
+int face_for_overlay_string (struct window *, ptrdiff_t, ptrdiff_t *, ptrdiff_t,
+ bool, Lisp_Object);
+int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t,
+ ptrdiff_t *, enum face_id, bool);
int merge_faces (struct frame *, Lisp_Object, int, int);
int compute_char_face (struct frame *, int, Lisp_Object);
void free_all_realized_faces (Lisp_Object);
-extern Lisp_Object Qforeground_color, Qbackground_color;
extern char unspecified_fg[], unspecified_bg[];
/* Defined in xfns.c. */
@@ -3402,6 +3411,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;
@@ -3409,14 +3419,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
@@ -3439,11 +3441,11 @@ extern void hide_hourglass (void);
#endif /* HAVE_WINDOW_SYSTEM */
-/* Defined in xmenu.c */
+/* Defined in xmenu.c. */
int popup_activated (void);
-/* Defined in dispnew.c */
+/* Defined in dispnew.c. */
extern Lisp_Object buffer_posn_from_coords (struct window *,
int *, int *,
@@ -3479,16 +3481,15 @@ void blank_row (struct window *, struct glyph_row *, int);
void clear_glyph_matrix_rows (struct glyph_matrix *, int, int);
void clear_glyph_row (struct glyph_row *);
void prepare_desired_row (struct window *, struct glyph_row *, bool);
-void update_single_window (struct window *, bool);
+void update_single_window (struct window *);
void do_pending_window_change (bool);
void change_frame_size (struct frame *, int, int, bool, bool, bool, bool);
void init_display (void);
void syms_of_display (void);
-extern Lisp_Object Qredisplay_dont_pause;
extern void spec_glyph_lookup_face (struct window *, GLYPH *);
extern void fill_up_frame_row_with_spaces (struct glyph_row *, int);
-/* Defined in terminal.c */
+/* Defined in terminal.c. */
extern void ring_bell (struct frame *);
extern void update_begin (struct frame *);
@@ -3516,7 +3517,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 *);
@@ -3524,13 +3524,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 205c28f7df8..3c8117e6b65 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 *);
@@ -103,8 +102,6 @@ static void set_window_update_flags (struct window *w, bool on_p);
bool display_completed;
-Lisp_Object Qdisplay_table, Qredisplay_dont_pause;
-
/* True means SIGWINCH happened when not safe. */
static bool delayed_size_change;
@@ -1108,10 +1105,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)
{
@@ -1342,8 +1339,8 @@ realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim)
ptrdiff_t old_nglyphs = pool->nglyphs;
pool->glyphs = xpalloc (pool->glyphs, &pool->nglyphs,
needed - old_nglyphs, -1, sizeof *pool->glyphs);
- memset (pool->glyphs + old_nglyphs, 0,
- (pool->nglyphs - old_nglyphs) * sizeof *pool->glyphs);
+ memclear (pool->glyphs + old_nglyphs,
+ (pool->nglyphs - old_nglyphs) * sizeof *pool->glyphs);
}
/* Remember the number of rows and columns because (a) we use them
@@ -2015,12 +2012,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 +2119,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 +2135,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 +2684,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 +2707,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 +2801,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 +2878,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 +2961,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;
}
@@ -3046,10 +3049,10 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
struct window *root_window = XWINDOW (f->root_window);
if (redisplay_dont_pause)
- force_p = 1;
+ force_p = true;
else if (!force_p && detect_input_pending_ignore_squeezables ())
{
- paused_p = 1;
+ paused_p = true;
goto do_pause;
}
@@ -3069,7 +3072,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
/* Update the menu bar on X frames that don't have toolkit
support. */
if (WINDOWP (f->menu_bar_window))
- update_window (XWINDOW (f->menu_bar_window), 1);
+ update_window (XWINDOW (f->menu_bar_window), true);
#endif
#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
@@ -3083,7 +3086,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
{
Lisp_Object tem;
- update_window (w, 1);
+ update_window (w, true);
w->must_be_updated_p = false;
/* Swap tool-bar strings. We swap because we want to
@@ -3108,7 +3111,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
/* Build F's desired matrix from window matrices. */
build_frame_matrix (f);
- /* Update the display */
+ /* Update the display. */
update_begin (f);
paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1);
update_end (f);
@@ -3220,7 +3223,7 @@ update_window_tree (struct window *w, bool force_p)
If FORCE_P, don't stop updating if input is pending. */
void
-update_single_window (struct window *w, bool force_p)
+update_single_window (struct window *w)
{
if (w->must_be_updated_p)
{
@@ -3229,12 +3232,9 @@ update_single_window (struct window *w, bool force_p)
/* Record that this is not a frame-based redisplay. */
set_frame_matrix_frame (NULL);
- if (redisplay_dont_pause)
- force_p = 1;
-
/* Update W. */
update_begin (f);
- update_window (w, force_p);
+ update_window (w, true);
update_end (f);
/* Reset flag in W. */
@@ -3423,7 +3423,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 +4539,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 +4572,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 +4600,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 +4650,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 +4671,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 +4697,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 +4707,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 +4721,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;
}
@@ -5153,7 +5162,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
Fset_buffer (old_current_buffer);
- *dx = x0 + it.first_visible_x - it.current_x;
+ *dx = to_x - it.current_x;
*dy = *y - it.current_y;
string = w->contents;
@@ -5228,9 +5237,9 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
}
/* Add extra (default width) columns if clicked after EOL. */
- x1 = max (0, it.current_x + it.pixel_width - it.first_visible_x);
- if (x0 > x1)
- it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w);
+ x1 = max (0, it.current_x + it.pixel_width);
+ if (to_x > x1)
+ it.hpos += (to_x - x1) / WINDOW_FRAME_COLUMN_WIDTH (w);
*x = it.hpos;
*y = it.vpos;
@@ -5435,7 +5444,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 +5487,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 +5499,64 @@ 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,
+ Qchange_frame_size);
+ }
+}
- 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 +5607,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)
@@ -5878,7 +5784,7 @@ immediately by pending input. */)
{
ptrdiff_t count;
- swallow_events (1);
+ swallow_events (true);
if ((detect_input_pending_run_timers (1)
&& NILP (force) && !redisplay_dont_pause)
|| !NILP (Vexecuting_kbd_macro))
@@ -6178,7 +6084,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 +6093,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
@@ -6286,7 +6190,9 @@ syms_of_display (void)
frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
staticpro (&frame_and_buffer_state);
+ /* This is the "purpose" slot of a display table. */
DEFSYM (Qdisplay_table, "display-table");
+
DEFSYM (Qredisplay_dont_pause, "redisplay-dont-pause");
DEFVAR_INT ("baud-rate", baud_rate,
@@ -6359,8 +6265,15 @@ See `buffer-display-table' for more information. */);
Vstandard_display_table = Qnil;
DEFVAR_BOOL ("redisplay-dont-pause", redisplay_dont_pause,
- doc: /* Non-nil means display update isn't paused when input is detected. */);
- redisplay_dont_pause = 1;
+ doc: /* Nil means display update is paused when input is detected. */);
+ /* Contrary to expectations, a value of "false" can be detrimental to
+ responsiveness since aborting a redisplay throws away some of the
+ work already performed. It's usually more efficient (and gives
+ more prompt feedback to the user) to let the redisplay terminate,
+ and just completely skip the next command's redisplay (which is
+ done regardless of this setting if there's pending input at the
+ beginning of the next redisplay). */
+ redisplay_dont_pause = true;
#ifdef CANNOT_DUMP
if (noninteractive)
diff --git a/src/disptab.h b/src/disptab.h
index cea040fe8aa..7afc862312a 100644
--- a/src/disptab.h
+++ b/src/disptab.h
@@ -48,9 +48,6 @@ extern struct Lisp_Char_Table *window_display_table (struct window *);
/* Defined in indent.c. */
extern struct Lisp_Char_Table *buffer_display_table (void);
-/* This is the `purpose' slot of a display table. */
-extern Lisp_Object Qdisplay_table;
-
/* Return the current length of the GLYPH table,
or 0 if the table isn't currently valid. */
#define GLYPH_TABLE_LENGTH \
diff --git a/src/doc.c b/src/doc.c
index 3bb67849d4a..8b18fb0a5a2 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -35,14 +35,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "keymap.h"
-Lisp_Object Qfunction_documentation;
-
/* Buffer used for reading from documentation file. */
static char *get_doc_string_buffer;
static ptrdiff_t get_doc_string_buffer_size;
static unsigned char *read_bytecode_pointer;
+static char const sibling_etc[] = "../etc/";
+
/* `readchar' in lread.c calls back here to fetch the next byte.
If UNREADFLAG is 1, we unread a byte. */
@@ -81,7 +81,6 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
{
char *from, *to, *name, *p, *p1;
int fd;
- ptrdiff_t minsize;
int offset;
EMACS_INT position;
Lisp_Object file, tem, pos;
@@ -114,21 +113,14 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
tem = Ffile_name_absolute_p (file);
file = ENCODE_FILE (file);
- if (NILP (tem))
- {
- Lisp_Object docdir = ENCODE_FILE (Vdoc_directory);
- minsize = SCHARS (docdir);
- /* sizeof ("../etc/") == 8 */
- if (minsize < 8)
- minsize = 8;
- name = SAFE_ALLOCA (minsize + SCHARS (file) + 8);
- strcpy (name, SSDATA (docdir));
- strcat (name, SSDATA (file));
- }
- else
- {
- name = SSDATA (file);
- }
+ Lisp_Object docdir
+ = NILP (tem) ? ENCODE_FILE (Vdoc_directory) : empty_unibyte_string;
+ ptrdiff_t docdir_sizemax = SBYTES (docdir) + 1;
+#ifndef CANNOT_DUMP
+ docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc);
+#endif
+ name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file));
+ lispstpcpy (lispstpcpy (name, docdir), file);
fd = emacs_open (name, O_RDONLY, 0);
if (fd < 0)
@@ -138,8 +130,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
{
/* Preparing to dump; DOC file is probably not installed.
So check in ../etc. */
- strcpy (name, "../etc/");
- strcat (name, SSDATA (file));
+ lispstpcpy (stpcpy (name, sibling_etc), file);
fd = emacs_open (name, O_RDONLY, 0);
}
@@ -147,8 +138,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 ();
@@ -307,19 +299,6 @@ read_doc_string (Lisp_Object filepos)
static bool
reread_doc_file (Lisp_Object file)
{
-#if 0
- Lisp_Object reply, prompt[3];
- struct gcpro gcpro1;
- GCPRO1 (file);
- prompt[0] = build_string ("File ");
- prompt[1] = NILP (file) ? Vdoc_file_name : file;
- prompt[2] = build_string (" is out of sync. Reload? ");
- reply = Fy_or_n_p (Fconcat (3, prompt));
- UNGCPRO;
- if (NILP (reply))
- return 0;
-#endif
-
if (NILP (file))
Fsnarf_documentation (Vdoc_file_name);
else
@@ -562,6 +541,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 =
@@ -578,16 +559,20 @@ the same file name is found in the `doc-directory'. */)
(0)
#endif /* CANNOT_DUMP */
{
- name = alloca (SCHARS (filename) + 14);
- strcpy (name, "../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);
}
- strcat (name, SSDATA (filename)); /*** Add this line ***/
+
+ count = SPECPDL_INDEX ();
+ USE_SAFE_ALLOCA;
+ name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1);
+ lispstpcpy (stpcpy (name, dirname), filename); /*** Add this line ***/
/* Vbuild_files is nil when temacs is run, and non-nil after that. */
if (NILP (Vbuild_files))
@@ -596,7 +581,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);
@@ -609,7 +594,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;
@@ -638,7 +622,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')
@@ -689,6 +673,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 e2cf6f20533..e506e9fbe14 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;
@@ -416,13 +409,11 @@ msdos_stdcolor_idx (const char *name)
Lisp_Object
msdos_stdcolor_name (int idx)
{
- extern Lisp_Object Qunspecified;
-
if (idx == FACE_TTY_DEFAULT_FG_COLOR)
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 +632,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 c6d95b06905..1c0d2f755f2 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 cc546f70c92..7026ccc084e 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -64,30 +64,35 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
extern Lisp_Object w32_get_internal_run_time (void);
#endif
+static struct lisp_time lisp_time_struct (Lisp_Object, int *);
+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);
-static Lisp_Object Qbuffer_access_fontify_functions;
-
-/* Symbol for the text property used to mark fields. */
-
-Lisp_Object Qfield;
-
-/* A special value for Qfield properties. */
-
-static Lisp_Object Qboundary;
+#ifndef HAVE_TM_GMTOFF
+# define HAVE_TM_GMTOFF false
+#endif
-/* 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";
+
+/* The cached value of Vsystem_name. This is used only to compare it
+ to Vsystem_name, so it need not be visible to the GC. */
+static Lisp_Object cached_system_name;
+static void
+init_and_cache_system_name (void)
+{
+ init_system_name ();
+ cached_system_name = Vsystem_name;
+}
void
init_editfns (void)
@@ -98,21 +103,46 @@ init_editfns (void)
Lisp_Object tem;
/* Set up system_name even when dumping. */
- init_system_name ();
+ init_and_cache_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 +406,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 +789,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);
}
@@ -883,17 +905,11 @@ save_excursion_restore (Lisp_Object info)
if (! NILP (tem))
{
if (! EQ (omark, nmark))
- {
- tem = intern ("activate-mark-hook");
- Frun_hooks (1, &tem);
- }
+ run_hook (intern ("activate-mark-hook"));
}
/* If mark has ceased to be active, run deactivate hook. */
else if (! NILP (tem1))
- {
- tem = intern ("deactivate-mark-hook");
- Frun_hooks (1, &tem);
- }
+ run_hook (intern ("deactivate-mark-hook"));
/* If buffer was visible in a window, and a different window was
selected, and the old selected window is still showing this
@@ -1325,17 +1341,15 @@ 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));
+ char *s = lispstpcpy (&r[q - p], login);
r[q - p] = upcase ((unsigned char) r[q - p]);
- strcat (r, q + 1);
+ strcpy (s, q + 1);
full = build_string (r);
+ SAFE_FREE ();
}
#endif /* AMPERSAND_FULL_NAME */
@@ -1346,6 +1360,8 @@ DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
doc: /* Return the host name of the machine you are running on, as a string. */)
(void)
{
+ if (EQ (Vsystem_name, cached_system_name))
+ init_and_cache_system_name ();
return Vsystem_name;
}
@@ -1373,30 +1389,60 @@ time_overflow (void)
error ("Specified time is not representable");
}
+static void
+invalid_time (void)
+{
+ error ("Invalid time specification");
+}
+
+/* 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)
{
- time_t hi = t >> 16;
+ time_t hi = t >> LO_TIME_BITS;
/* Check for overflow, helping the compiler for common cases where
no runtime check is needed, and taking care not to convert
negative numbers to unsigned before comparing them. */
if (! ((! TYPE_SIGNED (time_t)
- || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16
+ || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> LO_TIME_BITS
|| MOST_NEGATIVE_FIXNUM <= hi)
- && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM
+ && (TIME_T_MAX >> LO_TIME_BITS <= MOST_POSITIVE_FIXNUM
|| hi <= MOST_POSITIVE_FIXNUM)))
time_overflow ();
return hi;
}
-/* Return the bottom 16 bits of the time T. */
+/* Return the bottom bits of the time T. */
static int
lo_time (time_t t)
{
- return t & ((1 << 16) - 1);
+ return t & ((1 << LO_TIME_BITS) - 1);
}
DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
@@ -1410,6 +1456,96 @@ picosecond counts. */)
return make_lisp_time (current_timespec ());
}
+static struct lisp_time
+time_add (struct lisp_time ta, struct lisp_time tb)
+{
+ EMACS_INT hi = ta.hi + tb.hi;
+ int lo = ta.lo + tb.lo;
+ int us = ta.us + tb.us;
+ int ps = ta.ps + tb.ps;
+ us += (1000000 <= ps);
+ ps -= (1000000 <= ps) * 1000000;
+ lo += (1000000 <= us);
+ us -= (1000000 <= us) * 1000000;
+ hi += (1 << LO_TIME_BITS <= lo);
+ lo -= (1 << LO_TIME_BITS <= lo) << LO_TIME_BITS;
+ return (struct lisp_time) { hi, lo, us, ps };
+}
+
+static struct lisp_time
+time_subtract (struct lisp_time ta, struct lisp_time tb)
+{
+ EMACS_INT hi = ta.hi - tb.hi;
+ int lo = ta.lo - tb.lo;
+ int us = ta.us - tb.us;
+ int ps = ta.ps - tb.ps;
+ us -= (ps < 0);
+ ps += (ps < 0) * 1000000;
+ lo -= (us < 0);
+ us += (us < 0) * 1000000;
+ hi -= (lo < 0);
+ lo += (lo < 0) << LO_TIME_BITS;
+ return (struct lisp_time) { hi, lo, us, ps };
+}
+
+static Lisp_Object
+time_arith (Lisp_Object a, Lisp_Object b,
+ struct lisp_time (*op) (struct lisp_time, struct lisp_time))
+{
+ int alen, blen;
+ struct lisp_time ta = lisp_time_struct (a, &alen);
+ struct lisp_time tb = lisp_time_struct (b, &blen);
+ struct lisp_time t = op (ta, tb);
+ if (! (MOST_NEGATIVE_FIXNUM <= t.hi && t.hi <= MOST_POSITIVE_FIXNUM))
+ time_overflow ();
+ Lisp_Object val = Qnil;
+
+ switch (max (alen, blen))
+ {
+ default:
+ val = Fcons (make_number (t.ps), val);
+ /* Fall through. */
+ case 3:
+ val = Fcons (make_number (t.us), val);
+ /* Fall through. */
+ case 2:
+ val = Fcons (make_number (t.lo), val);
+ val = Fcons (make_number (t.hi), val);
+ break;
+ }
+
+ return val;
+}
+
+DEFUN ("time-add", Ftime_add, Stime_add, 2, 2, 0,
+ doc: /* Return the sum of two time values A and B, as a time value. */)
+ (Lisp_Object a, Lisp_Object b)
+{
+ return time_arith (a, b, time_add);
+}
+
+DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
+ doc: /* Return the difference between two time values A and B, as a time value. */)
+ (Lisp_Object a, Lisp_Object b)
+{
+ return time_arith (a, b, time_subtract);
+}
+
+DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0,
+ doc: /* Return non-nil if time value T1 is earlier than time value T2. */)
+ (Lisp_Object t1, Lisp_Object t2)
+{
+ int t1len, t2len;
+ struct lisp_time a = lisp_time_struct (t1, &t1len);
+ struct lisp_time b = lisp_time_struct (t2, &t2len);
+ return ((a.hi != b.hi ? a.hi < b.hi
+ : a.lo != b.lo ? a.lo < b.lo
+ : a.us != b.us ? a.us < b.us
+ : a.ps < b.ps)
+ ? Qt : Qnil);
+}
+
+
DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
0, 0, 0,
doc: /* Return the current run time used by Emacs.
@@ -1448,21 +1584,6 @@ does the same thing as `current-time'. */)
}
-/* Make a Lisp list that represents the time T with fraction TAIL. */
-static Lisp_Object
-make_time_tail (time_t t, Lisp_Object tail)
-{
- return Fcons (make_number (hi_time (t)),
- Fcons (make_number (lo_time (t)), tail));
-}
-
-/* Make a Lisp list that represents the system time T. */
-static Lisp_Object
-make_time (time_t t)
-{
- return make_time_tail (t, Qnil);
-}
-
/* Make a Lisp list that represents the Emacs time T. T may be an
invalid time, with a slightly negative tv_nsec value such as
UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a
@@ -1470,23 +1591,30 @@ make_time (time_t t)
Lisp_Object
make_lisp_time (struct timespec t)
{
+ time_t s = t.tv_sec;
int ns = t.tv_nsec;
- return make_time_tail (t.tv_sec, list2i (ns / 1000, ns % 1000 * 1000));
+ return list4i (hi_time (s), lo_time (s), ns / 1000, ns % 1000 * 1000);
}
/* Decode a Lisp list SPECIFIED_TIME that represents a time.
Set *PHIGH, *PLOW, *PUSEC, *PPSEC to its parts; do not check their values.
- Return true if successful. */
-static bool
+ Return 2, 3, or 4 to indicate the effective length of SPECIFIED_TIME
+ if successful, 0 if unsuccessful. */
+static int
disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
Lisp_Object *plow, Lisp_Object *pusec,
Lisp_Object *ppsec)
{
+ Lisp_Object high = make_number (0);
+ Lisp_Object low = specified_time;
+ Lisp_Object usec = make_number (0);
+ Lisp_Object psec = make_number (0);
+ int len = 4;
+
if (CONSP (specified_time))
{
- Lisp_Object low = XCDR (specified_time);
- Lisp_Object usec = make_number (0);
- Lisp_Object psec = make_number (0);
+ high = XCAR (specified_time);
+ low = XCDR (specified_time);
if (CONSP (low))
{
Lisp_Object low_tail = XCDR (low);
@@ -1497,39 +1625,119 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
low_tail = XCDR (low_tail);
if (CONSP (low_tail))
psec = XCAR (low_tail);
+ else
+ len = 3;
}
else if (!NILP (low_tail))
- usec = low_tail;
+ {
+ usec = low_tail;
+ len = 3;
+ }
+ else
+ len = 2;
}
+ else
+ len = 2;
- *phigh = XCAR (specified_time);
- *plow = low;
- *pusec = usec;
- *ppsec = psec;
- return 1;
+ /* When combining components, require LOW to be an integer,
+ as otherwise it would be a pain to add up times. */
+ if (! INTEGERP (low))
+ return 0;
}
+ else if (INTEGERP (specified_time))
+ len = 2;
+
+ *phigh = high;
+ *plow = low;
+ *pusec = usec;
+ *ppsec = psec;
+ return len;
+}
- return 0;
+/* Convert T into an Emacs time *RESULT, truncating toward minus infinity.
+ Return true if T is in range, false otherwise. */
+static bool
+decode_float_time (double t, struct lisp_time *result)
+{
+ double lo_multiplier = 1 << LO_TIME_BITS;
+ double emacs_time_min = MOST_NEGATIVE_FIXNUM * lo_multiplier;
+ if (! (emacs_time_min <= t && t < -emacs_time_min))
+ return false;
+
+ double small_t = t / lo_multiplier;
+ EMACS_INT hi = small_t;
+ double t_sans_hi = t - hi * lo_multiplier;
+ int lo = t_sans_hi;
+ long double fracps = (t_sans_hi - lo) * 1e12L;
+#ifdef INT_FAST64_MAX
+ int_fast64_t ifracps = fracps;
+ int us = ifracps / 1000000;
+ int ps = ifracps % 1000000;
+#else
+ int us = fracps / 1e6L;
+ int ps = fracps - us * 1e6L;
+#endif
+ us -= (ps < 0);
+ ps += (ps < 0) * 1000000;
+ lo -= (us < 0);
+ us += (us < 0) * 1000000;
+ hi -= (lo < 0);
+ lo += (lo < 0) << LO_TIME_BITS;
+ result->hi = hi;
+ result->lo = lo;
+ result->us = us;
+ result->ps = ps;
+ return true;
}
/* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp
list, generate the corresponding time value.
+ If LOW is floating point, the other components should be zero.
- 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 RESULT is not null, store into *RESULT the converted time.
If *DRESULT is not null, store into *DRESULT the number of
seconds since the start of the POSIX Epoch.
- Return true if successful. */
+ Return true if successful, false if the components are of the
+ wrong type or represent a time out of range. */
bool
decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
Lisp_Object psec,
- struct timespec *result, double *dresult)
+ struct lisp_time *result, double *dresult)
{
EMACS_INT hi, lo, us, ps;
- if (! (INTEGERP (high) && INTEGERP (low)
+ if (! (INTEGERP (high)
&& INTEGERP (usec) && INTEGERP (psec)))
- return 0;
+ return false;
+ if (! INTEGERP (low))
+ {
+ if (FLOATP (low))
+ {
+ double t = XFLOAT_DATA (low);
+ if (result && ! decode_float_time (t, result))
+ return false;
+ if (dresult)
+ *dresult = t;
+ return true;
+ }
+ else if (NILP (low))
+ {
+ struct timespec now = current_timespec ();
+ if (result)
+ {
+ result->hi = hi_time (now.tv_sec);
+ result->lo = lo_time (now.tv_sec);
+ result->us = now.tv_nsec / 1000;
+ result->ps = now.tv_nsec % 1000 * 1000;
+ }
+ if (dresult)
+ *dresult = now.tv_sec + now.tv_nsec / 1e9;
+ return true;
+ }
+ else
+ return false;
+ }
+
hi = XINT (high);
lo = XINT (low);
us = XINT (usec);
@@ -1539,74 +1747,85 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
each overflow into the next higher-order component. */
us += ps / 1000000 - (ps % 1000000 < 0);
lo += us / 1000000 - (us % 1000000 < 0);
- hi += lo >> 16;
+ hi += lo >> LO_TIME_BITS;
ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0);
us = us % 1000000 + 1000000 * (us % 1000000 < 0);
- lo &= (1 << 16) - 1;
+ lo &= (1 << LO_TIME_BITS) - 1;
if (result)
{
- if ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi)
- && hi <= TIME_T_MAX >> 16)
- {
- /* Return the greatest representable time that is not greater
- than the requested time. */
- time_t sec = hi;
- *result = make_timespec ((sec << 16) + lo, us * 1000 + ps / 1000);
- }
- else
- {
- /* Overflow in the highest-order component. */
- return 0;
- }
+ if (! (MOST_NEGATIVE_FIXNUM <= hi && hi <= MOST_POSITIVE_FIXNUM))
+ return false;
+ result->hi = hi;
+ result->lo = lo;
+ result->us = us;
+ result->ps = ps;
}
if (dresult)
- *dresult = (us * 1e6 + ps) / 1e12 + lo + hi * 65536.0;
+ {
+ double dhi = hi;
+ *dresult = (us * 1e6 + ps) / 1e12 + lo + dhi * (1 << LO_TIME_BITS);
+ }
+
+ return true;
+}
- return 1;
+struct timespec
+lisp_to_timespec (struct lisp_time t)
+{
+ if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
+ && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
+ return invalid_timespec ();
+ time_t s = (t.hi << LO_TIME_BITS) + t.lo;
+ int ns = t.us * 1000 + t.ps / 1000;
+ return make_timespec (s, ns);
}
/* Decode a Lisp list SPECIFIED_TIME that represents a time.
+ Store its effective length into *PLEN.
If SPECIFIED_TIME is nil, use the current time.
+ Signal an error if SPECIFIED_TIME does not represent a time. */
+static struct lisp_time
+lisp_time_struct (Lisp_Object specified_time, int *plen)
+{
+ Lisp_Object high, low, usec, psec;
+ struct lisp_time t;
+ int len = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec);
+ if (! (len && decode_time_components (high, low, usec, psec, &t, 0)))
+ invalid_time ();
+ *plen = len;
+ return t;
+}
- Round the time down to the nearest struct timespec value.
- Return seconds since the Epoch.
- Signal an error if unsuccessful. */
+/* Like lisp_time_struct, except return a struct timespec.
+ Discard any low-order digits. */
struct timespec
lisp_time_argument (Lisp_Object specified_time)
{
- struct timespec t;
- if (NILP (specified_time))
- t = current_timespec ();
- else
- {
- Lisp_Object high, low, usec, psec;
- if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
- && decode_time_components (high, low, usec, psec, &t, 0)))
- error ("Invalid time specification");
- }
+ int len;
+ struct lisp_time lt = lisp_time_struct (specified_time, &len);
+ struct timespec t = lisp_to_timespec (lt);
+ if (! timespec_valid_p (t))
+ time_overflow ();
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)
{
- if (NILP (specified_time))
- return time (NULL);
- 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, make_number (0),
- make_number (0), &t, 0)))
- error ("Invalid time specification");
- return t.tv_sec;
- }
+ Lisp_Object high, low, usec, psec;
+ struct lisp_time t;
+ if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
+ && decode_time_components (high, low, make_number (0),
+ make_number (0), &t, 0)))
+ invalid_time ();
+ if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
+ && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
+ time_overflow ();
+ return (t.hi << LO_TIME_BITS) + t.lo;
}
DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0,
@@ -1624,18 +1843,10 @@ or (if you need time as a string) `format-time-string'. */)
(Lisp_Object specified_time)
{
double t;
- if (NILP (specified_time))
- {
- struct timespec now = current_timespec ();
- t = now.tv_sec + now.tv_nsec / 1e9;
- }
- else
- {
- Lisp_Object high, low, usec, psec;
- if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
- && decode_time_components (high, low, usec, psec, 0, &t)))
- error ("Invalid time specification");
- }
+ Lisp_Object high, low, usec, psec;
+ if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
+ && decode_time_components (high, low, usec, psec, 0, &t)))
+ invalid_time ();
return make_float (t);
}
@@ -1767,39 +1978,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 +2023,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 CALLN (Flist,
+ 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
@@ -1871,6 +2063,29 @@ check_tm_member (Lisp_Object obj, int offset)
return n - offset;
}
+/* Decode ZONE as a time zone specification. */
+
+static Lisp_Object
+decode_time_zone (Lisp_Object zone)
+{
+ if (EQ (zone, Qt))
+ return build_string ("UTC0");
+ else if (STRINGP (zone))
+ return zone;
+ else if (INTEGERP (zone))
+ {
+ static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
+ char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
+ EMACS_INT abszone = eabs (XINT (zone)), zone_hr = abszone / (60 * 60);
+ int zone_min = (abszone / 60) % 60, zone_sec = abszone % 60;
+
+ return make_formatted_string (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0],
+ zone_hr, zone_min, zone_sec);
+ }
+ else
+ xsignal2 (Qerror, build_string ("Invalid time zone specification"), zone);
+}
+
DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
doc: /* Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.
This is the reverse operation of `decode-time', which see.
@@ -1910,63 +2125,18 @@ 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";
- else if (STRINGP (zone))
- tzstring = SSDATA (zone);
- else if (INTEGERP (zone))
- {
- EMACS_INT abszone = eabs (XINT (zone));
- EMACS_INT zone_hr = abszone / (60*60);
- int zone_min = (abszone/60) % 60;
- int zone_sec = abszone % 60;
- sprintf (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0],
- zone_hr, zone_min, zone_sec);
- 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);
- }
-
- 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 = tzalloc (SSDATA (decode_time_zone (zone)));
+ value = mktime_z (tz, &tm);
+ tzfree (tz);
}
if (value == (time_t) -1)
time_overflow ();
- return make_time (value);
+ return list2i (hi_time (value), lo_time (value));
}
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
@@ -1986,34 +2156,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 +2203,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 +2232,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);
}
}
@@ -2093,7 +2265,8 @@ the data it can't find. */)
DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
If TZ is nil, use implementation-defined default time zone information.
-If TZ is t, use Universal Time.
+If TZ is t, use Universal Time. If TZ is an integer, it is treated as in
+`encode-time'.
Instead of calling this function, you typically want (setenv "TZ" TZ).
That changes both the environment of the Emacs process and the
@@ -2101,17 +2274,7 @@ variable `process-environment', whereas `set-time-zone-rule' affects
only the former. */)
(Lisp_Object tz)
{
- const char *tzstring;
-
- if (! (NILP (tz) || EQ (tz, Qt)))
- CHECK_STRING (tz);
-
- if (NILP (tz))
- tzstring = initial_tz;
- else if (EQ (tz, Qt))
- tzstring = "UTC0";
- else
- tzstring = SSDATA (tz);
+ const char *tzstring = NILP (tz) ? initial_tz : SSDATA (decode_time_zone (tz));
block_input ();
set_time_zone_rule (tzstring);
@@ -2122,12 +2285,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 +2299,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;
- }
- 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;
- }
+ /* Although this is not thread-safe, in practice this runs only
+ on startup when there is only one thread. */
+ xputenv (tzval);
}
-#ifdef LOCALTIME_CACHE
+#ifdef HAVE_TZSET
tzset ();
#endif
}
@@ -2238,7 +2373,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);
@@ -2489,15 +2624,34 @@ make_buffer_string_both (ptrdiff_t start, ptrdiff_t start_byte,
ptrdiff_t end, ptrdiff_t end_byte, bool props)
{
Lisp_Object result, tem, tem1;
+ ptrdiff_t beg0, end0, beg1, end1, size;
- if (start < GPT && GPT < end)
- move_gap_both (start, start_byte);
+ if (start_byte < GPT_BYTE && GPT_BYTE < end_byte)
+ {
+ /* Two regions, before and after the gap. */
+ beg0 = start_byte;
+ end0 = GPT_BYTE;
+ beg1 = GPT_BYTE + GAP_SIZE - BEG_BYTE;
+ end1 = end_byte + GAP_SIZE - BEG_BYTE;
+ }
+ else
+ {
+ /* The only region. */
+ beg0 = start_byte;
+ end0 = end_byte;
+ beg1 = -1;
+ end1 = -1;
+ }
if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
result = make_uninit_multibyte_string (end - start, end_byte - start_byte);
else
result = make_uninit_string (end - start);
- memcpy (SDATA (result), BYTE_POS_ADDR (start_byte), end_byte - start_byte);
+
+ size = end0 - beg0;
+ memcpy (SDATA (result), BYTE_POS_ADDR (beg0), size);
+ if (beg1 != -1)
+ memcpy (SDATA (result) + size, BEG_ADDR + beg1, end1 - beg1);
/* If desired, update and copy the text properties. */
if (props)
@@ -2525,25 +2679,20 @@ update_buffer_properties (ptrdiff_t start, ptrdiff_t end)
call them, specifying the range of the buffer being accessed. */
if (!NILP (Vbuffer_access_fontify_functions))
{
- Lisp_Object args[3];
- Lisp_Object tem;
-
- args[0] = Qbuffer_access_fontify_functions;
- XSETINT (args[1], start);
- XSETINT (args[2], end);
-
/* But don't call them if we can tell that the work
has already been done. */
if (!NILP (Vbuffer_access_fontified_property))
{
- tem = Ftext_property_any (args[1], args[2],
- Vbuffer_access_fontified_property,
- Qnil, Qnil);
- if (! NILP (tem))
- Frun_hook_with_args (3, args);
+ Lisp_Object tem
+ = Ftext_property_any (make_number (start), make_number (end),
+ Vbuffer_access_fontified_property,
+ Qnil, Qnil);
+ if (NILP (tem))
+ return;
}
- else
- Frun_hook_with_args (3, args);
+
+ CALLN (Frun_hook_with_args, Qbuffer_access_fontify_functions,
+ make_number (start), make_number (end));
}
}
@@ -2852,7 +3001,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 +3094,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 +3160,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 +3190,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 +3203,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 +3283,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 +3757,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 +4034,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 +4324,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 +4338,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 +4510,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 CALLN (Fformat, format, arg0, arg1);
}
DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
@@ -4616,11 +4770,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 +4786,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,
@@ -4815,6 +4967,7 @@ functions if all the text being accessed has this property. */);
DEFVAR_LISP ("system-name", Vsystem_name,
doc: /* The host name of the machine Emacs is running on. */);
+ Vsystem_name = cached_system_name = Qnil;
DEFVAR_LISP ("user-full-name", Vuser_full_name,
doc: /* The full name of the user logged in. */);
@@ -4845,8 +4998,12 @@ functions if all the text being accessed has this property. */);
defsubr (&Sregion_beginning);
defsubr (&Sregion_end);
+ /* Symbol for the text property used to mark fields. */
DEFSYM (Qfield, "field");
+
+ /* A special value for Qfield properties. */
DEFSYM (Qboundary, "boundary");
+
defsubr (&Sfield_beginning);
defsubr (&Sfield_end);
defsubr (&Sfield_string);
@@ -4894,6 +5051,9 @@ functions if all the text being accessed has this property. */);
defsubr (&Suser_full_name);
defsubr (&Semacs_pid);
defsubr (&Scurrent_time);
+ defsubr (&Stime_add);
+ defsubr (&Stime_subtract);
+ defsubr (&Stime_less_p);
defsubr (&Sget_internal_run_time);
defsubr (&Sformat_time_string);
defsubr (&Sfloat_time);
diff --git a/src/emacs.c b/src/emacs.c
index 33e8e9df7ba..345fe3e75b8 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -51,15 +51,14 @@ 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 */
-#ifdef NS_IMPL_GNUSTEP
-/* At least under Debian, GSConfig is in a subdirectory. --Stef */
-#include <GNUstepBase/GSConfig.h>
-#endif
-
#include "commands.h"
#include "intervals.h"
#include "character.h"
@@ -79,7 +78,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"
#include "gnutls.h"
@@ -103,8 +104,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;
@@ -119,6 +121,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
@@ -130,21 +135,14 @@ 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
-Lisp_Object Qfile_name_handler_alist;
-
-Lisp_Object Qrisky_local_variable;
-
-Lisp_Object Qkill_emacs;
-static Lisp_Object Qkill_emacs_hook;
-
/* If true, Emacs should not attempt to use a window-specific code,
but instead should use the virtual terminal under which it was started. */
bool inhibit_window_system;
@@ -208,7 +206,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[] =
{ "\
@@ -319,7 +317,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"
};
@@ -384,10 +382,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;
@@ -411,7 +410,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);
@@ -429,7 +428,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);
}
}
@@ -565,12 +564,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
@@ -723,18 +716,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);
@@ -801,10 +789,10 @@ main (int argc, char **argv)
version = emacs_version;
copyright = emacs_copyright;
}
- printf ("GNU Emacs %s\n", version);
+ printf ("%s %s\n", PACKAGE_NAME, version);
printf ("%s\n", copyright);
- printf ("GNU Emacs comes with ABSOLUTELY NO WARRANTY.\n");
- printf ("You may redistribute copies of Emacs\n");
+ printf ("%s comes with ABSOLUTELY NO WARRANTY.\n", PACKAGE_NAME);
+ printf ("You may redistribute copies of %s\n", PACKAGE_NAME);
printf ("under the terms of the GNU General Public License.\n");
printf ("For more information about these matters, ");
printf ("see the file named COPYING.\n");
@@ -863,7 +851,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
@@ -897,7 +884,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);
@@ -905,22 +892,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.
@@ -998,7 +975,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);
}
@@ -1140,12 +1117,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 ();
@@ -1366,7 +1344,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. */
@@ -1547,8 +1526,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. */
@@ -1585,26 +1579,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
@@ -1629,15 +1603,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 */
@@ -1805,7 +1770,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;
@@ -1827,8 +1792,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))
@@ -1923,7 +1887,8 @@ or SIGHUP, and upon SIGINT in batch mode.
The value of `kill-emacs-hook', if not void,
is a list of functions (of no args),
-all of which are called before Emacs is actually killed. */)
+all of which are called before Emacs is actually killed. */
+ attributes: noreturn)
(Lisp_Object arg)
{
struct gcpro gcpro1;
@@ -1937,7 +1902,7 @@ all of which are called before Emacs is actually killed. */)
/* Fsignal calls emacs_abort () if it sees that waiting_for_input is
set. */
waiting_for_input = 0;
- Frun_hooks (1, &Qkill_emacs_hook);
+ run_hook (Qkill_emacs_hook);
UNGCPRO;
#ifdef HAVE_X_WINDOWS
@@ -2021,9 +1986,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. */
@@ -2078,6 +2041,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. */
@@ -2118,38 +2084,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
@@ -2331,7 +2281,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);
@@ -2448,6 +2401,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. */);
@@ -2525,6 +2484,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 cf062194cb1..b98b224e622 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -27,11 +27,7 @@ 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
+#include "buffer.h"
/* Chain of condition and catch handlers currently in effect. */
@@ -42,22 +38,6 @@ struct handler *handlerlist;
int gcpro_level;
#endif
-Lisp_Object Qautoload, Qmacro, Qexit, Qinteractive, Qcommandp;
-Lisp_Object Qinhibit_quit;
-Lisp_Object Qand_rest;
-static Lisp_Object Qand_optional;
-static Lisp_Object Qinhibit_debugger;
-static Lisp_Object Qdeclare;
-Lisp_Object Qinternal_interpreter_environment, Qclosure;
-
-static Lisp_Object Qdebug;
-
-/* This holds either the symbol `run-hooks' or nil.
- It is nil at an early stage of startup, and when Emacs
- is shutting down. */
-
-Lisp_Object Vrun_hooks;
-
/* Non-nil means record all fset's and provide's, to be undone
if the file being autoloaded is not fully loaded.
They are recorded by being consed onto the front of Vautoload_queue:
@@ -65,6 +45,11 @@ Lisp_Object Vrun_hooks;
Lisp_Object Vautoload_queue;
+/* This holds either the symbol `run-hooks' or nil.
+ It is nil at an early stage of startup, and when Emacs
+ is shutting down. */
+Lisp_Object Vrun_hooks;
+
/* Current number of specbindings allocated in specpdl, not counting
the dummy entry specpdl[-1]. */
@@ -97,10 +82,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. */
@@ -1179,7 +1162,8 @@ unwind_to_catch (struct handler *catch, Lisp_Object value)
DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
doc: /* Throw to the catch for TAG and return VALUE from it.
-Both TAG and VALUE are evalled. */)
+Both TAG and VALUE are evalled. */
+ attributes: noreturn)
(register Lisp_Object tag, Lisp_Object value)
{
struct handler *c;
@@ -1273,7 +1257,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 +1299,7 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
return val;
}
}
- }
+ }
val = eval_sub (bodyform);
handlerlist = oldhandlerlist;
@@ -2274,17 +2261,13 @@ 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;
- register Lisp_Object spread_arg;
- register Lisp_Object *funcall_args;
- Lisp_Object fun, retval;
- struct gcpro gcpro1;
+ ptrdiff_t i, numargs, funcall_nargs;
+ register Lisp_Object *funcall_args = NULL;
+ register Lisp_Object spread_arg = args[nargs - 1];
+ Lisp_Object fun = args[0];
+ Lisp_Object retval;
USE_SAFE_ALLOCA;
- fun = args [0];
- funcall_args = 0;
- spread_arg = args [nargs - 1];
CHECK_LIST (spread_arg);
numargs = XINT (Flength (spread_arg));
@@ -2302,38 +2285,29 @@ usage: (apply FUNCTION &rest ARGUMENTS) */)
/* Optimize for no indirection. */
if (SYMBOLP (fun) && !NILP (fun)
&& (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
- fun = indirect_function (fun);
- if (NILP (fun))
{
- /* Let funcall get the error. */
- fun = args[0];
- goto funcall;
+ fun = indirect_function (fun);
+ if (NILP (fun))
+ /* Let funcall get the error. */
+ fun = args[0];
}
- if (SUBRP (fun))
+ if (SUBRP (fun) && XSUBR (fun)->max_args > numargs
+ /* Don't hide an error by adding missing arguments. */
+ && numargs >= XSUBR (fun)->min_args)
{
- if (numargs < XSUBR (fun)->min_args
- || (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
- goto funcall; /* Let funcall get the error. */
- else if (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args > numargs)
- {
- /* 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;)
- funcall_args[++i] = Qnil;
- GCPRO1 (*funcall_args);
- gcpro1.nvars = 1 + XSUBR (fun)->max_args;
- }
+ /* 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);
+ memclear (funcall_args + numargs + 1,
+ (XSUBR (fun)->max_args - numargs) * word_size);
+ funcall_nargs = 1 + XSUBR (fun)->max_args;
}
- funcall:
- /* We add 1 to numargs because funcall_args includes the
- function itself as well as its arguments. */
- if (!funcall_args)
- {
+ else
+ { /* We add 1 to numargs because funcall_args includes the
+ function itself as well as its arguments. */
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);
@@ -2346,11 +2320,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;
}
@@ -2380,14 +2353,10 @@ Instead, use `add-hook' and specify t for the LOCAL argument.
usage: (run-hooks &rest HOOKS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- Lisp_Object hook[1];
ptrdiff_t i;
for (i = 0; i < nargs; i++)
- {
- hook[0] = args[i];
- run_hook_with_args (1, hook, funcall_nil);
- }
+ run_hook (args[i]);
return Qnil;
}
@@ -2553,46 +2522,34 @@ run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args,
}
}
+/* Run the hook HOOK, giving each function no args. */
+
+void
+run_hook (Lisp_Object hook)
+{
+ Frun_hook_with_args (1, &hook);
+}
+
/* Run the hook HOOK, giving each function the two args ARG1 and ARG2. */
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);
+ CALLN (Frun_hook_with_args, 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) : CALLN (Fapply, 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. */
@@ -2600,14 +2557,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 CALLN (Ffuncall, fn, arg1);
}
/* Call function fn with 2 arguments arg1, arg2. */
@@ -2615,14 +2565,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 CALLN (Ffuncall, fn, arg1, arg2);
}
/* Call function fn with 3 arguments arg1, arg2, arg3. */
@@ -2630,15 +2573,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 CALLN (Ffuncall, fn, arg1, arg2, arg3);
}
/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */
@@ -2647,16 +2582,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 CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4);
}
/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */
@@ -2665,17 +2591,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 CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5);
}
/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */
@@ -2684,18 +2600,7 @@ 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 CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6);
}
/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */
@@ -2704,19 +2609,7 @@ 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 CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
/* The caller should GCPRO all the elements of ARGS. */
@@ -2742,8 +2635,8 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
ptrdiff_t numargs = nargs - 1;
Lisp_Object lisp_numargs;
Lisp_Object val;
- register Lisp_Object *internal_args;
- ptrdiff_t i, count;
+ Lisp_Object *internal_args;
+ ptrdiff_t count;
QUIT;
@@ -2792,13 +2685,14 @@ 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;
+ memclear (internal_args + numargs,
+ (XSUBR (fun)->max_args - numargs) * word_size);
}
else
internal_args = args + 1;
@@ -3507,6 +3401,18 @@ backtrace_eval_unrewind (int distance)
unwind_protect, but the problem is that we don't know how to
rewind them afterwards. */
case SPECPDL_UNWIND:
+ {
+ Lisp_Object oldarg = tmp->unwind.arg;
+ if (tmp->unwind.func == set_buffer_if_live)
+ tmp->unwind.arg = Fcurrent_buffer ();
+ else if (tmp->unwind.func == save_excursion_restore)
+ tmp->unwind.arg = save_excursion_save ();
+ else
+ break;
+ tmp->unwind.func (oldarg);
+ break;
+ }
+
case SPECPDL_UNWIND_PTR:
case SPECPDL_UNWIND_INT:
case SPECPDL_UNWIND_VOID:
@@ -3847,7 +3753,8 @@ alist of active lexical bindings. */);
(Just imagine if someone makes it buffer-local). */
Funintern (Qinternal_interpreter_environment, Qnil);
- DEFSYM (Vrun_hooks, "run-hooks");
+ Vrun_hooks = intern_c_string ("run-hooks");
+ staticpro (&Vrun_hooks);
staticpro (&Vautoload_queue);
Vautoload_queue = Qnil;
diff --git a/src/fileio.c b/src/fileio.c
index fb1fe28aca2..43ab456d813 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -86,6 +86,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <careadlinkat.h>
#include <stat-time.h>
+#include <binary-io.h>
+
#ifdef HPUX
#include <netio.h>
#endif
@@ -113,49 +115,10 @@ static bool auto_save_error_occurred;
static bool valid_timestamp_file_system;
static dev_t timestamp_file_system;
-/* The symbol bound to coding-system-for-read when
- insert-file-contents is called for recovering a file. This is not
- an actual coding system name, but just an indicator to tell
- insert-file-contents to use `emacs-mule' with a special flag for
- auto saving and recovering a file. */
-static Lisp_Object Qauto_save_coding;
-
-/* Property name of a file name handler,
- which gives a list of operations it handles.. */
-static Lisp_Object Qoperations;
-
-/* Lisp functions for translating file formats. */
-static Lisp_Object Qformat_decode, Qformat_annotate_function;
-
-/* Lisp function for setting buffer-file-coding-system and the
- multibyteness of the current buffer after inserting a file. */
-static Lisp_Object Qafter_insert_file_set_coding;
-
-static Lisp_Object Qwrite_region_annotate_functions;
/* Each time an annotation function changes the buffer, the new buffer
is added here. */
static Lisp_Object Vwrite_region_annotation_buffers;
-static Lisp_Object Qdelete_by_moving_to_trash;
-
-/* Lisp function for moving files to trash. */
-static Lisp_Object Qmove_file_to_trash;
-
-/* Lisp function for recursively copying directories. */
-static Lisp_Object Qcopy_directory;
-
-/* Lisp function for recursively deleting directories. */
-static Lisp_Object Qdelete_directory;
-
-static Lisp_Object Qsubstitute_env_in_file_name;
-
-Lisp_Object Qfile_error, Qfile_notify_error;
-static Lisp_Object Qfile_already_exists, Qfile_date_error;
-static Lisp_Object Qexcl;
-Lisp_Object Qfile_name_history;
-
-static Lisp_Object Qcar_less_than_car;
-
static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
Lisp_Object *, struct coding_system *);
static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
@@ -197,7 +160,7 @@ check_writable (const char *filename, int amode)
bool res = faccessat (AT_FDCWD, filename, amode, AT_EACCESS) == 0;
#ifdef CYGWIN
/* faccessat may have returned failure because Cygwin couldn't
- determine the file's UID or GID; if so, we return success. */
+ determine the file's UID or GID; if so, we return success. */
if (!res)
{
int faccessat_errno = errno;
@@ -223,37 +186,17 @@ void
report_file_errno (char const *string, Lisp_Object name, int errorno)
{
Lisp_Object data = CONSP (name) || NILP (name) ? name : list1 (name);
- Lisp_Object errstring;
- char *str;
-
synchronize_system_messages_locale ();
- str = strerror (errorno);
- errstring = code_convert_string_norecord (build_unibyte_string (str),
- Vlocale_coding_system, 0);
-
- while (1)
- switch (errorno)
- {
- case EEXIST:
- xsignal (Qfile_already_exists, Fcons (errstring, data));
- break;
- default:
- /* System error messages are capitalized. Downcase the initial
- unless it is followed by a slash. (The slash case caters to
- error messages that begin with "I/O" or, in German, "E/A".) */
- if (STRING_MULTIBYTE (errstring)
- && ! EQ (Faref (errstring, make_number (1)), make_number ('/')))
- {
- int c;
-
- str = SSDATA (errstring);
- c = STRING_CHAR ((unsigned char *) str);
- Faset (errstring, make_number (0), make_number (downcase (c)));
- }
-
- xsignal (Qfile_error,
- Fcons (build_string (string), Fcons (errstring, data)));
- }
+ char *str = strerror (errorno);
+ Lisp_Object errstring
+ = code_convert_string_norecord (build_unibyte_string (str),
+ Vlocale_coding_system, 0);
+ Lisp_Object errdata = Fcons (errstring, data);
+
+ if (errorno == EEXIST)
+ xsignal (Qfile_already_exists, errdata);
+ else
+ xsignal (Qfile_error, Fcons (build_string (string), errdata));
}
/* Signal a file-access failure that set errno. STRING describes the
@@ -290,43 +233,6 @@ restore_point_unwind (Lisp_Object location)
}
-static Lisp_Object Qexpand_file_name;
-static Lisp_Object Qsubstitute_in_file_name;
-static Lisp_Object Qdirectory_file_name;
-static Lisp_Object Qfile_name_directory;
-static Lisp_Object Qfile_name_nondirectory;
-static Lisp_Object Qunhandled_file_name_directory;
-static Lisp_Object Qfile_name_as_directory;
-static Lisp_Object Qcopy_file;
-static Lisp_Object Qmake_directory_internal;
-static Lisp_Object Qmake_directory;
-static Lisp_Object Qdelete_directory_internal;
-Lisp_Object Qdelete_file;
-static Lisp_Object Qrename_file;
-static Lisp_Object Qadd_name_to_file;
-static Lisp_Object Qmake_symbolic_link;
-Lisp_Object Qfile_exists_p;
-static Lisp_Object Qfile_executable_p;
-static Lisp_Object Qfile_readable_p;
-static Lisp_Object Qfile_writable_p;
-static Lisp_Object Qfile_symlink_p;
-static Lisp_Object Qaccess_file;
-Lisp_Object Qfile_directory_p;
-static Lisp_Object Qfile_regular_p;
-static Lisp_Object Qfile_accessible_directory_p;
-static Lisp_Object Qfile_modes;
-static Lisp_Object Qset_file_modes;
-static Lisp_Object Qset_file_times;
-static Lisp_Object Qfile_selinux_context;
-static Lisp_Object Qset_file_selinux_context;
-static Lisp_Object Qfile_acl;
-static Lisp_Object Qset_file_acl;
-static Lisp_Object Qfile_newer_than_file_p;
-Lisp_Object Qinsert_file_contents;
-Lisp_Object Qwrite_region;
-static Lisp_Object Qverify_visited_file_modtime;
-static Lisp_Object Qset_visited_file_modtime;
-
DEFUN ("find-file-name-handler", Ffind_file_name_handler,
Sfind_file_name_handler, 2, 2, 0,
doc: /* Return FILENAME's handler function for OPERATION, if it has one.
@@ -396,13 +302,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 +316,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 +333,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 +381,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));
@@ -603,8 +504,6 @@ For a Unix-syntax file name, just appends a slash. */)
USE_SAFE_ALLOCA;
CHECK_STRING (file);
- if (NILP (file))
- return Qnil;
/* If the file name has special constructs in it,
call the corresponding file handler. */
@@ -672,9 +571,6 @@ In Unix-syntax, this function just removes the final slash. */)
CHECK_STRING (directory);
- if (NILP (directory))
- return Qnil;
-
/* If the file name has special constructs in it,
call the corresponding file handler. */
handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
@@ -847,8 +743,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 +772,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 +782,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 +885,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 +914,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 +1001,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 +1012,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 +1044,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 +1054,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 +1069,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 +1101,16 @@ filesystem tree, not (expand-file-name ".." dirname). */)
bite us since we expect the directory to be
multibyte. */
tem = make_unibyte_string (newdir, strlen (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 +1136,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 +1150,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
adir[1] = ':';
adir[2] = '/';
adir[3] = 0;
+ newdirlim = adir + 3;
}
newdir = adir;
}
@@ -1265,6 +1171,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 +1216,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 +1239,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 +1262,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 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
target = SAFE_ALLOCA (tlen);
#endif /* not DOS_NT */
*target = 0;
+ nbytes = 0;
if (newdir)
{
@@ -1405,13 +1316,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 +1629,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 +1641,7 @@ search_embedded_absfilename (char *nm, char *endp)
block_input ();
pw = getpwnam (o + 1);
unblock_input ();
+ SAFE_FREE ();
if (pw)
return p;
}
@@ -1776,7 +1690,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 +1705,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 +1733,7 @@ those `/' is discarded. */)
if (!NILP (Vw32_downcase_file_names))
filename = Fdowncase (filename);
#endif
+ SAFE_FREE ();
return filename;
}
@@ -1831,14 +1752,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 +2592,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 +2689,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 +2718,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;
}
@@ -2867,7 +2792,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
(Lisp_Object filename)
{
Lisp_Object absname;
- Lisp_Object values[4];
+ Lisp_Object user = Qnil, role = Qnil, type = Qnil, range = Qnil;
+
Lisp_Object handler;
#if HAVE_LIBSELINUX
security_context_t con;
@@ -2885,10 +2811,6 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
absname = ENCODE_FILE (absname);
- values[0] = Qnil;
- values[1] = Qnil;
- values[2] = Qnil;
- values[3] = Qnil;
#if HAVE_LIBSELINUX
if (is_selinux_enabled ())
{
@@ -2897,20 +2819,20 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
{
context = context_new (con);
if (context_user_get (context))
- values[0] = build_string (context_user_get (context));
+ user = build_string (context_user_get (context));
if (context_role_get (context))
- values[1] = build_string (context_role_get (context));
+ role = build_string (context_role_get (context));
if (context_type_get (context))
- values[2] = build_string (context_type_get (context));
+ type = build_string (context_type_get (context));
if (context_range_get (context))
- values[3] = build_string (context_range_get (context));
+ range = build_string (context_range_get (context));
context_free (context);
freecon (con);
}
}
#endif
- return Flist (sizeof (values) / sizeof (values[0]), values);
+ return list4 (user, role, type, range);
}
DEFUN ("set-file-selinux-context", Fset_file_selinux_context,
@@ -3386,6 +3308,56 @@ time_error_value (int errnum)
return make_timespec (0, ns);
}
+static Lisp_Object
+get_window_points_and_markers (void)
+{
+ Lisp_Object pt_marker = Fpoint_marker ();
+ Lisp_Object windows
+ = call3 (Qget_buffer_window_list, Fcurrent_buffer (), Qnil, Qt);
+ Lisp_Object window_markers = windows;
+ /* Window markers (and point) are handled specially: rather than move to
+ just before or just after the modified text, we try to keep the
+ markers at the same distance (bug#19161).
+ In general, this is wrong, but for window-markers, this should be harmless
+ and is convenient for the end user when most of the file is unmodified,
+ except for a few minor details near the beginning and near the end. */
+ for (; CONSP (windows); windows = XCDR (windows))
+ if (WINDOWP (XCAR (windows)))
+ {
+ Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
+ XSETCAR (windows,
+ Fcons (window_marker, Fmarker_position (window_marker)));
+ }
+ return Fcons (Fcons (pt_marker, Fpoint ()), window_markers);
+}
+
+static void
+restore_window_points (Lisp_Object window_markers, ptrdiff_t inserted,
+ ptrdiff_t same_at_start, ptrdiff_t same_at_end)
+{
+ for (; CONSP (window_markers); window_markers = XCDR (window_markers))
+ if (CONSP (XCAR (window_markers)))
+ {
+ Lisp_Object car = XCAR (window_markers);
+ Lisp_Object marker = XCAR (car);
+ Lisp_Object oldpos = XCDR (car);
+ if (MARKERP (marker) && INTEGERP (oldpos)
+ && XINT (oldpos) > same_at_start
+ && XINT (oldpos) < same_at_end)
+ {
+ ptrdiff_t oldsize = same_at_end - same_at_start;
+ ptrdiff_t newsize = inserted;
+ double growth = newsize / (double)oldsize;
+ ptrdiff_t newpos
+ = same_at_start + growth * (XINT (oldpos) - same_at_start);
+ Fset_marker (marker, make_number (newpos), Qnil);
+ }
+ }
+}
+
+/* FIXME: insert-file-contents should be split with the top-level moved to
+ Elisp and only the core kept in C. */
+
DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
1, 5, 0,
doc: /* Insert contents of file FILENAME after point.
@@ -3430,24 +3402,32 @@ by calling `format-decode', which see. */)
int save_errno = 0;
char read_buf[READ_BUF_SIZE];
struct coding_system coding;
- bool replace_handled = 0;
- bool set_coding_system = 0;
+ bool replace_handled = false;
+ bool set_coding_system = false;
Lisp_Object coding_system;
- bool read_quit = 0;
+ bool read_quit = false;
/* If the undo log only contains the insertion, there's no point
keeping it. It's typically when we first fill a file-buffer. */
bool empty_undo_list_p
= (!NILP (visit) && NILP (BVAR (current_buffer, undo_list))
&& BEG == Z);
Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
- bool we_locked_file = 0;
+ bool we_locked_file = false;
ptrdiff_t fd_index;
+ Lisp_Object window_markers = Qnil;
+ /* same_at_start and same_at_end count bytes, because file access counts
+ bytes and BEG and END count bytes. */
+ ptrdiff_t same_at_start = BEGV_BYTE;
+ ptrdiff_t same_at_end = ZV_BYTE;
+ /* SAME_AT_END_CHARPOS counts characters, because
+ restore_window_points needs the old character count. */
+ ptrdiff_t same_at_end_charpos = ZV;
if (current_buffer->base_buffer && ! NILP (visit))
error ("Cannot do file visiting in an indirect buffer");
if (!NILP (BVAR (current_buffer, read_only)))
- Fbarf_if_buffer_read_only ();
+ Fbarf_if_buffer_read_only (Qnil);
val = Qnil;
p = Qnil;
@@ -3497,7 +3477,11 @@ by calling `format-decode', which see. */)
/* Replacement should preserve point as it preserves markers. */
if (!NILP (replace))
- record_unwind_protect (restore_point_unwind, Fpoint_marker ());
+ {
+ window_markers = get_window_points_and_markers ();
+ record_unwind_protect (restore_point_unwind,
+ XCAR (XCAR (window_markers)));
+ }
if (fstat (fd, &st) != 0)
report_file_error ("Input file status", orig_filename);
@@ -3575,14 +3559,14 @@ by calling `format-decode', which see. */)
}
/* Prevent redisplay optimizations. */
- current_buffer->clip_changed = 1;
+ current_buffer->clip_changed = true;
if (EQ (Vcoding_system_for_read, Qauto_save_coding))
{
coding_system = coding_inherit_eol_type (Qutf_8_emacs, Qunix);
setup_coding_system (coding_system, &coding);
/* Ensure we set Vlast_coding_system_used. */
- set_coding_system = 1;
+ set_coding_system = true;
}
else if (BEG < Z)
{
@@ -3624,13 +3608,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);
@@ -3665,11 +3650,9 @@ by calling `format-decode', which see. */)
{
/* If we have not yet decided a coding system, check
file-coding-system-alist. */
- Lisp_Object args[6];
-
- args[0] = Qinsert_file_contents, args[1] = orig_filename;
- args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
- coding_system = Ffind_operation_coding_system (6, args);
+ coding_system = CALLN (Ffind_operation_coding_system,
+ Qinsert_file_contents, orig_filename,
+ visit, beg, end, replace);
if (CONSP (coding_system))
coding_system = XCAR (coding_system);
}
@@ -3687,7 +3670,7 @@ by calling `format-decode', which see. */)
setup_coding_system (coding_system, &coding);
/* Ensure we set Vlast_coding_system_used. */
- set_coding_system = 1;
+ set_coding_system = true;
}
/* If requested, replace the accessible part of the buffer
@@ -3709,16 +3692,11 @@ by calling `format-decode', which see. */)
&& (NILP (coding_system)
|| ! CODING_REQUIRE_DECODING (&coding)))
{
- /* same_at_start and same_at_end count bytes,
- because file access counts bytes
- and BEG and END count bytes. */
- ptrdiff_t same_at_start = BEGV_BYTE;
- ptrdiff_t same_at_end = ZV_BYTE;
ptrdiff_t overlap;
/* There is still a possibility we will find the need to do code
conversion. If that happens, set this variable to
give up on handling REPLACE in the optimized way. */
- bool giveup_match_end = 0;
+ bool giveup_match_end = false;
if (beg_offset != 0)
{
@@ -3752,7 +3730,7 @@ by calling `format-decode', which see. */)
/* We found that the file should be decoded somehow.
Let's give up here. */
{
- giveup_match_end = 1;
+ giveup_match_end = true;
break;
}
@@ -3765,7 +3743,7 @@ by calling `format-decode', which see. */)
if (bufpos != nread)
break;
}
- immediate_quit = 0;
+ immediate_quit = false;
/* If the file matches the buffer completely,
there's no need to replace anything. */
if (same_at_start - BEGV_BYTE == end_offset - beg_offset)
@@ -3777,7 +3755,7 @@ by calling `format-decode', which see. */)
del_range_1 (same_at_start, same_at_end, 0, 0);
goto handled;
}
- immediate_quit = 1;
+ immediate_quit = true;
QUIT;
/* Count how many chars at the end of the file
match the text at the end of the buffer. But, if we have
@@ -3828,7 +3806,7 @@ by calling `format-decode', which see. */)
&& FETCH_BYTE (same_at_end - 1) >= 0200
&& ! NILP (BVAR (current_buffer, enable_multibyte_characters))
&& (CODING_MAY_REQUIRE_DECODING (&coding)))
- giveup_match_end = 1;
+ giveup_match_end = true;
break;
}
@@ -3863,6 +3841,7 @@ by calling `format-decode', which see. */)
+ (! NILP (end) ? end_offset : st.st_size) - ZV_BYTE));
if (overlap > 0)
same_at_end += overlap;
+ same_at_end_charpos = BYTE_TO_CHAR (same_at_end);
/* Arrange to read only the nonmatching middle part of the file. */
beg_offset += same_at_start - BEGV_BYTE;
@@ -3870,7 +3849,7 @@ by calling `format-decode', which see. */)
invalidate_buffer_caches (current_buffer,
BYTE_TO_CHAR (same_at_start),
- BYTE_TO_CHAR (same_at_end));
+ same_at_end_charpos);
del_range_byte (same_at_start, same_at_end, 0);
/* Insert from the file at the proper position. */
temp = BYTE_TO_CHAR (same_at_start);
@@ -3881,7 +3860,7 @@ by calling `format-decode', which see. */)
if (XBUFFER (XWINDOW (selected_window)->contents) == current_buffer)
XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
- replace_handled = 1;
+ replace_handled = true;
}
}
@@ -3896,8 +3875,6 @@ by calling `format-decode', which see. */)
in a more optimized way. */
if (!NILP (replace) && ! replace_handled && BEGV < ZV)
{
- ptrdiff_t same_at_start = BEGV_BYTE;
- ptrdiff_t same_at_end = ZV_BYTE;
ptrdiff_t same_at_start_charpos;
ptrdiff_t inserted_chars;
ptrdiff_t overlap;
@@ -3961,7 +3938,7 @@ by calling `format-decode', which see. */)
}
coding_system = CODING_ID_NAME (coding.id);
- set_coding_system = 1;
+ set_coding_system = true;
decoded = BUF_BEG_ADDR (XBUFFER (conversion_buffer));
inserted = (BUF_Z_BYTE (XBUFFER (conversion_buffer))
- BUF_BEG_BYTE (XBUFFER (conversion_buffer)));
@@ -4021,6 +3998,7 @@ by calling `format-decode', which see. */)
overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
if (overlap > 0)
same_at_end += overlap;
+ same_at_end_charpos = BYTE_TO_CHAR (same_at_end);
/* If display currently starts at beginning of line,
keep it that way. */
@@ -4036,7 +4014,7 @@ by calling `format-decode', which see. */)
{
invalidate_buffer_caches (current_buffer,
BYTE_TO_CHAR (same_at_start),
- BYTE_TO_CHAR (same_at_end));
+ same_at_end_charpos);
del_range_byte (same_at_start, same_at_end, 0);
temp = GPT;
eassert (same_at_start == GPT_BYTE);
@@ -4044,7 +4022,7 @@ by calling `format-decode', which see. */)
}
else
{
- temp = BYTE_TO_CHAR (same_at_start);
+ temp = same_at_end_charpos;
}
/* Insert from the file at the proper position. */
SET_PT_BOTH (temp, same_at_start);
@@ -4082,13 +4060,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 */
+ we_locked_file = true;
prepare_to_modify_buffer (PT, PT, NULL);
}
@@ -4118,7 +4094,7 @@ by calling `format-decode', which see. */)
while (how_much < total)
{
- /* try is reserved in some compilers (Microsoft C) */
+ /* `try' is reserved in some compilers (Microsoft C). */
ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE);
ptrdiff_t this;
@@ -4143,7 +4119,7 @@ by calling `format-decode', which see. */)
if (NILP (nbytes))
{
- read_quit = 1;
+ read_quit = true;
break;
}
@@ -4188,10 +4164,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
@@ -4255,11 +4229,9 @@ by calling `format-decode', which see. */)
{
/* If the coding system is not yet decided, check
file-coding-system-alist. */
- Lisp_Object args[6];
-
- args[0] = Qinsert_file_contents, args[1] = orig_filename;
- args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
- coding_system = Ffind_operation_coding_system (6, args);
+ coding_system = CALLN (Ffind_operation_coding_system,
+ Qinsert_file_contents, orig_filename,
+ visit, beg, end, Qnil);
if (CONSP (coding_system))
coding_system = XCAR (coding_system);
}
@@ -4278,7 +4250,7 @@ by calling `format-decode', which see. */)
coding_system = raw_text_coding_system (coding_system);
setup_coding_system (coding_system, &coding);
/* Ensure we set Vlast_coding_system_used. */
- set_coding_system = 1;
+ set_coding_system = true;
}
if (!NILP (visit))
@@ -4289,7 +4261,7 @@ by calling `format-decode', which see. */)
/* Can't do this if part of the buffer might be preserved. */
&& NILP (replace))
/* Visiting a file with these coding system makes the buffer
- unibyte. */
+ unibyte. */
bset_enable_multibyte_characters (current_buffer, Qnil);
}
@@ -4328,6 +4300,11 @@ by calling `format-decode', which see. */)
handled:
+ if (inserted > 0)
+ restore_window_points (window_markers, inserted,
+ BYTE_TO_CHAR (same_at_start),
+ same_at_end_charpos);
+
if (!NILP (visit))
{
if (empty_undo_list_p)
@@ -4343,14 +4320,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);
@@ -4584,12 +4559,9 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
if (NILP (val))
{
/* Check file-coding-system-alist. */
- Lisp_Object args[7], coding_systems;
-
- args[0] = Qwrite_region; args[1] = start; args[2] = end;
- args[3] = filename; args[4] = append; args[5] = visit;
- args[6] = lockname;
- coding_systems = Ffind_operation_coding_system (7, args);
+ Lisp_Object coding_systems
+ = CALLN (Ffind_operation_coding_system, Qwrite_region, start, end,
+ filename, append, visit, lockname);
if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
val = XCDR (coding_systems);
}
@@ -4659,8 +4631,8 @@ Optional fifth argument VISIT, if t or a string, means
If VISIT is a string, it is a second file name;
the output goes to FILENAME, but the buffer is marked as visiting VISIT.
VISIT is also the file name to lock and unlock for clash detection.
-If VISIT is neither t nor nil nor a string,
- that means do not display the \"Wrote file\" message.
+If VISIT is neither t nor nil nor a string, or if Emacs is in batch mode,
+ do not display the \"Wrote file\" message.
The optional sixth arg LOCKNAME, if non-nil, specifies the name to
use for locking and unlocking, overriding FILENAME and VISIT.
The optional seventh arg MUSTBENEW, if non-nil, insists on a check
@@ -4809,13 +4781,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);
@@ -4837,10 +4807,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);
}
@@ -4855,10 +4823,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);
}
@@ -5001,10 +4967,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
@@ -5035,7 +4999,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
return Qnil;
}
- if (!auto_saving)
+ if (!auto_saving && !noninteractive)
message_with_string ((NUMBERP (append)
? "Updated %s"
: ! NILP (append)
@@ -5050,10 +5014,7 @@ DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
doc: /* Return t if (car A) is numerically less than (car B). */)
(Lisp_Object a, Lisp_Object b)
{
- Lisp_Object args[2];
- args[0] = Fcar (a);
- args[1] = Fcar (b);
- return Flss (2, args);
+ return CALLN (Flss, Fcar (a), Fcar (b));
}
/* Build the complete list of annotations appropriate for writing out
@@ -5072,7 +5033,7 @@ build_annotations (Lisp_Object start, Lisp_Object end)
struct gcpro gcpro1, gcpro2;
Lisp_Object original_buffer;
int i;
- bool used_global = 0;
+ bool used_global = false;
XSETBUFFER (original_buffer, current_buffer);
@@ -5084,11 +5045,10 @@ build_annotations (Lisp_Object start, Lisp_Object end)
struct buffer *given_buffer = current_buffer;
if (EQ (Qt, XCAR (p)) && !used_global)
{ /* Use the global value of the hook. */
- Lisp_Object arg[2];
- used_global = 1;
- arg[0] = Fdefault_value (Qwrite_region_annotate_functions);
- arg[1] = XCDR (p);
- p = Fappend (2, arg);
+ used_global = true;
+ p = CALLN (Fappend,
+ Fdefault_value (Qwrite_region_annotate_functions),
+ XCDR (p));
continue;
}
Vwrite_region_annotations_so_far = annotations;
@@ -5309,20 +5269,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;
@@ -5416,7 +5368,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;
@@ -5424,10 +5376,9 @@ 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 = CALLN (Fformat, format, BVAR (current_buffer, name),
+ Ferror_message_string (error_val));
GCPRO1 (msg);
for (i = 0; i < 3; ++i)
@@ -5749,8 +5700,8 @@ then any auto-save counts as "recent". */)
they're never autosaved. */
return (SAVE_MODIFF < BUF_AUTOSAVE_MODIFF (current_buffer) ? Qt : Qnil);
}
-
-/* Reading and completing file names */
+
+/* Reading and completing file names. */
DEFUN ("next-read-file-uses-dialog-p", Fnext_read_file_uses_dialog_p,
Snext_read_file_uses_dialog_p, 0, 0, 0,
@@ -5759,8 +5710,8 @@ The return value is only relevant for a call to `read-file-name' that happens
before any other event (mouse or keypress) is handled. */)
(void)
{
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) \
- || defined (HAVE_NS)
+#if (defined USE_GTK || defined USE_MOTIF \
+ || defined HAVE_NS || defined HAVE_NTGUI)
if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
&& use_dialog_box
&& use_file_dialog
@@ -5770,23 +5721,47 @@ 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)
+
+DEFUN ("set-binary-mode", Fset_binary_mode, Sset_binary_mode, 2, 2, 0,
+ doc: /* Switch STREAM to binary I/O mode or text I/O mode.
+STREAM can be one of the symbols `stdin', `stdout', or `stderr'.
+If MODE is non-nil, switch STREAM to binary mode, otherwise switch
+it to text mode.
+
+As a side effect, this function flushes any pending STREAM's data.
+
+Value is the previous value of STREAM's I/O mode, nil for text mode,
+non-nil for binary mode.
+
+On MS-Windows and MS-DOS, binary mode is needed to read or write
+arbitrary binary data, and for disabling translation between CR-LF
+pairs and a single newline character. Examples include generation
+of text files with Unix-style end-of-line format using `princ' in
+batch mode, with standard output redirected to a file.
+
+On Posix systems, this function always returns non-nil, and has no
+effect except for flushing STREAM's data. */)
+ (Lisp_Object stream, Lisp_Object mode)
{
- 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));
-}
+ FILE *fp = NULL;
+ int binmode;
+
+ CHECK_SYMBOL (stream);
+ if (EQ (stream, Qstdin))
+ fp = stdin;
+ else if (EQ (stream, Qstdout))
+ fp = stdout;
+ else if (EQ (stream, Qstderr))
+ fp = stderr;
+ else
+ xsignal2 (Qerror, build_string ("unsupported stream"), stream);
+ binmode = NILP (mode) ? O_TEXT : O_BINARY;
+ if (fp != stdin)
+ fflush (fp);
+
+ return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil;
+}
void
init_fileio (void)
@@ -5818,7 +5793,10 @@ init_fileio (void)
void
syms_of_fileio (void)
{
+ /* Property name of a file name handler,
+ which gives a list of operations it handles. */
DEFSYM (Qoperations, "operations");
+
DEFSYM (Qexpand_file_name, "expand-file-name");
DEFSYM (Qsubstitute_in_file_name, "substitute-in-file-name");
DEFSYM (Qdirectory_file_name, "directory-file-name");
@@ -5855,6 +5833,12 @@ syms_of_fileio (void)
DEFSYM (Qwrite_region, "write-region");
DEFSYM (Qverify_visited_file_modtime, "verify-visited-file-modtime");
DEFSYM (Qset_visited_file_modtime, "set-visited-file-modtime");
+
+ /* The symbol bound to coding-system-for-read when
+ insert-file-contents is called for recovering a file. This is not
+ an actual coding system name, but just an indicator to tell
+ insert-file-contents to use `emacs-mule' with a special flag for
+ auto saving and recovering a file. */
DEFSYM (Qauto_save_coding, "auto-save-coding");
DEFSYM (Qfile_name_history, "file-name-history");
@@ -5890,9 +5874,14 @@ On MS-Windows, the value of this variable is largely ignored if
behaves as if file names were encoded in `utf-8'. */);
Vdefault_file_name_coding_system = Qnil;
+ /* Lisp functions for translating file formats. */
DEFSYM (Qformat_decode, "format-decode");
DEFSYM (Qformat_annotate_function, "format-annotate-function");
+
+ /* Lisp function for setting buffer-file-coding-system and the
+ multibyteness of the current buffer after inserting a file. */
DEFSYM (Qafter_insert_file_set_coding, "after-insert-file-set-coding");
+
DEFSYM (Qcar_less_than_car, "car-less-than-car");
Fput (Qfile_error, Qerror_conditions,
@@ -6046,12 +6035,23 @@ When non-nil, certain file deletion commands use the function
This includes interactive calls to `delete-file' and
`delete-directory' and the Dired deletion commands. */);
delete_by_moving_to_trash = 0;
- Qdelete_by_moving_to_trash = intern_c_string ("delete-by-moving-to-trash");
+ DEFSYM (Qdelete_by_moving_to_trash, "delete-by-moving-to-trash");
+ /* Lisp function for moving files to trash. */
DEFSYM (Qmove_file_to_trash, "move-file-to-trash");
+
+ /* Lisp function for recursively copying directories. */
DEFSYM (Qcopy_directory, "copy-directory");
+
+ /* Lisp function for recursively deleting directories. */
DEFSYM (Qdelete_directory, "delete-directory");
+
DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
+ DEFSYM (Qget_buffer_window_list, "get-buffer-window-list");
+
+ DEFSYM (Qstdin, "stdin");
+ DEFSYM (Qstdout, "stdout");
+ DEFSYM (Qstderr, "stderr");
defsubr (&Sfind_file_name_handler);
defsubr (&Sfile_name_directory);
@@ -6102,6 +6102,8 @@ This includes interactive calls to `delete-file' and
defsubr (&Snext_read_file_uses_dialog_p);
+ defsubr (&Sset_binary_mode);
+
#ifdef HAVE_SYNC
defsubr (&Sunix_sync);
#endif
diff --git a/src/filelock.c b/src/filelock.c
index 24d44073340..89d3e350219 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
@@ -211,8 +209,6 @@ get_boot_time (void)
WTMP_FILE, counter);
if (! NILP (Ffile_exists_p (tempname)))
{
- Lisp_Object args[6];
-
/* The utmp functions on mescaline.gnu.org accept only
file names up to 8 characters long. Choose a 2
character long prefix, and call make_temp_file with
@@ -221,13 +217,9 @@ get_boot_time (void)
filename = Fexpand_file_name (build_string ("wt"),
Vtemporary_file_directory);
filename = make_temp_name (filename, 1);
- args[0] = build_string ("gzip");
- args[1] = Qnil;
- args[2] = list2 (QCfile, filename);
- args[3] = Qnil;
- args[4] = build_string ("-cd");
- args[5] = tempname;
- Fcall_process (6, args);
+ CALLN (Fcall_process, build_string ("gzip"), Qnil,
+ list2 (QCfile, filename), Qnil,
+ build_string ("-cd"), tempname);
delete_flag = 1;
}
}
@@ -594,9 +586,10 @@ current_lock_owner (lock_info_type *owner, char *lfname)
return -1;
/* On current host? */
- if (STRINGP (Vsystem_name)
- && dot - (at + 1) == SBYTES (Vsystem_name)
- && memcmp (at + 1, SSDATA (Vsystem_name), SBYTES (Vsystem_name)) == 0)
+ Lisp_Object system_name = Fsystem_name ();
+ if (STRINGP (system_name)
+ && dot - (at + 1) == SBYTES (system_name)
+ && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0)
{
if (pid == getpid ())
ret = 2; /* We own it. */
@@ -773,7 +766,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 +832,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 +843,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 8c50889bcb3..4c7095133eb 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"
@@ -40,19 +41,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "xterm.h"
#endif
-Lisp_Object Qstring_lessp;
-static Lisp_Object Qprovide, Qrequire;
-static Lisp_Object Qyes_or_no_p_history;
-Lisp_Object Qcursor_in_echo_area;
-static Lisp_Object Qwidget_type;
-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. */)
+ doc: /* Return the argument unchanged. */
+ attributes: const)
(Lisp_Object arg)
{
return arg;
@@ -232,6 +227,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 +240,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 +289,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 +338,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);
@@ -379,21 +440,14 @@ static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args,
Lisp_Object
concat2 (Lisp_Object s1, Lisp_Object s2)
{
- Lisp_Object args[2];
- args[0] = s1;
- args[1] = s2;
- return concat (2, args, Lisp_String, 0);
+ return concat (2, ((Lisp_Object []) {s1, s2}), Lisp_String, 0);
}
/* ARGSUSED */
Lisp_Object
concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3)
{
- Lisp_Object args[3];
- args[0] = s1;
- args[1] = s2;
- args[2] = s3;
- return concat (3, args, Lisp_String, 0);
+ return concat (3, ((Lisp_Object []) {s1, s2, s3}), Lisp_String, 0);
}
DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
@@ -1127,7 +1181,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 +1232,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 +1272,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 +1295,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 +1738,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);
+ }
}
- return prev;
+ 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);
+ }
+ }
+ 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);
}
- CHECK_LIST_END (list, list);
+ 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));
+ }
+ 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 +1885,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 +2042,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);
@@ -2004,12 +2248,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
if (depth > 200)
error ("Stack overflow in equal");
if (NILP (ht))
- {
- Lisp_Object args[2];
- args[0] = QCtest;
- args[1] = Qeq;
- ht = Fmake_hash_table (2, args);
- }
+ ht = CALLN (Fmake_hash_table, QCtest, Qeq);
switch (XTYPE (o1))
{
case Lisp_Cons: case Lisp_Misc: case Lisp_Vectorlike:
@@ -2213,10 +2452,7 @@ This makes STRING unibyte and may change its length. */)
Lisp_Object
nconc2 (Lisp_Object s1, Lisp_Object s2)
{
- Lisp_Object args[2];
- args[0] = s1;
- args[1] = s2;
- return Fnconc (2, args);
+ return CALLN (Fnconc, s1, s2);
}
DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
@@ -2266,16 +2502,14 @@ usage: (nconc &rest LISTS) */)
static void
mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
{
- register Lisp_Object tail;
- Lisp_Object dummy;
- register EMACS_INT i;
+ Lisp_Object tail, dummy;
+ EMACS_INT i;
struct gcpro gcpro1, gcpro2, gcpro3;
if (vals)
{
/* Don't let vals contain any garbage when GC happens. */
- for (i = 0; i < leni; i++)
- vals[i] = Qnil;
+ memclear (vals, leni * word_size);
GCPRO3 (dummy, fn, seq);
gcpro1.var = vals;
@@ -2446,8 +2680,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 +2699,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 = CALLN (Fconcat, prompt, yes_or_no);
GCPRO1 (prompt);
while (1)
@@ -2531,8 +2762,6 @@ advisable. */)
return ret;
}
-static Lisp_Object Qsubfeatures;
-
DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 2, 0,
doc: /* Return t if FEATURE is present in this Emacs.
@@ -2551,8 +2780,6 @@ SUBFEATURE can be used to check a specific subfeature of FEATURE. */)
return (NILP (tem)) ? Qnil : Qt;
}
-static Lisp_Object Qfuncall;
-
DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0,
doc: /* Announce that FEATURE is a feature of the current Emacs.
The optional argument SUBFEATURES should be a list of symbols listing
@@ -2753,15 +2980,13 @@ usage: (widget-apply WIDGET PROPERTY &rest ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
/* This function can GC. */
- Lisp_Object newargs[3];
struct gcpro gcpro1, gcpro2;
- Lisp_Object result;
-
- newargs[0] = Fwidget_get (args[0], args[1]);
- newargs[1] = args[0];
- newargs[2] = Flist (nargs - 2, args + 2);
- GCPRO2 (newargs[0], newargs[2]);
- result = Fapply (3, newargs);
+ Lisp_Object widget = args[0];
+ Lisp_Object property = args[1];
+ Lisp_Object propval = Fwidget_get (widget, property);
+ Lisp_Object trailing_args = Flist (nargs - 2, args + 2);
+ GCPRO2 (propval, trailing_args);
+ Lisp_Object result = CALLN (Fapply, propval, widget, trailing_args);
UNGCPRO;
return result;
}
@@ -3027,7 +3252,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 +3396,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");
}
@@ -3341,14 +3564,6 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length,
static struct Lisp_Hash_Table *weak_hash_tables;
-/* Various symbols. */
-
-static Lisp_Object Qhash_table_p;
-static Lisp_Object Qkey, Qvalue, Qeql;
-Lisp_Object Qeq, Qequal;
-Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
-static Lisp_Object Qhash_table_test, Qkey_or_value, Qkey_and_value;
-
/***********************************************************************
Utilities
@@ -3454,7 +3669,7 @@ Lisp_Object
larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max)
{
struct Lisp_Vector *v;
- ptrdiff_t i, incr, incr_max, old_size, new_size;
+ ptrdiff_t incr, incr_max, old_size, new_size;
ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / sizeof *v->contents;
ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
? nitems_max : C_language_max);
@@ -3468,8 +3683,7 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max)
new_size = old_size + incr;
v = allocate_vector (new_size);
memcpy (v->contents, XVECTOR (vec)->contents, old_size * sizeof *v->contents);
- for (i = old_size; i < new_size; ++i)
- v->contents[i] = Qnil;
+ memclear (v->contents + old_size, incr * word_size);
XSETVECTOR (vec, v);
return vec;
}
@@ -3519,12 +3733,7 @@ cmpfn_user_defined (struct hash_table_test *ht,
Lisp_Object key1,
Lisp_Object key2)
{
- Lisp_Object args[3];
-
- args[0] = ht->user_cmp_function;
- args[1] = key1;
- args[2] = key2;
- return !NILP (Ffuncall (3, args));
+ return !NILP (call2 (ht->user_cmp_function, key1, key2));
}
@@ -3572,14 +3781,19 @@ hashfn_equal (struct hash_table_test *ht, Lisp_Object key)
static EMACS_UINT
hashfn_user_defined (struct hash_table_test *ht, Lisp_Object key)
{
- Lisp_Object args[2], hash;
-
- args[0] = ht->user_hash_function;
- args[1] = key;
- hash = Ffuncall (2, args);
+ Lisp_Object hash = call1 (ht->user_hash_function, key);
return hashfn_eq (ht, hash);
}
+/* Allocate basically initialized hash table. */
+
+static struct Lisp_Hash_Table *
+allocate_hash_table (void)
+{
+ return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table,
+ count, PVEC_HASH_TABLE);
+}
+
/* An upper bound on the size of a hash table index. It must fit in
ptrdiff_t and be a valid Emacs fixnum. */
#define INDEX_SIZE_BOUND \
@@ -3740,12 +3954,8 @@ 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);
- }
+ CALLN (Fmessage, 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 +4242,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 +4435,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 +4526,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 +4598,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);
}
@@ -4523,17 +4732,10 @@ FUNCTION is called with two arguments, KEY and VALUE.
(Lisp_Object function, Lisp_Object table)
{
struct Lisp_Hash_Table *h = check_hash_table (table);
- Lisp_Object args[3];
- ptrdiff_t i;
- for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+ for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
if (!NILP (HASH_HASH (h, i)))
- {
- args[0] = function;
- args[1] = HASH_KEY (h, i);
- args[2] = HASH_VALUE (h, i);
- Ffuncall (3, args);
- }
+ call2 (function, HASH_KEY (h, i), HASH_VALUE (h, i));
return Qnil;
}
@@ -4570,12 +4772,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 +4814,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
{
@@ -4699,11 +4877,9 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_
if (NILP (coding_system) && !NILP (Fbuffer_file_name (object)))
{
/* Check file-coding-system-alist. */
- Lisp_Object args[4], val;
-
- args[0] = Qwrite_region; args[1] = start; args[2] = end;
- args[3] = Fbuffer_file_name (object);
- val = Ffind_operation_coding_system (4, args);
+ Lisp_Object val = CALLN (Ffind_operation_coding_system,
+ Qwrite_region, start, end,
+ Fbuffer_file_name (object));
if (CONSP (val) && !NILP (XCDR (val)))
coding_system = XCDR (val);
}
@@ -4898,6 +5074,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 +5129,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 f07fbe3bb11..9ea43cdfc85 100644
--- a/src/font.c
+++ b/src/font.c
@@ -41,16 +41,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
-Lisp_Object Qopentype;
-
-/* Important character set strings. */
-Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
-
#define DEFAULT_ENCODING Qiso8859_1
-/* Unicode category `Cf'. */
-static Lisp_Object QCf;
-
/* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
static Lisp_Object font_style_table;
@@ -110,21 +102,6 @@ static const struct table_entry width_table[] =
{ 200, { "ultra-expanded", "ultraexpanded", "wide" }}
};
-Lisp_Object QCfoundry;
-static Lisp_Object QCadstyle, QCregistry;
-/* Symbols representing keys of font extra info. */
-Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
-Lisp_Object QCantialias, QCfont_entity;
-static Lisp_Object QCfc_unknown_spec;
-/* Symbols representing values of font spacing property. */
-static Lisp_Object Qc, Qm, Qd;
-Lisp_Object Qp;
-/* Special ADSTYLE properties to avoid fonts used for Latin
- characters; used in xfont.c and ftfont.c. */
-Lisp_Object Qja, Qko;
-
-static Lisp_Object QCuser_spec;
-
/* Alist of font registry symbols and the corresponding charset
information. The information is retrieved from
Vfont_encoding_alist on demand.
@@ -179,7 +156,7 @@ font_make_spec (void)
struct font_spec *spec
= ((struct font_spec *)
allocate_pseudovector (VECSIZE (struct font_spec),
- FONT_SPEC_MAX, PVEC_FONT));
+ FONT_SPEC_MAX, FONT_SPEC_MAX, PVEC_FONT));
XSETFONT (font_spec, spec);
return font_spec;
}
@@ -191,7 +168,7 @@ font_make_entity (void)
struct font_entity *entity
= ((struct font_entity *)
allocate_pseudovector (VECSIZE (struct font_entity),
- FONT_ENTITY_MAX, PVEC_FONT));
+ FONT_ENTITY_MAX, FONT_ENTITY_MAX, PVEC_FONT));
XSETFONT (font_entity, entity);
return font_entity;
}
@@ -204,7 +181,8 @@ font_make_object (int size, Lisp_Object entity, int pixelsize)
{
Lisp_Object font_object;
struct font *font
- = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
+ = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX,
+ FONT_OBJECT_MAX, PVEC_FONT);
int i;
/* GC can happen before the driver is set up,
@@ -225,7 +203,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 +251,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 +283,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, tem);
}
/* Return a pixel size of font-spec SPEC on frame F. */
@@ -340,7 +341,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 +373,8 @@ 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,
+ CALLN (Fvconcat, table, Fmake_vector (make_number (1), elt)));
return (100 << 8) | (i << 4);
}
else
@@ -639,36 +639,32 @@ font_prop_validate_otf (Lisp_Object prop, Lisp_Object val)
values. */
static const struct
{
- /* Pointer to the key symbol. */
- Lisp_Object *key;
+ /* Index of the key symbol. */
+ int key;
/* Function to validate PROP's value VAL, or NULL if any value is
ok. The value is VAL or its regularized value if VAL is valid,
and Qerror if not. */
Lisp_Object (*validator) (Lisp_Object prop, Lisp_Object val);
} font_property_table[] =
- { { &QCtype, font_prop_validate_symbol },
- { &QCfoundry, font_prop_validate_symbol },
- { &QCfamily, font_prop_validate_symbol },
- { &QCadstyle, font_prop_validate_symbol },
- { &QCregistry, font_prop_validate_symbol },
- { &QCweight, font_prop_validate_style },
- { &QCslant, font_prop_validate_style },
- { &QCwidth, font_prop_validate_style },
- { &QCsize, font_prop_validate_non_neg },
- { &QCdpi, font_prop_validate_non_neg },
- { &QCspacing, font_prop_validate_spacing },
- { &QCavgwidth, font_prop_validate_non_neg },
+ { { SYMBOL_INDEX (QCtype), font_prop_validate_symbol },
+ { SYMBOL_INDEX (QCfoundry), font_prop_validate_symbol },
+ { SYMBOL_INDEX (QCfamily), font_prop_validate_symbol },
+ { SYMBOL_INDEX (QCadstyle), font_prop_validate_symbol },
+ { SYMBOL_INDEX (QCregistry), font_prop_validate_symbol },
+ { SYMBOL_INDEX (QCweight), font_prop_validate_style },
+ { SYMBOL_INDEX (QCslant), font_prop_validate_style },
+ { SYMBOL_INDEX (QCwidth), font_prop_validate_style },
+ { SYMBOL_INDEX (QCsize), font_prop_validate_non_neg },
+ { SYMBOL_INDEX (QCdpi), font_prop_validate_non_neg },
+ { SYMBOL_INDEX (QCspacing), font_prop_validate_spacing },
+ { SYMBOL_INDEX (QCavgwidth), font_prop_validate_non_neg },
/* The order of the above entries must match with enum
font_property_index. */
- { &QClang, font_prop_validate_symbol },
- { &QCscript, font_prop_validate_symbol },
- { &QCotf, font_prop_validate_otf }
+ { SYMBOL_INDEX (QClang), font_prop_validate_symbol },
+ { SYMBOL_INDEX (QCscript), font_prop_validate_symbol },
+ { SYMBOL_INDEX (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,8 +673,8 @@ get_font_prop_index (Lisp_Object key)
{
int i;
- for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
- if (EQ (key, *font_property_table[i].key))
+ for (i = 0; i < ARRAYELTS (font_property_table); i++)
+ if (EQ (key, builtin_lisp_symbol (font_property_table[i].key)))
return i;
return -1;
}
@@ -695,7 +691,7 @@ font_prop_validate (int idx, Lisp_Object prop, Lisp_Object val)
if (NILP (val))
return val;
if (NILP (prop))
- prop = *font_property_table[idx].key;
+ prop = builtin_lisp_symbol (font_property_table[idx].key);
else
{
idx = get_font_prop_index (prop);
@@ -992,15 +988,14 @@ font_expand_wildcards (Lisp_Object *field, int n)
if (i == 0 || ! NILP (tmp[i - 1]))
/* None of TMP[X] corresponds to Jth field. */
return -1;
- for (; j < range[i].from; j++)
- field[j] = Qnil;
+ memclear (field + j, (range[i].from - j) * word_size);
+ j = range[i].from;
}
field[j++] = tmp[i];
}
if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
return -1;
- for (; j < XLFD_LAST_INDEX; j++)
- field[j] = Qnil;
+ memclear (field + j, (XLFD_LAST_INDEX - j) * word_size);
if (INTEGERP (field[XLFD_ENCODING_INDEX]))
field[XLFD_ENCODING_INDEX]
= Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
@@ -1164,13 +1159,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 +1281,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 +1291,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 +1300,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 +1327,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 +1589,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 +1717,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 +1770,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 +2144,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 +2171,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 +2664,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 +3209,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 +3233,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 +3366,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;
}
@@ -3378,16 +3399,11 @@ font_open_by_spec (struct frame *f, Lisp_Object spec)
Lisp_Object
font_open_by_name (struct frame *f, Lisp_Object name)
{
- Lisp_Object args[2];
- Lisp_Object spec, ret;
-
- args[0] = QCname;
- args[1] = name;
- spec = Ffont_spec (2, args);
- ret = font_open_by_spec (f, spec);
+ Lisp_Object spec = CALLN (Ffont_spec, QCname, name);
+ Lisp_Object ret = font_open_by_spec (f, spec);
/* Do not lose name originally put in. */
if (!NILP (ret))
- font_put_extra (ret, QCuser_spec, args[1]);
+ font_put_extra (ret, QCuser_spec, name);
return ret;
}
@@ -3499,8 +3515,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 +3538,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 +3564,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.
@@ -3702,10 +3707,10 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
if (STRINGP (string))
face_id = face_at_string_position (w, string, pos, 0, &endptr,
- DEFAULT_FACE_ID, 0);
+ DEFAULT_FACE_ID, false);
else
face_id = face_at_buffer_position (w, pos, &endptr,
- pos + 100, 0, -1);
+ pos + 100, false, -1);
face = FACE_FROM_ID (f, face_id);
}
if (multibyte)
@@ -3749,7 +3754,7 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
int face_id;
face_id = face_at_buffer_position (w, pos, &ignore,
- *limit, 0, -1);
+ *limit, false, -1);
face = FACE_FROM_ID (XFRAME (w->frame), face_id);
}
}
@@ -3910,29 +3915,37 @@ usage: (font-spec ARGS...) */)
return spec;
}
-/* Return a copy of FONT as a font-spec. */
+/* Return a copy of FONT as a font-spec. For the sake of speed, this code
+ relies on an internal stuff exposed from alloc.c and should be handled
+ with care. */
+
Lisp_Object
copy_font_spec (Lisp_Object font)
{
- Lisp_Object new_spec, tail, prev, extra;
- int i;
+ enum { font_spec_size = VECSIZE (struct font_spec) };
+ Lisp_Object new_spec, tail, *pcdr;
+ struct font_spec *spec;
CHECK_FONT (font);
- new_spec = font_make_spec ();
- for (i = 1; i < FONT_EXTRA_INDEX; i++)
- ASET (new_spec, i, AREF (font, i));
- extra = Fcopy_alist (AREF (font, FONT_EXTRA_INDEX));
- /* We must remove :font-entity property. */
- for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
- if (EQ (XCAR (XCAR (tail)), QCfont_entity))
- {
- if (NILP (prev))
- extra = XCDR (extra);
- else
- XSETCDR (prev, XCDR (tail));
- break;
- }
- ASET (new_spec, FONT_EXTRA_INDEX, extra);
+
+ /* Make an uninitialized font-spec object. */
+ spec = (struct font_spec *) allocate_vector (font_spec_size);
+ XSETPVECTYPESIZE (spec, PVEC_FONT, FONT_SPEC_MAX,
+ font_spec_size - FONT_SPEC_MAX);
+
+ spec->props[FONT_TYPE_INDEX] = spec->props[FONT_EXTRA_INDEX] = Qnil;
+
+ /* Copy basic properties FONT_FOUNDRY_INDEX..FONT_AVGWIDTH_INDEX. */
+ memcpy (spec->props + 1, XVECTOR (font)->contents + 1,
+ (FONT_EXTRA_INDEX - 1) * word_size);
+
+ /* Copy an alist of extra information but discard :font-entity property. */
+ pcdr = spec->props + FONT_EXTRA_INDEX;
+ for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
+ if (!EQ (XCAR (XCAR (tail)), QCfont_entity))
+ *pcdr = Fcons (XCAR (tail), Qnil), pcdr = xcdr_addr (*pcdr);
+
+ XSETFONT (new_spec, spec);
return new_spec;
}
@@ -4162,13 +4175,7 @@ how close they are to PREFER. */)
else
vec = font_vconcat_entity_vectors (list);
if (n == 0 || n >= ASIZE (vec))
- {
- Lisp_Object args[2];
-
- args[0] = vec;
- args[1] = Qnil;
- list = Fappend (2, args);
- }
+ list = CALLN (Fappend, vec, Qnil);
else
{
for (list = Qnil, n--; n >= 0; n--)
@@ -4235,7 +4242,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;
}
@@ -4513,12 +4520,11 @@ character code corresponding to the glyph or nil if there's no
corresponding character. */)
(Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
{
- struct font *font;
+ struct font *font = CHECK_FONT_GET_OBJECT (font_object);
Lisp_Object gstring_in, gstring_out, g;
Lisp_Object alternates;
int i, num;
- CHECK_FONT_GET_OBJECT (font_object, font);
if (! font->driver->otf_drive)
error ("Font backend %s can't drive OpenType GSUB table",
SDATA (SYMBOL_NAME (font->driver->type)));
@@ -4628,12 +4634,9 @@ FEATURE is a symbol representing OpenType feature tag.
If the font is not OpenType font, CAPABILITY is nil. */)
(Lisp_Object font_object)
{
- struct font *font;
- Lisp_Object val;
+ struct font *font = CHECK_FONT_GET_OBJECT (font_object);
+ Lisp_Object val = make_uninit_vector (9);
- CHECK_FONT_GET_OBJECT (font_object, font);
-
- val = make_uninit_vector (9);
ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
ASET (val, 2, make_number (font->pixel_size));
@@ -4653,9 +4656,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]
@@ -4671,12 +4675,11 @@ the corresponding element is nil. */)
(Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
Lisp_Object object)
{
- struct font *font;
+ struct font *font = CHECK_FONT_GET_OBJECT (font_object);
ptrdiff_t i, len;
Lisp_Object *chars, vec;
USE_SAFE_ALLOCA;
- CHECK_FONT_GET_OBJECT (font_object, font);
if (NILP (object))
{
ptrdiff_t charpos, bytepos;
@@ -4698,45 +4701,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++)
@@ -4873,8 +4881,11 @@ If FRAME is omitted or nil, use the selected frame. */)
DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
doc: /* Return information about a font named NAME on frame FRAME.
If FRAME is omitted or nil, use the selected frame.
-The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
- HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
+
+The returned value is a vector:
+ [ OPENED-NAME FULL-NAME SIZE HEIGHT BASELINE-OFFSET RELATIVE-COMPOSE
+ DEFAULT-ASCENT MAX-WIDTH ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
+ CAPABILITY ]
where
OPENED-NAME is the name used for opening the font,
FULL-NAME is the full name of the font,
@@ -4882,7 +4893,33 @@ where
HEIGHT is the pixel-height of the font (i.e., ascent + descent),
BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
- how to compose characters.
+ how to compose characters,
+ MAX-WIDTH is the maximum advance width of the font,
+ ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font
+ in pixels,
+ FILENAME is the font file name, a string (or nil if the font backend
+ doesn't provide a file name).
+ CAPABILITY is a list whose first element is a symbol representing the
+ font format, one of x, opentype, truetype, type1, pcf, or bdf.
+ The remaining elements describe the details of the font capabilities,
+ as follows:
+
+ If the font is OpenType font, the form of the list is
+ \(opentype GSUB GPOS)
+ where GSUB shows which "GSUB" features the font supports, and GPOS
+ shows which "GPOS" features the font supports. Both GSUB and GPOS are
+ lists of the form:
+ \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
+
+ where
+ SCRIPT is a symbol representing OpenType script tag.
+ LANGSYS is a symbol representing OpenType langsys tag, or nil
+ representing the default langsys.
+ FEATURE is a symbol representing OpenType feature tag.
+
+ If the font is not an OpenType font, there are no elements
+ in CAPABILITY except the font format symbol.
+
If the named font is not yet loaded, return nil. */)
(Lisp_Object name, Lisp_Object frame)
{
@@ -4918,7 +4955,7 @@ If the named font is not yet loaded, return nil. */)
return Qnil;
font = XFONT_OBJECT (font_object);
- info = make_uninit_vector (7);
+ info = make_uninit_vector (14);
ASET (info, 0, AREF (font_object, FONT_NAME_INDEX));
ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX));
ASET (info, 2, make_number (font->pixel_size));
@@ -4926,6 +4963,16 @@ If the named font is not yet loaded, return nil. */)
ASET (info, 4, make_number (font->baseline_offset));
ASET (info, 5, make_number (font->relative_compose));
ASET (info, 6, make_number (font->default_ascent));
+ ASET (info, 7, make_number (font->max_width));
+ ASET (info, 8, make_number (font->ascent));
+ ASET (info, 9, make_number (font->descent));
+ ASET (info, 10, make_number (font->space_width));
+ ASET (info, 11, make_number (font->average_width));
+ ASET (info, 12, AREF (font_object, FONT_FILE_INDEX));
+ if (font->driver->otf_capability)
+ ASET (info, 13, Fcons (Qopentype, font->driver->otf_capability (font)));
+ else
+ ASET (info, 13, Qnil);
#if 0
/* As font_object is still in FONT_OBJLIST of the entity, we can't
@@ -4938,8 +4985,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 +5035,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 +5045,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 +5067,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))
@@ -5081,19 +5129,21 @@ syms_of_font (void)
DEFSYM (Qopentype, "opentype");
+ /* Important character set symbols. */
DEFSYM (Qascii_0, "ascii-0");
DEFSYM (Qiso8859_1, "iso8859-1");
DEFSYM (Qiso10646_1, "iso10646-1");
DEFSYM (Qunicode_bmp, "unicode-bmp");
DEFSYM (Qunicode_sip, "unicode-sip");
+ /* Unicode category `Cf'. */
DEFSYM (QCf, "Cf");
+ /* Symbols representing keys of font extra info. */
DEFSYM (QCotf, ":otf");
DEFSYM (QClang, ":lang");
DEFSYM (QCscript, ":script");
DEFSYM (QCantialias, ":antialias");
-
DEFSYM (QCfoundry, ":foundry");
DEFSYM (QCadstyle, ":adstyle");
DEFSYM (QCregistry, ":registry");
@@ -5104,11 +5154,14 @@ syms_of_font (void)
DEFSYM (QCfont_entity, ":font-entity");
DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
+ /* Symbols representing values of font spacing property. */
DEFSYM (Qc, "c");
DEFSYM (Qm, "m");
DEFSYM (Qp, "p");
DEFSYM (Qd, "d");
+ /* Special ADSTYLE properties to avoid fonts used for Latin
+ characters; used in xfont.c and ftfont.c. */
DEFSYM (Qja, "ja");
DEFSYM (Qko, "ko");
diff --git a/src/font.h b/src/font.h
index 832e7066965..efc184eef77 100644
--- a/src/font.h
+++ b/src/font.h
@@ -56,7 +56,6 @@ INLINE_HEADER_BEGIN
Note: Only the method `open' of a font-driver can create this
object, and it should never be modified by Lisp. */
-extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
/* An enumerator for each font property. This is used as an index to
the vector of FONT-SPEC and FONT-ENTITY.
@@ -162,9 +161,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 +178,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
};
@@ -245,17 +238,6 @@ enum font_property_index
#define FONT_BASE(f) ((f)->ascent)
#define FONT_DESCENT(f) ((f)->descent)
-extern Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript;
-extern Lisp_Object QCavgwidth, QCantialias, QCfont_entity;
-extern Lisp_Object Qp;
-
-
-/* Important character set symbols. */
-extern Lisp_Object Qascii_0;
-extern Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
-
-/* Special ADSTYLE properties to avoid fonts used for Latin characters. */
-extern Lisp_Object Qja, Qko;
/* Structure for a font-spec. */
@@ -431,55 +413,91 @@ struct font_bitmap
/* Predicates to check various font-related objects. */
/* True iff X is one of font-spec, font-entity, and font-object. */
-#define FONTP(x) PSEUDOVECTORP (x, PVEC_FONT)
+INLINE bool
+FONTP (Lisp_Object x)
+{
+ return PSEUDOVECTORP (x, PVEC_FONT);
+}
+
/* True iff X is font-spec. */
-#define FONT_SPEC_P(x) \
- (FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_SPEC_MAX)
+INLINE bool
+FONT_SPEC_P (Lisp_Object x)
+{
+ return FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_SPEC_MAX;
+}
+
/* True iff X is font-entity. */
-#define FONT_ENTITY_P(x) \
- (FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_ENTITY_MAX)
+INLINE bool
+FONT_ENTITY_P (Lisp_Object x)
+{
+ return FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_ENTITY_MAX;
+}
+
/* True iff X is font-object. */
-#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) \
- do { if (! FONTP (x)) wrong_type_argument (Qfont, x); } while (false)
-#define CHECK_FONT_SPEC(x) \
- do { if (! FONT_SPEC_P (x)) wrong_type_argument (Qfont_spec, x); } \
- while (false)
-#define CHECK_FONT_ENTITY(x) \
- do { if (! FONT_ENTITY_P (x)) wrong_type_argument (Qfont_entity, x); } \
- while (false)
-#define CHECK_FONT_OBJECT(x) \
- do { if (! FONT_OBJECT_P (x)) wrong_type_argument (Qfont_object, x); } \
- while (false)
-
-#define CHECK_FONT_GET_OBJECT(x, font) \
- do { \
- CHECK_FONT_OBJECT (x); \
- font = XFONT_OBJECT (x); \
- } while (false)
+INLINE bool
+FONT_OBJECT_P (Lisp_Object x)
+{
+ return FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX;
+}
+
+/* Type checking functions for various font-related objects. */
+
+INLINE void
+CHECK_FONT (Lisp_Object x)
+{
+ CHECK_TYPE (FONTP (x), Qfont, x);
+}
+
+INLINE void
+CHECK_FONT_SPEC (Lisp_Object x)
+{
+ CHECK_TYPE (FONT_SPEC_P (x), Qfont_spec, x);
+}
+
+INLINE void
+CHECK_FONT_ENTITY (Lisp_Object x)
+{
+ CHECK_TYPE (FONT_ENTITY_P (x), Qfont_entity, x);
+}
+
+INLINE void
+CHECK_FONT_OBJECT (Lisp_Object x)
+{
+ CHECK_TYPE (FONT_OBJECT_P (x), Qfont_object, x);
+}
+
+/* C pointer extraction functions for various font-related objects. */
+
+INLINE struct font_spec *
+XFONT_SPEC (Lisp_Object p)
+{
+ eassert (FONT_SPEC_P (p));
+ return XUNTAG (p, Lisp_Vectorlike);
+}
+
+INLINE struct font_entity *
+XFONT_ENTITY (Lisp_Object p)
+{
+ eassert (FONT_ENTITY_P (p));
+ return XUNTAG (p, Lisp_Vectorlike);
+}
+
+INLINE struct font *
+XFONT_OBJECT (Lisp_Object p)
+{
+ eassert (FONT_OBJECT_P (p));
+ return XUNTAG (p, Lisp_Vectorlike);
+}
-#define XFONT_SPEC(p) \
- (eassert (FONT_SPEC_P (p)), (struct font_spec *) XUNTAG (p, Lisp_Vectorlike))
-#define XFONT_ENTITY(p) \
- (eassert (FONT_ENTITY_P (p)), \
- (struct font_entity *) XUNTAG (p, Lisp_Vectorlike))
-#define XFONT_OBJECT(p) \
- (eassert (FONT_OBJECT_P (p)), (struct font *) XUNTAG (p, Lisp_Vectorlike))
#define XSETFONT(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FONT))
+INLINE struct font *
+CHECK_FONT_GET_OBJECT (Lisp_Object x)
+{
+ CHECK_FONT_OBJECT (x);
+ return XFONT_OBJECT (x);
+}
+
/* Number of pt per inch (from the TeXbook). */
#define PT_PER_INCH 72.27
@@ -564,11 +582,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 +603,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 +632,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 +732,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 +785,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 +805,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,
@@ -831,11 +824,11 @@ extern struct font_driver xfont_driver;
extern void syms_of_xfont (void);
extern void syms_of_ftxfont (void);
#ifdef HAVE_XFT
-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;
+extern void syms_of_xftfont (void);
#endif
#ifdef HAVE_BDFFONT
extern void syms_of_bdffont (void);
@@ -847,7 +840,6 @@ extern struct font_driver uniscribe_font_driver;
extern void syms_of_w32font (void);
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
-extern Lisp_Object Qfontsize;
extern struct font_driver nsfont_driver;
extern void syms_of_nsfont (void);
extern void syms_of_macfont (void);
@@ -857,8 +849,6 @@ extern void syms_of_macfont (void);
#define FONT_DEBUG
#endif
-extern Lisp_Object QCfoundry;
-
extern void font_add_log (const char *, Lisp_Object, Lisp_Object);
extern void font_deferred_log (const char *, Lisp_Object, Lisp_Object);
diff --git a/src/fontset.c b/src/fontset.c
index d9aa99d05f5..c0303fa5a34 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -92,26 +92,27 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
range of characters in this fontset, but may be available in the
default fontset.
+ A fontset has 8 extra slots.
- A fontset has 9 extra slots.
-
- The 1st slot: the ID number of the fontset
+ The 1st slot:
+ base: the ID number of the fontset
+ realized: Likewise
The 2nd slot:
base: the name of the fontset
realized: nil
The 3rd slot:
- base: nil
- realized: the base fontset
+ base: the font name for ASCII characters
+ realized: nil
The 4th slot:
base: nil
- realized: the frame that the fontset belongs to
+ realized: the base fontset
The 5th slot:
- base: the font name for ASCII characters
- realized: nil
+ base: nil
+ realized: the frame that the fontset belongs to
The 6th slot:
base: nil
@@ -120,15 +121,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
The 7th slot:
base: nil
- realized: Alist of font index vs the corresponding repertory
- char-table.
-
- The 8th slot:
- base: nil
realized: If the base is not the default fontset, a fontset
- realized from the default fontset, else nil.
+ realized from the default fontset, else nil.
- The 9th slot:
+ The 8th slot:
base: Same as element value (but for fallback fonts).
realized: Likewise.
@@ -156,11 +152,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/********** VARIABLES and FUNCTION PROTOTYPES **********/
-static Lisp_Object Qfontset;
-static Lisp_Object Qfontset_info;
-static Lisp_Object Qprepend, Qappend;
-Lisp_Object Qlatin;
-
/* Vector containing all fontsets. */
static Lisp_Object Vfontset_table;
@@ -209,27 +200,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 +230,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)))
@@ -358,16 +349,17 @@ fontset_add (Lisp_Object fontset, Lisp_Object range, Lisp_Object elt, Lisp_Objec
from1 = from, to1 = to;
args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
char_table_set_range (fontset, from, to1,
- NILP (args[idx]) ? args[1 - idx]
- : Fvconcat (2, args));
+ (NILP (args[idx]) ? args[1 - idx]
+ : CALLMANY (Fvconcat, args)));
from = to1 + 1;
} while (from < to);
}
else
{
args[idx] = FONTSET_FALLBACK (fontset);
- set_fontset_fallback
- (fontset, NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args));
+ set_fontset_fallback (fontset,
+ (NILP (args[idx]) ? args[1 - idx]
+ : CALLMANY (Fvconcat, args)));
}
}
@@ -393,7 +385,7 @@ reorder_font_vector (Lisp_Object font_group, struct font *font)
Lisp_Object vec, font_object;
int size;
int i;
- bool score_changed = 0;
+ bool score_changed = false;
if (font)
XSETFONT (font_object, font);
@@ -448,14 +440,15 @@ reorder_font_vector (Lisp_Object font_group, struct font *font)
if (RFONT_DEF_SCORE (rfont_def) != score)
{
RFONT_DEF_SET_SCORE (rfont_def, score);
- score_changed = 1;
+ score_changed = true;
}
}
if (score_changed)
qsort (XVECTOR (vec)->contents, size, word_size,
fontset_compare_rfontdef);
- XSETCAR (font_group, make_number (charset_ordered_list_tick));
+ EMACS_INT low_tick_bits = charset_ordered_list_tick & MOST_POSITIVE_FIXNUM;
+ XSETCAR (font_group, make_number (low_tick_bits));
}
/* Return a font-group (actually a cons (-1 . FONT-GROUP-VECTOR)) for
@@ -852,21 +845,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 +858,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 +868,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 +1072,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 +1104,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;
@@ -1455,12 +1433,8 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
}
else if (STRINGP (font_spec))
{
- Lisp_Object args[2];
-
fontname = font_spec;
- args[0] = QCname;
- args[1] = font_spec;
- font_spec = Ffont_spec (2, args);
+ font_spec = CALLN (Ffont_spec, QCname, fontname);
}
else if (FONT_SPEC_P (font_spec))
fontname = Ffont_xlfd_name (font_spec, Qnil);
@@ -1477,8 +1451,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 +1564,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 +1587,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);
}
}
}
@@ -1854,7 +1828,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
w = XWINDOW (window);
f = XFRAME (w->frame);
face_id = face_at_buffer_position (w, pos, &dummy,
- pos + 100, 0, -1);
+ pos + 100, false, -1);
}
if (! CHAR_VALID_P (c))
return Qnil;
@@ -1909,7 +1883,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 +1896,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 +1987,7 @@ format is the same as above. */)
break;
}
+ SAFE_FREE ();
return tables[0];
}
@@ -2163,7 +2139,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/fontset.h b/src/fontset.h
index e743555ef76..610394431e1 100644
--- a/src/fontset.h
+++ b/src/fontset.h
@@ -36,7 +36,6 @@ extern int fontset_from_font (Lisp_Object);
extern int fs_query_fontset (Lisp_Object, int);
extern Lisp_Object list_fontsets (struct frame *, Lisp_Object, int);
-extern Lisp_Object Qlatin;
extern Lisp_Object fontset_name (int);
extern Lisp_Object fontset_ascii (int);
diff --git a/src/frame.c b/src/frame.c
index d9b33c638a1..2ce5a623853 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -51,71 +51,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "msdos.h"
#include "dosfns.h"
#endif
-
-#ifdef HAVE_NS
-Lisp_Object Qns_parse_geometry;
-#endif
-
-Lisp_Object Qframep, Qframe_live_p;
-Lisp_Object Qicon, Qmodeline;
-Lisp_Object Qonly, Qnone;
-Lisp_Object Qx, Qw32, Qpc, Qns;
-Lisp_Object Qvisible;
-Lisp_Object Qdisplay_type;
-static Lisp_Object Qbackground_mode;
-Lisp_Object Qnoelisp;
-
-static Lisp_Object Qx_frame_parameter;
-Lisp_Object Qx_resource_name;
-Lisp_Object Qterminal;
-
-/* Frame parameters (set or reported). */
-
-Lisp_Object Qauto_raise, Qauto_lower;
-Lisp_Object Qborder_color, Qborder_width;
-Lisp_Object Qcursor_color, Qcursor_type;
-Lisp_Object Qheight, Qwidth;
-Lisp_Object Qleft, Qright;
-Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
-Lisp_Object Qtooltip;
-Lisp_Object Qinternal_border_width;
-Lisp_Object Qright_divider_width, Qbottom_divider_width;
-Lisp_Object Qmouse_color;
-Lisp_Object Qminibuffer;
-Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
-Lisp_Object Qvisibility;
-Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-Lisp_Object Qscreen_gamma;
-Lisp_Object Qline_spacing;
-static Lisp_Object Quser_position, Quser_size;
-Lisp_Object Qwait_for_wm;
-static Lisp_Object Qwindow_id;
-#ifdef HAVE_X_WINDOWS
-static Lisp_Object Qouter_window_id;
+#ifdef USE_X_TOOLKIT
+#include "widget.h"
#endif
-Lisp_Object Qparent_id;
-Lisp_Object Qtitle, Qname;
-static Lisp_Object Qexplicit_name;
-Lisp_Object Qunsplittable;
-Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position;
-Lisp_Object Qleft_fringe, Qright_fringe;
-Lisp_Object Qbuffer_predicate;
-static Lisp_Object Qbuffer_list, Qburied_buffer_list;
-Lisp_Object Qtty_color_mode;
-Lisp_Object Qtty, Qtty_type;
-
-Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth, Qmaximized;
-Lisp_Object Qsticky;
-Lisp_Object Qfont_backend;
-Lisp_Object Qalpha;
-
-Lisp_Object Qface_set_after_frame_default;
-
-static Lisp_Object Qfocus_in_hook;
-static Lisp_Object Qfocus_out_hook;
-static Lisp_Object Qdelete_frame_functions;
-
-static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
/* The currently selected frame. */
@@ -129,6 +67,9 @@ static struct frame *last_nonminibuf_frame;
/* False means there are no visible garbaged frames. */
bool frame_garbaged;
+/* The default tool bar height for future frames. */
+int frame_default_tool_bar_height;
+
#ifdef HAVE_WINDOW_SYSTEM
static void x_report_frame_params (struct frame *, Lisp_Object *);
#endif
@@ -163,19 +104,16 @@ decode_any_frame (register Lisp_Object frame)
return XFRAME (frame);
}
+#ifdef HAVE_WINDOW_SYSTEM
+
bool
window_system_available (struct frame *f)
{
- if (f)
- return FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f);
- else
-#ifdef HAVE_WINDOW_SYSTEM
- return x_display_list != NULL;
-#else
- return 0;
-#endif
+ return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL;
}
+#endif /* HAVE_WINDOW_SYSTEM */
+
struct frame *
decode_window_system_frame (Lisp_Object frame)
{
@@ -194,30 +132,34 @@ check_window_system (struct frame *f)
: "Window system is not in use or not initialized");
}
-static void
-set_menu_bar_lines_1 (Lisp_Object window, int n)
-{
- struct window *w = XWINDOW (window);
- struct frame *f = XFRAME (WINDOW_FRAME (w));
-
- w->top_line += n;
- w->pixel_top += n * FRAME_LINE_HEIGHT (f);
- w->total_lines -= n;
- w->pixel_height -= n * FRAME_LINE_HEIGHT (f);
-
- /* Handle just the top child in a vertical split. */
- if (WINDOW_VERTICAL_COMBINATION_P (w))
- set_menu_bar_lines_1 (w->contents, n);
- else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
- /* Adjust all children in a horizontal split. */
- for (window = w->contents; !NILP (window); window = w->next)
- {
- w = XWINDOW (window);
- set_menu_bar_lines_1 (window, n);
- }
+/* Return the value of frame parameter PROP in frame FRAME. */
+
+Lisp_Object
+get_frame_param (register struct frame *frame, Lisp_Object prop)
+{
+ register Lisp_Object tem;
+
+ tem = Fassq (prop, frame->param_alist);
+ if (EQ (tem, Qnil))
+ return tem;
+ return Fcdr (tem);
}
-void
+/* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
+ state of frame F would be affected by a vertical (horizontal if
+ HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
+ parameter that is changed. */
+bool
+frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
+{
+ return (EQ (frame_inhibit_implied_resize, Qt)
+ || (CONSP (frame_inhibit_implied_resize)
+ && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
+ || !NILP (get_frame_param (f, Qfullscreen))
+ || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
+}
+
+static void
set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
int nlines;
@@ -238,11 +180,11 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
if (nlines != olines)
{
windows_or_buffers_changed = 14;
- FRAME_WINDOW_SIZES_CHANGED (f) = 1;
FRAME_MENU_BAR_LINES (f) = nlines;
FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
- set_menu_bar_lines_1 (f->root_window, nlines - olines);
- adjust_frame_glyphs (f);
+ change_frame_size (f, FRAME_COLS (f),
+ FRAME_LINES (f) + olines - nlines,
+ 0, 1, 0, 0);
}
}
@@ -325,6 +267,317 @@ predicates which report frame's specific UI-related capabilities. */)
return type;
}
+/* Placeholder used by temacs -nw before window.el is loaded. */
+DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
+ Sframe_windows_min_size, 4, 4, 0,
+ doc: /* */
+ attributes: const)
+ (Lisp_Object frame, Lisp_Object horizontal,
+ Lisp_Object ignore, Lisp_Object pixelwise)
+{
+ return make_number (0);
+}
+
+static int
+frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
+ Lisp_Object ignore, Lisp_Object pixelwise)
+{
+ return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
+ ignore, pixelwise));
+}
+
+
+/* Make sure windows sizes of frame F are OK. new_width and new_height
+ are in pixels. A value of -1 means no change is requested for that
+ size (but the frame may still have to be resized to accommodate
+ windows with their minimum sizes). This can either issue a request
+ to resize the frame externally (via x_set_window_size), to resize the
+ frame internally (via resize_frame_windows) or do nothing at all.
+
+ The argument INHIBIT can assume the following values:
+
+ 0 means to unconditionally call x_set_window_size even if sizes
+ apparently do not change. Fx_create_frame uses this to pass the
+ initial size to the window manager.
+
+ 1 means to call x_set_window_size if the outer frame size really
+ changes. Fset_frame_size, Fset_frame_height, ... use this.
+
+ 2 means to call x_set_window_size provided frame_inhibit_resize
+ allows it. The menu and tool bar code use this ("3" won't work
+ here in general because menu and tool bar are often not counted in
+ the frame's text height).
+
+ 3 means call x_set_window_size if window minimum sizes must be
+ preserved or frame_inhibit_resize allows it. x_set_left_fringe,
+ x_set_scroll_bar_width, x_new_font ... use (or should use) this.
+
+ 4 means call x_set_window_size only if window minimum sizes must be
+ preserved. x_set_right_divider_width, x_set_border_width and the
+ code responsible for wrapping the tool bar use this.
+
+ 5 means to never call x_set_window_size. change_frame_size uses
+ this.
+
+ Note that even when x_set_window_size is not called, individual
+ windows may have to be resized (via `window--sanitize-window-sizes')
+ in order to support minimum size constraints.
+
+ PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
+ symbol of the parameter changed (like `menu-bar-lines', `font', ...).
+ This is passed on to frame_inhibit_resize to let the latter decide on
+ a case-by-case basis whether the frame may be resized externally. */
+void
+adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
+ bool pretend, Lisp_Object parameter)
+{
+ int unit_width = FRAME_COLUMN_WIDTH (f);
+ int unit_height = FRAME_LINE_HEIGHT (f);
+ int old_pixel_width = FRAME_PIXEL_WIDTH (f);
+ int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
+ int old_cols = FRAME_COLS (f);
+ int old_lines = FRAME_LINES (f);
+ int new_pixel_width, new_pixel_height;
+ /* The following two values are calculated from the old frame pixel
+ sizes and any "new" settings for tool bar, menu bar and internal
+ borders. We do it this way to detect whether we have to call
+ x_set_window_size as consequence of the new settings. */
+ int windows_width = FRAME_WINDOWS_WIDTH (f);
+ int windows_height = FRAME_WINDOWS_HEIGHT (f);
+ int min_windows_width, min_windows_height;
+ /* These are a bit tedious, maybe we should use a macro. */
+ struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
+ int old_windows_width = WINDOW_PIXEL_WIDTH (r);
+ int old_windows_height
+ = (WINDOW_PIXEL_HEIGHT (r)
+ + (FRAME_HAS_MINIBUF_P (f)
+ ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
+ : 0));
+ int new_windows_width, new_windows_height;
+ int old_text_width = FRAME_TEXT_WIDTH (f);
+ int old_text_height = FRAME_TEXT_HEIGHT (f);
+ /* If a size is < 0 use the old value. */
+ int new_text_width = (new_width >= 0) ? new_width : old_text_width;
+ int new_text_height = (new_height >= 0) ? new_height : old_text_height;
+ int new_cols, new_lines;
+ bool inhibit_horizontal, inhibit_vertical;
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+
+ /* `make-frame' initializes Vframe_adjust_size_history to (Qt) and
+ strips its car when exiting. Just in case make sure its size never
+ exceeds 100. */
+ if (!NILP (Fconsp (Vframe_adjust_size_history))
+ && EQ (Fcar (Vframe_adjust_size_history), Qt)
+ && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
+ Vframe_adjust_size_history =
+ Fcons (Qt, Fcons (list5 (make_number (0),
+ make_number (new_text_width),
+ make_number (new_text_height),
+ make_number (inhibit), parameter),
+ Fcdr (Vframe_adjust_size_history)));
+
+ /* The following two values are calculated from the old window body
+ sizes and any "new" settings for scroll bars, dividers, fringes and
+ margins (though the latter should have been processed already). */
+ min_windows_width
+ = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
+ min_windows_height
+ = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
+
+ if (inhibit >= 2 && inhibit <= 4)
+ /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
+ within the limits and either frame_inhibit_resize tells us to do
+ so or INHIBIT equals 4. */
+ {
+ inhibit_horizontal = ((windows_width >= min_windows_width
+ && (inhibit == 4
+ || frame_inhibit_resize (f, true, parameter)))
+ ? true : false);
+ inhibit_vertical = ((windows_height >= min_windows_height
+ && (inhibit == 4
+ || frame_inhibit_resize (f, false, parameter)))
+ ? true : false);
+ }
+ else
+ /* Otherwise inhibit if INHIBIT equals 5. */
+ inhibit_horizontal = inhibit_vertical = inhibit == 5;
+
+ new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
+ ? old_pixel_width
+ : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
+ min_windows_width
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
+ new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
+ new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
+ new_cols = new_text_width / unit_width;
+
+ new_pixel_height = ((inhibit_vertical && (inhibit < 5))
+ ? old_pixel_height
+ : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
+ min_windows_height
+ + FRAME_TOP_MARGIN_HEIGHT (f)
+ + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
+ new_windows_height = (new_pixel_height
+ - FRAME_TOP_MARGIN_HEIGHT (f)
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
+ new_lines = new_text_height / unit_height;
+
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f)
+ && f->can_x_set_window_size
+ && ((!inhibit_horizontal
+ && (new_pixel_width != old_pixel_width
+ || inhibit == 0 || inhibit == 2))
+ || (!inhibit_vertical
+ && (new_pixel_height != old_pixel_height
+ || inhibit == 0 || inhibit == 2))))
+ /* We are either allowed to change the frame size or the minimum
+ sizes request such a change. Do not care for fixing minimum
+ sizes here, we do that eventually when we're called from
+ change_frame_size. */
+ {
+ /* Make sure we respect fullheight and fullwidth. */
+ if (inhibit_horizontal)
+ new_text_width = old_text_width;
+ else if (inhibit_vertical)
+ new_text_height = old_text_height;
+
+ if (!NILP (Fconsp (Vframe_adjust_size_history))
+ && EQ (Fcar (Vframe_adjust_size_history), Qt)
+ && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
+ Vframe_adjust_size_history =
+ Fcons (Qt, Fcons (list5 (make_number (1),
+ make_number (new_text_width),
+ make_number (new_text_height),
+ make_number (new_cols),
+ make_number (new_lines)),
+ Fcdr (Vframe_adjust_size_history)));
+
+ x_set_window_size (f, 0, new_text_width, new_text_height, 1);
+ f->resized_p = true;
+
+ return;
+ }
+#endif
+
+ if (new_text_width == old_text_width
+ && new_text_height == old_text_height
+ && new_windows_width == old_windows_width
+ && new_windows_height == old_windows_height
+ && new_pixel_width == old_pixel_width
+ && new_pixel_height == old_pixel_height
+ && new_cols == old_cols
+ && new_lines == old_lines)
+ /* No change. Sanitize window sizes and return. */
+ {
+ sanitize_window_sizes (frame, Qt);
+ sanitize_window_sizes (frame, Qnil);
+
+ return;
+ }
+
+ block_input ();
+
+#ifdef MSDOS
+ /* We only can set screen dimensions to certain values supported
+ by our video hardware. Try to find the smallest size greater
+ or equal to the requested dimensions. */
+ dos_set_window_size (&new_lines, &new_cols);
+#endif
+
+ if (new_windows_width != old_windows_width)
+ {
+ resize_frame_windows (f, new_windows_width, 1, 1);
+
+ /* MSDOS frames cannot PRETEND, as they change frame size by
+ manipulating video hardware. */
+ if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
+ FrameCols (FRAME_TTY (f)) = new_cols;
+
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+ if (WINDOWP (f->tool_bar_window))
+ {
+ XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
+ XWINDOW (f->tool_bar_window)->total_cols
+ = new_windows_width / unit_width;
+ }
+#endif
+ }
+
+ if (new_windows_height != old_windows_height
+ /* When the top margin has changed we have to recalculate the top
+ edges of all windows. No such calculation is necessary for the
+ left edges. */
+ || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
+ {
+ resize_frame_windows (f, new_windows_height, 0, 1);
+
+ /* MSDOS frames cannot PRETEND, as they change frame size by
+ manipulating video hardware. */
+ if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
+ FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
+ }
+
+ /* Assign new sizes. */
+ FRAME_TEXT_WIDTH (f) = new_text_width;
+ FRAME_TEXT_HEIGHT (f) = new_text_height;
+ FRAME_PIXEL_WIDTH (f) = new_pixel_width;
+ FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
+ SET_FRAME_COLS (f, new_cols);
+ SET_FRAME_LINES (f, new_lines);
+
+ if (!NILP (Fconsp (Vframe_adjust_size_history))
+ && EQ (Fcar (Vframe_adjust_size_history), Qt)
+ && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
+ Vframe_adjust_size_history =
+ Fcons (Qt, Fcons (list5 (make_number (2),
+ make_number (new_text_width),
+ make_number (new_text_height),
+ make_number (new_cols),
+ make_number (new_lines)),
+ Fcdr (Vframe_adjust_size_history)));
+
+ {
+ struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+ int text_area_x, text_area_y, text_area_width, text_area_height;
+
+ window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
+ &text_area_height);
+ if (w->cursor.x >= text_area_x + text_area_width)
+ w->cursor.hpos = w->cursor.x = 0;
+ if (w->cursor.y >= text_area_y + text_area_height)
+ w->cursor.vpos = w->cursor.y = 0;
+ }
+
+ /* Sanitize window sizes. */
+ sanitize_window_sizes (frame, Qt);
+ sanitize_window_sizes (frame, Qnil);
+
+ adjust_frame_glyphs (f);
+ calculate_costs (f);
+ SET_FRAME_GARBAGED (f);
+
+ /* A frame was "resized" if one of its pixelsizes changed, even if its
+ X window wasn't resized at all. */
+ f->resized_p = (new_pixel_width != old_pixel_width
+ || new_pixel_height != old_pixel_height);
+
+ unblock_input ();
+
+ run_window_configuration_change_hook (f);
+}
+
+/* Allocate basically initialized frame. */
+
+static struct frame *
+allocate_frame (void)
+{
+ return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
+}
+
struct frame *
make_frame (bool mini_p)
{
@@ -337,9 +590,11 @@ make_frame (bool mini_p)
f = allocate_frame ();
XSETFRAME (frame, f);
+#ifdef USE_GTK
/* Initialize Lisp data. Note that allocate_frame initializes all
Lisp data to nil, so do it only for slots which should not be nil. */
fset_tool_bar_position (f, Qtop);
+#endif
/* Initialize non-Lisp data. Note that allocate_frame zeroes out all
non-Lisp data, so do it only for slots which should not be zero.
@@ -348,11 +603,18 @@ make_frame (bool mini_p)
f->wants_modeline = true;
f->redisplay = true;
f->garbaged = true;
- f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ f->can_x_set_window_size = false;
+ f->can_run_window_configuration_change_hook = false;
+ f->tool_bar_redisplayed_once = false;
f->column_width = 1; /* !FRAME_WINDOW_P value. */
f->line_height = 1; /* !FRAME_WINDOW_P value. */
#ifdef HAVE_WINDOW_SYSTEM
+ f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ f->horizontal_scroll_bars = false;
f->want_fullscreen = FULLSCREEN_NONE;
+#if ! defined (USE_GTK) && ! defined (HAVE_NS)
+ f->last_tool_bar_item = -1;
+#endif
#endif
root_window = make_window ();
@@ -378,10 +640,10 @@ make_frame (bool mini_p)
/* 10 is arbitrary,
just so that there is "something there."
- Correct size will be set up later with change_frame_size. */
+ Correct size will be set up later with adjust_frame_size. */
SET_FRAME_COLS (f, 10);
- FRAME_LINES (f) = 10;
+ SET_FRAME_LINES (f, 10);
SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
@@ -419,11 +681,15 @@ make_frame (bool mini_p)
}
if (mini_p)
- set_window_buffer (mini_window,
- (NILP (Vminibuffer_list)
- ? get_minibuffer (0)
- : Fcar (Vminibuffer_list)),
- 0, 0);
+ {
+ set_window_buffer (mini_window,
+ (NILP (Vminibuffer_list)
+ ? get_minibuffer (0)
+ : Fcar (Vminibuffer_list)),
+ 0, 0);
+ /* No horizontal scroll bars in minibuffers. */
+ wset_horizontal_scroll_bar (mw, Qnil);
+ }
fset_root_window (f, root_window);
fset_selected_window (f, root_window);
@@ -567,7 +833,10 @@ make_initial_frame (void)
FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+#ifdef HAVE_WINDOW_SYSTEM
+ f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ f->horizontal_scroll_bars = false;
+#endif
/* The default value of menu-bar-mode is t. */
set_menu_bar_lines (f, make_number (1), Qnil);
@@ -617,9 +886,15 @@ make_terminal_frame (struct terminal *terminal)
FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
#endif /* not MSDOS */
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+#ifdef HAVE_WINDOW_SYSTEM
+ f->vertical_scroll_bar_type = vertical_scroll_bar_none;
+ f->horizontal_scroll_bars = false;
+#endif
+
FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
+ FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+ FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
/* Set the top frame to the newly created frame. */
if (FRAMEP (FRAME_TTY (f)->top_frame)
@@ -701,7 +976,7 @@ affects all frames on the same terminal device. */)
if (CONSP (terminal))
{
terminal = XCDR (terminal);
- t = get_terminal (terminal, 1);
+ t = decode_live_terminal (terminal);
}
#ifdef MSDOS
if (t && t != the_only_display_info.terminal)
@@ -716,22 +991,24 @@ affects all frames on the same terminal device. */)
{
char *name = 0, *type = 0;
Lisp_Object tty, tty_type;
+ USE_SAFE_ALLOCA;
tty = get_future_frame_param
(Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
? FRAME_TTY (XFRAME (selected_frame))->name
: NULL));
if (!NILP (tty))
- name = xlispstrdupa (tty);
+ SAFE_ALLOCA_STRING (name, tty);
tty_type = get_future_frame_param
(Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
? FRAME_TTY (XFRAME (selected_frame))->type
: NULL));
if (!NILP (tty_type))
- type = xlispstrdupa (tty_type);
+ SAFE_ALLOCA_STRING (type, tty_type);
t = init_tty (name, type, 0); /* Errors are not fatal. */
+ SAFE_FREE ();
}
f = make_terminal_frame (t);
@@ -739,7 +1016,7 @@ affects all frames on the same terminal device. */)
{
int width, height;
get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
- change_frame_size (f, width, height, 0, 0, 0, 0);
+ adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil);
}
adjust_frame_glyphs (f);
@@ -870,8 +1147,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
frame's data. */
if (FRAME_COLS (f) != FrameCols (tty))
FrameCols (tty) = FRAME_COLS (f);
- if (FRAME_LINES (f) != FrameRows (tty))
- FrameRows (tty) = FRAME_LINES (f);
+ if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
+ FrameRows (tty) = FRAME_TOTAL_LINES (f);
}
tty->top_frame = frame;
}
@@ -926,7 +1203,7 @@ to that frame. */)
{
/* Preserve prefix arg that the command loop just cleared. */
kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
- Frun_hooks (1, &Qmouse_leave_buffer_hook);
+ run_hook (Qmouse_leave_buffer_hook);
/* `switch-frame' implies a focus in. */
call1 (intern ("handle-focus-in"), event);
return do_switch_frame (event, 0, 0, Qnil);
@@ -1365,7 +1642,9 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
fset_buried_buffer_list (f, Qnil);
free_font_driver_list (f);
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
xfree (f->namebuf);
+#endif
xfree (f->decode_mode_spec_buffer);
xfree (FRAME_INSERT_COST (f));
xfree (FRAME_DELETEN_COST (f));
@@ -1608,6 +1887,42 @@ and nil for X and Y. */)
RETURN_UNGCPRO (retval);
}
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* On frame F, convert character coordinates X and Y to pixel
+ coordinates *PIX_X and *PIX_Y. */
+
+static void
+frame_char_to_pixel_position (struct frame *f, int x, int y,
+ int *pix_x, int *pix_y)
+{
+ *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
+ *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
+
+ if (*pix_x < 0)
+ *pix_x = 0;
+ if (*pix_x > FRAME_PIXEL_WIDTH (f))
+ *pix_x = FRAME_PIXEL_WIDTH (f);
+
+ if (*pix_y < 0)
+ *pix_y = 0;
+ if (*pix_y > FRAME_PIXEL_HEIGHT (f))
+ *pix_y = FRAME_PIXEL_HEIGHT (f);
+}
+
+/* On frame F, reposition mouse pointer to character coordinates X and Y. */
+
+static void
+frame_set_mouse_position (struct frame *f, int x, int y)
+{
+ int pix_x, pix_y;
+
+ frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
+ frame_set_mouse_pixel_position (f, pix_x, pix_y);
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
Coordinates are relative to the frame, not a window,
@@ -1633,7 +1948,7 @@ before calling this function on it, like this.
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (XFRAME (frame)))
/* Warping the mouse will cause enternotify and focus events. */
- x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
+ frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
#else
#if defined (MSDOS)
if (FRAME_MSDOS_P (XFRAME (frame)))
@@ -1674,7 +1989,7 @@ before calling this function on it, like this.
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (XFRAME (frame)))
/* Warping the mouse will cause enternotify and focus events. */
- x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
+ frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
#else
#if defined (MSDOS)
if (FRAME_MSDOS_P (XFRAME (frame)))
@@ -1941,25 +2256,27 @@ If there is no window system support, this function does nothing. */)
return Qnil;
}
-
-/* Return the value of frame parameter PROP in frame FRAME. */
-
-#ifdef HAVE_WINDOW_SYSTEM
-#if !HAVE_NS && !HAVE_NTGUI
-static
-#endif
-Lisp_Object
-get_frame_param (register struct frame *frame, Lisp_Object prop)
+DEFUN ("frame-can-run-window-configuration-change-hook",
+ Fcan_run_window_configuration_change_hook,
+ Scan_run_window_configuration_change_hook, 2, 2, 0,
+ doc: /* Whether `window-configuration-change-hook' is run for frame FRAME.
+FRAME nil means use the selected frame. Second argument ALLOW non-nil
+means functions on `window-configuration-change-hook' are called
+whenever the window configuration of FRAME changes. ALLOW nil means
+these functions are not called.
+
+This function is currently called by `face-set-after-frame-default' only
+and should be otherwise used with utter care to avoid that running
+functions on `window-configuration-change-hook' is impeded forever. */)
+ (Lisp_Object frame, Lisp_Object allow)
{
- register Lisp_Object tem;
+ struct frame *f = decode_live_frame (frame);
- tem = Fassq (prop, frame->param_alist);
- if (EQ (tem, Qnil))
- return tem;
- return Fcdr (tem);
+ f->can_run_window_configuration_change_hook = NILP (allow) ? false : true;
+ return Qnil;
}
-#endif
+
/* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
void
@@ -2043,20 +2360,6 @@ set_term_frame_name (struct frame *f, Lisp_Object name)
update_mode_lines = 16;
}
-#ifdef HAVE_NTGUI
-void
-set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
-{
- register Lisp_Object old_alist_elt;
-
- old_alist_elt = Fassq (prop, f->param_alist);
- if (EQ (old_alist_elt, Qnil))
- fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
- else
- Fsetcdr (old_alist_elt, val);
-}
-#endif
-
void
store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
{
@@ -2148,6 +2451,18 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
}
}
+/* Return color matches UNSPEC on frame F or nil if UNSPEC
+ is not an unspecified foreground or background color. */
+
+static Lisp_Object
+frame_unspecified_color (struct frame *f, Lisp_Object unspec)
+{
+ return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
+ ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
+ : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
+ ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
+}
+
DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
doc: /* Return the parameters-alist of frame FRAME.
It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
@@ -2168,8 +2483,6 @@ If FRAME is omitted or nil, return information on the currently selected frame.
if (!FRAME_WINDOW_P (f))
{
- int fg = FRAME_FOREGROUND_PIXEL (f);
- int bg = FRAME_BACKGROUND_PIXEL (f);
Lisp_Object elt;
/* If the frame's parameter alist says the colors are
@@ -2178,31 +2491,23 @@ If FRAME is omitted or nil, return information on the currently selected frame.
elt = Fassq (Qforeground_color, alist);
if (CONSP (elt) && STRINGP (XCDR (elt)))
{
- if (strncmp (SSDATA (XCDR (elt)),
- unspecified_bg,
- SCHARS (XCDR (elt))) == 0)
- store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg));
- else if (strncmp (SSDATA (XCDR (elt)),
- unspecified_fg,
- SCHARS (XCDR (elt))) == 0)
- store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
+ elt = frame_unspecified_color (f, XCDR (elt));
+ if (!NILP (elt))
+ store_in_alist (&alist, Qforeground_color, elt);
}
else
- store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg));
+ store_in_alist (&alist, Qforeground_color,
+ tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
elt = Fassq (Qbackground_color, alist);
if (CONSP (elt) && STRINGP (XCDR (elt)))
{
- if (strncmp (SSDATA (XCDR (elt)),
- unspecified_fg,
- SCHARS (XCDR (elt))) == 0)
- store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg));
- else if (strncmp (SSDATA (XCDR (elt)),
- unspecified_bg,
- SCHARS (XCDR (elt))) == 0)
- store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
+ elt = frame_unspecified_color (f, XCDR (elt));
+ if (!NILP (elt))
+ store_in_alist (&alist, Qbackground_color, elt);
}
else
- store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg));
+ store_in_alist (&alist, Qbackground_color,
+ tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
store_in_alist (&alist, intern ("font"),
build_string (FRAME_MSDOS_P (f)
? "ms-dos"
@@ -2282,29 +2587,7 @@ If FRAME is nil, describe the currently selected frame. */)
important when param_alist's notion of colors is
"unspecified". We need to do the same here. */
if (STRINGP (value) && !FRAME_WINDOW_P (f))
- {
- const char *color_name;
- ptrdiff_t csz;
-
- if (EQ (parameter, Qbackground_color))
- {
- color_name = SSDATA (value);
- csz = SCHARS (value);
- if (strncmp (color_name, unspecified_bg, csz) == 0)
- value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
- else if (strncmp (color_name, unspecified_fg, csz) == 0)
- value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
- }
- else if (EQ (parameter, Qforeground_color))
- {
- color_name = SSDATA (value);
- csz = SCHARS (value);
- if (strncmp (color_name, unspecified_fg, csz) == 0)
- value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f));
- else if (strncmp (color_name, unspecified_bg, csz) == 0)
- value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f));
- }
- }
+ value = frame_unspecified_color (f, value);
}
else
value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
@@ -2455,7 +2738,7 @@ to `frame-height'). */)
return make_number (FRAME_PIXEL_HEIGHT (f));
else
#endif
- return make_number (FRAME_LINES (f));
+ return make_number (FRAME_TOTAL_LINES (f));
}
DEFUN ("frame-pixel-width", Fframe_pixel_width,
@@ -2472,7 +2755,7 @@ If FRAME is omitted or nil, the selected frame is used. */)
return make_number (FRAME_PIXEL_WIDTH (f));
else
#endif
- return make_number (FRAME_COLS (f));
+ return make_number (FRAME_TOTAL_COLS (f));
}
DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
@@ -2507,12 +2790,19 @@ DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
}
DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
- doc: /* Return total columns of FRAME. */)
+ doc: /* Return number of total columns of FRAME. */)
(Lisp_Object frame)
{
return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
}
+DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
+ doc: /* Return number of total lines of FRAME. */)
+ (Lisp_Object frame)
+{
+ return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
+}
+
DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
doc: /* Return text area width of FRAME in pixels. */)
(Lisp_Object frame)
@@ -2534,6 +2824,13 @@ DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
}
+DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
+ doc: /* Return scroll bar height of FRAME in pixels. */)
+ (Lisp_Object frame)
+{
+ return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
+}
+
DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
doc: /* Return fringe width of FRAME in pixels. */)
(Lisp_Object frame)
@@ -2561,110 +2858,79 @@ DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_widt
{
return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
}
-
+
DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
- doc: /* Specify that the frame FRAME has HEIGHT text lines.
+ doc: /* Set text height of frame FRAME to HEIGHT lines.
Optional third arg PRETEND non-nil means that redisplay should use
HEIGHT lines but that the idea of the actual height of the frame should
-not be changed. Optional fourth argument PIXELWISE non-nil means that
-FRAME should be HEIGHT pixels high. */)
+not be changed.
+
+Optional fourth argument PIXELWISE non-nil means that FRAME should be
+HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
+window managers may refuse to honor a HEIGHT that is not an integer
+multiple of the default frame font height. */)
(Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
{
- register struct frame *f = decode_live_frame (frame);
+ struct frame *f = decode_live_frame (frame);
+ int pixel_height;
CHECK_TYPE_RANGED_INTEGER (int, height);
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (NILP (pixelwise))
- {
- if (XINT (height) != FRAME_LINES (f))
- x_set_window_size (f, 1, FRAME_COLS (f), XINT (height), 0);
+ pixel_height = (!NILP (pixelwise)
+ ? XINT (height)
+ : XINT (height) * FRAME_LINE_HEIGHT (f));
+ adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
- do_pending_window_change (0);
- }
- else if (XINT (height) != FRAME_TEXT_HEIGHT (f))
- {
- x_set_window_size (f, 1, FRAME_TEXT_WIDTH (f), XINT (height), 1);
- do_pending_window_change (0);
- }
- }
- else
-#endif
- change_frame_size (f, 0, XINT (height), !NILP (pretend), 0, 0,
- NILP (pixelwise) ? 0 : 1);
return Qnil;
}
DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
- doc: /* Specify that the frame FRAME has WIDTH columns.
+ doc: /* Set text width of frame FRAME to WIDTH columns.
Optional third arg PRETEND non-nil means that redisplay should use WIDTH
columns but that the idea of the actual width of the frame should not
-be changed. Optional fourth argument PIXELWISE non-nil means that FRAME
-should be WIDTH pixels wide. */)
+be changed.
+
+Optional fourth argument PIXELWISE non-nil means that FRAME should be
+WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
+window managers may refuse to honor a WIDTH that is not an integer
+multiple of the default frame font width. */)
(Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
{
- register struct frame *f = decode_live_frame (frame);
+ struct frame *f = decode_live_frame (frame);
+ int pixel_width;
CHECK_TYPE_RANGED_INTEGER (int, width);
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (NILP (pixelwise))
- {
- if (XINT (width) != FRAME_COLS (f))
- x_set_window_size (f, 1, XINT (width), FRAME_LINES (f), 0);
+ pixel_width = (!NILP (pixelwise)
+ ? XINT (width)
+ : XINT (width) * FRAME_COLUMN_WIDTH (f));
+ adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
- do_pending_window_change (0);
- }
- else if (XINT (width) != FRAME_TEXT_WIDTH (f))
- {
- x_set_window_size (f, 1, XINT (width), FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
- }
- }
- else
-#endif
- change_frame_size (f, XINT (width), 0, !NILP (pretend), 0, 0,
- NILP (pixelwise) ? 0 : 1);
return Qnil;
}
DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
- doc: /* Sets size of FRAME to WIDTH by HEIGHT, measured in characters.
-Optional argument PIXELWISE non-nil means to measure in pixels. */)
+ doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters.
+Optional argument PIXELWISE non-nil means to measure in pixels. Note:
+When `frame-resize-pixelwise' is nil, some window managers may refuse to
+honor a WIDTH that is not an integer multiple of the default frame font
+width or a HEIGHT that is not an integer multiple of the default frame
+font height. */)
(Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
{
- register struct frame *f = decode_live_frame (frame);
+ struct frame *f = decode_live_frame (frame);
+ int pixel_width, pixel_height;
CHECK_TYPE_RANGED_INTEGER (int, width);
CHECK_TYPE_RANGED_INTEGER (int, height);
- /* I think this should be done with a hook. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- {
- if (!NILP (pixelwise)
- ? (XINT (width) != FRAME_TEXT_WIDTH (f)
- || XINT (height) != FRAME_TEXT_HEIGHT (f)
- || f->new_height || f->new_width)
- : (XINT (width) != FRAME_COLS (f)
- || XINT (height) != FRAME_LINES (f)
- || f->new_height || f->new_width))
- {
- x_set_window_size (f, 1, XINT (width), XINT (height),
- NILP (pixelwise) ? 0 : 1);
- do_pending_window_change (0);
- }
- }
- else
-#endif
- change_frame_size (f, XINT (width), XINT (height), 0, 0, 0,
- NILP (pixelwise) ? 0 : 1);
+ pixel_width = (!NILP (pixelwise)
+ ? XINT (width)
+ : XINT (width) * FRAME_COLUMN_WIDTH (f));
+ pixel_height = (!NILP (pixelwise)
+ ? XINT (height)
+ : XINT (height) * FRAME_LINE_HEIGHT (f));
+ adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
return Qnil;
}
@@ -2706,94 +2972,50 @@ or bottommost possible position (that stays within the screen). */)
struct frame_parm_table {
const char *name;
- Lisp_Object *variable;
+ int sym;
};
static const struct frame_parm_table frame_parms[] =
{
- {"auto-raise", &Qauto_raise},
- {"auto-lower", &Qauto_lower},
- {"background-color", 0},
- {"border-color", &Qborder_color},
- {"border-width", &Qborder_width},
- {"cursor-color", &Qcursor_color},
- {"cursor-type", &Qcursor_type},
- {"font", 0},
- {"foreground-color", 0},
- {"icon-name", &Qicon_name},
- {"icon-type", &Qicon_type},
- {"internal-border-width", &Qinternal_border_width},
- {"right-divider-width", &Qright_divider_width},
- {"bottom-divider-width", &Qbottom_divider_width},
- {"menu-bar-lines", &Qmenu_bar_lines},
- {"mouse-color", &Qmouse_color},
- {"name", &Qname},
- {"scroll-bar-width", &Qscroll_bar_width},
- {"title", &Qtitle},
- {"unsplittable", &Qunsplittable},
- {"vertical-scroll-bars", &Qvertical_scroll_bars},
- {"visibility", &Qvisibility},
- {"tool-bar-lines", &Qtool_bar_lines},
- {"scroll-bar-foreground", &Qscroll_bar_foreground},
- {"scroll-bar-background", &Qscroll_bar_background},
- {"screen-gamma", &Qscreen_gamma},
- {"line-spacing", &Qline_spacing},
- {"left-fringe", &Qleft_fringe},
- {"right-fringe", &Qright_fringe},
- {"wait-for-wm", &Qwait_for_wm},
- {"fullscreen", &Qfullscreen},
- {"font-backend", &Qfont_backend},
- {"alpha", &Qalpha},
- {"sticky", &Qsticky},
- {"tool-bar-position", &Qtool_bar_position},
+ {"auto-raise", SYMBOL_INDEX (Qauto_raise)},
+ {"auto-lower", SYMBOL_INDEX (Qauto_lower)},
+ {"background-color", -1},
+ {"border-color", SYMBOL_INDEX (Qborder_color)},
+ {"border-width", SYMBOL_INDEX (Qborder_width)},
+ {"cursor-color", SYMBOL_INDEX (Qcursor_color)},
+ {"cursor-type", SYMBOL_INDEX (Qcursor_type)},
+ {"font", -1},
+ {"foreground-color", -1},
+ {"icon-name", SYMBOL_INDEX (Qicon_name)},
+ {"icon-type", SYMBOL_INDEX (Qicon_type)},
+ {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)},
+ {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)},
+ {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)},
+ {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)},
+ {"mouse-color", SYMBOL_INDEX (Qmouse_color)},
+ {"name", SYMBOL_INDEX (Qname)},
+ {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)},
+ {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)},
+ {"title", SYMBOL_INDEX (Qtitle)},
+ {"unsplittable", SYMBOL_INDEX (Qunsplittable)},
+ {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)},
+ {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)},
+ {"visibility", SYMBOL_INDEX (Qvisibility)},
+ {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)},
+ {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)},
+ {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)},
+ {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)},
+ {"line-spacing", SYMBOL_INDEX (Qline_spacing)},
+ {"left-fringe", SYMBOL_INDEX (Qleft_fringe)},
+ {"right-fringe", SYMBOL_INDEX (Qright_fringe)},
+ {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)},
+ {"fullscreen", SYMBOL_INDEX (Qfullscreen)},
+ {"font-backend", SYMBOL_INDEX (Qfont_backend)},
+ {"alpha", SYMBOL_INDEX (Qalpha)},
+ {"sticky", SYMBOL_INDEX (Qsticky)},
+ {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
};
-#ifdef HAVE_NTGUI
-
-/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
- wanted positions of the WM window (not Emacs window).
- Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
- window (FRAME_X_WINDOW).
- */
-
-void
-x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
-{
- int newwidth = FRAME_COLS (f);
- int newheight = FRAME_LINES (f);
- Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
- *top_pos = f->top_pos;
- *left_pos = f->left_pos;
-
- if (f->want_fullscreen & FULLSCREEN_HEIGHT)
- {
- int ph;
-
- ph = x_display_pixel_height (dpyinfo);
- newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
- ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
- newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
- *top_pos = 0;
- }
-
- if (f->want_fullscreen & FULLSCREEN_WIDTH)
- {
- int pw;
-
- pw = x_display_pixel_width (dpyinfo);
- newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
- pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
- newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
- *left_pos = 0;
- }
-
- *width = newwidth;
- *height = newheight;
-}
-
-#endif /* HAVE_NTGUI */
-
#ifdef HAVE_WINDOW_SYSTEM
/* Change the parameters of frame F as specified by ALIST.
@@ -2810,7 +3032,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
/* If both of these parameters are present, it's more efficient to
set them both at once. So we wait until we've looked at the
entire list before we set them. */
- int width = 0, height = 0;
+ int width IF_LINT (= 0), height IF_LINT (= 0);
bool width_change = 0, height_change = 0;
/* Same here. */
@@ -2827,14 +3049,14 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
#ifdef HAVE_X_WINDOWS
bool icon_left_no_change = 0, icon_top_no_change = 0;
#endif
- struct gcpro gcpro1, gcpro2;
i = 0;
for (tail = alist; CONSP (tail); tail = XCDR (tail))
i++;
- parms = alloca (i * sizeof *parms);
- values = alloca (i * sizeof *values);
+ USE_SAFE_ALLOCA;
+ SAFE_ALLOCA_LISP (parms, 2 * i);
+ values = parms + i;
/* Extract parm names and values into those vectors. */
@@ -2851,10 +3073,6 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
/* TAIL and ALIST are not used again below here. */
alist = tail = Qnil;
- GCPRO2 (*parms, *values);
- gcpro1.nvars = i;
- gcpro2.nvars = i;
-
/* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
because their values appear in VALUES and strings are not valid. */
top = left = Qunbound;
@@ -2883,8 +3101,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
param_index = Fget (prop, Qx_frame_parameter);
if (NATNUMP (param_index)
- && (XFASTINT (param_index)
- < sizeof (frame_parms)/sizeof (frame_parms[0]))
+ && XFASTINT (param_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
(*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
}
@@ -2932,8 +3149,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
param_index = Fget (prop, Qx_frame_parameter);
if (NATNUMP (param_index)
- && (XFASTINT (param_index)
- < sizeof (frame_parms)/sizeof (frame_parms[0]))
+ && XFASTINT (param_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
(*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
}
@@ -2988,15 +3204,11 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
{
Lisp_Object frame;
- /* Make this 1, eventually. */
- check_frame_size (f, &width, &height, 1);
-
XSETFRAME (frame, f);
- if ((width_change || height_change)
- && (width != FRAME_TEXT_WIDTH (f)
- || height != FRAME_TEXT_HEIGHT (f)
- || f->new_height || f->new_width))
+ if ((width_change && width != FRAME_TEXT_WIDTH (f))
+ || (height_change && height != FRAME_TEXT_HEIGHT (f))
+ || (f->can_x_set_window_size && (f->new_height || f->new_width)))
{
/* If necessary provide default values for HEIGHT and WIDTH. Do
that here since otherwise a size change implied by an
@@ -3089,7 +3301,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
#endif /* HAVE_X_WINDOWS */
}
- UNGCPRO;
+ SAFE_FREE ();
}
@@ -3141,6 +3353,14 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
for non-toolkit scroll bar.
ruler-mode.el depends on this. */
: Qnil));
+ store_in_alist (alistptr, Qscroll_bar_height,
+ (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
+ ? make_number (0)
+ : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
+ ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
+ /* nil means "use default height"
+ for non-toolkit scroll bar. */
+ : Qnil));
/* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
MS-Windows it returns a value whose type is HANDLE, which is
actually a pointer. Explicit casting avoids compiler
@@ -3170,7 +3390,7 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
store_in_alist (alistptr, Qparent_id, tem);
- store_in_alist (alistptr, Qtool_bar_position, f->tool_bar_position);
+ store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
}
@@ -3244,8 +3464,7 @@ x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
{
Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
if (NATNUMP (parm_index)
- && (XFASTINT (parm_index)
- < sizeof (frame_parms)/sizeof (frame_parms[0]))
+ && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
&& FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
(*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
(f, bgcolor, Qnil);
@@ -3418,58 +3637,66 @@ x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
}
}
-
void
-x_set_fringe_width (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
+x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
- compute_fringe_widths (f, 1);
-#ifdef HAVE_X_WINDOWS
- /* Must adjust this so window managers report correct number of columns. */
- if (FRAME_X_WINDOW (f) != 0)
- x_wm_set_size_hint (f, 0, 0);
-#endif
+ int unit = FRAME_COLUMN_WIDTH (f);
+ int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
+ int new_width;
+
+ new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
+ ? eabs (XINT (new_value)) : 8);
+
+ if (new_width != old_width)
+ {
+ FRAME_LEFT_FRINGE_WIDTH (f) = new_width;
+ FRAME_FRINGE_COLS (f) /* Round up. */
+ = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
+
+ if (FRAME_X_WINDOW (f) != 0)
+ adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
+
+ SET_FRAME_GARBAGED (f);
+ }
}
+
void
-x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
- CHECK_TYPE_RANGED_INTEGER (int, arg);
+ int unit = FRAME_COLUMN_WIDTH (f);
+ int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
+ int new_width;
- if (XINT (arg) == f->border_width)
- return;
+ new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
+ ? eabs (XINT (new_value)) : 8);
- if (FRAME_X_WINDOW (f) != 0)
- error ("Cannot change the border width of a frame");
+ if (new_width != old_width)
+ {
+ FRAME_RIGHT_FRINGE_WIDTH (f) = new_width;
+ FRAME_FRINGE_COLS (f) /* Round up. */
+ = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
- f->border_width = XINT (arg);
+ if (FRAME_X_WINDOW (f) != 0)
+ adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
+
+ SET_FRAME_GARBAGED (f);
+ }
}
+
void
-x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int old = FRAME_INTERNAL_BORDER_WIDTH (f);
-
CHECK_TYPE_RANGED_INTEGER (int, arg);
- FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
- if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
- FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
-
-#ifdef USE_X_TOOLKIT
- if (FRAME_X_OUTPUT (f)->edit_widget)
- widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
-#endif
- if (FRAME_INTERNAL_BORDER_WIDTH (f) == old)
+ if (XINT (arg) == f->border_width)
return;
if (FRAME_X_WINDOW (f) != 0)
- {
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
- SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
- }
- else
- SET_FRAME_GARBAGED (f);
+ error ("Cannot change the border width of a frame");
+
+ f->border_width = XINT (arg);
}
void
@@ -3481,18 +3708,13 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg);
if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0)
FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
-
- if (FRAME_RIGHT_DIVIDER_WIDTH (f) == old)
- return;
-
- if (FRAME_X_WINDOW (f) != 0)
+ if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
{
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
+ adjust_frame_glyphs (f);
SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
}
- else
- SET_FRAME_GARBAGED (f);
+
}
void
@@ -3504,18 +3726,12 @@ x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval
FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg);
if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0)
FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
-
- if (FRAME_BOTTOM_DIVIDER_WIDTH (f) == old)
- return;
-
- if (FRAME_X_WINDOW (f) != 0)
+ if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
{
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
+ adjust_frame_glyphs (f);
SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
}
- else
- SET_FRAME_GARBAGED (f);
}
void
@@ -3556,7 +3772,7 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval
if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
|| (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
|| (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
+ || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
{
FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
= (NILP (arg)
@@ -3576,13 +3792,34 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval
However, if the window hasn't been created yet, we shouldn't
call x_set_window_size. */
if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
+
+ SET_FRAME_GARBAGED (f);
}
}
void
+x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+#if USE_HORIZONTAL_SCROLL_BARS
+ if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
+ || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
+ {
+ f->horizontal_scroll_bars = NILP (arg) ? false : true;
+
+ /* We set this parameter before creating the X window for the
+ frame, so we can get the geometry right from the start.
+ However, if the window hasn't been created yet, we shouldn't
+ call x_set_window_size. */
+ if (FRAME_X_WINDOW (f))
+ adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
+
+ SET_FRAME_GARBAGED (f);
+ }
+#endif
+}
+
+void
x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
int unit = FRAME_COLUMN_WIDTH (f);
@@ -3592,9 +3829,9 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
x_set_scroll_bar_default_width (f);
if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
+
+ SET_FRAME_GARBAGED (f);
}
else if (RANGED_INTEGERP (1, arg, INT_MAX)
&& XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
@@ -3602,19 +3839,47 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
if (FRAME_X_WINDOW (f))
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- do_pending_window_change (0);
+ adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
+
+ SET_FRAME_GARBAGED (f);
}
- /* Eventually remove the following call. It should have been done by
- x_set_window_size already. */
- change_frame_size (f, 0, 0, 0, 0, 0, 1);
XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
}
void
+x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+#if USE_HORIZONTAL_SCROLL_BARS
+ int unit = FRAME_LINE_HEIGHT (f);
+
+ if (NILP (arg))
+ {
+ x_set_scroll_bar_default_height (f);
+
+ if (FRAME_X_WINDOW (f))
+ adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
+
+ SET_FRAME_GARBAGED (f);
+ }
+ else if (RANGED_INTEGERP (1, arg, INT_MAX)
+ && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
+ {
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
+ if (FRAME_X_WINDOW (f))
+ adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
+
+ SET_FRAME_GARBAGED (f);
+ }
+
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
+#endif
+}
+
+void
x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
double alpha = 1.0;
@@ -3769,10 +4034,6 @@ validate_x_resource_name (void)
static Lisp_Object
xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
{
- register char *value;
- char *name_key;
- char *class_key;
-
CHECK_STRING (attribute);
CHECK_STRING (class);
@@ -3787,39 +4048,43 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
/* Allocate space for the components, the dots which separate them,
and the final '\0'. Make them big enough for the worst case. */
- name_key = alloca (SBYTES (Vx_resource_name)
- + (STRINGP (component)
- ? SBYTES (component) : 0)
- + SBYTES (attribute)
- + 3);
-
- class_key = alloca (SBYTES (Vx_resource_class)
- + SBYTES (class)
- + (STRINGP (subclass)
- ? SBYTES (subclass) : 0)
- + 3);
+ ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
+ + (STRINGP (component)
+ ? SBYTES (component) : 0)
+ + SBYTES (attribute)
+ + 3);
+
+ ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
+ + SBYTES (class)
+ + (STRINGP (subclass)
+ ? SBYTES (subclass) : 0)
+ + 3);
+ USE_SAFE_ALLOCA;
+ char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
+ char *class_key = name_key + name_keysize;
/* Start with emacs.FRAMENAME for the name (the specific one)
and with `Emacs' for the class key (the general one). */
- strcpy (name_key, SSDATA (Vx_resource_name));
- strcpy (class_key, SSDATA (Vx_resource_class));
+ char *nz = lispstpcpy (name_key, Vx_resource_name);
+ char *cz = lispstpcpy (class_key, Vx_resource_class);
- strcat (class_key, ".");
- strcat (class_key, SSDATA (class));
+ *cz++ = '.';
+ cz = lispstpcpy (cz, class);
if (!NILP (component))
{
- strcat (class_key, ".");
- strcat (class_key, SSDATA (subclass));
+ *cz++ = '.';
+ lispstpcpy (cz, subclass);
- strcat (name_key, ".");
- strcat (name_key, SSDATA (component));
+ *nz++ = '.';
+ nz = lispstpcpy (nz, component);
}
- strcat (name_key, ".");
- strcat (name_key, SSDATA (attribute));
+ *nz++ = '.';
+ lispstpcpy (nz, attribute);
- value = x_get_string_resource (rdb, name_key, class_key);
+ char *value = x_get_string_resource (rdb, name_key, class_key);
+ SAFE_FREE();
if (value && *value)
return build_string (value);
@@ -3871,8 +4136,10 @@ x_get_resource_string (const char *attribute, const char *class)
/* Allocate space for the components, the dots which separate them,
and the final '\0'. */
- char *name_key = SAFE_ALLOCA (invocation_namelen + strlen (attribute) + 2);
- char *class_key = alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2);
+ ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
+ ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
+ char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
+ char *class_key = name_key + name_keysize;
esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
sprintf (class_key, "%s.%s", EMACS_CLASS, class);
@@ -3899,7 +4166,7 @@ Lisp_Object
x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
const char *attribute, const char *class, enum resource_types type)
{
- register Lisp_Object tem;
+ Lisp_Object tem;
tem = Fassq (param, alist);
@@ -3925,10 +4192,9 @@ x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
{
if (attribute && dpyinfo)
{
- tem = display_x_get_resource (dpyinfo,
- build_string (attribute),
- build_string (class),
- Qnil, Qnil);
+ AUTO_STRING (at, attribute);
+ AUTO_STRING (cl, class);
+ tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
if (NILP (tem))
return Qunbound;
@@ -4038,7 +4304,8 @@ x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
if (EQ (tem, Qunbound))
tem = deflt;
- x_set_frame_parameters (f, list1 (Fcons (prop, tem)));
+ AUTO_FRAME_ARG (arg, prop, tem);
+ x_set_frame_parameters (f, arg);
return tem;
}
@@ -4215,7 +4482,7 @@ On Nextstep, this just calls `ns-parse-geometry'. */)
long
x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
{
- register Lisp_Object tem0, tem1, tem2;
+ Lisp_Object height, width, user_size, top, left, user_position;
long window_prompting = 0;
Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
@@ -4225,143 +4492,138 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
SET_FRAME_COLS (f, DEFAULT_COLS);
SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
- FRAME_LINES (f) = DEFAULT_ROWS;
+ SET_FRAME_LINES (f, DEFAULT_ROWS);
/* Window managers expect that if program-specified
positions are not (0,0), they're intentional, not defaults. */
f->top_pos = 0;
f->left_pos = 0;
- /* Ensure that old new_width and new_height will not override the
- values set here. */
- /* ++KFS: This was specific to W32, but seems ok for all platforms */
- f->new_width = f->new_height = f->new_pixelwise = 0;
+ /* Ensure that earlier new_width and new_height settings won't
+ override what we specify below. */
+ f->new_width = f->new_height = 0;
- tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
- tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
- tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+ height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+ width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+ if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
{
- if (!EQ (tem0, Qunbound))
+ if (!EQ (width, Qunbound))
{
- CHECK_NUMBER (tem0);
- if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX))
- xsignal1 (Qargs_out_of_range, tem0);
- FRAME_LINES (f) = XINT (tem0);
+ CHECK_NUMBER (width);
+ if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
+ xsignal1 (Qargs_out_of_range, width);
+
+ SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
}
- if (!EQ (tem1, Qunbound))
+
+ if (!EQ (height, Qunbound))
{
- CHECK_NUMBER (tem1);
- if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX))
- xsignal1 (Qargs_out_of_range, tem1);
- SET_FRAME_COLS (f, XINT (tem1));
+ CHECK_NUMBER (height);
+ if (! (0 <= XINT (height) && XINT (height) <= INT_MAX))
+ xsignal1 (Qargs_out_of_range, height);
+
+ SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
}
- if (!NILP (tem2) && !EQ (tem2, Qunbound))
+
+ user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+ if (!NILP (user_size) && !EQ (user_size, Qunbound))
window_prompting |= USSize;
else
window_prompting |= PSize;
}
-
- /* This used to be done _before_ calling x_figure_window_size, but
- since the height is reset here, this was really a no-op. I
- assume that moving it here does what Gerd intended (although he
- no longer can remember what that was... ++KFS, 2003-03-25. */
-
- /* Add the tool-bar height to the initial frame height so that the
- user gets a text display area of the size he specified with -g or
- via .Xdefaults. Later changes of the tool-bar height don't
- change the frame size. This is done so that users can create
- tall Emacs frames without having to guess how tall the tool-bar
- will get. */
- if (toolbar_p && FRAME_TOOL_BAR_HEIGHT (f))
+ /* Add a tool bar height to the initial frame height so that the user
+ gets a text display area of the size he specified with -g or via
+ .Xdefaults. Later changes of the tool bar height don't change the
+ frame size. This is done so that users can create tall Emacs
+ frames without having to guess how tall the tool bar will get. */
+ if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
{
- int margin, relief, bar_height;
-
- relief = (tool_bar_button_relief >= 0
- ? tool_bar_button_relief
- : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
-
- if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
- margin = XFASTINT (Vtool_bar_button_margin);
- else if (CONSP (Vtool_bar_button_margin)
- && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
- margin = XFASTINT (XCDR (Vtool_bar_button_margin));
+ if (frame_default_tool_bar_height)
+ FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height;
else
- margin = 0;
+ {
+ int margin, relief;
- /* PXW: We should be able to not round here. */
- bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
- FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
- }
+ relief = (tool_bar_button_relief >= 0
+ ? tool_bar_button_relief
+ : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
- compute_fringe_widths (f, 0);
+ if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
+ margin = XFASTINT (Vtool_bar_button_margin);
+ else if (CONSP (Vtool_bar_button_margin)
+ && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
+ margin = XFASTINT (XCDR (Vtool_bar_button_margin));
+ else
+ margin = 0;
- SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
- SET_FRAME_HEIGHT(f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
+ FRAME_TOOL_BAR_HEIGHT (f)
+ = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
+ }
+ }
- tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
- tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
- tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+ top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
+ left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
+ user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
+ if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
{
- if (EQ (tem0, Qminus))
+ if (EQ (top, Qminus))
{
f->top_pos = 0;
window_prompting |= YNegative;
}
- else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
- && CONSP (XCDR (tem0))
- && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX))
+ else if (CONSP (top) && EQ (XCAR (top), Qminus)
+ && CONSP (XCDR (top))
+ && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
{
- f->top_pos = - XINT (XCAR (XCDR (tem0)));
+ f->top_pos = - XINT (XCAR (XCDR (top)));
window_prompting |= YNegative;
}
- else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
- && CONSP (XCDR (tem0))
- && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0))))
+ else if (CONSP (top) && EQ (XCAR (top), Qplus)
+ && CONSP (XCDR (top))
+ && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
{
- f->top_pos = XINT (XCAR (XCDR (tem0)));
+ f->top_pos = XINT (XCAR (XCDR (top)));
}
- else if (EQ (tem0, Qunbound))
+ else if (EQ (top, Qunbound))
f->top_pos = 0;
else
{
- CHECK_TYPE_RANGED_INTEGER (int, tem0);
- f->top_pos = XINT (tem0);
+ CHECK_TYPE_RANGED_INTEGER (int, top);
+ f->top_pos = XINT (top);
if (f->top_pos < 0)
window_prompting |= YNegative;
}
- if (EQ (tem1, Qminus))
+ if (EQ (left, Qminus))
{
f->left_pos = 0;
window_prompting |= XNegative;
}
- else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
- && CONSP (XCDR (tem1))
- && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX))
+ else if (CONSP (left) && EQ (XCAR (left), Qminus)
+ && CONSP (XCDR (left))
+ && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
{
- f->left_pos = - XINT (XCAR (XCDR (tem1)));
+ f->left_pos = - XINT (XCAR (XCDR (left)));
window_prompting |= XNegative;
}
- else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
- && CONSP (XCDR (tem1))
- && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1))))
+ else if (CONSP (left) && EQ (XCAR (left), Qplus)
+ && CONSP (XCDR (left))
+ && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
{
- f->left_pos = XINT (XCAR (XCDR (tem1)));
+ f->left_pos = XINT (XCAR (XCDR (left)));
}
- else if (EQ (tem1, Qunbound))
+ else if (EQ (left, Qunbound))
f->left_pos = 0;
else
{
- CHECK_TYPE_RANGED_INTEGER (int, tem1);
- f->left_pos = XINT (tem1);
+ CHECK_TYPE_RANGED_INTEGER (int, left);
+ f->left_pos = XINT (left);
if (f->left_pos < 0)
window_prompting |= XNegative;
}
- if (!NILP (tem2) && ! EQ (tem2, Qunbound))
+ if (!NILP (user_position) && ! EQ (user_position, Qunbound))
window_prompting |= USPosition;
else
window_prompting |= PPosition;
@@ -4392,16 +4654,11 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
#endif /* HAVE_WINDOW_SYSTEM */
void
-frame_make_pointer_invisible (void)
+frame_make_pointer_invisible (struct frame *f)
{
if (! NILP (Vmake_pointer_invisible))
{
- struct frame *f;
- if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
- return;
-
- f = SELECTED_FRAME ();
- if (f && !f->pointer_invisible
+ if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
&& FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
{
f->mouse_moved = 0;
@@ -4412,17 +4669,11 @@ frame_make_pointer_invisible (void)
}
void
-frame_make_pointer_visible (void)
+frame_make_pointer_visible (struct frame *f)
{
/* We don't check Vmake_pointer_invisible here in case the
pointer was invisible when Vmake_pointer_invisible was set to nil. */
- struct frame *f;
-
- if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
- return;
-
- f = SELECTED_FRAME ();
- if (f && f->pointer_invisible && f->mouse_moved
+ if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
&& FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
{
FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
@@ -4519,6 +4770,7 @@ syms_of_frame (void)
{
DEFSYM (Qframep, "framep");
DEFSYM (Qframe_live_p, "frame-live-p");
+ DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
DEFSYM (Qexplicit_name, "explicit-name");
DEFSYM (Qheight, "height");
DEFSYM (Qicon, "icon");
@@ -4531,8 +4783,6 @@ syms_of_frame (void)
DEFSYM (Qicon_left, "icon-left");
DEFSYM (Qicon_top, "icon-top");
DEFSYM (Qtooltip, "tooltip");
- DEFSYM (Qleft, "left");
- DEFSYM (Qright, "right");
DEFSYM (Quser_position, "user-position");
DEFSYM (Quser_size, "user-size");
DEFSYM (Qwindow_id, "window-id");
@@ -4566,27 +4816,73 @@ syms_of_frame (void)
DEFSYM (Qterminal, "terminal");
- DEFSYM (Qgeometry, "geometry");
DEFSYM (Qworkarea, "workarea");
DEFSYM (Qmm_size, "mm-size");
DEFSYM (Qframes, "frames");
DEFSYM (Qsource, "source");
+ DEFSYM (Qframe_position, "frame-position");
+ DEFSYM (Qframe_outer_size, "frame-outer-size");
+ DEFSYM (Qexternal_border_size, "external-border-size");
+ DEFSYM (Qtitle_height, "title-height");
+ DEFSYM (Qmenu_bar_external, "menu-bar-external");
+ DEFSYM (Qmenu_bar_size, "menu-bar-size");
+ DEFSYM (Qtool_bar_external, "tool-bar-external");
+ DEFSYM (Qtool_bar_size, "tool-bar-size");
+ DEFSYM (Qframe_inner_size, "frame-inner-size");
+ DEFSYM (Qchange_frame_size, "change-frame-size");
+ DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
+ DEFSYM (Qset_window_configuration, "set-window-configuration");
+ DEFSYM (Qx_create_frame_1, "x-create-frame-1");
+ DEFSYM (Qx_create_frame_2, "x-create-frame-2");
+
#ifdef HAVE_NS
DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
#endif
+ DEFSYM (Qalpha, "alpha");
+ DEFSYM (Qauto_lower, "auto-lower");
+ DEFSYM (Qauto_raise, "auto-raise");
+ DEFSYM (Qborder_color, "border-color");
+ DEFSYM (Qborder_width, "border-width");
+ DEFSYM (Qbottom_divider_width, "bottom-divider-width");
+ DEFSYM (Qcursor_color, "cursor-color");
+ DEFSYM (Qcursor_type, "cursor-type");
+ DEFSYM (Qfont_backend, "font-backend");
+ DEFSYM (Qfullscreen, "fullscreen");
+ DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
+ DEFSYM (Qicon_name, "icon-name");
+ DEFSYM (Qicon_type, "icon-type");
+ DEFSYM (Qinternal_border_width, "internal-border-width");
+ DEFSYM (Qleft_fringe, "left-fringe");
+ DEFSYM (Qline_spacing, "line-spacing");
+ DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
+ DEFSYM (Qmouse_color, "mouse-color");
+ DEFSYM (Qname, "name");
+ DEFSYM (Qright_divider_width, "right-divider-width");
+ DEFSYM (Qright_fringe, "right-fringe");
+ DEFSYM (Qscreen_gamma, "screen-gamma");
+ DEFSYM (Qscroll_bar_background, "scroll-bar-background");
+ DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
+ DEFSYM (Qscroll_bar_height, "scroll-bar-height");
+ DEFSYM (Qscroll_bar_width, "scroll-bar-width");
+ DEFSYM (Qsticky, "sticky");
+ DEFSYM (Qtitle, "title");
+ DEFSYM (Qtool_bar_lines, "tool-bar-lines");
+ DEFSYM (Qtool_bar_position, "tool-bar-position");
+ DEFSYM (Qunsplittable, "unsplittable");
+ DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
+ DEFSYM (Qvisibility, "visibility");
+ DEFSYM (Qwait_for_wm, "wait-for-wm");
+
{
int i;
- for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
+ for (i = 0; i < ARRAYELTS (frame_parms); i++)
{
- Lisp_Object v = intern_c_string (frame_parms[i].name);
- if (frame_parms[i].variable)
- {
- *frame_parms[i].variable = v;
- staticpro (frame_parms[i].variable);
- }
+ Lisp_Object v = (frame_parms[i].sym < 0
+ ? intern_c_string (frame_parms[i].name)
+ : builtin_lisp_symbol (frame_parms[i].sym));
Fput (v, Qx_frame_parameter, make_number (i));
}
}
@@ -4639,7 +4935,7 @@ Setting this variable does not affect existing frames, only new ones. */);
Vdefault_frame_alist = Qnil;
DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
- doc: /* Default position of scroll bars on this window-system. */);
+ doc: /* Default position of vertical scroll bars on this window-system. */);
#ifdef HAVE_WINDOW_SYSTEM
#if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
/* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
@@ -4756,16 +5052,66 @@ current values of `frame-char-height' and `frame-char-width'. If this
is non-nil, no rounding occurs, hence frame sizes can increase/decrease
by one pixel.
-With some window managers you have to set this to non-nil in order to
-fully maximize frames. To resize your initial frame pixelwise,
-set this option to a non-nil value in your init file. */);
+With some window managers you may have to set this to non-nil in order
+to set the size of a frame in pixels, to maximize frames or to make them
+fullscreen. To resize your initial frame pixelwise, set this option to
+a non-nil value in your init file. */);
frame_resize_pixelwise = 0;
+ DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
+ doc: /* Whether frames should be resized implicitly.
+If this option is nil, setting font, menu bar, tool bar, internal
+borders, fringes or scroll bars of a specific frame may resize the frame
+in order to preserve the number of columns or lines it displays. If
+this option is `t', no such resizing is done. Note that the size of
+fullscreen and maximized frames, the height of fullheight frames and the
+width of fullwidth frames never change implicitly.
+
+The value of this option can be also be a list of frame parameters. In
+this case, resizing is inhibited when changing a parameter that appears
+in that list. The parameters currently handled by this option include
+`font', `font-backend', `internal-border-width', `menu-bar-lines' and
+`tool-bar-lines'.
+
+Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
+`vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
+`right-fringe' is handled as if the frame contained just one live
+window. This means, for example, that removing vertical scroll bars on
+a frame containing several side by side windows will shrink the frame
+width by the width of one scroll bar provided this option is nil and
+keep it unchanged if this option is either `t' or a list containing
+`vertical-scroll-bars'.
+
+The default value is '(tool-bar-lines) on Lucid, Motif and Windows
+\(which means that adding/removing a tool bar does not change the frame
+height), nil on all other window systems including GTK+ (which means
+that changing any of the parameters listed above may change the size of
+the frame), and `t' otherwise (which means the frame size never changes
+implicitly when there's no window system support).
+
+Note that when a frame is not large enough to accommodate a change of
+any of the parameters listed above, Emacs may try to enlarge the frame
+even if this option is non-nil. */);
+#if defined (HAVE_WINDOW_SYSTEM)
+#if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
+ frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
+#else
+ frame_inhibit_implied_resize = Qnil;
+#endif
+#else
+ frame_inhibit_implied_resize = Qt;
+#endif
+
+ DEFVAR_LISP ("frame-adjust-size-history", Vframe_adjust_size_history,
+ doc: /* History of frame size adjustments. */);
+ Vframe_adjust_size_history = Qnil;
+
staticpro (&Vframe_list);
defsubr (&Sframep);
defsubr (&Sframe_live_p);
defsubr (&Swindow_system);
+ defsubr (&Sframe_windows_min_size);
defsubr (&Smake_terminal_frame);
defsubr (&Shandle_switch_frame);
defsubr (&Sselect_frame);
@@ -4791,6 +5137,7 @@ set this option to a non-nil value in your init file. */);
defsubr (&Sraise_frame);
defsubr (&Slower_frame);
defsubr (&Sx_focus_frame);
+ defsubr (&Scan_run_window_configuration_change_hook);
defsubr (&Sredirect_frame_focus);
defsubr (&Sframe_focus);
defsubr (&Sframe_parameters);
@@ -4803,9 +5150,11 @@ set this option to a non-nil value in your init file. */);
defsubr (&Sframe_text_cols);
defsubr (&Sframe_text_lines);
defsubr (&Sframe_total_cols);
+ defsubr (&Sframe_total_lines);
defsubr (&Sframe_text_width);
defsubr (&Sframe_text_height);
defsubr (&Sscroll_bar_width);
+ defsubr (&Sscroll_bar_height);
defsubr (&Sfringe_width);
defsubr (&Sborder_width);
defsubr (&Sright_divider_width);
diff --git a/src/frame.h b/src/frame.h
index 3d3982f4104..cb0044cfe23 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,106 @@ 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 means x_set_window_size requests can be processed for this
+ frame. */
+ bool_bf can_x_set_window_size : 1;
+
+ /* True means run_window_configuration_change_hook can be processed
+ for this frame. */
+ bool_bf can_run_window_configuration_change_hook : 1;
+
+ /* True means tool bar has been redisplayed at least once in current
+ session. */
+ bool_bf tool_bar_redisplayed_once : 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 +364,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 +388,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 +415,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 +437,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 +456,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 +484,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 +598,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 +739,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 +755,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 +775,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 +804,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 +851,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 +863,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)
-#define FRAME_SCROLL_BAR_AREA_WIDTH(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
- ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
+/* 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)
+
+/* 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 +973,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 +990,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 +1066,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;
@@ -975,13 +1099,9 @@ SET_FRAME_VISIBLE (struct frame *f, int v)
(f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i))
extern Lisp_Object selected_frame;
-extern Lisp_Object Qframep, Qframe_live_p;
-extern Lisp_Object Qtty, Qtty_type;
-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 int frame_default_tool_bar_height;
+
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 +1112,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, Lisp_Object);
+extern void adjust_frame_size (struct frame *, int, int, int, bool, Lisp_Object);
extern Lisp_Object Vframe_list;
@@ -1018,12 +1142,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 +1158,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 +1200,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 +1208,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 +1217,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 +1226,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 +1239,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 +1249,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 +1280,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 +1304,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 +1318,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
@@ -1212,78 +1345,25 @@ extern Lisp_Object Vframe_list;
Frame Parameters
***********************************************************************/
-extern Lisp_Object Qauto_raise, Qauto_lower;
-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;
-extern Lisp_Object Qtooltip;
-extern Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position;
-extern Lisp_Object Qmouse_color;
-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_foreground, Qscroll_bar_background;
-extern Lisp_Object Qscreen_gamma;
-extern Lisp_Object Qline_spacing;
-extern Lisp_Object Qwait_for_wm;
-extern Lisp_Object Qfullscreen;
-extern Lisp_Object Qfullwidth, Qfullheight, Qfullboth, Qmaximized;
-extern Lisp_Object Qsticky;
-extern Lisp_Object Qfont_backend;
-extern Lisp_Object Qalpha;
-
-extern Lisp_Object Qleft_fringe, Qright_fringe;
-extern Lisp_Object Qheight, Qwidth;
-extern Lisp_Object Qminibuffer, Qmodeline;
-extern Lisp_Object Qx, Qw32, Qpc, Qns;
-extern Lisp_Object Qvisible;
-extern Lisp_Object Qdisplay_type;
-
-extern Lisp_Object Qx_resource_name;
-
-extern Lisp_Object Qleft, Qright, Qtop, Qbox, Qbottom;
-extern Lisp_Object Qdisplay;
-
-extern Lisp_Object Qrun_hook_with_args;
-
#ifdef HAVE_WINDOW_SYSTEM
/* 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 +1372,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);
@@ -1310,17 +1390,14 @@ extern Lisp_Object display_x_get_resource (Display_Info *,
Lisp_Object subclass);
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,
+extern void x_set_window_size (struct frame *f, bool change_gravity,
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 *);
@@ -1340,7 +1417,7 @@ extern void x_focus_frame (struct frame *);
#ifndef HAVE_NS
-extern int x_bitmap_icon (struct frame *, Lisp_Object);
+extern bool x_bitmap_icon (struct frame *, Lisp_Object);
/* Set F's bitmap icon, if specified among F's parameters. */
@@ -1354,7 +1431,6 @@ x_set_bitmap_icon (struct frame *f)
}
#endif /* !HAVE_NS */
-
#endif /* HAVE_WINDOW_SYSTEM */
INLINE void
@@ -1390,4 +1466,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 5561a596a99..5e5ec60a48f 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -65,10 +65,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
must specify physical bitmap symbols.
*/
-static Lisp_Object Qtruncation, Qcontinuation, Qoverlay_arrow;
-static Lisp_Object Qempty_line, Qtop_bottom;
-static Lisp_Object Qhollow_small;
-
enum fringe_bitmap_align
{
ALIGN_BITMAP_CENTER = 0,
@@ -474,15 +470,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;
@@ -594,7 +587,7 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o
if (face_id == DEFAULT_FACE_ID)
{
Lisp_Object face = fringe_faces[which];
- face_id = NILP (face) ? lookup_named_face (f, Qfringe, 0)
+ face_id = NILP (face) ? lookup_named_face (f, Qfringe, false)
: lookup_derived_face (f, face, FRINGE_FACE_ID, 0);
if (face_id < 0)
face_id = FRINGE_FACE_ID;
@@ -637,7 +630,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 +1325,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 +1475,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;
@@ -1828,15 +1723,12 @@ init_fringe_once (void)
void
init_fringe (void)
{
- int i;
-
max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
fringe_bitmaps = xzalloc (max_fringe_bitmaps * sizeof *fringe_bitmaps);
- fringe_faces = xmalloc (max_fringe_bitmaps * sizeof *fringe_faces);
- for (i = 0; i < max_fringe_bitmaps; i++)
- fringe_faces[i] = Qnil;
+ verify (NIL_IS_ZERO);
+ fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
}
#ifdef HAVE_NTGUI
diff --git a/src/ftfont.c b/src/ftfont.c
index 20482be8189..adf188815de 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"
@@ -36,12 +38,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "font.h"
#include "ftfont.h"
-/* Symbolic type of this font-driver. */
-static Lisp_Object Qfreetype;
-
-/* Fontconfig's generic families and their aliases. */
-static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
-
/* Flag to tell if FcInit is already called or not. */
static bool fc_initialized;
@@ -87,8 +83,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 +136,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 +173,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)
@@ -383,13 +375,7 @@ ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
if (NILP (cache))
{
if (NILP (ft_face_cache))
- {
- Lisp_Object args[2];
-
- args[0] = QCtest;
- args[1] = Qequal;
- ft_face_cache = Fmake_hash_table (2, args);
- }
+ ft_face_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
cache_data = xmalloc (sizeof *cache_data);
cache_data->ft_face = NULL;
cache_data->fc_charset = NULL;
@@ -501,8 +487,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 +526,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 +561,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 +578,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 +792,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 +1173,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 +1210,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 +1361,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 +1381,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 +1678,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 +1689,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 +1791,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 +1807,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 +1843,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 +1935,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 +1950,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 +2075,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 +2098,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 +2140,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 +2156,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 +2192,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 +2246,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 +2261,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 +2374,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);
@@ -2570,13 +2570,10 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
Lisp_Object
ftfont_shape (Lisp_Object lgstring)
{
- struct font *font;
- struct ftfont_info *ftfont_info;
- OTF *otf;
+ struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
+ struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
+ OTF *otf = ftfont_get_otf (ftfont_info);
- CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
- ftfont_info = (struct ftfont_info *) font;
- otf = ftfont_get_otf (ftfont_info);
if (! otf)
return make_number (0);
return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
@@ -2601,46 +2598,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",
@@ -2695,7 +2652,10 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
void
syms_of_ftfont (void)
{
+ /* Symbolic type of this font-driver. */
DEFSYM (Qfreetype, "freetype");
+
+ /* Fontconfig's generic families and their aliases. */
DEFSYM (Qmonospace, "monospace");
DEFSYM (Qsans_serif, "sans-serif");
DEFSYM (Qserif, "serif");
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 f5cab083fcf..cd2bf3e7415 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -35,11 +35,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* FTX font driver. */
-static Lisp_Object Qftx;
-
-#if defined HAVE_XFT || !defined HAVE_FREETYPE
-static
-#endif
struct font_driver ftxfont_driver;
struct ftxfont_frame_data
@@ -62,7 +57,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 +76,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 +113,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 +269,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 +321,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
}
unblock_input ();
+ SAFE_FREE ();
return len;
}
@@ -340,7 +329,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 +339,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/gfilenotify.c b/src/gfilenotify.c
index 7434a373476..e03bec93541 100644
--- a/src/gfilenotify.c
+++ b/src/gfilenotify.c
@@ -29,24 +29,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "process.h"
-/* Subroutines. */
-static Lisp_Object Qgfile_add_watch;
-static Lisp_Object Qgfile_rm_watch;
-
-/* Filter objects. */
-static Lisp_Object Qwatch_mounts; /* G_FILE_MONITOR_WATCH_MOUNTS */
-static Lisp_Object Qsend_moved; /* G_FILE_MONITOR_SEND_MOVED */
-
-/* Event types. */
-static Lisp_Object Qchanged; /* G_FILE_MONITOR_EVENT_CHANGED */
-static Lisp_Object Qchanges_done_hint; /* G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT */
-static Lisp_Object Qdeleted; /* G_FILE_MONITOR_EVENT_DELETED */
-static Lisp_Object Qcreated; /* G_FILE_MONITOR_EVENT_CREATED */
-static Lisp_Object Qattribute_changed; /* G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED */
-static Lisp_Object Qpre_unmount; /* G_FILE_MONITOR_EVENT_PRE_UNMOUNT */
-static Lisp_Object Qunmounted; /* G_FILE_MONITOR_EVENT_UNMOUNTED */
-static Lisp_Object Qmoved; /* G_FILE_MONITOR_EVENT_MOVED */
-
static Lisp_Object watch_list;
/* This is the callback function for arriving signals from
@@ -95,7 +77,7 @@ dir_monitor_callback (GFileMonitor *monitor,
}
/* Determine callback function. */
- monitor_object = XIL ((intptr_t) monitor);
+ monitor_object = make_pointer_integer (monitor);
eassert (INTEGERP (monitor_object));
watch_object = assq_no_quit (monitor_object, watch_list);
@@ -164,7 +146,7 @@ FILE is the name of the file whose event is being reported. FILE1
will be reported only in case of the 'moved' event. */)
(Lisp_Object file, Lisp_Object flags, Lisp_Object callback)
{
- Lisp_Object watch_descriptor, watch_object;
+ Lisp_Object watch_object;
GFile *gfile;
GFileMonitor *monitor;
GFileMonitorFlags gflags = G_FILE_MONITOR_NONE;
@@ -194,10 +176,9 @@ will be reported only in case of the 'moved' event. */)
if (! monitor)
xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file);
- /* On all known glib platforms, converting MONITOR directly to a
- Lisp_Object value results is a Lisp integer, which is safe. This
- assumption is dicey, though, so check it now. */
- watch_descriptor = XIL ((intptr_t) monitor);
+ Lisp_Object watch_descriptor = make_pointer_integer (monitor);
+
+ /* Check the dicey assumption that make_pointer_integer is safe. */
if (! INTEGERP (watch_descriptor))
{
g_object_unref (monitor);
@@ -221,8 +202,6 @@ DEFUN ("gfile-rm-watch", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0,
WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */)
(Lisp_Object watch_descriptor)
{
- intptr_t int_monitor;
- GFileMonitor *monitor;
Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list);
if (! CONSP (watch_object))
@@ -230,8 +209,7 @@ WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */)
watch_descriptor);
eassert (INTEGERP (watch_descriptor));
- int_monitor = XLI (watch_descriptor);
- monitor = (GFileMonitor *) int_monitor;
+ GFileMonitor *monitor = XINTPTR (watch_descriptor);
if (!g_file_monitor_cancel (monitor))
xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"),
watch_descriptor);
@@ -258,23 +236,27 @@ globals_of_gfilenotify (void)
void
syms_of_gfilenotify (void)
{
-
DEFSYM (Qgfile_add_watch, "gfile-add-watch");
defsubr (&Sgfile_add_watch);
DEFSYM (Qgfile_rm_watch, "gfile-rm-watch");
defsubr (&Sgfile_rm_watch);
- DEFSYM (Qwatch_mounts, "watch-mounts");
- DEFSYM (Qsend_moved, "send-moved");
- DEFSYM (Qchanged, "changed");
+ /* Filter objects. */
+ DEFSYM (Qwatch_mounts, "watch-mounts"); /* G_FILE_MONITOR_WATCH_MOUNTS */
+ DEFSYM (Qsend_moved, "send-moved"); /* G_FILE_MONITOR_SEND_MOVED */
+
+ /* Event types. */
+ DEFSYM (Qchanged, "changed"); /* G_FILE_MONITOR_EVENT_CHANGED */
DEFSYM (Qchanges_done_hint, "changes-done-hint");
- DEFSYM (Qdeleted, "deleted");
- DEFSYM (Qcreated, "created");
+ /* G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT */
+ DEFSYM (Qdeleted, "deleted"); /* G_FILE_MONITOR_EVENT_DELETED */
+ DEFSYM (Qcreated, "created"); /* G_FILE_MONITOR_EVENT_CREATED */
DEFSYM (Qattribute_changed, "attribute-changed");
- DEFSYM (Qpre_unmount, "pre-unmount");
- DEFSYM (Qunmounted, "unmounted");
- DEFSYM (Qmoved, "moved");
+ /* G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED */
+ DEFSYM (Qpre_unmount, "pre-unmount"); /* G_FILE_MONITOR_EVENT_PRE_UNMOUNT */
+ DEFSYM (Qunmounted, "unmounted"); /* G_FILE_MONITOR_EVENT_UNMOUNTED */
+ DEFSYM (Qmoved, "moved"); /* G_FILE_MONITOR_EVENT_MOVED */
staticpro (&watch_list);
diff --git a/src/gmalloc.c b/src/gmalloc.c
index cfd39be2bb3..a88f4ab75e0 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 d363fea2599..35f0eb48bc1 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -18,9 +18,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <errno.h>
+#include <stdio.h>
#include "lisp.h"
#include "process.h"
+#include "gnutls.h"
#include "coding.h"
#ifdef HAVE_GNUTLS
@@ -33,115 +35,148 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
static bool emacs_gnutls_handle_error (gnutls_session_t, int);
-static Lisp_Object Qgnutls_dll;
-static Lisp_Object Qgnutls_code;
-static Lisp_Object Qgnutls_anon, Qgnutls_x509pki;
-static Lisp_Object Qgnutls_e_interrupted, Qgnutls_e_again,
- Qgnutls_e_invalid_session, Qgnutls_e_not_ready_for_handshake;
static bool gnutls_global_initialized;
-/* The following are for the property list of `gnutls-boot'. */
-static Lisp_Object QCgnutls_bootprop_priority;
-static Lisp_Object QCgnutls_bootprop_trustfiles;
-static Lisp_Object QCgnutls_bootprop_keylist;
-static Lisp_Object QCgnutls_bootprop_crlfiles;
-static Lisp_Object QCgnutls_bootprop_callbacks;
-static Lisp_Object QCgnutls_bootprop_loglevel;
-static Lisp_Object QCgnutls_bootprop_hostname;
-static Lisp_Object QCgnutls_bootprop_min_prime_bits;
-static Lisp_Object QCgnutls_bootprop_verify_flags;
-static Lisp_Object QCgnutls_bootprop_verify_error;
-
-/* Callback keys for `gnutls-boot'. Unused currently. */
-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
+enum extra_peer_verification
+{
+ CERTIFICATE_NOT_MATCHING = 2
+};
+
#ifdef WINDOWSNT
-/* Macro for defining functions that will be loaded from the GnuTLS DLL. */
-#define DEF_GNUTLS_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
-
-/* Macro for loading GnuTLS functions from the library. */
-#define LOAD_GNUTLS_FN(lib,func) { \
- fn_##func = (void *) GetProcAddress (lib, #func); \
- if (!fn_##func) return 0; \
- }
+DEF_DLL_FN (gnutls_alert_description_t, gnutls_alert_get,
+ (gnutls_session_t));
+DEF_DLL_FN (const char *, gnutls_alert_get_name,
+ (gnutls_alert_description_t));
+DEF_DLL_FN (int, gnutls_alert_send_appropriate, (gnutls_session_t, int));
+DEF_DLL_FN (int, gnutls_anon_allocate_client_credentials,
+ (gnutls_anon_client_credentials_t *));
+DEF_DLL_FN (void, gnutls_anon_free_client_credentials,
+ (gnutls_anon_client_credentials_t));
+DEF_DLL_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
+DEF_DLL_FN (int, gnutls_certificate_allocate_credentials,
+ (gnutls_certificate_credentials_t *));
+DEF_DLL_FN (void, gnutls_certificate_free_credentials,
+ (gnutls_certificate_credentials_t));
+DEF_DLL_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
+ (gnutls_session_t, unsigned int *));
+DEF_DLL_FN (void, gnutls_certificate_set_verify_flags,
+ (gnutls_certificate_credentials_t, unsigned int));
+DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
+ (gnutls_certificate_credentials_t, const char *,
+ gnutls_x509_crt_fmt_t));
+DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
+ (gnutls_certificate_credentials_t, const char *, const char *,
+ gnutls_x509_crt_fmt_t));
+# if ((GNUTLS_VERSION_MAJOR \
+ + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
+ > 3)
+DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
+ (gnutls_certificate_credentials_t));
+# endif
+DEF_DLL_FN (int, gnutls_certificate_set_x509_trust_file,
+ (gnutls_certificate_credentials_t, const char *,
+ gnutls_x509_crt_fmt_t));
+DEF_DLL_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
+ (gnutls_session_t));
+DEF_DLL_FN (int, gnutls_certificate_verify_peers2,
+ (gnutls_session_t, unsigned int *));
+DEF_DLL_FN (int, gnutls_credentials_set,
+ (gnutls_session_t, gnutls_credentials_type_t, void *));
+DEF_DLL_FN (void, gnutls_deinit, (gnutls_session_t));
+DEF_DLL_FN (void, gnutls_dh_set_prime_bits,
+ (gnutls_session_t, unsigned int));
+DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
+DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
+DEF_DLL_FN (int, gnutls_global_init, (void));
+DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
+# ifdef HAVE_GNUTLS3
+DEF_DLL_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
+# endif
+DEF_DLL_FN (void, gnutls_global_set_log_level, (int));
+DEF_DLL_FN (int, gnutls_handshake, (gnutls_session_t));
+DEF_DLL_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
+DEF_DLL_FN (int, gnutls_priority_set_direct,
+ (gnutls_session_t, const char *, const char **));
+DEF_DLL_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
+DEF_DLL_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
+DEF_DLL_FN (ssize_t, gnutls_record_send,
+ (gnutls_session_t, const void *, size_t));
+DEF_DLL_FN (const char *, gnutls_strerror, (int));
+DEF_DLL_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
+DEF_DLL_FN (const char *, gnutls_check_version, (const char *));
+DEF_DLL_FN (void, gnutls_transport_set_lowat, (gnutls_session_t, int));
+DEF_DLL_FN (void, gnutls_transport_set_ptr2,
+ (gnutls_session_t, gnutls_transport_ptr_t,
+ gnutls_transport_ptr_t));
+DEF_DLL_FN (void, gnutls_transport_set_pull_function,
+ (gnutls_session_t, gnutls_pull_func));
+DEF_DLL_FN (void, gnutls_transport_set_push_function,
+ (gnutls_session_t, gnutls_push_func));
+DEF_DLL_FN (int, gnutls_x509_crt_check_hostname,
+ (gnutls_x509_crt_t, const char *));
+DEF_DLL_FN (int, gnutls_x509_crt_check_issuer,
+ (gnutls_x509_crt_t, gnutls_x509_crt_t));
+DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
+DEF_DLL_FN (int, gnutls_x509_crt_import,
+ (gnutls_x509_crt_t, const gnutls_datum_t *,
+ gnutls_x509_crt_fmt_t));
+DEF_DLL_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_fingerprint,
+ (gnutls_x509_crt_t,
+ gnutls_digest_algorithm_t, void *, size_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_version,
+ (gnutls_x509_crt_t));
+DEF_DLL_FN (int, gnutls_x509_crt_get_serial,
+ (gnutls_x509_crt_t, void *, size_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_dn,
+ (gnutls_x509_crt_t, char *, size_t *));
+DEF_DLL_FN (time_t, gnutls_x509_crt_get_activation_time,
+ (gnutls_x509_crt_t));
+DEF_DLL_FN (time_t, gnutls_x509_crt_get_expiration_time,
+ (gnutls_x509_crt_t));
+DEF_DLL_FN (int, gnutls_x509_crt_get_dn,
+ (gnutls_x509_crt_t, char *, size_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm,
+ (gnutls_x509_crt_t, unsigned int *));
+DEF_DLL_FN (const char*, gnutls_pk_algorithm_get_name,
+ (gnutls_pk_algorithm_t));
+DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param,
+ (gnutls_pk_algorithm_t, unsigned int));
+DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_unique_id,
+ (gnutls_x509_crt_t, char *, size_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_subject_unique_id,
+ (gnutls_x509_crt_t, char *, size_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_signature_algorithm,
+ (gnutls_x509_crt_t));
+DEF_DLL_FN (int, gnutls_x509_crt_get_signature,
+ (gnutls_x509_crt_t, char *, size_t *));
+DEF_DLL_FN (int, gnutls_x509_crt_get_key_id,
+ (gnutls_x509_crt_t, unsigned int, unsigned char *, size_t *_size));
+DEF_DLL_FN (const char*, gnutls_sec_param_get_name, (gnutls_sec_param_t));
+DEF_DLL_FN (const char*, gnutls_sign_get_name, (gnutls_sign_algorithm_t));
+DEF_DLL_FN (int, gnutls_server_name_set,
+ (gnutls_session_t, gnutls_server_name_type_t,
+ const void *, size_t));
+DEF_DLL_FN (gnutls_kx_algorithm_t, gnutls_kx_get, (gnutls_session_t));
+DEF_DLL_FN (const char*, gnutls_kx_get_name, (gnutls_kx_algorithm_t));
+DEF_DLL_FN (gnutls_protocol_t, gnutls_protocol_get_version,
+ (gnutls_session_t));
+DEF_DLL_FN (const char*, gnutls_protocol_get_name, (gnutls_protocol_t));
+DEF_DLL_FN (gnutls_cipher_algorithm_t, gnutls_cipher_get,
+ (gnutls_session_t));
+DEF_DLL_FN (const char*, gnutls_cipher_get_name,
+ (gnutls_cipher_algorithm_t));
+DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
+DEF_DLL_FN (const char*, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
-DEF_GNUTLS_FN (gnutls_alert_description_t, gnutls_alert_get,
- (gnutls_session_t));
-DEF_GNUTLS_FN (const char *, gnutls_alert_get_name,
- (gnutls_alert_description_t));
-DEF_GNUTLS_FN (int, gnutls_alert_send_appropriate, (gnutls_session_t, int));
-DEF_GNUTLS_FN (int, gnutls_anon_allocate_client_credentials,
- (gnutls_anon_client_credentials_t *));
-DEF_GNUTLS_FN (void, gnutls_anon_free_client_credentials,
- (gnutls_anon_client_credentials_t));
-DEF_GNUTLS_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
-DEF_GNUTLS_FN (int, gnutls_certificate_allocate_credentials,
- (gnutls_certificate_credentials_t *));
-DEF_GNUTLS_FN (void, gnutls_certificate_free_credentials,
- (gnutls_certificate_credentials_t));
-DEF_GNUTLS_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
- (gnutls_session_t, unsigned int *));
-DEF_GNUTLS_FN (void, gnutls_certificate_set_verify_flags,
- (gnutls_certificate_credentials_t, unsigned int));
-DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_crl_file,
- (gnutls_certificate_credentials_t, const char *,
- gnutls_x509_crt_fmt_t));
-DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_key_file,
- (gnutls_certificate_credentials_t, const char *, const char *,
- gnutls_x509_crt_fmt_t));
-DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_trust_file,
- (gnutls_certificate_credentials_t, const char *,
- gnutls_x509_crt_fmt_t));
-DEF_GNUTLS_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
- (gnutls_session_t));
-DEF_GNUTLS_FN (int, gnutls_certificate_verify_peers2,
- (gnutls_session_t, unsigned int *));
-DEF_GNUTLS_FN (int, gnutls_credentials_set,
- (gnutls_session_t, gnutls_credentials_type_t, void *));
-DEF_GNUTLS_FN (void, gnutls_deinit, (gnutls_session_t));
-DEF_GNUTLS_FN (void, gnutls_dh_set_prime_bits,
- (gnutls_session_t, unsigned int));
-DEF_GNUTLS_FN (int, gnutls_error_is_fatal, (int));
-DEF_GNUTLS_FN (int, gnutls_global_init, (void));
-DEF_GNUTLS_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
-#ifdef HAVE_GNUTLS3
-DEF_GNUTLS_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
-#endif
-DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int));
-DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t));
-DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
-DEF_GNUTLS_FN (int, gnutls_priority_set_direct,
- (gnutls_session_t, const char *, const char **));
-DEF_GNUTLS_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
-DEF_GNUTLS_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
-DEF_GNUTLS_FN (ssize_t, gnutls_record_send,
- (gnutls_session_t, const void *, size_t));
-DEF_GNUTLS_FN (const char *, gnutls_strerror, (int));
-DEF_GNUTLS_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
-DEF_GNUTLS_FN (const char *, gnutls_check_version, (const char *));
-DEF_GNUTLS_FN (void, gnutls_transport_set_lowat, (gnutls_session_t, int));
-DEF_GNUTLS_FN (void, gnutls_transport_set_ptr2,
- (gnutls_session_t, gnutls_transport_ptr_t,
- gnutls_transport_ptr_t));
-DEF_GNUTLS_FN (void, gnutls_transport_set_pull_function,
- (gnutls_session_t, gnutls_pull_func));
-DEF_GNUTLS_FN (void, gnutls_transport_set_push_function,
- (gnutls_session_t, gnutls_push_func));
-DEF_GNUTLS_FN (int, gnutls_x509_crt_check_hostname,
- (gnutls_x509_crt_t, const char *));
-DEF_GNUTLS_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
-DEF_GNUTLS_FN (int, gnutls_x509_crt_import,
- (gnutls_x509_crt_t, const gnutls_datum_t *,
- gnutls_x509_crt_fmt_t));
-DEF_GNUTLS_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
static bool
init_gnutls_functions (void)
@@ -155,51 +190,84 @@ init_gnutls_functions (void)
return 0;
}
- LOAD_GNUTLS_FN (library, gnutls_alert_get);
- LOAD_GNUTLS_FN (library, gnutls_alert_get_name);
- LOAD_GNUTLS_FN (library, gnutls_alert_send_appropriate);
- LOAD_GNUTLS_FN (library, gnutls_anon_allocate_client_credentials);
- LOAD_GNUTLS_FN (library, gnutls_anon_free_client_credentials);
- LOAD_GNUTLS_FN (library, gnutls_bye);
- LOAD_GNUTLS_FN (library, gnutls_certificate_allocate_credentials);
- LOAD_GNUTLS_FN (library, gnutls_certificate_free_credentials);
- LOAD_GNUTLS_FN (library, gnutls_certificate_get_peers);
- LOAD_GNUTLS_FN (library, gnutls_certificate_set_verify_flags);
- LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_crl_file);
- LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_key_file);
- LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_trust_file);
- LOAD_GNUTLS_FN (library, gnutls_certificate_type_get);
- LOAD_GNUTLS_FN (library, gnutls_certificate_verify_peers2);
- LOAD_GNUTLS_FN (library, gnutls_credentials_set);
- LOAD_GNUTLS_FN (library, gnutls_deinit);
- LOAD_GNUTLS_FN (library, gnutls_dh_set_prime_bits);
- LOAD_GNUTLS_FN (library, gnutls_error_is_fatal);
- LOAD_GNUTLS_FN (library, gnutls_global_init);
- LOAD_GNUTLS_FN (library, gnutls_global_set_log_function);
-#ifdef HAVE_GNUTLS3
- LOAD_GNUTLS_FN (library, gnutls_global_set_audit_log_function);
-#endif
- LOAD_GNUTLS_FN (library, gnutls_global_set_log_level);
- LOAD_GNUTLS_FN (library, gnutls_handshake);
- LOAD_GNUTLS_FN (library, gnutls_init);
- LOAD_GNUTLS_FN (library, gnutls_priority_set_direct);
- LOAD_GNUTLS_FN (library, gnutls_record_check_pending);
- LOAD_GNUTLS_FN (library, gnutls_record_recv);
- LOAD_GNUTLS_FN (library, gnutls_record_send);
- LOAD_GNUTLS_FN (library, gnutls_strerror);
- LOAD_GNUTLS_FN (library, gnutls_transport_set_errno);
- LOAD_GNUTLS_FN (library, gnutls_check_version);
+ LOAD_DLL_FN (library, gnutls_alert_get);
+ LOAD_DLL_FN (library, gnutls_alert_get_name);
+ LOAD_DLL_FN (library, gnutls_alert_send_appropriate);
+ LOAD_DLL_FN (library, gnutls_anon_allocate_client_credentials);
+ LOAD_DLL_FN (library, gnutls_anon_free_client_credentials);
+ LOAD_DLL_FN (library, gnutls_bye);
+ LOAD_DLL_FN (library, gnutls_certificate_allocate_credentials);
+ LOAD_DLL_FN (library, gnutls_certificate_free_credentials);
+ LOAD_DLL_FN (library, gnutls_certificate_get_peers);
+ LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
+ LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
+ LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
+# if ((GNUTLS_VERSION_MAJOR \
+ + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
+ > 3)
+ LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
+# endif
+ LOAD_DLL_FN (library, gnutls_certificate_set_x509_trust_file);
+ LOAD_DLL_FN (library, gnutls_certificate_type_get);
+ LOAD_DLL_FN (library, gnutls_certificate_verify_peers2);
+ LOAD_DLL_FN (library, gnutls_credentials_set);
+ LOAD_DLL_FN (library, gnutls_deinit);
+ LOAD_DLL_FN (library, gnutls_dh_set_prime_bits);
+ LOAD_DLL_FN (library, gnutls_dh_get_prime_bits);
+ LOAD_DLL_FN (library, gnutls_error_is_fatal);
+ LOAD_DLL_FN (library, gnutls_global_init);
+ LOAD_DLL_FN (library, gnutls_global_set_log_function);
+# ifdef HAVE_GNUTLS3
+ LOAD_DLL_FN (library, gnutls_global_set_audit_log_function);
+# endif
+ LOAD_DLL_FN (library, gnutls_global_set_log_level);
+ LOAD_DLL_FN (library, gnutls_handshake);
+ LOAD_DLL_FN (library, gnutls_init);
+ LOAD_DLL_FN (library, gnutls_priority_set_direct);
+ LOAD_DLL_FN (library, gnutls_record_check_pending);
+ LOAD_DLL_FN (library, gnutls_record_recv);
+ LOAD_DLL_FN (library, gnutls_record_send);
+ LOAD_DLL_FN (library, gnutls_strerror);
+ LOAD_DLL_FN (library, gnutls_transport_set_errno);
+ LOAD_DLL_FN (library, gnutls_check_version);
/* We don't need to call gnutls_transport_set_lowat in GnuTLS 2.11.1
and later, and the function was removed entirely in 3.0.0. */
if (!fn_gnutls_check_version ("2.11.1"))
- LOAD_GNUTLS_FN (library, gnutls_transport_set_lowat);
- LOAD_GNUTLS_FN (library, gnutls_transport_set_ptr2);
- LOAD_GNUTLS_FN (library, gnutls_transport_set_pull_function);
- LOAD_GNUTLS_FN (library, gnutls_transport_set_push_function);
- LOAD_GNUTLS_FN (library, gnutls_x509_crt_check_hostname);
- LOAD_GNUTLS_FN (library, gnutls_x509_crt_deinit);
- LOAD_GNUTLS_FN (library, gnutls_x509_crt_import);
- LOAD_GNUTLS_FN (library, gnutls_x509_crt_init);
+ LOAD_DLL_FN (library, gnutls_transport_set_lowat);
+ LOAD_DLL_FN (library, gnutls_transport_set_ptr2);
+ LOAD_DLL_FN (library, gnutls_transport_set_pull_function);
+ LOAD_DLL_FN (library, gnutls_transport_set_push_function);
+ LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname);
+ LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer);
+ LOAD_DLL_FN (library, gnutls_x509_crt_deinit);
+ LOAD_DLL_FN (library, gnutls_x509_crt_import);
+ LOAD_DLL_FN (library, gnutls_x509_crt_init);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_version);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_serial);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_dn);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_activation_time);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_dn);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm);
+ LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name);
+ LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_subject_unique_id);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_signature_algorithm);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_signature);
+ LOAD_DLL_FN (library, gnutls_x509_crt_get_key_id);
+ LOAD_DLL_FN (library, gnutls_sec_param_get_name);
+ LOAD_DLL_FN (library, gnutls_sign_get_name);
+ LOAD_DLL_FN (library, gnutls_server_name_set);
+ LOAD_DLL_FN (library, gnutls_kx_get);
+ LOAD_DLL_FN (library, gnutls_kx_get_name);
+ LOAD_DLL_FN (library, gnutls_protocol_get_version);
+ LOAD_DLL_FN (library, gnutls_protocol_get_name);
+ LOAD_DLL_FN (library, gnutls_cipher_get);
+ LOAD_DLL_FN (library, gnutls_cipher_get_name);
+ LOAD_DLL_FN (library, gnutls_mac_get);
+ LOAD_DLL_FN (library, gnutls_mac_get_name);
max_log_level = global_gnutls_log_level;
@@ -212,50 +280,77 @@ init_gnutls_functions (void)
return 1;
}
-#else /* !WINDOWSNT */
-
-#define fn_gnutls_alert_get gnutls_alert_get
-#define fn_gnutls_alert_get_name gnutls_alert_get_name
-#define fn_gnutls_alert_send_appropriate gnutls_alert_send_appropriate
-#define fn_gnutls_anon_allocate_client_credentials gnutls_anon_allocate_client_credentials
-#define fn_gnutls_anon_free_client_credentials gnutls_anon_free_client_credentials
-#define fn_gnutls_bye gnutls_bye
-#define fn_gnutls_certificate_allocate_credentials gnutls_certificate_allocate_credentials
-#define fn_gnutls_certificate_free_credentials gnutls_certificate_free_credentials
-#define fn_gnutls_certificate_get_peers gnutls_certificate_get_peers
-#define fn_gnutls_certificate_set_verify_flags gnutls_certificate_set_verify_flags
-#define fn_gnutls_certificate_set_x509_crl_file gnutls_certificate_set_x509_crl_file
-#define fn_gnutls_certificate_set_x509_key_file gnutls_certificate_set_x509_key_file
-#define fn_gnutls_certificate_set_x509_trust_file gnutls_certificate_set_x509_trust_file
-#define fn_gnutls_certificate_type_get gnutls_certificate_type_get
-#define fn_gnutls_certificate_verify_peers2 gnutls_certificate_verify_peers2
-#define fn_gnutls_credentials_set gnutls_credentials_set
-#define fn_gnutls_deinit gnutls_deinit
-#define fn_gnutls_dh_set_prime_bits gnutls_dh_set_prime_bits
-#define fn_gnutls_error_is_fatal gnutls_error_is_fatal
-#define fn_gnutls_global_init gnutls_global_init
-#define fn_gnutls_global_set_log_function gnutls_global_set_log_function
-#ifdef HAVE_GNUTLS3
-#define fn_gnutls_global_set_audit_log_function gnutls_global_set_audit_log_function
-#endif
-#define fn_gnutls_global_set_log_level gnutls_global_set_log_level
-#define fn_gnutls_handshake gnutls_handshake
-#define fn_gnutls_init gnutls_init
-#define fn_gnutls_priority_set_direct gnutls_priority_set_direct
-#define fn_gnutls_record_check_pending gnutls_record_check_pending
-#define fn_gnutls_record_recv gnutls_record_recv
-#define fn_gnutls_record_send gnutls_record_send
-#define fn_gnutls_strerror gnutls_strerror
-#ifdef WINDOWSNT
-#define fn_gnutls_transport_set_errno gnutls_transport_set_errno
-#endif
-#define fn_gnutls_transport_set_ptr2 gnutls_transport_set_ptr2
-#define fn_gnutls_x509_crt_check_hostname gnutls_x509_crt_check_hostname
-#define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit
-#define fn_gnutls_x509_crt_import gnutls_x509_crt_import
-#define fn_gnutls_x509_crt_init gnutls_x509_crt_init
+# define gnutls_alert_get fn_gnutls_alert_get
+# define gnutls_alert_get_name fn_gnutls_alert_get_name
+# define gnutls_alert_send_appropriate fn_gnutls_alert_send_appropriate
+# define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
+# define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
+# define gnutls_bye fn_gnutls_bye
+# define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
+# define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
+# define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
+# define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
+# define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
+# define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
+# define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
+# define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
+# define gnutls_certificate_type_get fn_gnutls_certificate_type_get
+# define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
+# define gnutls_check_version fn_gnutls_check_version
+# define gnutls_cipher_get fn_gnutls_cipher_get
+# define gnutls_cipher_get_name fn_gnutls_cipher_get_name
+# define gnutls_credentials_set fn_gnutls_credentials_set
+# define gnutls_deinit fn_gnutls_deinit
+# define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
+# define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
+# define gnutls_error_is_fatal fn_gnutls_error_is_fatal
+# define gnutls_global_init fn_gnutls_global_init
+# define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
+# define gnutls_global_set_log_function fn_gnutls_global_set_log_function
+# define gnutls_global_set_log_level fn_gnutls_global_set_log_level
+# define gnutls_handshake fn_gnutls_handshake
+# define gnutls_init fn_gnutls_init
+# define gnutls_kx_get fn_gnutls_kx_get
+# define gnutls_kx_get_name fn_gnutls_kx_get_name
+# define gnutls_mac_get fn_gnutls_mac_get
+# define gnutls_mac_get_name fn_gnutls_mac_get_name
+# define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
+# define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
+# define gnutls_priority_set_direct fn_gnutls_priority_set_direct
+# define gnutls_protocol_get_name fn_gnutls_protocol_get_name
+# define gnutls_protocol_get_version fn_gnutls_protocol_get_version
+# define gnutls_record_check_pending fn_gnutls_record_check_pending
+# define gnutls_record_recv fn_gnutls_record_recv
+# define gnutls_record_send fn_gnutls_record_send
+# define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
+# define gnutls_server_name_set fn_gnutls_server_name_set
+# define gnutls_sign_get_name fn_gnutls_sign_get_name
+# define gnutls_strerror fn_gnutls_strerror
+# define gnutls_transport_set_errno fn_gnutls_transport_set_errno
+# define gnutls_transport_set_lowat fn_gnutls_transport_set_lowat
+# define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
+# define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
+# define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
+# define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
+# define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
+# define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
+# define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
+# define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
+# define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
+# define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
+# define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
+# define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
+# define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
+# define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
+# define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
+# define gnutls_x509_crt_get_signature fn_gnutls_x509_crt_get_signature
+# define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
+# define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
+# define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
+# define gnutls_x509_crt_import fn_gnutls_x509_crt_import
+# define gnutls_x509_crt_init fn_gnutls_x509_crt_init
-#endif /* !WINDOWSNT */
+#endif
/* Report memory exhaustion if ERR is an out-of-memory indication. */
@@ -270,9 +365,9 @@ check_memory_full (int err)
}
#ifdef HAVE_GNUTLS3
-/* Function to log a simple audit message. */
+/* 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)
{
@@ -281,23 +376,23 @@ gnutls_audit_log_function (gnutls_session_t session, const char* string)
}
#endif
-/* Function to log a simple message. */
+/* 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. */
+/* 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. */
+/* 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);
}
@@ -317,11 +412,11 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
/* On W32 we cannot transfer socket handles between different runtime
libraries, so we tell GnuTLS to use our special push/pull
functions. */
- fn_gnutls_transport_set_ptr2 (state,
- (gnutls_transport_ptr_t) proc,
- (gnutls_transport_ptr_t) proc);
- fn_gnutls_transport_set_push_function (state, &emacs_gnutls_push);
- fn_gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
+ gnutls_transport_set_ptr2 (state,
+ (gnutls_transport_ptr_t) proc,
+ (gnutls_transport_ptr_t) proc);
+ gnutls_transport_set_push_function (state, &emacs_gnutls_push);
+ gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
/* For non blocking sockets or other custom made pull/push
functions the gnutls_transport_set_lowat must be called, with
@@ -334,15 +429,15 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
zero by default in version 2.11.1, and the function
gnutls_transport_set_lowat was removed from the library in
version 2.99.0. */
- if (!fn_gnutls_check_version ("2.11.1"))
- fn_gnutls_transport_set_lowat (state, 0);
+ if (!gnutls_check_version ("2.11.1"))
+ gnutls_transport_set_lowat (state, 0);
#else
/* This is how GnuTLS takes sockets: as file descriptors passed
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);
+ gnutls_transport_set_ptr2 (state,
+ (void *) (intptr_t) proc->infd,
+ (void *) (intptr_t) proc->outfd);
#endif
proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
@@ -350,11 +445,11 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
do
{
- ret = fn_gnutls_handshake (state);
+ ret = gnutls_handshake (state);
emacs_gnutls_handle_error (state, ret);
QUIT;
}
- while (ret < 0 && fn_gnutls_error_is_fatal (ret) == 0);
+ while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
@@ -365,7 +460,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
}
else
{
- check_memory_full (fn_gnutls_alert_send_appropriate (state, ret));
+ check_memory_full (gnutls_alert_send_appropriate (state, ret));
}
return ret;
}
@@ -373,14 +468,14 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
ptrdiff_t
emacs_gnutls_record_check_pending (gnutls_session_t state)
{
- return fn_gnutls_record_check_pending (state);
+ return gnutls_record_check_pending (state);
}
#ifdef WINDOWSNT
void
emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
{
- fn_gnutls_transport_set_errno (state, err);
+ gnutls_transport_set_errno (state, err);
}
#endif
@@ -401,7 +496,7 @@ emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
while (nbyte > 0)
{
- rtnval = fn_gnutls_record_send (state, buf, nbyte);
+ rtnval = gnutls_record_send (state, buf, nbyte);
if (rtnval < 0)
{
@@ -453,7 +548,7 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
proc->gnutls_handshakes_tried = 0;
return 0;
}
- rtnval = fn_gnutls_record_recv (state, buf, nbyte);
+ rtnval = gnutls_record_recv (state, buf, nbyte);
if (rtnval >= 0)
return rtnval;
else if (rtnval == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
@@ -488,14 +583,14 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
/* TODO: use gnutls-error-fatalp and gnutls-error-string. */
- str = fn_gnutls_strerror (err);
+ str = gnutls_strerror (err);
if (!str)
str = "unknown";
- if (fn_gnutls_error_is_fatal (err))
+ if (gnutls_error_is_fatal (err))
{
ret = 0;
- GNUTLS_LOG2 (0, max_log_level, "fatal error:", str);
+ GNUTLS_LOG2 (1, max_log_level, "fatal error:", str);
}
else
{
@@ -519,9 +614,9 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
|| err == GNUTLS_E_FATAL_ALERT_RECEIVED)
{
- int alert = fn_gnutls_alert_get (session);
+ int alert = gnutls_alert_get (session);
int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
- str = fn_gnutls_alert_get_name (alert);
+ str = gnutls_alert_get_name (alert);
if (!str)
str = "unknown";
@@ -568,20 +663,20 @@ emacs_gnutls_deinit (Lisp_Object proc)
if (XPROCESS (proc)->gnutls_x509_cred)
{
GNUTLS_LOG (2, log_level, "Deallocating x509 credentials");
- fn_gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
+ gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
XPROCESS (proc)->gnutls_x509_cred = NULL;
}
if (XPROCESS (proc)->gnutls_anon_cred)
{
GNUTLS_LOG (2, log_level, "Deallocating anon credentials");
- fn_gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
+ gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
XPROCESS (proc)->gnutls_anon_cred = NULL;
}
if (XPROCESS (proc)->gnutls_state)
{
- fn_gnutls_deinit (XPROCESS (proc)->gnutls_state);
+ gnutls_deinit (XPROCESS (proc)->gnutls_state);
XPROCESS (proc)->gnutls_state = NULL;
if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
@@ -604,7 +699,8 @@ See also `gnutls-boot'. */)
DEFUN ("gnutls-errorp", Fgnutls_errorp, Sgnutls_errorp, 1, 1, 0,
doc: /* Return t if ERROR indicates a GnuTLS problem.
ERROR is an integer or a symbol with an integer `gnutls-code' property.
-usage: (gnutls-errorp ERROR) */)
+usage: (gnutls-errorp ERROR) */
+ attributes: const)
(Lisp_Object err)
{
if (EQ (err, Qt)) return Qnil;
@@ -613,9 +709,9 @@ usage: (gnutls-errorp ERROR) */)
}
DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp, Sgnutls_error_fatalp, 1, 1, 0,
- doc: /* Check if ERROR is fatal.
+ doc: /* Return non-nil if ERROR is fatal.
ERROR is an integer or a symbol with an integer `gnutls-code' property.
-usage: (gnutls-error-fatalp ERROR) */)
+Usage: (gnutls-error-fatalp ERROR) */)
(Lisp_Object err)
{
Lisp_Object code;
@@ -638,7 +734,7 @@ usage: (gnutls-error-fatalp ERROR) */)
if (! TYPE_RANGED_INTEGERP (int, err))
error ("Not an error symbol or code");
- if (0 == fn_gnutls_error_is_fatal (XINT (err)))
+ if (0 == gnutls_error_is_fatal (XINT (err)))
return Qnil;
return Qt;
@@ -670,7 +766,7 @@ usage: (gnutls-error-string ERROR) */)
if (! TYPE_RANGED_INTEGERP (int, err))
return build_string ("Not an error symbol or code");
- return build_string (fn_gnutls_strerror (XINT (err)));
+ return build_string (gnutls_strerror (XINT (err)));
}
DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
@@ -681,25 +777,368 @@ See also `gnutls-init'. */)
return emacs_gnutls_deinit (proc);
}
-/* Initializes global GnuTLS state to defaults.
-Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
-Returns zero on success. */
+static Lisp_Object
+gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
+{
+ ptrdiff_t prefix_length = strlen (prefix);
+ if ((STRING_BYTES_BOUND - prefix_length) / 3 < buf_size)
+ string_overflow ();
+ Lisp_Object ret = make_uninit_string (prefix_length + 3 * buf_size
+ - (buf_size != 0));
+ char *string = SSDATA (ret);
+ strcpy (string, prefix);
+
+ for (ptrdiff_t i = 0; i < buf_size; i++)
+ sprintf (string + i * 3 + prefix_length,
+ i == buf_size - 1 ? "%02x" : "%02x:",
+ buf[i]);
+
+ return ret;
+}
+
+static Lisp_Object
+gnutls_certificate_details (gnutls_x509_crt_t cert)
+{
+ Lisp_Object res = Qnil;
+ int err;
+ size_t buf_size;
+
+ /* Version. */
+ {
+ int version = gnutls_x509_crt_get_version (cert);
+ check_memory_full (version);
+ if (version >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":version"),
+ make_number (version)));
+ }
+
+ /* Serial. */
+ buf_size = 0;
+ err = gnutls_x509_crt_get_serial (cert, NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ void *serial = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_serial (cert, serial, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":serial-number"),
+ gnutls_hex_string (serial, buf_size, "")));
+ xfree (serial);
+ }
+
+ /* Issuer. */
+ buf_size = 0;
+ err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ char *dn = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_issuer_dn (cert, dn, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":issuer"),
+ make_string (dn, buf_size)));
+ xfree (dn);
+ }
+
+ /* Validity. */
+ {
+ /* Add 1 to the buffer size, since 1900 is added to tm_year and
+ that might add 1 to the year length. */
+ char buf[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
+ struct tm t;
+ time_t tim = gnutls_x509_crt_get_activation_time (cert);
+
+ if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
+ res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf)));
+
+ tim = gnutls_x509_crt_get_expiration_time (cert);
+ if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
+ res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf)));
+ }
+
+ /* Subject. */
+ buf_size = 0;
+ err = gnutls_x509_crt_get_dn (cert, NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ char *dn = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_dn (cert, dn, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":subject"),
+ make_string (dn, buf_size)));
+ xfree (dn);
+ }
+
+ /* Versions older than 2.11 doesn't have these four functions. */
+#if GNUTLS_VERSION_NUMBER >= 0x020b00
+ /* SubjectPublicKeyInfo. */
+ {
+ unsigned int bits;
+
+ err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ {
+ const char *name = gnutls_pk_algorithm_get_name (err);
+ if (name)
+ res = nconc2 (res, list2 (intern (":public-key-algorithm"),
+ build_string (name)));
+
+ name = gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
+ (err, bits));
+ res = nconc2 (res, list2 (intern (":certificate-security-level"),
+ build_string (name)));
+ }
+ }
+
+ /* Unique IDs. */
+ buf_size = 0;
+ err = gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ char *buf = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":issuer-unique-id"),
+ make_string (buf, buf_size)));
+ xfree (buf);
+ }
+
+ buf_size = 0;
+ err = gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ char *buf = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":subject-unique-id"),
+ make_string (buf, buf_size)));
+ xfree (buf);
+ }
+#endif
+
+ /* Signature. */
+ err = gnutls_x509_crt_get_signature_algorithm (cert);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ {
+ const char *name = gnutls_sign_get_name (err);
+ if (name)
+ res = nconc2 (res, list2 (intern (":signature-algorithm"),
+ build_string (name)));
+ }
+
+ /* Public key ID. */
+ buf_size = 0;
+ err = gnutls_x509_crt_get_key_id (cert, 0, NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ void *buf = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_key_id (cert, 0, buf, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":public-key-id"),
+ gnutls_hex_string (buf, buf_size, "sha1:")));
+ xfree (buf);
+ }
+
+ /* Certificate fingerprint. */
+ buf_size = 0;
+ err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
+ NULL, &buf_size);
+ check_memory_full (err);
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ void *buf = xmalloc (buf_size);
+ err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
+ buf, &buf_size);
+ check_memory_full (err);
+ if (err >= GNUTLS_E_SUCCESS)
+ res = nconc2 (res, list2 (intern (":certificate-id"),
+ gnutls_hex_string (buf, buf_size, "sha1:")));
+ xfree (buf);
+ }
+
+ return res;
+}
+
+DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe, Sgnutls_peer_status_warning_describe, 1, 1, 0,
+ doc: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
+ (Lisp_Object status_symbol)
+{
+ CHECK_SYMBOL (status_symbol);
+
+ if (EQ (status_symbol, intern (":invalid")))
+ return build_string ("certificate could not be verified");
+
+ if (EQ (status_symbol, intern (":revoked")))
+ return build_string ("certificate was revoked (CRL)");
+
+ if (EQ (status_symbol, intern (":self-signed")))
+ return build_string ("certificate signer was not found (self-signed)");
+
+ if (EQ (status_symbol, intern (":unknown-ca")))
+ return build_string ("the certificate was signed by an unknown "
+ "and therefore untrusted authority");
+
+ if (EQ (status_symbol, intern (":not-ca")))
+ return build_string ("certificate signer is not a CA");
+
+ if (EQ (status_symbol, intern (":insecure")))
+ return build_string ("certificate was signed with an insecure algorithm");
+
+ if (EQ (status_symbol, intern (":not-activated")))
+ return build_string ("certificate is not yet activated");
+
+ if (EQ (status_symbol, intern (":expired")))
+ return build_string ("certificate has expired");
+
+ if (EQ (status_symbol, intern (":no-host-match")))
+ return build_string ("certificate host does not match hostname");
+
+ return Qnil;
+}
+
+DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0,
+ doc: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
+The return value is a property list with top-level keys :warnings and
+:certificate. The :warnings entry is a list of symbols you can describe with
+`gnutls-peer-status-warning-describe'. */)
+ (Lisp_Object proc)
+{
+ Lisp_Object warnings = Qnil, result = Qnil;
+ unsigned int verification;
+ gnutls_session_t state;
+
+ CHECK_PROCESS (proc);
+
+ if (GNUTLS_INITSTAGE (proc) < GNUTLS_STAGE_INIT)
+ return Qnil;
+
+ /* Then collect any warnings already computed by the handshake. */
+ verification = XPROCESS (proc)->gnutls_peer_verification;
+
+ if (verification & GNUTLS_CERT_INVALID)
+ warnings = Fcons (intern (":invalid"), warnings);
+
+ if (verification & GNUTLS_CERT_REVOKED)
+ warnings = Fcons (intern (":revoked"), warnings);
+
+ if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ warnings = Fcons (intern (":unknown-ca"), warnings);
+
+ if (verification & GNUTLS_CERT_SIGNER_NOT_CA)
+ warnings = Fcons (intern (":not-ca"), warnings);
+
+ if (verification & GNUTLS_CERT_INSECURE_ALGORITHM)
+ warnings = Fcons (intern (":insecure"), warnings);
+
+ if (verification & GNUTLS_CERT_NOT_ACTIVATED)
+ warnings = Fcons (intern (":not-activated"), warnings);
+
+ if (verification & GNUTLS_CERT_EXPIRED)
+ warnings = Fcons (intern (":expired"), warnings);
+
+ if (XPROCESS (proc)->gnutls_extra_peer_verification &
+ CERTIFICATE_NOT_MATCHING)
+ warnings = Fcons (intern (":no-host-match"), warnings);
+
+ /* This could get called in the INIT stage, when the certificate is
+ not yet set. */
+ if (XPROCESS (proc)->gnutls_certificate != NULL &&
+ gnutls_x509_crt_check_issuer(XPROCESS (proc)->gnutls_certificate,
+ XPROCESS (proc)->gnutls_certificate))
+ warnings = Fcons (intern (":self-signed"), warnings);
+
+ if (!NILP (warnings))
+ result = list2 (intern (":warnings"), warnings);
+
+ /* This could get called in the INIT stage, when the certificate is
+ not yet set. */
+ if (XPROCESS (proc)->gnutls_certificate != NULL)
+ result = nconc2 (result, list2
+ (intern (":certificate"),
+ gnutls_certificate_details (XPROCESS (proc)->gnutls_certificate)));
+
+ state = XPROCESS (proc)->gnutls_state;
+
+ /* Diffie-Hellman prime bits. */
+ {
+ int bits = gnutls_dh_get_prime_bits (state);
+ check_memory_full (bits);
+ if (bits > 0)
+ result = nconc2 (result, list2 (intern (":diffie-hellman-prime-bits"),
+ make_number (bits)));
+ }
+
+ /* Key exchange. */
+ result = nconc2
+ (result, list2 (intern (":key-exchange"),
+ build_string (gnutls_kx_get_name
+ (gnutls_kx_get (state)))));
+
+ /* Protocol name. */
+ result = nconc2
+ (result, list2 (intern (":protocol"),
+ build_string (gnutls_protocol_get_name
+ (gnutls_protocol_get_version (state)))));
+
+ /* Cipher name. */
+ result = nconc2
+ (result, list2 (intern (":cipher"),
+ build_string (gnutls_cipher_get_name
+ (gnutls_cipher_get (state)))));
+
+ /* MAC name. */
+ result = nconc2
+ (result, list2 (intern (":mac"),
+ build_string (gnutls_mac_get_name
+ (gnutls_mac_get (state)))));
+
+
+ return result;
+}
+
+/* Initialize global GnuTLS state to defaults.
+ Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
+ Return zero on success. */
static Lisp_Object
emacs_gnutls_global_init (void)
{
int ret = GNUTLS_E_SUCCESS;
if (!gnutls_global_initialized)
- ret = fn_gnutls_global_init ();
+ ret = gnutls_global_init ();
gnutls_global_initialized = 1;
return gnutls_make_error (ret);
}
+static bool
+gnutls_ip_address_p (char *string)
+{
+ char c;
+
+ while ((c = *string++) != 0)
+ if (! ((c == '.' || c == ':' || (c >= '0' && c <= '9'))))
+ return false;
+
+ return true;
+}
+
#if 0
-/* Deinitializes global GnuTLS state.
-See also `gnutls-global-init'. */
+/* Deinitialize global GnuTLS state.
+ See also `gnutls-global-init'. */
static Lisp_Object
emacs_gnutls_global_deinit (void)
{
@@ -778,7 +1217,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;
@@ -790,6 +1229,7 @@ one trustfile (usually a CA bundle). */)
Lisp_Object hostname;
Lisp_Object verify_error;
Lisp_Object prime_bits;
+ Lisp_Object warnings;
CHECK_PROCESS (proc);
CHECK_SYMBOL (type);
@@ -827,16 +1267,18 @@ one trustfile (usually a CA bundle). */)
if (TYPE_RANGED_INTEGERP (int, loglevel))
{
- fn_gnutls_global_set_log_function (gnutls_log_function);
+ gnutls_global_set_log_function (gnutls_log_function);
#ifdef HAVE_GNUTLS3
- fn_gnutls_global_set_audit_log_function (gnutls_audit_log_function);
+ gnutls_global_set_audit_log_function (gnutls_audit_log_function);
#endif
- fn_gnutls_global_set_log_level (XINT (loglevel));
+ gnutls_global_set_log_level (XINT (loglevel));
max_log_level = XINT (loglevel);
XPROCESS (proc)->gnutls_log_level = max_log_level;
}
- /* always initialize globals. */
+ GNUTLS_LOG2 (1, max_log_level, "connecting to host:", c_hostname);
+
+ /* Always initialize globals. */
global_init = emacs_gnutls_global_init ();
if (! NILP (Fgnutls_errorp (global_init)))
return global_init;
@@ -859,8 +1301,7 @@ one trustfile (usually a CA bundle). */)
unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
- check_memory_full ((fn_gnutls_certificate_allocate_credentials
- (&x509_cred)));
+ check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
XPROCESS (proc)->gnutls_x509_cred = x509_cred;
verify_flags = Fplist_get (proplist, QCgnutls_bootprop_verify_flags);
@@ -874,13 +1315,12 @@ one trustfile (usually a CA bundle). */)
else
GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
- fn_gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
+ gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
}
else /* Qgnutls_anon: */
{
GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
- check_memory_full ((fn_gnutls_anon_allocate_client_credentials
- (&anon_cred)));
+ check_memory_full (gnutls_anon_allocate_client_credentials (&anon_cred));
XPROCESS (proc)->gnutls_anon_cred = anon_cred;
}
@@ -892,6 +1332,17 @@ one trustfile (usually a CA bundle). */)
int file_format = GNUTLS_X509_FMT_PEM;
Lisp_Object tail;
+#if GNUTLS_VERSION_MAJOR + \
+ (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
+ ret = gnutls_certificate_set_x509_system_trust (x509_cred);
+ if (ret < GNUTLS_E_SUCCESS)
+ {
+ check_memory_full (ret);
+ GNUTLS_LOG2i (4, max_log_level,
+ "setting system trust failed with code ", ret);
+ }
+#endif
+
for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
{
Lisp_Object trustfile = XCAR (tail);
@@ -906,7 +1357,7 @@ one trustfile (usually a CA bundle). */)
name using the current ANSI codepage. */
trustfile = ansi_encode_filename (trustfile);
#endif
- ret = fn_gnutls_certificate_set_x509_trust_file
+ ret = gnutls_certificate_set_x509_trust_file
(x509_cred,
SSDATA (trustfile),
file_format);
@@ -932,7 +1383,7 @@ one trustfile (usually a CA bundle). */)
#ifdef WINDOWSNT
crlfile = ansi_encode_filename (crlfile);
#endif
- ret = fn_gnutls_certificate_set_x509_crl_file
+ ret = gnutls_certificate_set_x509_crl_file
(x509_cred, SSDATA (crlfile), file_format);
if (ret < GNUTLS_E_SUCCESS)
@@ -961,7 +1412,7 @@ one trustfile (usually a CA bundle). */)
keyfile = ansi_encode_filename (keyfile);
certfile = ansi_encode_filename (certfile);
#endif
- ret = fn_gnutls_certificate_set_x509_key_file
+ ret = gnutls_certificate_set_x509_key_file
(x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
if (ret < GNUTLS_E_SUCCESS)
@@ -983,7 +1434,7 @@ one trustfile (usually a CA bundle). */)
/* Call gnutls_init here: */
GNUTLS_LOG (1, max_log_level, "gnutls_init");
- ret = fn_gnutls_init (&state, GNUTLS_CLIENT);
+ ret = gnutls_init (&state, GNUTLS_CLIENT);
XPROCESS (proc)->gnutls_state = state;
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
@@ -1002,23 +1453,29 @@ one trustfile (usually a CA bundle). */)
}
GNUTLS_LOG (1, max_log_level, "setting the priority string");
- ret = fn_gnutls_priority_set_direct (state,
- priority_string_ptr,
- NULL);
+ ret = gnutls_priority_set_direct (state, priority_string_ptr, NULL);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY;
if (INTEGERP (prime_bits))
- fn_gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
+ gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
ret = EQ (type, Qgnutls_x509pki)
- ? fn_gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
- : fn_gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
+ ? gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
+ : gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
+ if (!gnutls_ip_address_p (c_hostname))
+ {
+ ret = gnutls_server_name_set (state, GNUTLS_NAME_DNS, c_hostname,
+ strlen (c_hostname));
+ if (ret < GNUTLS_E_SUCCESS)
+ return gnutls_make_error (ret);
+ }
+
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
ret = emacs_gnutls_handshake (XPROCESS (proc));
if (ret < GNUTLS_E_SUCCESS)
@@ -1028,39 +1485,26 @@ one trustfile (usually a CA bundle). */)
http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
The peer should present at least one certificate in the chain; do a
check of the certificate's hostname with
- gnutls_x509_crt_check_hostname() against :hostname. */
+ gnutls_x509_crt_check_hostname against :hostname. */
- ret = fn_gnutls_certificate_verify_peers2 (state, &peer_verification);
+ ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
- if (XINT (loglevel) > 0 && peer_verification & GNUTLS_CERT_INVALID)
- message ("%s certificate could not be verified.", c_hostname);
-
- if (peer_verification & GNUTLS_CERT_REVOKED)
- GNUTLS_LOG2 (1, max_log_level, "certificate was revoked (CRL):",
- c_hostname);
-
- if (peer_verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
- GNUTLS_LOG2 (1, max_log_level, "certificate signer was not found:",
- c_hostname);
-
- if (peer_verification & GNUTLS_CERT_SIGNER_NOT_CA)
- GNUTLS_LOG2 (1, max_log_level, "certificate signer is not a CA:",
- c_hostname);
-
- if (peer_verification & GNUTLS_CERT_INSECURE_ALGORITHM)
- GNUTLS_LOG2 (1, max_log_level,
- "certificate was signed with an insecure algorithm:",
- c_hostname);
+ XPROCESS (proc)->gnutls_peer_verification = peer_verification;
- if (peer_verification & GNUTLS_CERT_NOT_ACTIVATED)
- GNUTLS_LOG2 (1, max_log_level, "certificate is not yet activated:",
- c_hostname);
-
- if (peer_verification & GNUTLS_CERT_EXPIRED)
- GNUTLS_LOG2 (1, max_log_level, "certificate has expired:",
- c_hostname);
+ warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
+ if (!NILP (warnings))
+ {
+ Lisp_Object tail;
+ for (tail = warnings; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object warning = XCAR (tail);
+ Lisp_Object message = Fgnutls_peer_status_warning_describe (warning);
+ if (!NILP (message))
+ GNUTLS_LOG2 (1, max_log_level, "verification:", SSDATA (message));
+ }
+ }
if (peer_verification != 0)
{
@@ -1081,46 +1525,50 @@ one trustfile (usually a CA bundle). */)
/* Up to here the process is the same for X.509 certificates and
OpenPGP keys. From now on X.509 certificates are assumed. This
can be easily extended to work with openpgp keys as well. */
- if (fn_gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
+ if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
{
gnutls_x509_crt_t gnutls_verify_cert;
const gnutls_datum_t *gnutls_verify_cert_list;
unsigned int gnutls_verify_cert_list_size;
- ret = fn_gnutls_x509_crt_init (&gnutls_verify_cert);
+ ret = gnutls_x509_crt_init (&gnutls_verify_cert);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
gnutls_verify_cert_list =
- fn_gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
+ gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
if (gnutls_verify_cert_list == NULL)
{
- fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
+ gnutls_x509_crt_deinit (gnutls_verify_cert);
emacs_gnutls_deinit (proc);
error ("No x509 certificate was found\n");
}
/* We only check the first certificate in the given chain. */
- ret = fn_gnutls_x509_crt_import (gnutls_verify_cert,
+ ret = gnutls_x509_crt_import (gnutls_verify_cert,
&gnutls_verify_cert_list[0],
GNUTLS_X509_FMT_DER);
if (ret < GNUTLS_E_SUCCESS)
{
- fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
+ gnutls_x509_crt_deinit (gnutls_verify_cert);
return gnutls_make_error (ret);
}
- int err
- = fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname);
+ XPROCESS (proc)->gnutls_certificate = gnutls_verify_cert;
+
+ int err = gnutls_x509_crt_check_hostname (gnutls_verify_cert,
+ c_hostname);
check_memory_full (err);
if (!err)
{
+ XPROCESS (proc)->gnutls_extra_peer_verification |=
+ CERTIFICATE_NOT_MATCHING;
if (verify_error_all
|| !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error)))
{
- fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
+ gnutls_x509_crt_deinit (gnutls_verify_cert);
emacs_gnutls_deinit (proc);
error ("The x509 certificate does not match \"%s\"", c_hostname);
}
@@ -1130,7 +1578,6 @@ one trustfile (usually a CA bundle). */)
c_hostname);
}
}
- fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
}
/* Set this flag only if the whole initialization succeeded. */
@@ -1162,8 +1609,9 @@ This function may also return `gnutls-e-again', or
state = XPROCESS (proc)->gnutls_state;
- ret = fn_gnutls_bye (state,
- NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
+ gnutls_x509_crt_deinit (XPROCESS (proc)->gnutls_certificate);
+
+ ret = gnutls_bye (state, NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
return gnutls_make_error (ret);
}
@@ -1204,13 +1652,14 @@ syms_of_gnutls (void)
DEFSYM (Qgnutls_code, "gnutls-code");
DEFSYM (Qgnutls_anon, "gnutls-anon");
DEFSYM (Qgnutls_x509pki, "gnutls-x509pki");
+
+ /* The following are for the property list of 'gnutls-boot'. */
DEFSYM (QCgnutls_bootprop_hostname, ":hostname");
DEFSYM (QCgnutls_bootprop_priority, ":priority");
DEFSYM (QCgnutls_bootprop_trustfiles, ":trustfiles");
DEFSYM (QCgnutls_bootprop_keylist, ":keylist");
DEFSYM (QCgnutls_bootprop_crlfiles, ":crlfiles");
DEFSYM (QCgnutls_bootprop_callbacks, ":callbacks");
- DEFSYM (QCgnutls_bootprop_callbacks_verify, "verify");
DEFSYM (QCgnutls_bootprop_min_prime_bits, ":min-prime-bits");
DEFSYM (QCgnutls_bootprop_loglevel, ":loglevel");
DEFSYM (QCgnutls_bootprop_verify_flags, ":verify-flags");
@@ -1239,6 +1688,8 @@ syms_of_gnutls (void)
defsubr (&Sgnutls_boot);
defsubr (&Sgnutls_deinit);
defsubr (&Sgnutls_bye);
+ defsubr (&Sgnutls_peer_status);
+ defsubr (&Sgnutls_peer_status_warning_describe);
DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
doc: /* Logging level used by the GnuTLS functions.
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 5c9ff9ca68d..21f3cb15e66 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"
@@ -49,11 +50,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "emacsgtkfixed.h"
#endif
-#define FRAME_TOTAL_PIXEL_HEIGHT(f) \
- (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
+/** #define FRAME_TOTAL_PIXEL_HEIGHT(f) \ **/
+/** (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) **/
-#define FRAME_TOTAL_PIXEL_WIDTH(f) \
- (FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f))
+/** #define FRAME_TOTAL_PIXEL_WIDTH(f) \ **/
+/** (FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f)) **/
#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
#define gtk_widget_set_has_window(w, b) \
@@ -78,6 +79,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define remove_submenu(w) gtk_menu_item_remove_submenu ((w))
#endif
+#if ! GTK_CHECK_VERSION (2, 14, 0)
+#define gtk_adjustment_configure(adj, xvalue, xlower, \
+ xupper, xstep_increment, \
+ xpage_increment, xpagesize) \
+ do { \
+ adj->lower = xlower; \
+ adj->upper = xupper; \
+ adj->page_size = xpagesize; \
+ gtk_adjustment_set_value (adj, xvalue); \
+ adj->page_increment = xpage_increment; \
+ adj->step_increment = xstep_increment; \
+ } while (0)
+#endif /* < Gtk+ 2.14 */
+
#ifdef HAVE_FREETYPE
#if GTK_CHECK_VERSION (3, 2, 0)
#define USE_NEW_GTK_FONT_CHOOSER 1
@@ -92,6 +107,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 +139,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 +247,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 +532,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 +846,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 +908,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,12 +954,13 @@ 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, Qxg_frame_set_char_size);
}
/* Handle height/width changes (i.e. add/remove/move menu/toolbar).
The policy is to keep the number of editable lines. */
+#if 0
static void
xg_height_or_width_changed (struct frame *f)
{
@@ -992,6 +970,7 @@ xg_height_or_width_changed (struct frame *f)
f->output_data.x->hint_flags = 0;
x_wm_set_size_hint (f, 0, 0);
}
+#endif
/* Convert an X Window WSESC on display DPY to its corresponding GtkWidget.
Must be done like this, because GtkWidget:s can have "hidden"
@@ -1067,6 +1046,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 +1061,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 +1345,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 +1505,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 +1512,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 +1568,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 +1581,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 +1598,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 +1814,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);
@@ -1849,12 +1839,12 @@ xg_get_file_with_chooser (struct frame *f,
if (x_gtk_file_dialog_help_text)
{
- msgbuf[0] = '\0';
+ char *z = msgbuf;
/* Gtk+ 2.10 has the file name text entry box integrated in the dialog.
Show the C-l help text only for versions < 2.10. */
if (gtk_check_version (2, 10, 0) && action != GTK_FILE_CHOOSER_ACTION_SAVE)
- strcat (msgbuf, "\nType C-l to display a file name text entry box.\n");
- strcat (msgbuf, "\nIf you don't like this file selector, use the "
+ z = stpcpy (z, "\nType C-l to display a file name text entry box.\n");
+ strcpy (z, "\nIf you don't like this file selector, use the "
"corresponding\nkey binding or customize "
"use-file-dialog to turn it off.");
@@ -2082,28 +2072,17 @@ xg_get_font (struct frame *f, const char *default_name)
if (desc)
{
- Lisp_Object args[10];
const char *name = pango_font_description_get_family (desc);
gint size = pango_font_description_get_size (desc);
PangoWeight weight = pango_font_description_get_weight (desc);
PangoStyle style = pango_font_description_get_style (desc);
- args[0] = QCname;
- args[1] = build_string (name);
-
- args[2] = QCsize;
- args[3] = make_float (pango_units_to_double (size));
-
- args[4] = QCweight;
- args[5] = XG_WEIGHT_TO_SYMBOL (weight);
-
- args[6] = QCslant;
- args[7] = XG_STYLE_TO_SYMBOL (style);
-
- args[8] = QCtype;
- args[9] = Qxft;
-
- font = Ffont_spec (8, args);
+ font = CALLN (Ffont_spec,
+ QCname, build_string (name),
+ QCsize, make_float (pango_units_to_double (size)),
+ QCweight, XG_WEIGHT_TO_SYMBOL (weight),
+ QCslant, XG_STYLE_TO_SYMBOL (style),
+ QCtype, Qxft);
pango_font_description_free (desc);
dupstring (&x_last_font_name, name);
@@ -2333,9 +2312,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 +2391,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 +2461,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 +2482,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 +2532,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 +2545,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 +2575,6 @@ create_menus (widget_value *data,
highlight_cb,
0,
0,
- add_tearoff_p,
0,
cl_data,
0);
@@ -2714,7 +2632,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 +2741,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 +2814,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 +2821,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 +2850,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 +3002,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 +3049,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 +3060,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 +3147,6 @@ xg_update_submenu (GtkWidget *submenu,
highlight_cb,
0,
0,
- ! has_tearoff_p,
submenu,
cl_data,
0);
@@ -3348,7 +3246,7 @@ menubar_map_cb (GtkWidget *w, gpointer user_data)
if (FRAME_MENUBAR_HEIGHT (f) != req.height)
{
FRAME_MENUBAR_HEIGHT (f) = req.height;
- xg_height_or_width_changed (f);
+ adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
}
}
@@ -3380,7 +3278,7 @@ xg_update_frame_menubar (struct frame *f)
if (FRAME_MENUBAR_HEIGHT (f) != req.height)
{
FRAME_MENUBAR_HEIGHT (f) = req.height;
- xg_height_or_width_changed (f);
+ adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
}
unblock_input ();
}
@@ -3402,7 +3300,7 @@ free_frame_menubar (struct frame *f)
the container. */
x->menubar_widget = 0;
FRAME_MENUBAR_HEIGHT (f) = 0;
- xg_height_or_width_changed (f);
+ adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
unblock_input ();
}
}
@@ -3424,7 +3322,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 +3367,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 +3472,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 +3605,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 +3755,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 +3916,39 @@ 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));
+ gtk_adjustment_configure (adj, (gdouble) value, (gdouble) lower,
+ (gdouble) upper, (gdouble) step_increment,
+ (gdouble) page_increment, (gdouble) pagesize);
+ 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 +3999,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 +4071,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 +4084,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 +4163,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 +4170,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 +4191,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);
@@ -4365,7 +4215,7 @@ tb_size_cb (GtkWidget *widget,
size hints if tool bar size changes. Seen on Fedora 18 at least. */
struct frame *f = user_data;
if (xg_update_tool_bar_sizes (f))
- xg_height_or_width_changed (f);
+ adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
}
/* Create a tool bar for frame F. */
@@ -4493,10 +4343,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 +4456,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 +4495,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 +4546,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 +4583,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 +4621,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 +4674,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 +4756,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 +4780,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,10 +4812,10 @@ 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);
+ adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
}
unblock_input ();
@@ -4935,11 +4832,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 +4848,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;
@@ -4968,7 +4863,7 @@ free_frame_tool_bar (struct frame *f)
NULL);
}
- xg_height_or_width_changed (f);
+ adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
unblock_input ();
}
@@ -4978,7 +4873,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;
@@ -4998,7 +4893,7 @@ xg_change_toolbar_position (struct frame *f, Lisp_Object pos)
xg_pack_tool_bar (f, pos);
g_object_unref (top_widget);
if (xg_update_tool_bar_sizes (f))
- xg_height_or_width_changed (f);
+ adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
unblock_input ();
}
@@ -5022,9 +4917,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 +4952,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 5176be61f86..0ac49ca7db5 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,10 +78,7 @@ 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 bool xg_uses_old_file_dialog (void);
extern char *xg_get_file_name (struct frame *f,
char *prompt,
@@ -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 c068c863368..df299bbd164 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>
@@ -35,6 +33,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "frame.h"
#include "window.h"
+#include "buffer.h"
#include "dispextern.h"
#include "blockinput.h"
#include "systime.h"
@@ -87,12 +86,6 @@ typedef struct w32_bitmap_record Bitmap_Record;
#define x_defined_color w32_defined_color
#define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
-/* Versions of libpng, libgif, and libjpeg that we were compiled with,
- or -1 if no PNG/GIF support was compiled in. This is tested by
- w32-win.el to correctly set up the alist used to search for the
- respective image libraries. */
-Lisp_Object Qlibpng_version, Qlibgif_version, Qlibjpeg_version;
-
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
@@ -111,11 +104,6 @@ typedef struct ns_bitmap_record Bitmap_Record;
#define DefaultDepthOfScreen(screen) x_display_list->n_planes
#endif /* HAVE_NS */
-
-/* The symbol `postscript' identifying images of this type. */
-
-static Lisp_Object Qpostscript;
-
static void x_disable_image (struct frame *, struct image *);
static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
Lisp_Object);
@@ -127,8 +115,6 @@ static void free_color_table (void);
static unsigned long *colors_in_color_table (int *n);
#endif
-static Lisp_Object QCmax_width, QCmax_height;
-
/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
id, which is just an int that this section returns. Bitmaps are
reference counted so they can be shared among frames.
@@ -160,6 +146,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 +158,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
@@ -536,24 +524,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
static struct image_type *image_types;
-/* The symbol `xbm' which is used as the type symbol for XBM images. */
-
-static Lisp_Object Qxbm;
-
-/* Keywords. */
-
-Lisp_Object QCascent, QCmargin, QCrelief;
-Lisp_Object QCconversion;
-static Lisp_Object QCheuristic_mask;
-static Lisp_Object QCcolor_symbols;
-static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
-static Lisp_Object QCcrop, QCrotation;
-
-/* Other symbols. */
-
-static Lisp_Object Qcount, Qextension_data, Qdelay;
-static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
-
/* Forward function prototypes. */
static struct image_type *lookup_image_type (Lisp_Object);
@@ -578,27 +548,29 @@ static struct image_type *
define_image_type (struct image_type *type)
{
struct image_type *p = NULL;
- Lisp_Object target_type = *type->type;
- bool type_valid = 1;
+ int new_type = type->type;
+ bool type_valid = true;
block_input ();
for (p = image_types; p; p = p->next)
- if (EQ (*p->type, target_type))
+ if (p->type == new_type)
goto done;
if (type->init)
{
#if defined HAVE_NTGUI && defined WINDOWSNT
/* If we failed to load the library before, don't try again. */
- Lisp_Object tested = Fassq (target_type, Vlibrary_cache);
+ Lisp_Object tested = Fassq (builtin_lisp_symbol (new_type),
+ Vlibrary_cache);
if (CONSP (tested) && NILP (XCDR (tested)))
- type_valid = 0;
+ type_valid = false;
else
#endif
{
type_valid = type->init ();
- CACHE_IMAGE_TYPE (target_type, type_valid ? Qt : Qnil);
+ CACHE_IMAGE_TYPE (builtin_lisp_symbol (new_type),
+ type_valid ? Qt : Qnil);
}
}
@@ -998,6 +970,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 +1208,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
***********************************************************************/
@@ -1755,7 +1748,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
/* Do image transformations and compute masks, unless we
don't have the image yet. */
- if (!EQ (*img->type->type, Qpostscript))
+ if (!EQ (builtin_lisp_symbol (img->type->type), Qpostscript))
postprocess_image (f, img);
}
@@ -1837,19 +1830,6 @@ mark_image_cache (struct image_cache *c)
X / NS / W32 support code
***********************************************************************/
-#ifdef WINDOWSNT
-
-/* Macro for defining functions that will be loaded from image DLLs. */
-#define DEF_IMGLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
-
-/* Macro for loading those image functions from the library. */
-#define LOAD_IMGLIB_FN(lib,func) { \
- fn_##func = (void *) GetProcAddress (lib, #func); \
- if (!fn_##func) return 0; \
- }
-
-#endif /* WINDOWSNT */
-
/* Return true if XIMG's size WIDTH x HEIGHT doesn't break the
windowing system.
WIDTH and HEIGHT must both be positive.
@@ -2353,7 +2333,7 @@ static const struct image_keyword xbm_format[XBM_LAST] =
static struct image_type xbm_type =
{
- &Qxbm,
+ SYMBOL_INDEX (Qxbm),
xbm_image_p,
xbm_load,
x_clear_image,
@@ -3016,13 +2996,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 +3026,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 +3049,8 @@ xbm_load (struct frame *f, struct image *img)
img->spec, Qnil);
x_clear_image (f, img);
}
+
+ SAFE_FREE ();
}
}
@@ -3108,9 +3092,6 @@ static bool xpm_load (struct frame *f, struct image *img);
#endif /* HAVE_XPM */
#if defined (HAVE_XPM) || defined (HAVE_NS)
-/* The symbol `xpm' identifying XPM-format images. */
-
-static Lisp_Object Qxpm;
/* Indices of image specification fields in xpm_format, below. */
@@ -3158,7 +3139,7 @@ static bool init_xpm_functions (void);
static struct image_type xpm_type =
{
- &Qxpm,
+ SYMBOL_INDEX (Qxpm),
xpm_image_p,
xpm_load,
x_clear_image,
@@ -3351,12 +3332,14 @@ xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *
/* XPM library details. */
-DEF_IMGLIB_FN (void, XpmFreeAttributes, (XpmAttributes *));
-DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer, (Display *, char *, xpm_XImage **,
- xpm_XImage **, XpmAttributes *));
-DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **,
- xpm_XImage **, XpmAttributes *));
-DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *));
+DEF_DLL_FN (void, XpmFreeAttributes, (XpmAttributes *));
+DEF_DLL_FN (int, XpmCreateImageFromBuffer,
+ (Display *, char *, xpm_XImage **,
+ xpm_XImage **, XpmAttributes *));
+DEF_DLL_FN (int, XpmReadFileToImage,
+ (Display *, char *, xpm_XImage **,
+ xpm_XImage **, XpmAttributes *));
+DEF_DLL_FN (void, XImageFree, (xpm_XImage *));
static bool
init_xpm_functions (void)
@@ -3366,22 +3349,24 @@ init_xpm_functions (void)
if (!(library = w32_delayed_load (Qxpm)))
return 0;
- LOAD_IMGLIB_FN (library, XpmFreeAttributes);
- LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
- LOAD_IMGLIB_FN (library, XpmReadFileToImage);
- LOAD_IMGLIB_FN (library, XImageFree);
+ LOAD_DLL_FN (library, XpmFreeAttributes);
+ LOAD_DLL_FN (library, XpmCreateImageFromBuffer);
+ LOAD_DLL_FN (library, XpmReadFileToImage);
+ LOAD_DLL_FN (library, XImageFree);
return 1;
}
-#endif /* WINDOWSNT */
+# undef XImageFree
+# undef XpmCreateImageFromBuffer
+# undef XpmFreeAttributes
+# undef XpmReadFileToImage
-#if defined HAVE_NTGUI && !defined WINDOWSNT
-/* Glue for code below */
-#define fn_XpmReadFileToImage XpmReadFileToImage
-#define fn_XpmCreateImageFromBuffer XpmCreateImageFromBuffer
-#define fn_XImageFree XImageFree
-#define fn_XpmFreeAttributes XpmFreeAttributes
-#endif /* HAVE_NTGUI && !WINDOWSNT */
+# define XImageFree fn_XImageFree
+# define XpmCreateImageFromBuffer fn_XpmCreateImageFromBuffer
+# define XpmFreeAttributes fn_XpmFreeAttributes
+# define XpmReadFileToImage fn_XpmReadFileToImage
+
+#endif /* WINDOWSNT */
/* Value is true if COLOR_SYMBOLS is a valid color symbols list
for XPM images. Such a list must consist of conses whose car and
@@ -3473,6 +3458,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 +3502,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 +3512,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 +3535,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 +3570,7 @@ xpm_load (struct frame *f, struct image *img)
#ifdef ALLOC_XPM_COLORS
xpm_free_color_cache ();
#endif
+ SAFE_FREE ();
return 0;
}
@@ -3601,9 +3583,9 @@ xpm_load (struct frame *f, struct image *img)
#endif
/* XpmReadFileToPixmap is not available in the Windows port of
libxpm. But XpmReadFileToImage almost does what we want. */
- rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
- &xpm_image, &xpm_mask,
- &attrs);
+ rc = XpmReadFileToImage (&hdc, SDATA (file),
+ &xpm_image, &xpm_mask,
+ &attrs);
#else
rc = XpmReadFileToImage (FRAME_X_DISPLAY (f), SSDATA (file),
&img->ximg, &img->mask_img,
@@ -3619,14 +3601,15 @@ xpm_load (struct frame *f, struct image *img)
#ifdef ALLOC_XPM_COLORS
xpm_free_color_cache ();
#endif
+ SAFE_FREE ();
return 0;
}
#ifdef HAVE_NTGUI
/* XpmCreatePixmapFromBuffer is not available in the Windows port
of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
- rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
- &xpm_image, &xpm_mask,
- &attrs);
+ rc = XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
+ &xpm_image, &xpm_mask,
+ &attrs);
#else
rc = XpmCreateImageFromBuffer (FRAME_X_DISPLAY (f), SSDATA (buffer),
&img->ximg, &img->mask_img,
@@ -3675,7 +3658,7 @@ xpm_load (struct frame *f, struct image *img)
img->pixmap = xpm_image->bitmap;
/* XImageFree in libXpm frees XImage struct without destroying
the bitmap, which is what we want. */
- fn_XImageFree (xpm_image);
+ XImageFree (xpm_image);
}
if (xpm_mask && xpm_mask->bitmap)
{
@@ -3689,7 +3672,7 @@ xpm_load (struct frame *f, struct image *img)
SelectObject (hdc, old_obj);
img->mask = xpm_mask->bitmap;
- fn_XImageFree (xpm_mask);
+ XImageFree (xpm_mask);
DeleteDC (hdc);
}
@@ -3713,11 +3696,7 @@ xpm_load (struct frame *f, struct image *img)
eassert (img->width > 0 && img->height > 0);
/* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
-#ifdef HAVE_NTGUI
- fn_XpmFreeAttributes (&attrs);
-#else
XpmFreeAttributes (&attrs);
-#endif /* HAVE_NTGUI */
#ifdef HAVE_X_WINDOWS
/* Maybe fill in the background field while we have ximg handy. */
@@ -3761,6 +3740,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 +3933,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;
@@ -4272,7 +4250,11 @@ struct ct_color
/* Value is a hash of the RGB color given by R, G, and B. */
-#define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
+static unsigned
+ct_hash_rgb (unsigned r, unsigned g, unsigned b)
+{
+ return (r << 16) ^ (g << 8) ^ b;
+}
/* The color hash table. */
@@ -4327,7 +4309,7 @@ free_color_table (void)
static unsigned long
lookup_rgb_color (struct frame *f, int r, int g, int b)
{
- unsigned hash = CT_HASH_RGB (r, g, b);
+ unsigned hash = ct_hash_rgb (r, g, b);
int i = hash % CT_SIZE;
struct ct_color *p;
Display_Info *dpyinfo;
@@ -4441,7 +4423,7 @@ lookup_pixel_color (struct frame *f, unsigned long pixel)
Colormap cmap;
bool rc;
- if (ct_colors_allocated_max <= ct_colors_allocated)
+ if (ct_colors_allocated >= ct_colors_allocated_max)
return FRAME_FOREGROUND_PIXEL (f);
#ifdef HAVE_X_WINDOWS
@@ -4572,7 +4554,7 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
+ if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width)
memory_full (SIZE_MAX);
colors = xmalloc (sizeof *colors * img->width * img->height);
@@ -4713,7 +4695,7 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus
#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
+ if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width)
memory_full (SIZE_MAX);
new = xmalloc (sizeof *new * img->width * img->height);
@@ -5045,10 +5027,6 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
static bool pbm_image_p (Lisp_Object object);
static bool pbm_load (struct frame *f, struct image *img);
-/* The symbol `pbm' identifying images of this type. */
-
-static Lisp_Object Qpbm;
-
/* Indices of image specification fields in gs_format, below. */
enum pbm_keyword_index
@@ -5089,7 +5067,7 @@ static const struct image_keyword pbm_format[PBM_LAST] =
static struct image_type pbm_type =
{
- &Qpbm,
+ SYMBOL_INDEX (Qpbm),
pbm_image_p,
pbm_load,
x_clear_image,
@@ -5432,10 +5410,6 @@ pbm_load (struct frame *f, struct image *img)
static bool png_image_p (Lisp_Object object);
static bool png_load (struct frame *f, struct image *img);
-/* The symbol `png' identifying images of this type. */
-
-static Lisp_Object Qpng;
-
/* Indices of image specification fields in png_format, below. */
enum png_keyword_index
@@ -5480,7 +5454,7 @@ static bool init_png_functions (void);
static struct image_type png_type =
{
- &Qpng,
+ SYMBOL_INDEX (Qpng),
png_image_p,
png_load,
x_clear_image,
@@ -5506,41 +5480,44 @@ png_image_p (Lisp_Object object)
#endif /* HAVE_PNG || HAVE_NS */
-#ifdef HAVE_PNG
+#if defined HAVE_PNG && !defined HAVE_NS
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* PNG library details. */
-DEF_IMGLIB_FN (png_voidp, png_get_io_ptr, (png_structp));
-DEF_IMGLIB_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
-DEF_IMGLIB_FN (png_structp, png_create_read_struct, (png_const_charp, png_voidp,
- png_error_ptr, png_error_ptr));
-DEF_IMGLIB_FN (png_infop, png_create_info_struct, (png_structp));
-DEF_IMGLIB_FN (void, png_destroy_read_struct, (png_structpp, png_infopp, png_infopp));
-DEF_IMGLIB_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
-DEF_IMGLIB_FN (void, png_set_sig_bytes, (png_structp, int));
-DEF_IMGLIB_FN (void, png_read_info, (png_structp, png_infop));
-DEF_IMGLIB_FN (png_uint_32, png_get_IHDR, (png_structp, png_infop,
- png_uint_32 *, png_uint_32 *,
- int *, int *, int *, int *, int *));
-DEF_IMGLIB_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
-DEF_IMGLIB_FN (void, png_set_strip_16, (png_structp));
-DEF_IMGLIB_FN (void, png_set_expand, (png_structp));
-DEF_IMGLIB_FN (void, png_set_gray_to_rgb, (png_structp));
-DEF_IMGLIB_FN (void, png_set_background, (png_structp, png_color_16p,
- int, int, double));
-DEF_IMGLIB_FN (png_uint_32, png_get_bKGD, (png_structp, png_infop, png_color_16p *));
-DEF_IMGLIB_FN (void, png_read_update_info, (png_structp, png_infop));
-DEF_IMGLIB_FN (png_byte, png_get_channels, (png_structp, png_infop));
-DEF_IMGLIB_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
-DEF_IMGLIB_FN (void, png_read_image, (png_structp, png_bytepp));
-DEF_IMGLIB_FN (void, png_read_end, (png_structp, png_infop));
-DEF_IMGLIB_FN (void, png_error, (png_structp, png_const_charp));
-
-#if (PNG_LIBPNG_VER >= 10500)
-DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int)) PNG_NORETURN;
-DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t));
-#endif /* libpng version >= 1.5 */
+DEF_DLL_FN (png_voidp, png_get_io_ptr, (png_structp));
+DEF_DLL_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
+DEF_DLL_FN (png_structp, png_create_read_struct,
+ (png_const_charp, png_voidp, png_error_ptr, png_error_ptr));
+DEF_DLL_FN (png_infop, png_create_info_struct, (png_structp));
+DEF_DLL_FN (void, png_destroy_read_struct,
+ (png_structpp, png_infopp, png_infopp));
+DEF_DLL_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
+DEF_DLL_FN (void, png_set_sig_bytes, (png_structp, int));
+DEF_DLL_FN (void, png_read_info, (png_structp, png_infop));
+DEF_DLL_FN (png_uint_32, png_get_IHDR,
+ (png_structp, png_infop, png_uint_32 *, png_uint_32 *,
+ int *, int *, int *, int *, int *));
+DEF_DLL_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
+DEF_DLL_FN (void, png_set_strip_16, (png_structp));
+DEF_DLL_FN (void, png_set_expand, (png_structp));
+DEF_DLL_FN (void, png_set_gray_to_rgb, (png_structp));
+DEF_DLL_FN (void, png_set_background,
+ (png_structp, png_color_16p, int, int, double));
+DEF_DLL_FN (png_uint_32, png_get_bKGD,
+ (png_structp, png_infop, png_color_16p *));
+DEF_DLL_FN (void, png_read_update_info, (png_structp, png_infop));
+DEF_DLL_FN (png_byte, png_get_channels, (png_structp, png_infop));
+DEF_DLL_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
+DEF_DLL_FN (void, png_read_image, (png_structp, png_bytepp));
+DEF_DLL_FN (void, png_read_end, (png_structp, png_infop));
+DEF_DLL_FN (void, png_error, (png_structp, png_const_charp));
+
+# if (PNG_LIBPNG_VER >= 10500)
+DEF_DLL_FN (void, png_longjmp, (png_structp, int)) PNG_NORETURN;
+DEF_DLL_FN (jmp_buf *, png_set_longjmp_fn,
+ (png_structp, png_longjmp_ptr, size_t));
+# endif /* libpng version >= 1.5 */
static bool
init_png_functions (void)
@@ -5550,87 +5527,107 @@ init_png_functions (void)
if (!(library = w32_delayed_load (Qpng)))
return 0;
- LOAD_IMGLIB_FN (library, png_get_io_ptr);
- LOAD_IMGLIB_FN (library, png_sig_cmp);
- LOAD_IMGLIB_FN (library, png_create_read_struct);
- LOAD_IMGLIB_FN (library, png_create_info_struct);
- LOAD_IMGLIB_FN (library, png_destroy_read_struct);
- LOAD_IMGLIB_FN (library, png_set_read_fn);
- LOAD_IMGLIB_FN (library, png_set_sig_bytes);
- LOAD_IMGLIB_FN (library, png_read_info);
- LOAD_IMGLIB_FN (library, png_get_IHDR);
- LOAD_IMGLIB_FN (library, png_get_valid);
- LOAD_IMGLIB_FN (library, png_set_strip_16);
- LOAD_IMGLIB_FN (library, png_set_expand);
- LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
- LOAD_IMGLIB_FN (library, png_set_background);
- LOAD_IMGLIB_FN (library, png_get_bKGD);
- LOAD_IMGLIB_FN (library, png_read_update_info);
- LOAD_IMGLIB_FN (library, png_get_channels);
- LOAD_IMGLIB_FN (library, png_get_rowbytes);
- LOAD_IMGLIB_FN (library, png_read_image);
- LOAD_IMGLIB_FN (library, png_read_end);
- LOAD_IMGLIB_FN (library, png_error);
-
-#if (PNG_LIBPNG_VER >= 10500)
- LOAD_IMGLIB_FN (library, png_longjmp);
- LOAD_IMGLIB_FN (library, png_set_longjmp_fn);
-#endif /* libpng version >= 1.5 */
+ LOAD_DLL_FN (library, png_get_io_ptr);
+ LOAD_DLL_FN (library, png_sig_cmp);
+ LOAD_DLL_FN (library, png_create_read_struct);
+ LOAD_DLL_FN (library, png_create_info_struct);
+ LOAD_DLL_FN (library, png_destroy_read_struct);
+ LOAD_DLL_FN (library, png_set_read_fn);
+ LOAD_DLL_FN (library, png_set_sig_bytes);
+ LOAD_DLL_FN (library, png_read_info);
+ LOAD_DLL_FN (library, png_get_IHDR);
+ LOAD_DLL_FN (library, png_get_valid);
+ LOAD_DLL_FN (library, png_set_strip_16);
+ LOAD_DLL_FN (library, png_set_expand);
+ LOAD_DLL_FN (library, png_set_gray_to_rgb);
+ LOAD_DLL_FN (library, png_set_background);
+ LOAD_DLL_FN (library, png_get_bKGD);
+ LOAD_DLL_FN (library, png_read_update_info);
+ LOAD_DLL_FN (library, png_get_channels);
+ LOAD_DLL_FN (library, png_get_rowbytes);
+ LOAD_DLL_FN (library, png_read_image);
+ LOAD_DLL_FN (library, png_read_end);
+ LOAD_DLL_FN (library, png_error);
+
+# if (PNG_LIBPNG_VER >= 10500)
+ LOAD_DLL_FN (library, png_longjmp);
+ LOAD_DLL_FN (library, png_set_longjmp_fn);
+# endif /* libpng version >= 1.5 */
return 1;
}
-#else
-
-#define fn_png_get_io_ptr png_get_io_ptr
-#define fn_png_sig_cmp png_sig_cmp
-#define fn_png_create_read_struct png_create_read_struct
-#define fn_png_create_info_struct png_create_info_struct
-#define fn_png_destroy_read_struct png_destroy_read_struct
-#define fn_png_set_read_fn png_set_read_fn
-#define fn_png_set_sig_bytes png_set_sig_bytes
-#define fn_png_read_info png_read_info
-#define fn_png_get_IHDR png_get_IHDR
-#define fn_png_get_valid png_get_valid
-#define fn_png_set_strip_16 png_set_strip_16
-#define fn_png_set_expand png_set_expand
-#define fn_png_set_gray_to_rgb png_set_gray_to_rgb
-#define fn_png_set_background png_set_background
-#define fn_png_get_bKGD png_get_bKGD
-#define fn_png_read_update_info png_read_update_info
-#define fn_png_get_channels png_get_channels
-#define fn_png_get_rowbytes png_get_rowbytes
-#define fn_png_read_image png_read_image
-#define fn_png_read_end png_read_end
-#define fn_png_error png_error
-
-#if (PNG_LIBPNG_VER >= 10500)
-#define fn_png_longjmp png_longjmp
-#define fn_png_set_longjmp_fn png_set_longjmp_fn
-#endif /* libpng version >= 1.5 */
-#endif /* WINDOWSNT */
+# undef png_create_info_struct
+# undef png_create_read_struct
+# undef png_destroy_read_struct
+# undef png_error
+# undef png_get_bKGD
+# undef png_get_channels
+# undef png_get_IHDR
+# undef png_get_io_ptr
+# undef png_get_rowbytes
+# undef png_get_valid
+# undef png_longjmp
+# undef png_read_end
+# undef png_read_image
+# undef png_read_info
+# undef png_read_update_info
+# undef png_set_background
+# undef png_set_expand
+# undef png_set_gray_to_rgb
+# undef png_set_longjmp_fn
+# undef png_set_read_fn
+# undef png_set_sig_bytes
+# undef png_set_strip_16
+# undef png_sig_cmp
+
+# define png_create_info_struct fn_png_create_info_struct
+# define png_create_read_struct fn_png_create_read_struct
+# define png_destroy_read_struct fn_png_destroy_read_struct
+# define png_error fn_png_error
+# define png_get_bKGD fn_png_get_bKGD
+# define png_get_channels fn_png_get_channels
+# define png_get_IHDR fn_png_get_IHDR
+# define png_get_io_ptr fn_png_get_io_ptr
+# define png_get_rowbytes fn_png_get_rowbytes
+# define png_get_valid fn_png_get_valid
+# define png_longjmp fn_png_longjmp
+# define png_read_end fn_png_read_end
+# define png_read_image fn_png_read_image
+# define png_read_info fn_png_read_info
+# define png_read_update_info fn_png_read_update_info
+# define png_set_background fn_png_set_background
+# define png_set_expand fn_png_set_expand
+# define png_set_gray_to_rgb fn_png_set_gray_to_rgb
+# define png_set_longjmp_fn fn_png_set_longjmp_fn
+# define png_set_read_fn fn_png_set_read_fn
+# define png_set_sig_bytes fn_png_set_sig_bytes
+# define png_set_strip_16 fn_png_set_strip_16
+# define png_sig_cmp fn_png_sig_cmp
+
+# endif /* WINDOWSNT */
/* Fast implementations of setjmp and longjmp. Although setjmp and longjmp
will do, POSIX _setjmp and _longjmp (if available) are often faster.
Do not use sys_setjmp, as PNG supports only jmp_buf.
It's OK if the longjmp substitute restores the signal mask. */
-#ifdef HAVE__SETJMP
-# define FAST_SETJMP(j) _setjmp (j)
-# define FAST_LONGJMP _longjmp
-#else
-# define FAST_SETJMP(j) setjmp (j)
-# define FAST_LONGJMP longjmp
-#endif
-
-#if PNG_LIBPNG_VER < 10500
-#define PNG_LONGJMP(ptr) FAST_LONGJMP ((ptr)->jmpbuf, 1)
-#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
-#else
+# ifdef HAVE__SETJMP
+# define FAST_SETJMP(j) _setjmp (j)
+# define FAST_LONGJMP _longjmp
+# else
+# define FAST_SETJMP(j) setjmp (j)
+# define FAST_LONGJMP longjmp
+# endif
+
+# if PNG_LIBPNG_VER < 10500
+# define PNG_LONGJMP(ptr) FAST_LONGJMP ((ptr)->jmpbuf, 1)
+# define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
+# else
/* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */
-#define PNG_LONGJMP(ptr) fn_png_longjmp (ptr, 1)
-#define PNG_JMPBUF(ptr) \
- (*fn_png_set_longjmp_fn (ptr, FAST_LONGJMP, sizeof (jmp_buf)))
-#endif
+# define PNG_LONGJMP(ptr) png_longjmp (ptr, 1)
+# define PNG_JMPBUF(ptr) \
+ (*png_set_longjmp_fn (ptr, FAST_LONGJMP, sizeof (jmp_buf)))
+# endif
/* Error and warning handlers installed when the PNG library
is initialized. */
@@ -5670,10 +5667,10 @@ struct png_memory_storage
static void
png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
{
- struct png_memory_storage *tbr = fn_png_get_io_ptr (png_ptr);
+ struct png_memory_storage *tbr = png_get_io_ptr (png_ptr);
if (length > tbr->len - tbr->index)
- fn_png_error (png_ptr, "Read error");
+ png_error (png_ptr, "Read error");
memcpy (data, tbr->bytes + tbr->index, length);
tbr->index = tbr->index + length;
@@ -5687,10 +5684,10 @@ png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
static void
png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
{
- FILE *fp = fn_png_get_io_ptr (png_ptr);
+ FILE *fp = png_get_io_ptr (png_ptr);
if (fread (data, 1, length, fp) < length)
- fn_png_error (png_ptr, "Read error");
+ png_error (png_ptr, "Read error");
}
@@ -5752,7 +5749,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
/* Check PNG signature. */
if (fread (sig, 1, sizeof sig, fp) != sizeof sig
- || fn_png_sig_cmp (sig, 0, sizeof sig))
+ || png_sig_cmp (sig, 0, sizeof sig))
{
fclose (fp);
image_error ("Not a PNG file: `%s'", file, Qnil);
@@ -5774,7 +5771,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
/* Check PNG signature. */
if (tbr.len < sizeof sig
- || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
+ || png_sig_cmp (tbr.bytes, 0, sizeof sig))
{
image_error ("Not a PNG image: `%s'", img->spec, Qnil);
return 0;
@@ -5785,13 +5782,13 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
}
/* Initialize read and info structs for PNG lib. */
- png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
NULL, my_png_error,
my_png_warning);
if (png_ptr)
{
- info_ptr = fn_png_create_info_struct (png_ptr);
- end_info = fn_png_create_info_struct (png_ptr);
+ info_ptr = png_create_info_struct (png_ptr);
+ end_info = png_create_info_struct (png_ptr);
}
c->png_ptr = png_ptr;
@@ -5803,7 +5800,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
if (! (info_ptr && end_info))
{
- fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+ png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
png_ptr = 0;
}
if (! png_ptr)
@@ -5818,7 +5815,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
{
error:
if (c->png_ptr)
- fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+ png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
xfree (c->pixels);
xfree (c->rows);
if (c->fp)
@@ -5831,14 +5828,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
/* Read image info. */
if (!NILP (specified_data))
- fn_png_set_read_fn (png_ptr, &tbr, png_read_from_memory);
+ png_set_read_fn (png_ptr, &tbr, png_read_from_memory);
else
- fn_png_set_read_fn (png_ptr, fp, png_read_from_file);
+ png_set_read_fn (png_ptr, fp, png_read_from_file);
- fn_png_set_sig_bytes (png_ptr, sizeof sig);
- fn_png_read_info (png_ptr, info_ptr);
- fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
+ png_set_sig_bytes (png_ptr, sizeof sig);
+ png_read_info (png_ptr, info_ptr);
+ png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ &interlace_type, NULL, NULL);
if (! (width <= INT_MAX && height <= INT_MAX
&& check_image_size (f, width, height)))
@@ -5854,7 +5851,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
/* If image contains simply transparency data, we prefer to
construct a clipping mask. */
- if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
transparent_p = 1;
else
transparent_p = 0;
@@ -5865,16 +5862,16 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
/* Strip more than 8 bits per channel. */
if (bit_depth == 16)
- fn_png_set_strip_16 (png_ptr);
+ png_set_strip_16 (png_ptr);
/* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
if available. */
- fn_png_set_expand (png_ptr);
+ png_set_expand (png_ptr);
/* Convert grayscale images to RGB. */
if (color_type == PNG_COLOR_TYPE_GRAY
|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- fn_png_set_gray_to_rgb (png_ptr);
+ png_set_gray_to_rgb (png_ptr);
/* Handle alpha channel by combining the image with a background
color. Do this only if a real alpha channel is supplied. For
@@ -5884,64 +5881,44 @@ 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;
-
- 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,
- PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+ 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;
+
+ png_set_background (png_ptr, &bg,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
}
}
/* Update info structure. */
- fn_png_read_update_info (png_ptr, info_ptr);
+ png_read_update_info (png_ptr, info_ptr);
/* Get number of channels. Valid values are 1 for grayscale images
and images with a palette, 2 for grayscale images with transparency
information (alpha channel), 3 for RGB images, and 4 for RGB
images with alpha channel, i.e. RGBA. If conversions above were
sufficient we should only have 3 or 4 channels here. */
- channels = fn_png_get_channels (png_ptr, info_ptr);
+ channels = png_get_channels (png_ptr, info_ptr);
eassert (channels == 3 || channels == 4);
/* Number of bytes needed for one row of the image. */
- row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
+ row_bytes = png_get_rowbytes (png_ptr, info_ptr);
/* Allocate memory for the image. */
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
- || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
+ if (height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows
+ || row_bytes > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height)
memory_full (SIZE_MAX);
c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
c->rows = rows = xmalloc (height * sizeof *rows);
@@ -5949,8 +5926,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
rows[i] = pixels + i * row_bytes;
/* Read the entire image. */
- fn_png_read_image (png_ptr, rows);
- fn_png_read_end (png_ptr, info_ptr);
+ png_read_image (png_ptr, rows);
+ png_read_end (png_ptr, info_ptr);
if (fp)
{
fclose (fp);
@@ -6014,21 +5991,21 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
overrode it. */
{
png_color_16 *bg;
- if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
+ if (png_get_bKGD (png_ptr, info_ptr, &bg))
{
img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
img->background_valid = 1;
}
}
-#ifdef COLOR_TABLE_SUPPORT
+# ifdef COLOR_TABLE_SUPPORT
/* Remember colors allocated for this image. */
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
+# endif /* COLOR_TABLE_SUPPORT */
/* Clean up. */
- fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+ png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
xfree (rows);
xfree (pixels);
@@ -6062,9 +6039,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 +6048,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 */
@@ -6088,10 +6062,6 @@ png_load (struct frame *f, struct image *img)
static bool jpeg_image_p (Lisp_Object object);
static bool jpeg_load (struct frame *f, struct image *img);
-/* The symbol `jpeg' identifying images of this type. */
-
-static Lisp_Object Qjpeg;
-
/* Indices of image specification fields in gs_format, below. */
enum jpeg_keyword_index
@@ -6136,7 +6106,7 @@ static bool init_jpeg_functions (void);
static struct image_type jpeg_type =
{
- &Qjpeg,
+ SYMBOL_INDEX (Qjpeg),
jpeg_image_p,
jpeg_load,
x_clear_image,
@@ -6166,15 +6136,15 @@ jpeg_image_p (Lisp_Object object)
/* Work around a warning about HAVE_STDLIB_H being redefined in
jconfig.h. */
-#ifdef HAVE_STDLIB_H
-#undef HAVE_STDLIB_H
-#endif /* HAVE_STLIB_H */
+# ifdef HAVE_STDLIB_H
+# undef HAVE_STDLIB_H
+# endif
-#if defined (HAVE_NTGUI) && !defined (__WIN32__)
+# if defined (HAVE_NTGUI) && !defined (__WIN32__)
/* In older releases of the jpeg library, jpeglib.h will define boolean
differently depending on __WIN32__, so make sure it is defined. */
-#define __WIN32__ 1
-#endif
+# define __WIN32__ 1
+# endif
/* rpcndr.h (via windows.h) and jpeglib.h both define boolean types.
Some versions of jpeglib try to detect whether rpcndr.h is loaded,
@@ -6190,23 +6160,25 @@ jpeg_image_p (Lisp_Object object)
different name. This name, jpeg_boolean, remains in effect through
the rest of image.c.
*/
-#if defined CYGWIN && defined HAVE_NTGUI
-#define boolean jpeg_boolean
-#endif
-#include <jpeglib.h>
-#include <jerror.h>
+# if defined CYGWIN && defined HAVE_NTGUI
+# define boolean jpeg_boolean
+# endif
+# include <jpeglib.h>
+# include <jerror.h>
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* JPEG library details. */
-DEF_IMGLIB_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
-DEF_IMGLIB_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
-DEF_IMGLIB_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
-DEF_IMGLIB_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
-DEF_IMGLIB_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
-DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines, (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
-DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error, (struct jpeg_error_mgr *));
-DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
+DEF_DLL_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
+DEF_DLL_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
+DEF_DLL_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
+DEF_DLL_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
+DEF_DLL_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
+DEF_DLL_FN (JDIMENSION, jpeg_read_scanlines,
+ (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
+DEF_DLL_FN (struct jpeg_error_mgr *, jpeg_std_error,
+ (struct jpeg_error_mgr *));
+DEF_DLL_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
static bool
init_jpeg_functions (void)
@@ -6216,37 +6188,46 @@ init_jpeg_functions (void)
if (!(library = w32_delayed_load (Qjpeg)))
return 0;
- LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
- LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
- LOAD_IMGLIB_FN (library, jpeg_start_decompress);
- LOAD_IMGLIB_FN (library, jpeg_read_header);
- LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
- LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
- LOAD_IMGLIB_FN (library, jpeg_std_error);
- LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
+ LOAD_DLL_FN (library, jpeg_finish_decompress);
+ LOAD_DLL_FN (library, jpeg_read_scanlines);
+ LOAD_DLL_FN (library, jpeg_start_decompress);
+ LOAD_DLL_FN (library, jpeg_read_header);
+ LOAD_DLL_FN (library, jpeg_CreateDecompress);
+ LOAD_DLL_FN (library, jpeg_destroy_decompress);
+ LOAD_DLL_FN (library, jpeg_std_error);
+ LOAD_DLL_FN (library, jpeg_resync_to_restart);
return 1;
}
+# undef jpeg_CreateDecompress
+# undef jpeg_destroy_decompress
+# undef jpeg_finish_decompress
+# undef jpeg_read_header
+# undef jpeg_read_scanlines
+# undef jpeg_resync_to_restart
+# undef jpeg_start_decompress
+# undef jpeg_std_error
+
+# define jpeg_CreateDecompress fn_jpeg_CreateDecompress
+# define jpeg_destroy_decompress fn_jpeg_destroy_decompress
+# define jpeg_finish_decompress fn_jpeg_finish_decompress
+# define jpeg_read_header fn_jpeg_read_header
+# define jpeg_read_scanlines fn_jpeg_read_scanlines
+# define jpeg_resync_to_restart fn_jpeg_resync_to_restart
+# define jpeg_start_decompress fn_jpeg_start_decompress
+# define jpeg_std_error fn_jpeg_std_error
+
/* Wrapper since we can't directly assign the function pointer
to another function pointer that was declared more completely easily. */
static boolean
jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
{
- return fn_jpeg_resync_to_restart (cinfo, desired);
+ return jpeg_resync_to_restart (cinfo, desired);
}
+# undef jpeg_resync_to_restart
+# define jpeg_resync_to_restart jpeg_resync_to_restart_wrapper
-#else
-
-#define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress (a)
-#define fn_jpeg_start_decompress jpeg_start_decompress
-#define fn_jpeg_finish_decompress jpeg_finish_decompress
-#define fn_jpeg_destroy_decompress jpeg_destroy_decompress
-#define fn_jpeg_read_header jpeg_read_header
-#define fn_jpeg_read_scanlines jpeg_read_scanlines
-#define fn_jpeg_std_error jpeg_std_error
-#define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
-
-#endif /* WINDOWSNT */
+# endif /* WINDOWSNT */
struct my_jpeg_error_mgr
{
@@ -6354,7 +6335,7 @@ jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len)
src->init_source = our_common_init_source;
src->fill_input_buffer = our_memory_fill_input_buffer;
src->skip_input_data = our_memory_skip_input_data;
- src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
+ src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
src->term_source = our_common_term_source;
src->bytes_in_buffer = len;
src->next_input_byte = data;
@@ -6460,13 +6441,12 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
src->mgr.init_source = our_common_init_source;
src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
src->mgr.skip_input_data = our_stdio_skip_input_data;
- src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
+ src->mgr.resync_to_restart = jpeg_resync_to_restart; /* Use default. */
src->mgr.term_source = our_common_term_source;
src->mgr.bytes_in_buffer = 0;
src->mgr.next_input_byte = NULL;
}
-
/* Load image IMG for use on frame F. Patterned after example.c
from the JPEG lib. */
@@ -6512,7 +6492,7 @@ jpeg_load_body (struct frame *f, struct image *img,
/* Customize libjpeg's error handling to call my_error_exit when an
error is detected. This function will perform a longjmp. */
- mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
+ mgr->cinfo.err = jpeg_std_error (&mgr->pub);
mgr->pub.error_exit = my_error_exit;
if (sys_setjmp (mgr->setjmp_buffer))
{
@@ -6538,7 +6518,7 @@ jpeg_load_body (struct frame *f, struct image *img,
/* Close the input file and destroy the JPEG object. */
if (fp)
fclose (fp);
- fn_jpeg_destroy_decompress (&mgr->cinfo);
+ jpeg_destroy_decompress (&mgr->cinfo);
/* If we already have an XImage, free that. */
x_destroy_x_image (ximg);
@@ -6550,7 +6530,7 @@ jpeg_load_body (struct frame *f, struct image *img,
/* Create the JPEG decompression object. Let it read from fp.
Read the JPEG image header. */
- fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
+ jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
if (NILP (specified_data))
jpeg_file_src (&mgr->cinfo, fp);
@@ -6558,12 +6538,12 @@ jpeg_load_body (struct frame *f, struct image *img,
jpeg_memory_src (&mgr->cinfo, SDATA (specified_data),
SBYTES (specified_data));
- fn_jpeg_read_header (&mgr->cinfo, 1);
+ jpeg_read_header (&mgr->cinfo, 1);
/* Customize decompression so that color quantization will be used.
Start decompression. */
mgr->cinfo.quantize_colors = 1;
- fn_jpeg_start_decompress (&mgr->cinfo);
+ jpeg_start_decompress (&mgr->cinfo);
width = img->width = mgr->cinfo.output_width;
height = img->height = mgr->cinfo.output_height;
@@ -6585,6 +6565,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 +6581,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)
{
@@ -6625,14 +6606,14 @@ jpeg_load_body (struct frame *f, struct image *img,
JPOOL_IMAGE, row_stride, 1);
for (y = 0; y < height; ++y)
{
- fn_jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
+ jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
for (x = 0; x < mgr->cinfo.output_width; ++x)
XPutPixel (ximg, x, y, colors[buffer[0][x]]);
}
/* Clean up. */
- fn_jpeg_finish_decompress (&mgr->cinfo);
- fn_jpeg_destroy_decompress (&mgr->cinfo);
+ jpeg_finish_decompress (&mgr->cinfo);
+ jpeg_destroy_decompress (&mgr->cinfo);
if (fp)
fclose (fp);
@@ -6643,6 +6624,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;
}
@@ -6678,10 +6660,6 @@ jpeg_load (struct frame *f, struct image *img)
static bool tiff_image_p (Lisp_Object object);
static bool tiff_load (struct frame *f, struct image *img);
-/* The symbol `tiff' identifying images of this type. */
-
-static Lisp_Object Qtiff;
-
/* Indices of image specification fields in tiff_format, below. */
enum tiff_keyword_index
@@ -6728,7 +6706,7 @@ static bool init_tiff_functions (void);
static struct image_type tiff_type =
{
- &Qtiff,
+ SYMBOL_INDEX (Qtiff),
tiff_image_p,
tiff_load,
x_clear_image,
@@ -6755,22 +6733,22 @@ tiff_image_p (Lisp_Object object)
#ifdef HAVE_TIFF
-#include <tiffio.h>
+# include <tiffio.h>
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* TIFF library details. */
-DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
-DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
-DEF_IMGLIB_FN (TIFF *, TIFFOpen, (const char *, const char *));
-DEF_IMGLIB_FN (TIFF *, TIFFClientOpen, (const char *, const char *, thandle_t,
- TIFFReadWriteProc, TIFFReadWriteProc,
- TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
- TIFFMapFileProc, TIFFUnmapFileProc));
-DEF_IMGLIB_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
-DEF_IMGLIB_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
-DEF_IMGLIB_FN (void, TIFFClose, (TIFF *));
-DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
+DEF_DLL_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
+DEF_DLL_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
+DEF_DLL_FN (TIFF *, TIFFOpen, (const char *, const char *));
+DEF_DLL_FN (TIFF *, TIFFClientOpen,
+ (const char *, const char *, thandle_t, TIFFReadWriteProc,
+ TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
+ TIFFMapFileProc, TIFFUnmapFileProc));
+DEF_DLL_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
+DEF_DLL_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
+DEF_DLL_FN (void, TIFFClose, (TIFF *));
+DEF_DLL_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
static bool
init_tiff_functions (void)
@@ -6780,28 +6758,36 @@ init_tiff_functions (void)
if (!(library = w32_delayed_load (Qtiff)))
return 0;
- LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
- LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
- LOAD_IMGLIB_FN (library, TIFFOpen);
- LOAD_IMGLIB_FN (library, TIFFClientOpen);
- LOAD_IMGLIB_FN (library, TIFFGetField);
- LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
- LOAD_IMGLIB_FN (library, TIFFClose);
- LOAD_IMGLIB_FN (library, TIFFSetDirectory);
+ LOAD_DLL_FN (library, TIFFSetErrorHandler);
+ LOAD_DLL_FN (library, TIFFSetWarningHandler);
+ LOAD_DLL_FN (library, TIFFOpen);
+ LOAD_DLL_FN (library, TIFFClientOpen);
+ LOAD_DLL_FN (library, TIFFGetField);
+ LOAD_DLL_FN (library, TIFFReadRGBAImage);
+ LOAD_DLL_FN (library, TIFFClose);
+ LOAD_DLL_FN (library, TIFFSetDirectory);
return 1;
}
-#else
+# undef TIFFClientOpen
+# undef TIFFClose
+# undef TIFFGetField
+# undef TIFFOpen
+# undef TIFFReadRGBAImage
+# undef TIFFSetDirectory
+# undef TIFFSetErrorHandler
+# undef TIFFSetWarningHandler
-#define fn_TIFFSetErrorHandler TIFFSetErrorHandler
-#define fn_TIFFSetWarningHandler TIFFSetWarningHandler
-#define fn_TIFFOpen TIFFOpen
-#define fn_TIFFClientOpen TIFFClientOpen
-#define fn_TIFFGetField TIFFGetField
-#define fn_TIFFReadRGBAImage TIFFReadRGBAImage
-#define fn_TIFFClose TIFFClose
-#define fn_TIFFSetDirectory TIFFSetDirectory
-#endif /* WINDOWSNT */
+# define TIFFClientOpen fn_TIFFClientOpen
+# define TIFFClose fn_TIFFClose
+# define TIFFGetField fn_TIFFGetField
+# define TIFFOpen fn_TIFFOpen
+# define TIFFReadRGBAImage fn_TIFFReadRGBAImage
+# define TIFFSetDirectory fn_TIFFSetDirectory
+# define TIFFSetErrorHandler fn_TIFFSetErrorHandler
+# define TIFFSetWarningHandler fn_TIFFSetWarningHandler
+
+# endif /* WINDOWSNT */
/* Reading from a memory buffer for TIFF images Based on the PNG
@@ -6899,11 +6885,11 @@ tiff_size_of_memory (thandle_t data)
compiler error compiling tiff_handler, see Bugzilla bug #17406
(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406). Declaring
this function as external works around that problem. */
-#if defined (__MINGW32__) && __GNUC__ == 3
-# define MINGW_STATIC
-#else
-# define MINGW_STATIC static
-#endif
+# if defined (__MINGW32__) && __GNUC__ == 3
+# define MINGW_STATIC
+# else
+# define MINGW_STATIC static
+# endif
MINGW_STATIC void
tiff_handler (const char *, const char *, const char *, va_list)
@@ -6922,7 +6908,7 @@ tiff_handler (const char *log_format, const char *title,
add_to_log (log_format, build_string (title),
make_string (buf, max (0, min (len, sizeof buf - 1))));
}
-#undef MINGW_STATIC
+# undef MINGW_STATIC
static void tiff_error_handler (const char *, const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (2, 0);
@@ -6961,8 +6947,8 @@ tiff_load (struct frame *f, struct image *img)
specified_file = image_spec_value (img->spec, QCfile, NULL);
specified_data = image_spec_value (img->spec, QCdata, NULL);
- fn_TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
- fn_TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
+ TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
+ TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
if (NILP (specified_data))
{
@@ -6973,12 +6959,12 @@ tiff_load (struct frame *f, struct image *img)
image_error ("Cannot find image file `%s'", specified_file, Qnil);
return 0;
}
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
file = ansi_encode_filename (file);
-#endif
+# endif
/* Try to open the image file. */
- tiff = fn_TIFFOpen (SSDATA (file), "r");
+ tiff = TIFFOpen (SSDATA (file), "r");
if (tiff == NULL)
{
image_error ("Cannot open `%s'", file, Qnil);
@@ -6998,14 +6984,14 @@ tiff_load (struct frame *f, struct image *img)
memsrc.len = SBYTES (specified_data);
memsrc.index = 0;
- tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
- tiff_read_from_memory,
- tiff_write_from_memory,
- tiff_seek_in_memory,
- tiff_close_memory,
- tiff_size_of_memory,
- tiff_mmap_memory,
- tiff_unmap_memory);
+ tiff = TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
+ tiff_read_from_memory,
+ tiff_write_from_memory,
+ tiff_seek_in_memory,
+ tiff_close_memory,
+ tiff_size_of_memory,
+ tiff_mmap_memory,
+ tiff_unmap_memory);
if (!tiff)
{
@@ -7019,24 +7005,24 @@ tiff_load (struct frame *f, struct image *img)
{
EMACS_INT ino = XFASTINT (image);
if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
- && fn_TIFFSetDirectory (tiff, ino)))
+ && TIFFSetDirectory (tiff, ino)))
{
image_error ("Invalid image number `%s' in image `%s'",
image, img->spec);
- fn_TIFFClose (tiff);
+ TIFFClose (tiff);
return 0;
}
}
/* Get width and height of the image, and allocate a raster buffer
of width x height 32-bit values. */
- fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
- fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
+ TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
+ TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
if (!check_image_size (f, width, height))
{
image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
- fn_TIFFClose (tiff);
+ TIFFClose (tiff);
return 0;
}
@@ -7045,16 +7031,16 @@ tiff_load (struct frame *f, struct image *img)
&& image_create_x_image_and_pixmap (f, img, width, height, 0,
&ximg, 0)))
{
- fn_TIFFClose (tiff);
+ TIFFClose (tiff);
return 0;
}
buf = xmalloc (sizeof *buf * width * height);
- rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
+ rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
/* Count the number of images in the file. */
- for (count = 1; fn_TIFFSetDirectory (tiff, count); count++)
+ for (count = 1; TIFFSetDirectory (tiff, count); count++)
continue;
if (count > 1)
@@ -7062,7 +7048,7 @@ tiff_load (struct frame *f, struct image *img)
Fcons (make_number (count),
img->lisp_data));
- fn_TIFFClose (tiff);
+ TIFFClose (tiff);
if (!rc)
{
image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
@@ -7088,11 +7074,11 @@ tiff_load (struct frame *f, struct image *img)
}
}
-#ifdef COLOR_TABLE_SUPPORT
+# ifdef COLOR_TABLE_SUPPORT
/* Remember the colors allocated for the image. Free the color table. */
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
+# endif /* COLOR_TABLE_SUPPORT */
img->width = width;
img->height = height;
@@ -7109,9 +7095,8 @@ tiff_load (struct frame *f, struct image *img)
return 1;
}
-#else /* HAVE_TIFF */
+#elif defined HAVE_NS
-#ifdef HAVE_NS
static bool
tiff_load (struct frame *f, struct image *img)
{
@@ -7119,9 +7104,8 @@ tiff_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_TIFF */
+#endif
@@ -7135,10 +7119,6 @@ static bool gif_image_p (Lisp_Object object);
static bool gif_load (struct frame *f, struct image *img);
static void gif_clear_image (struct frame *f, struct image *img);
-/* The symbol `gif' identifying images of this type. */
-
-static Lisp_Object Qgif;
-
/* Indices of image specification fields in gif_format, below. */
enum gif_keyword_index
@@ -7185,7 +7165,7 @@ static bool init_gif_functions (void);
static struct image_type gif_type =
{
- &Qgif,
+ SYMBOL_INDEX (Qgif),
gif_image_p,
gif_load,
gif_clear_image,
@@ -7221,54 +7201,54 @@ gif_image_p (Lisp_Object object)
#ifdef HAVE_GIF
-#if defined (HAVE_NTGUI)
+# ifdef HAVE_NTGUI
/* winuser.h might define DrawText to DrawTextA or DrawTextW.
Undefine before redefining to avoid a preprocessor warning. */
-#ifdef DrawText
-#undef DrawText
-#endif
+# ifdef DrawText
+# undef DrawText
+# endif
/* avoid conflict with QuickdrawText.h */
-#define DrawText gif_DrawText
-#include <gif_lib.h>
-#undef DrawText
+# define DrawText gif_DrawText
+# include <gif_lib.h>
+# undef DrawText
/* Giflib before 5.0 didn't define these macros (used only if HAVE_NTGUI). */
-#ifndef GIFLIB_MINOR
-#define GIFLIB_MINOR 0
-#endif
-#ifndef GIFLIB_RELEASE
-#define GIFLIB_RELEASE 0
-#endif
+# ifndef GIFLIB_MINOR
+# define GIFLIB_MINOR 0
+# endif
+# ifndef GIFLIB_RELEASE
+# define GIFLIB_RELEASE 0
+# endif
-#else /* HAVE_NTGUI */
+# else /* HAVE_NTGUI */
-#include <gif_lib.h>
+# include <gif_lib.h>
-#endif /* HAVE_NTGUI */
+# endif /* HAVE_NTGUI */
/* Giflib before 5.0 didn't define these macros. */
-#ifndef GIFLIB_MAJOR
-#define GIFLIB_MAJOR 4
-#endif
+# ifndef GIFLIB_MAJOR
+# define GIFLIB_MAJOR 4
+# endif
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* GIF library details. */
-#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
-DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *, int *));
-#else
-DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *));
-#endif
-DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *));
-#if GIFLIB_MAJOR < 5
-DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc));
-DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *));
-#else
-DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc, int *));
-DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *, int *));
-DEF_IMGLIB_FN (char *, GifErrorString, (int));
-#endif
+# if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
+DEF_DLL_FN (int, DGifCloseFile, (GifFileType *, int *));
+# else
+DEF_DLL_FN (int, DGifCloseFile, (GifFileType *));
+# endif
+DEF_DLL_FN (int, DGifSlurp, (GifFileType *));
+# if GIFLIB_MAJOR < 5
+DEF_DLL_FN (GifFileType *, DGifOpen, (void *, InputFunc));
+DEF_DLL_FN (GifFileType *, DGifOpenFileName, (const char *));
+# else
+DEF_DLL_FN (GifFileType *, DGifOpen, (void *, InputFunc, int *));
+DEF_DLL_FN (GifFileType *, DGifOpenFileName, (const char *, int *));
+DEF_DLL_FN (char *, GifErrorString, (int));
+# endif
static bool
init_gif_functions (void)
@@ -7278,27 +7258,29 @@ init_gif_functions (void)
if (!(library = w32_delayed_load (Qgif)))
return 0;
- LOAD_IMGLIB_FN (library, DGifCloseFile);
- LOAD_IMGLIB_FN (library, DGifSlurp);
- LOAD_IMGLIB_FN (library, DGifOpen);
- LOAD_IMGLIB_FN (library, DGifOpenFileName);
-#if GIFLIB_MAJOR >= 5
- LOAD_IMGLIB_FN (library, GifErrorString);
-#endif
+ LOAD_DLL_FN (library, DGifCloseFile);
+ LOAD_DLL_FN (library, DGifSlurp);
+ LOAD_DLL_FN (library, DGifOpen);
+ LOAD_DLL_FN (library, DGifOpenFileName);
+# if GIFLIB_MAJOR >= 5
+ LOAD_DLL_FN (library, GifErrorString);
+# endif
return 1;
}
-#else
+# undef DGifCloseFile
+# undef DGifOpen
+# undef DGifOpenFileName
+# undef DGifSlurp
+# undef GifErrorString
-#define fn_DGifCloseFile DGifCloseFile
-#define fn_DGifSlurp DGifSlurp
-#define fn_DGifOpen DGifOpen
-#define fn_DGifOpenFileName DGifOpenFileName
-#if 5 <= GIFLIB_MAJOR
-# define fn_GifErrorString GifErrorString
-#endif
+# define DGifCloseFile fn_DGifCloseFile
+# define DGifOpen fn_DGifOpen
+# define DGifOpenFileName fn_DGifOpenFileName
+# define DGifSlurp fn_DGifSlurp
+# define GifErrorString fn_GifErrorString
-#endif /* WINDOWSNT */
+# endif /* WINDOWSNT */
/* Reading a GIF image from memory
Based on the PNG memory stuff to a certain extent. */
@@ -7334,10 +7316,10 @@ gif_close (GifFileType *gif, int *err)
{
int retval;
-#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
- retval = fn_DGifCloseFile (gif, err);
+#if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
+ retval = DGifCloseFile (gif, err);
#else
- retval = fn_DGifCloseFile (gif);
+ retval = DGifCloseFile (gif);
#if GIFLIB_MAJOR >= 5
if (err)
*err = gif->Error;
@@ -7385,18 +7367,18 @@ gif_load (struct frame *f, struct image *img)
/* Open the GIF file. */
#if GIFLIB_MAJOR < 5
- gif = fn_DGifOpenFileName (SSDATA (file));
+ gif = DGifOpenFileName (SSDATA (file));
if (gif == NULL)
{
image_error ("Cannot open `%s'", file, Qnil);
return 0;
}
#else
- gif = fn_DGifOpenFileName (SSDATA (file), &gif_err);
+ gif = DGifOpenFileName (SSDATA (file), &gif_err);
if (gif == NULL)
{
image_error ("Cannot open `%s': %s",
- file, build_string (fn_GifErrorString (gif_err)));
+ file, build_string (GifErrorString (gif_err)));
return 0;
}
#endif
@@ -7416,18 +7398,18 @@ gif_load (struct frame *f, struct image *img)
memsrc.index = 0;
#if GIFLIB_MAJOR < 5
- gif = fn_DGifOpen (&memsrc, gif_read_from_memory);
+ gif = DGifOpen (&memsrc, gif_read_from_memory);
if (!gif)
{
image_error ("Cannot open memory source `%s'", img->spec, Qnil);
return 0;
}
#else
- gif = fn_DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
+ gif = DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
if (!gif)
{
image_error ("Cannot open memory source `%s': %s",
- img->spec, build_string (fn_GifErrorString (gif_err)));
+ img->spec, build_string (GifErrorString (gif_err)));
return 0;
}
#endif
@@ -7442,7 +7424,7 @@ gif_load (struct frame *f, struct image *img)
}
/* Read entire contents. */
- rc = fn_DGifSlurp (gif);
+ rc = DGifSlurp (gif);
if (rc == GIF_ERROR || gif->ImageCount <= 0)
{
image_error ("Error reading `%s'", img->spec, Qnil);
@@ -7489,7 +7471,7 @@ gif_load (struct frame *f, struct image *img)
int subimg_height = subimage->ImageDesc.Height;
int subimg_top = subimage->ImageDesc.Top;
int subimg_left = subimage->ImageDesc.Left;
- if (! (0 <= subimg_width && 0 <= subimg_height
+ if (! (subimg_width >= 0 && subimg_height >= 0
&& 0 <= subimg_top && subimg_top <= height - subimg_height
&& 0 <= subimg_left && subimg_left <= width - subimg_width))
{
@@ -7676,7 +7658,7 @@ gif_load (struct frame *f, struct image *img)
if (gif_close (gif, &gif_err) == GIF_ERROR)
{
#if 5 <= GIFLIB_MAJOR
- char *error_text = fn_GifErrorString (gif_err);
+ char *error_text = GifErrorString (gif_err);
if (error_text)
image_error ("Error closing `%s': %s",
@@ -7807,8 +7789,6 @@ compute_image_size (size_t width, size_t height,
*d_height = desired_height;
}
-static Lisp_Object Qimagemagick;
-
static bool imagemagick_image_p (Lisp_Object);
static bool imagemagick_load (struct frame *, struct image *);
static void imagemagick_clear_image (struct frame *, struct image *);
@@ -7872,7 +7852,7 @@ static bool init_imagemagick_functions (void);
static struct image_type imagemagick_type =
{
- &Qimagemagick,
+ SYMBOL_INDEX (Qimagemagick),
imagemagick_image_p,
imagemagick_load,
imagemagick_clear_image,
@@ -8064,7 +8044,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 +8112,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 +8157,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 +8243,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 +8334,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 +8398,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 +8431,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 +8544,6 @@ and `imagemagick-types-inhibit'. */)
ExceptionInfo ex;
char **imtypes;
size_t i;
- Lisp_Object Qimagemagicktype;
GetExceptionInfo(&ex);
imtypes = GetMagickList ("*", &numf, &ex);
@@ -8574,8 +8551,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]);
}
@@ -8591,7 +8568,7 @@ and `imagemagick-types-inhibit'. */)
SVG
***********************************************************************/
-#if defined (HAVE_RSVG)
+#ifdef HAVE_RSVG
/* Function prototypes. */
@@ -8599,11 +8576,7 @@ static bool svg_image_p (Lisp_Object object);
static bool svg_load (struct frame *f, struct image *img);
static bool svg_load_image (struct frame *, struct image *,
- unsigned char *, ptrdiff_t);
-
-/* The symbol `svg' identifying images of this type. */
-
-static Lisp_Object Qsvg;
+ unsigned char *, ptrdiff_t, char *);
/* Indices of image specification fields in svg_format, below. */
@@ -8639,11 +8612,11 @@ static const struct image_keyword svg_format[SVG_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
-#if defined HAVE_NTGUI && defined WINDOWSNT
+# if defined HAVE_NTGUI && defined WINDOWSNT
static bool init_svg_functions (void);
-#else
+# else
#define init_svg_functions NULL
-#endif
+# endif
/* Structure describing the image type `svg'. Its the same type of
structure defined for all image formats, handled by emacs image
@@ -8651,7 +8624,7 @@ static bool init_svg_functions (void);
static struct image_type svg_type =
{
- &Qsvg,
+ SYMBOL_INDEX (Qsvg),
svg_image_p,
svg_load,
x_clear_image,
@@ -8677,94 +8650,116 @@ svg_image_p (Lisp_Object object)
return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
}
-#include <librsvg/rsvg.h>
+# include <librsvg/rsvg.h>
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* SVG library functions. */
-DEF_IMGLIB_FN (RsvgHandle *, rsvg_handle_new, (void));
-DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions, (RsvgHandle *, RsvgDimensionData *));
-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 *));
-DEF_IMGLIB_FN (guchar *, gdk_pixbuf_get_pixels, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_rowstride, (const GdkPixbuf *));
-DEF_IMGLIB_FN (GdkColorspace, gdk_pixbuf_get_colorspace, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_n_channels, (const GdkPixbuf *));
-DEF_IMGLIB_FN (gboolean, gdk_pixbuf_get_has_alpha, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_bits_per_sample, (const GdkPixbuf *));
-
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
-DEF_IMGLIB_FN (void, g_type_init, (void));
-#endif
-DEF_IMGLIB_FN (void, g_object_unref, (gpointer));
-DEF_IMGLIB_FN (void, g_error_free, (GError *));
-
-Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
+DEF_DLL_FN (RsvgHandle *, rsvg_handle_new, (void));
+DEF_DLL_FN (void, rsvg_handle_get_dimensions,
+ (RsvgHandle *, RsvgDimensionData *));
+DEF_DLL_FN (gboolean, rsvg_handle_write,
+ (RsvgHandle *, const guchar *, gsize, GError **));
+DEF_DLL_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **));
+DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *));
+DEF_DLL_FN (void, rsvg_handle_set_base_uri, (RsvgHandle *, const char *));
+
+DEF_DLL_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_height, (const GdkPixbuf *));
+DEF_DLL_FN (guchar *, gdk_pixbuf_get_pixels, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_rowstride, (const GdkPixbuf *));
+DEF_DLL_FN (GdkColorspace, gdk_pixbuf_get_colorspace, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_n_channels, (const GdkPixbuf *));
+DEF_DLL_FN (gboolean, gdk_pixbuf_get_has_alpha, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_bits_per_sample, (const GdkPixbuf *));
+
+# if ! GLIB_CHECK_VERSION (2, 36, 0)
+DEF_DLL_FN (void, g_type_init, (void));
+# endif
+DEF_DLL_FN (void, g_object_unref, (gpointer));
+DEF_DLL_FN (void, g_error_free, (GError *));
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);
- LOAD_IMGLIB_FN (library, rsvg_handle_write);
- LOAD_IMGLIB_FN (library, rsvg_handle_close);
- LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
-
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
- LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
-
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
- LOAD_IMGLIB_FN (gobject, g_type_init);
-#endif
- LOAD_IMGLIB_FN (gobject, g_object_unref);
- LOAD_IMGLIB_FN (glib, g_error_free);
+ LOAD_DLL_FN (library, rsvg_handle_new);
+ LOAD_DLL_FN (library, rsvg_handle_get_dimensions);
+ LOAD_DLL_FN (library, rsvg_handle_write);
+ LOAD_DLL_FN (library, rsvg_handle_close);
+ LOAD_DLL_FN (library, rsvg_handle_get_pixbuf);
+ LOAD_DLL_FN (library, rsvg_handle_set_base_uri);
+
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_width);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_height);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_pixels);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_rowstride);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_colorspace);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_n_channels);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_has_alpha);
+ LOAD_DLL_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
+
+# if ! GLIB_CHECK_VERSION (2, 36, 0)
+ LOAD_DLL_FN (gobject, g_type_init);
+# endif
+ LOAD_DLL_FN (gobject, g_object_unref);
+ LOAD_DLL_FN (glib, g_error_free);
return 1;
}
-#else
/* The following aliases for library functions allow dynamic loading
to be used on some platforms. */
-#define fn_rsvg_handle_new rsvg_handle_new
-#define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
-#define fn_rsvg_handle_write rsvg_handle_write
-#define fn_rsvg_handle_close rsvg_handle_close
-#define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
-
-#define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
-#define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
-#define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
-#define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
-#define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
-#define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
-#define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
-#define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
-#define fn_g_type_init g_type_init
-#endif
-#define fn_g_object_unref g_object_unref
-#define fn_g_error_free g_error_free
-#endif /* !WINDOWSNT */
+# undef gdk_pixbuf_get_bits_per_sample
+# undef gdk_pixbuf_get_colorspace
+# undef gdk_pixbuf_get_has_alpha
+# undef gdk_pixbuf_get_height
+# undef gdk_pixbuf_get_n_channels
+# undef gdk_pixbuf_get_pixels
+# undef gdk_pixbuf_get_rowstride
+# undef gdk_pixbuf_get_width
+# undef g_error_free
+# undef g_object_unref
+# undef g_type_init
+# undef rsvg_handle_close
+# undef rsvg_handle_get_dimensions
+# undef rsvg_handle_get_pixbuf
+# undef rsvg_handle_new
+# undef rsvg_handle_set_base_uri
+# undef rsvg_handle_write
+
+# define gdk_pixbuf_get_bits_per_sample fn_gdk_pixbuf_get_bits_per_sample
+# define gdk_pixbuf_get_colorspace fn_gdk_pixbuf_get_colorspace
+# define gdk_pixbuf_get_has_alpha fn_gdk_pixbuf_get_has_alpha
+# define gdk_pixbuf_get_height fn_gdk_pixbuf_get_height
+# define gdk_pixbuf_get_n_channels fn_gdk_pixbuf_get_n_channels
+# define gdk_pixbuf_get_pixels fn_gdk_pixbuf_get_pixels
+# define gdk_pixbuf_get_rowstride fn_gdk_pixbuf_get_rowstride
+# define gdk_pixbuf_get_width fn_gdk_pixbuf_get_width
+# define g_error_free fn_g_error_free
+# define g_object_unref fn_g_object_unref
+# define g_type_init fn_g_type_init
+# define rsvg_handle_close fn_rsvg_handle_close
+# define rsvg_handle_get_dimensions fn_rsvg_handle_get_dimensions
+# define rsvg_handle_get_pixbuf fn_rsvg_handle_get_pixbuf
+# define rsvg_handle_new fn_rsvg_handle_new
+# define rsvg_handle_set_base_uri fn_rsvg_handle_set_base_uri
+# define rsvg_handle_write fn_rsvg_handle_write
+
+# endif /* !WINDOWSNT */
/* Load SVG image IMG for use on frame F. Value is true if
successful. */
@@ -8798,14 +8793,14 @@ svg_load (struct frame *f, struct image *img)
return 0;
}
/* If the file was slurped into memory properly, parse it. */
- success_p = svg_load_image (f, img, contents, size);
+ success_p = svg_load_image (f, img, contents, size, SSDATA (file));
xfree (contents);
}
/* Else its not a file, its a lisp object. Load the image from a
lisp object rather than a file. */
else
{
- Lisp_Object data;
+ Lisp_Object data, original_filename;
data = image_spec_value (img->spec, QCdata, NULL);
if (!STRINGP (data))
@@ -8813,7 +8808,10 @@ svg_load (struct frame *f, struct image *img)
image_error ("Invalid image data `%s'", data, Qnil);
return 0;
}
- success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
+ original_filename = BVAR (current_buffer, filename);
+ success_p = svg_load_image (f, img, SDATA (data), SBYTES (data),
+ (NILP (original_filename) ? NULL
+ : SSDATA (original_filename)));
}
return success_p;
@@ -8830,7 +8828,8 @@ static bool
svg_load_image (struct frame *f, /* Pointer to emacs frame structure. */
struct image *img, /* Pointer to emacs image structure. */
unsigned char *contents, /* String containing the SVG XML data to be parsed. */
- ptrdiff_t size) /* Size of data in bytes. */
+ ptrdiff_t size, /* Size of data in bytes. */
+ char *filename) /* Name of SVG file being loaded. */
{
RsvgHandle *rsvg_handle;
RsvgDimensionData dimension_data;
@@ -8849,22 +8848,28 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
#if ! GLIB_CHECK_VERSION (2, 36, 0)
/* g_type_init is a glib function that must be called prior to
using gnome type library functions (obsolete since 2.36.0). */
- fn_g_type_init ();
+ g_type_init ();
#endif
/* Make a handle to a new rsvg object. */
- rsvg_handle = fn_rsvg_handle_new ();
+ rsvg_handle = rsvg_handle_new ();
+
+ /* Set base_uri for properly handling referenced images (via 'href').
+ See rsvg bug 596114 - "image refs are relative to curdir, not .svg file"
+ (https://bugzilla.gnome.org/show_bug.cgi?id=596114). */
+ if (filename)
+ rsvg_handle_set_base_uri(rsvg_handle, filename);
/* Parse the contents argument and fill in the rsvg_handle. */
- fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
+ rsvg_handle_write (rsvg_handle, contents, size, &err);
if (err) goto rsvg_error;
/* The parsing is complete, rsvg_handle is ready to used, close it
for further writes. */
- fn_rsvg_handle_close (rsvg_handle, &err);
+ rsvg_handle_close (rsvg_handle, &err);
if (err) goto rsvg_error;
- fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
+ rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
if (! check_image_size (f, dimension_data.width, dimension_data.height))
{
image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
@@ -8873,26 +8878,26 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
/* We can now get a valid pixel buffer from the svg file, if all
went ok. */
- pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
+ pixbuf = rsvg_handle_get_pixbuf (rsvg_handle);
if (!pixbuf) goto rsvg_error;
- fn_g_object_unref (rsvg_handle);
+ g_object_unref (rsvg_handle);
/* Extract some meta data from the svg handle. */
- width = fn_gdk_pixbuf_get_width (pixbuf);
- height = fn_gdk_pixbuf_get_height (pixbuf);
- pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
- rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
/* Validate the svg meta data. */
- eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
- eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
- eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
- eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
+ eassert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
+ eassert (gdk_pixbuf_get_n_channels (pixbuf) == 4);
+ eassert (gdk_pixbuf_get_has_alpha (pixbuf));
+ eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
/* Try to create a x pixmap to hold the svg pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
- fn_g_object_unref (pixbuf);
+ g_object_unref (pixbuf);
return 0;
}
@@ -8903,14 +8908,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
@@ -8956,7 +8954,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
free_color_table ();
#endif /* COLOR_TABLE_SUPPORT */
- fn_g_object_unref (pixbuf);
+ g_object_unref (pixbuf);
img->width = width;
img->height = height;
@@ -8971,11 +8969,11 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
return 1;
rsvg_error:
- fn_g_object_unref (rsvg_handle);
+ g_object_unref (rsvg_handle);
/* FIXME: Use error->message so the user knows what is the actual
problem with the image. */
image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
- fn_g_error_free (err);
+ g_error_free (err);
return 0;
}
@@ -8998,10 +8996,6 @@ static bool gs_image_p (Lisp_Object object);
static bool gs_load (struct frame *f, struct image *img);
static void gs_clear_image (struct frame *f, struct image *img);
-/* Keyword symbols. */
-
-static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
-
/* Indices of image specification fields in gs_format, below. */
enum gs_keyword_index
@@ -9046,7 +9040,7 @@ static const struct image_keyword gs_format[GS_LAST] =
static struct image_type gs_type =
{
- &Qpostscript,
+ SYMBOL_INDEX (Qpostscript),
gs_image_p,
gs_load,
gs_clear_image,
@@ -9294,7 +9288,8 @@ DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
}
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
+DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0,
+ doc: /* */)
(Lisp_Object spec)
{
ptrdiff_t id = -1;
@@ -9421,10 +9416,12 @@ as a ratio to the frame height and width. If the value is
non-numeric, there is no explicit limit on the size of images. */);
Vmax_image_size = make_float (MAX_IMAGE_SIZE);
+ /* Other symbols. */
DEFSYM (Qcount, "count");
DEFSYM (Qextension_data, "extension-data");
DEFSYM (Qdelay, "delay");
+ /* Keywords. */
DEFSYM (QCascent, ":ascent");
DEFSYM (QCmargin, ":margin");
DEFSYM (QCrelief, ":relief");
@@ -9439,6 +9436,7 @@ non-numeric, there is no explicit limit on the size of images. */);
DEFSYM (QCcolor_adjustment, ":color-adjustment");
DEFSYM (QCmask, ":mask");
+ /* Other symbols. */
DEFSYM (Qlaplace, "laplace");
DEFSYM (Qemboss, "emboss");
DEFSYM (Qedge_detection, "edge-detection");
@@ -9456,6 +9454,10 @@ non-numeric, there is no explicit limit on the size of images. */);
#endif /* HAVE_GHOSTSCRIPT */
#ifdef HAVE_NTGUI
+ /* Versions of libpng, libgif, and libjpeg that we were compiled with,
+ or -1 if no PNG/GIF support was compiled in. This is tested by
+ w32-win.el to correctly set up the alist used to search for the
+ respective image libraries. */
DEFSYM (Qlibpng_version, "libpng-version");
Fset (Qlibpng_version,
#if HAVE_PNG
diff --git a/src/indent.c b/src/indent.c
index 8b6ecd16a67..589aeb9c005 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -439,7 +439,7 @@ current_column (void)
/* With a display table entry, C is displayed as is, and
not displayed as \NNN or as ^N. If C is a single-byte
character, it takes one column. If C is multi-byte in
- an unibyte buffer, it's translated to unibyte, so it
+ a unibyte buffer, it's translated to unibyte, so it
also takes one column. */
++col;
else
@@ -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/inotify.c b/src/inotify.c
index 8e8ab202c41..eddad73e8f7 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -29,34 +29,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "frame.h" /* Required for termhooks.h. */
#include "termhooks.h"
-static Lisp_Object Qaccess; /* IN_ACCESS */
-static Lisp_Object Qattrib; /* IN_ATTRIB */
-static Lisp_Object Qclose_write; /* IN_CLOSE_WRITE */
-static Lisp_Object Qclose_nowrite; /* IN_CLOSE_NOWRITE */
-static Lisp_Object Qcreate; /* IN_CREATE */
-static Lisp_Object Qdelete; /* IN_DELETE */
-static Lisp_Object Qdelete_self; /* IN_DELETE_SELF */
-static Lisp_Object Qmodify; /* IN_MODIFY */
-static Lisp_Object Qmove_self; /* IN_MOVE_SELF */
-static Lisp_Object Qmoved_from; /* IN_MOVED_FROM */
-static Lisp_Object Qmoved_to; /* IN_MOVED_TO */
-static Lisp_Object Qopen; /* IN_OPEN */
-
-static Lisp_Object Qall_events; /* IN_ALL_EVENTS */
-static Lisp_Object Qmove; /* IN_MOVE */
-static Lisp_Object Qclose; /* IN_CLOSE */
-
-static Lisp_Object Qdont_follow; /* IN_DONT_FOLLOW */
-static Lisp_Object Qexcl_unlink; /* IN_EXCL_UNLINK */
-static Lisp_Object Qmask_add; /* IN_MASK_ADD */
-static Lisp_Object Qoneshot; /* IN_ONESHOT */
-static Lisp_Object Qonlydir; /* IN_ONLYDIR */
-
-static Lisp_Object Qignored; /* IN_IGNORED */
-static Lisp_Object Qisdir; /* IN_ISDIR */
-static Lisp_Object Qq_overflow; /* IN_Q_OVERFLOW */
-static Lisp_Object Qunmount; /* IN_UNMOUNT */
-
#include <sys/inotify.h>
#include <sys/ioctl.h>
@@ -398,33 +370,34 @@ See inotify_rm_watch(2) for more information.
void
syms_of_inotify (void)
{
- DEFSYM (Qaccess, "access");
- DEFSYM (Qattrib, "attrib");
- DEFSYM (Qclose_write, "close-write");
+ DEFSYM (Qaccess, "access"); /* IN_ACCESS */
+ DEFSYM (Qattrib, "attrib"); /* IN_ATTRIB */
+ DEFSYM (Qclose_write, "close-write"); /* IN_CLOSE_WRITE */
DEFSYM (Qclose_nowrite, "close-nowrite");
- DEFSYM (Qcreate, "create");
- DEFSYM (Qdelete, "delete");
- DEFSYM (Qdelete_self, "delete-self");
- DEFSYM (Qmodify, "modify");
- DEFSYM (Qmove_self, "move-self");
- DEFSYM (Qmoved_from, "moved-from");
- DEFSYM (Qmoved_to, "moved-to");
- DEFSYM (Qopen, "open");
-
- DEFSYM (Qall_events, "all-events");
- DEFSYM (Qmove, "move");
- DEFSYM (Qclose, "close");
-
- DEFSYM (Qdont_follow, "dont-follow");
- DEFSYM (Qexcl_unlink, "excl-unlink");
- DEFSYM (Qmask_add, "mask-add");
- DEFSYM (Qoneshot, "oneshot");
- DEFSYM (Qonlydir, "onlydir");
-
- DEFSYM (Qignored, "ignored");
- DEFSYM (Qisdir, "isdir");
- DEFSYM (Qq_overflow, "q-overflow");
- DEFSYM (Qunmount, "unmount");
+ /* IN_CLOSE_NOWRITE */
+ DEFSYM (Qcreate, "create"); /* IN_CREATE */
+ DEFSYM (Qdelete, "delete"); /* IN_DELETE */
+ DEFSYM (Qdelete_self, "delete-self"); /* IN_DELETE_SELF */
+ DEFSYM (Qmodify, "modify"); /* IN_MODIFY */
+ DEFSYM (Qmove_self, "move-self"); /* IN_MOVE_SELF */
+ DEFSYM (Qmoved_from, "moved-from"); /* IN_MOVED_FROM */
+ DEFSYM (Qmoved_to, "moved-to"); /* IN_MOVED_TO */
+ DEFSYM (Qopen, "open"); /* IN_OPEN */
+
+ DEFSYM (Qall_events, "all-events"); /* IN_ALL_EVENTS */
+ DEFSYM (Qmove, "move"); /* IN_MOVE */
+ DEFSYM (Qclose, "close"); /* IN_CLOSE */
+
+ DEFSYM (Qdont_follow, "dont-follow"); /* IN_DONT_FOLLOW */
+ DEFSYM (Qexcl_unlink, "excl-unlink"); /* IN_EXCL_UNLINK */
+ DEFSYM (Qmask_add, "mask-add"); /* IN_MASK_ADD */
+ DEFSYM (Qoneshot, "oneshot"); /* IN_ONESHOT */
+ DEFSYM (Qonlydir, "onlydir"); /* IN_ONLYDIR */
+
+ DEFSYM (Qignored, "ignored"); /* IN_IGNORED */
+ DEFSYM (Qisdir, "isdir"); /* IN_ISDIR */
+ DEFSYM (Qq_overflow, "q-overflow"); /* IN_Q_OVERFLOW */
+ DEFSYM (Qunmount, "unmount"); /* IN_UNMOUNT */
defsubr (&Sinotify_add_watch);
defsubr (&Sinotify_rm_watch);
diff --git a/src/insdel.c b/src/insdel.c
index 086bdb756b2..80650be25ae 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -51,8 +51,6 @@ static Lisp_Object combine_after_change_list;
/* Buffer which combine_after_change_list is about. */
static Lisp_Object combine_after_change_buffer;
-Lisp_Object Qinhibit_modification_hooks;
-
static void signal_before_change (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
/* Also used in marker.c to enable expensive marker checks. */
@@ -203,6 +201,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 +234,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 +274,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 +340,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 +721,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;
@@ -1180,10 +1200,10 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
/* Update various buffer positions for the new text. */
GAP_SIZE -= len_byte;
- ZV += len; Z+= len;
+ ZV += len; Z += len;
ZV_BYTE += len_byte; Z_BYTE += len_byte;
GPT += len; GPT_BYTE += len_byte;
- if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
+ if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
if (nchars_del > 0)
adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
@@ -1206,7 +1226,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
if (from < PT)
adjust_point (len - nchars_del, len_byte - nbytes_del);
- /* As byte combining will decrease Z, we must check this again. */
+ /* As byte combining will decrease Z, we must check this again. */
if (Z - GPT < END_UNCHANGED)
END_UNCHANGED = Z - GPT;
@@ -1577,7 +1597,7 @@ del_range_byte (ptrdiff_t from_byte, ptrdiff_t to_byte, bool prepare)
{
ptrdiff_t from, to;
- /* Make args be valid */
+ /* Make args be valid. */
if (from_byte < BEGV_BYTE)
from_byte = BEGV_BYTE;
if (to_byte > ZV_BYTE)
@@ -1659,7 +1679,7 @@ del_range_both (ptrdiff_t from, ptrdiff_t from_byte,
/* Delete a range of text, specified both as character positions
and byte positions. FROM and TO are character positions,
while FROM_BYTE and TO_BYTE are byte positions.
- If RET_STRING, the deleted area is returned as a string. */
+ If RET_STRING, the deleted area is returned as a string. */
Lisp_Object
del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
@@ -1758,8 +1778,6 @@ modify_text (ptrdiff_t start, ptrdiff_t end)
bset_point_before_scroll (current_buffer, Qnil);
}
-Lisp_Object Qregion_extract_function;
-
/* Check that it is okay to modify the buffer between START and END,
which are char positions.
@@ -1775,9 +1793,11 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end,
ptrdiff_t *preserve_ptr)
{
struct buffer *base_buffer;
+ Lisp_Object temp;
+ XSETFASTINT (temp, start);
if (!NILP (BVAR (current_buffer, read_only)))
- Fbarf_if_buffer_read_only ();
+ Fbarf_if_buffer_read_only (temp);
bset_redisplay (current_buffer);
@@ -1804,26 +1824,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 +1974,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,19 +1984,18 @@ 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))
{
PRESERVE_VALUE;
PRESERVE_START_END;
- Frun_hooks (1, &Qfirst_change_hook);
+ run_hook (Qfirst_change_hook);
}
/* Now run the before-change-functions if any. */
if (!NILP (Vbefore_change_functions))
{
- Lisp_Object args[3];
rvoe_arg.location = &Vbefore_change_functions;
rvoe_arg.errorp = 1;
@@ -1998,10 +2006,8 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int,
record_unwind_protect_ptr (reset_var_on_error, &rvoe_arg);
/* Actually run the hook functions. */
- args[0] = Qbefore_change_functions;
- args[1] = FETCH_START;
- args[2] = FETCH_END;
- Frun_hook_with_args (3, args);
+ CALLN (Frun_hook_with_args, Qbefore_change_functions,
+ FETCH_START, FETCH_END);
/* There was no error: unarm the reset_on_error. */
rvoe_arg.errorp = 0;
@@ -2069,7 +2075,6 @@ signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
if (!NILP (Vafter_change_functions))
{
- Lisp_Object args[4];
rvoe_arg.location = &Vafter_change_functions;
rvoe_arg.errorp = 1;
@@ -2077,11 +2082,9 @@ signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
record_unwind_protect_ptr (reset_var_on_error, &rvoe_arg);
/* Actually run the hook functions. */
- args[0] = Qafter_change_functions;
- XSETFASTINT (args[1], charpos);
- XSETFASTINT (args[2], charpos + lenins);
- XSETFASTINT (args[3], lendel);
- Frun_hook_with_args (4, args);
+ CALLN (Frun_hook_with_args, Qafter_change_functions,
+ make_number (charpos), make_number (charpos + lenins),
+ make_number (lendel));
/* There was no error: unarm the reset_on_error. */
rvoe_arg.errorp = 0;
diff --git a/src/intervals.h b/src/intervals.h
index 6850e7de04a..b2260d002e6 100644
--- a/src/intervals.h
+++ b/src/intervals.h
@@ -197,6 +197,7 @@ set_interval_plist (INTERVAL i, Lisp_Object plist)
/* Is this interval writable? Replace later with cache access. */
#define INTERVAL_WRITABLE_P(i) \
(i && (NILP (textget ((i)->plist, Qread_only)) \
+ || !NILP (textget ((i)->plist, Qinhibit_read_only)) \
|| ((CONSP (Vinhibit_read_only) \
? !NILP (Fmemq (textget ((i)->plist, Qread_only), \
Vinhibit_read_only)) \
@@ -270,23 +271,7 @@ extern INTERVAL interval_of (ptrdiff_t, Lisp_Object);
/* Defined in xdisp.c. */
extern int invisible_p (Lisp_Object, Lisp_Object);
-/* Declared in textprop.c. */
-
-/* Types of hooks. */
-extern Lisp_Object Qpoint_left;
-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. */
-extern Lisp_Object Qfront_sticky, Qrear_nonsticky;
-
+/* Defined in textprop.c. */
extern Lisp_Object copy_text_properties (Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
diff --git a/src/keyboard.c b/src/keyboard.c
index 945019e8418..383c109c446 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -88,11 +88,6 @@ static KBOARD *all_kboards;
/* True in the single-kboard state, false in the any-kboard state. */
static bool single_kboard;
-/* Non-nil disable property on a command means
- do not execute it; call disabled-command-function's value instead. */
-Lisp_Object Qdisabled;
-static Lisp_Object Qdisabled_command_function;
-
#define NUM_RECENT_KEYS (300)
/* Index for storing next element into recent_keys. */
@@ -134,6 +129,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;
@@ -219,48 +227,65 @@ static ptrdiff_t last_point_position;
'volatile' here. */
Lisp_Object internal_last_event_frame;
-static Lisp_Object Qx_set_selection, Qhandle_switch_frame;
-static Lisp_Object Qhandle_select_window;
-Lisp_Object QPRIMARY;
-
-static Lisp_Object Qself_insert_command;
-static Lisp_Object Qforward_char;
-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;
-static Lisp_Object Qinput_method_function;
-
-static Lisp_Object Qdeactivate_mark;
-
-Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook;
-
-static Lisp_Object Qecho_area_clear_hook;
-
-/* Hooks to run before and after each command. */
-static Lisp_Object Qpre_command_hook;
-static Lisp_Object Qpost_command_hook;
-
-static Lisp_Object Qdeferred_action_function;
-
-static Lisp_Object Qdelayed_warnings_hook;
-
-static Lisp_Object Qinput_method_exit_on_first_char;
-static Lisp_Object Qinput_method_use_echo_area;
-
-static Lisp_Object Qhelp_form_show;
-
/* File in which we write all commands we read. */
static FILE *dribble;
-/* Nonzero if input is available. */
+/* True if input is available. */
bool input_pending;
+/* True if more input was available last time we read an event.
+
+ Since redisplay can take a significant amount of time and is not
+ indispensable to perform the user's commands, when input arrives
+ "too fast", Emacs skips redisplay. More specifically, if the next
+ command has already been input when we finish the previous command,
+ we skip the intermediate redisplay.
+
+ This is useful to try and make sure Emacs keeps up with fast input
+ rates, such as auto-repeating keys. But in some cases, this proves
+ too conservative: we may end up disabling redisplay for the whole
+ duration of a key repetition, even though we could afford to
+ redisplay every once in a while.
+
+ So we "sample" the input_pending flag before running a command and
+ use *that* value after running the command to decide whether to
+ skip redisplay or not. This way, we only skip redisplay if we
+ really can't keep up with the repeat rate.
+
+ This only makes a difference if the next input arrives while running the
+ command, which is very unlikely if the command is executed quickly.
+ IOW this tends to avoid skipping redisplay after a long running command
+ (which is a case where skipping redisplay is not very useful since the
+ redisplay time is small compared to the time it took to run the command).
+
+ A typical use case is when scrolling. Scrolling time can be split into:
+ - Time to do jit-lock on the newly displayed portion of buffer.
+ - Time to run the actual scroll command.
+ - Time to perform the redisplay.
+ Jit-lock can happen either during the command or during the redisplay.
+ In the most painful cases, the jit-lock time is the one that dominates.
+ Also jit-lock can be tweaked (via jit-lock-defer) to delay its job, at the
+ cost of temporary inaccuracy in display and scrolling.
+ So without input_was_pending, what typically happens is the following:
+ - when the command starts, there's no pending input (yet).
+ - the scroll command triggers jit-lock.
+ - during the long jit-lock time the next input arrives.
+ - at the end of the command, we check input_pending and hence decide to
+ skip redisplay.
+ - we read the next input and start over.
+ End result: all the hard work of jit-locking is "wasted" since redisplay
+ doesn't actually happens (at least not before the input rate slows down).
+ With input_was_pending redisplay is still skipped if Emacs can't keep up
+ with the input rate, but if it can keep up just enough that there's no
+ input_pending when we begin the command, then redisplay is not skipped
+ which results in better feedback to the user. */
+static bool input_was_pending;
+
/* Circular buffer for pre-read keyboard input. */
static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
@@ -285,85 +310,12 @@ static struct input_event * volatile kbd_store_ptr;
dequeuing functions? Such a flag could be screwed up by interrupts
at inopportune times. */
-/* Symbols to head events. */
-static Lisp_Object Qmouse_movement;
-static Lisp_Object Qscroll_bar_movement;
-Lisp_Object Qswitch_frame;
-static Lisp_Object Qfocus_in, Qfocus_out;
-static Lisp_Object Qdelete_frame;
-static Lisp_Object Qiconify_frame;
-static Lisp_Object Qmake_frame_visible;
-static Lisp_Object Qselect_window;
-Lisp_Object Qhelp_echo;
-
-static Lisp_Object Qmouse_fixup_help_message;
-
-/* Symbols to denote kinds of events. */
-static Lisp_Object Qfunction_key;
-Lisp_Object Qmouse_click;
-#ifdef HAVE_NTGUI
-Lisp_Object Qlanguage_change;
-#endif
-static Lisp_Object Qdrag_n_drop;
-static Lisp_Object Qsave_session;
-#ifdef HAVE_DBUS
-static Lisp_Object Qdbus_event;
-#endif
-#ifdef USE_FILE_NOTIFY
-static Lisp_Object Qfile_notify;
-#endif /* USE_FILE_NOTIFY */
-static Lisp_Object Qconfig_changed_event;
-
-/* Lisp_Object Qmouse_movement; - also an event header */
-
-/* Properties of event headers. */
-Lisp_Object Qevent_kind;
-static Lisp_Object Qevent_symbol_elements;
-
-/* Menu and tool bar item parts. */
-static Lisp_Object Qmenu_enable;
-static Lisp_Object QCenable, QCvisible, QChelp, QCkeys, QCkey_sequence;
-Lisp_Object QCfilter;
-
-/* Non-nil disable property on a command means
- do not execute it; call disabled-command-function's value instead. */
-Lisp_Object QCtoggle, QCradio;
-static Lisp_Object QCbutton, QClabel;
-
-static Lisp_Object QCvert_only;
-
-/* An event header symbol HEAD may have a property named
- Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS);
- BASE is the base, unmodified version of HEAD, and MODIFIERS is the
- mask of modifiers applied to it. If present, this is used to help
- speed up parse_modifiers. */
-Lisp_Object Qevent_symbol_element_mask;
-
-/* An unmodified event header BASE may have a property named
- Qmodifier_cache, which is an alist mapping modifier masks onto
- modified versions of BASE. If present, this helps speed up
- apply_modifiers. */
-static Lisp_Object Qmodifier_cache;
-
-/* Symbols to use for parts of windows. */
-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;
-
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);
-static Lisp_Object Qpolling_period;
-
/* Incremented whenever a timer is run. */
unsigned timers_run;
@@ -378,12 +330,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;
@@ -496,10 +442,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);
@@ -511,13 +459,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;
}
@@ -528,14 +476,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;
}
@@ -545,6 +493,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;
@@ -560,14 +509,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
@@ -623,9 +573,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 ();
}
@@ -1118,7 +1068,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
@@ -1143,6 +1093,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;
@@ -1202,7 +1163,8 @@ top_level_1 (Lisp_Object ignore)
DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
doc: /* Exit all recursive editing levels.
-This also exits all active minibuffers. */)
+This also exits all active minibuffers. */
+ attributes: noreturn)
(void)
{
#ifdef HAVE_WINDOW_SYSTEM
@@ -1223,9 +1185,10 @@ 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. */)
+ doc: /* Exit from the innermost recursive edit or minibuffer. */
+ attributes: noreturn)
(void)
{
if (command_loop_level > 0 || minibuf_level > 0)
@@ -1234,9 +1197,10 @@ 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. */)
+ doc: /* Abort the command that requested this recursive edit or minibuffer input. */
+ attributes: noreturn)
(void)
{
if (command_loop_level > 0 || minibuf_level > 0)
@@ -1267,13 +1231,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;
@@ -1282,7 +1242,7 @@ usage: (track-mouse BODY...) */)
do_mouse_tracking = Qt;
- val = Fprogn (args);
+ val = call0 (bodyfun);
return unbind_to (count, val);
}
@@ -1293,9 +1253,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 *
@@ -1324,14 +1281,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, ... */
@@ -1450,7 +1404,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. */
@@ -1525,6 +1479,13 @@ command_loop_1 (void)
/* Execute the command. */
+ {
+ total_keys += total_keys < NUM_RECENT_KEYS;
+ ASET (recent_keys, recent_keys_index,
+ Fcons (Qnil, cmd));
+ if (++recent_keys_index >= NUM_RECENT_KEYS)
+ recent_keys_index = 0;
+ }
Vthis_command = cmd;
Vreal_this_command = cmd;
safe_run_hooks (Qpre_command_hook);
@@ -1644,14 +1605,11 @@ command_loop_1 (void)
= call1 (Fsymbol_value (Qregion_extract_function), Qnil);
if (XINT (Flength (txt)) > 0)
/* Don't set empty selections. */
- call2 (Qx_set_selection, QPRIMARY, txt);
+ call2 (Qgui_set_selection, QPRIMARY, txt);
}
if (current_buffer != prev_buffer || MODIFF != prev_modiff)
- {
- Lisp_Object hook = intern ("activate-mark-hook");
- Frun_hooks (1, &hook);
- }
+ run_hook (intern ("activate-mark-hook"));
}
Vsaved_region_selection = Qnil;
@@ -1698,7 +1656,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);
@@ -1867,30 +1825,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)
-{
- 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);
+safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args)
+{
+ eassert (nargs == 2);
+ AUTO_STRING (format, "Error in %s (%S): %S");
+ Lisp_Object hook = args[0];
+ Lisp_Object fun = args[1];
+ CALLN (Fmessage, format, hook, fun, error);
+
if (SYMBOLP (hook))
{
Lisp_Object val;
@@ -1922,13 +1877,11 @@ 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]);
-
- internal_condition_case (safe_run_hooks_1, Qt, safe_run_hooks_error);
+ eassert (nargs == 2);
+ /* Yes, run_hook_with_args works with args in the other order. */
+ internal_condition_case_n (safe_run_hooks_1,
+ 2, ((Lisp_Object []) {args[1], args[0]}),
+ Qt, safe_run_hooks_error);
return Qnil;
}
@@ -1939,15 +1892,14 @@ 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 ;-) */
+ struct gcpro gcpro1;
ptrdiff_t count = SPECPDL_INDEX ();
- specbind (Qinhibit_quit, hook);
-
- run_hook_with_args (1, &hook, safe_run_hook_funcall);
+ GCPRO1 (hook);
+ specbind (Qinhibit_quit, Qt);
+ run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), safe_run_hook_funcall);
unbind_to (count, Qnil);
+ UNGCPRO;
}
@@ -2092,16 +2044,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;
@@ -2303,8 +2252,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
@@ -2337,15 +2288,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)
@@ -2375,13 +2327,20 @@ 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.
-2 means do neither.
- 1 means do both. */
+ 1 means do both.
-/* The argument MAP is a keymap for menu prompting.
+ The argument MAP is a keymap for menu prompting.
PREV_EVENT is the previous input event, or nil if we are reading
the first event of a key sequence (or not reading a key sequence).
@@ -2432,7 +2391,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);
@@ -2446,9 +2404,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))
{
@@ -2457,17 +2418,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. */
@@ -2501,7 +2458,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;
}
@@ -2560,11 +2517,13 @@ read_char (int commandflag, Lisp_Object map,
user-visible, such as X selection_request events. */
if (input_pending
|| detect_input_pending_run_timers (0))
- swallow_events (0); /* May clear input_pending. */
+ swallow_events (false); /* May clear input_pending. */
/* Redisplay if no pending input. */
- while (!input_pending)
+ while (!(input_pending
+ && (input_was_pending || !redisplay_dont_pause)))
{
+ input_was_pending = input_pending;
if (help_echo_showing_p && !EQ (selected_window, minibuf_window))
redisplay_preserve_echo_area (5);
else
@@ -2576,7 +2535,7 @@ read_char (int commandflag, Lisp_Object map,
/* Input arrived and pre-empted redisplay.
Process any events which are not user-visible. */
- swallow_events (0);
+ swallow_events (false);
/* If that cleared input_pending, try again to redisplay. */
}
@@ -2656,6 +2615,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;
@@ -2710,8 +2670,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. */
@@ -2842,6 +2801,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. */
@@ -2895,8 +2859,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;
}
@@ -3172,8 +3136,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)))
{
@@ -3229,6 +3192,7 @@ read_char (int commandflag, Lisp_Object map,
exit:
RESUME_POLLING;
+ input_was_pending = input_pending;
RETURN_UNGCPRO (c);
}
@@ -3249,8 +3213,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);
@@ -3472,11 +3435,13 @@ 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
- )
+ && !((flags & READABLE_EVENTS_FILTER_EVENTS)
+ && event->kind == BUFFER_SWITCH_EVENT))
return 1;
event++;
if (event == kbd_buffer + KBD_BUFFER_SIZE)
@@ -3705,6 +3670,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.
@@ -3723,14 +3716,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);
}
@@ -3747,7 +3738,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);
}
@@ -3769,7 +3760,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;
}
@@ -3824,7 +3816,7 @@ kbd_buffer_get_event (KBOARD **kbp,
Lisp_Object obj;
#ifdef subprocesses
- if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE/4)
+ if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
{
/* Start reading input again because we have processed enough to
be able to accept new events again. */
@@ -4029,11 +4021,7 @@ kbd_buffer_get_event (KBOARD **kbp,
{
#ifdef HAVE_W32NOTIFY
/* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */
- obj = list3 (Qfile_notify,
- list3 (make_number (event->code),
- XCAR (event->arg),
- XCDR (event->arg)),
- event->frame_or_window);
+ obj = list3 (Qfile_notify, event->arg, event->frame_or_window);
#else
obj = make_lispy_event (event);
#endif
@@ -4061,7 +4049,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);
@@ -4316,7 +4304,7 @@ swallow_events (bool do_display)
old_timers_run = timers_run;
get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
- if (timers_run != old_timers_run && do_display)
+ if (!input_pending && timers_run != old_timers_run && do_display)
redisplay_preserve_echo_area (7);
}
@@ -4375,9 +4363,15 @@ decode_timer (Lisp_Object timer, struct timespec *result)
vector = XVECTOR (timer)->contents;
if (! NILP (vector[0]))
return 0;
+ if (! INTEGERP (vector[2]))
+ return false;
- return decode_time_components (vector[1], vector[2], vector[3], vector[8],
- result, 0);
+ struct lisp_time t;
+ if (! decode_time_components (vector[1], vector[2], vector[3], vector[8],
+ &t, 0))
+ return false;
+ *result = lisp_to_timespec (t);
+ return timespec_valid_p (*result);
}
@@ -5166,17 +5160,17 @@ static const char *const lispy_drag_n_drop_names[] =
"drag-n-drop"
};
-/* Scroll bar parts. */
-static Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
-Lisp_Object Qup, Qdown, Qbottom;
-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. */
-static Lisp_Object *const scroll_bar_parts[] = {
- &Qabove_handle, &Qhandle, &Qbelow_handle,
- &Qup, &Qdown, &Qtop, &Qbottom, &Qend_scroll, &Qratio
+/* An array of symbol indexes 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 short const scroll_bar_parts[] = {
+ SYMBOL_INDEX (Qnil), SYMBOL_INDEX (Qabove_handle), SYMBOL_INDEX (Qhandle),
+ SYMBOL_INDEX (Qbelow_handle), SYMBOL_INDEX (Qup), SYMBOL_INDEX (Qdown),
+ SYMBOL_INDEX (Qtop), SYMBOL_INDEX (Qbottom), SYMBOL_INDEX (Qend_scroll),
+ SYMBOL_INDEX (Qratio), SYMBOL_INDEX (Qbefore_handle),
+ SYMBOL_INDEX (Qhorizontal_handle), SYMBOL_INDEX (Qafter_handle),
+ SYMBOL_INDEX (Qleft), SYMBOL_INDEX (Qright), SYMBOL_INDEX (Qleftmost),
+ SYMBOL_INDEX (Qrightmost), SYMBOL_INDEX (Qend_scroll), SYMBOL_INDEX (Qratio)
};
/* A vector, indexed by button number, giving the down-going location
@@ -5226,7 +5220,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;
@@ -5261,9 +5255,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;
@@ -5282,12 +5274,14 @@ 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));
+ xret = wx;
yret = wy - WINDOW_HEADER_LINE_HEIGHT (w);
}
else if (part == ON_LEFT_FRINGE)
{
posn = Qleft_fringe;
col = 0;
+ xret = wx;
dx = wx
- (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
? 0 : window_box_width (w, LEFT_MARGIN_AREA));
@@ -5297,6 +5291,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
{
posn = Qright_fringe;
col = 0;
+ xret = wx;
dx = wx
- window_box_width (w, LEFT_MARGIN_AREA)
- window_box_width (w, TEXT_AREA)
@@ -5310,9 +5305,23 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
posn = Qvertical_line;
width = 1;
dx = 0;
+ xret = wx;
+ dy = yret = wy;
+ }
+ else if (part == ON_VERTICAL_SCROLL_BAR)
+ {
+ posn = Qvertical_scroll_bar;
+ width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+ dx = xret = wx;
+ dy = yret = wy;
+ }
+ else if (part == ON_HORIZONTAL_SCROLL_BAR)
+ {
+ posn = Qhorizontal_scroll_bar;
+ width = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+ dx = xret = wx;
dy = yret = wy;
}
- /* Nothing special for part == ON_SCROLL_BAR. */
else if (part == ON_RIGHT_DIVIDER)
{
posn = Qright_divider;
@@ -5331,7 +5340,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;
@@ -5382,21 +5391,26 @@ 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)));
}
else if (f != 0)
- XSETFRAME (window, f);
+ {
+ /* Return mouse pixel coordinates here. */
+ XSETFRAME (window, f);
+ xret = XINT (x);
+ yret = XINT (y);
+ }
else
window = Qnil;
@@ -5422,6 +5436,17 @@ 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),
+ builtin_lisp_symbol (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.
@@ -5481,14 +5506,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
@@ -5497,8 +5521,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 */
@@ -5509,47 +5532,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
@@ -5562,6 +5578,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;
@@ -5644,20 +5661,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))
@@ -5934,14 +5939,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;
- window = event->frame_or_window;
- portion_whole = Fcons (event->x, event->y);
- part = *scroll_bar_parts[(int) event->part];
+ position = make_scroll_bar_position (event, Qvertical_scroll_bar);
- position = list5 (window, Qvertical_scroll_bar, portion_whole,
- make_number (event->timestamp), part);
+ /* 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);
+ }
+
+ case HORIZONTAL_SCROLL_BAR_CLICK_EVENT:
+ {
+ Lisp_Object position, head;
+
+ position = make_scroll_bar_position (event, Qhorizontal_scroll_bar);
/* Always treat scroll bar events as clicks. */
event->modifiers |= click_modifier;
@@ -6058,7 +6083,7 @@ make_lispy_movement (struct frame *frame, Lisp_Object bar_window, enum scroll_ba
{
Lisp_Object part_sym;
- part_sym = *scroll_bar_parts[(int) part];
+ part_sym = builtin_lisp_symbol (scroll_bar_parts[part]);
return list2 (Qscroll_bar_movement,
list5 (bar_window,
Qvertical_scroll_bar,
@@ -6241,10 +6266,10 @@ apply_modifiers_uncached (int modifiers, char *base, int base_len, int base_len_
if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; }
if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; }
if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; }
- if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; }
- if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; }
- if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; }
- if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; }
+ if (modifiers & double_modifier) p = stpcpy (p, "double-");
+ if (modifiers & triple_modifier) p = stpcpy (p, "triple-");
+ if (modifiers & down_modifier) p = stpcpy (p, "down-");
+ if (modifiers & drag_modifier) p = stpcpy (p, "drag-");
/* The click modifier is denoted by the absence of other modifiers. */
*p = '\0';
@@ -6271,7 +6296,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;
@@ -6879,6 +6904,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);
}
@@ -6889,8 +6928,6 @@ gobble_input (void)
if (err && !nread)
nread = -1;
- frame_make_pointer_visible ();
-
return nread;
}
@@ -7296,7 +7333,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
@@ -7306,7 +7343,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",
@@ -7370,11 +7407,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
@@ -7403,7 +7443,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);
@@ -7420,7 +7460,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))
@@ -7481,8 +7521,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++;
@@ -7492,6 +7532,7 @@ menu_bar_items (Lisp_Object old)
}
Vinhibit_quit = oquit;
+ SAFE_FREE ();
return menu_bar_items_vector;
}
@@ -7807,11 +7848,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;
@@ -7854,8 +7896,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;
@@ -7906,15 +7947,11 @@ static Lisp_Object tool_bar_item_properties;
static int ntool_bar_items;
-/* The symbols `:image' and `:rtl'. */
-
-static Lisp_Object QCimage;
-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);
@@ -7927,9 +7964,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;
@@ -7953,7 +7992,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);
@@ -7970,7 +8009,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))
@@ -7999,6 +8038,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;
}
@@ -8437,7 +8477,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;
@@ -8555,10 +8595,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);
}
@@ -8936,8 +8980,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 ();
@@ -9069,8 +9112,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);
@@ -9735,8 +9777,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]);
}
@@ -9767,7 +9808,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))
{
@@ -9781,7 +9822,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);
@@ -9944,23 +9985,34 @@ If CHECK-TIMERS is non-nil, timers that are ready to run will do so. */)
? Qt : Qnil);
}
-DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0,
- doc: /* Return vector of last 300 events, not counting those from keyboard macros. */)
- (void)
+DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 1, 0,
+ doc: /* Return vector of last few events, not counting those from keyboard macros.
+If INCLUDE-CMDS is non-nil, include the commands that were run,
+represented as events of the form (nil . COMMAND). */)
+ (Lisp_Object include_cmds)
{
- Lisp_Object *keys = XVECTOR (recent_keys)->contents;
- Lisp_Object val;
+ bool cmds = !NILP (include_cmds);
- if (total_keys < NUM_RECENT_KEYS)
- return Fvector (total_keys, keys);
+ if (!total_keys
+ || (cmds && total_keys < NUM_RECENT_KEYS))
+ return Fvector (total_keys,
+ XVECTOR (recent_keys)->contents);
else
{
- val = Fvector (NUM_RECENT_KEYS, keys);
- vcopy (val, 0, keys + recent_keys_index,
- NUM_RECENT_KEYS - recent_keys_index);
- vcopy (val, NUM_RECENT_KEYS - recent_keys_index,
- keys, recent_keys_index);
- return val;
+ Lisp_Object es = Qnil;
+ int i = (total_keys < NUM_RECENT_KEYS
+ ? 0 : recent_keys_index);
+ eassert (recent_keys_index < NUM_RECENT_KEYS);
+ do
+ {
+ Lisp_Object e = AREF (recent_keys, i);
+ if (cmds || !CONSP (e) || !NILP (XCAR (e)))
+ es = Fcons (e, es);
+ if (++i >= NUM_RECENT_KEYS)
+ i = 0;
+ } while (i != recent_keys_index);
+ es = Fnreverse (es);
+ return Fvconcat (1, &es);
}
}
@@ -10153,7 +10205,6 @@ On such systems, Emacs starts a subshell instead of suspending. */)
int old_height, old_width;
int width, height;
struct gcpro gcpro1;
- Lisp_Object hook;
if (tty_list && tty_list->next)
error ("There are other tty frames open; close them before suspending Emacs");
@@ -10161,9 +10212,7 @@ On such systems, Emacs starts a subshell instead of suspending. */)
if (!NILP (stuffstring))
CHECK_STRING (stuffstring);
- /* Run the functions in suspend-hook. */
- hook = intern ("suspend-hook");
- Frun_hooks (1, &hook);
+ run_hook (intern ("suspend-hook"));
GCPRO1 (stuffstring);
get_tty_size (fileno (CURTTY ()->input), &old_width, &old_height);
@@ -10183,11 +10232,11 @@ 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");
- Frun_hooks (1, &hook);
+ run_hook (intern ("suspend-resume-hook"));
UNGCPRO;
return Qnil;
@@ -10266,7 +10315,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
@@ -10320,7 +10369,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)
{
@@ -10532,9 +10581,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;
@@ -10574,11 +10624,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;
@@ -10615,9 +10665,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;
@@ -10676,25 +10727,25 @@ The elements of this list correspond to the arguments of
`set-input-mode'. */)
(void)
{
- Lisp_Object val[4];
struct frame *sf = XFRAME (selected_frame);
- val[0] = interrupt_input ? Qt : Qnil;
+ Lisp_Object interrupt = interrupt_input ? Qt : Qnil;
+ Lisp_Object flow, meta;
if (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
{
- val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
- val[2] = (FRAME_TTY (sf)->meta_key == 2
- ? make_number (0)
- : (CURTTY ()->meta_key == 1 ? Qt : Qnil));
+ flow = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
+ meta = (FRAME_TTY (sf)->meta_key == 2
+ ? make_number (0)
+ : (CURTTY ()->meta_key == 1 ? Qt : Qnil));
}
else
{
- val[1] = Qnil;
- val[2] = Qt;
+ flow = Qnil;
+ meta = Qt;
}
- XSETFASTINT (val[3], quit_char);
+ Lisp_Object quit = make_number (quit_char);
- return Flist (sizeof (val) / sizeof (val[0]), val);
+ return list4 (interrupt, flow, meta, quit);
}
DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 4, 0,
@@ -10929,26 +10980,29 @@ init_keyboard (void)
#endif
}
-/* This type's only use is in syms_of_keyboard, to initialize the
- event header symbols and put properties on them. */
-struct event_head {
- Lisp_Object *var;
- const char *name;
- Lisp_Object *kind;
+/* This type's only use is in syms_of_keyboard, to put properties on the
+ event header symbols. */
+struct event_head
+{
+ short var;
+ short kind;
};
static const struct event_head head_table[] = {
- {&Qmouse_movement, "mouse-movement", &Qmouse_movement},
- {&Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement},
- {&Qswitch_frame, "switch-frame", &Qswitch_frame},
- {&Qfocus_in, "focus-in", &Qfocus_in},
- {&Qfocus_out, "focus-out", &Qfocus_out},
- {&Qdelete_frame, "delete-frame", &Qdelete_frame},
- {&Qiconify_frame, "iconify-frame", &Qiconify_frame},
- {&Qmake_frame_visible, "make-frame-visible", &Qmake_frame_visible},
+ {SYMBOL_INDEX (Qmouse_movement), SYMBOL_INDEX (Qmouse_movement)},
+ {SYMBOL_INDEX (Qscroll_bar_movement), SYMBOL_INDEX (Qmouse_movement)},
+
+ /* Some of the event heads. */
+ {SYMBOL_INDEX (Qswitch_frame), SYMBOL_INDEX (Qswitch_frame)},
+
+ {SYMBOL_INDEX (Qfocus_in), SYMBOL_INDEX (Qfocus_in)},
+ {SYMBOL_INDEX (Qfocus_out), SYMBOL_INDEX (Qfocus_out)},
+ {SYMBOL_INDEX (Qdelete_frame), SYMBOL_INDEX (Qdelete_frame)},
+ {SYMBOL_INDEX (Qiconify_frame), SYMBOL_INDEX (Qiconify_frame)},
+ {SYMBOL_INDEX (Qmake_frame_visible), SYMBOL_INDEX (Qmake_frame_visible)},
/* `select-window' should be handled just like `switch-frame'
in read_key_sequence. */
- {&Qselect_window, "select-window", &Qswitch_frame}
+ {SYMBOL_INDEX (Qselect_window), SYMBOL_INDEX (Qswitch_frame)}
};
void
@@ -10960,6 +11014,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");
@@ -10978,17 +11041,29 @@ syms_of_keyboard (void)
DEFSYM (Qself_insert_command, "self-insert-command");
DEFSYM (Qforward_char, "forward-char");
DEFSYM (Qbackward_char, "backward-char");
+
+ /* Non-nil disable property on a command means do not execute it;
+ call disabled-command-function's value instead. */
DEFSYM (Qdisabled, "disabled");
+
DEFSYM (Qundefined, "undefined");
+
+ /* Hooks to run before and after each command. */
DEFSYM (Qpre_command_hook, "pre-command-hook");
DEFSYM (Qpost_command_hook, "post-command-hook");
+
DEFSYM (Qdeferred_action_function, "deferred-action-function");
DEFSYM (Qdelayed_warnings_hook, "delayed-warnings-hook");
DEFSYM (Qfunction_key, "function-key");
+
+ /* The values of Qevent_kind properties. */
DEFSYM (Qmouse_click, "mouse-click");
+
DEFSYM (Qdrag_n_drop, "drag-n-drop");
DEFSYM (Qsave_session, "save-session");
DEFSYM (Qconfig_changed_event, "config-changed-event");
+
+ /* Menu and tool bar item parts. */
DEFSYM (Qmenu_enable, "menu-enable");
#ifdef HAVE_NTGUI
@@ -11003,6 +11078,7 @@ syms_of_keyboard (void)
DEFSYM (Qfile_notify, "file-notify");
#endif /* USE_FILE_NOTIFY */
+ /* Menu and tool bar item parts. */
DEFSYM (QCenable, ":enable");
DEFSYM (QCvisible, ":visible");
DEFSYM (QChelp, ":help");
@@ -11010,15 +11086,16 @@ syms_of_keyboard (void)
DEFSYM (QCbutton, ":button");
DEFSYM (QCkeys, ":keys");
DEFSYM (QCkey_sequence, ":key-sequence");
+
+ /* Non-nil disable property on a command means
+ do not execute it; call disabled-command-function's value instead. */
DEFSYM (QCtoggle, ":toggle");
DEFSYM (QCradio, ":radio");
DEFSYM (QClabel, ":label");
DEFSYM (QCvert_only, ":vert-only");
- DEFSYM (Qmode_line, "mode-line");
+ /* Symbols to use for parts of windows. */
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");
@@ -11033,10 +11110,29 @@ 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");
+
+ /* Properties of event headers. */
DEFSYM (Qevent_kind, "event-kind");
DEFSYM (Qevent_symbol_elements, "event-symbol-elements");
+
+ /* An event header symbol HEAD may have a property named
+ Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS);
+ BASE is the base, unmodified version of HEAD, and MODIFIERS is the
+ mask of modifiers applied to it. If present, this is used to help
+ speed up parse_modifiers. */
DEFSYM (Qevent_symbol_element_mask, "event-symbol-element-mask");
+
+ /* An unmodified event header BASE may have a property named
+ Qmodifier_cache, which is an alist mapping modifier masks onto
+ modified versions of BASE. If present, this helps speed up
+ apply_modifiers. */
DEFSYM (Qmodifier_cache, "modifier-cache");
DEFSYM (Qrecompute_lucid_menubar, "recompute-lucid-menubar");
@@ -11044,8 +11140,11 @@ syms_of_keyboard (void)
DEFSYM (Qpolling_period, "polling-period");
- DEFSYM (Qx_set_selection, "x-set-selection");
+ DEFSYM (Qgui_set_selection, "gui-set-selection");
+
+ /* The primary selection. */
DEFSYM (QPRIMARY, "PRIMARY");
+
DEFSYM (Qhandle_switch_frame, "handle-switch-frame");
DEFSYM (Qhandle_select_window, "handle-select-window");
@@ -11060,17 +11159,26 @@ syms_of_keyboard (void)
Fset (Qinput_method_exit_on_first_char, Qnil);
Fset (Qinput_method_use_echo_area, Qnil);
+ /* Symbols to head events. */
+ DEFSYM (Qmouse_movement, "mouse-movement");
+ DEFSYM (Qscroll_bar_movement, "scroll-bar-movement");
+ DEFSYM (Qswitch_frame, "switch-frame");
+ DEFSYM (Qfocus_in, "focus-in");
+ DEFSYM (Qfocus_out, "focus-out");
+ DEFSYM (Qdelete_frame, "delete-frame");
+ DEFSYM (Qiconify_frame, "iconify-frame");
+ DEFSYM (Qmake_frame_visible, "make-frame-visible");
+ DEFSYM (Qselect_window, "select-window");
{
int i;
- int len = sizeof (head_table) / sizeof (head_table[0]);
- for (i = 0; i < len; i++)
+ for (i = 0; i < ARRAYELTS (head_table); i++)
{
const struct event_head *p = &head_table[i];
- *p->var = intern_c_string (p->name);
- staticpro (p->var);
- Fput (*p->var, Qevent_kind, *p->kind);
- Fput (*p->var, Qevent_symbol_elements, list1 (*p->var));
+ Lisp_Object var = builtin_lisp_symbol (p->var);
+ Lisp_Object kind = builtin_lisp_symbol (p->kind);
+ Fput (var, Qevent_kind, kind);
+ Fput (var, Qevent_symbol_elements, list1 (var));
}
}
@@ -11078,14 +11186,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++)
@@ -11397,13 +11504,14 @@ with no modifiers; thus, setting `extra-keyboard-modifiers' to zero
cancels any modification. */);
extra_keyboard_modifiers = 0;
+ DEFSYM (Qdeactivate_mark, "deactivate-mark");
DEFVAR_LISP ("deactivate-mark", Vdeactivate_mark,
doc: /* If an editing command sets this to t, deactivate the mark afterward.
The command loop sets this to nil before each command,
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 7647ec44a17..0ce6d184482 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -248,8 +248,6 @@ extern ptrdiff_t this_command_key_count;
generated by the next character. */
extern Lisp_Object internal_last_event_frame;
-extern Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook;
-
/* This holds a Lisp vector that holds the properties of a single
menu item while decoding it in parse_menu_item.
Using a Lisp vector to hold this information while we decode it
@@ -305,9 +303,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 +350,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). */
@@ -440,25 +385,10 @@ typedef struct _widget_value
#define POSN_INBUFFER_P(posn) (NILP (POSN_STRING (posn)))
#define POSN_BUFFER_POSN(posn) (Fnth (make_number (5), (posn)))
-/* Some of the event heads. */
-extern Lisp_Object Qswitch_frame;
-
-/* Properties on event heads. */
-extern Lisp_Object Qevent_kind;
-
-/* The values of Qevent_kind properties. */
-extern Lisp_Object Qmouse_click;
-
-extern Lisp_Object Qhelp_echo;
-
/* Getting the kind of an event head. */
#define EVENT_HEAD_KIND(event_head) \
(Fget ((event_head), Qevent_kind))
-/* Symbols to use for non-text mouse positions. */
-extern Lisp_Object Qmode_line, Qvertical_line, Qheader_line;
-extern Lisp_Object Qright_divider, Qbottom_divider;
-
/* True while doing kbd input. */
extern bool waiting_for_input;
@@ -466,12 +396,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;
extern Lisp_Object parse_modifiers (Lisp_Object);
extern Lisp_Object reorder_modifiers (Lisp_Object);
@@ -483,17 +408,6 @@ extern int parse_solitary_modifier (Lisp_Object symbol);
/* This is like Vthis_command, except that commands never set it. */
extern Lisp_Object real_this_command;
-/* Non-nil disable property on a command means
- do not execute it; call disabled-command-function's value instead. */
-extern Lisp_Object QCtoggle, QCradio;
-
-/* An event header symbol HEAD may have a property named
- Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS);
- BASE is the base, unmodified version of HEAD, and MODIFIERS is the
- mask of modifiers applied to it. If present, this is used to help
- speed up parse_modifiers. */
-extern Lisp_Object Qevent_symbol_element_mask;
-
extern int quit_char;
extern unsigned int timers_run;
@@ -518,9 +432,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 773ac02c01a..34fe1cb7a95 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -76,12 +76,6 @@ Lisp_Object control_x_map; /* The keymap used for globally bound
bindings when spaces are not encouraged
in the minibuf. */
-/* Keymap used for minibuffers when doing completion. */
-/* Keymap used for minibuffers when doing completion and require a match. */
-static Lisp_Object Qkeymapp, Qnon_ascii;
-Lisp_Object Qkeymap, Qmenu_item, Qremap;
-static Lisp_Object QCadvertised_binding;
-
/* Alist of elements like (DEL . "\d"). */
static Lisp_Object exclude_keys;
@@ -654,8 +648,6 @@ map_keymap (Lisp_Object map, map_keymap_function_t fun, Lisp_Object args,
UNGCPRO;
}
-static Lisp_Object Qkeymap_canonicalize;
-
/* Same as map_keymap, but does it right, properly eliminating duplicate
bindings due to inheritance. */
void
@@ -727,11 +719,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 +755,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 +960,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 +978,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 +1084,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 +1238,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 +1291,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 CALLN (Fvconcat, key_sequence, key_list);
}
/* Given a event type C which is a symbol,
@@ -1381,11 +1331,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 +1843,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;
@@ -2041,7 +1990,6 @@ then the value includes only maps for prefixes that start with PREFIX. */)
}
return maps;
}
-static Lisp_Object Qsingle_key_description, Qkey_description;
/* This function cannot GC. */
@@ -2280,14 +2228,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 +2256,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)));
@@ -2483,8 +2435,7 @@ where_is_internal (Lisp_Object definition, Lisp_Object keymaps,
if (NILP (where_is_cache))
{
/* We need to create the cache. */
- Lisp_Object args[2];
- where_is_cache = Fmake_hash_table (0, args);
+ where_is_cache = Fmake_hash_table (0, NULL);
where_is_cache_keymaps = Qt;
}
else
@@ -2574,9 +2525,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 +2875,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 +2891,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 +3178,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 +3201,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 +3345,7 @@ describe_map (Lisp_Object map, Lisp_Object prefix,
}
}
+ SAFE_FREE ();
UNGCPRO;
}
@@ -3400,7 +3354,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 +3434,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;
}
@@ -3770,12 +3724,15 @@ be preferred. */);
Vwhere_is_preferred_modifier = Qnil;
where_is_preferred_modifier = 0;
+ DEFSYM (Qmenu_bar, "menu-bar");
+ DEFSYM (Qmode_line, "mode-line");
+
staticpro (&Vmouse_events);
Vmouse_events = listn (CONSTYPE_PURE, 9,
- intern_c_string ("menu-bar"),
+ Qmenu_bar,
intern_c_string ("tool-bar"),
intern_c_string ("header-line"),
- intern_c_string ("mode-line"),
+ Qmode_line,
intern_c_string ("mouse-1"),
intern_c_string ("mouse-2"),
intern_c_string ("mouse-3"),
@@ -3784,6 +3741,9 @@ be preferred. */);
DEFSYM (Qsingle_key_description, "single-key-description");
DEFSYM (Qkey_description, "key-description");
+
+ /* Keymap used for minibuffers when doing completion. */
+ /* Keymap used for minibuffers when doing completion and require a match. */
DEFSYM (Qkeymapp, "keymapp");
DEFSYM (Qnon_ascii, "non-ascii");
DEFSYM (Qmenu_item, "menu-item");
diff --git a/src/keymap.h b/src/keymap.h
index 25654ef0ab1..215dd3f289f 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -30,9 +30,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define KEY_DESCRIPTION_SIZE ((2 * 6) + 1 + (CHARACTERBITS / 3) + 1 + 1)
#define KEYMAPP(m) (!NILP (get_keymap (m, false, false)))
-extern Lisp_Object Qkeymap, Qmenu_bar;
-extern Lisp_Object Qremap;
-extern Lisp_Object Qmenu_item;
extern Lisp_Object current_global_map;
extern char *push_key_description (EMACS_INT, char *);
extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool);
@@ -46,7 +43,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 d20f2dd6c0a..1c8e1f33b5c 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 aa939ba157e..f5242ab84a1 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -36,46 +36,21 @@ 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
-# define DEFINE_GDB_SYMBOL_BEGIN(type, id) type const id EXTERNALLY_VISIBLE
+#define DECLARE_GDB_SYM(type, id) type const id EXTERNALLY_VISIBLE
+#ifdef MAIN_PROGRAM
+# define DEFINE_GDB_SYMBOL_BEGIN(type, id) DECLARE_GDB_SYM (type, id)
# define DEFINE_GDB_SYMBOL_END(id) = id;
#else
-# define DEFINE_GDB_SYMBOL_BEGIN(type, id)
-# define DEFINE_GDB_SYMBOL_END(val)
+# define DEFINE_GDB_SYMBOL_BEGIN(type, id) extern DECLARE_GDB_SYM (type, id)
+# define DEFINE_GDB_SYMBOL_END(val) ;
#endif
/* The ubiquitous max and min macros. */
@@ -84,6 +59,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 +87,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 +117,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 +135,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)
};
@@ -236,17 +233,11 @@ extern bool suppress_checking EXTERNALLY_VISIBLE;
USE_LSB_TAG not only requires the least 3 bits of pointers returned by
malloc to be 0 but also needs to be able to impose a mult-of-8 alignment
- on the few static Lisp_Objects used: all the defsubr as well
- as the two special buffers buffer_defaults and buffer_local_symbols. */
+ on the few static Lisp_Objects used: lispsym, all the defsubr, and
+ the two special buffers buffer_defaults and buffer_local_symbols. */
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
@@ -267,34 +258,23 @@ enum Lisp_Bits
/* The maximum value that can be stored in a EMACS_INT, assuming all
bits other than the type bits contribute to a nonnegative signed value.
- This can be used in #if, e.g., '#if VAL_MAX < UINTPTR_MAX' below. */
+ This can be used in #if, e.g., '#if USB_TAG' below expands to an
+ expression involving VAL_MAX. */
#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.
- On hosts where pointers-as-ints do not exceed VAL_MAX, USE_LSB_TAG is:
+/* Whether the least-significant bits of an EMACS_INT contain the tag.
+ On hosts where pointers-as-ints do not exceed VAL_MAX / 2, 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 (VAL_MAX / 2 < 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 +284,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,12 +333,12 @@ 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)
-#define lisp_h_INTEGERP(x) ((XTYPE (x) & ~Lisp_Int1) == 0)
+#define lisp_h_INTEGERP(x) ((XTYPE (x) & (Lisp_Int0 | ~Lisp_Int1)) == Lisp_Int0)
#define lisp_h_MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
#define lisp_h_MISCP(x) (XTYPE (x) == Lisp_Misc)
#define lisp_h_NILP(x) EQ (x, Qnil)
@@ -370,18 +355,21 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false };
(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_XSYMBOL(a) \
- (eassert (SYMBOLP (a)), (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol))
+ (SYMBOLP (a) ? XSYMBOL (a) : (void *) ((intptr_t) (XLI (a) & VALMASK)))
#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) + Lisp_Int0))
# define lisp_h_XFASTINT(a) XINT (a)
# define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS)
+# define lisp_h_XSYMBOL(a) \
+ (eassert (SYMBOLP (a)), \
+ (struct Lisp_Symbol *) ((uintptr_t) XLI (a) - Lisp_Symbol \
+ + (char *) lispsym))
# define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK))
-# define lisp_h_XUNTAG(a, type) ((void *) (XLI (a) - (type)))
+# define lisp_h_XUNTAG(a, type) ((void *) (intptr_t) (XLI (a) - (type)))
#endif
/* When compiling via gcc -O0, define the key operations as macros, as
@@ -395,7 +383,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)
@@ -413,7 +401,6 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false };
# define XCONS(a) lisp_h_XCONS (a)
# define XHASH(a) lisp_h_XHASH (a)
# define XPNTR(a) lisp_h_XPNTR (a)
-# define XSYMBOL(a) lisp_h_XSYMBOL (a)
# ifndef GC_CHECK_CONS_LIST
# define check_cons_list() lisp_h_check_cons_list ()
# endif
@@ -421,6 +408,7 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false };
# define make_number(n) lisp_h_make_number (n)
# define XFASTINT(a) lisp_h_XFASTINT (a)
# define XINT(a) lisp_h_XINT (a)
+# define XSYMBOL(a) lisp_h_XSYMBOL (a)
# define XTYPE(a) lisp_h_XTYPE (a)
# define XUNTAG(a, type) lisp_h_XUNTAG (a, type)
# endif
@@ -462,20 +450,20 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false };
enum Lisp_Type
{
- /* Integer. XINT (obj) is the integer value. */
- Lisp_Int0 = 0,
- Lisp_Int1 = USE_LSB_TAG ? 1 << INTTYPEBITS : 1,
-
/* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */
- Lisp_Symbol = 2,
+ Lisp_Symbol = 0,
/* Miscellaneous. XMISC (object) points to a union Lisp_Misc,
whose first member indicates the subtype. */
- Lisp_Misc = 3,
+ Lisp_Misc = 1,
+
+ /* Integer. XINT (obj) is the integer value. */
+ Lisp_Int0 = 2,
+ Lisp_Int1 = USE_LSB_TAG ? 6 : 3,
/* String. XSTRING (object) points to a struct Lisp_String.
The length of the string, and its contents, are stored therein. */
- Lisp_String = USE_LSB_TAG ? 1 : 1 << INTTYPEBITS,
+ Lisp_String = 4,
/* Vector of Lisp objects, or something resembling it.
XVECTOR (object) points to a struct Lisp_Vector, which contains
@@ -484,7 +472,7 @@ enum Lisp_Type
Lisp_Vectorlike = 5,
/* Cons. XCONS (object) points to a struct Lisp_Cons. */
- Lisp_Cons = 6,
+ Lisp_Cons = USE_LSB_TAG ? 3 : 6,
Lisp_Float = 7
};
@@ -577,7 +565,7 @@ enum Lisp_Fwd_Type
typedef struct { EMACS_INT i; } Lisp_Object;
-#define LISP_INITIALLY_ZERO {0}
+#define LISP_INITIALLY(i) {i}
#undef CHECK_LISP_OBJECT_TYPE
enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true };
@@ -586,10 +574,179 @@ enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true };
/* If a struct type is not wanted, define Lisp_Object as just a number. */
typedef EMACS_INT Lisp_Object;
-#define LISP_INITIALLY_ZERO 0
+#define LISP_INITIALLY(i) (i)
enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
#endif /* CHECK_LISP_OBJECT_TYPE */
+#define LISP_INITIALLY_ZERO LISP_INITIALLY (0)
+
+/* Forward declarations. */
+
+/* Defined in this file. */
+union Lisp_Fwd;
+INLINE bool BOOL_VECTOR_P (Lisp_Object);
+INLINE bool BUFFER_OBJFWDP (union Lisp_Fwd *);
+INLINE bool BUFFERP (Lisp_Object);
+INLINE bool CHAR_TABLE_P (Lisp_Object);
+INLINE Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object, ptrdiff_t);
+INLINE bool (CONSP) (Lisp_Object);
+INLINE bool (FLOATP) (Lisp_Object);
+INLINE bool functionp (Lisp_Object);
+INLINE bool (INTEGERP) (Lisp_Object);
+INLINE bool (MARKERP) (Lisp_Object);
+INLINE bool (MISCP) (Lisp_Object);
+INLINE bool (NILP) (Lisp_Object);
+INLINE bool OVERLAYP (Lisp_Object);
+INLINE bool PROCESSP (Lisp_Object);
+INLINE bool PSEUDOVECTORP (Lisp_Object, int);
+INLINE bool SAVE_VALUEP (Lisp_Object);
+INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t,
+ Lisp_Object);
+INLINE bool STRINGP (Lisp_Object);
+INLINE bool SUB_CHAR_TABLE_P (Lisp_Object);
+INLINE bool SUBRP (Lisp_Object);
+INLINE bool (SYMBOLP) (Lisp_Object);
+INLINE bool (VECTORLIKEP) (Lisp_Object);
+INLINE bool WINDOWP (Lisp_Object);
+INLINE bool TERMINALP (Lisp_Object);
+INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object);
+INLINE struct Lisp_Symbol *(XSYMBOL) (Lisp_Object);
+INLINE void *(XUNTAG) (Lisp_Object, int);
+
+/* Defined in chartab.c. */
+extern Lisp_Object char_table_ref (Lisp_Object, int);
+extern void char_table_set (Lisp_Object, int, Lisp_Object);
+
+/* Defined in data.c. */
+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 floatfns.c. */
+extern double extract_float (Lisp_Object);
+
+
+/* Interned state of a symbol. */
+
+enum symbol_interned
+{
+ SYMBOL_UNINTERNED = 0,
+ SYMBOL_INTERNED = 1,
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY = 2
+};
+
+enum symbol_redirect
+{
+ SYMBOL_PLAINVAL = 4,
+ SYMBOL_VARALIAS = 1,
+ SYMBOL_LOCALIZED = 2,
+ SYMBOL_FORWARDED = 3
+};
+
+struct Lisp_Symbol
+{
+ bool_bf gcmarkbit : 1;
+
+ /* Indicates where the value can be found:
+ 0 : it's a plain var, the value is in the `value' field.
+ 1 : it's a varalias, the value is really in the `alias' symbol.
+ 2 : it's a localized var, the value is in the `blv' object.
+ 3 : it's a forwarding variable, the value is in `forward'. */
+ ENUM_BF (symbol_redirect) redirect : 3;
+
+ /* Non-zero means symbol is constant, i.e. changing its value
+ should signal an error. If the value is 3, then the var
+ can be changed, but only by `defconst'. */
+ unsigned constant : 2;
+
+ /* Interned state of the symbol. This is an enumerator from
+ enum symbol_interned. */
+ unsigned interned : 2;
+
+ /* True means that this variable has been explicitly declared
+ special (with `defvar' etc), and shouldn't be lexically bound. */
+ bool_bf declared_special : 1;
+
+ /* True if pointed to from purespace and hence can't be GC'd. */
+ bool_bf pinned : 1;
+
+ /* The symbol's name, as a Lisp string. */
+ Lisp_Object name;
+
+ /* Value of the symbol or Qunbound if unbound. Which alternative of the
+ union is used depends on the `redirect' field above. */
+ union {
+ Lisp_Object value;
+ struct Lisp_Symbol *alias;
+ struct Lisp_Buffer_Local_Value *blv;
+ union Lisp_Fwd *fwd;
+ } val;
+
+ /* Function value of the symbol or Qnil if not fboundp. */
+ Lisp_Object function;
+
+ /* The symbol's property list. */
+ Lisp_Object plist;
+
+ /* Next symbol in obarray bucket, if the symbol is interned. */
+ struct Lisp_Symbol *next;
+};
+
+/* Declare a Lisp-callable function. The MAXARGS parameter has the same
+ meaning as in the DEFUN macro, and is used to construct a prototype. */
+/* We can use the same trick as in the DEFUN macro to generate the
+ appropriate prototype. */
+#define EXFUN(fnname, maxargs) \
+ extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
+
+/* Note that the weird token-substitution semantics of ANSI C makes
+ this work for MANY and UNEVALLED. */
+#define DEFUN_ARGS_MANY (ptrdiff_t, Lisp_Object *)
+#define DEFUN_ARGS_UNEVALLED (Lisp_Object)
+#define DEFUN_ARGS_0 (void)
+#define DEFUN_ARGS_1 (Lisp_Object)
+#define DEFUN_ARGS_2 (Lisp_Object, Lisp_Object)
+#define DEFUN_ARGS_3 (Lisp_Object, Lisp_Object, Lisp_Object)
+#define DEFUN_ARGS_4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
+#define DEFUN_ARGS_5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
+ Lisp_Object)
+#define DEFUN_ARGS_6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
+ Lisp_Object, Lisp_Object)
+#define DEFUN_ARGS_7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
+ Lisp_Object, Lisp_Object, Lisp_Object)
+#define DEFUN_ARGS_8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
+ Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
+
+/* Yield an integer that contains TAG along with PTR. */
+#define TAG_PTR(tag, ptr) \
+ ((USE_LSB_TAG ? (tag) : (EMACS_UINT) (tag) << VALBITS) + (uintptr_t) (ptr))
+
+/* Yield an integer that contains a symbol tag along with OFFSET.
+ OFFSET should be the offset in bytes from 'lispsym' to the symbol. */
+#define TAG_SYMOFFSET(offset) \
+ TAG_PTR (Lisp_Symbol, \
+ ((uintptr_t) (offset) >> (USE_LSB_TAG ? 0 : GCTYPEBITS)))
+
+/* XLI_BUILTIN_LISPSYM (iQwhatever) is equivalent to
+ XLI (builtin_lisp_symbol (Qwhatever)),
+ except the former expands to an integer constant expression. */
+#define XLI_BUILTIN_LISPSYM(iname) TAG_SYMOFFSET ((iname) * sizeof *lispsym)
+
+/* Declare extern constants for Lisp symbols. These can be helpful
+ when using a debugger like GDB, on older platforms where the debug
+ format does not represent C macros. */
+#define DEFINE_LISP_SYMBOL_BEGIN(name) \
+ DEFINE_GDB_SYMBOL_BEGIN (Lisp_Object, name)
+#define DEFINE_LISP_SYMBOL_END(name) \
+ DEFINE_GDB_SYMBOL_END (LISP_INITIALLY (XLI_BUILTIN_LISPSYM (i##name)))
+
+#include "globals.h"
+
/* Convert a Lisp_Object to the corresponding EMACS_INT and vice versa.
At the machine level, these operations are no-ops. */
LISP_MACRO_DEFUN (XLI, EMACS_INT, (Lisp_Object o), (o))
@@ -597,25 +754,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 +788,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,28 +815,21 @@ 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. */
#define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS)
#define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
-/* Extract the pointer hidden within A. */
-LISP_MACRO_DEFUN (XPNTR, void *, (Lisp_Object a), (a))
-
#if USE_LSB_TAG
LISP_MACRO_DEFUN (make_number, Lisp_Object, (EMACS_INT n), (n))
LISP_MACRO_DEFUN (XINT, EMACS_INT, (Lisp_Object a), (a))
LISP_MACRO_DEFUN (XFASTINT, EMACS_INT, (Lisp_Object a), (a))
+LISP_MACRO_DEFUN (XSYMBOL, struct Lisp_Symbol *, (Lisp_Object a), (a))
LISP_MACRO_DEFUN (XTYPE, enum Lisp_Type, (Lisp_Object a), (a))
LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type))
@@ -714,7 +844,19 @@ 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);
+ EMACS_INT int0 = Lisp_Int0;
+ if (USE_LSB_TAG)
+ {
+ EMACS_UINT u = n;
+ n = u << INTTYPEBITS;
+ n += int0;
+ }
+ else
+ {
+ n &= INTMASK;
+ n += (int0 << VALBITS);
+ }
+ return XIL (n);
}
/* Extract A's value as a signed integer. */
@@ -722,7 +864,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.
@@ -731,11 +878,23 @@ XINT (Lisp_Object a)
INLINE EMACS_INT
XFASTINT (Lisp_Object a)
{
- EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a);
+ EMACS_INT int0 = Lisp_Int0;
+ EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a) - (int0 << VALBITS);
eassert (0 <= n);
return n;
}
+/* Extract A's value as a symbol. */
+INLINE struct Lisp_Symbol *
+XSYMBOL (Lisp_Object a)
+{
+ uintptr_t i = (uintptr_t) XUNTAG (a, Lisp_Symbol);
+ if (! USE_LSB_TAG)
+ i <<= GCTYPEBITS;
+ void *p = (char *) lispsym + i;
+ return p;
+}
+
/* Extract A's type. */
INLINE enum Lisp_Type
XTYPE (Lisp_Object a)
@@ -748,16 +907,15 @@ XTYPE (Lisp_Object a)
INLINE void *
XUNTAG (Lisp_Object a, int type)
{
- if (USE_LSB_TAG)
- {
- intptr_t i = XLI (a) - type;
- return (void *) i;
- }
- return XPNTR (a);
+ intptr_t i = USE_LSB_TAG ? XLI (a) - type : XLI (a) & VALMASK;
+ return (void *) i;
}
#endif /* ! USE_LSB_TAG */
+/* Extract the pointer hidden within A. */
+LISP_MACRO_DEFUN (XPNTR, void *, (Lisp_Object a), (a))
+
/* Extract A's value as an unsigned integer. */
INLINE EMACS_UINT
XUINT (Lisp_Object a)
@@ -776,7 +934,8 @@ INLINE Lisp_Object
make_natnum (EMACS_INT n)
{
eassert (0 <= n && n <= MOST_POSITIVE_FIXNUM);
- return USE_LSB_TAG ? make_number (n) : XIL (n);
+ EMACS_INT int0 = Lisp_Int0;
+ return USE_LSB_TAG ? make_number (n) : XIL (n + (int0 << VALBITS));
}
/* Return true if X and Y are the same object. */
@@ -795,69 +954,6 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
return num < lower ? lower : num <= upper ? num : upper;
}
-/* Forward declarations. */
-
-/* Defined in this file. */
-union Lisp_Fwd;
-INLINE bool BOOL_VECTOR_P (Lisp_Object);
-INLINE bool BUFFER_OBJFWDP (union Lisp_Fwd *);
-INLINE bool BUFFERP (Lisp_Object);
-INLINE bool CHAR_TABLE_P (Lisp_Object);
-INLINE Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object, ptrdiff_t);
-INLINE bool (CONSP) (Lisp_Object);
-INLINE bool (FLOATP) (Lisp_Object);
-INLINE bool functionp (Lisp_Object);
-INLINE bool (INTEGERP) (Lisp_Object);
-INLINE bool (MARKERP) (Lisp_Object);
-INLINE bool (MISCP) (Lisp_Object);
-INLINE bool (NILP) (Lisp_Object);
-INLINE bool OVERLAYP (Lisp_Object);
-INLINE bool PROCESSP (Lisp_Object);
-INLINE bool PSEUDOVECTORP (Lisp_Object, int);
-INLINE bool SAVE_VALUEP (Lisp_Object);
-INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t,
- Lisp_Object);
-INLINE bool STRINGP (Lisp_Object);
-INLINE bool SUB_CHAR_TABLE_P (Lisp_Object);
-INLINE bool SUBRP (Lisp_Object);
-INLINE bool (SYMBOLP) (Lisp_Object);
-INLINE bool (VECTORLIKEP) (Lisp_Object);
-INLINE bool WINDOWP (Lisp_Object);
-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;
-extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil;
-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);
-
-/* Defined in emacs.c. */
-extern bool initialized;
-
-/* Defined in eval.c. */
-extern Lisp_Object Qautoload;
-
-/* Defined in floatfns.c. */
-extern double extract_float (Lisp_Object);
-
-/* Defined in process.c. */
-extern Lisp_Object Qprocessp;
-
-/* Defined in window.c. */
-extern Lisp_Object Qwindowp;
-
-/* Defined in xdisp.c. */
-extern Lisp_Object Qimage;
-
/* Extract a value or address from a Lisp_Object. */
@@ -877,7 +973,9 @@ XSTRING (Lisp_Object a)
return XUNTAG (a, Lisp_String);
}
-LISP_MACRO_DEFUN (XSYMBOL, struct Lisp_Symbol *, (Lisp_Object a), (a))
+/* The index of the C-defined Lisp symbol SYM.
+ This can be used in a static initializer. */
+#define SYMBOL_INDEX(sym) i##sym
INLINE struct Lisp_Float *
XFLOAT (Lisp_Object a)
@@ -905,6 +1003,7 @@ XWINDOW (Lisp_Object a)
INLINE struct terminal *
XTERMINAL (Lisp_Object a)
{
+ eassert (TERMINALP (a));
return XUNTAG (a, Lisp_Vectorlike);
}
@@ -948,17 +1047,23 @@ XBOOL_VECTOR (Lisp_Object a)
INLINE Lisp_Object
make_lisp_ptr (void *ptr, enum Lisp_Type type)
{
- EMACS_UINT utype = type;
- EMACS_UINT typebits = USE_LSB_TAG ? type : utype << VALBITS;
- Lisp_Object a = XIL (typebits | (uintptr_t) ptr);
+ Lisp_Object a = XIL (TAG_PTR (type, ptr));
eassert (XTYPE (a) == type && XUNTAG (a, type) == ptr);
return a;
}
INLINE Lisp_Object
-make_lisp_proc (struct Lisp_Process *p)
+make_lisp_symbol (struct Lisp_Symbol *sym)
{
- return make_lisp_ptr (p, Lisp_Vectorlike);
+ Lisp_Object a = XIL (TAG_SYMOFFSET ((char *) sym - (char *) lispsym));
+ eassert (XSYMBOL (a) == sym);
+ return a;
+}
+
+INLINE Lisp_Object
+builtin_lisp_symbol (int index)
+{
+ return make_lisp_symbol (lispsym + index);
}
#define XSETINT(a, b) ((a) = make_number (b))
@@ -966,7 +1071,7 @@ make_lisp_proc (struct Lisp_Process *p)
#define XSETCONS(a, b) ((a) = make_lisp_ptr (b, Lisp_Cons))
#define XSETVECTOR(a, b) ((a) = make_lisp_ptr (b, Lisp_Vectorlike))
#define XSETSTRING(a, b) ((a) = make_lisp_ptr (b, Lisp_String))
-#define XSETSYMBOL(a, b) ((a) = make_lisp_ptr (b, Lisp_Symbol))
+#define XSETSYMBOL(a, b) ((a) = make_lisp_symbol (b))
#define XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float))
#define XSETMISC(a, b) ((a) = make_lisp_ptr (b, Lisp_Misc))
@@ -1004,10 +1109,30 @@ make_lisp_proc (struct Lisp_Process *p)
#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
+/* Efficiently convert a pointer to a Lisp object and back. The
+ pointer is represented as a Lisp integer, so the garbage collector
+ does not know about it. The pointer should not have both Lisp_Int1
+ bits set, which makes this conversion inherently unportable. */
+
+INLINE void *
+XINTPTR (Lisp_Object a)
+{
+ return XUNTAG (a, Lisp_Int0);
+}
+
+INLINE Lisp_Object
+make_pointer_integer (void *p)
+{
+ Lisp_Object a = XIL (TAG_PTR (Lisp_Int0, p));
+ eassert (INTEGERP (a) && XINTPTR (a) == p);
+ return a;
+}
+
/* 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 +1142,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 +1224,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 +1326,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
@@ -1384,6 +1503,22 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val)
XVECTOR (array)->contents[idx] = val;
}
+/* True, since Qnil's representation is zero. Every place in the code
+ that assumes Qnil is zero should verify (NIL_IS_ZERO), to make it easy
+ to find such assumptions later if we change Qnil to be nonzero. */
+enum { NIL_IS_ZERO = XLI_BUILTIN_LISPSYM (iQnil) == 0 };
+
+/* Clear the object addressed by P, with size NBYTES, so that all its
+ bytes are zero and all its Lisp values are nil. */
+INLINE void
+memclear (void *p, ptrdiff_t nbytes)
+{
+ eassert (0 <= nbytes);
+ verify (NIL_IS_ZERO);
+ /* Since Qnil is zero, memset suffices. */
+ memset (p, 0, nbytes);
+}
+
/* If a struct is made to look like a vector, this macro returns the length
of the shortest vector that would hold that struct. */
@@ -1415,10 +1550,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 +1609,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 +1683,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,77 +1704,14 @@ CHAR_TABLE_EXTRA_SLOTS (struct Lisp_Char_Table *ct)
- CHAR_TABLE_STANDARD_SLOTS);
}
-
+/* Make sure that sub char-table contents slot is where we think it is. */
+verify (offsetof (struct Lisp_Sub_Char_Table, contents)
+ == offsetof (struct Lisp_Vector, contents[SUB_CHAR_TABLE_OFFSET]));
+
/***********************************************************************
Symbols
***********************************************************************/
-/* Interned state of a symbol. */
-
-enum symbol_interned
-{
- SYMBOL_UNINTERNED = 0,
- SYMBOL_INTERNED = 1,
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY = 2
-};
-
-enum symbol_redirect
-{
- SYMBOL_PLAINVAL = 4,
- SYMBOL_VARALIAS = 1,
- SYMBOL_LOCALIZED = 2,
- SYMBOL_FORWARDED = 3
-};
-
-struct Lisp_Symbol
-{
- bool_bf gcmarkbit : 1;
-
- /* Indicates where the value can be found:
- 0 : it's a plain var, the value is in the `value' field.
- 1 : it's a varalias, the value is really in the `alias' symbol.
- 2 : it's a localized var, the value is in the `blv' object.
- 3 : it's a forwarding variable, the value is in `forward'. */
- ENUM_BF (symbol_redirect) redirect : 3;
-
- /* Non-zero means symbol is constant, i.e. changing its value
- should signal an error. If the value is 3, then the var
- can be changed, but only by `defconst'. */
- unsigned constant : 2;
-
- /* Interned state of the symbol. This is an enumerator from
- enum symbol_interned. */
- unsigned interned : 2;
-
- /* True means that this variable has been explicitly declared
- special (with `defvar' etc), and shouldn't be lexically bound. */
- bool_bf declared_special : 1;
-
- /* True if pointed to from purespace and hence can't be GC'd. */
- bool_bf pinned : 1;
-
- /* The symbol's name, as a Lisp string. */
- Lisp_Object name;
-
- /* Value of the symbol or Qunbound if unbound. Which alternative of the
- union is used depends on the `redirect' field above. */
- union {
- Lisp_Object value;
- struct Lisp_Symbol *alias;
- struct Lisp_Buffer_Local_Value *blv;
- union Lisp_Fwd *fwd;
- } val;
-
- /* Function value of the symbol or Qnil if not fboundp. */
- Lisp_Object function;
-
- /* The symbol's property list. */
- Lisp_Object plist;
-
- /* Next symbol in obarray bucket, if the symbol is interned. */
- struct Lisp_Symbol *next;
-};
-
/* Value is name of symbol. */
LISP_MACRO_DEFUN (SYMBOL_VAL, Lisp_Object, (struct Lisp_Symbol *sym), (sym))
@@ -1708,8 +1785,9 @@ SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (Lisp_Object sym)
LISP_MACRO_DEFUN (SYMBOL_CONSTANT_P, int, (Lisp_Object sym), (sym))
-#define DEFSYM(sym, name) \
- do { (sym) = intern_c_string ((name)); staticpro (&(sym)); } while (false)
+/* Placeholder for make-docfile to process. The actual symbol
+ definition is done by lread.c's defsym. */
+#define DEFSYM(sym, name) /* empty */
/***********************************************************************
@@ -2555,15 +2633,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,38 +2773,14 @@ 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
-/* Note that the weird token-substitution semantics of ANSI C makes
- this work for MANY and UNEVALLED. */
-#define DEFUN_ARGS_MANY (ptrdiff_t, Lisp_Object *)
-#define DEFUN_ARGS_UNEVALLED (Lisp_Object)
-#define DEFUN_ARGS_0 (void)
-#define DEFUN_ARGS_1 (Lisp_Object)
-#define DEFUN_ARGS_2 (Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_3 (Lisp_Object, Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object)
-#define DEFUN_ARGS_6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object, Lisp_Object, Lisp_Object)
-#define DEFUN_ARGS_8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
- Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
-
/* True if OBJ is a Lisp function. */
INLINE bool
FUNCTIONP (Lisp_Object obj)
@@ -2739,6 +2798,15 @@ enum maxargs
UNEVALLED = -1
};
+/* Call a function F that accepts many args, passing it ARRAY's elements. */
+#define CALLMANY(f, array) (f) (ARRAYELTS (array), array)
+
+/* Call a function F that accepts many args, passing it the remaining args,
+ E.g., 'return CALLN (Fformat, fmt, text);' is less error-prone than
+ '{ Lisp_Object a[2]; a[0] = fmt; a[1] = text; return Fformat (2, a); }'.
+ CALLN is overkill for simple usages like 'Finsert (1, &text);'. */
+#define CALLN(f, ...) CALLMANY (f, ((Lisp_Object []) {__VA_ARGS__}))
+
extern void defvar_lisp (struct Lisp_Objfwd *, const char *, Lisp_Object *);
extern void defvar_lisp_nopro (struct Lisp_Objfwd *, const char *, Lisp_Object *);
extern void defvar_bool (struct Lisp_Boolfwd *, const char *, bool *);
@@ -3036,6 +3104,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 +3169,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 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 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 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 \
@@ -3232,15 +3338,6 @@ extern int gcpro_level;
void staticpro (Lisp_Object *);
-/* Declare a Lisp-callable function. The MAXARGS parameter has the same
- meaning as in the DEFUN macro, and is used to construct a prototype. */
-/* We can use the same trick as in the DEFUN macro to generate the
- appropriate prototype. */
-#define EXFUN(fnname, maxargs) \
- extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
-
-#include "globals.h"
-
/* Forward declarations for prototypes. */
struct window;
struct frame;
@@ -3359,38 +3456,6 @@ 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 Qerror_conditions, Qerror_message, Qtop_level;
-extern Lisp_Object Qerror, Qquit, Qargs_out_of_range;
-extern Lisp_Object Qvoid_variable, Qvoid_function;
-extern Lisp_Object Qinvalid_read_syntax;
-extern Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch;
-extern Lisp_Object Quser_error, Qend_of_file, Qarith_error, Qmark_inactive;
-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 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 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);
enum Arith_Comparison {
@@ -3436,7 +3501,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);
@@ -3447,7 +3511,6 @@ extern void syms_of_cmds (void);
extern void keys_of_cmds (void);
/* Defined in coding.c. */
-extern Lisp_Object Qcharset;
extern Lisp_Object detect_coding_system (const unsigned char *, ptrdiff_t,
ptrdiff_t, bool, bool, Lisp_Object);
extern void init_coding (void);
@@ -3455,11 +3518,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,23 +3529,15 @@ 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);
/* 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);
-extern Lisp_Object Qcursor_in_echo_area;
-extern Lisp_Object Qstring_lessp;
-extern Lisp_Object QCsize, QCtest, QCweakness, Qequal, Qeq;
EMACS_UINT hash_string (char const *, ptrdiff_t);
EMACS_UINT sxhash (Lisp_Object, int);
Lisp_Object make_hash_table (struct hash_table_test, Lisp_Object, Lisp_Object,
@@ -3494,7 +3546,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 +3565,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);
@@ -3525,14 +3577,11 @@ extern void init_fringe_once (void);
#endif /* HAVE_WINDOW_SYSTEM */
/* Defined in image.c. */
-extern Lisp_Object QCascent, QCmargin, QCrelief;
-extern Lisp_Object QCconversion;
extern int x_bitmap_mask (struct frame *, ptrdiff_t);
extern void reset_image_types (void);
extern void syms_of_image (void);
/* Defined in insdel.c. */
-extern Lisp_Object Qinhibit_modification_hooks;
extern void move_gap_both (ptrdiff_t, ptrdiff_t);
extern _Noreturn void buffer_overflow (void);
extern void make_gap (ptrdiff_t);
@@ -3585,22 +3634,8 @@ _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 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 Qspace, Qcenter, QCalign_to;
-extern Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
-extern Lisp_Object Qleft_margin, Qright_margin;
-extern Lisp_Object QCdata, QCfile;
-extern Lisp_Object QCmap;
-extern Lisp_Object Qrisky_local_variable;
extern bool noninteractive_need_newline;
extern Lisp_Object echo_area_buffer[2];
extern void add_to_log (const char *, Lisp_Object, Lisp_Object);
@@ -3623,7 +3658,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 +3672,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 +3685,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;
@@ -3731,8 +3769,6 @@ build_string (const char *str)
extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object);
extern void make_byte_code (struct Lisp_Vector *);
-extern Lisp_Object Qautomatic_gc;
-extern Lisp_Object Qchar_table_extra_slots;
extern struct Lisp_Vector *allocate_vector (EMACS_INT);
/* Make an uninitialized vector for SIZE objects. NOTE: you must
@@ -3755,16 +3791,39 @@ make_uninit_vector (ptrdiff_t size)
return v;
}
-extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type);
-#define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \
- ((typ*) \
- allocate_pseudovector \
- (VECSIZE (typ), PSEUDOVECSIZE (typ, field), tag))
-extern struct Lisp_Hash_Table *allocate_hash_table (void);
-extern struct window *allocate_window (void);
-extern struct frame *allocate_frame (void);
-extern struct Lisp_Process *allocate_process (void);
-extern struct terminal *allocate_terminal (void);
+/* 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, int,
+ enum pvec_type);
+
+/* Allocate partially initialized pseudovector where all Lisp_Object
+ slots are set to Qnil but the rest (if any) is left uninitialized. */
+
+#define ALLOCATE_PSEUDOVECTOR(type, field, tag) \
+ ((type *) allocate_pseudovector (VECSIZE (type), \
+ PSEUDOVECSIZE (type, field), \
+ PSEUDOVECSIZE (type, field), tag))
+
+/* Allocate fully initialized pseudovector where all Lisp_Object
+ slots are set to Qnil and the rest (if any) is zeroed. */
+
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(type, field, tag) \
+ ((type *) allocate_pseudovector (VECSIZE (type), \
+ PSEUDOVECSIZE (type, field), \
+ VECSIZE (type), tag))
+
extern bool gc_in_progress;
extern bool abort_on_gc;
extern Lisp_Object make_float (double);
@@ -3788,6 +3847,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 +3856,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);
@@ -3824,11 +3881,8 @@ extern void syms_of_chartab (void);
/* Defined in print.c. */
extern Lisp_Object Vprin1_to_string_buffer;
extern void debug_print (Lisp_Object) EXTERNALLY_VISIBLE;
-extern Lisp_Object Qstandard_output;
-extern Lisp_Object Qexternal_debugging_output;
extern void temp_output_buffer_setup (const char *);
extern int print_level;
-extern Lisp_Object Qprint_escape_newlines;
extern void write_string (const char *, int);
extern void print_error_message (Lisp_Object, Lisp_Object, const char *,
Lisp_Object);
@@ -3852,12 +3906,11 @@ extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char const *, ptrdiff_t,
ATTRIBUTE_FORMAT_PRINTF (5, 0);
/* Defined in lread.c. */
-extern Lisp_Object Qvariable_documentation, Qstandard_input;
-extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-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, Lisp_Object);
+extern void init_symbol (Lisp_Object, Lisp_Object);
extern Lisp_Object oblookup (Lisp_Object, const char *, ptrdiff_t, ptrdiff_t);
INLINE void
LOADHIST_ATTACH (Lisp_Object x)
@@ -3888,10 +3941,9 @@ intern_c_string (const char *str)
}
/* Defined in eval.c. */
-extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qmacro;
-extern Lisp_Object Qinhibit_quit, Qinternal_interpreter_environment, Qclosure;
-extern Lisp_Object Qand_rest;
+extern EMACS_INT lisp_eval_depth;
extern Lisp_Object Vautoload_queue;
+extern Lisp_Object Vrun_hooks;
extern Lisp_Object Vsignaling_function;
extern Lisp_Object inhibit_lisp_code;
extern struct handler *handlerlist;
@@ -3903,7 +3955,7 @@ extern struct handler *handlerlist;
call1 (Vrun_hooks, Qmy_funny_hook);
should no longer be used. */
-extern Lisp_Object Vrun_hooks;
+extern void run_hook (Lisp_Object);
extern void run_hook_with_args_2 (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args,
Lisp_Object (*funcall)
@@ -3964,7 +4016,6 @@ extern bool let_shadows_global_binding_p (Lisp_Object symbol);
/* Defined in editfns.c. */
-extern Lisp_Object Qfield;
extern void insert1 (Lisp_Object);
extern Lisp_Object format2 (const char *, Lisp_Object, Lisp_Object);
extern Lisp_Object save_excursion_save (void);
@@ -3977,7 +4028,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 +4041,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);
@@ -4012,17 +4062,10 @@ extern void syms_of_marker (void);
/* Defined in fileio.c. */
-extern Lisp_Object Qfile_error;
-extern Lisp_Object Qfile_notify_error;
-extern Lisp_Object Qfile_exists_p;
-extern Lisp_Object Qfile_directory_p;
-extern Lisp_Object Qinsert_file_contents;
-extern Lisp_Object Qfile_name_history;
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,11 +4074,10 @@ 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);
-extern Lisp_Object Qdelete_file;
/* Defined in search.c. */
extern void shrink_regexp_cache (void);
@@ -4045,16 +4087,30 @@ struct re_registers;
extern struct re_pattern_buffer *compile_pattern (Lisp_Object,
struct re_registers *,
Lisp_Object, bool, bool);
-extern ptrdiff_t fast_string_match (Lisp_Object, Lisp_Object);
+extern ptrdiff_t fast_string_match_internal (Lisp_Object, Lisp_Object,
+ Lisp_Object);
+
+INLINE ptrdiff_t
+fast_string_match (Lisp_Object regexp, Lisp_Object string)
+{
+ return fast_string_match_internal (regexp, string, Qnil);
+}
+
+INLINE ptrdiff_t
+fast_string_match_ignore_case (Lisp_Object regexp, Lisp_Object string)
+{
+ return fast_string_match_internal (regexp, string, Vascii_canon_table);
+}
+
extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
ptrdiff_t);
-extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object);
extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t, Lisp_Object);
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,
@@ -4064,7 +4120,6 @@ extern void clear_regexp_cache (void);
/* Defined in minibuf.c. */
-extern Lisp_Object Qcompletion_ignore_case;
extern Lisp_Object Vminibuffer_list;
extern Lisp_Object last_minibuf_string;
extern Lisp_Object get_minibuffer (EMACS_INT);
@@ -4073,14 +4128,10 @@ extern void syms_of_minibuf (void);
/* Defined in callint.c. */
-extern Lisp_Object Qminus, Qplus;
-extern Lisp_Object Qwhen;
-extern Lisp_Object Qmouse_leave_buffer_hook;
extern void syms_of_callint (void);
/* Defined in casefiddle.c. */
-extern Lisp_Object Qidentity;
extern void syms_of_casefiddle (void);
extern void keys_of_casefiddle (void);
@@ -4094,11 +4145,11 @@ extern void syms_of_casetab (void);
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 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);
@@ -4127,15 +4178,10 @@ extern bool indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
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);
@@ -4147,9 +4193,7 @@ extern bool display_arg;
#endif
extern Lisp_Object decode_env_path (const char *, const char *, bool);
extern Lisp_Object empty_unibyte_string, empty_multibyte_string;
-extern Lisp_Object Qfile_name_handler_alist;
extern _Noreturn void terminate_due_to_signal (int, int);
-extern Lisp_Object Qkill_emacs;
#ifdef WINDOWSNT
extern Lisp_Object Vlibrary_cache;
#endif
@@ -4184,12 +4228,9 @@ extern bool inhibit_window_system;
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 +4239,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
@@ -4219,7 +4263,6 @@ extern void set_initial_environment (void);
extern void syms_of_callproc (void);
/* Defined in doc.c. */
-extern Lisp_Object Qfunction_documentation;
extern Lisp_Object read_doc_string (Lisp_Object);
extern Lisp_Object get_doc_string (Lisp_Object, bool, bool);
extern void syms_of_doc (void);
@@ -4240,8 +4283,6 @@ extern void init_macros (void);
extern void syms_of_macros (void);
/* Defined in undo.c. */
-extern Lisp_Object Qapply;
-extern Lisp_Object Qinhibit_read_only;
extern void truncate_undo_list (struct buffer *);
extern void record_insert (ptrdiff_t, ptrdiff_t);
extern void record_delete (ptrdiff_t, Lisp_Object, bool);
@@ -4251,12 +4292,8 @@ extern void record_property_change (ptrdiff_t, ptrdiff_t,
Lisp_Object, Lisp_Object,
Lisp_Object);
extern void syms_of_undo (void);
-/* Defined in textprop.c. */
-extern Lisp_Object Qfont, Qmouse_face;
-extern Lisp_Object Qinsert_in_front_hooks, Qinsert_behind_hooks;
-extern Lisp_Object Qfront_sticky, Qrear_nonsticky;
-extern Lisp_Object Qminibuffer_prompt;
+/* Defined in textprop.c. */
extern void report_interval_modification (Lisp_Object, Lisp_Object);
/* Defined in menu.c. */
@@ -4277,12 +4314,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 +4342,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);
@@ -4342,9 +4377,6 @@ extern void init_font (void);
#ifdef HAVE_WINDOW_SYSTEM
/* Defined in fontset.c. */
extern void syms_of_fontset (void);
-
-/* Defined in xfns.c, w32fns.c, or macfns.c. */
-extern Lisp_Object Qfont_param;
#endif
/* Defined in gfilenotify.c */
@@ -4364,16 +4396,6 @@ 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 Qmode_line_inactive;
-extern Lisp_Object Qface;
-extern Lisp_Object Qnormal;
-extern Lisp_Object QCfamily, QCweight, QCslant;
-extern Lisp_Object QCheight, QCname, QCwidth, QCforeground, QCbackground;
-extern Lisp_Object Qextra_light, Qlight, Qsemi_light, Qsemi_bold;
-extern Lisp_Object Qbold, Qextra_bold, Qultra_bold;
-extern Lisp_Object Qoblique, Qitalic;
extern Lisp_Object Vface_alternative_font_family_alist;
extern Lisp_Object Vface_alternative_font_registry_alist;
extern void syms_of_xfaces (void);
@@ -4389,6 +4411,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 +4433,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 +4448,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 *);
+
+extern char *egetenv_internal (const char *, ptrdiff_t);
-#define xlispstrdupa(string) \
- memcpy (alloca (SBYTES (string) + 1), \
- SSDATA (string), SBYTES (string) + 1)
+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 +4512,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 +4532,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 +4542,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 +4561,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 +4595,114 @@ 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
+
+#ifdef GC_CHECK_STRING_BYTES
+enum { defined_GC_CHECK_STRING_BYTES = true };
+#else
+enum { defined_GC_CHECK_STRING_BYTES = 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
+ && !defined_GC_CHECK_STRING_BYTES
+ && 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 4eedee0d04c..a9deb2b53d9 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 62f12919e09..69ec05964be 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -18,6 +18,8 @@ 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/>. */
+/* Tell globals.h to define tables needed by init_obarray. */
+#define DEFINE_SYMBOLS
#include <config.h>
#include "sysstdio.h"
@@ -64,31 +66,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define file_tell ftell
#endif
-/* Hash table read constants. */
-static Lisp_Object Qhash_table, Qdata;
-static Lisp_Object Qtest, Qsize;
-static Lisp_Object Qweakness;
-static Lisp_Object Qrehash_size;
-static Lisp_Object Qrehash_threshold;
-
-static Lisp_Object Qread_char, Qget_file_char, Qcurrent_load_list;
-Lisp_Object Qstandard_input;
-Lisp_Object Qvariable_documentation;
-static Lisp_Object Qascii_character, Qload, Qload_file_name;
-Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-static Lisp_Object Qinhibit_file_name_operation;
-static Lisp_Object Qeval_buffer_list;
-Lisp_Object Qlexical_binding;
-static Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */
-
-/* Used instead of Qget_file_char while loading *.elc files compiled
- by Emacs 21 or older. */
-static Lisp_Object Qget_emacs_mule_file_char;
-
-static Lisp_Object Qload_force_doc_strings;
-
-static Lisp_Object Qload_in_progress;
-
/* The association list of objects read with the #n=object form.
Each member of the list has the form (n . object), and is used to
look up the object for the corresponding #n# construct.
@@ -132,7 +109,6 @@ static file_offset prev_saved_doc_string_position;
Fread initializes this to false, so we need not specbind it
or worry about what happens to it when there is an error. */
static bool new_backquote_flag;
-static Lisp_Object Qold_style_backquotes;
/* A list of file names for files being loaded in Fload. Used to
check for recursive loads. */
@@ -213,7 +189,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 +218,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 +300,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 +946,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!");
+ CALLN (Fmessage, format, file);
}
}
@@ -1126,12 +1100,7 @@ Return t if the file exists and loads successfully. */)
{
suffixes = Fget_load_suffixes ();
if (NILP (must_suffix))
- {
- Lisp_Object arg[2];
- arg[0] = suffixes;
- arg[1] = Vload_file_rep_suffixes;
- suffixes = Fappend (2, arg);
- }
+ suffixes = CALLN (Fappend, suffixes, Vload_file_rep_suffixes);
}
fd = openp (Vload_path, file, suffixes, &found, Qnil, load_prefer_newer);
@@ -1431,8 +1400,6 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */)
return file;
}
-static Lisp_Object Qdir_ok;
-
/* Search for a file whose name is STR, looking in directories
in the Lisp list PATH, and trying suffixes from SUFFIX.
On success, return a file descriptor (or 1 or -2 as described below).
@@ -1473,6 +1440,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 +1481,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 +1550,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 +1623,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 +1634,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
{
if (storeptr)
*storeptr = save_string;
+ SAFE_FREE ();
UNGCPRO;
return save_fd;
}
@@ -1670,6 +1644,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
break;
}
+ SAFE_FREE ();
UNGCPRO;
errno = last_errno;
return -1;
@@ -1763,6 +1738,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 +1930,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 +2065,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 +2079,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 +2103,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 +2580,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 +2842,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 +3322,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 +3629,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 +3760,38 @@ check_obarray (Lisp_Object obarray)
return obarray;
}
+/* Intern symbol SYM in OBARRAY using bucket INDEX. */
+
+static Lisp_Object
+intern_sym (Lisp_Object sym, Lisp_Object obarray, Lisp_Object index)
+{
+ Lisp_Object *ptr;
+
+ XSYMBOL (sym)->interned = (EQ (obarray, initial_obarray)
+ ? SYMBOL_INTERNED_IN_INITIAL_OBARRAY
+ : SYMBOL_INTERNED);
+
+ if (SREF (SYMBOL_NAME (sym), 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 (index));
+ set_symbol_next (sym, SYMBOLP (*ptr) ? XSYMBOL (*ptr) : NULL);
+ *ptr = sym;
+ return sym;
+}
+
+/* Intern a symbol with name STRING in OBARRAY using bucket INDEX. */
+
+Lisp_Object
+intern_driver (Lisp_Object string, Lisp_Object obarray, Lisp_Object index)
+{
+ return intern_sym (Fmake_symbol (string), obarray, index);
+}
+
/* Intern the C string STR: return a symbol with that name,
interned in the current obarray. */
@@ -3768,7 +3801,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, tem);
}
Lisp_Object
@@ -3777,16 +3811,31 @@ 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 (!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, 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 ();
+static void
+define_symbol (Lisp_Object sym, char const *str)
+{
+ ptrdiff_t len = strlen (str);
+ Lisp_Object string = make_pure_c_string (str, len);
+ init_symbol (sym, string);
- return Fintern (make_pure_c_string (str, len), obarray);
+ /* Qunbound is uninterned, so that it's not confused with any symbol
+ 'unbound' created by a Lisp program. */
+ if (! EQ (sym, Qunbound))
+ {
+ Lisp_Object bucket = oblookup (initial_obarray, str, len, len);
+ eassert (INTEGERP (bucket));
+ intern_sym (sym, initial_obarray, bucket);
+ }
}
DEFUN ("intern", Fintern, Sintern, 1, 2, 0,
@@ -3796,43 +3845,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, tem);
+ return tem;
}
DEFUN ("intern-soft", Fintern_soft, Sintern_soft, 1, 2, 0,
@@ -4030,27 +4052,20 @@ init_obarray (void)
initial_obarray = Vobarray;
staticpro (&initial_obarray);
- Qunbound = Fmake_symbol (build_pure_c_string ("unbound"));
- /* Set temporary dummy values to Qnil and Vpurify_flag to satisfy the
- NILP (Vpurify_flag) check in intern_c_string. */
- Qnil = make_number (-1); Vpurify_flag = make_number (1);
- Qnil = intern_c_string ("nil");
-
- /* Fmake_symbol inits fields of new symbols with Qunbound and Qnil,
- so those two need to be fixed manually. */
- SET_SYMBOL_VAL (XSYMBOL (Qunbound), Qunbound);
- set_symbol_function (Qunbound, Qnil);
- set_symbol_plist (Qunbound, Qnil);
+ for (int i = 0; i < ARRAYELTS (lispsym); i++)
+ define_symbol (builtin_lisp_symbol (i), defsym_name[i]);
+
+ DEFSYM (Qunbound, "unbound");
+
+ DEFSYM (Qnil, "nil");
SET_SYMBOL_VAL (XSYMBOL (Qnil), Qnil);
XSYMBOL (Qnil)->constant = 1;
- XSYMBOL (Qnil)->declared_special = 1;
- set_symbol_plist (Qnil, Qnil);
- set_symbol_function (Qnil, Qnil);
+ XSYMBOL (Qnil)->declared_special = true;
- Qt = intern_c_string ("t");
+ DEFSYM (Qt, "t");
SET_SYMBOL_VAL (XSYMBOL (Qt), Qt);
- XSYMBOL (Qnil)->declared_special = 1;
XSYMBOL (Qt)->constant = 1;
+ XSYMBOL (Qt)->declared_special = true;
/* Qt is correct even if CANNOT_DUMP. loadup.el will set to nil at end. */
Vpurify_flag = Qt;
@@ -4172,7 +4187,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));
}
}
@@ -4381,12 +4396,10 @@ init_lread (void)
/* Replace nils from EMACSLOADPATH by default. */
while (CONSP (elpath))
{
- Lisp_Object arg[2];
elem = XCAR (elpath);
elpath = XCDR (elpath);
- arg[0] = Vload_path;
- arg[1] = NILP (elem) ? default_lpath : Fcons (elem, Qnil);
- Vload_path = Fappend (2, arg);
+ Vload_path = CALLN (Fappend, Vload_path,
+ NILP (elem) ? default_lpath : list1 (elem));
}
} /* Fmemq (Qnil, Vload_path) */
}
@@ -4700,7 +4713,11 @@ that are loaded before your customizations are read! */);
DEFSYM (Qstandard_input, "standard-input");
DEFSYM (Qread_char, "read-char");
DEFSYM (Qget_file_char, "get-file-char");
+
+ /* Used instead of Qget_file_char while loading *.elc files compiled
+ by Emacs 21 or older. */
DEFSYM (Qget_emacs_mule_file_char, "get-emacs-mule-file-char");
+
DEFSYM (Qload_force_doc_strings, "load-force-doc-strings");
DEFSYM (Qbackquote, "`");
diff --git a/src/macfont.h b/src/macfont.h
index 65c52c21130..f311577f051 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 f480b656afd..cbf1b07bc94 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -36,53 +36,36 @@ 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. */
-static Lisp_Object Qmac_ct;
-
static double mac_ctfont_get_advance_width_for_glyph (CTFontRef, CGGlyph);
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
- value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
- text. (See the documentation of X Logical Font Description
- Conventions.) In the Mac font driver, 1 means the screen font is
- used for calculating some glyph metrics. You can see the
- difference with Monaco 8pt or 9pt, for example. */
-static Lisp_Object QCdestination;
-
-/* The boolean-valued font property key specifying the use of
- leading. */
-static Lisp_Object QCminspace;
-
struct macfont_metrics;
/* The actual structure for Mac font that can be cast to struct font. */
@@ -129,26 +112,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 +163,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 +189,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 +209,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 +220,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 +244,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 +275,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 +306,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 +325,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 +343,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 +379,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 +397,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 +415,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 +632,7 @@ get_cgcolor(unsigned long idx, struct frame *f)
CGColorRelease (refcol_); \
} while (0)
+
/* Mac font driver. */
@@ -712,17 +695,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 +720,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 +755,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 +773,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 +781,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 +855,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 +875,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 +883,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 +909,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 +919,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 +975,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 +999,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 +1013,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 +1027,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 +1037,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 +1058,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 && ! force_integral_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 && ! force_integral_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 +1114,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 +1191,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 +1202,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 +1256,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 +1296,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 +1414,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 +1444,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 +1465,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 +1514,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 +1541,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 +1571,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 +1596,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 +1629,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 +1660,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 +1672,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 +1682,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 +1730,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 +1753,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 +1774,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 +1810,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 +1853,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 +1923,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 +1934,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 +1973,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 +2040,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 +2053,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 +2068,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 +2077,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 +2093,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 +2142,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 +2170,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 +2357,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 +2386,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 +2399,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 +2445,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 +2461,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 +2481,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 +2490,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 +2509,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 +2518,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 +2527,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 +2581,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 +2632,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,144 +2644,140 @@ 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 =
+ (NILP (ns_antialias_text)
+ || 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 =
- (NILP (ns_antialias_text)
- || 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 && ! no_antialias_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 ();
@@ -2836,9 +2788,9 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
static Lisp_Object
macfont_shape (Lisp_Object lgstring)
{
- struct font *font;
- struct macfont_info *macfont_info;
- FontRef macfont;
+ struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
+ struct macfont_info *macfont_info = (struct macfont_info *) font;
+ FontRef macfont = macfont_info->macfont;
ptrdiff_t glyph_len, len, i, j;
CFIndex nonbmp_len;
UniChar *unichars;
@@ -2847,10 +2799,6 @@ macfont_shape (Lisp_Object lgstring)
CFIndex used = 0;
struct mac_glyph_layout *glyph_layouts;
- CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
- macfont_info = (struct macfont_info *) font;
- macfont = macfont_info->macfont;
-
glyph_len = LGSTRING_GLYPH_LEN (lgstring);
nonbmp_len = 0;
for (i = 0; i < glyph_len; i++)
@@ -2858,9 +2806,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;
@@ -2875,25 +2823,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);
}
@@ -2913,40 +2861,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);
}
{
@@ -2965,15 +2913,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 ();
@@ -2996,7 +2944,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
@@ -3008,7 +2956,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
@@ -3021,7 +2969,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)
@@ -3053,98 +3001,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);
@@ -3167,18 +3115,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;
@@ -3188,86 +3134,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
@@ -3286,26 +3226,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 ();
@@ -3333,7 +3273,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 =
@@ -3348,13 +3288,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);
}
@@ -3372,79 +3312,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;
@@ -3454,14 +3394,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
@@ -3469,83 +3409,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
@@ -3563,10 +3451,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);
}
@@ -3575,7 +3463,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};
@@ -3589,10 +3477,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)
@@ -3608,30 +3496,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;
@@ -3639,7 +3527,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);
@@ -3656,128 +3544,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;
}
@@ -3792,7 +3680,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};
@@ -3801,32 +3689,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)
@@ -3839,24 +3727,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);
}
@@ -3864,41 +3752,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)
{
@@ -3910,22 +3763,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 */
@@ -3936,55 +3789,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
@@ -3993,7 +3846,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);
@@ -4005,30 +3858,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);
}
@@ -4050,20 +3902,25 @@ 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;
+ /* Core Text, for Mac OS X. */
DEFSYM (Qmac_ct, "mac-ct");
macfont_driver.type = Qmac_ct;
register_font_driver (&macfont_driver, NULL);
+ /* The font property key specifying the font design destination. The
+ value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
+ text. (See the documentation of X Logical Font Description
+ Conventions.) In the Mac font driver, 1 means the screen font is
+ used for calculating some glyph metrics. You can see the
+ difference with Monaco 8pt or 9pt, for example. */
DEFSYM (QCdestination, ":destination");
+
+ /* The boolean-valued font property key specifying the use of leading. */
DEFSYM (QCminspace, ":minspace");
-#endif
}
diff --git a/src/macros.c b/src/macros.c
index 6d924f6c080..e5b8ab70870 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -28,9 +28,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "window.h"
#include "keyboard.h"
-static Lisp_Object Qexecute_kbd_macro;
-static Lisp_Object Qkbd_macro_termination_hook;
-
/* Number of successful iterations so far
for innermost keyboard macro.
This is not bound at each level,
@@ -45,8 +42,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 +79,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,
- &current_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,
+ &current_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));
@@ -289,7 +277,7 @@ pop_kbd_macro (Lisp_Object info)
tem = XCDR (info);
executing_kbd_macro_index = XINT (XCAR (tem));
Vreal_this_command = XCDR (tem);
- Frun_hooks (1, &Qkbd_macro_termination_hook);
+ run_hook (Qkbd_macro_termination_hook);
}
DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 3, 0,
diff --git a/src/marker.c b/src/marker.c
index 05563c47597..73928ba194f 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 e318da059a3..5a8ea34242f 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 271be0eaddb..de586a5e101 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -20,14 +20,15 @@ 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
+/* Bit fields used by terminal-specific menu_show_hook. */
-extern void x_set_menu_bar_lines (struct frame *f,
- Lisp_Object value,
- Lisp_Object oldval);
+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 +42,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 469776eaaeb..3408bb995c6 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
@@ -51,37 +54,10 @@ static Lisp_Object minibuf_save_list;
EMACS_INT minibuf_level;
-/* The maximum length of a minibuffer history. */
-
-static Lisp_Object Qhistory_length;
-
/* Fread_minibuffer leaves the input here as a string. */
Lisp_Object last_minibuf_string;
-static Lisp_Object Qminibuffer_history, Qbuffer_name_history;
-
-static Lisp_Object Qread_file_name_internal;
-
-/* Normal hooks for entry to and exit from minibuffer. */
-
-static Lisp_Object Qminibuffer_setup_hook;
-static Lisp_Object Qminibuffer_exit_hook;
-
-Lisp_Object Qcompletion_ignore_case;
-static Lisp_Object Qminibuffer_completion_table;
-static Lisp_Object Qminibuffer_completion_predicate;
-static Lisp_Object Qminibuffer_completion_confirm;
-static Lisp_Object Qcustom_variable_p;
-
-static Lisp_Object Qminibuffer_default;
-
-static Lisp_Object Qcurrent_input_method, Qactivate_input_method;
-
-static Lisp_Object Qcase_fold_search;
-
-static Lisp_Object Qread_expression_history;
-
/* Prompt to display in front of the mini-buffer contents. */
static Lisp_Object minibuf_prompt;
@@ -224,8 +200,24 @@ 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));
+ fwrite (SDATA (prompt), 1, SBYTES (prompt), stdout);
fflush (stdout);
val = Qnil;
@@ -233,7 +225,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 +234,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 +247,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 +624,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;
@@ -666,7 +672,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
if (STRINGP (input_method) && !NILP (Ffboundp (Qactivate_input_method)))
call1 (Qactivate_input_method, input_method);
- Frun_hooks (1, &Qminibuffer_setup_hook);
+ run_hook (Qminibuffer_setup_hook);
/* Don't allow the user to undo past this point. */
bset_undo_list (current_buffer, Qnil);
@@ -680,8 +686,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
{
XWINDOW (minibuf_window)->cursor.hpos = 0;
XWINDOW (minibuf_window)->cursor.x = 0;
- XWINDOW (minibuf_window)->must_be_updated_p = 1;
- update_frame (XFRAME (selected_frame), 1, 1);
+ XWINDOW (minibuf_window)->must_be_updated_p = true;
+ update_frame (XFRAME (selected_frame), true, true);
flush_frame (XFRAME (XWINDOW (minibuf_window)->frame));
}
@@ -1090,7 +1096,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 +1130,9 @@ 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 = CALLN (Fformat, format, prompt,
+ CONSP (def) ? XCAR (def) : def);
}
result = Fcompleting_read (prompt, intern ("internal-complete-buffer"),
@@ -1135,13 +1140,7 @@ 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 = call3 (Vread_buffer_function, prompt, def, require_match);
return unbind_to (count, result);
}
@@ -1661,17 +1660,10 @@ Completion ignores case if the ambient value of
See also `completing-read-function'. */)
(Lisp_Object prompt, Lisp_Object collection, Lisp_Object predicate, Lisp_Object require_match, Lisp_Object initial_input, Lisp_Object hist, Lisp_Object def, Lisp_Object inherit_input_method)
{
- Lisp_Object args[9];
- args[0] = Fsymbol_value (intern ("completing-read-function"));
- args[1] = prompt;
- args[2] = collection;
- args[3] = predicate;
- args[4] = require_match;
- args[5] = initial_input;
- args[6] = hist;
- args[7] = def;
- args[8] = inherit_input_method;
- return Ffuncall (9, args);
+ return CALLN (Ffuncall,
+ Fsymbol_value (intern ("completing-read-function")),
+ prompt, collection, predicate, require_match, initial_input,
+ hist, def, inherit_input_method);
}
/* Test whether TXT is an exact completion. */
@@ -1793,8 +1785,6 @@ the values STRING, PREDICATE and `lambda'. */)
return Qt;
}
-static Lisp_Object Qmetadata;
-
DEFUN ("internal-complete-buffer", Finternal_complete_buffer, Sinternal_complete_buffer, 3, 3, 0,
doc: /* Perform completion on buffer names.
STRING and PREDICATE have the same meanings as in `try-completion',
@@ -1928,9 +1918,14 @@ syms_of_minibuf (void)
Fset (Qbuffer_name_history, Qnil);
DEFSYM (Qcustom_variable_p, "custom-variable-p");
+
+ /* Normal hooks for entry to and exit from minibuffer. */
DEFSYM (Qminibuffer_setup_hook, "minibuffer-setup-hook");
DEFSYM (Qminibuffer_exit_hook, "minibuffer-exit-hook");
+
+ /* The maximum length of a minibuffer history. */
DEFSYM (Qhistory_length, "history-length");
+
DEFSYM (Qcurrent_input_method, "current-input-method");
DEFSYM (Qactivate_input_method, "activate-input-method");
DEFSYM (Qcase_fold_search, "case-fold-search");
@@ -2079,6 +2074,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 8fa0484d180..3c2277e6955 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 (&current_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 (&current_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 33d63a65728..cc2e49641e8 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;
@@ -63,35 +61,6 @@ int fns_trace_num = 1;
extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
-extern Lisp_Object Qforeground_color;
-extern Lisp_Object Qbackground_color;
-extern Lisp_Object Qcursor_color;
-extern Lisp_Object Qinternal_border_width;
-extern Lisp_Object Qvisibility;
-extern Lisp_Object Qcursor_type;
-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 Qauto_raise;
-extern Lisp_Object Qauto_lower;
-extern Lisp_Object Qbox;
-extern Lisp_Object Qscroll_bar_width;
-extern Lisp_Object Qx_resource_name;
-extern Lisp_Object Qface_set_after_frame_default;
-extern Lisp_Object Qunderline, Qundefined;
-extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
-extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
-
-
-Lisp_Object Qbuffered;
-Lisp_Object Qfontsize;
-
EmacsTooltip *ns_tooltip = nil;
/* Need forward declaration here to preserve organizational integrity of file */
@@ -135,7 +104,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 +166,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 +178,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;
@@ -724,6 +693,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, Qinternal_border_width);
+
+ SET_FRAME_GARBAGED (f);
+}
+
+
static void
ns_implicitly_set_icon_type (struct frame *f)
{
@@ -890,12 +879,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
@@ -969,17 +962,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 */
@@ -1041,7 +1036,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)))
{
@@ -1188,13 +1183,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);
@@ -1223,7 +1215,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
@@ -1235,6 +1227,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"),
@@ -1255,11 +1250,9 @@ 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,
+ Qx_create_frame_1);
/* The resources controlling the menu-bar and tool-bar are
processed specially at startup, and reflected in the mode
@@ -1295,6 +1288,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];
@@ -1320,16 +1315,19 @@ 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);
+ /* Allow x_set_window_size, now. */
+ f->can_x_set_window_size = true;
+
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1,
+ Qx_create_frame_2);
if (! f->output_data.ns->explicit_parent)
{
@@ -1401,11 +1399,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];
@@ -1427,8 +1425,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
@@ -1438,8 +1435,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)
@@ -1519,8 +1515,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]];
@@ -1980,7 +1975,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
@@ -2113,7 +2108,6 @@ ns_do_applescript (Lisp_Object script, Lisp_Object *result)
returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
[scriptObject release];
-
*result = Qnil;
if (returnDescriptor != NULL)
@@ -2174,6 +2168,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);
@@ -2201,8 +2196,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;
@@ -2242,6 +2239,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)
@@ -2530,7 +2536,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;
@@ -2938,8 +2944,7 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
void
syms_of_nsfns (void)
{
- Qfontsize = intern_c_string ("fontsize");
- staticpro (&Qfontsize);
+ DEFSYM (Qfontsize, "fontsize");
DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
diff --git a/src/nsfont.m b/src/nsfont.m
index 714ce602c19..683ab178836 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -45,11 +45,6 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu)
#define NSFONT_TRACE 0
#define LCD_SMOOTHING_MARGIN 2
-extern Lisp_Object Qns;
-extern Lisp_Object Qnormal, Qbold, Qitalic;
-static Lisp_Object Qapple, Qroman, Qmedium;
-static Lisp_Object Qcondensed, Qexpanded;
-extern Lisp_Object Qappend;
extern float ns_antialias_threshold;
@@ -98,7 +93,7 @@ ns_get_family (Lisp_Object font_spec)
return nil;
else
{
- char *tmp = xstrdup (SSDATA (SYMBOL_NAME (tem)));
+ char *tmp = xlispstrdup (SYMBOL_NAME (tem));
NSString *family;
ns_unescape_name (tmp);
family = [NSString stringWithUTF8String: tmp];
@@ -627,8 +622,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 +644,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 +825,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 +937,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 +983,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 +995,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 +1019,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 +1029,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 +1052,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 +1093,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 +1188,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 +1270,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);
}
@@ -1493,7 +1488,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
characterIndex: (NSUInteger)charIndex
{
len = glyphIndex+length;
- for (i =glyphIndex; i<len; i++)
+ for (i =glyphIndex; i<len; i++)
cglyphs[i] = glyphs[i-glyphIndex];
if (len > maxGlyph)
maxGlyph = len;
diff --git a/src/nsgui.h b/src/nsgui.h
index aa153aff475..498eb7f87f5 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 541585a3985..f37ad38ad1e 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -34,8 +34,6 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
#include "nsterm.h"
#include "frame.h"
-extern Lisp_Object QCfile, QCdata;
-
/* call tracing */
#if 0
int image_trace_num = 0;
@@ -175,7 +173,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
[NSString stringWithUTF8String: SSDATA (found)]];
image->bmRep = nil;
-#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 27ba6928eea..26fe26e5e0d 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -59,12 +59,6 @@ int menu_trace_num = 0;
#include "nsmenu_common.c"
#endif
-extern Lisp_Object Qundefined, Qmenu_enable, Qmenu_bar_update_hook;
-extern Lisp_Object QCtoggle, QCradio;
-
-Lisp_Object Qdebug_on_next_call;
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
extern long context_menu_value;
EmacsMenu *mainMenu, *svcsMenu, *dockMenu;
@@ -266,12 +260,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 +368,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 +425,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 +486,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 +534,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 +562,6 @@ extern NSString *NSMenuDidBeginTrackingNotification;
{
--trackingMenu;
}
-#endif /* OSX >= 10.5 */
#endif /* NS_IMPL_COCOA */
@@ -620,8 +590,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 +687,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 +791,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 +799,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 +878,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 +923,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 +947,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 +957,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;
}
@@ -1188,7 +1136,10 @@ update_frame_tool_bar (struct frame *f)
if (oldh != FRAME_TOOLBAR_HEIGHT (f))
[view updateFrameSize:YES];
if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
+ {
+ view->wait_for_tool_bar = NO;
[view setNeedsDisplay: YES];
+ }
unblock_input ();
}
@@ -1464,11 +1415,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;
@@ -1477,41 +1427,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;
@@ -1955,6 +1870,5 @@ syms_of_nsmenu (void)
defsubr (&Sns_reset_menu);
defsubr (&Smenu_or_popup_active_p);
- Qdebug_on_next_call = intern_c_string ("debug-on-next-call");
- staticpro (&Qdebug_on_next_call);
+ DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
}
diff --git a/src/nsselect.m b/src/nsselect.m
index c660e80e56d..1544b16dc9d 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -26,7 +26,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
*/
/* This should be the first include, as it may set up #defines affecting
- interpretation of even the system includes. */
+ interpretation of even the system includes. */
#include <config.h>
#include "lisp.h"
@@ -34,17 +34,14 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
#include "termhooks.h"
#include "keyboard.h"
-Lisp_Object QCLIPBOARD, QSECONDARY, QTEXT, QFILE_NAME;
-
static Lisp_Object Vselection_alist;
-static Lisp_Object Qforeign_selection;
-
/* NSGeneralPboard is pretty much analogous to X11 CLIPBOARD */
-NSString *NXPrimaryPboard;
-NSString *NXSecondaryPboard;
+static NSString *NXPrimaryPboard;
+static NSString *NXSecondaryPboard;
+static NSMutableDictionary *pasteboard_changecount;
/* ==========================================================================
@@ -140,6 +137,29 @@ ns_undeclare_pasteboard (id pb)
[pb declareTypes: [NSArray array] owner: nil];
}
+static void
+ns_store_pb_change_count (id pb)
+{
+ [pasteboard_changecount
+ setObject: [NSNumber numberWithLong: [pb changeCount]]
+ forKey: [pb name]];
+}
+
+static NSInteger
+ns_get_pb_change_count (Lisp_Object selection)
+{
+ id pb = ns_symbol_to_pb (selection);
+ return pb != nil ? [pb changeCount] : -1;
+}
+
+static NSInteger
+ns_get_our_change_count_for (Lisp_Object selection)
+{
+ NSNumber *num = [pasteboard_changecount
+ objectForKey: symbol_to_nsstring (selection)];
+ return num != nil ? (NSInteger)[num longValue] : -1;
+}
+
static void
ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype)
@@ -161,8 +181,10 @@ ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype)
length: SBYTES (str)
encoding: NSUTF8StringEncoding
freeWhenDone: NO];
+ // FIXME: Why those 2 different code paths?
if (gtype == nil)
{
+ // Used for ns_string_to_pasteboard
[pb declareTypes: ns_send_types owner: nil];
tenum = [ns_send_types objectEnumerator];
while ( (type = [tenum nextObject]) )
@@ -170,61 +192,23 @@ ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype)
}
else
{
+ // Used for ns-own-selection-internal.
+ eassert (gtype == NSStringPboardType);
[pb setString: nsStr forType: gtype];
}
[nsStr release];
+ ns_store_pb_change_count (pb);
}
}
Lisp_Object
ns_get_local_selection (Lisp_Object selection_name,
- Lisp_Object target_type)
+ Lisp_Object target_type)
{
Lisp_Object local_value;
- Lisp_Object handler_fn, value, check;
- ptrdiff_t count;
-
local_value = assq_no_quit (selection_name, Vselection_alist);
-
- if (NILP (local_value)) return Qnil;
-
- count = specpdl_ptr - specpdl;
- specbind (Qinhibit_quit, Qt);
- CHECK_SYMBOL (target_type);
- handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
- if (!NILP (handler_fn))
- value = call3 (handler_fn, selection_name, target_type,
- XCAR (XCDR (local_value)));
- else
- value = Qnil;
- unbind_to (count, Qnil);
-
- check = value;
- if (CONSP (value) && SYMBOLP (XCAR (value)))
- {
- check = XCDR (value);
- }
-
- if (STRINGP (check) || VECTORP (check) || SYMBOLP (check)
- || INTEGERP (check) || NILP (value))
- return value;
-
- if (CONSP (check)
- && INTEGERP (XCAR (check))
- && (INTEGERP (XCDR (check))||
- (CONSP (XCDR (check))
- && INTEGERP (XCAR (XCDR (check)))
- && NILP (XCDR (XCDR (check))))))
- return value;
-
- // FIXME: Why `quit' rather than `error'?
- Fsignal (Qquit,
- list3 (build_string ("invalid data returned by"
- " selection-conversion function"),
- handler_fn, value));
- // FIXME: Beware, `quit' can return!!
- return Qnil;
+ return local_value;
}
@@ -328,25 +312,19 @@ 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;
NSString *type;
Lisp_Object successful_p = Qnil, rest;
- Lisp_Object target_symbol, data;
+ Lisp_Object target_symbol;
check_window_system (NULL);
CHECK_SYMBOL (selection);
@@ -356,27 +334,28 @@ On Nextstep, FRAME is unused. */)
if (pb == nil) return Qnil;
ns_declare_pasteboard (pb);
- old_value = assq_no_quit (selection, Vselection_alist);
- new_value = list2 (selection, value);
+ {
+ Lisp_Object old_value = assq_no_quit (selection, Vselection_alist);
+ Lisp_Object new_value = list2 (selection, value);
- if (NILP (old_value))
- Vselection_alist = Fcons (new_value, Vselection_alist);
- else
- Fsetcdr (old_value, Fcdr (new_value));
+ if (NILP (old_value))
+ Vselection_alist = Fcons (new_value, Vselection_alist);
+ else
+ Fsetcdr (old_value, Fcdr (new_value));
+ }
/* We only support copy of text. */
type = NSStringPboardType;
target_symbol = ns_string_to_symbol (type);
- data = ns_get_local_selection (selection, target_symbol);
- if (!NILP (data))
+ if (STRINGP (value))
{
- if (STRINGP (data))
- ns_string_to_pasteboard_internal (pb, data, type);
+ ns_string_to_pasteboard_internal (pb, value, type);
successful_p = Qt;
}
if (!EQ (Vns_sent_selection_hooks, Qunbound))
{
+ /* FIXME: Use run-hook-with-args! */
for (rest = Vns_sent_selection_hooks; CONSP (rest); rest = Fcdr (rest))
call3 (Fcar (rest), selection, target_symbol, successful_p);
}
@@ -385,26 +364,19 @@ 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);
CHECK_SYMBOL (selection);
- if (NILP (assq_no_quit (selection, Vselection_alist))) return Qnil;
+
+ if (ns_get_pb_change_count (selection)
+ != ns_get_our_change_count_for (selection))
+ return Qnil;
pb = ns_symbol_to_pb (selection);
if (pb != nil) ns_undeclare_pasteboard (pb);
@@ -412,7 +384,7 @@ On MS-DOS, all this does is return non-nil if we own the selection. */)
}
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
+DEFUN ("ns-selection-exists-p", Fns_selection_exists_p, Sns_selection_exists_p,
0, 2, 0, doc: /* Whether there is an owner for the given X selection.
SELECTION should be the name of the selection in question, typically
one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects
@@ -443,7 +415,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
@@ -463,12 +435,14 @@ On Nextstep, TERMINAL is unused. */)
CHECK_SYMBOL (selection);
if (EQ (selection, Qnil)) selection = QPRIMARY;
if (EQ (selection, Qt)) selection = QSECONDARY;
- return (NILP (Fassq (selection, Vselection_alist))) ? Qnil : Qt;
+ return ns_get_pb_change_count (selection)
+ == ns_get_our_change_count_for (selection)
+ ? Qt : Qnil;
}
-DEFUN ("x-get-selection-internal", Fx_get_selection_internal,
- Sx_get_selection_internal, 2, 4, 0,
+DEFUN ("ns-get-selection", Fns_get_selection,
+ Sns_get_selection, 2, 4, 0,
doc: /* Return text selected from some X window.
SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
\(Those are literal upper-case symbol names, since that's what X expects.)
@@ -485,12 +459,15 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */)
(Lisp_Object selection_name, Lisp_Object target_type,
Lisp_Object time_stamp, Lisp_Object terminal)
{
- Lisp_Object val;
+ Lisp_Object val = Qnil;
check_window_system (NULL);
CHECK_SYMBOL (selection_name);
CHECK_SYMBOL (target_type);
- val = ns_get_local_selection (selection_name, target_type);
+
+ if (ns_get_pb_change_count (selection_name)
+ == ns_get_our_change_count_for (selection_name))
+ val = ns_get_local_selection (selection_name, target_type);
if (NILP (val))
val = ns_get_foreign_selection (selection_name, target_type);
if (CONSP (val) && SYMBOLP (Fcar (val)))
@@ -504,55 +481,38 @@ 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'. */)
- (Lisp_Object selection)
-{
- id pb;
- check_window_system (NULL);
- pb = ns_symbol_to_pb (selection);
- return pb != nil ? ns_string_from_pasteboard (pb) : Qnil;
-}
-
-
-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'. */)
- (Lisp_Object selection, Lisp_Object string)
-{
- id pb;
- check_window_system (NULL);
- pb = ns_symbol_to_pb (selection);
- if (pb != nil) ns_string_to_pasteboard (pb, string);
- return Qnil;
-}
-
-
void
nxatoms_of_nsselect (void)
{
NXPrimaryPboard = @"Selection";
NXSecondaryPboard = @"Secondary";
+
+ // This is a memory loss, never released.
+ pasteboard_changecount =
+ [[NSMutableDictionary
+ dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithLong:0], NSGeneralPboard,
+ [NSNumber numberWithLong:0], NXPrimaryPboard,
+ [NSNumber numberWithLong:0], NXSecondaryPboard,
+ [NSNumber numberWithLong:0], NSStringPboardType,
+ [NSNumber numberWithLong:0], NSFilenamesPboardType,
+ [NSNumber numberWithLong:0], NSTabularTextPboardType,
+ nil] retain];
}
void
syms_of_nsselect (void)
{
- QCLIPBOARD = intern_c_string ("CLIPBOARD"); staticpro (&QCLIPBOARD);
- QSECONDARY = intern_c_string ("SECONDARY"); staticpro (&QSECONDARY);
- QTEXT = intern_c_string ("TEXT"); staticpro (&QTEXT);
- QFILE_NAME = intern_c_string ("FILE_NAME"); staticpro (&QFILE_NAME);
-
- defsubr (&Sx_disown_selection_internal);
- defsubr (&Sx_get_selection_internal);
- defsubr (&Sx_own_selection_internal);
- defsubr (&Sx_selection_exists_p);
- defsubr (&Sx_selection_owner_p);
- defsubr (&Sns_get_selection_internal);
- defsubr (&Sns_store_selection_internal);
+ DEFSYM (QCLIPBOARD, "CLIPBOARD");
+ DEFSYM (QSECONDARY, "SECONDARY");
+ DEFSYM (QTEXT, "TEXT");
+ DEFSYM (QFILE_NAME, "FILE_NAME");
+
+ defsubr (&Sns_disown_selection_internal);
+ defsubr (&Sns_get_selection);
+ defsubr (&Sns_own_selection_internal);
+ defsubr (&Sns_selection_exists_p);
+ defsubr (&Sns_selection_owner_p);
Vselection_alist = Qnil;
staticpro (&Vselection_alist);
@@ -570,30 +530,4 @@ to convert into a type that we don't know about or that is inappropriate.\n\
This hook doesn't let you change the behavior of Emacs's selection replies,\n\
it merely informs you that they have happened.");
Vns_sent_selection_hooks = Qnil;
-
- DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
- "An alist associating X Windows selection-types with functions.\n\
-These functions are called to convert the selection, with three args:\n\
-the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
-a desired type to which the selection should be converted;\n\
-and the local selection value (whatever was given to `x-own-selection').\n\
-\n\
-The function should return the value to send to the X server\n\
-\(typically a string). A return value of nil\n\
-means that the conversion could not be done.\n\
-A return value which is the symbol `NULL'\n\
-means that a side-effect was executed,\n\
-and there is no meaningful selection value.");
- Vselection_converter_alist = Qnil;
-
- DEFVAR_LISP ("ns-lost-selection-hooks", Vns_lost_selection_hooks,
- "A list of functions to be called when Emacs loses an X selection.\n\
-\(This happens when some other X client makes its own selection\n\
-or when a Lisp program explicitly clears the selection.)\n\
-The functions are called with one argument, the selection type\n\
-\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD').");
- Vns_lost_selection_hooks = Qnil;
-
- Qforeign_selection = intern_c_string ("foreign-selection");
- staticpro (&Qforeign_selection);
}
diff --git a/src/nsterm.h b/src/nsterm.h
index df4dd2f738d..9035ee1a328 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
@@ -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
@@ -396,7 +376,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;
@@ -408,7 +388,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
@@ -600,6 +579,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;
@@ -740,12 +722,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. */
@@ -754,6 +744,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)
@@ -771,8 +768,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);
@@ -795,7 +792,6 @@ struct glyph_string;
void ns_dump_glyphstring (struct glyph_string *s);
/* Implemented in nsterm, published in or needed from nsfns. */
-extern Lisp_Object Qfontsize;
extern Lisp_Object ns_list_fonts (struct frame *f, Lisp_Object pattern,
int size, int maxnames);
extern void ns_clear_frame (struct frame *f);
@@ -849,7 +845,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
@@ -890,6 +886,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 ();
+
#ifdef __OBJC__
/* From nsterm.m, needed in nsfont.m. */
extern void
@@ -913,6 +912,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 9ba08522309..ee1268ef850 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
@@ -227,14 +225,6 @@ static unsigned convert_ns_to_X_keysym[] =
0x1B, 0x1B /* escape */
};
-static Lisp_Object Qmodifier_value;
-Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
-extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft;
-
-static Lisp_Object QUTF8_STRING;
-static Lisp_Object Qcocoa, Qgnustep;
-static Lisp_Object Qfile, Qurl;
-
/* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
the maximum font size to NOT antialias. On GNUstep there is currently
no way to control this behavior. */
@@ -283,6 +273,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;
@@ -378,8 +373,11 @@ static CGPoint menu_mouse_point;
if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
if (q_event_ptr) \
{ \
+ Lisp_Object tem = Vinhibit_quit; \
+ Vinhibit_quit = Qt; \
n_emacs_events_pending++; \
kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
+ Vinhibit_quit = tem; \
} \
else \
hold_event (emacs_event); \
@@ -406,6 +404,18 @@ ns_set_represented_filename (NSString* fstr, struct frame *f)
represented_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)
@@ -699,7 +709,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);
@@ -732,7 +741,6 @@ ns_update_auto_hide_menu_bar (void)
unblock_input ();
#endif
-#endif
}
@@ -1069,7 +1077,7 @@ ns_lower_frame (struct frame *f)
static void
-ns_frame_raise_lower (struct frame *f, int raise)
+ns_frame_raise_lower (struct frame *f, bool raise)
/* --------------------------------------------------------------------------
External (hook)
-------------------------------------------------------------------------- */
@@ -1309,7 +1317,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
void
x_set_window_size (struct frame *f,
- int change_grav,
+ bool change_gravity,
int width,
int height,
bool pixelwise)
@@ -1335,10 +1343,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);
@@ -1403,12 +1407,7 @@ x_set_window_size (struct frame *f,
[view setBoundsOrigin: origin];
}
- change_frame_size (f, width, height, 0, 1, 0, pixelwise);
-/* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
-
- mark_window_cursors_off (XWINDOW (f->root_window));
- cancel_mouse_face (f);
-
+ [view updateFrameSize: NO];
unblock_input ();
}
@@ -1810,12 +1809,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? */
@@ -1827,28 +1826,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)
/* ------------------------------------------------------------------------
@@ -1937,7 +1914,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
/*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));
@@ -2009,8 +1986,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)
@@ -2317,52 +2293,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);
@@ -2397,8 +2327,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
@@ -2481,7 +2422,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;
}
@@ -2596,38 +2540,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
@@ -3094,7 +3018,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);
@@ -3353,10 +3277,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
@@ -3515,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)
@@ -3580,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)
@@ -3613,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
@@ -3640,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;
@@ -3649,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;
@@ -3750,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';
@@ -3824,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;
BOOL update_p = YES;
/* optimization; display engine sends WAY too many of these.. */
@@ -3856,18 +3800,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 ();
@@ -3881,7 +3818,7 @@ ns_set_vertical_scroll_bar (struct window *window,
wset_vertical_scroll_bar (window, Qnil);
[bar release];
}
- ns_clear_frame_area (f, sb_left, top, width, height);
+ ns_clear_frame_area (f, left, top, width, height);
unblock_input ();
return;
}
@@ -3889,12 +3826,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));
@@ -3909,7 +3841,101 @@ 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];
+ }
+ }
+
+ if (update_p)
+ [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);
+ BOOL update_p = YES;
+
+ /* 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--;
+ update_p = NO;
+ }
+ }
+
+ 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));
+ update_p = YES;
+ }
+ 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];
update_p = YES;
}
@@ -3957,6 +3983,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];
+ }
}
@@ -4132,7 +4164,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
};
@@ -4172,38 +4206,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;
}
@@ -4290,7 +4316,7 @@ ns_term_init (Lisp_Object display_name)
dpyinfo->name_list_element = Fcons (display_name, Qnil);
- terminal->name = xstrdup (SSDATA (display_name));
+ terminal->name = xlispstrdup (display_name);
unblock_input ();
@@ -4508,27 +4534,28 @@ ns_term_shutdown (int sig)
return;
}
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- if (isFirst) [self finishLaunching];
- isFirst = NO;
+ 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];
+ 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
@@ -4716,14 +4743,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);
}
@@ -4731,10 +4756,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
}
@@ -5074,11 +5097,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]))
@@ -5130,7 +5153,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;
@@ -5361,7 +5384,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. */
@@ -5757,14 +5780,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);
@@ -5825,7 +5844,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)
@@ -6045,6 +6065,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];
@@ -6498,8 +6526,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;
@@ -6539,7 +6566,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];
}
@@ -6551,8 +6578,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];
@@ -6571,7 +6597,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];
@@ -6877,7 +6903,7 @@ if (cols > 0 && rows > 0)
}
else
{
- error ("Invalid data type in dragging pasteboard");
+ fprintf (stderr, "Invalid data type in dragging pasteboard");
return NO;
}
}
@@ -7067,7 +7093,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];
@@ -7079,7 +7105,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
@@ -7284,7 +7310,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
@@ -7298,7 +7324,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
@@ -7506,7 +7532,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;
}
@@ -7556,8 +7582,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)
{
@@ -7571,10 +7595,23 @@ 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),
- FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
+ x_set_window_size (f, false, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), true);
return font_object;
}
@@ -7756,6 +7793,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.
@@ -7793,14 +7836,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 cc9f0826f7f..1a0aebbeba7 100644
--- a/src/print.c
+++ b/src/print.c
@@ -37,14 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "termhooks.h" /* For struct terminal. */
#include "font.h"
-Lisp_Object Qstandard_output;
-
-static Lisp_Object Qtemp_buffer_setup_hook;
-
-/* These are used to print like we read. */
-
-static Lisp_Object Qfloat_output_format;
-
#include <float.h>
#include <ftoastr.h>
@@ -58,6 +50,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;
@@ -69,9 +64,6 @@ static ptrdiff_t print_buffer_pos;
/* Bytes stored in print_buffer. */
static ptrdiff_t print_buffer_pos_byte;
-Lisp_Object Qprint_escape_newlines;
-static Lisp_Object Qprint_escape_multibyte, Qprint_escape_nonascii;
-
/* Vprint_number_table is a table, that keeps objects that are going to
be printed, to allow use of #n= and #n# to express sharing.
For any given object, the table can give the following values:
@@ -169,11 +161,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 +230,7 @@ printchar (unsigned int ch, Lisp_Object fun)
}
else if (noninteractive)
{
+ printchar_stdout_last = ch;
fwrite (str, 1, len, stdout);
noninteractive_need_newline = 1;
}
@@ -501,7 +496,7 @@ temp_output_buffer_setup (const char *bufname)
Ferase_buffer ();
XSETBUFFER (buf, current_buffer);
- Frun_hooks (1, &Qtemp_buffer_setup_hook);
+ run_hook (Qtemp_buffer_setup_hook);
unbind_to (count, Qnil);
@@ -513,19 +508,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 +590,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 +603,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 +626,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);
@@ -699,10 +705,6 @@ is used instead. */)
return object;
}
-/* The subroutine object for external-debugging-output is kept here
- for the convenience of the debugger. */
-Lisp_Object Qexternal_debugging_output;
-
DEFUN ("external-debugging-output", Fexternal_debugging_output, Sexternal_debugging_output, 1, 1, 0,
doc: /* Write CHARACTER to stderr.
You can call print while debugging emacs, and pass it this function
@@ -1169,12 +1171,7 @@ print_preprocess (Lisp_Object obj)
if (PRINT_CIRCLE_CANDIDATE_P (obj))
{
if (!HASH_TABLE_P (Vprint_number_table))
- {
- Lisp_Object args[2];
- args[0] = QCtest;
- args[1] = Qeq;
- Vprint_number_table = Fmake_hash_table (2, args);
- }
+ Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq);
/* In case print-circle is nil and print-gensym is t,
add OBJ to Vprint_number_table only when OBJ is a symbol. */
@@ -1228,7 +1225,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 +1470,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 +1966,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 +1979,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);
@@ -2072,14 +2078,16 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
for (i = 0; i < limit; i++)
{
Lisp_Object maybe = area[i];
+ int valid = valid_lisp_object_p (maybe);
- if (valid_lisp_object_p (maybe) > 0)
+ if (0 < valid)
{
PRINTCHAR (' ');
print_object (maybe, printcharfun, escapeflag);
}
else
- strout (" <invalid>", -1, -1, printcharfun);
+ strout (valid ? " <some>" : " <invalid>",
+ -1, -1, printcharfun);
}
if (i == limit && i < amount)
strout (" ...", 4, 4, printcharfun);
@@ -2192,7 +2200,10 @@ print_interval (INTERVAL interval, Lisp_Object printcharfun)
void
init_print_once (void)
{
+ /* The subroutine object for external-debugging-output is kept here
+ for the convenience of the debugger. */
DEFSYM (Qexternal_debugging_output, "external-debugging-output");
+
defsubr (&Sexternal_debugging_output);
}
diff --git a/src/process.c b/src/process.c
index 5b16af02908..1d935ba8a3e 100644
--- a/src/process.c
+++ b/src/process.c
@@ -140,12 +140,6 @@ extern int sys_select (int, fd_set *, fd_set *, fd_set *,
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
# pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif
-
-Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
-Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
-Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
-Lisp_Object QCname, QCtype;
/* True if keyboard input is on hold, zero otherwise. */
@@ -191,27 +185,6 @@ process_socket (int domain, int type, int protocol)
# define socket(domain, type, protocol) process_socket (domain, type, protocol)
#endif
-Lisp_Object Qprocessp;
-static Lisp_Object Qrun, Qstop, Qsignal;
-static Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal;
-static Lisp_Object Qipv4, Qdatagram, Qseqpacket;
-static Lisp_Object Qreal, Qnetwork, Qserial;
-#ifdef AF_INET6
-static Lisp_Object Qipv6;
-#endif
-static Lisp_Object QCport, QCprocess;
-Lisp_Object QCspeed;
-Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
-Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
-static Lisp_Object QCbuffer, QChost, QCservice;
-static Lisp_Object QClocal, QCremote, QCcoding;
-static Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
-static Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
-static Lisp_Object Qlast_nonmenu_event;
-static Lisp_Object Qinternal_default_process_sentinel;
-static Lisp_Object Qinternal_default_process_filter;
-
#define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
#define NETCONN1_P(p) (EQ (p->type, Qnetwork))
#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
@@ -227,8 +200,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 +258,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);
@@ -331,10 +299,10 @@ static int max_process_desc;
/* The largest descriptor currently in use for input; -1 if none. */
static int max_input_desc;
-/* Indexed by descriptor, gives the process (if any) for that descriptor */
+/* Indexed by descriptor, gives the process (if any) for that descriptor. */
static Lisp_Object chan_process[FD_SETSIZE];
-/* Alist of elements (NAME . PROCESS) */
+/* Alist of elements (NAME . PROCESS). */
static Lisp_Object Vprocess_alist;
/* Buffered-ahead input char from process, indexed by channel.
@@ -454,6 +422,11 @@ pset_write_queue (struct Lisp_Process *p, Lisp_Object val)
}
+static Lisp_Object
+make_lisp_proc (struct Lisp_Process *p)
+{
+ return make_lisp_ptr (p, Lisp_Vectorlike);
+}
static struct fd_callback_data
{
@@ -461,7 +434,7 @@ static struct fd_callback_data
void *data;
#define FOR_READ 1
#define FOR_WRITE 2
- int condition; /* mask of the defines above. */
+ int condition; /* Mask of the defines above. */
} fd_callback_info[FD_SETSIZE];
@@ -471,7 +444,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 +456,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 +472,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 +502,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 +577,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 +601,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 +610,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));
@@ -700,8 +669,8 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
have a race condition between the PTY_OPEN and here. */
fcntl (fd, F_SETFD, FD_CLOEXEC);
#endif
- /* check to make certain that both sides are available
- this avoids a nasty yet stupid bug in rlogins */
+ /* Check to make certain that both sides are available
+ this avoids a nasty yet stupid bug in rlogins. */
#ifdef PTY_TTY_NAME_SPRINTF
PTY_TTY_NAME_SPRINTF
#else
@@ -723,7 +692,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
#endif /* HAVE_PTYS */
return -1;
}
-
+
+/* Allocate basically initialized process. */
+
+static struct Lisp_Process *
+allocate_process (void)
+{
+ return ALLOCATE_ZEROED_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS);
+}
+
static Lisp_Object
make_process (Lisp_Object name)
{
@@ -873,7 +850,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 +870,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 +1291,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))
@@ -1348,18 +1329,16 @@ Returns nil if format of ADDRESS is invalid. */)
&& XINT (p->contents[i]) > 255)
return Qnil;
- args[i+1] = p->contents[i];
+ 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 CALLN (Fformat, format, Fcar (address));
}
return Qnil;
@@ -1398,9 +1377,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 +1456,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 +1475,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);
@@ -1550,11 +1530,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
tem = program;
}
- /* If program file name starts with /: for quoting a magic name,
- discard that. */
- if (SBYTES (tem) > 2 && SREF (tem, 0) == '/'
- && SREF (tem, 1) == ':')
- tem = Fsubstring (tem, make_number (2), Qnil);
+ /* Remove "/:" from TEM. */
+ tem = remove_slash_colon (tem);
{
Lisp_Object arg_encoding = Qnil;
@@ -1590,7 +1567,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 +1581,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
else
create_pty (proc);
+ SAFE_FREE ();
return unbind_to (count, proc);
}
@@ -1666,6 +1644,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;
@@ -1727,11 +1706,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
if (inchannel > max_process_desc)
max_process_desc = inchannel;
- /* This may signal an error. */
+ /* This may signal an error. */
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 +1834,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 +1853,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 +1948,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)
{
@@ -2003,7 +1979,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr;
- len = sizeof (sin6->sin6_addr)/2 + 1;
+ len = sizeof (sin6->sin6_addr) / 2 + 1;
address = Fmake_vector (make_number (len), Qnil);
p = XVECTOR (address);
p->contents[--len] = make_number (ntohs (sin6->sin6_port));
@@ -2024,11 +2000,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 +2061,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;
@@ -2212,14 +2190,14 @@ Returns nil upon error setting address, ADDRESS otherwise. */)
static const struct socket_options {
/* The name of this option. Should be lowercase version of option
- name without SO_ prefix. */
+ name without SO_ prefix. */
const char *name;
- /* Option level SOL_... */
+ /* Option level SOL_... */
int optlevel;
- /* Option number SO_... */
+ /* Option number SO_... */
int optnum;
enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_IFNAME, SOPT_LINGER } opttype;
- enum { OPIX_NONE=0, OPIX_MISC=1, OPIX_REUSEADDR=2 } optbit;
+ enum { OPIX_NONE = 0, OPIX_MISC = 1, OPIX_REUSEADDR = 2 } optbit;
} socket_options[] =
{
#ifdef SO_BINDTODEVICE
@@ -2295,7 +2273,7 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
#ifdef SO_BINDTODEVICE
case SOPT_IFNAME:
{
- char devname[IFNAMSIZ+1];
+ char devname[IFNAMSIZ + 1];
/* This is broken, at least in the Linux 2.4 kernel.
To unbind, the arg must be a zero integer, not the empty string.
@@ -2672,7 +2650,7 @@ usage: (make-serial-process &rest ARGS) */)
exactly like a normal process when reading and writing. Primary
differences are in status display and process deletion. A network
connection has no PID; you cannot signal it. All you can do is
- stop/continue it and deactivate/close it via delete-process */
+ stop/continue it and deactivate/close it via delete-process. */
DEFUN ("make-network-process", Fmake_network_process, Smake_network_process,
0, MANY, 0,
@@ -2858,7 +2836,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;
@@ -2876,7 +2854,7 @@ usage: (make-network-process &rest ARGS) */)
GCPRO1 (contact);
#ifdef WINDOWSNT
- /* Ensure socket support is loaded if available. */
+ /* Ensure socket support is loaded if available. */
init_winsock (TRUE);
#endif
@@ -2906,8 +2884,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 +2912,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;
@@ -2983,7 +2961,7 @@ usage: (make-network-process &rest ARGS) */)
{
if (EQ (host, Qlocal))
/* Depending on setup, "localhost" may map to different IPv4 and/or
- IPv6 addresses, so it's better to be explicit. (Bug#6781) */
+ IPv6 addresses, so it's better to be explicit (Bug#6781). */
host = build_string ("127.0.0.1");
CHECK_STRING (host);
}
@@ -3003,7 +2981,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;
@@ -3115,7 +3093,7 @@ usage: (make-network-process &rest ARGS) */)
address_in.sin_family = family;
}
else
- /* Attempt to interpret host as numeric inet address */
+ /* Attempt to interpret host as numeric inet address. */
{
unsigned long numeric_addr;
numeric_addr = inet_addr (SSDATA (host));
@@ -3181,8 +3159,8 @@ usage: (make-network-process &rest ARGS) */)
/* Parse network options in the arg list.
We simply ignore anything which isn't a known option (including other keywords).
An error is signaled if setting a known option fails. */
- for (optn = optbits = 0; optn < nargs-1; optn += 2)
- optbits |= set_socket_option (s, args[optn], args[optn+1]);
+ for (optn = optbits = 0; optn < nargs - 1; optn += 2)
+ optbits |= set_socket_option (s, args[optn], args[optn + 1]);
if (is_server)
{
@@ -3253,7 +3231,7 @@ usage: (make-network-process &rest ARGS) */)
{
/* Unlike most other syscalls connect() cannot be called
again. (That would return EALREADY.) The proper way to
- wait for completion is pselect(). */
+ wait for completion is pselect(). */
int sc;
socklen_t len;
fd_set fdset;
@@ -3321,7 +3299,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)
@@ -3444,7 +3422,7 @@ usage: (make-network-process &rest ARGS) */)
struct gcpro gcpro1;
/* Qt denotes we have not yet called Ffind_operation_coding_system. */
Lisp_Object coding_systems = Qt;
- Lisp_Object fargs[5], val;
+ Lisp_Object val;
if (!NILP (tem))
{
@@ -3467,10 +3445,10 @@ usage: (make-network-process &rest ARGS) */)
coding_systems = Qnil;
else
{
- fargs[0] = Qopen_network_stream, fargs[1] = name,
- fargs[2] = buffer, fargs[3] = host, fargs[4] = service;
GCPRO1 (proc);
- coding_systems = Ffind_operation_coding_system (5, fargs);
+ coding_systems = CALLN (Ffind_operation_coding_system,
+ Qopen_network_stream, name, buffer,
+ host, service);
UNGCPRO;
}
if (CONSP (coding_systems))
@@ -3500,10 +3478,10 @@ usage: (make-network-process &rest ARGS) */)
coding_systems = Qnil;
else
{
- fargs[0] = Qopen_network_stream, fargs[1] = name,
- fargs[2] = buffer, fargs[3] = host, fargs[4] = service;
GCPRO1 (proc);
- coding_systems = Ffind_operation_coding_system (5, fargs);
+ coding_systems = CALLN (Ffind_operation_coding_system,
+ Qopen_network_stream, name, buffer,
+ host, service);
UNGCPRO;
}
}
@@ -3631,7 +3609,7 @@ static const struct ifflag_def ifflag_table[] = {
#endif
#ifdef IFF_NOTRAILERS
#ifdef NS_IMPL_COCOA
- /* Really means smart, notrailers is obsolete */
+ /* Really means smart, notrailers is obsolete. */
{ IFF_NOTRAILERS, "smart" },
#else
{ IFF_NOTRAILERS, "notrailers" },
@@ -3659,19 +3637,19 @@ static const struct ifflag_def ifflag_table[] = {
{ IFF_DYNAMIC, "dynamic" },
#endif
#ifdef IFF_OACTIVE
- { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress */
+ { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress. */
#endif
#ifdef IFF_SIMPLEX
- { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */
+ { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions. */
#endif
#ifdef IFF_LINK0
- { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit */
+ { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit. */
#endif
#ifdef IFF_LINK1
- { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit */
+ { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit. */
#endif
#ifdef IFF_LINK2
- { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit */
+ { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit. */
#endif
{ 0, 0 }
};
@@ -3694,7 +3672,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)
@@ -3862,6 +3840,18 @@ Data that is unavailable is returned as nil. */)
#endif
}
+/* If program file NAME starts with /: for quoting a magic
+ name, remove that, preserving the multibyteness of NAME. */
+
+Lisp_Object
+remove_slash_colon (Lisp_Object name)
+{
+ return
+ ((SBYTES (name) > 2 && SREF (name, 0) == '/' && SREF (name, 1) == ':')
+ ? make_specified_string (SSDATA (name) + 2, SCHARS (name) - 2,
+ SBYTES (name) - 2, STRING_MULTIBYTE (name))
+ : name);
+}
/* Turn off input and output for process PROC. */
@@ -3887,7 +3877,7 @@ deactivate_process (Lisp_Object proc)
}
#endif
- /* Beware SIGCHLD hereabouts. */
+ /* Beware SIGCHLD hereabouts. */
for (i = 0; i < PROCESS_OPEN_FDS; i++)
close_process_fd (&p->open_fd[i]);
@@ -3936,19 +3926,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 +3991,13 @@ Return non-nil if we received any output before the timeout expired. */)
nsecs = 0;
return
- (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);
+ ((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))
+ <= 0)
+ ? Qnil : Qt);
}
/* Accept a connection for server process SERVER on CHANNEL. */
@@ -4017,7 +4009,7 @@ server_accept_connection (Lisp_Object server, int channel)
{
Lisp_Object proc, caller, name, buffer;
Lisp_Object contact, host, service;
- struct Lisp_Process *ps= XPROCESS (server);
+ struct Lisp_Process *ps = XPROCESS (server);
struct Lisp_Process *p;
int s;
union u_sockaddr {
@@ -4069,20 +4061,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 = CALLN (Fformat, 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 = CALLN (Fformat, caller_format, host, service);
}
break;
@@ -4092,16 +4079,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]));
- host = Fformat (9, args);
+ args[i + 1] = make_number (ntohs (ip6[i]));
+ host = CALLMANY (Fformat, 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 = CALLN (Fformat, caller_format, host, service);
}
break;
#endif
@@ -4111,7 +4097,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 +4196,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 +4260,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 +4285,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 +4296,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;
@@ -4334,7 +4318,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
while (1)
{
- bool timeout_reduced_for_timers = 0;
+ bool timeout_reduced_for_timers = false;
/* If calling from keyboard input, do not quit
since we want to return C-g as an input character.
@@ -4348,13 +4332,17 @@ 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)
{
/* A negative timeout means
gobble output available now
- but don't wait at all. */
+ but don't wait at all. */
timeout = make_timespec (0, 0);
}
@@ -4417,7 +4405,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (timespec_cmp (timer_delay, timeout) < 0)
{
timeout = timer_delay;
- timeout_reduced_for_timers = 1;
+ timeout_reduced_for_timers = true;
}
}
else
@@ -4466,7 +4454,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,30 +4464,36 @@ 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))
{
- bool read_some_bytes = 0;
+ bool read_some_bytes = false;
clear_waiting_for_input ();
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);
@@ -4507,11 +4501,11 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
break;
}
- /* Wait till there is something to do */
+ /* Wait till there is something to do. */
if (wait_proc && just_wait_proc)
{
- if (wait_proc->infd < 0) /* Terminated */
+ if (wait_proc->infd < 0) /* Terminated. */
break;
FD_SET (wait_proc->infd, &Available);
check_delay = 0;
@@ -4530,12 +4524,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 +4551,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 +4561,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,19 +4623,20 @@ 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);
}
}
}
else
{
- /* Check this specific channel. */
+ /* Check this specific channel. */
if (wait_proc->gnutls_p /* Check for valid process. */
&& wait_proc->gnutls_state
/* Do we have pending data? */
@@ -4653,6 +4645,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);
}
@@ -4663,7 +4656,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
xerrno = errno;
- /* Make C-g and alarm signals set flags again */
+ /* Make C-g and alarm signals set flags again. */
clear_waiting_for_input ();
/* If we woke up due to SIGWINCH, actually change size now. */
@@ -4682,28 +4675,22 @@ 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 */
+ /* Check for keyboard input. */
/* If there is any, return immediately
- to give it higher priority than subprocesses */
+ to give it higher priority than subprocesses. */
if (read_kbd != 0)
{
unsigned old_timers_run = timers_run;
struct buffer *old_buffer = current_buffer;
Lisp_Object old_window = selected_window;
- bool leave = 0;
+ bool leave = false;
if (detect_input_pending_run_timers (do_display))
{
swallow_events (do_display);
if (detect_input_pending_run_timers (do_display))
- leave = 1;
+ leave = true;
}
/* If a timer has run, this might have changed buffers
@@ -4754,9 +4741,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 +4772,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 +4787,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 +4913,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 +4975,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 +5135,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
@@ -5706,7 +5686,7 @@ return t unconditionally. */)
return Qt;
}
-/* send a signal number SIGNO to PROCESS.
+/* Send a signal number SIGNO to PROCESS.
If CURRENT_GROUP is t, that means send to the process group
that currently owns the terminal being used to communicate with PROCESS.
This is used for various commands in shell mode.
@@ -5809,11 +5789,11 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
Or perhaps this is vestigial. */
if (gid == -1)
no_pgrp = 1;
-#else /* ! defined (TIOCGPGRP ) */
+#else /* ! defined (TIOCGPGRP) */
/* Can't select pgrps on this system, so we know that
the child itself heads the pgrp. */
gid = p->pid;
-#endif /* ! defined (TIOCGPGRP ) */
+#endif /* ! defined (TIOCGPGRP) */
/* If current_group is lambda, and the shell owns the terminal,
don't send any signal. */
@@ -5829,36 +5809,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,
@@ -6000,8 +5975,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */)
Lisp_Object tem = Fget_process (process);
if (NILP (tem))
{
- Lisp_Object process_number =
- string_to_number (SSDATA (process), 10, 1);
+ Lisp_Object process_number
+ = string_to_number (SSDATA (process), 10, 1);
if (INTEGERP (process_number) || FLOATP (process_number))
tem = process_number;
}
@@ -6100,8 +6075,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]);
@@ -6184,7 +6159,7 @@ static signal_handler_t volatile lib_child_handler;
Inc.
** Malloc WARNING: This should never call malloc either directly or
- indirectly; if it does, that is a bug */
+ indirectly; if it does, that is a bug. */
static void
handle_child_signal (int sig)
@@ -6257,7 +6232,7 @@ handle_child_signal (int sig)
#ifdef NS_IMPL_GNUSTEP
/* NSTask in GNUstep sets its child handler each time it is called.
So we must re-set ours. */
- catch_child_signal();
+ catch_child_signal ();
#endif
}
@@ -6357,14 +6332,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 +6375,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 +6414,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 +6550,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 +6596,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 +6628,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,
@@ -6672,7 +6664,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
while (1)
{
- bool timeout_reduced_for_timers = 0;
+ bool timeout_reduced_for_timers = false;
fd_set waitchannels;
int xerrno;
@@ -6739,7 +6731,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (timespec_cmp (timer_delay, timeout) < 0)
{
timeout = timer_delay;
- timeout_reduced_for_timers = 1;
+ timeout_reduced_for_timers = true;
}
}
}
@@ -6772,7 +6764,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
xerrno = errno;
- /* Make C-g and alarm signals set flags again */
+ /* Make C-g and alarm signals set flags again. */
clear_waiting_for_input ();
/* If we woke up due to SIGWINCH, actually change size now. */
@@ -6792,7 +6784,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
report_file_errno ("Failed select", Qnil, xerrno);
}
- /* Check for keyboard input */
+ /* Check for keyboard input. */
if (read_kbd
&& detect_input_pending_run_timers (do_display))
@@ -6828,7 +6820,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
start_polling ();
- return 0;
+ return -1;
}
#endif /* not subprocesses */
@@ -6836,12 +6828,32 @@ 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
add_keyboard_wait_descriptor (int desc)
{
-#ifdef subprocesses /* actually means "not MSDOS" */
+#ifdef subprocesses /* Actually means "not MSDOS". */
FD_SET (desc, &input_wait_mask);
FD_SET (desc, &non_process_wait_mask);
if (desc > max_input_desc)
@@ -6932,7 +6944,7 @@ the process output. */)
}
/* Kill all processes associated with `buffer'.
- If `buffer' is nil, kill all processes */
+ If `buffer' is nil, kill all processes. */
void
kill_buffer_processes (Lisp_Object buffer)
@@ -7067,24 +7079,23 @@ 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));
+ eassert (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN
+ || ! (old_action.sa_flags & SA_SIGINFO));
if (old_action.sa_handler != deliver_child_signal)
lib_child_handler
= (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 */
@@ -7212,10 +7223,7 @@ syms_of_process (void)
DEFSYM (Qsignal, "signal");
/* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
- here again.
-
- Qexit = intern_c_string ("exit");
- staticpro (&Qexit); */
+ here again. */
DEFSYM (Qopen, "open");
DEFSYM (Qclosed, "closed");
diff --git a/src/process.h b/src/process.h
index 6a0ce094a14..36979dcac9e 100644
--- a/src/process.h
+++ b/src/process.h
@@ -162,6 +162,9 @@ struct Lisp_Process
gnutls_session_t gnutls_state;
gnutls_certificate_client_credentials gnutls_x509_cred;
gnutls_anon_client_credentials_t gnutls_anon_cred;
+ gnutls_x509_crt_t gnutls_certificate;
+ unsigned int gnutls_peer_verification;
+ unsigned int gnutls_extra_peer_verification;
int gnutls_log_level;
int gnutls_handshakes_tried;
bool_bf gnutls_p : 1;
@@ -194,15 +197,6 @@ pset_gnutls_cred_type (struct Lisp_Process *p, Lisp_Object val)
when exiting. */
extern bool inhibit_sentinels;
-extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname;
-extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime;
-extern Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-extern Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtpgid, Qcstime;
-extern Lisp_Object Qtime, Qctime;
-extern Lisp_Object QCspeed;
-extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
-extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
-
/* Exit statuses for GNU programs that exec other programs. */
enum
{
@@ -213,8 +207,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 +219,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,13 +230,13 @@ 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);
extern Lisp_Object network_interface_info (Lisp_Object);
#endif
+extern Lisp_Object remove_slash_colon (Lisp_Object);
+
INLINE_HEADER_END
diff --git a/src/profiler.c b/src/profiler.c
index 8ae237a4435..1b49afe0331 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -35,7 +35,6 @@ saturated_add (EMACS_INT a, EMACS_INT b)
typedef struct Lisp_Hash_Table log_t;
-static Lisp_Object Qprofiler_backtrace_equal;
static struct hash_table_test hashtest_profiler;
static Lisp_Object
@@ -294,7 +293,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 93ba21fc7ff..b72fb6c03f9 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 b70eee81766..fb5087d4068 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 1819a31a588..41fe3fa8088 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)), \
@@ -1635,7 +1632,7 @@ static boolean at_begline_loc_p (re_char *pattern, re_char *p,
static boolean at_endline_loc_p (re_char *p, re_char *pend,
reg_syntax_t syntax);
static re_char *skip_one_char (re_char *p);
-static int analyse_first (re_char *p, re_char *pend,
+static int analyze_first (re_char *p, re_char *pend,
char *fastmap, const int multibyte);
/* Fetch the next character in the uncompiled pattern, with no
@@ -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);
}
}
}
@@ -2691,7 +2688,7 @@ regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax,
size_t startoffset = 0;
re_opcode_t ofj =
/* Check if the loop can match the empty string. */
- (simple || !analyse_first (laststart, b, NULL, 0))
+ (simple || !analyze_first (laststart, b, NULL, 0))
? on_failure_jump : on_failure_jump_loop;
assert (skip_one_char (laststart) <= b);
@@ -2738,7 +2735,7 @@ regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax,
GET_BUFFER_SPACE (7); /* We might use less. */
if (many_times_ok)
{
- boolean emptyp = analyse_first (laststart, b, NULL, 0);
+ boolean emptyp = analyze_first (laststart, b, NULL, 0);
/* The non-greedy multiple match looks like
a repeat..until: we only need a conditional jump
@@ -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))
@@ -3839,7 +3836,7 @@ group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
return false;
}
-/* analyse_first.
+/* analyze_first.
If fastmap is non-NULL, go through the pattern and fill fastmap
with all the possible leading chars. If fastmap is NULL, don't
bother filling it up (obviously) and only return whether the
@@ -3850,7 +3847,7 @@ group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
Return -1 if fastmap was not updated accurately. */
static int
-analyse_first (const_re_char *p, const_re_char *pend, char *fastmap,
+analyze_first (const_re_char *p, const_re_char *pend, char *fastmap,
const int multibyte)
{
int j, k;
@@ -4092,7 +4089,7 @@ analyse_first (const_re_char *p, const_re_char *pend, char *fastmap,
{ /* We have to look down both arms.
We first go down the "straight" path so as to minimize
stack usage when going through alternatives. */
- int r = analyse_first (p, pend, fastmap, multibyte);
+ int r = analyze_first (p, pend, fastmap, multibyte);
if (r) return r;
p += j;
}
@@ -4142,7 +4139,7 @@ analyse_first (const_re_char *p, const_re_char *pend, char *fastmap,
/* We reached the end without matching anything. */
return 1;
-} /* analyse_first */
+} /* analyze_first */
/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
@@ -4172,7 +4169,7 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
memset (fastmap, 0, 1 << BYTEWIDTH); /* Assume nothing's valid. */
bufp->fastmap_accurate = 1; /* It will be when we're done. */
- analysis = analyse_first (bufp->buffer, bufp->buffer + bufp->used,
+ analysis = analyze_first (bufp->buffer, bufp->buffer + bufp->used,
fastmap, RE_MULTIBYTE_P (bufp));
bufp->can_be_null = (analysis != 0);
return 0;
@@ -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 965425a0655..3dfecf0a7e5 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 5553cf3393b..ad7f0f7eced 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 eec642ecb20..e9617985c18 100644
--- a/src/search.c
+++ b/src/search.c
@@ -84,12 +84,6 @@ static struct re_registers search_regs;
Qnil if no searching has been done yet. */
static Lisp_Object last_thing_searched;
-/* Error condition signaled when regexp compile_pattern fails. */
-static Lisp_Object Qinvalid_regexp;
-
-/* Error condition used for failing searches. */
-static Lisp_Object Qsearch_failed;
-
static void set_search_regs (ptrdiff_t, ptrdiff_t);
static void save_search_regs (void);
static EMACS_INT simple_search (EMACS_INT, unsigned char *, ptrdiff_t,
@@ -465,17 +459,18 @@ matched by parenthesis constructs in the pattern. */)
return string_match_1 (regexp, string, start, 1);
}
-/* Match REGEXP against STRING, searching all of STRING,
- and return the index of the match, or negative on failure.
- This does not clobber the match data. */
+/* Match REGEXP against STRING using translation table TABLE,
+ searching all of STRING, and return the index of the match,
+ or negative on failure. This does not clobber the match data. */
ptrdiff_t
-fast_string_match (Lisp_Object regexp, Lisp_Object string)
+fast_string_match_internal (Lisp_Object regexp, Lisp_Object string,
+ Lisp_Object table)
{
ptrdiff_t val;
struct re_pattern_buffer *bufp;
- bufp = compile_pattern (regexp, 0, Qnil,
+ bufp = compile_pattern (regexp, 0, table,
0, STRING_MULTIBYTE (string));
immediate_quit = 1;
re_match_object = string;
@@ -510,26 +505,6 @@ fast_c_string_match_ignore_case (Lisp_Object regexp,
return val;
}
-/* Like fast_string_match but ignore case. */
-
-ptrdiff_t
-fast_string_match_ignore_case (Lisp_Object regexp, Lisp_Object string)
-{
- ptrdiff_t val;
- struct re_pattern_buffer *bufp;
-
- bufp = compile_pattern (regexp, 0, Vascii_canon_table,
- 0, STRING_MULTIBYTE (string));
- immediate_quit = 1;
- re_match_object = string;
-
- val = re_search (bufp, SSDATA (string),
- SBYTES (string), 0,
- SBYTES (string), 0);
- immediate_quit = 0;
- return val;
-}
-
/* Match REGEXP against the characters after POS to LIMIT, and return
the number of matched characters. If STRING is non-nil, match
against the characters in it. In that case, POS and LIMIT are
@@ -985,6 +960,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 +1311,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 +1329,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 +1343,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 +1351,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 +1410,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 +1491,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 +1823,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 +2592,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 +2615,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 +2675,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 +2805,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 +2849,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 +3075,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 +3094,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. */
@@ -3310,7 +3304,10 @@ syms_of_search (void)
}
searchbuf_head = &searchbufs[0];
+ /* Error condition used for failing searches. */
DEFSYM (Qsearch_failed, "search-failed");
+
+ /* Error condition signaled when regexp compile_pattern fails. */
DEFSYM (Qinvalid_regexp, "invalid-regexp");
Fput (Qsearch_failed, Qerror_conditions,
diff --git a/src/sheap.c b/src/sheap.c
index 7d2d9eb417d..58a6a0b1cd3 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 6507695cdc2..05c7b060104 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 */
@@ -97,12 +99,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* BEGIN: Common Definitions */
-/* Symbols. */
-
-static Lisp_Object QCvolume, QCdevice;
-static Lisp_Object Qsound;
-static Lisp_Object Qplay_sound_functions;
-
/* Indices of attributes in a sound attributes vector. */
enum sound_attr
@@ -567,12 +563,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 +580,7 @@ wav_play (struct sound *s, struct sound_device *sd)
if (nbytes < 0)
sound_perror ("Error reading sound file");
+ SAFE_FREE ();
}
}
@@ -659,19 +655,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 +702,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 +714,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 +748,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 +764,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 +776,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 +1203,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];
- 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);
+ /* 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;
+ }
+
+ 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 +1293,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 +1351,9 @@ 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;
+
+#ifdef WINDOWSNT
unsigned long ui_volume_tmp = UINT_MAX;
unsigned long ui_volume = UINT_MAX;
#endif /* WINDOWSNT */
@@ -1321,13 +1362,15 @@ Internal use only, use `play-sound' instead. */)
if (!parse_sound (sound, attrs))
error ("Invalid sound specification");
-#ifndef WINDOWSNT
- file = Qnil;
+ Lisp_Object file = Qnil;
GCPRO2 (sound, file);
+
+#ifndef WINDOWSNT
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]))
{
@@ -1363,9 +1406,7 @@ Internal use only, use `play-sound' instead. */)
else if (FLOATP (attrs[SOUND_VOLUME]))
current_sound_device->volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
- args[0] = Qplay_sound_functions;
- args[1] = sound;
- Frun_hook_with_args (2, args);
+ CALLN (Frun_hook_with_args, Qplay_sound_functions, sound);
#ifdef HAVE_ALSA
if (!alsa_init (current_sound_device))
@@ -1379,16 +1420,10 @@ Internal use only, use `play-sound' instead. */)
/* Play the sound. */
current_sound->play (current_sound, current_sound_device);
- /* Clean up. */
- UNGCPRO;
-
#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 +1432,9 @@ Internal use only, use `play-sound' instead. */)
{
ui_volume_tmp = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
}
+
+ CALLN (Frun_hook_with_args, Qplay_sound_functions, sound);
+
/*
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,12 +1448,12 @@ 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);
#endif /* WINDOWSNT */
- unbind_to (count, Qnil);
- return Qnil;
+ UNGCPRO;
+ return unbind_to (count, Qnil);
}
/***********************************************************************
diff --git a/src/syntax.c b/src/syntax.c
index 63e8a4b62a0..2f821564294 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -137,9 +137,6 @@ enum
ST_STRING_STYLE = 256 + 2
};
-static Lisp_Object Qsyntax_table_p;
-static Lisp_Object Qsyntax_table, Qscan_error;
-
/* This is the internal form of the parse state used in parse-partial-sexp. */
struct lisp_parse_state
@@ -835,12 +832,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 +1228,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 +1564,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 +1697,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 +1721,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 +2030,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);
}
}
@@ -3500,11 +3497,6 @@ init_syntax_once (void)
/* This has to be done here, before we call Fmake_char_table. */
DEFSYM (Qsyntax_table, "syntax-table");
- /* This variable is DEFSYMed in alloc.c and not initialized yet, so
- intern it here. NOTE: you must guarantee that init_syntax_once
- is called before all other users of this variable. */
- Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
-
/* Create objects which can be shared among syntax tables. */
Vsyntax_code_object = make_uninit_vector (Smax);
for (i = 0; i < Smax; i++)
diff --git a/src/sysdep.c b/src/sysdep.c
index 01692c2d214..a2bda96192f 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>
@@ -100,14 +110,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define _P_WAIT 0
int _cdecl _spawnlp (int, const char *, const char *, ...);
int _cdecl _getpid (void);
+/* The following is needed for O_CLOEXEC, F_SETFD, FD_CLOEXEC, and
+ several prototypes of functions called below. */
+#include <sys/socket.h>
#endif
#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 +132,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 +231,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 +266,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 +614,7 @@ init_sigio (int fd)
#endif
}
+#ifndef DOS_NT
static void
reset_sigio (int fd)
{
@@ -610,6 +622,7 @@ reset_sigio (int fd)
fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
#endif
}
+#endif
void
request_sigio (void)
@@ -657,7 +670,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 +727,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 +756,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 +787,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 +817,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 +1177,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.
@@ -1327,29 +1409,19 @@ setup_pty (int fd)
}
#endif /* HAVE_PTYS */
-#ifdef HAVE_SOCKETS
-#include <sys/socket.h>
-#include <netdb.h>
-#endif /* HAVE_SOCKETS */
-
-#ifdef TRY_AGAIN
-#ifndef HAVE_H_ERRNO
-extern int h_errno;
-#endif
-#endif /* TRY_AGAIN */
-
void
init_system_name (void)
{
+ char *hostname_alloc = NULL;
+ char *hostname;
#ifndef HAVE_GETHOSTNAME
struct utsname uts;
uname (&uts);
- Vsystem_name = build_string (uts.nodename);
+ hostname = uts.nodename;
#else /* HAVE_GETHOSTNAME */
- char *hostname_alloc = NULL;
char hostname_buf[256];
ptrdiff_t hostname_size = sizeof hostname_buf;
- char *hostname = hostname_buf;
+ hostname = hostname_buf;
/* Try to get the host name; if the buffer is too short, try
again. Apparently, the only indication gethostname gives of
@@ -1367,110 +1439,15 @@ init_system_name (void)
hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1,
min (PTRDIFF_MAX, SIZE_MAX), 1);
}
-#ifdef HAVE_SOCKETS
- /* Turn the hostname into the official, fully-qualified hostname.
- Don't do this if we're going to dump; this can confuse system
- libraries on some machines and make the dumped emacs core dump. */
-#ifndef CANNOT_DUMP
- if (initialized)
-#endif /* not CANNOT_DUMP */
- if (! strchr (hostname, '.'))
- {
- int count;
-#ifdef HAVE_GETADDRINFO
- struct addrinfo *res;
- struct addrinfo hints;
- int ret;
-
- memset (&hints, 0, sizeof (hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_CANONNAME;
-
- for (count = 0;; count++)
- {
- if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
- || ret != EAI_AGAIN)
- break;
-
- if (count >= 5)
- break;
- Fsleep_for (make_number (1), Qnil);
- }
-
- if (ret == 0)
- {
- struct addrinfo *it = res;
- while (it)
- {
- char *fqdn = it->ai_canonname;
- if (fqdn && strchr (fqdn, '.')
- && strcmp (fqdn, "localhost.localdomain") != 0)
- break;
- it = it->ai_next;
- }
- if (it)
- {
- ptrdiff_t len = strlen (it->ai_canonname);
- if (hostname_size <= len)
- {
- hostname_size = len + 1;
- hostname = hostname_alloc = xrealloc (hostname_alloc,
- hostname_size);
- }
- strcpy (hostname, it->ai_canonname);
- }
- freeaddrinfo (res);
- }
-#else /* !HAVE_GETADDRINFO */
- struct hostent *hp;
- for (count = 0;; count++)
- {
-
-#ifdef TRY_AGAIN
- h_errno = 0;
-#endif
- hp = gethostbyname (hostname);
-#ifdef TRY_AGAIN
- if (! (hp == 0 && h_errno == TRY_AGAIN))
-#endif
-
- break;
-
- if (count >= 5)
- break;
- Fsleep_for (make_number (1), Qnil);
- }
-
- if (hp)
- {
- char *fqdn = (char *) hp->h_name;
-
- if (!strchr (fqdn, '.'))
- {
- /* We still don't have a fully qualified domain name.
- Try to find one in the list of alternate names */
- char **alias = hp->h_aliases;
- while (*alias
- && (!strchr (*alias, '.')
- || !strcmp (*alias, "localhost.localdomain")))
- alias++;
- if (*alias)
- fqdn = *alias;
- }
- hostname = fqdn;
- }
-#endif /* !HAVE_GETADDRINFO */
- }
-#endif /* HAVE_SOCKETS */
- Vsystem_name = build_string (hostname);
- xfree (hostname_alloc);
#endif /* HAVE_GETHOSTNAME */
- {
- char *p;
- for (p = SSDATA (Vsystem_name); *p; p++)
- if (*p == ' ' || *p == '\t')
- *p = '-';
- }
+ char *p;
+ for (p = hostname; *p; p++)
+ if (*p == ' ' || *p == '\t')
+ *p = '-';
+ if (! (STRINGP (Vsystem_name) && SBYTES (Vsystem_name) == p - hostname
+ && strcmp (SSDATA (Vsystem_name), hostname) == 0))
+ Vsystem_name = build_string (hostname);
+ xfree (hostname_alloc);
}
sigset_t empty_mask;
@@ -1527,9 +1504,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 +1623,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 +1966,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 +2185,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 +2195,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 +2244,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 +3498,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 09021e29e1a..54f90fb3965 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 5900fa1df7b..b536eb501b8 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 40139a1b931..1d3a4ba2914 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -86,13 +86,42 @@ extern void set_waiting_for_input (struct timespec *);
happen when this files is used outside the src directory).
Use GCPRO1 to determine if lisp.h was included. */
#ifdef GCPRO1
+
+/* Emacs uses the integer list (HI LO US PS) to represent the time
+ (HI << LO_TIME_BITS) + LO + US / 1e6 + PS / 1e12. */
+enum { LO_TIME_BITS = 16 };
+
+/* A Lisp time (HI LO US PS), sans the cons cells. */
+struct lisp_time
+{
+ EMACS_INT hi;
+ int lo, us, ps;
+};
+
/* defined in editfns.c */
extern Lisp_Object make_lisp_time (struct timespec);
extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object, struct timespec *, double *);
+ Lisp_Object, struct lisp_time *, double *);
+extern struct timespec lisp_to_timespec (struct lisp_time);
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 682ffdca34b..3a461565e5d 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 8312491f2de..15d33b4e3ee 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
@@ -162,6 +161,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 +197,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 +218,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 +253,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 +268,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 +442,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 +523,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 +744,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 +816,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 +1005,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 +1042,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 +1359,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 +1510,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 +1706,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 +1790,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 +1854,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 +2025,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 +2040,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 +2157,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 +2165,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 +2179,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 +2195,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 +2210,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 +2240,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;
@@ -2295,10 +2253,9 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
/* First run `suspend-tty-functions' and then clean up the tty
state because `suspend-tty-functions' might need to change
the tty state. */
- Lisp_Object args[2];
- args[0] = intern ("suspend-tty-functions");
- XSETTERMINAL (args[1], t);
- Frun_hook_with_args (2, args);
+ Lisp_Object term;
+ XSETTERMINAL (term, t);
+ CALLN (Frun_hook_with_args, intern ("suspend-tty-functions"), term);
reset_sys_modes (t->display_info.tty);
delete_keyboard_wait_descriptor (fileno (f));
@@ -2342,15 +2299,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,26 +2338,24 @@ 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);
}
set_tty_hooks (t);
init_sys_modes (t->display_info.tty);
- {
- /* Run `resume-tty-functions'. */
- Lisp_Object args[2];
- args[0] = intern ("resume-tty-functions");
- XSETTERMINAL (args[1], t);
- Frun_hook_with_args (2, args);
- }
+ /* Run `resume-tty-functions'. */
+ Lisp_Object term;
+ XSETTERMINAL (term, t);
+ CALLN (Frun_hook_with_args, intern ("resume-tty-functions"), term);
}
set_tty_hooks (t);
@@ -2515,7 +2470,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);
@@ -2748,12 +2703,6 @@ static const char *menu_help_message, *prev_menu_help_message;
last menu help message. */
static int menu_help_paneno, menu_help_itemno;
-static Lisp_Object Qtty_menu_navigation_map, Qtty_menu_exit;
-static Lisp_Object Qtty_menu_prev_item, Qtty_menu_next_item;
-static Lisp_Object Qtty_menu_next_menu, Qtty_menu_prev_menu;
-static Lisp_Object Qtty_menu_select, Qtty_menu_ignore;
-static Lisp_Object Qtty_menu_mouse_movement;
-
typedef struct tty_menu_struct
{
int count;
@@ -2870,7 +2819,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 +2867,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 +2876,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 +2890,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 +2905,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 +3115,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 +3124,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 +3200,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 +3346,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 +3488,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 +3518,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 +3549,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 +3601,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 +3687,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 +3714,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 +3747,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 +3829,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 +3849,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 +3886,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 +3913,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 +3931,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 +3949,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 +3974,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 +4002,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 +4157,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 +4393,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 +4418,7 @@ delete_tty (struct terminal *terminal)
;
if (! p)
- /* This should not happen. */
+ /* This should not happen. */
emacs_abort ();
p->next = tty->next;
@@ -4499,7 +4426,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 +4504,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 848e1db9122..394b4056eb3 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 d792e277efd..3cafc437e59 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;
};
@@ -423,7 +451,7 @@ struct terminal
void (*delete_glyphs_hook) (struct frame *, int);
void (*ring_bell_hook) (struct frame *f);
- void (*toggle_invisible_pointer_hook) (struct frame *f, int invisible);
+ void (*toggle_invisible_pointer_hook) (struct frame *f, bool invisible);
void (*reset_terminal_modes_hook) (struct terminal *);
void (*set_terminal_modes_hook) (struct terminal *);
@@ -468,17 +496,24 @@ struct terminal
support overlapping frames, so there's no need to raise or lower
anything.
- If RAISE_FLAG is non-zero, F is brought to the front, before all other
- windows. If RAISE_FLAG is zero, F is sent to the back, behind all other
+ If RAISE_FLAG, F is brought to the front, before all other
+ windows. If !RAISE_FLAG, F is sent to the back, behind all other
windows. */
- void (*frame_raise_lower_hook) (struct frame *f, int raise_flag);
+ void (*frame_raise_lower_hook) (struct frame *f, bool raise_flag);
/* If the value of the frame parameter changed, this hook is called.
For example, if going from fullscreen to not fullscreen this hook
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 7a7fdca5077..b48d0623e12 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -28,17 +28,15 @@ 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;
-static Lisp_Object Qterminal_live_p;
-
static void delete_initial_terminal (struct terminal *);
/* This setter is used only in this file, so it can be private. */
@@ -121,9 +119,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 +129,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 +192,90 @@ 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. */
-/* Create a new terminal object and add it to the terminal list. */
+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;
+}
+
+/* Allocate basically initialized terminal. */
+
+static struct terminal *
+allocate_terminal (void)
+{
+ return ALLOCATE_ZEROED_PSEUDOVECTOR
+ (struct terminal, next_terminal, PVEC_TERMINAL);
+}
+
+/* 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 +347,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 +356,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 +417,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 +464,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 +501,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 +510,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 +523,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 +545,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 c8d238e666e..35f22bf454e 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -44,21 +44,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
is enforced by the subrs installing properties onto the intervals. */
-/* Types of hooks. */
-static Lisp_Object Qmouse_left;
-static Lisp_Object Qmouse_entered;
-Lisp_Object Qpoint_left;
-Lisp_Object Qpoint_entered;
-Lisp_Object Qcategory;
-Lisp_Object Qlocal_map;
-
-/* Visual properties text (including strings) may have. */
-static Lisp_Object Qforeground, Qbackground, Qunderline;
-Lisp_Object Qfont;
-static Lisp_Object Qstipple;
-Lisp_Object Qinvisible, Qintangible, Qmouse_face;
-static Lisp_Object Qread_only;
-Lisp_Object Qminibuffer_prompt;
enum property_set_type
{
@@ -67,9 +52,6 @@ enum property_set_type
TEXT_PROPERTY_APPEND
};
-/* Sticky properties. */
-Lisp_Object Qfront_sticky, Qrear_nonsticky;
-
/* If o1 is a cons whose cdr is a cons, return non-zero and set o2 to
the o1's cdr. Otherwise, return zero. This is handy for
traversing plists. */
@@ -660,6 +642,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 +657,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 +1299,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 +1344,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 +1894,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 +1948,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)
@@ -2293,6 +2280,11 @@ verify_interval_modification (struct buffer *buf,
}
}
+ if (i->position + LENGTH (i) < end
+ && (!NILP (BVAR (current_buffer, read_only))
+ && NILP (Vinhibit_read_only)))
+ xsignal1 (Qbuffer_read_only, Fcurrent_buffer ());
+
i = next_interval (i);
}
/* Keep going thru the interval containing the char before END. */
@@ -2373,7 +2365,7 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and
interval_insert_in_front_hooks = Qnil;
- /* Common attributes one might give text */
+ /* Common attributes one might give text. */
DEFSYM (Qforeground, "foreground");
DEFSYM (Qbackground, "background");
@@ -2391,7 +2383,7 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and
DEFSYM (Qmouse_face, "mouse-face");
DEFSYM (Qminibuffer_prompt, "minibuffer-prompt");
- /* Properties that text might use to specify certain actions */
+ /* Properties that text might use to specify certain actions. */
DEFSYM (Qmouse_left, "mouse-left");
DEFSYM (Qmouse_entered, "mouse-entered");
diff --git a/src/tparam.c b/src/tparam.c
index a9f9d7843e9..538f26c83b6 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -255,9 +255,9 @@ tparam1 (const char *string, char *outstring, int len,
}
*op = 0;
while (doup-- > 0)
- strcat (op, up);
+ op = stpcpy (op, up);
while (doleft-- > 0)
- strcat (op, left);
+ op = stpcpy (op, left);
return outstring;
}
diff --git a/src/undo.c b/src/undo.c
index 46b467ac6b4..948dcf9ec1a 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -34,12 +34,6 @@ static struct buffer *last_undo_buffer;
static struct buffer *last_boundary_buffer;
static ptrdiff_t last_boundary_position;
-Lisp_Object Qinhibit_read_only;
-
-/* Marker for function call undo list elements. */
-
-Lisp_Object Qapply;
-
/* The first time a command records something for undo.
it also allocates the undo-boundary object
which will be added to the list at the end of the command.
@@ -461,6 +455,8 @@ void
syms_of_undo (void)
{
DEFSYM (Qinhibit_read_only, "inhibit-read-only");
+
+ /* Marker for function call undo list elements. */
DEFSYM (Qapply, "apply");
pending_boundary = Qnil;
diff --git a/src/unexaix.c b/src/unexaix.c
index 23798b13b69..af114e4427d 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -55,7 +55,6 @@ what you give them. Help stamp out software-hoarding! */
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
-#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
@@ -134,7 +133,7 @@ unexec (const char *new_name, const char *a_name)
{
PERROR (a_name);
}
- if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
+ if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0777)) < 0)
{
PERROR (new_name);
}
@@ -152,7 +151,6 @@ unexec (const char *new_name, const char *a_name)
emacs_close (new);
if (a_out >= 0)
emacs_close (a_out);
- mark_x (new_name);
}
/* ****************************************************************
@@ -466,29 +464,6 @@ copy_sym (int new, int a_out, const char *a_name, const char *new_name)
return 0;
}
-/* ****************************************************************
- * mark_x
- *
- * After successfully building the new a.out, mark it executable
- */
-static void
-mark_x (const char *name)
-{
- struct stat sbuf;
- int um;
- int new = 0; /* for PERROR */
-
- um = umask (777);
- umask (um);
- if (stat (name, &sbuf) == -1)
- {
- PERROR (name);
- }
- sbuf.st_mode |= 0111 & ~um;
- if (chmod (name, sbuf.st_mode) == -1)
- PERROR (name);
-}
-
static int
adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
{
diff --git a/src/unexcoff.c b/src/unexcoff.c
index 0cb72d9dcd2..3f6549003a5 100644
--- a/src/unexcoff.c
+++ b/src/unexcoff.c
@@ -97,7 +97,6 @@ struct aouthdr
#include <sys/types.h>
#endif /* makedev */
#include <stdio.h>
-#include <sys/stat.h>
#include <errno.h>
#include <sys/file.h>
@@ -122,7 +121,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"
@@ -439,29 +438,6 @@ copy_sym (int new, int a_out, const char *a_name, const char *new_name)
return 0;
}
-/* ****************************************************************
- * mark_x
- *
- * After successfully building the new a.out, mark it executable
- */
-static void
-mark_x (const char *name)
-{
- struct stat sbuf;
- int um;
- int new = 0; /* for PERROR */
-
- um = umask (777);
- umask (um);
- if (stat (name, &sbuf) == -1)
- {
- PERROR (name);
- }
- sbuf.st_mode |= 0111 & ~um;
- if (chmod (name, sbuf.st_mode) == -1)
- PERROR (name);
-}
-
/*
* If the COFF file contains a symbol table and a line number section,
@@ -542,7 +518,7 @@ unexec (const char *new_name, const char *a_name)
{
PERROR (a_name);
}
- if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
+ if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0777)) < 0)
{
PERROR (new_name);
}
@@ -560,7 +536,6 @@ unexec (const char *new_name, const char *a_name)
emacs_close (new);
if (a_out >= 0)
emacs_close (a_out);
- mark_x (new_name);
}
#endif /* not CANNOT_DUMP */
diff --git a/src/unexcw.c b/src/unexcw.c
index 217dd71214a..be8857878eb 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/unexelf.c b/src/unexelf.c
index 59e2725ba20..483da6eef0c 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -665,7 +665,6 @@ unexec (const char *new_name, const char *old_name)
#endif
struct stat stat_buf;
off_t old_file_size;
- int mask;
/* Open the old file, allocate a buffer of the right size, and read
in the file contents. */
@@ -799,7 +798,7 @@ unexec (const char *new_name, const char *old_name)
the image of the new file. Set pointers to various interesting
objects. */
- new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0666);
+ new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
if (new_file < 0)
fatal ("Can't creat (%s): %s", new_name, strerror (errno));
@@ -1319,13 +1318,4 @@ temacs:
if (emacs_close (new_file) != 0)
fatal ("Can't close (%s): %s", new_name, strerror (errno));
-
- if (stat (new_name, &stat_buf) != 0)
- fatal ("Can't stat (%s): %s", new_name, strerror (errno));
-
- mask = umask (777);
- umask (mask);
- stat_buf.st_mode |= 0111 & ~mask;
- if (chmod (new_name, stat_buf.st_mode) != 0)
- fatal ("Can't chmod (%s): %s", new_name, strerror (errno));
}
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 2f01927e7b2..fe6637e2ef5 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;
@@ -1035,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)
@@ -1053,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
@@ -1091,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;
@@ -1138,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
@@ -1353,7 +1267,7 @@ unexec (const char *outfile, const char *infile)
unexec_error ("cannot open input file `%s'", infile);
}
- outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755);
+ outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0777);
if (outfd < 0)
{
emacs_close (infd);
diff --git a/src/unexw32.c b/src/unexw32.c
index a53c52c68c5..322d60d062f 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 4d668ec2ad3..ab102e32623 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/w16select.c b/src/w16select.c
index 7d412991d46..96f8437b4b1 100644
--- a/src/w16select.c
+++ b/src/w16select.c
@@ -625,9 +625,9 @@ DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_dat
return (ret);
}
-/* Support checking for a clipboard selection. */
+/* Support checking for a clipboard selection. */
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
+DEFUN ("w16-selection-exists-p", Fw16_selection_exists_p, Sw16_selection_exists_p,
0, 2, 0,
doc: /* Whether there is an owner for the given X selection.
SELECTION should be the name of the selection in question, typically
@@ -677,7 +677,7 @@ syms_of_win16select (void)
{
defsubr (&Sw16_set_clipboard_data);
defsubr (&Sw16_get_clipboard_data);
- defsubr (&Sx_selection_exists_p);
+ defsubr (&Sw16_selection_exists_p);
DEFVAR_LISP ("selection-coding-system", Vselection_coding_system,
doc: /* Coding system for communicating with other programs.
diff --git a/src/w32.c b/src/w32.c
index 09902a2bb0d..31b13289b57 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 defines these in its _mingw.h. */
-#if defined(__GNUC__) && !defined(MINGW_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
@@ -240,8 +242,6 @@ typedef struct _REPARSE_DATA_BUFFER {
typedef HRESULT (WINAPI * ShGetFolderPath_fn)
(IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
-Lisp_Object QCloaded_from;
-
void globals_of_w32 (void);
static DWORD get_rid (PSID);
static int is_symlink (const char *);
@@ -307,6 +307,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 +882,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 +1709,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 +2292,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 +2343,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 +2417,6 @@ unsetenv (const char *name)
{
char *var;
size_t name_len;
- int retval;
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
@@ -2514,7 +2515,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 +2588,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
@@ -3402,10 +3403,10 @@ sys_readdir (DIR *dirp)
int ln;
strcpy (filename, dir_pathname);
- ln = strlen (filename) - 1;
- if (!IS_DIRECTORY_SEP (filename[ln]))
- strcat (filename, "\\");
- strcat (filename, "*");
+ ln = strlen (filename);
+ if (!IS_DIRECTORY_SEP (filename[ln - 1]))
+ filename[ln++] = '\\';
+ strcpy (filename + ln, "*");
/* Note: No need to resolve symlinks in FILENAME, because
FindFirst opens the directory that is the target of a
@@ -4966,7 +4967,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
{
/* Make sure root directories end in a slash. */
if (!IS_DIRECTORY_SEP (name[len-1]))
- strcat (name, "\\");
+ strcpy (name + len, "\\");
if (GetDriveType (name) < 2)
{
errno = ENOENT;
@@ -5435,8 +5436,7 @@ symlink (char const *filename, char const *linkname)
p--;
if (p > linkfn)
strncpy (tem, linkfn, p - linkfn);
- tem[p - linkfn] = '\0';
- strcat (tem, filename);
+ strcpy (tem + (p - linkfn), filename);
dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
}
else
@@ -6956,6 +6956,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 +7889,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 +8262,7 @@ int
sys_write (int fd, const void * buffer, unsigned int count)
{
int nchars;
+ USE_SAFE_ALLOCA;
if (fd < 0)
{
@@ -8251,30 +8281,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 +8321,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 +8435,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
}
}
+ SAFE_FREE ();
return nchars;
}
@@ -8738,6 +8785,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 +9125,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 +9345,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 fa63ece3ddd..835557d5ec7 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,
@@ -172,7 +172,6 @@ extern void init_timers (void);
extern int _sys_read_ahead (int fd);
extern int _sys_wait_accept (int fd);
-extern Lisp_Object QCloaded_from;
extern HMODULE w32_delayed_load (Lisp_Object);
extern int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
@@ -206,6 +205,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>
@@ -218,4 +224,17 @@ extern ssize_t emacs_gnutls_push (gnutls_transport_ptr_t p,
const void* buf, size_t sz);
#endif /* HAVE_GNUTLS */
+/* Definine a function that will be loaded from a DLL. */
+#define DEF_DLL_FN(type, func, args) static type (FAR CDECL *fn_##func) args
+
+/* Load a function from the DLL. */
+#define LOAD_DLL_FN(lib, func) \
+ do \
+ { \
+ fn_##func = (void *) GetProcAddress (lib, #func); \
+ if (!fn_##func) \
+ return false; \
+ } \
+ while (false)
+
#endif /* EMACS_W32_H */
diff --git a/src/w32console.c b/src/w32console.c
index e530e09f9d7..a38a558c226 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 64e0e6d028a..c269c4f8e68 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -89,27 +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;
-Lisp_Object Qhyper;
-Lisp_Object Qsuper;
-Lisp_Object Qmeta;
-Lisp_Object Qalt;
-Lisp_Object Qctrl;
-Lisp_Object Qcontrol;
-Lisp_Object Qshift;
-static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes;
-
-
/* Prefix for system colors. */
#define SYSTEM_COLOR_PREFIX "System"
#define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
@@ -228,16 +211,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 +250,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 +261,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 +324,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 +710,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);
@@ -1147,7 +1133,8 @@ gamma_correct (struct frame *f, COLORREF *color)
If ALLOC is nonzero, allocate a new colormap cell. */
int
-w32_defined_color (struct frame *f, const char *color, XColor *color_def, int alloc)
+w32_defined_color (struct frame *f, const char *color, XColor *color_def,
+ bool alloc_p)
{
register Lisp_Object tem;
COLORREF w32_color_ref;
@@ -1181,7 +1168,7 @@ w32_defined_color (struct frame *f, const char *color, XColor *color_def, int al
entry = entry->next;
}
- if (entry == NULL && alloc)
+ if (entry == NULL && alloc_p)
{
/* not already mapped, so add to list */
entry = xmalloc (sizeof (struct w32_palette_entry));
@@ -1234,7 +1221,7 @@ x_decode_color (struct frame *f, Lisp_Object arg, int def)
/* w32_defined_color is responsible for coping with failures
by looking for a near-miss. */
- if (w32_defined_color (f, SDATA (arg), &cdef, 1))
+ if (w32_defined_color (f, SDATA (arg), &cdef, true))
return cdef.pixel;
/* defined_color failed; return an ultimate default. */
@@ -1370,23 +1357,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");
@@ -1538,7 +1525,7 @@ x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
void
x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int result;
+ bool result;
if (NILP (arg) && NILP (oldval))
return;
@@ -1608,9 +1595,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, false, Qinternal_border_width);
+
+ 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 +1662,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 +1674,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, true, Qmenu_bar_lines);
+
+ /* Not sure whether this is needed. */
+ x_clear_under_internal_border (f);
}
- adjust_frame_glyphs (f);
}
@@ -1657,8 +1697,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 +1709,54 @@ 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;
+ /* Store `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,
+ (!f->tool_bar_redisplayed_once ? 1
+ : (old_height == 0 || height == 0) ? 2
+ : 4),
+ false, Qtool_bar_lines);
- run_window_configuration_change_hook (f);
+ /* adjust_frame_size might not have done anything, garbage frame
+ here. */
+ adjust_frame_glyphs (f);
+ SET_FRAME_GARBAGED (f);
+ if (FRAME_X_WINDOW (f))
+ x_clear_under_internal_border (f);
}
@@ -1745,7 +1772,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
F->explicit_name is set, ignore the new name; otherwise, set it. */
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. */
@@ -1800,7 +1827,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
void
x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- x_set_name (f, arg, 1);
+ x_set_name (f, arg, true);
}
/* This function should be called by Emacs redisplay code to set the
@@ -1809,7 +1836,7 @@ x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
void
x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- x_set_name (f, arg, 0);
+ x_set_name (f, arg, false);
}
/* Change the title of frame F to NAME.
@@ -1848,6 +1875,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 +1939,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 +1947,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 +2002,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 +2418,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 +2436,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
@@ -2495,7 +2544,7 @@ w32_msg_pump (deferred_msg * msg_buf)
thread-safe. The next line is okay because the cons
cell is never made into garbage and is not relocated by
GC. */
- XSETCAR (XIL ((EMACS_INT) msg.lParam), Qnil);
+ XSETCAR (make_lisp_ptr ((void *)msg.lParam, Lisp_Cons), Qnil);
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
emacs_abort ();
break;
@@ -2503,16 +2552,10 @@ w32_msg_pump (deferred_msg * msg_buf)
{
int vk_code = (int) msg.wParam;
int cur_state = (GetKeyState (vk_code) & 1);
- Lisp_Object new_state = XIL ((EMACS_INT) msg.lParam);
-
- /* NB: This code must be thread-safe. It is safe to
- call NILP because symbols are not relocated by GC,
- and pointer here is not touched by GC (so the markbit
- can't be set). Numbers are safe because they are
- immediate values. */
- if (NILP (new_state)
- || (NUMBERP (new_state)
- && ((XUINT (new_state)) & 1) != cur_state))
+ int new_state = msg.lParam;
+
+ if (new_state == -1
+ || ((new_state & 1) != cur_state))
{
one_w32_display_info.faked_key = vk_code;
@@ -3446,6 +3489,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 +3828,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 +3858,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 +3870,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 +3882,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 +3920,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 +3955,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 +4188,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);
@@ -4137,7 +4200,7 @@ my_create_tip_window (struct frame *f)
/* Create and set up the w32 window for frame F. */
static void
-w32_window (struct frame *f, long window_prompting, int minibuffer_only)
+w32_window (struct frame *f, long window_prompting, bool minibuffer_only)
{
block_input ();
@@ -4146,7 +4209,7 @@ w32_window (struct frame *f, long window_prompting, int minibuffer_only)
for the window manager, so GC relocation won't bother it.
Elsewhere we specify the window name for the window manager. */
- f->namebuf = xstrdup (SSDATA (Vx_resource_name));
+ f->namebuf = xlispstrdup (Vx_resource_name);
my_create_window (f);
@@ -4356,9 +4419,8 @@ This function is an internal primitive--use `make-frame' instead. */)
struct frame *f;
Lisp_Object frame, tem;
Lisp_Object name;
- int minibuffer_only = 0;
+ bool minibuffer_only = false;
long window_prompting = 0;
- int width, height;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object display;
@@ -4417,17 +4479,18 @@ This function is an internal primitive--use `make-frame' instead. */)
else if (EQ (tem, Qonly))
{
f = make_minibuffer_frame ();
- minibuffer_only = 1;
+ minibuffer_only = true;
}
else if (WINDOWP (tem))
f = make_frame_without_minibuffer (tem, kb, display);
else
- f = make_frame (1);
+ f = make_frame (true);
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,16 +4516,17 @@ 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);
- f->output_data.w32->explicit_parent = 1;
+ /* Cast to UINT_PTR shuts up compiler warnings about cast to
+ pointer from integer of different size. */
+ f->output_data.w32->parent_desc = (Window) (UINT_PTR) XFASTINT (parent);
+ f->output_data.w32->explicit_parent = true;
}
else
{
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
- f->output_data.w32->explicit_parent = 0;
+ f->output_data.w32->explicit_parent = false;
}
/* Set the name; the functions to which we pass f expect the name to
@@ -4470,13 +4534,13 @@ This function is an internal primitive--use `make-frame' instead. */)
if (EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->w32_id_name));
- f->explicit_name = 0;
+ f->explicit_name = false;
}
else
{
fset_name (f, name);
- f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
+ f->explicit_name = true;
+ /* Use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
@@ -4486,9 +4550,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 +4568,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 +4579,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 +4601,43 @@ 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, true,
+ Qx_create_frame_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;
@@ -4598,7 +4652,7 @@ This function is an internal primitive--use `make-frame' instead. */)
f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
- window_prompting = x_figure_window_size (f, parameters, 1);
+ window_prompting = x_figure_window_size (f, parameters, true);
tem = x_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
@@ -4626,21 +4680,20 @@ 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);
+
+ /* Allow x_set_window_size, now. */
+ f->can_x_set_window_size = 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, true,
+ Qx_create_frame_2);
/* 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
bar so that its size can be taken into account. */
block_input ();
- x_wm_set_size_hint (f, window_prompting, 0);
+ x_wm_set_size_hint (f, window_prompting, false);
unblock_input ();
/* Make the window appear on the frame and enable display, unless
@@ -4710,7 +4763,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
CHECK_STRING (color);
- if (w32_defined_color (f, SDATA (color), &foo, 0))
+ if (w32_defined_color (f, SDATA (color), &foo, false))
return Qt;
else
return Qnil;
@@ -4725,7 +4778,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
CHECK_STRING (color);
- if (w32_defined_color (f, SDATA (color), &foo, 0))
+ if (w32_defined_color (f, SDATA (color), &foo, false))
return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel),
(GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel),
(GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel));
@@ -4971,7 +5024,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 +5351,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 +5563,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
***********************************************************************/
@@ -5689,14 +5648,15 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
frame = Qnil;
GCPRO3 (parms, name, frame);
/* Make a frame without minibuffer nor mode-line. */
- f = make_frame (0);
+ f = make_frame (false);
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);
+ set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (buffer));
bset_truncate_lines (current_buffer, Qnil);
@@ -5726,19 +5686,19 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
#endif /* GLYPH_DEBUG */
FRAME_KBOARD (f) = kb;
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
- f->output_data.w32->explicit_parent = 0;
+ f->output_data.w32->explicit_parent = false;
/* Set the name; the functions to which we pass f expect the name to
be set. */
if (EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->w32_id_name));
- f->explicit_name = 0;
+ f->explicit_name = false;
}
else
{
fset_name (f, name);
- f->explicit_name = 1;
+ f->explicit_name = true;
/* use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
@@ -5788,19 +5748,18 @@ 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;
f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
- window_prompting = x_figure_window_size (f, parms, 0);
+ window_prompting = x_figure_window_size (f, parms, false);
/* No fringes on tip frame. */
f->fringe_cols = 0;
@@ -5825,9 +5784,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, true, Qnil);
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -5859,7 +5819,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
Fmodify_frame_parameters (frame, colors);
}
- f->no_split = 1;
+ f->no_split = true;
UNGCPRO;
@@ -5872,6 +5832,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->can_x_set_window_size = true;
/* Setting attributes of faces of the tooltip frame from resources
and similar will increment face_change_count, which leads to the
@@ -6005,7 +5966,8 @@ Text larger than the specified size is clipped. */)
int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
- int i, width, height, seen_reversed_p;
+ int i, width, height;
+ bool seen_reversed_p;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t count = SPECPDL_INDEX ();
@@ -6134,7 +6096,7 @@ Text larger than the specified size is clipped. */)
FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
adjust_frame_glyphs (f);
- w->pseudo_window_p = 1;
+ w->pseudo_window_p = true;
/* Display the tooltip text in a temporary buffer. */
old_buffer = current_buffer;
@@ -6146,7 +6108,8 @@ Text larger than the specified size is clipped. */)
try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
/* Compute width and height of the tooltip. */
- width = height = seen_reversed_p = 0;
+ width = height = 0;
+ seen_reversed_p = false;
for (i = 0; i < w->desired_matrix->nrows; ++i)
{
struct glyph_row *row = &w->desired_matrix->rows[i];
@@ -6158,7 +6121,7 @@ Text larger than the specified size is clipped. */)
break;
/* Let the row go over the full width of the frame. */
- row->full_width_p = 1;
+ row->full_width_p = true;
row_width = row->pixel_width;
if (row->used[TEXT_AREA])
@@ -6169,7 +6132,7 @@ Text larger than the specified size is clipped. */)
place the cursor there. Don't include the width of
this glyph. */
last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (INTEGERP (last->object))
+ if (NILP (last->object))
row_width -= last->pixel_width;
}
else
@@ -6179,10 +6142,10 @@ Text larger than the specified size is clipped. */)
Don't count that glyph. */
struct glyph *g = row->glyphs[TEXT_AREA];
- if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
+ if (g->type == STRETCH_GLYPH && NILP (g->object))
{
row_width -= g->pixel_width;
- seen_reversed_p = 1;
+ seen_reversed_p = true;
}
}
}
@@ -6223,12 +6186,12 @@ Text larger than the specified size is clipped. */)
if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
break;
- row->full_width_p = 1;
+ row->full_width_p = true;
row_width = row->pixel_width;
if (row->used[TEXT_AREA] && !row->reversed_p)
{
last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (INTEGERP (last->object))
+ if (NILP (last->object))
row_width -= last->pixel_width;
}
@@ -6280,8 +6243,8 @@ Text larger than the specified size is clipped. */)
}
/* Draw into the window. */
- w->must_be_updated_p = 1;
- update_single_window (w, 1);
+ w->must_be_updated_p = true;
+ update_single_window (w);
unblock_input ();
@@ -6900,24 +6863,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 +6907,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 +6941,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
@@ -7004,6 +7019,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. */
@@ -7037,14 +7053,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);
@@ -7059,51 +7089,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))
{
@@ -7233,7 +7239,7 @@ The return value is the hotkey-id if registered, otherwise nil. */)
/* Notify input thread about new hot-key definition, so that it
takes effect without needing to switch focus. */
PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
- (WPARAM) XLI (key), 0);
+ (WPARAM) XINT (key), 0);
}
return key;
@@ -7253,10 +7259,17 @@ DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
if (!NILP (item))
{
+ LPARAM lparam;
+
+ eassert (CONSP (item));
+ /* Pass the tail of the list as a pointer to a Lisp_Cons cell,
+ so that it works in a --with-wide-int build as well. */
+ lparam = (LPARAM) XUNTAG (item, Lisp_Cons);
+
/* Notify input thread about hot-key definition being removed, so
that it takes effect without needing focus switch. */
if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
- (WPARAM) XINT (XCAR (item)), (LPARAM) XLI (item)))
+ (WPARAM) XINT (XCAR (item)), lparam))
{
MSG msg;
GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
@@ -7311,10 +7324,15 @@ DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
doc: /* Toggle the state of the lock key KEY.
KEY can be `capslock', `kp-numlock', or `scroll'.
If the optional parameter NEW-STATE is a number, then the state of KEY
-is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
+is set to off if the low bit of NEW-STATE is zero, otherwise on.
+If NEW-STATE is omitted or nil, the function toggles the state,
+
+Value is the new state of the key, or nil if the function failed
+to change the state. */)
(Lisp_Object key, Lisp_Object new_state)
{
int vk_code;
+ LPARAM lparam;
if (EQ (key, intern ("capslock")))
vk_code = VK_CAPITAL;
@@ -7328,8 +7346,12 @@ is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
if (!dwWindowsThreadId)
return make_number (w32_console_toggle_lock_key (vk_code, new_state));
+ if (NILP (new_state))
+ lparam = -1;
+ else
+ lparam = (XUINT (new_state)) & 1;
if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
- (WPARAM) vk_code, (LPARAM) XLI (new_state)))
+ (WPARAM) vk_code, lparam))
{
MSG msg;
GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
@@ -7359,6 +7381,37 @@ This is a direct interface to the Windows API FindWindow function. */)
return Qt;
}
+DEFUN ("w32-frame-menu-bar-size", Fw32_frame_menu_bar_size, Sw32_frame_menu_bar_size, 0, 1, 0,
+ doc: /* Return sizes of menu bar on frame FRAME.
+The return value is a list of four elements: The current width and
+height of FRAME's menu bar in pixels, the height of one menu bar line in
+a wrapped menu bar in pixels, and the height of a single line menu bar
+in pixels.
+
+If FRAME is omitted or nil, the selected frame is used. */)
+ (Lisp_Object frame)
+{
+ struct frame *f = decode_any_frame (frame);
+ MENUBARINFO menu_bar;
+ int width, height, single_height, wrapped_height;
+
+ block_input ();
+
+ single_height = GetSystemMetrics (SM_CYMENU);
+ wrapped_height = GetSystemMetrics (SM_CYMENUSIZE);
+ menu_bar.cbSize = sizeof (menu_bar);
+ menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
+ menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
+ GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
+ width = menu_bar.rcBar.right - menu_bar.rcBar.left;
+ height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
+
+ unblock_input ();
+
+ return list4 (make_number (width), make_number (height),
+ make_number (wrapped_height), make_number (single_height));
+}
+
DEFUN ("w32-frame-rect", Fw32_frame_rect, Sw32_frame_rect, 0, 2, 0,
doc: /* Return boundary rectangle of FRAME in screen coordinates.
FRAME must be a live frame and defaults to the selected one.
@@ -7373,15 +7426,131 @@ title bar and decorations. */)
struct frame *f = decode_live_frame (frame);
RECT rect;
+ block_input ();
+
if (!NILP (client))
GetClientRect (FRAME_W32_WINDOW (f), &rect);
else
GetWindowRect (FRAME_W32_WINDOW (f), &rect);
+ unblock_input ();
+
return list4 (make_number (rect.left), make_number (rect.top),
make_number (rect.right), make_number (rect.bottom));
}
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+ doc: /* Return geometric attributes of frame FRAME.
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is an association list containing the following
+elements (all size values are in pixels).
+
+- `frame-outer-size' is a cons of the outer width and height of FRAME.
+ The outer size includes the title bar and the external borders as well
+ as any menu and/or tool bar of frame.
+
+- `border' is a cons of the horizontal and vertical width of FRAME's
+ external borders.
+
+- `title-bar-height' is the height of the title bar of FRAME.
+
+- `menu-bar-external' if `t' means the menu bar is by default external
+ (not included in the inner size of FRAME).
+
+- `menu-bar-size' is a cons of the width and height of the menu bar of
+ FRAME.
+
+- `tool-bar-external' if `t' means the tool bar is by default external
+ (not included in the inner size of FRAME).
+
+- `tool-bar-side' tells tells on which side the tool bar on FRAME is by
+ default and can be one of `left', `top', `right' or `bottom'.
+
+- `tool-bar-size' is a cons of the width and height of the tool bar of
+ FRAME.
+
+- `frame-inner-size' is a cons of the inner width and height of FRAME.
+ This excludes FRAME's title bar and external border as well as any
+ external menu and/or tool bar. */)
+ (Lisp_Object frame)
+{
+ struct frame *f = decode_live_frame (frame);
+ Lisp_Object geometry = Qnil;
+ RECT frame_outer_edges, frame_inner_edges;
+ MENUBARINFO menu_bar;
+ int border_width, border_height, title_height;
+ int single_bar_height, wrapped_bar_height, menu_bar_height;
+ Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
+
+ block_input ();
+
+ /* Outer frame rectangle, including outer borders and title bar. */
+ GetWindowRect (FRAME_W32_WINDOW (f), &frame_outer_edges);
+ /* Inner frame rectangle, excluding borders and title bar. */
+ GetClientRect (FRAME_W32_WINDOW (f), &frame_inner_edges);
+ /* Outer border. */
+ border_width = GetSystemMetrics (SM_CXFRAME);
+ border_height = GetSystemMetrics (SM_CYFRAME);
+ /* Title bar. */
+ title_height = GetSystemMetrics (SM_CYCAPTION);
+ /* Menu bar. */
+ menu_bar.cbSize = sizeof (menu_bar);
+ menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
+ menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
+ GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
+ single_bar_height = GetSystemMetrics (SM_CYMENU);
+ wrapped_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
+ unblock_input ();
+
+ menu_bar_height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
+ /* Fix menu bar height reported by GetMenuBarInfo. */
+ if (menu_bar_height > single_bar_height)
+ /* A wrapped menu bar. */
+ menu_bar_height += single_bar_height - wrapped_bar_height;
+ else if (menu_bar_height > 0)
+ /* A single line menu bar. */
+ menu_bar_height = single_bar_height;
+
+ return
+ listn (CONSTYPE_PURE, 10,
+ Fcons (Qframe_position,
+ Fcons (make_number (frame_outer_edges.left),
+ make_number (frame_outer_edges.top))),
+ Fcons (Qframe_outer_size,
+ Fcons (make_number
+ (frame_outer_edges.right - frame_outer_edges.left),
+ make_number
+ (frame_outer_edges.bottom - frame_outer_edges.top))),
+ Fcons (Qexternal_border_size,
+ ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+ ? Fcons (make_number (0), make_number (0))
+ : Fcons (make_number (border_width),
+ make_number (border_height)))),
+ Fcons (Qtitle_height,
+ ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+ ? make_number (0)
+ : make_number (title_height))),
+ Fcons (Qmenu_bar_external, Qt),
+ Fcons (Qmenu_bar_size,
+ Fcons (make_number
+ (menu_bar.rcBar.right - menu_bar.rcBar.left),
+ make_number (menu_bar_height))),
+ Fcons (Qtool_bar_external, Qnil),
+ Fcons (Qtool_bar_position, Qtop),
+ Fcons (Qtool_bar_size,
+ Fcons (make_number (FRAME_TOOL_BAR_LINES (f)
+ ? (FRAME_PIXEL_WIDTH (f)
+ - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+ : 0),
+ make_number (FRAME_TOOL_BAR_HEIGHT (f)))),
+ Fcons (Qframe_inner_size,
+ Fcons (make_number
+ (frame_inner_edges.right - frame_inner_edges.left),
+ make_number
+ (frame_inner_edges.bottom - frame_inner_edges.top))));
+}
+
DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
doc: /* Get power status information from Windows system.
@@ -7523,8 +7692,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. */
@@ -8046,17 +8215,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,
@@ -8073,7 +8244,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");
@@ -8088,8 +8258,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));
@@ -8377,6 +8545,7 @@ only be necessary if the default setting causes problems. */);
defsubr (&Sx_open_connection);
defsubr (&Sx_close_connection);
defsubr (&Sx_display_list);
+ defsubr (&Sx_frame_geometry);
defsubr (&Sx_synchronize);
/* W32 specific functions */
@@ -8393,6 +8562,7 @@ only be necessary if the default setting causes problems. */);
defsubr (&Sw32_toggle_lock_key);
defsubr (&Sw32_window_exists_p);
defsubr (&Sw32_frame_rect);
+ defsubr (&Sw32_frame_menu_bar_size);
defsubr (&Sw32_battery_status);
#ifdef WINDOWSNT
@@ -8401,9 +8571,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 78e5431ee16..ab772679908 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -57,51 +57,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define JOHAB_CHARSET 130
#endif
-Lisp_Object Qgdi;
-Lisp_Object Quniscribe;
-static Lisp_Object QCformat;
-static Lisp_Object Qmonospace, Qsansserif, Qmono, Qsans, Qsans_serif;
-static Lisp_Object Qserif, Qscript, Qdecorative;
-static Lisp_Object Qraster, Qoutline, Qunknown;
-
-/* antialiasing */
-static Lisp_Object Qstandard, Qsubpixel, Qnatural;
-
-/* languages */
-static Lisp_Object Qzh;
-
-/* scripts */
-static Lisp_Object Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
-static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali;
-static Lisp_Object Qgurmukhi, Qgujarati, Qoriya, Qtamil, Qtelugu;
-static Lisp_Object Qkannada, Qmalayalam, Qsinhala, Qthai, Qlao;
-static Lisp_Object Qtibetan, Qmyanmar, Qgeorgian, Qhangul, Qethiopic;
-static Lisp_Object Qcherokee, Qcanadian_aboriginal, Qogham, Qrunic;
-static Lisp_Object Qkhmer, Qmongolian, Qbraille, Qhan;
-static Lisp_Object Qideographic_description, Qcjk_misc, Qkana, Qbopomofo;
-static Lisp_Object Qkanbun, Qyi, Qbyzantine_musical_symbol;
-static Lisp_Object Qmusical_symbol, Qmathematical, Qcham, Qphonetic;
-/* Not defined in characters.el, but referenced in fontset.el. */
-static Lisp_Object Qbalinese, Qbuginese, Qbuhid, Qcuneiform, Qcypriot;
-static Lisp_Object Qdeseret, Qglagolitic, Qgothic, Qhanunoo, Qkharoshthi;
-static Lisp_Object Qlimbu, Qlinear_b, Qold_italic, Qold_persian, Qosmanya;
-static Lisp_Object Qphags_pa, Qphoenician, Qshavian, Qsyloti_nagri;
-static Lisp_Object Qtagalog, Qtagbanwa, Qtai_le, Qtifinagh, Qugaritic;
-
-/* W32 charsets: for use in Vw32_charset_info_alist. */
-static Lisp_Object Qw32_charset_ansi, Qw32_charset_default;
-static Lisp_Object Qw32_charset_symbol, Qw32_charset_shiftjis;
-static Lisp_Object Qw32_charset_hangeul, Qw32_charset_gb2312;
-static Lisp_Object Qw32_charset_chinesebig5, Qw32_charset_oem;
-static Lisp_Object Qw32_charset_easteurope, Qw32_charset_turkish;
-static Lisp_Object Qw32_charset_baltic, Qw32_charset_russian;
-static Lisp_Object Qw32_charset_arabic, Qw32_charset_greek;
-static Lisp_Object Qw32_charset_hebrew, Qw32_charset_vietnamese;
-static Lisp_Object Qw32_charset_thai, Qw32_charset_johab, Qw32_charset_mac;
-
-/* Font spacing symbols - defined in font.c. */
-extern Lisp_Object Qc, Qp, Qm;
-
static void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
static BYTE w32_antialias_type (Lisp_Object);
@@ -115,15 +70,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 +242,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, tem);
}
/* w32 implementation of get_cache for font backend.
@@ -473,7 +428,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 +442,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;
-
- 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;
+ memset (metrics, 0, sizeof (struct font_metrics));
+ metrics->ascent = font->ascent;
+ metrics->descent = font->descent;
- 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 +571,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 +703,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 +832,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 +925,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 +955,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 +1401,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 +1520,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 +2475,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 16fb650efe7..82c5e09b9fc 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 ee37fe61b22..c90404bbc2d 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 3b4738fcf46..ee0eb161502 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-2015 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. */
+#if defined _WIN64 || defined WIDE_EMACS_INT
+# 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 MINGW_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 256GB */
-#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 MINGW_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 >= 0x00800000)
+ 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 (&params, 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, &params);
+ 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)
+ {
+ /* If found, use it. */
+ p = blocks[i].address;
+ blocks[i].occupied = TRUE;
+ }
+ else
{
- /* Decommit size bytes from the end of the heap. */
- if (using_dynamic_heap
- && !VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT))
- return NULL;
- }
+ /* 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;
+ void *p;
- 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);
-
- 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;
+}
+
+/* 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;
-#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)
+ 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);
+ }
+
+ if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0)
+ DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ()));
- needs_to_be = (DWORD_PTR) ROUND_UP (get_heap_end (), align);
- need_to_alloc = needs_to_be - (DWORD_PTR) get_heap_end ();
+ /* 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 775322dda4e..b5eb3ffa854 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 665e7c1046e..e09903f99be 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
@@ -656,11 +657,12 @@ handle_file_notifications (struct input_event *hold_quit)
Lisp_Object action = lispy_file_action (fni->Action);
inev.kind = FILE_NOTIFY_EVENT;
- inev.code = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
inev.timestamp = GetTickCount ();
inev.modifiers = 0;
inev.frame_or_window = callback;
inev.arg = Fcons (action, fname);
+ inev.arg = list3 (make_pointer_integer (notifications_desc),
+ action, fname);
kbd_buffer_store_event_hold (&inev, hold_quit);
if (!fni->NextEntryOffset)
diff --git a/src/w32inevt.h b/src/w32inevt.h
index 1776d31318c..4677c3eb5f8 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 8faf6343338..2a1dafbd6d7 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -98,12 +98,10 @@ AppendMenuW_Proc unicode_append_menu = NULL;
MessageBoxW_Proc unicode_message_box = NULL;
#endif /* NTGUI_UNICODE */
-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 +139,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 ();
@@ -219,9 +217,9 @@ menubar_selection_callback (struct frame *f, void * client_data)
else
{
entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
- /* The EMACS_INT cast avoids a warning. There's no problem
+ /* The UINT_PTR cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
- if ((int) (EMACS_INT) client_data == i)
+ if ((int) (UINT_PTR) client_data == i)
{
int j;
struct input_event buf;
@@ -376,12 +374,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 +438,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 +451,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 +501,7 @@ 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, -1, -1, 2, 0, Qmenu_bar_lines);
}
unblock_input ();
@@ -561,8 +547,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 +557,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 +587,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 +646,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 +696,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);
+ wv->call_data = !NILP (def) ? (void *) (UINT_PTR) i : 0;
if (NILP (type))
wv->button_type = BUTTON_TYPE_NONE;
@@ -742,11 +719,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 +728,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 +810,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 +831,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 +872,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 +897,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 +939,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 +960,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 +1008,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;
}
}
@@ -1311,9 +1253,9 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
if (wv->key != NULL)
{
out_string = SAFE_ALLOCA (strlen (wv->name) + strlen (wv->key) + 2);
- strcpy (out_string, wv->name);
- strcat (out_string, "\t");
- strcat (out_string, wv->key);
+ p = stpcpy (out_string, wv->name);
+ p = stpcpy (p, "\t");
+ strcpy (p, wv->key);
}
else
out_string = (char *)wv->name;
@@ -1459,17 +1401,21 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
info.cbSize = sizeof (info);
info.fMask = MIIM_DATA;
- /* Set help string for menu item. Leave it as a Lisp_Object
- until it is ready to be displayed, since GC can happen while
- menus are active. */
+ /* Set help string for menu item. Leave it as a pointer to
+ a Lisp_String until it is ready to be displayed, since GC
+ can happen while menus are active. */
if (!NILP (wv->help))
{
+ /* We use XUNTAG below because in a 32-bit build
+ --with-wide-int we cannot pass a Lisp_Object
+ via a DWORD member of MENUITEMINFO. */
/* As of Jul-2012, w32api headers say that dwItemData
has DWORD type, but that's a bug: it should actually
be ULONG_PTR, which is correct for 32-bit and 64-bit
Windows alike. MSVC headers get it right; hopefully,
MinGW headers will, too. */
- info.dwItemData = (ULONG_PTR) XLI (wv->help);
+ eassert (STRINGP (wv->help));
+ info.dwItemData = (ULONG_PTR) XUNTAG (wv->help, Lisp_String);
}
if (wv->button_type == BUTTON_TYPE_RADIO)
{
@@ -1530,11 +1476,24 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
Lisp_Object frame, help;
- /* No help echo on owner-draw menu items, or when the keyboard is used
- to navigate the menus, since tooltips are distracting if they pop
- up elsewhere. */
- if (flags & MF_OWNERDRAW || flags & MF_POPUP
- || !(flags & MF_MOUSESELECT))
+ /* No help echo on owner-draw menu items, or when the keyboard
+ is used to navigate the menus, since tooltips are distracting
+ if they pop up elsewhere. */
+ if ((flags & MF_OWNERDRAW) || (flags & MF_POPUP)
+ || !(flags & MF_MOUSESELECT)
+ /* Ignore any dwItemData for menu items whose flags don't
+ have the MF_HILITE bit set. These are dwItemData that
+ Windows sends our way, but they aren't pointers to our
+ Lisp_String objects, so trying to create Lisp_Strings out
+ of them below and pass that to the keyboard queue will
+ crash Emacs when we try to display those "strings". It
+ is unclear why we get these dwItemData, or what they are:
+ sometimes they point to a wchar_t string that is the menu
+ title, sometimes to someting that doesn't look like text
+ at all. (The problematic data also comes with the 0x0800
+ bit set, but this bit is not documented, so we don't want
+ to depend on it.) */
+ || !(flags & MF_HILITE))
help = Qnil;
else
{
@@ -1545,7 +1504,10 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
info.fMask = MIIM_DATA;
get_menu_item_info (menu, item, FALSE, &info);
- help = info.dwItemData ? XIL (info.dwItemData) : Qnil;
+ help =
+ info.dwItemData
+ ? make_lisp_ptr ((void *) info.dwItemData, Lisp_String)
+ : Qnil;
}
/* Store the help echo in the keyboard buffer as the X toolkit
diff --git a/src/w32notify.c b/src/w32notify.c
index 437029140aa..ab6cd12ab93 100644
--- a/src/w32notify.c
+++ b/src/w32notify.c
@@ -118,9 +118,7 @@ BYTE file_notifications[16384];
DWORD notifications_size;
void *notifications_desc;
-static Lisp_Object Qfile_name, Qdirectory_name, Qattributes, Qsize;
-static Lisp_Object Qlast_write_time, Qlast_access_time, Qcreation_time;
-static Lisp_Object Qsecurity_desc, Qsubtree, watch_list;
+static Lisp_Object watch_list;
/* Signal to the main thread that we have file notifications for it to
process. */
@@ -247,7 +245,6 @@ watch_worker (LPVOID arg)
do {
BOOL status;
- DWORD sleep_result;
DWORD bytes_ret = 0;
if (dirwatch->dir)
@@ -275,7 +272,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 +284,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);
@@ -584,7 +580,7 @@ generate notifications correctly, though. */)
report_file_error ("Cannot watch file", Fcons (file, Qnil));
}
/* Store watch object in watch list. */
- watch_descriptor = XIL ((EMACS_INT)dirwatch);
+ watch_descriptor = make_pointer_integer (dirwatch);
watch_object = Fcons (watch_descriptor, callback);
watch_list = Fcons (watch_object, watch_list);
@@ -609,7 +605,7 @@ WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */)
if (!NILP (watch_object))
{
watch_list = Fdelete (watch_object, watch_list);
- dirwatch = (struct notification *)XLI (watch_descriptor);
+ dirwatch = (struct notification *)XINTPTR (watch_descriptor);
if (w32_valid_pointer_p (dirwatch, sizeof(struct notification)))
status = remove_watch (dirwatch);
}
@@ -624,7 +620,7 @@ WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */)
Lisp_Object
w32_get_watch_object (void *desc)
{
- Lisp_Object descriptor = XIL ((EMACS_INT)desc);
+ Lisp_Object descriptor = make_pointer_integer (desc);
/* This is called from the input queue handling code, inside a
critical section, so we cannot possibly QUIT if watch_list is not
@@ -644,7 +640,6 @@ syms_of_w32notify (void)
DEFSYM (Qfile_name, "file-name");
DEFSYM (Qdirectory_name, "directory-name");
DEFSYM (Qattributes, "attributes");
- DEFSYM (Qsize, "size");
DEFSYM (Qlast_write_time, "last-write-time");
DEFSYM (Qlast_access_time, "last-access-time");
DEFSYM (Qcreation_time, "creation-time");
diff --git a/src/w32proc.c b/src/w32proc.c
index c067eba2b4e..74731db2426 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>
@@ -71,8 +72,6 @@ extern BOOL WINAPI IsValidLocale (LCID, DWORD);
+ ((DWORD_PTR)(var) - (section)->VirtualAddress) \
+ (filedata).file_base))
-Lisp_Object Qhigh, Qlow;
-
/* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
static signal_handler sig_handlers[NSIG];
@@ -1077,6 +1076,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
DWORD flags;
char dir[ MAX_PATH ];
char *p;
+ const char *ext;
if (cp == NULL) emacs_abort ();
@@ -1115,6 +1115,15 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
if (*p == '/')
*p = '\\';
+ /* CreateProcess handles batch files as exe specially. This special
+ handling fails when both the batch file and arguments are quoted.
+ We pass NULL as exe to avoid the special handling. */
+ if (exe && cmdline[0] == '"' &&
+ (ext = strrchr (exe, '.')) &&
+ (xstrcasecmp (ext, ".bat") == 0
+ || xstrcasecmp (ext, ".cmd") == 0))
+ exe = NULL;
+
flags = (!NILP (Vw32_start_process_share_console)
? CREATE_NEW_PROCESS_GROUP
: CREATE_NEW_CONSOLE);
@@ -1604,6 +1613,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);
@@ -1645,10 +1663,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
if (egetenv ("CMDPROXY"))
strcpy (cmdname, egetenv ("CMDPROXY"));
else
- {
- strcpy (cmdname, SDATA (Vinvocation_directory));
- strcat (cmdname, "cmdproxy.exe");
- }
+ strcpy (lispstpcpy (cmdname, Vinvocation_directory), "cmdproxy.exe");
/* Can't use unixtodos_filename here, since that needs its file
name argument encoded in UTF-8. */
@@ -1772,12 +1787,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 +2264,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 +2923,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 +2987,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);
@@ -3063,13 +3077,18 @@ yield nil. */)
(Lisp_Object cp)
{
CHARSETINFO info;
+ DWORD dwcp;
CHECK_NUMBER (cp);
if (!IsValidCodePage (XINT (cp)))
return Qnil;
- if (TranslateCharsetInfo ((DWORD *) XINT (cp), &info, TCI_SRCCODEPAGE))
+ /* Going through a temporary DWORD variable avoids compiler warning
+ about cast to pointer from integer of different size, when
+ building --with-wide-int. */
+ dwcp = XINT (cp);
+ if (TranslateCharsetInfo ((DWORD *) dwcp, &info, TCI_SRCCODEPAGE))
return make_number (info.ciCharset);
return Qnil;
@@ -3128,8 +3147,8 @@ If successful, the new layout id is returned, otherwise nil. */)
CHECK_NUMBER_CAR (layout);
CHECK_NUMBER_CDR (layout);
- kl = (HKL) ((XINT (XCAR (layout)) & 0xffff)
- | (XINT (XCDR (layout)) << 16));
+ kl = (HKL) (UINT_PTR) ((XINT (XCAR (layout)) & 0xffff)
+ | (XINT (XCDR (layout)) << 16));
/* Synchronize layout with input thread. */
if (dwWindowsThreadId)
@@ -3150,6 +3169,192 @@ 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))
+ {
+ size_t locval_len;
+
+ /* This is for when they only specify the language, as in "ENU". */
+ if (stricmp (locval, lname) == 0)
+ {
+ found_lcid = try_lcid;
+ return FALSE;
+ }
+ locval_len = strlen (locval);
+ strcpy (locval + locval_len, "_");
+ if (GetLocaleInfo (try_lcid, LOCALE_SABBREVCTRYNAME,
+ locval + locval_len + 1, LOCALE_NAME_MAX_LENGTH))
+ {
+ 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)
@@ -3260,6 +3465,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 41554b87c33..3c554c622ae 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);
@@ -107,17 +107,11 @@ static Lisp_Object validate_coding_system (Lisp_Object coding_system);
static void setup_windows_coding_system (Lisp_Object coding_system,
struct coding_system * coding);
-
-/* A remnant from X11: Symbol for the CLIPBORD selection type. Other
- selections are not used on Windows, so we don't need symbols for
- PRIMARY and SECONDARY. */
-Lisp_Object QCLIPBOARD;
-
/* Internal pseudo-constants, initialized in globals_of_w32select()
based on current system parameters. */
static LCID DEFAULT_LCID;
static UINT ANSICP, OEMCP;
-static Lisp_Object QUNICODE, QANSICP, QOEMCP;
+static Lisp_Object QANSICP, QOEMCP;
/* A hidden window just for the clipboard management. */
static HWND clipboard_owner;
@@ -420,7 +414,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)
@@ -1013,9 +1007,9 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
return (ret);
}
-/* Support checking for a clipboard selection. */
+/* Support checking for a clipboard selection. */
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
+DEFUN ("w32-selection-exists-p", Fw32_selection_exists_p, Sw32_selection_exists_p,
0, 2, 0,
doc: /* Whether there is an owner for the given X selection.
SELECTION should be the name of the selection in question, typically
@@ -1031,7 +1025,7 @@ frame's display, or the first available X display. */)
CHECK_SYMBOL (selection);
/* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
- if the clipboard currently has valid text format contents. */
+ if the clipboard currently has valid text format contents. */
if (EQ (selection, QCLIPBOARD))
{
@@ -1060,14 +1054,14 @@ frame's display, or the first available X display. */)
}
/* One-time init. Called in the un-dumped Emacs, but not in the
- dumped version. */
+ dumped version. */
void
syms_of_w32select (void)
{
defsubr (&Sw32_set_clipboard_data);
defsubr (&Sw32_get_clipboard_data);
- defsubr (&Sx_selection_exists_p);
+ defsubr (&Sw32_selection_exists_p);
DEFVAR_LISP ("selection-coding-system", Vselection_coding_system,
doc: /* Coding system for communicating with other programs.
diff --git a/src/w32term.c b/src/w32term.c
index e5b3a3129eb..251c46c73cf 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;
@@ -181,7 +185,7 @@ void x_lower_frame (struct frame *);
void x_scroll_bar_clear (struct frame *);
void x_wm_set_size_hint (struct frame *, long, bool);
void x_raise_frame (struct frame *);
-void x_set_window_size (struct frame *, int, int, int, bool);
+void x_set_window_size (struct frame *, bool, int, int, bool);
void x_wm_set_window_state (struct frame *, int);
void x_wm_set_icon_pixmap (struct frame *, int);
static void w32_initialize (void);
@@ -216,10 +220,6 @@ static void w32fullscreen_hook (struct frame *);
static void x_check_font (struct frame *, struct font *);
#endif
-static Lisp_Object Qvendor_specific_keysyms;
-static Lisp_Object Qadded, Qremoved, Qmodified;
-static Lisp_Object Qrenamed_from, Qrenamed_to;
-
/***********************************************************************
Debugging
@@ -454,7 +454,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];
@@ -559,7 +559,7 @@ x_update_window_begin (struct window *w)
if (f == hlinfo->mouse_face_mouse_frame)
{
/* Don't do highlighting for mouse motion during the update. */
- hlinfo->mouse_face_defer = 1;
+ hlinfo->mouse_face_defer = true;
/* If F needs to be redrawn, simply forget about any prior mouse
highlighting. */
@@ -682,11 +682,11 @@ x_update_window_end (struct window *w, bool cursor_on_p,
block_input ();
if (cursor_on_p)
- display_and_set_cursor (w, 1,
+ display_and_set_cursor (w, true,
w->output_cursor.hpos, w->output_cursor.vpos,
w->output_cursor.x, w->output_cursor.y);
- if (draw_window_fringes (w, 1))
+ if (draw_window_fringes (w, true))
{
if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
x_draw_right_divider (w);
@@ -728,7 +728,7 @@ x_update_end (struct frame *f)
return;
/* Mouse highlight may be displayed again. */
- MOUSE_HL_INFO (f)->mouse_face_defer = 0;
+ MOUSE_HL_INFO (f)->mouse_face_defer = false;
}
@@ -758,7 +758,7 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
eassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
- desired_row->redraw_fringe_bitmaps_p = 1;
+ desired_row->redraw_fringe_bitmaps_p = true;
/* When a window has disappeared, make sure that no rest of
full-width rows stays visible in the internal border. Could
@@ -903,7 +903,7 @@ w32_destroy_fringe_bitmap (int which)
static void x_set_glyph_string_clipping (struct glyph_string *);
static void x_set_glyph_string_gc (struct glyph_string *);
static void x_draw_glyph_string_background (struct glyph_string *,
- int);
+ bool);
static void x_draw_glyph_string_foreground (struct glyph_string *);
static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
static void x_draw_glyph_string_box (struct glyph_string *);
@@ -925,7 +925,7 @@ static void w32_draw_relief_rect (struct frame *, int, int, int, int,
int, int, int, int, int, int,
RECT *);
static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
- int, int, int, RECT *);
+ int, bool, bool, RECT *);
/* Set S->gc to a suitable GC for drawing glyph string S in cursor
@@ -999,7 +999,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 +1049,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)
{
@@ -1064,7 +1064,7 @@ x_set_glyph_string_gc (struct glyph_string *s)
else if (s->hl == DRAW_CURSOR)
{
x_set_cursor_gc (s);
- s->stippled_p = 0;
+ s->stippled_p = false;
}
else if (s->hl == DRAW_MOUSE_FACE)
{
@@ -1078,10 +1078,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);
@@ -1193,7 +1190,7 @@ x_clear_glyph_string_rect (struct glyph_string *s,
contains the first component of a composition. */
static void
-x_draw_glyph_string_background (struct glyph_string *s, int force_p)
+x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
{
/* Nothing to do if background has already been drawn or if it
shouldn't be drawn in the first place. */
@@ -1211,7 +1208,7 @@ x_draw_glyph_string_background (struct glyph_string *s, int force_p)
s->background_width,
s->height - 2 * box_line_width);
XSetFillStyle (s->display, s->gc, FillSolid);
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
else
#endif
@@ -1223,7 +1220,7 @@ x_draw_glyph_string_background (struct glyph_string *s, int force_p)
x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
}
}
@@ -1276,11 +1273,11 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
y = s->ybase - boff;
if (s->for_overlaps
|| (s->background_filled_p && s->hl != DRAW_CURSOR))
- font->driver->draw (s, 0, s->nchars, x, y, 0);
+ font->driver->draw (s, 0, s->nchars, x, y, false);
else
- font->driver->draw (s, 0, s->nchars, x, y, 1);
+ font->driver->draw (s, 0, s->nchars, x, y, true);
if (s->face->overstrike)
- font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+ font->driver->draw (s, 0, s->nchars, x + 1, y, false);
SelectObject (s->hdc, old_font);
}
@@ -1334,9 +1331,9 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
int xx = x + s->cmp->offsets[j * 2];
int yy = y - s->cmp->offsets[j * 2 + 1];
- font->driver->draw (s, j, j + 1, xx, yy, 0);
+ font->driver->draw (s, j, j + 1, xx, yy, false);
if (s->face->overstrike)
- font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+ font->driver->draw (s, j, j + 1, xx + 1, yy, false);
}
SelectObject (s->hdc, old_font);
}
@@ -1361,20 +1358,20 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
if (j < i)
{
- font->driver->draw (s, j, i, x, y, 0);
+ font->driver->draw (s, j, i, x, y, false);
x += width;
}
xoff = LGLYPH_XOFF (glyph);
yoff = LGLYPH_YOFF (glyph);
wadjust = LGLYPH_WADJUST (glyph);
- font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+ font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
x += wadjust;
j = i + 1;
width = 0;
}
}
if (j < i)
- font->driver->draw (s, j, i, x, y, 0);
+ font->driver->draw (s, j, i, x, y, false);
SelectObject (s->hdc, old_font);
}
@@ -1389,7 +1386,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
struct glyph *glyph = s->first_glyph;
XChar2b char2b[8];
int x, i, j;
- int with_background;
+ bool with_background;
/* If first glyph of S has a left box line, start drawing the text
of S to the right of that box line. */
@@ -1404,8 +1401,8 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
s->char2b = char2b;
- with_background = ! (s->for_overlaps
- || (s->background_filled_p && s->hl != DRAW_CURSOR));
+ with_background = ((s->for_overlaps
+ || (s->background_filled_p && s->hl != DRAW_CURSOR))) == 0;
for (i = 0; i < s->nchars; i++, glyph++)
{
char buf[7], *str = NULL;
@@ -1715,7 +1712,7 @@ w32_draw_relief_rect (struct frame *f,
static void
w32_draw_box_rect (struct glyph_string *s,
int left_x, int top_y, int right_x, int bottom_y, int width,
- int left_p, int right_p, RECT *clip_rect)
+ bool left_p, bool right_p, RECT *clip_rect)
{
w32_set_clip_rectangle (s->hdc, clip_rect);
@@ -1750,8 +1747,8 @@ w32_draw_box_rect (struct glyph_string *s,
static void
x_draw_glyph_string_box (struct glyph_string *s)
{
- int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
- int left_p, right_p;
+ int width, left_x, right_x, top_y, bottom_y, last_x;
+ bool left_p, right_p, raised_p;
struct glyph *last_glyph;
RECT clip_rect;
@@ -2160,7 +2157,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
#endif
x_draw_glyph_string_bg_rect (s, x, y, width, height);
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
/* Draw the foreground. */
@@ -2296,7 +2293,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
}
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
@@ -2324,7 +2321,7 @@ x_draw_glyph_string (struct glyph_string *s)
if (next->first_glyph->type == STRETCH_GLYPH)
x_draw_stretch_glyph_string (next);
else
- x_draw_glyph_string_background (next, 1);
+ x_draw_glyph_string_background (next, true);
next->num_clips = 0;
}
}
@@ -2341,7 +2338,7 @@ x_draw_glyph_string (struct glyph_string *s)
{
x_set_glyph_string_clipping (s);
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_glyph_string_box (s);
x_set_glyph_string_clipping (s);
relief_drawn_p = 1;
@@ -2369,26 +2366,26 @@ x_draw_glyph_string (struct glyph_string *s)
case CHAR_GLYPH:
if (s->for_overlaps)
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 0);
+ x_draw_glyph_string_background (s, false);
x_draw_glyph_string_foreground (s);
break;
case COMPOSITE_GLYPH:
if (s->for_overlaps || (s->cmp_from > 0
&& ! s->first_glyph->u.cmp.automatic))
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_composite_glyph_string_foreground (s);
break;
case GLYPHLESS_GLYPH:
if (s->for_overlaps)
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 0);
+ x_draw_glyph_string_background (s, false);
x_draw_glyphless_glyph_string_foreground (s);
break;
@@ -3250,12 +3247,11 @@ queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
Lisp_Object action = lispy_file_action (fni->Action);
event->kind = FILE_NOTIFY_EVENT;
- event->code
- = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
event->timestamp = msg->msg.time;
event->modifiers = 0;
event->frame_or_window = callback;
- event->arg = Fcons (action, fname);
+ event->arg = list3 (make_pointer_integer (notifications_desc),
+ action, fname);
kbd_buffer_store_event (event);
(*evcount)++;
@@ -3306,7 +3302,7 @@ note_mouse_movement (struct frame *frame, MSG *msg)
if (msg->hwnd != FRAME_W32_WINDOW (frame))
{
- frame->mouse_moved = 1;
+ frame->mouse_moved = true;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, -1, -1);
dpyinfo->last_mouse_glyph_frame = NULL;
@@ -3319,7 +3315,7 @@ note_mouse_movement (struct frame *frame, MSG *msg)
|| mouse_x < r->left || mouse_x >= r->right
|| mouse_y < r->top || mouse_y >= r->bottom)
{
- frame->mouse_moved = 1;
+ frame->mouse_moved = true;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, mouse_x, mouse_y);
/* Remember the mouse position here, as w32_mouse_position only
@@ -3339,11 +3335,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 +3351,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 +3375,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 +3383,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;
@@ -3391,7 +3399,7 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
/* Clear the mouse-moved flag for every frame on this display. */
FOR_EACH_FRAME (tail, frame)
- XFRAME (frame)->mouse_moved = 0;
+ XFRAME (frame)->mouse_moved = false;
dpyinfo->last_mouse_scroll_bar = NULL;
@@ -3410,7 +3418,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 +3443,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 +3485,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 +3508,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 +3520,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 +3594,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 +3706,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 +3725,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 +3778,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 +3822,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, false);
}
else
{
@@ -3831,6 +3886,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, true);
+ }
+ 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 +4002,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 +4026,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 +4134,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 +4161,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 +4202,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 +4248,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 +4378,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,33 +4386,77 @@ 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);
- f->mouse_moved = 0;
+ f->mouse_moved = false;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+
+ *time = dpyinfo->last_mouse_movement_time;
+
+ 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 = false;
dpyinfo->last_mouse_scroll_bar = NULL;
*time = dpyinfo->last_mouse_movement_time;
@@ -4116,7 +4478,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 +4500,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
@@ -4222,7 +4596,7 @@ w32_read_socket (struct terminal *terminal,
/* Definitely not obscured, so mark as visible. */
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
+ SET_FRAME_ICONIFIED (f, false);
SET_FRAME_GARBAGED (f);
if (!f->output_data.w32->asked_for_visible)
DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
@@ -4284,7 +4658,7 @@ w32_read_socket (struct terminal *terminal,
&& !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
{
clear_mouse_face (hlinfo);
- hlinfo->mouse_face_hidden = 1;
+ hlinfo->mouse_face_hidden = true;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
@@ -4309,7 +4683,7 @@ w32_read_socket (struct terminal *terminal,
&& !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
{
clear_mouse_face (hlinfo);
- hlinfo->mouse_face_hidden = 1;
+ hlinfo->mouse_face_hidden = true;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
@@ -4387,7 +4761,7 @@ w32_read_socket (struct terminal *terminal,
&& !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
{
clear_mouse_face (hlinfo);
- hlinfo->mouse_face_hidden = 1;
+ hlinfo->mouse_face_hidden = true;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
@@ -4420,7 +4794,7 @@ w32_read_socket (struct terminal *terminal,
if (hlinfo->mouse_face_hidden)
{
- hlinfo->mouse_face_hidden = 0;
+ hlinfo->mouse_face_hidden = false;
clear_mouse_face (hlinfo);
}
@@ -4538,10 +4912,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 = false;
+ if (!tool_bar_p)
+ f->last_tool_bar_item = -1;
+ }
}
break;
}
@@ -4565,10 +4940,10 @@ w32_read_socket (struct terminal *terminal,
event; any subsequent mouse-movement Emacs events
should reflect only motion after the
ButtonPress. */
- f->mouse_moved = 0;
+ f->mouse_moved = false;
+ f->last_tool_bar_item = -1;
}
dpyinfo->last_mouse_frame = f;
- last_tool_bar_item = -1;
}
break;
@@ -4579,10 +4954,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);
@@ -4656,7 +5041,7 @@ w32_read_socket (struct terminal *terminal,
{
case SIZE_MINIMIZED:
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
inev.kind = ICONIFY_EVENT;
XSETFRAME (inev.frame_or_window, f);
@@ -4667,7 +5052,7 @@ w32_read_socket (struct terminal *terminal,
bool iconified = FRAME_ICONIFIED_P (f);
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
+ SET_FRAME_ICONIFIED (f, false);
/* wait_reading_process_output will notice this
and update the frame's display structures. */
@@ -4714,7 +5099,7 @@ w32_read_socket (struct terminal *terminal,
conditional again in revision 116727. martin */
if (iconified)
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
+ SET_FRAME_ICONIFIED (f, false);
/* wait_reading_process_output will notice this
and update the frame's display structures. */
@@ -4767,8 +5152,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 +5169,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;
}
}
@@ -5255,7 +5636,7 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
w->phys_cursor_type = cursor_type;
}
- w->phys_cursor_on_p = 1;
+ w->phys_cursor_on_p = true;
/* If this is the active cursor, we need to track it with the
system caret, so third party software like screen magnifiers
@@ -5293,7 +5674,7 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
? (w->phys_cursor.hpos < 0)
: (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
{
- glyph_row->cursor_in_fringe_p = 1;
+ glyph_row->cursor_in_fringe_p = true;
draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
return;
}
@@ -5330,7 +5711,7 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
/* Icons. */
-int
+bool
x_bitmap_icon (struct frame *f, Lisp_Object icon)
{
HANDLE main_icon;
@@ -5437,8 +5818,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 +5837,9 @@ 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,
+ false, Qfont);
}
/* X version sets font of input methods here also. */
@@ -5566,7 +5946,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
x_calc_absolute_position (f);
block_input ();
- x_wm_set_size_hint (f, (long) 0, 0);
+ x_wm_set_size_hint (f, (long) 0, false);
modified_left = f->left_pos;
modified_top = f->top_pos;
@@ -5579,6 +5959,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 +6036,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 +6058,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,
@@ -5663,78 +6092,73 @@ w32fullscreen_hook (struct frame *f)
}
/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+ If CHANGE_GRAVITY, change to top-left-corner window gravity
for this size change and subsequent size changes.
Otherwise we leave the window gravity unchanged. */
void
-x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
+x_set_window_size (struct frame *f, bool 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);
+ }
+
+ if (w32_add_wrapped_menu_bar_lines)
+ {
+ /* When the menu bar wraps sending a SetWindowPos shrinks the
+ height of the frame when the wrapped menu bar lines are not
+ accounted for (Bug#15174 and Bug#18720). Here we add these
+ extra lines to the frame height. */
+ MENUBARINFO info;
+ int default_menu_bar_height;
+ int menu_bar_height;
+
+ /* Why is (apparently) SM_CYMENUSIZE needed here instead of
+ SM_CYMENU ?? */
+ default_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
+ info.cbSize = sizeof (info);
+ info.rcBar.top = info.rcBar.bottom = 0;
+ GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info);
+ menu_bar_height = info.rcBar.bottom - info.rcBar.top;
+
+ if ((default_menu_bar_height > 0)
+ && (menu_bar_height > default_menu_bar_height)
+ && ((menu_bar_height % default_menu_bar_height) == 0))
+ pixelheight = pixelheight + menu_bar_height - default_menu_bar_height;
}
f->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
+ x_wm_set_size_hint (f, (long) 0, false);
- {
- 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 +6207,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 +6237,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 ();
@@ -5919,7 +6328,7 @@ x_lower_frame (struct frame *f)
}
static void
-w32_frame_raise_lower (struct frame *f, int raise_flag)
+w32_frame_raise_lower (struct frame *f, bool raise_flag)
{
if (! FRAME_W32_P (f))
return;
@@ -6044,7 +6453,7 @@ x_make_frame_invisible (struct frame *f)
FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
and synchronize with the server to make sure we agree. */
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 0);
+ SET_FRAME_ICONIFIED (f, false);
unblock_input ();
}
@@ -6069,7 +6478,7 @@ x_iconify_frame (struct frame *f)
SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
unblock_input ();
}
@@ -6139,7 +6548,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 +6573,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 +6636,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 +6723,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 +6735,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 +6746,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 +6885,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 +6936,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 +6990,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);
}
}
@@ -6663,6 +7101,21 @@ systems of the NT family, including W2K, XP, Vista, Windows 7 and
Windows 8. It is set to nil on Windows 9X. */);
w32_unicode_filenames = 0;
+
+ /* FIXME: The following two variables will be (hopefully) removed
+ before Emacs 25.1 gets released. */
+
+ DEFVAR_BOOL ("w32-add-wrapped-menu-bar-lines",
+ w32_add_wrapped_menu_bar_lines,
+ doc: /* Non-nil means frame resizing accounts for wrapped menu bar lines.
+A value of nil means frame resizing does not add the height of wrapped
+menu bar lines when sending a frame resize request to the Windows API.
+This usually means that the resulting frame height is off by the number
+of wrapped menu bar lines. If this is non-nil, Emacs adds the height of
+wrapped menu bar lines when sending frame resize requests to the Windows
+API. */);
+ w32_add_wrapped_menu_bar_lines = 1;
+
DEFVAR_BOOL ("w32-enable-frame-resize-hack",
w32_enable_frame_resize_hack,
doc: /* Non-nil means enable hack for frame resizing on Windows.
diff --git a/src/w32term.h b/src/w32term.h
index 58ed90c0bde..3532e95fdce 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);
@@ -213,14 +239,12 @@ Lisp_Object display_x_get_resource (struct w32_display_info *,
extern struct w32_display_info *w32_term_init (Lisp_Object,
char *, char *);
extern int w32_defined_color (struct frame *f, const char *color,
- XColor *color_def, int alloc);
-extern void x_set_window_size (struct frame *f, int change_grav,
+ XColor *color_def, bool alloc_p);
+extern void x_set_window_size (struct frame *f, bool change_gravity,
int width, int height, bool pixelwise);
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,8 +253,11 @@ 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 bool x_bitmap_icon (struct frame *, Lisp_Object);
extern void initialize_frame_menubar (struct frame *);
extern void x_free_frame_resources (struct frame *);
extern void x_real_positions (struct frame *, int *, int *);
@@ -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. */
@@ -463,8 +493,8 @@ struct scroll_bar {
(XSETINT ((low), ((DWORDLONG)(int64)) & 0xffffffff), \
XSETINT ((high), ((DWORDLONG)(int64) >> 32) & 0xffffffff))
#else /* not _WIN64 */
-/* Building a 32-bit C integer from two 16-bit lisp integers. */
-#define SCROLL_BAR_PACK(low, high) (XINT (high) << 16 | XINT (low))
+/* Building a 32-bit C unsigned integer from two 16-bit lisp integers. */
+#define SCROLL_BAR_PACK(low, high) ((UINT_PTR)(XINT (high) << 16 | XINT (low)))
/* Setting two lisp integers to the low and high words of a 32-bit C int. */
#define SCROLL_BAR_UNPACK(low, high, int32) \
@@ -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 0ad0a6bfe48..9cd97e28616 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -47,14 +47,10 @@ struct uniscribe_font_info
int uniscribe_available = 0;
-/* Defined in w32font.c, since it is required there as well. */
-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 +123,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;
@@ -189,8 +183,9 @@ uniscribe_otf_capability (struct font *font)
static Lisp_Object
uniscribe_shape (Lisp_Object lgstring)
{
- struct font * font;
- struct uniscribe_font_info * uniscribe_font;
+ struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
+ struct uniscribe_font_info *uniscribe_font
+ = (struct uniscribe_font_info *) font;
EMACS_UINT nchars;
int nitems, max_items, i, max_glyphs, done_glyphs;
wchar_t *chars;
@@ -205,9 +200,6 @@ uniscribe_shape (Lisp_Object lgstring)
HDC context = NULL;
HFONT old_font = NULL;
- CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
- uniscribe_font = (struct uniscribe_font_info *) font;
-
/* Get the chars from lgstring in a form we can use with uniscribe. */
max_glyphs = nchars = LGSTRING_GLYPH_LEN (lgstring);
done_glyphs = 0;
@@ -593,8 +585,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 +596,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 +607,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 +971,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 b41c06ee153..c4d69407176 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,9 @@ 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, Qfont)
+ && !frame_inhibit_resize (f, 1, Qfont))
+ x_set_window_size (f, 0, columns, rows, 0);
}
diff --git a/src/widgetprv.h b/src/widgetprv.h
index 60e4c0be47e..6cbbbd617f0 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 aafa4a16df1..2f44bf78304 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"
@@ -44,19 +45,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "msdos.h"
#endif
-Lisp_Object Qwindowp, Qwindow_live_p;
-static Lisp_Object Qwindow_valid_p;
-static Lisp_Object Qwindow_configuration_p;
-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_pixel_to_total;
-static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
-static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
-static Lisp_Object Qfloor, Qceiling;
-static Lisp_Object Qwindow_point_insertion_type;
-
static int displayed_window_lines (struct window *);
static int count_windows (struct window *);
static int get_leaf_windows (struct window *, struct window **, int);
@@ -86,7 +74,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
@@ -113,18 +101,9 @@ Lisp_Object minibuf_window;
shown as the selected window when the minibuffer is selected. */
Lisp_Object minibuf_selected_window;
-/* Hook run at end of temp_output_buffer_show. */
-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;
-
/* Used by the function window_scroll_pixel_based. */
static int window_scroll_pixel_based_preserve_x;
static int window_scroll_pixel_based_preserve_y;
@@ -145,66 +124,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 +903,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));
@@ -1028,6 +1029,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. */)
@@ -1055,6 +1065,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);
}
@@ -1204,12 +1216,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)));
}
@@ -1323,6 +1339,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
@@ -1366,7 +1393,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);
@@ -1530,10 +1557,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;
@@ -1674,6 +1704,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.
@@ -2388,16 +2426,14 @@ window_list (void)
Vwindow_list = Qnil;
FOR_EACH_FRAME (tail, frame)
{
- Lisp_Object args[2];
+ Lisp_Object arglist = Qnil;
/* We are visiting windows in canonical order, and add
new windows at the front of args[1], which means we
have to reverse this list at the end. */
- args[1] = Qnil;
- foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
- args[0] = Vwindow_list;
- args[1] = Fnreverse (args[1]);
- Vwindow_list = Fnconc (2, args);
+ foreach_window (XFRAME (frame), add_window_to_list, &arglist);
+ arglist = Fnreverse (arglist);
+ Vwindow_list = CALLN (Fnconc, Vwindow_list, arglist);
}
}
@@ -2952,17 +2988,34 @@ 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)
{
return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
}
+/* Placeholder used by temacs -nw before window.el is loaded. */
+DEFUN ("window--sanitize-window-sizes", Fwindow__sanitize_window_sizes,
+ Swindow__sanitize_window_sizes, 2, 2, 0,
+ doc: /* */
+ attributes: const)
+ (Lisp_Object frame, Lisp_Object horizontal)
+{
+ return Qnil;
+}
+
+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);
}
@@ -3241,89 +3294,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. */
@@ -3357,7 +3327,9 @@ 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->can_x_set_window_size)
+ || !(f->can_run_window_configuration_change_hook))
return;
/* Use the right buffer. Matters when running the local hooks. */
@@ -3452,17 +3424,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);
@@ -3474,16 +3450,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)
{
@@ -3492,7 +3465,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);
@@ -3638,10 +3613,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. */
@@ -3659,12 +3635,21 @@ temp_output_buffer_show (register Lisp_Object buf)
record_unwind_protect (select_window_norecord, prev_window);
Fselect_window (window, Qt);
Fset_buffer (w->contents);
- Frun_hooks (1, &Qtemp_buffer_show_hook);
+ run_hook (Qtemp_buffer_show_hook);
unbind_to (count, Qnil);
}
}
}
-
+
+/* Allocate basically initialized window. */
+
+static struct window *
+allocate_window (void)
+{
+ return ALLOCATE_ZEROED_PSEUDOVECTOR
+ (struct window, current_matrix, PVEC_WINDOW);
+}
+
/* Make new window, have it replace WINDOW in window-tree, and make
WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
horizontal child). */
@@ -3693,6 +3678,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);
@@ -3716,7 +3702,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);
@@ -3733,8 +3721,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. */
@@ -3995,11 +3983,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;
}
@@ -4149,11 +4134,7 @@ values. */)
/* Resize frame F's windows when number of lines of F is set to SIZE.
HORFLAG 1 means resize windows when number of columns of F is set to
- SIZE. PIXELWISE 1 means to interpret SIZE as pixels.
-
- This function can delete all windows but the selected one in order to
- satisfy the request. The result will be meaningful if and only if
- F's windows have meaningful sizes when you call this. */
+ SIZE. PIXELWISE 1 means to interpret SIZE as pixels. */
void
resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
{
@@ -4164,6 +4145,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);
@@ -4178,7 +4160,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)),
@@ -4190,7 +4171,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)),
@@ -4201,7 +4181,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. */
@@ -4243,6 +4224,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
{
@@ -4255,7 +4237,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
@@ -4459,7 +4440,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)
@@ -4603,6 +4586,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);
}
@@ -4864,6 +4848,7 @@ window_internal_height (struct window *w)
return ht;
}
+
/************************************************************************
Window Scrolling
@@ -4879,11 +4864,16 @@ window_internal_height (struct window *w)
static void
window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+
immediate_quit = 1;
n = clip_to_bounds (INT_MIN, n, INT_MAX);
wset_redisplay (XWINDOW (window));
+ if (whole && Vfast_but_imprecise_scrolling)
+ specbind (Qfontification_functions, Qnil);
+
/* If we must, use the pixel-based version which is much slower than
the line-based one but can handle varying line heights. */
if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
@@ -4891,6 +4881,8 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
else
window_scroll_line_based (window, n, whole, noerror);
+ unbind_to (count, Qnil);
+
/* Bug#15957. */
XWINDOW (window)->window_end_valid = 0;
immediate_quit = 0;
@@ -4914,6 +4906,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
@@ -4925,7 +4919,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))
{
@@ -4954,7 +4948,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;
@@ -5294,6 +5288,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);
}
@@ -5318,6 +5319,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. */
@@ -5333,6 +5336,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;
}
@@ -5448,6 +5452,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);
}
@@ -5584,6 +5595,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);
@@ -5598,6 +5610,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;
@@ -5623,6 +5636,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;
}
@@ -5646,6 +5661,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;
}
@@ -5736,14 +5753,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))
{
@@ -5765,7 +5784,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
{
@@ -5774,12 +5793,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
@@ -5827,7 +5844,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++;
}
@@ -5906,44 +5923,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,
@@ -6048,22 +6076,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;
};
@@ -6091,13 +6120,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.
@@ -6114,6 +6136,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);
@@ -6177,19 +6200,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. */
@@ -6206,36 +6216,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;
+ /* Disallow x_set_window_size, temporarily. */
+ f->can_x_set_window_size = 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
@@ -6258,8 +6244,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!
@@ -6314,7 +6300,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);
@@ -6322,7 +6310,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.
@@ -6353,18 +6343,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. */
{
@@ -6376,20 +6363,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. */
@@ -6424,30 +6417,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)
{
@@ -6457,9 +6426,13 @@ the return value is nil. Otherwise the value is t. */)
++n;
}
+ /* Allow x_set_window_size again and apply frame size changes if
+ needed. */
+ f->can_x_set_window_size = true;
+ adjust_frame_size (f, -1, -1, 1, 0, Qset_window_configuration);
+
adjust_frame_glyphs (f);
unblock_input ();
- unbind_to (count, Qnil);
/* Scan dead buffer windows. */
for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
@@ -6496,9 +6469,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)
{
@@ -6530,6 +6505,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
@@ -6636,7 +6612,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);
@@ -6644,7 +6622,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;
@@ -6706,33 +6686,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);
@@ -6746,8 +6720,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
@@ -6796,7 +6770,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;
@@ -6814,8 +6787,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
@@ -6823,11 +6796,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,
@@ -6889,12 +6874,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,
@@ -6945,9 +6943,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;
@@ -6961,32 +6961,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;
}
@@ -6996,19 +7042,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
@@ -7191,15 +7243,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;
}
@@ -7209,7 +7262,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)
{
@@ -7226,8 +7279,6 @@ init_window_once (void)
Vterminal_frame = selected_frame;
minibuf_window = f->minibuffer_window;
selected_window = f->selected_window;
-
- window_initialized = 1;
}
void
@@ -7255,6 +7306,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");
@@ -7295,7 +7347,7 @@ the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */
doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
If the minibuffer is active, the `minibuffer-scroll-window' mode line
is displayed in the `mode-line' face. */);
- mode_line_in_non_selected_windows = 1;
+ mode_line_in_non_selected_windows = true;
DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
@@ -7303,7 +7355,7 @@ is displayed in the `mode-line' face. */);
DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
- auto_window_vscroll_p = 1;
+ auto_window_vscroll_p = true;
DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
doc: /* Number of lines of continuity when scrolling by screenfuls. */);
@@ -7426,7 +7478,18 @@ all functions that symmetrically resize a parent window.
Note that when a frame's pixel size is not a multiple of the
frame's character size, at least one window may get resized
pixelwise even if this option is nil. */);
- window_resize_pixelwise = 0;
+ window_resize_pixelwise = false;
+
+ DEFVAR_BOOL ("fast-but-imprecise-scrolling",
+ Vfast_but_imprecise_scrolling,
+ doc: /* When non-nil, accelerate scrolling operations.
+This comes into play when scrolling rapidly over previously
+unfontified buffer regions. Only those portions of the buffer which
+are actually going to be displayed get fontified.
+
+Note that this optimization can cause the portion of the buffer
+displayed after a scrolling operation to be somewhat inaccurate. */);
+ Vfast_but_imprecise_scrolling = false;
defsubr (&Sselected_window);
defsubr (&Sminibuffer_window);
@@ -7481,12 +7544,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);
@@ -7497,6 +7562,7 @@ pixelwise even if this option is nil. */);
defsubr (&Sset_window_display_table);
defsubr (&Snext_window);
defsubr (&Sprevious_window);
+ defsubr (&Swindow__sanitize_window_sizes);
defsubr (&Sget_buffer_window);
defsubr (&Sdelete_other_windows_internal);
defsubr (&Sdelete_window_internal);
diff --git a/src/window.h b/src/window.h
index 43c44470fb6..2ec28ab4e56 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 line height 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,8 +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;
extern Lisp_Object window_list (void);
@@ -1024,6 +1097,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 ebab8395a6c..71871ec5885 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -324,52 +324,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define INFINITY 10000000
-Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-Lisp_Object Qwindow_scroll_functions;
-static Lisp_Object Qwindow_text_change_functions;
-static Lisp_Object Qredisplay_end_trigger_functions;
-Lisp_Object Qinhibit_point_motion_hooks;
-static Lisp_Object QCeval, QCpropertize;
-Lisp_Object QCfile, QCdata;
-static Lisp_Object Qfontified;
-static Lisp_Object Qgrow_only;
-static Lisp_Object Qinhibit_eval_during_redisplay;
-static Lisp_Object Qbuffer_position, Qposition, Qobject;
-static Lisp_Object Qright_to_left, Qleft_to_right;
-
-/* Cursor shapes. */
-Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
-
-/* Pointer shapes. */
-static Lisp_Object Qarrow, Qhand;
-Lisp_Object Qtext;
-
/* Holds the list (error). */
static Lisp_Object list_of_error;
-static Lisp_Object Qfontification_functions;
-
-static Lisp_Object Qwrap_prefix;
-static Lisp_Object Qline_prefix;
-static Lisp_Object Qredisplay_internal;
-
-/* Non-nil means don't actually do any redisplay. */
-
-Lisp_Object Qinhibit_redisplay;
-
-/* Names of text properties relevant for redisplay. */
-
-Lisp_Object Qdisplay;
-
-Lisp_Object Qspace, QCalign_to;
-static Lisp_Object QCrelative_width, QCrelative_height;
-Lisp_Object Qleft_margin, Qright_margin;
-static Lisp_Object Qspace_width, Qraise;
-static Lisp_Object Qslice;
-Lisp_Object Qcenter;
-static Lisp_Object Qmargin, Qpointer;
-static Lisp_Object Qline_height;
-
#ifdef HAVE_WINDOW_SYSTEM
/* Test if overflow newline into fringe. Called with iterator IT
@@ -403,31 +360,6 @@ static Lisp_Object Qline_height;
&& (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
|| *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) \
-/* Name of the face used to highlight trailing whitespace. */
-
-static Lisp_Object Qtrailing_whitespace;
-
-/* Name and number of the face used to highlight escape glyphs. */
-
-static Lisp_Object Qescape_glyph;
-
-/* Name and number of the face used to highlight non-breaking spaces. */
-
-static Lisp_Object Qnobreak_space;
-
-/* The symbol `image' which is the car of the lists used to represent
- images in Lisp. Also a tool bar style. */
-
-Lisp_Object Qimage;
-
-/* The image map types. */
-Lisp_Object QCmap;
-static Lisp_Object QCpointer;
-static Lisp_Object Qrect, Qcircle, Qpoly;
-
-/* Tool bar styles */
-Lisp_Object Qboth, Qboth_horiz, Qtext_image_horiz;
-
/* Non-zero means print newline to stdout before next mini-buffer
message. */
@@ -477,21 +409,6 @@ static struct text_pos this_line_min_pos;
static struct buffer *this_line_buffer;
-
-/* Values of those variables at last redisplay are stored as
- properties on `overlay-arrow-position' symbol. However, if
- Voverlay_arrow_position is a marker, last-arrow-position is its
- numerical position. */
-
-static Lisp_Object Qlast_arrow_position, Qlast_arrow_string;
-
-/* Alternative overlay-arrow-string and overlay-arrow-bitmap
- properties on a symbol in overlay-arrow-variable-list. */
-
-static Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
-
-Lisp_Object Qmenu_bar_update_hook;
-
/* Nonzero if an overlay arrow has been displayed in this window. */
static bool overlay_arrow_seen;
@@ -567,11 +484,6 @@ static bool display_last_displayed_message_p;
static bool message_buf_print;
-/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
-
-static Lisp_Object Qinhibit_menubar_update;
-static Lisp_Object Qmessage_truncate_lines;
-
/* Set to 1 in clear_message to make redisplay_internal aware
of an emptied echo area. */
@@ -691,8 +603,6 @@ int trace_move;
#define TRACE_MOVE(x) (void) 0
#endif
-static Lisp_Object Qauto_hscroll_mode;
-
/* Buffer being redisplayed -- for redisplay_window_error. */
static struct buffer *displayed_buffer;
@@ -712,8 +622,8 @@ enum prop_handled
struct props
{
- /* The name of the property. */
- Lisp_Object *name;
+ /* The symbol index of the name of the property. */
+ short name;
/* A unique index for the property. */
enum prop_idx idx;
@@ -734,14 +644,14 @@ static enum prop_handled handle_fontified_prop (struct it *);
static struct props it_props[] =
{
- {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
+ {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
/* Handle `face' before `display' because some sub-properties of
`display' need to know the face. */
- {&Qface, FACE_PROP_IDX, handle_face_prop},
- {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
- {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
- {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
- {NULL, 0, NULL}
+ {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
+ {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
+ {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
+ {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
+ {0, 0, NULL}
};
/* Value is the position described by X. If X is a marker, value is
@@ -796,9 +706,6 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
bool redisplaying_p;
-static Lisp_Object Qinhibit_free_realized_faces;
-static Lisp_Object Qmode_line_default_help_echo;
-
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
@@ -816,23 +723,14 @@ 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 */
-/* Name of the face used to display glyphless characters. */
-static Lisp_Object Qglyphless_char;
-
-/* Symbol for the purpose of Vglyphless_char_display. */
-static Lisp_Object Qglyphless_char_display;
-
-/* Method symbols for Vglyphless_char_display. */
-static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
-
/* Default number of seconds to wait before displaying an hourglass
cursor. */
#define DEFAULT_HOURGLASS_DELAY 1
@@ -905,7 +803,7 @@ static void iterate_out_of_display_property (struct it *);
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
static void redisplay_internal (void);
-static int echo_area_display (int);
+static bool echo_area_display (bool);
static void redisplay_windows (Lisp_Object);
static void redisplay_window (Lisp_Object, bool);
static Lisp_Object redisplay_window_error (Lisp_Object);
@@ -1024,6 +922,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 +968,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 +1042,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. */
@@ -1972,8 +1873,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
@@ -2189,7 +2090,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);
@@ -2311,10 +2215,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)
@@ -2516,7 +2417,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)
@@ -2550,7 +2451,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;
@@ -2638,15 +2539,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);
@@ -2654,7 +2554,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);
}
@@ -2694,8 +2594,6 @@ safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
return retval;
}
-static Lisp_Object Qeval;
-
Lisp_Object
safe_eval (Lisp_Object sexpr)
{
@@ -2848,17 +2746,14 @@ init_iterator (struct it *it, struct window *w,
row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
}
- /* Clear IT. */
- memset (it, 0, sizeof *it);
+ /* Clear IT, and set it->object and other IT's Lisp objects to Qnil.
+ Other parts of redisplay rely on that. */
+ memclear (it, sizeof *it);
it->current.overlay_string_index = -1;
it->current.dpvec_index = -1;
it->base_face_id = remapped_base_face_id;
- it->string = Qnil;
IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
it->paragraph_embedding = L2R;
- it->bidi_it.string.lstring = Qnil;
- it->bidi_it.string.s = NULL;
- it->bidi_it.string.bufpos = 0;
it->bidi_it.w = w;
/* The window in which we iterate over current_buffer: */
@@ -2879,7 +2774,6 @@ init_iterator (struct it *it, struct window *w,
* FRAME_LINE_HEIGHT (it->f));
else if (it->f->extra_line_spacing > 0)
it->extra_line_spacing = it->f->extra_line_spacing;
- it->max_extra_line_spacing = 0;
}
/* If realized faces have been removed, e.g. because of face
@@ -2891,10 +2785,6 @@ init_iterator (struct it *it, struct window *w,
if (FRAME_FACE_CACHE (it->f)->used == 0)
recompute_basic_faces (it->f);
- /* Current value of the `slice', `space-width', and 'height' properties. */
- it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
- it->space_width = Qnil;
- it->font_height = Qnil;
it->override_ascent = -1;
/* Are control characters displayed as `^C'? */
@@ -2932,21 +2822,19 @@ init_iterator (struct it *it, struct window *w,
it->tab_width = SANE_TAB_WIDTH (current_buffer);
/* Are lines in the display truncated? */
- if (base_face_id != DEFAULT_FACE_ID
- || it->w->hscroll
- || (! WINDOW_FULL_WIDTH_P (it->w)
- && ((!NILP (Vtruncate_partial_width_windows)
- && !INTEGERP (Vtruncate_partial_width_windows))
- || (INTEGERP (Vtruncate_partial_width_windows)
- /* PXW: Shall we do something about this? */
- && (WINDOW_TOTAL_COLS (it->w)
- < XINT (Vtruncate_partial_width_windows))))))
+ if (TRUNCATE != 0)
it->line_wrap = TRUNCATE;
- else if (NILP (BVAR (current_buffer, truncate_lines)))
+ if (base_face_id == DEFAULT_FACE_ID
+ && !it->w->hscroll
+ && (WINDOW_FULL_WIDTH_P (it->w)
+ || NILP (Vtruncate_partial_width_windows)
+ || (INTEGERP (Vtruncate_partial_width_windows)
+ /* PXW: Shall we do something about this? */
+ && (XINT (Vtruncate_partial_width_windows)
+ <= WINDOW_TOTAL_COLS (it->w))))
+ && NILP (BVAR (current_buffer, truncate_lines)))
it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
? WINDOW_WRAP : WORD_WRAP;
- else
- it->line_wrap = TRUNCATE;
/* Get dimensions of truncation and continuation glyphs. These are
displayed as fringe bitmaps under X, but we need them for such
@@ -2986,10 +2874,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
@@ -3622,7 +3506,8 @@ compute_stop_pos (struct it *it)
/* Get properties here. */
for (p = it_props; p->handler; ++p)
- values_here[p->idx] = textget (iv->plist, *p->name);
+ values_here[p->idx] = textget (iv->plist,
+ builtin_lisp_symbol (p->name));
/* Look for an interval following iv that has different
properties. */
@@ -3634,9 +3519,8 @@ compute_stop_pos (struct it *it)
{
for (p = it_props; p->handler; ++p)
{
- Lisp_Object new_value;
-
- new_value = textget (next_iv->plist, *p->name);
+ Lisp_Object new_value = textget (next_iv->plist,
+ builtin_lisp_symbol (p->name));
if (!EQ (values_here[p->idx], new_value))
break;
}
@@ -3684,6 +3568,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);
@@ -3700,6 +3585,7 @@ next_overlay_change (ptrdiff_t pos)
endpos = min (endpos, oendpos);
}
+ SAFE_FREE ();
return endpos;
}
@@ -3991,7 +3877,7 @@ handle_face_prop (struct it *it)
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
- 0, it->base_face_id);
+ false, it->base_face_id);
/* Is this a start of a run of characters with box face?
Caveat: this can be called for a freshly initialized
@@ -4067,7 +3953,7 @@ handle_face_prop (struct it *it)
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
- 0,
+ false,
from_overlay);
}
else
@@ -4102,7 +3988,7 @@ handle_face_prop (struct it *it)
IT_STRING_CHARPOS (*it),
bufpos,
&next_stop,
- base_face_id, 0);
+ base_face_id, false);
/* Is this a start of a run of characters with box? Caveat:
this can be called for a freshly allocated iterator; face_id
@@ -4244,7 +4130,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
charpos,
bufpos,
&next_check_charpos,
- base_face_id, 0);
+ base_face_id, false);
/* Correct the face for charsets different from ASCII. Do it
for the multibyte case only. The face returned above is
@@ -4333,7 +4219,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
face_id = face_at_buffer_position (it->w,
CHARPOS (pos),
&next_check_charpos,
- limit, 0, -1);
+ limit, false, -1);
/* Correct the face for charsets different from ASCII. Do it
for the multibyte case only. The face returned above is
@@ -5153,7 +5039,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))))
{
@@ -5768,10 +5654,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)
@@ -6954,7 +6841,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
@@ -7277,7 +7165,7 @@ get_next_display_element (struct it *it)
{
next_face_id = face_at_buffer_position
(it->w, CHARPOS (pos), &ignore,
- CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, 0, -1);
+ CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, false, -1);
it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX);
@@ -8036,7 +7924,7 @@ next_element_from_c_string (struct it *it)
eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
it->what = IT_CHARACTER;
BYTEPOS (it->position) = CHARPOS (it->position) = 0;
- it->object = Qnil;
+ it->object = make_number (0);
/* With bidi reordering, the character to display might not be the
character at IT_CHARPOS. BIDI_IT.FIRST_ELT non-zero means that
@@ -8348,7 +8236,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;
@@ -8398,22 +8286,18 @@ next_element_from_buffer (struct it *it)
static void
run_redisplay_end_trigger_hook (struct it *it)
{
- Lisp_Object args[3];
-
/* IT->glyph_row should be non-null, i.e. we should be actually
displaying something, or otherwise we should not run the hook. */
eassert (it->glyph_row);
- /* Set up hook arguments. */
- args[0] = Qredisplay_end_trigger_functions;
- args[1] = it->window;
- XSETINT (args[2], it->redisplay_end_trigger_charpos);
+ ptrdiff_t charpos = it->redisplay_end_trigger_charpos;
it->redisplay_end_trigger_charpos = 0;
/* Since we are *trying* to run these functions, don't try to run
them again, even if they get an error. */
wset_redisplay_end_trigger (it->w, Qnil);
- Frun_hook_with_args (3, args);
+ CALLN (Frun_hook_with_args, Qredisplay_end_trigger_functions, it->window,
+ make_number (charpos));
/* Notice if it changed the face of the character we are on. */
handle_face_prop (it);
@@ -9912,7 +9796,6 @@ include the height of both, if present, in the return value. */)
void
add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
{
- Lisp_Object args[3];
Lisp_Object msg, fmt;
char *buffer;
ptrdiff_t len;
@@ -9922,10 +9805,8 @@ add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
fmt = msg = Qnil;
GCPRO4 (fmt, msg, arg1, arg2);
- args[0] = fmt = build_string (format);
- args[1] = arg1;
- args[2] = arg2;
- msg = Fformat (3, args);
+ fmt = build_string (format);
+ msg = CALLN (Fformat, fmt, arg1, arg2);
len = SBYTES (msg) + 1;
buffer = SAFE_ALLOCA (len);
@@ -10027,9 +9908,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 +10083,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 ();
}
@@ -10267,9 +10146,9 @@ message3_nolog (Lisp_Object m)
else
clear_message (true, true);
- do_pending_window_change (0);
- echo_area_display (1);
- do_pending_window_change (0);
+ do_pending_window_change (false);
+ echo_area_display (true);
+ do_pending_window_change (false);
if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
@@ -10311,19 +10190,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)
@@ -10344,15 +10221,13 @@ message_with_string (const char *m, Lisp_Object string, int log)
initialized yet, just toss it. */
if (f->glyphs_initialized_p)
{
- Lisp_Object args[2], msg;
struct gcpro gcpro1, gcpro2;
- args[0] = build_string (m);
- args[1] = msg = string;
- GCPRO2 (args[0], msg);
- gcpro1.nvars = 2;
+ Lisp_Object fmt = build_string (m);
+ Lisp_Object msg = string;
+ GCPRO2 (fmt, msg);
- msg = Fformat (2, args);
+ msg = CALLN (Fformat, fmt, msg);
if (log)
message3 (msg);
@@ -10410,11 +10285,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 +10457,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 +10496,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 +10508,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 +10547,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;
@@ -11234,13 +11117,13 @@ clear_garbaged_frames (void)
is non-zero update selected_frame. Value is non-zero if the
mini-windows height has been changed. */
-static int
-echo_area_display (int update_frame_p)
+static bool
+echo_area_display (bool update_frame_p)
{
Lisp_Object mini_window;
struct window *w;
struct frame *f;
- int window_height_changed_p = 0;
+ bool window_height_changed_p = false;
struct frame *sf = SELECTED_FRAME ();
mini_window = FRAME_MINIBUF_WINDOW (sf);
@@ -11303,11 +11186,11 @@ echo_area_display (int update_frame_p)
/* Window configuration is the same as before.
Can do with a display update of the echo area,
unless we displayed some mode lines. */
- update_single_window (w, 1);
+ update_single_window (w);
flush_frame (f);
}
else
- update_frame (f, 1, 1);
+ update_frame (f, true, true);
/* If cursor is in the echo area, make sure that the next
redisplay displays the minibuffer, so that the cursor will
@@ -11912,11 +11795,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
@@ -11943,7 +11821,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)
@@ -12039,11 +11917,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. */
@@ -12062,9 +11940,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,
@@ -12175,8 +12056,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
@@ -12187,6 +12070,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
}
@@ -12327,16 +12211,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)
{
@@ -12350,6 +12227,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);
@@ -12375,11 +12253,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.
@@ -12410,7 +12283,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)
{
@@ -12432,7 +12304,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. */
@@ -12440,6 +12312,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);
@@ -12459,14 +12332,8 @@ 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);
+ frame_default_tool_bar_height = new_height;
/* Always do that now. */
clear_glyph_matrix (w->desired_matrix);
f->fonts_changed = 1;
@@ -12519,14 +12386,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
@@ -12545,15 +12409,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);
@@ -12565,35 +12427,13 @@ 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);
+ frame_default_tool_bar_height = new_height;
+ clear_glyph_matrix (w->desired_matrix);
+ f->n_tool_bar_rows = nrows;
+ f->fonts_changed = 1;
+
+ return 1;
}
}
}
@@ -12718,7 +12558,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);
@@ -12730,7 +12570,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
{
@@ -12755,7 +12595,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;
}
}
@@ -12805,8 +12645,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;
@@ -12928,7 +12767,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
@@ -12941,8 +12793,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))))
@@ -13455,7 +13306,7 @@ redisplay_internal (void)
struct window *w = XWINDOW (selected_window);
struct window *sw;
struct frame *fr;
- int pending;
+ bool pending;
bool must_finish = 0, match_p;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
@@ -13506,7 +13357,7 @@ redisplay_internal (void)
specbind (Qinhibit_free_realized_faces, Qnil);
/* Record this function, so it appears on the profiler's backtraces. */
- record_in_backtrace (Qredisplay_internal, &Qnil, 0);
+ record_in_backtrace (Qredisplay_internal, 0, 0);
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->already_hscrolled_p = 0;
@@ -13515,7 +13366,7 @@ redisplay_internal (void)
/* Remember the currently selected window. */
sw = w;
- pending = 0;
+ pending = false;
last_escape_glyph_frame = NULL;
last_escape_glyph_face_id = (1 << FACE_ID_BITS);
last_glyphless_glyph_frame = NULL;
@@ -13567,7 +13418,7 @@ redisplay_internal (void)
}
/* Notice any pending interrupt request to change frame size. */
- do_pending_window_change (1);
+ do_pending_window_change (true);
/* do_pending_window_change could change the selected_window due to
frame resizing which makes the selected window too small. */
@@ -13614,7 +13465,7 @@ redisplay_internal (void)
echo-area doesn't show through. */
&& !MINI_WINDOW_P (XWINDOW (selected_window))))
{
- int window_height_changed_p = echo_area_display (0);
+ int window_height_changed_p = echo_area_display (false);
if (message_cleared_p)
update_miniwindow_p = true;
@@ -13822,7 +13673,7 @@ redisplay_internal (void)
{
if (!must_finish)
{
- do_pending_window_change (1);
+ do_pending_window_change (true);
/* If selected_window changed, redisplay again. */
if (WINDOWP (selected_window)
&& (w = XWINDOW (selected_window)) != sw)
@@ -13907,6 +13758,17 @@ redisplay_internal (void)
retry_frame:
+#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_GTK) && !defined (HAVE_NS)
+ /* Redisplay internal tool bar if this is the first time so we
+ can adjust the frame height right now, if necessary. */
+ if (!f->tool_bar_redisplayed_once)
+ {
+ if (redisplay_tool_bar (f))
+ adjust_frame_glyphs (f);
+ f->tool_bar_redisplayed_once = true;
+ }
+#endif
+
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
bool gcscrollbars
@@ -13939,14 +13801,14 @@ redisplay_internal (void)
if (f->fonts_changed)
{
adjust_frame_glyphs (f);
- f->fonts_changed = 0;
+ f->fonts_changed = false;
goto retry_frame;
}
/* See if we have to hscroll. */
if (!f->already_hscrolled_p)
{
- f->already_hscrolled_p = 1;
+ f->already_hscrolled_p = true;
if (hscroll_windows (f->root_window))
goto retry_frame;
}
@@ -13958,9 +13820,9 @@ redisplay_internal (void)
unrequest_sigio ();
STOP_POLLING;
- pending |= update_frame (f, 0, 0);
- f->cursor_type_changed = 0;
- f->updated_p = 1;
+ pending |= update_frame (f, false, false);
+ f->cursor_type_changed = false;
+ f->updated_p = true;
}
}
}
@@ -14021,8 +13883,8 @@ redisplay_internal (void)
goto retry;
XWINDOW (selected_window)->must_be_updated_p = true;
- pending = update_frame (sf, 0, 0);
- sf->cursor_type_changed = 0;
+ pending = update_frame (sf, false, false);
+ sf->cursor_type_changed = false;
}
/* We may have called echo_area_display at the top of this
@@ -14036,8 +13898,8 @@ redisplay_internal (void)
if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
{
XWINDOW (mini_window)->must_be_updated_p = true;
- pending |= update_frame (mini_frame, 0, 0);
- mini_frame->cursor_type_changed = 0;
+ pending |= update_frame (mini_frame, false, false);
+ mini_frame->cursor_type_changed = false;
if (!pending && hscroll_windows (mini_window))
goto retry;
}
@@ -14114,7 +13976,7 @@ redisplay_internal (void)
}
/* Change frame size now if a change is pending. */
- do_pending_window_change (1);
+ do_pending_window_change (true);
/* If we just did a pending size change, or have additional
visible frames, or selected_window changed, redisplay again. */
@@ -14130,7 +13992,7 @@ redisplay_internal (void)
if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
{
- clear_face_cache (0);
+ clear_face_cache (false);
clear_face_cache_count = 0;
}
@@ -14174,9 +14036,9 @@ redisplay_preserve_echo_area (int from_where)
{
/* We have a previously displayed message, but no current
message. Redisplay the previous message. */
- display_last_displayed_message_p = 1;
+ display_last_displayed_message_p = true;
redisplay_internal ();
- display_last_displayed_message_p = 0;
+ display_last_displayed_message_p = false;
}
else
redisplay_internal ();
@@ -14413,14 +14275,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
if (!row->reversed_p)
{
while (glyph < end
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0)
{
x += glyph->pixel_width;
++glyph;
}
while (end > glyph
- && INTEGERP ((end - 1)->object)
+ && NILP ((end - 1)->object)
/* CHARPOS is zero for blanks and stretch glyphs
inserted by extend_face_to_end_of_line. */
&& (end - 1)->charpos <= 0)
@@ -14438,20 +14300,20 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
glyph += row->used[TEXT_AREA] - 1;
while (glyph > end + 1
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0)
{
--glyph;
x -= glyph->pixel_width;
}
- if (INTEGERP (glyph->object) && glyph->charpos < 0)
+ if (NILP (glyph->object) && glyph->charpos < 0)
--glyph;
/* By default, in reversed rows we put the cursor on the
rightmost (first in the reading order) glyph. */
for (g = end + 1; g < glyph; g++)
x += g->pixel_width;
while (end < glyph
- && INTEGERP ((end + 1)->object)
+ && NILP ((end + 1)->object)
&& (end + 1)->charpos <= 0)
++end;
glyph_before = glyph + 1;
@@ -14482,7 +14344,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
while (/* not marched to end of glyph row */
glyph < end
/* glyph was not inserted by redisplay for internal purposes */
- && !INTEGERP (glyph->object))
+ && !NILP (glyph->object))
{
if (BUFFERP (glyph->object))
{
@@ -14570,7 +14432,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
++glyph;
}
else if (glyph > end) /* row is reversed */
- while (!INTEGERP (glyph->object))
+ while (!NILP (glyph->object))
{
if (BUFFERP (glyph->object))
{
@@ -14647,16 +14509,16 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
&& BUFFERP (glyph->object) && glyph->charpos == pt_old)
&& !(bpos_max <= pt_old && pt_old <= bpos_covered))
{
- /* An empty line has a single glyph whose OBJECT is zero and
+ /* An empty line has a single glyph whose OBJECT is nil and
whose CHARPOS is the position of a newline on that line.
Note that on a TTY, there are more glyphs after that, which
were produced by extend_face_to_end_of_line, but their
CHARPOS is zero or negative. */
int empty_line_p =
(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
- && INTEGERP (glyph->object) && glyph->charpos > 0
+ && NILP (glyph->object) && glyph->charpos > 0
/* On a TTY, continued and truncated rows also have a glyph at
- their end whose OBJECT is zero and whose CHARPOS is
+ their end whose OBJECT is nil and whose CHARPOS is
positive (the continuation and truncation glyphs), but such
rows are obviously not "empty". */
&& !(row->continued_p || row->truncated_on_right_p);
@@ -14933,7 +14795,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
&& string_from_text_prop)
/* this candidate is from newline and its
position is not an exact match */
- || (INTEGERP (glyph->object)
+ || (NILP (glyph->object)
&& glyph->charpos != pt_old)))))
return 0;
/* If this candidate gives an exact match, use that. */
@@ -14942,7 +14804,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
terminating newline of a line, and point is on that
newline, it wins because it's an exact match. */
|| (!row->continued_p
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos == 0
&& pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
/* Otherwise, keep the candidate that comes from a row
@@ -15224,8 +15086,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
non-zero margins, because scroll_up_aggressively
means put point that fraction of window height
_from_the_bottom_margin_. */
- if (aggressive_scroll + 2*this_scroll_margin > height)
- aggressive_scroll = height - 2*this_scroll_margin;
+ if (aggressive_scroll + 2 * this_scroll_margin > height)
+ aggressive_scroll = height - 2 * this_scroll_margin;
amount_to_scroll = dy + aggressive_scroll;
}
}
@@ -15318,8 +15180,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
start_display (&it, w, startp);
if (arg_scroll_conservatively)
- amount_to_scroll = max (dy, frame_line_height *
- max (scroll_step, temp_scroll_step));
+ amount_to_scroll = max (dy, frame_line_height
+ * max (scroll_step, temp_scroll_step));
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
else
@@ -15336,8 +15198,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
bottom of the window, if the value of
scroll_down_aggressively happens to be too
large. */
- if (aggressive_scroll + 2*this_scroll_margin > height)
- aggressive_scroll = height - 2*this_scroll_margin;
+ if (aggressive_scroll + 2 * this_scroll_margin > height)
+ aggressive_scroll = height - 2 * this_scroll_margin;
amount_to_scroll = dy + aggressive_scroll;
}
}
@@ -15785,7 +15647,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
exact_match_p =
(BUFFERP (g->object) && g->charpos == PT)
- || (INTEGERP (g->object)
+ || (NILP (g->object)
&& (g->charpos == PT
|| (g->charpos == 0 && endpos - 1 == PT)));
}
@@ -15836,9 +15698,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)
{
@@ -15877,6 +15737,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.
@@ -16090,6 +16015,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;
@@ -16544,8 +16470,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
{
int window_total_lines
= WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
- int margin =
- scroll_margin > 0
+ int margin
+ = scroll_margin > 0
? min (scroll_margin, window_total_lines / 4)
: 0;
ptrdiff_t margin_pos = CHARPOS (startp);
@@ -16871,7 +16797,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;
@@ -16911,10 +16837,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. */
@@ -16970,6 +16901,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)
@@ -17153,6 +17085,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;
@@ -18173,6 +18106,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
@@ -18563,7 +18501,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
@@ -18586,7 +18524,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
@@ -18607,7 +18545,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
@@ -18628,7 +18566,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
@@ -18717,10 +18655,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)
@@ -18728,7 +18666,7 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
struct glyph *glyph = row->glyphs[area] + i;
if (i == row->used[area] - 1
&& area == TEXT_AREA
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->type == CHAR_GLYPH
&& glyph->u.ch == ' ')
{
@@ -18859,7 +18797,7 @@ usage: (trace-to-stderr STRING &rest OBJECTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object s = Fformat (nargs, args);
- fprintf (stderr, "%s", SDATA (s));
+ fwrite (SDATA (s), 1, SBYTES (s), stderr);
return Qnil;
}
@@ -18881,7 +18819,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;
@@ -18890,6 +18828,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);
@@ -18957,7 +18896,7 @@ insert_left_trunc_glyphs (struct it *it)
truncate_it.area = TEXT_AREA;
truncate_it.glyph_row->used[TEXT_AREA] = 0;
CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
- truncate_it.object = make_number (0);
+ truncate_it.object = Qnil;
produce_special_glyphs (&truncate_it, IT_TRUNCATION);
/* Overwrite glyphs from IT with truncation glyphs. */
@@ -19240,7 +19179,7 @@ append_space_for_newline (struct it *it, int default_face_p)
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
- it->object = make_number (0);
+ it->object = Qnil;
it->c = it->char_to_display = ' ';
it->len = 1;
@@ -19432,7 +19371,7 @@ extend_face_to_end_of_line (struct it *it)
else
it->face_id = face->id;
it->start_of_box_run_p = 0;
- append_stretch_glyph (it, make_number (0), stretch_width,
+ append_stretch_glyph (it, Qnil, stretch_width,
it->ascent + it->descent, stretch_ascent);
it->position = saved_pos;
it->avoid_cursor_p = saved_avoid_cursor;
@@ -19462,7 +19401,7 @@ extend_face_to_end_of_line (struct it *it)
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
- it->object = make_number (0);
+ it->object = Qnil;
it->c = it->char_to_display = ' ';
it->len = 1;
@@ -19591,14 +19530,14 @@ highlight_trailing_whitespace (struct frame *f, struct glyph_row *row)
{
while (glyph >= start
&& glyph->type == CHAR_GLYPH
- && INTEGERP (glyph->object))
+ && NILP (glyph->object))
--glyph;
}
else
{
while (glyph <= start
&& glyph->type == CHAR_GLYPH
- && INTEGERP (glyph->object))
+ && NILP (glyph->object))
++glyph;
}
@@ -19612,7 +19551,7 @@ highlight_trailing_whitespace (struct frame *f, struct glyph_row *row)
&& glyph->u.ch == ' '))
&& trailing_whitespace_p (glyph->charpos))
{
- int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
+ int face_id = lookup_named_face (f, Qtrailing_whitespace, false);
if (face_id < 0)
return;
@@ -19961,10 +19900,9 @@ find_row_edges (struct it *it, struct glyph_row *row,
{
start = r1->glyphs[TEXT_AREA];
end = start + r1->used[TEXT_AREA];
- /* Glyphs inserted by redisplay have an integer (zero)
- as their object. */
+ /* Glyphs inserted by redisplay have nil as their object. */
while (end > start
- && INTEGERP ((end - 1)->object)
+ && NILP ((end - 1)->object)
&& (end - 1)->charpos <= 0)
--end;
if (end > start)
@@ -19985,7 +19923,7 @@ find_row_edges (struct it *it, struct glyph_row *row,
end = r1->glyphs[TEXT_AREA] - 1;
start = end + r1->used[TEXT_AREA];
while (end < start
- && INTEGERP ((end + 1)->object)
+ && NILP ((end + 1)->object)
&& (end + 1)->charpos <= 0)
++end;
if (end < start)
@@ -20941,7 +20879,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'
@@ -20983,6 +20922,143 @@ See also `bidi-paragraph-direction'. */)
}
}
+DEFUN ("bidi-find-overridden-directionality",
+ Fbidi_find_overridden_directionality,
+ Sbidi_find_overridden_directionality, 2, 3, 0,
+ doc: /* Return position between FROM and TO where directionality was overridden.
+
+This function returns the first character position in the specified
+region of OBJECT where there is a character whose `bidi-class' property
+is `L', but which was forced to display as `R' by a directional
+override, and likewise with characters whose `bidi-class' is `R'
+or `AL' that were forced to display as `L'.
+
+If no such character is found, the function returns nil.
+
+OBJECT is a Lisp string or buffer to search for overridden
+directionality, and defaults to the current buffer if nil or omitted.
+OBJECT can also be a window, in which case the function will search
+the buffer displayed in that window. Passing the window instead of
+a buffer is preferable when the buffer is displayed in some window,
+because this function will then be able to correctly account for
+window-specific overlays, which can affect the results.
+
+Strong directional characters `L', `R', and `AL' can have their
+intrinsic directionality overridden by directional override
+control characters RLO \(u+202e) and LRO \(u+202d). See the
+function `get-char-code-property' for a way to inquire about
+the `bidi-class' property of a character. */)
+ (Lisp_Object from, Lisp_Object to, Lisp_Object object)
+{
+ struct buffer *buf = current_buffer;
+ struct buffer *old = buf;
+ struct window *w = NULL;
+ bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
+ struct bidi_it itb;
+ ptrdiff_t from_pos, to_pos, from_bpos;
+ void *itb_data;
+
+ if (!NILP (object))
+ {
+ if (BUFFERP (object))
+ buf = XBUFFER (object);
+ else if (WINDOWP (object))
+ {
+ w = decode_live_window (object);
+ buf = XBUFFER (w->contents);
+ frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
+ }
+ else
+ CHECK_STRING (object);
+ }
+
+ if (STRINGP (object))
+ {
+ /* Characters in unibyte strings are always treated by bidi.c as
+ strong LTR. */
+ if (!STRING_MULTIBYTE (object)
+ /* When we are loading loadup.el, the character property
+ tables needed for bidi iteration are not yet
+ available. */
+ || !NILP (Vpurify_flag))
+ return Qnil;
+
+ validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
+ if (from_pos >= SCHARS (object))
+ return Qnil;
+
+ /* Set up the bidi iterator. */
+ itb_data = bidi_shelve_cache ();
+ itb.paragraph_dir = NEUTRAL_DIR;
+ itb.string.lstring = object;
+ itb.string.s = NULL;
+ itb.string.schars = SCHARS (object);
+ itb.string.bufpos = 0;
+ itb.string.from_disp_str = 0;
+ itb.string.unibyte = 0;
+ itb.w = w;
+ bidi_init_it (0, 0, frame_window_p, &itb);
+ }
+ else
+ {
+ /* Nothing this fancy can happen in unibyte buffers, or in a
+ buffer that disabled reordering, or if FROM is at EOB. */
+ if (NILP (BVAR (buf, bidi_display_reordering))
+ || NILP (BVAR (buf, enable_multibyte_characters))
+ /* When we are loading loadup.el, the character property
+ tables needed for bidi iteration are not yet
+ available. */
+ || !NILP (Vpurify_flag))
+ return Qnil;
+
+ set_buffer_temp (buf);
+ validate_region (&from, &to);
+ from_pos = XINT (from);
+ to_pos = XINT (to);
+ if (from_pos >= ZV)
+ return Qnil;
+
+ /* Set up the bidi iterator. */
+ itb_data = bidi_shelve_cache ();
+ from_bpos = CHAR_TO_BYTE (from_pos);
+ if (from_pos == BEGV)
+ {
+ itb.charpos = BEGV;
+ itb.bytepos = BEGV_BYTE;
+ }
+ else if (FETCH_CHAR (from_bpos - 1) == '\n')
+ {
+ itb.charpos = from_pos;
+ itb.bytepos = from_bpos;
+ }
+ else
+ itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
+ -1, &itb.bytepos);
+ itb.paragraph_dir = NEUTRAL_DIR;
+ itb.string.s = NULL;
+ itb.string.lstring = Qnil;
+ itb.string.bufpos = 0;
+ itb.string.from_disp_str = 0;
+ itb.string.unibyte = 0;
+ itb.w = w;
+ bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
+ }
+
+ ptrdiff_t found;
+ do {
+ /* For the purposes of this function, the actual base direction of
+ the paragraph doesn't matter, so just set it to L2R. */
+ bidi_paragraph_init (L2R, &itb, 0);
+ while ((found = bidi_find_first_overridden (&itb)) < from_pos)
+ ;
+ } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
+
+ bidi_unshelve_cache (itb_data, 0);
+ set_buffer_temp (old);
+
+ return (from_pos <= found && found < to_pos) ? make_number (found) : Qnil;
+}
+
DEFUN ("move-point-visually", Fmove_point_visually,
Smove_point_visually, 1, 1, 0,
doc: /* Move point in the visual order in the specified DIRECTION.
@@ -21000,7 +21076,7 @@ Value is the new character position of point. */)
#define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
(!(ROW)->continued_p \
- && INTEGERP ((GLYPH)->object) \
+ && NILP ((GLYPH)->object) \
&& (GLYPH)->type == CHAR_GLYPH \
&& (GLYPH)->u.ch == ' ' \
&& (GLYPH)->charpos >= 0 \
@@ -21042,7 +21118,7 @@ Value is the new character position of point. */)
w->cursor.vpos = -1;
return make_number (PT);
}
- else if (!INTEGERP (g->object) && !EQ (g->object, gpt->object))
+ else if (!NILP (g->object) && !EQ (g->object, gpt->object))
{
ptrdiff_t new_pos;
@@ -21052,7 +21128,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;
@@ -21079,7 +21155,7 @@ Value is the new character position of point. */)
return make_number (PT);
}
}
- if (g == e || INTEGERP (g->object))
+ if (g == e || NILP (g->object))
{
if (row->truncated_on_left_p || row->truncated_on_right_p)
goto simulate_display;
@@ -21112,7 +21188,7 @@ Value is the new character position of point. */)
EOB also has one glyph, but its charpos is -1. */
|| (row->ends_at_zv_p
&& !row->reversed_p
- && INTEGERP (g->object)
+ && NILP (g->object)
&& g->type == CHAR_GLYPH
&& g->u.ch == ' '))
{
@@ -21150,7 +21226,7 @@ Value is the new character position of point. */)
|| g->type == STRETCH_GLYPH
|| (row->ends_at_zv_p
&& row->reversed_p
- && INTEGERP (g->object)
+ && NILP (g->object)
&& g->type == CHAR_GLYPH
&& g->u.ch == ' '))
{
@@ -21442,6 +21518,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
+ && NILP (g->object)
+ && g->charpos < 0)
+ g++;
+ g1 = g;
+
+ /* Count the "interesting" glyphs in this row. */
+ for (nglyphs = 0; g < e && !NILP (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
+ && NILP (g->object)
+ && g->charpos < 0)
+ g--;
+ g1 = g;
+ for (nglyphs = 0; g > e && !NILP (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
@@ -21520,6 +21704,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. */
@@ -22753,10 +22938,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
{
@@ -22892,7 +23075,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 "";
@@ -23033,7 +23216,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++ = ' ';
@@ -23378,7 +23561,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
it->face_id
= face_at_string_position (it->w, face_string, face_string_pos,
- 0, &endptr, it->base_face_id, 0);
+ 0, &endptr, it->base_face_id, false);
face = FACE_FROM_ID (it->f, it->face_id);
it->face_box_p = face->box != FACE_NO_BOX;
}
@@ -23785,7 +23968,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;
}
@@ -23837,7 +24020,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;
}
@@ -24014,7 +24197,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;
@@ -24037,7 +24220,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;
@@ -24354,7 +24537,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];
}
@@ -24672,7 +24855,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); \
@@ -24700,7 +24883,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. */ \
@@ -24735,7 +24918,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); \
@@ -24887,6 +25070,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;
@@ -25086,6 +25270,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
RELEASE_HDC (hdc, f);
+ SAFE_FREE ();
return x_reached;
}
@@ -25171,8 +25356,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
@@ -25255,8 +25439,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];
@@ -25303,7 +25486,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)
{
@@ -25444,8 +25627,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];
@@ -25533,8 +25715,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
@@ -25599,7 +25780,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
@@ -25757,7 +25938,7 @@ produce_special_glyphs (struct it *it, enum display_element_type what)
GLYPH glyph;
temp_it = *it;
- temp_it.object = make_number (0);
+ temp_it.object = Qnil;
memset (&temp_it.current, 0, sizeof temp_it.current);
if (what == IT_CONTINUATION)
@@ -25820,7 +26001,7 @@ produce_special_glyphs (struct it *it, enum display_element_type what)
(((temp_it.ascent + temp_it.descent)
* FONT_BASE (font)) / FONT_HEIGHT (font));
- append_stretch_glyph (&temp_it, make_number (0), stretch_width,
+ append_stretch_glyph (&temp_it, Qnil, stretch_width,
temp_it.ascent + temp_it.descent,
stretch_ascent);
}
@@ -25886,7 +26067,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
int face_id;
struct face *face;
- face_id = lookup_named_face (it->f, face_name, 0);
+ face_id = lookup_named_face (it->f, face_name, false);
if (face_id < 0)
return make_number (-1);
@@ -25993,8 +26174,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];
@@ -26062,7 +26242,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)
{
@@ -26078,7 +26258,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,
@@ -27403,9 +27583,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)
{
@@ -27828,7 +28005,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
#ifdef HAVE_WINDOW_SYSTEM
/* Change the mouse cursor. */
- if (FRAME_WINDOW_P (f))
+ if (FRAME_WINDOW_P (f) && NILP (do_mouse_tracking))
{
#if ! defined (USE_GTK) && ! defined (HAVE_NS)
if (draw == DRAW_NORMAL_TEXT
@@ -27999,7 +28176,7 @@ rows_from_pos_range (struct window *w,
while (g < e)
{
- if (((BUFFERP (g->object) || INTEGERP (g->object))
+ if (((BUFFERP (g->object) || NILP (g->object))
&& start_charpos <= g->charpos && g->charpos < end_charpos)
/* A glyph that comes from DISP_STRING is by
definition to be highlighted. */
@@ -28054,7 +28231,7 @@ rows_from_pos_range (struct window *w,
while (g < e)
{
- if (((BUFFERP (g->object) || INTEGERP (g->object))
+ if (((BUFFERP (g->object) || NILP (g->object))
&& ((start_charpos <= g->charpos && g->charpos < end_charpos)
/* If the buffer position of the first glyph in
the row is equal to END_CHARPOS, it means
@@ -28136,7 +28313,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
{
struct glyph *beg = prev->glyphs[TEXT_AREA];
glyph = beg + prev->used[TEXT_AREA];
- while (--glyph >= beg && INTEGERP (glyph->object));
+ while (--glyph >= beg && NILP (glyph->object));
if (glyph < beg
|| !(EQ (glyph->object, before_string)
|| EQ (glyph->object, disp_string)))
@@ -28200,7 +28377,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
/* Skip truncation glyphs at the start of the glyph row. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
for (; glyph < end
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0;
++glyph)
x += glyph->pixel_width;
@@ -28209,7 +28386,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
or DISP_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph < end
- && !INTEGERP (glyph->object)
+ && !NILP (glyph->object)
&& !EQ (glyph->object, disp_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
@@ -28251,7 +28428,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
/* Skip truncation glyphs at the start of the glyph row. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
for (; glyph > end
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0;
--glyph)
;
@@ -28260,7 +28437,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
or DISP_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph > end
- && !INTEGERP (glyph->object)
+ && !NILP (glyph->object)
&& !EQ (glyph->object, disp_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
@@ -28317,7 +28494,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
row, and also blanks and stretch glyphs inserted by
extend_face_to_end_of_line. */
while (end > glyph
- && INTEGERP ((end - 1)->object))
+ && NILP ((end - 1)->object))
--end;
/* Scan the rest of the glyph row from the end, looking for the
first glyph that comes from BEFORE_STRING, AFTER_STRING, or
@@ -28325,7 +28502,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
and END_CHARPOS */
for (--end;
end > glyph
- && !INTEGERP (end->object)
+ && !NILP (end->object)
&& !EQ (end->object, disp_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
@@ -28363,7 +28540,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
x = r2->x;
end++;
while (end < glyph
- && INTEGERP (end->object))
+ && NILP (end->object))
{
x += end->pixel_width;
++end;
@@ -28374,7 +28551,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
and END_CHARPOS */
for ( ;
end < glyph
- && !INTEGERP (end->object)
+ && !NILP (end->object)
&& !EQ (end->object, disp_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
@@ -28937,8 +29114,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))
{
@@ -29106,7 +29283,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
charpos,
0, &ignore,
glyph->face_id,
- 1);
+ true);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
if (NILP (pointer))
@@ -29232,7 +29409,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;
@@ -29305,12 +29483,12 @@ note_mouse_highlight (struct frame *f, int x, int y)
if (glyph == NULL
|| area != TEXT_AREA
|| !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
- /* Glyph's OBJECT is an integer for glyphs inserted by the
+ /* Glyph's OBJECT is nil for glyphs inserted by the
display engine for its internal purposes, like truncation
and continuation glyphs and blanks beyond the end of
line's text on text terminals. If we are over such a
glyph, we are not over any text. */
- || INTEGERP (glyph->object)
+ || NILP (glyph->object)
/* R2L rows have a stretch glyph at their front, which
stands for no text, whereas L2R rows have no glyphs at
all beyond the end of text. Treat such stretch glyphs
@@ -29355,6 +29533,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. */
@@ -29431,7 +29611,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id
= face_at_string_position (w, object, pos, 0, &ignore,
- glyph->face_id, 1);
+ glyph->face_id, true);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
cursor = No_Cursor;
}
@@ -29636,6 +29816,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
BEGV = obegv;
ZV = ozv;
current_buffer = obuf;
+ SAFE_FREE ();
}
set_cursor:
@@ -30153,8 +30334,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
{
@@ -30279,7 +30460,9 @@ syms_of_xdisp (void)
Vmessage_stack = Qnil;
staticpro (&Vmessage_stack);
+ /* Non-nil means don't actually do any redisplay. */
DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
+
DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
message_dolog_marker1 = Fmake_marker ();
@@ -30307,6 +30490,7 @@ syms_of_xdisp (void)
defsubr (&Scurrent_bidi_paragraph_direction);
defsubr (&Swindow_text_pixel_size);
defsubr (&Smove_point_visually);
+ defsubr (&Sbidi_find_overridden_directionality);
DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
@@ -30317,6 +30501,8 @@ syms_of_xdisp (void)
DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
DEFSYM (Qeval, "eval");
DEFSYM (QCdata, ":data");
+
+ /* Names of text properties relevant for redisplay. */
DEFSYM (Qdisplay, "display");
DEFSYM (Qspace_width, "space-width");
DEFSYM (Qraise, "raise");
@@ -30336,40 +30522,69 @@ syms_of_xdisp (void)
DEFSYM (QCfile, ":file");
DEFSYM (Qfontified, "fontified");
DEFSYM (Qfontification_functions, "fontification-functions");
+
+ /* Name of the face used to highlight trailing whitespace. */
DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
+
+ /* Name and number of the face used to highlight escape glyphs. */
DEFSYM (Qescape_glyph, "escape-glyph");
+
+ /* Name and number of the face used to highlight non-breaking spaces. */
DEFSYM (Qnobreak_space, "nobreak-space");
+
+ /* The symbol 'image' which is the car of the lists used to represent
+ images in Lisp. Also a tool bar style. */
DEFSYM (Qimage, "image");
+
+ /* Tool bar styles. */
DEFSYM (Qtext, "text");
DEFSYM (Qboth, "both");
DEFSYM (Qboth_horiz, "both-horiz");
DEFSYM (Qtext_image_horiz, "text-image-horiz");
+
+ /* The image map types. */
DEFSYM (QCmap, ":map");
DEFSYM (QCpointer, ":pointer");
DEFSYM (Qrect, "rect");
DEFSYM (Qcircle, "circle");
DEFSYM (Qpoly, "poly");
+
+ /* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
+ DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
DEFSYM (Qmessage_truncate_lines, "message-truncate-lines");
+
DEFSYM (Qgrow_only, "grow-only");
- DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
DEFSYM (Qposition, "position");
DEFSYM (Qbuffer_position, "buffer-position");
DEFSYM (Qobject, "object");
+
+ /* Cursor shapes. */
DEFSYM (Qbar, "bar");
DEFSYM (Qhbar, "hbar");
DEFSYM (Qbox, "box");
DEFSYM (Qhollow, "hollow");
+
+ /* Pointer shapes. */
DEFSYM (Qhand, "hand");
DEFSYM (Qarrow, "arrow");
+ /* also Qtext */
+
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
list_of_error = list1 (list2 (intern_c_string ("error"),
intern_c_string ("void-variable")));
staticpro (&list_of_error);
+ /* Values of those variables at last redisplay are stored as
+ properties on 'overlay-arrow-position' symbol. However, if
+ Voverlay_arrow_position is a marker, last-arrow-position is its
+ numerical position. */
DEFSYM (Qlast_arrow_position, "last-arrow-position");
DEFSYM (Qlast_arrow_string, "last-arrow-string");
+
+ /* Alternative overlay-arrow-string and overlay-arrow-bitmap
+ properties on a symbol in overlay-arrow-variable-list. */
DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
@@ -30409,6 +30624,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,
@@ -30440,8 +30656,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,
@@ -30587,9 +30804,12 @@ all the functions in the list are called, with the frame as argument. */);
DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
doc: /* List of functions to call before redisplaying a window with scrolling.
Each function is called with two arguments, the window and its new
-display-start position. Note that these functions are also called by
-`set-window-buffer'. Also note that the value of `window-end' is not
-valid when these functions are called.
+display-start position.
+These functions are called whenever the `window-start' marker is modified,
+either to point into another buffer (e.g. via `set-window-buffer') or another
+place in the same buffer.
+Note that the value of `window-end' is not valid when these functions are
+called.
Warning: Do not use this feature to alter the way the window
is scrolled. It is not designed for that, and such use probably won't
@@ -30814,6 +31034,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. */);
@@ -30858,7 +31084,10 @@ cursor shapes. */);
hourglass_shown_p = 0;
#endif /* HAVE_WINDOW_SYSTEM */
+ /* Name of the face used to display glyphless characters. */
DEFSYM (Qglyphless_char, "glyphless-char");
+
+ /* Method symbols for Vglyphless_char_display. */
DEFSYM (Qhex_code, "hex-code");
DEFSYM (Qempty_box, "empty-box");
DEFSYM (Qthin_space, "thin-space");
@@ -30871,6 +31100,7 @@ be redisplayed. This set can be nil (meaning, only the selected window),
or t (meaning all windows). */);
Vpre_redisplay_function = intern ("ignore");
+ /* Symbol for the purpose of Vglyphless_char_display. */
DEFSYM (Qglyphless_char_display, "glyphless-char-display");
Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
@@ -30936,10 +31166,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);
@@ -30972,7 +31202,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)
{
@@ -30991,20 +31252,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)
{
@@ -31015,7 +31269,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 44c72aa4944..7c9f62683fd 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -265,74 +265,21 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <c-ctype.h>
-/* Non-zero if face attribute ATTR is unspecified. */
+/* True if face attribute ATTR is unspecified. */
#define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
-/* Non-zero if face attribute ATTR is `ignore-defface'. */
+/* True if face attribute ATTR is `ignore-defface'. */
#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). */
#define FACE_CACHE_BUCKETS_SIZE 1001
-/* Keyword symbols used for face attribute names. */
-
-Lisp_Object QCfamily, QCheight, QCweight, QCslant;
-static Lisp_Object QCunderline;
-static Lisp_Object QCinverse_video, QCstipple;
-Lisp_Object QCforeground, QCbackground;
-Lisp_Object QCwidth;
-static Lisp_Object QCfont, QCbold, QCitalic;
-static Lisp_Object QCreverse_video;
-static Lisp_Object QCoverline, QCstrike_through, QCbox, QCinherit;
-static Lisp_Object QCfontset, QCdistant_foreground;
-
-/* Symbols used for attribute values. */
-
-Lisp_Object Qnormal;
-Lisp_Object Qbold;
-static Lisp_Object Qline, Qwave;
-Lisp_Object Qextra_light, Qlight;
-Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold;
-Lisp_Object Qoblique;
-Lisp_Object Qitalic;
-static Lisp_Object Qreleased_button, Qpressed_button;
-static Lisp_Object QCstyle, QCcolor, QCline_width;
-Lisp_Object Qunspecified; /* used in dosfns.c */
-static Lisp_Object QCignore_defface;
-
char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
-/* The name of the function to call when the background of the frame
- has changed, frame_set_background_mode. */
-
-static Lisp_Object Qframe_set_background_mode;
-
-/* Names of basic faces. */
-
-Lisp_Object Qdefault, Qtool_bar, Qfringe;
-static Lisp_Object Qregion;
-Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
-static Lisp_Object Qborder, Qmouse, Qmenu;
-Lisp_Object Qmode_line_inactive;
-static Lisp_Object Qvertical_border;
-static Lisp_Object Qwindow_divider;
-static Lisp_Object Qwindow_divider_first_pixel;
-static Lisp_Object Qwindow_divider_last_pixel;
-
-/* The symbol `face-alias'. A symbols having that property is an
- alias for another face. Value of the property is the name of
- the aliased face. */
-
-static Lisp_Object Qface_alias;
-
/* Alist of alternative font families. Each element is of the form
(FAMILY FAMILY1 FAMILY2 ...). If fonts of FAMILY can't be loaded,
try FAMILY1, then FAMILY2, ... */
@@ -345,32 +292,6 @@ Lisp_Object Vface_alternative_font_family_alist;
Lisp_Object Vface_alternative_font_registry_alist;
-/* Allowed scalable fonts. A value of nil means don't allow any
- scalable fonts. A value of t means allow the use of any scalable
- font. Otherwise, value must be a list of regular expressions. A
- font may be scaled if its name matches a regular expression in the
- list. */
-
-static Lisp_Object Qscalable_fonts_allowed;
-
-/* The symbols `foreground-color' and `background-color' which can be
- used as part of a `face' property. This is for compatibility with
- Emacs 20.2. */
-
-Lisp_Object Qforeground_color, Qbackground_color;
-
-/* The symbols `face' and `mouse-face' used as text properties. */
-
-Lisp_Object Qface;
-
-/* Property for basic faces which other faces cannot inherit. */
-
-static Lisp_Object Qface_no_inherit;
-
-/* Error symbol for wrong_type_argument in load_pixmap. */
-
-static Lisp_Object Qbitmap_spec_p;
-
/* The next ID to assign to Lisp faces. */
static int next_lface_id;
@@ -380,14 +301,6 @@ static int next_lface_id;
static Lisp_Object *lface_id_to_name;
static ptrdiff_t lface_id_to_name_size;
-/* TTY color-related functions (defined in tty-colors.el). */
-
-static Lisp_Object Qtty_color_desc, Qtty_color_by_index, Qtty_color_standard_values;
-
-/* The name of the function used to compute colors on TTYs. */
-
-static Lisp_Object Qtty_color_alist;
-
#ifdef HAVE_WINDOW_SYSTEM
/* Counter for calls to clear_face_cache. If this counter reaches
@@ -405,12 +318,12 @@ static int clear_font_table_count;
int face_change_count;
-/* Non-zero means don't display bold text if a face's foreground
+/* True means don't display bold text if a face's foreground
and background colors are the inverse of the default colors of the
display. This is a kluge to suppress `bold black' foreground text
which is hard to read on an LCD monitor. */
-static int tty_suppress_bold_inverse_default_colors_p;
+static bool tty_suppress_bold_inverse_default_colors_p;
/* A list of the form `((x . y))' used to avoid consing in
Finternal_set_lisp_face_attribute. */
@@ -425,10 +338,10 @@ static int npixmaps_allocated;
static int ngcs;
#endif
-/* Non-zero means the definition of the `menu' face for new frames has
+/* True means the definition of the `menu' face for new frames has
been changed. */
-static int menu_face_changed_default;
+static bool menu_face_changed_default;
struct named_merge_point;
@@ -441,8 +354,8 @@ static bool realize_default_face (struct frame *);
static void realize_named_face (struct frame *, Lisp_Object, int);
static struct face_cache *make_face_cache (struct frame *);
static void free_face_cache (struct face_cache *);
-static int merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *,
- int, struct named_merge_point *);
+static bool merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *,
+ bool, struct named_merge_point *);
static int color_distance (XColor *x, XColor *y);
#ifdef HAVE_WINDOW_SYSTEM
@@ -515,7 +428,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]);
@@ -725,18 +638,18 @@ recompute_basic_faces (struct frame *f)
{
if (FRAME_FACE_CACHE (f))
{
- clear_face_cache (0);
+ clear_face_cache (false);
if (!realize_basic_faces (f))
emacs_abort ();
}
}
-/* Clear the face caches of all frames. CLEAR_FONTS_P non-zero means
+/* Clear the face caches of all frames. CLEAR_FONTS_P means
try to free unused fonts, too. */
void
-clear_face_cache (int clear_fonts_p)
+clear_face_cache (bool clear_fonts_p)
{
#ifdef HAVE_WINDOW_SYSTEM
Lisp_Object tail, frame;
@@ -802,11 +715,11 @@ the pixmap. Bits are stored row by row, each row occupies
\(WIDTH + 7)/8 bytes. */)
(Lisp_Object object)
{
- bool pixmap_p = 0;
+ bool pixmap_p = false;
if (STRINGP (object))
/* If OBJECT is a string, it's a file name. */
- pixmap_p = 1;
+ pixmap_p = true;
else if (CONSP (object))
{
/* Otherwise OBJECT must be (WIDTH HEIGHT DATA), WIDTH and
@@ -836,7 +749,7 @@ the pixmap. Bits are stored row by row, each row occupies
int bytes_per_row = ((XINT (width) + BITS_PER_CHAR - 1)
/ BITS_PER_CHAR);
if (XINT (height) <= SBYTES (data) / bytes_per_row)
- pixmap_p = 1;
+ pixmap_p = true;
}
}
@@ -907,9 +820,9 @@ load_pixmap (struct frame *f, Lisp_Object name)
/* Parse RGB_LIST, and fill in the RGB fields of COLOR.
RGB_LIST should contain (at least) 3 lisp integers.
- Return 0 if there's a problem with RGB_LIST, otherwise return 1. */
+ Return true iff RGB_LIST is OK. */
-static int
+static bool
parse_rgb_list (Lisp_Object rgb_list, XColor *color)
{
#define PARSE_RGB_LIST_FIELD(field) \
@@ -919,13 +832,13 @@ parse_rgb_list (Lisp_Object rgb_list, XColor *color)
rgb_list = XCDR (rgb_list); \
} \
else \
- return 0;
+ return false;
PARSE_RGB_LIST_FIELD (red);
PARSE_RGB_LIST_FIELD (green);
PARSE_RGB_LIST_FIELD (blue);
- return 1;
+ return true;
}
@@ -941,7 +854,7 @@ tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
Lisp_Object frame, color_desc;
if (!STRINGP (color) || NILP (Ffboundp (Qtty_color_desc)))
- return 0;
+ return false;
XSETFRAME (frame, f);
@@ -951,13 +864,13 @@ tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
Lisp_Object rgb;
if (! INTEGERP (XCAR (XCDR (color_desc))))
- return 0;
+ return false;
tty_color->pixel = XINT (XCAR (XCDR (color_desc)));
rgb = XCDR (XCDR (color_desc));
if (! parse_rgb_list (rgb, tty_color))
- return 0;
+ return false;
/* Should we fill in STD_COLOR too? */
if (std_color)
@@ -976,21 +889,21 @@ tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
/* Look up STD_COLOR separately. */
rgb = call1 (Qtty_color_standard_values, color);
if (! parse_rgb_list (rgb, std_color))
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
else if (NILP (Fsymbol_value (intern ("tty-defined-color-alist"))))
/* We were called early during startup, and the colors are not
yet set up in tty-defined-color-alist. Don't return a failure
indication, since this produces the annoying "Unable to
load color" messages in the *Messages* buffer. */
- return 1;
+ return true;
else
/* tty-color-desc seems to have returned a bad value. */
- return 0;
+ return false;
}
/* A version of defined_color for non-X frames. */
@@ -999,7 +912,7 @@ static bool
tty_defined_color (struct frame *f, const char *color_name,
XColor *color_def, bool alloc)
{
- bool status = 1;
+ bool status = true;
/* Defaults. */
color_def->pixel = FACE_TTY_DEFAULT_COLOR;
@@ -1019,7 +932,7 @@ tty_defined_color (struct frame *f, const char *color_name,
}
if (color_def->pixel != FACE_TTY_DEFAULT_COLOR)
- status = 1;
+ status = true;
return status;
}
@@ -1047,7 +960,7 @@ defined_color (struct frame *f, const char *color_name, XColor *color_def,
#endif
#ifdef HAVE_NS
else if (FRAME_NS_P (f))
- return ns_defined_color (f, color_name, color_def, alloc, 1);
+ return ns_defined_color (f, color_name, color_def, alloc, true);
#endif
else
emacs_abort ();
@@ -1072,7 +985,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);
@@ -1087,18 +1000,18 @@ tty_color_name (struct frame *f, int idx)
}
-/* Return non-zero if COLOR_NAME is a shade of gray (or white or
+/* Return true if COLOR_NAME is a shade of gray (or white or
black) on frame F.
The criterion implemented here is not a terribly sophisticated one. */
-static int
+static bool
face_color_gray_p (struct frame *f, const char *color_name)
{
XColor color;
- int gray_p;
+ bool gray_p;
- if (defined_color (f, color_name, &color, 0))
+ if (defined_color (f, color_name, &color, false))
gray_p = (/* Any color sufficiently close to black counts as gray. */
(color.red < 5000 && color.green < 5000 && color.blue < 5000)
||
@@ -1109,19 +1022,18 @@ face_color_gray_p (struct frame *f, const char *color_name)
&& (eabs (color.blue - color.red)
< max (color.blue, color.red) / 20)));
else
- gray_p = 0;
+ gray_p = false;
return gray_p;
}
-/* Return non-zero if color COLOR_NAME can be displayed on frame F.
- BACKGROUND_P non-zero means the color will be used as background
- color. */
+/* Return true if color COLOR_NAME can be displayed on frame F.
+ BACKGROUND_P means the color will be used as background color. */
-static int
+static bool
face_color_supported_p (struct frame *f, const char *color_name,
- int background_p)
+ bool background_p)
{
Lisp_Object frame;
XColor not_used;
@@ -1139,7 +1051,7 @@ face_color_supported_p (struct frame *f, const char *color_name,
&& face_color_gray_p (f, color_name)))
:
#endif
- tty_defined_color (f, color_name, &not_used, 0);
+ tty_defined_color (f, color_name, &not_used, false);
}
@@ -1185,39 +1097,39 @@ load_color2 (struct frame *f, struct face *face, Lisp_Object name,
/* if the color map is full, defined_color will return a best match
to the values in an existing cell. */
- if (!defined_color (f, SSDATA (name), color, 1))
+ if (!defined_color (f, SSDATA (name), color, true))
{
add_to_log ("Unable to load color \"%s\"", name, Qnil);
switch (target_index)
{
case LFACE_FOREGROUND_INDEX:
- face->foreground_defaulted_p = 1;
+ face->foreground_defaulted_p = true;
color->pixel = FRAME_FOREGROUND_PIXEL (f);
break;
case LFACE_BACKGROUND_INDEX:
- face->background_defaulted_p = 1;
+ face->background_defaulted_p = true;
color->pixel = FRAME_BACKGROUND_PIXEL (f);
break;
case LFACE_UNDERLINE_INDEX:
- face->underline_defaulted_p = 1;
+ face->underline_defaulted_p = true;
color->pixel = FRAME_FOREGROUND_PIXEL (f);
break;
case LFACE_OVERLINE_INDEX:
- face->overline_color_defaulted_p = 1;
+ face->overline_color_defaulted_p = true;
color->pixel = FRAME_FOREGROUND_PIXEL (f);
break;
case LFACE_STRIKE_THROUGH_INDEX:
- face->strike_through_color_defaulted_p = 1;
+ face->strike_through_color_defaulted_p = true;
color->pixel = FRAME_FOREGROUND_PIXEL (f);
break;
case LFACE_BOX_INDEX:
- face->box_color_defaulted_p = 1;
+ face->box_color_defaulted_p = true;
color->pixel = FRAME_FOREGROUND_PIXEL (f);
break;
@@ -1242,9 +1154,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)
@@ -1286,7 +1195,7 @@ load_face_colors (struct frame *f, struct face *face,
face_color_supported_p is smart enough to know that grays are
"supported" as background because we are supposed to use stipple
for them. */
- if (!face_color_supported_p (f, SSDATA (bg), 0)
+ if (!face_color_supported_p (f, SSDATA (bg), false)
&& !NILP (Fbitmap_spec_p (Vface_default_stipple)))
{
x_destroy_bitmap (f, face->stipple);
@@ -1651,7 +1560,7 @@ the WIDTH times as wide as FACE on FRAME. */)
{
/* This is of limited utility since it works with character
widths. Keep it for compatibility. --gerd. */
- int face_id = lookup_named_face (f, face, 0);
+ int face_id = lookup_named_face (f, face, false);
struct face *width_face = (face_id < 0
? NULL
: FACE_FROM_ID (f, face_id));
@@ -1670,43 +1579,38 @@ the WIDTH times as wide as FACE on FRAME. */)
avgwidth *= XINT (width);
}
- {
- Lisp_Object font_spec;
- Lisp_Object args[2], tail;
-
- font_spec = font_spec_from_name (pattern);
- if (!FONTP (font_spec))
- signal_error ("Invalid font name", pattern);
+ Lisp_Object font_spec = font_spec_from_name (pattern);
+ if (!FONTP (font_spec))
+ signal_error ("Invalid font name", pattern);
- if (size)
- {
- Ffont_put (font_spec, QCsize, make_number (size));
- Ffont_put (font_spec, QCavgwidth, make_number (avgwidth));
- }
- args[0] = Flist_fonts (font_spec, frame, maximum, font_spec);
- for (tail = args[0]; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object font_entity;
+ if (size)
+ {
+ Ffont_put (font_spec, QCsize, make_number (size));
+ Ffont_put (font_spec, QCavgwidth, make_number (avgwidth));
+ }
+ Lisp_Object fonts = Flist_fonts (font_spec, frame, maximum, font_spec);
+ for (Lisp_Object tail = fonts; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object font_entity;
- font_entity = XCAR (tail);
- if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
- || XINT (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
- && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
- {
- /* This is a scalable font. For backward compatibility,
- we set the specified size. */
- font_entity = copy_font_spec (font_entity);
- ASET (font_entity, FONT_SIZE_INDEX,
- AREF (font_spec, FONT_SIZE_INDEX));
- }
- XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
- }
- if (NILP (frame))
- /* We don't have to check fontsets. */
- return args[0];
- args[1] = list_fontsets (f, pattern, size);
- return Fnconc (2, args);
- }
+ font_entity = XCAR (tail);
+ if ((NILP (AREF (font_entity, FONT_SIZE_INDEX))
+ || XINT (AREF (font_entity, FONT_SIZE_INDEX)) == 0)
+ && ! NILP (AREF (font_spec, FONT_SIZE_INDEX)))
+ {
+ /* This is a scalable font. For backward compatibility,
+ we set the specified size. */
+ font_entity = copy_font_spec (font_entity);
+ ASET (font_entity, FONT_SIZE_INDEX,
+ AREF (font_spec, FONT_SIZE_INDEX));
+ }
+ XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
+ }
+ if (NILP (frame))
+ /* We don't have to check fontsets. */
+ return fonts;
+ Lisp_Object fontsets = list_fontsets (f, pattern, size);
+ return CALLN (Fnconc, fonts, fontsets);
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -1738,7 +1642,7 @@ the WIDTH times as wide as FACE on FRAME. */)
#define LFACE_DISTANT_FOREGROUND(LFACE) \
AREF ((LFACE), LFACE_DISTANT_FOREGROUND_INDEX)
-/* Non-zero if LFACE is a Lisp face. A Lisp face is a vector of size
+/* True if LFACE is a Lisp face. A Lisp face is a vector of size
LFACE_VECTOR_SIZE which has the symbol `face' in slot 0. */
#define LFACEP(LFACE) \
@@ -1868,12 +1772,12 @@ struct named_merge_point
};
-/* If a face merging cycle is detected for FACE_NAME, return 0,
+/* If a face merging cycle is detected for FACE_NAME, return false,
otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
- pointed to by NAMED_MERGE_POINTS, and return 1. */
+ pointed to by NAMED_MERGE_POINTS, and return true. */
-static int
+static bool
push_named_merge_point (struct named_merge_point *new_named_merge_point,
Lisp_Object face_name,
enum named_merge_point_kind named_merge_point_kind,
@@ -1886,7 +1790,7 @@ push_named_merge_point (struct named_merge_point *new_named_merge_point,
{
if (prev->named_merge_point_kind == named_merge_point_kind)
/* A cycle, so fail. */
- return 0;
+ return false;
else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
/* A remap `hides ' any previous normal merge points
(because the remap means that it's actually different face),
@@ -1901,7 +1805,7 @@ push_named_merge_point (struct named_merge_point *new_named_merge_point,
*named_merge_points = new_named_merge_point;
- return 1;
+ return true;
}
@@ -1912,7 +1816,7 @@ push_named_merge_point (struct named_merge_point *new_named_merge_point,
Return default face in case of errors. */
static Lisp_Object
-resolve_face_name (Lisp_Object face_name, int signal_p)
+resolve_face_name (Lisp_Object face_name, bool signal_p)
{
Lisp_Object orig_face;
Lisp_Object tortoise, hare;
@@ -1926,7 +1830,7 @@ resolve_face_name (Lisp_Object face_name, int signal_p)
orig_face = face_name;
tortoise = hare = face_name;
- while (1)
+ while (true)
{
face_name = hare;
hare = Fget (hare, Qface_alias);
@@ -1954,12 +1858,12 @@ resolve_face_name (Lisp_Object face_name, int signal_p)
/* Return the face definition of FACE_NAME on frame F. F null means
return the definition for new frames. FACE_NAME may be a string or
a symbol (apparently Emacs 20.2 allowed strings as face names in
- face text properties; Ediff uses that). If SIGNAL_P is non-zero,
- signal an error if FACE_NAME is not a valid face name. If SIGNAL_P
- is zero, value is nil if FACE_NAME is not a valid face name. */
+ face text properties; Ediff uses that).
+ If SIGNAL_P, signal an error if FACE_NAME is not a valid face name.
+ Otherwise, value is nil if FACE_NAME is not a valid face name. */
static Lisp_Object
lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
- int signal_p)
+ bool signal_p)
{
Lisp_Object lface;
@@ -1982,12 +1886,11 @@ lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
return the definition for new frames. FACE_NAME may be a string or
a symbol (apparently Emacs 20.2 allowed strings as face names in
face text properties; Ediff uses that). If FACE_NAME is an alias
- for another face, return that face's definition. If SIGNAL_P is
- non-zero, signal an error if FACE_NAME is not a valid face name.
- If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
- name. */
+ for another face, return that face's definition.
+ If SIGNAL_P, signal an error if FACE_NAME is not a valid face name.
+ Otherwise, value is nil if FACE_NAME is not a valid face name. */
static Lisp_Object
-lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
+lface_from_face_name (struct frame *f, Lisp_Object face_name, bool signal_p)
{
face_name = resolve_face_name (face_name, signal_p);
return lface_from_face_name_no_resolve (f, face_name, signal_p);
@@ -1996,14 +1899,14 @@ lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
/* Get face attributes of face FACE_NAME from frame-local faces on
frame F. Store the resulting attributes in ATTRS which must point
- to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If SIGNAL_P
- is non-zero, signal an error if FACE_NAME does not name a face.
- Otherwise, value is zero if FACE_NAME is not a face. */
+ to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE.
+ If SIGNAL_P, signal an error if FACE_NAME does not name a face.
+ Otherwise, return true iff FACE_NAME is a face. */
-static int
+static bool
get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
Lisp_Object attrs[LFACE_VECTOR_SIZE],
- int signal_p)
+ bool signal_p)
{
Lisp_Object lface;
@@ -2019,13 +1922,13 @@ get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
/* Get face attributes of face FACE_NAME from frame-local faces on frame
F. Store the resulting attributes in ATTRS which must point to a
vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an
- alias for another face, use that face's definition. If SIGNAL_P is
- non-zero, signal an error if FACE_NAME does not name a face.
- Otherwise, value is zero if FACE_NAME is not a face. */
+ alias for another face, use that face's definition.
+ If SIGNAL_P, signal an error if FACE_NAME does not name a face.
+ Otherwise, return true iff FACE_NAME is a face. */
-static int
+static bool
get_lface_attributes (struct frame *f, Lisp_Object face_name,
- Lisp_Object attrs[LFACE_VECTOR_SIZE], int signal_p,
+ Lisp_Object attrs[LFACE_VECTOR_SIZE], bool signal_p,
struct named_merge_point *named_merge_points)
{
Lisp_Object face_remapping;
@@ -2058,10 +1961,10 @@ get_lface_attributes (struct frame *f, Lisp_Object face_name,
}
-/* Non-zero if all attributes in face attribute vector ATTRS are
+/* True iff all attributes in face attribute vector ATTRS are
specified, i.e. are non-nil. */
-static int
+static bool
lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
int i;
@@ -2078,13 +1981,13 @@ lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE])
#ifdef HAVE_WINDOW_SYSTEM
/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT.
- If FORCE_P is zero, set only unspecified attributes of LFACE. The
+ If FORCE_P, set only unspecified attributes of LFACE. The
exception is `font' attribute. It is set to FONT_OBJECT regardless
of FORCE_P. */
-static int
+static void
set_lface_from_font (struct frame *f, Lisp_Object lface,
- Lisp_Object font_object, int force_p)
+ Lisp_Object font_object, bool force_p)
{
Lisp_Object val;
struct font *font = XFONT_OBJECT (font_object);
@@ -2132,7 +2035,6 @@ set_lface_from_font (struct frame *f, Lisp_Object lface,
}
ASET (lface, LFACE_FONT_INDEX, font_object);
- return 1;
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -2203,7 +2105,7 @@ merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
other code uses `unspecified' as a generic value for face attributes. */
if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
&& !NILP (from[LFACE_INHERIT_INDEX]))
- merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
+ merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, false, named_merge_points);
if (FONT_SPEC_P (from[LFACE_FONT_INDEX]))
{
@@ -2261,11 +2163,11 @@ merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
}
/* Merge the named face FACE_NAME on frame F, into the vector of face
- attributes TO. NAMED_MERGE_POINTS is used to detect loops in face
- inheritance. Returns true if FACE_NAME is a valid face name and
+ attributes TO. Use NAMED_MERGE_POINTS to detect loops in face
+ inheritance. Return true if FACE_NAME is a valid face name and
merging succeeded. */
-static int
+static bool
merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
struct named_merge_point *named_merge_points)
{
@@ -2277,7 +2179,8 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
{
struct gcpro gcpro1;
Lisp_Object from[LFACE_VECTOR_SIZE];
- int ok = get_lface_attributes (f, face_name, from, 0, named_merge_points);
+ bool ok = get_lface_attributes (f, face_name, from, false,
+ named_merge_points);
if (ok)
{
@@ -2289,15 +2192,15 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
return ok;
}
else
- return 0;
+ return false;
}
/* Merge face attributes from the lisp `face reference' FACE_REF on
- frame F into the face attribute vector TO. If ERR_MSGS is non-zero,
+ frame F into the face attribute vector TO. If ERR_MSGS,
problems with FACE_REF cause an error message to be shown. Return
- non-zero if no errors occurred (regardless of the value of ERR_MSGS).
- NAMED_MERGE_POINTS is used to detect loops in face inheritance or
+ true if no errors occurred (regardless of the value of ERR_MSGS).
+ Use NAMED_MERGE_POINTS to detect loops in face inheritance or
list structure; it may be 0 for most callers.
FACE_REF may be a single face specification or a list of such
@@ -2316,11 +2219,11 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
Face specifications earlier in lists take precedence over later
specifications. */
-static int
+static bool
merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
- int err_msgs, struct named_merge_point *named_merge_points)
+ bool err_msgs, struct named_merge_point *named_merge_points)
{
- int ok = 1; /* Succeed without an error? */
+ bool ok = true; /* Succeed without an error? */
if (CONSP (face_ref))
{
@@ -2345,7 +2248,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
{
if (err_msgs)
add_to_log ("Invalid face color", color_name, Qnil);
- ok = 0;
+ ok = false;
}
}
else if (SYMBOLP (first)
@@ -2356,7 +2259,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
{
Lisp_Object keyword = XCAR (face_ref);
Lisp_Object value = XCAR (XCDR (face_ref));
- int err = 0;
+ bool err = false;
/* Specifying `unspecified' is a no-op. */
if (EQ (value, Qunspecified))
@@ -2369,7 +2272,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
font_clear_prop (to, FONT_FAMILY_INDEX);
}
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCfoundry))
{
@@ -2379,7 +2282,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
font_clear_prop (to, FONT_FOUNDRY_INDEX);
}
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCheight))
{
@@ -2392,7 +2295,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
font_clear_prop (to, FONT_SIZE_INDEX);
}
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCweight))
{
@@ -2402,7 +2305,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
font_clear_prop (to, FONT_WEIGHT_INDEX);
}
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCslant))
{
@@ -2412,7 +2315,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
font_clear_prop (to, FONT_SLANT_INDEX);
}
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCunderline))
{
@@ -2422,7 +2325,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
|| CONSP (value))
to[LFACE_UNDERLINE_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCoverline))
{
@@ -2431,7 +2334,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
|| STRINGP (value))
to[LFACE_OVERLINE_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCstrike_through))
{
@@ -2440,7 +2343,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
|| STRINGP (value))
to[LFACE_STRIKE_THROUGH_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCbox))
{
@@ -2452,7 +2355,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
|| NILP (value))
to[LFACE_BOX_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCinverse_video)
|| EQ (keyword, QCreverse_video))
@@ -2460,28 +2363,28 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
if (EQ (value, Qt) || NILP (value))
to[LFACE_INVERSE_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCforeground))
{
if (STRINGP (value))
to[LFACE_FOREGROUND_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCdistant_foreground))
{
if (STRINGP (value))
to[LFACE_DISTANT_FOREGROUND_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCbackground))
{
if (STRINGP (value))
to[LFACE_BACKGROUND_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCstipple))
{
@@ -2490,7 +2393,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
if (!NILP (pixmap_p))
to[LFACE_STIPPLE_INDEX] = value;
else
- err = 1;
+ err = true;
#endif /* HAVE_WINDOW_SYSTEM */
}
else if (EQ (keyword, QCwidth))
@@ -2501,14 +2404,14 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
font_clear_prop (to, FONT_WIDTH_INDEX);
}
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCfont))
{
if (FONTP (value))
to[LFACE_FONT_INDEX] = value;
else
- err = 1;
+ err = true;
}
else if (EQ (keyword, QCinherit))
{
@@ -2516,15 +2419,15 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
normal face reference. */
if (! merge_face_ref (f, value, to,
err_msgs, named_merge_points))
- err = 1;
+ err = true;
}
else
- err = 1;
+ err = true;
if (err)
{
add_to_log ("Invalid face attribute %S %S", keyword, value);
- ok = 0;
+ ok = false;
}
face_ref = XCDR (XCDR (face_ref));
@@ -2541,7 +2444,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
ok = merge_face_ref (f, next, to, err_msgs, named_merge_points);
if (! merge_face_ref (f, first, to, err_msgs, named_merge_points))
- ok = 0;
+ ok = false;
}
}
else
@@ -2570,13 +2473,13 @@ Value is a vector of face attributes. */)
int i;
CHECK_SYMBOL (face);
- global_lface = lface_from_face_name (NULL, face, 0);
+ global_lface = lface_from_face_name (NULL, face, false);
if (!NILP (frame))
{
CHECK_LIVE_FRAME (frame);
f = XFRAME (frame);
- lface = lface_from_face_name (f, face, 0);
+ lface = lface_from_face_name (f, face, false);
}
else
f = NULL, lface = Qnil;
@@ -2652,15 +2555,15 @@ Otherwise check for the existence of a global face. */)
{
Lisp_Object lface;
- face = resolve_face_name (face, 1);
+ face = resolve_face_name (face, true);
if (!NILP (frame))
{
CHECK_LIVE_FRAME (frame);
- lface = lface_from_face_name (XFRAME (frame), face, 0);
+ lface = lface_from_face_name (XFRAME (frame), face, false);
}
else
- lface = lface_from_face_name (NULL, face, 0);
+ lface = lface_from_face_name (NULL, face, false);
return lface;
}
@@ -2687,7 +2590,7 @@ The value is TO. */)
{
/* Copy global definition of FROM. We don't make copies of
strings etc. because 20.2 didn't do it either. */
- lface = lface_from_face_name (NULL, from, 1);
+ lface = lface_from_face_name (NULL, from, true);
copy = Finternal_make_lisp_face (to, Qnil);
}
else
@@ -2697,7 +2600,7 @@ The value is TO. */)
new_frame = frame;
CHECK_LIVE_FRAME (frame);
CHECK_LIVE_FRAME (new_frame);
- lface = lface_from_face_name (XFRAME (frame), from, 1);
+ lface = lface_from_face_name (XFRAME (frame), from, true);
copy = Finternal_make_lisp_face (to, new_frame);
}
@@ -2737,7 +2640,7 @@ FRAME 0 means change the face on all frames, and change the default
CHECK_SYMBOL (face);
CHECK_SYMBOL (attr);
- face = resolve_face_name (face, 1);
+ face = resolve_face_name (face, true);
/* If FRAME is 0, change face on all frames, and change the
default for new frames. */
@@ -2753,7 +2656,7 @@ FRAME 0 means change the face on all frames, and change the default
/* Set lface to the Lisp attribute vector of FACE. */
if (EQ (frame, Qt))
{
- lface = lface_from_face_name (NULL, face, 1);
+ lface = lface_from_face_name (NULL, face, true);
/* When updating face-new-frame-defaults, we put :ignore-defface
where the caller wants `unspecified'. This forces the frame
@@ -2770,7 +2673,7 @@ FRAME 0 means change the face on all frames, and change the default
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
- lface = lface_from_face_name (XFRAME (frame), face, 0);
+ lface = lface_from_face_name (XFRAME (frame), face, false);
/* If a frame-local face doesn't exist yet, create one. */
if (NILP (lface))
@@ -2855,14 +2758,14 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCunderline))
{
- bool valid_p = 0;
+ bool valid_p = false;
if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
- valid_p = 1;
+ valid_p = true;
else if (NILP (value) || EQ (value, Qt))
- valid_p = 1;
+ valid_p = true;
else if (STRINGP (value) && SCHARS (value) > 0)
- valid_p = 1;
+ valid_p = true;
else if (CONSP (value))
{
Lisp_Object key, val, list;
@@ -2874,7 +2777,7 @@ FRAME 0 means change the face on all frames, and change the default
Non-nil symbols other than t are not documented as being valid.
Eg compare with inverse-video, which explicitly rejects them.
*/
- valid_p = 1;
+ valid_p = true;
while (!NILP (CAR_SAFE(list)))
{
@@ -2885,7 +2788,7 @@ FRAME 0 means change the face on all frames, and change the default
if (NILP (key) || NILP (val))
{
- valid_p = 0;
+ valid_p = false;
break;
}
@@ -2893,14 +2796,14 @@ FRAME 0 means change the face on all frames, and change the default
&& !(EQ (val, Qforeground_color)
|| (STRINGP (val) && SCHARS (val) > 0)))
{
- valid_p = 0;
+ valid_p = false;
break;
}
else if (EQ (key, QCstyle)
&& !(EQ (val, Qline) || EQ (val, Qwave)))
{
- valid_p = 0;
+ valid_p = false;
break;
}
}
@@ -2950,9 +2853,9 @@ FRAME 0 means change the face on all frames, and change the default
value = make_number (1);
if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
- valid_p = 1;
+ valid_p = true;
else if (NILP (value))
- valid_p = 1;
+ valid_p = true;
else if (INTEGERP (value))
valid_p = XINT (value) != 0;
else if (STRINGP (value))
@@ -2995,7 +2898,7 @@ FRAME 0 means change the face on all frames, and change the default
valid_p = NILP (tem);
}
else
- valid_p = 0;
+ valid_p = false;
if (!valid_p)
signal_error ("Invalid face box", value);
@@ -3123,10 +3026,9 @@ FRAME 0 means change the face on all frames, and change the default
/* FIXME:
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.
- */
- if (f->terminal->type != output_termcap)
+ for a non-tty frame and use that. See discussion in Bug#18573.
+ For a daemon, frame may be an initial frame (Bug#18869). */
+ if (FRAME_WINDOW_P (f))
{
if (! FONT_OBJECT_P (value))
{
@@ -3138,7 +3040,7 @@ FRAME 0 means change the face on all frames, and change the default
signal_error ("Font not available", value);
value = font_object;
}
- set_lface_from_font (f, lface, value, 1);
+ set_lface_from_font (f, lface, value, true);
}
}
else
@@ -3283,10 +3185,10 @@ FRAME 0 means change the face on all frames, and change the default
struct frame *f = XFRAME (frame);
if (FRAME_FACE_CACHE (f) == NULL)
FRAME_FACE_CACHE (f) = make_face_cache (f);
- FRAME_FACE_CACHE (f)->menu_face_changed_p = 1;
+ FRAME_FACE_CACHE (f)->menu_face_changed_p = true;
}
else
- menu_face_changed_default = 1;
+ menu_face_changed_default = true;
}
if (!NILP (param))
@@ -3331,7 +3233,7 @@ update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
if (EQ (param, Qforeground_color))
{
face = Qdefault;
- lface = lface_from_face_name (f, face, 1);
+ lface = lface_from_face_name (f, face, true);
ASET (lface, LFACE_FOREGROUND_INDEX,
(STRINGP (new_value) ? new_value : Qunspecified));
realize_basic_faces (f);
@@ -3347,7 +3249,7 @@ update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
call1 (Qframe_set_background_mode, frame);
face = Qdefault;
- lface = lface_from_face_name (f, face, 1);
+ lface = lface_from_face_name (f, face, true);
ASET (lface, LFACE_BACKGROUND_INDEX,
(STRINGP (new_value) ? new_value : Qunspecified));
realize_basic_faces (f);
@@ -3356,21 +3258,21 @@ update_face_from_frame_parameter (struct frame *f, Lisp_Object param,
else if (EQ (param, Qborder_color))
{
face = Qborder;
- lface = lface_from_face_name (f, face, 1);
+ lface = lface_from_face_name (f, face, true);
ASET (lface, LFACE_BACKGROUND_INDEX,
(STRINGP (new_value) ? new_value : Qunspecified));
}
else if (EQ (param, Qcursor_color))
{
face = Qcursor;
- lface = lface_from_face_name (f, face, 1);
+ lface = lface_from_face_name (f, face, true);
ASET (lface, LFACE_BACKGROUND_INDEX,
(STRINGP (new_value) ? new_value : Qunspecified));
}
else if (EQ (param, Qmouse_color))
{
face = Qmouse;
- lface = lface_from_face_name (f, face, 1);
+ lface = lface_from_face_name (f, face, true);
ASET (lface, LFACE_BACKGROUND_INDEX,
(STRINGP (new_value) ? new_value : Qunspecified));
}
@@ -3414,8 +3316,9 @@ set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
return;
ASET (lface, LFACE_FONT_INDEX, font);
}
- f->default_face_done_p = 0;
- Fmodify_frame_parameters (frame, list1 (Fcons (Qfont, font)));
+ f->default_face_done_p = false;
+ AUTO_FRAME_ARG (arg, Qfont, font);
+ Fmodify_frame_parameters (frame, arg);
}
}
@@ -3443,11 +3346,11 @@ ordinary `x-get-resource' doesn't take a frame argument. */)
/* Return resource string VALUE as a boolean value, i.e. nil, or t.
If VALUE is "on" or "true", return t. If VALUE is "off" or
- "false", return nil. Otherwise, if SIGNAL_P is non-zero, signal an
- error; if SIGNAL_P is zero, return 0. */
+ "false", return nil. Otherwise, if SIGNAL_P, signal an
+ error; if !SIGNAL_P, return 0. */
static Lisp_Object
-face_boolean_x_resource_value (Lisp_Object value, int signal_p)
+face_boolean_x_resource_value (Lisp_Object value, bool signal_p)
{
Lisp_Object result = make_number (0);
@@ -3487,11 +3390,11 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
signal_error ("Invalid face height from X resource", value);
}
else if (EQ (attr, QCbold) || EQ (attr, QCitalic))
- value = face_boolean_x_resource_value (value, 1);
+ value = face_boolean_x_resource_value (value, true);
else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
value = intern (SSDATA (value));
else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video))
- value = face_boolean_x_resource_value (value, 1);
+ value = face_boolean_x_resource_value (value, true);
else if (EQ (attr, QCunderline)
|| EQ (attr, QCoverline)
|| EQ (attr, QCstrike_through))
@@ -3500,7 +3403,7 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
/* If the result of face_boolean_x_resource_value is t or nil,
VALUE does NOT specify a color. */
- boolean_value = face_boolean_x_resource_value (value, 0);
+ boolean_value = face_boolean_x_resource_value (value, false);
if (SYMBOLP (boolean_value))
value = boolean_value;
}
@@ -3534,10 +3437,10 @@ x_update_menu_appearance (struct frame *f)
char line[512];
char *buf = line;
ptrdiff_t bufsize = sizeof line;
- Lisp_Object lface = lface_from_face_name (f, Qmenu, 1);
+ Lisp_Object lface = lface_from_face_name (f, Qmenu, true);
struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
const char *myname = SSDATA (Vx_resource_name);
- bool changed_p = 0;
+ bool changed_p = false;
#ifdef USE_MOTIF
const char *popup_path = "popup_menu";
#else
@@ -3553,7 +3456,7 @@ x_update_menu_appearance (struct frame *f)
exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*foreground: %s",
myname, SDATA (LFACE_FOREGROUND (lface)));
XrmPutLineResource (&rdb, line);
- changed_p = 1;
+ changed_p = true;
}
if (STRINGP (LFACE_BACKGROUND (lface)))
@@ -3566,7 +3469,7 @@ x_update_menu_appearance (struct frame *f)
exprintf (&buf, &bufsize, line, -1, "%s.pane.menubar*background: %s",
myname, SDATA (LFACE_BACKGROUND (lface)));
XrmPutLineResource (&rdb, line);
- changed_p = 1;
+ changed_p = true;
}
if (face->font
@@ -3584,7 +3487,7 @@ x_update_menu_appearance (struct frame *f)
Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
#ifdef USE_MOTIF
const char *suffix = "List";
- Bool motif = True;
+ bool motif = true;
#else
#if defined HAVE_X_I18N
@@ -3592,7 +3495,7 @@ x_update_menu_appearance (struct frame *f)
#else
const char *suffix = "";
#endif
- Bool motif = False;
+ bool motif = false;
#endif
if (! NILP (xlfd))
@@ -3609,7 +3512,7 @@ x_update_menu_appearance (struct frame *f)
exprintf (&buf, &bufsize, line, -1, "%s.%s*font%s: %s",
myname, popup_path, suffix, fontsetname);
XrmPutLineResource (&rdb, line);
- changed_p = 1;
+ changed_p = true;
if (fontsetname != SSDATA (xlfd))
xfree (fontsetname);
}
@@ -3636,7 +3539,8 @@ with the value VALUE is relative.
A relative value is one that doesn't entirely override whatever is
inherited from another face. For most possible attributes,
the only relative value that users see is `unspecified'.
-However, for :height, floating point values are also relative. */)
+However, for :height, floating point values are also relative. */
+ attributes: const)
(Lisp_Object attribute, Lisp_Object value)
{
if (EQ (value, Qunspecified) || (EQ (value, QCignore_defface)))
@@ -3675,7 +3579,7 @@ frames). If FRAME is omitted or nil, use the selected frame. */)
(Lisp_Object symbol, Lisp_Object keyword, Lisp_Object frame)
{
struct frame *f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
- Lisp_Object lface = lface_from_face_name (f, symbol, 1), value = Qnil;
+ Lisp_Object lface = lface_from_face_name (f, symbol, true), value = Qnil;
CHECK_SYMBOL (symbol);
CHECK_SYMBOL (keyword);
@@ -3758,8 +3662,8 @@ Default face attributes override any local face attributes. */)
struct frame *f = XFRAME (frame);
CHECK_LIVE_FRAME (frame);
- global_lface = lface_from_face_name (NULL, face, 1);
- local_lface = lface_from_face_name (f, face, 0);
+ global_lface = lface_from_face_name (NULL, face, true);
+ local_lface = lface_from_face_name (f, face, false);
if (NILP (local_lface))
local_lface = Finternal_make_lisp_face (face, frame);
@@ -3804,18 +3708,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);
+ }
}
}
@@ -3843,7 +3752,7 @@ return the font name used for CHARACTER. */)
if (EQ (frame, Qt))
{
Lisp_Object result = Qnil;
- Lisp_Object lface = lface_from_face_name (NULL, face, 1);
+ Lisp_Object lface = lface_from_face_name (NULL, face, true);
if (!UNSPECIFIEDP (LFACE_WEIGHT (lface))
&& !EQ (LFACE_WEIGHT (lface), Qnormal))
@@ -3858,7 +3767,7 @@ return the font name used for CHARACTER. */)
else
{
struct frame *f = decode_live_frame (frame);
- int face_id = lookup_named_face (f, face, 1);
+ int face_id = lookup_named_face (f, face, true);
struct face *fface = FACE_FROM_ID (f, face_id);
if (! fface)
@@ -3883,7 +3792,7 @@ return the font name used for CHARACTER. */)
}
-/* Compare face-attribute values v1 and v2 for equality. Value is non-zero if
+/* Compare face-attribute values v1 and v2 for equality. Value is true if
all attributes are `equal'. Tries to be fast because this function
is called quite often. */
@@ -3893,22 +3802,22 @@ face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
/* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
and the other is specified. */
if (XTYPE (v1) != XTYPE (v2))
- return 0;
+ return false;
if (EQ (v1, v2))
- return 1;
+ return true;
switch (XTYPE (v1))
{
case Lisp_String:
if (SBYTES (v1) != SBYTES (v2))
- return 0;
+ return false;
return memcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
case_Lisp_Int:
case Lisp_Symbol:
- return 0;
+ return false;
default:
return !NILP (Fequal (v1, v2));
@@ -3916,7 +3825,7 @@ face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
}
-/* Compare face vectors V1 and V2 for equality. Value is non-zero if
+/* Compare face vectors V1 and V2 for equality. Value is true if
all attributes are `equal'. Tries to be fast because this function
is called quite often. */
@@ -3924,7 +3833,7 @@ static bool
lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
{
int i;
- bool equal_p = 1;
+ bool equal_p = true;
for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i)
equal_p = face_attr_equal_p (v1[i], v2[i]);
@@ -3941,7 +3850,7 @@ If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames).
If FRAME is omitted or nil, use the selected frame. */)
(Lisp_Object face1, Lisp_Object face2, Lisp_Object frame)
{
- int equal_p;
+ bool equal_p;
struct frame *f;
Lisp_Object lface1, lface2;
@@ -3951,8 +3860,8 @@ If FRAME is omitted or nil, use the selected frame. */)
Emacs. That frame is not an X frame. */
f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
- lface1 = lface_from_face_name (f, face1, 1);
- lface2 = lface_from_face_name (f, face2, 1);
+ lface1 = lface_from_face_name (f, face1, true);
+ lface2 = lface_from_face_name (f, face2, true);
equal_p = lface_equal_p (XVECTOR (lface1)->contents,
XVECTOR (lface2)->contents);
return equal_p ? Qt : Qnil;
@@ -3968,7 +3877,7 @@ If FRAME is omitted or nil, use the selected frame. */)
(Lisp_Object face, Lisp_Object frame)
{
struct frame *f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
- Lisp_Object lface = lface_from_face_name (f, face, 1);
+ Lisp_Object lface = lface_from_face_name (f, face, true);
int i;
for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
@@ -4021,12 +3930,12 @@ lface_hash (Lisp_Object *v)
#ifdef HAVE_WINDOW_SYSTEM
-/* Return non-zero if LFACE1 and LFACE2 specify the same font (without
+/* Return true if LFACE1 and LFACE2 specify the same font (without
considering charsets/registries). They do if they specify the same
family, point size, weight, width, slant, and font. Both
LFACE1 and LFACE2 must be fully-specified. */
-static int
+static bool
lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
{
eassert (lface_fully_specified_p (lface1)
@@ -4105,15 +4014,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 +4050,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
@@ -4183,10 +4092,12 @@ If FRAME is unspecified or nil, the current frame is used. */)
XColor cdef1, cdef2;
if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
- && !(STRINGP (color1) && defined_color (f, SSDATA (color1), &cdef1, 0)))
+ && !(STRINGP (color1)
+ && defined_color (f, SSDATA (color1), &cdef1, false)))
signal_error ("Invalid color", color1);
if (!(CONSP (color2) && parse_rgb_list (color2, &cdef2))
- && !(STRINGP (color2) && defined_color (f, SSDATA (color2), &cdef2, 0)))
+ && !(STRINGP (color2)
+ && defined_color (f, SSDATA (color2), &cdef2, false)))
signal_error ("Invalid color", color2);
return make_number (color_distance (&cdef1, &cdef2));
@@ -4502,7 +4413,7 @@ face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
face isn't realized and cannot be realized. */
int
-lookup_named_face (struct frame *f, Lisp_Object symbol, int signal_p)
+lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p)
{
Lisp_Object attrs[LFACE_VECTOR_SIZE];
Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4569,7 +4480,7 @@ lookup_basic_face (struct frame *f, int face_id)
/* If there is a remapping entry, lookup the face using NAME, which will
handle the remapping too. */
- remapped_face_id = lookup_named_face (f, name, 0);
+ remapped_face_id = lookup_named_face (f, name, false);
if (remapped_face_id < 0)
return face_id; /* Give up. */
@@ -4671,7 +4582,7 @@ face_with_height (struct frame *f, int face_id, int height)
int
lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id,
- int signal_p)
+ bool signal_p)
{
Lisp_Object attrs[LFACE_VECTOR_SIZE];
Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4697,7 +4608,7 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
Qunspecified);
merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents,
- 1, 0);
+ true, 0);
return lface;
}
@@ -4762,7 +4673,7 @@ x_supports_face_attributes_p (struct frame *f,
|| (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
&& face_attr_equal_p (attrs[LFACE_BOX_INDEX],
def_attrs[LFACE_BOX_INDEX])))
- return 0;
+ return false;
/* Check font-related attributes, as those are the most commonly
"unsupported" on a window-system (because of missing fonts). */
@@ -4792,7 +4703,7 @@ x_supports_face_attributes_p (struct frame *f,
supported. */
if (face->font == def_face->font
|| ! face->font)
- return 0;
+ return false;
for (i = FONT_TYPE_INDEX; i <= FONT_SIZE_INDEX; i++)
if (! EQ (face->font->props[i], def_face->font->props[i]))
{
@@ -4800,18 +4711,18 @@ x_supports_face_attributes_p (struct frame *f,
if (i < FONT_FOUNDRY_INDEX || i > FONT_REGISTRY_INDEX
|| face->font->driver->case_sensitive)
- return 1;
+ return true;
s1 = SYMBOL_NAME (face->font->props[i]);
s2 = SYMBOL_NAME (def_face->font->props[i]);
if (! EQ (Fcompare_strings (s1, make_number (0), Qnil,
s2, make_number (0), Qnil, Qt), Qt))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Everything checks out, this face is supported. */
- return 1;
+ return true;
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -4860,7 +4771,7 @@ tty_supports_face_attributes_p (struct frame *f,
|| !UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
|| !UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
|| !UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]))
- return 0;
+ return false;
/* Test for terminal `capabilities' (non-color character attributes). */
@@ -4874,17 +4785,17 @@ tty_supports_face_attributes_p (struct frame *f,
if (weight > 100)
{
if (def_weight > 100)
- return 0; /* same as default */
+ return false; /* same as default */
test_caps = TTY_CAP_BOLD;
}
else if (weight < 100)
{
if (def_weight < 100)
- return 0; /* same as default */
+ return false; /* same as default */
test_caps = TTY_CAP_DIM;
}
else if (def_weight == 100)
- return 0; /* same as default */
+ return false; /* same as default */
}
/* font slant */
@@ -4894,7 +4805,7 @@ tty_supports_face_attributes_p (struct frame *f,
{
int def_slant = FONT_SLANT_NAME_NUMERIC (def_attrs[LFACE_SLANT_INDEX]);
if (slant == 100 || slant == def_slant)
- return 0; /* same as default */
+ return false; /* same as default */
else
test_caps |= TTY_CAP_ITALIC;
}
@@ -4904,11 +4815,11 @@ tty_supports_face_attributes_p (struct frame *f,
if (!UNSPECIFIEDP (val))
{
if (STRINGP (val))
- return 0; /* ttys can't use colored underlines */
+ return false; /* ttys can't use colored underlines */
else if (EQ (CAR_SAFE (val), QCstyle) && EQ (CAR_SAFE (CDR_SAFE (val)), Qwave))
- return 0; /* ttys can't use wave underlines */
+ return false; /* ttys can't use wave underlines */
else if (face_attr_equal_p (val, def_attrs[LFACE_UNDERLINE_INDEX]))
- return 0; /* same as default */
+ return false; /* same as default */
else
test_caps |= TTY_CAP_UNDERLINE;
}
@@ -4918,7 +4829,7 @@ tty_supports_face_attributes_p (struct frame *f,
if (!UNSPECIFIEDP (val))
{
if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
- return 0; /* same as default */
+ return false; /* same as default */
else
test_caps |= TTY_CAP_INVERSE;
}
@@ -4933,12 +4844,12 @@ tty_supports_face_attributes_p (struct frame *f,
Lisp_Object def_fg = def_attrs[LFACE_FOREGROUND_INDEX];
if (face_attr_equal_p (fg, def_fg))
- return 0; /* same as default */
+ return false; /* same as default */
else if (! tty_lookup_color (f, fg, &fg_tty_color, &fg_std_color))
- return 0; /* not a valid color */
+ return false; /* not a valid color */
else if (color_distance (&fg_tty_color, &fg_std_color)
> TTY_SAME_COLOR_THRESHOLD)
- return 0; /* displayed color is too different */
+ return false; /* displayed color is too different */
else
/* Make sure the color is really different than the default. */
{
@@ -4946,7 +4857,7 @@ tty_supports_face_attributes_p (struct frame *f,
if (tty_lookup_color (f, def_fg, &def_fg_color, 0)
&& (color_distance (&fg_tty_color, &def_fg_color)
<= TTY_SAME_COLOR_THRESHOLD))
- return 0;
+ return false;
}
}
@@ -4957,12 +4868,12 @@ tty_supports_face_attributes_p (struct frame *f,
Lisp_Object def_bg = def_attrs[LFACE_BACKGROUND_INDEX];
if (face_attr_equal_p (bg, def_bg))
- return 0; /* same as default */
+ return false; /* same as default */
else if (! tty_lookup_color (f, bg, &bg_tty_color, &bg_std_color))
- return 0; /* not a valid color */
+ return false; /* not a valid color */
else if (color_distance (&bg_tty_color, &bg_std_color)
> TTY_SAME_COLOR_THRESHOLD)
- return 0; /* displayed color is too different */
+ return false; /* displayed color is too different */
else
/* Make sure the color is really different than the default. */
{
@@ -4970,7 +4881,7 @@ tty_supports_face_attributes_p (struct frame *f,
if (tty_lookup_color (f, def_bg, &def_bg_color, 0)
&& (color_distance (&bg_tty_color, &def_bg_color)
<= TTY_SAME_COLOR_THRESHOLD))
- return 0;
+ return false;
}
}
@@ -4985,7 +4896,7 @@ tty_supports_face_attributes_p (struct frame *f,
- color_distance (&fg_tty_color, &bg_tty_color));
if (delta_delta > TTY_SAME_COLOR_THRESHOLD
|| delta_delta < -TTY_SAME_COLOR_THRESHOLD)
- return 0;
+ return false;
}
@@ -5016,7 +4927,7 @@ satisfied by the tty display code's automatic substitution of a `dim'
face for italic. */)
(Lisp_Object attributes, Lisp_Object display)
{
- bool supports = 0;
+ bool supports = false;
int i;
Lisp_Object frame;
struct frame *f;
@@ -5051,7 +4962,7 @@ face for italic. */)
for (i = 0; i < LFACE_VECTOR_SIZE; i++)
attrs[i] = Qunspecified;
- merge_face_ref (f, attributes, attrs, 1, 0);
+ merge_face_ref (f, attributes, attrs, true, 0);
def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
if (def_face == NULL)
@@ -5093,14 +5004,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 +5033,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);
@@ -5229,7 +5140,7 @@ face_fontset (Lisp_Object attrs[LFACE_VECTOR_SIZE])
static bool
realize_basic_faces (struct frame *f)
{
- bool success_p = 0;
+ bool success_p = false;
ptrdiff_t count = SPECPDL_INDEX ();
/* Block input here so that we won't be surprised by an X expose
@@ -5259,14 +5170,14 @@ realize_basic_faces (struct frame *f)
/* Reflect changes in the `menu' face in menu bars. */
if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
{
- FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
+ FRAME_FACE_CACHE (f)->menu_face_changed_p = false;
#ifdef USE_X_TOOLKIT
if (FRAME_WINDOW_P (f))
x_update_menu_appearance (f);
#endif
}
- success_p = 1;
+ success_p = true;
}
unbind_to (count, Qnil);
@@ -5288,7 +5199,7 @@ realize_default_face (struct frame *f)
struct face *face;
/* If the `default' face is not yet known, create it. */
- lface = lface_from_face_name (f, Qdefault, 0);
+ lface = lface_from_face_name (f, Qdefault, false);
if (NILP (lface))
{
Lisp_Object frame;
@@ -5304,7 +5215,7 @@ realize_default_face (struct frame *f)
XSETFONT (font_object, FRAME_FONT (f));
set_lface_from_font (f, lface, font_object, f->default_face_done_p);
ASET (lface, LFACE_FONTSET_INDEX, fontset_name (FRAME_FONTSET (f)));
- f->default_face_done_p = 1;
+ f->default_face_done_p = true;
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -5346,7 +5257,7 @@ realize_default_face (struct frame *f)
if (CONSP (color) && STRINGP (XCDR (color)))
ASET (lface, LFACE_FOREGROUND_INDEX, XCDR (color));
else if (FRAME_WINDOW_P (f))
- return 0;
+ return false;
else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg));
else
@@ -5361,7 +5272,7 @@ realize_default_face (struct frame *f)
if (CONSP (color) && STRINGP (XCDR (color)))
ASET (lface, LFACE_BACKGROUND_INDEX, XCDR (color));
else if (FRAME_WINDOW_P (f))
- return 0;
+ return false;
else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg));
else
@@ -5384,7 +5295,7 @@ realize_default_face (struct frame *f)
/* This can happen when making a frame on a display that does
not support the default font. */
if (!face->font)
- return 0;
+ return false;
/* Otherwise, the font specified for the frame was not
acceptable as a font for the default face (perhaps because
@@ -5394,7 +5305,7 @@ realize_default_face (struct frame *f)
}
#endif /* HAVE_X_WINDOWS */
#endif /* HAVE_WINDOW_SYSTEM */
- return 1;
+ return true;
}
@@ -5406,12 +5317,12 @@ static void
realize_named_face (struct frame *f, Lisp_Object symbol, int id)
{
struct face_cache *c = FRAME_FACE_CACHE (f);
- Lisp_Object lface = lface_from_face_name (f, symbol, 0);
+ Lisp_Object lface = lface_from_face_name (f, symbol, false);
Lisp_Object attrs[LFACE_VECTOR_SIZE];
Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
/* The default face must exist and be fully specified. */
- get_lface_attributes_no_remap (f, Qdefault, attrs, 1);
+ get_lface_attributes_no_remap (f, Qdefault, attrs, true);
check_lface_attrs (attrs);
eassert (lface_fully_specified_p (attrs));
@@ -5424,7 +5335,7 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id)
}
/* Merge SYMBOL's face with the default face. */
- get_lface_attributes_no_remap (f, symbol, symbol_attrs, 1);
+ get_lface_attributes_no_remap (f, symbol, symbol_attrs, true);
merge_face_vectors (f, symbol_attrs, attrs, 0);
/* Realize the face. */
@@ -5490,14 +5401,13 @@ 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
&& FONT_WEIGHT_NUMERIC (font_object) <= 100);
/* Don't try to free the colors copied bitwise from BASE_FACE. */
- face->colors_copied_bitwise_p = 1;
+ face->colors_copied_bitwise_p = true;
face->font = NILP (font_object) ? NULL : XFONT_OBJECT (font_object);
face->gc = 0;
@@ -5565,7 +5475,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]);
@@ -5581,7 +5491,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
if (face->font
&& FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]) > 100
&& FONT_WEIGHT_NUMERIC (attrs[LFACE_FONT_INDEX]) <= 100)
- face->overstrike = 1;
+ face->overstrike = true;
/* Load colors, and set remaining attributes. */
@@ -5606,7 +5516,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
face->box = FACE_SIMPLE_BOX;
face->box_line_width = XINT (box);
face->box_color = face->foreground;
- face->box_color_defaulted_p = 1;
+ face->box_color_defaulted_p = true;
}
else if (CONSP (box))
{
@@ -5614,7 +5524,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
being one of `raised' or `sunken'. */
face->box = FACE_SIMPLE_BOX;
face->box_color = face->foreground;
- face->box_color_defaulted_p = 1;
+ face->box_color_defaulted_p = true;
face->box_line_width = 1;
while (CONSP (box))
@@ -5640,7 +5550,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
face->box_color = load_color (f, face, value,
LFACE_BOX_INDEX);
- face->use_box_color_for_shadows_p = 1;
+ face->use_box_color_for_shadows_p = true;
}
}
else if (EQ (keyword, QCstyle))
@@ -5659,34 +5569,34 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
if (EQ (underline, Qt))
{
/* Use default color (same as foreground color). */
- face->underline_p = 1;
+ face->underline_p = true;
face->underline_type = FACE_UNDER_LINE;
- face->underline_defaulted_p = 1;
+ face->underline_defaulted_p = true;
face->underline_color = 0;
}
else if (STRINGP (underline))
{
/* Use specified color. */
- face->underline_p = 1;
+ face->underline_p = true;
face->underline_type = FACE_UNDER_LINE;
- face->underline_defaulted_p = 0;
+ face->underline_defaulted_p = false;
face->underline_color
= load_color (f, face, underline,
LFACE_UNDERLINE_INDEX);
}
else if (NILP (underline))
{
- face->underline_p = 0;
- face->underline_defaulted_p = 0;
+ face->underline_p = false;
+ face->underline_defaulted_p = false;
face->underline_color = 0;
}
else if (CONSP (underline))
{
/* `(:color COLOR :style STYLE)'.
STYLE being one of `line' or `wave'. */
- face->underline_p = 1;
+ face->underline_p = true;
face->underline_color = 0;
- face->underline_defaulted_p = 1;
+ face->underline_defaulted_p = true;
face->underline_type = FACE_UNDER_LINE;
/* FIXME? This is also not robust about checking the precise form.
@@ -5707,12 +5617,12 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
if (EQ (value, Qforeground_color))
{
- face->underline_defaulted_p = 1;
+ face->underline_defaulted_p = true;
face->underline_color = 0;
}
else if (STRINGP (value))
{
- face->underline_defaulted_p = 0;
+ face->underline_defaulted_p = false;
face->underline_color = load_color (f, face, value,
LFACE_UNDERLINE_INDEX);
}
@@ -5733,13 +5643,13 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
face->overline_color
= load_color (f, face, attrs[LFACE_OVERLINE_INDEX],
LFACE_OVERLINE_INDEX);
- face->overline_p = 1;
+ face->overline_p = true;
}
else if (EQ (overline, Qt))
{
face->overline_color = face->foreground;
- face->overline_color_defaulted_p = 1;
- face->overline_p = 1;
+ face->overline_color_defaulted_p = true;
+ face->overline_p = true;
}
strike_through = attrs[LFACE_STRIKE_THROUGH_INDEX];
@@ -5748,13 +5658,13 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
face->strike_through_color
= load_color (f, face, attrs[LFACE_STRIKE_THROUGH_INDEX],
LFACE_STRIKE_THROUGH_INDEX);
- face->strike_through_p = 1;
+ face->strike_through_p = true;
}
else if (EQ (strike_through, Qt))
{
face->strike_through_color = face->foreground;
- face->strike_through_color_defaulted_p = 1;
- face->strike_through_p = 1;
+ face->strike_through_color_defaulted_p = true;
+ face->strike_through_p = true;
}
stipple = attrs[LFACE_STIPPLE_INDEX];
@@ -5768,15 +5678,15 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
/* Map a specified color of face FACE on frame F to a tty color index.
IDX is either LFACE_FOREGROUND_INDEX or LFACE_BACKGROUND_INDEX, and
- specifies which color to map. Set *DEFAULTED to 1 if mapping to the
+ specifies which color to map. Set *DEFAULTED to true if mapping to the
default foreground/background colors. */
static void
map_tty_color (struct frame *f, struct face *face,
- enum lface_attribute_index idx, int *defaulted)
+ enum lface_attribute_index idx, bool *defaulted)
{
Lisp_Object frame, color, def;
- int foreground_p = idx == LFACE_FOREGROUND_INDEX;
+ bool foreground_p = idx == LFACE_FOREGROUND_INDEX;
unsigned long default_pixel =
foreground_p ? FACE_TTY_DEFAULT_FG_COLOR : FACE_TTY_DEFAULT_BG_COLOR;
unsigned long pixel = default_pixel;
@@ -5818,7 +5728,7 @@ map_tty_color (struct frame *f, struct face *face,
else
pixel = FRAME_BACKGROUND_PIXEL (f);
face->lface[idx] = tty_color_name (f, pixel);
- *defaulted = 1;
+ *defaulted = true;
}
else if (pixel == default_other_pixel)
{
@@ -5827,7 +5737,7 @@ map_tty_color (struct frame *f, struct face *face,
else
pixel = FRAME_FOREGROUND_PIXEL (f);
face->lface[idx] = tty_color_name (f, pixel);
- *defaulted = 1;
+ *defaulted = true;
}
}
#endif /* MSDOS */
@@ -5850,7 +5760,7 @@ realize_tty_face (struct face_cache *cache,
{
struct face *face;
int weight, slant;
- int face_colors_defaulted = 0;
+ bool face_colors_defaulted = false;
struct frame *f = cache->f;
/* Frame must be a termcap frame. */
@@ -5858,7 +5768,7 @@ realize_tty_face (struct face_cache *cache,
/* Allocate a new realized face. */
face = make_realized_face (attrs);
-#if 0
+#if false
face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
#endif
@@ -5866,13 +5776,13 @@ realize_tty_face (struct face_cache *cache,
weight = FONT_WEIGHT_NAME_NUMERIC (attrs[LFACE_WEIGHT_INDEX]);
slant = FONT_SLANT_NAME_NUMERIC (attrs[LFACE_SLANT_INDEX]);
if (weight > 100)
- face->tty_bold_p = 1;
+ face->tty_bold_p = true;
if (slant != 100)
- face->tty_italic_p = 1;
+ face->tty_italic_p = true;
if (!NILP (attrs[LFACE_UNDERLINE_INDEX]))
- face->tty_underline_p = 1;
+ face->tty_underline_p = true;
if (!NILP (attrs[LFACE_INVERSE_INDEX]))
- face->tty_reverse_p = 1;
+ face->tty_reverse_p = true;
/* Map color names to color indices. */
map_tty_color (f, face, LFACE_FOREGROUND_INDEX, &face_colors_defaulted);
@@ -5892,7 +5802,7 @@ realize_tty_face (struct face_cache *cache,
&& face->tty_bold_p
&& face->background == FACE_TTY_DEFAULT_FG_COLOR
&& face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
- face->tty_bold_p = 0;
+ face->tty_bold_p = false;
return face;
}
@@ -5941,7 +5851,7 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop)
Lisp_Object attrs[LFACE_VECTOR_SIZE];
struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
memcpy (attrs, default_face->lface, sizeof attrs);
- merge_face_ref (f, prop, attrs, 1, 0);
+ merge_face_ref (f, prop, attrs, true, 0);
face_id = lookup_face (f, attrs);
}
@@ -5959,7 +5869,7 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop)
LIMIT is a position not to scan beyond. That is to limit the time
this function can take.
- If MOUSE is non-zero, use the character's mouse-face, not its face.
+ If MOUSE, use the character's mouse-face, not its face.
BASE_FACE_ID, if non-negative, specifies a base face id to use
instead of DEFAULT_FACE_ID.
@@ -5969,7 +5879,7 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop)
int
face_at_buffer_position (struct window *w, ptrdiff_t pos,
ptrdiff_t *endptr, ptrdiff_t limit,
- int mouse, int base_face_id)
+ bool mouse, int base_face_id)
{
struct frame *f = XFRAME (w->frame);
Lisp_Object attrs[LFACE_VECTOR_SIZE];
@@ -5998,10 +5908,11 @@ 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;
- GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, 0);
+ GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, false);
if (next_overlay < endpos)
endpos = next_overlay;
}
@@ -6024,14 +5935,17 @@ 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);
/* Merge in attributes specified via text properties. */
if (!NILP (prop))
- merge_face_ref (f, prop, attrs, 1, 0);
+ merge_face_ref (f, prop, attrs, true, 0);
/* Now merge the overlay data. */
noverlays = sort_overlays (overlay_vec, noverlays, w);
@@ -6042,7 +5956,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
prop = Foverlay_get (overlay_vec[i], propname);
if (!NILP (prop))
- merge_face_ref (f, prop, attrs, 1, 0);
+ merge_face_ref (f, prop, attrs, true, 0);
oend = OVERLAY_END (overlay_vec[i]);
oendpos = OVERLAY_POSITION (oend);
@@ -6052,6 +5966,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);
@@ -6066,7 +5982,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
int
face_for_overlay_string (struct window *w, ptrdiff_t pos,
ptrdiff_t *endptr, ptrdiff_t limit,
- int mouse, Lisp_Object overlay)
+ bool mouse, Lisp_Object overlay)
{
struct frame *f = XFRAME (w->frame);
Lisp_Object attrs[LFACE_VECTOR_SIZE];
@@ -6105,7 +6021,7 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos,
/* Merge in attributes specified via text properties. */
if (!NILP (prop))
- merge_face_ref (f, prop, attrs, 1, 0);
+ merge_face_ref (f, prop, attrs, true, 0);
*endptr = endpos;
@@ -6127,7 +6043,7 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos,
BASE_FACE_ID is the id of a face to merge with. For strings coming
from overlays or the `display' property it is the face at BUFPOS.
- If MOUSE_P is non-zero, use the character's mouse-face, not its face.
+ If MOUSE_P, use the character's mouse-face, not its face.
Set *ENDPTR to the next position where to check for faces in
STRING; -1 if the face is constant from POS to the end of the
@@ -6140,7 +6056,7 @@ int
face_at_string_position (struct window *w, Lisp_Object string,
ptrdiff_t pos, ptrdiff_t bufpos,
ptrdiff_t *endptr, enum face_id base_face_id,
- int mouse_p)
+ bool mouse_p)
{
Lisp_Object prop, position, end, limit;
struct frame *f = XFRAME (WINDOW_FRAME (w));
@@ -6185,7 +6101,7 @@ face_at_string_position (struct window *w, Lisp_Object string,
/* Merge in attributes specified via text properties. */
if (!NILP (prop))
- merge_face_ref (f, prop, attrs, 1, 0);
+ merge_face_ref (f, prop, attrs, true, 0);
/* Look up a realized face with the given face attributes,
or realize a new one for ASCII characters. */
@@ -6317,7 +6233,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 +6264,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");
@@ -6394,9 +6310,17 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
void
syms_of_xfaces (void)
{
+ /* The symbols `face' and `mouse-face' used as text properties. */
DEFSYM (Qface, "face");
+
+ /* Property for basic faces which other faces cannot inherit. */
DEFSYM (Qface_no_inherit, "face-no-inherit");
+
+ /* Error symbol for wrong_type_argument in load_pixmap. */
DEFSYM (Qbitmap_spec_p, "bitmap-spec-p");
+
+ /* The name of the function to call when the background of the frame
+ has changed, frame_set_background_mode. */
DEFSYM (Qframe_set_background_mode, "frame-set-background-mode");
/* Lisp face attribute keywords. */
@@ -6439,12 +6363,22 @@ syms_of_xfaces (void)
DEFSYM (Qultra_bold, "ultra-bold");
DEFSYM (Qoblique, "oblique");
DEFSYM (Qitalic, "italic");
+
+ /* The symbols `foreground-color' and `background-color' which can be
+ used as part of a `face' property. This is for compatibility with
+ Emacs 20.2. */
DEFSYM (Qbackground_color, "background-color");
DEFSYM (Qforeground_color, "foreground-color");
+
DEFSYM (Qunspecified, "unspecified");
DEFSYM (QCignore_defface, ":ignore-defface");
+ /* The symbol `face-alias'. A symbol having that property is an
+ alias for another face. Value of the property is the name of
+ the aliased face. */
DEFSYM (Qface_alias, "face-alias");
+
+ /* Names of basic faces. */
DEFSYM (Qdefault, "default");
DEFSYM (Qtool_bar, "tool-bar");
DEFSYM (Qregion, "region");
@@ -6457,13 +6391,23 @@ syms_of_xfaces (void)
DEFSYM (Qmouse, "mouse");
DEFSYM (Qmode_line_inactive, "mode-line-inactive");
DEFSYM (Qvertical_border, "vertical-border");
+
+ /* TTY color-related functions (defined in tty-colors.el). */
DEFSYM (Qwindow_divider, "window-divider");
DEFSYM (Qwindow_divider_first_pixel, "window-divider-first-pixel");
DEFSYM (Qwindow_divider_last_pixel, "window-divider-last-pixel");
DEFSYM (Qtty_color_desc, "tty-color-desc");
DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
DEFSYM (Qtty_color_by_index, "tty-color-by-index");
+
+ /* The name of the function used to compute colors on TTYs. */
DEFSYM (Qtty_color_alist, "tty-color-alist");
+
+ /* Allowed scalable fonts. A value of nil means don't allow any
+ scalable fonts. A value of t means allow the use of any scalable
+ font. Otherwise, value must be a list of regular expressions. A
+ font may be scaled if its name matches a regular expression in the
+ list. */
DEFSYM (Qscalable_fonts_allowed, "scalable-fonts-allowed");
Vparam_value_alist = list1 (Fcons (Qnil, Qnil));
diff --git a/src/xfns.c b/src/xfns.c
index a9192c8431d..9dd00868d7b 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"
@@ -45,12 +46,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/stat.h>
-#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
#include "bitmaps/gray.xbm"
-#else
-#include <X11/bitmaps/gray>
-#endif
-
#include "xsettings.h"
#ifdef HAVE_XRANDR
@@ -124,11 +120,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;
-
#ifdef GLYPH_DEBUG
static ptrdiff_t image_cache_refcount;
static int dpyinfo_refcount;
@@ -159,7 +150,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);
@@ -186,7 +177,7 @@ x_real_positions (struct frame *f, int *xptr, int *yptr)
{
int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
int real_x = 0, real_y = 0;
- int had_errors = 0;
+ bool had_errors = false;
Window win = f->output_data.x->parent_desc;
Atom actual_type;
unsigned long actual_size, bytes_remaining;
@@ -329,8 +320,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. */
@@ -355,7 +381,7 @@ bool
x_defined_color (struct frame *f, const char *color_name,
XColor *color, bool alloc_p)
{
- bool success_p = 0;
+ bool success_p = false;
Display *dpy = FRAME_X_DISPLAY (f);
Colormap cmap = FRAME_X_COLORMAP (f);
@@ -384,9 +410,9 @@ x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
CHECK_STRING (color_name);
-#if 0 /* Don't do this. It's wrong when we're not using the default
- colormap, it makes freeing difficult, and it's probably not
- an important optimization. */
+#if false /* Don't do this. It's wrong when we're not using the default
+ colormap, it makes freeing difficult, and it's probably not
+ an important optimization. */
if (strcmp (SDATA (color_name), "black") == 0)
return BLACK_PIX_DEFAULT (f);
else if (strcmp (SDATA (color_name), "white") == 0)
@@ -399,7 +425,7 @@ x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
/* x_defined_color is responsible for coping with failures
by looking for a near-miss. */
- if (x_defined_color (f, SSDATA (color_name), &cdef, 1))
+ if (x_defined_color (f, SSDATA (color_name), &cdef, true))
return cdef.pixel;
signal_error ("Undefined color", color_name);
@@ -422,15 +448,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
@@ -438,10 +472,10 @@ x_set_tool_bar_position (struct frame *f,
/* Set icon from FILE for frame F. By using GTK functions the icon
may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
-int
+bool
xg_set_icon (struct frame *f, Lisp_Object file)
{
- int result = 0;
+ bool result = false;
Lisp_Object found;
found = x_find_image_file (file);
@@ -461,7 +495,7 @@ xg_set_icon (struct frame *f, Lisp_Object file)
pixbuf);
g_object_unref (pixbuf);
- result = 1;
+ result = true;
}
else
g_error_free (err);
@@ -472,17 +506,17 @@ xg_set_icon (struct frame *f, Lisp_Object file)
return result;
}
-int
+bool
xg_set_icon_from_xpm_data (struct frame *f, const char **data)
{
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
if (!pixbuf)
- return 0;
+ return false;
gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
g_object_unref (pixbuf);
- return 1;
+ return true;
}
#endif /* USE_GTK */
@@ -577,35 +611,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 +728,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);
@@ -771,20 +773,20 @@ static void
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
unsigned long fore_pixel, pixel;
- bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
+ bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
struct x_output *x = f->output_data.x;
if (!NILP (Vx_cursor_fore_pixel))
{
fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
WHITE_PIX_DEFAULT (f));
- fore_pixel_allocated_p = 1;
+ fore_pixel_allocated_p = true;
}
else
fore_pixel = FRAME_BACKGROUND_PIXEL (f);
pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
- pixel_allocated_p = 1;
+ pixel_allocated_p = true;
/* Make sure that the cursor color differs from the background color. */
if (pixel == FRAME_BACKGROUND_PIXEL (f))
@@ -792,7 +794,7 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (pixel_allocated_p)
{
x_free_colors (f, &pixel, 1);
- pixel_allocated_p = 0;
+ pixel_allocated_p = false;
}
pixel = x->mouse_pixel;
@@ -801,7 +803,7 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (fore_pixel_allocated_p)
{
x_free_colors (f, &fore_pixel, 1);
- fore_pixel_allocated_p = 0;
+ fore_pixel_allocated_p = false;
}
fore_pixel = FRAME_BACKGROUND_PIXEL (f);
}
@@ -826,8 +828,8 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (FRAME_VISIBLE_P (f))
{
- x_update_cursor (f, 0);
- x_update_cursor (f, 1);
+ x_update_cursor (f, false);
+ x_update_cursor (f, true);
}
}
@@ -887,7 +889,7 @@ x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
static void
x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int result;
+ bool result;
if (STRINGP (arg))
{
@@ -919,7 +921,7 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
static void
x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int result;
+ bool result;
if (STRINGP (arg))
{
@@ -954,7 +956,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;
@@ -985,7 +987,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
FRAME_EXTERNAL_MENU_BAR (f) = 1;
if (FRAME_X_P (f) && f->output_data.x->menubar_widget == 0)
/* Make sure next redisplay shows the menu bar. */
- XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = 1;
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
}
else
{
@@ -998,7 +1000,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, true, Qmenu_bar_lines);
if (FRAME_X_WINDOW (f))
x_clear_under_internal_border (f);
@@ -1049,14 +1051,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,57 +1066,46 @@ 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;
+ FRAME_EXTERNAL_TOOL_BAR (f) = true;
if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
/* Make sure next redisplay shows the tool bar. */
- XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = 1;
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
update_frame_tool_bar (f);
}
else
{
if (FRAME_EXTERNAL_TOOL_BAR (f))
free_frame_tool_bar (f);
- FRAME_EXTERNAL_TOOL_BAR (f) = 0;
+ FRAME_EXTERNAL_TOOL_BAR (f) = false;
}
-
#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;
+ /* 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 +1119,58 @@ 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,
+ (!f->tool_bar_redisplayed_once ? 1
+ : (old_height == 0 || height == 0) ? 2
+ : 4),
+ false, Qtool_bar_lines);
+
+ /* adjust_frame_size might not have done anything, garbage frame
+ here. */
+ adjust_frame_glyphs (f);
+ SET_FRAME_GARBAGED (f);
+ 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, false, Qinternal_border_width);
- 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 +1225,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 +1237,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,20 +1264,16 @@ 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,
+ If the text contains only ASCII and Latin-1, store true in *STRING_P,
which means that the `encoding' of the result can be `STRING'.
- Otherwise store 0 in *STRINGP, which means that the `encoding' of
+ Otherwise store false in *STRINGP, which means that the `encoding' of
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, bool *stringp, bool *freep)
{
int result = string_xstring_p (string);
struct coding_system coding;
@@ -1271,8 +1282,8 @@ x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp,
{
/* No multibyte character in OBJ. We need not encode it. */
*text_bytes = SBYTES (string);
- *stringp = 1;
- *freep = 0;
+ *stringp = true;
+ *freep = false;
return SDATA (string);
}
@@ -1286,7 +1297,7 @@ x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp,
SCHARS (string), SBYTES (string), Qnil);
*text_bytes = coding.produced;
*stringp = (result == 1 || !EQ (coding_system, Qcompound_text));
- *freep = 1;
+ *freep = true;
return coding.destination;
}
@@ -1304,8 +1315,8 @@ 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 stringp;
+ bool do_free_icon_value = false, do_free_text_value = false;
Lisp_Object coding_system;
Lisp_Object encoded_name;
Lisp_Object encoded_icon_name;
@@ -1337,14 +1348,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 +1363,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 +1406,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. */
@@ -1457,7 +1464,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
static void
x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- x_set_name (f, arg, 1);
+ x_set_name (f, arg, true);
}
/* This function should be called by Emacs redisplay code to set the
@@ -1466,7 +1473,7 @@ x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
void
x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- x_set_name (f, arg, 0);
+ x_set_name (f, arg, false);
}
/* Change the title of frame F to NAME.
@@ -1505,14 +1512,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
@@ -1523,7 +1552,7 @@ static Lisp_Object
x_default_scroll_bar_color_parameter (struct frame *f,
Lisp_Object alist, Lisp_Object prop,
const char *xprop, const char *xclass,
- int foreground_p)
+ bool foreground_p)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Lisp_Object tem;
@@ -1535,13 +1564,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 +1589,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;
}
@@ -1578,9 +1609,9 @@ hack_wm_protocols (struct frame *f, Widget widget)
{
Display *dpy = XtDisplay (widget);
Window w = XtWindow (widget);
- int need_delete = 1;
- int need_focus = 1;
- int need_save = 1;
+ bool need_delete = true;
+ bool need_focus = true;
+ bool need_save = true;
block_input ();
{
@@ -1592,7 +1623,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)
@@ -1604,20 +1635,20 @@ hack_wm_protocols (struct frame *f, Widget widget)
nitems--;
if (atoms[nitems]
== FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window)
- need_delete = 0;
+ need_delete = false;
else if (atoms[nitems]
== FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus)
- need_focus = 0;
+ need_focus = false;
else if (atoms[nitems]
== FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
- need_save = 0;
+ need_save = false;
}
}
if (catoms)
XFree (catoms);
}
{
- Atom props [10];
+ Atom props[10];
int count = 0;
if (need_delete)
props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window;
@@ -1669,17 +1700,18 @@ static const char xic_default_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
/* Create an Xt fontset spec from the name of a base font.
If `motif' is True use the Motif syntax. */
char *
-xic_create_fontsetname (const char *base_fontname, int motif)
+xic_create_fontsetname (const char *base_fontname, bool motif)
{
const char *sep = motif ? ";" : ",";
char *fontsetname;
+ char *z;
/* Make a fontset name from the base font name. */
if (xic_default_fontset == base_fontname)
{
/* There is no base font name, use the default. */
fontsetname = xmalloc (strlen (base_fontname) + 2);
- strcpy (fontsetname, base_fontname);
+ z = stpcpy (fontsetname, base_fontname);
}
else
{
@@ -1700,9 +1732,9 @@ xic_create_fontsetname (const char *base_fontname, int motif)
Use the specified font plus the default. */
fontsetname = xmalloc (strlen (base_fontname)
+ strlen (xic_default_fontset) + 3);
- strcpy (fontsetname, base_fontname);
- strcat (fontsetname, sep);
- strcat (fontsetname, xic_default_fontset);
+ z = stpcpy (fontsetname, base_fontname);
+ z = stpcpy (z, sep);
+ z = stpcpy (z, xic_default_fontset);
}
else
{
@@ -1750,7 +1782,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,31 +1790,31 @@ 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;
font_all = alloca (len);
- strcpy (font_all, allfamilies);
- strcat (font_all, all);
- memcpy (font_all + strlen (all) + strlen (allfamilies), p2, p - p2);
- strcat (font_all, allcs);
+ z = stpcpy (font_all, allfamilies);
+ z = stpcpy (z, all);
+ memcpy (z, p2, p - p2);
+ strcpy (z + (p - p2), allcs);
/* Build the actual font set name. */
len = strlen (base_fontname) + strlen (font_allcs)
+ strlen (font_allfamilies) + strlen (font_all) + 5;
fontsetname = xmalloc (len);
- strcpy (fontsetname, base_fontname);
- strcat (fontsetname, sep);
- strcat (fontsetname, font_allcs);
- strcat (fontsetname, sep);
- strcat (fontsetname, font_allfamilies);
- strcat (fontsetname, sep);
- strcat (fontsetname, font_all);
+ z = stpcpy (fontsetname, base_fontname);
+ z = stpcpy (z, sep);
+ z = stpcpy (z, font_allcs);
+ z = stpcpy (z, sep);
+ z = stpcpy (z, font_allfamilies);
+ z = stpcpy (z, sep);
+ z = stpcpy (z, font_all);
}
}
if (motif)
- return strcat (fontsetname, ":");
+ strcpy (z, ":");
return fontsetname;
}
#endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
@@ -1910,7 +1942,7 @@ void
xic_free_xfontset (struct frame *f)
{
Lisp_Object rest, frame;
- bool shared_p = 0;
+ bool shared_p = false;
if (!FRAME_XIC_FONTSET (f))
return;
@@ -1923,7 +1955,7 @@ xic_free_xfontset (struct frame *f)
&& FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f)
&& FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
{
- shared_p = 1;
+ shared_p = true;
break;
}
}
@@ -1944,8 +1976,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)
@@ -2184,7 +2215,7 @@ xic_set_xfontset (struct frame *f, const char *base_fontname)
/* Create and set up the X widget for frame F. */
static void
-x_window (struct frame *f, long window_prompting, int minibuffer_only)
+x_window (struct frame *f, long window_prompting)
{
XClassHint class_hints;
XSetWindowAttributes attributes;
@@ -2192,7 +2223,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
Widget shell_widget;
Widget pane_widget;
Widget frame_widget;
- Arg al [25];
+ Arg al[25];
int ac;
block_input ();
@@ -2202,7 +2233,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
for the window manager, so GC relocation won't bother it.
Elsewhere we specify the window name for the window manager. */
- f->namebuf = xstrdup (SSDATA (Vx_resource_name));
+ f->namebuf = xlispstrdup (Vx_resource_name);
ac = 0;
XtSetArg (al[ac], XtNallowShellResize, 1); ac++;
@@ -2253,8 +2284,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
@@ -2263,8 +2293,8 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
+ f->output_data.x->menubar_widget->core.border_width)
: 0);
-#if 0 /* Experimentally, we now get the right results
- for -geometry -0-0 without this. 24 Aug 96, rms. */
+#if false /* Experimentally, we now get the right results
+ for -geometry -0-0 without this. 24 Aug 96, rms. */
if (FRAME_EXTERNAL_MENU_BAR (f))
{
Dimension ibw = 0;
@@ -2273,7 +2303,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 +2314,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
@@ -2291,23 +2323,23 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
We pass that information later, in x_wm_set_size_hints. */
{
int left = f->left_pos;
- int xneg = window_prompting & XNegative;
+ bool xneg = (window_prompting & XNegative) != 0;
int top = f->top_pos;
- int yneg = window_prompting & YNegative;
+ bool yneg = (window_prompting & YNegative) != 0;
if (xneg)
left = -left;
if (yneg)
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 +2353,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,9 +2422,9 @@ 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;
+ f->explicit_name = false;
name = f->name;
fset_name (f, Qnil);
x_set_name (f, name, explicit);
@@ -2509,10 +2536,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,9 +2561,9 @@ 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;
+ f->explicit_name = false;
name = f->name;
fset_name (f, Qnil);
x_set_name (f, name, explicit);
@@ -2586,15 +2609,12 @@ x_icon_verify (struct frame *f, Lisp_Object parms)
static void
x_icon (struct frame *f, Lisp_Object parms)
{
- Lisp_Object icon_x, icon_y;
-#if 0
- struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-#endif
-
/* Set the position of the icon. Note that twm groups all
icons in an icon window. */
- icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
- icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
+ Lisp_Object icon_x
+ = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
+ Lisp_Object icon_y
+ = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
{
CHECK_TYPE_RANGED_INTEGER (int, icon_x);
@@ -2608,9 +2628,10 @@ x_icon (struct frame *f, Lisp_Object parms)
if (! EQ (icon_x, Qunbound))
x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
-#if 0 /* x_get_arg removes the visibility parameter as a side effect,
- but x_create_frame still needs it. */
+#if false /* x_get_arg removes the visibility parameter as a side effect,
+ but x_create_frame still needs it. */
/* Start up iconic or window? */
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
x_wm_set_window_state
(f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
Qicon)
@@ -2762,12 +2783,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 +2840,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. */
@@ -2843,7 +2859,7 @@ Signal error if FRAME is not an X frame. */)
struct frame *f = decode_window_system_frame (frame);
block_input ();
- x_wm_set_size_hint (f, 0, 0);
+ x_wm_set_size_hint (f, 0, false);
unblock_input ();
return Qnil;
}
@@ -2851,29 +2867,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)
@@ -2881,10 +2899,9 @@ This function is an internal primitive--use `make-frame' instead. */)
struct frame *f;
Lisp_Object frame, tem;
Lisp_Object name;
- int minibuffer_only = 0;
+ bool minibuffer_only = false;
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;
@@ -2936,12 +2953,12 @@ This function is an internal primitive--use `make-frame' instead. */)
else if (EQ (tem, Qonly))
{
f = make_minibuffer_frame ();
- minibuffer_only = 1;
+ minibuffer_only = true;
}
else if (WINDOWP (tem))
f = make_frame_without_minibuffer (tem, kb, display);
else
- f = make_frame (1);
+ f = make_frame (true);
XSETFRAME (frame, f);
@@ -2953,10 +2970,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,16 +3022,15 @@ 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);
- f->output_data.x->explicit_parent = 1;
+ f->output_data.x->explicit_parent = true;
}
else
{
f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
- f->output_data.x->explicit_parent = 0;
+ f->output_data.x->explicit_parent = false;
}
/* Set the name; the functions to which we pass f expect the name to
@@ -3022,13 +3038,13 @@ This function is an internal primitive--use `make-frame' instead. */)
if (EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->x_id_name));
- f->explicit_name = 0;
+ f->explicit_name = false;
}
else
{
fset_name (f, name);
- f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
+ f->explicit_name = true;
+ /* Use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
@@ -3091,7 +3107,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);
@@ -3112,10 +3130,10 @@ This function is an internal primitive--use `make-frame' instead. */)
x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
"scrollBarForeground",
- "ScrollBarForeground", 1);
+ "ScrollBarForeground", true);
x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
"scrollBarBackground",
- "ScrollBarBackground", 0);
+ "ScrollBarBackground", false);
#ifdef GLYPH_DEBUG
image_cache_refcount =
@@ -3123,32 +3141,23 @@ 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, true,
+ Qx_create_frame_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 +3173,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,12 +3181,12 @@ 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);
+ window_prompting = x_figure_window_size (f, parms, true);
tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
@@ -3188,7 +3195,7 @@ This function is an internal primitive--use `make-frame' instead. */)
/* Create the X widget or window. */
#ifdef USE_X_TOOLKIT
- x_window (f, window_prompting, minibuffer_only);
+ x_window (f, window_prompting);
#else
x_window (f);
#endif
@@ -3215,17 +3222,17 @@ 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->can_x_set_window_size = true;
+
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, true,
+ Qx_create_frame_2);
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Create the menu bar. */
@@ -3249,7 +3256,7 @@ This function is an internal primitive--use `make-frame' instead. */)
badly we want them. This should be done after we have the menu
bar so that its size can be taken into account. */
block_input ();
- x_wm_set_size_hint (f, window_prompting, 0);
+ x_wm_set_size_hint (f, window_prompting, false);
unblock_input ();
/* Make the window appear on the frame and enable display, unless
@@ -3378,7 +3385,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
CHECK_STRING (color);
- if (x_defined_color (f, SSDATA (color), &foo, 0))
+ if (x_defined_color (f, SSDATA (color), &foo, false))
return Qt;
else
return Qnil;
@@ -3393,7 +3400,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
CHECK_STRING (color);
- if (x_defined_color (f, SSDATA (color), &foo, 0))
+ if (x_defined_color (f, SSDATA (color), &foo, false))
return list3i (foo.red, foo.green, foo.blue);
else
return Qnil;
@@ -4209,6 +4216,124 @@ Internal use only, use `display-monitor-attributes-list' instead. */)
return attributes_list;
}
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+ doc: /* Return geometric attributes of frame FRAME.
+
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is an association list containing the following
+elements (all size values are in pixels).
+
+- `frame-outer-size' is a cons of the outer width and height of FRAME.
+ The outer size include the title bar and the external borders as well
+ as any menu and/or tool bar of frame.
+
+- `border' is a cons of the horizontal and vertical width of FRAME's
+ external borders.
+
+- `title-bar-height' is the height of the title bar of FRAME.
+
+- `menu-bar-external' if `t' means the menu bar is external (not
+ included in the inner edges of FRAME).
+
+- `menu-bar-size' is a cons of the width and height of the menu bar of
+ FRAME.
+
+- `tool-bar-external' if `t' means the tool bar is external (not
+ included in the inner edges of FRAME).
+
+- `tool-bar-side' tells tells on which side the tool bar on FRAME is and
+ can be one of `left', `top', `right' or `bottom'.
+
+- `tool-bar-size' is a cons of the width and height of the tool bar of
+ FRAME.
+
+- `frame-inner-size' is a cons of the inner width and height of FRAME.
+ This excludes FRAME's title bar and external border as well as any
+ external menu and/or tool bar. */)
+ (Lisp_Object frame)
+{
+ struct frame *f = decode_live_frame (frame);
+ int inner_width = FRAME_PIXEL_WIDTH (f);
+ int inner_height = FRAME_PIXEL_HEIGHT (f);
+ int outer_width, outer_height, border, title;
+ Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
+ int menu_bar_height, menu_bar_width, tool_bar_height, tool_bar_width;
+
+ border = FRAME_OUTER_TO_INNER_DIFF_X (f);
+ title = FRAME_X_OUTPUT (f)->y_pixels_outer_diff - border;
+
+ outer_width = FRAME_PIXEL_WIDTH (f) + 2 * border;
+ outer_height = (FRAME_PIXEL_HEIGHT (f)
+ + FRAME_OUTER_TO_INNER_DIFF_Y (f)
+ + FRAME_OUTER_TO_INNER_DIFF_X (f));
+
+#if defined (USE_GTK)
+ {
+ bool tool_bar_left_right = (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft)
+ || EQ (FRAME_TOOL_BAR_POSITION (f), Qright));
+
+ tool_bar_width = (tool_bar_left_right
+ ? FRAME_TOOLBAR_WIDTH (f)
+ : FRAME_PIXEL_WIDTH (f));
+ tool_bar_height = (tool_bar_left_right
+ ? FRAME_PIXEL_HEIGHT (f)
+ : FRAME_TOOLBAR_HEIGHT (f));
+ if (tool_bar_left_right)
+ /* For some reason FRAME_OUTER_TO_INNER_DIFF_X does not count the
+ width of a tool bar. */
+ outer_width += FRAME_TOOLBAR_WIDTH (f);
+ }
+#else
+ tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
+ tool_bar_width = ((tool_bar_height > 0)
+ ? outer_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)
+ : 0);
+#endif
+
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+ menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
+#else
+ menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+#endif
+
+ menu_bar_width = ((menu_bar_height > 0)
+ ? outer_width - 2 * border
+ : 0);
+
+ if (!FRAME_EXTERNAL_MENU_BAR (f))
+ inner_height -= menu_bar_height;
+ if (!FRAME_EXTERNAL_TOOL_BAR (f))
+ inner_height -= tool_bar_height;
+
+ return
+ listn (CONSTYPE_PURE, 10,
+ Fcons (Qframe_position,
+ Fcons (make_number (f->left_pos), make_number (f->top_pos))),
+ Fcons (Qframe_outer_size,
+ Fcons (make_number (outer_width), make_number (outer_height))),
+ Fcons (Qexternal_border_size,
+ ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+ ? Fcons (make_number (0), make_number (0))
+ : Fcons (make_number (border), make_number (border)))),
+ Fcons (Qtitle_height,
+ ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+ ? make_number (0)
+ : make_number (title))),
+ Fcons (Qmenu_bar_external, FRAME_EXTERNAL_MENU_BAR (f) ? Qt : Qnil),
+ Fcons (Qmenu_bar_size,
+ Fcons (make_number (menu_bar_width),
+ make_number (menu_bar_height))),
+ Fcons (Qtool_bar_external, FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
+ Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
+ Fcons (Qtool_bar_size,
+ Fcons (make_number (tool_bar_width),
+ make_number (tool_bar_height))),
+ Fcons (Qframe_inner_size,
+ Fcons (make_number (inner_width),
+ make_number (inner_height))));
+}
+
/************************************************************************
X Displays
************************************************************************/
@@ -4263,13 +4388,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 +4405,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 +4707,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 +4771,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 +4783,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;
}
-}
+ 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);
+ }
-/* Hide the hourglass pointer on all frames, if it is currently
- shown. */
-
-void
-hide_hourglass (void)
-{
- if (hourglass_shown_p)
+ 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))
{
- Lisp_Object rest, frame;
+ prop_value = x_window_property_intern (f,
+ FRAME_OUTER_WINDOW (f),
+ prop_atom,
+ target_type,
+ delete_p,
+ vector_ret_p,
+ &found);
+ }
- block_input ();
- FOR_EACH_FRAME (rest, frame)
- {
- struct frame *f = XFRAME (frame);
- 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
***********************************************************************/
@@ -4882,13 +4939,14 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
frame = Qnil;
GCPRO3 (parms, name, frame);
- f = make_frame (1);
+ f = make_frame (true);
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);
+ set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false);
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (buffer));
bset_truncate_lines (current_buffer, Qnil);
@@ -4912,17 +4970,17 @@ 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;
fset_icon_name (f, Qnil);
FRAME_DISPLAY_INFO (f) = dpyinfo;
f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
- f->output_data.x->explicit_parent = 0;
+ f->output_data.x->explicit_parent = false;
/* These colors will be set anyway later, but it's important
to get the color reference counts right, so initialize them! */
@@ -4962,12 +5020,12 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
if (EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->x_id_name));
- f->explicit_name = 0;
+ f->explicit_name = false;
}
else
{
fset_name (f, name);
- f->explicit_name = 1;
+ f->explicit_name = true;
/* use the frame's title when getting resources for this frame. */
specbind (Qx_resource_name, name);
}
@@ -5031,17 +5089,14 @@ 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;
- x_figure_window_size (f, parms, 0);
+ x_figure_window_size (f, parms, false);
{
XSetWindowAttributes attrs;
@@ -5093,12 +5148,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;
- change_frame_size (f, width, height, 1, 0, 0, 0);
+ SET_FRAME_LINES (f, 0);
+ change_frame_size (f, width, height, true, false, false, false);
/* 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 +5174,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,10 +5196,13 @@ 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;
+ f->no_split = true;
UNGCPRO;
@@ -5151,7 +5215,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->can_x_set_window_size = true;
/* Setting attributes of faces of the tooltip frame from resources
and similar will increment face_change_count, which leads to the
@@ -5256,7 +5320,8 @@ Text larger than the specified size is clipped. */)
int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
- int i, width, height, seen_reversed_p;
+ int i, width, height;
+ bool seen_reversed_p;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t count = SPECPDL_INDEX ();
@@ -5394,7 +5459,7 @@ Text larger than the specified size is clipped. */)
FRAME_TOTAL_COLS (f) = w->total_cols;
adjust_frame_glyphs (f);
- w->pseudo_window_p = 1;
+ w->pseudo_window_p = true;
/* Display the tooltip text in a temporary buffer. */
old_buffer = current_buffer;
@@ -5406,7 +5471,8 @@ Text larger than the specified size is clipped. */)
try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
/* Compute width and height of the tooltip. */
- width = height = seen_reversed_p = 0;
+ width = height = 0;
+ seen_reversed_p = false;
for (i = 0; i < w->desired_matrix->nrows; ++i)
{
struct glyph_row *row = &w->desired_matrix->rows[i];
@@ -5418,7 +5484,7 @@ Text larger than the specified size is clipped. */)
break;
/* Let the row go over the full width of the frame. */
- row->full_width_p = 1;
+ row->full_width_p = true;
row_width = row->pixel_width;
if (row->used[TEXT_AREA])
@@ -5428,7 +5494,7 @@ Text larger than the specified size is clipped. */)
if (!row->reversed_p)
{
last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (INTEGERP (last->object))
+ if (NILP (last->object))
row_width -= last->pixel_width;
}
else
@@ -5438,10 +5504,10 @@ Text larger than the specified size is clipped. */)
Don't count that glyph. */
struct glyph *g = row->glyphs[TEXT_AREA];
- if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
+ if (g->type == STRETCH_GLYPH && NILP (g->object))
{
row_width -= g->pixel_width;
- seen_reversed_p = 1;
+ seen_reversed_p = true;
}
}
}
@@ -5477,12 +5543,12 @@ Text larger than the specified size is clipped. */)
if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
break;
- row->full_width_p = 1;
+ row->full_width_p = true;
row_width = row->pixel_width;
if (row->used[TEXT_AREA] && !row->reversed_p)
{
last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- if (INTEGERP (last->object))
+ if (NILP (last->object))
row_width -= last->pixel_width;
}
@@ -5507,8 +5573,8 @@ Text larger than the specified size is clipped. */)
unblock_input ();
/* Draw into the window. */
- w->must_be_updated_p = 1;
- update_single_window (w, 1);
+ w->must_be_updated_p = true;
+ update_single_window (w);
/* Restore original current buffer. */
set_buffer_internal_1 (old_buffer);
@@ -5644,7 +5710,7 @@ clean_up_file_dialog (void *arg)
block_input ();
XtUnmanageChild (dialog);
XtDestroyWidget (dialog);
- x_menu_set_in_use (0);
+ x_menu_set_in_use (false);
unblock_input ();
}
@@ -5768,7 +5834,7 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
record_unwind_protect_ptr (clean_up_file_dialog, dialog);
/* Process events until the user presses Cancel or OK. */
- x_menu_set_in_use (1);
+ x_menu_set_in_use (true);
result = 0;
while (result == 0)
{
@@ -5822,7 +5888,7 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
static void
clean_up_dialog (void)
{
- x_menu_set_in_use (0);
+ x_menu_set_in_use (false);
}
DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
@@ -5924,12 +5990,12 @@ nil, it defaults to the selected frame. */)
XSETFONT (font, FRAME_FONT (f));
font_param = Ffont_get (font, intern (":name"));
if (STRINGP (font_param))
- default_name = xstrdup (SSDATA (font_param));
+ default_name = xlispstrdup (font_param);
else
{
font_param = Fframe_parameter (frame, Qfont_param);
if (STRINGP (font_param))
- default_name = xstrdup (SSDATA (font_param));
+ default_name = xlispstrdup (font_param);
}
font = xg_get_font (f, default_name);
@@ -6035,7 +6101,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 +6147,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 +6171,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));
@@ -6120,7 +6187,7 @@ Changing the value does not affect existing frames
unless you set the mouse color. */);
Vx_pointer_shape = Qnil;
-#if 0 /* This doesn't really do anything. */
+#if false /* This doesn't really do anything. */
DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
doc: /* The shape of the pointer when not over text.
This variable takes effect when you create a new frame
@@ -6134,7 +6201,7 @@ This variable takes effect when you create a new frame
or when you set the mouse color. */);
Vx_hourglass_pointer_shape = Qnil;
-#if 0 /* This doesn't really do anything. */
+#if false /* This doesn't really do anything. */
DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
doc: /* The shape of the pointer when over the mode line.
This variable takes effect when you create a new frame
@@ -6196,31 +6263,25 @@ Chinese, Japanese, and Korean. */);
If nil or if the file selection dialog is not available, the new GTK file
chooser is used instead. To turn off all file dialogs set the
variable `use-file-dialog'. */);
- x_gtk_use_old_file_dialog = 0;
+ x_gtk_use_old_file_dialog = false;
DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
doc: /* If non-nil, the GTK file chooser will by default show hidden files.
Note that this is just the default, there is a toggle button on the file
chooser to show or not show hidden files on a case by case basis. */);
- x_gtk_show_hidden_files = 0;
+ x_gtk_show_hidden_files = false;
DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
doc: /* If non-nil, the GTK file chooser will show additional help text.
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;
+ x_gtk_file_dialog_help_text = true;
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.
When using Gtk+ tooltips, the tooltip face is not used. */);
- x_gtk_use_system_tooltips = 1;
+ x_gtk_use_system_tooltips = true;
/* Tell Emacs about this window system. */
Fprovide (Qx, Qnil);
@@ -6251,7 +6312,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
int len = sprintf (gtk_version, "%d.%d.%d",
GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
- Vgtk_version_string = make_pure_string (gtk_version, len, len, 0);
+ Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
}
#endif /* USE_GTK */
@@ -6278,6 +6339,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
defsubr (&Sx_display_backing_store);
defsubr (&Sx_display_save_under);
defsubr (&Sx_display_monitor_attributes_list);
+ defsubr (&Sx_frame_geometry);
defsubr (&Sx_wm_set_size_hint);
defsubr (&Sx_create_frame);
defsubr (&Sx_open_connection);
diff --git a/src/xfont.c b/src/xfont.c
index c9c017fe9d9..3a0f5e39b4e 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -121,18 +121,18 @@ 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 *);
struct font_driver xfont_driver =
{
LISP_INITIALLY_ZERO, /* Qx */
- 0, /* case insensitive */
+ false, /* case insensitive */
xfont_get_cache,
xfont_list,
xfont_match,
@@ -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 */
@@ -269,7 +269,7 @@ xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
}
return (i >= 0);
}
- return 0;
+ return false;
}
/* A hash table recoding which font supports which scripts. Each key
@@ -386,7 +386,7 @@ xfont_list_pattern (Display *display, const char *pattern,
{
char **indices = alloca (sizeof (char *) * num_fonts);
Lisp_Object *props = XVECTOR (xfont_scratch_props)->contents;
- Lisp_Object scripts = Qnil;
+ Lisp_Object scripts = Qnil, entity = Qnil;
for (i = 0; i < ASIZE (xfont_scratch_props); i++)
ASET (xfont_scratch_props, i, Qnil);
@@ -397,11 +397,11 @@ xfont_list_pattern (Display *display, const char *pattern,
for (i = 0; i < num_fonts; i++)
{
ptrdiff_t len;
- Lisp_Object entity;
if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
continue;
- entity = font_make_entity ();
+ if (NILP (entity))
+ entity = font_make_entity ();
len = xfont_decode_coding_xlfd (indices[i], -1, buf);
if (font_parse_xlfd (buf, len, entity) < 0)
continue;
@@ -459,7 +459,7 @@ xfont_list_pattern (Display *display, const char *pattern,
{
if (NILP (script)
|| xfont_chars_supported (chars, NULL, encoding, repertory))
- list = Fcons (entity, list);
+ list = Fcons (entity, list), entity = Qnil;
continue;
}
if (memcmp (props, aref_addr (entity, FONT_FOUNDRY_INDEX),
@@ -474,7 +474,7 @@ xfont_list_pattern (Display *display, const char *pattern,
}
if (NILP (script)
|| ! NILP (Fmemq (script, scripts)))
- list = Fcons (entity, list);
+ list = Fcons (entity, list), entity = Qnil;
}
XFreeFontNames (names);
}
@@ -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,16 +975,15 @@ 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++)
+ for (i = 0, first = true; i < nglyphs; i++)
{
XChar2b char2b;
static XCharStruct *pcm;
@@ -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;
- }
- first = 0;
+ metrics->lbearing = pcm->lbearing;
+ metrics->rbearing = pcm->rbearing;
+ metrics->ascent = pcm->ascent;
+ metrics->descent = pcm->descent;
+ first = false;
}
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
@@ -1118,13 +1106,7 @@ void
syms_of_xfont (void)
{
staticpro (&xfont_scripts_cache);
- { /* Here we rely on the fact that syms_of_xfont (via syms_of_font)
- is called fairly late, when QCtest and Qequal are known to be set. */
- Lisp_Object args[2];
- args[0] = QCtest;
- args[1] = Qequal;
- xfont_scripts_cache = Fmake_hash_table (2, args);
- }
+ xfont_scripts_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
staticpro (&xfont_scratch_props);
xfont_scratch_props = Fmake_vector (make_number (8), Qnil);
xfont_driver.type = Qx;
diff --git a/src/xftfont.c b/src/xftfont.c
index 2f05eee5b86..0e8b876f1d3 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -38,9 +38,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Xft font driver. */
-Lisp_Object Qxft;
-static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
- QClcdfilter;
/* The actual structure for Xft font that can be cast to struct
font. */
@@ -88,7 +85,7 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
else
{
XGCValues xgcv;
- bool fg_done = 0, bg_done = 0;
+ bool fg_done = false, bg_done = false;
block_input ();
XGetGCValues (FRAME_X_DISPLAY (f), gc,
@@ -96,15 +93,15 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
if (xftface_info)
{
if (xgcv.foreground == face->foreground)
- *fg = xftface_info->xft_fg, fg_done = 1;
+ *fg = xftface_info->xft_fg, fg_done = true;
else if (xgcv.foreground == face->background)
- *fg = xftface_info->xft_bg, fg_done = 1;
+ *fg = xftface_info->xft_bg, fg_done = true;
if (! bg)
- bg_done = 1;
+ bg_done = true;
else if (xgcv.background == face->background)
- *bg = xftface_info->xft_bg, bg_done = 1;
+ *bg = xftface_info->xft_bg, bg_done = true;
else if (xgcv.background == face->foreground)
- *bg = xftface_info->xft_fg, bg_done = 1;
+ *bg = xftface_info->xft_fg, bg_done = true;
}
if (! (fg_done & bg_done))
@@ -270,8 +267,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 +318,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 +337,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;
@@ -459,7 +434,7 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
font->baseline_offset = 0;
font->relative_compose = 0;
font->default_ascent = 0;
- font->vertical_centering = 0;
+ font->vertical_centering = false;
#ifdef FT_BDF_H
if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
{
@@ -507,27 +482,24 @@ xftfont_close (struct font *font)
}
}
-static int
+static void
xftfont_prepare_face (struct frame *f, struct face *face)
{
struct xftface_info *xftface_info;
-#if 0
+#if false
/* This doesn't work if face->ascii_face doesn't use an Xft font. */
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
@@ -535,7 +507,7 @@ xftfont_done_face (struct frame *f, struct face *face)
{
struct xftface_info *xftface_info;
-#if 0
+#if false
/* This doesn't work if face->ascii_face doesn't use an Xft font. */
if (face != face->ascii_face
|| ! face->extra)
@@ -545,7 +517,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 +554,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 +565,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 +587,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;
}
@@ -670,13 +640,11 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
static Lisp_Object
xftfont_shape (Lisp_Object lgstring)
{
- struct font *font;
- struct xftfont_info *xftfont_info;
+ struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
+ struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
FT_Face ft_face;
Lisp_Object val;
- CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
- xftfont_info = (struct xftfont_info *) font;
ft_face = XftLockFace (xftfont_info->xftfont);
xftfont_info->ft_size = ft_face->size;
val = ftfont_driver.shape (lgstring);
@@ -693,14 +661,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;
}
@@ -714,7 +682,7 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
Display *display = FRAME_X_DISPLAY (f);
FcPattern *pat = FcPatternCreate ();
FcBool b1, b2;
- bool ok = 0;
+ bool ok = false;
int i1, i2, r1, r2;
xftfont_add_rendering_parameters (pat, entity);
@@ -744,7 +712,7 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
if (r1 != r2 || i1 != i2) goto out;
- ok = 1;
+ ok = true;
out:
FcPatternDestroy (pat);
return ok;
diff --git a/src/xgselect.c b/src/xgselect.c
index 9b938892618..0b62d3e8255 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -50,13 +50,13 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
struct timespec const *tmop = timeout;
GMainContext *context;
- int have_wfds = wfds != NULL;
+ bool 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;
bool context_acquired = false;
- int i, nfds, tmo_in_millisec = -1;
+ int i, nfds, tmo_in_millisec;
bool need_to_dispatch;
USE_SAFE_ALLOCA;
@@ -96,13 +96,13 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
{
FD_SET (gfds[i].fd, &all_wfds);
if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
- have_wfds = 1;
+ have_wfds = true;
}
}
SAFE_FREE ();
- if (tmo_in_millisec >= 0)
+ if (n_gfds >= 0 && tmo_in_millisec >= 0)
{
tmo = make_timespec (tmo_in_millisec / 1000,
1000 * 1000 * (tmo_in_millisec % 1000));
diff --git a/src/xmenu.c b/src/xmenu.c
index 53683c708f1..fdf1f6f4d84 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -104,16 +104,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "menu.h"
-#ifndef TRUE
-#define TRUE 1
-#endif /* no TRUE */
-
-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. */
@@ -122,7 +112,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 +134,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
@@ -199,7 +142,7 @@ mouse_position_for_popup (struct frame *f, int *x, int *y)
/* Set menu_items_inuse so no other popup menu or dialog is created. */
void
-x_menu_set_in_use (int in_use)
+x_menu_set_in_use (bool in_use)
{
menu_items_inuse = in_use ? Qt : Qnil;
popup_activated_flag = in_use;
@@ -213,9 +156,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)
{
@@ -278,7 +218,8 @@ x_menu_wait_for_event (void *data)
with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
static void
-popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, LWLIB_ID id, int do_timers)
+popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
+ LWLIB_ID id, bool do_timers)
{
XEvent event;
@@ -343,13 +284,13 @@ If FRAME is nil or not given, use the selected frame. */)
block_input ();
if (FRAME_EXTERNAL_MENU_BAR (f))
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
menubar = FRAME_X_OUTPUT (f)->menubar_widget;
if (menubar)
{
Window child;
- bool error_p = 0;
+ bool error_p = false;
x_catch_errors (FRAME_X_DISPLAY (f));
memset (&ev, 0, sizeof ev);
@@ -422,7 +363,7 @@ If FRAME is nil or not given, use the selected frame. */)
f = decode_window_system_frame (frame);
if (FRAME_EXTERNAL_MENU_BAR (f))
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
menubar = FRAME_X_OUTPUT (f)->menubar_widget;
if (menubar)
@@ -446,7 +387,7 @@ If FRAME is nil or not given, use the selected frame. */)
Used for popup menus and dialogs. */
static void
-popup_widget_loop (int do_timers, GtkWidget *widget)
+popup_widget_loop (bool do_timers, GtkWidget *widget)
{
++popup_activated_flag;
@@ -487,7 +428,7 @@ x_activate_menubar (struct frame *f)
return;
#endif
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
block_input ();
popup_activated_flag = 1;
#ifdef USE_GTK
@@ -544,24 +485,7 @@ show_help_event (struct frame *f, xt_or_gtk_widget widget, Lisp_Object help)
kbd_buffer_store_help_event (frame, help);
}
else
- {
-#if 0 /* This code doesn't do anything useful. ++kfs */
- /* WIDGET is the popup menu. It's parent is the frame's
- widget. See which frame that is. */
- xt_or_gtk_widget frame_widget = XtParent (widget);
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- frame = XCAR (tail);
- if (FRAMEP (frame)
- && (f = XFRAME (frame),
- FRAME_X_P (f) && f->output_data.x->widget == frame_widget))
- break;
- }
-#endif
- show_help_echo (help, Qnil, Qnil, Qnil);
- }
+ show_help_echo (help, Qnil, Qnil, Qnil);
}
/* Callback called when menu items are highlighted/unhighlighted
@@ -610,7 +534,7 @@ menu_highlight_callback (Widget widget, LWLIB_ID id, void *call_data)
selected in a radio group. If this variable is set to a non-zero
value, we are creating menus and don't want callbacks right now.
*/
-static int xg_crazy_callback_abort;
+static bool xg_crazy_callback_abort;
/* This callback is called from the menu bar pulldown menu
when the user makes a selection.
@@ -682,7 +606,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 +615,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,10 +635,16 @@ 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. */
+ int new_height = -1;
+#ifdef USE_LUCID
+ /* For reasons I don't know Lucid wants to add one pixel to the frame
+ height when adding the menu bar. Compensate that here. */
+ new_height = FRAME_TEXT_HEIGHT (f) - 1;
+#endif /* USE_LUCID */
+ adjust_frame_size (f, -1, new_height, 2, false, Qmenu_bar_lines);
unblock_input ();
-#endif
+#endif /* USE_GTK */
}
#ifdef USE_LUCID
@@ -760,7 +685,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 +698,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);
@@ -784,21 +709,15 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
#endif
if (! menubar_widget)
- deep_p = 1;
+ deep_p = true;
/* Make the first call for any given frame always go deep. */
else if (!f->output_data.x->saved_menu_event && !deep_p)
{
- deep_p = 1;
+ deep_p = true;
f->output_data.x->saved_menu_event = xmalloc (sizeof (XEvent));
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 +806,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++)
@@ -905,7 +820,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
else
first_wv->contents = wv;
/* Don't set wv->name here; GC during the loop might relocate it. */
- wv->enabled = 1;
+ wv->enabled = true;
wv->button_type = BUTTON_TYPE_NONE;
prev_wv = wv;
}
@@ -957,12 +872,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 +885,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.
@@ -1004,7 +911,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
block_input ();
#ifdef USE_GTK
- xg_crazy_callback_abort = 1;
+ xg_crazy_callback_abort = true;
if (menubar_widget)
{
/* The fourth arg is DEEP_P, which says to consider the entire
@@ -1053,7 +960,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
menubar_widget = lw_create_widget ("menubar", "menubar", id,
first_wv,
f->output_data.x->column_widget,
- 0,
+ false,
popup_activate_callback,
menubar_selection_callback,
popup_deactivate_callback,
@@ -1075,11 +982,11 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
+ f->output_data.x->menubar_widget->core.border_width)
: 0);
-#if 1 /* Experimentally, we now get the right results
+#ifdef USE_LUCID
+ /* Experimentally, we now get the right results
for -geometry -0-0 without this. 24 Aug 96, rms.
Maybe so, but the menu bar size is missing the pixels so the
WM size hints are off by these pixels. Jan D, oct 2009. */
-#ifdef USE_LUCID
if (FRAME_EXTERNAL_MENU_BAR (f))
{
Dimension ibw = 0;
@@ -1088,9 +995,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
menubar_size += ibw;
}
#endif /* USE_LUCID */
-#endif /* 1 */
- f->output_data.x->menubar_height = menubar_size;
+ FRAME_MENUBAR_HEIGHT (f) = menubar_size;
}
#endif /* not USE_GTK */
@@ -1098,7 +1004,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
update_frame_menubar (f);
#ifdef USE_GTK
- xg_crazy_callback_abort = 0;
+ xg_crazy_callback_abort = false;
#endif
unblock_input ();
@@ -1115,7 +1021,7 @@ initialize_frame_menubar (struct frame *f)
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
- set_frame_menubar (f, 1, 1);
+ set_frame_menubar (f, true, true);
}
@@ -1128,12 +1034,18 @@ void
free_frame_menubar (struct frame *f)
{
Widget menubar_widget;
+#ifdef USE_MOTIF
+ /* Motif automatically shrinks the frame in lw_destroy_all_widgets.
+ If we want to preserve the old height, calculate it now so we can
+ restore it below. */
+ int old_height = FRAME_TEXT_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
+#endif
eassert (FRAME_X_P (f));
menubar_widget = f->output_data.x->menubar_widget;
- f->output_data.x->menubar_height = 0;
+ FRAME_MENUBAR_HEIGHT (f) = 0;
if (menubar_widget)
{
@@ -1161,13 +1073,24 @@ free_frame_menubar (struct frame *f)
if (f->output_data.x->widget)
{
+ int new_height = -1;
#ifdef USE_MOTIF
XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
if (x1 == 0 && y1 == 0)
XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
+ if (frame_inhibit_resize (f, false, Qmenu_bar_lines))
+ new_height = old_height;
+#endif /* USE_MOTIF */
+ adjust_frame_size (f, -1, new_height, 2, false, Qmenu_bar_lines);
+ }
+ else
+ {
+#ifdef USE_MOTIF
+ if (frame_inhibit_resize (f, false, Qmenu_bar_lines))
+ adjust_frame_size (f, -1, old_height, 1, false, Qmenu_bar_lines);
#endif
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
}
+
unblock_input ();
}
}
@@ -1175,16 +1098,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.
@@ -1273,17 +1197,17 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
#ifdef HAVE_GTK3
/* Always use position function for Gtk3. Otherwise menus may become
too small to show anything. */
- use_pos_func = 1;
+ use_pos_func = true;
#endif
eassert (FRAME_X_P (f));
- xg_crazy_callback_abort = 1;
+ xg_crazy_callback_abort = true;
menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
G_CALLBACK (popup_selection_callback),
G_CALLBACK (popup_deactivate_callback),
G_CALLBACK (menu_highlight_callback));
- xg_crazy_callback_abort = 0;
+ xg_crazy_callback_abort = false;
if (use_pos_func)
{
@@ -1324,7 +1248,7 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
two. show_help_echo uses this to detect popup menus. */
popup_activated_flag = 1;
/* Process events that apply to the menu. */
- popup_widget_loop (1, menu);
+ popup_widget_loop (true, menu);
}
unbind_to (specpdl_count, Qnil);
@@ -1339,8 +1263,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 +1276,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;
}
@@ -1390,14 +1310,14 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
menu_id = widget_id_tick++;
menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
- f->output_data.x->widget, 1, 0,
+ f->output_data.x->widget, true, 0,
popup_selection_callback,
popup_deactivate_callback,
menu_highlight_callback);
event->type = ButtonPress;
event->serial = 0;
- event->send_event = 0;
+ event->send_event = false;
event->display = FRAME_X_DISPLAY (f);
event->time = CurrentTime;
event->root = FRAME_DISPLAY_INFO (f)->root_window;
@@ -1428,14 +1348,12 @@ 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);
+ popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, true);
unbind_to (specpdl_count, Qnil);
}
@@ -1450,8 +1368,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;
@@ -1461,8 +1379,6 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
= alloca (menu_items_used * sizeof *subprefix_stack);
int submenu_depth = 0;
- int first_pane;
-
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_X_P (f));
@@ -1479,14 +1395,10 @@ 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;
+ bool first_pane = true;
/* Loop over all panes and items, filling in the tree. */
i = 0;
@@ -1497,14 +1409,14 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
- first_pane = 1;
+ first_pane = true;
i++;
}
else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
- first_pane = 0;
+ first_pane = false;
i++;
}
else if (EQ (AREF (menu_items, i), Qt)
@@ -1540,20 +1452,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;
}
@@ -1562,7 +1470,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
save_wv = wv;
prev_wv = 0;
}
- first_pane = 0;
+ first_pane = false;
i += MENU_ITEMS_PANE_LENGTH;
}
else
@@ -1591,20 +1499,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 +1523,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 +1532,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 +1558,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 +1600,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 +1618,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. */
@@ -1770,7 +1665,7 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
gtk_widget_show_all (menu);
/* Process events that apply to the menu. */
- popup_widget_loop (1, menu);
+ popup_widget_loop (true, menu);
unbind_to (specpdl_count, Qnil);
}
@@ -1807,7 +1702,7 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
apply_systemfont_to_dialog (f->output_data.x->widget);
#endif
lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
- f->output_data.x->widget, 1, 0,
+ f->output_data.x->widget, true, 0,
dialog_selection_callback, 0, 0);
lw_modify_all_widgets (dialog_id, first_wv->contents, True);
/* Display the dialog box. */
@@ -1819,14 +1714,12 @@ 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)))));
- popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
+ record_unwind_protect_int (pop_down_menu, (int) dialog_id);
+
+ popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, true);
unbind_to (count, Qnil);
}
@@ -1839,11 +1732,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];
@@ -1852,8 +1742,8 @@ xdialog_show (struct frame *f,
/* Number of elements seen so far, before boundary. */
int left_count = 0;
- /* 1 means we've seen the boundary between left-hand elts and right-hand. */
- int boundary_seen = 0;
+ /* Whether we've seen the boundary between left-hand elts and right-hand. */
+ bool boundary_seen = false;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
@@ -1870,19 +1760,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. */
@@ -1907,7 +1790,7 @@ xdialog_show (struct frame *f,
{
/* This is the boundary between left-side elts
and right-side elts. Stop incrementing right_count. */
- boundary_seen = 1;
+ boundary_seen = true;
i++;
continue;
}
@@ -1918,15 +1801,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 +1822,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 +1861,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 +1879,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 +1916,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 +1954,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 +1996,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 +2025,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 +2038,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,16 +2073,15 @@ 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);
+ lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, true);
if (lpane == XM_FAILURE)
{
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 +2125,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 +2143,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 +2192,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
@@ -2340,8 +2201,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
y += 1.5*height/(maxlines+2);
}
- XMenuSetAEQ (menu, TRUE);
- XMenuSetFreeze (menu, TRUE);
+ XMenuSetAEQ (menu, true);
+ XMenuSetFreeze (menu, true);
pane = selidx = 0;
#ifndef MSDOS
@@ -2356,7 +2217,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 +2246,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 +2268,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 +2276,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 */
@@ -2427,7 +2288,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
/* Detect if a dialog or menu has been posted. MSDOS has its own
implementation on msdos.c. */
-int ATTRIBUTE_CONST
+int
popup_activated (void)
{
return popup_activated_flag;
@@ -2446,13 +2307,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/xml.c b/src/xml.c
index b5223ab12e6..e32417724ce 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -29,64 +29,70 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "buffer.h"
-static Lisp_Object Qlibxml2_dll;
-
#ifdef WINDOWSNT
-#include <windows.h>
-#include "w32.h"
-
-/* Macro for defining functions that will be loaded from the libxml2 DLL. */
-#define DEF_XML2_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
+# include <windows.h>
+# include "w32.h"
-/* Macro for loading libxml2 functions from the library. */
-#define LOAD_XML2_FN(lib,func) { \
- fn_##func = (void *) GetProcAddress (lib, #func); \
- if (!fn_##func) goto bad_library; \
- }
-
-DEF_XML2_FN (htmlDocPtr, htmlReadMemory,
+DEF_DLL_FN (htmlDocPtr, htmlReadMemory,
(const char *, int, const char *, const char *, int));
-DEF_XML2_FN (xmlDocPtr, xmlReadMemory,
+DEF_DLL_FN (xmlDocPtr, xmlReadMemory,
(const char *, int, const char *, const char *, int));
-DEF_XML2_FN (xmlNodePtr, xmlDocGetRootElement, (xmlDocPtr));
-DEF_XML2_FN (void, xmlFreeDoc, (xmlDocPtr));
-DEF_XML2_FN (void, xmlCleanupParser, (void));
-DEF_XML2_FN (void, xmlCheckVersion, (int));
+DEF_DLL_FN (xmlNodePtr, xmlDocGetRootElement, (xmlDocPtr));
+DEF_DLL_FN (void, xmlFreeDoc, (xmlDocPtr));
+DEF_DLL_FN (void, xmlCleanupParser, (void));
+DEF_DLL_FN (void, xmlCheckVersion, (int));
-static int
+static bool
libxml2_loaded_p (void)
{
Lisp_Object found = Fassq (Qlibxml2_dll, Vlibrary_cache);
- if (CONSP (found))
- return EQ (XCDR (found), Qt) ? 1 : 0;
- return 0;
+ return CONSP (found) && EQ (XCDR (found), Qt);
}
-#else /* !WINDOWSNT */
+# undef htmlReadMemory
+# undef xmlCheckVersion
+# undef xmlCleanupParser
+# undef xmlDocGetRootElement
+# undef xmlFreeDoc
+# undef xmlReadMemory
+
+# define htmlReadMemory fn_htmlReadMemory
+# define xmlCheckVersion fn_xmlCheckVersion
+# define xmlCleanupParser fn_xmlCleanupParser
+# define xmlDocGetRootElement fn_xmlDocGetRootElement
+# define xmlFreeDoc fn_xmlFreeDoc
+# define xmlReadMemory fn_xmlReadMemory
+
+static bool
+load_dll_functions (HMODULE library)
+{
+ LOAD_DLL_FN (library, htmlReadMemory);
+ LOAD_DLL_FN (library, xmlReadMemory);
+ LOAD_DLL_FN (library, xmlDocGetRootElement);
+ LOAD_DLL_FN (library, xmlFreeDoc);
+ LOAD_DLL_FN (library, xmlCleanupParser);
+ LOAD_DLL_FN (library, xmlCheckVersion);
+ return true;
+}
-#define fn_htmlReadMemory htmlReadMemory
-#define fn_xmlReadMemory xmlReadMemory
-#define fn_xmlDocGetRootElement xmlDocGetRootElement
-#define fn_xmlFreeDoc xmlFreeDoc
-#define fn_xmlCleanupParser xmlCleanupParser
-#define fn_xmlCheckVersion xmlCheckVersion
+#else /* !WINDOWSNT */
-static int
+static bool
libxml2_loaded_p (void)
{
- return 1;
+ return true;
}
#endif /* !WINDOWSNT */
-static int
+static bool
init_libxml2_functions (void)
{
#ifdef WINDOWSNT
if (libxml2_loaded_p ())
- return 1;
+ return true;
else
{
HMODULE library;
@@ -94,28 +100,22 @@ init_libxml2_functions (void)
if (!(library = w32_delayed_load (Qlibxml2_dll)))
{
message1 ("libxml2 library not found");
- return 0;
+ return false;
}
- /* LOAD_XML2_FN jumps to bad_library if it fails to find the
- named function. */
- LOAD_XML2_FN (library, htmlReadMemory);
- LOAD_XML2_FN (library, xmlReadMemory);
- LOAD_XML2_FN (library, xmlDocGetRootElement);
- LOAD_XML2_FN (library, xmlFreeDoc);
- LOAD_XML2_FN (library, xmlCleanupParser);
- LOAD_XML2_FN (library, xmlCheckVersion);
+ if (! load_dll_functions (library))
+ goto bad_library;
Vlibrary_cache = Fcons (Fcons (Qlibxml2_dll, Qt), Vlibrary_cache);
- return 1;
+ return true;
}
bad_library:
Vlibrary_cache = Fcons (Fcons (Qlibxml2_dll, Qnil), Vlibrary_cache);
- return 0;
+ return false;
#else /* !WINDOWSNT */
- return 1;
+ return true;
#endif /* !WINDOWSNT */
}
@@ -175,14 +175,15 @@ make_dom (xmlNode *node)
}
static Lisp_Object
-parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int htmlp)
+parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url,
+ Lisp_Object discard_comments, bool htmlp)
{
xmlDoc *doc;
Lisp_Object result = Qnil;
const char *burl = "";
ptrdiff_t istart, iend, istart_byte, iend_byte;
- fn_xmlCheckVersion (LIBXML_VERSION);
+ xmlCheckVersion (LIBXML_VERSION);
validate_region (&start, &end);
@@ -201,42 +202,45 @@ parse_region (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, int html
}
if (htmlp)
- doc = fn_htmlReadMemory ((char *) BYTE_POS_ADDR (istart_byte),
- iend_byte - istart_byte, burl, "utf-8",
- HTML_PARSE_RECOVER|HTML_PARSE_NONET|
- HTML_PARSE_NOWARNING|HTML_PARSE_NOERROR|
- HTML_PARSE_NOBLANKS);
+ doc = htmlReadMemory ((char *) BYTE_POS_ADDR (istart_byte),
+ iend_byte - istart_byte, burl, "utf-8",
+ HTML_PARSE_RECOVER|HTML_PARSE_NONET|
+ HTML_PARSE_NOWARNING|HTML_PARSE_NOERROR|
+ HTML_PARSE_NOBLANKS);
else
- doc = fn_xmlReadMemory ((char *) BYTE_POS_ADDR (istart_byte),
- iend_byte - istart_byte, burl, "utf-8",
- XML_PARSE_NONET|XML_PARSE_NOWARNING|
- XML_PARSE_NOBLANKS |XML_PARSE_NOERROR);
+ doc = xmlReadMemory ((char *) BYTE_POS_ADDR (istart_byte),
+ iend_byte - istart_byte, burl, "utf-8",
+ XML_PARSE_NONET|XML_PARSE_NOWARNING|
+ XML_PARSE_NOBLANKS |XML_PARSE_NOERROR);
if (doc != NULL)
{
- /* If the document is just comments, then this should get us the
- nodes anyway. */
- xmlNode *n = doc->children->next;
Lisp_Object r = Qnil;
-
- while (n) {
- if (!NILP (r))
- result = Fcons (r, result);
- r = make_dom (n);
- n = n->next;
- }
+ if (NILP(discard_comments))
+ {
+ /* If the document has toplevel comments, then this should
+ get us the nodes and the comments. */
+ xmlNode *n = doc->children;
+
+ while (n) {
+ if (!NILP (r))
+ result = Fcons (r, result);
+ r = make_dom (n);
+ n = n->next;
+ }
+ }
if (NILP (result)) {
- /* The document isn't just comments, so get the tree the
- proper way. */
- xmlNode *node = fn_xmlDocGetRootElement (doc);
+ /* The document doesn't have toplevel comments or we discarded
+ them. Get the tree the proper way. */
+ xmlNode *node = xmlDocGetRootElement (doc);
if (node != NULL)
result = make_dom (node);
} else
result = Fcons (intern ("top"),
Fcons (Qnil, Fnreverse (Fcons (r, result))));
- fn_xmlFreeDoc (doc);
+ xmlFreeDoc (doc);
}
return result;
@@ -246,30 +250,32 @@ void
xml_cleanup_parser (void)
{
if (libxml2_loaded_p ())
- fn_xmlCleanupParser ();
+ xmlCleanupParser ();
}
DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region,
Slibxml_parse_html_region,
- 2, 3, 0,
+ 2, 4, 0,
doc: /* Parse the region as an HTML document and return the parse tree.
-If BASE-URL is non-nil, it is used to expand relative URLs. */)
- (Lisp_Object start, Lisp_Object end, Lisp_Object base_url)
+If BASE-URL is non-nil, it is used to expand relative URLs.
+If DISCARD-COMMENTS is non-nil, all HTML comments are discarded. */)
+ (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, Lisp_Object discard_comments)
{
if (init_libxml2_functions ())
- return parse_region (start, end, base_url, 1);
+ return parse_region (start, end, base_url, discard_comments, true);
return Qnil;
}
DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region,
Slibxml_parse_xml_region,
- 2, 3, 0,
+ 2, 4, 0,
doc: /* Parse the region as an XML document and return the parse tree.
-If BASE-URL is non-nil, it is used to expand relative URLs. */)
- (Lisp_Object start, Lisp_Object end, Lisp_Object base_url)
+If BASE-URL is non-nil, it is used to expand relative URLs.
+If DISCARD-COMMENTS is non-nil, all HTML comments are discarded. */)
+ (Lisp_Object start, Lisp_Object end, Lisp_Object base_url, Lisp_Object discard_comments)
{
if (init_libxml2_functions ())
- return parse_region (start, end, base_url, 0);
+ return parse_region (start, end, base_url, discard_comments, false);
return Qnil;
}
diff --git a/src/xrdb.c b/src/xrdb.c
index 7a91eb8ff24..9e85e5a6277 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -232,9 +232,10 @@ gethomedir (void)
if (ptr == NULL)
return xstrdup ("/");
- copy = xmalloc (strlen (ptr) + 2);
- strcpy (copy, ptr);
- return strcat (copy, "/");
+ ptrdiff_t len = strlen (ptr);
+ copy = xmalloc (len + 2);
+ strcpy (copy + len, "/");
+ return memcpy (copy, ptr, len);
}
@@ -334,6 +335,7 @@ get_user_app (const char *class)
return db;
}
+static char const xdefaults[] = ".Xdefaults";
static XrmDatabase
get_user_db (Display *display)
@@ -351,16 +353,12 @@ get_user_db (Display *display)
db = XrmGetStringDatabase (xdefs);
else
{
- char *home;
- char *xdefault;
-
- home = gethomedir ();
- xdefault = xmalloc (strlen (home) + sizeof ".Xdefaults");
- strcpy (xdefault, home);
- strcat (xdefault, ".Xdefaults");
- db = XrmGetFileDatabase (xdefault);
- xfree (home);
- xfree (xdefault);
+ char *home = gethomedir ();
+ ptrdiff_t homelen = strlen (home);
+ char *filename = xrealloc (home, homelen + sizeof xdefaults);
+ strcpy (filename + homelen, xdefaults);
+ db = XrmGetFileDatabase (filename);
+ xfree (filename);
}
#ifdef HAVE_XSCREENRESOURCESTRING
@@ -380,24 +378,23 @@ static XrmDatabase
get_environ_db (void)
{
XrmDatabase db;
- char *p;
- char *path = 0;
+ char *p = getenv ("XENVIRONMENT");
+ char *filename = 0;
- if ((p = getenv ("XENVIRONMENT")) == NULL)
+ if (!p)
{
- static char const xdefaults[] = ".Xdefaults-";
char *home = gethomedir ();
- char const *host = SSDATA (Vsystem_name);
- ptrdiff_t pathsize = (strlen (home) + sizeof xdefaults
- + SBYTES (Vsystem_name));
- path = xrealloc (home, pathsize);
- strcat (strcat (path, xdefaults), host);
- p = path;
+ ptrdiff_t homelen = strlen (home);
+ Lisp_Object system_name = Fsystem_name ();
+ ptrdiff_t filenamesize = (homelen + sizeof xdefaults
+ + SBYTES (system_name));
+ p = filename = xrealloc (home, filenamesize);
+ lispstpcpy (stpcpy (filename + homelen, xdefaults), system_name);
}
db = XrmGetFileDatabase (p);
- xfree (path);
+ xfree (filename);
return db;
}
@@ -452,6 +449,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 +500,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 */
@@ -664,7 +667,7 @@ main (int argc, char **argv)
/* In a real program, you'd want to also do this: */
display->db = xdb;
- while (1)
+ while (true)
{
char query_name[90];
char query_class[90];
diff --git a/src/xselect.c b/src/xselect.c
index ac980dc1e30..027192dfea2 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -46,22 +46,22 @@ struct prop_location;
struct selection_data;
static void x_decline_selection_request (struct input_event *);
-static int x_convert_selection (struct input_event *, Lisp_Object, Lisp_Object,
- Atom, int, struct x_display_info *);
-static int waiting_for_other_props_on_window (Display *, Window);
+static bool x_convert_selection (struct input_event *, Lisp_Object,
+ Lisp_Object, Atom, bool,
+ struct x_display_info *);
+static bool waiting_for_other_props_on_window (Display *, Window);
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. */
@@ -80,30 +80,10 @@ static void lisp_data_to_selection_data (Display *, Lisp_Object,
#define TRACE2(fmt, a0, a1) (void) 0
#endif
-
-static Lisp_Object QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
- QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
- QATOM_PAIR, QCLIPBOARD_MANAGER, QSAVE_TARGETS;
-
-static Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */
-static Lisp_Object QUTF8_STRING; /* This is a type of selection. */
-
-static Lisp_Object Qcompound_text_with_extensions;
-
-static Lisp_Object Qforeign_selection;
-static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions;
-
/* Bytes needed to represent 'long' data. This is as per libX11; it
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 +225,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 +247,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 +273,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;
@@ -370,7 +348,7 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
static Lisp_Object
x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
- int local_request, struct x_display_info *dpyinfo)
+ bool local_request, struct x_display_info *dpyinfo)
{
Lisp_Object local_value;
Lisp_Object handler_fn, value, check;
@@ -458,7 +436,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 ();
@@ -480,7 +458,7 @@ struct selection_data
ptrdiff_t size;
int format;
Atom type;
- int nofree;
+ bool nofree;
Atom property;
/* This can be set to non-NULL during x_reply_selection_request, if
the selection is waiting for an INCR transfer to complete. Don't
@@ -508,7 +486,7 @@ x_selection_request_lisp_error (void)
for (cs = converted_selections; cs; cs = next)
{
next = cs->next;
- if (cs->nofree == 0 && cs->data)
+ if (! cs->nofree && cs->data)
xfree (cs->data);
xfree (cs);
}
@@ -541,7 +519,7 @@ struct prop_location
Window window;
Atom property;
int desired_state;
- int arrived;
+ bool arrived;
struct prop_location *next;
};
@@ -632,7 +610,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 +688,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,15 +728,14 @@ 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;
+ bool success = false;
ptrdiff_t count = SPECPDL_INDEX ();
GCPRO2 (local_selection_data, target_symbol);
@@ -800,7 +777,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)
@@ -816,9 +793,9 @@ x_handle_selection_request (struct input_event *event)
if (subproperty != None)
x_convert_selection (event, selection_symbol, subtarget,
- subproperty, 1, dpyinfo);
+ subproperty, true, dpyinfo);
}
- success = 1;
+ success = true;
}
else
{
@@ -826,7 +803,7 @@ x_handle_selection_request (struct input_event *event)
property = SELECTION_EVENT_TARGET (event);
success = x_convert_selection (event, selection_symbol,
target_symbol, property,
- 0, dpyinfo);
+ false, dpyinfo);
}
DONE:
@@ -840,14 +817,8 @@ x_handle_selection_request (struct input_event *event)
/* Run the `x-sent-selection-functions' abnormal hook. */
if (!NILP (Vx_sent_selection_functions)
&& !EQ (Vx_sent_selection_functions, Qunbound))
- {
- Lisp_Object args[4];
- args[0] = Qx_sent_selection_functions;
- args[1] = selection_symbol;
- args[2] = target_symbol;
- args[3] = success ? Qt : Qnil;
- Frun_hook_with_args (4, args);
- }
+ CALLN (Frun_hook_with_args, Qx_sent_selection_functions,
+ selection_symbol, target_symbol, success ? Qt : Qnil);
unbind_to (count, Qnil);
UNGCPRO;
@@ -855,15 +826,15 @@ x_handle_selection_request (struct input_event *event)
/* Perform the requested selection conversion, and write the data to
the converted_selections linked list, where it can be accessed by
- x_reply_selection_request. If FOR_MULTIPLE is non-zero, write out
+ x_reply_selection_request. If FOR_MULTIPLE, write out
the data even if conversion fails, using conversion_fail_tag.
- Return 0 if the selection failed to convert, 1 otherwise. */
+ Return true iff successful. */
-static int
+static bool
x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
Lisp_Object target_symbol, Atom property,
- int for_multiple, struct x_display_info *dpyinfo)
+ bool for_multiple, struct x_display_info *dpyinfo)
{
struct gcpro gcpro1;
Lisp_Object lisp_selection;
@@ -872,7 +843,7 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
lisp_selection
= x_get_local_selection (selection_symbol, target_symbol,
- 0, dpyinfo);
+ false, dpyinfo);
/* A nil return value means we can't perform the conversion. */
if (NILP (lisp_selection)
@@ -885,7 +856,7 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
cs->size = 1;
cs->format = 32;
cs->type = XA_ATOM;
- cs->nofree = 1;
+ cs->nofree = true;
cs->property = property;
cs->wait_object = NULL;
cs->next = converted_selections;
@@ -893,24 +864,20 @@ x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
}
UNGCPRO;
- return 0;
+ return false;
}
/* Otherwise, record the converted selection to binary. */
cs = xmalloc (sizeof *cs);
cs->data = NULL;
- cs->nofree = 1;
+ cs->nofree = true;
cs->property = property;
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;
+ return true;
}
/* Handle a SelectionClear event EVENT, which indicates that some
@@ -920,20 +887,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. */
@@ -965,12 +931,7 @@ x_handle_selection_clear (struct input_event *event)
tset_selection_alist (dpyinfo->terminal, Vselection_alist);
/* Run the `x-lost-selection-functions' abnormal hook. */
- {
- Lisp_Object args[2];
- args[0] = Qx_lost_selection_functions;
- args[1] = selection_symbol;
- Frun_hook_with_args (2, args);
- }
+ CALLN (Frun_hook_with_args, Qx_lost_selection_functions, selection_symbol);
redisplay_preserve_echo_area (20);
}
@@ -1006,10 +967,8 @@ x_clear_frame_selections (struct frame *f)
&& EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist)))))))
{
/* Run the `x-lost-selection-functions' abnormal hook. */
- Lisp_Object args[2];
- args[0] = Qx_lost_selection_functions;
- args[1] = Fcar (Fcar (t->Vselection_alist));
- Frun_hook_with_args (2, args);
+ CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
+ Fcar (Fcar (t->Vselection_alist)));
tset_selection_alist (t, XCDR (t->Vselection_alist));
}
@@ -1019,28 +978,23 @@ x_clear_frame_selections (struct frame *f)
if (CONSP (XCDR (rest))
&& EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest))))))))
{
- Lisp_Object args[2];
- args[0] = Qx_lost_selection_functions;
- args[1] = XCAR (XCAR (XCDR (rest)));
- Frun_hook_with_args (2, args);
+ CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
+ XCAR (XCAR (XCDR (rest))));
XSETCDR (rest, XCDR (XCDR (rest)));
break;
}
}
-/* Nonzero if any properties for DISPLAY and WINDOW
+/* True if any properties for DISPLAY and WINDOW
are on the list of what we are waiting for. */
-static int
+static bool
waiting_for_other_props_on_window (Display *display, Window window)
{
- struct prop_location *rest = property_change_wait_list;
- while (rest)
- if (rest->display == display && rest->window == window)
- return 1;
- else
- rest = rest->next;
- return 0;
+ for (struct prop_location *p = property_change_wait_list; p; p = p->next)
+ if (p->display == display && p->window == window)
+ return true;
+ return false;
}
/* Add an entry to the list of property changes we are waiting for.
@@ -1059,7 +1013,7 @@ expect_property_change (Display *display, Window window,
pl->property = property;
pl->desired_state = state;
pl->next = property_change_wait_list;
- pl->arrived = 0;
+ pl->arrived = false;
property_change_wait_list = pl;
return pl;
}
@@ -1070,20 +1024,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;
}
}
@@ -1124,7 +1076,7 @@ wait_for_property_change (struct prop_location *location)
EMACS_INT secs = timeout / 1000;
int nsecs = (timeout % 1000) * 1000000;
TRACE2 (" Waiting %"pI"d secs, %d nsecs", secs, nsecs);
- wait_reading_process_output (secs, nsecs, 0, 0,
+ wait_reading_process_output (secs, nsecs, 0, false,
property_change_reply, NULL, 0);
if (NILP (XCAR (property_change_reply)))
@@ -1156,7 +1108,7 @@ x_handle_property_notify (const XPropertyEvent *event)
(event->state == PropertyDelete ? "deletion" : "change"),
XGetAtomName (event->display, event->atom));
- rest->arrived = 1;
+ rest->arrived = true;
/* If this is the one wait_for_property_change is waiting for,
tell it to wake up. */
@@ -1222,7 +1174,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
during this time. In fact, the SAVE_TARGETS mechanism requires
us to handle a clipboard manager's requests before it returns
SelectionNotify. */
-#if 0
+#if false
x_start_queuing_selection_requests ();
record_unwind_protect_void (x_stop_queuing_selection_requests);
#endif
@@ -1234,7 +1186,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
secs = timeout / 1000;
nsecs = (timeout % 1000) * 1000000;
TRACE1 (" Start waiting %"pI"d secs for SelectionNotify", secs);
- wait_reading_process_output (secs, nsecs, 0, 0,
+ wait_reading_process_output (secs, nsecs, 0, false,
reading_selection_reply, NULL, 0);
TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply)));
@@ -1245,7 +1197,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);
}
@@ -1258,7 +1210,7 @@ static void
x_get_window_property (Display *display, Window window, Atom property,
unsigned char **data_ret, ptrdiff_t *bytes_ret,
Atom *actual_type_ret, int *actual_format_ret,
- unsigned long *actual_size_ret, int delete_p)
+ unsigned long *actual_size_ret)
{
ptrdiff_t total_size;
unsigned long bytes_remaining;
@@ -1283,7 +1235,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 +1251,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 +1302,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 +1334,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 +1354,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,16 +1374,16 @@ 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);
unblock_input ();
- while (1)
+ while (true)
{
unsigned char *tmp_data;
ptrdiff_t tmp_size_bytes;
@@ -1450,7 +1397,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
TRACE0 (" Get property value");
x_get_window_property (display, window, property,
&tmp_data, &tmp_size_bytes,
- type_ret, format_ret, size_ret, 1);
+ type_ret, format_ret, size_ret);
TRACE1 (" Read increment of %"pD"d bytes", tmp_size_bytes);
@@ -1495,8 +1442,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,28 +1453,27 @@ 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");
x_get_window_property (display, window, property, &data, &bytes,
- &actual_type, &actual_format, &actual_size, 1);
+ &actual_type, &actual_format, &actual_size);
if (! data)
{
- int there_is_a_selection_owner;
block_input ();
- there_is_a_selection_owner
- = XGetSelectionOwner (display, selection_atom);
+ bool there_is_a_selection_owner
+ = XGetSelectionOwner (display, selection_atom) != 0;
unblock_input ();
if (there_is_a_selection_owner)
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 +1486,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 +1500,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 +1541,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 +1582,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 +1650,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 = false;
if (CONSP (obj) && SYMBOLP (XCAR (obj)))
{
@@ -1725,9 +1668,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 +1680,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 = true;
}
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 +1700,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 +1715,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 +1741,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 +1770,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 +1787,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 +1870,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)
@@ -2007,7 +1950,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */)
if (!f)
error ("X selection unavailable for this frame");
- val = x_get_local_selection (selection_symbol, target_type, 1,
+ val = x_get_local_selection (selection_symbol, target_type, true,
FRAME_DISPLAY_INFO (f));
if (NILP (val) && FRAME_LIVE_P (f))
@@ -2077,7 +2020,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 +2121,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);
+ CALLN (Fmessage, format, CAR (CDR (err)));
return Qnil;
}
@@ -2249,10 +2190,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 +2246,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 +2257,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 +2284,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 +2321,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,
@@ -2486,7 +2401,7 @@ FRAME is on. If FRAME is nil, the selected frame is used. */)
/* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT. */
-int
+bool
x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
struct x_display_info *dpyinfo, struct input_event *bufp)
{
@@ -2502,7 +2417,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
if (dpyinfo->x_dnd_atoms[i] == event->message_type) break;
- if (i == dpyinfo->x_dnd_atoms_length) return 0;
+ if (i == dpyinfo->x_dnd_atoms_length) return false;
XSETFRAME (frame, f);
@@ -2519,7 +2434,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 +2444,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;
@@ -2538,7 +2453,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
bufp->arg = vec;
bufp->modifiers = 0;
- return 1;
+ return true;
}
DEFUN ("x-send-client-message", Fx_send_client_message,
@@ -2589,7 +2504,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
Window wdest;
XEvent event;
struct frame *f = decode_window_system_frame (from);
- int to_root;
+ bool to_root;
CHECK_NUMBER (format);
CHECK_CONS (values);
@@ -2646,7 +2561,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
event then goes to clients selecting for events on the root window. */
x_catch_errors (dpyinfo->display);
{
- int propagate = to_root ? False : True;
+ bool propagate = !to_root;
long mask = to_root ? 0xffffff : 0;
XSendEvent (dpyinfo->display, wdest, propagate, mask, &event);
@@ -2683,12 +2598,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
@@ -2742,8 +2659,11 @@ A value of 0 means wait as long as necessary. This is initialized from the
DEFSYM (QCLIPBOARD, "CLIPBOARD");
DEFSYM (QTIMESTAMP, "TIMESTAMP");
DEFSYM (QTEXT, "TEXT");
+
+ /* These are types of selection. */
DEFSYM (QCOMPOUND_TEXT, "COMPOUND_TEXT");
DEFSYM (QUTF8_STRING, "UTF8_STRING");
+
DEFSYM (QDELETE, "DELETE");
DEFSYM (QMULTIPLE, "MULTIPLE");
DEFSYM (QINCR, "INCR");
diff --git a/src/xsettings.c b/src/xsettings.c
index bd16ecc86dd..028487b91ee 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -51,8 +51,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
static char *current_mono_font;
static char *current_font;
static struct x_display_info *first_dpyinfo;
-static Lisp_Object Qmonospace_font_name, Qfont_name, Qfont_render,
- Qtool_bar_style;
static Lisp_Object current_tool_bar_style;
/* Store an config changed event in to the event queue. */
@@ -68,11 +66,11 @@ store_config_changed_event (Lisp_Object arg, Lisp_Object display_name)
kbd_buffer_store_event (&event);
}
-/* Return non-zero if DPYINFO is still valid. */
-static int
+/* Return true if DPYINFO is still valid. */
+static bool
dpyinfo_valid (struct x_display_info *dpyinfo)
{
- int found = 0;
+ bool found = false;
if (dpyinfo != NULL)
{
struct x_display_info *d;
@@ -404,7 +402,7 @@ parse_settings (unsigned char *prop,
/* First 4 bytes is a serial number, skip that. */
- if (bytes < 12) return BadLength;
+ if (bytes < 12) return settings_seen;
memcpy (&n_settings, prop+8, 4);
if (my_bo != that_bo) n_settings = bswap_32 (n_settings);
bytes_parsed = 12;
@@ -419,7 +417,7 @@ parse_settings (unsigned char *prop,
CARD32 vlen, ival = 0;
char name[128]; /* The names we are looking for are not this long. */
char sval[128]; /* The values we are looking for are not this long. */
- int want_this;
+ bool want_this;
int to_cpy;
sval[0] = '\0';
@@ -429,8 +427,8 @@ parse_settings (unsigned char *prop,
memcpy (&nlen, prop+bytes_parsed, 2);
bytes_parsed += 2;
if (my_bo != that_bo) nlen = bswap_16 (nlen);
- if (bytes_parsed+nlen > bytes) return BadLength;
- to_cpy = nlen > 127 ? 127 : nlen;
+ if (bytes_parsed + nlen > bytes) return settings_seen;
+ to_cpy = min (nlen, sizeof name - 1);
memcpy (name, prop+bytes_parsed, to_cpy);
name[to_cpy] = '\0';
@@ -438,20 +436,19 @@ parse_settings (unsigned char *prop,
bytes_parsed = PAD (bytes_parsed);
bytes_parsed += 4; /* Skip serial for this value */
- if (bytes_parsed > bytes) return BadLength;
+ if (bytes_parsed > bytes) return settings_seen;
- want_this =
+ want_this = strcmp (XSETTINGS_TOOL_BAR_STYLE, name) == 0;
#ifdef HAVE_XFT
- (nlen > 6 && strncmp (name, "Xft/", 4) == 0)
- || strcmp (XSETTINGS_FONT_NAME, name) == 0
- ||
+ if ((nlen > 6 && memcmp (name, "Xft/", 4) == 0)
+ || strcmp (XSETTINGS_FONT_NAME, name) == 0)
+ want_this = true;
#endif
- strcmp (XSETTINGS_TOOL_BAR_STYLE, name) == 0;
switch (type)
{
case 0: /* Integer */
- if (bytes_parsed+4 > bytes) return BadLength;
+ if (bytes_parsed + 4 > bytes) return settings_seen;
if (want_this)
{
memcpy (&ival, prop+bytes_parsed, 4);
@@ -461,13 +458,13 @@ parse_settings (unsigned char *prop,
break;
case 1: /* String */
- if (bytes_parsed+4 > bytes) return BadLength;
+ if (bytes_parsed + 4 > bytes) return settings_seen;
memcpy (&vlen, prop+bytes_parsed, 4);
bytes_parsed += 4;
if (my_bo != that_bo) vlen = bswap_32 (vlen);
if (want_this)
{
- to_cpy = vlen > 127 ? 127 : vlen;
+ to_cpy = min (vlen, sizeof sval - 1);
memcpy (sval, prop+bytes_parsed, to_cpy);
sval[to_cpy] = '\0';
}
@@ -477,17 +474,16 @@ parse_settings (unsigned char *prop,
case 2: /* RGB value */
/* No need to parse this */
- if (bytes_parsed+8 > bytes) return BadLength;
+ if (bytes_parsed + 8 > bytes) return settings_seen;
bytes_parsed += 8; /* 4 values (r, b, g, alpha), 2 bytes each. */
break;
default: /* Parse Error */
- return BadValue;
+ return settings_seen;
}
if (want_this)
{
- ++settings_seen;
if (strcmp (name, XSETTINGS_TOOL_BAR_STYLE) == 0)
{
dupstring (&settings->tb_style, sval);
@@ -557,6 +553,9 @@ parse_settings (unsigned char *prop,
settings->seen &= ~SEEN_LCDFILTER;
}
#endif /* HAVE_XFT */
+ else
+ want_this = false;
+ settings_seen += want_this;
}
}
@@ -565,9 +564,9 @@ parse_settings (unsigned char *prop,
/* Read settings from the XSettings property window on display for DPYINFO.
Store settings read in SETTINGS.
- Return non-zero if successful, zero if not. */
+ Return true iff successful. */
-static int
+static bool
read_settings (struct x_display_info *dpyinfo, struct xsettings *settings)
{
Atom act_type;
@@ -576,6 +575,7 @@ read_settings (struct x_display_info *dpyinfo, struct xsettings *settings)
unsigned char *prop = NULL;
Display *dpy = dpyinfo->display;
int rc;
+ bool got_settings = false;
x_catch_errors (dpy);
rc = XGetWindowProperty (dpy,
@@ -587,27 +587,26 @@ read_settings (struct x_display_info *dpyinfo, struct xsettings *settings)
if (rc == Success && prop != NULL && act_form == 8 && nitems > 0
&& act_type == dpyinfo->Xatom_xsettings_prop)
- rc = parse_settings (prop, nitems, settings);
+ got_settings = parse_settings (prop, nitems, settings) != 0;
XFree (prop);
x_uncatch_errors ();
- return rc != 0;
+ return got_settings;
}
/* Apply Xft settings in SETTINGS to the Xft library.
- If SEND_EVENT_P is non-zero store a Lisp event that Xft settings changed. */
+ Store a Lisp event that Xft settings changed. */
static void
apply_xft_settings (struct x_display_info *dpyinfo,
- int send_event_p,
struct xsettings *settings)
{
#ifdef HAVE_XFT
FcPattern *pat;
struct xsettings oldsettings;
- int changed = 0;
+ bool changed = false;
memset (&oldsettings, 0, sizeof (oldsettings));
pat = FcPatternCreate ();
@@ -627,7 +626,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
{
FcPatternDel (pat, FC_ANTIALIAS);
FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa);
- ++changed;
+ changed = true;
oldsettings.aa = settings->aa;
}
@@ -636,7 +635,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
{
FcPatternDel (pat, FC_HINTING);
FcPatternAddBool (pat, FC_HINTING, settings->hinting);
- ++changed;
+ changed = true;
oldsettings.hinting = settings->hinting;
}
if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba)
@@ -644,7 +643,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
FcPatternDel (pat, FC_RGBA);
FcPatternAddInteger (pat, FC_RGBA, settings->rgba);
oldsettings.rgba = settings->rgba;
- ++changed;
+ changed = true;
}
/* Older fontconfig versions don't have FC_LCD_FILTER. */
@@ -653,7 +652,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
{
FcPatternDel (pat, FC_LCD_FILTER);
FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter);
- ++changed;
+ changed = true;
oldsettings.lcdfilter = settings->lcdfilter;
}
@@ -663,7 +662,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
{
FcPatternDel (pat, FC_HINT_STYLE);
FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle);
- ++changed;
+ changed = true;
oldsettings.hintstyle = settings->hintstyle;
}
#endif
@@ -673,7 +672,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
{
FcPatternDel (pat, FC_DPI);
FcPatternAddDouble (pat, FC_DPI, settings->dpi);
- ++changed;
+ changed = true;
oldsettings.dpi = settings->dpi;
/* Changing the DPI on this display affects all frames on it.
@@ -699,9 +698,8 @@ apply_xft_settings (struct x_display_info *dpyinfo,
char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth];
XftDefaultSet (dpyinfo->display, pat);
- if (send_event_p)
- store_config_changed_event (Qfont_render,
- XCAR (dpyinfo->name_list_element));
+ store_config_changed_event (Qfont_render,
+ XCAR (dpyinfo->name_list_element));
Vxft_settings
= make_formatted_string (buf, format,
oldsettings.aa, oldsettings.hinting,
@@ -715,17 +713,17 @@ apply_xft_settings (struct x_display_info *dpyinfo,
}
/* Read XSettings from the display for DPYINFO.
- If SEND_EVENT_P is non-zero store a Lisp event settings that changed. */
+ If SEND_EVENT_P store a Lisp event settings that changed. */
static void
-read_and_apply_settings (struct x_display_info *dpyinfo, int send_event_p)
+read_and_apply_settings (struct x_display_info *dpyinfo, bool send_event_p)
{
struct xsettings settings;
if (!read_settings (dpyinfo, &settings))
return;
- apply_xft_settings (dpyinfo, True, &settings);
+ apply_xft_settings (dpyinfo, &settings);
if (settings.seen & SEEN_TB_STYLE)
{
if (send_event_p)
@@ -751,27 +749,27 @@ read_and_apply_settings (struct x_display_info *dpyinfo, int send_event_p)
void
xft_settings_event (struct x_display_info *dpyinfo, const XEvent *event)
{
- bool check_window_p = 0, apply_settings_p = 0;
+ bool check_window_p = false, apply_settings_p = false;
switch (event->type)
{
case DestroyNotify:
if (dpyinfo->xsettings_window == event->xany.window)
- check_window_p = 1;
+ check_window_p = true;
break;
case ClientMessage:
if (event->xclient.message_type == dpyinfo->Xatom_xsettings_mgr
&& event->xclient.data.l[1] == dpyinfo->Xatom_xsettings_sel
&& event->xclient.window == dpyinfo->root_window)
- check_window_p = 1;
+ check_window_p = true;
break;
case PropertyNotify:
if (event->xproperty.window == dpyinfo->xsettings_window
&& event->xproperty.state == PropertyNewValue
&& event->xproperty.atom == dpyinfo->Xatom_xsettings_prop)
- apply_settings_p = 1;
+ apply_settings_p = true;
break;
}
@@ -781,11 +779,11 @@ xft_settings_event (struct x_display_info *dpyinfo, const XEvent *event)
dpyinfo->xsettings_window = None;
get_prop_window (dpyinfo);
if (dpyinfo->xsettings_window != None)
- apply_settings_p = 1;
+ apply_settings_p = true;
}
if (apply_settings_p)
- read_and_apply_settings (dpyinfo, True);
+ read_and_apply_settings (dpyinfo, true);
}
/* Initialize GSettings and read startup values. */
@@ -795,7 +793,7 @@ init_gsettings (void)
{
#ifdef HAVE_GSETTINGS
GVariant *val;
- int schema_found = 0;
+ bool schema_found = false;
#if ! GLIB_CHECK_VERSION (2, 36, 0)
g_type_init ();
@@ -806,7 +804,7 @@ init_gsettings (void)
GSettingsSchema *sc = g_settings_schema_source_lookup
(g_settings_schema_source_get_default (),
GSETTINGS_SCHEMA,
- TRUE);
+ true);
schema_found = sc != NULL;
if (sc) g_settings_schema_unref (sc);
}
@@ -937,7 +935,7 @@ init_xsettings (struct x_display_info *dpyinfo)
get_prop_window (dpyinfo);
if (dpyinfo->xsettings_window != None)
- read_and_apply_settings (dpyinfo, False);
+ read_and_apply_settings (dpyinfo, false);
unblock_input ();
}
@@ -1030,7 +1028,7 @@ syms_of_xsettings (void)
When this is non-nil and the system defined fixed width font changes, we
update frames dynamically.
If this variable is nil, Emacs ignores system font changes. */);
- use_system_font = 0;
+ use_system_font = false;
DEFVAR_LISP ("xft-settings", Vxft_settings,
doc: /* Font settings applied to Xft. */);
diff --git a/src/xsmfns.c b/src/xsmfns.c
index 680fea652a7..0e635d38ec6 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -49,11 +49,11 @@ 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. */
-static int doing_interact;
+static bool doing_interact;
/* The session manager object for the session manager connection. */
@@ -123,9 +123,9 @@ x_session_check_input (int fd, void *data)
kbd_buffer_store_event (&emacs_event);
}
-/* Return non-zero if we have a connection to a session manager. */
+/* Return true if we have a connection to a session manager. */
-int
+bool
x_session_have_connection (void)
{
return ice_fd != -1;
@@ -138,7 +138,7 @@ x_session_have_connection (void)
static void
smc_interact_CB (SmcConn smcConn, SmPointer clientData)
{
- doing_interact = True;
+ doing_interact = true;
emacs_event.kind = SAVE_SESSION_EVENT;
emacs_event.arg = Qnil;
}
@@ -230,8 +230,7 @@ smc_save_yourself_CB (SmcConn smcConn,
props[props_idx]->vals[vp_idx++].value = emacs_program;
smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1);
- strcpy (smid_opt, SMID_OPT);
- strcat (smid_opt, client_id);
+ strcpy (stpcpy (smid_opt, SMID_OPT), client_id);
props[props_idx]->vals[vp_idx].length = strlen (smid_opt);
props[props_idx]->vals[vp_idx++].value = smid_opt;
@@ -242,8 +241,7 @@ smc_save_yourself_CB (SmcConn smcConn,
if (cwd)
{
chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1);
- strcpy (chdir_opt, CHDIR_OPT);
- strcat (chdir_opt, cwd);
+ strcpy (stpcpy (chdir_opt, CHDIR_OPT), cwd);
props[props_idx]->vals[vp_idx].length = strlen (chdir_opt);
props[props_idx]->vals[vp_idx++].value = chdir_opt;
@@ -395,31 +393,31 @@ 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;
ice_fd = -1;
- doing_interact = False;
+ doing_interact = false;
/* Check if we where started by the session manager. If so, we will
have a previous id. */
- if (! EQ (Vx_session_previous_id, Qnil) && STRINGP (Vx_session_previous_id))
+ if (! NILP (Vx_session_previous_id) && STRINGP (Vx_session_previous_id))
previous_id = SSDATA (Vx_session_previous_id);
/* Construct the path to the Emacs program. */
- if (! EQ (Vinvocation_directory, Qnil))
+ if (! NILP (Vinvocation_directory))
name_len += SBYTES (Vinvocation_directory);
name_len += SBYTES (Vinvocation_name);
/* 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));
+ if (! NILP (Vinvocation_directory))
+ 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. */
@@ -491,21 +489,19 @@ is told to abort the window system shutdown.
Do not call this function yourself. */)
(Lisp_Object event)
{
- int kill_emacs = CONSP (event) && CONSP (XCDR (event))
- && EQ (Qt, XCAR (XCDR (event)));
+ bool kill_emacs = (CONSP (event) && CONSP (XCDR (event))
+ && EQ (Qt, XCAR (XCDR (event))));
/* Check doing_interact so that we don't do anything if someone called
this at the wrong time. */
if (doing_interact && ! kill_emacs)
{
- Bool cancel_shutdown = False;
-
- cancel_shutdown = ! EQ (call0 (intern ("emacs-session-save")), Qnil);
+ bool cancel_shutdown = ! NILP (call0 (intern ("emacs-session-save")));
SmcInteractDone (smc_conn, cancel_shutdown);
SmcSaveYourselfDone (smc_conn, True);
- doing_interact = False;
+ doing_interact = false;
}
else if (kill_emacs)
{
@@ -513,7 +509,7 @@ Do not call this function yourself. */)
prevent. Fix this in next version. */
Fkill_emacs (Qnil);
-#if 0
+#if false
/* This will not be reached, but we want kill-emacs-hook to be run. */
SmcCloseConnection (smc_conn, 0, 0);
ice_connection_closed ();
diff --git a/src/xterm.c b/src/xterm.c
index 4ca1e131e67..3955d027a52 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>
@@ -169,17 +180,9 @@ static Time ignore_next_mouse_click_timeout;
static int x_noop_count;
-static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
-
-static Lisp_Object Qvendor_specific_keysyms;
-static Lisp_Object Qlatin_1;
-
#ifdef USE_GTK
/* The name of the Emacs icon file. */
static Lisp_Object xg_default_icon_file;
-
-/* Used in gtkutil.c. */
-Lisp_Object Qx_gtk_map_stock;
#endif
/* Some functions take this as char *, not const char *. */
@@ -209,13 +212,12 @@ enum xembed_message
};
static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, int, int, int, bool);
+static void x_set_window_size_1 (struct frame *, bool, int, int, bool);
static void x_raise_frame (struct frame *);
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,15 +238,19 @@ 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 int x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
+static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
+ enum scroll_bar_part *,
+ Lisp_Object *, Lisp_Object *,
+ Time *);
+static bool 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);
-static void x_sync_with_move (struct frame *, int, int, int);
+static void x_sync_with_move (struct frame *, int, int, bool);
static int handle_one_xevent (struct x_display_info *,
const XEvent *, int *,
struct input_event *);
@@ -258,6 +264,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 bool get_current_wm_state (struct frame *, Window, int *, bool *);
/* Flush display of frame F. */
@@ -290,7 +297,7 @@ x_flush (struct frame *f)
Debugging
***********************************************************************/
-#if 0
+#if false
/* This is a function useful for recording debugging information about
the sequence of occurrences in this file. */
@@ -308,7 +315,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;
@@ -316,7 +323,7 @@ record_event (char *locus, int type)
event_record_index++;
}
-#endif /* 0 */
+#endif
@@ -348,8 +355,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 +407,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 +417,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 +435,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
***********************************************************************/
@@ -475,7 +471,7 @@ x_update_window_begin (struct window *w)
if (f == hlinfo->mouse_face_mouse_frame)
{
/* Don't do highlighting for mouse motion during the update. */
- hlinfo->mouse_face_defer = 1;
+ hlinfo->mouse_face_defer = true;
/* If F needs to be redrawn, simply forget about any prior mouse
highlighting. */
@@ -579,11 +575,11 @@ x_update_window_end (struct window *w, bool cursor_on_p,
block_input ();
if (cursor_on_p)
- display_and_set_cursor (w, 1,
+ display_and_set_cursor (w, true,
w->output_cursor.hpos, w->output_cursor.vpos,
w->output_cursor.x, w->output_cursor.y);
- if (draw_window_fringes (w, 1))
+ if (draw_window_fringes (w, true))
{
if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
x_draw_right_divider (w);
@@ -614,7 +610,7 @@ static void
x_update_end (struct frame *f)
{
/* Mouse highlight may be displayed again. */
- MOUSE_HL_INFO (f)->mouse_face_defer = 0;
+ MOUSE_HL_INFO (f)->mouse_face_defer = false;
#ifndef XFlush
block_input ();
@@ -635,10 +631,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)
{
@@ -673,7 +667,7 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
eassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
- desired_row->redraw_fringe_bitmaps_p = 1;
+ desired_row->redraw_fringe_bitmaps_p = true;
#ifdef USE_X_TOOLKIT
/* When a window has disappeared, make sure that no rest of
@@ -815,10 +809,10 @@ static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
static void x_clear_glyph_string_rect (struct glyph_string *, int,
int, int, int);
static void x_draw_relief_rect (struct frame *, int, int, int, int,
- int, int, int, int, int, int,
+ int, bool, bool, bool, bool, bool,
XRectangle *);
static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
- int, int, int, XRectangle *);
+ int, bool, bool, XRectangle *);
static void x_scroll_bar_clear (struct frame *);
#ifdef GLYPH_DEBUG
@@ -897,7 +891,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 +939,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)
{
@@ -960,7 +954,7 @@ x_set_glyph_string_gc (struct glyph_string *s)
else if (s->hl == DRAW_CURSOR)
{
x_set_cursor_gc (s);
- s->stippled_p = 0;
+ s->stippled_p = false;
}
else if (s->hl == DRAW_MOUSE_FACE)
{
@@ -974,10 +968,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);
@@ -1095,7 +1086,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
s->background_width,
s->height - 2 * box_line_width);
XSetFillStyle (s->display, s->gc, FillSolid);
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
|| s->font_not_found_p
@@ -1105,7 +1096,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
}
}
@@ -1151,11 +1142,11 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
y = s->ybase - boff;
if (s->for_overlaps
|| (s->background_filled_p && s->hl != DRAW_CURSOR))
- font->driver->draw (s, 0, s->nchars, x, y, 0);
+ font->driver->draw (s, 0, s->nchars, x, y, false);
else
- font->driver->draw (s, 0, s->nchars, x, y, 1);
+ font->driver->draw (s, 0, s->nchars, x, y, true);
if (s->face->overstrike)
- font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+ font->driver->draw (s, 0, s->nchars, x + 1, y, false);
}
}
@@ -1200,9 +1191,9 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
int xx = x + s->cmp->offsets[j * 2];
int yy = y - s->cmp->offsets[j * 2 + 1];
- font->driver->draw (s, j, j + 1, xx, yy, 0);
+ font->driver->draw (s, j, j + 1, xx, yy, false);
if (s->face->overstrike)
- font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+ font->driver->draw (s, j, j + 1, xx + 1, yy, false);
}
}
else
@@ -1223,17 +1214,18 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
if (j < i)
{
- font->driver->draw (s, j, i, x, y, 0);
+ font->driver->draw (s, j, i, x, y, false);
if (s->face->overstrike)
- font->driver->draw (s, j, i, x + 1, y, 0);
+ font->driver->draw (s, j, i, x + 1, y, false);
x += width;
}
xoff = LGLYPH_XOFF (glyph);
yoff = LGLYPH_YOFF (glyph);
wadjust = LGLYPH_WADJUST (glyph);
- font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+ font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
if (s->face->overstrike)
- font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
+ font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
+ false);
x += wadjust;
j = i + 1;
width = 0;
@@ -1241,9 +1233,9 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
}
if (j < i)
{
- font->driver->draw (s, j, i, x, y, 0);
+ font->driver->draw (s, j, i, x, y, false);
if (s->face->overstrike)
- font->driver->draw (s, j, i, x + 1, y, 0);
+ font->driver->draw (s, j, i, x + 1, y, false);
}
}
}
@@ -1311,11 +1303,11 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
s->font->driver->draw (s, 0, upper_len,
x + glyph->slice.glyphless.upper_xoff,
s->ybase + glyph->slice.glyphless.upper_yoff,
- 0);
+ false);
s->font->driver->draw (s, upper_len, len,
x + glyph->slice.glyphless.lower_xoff,
s->ybase + glyph->slice.glyphless.lower_yoff,
- 0);
+ false);
}
if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
XDrawRectangle (s->display, s->window, s->gc,
@@ -1782,7 +1774,7 @@ x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
success_p = x_alloc_nearest_color (f, cmap, &new);
}
else
- success_p = 1;
+ success_p = true;
*pixel = new.pixel;
}
@@ -1877,16 +1869,17 @@ x_setup_relief_colors (struct glyph_string *s)
/* Draw a relief on frame F inside the rectangle given by LEFT_X,
TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
- to draw, it must be >= 0. RAISED_P non-zero means draw a raised
- relief. LEFT_P non-zero means draw a relief on the left side of
- the rectangle. RIGHT_P non-zero means draw a relief on the right
+ to draw, it must be >= 0. RAISED_P means draw a raised
+ relief. LEFT_P means draw a relief on the left side of
+ the rectangle. RIGHT_P means draw a relief on the right
side of the rectangle. CLIP_RECT is the clipping rectangle to use
when drawing. */
static void
x_draw_relief_rect (struct frame *f,
- int left_x, int top_y, int right_x, int bottom_y, int width,
- int raised_p, int top_p, int bot_p, int left_p, int right_p,
+ int left_x, int top_y, int right_x, int bottom_y,
+ int width, bool raised_p, bool top_p, bool bot_p,
+ bool left_p, bool right_p,
XRectangle *clip_rect)
{
Display *dpy = FRAME_X_DISPLAY (f);
@@ -1910,8 +1903,8 @@ x_draw_relief_rect (struct frame *f,
{
if (width == 1)
XDrawLine (dpy, window, gc,
- left_x + (left_p ? 1 : 0), top_y,
- right_x + (right_p ? 0 : 1), top_y);
+ left_x + left_p, top_y,
+ right_x + !right_p, top_y);
for (i = 1; i < width; ++i)
XDrawLine (dpy, window, gc,
@@ -1946,8 +1939,8 @@ x_draw_relief_rect (struct frame *f,
/* Outermost top line. */
if (top_p)
XDrawLine (dpy, window, gc,
- left_x + (left_p ? 1 : 0), top_y,
- right_x + (right_p ? 0 : 1), top_y);
+ left_x + left_p, top_y,
+ right_x + !right_p, top_y);
/* Outermost left line. */
if (left_p)
@@ -1958,8 +1951,8 @@ x_draw_relief_rect (struct frame *f,
if (bot_p)
{
XDrawLine (dpy, window, gc,
- left_x + (left_p ? 1 : 0), bottom_y,
- right_x + (right_p ? 0 : 1), bottom_y);
+ left_x + left_p, bottom_y,
+ right_x + !right_p, bottom_y);
for (i = 1; i < width; ++i)
XDrawLine (dpy, window, gc,
left_x + i * left_p, bottom_y - i,
@@ -1983,15 +1976,15 @@ x_draw_relief_rect (struct frame *f,
/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
- draw, it must be >= 0. LEFT_P non-zero means draw a line on the
- left side of the rectangle. RIGHT_P non-zero means draw a line
+ draw, it must be >= 0. LEFT_P means draw a line on the
+ left side of the rectangle. RIGHT_P means draw a line
on the right side of the rectangle. CLIP_RECT is the clipping
rectangle to use when drawing. */
static void
x_draw_box_rect (struct glyph_string *s,
int left_x, int top_y, int right_x, int bottom_y, int width,
- int left_p, int right_p, XRectangle *clip_rect)
+ bool left_p, bool right_p, XRectangle *clip_rect)
{
XGCValues xgcv;
@@ -2027,8 +2020,8 @@ x_draw_box_rect (struct glyph_string *s,
static void
x_draw_glyph_string_box (struct glyph_string *s)
{
- int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
- int left_p, right_p;
+ int width, left_x, right_x, top_y, bottom_y, last_x;
+ bool raised_p, left_p, right_p;
struct glyph *last_glyph;
XRectangle clip_rect;
@@ -2068,7 +2061,8 @@ x_draw_glyph_string_box (struct glyph_string *s)
{
x_setup_relief_colors (s);
x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
- width, raised_p, 1, 1, left_p, right_p, &clip_rect);
+ width, raised_p, true, true, left_p, right_p,
+ &clip_rect);
}
}
@@ -2167,7 +2161,8 @@ x_draw_image_foreground (struct glyph_string *s)
static void
x_draw_image_relief (struct glyph_string *s)
{
- int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
+ int x1, y1, thick;
+ bool raised_p, top_p, bot_p, left_p, right_p;
int extra_x, extra_y;
XRectangle r;
int x = s->x;
@@ -2216,16 +2211,16 @@ x_draw_image_relief (struct glyph_string *s)
extra_x = extra_y = XINT (Vtool_bar_button_margin);
}
- top_p = bot_p = left_p = right_p = 0;
+ top_p = bot_p = left_p = right_p = false;
if (s->slice.x == 0)
- x -= thick + extra_x, left_p = 1;
+ x -= thick + extra_x, left_p = true;
if (s->slice.y == 0)
- y -= thick + extra_y, top_p = 1;
+ y -= thick + extra_y, top_p = true;
if (s->slice.x + s->slice.width == s->img->width)
- x1 += thick + extra_x, right_p = 1;
+ x1 += thick + extra_x, right_p = true;
if (s->slice.y + s->slice.height == s->img->height)
- y1 += thick + extra_y, bot_p = 1;
+ y1 += thick + extra_y, bot_p = true;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
@@ -2423,7 +2418,7 @@ x_draw_image_glyph_string (struct glyph_string *s)
x_draw_glyph_string_bg_rect (s, x, y, width, height);
}
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
/* Draw the foreground. */
@@ -2547,7 +2542,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
}
- s->background_filled_p = 1;
+ s->background_filled_p = true;
}
/*
@@ -2565,7 +2560,8 @@ static void
x_draw_underwave (struct glyph_string *s)
{
int wave_height = 3, wave_length = 2;
- int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
+ int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
+ bool odd;
XRectangle wave_clip, string_clip, final_clip;
dx = wave_length;
@@ -2592,7 +2588,7 @@ x_draw_underwave (struct glyph_string *s)
x1 = x0 - (x0 % dx);
x2 = x1 + dx;
- odd = (x1/dx) % 2;
+ odd = (x1 / dx) & 1;
y1 = y2 = y0;
if (odd)
@@ -2621,7 +2617,7 @@ x_draw_underwave (struct glyph_string *s)
static void
x_draw_glyph_string (struct glyph_string *s)
{
- bool relief_drawn_p = 0;
+ bool relief_drawn_p = false;
/* If S draws into the background of its successors, draw the
background of the successors first so that S can draw into it.
@@ -2641,7 +2637,7 @@ x_draw_glyph_string (struct glyph_string *s)
if (next->first_glyph->type == STRETCH_GLYPH)
x_draw_stretch_glyph_string (next);
else
- x_draw_glyph_string_background (next, 1);
+ x_draw_glyph_string_background (next, true);
next->num_clips = 0;
}
}
@@ -2658,10 +2654,10 @@ x_draw_glyph_string (struct glyph_string *s)
{
x_set_glyph_string_clipping (s);
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_glyph_string_box (s);
x_set_glyph_string_clipping (s);
- relief_drawn_p = 1;
+ relief_drawn_p = true;
}
else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
&& !s->clip_tail
@@ -2686,26 +2682,26 @@ x_draw_glyph_string (struct glyph_string *s)
case CHAR_GLYPH:
if (s->for_overlaps)
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 0);
+ x_draw_glyph_string_background (s, false);
x_draw_glyph_string_foreground (s);
break;
case COMPOSITE_GLYPH:
if (s->for_overlaps || (s->cmp_from > 0
&& ! s->first_glyph->u.cmp.automatic))
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_composite_glyph_string_foreground (s);
break;
case GLYPHLESS_GLYPH:
if (s->for_overlaps)
- s->background_filled_p = 1;
+ s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_background (s, true);
x_draw_glyphless_glyph_string_foreground (s);
break;
@@ -2956,8 +2952,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 = true;
+
+ 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 = false;
+ }
+}
-
/* Invert the middle quarter of the frame for .15 sec. */
static void
@@ -2979,7 +3031,7 @@ XTflash (struct frame *f)
cairo_rectangle (cr, x, y, w, h); \
cairo_fill (cr); \
} \
- while (0)
+ while (false)
#else /* ! HAVE_GTK3 */
GdkGCValues vals;
GdkGC *gc;
@@ -2989,7 +3041,7 @@ XTflash (struct frame *f)
gc = gdk_gc_new_with_values (window,
&vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
#define XFillRectangle(d, win, gc, x, y, w, h) \
- gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
+ gdk_draw_rectangle (window, gc, true, x, y, w, h)
#endif /* ! HAVE_GTK3 */
#else /* ! USE_GTK */
GC gc;
@@ -3102,19 +3154,10 @@ XTflash (struct frame *f)
static void
-XTtoggle_invisible_pointer (struct frame *f, int invisible)
+XTtoggle_invisible_pointer (struct frame *f, bool 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 ();
}
@@ -3231,7 +3274,7 @@ frame_highlight (struct frame *f)
f->output_data.x->border_pixel);
x_uncatch_errors ();
unblock_input ();
- x_update_cursor (f, 1);
+ x_update_cursor (f, true);
x_set_frame_alpha (f);
}
@@ -3249,7 +3292,7 @@ frame_unhighlight (struct frame *f)
f->output_data.x->border_tile);
x_uncatch_errors ();
unblock_input ();
- x_update_cursor (f, 1);
+ x_update_cursor (f, true);
x_set_frame_alpha (f);
}
@@ -3334,7 +3377,7 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
XUnsetICFocus (FRAME_XIC (frame));
#endif
if (frame->pointer_invisible)
- XTtoggle_invisible_pointer (frame, 0);
+ XTtoggle_invisible_pointer (frame, false);
}
}
@@ -3647,11 +3690,11 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
Alt keysyms are on. */
{
int row, col; /* The row and column in the modifier table. */
- int found_alt_or_meta;
+ bool found_alt_or_meta;
for (row = 3; row < 8; row++)
{
- found_alt_or_meta = 0;
+ found_alt_or_meta = false;
for (col = 0; col < mods->max_keypermod; col++)
{
KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
@@ -3672,13 +3715,13 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
{
case XK_Meta_L:
case XK_Meta_R:
- found_alt_or_meta = 1;
+ found_alt_or_meta = true;
dpyinfo->meta_mod_mask |= (1 << row);
break;
case XK_Alt_L:
case XK_Alt_R:
- found_alt_or_meta = 1;
+ found_alt_or_meta = true;
dpyinfo->alt_mod_mask |= (1 << row);
break;
@@ -3857,14 +3900,14 @@ construct_mouse_click (struct input_event *result,
the mainstream emacs code by setting mouse_moved. If not, ask for
another motion event, so we can check again the next time it moves. */
-static int
+static bool
note_mouse_movement (struct frame *frame, const XMotionEvent *event)
{
XRectangle *r;
struct x_display_info *dpyinfo;
if (!FRAME_X_OUTPUT (frame))
- return 0;
+ return false;
dpyinfo = FRAME_DISPLAY_INFO (frame);
dpyinfo->last_mouse_movement_time = event->time;
@@ -3874,11 +3917,11 @@ note_mouse_movement (struct frame *frame, const XMotionEvent *event)
if (event->window != FRAME_X_WINDOW (frame))
{
- frame->mouse_moved = 1;
+ frame->mouse_moved = true;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, -1, -1);
dpyinfo->last_mouse_glyph_frame = NULL;
- return 1;
+ return true;
}
@@ -3888,16 +3931,16 @@ note_mouse_movement (struct frame *frame, const XMotionEvent *event)
|| event->x < r->x || event->x >= r->x + r->width
|| event->y < r->y || event->y >= r->y + r->height)
{
- frame->mouse_moved = 1;
+ frame->mouse_moved = true;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, event->x, event->y);
/* Remember which glyph we're now on. */
remember_mouse_glyph (frame, event->x, event->y, r);
dpyinfo->last_mouse_glyph_frame = frame;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Return the current position of the mouse.
@@ -3931,7 +3974,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;
@@ -3946,7 +3996,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
FOR_EACH_FRAME (tail, frame)
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
- XFRAME (frame)->mouse_moved = 0;
+ XFRAME (frame)->mouse_moved = false;
dpyinfo->last_mouse_scroll_bar = NULL;
@@ -4007,7 +4057,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
}
else
{
- while (1)
+ while (true)
{
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
@@ -4075,7 +4125,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 +4154,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 +4180,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 +4205,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 +4247,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 +4262,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;
@@ -4226,7 +4281,7 @@ static void
xt_action_hook (Widget widget, XtPointer client_data, String action_name,
XEvent *event, String *params, Cardinal *num_params)
{
- int scroll_bar_p;
+ bool scroll_bar_p;
const char *end_action;
#ifdef USE_MOTIF
@@ -4245,7 +4300,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, false);
w = XWINDOW (window_being_scrolled);
bar = XSCROLL_BAR (w->vertical_scroll_bar);
@@ -4260,7 +4315,50 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name,
bar->last_seen_part = scroll_bar_nowhere;
#endif
/* Xt timeouts no longer needed. */
- toolkit_scroll_bar_interaction = 0;
+ toolkit_scroll_bar_interaction = false;
+ }
+}
+
+
+static void
+xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
+ XEvent *event, String *params, Cardinal *num_params)
+{
+ bool 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, true);
+ 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 = false;
}
}
#endif /* not USE_GTK */
@@ -4271,7 +4369,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 +4385,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;
@@ -4304,7 +4405,7 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
/* Make Xt timeouts work while the scroll bar is active. */
#ifdef USE_X_TOOLKIT
- toolkit_scroll_bar_interaction = 1;
+ toolkit_scroll_bar_interaction = true;
x_activate_timeout_atimer ();
#endif
@@ -4351,6 +4452,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 +4494,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 +4503,64 @@ 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;
+ bool horizontal = bar->horizontal;
+ int 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 +4569,11 @@ 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,12 +4588,13 @@ 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);
- if (xg_ignore_gtk_scrollbar) return FALSE;
+ if (xg_ignore_gtk_scrollbar) return false;
switch (scroll)
{
@@ -4454,38 +4603,54 @@ 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;
+ return false;
}
/* Callback for button release. Sets dragging to -1 when dragging is done. */
@@ -4500,11 +4665,11 @@ 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;
}
- return FALSE;
+ return false;
}
@@ -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;
+ bool 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)
+ {
+ whole = bar->whole - (shown * bar->whole);
+ portion = min (top * bar->whole, whole);
+ }
+ else
+ {
+ whole = bar->whole;
+ portion = 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;
+ 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,62 @@ 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 +4827,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 +5034,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 = false;
+
+ 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 = true;
unblock_input ();
}
@@ -4819,6 +5252,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 +5370,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 false
+ /* 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 false
+ 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 +5469,8 @@ 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 +5480,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 +5530,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 +5547,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);
@@ -5042,7 +5573,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
/* Draw BAR's handle in the proper position.
If the handle is already drawn from START to END, don't bother
- redrawing it, unless REBUILD is non-zero; in that case, always
+ redrawing it, unless REBUILD; in that case, always
redraw it. (REBUILD is handy for drawing the handle after expose
events.)
@@ -5053,7 +5584,8 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
to move to the very end of the buffer. */
static void
-x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild)
+x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
+ bool rebuild)
{
bool dragging = bar->dragging != -1;
Window w = bar->x_window;
@@ -5105,7 +5637,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 +5662,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 +5694,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 +5721,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 +5735,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), false);
}
else
{
@@ -5276,12 +5809,12 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, top_range, 0);
+ x_scroll_bar_set_handle (bar, 0, top_range, false);
else
{
int start = ((double) position * top_range) / whole;
int end = ((double) (position + portion) * top_range) / whole;
- x_scroll_bar_set_handle (bar, start, end, 0);
+ x_scroll_bar_set_handle (bar, start, end, false);
}
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -5291,6 +5824,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, true);
+ }
+ 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, false);
+ else
+ {
+ int start = ((double) position * left_range) / whole;
+ int end = ((double) (position + portion) * left_range) / whole;
+ x_scroll_bar_set_handle (bar, start, end, false);
+ }
+ }
+#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 +5971,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 +5995,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;
+
+ 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);
+ 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
@@ -5413,7 +6120,7 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
block_input ();
- x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
+ x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
/* Switch to scroll bar foreground color. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -5450,7 +6157,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 +6171,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, false);
+ 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, false);
+ bar->dragging = -1;
+ }
+#endif
+
+ XSETINT (emacs_event->x, y);
+ XSETINT (emacs_event->y, top_range);
+ }
}
#ifndef USE_TOOLKIT_SCROLL_BARS
@@ -5510,7 +6251,7 @@ x_scroll_bar_note_movement (struct scroll_bar *bar,
dpyinfo->last_mouse_movement_time = event->time;
dpyinfo->last_mouse_scroll_bar = bar;
- f->mouse_moved = 1;
+ f->mouse_moved = true;
/* If we're dragging the bar, display it. */
if (bar->dragging != -1)
@@ -5522,7 +6263,7 @@ x_scroll_bar_note_movement (struct scroll_bar *bar,
{
int new_end = new_start + bar->end - bar->start;
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ x_scroll_bar_set_handle (bar, new_start, new_end, false);
}
}
}
@@ -5589,7 +6330,76 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
XSETINT (*x, win_y);
XSETINT (*y, top_range);
- f->mouse_moved = 0;
+ f->mouse_moved = false;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+ *timestamp = dpyinfo->last_mouse_movement_time;
+ }
+
+ unblock_input ();
+}
+
+
+/* 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 = false;
dpyinfo->last_mouse_scroll_bar = NULL;
*timestamp = dpyinfo->last_mouse_movement_time;
}
@@ -5630,7 +6440,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 +6550,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;
+ bool sticky = false;
+
+ 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.
@@ -5801,7 +6640,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (f && FRAME_XIC (f))
XSetICFocus (FRAME_XIC (f));
#endif
-#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
+#if false
+ /* Emacs sets WM hints whose `input' field is `true'. This
instructs the WM to set the input focus automatically for
Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
@@ -5834,7 +6674,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_uncatch_errors ();
}
/* Not certain about handling scroll bars here */
-#endif /* 0 */
+#endif
goto done;
}
@@ -5937,6 +6777,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 +6807,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 +6816,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 +6825,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 +6841,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 +6851,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);
- }
+ {
+ bool 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, false);
+ f->output_data.x->has_been_visible = true;
+ 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, true);
+ inev.ie.kind = ICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ }
+ }
x_handle_property_notify (&event->xproperty);
xft_settings_event (dpyinfo, event);
@@ -6049,8 +6902,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!FRAME_VISIBLE_P (f))
{
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
- f->output_data.x->has_been_visible = 1;
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
SET_FRAME_GARBAGED (f);
}
else
@@ -6088,7 +6941,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);
@@ -6145,7 +6998,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
and that way, we know the window is not iconified now. */
if (visible || FRAME_ICONIFIED_P (f))
{
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
inev.ie.kind = ICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
}
@@ -6172,8 +7025,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_check_fullscreen (f);
SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, 0);
- f->output_data.x->has_been_visible = 1;
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
if (iconified)
{
@@ -6193,7 +7046,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)
@@ -6212,7 +7065,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !EQ (f->tool_bar_window, hlinfo->mouse_face_window)))
{
clear_mouse_face (hlinfo);
- hlinfo->mouse_face_hidden = 1;
+ hlinfo->mouse_face_hidden = true;
}
#endif
@@ -6460,7 +7313,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]);
}
@@ -6473,8 +7326,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
which depends on which X*LookupString function
we used just above and the locale. */
setup_coding_system (coding_system, &coding);
- coding.src_multibyte = 0;
- coding.dst_multibyte = 1;
+ coding.src_multibyte = false;
+ coding.dst_multibyte = true;
/* The input is converted to events, thus we can't
handle composition. Anyway, there's no XIM that
gives us composition information. */
@@ -6527,7 +7380,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 +7391,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 +7416,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 +7450,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;
@@ -6606,7 +7459,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (hlinfo->mouse_face_hidden)
{
- hlinfo->mouse_face_hidden = 0;
+ hlinfo->mouse_face_hidden = false;
clear_mouse_face (hlinfo);
}
@@ -6623,7 +7476,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
static Lisp_Object last_mouse_window;
Lisp_Object window = window_from_coordinates
- (f, event->xmotion.x, event->xmotion.y, 0, 0);
+ (f, event->xmotion.x, event->xmotion.y, 0, false);
/* Window will be selected only when it is not selected now and
last mouse movement event was not in it. Minibuffer window
@@ -6652,7 +7505,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 +7538,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);
@@ -6702,14 +7557,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| event->xconfigure.width != FRAME_PIXEL_WIDTH (f)
|| event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
{
- change_frame_size (f, width, height, 0, 1, 0, 1);
+ change_frame_size (f, width, height, false, true, false, true);
x_clear_under_internal_border (f);
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
@@ -6734,11 +7586,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
/* If we decide we want to generate an event to be seen
by the rest of Emacs, we put it here. */
- bool tool_bar_p = 0;
+ bool tool_bar_p = false;
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));
@@ -6758,7 +7610,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int x = event->xbutton.x;
int y = event->xbutton.y;
- window = window_from_coordinates (f, x, y, 0, 1);
+ window = window_from_coordinates (f, x, y, 0, true);
tool_bar_p = EQ (window, f->tool_bar_window);
if (tool_bar_p && event->xbutton.button < 4)
@@ -6795,7 +7647,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 +7667,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);
@@ -6826,7 +7679,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
any subsequent mouse-movement Emacs events should reflect
only motion after the ButtonPress/Release. */
if (f != 0)
- f->mouse_moved = 0;
+ f->mouse_moved = false;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
f = x_menubar_window_to_frame (dpyinfo, event);
@@ -6846,7 +7699,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)
@@ -6918,7 +7771,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (do_help > 0)
{
- any_help_event_p = 1;
+ any_help_event_p = true;
gen_help_event (help_echo_string, frame, help_echo_window,
help_echo_object, help_echo_pos);
}
@@ -6965,7 +7818,7 @@ static int
XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
{
int count = 0;
- int event_found = 0;
+ bool event_found = false;
struct x_display_info *dpyinfo = terminal->display_info.x;
block_input ();
@@ -6990,7 +7843,7 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
if (x_filter_event (dpyinfo, &event))
continue;
#endif
- event_found = 1;
+ event_found = true;
count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
@@ -7114,7 +7967,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 +7983,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;
}
@@ -7190,7 +8043,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
xgcv.background = xgcv.foreground = face->foreground;
else
xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
- xgcv.graphics_exposures = 0;
+ xgcv.graphics_exposures = False;
if (gc)
XChangeGC (dpy, gc, mask, &xgcv);
@@ -7235,12 +8088,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);
@@ -7286,14 +8139,14 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
if (on_p)
{
w->phys_cursor_type = cursor_type;
- w->phys_cursor_on_p = 1;
+ w->phys_cursor_on_p = true;
if (glyph_row->exact_window_width_line_p
&& (glyph_row->reversed_p
? (w->phys_cursor.hpos < 0)
: (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
{
- glyph_row->cursor_in_fringe_p = 1;
+ glyph_row->cursor_in_fringe_p = true;
draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
}
else
@@ -7340,13 +8193,13 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
/* Make the x-window of frame F use the gnu icon bitmap. */
-int
+bool
x_bitmap_icon (struct frame *f, Lisp_Object file)
{
ptrdiff_t bitmap_id;
if (FRAME_X_WINDOW (f) == 0)
- return 1;
+ return true;
/* Free up our existing icon bitmap and mask if any. */
if (f->output_data.x->icon_bitmap > 0)
@@ -7359,7 +8212,7 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
/* Use gtk_window_set_icon_from_file () if available,
It's not restricted to bitmaps */
if (xg_set_icon (f, file))
- return 0;
+ return false;
#endif /* USE_GTK */
bitmap_id = x_create_bitmap_from_file (f, file);
x_create_bitmap_mask (f, bitmap_id);
@@ -7373,9 +8226,12 @@ 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 (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 false;
+ }
#elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
@@ -7391,7 +8247,7 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
rc = x_create_bitmap_from_data (f, (char *) gnu_xbm_bits,
gnu_xbm_width, gnu_xbm_height);
if (rc == -1)
- return 1;
+ return true;
FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
@@ -7410,18 +8266,18 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
x_wm_set_icon_pixmap (f, bitmap_id);
f->output_data.x->icon_bitmap = bitmap_id;
- return 0;
+ return false;
}
/* Make the x-window of frame F use a rectangle with text.
Use ICON_NAME as the text. */
-int
+bool
x_text_icon (struct frame *f, const char *icon_name)
{
if (FRAME_X_WINDOW (f) == 0)
- return 1;
+ return true;
{
XTextProperty text;
@@ -7437,7 +8293,7 @@ x_text_icon (struct frame *f, const char *icon_name)
f->output_data.x->icon_bitmap = 0;
x_wm_set_icon_pixmap (f, 0);
- return 0;
+ return false;
}
#define X_ERROR_MESSAGE_SIZE 200
@@ -7555,7 +8411,8 @@ x_clear_errors (Display *dpy)
x_error_message->string[0] = 0;
}
-#if 0 /* See comment in unwind_to_catch why calling this is a bad
+#if false
+ /* See comment in unwind_to_catch why calling this is a bad
* idea. --lorentey */
/* Close off all unclosed x_catch_errors calls. */
@@ -7567,13 +8424,13 @@ x_fully_uncatch_errors (void)
}
#endif
-#if 0
+#if false
static unsigned int x_wire_count;
x_trace_wire (void)
{
fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
}
-#endif /* ! 0 */
+#endif
/************************************************************************
@@ -7789,10 +8646,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.
@@ -7811,8 +8667,9 @@ 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,
+ false, Qfont);
}
#ifdef HAVE_X_I18N
@@ -7868,11 +8725,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 +8959,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, false);
modified_left = f->left_pos;
modified_top = f->top_pos;
@@ -8125,8 +8977,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
modified_left, modified_top);
x_sync_with_move (f, f->left_pos, f->top_pos,
- FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
- ? 1 : 0);
+ FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
/* change_gravity is non-zero when this function is called from Lisp to
programmatically move a frame. In that case, we call
@@ -8138,32 +8989,33 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
either the window manager type (A/B) is unknown or it is Type A but we
need to compute the top/left offset adjustment for this frame. */
- if (change_gravity != 0 &&
- (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
- || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
- && (FRAME_X_OUTPUT (f)->move_offset_left == 0
- && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
+ if (change_gravity != 0
+ && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+ || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
+ && (FRAME_X_OUTPUT (f)->move_offset_left == 0
+ && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
x_check_expected_move (f, modified_left, modified_top);
unblock_input ();
}
-/* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
+/* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
on the root window for frame F contains ATOMNAME.
This is how a WM check shall be done according to the Window Manager
Specification/Extended Window Manager Hints at
http://freedesktop.org/wiki/Specifications/wm-spec. */
-static int
+static bool
wm_supports (struct frame *f, Atom want_atom)
{
Atom actual_type;
unsigned long actual_size, bytes_remaining;
int i, rc, actual_format;
+ bool ret;
Window wmcheck_window;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Window target_window = dpyinfo->root_window;
- long max_len = 65536;
+ int max_len = 65536;
Display *dpy = FRAME_X_DISPLAY (f);
unsigned char *tmp_data = NULL;
Atom target_type = XA_WINDOW;
@@ -8182,7 +9034,7 @@ wm_supports (struct frame *f, Atom want_atom)
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
unblock_input ();
- return 0;
+ return false;
}
wmcheck_window = *(Window *) tmp_data;
@@ -8195,7 +9047,7 @@ wm_supports (struct frame *f, Atom want_atom)
{
x_uncatch_errors ();
unblock_input ();
- return 0;
+ return false;
}
if (dpyinfo->net_supported_window != wmcheck_window)
@@ -8220,7 +9072,7 @@ wm_supports (struct frame *f, Atom want_atom)
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
unblock_input ();
- return 0;
+ return false;
}
dpyinfo->net_supported_atoms = (Atom *)tmp_data;
@@ -8228,19 +9080,19 @@ wm_supports (struct frame *f, Atom want_atom)
dpyinfo->net_supported_window = wmcheck_window;
}
- rc = 0;
+ ret = false;
- for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
- rc = dpyinfo->net_supported_atoms[i] == want_atom;
+ for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
+ ret = dpyinfo->net_supported_atoms[i] == want_atom;
x_uncatch_errors ();
unblock_input ();
- return rc;
+ return ret;
}
static void
-set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
+set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
@@ -8249,7 +9101,7 @@ set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
make_number (32),
/* 1 = add, 0 = remove */
Fcons
- (make_number (add ? 1 : 0),
+ (make_number (add),
Fcons
(make_fixnum_or_float (atom),
(value != 0
@@ -8265,32 +9117,33 @@ x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
XSETFRAME (frame, f);
- set_wm_state (frame, NILP (new_value) ? 0 : 1,
+ set_wm_state (frame, !NILP (new_value),
dpyinfo->Xatom_net_wm_state_sticky, None);
}
/* Return the current _NET_WM_STATE.
SIZE_STATE is set to one of the FULLSCREEN_* values.
- STICKY is set to 1 if the sticky state is set, 0 if not.
+ Set *STICKY to the sticky state.
- Return non-zero if we are not hidden, zero if we are. */
+ Return true iff we are not hidden. */
-static int
+static bool
get_current_wm_state (struct frame *f,
Window window,
int *size_state,
- int *sticky)
+ bool *sticky)
{
Atom actual_type;
unsigned long actual_size, bytes_remaining;
- int i, rc, actual_format, is_hidden = 0;
+ int i, rc, actual_format;
+ bool is_hidden = false;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
long max_len = 65536;
Display *dpy = FRAME_X_DISPLAY (f);
unsigned char *tmp_data = NULL;
Atom target_type = XA_ATOM;
- *sticky = 0;
+ *sticky = false;
*size_state = FULLSCREEN_NONE;
block_input ();
@@ -8314,10 +9167,7 @@ get_current_wm_state (struct frame *f,
{
Atom a = ((Atom*)tmp_data)[i];
if (a == dpyinfo->Xatom_net_wm_state_hidden)
- {
- is_hidden = 1;
- f->output_data.x->net_wm_state_hidden_seen = 1;
- }
+ is_hidden = true;
else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
{
if (*size_state == FULLSCREEN_HEIGHT)
@@ -8335,7 +9185,7 @@ get_current_wm_state (struct frame *f,
else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
*size_state = FULLSCREEN_BOTH;
else if (a == dpyinfo->Xatom_net_wm_state_sticky)
- *sticky = 1;
+ *sticky = true;
}
if (tmp_data) XFree (tmp_data);
@@ -8345,14 +9195,15 @@ get_current_wm_state (struct frame *f,
/* Do fullscreen as specified in extended window manager hints */
-static int
+static bool
do_ewmh_fullscreen (struct frame *f)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- int have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
- int cur, dummy;
+ bool have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
+ int cur;
+ bool dummy;
- (void)get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
+ get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
/* Some window managers don't say they support _NET_WM_STATE, but they do say
they support _NET_WM_STATE_FULLSCREEN. Try that also. */
@@ -8372,36 +9223,42 @@ do_ewmh_fullscreen (struct frame *f)
{
case FULLSCREEN_BOTH:
if (cur != FULLSCREEN_BOTH)
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_fullscreen,
+ set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
None);
break;
case FULLSCREEN_WIDTH:
if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
|| cur == FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
dpyinfo->Xatom_net_wm_state_maximized_vert);
if (cur != FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz, None);
break;
case FULLSCREEN_HEIGHT:
if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
|| cur == FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
dpyinfo->Xatom_net_wm_state_maximized_horz);
if (cur != FULLSCREEN_MAXIMIZED)
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_vert, None);
break;
case FULLSCREEN_MAXIMIZED:
if (cur == FULLSCREEN_BOTH)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
- set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz,
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+ None);
+ set_wm_state (frame, true,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
dpyinfo->Xatom_net_wm_state_maximized_vert);
break;
case FULLSCREEN_NONE:
if (cur == FULLSCREEN_BOTH)
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
+ set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+ None);
else
- set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
+ set_wm_state (frame, false,
+ dpyinfo->Xatom_net_wm_state_maximized_horz,
dpyinfo->Xatom_net_wm_state_maximized_vert);
}
@@ -8425,13 +9282,13 @@ XTfullscreen_hook (struct frame *f)
}
-static int
+static bool
x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
{
int value = FULLSCREEN_NONE;
Lisp_Object lval;
- int sticky = 0;
- int not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
+ bool sticky = false;
+ bool not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
lval = Qnil;
switch (value)
@@ -8533,7 +9390,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
adjusted_left, adjusted_top);
- x_sync_with_move (f, expected_left, expected_top, 0);
+ x_sync_with_move (f, expected_left, expected_top, false);
}
else
/* It's a "Type B" window manager. We don't have to adjust the
@@ -8550,7 +9407,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
of an exact comparison. */
static void
-x_sync_with_move (struct frame *f, int left, int top, int fuzzy)
+x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
{
int count = 0;
@@ -8573,7 +9430,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;
}
@@ -8581,7 +9438,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, false, Qnil, NULL, 0);
}
@@ -8604,7 +9461,7 @@ x_wait_for_event (struct frame *f, int eventtype)
while (f->wait_event_type)
{
- pending_signals = 1;
+ pending_signals = true;
totally_unblock_input ();
/* XTread_socket is called after unblock. */
block_input ();
@@ -8626,33 +9483,28 @@ 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
- doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
+/* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
+ doesn't have a widget. If CHANGE_GRAVITY, change to
top-left-corner window gravity for this size change and subsequent
- size changes. Otherwise we leave the window gravity unchanged. */
+ size changes. Otherwise leave the window gravity unchanged. */
static void
-x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
+x_set_window_size_1 (struct frame *f, bool change_gravity,
+ int width, int height, bool pixelwise)
{
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, false);
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
@@ -8672,7 +9524,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height,
wouldn't be reported in the frame parameters until some random
point in the future when the ConfigureNotify event arrives.
- We pass 1 for DELAY since we can't run Lisp code inside of
+ Pass true for DELAY since we can't run Lisp code inside of
a BLOCK_INPUT. */
/* But the ConfigureNotify may in fact never arrive, and then this is
@@ -8682,24 +9534,26 @@ 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, width, height, false, true, false, true);
x_sync (f);
}
}
/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+ If CHANGE_GRAVITY, change to top-left-corner window gravity
for this size change and subsequent size changes.
Otherwise we leave the window gravity unchanged. */
void
-x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
+x_set_window_size (struct frame *f, bool change_gravity,
+ int width, int height, bool pixelwise)
{
block_input ();
- check_frame_size (f, &width, &height, pixelwise);
-
+ /* The following breaks our calculations. If it's really needed,
+ think of something else. */
+#if false
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
int text_width, text_height;
@@ -8720,8 +9574,9 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
- change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
+ change_frame_size (f, text_width, text_height, false, true, false, true);
}
+#endif
#ifdef USE_GTK
if (FRAME_GTK_WIDGET (f))
@@ -8735,9 +9590,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 */
@@ -8751,35 +9604,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 (false);
}
/* 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 ();
@@ -8848,7 +9680,7 @@ x_ewmh_activate_frame (struct frame *f)
}
static void
-XTframe_raise_lower (struct frame *f, int raise_flag)
+XTframe_raise_lower (struct frame *f, bool raise_flag)
{
if (raise_flag)
x_raise_frame (f);
@@ -8930,7 +9762,7 @@ x_make_frame_visible (struct frame *f)
&& ! f->output_data.x->asked_for_visible)
x_set_offset (f, f->left_pos, f->top_pos, 0);
- f->output_data.x->asked_for_visible = 1;
+ f->output_data.x->asked_for_visible = true;
if (! EQ (Vx_no_window_manager, Qt))
x_wm_set_window_state (f, NormalState);
@@ -8965,7 +9797,7 @@ x_make_frame_visible (struct frame *f)
/* This must be before UNBLOCK_INPUT
since events that arrive in response to the actions above
will set it when they are handled. */
- int previously_visible = f->output_data.x->has_been_visible;
+ bool previously_visible = f->output_data.x->has_been_visible;
original_left = f->left_pos;
original_top = f->top_pos;
@@ -9080,7 +9912,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, true);
#ifdef USE_GTK
if (FRAME_GTK_OUTER_WIDGET (f))
@@ -9107,7 +9939,7 @@ x_make_frame_invisible (struct frame *f)
FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
and synchronize with the server to make sure we agree. */
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 0);
+ SET_FRAME_ICONIFIED (f, false);
x_sync (f);
@@ -9142,7 +9974,7 @@ x_iconify_frame (struct frame *f)
gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
unblock_input ();
return;
}
@@ -9160,7 +9992,7 @@ x_iconify_frame (struct frame *f)
that an invisible frame was changed to an icon,
so we have to record it here. */
SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
unblock_input ();
return;
}
@@ -9173,7 +10005,7 @@ x_iconify_frame (struct frame *f)
if (!result)
error ("Can't notify window manager of iconification");
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
SET_FRAME_VISIBLE (f, 0);
block_input ();
@@ -9223,7 +10055,7 @@ x_iconify_frame (struct frame *f)
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
}
- SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_ICONIFIED (f, true);
SET_FRAME_VISIBLE (f, 0);
XFlush (FRAME_X_DISPLAY (f));
@@ -9250,6 +10082,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. */
@@ -9287,6 +10124,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
@@ -9308,13 +10148,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)
@@ -9402,6 +10242,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)
{
@@ -9435,8 +10278,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. */
@@ -9636,7 +10477,7 @@ static XrmOptionDescRec emacs_options[] = {
/* Whether atimer for Xt timeouts is activated or not. */
-static int x_timeout_atimer_activated_flag;
+static bool x_timeout_atimer_activated_flag;
#endif /* USE_X_TOOLKIT */
@@ -9644,12 +10485,13 @@ static int x_initialized;
/* Test whether two display-name strings agree up to the dot that separates
the screen number from the server number. */
-static int
+static bool
same_x_server (const char *name1, const char *name2)
{
- int seen_colon = 0;
- const char *system_name = SSDATA (Vsystem_name);
- ptrdiff_t system_name_length = SBYTES (Vsystem_name);
+ bool seen_colon = false;
+ Lisp_Object sysname = Fsystem_name ();
+ const char *system_name = SSDATA (sysname);
+ ptrdiff_t system_name_length = SBYTES (sysname);
ptrdiff_t length_until_period = 0;
while (system_name[length_until_period] != 0
@@ -9679,9 +10521,9 @@ same_x_server (const char *name1, const char *name2)
for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
{
if (*name1 == ':')
- seen_colon = 1;
+ seen_colon = true;
if (seen_colon && *name1 == '.')
- return 1;
+ return true;
}
return (seen_colon
&& (*name1 == '.' || *name1 == '\0')
@@ -9713,14 +10555,17 @@ get_bits_and_offset (unsigned long mask, int *bits, int *offset)
*bits = nr;
}
-/* Return 1 if display DISPLAY is available for use, 0 otherwise.
+/* Return true iff display DISPLAY is available for use.
But don't permanently open it, just test its availability. */
bool
x_display_ok (const char *display)
{
Display *dpy = XOpenDisplay (display);
- return dpy ? (XCloseDisplay (dpy), 1) : 0;
+ if (!dpy)
+ return false;
+ XCloseDisplay (dpy);
+ return true;
}
#ifdef USE_GTK
@@ -9733,6 +10578,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;
@@ -9744,7 +10679,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;
@@ -9796,10 +10730,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
@@ -9860,12 +10790,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
argv[argc++] = "-xrm";
argv[argc++] = xrm_option;
}
- turn_on_atimers (0);
+ turn_on_atimers (false);
dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
resource_name, EMACS_CLASS,
emacs_options, XtNumber (emacs_options),
&argc, argv);
- turn_on_atimers (1);
+ turn_on_atimers (true);
#ifdef HAVE_X11XTR6
/* I think this is to compensate for XtSetLanguageProc. */
@@ -9948,18 +10878,20 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
/* Set the name of the terminal. */
terminal->name = xlispstrdup (display_name);
-#if 0
+#if false
XSetAfterFunction (x_current_display, x_trace_wire);
-#endif /* ! 0 */
+#endif
lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
- if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name))
+ Lisp_Object system_name = Fsystem_name ();
+ if (lim - SBYTES (Vinvocation_name) < SBYTES (system_name))
memory_full (SIZE_MAX);
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));
+ + SBYTES (system_name) + 2);
+ char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
+ *nametail++ = '@';
+ lispstpcpy (nametail, system_name);
/* Figure out which modifier bits mean what. */
x_find_modifier_meanings (dpyinfo);
@@ -9973,6 +10905,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
@@ -10010,11 +10945,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")))
@@ -10027,14 +10962,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;
}
@@ -10095,6 +11043,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)
@@ -10124,11 +11073,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)];
@@ -10136,7 +11085,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;
@@ -10147,11 +11096,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;
@@ -10162,24 +11108,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
{
@@ -10198,6 +11144,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
@@ -10205,11 +11153,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")))
@@ -10217,11 +11164,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")
@@ -10238,8 +11184,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
@@ -10301,7 +11247,7 @@ static void
x_process_timeouts (struct atimer *timer)
{
block_input ();
- x_timeout_atimer_activated_flag = 0;
+ x_timeout_atimer_activated_flag = false;
if (toolkit_scroll_bar_interaction || popup_activated ())
{
while (XtAppPending (Xt_app_con) & XtIMTimer)
@@ -10328,7 +11274,7 @@ x_activate_timeout_atimer (void)
{
struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
- x_timeout_atimer_activated_flag = 1;
+ x_timeout_atimer_activated_flag = true;
}
unblock_input ();
}
@@ -10363,7 +11309,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
};
@@ -10386,8 +11334,7 @@ x_delete_terminal (struct terminal *terminal)
xim_close_dpy (dpyinfo);
#endif
- /* If called from x_connection_closed, the display may already be closed
- and dpyinfo->display was set to 0 to indicate that. */
+ /* Normally, the display is available... */
if (dpyinfo->display)
{
x_destroy_all_bitmaps (dpyinfo);
@@ -10407,7 +11354,7 @@ x_delete_terminal (struct terminal *terminal)
don't destroy the database here in order to avoid the crash
in the above situations for now, though that may cause memory
leaks in other situations. */
-#if 0
+#if false
#ifdef HAVE_XRMSETDATABASE
XrmSetDatabase (dpyinfo->display, NULL);
#else
@@ -10428,15 +11375,23 @@ x_delete_terminal (struct terminal *terminal)
XCloseDisplay (dpyinfo->display);
#endif
#endif /* ! USE_GTK */
+ /* Do not close the connection here because it's already closed
+ by X(t)CloseDisplay (Bug#18403). */
+ dpyinfo->display = NULL;
}
- /* No more input on this descriptor. */
- if (0 <= dpyinfo->connection)
- delete_keyboard_wait_descriptor (dpyinfo->connection);
+ /* ...but if called from x_connection_closed, the display may already
+ be closed and dpyinfo->display was set to 0 to indicate that. Since
+ X server is most likely gone, explicit close is the only reliable
+ way to continue and avoid Bug#19147. */
+ else if (dpyinfo->connection >= 0)
+ emacs_close (dpyinfo->connection);
+ /* No more input on this descriptor. */
+ delete_keyboard_wait_descriptor (dpyinfo->connection);
/* Mark as dead. */
- dpyinfo->display = NULL;
dpyinfo->connection = -1;
+
x_delete_display (dpyinfo);
unblock_input ();
}
@@ -10449,9 +11404,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;
@@ -10462,38 +11416,37 @@ 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;
+ any_help_event_p = false;
ignore_next_mouse_click_timeout = 0;
#ifdef USE_GTK
@@ -10532,6 +11485,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)
@@ -10556,7 +11518,7 @@ UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
to 4.1, set this to nil. You can also use `underline-minimum-offset'
to override the font's UNDERLINE_POSITION for small font display
sizes. */);
- x_use_underline_position_properties = 1;
+ x_use_underline_position_properties = true;
DEFVAR_BOOL ("x-underline-at-descent-line",
x_underline_at_descent_line,
@@ -10564,7 +11526,7 @@ sizes. */);
A value of nil means to draw the underline according to the value of the
variable `x-use-underline-position-properties', which is usually at the
baseline level. The default value is nil. */);
- x_underline_at_descent_line = 0;
+ x_underline_at_descent_line = false;
DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
x_mouse_click_focus_ignore_position,
@@ -10574,7 +11536,7 @@ click on a frame to select it (give it focus). In that case, a value
of nil, means that the selected window and cursor position changes to
reflect the mouse click position, while a non-nil value means that the
selected window or cursor position is preserved. */);
- x_mouse_click_focus_ignore_position = 0;
+ x_mouse_click_focus_ignore_position = false;
DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
doc: /* Which toolkit scroll bars Emacs uses, if any.
diff --git a/src/xterm.h b/src/xterm.h
index 4683a4c7877..e597227c81c 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
+
+ /* True 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. */
@@ -922,16 +979,13 @@ XrmDatabase x_load_resources (Display *, const char *, const char *,
/* Defined in xterm.c */
-extern int x_text_icon (struct frame *, const char *);
+extern bool x_text_icon (struct frame *, const char *);
extern void x_catch_errors (Display *);
extern void x_check_errors (Display *, const char *)
ATTRIBUTE_FORMAT_PRINTF (2, 0);
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. */
@@ -976,10 +1049,10 @@ extern void x_send_client_event (Lisp_Object display,
Lisp_Object format,
Lisp_Object values);
-extern int x_handle_dnd_message (struct frame *,
- const XClientMessageEvent *,
- struct x_display_info *,
- struct input_event *);
+extern bool x_handle_dnd_message (struct frame *,
+ const XClientMessageEvent *,
+ struct x_display_info *,
+ struct input_event *);
extern int x_check_property_data (Lisp_Object);
extern void x_fill_property_data (Display *,
Lisp_Object,
@@ -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 bool xg_set_icon (struct frame *, Lisp_Object);
+extern bool 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 *);
@@ -1013,7 +1081,7 @@ extern bool x_defined_color (struct frame *, const char *, XColor *, bool);
#ifdef HAVE_X_I18N
extern void free_frame_xic (struct frame *);
# if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
-extern char * xic_create_fontsetname (const char *base_fontname, int motif);
+extern char *xic_create_fontsetname (const char *, bool);
# endif
#endif
@@ -1031,34 +1099,18 @@ extern Lisp_Object xw_popup_dialog (struct frame *, Lisp_Object, Lisp_Object);
#endif
#if defined USE_GTK || defined USE_MOTIF
-extern void x_menu_set_in_use (int);
+extern void x_menu_set_in_use (bool);
#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);
-extern int x_session_have_connection (void);
+extern bool x_session_have_connection (void);
extern void x_session_close (void);
#endif
-/* Defined in xterm.c */
-
-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? */
@@ -1079,4 +1131,6 @@ extern void x_clear_under_internal_border (struct frame *f);
(nr).width = (rwidth), \
(nr).height = (rheight))
+INLINE_HEADER_END
+
#endif /* XTERM_H */