summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit81
-rw-r--r--src/ChangeLog4437
-rw-r--r--src/ChangeLog.112
-rw-r--r--src/ChangeLog.22
-rw-r--r--src/ChangeLog.32
-rw-r--r--src/Makefile.in68
-rw-r--r--src/alloc.c957
-rw-r--r--src/atimer.c142
-rw-r--r--src/bidi.c152
-rw-r--r--src/blockinput.h124
-rw-r--r--src/buffer.c355
-rw-r--r--src/buffer.h82
-rw-r--r--src/bytecode.c29
-rw-r--r--src/callint.c1
-rw-r--r--src/callproc.c478
-rw-r--r--src/casefiddle.c4
-rw-r--r--src/casetab.c2
-rw-r--r--src/category.c7
-rw-r--r--src/ccl.c1
-rw-r--r--src/character.c7
-rw-r--r--src/character.h17
-rw-r--r--src/charset.c25
-rw-r--r--src/charset.h1
-rw-r--r--src/chartab.c12
-rw-r--r--src/cm.c3
-rw-r--r--src/cmds.c4
-rw-r--r--src/coding.c159
-rw-r--r--src/coding.h28
-rw-r--r--src/commands.h3
-rw-r--r--src/composite.c56
-rw-r--r--src/composite.h2
-rw-r--r--src/conf_post.h54
-rw-r--r--src/cygw32.c138
-rw-r--r--src/cygw32.h39
-rw-r--r--src/data.c224
-rw-r--r--src/dbusbind.c16
-rw-r--r--src/deps.mk1
-rw-r--r--src/dired.c303
-rw-r--r--src/dispextern.h38
-rw-r--r--src/dispnew.c238
-rw-r--r--src/doc.c31
-rw-r--r--src/doprnt.c10
-rw-r--r--src/dosfns.c6
-rw-r--r--src/editfns.c434
-rw-r--r--src/emacs.c390
-rw-r--r--src/emacsgtkfixed.c9
-rw-r--r--src/eval.c320
-rw-r--r--src/fileio.c838
-rw-r--r--src/filelock.c25
-rw-r--r--src/floatfns.c637
-rw-r--r--src/fns.c320
-rw-r--r--src/font.c233
-rw-r--r--src/font.h50
-rw-r--r--src/fontset.c46
-rw-r--r--src/frame.c735
-rw-r--r--src/frame.h63
-rw-r--r--src/fringe.c20
-rw-r--r--src/ftfont.c32
-rw-r--r--src/ftxfont.c39
-rw-r--r--src/gmalloc.c16
-rw-r--r--src/gnutls.c44
-rw-r--r--src/gtkutil.c279
-rw-r--r--src/gtkutil.h38
-rw-r--r--src/image.c1002
-rw-r--r--src/indent.c106
-rw-r--r--src/indent.h6
-rw-r--r--src/inotify.c437
-rw-r--r--src/insdel.c86
-rw-r--r--src/intervals.c36
-rw-r--r--src/keyboard.c1049
-rw-r--r--src/keyboard.h35
-rw-r--r--src/keymap.c167
-rw-r--r--src/keymap.h13
-rw-r--r--src/lisp.h615
-rw-r--r--src/lisp.mk8
-rw-r--r--src/lread.c360
-rw-r--r--src/macros.c4
-rw-r--r--src/makefile.w32-in207
-rw-r--r--src/marker.c52
-rw-r--r--src/menu.c50
-rw-r--r--src/menu.h8
-rw-r--r--src/minibuf.c46
-rw-r--r--src/msdos.c65
-rw-r--r--src/ndir.h41
-rw-r--r--src/ns.mk39
-rw-r--r--src/nsfns.m170
-rw-r--r--src/nsfont.m90
-rw-r--r--src/nsimage.m11
-rw-r--r--src/nsmenu.m65
-rw-r--r--src/nsselect.m5
-rw-r--r--src/nsterm.h50
-rw-r--r--src/nsterm.m1232
-rw-r--r--src/print.c26
-rw-r--r--src/process.c1190
-rw-r--r--src/process.h26
-rw-r--r--src/profiler.c607
-rw-r--r--src/puresize.h2
-rw-r--r--src/ralloc.c89
-rw-r--r--src/regex.c10
-rw-r--r--src/region-cache.c25
-rw-r--r--src/scroll.c6
-rw-r--r--src/search.c93
-rw-r--r--src/sheap.c3
-rw-r--r--src/sound.c40
-rw-r--r--src/syntax.c16
-rw-r--r--src/sysdep.c947
-rw-r--r--src/syssignal.h131
-rw-r--r--src/systty.h39
-rw-r--r--src/syswait.h8
-rw-r--r--src/term.c128
-rw-r--r--src/termcap.c1
-rw-r--r--src/termchar.h22
-rw-r--r--src/termhooks.h57
-rw-r--r--src/terminal.c20
-rw-r--r--src/terminfo.c3
-rw-r--r--src/termopts.h11
-rw-r--r--src/textprop.c33
-rw-r--r--src/tparam.c4
-rw-r--r--src/undo.c2
-rw-r--r--src/unexaix.c1
-rw-r--r--src/unexcoff.c7
-rw-r--r--src/unexcw.c15
-rw-r--r--src/unexelf.c12
-rw-r--r--src/unexmacosx.c21
-rw-r--r--src/unexsol.c1
-rw-r--r--src/unexw32.c65
-rw-r--r--src/vm-limit.c90
-rw-r--r--src/w16select.c9
-rw-r--r--src/w32.c401
-rw-r--r--src/w32.h104
-rw-r--r--src/w32common.h53
-rw-r--r--src/w32console.c55
-rw-r--r--src/w32fns.c1213
-rw-r--r--src/w32font.c16
-rw-r--r--src/w32font.h2
-rw-r--r--src/w32gui.h6
-rw-r--r--src/w32heap.c98
-rw-r--r--src/w32heap.h31
-rw-r--r--src/w32inevt.c305
-rw-r--r--src/w32inevt.h2
-rw-r--r--src/w32menu.c67
-rw-r--r--src/w32notify.c631
-rw-r--r--src/w32proc.c1009
-rw-r--r--src/w32reg.c5
-rw-r--r--src/w32select.c29
-rw-r--r--src/w32select.h28
-rw-r--r--src/w32term.c402
-rw-r--r--src/w32term.h127
-rw-r--r--src/w32uniscribe.c7
-rw-r--r--src/w32xfns.c177
-rw-r--r--src/widget.c45
-rw-r--r--src/window.c551
-rw-r--r--src/window.h51
-rw-r--r--src/xdisp.c909
-rw-r--r--src/xfaces.c321
-rw-r--r--src/xfns.c276
-rw-r--r--src/xfont.c54
-rw-r--r--src/xftfont.c71
-rw-r--r--src/xgselect.c6
-rw-r--r--src/xmenu.c127
-rw-r--r--src/xml.c11
-rw-r--r--src/xrdb.c114
-rw-r--r--src/xselect.c128
-rw-r--r--src/xsettings.c10
-rw-r--r--src/xsmfns.c2
-rw-r--r--src/xterm.c528
-rw-r--r--src/xterm.h30
167 files changed, 18481 insertions, 12245 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index de980c6345f..e1ee81e66b5 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -495,7 +495,8 @@ define pgx
end
xgettype ($g.object)
if ($type == Lisp_String)
- printf " str=%x[%d]", $g.object, $g.charpos
+ xgetptr $g.object
+ printf " str=0x%x[%d]", ((struct Lisp_String *)$ptr)->data, $g.charpos
else
printf " pos=%d", $g.charpos
end
@@ -650,19 +651,52 @@ If the first type printed is Lisp_Vector or Lisp_Misc,
a second line gives the more precise type.
end
+define pvectype
+ set $size = ((struct Lisp_Vector *) $arg0)->header.size
+ if ($size & PSEUDOVECTOR_FLAG)
+ output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
+ else
+ output PVEC_NORMAL_VECTOR
+ end
+ echo \n
+end
+document pvectype
+Print the subtype of vectorlike object.
+Takes one argument, a pointer to an object.
+end
+
define xvectype
xgetptr $
- set $size = ((struct Lisp_Vector *) $ptr)->header.size
+ pvectype $ptr
+end
+document xvectype
+Print the subtype of vectorlike object.
+This command assumes that $ is a Lisp_Object.
+end
+
+define pvecsize
+ set $size = ((struct Lisp_Vector *) $arg0)->header.size
if ($size & PSEUDOVECTOR_FLAG)
- output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_SIZE_BITS)
+ output ($size & PSEUDOVECTOR_SIZE_MASK)
+ echo \n
+ output (($size & PSEUDOVECTOR_REST_MASK) >> PSEUDOVECTOR_SIZE_BITS)
else
- output $size & ~ARRAY_MARK_FLAG
+ output ($size & ~ARRAY_MARK_FLAG)
end
echo \n
end
-document xvectype
-Print the size or vector subtype of $.
-This command assumes that $ is a vector or pseudovector.
+document pvecsize
+Print the size of vectorlike object.
+Takes one argument, a pointer to an object.
+end
+
+define xvecsize
+ xgetptr $
+ pvecsize $ptr
+end
+document xvecsize
+Print the size of $
+This command assumes that $ is a Lisp_Object.
end
define xmisctype
@@ -996,7 +1030,7 @@ define xpr
if $type == Lisp_Vectorlike
set $size = ((struct Lisp_Vector *) $ptr)->header.size
if ($size & PSEUDOVECTOR_FLAG)
- set $vec = (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_SIZE_BITS)
+ set $vec = (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
if $vec == PVEC_NORMAL_VECTOR
xvector
end
@@ -1121,18 +1155,18 @@ end
define xbacktrace
set $bt = backtrace_list
while $bt
- xgettype (*$bt->function)
+ xgettype ($bt->function)
if $type == Lisp_Symbol
- xprintsym (*$bt->function)
+ xprintsym ($bt->function)
printf " (0x%x)\n", $bt->args
else
- xgetptr *$bt->function
+ xgetptr $bt->function
printf "0x%x ", $ptr
if $type == Lisp_Vectorlike
- xgetptr (*$bt->function)
+ xgetptr ($bt->function)
set $size = ((struct Lisp_Vector *) $ptr)->header.size
if ($size & PSEUDOVECTOR_FLAG)
- output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_SIZE_BITS)
+ output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
else
output $size & ~ARRAY_MARK_FLAG
end
@@ -1213,24 +1247,9 @@ set print sevenbit-strings
show environment DISPLAY
show environment TERM
-# People get bothered when they see messages about non-existent functions...
-xgetptr globals.f_Vsystem_type
-# $ptr is NULL in temacs
-if ($ptr != 0)
- set $tem = (struct Lisp_Symbol *) $ptr
- xgetptr $tem->name
- set $tem = (struct Lisp_String *) $ptr
- set $tem = (char *) $tem->data
-
- # Don't let abort actually run, as it will make stdio stop working and
- # therefore the `pr' command above as well.
- if $tem[0] == 'w' && $tem[1] == 'i' && $tem[2] == 'n' && $tem[3] == 'd'
- # The windows-nt build replaces abort with its own function.
- break w32_abort
- else
- break abort
- end
-end
+# When debugging, it is handy to be able to "return" from
+# terminate_due_to_signal when an assertion failure is non-fatal.
+break terminate_due_to_signal
# x_error_quitter is defined only on X. But window-system is set up
# only at run time, during Emacs startup, so we need to defer setting
diff --git a/src/ChangeLog b/src/ChangeLog
index a8d6a4026a0..3cf105c8003 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,4396 @@
+2012-12-16 Romain Francoise <romain@orebokech.com>
+
+ * fileio.c (Ffile_acl, Fset_file_acl): New functions.
+ (Fcopy_file): Change last arg to `preserve_extended_attributes'
+ and copy ACL entries of file in addition to SELinux context if
+ set.
+ (syms_of_fileio): Add `file-acl' and `set-file-acl'.
+
+ * Makefile.in (LIBACL_LIBS): New macro.
+ (LIBES): Use it.
+
+2012-12-15 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fileio.c (internal_delete_file): Use bool for boolean.
+
+2012-12-15 Eli Zaretskii <eliz@gnu.org>
+
+ Fix bug #13079 on MS-Windows with temp files not being deleted.
+ * w32.h (_child_process): New members input_file and
+ pending_deletion.
+ (register_child): First argument is now pid_t.
+ (record_infile, record_pending_deletion): New prototypes.
+
+ * w32proc.c (new_child): Initialize input_file and
+ pending_deletion members of the child.
+ (delete_child): Delete the child's temporary input file, if any,
+ that is pending deletion.
+ (register_child): First argument is now pid_t.
+ (record_infile, record_pending_deletion): New functions.
+ (reap_subprocess): Fix a typo in DebPrint string.
+ (sys_spawnve, sys_kill): Use pid_t for PID arguments.
+
+ * fileio.c (internal_delete_file): Return an int again: non-zero
+ if delete-file succeeds, zero otherwise.
+
+ * lisp.h (internal_delete_file): Adjust prototype.
+
+ * callproc.c (Fcall_process): Don't overwrite infile with result
+ of DECODE_FILE.
+ [WINDOWSNT] If BUFFER is an integer, i.e. we are launching an
+ asynchronous subprocess, record the name of the input file name,
+ if any.
+ (delete_temp_file) [WINDOWSNT]: If internal_delete_file fails to
+ delete the file, record it as pending deletion when the subprocess
+ exits.
+
+2012-12-14 Eli Zaretskii <eliz@gnu.org>
+
+ * editfns.c [HAVE_PWD_H]: Include grp.h.
+
+ * makefile.w32-in ($(BLD)/editfns.$(O)): Add $(NT_INC)/grp.h.
+
+2012-12-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix permissions bugs with setgid directories etc. (Bug#13125)
+ * dired.c (Ffile_attributes): Return t as the 9th attribute,
+ to mark it as a placeholder. The old value was often wrong.
+ The only user of this attribute has been changed to use
+ file-ownership-preserved-p instead, with its new group arg.
+ * editfns.c (Fgroup_gid, Fgroup_real_gid): New functions.
+
+2012-12-14 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * xdisp.c (select_frame_for_redisplay, display_mode_lines):
+ Keep selected_window and selected_frame in sync.
+
+2012-12-14 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (stat_worker): If w32_stat_get_owner_group is zero, do not
+ try to get accurate owner and group information from NT file
+ security APIs. This is to make most callers of 'stat' and
+ 'lstat', which don't need that information, much faster.
+
+ * dired.c (Ffile_attributes) [WINDOWSNT]:
+ Set w32_stat_get_owner_group to a non-zero value, to request accurate
+ owner and group information from 'lstat'.
+
+2012-12-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fileio.c (Finsert_file_contents): Don't put tail into head area,
+ as that confuses set-auto-coding, so insist on the head-read
+ returning the full 1024 bytes. Let lseek compute the tail offset;
+ less work for us. Do not ignore I/O errors when reading the tail.
+
+ * xdisp.c: Minor style fixes.
+ (init_iterator): Hoist assignment out of if-expression.
+ (markpos_of_region): Callers now test for sign, not for -1.
+
+2012-12-13 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Minor redisplay optimization when the region length is zero.
+ * xdisp.c (markpos_of_region): New function.
+ (init_iterator): Do not highlight the region of zero length.
+ (redisplay_window): Check whether the region is of non-zero length.
+ (try_cursor_movement): Allow if the region length is zero.
+ (try_window_reusing_current_matrix, try_window_id): Likewise.
+
+2012-12-13 Eli Zaretskii <eliz@gnu.org>
+
+ * search.c (search_buffer): Check the inverse translations of each
+ character in pattern when the buffer being searched is unibyte.
+ (Bug#13084)
+
+2012-12-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fileio.c (Fvisited_file_modtime): Return (-1 ...) for nonexistent
+ files, fixing a regression from 24.2.
+ (Fverify_visited_file_modtime): Don't read uninitialized st.st_size.
+
+2012-12-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fileio.c (Fcopy_file): Make fstat failure as serious as open failure.
+ fstat shouldn't fail, and if it does fail copy-file should not proceed.
+ Remove unnecessary S_ISLNK test, as (contra the comments) this
+ function can't copy symlinks. Improve quality of error message
+ when attempting to copy files that are neither regular files nor
+ directories.
+
+2012-12-12 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * dispnew.c (set_window_cursor_after_update): Use clip_to_bounds.
+ * gtkutil.c (xg_set_toolkit_scroll_bar_thumb):
+ * window.c (Frecenter):
+ * xdisp.c (resize_mini_window, hscroll_window_tree, draw_glyphs):
+ * xterm.c (x_set_toolkit_scroll_bar_thumb): Likewise.
+
+2012-12-12 Daniel Colascione <dancol@dancol.org>
+
+ * unexcw.c (fixup_executable): use posix_fallocate to ensure that
+ the dumped Emacs is not a sparse file, greatly improving Cygwin
+ "make bootstrap" performance.
+
+2012-12-11 Michael Albinus <michael.albinus@gmx.de>
+
+ * inotify.c (inotify_callback): Generate an Emacs event for every
+ incoming inotify event.
+
+2012-12-11 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (handle_face_prop): Fix logic of computing
+ it->start_of_box_run_p.
+ (append_space_for_newline): If the glyph row is R2L, reset the
+ iterator's end_of_box_run_p flag before prepending the space glyph.
+ (extend_face_to_end_of_line): If the glyph row is R2L, reset the
+ iterator's start_of_box_run_p flag before prepending the stretch.
+ (append_glyph, produce_image_glyph, append_composite_glyph)
+ (append_stretch_glyph, append_glyphless_glyph): Reverse the
+ left_box_line_p and right_box_line_p flags of the glyph for R2L
+ glyph rows. (Bug#13011)
+
+2012-12-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * buffer.c (Fset_buffer_multibyte): Do not force redisplay
+ if changed buffer is not shown in a window.
+ * insdel.c (prepare_to_modify_buffer): Likewise.
+ * window.c (replace_buffer_in_windows_safely): Do nothing
+ if buffer is not shown in a window.
+ (Fforce_window_update): Likewise if string or buffer argument
+ is passed.
+
+2012-12-11 Eli Zaretskii <eliz@gnu.org>
+
+ * inotify.c (Finotify_add_watch): Rename decoded_file_name to
+ encoded_file_name, which is what it is.
+
+2012-12-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Consistently use marker_position and marker_byte_position.
+ * fringe.c (Ffringe_bitmaps_at_pos):
+ * indent.c (Fvertical_motion):
+ * insdel.c (prepare_to_modify_buffer):
+ * keyboard.c (make_lispy_position):
+ * window.c (Fwindow_end, Fpos_visible_in_window_p, unshow_buffer)
+ (window_scroll_pixel_based, displayed_window_lines)
+ (Fset_window_configuration):
+ * xdisp.c (message_dolog, with_echo_area_buffer_unwind_data)
+ (mark_window_display_accurate_1, redisplay_window, decode_mode_spec):
+ Replace direct access to marker fields with calls
+ to marker_position and/or marker_byte_position.
+
+2012-12-11 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in (SIG2STR_H): New macro.
+ (SYSWAIT_H, $(BLD)/emacs.$(O), $(BLD)/process.$(O))
+ ($(BLD)/w32notify.$(O)): Update dependencies.
+
+2012-12-10 Daniel Colascione <dancol@dancol.org>
+
+ * w32term.c, keyboard.c: Fix build break in cygw32 by omitting
+ Windows file notification functionality unless WINDOWSNT.
+
+ * w32gui.h (hprevinst, lpCmdLine, nCmdShow): Remove unused
+ declarations.
+
+ * w32fns.c (cache_system_info): Initialize the global hinst
+ variable here so various initialization calls DTRT.
+
+ * unexw32.c (hprevinst, lpCmdLine, nCmdShow): Remove unused
+ variables.
+ (hinst): Remove unneeded extern declaration.
+ (_start): Remove initialization of above variables; remove
+ initialization of hinst, as cache_system_info now does that.
+
+ * emacs.c (main): Call cache_system_info early in startup; we
+ previously weren't calling it in Cygwin builds.
+
+ * Makefile.in (ntsource, WINDRES, W32_RES, W#@_RES_LINK):
+ Teach the autoconf build system how to compile a Windows resource file
+ and link it to Emacs.
+
+2012-12-10 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Per-buffer window counters.
+ * buffer.h (struct buffer): New member window_count.
+ (buffer_window_count): New function.
+ * buffer.c (Fget_buffer_create, Fmake_indirect_buffer):
+ Initialize window_count.
+ (Fkill_buffer): Verify window_count for the buffer being killed.
+ (modify_overlay): Do not force redisplay if buffer is not shown
+ in any window.
+ (init_buffer_once): Initialize window_count for buffer_defaults
+ and buffer_local_symbols.
+ * window.h (buffer_shared): Remove declaration.
+ (wset_buffer): Convert from inline ...
+ * window.c (wset_buffer): ... to an ordinary function.
+ (adjust_window_count): New function.
+ (make_parent_window): Use it.
+ * xdisp.c (buffer_shared): Remove.
+ (redisplay_internal, redisplay_window): Adjust users.
+ (buffer_shared_and_changed): Use per-buffer window counter.
+
+2012-12-10 Eli Zaretskii <eliz@gnu.org>
+
+ Support for filesystem notifications on MS-Windows.
+ * w32proc.c (sys_select): If drain_message_queue returns non-zero,
+ and this is a TTY frame, signal the caller that keyboard input is
+ available.
+
+ * w32xfns.c (drain_message_queue): Now returns an int: an
+ indication whether any WM_EMACS_FILENOTIFY messages were found in
+ the queue.
+
+ * w32inevt.c (handle_file_notifications): New function.
+ (w32_console_read_socket): Call it to process file notifications.
+
+ * w32console.c (initialize_w32_display): Record the main thread ID
+ in dwMainThreadId.
+
+ * deps.mk (inotify.o): New dependency list.
+
+ * Makefile.in (SOME_MACHINE_OBJECTS): Add w32notify.o.
+
+ * w32term.h (WM_EMACS_FILENOTIFY): New custom message.
+ (WM_EMACS_END): Bump value by 1.
+ (notification_buffer_in_use, file_notifications)
+ (notifications_size, notifications_desc): Declare.
+ (w32_get_watch_object, lispy_file_action, globals_of_w32notify):
+ Add prototypes.
+
+ * w32term.c (lispy_file_action, queue_notifications): New functions.
+ (syms_of_w32term) <Qadded, Qremoved, Qmodified, Qrenamed_from>
+ <Qrenamed_to>: New symbols.
+ (w32_read_socket): Handle the WM_EMACS_FILENOTIFY message.
+
+ * w32notify.c: New file, implements file event notifications for
+ MS-Windows.
+
+ * w32fns.c (w32_wnd_proc): Handle the WM_EMACS_FILENOTIFY message
+ by posting it to the w32_read_socket queue.
+
+ * termhooks.h (enum event_kind) [HAVE_NTGUI]: Support
+ FILE_NOTIFY_EVENT.
+
+ * makefile.w32-in (OBJ2): Add $(BLD)/w32notify.$(O).
+ (GLOBAL_SOURCES): Add w32notify.c
+ ($(BLD)/w32notify.$(O)): New set of dependencies.
+
+ * lisp.h (syms_of_w32notify) [WINDOWSNT]: Add prototype.
+
+ * keyboard.c (kbd_buffer_get_event) [WINDOWSNT]: Handle
+ FILE_NOTIFY_EVENT.
+ (syms_of_keyboard) [HAVE_NTGUI] <Qfile_notify>: New symbol.
+ (keys_of_keyboard) [WINDOWSNT]: Bind file-notify to
+ w32notify-handle-event by default.
+
+ * emacs.c (main) [WINDOWSNT]: Call globals_of_w32notify and
+ syms_of_w32notify.
+
+2012-12-10 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+
+ Support for filesystem notifications on GNU/Linux via inotify.
+ * termhooks.h (enum event_kind) [HAVE_INOTIFY]: Add
+ FILE_NOTIFY_EVENT.
+
+ * lisp.h (syms_of_inotify) [HAVE_INOTIFY]: Add prototype.
+
+ * keyboard.c (Qfile_inotify) [HAVE_INOTIFY]: New variable.
+ (syms_of_keyboard): DEFSYM it.
+ (kbd_buffer_get_event) [HAVE_INOTIFY]: Generate FILE_NOTIFY_EVENT.
+ (make_lispy_event): Support FILE_NOTIFY_EVENT by generating
+ Qfile_inotify events.
+ (keys_of_keyboard) [HAVE_INOTIFY]: Bind file-inotify events in
+ special-event-map to inotify-handle-event.
+
+ * emacs.c (main) [HAVE_INOTIFY]: Call syms_of_inotify.
+
+ * Makefile.in (base_obj): Add inotify.o.
+
+ * inotify.c: New file.
+
+2012-12-10 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (fd_handler:): FD_ZERO fds (Bug#13103).
+
+2012-12-10 Fabrice Popineau <fabrice.popineau@gmail.com>
+
+ * w32fns.c (cache_system_info): Cast sysinfo_cache.dwPageSize to
+ DWORD_PTR, for compatibility with 64-bit builds.
+
+ * w32.c (_PROCESS_MEMORY_COUNTERS_EX):
+ (GetProcessWorkingSetSize_Proc, get_process_working_set_size)
+ (system_process_attributes): Use SIZE_T rather than DWORD, for
+ compatibility with 64-bit builds.
+
+2012-12-10 Christopher Schmidt <christopher@ch.ristopher.com>
+
+ * lread.c (Vload_source_file_function): Doc fix (Bug#11647).
+
+2012-12-10 Eli Zaretskii <eliz@gnu.org>
+
+ * indent.c (Fvertical_motion): If a display string will be
+ displayed on the left or the right margin, don't consider it as a
+ factor in cursor positioning. (Bug#13108)
+
+2012-12-10 Martin Rudalics <rudalics@gmx.at>
+
+ * editfns.c (Fcompare_buffer_substrings): Reword doc-string.
+
+2012-12-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fileio.c (Fsubstitute_in_file_name): Use ptrdiff_t, not int,
+ for string length.
+
+2012-12-08 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (unsetenv): Return 0 if the input string is too long.
+
+2012-12-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use putenv+unsetenv instead of modifying environ directly (Bug#13070).
+ * alloc.c (xputenv): New function.
+ * dbusbind.c (Fdbus_init_bus):
+ * emacs.c (main):
+ * xterm.c (x_term_init):
+ Use xputenv instead of setenv or putenv, to detect memory exhaustion.
+ * editfns.c (initial_tz): Move static var decl up.
+ (tzvalbuf_in_environ): New static var.
+ (init_editfns): Initialize these two static vars.
+ (Fencode_time): Don't assume arbitrary limit on EMACS_INT width.
+ Save old TZ value on stack, if it's small.
+ (Fencode_time, set_time_zone_rule): Don't modify 'environ' directly;
+ instead, use xputenv+unsetenv to set and restore TZ.
+ (environbuf): Remove static var. All uses removed.
+ (Fset_time_zone_rule): Do not save TZ and environ;
+ no longer needed here.
+ (set_time_zone_rule_tz1, set_time_zone_rule_tz2) [LOCALTIME_CACHE]:
+ Move to inside set_time_zone_rule; they don't need file scope any more.
+ (set_time_zone_rule): Maintain the TZ=value string separately.
+ (syms_of_editfns): Don't initialize initial_tz;
+ init_editfns now does it.
+ * emacs.c (dump_tz) [HAVE_TZSET]: Now const.
+ * lisp.h (xputenv): New decl.
+
+2012-12-08 Fabrice Popineau <fabrice.popineau@gmail.com>
+
+ * w32fns.c (emacs_abort): Don't do arithmetics on void pointers.
+
+2012-12-08 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (unsetenv, sys_putenv): New functions.
+
+2012-12-08 Chong Yidong <cyd@gnu.org>
+
+ * editfns.c (Finsert_char): Make the error message more
+ informative (Bug#12992).
+
+2012-12-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Simplify get_lim_data.
+ * vm-limit.c (get_lim_data): Combine RLIMIT_AS and RLIMIT_DATA methods.
+ Remove USG and vlimit methods; no longer used these days.
+ Add #error catchall just in case.
+
+ Assume POSIX 1003.1-1988 or later for signal.h (Bug#13026).
+ Exceptions: do not assume SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN,
+ SIGTTOU, SIGUSR1, SIGUSR2, as Microsoft platforms lack these.
+ * process.c [subprocesses]: Include <c-ctype.h>, <sig2str.h>.
+ (deleted_pid_list, Fdelete_process, create_process)
+ (record_child_status_change, handle_child_signal, deliver_child_signal)
+ (init_process_emacs, syms_of_process):
+ Assume SIGCHLD is defined.
+ (parse_signal): Remove. All uses removed.
+ (abbr_to_signal): New static function.
+ (Fsignal_process): Use it to convert signal names to ints.
+ * sysdep.c (sys_suspend) [!DOS_NT]: Use kill (0, ...) rather than
+ kill (getpgrp (), ...).
+ (emacs_sigaction_init): Assume SIGCHLD is defined.
+ (init_signals): Assume SIGALRM, SIGCHLD, SIGHUP, SIGKILL,
+ SIGPIPE, and SIGQUIT are defined. Do not worry about SIGCLD any more.
+ * syssignal.h (EMACS_KILLPG): Remove.
+ All uses replaced by 'kill' with a negative pid.
+ (SIGCHLD): Remove definition, as we now assume SIGCHLD.
+ * w32proc.c (sys_kill): Support negative pids compatibly with POSIX.
+
+2012-12-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ * sysdep.c (get_child_status): Abort on internal error (Bug#13086).
+ This will cause a production Emacs to dump core instead of
+ infinite-looping.
+
+2012-12-07 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * frame.c (make_frame): Do not set window's buffer to t.
+ * window.c (Fsplit_window_internal): Likewise. Previously it was
+ used to indicate that the window is being set up. Now we use
+ set_window_buffer for all new windows, so the condition in ...
+ (Fset_window_buffer): ... is always true and can be removed.
+
+2012-12-07 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Convenient macro to check whether the buffer is hidden.
+ * buffer.h (BUFFER_HIDDEN_P): New macro.
+ * frame.c (make_frame): Use it. Adjust comment.
+ * buffer.c (candidate_buffer): New function.
+ (Fother_buffer, other_buffer_safely): Use it.
+
+2012-12-06 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (waitpid): Avoid busy-waiting when called with WNOHANG
+ if the child process is still running. Instead, exit the wait
+ loop and return zero. (Bug#13086)
+
+2012-12-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * frame.h (x_char_width, x_char_height): Remove prototypes.
+ * w32term.h (x_char_width, x_char_height): Likewise.
+ * xfns.c (x_char_width, x_char_height): Remove.
+ * w32fns.c (x_char_width, x_char_height): Likewise.
+ * nsfns.c (x_char_width, x_char_height): Likewise.
+ * frame.c (Fframe_char_width): Use FRAME_COLUMN_WIDTH for
+ all window frames.
+ (Fframe_char_height): Likewise with FRAME_LINE_HEIGHT.
+ * keyboard.c (command_loop_1): Remove prototype.
+ (command_loop_2, top_level_1): Add static to match prototype.
+
+2012-12-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix a recently-introduced delete-process race condition.
+ * callproc.c, process.h (record_kill_process):
+ New function, containing part of the old call_process_kill.
+ (call_process_kill): Use it.
+ This does not change call_process_kill's behavior.
+ * process.c (Fdelete_process): Use record_kill_process to fix a
+ race condition that could cause Emacs to lose track of a child.
+
+2012-12-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Avoid code duplication between prev_frame and next_frame.
+ * frame.c (candidate_frame): New function. Add comment.
+ (prev_frame, next_frame): Use it. Adjust comment.
+
+2012-12-06 Eli Zaretskii <eliz@gnu.org>
+
+ * callproc.c (Fcall_process_region) [!HAVE_MKSTEMP]: If mktemp
+ fails, signal an error instead of continuing with an empty
+ string. (Bug#13079)
+ Encode expanded temp file pattern before passing it to mkstemp or
+ mktemp.
+
+ * fileio.c (file_name_as_directory, directory_file_name) [DOS_NT]:
+ Encode the file name before passing it to dostounix_filename, in
+ case it will downcase it (under w32-downcase-file-names).
+ (Bug#12933)
+
+2012-12-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ Minor call-process cleanups.
+ * callproc.c (Fcall_process): Do record-unwind-protect on MSDOS
+ at the same time as other platforms, to simplify analysis.
+ No need for fd0_volatile since we have synch_process_fd.
+ Avoid needless emacs_close; arg is always negative.
+
+2012-12-04 Andreas Schwab <schwab@linux-m68k.org>
+
+ * callproc.c (Fcall_process): Fix specpdl nesting for asynchronous
+ processes.
+
+2012-12-04 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * lisp.h (Mouse_HLInfo): Remove set-but-unused mouse_face_image_state
+ member. Adjust users. Convert mouse_face_past_end, mouse_face_defer
+ and mouse_face_hidden members to a bitfields.
+ * frame.h (struct frame): Remove set-but-not-used space_width member.
+ (FRAME_SPACE_WIDTH): Remove.
+ * nsterm.m, w32term.c, xterm.c: Adjust users.
+ * termchar.h (struct tty_display_info): Remove set-but-unused se_is_so
+ member. Adjust users. Convert term_initted, delete_in_insert_mode,
+ costs_set, insert_mode, standout_mode, cursor_hidden and flow_control
+ members to a bitfields.
+
+2012-12-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Don't let call-process be a zombie factory (Bug#12980).
+ Fixing this bug required some cleanup of the signal-handling code.
+ As a side effect, this change also fixes a longstanding rare race
+ condition whereby Emacs could mistakenly kill unrelated processes,
+ and it fixes a bug where a second C-g does not kill a recalcitrant
+ synchronous process in GNU/Linux and similar platforms.
+ The patch should also fix the last vestiges of Bug#9488,
+ a bug which has mostly been fixed on the trunk by other changes.
+ * callproc.c, process.h (synch_process_alive, synch_process_death)
+ (synch_process_termsig, sync_process_retcode):
+ Remove. All uses removed, to simplify analysis and so that
+ less consing is done inside critical sections.
+ * callproc.c (call_process_exited): Remove. All uses replaced
+ with !synch_process_pid.
+ * callproc.c (synch_process_pid, synch_process_fd): New static vars.
+ These take the role of what used to be in unwind-protect arg.
+ All uses changed.
+ (block_child_signal, unblock_child_signal):
+ New functions, to avoid races that could kill innocent-victim processes.
+ (call_process_kill, call_process_cleanup, Fcall_process): Use them.
+ (call_process_kill): Record killed processes as deleted, so that
+ zombies do not clutter up the system. Do this inside a critical
+ section, to avoid a race that would allow the clutter.
+ (call_process_cleanup): Fix code so that the second C-g works again
+ on common platforms such as GNU/Linux.
+ (Fcall_process): Create the child process in a critical section,
+ to fix a race condition. If creating an asynchronous process,
+ record it as deleted so that zombies do not clutter up the system.
+ Do unwind-protect for WINDOWSNT too, as that's simpler in the
+ light of these changes. Omit unnecessary call to emacs_close
+ before failure, as the unwind-protect code does that.
+ * callproc.c (call_process_cleanup):
+ * w32proc.c (waitpid): Simplify now that synch_process_alive is gone.
+ * process.c (record_deleted_pid): New function, containing
+ code refactored out of Fdelete_process.
+ (Fdelete_process): Use it.
+ (process_status_retrieved): Remove. All callers changed to use
+ child_status_change.
+ (record_child_status_change): Remove, folding its contents into ...
+ (handle_child_signal): ... this signal handler. Now, this
+ function is purely a handler for SIGCHLD, and is not called after
+ a synchronous waitpid returns; the synchronous code is moved to
+ wait_for_termination. There is no need to worry about reaping
+ more than one child now.
+ * sysdep.c (get_child_status, child_status_changed): New functions.
+ (wait_for_termination): Now takes int * status and bool
+ interruptible arguments, too. Do not record child status change;
+ that's now the caller's responsibility. All callers changed.
+ Reimplement in terms of get_child_status.
+ (wait_for_termination_1, interruptible_wait_for_termination):
+ Remove. All callers changed to use wait_for_termination.
+ * syswait.h: Include <stdbool.h>, for bool.
+ (record_child_status_change, interruptible_wait_for_termination):
+ Remove decls.
+ (record_deleted_pid, child_status_changed): New decls.
+ (wait_for_termination): Adjust to API changes noted above.
+
+ * bytecode.c, lisp.h (Qbytecode): Remove.
+ No longer needed after 2012-11-20 interactive-p changes.
+
+2012-12-03 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (redisplay_window): If the cursor is visible, but inside
+ the scroll margin, move point outside the margin. (Bug#13055)
+
+2012-12-03 Jan Djärv <jan.h.d@swipnet.se>
+
+ * gtkutil.c (my_log_handler): New function.
+ (xg_set_geometry): Set log handler to my_log_handler (Bug#11177).
+
+2012-12-03 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * lisp.h (modify_region): Rename to...
+ (modify_region_1): ...new prototype.
+ * textprop.c (modify_region): Now static. Adjust users.
+ * insdel.c (modify_region): Rename to...
+ (modify_region_1): ...new function to work with current buffer.
+ Adjust comment and users. Use true and false for booleans.
+
+2012-12-03 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (free_save_value): New function.
+ (safe_alloca_unwind): Use it.
+ * lisp.h (free_save_value): New prototype.
+ * editfns.c (save_excursion_save): Use Lisp_Misc_Save_Value.
+ Add comment.
+ (save_excursion_restore): Adjust to match saved data structure.
+ Use free_save_value to offload some work from GC. Drop obsolete
+ #if 0 code.
+
+2012-12-03 Chong Yidong <cyd@gnu.org>
+
+ * fileio.c (Vauto_save_list_file_name): Doc fix.
+
+2012-12-03 Fabrice Popineau <fabrice.popineau@gmail.com>
+
+ * w32fns.c: Remove prototype of atof.
+ (syspage_mask): Declared DWORD_PTR, for compatibility with 64-bit
+ builds.
+ (file_dialog_callback): Declared UINT_PTR.
+
+ * w32common.h (syspage_mask): Declare DWORD_PTR, for compatibility
+ with 64-bit builds.
+
+ * w32.c (FILE_DEVICE_FILE_SYSTEM, METHOD_BUFFERED)
+ (FILE_ANY_ACCESS, CTL_CODE) [_MSC_VER]: Define only if not already
+ defined.
+
+2012-12-03 Glenn Morris <rgm@gnu.org>
+
+ * data.c (Fboundp, Fsymbol_value): Doc fix re lexical-binding.
+
+2012-12-02 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix xpalloc confusion after memory is exhausted.
+ * alloc.c (xpalloc): Comment fix.
+ * charset.c (Fdefine_charset_internal): If xpalloc exhausts memory
+ and signals an error, do not clear charset_table_size, as
+ charset_table is still valid.
+ * doprnt.c (evxprintf): Clear *BUF after freeing it.
+
+ Use execve to avoid need to munge environ (Bug#13054).
+ * callproc.c (Fcall_process):
+ * process.c (create_process):
+ Don't save and restore environ; no longer needed.
+ * callproc.c (child_setup):
+ Use execve, not execvp, to preserve environ.
+
+2012-12-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ * xterm.c (x_draw_image_relief): Remove unused locals (Bug#10500).
+
+2012-12-01 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
+
+ * xterm.c (x_draw_relief_rect, x_draw_image_relief): Fix relief
+ display for sliced images (Bug#10500).
+
+ * w32term.c (w32_draw_relief_rect, x_draw_image_relief): Likewise.
+
+2012-11-30 Juanma Barranquero <lekktu@gmail.com>
+
+ * doc.c (Fdocumentation): Re-add handling of function-documentation,
+ accidentally removed in 2012-11-09T04:10:16Z!monnier@iro.umontreal.ca (bug#13034).
+
+2012-11-29 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xdisp.c (window_outdated): Remove eassert since it hits
+ some suspicious corner cases (see Bug#13007 and Bug#13012).
+ (mode_line_update_needed): New function.
+ (redisplay_internal, redisplay_window): Use it.
+ (ensure_selected_frame): New function.
+ (redisplay_internal, unwind_redisplay): Use it.
+ (redisplay_internal): Move comment about buffer_shared...
+ (buffer_shared_and_changed): ...near to its real use.
+
+2012-11-29 Paul Eggert <eggert@cs.ucla.edu>
+
+ * callproc.c (Fcall_process): Don't misreport vfork failure.
+
+2012-11-28 Paul Eggert <eggert@cs.ucla.edu>
+
+ * callproc.c (Fcall_process): Fix vfork portability problems.
+ Do not assume that fd[0], count, filefd, and save_environ survive
+ vfork. Fix bug whereby wrong errno value could be reported for
+ pipe failure. Some minor cleanups, too, as follows. Move buf and
+ bufsize to the context where they're needed. Change new_argv to
+ be of type char **, as this is more convenient and avoids casts.
+ (CALLPROC_BUFFER_SIZE_MIN, CALLPROC_BUFFER_SIZE_MAX):
+ Now local constants, not macros.
+
+2012-11-18 Kenichi Handa <handa@gnu.org>
+
+ * font.c (font_unparse_xlfd): Fix previous change. Keep "const"
+ for the variable "f".
+
+2012-11-13 Kenichi Handa <handa@gnu.org>
+
+ * font.c (font_unparse_xlfd): Exclude special characters from the
+ generating XLFD name.
+
+2012-11-27 Paul Eggert <eggert@cs.ucla.edu>
+
+ Assume POSIX 1003.1-1988 or later for grp.h, pwd.h.
+ * dired.c (stat_uname, stat_gname):
+ * fileio.c (Fexpand_file_name): Remove no-longer-needed casts.
+
+ Assume POSIX 1003.1-1988 or later for errno.h (Bug#12968).
+ * dired.c (directory_files_internal, file_name_completion):
+ Assume EAGAIN and EINTR are defined.
+
+ * fileio.c (Fcopy_file): Assume EISDIR is defined.
+ * gmalloc.c (ENOMEM, EINVAL): Assume they're defined.
+ * gnutls.c (emacs_gnutls_write): Assume EAGAIN is defined.
+ * lread.c (readbyte_from_file): Assume EINTR is defined.
+ * process.c (wait_reading_process_output, send_process) [subprocesses]:
+ Assume EIO and EAGAIN are defined.
+ * unexcoff.c (write_segment): Assume EFAULT is defined.
+
+2012-11-27 Eli Zaretskii <eliz@gnu.org>
+
+ * fontset.c (Finternal_char_font): Return nil on non-GUI frames.
+ (Bug#11964)
+
+ * xdisp.c (draw_glyphs): Don't draw in mouse face if mouse
+ highlighting on the frame was cleared. Prevents assertion
+ violations when repeatedly clicking on the "Top" link of the
+ "bread-crumbs" in Info buffers.
+
+2012-11-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ * sysdep.c (sys_subshell): Don't assume pid_t fits in int.
+
+2012-11-24 Ken Brown <kbrown@cornell.edu>
+
+ * keyboard.c (HAVE_MOUSE):
+ * frame.c (HAVE_MOUSE): Remove, and rewrite code as if HAVE_MOUSE
+ were always defined.
+
+2012-11-24 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (set_cursor_from_row): Skip step 2 only if point is not
+ between bpos_covered and bpos_max. This fixes cursor display when
+ several display strings follow each other.
+
+ * .gdbinit (pgx): If the glyph's object is a string, display the
+ pointer to string data, rather than the value of the string object
+ itself (which barfs under CHECK_LISP_OBJECT_TYPE).
+
+ * indent.c (Fvertical_motion): If the starting position is covered
+ by a display string, return to one position before that, to avoid
+ overshooting it inside move_it_to. (Bug#12930)
+
+2012-11-23 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * frame.h (struct frame): Remove display_preempted member
+ since all users are dead long ago.
+ * nsterm.h (struct x_output): Use the only dummy member.
+ * w32menu.c (pending_menu_activation): Remove since not
+ really used.
+ (set_frame_menubar): Adjust user.
+ * w32term.h (struct x_output): Drop outdated #if 0 code.
+ (struct w32_output): Use bitfields for explicit_parent,
+ asked_for_visible and menubar_active members.
+ Drop unused pending_menu_activation member.
+ * xterm.h (struct x_output): Drop outdated #if 0 code.
+ Use bitfields for explicit_parent, asked_for_visible,
+ has_been_visible and net_wm_state_hidden_seen members.
+
+2012-11-23 Eli Zaretskii <eliz@gnu.org>
+
+ * makefile.w32-in (globals.h, gl-stamp): Use $(SWITCHCHAR) instead
+ of a literal "/". (Bug#12955)
+ (gl-stamp): Invoke fc.exe directly, not through cmd.
+
+2012-11-23 Paul Eggert <eggert@cs.ucla.edu>
+
+ Assume POSIX 1003.1-1988 or later for dirent.h (Bug#12958).
+ * dired.c: Assume HAVE_DIRENT_H.
+ (NAMLEN): Remove, replacing with ...
+ (dirent_namelen): New function. All uses changed. Use the GNU macro
+ _D_EXACT_NAMELEN if available, as it's faster than strlen.
+ (DIRENTRY): Remove, replacing all uses with 'struct dirent'.
+ (DIRENTRY_NONEMPTY): Remove. All callers now assume it's nonzero.
+ * makefile.w32-in (DIR_H): Remove. All uses replaced with
+ $(NT_INC)/dirent.h.
+ ($(BLD)/w32.$(O)): Do not depend on $(SRC)/ndir.h.
+ * ndir.h: Rename to ../nt/inc/dirent.h.
+ * sysdep.h (closedir) [!HAVE_CLOSEDIR]: Remove.
+ Do not include <dirent.h>; no longer needed.
+ * w32.c: Include <dirent.h> rather than "ndir.h".
+
+2012-11-23 Chong Yidong <cyd@gnu.org>
+
+ * xftfont.c (xftfont_open): Remove duplicate assignment.
+
+2012-11-22 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (Fgarbage_collect): Unblock input after clearing
+ gc_in_progress to avoid note_mouse_highlight glitch with GC.
+ * frame.h (FRAME_MOUSE_UPDATE): New macro.
+ * msdos.c (IT_frame_up_to_date): Use it here...
+ * w32term.c (w32_frame_up_to_date): ...here...
+ * xterm.c (XTframe_up_to_date): ...and here...
+ * nsterm.m (ns_frame_up_to_date): ...but not here.
+ * lisp.h (Mouse_HLInfo): Remove mouse_face_deferred_gc member.
+ Adjust users.
+ * xdisp.c (message2_nolog, message3_nolog, note_mouse_highlight):
+ Do not check whether GC is in progress.
+
+2012-11-22 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xdisp.c (window_buffer_changed): New function.
+ (update_menu_bar, update_tool_bar): Use it to
+ simplify large 'if' statements.
+ (redisplay_internal): Generalize commonly used
+ 'tail' and 'frame' local variables.
+
+2012-11-22 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (getcwd): Fix the 2nd argument type, to prevent conflicts
+ with Windows system header.
+
+2012-11-21 Paul Eggert <eggert@cs.ucla.edu>
+
+ Assume POSIX 1003.1-1988 or later for unistd.h (Bug#12945).
+ * alloc.c: Assume unistd.h exists.
+ * fileio.c (Fexpand_file_name) [DOS_NT]: Use getcwd, not getwd.
+ * sysdep.c (get_current_dir_name): Assume getcwd exists.
+ (getwd) [USG]: Remove; no longer needed.
+ (sys_subshell) [DOS_NT]: Use getcwd, not getwd.
+ * w32.c (getcwd): Rename from getwd, and switch to getcwd's API.
+ * w32.h (getcwd): Remove decl.
+
+2012-11-21 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * xdisp.c (fast_set_selected_frame): Rename from update_tool_bar_unwind.
+ Make it set selected_window as well.
+ (update_tool_bar): Use it.
+
+2012-11-21 Ken Brown <kbrown@cornell.edu>
+
+ * emacs.c (main): Set the G_SLICE environment variable for all
+ Cygwin builds, not just GTK builds. See
+ https://lists.gnu.org/archive/html/emacs-devel/2012-11/msg00368.html.
+
+2012-11-21 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (FILE_DEVICE_FILE_SYSTEM, METHOD_BUFFERED)
+ (FILE_ANY_ACCESS, CTL_CODE, FSCTL_GET_REPARSE_POINT) [_MSC_VER]:
+ Define for the MSVC compiler.
+
+ * w32term.h (EnumSystemLocalesW) [_MSC_VER]: Add a missing semi-colon.
+
+ * fileio.c (Fsubstitute_in_file_name, Ffile_name_directory)
+ (Fexpand_file_name) [DOS_NT]: Pass encoded file name to
+ dostounix_filename. Prevents crashes down the road, because
+ dostounix_filename assumes it gets a unibyte string.
+ Reported by Michel de Ruiter <michel@sentient.nl>, see
+ http://lists.gnu.org/archive/html/help-emacs-windows/2012-11/msg00017.html
+
+2012-11-20 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ Conflate Qnil and Qunbound for `symbol-function'.
+ * alloc.c (Fmake_symbol): Initialize `function' to Qnil.
+ * lread.c (init_obarray): Set `function' fields to Qnil.
+ * eval.c (Fcommandp): Ignore Qunbound.
+ (Fautoload, eval_sub, Fapply, Ffuncall, Fmacroexpand):
+ * data.c (Ffset, Ffboundp, indirect_function, Findirect_function):
+ Test NILP rather than Qunbound.
+ (Ffmakunbound): Set to Qnil.
+ (Fsymbol_function): Never signal an error.
+ (Finteractive_form): Ignore Qunbound.
+
+2012-11-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ * eval.c (interactive_p): Remove no-longer-used decl.
+
+2012-11-20 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xdisp.c (buffer_shared): Adjust comment.
+ (buffer_shared_and_changed): New function.
+ (prepare_menu_bars, redisplay_internal): Use it to
+ decide whether all windows or frames should be updated.
+ (window_outdated): New function.
+ (text_outside_line_unchanged_p, redisplay_window): Use it.
+ (redisplay_internal): Likewise. Fix indentation.
+
+2012-11-20 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * eval.c (Finteractive_p, Fcalled_interactively_p, interactive_p): Remove.
+ (syms_of_eval): Remove corresponding defsubr.
+ * bytecode.c (exec_byte_code): `interactive-p' is now a Lisp function.
+
+2012-11-19 Daniel Colascione <dancol@dancol.org>
+
+ * w32fns.c (Fx_file_dialog):
+ (Fx_file_dialog): Accomodate rename of cygwin_convert_path* to
+ cygwin_convert_file_name*.
+
+ * cygw32.c (Fcygwin_convert_path_to_windows, syms_of_cygw32):
+ Rename cygwin_convert_path* to cygwin_convert_file_name*.
+
+2012-11-18 Paul Eggert <eggert@cs.ucla.edu>
+
+ * nsterm.m (ns_select): Send SIGIO only to self, not to process group.
+
+2012-11-18 Eli Zaretskii <eliz@gnu.org>
+
+ * w32select.c: Include w32common.h before w32term.h, so that
+ windows.h gets included before w32term.h uses some of its
+ features, see below.
+
+ * w32term.h (LOCALE_ENUMPROCA, LOCALE_ENUMPROCW) [_MSC_VER]:
+ New typedefs.
+ (EnumSystemLocalesA, EnumSystemLocalesW) [_MSC_VER]:
+ New prototypes.
+ (EnumSystemLocales) [_MSC_VER]: Define if undefined. (Bug#12878)
+
+2012-11-18 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (hold_event): Set send_appdefined to YES (Bug#12834).
+ (ns_select): Return at once if events are held (Bug#12834).
+
+2012-11-18 enami tsugutomo <tsugutomo.enami@jp.sony.com>
+
+ * unexelf.c (ELFSIZE) [__NetBSD__ && _LP64]: Set to 64.
+ Needed following 2012-10-20 change. (Bug#12902)
+
+2012-11-18 Juanma Barranquero <lekktu@gmail.com>
+
+ * w32proc.c (waitpid): Remove unused label get_result.
+
+2012-11-17 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in (SYSWAIT_H): New macro.
+ ($(BLD)/callproc.$(O), $(BLD)/w32proc.$(O), $(BLD)/process.$(O))
+ ($(BLD)/sysdep.$(O)): Update dependencies.
+
+2012-11-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ Assume POSIX 1003.1-1988 or later for fcntl.h (Bug#12881).
+ * callproc.c (relocate_fd): Assume F_DUPFD.
+ * emacs.c, term.c (O_RDWR): Remove.
+ * keyboard.c (tty_read_avail_input): Use O_NONBLOCK rather than
+ O_NDELAY, since O_NONBLOCK is the standard name for this flag.
+ * nsterm.m: Assume <fcntl.h> exists.
+ * process.c (NON_BLOCKING_CONNECT, allocate_pty, create_process)
+ (create_pty, Fmake_network_process, server_accept_connection)
+ (wait_reading_process_output, init_process_emacs):
+ Assume O_NONBLOCK.
+ (wait_reading_process_output): Put in a special case for WINDOWSNT
+ to mimick the older behavior where it had O_NDELAY but not O_NONBLOCK.
+ It's not clear this is needed, but it's a more-conservative change.
+ (create_process): Assume FD_CLOEXEC.
+ (create_process, create_pty): Assume O_NOCTTY.
+ * sysdep.c (init_sys_modes, reset_sys_modes): Assume F_SETFL.
+ (reset_sys_modes): Use O_NONBLOCK rather than O_NDELAY.
+ Omit if not DOS_NT, since F_GETFL is not defined there.
+ (serial_open): Assume O_NONBLOCK and O_NOCTTY.
+ * term.c: Include <fcntl.h>, for flags like O_NOCTTY.
+ (O_NOCTTY): Remove.
+ (init_tty): Assume O_IGNORE_CTTY is defined to 0 on platforms that
+ lack it, since gnulib guarantees this.
+ * w32.c (fcntl): Test for O_NONBLOCK rather than O_NDELAY.
+
+2012-11-17 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (faccessat): Pretend that directories have the execute bit
+ set. Emacs expects that, e.g., in files.el:cd-absolute.
+
+ * w32proc.c (create_child): Don't clip the PID of the child
+ process to fit into an Emacs integer, as this is no longer a
+ restriction.
+ (waitpid): Rename from sys_wait. Emulate a Posix 'waitpid' by
+ reaping only the process specified by PID argument, if that is
+ positive. Use PID instead of dead_child to know which process to
+ reap. Wait for the child to die only if WNOHANG is not in
+ OPTIONS.
+ (sys_select): Don't set dead_child.
+
+ * sysdep.c (wait_for_termination_1): Remove the WINDOWSNT portion,
+ as it is no longer needed.
+
+ * process.c (waitpid, WUNTRACED) [!WNOHANG]: Remove definitions,
+ no longer needed.
+ (record_child_status_change): Remove the setting of
+ record_at_most_one_child for the !WNOHANG case.
+
+2012-11-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix problems in ns port found by static checking.
+ * nsterm.m: Include <pthread.h>, for pthread_mutex_lock etc.
+ (hold_event, setPosition:portion:whole:): Send SIGIO only to self,
+ not to process group.
+ (ns_select): Use emacs_write, not write, as that's more robust
+ in the presence of signals.
+ (fd_handler:): Check for read errors.
+
+2012-11-16 Glenn Morris <rgm@gnu.org>
+
+ * editfns.c (Fmessage): Mention message-log-max. (Bug#12849)
+
+2012-11-16 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * eval.c (Finteractive_p): Revert lexbind-merge mishap.
+
+2012-11-16 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (timer_loop): Make sure SuspendThread and ResumeThread
+ use the same value of thread handle.
+ (start_timer_thread): If the timer thread exited (due to error),
+ clean up by closing the two handles it used. Duplicate the caller
+ thread's handle here, so it gets duplicated only once, when
+ launching the timer thread. Set priority of the timer thread, not
+ the caller thread.
+ (getitimer): Don't duplicate the caller thread's handle here.
+ (Bug#12832)
+
+2012-11-16 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (hold_event): Send SIGIO to make sure ns_read_socket is
+ called (Bug#12834).
+
+2012-11-16 Paul Eggert <eggert@cs.ucla.edu>
+
+ Remove no-longer-used pty_max_bytes variable.
+ * process.c (pty_max_bytes): Remove; unused.
+ (send_process): Do not set it.
+
+2012-11-15 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/dispnew.$(O), $(BLD)/emacs.$(O)):
+ Update dependencies.
+
+2012-11-15 Paul Eggert <eggert@cs.ucla.edu>
+
+ * eval.c (mark_backtrace) [BYTE_MARK_STACK]: Remove stray '*'.
+ This follows up on the 2012-09-29 patch that removed indirection
+ for the 'function' field. Reported by Sergey Vinokurov in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-11/msg00263.html>.
+
+2012-11-14 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (faccessat): Rename from sys_faccessat. (No need to use a
+ different name, as the MS runtime does not have such a function,
+ and probably never will.) All callers changed. Ignore DIRFD
+ value if PATH is an absolute file name, to match Posix spec
+ better. If AT_SYMLINK_NOFOLLOW is set in FLAGS, don't resolve
+ symlinks.
+
+2012-11-14 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xdisp.c (echo_area_display, redisplay_internal):
+ Omit redundant check whether frame_garbaged is set.
+
+2012-11-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use faccessat, not access, when checking file permissions (Bug#12632).
+ This fixes a bug that has been present in Emacs since its creation.
+ It was reported by Chris Torek in 1983 even before GNU Emacs existed,
+ which must set some sort of record. (Torek's bug report was against
+ a predecessor of GNU Emacs, but GNU Emacs happened to have the
+ same common flaw.) See Torek's Usenet posting
+ "setuid/setgid programs & Emacs" Article-I.D.: sri-arpa.858
+ Posted: Fri Apr 8 14:18:56 1983.
+ * Makefile.in (LIB_EACCESS): New macro.
+ (LIBES): Use it.
+ * callproc.c (init_callproc):
+ * charset.c (init_charset):
+ * fileio.c (check_existing, check_executable, check_writable)
+ (Ffile_readable_p):
+ * lread.c (openp, load_path_check):
+ * process.c (allocate_pty):
+ * xrdb.c (file_p):
+ Use effective UID when checking permissions, not real UID.
+ * callproc.c (init_callproc):
+ * charset.c (init_charset):
+ * lread.c (load_path_check, init_lread):
+ Test whether directories are accessible, not merely whether they exist.
+ * conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): New macro.
+ * fileio.c (check_existing, check_executable, check_writable)
+ (Ffile_readable_p):
+ Use symbolic names instead of integers for the flags, as they're
+ portable now.
+ (check_writable): New arg AMODE. All uses changed.
+ Set errno on failure.
+ (Ffile_readable_p): Use faccessat, not stat + open + close.
+ (Ffile_writable_p): No need to call check_existing + check_writable.
+ Just call check_writable and then look at errno. This saves a syscall.
+ dir should never be nil; replace an unnecessary runtime check
+ with an eassert. When checking the parent directory of a nonexistent
+ file, check that the directory is searchable as well as writable, as
+ we can't create files in unsearchable directories.
+ (file_directory_p): New function, which uses 'stat' on most platforms
+ but faccessat with D_OK (for efficiency) if WINDOWSNT.
+ (Ffile_directory_p, Fset_file_times): Use it.
+ (file_accessible_directory_p): New function, which uses a single
+ syscall for efficiency.
+ (Ffile_accessible_directory_p): Use it.
+ * xrdb.c (file_p): Use file_directory_p.
+ * lisp.h (file_directory_p, file_accessible_directory_p): New decls.
+ * lread.c (openp): When opening a file, use fstat rather than
+ stat, as that avoids a permissions race. When not opening a file,
+ use file_directory_p rather than stat.
+ (dir_warning): First arg is now a usage string, not a format.
+ Use errno. All uses changed.
+ * nsterm.m (ns_term_init): Remove unnecessary call to file-readable
+ that merely introduced a race.
+ * process.c, sysdep.c, term.c: All uses of '#ifdef O_NONBLOCK'
+ changed to '#if O_NONBLOCK', to accommodate gnulib O_* style,
+ and similarly for the other O_* flags.
+ * w32.c (sys_faccessat): Rename from sys_access and switch to
+ faccessat's API. All uses changed.
+ * xrdb.c: Do not include <sys/stat.h>; no longer needed.
+ (magic_db): Rename from magic_file_p.
+ (magic_db, search_magic_path): Return an XrmDatabase rather than a
+ char *, so that we don't have to test for file existence
+ separately from opening the file for reading. This removes a race
+ fixes a permission-checking problem, and simplifies the code.
+ All uses changed.
+ (file_p): Remove; no longer needed.
+
+2012-11-13 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Omit glyphs initialization at startup.
+ * dispnew.c (glyphs_initialized_initially_p): Remove.
+ (adjust_frame_glyphs_initially): Likewise. Adjust users.
+ (Fredraw_frame): Move actual code from here...
+ (redraw_frame): ...to here. Add eassert. Adjust comment.
+ (Fredraw_display): Use redraw_frame.
+ * xdisp.c (clear_garbaged_frames): Likewise.
+
+2012-11-13 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (decode_mode_spec): Limit the value of WIDTH argument
+ passed to pint2str and pint2hrstr to be at most the size of the
+ frame's decode_mode_spec_buffer. This avoids crashes with very
+ large values of FIELD_WIDTH argument to decode_mode_spec.
+ (Bug#12867)
+
+2012-11-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix a race with verify-visited-file-modtime (Bug#12863).
+ Since at least 1991 Emacs has ignored an mtime difference of no
+ more than one second, but my guess is that this was to work around
+ file system bugs that were fixed long ago. Since the race is
+ causing problems now, let's remove that code.
+ * fileio.c (Fverify_visited_file_modtime): Do not accept a file
+ whose time stamp is off by no more than a second. Insist that the
+ file time stamps match exactly.
+
+2012-11-12 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * frame.h (struct frame): Convert external_tool_bar member to
+ 1-bit unsigned bitfield.
+ * termhooks.h (struct terminal): Remove mouse_moved member since
+ all users are long dead. Adjust comment on mouse_position_hook.
+
+2012-11-12 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Simplify by using FOR_EACH_FRAME here and there.
+ * frame.c (next_frame, prev_frame, other_visible_frames)
+ (delete_frame, visible-frame-list): Use FOR_EACH_FRAME.
+ * w32term.c (x_window_to_scroll_bar): Likewise.
+ * window.c (window_list): Likewise.
+ * xdisp.c (x_consider_frame_title): Likewise.
+ * xfaces.c ( Fdisplay_supports_face_attributes_p): Likewise.
+ * xfns.c (x_window_to_frame, x_any_window_to_frame)
+ (x_menubar_window_to_frame, x_top_window_to_frame): Likewise.
+ * xmenu.c (menubar_id_to_frame): Likewise.
+ * xselect.c (frame_for_x_selection): Likewise.
+ * xterm.c (x_frame_of_widget, x_window_to_scroll_bar)
+ (x_window_to_menu_bar): Likewise.
+ * w32fns.c (x_window_to_frame): Likewise. Adjust comment.
+
+2012-11-12 Paul Eggert <eggert@cs.ucla.edu>
+
+ * data.c (Qdefalias_fset_function): Now static.
+
+ Another tweak to vectorlike_header change.
+ * alloc.c (struct Lisp_Vectorlike_Free, NEXT_IN_FREE_LIST):
+ Remove, and replace all uses with ...
+ (next_in_free_list, set_next_in_free_list):
+ New functions, which respect C's aliasing rules better.
+
+2012-11-11 Paul Eggert <eggert@cs.ucla.edu>
+
+ * window.c (list4i): Rename from 'quad'. All uses changed.
+ Needed because <sys/types.h> defines 'quad' on Solaris 10.
+
+2012-11-11 Juanma Barranquero <lekktu@gmail.com>
+
+ * xdisp.c (start_hourglass) [HAVE_NTGUI]: Add block to silence
+ warning about mixing declarations and code in ISO C90.
+
+2012-11-10 Martin Rudalics <rudalics@gmx.at>
+
+ * window.c (Fsplit_window_internal): Set combination limit of
+ new parent window to t iff Vwindow_combination_limit is t;
+ fixing a regression introduced with the change from 2012-09-22.
+ (Fset_window_combination_limit): Fix doc-string.
+
+2012-11-10 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (try_scrolling): Fix correction of aggressive-scroll
+ amount when the scroll margins are too large. When scrolling
+ backwards in the buffer, give up if cannot reach point or the
+ scroll margin within a reasonable number of screen lines.
+ Fixes point position in window under scroll-up/down-aggressively when
+ point is positioned many lines beyond the window top/bottom.
+ (Bug#12811)
+
+ * ralloc.c (relinquish): If real_morecore fails to return memory
+ to the system, don't crash; instead, leave the last heap
+ unchanged and return. (Bug#12774)
+
+2012-11-09 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp.h (AUTOLOADP): New macro.
+ * eval.c (Fautoload): Don't attach to loadhist, call Fdefalias instead.
+ * data.c (Ffset): Remove special ad-advice-info handling.
+ (Fdefalias): Handle autoload definitions and new Qdefalias_fset_function.
+ (Fsubr_arity): CSE.
+ (Finteractive_form): Simplify.
+ (Fquo): Don't insist on having at least 2 arguments.
+ (Qdefalias_fset_function): New var.
+
+2012-11-09 Jan Djärv <jan.h.d@swipnet.se>
+
+ * image.c (xpm_make_color_table_h): Change to hashtest_equal.
+
+ * nsfont.m (Qcondensed, Qexpanded): New variables.
+ (ns_descriptor_to_entity): Restore Qcondensed, Qexpanded setting.
+ (syms_of_nsfont): Defsym Qcondensed, Qexpanded.
+
+2012-11-09 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Fix recently introduced crash on MS-Windows (Bug#12839).
+ * w32term.h (struct scroll_bar): Use convenient header.
+ (SCROLL_BAR_VEC_SIZE): Remove.
+ * w32term.c (x_scroll_bar_create): Use VECSIZE.
+
+2012-11-09 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Tweak last vectorlike_header change.
+ * alloc.c (struct Lisp_Vectorlike_Free): Special type to represent
+ vectorlike object on the free list. This is introduced to avoid
+ some (but not all) pointer casting and aliasing problems, see
+ http://lists.gnu.org/archive/html/emacs-devel/2012-11/msg00105.html.
+ * .gdbinit (pvectype, pvecsize): New commands to examine vectorlike
+ objects.
+ (xvectype, xvecsize): Use them to examine Lisp_Object values.
+
+2012-11-09 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfont.m (ns_descriptor_to_entity): Qcondensed and Qexpanded has
+ been removed, so remove them here also.
+
+2012-11-09 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * doc.c (Fdocumentation): Handle new property
+ dynamic-docstring-function to replace the old ad-advice-info.
+
+2012-11-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fns.c (Qeql, hashtest_eq): Now static.
+
+2012-11-08 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp.h (XHASH): Redefine to be imperfect and fit in a Lisp int.
+ * fns.c (hashfn_eq, hashfn_eql, sxhash):
+ * profiler.c (hashfn_profiler): Don't use XUINT on non-integers.
+ * buffer.c (compare_overlays): Use XLI rather than XHASH.
+
+2012-11-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use same hash function for hashfn_profiler as for hash_string etc.
+ * fns.c (SXHASH_COMBINE): Remove. All uses replaced by sxhash_combine.
+ * lisp.h (sxhash_combine): New inline function, with the contents
+ of the old SXHASH_COMBINE.
+ * profiler.c (hashfn_profiler): Use it, instead of having a
+ special hash function containing a comparison that always yields 1.
+
+2012-11-08 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * xfaces.c (Qultra_light, Qreverse_oblique, Qreverse_italic)
+ (Qultra_condensed, Qextra_condensed, Qcondensed, Qsemi_condensed)
+ (Qsemi_expanded, Qextra_expanded, Qexpanded, Qultra_expanded):
+ Remove unused vars.
+
+2012-11-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * image.c (xpm_make_color_table_h): Fix compiler error because
+ make_hash_table changed.
+
+2012-11-08 Thomas Kappler <tkappler@gmail.com> (tiny change)
+
+ * nsfont.m (ns_findfonts): Handle empty matchingDescs (Bug#11541).
+
+2012-11-08 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ Use ad-hoc comparison function for the profiler's hash-tables.
+ * profiler.c (Qprofiler_backtrace_equal, hashtest_profiler): New vars.
+ (make_log): Use them.
+ (handle_profiler_signal): Don't inhibit quit any longer since we don't
+ call Fequal any more.
+ (Ffunction_equal): New function.
+ (cmpfn_profiler, hashfn_profiler): New functions.
+ (syms_of_profiler): Initialize them.
+ * lisp.h (struct hash_table_test): New struct.
+ (struct Lisp_Hash_Table): Use it.
+ * alloc.c (mark_object): Mark hash_table_test fields of hash tables.
+ * fns.c (make_hash_table): Take a struct to describe the test.
+ (cmpfn_eql, cmpfn_equal, cmpfn_user_defined, hashfn_eq, hashfn_eql)
+ (hashfn_equal, hashfn_user_defined): Adjust to new calling convention.
+ (hash_lookup, hash_remove_from_table): Move assertion checking of
+ hashfn result here. Check hash-equality before calling cmpfn.
+ (Fmake_hash_table): Adjust call to make_hash_table.
+ (hashtest_eq, hashtest_eql, hashtest_equal): New structs.
+ (syms_of_fns): Initialize them.
+ * emacs.c (main): Move syms_of_fns earlier.
+ * xterm.c (syms_of_xterm):
+ * category.c (hash_get_category_set): Adjust call to make_hash_table.
+ * print.c (print_object): Adjust to new hash-table struct.
+ * composite.c (composition_gstring_put_cache): Adjust to new hashfn.
+
+2012-11-08 Eli Zaretskii <eliz@gnu.org>
+
+ * w32fns.c (modifier_set): Fix handling of Scroll Lock when the
+ value of w32-scroll-lock-modifier is neither nil nor one of the
+ known key modifiers. (Bug#12806)
+
+2012-11-08 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Shrink struct vectorlike_header to the only size field.
+ * lisp.h (enum pvec_type): Avoid explicit enum member values.
+ Adjust comment.
+ (enum More_Lisp_Bits): Change PSEUDOVECTOR_SIZE_BITS and
+ PVEC_TYPE_MASK to arrange new bitfield in the vector header.
+ (PSEUDOVECTOR_REST_BITS, PSEUDOVECTOR_REST_MASK): New members.
+ (PSEUDOVECTOR_AREA_BITS): New member used to extract subtype
+ information from the vector header. Adjust comment.
+ (XSETPVECTYPE, XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR)
+ (PSEUDOVECTOR_TYPEP, DEFUN): Adjust to match new vector header
+ layout.
+ (XSETSUBR, SUBRP): Adjust to match new Lisp_Subr layout.
+ (struct vectorlike_header): Remove next member. Adjust comment.
+ (struct Lisp_Subr): Add convenient header. Adjust comment.
+ (allocate_pseudovector): Adjust prototype.
+ * alloc.c (mark_glyph_matrix, mark_face_cache, allocate_string)
+ (sweep_string, lisp_malloc): Remove useless prototypes.
+ (enum mem_type): Adjust comment.
+ (NEXT_IN_FREE_LIST): New macro.
+ (SETUP_ON_FREE_LIST): Adjust XSETPVECTYPESIZE usage.
+ (Fmake_bool_vector): Likewise.
+ (struct large_vector): New type to represent allocation unit for
+ the vectors with the memory footprint more than VBLOOCK_BYTES_MAX.
+ (large_vectors): Change type to struct large_vector.
+ (allocate_vector_from_block): Simplify.
+ (PSEUDOVECTOR_NBYTES): Replace with...
+ (vector_nbytes): ...new function. Adjust users.
+ (sweep_vectors): Adjust processing of large vectors.
+ (allocate_vectorlike): Likewise.
+ (allocate_pseudovector): Change type of 3rd arg to enum pvec_type.
+ Add easserts. Adjust XSETPVECTYPESIZE usage.
+ (allocate_buffer): Use BUFFER_PVEC_INIT.
+ (live_vector_p): Adjust to match large vector.
+ * buffer.c (init_buffer_once): Use BUFFER_PVEC_INIT.
+ * buffer.h (struct buffer): Add next member.
+ (BUFFER_LISP_SIZE, BUFFER_REST_SIZE, BUFFER_PVEC_INIT):
+ New macros.
+ (FOR_EACH_BUFFER): Adjust to match struct buffer change.
+ * fns.c (internal_equal): Adjust to match enum pvec_type change.
+ (copy_hash_table): Adjust to match vector header change.
+ * lread.c (defsubr): Use XSETPVECTYPE.
+ * .gdbinit (xpr, xbacktrace): Adjust to match vector header change.
+ (xvectype): Likewise. Print PVEC_NORMAL_VECTOR for regular vectors.
+ (xvecsize): New command.
+
+2012-11-08 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * keyboard.c (event_to_kboard): Do not dereference
+ frame_or_window field of SELECTION_REQUEST_EVENT
+ and SELECTION_CLEAR_EVENT events (Bug#12814).
+ * xterm.h (struct selection_input_event): Adjust comment.
+
+2012-11-07 Eli Zaretskii <eliz@gnu.org>
+
+ * w32fns.c (modifier_set): Don't report modifiers from toggle key,
+ such as Scroll Lock, if the respective keys are treated as
+ function keys, not as modifiers. This avoids destroying non-ASCII
+ keyboard input when Scroll Lock is toggled ON. (Bug#12806)
+
+2012-11-07 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xfns.c (Fx_wm_set_size_hint): Use check_x_frame. Adjust docstring.
+
+2012-11-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ Restore some duplicate definitions (Bug#12814).
+ This undoes part of the 2012-11-03 changes. Some people build
+ with plain -g rather than with -g3, and they need the duplicate
+ definitions for .gdbinit to work; see <http://bugs.gnu.org/12814#26>.
+ * lisp.h (GCTYPEBITS, ARRAY_MARK_FLAG, PSEUDOVECTOR_FLAG, VALMASK):
+ Define as macros, as well as as enums or as constants.
+
+2012-11-06 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (convert_ns_to_X_keysym, keyDown:): Add NSNumericPadKeyMask
+ to keypad keys (Bug#12816).
+
+2012-11-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ Minor adjustments of recently-changed frame functions.
+ * buffer.c (Fbuffer_list): Omit CHECK_FRAME, since arg is already
+ known to be a frame (we're in the FRAMEP branch).
+ * lisp.h (Qframep): Remove decl. frame.h declares this.
+ * window.c (quad): Args are of type EMACS_INT, not ptrdiff_t,
+ since they're meant for Lisp fixnum values.
+
+2012-11-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * window.c (Fwindow_combination_limit): Revert to the only
+ required argument and adjust docstring as suggested in
+ http://lists.gnu.org/archive/html/emacs-diffs/2012-11/msg01082.html
+ by Martin Rudalics <rudalics@gmx.at>.
+
+2012-11-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Widely used frame validity and checking functions.
+ * frame.h (decode_live_frame, decode_any_frame): Add prototypes.
+ * frame.c (decode_live_frame, decode_any_frame): New functions.
+ (delete_frame, Fredirect_frame_focus, Fframe_parameters)
+ (Fframe_parameter, Fframe_char_height, Fframe_char_width)
+ (Fframe_pixel_height, Fframe_pixel_width, Ftool_bar_pixel_width)
+ (Fframe_pointer_visible_p): Use decode_any_frame.
+ (Fmake_frame_visible, Fmake_frame_invisible, Ficonify_frame)
+ (Fraise_frame, Flower_frame, Fmodify_frame_parameters)
+ (Fset_frame_height, Fset_frame_width): Use decode_live_frame.
+ (Fframe_focus): Likewise. Allow zero number of arguments.
+ Adjust docstring.
+ (frame_buffer_list, frame_buffer_predicate): Remove.
+ * lisp.h (frame_buffer_predicate): Remove prototype.
+ * buffer.c (Fother_buffer): Use decode_any_frame.
+ * xdisp.c (Ftool_bar_lines_needed): Likewise.
+ * xfaces.c (Fcolor_gray_p, Fcolor_supported_p): Likewise.
+ * font.c (Ffont_face_attributes, Ffont_family_list, Fopen_font)
+ (Fclose_font, Ffont_info): Use decode_live_frame.
+ * fontset.c (check_fontset_name): Likewise.
+ * terminal.c (Fframe_terminal): Likewise.
+ * w32fns.c (check_x_frame): Likewise.
+ * window.c (Fminibuffer_window, Fwindow_at)
+ (Fcurrent_window_configuration): Likewise.
+ (Frun_window_configuration_change_hook, Fwindow_resize_apply):
+ Likewise. Allow zero number of arguments. Adjust docstring.
+ * dispnew.c (Fredraw_frame): Likewise.
+ * xfaces.c (frame_or_selected_frame): Remove.
+ (Fx_list_fonts, Finternal_get_lisp_face_attribute, Fface_font)
+ (Finternal_lisp_face_equal_p, Finternal_lisp_face_empty_p)
+ (Fframe_face_alist): Use decode_live_frame.
+ * xfns.c (check_x_frame): Likewise.
+
+2012-11-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * window.c (quad): New function.
+ (Fwindow_edges, Fwindow_pixel_edges, Fwindow_inside_edges)
+ (Fwindow_absolute_pixel_edges, Fwindow_inside_absolute_pixel_edges)
+ (Fwindow_inside_pixel_edges, Fpos_visible_in_window_p)
+ (Fwindow_line_height): Use it.
+ (Fwindow_fringes): Use list3.
+ (Fwindow_scroll_bars): Use list4.
+ (Fwindow_frame, Fwindow_top_child, Fwindow_left_child)
+ (Fwindow_combination_limit): Allow zero number of arguments.
+
+2012-11-05 Eli Zaretskii <eliz@gnu.org>
+
+ * makefile.w32-in ($(BLD)/w32fns.$(O)): Depend on $(NT_INC)/unistd.h.
+
+ * w32fns.c: Include unistd.h, to avoid compiler warnings on Cygwin.
+ (emacs_abort) [CYGWIN]: Don't call _open_osfhandle; instead, use
+ file descriptor 2 for standard error. (Bug#12805)
+
+2012-11-05 Chong Yidong <cyd@gnu.org>
+
+ * process.c (wait_reading_process_output): Revert previous change.
+
+2012-11-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ Assume at least POSIX.1-1988 for getpgrp, setpgid, setsid (Bug#12800).
+ This removes code that has been obsolete since around 1990.
+ * callproc.c (Fcall_process):
+ * emacs.c (main):
+ * process.c (create_process):
+ * term.c (dissociate_if_controlling_tty):
+ Assume setsid exists.
+ * callproc.c (child_setup): Assume setpgid exists and behaves as
+ per POSIX.1-1988 or later.
+ * conf_post.h (setpgid) [!HAVE_SETPGID]: Remove.
+ * emacs.c (shut_down_emacs):
+ * sysdep.c (sys_suspend, init_foreground_group):
+ Assume getpgrp behaves as per POSIX.1-1998 or later.
+ * msdos.c (setpgrp): Remove.
+ (tcgetpgrp, setpgid, setsid): New functions.
+ * systty.h (EMACS_GETPGRP): Remove. All callers now use getpgrp.
+ * term.c (no_controlling_tty): Remove; unused.
+ * w32proc.c (setpgrp): Remove.
+ (setsid, tcgetpgrp): New functions.
+
+ Simplify by assuming __fpending.
+ * dispnew.c: Include <fpending.h>, not <stdio_ext.h>.
+ (update_frame_1): Use __fpending, not PENDING_OUTPUT_COUNT.
+ Do not assume that __fpending's result fits in int.
+
+2012-11-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ Remove EMACS_OUTQSIZE+sleep hack.
+ * dispnew.c (update_frame_1): Remove hack for terminals slower
+ than 2400 bps, which throttled Emacs by having it sleep.
+ This code hasn't worked since at least 2007, when the multi-tty stuff
+ was added, and anyway those old terminals are long dead.
+ * systty.h (EMACS_OUTQSIZE): Remove; unused. The macro isn't used even
+ without the dispnew.c change, as dispnew.c doesn't include systty.h.
+
+ Fix data-loss with --version (Bug#9574).
+ * emacs.c (close_output_streams): Use strerror, not emacs_strerror,
+ as we can't assume that emacs_strerror is initialized, and strerror
+ is good enough here.
+ (main): Invoke atexit earlier, to catch earlier instances of
+ sending data to stdout and exiting, e.g., "emacs --version >/dev/full".
+
+2012-11-04 Michael Marchionna <tralfaz@pacbell.net>
+
+ * nsterm.m: Add NSClearLineFunctionKey and keypad keys (Bug#8680).
+ (keyDown): Remap keypad keys to X11 virtual key codes.
+
+2012-11-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix data-loss with --batch (Bug#9574).
+ * emacs.c: Include <close-stream.h>.
+ (close_output_streams): New function.
+ (main): Pass it to atexit, so that Emacs closes stdout and stderr
+ and handles errors appropriately.
+ (Fkill_emacs): Don't worry about flushing, as close_output_stream
+ does that now.
+
+ Fix a race condition that causes Emacs to mess up glib (Bug#8855).
+ The symptom is a diagnostic "GLib-WARNING **: In call to
+ g_spawn_sync(), exit status of a child process was requested but
+ SIGCHLD action was set to SIG_IGN and ECHILD was received by
+ waitpid(), so exit status can't be returned." The diagnostic
+ is partly wrong, as the SIGCHLD action is not set to SIG_IGN.
+ The real bug is a race condition between Emacs and glib: Emacs
+ does a waitpid (-1, ...) and reaps glib's subprocess by mistake,
+ so that glib can't find it. Work around the bug by invoking
+ waitpid only on subprocesses that Emacs itself creates.
+ * process.c (create_process, record_child_status_change):
+ Don't use special value -1 in pid field, as the caller now must
+ know the pid rather than having the callee infer it.
+ The inference was sometimes incorrect anyway, due to another race.
+ (create_process): Set new 'alive' member if child is created.
+ (process_status_retrieved): New function.
+ (record_child_status_change): Use it.
+ Accept negative 1st argument, which means to wait for the
+ processes that Emacs already knows about. Move special-case code
+ for DOS_NT (which lacks WNOHANG) here, from caller. Keep track of
+ processes that have already been waited for, by testing and
+ clearing new 'alive' member.
+ (CAN_HANDLE_MULTIPLE_CHILDREN): Remove, as record_child_status_change
+ now does this internally.
+ (handle_child_signal): Let record_child_status_change do all
+ the work, since we do not want to reap all exited child processes,
+ only the child processes that Emacs itself created.
+ * process.h (Lisp_Process): New boolean member 'alive'.
+
+ Omit duplicate definitions no longer needed with gcc -g3.
+ * lisp.h (GCTYPEBITS, GCALIGNMENT, ARRAY_MARK_FLAG, PSEUDOVECTOR_FLAG)
+ (VALMASK, MOST_POSITIVE_FIXNUM, MOST_NEGATIVE_FIXNUM):
+ Define only as macros. There's no longer any need to also define
+ these symbols as enums or as constants, since we now assume
+ gcc -g3 when debugging.
+
+2012-11-03 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp.mk: Adjust comments to the fact that term/internal is now
+ loaded from loadup.el.
+
+ * msdos.c (msdos_abort): Rename from emacs_abort, and make static.
+ (msdos_fatal_signal): New function.
+ (XMenuActivate): Adjust the call to kbd_buffer_events_waiting to
+ its argument list.
+
+ * conf_post.h (_GL_EXECINFO_INLINE) [MSDOS]: Define to "inline"
+ for GCC versions before 4.
+ (emacs_raise): Define to call msdos_fatal_signal.
+
+ * xdisp.c (init_from_display_pos): Fix initialization of the bidi
+ iterator when starting in the middle of a display or overlay
+ string. (Bug#12745)
+
+2012-11-03 Chong Yidong <cyd@gnu.org>
+
+ * process.c (wait_reading_process_output): Clean up the last
+ change.
+
+2012-11-03 Jim Paris <jim@jtan.com> (tiny change)
+
+ * process.c (wait_reading_process_output): Avoid a race condition
+ with SIGIO delivery (Bug#11536).
+
+2012-11-03 Chong Yidong <cyd@gnu.org>
+
+ * buffer.c (cursor_type): Untabify docstring.
+
+2012-11-03 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * frame.h (struct frame): Drop can_have_scroll_bars member
+ which is meaningless for a long time. Adjust comments.
+ (FRAME_CAN_HAVE_SCROLL_BARS): Remove.
+ * frame.c, nsfns.m, term.c, w32fns.c, xfns.c: Adjust users.
+
+2012-11-03 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * window.c (decode_next_window_args): Update window arg after
+ calling decode_live_window and so fix crash reported at
+ http://lists.gnu.org/archive/html/emacs-devel/2012-11/msg00035.html
+ by Juanma Barranquero <lekktu@gmail.com>.
+ (Fwindow_body_width, Fwindow_body_height): Simplify a bit.
+ * font.c (Ffont_at): Likewise.
+
+2012-11-01 Jan Djärv <jan.h.d@swipnet.se>
+
+ * widget.c (resize_cb): New function.
+ (EmacsFrameRealize): Add resize_cb as event handler (Bug#12733).
+ (EmacsFrameResize): Check if all is up to date before changing frame
+ size.
+
+2012-11-02 Eli Zaretskii <eliz@gnu.org>
+
+ Implement backtrace output for fatal errors on MS-Windows.
+ * w32fns.c (CaptureStackBackTrace_proc): New typedef.
+ (BACKTRACE_LIMIT_MAX): New macro.
+ (w32_backtrace): New function.
+ (emacs_abort): Use w32_backtrace when the user chooses not to
+ attach a debugger. Update the text of the abort dialog.
+
+2012-11-02 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Window-related stuff cleanup here and there.
+ * dispnew.c (Finternal_show_cursor, Finternal_show_cursor_p):
+ Use decode_any_window.
+ * fringe.c (Ffringe_bitmaps_at_pos): Likewise.
+ * xdisp.c (Fformat_mode_line): Likewise.
+ * font.c (Ffont_at): Use decode_live_window.
+ * indent.c (Fcompute_motion, Fvertical_motion): Likewise.
+ * window.c (decode_next_window_args): Likewise.
+ (decode_any_window): Remove static.
+ * window.h (decode_any_window): Add prototype.
+ * lisp.h (CHECK_VALID_WINDOW, CHECK_LIVE_WINDOW): Move from here...
+ * window.h: ...to here, redefine via WINDOW_VALID_P and WINDOW_LIVE_P,
+ respectively.
+
+2012-11-02 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Remove pad from struct input_event.
+ * termhooks.h (struct input_event): Remove padding field.
+ Adjust comment.
+ * keyboard.c (event_to_kboard): Simplify because frame_or_window
+ member is never cons for a long time. Adjust comment.
+ (mark_kboards): Adjust because SELECTION_REQUEST_EVENT and
+ SELECTION_CLEAR_EVENT has no Lisp_Objects to mark. Add comment.
+ * xterm.c (handle_one_xevent): Do not initialize frame_or_window
+ field of SELECTION_REQUEST_EVENT and SELECTION_CLEAR_EVENT.
+
+2012-11-01 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (getpgrp, setpgid): New functions. (Bug#12776)
+
+2012-10-31 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix crash when using Emacs as commit editor for git (Bug#12697).
+ * callproc.c (setpgrp): Remove macro, as we now use setpgid
+ and it is configured in conf_post.h.
+ (Fcall_process): Don't invoke both setsid and setpgid; the former
+ is enough, if it exists.
+ * callproc.c (Fcall_process, child_setup):
+ * process.c (create_process): Use setpgid.
+ * conf_post.h (setpgid) [!HAVE_SETPGID]: New macro, which substitutes
+ for the real thing.
+ * dispnew.c (init_display): Initialize the foreground group
+ if we are running a tty display.
+ * emacs.c (main): Do not worry about setpgrp; init_display does it now.
+ * lisp.h (init_foreground_group): New decl.
+ * sysdep.c (inherited_pgroup): New static var.
+ (init_foreground_group, tcsetpgrp_without_stopping)
+ (narrow_foreground_group, widen_foreground_group): New functions.
+ (init_sys_modes): Narrow foreground group.
+ (reset_sys_modes): Widen foreground group.
+
+2012-10-31 Michael Albinus <michael.albinus@gmx.de>
+
+ * dbusbind.c: Fix cut'n'waste error. Use HAVE_DBUS_VALIDATE_INTERFACE.
+
+2012-10-31 Martin Rudalics <rudalics@gmx.at>
+
+ * minibuf.c (read_minibuf): Restore current buffer since
+ choose_minibuf_frame calling Fset_frame_selected_window may
+ change it (Bug#12766).
+
+2012-10-30 Jan Djärv <jan.h.d@swipnet.se>
+
+ * frame.c (Fframe_pixel_height): Fix documentation (Bug#12733).
+
+2012-10-30 Kenichi Handa <handa@gnu.org>
+
+ * font.c (Ffont_at): If WINDOW is specified and it is not
+ displaying the current buffer, signal an error.
+
+2012-10-29 Daniel Colascione <dancol@dancol.org>
+
+ * cygw32.h, cygw32.c (Qutf_16le, from_unicode, to_unicode):
+ In preparation for fixing bug#12739, move these functions from
+ here...
+
+ * coding.h, coding.c: ... to here, and compile them only when
+ WINDOWSNT or CYGWIN. Moving these functions out of cygw32 proper
+ lets us write cygw32-agnostic code for the HAVE_NTGUI case.
+
+2012-10-28 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (TIMER_TICKS_PER_SEC): New macro.
+ (timer_loop, getitimer, setitimer): Use it instead of
+ CLOCKS_PER_SEC, which is no longer pertinent, since we don't use
+ 'clock'.
+ (w32_get_timer_time): Use 10*TIMER_TICKS_PER_SEC instead of a
+ literal 10000.
+
+2012-10-28 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (NO_APPDEFINED_DATA): New define.
+ (last_appdefined_event_data): New variable
+ (last_appdefined_event): Remove.
+ (ns_select): Initialize t from last_appdefined_event_data instead
+ of [last_appdefined_event data1].
+ (sendEvent:): Save [theEvent data1] to last_appdefined_event_data,
+ remove last_appdefined_event (Bug#12698).
+
+2012-10-28 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * frame.c (x_set_font): Catch internal error.
+
+2012-10-27 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid overflow in w32 implementation of interval timers.
+ When possible, for ITIMER_PROF count only times the main thread
+ actually executes.
+ * w32proc.c <struct itimer_data>: 'expire' and 'reload' are now
+ 'volatile ULONGLONG' types. All the other data which was
+ previously clock_t is now ULONGLONG. 'terminate' is 'volatile int'.
+ (GetThreadTimes_Proc): New typedef.
+ (w32_get_timer_time): New function, returns a suitable time value
+ for the timer.
+ (timer_loop): Enter critical section when accessing ULONGLONG
+ values of the itimer_data struct, as these accesses are no longer
+ atomic. Call 'w32_get_timer_time' instead of 'clock'.
+ Remove unused variable.
+ (init_timers): Initialize s_pfn_Get_Thread_Times.
+ (start_timer_thread): Don't assign itimer->caller_thread here.
+ (getitimer): Assign itimer->caller_thread here.
+ (setitimer): Always call getitimer to get the value of ticks_now.
+ (sys_spawnve): Avoid compiler warning about format mismatch.
+
+2012-10-26 Eli Zaretskii <eliz@gnu.org>
+
+ * w32fns.c (w32_wnd_proc) <WM_MOUSEMOVE>: Don't enable tracking of
+ mouse movement events if the menu bar is active. This avoids
+ producing a busy "hour-glass" cursor by Windows if the mouse
+ pointer is positioned over a tooltip shown for some menu item.
+
+2012-10-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ Don't assume process IDs fit in int.
+ * emacs.c (shut_down_emacs) [!DOS_NT]:
+ * sysdep.c (sys_suspend) [SIGTSTP && !MSDOS]:
+ * term.c (dissociate_if_controlling_tty) [!DOS_NT]:
+ Use pid_t, not int, to store process IDs, as 'int'
+ is not wide enough on a few platforms (e.g., AIX and IRIX).
+
+2012-10-23 Kenichi Handa <handa@gnu.org>
+
+ The following change is to make face-font-rescale-alist work
+ correctly for non-ASCII fonts.
+
+ * font.c (font_open_entity): Don't handle Vface_font_rescale_alist.
+ (font_open_for_lface): Handle Vface_font_rescale_alist.
+
+2012-10-23 Chong Yidong <cyd@gnu.org>
+
+ * xfaces.c (Vfont_list_limit): Move unused variable to faces.el.
+
+2012-10-21 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfont.m (nsfont_open, ns_glyph_metrics): Force integer advancement
+ for screen font.
+ (nsfont_draw): Turn off LCD-smoothing (Bug#11484).
+
+ * xterm.c (x_focus_changed): Check if daemonp when sending focus in
+ event (Bug#12681).
+
+2012-10-21 Glenn Morris <rgm@gnu.org>
+
+ * lisp.mk (lisp): Add cp51932.el and eucjp-ms.el.
+
+2012-10-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port to OpenBSD 5.1.
+ * frame.c (Fmouse_position, Fmouse_pixel_position):
+ * xdisp.c (produce_stretch_glyph):
+ Declare local vars only when they're needed.
+ This is clearer and avoids a warning on OpenBSD about unused vars.
+ * frame.h (FRAME_WINDOW_P): Always evaluate its argument.
+ This is safer, and avoids OpenBSD warnings about unused vars.
+ * keyboard.c (record_menu_key): Remove unnecessary decl.
+ (poll_timer): Define only if POLL_FOR_INPUT is defined.
+ * unexelf.c (ELFSIZE) [!ElfW]: Do not define if already defined,
+ as our definition clashes with OpenBSD's.
+ * xfaces.c (load_face_colors, check_lface_attrs)
+ (get_lface_attributes_no_remap, get_lface_attributes)
+ (lface_fully_specified_p, x_supports_face_attributes_p)
+ (tty_supports_face_attributes_p, face_fontset, realize_face)
+ (realize_x_face, realize_tty_face):
+ Declare parameters to be Lisp_Object[LFACE_VECTOR_SIZE], not
+ merely Lisp_Object *. This is more informative and avoids
+ a warning on OpenBSD about accessing beyond an object's size.
+
+2012-10-20 Chong Yidong <cyd@gnu.org>
+
+ * lread.c (Fload): Doc fix (Bug#12592).
+
+2012-10-19 Kazuhiro Ito <kzhr@d1.dion.ne.jp> (tiny change)
+
+ * font.c (Ffont_at): Fix previous change.
+
+2012-10-19 Eli Zaretskii <eliz@gnu.org>
+
+ * puresize.h (BASE_PURESIZE): Bump the base value to 1700000.
+ See http://lists.gnu.org/archive/html/emacs-devel/2012-10/msg00593.html
+ for the reasons.
+
+ * alloc.c (NSTATICS): Decrease to 0x800.
+
+2012-10-19 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * fns.c (Fnreverse): Include the problem element when signaling an
+ error (bug#12677).
+
+2012-10-18 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_select): Check writefds before call to
+ FD_ISSET (Bug#12668).
+
+2012-10-18 Daniel Colascione <dancol@dancol.org>
+
+ * alloc.c (NSTATICS): Increase from 0x650 to 0x1000
+ (staticpro): If we run out of staticpro slots, die with an
+ informative error instead of just calling emacs_abort.
+
+2012-10-18 Martin Rudalics <rudalics@gmx.at>
+
+ Fix two flaws reported by Dmitry Antipov.
+ * window.c (Ftemp_output_buffer_show): Remove.
+ (Fwindow_vscroll, Fset_window_vscroll): Use decode_live_window.
+ (syms_of_window): Remove defsubr for Stemp_output_buffer_show.
+
+2012-10-17 Eli Zaretskii <eliz@gnu.org>
+
+ * makefile.w32-in ($(BLD)/w32.$(O)):
+ ($(BLD)/vm-limit.$(O)):
+ ($(BLD)/term.$(O)):
+ ($(BLD)/unexw32.$(O)):
+ ($(BLD)/fileio.$(O)):
+ ($(BLD)/dispnew.$(O)): Update dependencies.
+
+ * w32term.h (w32_initialize_display_info, initialize_w32_display):
+ Add prototypes.
+
+ * w32proc.c: Include ctype.h.
+
+ * w32.h (init_environment, check_windows_init_file)
+ (syms_of_ntproc, syms_of_ntterm, dostounix_filename)
+ (unixtodos_filename, init_winsock, srandom, random, sys_pipe)
+ (set_process_dir, sys_spawnve, register_child, sys_sleep, getwd)
+ (sys_link): Add prototypes.
+
+ * w32.c: Include w32select.h.
+ (sys_access, e_malloc, sys_select): Add prototypes.
+ (emacs_gnutls_pull): 'timeout' is now EMACS_TIME, not struct timeval.
+
+ * vm-limit.c [WINDOWSNT]: Include w32heap.h.
+
+ * unexw32.c: Include lisp.h and w32.h.
+
+ * term.c [WINDOWSNT]: Include w32term.h.
+
+ * process.c [WINDOWSNT]: Add prototype of sys_select.
+
+ * fileio.c [WINDOWSNT]: Include w32.h.
+
+ * dispnew.c [WINDOWSNT]: Include w32.h.
+
+ * cygw32.c (Fcygwin_convert_path_to_windows)
+ (Fcygwin_convert_path_from_windows): Use EQ to compare 2
+ Lisp_Object values. (Bug#12661)
+
+ * w32fns.c (w32_msg_pump): Use XIL instead of casting an integer
+ to Lisp_Object. (Bug#12661)
+
+2012-10-17 Kenichi Handa <handa@gnu.org>
+
+ * xdisp.c (reseat_1): Make the information stored in it->cmp_it
+ invalidate.
+
+2012-10-17 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * buffer.c (Fkill_buffer): When unchaining the marker,
+ reset its buffer pointer to NULL (Bug#12652).
+
+2012-10-17 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Do not verify indirection counters of killed buffers (Bug#12579).
+ * buffer.h (BUFFER_CHECK_INDIRECTION): New macro.
+ * buffer.c (compact_buffer, set_buffer_internal_1): Use it.
+
+2012-10-16 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (Fmake_byte_code): Fix typo in comment.
+ * print.c (print_interval): Define as static to match prototype.
+ * indent.c (disptab_matches_widthtab, recompute_width_table):
+ Convert to eassert.
+
+2012-10-16 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * editfns.c (get_system_name): Remove.
+ * lisp.h (get_system_name): Remove prototype.
+ * xrdb.c (getenv, getpwuid, getpwnam): Remove prototypes.
+ (get_environ_db): Use Vsystem_name. Avoid call to strlen.
+
+2012-10-15 Daniel Colascione <dancol@dancol.org>
+
+ * dbusbind.c: Add comment explaining reason for previous change.
+
+2012-10-15 Martin Rudalics <rudalics@gmx.at>
+
+ * window.c (Fwindow_end): Rewrite check whether cached position
+ can be used (Bug#12600).
+ (resize_frame_windows, grow_mini_window, shrink_mini_window):
+ Set windows_or_buffers_changed.
+
+2012-10-15 Daniel Colascione <dancol@dancol.org>
+
+ * dbusbind.c: Fix cygw32 build break when compiling with dbus
+ enabled by undefining the symbol "interface", which the platform
+ headers define to something incompatible.
+
+2012-10-14 Daniel Colascione <dancol@dancol.org>
+
+ * image.c (init_tiff_functions, init_imagemagick_functions)
+ (init_svg_functions): Fix cygw32 build break by using these
+ functions only when WINDOWSNT _and_ HAVE_NTGUI.
+
+2012-10-14 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_select): Count fd:s in writefs also (Bug#12422).
+
+2012-10-13 Jan Djärv <jan.h.d@swipnet.se>
+
+ * gtkutil.c (xg_set_widget_bg): Divide by 65535 (Bug#12612).
+
+2012-10-13 HANATAKA, Shinya <bogytech@gmail.com> (tiny change)
+
+ * coding.c (detect_coding): Set coding->id before calling
+ this->detector.
+
+2012-10-13 Andreas Schwab <schwab@linux-m68k.org>
+
+ * fileio.c: Formatting fixes.
+
+2012-10-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix some stat-related races.
+ * fileio.c (Fwrite_region): Avoid race condition if a file is
+ removed or renamed by some other process immediately after Emacs
+ writes it but before Emacs stats it. Do not assume that stat (or
+ fstat) succeeds.
+ * image.c (slurp_file): Resolve the file name with fopen + fstat
+ rather than stat + fopen.
+ (pbm_read_file) [0]: Remove unused code with stat race.
+ * process.c (allocate_pty) [HAVE_PTYS && !PTY_ITERATION && !PTY_OPEN]:
+ Remove ineffective code with stat race.
+
+2012-10-12 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * doc.c (get_doc_string): Don't signal an error if the file is missing.
+
+2012-10-12 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (hold_event_q): New static variable.
+ (EV_TRAILER, sendScrollEventAtLoc:fromEvent:): Call hold_event if
+ ! q_event_ptr.
+ (hold_event): New function.
+ (ns_read_socket): If hold_event_q have events, store them and
+ return (Bug#12384).
+ (setPosition:portion:whole:): Send SIGIO to ourselves if apploopnr
+ is zero (Bug#12384).
+
+2012-10-12 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/w32select.$(O)): Update dependencies.
+
+2012-10-12 Eli Zaretskii <eliz@gnu.org>
+
+ * makefile.w32-in ($(BLD)/fileio.$(O)): Add sys/file.h.
+
+ * fileio.c (check_existing): New function.
+ (make_temp_name, Ffile_exists_p, Ffile_writable_p): Call it
+ instead of calling 'stat', when what's needed is to check whether
+ a file exists. This avoids expensive system calls on MS-Windows.
+ (Bug#12587)
+
+ * w32.c (init_environment): Call 'check_existing' instead of 'stat'.
+
+ * lread.c (openp) [WINDOWSNT]: Call 'access' instead of 'stat' to
+ determine whether a file exists and is not a directory.
+
+ * lisp.h (check_existing): Add prototype.
+
+2012-10-12 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfont.m (nsfont_open): Remove font cache, it is not GC correct.
+
+2012-10-12 Glenn Morris <rgm@gnu.org>
+
+ * buffer.c (Fset_buffer): Doc fix. (Bug#12624)
+
+2012-10-11 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * buffer.c (Fkill_buffer): Null out the overlay list(s) as well.
+
+ * eval.c (Fautoload): Remember previous autoload status in load-history.
+
+2012-10-11 Paul Eggert <eggert@cs.ucla.edu>
+
+ lread.c, macros.c, marker.c, menu.c, minibuf.c: Use bool for booleans.
+ * lread.c (load_each_byte, new_backquote_flag, readchar)
+ (read_filtered_event, lisp_file_lexically_bound_p)
+ (safe_to_load_version, Fload, complete_filename_p, openp)
+ (build_load_history, readevalloop, read_escape, read1)
+ (string_to_number, read_vector, read_list):
+ * macros.c (Fstart_kbd_macro):
+ * marker.c (CONSIDER):
+ * menu.c (parse_single_submenu, digest_single_submenu)
+ (find_and_return_menu_selection, Fx_popup_menu):
+ * minibuf.c (read_minibuf_noninteractive, read_minibuf)
+ (Ftry_completion):
+ * nsmenu.m (ns_update_menubar, runMenuAt:forFrame:keymaps:):
+ (ns_menu_show):
+ * xmenu.c (set_frame_menubar, create_and_show_popup_menu)
+ (xmenu_show, xdialog_show):
+ Use bool for booleans.
+ * lread.c (safe_to_load_version): Rename from safe_to_load_p,
+ as it's not a predicate. All uses changed. Omit unnecessary
+ buffer termination.
+
+2012-10-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * editfns.c (save_excursion_save): Use nil if mark points to nowhere.
+ (save_excursion_restore): Do not restore mark if it was not saved.
+
+2012-10-11 Paul Eggert <eggert@cs.ucla.edu>
+
+ * marker.c (cached_modiff): EMACS_INT, not int.
+
+ * w32select.c (waiting_for_input): Declare by including "keyboard.h"
+ instead of having a wrong decl.
+ * nsmenu.m (waiting_for_input): Remove wrong decl.
+
+2012-10-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ keyboard.c, keymap.c: Use bool for booleans.
+ * dispnew.c (sit_for): Distinguish between 3-way display_option
+ and boolean do_display.
+ * keyboard.c (single_kboard, this_command_key_count_reset)
+ (waiting_for_input, echoing, immediate_quit, input_pending)
+ (interrupt_input, interrupts_deferred, pop_kboard)
+ (temporarily_switch_to_single_kboard, ignore_mouse_drag_p)
+ (command_loop_1, adjust_point_for_property)
+ (safe_run_hooks_error, input_polling_used, read_char):
+ (help_char_p, readable_events, kbd_buffer_events_waiting)
+ (kbd_buffer_get_event, timer_check_2, make_lispy_event)
+ (lucid_event_type_list_p, get_input_pending):
+ (gobble_input, menu_separator_name_p, menu_bar_item)
+ (parse_menu_item, parse_tool_bar_item, read_char_x_menu_prompt)
+ (read_char_minibuf_menu_prompt, access_keymap_keyremap)
+ (keyremap_step, test_undefined, read_key_sequence)
+ (detect_input_pending, detect_input_pending_ignore_squeezables)
+ (detect_input_pending_run_timers, requeued_events_pending_p)
+ (quit_throw_to_read_char, Fset_input_interrupt_mode):
+ * keymap.c (get_keymap, keymap_parent, keymap_memberp)
+ (access_keymap_1, access_keymap, map_keymap, get_keyelt)
+ (Fdefine_key, Flookup_key, struct accessible_keymaps_data)
+ (accessible_keymaps_1, Fkey_description, push_key_description):
+ (shadow_lookup, struct where_is_internal_data)
+ (where_is_internal, Fwhere_is_internal, where_is_internal_1)
+ (Fdescribe_buffer_bindings, describe_map_tree, struct describe_map_elt)
+ (describe_map, describe_vector):
+ * menu.c (single_menu_item):
+ * nsmenu.m (ns_update_menubar):
+ * process.c (wait_reading_process_output):
+ * search.c (scan_buffer, scan_newline):
+ Use bool for boolean.
+ * keyboard.c (timers_run, swallow_events)
+ (detect_input_pending_run_timers):
+ * process.c (wait_reading_process_output):
+ Use unsigned for counter where wraparound-on-overflow is desired,
+ since unsigned is guaranteed to have that behavior and signed is not.
+ (read_char): Use ptrdiff_t for string length.
+ (get_input_pending): Remove first argument, since it was always
+ the same pointer-to-int (now pointer-to-boolean) &input_pending,
+ and behave as if it had that value. Return new value of
+ input_pending. All callers changed.
+ * keyboard.h (struct kboard): Use unsigned : 1 for boolean member
+ immediate_echo. Use ptrdiff_t for echo_after_prompt, since it's
+ a string length.
+ * keymap.c (push_key_description): Omit last arg, which was always 1.
+ All callers changed.
+
+ * regex.c (immediate_quit) [emacs]: Remove duplicate decl.
+
+2012-10-10 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/dispnew.$(O), $(BLD)/indent.$(O))
+ ($(BLD)/term.$(O)): Update dependencies.
+
+2012-10-10 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (mark_object): Use meaningful PVEC_NORMAL_VECTOR.
+ * lisp.h (enum pvec_type): Adjust comments and omit explicit
+ initializer for PVEC_NORMAL_VECTOR.
+
+2012-10-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ Clean out old termopts cruft.
+ * termopts.h (flow_control, meta_key): Remove unused decls.
+ * dispnew.c, indent.c, nsterm.m, term.c, xsettings.c, xsmfns.c:
+ Don't include termopts.h.
+
+2012-10-10 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (gc_sweep): Use pointer-to-a-pointer loop for buffers.
+
+2012-10-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ * commands.h (immediate_quit): Remove duplicate decl.
+
+2012-10-09 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfont.m (Vfonts_in_cache): Remove, not needed as font.c handles
+ caching.
+ (nsfont_open): Remove setting of Vfonts_in_cache.
+ (syms_of_nsfont): Remove initialization of Vfonts_in_cache.
+
+2012-10-09 Eli Zaretskii <eliz@gnu.org>
+
+ * w32fns.c (w32_last_error): Change the return value to DWORD, to
+ match what GetLastError returns. Explain why the function is
+ needed.
+
+ * frame.c (delete_frame): Rename local variable 'tooltip_frame' to
+ 'is_tooltip_frame', to avoid confusion with its global namesake.
+
+2012-10-08 Daniel Colascione <dancol@dancol.org>
+
+ * xdisp.c (start_hourglass): Call w32_note_current_window when
+ HAVE_NTGUI, not just WINDOWSNT, resolving a problem in the cygw32
+ build that caused Emacs to display the hourglass cursor forever.
+
+ * w32fns.c (Fx_display_color_cells): Instead of using NCOLORS,
+ which is broken under remote desktop, calculate the number of
+ colors available for a display based on the display's number of
+ planes and number of bits per pixel per plane. (bug#10397).
+
+2012-10-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfont.m (Vfonts_in_cache): New variable.
+ (nsfont_open): Use unsignedLongLongValue for cache in case wide ints
+ are used. Add cached fonts to Vfonts_in_cache.
+ (syms_of_nsfont): Initialize and staticpro Vfonts_in_cache.
+
+2012-10-08 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in (LOCAL_FLAGS): Don't define HAVE_NTGUI, it's now
+ in nt/config.nt.
+ (FONT_H): Define after FRAME_H.
+ ($(BLD)/emacs.$(O), $(BLD)/process.$(O), $(BLD)/w32heap.$(O)):
+ Update dependencies.
+
+ * w32term.c: Remove leftover declaration of keyboard_codepage.
+
+2012-10-08 Eli Zaretskii <eliz@gnu.org>
+
+ * makefile.w32-in (FONT_H): Add $(FRAME_H).
+ (W32TERM_H): Add $(ATIMER_H) and $(FRAME_H).
+ ($(BLD)/emacs.$(O), $(BLD)/w32console.$(O)): Update dependencies.
+ (GLOBAL_SOURCES): Add cygw32.c.
+ ($(BLD)/unexw32.$(O)):
+ ($(BLD)/w32.$(O)):
+ ($(BLD)/w32console.$(O)):
+ ($(BLD)/w32fns.$(O)):
+ ($(BLD)/w32heap.$(O)):
+ ($(BLD)/w32menu.$(O)):
+ ($(BLD)/w32proc.$(O)): Add w32common.h.
+
+ * w32fns.c (w32_color_map_lookup, x_to_w32_color): Argument is now
+ 'const char *'.
+ (x_to_w32_color): Don't modify the argument, modify a copy instead.
+
+2012-10-08 Daniel Colascione <dancol@dancol.org>
+
+ * w32term.h (WM_EMACS_BRINGTOTOP, WM_EMACS_INPUT_READY)
+ (WM_EMACS_END): Change WM_EMACS_BRINGTOTOP from 22 to 21 to close
+ accidental message numbering hole. Change other messages to
+ match.
+
+ * w32select.h (HAVE_W32SELECT): Remove.
+
+ * w32select.c, w32proc.c, w32menu.c, w32console.c, w32.c: Include
+ w32common.h instead of w32heap.h.
+
+ * w32heap.h (ROUND_UP, ROUND_DOWN, get_page_size)
+ (get_allocation_unit, get_processor_type, get_w32_major_version)
+ (get_w32_minor_version, sysinfo_cache, osinfo_cache)
+ (w32_major_version, w32_minor_version, w32_build_number, OS_9X)
+ (OS_NT, os_subtype, cache_system_info): Move declarations to
+ w32common.
+
+ * w32heap.c: Include w32common.h.
+ (sysinfo_cache, syspage_mask, osinfo_cache, w32_major_version)
+ (w32_minor_version, w32_build_number, w32_subtype):
+ Remove duplicate definitions.
+
+ * w32fns.c: Include w32common.h; include w32heap.h only in
+ WINDOWSNT.
+
+ (Fx_file_dialog): Clarify comment on GetOpenFileName structure.
+ Use `report_file_error' instead of `error' in order to better
+ inform users of what went wrong. Increase NTGUI_UNICODE file
+ dialog box file name length to 32k, the maximum allowed by the NT
+ kernel.
+
+ * w32common.h: New file.
+ (ROUND_UP, ROUND_DOWN, get_page_size)
+ (get_allocation_unit, get_processor_type, get_w32_major_version)
+ (get_w32_minor_version, sysinfo_cache, osinfo_cache)
+ (w32_major_version, w32_minor_version, w32_build_number, OS_9X)
+ (OS_NT, os_subtype, cache_system_info): Move here.
+
+ * unexw32.c, unexcw.c: Include w32common.h.
+
+ * emacs.c (main): Use (defined (WINDOWSNT) || defined
+ HAVE_NTGUI) instead of removed HAVE_W32SELECT to decide whether
+ to call syms_of_w32select.
+
+ * cygw32.h: Remove obsolete EXFUN declarations.
+
+ * cygw32.c (Qutf_16_le): Rename to Qutf_16le.
+
+ * Makefile.in (SOME_MACHINE_OBJECTS): Reverse accidental removal
+ of w32inevt.o from SOME_MACHINE_OBJECTS.
+
+2012-10-08 Daniel Colascione <dancol@dancol.org>
+
+ * image.c: Permanent fix for JPEG compilation issue --- limit
+ jpeglib `boolean' redefinition to Cygwin builds.
+
+2012-10-08 Eli Zaretskii <eliz@gnu.org>
+
+ * image.c (CHECK_LIB_AVAILABLE): Remove, no longer used.
+
+ * emacs.c (DAEMON_MUST_EXEC) [HAVE_NTGUI]: Define this only on
+ Cygwin.
+
+2012-10-08 Daniel Colascione <dancol@dancol.org>
+
+ * xfaces.c, xdisp.c, window.c, w32xfns.c, w32term.h, w32term.c,
+ w32select.h w32select.c, w32proc.c, w32menu.c, w32inevt.c,
+ w32help.c, w32font.c, w32font.c, w32fns.c, w32console.c, w32.h,
+ w32.c, unexw32.c, termhooks.h, process.c, menu.c, keyboard.h,
+ keyboard.c, image.c, frame.h, frame.c, fontset.c, font.h, font.c,
+ emacs.c, dispextern.h, cygw32.h, cygw32.c, conf_post.h,
+ Makefile.in: use HAVE_NTGUI for W32 GUI and WINDOWSNT for the
+ operating system. defined(HAVE_NTGUI) && !defined(WINDOWSNT) is
+ now a supported configuration.
+
+ * Makefile.in: consolidate image variables into LIBIMAGE; add
+ W32_OBJ and W32_LIBS. Compile new files.
+
+ * conf_post.h:
+ (_DebPrint) declare tracing facility for W32 debugging. We need
+ to unify tracing later.
+
+ (NTGUI_UNICODE) Define when compiling for Cygwin to allow the
+ unconditional use of W32 Unicode functions. Cygwin runs only on
+ 100% Unicode operating systems.
+
+ * cygw32.c: New file. Define Cygwin-specific facilities.
+ (Fcygwin_convert_path_to_windows)
+ (Fcygwin_convert_path_from_windows): New user functions for
+ accessing Cygwin path-munging routines.
+
+ * cygw32.h: New file.
+ (WCSDATA, to_unicode, from_unicode): Define facilities for storing
+ UTF-16LE strings temporarily inside non-Lisp-visible string
+ objects.
+
+ (w32_strerror): Just what it says on the tin.
+
+ * emacs.c: Make the NS fork-then-exec code for daemon-launching
+ also run for Cygwin; both systems have the same problem with using
+ GUI facilities in a forked child. Also call syms_of_cygw32,
+ syms_of_w32select in correct places.
+
+ (DAEMON_MUST_EXEC): new macro defined to signal that a platform
+ needs fork-then-exec for daemon launching.
+
+ * font.h: Include frame.h.
+
+ * image.c: Use the image library cache machinery only when we're
+ compiling for native WINDOWSNT; Cygwin can use shared libraries
+ like any other Unixlike system.
+
+ * keyboard.c: Clarify a comment regarding the input loop.
+
+ * menu.c: When NTGUI_UNICODE is defined, use Unicode menu
+ functions directly instead of trying to detect at runtime that our
+ host operating system supports them. We make this change for two
+ reasons: Cygwin lacks support for the multibyte character
+ conversion functions used by the legacy menu code, and Cygwin
+ never needs to rely on non-Unicode APIs.
+
+ * unexw32.c (hinst): Declare extern.
+
+ * w32.c: Change header order;
+ (w32_strerror): Move to w32fns.c because we need it for
+ non-WINDOWSNT builds.
+
+ * w32.h: Add #error macro to make sure we don't include w32.h for
+ Cygwin builds. Remove w32select declarations.
+
+ * w32console.c (w32_sys_ring_bell, Fset_message_beep): Move to
+ w32fns.c. w32console.c is WINDOWSNT-only.
+
+ * w32fns.c: Include cygw32.h or w32.h depending on CYGWIN; more
+ NTGUI_UNICODE tweaks. (See above.) Change _snprintf to the more
+ POSIXy alternative.
+ (faked_key, sysinfo_cache, osinfo_cahce, syspage_mask)
+ (w32_major_version, w32_minor_version, w32_build_number)
+ (os_subtype, sound_type): Define here
+ (w32_defined_color): Make color parameter const for consistency
+ with other _defined_color functions.
+ (w32_createwindow): Unconditionally call w32_init_class instead of
+ doing so only when hprevinst is non-NULL. Plumbing hprevinst
+ through the code is complex and unnecessary because class
+ registration is practically free.
+ (w32_name_of_message): New EMACSDEBUG-only function.
+ (Fset_message_beep): Move here
+ (Fx_open_connection): Require that the display name for Windows be
+ "w32" for consistency, emacsclient disambiguation, and maybe, one
+ day, multi-window-system support.
+ (file_dialog_callback): NTGUI_UNICODE changes; encode and decode
+ Cygwin files for W32 GUI facilities, since these clearly don't
+ expect Cygwin names.
+ (_DebPrint): Define.
+ (w32_strerror, w32_console_toggle_lock_key, w32_kbd_mods_to_emacs)
+ (w32_kbd_patch_key, w32_sys_ring_bell): Move here.
+ (Ssystem_move_file_to_trash): Define only for native WINDOWSNT.
+ (w32_last_error): Remove.
+
+ * w32font.c: Define _strlwr to strlwr for non-WINDOWSNT builds.
+
+ * w32heap.c (syspage_mask): Declare here.
+ (cache_system_info): Remove.
+
+ * w32inevt.c (faked_key): Define globally, not statically.
+ (w32_kbd_mods_to_emacs, w32_kbd_patch_key, faked_key)
+ (w32_console_toggle_lock_key): Move to w32fns.c.
+
+ * w32menu.c: Include setjmp.h. NTGUI_UNICODE changes throughout.
+
+ * w32proc.c (_DebPrint): Move to w32fns.c.
+ * w32select.c: Include string.h, stdio.h for Cygwin.
+ * w32select.h: New File.
+
+ * w32term.c: Include io.h for non-CYGWIN builds; needed for
+ get_osfhandle.
+ (w32_message_fd): New variable. Under Cygwin, holds the file
+ descriptor the system used to tell us about pending thread
+ messages.
+
+ (w32_init_term): Remove incorrect calls to fcntl and init_sigio
+ that prevented compilation under non-WINDOWSNT systems.
+
+ (w32_initialize): Open /dev/windows and assign it to
+ w32_message_fd. Provide w32 feature.
+
+ * w32term.h: Include frame.h, atimer.h. Declare various frame functions.
+ (WM_EMACS_INPUT_READY): add.
+ (prepend_msg, w32_message_fd): Declare globally.
+
+ * w32xfns.c:
+ (keyboard_handle): Use only when WINDOWSNT.
+ (notify_msg_ready): New function. Posts a message to the main
+ thread's message queue under CYGWIN, which wakes up the main
+ thread from select(2) by making the /dev/windows file descriptor
+ ready. Under WINDOWSNT, it sets an event the same way the old
+ code did.
+
+ (post, prepend_msg): Actually call notify_msg_ready instead of
+ setting the input event directly.
+
+2012-10-07 Eli Zaretskii <eliz@gnu.org>
+
+ * ralloc.c (relinquish): If a heap is ready to be relinquished,
+ but it still has blocs in it, don't return it to the system,
+ instead of aborting. (Bug#12402)
+
+2012-10-07 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_dumpglyphs_image): Only draw slice of image (Bug#12506).
+
+ * nsterm.m (ns_update_auto_hide_menu_bar): Remove defintion of
+ MAC_OS_X_VERSION_10_6.
+ (syms_of_nsterm): Remove comment about Panther and above for
+ ns-antialias-text.
+ * nsterm.h (MAC_OS_X_VERSION_10_3, onTiger): Remove.
+ (EmacsApp): Remove check for >= MAC_OS_X_VERSION_10_4.
+ (struct nsfont_info): Remove check for >= MAC_OS_X_VERSION_10_3.
+
+ * nsselect.m (ns_string_from_pasteboard): Remove check for >=
+ MAC_OS_X_VERSION_10_4.
+
+ * nsmenu.m (fillWithWidgetValue:): Remove code for <
+ MAC_OS_X_VERSION_10_2.
+
+ * nsimage.m (setPixmapData, getPixelAtX, setAlphaAtX): Remove onTiger.
+
+ * nsfns.m (Fns_list_services): Remove comment and check for OSX < 10.4.
+ (ns_do_applescript): Remove check for >= MAC_OS_X_VERSION_10_4.
+
+ * nsterm.m (ns_in_resize): Remove (Bug#12479).
+ (ns_resize_handle_rect, mouseDown, mouseUp, mouseDragged): Remove.
+ (ns_clear_frame, sendEvent, windowDidResize, drawRect:):
+ Remove ns_in_resize check.
+ (ns_clear_frame_area): Remove resize handle code.
+
+ * nsfns.m (ns_in_resize): Remove.
+ (x_set_icon_name, ns_set_name, ns_set_name_as_filename):
+ Remove ns_in_resize check.
+
+2012-10-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ Improve sys_siglist detection.
+ * sysdep.c (sys_siglist, init_signals): Use _sys_siglist if it's
+ defined as a macro, as is done in Solaris.
+ (sys_siglist_entries): New macro.
+ (save_strsignal): Use it.
+ * syssignal.h (safe_strsignal): Now ATTRIBUTE_CONST, to pacify
+ GCC 4.7.2 on Fedora 17 with the fixed sys_siglist detection.
+
+2012-10-06 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfns.m (Fx_create_frame): Call x_default_parameter with
+ fullscreen/Fullscreen.
+
+ * nsterm.h (EmacsView): Rename tbar_height to tibar_height.
+ tobar_height is new.
+
+ * nsterm.m (x_make_frame_visible): Check for fullscreen.
+ (ns_fullscreen_hook): Activate old style fullscreen with a timer.
+ (ns_term_init): Set activateIgnoringOtherApps if old style fullscreen.
+ (windowDidResize:): Check for correct window if old style fullscreen.
+ Capitalize word in comment. Remove incorrect comment.
+ (initFrameFromEmacs:): tbar_height renamed tibar_height.
+ (windowDidEnterFullScreen:): Toggle toolbar for fullscreen to fix
+ error in drawing background.
+ (toggleFullScreen:): Remove comment. Rearrange calls.
+ Set toolbar values to zero, save old height in tobar_height.
+ Restore tool bar height when leaving fullscreen.
+ (canBecomeMainWindow): New function.
+
+2012-10-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ * keyboard.c (read_char): Remove unnecessary 'volatile's and label.
+
+2012-10-05 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (stop_timer_thread): Fix declaration of 'err'.
+
+ * w32.c (utime): Open the file with FILE_FLAG_BACKUP_SEMANTICS, so
+ that time stamps of directories could also be changed.
+ Don't request the too broad GENERIC_WRITE, only the more restrictive
+ FILE_WRITE_ATTRIBUTES access rights.
+
+ * fileio.c (Fset_file_times): Special-case ignoring errors for
+ directories only on MSDOS, not on MS-Windows.
+
+2012-10-05 Ikumi Keita <ikumi@ikumi.que.jp> (tiny change)
+
+ * minibuf.c (Fcompleting_read): Doc fix. (Bug#12555)
+
+2012-10-04 Eli Zaretskii <eliz@gnu.org>
+
+ * w32.c (utime): Test for INVALID_HANDLE_VALUE, not for NULL, to
+ see whether CreateFile failed.
+
+2012-10-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ * profiler.c (handle_profiler_signal): Inhibit pending signals too,
+ to avoid similar races.
+ * keyboard.c (pending_signals): Now bool, not int.
+
+ Port timers to OpenBSD, plus check for timer failures.
+ OpenBSD problem reported by Han Boetes.
+ * profiler.c (setup_cpu_timer): Check for failure of timer_settime
+ and/or setitimer.
+ (Fprofiler_cpu_stop): Don't assume HAVE_SETITIMER.
+ * syssignal.h (HAVE_ITIMERSPEC): New macro. This is for platforms
+ like OpenBSD, which has timer_settime but does not declare it.
+ OpenBSD does not define SIGEV_SIGNAL, so use that when deciding
+ whether to use itimerspec-related primitives. All uses of
+ HAVE_TIMER_SETTIME replaced with HAVE_ITIMERSPEC.
+
+2012-10-02 Paul Eggert <eggert@cs.ucla.edu>
+
+ * profiler.c (handle_profiler_signal): Fix a malloc race
+ that caused Emacs to hang on Fedora 17 when profiling Lisp.
+
+2012-10-02 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (windowDidEnterFullScreen): Remove fprintf.
+
+2012-10-02 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (sys_wait): Declare 'signame' 'const char *', to be
+ consistent with the change in return value of 'safe_strsignal'.
+
+2012-10-02 Paul Eggert <eggert@cs.ucla.edu>
+
+ Prefer plain 'static' to 'static inline' (Bug#12541).
+ * bidi.c (bidi_get_type, bidi_check_type, bidi_get_category)
+ (bidi_set_sor_type, bidi_push_embedding_level)
+ (bidi_pop_embedding_level, bidi_remember_char, bidi_copy_it)
+ (bidi_cache_reset, bidi_cache_shrink, bidi_cache_fetch_state)
+ (bidi_cache_search, bidi_cache_ensure_space)
+ (bidi_cache_iterator_state, bidi_cache_find)
+ (bidi_peek_at_next_level, bidi_set_paragraph_end)
+ (bidi_count_bytes, bidi_char_at_pos, bidi_fetch_char)
+ (bidi_explicit_dir_char, bidi_resolve_neutral_1):
+ Now 'static', not 'static inline'.
+
+ Count overruns when profiling; change units to ns.
+ * profiler.c (handle_profiler_signal): Count sampling intervals, not ms.
+ Give extra weight to samples after overruns, to attempt to count
+ the time more accurately.
+ (setup_cpu_timer): Change sampling interval units from ms to ns, since
+ the underlying primitives nominally do ns.
+ (Fprofiler_cpu_start): Document the change. Mention that
+ the sampling intervals are only approximate.
+
+2012-10-02 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * frame.c (Fmake_terminal_frame): Prefer safer CONSP over !NILP.
+
+ * coding.h (ENCODE_FILE, DECODE_FILE, DECODE_SYSTEM): Remove special
+ case for the special 0 coding-system.
+
+ * buffer.c (Fset_buffer_multibyte): Signal an error instead of widening.
+ (Fmake_overlay): Remove redundant tests.
+ (fix_start_end_in_overlays): Remove redundant recentering.
+
+2012-10-02 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/alloc.$(O), $(BLD)/gmalloc.$(O)):
+ Update dependencies.
+
+2012-10-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix a malloc race condition involving strsignal.
+ A signal can arrive in the middle of a malloc, and Emacs's signal
+ handler can invoke strsignal, which can invoke malloc, which is
+ not portable. This race condition bug makes Emacs hang on GNU/Linux.
+ Fix it by altering the signal handler so that it does not invoke
+ strsignal.
+ * emacs.c (shut_down_emacs): Use safe_strsignal, not strsignal.
+ * process.c (status_message): Use const pointer, in case strsignal
+ is #defined to safe_strsignal.
+ * sysdep.c (sys_siglist, init_signals): Always define and
+ initialize a substitute sys_siglist if the system does not define
+ one, even if HAVE_STRSIGNAL.
+ (safe_strsignal): Rename from strsignal. Always define,
+ using sys_siglist. Return a const pointer.
+ * syssignal.h (safe_strsignal): New decl.
+ (strsignal) [!HAVE_STRSIGNAL]: Define in terms of safe_strsignal.
+
+2012-10-01 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (timer_loop): Fix code that waits for timer
+ expiration, to avoid high CPU usage.
+
+2012-10-01 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * fns.c (check_hash_table, get_key_arg, maybe_resize_hash_table)
+ (sweep_weak_table): Remove redundant prototypes.
+
+2012-10-01 Fabrice Popineau <fabrice.popineau@gmail.com>
+
+ * emacs.c: Move the inclusion of TERM_HEADER after including
+ windows.h on WINDOWSNT. This avoids compilation problems with
+ MSVC.
+
+2012-10-01 Eli Zaretskii <eliz@gnu.org>
+
+ * unexw32.c (OFFSET_TO_RVA, RVA_TO_OFFSET)
+ (RVA_TO_SECTION_OFFSET): Encode all macro arguments in parentheses.
+ (RVA_TO_PTR): Cast the result of RVA_TO_OFFSET to 'unsigned char *',
+ as the previous version used 'void *'.
+
+ * ralloc.c (ROUNDUP): Fix last change.
+ (MEM_ROUNDUP): Don't cast MEM_ALIGN, it is already of type
+ 'size_t'.
+
+ * w32proc.c <disable_itimers>: New static flag.
+ (init_timers): Initialize it to zero, after creating the critical
+ sections used by the timer threads.
+ (term_timers): Set to 1 before deleting the critical sections.
+ (getitimer, setitimer): If disable_itimers is non-zero, return an
+ error indication without doing anything. Reported by Fabrice
+ Popineau <fabrice.popineau@supelec.fr> as part of bug#12544.
+ (alarm) [HAVE_SETITIMER]: Be more conformant to the expected
+ return results.
+ [!HAVE_SETITIMER]: Behave as the previous version that didn't
+ support timers.
+
+ * emacs.c (shut_down_emacs) [WINDOWSNT]: Move the call to
+ term_ntproc after all the other bookkeeping, to get timers working
+ as long as possible.
+
+2012-10-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ * xdisp.c (syms_of_xdisp): Default message-log-max to 1000, not 100.
+ Suggested by Juri Linkov in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00821.html>.
+
+ Prefer plain 'static' to 'static inline' (Bug#12541).
+ With static functions, modern compilers inline pretty well by
+ themselves; advice from programmers often hurts as much as it helps.
+ On my host (x86-64, Fedora 17, GCC 4.7.2, default 'configure'),
+ this change shrinks the text size of the Emacs executable by 1.1%
+ without affecting CPU significantly in my benchmark.
+ * alloc.c (mem_find, live_string_p, live_cons_p, live_symbol_p)
+ (live_float_p, live_misc_p, live_vector_p, live_buffer_p)
+ (mark_maybe_object, mark_maybe_pointer, bounded_number):
+ * buffer.c (bset_abbrev_mode, bset_abbrev_table)
+ (bset_auto_fill_function, bset_auto_save_file_format)
+ (bset_auto_save_file_name, bset_backed_up, bset_begv_marker)
+ (bset_bidi_display_reordering, bset_buffer_file_coding_system)
+ (bset_cache_long_line_scans, bset_case_fold_search)
+ (bset_ctl_arrow, bset_cursor_in_non_selected_windows)
+ (bset_cursor_type, bset_display_table, bset_extra_line_spacing)
+ (bset_file_format, bset_file_truename, bset_fringe_cursor_alist)
+ (bset_fringe_indicator_alist, bset_fringes_outside_margins)
+ (bset_header_line_format, bset_indicate_buffer_boundaries)
+ (bset_indicate_empty_lines, bset_invisibility_spec)
+ (bset_left_fringe_width, bset_major_mode, bset_mark)
+ (bset_minor_modes, bset_mode_line_format, bset_mode_name)
+ (bset_name, bset_overwrite_mode, bset_pt_marker)
+ (bset_right_fringe_width, bset_save_length)
+ (bset_scroll_bar_width, bset_scroll_down_aggressively)
+ (bset_scroll_up_aggressively, bset_selective_display)
+ (bset_selective_display_ellipses, bset_vertical_scroll_bar_type)
+ (bset_word_wrap, bset_zv_marker, set_buffer_overlays_before)
+ (set_buffer_overlays_after):
+ * category.c (bset_category_table):
+ * charset.c (read_hex):
+ * coding.c (produce_composition, produce_charset)
+ (handle_composition_annotation, handle_charset_annotation)
+ (char_encodable_p):
+ * dispnew.c (swap_glyph_pointers, copy_row_except_pointers)
+ (assign_row, set_frame_matrix_frame, make_current)
+ (add_row_entry):
+ * eval.c (set_specpdl_symbol, set_specpdl_old_value):
+ * fns.c (maybe_resize_hash_table):
+ * frame.c (fset_buffer_predicate, fset_minibuffer_window):
+ * gmalloc.c (register_heapinfo):
+ * image.c (lookup_image_type):
+ * intervals.c (set_interval_object, set_interval_left)
+ (set_interval_right, copy_interval_parent, rotate_right)
+ (rotate_left, balance_possible_root_interval):
+ * keyboard.c (kset_echo_string, kset_kbd_queue)
+ (kset_keyboard_translate_table, kset_last_prefix_arg)
+ (kset_last_repeatable_command, kset_local_function_key_map)
+ (kset_overriding_terminal_local_map, kset_real_last_command)
+ (kset_system_key_syms, clear_event, set_prop):
+ * lread.c (digit_to_number):
+ * marker.c (attach_marker, live_buffer, set_marker_internal):
+ * nsterm.m (ns_compute_glyph_string_overhangs):
+ * process.c (pset_buffer, pset_command)
+ (pset_decode_coding_system, pset_decoding_buf)
+ (pset_encode_coding_system, pset_encoding_buf, pset_filter)
+ (pset_log, pset_mark, pset_name, pset_plist, pset_sentinel)
+ (pset_status, pset_tty_name, pset_type, pset_write_queue):
+ * syntax.c (bset_syntax_table, dec_bytepos):
+ * terminal.c (tset_param_alist):
+ * textprop.c (interval_has_some_properties)
+ (interval_has_some_properties_list):
+ * window.c (wset_combination_limit, wset_dedicated)
+ (wset_display_table, wset_hchild, wset_left_fringe_width)
+ (wset_left_margin_cols, wset_new_normal, wset_new_total)
+ (wset_normal_cols, wset_normal_lines, wset_parent, wset_pointm)
+ (wset_right_fringe_width, wset_right_margin_cols)
+ (wset_scroll_bar_width, wset_start, wset_temslot, wset_vchild)
+ (wset_vertical_scroll_bar_type, wset_window_parameters):
+ * xdisp.c (wset_base_line_number, wset_base_line_pos)
+ (wset_column_number_displayed, wset_region_showing)
+ (window_box_edges, run_window_scroll_functions)
+ (append_glyph_string_lists, prepend_glyph_string_lists)
+ (append_glyph_string, set_glyph_string_background_width)
+ (append_glyph, append_composite_glyph)
+ (take_vertical_position_into_account):
+ * xfaces.c (x_create_gc, x_free_gc, merge_face_vectors)
+ (face_attr_equal_p, lface_equal_p, hash_string_case_insensitive)
+ (lface_hash, lface_same_font_attributes_p, lookup_face):
+ * xml.c (libxml2_loaded_p):
+ * xterm.c (x_set_mode_line_face_gc, x_set_glyph_string_gc)
+ (x_set_glyph_string_clipping, x_clear_glyph_string_rect):
+ Now 'static', not 'static inline'.
+
+ * bidi.c: Tune.
+ (bidi_copy_it): Do the whole copy with a single memcpy.
+ (bidi_char_at_pos): Merge the two STRING_CHAR calls into one.
+
+ Revert the FOLLOW-SYMLINKS change for file-attributes.
+ Doing it right would require several changes to Tramp, and there's
+ not enough time to get that tested before the freeze today.
+ * dired.c (directory_files_internal, Ffile_attributes):
+ Undo last change.
+
+ * frame.c (x_report_frame_params): Port better to wider ints.
+ Do not assume that EMACS_UINT is the same width as uprintmax_t,
+ or that pointers can be printed in 15 decimal digits.
+ Avoid GCC warnings if EMACS_UINT is wider than a pointer.
+
+2012-09-30 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ Support x64 build on MS-Windows.
+ * w32term.h (SCROLL_BAR_PACK, SCROLL_BAR_UNPACK): Define for x64.
+ (SET_SCROLL_BAR_W32_WINDOW): Cast ID to intptr_t, for
+ compatibility with x64.
+ (x_get_focus_frame): Add prototype.
+
+ * w32term.c (w32_draw_underwave): Don't use GCC extensions for
+ defining an XRectangle structure.
+
+ * w32proc.c (RVA_TO_PTR, w32_executable_type): Fix pointer
+ arithmetics for compatibility with x64.
+
+ * w32menu.c (add_menu_item): Use UINT_PTR instead of UINT, for
+ compatibility with x64.
+
+ * w32heap.h: Adjust prototypes and declarations.
+
+ * w32heap.c (RVA_TO_PTR, allocate_heap, sbrk, init_heap)
+ (round_heap): Use DWORD_PTR, ptrdiff_t and size_t instead of
+ DWORD, long, and unsigned long, for compatibility with x64.
+ (allocate_heap) [_WIN64]: Reserve 32GB of memory.
+ (sbrk): Argument is now of type ptrdiff_t.
+
+ * w32fns.c (HMONITOR): Condition declaration on _WIN32_WINNT being
+ less than 0x0500.
+ (w32_msg_pump): Use WPARAM type for 'result'.
+
+ * w32.c (init_environment, get_emacs_configuration): Support AMD64
+ architecture.
+ (init_ntproc): Cast arguments of _open_osfhandle to intptr_t, for
+ compatibility with x64.
+
+ * vm-limit.c (lim_data): Now size_t.
+ (check_memory_limits): Adjust prototypes of real_morecore and
+ __morecore to receive argument of type ptrdiff_t. Use size_t for
+ five_percent and data_size.
+
+ * unexw32.c: Use DWORD_PTR instead of DWORD for file-scope
+ variables, for compatibility with x64.
+ (rva_to_section, offset_to_section, relocate_offset)
+ (OFFSET_TO_RVA, RVA_TO_OFFSET, RVA_TO_SECTION_OFFSET)
+ (PTR_TO_RVA, RVA_TO_PTR, OFFSET_TO_PTR, get_section_info)
+ (copy_executable_and_dump_data): Use DWORD_PTR instead of DWORD
+ for compatibility with x64.
+
+ * sysdep.c (STDERR_FILENO): Define if not already defined.
+
+ * ralloc.c (real_morecore): Argument type is now ptrdiff_t.
+ (__morecore): Argument type is now ptrdiff_t.
+ (ROUNDUP, MEM_ROUNDUP): Use size_t instead of 'unsigned long'.
+ (relinquish): Use ptrdiff_t type for 'excess'.
+ (r_alloc_sbrk): Argument type is now ptrdiff_t.
+
+ * makefile.w32-in (HEAPSIZE): Get value from EMACS_HEAPSIZE.
+ (bootstrap-temacs-CMD, bootstrap-temacs-SH): Use $(EMACS_PURESIZE)
+ instead of a literal number.
+
+ * gmalloc.c [WINDOWSNT]: Include w32heap.h.
+ (min): Define only if not already defined.
+
+ * frame.c (x_report_frame_params): Use EMACS_UINT for the return
+ value of FRAME_X_WINDOW, to fit a 64-bit pointer on 64-bit Windows
+ hosts.
+
+ * image.c (x_bitmap_pixmap): Return ptrdiff_t, not int, since
+ 'bitmaps' is a pointer.
+
+ * dispextern.h (x_bitmap_pixmap): Adjust prototype.
+
+ * alloc.c (gdb_make_enums_visible): Now conditional on __GNUC__.
+
+2012-09-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ file-attributes has a new optional arg FOLLOW-SYMLINKS.
+ * dired.c (directory_files_internal, Ffile_attributes):
+ New arg follow_symlinks. All uses changed.
+
+2012-09-30 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * .gdbinit (xbacktrace): Adjust to recent "struct backtrace" change.
+
+2012-09-30 Eli Zaretskii <eliz@gnu.org>
+
+ Support atimers and CPU profiler via profile.c on MS-Windows.
+ * w32proc.c (sig_mask, crit_sig): New static variables.
+ (sys_signal): Support SIGALRM and SIGPROF.
+ (sigemptyset, sigaddset, sigfillset, sigprocmask)
+ (pthread_sigmask, setpgrp): Move here from w32.c. sigaddset,
+ sigfillset, and sigprocmask are no longer no-ops.
+ (sigismember): New function.
+ (struct itimer_data): New definition.
+ (ticks_now, real_itimer, prof_itimer, clocks_min, crit_real)
+ (crit_prof): New static variables.
+ (MAX_SINGLE_SLEEP): New definition.
+ (timer_loop, stop_timer_thread, term_timers, init_timers)
+ (start_timer_thread, getitimer, setitimer): New functions.
+ (alarm): No longer a no-op, calls setitimer.
+
+ * w32.c (term_ntproc): Call term_timers.
+ (init_ntproc): Make sure all signals are unblocked at startup, to
+ erase any traces of dumping. Call init_timers.
+
+ * w32fns.c (hourglass_timer, HOURGLASS_ID): Remove.
+ Windows-specific code to display the hourglass mouse pointer is no
+ longer used.
+ (w32_wnd_proc): Remove code that handled the WM_TIMER message due
+ to hourglass timer expiration.
+ (start_hourglass, cancel_hourglass, DEFAULT_HOURGLASS_DELAY):
+ Remove, no longer used.
+ (w32_note_current_window, show_hourglass, hide_hourglass):
+ New functions, in support of hourglass cursor display similar to other
+ window systems.
+ (syms_of_w32fns): Don't initialize hourglass_timer.
+
+ * xdisp.c (start_hourglass, cancel_hourglass): Now used on
+ WINDOWSNT as well.
+ (start_hourglass) [WINDOWSNT]: Call w32_note_current_window.
+
+ * w32.h (init_timers, term_timers): Add prototypes.
+
+2012-09-30 Kenichi Handa <handa@gnu.org>
+
+ * coding.c (decode_coding_ccl, encode_coding_ccl): Pay attention
+ to the buffer relocation which may be caused by ccl_driver.
+
+2012-09-30 Jan Djärv <jan.h.d@swipnet.se>
+
+ * xfns.c (Fx_file_dialog): Update comment.
+
+ * w32fns.c (Fx_file_dialog): Update comment.
+
+ * nsfns.m (Fns_read_file_name): Add argument DIR_ONLY_P.
+ Initialize panel name field if OSX >= 10.6.
+
+ * fileio.c (Fnext_read_file_uses_dialog_p): Add HAVE_NS.
+
+ * nsfns.m (ns_frame_parm_handlers): Add x_set_fullscreen.
+
+ * nsterm.m (NEW_STYLE_FS): New define.
+ (ns_fullscreen_hook, windowWillEnterFullScreen)
+ (windowDidEnterFullScreen, windowWillExitFullScreen)
+ (windowDidExitFullScreen, toggleFullScreen, handleFS)
+ (setFSValue): New functions.
+ (EmacsFSWindow): New implementation.
+ (canBecomeKeyWindow): New function for EmacsFSWindow.
+ (ns_create_terminal): Set fullscreen_hook to ns_fullscreen_hook.
+ (dealloc): Release nonfs_window if in fullscreen.
+ (updateFrameSize:): Call windowDidMove to update top/left.
+ (windowWillResize:toSize:): Check if frame is still maximized.
+ (initFrameFromEmacs:): Initialize fs_state, fs_before_fs,
+ next_maximized, maximized_width, maximized_height and nonfs_window.
+ Call setCollectionBehavior if NEW_STYLE_FS. Initialize bwidth and
+ tbar_height.
+ (windowWillUseStandardFrame:defaultFrame:): Update frame parameter
+ fullscreen. Set maximized_width/height. Act on next_maximized.
+
+ * nsterm.h (MAC_OS_X_VERSION_10_7, MAC_OS_X_VERSION_10_8): New.
+ (EmacsView): Add variables for fullscreen.
+ (handleFS, setFSValue, toggleFullScreen): New in EmacsView.
+ (EmacsFSWindow): New interface for fullscreen.
+
+2012-09-30 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/profiler.$(O)): Update dependencies.
+
+2012-09-30 Chong Yidong <cyd@gnu.org>
+
+ * fns.c (Frandom): Doc fix.
+
+2012-09-30 Martin Rudalics <rudalics@gmx.at>
+
+ * window.c (Vwindow_combination_limit): New default value.
+ (Qwindow_size): New symbol replacing Qtemp_buffer_resize.
+
+2012-09-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ * syssignal.h (PROFILER_CPU_SUPPORT): Don't define if PROFILING.
+ Suggested by Eli Zaretskii in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00811.html>.
+
+2012-09-30 Eli Zaretskii <eliz@gnu.org>
+
+ * profiler.c (Fprofiler_cpu_stop): Use timer_settime only if
+ HAVE_TIMER_SETTIME is defined.
+
+2012-09-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ Profiler improvements: more-accurate timers, overflow checks.
+ * profiler.c: Don't include stdio.h, limits.h, sys/time.h,
+ signal.h, setjmp.h. Include systime.h instead.
+ (saturated_add): New function.
+ (record_backtrace, current_sample_interval): Use EMACS_INT, not size_t.
+ (record_backtrace, handle_profiler_signal): Saturate on fixnum overflow.
+ (profiler_timer, profiler_timer_ok) [HAVE_TIMER_SETTIME]:
+ New static vars.
+ (enum profiler_cpu_running): New enum.
+ (profiler_cpu_running): Now of that enum type, not bool.
+ All uses changed to store the new value.
+ (handle_profiler_signal): Rename from sigprof_handler_1,
+ for consistency with other handlers. Do not check whether
+ cpu_log is a hash-table if garbage collecting, since it
+ doesn't matter in that case.
+ (deliver_profiler_signal): Rename from sigprof_handler,
+ for consistency with other handlers.
+ (setup_cpu_timer): New function, with much of what used to be in
+ Fprofiler_cpu_start. Check for out-of-range argument.
+ Prefer timer_settime if available, and prefer
+ thread cputime clocks, then process cputime clocks, then
+ monotonic clocks, to the old realtime clock. Use make_timeval
+ to round more-correctly when falling back to setitimer.
+ (Fprofiler_cpu_start): Use it.
+ (Fprofiler_cpu_stop): Prefer timer_settime if available.
+ Don't assume that passing NULL as the 2nd argument of setitimer
+ is the same as passing a pointer to all-zero storage.
+ Ignore SIGPROF afterwards.
+ (malloc_probe): Saturate at MOST_POSITIVE_FIXNUM.
+ * sysdep.c (emacs_sigaction_init): Also mask out SIGPROF in
+ non-fatal signal handlers. Ignore SIGPROF on startup.
+ * syssignal.h (PROFILER_CPU_SUPPORT): Define this macro here, not
+ in profiler.c, since sysdep.c now uses it.
+
+ * sysdep.c (handle_fatal_signal): Bump backtrace size to 40.
+ Suggested by Eli Zaretskii in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00796.html>.
+
+2012-09-29 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/profiler.$(O)): Update dependencies.
+
+2012-09-29 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp.h (struct backtrace): Remove indirection for `function' field.
+ * xdisp.c (redisplay_internal):
+ * profiler.c (record_backtrace, sigprof_handler_1):
+ * alloc.c (Fgarbage_collect):
+ * eval.c (interactive_p, Fsignal, eval_sub, Ffuncall, Fbacktrace)
+ (Fbacktrace_frame): Adjust accordingly.
+
+2012-09-28 Glenn Morris <rgm@gnu.org>
+
+ * eval.c (Frun_hook_with_args, Frun_hook_with_args_until_success)
+ (Frun_hook_with_args_until_failure): Doc fixes.
+
+2012-09-28 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (syms_of_xdisp) <Qredisplay_internal>: Rename from
+ Qautomatic_redisplay and change the symbol name. All users changed.
+
+2012-09-28 Tomohiro Matsuyama <tomo@cx4a.org>
+
+ * profiler.c (sigprof_handler): Fix race condition.
+
+2012-09-28 Glenn Morris <rgm@gnu.org>
+
+ * lread.c (lisp_file_lexically_bound_p): Handle #! lines. (Bug#12528)
+
+2012-09-27 Paul Eggert <eggert@cs.ucla.edu>
+
+ Check more robustly for timer_settime.
+ * Makefile.in (LIB_TIMER_TIME): New macro.
+ (LIBES): Add it.
+ * atimer.c (alarm_timer, alarm_timer_ok, set_alarm, init_atimer):
+ Use HAVE_TIMER_SETTIME, not SIGEV_SIGNAL, to decide whether to
+ call timer_settime.
+
+2012-09-26 Tomohiro Matsuyama <tomo@cx4a.org>
+
+ * profiler.c (Fprofiler_cpu_start): Remove unnecessary flag SA_SIGINFO.
+
+2012-09-26 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/profiler.$(O)): Update dependencies.
+
+2012-09-26 Paul Eggert <eggert@cs.ucla.edu>
+
+ * character.h (MAYBE_UNIFY_CHAR): Remove.
+ * charset.c, charset.h (maybe_unify_char): Now static.
+ * charset.c (decode_char): Use maybe_unify_char, not MAYBE_UNIFY_CHAR.
+ Since this stuff is now private to charset.c, there's no need for
+ a public macro and no need to inline by hand.
+
+2012-09-26 Tomohiro Matsuyama <tomo@cx4a.org>
+ Stefan Monnier <monnier@iro.umontreal.ca>
+ Juanma Barranquero <lekktu@gmail.com>
+
+ * profiler.c: New file.
+ * Makefile.in (base_obj): Add profiler.o.
+ * makefile.w32-in (OBJ2, GLOBAL_SOURCES): Add profiler.c.
+ ($(BLD)/profiler.$(O)): New target.
+ * emacs.c (main): Call syms_of_profiler.
+ * alloc.c (Qautomatic_gc): New constant.
+ (MALLOC_PROBE): New macro.
+ (xmalloc, xzalloc, xrealloc, lisp_malloc, lisp_align_malloc): Use it.
+ (total_bytes_of_live_objects): New function.
+ (Fgarbage_collect): Use it. Record itself in backtrace_list.
+ Call malloc_probe for the memory profiler.
+ (syms_of_alloc): Define Qautomatic_gc.
+ * eval.c (eval_sub, Ffuncall): Reorder assignments to avoid
+ race condition.
+ (struct backtrace): Move definition...
+ * lisp.h (struct backtrace): ..here.
+ (Qautomatic_gc, profiler_memory_running): Declare vars.
+ (malloc_probe, syms_of_profiler): Declare functions.
+ * xdisp.c (Qautomatic_redisplay): New constant.
+ (redisplay_internal): Record itself in backtrace_list.
+ (syms_of_xdisp): Define Qautomatic_redisplay.
+
+2012-09-25 Eli Zaretskii <eliz@gnu.org>
+2012-09-25 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/callproc.$(O)): Update dependencies.
+
+2012-09-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ Prefer POSIX timers if available.
+ They avoid a race if the timer is too close to the current time.
+ * atimer.c (alarm_timer, alarm_timer_ok) [SIGEV_SIGNAL]: New static vars.
+ (set_alarm) [SIGEV_SIGNAL]: Use POSIX timers if available.
+ (init_atimer) [SIGEV_SIGNAL]: Initialize them.
+
+2012-09-25 Eli Zaretskii <eliz@gnu.org>
+
+ * coding.c (CHAR_STRING_ADVANCE_NO_UNIFY): Make it an alias of
+ CHAR_STRING_ADVANCE.
+ (STRING_CHAR_ADVANCE_NO_UNIFY): Make it an alias of
+ STRING_CHAR_ADVANCE.
+
+2012-09-25 Juanma Barranquero <lekktu@gmail.com>
+
+ Move Vlibrary_cache to emacs.c and reset before dumping.
+
+ * lisp.h (reset_image_types): Declare.
+ [WINDOWSNT] (Vlibrary_cache): Declare.
+
+ * image.c (reset_image_types): New function.
+
+ * emacs.c [WINDOWSNT] (Vlibrary_cache): Move from w32.c.
+ (syms_of_emacs) [WINDOWSNT] <Vlibrary_cache>: Initialize and staticpro.
+ (Fdump_emacs): Reset Vlibrary_cache and image_types.
+
+ * w32.c (Vlibrary_cache): Do not define; moved to emacs.c
+ (globals_of_w32) <Vlibrary_cache>: Do not initialize.
+
+ * w32.h (Vlibrary_cache): Do not declare.
+
+2012-09-25 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (sys_signal): Handle all signals defined by the
+ MS-Windows runtime, not just SIGCHLD. Actually install the signal
+ handlers for signals supported by Windows. Don't override
+ term_ntproc as the handler for SIGABRT.
+ (sigaction): Rewrite to call sys_signal instead of duplicating its
+ code.
+ (sys_kill): Improve commentary.
+
+ * w32.c (term_ntproc): Accept (and ignore) one argument, for
+ consistency with a signature of a signal handler. All callers
+ changed.
+ (init_ntproc): Accept an argument DUMPING. If dumping, don't
+ install term_ntproc as a signal handler for SIGABRT, as that
+ should be done by the dumped Emacs.
+
+ * w32.h (init_ntproc, term_ntproc): Adjust prototypes.
+
+ * w32select.c (term_w32select): Protect against repeated
+ invocation by setting clipboard_owner to NULL after calling
+ DestroyWindow.
+
+ * emacs.c (shut_down_emacs, main): Adapt the calls to init_ntproc
+ and term_ntproc to their modified signatures.
+
+ * character.c (char_string, string_char): Remove calls to
+ MAYBE_UNIFY_CHAR. See the discussion starting at
+ http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00433.html
+ for the details.
+
+2012-09-25 Chong Yidong <cyd@gnu.org>
+
+ * xdisp.c (mode_line_inverse_video): Delete obsolete variable.
+
+2012-09-24 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * bytecode.c (exec_byte_code): Signal an error instead of aborting,
+ when encountering an unknown bytecode.
+
+2012-09-24 Paul Eggert <eggert@cs.ucla.edu>
+
+ image.c, indent.c: Use bool for booleans.
+ * dispextern.h (struct image_type): Members valid_p, load, init
+ now return bool, not int. All uses changed.
+ * image.c: Omit unnecessary static decls.
+ (x_create_bitmap_mask, x_build_heuristic_mask):
+ Return void, not int, since callers don't care about the return value.
+ (x_create_bitmap_mask, define_image_type, valid_image_p)
+ (struct image_keyword, parse_image_spec, image_spec_value)
+ (check_image_size, image_background)
+ (image_background_transparent, x_clear_image_1)
+ (postprocess_image, lookup_image, x_check_image_size)
+ (x_create_x_image_and_pixmap, xbm_image_p)
+ (Create_Pixmap_From_Bitmap_Data, xbm_read_bitmap_data)
+ (xbm_load_image, xbm_file_p, xbm_load, xpm_lookup_color)
+ (init_xpm_functions, xpm_valid_color_symbols_p, xpm_image_p)
+ (xpm_load, xpm_load_image, lookup_rgb_color, lookup_pixel_color)
+ (x_to_xcolors, x_build_heuristic_mask, pbm_image_p, pbm_load)
+ (png_image_p, init_png_functions, png_load_body, png_load)
+ (jpeg_image_p, init_jpeg_functions, jpeg_load_body, jpeg_load)
+ (tiff_image_p, init_tiff_functions, tiff_load, gif_image_p)
+ (init_gif_functions, gif_load, imagemagick_image_p)
+ (imagemagick_load_image, imagemagick_load, svg_image_p)
+ (init_svg_functions, svg_load, svg_load_image, gs_image_p)
+ (gs_load):
+ * nsimage.m (ns_load_image):
+ * nsterm.m (ns_defined_color):
+ * xfaces.c (tty_lookup_color, tty_defined_color, defined_color):
+ * xfns.c (x_defined_color):
+ * xterm.c (x_alloc_lighter_color_for_widget)
+ (x_alloc_nearest_color_1, x_alloc_nearest_color)
+ (x_alloc_lighter_color):
+ * indent.c (disptab_matches_widthtab, current_column)
+ (scan_for_column, string_display_width, indented_beyond_p)
+ (compute_motion, vmotion, Fvertical_motion):
+ Use bool for booleans.
+
+2012-09-24 Chong Yidong <cyd@gnu.org>
+
+ * chartab.c (Fset_char_table_default): Obsolete function removed.
+
+2012-09-23 Paul Eggert <eggert@cs.ucla.edu>
+
+ Move pid_t related decls out of lisp.h.
+ * lisp.h, syswait.h (record_child_status_change, wait_for_termination)
+ (interruptible_wait_for_termination):
+ Move these decls from lisp.h to syswait.h, since they use pid_t.
+ Needed on FreeBSD; see Herbert J. Skuhra in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00571.html>.
+ * callproc.c: Include syswait.h.
+
+ gnutls.c, gtkutil.c: Use bool for boolean.
+ * gnutls.c (gnutls_global_initialized, init_gnutls_functions)
+ (emacs_gnutls_handle_error):
+ * gtkutil.c (xg_check_special_colors, xg_prepare_tooltip)
+ (xg_hide_tooltip, xg_create_frame_widgets)
+ (create_dialog, xg_uses_old_file_dialog)
+ (xg_get_file_with_chooser, xg_get_file_with_selection)
+ (xg_get_file_name, xg_have_tear_offs, create_menus, xg_create_widget)
+ (xg_item_label_same_p, xg_update_menubar)
+ (xg_modify_menubar_widgets, xg_event_is_for_menubar)
+ (xg_ignore_gtk_scrollbar, xg_set_toolkit_scroll_bar_thumb)
+ (xg_event_is_for_scrollbar, xg_pack_tool_bar, xg_make_tool_item)
+ (is_box_type, xg_tool_item_stale_p, xg_update_tool_bar_sizes)
+ (update_frame_tool_bar, free_frame_tool_bar):
+ * gtkutil.c, w32term.c, xterm.c (x_wm_set_size_hint):
+ * nsmenu.m (ns_update_menubar):
+ * nsmenu.m, w32menu.c, xmenu.c (set_frame_menubar):
+ * xfns.c (Fx_show_tip) [USE_GTK]:
+ Use bool for boolean.
+ * gtkutil.c (xg_update_frame_menubar):
+ * xmenu.c (update_frame_menubar):
+ Return void, not int, since caller ignores return value.
+ * gtkutil.c (xg_change_toolbar_position):
+ Return void, not 1.
+
+2012-09-23 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in (BLOCKINPUT_H): Remove.
+ (SYSSIGNAL_H): New macro.
+ ($(BLD)/alloc.$(O), $(BLD)/atimer.$(O), $(BLD)/buffer.$(O))
+ ($(BLD)/callproc.$(O), $(BLD)/data.$(O), $(BLD)/dired.$(O))
+ ($(BLD)/dispnew.$(O), $(BLD)/editfns.$(O), $(BLD)/emacs.$(O))
+ ($(BLD)/eval.$(O), $(BLD)/fileio.$(O), $(BLD)/floatfns.$(O))
+ ($(BLD)/fns.$(O), $(BLD)/fontset.$(O), $(BLD)/frame.$(O))
+ ($(BLD)/fringe.$(O), $(BLD)/image.$(O), $(BLD)/insdel.$(O))
+ ($(BLD)/keyboard.$(O), $(BLD)/keymap.$(O), $(BLD)/lread.$(O))
+ ($(BLD)/menu.$(O), $(BLD)/w32inevt.$(O), $(BLD)/w32proc.$(O))
+ ($(BLD)/print.$(O), $(BLD)/process.$(O), $(BLD)/ralloc.$(O))
+ ($(BLD)/search.$(O), $(BLD)/sound.$(O), $(BLD)/sysdep.$(O))
+ ($(BLD)/term.$(O), $(BLD)/window.$(O), $(BLD)/xdisp.$(O))
+ ($(BLD)/xfaces.$(O), $(BLD)/w32fns.$(O), $(BLD)/w32menu.$(O))
+ ($(BLD)/w32term.$(O), $(BLD)/w32select.$(O), $(BLD)/w32reg.$(O))
+ ($(BLD)/w32xfns.$(O)): Update dependencies.
+
+2012-09-23 Eli Zaretskii <eliz@gnu.org>
+
+ * .gdbinit: Set breakpoint on terminate_due_to_signal, not on
+ fatal_error_backtrace.
+
+ * w32proc.c (sys_kill): Undo last change: don't do anything when
+ invoked to deliver SIGABRT to our own process. This is now
+ handled by emacs_raise.
+
+2012-09-23 Juanma Barranquero <lekktu@gmail.com>
+
+ * w32term.c (w32_read_socket): Remove leftover reference to
+ interrupt_input_pending.
+
+2012-09-23 Paul Eggert <eggert@cs.ucla.edu>
+
+ Do not use SA_NODEFER.
+ Problem reported by Dani Moncayo in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00557.html>.
+ * alloc.c (die):
+ * sysdep.c (emacs_abort): Do not reset signal handler.
+ * emacs.c (terminate_due_to_signal): Reset signal handler here.
+ * sysdep.c (init_signals): Do not use SA_NODEFER. It wasn't
+ wanted even on POSIXish hosts, and it doesn't work on Windows.
+
+2012-09-23 Jan Djärv <jan.h.d@swipnet.se>
+
+ * xterm.c (x_term_init): Call fixup_locale before and after calling
+ gtk_init (Bug#12392).
+
+2012-09-23 Chong Yidong <cyd@gnu.org>
+
+ * w32.c (w32_delayed_load): Remove LIBRARIES argument; always use
+ Vdynamic_library_alist.
+
+ * gnutls.c (init_gnutls_functions): Caller changed; remove arg.
+ (Fgnutls_available_p): Caller changed.
+
+ * xml.c (init_libxml2_functions, Flibxml_parse_html_region)
+ (Flibxml_parse_xml_region): Likewise.
+
+ * dispextern.h (struct image_type): Remove arg from init function.
+
+ * image.c (Finit_image_library, lookup_image_type)
+ (define_image_type): Remove now-unneeded second arg.
+ (init_xpm_functions, init_png_functions, init_jpeg_functions)
+ (init_tiff_functions, init_gif_functions, init_svg_functions):
+ Arglist and w32_delayed_load calling convention changed.
+ (gs_type): Remove init_gs_functions; there is no such function.
+ (valid_image_p, make_image): Fix caller to lookup_image_type.
+
+2012-09-23 Paul Eggert <eggert@cs.ucla.edu>
+
+ Simplify and avoid signal-handling races (Bug#12471).
+ * alloc.c (die):
+ * sysdep.c (emacs_abort) [HAVE_NTGUI]:
+ Avoid recursive loop if there's a fatal error in the function itself.
+ * atimer.c (pending_atimers):
+ * blockinput.h: Don't include "atimer.h"; no longer needed.
+ (interrupt_input_pending): Remove. All uses removed.
+ pending_signals now counts both atimers and ordinary interrupts.
+ This is less racy than having three separate pending-signal flags.
+ (block_input, unblock_input, totally_unblock_input, unblock_input_to)
+ (input_blocked_p):
+ Rename from their upper-case counterparts BLOCK_INPUT,
+ UNBLOCK_INPUT, TOTALLY_UNBLOCK_INPUT, UNBLOCK_INPUT_TO,
+ INPUT_BLOCKED_P, and turn into functions. All uses changed.
+ This makes it easier to access volatile variables more accurately.
+ (BLOCK_INPUT_RESIGNAL): Remove. All uses replaced by unblock_input ().
+ (input_blocked_p): Prefer this to 'interrupt_input_blocked', as
+ that's more reliable if the code is buggy and sets
+ interrupt_input_blocked to a negative value. All uses changed.
+ * atimer.c (deliver_alarm_signal):
+ Remove. No need to deliver this to the parent; any thread can
+ handle this signal now. All uses replaced by underlying handler.
+ * atimer.c (turn_on_atimers):
+ * dispnew.c (handle_window_change_signal):
+ * emacs.c (handle_danger_signal):
+ * keyboard.c (kbd_buffer_get_event):
+ Don't reestablish signal handler; not needed with sigaction.
+ * blockinput.h (UNBLOCK_INPUT_TO, TOTALLY_UNBLOCK_INPUT)
+ (UNBLOCK_INPUT_TO):
+ Rework to avoid unnecessary accesses to volatile variables.
+ (UNBLOCK_INPUT_TO): Now a function.
+ (totally_unblock_input, unblock_input): New decls.
+ * data.c (handle_arith_signal, deliver_arith_signal): Move to sysdep.c
+ (init_data): Remove. Necessary stuff now done in init_signal.
+ * emacs.c, xdisp.c: Include "atimer.h", since we invoke atimer functions.
+ * emacs.c (handle_fatal_signal, deliver_fatal_signal): Move to sysdep.c.
+ (fatal_error_code): Remove; no longer needed.
+ (terminate_due_to_signal): Rename from fatal_error_backtrace, since
+ it doesn't always backtrace. All uses changed. No need to reset
+ signal to default, since sigaction and/or die does that for us now.
+ Use emacs_raise (FOO), not kill (getpid (), FOO).
+ (main): Check more-accurately whether we're dumping.
+ Move fatal-error setup to sysdep.c
+ * floatfns.c: Do not include "syssignal.h"; no longer needed.
+ * gtkutil.c (xg_get_file_name, xg_get_font):
+ Remove no-longer-needed signal-mask manipulation.
+ * keyboard.c, process.c (POLL_FOR_INPUT):
+ Don't depend on USE_ASYNC_EVENTS, a symbol that is never defined.
+ * keyboard.c (read_avail_input): Remove.
+ All uses replaced by gobble_input.
+ (Ftop_level): Use TOTALLY_UNBLOCK_INPUT rather than open code.
+ (kbd_buffer_store_event_hold, gobble_input):
+ (record_asynch_buffer_change) [USABLE_SIGIO]:
+ (store_user_signal_events):
+ No need to mess with signal mask.
+ (gobble_input): If blocking input and there are terminals, simply
+ set pending_signals to 1 and return. All hooks changed to not
+ worry about whether input is blocked.
+ (process_pending_signals): Clear pending_signals before processing
+ them, in case a signal comes in while we're processing.
+ By convention callers now test pending_signals before calling us.
+ (UNBLOCK_INPUT_TO, unblock_input, totally_unblock_input):
+ New functions, to support changes to blockinput.h.
+ (handle_input_available_signal): Now extern.
+ (reinvoke_input_signal): Remove. All uses replaced by
+ handle_async_input.
+ (quit_count): Now volatile, since a signal handler uses it.
+ (handle_interrupt): Now takes bool IN_SIGNAL_HANDLER as arg.
+ All callers changed. Block SIGINT only if not already blocked.
+ Clear sigmask reliably, even if Fsignal returns, which it can.
+ Omit unnecessary accesses to volatile var.
+ (quit_throw_to_read_char): No need to restore sigmask.
+ * keyboard.c (gobble_input, handle_user_signal):
+ * process.c (wait_reading_process_output):
+ Call signal-handling code rather than killing ourselves.
+ * lisp.h: Include <float.h>, for...
+ (IEEE_FLOATING_POINT): New macro, moved here to avoid duplication.
+ (pending_signals): Now volatile.
+ (syms_of_data): Now const if IEEE floating point.
+ (handle_input_available_signal) [USABLE_SIGIO]:
+ (terminate_due_to_signal, record_child_status_change): New decls.
+ * process.c (create_process): Avoid disaster if memory is exhausted
+ while we're processing a vfork, by tightening the critical section
+ around the vfork.
+ (send_process_frame, process_sent_to, handle_pipe_signal)
+ (deliver_pipe_signal): Remove. No longer needed, as Emacs now
+ ignores SIGPIPE.
+ (send_process): No need for setjmp/longjmp any more, since the
+ SIGPIPE stuff is now gone. Instead, report an error if errno
+ is EPIPE.
+ (record_child_status_change): Now extern. PID and W are now args.
+ Return void, not bool. All callers changed.
+ * sysdep.c (wait_debugging) [(BSD_SYSTEM || HPUX) && !defined (__GNU__)]:
+ Remove. All uses removed. This bug should be fixed now in a
+ different way.
+ (wait_for_termination_1): Use waitpid rather than sigsuspend,
+ and record the child status change directly. This avoids the
+ need to futz with the signal mask.
+ (process_fatal_action): Move here from emacs.c.
+ (emacs_sigaction_flags): New function, containing
+ much of what used to be in emacs_sigaction_init.
+ (emacs_sigaction_init): Use it. Block nonfatal system signals that are
+ caught by emacs, to make races less likely.
+ (deliver_process_signal): Rename from handle_on_main_thread.
+ All uses changed.
+ (BACKTRACE_LIMIT_MAX): Now at top level.
+ (thread_backtrace_buffer, threadback_backtrace_pointers):
+ New static vars.
+ (deliver_thread_signal, deliver_fatal_thread_signal):
+ New functions, for more-accurate delivery of thread-specific signals.
+ (handle_fatal_signal, deliver_fatal_signal): Move here from emacs.c.
+ (deliver_arith_signal): Handle in this thread, not
+ in the main thread, since it's triggered by this thread.
+ (maybe_fatal_sig): New function.
+ (init_signals): New arg DUMPING so that we can be more accurate
+ about whether we're dumping. Caller changed.
+ Treat thread-specific signals differently from process-general signals.
+ Block all signals while handling fatal error; that's safer.
+ xsignal from SIGFPE only on non-IEEE hosts, treating it as fatal
+ on IEEE hosts.
+ When batch, ignore SIGHUP, SIGINT, SIGTERM if they were already ignored.
+ Ignore SIGPIPE unless batch.
+ (emacs_backtrace): Output backtrace for the appropriate thread,
+ which is not necessarily the main thread.
+ * syssignal.h: Include <stdbool.h>.
+ (emacs_raise): New macro.
+ * xterm.c (x_connection_signal): Remove; no longer needed
+ now that we use sigaction.
+ (x_connection_closed): No need to mess with sigmask now.
+ (x_initialize): No need to reset SIGPIPE handler here, since
+ init_signals does this for us now.
+
+2012-09-23 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_dumpglyphs_image): dr is a new rect to draw image into,
+ background rect may be larger (Bug#12245).
+
+2012-09-23 Chong Yidong <cyd@gnu.org>
+
+ * keyboard.c (timer_check): Avoid quitting during Fcopy_sequence.
+
+2012-09-22 Paul Eggert <eggert@cs.ucla.edu>
+
+ * .gdbinit: Just stop at fatal_error_backtrace.
+ See Stefan Monnier's request in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00549.html>.
+ Remove no-longer-used query of system type.
+
+2012-09-22 Chong Yidong <cyd@gnu.org>
+
+ * search.c (Freplace_match): Doc fix (Bug#12325).
+
+ * minibuf.c (Finternal_complete_buffer): Doc fix (Bug#12391).
+
+ * editfns.c (Fline_beginning_position): Doc fix (Bug#12416).
+ (Fline_end_position): Doc fix.
+
+ * cmds.c (Fforward_char, Fbackward_char): Doc fix (Bug#12414).
+
+2012-09-22 Chong Yidong <cyd@gnu.org>
+
+ * dispextern.h (struct image_type): Add new slot, storing a type
+ initialization function.
+
+ * image.c (define_image_type): Call the image initializer function
+ if it is defined. Arguments and return value changed.
+ (valid_image_p, make_image): Callers changed.
+ (xbm_type, xpm_type, pbm_type, png_type, jpeg_type, tiff_type)
+ (gif_type, imagemagick_type, svg_type, gs_type):
+ Add initialization functions.
+ (Finit_image_library): Call lookup_image_type.
+ (CHECK_LIB_AVAILABLE): Macro deleted.
+ (lookup_image_type): Call define_image_type here, rather than via
+ Finit_image_library, and without using CHECK_LIB_AVAILABLE.
+ (syms_of_image): Move define_image_type calls for xbm_type and
+ pbm_type to lookup_image_type.
+
+2012-09-22 Eli Zaretskii <eliz@gnu.org>
+
+ * keyboard.c (timer_check_2): Move calculation of 'timers' and
+ 'idle_timers' from here ...
+ (timer_check): ... to here. Use Fcopy_sequence to copy the timer
+ lists, to avoid infloops when the timer does something stupid,
+ like reinvoke itself with the same or smaller time-out.
+ (Bug#12447)
+
+2012-09-22 Martin Rudalics <rudalics@gmx.at>
+
+ * window.c (Fsplit_window_internal): Handle only Qt value of
+ Vwindow_combination_limit separately.
+ (Qtemp_buffer_resize): New symbol.
+ (Vwindow_combination_limit): New default value.
+ Rewrite doc-string.
+
+2012-09-22 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (next_overlay_string): Initialize it->end_charpos for
+ the new overlay string. (Bug#10159)
+
+2012-09-22 Paul Eggert <eggert@cs.ucla.edu>
+
+ * emacs.c (shut_down_emacs): Don't assume stderr is buffered,
+ or that fprintf is async-signal-safe. POSIX doesn't require
+ either assumption.
+
+2012-09-22 Chong Yidong <cyd@gnu.org>
+
+ * buffer.c (Fset_buffer_modified_p): Handle indirect buffers
+ (Bug#8207).
+
+2012-09-22 Kenichi Handa <handa@gnu.org>
+
+ * composite.c (composition_reseat_it): Handle the case that a
+ grapheme cluster is not covered by a single font (Bug#12352).
+
+2012-09-21 Chong Yidong <cyd@gnu.org>
+
+ * image.c (define_image_type): Avoid adding duplicate types to
+ image_types (Bug#12463). Suggested by Jörg Walter.
+
+2012-09-21 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
+
+ * unexmacosx.c: Define LC_DATA_IN_CODE if not defined.
+ (print_load_command_name): Add case LC_DATA_IN_CODE.
+ (dump_it) [LC_DATA_IN_CODE]: Call copy_linkedit_data.
+
+2012-09-21 Glenn Morris <rgm@gnu.org>
+
+ * eval.c (Frun_hook_with_args_until_success)
+ (Frun_hook_with_args_until_failure): Doc fixes. (Bug#12393)
+
+2012-09-21 Andreas Schwab <schwab@linux-m68k.org>
+
+ * fileio.c (Ffile_selinux_context): Only call freecon when
+ lgetfilecon succeeded.
+ (Fset_file_selinux_context): Likewise. (Bug#12444)
+
+2012-09-21 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (try_window_reusing_current_matrix): Under bidi
+ reordering, locate the cursor by calling set_cursor_from_row; if
+ that fails, clear the desired glyph matrix before returning a
+ failure indication to the caller. Fixes leaving garbled display
+ when fast scrolling with a down-key. (Bug#12403)
+ (compute_stop_pos_backwards): Fix a typo that caused crashes while
+ scrolling through multibyte text.
+
+2012-09-20 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * alloc.c (mark_object) <PVEC_WINDOW>: Mark prev/next_buffers *after*
+ calling mark_vectorlike since that's the one that marks the window.
+ (mark_discard_killed_buffers): Mark the final cdr.
+ * window.h (struct window): Move prev/next_buffers to the
+ non-standard fields.
+ * window.c (make_window): Initialize prev/next_buffers manually.
+
+2012-09-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ Omit unused arg EXPECTED from socket hooks.
+ * keyboard.c (gobble_input, read_avail_input, tty_read_avail_input):
+ * nsterm.m (ns_term_init):
+ * termhooks.h (struct terminal.read_socket_hook):
+ * w32inevt.c (w32_console_read_socket):
+ * w32term.c (w32_read_socket):
+ * xterm.c (XTread_socket):
+ Omit unused arg EXPECTED. All callers changed.
+ (store_user_signal_events): Return void, not int, since callers no
+ longer care about the return value. All uses changed.
+
+2012-09-20 Juanma Barranquero <lekktu@gmail.com>
+
+ * w32gui.h (XParseGeometry): Do not declare.
+
+2012-09-19 Paul Eggert <eggert@cs.ucla.edu>
+
+ * w32inevt.c (w32_console_read_socket): Return -1 on failure, not 0.
+ Ignore 'expected'. See Eli Zaretskii in
+ <http://bugs.gnu.org/12471#8> (last line).
+
+ * frame.c (read_integer): Remove. All uses replaced by strtol/strtoul.
+ (XParseGeometry): Now static. Substitute extremal values for
+ values that are out of range.
+
+2012-09-19 Jan Djärv <jan.h.d@swipnet.se>
+
+ * w32xfns.c (read_integer, XParseGeometry): Move to frame.c.
+
+ * nsfns.m (XParseGeometry): Remove.
+ (Fx_create_frame): Call x_set_offset to correctly interpret
+ top_pos in geometry.
+
+ * frame.c (read_integer, XParseGeometry): Move from w32xfns.c.
+ (Fx_parse_geometry): If there is a space in string, call
+ Qns_parse_geometry, otherwise do as on other terms (Bug#12368).
+
+2012-09-17 Eli Zaretskii <eliz@gnu.org>
+
+ * search.c (scan_buffer): Use character positions in calls to
+ region_cache_forward and region_cache_backward, not byte
+ positions. (Bug#12196)
+
+ * w32term.c (w32_read_socket): Set pending_signals to 1, like
+ xterm.c does. Reported by Daniel Colascione <dancol@dancol.org>.
+
+ * ralloc.c (r_alloc_init) [!SYSTEM_MALLOC]: Initialize
+ __malloc_extra_blocks to 32 instead of 64, like alloc.c did in
+ emacs_blocked_malloc, now deleted.
+
+2012-09-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ Remove no-longer-needed Solaris 2.4 vfork bug workaround.
+ The workaround was for improving performance on Solaris 2.4, but
+ is getting in the way now. Emacs will still work if someone is
+ still running Solaris 2.4 in a museum somewhere; Sun dropped
+ support for Solaris 2.4 in 2003.
+ * callproc.c (Fcall_process) [HAVE_WORKING_VFORK]:
+ * process.c (create_process) [HAVE_WORKING_VFORK]:
+ Omit now-unnecessary workaround for the Solaris 2.4 vfork bug,
+ since Emacs no longer uses vfork on that platform.
+
+2012-09-17 Glenn Morris <rgm@gnu.org>
+
+ * emacs.c: Use COPYRIGHT.
+
+2012-09-16 Paul Eggert <eggert@cs.ucla.edu>
+
+ Remove configure's --without-sync-input option (Bug#12450).
+ When auditing signal-handling in preparation for cleaning it up,
+ I found that SYNC_INPUT has race conditions and would be a real
+ pain to fix. Since it's an undocumented and deprecated
+ configure-time option, now seems like a good time to remove it.
+ Also see <http://bugs.gnu.org/11080#16>.
+ * alloc.c (_bytes_used, __malloc_extra_blocks, _malloc_internal)
+ (_free_internal) [!DOUG_LEA_MALLOC]: Remove decls.
+ (alloc_mutex) [!SYSTEM_MALLOC && !SYNC_INPUT && HAVE_PTHREAD]:
+ (malloc_hysteresis):
+ (check_depth) [XMALLOC_OVERRUN_CHECK]:
+ (MALLOC_BLOCK_INPUT, MALLOC_UNBLOCK_INPUT):
+ (__malloc_hook, __realloc_hook, __free_hook, BYTES_USED)
+ (dont_register_blocks, bytes_used_when_reconsidered)
+ (bytes_used_when_full, emacs_blocked_free, emacs_blocked_malloc)
+ (emacs_blocked_realloc, reset_malloc_hooks, uninterrupt_malloc):
+ [!SYSTEM_MALLOC && !SYNC_INPUT]:
+ Remove. All uses removed.
+ (MALLOC_BLOCK_INPUT, MALLOC_UNBLOCK_INPUT): Use a different
+ implementation, one that depends on whether the new macro
+ XMALLOC_BLOCK_INPUT_CHECK is defined, not on whether SYNC_INPUT
+ is defined.
+ * atimer.c (run_timers, handle_alarm_signal):
+ * keyboard.c (pending_signal, poll_for_input_1, poll_for_input)
+ (handle_async_input, process_pending_signals)
+ (handle_input_available_signal, init_keyboard):
+ * nsterm.m (ns_read_socket):
+ * process.c (wait_reading_process_output):
+ * regex.c (immediate_quit, IMMEDIATE_QUIT_CHECK):
+ * sysdep.c (emacs_sigaction_init) [SA_RESTART]:
+ (emacs_write):
+ * xterm.c (XTread_socket):
+ Assume SYNC_INPUT.
+ * conf_post.h (SA_RESTART) [IRIX6_5]: Do not #undef.
+ * eval.c (handling_signal): Remove. All uses removed.
+ * lisp.h (ELSE_PENDING_SIGNALS): Remove.
+ All uses replaced with the SYNC_INPUT version.
+ (reset_malloc_hooks, uninterrupt_malloc, handling_signal):
+ Remove decls.
+ * sysdep.c, syssignal.h (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
+ Now static.
+
+ * font.c (Ffont_shape_gstring): Remove unused local.
+
+2012-09-16 Glenn Morris <rgm@gnu.org>
+
+ * Makefile.in (clean): No longer run nextstep's clean.
+
+ * Makefile.in (ns_appdir, ns_appbindir, ns_appsrc): Remove variables.
+ (ns_frag): Remove.
+ (ns-app): Move here from ns.mk, and simplify.
+ (clean): Simplify nextstep entry.
+ * ns.mk: Remove file.
+
+2012-09-17 Kenichi Handa <handa@gnu.org>
+
+ * font.c (Ffont_shape_gstring): Fix previous change; GLYPHs may
+ not covert the last few charactes.
+
+2012-09-16 Kenichi Handa <handa@gnu.org>
+
+ * font.c (Ffont_shape_gstring): Don't adjust grapheme cluster
+ here, but just check the validity of glyphs in the glyph-string.
+
+2012-09-16 Martin Rudalics <rudalics@gmx.at>
+
+ * window.c (Fwindow_parameter, Fset_window_parameter):
+ Accept any window as argument (Bug#12452).
+
+2012-09-16 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsfns.m (Fx_open_connection): Move initialization of ns_*_types
+ to ns_term_init to avoid memory leak.
+
+ * nsterm.m (ns_update_begin): Initialize bp after lcokFocus, use
+ explicit retain/release.
+ (ns_term_init): Only allow one display. Initialize outerpool and
+ ns_*_types.
+
+2012-09-15 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port _setjmp fix to POSIXish hosts as well as Microsoft.
+ * image.c (_setjmp) [!HAVE__SETJMP]: Restore definition, as
+ it's needed on POSIXish hosts that lack _setjmp. Attempt to solve
+ the Microsoft problem in a different way, by altering ../nt/config.nt.
+
+2012-09-15 Eli Zaretskii <eliz@gnu.org>
+
+ * w32xfns.c:
+ * w32uniscribe.c:
+ * w32term.c:
+ * w32select.c:
+ * w32reg.c:
+ * w32proc.c:
+ * w32menu.c:
+ * w32inevt.c:
+ * w32heap.c:
+ * w32font.c:
+ * w32fns.c:
+ * w32console.c:
+ * w32.c:
+ * w16select.c: Remove inclusion of setjmp.h, as it is now included
+ by lisp.h. This completes removal of setjmp.h inclusion
+ erroneously announced in the previous commit. (Bug#12446)
+
+ * lisp.h [!HAVE__SETJMP, !HAVE_SIGSETJMP]: Make the commentary
+ more accurate.
+
+ * image.c (_setjmp) [!HAVE__SETJMP]: Define only if 'setjmp' is
+ not defined as a macro. The latter happens on MS-Windows.
+ (Bug#12446)
+
+2012-09-15 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port better to POSIX hosts lacking _setjmp (Bug#12446).
+ * lisp.h: Include <setjmp.h> here, since we use its symbols here.
+ Some instances of '#include <setjmp.h>' removed, if the
+ only reason for the instance was because "lisp.h" was included.
+ (sys_jmp_buf, sys_setjmp, sys_longjmp): New symbols.
+ Unless otherwise specified, replace all uses of jmp_buf, _setjmp,
+ and _longjmp with the new symbols. Emacs already uses _setjmp if
+ available, so this change affects only POSIXish hosts that have
+ sigsetjmp but not _setjmp, such as some versions of Solaris and
+ Unixware. (Also, POSIX-2008 marks _setjmp as obsolescent.)
+ * image.c (_setjmp, _longjmp) [HAVE_PNG && !HAVE__SETJMP]: New macros.
+ (png_load_body) [HAVE_PNG]:
+ (PNG_LONGJMP) [HAVE_PNG && PNG_LIBPNG_VER < 10500]:
+ (PNG_JMPBUF) [HAVE_PNG && PNG_LIBPNG_VER >= 10500]:
+ Use _setjmp and _longjmp rather than sys_setjmp and sys_longjmp,
+ since PNG requires jmp_buf. This is the only exception to the
+ general rule that we now use sys_setjmp and sys_longjmp.
+ This exception is OK since this code does not change the signal
+ mask or longjmp out of a signal handler.
+
+2012-09-14 Paul Eggert <eggert@cs.ucla.edu>
+
+ * alloc.c [!SYSTEM_MALLOC && !SYNC_INPUT && HAVE_PTHREAD]:
+ Include "syssignal.h", for 'main_thread'.
+
+2012-09-14 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Avoid out-of-range marker position (Bug#12426).
+ * insdel.c (replace_range, replace_range_2):
+ Adjust markers before overlays, as suggested by comments.
+ (insert_1_both, insert_from_buffer_1, adjust_after_replace):
+ Remove redundant check before calling offset_intervals.
+
+2012-09-14 Martin Rudalics <rudalics@gmx.at>
+
+ * xdisp.c (Fformat_mode_line): Unconditionally save/restore
+ current buffer (Bug#12387).
+
+2012-09-14 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/alloc.$(O)): Update dependencies.
+
+2012-09-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use a more backwards-compatible timer format (Bug#12430).
+ * keyboard.c (decode_timer): Get PSECS from the 8th (origin-0)
+ vector element, not from the 4th, since PSECS is now at the end.
+ (Fcurrent_idle_time): Doc fix.
+
+2012-09-13 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Function to mark objects and remove killed buffers at once.
+ * alloc.c (discard_killed_buffers): Rename to ...
+ (mark_discard_killed buffers) ... new name. Add marking
+ of remaining objects. Fix comment. Adjust users.
+ (mark_object): Do not touch frame buffer lists here.
+ * frame.c (delete_frame): Reset frame buffer lists here.
+
+2012-09-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ Better workaround for GNOME bug when --enable-gcc-warnings.
+ * emacsgtkfixed.c (G_STATIC_ASSERT): Remove, undoing last change.
+ Instead, disable -Wunused-local-typedefs. See Dmitry Antipov in
+ <http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00335.html>.
+
+ Simplify SIGIO usage (Bug#12408).
+ The code that dealt with SIGIO was crufty and confusing, e.g., it
+ played tricks like "#undef SIGIO" but these tricks were not used
+ consistently. Simplify mostly by not #undeffing standard symbols,
+ e.g., use "defined USABLE_SIGIO" (our symbol, which we can define
+ or not as we please) rather than "defined SIGIO" (standard symbol
+ that we probably shouldn't #undef).
+ * conf_post.h [USG5_4]: Do not include <sys/wait.h> here.
+ Modules that need it can include it.
+ [USG5_4 && emacs]: Likewise, do not include the streams stuff here.
+ * dispextern.h (ignore_sigio): New decl.
+ * emacs.c (shut_down_emacs): Invoke unrequest_sigio
+ unconditionally, since it's now a no-op if !USABLE_SIGIO.
+ * emacs.c (shut_down_emacs):
+ * keyboard.c (kbd_buffer_store_event_hold):
+ Use ignore_sigio rather than invoking 'signal' directly.
+ * keyboard.c (USABLE_FIONREAD && USG5_4): Include <sys/filio.h>,
+ for FIONREAD.
+ (FIONREAD, SIGIO): Do not #undef.
+ (tty_read_avail_input): Use #error rather than a syntax error.
+ * process.c [USG5_4]: Include <sys/stream.h> and <sys/stropts.h>,
+ for I_PIPE, used by SETUP_SLAVE_PTY.
+ (DATAGRAM_SOCKETS): Simplify defn, based on USABLE_FIONREAD.
+ * sysdep.c (croak): Remove; no longer needed. This bit of
+ temporary code, with Fred N. Fish's comment that it's temporary,
+ has been in Emacs since at least 1992!
+ (init_sigio, reset_sigio, request_sigio, unrequest_sigio):
+ Arrange for them to be no-ops in all cases when ! USABLE_SIGIO.
+ * syssignal.h (croak): Remove decl.
+ (SIGIO, SIGPOO, SIGAIO, SIGPTY): Do not #undef; that's too fragile.
+ * systty.h [!NO_TERMIO]: Do not include <termio.h>; no longer needed
+ now that we're termios-only.
+ (FIONREAD, ASYNC) [BROKEN_FIONREAD]: Do not #undef.
+ * term.c (dissociate_if_controlling_tty): Use #error rather than
+ a run-time error.
+
+ Work around GCC and GNOME bugs when --enable-gcc-warnings.
+ * emacsgtkfixed.c (G_STATIC_ASSERT): Redefine to use 'verify',
+ to work around GNOME bug 683906.
+ * image.c (jpeg_load_body) [HAVE_JPEG && lint]: Pacify gcc -Wclobber.
+ (struct my_jpeg_error_mgr) [HAVE_JPEG && lint]: New member fp.
+ This works around GCC bug 54561.
+
+2012-09-12 Paul Eggert <eggert@cs.ucla.edu>
+
+ More fixes for 'volatile' and setjmp/longjmp.
+ * eval.c (Fdefvar, Fcondition_case): Remove unnecessary 'volatile's.
+ * image.c (struct png_load_context) [HAVE_PNG]: New type.
+ (png_load_body) [HAVE_PNG]:
+ (jpeg_load_body) [HAVE_JPEG]:
+ New function, with most of the old parent function's body.
+ (png_load) [HAVE_PNG]:
+ (jpeg_load) [HAVE_JPEG]:
+ Invoke the new function, to avoid longjmp munging our locals.
+ (struct my_jpeg_error_mgr) [HAVE_JPEG]: New members cinfo, failure_code.
+ (my_error_exit) [HAVE_JPEG]: Don't trust 'setjmp' to return 2 when
+ longjmp is passed 2, as the C standard doesn't guarantee this.
+ Instead, store the failure code into mgr->failure_code.
+
+2012-09-12 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * keyboard.c (read_char, requeued_events_pending_p, Finput_pending_p)
+ (Fdiscard_input, quit_throw_to_read_char, init_keyboard)
+ (syms_of_keyboard): Remove support for unread-command-char.
+
+2012-09-12 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (sys_kill): If PID is our process ID and the signal is
+ SIGABRT, call emacs_abort. Avoids silently exiting upon assertion
+ violation. (Bug#12426)
+
+2012-09-12 Paul Eggert <eggert@cs.ucla.edu>
+
+ * image.c (jpeg_memory_src): Don't assume string len fits in unsigned.
+
+2012-09-12 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * eval.c: Add `inhibit-debugger'.
+ (Qinhibit_debugger): New symbol.
+ (call_debugger): Bind it instead of Qdebug_on_error.
+ (maybe_call_debugger): Test Vinhibit_debugger.
+ (syms_of_eval): Define inhibit-debugger.
+ * xdisp.c (set_message): Don't bind Qinhibit_debug_on_message.
+ (syms_of_xdisp): Remove inhibit-debug-on-message.
+
+2012-09-11 Paul Eggert <eggert@cs.ucla.edu>
+
+ Avoid _setjmp/_longjmp problems with local nonvolatile variables.
+ If a nonvolatile local variable is written before a _longjmp to
+ the frame containing the variable, and is read after the _longjmp,
+ the value read is indeterminate. Some local variables of type
+ 'struct handler' and 'struct catchtag' are used in this way, so
+ mark each of their slots as volatile if the slot can be set before
+ _longjmp and read afterwards.
+ * lisp.h (struct handler): var and chosen_clause are now volatile.
+ (struct catchtag): val, next, and pdlcount are now volatile.
+
+ * bidi.c (bidi_push_it, bidi_pop_it):
+ * fns.c (copy_hash_table):
+ * image.c (define_image_type):
+ * keyboard.c (kbd_buffer_store_event_hold):
+ * process.c (Fprocess_send_eof):
+ * xfaces.c (x_create_gc) [HAVE_NS]:
+ * xgselect.c (xg_select):
+ Prefer assignment to memcpy when either will do.
+
+ * alloc.c (discard_killed_buffers): Tune and simplify a bit.
+ Use pointer-to-a-pointer to simplify and avoid a NILP check each
+ time an item is removed. No need to mark this function 'inline';
+ the compiler knows better than we do.
+
+2012-09-11 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_judge_scroll_bars): Pass NO to updateFrameSize.
+ (updateFrameSize:): Add delay parameter to updateFrameSize, send it
+ to change_frame_size (Bug#12388).
+ (windowDidResize:): Pass YES to updateFrameSize.
+
+ * nsterm.h: Add delay parameter to updateFrameSize.
+
+2012-09-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Discard killed buffers from deleted window and frame objects.
+ This reduces an amount of references to killed buffers and
+ helps GC to reclaim them faster.
+ * alloc.c (discard_killed_buffers): New function.
+ (mark_object): Use it for deleted windows and frames.
+ (mark_object): If symbol's value is set up for a killed buffer
+ or deleted frame, restore its global binding.
+ * data.c (swap_in_global_binding): Add GC notice.
+ (swap_in_symval_forwarding): Use convenient set_blv_where.
+ * window.c (wset_next_buffers, wset_prev_buffers): Move ...
+ * window.h: ... to here.
+
+2012-09-11 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Convenient macro to check whether the buffer is live.
+ * buffer.h (BUFFER_LIVE_P): New macro.
+ * alloc.c, buffer.c, editfns.c, insdel.c, lread.c, marker.c:
+ * minibuf.c, print.c, process.c, window.c, xdisp.c: Use it.
+
+2012-09-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
+
+ * xdisp.c (right_overwritten, right_overwriting): Also handle gstring
+ composition cases (Bug#12364).
+
+ * xterm.c (x_draw_glyph_string): Avoid overwriting inverted left
+ overhang of succeeding glyphs overlapping box cursor.
+
+ * w32term.c (x_draw_glyph_string): Likewise.
+
+2012-09-11 Paul Eggert <eggert@cs.ucla.edu>
+
+ Simplify, document, and port floating-point (Bug#12381).
+ The porting part of this patch fixes bugs on non-IEEE platforms
+ with frexp, ldexp, logb.
+ * data.c, lisp.h (Qdomain_error, Qsingularity_error, Qunderflow_error):
+ Now static.
+ * floatfns.c: Simplify discussion of functions that Emacs doesn't
+ support, by removing commented-out code and briefly listing the
+ C89 functions excluded. The commented-out stuff was confusing
+ maintenance, e.g., we thought we needed cbrt but it was commented out.
+ (logb): Remove decl; no longer needed.
+ (isfinite): New macro, if not already supplied.
+ (isnan): Don't replace any existing macro.
+ (Ffrexp, Fldexp): Define even if !HAVE_COPYSIGN, as frexp and ldexp
+ are present on all C89 platforms.
+ (Ffrexp): Do not special-case zero, as frexp does the right thing
+ for that case.
+ (Flogb): Do not use logb, as it doesn't have the desired meaning
+ on hosts that use non-base-2 floating point. Instead, stick with
+ frexp, which is C89 anyway. Do not pass an infinity or a NaN to
+ frexp, to avoid getting an unspecified result.
+
+ * xdisp.c (Qinhibit_debug_on_message): Now static.
+
+2012-09-10 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_update_begin): Set clip path to whole view by using
+ NSBezierPath (Bug#12131).
+
+2012-09-10 Chong Yidong <cyd@gnu.org>
+
+ * fns.c (Fdelq, Fdelete): Doc fix.
+
+2012-09-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ * lisp.h (XSETINT, XSETCONS, XSETVECTOR, XSETSTRING, XSETSYMBOL)
+ (XSETFLOAT, XSETMISC): Parenthesize macro bodies.
+
+2012-09-09 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp.h (make_lisp_ptr): New macro to replace XSET.
+ (XSETCONS, XSETVECTOR, XSETSTRING, XSETSYMBOL, XSETFLOAT, XSETMISC):
+ Use it.
+
+2012-09-09 Eli Zaretskii <eliz@gnu.org>
+
+ * fringe.c (draw_fringe_bitmap_1): Don't reduce the width of the
+ left fringe if the window has a left margin. This avoids leaving
+ traces of the cursor because its leftmost pixel is not drawn over.
+
+ * dispnew.c (update_window_line): When the left margin area of a
+ screen line is updated, set the redraw_fringe_bitmaps_p flag of
+ that screen line. (Bug#12277)
+
+2012-09-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ Assume C89 or later for math functions (Bug#12381).
+ This simplifies the code, and makes it a bit smaller and faster,
+ and (most important) makes it easier to clean up signal handling
+ since we can stop worring about floating-point exceptions in
+ library code. That was a problem before C89, but the problem
+ went away many years ago on all practical Emacs targets.
+ * data.c, image.c, lread.c, print.c:
+ Don't include <math.h>; no longer needed.
+ * data.c, floatfns.c (IEEE_FLOATING_POINT): Don't worry that it
+ might be autoconfigured, as that never happens.
+ * data.c (fmod):
+ * doprnt.c (DBL_MAX_10_EXP):
+ * print.c (DBL_DIG):
+ Remove. C89 or later always defines these.
+ * floatfns.c (HAVE_MATHERR, FLOAT_CHECK_ERRNO, FLOAT_CHECK_DOMAIN)
+ (in_float, float_error_arg, float_error_arg2, float_error_fn_name)
+ (arith_error, domain_error, domain_error2):
+ Remove all this pre-C89 cruft. Do not include <errno.h> as that's
+ no longer needed -- we simply return what C returns. All uses removed.
+ (IN_FLOAT, IN_FLOAT2): Remove. All uses replaced with
+ the wrapped code.
+ (FLOAT_TO_INT, FLOAT_TO_INT2, range_error, range_error2):
+ Remove. All uses expanded, as these macros are no longer used
+ more than once and are now more trouble than they're worth.
+ (Ftan): Use tan, not sin / cos.
+ (Flogb): Assume C89 frexp.
+ (fmod_float): Assume C89 fmod.
+ (matherr) [HAVE_MATHERR]: Remove; no longer needed.
+ (init_floatfns): Remove. All uses removed.
+
+2012-09-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_draw_fringe_bitmap, ns_dumpglyphs_image): Take back
+ compositeToPoint for OSX < 10.6 (Bug#12390).
+
+2012-09-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ * floatfns.c (Ftan): Use tan (x), not (sin (x) / cos (x)).
+ This produces more-accurate results.
+
+2012-09-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (updateFrameSize): Call setFrame: on the view when size
+ changes (Bug#12088).
+
+2012-09-08 Chong Yidong <cyd@gnu.org>
+
+ * syntax.c (Fstring_to_syntax): Doc fix.
+
+2012-09-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_clip_to_row): Remove code that deals with drawing fringe
+ in the internal border.
+ (x_set_window_size): Remove static variables and their usage.
+ (ns_redraw_scroll_bars): Fix NSTRACE arg.
+ (ns_after_update_window_line, ns_draw_fringe_bitmap):
+ Remove fringe/internal border adjustment (Bug#11052).
+ (ns_draw_fringe_bitmap): Make code more like other terms (xterm.c).
+ (ns_draw_window_cursor): Remove fringe/internal border adjustment.
+ (ns_fix_rect_ibw): Remove.
+ (ns_get_glyph_string_clip_rect): Remove call to ns_fix_rect_ibw.
+ (ns_dumpglyphs_box_or_relief): Ditto.
+ (ns_maybe_dumpglyphs_background): Remove fringe/internal border
+ adjustment.
+ (ns_dumpglyphs_image): Ditto.
+ (ns_dumpglyphs_stretch): Fix coding style. Remove fringe/internal
+ border adjustment.
+ (ns_set_vertical_scroll_bar): Remove variables barOnVeryLeft/Right and
+ their usage. Add fringe_extended_p and its use as in other terms.
+ (ns_judge_scroll_bars): Code style fix. Call updateFrameSize if
+ scroll bar was removed.
+ (updateFrameSize): New function.
+ (windowDidResize): Move code to updateFrameSize and call it.
+
+ * nsterm.h (EmacsView): Add updateFrameSize.
+
+2012-09-07 Chong Yidong <cyd@gnu.org>
+
+ * textprop.c (Fget_text_property): Minor doc fix (Bug#12323).
+
+ * data.c (Flocal_variable_if_set_p): Doc fix (Bug#10713).
+
+2012-09-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ More signal-handler cleanup (Bug#12327).
+ * emacs.c (main): Convert three 'signal' calls to 'sigaction' calls.
+ Problem introduced when merging patches. Noted by Eli Zaretskii in
+ <http://bugs.gnu.org/12327#67>.
+ * floatfns.c: Comment fix.
+ * lisp.h (force_auto_save_soon): Declare regardless of SIGDANGER.
+ SIGDANGER might not be in scope so "#ifdef SIGDANGER" is not right,
+ and anyway the declaration is harmless even if SIGDANGER is not defined.
+ * syssignal.h (SIGIO): Also #undef if (! defined FIONREAD ||
+ defined BROKEN_FIONREAD). systty.h formerly did this, but other
+ source files not surprisingly expected syssignal.h to define, or
+ not define, SIGIO, and it's cleaner to do it that way, for consistency.
+ Include <sys/ioctl.h>, for FIONREAD.
+ * systty.h (SIGIO): Do not #undef here; it's now syssignal.h's job.
+ This eliminates a problem whereby other files mysteriously had
+ to include "syssignal.h" before including "systty.h" if they
+ wanted to use "#ifdef SIGIO".
+
+2012-09-07 Eli Zaretskii <eliz@gnu.org>
+
+ * w32proc.c (sigaction): New function, emulates Posix 'sigaction'.
+
+ * w32.c (sigemptyset): Empty the set.
+ (sigsetmask, sigmask, sigblock, sigunblock): Remove unused functions.
+
+ * alloc.c [ENABLE_CHECKING]: Include signal.h, since we need SIGABRT.
+
+2012-09-07 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (mark_buffer): Revert unsafe marking optimization.
+ (mark_object): Likewise for frame objects.
+
+2012-09-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ * syssignal.h (handle_on_main_thread): Always declare,
+ even if FORWARD_SIGNAL_TO_MAIN_THREAD is not defined.
+ This ports to platforms without HAVE_PTHREAD.
+
+2012-09-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ Signal-handler cleanup (Bug#12327).
+ Emacs's signal handlers were written in the old 4.2BSD style with
+ sigblock and sigmask and so forth, and this led to some
+ inefficiencies and confusion. Rewrite these to use
+ pthread_sigmask etc. without copying signal sets around. Also,
+ get rid of the confusing macros 'SIGNAL_THREAD_CHECK' and
+ 'signal', and instead use functions that do not attempt to take
+ over the system name space. This patch causes Emacs's text
+ segment to shrink by 0.7% on my platform, Fedora 17 x86-64.
+ * alloc.c, emacsgtkfixed.c, nsfns.m, widget.c, xmenu.c:
+ Do not include <signal.h> or "syssignal.h", as these
+ modules do not use signals.
+ * atimer.c, callproc.c, data.c, dispnew.c, emacs.c, floatfns.c:
+ * gtkutil.c, keyboard.c, process.c, sound.c, sysdep.c, term.c, xterm.c:
+ Do not include <signal.h>, as "syssignal.h" does that for us now.
+ * atimer.c (sigmask_atimers): New function.
+ (block_atimers, unblock_atimers): New functions,
+ replacing the old macros BLOCK_ATIMERS and UNBLOCK_ATIMERS.
+ All uses replaced.
+ * conf_post.h [SIGNAL_H_AHB]: Do not include <signal.h>;
+ no longer needed here.
+ * emacs.c (main): Inspect existing signal handler with sigaction,
+ so that there's no need to block and unblock SIGHUP.
+ * sysdep.c (struct save_signal): New member 'action', replacing
+ old member 'handler'.
+ (save_signal_handlers, restore_signal_handlers):
+ Use sigaction instead of 'signal' to save and restore.
+ (get_set_sighandler, set_sighandler) [!WINDOWSNT]:
+ New function. All users of 'signal' modified to use set_sighandler
+ if they're writeonly, and to use sys_signal if they're read+write.
+ (emacs_sigaction_init, forwarded_signal): New functions.
+ (sys_signal): Remove. All uses replaced by calls to sigaction
+ and emacs_sigaction_init, or by direct calls to 'signal'.
+ (sys_sigmask) [!__GNUC__]: Remove; no longer needed.
+ (sys_sigblock, sys_sigunblock, sys_sigsetmask): Remove;
+ all uses replaced by pthread_sigmask etc. calls.
+ * syssignal.h: Include <signal.h>.
+ (emacs_sigaction_init, forwarded_signal): New decls.
+ (SIGMASKTYPE): Remove. All uses replaced by its definiens, sigset_t.
+ (SIGEMPTYMASK): Remove; all uses replaced by its definiens, empty_mask.
+ (sigmask, sys_sigmask): Remove; no longer needed.
+ (sigpause): Remove. All uses replaced by its definiens, sigsuspend.
+ (sigblock, sigunblock, sigfree):
+ (sigsetmask) [!defined sigsetmask]:
+ Remove. All uses replaced by pthread_sigmask.
+ (signal): Remove. Its remaining uses (with SIG_DFL and SIG_IGN)
+ no longer need to be replaced, and its typical old uses
+ are now done via emacs_sigaction_init and sigaction.
+ (sys_sigblock, sys_sigunblock, sys_sigsetmask): Remove decls.
+ (sys_sigdel): Remove; unused.
+ (NSIG): Remove a FIXME; the code's fine. Remove an unnecessary ifdef.
+
+2012-09-06 Eli Zaretskii <eliz@gnu.org>
+
+ * process.c (CAN_HANDLE_MULTIPLE_CHILDREN): Fix a typo that broke
+ SIGCHLD handling on systems that don't have WNOHANG. (Bug#12327)
+
+2012-09-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Explicitly mark buffer_defaults and buffer_local_symbols.
+ * alloc.c (Fgarbage_collect): Mark buffer_defaults and
+ mark_local_symbols here.
+ (mark_object): If GC_CHECK_MARKED_OBJECTS, simplify checking
+ since special buffers aren't marked here any more.
+ (allocate_buffer): Chain new buffer with all_buffers here...
+ * buffer.c (Fget_buffer_create, Fmake_indirect_buffer): ...and
+ not here.
+ (Vbuffer_defaults, Vbuffer_local_symbols): Remove.
+ (syms_of_buffer): Remove staticpro of the above.
+ (init_buffer_once): Set names for buffer_defaults and
+ buffer_local_symbols.
+
+2012-09-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use bool for booleans in font-related modules.
+ * font.c (font_intern_prop, font_style_to_value)
+ (font_style_symbolic, font_parse_xlfd, font_parse_fcname)
+ (generate_otf_features, font_check_otf_features, font_check_otf)
+ (font_match_p, font_list_entities, font_at):
+ * fontset.c (fontset_id_valid_p, reorder_font_vector
+ (fontset_find_font, Fset_fontset_font)
+ (face_suitable_for_char_p) [0]:
+ * ftfont.c (fc_initialized, ftfont_get_open_type_spec)
+ (ftfont_open, ftfont_text_extents, ftfont_check_otf):
+ (m17n_flt_initialized, ftfont_shape_by_flt):
+ * ftxfont.c (ftxfont_draw_bitmap, ftxfont_draw):
+ * nsfont.m (nsfont_draw):
+ * w32font.c (w32font_draw):
+ * w32term.c (x_draw_glyphless_glyph_string_foreground):
+ Use bool for booleans.
+ * font.h: Adjust to above API changes.
+ (struct font, struct font_driver, struct font_driver_list):
+ Use bool for booleans.
+ (struct font): Remove useless member encoding_type.
+ All users removed.
+ * fontset.c, xftfont.c: Omit unnecessary static decls.
+
+2012-09-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (mark_object): Revert window marking code
+ since it's unsafe for the Fset_window_configuration.
+
+2012-09-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix race conditions with signal handlers and errno (Bug#12327).
+ Be more systematic about preserving errno whenever a signal
+ handler returns, even if it's not in the main thread. Do this by
+ renaming signal handlers to distinguish between signal delivery
+ and signal handling. All uses changed.
+ * atimer.c (deliver_alarm_signal): Rename from alarm_signal_handler.
+ * data.c (deliver_arith_signal): Rename from arith_error.
+ * dispnew.c (deliver_window_change_signal): Rename from
+ window_change_signal.
+ * emacs.c (deliver_error_signal): Rename from fatal_error_signal.
+ (deliver_danger_signal) [SIGDANGER]: Rename from memory_warning_signal.
+ * keyboard.c (deliver_input_available_signal): Rename from
+ input_available_signal.
+ (deliver_user_signal): Rename from handle_user_signal.
+ (deliver_interrupt_signal): Rename from interrupt_signal.
+ * process.c (deliver_pipe_signal): Rename from send_process_trap.
+ (deliver_child_signal): Rename from sigchld_handler.
+ * atimer.c (handle_alarm_signal):
+ * data.c (handle_arith_signal):
+ * dispnew.c (handle_window_change_signal):
+ * emacs.c (handle_fatal_signal, handle_danger_signal):
+ * keyboard.c (handle_input_available_signal):
+ * keyboard.c (handle_user_signal, handle_interrupt_signal):
+ * process.c (handle_pipe_signal, handle_child_signal):
+ New functions, with the actual signal-handling code taken from the
+ original respective signal handlers, sans the sporadic attempts to
+ preserve errno, since that's now done by handle_on_main_thread.
+ * atimer.c (alarm_signal_handler): Remove unnecessary decl.
+ * emacs.c, floatfns.c, lisp.h: Remove unused FLOAT_CATCH_SIGKILL cruft.
+ * emacs.c (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
+ Move to sysdep.c.
+ (main) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
+ Move initialization of main_thread to sysdep.c's init_signals.
+ * process.c (waitpid) [!WNOHANG]: #define to wait; that's good enough for
+ our usage, and simplifies the mainline code.
+ (record_child_status_change): New static function, as a helper
+ for handle_child_signal, and with most of the old child handler's
+ contents.
+ (CAN_HANDLE_MULTIPLE_CHILDREN): New constant.
+ (handle_child_signal): Use the above.
+ * sysdep.c (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
+ Moved here from emacs.c.
+ (init_signals) [FORWARD_SIGNAL_TO_MAIN_THREAD]: Initialize it;
+ code moved here from emacs.c's main function.
+ * sysdep.c, syssignal.h (handle_on_main_thread): New function,
+ replacing the old SIGNAL_THREAD_CHECK. All uses changed.
+ This lets callers save and restore errno properly.
+
+2012-09-05 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Remove redundant or unused things here and there.
+ * lisp.h (CYCLE_CHECK, CHAR_TABLE_TRANSLATE): Remove.
+ * conf_post.h (RE_TRANSLATE): Use char_table_translate.
+ * editfns.c (Fcompare_buffer_substrings): Likewise.
+ * frame.h (struct terminal, struct font_driver_list):
+ Remove redundant declarations.
+ * window.h (Qleft, Qright): Likewise.
+
+2012-09-05 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Do not mark objects from deleted buffers, windows and frames.
+ * alloc.c (mark_buffer): Mark just the buffer if it is dead.
+ (mark_object): Likewise for windows and frames.
+
+2012-09-05 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (valid_lisp_object_p): Treat killed buffers,
+ buffer_defaults and buffer_local_symbols as valid objects.
+ Return special value to denote them.
+
+2012-09-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ * fileio.c, filelock.c, floatfns.c, fns.c: Use bool for boolean.
+ * fileio.c (auto_saving, auto_save_error_occurred, make_temp_name)
+ (Fexpand_file_name, barf_or_query_if_file_exists, Fcopy_file)
+ (file_name_absolute_p, Fsubstitute_in_file_name):
+ (check_executable, check_writable, Ffile_accessible_directory_p)
+ (Fset_file_selinux_context, Fdefault_file_modes)
+ (Finsert_file_contents, choose_write_coding_system)
+ (Fwrite_region, build_annotations, a_write, e_write)
+ (Fdo_auto_save):
+ * filelock.c (boot_time_initialized, get_boot_time)
+ (get_boot_time_1, lock_file_1, within_one_second):
+ * floatfns.c (in_float):
+ * fns.c (concat, internal_equal, Frequire, base64_encode_1)
+ (base64_decode_1, cmpfn_eql, cmpfn_user_defined)
+ (sweep_weak_table, sweep_weak_hash_tables, secure_hash):
+ * lisp.h (struct Lisp_Hash_Table.cmpfn):
+ * window.c (compare_window_configurations):
+ Use bool for booleans.
+ * fileio.c (auto_saving_dir_umask, auto_saving_mode_bits)
+ (Fdefault_file_modes): Now mode_t, not int, for modes.
+ (Fdo_auto_save): Set a boolean to 1 rather than using ++.
+ (internal_delete_file): Now returns void, not a (boolean) int,
+ since nobody was looking at the return value.
+ * lisp.h, window.h: Adjust to above API changes.
+
+ * xdisp.c (set_message): Simplify and reindent last change.
+
+2012-09-05 Juanma Barranquero <lekktu@gmail.com>
+
+ * makefile.w32-in ($(BLD)/sysdep.$(O)): Update dependencies.
+
+2012-09-04 Lars Ingebrigtsen <larsi@gnus.org>
+
+ * eval.c (call_debugger): Make the function non-static so that we
+ can call it from set_message.
+
+ * xdisp.c (set_message): Implement the new variable `debug-on-message'.
+ (syms_of_xdisp): Defvar it and `inhibit-debug-on-message'.
+
+2012-09-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ Give more-useful info on a fatal error (Bug#12328).
+ * alloc.c [ENABLE_CHECKING]: Do not include <execinfo.h>.
+ (die) [ENABLE_CHECKING]: Call fatal_error_backtrace instead
+ of doing the work ourselves.
+ * emacs.c (fatal_error_signal): Let fatal_error_backtrace
+ do most of the work.
+ (fatal_error_backtrace): New function, taken from the guts
+ of the old fatal_error_signal, but with a new option to output
+ a backtrace.
+ (shut_down_emacs) [!DOS_NT]: Use strsignal to give more-useful
+ info about the signal than just its number.
+ * lisp.h (fatal_error_backtrace, emacs_backtrace): New decls.
+ * sysdep.c: Include <execinfo.h>
+ (emacs_backtrace): New function, taken partly from the previous
+ code of the 'die' function.
+ (emacs_abort): Call fatal_error_backtrace rather than abort.
+
+2012-09-04 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lread.c (readevalloop): Call internal-macroexpand-for-load to perform
+ eager (load-time) macro-expansion.
+ * lisp.mk (lisp): Add macroexp.
+
+2012-09-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ Simplify redefinition of 'abort' (Bug#12316).
+ Do not try to redefine the 'abort' function. Instead, redo
+ the code so that it calls 'emacs_abort' rather than 'abort'.
+ This removes the need for the NO_ABORT configure-time macro
+ and makes it easier to change the abort code to do a backtrace.
+ * .gdbinit: Just stop at emacs_abort, not at w32_abort or abort.
+ * emacs.c (abort) [!DOS_NT && !NO_ABORT]:
+ Remove; sysdep.c's emacs_abort now takes its place.
+ * lisp.h (emacs_abort): New decl. All calls from Emacs code to
+ 'abort' changed to use 'emacs_abort'.
+ * msdos.c (dos_abort) [defined abort]: Remove; not used.
+ (abort) [!defined abort]: Rename to ...
+ (emacs_abort): ... new name.
+ * sysdep.c (emacs_abort) [!HAVE_NTGUI]: New function, taking
+ the place of the old 'abort' in emacs.c.
+ * w32.c, w32fns.c (abort): Do not #undef.
+ * w32.c (emacs_abort): Rename from w32_abort.
+
+2012-09-04 Eli Zaretskii <eliz@gnu.org>
+
+ * w32uniscribe.c (uniscribe_shape): Reverse the sign of
+ offsets[j].dv, since the y axis of the screen coordinates points
+ down, while the y axis of the font definition coordinates points
+ up. This fixes display of Arabic diacritics such as KASRA and
+ KASRATAN. (Bug#11860)
+
2012-09-04 Paul Eggert <eggert@cs.ucla.edu>
Be more systematic about _setjmp vs setjmp.
@@ -189,8 +4582,8 @@
* process.c: Include TERM_HEADER instead of listing all possible
window-system headers.
- * nsterm.h: Remove declarations now in frame.h. Define
- FRAME_X_SCREEN, FRAME_X_VISUAL.
+ * nsterm.h: Remove declarations now in frame.h.
+ Define FRAME_X_SCREEN, FRAME_X_VISUAL.
* menu.c: Include TERM_HEADER instead of listing all possible
window-system headers.
@@ -279,18 +4672,18 @@
2012-08-28 Jan Djärv <jan.h.d@swipnet.se>
* nsmenu.m (initWithContentRect:styleMask:backing:defer:): Initialize
- button_values to NULL. Call setStykeMask so dialogs get a close button.
+ button_values to NULL. Call setStykeMask so dialogs get a close button.
(windowShouldClose:): Set window_closed.
(dealloc): New member, free button_values.
- (process_dialog:): Make member function. Remove window argument,
- replace window with self. Count buttons and allocate and store values
+ (process_dialog:): Make member function. Remove window argument,
+ replace window with self. Count buttons and allocate and store values
in button_values.
(addButton:value:row:): value is int with the name tag. Call setTag
- with tag. Remove return self, declare return value as void.
+ with tag. Remove return self, declare return value as void.
(addString:row:): Remove return self, declare return value as void.
(addSplit): Remove return self, declare return value as void.
(clicked:): Remove return self, declare return value as void.
- Set dialog_return to button_values[seltag]. Code formatting change.
+ Set dialog_return to button_values[seltag]. Code formatting change.
(initFromContents:isQuestion:): Adjust call to process_dialog.
Code formatting change.
(timeout_handler:): Set timer_fired to YES.
@@ -386,8 +4779,8 @@
* nsterm.h (NSPanel): New class variable dialog_return.
- * nsmenu.m (initWithContentRect:styleMask:backing:defer:): Initialize
- dialog_return.
+ * nsmenu.m (initWithContentRect:styleMask:backing:defer:):
+ Initialize dialog_return.
(windowShouldClose:): Use stop instead of stopModalWithCode.
(clicked:): Ditto, and also set dialog_return (Bug#12258).
(timeout_handler:): Use stop instead of abortModal. Send a dummy
@@ -625,7 +5018,7 @@
* fontset.c (FONTSET_ADD): Return void, not Lisp_Object.
Otherwise, the compiler complains about (A?B:C) where B is void
- and C is Lisp_Object. This fixes an incompatibility with Sun C 5.12.
+ and C is Lisp_Object. This fixes an incompatibility with Sun C 5.12.
(fontset_add): Return void, for FONTSET_ADD.
2012-08-21 Paul Eggert <eggert@cs.ucla.edu>
@@ -1141,7 +5534,7 @@
Start main loop and wait for application defined event.
Inform select thread to stop selecting after main loop is exited.
(ns_term_init): Create selfds pipe and set non-blocking.
- Initialize select_mutex. Start the select thread (fd_handler).
+ Initialize select_mutex. Start the select thread (fd_handler).
(fd_handler:): Loop forever, wait for info from the main thread
to either start or stop selecting. When select returns, send
and appdefined event.
@@ -1273,7 +5666,7 @@
(xg_create_tool_bar): Allocate and initialize a xg_frame_tb_info
if not present.
(update_frame_tool_bar): Return early if data in xg_frame_tb_info
- is up to date. Otherwise store new data.
+ is up to date. Otherwise store new data.
(free_frame_tool_bar): Free xg_frame_tb_info if present.
2012-08-13 Dmitry Antipov <dmantipov@yandex.ru>
@@ -1300,7 +5693,7 @@
2012-08-11 Jan Djärv <jan.h.d@swipnet.se>
* nsterm.m (not_in_argv): New function.
- (application:openFile, application:openTempFile:):
+ (application:openFile, application:openTempFile:):
(application:openFileWithoutUI:, application:openFiles:): Open file
if not_in_argv returns non-zero (bug#12171).
@@ -1833,7 +6226,7 @@
* nsterm.m (ns_set_vertical_scroll_bar, ns_redeem_scroll_bar)
(EmacsWindow-accessibilityAttributeValue, EmacsScroller-initFrame:)
- (EmacsScroller-dealloc): Adjust to use WVAR. (Bug#12114)
+ (EmacsScroller-dealloc): Adjust to use WVAR. (Bug#12114)
* nsfns.m (ns_set_name_as_filename): Likewise.
* nsmenu.m (ns_update_menubar): Likewise.
* nsselect.m (symbol_to_nsstring): Adjust to use SVAR.
@@ -2487,7 +6880,7 @@
2012-07-21 Jan Djärv <jan.h.d@swipnet.se>
- * nsterm.m (accessibilityAttributeValue): New function. (Bug#11134).
+ * nsterm.m (accessibilityAttributeValue): New function. (Bug#11134).
(conversationIdentifier): Return value is NSInteger.
* nsterm.m (accessibilityAttributeValue): Surround with NS_IMPL_COCOA.
@@ -3383,7 +7776,7 @@
* lisp.h (make_formatted_string): New prototype.
* alloc.c (make_formatted_string): New function.
* buffer.c (Fgenerate_new_buffer_name): Use it.
- * dbus.c (syms_of_dbusbind): Likewise.
+ * dbusbind.c (syms_of_dbusbind): Likewise.
* editfns.c (Fcurrent_time_zone): Likewise.
* filelock.c (get_boot_time): Likewise.
* frame.c (make_terminal_frame, set_term_frame_name)
@@ -3929,7 +8322,7 @@
Fix block vector allocation code to allow VECTOR_BLOCK_SIZE
values which aren't power of 2.
* alloc.c (VECTOR_FREE_LIST_SIZE_MASK): New macro.
- Verify it's value and the value of VECTOR_BLOCK_SIZE. Adjust users
+ Verify its value and the value of VECTOR_BLOCK_SIZE. Adjust users
accordingly.
2012-07-03 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -4997,7 +9390,7 @@
* lisp.h (struct vectorlike_header): New field `nbytes',
adjust comment accordingly.
* alloc.c (enum mem_type): New type `MEM_TYPE_VECTOR_BLOCK'
- to denote vector blocks. Adjust users (live_vector_p,
+ to denote vector blocks. Adjust users (live_vector_p,
mark_maybe_pointer, valid_lisp_object_p) accordingly.
(COMMON_MULTIPLE): Move outside #if USE_LSB_TAG.
(VECTOR_BLOCK_SIZE, vroundup, VECTOR_BLOCK_BYTES),
@@ -5011,7 +9404,7 @@
(allocate_vector_from_block, init_vectors, allocate_vector_from_block)
(sweep_vectors): New functions.
(allocate_vectorlike): Return `zero_vector' as the only vector of
- 0 items. Allocate new vector from block if vector size is less than
+ 0 items. Allocate new vector from block if vector size is less than
or equal to VBLOCK_BYTES_MAX.
(Fgarbage_collect): Move all vector sweeping code to sweep_vectors.
(init_alloc_once): Add call to init_vectors.
@@ -5098,10 +9491,10 @@
bitfields where appropriate, remove unused fields.
* window.h (struct window): Remove unused 'last_mark_x' and
'last_mark_y' fields. Rename 'mini_p' field to 'mini',
- change it's type from Lisp_Object to bitfield.
+ change its type from Lisp_Object to bitfield.
Change type of 'force_start', 'optional_new_start',
'last_had_star', 'update_mode_line' and 'start_at_line_beg'
- fields from Lisp_Object to bitfield. Adjust users accordingly.
+ fields from Lisp_Object to bitfield. Adjust users accordingly.
2012-05-31 Paul Eggert <eggert@cs.ucla.edu>
@@ -6340,7 +10733,7 @@
2012-05-09 Michael Albinus <michael.albinus@gmx.de>
* dbusbind.c (xd_registered_buses): New internal Lisp object.
- Rename all occurences of Vdbus_registered_buses to xd_registered_buses.
+ Rename all occurrences of Vdbus_registered_buses to xd_registered_buses.
(syms_of_dbusbind): Remove declaration of Vdbus_registered_buses.
Initialize xd_registered_buses.
diff --git a/src/ChangeLog.11 b/src/ChangeLog.11
index d3b0a8284b5..1f444b9292c 100644
--- a/src/ChangeLog.11
+++ b/src/ChangeLog.11
@@ -5532,7 +5532,7 @@
(update_frame_tool_bar): Remove old_req, new_req. Do not get tool bar
height, call xg_update_tool_bar_sizes instead.
(free_frame_tool_bar): Remove from hbox or vbox depending on
- toolbar_in_hbox, Set all FRAME_TOOLBAR_*_(WIDTH|HEIGHT) to zero.
+ toolbar_in_hbox. Set all FRAME_TOOLBAR_*_(WIDTH|HEIGHT) to zero.
(xg_change_toolbar_position): New function.
* frame.h (struct frame): Add tool_bar_position.
diff --git a/src/ChangeLog.2 b/src/ChangeLog.2
index 1a9728f6896..0806106836e 100644
--- a/src/ChangeLog.2
+++ b/src/ChangeLog.2
@@ -2680,7 +2680,7 @@
1986-12-11 Richard Mlynarik (mly@prep)
- * emacs.c, dispnew.c:
+ * emacs.c, dispnew.c:
Rename inhibit_x_windows inhibit_window_system.
Understand "-nw" command-line option.
Reorganize init_display a little to make other window-system
diff --git a/src/ChangeLog.3 b/src/ChangeLog.3
index 6c580fe4b52..4f6e02ff8d3 100644
--- a/src/ChangeLog.3
+++ b/src/ChangeLog.3
@@ -11154,7 +11154,7 @@
(classify_object): Removed code to look up a function key in the
global and local function key keymaps, since this will be done
more generally.
- (Fexecute_mouse_event): Elided this function with a #if 0; I
+ (Fexecute_mouse_event): Elided this function with a #if 0; I
think it will go away once the more general keymap stuff is
implemented, but I'm not sure.
(syms_of_keyboard): Removed defsubr for Sexecute_mouse_event.
diff --git a/src/Makefile.in b/src/Makefile.in
index 24c8b94b590..b920600c4c0 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -28,9 +28,11 @@ SHELL = /bin/sh
# 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@
+ntsource = $(srcdir)/../nt
abs_builddir = @abs_builddir@
VPATH = $(srcdir)
CC = @CC@
+WINDRES = @WINDRES@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
@@ -135,13 +137,10 @@ LIB_MATH=@LIB_MATH@
## -lpthreads, or empty.
LIB_PTHREAD=@LIB_PTHREAD@
-LIBTIFF=@LIBTIFF@
-LIBJPEG=@LIBJPEG@
-LIBPNG=@LIBPNG@
-LIBGIF=@LIBGIF@
-LIBXPM=@LIBXPM@
+LIBIMAGE=@LIBTIFF@ @LIBJPEG@ @LIBPNG@ @LIBGIF@ @LIBXPM@
+
XFT_LIBS=@XFT_LIBS@
-LIBX_EXTRA=$(LIBTIFF) $(LIBJPEG) $(LIBPNG) $(LIBGIF) $(LIBXPM) -lX11 $(XFT_LIBS)
+LIBX_EXTRA=-lX11 $(XFT_LIBS)
FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
@@ -153,6 +152,8 @@ M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
M17N_FLT_LIBS = @M17N_FLT_LIBS@
LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
+LIB_EACCESS=@LIB_EACCESS@
+LIB_TIMER_TIME=@LIB_TIMER_TIME@
DBUS_CFLAGS = @DBUS_CFLAGS@
DBUS_LIBS = @DBUS_LIBS@
@@ -255,14 +256,25 @@ MSDOS_OBJ =
## w16select.o termcap.o if MSDOS && HAVE_X_WINDOWS.
MSDOS_X_OBJ =
-ns_appdir=@ns_appdir@
-ns_appbindir=@ns_appbindir@
-ns_appsrc=@ns_appsrc@
NS_OBJ=@NS_OBJ@
## nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o if HAVE_NS.
NS_OBJC_OBJ=@NS_OBJC_OBJ@
## Only set if NS_IMPL_GNUSTEP.
GNU_OBJC_CFLAGS=@GNU_OBJC_CFLAGS@
+## w32fns.o w32menu.c w32reg.o fringe.o fontset.o w32font.o w32term.o
+## w32xfns.o w32select.o image.o w32uniscribe.o if HAVE_W32, else
+## empty.
+W32_OBJ=@W32_OBJ@
+## -lkernel32 -luser32 -lgdi32 -lole32 -lcomdlg32 lusp10 -lcomctl32
+## --lwinspool if HAVE_W32, else empty.
+W32_LIBS=@W32_LIBS@
+
+## emacs.res if HAVE_W32
+W32_RES=@W32_RES@
+## If HAVE_W32, compiler arguments for including
+## the resource file in the binary.
+## XXX -Wl,-b -Wl,pe-i386 -Wl,emacs.res
+W32_RES_LINK=@W32_RES_LINK@
## Empty if !HAVE_X_WINDOWS
## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT
@@ -280,6 +292,8 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@
LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBACL_LIBS = @LIBACL_LIBS@
+
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
INTERVALS_H = dispextern.h intervals.h composite.h
@@ -326,7 +340,6 @@ ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
@$(MKDEPDIR)
$(CC) -c $(CPPFLAGS) $(ALL_OBJC_CFLAGS) $<
-
## lastfile must follow all files whose initialized data areas should
## be dumped as pure by dump-emacs.
base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
@@ -340,10 +353,12 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
eval.o floatfns.o fns.o font.o print.o lread.o \
syntax.o $(UNEXEC_OBJ) bytecode.o \
process.o gnutls.o callproc.o \
- region-cache.o sound.o atimer.o thread.o systhread.o \
- doprnt.o intervals.o textprop.o composite.o xml.o \
+ region-cache.o sound.o atimer.o \
+ doprnt.o intervals.o textprop.o composite.o xml.o inotify.o \
+ profiler.o \
+ thread.o systhread.o \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
- $(WINDOW_SYSTEM_OBJ)
+ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ)
obj = $(base_obj) $(NS_OBJC_OBJ)
## Object files used on some machine or other.
@@ -352,9 +367,9 @@ obj = $(base_obj) $(NS_OBJC_OBJ)
## in the list, in case they ever add any such entries.
SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o fringe.o image.o \
- fontset.o dbusbind.o \
+ fontset.o dbusbind.o cygw32.o \
nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o \
- w32.o w32console.o w32fns.o w32heap.o w32inevt.o \
+ w32.o w32console.o w32fns.o w32heap.o w32inevt.o w32notify.o \
w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
w16select.o widget.o xfont.o ftfont.o xftfont.o ftxfont.o gtkutil.o \
xsettings.o xgselect.o termcap.o
@@ -386,13 +401,15 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
## Note that SunOS needs -lm to come before -lc; otherwise, you get
## duplicated symbols. If the standard libraries were compiled
## with GCC, we might need LIB_GCC again after them.
-LIBES = $(LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \
- $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) $(DBUS_LIBS) \
+LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \
+ $(LIBX_OTHER) $(LIBSOUND) \
+ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \
+ $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
$(LIB_EXECINFO) \
$(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) \
+ $(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
$(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC)
all: emacs$(EXEEXT) $(OTHER_FILES)
@@ -457,9 +474,11 @@ $(obj) $(otherobj): globals.h
$(lib)/libgnu.a: $(config_h)
cd $(lib) && $(MAKE) libgnu.a
-temacs$(EXEEXT): $(START_FILES) stamp-oldxmenu $(obj) $(otherobj) $(lib)/libgnu.a
+temacs$(EXEEXT): $(START_FILES) stamp-oldxmenu $(obj) $(otherobj) \
+ $(lib)/libgnu.a $(W32_RES)
$(CC) $(LD_FIRSTFLAG) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(TEMACS_LDFLAGS2) \
- -o temacs $(START_FILES) $(obj) $(otherobj) $(lib)/libgnu.a $(LIBES)
+ -o temacs $(START_FILES) $(obj) $(otherobj) $(lib)/libgnu.a $(LIBES) \
+ $(W32_RES_LINK)
test "$(CANNOT_DUMP)" = "yes" || \
test "X$(PAXCTL)" = X || $(PAXCTL) -r temacs$(EXEEXT)
@@ -500,9 +519,13 @@ $(OLDXMENU): $(OLDXMENU_TARGET)
doc.o: buildobj.h
+emacs.res: $(ntsource)/emacs.rc \
+ $(ntsource)/icons/emacs.ico \
+ $(ntsource)/emacs-x86.manifest
+ $(WINDRES) -O COFF -o $@ $(ntsource)/emacs.rc
-## If HAVE_NS, some ns-specific rules (for OTHER_FILES) are inserted here.
-@ns_frag@
+ns-app: emacs$(EXEEXT)
+ cd ../nextstep && $(MAKE) $(MFLAGS) all
.PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean
.PHONY: versionclean extraclean frc
@@ -516,7 +539,6 @@ mostlyclean:
clean: mostlyclean
rm -f emacs-*.*.*$(EXEEXT) emacs$(EXEEXT)
-rm -rf $(DEPDIR)
- test "X$(ns_appdir)" = "X" || rm -rf $(ns_appdir)
## bootstrap-clean is used to clean up just before a bootstrap.
## It should remove all files generated during a compilation/bootstrap,
diff --git a/src/alloc.c b/src/alloc.c
index 859961781e0..d091a9cdf55 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -24,9 +24,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <limits.h> /* For CHAR_BIT. */
-#include <setjmp.h>
-#include <signal.h>
+#ifdef ENABLE_CHECKING
+#include <signal.h> /* For SIGABRT. */
+#endif
#ifdef HAVE_PTHREAD
#include <pthread.h>
@@ -42,9 +43,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "frame.h"
#include "blockinput.h"
-#include "syssignal.h"
#include "termhooks.h" /* For struct terminal. */
-#include <setjmp.h>
+
#include <verify.h>
/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
@@ -63,10 +63,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif
#include <unistd.h>
-#ifndef HAVE_UNISTD_H
-extern void *sbrk ();
-#endif
-
#include <fcntl.h>
#ifdef USE_GTK
@@ -74,6 +70,7 @@ extern void *sbrk ();
#endif
#ifdef WINDOWSNT
#include "w32.h"
+#include "w32heap.h" /* for sbrk */
#endif
#ifdef DOUG_LEA_MALLOC
@@ -85,66 +82,8 @@ extern void *sbrk ();
#define MMAP_MAX_AREAS 100000000
-#else /* not DOUG_LEA_MALLOC */
-
-/* The following come from gmalloc.c. */
-
-extern size_t _bytes_used;
-extern size_t __malloc_extra_blocks;
-extern void *_malloc_internal (size_t);
-extern void _free_internal (void *);
-
#endif /* not DOUG_LEA_MALLOC */
-#if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT
-#ifdef HAVE_PTHREAD
-
-/* When GTK uses the file chooser dialog, different backends can be loaded
- dynamically. One such a backend is the Gnome VFS backend that gets loaded
- if you run Gnome. That backend creates several threads and also allocates
- memory with malloc.
-
- Also, gconf and gsettings may create several threads.
-
- If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_*
- functions below are called from malloc, there is a chance that one
- of these threads preempts the Emacs main thread and the hook variables
- end up in an inconsistent state. So we have a mutex to prevent that (note
- that the backend handles concurrent access to malloc within its own threads
- but Emacs code running in the main thread is not included in that control).
-
- When UNBLOCK_INPUT is called, reinvoke_input_signal may be called. If this
- happens in one of the backend threads we will have two threads that tries
- to run Emacs code at once, and the code is not prepared for that.
- To prevent that, we only call BLOCK/UNBLOCK from the main thread. */
-
-static pthread_mutex_t alloc_mutex;
-
-#define BLOCK_INPUT_ALLOC \
- do \
- { \
- if (pthread_equal (pthread_self (), main_thread)) \
- BLOCK_INPUT; \
- pthread_mutex_lock (&alloc_mutex); \
- } \
- while (0)
-#define UNBLOCK_INPUT_ALLOC \
- do \
- { \
- pthread_mutex_unlock (&alloc_mutex); \
- if (pthread_equal (pthread_self (), main_thread)) \
- UNBLOCK_INPUT; \
- } \
- while (0)
-
-#else /* ! defined HAVE_PTHREAD */
-
-#define BLOCK_INPUT_ALLOC BLOCK_INPUT
-#define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT
-
-#endif /* ! defined HAVE_PTHREAD */
-#endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */
-
/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
to a struct Lisp_String. */
@@ -203,10 +142,6 @@ static char *spare_memory[7];
#define SPARE_MEMORY (1 << 14)
-/* Number of extra blocks malloc should get when it needs more core. */
-
-static int malloc_hysteresis;
-
/* Initialize it to a nonzero value to force it into data space
(rather than bss space). That way unexec will remap it into text
space (pure), on some systems. We have not implemented the
@@ -267,6 +202,7 @@ 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. */
@@ -276,22 +212,19 @@ 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_glyph_matrix (struct glyph_matrix *);
-static void mark_face_cache (struct face_cache *);
+static void mark_buffer (struct buffer *);
#if !defined REL_ALLOC || defined SYSTEM_MALLOC
static void refill_memory_reserve (void);
#endif
-static struct Lisp_String *allocate_string (void);
static void compact_small_strings (void);
static void free_large_strings (void);
-static void sweep_strings (void);
static void free_misc (Lisp_Object);
extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
-/* When scanning the C stack for live Lisp objects, Emacs keeps track
- of what memory allocated via lisp_malloc is intended for what
- purpose. This enumeration specifies the type of memory. */
+/* When scanning the C stack for live Lisp objects, Emacs keeps track of
+ what memory allocated via lisp_malloc and lisp_align_malloc is intended
+ for what purpose. This enumeration specifies the type of memory. */
enum mem_type
{
@@ -302,10 +235,9 @@ enum mem_type
MEM_TYPE_MISC,
MEM_TYPE_SYMBOL,
MEM_TYPE_FLOAT,
- /* We used to keep separate mem_types for subtypes of vectors such as
- process, hash_table, frame, terminal, and window, but we never made
- use of the distinction, so it only caused source-code complexity
- and runtime slowdown. Minor but pointless. */
+ /* Since all non-bool pseudovectors are small enough to be
+ allocated from vector blocks, this memory type denotes
+ large regular vectors and large bool pseudovectors. */
MEM_TYPE_VECTORLIKE,
/* Special type to denote vector blocks. */
MEM_TYPE_VECTOR_BLOCK,
@@ -313,9 +245,6 @@ enum mem_type
MEM_TYPE_SPARE
};
-static void *lisp_malloc (size_t, enum mem_type);
-
-
#if GC_MARK_STACK || defined GC_MALLOC_CHECK
#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
@@ -405,12 +334,12 @@ static void mark_memory (void *, void *);
static void mem_init (void);
static struct mem_node *mem_insert (void *, void *, enum mem_type);
static void mem_insert_fixup (struct mem_node *);
-#endif
static void mem_rotate_left (struct mem_node *);
static void mem_rotate_right (struct mem_node *);
static void mem_delete (struct mem_node *);
static void mem_delete_fixup (struct mem_node *);
-static inline struct mem_node *mem_find (void *);
+static struct mem_node *mem_find (void *);
+#endif
#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
@@ -426,7 +355,7 @@ static void check_gcpros (void);
/* Addresses of staticpro'd variables. Initialize it to a nonzero
value; otherwise some compilers put it into BSS. */
-#define NSTATICS 0x650
+#define NSTATICS 0x800
static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag};
/* Index of next unused slot in staticvec. */
@@ -575,39 +504,17 @@ xmalloc_get_size (unsigned char *ptr)
}
-/* The call depth in overrun_check functions. For example, this might happen:
- xmalloc()
- overrun_check_malloc()
- -> malloc -> (via hook)_-> emacs_blocked_malloc
- -> overrun_check_malloc
- call malloc (hooks are NULL, so real malloc is called).
- malloc returns 10000.
- add overhead, return 10016.
- <- (back in overrun_check_malloc)
- add overhead again, return 10032
- xmalloc returns 10032.
-
- (time passes).
-
- xfree(10032)
- overrun_check_free(10032)
- decrease overhead
- free(10016) <- crash, because 10000 is the original pointer. */
-
-static ptrdiff_t check_depth;
-
/* Like malloc, but wraps allocated block with header and trailer. */
static void *
overrun_check_malloc (size_t size)
{
register unsigned char *val;
- int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0;
- if (SIZE_MAX - overhead < size)
- abort ();
+ if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size)
+ emacs_abort ();
- val = malloc (size + overhead);
- if (val && check_depth == 1)
+ val = malloc (size + XMALLOC_OVERRUN_CHECK_OVERHEAD);
+ if (val)
{
memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
@@ -615,7 +522,6 @@ overrun_check_malloc (size_t size)
memcpy (val + size, xmalloc_overrun_check_trailer,
XMALLOC_OVERRUN_CHECK_SIZE);
}
- --check_depth;
return val;
}
@@ -627,12 +533,10 @@ static void *
overrun_check_realloc (void *block, size_t size)
{
register unsigned char *val = (unsigned char *) block;
- int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0;
- if (SIZE_MAX - overhead < size)
- abort ();
+ if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size)
+ emacs_abort ();
if (val
- && check_depth == 1
&& memcmp (xmalloc_overrun_check_header,
val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE,
XMALLOC_OVERRUN_CHECK_SIZE) == 0)
@@ -640,15 +544,15 @@ overrun_check_realloc (void *block, size_t size)
size_t osize = xmalloc_get_size (val);
if (memcmp (xmalloc_overrun_check_trailer, val + osize,
XMALLOC_OVERRUN_CHECK_SIZE))
- abort ();
+ emacs_abort ();
memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE);
}
- val = realloc (val, size + overhead);
+ val = realloc (val, size + XMALLOC_OVERRUN_CHECK_OVERHEAD);
- if (val && check_depth == 1)
+ if (val)
{
memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
@@ -656,7 +560,6 @@ overrun_check_realloc (void *block, size_t size)
memcpy (val + size, xmalloc_overrun_check_trailer,
XMALLOC_OVERRUN_CHECK_SIZE);
}
- --check_depth;
return val;
}
@@ -667,9 +570,7 @@ overrun_check_free (void *block)
{
unsigned char *val = (unsigned char *) block;
- ++check_depth;
if (val
- && check_depth == 1
&& memcmp (xmalloc_overrun_check_header,
val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE,
XMALLOC_OVERRUN_CHECK_SIZE) == 0)
@@ -677,7 +578,7 @@ overrun_check_free (void *block)
size_t osize = xmalloc_get_size (val);
if (memcmp (xmalloc_overrun_check_trailer, val + osize,
XMALLOC_OVERRUN_CHECK_SIZE))
- abort ();
+ emacs_abort ();
#ifdef XMALLOC_CLEAR_FREE_MEMORY
val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD);
@@ -689,7 +590,6 @@ overrun_check_free (void *block)
}
free (val);
- --check_depth;
}
#undef malloc
@@ -700,16 +600,42 @@ overrun_check_free (void *block)
#define free overrun_check_free
#endif
-#ifdef SYNC_INPUT
-/* When using SYNC_INPUT, we don't call malloc from a signal handler, so
- there's no need to block input around malloc. */
-#define MALLOC_BLOCK_INPUT ((void)0)
-#define MALLOC_UNBLOCK_INPUT ((void)0)
+/* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol
+ BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger.
+ If that variable is set, block input while in one of Emacs's memory
+ allocation functions. There should be no need for this debugging
+ option, since signal handlers do not allocate memory, but Emacs
+ formerly allocated memory in signal handlers and this compile-time
+ option remains as a way to help debug the issue should it rear its
+ ugly head again. */
+#ifdef XMALLOC_BLOCK_INPUT_CHECK
+bool block_input_in_memory_allocators EXTERNALLY_VISIBLE;
+static void
+malloc_block_input (void)
+{
+ if (block_input_in_memory_allocators)
+ block_input ();
+}
+static void
+malloc_unblock_input (void)
+{
+ if (block_input_in_memory_allocators)
+ unblock_input ();
+}
+# define MALLOC_BLOCK_INPUT malloc_block_input ()
+# define MALLOC_UNBLOCK_INPUT malloc_unblock_input ()
#else
-#define MALLOC_BLOCK_INPUT BLOCK_INPUT
-#define MALLOC_UNBLOCK_INPUT UNBLOCK_INPUT
+# define MALLOC_BLOCK_INPUT ((void) 0)
+# define MALLOC_UNBLOCK_INPUT ((void) 0)
#endif
+#define MALLOC_PROBE(size) \
+ do { \
+ if (profiler_memory_running) \
+ malloc_probe (size); \
+ } while (0)
+
+
/* Like malloc but check for no memory and block interrupt input.. */
void *
@@ -723,6 +649,7 @@ xmalloc (size_t size)
if (!val && size)
memory_full (size);
+ MALLOC_PROBE (size);
return val;
}
@@ -740,6 +667,7 @@ xzalloc (size_t size)
if (!val && size)
memory_full (size);
memset (val, 0, size);
+ MALLOC_PROBE (size);
return val;
}
@@ -761,6 +689,7 @@ xrealloc (void *block, size_t size)
if (!val && size)
memory_full (size);
+ MALLOC_PROBE (size);
return val;
}
@@ -776,8 +705,7 @@ xfree (void *block)
free (block);
MALLOC_UNBLOCK_INPUT;
/* We don't call refill_memory_reserve here
- because that duplicates doing so in emacs_blocked_free
- and the criterion should go there. */
+ because in practice the call in r_alloc_free seems to suffice. */
}
@@ -824,13 +752,17 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
infinity.
If PA is null, then allocate a new array instead of reallocating
- the old one. Thus, to grow an array A without saving its old
- contents, invoke xfree (A) immediately followed by xgrowalloc (0,
- &NITEMS, ...).
+ the old one.
Block interrupt input as needed. If memory exhaustion occurs, set
*NITEMS to zero if PA is null, and signal an error (i.e., do not
- return). */
+ return).
+
+ Thus, to grow an array A without saving its old contents, do
+ { xfree (A); A = NULL; A = xpalloc (NULL, &AITEMS, ...); }.
+ The A = NULL avoids a dangling pointer if xpalloc exhausts memory
+ and signals an error, and later this code is reexecuted and
+ attempts to free A. */
void *
xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
@@ -879,18 +811,22 @@ xstrdup (const char *s)
return p;
}
+/* Like putenv, but (1) use the equivalent of xmalloc and (2) the
+ argument is a const pointer. */
+
+void
+xputenv (char const *string)
+{
+ if (putenv ((char *) string) != 0)
+ memory_full (0);
+}
/* Unwind for SAFE_ALLOCA */
Lisp_Object
safe_alloca_unwind (Lisp_Object arg)
{
- register struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
-
- p->dogc = 0;
- xfree (p->pointer);
- p->pointer = 0;
- free_misc (arg);
+ free_save_value (arg);
return Qnil;
}
@@ -951,6 +887,7 @@ lisp_malloc (size_t nbytes, enum mem_type type)
MALLOC_UNBLOCK_INPUT;
if (!val && nbytes)
memory_full (nbytes);
+ MALLOC_PROBE (nbytes);
return val;
}
@@ -1156,6 +1093,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
MALLOC_UNBLOCK_INPUT;
+ MALLOC_PROBE (nbytes);
+
eassert (0 == ((uintptr_t) val) % BLOCK_ALIGN);
return val;
}
@@ -1204,256 +1143,6 @@ lisp_align_free (void *block)
}
-#ifndef SYSTEM_MALLOC
-
-/* Arranging to disable input signals while we're in malloc.
-
- This only works with GNU malloc. To help out systems which can't
- use GNU malloc, all the calls to malloc, realloc, and free
- elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT
- pair; unfortunately, we have no idea what C library functions
- might call malloc, so we can't really protect them unless you're
- using GNU malloc. Fortunately, most of the major operating systems
- can use GNU malloc. */
-
-#ifndef SYNC_INPUT
-/* When using SYNC_INPUT, we don't call malloc from a signal handler, so
- there's no need to block input around malloc. */
-
-#ifndef DOUG_LEA_MALLOC
-extern void * (*__malloc_hook) (size_t, const void *);
-extern void * (*__realloc_hook) (void *, size_t, const void *);
-extern void (*__free_hook) (void *, const void *);
-/* Else declared in malloc.h, perhaps with an extra arg. */
-#endif /* DOUG_LEA_MALLOC */
-static void * (*old_malloc_hook) (size_t, const void *);
-static void * (*old_realloc_hook) (void *, size_t, const void*);
-static void (*old_free_hook) (void*, const void*);
-
-#ifdef DOUG_LEA_MALLOC
-# define BYTES_USED (mallinfo ().uordblks)
-#else
-# define BYTES_USED _bytes_used
-#endif
-
-#ifdef GC_MALLOC_CHECK
-static bool dont_register_blocks;
-#endif
-
-static size_t bytes_used_when_reconsidered;
-
-/* Value of _bytes_used, when spare_memory was freed. */
-
-static size_t bytes_used_when_full;
-
-/* This function is used as the hook for free to call. */
-
-static void
-emacs_blocked_free (void *ptr, const void *ptr2)
-{
- BLOCK_INPUT_ALLOC;
-
-#ifdef GC_MALLOC_CHECK
- if (ptr)
- {
- struct mem_node *m;
-
- m = mem_find (ptr);
- if (m == MEM_NIL || m->start != ptr)
- {
- fprintf (stderr,
- "Freeing `%p' which wasn't allocated with malloc\n", ptr);
- abort ();
- }
- else
- {
- /* fprintf (stderr, "free %p...%p (%p)\n", m->start, m->end, ptr); */
- mem_delete (m);
- }
- }
-#endif /* GC_MALLOC_CHECK */
-
- __free_hook = old_free_hook;
- free (ptr);
-
- /* If we released our reserve (due to running out of memory),
- and we have a fair amount free once again,
- try to set aside another reserve in case we run out once more. */
- if (! NILP (Vmemory_full)
- /* Verify there is enough space that even with the malloc
- hysteresis this call won't run out again.
- The code here is correct as long as SPARE_MEMORY
- is substantially larger than the block size malloc uses. */
- && (bytes_used_when_full
- > ((bytes_used_when_reconsidered = BYTES_USED)
- + max (malloc_hysteresis, 4) * SPARE_MEMORY)))
- refill_memory_reserve ();
-
- __free_hook = emacs_blocked_free;
- UNBLOCK_INPUT_ALLOC;
-}
-
-
-/* This function is the malloc hook that Emacs uses. */
-
-static void *
-emacs_blocked_malloc (size_t size, const void *ptr)
-{
- void *value;
-
- BLOCK_INPUT_ALLOC;
- __malloc_hook = old_malloc_hook;
-#ifdef DOUG_LEA_MALLOC
- /* Segfaults on my system. --lorentey */
- /* mallopt (M_TOP_PAD, malloc_hysteresis * 4096); */
-#else
- __malloc_extra_blocks = malloc_hysteresis;
-#endif
-
- value = malloc (size);
-
-#ifdef GC_MALLOC_CHECK
- {
- struct mem_node *m = mem_find (value);
- if (m != MEM_NIL)
- {
- fprintf (stderr, "Malloc returned %p which is already in use\n",
- value);
- fprintf (stderr, "Region in use is %p...%p, %td bytes, type %d\n",
- m->start, m->end, (char *) m->end - (char *) m->start,
- m->type);
- abort ();
- }
-
- if (!dont_register_blocks)
- {
- mem_insert (value, (char *) value + max (1, size), allocated_mem_type);
- allocated_mem_type = MEM_TYPE_NON_LISP;
- }
- }
-#endif /* GC_MALLOC_CHECK */
-
- __malloc_hook = emacs_blocked_malloc;
- UNBLOCK_INPUT_ALLOC;
-
- /* fprintf (stderr, "%p malloc\n", value); */
- return value;
-}
-
-
-/* This function is the realloc hook that Emacs uses. */
-
-static void *
-emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2)
-{
- void *value;
-
- BLOCK_INPUT_ALLOC;
- __realloc_hook = old_realloc_hook;
-
-#ifdef GC_MALLOC_CHECK
- if (ptr)
- {
- struct mem_node *m = mem_find (ptr);
- if (m == MEM_NIL || m->start != ptr)
- {
- fprintf (stderr,
- "Realloc of %p which wasn't allocated with malloc\n",
- ptr);
- abort ();
- }
-
- mem_delete (m);
- }
-
- /* fprintf (stderr, "%p -> realloc\n", ptr); */
-
- /* Prevent malloc from registering blocks. */
- dont_register_blocks = 1;
-#endif /* GC_MALLOC_CHECK */
-
- value = realloc (ptr, size);
-
-#ifdef GC_MALLOC_CHECK
- dont_register_blocks = 0;
-
- {
- struct mem_node *m = mem_find (value);
- if (m != MEM_NIL)
- {
- fprintf (stderr, "Realloc returns memory that is already in use\n");
- abort ();
- }
-
- /* Can't handle zero size regions in the red-black tree. */
- mem_insert (value, (char *) value + max (size, 1), MEM_TYPE_NON_LISP);
- }
-
- /* fprintf (stderr, "%p <- realloc\n", value); */
-#endif /* GC_MALLOC_CHECK */
-
- __realloc_hook = emacs_blocked_realloc;
- UNBLOCK_INPUT_ALLOC;
-
- return value;
-}
-
-
-#ifdef HAVE_PTHREAD
-/* Called from Fdump_emacs so that when the dumped Emacs starts, it has a
- normal malloc. Some thread implementations need this as they call
- malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then
- calls malloc because it is the first call, and we have an endless loop. */
-
-void
-reset_malloc_hooks (void)
-{
- __free_hook = old_free_hook;
- __malloc_hook = old_malloc_hook;
- __realloc_hook = old_realloc_hook;
-}
-#endif /* HAVE_PTHREAD */
-
-
-/* Called from main to set up malloc to use our hooks. */
-
-void
-uninterrupt_malloc (void)
-{
-#ifdef HAVE_PTHREAD
-#ifdef DOUG_LEA_MALLOC
- pthread_mutexattr_t attr;
-
- /* GLIBC has a faster way to do this, but let's keep it portable.
- This is according to the Single UNIX Specification. */
- pthread_mutexattr_init (&attr);
- pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init (&alloc_mutex, &attr);
-#else /* !DOUG_LEA_MALLOC */
- /* Some systems such as Solaris 2.6 don't have a recursive mutex,
- and the bundled gmalloc.c doesn't require it. */
- pthread_mutex_init (&alloc_mutex, NULL);
-#endif /* !DOUG_LEA_MALLOC */
-#endif /* HAVE_PTHREAD */
-
- if (__free_hook != emacs_blocked_free)
- old_free_hook = __free_hook;
- __free_hook = emacs_blocked_free;
-
- if (__malloc_hook != emacs_blocked_malloc)
- old_malloc_hook = __malloc_hook;
- __malloc_hook = emacs_blocked_malloc;
-
- if (__realloc_hook != emacs_blocked_realloc)
- old_realloc_hook = __realloc_hook;
- __realloc_hook = emacs_blocked_realloc;
-}
-
-#endif /* not SYNC_INPUT */
-#endif /* not SYSTEM_MALLOC */
-
-
-
/***********************************************************************
Interval Allocation
***********************************************************************/
@@ -1499,8 +1188,6 @@ make_interval (void)
{
INTERVAL val;
- /* eassert (!handling_signal); */
-
MALLOC_BLOCK_INPUT;
if (interval_free_list)
@@ -1795,7 +1482,7 @@ string_bytes (struct Lisp_String *s)
if (!PURE_POINTER_P (s)
&& s->data
&& nbytes != SDATA_NBYTES (SDATA_OF_STRING (s)))
- abort ();
+ emacs_abort ();
return nbytes;
}
@@ -1869,7 +1556,7 @@ check_string_free_list (void)
while (s != NULL)
{
if ((uintptr_t) s < 1024)
- abort ();
+ emacs_abort ();
s = NEXT_FREE_LISP_STRING (s);
}
}
@@ -1884,8 +1571,6 @@ allocate_string (void)
{
struct Lisp_String *s;
- /* eassert (!handling_signal); */
-
MALLOC_BLOCK_INPUT;
/* If the free-list is empty, allocate a new string_block, and
@@ -2098,7 +1783,7 @@ sweep_strings (void)
back-pointer so that we know it's free. */
#ifdef GC_CHECK_STRING_BYTES
if (string_bytes (s) != SDATA_NBYTES (data))
- abort ();
+ emacs_abort ();
#else
data->u.nbytes = STRING_BYTES (s);
#endif
@@ -2209,7 +1894,7 @@ compact_small_strings (void)
/* Check that the string size recorded in the string is the
same as the one recorded in the sdata structure. */
if (s && string_bytes (s) != SDATA_NBYTES (from))
- abort ();
+ emacs_abort ();
#endif /* GC_CHECK_STRING_BYTES */
nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from);
@@ -2222,7 +1907,7 @@ compact_small_strings (void)
if (memcmp (string_overrun_cookie,
(char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE,
GC_STRING_OVERRUN_COOKIE_SIZE))
- abort ();
+ emacs_abort ();
#endif
/* Non-NULL S means it's alive. Copy its data. */
@@ -2342,7 +2027,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */)
val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil);
/* No Lisp_Object to trace in there. */
- XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0);
+ XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
p = XBOOL_VECTOR (val);
p->size = XFASTINT (length);
@@ -2479,7 +2164,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
struct Lisp_String *s;
if (nchars < 0)
- abort ();
+ emacs_abort ();
if (!nbytes)
return empty_multibyte_string;
@@ -2577,8 +2262,6 @@ make_float (double float_value)
{
register Lisp_Object val;
- /* eassert (!handling_signal); */
-
MALLOC_BLOCK_INPUT;
if (float_free_list)
@@ -2686,8 +2369,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
{
register Lisp_Object val;
- /* eassert (!handling_signal); */
-
MALLOC_BLOCK_INPUT;
if (cons_free_list)
@@ -2800,7 +2481,7 @@ listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...)
else if (type == CONSTYPE_HEAP)
val = Fcons (objp[i], val);
else
- abort ();
+ emacs_abort ();
}
return val;
}
@@ -2925,19 +2606,54 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
#define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
+/* Get and set the next field in block-allocated vectorlike objects on
+ the free list. Doing it this way respects C's aliasing rules.
+ We could instead make 'contents' a union, but that would mean
+ changes everywhere that the code uses 'contents'. */
+static struct Lisp_Vector *
+next_in_free_list (struct Lisp_Vector *v)
+{
+ intptr_t i = XLI (v->contents[0]);
+ return (struct Lisp_Vector *) i;
+}
+static void
+set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next)
+{
+ v->contents[0] = XIL ((intptr_t) next);
+}
+
/* Common shortcut to setup vector on a free list. */
-#define SETUP_ON_FREE_LIST(v, nbytes, index) \
- do { \
- XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \
- eassert ((nbytes) % roundup_size == 0); \
- (index) = VINDEX (nbytes); \
- eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \
- (v)->header.next.vector = vector_free_lists[index]; \
- vector_free_lists[index] = (v); \
- total_free_vector_slots += (nbytes) / word_size; \
+#define SETUP_ON_FREE_LIST(v, nbytes, tmp) \
+ do { \
+ (tmp) = ((nbytes - header_size) / word_size); \
+ XSETPVECTYPESIZE (v, PVEC_FREE, 0, (tmp)); \
+ eassert ((nbytes) % roundup_size == 0); \
+ (tmp) = VINDEX (nbytes); \
+ eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \
+ set_next_in_free_list (v, vector_free_lists[tmp]); \
+ vector_free_lists[tmp] = (v); \
+ total_free_vector_slots += (nbytes) / word_size; \
} while (0)
+/* This internal type is used to maintain the list of large vectors
+ which are allocated at their own, e.g. outside of vector blocks. */
+
+struct large_vector
+{
+ union {
+ struct large_vector *vector;
+#if USE_LSB_TAG
+ /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */
+ unsigned char c[vroundup (sizeof (struct large_vector *))];
+#endif
+ } next;
+ struct Lisp_Vector v;
+};
+
+/* This internal type is used to maintain an underlying storage
+ for small vectors. */
+
struct vector_block
{
char data[VECTOR_BLOCK_BYTES];
@@ -2955,7 +2671,7 @@ static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX];
/* Singly-linked list of large vectors. */
-static struct Lisp_Vector *large_vectors;
+static struct large_vector *large_vectors;
/* The only vector with 0 slots, allocated from pure space. */
@@ -2999,7 +2715,7 @@ init_vectors (void)
static struct Lisp_Vector *
allocate_vector_from_block (size_t nbytes)
{
- struct Lisp_Vector *vector, *rest;
+ struct Lisp_Vector *vector;
struct vector_block *block;
size_t index, restbytes;
@@ -3012,8 +2728,7 @@ allocate_vector_from_block (size_t nbytes)
if (vector_free_lists[index])
{
vector = vector_free_lists[index];
- vector_free_lists[index] = vector->header.next.vector;
- vector->header.next.nbytes = nbytes;
+ vector_free_lists[index] = next_in_free_list (vector);
total_free_vector_slots -= nbytes / word_size;
return vector;
}
@@ -3027,16 +2742,14 @@ allocate_vector_from_block (size_t nbytes)
{
/* This vector is larger than requested. */
vector = vector_free_lists[index];
- vector_free_lists[index] = vector->header.next.vector;
- vector->header.next.nbytes = nbytes;
+ vector_free_lists[index] = next_in_free_list (vector);
total_free_vector_slots -= nbytes / word_size;
/* Excess bytes are used for the smaller vector,
which should be set on an appropriate free list. */
restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
eassert (restbytes % roundup_size == 0);
- rest = ADVANCE (vector, nbytes);
- SETUP_ON_FREE_LIST (rest, restbytes, index);
+ SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
return vector;
}
@@ -3045,7 +2758,6 @@ allocate_vector_from_block (size_t nbytes)
/* New vector will be at the beginning of this block. */
vector = (struct Lisp_Vector *) block->data;
- vector->header.next.nbytes = nbytes;
/* If the rest of space from this block is large enough
for one-slot vector at least, set up it on a free list. */
@@ -3053,11 +2765,10 @@ allocate_vector_from_block (size_t nbytes)
if (restbytes >= VBLOCK_BYTES_MIN)
{
eassert (restbytes % roundup_size == 0);
- rest = ADVANCE (vector, nbytes);
- SETUP_ON_FREE_LIST (rest, restbytes, index);
+ SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
}
return vector;
- }
+}
/* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */
@@ -3065,15 +2776,30 @@ allocate_vector_from_block (size_t nbytes)
((char *) (vector) <= (block)->data \
+ VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
-/* Number of bytes used by vector-block-allocated object. This is the only
- place where we actually use the `nbytes' field of the vector-header.
- I.e. we could get rid of the `nbytes' field by computing it based on the
- vector-type. */
+/* Return the memory footprint of V in bytes. */
-#define PSEUDOVECTOR_NBYTES(vector) \
- (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \
- ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \
- : vector->header.next.nbytes)
+static ptrdiff_t
+vector_nbytes (struct Lisp_Vector *v)
+{
+ ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG;
+
+ if (size & PSEUDOVECTOR_FLAG)
+ {
+ if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
+ size = (bool_header_size
+ + (((struct Lisp_Bool_Vector *) v)->size
+ + BOOL_VECTOR_BITS_PER_CHAR - 1)
+ / BOOL_VECTOR_BITS_PER_CHAR);
+ else
+ size = (header_size
+ + ((size & PSEUDOVECTOR_SIZE_MASK)
+ + ((size & PSEUDOVECTOR_REST_MASK)
+ >> PSEUDOVECTOR_SIZE_BITS)) * word_size);
+ }
+ else
+ size = header_size + size * word_size;
+ return vroundup (size);
+}
/* Reclaim space used by unmarked vectors. */
@@ -3081,7 +2807,8 @@ static void
sweep_vectors (void)
{
struct vector_block *block = vector_blocks, **bprev = &vector_blocks;
- struct Lisp_Vector *vector, *next, **vprev = &large_vectors;
+ struct large_vector *lv, **lvprev = &large_vectors;
+ struct Lisp_Vector *vector, *next;
total_vectors = total_vector_slots = total_free_vector_slots = 0;
memset (vector_free_lists, 0, sizeof (vector_free_lists));
@@ -3091,6 +2818,7 @@ sweep_vectors (void)
for (block = vector_blocks; block; block = *bprev)
{
bool free_this_block = 0;
+ ptrdiff_t nbytes;
for (vector = (struct Lisp_Vector *) block->data;
VECTOR_IN_BLOCK (vector, block); vector = next)
@@ -3099,13 +2827,13 @@ sweep_vectors (void)
{
VECTOR_UNMARK (vector);
total_vectors++;
- total_vector_slots += vector->header.next.nbytes / word_size;
- next = ADVANCE (vector, vector->header.next.nbytes);
+ nbytes = vector_nbytes (vector);
+ total_vector_slots += nbytes / word_size;
+ next = ADVANCE (vector, nbytes);
}
else
{
- ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector);
- ptrdiff_t total_bytes = nbytes;
+ ptrdiff_t total_bytes;
if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD))
finalize_one_thread ((struct thread_state *) vector);
@@ -3114,6 +2842,8 @@ sweep_vectors (void)
else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR))
finalize_one_condvar ((struct Lisp_CondVar *) vector);
+ nbytes = vector_nbytes (vector);
+ total_bytes = nbytes;
next = ADVANCE (vector, nbytes);
/* While NEXT is not marked, try to coalesce with VECTOR,
@@ -3123,7 +2853,7 @@ sweep_vectors (void)
{
if (VECTOR_MARKED_P (next))
break;
- nbytes = PSEUDOVECTOR_NBYTES (next);
+ nbytes = vector_nbytes (next);
total_bytes += nbytes;
next = ADVANCE (next, nbytes);
}
@@ -3157,8 +2887,9 @@ sweep_vectors (void)
/* Sweep large vectors. */
- for (vector = large_vectors; vector; vector = *vprev)
+ for (lv = large_vectors; lv; lv = *lvprev)
{
+ vector = &lv->v;
if (VECTOR_MARKED_P (vector))
{
VECTOR_UNMARK (vector);
@@ -3180,12 +2911,12 @@ sweep_vectors (void)
else
total_vector_slots
+= header_size / word_size + vector->header.size;
- vprev = &vector->header.next.vector;
+ lvprev = &lv->next.vector;
}
else
{
- *vprev = vector->header.next.vector;
- lisp_free (vector);
+ *lvprev = lv->next.vector;
+ lisp_free (lv);
}
}
}
@@ -3200,9 +2931,6 @@ allocate_vectorlike (ptrdiff_t len)
MALLOC_BLOCK_INPUT;
- /* This gets triggered by code which I haven't bothered to fix. --Stef */
- /* eassert (!handling_signal); */
-
if (len == 0)
p = XVECTOR (zero_vector);
else
@@ -3220,9 +2948,12 @@ allocate_vectorlike (ptrdiff_t len)
p = allocate_vector_from_block (vroundup (nbytes));
else
{
- p = lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE);
- p->header.next.vector = large_vectors;
- large_vectors = p;
+ struct large_vector *lv
+ = lisp_malloc (sizeof (*lv) + (len - 1) * word_size,
+ MEM_TYPE_VECTORLIKE);
+ lv->next.vector = large_vectors;
+ large_vectors = lv;
+ p = &lv->v;
}
#ifdef DOUG_LEA_MALLOC
@@ -3259,16 +2990,21 @@ allocate_vector (EMACS_INT len)
/* Allocate other vector-like structures. */
struct Lisp_Vector *
-allocate_pseudovector (int memlen, int lisplen, int tag)
+allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag)
{
struct Lisp_Vector *v = allocate_vectorlike (memlen);
int i;
+ /* Catch bogus values. */
+ eassert (tag <= PVEC_FONT);
+ 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;
- XSETPVECTYPESIZE (v, tag, lisplen);
+ XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
return v;
}
@@ -3277,9 +3013,11 @@ allocate_buffer (void)
{
struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER);
- XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text)
- - header_size) / word_size);
- /* Note that the fields of B are not initialized. */
+ BUFFER_PVEC_INIT (b);
+ /* Put B on the chain of all buffers including killed ones. */
+ b->next = all_buffers;
+ all_buffers = b;
+ /* Note that the rest fields of B are not initialized. */
return b;
}
@@ -3413,7 +3151,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
ptrdiff_t i;
register struct Lisp_Vector *p;
- /* We used to purecopy everything here, if purify-flga was set. This worked
+ /* We used to purecopy everything here, if purify-flag was set. This worked
OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
dangerous, since make-byte-code is used during execution to build
closures, so any closure built during the preload phase would end up
@@ -3476,7 +3214,7 @@ static struct Lisp_Symbol *symbol_free_list;
DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
doc: /* Return a newly allocated uninterned symbol whose name is NAME.
-Its value and function definition are void, and its property list is nil. */)
+Its value is void, and its function definition and property list are nil. */)
(Lisp_Object name)
{
register Lisp_Object val;
@@ -3484,8 +3222,6 @@ Its value and function definition are void, and its property list is nil. */)
CHECK_STRING (name);
- /* eassert (!handling_signal); */
-
MALLOC_BLOCK_INPUT;
if (symbol_free_list)
@@ -3515,7 +3251,7 @@ Its value and function definition are void, and its property list is nil. */)
set_symbol_plist (val, Qnil);
p->redirect = SYMBOL_PLAINVAL;
SET_SYMBOL_VAL (p, Qunbound);
- set_symbol_function (val, Qunbound);
+ set_symbol_function (val, Qnil);
set_symbol_next (val, NULL);
p->gcmarkbit = 0;
p->interned = SYMBOL_UNINTERNED;
@@ -3570,8 +3306,6 @@ allocate_misc (enum Lisp_Misc_Type type)
{
Lisp_Object val;
- /* eassert (!handling_signal); */
-
MALLOC_BLOCK_INPUT;
if (marker_free_list)
@@ -3633,6 +3367,19 @@ make_save_value (void *pointer, ptrdiff_t integer)
return val;
}
+/* Free a Lisp_Misc_Save_Value object. */
+
+void
+free_save_value (Lisp_Object save)
+{
+ register struct Lisp_Save_Value *p = XSAVE_VALUE (save);
+
+ p->dogc = 0;
+ xfree (p->pointer);
+ p->pointer = NULL;
+ free_misc (save);
+}
+
/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */
Lisp_Object
@@ -3675,7 +3422,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
struct Lisp_Marker *m;
/* No dead buffers here. */
- eassert (!NILP (BVAR (buf, name)));
+ eassert (BUFFER_LIVE_P (buf));
/* Every character is at least one byte. */
eassert (charpos <= bytepos);
@@ -3791,12 +3538,6 @@ memory_full (size_t nbytes)
lisp_free (spare_memory[i]);
spare_memory[i] = 0;
}
-
- /* Record the space now used. When it decreases substantially,
- we can refill the memory reserve. */
-#if !defined SYSTEM_MALLOC && !defined SYNC_INPUT
- bytes_used_when_full = BYTES_USED;
-#endif
}
/* This used to call error, but if we've run out of memory, we could
@@ -3873,7 +3614,7 @@ mem_init (void)
/* Value is a pointer to the mem_node containing START. Value is
MEM_NIL if there is no node in the tree containing START. */
-static inline struct mem_node *
+static struct mem_node *
mem_find (void *start)
{
struct mem_node *p;
@@ -3917,7 +3658,7 @@ mem_insert (void *start, void *end, enum mem_type type)
while (c != MEM_NIL)
{
if (start >= c->start && start < c->end)
- abort ();
+ emacs_abort ();
parent = c;
c = start < c->start ? c->left : c->right;
}
@@ -3934,9 +3675,9 @@ mem_insert (void *start, void *end, enum mem_type type)
/* Create a new node. */
#ifdef GC_MALLOC_CHECK
- x = _malloc_internal (sizeof *x);
+ x = malloc (sizeof *x);
if (x == NULL)
- abort ();
+ emacs_abort ();
#else
x = xmalloc (sizeof *x);
#endif
@@ -4158,7 +3899,7 @@ mem_delete (struct mem_node *z)
mem_delete_fixup (x);
#ifdef GC_MALLOC_CHECK
- _free_internal (y);
+ free (y);
#else
xfree (y);
#endif
@@ -4249,7 +3990,7 @@ mem_delete_fixup (struct mem_node *x)
/* Value is non-zero if P is a pointer to a live Lisp string on
the heap. M is a pointer to the mem_block for P. */
-static inline bool
+static bool
live_string_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_STRING)
@@ -4272,7 +4013,7 @@ live_string_p (struct mem_node *m, void *p)
/* Value is non-zero if P is a pointer to a live Lisp cons on
the heap. M is a pointer to the mem_block for P. */
-static inline bool
+static bool
live_cons_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_CONS)
@@ -4298,7 +4039,7 @@ live_cons_p (struct mem_node *m, void *p)
/* Value is non-zero if P is a pointer to a live Lisp symbol on
the heap. M is a pointer to the mem_block for P. */
-static inline bool
+static bool
live_symbol_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_SYMBOL)
@@ -4324,7 +4065,7 @@ live_symbol_p (struct mem_node *m, void *p)
/* Value is non-zero if P is a pointer to a live Lisp float on
the heap. M is a pointer to the mem_block for P. */
-static inline bool
+static bool
live_float_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_FLOAT)
@@ -4348,7 +4089,7 @@ live_float_p (struct mem_node *m, void *p)
/* Value is non-zero if P is a pointer to a live Lisp Misc on
the heap. M is a pointer to the mem_block for P. */
-static inline bool
+static bool
live_misc_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_MISC)
@@ -4374,7 +4115,7 @@ live_misc_p (struct mem_node *m, void *p)
/* Value is non-zero if P is a pointer to a live vector-like object.
M is a pointer to the mem_block for P. */
-static inline bool
+static bool
live_vector_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_VECTOR_BLOCK)
@@ -4391,16 +4132,15 @@ live_vector_p (struct mem_node *m, void *p)
while (VECTOR_IN_BLOCK (vector, block)
&& vector <= (struct Lisp_Vector *) p)
{
- if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
- vector = ADVANCE (vector, (vector->header.size
- & PSEUDOVECTOR_SIZE_MASK));
- else if (vector == p)
+ if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p)
return 1;
else
- vector = ADVANCE (vector, vector->header.next.nbytes);
+ vector = ADVANCE (vector, vector_nbytes (vector));
}
}
- else if (m->type == MEM_TYPE_VECTORLIKE && p == m->start)
+ else if (m->type == MEM_TYPE_VECTORLIKE
+ && (char *) p == ((char *) m->start
+ + offsetof (struct large_vector, v)))
/* This memory node corresponds to a large vector. */
return 1;
return 0;
@@ -4410,7 +4150,7 @@ live_vector_p (struct mem_node *m, void *p)
/* Value is non-zero if P is a pointer to a live buffer. M is a
pointer to the mem_block for P. */
-static inline bool
+static bool
live_buffer_p (struct mem_node *m, void *p)
{
/* P must point to the start of the block, and the buffer
@@ -4476,7 +4216,7 @@ DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "",
/* Mark OBJ if we can prove it's a Lisp_Object. */
-static inline void
+static void
mark_maybe_object (Lisp_Object obj)
{
void *po;
@@ -4545,7 +4285,7 @@ mark_maybe_object (Lisp_Object obj)
/* If P points to Lisp data, mark that as live if it isn't already
marked. */
-static inline void
+static void
mark_maybe_pointer (void *p)
{
struct mem_node *m;
@@ -4611,7 +4351,7 @@ mark_maybe_pointer (void *p)
break;
default:
- abort ();
+ emacs_abort ();
}
if (!NILP (obj))
@@ -4755,14 +4495,14 @@ test_setjmp (void)
{
char buf[10];
register int x;
- jmp_buf jbuf;
+ sys_jmp_buf jbuf;
/* Arrange for X to be put in a register. */
sprintf (buf, "1");
x = strlen (buf);
x = 2 * x - 1;
- _setjmp (jbuf);
+ sys_setjmp (jbuf);
if (longjmps_done == 1)
{
/* Came here after the longjmp at the end of the function.
@@ -4787,7 +4527,7 @@ test_setjmp (void)
++longjmps_done;
x = 2;
if (longjmps_done == 1)
- _longjmp (jbuf, 1);
+ sys_longjmp (jbuf, 1);
}
#endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */
@@ -4808,7 +4548,7 @@ check_gcpros (void)
if (!survives_gc_p (p->var[i]))
/* FIXME: It's not necessarily a bug. It might just be that the
GCPRO is unnecessary or should release the object sooner. */
- abort ();
+ emacs_abort ();
}
#elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
@@ -4912,7 +4652,7 @@ flush_stack_call_func (void (*func) (void *arg), void *arg)
/* jmp_buf may not be aligned enough on darwin-ppc64 */
union aligned_jmpbuf {
Lisp_Object o;
- jmp_buf j;
+ sys_jmp_buf j;
} j;
volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom;
#endif
@@ -4948,7 +4688,7 @@ flush_stack_call_func (void (*func) (void *arg), void *arg)
}
#endif /* GC_SETJMP_WORKS */
- _setjmp (j.j);
+ 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 */
@@ -4986,7 +4726,8 @@ valid_pointer_p (void *p)
#endif
}
-/* Return 1 if OBJ is a valid lisp object.
+/* Return 2 if OBJ is a killed or special buffer object.
+ Return 1 if OBJ is a valid lisp object.
Return 0 if OBJ is NOT a valid lisp object.
Return -1 if we cannot validate OBJ.
This function can be quite slow,
@@ -5007,6 +4748,9 @@ valid_lisp_object_p (Lisp_Object obj)
if (PURE_POINTER_P (p))
return 1;
+ if (p == &buffer_defaults || p == &buffer_local_symbols)
+ return 2;
+
#if !GC_MARK_STACK
return valid_pointer_p (p);
#else
@@ -5032,7 +4776,7 @@ valid_lisp_object_p (Lisp_Object obj)
return 0;
case MEM_TYPE_BUFFER:
- return live_buffer_p (m, p);
+ return live_buffer_p (m, p) ? 1 : 2;
case MEM_TYPE_CONS:
return live_cons_p (m, p);
@@ -5356,7 +5100,7 @@ staticpro (Lisp_Object *varaddress)
{
staticvec[staticidx++] = varaddress;
if (staticidx >= NSTATICS)
- abort ();
+ fatal ("NSTATICS too small; try increasing and recompiling Emacs.");
}
@@ -5378,12 +5122,29 @@ inhibit_garbage_collection (void)
/* Used to avoid possible overflows when
converting from C to Lisp integers. */
-static inline Lisp_Object
+static Lisp_Object
bounded_number (EMACS_INT number)
{
return make_number (min (MOST_POSITIVE_FIXNUM, number));
}
+/* Calculate total bytes of live objects. */
+
+static size_t
+total_bytes_of_live_objects (void)
+{
+ size_t tot = 0;
+ tot += total_conses * sizeof (struct Lisp_Cons);
+ tot += total_symbols * sizeof (struct Lisp_Symbol);
+ tot += total_markers * sizeof (union Lisp_Misc);
+ tot += total_string_bytes;
+ tot += total_vector_slots * word_size;
+ tot += total_floats * sizeof (struct Lisp_Float);
+ tot += total_intervals * sizeof (struct interval);
+ tot += total_strings * sizeof (struct Lisp_String);
+ return tot;
+}
+
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
@@ -5409,15 +5170,25 @@ See Info node `(elisp)Garbage Collection'. */)
ptrdiff_t count = SPECPDL_INDEX ();
EMACS_TIME start;
Lisp_Object retval = Qnil;
+ size_t tot_before = 0;
+ struct backtrace backtrace;
if (abort_on_gc)
- abort ();
+ emacs_abort ();
/* Can't GC if pure storage overflowed because we can't determine
if something is a pure object or not. */
if (pure_bytes_used_before_overflow)
return Qnil;
+ /* Record this function, so it appears on the profiler's backtraces. */
+ backtrace.next = backtrace_list;
+ backtrace.function = Qautomatic_gc;
+ backtrace.args = &Qnil;
+ backtrace.nargs = 0;
+ backtrace.debug_on_exit = 0;
+ backtrace_list = &backtrace;
+
check_cons_list ();
/* Don't keep undo information around forever.
@@ -5425,6 +5196,9 @@ See Info node `(elisp)Garbage Collection'. */)
FOR_EACH_BUFFER (nextb)
compact_buffer (nextb);
+ if (profiler_memory_running)
+ tot_before = total_bytes_of_live_objects ();
+
start = current_emacs_time ();
/* In case user calls debug_print during GC,
@@ -5466,7 +5240,7 @@ See Info node `(elisp)Garbage Collection'. */)
if (garbage_collection_messages)
message1_nolog ("Garbage collecting...");
- BLOCK_INPUT;
+ block_input ();
shrink_regexp_cache ();
@@ -5474,6 +5248,9 @@ See Info node `(elisp)Garbage Collection'. */)
/* Mark all the special slots that serve as the roots of accessibility. */
+ mark_buffer (&buffer_defaults);
+ mark_buffer (&buffer_local_symbols);
+
for (i = 0; i < staticidx; i++)
mark_object (*staticvec[i]);
@@ -5548,12 +5325,12 @@ See Info node `(elisp)Garbage Collection'. */)
dump_zombies ();
#endif
- UNBLOCK_INPUT;
-
check_cons_list ();
gc_in_progress = 0;
+ unblock_input ();
+
consing_since_gc = 0;
if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10)
gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10;
@@ -5561,16 +5338,7 @@ See Info node `(elisp)Garbage Collection'. */)
gc_relative_threshold = 0;
if (FLOATP (Vgc_cons_percentage))
{ /* Set gc_cons_combined_threshold. */
- double tot = 0;
-
- tot += total_conses * sizeof (struct Lisp_Cons);
- tot += total_symbols * sizeof (struct Lisp_Symbol);
- tot += total_markers * sizeof (union Lisp_Misc);
- tot += total_string_bytes;
- tot += total_vector_slots * word_size;
- tot += total_floats * sizeof (struct Lisp_Float);
- tot += total_intervals * sizeof (struct interval);
- tot += total_strings * sizeof (struct Lisp_String);
+ double tot = total_bytes_of_live_objects ();
tot *= XFLOAT_DATA (Vgc_cons_percentage);
if (0 < tot)
@@ -5673,6 +5441,17 @@ See Info node `(elisp)Garbage Collection'. */)
gcs_done++;
+ /* Collect profiling data. */
+ if (profiler_memory_running)
+ {
+ size_t swept = 0;
+ size_t tot_after = total_bytes_of_live_objects ();
+ if (tot_before > tot_after)
+ swept = tot_before - tot_after;
+ malloc_probe (swept);
+ }
+
+ backtrace_list = backtrace.next;
return retval;
}
@@ -5826,6 +5605,33 @@ mark_buffer (struct buffer *buffer)
mark_buffer (buffer->base_buffer);
}
+/* Remove killed buffers or items whose car is a killed buffer from
+ LIST, and mark other items. Return changed LIST, which is marked. */
+
+static Lisp_Object
+mark_discard_killed_buffers (Lisp_Object list)
+{
+ Lisp_Object tail, *prev = &list;
+
+ for (tail = list; CONSP (tail) && !CONS_MARKED_P (XCONS (tail));
+ tail = XCDR (tail))
+ {
+ Lisp_Object tem = XCAR (tail);
+ if (CONSP (tem))
+ tem = XCAR (tem);
+ if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem)))
+ *prev = XCDR (tail);
+ else
+ {
+ CONS_MARK (XCONS (tail));
+ mark_object (XCAR (tail));
+ prev = &XCDR_AS_LVALUE (tail);
+ }
+ }
+ mark_object (tail);
+ return list;
+}
+
/* Determine type of generic Lisp_Object and mark it accordingly. */
void
@@ -5860,7 +5666,7 @@ mark_object (Lisp_Object arg)
do { \
m = mem_find (po); \
if (m == MEM_NIL) \
- abort (); \
+ emacs_abort (); \
} while (0)
/* Check that the object pointed to by PO is live, using predicate
@@ -5868,7 +5674,7 @@ mark_object (Lisp_Object arg)
#define CHECK_LIVE(LIVEP) \
do { \
if (!LIVEP (m, po)) \
- abort (); \
+ emacs_abort (); \
} while (0)
/* Check both of the above conditions. */
@@ -5913,17 +5719,15 @@ mark_object (Lisp_Object arg)
#ifdef GC_CHECK_MARKED_OBJECTS
m = mem_find (po);
- if (m == MEM_NIL && !SUBRP (obj)
- && po != &buffer_defaults
- && po != &buffer_local_symbols)
- abort ();
+ if (m == MEM_NIL && !SUBRP (obj))
+ emacs_abort ();
#endif /* GC_CHECK_MARKED_OBJECTS */
if (ptr->header.size & PSEUDOVECTOR_FLAG)
pvectype = ((ptr->header.size & PVEC_TYPE_MASK)
- >> PSEUDOVECTOR_SIZE_BITS);
+ >> PSEUDOVECTOR_AREA_BITS);
else
- pvectype = 0;
+ pvectype = PVEC_NORMAL_VECTOR;
if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER)
CHECK_LIVE (live_vector_p);
@@ -5932,15 +5736,14 @@ mark_object (Lisp_Object arg)
{
case PVEC_BUFFER:
#ifdef GC_CHECK_MARKED_OBJECTS
- if (po != &buffer_defaults && po != &buffer_local_symbols)
- {
- struct buffer *b;
- FOR_EACH_BUFFER (b)
- if (b == po)
- break;
- if (b == NULL)
- abort ();
- }
+ {
+ struct buffer *b;
+ FOR_EACH_BUFFER (b)
+ if (b == po)
+ break;
+ if (b == NULL)
+ emacs_abort ();
+ }
#endif /* GC_CHECK_MARKED_OBJECTS */
mark_buffer ((struct buffer *) ptr);
break;
@@ -5965,26 +5768,34 @@ mark_object (Lisp_Object arg)
break;
case PVEC_FRAME:
- {
- mark_vectorlike (ptr);
- mark_face_cache (((struct frame *) ptr)->face_cache);
- }
+ mark_vectorlike (ptr);
+ mark_face_cache (((struct frame *) ptr)->face_cache);
break;
case PVEC_WINDOW:
{
struct window *w = (struct window *) ptr;
+ bool leaf = NILP (w->hchild) && NILP (w->vchild);
mark_vectorlike (ptr);
+
/* Mark glyphs for leaf windows. Marking window
matrices is sufficient because frame matrices
use the same glyph memory. */
- if (NILP (w->hchild) && NILP (w->vchild)
- && w->current_matrix)
+ if (leaf && w->current_matrix)
{
mark_glyph_matrix (w->current_matrix);
mark_glyph_matrix (w->desired_matrix);
}
+
+ /* Filter out killed buffers from both buffer lists
+ in attempt to help GC to reclaim killed buffers faster.
+ We can do it elsewhere for live windows, but this is the
+ best place to do it for dead windows. */
+ wset_prev_buffers
+ (w, mark_discard_killed_buffers (w->prev_buffers));
+ wset_next_buffers
+ (w, mark_discard_killed_buffers (w->next_buffers));
}
break;
@@ -5993,6 +5804,9 @@ mark_object (Lisp_Object arg)
struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
mark_vectorlike (ptr);
+ mark_object (h->test.name);
+ mark_object (h->test.user_hash_function);
+ mark_object (h->test.user_cmp_function);
/* If hash table is not weak, mark all keys and values.
For weak tables, mark only the vector. */
if (NILP (h->weak))
@@ -6015,7 +5829,7 @@ mark_object (Lisp_Object arg)
break;
case PVEC_FREE:
- abort ();
+ emacs_abort ();
default:
mark_vectorlike (ptr);
@@ -6047,10 +5861,14 @@ mark_object (Lisp_Object arg)
case SYMBOL_LOCALIZED:
{
struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
- /* If the value is forwarded to a buffer or keyboard field,
- these are marked when we see the corresponding object.
- And if it's forwarded to a C variable, either it's not
- a Lisp_Object var, or it's staticpro'd already. */
+ 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);
@@ -6062,7 +5880,7 @@ mark_object (Lisp_Object arg)
And if it's forwarded to a C variable, either it's not
a Lisp_Object var, or it's staticpro'd already. */
break;
- default: abort ();
+ default: emacs_abort ();
}
if (!PURE_POINTER_P (XSTRING (ptr->name)))
MARK_STRING (XSTRING (ptr->name));
@@ -6116,7 +5934,7 @@ mark_object (Lisp_Object arg)
break;
default:
- abort ();
+ emacs_abort ();
}
break;
@@ -6138,7 +5956,7 @@ mark_object (Lisp_Object arg)
obj = ptr->u.cdr;
cdr_count++;
if (cdr_count == mark_object_loop_halt)
- abort ();
+ emacs_abort ();
goto loop;
}
@@ -6151,7 +5969,7 @@ mark_object (Lisp_Object arg)
break;
default:
- abort ();
+ emacs_abort ();
}
#undef CHECK_LIVE
@@ -6220,7 +6038,7 @@ survives_gc_p (Lisp_Object obj)
break;
default:
- abort ();
+ emacs_abort ();
}
return survives_p || PURE_POINTER_P ((void *) XPNTR (obj));
@@ -6534,19 +6352,14 @@ gc_sweep (void)
/* Free all unmarked buffers */
{
- register struct buffer *buffer = all_buffers, *prev = 0, *next;
+ register struct buffer *buffer, **bprev = &all_buffers;
total_buffers = 0;
- while (buffer)
+ for (buffer = all_buffers; buffer; buffer = *bprev)
if (!VECTOR_MARKED_P (buffer))
{
- if (prev)
- prev->header.next = buffer->header.next;
- else
- all_buffers = buffer->header.next.buffer;
- next = buffer->header.next.buffer;
+ *bprev = buffer->next;
lisp_free (buffer);
- buffer = next;
}
else
{
@@ -6554,7 +6367,7 @@ gc_sweep (void)
/* Do not use buffer_(set|get)_intervals here. */
buffer->text->intervals = balance_intervals (buffer->text->intervals);
total_buffers++;
- prev = buffer, buffer = buffer->header.next.buffer;
+ bprev = &buffer->next;
}
}
@@ -6658,21 +6471,14 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
#ifdef ENABLE_CHECKING
-# include <execinfo.h>
-
bool suppress_checking;
void
die (const char *msg, const char *file, int line)
{
- enum { NPOINTERS_MAX = 500 };
- void *buffer[NPOINTERS_MAX];
- int npointers;
fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n",
file, line, msg);
- npointers = backtrace (buffer, NPOINTERS_MAX);
- backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
- abort ();
+ terminate_due_to_signal (SIGABRT, INT_MAX);
}
#endif
@@ -6698,12 +6504,6 @@ init_alloc_once (void)
init_strings ();
init_vectors ();
-#ifdef REL_ALLOC
- malloc_hysteresis = 32;
-#else
- malloc_hysteresis = 0;
-#endif
-
refill_memory_reserve ();
gc_cons_threshold = GC_DEFAULT_THRESHOLD;
}
@@ -6810,6 +6610,7 @@ do hash-consing of the objects allocated to pure space. */);
DEFSYM (Qstring_bytes, "string-bytes");
DEFSYM (Qvector_slots, "vector-slots");
DEFSYM (Qheap, "heap");
+ DEFSYM (Qautomatic_gc, "Automatic GC");
DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
@@ -6843,7 +6644,8 @@ The time is in seconds as a floating point value. */);
/* When compiled with GCC, GDB might say "No enum type named
pvec_type" if we don't have at least one symbol with that type, and
then xbacktrace could fail. Similarly for the other enums and
- their values. */
+ their values. Some non-GCC compilers don't like these constructs. */
+#ifdef __GNUC__
union
{
enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS;
@@ -6863,3 +6665,4 @@ union
enum lsb_bits lsb_bits;
#endif
} const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
+#endif /* __GNUC__ */
diff --git a/src/atimer.c b/src/atimer.c
index eb3136ae55d..5752192be76 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -17,9 +17,8 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "syssignal.h"
#include "systime.h"
@@ -41,18 +40,33 @@ static struct atimer *stopped_atimers;
static struct atimer *atimers;
-/* Non-zero means alarm_signal_handler has found ripe timers but
- interrupt_input_blocked was non-zero. In this case, timer
- functions are not called until the next UNBLOCK_INPUT because timer
- functions are expected to call X, and X cannot be assumed to be
- reentrant. */
-
-int pending_atimers;
+/* 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;
+#endif
/* Block/unblock SIGALRM. */
-#define BLOCK_ATIMERS sigblock (sigmask (SIGALRM))
-#define UNBLOCK_ATIMERS sigunblock (sigmask (SIGALRM))
+static void
+sigmask_atimers (int how)
+{
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGALRM);
+ pthread_sigmask (how, &blocked, 0);
+}
+static void
+block_atimers (void)
+{
+ sigmask_atimers (SIG_BLOCK);
+}
+static void
+unblock_atimers (void)
+{
+ sigmask_atimers (SIG_UNBLOCK);
+}
/* Function prototypes. */
@@ -60,8 +74,6 @@ static void set_alarm (void);
static void schedule_atimer (struct atimer *);
static struct atimer *append_atimer_lists (struct atimer *,
struct atimer *);
-static void alarm_signal_handler (int signo);
-
/* Start a new atimer of type TYPE. TIME specifies when the timer is
ripe. FN is the function to call when the timer fires.
@@ -111,7 +123,7 @@ start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn,
t->fn = fn;
t->client_data = client_data;
- BLOCK_ATIMERS;
+ block_atimers ();
/* Compute the timer's expiration time. */
switch (type)
@@ -132,7 +144,7 @@ start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn,
/* Insert the timer in the list of active atimers. */
schedule_atimer (t);
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
/* Arrange for a SIGALRM at the time the next atimer is ripe. */
set_alarm ();
@@ -148,7 +160,7 @@ cancel_atimer (struct atimer *timer)
{
int i;
- BLOCK_ATIMERS;
+ block_atimers ();
for (i = 0; i < 2; ++i)
{
@@ -175,7 +187,7 @@ cancel_atimer (struct atimer *timer)
}
}
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
@@ -206,7 +218,7 @@ append_atimer_lists (struct atimer *list_1, struct atimer *list_2)
void
stop_other_atimers (struct atimer *t)
{
- BLOCK_ATIMERS;
+ block_atimers ();
if (t)
{
@@ -231,7 +243,7 @@ stop_other_atimers (struct atimer *t)
stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
atimers = t;
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
@@ -246,7 +258,7 @@ run_all_atimers (void)
struct atimer *t = atimers;
struct atimer *next;
- BLOCK_ATIMERS;
+ block_atimers ();
atimers = stopped_atimers;
stopped_atimers = NULL;
@@ -257,7 +269,7 @@ run_all_atimers (void)
t = next;
}
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
}
@@ -282,14 +294,25 @@ set_alarm (void)
#ifdef HAVE_SETITIMER
struct itimerval it;
#endif
+ EMACS_TIME now, interval;
- /* Determine s/us till the next timer is ripe. */
- EMACS_TIME now = current_emacs_time ();
+#ifdef HAVE_ITIMERSPEC
+ if (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)
+ return;
+ }
+#endif
- /* Don't set the interval to 0; this disables the timer. */
- EMACS_TIME interval = (EMACS_TIME_LE (atimers->expiration, now)
- ? make_emacs_time (0, 1000 * 1000)
- : sub_emacs_time (atimers->expiration, now));
+ /* Determine interval till the next timer is ripe.
+ Don't set the interval to 0; this disables the timer. */
+ now = current_emacs_time ();
+ interval = (EMACS_TIME_LE (atimers->expiration, now)
+ ? make_emacs_time (0, 1000 * 1000)
+ : sub_emacs_time (atimers->expiration, now));
#ifdef HAVE_SETITIMER
@@ -328,16 +351,11 @@ schedule_atimer (struct atimer *t)
static void
run_timers (void)
{
- EMACS_TIME now;
+ EMACS_TIME now = current_emacs_time ();
- while (atimers
- && (pending_atimers = interrupt_input_blocked) == 0
- && (now = current_emacs_time (),
- EMACS_TIME_LE (atimers->expiration, now)))
+ while (atimers && EMACS_TIME_LE (atimers->expiration, now))
{
- struct atimer *t;
-
- t = atimers;
+ struct atimer *t = atimers;
atimers = atimers->next;
t->fn (t);
@@ -353,53 +371,30 @@ run_timers (void)
}
}
- if (! atimers)
- pending_atimers = 0;
-
-#ifdef SYNC_INPUT
- if (pending_atimers)
- pending_signals = 1;
- else
- {
- pending_signals = interrupt_input_pending;
- set_alarm ();
- }
-#else
- if (! pending_atimers)
- set_alarm ();
-#endif
+ set_alarm ();
}
/* Signal handler for SIGALRM. SIGNO is the signal number, i.e.
SIGALRM. */
-void
-alarm_signal_handler (int signo)
+static void
+handle_alarm_signal (int sig)
{
-#ifndef SYNC_INPUT
- SIGNAL_THREAD_CHECK (signo);
-#endif
-
- pending_atimers = 1;
-#ifdef SYNC_INPUT
pending_signals = 1;
-#else
- run_timers ();
-#endif
}
-/* Call alarm_signal_handler for pending timers. */
+/* Do pending timers. */
void
do_pending_atimers (void)
{
- if (pending_atimers)
+ if (atimers)
{
- BLOCK_ATIMERS;
+ block_atimers ();
run_timers ();
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
}
@@ -411,10 +406,7 @@ void
turn_on_atimers (bool on)
{
if (on)
- {
- signal (SIGALRM, alarm_signal_handler);
- set_alarm ();
- }
+ set_alarm ();
else
alarm (0);
}
@@ -423,8 +415,16 @@ turn_on_atimers (bool on)
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;
+#endif
free_atimers = stopped_atimers = atimers = NULL;
- pending_atimers = 0;
/* pending_signals is initialized in init_keyboard.*/
- signal (SIGALRM, alarm_signal_handler);
+ emacs_sigaction_init (&action, handle_alarm_signal);
+ sigaction (SIGALRM, &action, 0);
}
diff --git a/src/bidi.c b/src/bidi.c
index 6b3ac53d318..6f3d749ef22 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -56,7 +56,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -97,7 +96,7 @@ static Lisp_Object Qparagraph_start, Qparagraph_separate;
/* Return the bidi type of a character CH, subject to the current
directional OVERRIDE. */
-static inline bidi_type_t
+static bidi_type_t
bidi_get_type (int ch, bidi_dir_t override)
{
bidi_type_t default_type;
@@ -105,7 +104,7 @@ bidi_get_type (int ch, bidi_dir_t override)
if (ch == BIDI_EOB)
return NEUTRAL_B;
if (ch < 0 || ch > MAX_CHAR)
- abort ();
+ emacs_abort ();
default_type = (bidi_type_t) XINT (CHAR_TABLE_REF (bidi_type_table, ch));
/* Every valid character code, even those that are unassigned by the
@@ -113,7 +112,7 @@ bidi_get_type (int ch, bidi_dir_t override)
DerivedBidiClass.txt file. Therefore, if we ever get UNKNOWN_BT
(= zero) code from CHAR_TABLE_REF, that's a bug. */
if (default_type == UNKNOWN_BT)
- abort ();
+ emacs_abort ();
if (override == NEUTRAL_DIR)
return default_type;
@@ -141,19 +140,19 @@ bidi_get_type (int ch, bidi_dir_t override)
else if (override == R2L)
return STRONG_R;
else
- abort (); /* can't happen: handled above */
+ emacs_abort (); /* can't happen: handled above */
}
}
}
-static inline void
+static void
bidi_check_type (bidi_type_t type)
{
eassert (UNKNOWN_BT <= type && type <= NEUTRAL_ON);
}
/* Given a bidi TYPE of a character, return its category. */
-static inline bidi_category_t
+static bidi_category_t
bidi_get_category (bidi_type_t type)
{
switch (type)
@@ -183,7 +182,7 @@ bidi_get_category (bidi_type_t type)
case NEUTRAL_ON:
return NEUTRAL;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -199,7 +198,7 @@ bidi_mirror_char (int c)
if (c == BIDI_EOB)
return c;
if (c < 0 || c > MAX_CHAR)
- abort ();
+ emacs_abort ();
val = CHAR_TABLE_REF (bidi_mirror_table, c);
if (INTEGERP (val))
@@ -215,7 +214,7 @@ bidi_mirror_char (int c)
/* Minimal test we must do in optimized builds, to prevent weird
crashes further down the road. */
if (v < 0 || v > MAX_CHAR)
- abort ();
+ emacs_abort ();
return v;
}
@@ -227,7 +226,7 @@ bidi_mirror_char (int c)
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 inline void
+static void
bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after)
{
int higher_level = (level_before > level_after ? level_before : level_after);
@@ -258,7 +257,7 @@ bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after)
/* Push the current embedding level and override status; reset the
current level to LEVEL and the current override status to OVERRIDE. */
-static inline void
+static void
bidi_push_embedding_level (struct bidi_it *bidi_it,
int level, bidi_dir_t override)
{
@@ -270,7 +269,7 @@ bidi_push_embedding_level (struct bidi_it *bidi_it,
/* Pop the embedding level and directional override status from the
stack, and return the new level. */
-static inline int
+static int
bidi_pop_embedding_level (struct bidi_it *bidi_it)
{
/* UAX#9 says to ignore invalid PDFs. */
@@ -280,7 +279,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
}
/* Record in SAVED_INFO the information about the current character. */
-static inline void
+static void
bidi_remember_char (struct bidi_saved_info *saved_info,
struct bidi_it *bidi_it)
{
@@ -296,18 +295,14 @@ bidi_remember_char (struct bidi_saved_info *saved_info,
/* Copy the bidi iterator from FROM to TO. To save cycles, this only
copies the part of the level stack that is actually in use. */
-static inline void
+static void
bidi_copy_it (struct bidi_it *to, struct bidi_it *from)
{
- int i;
-
- /* Copy everything except the level stack and beyond. */
- memcpy (to, from, offsetof (struct bidi_it, level_stack[0]));
-
- /* Copy the active part of the level stack. */
- to->level_stack[0] = from->level_stack[0]; /* level zero is always in use */
- for (i = 1; i <= from->stack_idx; i++)
- to->level_stack[i] = from->level_stack[i];
+ /* Copy everything from the start through the active part of
+ the level stack. */
+ memcpy (to, from,
+ (offsetof (struct bidi_it, level_stack[1])
+ + from->stack_idx * sizeof from->level_stack[0]));
}
@@ -345,7 +340,7 @@ enum
intact. This is called when the cached information is no more
useful for the current iteration, e.g. when we were reseated to a
new position on the same object. */
-static inline void
+static void
bidi_cache_reset (void)
{
bidi_cache_idx = bidi_cache_start;
@@ -356,7 +351,7 @@ bidi_cache_reset (void)
iterator for reordering a buffer or a string that does not come
from display properties, because that means all the previously
cached info is of no further use. */
-static inline void
+static void
bidi_cache_shrink (void)
{
if (bidi_cache_size > BIDI_CACHE_CHUNK)
@@ -367,13 +362,13 @@ bidi_cache_shrink (void)
bidi_cache_reset ();
}
-static inline void
+static void
bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it)
{
int current_scan_dir = bidi_it->scan_dir;
if (idx < bidi_cache_start || idx >= bidi_cache_idx)
- abort ();
+ emacs_abort ();
bidi_copy_it (bidi_it, &bidi_cache[idx]);
bidi_it->scan_dir = current_scan_dir;
@@ -384,7 +379,7 @@ bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it)
level less or equal to LEVEL. if LEVEL is -1, disregard the
resolved levels in cached states. DIR, if non-zero, means search
in that direction from the last cache hit. */
-static inline ptrdiff_t
+static ptrdiff_t
bidi_cache_search (ptrdiff_t charpos, int level, int dir)
{
ptrdiff_t i, i_start;
@@ -489,7 +484,7 @@ bidi_cache_find_level_change (int level, int dir, bool before)
return -1;
}
-static inline void
+static void
bidi_cache_ensure_space (ptrdiff_t idx)
{
/* Enlarge the cache as needed. */
@@ -511,14 +506,14 @@ bidi_cache_ensure_space (ptrdiff_t idx)
}
}
-static inline void
+static void
bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
{
ptrdiff_t idx;
/* We should never cache on backward scans. */
if (bidi_it->scan_dir == -1)
- abort ();
+ emacs_abort ();
idx = bidi_cache_search (bidi_it->charpos, -1, 1);
if (idx < 0)
@@ -537,7 +532,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
idx = bidi_cache_start;
}
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
bidi_copy_it (&bidi_cache[idx], bidi_it);
if (!resolved)
bidi_cache[idx].resolved_level = -1;
@@ -568,7 +563,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
bidi_cache_idx = idx + 1;
}
-static inline bidi_type_t
+static bidi_type_t
bidi_cache_find (ptrdiff_t charpos, int level, struct bidi_it *bidi_it)
{
ptrdiff_t i = bidi_cache_search (charpos, level, bidi_it->scan_dir);
@@ -588,11 +583,11 @@ bidi_cache_find (ptrdiff_t charpos, int level, struct bidi_it *bidi_it)
return UNKNOWN_BT;
}
-static inline int
+static int
bidi_peek_at_next_level (struct bidi_it *bidi_it)
{
if (bidi_cache_idx == bidi_cache_start || bidi_cache_last_idx == -1)
- abort ();
+ emacs_abort ();
return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level;
}
@@ -612,7 +607,7 @@ bidi_push_it (struct bidi_it *bidi_it)
/* Save the current iterator state in its entirety after the last
used cache slot. */
bidi_cache_ensure_space (bidi_cache_idx);
- memcpy (&bidi_cache[bidi_cache_idx++], bidi_it, sizeof (struct bidi_it));
+ bidi_cache[bidi_cache_idx++] = *bidi_it;
/* Push the current cache start onto the stack. */
eassert (bidi_cache_sp < IT_STACK_SIZE);
@@ -629,18 +624,18 @@ void
bidi_pop_it (struct bidi_it *bidi_it)
{
if (bidi_cache_start <= 0)
- abort ();
+ emacs_abort ();
/* Reset the next free cache slot index to what it was before the
call to bidi_push_it. */
bidi_cache_idx = bidi_cache_start - 1;
/* Restore the bidi iterator state saved in the cache. */
- memcpy (bidi_it, &bidi_cache[bidi_cache_idx], sizeof (struct bidi_it));
+ *bidi_it = bidi_cache[bidi_cache_idx];
/* Pop the previous cache start from the stack. */
if (bidi_cache_sp <= 0)
- abort ();
+ emacs_abort ();
bidi_cache_start = bidi_cache_start_stack[--bidi_cache_sp];
/* Invalidate the last-used cache slot data. */
@@ -762,12 +757,12 @@ bidi_initialize (void)
{
bidi_type_table = uniprop_table (intern ("bidi-class"));
if (NILP (bidi_type_table))
- abort ();
+ emacs_abort ();
staticpro (&bidi_type_table);
bidi_mirror_table = uniprop_table (intern ("mirroring"));
if (NILP (bidi_mirror_table))
- abort ();
+ emacs_abort ();
staticpro (&bidi_mirror_table);
Qparagraph_start = intern ("paragraph-start");
@@ -791,7 +786,7 @@ bidi_initialize (void)
/* Do whatever UAX#9 clause X8 says should be done at paragraph's
end. */
-static inline void
+static void
bidi_set_paragraph_end (struct bidi_it *bidi_it)
{
bidi_it->invalid_levels = 0;
@@ -873,7 +868,7 @@ bidi_line_init (struct bidi_it *bidi_it)
/* Count bytes in string S between BEG/BEGBYTE and END. BEG and END
are zero-based character positions in S, BEGBYTE is byte position
corresponding to BEG. UNIBYTE means S is a unibyte string. */
-static inline ptrdiff_t
+static ptrdiff_t
bidi_count_bytes (const unsigned char *s, const ptrdiff_t beg,
const ptrdiff_t begbyte, const ptrdiff_t end, bool unibyte)
{
@@ -885,7 +880,7 @@ bidi_count_bytes (const unsigned char *s, const ptrdiff_t beg,
else
{
if (!CHAR_HEAD_P (*p))
- abort ();
+ emacs_abort ();
while (pos < end)
{
@@ -897,22 +892,22 @@ bidi_count_bytes (const unsigned char *s, const ptrdiff_t beg,
return p - start;
}
-/* Fetch and returns the character at byte position BYTEPOS. If S is
+/* Fetch and return the character at byte position BYTEPOS. If S is
non-NULL, fetch the character from string S; otherwise fetch the
character from the current buffer. UNIBYTE means S is a
unibyte string. */
-static inline int
+static int
bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, bool unibyte)
{
if (s)
{
+ s += bytepos;
if (unibyte)
- return s[bytepos];
- else
- return STRING_CHAR (s + bytepos);
+ return *s;
}
else
- return FETCH_MULTIBYTE_CHAR (bytepos);
+ s = BYTE_POS_ADDR (bytepos);
+ return STRING_CHAR (s);
}
/* Fetch and return the character at BYTEPOS/CHARPOS. If that
@@ -929,7 +924,7 @@ bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, bool unibyte)
u+2029 to handle it as a paragraph separator. STRING->s is the C
string to iterate, or NULL if iterating over a buffer or a Lisp
string; in the latter case, STRING->lstring is the Lisp string. */
-static inline int
+static int
bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos,
int *disp_prop, struct bidi_string_data *string,
bool frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars)
@@ -965,7 +960,7 @@ bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos,
/* We don't expect to find ourselves in the middle of a display
property. Hopefully, it will never be needed. */
if (charpos > *disp_pos)
- abort ();
+ emacs_abort ();
/* Text covered by `display' properties and overlays with
display properties or display strings is handled as a single
character that represents the entire run of characters
@@ -995,7 +990,7 @@ bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos,
}
*nchars = disp_end_pos - *disp_pos;
if (*nchars <= 0)
- abort ();
+ emacs_abort ();
if (string->s)
*ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos,
disp_end_pos, string->unibyte);
@@ -1160,7 +1155,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
dir = L2R;
/* We should never be called at EOB or before BEGV. */
else if (bidi_it->charpos >= end || bytepos < begbyte)
- abort ();
+ emacs_abort ();
if (dir == L2R)
{
@@ -1298,7 +1293,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
&& no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR);
}
else
- abort ();
+ emacs_abort ();
/* Contrary to UAX#9 clause P3, we only default the paragraph
direction to L2R if we have no previous usable paragraph
@@ -1319,13 +1314,13 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
The rest of this file constitutes the core of the UBA implementation.
***********************************************************************/
-static inline bool
+static bool
bidi_explicit_dir_char (int ch)
{
bidi_type_t ch_type;
if (!bidi_initialized)
- abort ();
+ emacs_abort ();
ch_type = (bidi_type_t) XINT (CHAR_TABLE_REF (bidi_type_table, ch));
return (ch_type == LRE || ch_type == LRO
|| ch_type == RLE || ch_type == RLO
@@ -1378,10 +1373,10 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
/* Advance to the next character, skipping characters covered by
display strings (nchars > 1). */
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
bidi_it->charpos += bidi_it->nchars;
if (bidi_it->ch_len == 0)
- abort ();
+ emacs_abort ();
bidi_it->bytepos += bidi_it->ch_len;
}
@@ -1581,7 +1576,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
}
if (bidi_it->nchars <= 0)
- abort ();
+ 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 */
@@ -1644,7 +1639,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
|| type == RLE
|| type == RLO
|| type == PDF)
- abort ();
+ emacs_abort ();
if (new_level != prev_level
|| bidi_it->type == NEUTRAL_B)
@@ -1685,7 +1680,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
else if (bidi_it->sor == L2R)
type = STRONG_L;
else /* shouldn't happen! */
- abort ();
+ emacs_abort ();
}
if (type == WEAK_EN /* W2 */
&& bidi_it->last_strong.type_after_w1 == STRONG_AL)
@@ -1767,7 +1762,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
: bidi_it->string.s);
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
next_char
= (bidi_it->charpos + bidi_it->nchars >= eob
? BIDI_EOB
@@ -1842,7 +1837,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
/* Resolve the type of a neutral character according to the type of
surrounding strong text and the current embedding level. */
-static inline bidi_type_t
+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. */
@@ -1875,7 +1870,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
|| type == NEUTRAL_S
|| type == NEUTRAL_WS
|| type == NEUTRAL_ON))
- abort ();
+ emacs_abort ();
if ((type != NEUTRAL_B /* Don't risk entering the long loop below if
we are already at paragraph end. */
@@ -1930,7 +1925,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
bidi_type_t next_type;
if (bidi_it->scan_dir == -1)
- abort ();
+ emacs_abort ();
bidi_copy_it (&saved_it, bidi_it);
/* Scan the text forward until we find the first non-neutral
@@ -1979,7 +1974,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
break;
case WEAK_BN:
if (!bidi_explicit_dir_char (bidi_it->ch))
- abort (); /* can't happen: BNs are skipped */
+ emacs_abort (); /* can't happen: BNs are skipped */
/* FALLTHROUGH */
case NEUTRAL_B:
/* Marched all the way to the end of this level run.
@@ -1998,7 +1993,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
}
break;
default:
- abort ();
+ emacs_abort ();
}
type = bidi_resolve_neutral_1 (saved_it.prev_for_neutral.type,
next_type, current_level);
@@ -2023,7 +2018,7 @@ bidi_type_of_next_char (struct bidi_it *bidi_it)
/* This should always be called during a forward scan. */
if (bidi_it->scan_dir != 1)
- abort ();
+ emacs_abort ();
/* Reset the limit until which to ignore BNs if we step out of the
area where we found only empty levels. */
@@ -2107,7 +2102,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
if (bidi_it->scan_dir > 0)
{
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
next_char_pos = bidi_it->charpos + bidi_it->nchars;
}
else if (bidi_it->charpos >= bob)
@@ -2143,7 +2138,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
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. */
- abort ();
+ emacs_abort ();
if (type == UNKNOWN_BT)
type = bidi_type_of_next_char (bidi_it);
@@ -2156,7 +2151,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
|| (type == WEAK_BN && prev_level == level))
{
if (bidi_it->next_for_neutral.type == UNKNOWN_BT)
- abort ();
+ emacs_abort ();
/* If the cached state shows a neutral character, it was not
resolved by bidi_resolve_neutral, so do it now. */
@@ -2170,7 +2165,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
|| type == WEAK_BN
|| type == WEAK_EN
|| type == WEAK_AN))
- abort ();
+ emacs_abort ();
bidi_it->type = type;
bidi_check_type (bidi_it->type);
@@ -2192,7 +2187,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
int dpp = bidi_it->disp_prop;
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
do {
ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &dpp, &bs,
fwp, &clen, &nc);
@@ -2301,8 +2296,9 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag)
{
int new_level;
+ /* If we are at end of level, its edges must be cached. */
if (end_flag)
- abort (); /* if we are at end of level, its edges must be cached */
+ emacs_abort ();
bidi_cache_iterator_state (bidi_it, 1);
do {
@@ -2320,7 +2316,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
struct gcpro gcpro1;
if (bidi_it->charpos < 0 || bidi_it->bytepos < 0)
- abort ();
+ emacs_abort ();
if (bidi_it->scan_dir == 0)
{
@@ -2431,7 +2427,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
= bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars,
bidi_it->bytepos + bidi_it->ch_len);
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
if (sep_len >= 0)
{
bidi_it->new_paragraph = 1;
diff --git a/src/blockinput.h b/src/blockinput.h
index dc02919cf4f..70822e29be7 100644
--- a/src/blockinput.h
+++ b/src/blockinput.h
@@ -19,109 +19,57 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef EMACS_BLOCKINPUT_H
#define EMACS_BLOCKINPUT_H
-#include "atimer.h"
+INLINE_HEADER_BEGIN
+#ifndef BLOCKINPUT_INLINE
+# define BLOCKINPUT_INLINE INLINE
+#endif
-/* When Emacs is using signal-driven input, the processing of those
- input signals can get pretty hairy. For example, when Emacs is
- running under X windows, handling an input signal can entail
- retrieving events from the X event queue, or making other X calls.
-
- If an input signal occurs while Emacs is in the midst of some
- non-reentrant code, and the signal processing invokes that same
- code, we lose. For example, malloc and the Xlib functions aren't
- usually re-entrant, and both are used by the X input signal handler
- - if we try to process an input signal in the midst of executing
- any of these functions, we'll lose.
+/* Emacs should avoid doing anything hairy in a signal handler, because
+ so many system functions are non-reentrant. For example, malloc
+ and the Xlib functions aren't usually re-entrant, so if they were
+ used by the SIGIO handler, we'd lose.
To avoid this, we make the following requirements:
- * Everyone must evaluate BLOCK_INPUT before entering these functions,
- and then call UNBLOCK_INPUT after performing them. Calls
- BLOCK_INPUT and UNBLOCK_INPUT may be nested.
+ * Everyone must evaluate BLOCK_INPUT before performing actions that
+ might conflict with a signal handler, and then call UNBLOCK_INPUT
+ after performing them. Calls BLOCK_INPUT and UNBLOCK_INPUT may be
+ nested.
* Any complicated interrupt handling code should test
- interrupt_input_blocked, and put off its work until later.
+ INPUT_BLOCKED_P, and put off its work until later.
* If the interrupt handling code wishes, it may set
- interrupt_input_pending to a non-zero value. If that flag is set
- when input becomes unblocked, UNBLOCK_INPUT will send a new SIGIO. */
-
-extern volatile int interrupt_input_blocked;
+ pending_signals to a non-zero value. If that flag is set
+ when input becomes unblocked, UNBLOCK_INPUT will then read
+ input and process timers.
-/* Nonzero means an input interrupt has arrived
- during the current critical section. */
-extern int interrupt_input_pending;
+ Historically, Emacs signal handlers did much more than they do now,
+ and this caused many BLOCK_INPUT calls to be sprinkled around the code.
+ FIXME: Remove calls that aren't needed now. */
+extern volatile int interrupt_input_blocked;
-/* Non-zero means asynchronous timers should be run when input is
- unblocked. */
-
-extern int pending_atimers;
+/* Begin critical section. */
+BLOCKINPUT_INLINE void
+block_input (void)
+{
+ interrupt_input_blocked++;
+}
-/* Begin critical section. */
-#define BLOCK_INPUT (interrupt_input_blocked++)
-
-/* End critical section.
-
- If doing signal-driven input, and a signal came in when input was
- blocked, reinvoke the signal handler now to deal with it.
-
- We used to have two possible definitions of this macro - one for
- when SIGIO was #defined, and one for when it wasn't; when SIGIO
- wasn't #defined, we wouldn't bother to check if we should re-invoke
- the signal handler. But that doesn't work very well; some of the
- files which use this macro don't #include the right files to get
- SIGIO.
-
- So, we always test interrupt_input_pending now; that's not too
- expensive, and it'll never get set if we don't need to resignal. */
-
-#define UNBLOCK_INPUT \
- do \
- { \
- --interrupt_input_blocked; \
- if (interrupt_input_blocked == 0) \
- { \
- if (interrupt_input_pending) \
- reinvoke_input_signal (); \
- if (pending_atimers) \
- do_pending_atimers (); \
- } \
- else if (interrupt_input_blocked < 0) \
- abort (); \
- } \
- while (0)
-
-/* Undo any number of BLOCK_INPUT calls,
- and also reinvoke any pending signal. */
-
-#define TOTALLY_UNBLOCK_INPUT \
- do if (interrupt_input_blocked != 0) \
- { \
- interrupt_input_blocked = 1; \
- UNBLOCK_INPUT; \
- } \
- while (0)
-
-/* Undo any number of BLOCK_INPUT calls down to level LEVEL,
- and also (if the level is now 0) reinvoke any pending signal. */
-
-#define UNBLOCK_INPUT_TO(LEVEL) \
- do \
- { \
- interrupt_input_blocked = (LEVEL) + 1; \
- UNBLOCK_INPUT; \
- } \
- while (0)
-
-#define UNBLOCK_INPUT_RESIGNAL UNBLOCK_INPUT
+extern void unblock_input (void);
+extern void totally_unblock_input (void);
+extern void unblock_input_to (int);
/* In critical section ? */
-#define INPUT_BLOCKED_P (interrupt_input_blocked > 0)
-/* Defined in keyboard.c */
-extern void reinvoke_input_signal (void);
+BLOCKINPUT_INLINE bool
+input_blocked_p (void)
+{
+ return 0 < interrupt_input_blocked;
+}
-#endif /* EMACS_BLOCKINPUT_H */
+INLINE_HEADER_END
+#endif /* EMACS_BLOCKINPUT_H */
diff --git a/src/buffer.c b/src/buffer.c
index ef87f40e81a..c8864419076 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -26,7 +26,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
-#include <setjmp.h>
#include <unistd.h>
#include <verify.h>
@@ -58,10 +57,6 @@ struct buffer *all_buffers;
struct buffer alignas (GCALIGNMENT) buffer_defaults;
-/* A Lisp_Object pointer to the above, used for staticpro */
-
-static Lisp_Object Vbuffer_defaults;
-
/* This structure marks which slots in a buffer have corresponding
default values in buffer_defaults.
Each such slot has a nonzero value in this structure.
@@ -76,18 +71,15 @@ static Lisp_Object Vbuffer_defaults;
and the corresponding slot in buffer_defaults is not used.
If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
- zero, that is a bug */
+ zero, that is a bug. */
struct buffer buffer_local_flags;
/* This structure holds the names of symbols whose values may be
- buffer-local. It is indexed and accessed in the same way as the above. */
+ buffer-local. It is indexed and accessed in the same way as the above. */
struct buffer alignas (GCALIGNMENT) buffer_local_symbols;
-/* A Lisp_Object pointer to the above, used for staticpro */
-static Lisp_Object Vbuffer_local_symbols;
-
/* Return the symbol of the per-buffer variable at offset OFFSET in
the buffer structure. */
@@ -113,7 +105,7 @@ static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay,
static void swap_out_buffer_local_variables (struct buffer *b);
static void reset_buffer_local_variables (struct buffer *, bool);
-/* Alist of all buffer names vs the buffers. */
+/* Alist of all buffer names vs the buffers. */
/* This used to be a variable, but is no longer,
to prevent lossage due to user rplac'ing this alist or its elements. */
Lisp_Object Vbuffer_alist;
@@ -132,7 +124,7 @@ static Lisp_Object Qpermanent_local_hook;
static Lisp_Object Qprotected_field;
-static Lisp_Object QSFundamental; /* A string "Fundamental" */
+static Lisp_Object QSFundamental; /* A string "Fundamental". */
static Lisp_Object Qkill_buffer_hook;
static Lisp_Object Qbuffer_list_update_hook;
@@ -156,222 +148,222 @@ static void modify_overlay (struct buffer *, ptrdiff_t, ptrdiff_t);
static Lisp_Object buffer_lisp_local_variables (struct buffer *, bool);
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
bset_abbrev_mode (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (abbrev_mode) = val;
}
-static inline void
+static void
bset_abbrev_table (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (abbrev_table) = val;
}
-static inline void
+static void
bset_auto_fill_function (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (auto_fill_function) = val;
}
-static inline void
+static void
bset_auto_save_file_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (auto_save_file_format) = val;
}
-static inline void
+static void
bset_auto_save_file_name (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (auto_save_file_name) = val;
}
-static inline void
+static void
bset_backed_up (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (backed_up) = val;
}
-static inline void
+static void
bset_begv_marker (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (begv_marker) = val;
}
-static inline void
+static void
bset_bidi_display_reordering (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (bidi_display_reordering) = val;
}
-static inline void
+static void
bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (buffer_file_coding_system) = val;
}
-static inline void
+static void
bset_cache_long_line_scans (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (cache_long_line_scans) = val;
}
-static inline void
+static void
bset_case_fold_search (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (case_fold_search) = val;
}
-static inline void
+static void
bset_ctl_arrow (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (ctl_arrow) = val;
}
-static inline void
+static void
bset_cursor_in_non_selected_windows (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (cursor_in_non_selected_windows) = val;
}
-static inline void
+static void
bset_cursor_type (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (cursor_type) = val;
}
-static inline void
+static void
bset_display_table (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (display_table) = val;
}
-static inline void
+static void
bset_extra_line_spacing (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (extra_line_spacing) = val;
}
-static inline void
+static void
bset_file_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (file_format) = val;
}
-static inline void
+static void
bset_file_truename (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (file_truename) = val;
}
-static inline void
+static void
bset_fringe_cursor_alist (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (fringe_cursor_alist) = val;
}
-static inline void
+static void
bset_fringe_indicator_alist (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (fringe_indicator_alist) = val;
}
-static inline void
+static void
bset_fringes_outside_margins (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (fringes_outside_margins) = val;
}
-static inline void
+static void
bset_header_line_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (header_line_format) = val;
}
-static inline void
+static void
bset_indicate_buffer_boundaries (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (indicate_buffer_boundaries) = val;
}
-static inline void
+static void
bset_indicate_empty_lines (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (indicate_empty_lines) = val;
}
-static inline void
+static void
bset_invisibility_spec (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (invisibility_spec) = val;
}
-static inline void
+static void
bset_left_fringe_width (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (left_fringe_width) = val;
}
-static inline void
+static void
bset_major_mode (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (major_mode) = val;
}
-static inline void
+static void
bset_mark (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (mark) = val;
}
-static inline void
+static void
bset_minor_modes (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (minor_modes) = val;
}
-static inline void
+static void
bset_mode_line_format (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (mode_line_format) = val;
}
-static inline void
+static void
bset_mode_name (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (mode_name) = val;
}
-static inline void
+static void
bset_name (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (name) = val;
}
-static inline void
+static void
bset_overwrite_mode (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (overwrite_mode) = val;
}
-static inline void
+static void
bset_pt_marker (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (pt_marker) = val;
}
-static inline void
+static void
bset_right_fringe_width (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (right_fringe_width) = val;
}
-static inline void
+static void
bset_save_length (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (save_length) = val;
}
-static inline void
+static void
bset_scroll_bar_width (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_bar_width) = val;
}
-static inline void
+static void
bset_scroll_down_aggressively (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_down_aggressively) = val;
}
-static inline void
+static void
bset_scroll_up_aggressively (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (scroll_up_aggressively) = val;
}
-static inline void
+static void
bset_selective_display (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (selective_display) = val;
}
-static inline void
+static void
bset_selective_display_ellipses (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (selective_display_ellipses) = val;
}
-static inline void
+static void
bset_vertical_scroll_bar_type (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (vertical_scroll_bar_type) = val;
}
-static inline void
+static void
bset_word_wrap (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (word_wrap) = val;
}
-static inline void
+static void
bset_zv_marker (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (zv_marker) = val;
@@ -393,7 +385,7 @@ DEFUN ("buffer-live-p", Fbuffer_live_p, Sbuffer_live_p, 1, 1, 0,
Value is nil if OBJECT is not a buffer or if it has been killed. */)
(Lisp_Object object)
{
- return ((BUFFERP (object) && ! NILP (BVAR (XBUFFER (object), name)))
+ return ((BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object)))
? Qt : Qnil);
}
@@ -412,7 +404,6 @@ followed by the rest of the buffers. */)
Lisp_Object framelist, prevlist, tail;
Lisp_Object args[3];
- CHECK_FRAME (frame);
framelist = Fcopy_sequence (XFRAME (frame)->buffer_list);
prevlist = Fnreverse (Fcopy_sequence
(XFRAME (frame)->buried_buffer_list));
@@ -554,13 +545,15 @@ even if it is dead. The return value is never nil. */)
b->base_buffer = NULL;
/* No one shares the text with us now. */
b->indirections = 0;
+ /* No one shows us now. */
+ b->window_count = 0;
BUF_GAP_SIZE (b) = 20;
- BLOCK_INPUT;
+ block_input ();
/* We allocate extra 1-byte at the tail and keep it always '\0' for
anchoring a search. */
alloc_buffer_text (b, BUF_GAP_SIZE (b) + 1);
- UNBLOCK_INPUT;
+ unblock_input ();
if (! BUF_BEG_ADDR (b))
buffer_memory_full (BUF_GAP_SIZE (b) + 1);
@@ -593,10 +586,6 @@ even if it is dead. The return value is never nil. */)
bset_width_table (b, Qnil);
b->prevent_redisplay_optimizations_p = 1;
- /* Put this on the chain of all buffers including killed ones. */
- b->header.next.buffer = all_buffers;
- all_buffers = b;
-
/* An ordinary buffer normally doesn't need markers
to handle BEGV and ZV. */
bset_pt_marker (b, Qnil);
@@ -661,13 +650,13 @@ copy_overlays (struct buffer *b, struct Lisp_Overlay *list)
/* Set an appropriate overlay of B. */
-static inline void
+static void
set_buffer_overlays_before (struct buffer *b, struct Lisp_Overlay *o)
{
b->overlays_before = o;
}
-static inline void
+static void
set_buffer_overlays_after (struct buffer *b, struct Lisp_Overlay *o)
{
b->overlays_after = o;
@@ -785,7 +774,7 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
base_buffer = Fget_buffer (base_buffer);
if (NILP (base_buffer))
error ("No such buffer: `%s'", SDATA (tem));
- if (NILP (BVAR (XBUFFER (base_buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (base_buffer)))
error ("Base buffer has been killed");
if (SCHARS (name) == 0)
@@ -805,6 +794,8 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
b->indirections = -1;
/* Notify base buffer that we share the text now. */
b->base_buffer->indirections++;
+ /* Always -1 for an indirect buffer. */
+ b->window_count = -1;
b->pt = b->base_buffer->pt;
b->begv = b->base_buffer->begv;
@@ -817,10 +808,6 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
b->width_run_cache = 0;
bset_width_table (b, Qnil);
- /* Put this on the chain of all buffers including killed ones. */
- b->header.next.buffer = all_buffers;
- all_buffers = b;
-
name = Fcopy_sequence (name);
set_string_intervals (name, NULL);
bset_name (b, name);
@@ -911,6 +898,8 @@ delete_all_overlays (struct buffer *b)
{
struct Lisp_Overlay *ov, *next;
+ /* FIXME: Since each drop_overlay will scan BUF_MARKERS to unlink its
+ markers, we have an unneeded O(N^2) behavior here. */
for (ov = b->overlays_before; ov; ov = next)
{
drop_overlay (b, ov);
@@ -1240,7 +1229,7 @@ buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer)
result = Fdefault_value (variable);
break;
}
- default: abort ();
+ default: emacs_abort ();
}
return result;
@@ -1355,9 +1344,13 @@ A non-nil FLAG means mark the buffer modified. */)
/* If buffer becoming modified, lock the file.
If buffer becoming unmodified, unlock the file. */
- fn = BVAR (current_buffer, file_truename);
+ struct buffer *b = current_buffer->base_buffer
+ ? current_buffer->base_buffer
+ : current_buffer;
+
+ fn = BVAR (b, file_truename);
/* Test buffer-file-name so that binding it to nil is effective. */
- if (!NILP (fn) && ! NILP (BVAR (current_buffer, filename)))
+ if (!NILP (fn) && ! NILP (BVAR (b, filename)))
{
bool already = SAVE_MODIFF < MODIFF;
if (!already && !NILP (flag))
@@ -1538,6 +1531,16 @@ This does not change the name of the visited file (if any). */)
return BVAR (current_buffer, name);
}
+/* True if B can be used as 'other-than-BUFFER' buffer. */
+
+static bool
+candidate_buffer (Lisp_Object b, Lisp_Object buffer)
+{
+ return (BUFFERP (b) && !EQ (b, buffer)
+ && BUFFER_LIVE_P (XBUFFER (b))
+ && !BUFFER_HIDDEN_P (XBUFFER (b)));
+}
+
DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 3, 0,
doc: /* Return most recently selected buffer other than BUFFER.
Buffers not visible in windows are preferred to visible buffers, unless
@@ -1551,23 +1554,15 @@ 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 tail, buf, pred;
- Lisp_Object notsogood = Qnil;
-
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_FRAME (frame);
+ struct frame *f = decode_any_frame (frame);
+ Lisp_Object tail = f->buffer_list, pred = f->buffer_predicate;
+ Lisp_Object buf, notsogood = Qnil;
- pred = frame_buffer_predicate (frame);
/* Consider buffers that have been seen in the frame first. */
- tail = XFRAME (frame)->buffer_list;
for (; CONSP (tail); tail = XCDR (tail))
{
buf = XCAR (tail);
- if (BUFFERP (buf) && !EQ (buf, buffer)
- && !NILP (BVAR (XBUFFER (buf), name))
- && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')
+ if (candidate_buffer (buf, buffer)
/* If the frame has a buffer_predicate, disregard buffers that
don't fit the predicate. */
&& (NILP (pred) || !NILP (call1 (pred, buf))))
@@ -1585,9 +1580,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */)
for (; CONSP (tail); tail = XCDR (tail))
{
buf = Fcdr (XCAR (tail));
- if (BUFFERP (buf) && !EQ (buf, buffer)
- && !NILP (BVAR (XBUFFER (buf), name))
- && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')
+ if (candidate_buffer (buf, buffer)
/* If the frame has a buffer_predicate, disregard buffers that
don't fit the predicate. */
&& (NILP (pred) || !NILP (call1 (pred, buf))))
@@ -1623,13 +1616,10 @@ other_buffer_safely (Lisp_Object buffer)
{
Lisp_Object tail, buf;
- tail = Vbuffer_alist;
- for (; CONSP (tail); tail = XCDR (tail))
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
{
buf = Fcdr (XCAR (tail));
- if (BUFFERP (buf) && !EQ (buf, buffer)
- && !NILP (BVAR (XBUFFER (buf), name))
- && (SREF (BVAR (XBUFFER (buf), name), 0) != ' '))
+ if (candidate_buffer (buf, buffer))
return buf;
}
@@ -1671,18 +1661,11 @@ No argument or nil as argument means do this for the current buffer. */)
void
compact_buffer (struct buffer *buffer)
{
- /* Verify indirection counters. */
- if (buffer->base_buffer)
- {
- eassert (buffer->indirections == -1);
- eassert (buffer->base_buffer->indirections > 0);
- }
- else
- eassert (buffer->indirections >= 0);
+ BUFFER_CHECK_INDIRECTION (buffer);
/* Skip dead buffers, indirect buffers and buffers
which aren't changed since last compaction. */
- if (!NILP (buffer->INTERNAL_FIELD (name))
+ if (BUFFER_LIVE_P (buffer)
&& (buffer->base_buffer == NULL)
&& (buffer->text->compact != buffer->text->modiff))
{
@@ -1747,7 +1730,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
b = XBUFFER (buffer);
/* Avoid trouble for buffer already dead. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qnil;
/* Query if the buffer is still modified. */
@@ -1783,7 +1766,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
}
/* If the hooks have killed the buffer, exit now. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
/* We have no more questions to ask. Verify that it is valid
@@ -1815,7 +1798,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
UNGCPRO;
/* Exit if we now have killed the base buffer (Bug#11665). */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
}
@@ -1826,7 +1809,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
replace_buffer_in_windows (buffer);
/* Exit if replacing the buffer in windows has killed our buffer. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
/* Make this buffer not be current. Exit if it is the sole visible
@@ -1859,7 +1842,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Killing buffer processes may run sentinels which may have killed
our buffer. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
/* These may run Lisp code and into infinite loops (if someone
@@ -1891,7 +1874,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
}
/* Deleting an auto-save file could have killed our buffer. */
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
return Qt;
if (b->base_buffer)
@@ -1899,12 +1882,16 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Unchain all markers that belong to this indirect buffer.
Don't unchain the markers that belong to the base buffer
or its other indirect buffers. */
- for (m = BUF_MARKERS (b); m; )
+ struct Lisp_Marker **mp = &BUF_MARKERS (b);
+ while ((m = *mp))
{
- struct Lisp_Marker *next = m->next;
if (m->buffer == b)
- unchain_marker (m);
- m = next;
+ {
+ m->buffer = NULL;
+ *mp = m->next;
+ }
+ else
+ mp = &m->next;
}
}
else
@@ -1921,8 +1908,12 @@ cleaning up all windows currently displaying the buffer to be killed. */)
BUF_MARKERS (b) = NULL;
set_buffer_intervals (b, NULL);
- /* Perhaps we should explicitly free the interval tree here... */
+ /* Perhaps we should explicitly free the interval tree here... */
}
+ /* Since we've unlinked the markers, the overlays can't be here any more
+ either. */
+ b->overlays_before = NULL;
+ b->overlays_after = NULL;
/* Reset the local variables, so that this buffer's local values
won't be protected from GC. They would be protected
@@ -1933,17 +1924,23 @@ cleaning up all windows currently displaying the buffer to be killed. */)
bset_name (b, Qnil);
- BLOCK_INPUT;
+ block_input ();
if (b->base_buffer)
{
/* Notify our base buffer that we don't share the text anymore. */
eassert (b->indirections == -1);
b->base_buffer->indirections--;
eassert (b->base_buffer->indirections >= 0);
+ /* Make sure that we wasn't confused. */
+ eassert (b->window_count == -1);
}
else
- /* No one shares our buffer text, can free it. */
- free_buffer_text (b);
+ {
+ /* Make sure that no one shows us. */
+ eassert (b->window_count == 0);
+ /* No one shares our buffer text, can free it. */
+ free_buffer_text (b);
+ }
if (b->newline_cache)
{
@@ -1956,7 +1953,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
b->width_run_cache = 0;
}
bset_width_table (b, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
bset_undo_list (b, Qnil);
/* Run buffer-list-update-hook. */
@@ -2060,7 +2057,7 @@ the current buffer's major mode. */)
CHECK_BUFFER (buffer);
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
error ("Attempt to set major mode for a dead buffer");
if (strcmp (SSDATA (BVAR (XBUFFER (buffer), name)), "*scratch*") == 0)
@@ -2115,6 +2112,8 @@ set_buffer_internal_1 (register struct buffer *b)
if (current_buffer == b)
return;
+ BUFFER_CHECK_INDIRECTION (b);
+
old_buf = current_buffer;
current_buffer = b;
last_known_column_point = -1; /* invalidate indentation cache */
@@ -2186,7 +2185,7 @@ set_buffer_temp (struct buffer *b)
DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
doc: /* Make buffer BUFFER-OR-NAME current for editing operations.
BUFFER-OR-NAME may be a buffer or the name of an existing buffer. See
-also `save-excursion' when you want to make a buffer current
+also `with-current-buffer' when you want to make a buffer current
temporarily. This function does not display the buffer, so its effect
ends when the current command terminates. Use `switch-to-buffer' or
`pop-to-buffer' to switch buffers permanently. */)
@@ -2196,7 +2195,7 @@ ends when the current command terminates. Use `switch-to-buffer' or
buffer = Fget_buffer (buffer_or_name);
if (NILP (buffer))
nsberror (buffer_or_name);
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
error ("Selecting deleted buffer");
set_buffer_internal (XBUFFER (buffer));
return buffer;
@@ -2207,7 +2206,7 @@ ends when the current command terminates. Use `switch-to-buffer' or
Lisp_Object
set_buffer_if_live (Lisp_Object buffer)
{
- if (! NILP (BVAR (XBUFFER (buffer), name)))
+ if (BUFFER_LIVE_P (XBUFFER (buffer)))
set_buffer_internal (XBUFFER (buffer));
return Qnil;
}
@@ -2302,7 +2301,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
CHECK_BUFFER (buffer);
other_buffer = XBUFFER (buffer);
- if (NILP (BVAR (other_buffer, name)))
+ if (!BUFFER_LIVE_P (other_buffer))
error ("Cannot swap a dead buffer's text");
/* Actually, it probably works just fine.
@@ -2474,7 +2473,7 @@ current buffer is cleared. */)
begv = BEGV, zv = ZV;
if (narrowed)
- Fwiden ();
+ error ("Changing multibyteness in a narrowed buffer");
if (NILP (flag))
{
@@ -2669,7 +2668,7 @@ current buffer is cleared. */)
/* Make sure no markers were put on the chain
while the chain value was incorrect. */
if (BUF_MARKERS (current_buffer))
- abort ();
+ emacs_abort ();
BUF_MARKERS (current_buffer) = markers;
@@ -2690,15 +2689,16 @@ current buffer is cleared. */)
UNGCPRO;
- /* Changing the multibyteness of a buffer means that all windows
- showing that buffer must be updated thoroughly. */
current_buffer->prevent_redisplay_optimizations_p = 1;
- ++windows_or_buffers_changed;
+
+ /* If buffer is shown in a window, let redisplay consider other windows. */
+ if (buffer_window_count (current_buffer))
+ ++windows_or_buffers_changed;
/* Copy this buffer's new multibyte status
into all of its indirect buffers. */
FOR_EACH_BUFFER (other)
- if (other->base_buffer == current_buffer && !NILP (BVAR (other, name)))
+ if (other->base_buffer == current_buffer && BUFFER_LIVE_P (other))
{
BVAR (other, enable_multibyte_characters)
= BVAR (current_buffer, enable_multibyte_characters);
@@ -3144,8 +3144,8 @@ compare_overlays (const void *v1, const void *v2)
between "equal" overlays. The result can still change between
invocations of Emacs, but it won't change in the middle of
`find_field' (bug#6830). */
- if (XHASH (s1->overlay) != XHASH (s2->overlay))
- return XHASH (s1->overlay) < XHASH (s2->overlay) ? -1 : 1;
+ if (!EQ (s1->overlay, s2->overlay))
+ return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1;
return 0;
}
@@ -3411,7 +3411,7 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
}
}
if (p != overlay_str_buf + total)
- abort ();
+ emacs_abort ();
if (pstr)
*pstr = overlay_str_buf;
return total;
@@ -3699,7 +3699,6 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end)
beforep->next = current_buffer->overlays_before;
set_buffer_overlays_before (current_buffer, before_list);
}
- recenter_overlay_lists (current_buffer, current_buffer->overlay_center);
if (afterp)
{
@@ -3857,17 +3856,16 @@ for the rear of the overlay advance when text is inserted there
end = OVERLAY_END (overlay);
if (OVERLAY_POSITION (end) < b->overlay_center)
{
- if (b->overlays_after)
- XOVERLAY (overlay)->next = b->overlays_after;
+ eassert (b->overlays_after || (XOVERLAY (overlay)->next == NULL));
+ XOVERLAY (overlay)->next = b->overlays_after;
set_buffer_overlays_after (b, XOVERLAY (overlay));
}
else
{
- if (b->overlays_before)
- XOVERLAY (overlay)->next = b->overlays_before;
+ eassert (b->overlays_before || (XOVERLAY (overlay)->next == NULL));
+ XOVERLAY (overlay)->next = b->overlays_before;
set_buffer_overlays_before (b, XOVERLAY (overlay));
}
-
/* This puts it in the right list, and in the right order. */
recenter_overlay_lists (b, b->overlay_center);
@@ -3891,17 +3889,17 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
BUF_COMPUTE_UNCHANGED (buf, start, end);
- /* If this is a buffer not in the selected window,
- we must do other windows. */
- if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
- windows_or_buffers_changed = 1;
- /* If multiple windows show this buffer, we must do other windows. */
- else if (buffer_shared > 1)
- windows_or_buffers_changed = 1;
- /* If we modify an overlay at the end of the buffer, we cannot
- be sure that window end is still valid. */
- else if (end >= ZV && start <= ZV)
- windows_or_buffers_changed = 1;
+ /* If BUF is visible, consider updating the display if ... */
+ if (buffer_window_count (buf) > 0)
+ {
+ /* ... it's visible in other window than selected, */
+ if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
+ windows_or_buffers_changed = 1;
+ /* ... or if we modify an overlay at the end of the buffer
+ and so we cannot be sure that window end is still valid. */
+ else if (end >= ZV && start <= ZV)
+ windows_or_buffers_changed = 1;
+ }
++BUF_OVERLAY_MODIFF (buf);
}
@@ -4151,7 +4149,7 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
/* Put all the overlays we want in a vector in overlay_vec.
Store the length in len. */
noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
- 0, 0, 0);
+ NULL, NULL, 0);
/* Make a list of them all. */
result = Flist (noverlays, overlay_vec);
@@ -4594,7 +4592,7 @@ buffer_slot_type_mismatch (Lisp_Object newval, int type)
case_Lisp_Int: predicate = Qintegerp; break;
case Lisp_String: predicate = Qstringp; break;
case Lisp_Symbol: predicate = Qsymbolp; break;
- default: abort ();
+ default: emacs_abort ();
}
wrong_type_argument (predicate, newval);
@@ -5042,7 +5040,7 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
{
void *p;
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
p = mmap_alloc ((void **) &b->text->beg, nbytes);
#elif defined REL_ALLOC
@@ -5053,12 +5051,12 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
if (p == NULL)
{
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (nbytes);
}
b->text->beg = (unsigned char *) p;
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Enlarge buffer B's text buffer by DELTA bytes. DELTA < 0 means
@@ -5070,7 +5068,7 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
void *p;
ptrdiff_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
+ delta);
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
p = mmap_realloc ((void **) &b->text->beg, nbytes);
#elif defined REL_ALLOC
@@ -5081,12 +5079,12 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
if (p == NULL)
{
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (nbytes);
}
BUF_BEG_ADDR (b) = (unsigned char *) p;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5095,7 +5093,7 @@ enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
static void
free_buffer_text (struct buffer *b)
{
- BLOCK_INPUT;
+ block_input ();
#if defined USE_MMAP_FOR_BUFFERS
mmap_free ((void **) &b->text->beg);
@@ -5106,7 +5104,7 @@ free_buffer_text (struct buffer *b)
#endif
BUF_BEG_ADDR (b) = NULL;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5119,11 +5117,6 @@ void
init_buffer_once (void)
{
int idx;
- /* If you add, remove, or reorder Lisp_Objects in a struct buffer, make
- sure that this is still correct. Otherwise, mark_vectorlike may not
- trace all Lisp_Objects in buffer_defaults and buffer_local_symbols. */
- const int pvecsize
- = (offsetof (struct buffer, own_text) - header_size) / word_size;
memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags);
@@ -5141,12 +5134,16 @@ init_buffer_once (void)
/* No one will share the text with these buffers, but let's play it safe. */
buffer_defaults.indirections = 0;
buffer_local_symbols.indirections = 0;
+ /* Likewise no one will display them. */
+ buffer_defaults.window_count = 0;
+ buffer_local_symbols.window_count = 0;
set_buffer_intervals (&buffer_defaults, NULL);
set_buffer_intervals (&buffer_local_symbols, NULL);
- XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize);
- XSETBUFFER (Vbuffer_defaults, &buffer_defaults);
- XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize);
- XSETBUFFER (Vbuffer_local_symbols, &buffer_local_symbols);
+ /* This is not strictly necessary, but let's make them initialized. */
+ bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*"));
+ bset_name (&buffer_local_symbols, build_pure_c_string (" *buffer-local-symbols*"));
+ BUFFER_PVEC_INIT (&buffer_defaults);
+ BUFFER_PVEC_INIT (&buffer_local_symbols);
/* Set up the default values of various buffer slots. */
/* Must do these before making the first buffer! */
@@ -5275,7 +5272,7 @@ init_buffer_once (void)
/* Need more room? */
if (idx >= MAX_PER_BUFFER_VARS)
- abort ();
+ emacs_abort ();
last_per_buffer_idx = idx;
Vbuffer_alist = Qnil;
@@ -5416,7 +5413,7 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
if (PER_BUFFER_IDX (offset) == 0)
/* Did a DEFVAR_PER_BUFFER without initializing the corresponding
slot of buffer_local_flags */
- abort ();
+ emacs_abort ();
}
@@ -5428,8 +5425,6 @@ syms_of_buffer (void)
last_overlay_modification_hooks
= Fmake_vector (make_number (10), Qnil);
- staticpro (&Vbuffer_defaults);
- staticpro (&Vbuffer_local_symbols);
staticpro (&Qfundamental_mode);
staticpro (&Qmode_class);
staticpro (&QSFundamental);
@@ -6218,15 +6213,15 @@ is a member of the list. */);
doc: /* Cursor to use when this buffer is in the selected window.
Values are interpreted as follows:
- t use the cursor specified for the frame
- nil don't display a cursor
- box display a filled box cursor
- hollow display a hollow box cursor
- bar display a vertical bar cursor with default width
- (bar . WIDTH) display a vertical bar cursor with width WIDTH
- hbar display a horizontal bar cursor with default height
+ t use the cursor specified for the frame
+ nil don't display a cursor
+ box display a filled box cursor
+ hollow display a hollow box cursor
+ bar display a vertical bar cursor with default width
+ (bar . WIDTH) display a vertical bar cursor with width WIDTH
+ hbar display a horizontal bar cursor with default height
(hbar . HEIGHT) display a horizontal bar cursor with height HEIGHT
- ANYTHING ELSE display a hollow box cursor
+ ANYTHING ELSE display a hollow box cursor
When the buffer is displayed in a non-selected window, the
cursor's appearance is instead controlled by the variable
diff --git a/src/buffer.h b/src/buffer.h
index e603486418b..a65b769469f 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -482,11 +482,6 @@ struct buffer_text
struct buffer
{
- /* HEADER.NEXT is the next buffer, in chain of all buffers, including killed
- buffers. This chain, starting from all_buffers, is used only for garbage
- collection, in order to collect killed buffers properly. Note that large
- vectors and large pseudo-vector objects are all on another chain starting
- from large_vectors. */
struct vectorlike_header header;
/* The name of this buffer. */
@@ -750,6 +745,9 @@ struct buffer
In an indirect buffer, this is the own_text field of another buffer. */
struct buffer_text *text;
+ /* Next buffer, in chain of all buffers, including killed ones. */
+ struct buffer *next;
+
/* Char position of point in buffer. */
ptrdiff_t pt;
@@ -772,11 +770,15 @@ struct buffer
In an ordinary buffer, it is 0. */
struct buffer *base_buffer;
- /* In an indirect buffer, this is -1. In an ordinary buffer,
+ /* In an indirect buffer, this is -1. In an ordinary buffer,
it's the number of indirect buffers that share our text;
zero means that we're the only owner of this text. */
int indirections;
+ /* Number of windows showing this buffer. Always -1 for
+ an indirect buffer since it counts as its base buffer. */
+ int window_count;
+
/* A non-zero value in slot IDX means that per-buffer variable
with index IDX has a local value in this buffer. The index IDX
for a buffer-local variable is stored in that variable's slot
@@ -959,7 +961,52 @@ bset_width_table (struct buffer *b, Lisp_Object val)
b->INTERNAL_FIELD (width_table) = val;
}
-
+/* Number of Lisp_Objects at the beginning of struct buffer.
+ If you add, remove, or reorder Lisp_Objects within buffer
+ structure, make sure that this is still correct. */
+
+#define BUFFER_LISP_SIZE \
+ ((offsetof (struct buffer, own_text) - header_size) / word_size)
+
+/* Size of the struct buffer part beyond leading Lisp_Objects, in word_size
+ units. Rounding is needed for --with-wide-int configuration. */
+
+#define BUFFER_REST_SIZE \
+ ((((sizeof (struct buffer) - offsetof (struct buffer, own_text)) \
+ + (word_size - 1)) & ~(word_size - 1)) / word_size)
+
+/* Initialize the pseudovector header of buffer object. BUFFER_LISP_SIZE
+ is required for GC, but BUFFER_REST_SIZE is set up just to be consistent
+ with other pseudovectors. */
+
+#define BUFFER_PVEC_INIT(b) \
+ XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE)
+
+/* Convenient check whether buffer B is live. */
+
+#define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name)))
+
+/* Convenient check whether buffer B is hidden (i.e. its name
+ starts with a space). Caller must ensure that B is live. */
+
+#define BUFFER_HIDDEN_P(b) (SREF (BVAR (b, name), 0) == ' ')
+
+/* Verify indirection counters. */
+
+#define BUFFER_CHECK_INDIRECTION(b) \
+ do { \
+ if (BUFFER_LIVE_P (b)) \
+ { \
+ if (b->base_buffer) \
+ { \
+ eassert (b->indirections == -1); \
+ eassert (b->base_buffer->indirections > 0); \
+ } \
+ else \
+ eassert (b->indirections >= 0); \
+ } \
+ } while (0)
+
/* Chain of all buffers, including killed ones. */
extern struct buffer *all_buffers;
@@ -967,7 +1014,7 @@ extern struct buffer *all_buffers;
/* Used to iterate over the chain above. */
#define FOR_EACH_BUFFER(b) \
- for ((b) = all_buffers; (b); (b) = (b)->header.next.buffer)
+ for ((b) = all_buffers; (b); (b) = (b)->next)
/* This structure holds the default values of the buffer-local variables
that have special slots in each buffer.
@@ -1126,7 +1173,18 @@ BUF_FETCH_MULTIBYTE_CHAR (struct buffer *buf, ptrdiff_t pos)
+ pos + BUF_BEG_ADDR (buf) - BEG_BYTE);
return STRING_CHAR (p);
}
-
+
+/* Return number of windows showing B. */
+
+BUFFER_INLINE int
+buffer_window_count (struct buffer *b)
+{
+ if (b->base_buffer)
+ b = b->base_buffer;
+ eassert (b->window_count >= 0);
+ return b->window_count;
+}
+
/* Overlays */
/* Return the marker that stands for where OV starts in the buffer. */
@@ -1145,7 +1203,7 @@ BUF_FETCH_MULTIBYTE_CHAR (struct buffer *buf, ptrdiff_t pos)
We assume you know which buffer it's pointing into. */
#define OVERLAY_POSITION(P) \
- (MARKERP (P) ? marker_position (P) : (abort (), 0))
+ (MARKERP (P) ? marker_position (P) : (emacs_abort (), 0))
/***********************************************************************
@@ -1185,7 +1243,7 @@ extern int last_per_buffer_idx;
#define PER_BUFFER_VALUE_P(B, IDX) \
(((IDX) < 0 || IDX >= last_per_buffer_idx) \
- ? (abort (), 0) \
+ ? (emacs_abort (), 0) \
: ((B)->local_flags[IDX] != 0))
/* Set whether per-buffer variable with index IDX has a buffer-local
@@ -1194,7 +1252,7 @@ extern int last_per_buffer_idx;
#define SET_PER_BUFFER_VALUE_P(B, IDX, VAL) \
do { \
if ((IDX) < 0 || (IDX) >= last_per_buffer_idx) \
- abort (); \
+ emacs_abort (); \
(B)->local_flags[IDX] = (VAL); \
} while (0)
diff --git a/src/bytecode.c b/src/bytecode.c
index be5b7ea6137..a0b257347c2 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -33,7 +33,7 @@ by Hallvard:
*/
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -87,8 +87,6 @@ Lisp_Object Qbyte_code_meter;
#endif /* BYTE_CODE_METER */
-Lisp_Object Qbytecode;
-
/* Byte codes: */
#define BYTE_CODES \
@@ -432,7 +430,7 @@ unmark_byte_stack (struct byte_stack *stack)
#ifdef BYTE_CODE_SAFE
#define CHECK_RANGE(ARG) \
- if (ARG >= bytestr_length) abort ()
+ if (ARG >= bytestr_length) emacs_abort ()
#else /* not BYTE_CODE_SAFE */
@@ -455,7 +453,8 @@ unmark_byte_stack (struct byte_stack *stack)
Fsignal (Qquit, Qnil); \
AFTER_POTENTIAL_GC (); \
} \
- ELSE_PENDING_SIGNALS \
+ else if (pending_signals) \
+ process_pending_signals (); \
} while (0)
@@ -505,7 +504,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
if (FRAME_X_P (f)
&& FRAME_FONT (f)->direction != 0
&& FRAME_FONT (f)->direction != 1)
- abort ();
+ emacs_abort ();
}
#endif
@@ -597,9 +596,9 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
{
#ifdef BYTE_CODE_SAFE
if (top > stacke)
- abort ();
+ emacs_abort ();
else if (top < stack.bottom - 1)
- abort ();
+ emacs_abort ();
#endif
#ifdef BYTE_CODE_METER
@@ -1575,7 +1574,9 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
NEXT;
CASE (Binteractive_p): /* Obsolete since 24.1. */
- PUSH (Finteractive_p ());
+ BEFORE_POTENTIAL_GC ();
+ PUSH (call0 (intern ("interactive-p")));
+ AFTER_POTENTIAL_GC ();
NEXT;
CASE (Bforward_char):
@@ -1872,7 +1873,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
/* Actually this is Bstack_ref with offset 0, but we use Bdup
for that instead. */
/* CASE (Bstack_ref): */
- abort ();
+ error ("Invalid byte opcode");
/* Handy byte-codes for lexical binding. */
CASE (Bstack_ref1):
@@ -1925,11 +1926,11 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
#ifdef BYTE_CODE_SAFE
if (op < Bconstant)
{
- abort ();
+ emacs_abort ();
}
if ((op -= Bconstant) >= const_length)
{
- abort ();
+ emacs_abort ();
}
PUSH (vectorp[op]);
#else
@@ -1948,7 +1949,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
#ifdef BYTE_CODE_SAFE
error ("binding stack not balanced (serious byte compiler bug)");
#else
- abort ();
+ emacs_abort ();
#endif
return result;
@@ -1957,8 +1958,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
void
syms_of_bytecode (void)
{
- DEFSYM (Qbytecode, "byte-code");
-
defsubr (&Sbyte_code);
#ifdef BYTE_CODE_METER
diff --git a/src/callint.c b/src/callint.c
index b11545ddea2..c4c087e83d7 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
diff --git a/src/callproc.c b/src/callproc.c
index 2e9a8950700..5eba3271358 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -19,10 +19,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <signal.h>
#include <errno.h>
#include <stdio.h>
-#include <setjmp.h>
#include <sys/types.h>
#include <unistd.h>
@@ -53,6 +51,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "process.h"
#include "syssignal.h"
#include "systty.h"
+#include "syswait.h"
#include "blockinput.h"
#include "frame.h"
#include "termhooks.h"
@@ -65,98 +64,125 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "nsterm.h"
#endif
-#ifdef HAVE_SETPGID
-#if !defined (USG)
-#undef setpgrp
-#define setpgrp setpgid
-#endif
-#endif
-
/* Pattern used by call-process-region to make temp files. */
static Lisp_Object Vtemp_file_name_pattern;
-/* True if we are about to fork off a synchronous process or if we
- are waiting for it. */
-bool synch_process_alive;
+/* The next two variables are valid only while record-unwind-protect
+ is in place during call-process for a synchronous subprocess. At
+ other times, their contents are irrelevant. Doing this via static
+ C variables is more convenient than putting them into the arguments
+ of record-unwind-protect, as they need to be updated at randomish
+ times in the code, and Lisp cannot always store these values as
+ Emacs integers. It's safe to use static variables here, as the
+ code is never invoked reentrantly. */
-/* Nonzero => this is a string explaining death of synchronous subprocess. */
-const char *synch_process_death;
+/* If nonzero, a process-ID that has not been reaped. */
+static pid_t synch_process_pid;
-/* Nonzero => this is the signal number that terminated the subprocess. */
-int synch_process_termsig;
+/* If nonnegative, a file descriptor that has not been closed. */
+static int synch_process_fd;
+
+/* Block SIGCHLD. */
-/* If synch_process_death is zero,
- this is exit code of synchronous subprocess. */
-int synch_process_retcode;
+static void
+block_child_signal (void)
+{
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGCHLD);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+}
-
-/* Clean up when exiting Fcall_process.
- On MSDOS, delete the temporary file on any kind of termination.
- On Unix, kill the process and any children on termination by signal. */
+/* Unblock SIGCHLD. */
-/* True if this is termination due to exit. */
-static bool call_process_exited;
+static void
+unblock_child_signal (void)
+{
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+}
+
+/* If P is reapable, record it as a deleted process and kill it.
+ Do this in a critical section. Unless PID is wedged it will be
+ reaped on receipt of the first SIGCHLD after the critical section. */
+
+void
+record_kill_process (struct Lisp_Process *p)
+{
+ block_child_signal ();
+
+ if (p->alive)
+ {
+ p->alive = 0;
+ record_deleted_pid (p->pid);
+ kill (- p->pid, SIGKILL);
+ }
+
+ unblock_child_signal ();
+}
+
+/* Clean up when exiting call_process_cleanup. */
static Lisp_Object
-call_process_kill (Lisp_Object fdpid)
+call_process_kill (Lisp_Object ignored)
{
- int fd;
- pid_t pid;
- CONS_TO_INTEGER (Fcar (fdpid), int, fd);
- CONS_TO_INTEGER (Fcdr (fdpid), pid_t, pid);
- emacs_close (fd);
- EMACS_KILLPG (pid, SIGKILL);
- synch_process_alive = 0;
+ if (0 <= synch_process_fd)
+ emacs_close (synch_process_fd);
+
+ if (synch_process_pid)
+ {
+ struct Lisp_Process proc;
+ proc.alive = 1;
+ proc.pid = synch_process_pid;
+ record_kill_process (&proc);
+ }
+
return Qnil;
}
+/* Clean up when exiting Fcall_process.
+ On MSDOS, delete the temporary file on any kind of termination.
+ On Unix, kill the process and any children on termination by signal. */
+
static Lisp_Object
call_process_cleanup (Lisp_Object arg)
{
- Lisp_Object fdpid = Fcdr (arg);
- int fd;
-#if defined (MSDOS)
- Lisp_Object file;
+#ifdef MSDOS
+ Lisp_Object buffer = Fcar (arg);
+ Lisp_Object file = Fcdr (arg);
#else
- pid_t pid;
+ Lisp_Object buffer = arg;
#endif
- Fset_buffer (Fcar (arg));
- CONS_TO_INTEGER (Fcar (fdpid), int, fd);
-
-#if defined (MSDOS)
- /* for MSDOS fdpid is really (fd . tempfile) */
- file = Fcdr (fdpid);
- /* FD is -1 and FILE is "" when we didn't actually create a
- temporary file in call-process. */
- if (fd >= 0)
- emacs_close (fd);
- if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0'))
- unlink (SDATA (file));
-#else /* not MSDOS */
- CONS_TO_INTEGER (Fcdr (fdpid), pid_t, pid);
-
- if (call_process_exited)
- {
- emacs_close (fd);
- return Qnil;
- }
+ Fset_buffer (buffer);
- if (EMACS_KILLPG (pid, SIGINT) == 0)
+#ifndef MSDOS
+ /* If the process still exists, kill its process group. */
+ if (synch_process_pid)
{
ptrdiff_t count = SPECPDL_INDEX ();
- record_unwind_protect (call_process_kill, fdpid);
+ kill (-synch_process_pid, SIGINT);
+ record_unwind_protect (call_process_kill, make_number (0));
message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
immediate_quit = 1;
QUIT;
- wait_for_termination (pid);
+ wait_for_termination (synch_process_pid, 0, 1);
+ synch_process_pid = 0;
immediate_quit = 0;
specpdl_ptr = specpdl + count; /* Discard the unwind protect. */
message1 ("Waiting for process to die...done");
}
- synch_process_alive = 0;
- emacs_close (fd);
-#endif /* not MSDOS */
+#endif
+
+ if (0 <= synch_process_fd)
+ emacs_close (synch_process_fd);
+
+#ifdef MSDOS
+ /* FILE is "" when we didn't actually create a temporary file in
+ call-process. */
+ if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0'))
+ unlink (SDATA (file));
+#endif
+
return Qnil;
}
@@ -189,18 +215,14 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail;
+ Lisp_Object infile, buffer, current_dir, path;
bool display_p;
- int fd[2];
- int filefd;
-#define CALLPROC_BUFFER_SIZE_MIN (16 * 1024)
-#define CALLPROC_BUFFER_SIZE_MAX (4 * CALLPROC_BUFFER_SIZE_MIN)
- char buf[CALLPROC_BUFFER_SIZE_MAX];
- int bufsize = CALLPROC_BUFFER_SIZE_MIN;
+ int fd0, fd1, filefd;
+ int status;
ptrdiff_t count = SPECPDL_INDEX ();
USE_SAFE_ALLOCA;
- register const unsigned char **new_argv;
+ char **new_argv;
/* File to use for stderr in the child.
t means use same as standard output. */
Lisp_Object error_file;
@@ -212,6 +234,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
#else
pid_t pid;
#endif
+ int child_errno;
int fd_output = -1;
struct coding_system process_coding; /* coding-system of process output */
struct coding_system argument_coding; /* coding-system of arguments */
@@ -379,10 +402,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
filefd = emacs_open (SSDATA (infile), O_RDONLY, 0);
if (filefd < 0)
- {
- infile = DECODE_FILE (infile);
- report_file_error ("Opening process input file", Fcons (infile, Qnil));
- }
+ report_file_error ("Opening process input file",
+ Fcons (DECODE_FILE (infile), Qnil));
if (STRINGP (output_file))
{
@@ -440,12 +461,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
}
UNGCPRO;
for (i = 4; i < nargs; i++)
- new_argv[i - 3] = SDATA (args[i]);
+ new_argv[i - 3] = SSDATA (args[i]);
new_argv[i - 3] = 0;
}
else
new_argv[1] = 0;
- new_argv[0] = SDATA (path);
+ new_argv[0] = SSDATA (path);
#ifdef MSDOS /* MW, July 1993 */
@@ -474,51 +495,36 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
}
else
outfilefd = fd_output;
- fd[0] = filefd;
- fd[1] = outfilefd;
+ fd0 = filefd;
+ fd1 = outfilefd;
#endif /* MSDOS */
if (INTEGERP (buffer))
- fd[1] = emacs_open (NULL_DEVICE, O_WRONLY, 0), fd[0] = -1;
+ {
+ fd0 = -1;
+ fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0);
+ }
else
{
#ifndef MSDOS
- errno = 0;
+ int fd[2];
if (pipe (fd) == -1)
{
+ int pipe_errno = errno;
emacs_close (filefd);
+ errno = pipe_errno;
report_file_error ("Creating process pipe", Qnil);
}
+ fd0 = fd[0];
+ fd1 = fd[1];
#endif
}
{
- /* child_setup must clobber environ in systems with true vfork.
- Protect it from permanent change. */
- register char **save_environ = environ;
- register int fd1 = fd[1];
int fd_error = fd1;
-#ifdef HAVE_WORKING_VFORK
- sigset_t procmask;
- sigset_t blocked;
- struct sigaction sigpipe_action;
-#endif
if (fd_output >= 0)
fd1 = fd_output;
-#if 0 /* Some systems don't have sigblock. */
- mask = sigblock (sigmask (SIGCHLD));
-#endif
-
- /* Record that we're about to create a synchronous process. */
- synch_process_alive = 1;
-
- /* These vars record information from process termination.
- Clear them now before process can possibly terminate,
- to avoid timing error if process terminates soon. */
- synch_process_death = 0;
- synch_process_retcode = 0;
- synch_process_termsig = 0;
if (NILP (error_file))
fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0);
@@ -536,8 +542,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
if (fd_error < 0)
{
emacs_close (filefd);
- if (fd[0] != filefd)
- emacs_close (fd[0]);
+ if (fd0 != filefd)
+ emacs_close (fd0);
if (fd1 >= 0)
emacs_close (fd1);
#ifdef MSDOS
@@ -552,31 +558,28 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
#ifdef MSDOS /* MW, July 1993 */
/* Note that on MSDOS `child_setup' actually returns the child process
- exit status, not its PID, so we assign it to `synch_process_retcode'
- below. */
- pid = child_setup (filefd, outfilefd, fd_error, (char **) new_argv,
- 0, current_dir);
-
- /* Record that the synchronous process exited and note its
- termination status. */
- synch_process_alive = 0;
- synch_process_retcode = pid;
- if (synch_process_retcode < 0) /* means it couldn't be exec'ed */
- {
- synchronize_system_messages_locale ();
- synch_process_death = strerror (errno);
- }
+ exit status, not its PID, so assign it to status below. */
+ pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir);
+ child_errno = errno;
emacs_close (outfilefd);
if (fd_error != outfilefd)
emacs_close (fd_error);
+ if (pid < 0)
+ {
+ synchronize_system_messages_locale ();
+ return
+ code_convert_string_norecord (build_string (strerror (child_errno)),
+ Vlocale_coding_system, 0);
+ }
+ status = pid;
fd1 = -1; /* No harm in closing that one! */
if (tempfile)
{
/* Since CRLF is converted to LF within `decode_coding', we
can always open a file with binary mode. */
- fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
- if (fd[0] < 0)
+ fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
+ if (fd0 < 0)
{
unlink (tempfile);
emacs_close (filefd);
@@ -585,25 +588,38 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
}
}
else
- fd[0] = -1; /* We are not going to read from tempfile. */
-#else /* not MSDOS */
-#ifdef WINDOWSNT
- pid = child_setup (filefd, fd1, fd_error, (char **) new_argv,
- 0, current_dir);
-#else /* not WINDOWSNT */
+ fd0 = -1; /* We are not going to read from tempfile. */
+#endif /* MSDOS */
-#ifdef HAVE_WORKING_VFORK
- /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal',
- this sets the parent's signal handlers as well as the child's.
- So delay all interrupts whose handlers the child might munge,
- and record the current handlers so they can be restored later. */
- sigemptyset (&blocked);
- sigaddset (&blocked, SIGPIPE);
- sigaction (SIGPIPE, 0, &sigpipe_action);
- pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
-#endif
+ /* Do the unwind-protect now, even though the pid is not known, so
+ that no storage allocation is done in the critical section.
+ The actual PID will be filled in during the critical section. */
+ synch_process_pid = 0;
+ synch_process_fd = fd0;
+
+#ifdef MSDOS
+ /* MSDOS needs different cleanup information. */
+ record_unwind_protect (call_process_cleanup,
+ Fcons (Fcurrent_buffer (),
+ build_string (tempfile ? tempfile : "")));
+#else
+ record_unwind_protect (call_process_cleanup, Fcurrent_buffer ());
- BLOCK_INPUT;
+ block_input ();
+ block_child_signal ();
+
+#ifdef WINDOWSNT
+ pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
+ /* We need to record the input file of this child, for when we are
+ called from call-process-region to create an async subprocess.
+ That's because call-process-region's unwind procedure will
+ attempt to delete the temporary input file, which will fail
+ because that file is still in use. Recording it with the child
+ will allow us to delete the file when the subprocess exits.
+ The second part of this is in delete_temp_file, q.v. */
+ if (pid > 0 && INTEGERP (buffer) && nargs >= 2 && !NILP (args[1]))
+ record_infile (pid, xstrdup (SSDATA (infile)));
+#else /* not WINDOWSNT */
/* vfork, and prevent local vars from being clobbered by the vfork. */
{
@@ -616,66 +632,67 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
int volatile fd1_volatile = fd1;
int volatile fd_error_volatile = fd_error;
int volatile fd_output_volatile = fd_output;
+ int volatile filefd_volatile = filefd;
+ ptrdiff_t volatile count_volatile = count;
ptrdiff_t volatile sa_count_volatile = sa_count;
- unsigned char const **volatile new_argv_volatile = new_argv;
+ char **volatile new_argv_volatile = new_argv;
pid = vfork ();
+ child_errno = errno;
buffer = buffer_volatile;
coding_systems = coding_systems_volatile;
current_dir = current_dir_volatile;
display_p = display_p_volatile;
+ output_to_buffer = output_to_buffer_volatile;
+ sa_must_free = sa_must_free_volatile;
fd1 = fd1_volatile;
fd_error = fd_error_volatile;
fd_output = fd_output_volatile;
- output_to_buffer = output_to_buffer_volatile;
- sa_must_free = sa_must_free_volatile;
+ filefd = filefd_volatile;
+ count = count_volatile;
sa_count = sa_count_volatile;
new_argv = new_argv_volatile;
+
+ fd0 = synch_process_fd;
}
if (pid == 0)
{
- if (fd[0] >= 0)
- emacs_close (fd[0]);
-#ifdef HAVE_SETSID
+ unblock_child_signal ();
+
+ if (fd0 >= 0)
+ emacs_close (fd0);
+
setsid ();
-#endif
-#if defined (USG)
- setpgrp ();
-#else
- setpgrp (pid, pid);
-#endif /* USG */
- /* GConf causes us to ignore SIGPIPE, make sure it is restored
- in the child. */
+ /* Emacs ignores SIGPIPE, but the child should not. */
signal (SIGPIPE, SIG_DFL);
-#ifdef HAVE_WORKING_VFORK
- pthread_sigmask (SIG_SETMASK, &procmask, 0);
-#endif
- child_setup (filefd, fd1, fd_error, (char **) new_argv,
- 0, current_dir);
+ child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
}
- UNBLOCK_INPUT;
+#endif /* not WINDOWSNT */
+
+ child_errno = errno;
-#ifdef HAVE_WORKING_VFORK
- /* Restore the signal state. */
- sigaction (SIGPIPE, &sigpipe_action, 0);
- pthread_sigmask (SIG_SETMASK, &procmask, 0);
-#endif
+ if (0 < pid)
+ {
+ if (INTEGERP (buffer))
+ record_deleted_pid (pid);
+ else
+ synch_process_pid = pid;
+ }
-#endif /* not WINDOWSNT */
+ unblock_child_signal ();
+ unblock_input ();
/* The MSDOS case did this already. */
if (fd_error >= 0)
emacs_close (fd_error);
#endif /* not MSDOS */
- environ = save_environ;
-
- /* Close most of our fd's, but not fd[0]
+ /* Close most of our file descriptors, but not fd0
since we will use that to read input from. */
emacs_close (filefd);
if (fd_output >= 0)
@@ -686,31 +703,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
if (pid < 0)
{
- if (fd[0] >= 0)
- emacs_close (fd[0]);
+ errno = child_errno;
report_file_error ("Doing vfork", Qnil);
}
if (INTEGERP (buffer))
- {
- if (fd[0] >= 0)
- emacs_close (fd[0]);
- return Qnil;
- }
-
- /* Enable sending signal if user quits below. */
- call_process_exited = 0;
-
-#if defined (MSDOS)
- /* MSDOS needs different cleanup information. */
- cleanup_info_tail = build_string (tempfile ? tempfile : "");
-#else
- cleanup_info_tail = INTEGER_TO_CONS (pid);
-#endif /* not MSDOS */
- record_unwind_protect (call_process_cleanup,
- Fcons (Fcurrent_buffer (),
- Fcons (INTEGER_TO_CONS (fd[0]),
- cleanup_info_tail)));
+ return unbind_to (count, Qnil);
if (BUFFERP (buffer))
Fset_buffer (buffer);
@@ -766,6 +764,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
if (output_to_buffer)
{
+ enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 };
+ enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN };
+ char buf[CALLPROC_BUFFER_SIZE_MAX];
+ int bufsize = CALLPROC_BUFFER_SIZE_MIN;
int nread;
bool first = 1;
EMACS_INT total_read = 0;
@@ -782,7 +784,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
nread = carryover;
while (nread < bufsize - 1024)
{
- int this_read = emacs_read (fd[0], buf + nread,
+ int this_read = emacs_read (fd0, buf + nread,
bufsize - nread);
if (this_read < 0)
@@ -893,38 +895,34 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
#ifndef MSDOS
/* Wait for it to terminate, unless it already has. */
- if (output_to_buffer)
- wait_for_termination (pid);
- else
- interruptible_wait_for_termination (pid);
+ wait_for_termination (pid, &status, !output_to_buffer);
#endif
immediate_quit = 0;
/* Don't kill any children that the subprocess may have left behind
when exiting. */
- call_process_exited = 1;
+ synch_process_pid = 0;
SAFE_FREE ();
unbind_to (count, Qnil);
- if (synch_process_termsig)
+ if (WIFSIGNALED (status))
{
const char *signame;
synchronize_system_messages_locale ();
- signame = strsignal (synch_process_termsig);
+ signame = strsignal (WTERMSIG (status));
if (signame == 0)
signame = "unknown";
- synch_process_death = signame;
+ return code_convert_string_norecord (build_string (signame),
+ Vlocale_coding_system, 0);
}
- if (synch_process_death)
- return code_convert_string_norecord (build_string (synch_process_death),
- Vlocale_coding_system, 0);
- return make_number (synch_process_retcode);
+ eassert (WIFEXITED (status));
+ return make_number (WEXITSTATUS (status));
}
static Lisp_Object
@@ -933,7 +931,21 @@ delete_temp_file (Lisp_Object name)
/* Suppress jka-compr handling, etc. */
ptrdiff_t count = SPECPDL_INDEX ();
specbind (intern ("file-name-handler-alist"), Qnil);
+#ifdef WINDOWSNT
+ /* If this is called when the subprocess didn't exit yet, the
+ attempt to delete its input file will fail. In that case, we
+ schedule the file for deletion when the subprocess exits. This
+ is the 2nd part of handling this situation; see the call to
+ record_infile in call-process above, for the first part. */
+ if (!internal_delete_file (name))
+ {
+ Lisp_Object encoded_file = ENCODE_FILE (name);
+
+ record_pending_deletion (SSDATA (encoded_file));
+ }
+#else
internal_delete_file (name);
+#endif
unbind_to (count, Qnil);
return Qnil;
}
@@ -998,17 +1010,18 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
{
USE_SAFE_ALLOCA;
Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir);
- char *tempfile = SAFE_ALLOCA (SBYTES (pattern) + 1);
- memcpy (tempfile, SDATA (pattern), SBYTES (pattern) + 1);
+ Lisp_Object encoded_tem = ENCODE_FILE (pattern);
+ char *tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1);
+ memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
coding_systems = Qt;
#ifdef HAVE_MKSTEMP
{
int fd;
- BLOCK_INPUT;
+ block_input ();
fd = mkstemp (tempfile);
- UNBLOCK_INPUT;
+ unblock_input ();
if (fd == -1)
report_file_error ("Failed to open temporary file",
Fcons (build_string (tempfile), Qnil));
@@ -1016,7 +1029,15 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
close (fd);
}
#else
+ errno = 0;
mktemp (tempfile);
+ if (!*tempfile)
+ {
+ if (!errno)
+ errno = EEXIST;
+ report_file_error ("Failed to open temporary file using pattern",
+ Fcons (pattern, Qnil));
+ }
#endif
filename_string = build_string (tempfile);
@@ -1122,10 +1143,6 @@ add_env (char **env, char **new_env, char *string)
Initialize inferior's priority, pgrp, connected dir and environment.
then exec another program based on new_argv.
- This function may change environ for the superior process.
- Therefore, the superior process must save and restore the value
- of environ around the vfork and the call to this function.
-
If SET_PGRP, put the subprocess into a separate process group.
CURRENT_DIR is an elisp string giving the path of the current
@@ -1278,7 +1295,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
#ifdef WINDOWSNT
prepare_standard_handles (in, out, err, handles);
set_process_dir (SDATA (current_dir));
- /* Spawn the child. (See ntproc.c:Spawnve). */
+ /* Spawn the child. (See w32proc.c:sys_spawnve). */
cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env);
reset_standard_handles (in, out, err, handles);
if (cpid == -1)
@@ -1325,22 +1342,10 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
if (err != in && err != out)
emacs_close (err);
-#if defined (USG)
-#ifndef SETPGRP_RELEASES_CTTY
- setpgrp (); /* No arguments but equivalent in this case */
-#endif
-#else /* not USG */
- setpgrp (pid, pid);
-#endif /* not USG */
-
- /* setpgrp_of_tty is incorrect here; it uses input_fd. */
+ setpgid (0, 0);
tcsetpgrp (0, pid);
- /* execvp does not accept an environment arg so the only way
- to pass this environment is to set environ. Our caller
- is responsible for restoring the ambient value of environ. */
- environ = env;
- execvp (new_argv[0], new_argv);
+ execve (new_argv[0], new_argv, env);
emacs_write (1, "Can't exec program: ", 20);
emacs_write (1, new_argv[0], strlen (new_argv[0]));
@@ -1368,16 +1373,7 @@ relocate_fd (int fd, int minfd)
return fd;
else
{
- int new;
-#ifdef F_DUPFD
- new = fcntl (fd, F_DUPFD, minfd);
-#else
- new = dup (fd);
- if (new != -1)
- /* Note that we hold the original FD open while we recurse,
- to guarantee we'll get a new FD if we need it. */
- new = relocate_fd (new, minfd);
-#endif
+ int new = fcntl (fd, F_DUPFD, minfd);
if (new == -1)
{
const char *message_1 = "Error while setting up child: ";
@@ -1627,15 +1623,13 @@ init_callproc (void)
#endif
{
tempdir = Fdirectory_file_name (Vexec_directory);
- if (access (SSDATA (tempdir), 0) < 0)
- dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n",
- Vexec_directory);
+ if (! file_accessible_directory_p (SSDATA (tempdir)))
+ dir_warning ("arch-dependent data dir", Vexec_directory);
}
tempdir = Fdirectory_file_name (Vdata_directory);
- if (access (SSDATA (tempdir), 0) < 0)
- dir_warning ("Warning: arch-independent data dir (%s) does not exist.\n",
- Vdata_directory);
+ if (! file_accessible_directory_p (SSDATA (tempdir)))
+ dir_warning ("arch-independent data dir", Vdata_directory);
sh = (char *) getenv ("SHELL");
Vshell_file_name = build_string (sh ? sh : "/bin/sh");
@@ -1644,7 +1638,7 @@ init_callproc (void)
Vshared_game_score_directory = Qnil;
#else
Vshared_game_score_directory = build_string (PATH_GAME);
- if (NILP (Ffile_directory_p (Vshared_game_score_directory)))
+ if (NILP (Ffile_accessible_directory_p (Vshared_game_score_directory)))
Vshared_game_score_directory = Qnil;
#endif
}
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 1102054b153..d9c6a078973 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -19,7 +19,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -213,7 +213,7 @@ casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e)
validate_region (&b, &e);
start = XFASTINT (b);
end = XFASTINT (e);
- modify_region (current_buffer, start, end, 0);
+ modify_region_1 (start, end, false);
record_change (start, end - start);
start_byte = CHAR_TO_BYTE (start);
diff --git a/src/casetab.c b/src/casetab.c
index 3e22d0d0b77..a84bc9202d0 100644
--- a/src/casetab.c
+++ b/src/casetab.c
@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
diff --git a/src/category.c b/src/category.c
index 80dc6938d8b..31cc90bca68 100644
--- a/src/category.c
+++ b/src/category.c
@@ -32,7 +32,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define CATEGORY_INLINE EXTERN_INLINE
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -41,7 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keymap.h"
/* This setter is used only in this file, so it can be private. */
-static inline void
+static void
bset_category_table (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (category_table) = val;
@@ -79,10 +78,10 @@ hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
if (NILP (XCHAR_TABLE (table)->extras[1]))
set_char_table_extras
(table, 1,
- make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
+ make_hash_table (hashtest_equal, make_number (DEFAULT_HASH_SIZE),
make_float (DEFAULT_REHASH_SIZE),
make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil));
+ Qnil));
h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
i = hash_lookup (h, category_set, &hash);
if (i >= 0)
diff --git a/src/ccl.c b/src/ccl.c
index dd37934451d..34cc1c98eea 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -26,7 +26,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include <limits.h>
#include "lisp.h"
diff --git a/src/character.c b/src/character.c
index cfaaf8eeca9..5808d48a235 100644
--- a/src/character.c
+++ b/src/character.c
@@ -36,7 +36,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef emacs
#include <sys/types.h>
-#include <setjmp.h>
#include <intprops.h>
#include "lisp.h"
#include "character.h"
@@ -127,8 +126,6 @@ char_string (unsigned int c, unsigned char *p)
c &= ~CHAR_MODIFIER_MASK;
}
- MAYBE_UNIFY_CHAR (c);
-
if (c <= MAX_3_BYTE_CHAR)
{
bytes = CHAR_STRING (c, p);
@@ -196,8 +193,6 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len)
p += 5;
}
- MAYBE_UNIFY_CHAR (c);
-
if (len)
*len = p - saved_p;
if (advanced)
@@ -541,7 +536,7 @@ multibyte_chars_in_text (const unsigned char *ptr, ptrdiff_t nbytes)
int len = MULTIBYTE_LENGTH (ptr, endp);
if (len == 0)
- abort ();
+ emacs_abort ();
ptr += len;
chars++;
}
diff --git a/src/character.h b/src/character.h
index 70d4e67a978..b2cdcb76699 100644
--- a/src/character.h
+++ b/src/character.h
@@ -554,23 +554,6 @@ INLINE_HEADER_BEGIN
} while (0)
-/* If C is a character to be unified with a Unicode character, return
- the unified Unicode character. */
-
-#define MAYBE_UNIFY_CHAR(c) \
- do { \
- if (c > MAX_UNICODE_CHAR && c <= MAX_5_BYTE_CHAR) \
- { \
- Lisp_Object val; \
- val = CHAR_TABLE_REF (Vchar_unify_table, c); \
- if (INTEGERP (val)) \
- c = XFASTINT (val); \
- else if (! NILP (val)) \
- c = maybe_unify_char (c, val); \
- } \
- } while (0)
-
-
/* Return a non-outlandish value for the tab width. */
#define SANE_TAB_WIDTH(buf) \
diff --git a/src/charset.c b/src/charset.c
index 0673790e91c..43be0e9c780 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -32,7 +32,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
-#include <setjmp.h>
#include <c-ctype.h>
#include "lisp.h"
#include "character.h"
@@ -422,7 +421,7 @@ load_charset_map (struct charset *charset, struct charset_map_entries *entries,
/* Read a hexadecimal number (preceded by "0x") from the file FP while
paying attention to comment character '#'. */
-static inline unsigned
+static unsigned
read_hex (FILE *fp, bool *eof, bool *overflow)
{
int c;
@@ -636,7 +635,7 @@ load_charset (struct charset *charset, int control_flag)
else
{
if (! CHARSET_UNIFIED_P (charset))
- abort ();
+ emacs_abort ();
map = CHARSET_UNIFY_MAP (charset);
}
if (STRINGP (map))
@@ -1143,12 +1142,14 @@ usage: (define-charset-internal ...) */)
example, the IDs are stuffed into struct
coding_system.charbuf[i] entries, which are 'int'. */
int old_size = charset_table_size;
+ ptrdiff_t new_size = old_size;
struct charset *new_table =
- xpalloc (0, &charset_table_size, 1,
+ xpalloc (0, &new_size, 1,
min (INT_MAX, MOST_POSITIVE_FIXNUM),
sizeof *charset_table);
memcpy (new_table, charset_table, old_size * sizeof *new_table);
charset_table = new_table;
+ charset_table_size = new_size;
/* FIXME: This leaks memory, as the old charset_table becomes
unreachable. If the old charset table is charset_table_init
then this leak is intentional; otherwise, it's unclear.
@@ -1618,7 +1619,7 @@ only `ascii', `eight-bit-control', and `eight-bit-graphic'. */)
/* Return a unified character code for C (>= 0x110000). VAL is a
value of Vchar_unify_table for C; i.e. it is nil, an integer, or a
charset symbol. */
-int
+static int
maybe_unify_char (int c, Lisp_Object val)
{
struct charset *charset;
@@ -1724,8 +1725,12 @@ decode_char (struct charset *charset, unsigned int code)
{
c = char_index + CHARSET_CODE_OFFSET (charset);
if (CHARSET_UNIFIED_P (charset)
- && c > MAX_UNICODE_CHAR)
- MAYBE_UNIFY_CHAR (c);
+ && MAX_UNICODE_CHAR < c && c <= MAX_5_BYTE_CHAR)
+ {
+ /* Unify C with a Unicode character if possible. */
+ Lisp_Object val = CHAR_TABLE_REF (Vchar_unify_table, c);
+ c = maybe_unify_char (c, val);
+ }
}
}
@@ -2025,10 +2030,10 @@ CH in the charset. */)
c = XFASTINT (ch);
charset = CHAR_CHARSET (c);
if (! charset)
- abort ();
+ emacs_abort ();
code = ENCODE_CHAR (charset, c);
if (code == CHARSET_INVALID_CODE (charset))
- abort ();
+ emacs_abort ();
dimension = CHARSET_DIMENSION (charset);
for (val = Qnil; dimension > 0; dimension--)
{
@@ -2290,7 +2295,7 @@ init_charset (void)
{
Lisp_Object tempdir;
tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory);
- if (access (SSDATA (tempdir), 0) < 0)
+ if (! file_accessible_directory_p (SSDATA (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
diff --git a/src/charset.h b/src/charset.h
index 50d230489fe..b5fa36290c8 100644
--- a/src/charset.h
+++ b/src/charset.h
@@ -538,7 +538,6 @@ extern int charset_unibyte;
extern struct charset *char_charset (int, Lisp_Object, unsigned *);
extern Lisp_Object charset_attributes (int);
-extern int maybe_unify_char (int, Lisp_Object);
extern int decode_char (struct charset *, unsigned);
extern unsigned encode_char (struct charset *, int);
extern int string_xstring_p (Lisp_Object);
diff --git a/src/chartab.c b/src/chartab.c
index c14df0ebac6..7430235b4af 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "charset.h"
@@ -655,15 +655,6 @@ or a character code. Return VALUE. */)
return value;
}
-DEFUN ("set-char-table-default", Fset_char_table_default,
- Sset_char_table_default, 3, 3, 0,
- doc: /*
-This function is obsolete and has no effect. */)
- (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value)
-{
- return Qnil;
-}
-
/* 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. */
@@ -1415,7 +1406,6 @@ syms_of_chartab (void)
defsubr (&Sset_char_table_extra_slot);
defsubr (&Schar_table_range);
defsubr (&Sset_char_table_range);
- defsubr (&Sset_char_table_default);
defsubr (&Soptimize_char_table);
defsubr (&Smap_char_table);
defsubr (&Sunicode_property_table_internal);
diff --git a/src/cm.c b/src/cm.c
index 1922cd8140a..eda6430bafa 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "frame.h"
@@ -119,7 +118,7 @@ cmcheckmagic (struct tty_display_info *tty)
if (curX (tty) == FrameCols (tty))
{
if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
- abort ();
+ emacs_abort ();
if (tty->termscript)
putc ('\r', tty->termscript);
putc ('\r', tty->output);
diff --git a/src/cmds.c b/src/cmds.c
index 90d3cd6dced..453a4b67e57 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -19,7 +19,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "commands.h"
#include "character.h"
@@ -85,6 +85,7 @@ move_point (Lisp_Object n, bool forward)
DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "^p",
doc: /* Move point N characters forward (backward if N is negative).
On reaching end or beginning of buffer, stop and signal error.
+Interactively, N is the numeric prefix argument.
Depending on the bidirectional context, the movement may be to the
right or to the left on the screen. This is in contrast with
@@ -97,6 +98,7 @@ right or to the left on the screen. This is in contrast with
DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "^p",
doc: /* Move point N characters backward (forward if N is negative).
On attempt to pass beginning or end of buffer, stop and signal error.
+Interactively, N is the numeric prefix argument.
Depending on the bidirectional context, the movement may be to the
right or to the left on the screen. This is in contrast with
diff --git a/src/coding.c b/src/coding.c
index 02e7b34695e..56202e4861d 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -285,7 +285,6 @@ encode_coding_XXX (struct coding_system *coding)
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -344,6 +343,10 @@ Lisp_Object Qcoding_system_p, Qcoding_system_error;
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
@@ -416,7 +419,7 @@ enum iso_code_class_type
ISO_shift_out, /* ISO_CODE_SO (0x0E) */
ISO_shift_in, /* ISO_CODE_SI (0x0F) */
ISO_single_shift_2_7, /* ISO_CODE_SS2_7 (0x19) */
- ISO_escape, /* ISO_CODE_SO (0x1B) */
+ ISO_escape, /* ISO_CODE_ESC (0x1B) */
ISO_control_1, /* Control codes in the range
0x80..0x9F, except for the
following 3 codes. */
@@ -921,65 +924,18 @@ record_conversion_result (struct coding_system *coding,
/* Store multibyte form of the character C in P, and advance P to the
- end of the multibyte form. This is like CHAR_STRING_ADVANCE but it
- never calls MAYBE_UNIFY_CHAR. */
-
-#define CHAR_STRING_ADVANCE_NO_UNIFY(c, p) \
- do { \
- if ((c) <= MAX_1_BYTE_CHAR) \
- *(p)++ = (c); \
- else if ((c) <= MAX_2_BYTE_CHAR) \
- *(p)++ = (0xC0 | ((c) >> 6)), \
- *(p)++ = (0x80 | ((c) & 0x3F)); \
- else if ((c) <= MAX_3_BYTE_CHAR) \
- *(p)++ = (0xE0 | ((c) >> 12)), \
- *(p)++ = (0x80 | (((c) >> 6) & 0x3F)), \
- *(p)++ = (0x80 | ((c) & 0x3F)); \
- else if ((c) <= MAX_4_BYTE_CHAR) \
- *(p)++ = (0xF0 | (c >> 18)), \
- *(p)++ = (0x80 | ((c >> 12) & 0x3F)), \
- *(p)++ = (0x80 | ((c >> 6) & 0x3F)), \
- *(p)++ = (0x80 | (c & 0x3F)); \
- else if ((c) <= MAX_5_BYTE_CHAR) \
- *(p)++ = 0xF8, \
- *(p)++ = (0x80 | ((c >> 18) & 0x0F)), \
- *(p)++ = (0x80 | ((c >> 12) & 0x3F)), \
- *(p)++ = (0x80 | ((c >> 6) & 0x3F)), \
- *(p)++ = (0x80 | (c & 0x3F)); \
- else \
- (p) += BYTE8_STRING ((c) - 0x3FFF80, p); \
- } while (0)
+ end of the multibyte form. This used to be like CHAR_STRING_ADVANCE
+ without ever calling MAYBE_UNIFY_CHAR, but nowadays we don't call
+ MAYBE_UNIFY_CHAR in CHAR_STRING_ADVANCE. */
+#define CHAR_STRING_ADVANCE_NO_UNIFY(c, p) CHAR_STRING_ADVANCE(c, p)
/* Return the character code of character whose multibyte form is at
- P, and advance P to the end of the multibyte form. This is like
- STRING_CHAR_ADVANCE, but it never calls MAYBE_UNIFY_CHAR. */
-
-#define STRING_CHAR_ADVANCE_NO_UNIFY(p) \
- (!((p)[0] & 0x80) \
- ? *(p)++ \
- : ! ((p)[0] & 0x20) \
- ? ((p) += 2, \
- ((((p)[-2] & 0x1F) << 6) \
- | ((p)[-1] & 0x3F) \
- | ((unsigned char) ((p)[-2]) < 0xC2 ? 0x3FFF80 : 0))) \
- : ! ((p)[0] & 0x10) \
- ? ((p) += 3, \
- ((((p)[-3] & 0x0F) << 12) \
- | (((p)[-2] & 0x3F) << 6) \
- | ((p)[-1] & 0x3F))) \
- : ! ((p)[0] & 0x08) \
- ? ((p) += 4, \
- ((((p)[-4] & 0xF) << 18) \
- | (((p)[-3] & 0x3F) << 12) \
- | (((p)[-2] & 0x3F) << 6) \
- | ((p)[-1] & 0x3F))) \
- : ((p) += 5, \
- ((((p)[-4] & 0x3F) << 18) \
- | (((p)[-3] & 0x3F) << 12) \
- | (((p)[-2] & 0x3F) << 6) \
- | ((p)[-1] & 0x3F))))
+ P, and advance P to the end of the multibyte form. This used to be
+ like STRING_CHAR_ADVANCE without ever calling MAYBE_UNIFY_CHAR, but
+ nowadays STRING_CHAR_ADVANCE doesn't call MAYBE_UNIFY_CHAR. */
+#define STRING_CHAR_ADVANCE_NO_UNIFY(p) STRING_CHAR_ADVANCE(p)
/* Set coding->source from coding->src_object. */
@@ -2051,7 +2007,7 @@ emacs_mule_char (struct coding_system *coding, const unsigned char *src,
break;
default:
- abort ();
+ emacs_abort ();
}
CODING_DECODE_CHAR (coding, src, src_base, src_end,
CHARSET_FROM_ID (charset_ID), code, c);
@@ -2345,7 +2301,7 @@ decode_coding_emacs_mule (struct coding_system *coding)
int i;
if (charbuf_end - charbuf < cmp_status->length)
- abort ();
+ emacs_abort ();
for (i = 0; i < cmp_status->length; i++)
*charbuf++ = cmp_status->carryover[i];
coding->annotated = 1;
@@ -2619,7 +2575,7 @@ encode_coding_emacs_mule (struct coding_system *coding)
preferred_charset_id = -1;
break;
default:
- abort ();
+ emacs_abort ();
}
charbuf += -c - 1;
continue;
@@ -3482,7 +3438,7 @@ decode_coding_iso_2022 (struct coding_system *coding)
if (cmp_status->state != COMPOSING_NO)
{
if (charbuf_end - charbuf < cmp_status->length)
- abort ();
+ emacs_abort ();
for (i = 0; i < cmp_status->length; i++)
*charbuf++ = cmp_status->carryover[i];
coding->annotated = 1;
@@ -3864,7 +3820,7 @@ decode_coding_iso_2022 (struct coding_system *coding)
break;
default:
- abort ();
+ emacs_abort ();
}
if (cmp_status->state == COMPOSING_NO
@@ -4419,7 +4375,7 @@ encode_coding_iso_2022 (struct coding_system *coding)
preferred_charset_id = -1;
break;
default:
- abort ();
+ emacs_abort ();
}
charbuf += -c - 1;
continue;
@@ -4933,7 +4889,7 @@ encode_coding_sjis (struct coding_system *coding)
}
}
if (code == CHARSET_INVALID_CODE (charset))
- abort ();
+ emacs_abort ();
if (charset == charset_kanji)
{
int c1, c2;
@@ -5023,7 +4979,7 @@ encode_coding_big5 (struct coding_system *coding)
}
}
if (code == CHARSET_INVALID_CODE (charset))
- abort ();
+ emacs_abort ();
if (charset == charset_big5)
{
int c1, c2;
@@ -5107,6 +5063,7 @@ decode_coding_ccl (struct coding_system *coding)
while (1)
{
const unsigned char *p = src;
+ ptrdiff_t offset;
int i = 0;
if (multibytep)
@@ -5124,8 +5081,17 @@ decode_coding_ccl (struct coding_system *coding)
if (p == src_end && coding->mode & CODING_MODE_LAST_BLOCK)
ccl->last_block = 1;
+ /* As ccl_driver calls DECODE_CHAR, buffer may be relocated. */
+ charset_map_loaded = 0;
ccl_driver (ccl, source_charbuf, charbuf, i, charbuf_end - charbuf,
charset_list);
+ if (charset_map_loaded
+ && (offset = coding_change_source (coding)))
+ {
+ p += offset;
+ src += offset;
+ src_end += offset;
+ }
charbuf += ccl->produced;
if (multibytep)
src += source_byteidx[ccl->consumed];
@@ -5178,8 +5144,15 @@ encode_coding_ccl (struct coding_system *coding)
do
{
+ ptrdiff_t offset;
+
+ /* As ccl_driver calls DECODE_CHAR, buffer may be relocated. */
+ charset_map_loaded = 0;
ccl_driver (ccl, charbuf, destination_charbuf,
charbuf_end - charbuf, 1024, charset_list);
+ if (charset_map_loaded
+ && (offset = coding_change_destination (coding)))
+ dst += offset;
if (multibytep)
{
ASSURE_DESTINATION (ccl->produced * 2);
@@ -6332,6 +6305,9 @@ detect_coding (struct coding_system *coding)
{
category = coding_priorities[i];
this = coding_categories + category;
+ /* Some of this->detector (e.g. detect_coding_sjis)
+ require this information. */
+ coding->id = this->id;
if (this->id < 0)
{
/* No coding system of this category is defined. */
@@ -6853,7 +6829,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table,
[ -LENGTH ANNOTATION_MASK NCHARS NBYTES METHOD [ COMPONENTS... ] ]
*/
-static inline void
+static void
produce_composition (struct coding_system *coding, int *charbuf, ptrdiff_t pos)
{
int len;
@@ -6897,7 +6873,7 @@ produce_composition (struct coding_system *coding, int *charbuf, ptrdiff_t pos)
[ -LENGTH ANNOTATION_MASK NCHARS CHARSET-ID ]
*/
-static inline void
+static void
produce_charset (struct coding_system *coding, int *charbuf, ptrdiff_t pos)
{
ptrdiff_t from = pos - charbuf[2];
@@ -7132,7 +7108,7 @@ decode_coding (struct coding_system *coding)
position of a composition after POS (if any) or to LIMIT, and
return BUF. */
-static inline int *
+static int *
handle_composition_annotation (ptrdiff_t pos, ptrdiff_t limit,
struct coding_system *coding, int *buf,
ptrdiff_t *stop)
@@ -7190,7 +7166,7 @@ handle_composition_annotation (ptrdiff_t pos, ptrdiff_t limit,
*buf++ = XINT (XCAR (components));
}
else
- abort ();
+ emacs_abort ();
*head -= len;
}
}
@@ -7215,7 +7191,7 @@ handle_composition_annotation (ptrdiff_t pos, ptrdiff_t limit,
If the property value is nil, set *STOP to the position where the
property value is non-nil (limiting by LIMIT), and return BUF. */
-static inline int *
+static int *
handle_charset_annotation (ptrdiff_t pos, ptrdiff_t limit,
struct coding_system *coding, int *buf,
ptrdiff_t *stop)
@@ -7999,6 +7975,40 @@ preferred_coding_system (void)
return CODING_ID_NAME (id);
}
+#if defined (WINDOWSNT) || defined (CYGWIN)
+
+Lisp_Object
+from_unicode (Lisp_Object str)
+{
+ CHECK_STRING (str);
+ if (!STRING_MULTIBYTE (str) &&
+ SBYTES (str) & 1)
+ {
+ str = Fsubstring (str, make_number (0), make_number (-1));
+ }
+
+ return code_convert_string_norecord (str, Qutf_16le, 0);
+}
+
+wchar_t *
+to_unicode (Lisp_Object str, Lisp_Object *buf)
+{
+ *buf = code_convert_string_norecord (str, Qutf_16le, 1);
+ /* We need to make a another copy (in addition to the one made by
+ code_convert_string_norecord) to ensure that the final string is
+ _doubly_ zero terminated --- that is, that the string is
+ terminated by two zero bytes and one utf-16le null character.
+ Because strings are already terminated with a single zero byte,
+ we just add one additional zero. */
+ str = make_uninit_string (SBYTES (*buf) + 1);
+ memcpy (SDATA (str), SDATA (*buf), SBYTES (*buf));
+ SDATA (str) [SBYTES (*buf)] = '\0';
+ *buf = str;
+ return WCSDATA (*buf);
+}
+
+#endif /* WINDOWSNT || CYGWIN */
+
#ifdef emacs
/*** 8. Emacs Lisp library functions ***/
@@ -8460,7 +8470,7 @@ highest priority. */)
}
-static inline bool
+static bool
char_encodable_p (int c, Lisp_Object attrs)
{
Lisp_Object tail;
@@ -9428,7 +9438,7 @@ usage: (set-coding-system-priority &rest coding-systems) */)
&& changed[coding_priorities[j]])
j++;
if (j == coding_category_max)
- abort ();
+ emacs_abort ();
priorities[i] = coding_priorities[j];
}
@@ -10312,6 +10322,11 @@ syms_of_coding (void)
DEFSYM (Qutf_8, "utf-8");
DEFSYM (Qutf_8_emacs, "utf-8-emacs");
+#if defined (WINDOWSNT) || defined (CYGWIN)
+ /* No, not utf-16-le: that one has a BOM. */
+ DEFSYM (Qutf_16le, "utf-16le");
+#endif
+
DEFSYM (Qutf_16, "utf-16");
DEFSYM (Qbig, "big");
DEFSYM (Qlittle, "little");
diff --git a/src/coding.h b/src/coding.h
index c45d2ef86e2..192be58f083 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -646,10 +646,8 @@ struct coding_system
for file names, if any. */
#define ENCODE_FILE(name) \
(! NILP (Vfile_name_coding_system) \
- && !EQ (Vfile_name_coding_system, make_number (0)) \
? code_convert_string_norecord (name, Vfile_name_coding_system, 1) \
: (! NILP (Vdefault_file_name_coding_system) \
- && !EQ (Vdefault_file_name_coding_system, make_number (0)) \
? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 1) \
: name))
@@ -658,10 +656,8 @@ struct coding_system
for file names, if any. */
#define DECODE_FILE(name) \
(! NILP (Vfile_name_coding_system) \
- && !EQ (Vfile_name_coding_system, make_number (0)) \
? code_convert_string_norecord (name, Vfile_name_coding_system, 0) \
: (! NILP (Vdefault_file_name_coding_system) \
- && !EQ (Vdefault_file_name_coding_system, make_number (0)) \
? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 0) \
: name))
@@ -670,7 +666,6 @@ struct coding_system
for system functions, if any. */
#define ENCODE_SYSTEM(str) \
(! NILP (Vlocale_coding_system) \
- && !EQ (Vlocale_coding_system, make_number (0)) \
? code_convert_string_norecord (str, Vlocale_coding_system, 1) \
: str)
@@ -678,7 +673,6 @@ struct coding_system
for system functions, if any. */
#define DECODE_SYSTEM(str) \
(! NILP (Vlocale_coding_system) \
- && !EQ (Vlocale_coding_system, make_number (0)) \
? code_convert_string_norecord (str, Vlocale_coding_system, 0) \
: str)
@@ -707,6 +701,28 @@ extern void encode_coding_object (struct coding_system *,
Lisp_Object, ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t, Lisp_Object);
+#if defined (WINDOWSNT) || defined (CYGWIN)
+
+/* These functions use Lisp string objects to store the UTF-16LE
+ strings that modern versions of Windows expect. These strings are
+ not particularly useful to Lisp, and all Lisp strings should be
+ native Emacs multibyte. */
+
+/* Access the wide-character string stored in a Lisp string object. */
+#define WCSDATA(x) ((wchar_t *) SDATA (x))
+
+/* Convert the multi-byte string in STR to UTF-16LE encoded unibyte
+ string, and store it in *BUF. BUF may safely point to STR on entry. */
+extern wchar_t *to_unicode (Lisp_Object str, Lisp_Object *buf);
+
+/* Convert STR, a UTF-16LE encoded string embedded in a unibyte string
+ object, to a multi-byte Emacs string and return it. This function
+ calls code_convert_string_norecord internally and has all its
+ failure modes. STR itself is not modified. */
+extern Lisp_Object from_unicode (Lisp_Object str);
+
+#endif /* WINDOWSNT || CYGWIN */
+
/* Macros for backward compatibility. */
#define decode_coding_region(coding, from, to) \
diff --git a/src/commands.h b/src/commands.h
index 36f600cee01..510fce0e182 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -36,9 +36,6 @@ extern Lisp_Object control_x_map;
events until a non-ASCII event is acceptable as input. */
extern Lisp_Object unread_switch_frame;
-/* Nonzero means ^G can quit instantly */
-extern int immediate_quit;
-
/* Nonzero if input is coming from the keyboard */
#define INTERACTIVE (NILP (Vexecuting_kbd_macro) && !noninteractive)
diff --git a/src/composite.c b/src/composite.c
index eddabb66d33..bcde0a4c9e6 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -26,7 +26,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define COMPOSITE_INLINE EXTERN_INLINE
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -677,7 +676,7 @@ composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len)
ptrdiff_t i;
header = LGSTRING_HEADER (gstring);
- hash = h->hashfn (h, header);
+ hash = h->test.hashfn (&h->test, header);
if (len < 0)
{
ptrdiff_t j, glyph_len = LGSTRING_GLYPH_LEN (gstring);
@@ -1220,9 +1219,6 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
ptrdiff_t bytepos, ptrdiff_t endpos, struct window *w,
struct face *face, Lisp_Object string)
{
- if (endpos < 0)
- endpos = NILP (string) ? BEGV : 0;
-
if (cmp_it->ch == -2)
{
composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
@@ -1231,6 +1227,9 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
return 0;
}
+ if (endpos < 0)
+ endpos = NILP (string) ? BEGV : 0;
+
if (cmp_it->ch < 0)
{
/* We are looking at a static composition. */
@@ -1278,36 +1277,23 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
{
ptrdiff_t cpos = charpos, bpos = bytepos;
- while (1)
+ cmp_it->reversed_p = 1;
+ elt = XCAR (val);
+ if (cmp_it->lookback > 0)
{
- elt = XCAR (val);
- if (cmp_it->lookback > 0)
- {
- cpos = charpos - cmp_it->lookback;
- if (STRINGP (string))
- bpos = string_char_to_byte (string, cpos);
- else
- bpos = CHAR_TO_BYTE (cpos);
- }
- lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face,
- string);
- if (composition_gstring_p (lgstring)
- && cpos + LGSTRING_CHAR_LEN (lgstring) - 1 == charpos)
- break;
- /* Composition failed or didn't cover the current
- character. */
- if (cmp_it->lookback == 0)
- goto no_composition;
- lgstring = Qnil;
- /* Try to find a shorter composition that starts after CPOS. */
- composition_compute_stop_pos (cmp_it, charpos, bytepos, cpos,
- string);
- if (cmp_it->ch == -2 || cmp_it->stop_pos < charpos)
- goto no_composition;
- val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
- for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val));
+ cpos = charpos - cmp_it->lookback;
+ if (STRINGP (string))
+ bpos = string_char_to_byte (string, cpos);
+ else
+ bpos = CHAR_TO_BYTE (cpos);
}
- cmp_it->reversed_p = 1;
+ lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face,
+ string);
+ if (! composition_gstring_p (lgstring)
+ || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos)
+ /* Composition failed or didn't cover the current
+ character. */
+ goto no_composition;
}
if (NILP (lgstring))
goto no_composition;
@@ -1342,6 +1328,8 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
/* BYTEPOS is calculated in composition_compute_stop_pos */
bytepos = -1;
}
+ if (cmp_it->reversed_p)
+ endpos = -1;
composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
return 0;
}
@@ -1394,7 +1382,7 @@ composition_update_it (struct composition_it *cmp_it, ptrdiff_t charpos, ptrdiff
}
else
{
- /* automatic composition */
+ /* Automatic composition. */
Lisp_Object gstring = composition_gstring_from_id (cmp_it->id);
Lisp_Object glyph;
ptrdiff_t from;
diff --git a/src/composite.h b/src/composite.h
index 68f5b27ee42..9462b932c66 100644
--- a/src/composite.h
+++ b/src/composite.h
@@ -113,7 +113,7 @@ extern Lisp_Object composition_temp;
&& (end - start) == COMPOSITION_LENGTH (prop))
/* Return the Nth glyph of composition specified by CMP. CMP is a
- pointer to `struct composition'. */
+ pointer to `struct composition'. */
#define COMPOSITION_GLYPH(cmp, n) \
XINT (XVECTOR (XVECTOR (XHASH_TABLE (composition_hash_table) \
->key_and_value) \
diff --git a/src/conf_post.h b/src/conf_post.h
index f90ef90fb83..b1997e79081 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -40,11 +40,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif
#endif
-#ifdef SIGNAL_H_AHB
-#undef SIGNAL_H_AHB
-#include <signal.h>
-#endif
-
/* This silences a few compilation warnings on FreeBSD. */
#ifdef BSD_SYSTEM_AHB
#undef BSD_SYSTEM_AHB
@@ -95,7 +90,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
char *_getpty();
#endif
-#undef SA_RESTART /* not the same as defining BROKEN_SA_RESTART */
#endif /* IRIX6_5 */
#ifdef MSDOS
@@ -116,8 +110,17 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
#else
# define lstat stat
#endif
+/* The "portable" definition of _GL_INLINE on config.h does not work
+ with DJGPP GCC 3.4.4: it causes unresolved externals in sysdep.c,
+ although lib/execinfo.h is included and the inline functions there
+ are visible. */
+#if __GNUC__ < 4
+# define _GL_EXECINFO_INLINE inline
+#endif
/* End of gnulib-related stuff. */
+#define emacs_raise(sig) msdos_fatal_signal (sig)
+
/* Define one of these for easier conditionals. */
#ifdef HAVE_X_WINDOWS
/* We need a little extra space, see ../../lisp/loadup.el and the
@@ -138,22 +141,6 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
#endif
#endif /* MSDOS */
-#ifdef USG5_4
-/* Get FIONREAD from <sys/filio.h>. Get <sys/ttold.h> to get struct tchars.
- But get <termio.h> first to make sure ttold.h doesn't interfere. */
-#include <sys/wait.h>
-
-#ifdef emacs
-#include <sys/filio.h>
-#include <termio.h>
-#include <sys/ttold.h>
-#include <signal.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/termios.h>
-#endif
-#endif /* USG5_4 */
-
/* Mac OS X / GNUstep need a bit more pure memory. Of the existing knobs,
SYSTEM_PURESIZE_EXTRA seems like the least likely to cause problems. */
#ifdef HAVE_NS
@@ -164,10 +151,24 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
#endif
#endif
+#if defined HAVE_NTGUI && !defined DebPrint
+# ifdef EMACSDEBUG
+extern void _DebPrint (const char *fmt, ...);
+# define DebPrint(stuff) _DebPrint stuff
+# else
+# define DebPrint(stuff)
+# endif
+#endif
+
+#if defined CYGWIN && defined HAVE_NTGUI
+# define NTGUI_UNICODE /* Cygwin runs only on UNICODE-supporting systems */
+# define _WIN32_WINNT 0x500 /* Win2k */
+#endif
+
#ifdef emacs /* Don't do this for lib-src. */
/* Tell regex.c to use a type compatible with Emacs. */
#define RE_TRANSLATE_TYPE Lisp_Object
-#define RE_TRANSLATE(TBL, C) CHAR_TABLE_TRANSLATE (TBL, C)
+#define RE_TRANSLATE(TBL, C) char_table_translate (TBL, C)
#ifdef make_number
/* If make_number is a macro, use it. */
#define RE_TRANSLATE_P(TBL) (!EQ (TBL, make_number (0)))
@@ -177,10 +178,11 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
#endif
#endif
+/* Tell gnulib to omit support for openat-related functions having a
+ first argument other than AT_FDCWD. */
+#define GNULIB_SUPPORT_ONLY_AT_FDCWD
+
#include <string.h>
-/* If you think about removing the line below, note that the
- MS-Windows build relies on it for declaration of 'environ' needed
- by a few source files. */
#include <stdlib.h>
#if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
diff --git a/src/cygw32.c b/src/cygw32.c
new file mode 100644
index 00000000000..d9777d5e22e
--- /dev/null
+++ b/src/cygw32.c
@@ -0,0 +1,138 @@
+/* Cygwin support routines.
+ Copyright (C) 2011-2012 Free Software Foundation, Inc.
+
+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 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/>. */
+
+
+#include "cygw32.h"
+#include "character.h"
+#include "buffer.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+static Lisp_Object
+fchdir_unwind (Lisp_Object dir_fd)
+{
+ (void) fchdir (XFASTINT (dir_fd));
+ (void) close (XFASTINT (dir_fd));
+ return Qnil;
+}
+
+static void
+chdir_to_default_directory ()
+{
+ Lisp_Object new_cwd;
+ int old_cwd_fd = open (".", O_RDONLY | O_DIRECTORY);
+
+ if (old_cwd_fd == -1)
+ error ("could not open current directory: %s", strerror (errno));
+
+ record_unwind_protect (fchdir_unwind, make_number (old_cwd_fd));
+
+ new_cwd = Funhandled_file_name_directory (
+ Fexpand_file_name (build_string ("."), Qnil));
+ if (!STRINGP (new_cwd))
+ new_cwd = build_string ("/");
+
+ if (chdir (SDATA (ENCODE_FILE (new_cwd))))
+ error ("could not chdir: %s", strerror (errno));
+}
+
+static Lisp_Object
+conv_filename_to_w32_unicode (Lisp_Object in, int absolute_p)
+{
+ ssize_t converted_len;
+ Lisp_Object converted;
+ unsigned flags;
+ int count = SPECPDL_INDEX ();
+
+ chdir_to_default_directory ();
+
+ flags = CCP_POSIX_TO_WIN_W;
+ if (!absolute_p) {
+ flags |= CCP_RELATIVE;
+ }
+
+ in = ENCODE_FILE (in);
+
+ converted_len = cygwin_conv_path (flags, SDATA (in), NULL, 0);
+ if (converted_len < 2)
+ error ("cygwin_conv_path: %s", strerror (errno));
+
+ converted = make_uninit_string (converted_len - 1);
+ if (cygwin_conv_path (flags, SDATA (in),
+ SDATA (converted), converted_len))
+ error ("cygwin_conv_path: %s", strerror (errno));
+
+ return unbind_to (count, converted);
+}
+
+static Lisp_Object
+conv_filename_from_w32_unicode (const wchar_t* in, int absolute_p)
+{
+ ssize_t converted_len;
+ Lisp_Object converted;
+ unsigned flags;
+ int count = SPECPDL_INDEX ();
+
+ chdir_to_default_directory ();
+
+ flags = CCP_WIN_W_TO_POSIX;
+ if (!absolute_p) {
+ flags |= CCP_RELATIVE;
+ }
+
+ converted_len = cygwin_conv_path (flags, in, NULL, 0);
+ if (converted_len < 1)
+ error ("cygwin_conv_path: %s", strerror (errno));
+
+ converted = make_uninit_string (converted_len - 1 /*subtract terminator*/);
+ if (cygwin_conv_path (flags, in, SDATA (converted), converted_len))
+ error ("cygwin_conv_path: %s", strerror (errno));
+
+ return unbind_to (count, DECODE_FILE (converted));
+}
+
+DEFUN ("cygwin-convert-file-name-to-windows",
+ Fcygwin_convert_file_name_to_windows,
+ Scygwin_convert_file_name_to_windows,
+ 1, 2, 0,
+ doc: /* Convert PATH to a Windows path. If ABSOLUTE-P is
+non-nil, return an absolute path.*/)
+ (Lisp_Object path, Lisp_Object absolute_p)
+{
+ return from_unicode (
+ conv_filename_to_w32_unicode (path, EQ (absolute_p, Qnil) ? 0 : 1));
+}
+
+DEFUN ("cygwin-convert-file-name-from-windows",
+ Fcygwin_convert_file_name_from_windows,
+ Scygwin_convert_file_name_from_windows,
+ 1, 2, 0,
+ doc: /* Convert a Windows path to a Cygwin path. If ABSOLUTE-P
+is non-nil, return an absolute path.*/)
+ (Lisp_Object path, Lisp_Object absolute_p)
+{
+ return conv_filename_from_w32_unicode (to_unicode (path, &path),
+ EQ (absolute_p, Qnil) ? 0 : 1);
+}
+
+void
+syms_of_cygw32 (void)
+{
+ defsubr (&Scygwin_convert_file_name_from_windows);
+ defsubr (&Scygwin_convert_file_name_to_windows);
+}
diff --git a/src/cygw32.h b/src/cygw32.h
new file mode 100644
index 00000000000..51571913fd1
--- /dev/null
+++ b/src/cygw32.h
@@ -0,0 +1,39 @@
+/* Header for Cygwin support routines.
+ Copyright (C) 2011-2012 Free Software Foundation, Inc.
+
+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 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/>. */
+
+#ifndef CYGW32_H
+#define CYGW32_H
+#include <config.h>
+#include <windef.h>
+#include <sys/cygwin.h>
+#include <wchar.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <limits.h>
+#include <errno.h>
+#include <math.h>
+#include <setjmp.h>
+
+#include "lisp.h"
+#include "coding.h"
+
+extern void syms_of_cygw32 (void);
+extern char * w32_strerror (int error_no);
+
+#endif /* CYGW32_H */
diff --git a/src/data.c b/src/data.c
index a93cd169bf5..540c91bd4a5 100644
--- a/src/data.c
+++ b/src/data.c
@@ -19,9 +19,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#include <intprops.h>
@@ -36,19 +34,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "font.h"
#include "keymap.h"
-#include <float.h>
-/* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
-#ifndef IEEE_FLOATING_POINT
-#if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
-#define IEEE_FLOATING_POINT 1
-#else
-#define IEEE_FLOATING_POINT 0
-#endif
-#endif
-
-#include <math.h>
-
Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound;
static Lisp_Object Qsubr;
Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
@@ -77,8 +62,8 @@ Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
Lisp_Object Qcdr;
static Lisp_Object Qad_advice_info, Qad_activate_internal;
-Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
-Lisp_Object Qoverflow_error, Qunderflow_error;
+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;
@@ -97,6 +82,7 @@ static Lisp_Object Qdefun;
Lisp_Object Qthread, Qmutex, Qcondition_variable;
Lisp_Object Qinteractive_form;
+static Lisp_Object Qdefalias_fset_function;
static void swap_in_symval_forwarding (struct Lisp_Symbol *, struct Lisp_Buffer_Local_Value *);
@@ -109,7 +95,7 @@ wrong_type_argument (register Lisp_Object predicate, register Lisp_Object value)
to try and do that by checking the tagbits, but nowadays all
tagbits are potentially valid. */
/* if ((unsigned int) XTYPE (value) >= Lisp_Type_Limit)
- * abort (); */
+ * emacs_abort (); */
xsignal2 (Qwrong_type_argument, predicate, value);
}
@@ -183,7 +169,7 @@ for example, (type-of 1) returns `integer'. */)
case Lisp_Misc_Float:
return Qfloat;
}
- abort ();
+ emacs_abort ();
case Lisp_Vectorlike:
if (WINDOW_CONFIGURATIONP (object))
@@ -224,7 +210,7 @@ for example, (type-of 1) returns `integer'. */)
return Qfloat;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -496,7 +482,7 @@ DEFUN ("condition-variable-p", Fcondition_variable_p, Scondition_variable_p,
return Qnil;
}
-/* Extract and set components of lists */
+/* Extract and set components of lists. */
DEFUN ("car", Fcar, Scar, 1, 1, 0,
doc: /* Return the car of LIST. If arg is nil, return nil.
@@ -557,7 +543,9 @@ DEFUN ("setcdr", Fsetcdr, Ssetcdr, 2, 2, 0,
/* Extract and set components of symbols. */
DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0,
- doc: /* Return t if SYMBOL's value is not void. */)
+ doc: /* Return t if SYMBOL's value is not void.
+Note that if `lexical-binding' is in effect, this refers to the
+global value outside of any lexical scope. */)
(register Lisp_Object symbol)
{
Lisp_Object valcontents;
@@ -588,18 +576,19 @@ DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0,
/* In set_internal, we un-forward vars when their value is
set to Qunbound. */
return Qt;
- default: abort ();
+ default: emacs_abort ();
}
return (EQ (valcontents, Qunbound) ? Qnil : Qt);
}
+/* FIXME: Make it an alias for function-symbol! */
DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0,
doc: /* Return t if SYMBOL's function definition is not void. */)
(register Lisp_Object symbol)
{
CHECK_SYMBOL (symbol);
- return EQ (XSYMBOL (symbol)->function, Qunbound) ? Qnil : Qt;
+ return NILP (XSYMBOL (symbol)->function) ? Qnil : Qt;
}
DEFUN ("makunbound", Fmakunbound, Smakunbound, 1, 1, 0,
@@ -615,14 +604,14 @@ Return SYMBOL. */)
}
DEFUN ("fmakunbound", Ffmakunbound, Sfmakunbound, 1, 1, 0,
- doc: /* Make SYMBOL's function definition be void.
+ doc: /* Make SYMBOL's function definition be nil.
Return SYMBOL. */)
(register Lisp_Object symbol)
{
CHECK_SYMBOL (symbol);
if (NILP (symbol) || EQ (symbol, Qt))
xsignal1 (Qsetting_constant, symbol);
- set_symbol_function (symbol, Qunbound);
+ set_symbol_function (symbol, Qnil);
return symbol;
}
@@ -631,9 +620,7 @@ DEFUN ("symbol-function", Fsymbol_function, Ssymbol_function, 1, 1, 0,
(register Lisp_Object symbol)
{
CHECK_SYMBOL (symbol);
- if (!EQ (XSYMBOL (symbol)->function, Qunbound))
return XSYMBOL (symbol)->function;
- xsignal1 (Qvoid_function, symbol);
}
DEFUN ("symbol-plist", Fsymbol_plist, Ssymbol_plist, 1, 1, 0,
@@ -660,27 +647,18 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
(register Lisp_Object symbol, Lisp_Object definition)
{
register Lisp_Object function;
-
CHECK_SYMBOL (symbol);
- if (NILP (symbol) || EQ (symbol, Qt))
- xsignal1 (Qsetting_constant, symbol);
function = XSYMBOL (symbol)->function;
- if (!NILP (Vautoload_queue) && !EQ (function, Qunbound))
+ if (!NILP (Vautoload_queue) && !NILP (function))
Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue);
- if (CONSP (function) && EQ (XCAR (function), Qautoload))
+ if (AUTOLOADP (function))
Fput (symbol, Qautoload, XCDR (function));
set_symbol_function (symbol, definition);
- /* Handle automatic advice activation. */
- if (CONSP (XSYMBOL (symbol)->plist)
- && !NILP (Fget (symbol, Qad_advice_info)))
- {
- call2 (Qad_activate_internal, symbol, Qnil);
- definition = XSYMBOL (symbol)->function;
- }
+
return definition;
}
@@ -694,15 +672,32 @@ The return value is undefined. */)
(register Lisp_Object symbol, Lisp_Object definition, Lisp_Object docstring)
{
CHECK_SYMBOL (symbol);
- if (CONSP (XSYMBOL (symbol)->function)
- && EQ (XCAR (XSYMBOL (symbol)->function), Qautoload))
- LOADHIST_ATTACH (Fcons (Qt, symbol));
if (!NILP (Vpurify_flag)
/* If `definition' is a keymap, immutable (and copying) is wrong. */
&& !KEYMAPP (definition))
definition = Fpurecopy (definition);
- definition = Ffset (symbol, definition);
- LOADHIST_ATTACH (Fcons (Qdefun, symbol));
+
+ {
+ bool autoload = AUTOLOADP (definition);
+ if (NILP (Vpurify_flag) || !autoload)
+ { /* Only add autoload entries after dumping, because the ones before are
+ not useful and else we get loads of them from the loaddefs.el. */
+
+ if (AUTOLOADP (XSYMBOL (symbol)->function))
+ /* Remember that the function was already an autoload. */
+ LOADHIST_ATTACH (Fcons (Qt, symbol));
+ LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol));
+ }
+ }
+
+ { /* Handle automatic advice activation. */
+ Lisp_Object hook = Fget (symbol, Qdefalias_fset_function);
+ if (!NILP (hook))
+ call2 (hook, symbol, definition);
+ else
+ Ffset (symbol, definition);
+ }
+
if (!NILP (docstring))
Fput (symbol, Qfunction_documentation, docstring);
/* We used to return `definition', but now that `defun' and `defmacro' expand
@@ -732,12 +727,10 @@ function with `&rest' args, or `unevalled' for a special form. */)
CHECK_SUBR (subr);
minargs = XSUBR (subr)->min_args;
maxargs = XSUBR (subr)->max_args;
- if (maxargs == MANY)
- return Fcons (make_number (minargs), Qmany);
- else if (maxargs == UNEVALLED)
- return Fcons (make_number (minargs), Qunevalled);
- else
- return Fcons (make_number (minargs), make_number (maxargs));
+ return Fcons (make_number (minargs),
+ maxargs == MANY ? Qmany
+ : maxargs == UNEVALLED ? Qunevalled
+ : make_number (maxargs));
}
DEFUN ("subr-name", Fsubr_name, Ssubr_name, 1, 1, 0,
@@ -759,11 +752,11 @@ Value, if non-nil, is a list \(interactive SPEC). */)
{
Lisp_Object fun = indirect_function (cmd); /* Check cycles. */
- if (NILP (fun) || EQ (fun, Qunbound))
+ if (NILP (fun))
return Qnil;
/* Use an `interactive-form' property if present, analogous to the
- function-documentation property. */
+ function-documentation property. */
fun = cmd;
while (SYMBOLP (fun))
{
@@ -787,6 +780,8 @@ Value, if non-nil, is a list \(interactive SPEC). */)
if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE)
return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE));
}
+ else if (AUTOLOADP (fun))
+ return Finteractive_form (Fautoload_do_load (fun, cmd, Qnil));
else if (CONSP (fun))
{
Lisp_Object funcar = XCAR (fun);
@@ -794,14 +789,6 @@ Value, if non-nil, is a list \(interactive SPEC). */)
return Fassq (Qinteractive, Fcdr (Fcdr (XCDR (fun))));
else if (EQ (funcar, Qlambda))
return Fassq (Qinteractive, Fcdr (XCDR (fun)));
- else if (EQ (funcar, Qautoload))
- {
- struct gcpro gcpro1;
- GCPRO1 (cmd);
- Fautoload_do_load (fun, cmd, Qnil);
- UNGCPRO;
- return Finteractive_form (cmd);
- }
}
return Qnil;
}
@@ -901,7 +888,7 @@ do_symval_forwarding (register union Lisp_Fwd *valcontents)
don't think anything will break. --lorentey */
return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
+ (char *)FRAME_KBOARD (SELECTED_FRAME ()));
- default: abort ();
+ default: emacs_abort ();
}
}
@@ -987,12 +974,14 @@ store_symval_forwarding (union Lisp_Fwd *valcontents, register Lisp_Object newva
break;
default:
- abort (); /* goto def; */
+ emacs_abort (); /* goto def; */
}
}
-/* Set up SYMBOL to refer to its global binding.
- This makes it safe to alter the status of other bindings. */
+/* Set up SYMBOL to refer to its global binding. This makes it safe
+ to alter the status of other bindings. BEWARE: this may be called
+ during the mark phase of GC, where we assume that Lisp_Object slots
+ of BLV are marked after this function has changed them. */
void
swap_in_global_binding (struct Lisp_Symbol *symbol)
@@ -1051,7 +1040,7 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_
else
{
tem1 = assq_no_quit (var, BVAR (current_buffer, local_var_alist));
- XSETBUFFER (blv->where, current_buffer);
+ set_blv_where (blv, Fcurrent_buffer ());
}
}
if (!(blv->found = !NILP (tem1)))
@@ -1092,12 +1081,14 @@ find_symbol_value (Lisp_Object symbol)
/* FALLTHROUGH */
case SYMBOL_FORWARDED:
return do_symval_forwarding (SYMBOL_FWD (sym));
- default: abort ();
+ default: emacs_abort ();
}
}
DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0,
- doc: /* Return SYMBOL's value. Error if that is void. */)
+ doc: /* Return SYMBOL's value. Error if that is void.
+Note that if `lexical-binding' is in effect, this returns the
+global value outside of any lexical scope. */)
(Lisp_Object symbol)
{
Lisp_Object val;
@@ -1205,7 +1196,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
the default binding is loaded, the loaded binding may be the
wrong one. */
if (!EQ (blv->where, where)
- /* Also unload a global binding (if the var is local_if_set). */
+ /* Also unload a global binding (if the var is local_if_set). */
|| (EQ (blv->valcell, blv->defcell)))
{
/* The currently loaded binding is not necessarily valid.
@@ -1302,7 +1293,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
store_symval_forwarding (/* sym, */ innercontents, newval, buf);
break;
}
- default: abort ();
+ default: emacs_abort ();
}
return;
}
@@ -1353,7 +1344,7 @@ default_value (Lisp_Object symbol)
/* For other variables, get the current value. */
return do_symval_forwarding (valcontents);
}
- default: abort ();
+ default: emacs_abort ();
}
}
@@ -1451,7 +1442,7 @@ for this variable. */)
else
return Fset (symbol, value);
}
- default: abort ();
+ default: emacs_abort ();
}
}
@@ -1575,7 +1566,7 @@ The function `default-value' gets the default value and `set-default' sets it.
else if (BUFFER_OBJFWDP (valcontents.fwd))
return variable;
break;
- default: abort ();
+ default: emacs_abort ();
}
if (sym->constant)
@@ -1648,7 +1639,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
error ("Symbol %s may not be buffer-local",
SDATA (SYMBOL_NAME (variable)));
break;
- default: abort ();
+ default: emacs_abort ();
}
if (sym->constant)
@@ -1755,7 +1746,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
if (blv->frame_local)
return variable;
break;
- default: abort ();
+ default: emacs_abort ();
}
/* Get rid of this buffer's alist element, if any. */
@@ -1837,7 +1828,7 @@ frame-local bindings). */)
error ("Symbol %s may not be frame-local",
SDATA (SYMBOL_NAME (variable)));
break;
- default: abort ();
+ default: emacs_abort ();
}
if (sym->constant)
@@ -1914,18 +1905,18 @@ BUFFER defaults to the current buffer. */)
}
return Qnil;
}
- default: abort ();
+ default: emacs_abort ();
}
}
DEFUN ("local-variable-if-set-p", Flocal_variable_if_set_p, Slocal_variable_if_set_p,
1, 2, 0,
- doc: /* Non-nil if VARIABLE will be local in buffer BUFFER when set there.
-More precisely, this means that setting the variable \(with `set' or`setq'),
-while it does not have a `let'-style binding that was made in BUFFER,
-will produce a buffer local binding. See Info node
-`(elisp)Creating Buffer-Local'.
-BUFFER defaults to the current buffer. */)
+ doc: /* Non-nil if VARIABLE is local in buffer BUFFER when set there.
+BUFFER defaults to the current buffer.
+
+More precisely, return non-nil if either VARIABLE already has a local
+value in BUFFER, or if VARIABLE is automatically buffer-local (see
+`make-variable-buffer-local'). */)
(register Lisp_Object variable, Lisp_Object buffer)
{
struct Lisp_Symbol *sym;
@@ -1949,7 +1940,7 @@ BUFFER defaults to the current buffer. */)
case SYMBOL_FORWARDED:
/* All BUFFER_OBJFWD slots become local if they are set. */
return (BUFFER_OBJFWDP (SYMBOL_FWD (sym)) ? Qt : Qnil);
- default: abort ();
+ default: emacs_abort ();
}
}
@@ -1993,7 +1984,7 @@ If the current binding is global (the default), the value is nil. */)
return SYMBOL_BLV (sym)->where;
else
return Qnil;
- default: abort ();
+ default: emacs_abort ();
}
}
@@ -2057,10 +2048,10 @@ indirect_function (register Lisp_Object object)
for (;;)
{
- if (!SYMBOLP (hare) || EQ (hare, Qunbound))
+ if (!SYMBOLP (hare) || NILP (hare))
break;
hare = XSYMBOL (hare)->function;
- if (!SYMBOLP (hare) || EQ (hare, Qunbound))
+ if (!SYMBOLP (hare) || NILP (hare))
break;
hare = XSYMBOL (hare)->function;
@@ -2087,10 +2078,10 @@ function chain of symbols. */)
/* Optimize for no indirection. */
result = object;
- if (SYMBOLP (result) && !EQ (result, Qunbound)
+ if (SYMBOLP (result) && !NILP (result)
&& (result = XSYMBOL (result)->function, SYMBOLP (result)))
result = indirect_function (result);
- if (!EQ (result, Qunbound))
+ if (!NILP (result))
return result;
if (NILP (noerror))
@@ -2309,7 +2300,7 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison)
return Qnil;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -2745,10 +2736,10 @@ usage: (* &rest NUMBERS-OR-MARKERS) */)
return arith_driver (Amult, nargs, args);
}
-DEFUN ("/", Fquo, Squo, 2, MANY, 0,
+DEFUN ("/", Fquo, Squo, 1, MANY, 0,
doc: /* Return first argument divided by all the remaining arguments.
The arguments must be numbers or markers.
-usage: (/ DIVIDEND DIVISOR &rest DIVISORS) */)
+usage: (/ DIVIDEND &rest DIVISORS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
ptrdiff_t argnum;
@@ -2775,28 +2766,6 @@ Both must be integers or markers. */)
return val;
}
-#ifndef HAVE_FMOD
-double
-fmod (double f1, double f2)
-{
- double r = f1;
-
- if (f2 < 0.0)
- f2 = -f2;
-
- /* If the magnitude of the result exceeds that of the divisor, or
- the sign of the result does not agree with that of the dividend,
- iterate with the reduced value. This does not yield a
- particularly accurate result, but at least it will be in the
- range promised by fmod. */
- do
- r -= f2 * floor (r / f2);
- while (f2 <= (r < 0 ? -r : r) || ((r < 0) != (f1 < 0) && ! isnan (r)));
-
- return r;
-}
-#endif /* ! HAVE_FMOD */
-
DEFUN ("mod", Fmod, Smod, 2, 2, 0,
doc: /* Return X modulo Y.
The result falls between zero (inclusive) and Y (exclusive).
@@ -3138,6 +3107,7 @@ syms_of_data (void)
DEFSYM (Qfont_object, "font-object");
DEFSYM (Qinteractive_form, "interactive-form");
+ DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
defsubr (&Sindirect_variable);
defsubr (&Sinteractive_form);
@@ -3249,29 +3219,3 @@ syms_of_data (void)
Vmost_negative_fixnum = make_number (MOST_NEGATIVE_FIXNUM);
XSYMBOL (intern_c_string ("most-negative-fixnum"))->constant = 1;
}
-
-#ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
-_Noreturn
-#endif
-static void
-arith_error (int signo)
-{
- sigsetmask (SIGEMPTYMASK);
-
- SIGNAL_THREAD_CHECK (signo);
- xsignal0 (Qarith_error);
-}
-
-void
-init_data (void)
-{
- /* Don't do this if just dumping out.
- We don't want to call `signal' in this case
- so that we don't have trouble with dumping
- signal-delivering routines in an inconsistent state. */
-#ifndef CANNOT_DUMP
- if (!initialized)
- return;
-#endif /* CANNOT_DUMP */
- signal (SIGFPE, arith_error);
-}
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 901820648cb..da8bbb1e5d7 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_DBUS
#include <stdio.h>
#include <dbus/dbus.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "frame.h"
#include "termhooks.h"
@@ -32,6 +32,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define DBUS_NUM_MESSAGE_TYPES 5
#endif
+
+/* Some platforms define the symbol "interface", but we want to use it
+ * as a variable name below. */
+
+#ifdef interface
+#undef interface
+#endif
+
/* Subroutines. */
static Lisp_Object Qdbus_init_bus;
@@ -291,8 +299,8 @@ xd_symbol_to_dbus_type (Lisp_Object object)
} \
} while (0)
-#if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \
- || XD_DBUS_VALIDATE_OBJECT || HAVE_DBUS_VALIDATE_MEMBER)
+#if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \
+ || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER)
#define XD_DBUS_VALIDATE_OBJECT(object, func) \
do { \
if (!NILP (object)) \
@@ -1195,7 +1203,7 @@ this connection to those buses. */)
xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses);
/* We do not want to abort. */
- putenv ((char *) "DBUS_FATAL_WARNINGS=0");
+ xputenv ("DBUS_FATAL_WARNINGS=0");
/* Cleanup. */
dbus_error_free (&derror);
diff --git a/src/deps.mk b/src/deps.mk
index c7316a24dad..beca5f7c6bc 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -128,6 +128,7 @@ image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \
indent.o: indent.c frame.h window.h indent.h buffer.h lisp.h $(config_h) \
termchar.h termopts.h disptab.h region-cache.h character.h category.h \
keyboard.h systime.h coding.h $(INTERVALS_H) globals.h
+inotify.o: inotify.c lisp.h coding.h process.h keyboard.h frame.h termhooks.h
insdel.o: insdel.c window.h buffer.h $(INTERVALS_H) blockinput.h character.h \
atimer.h systime.h region-cache.h lisp.h globals.h $(config_h)
keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \
diff --git a/src/dired.c b/src/dired.c
index fa293258107..1fda9e8b371 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <setjmp.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -32,44 +31,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <unistd.h>
-/* The d_nameln member of a struct dirent includes the '\0' character
- on some systems, but not on others. What's worse, you can't tell
- at compile-time which one it will be, since it really depends on
- the sort of system providing the filesystem you're reading from,
- not the system you are running on. Paul Eggert
- <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
- SunOS 4.1.2 host, reading a directory that is remote-mounted from a
- Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
-
- Since applying strlen to the name always works, we'll just do that. */
-#define NAMLEN(p) strlen (p->d_name)
-
-#ifdef HAVE_DIRENT_H
-
#include <dirent.h>
-#define DIRENTRY struct dirent
-
-#else /* not HAVE_DIRENT_H */
-
-#include <sys/dir.h>
-#include <sys/stat.h>
-
-#define DIRENTRY struct direct
-
-extern DIR *opendir (char *);
-extern struct direct *readdir (DIR *);
-
-#endif /* HAVE_DIRENT_H */
-
#include <filemode.h>
#include <stat-time.h>
-#ifdef MSDOS
-#define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
-#else
-#define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
-#endif
-
#include "lisp.h"
#include "systime.h"
#include "character.h"
@@ -89,6 +54,17 @@ static Lisp_Object Qfile_attributes_lessp;
static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
+/* Return the number of bytes in DP's name. */
+static ptrdiff_t
+dirent_namelen (struct dirent *dp)
+{
+#ifdef _D_EXACT_NAMLEN
+ return _D_EXACT_NAMLEN (dp);
+#else
+ return strlen (dp->d_name);
+#endif
+}
+
#ifdef WINDOWSNT
Lisp_Object
directory_files_internal_w32_unwind (Lisp_Object arg)
@@ -102,9 +78,9 @@ static Lisp_Object
directory_files_internal_unwind (Lisp_Object dh)
{
DIR *d = (DIR *) XSAVE_VALUE (dh)->pointer;
- BLOCK_INPUT;
+ block_input ();
closedir (d);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -125,7 +101,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
bool needsep = 0;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
- DIRENTRY *dp;
+ struct dirent *dp;
#ifdef WINDOWSNT
Lisp_Object w32_save = Qnil;
#endif
@@ -165,9 +141,9 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
/* 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! */
- BLOCK_INPUT;
+ block_input ();
d = opendir (SSDATA (dirfilename));
- UNBLOCK_INPUT;
+ unblock_input ();
if (d == NULL)
report_file_error ("Opening directory", Fcons (directory, Qnil));
@@ -210,110 +186,103 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
/* Loop reading blocks until EOF or error. */
for (;;)
{
+ ptrdiff_t len;
+ bool wanted = 0;
+ Lisp_Object name, finalname;
+ struct gcpro gcpro1, gcpro2;
+
errno = 0;
dp = readdir (d);
+ if (!dp)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ {
+ QUIT;
+ continue;
+ }
+ break;
+ }
- if (dp == NULL && (0
-#ifdef EAGAIN
- || errno == EAGAIN
-#endif
-#ifdef EINTR
- || errno == EINTR
-#endif
- ))
- { QUIT; continue; }
+ len = dirent_namelen (dp);
+ name = finalname = make_unibyte_string (dp->d_name, len);
+ GCPRO2 (finalname, name);
- if (dp == NULL)
- break;
+ /* Note: DECODE_FILE can GC; it should protect its argument,
+ though. */
+ name = DECODE_FILE (name);
+ len = SBYTES (name);
- if (DIRENTRY_NONEMPTY (dp))
+ /* Now that we have unwind_protect in place, we might as well
+ allow matching to be interrupted. */
+ immediate_quit = 1;
+ QUIT;
+
+ if (NILP (match)
+ || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0)))
+ wanted = 1;
+
+ immediate_quit = 0;
+
+ if (wanted)
{
- ptrdiff_t len;
- bool wanted = 0;
- Lisp_Object name, finalname;
- struct gcpro gcpro1, gcpro2;
+ if (!NILP (full))
+ {
+ Lisp_Object fullname;
+ ptrdiff_t nbytes = len + directory_nbytes + needsep;
+ ptrdiff_t nchars;
- len = NAMLEN (dp);
- name = finalname = make_unibyte_string (dp->d_name, len);
- GCPRO2 (finalname, name);
+ fullname = make_uninit_multibyte_string (nbytes, nbytes);
+ memcpy (SDATA (fullname), SDATA (directory),
+ directory_nbytes);
- /* Note: DECODE_FILE can GC; it should protect its argument,
- though. */
- name = DECODE_FILE (name);
- len = SBYTES (name);
+ if (needsep)
+ SSET (fullname, directory_nbytes, DIRECTORY_SEP);
- /* Now that we have unwind_protect in place, we might as well
- allow matching to be interrupted. */
- immediate_quit = 1;
- QUIT;
+ memcpy (SDATA (fullname) + directory_nbytes + needsep,
+ SDATA (name), len);
- if (NILP (match)
- || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0)))
- wanted = 1;
+ nchars = chars_in_text (SDATA (fullname), nbytes);
- immediate_quit = 0;
+ /* Some bug somewhere. */
+ if (nchars > nbytes)
+ emacs_abort ();
- if (wanted)
- {
- if (!NILP (full))
- {
- Lisp_Object fullname;
- ptrdiff_t nbytes = len + directory_nbytes + needsep;
- ptrdiff_t nchars;
-
- fullname = make_uninit_multibyte_string (nbytes, nbytes);
- memcpy (SDATA (fullname), SDATA (directory),
- directory_nbytes);
-
- if (needsep)
- SSET (fullname, directory_nbytes, DIRECTORY_SEP);
-
- memcpy (SDATA (fullname) + directory_nbytes + needsep,
- SDATA (name), len);
-
- nchars = chars_in_text (SDATA (fullname), nbytes);
-
- /* Some bug somewhere. */
- if (nchars > nbytes)
- abort ();
-
- STRING_SET_CHARS (fullname, nchars);
- if (nchars == nbytes)
- STRING_SET_UNIBYTE (fullname);
-
- finalname = fullname;
- }
- else
- finalname = name;
-
- if (attrs)
- {
- /* Construct an expanded filename for the directory entry.
- Use the decoded names for input to Ffile_attributes. */
- Lisp_Object decoded_fullname, fileattrs;
- struct gcpro gcpro1, gcpro2;
-
- decoded_fullname = fileattrs = Qnil;
- GCPRO2 (decoded_fullname, fileattrs);
-
- /* Both Fexpand_file_name and Ffile_attributes can GC. */
- decoded_fullname = Fexpand_file_name (name, directory);
- fileattrs = Ffile_attributes (decoded_fullname, id_format);
-
- list = Fcons (Fcons (finalname, fileattrs), list);
- UNGCPRO;
- }
- else
- list = Fcons (finalname, list);
+ STRING_SET_CHARS (fullname, nchars);
+ if (nchars == nbytes)
+ STRING_SET_UNIBYTE (fullname);
+
+ finalname = fullname;
}
+ else
+ finalname = name;
- UNGCPRO;
+ if (attrs)
+ {
+ /* Construct an expanded filename for the directory entry.
+ Use the decoded names for input to Ffile_attributes. */
+ Lisp_Object decoded_fullname, fileattrs;
+ struct gcpro gcpro1, gcpro2;
+
+ decoded_fullname = fileattrs = Qnil;
+ GCPRO2 (decoded_fullname, fileattrs);
+
+ /* Both Fexpand_file_name and Ffile_attributes can GC. */
+ decoded_fullname = Fexpand_file_name (name, directory);
+ fileattrs = Ffile_attributes (decoded_fullname, id_format);
+
+ list = Fcons (Fcons (finalname, fileattrs), list);
+ UNGCPRO;
+ }
+ else
+ list = Fcons (finalname, list);
}
+
+ UNGCPRO;
}
- BLOCK_INPUT;
+ block_input ();
closedir (d);
- UNBLOCK_INPUT;
+ unblock_input ();
#ifdef WINDOWSNT
if (attrs)
Vw32_get_true_file_attributes = w32_save;
@@ -443,7 +412,8 @@ These are all file names in directory DIRECTORY which begin with FILE. */)
return file_name_completion (file, directory, 1, Qnil);
}
-static int file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr);
+static int file_name_completion_stat (Lisp_Object dirname, struct dirent *dp,
+ struct stat *st_addr);
static Lisp_Object Qdefault_directory;
static Lisp_Object
@@ -487,9 +457,9 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
encoded_dir = ENCODE_FILE (dirname);
- BLOCK_INPUT;
+ block_input ();
d = opendir (SSDATA (Fdirectory_file_name (encoded_dir)));
- UNBLOCK_INPUT;
+ unblock_input ();
if (!d)
report_file_error ("Opening directory", Fcons (dirname, Qnil));
@@ -500,29 +470,26 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
/* (att3b compiler bug requires do a null comparison this way) */
while (1)
{
- DIRENTRY *dp;
+ struct dirent *dp;
ptrdiff_t len;
bool canexclude = 0;
errno = 0;
dp = readdir (d);
- if (dp == NULL && (0
-# ifdef EAGAIN
- || errno == EAGAIN
-# endif
-# ifdef EINTR
- || errno == EINTR
-# endif
- ))
- { QUIT; continue; }
-
- if (!dp) break;
+ if (!dp)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ {
+ QUIT;
+ continue;
+ }
+ break;
+ }
- len = NAMLEN (dp);
+ len = dirent_namelen (dp);
QUIT;
- if (! DIRENTRY_NONEMPTY (dp)
- || len < SCHARS (encoded_file)
+ if (len < SCHARS (encoded_file)
|| 0 <= scmp (dp->d_name, SSDATA (encoded_file),
SCHARS (encoded_file)))
continue;
@@ -807,9 +774,10 @@ scmp (const char *s1, const char *s2, ptrdiff_t len)
}
static int
-file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr)
+file_name_completion_stat (Lisp_Object dirname, struct dirent *dp,
+ struct stat *st_addr)
{
- ptrdiff_t len = NAMLEN (dp);
+ ptrdiff_t len = dirent_namelen (dp);
ptrdiff_t pos = SCHARS (dirname);
int value;
USE_SAFE_ALLOCA;
@@ -852,7 +820,7 @@ stat_uname (struct stat *st)
#ifdef WINDOWSNT
return st->st_uname;
#else
- struct passwd *pw = (struct passwd *) getpwuid (st->st_uid);
+ struct passwd *pw = getpwuid (st->st_uid);
if (pw)
return pw->pw_name;
@@ -867,7 +835,7 @@ stat_gname (struct stat *st)
#ifdef WINDOWSNT
return st->st_gname;
#else
- struct group *gr = (struct group *) getgrgid (st->st_gid);
+ struct group *gr = getgrgid (st->st_gid);
if (gr)
return gr->gr_name;
@@ -901,7 +869,7 @@ Elements of the attribute list are:
7. Size in bytes.
This is a floating point number if the size is too large for an integer.
8. File modes, as a string of ten letters or dashes as in ls -l.
- 9. t if file's gid would change if file were deleted and recreated.
+ 9. An unspecified value, present only for backward compatibility.
10. inode number. If it is larger than what an Emacs integer can hold,
this is of the form (HIGH . LOW): first the high bits, then the low 16 bits.
If even HIGH is too large for an Emacs integer, this is instead of the form
@@ -923,10 +891,7 @@ so last access time will always be midnight of that day. */)
Lisp_Object values[12];
Lisp_Object encoded;
struct stat s;
-#ifdef BSD4_2
- Lisp_Object dirname;
- struct stat sdir;
-#endif /* BSD4_2 */
+ int lstat_result;
/* An array to hold the mode string generated by filemodestring,
including its terminating space and null byte. */
@@ -954,7 +919,21 @@ so last access time will always be midnight of that day. */)
encoded = ENCODE_FILE (filename);
UNGCPRO;
- if (lstat (SSDATA (encoded), &s) < 0)
+#ifdef WINDOWSNT
+ /* We usually don't request accurate owner and group info, because
+ it can be very expensive on Windows to get that, and most callers
+ of 'lstat' don't need that. But here we do want that information
+ to be accurate. */
+ w32_stat_get_owner_group = 1;
+#endif
+
+ lstat_result = lstat (SSDATA (encoded), &s);
+
+#ifdef WINDOWSNT
+ w32_stat_get_owner_group = 0;
+#endif
+
+ if (lstat_result < 0)
return Qnil;
values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename)
@@ -963,10 +942,10 @@ so last access time will always be midnight of that day. */)
if (!(NILP (id_format) || EQ (id_format, Qinteger)))
{
- BLOCK_INPUT;
+ block_input ();
uname = stat_uname (&s);
gname = stat_gname (&s);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (uname)
values[2] = DECODE_SYSTEM (build_string (uname));
@@ -991,17 +970,7 @@ so last access time will always be midnight of that day. */)
filemodestring (&s, modes);
values[8] = make_string (modes, 10);
-#ifdef BSD4_2 /* file gid will be dir gid */
- dirname = Ffile_name_directory (filename);
- if (! NILP (dirname))
- encoded = ENCODE_FILE (dirname);
- if (! NILP (dirname) && stat (SDATA (encoded), &sdir) == 0)
- values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
- else /* if we can't tell, assume worst */
- values[9] = Qt;
-#else /* file gid will be egid */
- values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
-#endif /* not BSD4_2 */
+ values[9] = Qt;
values[10] = INTEGER_TO_CONS (s.st_ino);
values[11] = INTEGER_TO_CONS (s.st_dev);
diff --git a/src/dispextern.h b/src/dispextern.h
index 73f3350713f..aa40f019fbe 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1572,12 +1572,12 @@ struct face
/* Pixmap width and height. */
unsigned int pixmap_w, pixmap_h;
- /* Non-zero means characters in this face have a box that thickness
- around them. If it is negative, the absolute value indicates the
- thickness, and the horizontal lines of box (top and bottom) are
- drawn inside of characters glyph area. The vertical lines of box
- (left and right) are drawn as the same way as the case that this
- value is positive. */
+ /* Non-zero means characters in this face have a box of that
+ thickness around them. If this value is negative, its absolute
+ value indicates the thickness, and the horizontal (top and
+ bottom) borders of box are drawn inside of the character glyphs'
+ area. The vertical (left and right) borders of the box are drawn
+ in the same way as when this value is positive. */
int box_line_width;
/* Type of box drawn. A value of FACE_NO_BOX means no box is drawn
@@ -2138,7 +2138,8 @@ struct it
const unsigned char *s;
/* Number of characters in the string (s, or it->string) we iterate
- over. */
+ over. Used only in display_string and its subroutines; never
+ used for overlay strings and strings from display properties. */
ptrdiff_t string_nchars;
/* Start and end of a visible region; -1 if the region is not
@@ -2756,16 +2757,20 @@ struct image_type
Lisp_Object *type;
/* Check that SPEC is a valid image specification for the given
- image type. Value is non-zero if SPEC is valid. */
- int (* valid_p) (Lisp_Object spec);
+ image type. Value is true if SPEC is valid. */
+ bool (* valid_p) (Lisp_Object spec);
/* Load IMG which is used on frame F from information contained in
- IMG->spec. Value is non-zero if successful. */
- int (* load) (struct frame *f, struct image *img);
+ IMG->spec. Value is true if successful. */
+ bool (* load) (struct frame *f, struct image *img);
/* Free resources of image IMG which is used on frame F. */
void (* free) (struct frame *f, struct image *img);
+ /* Initialization function (used for dynamic loading of image
+ libraries on Windows), or NULL if none. */
+ bool (* init) (void);
+
/* Next in list of all supported image types. */
struct image_type *next;
};
@@ -3139,7 +3144,7 @@ int draw_window_fringes (struct window *, int);
int update_window_fringes (struct window *, int);
void compute_fringe_widths (struct frame *, int);
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
void w32_init_fringe (struct redisplay_interface *);
void w32_reset_fringes (void);
#endif
@@ -3152,7 +3157,7 @@ extern unsigned row_hash (struct glyph_row *);
extern int x_bitmap_height (struct frame *, ptrdiff_t);
extern int x_bitmap_width (struct frame *, ptrdiff_t);
-extern int x_bitmap_pixmap (struct frame *, ptrdiff_t);
+extern ptrdiff_t x_bitmap_pixmap (struct frame *, ptrdiff_t);
extern void x_reference_bitmap (struct frame *, ptrdiff_t);
extern ptrdiff_t x_create_bitmap_from_data (struct frame *, char *,
unsigned int, unsigned int);
@@ -3164,7 +3169,7 @@ extern ptrdiff_t x_create_bitmap_from_xpm_data (struct frame *, const char **);
extern void x_destroy_bitmap (struct frame *, ptrdiff_t);
#endif
extern void x_destroy_all_bitmaps (Display_Info *);
-extern int x_create_bitmap_mask (struct frame *, ptrdiff_t);
+extern void x_create_bitmap_mask (struct frame *, ptrdiff_t);
extern Lisp_Object x_find_image_file (Lisp_Object);
void x_kill_gs_process (Pixmap, struct frame *);
@@ -3172,7 +3177,7 @@ struct image_cache *make_image_cache (void);
void free_image_cache (struct frame *);
void clear_image_caches (Lisp_Object);
void mark_image_cache (struct image_cache *);
-int valid_image_p (Lisp_Object);
+bool valid_image_p (Lisp_Object);
void prepare_image_for_display (struct frame *, struct image *);
ptrdiff_t lookup_image (struct frame *, Lisp_Object);
@@ -3193,6 +3198,7 @@ void unrequest_sigio (void);
int tabs_safe_p (int);
void init_baud_rate (int);
void init_sigio (int);
+void ignore_sigio (void);
/* Defined in xfaces.c */
@@ -3241,7 +3247,7 @@ extern char unspecified_fg[], unspecified_bg[];
#ifdef HAVE_X_WINDOWS
void gamma_correct (struct frame *, XColor *);
#endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
void gamma_correct (struct frame *, COLORREF *);
#endif
diff --git a/src/dispnew.c b/src/dispnew.c
index cac4c2da4c4..02b2f9c84e4 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -21,14 +21,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define DISPEXTERN_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#include <unistd.h>
#include "lisp.h"
#include "termchar.h"
-#include "termopts.h"
/* cm.h must come after dispextern.h on Windows. */
#include "dispextern.h"
#include "cm.h"
@@ -56,13 +53,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "systime.h"
#include <errno.h>
-#ifdef DISPNEW_NEEDS_STDIO_EXT
-#include <stdio_ext.h>
-#endif
+#include <fpending.h>
#if defined (HAVE_TERM_H) && defined (GNU_LINUX)
#include <term.h> /* for tgetent */
#endif
+
+#ifdef WINDOWSNT
+#include "w32.h"
+#endif
/* Structure to pass dimensions around. Used for character bounding
boxes, glyph matrix dimensions and alike. */
@@ -142,10 +141,6 @@ struct frame *last_nonminibuf_frame;
static bool delayed_size_change;
-/* 1 means glyph initialization has been completed at startup. */
-
-static bool glyphs_initialized_initially_p;
-
/* Updated window if != 0. Set by update_window. */
struct window *updated_window;
@@ -297,7 +292,7 @@ DEFUN ("dump-redisplay-history", Fdump_redisplay_history,
void
__executable_start (void)
{
- abort ();
+ emacs_abort ();
}
#endif
@@ -347,7 +342,7 @@ free_glyph_matrix (struct glyph_matrix *matrix)
/* Detect the case that more matrices are freed than were
allocated. */
if (--glyph_matrix_count < 0)
- abort ();
+ emacs_abort ();
/* Free glyph memory if MATRIX owns it. */
if (matrix->pool == NULL)
@@ -1030,7 +1025,7 @@ swap_glyphs_in_rows (struct glyph_row *a, struct glyph_row *b)
these should all go together for the row's hash value to be
correct. */
-static inline void
+static void
swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b)
{
int i;
@@ -1059,7 +1054,7 @@ swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b)
that glyph pointers, the `used' counts, and the hash values in the
structures are left unchanged. */
-static inline void
+static void
copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
{
struct glyph *pointers[1 + LAST_AREA];
@@ -1086,7 +1081,7 @@ copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
exchanged between TO and FROM. Pointers must be exchanged to avoid
a memory leak. */
-static inline void
+static void
assign_row (struct glyph_row *to, struct glyph_row *from)
{
swap_glyph_pointers (to, from);
@@ -1251,7 +1246,7 @@ line_draw_cost (struct glyph_matrix *matrix, int vpos)
/* Return true if the glyph rows A and B have equal contents.
MOUSE_FACE_P means compare the mouse_face_p flags of A and B, too. */
-static inline bool
+static bool
row_equal_p (struct glyph_row *a, struct glyph_row *b, bool mouse_face_p)
{
eassert (verify_row_hash (a));
@@ -1836,7 +1831,7 @@ adjust_glyphs (struct frame *f)
{
/* Block input so that expose events and other events that access
glyph matrices are not processed while we are changing them. */
- BLOCK_INPUT;
+ block_input ();
if (f)
adjust_frame_glyphs (f);
@@ -1848,46 +1843,9 @@ adjust_glyphs (struct frame *f)
adjust_frame_glyphs (XFRAME (lisp_frame));
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
-
-/* Adjust frame glyphs when Emacs is initialized.
-
- To be called from init_display.
-
- We need a glyph matrix because redraw will happen soon.
- Unfortunately, window sizes on selected_frame are not yet set to
- meaningful values. I believe we can assume that there are only two
- windows on the frame---the mini-buffer and the root window. Frame
- height and width seem to be correct so far. So, set the sizes of
- windows to estimated values. */
-
-static void
-adjust_frame_glyphs_initially (void)
-{
- struct frame *sf = SELECTED_FRAME ();
- struct window *root = XWINDOW (sf->root_window);
- struct window *mini = XWINDOW (root->next);
- int frame_lines = FRAME_LINES (sf);
- int frame_cols = FRAME_COLS (sf);
- int top_margin = FRAME_TOP_MARGIN (sf);
-
- /* Do it for the root window. */
- wset_top_line (root, make_number (top_margin));
- wset_total_lines (root, make_number (frame_lines - 1 - top_margin));
- wset_total_cols (root, make_number (frame_cols));
-
- /* Do it for the mini-buffer window. */
- wset_top_line (mini, make_number (frame_lines - 1));
- wset_total_lines (mini, make_number (1));
- wset_total_cols (mini, make_number (frame_cols));
-
- adjust_frame_glyphs (sf);
- glyphs_initialized_initially_p = 1;
-}
-
-
/* Allocate/reallocate glyph matrices of a single frame F. */
static void
@@ -2244,7 +2202,7 @@ free_glyphs (struct frame *f)
{
/* Block interrupt input so that we don't get surprised by an X
event while we're in an inconsistent state. */
- BLOCK_INPUT;
+ block_input ();
f->glyphs_initialized_p = 0;
/* Release window sub-matrices. */
@@ -2289,7 +2247,7 @@ free_glyphs (struct frame *f)
f->desired_pool = f->current_pool = NULL;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -2339,9 +2297,9 @@ check_glyph_memory (void)
/* Check that nothing is left allocated. */
if (glyph_matrix_count)
- abort ();
+ emacs_abort ();
if (glyph_pool_count)
- abort ();
+ emacs_abort ();
}
@@ -2659,7 +2617,7 @@ fill_up_frame_row_with_spaces (struct glyph_row *row, int upto)
function must be called before updates to make explicit that we are
working on frame matrices or not. */
-static inline void
+static void
set_frame_matrix_frame (struct frame *f)
{
frame_matrix_frame = f;
@@ -2674,7 +2632,7 @@ set_frame_matrix_frame (struct frame *f)
done in frame matrices, and that we have to perform analogous
operations in window matrices of frame_matrix_frame. */
-static inline void
+static void
make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row)
{
struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
@@ -3024,7 +2982,7 @@ check_matrix_pointers (struct glyph_matrix *window_matrix,
{
if (!glyph_row_slice_p (window_matrix->rows + i,
frame_matrix->rows + j))
- abort ();
+ emacs_abort ();
++i, ++j;
}
}
@@ -3072,21 +3030,13 @@ window_to_frame_hpos (struct window *w, int hpos)
Redrawing Frames
**********************************************************************/
-DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
- doc: /* Clear frame FRAME and output again what is supposed to appear on it. */)
- (Lisp_Object frame)
-{
- struct frame *f;
-
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
-
- /* Ignore redraw requests, if frame has no glyphs yet.
- (Implementation note: It still has to be checked why we are
- called so early here). */
- if (!glyphs_initialized_initially_p)
- return Qnil;
+/* Redraw frame F. */
+void
+redraw_frame (struct frame *f)
+{
+ /* Error if F has no glyphs. */
+ eassert (f->glyphs_initialized_p);
update_begin (f);
#ifdef MSDOS
if (FRAME_MSDOS_P (f))
@@ -3103,22 +3053,17 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
f->garbaged = 0;
- return Qnil;
}
-
-/* Redraw frame F. This is nothing more than a call to the Lisp
- function redraw-frame. */
-
-void
-redraw_frame (struct frame *f)
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 0, 1, 0,
+ doc: /* Clear frame FRAME and output again what is supposed to appear on it.
+If FRAME is omitted or nil, the selected frame is used. */)
+ (Lisp_Object frame)
{
- Lisp_Object frame;
- XSETFRAME (frame, f);
- Fredraw_frame (frame);
+ redraw_frame (decode_live_frame (frame));
+ return Qnil;
}
-
DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
doc: /* Clear and redisplay all visible frames. */)
(void)
@@ -3127,7 +3072,7 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
FOR_EACH_FRAME (tail, frame)
if (FRAME_VISIBLE_P (XFRAME (frame)))
- Fredraw_frame (frame);
+ redraw_frame (XFRAME (frame));
return Qnil;
}
@@ -3453,7 +3398,7 @@ check_current_matrix_flags (struct window *w)
if (!last_seen_p && MATRIX_ROW_BOTTOM_Y (row) >= yb)
last_seen_p = 1;
else if (last_seen_p && row->enabled_p)
- abort ();
+ emacs_abort ();
}
}
@@ -3952,6 +3897,11 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
{
changed_p = 1;
update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+ /* Setting this flag will ensure the vertical border, if
+ any, between this window and the one on its left will be
+ redrawn. This is necessary because updating the left
+ margin area can potentially draw over the border. */
+ current_row->redraw_fringe_bitmaps_p = 1;
}
/* Update the display of the text area. */
@@ -4066,11 +4016,10 @@ set_window_cursor_after_update (struct window *w)
vpos = w->cursor.vpos;
}
- /* Window cursor can be out of sync for horizontally split windows. */
- hpos = max (-1, hpos); /* -1 is for when cursor is on the left fringe */
- hpos = min (w->current_matrix->matrix_w - 1, hpos);
- vpos = max (0, vpos);
- vpos = min (w->current_matrix->nrows - 1, vpos);
+ /* Window cursor can be out of sync for horizontally split windows.
+ Horizontal position is -1 when cursor is on the left fringe. */
+ hpos = clip_to_bounds (-1, hpos, w->current_matrix->matrix_w - 1);
+ vpos = clip_to_bounds (0, vpos, w->current_matrix->nrows - 1);
rif->cursor_to (vpos, hpos, cy, cx);
}
@@ -4155,7 +4104,7 @@ static struct run **runs;
/* Add glyph row ROW to the scrolling hash table. */
-static inline struct row_entry *
+static struct row_entry *
add_row_entry (struct glyph_row *row)
{
struct row_entry *entry;
@@ -4641,24 +4590,10 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
FILE *display_output = FRAME_TTY (f)->output;
if (display_output)
{
- int outq = PENDING_OUTPUT_COUNT (display_output);
+ ptrdiff_t outq = __fpending (display_output);
if (outq > 900
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
- {
- fflush (display_output);
- if (preempt_count == 1)
- {
-#ifdef EMACS_OUTQSIZE
- if (EMACS_OUTQSIZE (0, &outq) < 0)
- /* Probably not a tty. Ignore the error and reset
- the outq count. */
- outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
-#endif
- outq *= 10;
- if (baud_rate <= outq && baud_rate > 0)
- sleep (outq / baud_rate);
- }
- }
+ fflush (display_output);
}
}
@@ -4809,7 +4744,7 @@ scrolling (struct frame *frame)
struct glyph_matrix *desired_matrix = frame->desired_matrix;
if (!current_matrix)
- abort ();
+ emacs_abort ();
/* Compute hash codes of all the lines. Also calculate number of
changed lines, number of unchanged lines at the beginning, and
@@ -5477,7 +5412,7 @@ marginal_area_string (struct window *w, enum window_part part,
else if (part == ON_RIGHT_MARGIN)
area = RIGHT_MARGIN_AREA;
else
- abort ();
+ emacs_abort ();
for (i = 0; row->enabled_p && i < w->current_matrix->nrows; ++i, ++row)
if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row))
@@ -5552,18 +5487,14 @@ marginal_area_string (struct window *w, enum window_part part,
#ifdef SIGWINCH
+static void deliver_window_change_signal (int);
+
static void
-window_change_signal (int signalnum) /* If we don't have an argument, */
- /* some compilers complain in signal calls. */
+handle_window_change_signal (int sig)
{
int width, height;
- int old_errno = errno;
-
struct tty_display_info *tty;
- signal (SIGWINCH, window_change_signal);
- SIGNAL_THREAD_CHECK (signalnum);
-
/* The frame size change obviously applies to a single
termcap-controlled terminal, but we can't decide which.
Therefore, we resize the frames corresponding to each tty.
@@ -5591,8 +5522,12 @@ window_change_signal (int signalnum) /* If we don't have an argument, */
change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
}
}
+}
- errno = old_errno;
+static void
+deliver_window_change_signal (int sig)
+{
+ deliver_process_signal (sig, handle_window_change_signal);
}
#endif /* SIGWINCH */
@@ -5604,7 +5539,7 @@ window_change_signal (int signalnum) /* If we don't have an argument, */
void
do_pending_window_change (bool safe)
{
- /* If window_change_signal should have run before, run it now. */
+ /* If window change signal handler should have run before, run it now. */
if (redisplaying_p && !safe)
return;
@@ -5701,7 +5636,7 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
&& new_frame_total_cols == FRAME_TOTAL_COLS (f))
return;
- BLOCK_INPUT;
+ block_input ();
#ifdef MSDOS
/* We only can set screen dimensions to certain values supported
@@ -5753,7 +5688,7 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
SET_FRAME_GARBAGED (f);
f->resized_p = 1;
- UNBLOCK_INPUT;
+ unblock_input ();
record_unwind_current_buffer ();
@@ -5784,9 +5719,9 @@ FILE = nil means just close any termscript file currently open. */)
if (tty->termscript != 0)
{
- BLOCK_INPUT;
+ block_input ();
fclose (tty->termscript);
- UNBLOCK_INPUT;
+ unblock_input ();
}
tty->termscript = 0;
@@ -5817,7 +5752,7 @@ when TERMINAL is nil. */)
/* ??? Perhaps we should do something special for multibyte strings here. */
CHECK_STRING (string);
- BLOCK_INPUT;
+ block_input ();
if (!t)
error ("Unknown terminal device");
@@ -5842,7 +5777,7 @@ when TERMINAL is nil. */)
}
fwrite (SDATA (string), 1, SBYTES (string), out);
fflush (out);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -5916,15 +5851,16 @@ additional wait period, in milliseconds; this is for backwards compatibility.
TIMEOUT is number of seconds to wait (float or integer),
or t to wait forever.
READING is true if reading input.
- If DO_DISPLAY is >0 display process output while waiting.
- If DO_DISPLAY is >1 perform an initial redisplay before waiting.
+ If DISPLAY_OPTION is >0 display process output while waiting.
+ If DISPLAY_OPTION is >1 perform an initial redisplay before waiting.
*/
Lisp_Object
-sit_for (Lisp_Object timeout, bool reading, int do_display)
+sit_for (Lisp_Object timeout, bool reading, int display_option)
{
intmax_t sec;
int nsec;
+ bool do_display = display_option > 0;
swallow_events (do_display);
@@ -5932,7 +5868,7 @@ sit_for (Lisp_Object timeout, bool reading, int do_display)
|| !NILP (Vexecuting_kbd_macro))
return Qnil;
- if (do_display >= 2)
+ if (display_option > 1)
redisplay_preserve_echo_area (2);
if (INTEGERP (timeout))
@@ -5963,8 +5899,8 @@ sit_for (Lisp_Object timeout, bool reading, int do_display)
wrong_type_argument (Qnumberp, timeout);
-#ifdef SIGIO
- gobble_input (0);
+#ifdef USABLE_SIGIO
+ gobble_input ();
#endif
wait_reading_process_output (sec, nsec, reading ? -1 : 1, do_display,
@@ -6173,7 +6109,11 @@ init_display (void)
#ifndef CANNOT_DUMP
if (initialized)
#endif /* CANNOT_DUMP */
- signal (SIGWINCH, window_change_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_window_change_signal);
+ sigaction (SIGWINCH, &action, 0);
+ }
#endif /* SIGWINCH */
/* If running as a daemon, no need to initialize any frames/terminal. */
@@ -6215,7 +6155,6 @@ init_display (void)
So call tgetent. */
{ char b[2044]; tgetent (b, "xterm");}
#endif
- adjust_frame_glyphs_initially ();
return;
}
#endif /* HAVE_X_WINDOWS */
@@ -6225,7 +6164,6 @@ init_display (void)
{
Vinitial_window_system = Qw32;
Vwindow_system_version = make_number (1);
- adjust_frame_glyphs_initially ();
return;
}
#endif /* HAVE_NTGUI */
@@ -6239,7 +6177,6 @@ init_display (void)
{
Vinitial_window_system = Qns;
Vwindow_system_version = make_number (10);
- adjust_frame_glyphs_initially ();
return;
}
#endif
@@ -6272,12 +6209,14 @@ init_display (void)
struct terminal *t;
struct frame *f = XFRAME (selected_frame);
+ init_foreground_group ();
+
/* Open a display on the controlling tty. */
t = init_tty (0, terminal_type, 1); /* Errors are fatal. */
/* Convert the initial frame to use the new display. */
if (f->output_method != output_initial)
- abort ();
+ emacs_abort ();
f->output_method = t->type;
f->terminal = t;
@@ -6327,7 +6266,6 @@ init_display (void)
fatal ("screen size %dx%d too big", width, height);
}
- adjust_frame_glyphs_initially ();
calculate_costs (XFRAME (selected_frame));
/* Set up faces of the initial terminal frame of a dumped Emacs. */
@@ -6362,15 +6300,7 @@ don't show a cursor. */)
/* Don't change cursor state while redisplaying. This could confuse
output routines. */
if (!redisplaying_p)
- {
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window);
-
- XWINDOW (window)->cursor_off_p = NILP (show);
- }
-
+ decode_any_window (window)->cursor_off_p = NILP (show);
return Qnil;
}
@@ -6381,15 +6311,7 @@ DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p,
WINDOW nil or omitted means report on the selected window. */)
(Lisp_Object window)
{
- struct window *w;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window);
-
- w = XWINDOW (window);
- return w->cursor_off_p ? Qnil : Qt;
+ return decode_any_window (window)->cursor_off_p ? Qnil : Qt;
}
DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
diff --git a/src/doc.c b/src/doc.c
index 02a5b4b8143..76008295add 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -21,8 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <sys/types.h>
-#include <sys/file.h> /* Must be after sys/types.h for USG*/
-#include <setjmp.h>
+#include <sys/file.h> /* Must be after sys/types.h for USG. */
#include <fcntl.h>
#include <unistd.h>
@@ -43,7 +42,7 @@ static ptrdiff_t get_doc_string_buffer_size;
static unsigned char *read_bytecode_pointer;
-/* readchar in lread.c calls back here to fetch the next byte.
+/* `readchar' in lread.c calls back here to fetch the next byte.
If UNREADFLAG is 1, we unread a byte. */
int
@@ -145,7 +144,8 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
}
#endif
if (fd < 0)
- error ("Cannot open doc string file \"%s\"", name);
+ return concat3 (build_string ("Cannot open doc string file \""),
+ file, build_string ("\"\n"));
}
/* Seek only to beginning of disk block. */
@@ -347,6 +347,8 @@ string is passed through `substitute-command-keys'. */)
}
fun = Findirect_function (function, Qnil);
+ if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
+ fun = XCDR (fun);
if (SUBRP (fun))
{
if (XSUBR (fun)->doc == 0)
@@ -400,8 +402,6 @@ string is passed through `substitute-command-keys'. */)
else
return Qnil;
}
- else if (EQ (funcar, Qmacro))
- return Fdocumentation (Fcdr (fun), raw);
else
goto oops;
}
@@ -411,16 +411,19 @@ string is passed through `substitute-command-keys'. */)
xsignal1 (Qinvalid_function, fun);
}
- /* Check for an advised function. Its doc string
- has an `ad-advice-info' text property. */
+ /* Check for a dynamic docstring. These come with
+ a dynamic-docstring-function text property. */
if (STRINGP (doc))
{
- Lisp_Object innerfunc;
- innerfunc = Fget_text_property (make_number (0),
- intern ("ad-advice-info"),
+ Lisp_Object func
+ = Fget_text_property (make_number (0),
+ intern ("dynamic-docstring-function"),
doc);
- if (! NILP (innerfunc))
- doc = call1 (intern ("ad-make-advised-docstring"), innerfunc);
+ if (!NILP (func))
+ /* Pass both `doc' and `function' since `function' can be needed, and
+ finding `doc' can be annoying: calling `documentation' is not an
+ option because it would infloop. */
+ doc = call2 (func, doc, function);
}
/* If DOC is 0, it's typically because of a dumped file missing
@@ -528,6 +531,8 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
{
tem = Fcdr (Fcdr (fun));
if (CONSP (tem) && INTEGERP (XCAR (tem)))
+ /* FIXME: This modifies typically pure hash-cons'd data, so its
+ correctness is quite delicate. */
XSETCAR (tem, make_number (offset));
}
else if (EQ (tem, Qmacro))
diff --git a/src/doprnt.c b/src/doprnt.c
index b36e946005d..8cab219aafa 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -102,7 +102,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include <float.h>
#include <unistd.h>
#include <limits.h>
@@ -114,10 +113,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
another macro. */
#include "character.h"
-#ifndef DBL_MAX_10_EXP
-#define DBL_MAX_10_EXP 308 /* IEEE double */
-#endif
-
/* Generate output from a format-spec FORMAT,
terminated at position FORMAT_END.
(*FORMAT_END is not part of the format, but must exist and be readable.)
@@ -526,7 +521,10 @@ evxprintf (char **buf, ptrdiff_t *bufsize,
if (nbytes < *bufsize - 1)
return nbytes;
if (*buf != nonheapbuf)
- xfree (*buf);
+ {
+ xfree (*buf);
+ *buf = NULL;
+ }
*buf = xpalloc (NULL, bufsize, 1, bufsize_max, 1);
}
}
diff --git a/src/dosfns.c b/src/dosfns.c
index 21676f4b4f5..ce1ec4a4f93 100644
--- a/src/dosfns.c
+++ b/src/dosfns.c
@@ -30,7 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <dos.h>
#undef gettime
#undef settime
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -480,9 +480,9 @@ x_set_title (struct frame *f, Lisp_Object name)
if (FRAME_MSDOS_P (f))
{
- BLOCK_INPUT;
+ block_input ();
w95_set_virtual_machine_title (SDATA (name));
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
#endif /* !HAVE_X_WINDOWS */
diff --git a/src/editfns.c b/src/editfns.c
index a14e043c1bf..911cd416e80 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -21,10 +21,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <sys/types.h>
#include <stdio.h>
-#include <setjmp.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
+#include <grp.h>
#endif
#include <unistd.h>
@@ -79,6 +79,15 @@ Lisp_Object Qfield;
static Lisp_Object Qboundary;
+/* The startup value of the TZ environment variable so it can be
+ restored if the user calls set-time-zone-rule with a nil
+ argument. If null, the TZ environment variable was unset. */
+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;
+
void
init_editfns (void)
@@ -97,6 +106,9 @@ init_editfns (void)
return;
#endif /* not CANNOT_DUMP */
+ initial_tz = getenv ("TZ");
+ tzvalbuf_in_environ = 0;
+
pw = getpwuid (getuid ());
#ifdef MSDOS
/* We let the real user name default to "root" because that's quite
@@ -739,17 +751,18 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */)
DEFUN ("line-beginning-position",
Fline_beginning_position, Sline_beginning_position, 0, 1, 0,
doc: /* Return the character position of the first character on the current line.
-With argument N not nil or 1, move forward N - 1 lines first.
-If scan reaches end of buffer, return that position.
+With optional argument N, scan forward N - 1 lines first.
+If the scan reaches the end of the buffer, return that position.
-The returned position is of the first character in the logical order,
-i.e. the one that has the smallest character position.
+This function ignores text display directionality; it returns the
+position of the first character in logical order, i.e. the smallest
+character position on the line.
This function constrains the returned position to the current field
-unless that would be on a different line than the original,
+unless that position would be on a different line than the original,
unconstrained result. If N is nil or 1, and a front-sticky field
starts at point, the scan stops as soon as it starts. To ignore field
-boundaries bind `inhibit-field-text-motion' to t.
+boundaries, bind `inhibit-field-text-motion' to t.
This function does not move point. */)
(Lisp_Object n)
@@ -783,8 +796,9 @@ DEFUN ("line-end-position", Fline_end_position, Sline_end_position, 0, 1, 0,
With argument N not nil or 1, move forward N - 1 lines first.
If scan reaches end of buffer, return that position.
-The returned position is of the last character in the logical order,
-i.e. the character whose buffer position is the largest one.
+This function ignores text display directionality; it returns the
+position of the last character in logical order, i.e. the largest
+character position on the line.
This function constrains the returned position to the current field
unless that would be on a different line than the original,
@@ -812,34 +826,43 @@ This function does not move point. */)
Qnil, Qt, Qnil);
}
-
+/* Save current buffer state for `save-excursion' special form.
+ We (ab)use Lisp_Misc_Save_Value to allow explicit free and so
+ offload some work from GC. */
+
Lisp_Object
save_excursion_save (void)
{
- bool visible = (XBUFFER (XWINDOW (selected_window)->buffer)
- == current_buffer);
-
- return Fcons (Fpoint_marker (),
- Fcons (Fcopy_marker (BVAR (current_buffer, mark), Qnil),
- Fcons (visible ? Qt : Qnil,
- Fcons (BVAR (current_buffer, mark_active),
- selected_window))));
+ Lisp_Object save, *data = xmalloc (word_size * 4);
+
+ data[0] = Fpoint_marker ();
+ /* Do not copy the mark if it points to nowhere. */
+ data[1] = (XMARKER (BVAR (current_buffer, mark))->buffer
+ ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
+ : Qnil);
+ /* Selected window if current buffer is shown in it, nil otherwise. */
+ data[2] = ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+ ? selected_window : Qnil);
+ data[3] = BVAR (current_buffer, mark_active);
+
+ save = make_save_value (data, 4);
+ XSAVE_VALUE (save)->dogc = 1;
+ return save;
}
+/* Restore saved buffer before leaving `save-excursion' special form. */
+
Lisp_Object
save_excursion_restore (Lisp_Object info)
{
- Lisp_Object tem, tem1, omark, nmark;
+ Lisp_Object tem, tem1, omark, nmark, *data = XSAVE_VALUE (info)->pointer;
struct gcpro gcpro1, gcpro2, gcpro3;
- bool visible_p;
- tem = Fmarker_buffer (XCAR (info));
- /* If buffer being returned to is now deleted, avoid error */
- /* Otherwise could get error here while unwinding to top level
- and crash */
- /* In that case, Fmarker_buffer returns nil now. */
+ tem = Fmarker_buffer (data[0]);
+ /* If we're unwinding to top level, saved buffer may be deleted. This
+ means that all of its markers are unchained and so tem is nil. */
if (NILP (tem))
- return Qnil;
+ goto out;
omark = nmark = Qnil;
GCPRO3 (info, omark, nmark);
@@ -847,35 +870,24 @@ save_excursion_restore (Lisp_Object info)
Fset_buffer (tem);
/* Point marker. */
- tem = XCAR (info);
+ tem = data[0];
Fgoto_char (tem);
unchain_marker (XMARKER (tem));
/* Mark marker. */
- info = XCDR (info);
- tem = XCAR (info);
+ tem = data[1];
omark = Fmarker_position (BVAR (current_buffer, mark));
- Fset_marker (BVAR (current_buffer, mark), tem, Fcurrent_buffer ());
- nmark = Fmarker_position (tem);
- unchain_marker (XMARKER (tem));
+ if (NILP (tem))
+ unchain_marker (XMARKER (BVAR (current_buffer, mark)));
+ else
+ {
+ Fset_marker (BVAR (current_buffer, mark), tem, Fcurrent_buffer ());
+ nmark = Fmarker_position (tem);
+ unchain_marker (XMARKER (tem));
+ }
- /* visible */
- info = XCDR (info);
- visible_p = !NILP (XCAR (info));
-
-#if 0 /* We used to make the current buffer visible in the selected window
- if that was true previously. That avoids some anomalies.
- But it creates others, and it wasn't documented, and it is simpler
- and cleaner never to alter the window/buffer connections. */
- tem1 = Fcar (tem);
- if (!NILP (tem1)
- && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
- Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
-#endif /* 0 */
-
- /* Mark active */
- info = XCDR (info);
- tem = XCAR (info);
+ /* Mark active. */
+ tem = data[3];
tem1 = BVAR (current_buffer, mark_active);
bset_mark_active (current_buffer, tem);
@@ -899,8 +911,8 @@ save_excursion_restore (Lisp_Object info)
/* If buffer was visible in a window, and a different window was
selected, and the old selected window is still showing this
buffer, restore point in that window. */
- tem = XCDR (info);
- if (visible_p
+ tem = data[2];
+ if (WINDOWP (tem)
&& !EQ (tem, selected_window)
&& (tem1 = XWINDOW (tem)->buffer,
(/* Window is live... */
@@ -910,6 +922,10 @@ save_excursion_restore (Lisp_Object info)
Fset_window_point (tem, make_number (PT));
UNGCPRO;
+
+ out:
+
+ free_save_value (info);
return Qnil;
}
@@ -1218,9 +1234,9 @@ of the user with that uid, or nil if there is no such user. */)
return Vuser_login_name;
CONS_TO_INTEGER (uid, uid_t, id);
- BLOCK_INPUT;
+ block_input ();
pw = getpwuid (id);
- UNBLOCK_INPUT;
+ unblock_input ();
return (pw ? build_string (pw->pw_name) : Qnil);
}
@@ -1257,6 +1273,24 @@ Value is an integer or a float, depending on the value. */)
return make_fixnum_or_float (uid);
}
+DEFUN ("group-gid", Fgroup_gid, Sgroup_gid, 0, 0, 0,
+ doc: /* Return the effective gid of Emacs.
+Value is an integer or a float, depending on the value. */)
+ (void)
+{
+ gid_t egid = getegid ();
+ return make_fixnum_or_float (egid);
+}
+
+DEFUN ("group-real-gid", Fgroup_real_gid, Sgroup_real_gid, 0, 0, 0,
+ doc: /* Return the real gid of Emacs.
+Value is an integer or a float, depending on the value. */)
+ (void)
+{
+ gid_t gid = getgid ();
+ return make_fixnum_or_float (gid);
+}
+
DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0,
doc: /* Return the full name of the user logged in, as a string.
If the full name corresponding to Emacs's userid is not known,
@@ -1278,15 +1312,15 @@ name, or nil if there is no such user. */)
{
uid_t u;
CONS_TO_INTEGER (uid, uid_t, u);
- BLOCK_INPUT;
+ block_input ();
pw = getpwuid (u);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else if (STRINGP (uid))
{
- BLOCK_INPUT;
+ block_input ();
pw = getpwnam (SSDATA (uid));
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
error ("Invalid UID specification");
@@ -1329,15 +1363,6 @@ DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
return Vsystem_name;
}
-const char *
-get_system_name (void)
-{
- if (STRINGP (Vsystem_name))
- return SSDATA (Vsystem_name);
- else
- return "";
-}
-
DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
doc: /* Return the process ID of Emacs, as a number. */)
(void)
@@ -1762,14 +1787,14 @@ format_time_string (char const *format, ptrdiff_t formatlen,
while (1)
{
time_t *taddr = emacs_secs_addr (&t);
- BLOCK_INPUT;
+ block_input ();
synchronize_system_time_locale ();
tm = ut ? gmtime (taddr) : localtime (taddr);
if (! tm)
{
- UNBLOCK_INPUT;
+ unblock_input ();
time_overflow ();
}
*tmp = *tm;
@@ -1781,14 +1806,14 @@ format_time_string (char const *format, ptrdiff_t formatlen,
/* Buffer was too small, so make it bigger and try again. */
len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tm, ut, ns);
- UNBLOCK_INPUT;
+ unblock_input ();
if (STRING_BYTES_BOUND <= len)
string_overflow ();
size = len + 1;
buf = SAFE_ALLOCA (size);
}
- UNBLOCK_INPUT;
+ unblock_input ();
bufstring = make_unibyte_string (buf, len);
SAFE_FREE ();
return code_convert_string_norecord (bufstring, Vlocale_coding_system, 0);
@@ -1816,11 +1841,11 @@ DOW and ZONE.) */)
struct tm *decoded_time;
Lisp_Object list_args[9];
- BLOCK_INPUT;
+ block_input ();
decoded_time = localtime (&time_spec);
if (decoded_time)
save_tm = *decoded_time;
- UNBLOCK_INPUT;
+ 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))
@@ -1836,13 +1861,13 @@ DOW and ZONE.) */)
XSETFASTINT (list_args[6], save_tm.tm_wday);
list_args[7] = save_tm.tm_isdst ? Qt : Qnil;
- BLOCK_INPUT;
+ 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;
+ unblock_input ();
return Flist (9, list_args);
}
@@ -1900,15 +1925,17 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
zone = XCAR (zone);
if (NILP (zone))
{
- BLOCK_INPUT;
+ block_input ();
value = mktime (&tm);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
{
- char tzbuf[100];
+ 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;
- char **oldenv = environ, **newenv;
+ USE_SAFE_ALLOCA;
if (EQ (zone, Qt))
tzstring = "UTC0";
@@ -1920,14 +1947,21 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
EMACS_INT zone_hr = abszone / (60*60);
int zone_min = (abszone/60) % 60;
int zone_sec = abszone % 60;
- sprintf (tzbuf, "XXX%s%"pI"d:%02d:%02d", "-" + (XINT (zone) < 0),
+ sprintf (tzbuf, tzbuf_format, "-" + (XINT (zone) < 0),
zone_hr, zone_min, zone_sec);
tzstring = tzbuf;
}
else
error ("Invalid time zone specification");
- BLOCK_INPUT;
+ 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. */
@@ -1935,15 +1969,12 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
value = mktime (&tm);
- /* Restore TZ to previous value. */
- newenv = environ;
- environ = oldenv;
+ set_time_zone_rule (old_tzstring);
#ifdef LOCALTIME_CACHE
tzset ();
#endif
- UNBLOCK_INPUT;
-
- xfree (newenv);
+ unblock_input ();
+ SAFE_FREE ();
}
if (value == (time_t) -1)
@@ -1977,7 +2008,7 @@ but this is considered obsolete. */)
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;
+ block_input ();
tm = localtime (&value);
if (tm)
{
@@ -1993,7 +2024,7 @@ but this is considered obsolete. */)
tm->tm_hour, tm->tm_min, tm->tm_sec,
tm->tm_year + year_base);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (! tm)
time_overflow ();
@@ -2049,11 +2080,11 @@ the data it can't find. */)
zone_offset = Qnil;
value = make_emacs_time (lisp_seconds_argument (specified_time), 0);
zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value, 0, &localtm);
- BLOCK_INPUT;
+ block_input ();
t = gmtime (emacs_secs_addr (&value));
if (t)
offset = tm_diff (&localtm, t);
- UNBLOCK_INPUT;
+ unblock_input ();
if (t)
{
@@ -2073,16 +2104,6 @@ the data it can't find. */)
return list2 (zone_offset, zone_name);
}
-/* This holds the value of `environ' produced by the previous
- call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
- has never been called. */
-static char **environbuf;
-
-/* This holds 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. */
-static char *initial_tz;
-
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.
@@ -2095,18 +2116,10 @@ only the former. */)
(Lisp_Object tz)
{
const char *tzstring;
- char **old_environbuf;
if (! (NILP (tz) || EQ (tz, Qt)))
CHECK_STRING (tz);
- BLOCK_INPUT;
-
- /* When called for the first time, save the original TZ. */
- old_environbuf = environbuf;
- if (!old_environbuf)
- initial_tz = (char *) getenv ("TZ");
-
if (NILP (tz))
tzstring = initial_tz;
else if (EQ (tz, Qt))
@@ -2114,106 +2127,97 @@ only the former. */)
else
tzstring = SSDATA (tz);
+ block_input ();
set_time_zone_rule (tzstring);
- environbuf = environ;
-
- UNBLOCK_INPUT;
+ unblock_input ();
- xfree (old_environbuf);
return Qnil;
}
-#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_tz1[] = "TZ=GMT+0";
-static char set_time_zone_rule_tz2[] = "TZ=GMT+1";
-
-#endif
-
/* Set the local time zone rule to TZSTRING.
- This allocates memory into `environ', which it is the caller's
- responsibility to free. */
+
+ 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. */
void
set_time_zone_rule (const char *tzstring)
{
- ptrdiff_t envptrs;
- char **from, **to, **newenv;
+ /* A buffer holding a string of the form "TZ=value", intended
+ to be part of the environment. */
+ static char *tzvalbuf;
+ static ptrdiff_t tzvalbufsize;
- /* Make the ENVIRON vector longer with room for TZSTRING. */
- for (from = environ; *from; from++)
- continue;
- envptrs = from - environ + 2;
- newenv = to = xmalloc (envptrs * sizeof *newenv
- + (tzstring ? strlen (tzstring) + 4 : 0));
+ int tzeqlen = sizeof "TZ=" - 1;
+
+#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. */
- /* Add TZSTRING to the end of environ, as a value for TZ. */
if (tzstring)
{
- char *t = (char *) (to + envptrs);
- strcpy (t, "TZ=");
- strcat (t, tzstring);
- *to++ = t;
+ /* 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]);
}
+ 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]);
+ }
+ tzset ();
+#endif
- /* Copy the old environ vector elements into NEWENV,
- but don't copy the TZ variable.
- So we have only one definition of TZ, which came from TZSTRING. */
- for (from = environ; *from; from++)
- if (strncmp (*from, "TZ=", 3) != 0)
- *to++ = *from;
- *to = 0;
-
- environ = newenv;
+ if (!tzstring)
+ {
+ unsetenv ("TZ");
+ tzvalbuf_in_environ = 0;
+ }
+ else
+ {
+ ptrdiff_t tzstringlen = strlen (tzstring);
- /* If we do have a TZSTRING, NEWENV points to the vector slot where
- the TZ variable is stored. If we do not have a TZSTRING,
- TO points to the vector slot which has the terminating null. */
+ if (tzvalbufsize <= tzeqlen + tzstringlen)
+ {
+ unsetenv ("TZ");
+ tzvalbuf_in_environ = 0;
+ tzvalbuf = xpalloc (tzvalbuf, &tzvalbufsize,
+ tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1);
+ memcpy (tzvalbuf, "TZ=", tzeqlen);
+ }
-#ifdef LOCALTIME_CACHE
- {
- /* 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 (tzstring)
- {
- /* Temporarily set TZ to a value that loads a tz file
- and that differs from tzstring. */
- char *tz = *newenv;
- *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
- ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
- tzset ();
- *newenv = tz;
- }
- else
- {
- /* The implied tzstring is unknown, so temporarily set TZ to
- two different values that each load a tz file. */
- *to = set_time_zone_rule_tz1;
- to[1] = 0;
- tzset ();
- *to = set_time_zone_rule_tz2;
- tzset ();
- *to = 0;
- }
+ strcpy (tzvalbuf + tzeqlen, tzstring);
- /* Now TZ has the desired value, and tzset can be invoked safely. */
- }
+ if (!tzvalbuf_in_environ)
+ {
+ xputenv (tzvalbuf);
+ tzvalbuf_in_environ = 1;
+ }
+ }
+#ifdef LOCALTIME_CACHE
tzset ();
#endif
}
@@ -2357,9 +2361,10 @@ usage: (insert-before-markers-and-inherit &rest ARGS) */)
}
DEFUN ("insert-char", Finsert_char, Sinsert_char, 1, 3,
- "(list (read-char-by-name \"Insert character (Unicode name or hex): \")\
- (prefix-numeric-value current-prefix-arg)\
- t))",
+ "(list (or (read-char-by-name \"Insert character (Unicode name or hex): \")\
+ (error \"You did not specify a valid character\"))\
+ (prefix-numeric-value current-prefix-arg)\
+ t))",
doc: /* Insert COUNT copies of CHARACTER.
Interactively, prompt for CHARACTER. You can specify CHARACTER in one
of these ways:
@@ -2613,7 +2618,7 @@ They default to the values of (point-min) and (point-max) in BUFFER. */)
if (NILP (buf))
nsberror (buffer);
bp = XBUFFER (buf);
- if (NILP (BVAR (bp, name)))
+ if (!BUFFER_LIVE_P (bp))
error ("Selecting deleted buffer");
if (NILP (start))
@@ -2649,10 +2654,10 @@ They default to the values of (point-min) and (point-max) in BUFFER. */)
DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
6, 6, 0,
doc: /* Compare two substrings of two buffers; return result as number.
-the value is -N if first string is less after N-1 chars,
-+N if first string is greater after N-1 chars, or 0 if strings match.
-Each substring is represented as three arguments: BUFFER, START and END.
-That makes six args in all, three for each substring.
+Return -N if first string is less after N-1 chars, +N if first string is
+greater after N-1 chars, or 0 if strings match. Each substring is
+represented as three arguments: BUFFER, START and END. That makes six
+args in all, three for each substring.
The value of `case-fold-search' in the current buffer
determines whether case is significant or ignored. */)
@@ -2677,7 +2682,7 @@ determines whether case is significant or ignored. */)
if (NILP (buf1))
nsberror (buffer1);
bp1 = XBUFFER (buf1);
- if (NILP (BVAR (bp1, name)))
+ if (!BUFFER_LIVE_P (bp1))
error ("Selecting deleted buffer");
}
@@ -2715,7 +2720,7 @@ determines whether case is significant or ignored. */)
if (NILP (buf2))
nsberror (buffer2);
bp2 = XBUFFER (buf2);
- if (NILP (BVAR (bp2, name)))
+ if (!BUFFER_LIVE_P (bp2))
error ("Selecting deleted buffer");
}
@@ -2783,8 +2788,8 @@ determines whether case is significant or ignored. */)
if (!NILP (trt))
{
- c1 = CHAR_TABLE_TRANSLATE (trt, c1);
- c2 = CHAR_TABLE_TRANSLATE (trt, c2);
+ c1 = char_table_translate (trt, c1);
+ c2 = char_table_translate (trt, c2);
}
if (c1 < c2)
return make_number (- 1 - chars);
@@ -2928,7 +2933,7 @@ Both characters must have the same length of multi-byte form. */)
else if (!changed)
{
changed = -1;
- modify_region (current_buffer, pos, XINT (end), 0);
+ modify_region_1 (pos, XINT (end), false);
if (! NILP (noundo))
{
@@ -3104,7 +3109,7 @@ It returns the number of characters changed. */)
pos = XINT (start);
pos_byte = CHAR_TO_BYTE (pos);
end_pos = XINT (end);
- modify_region (current_buffer, pos, end_pos, 0);
+ modify_region_1 (pos, end_pos, false);
cnt = 0;
for (; pos < end_pos; )
@@ -3433,8 +3438,8 @@ static ptrdiff_t message_length;
DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
doc: /* Display a message at the bottom of the screen.
-The message also goes into the `*Messages*' buffer.
-\(In keyboard macros, that's all it does.)
+The message also goes into the `*Messages*' buffer, if `message-log-max'
+is non-nil. (In keyboard macros, that's all it does.)
Return the message.
The first argument is a format control string, and the rest are data
@@ -4263,7 +4268,7 @@ usage: (format STRING &rest OBJECTS) */)
}
if (bufsize < p - buf)
- abort ();
+ emacs_abort ();
if (maybe_combine_byte)
nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
@@ -4603,7 +4608,7 @@ Transposing beyond buffer boundaries is an error. */)
len1_byte, end2, start2_byte + len2_byte)
|| count_combining_after (BYTE_POS_ADDR (start1_byte),
len1_byte, end2, start2_byte + len2_byte))
- abort ();
+ emacs_abort ();
}
else
{
@@ -4615,7 +4620,7 @@ Transposing beyond buffer boundaries is an error. */)
len2_byte, end1, start1_byte + len1_byte)
|| count_combining_after (BYTE_POS_ADDR (start1_byte),
len1_byte, end2, start2_byte + len2_byte))
- abort ();
+ emacs_abort ();
}
#endif
@@ -4628,7 +4633,7 @@ Transposing beyond buffer boundaries is an error. */)
if (end1 == start2) /* adjacent regions */
{
- modify_region (current_buffer, start1, end2, 0);
+ modify_region_1 (start1, end2, false);
record_change (start1, len1 + len2);
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
@@ -4687,8 +4692,8 @@ Transposing beyond buffer boundaries is an error. */)
{
USE_SAFE_ALLOCA;
- modify_region (current_buffer, start1, end1, 0);
- modify_region (current_buffer, start2, end2, 0);
+ modify_region_1 (start1, end1, false);
+ modify_region_1 (start2, end2, false);
record_change (start1, len1);
record_change (start2, len2);
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
@@ -4721,7 +4726,7 @@ Transposing beyond buffer boundaries is an error. */)
{
USE_SAFE_ALLOCA;
- modify_region (current_buffer, start1, end2, 0);
+ modify_region_1 (start1, end2, false);
record_change (start1, (end2 - start1));
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
@@ -4754,7 +4759,7 @@ Transposing beyond buffer boundaries is an error. */)
USE_SAFE_ALLOCA;
record_change (start1, (end2 - start1));
- modify_region (current_buffer, start1, end2, 0);
+ modify_region_1 (start1, end2, false);
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
@@ -4805,9 +4810,6 @@ Transposing beyond buffer boundaries is an error. */)
void
syms_of_editfns (void)
{
- environbuf = 0;
- initial_tz = 0;
-
DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
@@ -4916,6 +4918,8 @@ functions if all the text being accessed has this property. */);
defsubr (&Suser_real_login_name);
defsubr (&Suser_uid);
defsubr (&Suser_real_uid);
+ defsubr (&Sgroup_gid);
+ defsubr (&Sgroup_real_gid);
defsubr (&Suser_full_name);
defsubr (&Semacs_pid);
defsubr (&Scurrent_time);
diff --git a/src/emacs.c b/src/emacs.c
index 3c814a36043..8787e4bca9f 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -20,28 +20,38 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
-#include <setjmp.h>
#include <unistd.h>
-#include "lisp.h"
+#include <close-stream.h>
+#include <ignore-value.h>
-#ifdef HAVE_WINDOW_SYSTEM
-#include TERM_HEADER
-#endif /* HAVE_WINDOW_SYSTEM */
+#include "lisp.h"
#ifdef WINDOWSNT
#include <fcntl.h>
-#include <windows.h> /* just for w32.h */
#include "w32.h"
-#include "w32heap.h" /* for prototype of sbrk */
+#include "w32heap.h"
+#endif
+
+#if defined WINDOWSNT || defined HAVE_NTGUI
+#include "w32select.h"
+#include "w32font.h"
+#include "w32common.h"
+#endif
+
+#if defined HAVE_NTGUI && defined CYGWIN
+#include "cygw32.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>
@@ -54,6 +64,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "window.h"
#include "systty.h"
+#include "atimer.h"
#include "blockinput.h"
#include "syssignal.h"
#include "process.h"
@@ -85,16 +96,17 @@ extern void moncontrol (int mode);
#include <sys/personality.h>
#endif
-#ifndef O_RDWR
-#define O_RDWR 2
-#endif
-
static const char emacs_version[] = VERSION;
-static const char emacs_copyright[] = "Copyright (C) 2012 Free Software Foundation, Inc.";
+static const char emacs_copyright[] = COPYRIGHT;
/* Empty lisp strings. To avoid having to build any others. */
Lisp_Object empty_unibyte_string, empty_multibyte_string;
+#ifdef WINDOWSNT
+/* Cache for externally loaded libraries. */
+Lisp_Object Vlibrary_cache;
+#endif
+
/* Set after Emacs has started up the first time.
Prevents reinitialization of the Lisp world and keymaps
on subsequent starts. */
@@ -146,6 +158,22 @@ static void *my_heap_start;
static uprintmax_t heap_bss_diff;
#endif
+/* To run as a daemon under Cocoa or Windows, we must do a fork+exec,
+ not a simple fork.
+
+ On Cocoa, CoreFoundation lib fails in forked process:
+ http://developer.apple.com/ReleaseNotes/
+ CoreFoundation/CoreFoundation.html)
+
+ On Windows, a Cygwin fork child cannot access the USER subsystem.
+
+ We mark being in the exec'd process by a daemon name argument of
+ form "--daemon=\nFD0,FD1\nNAME" where FD are the pipe file descriptors,
+ NAME is the original daemon name, if any. */
+#if defined NS_IMPL_COCOA || (defined HAVE_NTGUI && defined CYGWIN)
+# define DAEMON_MUST_EXEC
+#endif
+
/* True means running Emacs without interactive terminal. */
bool noninteractive;
@@ -265,20 +293,9 @@ Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\
section of the Emacs manual or the file BUGS.\n"
-/* Signal code for the fatal signal that was received. */
-static int fatal_error_code;
-
/* True if handling a fatal error already. */
bool fatal_error_in_progress;
-#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
-/* When compiled with GTK and running under Gnome,
- multiple threads may be created. Keep track of our main
- thread to make sure signals are delivered to it (see syssignal.h). */
-
-pthread_t main_thread;
-#endif
-
#ifdef HAVE_NS
/* NS autrelease pool, for memory management. */
static void *ns_pool;
@@ -286,18 +303,13 @@ static void *ns_pool;
-/* Handle bus errors, invalid instruction, etc. */
-#ifndef FLOAT_CATCH_SIGILL
-static
-#endif
-void
-fatal_error_signal (int sig)
+/* Report a fatal error due to signal SIG, output a backtrace of at
+ most BACKTRACE_LIMIT lines, and exit. */
+_Noreturn void
+terminate_due_to_signal (int sig, int backtrace_limit)
{
- SIGNAL_THREAD_CHECK (sig);
- fatal_error_code = sig;
signal (sig, SIG_DFL);
-
- TOTALLY_UNBLOCK_INPUT;
+ totally_unblock_input ();
/* If fatal error occurs in code below, avoid infinite recursion. */
if (! fatal_error_in_progress)
@@ -308,50 +320,45 @@ fatal_error_signal (int sig)
Fkill_emacs (make_number (sig));
shut_down_emacs (sig, Qnil);
+ emacs_backtrace (backtrace_limit);
}
/* Signal the same code; this time it will really be fatal.
- Remember that since we're in a signal handler, the signal we're
- going to send is probably blocked, so we have to unblock it if we
- want to really receive it. */
+ Since we're in a signal handler, the signal is blocked, so we
+ have to unblock it if we want to really receive it. */
#ifndef MSDOS
- sigunblock (sigmask (fatal_error_code));
+ {
+ sigset_t unblocked;
+ sigemptyset (&unblocked);
+ sigaddset (&unblocked, sig);
+ pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
+ }
#endif
- kill (getpid (), fatal_error_code);
+ emacs_raise (sig);
+
+ /* This shouldn't be executed, but it prevents a warning. */
+ exit (1);
}
#ifdef SIGDANGER
/* Handler for SIGDANGER. */
-void
-memory_warning_signal (int sig)
+static void
+handle_danger_signal (int sig)
{
- signal (sig, memory_warning_signal);
- SIGNAL_THREAD_CHECK (sig);
-
malloc_warning ("Operating system warns that virtual memory is running low.\n");
/* It might be unsafe to call do_auto_save now. */
force_auto_save_soon ();
}
-#endif
-/* We define abort, rather than using it from the library,
- so that GDB can return from a breakpoint here.
- MSDOS has its own definition in msdos.c. */
-
-#if ! defined (DOS_NT) && ! defined (NO_ABORT)
-
-void
-abort (void)
+static void
+deliver_danger_signal (int sig)
{
- kill (getpid (), SIGABRT);
- /* This shouldn't be executed, but it prevents a warning. */
- exit (1);
+ deliver_process_signal (sig, handle_danger_signal);
}
#endif
-
/* Code for dealing with Lisp access to the Unix command line. */
@@ -525,7 +532,7 @@ 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 dump_tz[] = "UtC0";
+static char const dump_tz[] = "UtC0";
#endif
#ifndef ORDINARY_LINK
@@ -662,6 +669,22 @@ void (*__malloc_initialize_hook) (void) EXTERNALLY_VISIBLE = malloc_initialize_h
#endif /* DOUG_LEA_MALLOC */
+/* Close standard output and standard error, reporting any write
+ errors as best we can. This is intended for use with atexit. */
+static void
+close_output_streams (void)
+{
+ if (close_stream (stdout) != 0)
+ {
+ fprintf (stderr, "Write error to standard output: %s\n",
+ strerror (errno));
+ fflush (stderr);
+ _exit (EXIT_FAILURE);
+ }
+
+ if (close_stream (stderr) != 0)
+ _exit (EXIT_FAILURE);
+}
/* ARGSUSED */
int
@@ -669,6 +692,7 @@ main (int argc, char **argv)
{
char stack_bottom_variable;
bool do_initial_setlocale;
+ bool dumping;
int skip_args = 0;
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
@@ -676,7 +700,7 @@ main (int argc, char **argv)
bool no_loadup = 0;
char *junk = 0;
char *dname_arg = 0;
-#ifdef NS_IMPL_COCOA
+#ifdef DAEMON_MUST_EXEC
char dname_arg2[80];
#endif
char *ch_to_dir;
@@ -684,9 +708,9 @@ main (int argc, char **argv)
/* Record (approximately) where the stack begins. */
stack_bottom = &stack_bottom_variable;
-#if defined (USE_GTK) && defined (G_SLICE_ALWAYS_MALLOC)
+#ifdef G_SLICE_ALWAYS_MALLOC
/* This is used by the Cygwin build. */
- setenv ("G_SLICE", "always-malloc", 1);
+ xputenv ("G_SLICE=always-malloc");
#endif
#ifdef GNU_LINUX
@@ -702,6 +726,13 @@ main (int argc, char **argv)
}
#endif
+#if defined WINDOWSNT || defined HAVE_NTGUI
+ /* Set global variables used to detect Windows version. Do this as
+ early as possible. (unexw32.c calls this function as well, but
+ the additional call here is harmless.) */
+ cache_system_info ();
+#endif
+
#ifdef RUN_TIME_REMAP
if (initialized)
run_time_remap (argv[0]);
@@ -713,6 +744,8 @@ main (int argc, char **argv)
unexec_init_emacs_zone ();
#endif
+ atexit (close_output_streams);
+
sort_args (argc, argv);
argc = 0;
while (argv[argc]) argc++;
@@ -764,16 +797,14 @@ main (int argc, char **argv)
exit (1);
}
+ dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0
+ || strcmp (argv[argc - 1], "bootstrap") == 0);
#ifdef HAVE_PERSONALITY_LINUX32
- if (!initialized
- && (strcmp (argv[argc-1], "dump") == 0
- || strcmp (argv[argc-1], "bootstrap") == 0)
- && ! getenv ("EMACS_HEAP_EXEC"))
+ if (dumping && ! getenv ("EMACS_HEAP_EXEC"))
{
- static char heapexec[] = "EMACS_HEAP_EXEC=true";
/* Set this so we only do this once. */
- putenv (heapexec);
+ xputenv ("EMACS_HEAP_EXEC=true");
/* A flag to turn off address randomization which is introduced
in linux kernel shipped with fedora core 4 */
@@ -834,20 +865,12 @@ main (int argc, char **argv)
/* Arrange to get warning messages as memory fills up. */
memory_warnings (0, malloc_warning);
- /* Call malloc at least once, to run the initial __malloc_hook.
+ /* Call malloc at least once, to run malloc_initialize_hook.
Also call realloc and free for consistency. */
free (realloc (malloc (4), 4));
-# ifndef SYNC_INPUT
- /* Arrange to disable interrupt input inside malloc etc. */
- uninterrupt_malloc ();
-# endif /* not SYNC_INPUT */
#endif /* not SYSTEM_MALLOC */
-#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
- main_thread = pthread_self ();
-#endif /* FORWARD_SIGNAL_TO_MAIN_THREAD */
-
#if defined (MSDOS) || defined (WINDOWSNT)
/* We do all file input/output as binary files. When we need to translate
newlines, we do that manually. */
@@ -976,25 +999,19 @@ main (int argc, char **argv)
exit (1);
}
-#ifndef NS_IMPL_COCOA
+#ifndef DAEMON_MUST_EXEC
#ifdef USE_GTK
fprintf (stderr, "\nWarning: due to a long standing Gtk+ bug\nhttp://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
Emacs might crash when run in daemon mode and the X11 connection is unexpectedly lost.\n\
Using an Emacs configured with --with-x-toolkit=lucid does not have this problem.\n");
-#endif
+#endif /* USE_GTK */
f = fork ();
-#else /* NS_IMPL_COCOA */
- /* Under Cocoa we must do fork+exec as CoreFoundation lib fails in
- forked process: http://developer.apple.com/ReleaseNotes/
- CoreFoundation/CoreFoundation.html)
- We mark being in the exec'd process by a daemon name argument of
- form "--daemon=\nFD0,FD1\nNAME" where FD are the pipe file descriptors,
- NAME is the original daemon name, if any. */
+#else /* DAEMON_MUST_EXEC */
if (!dname_arg || !strchr (dname_arg, '\n'))
f = fork (); /* in orig */
else
f = 0; /* in exec'd */
-#endif /* NS_IMPL_COCOA */
+#endif /* !DAEMON_MUST_EXEC */
if (f > 0)
{
int retval;
@@ -1030,7 +1047,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
exit (1);
}
-#ifdef NS_IMPL_COCOA
+#ifdef DAEMON_MUST_EXEC
{
/* In orig process, forked as child, OR in exec'd. */
if (!dname_arg || !strchr (dname_arg, '\n'))
@@ -1066,7 +1083,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
dname_arg2);
dname_arg = *dname_arg2 ? dname_arg2 : NULL;
}
-#endif /* NS_IMPL_COCOA */
+#endif /* DAEMON_MUST_EXEC */
if (dname_arg)
daemon_name = xstrdup (dname_arg);
@@ -1076,132 +1093,23 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
that it is not accessible to programs started from .emacs. */
fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC);
-#ifdef HAVE_SETSID
setsid ();
-#endif
#else /* DOS_NT */
fprintf (stderr, "This platform does not support the -daemon flag.\n");
exit (1);
#endif /* DOS_NT */
}
+#if defined (HAVE_PTHREAD) && !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC)
if (! noninteractive)
{
-#if defined (USG5) && defined (INTERRUPT_INPUT)
- setpgrp ();
-#endif
-#if defined (HAVE_PTHREAD) && !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC)
- {
- extern void malloc_enable_thread (void);
-
- malloc_enable_thread ();
- }
-#endif
- }
+ extern void malloc_enable_thread (void);
- init_signals ();
-
- /* Don't catch SIGHUP if dumping. */
- if (1
-#ifndef CANNOT_DUMP
- && initialized
-#endif
- )
- {
- sigblock (sigmask (SIGHUP));
- /* In --batch mode, don't catch SIGHUP if already ignored.
- That makes nohup work. */
- if (! noninteractive
- || signal (SIGHUP, SIG_IGN) != SIG_IGN)
- signal (SIGHUP, fatal_error_signal);
- sigunblock (sigmask (SIGHUP));
+ malloc_enable_thread ();
}
-
- if (
-#ifndef CANNOT_DUMP
- ! noninteractive || initialized
-#else
- 1
-#endif
- )
- {
- /* Don't catch these signals in batch mode if dumping.
- On some machines, this sets static data that would make
- signal fail to work right when the dumped Emacs is run. */
- signal (SIGQUIT, fatal_error_signal);
- signal (SIGILL, fatal_error_signal);
- signal (SIGTRAP, fatal_error_signal);
-#ifdef SIGUSR1
- add_user_signal (SIGUSR1, "sigusr1");
-#endif
-#ifdef SIGUSR2
- add_user_signal (SIGUSR2, "sigusr2");
-#endif
-#ifdef SIGABRT
- signal (SIGABRT, fatal_error_signal);
-#endif
-#ifdef SIGHWE
- signal (SIGHWE, fatal_error_signal);
-#endif
-#ifdef SIGPRE
- signal (SIGPRE, fatal_error_signal);
-#endif
-#ifdef SIGORE
- signal (SIGORE, fatal_error_signal);
-#endif
-#ifdef SIGUME
- signal (SIGUME, fatal_error_signal);
-#endif
-#ifdef SIGDLK
- signal (SIGDLK, fatal_error_signal);
-#endif
-#ifdef SIGCPULIM
- signal (SIGCPULIM, fatal_error_signal);
-#endif
-#ifdef SIGIOT
- /* This is missing on some systems - OS/2, for example. */
- signal (SIGIOT, fatal_error_signal);
-#endif
-#ifdef SIGEMT
- signal (SIGEMT, fatal_error_signal);
-#endif
- signal (SIGFPE, fatal_error_signal);
-#ifdef SIGBUS
- signal (SIGBUS, fatal_error_signal);
-#endif
- signal (SIGSEGV, fatal_error_signal);
-#ifdef SIGSYS
- signal (SIGSYS, fatal_error_signal);
-#endif
- /* May need special treatment on MS-Windows. See
- http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html
- Please update the doc of kill-emacs, kill-emacs-hook, and
- NEWS if you change this.
- */
- if (noninteractive) signal (SIGINT, fatal_error_signal);
- signal (SIGTERM, fatal_error_signal);
-#ifdef SIGXCPU
- signal (SIGXCPU, fatal_error_signal);
-#endif
-#ifdef SIGXFSZ
- signal (SIGXFSZ, fatal_error_signal);
-#endif /* SIGXFSZ */
-
-#ifdef SIGDANGER
- /* This just means available memory is getting low. */
- signal (SIGDANGER, memory_warning_signal);
#endif
-#ifdef AIX
-/* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */
- signal (SIGXCPU, fatal_error_signal);
- signal (SIGIOINT, fatal_error_signal);
- signal (SIGGRANT, fatal_error_signal);
- signal (SIGRETRACT, fatal_error_signal);
- signal (SIGSOUND, fatal_error_signal);
- signal (SIGMSG, fatal_error_signal);
-#endif /* AIX */
- }
+ init_signals (dumping);
noninteractive1 = noninteractive;
@@ -1239,6 +1147,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
/* Called before syms_of_fileio, because it sets up Qerror_condition. */
syms_of_data ();
+ syms_of_fns (); /* Before syms_of_charset which uses hashtables. */
syms_of_fileio ();
/* Before syms_of_coding to initialize Vgc_cons_threshold. */
syms_of_alloc ();
@@ -1250,7 +1159,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_window_once (); /* Init the window system. */
#ifdef HAVE_WINDOW_SYSTEM
- init_fringe_once (); /* Swap bitmaps if necessary. */
+ init_fringe_once (); /* Swap bitmaps if necessary. */
#endif /* HAVE_WINDOW_SYSTEM */
}
@@ -1265,7 +1174,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
}
init_eval ();
- init_data ();
init_atimer ();
running_asynch_code = 0;
init_random ();
@@ -1378,9 +1286,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#ifdef WINDOWSNT
globals_of_w32 ();
+ globals_of_w32notify ();
/* Initialize environment from registry settings. */
init_environment (argv);
- init_ntproc (); /* must precede init_editfns. */
+ init_ntproc (dumping); /* must precede init_editfns. */
#endif
/* Initialize and GC-protect Vinitial_environment and
@@ -1391,8 +1300,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
/* egetenv is a pretty low-level facility, which may get called in
many circumstances; it seems flimsy to put off initializing it
until calling init_callproc. Do not do it when dumping. */
- if (initialized || ((strcmp (argv[argc-1], "dump") != 0
- && strcmp (argv[argc-1], "bootstrap") != 0)))
+ if (! dumping)
set_initial_environment ();
/* AIX crashes are reported in system versions 3.2.3 and 3.2.4
@@ -1400,7 +1308,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
don't pollute Vglobal_environment. */
/* Setting LANG here will defeat the startup locale processing... */
#ifdef AIX
- putenv ("LANG=C");
+ xputenv ("LANG=C");
#endif
init_buffer (); /* Init default directory of main buffer. */
@@ -1436,7 +1344,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
syms_of_lread ();
syms_of_print ();
syms_of_eval ();
- syms_of_fns ();
syms_of_floatfns ();
syms_of_buffer ();
@@ -1475,6 +1382,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#ifdef WINDOWSNT
syms_of_ntproc ();
#endif /* WINDOWSNT */
+#if defined CYGWIN && defined HAVE_NTGUI
+ syms_of_cygw32 ();
+#endif
syms_of_window ();
syms_of_xdisp ();
syms_of_font ();
@@ -1505,11 +1415,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#ifdef HAVE_NTGUI
syms_of_w32term ();
syms_of_w32fns ();
- syms_of_w32select ();
syms_of_w32menu ();
syms_of_fontset ();
#endif /* HAVE_NTGUI */
+#if defined WINDOWSNT || defined HAVE_NTGUI
+ syms_of_w32select ();
+#endif
+
#ifdef MSDOS
syms_of_xmenu ();
syms_of_dosfns ();
@@ -1529,15 +1442,21 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
syms_of_gnutls ();
#endif
+#ifdef HAVE_INOTIFY
+ syms_of_inotify ();
+#endif /* HAVE_INOTIFY */
+
#ifdef HAVE_DBUS
syms_of_dbusbind ();
#endif /* HAVE_DBUS */
#ifdef WINDOWSNT
syms_of_ntterm ();
+ syms_of_w32notify ();
#endif /* WINDOWSNT */
syms_of_threads ();
+ syms_of_profiler ();
keys_of_casefiddle ();
keys_of_cmds ();
@@ -1554,8 +1473,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
globals_of_w32font ();
globals_of_w32fns ();
globals_of_w32menu ();
- globals_of_w32select ();
#endif /* HAVE_NTGUI */
+
+#if defined WINDOWSNT || defined HAVE_NTGUI
+ globals_of_w32select ();
+#endif
}
init_charset ();
@@ -1570,7 +1492,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_fringe ();
#endif /* HAVE_WINDOW_SYSTEM */
init_macros ();
- init_floatfns ();
init_window ();
init_font ();
@@ -1885,7 +1806,7 @@ sort_args (int argc, char **argv)
}
if (best < 0)
- abort ();
+ emacs_abort ();
/* Copy the highest priority remaining option, with its args, to NEW.
Unless it is a duplicate of the previous one. */
@@ -1964,8 +1885,6 @@ all of which are called before Emacs is actually killed. */)
exit_code = (XINT (arg) < 0
? XINT (arg) | INT_MIN
: XINT (arg) & INT_MAX);
- else if (noninteractive && (fflush (stdout) || ferror (stdout)))
- exit_code = EXIT_FAILURE;
else
exit_code = EXIT_SUCCESS;
exit (exit_code);
@@ -1995,13 +1914,20 @@ shut_down_emacs (int sig, Lisp_Object stuff)
/* If we are controlling the terminal, reset terminal modes. */
#ifndef DOS_NT
{
- int pgrp = EMACS_GETPGRP (0);
- int tpgrp = tcgetpgrp (0);
+ pid_t pgrp = getpgrp ();
+ pid_t tpgrp = tcgetpgrp (0);
if ((tpgrp != -1) && tpgrp == pgrp)
{
reset_all_sys_modes ();
if (sig && sig != SIGTERM)
- fprintf (stderr, "Fatal error (%d)", sig);
+ {
+ static char const format[] = "Fatal error %d: ";
+ char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)];
+ int buflen = sprintf (buf, format, sig);
+ char const *sig_desc = safe_strsignal (sig);
+ ignore_value (write (STDERR_FILENO, buf, buflen));
+ ignore_value (write (STDERR_FILENO, sig_desc, strlen (sig_desc)));
+ }
}
}
#else
@@ -2019,16 +1945,10 @@ shut_down_emacs (int sig, Lisp_Object stuff)
unlock_all_files ();
#endif
-#ifdef SIGIO
/* There is a tendency for a SIGIO signal to arrive within exit,
and cause a SIGHUP because the input descriptor is already closed. */
unrequest_sigio ();
- signal (SIGIO, SIG_IGN);
-#endif
-
-#ifdef WINDOWSNT
- term_ntproc ();
-#endif
+ ignore_sigio ();
/* Do this only if terminating normally, we want glyph matrices
etc. in a core dump. */
@@ -2049,6 +1969,10 @@ shut_down_emacs (int sig, Lisp_Object stuff)
#ifdef HAVE_LIBXML2
xml_cleanup_parser ();
#endif
+
+#ifdef WINDOWSNT
+ term_ntproc (0);
+#endif
}
@@ -2130,12 +2054,6 @@ You must run Emacs in batch mode in order to dump it. */)
memory_warnings (my_edata, malloc_warning);
}
#endif /* not WINDOWSNT */
-#if defined (HAVE_PTHREAD) && !defined SYNC_INPUT
- /* Pthread may call malloc before main, and then we will get an endless
- loop, because pthread_self (see alloc.c) calls malloc the first time
- it is called on some systems. */
- reset_malloc_hooks ();
-#endif
#endif /* not SYSTEM_MALLOC */
#ifdef DOUG_LEA_MALLOC
malloc_state_ptr = malloc_get_state ();
@@ -2152,6 +2070,13 @@ You must run Emacs in batch mode in order to dump it. */)
free (malloc_state_ptr);
#endif
+#ifdef WINDOWSNT
+ Vlibrary_cache = Qnil;
+#endif
+#ifdef HAVE_WINDOW_SYSTEM
+ reset_image_types ();
+#endif
+
Vpurify_flag = tem;
return unbind_to (count, Qnil);
@@ -2484,6 +2409,11 @@ libraries; only those already known by Emacs will be loaded. */);
Vdynamic_library_alist = Qnil;
Fput (intern_c_string ("dynamic-library-alist"), Qrisky_local_variable, Qt);
+#ifdef WINDOWSNT
+ Vlibrary_cache = Qnil;
+ staticpro (&Vlibrary_cache);
+#endif
+
/* Make sure IS_DAEMON starts up as false. */
daemon_pipe[1] = 0;
}
diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index 1a62b59b7af..d10185072cc 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -21,13 +21,18 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "emacsgtkfixed.h"
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "frame.h"
#include "xterm.h"
+/* Silence a bogus diagnostic; see GNOME bug 683906. */
+#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif
+
#define EMACS_TYPE_FIXED emacs_fixed_get_type ()
#define EMACS_FIXED(obj) \
G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed)
diff --git a/src/eval.c b/src/eval.c
index ecdbe960a8a..0932564b36f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <limits.h>
-#include <setjmp.h>
#include <stdio.h>
#include "lisp.h"
#include "blockinput.h"
@@ -32,16 +31,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "xterm.h"
#endif
-struct backtrace
-{
- struct backtrace *next;
- Lisp_Object *function;
- Lisp_Object *args; /* Points to vector of args. */
- ptrdiff_t nargs; /* Length of vector. */
- /* Nonzero means call value of debugger when done with this operation. */
- unsigned int debug_on_exit : 1;
-};
-
/* static struct backtrace *backtrace_list; */
/* #if !BYTE_MARK_STACK */
@@ -69,7 +58,7 @@ Lisp_Object Qautoload, Qmacro, Qexit, Qinteractive, Qcommandp;
Lisp_Object Qinhibit_quit;
Lisp_Object Qand_rest;
static Lisp_Object Qand_optional;
-static Lisp_Object Qdebug_on_error;
+static Lisp_Object Qinhibit_debugger;
static Lisp_Object Qdeclare;
Lisp_Object Qinternal_interpreter_environment, Qclosure;
@@ -118,12 +107,6 @@ static EMACS_INT when_entered_debugger;
Lisp_Object Vsignaling_function;
-/* Set to non-zero while processing X events. Checked in Feval to
- make sure the Lisp interpreter isn't called from a signal handler,
- which is unsafe because the interpreter isn't reentrant. */
-
-int handling_signal;
-
/* 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
@@ -131,18 +114,17 @@ int handling_signal;
Lisp_Object inhibit_lisp_code;
static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
-static bool interactive_p (void);
static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args);
/* Functions to set Lisp_Object slots of struct specbinding. */
-static inline void
+static void
set_specpdl_symbol (Lisp_Object symbol)
{
specpdl_ptr->symbol = symbol;
}
-static inline void
+static void
set_specpdl_old_value (Lisp_Object oldval)
{
specpdl_ptr->old_value = oldval;
@@ -210,7 +192,7 @@ restore_stack_limits (Lisp_Object data)
/* Call the Lisp debugger, giving it argument ARG. */
-static Lisp_Object
+Lisp_Object
call_debugger (Lisp_Object arg)
{
bool debug_while_redisplaying;
@@ -248,7 +230,7 @@ call_debugger (Lisp_Object arg)
specbind (intern ("debugger-may-continue"),
debug_while_redisplaying ? Qnil : Qt);
specbind (Qinhibit_redisplay, Qnil);
- specbind (Qdebug_on_error, Qnil);
+ specbind (Qinhibit_debugger, Qt);
#if 0 /* Binding this prevents execution of Lisp code during
redisplay, which necessarily leads to display problems. */
@@ -525,102 +507,6 @@ usage: (function ARG) */)
}
-DEFUN ("interactive-p", Finteractive_p, Sinteractive_p, 0, 0, 0,
- doc: /* Return t if the containing function was run directly by user input.
-This means that the function was called with `call-interactively'
-\(which includes being called as the binding of a key)
-and input is currently coming from the keyboard (not a keyboard macro),
-and Emacs is not running in batch mode (`noninteractive' is nil).
-
-The only known proper use of `interactive-p' is in deciding whether to
-display a helpful message, or how to display it. If you're thinking
-of using it for any other purpose, it is quite likely that you're
-making a mistake. Think: what do you want to do when the command is
-called from a keyboard macro?
-
-To test whether your function was called with `call-interactively',
-either (i) add an extra optional argument and give it an `interactive'
-spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
-use `called-interactively-p'. */)
- (void)
-{
- return interactive_p () ? Qt : Qnil;
-}
-
-
-DEFUN ("called-interactively-p", Fcalled_interactively_p, Scalled_interactively_p, 0, 1, 0,
- doc: /* Return t if the containing function was called by `call-interactively'.
-If KIND is `interactive', then only return t if the call was made
-interactively by the user, i.e. not in `noninteractive' mode nor
-when `executing-kbd-macro'.
-If KIND is `any', on the other hand, it will return t for any kind of
-interactive call, including being called as the binding of a key, or
-from a keyboard macro, or in `noninteractive' mode.
-
-The only known proper use of `interactive' for KIND is in deciding
-whether to display a helpful message, or how to display it. If you're
-thinking of using it for any other purpose, it is quite likely that
-you're making a mistake. Think: what do you want to do when the
-command is called from a keyboard macro?
-
-Instead of using this function, it is sometimes cleaner to give your
-function an extra optional argument whose `interactive' spec specifies
-non-nil unconditionally (\"p\" is a good way to do this), or via
-\(not (or executing-kbd-macro noninteractive)). */)
- (Lisp_Object kind)
-{
- return (((INTERACTIVE || !EQ (kind, intern ("interactive")))
- && interactive_p ())
- ? Qt : Qnil);
-}
-
-
-/* Return true if function in which this appears was called using
- call-interactively and is not a built-in. */
-
-static bool
-interactive_p (void)
-{
- struct backtrace *btp;
- Lisp_Object fun;
-
- btp = backtrace_list;
-
- /* If this isn't a byte-compiled function, there may be a frame at
- the top for Finteractive_p. If so, skip it. */
- fun = Findirect_function (*btp->function, Qnil);
- if (SUBRP (fun) && (XSUBR (fun) == &Sinteractive_p
- || XSUBR (fun) == &Scalled_interactively_p))
- btp = btp->next;
-
- /* If we're running an Emacs 18-style byte-compiled function, there
- may be a frame for Fbytecode at the top level. In any version of
- Emacs there can be Fbytecode frames for subexpressions evaluated
- inside catch and condition-case. Skip past them.
-
- If this isn't a byte-compiled function, then we may now be
- looking at several frames for special forms. Skip past them. */
- while (btp
- && (EQ (*btp->function, Qbytecode)
- || btp->nargs == UNEVALLED))
- btp = btp->next;
-
- /* `btp' now points at the frame of the innermost function that isn't
- a special form, ignoring frames for Finteractive_p and/or
- Fbytecode at the top. If this frame is for a built-in function
- (such as load or eval-region) return false. */
- fun = Findirect_function (*btp->function, Qnil);
- if (SUBRP (fun))
- return 0;
-
- /* `btp' points to the frame of a Lisp function that called interactive-p.
- Return t if that function was called interactively. */
- if (btp && btp->next && EQ (*btp->next->function, Qcall_interactively))
- return 1;
- return 0;
-}
-
-
DEFUN ("defvaralias", Fdefvaralias, Sdefvaralias, 2, 3, 0,
doc: /* Make NEW-ALIAS a variable alias for symbol BASE-VARIABLE.
Aliased variables always have the same value; setting one sets the other.
@@ -726,14 +612,15 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
else
{ /* Check if there is really a global binding rather than just a let
binding that shadows the global unboundness of the var. */
- volatile struct specbinding *pdl = specpdl_ptr;
+ struct specbinding *pdl = specpdl_ptr;
while (pdl > specpdl)
{
if (EQ ((--pdl)->symbol, sym) && !pdl->func
&& EQ (pdl->old_value, Qunbound))
{
- message_with_string ("Warning: defvar ignored because %s is let-bound",
- SYMBOL_NAME (sym), 1);
+ message_with_string
+ ("Warning: defvar ignored because %s is let-bound",
+ SYMBOL_NAME (sym), 1);
break;
}
}
@@ -753,8 +640,8 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
/* A simple (defvar foo) with lexical scoping does "nothing" except
declare that var to be dynamically scoped *locally* (i.e. within
the current file or let-block). */
- Vinternal_interpreter_environment =
- Fcons (sym, Vinternal_interpreter_environment);
+ Vinternal_interpreter_environment
+ = Fcons (sym, Vinternal_interpreter_environment);
else
{
/* Simple (defvar <var>) should not count as a definition at all.
@@ -1007,7 +894,7 @@ definitions to shadow the loaded ones for use in file byte-compilation. */)
if (NILP (tem))
{
def = XSYMBOL (sym)->function;
- if (!EQ (def, Qunbound))
+ if (!NILP (def))
continue;
}
break;
@@ -1022,7 +909,7 @@ definitions to shadow the loaded ones for use in file byte-compilation. */)
GCPRO1 (form);
def = Fautoload_do_load (def, sym, Qmacro);
UNGCPRO;
- if (EQ (def, Qunbound) || !CONSP (def))
+ if (!CONSP (def))
/* Not defined or definition not suitable. */
break;
if (!EQ (XCAR (def), Qmacro))
@@ -1091,7 +978,7 @@ internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object
catchlist = &c;
/* Call FUNC. */
- if (! _setjmp (c.jmp))
+ if (! sys_setjmp (c.jmp))
c.val = (*func) (arg);
/* Throw works by a longjmp that comes right here. */
@@ -1102,7 +989,7 @@ internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object
/* Unwind the specbind, catch, and handler stacks back to CATCH, and
jump to that CATCH, returning VALUE as the value of that catch.
- This is the guts Fthrow and Fsignal; they differ only in the way
+ This is the guts of Fthrow and Fsignal; they differ only in the way
they choose the catch tag to throw to. A catch tag for a
condition-case form has a TAG of Qnil.
@@ -1111,7 +998,7 @@ internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object
the handler stack as we go, so that the proper handlers are in
effect for each unwind-protect clause we run. At the end, restore
some static info saved in CATCH, and longjmp to the location
- specified in the
+ specified there.
This is used for correct unwinding in Fthrow and Fsignal. */
@@ -1125,8 +1012,7 @@ unwind_to_catch (struct catchtag *catch, Lisp_Object value)
/* Restore certain special C variables. */
set_poll_suppress_count (catch->poll_suppress_count);
- UNBLOCK_INPUT_TO (catch->interrupt_input_blocked);
- handling_signal = 0;
+ unblock_input_to (catch->interrupt_input_blocked);
immediate_quit = 0;
do
@@ -1141,16 +1027,6 @@ unwind_to_catch (struct catchtag *catch, Lisp_Object value)
}
while (! last_time);
-#if HAVE_X_WINDOWS
- /* If x_catch_errors was done, turn it off now.
- (First we give unbind_to a chance to do that.) */
-#if 0 /* This would disable x_catch_errors after x_connection_closed.
- The catch must remain in effect during that delicate
- state. --lorentey */
- x_fully_uncatch_errors ();
-#endif
-#endif
-
byte_stack_list = catch->byte_stack;
gcprolist = catch->gcpro;
#ifdef DEBUG_GCPRO
@@ -1159,7 +1035,7 @@ unwind_to_catch (struct catchtag *catch, Lisp_Object value)
backtrace_list = catch->backlist;
lisp_eval_depth = catch->f_lisp_eval_depth;
- _longjmp (catch->jmp, 1);
+ sys_longjmp (catch->jmp, 1);
}
DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
@@ -1223,12 +1099,9 @@ See also the function `signal' for more info.
usage: (condition-case VAR BODYFORM &rest HANDLERS) */)
(Lisp_Object args)
{
- register Lisp_Object bodyform, handlers;
- volatile Lisp_Object var;
-
- var = Fcar (args);
- bodyform = Fcar (Fcdr (args));
- handlers = Fcdr (Fcdr (args));
+ Lisp_Object var = Fcar (args);
+ Lisp_Object bodyform = Fcar (Fcdr (args));
+ Lisp_Object handlers = Fcdr (Fcdr (args));
return internal_lisp_condition_case (var, bodyform, handlers);
}
@@ -1268,7 +1141,7 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
c.interrupt_input_blocked = interrupt_input_blocked;
c.gcpro = gcprolist;
c.byte_stack = byte_stack_list;
- if (_setjmp (c.jmp))
+ if (sys_setjmp (c.jmp))
{
if (!NILP (h.var))
specbind (h.var, c.val);
@@ -1323,7 +1196,7 @@ internal_condition_case (Lisp_Object (*bfun) (void), Lisp_Object handlers,
c.interrupt_input_blocked = interrupt_input_blocked;
c.gcpro = gcprolist;
c.byte_stack = byte_stack_list;
- if (_setjmp (c.jmp))
+ if (sys_setjmp (c.jmp))
{
return (*hfun) (c.val);
}
@@ -1361,7 +1234,7 @@ internal_condition_case_1 (Lisp_Object (*bfun) (Lisp_Object), Lisp_Object arg,
c.interrupt_input_blocked = interrupt_input_blocked;
c.gcpro = gcprolist;
c.byte_stack = byte_stack_list;
- if (_setjmp (c.jmp))
+ if (sys_setjmp (c.jmp))
{
return (*hfun) (c.val);
}
@@ -1403,7 +1276,7 @@ internal_condition_case_2 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object),
c.interrupt_input_blocked = interrupt_input_blocked;
c.gcpro = gcprolist;
c.byte_stack = byte_stack_list;
- if (_setjmp (c.jmp))
+ if (sys_setjmp (c.jmp))
{
return (*hfun) (c.val);
}
@@ -1447,7 +1320,7 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
c.interrupt_input_blocked = interrupt_input_blocked;
c.gcpro = gcprolist;
c.byte_stack = byte_stack_list;
- if (_setjmp (c.jmp))
+ if (sys_setjmp (c.jmp))
{
return (*hfun) (c.val, nargs, args);
}
@@ -1509,10 +1382,10 @@ See also the function `condition-case'. */)
struct handler *h;
struct backtrace *bp;
- immediate_quit = handling_signal = 0;
+ immediate_quit = 0;
abort_on_gc = 0;
if (gc_in_progress || waiting_for_input)
- abort ();
+ emacs_abort ();
#if 0 /* rms: I don't know why this was here,
but it is surely wrong for an error that is handled. */
@@ -1546,10 +1419,10 @@ See also the function `condition-case'. */)
if (backtrace_list && !NILP (error_symbol))
{
bp = backtrace_list->next;
- if (bp && bp->function && EQ (*bp->function, Qerror))
+ if (bp && EQ (bp->function, Qerror))
bp = bp->next;
- if (bp && bp->function)
- Vsignaling_function = *bp->function;
+ if (bp)
+ Vsignaling_function = bp->function;
}
for (h = handlerlist; h; h = h->next)
@@ -1560,7 +1433,7 @@ See also the function `condition-case'. */)
}
if (/* Don't run the debugger for a memory-full error.
- (There is no room in memory to do that!) */
+ (There is no room in memory to do that!) */
!NILP (error_symbol)
&& (!NILP (Vdebug_on_signal)
/* If no handler is present now, try to run the debugger. */
@@ -1609,7 +1482,7 @@ void
xsignal (Lisp_Object error_symbol, Lisp_Object data)
{
Fsignal (error_symbol, data);
- abort ();
+ emacs_abort ();
}
/* Like xsignal, but takes 0, 1, 2, or 3 args instead of a list. */
@@ -1743,7 +1616,8 @@ maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, Lisp_Object data)
if (
/* Don't try to run the debugger with interrupts blocked.
The editing loop would return anyway. */
- ! INPUT_BLOCKED_P
+ ! input_blocked_p ()
+ && NILP (Vinhibit_debugger)
/* Does user want to enter debugger for this kind of error? */
&& (EQ (sig, Qquit)
? debug_on_quit
@@ -1860,12 +1734,12 @@ then strings and vectors are not accepted. */)
fun = function;
- fun = indirect_function (fun); /* Check cycles. */
- if (NILP (fun) || EQ (fun, Qunbound))
+ fun = indirect_function (fun); /* Check cycles. */
+ if (NILP (fun))
return Qnil;
/* Check an `interactive-form' property if present, analogous to the
- function-documentation property. */
+ function-documentation property. */
fun = function;
while (SYMBOLP (fun))
{
@@ -1925,24 +1799,19 @@ this does nothing and returns nil. */)
CHECK_STRING (file);
/* If function is defined and not as an autoload, don't override. */
- if (!EQ (XSYMBOL (function)->function, Qunbound)
- && !(CONSP (XSYMBOL (function)->function)
- && EQ (XCAR (XSYMBOL (function)->function), Qautoload)))
+ if (!NILP (XSYMBOL (function)->function)
+ && !AUTOLOADP (XSYMBOL (function)->function))
return Qnil;
- if (NILP (Vpurify_flag))
- /* Only add entries after dumping, because the ones before are
- not useful and else we get loads of them from the loaddefs.el. */
- LOADHIST_ATTACH (Fcons (Qautoload, function));
- else if (EQ (docstring, make_number (0)))
+ if (!NILP (Vpurify_flag) && EQ (docstring, make_number (0)))
/* `read1' in lread.c has found the docstring starting with "\
and assumed the docstring will be provided by Snarf-documentation, so it
passed us 0 instead. But that leads to accidental sharing in purecopy's
hash-consing, so we use a (hopefully) unique integer instead. */
- docstring = make_number (XUNTAG (function, Lisp_Symbol));
- return Ffset (function,
- Fpurecopy (list5 (Qautoload, file, docstring,
- interactive, type)));
+ docstring = make_number (XHASH (function));
+ return Fdefalias (function,
+ list5 (Qautoload, file, docstring, interactive, type),
+ Qnil);
}
Lisp_Object
@@ -2061,9 +1930,6 @@ eval_sub (Lisp_Object form)
struct backtrace backtrace;
struct gcpro gcpro1, gcpro2, gcpro3;
- if (handling_signal)
- abort ();
-
if (SYMBOLP (form))
{
/* Look up its binding in the lexical environment.
@@ -2097,11 +1963,11 @@ eval_sub (Lisp_Object form)
original_args = XCDR (form);
backtrace.next = backtrace_list;
- backtrace_list = &backtrace;
- backtrace.function = &original_fun; /* This also protects them from gc. */
+ backtrace.function = original_fun; /* This also protects them from gc. */
backtrace.args = &original_args;
backtrace.nargs = UNEVALLED;
backtrace.debug_on_exit = 0;
+ backtrace_list = &backtrace;
if (debug_on_next_call)
do_debug_on_call (Qt);
@@ -2112,7 +1978,7 @@ eval_sub (Lisp_Object form)
/* Optimize for no indirection. */
fun = original_fun;
- if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+ if (SYMBOLP (fun) && !NILP (fun)
&& (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
fun = indirect_function (fun);
@@ -2226,7 +2092,7 @@ eval_sub (Lisp_Object form)
is supported by this code. We need to either rewrite the
subr to use a different argument protocol, or add more
cases to this switch. */
- abort ();
+ emacs_abort ();
}
}
}
@@ -2234,7 +2100,7 @@ eval_sub (Lisp_Object form)
val = apply_lambda (fun, original_args);
else
{
- if (EQ (fun, Qunbound))
+ if (NILP (fun))
xsignal1 (Qvoid_function, original_fun);
if (!CONSP (fun))
xsignal1 (Qinvalid_function, original_fun);
@@ -2308,10 +2174,10 @@ usage: (apply FUNCTION &rest ARGUMENTS) */)
numargs += nargs - 2;
/* Optimize for no indirection. */
- if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+ if (SYMBOLP (fun) && !NILP (fun)
&& (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
fun = indirect_function (fun);
- if (EQ (fun, Qunbound))
+ if (NILP (fun))
{
/* Let funcall get the error. */
fun = args[0];
@@ -2403,14 +2269,10 @@ usage: (run-hooks &rest HOOKS) */)
DEFUN ("run-hook-with-args", Frun_hook_with_args,
Srun_hook_with_args, 1, MANY, 0,
doc: /* Run HOOK with the specified arguments ARGS.
-HOOK should be a symbol, a hook variable. If HOOK has a non-nil
-value, that value may be a function or a list of functions to be
-called to run the hook. If the value is a function, it is called with
-the given arguments and its return value is returned. If it is a list
-of functions, those functions are called, in order,
-with the given arguments ARGS.
-It is best not to depend on the value returned by `run-hook-with-args',
-as that may change.
+HOOK should be a symbol, a hook variable. The value of HOOK
+may be nil, a function, or a list of functions. Call each
+function in order with arguments ARGS. The final return value
+is unspecified.
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
@@ -2420,17 +2282,18 @@ usage: (run-hook-with-args HOOK &rest ARGS) */)
return run_hook_with_args (nargs, args, funcall_nil);
}
+/* NB this one still documents a specific non-nil return value.
+ (As did run-hook-with-args and run-hook-with-args-until-failure
+ until they were changed in 24.1.) */
DEFUN ("run-hook-with-args-until-success", Frun_hook_with_args_until_success,
Srun_hook_with_args_until_success, 1, MANY, 0,
doc: /* Run HOOK with the specified arguments ARGS.
-HOOK should be a symbol, a hook variable. If HOOK has a non-nil
-value, that value may be a function or a list of functions to be
-called to run the hook. If the value is a function, it is called with
-the given arguments and its return value is returned.
-If it is a list of functions, those functions are called, in order,
-with the given arguments ARGS, until one of them
-returns a non-nil value. Then we return that value.
-However, if they all return nil, we return nil.
+HOOK should be a symbol, a hook variable. The value of HOOK
+may be nil, a function, or a list of functions. Call each
+function in order with arguments ARGS, stopping at the first
+one that returns non-nil, and return that value. Otherwise (if
+all functions return nil, or if there are no functions to call),
+return nil.
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
@@ -2449,13 +2312,12 @@ funcall_not (ptrdiff_t nargs, Lisp_Object *args)
DEFUN ("run-hook-with-args-until-failure", Frun_hook_with_args_until_failure,
Srun_hook_with_args_until_failure, 1, MANY, 0,
doc: /* Run HOOK with the specified arguments ARGS.
-HOOK should be a symbol, a hook variable. If HOOK has a non-nil
-value, that value may be a function or a list of functions to be
-called to run the hook. If the value is a function, it is called with
-the given arguments and its return value is returned.
-If it is a list of functions, those functions are called, in order,
-with the given arguments ARGS, until one of them returns nil.
-Then we return nil. However, if they all return non-nil, we return non-nil.
+HOOK should be a symbol, a hook variable. The value of HOOK
+may be nil, a function, or a list of functions. Call each
+function in order with arguments ARGS, stopping at the first
+one that returns nil, and return nil. Otherwise (if all functions
+return non-nil, or if there are no functions to call), return non-nil
+\(do not rely on the precise return value in this case).
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
@@ -2769,11 +2631,11 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
}
backtrace.next = backtrace_list;
- backtrace_list = &backtrace;
- backtrace.function = &args[0];
+ backtrace.function = args[0];
backtrace.args = &args[1]; /* This also GCPROs them. */
backtrace.nargs = nargs - 1;
backtrace.debug_on_exit = 0;
+ backtrace_list = &backtrace;
/* Call GC after setting up the backtrace, so the latter GCPROs the args. */
maybe_gc ();
@@ -2789,7 +2651,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
/* Optimize for no indirection. */
fun = original_fun;
- if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+ if (SYMBOLP (fun) && !NILP (fun)
&& (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
fun = indirect_function (fun);
@@ -2869,7 +2731,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
/* If a subr takes more than 8 arguments without using MANY
or UNEVALLED, we need to extend this function to support it.
Until this is done, there is no way to call the function. */
- abort ();
+ emacs_abort ();
}
}
}
@@ -2877,7 +2739,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
val = funcall_lambda (fun, numargs, args + 1);
else
{
- if (EQ (fun, Qunbound))
+ if (NILP (fun))
xsignal1 (Qvoid_function, original_fun);
if (!CONSP (fun))
xsignal1 (Qinvalid_function, original_fun);
@@ -3000,7 +2862,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
lexenv = Qnil;
}
else
- abort ();
+ emacs_abort ();
i = optional = rest = 0;
for (; CONSP (syms_left); syms_left = XCDR (syms_left))
@@ -3172,8 +3034,6 @@ specbind (Lisp_Object symbol, Lisp_Object value)
{
struct Lisp_Symbol *sym;
- eassert (!handling_signal);
-
CHECK_SYMBOL (symbol);
sym = XSYMBOL (symbol);
if (specpdl_ptr == specpdl + specpdl_size)
@@ -3258,15 +3118,13 @@ specbind (Lisp_Object symbol, Lisp_Object value)
do_specbind (sym, specpdl_ptr - 1, value);
break;
}
- default: abort ();
+ default: emacs_abort ();
}
}
void
record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg)
{
- eassert (!handling_signal);
-
if (specpdl_ptr == specpdl + specpdl_size)
grow_specpdl ();
specpdl_ptr->func = function;
@@ -3432,12 +3290,12 @@ Output stream used is value of `standard-output'. */)
write_string (backlist->debug_on_exit ? "* " : " ", 2);
if (backlist->nargs == UNEVALLED)
{
- Fprin1 (Fcons (*backlist->function, *backlist->args), Qnil);
+ Fprin1 (Fcons (backlist->function, *backlist->args), Qnil);
write_string ("\n", -1);
}
else
{
- tem = *backlist->function;
+ tem = backlist->function;
Fprin1 (tem, Qnil); /* This can QUIT. */
write_string ("(", -1);
if (backlist->nargs == MANY)
@@ -3495,7 +3353,7 @@ If NFRAMES is more than the number of frames, the value is nil. */)
if (!backlist)
return Qnil;
if (backlist->nargs == UNEVALLED)
- return Fcons (Qnil, Fcons (*backlist->function, *backlist->args));
+ return Fcons (Qnil, Fcons (backlist->function, *backlist->args));
else
{
if (backlist->nargs == MANY) /* FIXME: Can this happen? */
@@ -3503,7 +3361,7 @@ If NFRAMES is more than the number of frames, the value is nil. */)
else
tem = Flist (backlist->nargs, backlist->args);
- return Fcons (Qt, Fcons (*backlist->function, tem));
+ return Fcons (Qt, Fcons (backlist->function, tem));
}
}
@@ -3517,7 +3375,7 @@ mark_backtrace (void)
for (backlist = backtrace_list; backlist; backlist = backlist->next)
{
- mark_object (*backlist->function);
+ mark_object (backlist->function);
if (backlist->nargs == UNEVALLED
|| backlist->nargs == MANY) /* FIXME: Can this happen? */
@@ -3569,7 +3427,7 @@ before making `inhibit-quit' nil. */);
DEFSYM (Qinhibit_quit, "inhibit-quit");
DEFSYM (Qautoload, "autoload");
- DEFSYM (Qdebug_on_error, "debug-on-error");
+ DEFSYM (Qinhibit_debugger, "inhibit-debugger");
DEFSYM (Qmacro, "macro");
DEFSYM (Qdeclare, "declare");
@@ -3584,6 +3442,12 @@ before making `inhibit-quit' nil. */);
DEFSYM (Qclosure, "closure");
DEFSYM (Qdebug, "debug");
+ DEFVAR_LISP ("inhibit-debugger", Vinhibit_debugger,
+ doc: /* Non-nil means never enter the debugger.
+Normally set while the debugger is already active, to avoid recursive
+invocations. */);
+ Vinhibit_debugger = Qnil;
+
DEFVAR_LISP ("debug-on-error", Vdebug_on_error,
doc: /* Non-nil means enter debugger if an error is signaled.
Does not apply to errors handled by `condition-case' or those
@@ -3593,7 +3457,7 @@ if one of its condition symbols appears in the list.
When you evaluate an expression interactively, this variable
is temporarily non-nil if `eval-expression-debug-on-error' is non-nil.
The command `toggle-debug-on-error' toggles this.
-See also the variable `debug-on-quit'. */);
+See also the variable `debug-on-quit' and `inhibit-debugger'. */);
Vdebug_on_error = Qnil;
DEFVAR_LISP ("debug-ignored-errors", Vdebug_ignored_errors,
@@ -3693,8 +3557,6 @@ alist of active lexical bindings. */);
defsubr (&Sunwind_protect);
defsubr (&Scondition_case);
defsubr (&Ssignal);
- defsubr (&Sinteractive_p);
- defsubr (&Scalled_interactively_p);
defsubr (&Scommandp);
defsubr (&Sautoload);
defsubr (&Sautoload_do_load);
diff --git a/src/fileio.c b/src/fileio.c
index 7466914af1c..f1cfe0eb625 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -23,7 +23,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <setjmp.h>
#include <unistd.h>
#ifdef HAVE_PWD_H
@@ -37,6 +36,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <selinux/context.h>
#endif
+#ifdef HAVE_POSIX_ACL
+#include <sys/acl.h>
+#endif
+
#include <c-ctype.h>
#include "lisp.h"
@@ -53,6 +56,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define NOMINMAX 1
#include <windows.h>
#include <fcntl.h>
+#include <sys/file.h>
+#include "w32.h"
#endif /* not WINDOWSNT */
#ifdef MSDOS
@@ -85,18 +90,18 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "commands.h"
-/* Nonzero during writing of auto-save files. */
-static int auto_saving;
+/* True during writing of auto-save files. */
+static bool auto_saving;
/* Nonzero umask during creation of auto-save directories. */
-static int auto_saving_dir_umask;
+static mode_t auto_saving_dir_umask;
/* Set by auto_save_1 to mode of original file so Fwrite_region will create
a new file with the same mode as the original. */
-static int auto_save_mode_bits;
+static mode_t auto_save_mode_bits;
/* Set by auto_save_1 if an error occurred during the last auto-save. */
-static int auto_save_error_occurred;
+static bool auto_save_error_occurred;
/* The symbol bound to coding-system-for-read when
insert-file-contents is called for recovering a file. This is not
@@ -145,10 +150,10 @@ Lisp_Object Qfile_name_history;
static Lisp_Object Qcar_less_than_car;
-static int a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
- Lisp_Object *, struct coding_system *);
-static int e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
- struct coding_system *);
+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,
+ struct coding_system *);
void
@@ -235,6 +240,8 @@ 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;
@@ -314,6 +321,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
register const char *beg;
#else
register char *beg;
+ Lisp_Object tem_fn;
#endif
register const char *p;
Lisp_Object handler;
@@ -373,10 +381,13 @@ Given a Unix syntax file name, returns a string ending in slash. */)
p = beg + strlen (beg);
}
}
- dostounix_filename (beg);
-#endif /* DOS_NT */
-
+ tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg,
+ STRING_MULTIBYTE (filename)));
+ dostounix_filename (SSDATA (tem_fn));
+ return DECODE_FILE (tem_fn);
+#else /* DOS_NT */
return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
+#endif /* DOS_NT */
}
DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,
@@ -450,7 +461,7 @@ get a current directory to run processes in. */)
/* Convert from file name SRC of length SRCLEN to directory name
in DST. On UNIX, just make sure there is a terminating /.
- Return the length of DST. */
+ Return the length of DST in bytes. */
static ptrdiff_t
file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen)
@@ -472,7 +483,14 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen)
srclen++;
}
#ifdef DOS_NT
- dostounix_filename (dst);
+ {
+ Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
+
+ tem_fn = ENCODE_FILE (tem_fn);
+ dostounix_filename (SSDATA (tem_fn));
+ tem_fn = DECODE_FILE (tem_fn);
+ memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
+ }
#endif
return srclen;
}
@@ -514,7 +532,7 @@ For a Unix-syntax file name, just appends a slash. */)
/* Convert from directory name SRC of length SRCLEN to
file name in DST. On UNIX, just make sure there isn't
- a terminating /. Return the length of DST. */
+ a terminating /. Return the length of DST in bytes. */
static ptrdiff_t
directory_file_name (char *dst, char *src, ptrdiff_t srclen)
@@ -533,7 +551,14 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen)
srclen--;
}
#ifdef DOS_NT
- dostounix_filename (dst);
+ {
+ Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
+
+ tem_fn = ENCODE_FILE (tem_fn);
+ dostounix_filename (SSDATA (tem_fn));
+ tem_fn = DECODE_FILE (tem_fn);
+ memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
+ }
#endif
return srclen;
}
@@ -595,7 +620,7 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
which has no existing file. To make this work, PREFIX should be
an absolute file name.
- BASE64_P non-zero means add the pid as 3 characters in base64
+ BASE64_P means add the pid as 3 characters in base64
encoding. In this case, 6 characters will be added to PREFIX to
form the file name. Otherwise, if Emacs is running on a system
with long file names, add the pid as a decimal number.
@@ -604,7 +629,7 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
generated. */
Lisp_Object
-make_temp_name (Lisp_Object prefix, int base64_p)
+make_temp_name (Lisp_Object prefix, bool base64_p)
{
Lisp_Object val;
int len, clen;
@@ -669,7 +694,6 @@ make_temp_name (Lisp_Object prefix, int base64_p)
while (1)
{
- struct stat ignored;
unsigned num = make_temp_name_count;
p[0] = make_temp_name_tbl[num & 63], num >>= 6;
@@ -681,7 +705,7 @@ make_temp_name (Lisp_Object prefix, int base64_p)
make_temp_name_count += 25229;
make_temp_name_count %= 225307;
- if (stat (data, &ignored) < 0)
+ if (!check_existing (data))
{
/* We want to return only if errno is ENOENT. */
if (errno == ENOENT)
@@ -761,8 +785,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
struct passwd *pw;
#ifdef DOS_NT
int drive = 0;
- int collapse_newdir = 1;
- int is_escaped = 0;
+ bool collapse_newdir = 1;
+ bool is_escaped = 0;
#endif /* DOS_NT */
ptrdiff_t length;
Lisp_Object handler, result, handled_name;
@@ -920,10 +944,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
/* If it turns out that the filename we want to return is just a
suffix of FILENAME, we don't need to go through and edit
things; we just need to construct a new string using data
- starting at the middle of FILENAME. If we set lose to a
- non-zero value, that means we've discovered that we can't do
- that cool trick. */
- int lose = 0;
+ starting at the middle of FILENAME. If we set LOSE, that
+ means we've discovered that we can't do that cool trick. */
+ bool lose = 0;
char *p = nm;
while (*p)
@@ -952,7 +975,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
#ifdef DOS_NT
/* Make sure directories are all separated with /, but
avoid allocation of a new string when not required. */
- dostounix_filename (nm);
+ if (multibyte)
+ {
+ Lisp_Object tem_name = make_specified_string (nm, -1, strlen (nm),
+ multibyte);
+
+ tem_name = ENCODE_FILE (tem_name);
+ dostounix_filename (SSDATA (tem_name));
+ tem_name = DECODE_FILE (tem_name);
+ memcpy (nm, SSDATA (tem_name), SBYTES (tem_name) + 1);
+ }
+ else
+ dostounix_filename (nm);
#ifdef WINDOWSNT
if (IS_DIRECTORY_SEP (nm[1]))
{
@@ -1027,9 +1061,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
memcpy (o, nm, p - nm);
o [p - nm] = 0;
- BLOCK_INPUT;
- pw = (struct passwd *) getpwnam (o + 1);
- UNBLOCK_INPUT;
+ block_input ();
+ pw = getpwnam (o + 1);
+ unblock_input ();
if (pw)
{
newdir = pw->pw_dir;
@@ -1134,7 +1168,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
newdir = "/";
}
else
- getwd (adir);
+ getcwd (adir, MAXPATHLEN + 1);
newdir = adir;
}
@@ -1294,7 +1328,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
#endif /* WINDOWSNT */
{
- if (!drive) abort ();
+ if (!drive) emacs_abort ();
target -= 2;
target[0] = DRIVE_LETTER (drive);
target[1] = ':';
@@ -1306,10 +1340,13 @@ filesystem tree, not (expand-file-name ".." dirname). */)
target[0] = '/';
target[1] = ':';
}
- dostounix_filename (target);
-#endif /* DOS_NT */
-
result = make_specified_string (target, -1, o - target, multibyte);
+ result = ENCODE_FILE (result);
+ dostounix_filename (SSDATA (result));
+ result = DECODE_FILE (result);
+#else /* !DOS_NT */
+ result = make_specified_string (target, -1, o - target, multibyte);
+#endif /* !DOS_NT */
}
/* Again look to see if the file name has special constructs in it
@@ -1360,7 +1397,6 @@ See also the function `substitute-in-file-name'.")
ptrdiff_t tlen;
unsigned char *target;
struct passwd *pw;
- int lose;
CHECK_STRING (name);
nm = SDATA (name);
@@ -1369,12 +1405,11 @@ See also the function `substitute-in-file-name'.")
If no /./ or /../ we can return right away. */
if (nm[0] == '/')
{
+ bool lose = 0;
p = nm;
- lose = 0;
while (*p)
{
- if (p[0] == '/' && p[1] == '/'
- )
+ if (p[0] == '/' && p[1] == '/')
nm = p + 1;
if (p[0] == '/' && p[1] == '~')
nm = p + 1, lose = 1;
@@ -1416,9 +1451,9 @@ See also the function `substitute-in-file-name'.")
o[len] = 0;
/* Look up the user name. */
- BLOCK_INPUT;
+ block_input ();
pw = (struct passwd *) getpwnam (o + 1);
- UNBLOCK_INPUT;
+ unblock_input ();
if (!pw)
error ("\"%s\" isn't a registered user", o + 1);
@@ -1494,7 +1529,7 @@ See also the function `substitute-in-file-name'.")
#endif
/* If /~ or // appears, discard everything through first slash. */
-static int
+static bool
file_name_absolute_p (const char *filename)
{
return
@@ -1513,17 +1548,16 @@ search_embedded_absfilename (char *nm, char *endp)
for (p = nm + 1; p < endp; p++)
{
- if ((0
- || IS_DIRECTORY_SEP (p[-1]))
+ if (IS_DIRECTORY_SEP (p[-1])
&& file_name_absolute_p (p)
#if defined (WINDOWSNT) || defined (CYGWIN)
/* // at start of file name is meaningful in Apollo,
WindowsNT and Cygwin systems. */
&& !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm)
#endif /* not (WINDOWSNT || CYGWIN) */
- )
+ )
{
- for (s = p; *s && (!IS_DIRECTORY_SEP (*s)); s++);
+ 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);
@@ -1534,9 +1568,9 @@ search_embedded_absfilename (char *nm, char *endp)
/* If we have ~user and `user' exists, discard
everything up to ~. But if `user' does not exist, leave
~user alone, it might be a literal file name. */
- BLOCK_INPUT;
+ block_input ();
pw = getpwnam (o + 1);
- UNBLOCK_INPUT;
+ unblock_input ();
if (pw)
return p;
}
@@ -1560,12 +1594,10 @@ If `//' appears, everything up to and including the first of
those `/' is discarded. */)
(Lisp_Object filename)
{
- char *nm;
-
- register char *s, *p, *o, *x, *endp;
+ char *nm, *s, *p, *o, *x, *endp;
char *target = NULL;
- int total = 0;
- int substituted = 0;
+ ptrdiff_t total = 0;
+ bool substituted = 0;
bool multibyte;
char *xnm;
Lisp_Object handler;
@@ -1593,8 +1625,18 @@ those `/' is discarded. */)
memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
#ifdef DOS_NT
- dostounix_filename (nm);
- substituted = (strcmp (nm, SDATA (filename)) != 0);
+ {
+ Lisp_Object encoded_filename = ENCODE_FILE (filename);
+ Lisp_Object tem_fn;
+
+ dostounix_filename (SDATA (encoded_filename));
+ tem_fn = DECODE_FILE (encoded_filename);
+ nm = alloca (SBYTES (tem_fn) + 1);
+ memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
+ substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
+ if (substituted)
+ filename = tem_fn;
+ }
#endif
endp = nm + SBYTES (filename);
@@ -1740,7 +1782,7 @@ those `/' is discarded. */)
*x = 0;
/* If /~ or // appears, discard everything through first slash. */
- while ((p = search_embedded_absfilename (xnm, x)))
+ while ((p = search_embedded_absfilename (xnm, x)) != NULL)
/* This time we do not start over because we've already expanded envvars
and replaced $$ with $. Maybe we should start over as well, but we'd
need to quote some $ to $$ first. */
@@ -1780,7 +1822,7 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
}
/* Signal an error if the file ABSNAME already exists.
- If INTERACTIVE is nonzero, ask the user whether to proceed,
+ If INTERACTIVE, ask the user whether to proceed,
and bypass the error if the user says to go ahead.
QUERYSTRING is a name for the action that is being considered
to alter the file.
@@ -1789,13 +1831,14 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
If the file does not exist, STATPTR->st_mode is set to 0.
If STATPTR is null, we don't store into it.
- If QUICK is nonzero, we ask for y or n, not yes or no. */
+ If QUICK, ask for y or n, not yes or no. */
static void
barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring,
- int interactive, struct stat *statptr, int quick)
+ bool interactive, struct stat *statptr,
+ bool quick)
{
- register Lisp_Object tem, encoded_filename;
+ Lisp_Object tem, encoded_filename;
struct stat statbuf;
struct gcpro gcpro1;
@@ -1858,9 +1901,10 @@ A prefix arg makes KEEP-TIME non-nil.
If PRESERVE-UID-GID is non-nil, we try to transfer the
uid and gid of FILE to NEWNAME.
-If PRESERVE-SELINUX-CONTEXT is non-nil and SELinux is enabled
-on the system, we copy the SELinux context of FILE to NEWNAME. */)
- (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, Lisp_Object keep_time, Lisp_Object preserve_uid_gid, Lisp_Object preserve_selinux_context)
+If PRESERVE-EXTENDED-ATTRIBUTES is non-nil, we try to copy additional
+attributes of FILE to NEWNAME, such as its SELinux context and ACL
+entries (depending on how Emacs was built). */)
+ (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, Lisp_Object keep_time, Lisp_Object preserve_uid_gid, Lisp_Object preserve_extended_attributes)
{
int ifd, ofd;
int n;
@@ -1869,11 +1913,13 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
Lisp_Object handler;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
ptrdiff_t count = SPECPDL_INDEX ();
- int input_file_statable_p;
Lisp_Object encoded_file, encoded_newname;
#if HAVE_LIBSELINUX
security_context_t con;
- int fail, conlength = 0;
+ int conlength = 0;
+#endif
+#ifdef HAVE_POSIX_ACL
+ acl_t acl = NULL;
#endif
encoded_file = encoded_newname = Qnil;
@@ -1897,7 +1943,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
if (!NILP (handler))
RETURN_UNGCPRO (call7 (handler, Qcopy_file, file, newname,
ok_if_already_exists, keep_time, preserve_uid_gid,
- preserve_selinux_context));
+ preserve_extended_attributes));
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
@@ -1947,19 +1993,27 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
record_unwind_protect (close_file_unwind, make_number (ifd));
- /* We can only copy regular files and symbolic links. Other files are not
- copyable by us. */
- input_file_statable_p = (fstat (ifd, &st) >= 0);
+ if (fstat (ifd, &st) != 0)
+ report_file_error ("Input file status", Fcons (file, Qnil));
-#if HAVE_LIBSELINUX
- if (!NILP (preserve_selinux_context) && is_selinux_enabled ())
+ if (!NILP (preserve_extended_attributes))
{
- conlength = fgetfilecon (ifd, &con);
- if (conlength == -1)
- report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
- }
+#if HAVE_LIBSELINUX
+ if (is_selinux_enabled ())
+ {
+ conlength = fgetfilecon (ifd, &con);
+ if (conlength == -1)
+ report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
+ }
#endif
+#ifdef HAVE_POSIX_ACL
+ acl = acl_get_fd (ifd);
+ if (acl == NULL && errno != ENOTSUP)
+ report_file_error ("Getting ACL", Fcons (file, Qnil));
+#endif
+ }
+
if (out_st.st_mode != 0
&& st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
{
@@ -1968,16 +2022,12 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
Fcons (file, Fcons (newname, Qnil)));
}
- if (input_file_statable_p)
+ /* We can copy only regular files. */
+ if (!S_ISREG (st.st_mode))
{
- if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
- {
-#if defined (EISDIR)
- /* Get a better looking error message. */
- errno = EISDIR;
-#endif /* EISDIR */
- report_file_error ("Non-regular file", Fcons (file, Qnil));
- }
+ /* Get a better looking error message. */
+ errno = S_ISDIR (st.st_mode) ? EISDIR : EINVAL;
+ report_file_error ("Non-regular file", Fcons (file, Qnil));
}
#ifdef MSDOS
@@ -1988,13 +2038,8 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
S_IREAD | S_IWRITE);
#else /* not MSDOS */
{
- int new_mask = 0666;
- if (input_file_statable_p)
- {
- if (!NILP (preserve_uid_gid))
- new_mask = 0600;
- new_mask &= st.st_mode;
- }
+ mode_t new_mask = !NILP (preserve_uid_gid) ? 0600 : 0666;
+ new_mask &= st.st_mode;
ofd = emacs_open (SSDATA (encoded_newname),
(O_WRONLY | O_TRUNC | O_CREAT
| (NILP (ok_if_already_exists) ? O_EXCL : 0)),
@@ -2016,32 +2061,31 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
#ifndef MSDOS
/* Preserve the original file modes, and if requested, also its
owner and group. */
- if (input_file_statable_p)
- {
- int mode_mask = 07777;
- if (!NILP (preserve_uid_gid))
- {
- /* Attempt to change owner and group. If that doesn't work
- attempt to change just the group, as that is sometimes allowed.
- Adjust the mode mask to eliminate setuid or setgid bits
- that are inappropriate if the owner and group are wrong. */
- if (fchown (ofd, st.st_uid, st.st_gid) != 0)
- {
- mode_mask &= ~06000;
- if (fchown (ofd, -1, st.st_gid) == 0)
- mode_mask |= 02000;
- }
- }
- if (fchmod (ofd, st.st_mode & mode_mask) != 0)
- report_file_error ("Doing chmod", Fcons (newname, Qnil));
- }
+ {
+ mode_t mode_mask = 07777;
+ if (!NILP (preserve_uid_gid))
+ {
+ /* Attempt to change owner and group. If that doesn't work
+ attempt to change just the group, as that is sometimes allowed.
+ Adjust the mode mask to eliminate setuid or setgid bits
+ that are inappropriate if the owner and group are wrong. */
+ if (fchown (ofd, st.st_uid, st.st_gid) != 0)
+ {
+ mode_mask &= ~06000;
+ if (fchown (ofd, -1, st.st_gid) == 0)
+ mode_mask |= 02000;
+ }
+ }
+ if (fchmod (ofd, st.st_mode & mode_mask) != 0)
+ report_file_error ("Doing chmod", Fcons (newname, Qnil));
+ }
#endif /* not MSDOS */
#if HAVE_LIBSELINUX
if (conlength > 0)
{
/* Set the modified context back to the file. */
- fail = fsetfilecon (ofd, con);
+ bool fail = fsetfilecon (ofd, con) != 0;
/* See http://debbugs.gnu.org/11245 for ENOTSUP. */
if (fail && errno != ENOTSUP)
report_file_error ("Doing fsetfilecon", Fcons (newname, Qnil));
@@ -2050,16 +2094,24 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
}
#endif
- if (input_file_statable_p)
+#ifdef HAVE_POSIX_ACL
+ if (acl != NULL)
{
- if (!NILP (keep_time))
- {
- EMACS_TIME atime = get_stat_atime (&st);
- EMACS_TIME mtime = get_stat_mtime (&st);
- if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime))
- xsignal2 (Qfile_date_error,
- build_string ("Cannot set file date"), newname);
- }
+ bool fail = acl_set_fd (ofd, acl) != 0;
+ if (fail && errno != ENOTSUP)
+ report_file_error ("Setting ACL", Fcons (newname, Qnil));
+
+ acl_free (acl);
+ }
+#endif
+
+ if (!NILP (keep_time))
+ {
+ EMACS_TIME atime = get_stat_atime (&st);
+ EMACS_TIME mtime = get_stat_mtime (&st);
+ if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime))
+ xsignal2 (Qfile_date_error,
+ build_string ("Cannot set file date"), newname);
}
if (emacs_close (ofd) < 0)
@@ -2068,15 +2120,12 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
emacs_close (ifd);
#ifdef MSDOS
- if (input_file_statable_p)
- {
- /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
- and if it can't, it tells so. Otherwise, under MSDOS we usually
- get only the READ bit, which will make the copied file read-only,
- so it's better not to chmod at all. */
- if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
- chmod (SDATA (encoded_newname), st.st_mode & 07777);
- }
+ /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
+ and if it can't, it tells so. Otherwise, under MSDOS we usually
+ get only the READ bit, which will make the copied file read-only,
+ so it's better not to chmod at all. */
+ if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
+ chmod (SDATA (encoded_newname), st.st_mode & 07777);
#endif /* MSDOS */
#endif /* not WINDOWSNT */
@@ -2173,7 +2222,7 @@ With a prefix argument, TRASH is nil. */)
encoded_file = ENCODE_FILE (filename);
- if (0 > unlink (SSDATA (encoded_file)))
+ if (unlink (SSDATA (encoded_file)) < 0)
report_file_error ("Removing old name", list1 (filename));
return Qnil;
}
@@ -2184,10 +2233,10 @@ internal_delete_file_1 (Lisp_Object ignore)
return Qt;
}
-/* Delete file FILENAME, returning 1 if successful and 0 if failed.
+/* Delete file FILENAME, returning true if successful.
This ignores `delete-by-moving-to-trash'. */
-int
+bool
internal_delete_file (Lisp_Object filename)
{
Lisp_Object tem;
@@ -2225,8 +2274,8 @@ This is what happens in interactive use with M-x. */)
#endif
)
{
- Lisp_Object fname = NILP (Ffile_directory_p (file))
- ? file : Fdirectory_file_name (file);
+ Lisp_Object fname = (NILP (Ffile_directory_p (file))
+ ? file : Fdirectory_file_name (file));
newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname);
}
else
@@ -2254,7 +2303,7 @@ This is what happens in interactive use with M-x. */)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (newname, "rename to it",
INTEGERP (ok_if_already_exists), 0, 0);
- if (0 > rename (SSDATA (encoded_file), SSDATA (encoded_newname)))
+ if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
{
if (errno == EXDEV)
{
@@ -2335,7 +2384,7 @@ This is what happens in interactive use with M-x. */)
INTEGERP (ok_if_already_exists), 0, 0);
unlink (SSDATA (newname));
- if (0 > link (SSDATA (encoded_file), SSDATA (encoded_newname)))
+ if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
report_file_error ("Adding new name", list2 (file, newname));
UNGCPRO;
@@ -2392,15 +2441,14 @@ This happens for interactive use with M-x. */)
|| INTEGERP (ok_if_already_exists))
barf_or_query_if_file_exists (linkname, "make it a link",
INTEGERP (ok_if_already_exists), 0, 0);
- if (0 > symlink (SSDATA (encoded_filename),
- SSDATA (encoded_linkname)))
+ if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0)
{
/* If we didn't complain already, silently delete existing file. */
if (errno == EEXIST)
{
unlink (SSDATA (encoded_linkname));
- if (0 <= symlink (SSDATA (encoded_filename),
- SSDATA (encoded_linkname)))
+ if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname))
+ >= 0)
{
UNGCPRO;
return Qnil;
@@ -2430,61 +2478,52 @@ On Unix, this is a name starting with a `/' or a `~'. */)
return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil;
}
-/* Return nonzero if file FILENAME exists and can be executed. */
+/* Return true if FILENAME exists. */
+bool
+check_existing (const char *filename)
+{
+ return faccessat (AT_FDCWD, filename, F_OK, AT_EACCESS) == 0;
+}
+
+/* Return true if file FILENAME exists and can be executed. */
-static int
+static bool
check_executable (char *filename)
{
-#ifdef DOS_NT
- struct stat st;
- if (stat (filename, &st) < 0)
- return 0;
- return ((st.st_mode & S_IEXEC) != 0);
-#else /* not DOS_NT */
-#ifdef HAVE_EUIDACCESS
- return (euidaccess (filename, 1) >= 0);
-#else
- /* Access isn't quite right because it uses the real uid
- and we really want to test with the effective uid.
- But Unix doesn't give us a right way to do it. */
- return (access (filename, 1) >= 0);
-#endif
-#endif /* not DOS_NT */
+ return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0;
}
-/* Return nonzero if file FILENAME exists and can be written. */
+/* Return true if file FILENAME exists and can be accessed
+ according to AMODE, which should include W_OK.
+ On failure, return false and set errno. */
-static int
-check_writable (const char *filename)
+static bool
+check_writable (const char *filename, int amode)
{
#ifdef MSDOS
+ /* FIXME: an faccessat implementation should be added to the
+ DOS/Windows ports and this #ifdef branch should be removed. */
struct stat st;
if (stat (filename, &st) < 0)
return 0;
+ errno = EPERM;
return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
#else /* not MSDOS */
-#ifdef HAVE_EUIDACCESS
- int res = (euidaccess (filename, 2) >= 0);
+ bool res = faccessat (AT_FDCWD, filename, amode, AT_EACCESS) == 0;
#ifdef CYGWIN
- /* euidaccess may have returned failure because Cygwin couldn't
+ /* faccessat may have returned failure because Cygwin couldn't
determine the file's UID or GID; if so, we return success. */
if (!res)
{
+ int faccessat_errno = errno;
struct stat st;
if (stat (filename, &st) < 0)
return 0;
res = (st.st_uid == -1 || st.st_gid == -1);
+ errno = faccessat_errno;
}
#endif /* CYGWIN */
return res;
-#else /* not HAVE_EUIDACCESS */
- /* Access isn't quite right because it uses the real uid
- and we really want to test with the effective uid.
- But Unix doesn't give us a right way to do it.
- Opening with O_WRONLY could work for an ordinary file,
- but would lose for directories. */
- return (access (filename, 2) >= 0);
-#endif /* not HAVE_EUIDACCESS */
#endif /* not MSDOS */
}
@@ -2497,7 +2536,6 @@ Use `file-symlink-p' to test for such links. */)
{
Lisp_Object absname;
Lisp_Object handler;
- struct stat statbuf;
CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
@@ -2510,7 +2548,7 @@ Use `file-symlink-p' to test for such links. */)
absname = ENCODE_FILE (absname);
- return (stat (SSDATA (absname), &statbuf) >= 0) ? Qt : Qnil;
+ return (check_existing (SSDATA (absname))) ? Qt : Qnil;
}
DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2542,9 +2580,6 @@ See also `file-exists-p' and `file-attributes'. */)
{
Lisp_Object absname;
Lisp_Object handler;
- int desc;
- int flags;
- struct stat statbuf;
CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
@@ -2556,42 +2591,16 @@ See also `file-exists-p' and `file-attributes'. */)
return call2 (handler, Qfile_readable_p, absname);
absname = ENCODE_FILE (absname);
-
-#if defined (DOS_NT) || defined (macintosh)
- /* Under MS-DOS, Windows, and Macintosh, open does not work for
- directories. */
- if (access (SDATA (absname), 0) == 0)
- return Qt;
- return Qnil;
-#else /* not DOS_NT and not macintosh */
- flags = O_RDONLY;
-#ifdef O_NONBLOCK
- /* Opening a fifo without O_NONBLOCK can wait.
- We don't want to wait. But we don't want to mess wth O_NONBLOCK
- except in the case of a fifo, on a system which handles it. */
- desc = stat (SSDATA (absname), &statbuf);
- if (desc < 0)
- return Qnil;
- if (S_ISFIFO (statbuf.st_mode))
- flags |= O_NONBLOCK;
-#endif
- desc = emacs_open (SSDATA (absname), flags, 0);
- if (desc < 0)
- return Qnil;
- emacs_close (desc);
- return Qt;
-#endif /* not DOS_NT and not macintosh */
+ return (faccessat (AT_FDCWD, SSDATA (absname), R_OK, AT_EACCESS) == 0
+ ? Qt : Qnil);
}
-/* Having this before file-symlink-p mysteriously caused it to be forgotten
- on the RT/PC. */
DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
doc: /* Return t if file FILENAME can be written or created by you. */)
(Lisp_Object filename)
{
Lisp_Object absname, dir, encoded;
Lisp_Object handler;
- struct stat statbuf;
CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
@@ -2603,14 +2612,15 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
return call2 (handler, Qfile_writable_p, absname);
encoded = ENCODE_FILE (absname);
- if (stat (SSDATA (encoded), &statbuf) >= 0)
- return (check_writable (SSDATA (encoded))
- ? Qt : Qnil);
+ if (check_writable (SSDATA (encoded), W_OK))
+ return Qt;
+ if (errno != ENOENT)
+ return Qnil;
dir = Ffile_name_directory (absname);
+ eassert (!NILP (dir));
#ifdef MSDOS
- if (!NILP (dir))
- dir = Fdirectory_file_name (dir);
+ dir = Fdirectory_file_name (dir);
#endif /* MSDOS */
dir = ENCODE_FILE (dir);
@@ -2618,12 +2628,9 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
/* The read-only attribute of the parent directory doesn't affect
whether a file or directory can be created within it. Some day we
should check ACLs though, which do affect this. */
- if (stat (SDATA (dir), &statbuf) < 0)
- return Qnil;
- return S_ISDIR (statbuf.st_mode) ? Qt : Qnil;
+ return file_directory_p (SDATA (dir)) ? Qt : Qnil;
#else
- return (check_writable (!NILP (dir) ? SSDATA (dir) : "")
- ? Qt : Qnil);
+ return check_writable (SSDATA (dir), W_OK | X_OK) ? Qt : Qnil;
#endif
}
@@ -2701,8 +2708,7 @@ Symbolic links to directories count as directories.
See `file-symlink-p' to distinguish symlinks. */)
(Lisp_Object filename)
{
- register Lisp_Object absname;
- struct stat st;
+ Lisp_Object absname;
Lisp_Object handler;
absname = expand_and_dir_to_file (filename, BVAR (current_buffer, directory));
@@ -2715,9 +2721,20 @@ See `file-symlink-p' to distinguish symlinks. */)
absname = ENCODE_FILE (absname);
- if (stat (SSDATA (absname), &st) < 0)
- return Qnil;
- return S_ISDIR (st.st_mode) ? Qt : Qnil;
+ return file_directory_p (SSDATA (absname)) ? Qt : Qnil;
+}
+
+/* Return true if FILE is a directory or a symlink to a directory. */
+bool
+file_directory_p (char const *file)
+{
+#ifdef WINDOWSNT
+ /* This is cheaper than 'stat'. */
+ return faccessat (AT_FDCWD, file, D_OK, AT_EACCESS) == 0;
+#else
+ struct stat st;
+ return stat (file, &st) == 0 && S_ISDIR (st.st_mode);
+#endif
}
DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p,
@@ -2731,21 +2748,65 @@ if the directory so specified exists and really is a readable and
searchable directory. */)
(Lisp_Object filename)
{
+ Lisp_Object absname;
Lisp_Object handler;
- int tem;
- struct gcpro gcpro1;
+
+ CHECK_STRING (filename);
+ absname = Fexpand_file_name (filename, Qnil);
/* If the file name has special constructs in it,
call the corresponding file handler. */
- handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
+ handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p);
if (!NILP (handler))
- return call2 (handler, Qfile_accessible_directory_p, filename);
+ return call2 (handler, Qfile_accessible_directory_p, absname);
- GCPRO1 (filename);
- tem = (NILP (Ffile_directory_p (filename))
- || NILP (Ffile_executable_p (filename)));
- UNGCPRO;
- return tem ? Qnil : Qt;
+ absname = ENCODE_FILE (absname);
+ return file_accessible_directory_p (SSDATA (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)
+{
+#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);
+#else
+ /* On POSIXish platforms, use just one system call; this avoids a
+ race and is typically faster. */
+ ptrdiff_t len = strlen (file);
+ char const *dir;
+ bool ok;
+ int saved_errno;
+ USE_SAFE_ALLOCA;
+
+ /* Normally a file "FOO" is an accessible directory if "FOO/." exists.
+ There are three exceptions: "", "/", and "//". Leave "" alone,
+ as it's invalid. Append only "." to the other two exceptions as
+ "/" and "//" are distinct on some platforms, whereas "/", "///",
+ "////", etc. are all equivalent. */
+ if (! len)
+ dir = file;
+ 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] == '/'));
+ dir = buf;
+ }
+
+ ok = check_existing (dir);
+ saved_errno = errno;
+ SAFE_FREE ();
+ errno = saved_errno;
+ return ok;
+#endif
}
DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
@@ -2840,9 +2901,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
if (context_range_get (context))
values[3] = build_string (context_range_get (context));
context_free (context);
+ freecon (con);
}
- if (con)
- freecon (con);
}
#endif
@@ -2868,7 +2928,8 @@ compiled with SELinux support. */)
Lisp_Object type = CAR_SAFE (CDR_SAFE (CDR_SAFE (context)));
Lisp_Object range = CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (context))));
security_context_t con;
- int fail, conlength;
+ bool fail;
+ int conlength;
context_t parsed_con;
#endif
@@ -2912,19 +2973,118 @@ compiled with SELinux support. */)
}
/* Set the modified context back to the file. */
- fail = lsetfilecon (SSDATA (encoded_absname),
- context_str (parsed_con));
+ fail = (lsetfilecon (SSDATA (encoded_absname),
+ context_str (parsed_con))
+ != 0);
/* See http://debbugs.gnu.org/11245 for ENOTSUP. */
if (fail && errno != ENOTSUP)
report_file_error ("Doing lsetfilecon", Fcons (absname, Qnil));
context_free (parsed_con);
+ freecon (con);
}
else
report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
+ }
+#endif
- if (con)
- freecon (con);
+ return Qnil;
+}
+
+DEFUN ("file-acl", Ffile_acl, Sfile_acl, 1, 1, 0,
+ doc: /* Return ACL entries of file named FILENAME, as a string.
+Return nil if file does not exist or is not accessible, or if Emacs
+was unable to determine the ACL entries. The latter can happen for
+local files if Emacs was not compiled with ACL support, or for remote
+files if the file handler returns nil for the file's ACL entries. */)
+ (Lisp_Object filename)
+{
+ Lisp_Object absname;
+ Lisp_Object handler;
+#ifdef HAVE_POSIX_ACL
+ acl_t acl;
+ Lisp_Object acl_string;
+ char *str;
+#endif
+
+ absname = expand_and_dir_to_file (filename,
+ BVAR (current_buffer, directory));
+
+ /* If the file name has special constructs in it,
+ call the corresponding file handler. */
+ handler = Ffind_file_name_handler (absname, Qfile_acl);
+ if (!NILP (handler))
+ return call2 (handler, Qfile_acl, absname);
+
+#ifdef HAVE_POSIX_ACL
+ absname = ENCODE_FILE (absname);
+
+ acl = acl_get_file (SSDATA (absname), ACL_TYPE_ACCESS);
+ if (acl == NULL)
+ return Qnil;
+
+ str = acl_to_text (acl, NULL);
+ if (str == NULL)
+ {
+ acl_free (acl);
+ return Qnil;
+ }
+
+ acl_string = build_string (str);
+ acl_free (str);
+ acl_free (acl);
+
+ return acl_string;
+#endif
+
+ return Qnil;
+}
+
+DEFUN ("set-file-acl", Fset_file_acl, Sset_file_acl,
+ 2, 2, 0,
+ doc: /* Set ACL of file named FILENAME to ACL-STRING.
+ACL-STRING should contain the textual representation of the ACL
+entries in a format suitable for the platform.
+
+Setting ACL for local files requires Emacs to be built with ACL
+support. */)
+ (Lisp_Object filename, Lisp_Object acl_string)
+{
+ Lisp_Object absname;
+ Lisp_Object handler;
+#ifdef HAVE_POSIX_ACL
+ Lisp_Object encoded_absname;
+ acl_t acl;
+ bool fail;
+#endif
+
+ absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
+
+ /* If the file name has special constructs in it,
+ call the corresponding file handler. */
+ handler = Ffind_file_name_handler (absname, Qset_file_acl);
+ if (!NILP (handler))
+ return call3 (handler, Qset_file_acl, absname, acl_string);
+
+#ifdef HAVE_POSIX_ACL
+ if (STRINGP (acl_string))
+ {
+ acl = acl_from_text (SSDATA (acl_string));
+ if (acl == NULL)
+ {
+ report_file_error ("Converting ACL", Fcons (absname, Qnil));
+ return Qnil;
+ }
+
+ encoded_absname = ENCODE_FILE (absname);
+
+ fail = (acl_set_file (SSDATA (encoded_absname), ACL_TYPE_ACCESS,
+ acl)
+ != 0);
+ if (fail && errno != ENOTSUP)
+ report_file_error ("Setting ACL", Fcons (absname, Qnil));
+
+ acl_free (acl);
}
#endif
@@ -3004,13 +3164,13 @@ DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
The value is an integer. */)
(void)
{
- int realmask;
+ mode_t realmask;
Lisp_Object value;
- BLOCK_INPUT;
+ block_input ();
realmask = umask (0);
umask (realmask);
- UNBLOCK_INPUT;
+ unblock_input ();
XSETINT (value, (~ realmask) & 0777);
return value;
@@ -3042,11 +3202,9 @@ Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of
{
if (set_file_times (-1, SSDATA (encoded_absname), t, t))
{
-#ifdef DOS_NT
- struct stat st;
-
+#ifdef MSDOS
/* Setting times on a directory always fails. */
- if (stat (SSDATA (encoded_absname), &st) == 0 && S_ISDIR (st.st_mode))
+ if (file_directory_p (SSDATA (encoded_absname)))
return Qnil;
#endif
report_file_error ("Setting file times", Fcons (absname, Qnil));
@@ -3200,7 +3358,7 @@ emacs_lseek (int fd, EMACS_INT offset, int whence)
{
/* Use "&" rather than "&&" to suppress a bogus GCC warning; see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>. */
- if (! ((TYPE_MINIMUM (off_t) <= offset) & (offset <= TYPE_MAXIMUM (off_t))))
+ if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t))))
{
errno = EINVAL;
return -1;
@@ -3246,29 +3404,29 @@ variable `last-coding-system-used' to the coding system actually used. */)
struct stat st;
int file_status;
EMACS_TIME mtime;
- register int fd;
+ int fd;
ptrdiff_t inserted = 0;
- int nochange = 0;
- register ptrdiff_t how_much;
+ bool nochange = 0;
+ ptrdiff_t how_much;
off_t beg_offset, end_offset;
- register int unprocessed;
+ int unprocessed;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
Lisp_Object handler, val, insval, orig_filename, old_undo;
Lisp_Object p;
ptrdiff_t total = 0;
- int not_regular = 0;
+ bool not_regular = 0;
int save_errno = 0;
char read_buf[READ_BUF_SIZE];
struct coding_system coding;
char buffer[1 << 14];
- int replace_handled = 0;
- int set_coding_system = 0;
+ bool replace_handled = 0;
+ bool set_coding_system = 0;
Lisp_Object coding_system;
- int read_quit = 0;
+ bool read_quit = 0;
Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
- int we_locked_file = 0;
- int deferred_remove_unwind_protect = 0;
+ bool we_locked_file = 0;
+ bool deferred_remove_unwind_protect = 0;
if (current_buffer->base_buffer && ! NILP (visit))
error ("Cannot do file visiting in an indirect buffer");
@@ -3373,7 +3531,7 @@ variable `last-coding-system-used' to the coding system actually used. */)
if (!NILP (beg))
{
- if (! (RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))))
+ if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t)))
wrong_type_argument (intern ("file-offset"), beg);
beg_offset = XFASTINT (beg);
}
@@ -3382,7 +3540,7 @@ variable `last-coding-system-used' to the coding system actually used. */)
if (!NILP (end))
{
- if (! (RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))))
+ if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t)))
wrong_type_argument (intern ("file-offset"), end);
end_offset = XFASTINT (end);
}
@@ -3418,8 +3576,8 @@ variable `last-coding-system-used' to the coding system actually used. */)
if (beg_offset < likely_end)
{
- ptrdiff_t buf_bytes =
- Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE : 0);
+ ptrdiff_t buf_bytes
+ = Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE : 0);
ptrdiff_t buf_growth_max = BUF_BYTES_MAX - buf_bytes;
off_t likely_growth = likely_end - beg_offset;
if (buf_growth_max < likely_growth)
@@ -3462,12 +3620,14 @@ variable `last-coding-system-used' to the coding system actually used. */)
else
{
nread = emacs_read (fd, read_buf, 1024);
- if (nread >= 0)
+ if (nread == 1024)
{
- if (lseek (fd, st.st_size - (1024 * 3), SEEK_SET) < 0)
+ int ntail;
+ if (lseek (fd, - (1024 * 3), SEEK_END) < 0)
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
- nread += emacs_read (fd, read_buf + nread, 1024 * 3);
+ ntail = emacs_read (fd, read_buf + nread, 1024 * 3);
+ nread = ntail < 0 ? ntail : nread + ntail;
}
}
@@ -3569,9 +3729,9 @@ variable `last-coding-system-used' to the coding system actually used. */)
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, we set this variable to 1 to
+ conversion. If that happens, set this variable to
give up on handling REPLACE in the optimized way. */
- int giveup_match_end = 0;
+ bool giveup_match_end = 0;
if (beg_offset != 0)
{
@@ -4427,8 +4587,8 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
If it is not set locally, we anyway have to convert EOL
format if the default value of `buffer-file-coding-system'
tells that it is not Unix-like (LF only) format. */
- int using_default_coding = 0;
- int force_raw_text = 0;
+ bool using_default_coding = 0;
+ bool force_raw_text = 0;
val = BVAR (current_buffer, buffer_file_coding_system);
if (NILP (val)
@@ -4537,19 +4697,20 @@ This calls `write-region-annotate-functions' at the start, and
`write-region-post-annotation-function' at the end. */)
(Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
{
- register int desc;
- int failure;
+ int desc;
+ bool ok;
int save_errno = 0;
const char *fn;
struct stat st;
+ EMACS_TIME modtime;
ptrdiff_t count = SPECPDL_INDEX ();
int count1;
Lisp_Object handler;
Lisp_Object visit_file;
Lisp_Object annotations;
Lisp_Object encoded_filename;
- int visiting = (EQ (visit, Qt) || STRINGP (visit));
- int quietly = !NILP (visit);
+ bool visiting = (EQ (visit, Qt) || STRINGP (visit));
+ bool quietly = !NILP (visit);
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
struct buffer *given_buffer;
struct coding_system coding;
@@ -4713,37 +4874,27 @@ This calls `write-region-annotate-functions' at the start, and
UNGCPRO;
- failure = 0;
immediate_quit = 1;
if (STRINGP (start))
- {
- failure = 0 > a_write (desc, start, 0, SCHARS (start),
- &annotations, &coding);
- save_errno = errno;
- }
+ ok = a_write (desc, start, 0, SCHARS (start), &annotations, &coding);
else if (XINT (start) != XINT (end))
- {
- failure = 0 > a_write (desc, Qnil,
- XINT (start), XINT (end) - XINT (start),
- &annotations, &coding);
- save_errno = errno;
- }
+ ok = a_write (desc, Qnil, XINT (start), XINT (end) - XINT (start),
+ &annotations, &coding);
else
{
- /* If file was empty, still need to write the annotations */
+ /* If file was empty, still need to write the annotations. */
coding.mode |= CODING_MODE_LAST_BLOCK;
- failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
- save_errno = errno;
+ ok = a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
}
+ save_errno = errno;
- if (CODING_REQUIRE_FLUSHING (&coding)
- && !(coding.mode & CODING_MODE_LAST_BLOCK)
- && ! failure)
+ if (ok && CODING_REQUIRE_FLUSHING (&coding)
+ && !(coding.mode & CODING_MODE_LAST_BLOCK))
{
/* We have to flush out a data. */
coding.mode |= CODING_MODE_LAST_BLOCK;
- failure = 0 > e_write (desc, Qnil, 1, 1, &coding);
+ ok = e_write (desc, Qnil, 1, 1, &coding);
save_errno = errno;
}
@@ -4760,15 +4911,22 @@ This calls `write-region-annotate-functions' at the start, and
ignore EINVAL which happens when fsync is not supported on this
file. */
if (errno != EINTR && errno != EINVAL)
- failure = 1, save_errno = errno;
+ ok = 0, save_errno = errno;
}
#endif
+ modtime = invalid_emacs_time ();
+ if (visiting)
+ {
+ if (fstat (desc, &st) == 0)
+ modtime = get_stat_mtime (&st);
+ else
+ ok = 0, save_errno = errno;
+ }
+
/* NFS can report a write failure now. */
if (emacs_close (desc) < 0)
- failure = 1, save_errno = errno;
-
- stat (fn, &st);
+ ok = 0, save_errno = errno;
/* Discard the unwind protect for close_file_unwind. */
specpdl_ptr = specpdl + count1;
@@ -4797,13 +4955,13 @@ This calls `write-region-annotate-functions' at the start, and
/* Do this before reporting IO error
to avoid a "file has changed on disk" warning on
next attempt to save. */
- if (visiting)
+ if (EMACS_TIME_VALID_P (modtime))
{
- current_buffer->modtime = get_stat_mtime (&st);
+ current_buffer->modtime = modtime;
current_buffer->modtime_size = st.st_size;
}
- if (failure)
+ if (! ok)
error ("IO error writing %s: %s", SDATA (filename),
emacs_strerror (save_errno));
@@ -4859,7 +5017,8 @@ build_annotations (Lisp_Object start, Lisp_Object end)
Lisp_Object p, res;
struct gcpro gcpro1, gcpro2;
Lisp_Object original_buffer;
- int i, used_global = 0;
+ int i;
+ bool used_global = 0;
XSETBUFFER (original_buffer, current_buffer);
@@ -4939,11 +5098,11 @@ build_annotations (Lisp_Object start, Lisp_Object end)
We modify *ANNOT by discarding elements as we use them up.
- The return value is negative in case of system call failure. */
+ Return true if successful. */
-static int
+static bool
a_write (int desc, Lisp_Object string, ptrdiff_t pos,
- register ptrdiff_t nchars, Lisp_Object *annot,
+ ptrdiff_t nchars, Lisp_Object *annot,
struct coding_system *coding)
{
Lisp_Object tem;
@@ -4965,29 +5124,29 @@ a_write (int desc, Lisp_Object string, ptrdiff_t pos,
/* Output buffer text up to the next annotation's position. */
if (nextpos > pos)
{
- if (0 > e_write (desc, string, pos, nextpos, coding))
- return -1;
+ if (!e_write (desc, string, pos, nextpos, coding))
+ return 0;
pos = nextpos;
}
/* Output the annotation. */
tem = Fcdr (Fcar (*annot));
if (STRINGP (tem))
{
- if (0 > e_write (desc, tem, 0, SCHARS (tem), coding))
- return -1;
+ if (!e_write (desc, tem, 0, SCHARS (tem), coding))
+ return 0;
}
*annot = Fcdr (*annot);
}
- return 0;
+ return 1;
}
/* Write text in the range START and END into descriptor DESC,
encoding them with coding system CODING. If STRING is nil, START
and END are character positions of the current buffer, else they
- are indexes to the string STRING. */
+ are indexes to the string STRING. Return true if successful. */
-static int
+static bool
e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
struct coding_system *coding)
{
@@ -5048,20 +5207,20 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
if (coding->produced > 0)
{
- coding->produced -=
- emacs_write (desc,
- STRINGP (coding->dst_object)
- ? SSDATA (coding->dst_object)
- : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
- coding->produced);
+ coding->produced
+ -= emacs_write (desc,
+ STRINGP (coding->dst_object)
+ ? SSDATA (coding->dst_object)
+ : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
+ coding->produced);
if (coding->produced)
- return -1;
+ return 0;
}
start += coding->consumed_char;
}
- return 0;
+ return 1;
}
DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
@@ -5076,7 +5235,7 @@ See Info node `(elisp)Modification Time' for more details. */)
struct stat st;
Lisp_Object handler;
Lisp_Object filename;
- EMACS_TIME mtime, diff;
+ EMACS_TIME mtime;
if (NILP (buf))
b = current_buffer;
@@ -5101,15 +5260,9 @@ See Info node `(elisp)Modification Time' for more details. */)
mtime = (stat (SSDATA (filename), &st) == 0
? get_stat_mtime (&st)
: time_error_value (errno));
- if ((EMACS_TIME_EQ (mtime, b->modtime)
- /* If both exist, accept them if they are off by one second. */
- || (EMACS_TIME_VALID_P (mtime) && EMACS_TIME_VALID_P (b->modtime)
- && ((diff = (EMACS_TIME_LT (mtime, b->modtime)
- ? sub_emacs_time (b->modtime, mtime)
- : sub_emacs_time (mtime, b->modtime))),
- EMACS_TIME_LE (diff, make_emacs_time (1, 0)))))
- && (st.st_size == b->modtime_size
- || b->modtime_size < 0))
+ if (EMACS_TIME_EQ (mtime, b->modtime)
+ && (b->modtime_size < 0
+ || st.st_size == b->modtime_size))
return Qt;
return Qnil;
}
@@ -5136,7 +5289,15 @@ See Info node `(elisp)Modification Time' for more details. */)
(void)
{
if (EMACS_NSECS (current_buffer->modtime) < 0)
- return make_number (0);
+ {
+ if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
+ {
+ /* make_lisp_time won't work here if time_t is unsigned. */
+ return list4 (make_number (-1), make_number (65535),
+ make_number (0), make_number (0));
+ }
+ return make_number (0);
+ }
return make_lisp_time (current_buffer->modtime);
}
@@ -5232,8 +5393,8 @@ auto_save_1 (void)
if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0)
/* But make sure we can overwrite it later! */
auto_save_mode_bits = (st.st_mode | 0600) & 0777;
- else if ((modes = Ffile_modes (BVAR (current_buffer, filename)),
- INTEGERP (modes)))
+ else if (modes = Ffile_modes (BVAR (current_buffer, filename)),
+ INTEGERP (modes))
/* Remote files don't cooperate with stat. */
auto_save_mode_bits = (XINT (modes) | 0600) & 0777;
}
@@ -5252,9 +5413,9 @@ do_auto_save_unwind (Lisp_Object arg) /* used as unwind-protect function */
auto_saving = 0;
if (stream != NULL)
{
- BLOCK_INPUT;
+ block_input ();
fclose (stream);
- UNBLOCK_INPUT;
+ unblock_input ();
}
return Qnil;
}
@@ -5300,12 +5461,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
{
struct buffer *old = current_buffer, *b;
Lisp_Object tail, buf, hook;
- int auto_saved = 0;
+ bool auto_saved = 0;
int do_handled_files;
Lisp_Object oquit;
FILE *stream = NULL;
ptrdiff_t count = SPECPDL_INDEX ();
- int orig_minibuffer_auto_raise = minibuffer_auto_raise;
+ bool orig_minibuffer_auto_raise = minibuffer_auto_raise;
bool old_message_p = 0;
struct gcpro gcpro1, gcpro2;
@@ -5385,7 +5546,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
if (STRINGP (BVAR (b, auto_save_file_name))
&& stream != NULL && do_handled_files == 0)
{
- BLOCK_INPUT;
+ block_input ();
if (!NILP (BVAR (b, filename)))
{
fwrite (SDATA (BVAR (b, filename)), 1,
@@ -5395,7 +5556,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
fwrite (SDATA (BVAR (b, auto_save_file_name)), 1,
SBYTES (BVAR (b, auto_save_file_name)), stream);
putc ('\n', stream);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (!NILP (current_only)
@@ -5452,7 +5613,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
if (!auto_saved && NILP (no_message))
message1 ("Auto-saving...");
internal_condition_case (auto_save_1, Qt, auto_save_error);
- auto_saved++;
+ auto_saved = 1;
BUF_AUTOSAVE_MODIFF (b) = BUF_MODIFF (b);
XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
set_buffer_internal (old);
@@ -5537,7 +5698,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)
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) \
+ || defined (HAVE_NS)
if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
&& use_dialog_box
&& use_file_dialog
@@ -5598,6 +5760,8 @@ syms_of_fileio (void)
DEFSYM (Qset_file_times, "set-file-times");
DEFSYM (Qfile_selinux_context, "file-selinux-context");
DEFSYM (Qset_file_selinux_context, "set-file-selinux-context");
+ DEFSYM (Qfile_acl, "file-acl");
+ DEFSYM (Qset_file_acl, "set-file-acl");
DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p");
DEFSYM (Qinsert_file_contents, "insert-file-contents");
DEFSYM (Qwrite_region, "write-region");
@@ -5750,7 +5914,7 @@ This applies only to the operation `inhibit-file-name-operation'. */);
DEFVAR_LISP ("auto-save-list-file-name", Vauto_save_list_file_name,
doc: /* File name in which we write a list of all auto save file names.
This variable is initialized automatically from `auto-save-list-file-prefix'
-shortly after Emacs reads your `.emacs' file, if you have not yet given it
+shortly after Emacs reads your init file, if you have not yet given it
a non-nil value. */);
Vauto_save_list_file_name = Qnil;
@@ -5817,6 +5981,8 @@ This includes interactive calls to `delete-file' and
defsubr (&Sset_file_modes);
defsubr (&Sset_file_times);
defsubr (&Sfile_selinux_context);
+ defsubr (&Sfile_acl);
+ defsubr (&Sset_file_acl);
defsubr (&Sset_file_selinux_context);
defsubr (&Sset_default_file_modes);
defsubr (&Sdefault_file_modes);
diff --git a/src/filelock.c b/src/filelock.c
index d21d8e7ba02..17f3f253249 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -23,7 +23,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -100,10 +99,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Return the time of the last system boot. */
static time_t boot_time;
-static int boot_time_initialized;
+static bool boot_time_initialized;
#ifdef BOOT_TIME
-static void get_boot_time_1 (const char *, int);
+static void get_boot_time_1 (const char *, bool);
#endif
static time_t
@@ -170,7 +169,7 @@ get_boot_time (void)
{
char cmd_string[sizeof WTMP_FILE ".19.gz"];
Lisp_Object tempname, filename;
- int delete_flag = 0;
+ bool delete_flag = 0;
filename = Qnil;
@@ -225,13 +224,13 @@ get_boot_time (void)
If FILENAME is zero, use the same file as before;
if no FILENAME has ever been specified, this is the utmp file.
- Use the newest reboot record if NEWEST is nonzero,
+ Use the newest reboot record if NEWEST,
the first reboot record otherwise.
Ignore all reboot records on or before BOOT_TIME.
Success is indicated by setting BOOT_TIME to a larger value. */
void
-get_boot_time_1 (const char *filename, int newest)
+get_boot_time_1 (const char *filename, bool newest)
{
struct utmp ut, *utp;
int desc;
@@ -331,11 +330,11 @@ fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn)
}
/* Lock the lock file named LFNAME.
- If FORCE is nonzero, we do so even if it is already locked.
- Return 1 if successful, 0 if not. */
+ If FORCE, do so even if it is already locked.
+ Return true if successful. */
-static int
-lock_file_1 (char *lfname, int force)
+static bool
+lock_file_1 (char *lfname, bool force)
{
int err;
int symlink_errno;
@@ -370,9 +369,9 @@ lock_file_1 (char *lfname, int force)
return err == 0;
}
-/* Return 1 if times A and B are no more than one second apart. */
+/* Return true if times A and B are no more than one second apart. */
-static int
+static bool
within_one_second (time_t a, time_t b)
{
return (a - b >= -1 && a - b <= 1);
@@ -491,7 +490,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
static int
lock_if_free (lock_info_type *clasher, register char *lfname)
{
- while (lock_file_1 (lfname, 0) == 0)
+ while (! lock_file_1 (lfname, 0))
{
int locker;
diff --git a/src/floatfns.c b/src/floatfns.c
index cad071f1e15..645a5957609 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -22,171 +22,23 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-/* ANSI C requires only these float functions:
- acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
- frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh.
-
- Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh.
- Define HAVE_CBRT if you have cbrt.
- Define HAVE_RINT if you have a working rint.
- If you don't define these, then the appropriate routines will be simulated.
-
- Define HAVE_MATHERR if on a system supporting the SysV matherr callback.
- (This should happen automatically.)
-
- Define FLOAT_CHECK_ERRNO if the float library routines set errno.
- This has no effect if HAVE_MATHERR is defined.
-
- Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL.
- (What systems actually do this? Please let us know.)
-
- Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
- either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and
- range checking will happen before calling the float routines. This has
- no effect if HAVE_MATHERR is defined (since matherr will be called when
- a domain error occurs.)
+/* C89 requires only the following math.h functions, and Emacs omits
+ the starred functions since we haven't found a use for them:
+ acos, asin, atan, atan2, ceil, cos, *cosh, exp, fabs, floor, fmod,
+ frexp, ldexp, log, log10, *modf, pow, sin, *sinh, sqrt, tan, *tanh.
*/
#include <config.h>
-#include <signal.h>
-#include <setjmp.h>
+
#include "lisp.h"
-#include "syssignal.h"
-
-#include <float.h>
-/* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
-#ifndef IEEE_FLOATING_POINT
-#if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
-#define IEEE_FLOATING_POINT 1
-#else
-#define IEEE_FLOATING_POINT 0
-#endif
-#endif
#include <math.h>
-/* This declaration is omitted on some systems, like Ultrix. */
-#if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
-extern double logb (double);
-#endif /* not HPUX and HAVE_LOGB and no logb macro */
-
-#if defined (DOMAIN) && defined (SING) && defined (OVERFLOW)
- /* If those are defined, then this is probably a `matherr' machine. */
-# ifndef HAVE_MATHERR
-# define HAVE_MATHERR
-# endif
-#endif
-
-#ifdef NO_MATHERR
-#undef HAVE_MATHERR
-#endif
-
-#ifdef HAVE_MATHERR
-# ifdef FLOAT_CHECK_ERRNO
-# undef FLOAT_CHECK_ERRNO
-# endif
-# ifdef FLOAT_CHECK_DOMAIN
-# undef FLOAT_CHECK_DOMAIN
-# endif
+#ifndef isfinite
+# define isfinite(x) ((x) - (x) == 0)
#endif
-
-#ifndef NO_FLOAT_CHECK_ERRNO
-#define FLOAT_CHECK_ERRNO
-#endif
-
-#ifdef FLOAT_CHECK_ERRNO
-# include <errno.h>
-#endif
-
-#ifdef FLOAT_CATCH_SIGILL
-static void float_error ();
-#endif
-
-/* Nonzero while executing in floating point.
- This tells float_error what to do. */
-
-static int in_float;
-
-/* If an argument is out of range for a mathematical function,
- here is the actual argument value to use in the error message.
- These variables are used only across the floating point library call
- so there is no need to staticpro them. */
-
-static Lisp_Object float_error_arg, float_error_arg2;
-
-static const char *float_error_fn_name;
-
-/* Evaluate the floating point expression D, recording NUM
- as the original argument for error messages.
- D is normally an assignment expression.
- Handle errors which may result in signals or may set errno.
-
- Note that float_error may be declared to return void, so you can't
- just cast the zero after the colon to (void) to make the types
- check properly. */
-
-#ifdef FLOAT_CHECK_ERRNO
-#define IN_FLOAT(d, name, num) \
- do { \
- float_error_arg = num; \
- float_error_fn_name = name; \
- in_float = 1; errno = 0; (d); in_float = 0; \
- switch (errno) { \
- case 0: break; \
- case EDOM: domain_error (float_error_fn_name, float_error_arg); \
- case ERANGE: range_error (float_error_fn_name, float_error_arg); \
- default: arith_error (float_error_fn_name, float_error_arg); \
- } \
- } while (0)
-#define IN_FLOAT2(d, name, num, num2) \
- do { \
- float_error_arg = num; \
- float_error_arg2 = num2; \
- float_error_fn_name = name; \
- in_float = 1; errno = 0; (d); in_float = 0; \
- switch (errno) { \
- case 0: break; \
- case EDOM: domain_error (float_error_fn_name, float_error_arg); \
- case ERANGE: range_error (float_error_fn_name, float_error_arg); \
- default: arith_error (float_error_fn_name, float_error_arg); \
- } \
- } while (0)
-#else
-#define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
-#define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
-#endif
-
-/* Convert float to Lisp_Int if it fits, else signal a range error
- using the given arguments. */
-#define FLOAT_TO_INT(x, i, name, num) \
- do \
- { \
- if (FIXNUM_OVERFLOW_P (x)) \
- range_error (name, num); \
- XSETINT (i, (EMACS_INT)(x)); \
- } \
- while (0)
-#define FLOAT_TO_INT2(x, i, name, num1, num2) \
- do \
- { \
- if (FIXNUM_OVERFLOW_P (x)) \
- range_error2 (name, num1, num2); \
- XSETINT (i, (EMACS_INT)(x)); \
- } \
- while (0)
-
-#define arith_error(op,arg) \
- xsignal2 (Qarith_error, build_string ((op)), (arg))
-#define range_error(op,arg) \
- xsignal2 (Qrange_error, build_string ((op)), (arg))
-#define range_error2(op,a1,a2) \
- xsignal3 (Qrange_error, build_string ((op)), (a1), (a2))
-#define domain_error(op,arg) \
- xsignal2 (Qdomain_error, build_string ((op)), (arg))
-#ifdef FLOAT_CHECK_DOMAIN
-#define domain_error2(op,a1,a2) \
- xsignal3 (Qdomain_error, build_string ((op)), (a1), (a2))
+#ifndef isnan
+# define isnan(x) ((x) != (x))
#endif
/* Extract a Lisp number as a `double', or signal an error. */
@@ -205,27 +57,19 @@ extract_float (Lisp_Object num)
DEFUN ("acos", Facos, Sacos, 1, 1, 0,
doc: /* Return the inverse cosine of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 1.0 || d < -1.0)
- domain_error ("acos", arg);
-#endif
- IN_FLOAT (d = acos (d), "acos", arg);
+ d = acos (d);
return make_float (d);
}
DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
doc: /* Return the inverse sine of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 1.0 || d < -1.0)
- domain_error ("asin", arg);
-#endif
- IN_FLOAT (d = asin (d), "asin", arg);
+ d = asin (d);
return make_float (d);
}
@@ -235,56 +79,47 @@ If only one argument Y is given, return the inverse tangent of Y.
If two arguments Y and X are given, return the inverse tangent of Y
divided by X, i.e. the angle in radians between the vector (X, Y)
and the x-axis. */)
- (register Lisp_Object y, Lisp_Object x)
+ (Lisp_Object y, Lisp_Object x)
{
double d = extract_float (y);
if (NILP (x))
- IN_FLOAT (d = atan (d), "atan", y);
+ d = atan (d);
else
{
double d2 = extract_float (x);
-
- IN_FLOAT2 (d = atan2 (d, d2), "atan", y, x);
+ d = atan2 (d, d2);
}
return make_float (d);
}
DEFUN ("cos", Fcos, Scos, 1, 1, 0,
doc: /* Return the cosine of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- IN_FLOAT (d = cos (d), "cos", arg);
+ d = cos (d);
return make_float (d);
}
DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
doc: /* Return the sine of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- IN_FLOAT (d = sin (d), "sin", arg);
+ d = sin (d);
return make_float (d);
}
DEFUN ("tan", Ftan, Stan, 1, 1, 0,
doc: /* Return the tangent of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- double c = cos (d);
-#ifdef FLOAT_CHECK_DOMAIN
- if (c == 0.0)
- domain_error ("tan", arg);
-#endif
- IN_FLOAT (d = sin (d) / c, "tan", arg);
+ d = tan (d);
return make_float (d);
}
-#undef isnan
-#define isnan(x) ((x) != (x))
-
DEFUN ("isnan", Fisnan, Sisnan, 1, 1, 0,
doc: /* Return non nil iff argument X is a NaN. */)
(Lisp_Object x)
@@ -309,6 +144,7 @@ Cause an error if X1 or X2 is not a float. */)
return make_float (copysign (f1, f2));
}
+#endif
DEFUN ("frexp", Ffrexp, Sfrexp, 1, 1, 0,
doc: /* Get significand and exponent of a floating point number.
@@ -323,15 +159,9 @@ If X is zero, both parts (SGNFCAND and EXP) are zero. */)
(Lisp_Object x)
{
double f = XFLOATINT (x);
-
- if (f == 0.0)
- return Fcons (make_float (0.0), make_number (0));
- else
- {
- int exponent;
- double sgnfcand = frexp (f, &exponent);
- return Fcons (make_float (sgnfcand), make_number (exponent));
- }
+ int exponent;
+ double sgnfcand = frexp (f, &exponent);
+ return Fcons (make_float (sgnfcand), make_number (exponent));
}
DEFUN ("ldexp", Fldexp, Sldexp, 1, 2, 0,
@@ -343,138 +173,19 @@ Returns the floating point value resulting from multiplying SGNFCAND
CHECK_NUMBER (exponent);
return make_float (ldexp (XFLOATINT (sgnfcand), XINT (exponent)));
}
-#endif
-
-#if 0 /* Leave these out unless we find there's a reason for them. */
-
-DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
- doc: /* Return the bessel function j0 of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = j0 (d), "bessel-j0", arg);
- return make_float (d);
-}
-
-DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
- doc: /* Return the bessel function j1 of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = j1 (d), "bessel-j1", arg);
- return make_float (d);
-}
-
-DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
- doc: /* Return the order N bessel function output jn of ARG.
-The first arg (the order) is truncated to an integer. */)
- (register Lisp_Object n, Lisp_Object arg)
-{
- int i1 = extract_float (n);
- double f2 = extract_float (arg);
-
- IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", n);
- return make_float (f2);
-}
-
-DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
- doc: /* Return the bessel function y0 of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = y0 (d), "bessel-y0", arg);
- return make_float (d);
-}
-
-DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
- doc: /* Return the bessel function y1 of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = y1 (d), "bessel-y0", arg);
- return make_float (d);
-}
-
-DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
- doc: /* Return the order N bessel function output yn of ARG.
-The first arg (the order) is truncated to an integer. */)
- (register Lisp_Object n, Lisp_Object arg)
-{
- int i1 = extract_float (n);
- double f2 = extract_float (arg);
-
- IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", n);
- return make_float (f2);
-}
-
-#endif
-
-#if 0 /* Leave these out unless we see they are worth having. */
-
-DEFUN ("erf", Ferf, Serf, 1, 1, 0,
- doc: /* Return the mathematical error function of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = erf (d), "erf", arg);
- return make_float (d);
-}
-
-DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
- doc: /* Return the complementary error function of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = erfc (d), "erfc", arg);
- return make_float (d);
-}
-
-DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
- doc: /* Return the log gamma of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
- IN_FLOAT (d = lgamma (d), "log-gamma", arg);
- return make_float (d);
-}
-
-DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
- doc: /* Return the cube root of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef HAVE_CBRT
- IN_FLOAT (d = cbrt (d), "cube-root", arg);
-#else
- if (d >= 0.0)
- IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg);
- else
- IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg);
-#endif
- return make_float (d);
-}
-
-#endif
DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
doc: /* Return the exponential base e of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 709.7827) /* Assume IEEE doubles here */
- range_error ("exp", arg);
- else if (d < -709.0)
- return make_float (0.0);
- else
-#endif
- IN_FLOAT (d = exp (d), "exp", arg);
+ d = exp (d);
return make_float (d);
}
DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
doc: /* Return the exponential ARG1 ** ARG2. */)
- (register Lisp_Object arg1, Lisp_Object arg2)
+ (Lisp_Object arg1, Lisp_Object arg2)
{
double f1, f2, f3;
@@ -503,159 +214,48 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
}
f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1);
f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2);
- /* Really should check for overflow, too */
- if (f1 == 0.0 && f2 == 0.0)
- f1 = 1.0;
-#ifdef FLOAT_CHECK_DOMAIN
- else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor (f2)))
- domain_error2 ("expt", arg1, arg2);
-#endif
- IN_FLOAT2 (f3 = pow (f1, f2), "expt", arg1, arg2);
- /* Check for overflow in the result. */
- if (f1 != 0.0 && f3 == 0.0)
- range_error ("expt", arg1);
+ f3 = pow (f1, f2);
return make_float (f3);
}
DEFUN ("log", Flog, Slog, 1, 2, 0,
doc: /* Return the natural logarithm of ARG.
If the optional argument BASE is given, return log ARG using that base. */)
- (register Lisp_Object arg, Lisp_Object base)
+ (Lisp_Object arg, Lisp_Object base)
{
double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d <= 0.0)
- domain_error2 ("log", arg, base);
-#endif
if (NILP (base))
- IN_FLOAT (d = log (d), "log", arg);
+ d = log (d);
else
{
double b = extract_float (base);
-#ifdef FLOAT_CHECK_DOMAIN
- if (b <= 0.0 || b == 1.0)
- domain_error2 ("log", arg, base);
-#endif
if (b == 10.0)
- IN_FLOAT2 (d = log10 (d), "log", arg, base);
+ d = log10 (d);
else
- IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
+ d = log (d) / log (b);
}
return make_float (d);
}
DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
doc: /* Return the logarithm base 10 of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d <= 0.0)
- domain_error ("log10", arg);
-#endif
- IN_FLOAT (d = log10 (d), "log10", arg);
+ d = log10 (d);
return make_float (d);
}
DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
doc: /* Return the square root of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d < 0.0)
- domain_error ("sqrt", arg);
-#endif
- IN_FLOAT (d = sqrt (d), "sqrt", arg);
- return make_float (d);
-}
-
-#if 0 /* Not clearly worth adding. */
-
-DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
- doc: /* Return the inverse hyperbolic cosine of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d < 1.0)
- domain_error ("acosh", arg);
-#endif
-#ifdef HAVE_INVERSE_HYPERBOLIC
- IN_FLOAT (d = acosh (d), "acosh", arg);
-#else
- IN_FLOAT (d = log (d + sqrt (d*d - 1.0)), "acosh", arg);
-#endif
- return make_float (d);
-}
-
-DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
- doc: /* Return the inverse hyperbolic sine of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef HAVE_INVERSE_HYPERBOLIC
- IN_FLOAT (d = asinh (d), "asinh", arg);
-#else
- IN_FLOAT (d = log (d + sqrt (d*d + 1.0)), "asinh", arg);
-#endif
- return make_float (d);
-}
-
-DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
- doc: /* Return the inverse hyperbolic tangent of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d >= 1.0 || d <= -1.0)
- domain_error ("atanh", arg);
-#endif
-#ifdef HAVE_INVERSE_HYPERBOLIC
- IN_FLOAT (d = atanh (d), "atanh", arg);
-#else
- IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)), "atanh", arg);
-#endif
- return make_float (d);
-}
-
-DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
- doc: /* Return the hyperbolic cosine of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 710.0 || d < -710.0)
- range_error ("cosh", arg);
-#endif
- IN_FLOAT (d = cosh (d), "cosh", arg);
- return make_float (d);
-}
-
-DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
- doc: /* Return the hyperbolic sine of ARG. */)
- (register Lisp_Object arg)
-{
- double d = extract_float (arg);
-#ifdef FLOAT_CHECK_DOMAIN
- if (d > 710.0 || d < -710.0)
- range_error ("sinh", arg);
-#endif
- IN_FLOAT (d = sinh (d), "sinh", arg);
- return make_float (d);
-}
-
-DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
- doc: /* Return the hyperbolic tangent of ARG. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- IN_FLOAT (d = tanh (d), "tanh", arg);
+ d = sqrt (d);
return make_float (d);
}
-#endif
DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
doc: /* Return the absolute value of ARG. */)
@@ -694,38 +294,15 @@ This is the same as the exponent of a float. */)
if (f == 0.0)
value = MOST_NEGATIVE_FIXNUM;
- else
+ else if (isfinite (f))
{
-#ifdef HAVE_LOGB
- IN_FLOAT (value = logb (f), "logb", arg);
-#else
-#ifdef HAVE_FREXP
int ivalue;
- IN_FLOAT (frexp (f, &ivalue), "logb", arg);
+ frexp (f, &ivalue);
value = ivalue - 1;
-#else
- int i;
- double d;
- if (f < 0.0)
- f = -f;
- value = -1;
- while (f < 0.5)
- {
- for (i = 1, d = 0.5; d * d >= f; i += i)
- d *= d;
- f /= d;
- value -= i;
- }
- while (f >= 1.0)
- {
- for (i = 1, d = 2.0; d * d <= f; i += i)
- d *= d;
- f /= d;
- value += i;
- }
-#endif
-#endif
}
+ else
+ value = MOST_POSITIVE_FIXNUM;
+
XSETINT (val, value);
return val;
}
@@ -756,8 +333,10 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor,
if (! IEEE_FLOATING_POINT && f2 == 0)
xsignal0 (Qarith_error);
- IN_FLOAT2 (f1 = (*double_round) (f1 / f2), name, arg, divisor);
- FLOAT_TO_INT2 (f1, arg, name, arg, divisor);
+ f1 = (*double_round) (f1 / f2);
+ if (FIXNUM_OVERFLOW_P (f1))
+ xsignal3 (Qrange_error, build_string (name), arg, divisor);
+ arg = make_number (f1);
return arg;
}
@@ -773,10 +352,10 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor,
if (FLOATP (arg))
{
- double d;
-
- IN_FLOAT (d = (*double_round) (XFLOAT_DATA (arg)), name, arg);
- FLOAT_TO_INT (d, arg, name, arg);
+ double d = (*double_round) (XFLOAT_DATA (arg));
+ if (FIXNUM_OVERFLOW_P (d))
+ xsignal2 (Qrange_error, build_string (name), arg);
+ arg = make_number (d);
}
return arg;
@@ -893,125 +472,57 @@ fmod_float (Lisp_Object x, Lisp_Object y)
f1 = FLOATP (x) ? XFLOAT_DATA (x) : XINT (x);
f2 = FLOATP (y) ? XFLOAT_DATA (y) : XINT (y);
- if (! IEEE_FLOATING_POINT && f2 == 0)
- xsignal0 (Qarith_error);
+ f1 = fmod (f1, f2);
/* If the "remainder" comes out with the wrong sign, fix it. */
- IN_FLOAT2 ((f1 = fmod (f1, f2),
- f1 = (f2 < 0 ? f1 > 0 : f1 < 0) ? f1 + f2 : f1),
- "mod", x, y);
+ if (f2 < 0 ? 0 < f1 : f1 < 0)
+ f1 += f2;
+
return make_float (f1);
}
-/* It's not clear these are worth adding. */
-
DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
doc: /* Return the smallest integer no less than ARG, as a float.
\(Round toward +inf.\) */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- IN_FLOAT (d = ceil (d), "fceiling", arg);
+ d = ceil (d);
return make_float (d);
}
DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
doc: /* Return the largest integer no greater than ARG, as a float.
\(Round towards -inf.\) */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- IN_FLOAT (d = floor (d), "ffloor", arg);
+ d = floor (d);
return make_float (d);
}
DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
doc: /* Return the nearest integer to ARG, as a float. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
- IN_FLOAT (d = emacs_rint (d), "fround", arg);
+ d = emacs_rint (d);
return make_float (d);
}
DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
doc: /* Truncate a floating point number to an integral float value.
Rounds the value toward zero. */)
- (register Lisp_Object arg)
+ (Lisp_Object arg)
{
double d = extract_float (arg);
if (d >= 0.0)
- IN_FLOAT (d = floor (d), "ftruncate", arg);
+ d = floor (d);
else
- IN_FLOAT (d = ceil (d), "ftruncate", arg);
+ d = ceil (d);
return make_float (d);
}
-#ifdef FLOAT_CATCH_SIGILL
-static void
-float_error (int signo)
-{
- if (! in_float)
- fatal_error_signal (signo);
-
-#ifdef BSD_SYSTEM
- sigsetmask (SIGEMPTYMASK);
-#else
- /* Must reestablish handler each time it is called. */
- signal (SIGILL, float_error);
-#endif /* BSD_SYSTEM */
-
- SIGNAL_THREAD_CHECK (signo);
- in_float = 0;
-
- xsignal1 (Qarith_error, float_error_arg);
-}
-
-/* Another idea was to replace the library function `infnan'
- where SIGILL is signaled. */
-
-#endif /* FLOAT_CATCH_SIGILL */
-
-#ifdef HAVE_MATHERR
-int
-matherr (struct exception *x)
-{
- Lisp_Object args;
- const char *name = x->name;
-
- if (! in_float)
- /* Not called from emacs-lisp float routines; do the default thing. */
- return 0;
- if (!strcmp (x->name, "pow"))
- name = "expt";
-
- args
- = Fcons (build_string (name),
- Fcons (make_float (x->arg1),
- ((!strcmp (name, "log") || !strcmp (name, "pow"))
- ? Fcons (make_float (x->arg2), Qnil)
- : Qnil)));
- switch (x->type)
- {
- case DOMAIN: xsignal (Qdomain_error, args); break;
- case SING: xsignal (Qsingularity_error, args); break;
- case OVERFLOW: xsignal (Qoverflow_error, args); break;
- case UNDERFLOW: xsignal (Qunderflow_error, args); break;
- default: xsignal (Qarith_error, args); break;
- }
- return (1); /* don't set errno or print a message */
-}
-#endif /* HAVE_MATHERR */
-
-void
-init_floatfns (void)
-{
-#ifdef FLOAT_CATCH_SIGILL
- signal (SIGILL, float_error);
-#endif
- in_float = 0;
-}
-
void
syms_of_floatfns (void)
{
@@ -1024,27 +535,9 @@ syms_of_floatfns (void)
defsubr (&Sisnan);
#ifdef HAVE_COPYSIGN
defsubr (&Scopysign);
+#endif
defsubr (&Sfrexp);
defsubr (&Sldexp);
-#endif
-#if 0
- defsubr (&Sacosh);
- defsubr (&Sasinh);
- defsubr (&Satanh);
- defsubr (&Scosh);
- defsubr (&Ssinh);
- defsubr (&Stanh);
- defsubr (&Sbessel_y0);
- defsubr (&Sbessel_y1);
- defsubr (&Sbessel_yn);
- defsubr (&Sbessel_j0);
- defsubr (&Sbessel_j1);
- defsubr (&Sbessel_jn);
- defsubr (&Serf);
- defsubr (&Serfc);
- defsubr (&Slog_gamma);
- defsubr (&Scube_root);
-#endif
defsubr (&Sfceiling);
defsubr (&Sffloor);
defsubr (&Sfround);
diff --git a/src/fns.c b/src/fns.c
index 4d82e4e6e1d..7c2222e9805 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <time.h>
-#include <setjmp.h>
#include <intprops.h>
@@ -51,7 +50,7 @@ static Lisp_Object Qcodeset, Qdays, Qmonths, Qpaper;
static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512;
-static int internal_equal (Lisp_Object , Lisp_Object, int, int);
+static bool internal_equal (Lisp_Object, Lisp_Object, int, bool);
DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
doc: /* Return the argument unchanged. */)
@@ -62,8 +61,9 @@ DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
DEFUN ("random", Frandom, Srandom, 0, 1, 0,
doc: /* Return a pseudo-random number.
-All integers representable in Lisp are equally likely.
- On most systems, this is 29 bits' worth.
+All integers representable in Lisp, i.e. between `most-negative-fixnum'
+and `most-positive-fixnum', inclusive, are equally likely.
+
With positive integer LIMIT, return random number in interval [0,LIMIT).
With argument t, set the random number seed from the current time and pid.
Other values of LIMIT are ignored. */)
@@ -352,7 +352,7 @@ Symbols are also allowed; their print names are used instead. */)
}
static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args,
- enum Lisp_Type target_type, int last_special);
+ enum Lisp_Type target_type, bool last_special);
/* ARGSUSED */
Lisp_Object
@@ -450,19 +450,19 @@ struct textprop_rec
static Lisp_Object
concat (ptrdiff_t nargs, Lisp_Object *args,
- enum Lisp_Type target_type, int last_special)
+ enum Lisp_Type target_type, bool last_special)
{
Lisp_Object val;
- register Lisp_Object tail;
- register Lisp_Object this;
+ Lisp_Object tail;
+ Lisp_Object this;
ptrdiff_t toindex;
ptrdiff_t toindex_byte = 0;
- register EMACS_INT result_len;
- register EMACS_INT result_len_byte;
+ EMACS_INT result_len;
+ EMACS_INT result_len_byte;
ptrdiff_t argnum;
Lisp_Object last_tail;
Lisp_Object prev;
- int some_multibyte;
+ bool some_multibyte;
/* When we make a multibyte string, we can't copy text properties
while concatenating each string because the length of resulting
string can't be decided until we finish the whole concatenation.
@@ -1527,11 +1527,14 @@ The value is actually the first element of LIST whose cdr equals KEY. */)
}
DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
- doc: /* Delete by side effect any occurrences of ELT as a member of LIST.
-The modified LIST is returned. Comparison is done with `eq'.
-If the first member of LIST is ELT, there is no way to remove it by side effect;
-therefore, write `(setq foo (delq element foo))'
-to be sure of changing the value of `foo'. */)
+ doc: /* Delete members of LIST which are `eq' to ELT, and return the result.
+More precisely, this function skips any members `eq' to ELT at the
+front of LIST, then removes members `eq' to ELT from the remaining
+sublist by modifying its list structure, then returns the resulting
+list.
+
+Write `(setq foo (delq element foo))' to be sure of correctly changing
+the value of a list `foo'. */)
(register Lisp_Object elt, Lisp_Object list)
{
register Lisp_Object tail, prev;
@@ -1559,13 +1562,19 @@ to be sure of changing the value of `foo'. */)
}
DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
- doc: /* Delete by side effect any occurrences of ELT as a member of SEQ.
-SEQ must be a list, a vector, or a string.
-The modified SEQ is returned. Comparison is done with `equal'.
-If SEQ is not a list, or the first member of SEQ is ELT, deleting it
-is not a side effect; it is simply using a different sequence.
-Therefore, write `(setq foo (delete element foo))'
-to be sure of changing the value of `foo'. */)
+ doc: /* Delete members of SEQ which are `equal' to ELT, and return the result.
+SEQ must be a sequence (i.e. a list, a vector, or a string).
+The return value is a sequence of the same type.
+
+If SEQ is a list, this behaves like `delq', except that it compares
+with `equal' instead of `eq'. In particular, it may remove elements
+by altering the list structure.
+
+If SEQ is not a list, deletion is never performed destructively;
+instead this function creates and returns a new vector or string.
+
+Write `(setq foo (delete element foo))' to be sure of correctly
+changing the value of a sequence `foo'. */)
(Lisp_Object elt, Lisp_Object seq)
{
if (VECTORP (seq))
@@ -1680,7 +1689,7 @@ to be sure of changing the value of `foo'. */)
DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
doc: /* Reverse LIST by modifying cdr pointers.
-Return the reversed list. */)
+Return the reversed list. Expects a properly nil-terminated list. */)
(Lisp_Object list)
{
register Lisp_Object prev, tail, next;
@@ -1691,7 +1700,7 @@ Return the reversed list. */)
while (!NILP (tail))
{
QUIT;
- CHECK_LIST_CONS (tail, list);
+ CHECK_LIST_CONS (tail, tail);
next = XCDR (tail);
Fsetcdr (tail, prev);
prev = tail;
@@ -1830,13 +1839,6 @@ properties on the list. This function never signals an error. */)
halftail = XCDR (halftail);
if (EQ (tail, halftail))
break;
-
-#if 0 /* Unsafe version. */
- /* This function can be called asynchronously
- (setup_coding_system). Don't QUIT in that case. */
- if (!interrupt_input_blocked)
- QUIT;
-#endif
}
return Qnil;
@@ -1988,10 +1990,10 @@ of strings. (`equal' ignores text properties.) */)
/* DEPTH is current depth of recursion. Signal an error if it
gets too deep.
- PROPS, if non-nil, means compare string text properties too. */
+ PROPS means compare string text properties too. */
-static int
-internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int props)
+static bool
+internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props)
{
if (depth > 200)
error ("Stack overflow in equal");
@@ -2012,7 +2014,7 @@ internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int
d1 = extract_float (o1);
d2 = extract_float (o2);
/* If d is a NaN, then d != d. Two NaNs should be `equal' even
- though they are not =. */
+ though they are not =. */
return d1 == d2 || (d1 != d1 && d2 != d2);
}
@@ -2074,9 +2076,8 @@ internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int
are sensible to compare, so eliminate the others now. */
if (size & PSEUDOVECTOR_FLAG)
{
- if (!(size & ((PVEC_COMPILED | PVEC_CHAR_TABLE
- | PVEC_SUB_CHAR_TABLE | PVEC_FONT)
- << PSEUDOVECTOR_SIZE_BITS)))
+ if (((size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
+ < PVEC_COMPILED)
return 0;
size &= PSEUDOVECTOR_SIZE_MASK;
}
@@ -2589,9 +2590,9 @@ Normally the return value is FEATURE.
The normal messages at start and end of loading FILENAME are suppressed. */)
(Lisp_Object feature, Lisp_Object filename, Lisp_Object noerror)
{
- register Lisp_Object tem;
+ Lisp_Object tem;
struct gcpro gcpro1, gcpro2;
- int from_file = load_in_progress;
+ bool from_file = load_in_progress;
CHECK_SYMBOL (feature);
@@ -2917,8 +2918,8 @@ static const short base64_char_to_value[128] =
base64 characters. */
-static ptrdiff_t base64_encode_1 (const char *, char *, ptrdiff_t, int, int);
-static ptrdiff_t base64_decode_1 (const char *, char *, ptrdiff_t, int,
+static ptrdiff_t base64_encode_1 (const char *, char *, ptrdiff_t, bool, bool);
+static ptrdiff_t base64_decode_1 (const char *, char *, ptrdiff_t, bool,
ptrdiff_t *);
DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region,
@@ -2953,7 +2954,7 @@ into shorter lines. */)
encoded, length, NILP (no_line_break),
!NILP (BVAR (current_buffer, enable_multibyte_characters)));
if (encoded_length > allength)
- abort ();
+ emacs_abort ();
if (encoded_length < 0)
{
@@ -3009,7 +3010,7 @@ into shorter lines. */)
encoded, length, NILP (no_line_break),
STRING_MULTIBYTE (string));
if (encoded_length > allength)
- abort ();
+ emacs_abort ();
if (encoded_length < 0)
{
@@ -3026,7 +3027,7 @@ into shorter lines. */)
static ptrdiff_t
base64_encode_1 (const char *from, char *to, ptrdiff_t length,
- int line_break, int multibyte)
+ bool line_break, bool multibyte)
{
int counter = 0;
ptrdiff_t i = 0;
@@ -3133,7 +3134,7 @@ If the region can't be decoded, signal an error and don't modify the buffer. */
ptrdiff_t old_pos = PT;
ptrdiff_t decoded_length;
ptrdiff_t inserted_chars;
- int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
+ bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
USE_SAFE_ALLOCA;
validate_region (&beg, &end);
@@ -3154,7 +3155,7 @@ If the region can't be decoded, signal an error and don't modify the buffer. */
decoded, length,
multibyte, &inserted_chars);
if (decoded_length > allength)
- abort ();
+ emacs_abort ();
if (decoded_length < 0)
{
@@ -3204,7 +3205,7 @@ DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
decoded_length = base64_decode_1 (SSDATA (string), decoded, length,
0, NULL);
if (decoded_length > length)
- abort ();
+ emacs_abort ();
else if (decoded_length >= 0)
decoded_string = make_unibyte_string (decoded, decoded_length);
else
@@ -3218,13 +3219,13 @@ DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
}
/* Base64-decode the data at FROM of LENGTH bytes into TO. If
- MULTIBYTE is nonzero, the decoded result should be in multibyte
+ MULTIBYTE, the decoded result should be in multibyte
form. If NCHARS_RETURN is not NULL, store the number of produced
characters in *NCHARS_RETURN. */
static ptrdiff_t
base64_decode_1 (const char *from, char *to, ptrdiff_t length,
- int multibyte, ptrdiff_t *nchars_return)
+ bool multibyte, ptrdiff_t *nchars_return)
{
ptrdiff_t i = 0; /* Used inside READ_QUADRUPLET_BYTE */
char *e = to;
@@ -3330,19 +3331,11 @@ static struct Lisp_Hash_Table *weak_hash_tables;
/* Various symbols. */
-static Lisp_Object Qhash_table_p, Qkey, Qvalue;
-Lisp_Object Qeq, Qeql, Qequal;
+static Lisp_Object Qhash_table_p, 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;
-/* Function prototypes. */
-
-static struct Lisp_Hash_Table *check_hash_table (Lisp_Object);
-static ptrdiff_t get_key_arg (Lisp_Object, ptrdiff_t, Lisp_Object *, char *);
-static void maybe_resize_hash_table (struct Lisp_Hash_Table *);
-static int sweep_weak_table (struct Lisp_Hash_Table *, int);
-
-
/***********************************************************************
Utilities
@@ -3431,14 +3424,17 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max)
Low-level Functions
***********************************************************************/
+static struct hash_table_test hashtest_eq;
+struct hash_table_test hashtest_eql, hashtest_equal;
+
/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
- HASH2 in hash table H using `eql'. Value is non-zero if KEY1 and
+ HASH2 in hash table H using `eql'. Value is true if KEY1 and
KEY2 are the same. */
-static int
-cmpfn_eql (struct Lisp_Hash_Table *h,
- Lisp_Object key1, EMACS_UINT hash1,
- Lisp_Object key2, EMACS_UINT hash2)
+static bool
+cmpfn_eql (struct hash_table_test *ht,
+ Lisp_Object key1,
+ Lisp_Object key2)
{
return (FLOATP (key1)
&& FLOATP (key2)
@@ -3447,38 +3443,33 @@ cmpfn_eql (struct Lisp_Hash_Table *h,
/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
- HASH2 in hash table H using `equal'. Value is non-zero if KEY1 and
+ HASH2 in hash table H using `equal'. Value is true if KEY1 and
KEY2 are the same. */
-static int
-cmpfn_equal (struct Lisp_Hash_Table *h,
- Lisp_Object key1, EMACS_UINT hash1,
- Lisp_Object key2, EMACS_UINT hash2)
+static bool
+cmpfn_equal (struct hash_table_test *ht,
+ Lisp_Object key1,
+ Lisp_Object key2)
{
- return hash1 == hash2 && !NILP (Fequal (key1, key2));
+ return !NILP (Fequal (key1, key2));
}
/* Compare KEY1 which has hash code HASH1, and KEY2 with hash code
- HASH2 in hash table H using H->user_cmp_function. Value is non-zero
+ HASH2 in hash table H using H->user_cmp_function. Value is true
if KEY1 and KEY2 are the same. */
-static int
-cmpfn_user_defined (struct Lisp_Hash_Table *h,
- Lisp_Object key1, EMACS_UINT hash1,
- Lisp_Object key2, EMACS_UINT hash2)
+static bool
+cmpfn_user_defined (struct hash_table_test *ht,
+ Lisp_Object key1,
+ Lisp_Object key2)
{
- if (hash1 == hash2)
- {
- Lisp_Object args[3];
+ Lisp_Object args[3];
- args[0] = h->user_cmp_function;
- args[1] = key1;
- args[2] = key2;
- return !NILP (Ffuncall (3, args));
- }
- else
- return 0;
+ args[0] = ht->user_cmp_function;
+ args[1] = key1;
+ args[2] = key2;
+ return !NILP (Ffuncall (3, args));
}
@@ -3487,54 +3478,48 @@ cmpfn_user_defined (struct Lisp_Hash_Table *h,
in a Lisp integer. */
static EMACS_UINT
-hashfn_eq (struct Lisp_Hash_Table *h, Lisp_Object key)
+hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
{
- EMACS_UINT hash = XUINT (key) ^ XTYPE (key);
- eassert ((hash & ~INTMASK) == 0);
+ EMACS_UINT hash = XHASH (key) ^ XTYPE (key);
return hash;
}
-
/* Value is a hash code for KEY for use in hash table H which uses
`eql' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */
static EMACS_UINT
-hashfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key)
+hashfn_eql (struct hash_table_test *ht, Lisp_Object key)
{
EMACS_UINT hash;
if (FLOATP (key))
hash = sxhash (key, 0);
else
- hash = XUINT (key) ^ XTYPE (key);
- eassert ((hash & ~INTMASK) == 0);
+ hash = XHASH (key) ^ XTYPE (key);
return hash;
}
-
/* Value is a hash code for KEY for use in hash table H which uses
`equal' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */
static EMACS_UINT
-hashfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key)
+hashfn_equal (struct hash_table_test *ht, Lisp_Object key)
{
EMACS_UINT hash = sxhash (key, 0);
- eassert ((hash & ~INTMASK) == 0);
return hash;
}
-
/* Value is a hash code for KEY for use in hash table H which uses as
user-defined function to compare keys. The hash code returned is
guaranteed to fit in a Lisp integer. */
static EMACS_UINT
-hashfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key)
+hashfn_user_defined (struct hash_table_test *ht, Lisp_Object key)
{
Lisp_Object args[2], hash;
- args[0] = h->user_hash_function;
+ args[0] = ht->user_hash_function;
args[1] = key;
hash = Ffuncall (2, args);
if (!INTEGERP (hash))
@@ -3570,9 +3555,9 @@ hashfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key)
one of the symbols `key', `value', `key-or-value', or `key-and-value'. */
Lisp_Object
-make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size,
- Lisp_Object rehash_threshold, Lisp_Object weak,
- Lisp_Object user_test, Lisp_Object user_hash)
+make_hash_table (struct hash_table_test test,
+ Lisp_Object size, Lisp_Object rehash_size,
+ Lisp_Object rehash_threshold, Lisp_Object weak)
{
struct Lisp_Hash_Table *h;
Lisp_Object table;
@@ -3581,7 +3566,7 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size,
double index_float;
/* Preconditions. */
- eassert (SYMBOLP (test));
+ eassert (SYMBOLP (test.name));
eassert (INTEGERP (size) && XINT (size) >= 0);
eassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0)
|| (FLOATP (rehash_size) && 1 < XFLOAT_DATA (rehash_size)));
@@ -3605,29 +3590,6 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size,
/* Initialize hash table slots. */
h->test = test;
- if (EQ (test, Qeql))
- {
- h->cmpfn = cmpfn_eql;
- h->hashfn = hashfn_eql;
- }
- else if (EQ (test, Qeq))
- {
- h->cmpfn = NULL;
- h->hashfn = hashfn_eq;
- }
- else if (EQ (test, Qequal))
- {
- h->cmpfn = cmpfn_equal;
- h->hashfn = hashfn_equal;
- }
- else
- {
- h->user_cmp_function = user_test;
- h->user_hash_function = user_hash;
- h->cmpfn = cmpfn_user_defined;
- h->hashfn = hashfn_user_defined;
- }
-
h->weak = weak;
h->rehash_threshold = rehash_threshold;
h->rehash_size = rehash_size;
@@ -3667,12 +3629,9 @@ copy_hash_table (struct Lisp_Hash_Table *h1)
{
Lisp_Object table;
struct Lisp_Hash_Table *h2;
- struct Lisp_Vector *next;
h2 = allocate_hash_table ();
- next = h2->header.next.vector;
- memcpy (h2, h1, sizeof *h2);
- h2->header.next.vector = next;
+ *h2 = *h1;
h2->key_and_value = Fcopy_sequence (h1->key_and_value);
h2->hash = Fcopy_sequence (h1->hash);
h2->next = Fcopy_sequence (h1->next);
@@ -3693,7 +3652,7 @@ copy_hash_table (struct Lisp_Hash_Table *h1)
/* Resize hash table H if it's too full. If H cannot be resized
because it's already too large, throw an error. */
-static inline void
+static void
maybe_resize_hash_table (struct Lisp_Hash_Table *h)
{
if (NILP (h->next_free))
@@ -3786,7 +3745,8 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash)
ptrdiff_t start_of_bucket;
Lisp_Object idx;
- hash_code = h->hashfn (h, key);
+ hash_code = h->test.hashfn (&h->test, key);
+ eassert ((hash_code & ~INTMASK) == 0);
if (hash)
*hash = hash_code;
@@ -3798,9 +3758,9 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash)
{
ptrdiff_t i = XFASTINT (idx);
if (EQ (key, HASH_KEY (h, i))
- || (h->cmpfn
- && h->cmpfn (h, key, hash_code,
- HASH_KEY (h, i), XUINT (HASH_HASH (h, i)))))
+ || (h->test.cmpfn
+ && hash_code == XUINT (HASH_HASH (h, i))
+ && h->test.cmpfn (&h->test, key, HASH_KEY (h, i))))
break;
idx = HASH_NEXT (h, i);
}
@@ -3851,7 +3811,8 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
ptrdiff_t start_of_bucket;
Lisp_Object idx, prev;
- hash_code = h->hashfn (h, key);
+ hash_code = h->test.hashfn (&h->test, key);
+ eassert ((hash_code & ~INTMASK) == 0);
start_of_bucket = hash_code % ASIZE (h->index);
idx = HASH_INDEX (h, start_of_bucket);
prev = Qnil;
@@ -3862,9 +3823,9 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
ptrdiff_t i = XFASTINT (idx);
if (EQ (key, HASH_KEY (h, i))
- || (h->cmpfn
- && h->cmpfn (h, key, hash_code,
- HASH_KEY (h, i), XUINT (HASH_HASH (h, i)))))
+ || (h->test.cmpfn
+ && hash_code == XUINT (HASH_HASH (h, i))
+ && h->test.cmpfn (&h->test, key, HASH_KEY (h, i))))
{
/* Take entry out of collision chain. */
if (NILP (prev))
@@ -3923,16 +3884,16 @@ hash_clear (struct Lisp_Hash_Table *h)
Weak Hash Tables
************************************************************************/
-/* Sweep weak hash table H. REMOVE_ENTRIES_P non-zero means remove
+/* Sweep weak hash table H. REMOVE_ENTRIES_P means remove
entries from the table that don't survive the current GC.
- REMOVE_ENTRIES_P zero means mark entries that are in use. Value is
- non-zero if anything was marked. */
+ !REMOVE_ENTRIES_P means mark entries that are in use. Value is
+ true if anything was marked. */
-static int
-sweep_weak_table (struct Lisp_Hash_Table *h, int remove_entries_p)
+static bool
+sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
{
ptrdiff_t bucket, n;
- int marked;
+ bool marked;
n = ASIZE (h->index) & ~ARRAY_MARK_FLAG;
marked = 0;
@@ -3949,7 +3910,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, int remove_entries_p)
ptrdiff_t i = XFASTINT (idx);
bool key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i));
bool value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i));
- int remove_p;
+ bool remove_p;
if (EQ (h->weak, Qkey))
remove_p = !key_known_to_survive_p;
@@ -3960,7 +3921,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, int remove_entries_p)
else if (EQ (h->weak, Qkey_and_value))
remove_p = !(key_known_to_survive_p && value_known_to_survive_p);
else
- abort ();
+ emacs_abort ();
next = HASH_NEXT (h, i);
@@ -4022,7 +3983,7 @@ void
sweep_weak_hash_tables (void)
{
struct Lisp_Hash_Table *h, *used, *next;
- int marked;
+ bool marked;
/* Mark all keys and values that are in use. Keep on marking until
there is no more change. This is necessary for cases like
@@ -4076,13 +4037,6 @@ sweep_weak_hash_tables (void)
#define SXHASH_MAX_LEN 7
-/* Combine two integers X and Y for hashing. The result might not fit
- into a Lisp integer. */
-
-#define SXHASH_COMBINE(X, Y) \
- ((((EMACS_UINT) (X) << 4) + ((EMACS_UINT) (X) >> (BITS_PER_EMACS_INT - 4))) \
- + (EMACS_UINT) (Y))
-
/* Hash X, returning a value that fits into a Lisp integer. */
#define SXHASH_REDUCE(X) \
((((X) ^ (X) >> (BITS_PER_EMACS_INT - FIXNUM_BITS))) & INTMASK)
@@ -4101,7 +4055,7 @@ hash_string (char const *ptr, ptrdiff_t len)
while (p != end)
{
c = *p++;
- hash = SXHASH_COMBINE (hash, c);
+ hash = sxhash_combine (hash, c);
}
return hash;
@@ -4135,7 +4089,7 @@ sxhash_float (double val)
u.val = val;
memset (&u.val + 1, 0, sizeof u - sizeof u.val);
for (i = 0; i < WORDS_PER_DOUBLE; i++)
- hash = SXHASH_COMBINE (hash, u.word[i]);
+ hash = sxhash_combine (hash, u.word[i]);
return SXHASH_REDUCE (hash);
}
@@ -4154,13 +4108,13 @@ sxhash_list (Lisp_Object list, int depth)
list = XCDR (list), ++i)
{
EMACS_UINT hash2 = sxhash (XCAR (list), depth + 1);
- hash = SXHASH_COMBINE (hash, hash2);
+ hash = sxhash_combine (hash, hash2);
}
if (!NILP (list))
{
EMACS_UINT hash2 = sxhash (list, depth + 1);
- hash = SXHASH_COMBINE (hash, hash2);
+ hash = sxhash_combine (hash, hash2);
}
return SXHASH_REDUCE (hash);
@@ -4180,7 +4134,7 @@ sxhash_vector (Lisp_Object vec, int depth)
for (i = 0; i < n; ++i)
{
EMACS_UINT hash2 = sxhash (AREF (vec, i), depth + 1);
- hash = SXHASH_COMBINE (hash, hash2);
+ hash = sxhash_combine (hash, hash2);
}
return SXHASH_REDUCE (hash);
@@ -4196,7 +4150,7 @@ sxhash_bool_vector (Lisp_Object vec)
n = min (SXHASH_MAX_LEN, XBOOL_VECTOR (vec)->header.size);
for (i = 0; i < n; ++i)
- hash = SXHASH_COMBINE (hash, XBOOL_VECTOR (vec)->data[i]);
+ hash = sxhash_combine (hash, XBOOL_VECTOR (vec)->data[i]);
return SXHASH_REDUCE (hash);
}
@@ -4220,7 +4174,7 @@ sxhash (Lisp_Object obj, int depth)
break;
case Lisp_Misc:
- hash = XUINT (obj);
+ hash = XHASH (obj);
break;
case Lisp_Symbol:
@@ -4244,7 +4198,7 @@ sxhash (Lisp_Object obj, int depth)
else
/* Others are `equal' if they are `eq', so let's take their
address as hash. */
- hash = XUINT (obj);
+ hash = XHASH (obj);
break;
case Lisp_Cons:
@@ -4256,7 +4210,7 @@ sxhash (Lisp_Object obj, int depth)
break;
default:
- abort ();
+ emacs_abort ();
}
return hash;
@@ -4313,7 +4267,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object test, size, rehash_size, rehash_threshold, weak;
- Lisp_Object user_test, user_hash;
+ struct hash_table_test testdesc;
char *used;
ptrdiff_t i;
@@ -4325,7 +4279,13 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
/* See if there's a `:test TEST' among the arguments. */
i = get_key_arg (QCtest, nargs, args, used);
test = i ? args[i] : Qeql;
- if (!EQ (test, Qeq) && !EQ (test, Qeql) && !EQ (test, Qequal))
+ if (EQ (test, Qeq))
+ testdesc = hashtest_eq;
+ else if (EQ (test, Qeql))
+ testdesc = hashtest_eql;
+ else if (EQ (test, Qequal))
+ testdesc = hashtest_equal;
+ else
{
/* See if it is a user-defined test. */
Lisp_Object prop;
@@ -4333,11 +4293,12 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
prop = Fget (test, Qhash_table_test);
if (!CONSP (prop) || !CONSP (XCDR (prop)))
signal_error ("Invalid hash table test", test);
- user_test = XCAR (prop);
- user_hash = XCAR (XCDR (prop));
+ testdesc.name = test;
+ testdesc.user_cmp_function = XCAR (prop);
+ testdesc.user_hash_function = XCAR (XCDR (prop));
+ testdesc.hashfn = hashfn_user_defined;
+ testdesc.cmpfn = cmpfn_user_defined;
}
- else
- user_test = user_hash = Qnil;
/* See if there's a `:size SIZE' argument. */
i = get_key_arg (QCsize, nargs, args, used);
@@ -4379,8 +4340,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
if (!used[i])
signal_error ("Invalid argument list", args[i]);
- return make_hash_table (test, size, rehash_size, rehash_threshold, weak,
- user_test, user_hash);
+ return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak);
}
@@ -4434,7 +4394,7 @@ DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
doc: /* Return the test TABLE uses. */)
(Lisp_Object table)
{
- return check_hash_table (table)->test;
+ return check_hash_table (table)->test.name;
}
@@ -4674,7 +4634,7 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_
coding_system = Vcoding_system_for_write;
else
{
- int force_raw_text = 0;
+ bool force_raw_text = 0;
coding_system = BVAR (XBUFFER (object), buffer_file_coding_system);
if (NILP (coding_system)
@@ -4998,4 +4958,14 @@ this variable. */);
defsubr (&Smd5);
defsubr (&Ssecure_hash);
defsubr (&Slocale_info);
+
+ {
+ struct hash_table_test
+ eq = { Qeq, Qnil, Qnil, NULL, hashfn_eq },
+ eql = { Qeql, Qnil, Qnil, cmpfn_eql, hashfn_eql },
+ equal = { Qequal, Qnil, Qnil, cmpfn_equal, hashfn_equal };
+ hashtest_eq = eq;
+ hashtest_eql = eql;
+ hashtest_equal = equal;
+ }
}
diff --git a/src/font.c b/src/font.c
index cf9964f08f3..f6b6fa026c0 100644
--- a/src/font.c
+++ b/src/font.c
@@ -23,7 +23,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <float.h>
#include <stdio.h>
-#include <setjmp.h>
#include <c-ctype.h>
@@ -216,13 +215,12 @@ static int num_font_drivers;
/* Return a Lispy value of a font property value at STR and LEN bytes.
- If STR is "*", return nil.
- If FORCE_SYMBOL is zero and all characters in STR are digits,
- return an integer. Otherwise, return a symbol interned from
- STR. */
+ If STR is "*", return nil. If FORCE_SYMBOL, or if STR does not
+ consist entirely of one or more digits, return a symbol interned
+ from STR. Otherwise, return an integer. */
Lisp_Object
-font_intern_prop (const char *str, ptrdiff_t len, int force_symbol)
+font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
{
ptrdiff_t i;
Lisp_Object tem;
@@ -306,7 +304,8 @@ font_pixel_size (FRAME_PTR f, Lisp_Object spec)
VAL is an integer. */
int
-font_style_to_value (enum font_property_index prop, Lisp_Object val, int noerror)
+font_style_to_value (enum font_property_index prop, Lisp_Object val,
+ bool noerror)
{
Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
int len;
@@ -385,7 +384,8 @@ font_style_to_value (enum font_property_index prop, Lisp_Object val, int noerror
}
Lisp_Object
-font_style_symbolic (Lisp_Object font, enum font_property_index prop, int for_face)
+font_style_symbolic (Lisp_Object font, enum font_property_index prop,
+ bool for_face)
{
Lisp_Object val = AREF (font, prop);
Lisp_Object table, elt;
@@ -1101,7 +1101,7 @@ font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font)
}
else
{
- int wild_card_found = 0;
+ bool wild_card_found = 0;
Lisp_Object prop[XLFD_LAST_INDEX];
if (FONT_ENTITY_P (font))
@@ -1234,8 +1234,21 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
f[j] = "*";
else
{
+ int c, k, l;
+ ptrdiff_t alloc;
+
val = SYMBOL_NAME (val);
- f[j] = SSDATA (val);
+ alloc = SBYTES (val) + 1;
+ if (nbytes <= alloc)
+ return -1;
+ f[j] = p = alloca (alloc);
+ /* Copy the name while excluding '-', '?', ',', and '"'. */
+ for (k = l = 0; k < alloc; k++)
+ {
+ c = SREF (val, k);
+ if (c != '-' && c != '?' && c != ',' && c != '"')
+ p[l++] = c;
+ }
}
}
@@ -1337,7 +1350,7 @@ font_parse_fcname (char *name, ptrdiff_t len, Lisp_Object font)
}
else if (*p == '-')
{
- int decimal = 0, size_found = 1;
+ bool decimal = 0, size_found = 1;
for (q = p + 1; *q && *q != ':'; q++)
if (! c_isdigit (*q))
{
@@ -1938,7 +1951,7 @@ generate_otf_features (Lisp_Object spec, char *features)
{
Lisp_Object val;
char *p;
- int asterisk;
+ bool asterisk;
p = features;
*p = '\0';
@@ -2302,11 +2315,12 @@ font_update_sort_order (int *order)
}
}
-static int
-font_check_otf_features (Lisp_Object script, Lisp_Object langsys, Lisp_Object features, Lisp_Object table)
+static bool
+font_check_otf_features (Lisp_Object script, Lisp_Object langsys,
+ Lisp_Object features, Lisp_Object table)
{
Lisp_Object val;
- int negative;
+ bool negative;
table = assq_no_quit (script, table);
if (NILP (table))
@@ -2342,7 +2356,7 @@ font_check_otf_features (Lisp_Object script, Lisp_Object langsys, Lisp_Object fe
/* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
-static int
+static bool
font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
{
Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
@@ -2376,7 +2390,7 @@ font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
/* Check if FONT (font-entity or font-object) matches with the font
specification SPEC. */
-int
+bool
font_match_p (Lisp_Object spec, Lisp_Object font)
{
Lisp_Object prop[FONT_SPEC_MAX], *props;
@@ -2694,7 +2708,7 @@ font_list_entities (Lisp_Object frame, Lisp_Object spec)
Lisp_Object ftype, val;
Lisp_Object list = Qnil;
int size;
- int need_filtering = 0;
+ bool need_filtering = 0;
int i;
eassert (FONT_SPEC_P (spec));
@@ -2815,14 +2829,11 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
Lisp_Object objlist, size, val, font_object;
struct font *font;
int min_width, height;
- int scaled_pixel_size = pixel_size;
eassert (FONT_ENTITY_P (entity));
size = AREF (entity, FONT_SIZE_INDEX);
if (XINT (size) != 0)
- scaled_pixel_size = pixel_size = XINT (size);
- else if (CONSP (Vface_font_rescale_alist))
- scaled_pixel_size = pixel_size * font_rescale_ratio (entity);
+ pixel_size = XINT (size);
val = AREF (entity, FONT_TYPE_INDEX);
for (driver_list = f->font_driver_list;
@@ -2844,7 +2855,7 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
}
}
- font_object = driver_list->driver->open (f, entity, scaled_pixel_size);
+ font_object = driver_list->driver->open (f, entity, pixel_size);
if (!NILP (font_object))
ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
FONT_ADD_LOG ("open", entity, font_object);
@@ -3036,15 +3047,14 @@ font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs,
{
Lisp_Object font_entity;
Lisp_Object prefer;
- int result, i;
+ int i;
FRAME_PTR f = XFRAME (frame);
if (NILP (XCDR (entities))
&& ASIZE (XCAR (entities)) == 1)
{
font_entity = AREF (XCAR (entities), 0);
- if (c < 0
- || (result = font_has_char (f, font_entity, c)) > 0)
+ if (c < 0 || font_has_char (f, font_entity, c) > 0)
return font_entity;
return Qnil;
}
@@ -3230,31 +3240,36 @@ font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_O
if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
&& XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
size = XINT (AREF (entity, FONT_SIZE_INDEX));
- else if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
- size = font_pixel_size (f, spec);
else
{
- double pt;
- if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
- pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
+ if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
+ size = font_pixel_size (f, spec);
else
{
- struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
- Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
- eassert (INTEGERP (height));
- pt = XINT (height);
- }
+ double pt;
+ if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
+ pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
+ else
+ {
+ struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+ Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
+ eassert (INTEGERP (height));
+ pt = XINT (height);
+ }
- pt /= 10;
- size = POINT_TO_PIXEL (pt, f->resy);
+ pt /= 10;
+ size = POINT_TO_PIXEL (pt, f->resy);
#ifdef HAVE_NS
- if (size == 0)
- {
- Lisp_Object ffsize = get_frame_param (f, Qfontsize);
- size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
- }
+ if (size == 0)
+ {
+ Lisp_Object ffsize = get_frame_param (f, Qfontsize);
+ size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
+ }
#endif
+ }
+ size *= font_rescale_ratio (entity);
}
+
return font_open_entity (f, entity, size);
}
@@ -3618,7 +3633,7 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
Lisp_Object string)
{
FRAME_PTR f;
- int multibyte;
+ bool multibyte;
Lisp_Object font_object;
multibyte = (NILP (string)
@@ -3991,16 +4006,11 @@ The optional argument FRAME specifies the frame that the face attributes
are to be displayed on. If omitted, the selected frame is used. */)
(Lisp_Object font, Lisp_Object frame)
{
- struct frame *f;
+ struct frame *f = decode_live_frame (frame);
Lisp_Object plist[10];
Lisp_Object val;
int n = 0;
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
-
if (STRINGP (font))
{
int fontset = fs_query_fontset (font, 0);
@@ -4150,18 +4160,15 @@ how close they are to PREFER. */)
DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
doc: /* List available font families on the current frame.
-Optional argument FRAME, if non-nil, specifies the target frame. */)
+If FRAME is omitted or nil, the selected frame is used. */)
(Lisp_Object frame)
{
- FRAME_PTR f;
+ struct frame *f = decode_live_frame (frame);
struct font_driver_list *driver_list;
- Lisp_Object list;
+ Lisp_Object list = Qnil;
+
+ XSETFRAME (frame, f);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
- list = Qnil;
for (driver_list = f->font_driver_list; driver_list;
driver_list = driver_list->next)
if (driver_list->driver->list_family)
@@ -4295,12 +4302,15 @@ to get the correct visual image of character sequences set in the
header of the glyph-string.
If the shaping was successful, the value is GSTRING itself or a newly
-created glyph-string. Otherwise, the value is nil. */)
+created glyph-string. Otherwise, the value is nil.
+
+See the documentation of `composition-get-gstring' for the format of
+GSTRING. */)
(Lisp_Object gstring)
{
struct font *font;
Lisp_Object font_object, n, glyph;
- ptrdiff_t i, j, from, to;
+ ptrdiff_t i, from, to;
if (! composition_gstring_p (gstring))
signal_error ("Invalid glyph-string: ", gstring);
@@ -4326,44 +4336,42 @@ created glyph-string. Otherwise, the value is nil. */)
if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
+ /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
+ GLYPHS covers all characters (except for the last few ones) in
+ GSTRING. More formally, provided that NCHARS is the number of
+ characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
+ and TO_IDX of each glyph must satisfy these conditions:
+
+ GLYPHS[0].FROM_IDX == 0
+ GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
+ if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
+ ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
+ GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
+ else
+ ;; Be sure to cover all characters.
+ GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
glyph = LGSTRING_GLYPH (gstring, 0);
from = LGLYPH_FROM (glyph);
to = LGLYPH_TO (glyph);
- for (i = 1, j = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
+ if (from != 0 || to < from)
+ goto shaper_error;
+ for (i = 1; i < LGSTRING_GLYPH_LEN (gstring); i++)
{
- Lisp_Object this = LGSTRING_GLYPH (gstring, i);
-
- if (NILP (this))
+ glyph = LGSTRING_GLYPH (gstring, i);
+ if (NILP (glyph))
break;
- if (NILP (LGLYPH_ADJUSTMENT (this)))
- {
- if (j < i - 1)
- for (; j < i; j++)
- {
- glyph = LGSTRING_GLYPH (gstring, j);
- LGLYPH_SET_FROM (glyph, from);
- LGLYPH_SET_TO (glyph, to);
- }
- from = LGLYPH_FROM (this);
- to = LGLYPH_TO (this);
- j = i;
- }
- else
- {
- if (from > LGLYPH_FROM (this))
- from = LGLYPH_FROM (this);
- if (to < LGLYPH_TO (this))
- to = LGLYPH_TO (this);
- }
+ if (! (LGLYPH_FROM (glyph) <= LGLYPH_TO (glyph)
+ && (LGLYPH_FROM (glyph) == from
+ ? LGLYPH_TO (glyph) == to
+ : LGLYPH_FROM (glyph) == to + 1)))
+ goto shaper_error;
+ from = LGLYPH_FROM (glyph);
+ to = LGLYPH_TO (glyph);
}
- if (j < i - 1)
- for (; j < i; j++)
- {
- glyph = LGSTRING_GLYPH (gstring, j);
- LGLYPH_SET_FROM (glyph, from);
- LGLYPH_SET_TO (glyph, to);
- }
return composition_gstring_put_cache (gstring, XINT (n));
+
+ shaper_error:
+ return Qnil;
}
DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
@@ -4528,11 +4536,9 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
(Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
{
EMACS_INT isize;
+ struct frame *f = decode_live_frame (frame);
CHECK_FONT_ENTITY (font_entity);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
if (NILP (size))
isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
@@ -4540,7 +4546,7 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
{
CHECK_NUMBER_OR_FLOAT (size);
if (FLOATP (size))
- isize = POINT_TO_PIXEL (XFLOAT_DATA (size), XFRAME (frame)->resy);
+ isize = POINT_TO_PIXEL (XFLOAT_DATA (size), f->resy);
else
isize = XINT (size);
if (! (INT_MIN <= isize && isize <= INT_MAX))
@@ -4548,7 +4554,7 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
if (isize == 0)
isize = 120;
}
- return font_open_entity (XFRAME (frame), font_entity, isize);
+ return font_open_entity (f, font_entity, isize);
}
DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
@@ -4556,10 +4562,7 @@ DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
(Lisp_Object font_object, Lisp_Object frame)
{
CHECK_FONT_OBJECT (font_object);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- font_close_object (XFRAME (frame), font_object);
+ font_close_object (decode_live_frame (frame), font_object);
return Qnil;
}
@@ -4757,33 +4760,30 @@ FONT is a font-spec, font-entity, or font-object. */)
DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
doc: /* Return a font-object for displaying a character at POSITION.
Optional second arg WINDOW, if non-nil, is a window displaying
-the current buffer. It defaults to the currently selected window. */)
+the current buffer. It defaults to the currently selected window.
+Optional third arg STRING, if non-nil, is a string containing the target
+character at index specified by POSITION. */)
(Lisp_Object position, Lisp_Object window, Lisp_Object string)
{
- struct window *w;
- ptrdiff_t pos;
+ struct window *w = decode_live_window (window);
if (NILP (string))
{
+ if (XBUFFER (w->buffer) != current_buffer)
+ error ("Specified window is not displaying the current buffer.");
CHECK_NUMBER_COERCE_MARKER (position);
if (! (BEGV <= XINT (position) && XINT (position) < ZV))
args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
- pos = XINT (position);
}
else
{
CHECK_NUMBER (position);
CHECK_STRING (string);
- if (! (0 < XINT (position) && XINT (position) < SCHARS (string)))
+ if (! (0 <= XINT (position) && XINT (position) < SCHARS (string)))
args_out_of_range (string, position);
- pos = XINT (position);
}
- if (NILP (window))
- window = selected_window;
- CHECK_LIVE_WINDOW (window);
- w = XWINDOW (window);
- return font_at (-1, pos, NULL, w, string);
+ return font_at (-1, XINT (position), NULL, w, string);
}
#if 0
@@ -4847,7 +4847,7 @@ where
If the named font is not yet loaded, return nil. */)
(Lisp_Object name, Lisp_Object frame)
{
- FRAME_PTR f;
+ struct frame *f;
struct font *font;
Lisp_Object info;
Lisp_Object font_object;
@@ -4856,10 +4856,7 @@ If the named font is not yet loaded, return nil. */)
if (! FONTP (name))
CHECK_STRING (name);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
+ f = decode_live_frame (frame);
if (STRINGP (name))
{
@@ -5207,9 +5204,9 @@ EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
#ifdef HAVE_BDFFONT
syms_of_bdffont ();
#endif /* HAVE_BDFFONT */
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
syms_of_w32font ();
-#endif /* WINDOWSNT */
+#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
syms_of_nsfont ();
#endif /* HAVE_NS */
diff --git a/src/font.h b/src/font.h
index 3b90bc2ab8a..3035a909efc 100644
--- a/src/font.h
+++ b/src/font.h
@@ -23,6 +23,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define EMACS_FONT_H
#include "ccl.h"
+#include "frame.h"
/* We have three types of Lisp objects related to font.
@@ -320,19 +321,10 @@ struct font
negative if that information is not in the font. */
int underline_position;
- /* 1 if `vertical-centering-font-regexp' matches this font name.
+ /* True if `vertical-centering-font-regexp' matches this font name.
In this case, we render characters at vertical center positions
of lines. */
- int vertical_centering;
-
- /* Encoding type of the font. The value is one of
- 0, 1, 2, or 3:
- 0: code points 0x20..0x7F or 0x2020..0x7F7F are used
- 1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used
- 2: code points 0x20A0..0x7FFF are used
- 3: code points 0xA020..0xFF7F are used
- If the member `font_encoder' is not NULL, this member is ignored. */
- unsigned char encoding_type;
+ bool vertical_centering;
/* The baseline position of a font is normally `ascent' value of the
font. However, there exist many fonts which don't set `ascent' to
@@ -506,9 +498,9 @@ struct font_driver
/* Symbol indicating the type of the font-driver. */
Lisp_Object type;
- /* 1 iff the font's foundry, family, and adstyle names are case
+ /* True iff the font's foundry, family, and adstyle names are case
sensitive. */
- int case_sensitive;
+ bool case_sensitive;
/* Return a cache of font-entities on frame F. The cache must be a
cons whose cdr part is the actual cache area. */
@@ -592,11 +584,11 @@ struct font_driver
/* Optional.
Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
- position of frame F with S->FACE and S->GC. If WITH_BACKGROUND
- is nonzero, fill the background in advance. It is assured that
- WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars). */
+ position of frame F with S->FACE and S->GC. If WITH_BACKGROUND,
+ fill the background in advance. It is assured that WITH_BACKGROUND
+ is false when (FROM > 0 || TO < S->nchars). */
int (*draw) (struct glyph_string *s, int from, int to,
- int x, int y, int with_background);
+ int x, int y, bool with_background);
/* Optional.
Store bitmap data for glyph-code CODE of FONT in BITMAP. It is
@@ -648,7 +640,7 @@ struct font_driver
short, return -1. */
int (*otf_drive) (struct font *font, Lisp_Object features,
Lisp_Object gstring_in, int from, int to,
- Lisp_Object gstring_out, int idx, int alternate_subst);
+ Lisp_Object gstring_out, int idx, bool alternate_subst);
/* Optional.
Make the font driver ready for frame F. Usually this function
@@ -699,9 +691,9 @@ struct font_driver
Return non-zero if FONT_OBJECT can be used as a (cached) font
for ENTITY on frame F. */
- int (*cached_font_ok) (struct frame *f,
- Lisp_Object font_object,
- Lisp_Object entity);
+ bool (*cached_font_ok) (struct frame *f,
+ Lisp_Object font_object,
+ Lisp_Object entity);
};
@@ -711,9 +703,9 @@ struct font_driver
struct font_driver_list
{
- /* 1 iff this driver is currently used. It is ignored in the global
+ /* True iff this driver is currently used. It is ignored in the global
font driver list.*/
- int on;
+ bool on;
/* Pointer to the font driver. */
struct font_driver *driver;
/* Pointer to the next element of the chain. */
@@ -744,12 +736,12 @@ extern Lisp_Object find_font_encoding (Lisp_Object);
extern int font_registry_charsets (Lisp_Object, struct charset **,
struct charset **);
extern int font_style_to_value (enum font_property_index prop,
- Lisp_Object name, int noerror);
+ Lisp_Object name, bool noerror);
extern Lisp_Object font_style_symbolic (Lisp_Object font,
enum font_property_index prop,
- int for_face);
+ bool for_face);
-extern int font_match_p (Lisp_Object spec, Lisp_Object font);
+extern bool font_match_p (Lisp_Object spec, Lisp_Object font);
extern Lisp_Object font_list_entities (Lisp_Object frame,
Lisp_Object spec);
@@ -774,7 +766,7 @@ extern Lisp_Object font_open_by_spec (FRAME_PTR f, Lisp_Object spec);
extern Lisp_Object font_open_by_name (FRAME_PTR f, Lisp_Object name);
extern Lisp_Object font_intern_prop (const char *str, ptrdiff_t len,
- int force_symbol);
+ bool force_symbol);
extern void font_update_sort_order (int *order);
extern void font_parse_family_registry (Lisp_Object family,
@@ -827,11 +819,11 @@ extern struct font_driver ftxfont_driver;
extern void syms_of_bdffont (void);
#endif /* HAVE_BDFFONT */
#endif /* HAVE_X_WINDOWS */
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
extern struct font_driver w32font_driver;
extern struct font_driver uniscribe_font_driver;
extern void syms_of_w32font (void);
-#endif /* WINDOWSNT */
+#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
extern Lisp_Object Qfontsize;
extern struct font_driver nsfont_driver;
diff --git a/src/fontset.c b/src/fontset.c
index 01e38fe45e5..660ca432fad 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -26,7 +26,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "blockinput.h"
@@ -43,7 +42,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
#include "w32term.h"
#endif
#ifdef HAVE_NS
@@ -185,21 +184,12 @@ void (*check_window_system_func) (void);
/* Prototype declarations for static functions. */
-static void fontset_add (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-static Lisp_Object fontset_find_font (Lisp_Object, int, struct face *,
- int, int);
-static void reorder_font_vector (Lisp_Object, struct font *);
-static Lisp_Object fontset_font (Lisp_Object, int, struct face *, int);
static Lisp_Object make_fontset (Lisp_Object, Lisp_Object, Lisp_Object);
-static Lisp_Object fontset_pattern_regexp (Lisp_Object);
-static void accumulate_script_ranges (Lisp_Object, Lisp_Object,
- Lisp_Object);
-static void set_fontset_font (Lisp_Object, Lisp_Object);
-/* Return 1 if ID is a valid fontset id, else return 0.
+/* Return true if ID is a valid fontset id.
Optimized away if ENABLE_CHECKING is not defined. */
-static int
+static bool
fontset_id_valid_p (int id)
{
return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
@@ -413,7 +403,7 @@ reorder_font_vector (Lisp_Object font_group, struct font *font)
Lisp_Object vec, font_object;
int size;
int i;
- int score_changed = 0;
+ bool score_changed = 0;
if (font)
XSETFONT (font_object, font);
@@ -544,10 +534,11 @@ fontset_get_font_group (Lisp_Object fontset, int c)
ID is a charset-id that must be preferred, or -1 meaning no
preference.
- If FALLBACK is nonzero, search only fallback fonts. */
+ If FALLBACK, search only fallback fonts. */
static Lisp_Object
-fontset_find_font (Lisp_Object fontset, int c, struct face *face, int id, int fallback)
+fontset_find_font (Lisp_Object fontset, int c, struct face *face, int id,
+ bool fallback)
{
Lisp_Object vec, font_group;
int i, charset_matched = 0, found_index;
@@ -919,11 +910,11 @@ free_face_fontset (FRAME_PTR f, struct face *face)
#if 0
-/* Return 1 if FACE is suitable for displaying character C.
- Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
+/* Return true if FACE is suitable for displaying character C.
+ Called from the macro FACE_SUITABLE_FOR_CHAR_P
when C is not an ASCII character. */
-int
+bool
face_suitable_for_char_p (struct face *face, int c)
{
Lisp_Object fontset, rfont_def;
@@ -1284,7 +1275,7 @@ free_realized_fontsets (Lisp_Object base)
doesn't remove FACE from a cache. Until we find a solution, we
suppress this code, and simply use Fclear_face_cache even though
that is not efficient. */
- BLOCK_INPUT;
+ block_input ();
for (id = 0; id < ASIZE (Vfontset_table); id++)
{
Lisp_Object this = AREF (Vfontset_table, id);
@@ -1305,7 +1296,7 @@ free_realized_fontsets (Lisp_Object base)
}
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
#else /* not 0 */
/* But, we don't have to call Fclear_face_cache if no fontset has
been realized from BASE. */
@@ -1335,17 +1326,14 @@ static Lisp_Object
check_fontset_name (Lisp_Object name, Lisp_Object *frame)
{
int id;
+ struct frame *f = decode_live_frame (*frame);
- if (NILP (*frame))
- *frame = selected_frame;
- CHECK_LIVE_FRAME (*frame);
+ XSETFRAME (*frame, f);
if (EQ (name, Qt))
return Vdefault_fontset;
if (NILP (name))
- {
- id = FRAME_FONTSET (XFRAME (*frame));
- }
+ id = FRAME_FONTSET (f);
else
{
CHECK_STRING (name);
@@ -1470,7 +1458,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
Lisp_Object range_list;
struct charset *charset = NULL;
Lisp_Object fontname;
- int ascii_changed = 0;
+ bool ascii_changed = 0;
fontset = check_fontset_name (name, &frame);
@@ -1888,6 +1876,8 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
}
if (! CHAR_VALID_P (c))
return Qnil;
+ if (!FRAME_WINDOW_P (f))
+ return Qnil;
face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
face = FACE_FROM_ID (f, face_id);
if (face->font)
diff --git a/src/frame.c b/src/frame.c
index 968cb4905a2..5cefad6ca46 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -24,7 +24,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <errno.h>
#include <limits.h>
-#include <setjmp.h>
#include <c-ctype.h>
@@ -121,18 +120,35 @@ static void x_report_frame_params (struct frame *, Lisp_Object *);
#endif
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
fset_buffer_predicate (struct frame *f, Lisp_Object val)
{
f->buffer_predicate = val;
}
-static inline void
+static void
fset_minibuffer_window (struct frame *f, Lisp_Object val)
{
f->minibuffer_window = val;
}
-
+struct frame *
+decode_live_frame (register Lisp_Object frame)
+{
+ if (NILP (frame))
+ frame = selected_frame;
+ CHECK_LIVE_FRAME (frame);
+ return XFRAME (frame);
+}
+
+struct frame *
+decode_any_frame (register Lisp_Object frame)
+{
+ if (NILP (frame))
+ frame = selected_frame;
+ CHECK_FRAME (frame);
+ return XFRAME (frame);
+}
+
static void
set_menu_bar_lines_1 (Lisp_Object window, int n)
{
@@ -214,7 +230,7 @@ See also `frame-live-p'. */)
case output_ns:
return Qns;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -330,13 +346,10 @@ make_frame (int mini_p)
/* Choose a buffer for the frame's root window. */
{
- Lisp_Object buf;
+ Lisp_Object buf = Fcurrent_buffer ();
- wset_buffer (XWINDOW (root_window), Qt);
- buf = Fcurrent_buffer ();
- /* If buf is a 'hidden' buffer (i.e. one whose name starts with
- a space), try to find another one. */
- if (SREF (Fbuffer_name (buf), 0) == ' ')
+ /* If current buffer is hidden, try to find another one. */
+ if (BUFFER_HIDDEN_P (XBUFFER (buf)))
buf = other_buffer_safely (buf);
/* Use set_window_buffer, not Fset_window_buffer, and don't let
@@ -350,14 +363,11 @@ make_frame (int mini_p)
}
if (mini_p)
- {
- wset_buffer (XWINDOW (mini_window), Qt);
- 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);
fset_root_window (f, root_window);
fset_selected_window (f, root_window);
@@ -503,7 +513,6 @@ make_initial_frame (void)
FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
/* The default value of menu-bar-mode is t. */
@@ -552,7 +561,6 @@ make_terminal_frame (struct terminal *terminal)
FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
#endif /* not MSDOS */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
FRAME_MENU_BAR_LINES(f) = NILP (Vmenu_bar_mode) ? 0 : 1;
@@ -620,7 +628,7 @@ affects all frames on the same terminal device. */)
#ifdef MSDOS
if (sf->output_method != output_msdos_raw
&& sf->output_method != output_termcap)
- abort ();
+ emacs_abort ();
#else /* not MSDOS */
#ifdef WINDOWSNT /* This should work now! */
@@ -633,7 +641,7 @@ affects all frames on the same terminal device. */)
Lisp_Object terminal;
terminal = Fassq (Qterminal, parms);
- if (!NILP (terminal))
+ if (CONSP (terminal))
{
terminal = XCDR (terminal);
t = get_terminal (terminal, 1);
@@ -767,7 +775,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
Lisp_Object focus;
if (!FRAMEP (XCAR (tail)))
- abort ();
+ emacs_abort ();
focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
@@ -881,150 +889,100 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
return frames;
}
-/* Return the next frame in the frame list after FRAME.
- If MINIBUF is nil, exclude minibuffer-only frames.
- If MINIBUF is a window, include only its own frame
- and any frame now using that window as the minibuffer.
- If MINIBUF is `visible', include all visible frames.
- If MINIBUF is 0, include all visible and iconified frames.
- Otherwise, include all frames. */
+/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
+ same tty (for tty frames) or among frames which uses FRAME's keyboard.
+ If MINIBUF is nil, do not consider minibuffer-only candidate.
+ If MINIBUF is `visible', do not consider an invisible candidate.
+ If MINIBUF is a window, consider only its own frame and candidate now
+ using that window as the minibuffer.
+ If MINIBUF is 0, consider candidate if it is visible or iconified.
+ Otherwise consider any candidate and return nil if CANDIDATE is not
+ acceptable. */
+
+static Lisp_Object
+candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
+{
+ struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
+
+ if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
+ && FRAME_KBOARD (c) == FRAME_KBOARD (f))
+ || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
+ && FRAME_TTY (c) == FRAME_TTY (f)))
+ {
+ if (NILP (minibuf))
+ {
+ if (!FRAME_MINIBUF_ONLY_P (c))
+ return candidate;
+ }
+ else if (EQ (minibuf, Qvisible))
+ {
+ FRAME_SAMPLE_VISIBILITY (c);
+ if (FRAME_VISIBLE_P (c))
+ return candidate;
+ }
+ else if (WINDOWP (minibuf))
+ {
+ if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
+ || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
+ || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
+ FRAME_FOCUS_FRAME (c)))
+ return candidate;
+ }
+ else if (XFASTINT (minibuf) == 0)
+ {
+ FRAME_SAMPLE_VISIBILITY (c);
+ if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
+ return candidate;
+ }
+ else
+ return candidate;
+ }
+ return Qnil;
+}
+
+/* Return the next frame in the frame list after FRAME. */
static Lisp_Object
next_frame (Lisp_Object frame, Lisp_Object minibuf)
{
- Lisp_Object tail;
+ Lisp_Object f, tail;
int passed = 0;
/* There must always be at least one frame in Vframe_list. */
- if (! CONSP (Vframe_list))
- abort ();
+ eassert (CONSP (Vframe_list));
- /* If this frame is dead, it won't be in Vframe_list, and we'll loop
- forever. Forestall that. */
- CHECK_LIVE_FRAME (frame);
-
- while (1)
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ while (passed < 2)
+ FOR_EACH_FRAME (tail, f)
{
- Lisp_Object f;
-
- f = XCAR (tail);
-
- if (passed
- && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
- && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
- || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
- && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
+ if (passed)
{
- /* Decide whether this frame is eligible to be returned. */
-
- /* If we've looped all the way around without finding any
- eligible frames, return the original frame. */
- if (EQ (f, frame))
- return f;
-
- /* Let minibuf decide if this frame is acceptable. */
- if (NILP (minibuf))
- {
- if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
- return f;
- }
- else if (EQ (minibuf, Qvisible))
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f)))
- return f;
- }
- else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f))
- || FRAME_ICONIFIED_P (XFRAME (f)))
- return f;
- }
- else if (WINDOWP (minibuf))
- {
- if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
- || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
- || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
- FRAME_FOCUS_FRAME (XFRAME (f))))
- return f;
- }
- else
+ f = candidate_frame (f, frame, minibuf);
+ if (!NILP (f))
return f;
}
-
if (EQ (frame, f))
passed++;
}
+ return frame;
}
-/* Return the previous frame in the frame list before FRAME.
- If MINIBUF is nil, exclude minibuffer-only frames.
- If MINIBUF is a window, include only its own frame
- and any frame now using that window as the minibuffer.
- If MINIBUF is `visible', include all visible frames.
- If MINIBUF is 0, include all visible and iconified frames.
- Otherwise, include all frames. */
+/* Return the previous frame in the frame list before FRAME. */
static Lisp_Object
prev_frame (Lisp_Object frame, Lisp_Object minibuf)
{
- Lisp_Object tail;
- Lisp_Object prev;
+ Lisp_Object f, tail, prev = Qnil;
/* There must always be at least one frame in Vframe_list. */
- if (! CONSP (Vframe_list))
- abort ();
+ eassert (CONSP (Vframe_list));
- prev = Qnil;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, f)
{
- Lisp_Object f;
-
- f = XCAR (tail);
- if (!FRAMEP (f))
- abort ();
-
if (EQ (frame, f) && !NILP (prev))
return prev;
-
- if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
- && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
- || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
- && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
- {
- /* Decide whether this frame is eligible to be returned,
- according to minibuf. */
- if (NILP (minibuf))
- {
- if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
- prev = f;
- }
- else if (WINDOWP (minibuf))
- {
- if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
- || EQ (WINDOW_FRAME (XWINDOW (minibuf)), f)
- || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
- FRAME_FOCUS_FRAME (XFRAME (f))))
- prev = f;
- }
- else if (EQ (minibuf, Qvisible))
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f)))
- prev = f;
- }
- else if (XFASTINT (minibuf) == 0)
- {
- FRAME_SAMPLE_VISIBILITY (XFRAME (f));
- if (FRAME_VISIBLE_P (XFRAME (f))
- || FRAME_ICONIFIED_P (XFRAME (f)))
- prev = f;
- }
- else
- prev = f;
- }
+ f = candidate_frame (f, frame, minibuf);
+ if (!NILP (f))
+ prev = f;
}
/* We've scanned the entire list. */
@@ -1055,7 +1013,6 @@ Otherwise, include all frames. */)
{
if (NILP (frame))
frame = selected_frame;
-
CHECK_LIVE_FRAME (frame);
return next_frame (frame, miniframe);
}
@@ -1086,11 +1043,10 @@ Otherwise, include all frames. */)
static int
other_visible_frames (FRAME_PTR f)
{
- Lisp_Object frames;
+ Lisp_Object frames, this;
- for (frames = Vframe_list; CONSP (frames); frames = XCDR (frames))
+ FOR_EACH_FRAME (frames, this)
{
- Lisp_Object this = XCAR (frames);
if (f == XFRAME (this))
continue;
@@ -1121,22 +1077,11 @@ other_visible_frames (FRAME_PTR f)
Lisp_Object
delete_frame (Lisp_Object frame, Lisp_Object force)
{
- struct frame *f;
+ struct frame *f = decode_any_frame (frame);
struct frame *sf = SELECTED_FRAME ();
struct kboard *kb;
- int minibuffer_selected, tooltip_frame;
-
- if (EQ (frame, Qnil))
- {
- f = sf;
- XSETFRAME (frame, f);
- }
- else
- {
- CHECK_FRAME (frame);
- f = XFRAME (frame);
- }
+ int minibuffer_selected, is_tooltip_frame;
if (! FRAME_LIVE_P (f))
return Qnil;
@@ -1149,19 +1094,16 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
error ("Attempt to delete the only frame");
+ XSETFRAME (frame, f);
+
/* Does this frame have a minibuffer, and is it the surrogate
minibuffer for any other frame? */
- if (FRAME_HAS_MINIBUF_P (XFRAME (frame)))
+ if (FRAME_HAS_MINIBUF_P (f))
{
- Lisp_Object frames;
+ Lisp_Object frames, this;
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCDR (frames))
+ FOR_EACH_FRAME (frames, this)
{
- Lisp_Object this;
- this = XCAR (frames);
-
if (! EQ (this, frame)
&& EQ (frame,
WINDOW_FRAME (XWINDOW
@@ -1177,13 +1119,13 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
}
}
- tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
+ is_tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
/* Run `delete-frame-functions' unless FORCE is `noelisp' or
frame is a tooltip. FORCE is set to `noelisp' when handling
a disconnect from the terminal, so we don't dare call Lisp
code. */
- if (NILP (Vrun_hooks) || tooltip_frame)
+ if (NILP (Vrun_hooks) || is_tooltip_frame)
;
else if (EQ (force, Qnoelisp))
pending_funcalls
@@ -1299,6 +1241,11 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
structures can still refer to it. */
fset_menu_bar_vector (f, Qnil);
+ /* If FRAME's buffer lists contains killed
+ buffers, this helps GC to reclaim them. */
+ fset_buffer_list (f, Qnil);
+ fset_buried_buffer_list (f, Qnil);
+
free_font_driver_list (f);
xfree (f->namebuf);
xfree (f->decode_mode_spec_buffer);
@@ -1349,15 +1296,13 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
another one. */
if (f == last_nonminibuf_frame)
{
- Lisp_Object frames;
+ Lisp_Object frames, this;
last_nonminibuf_frame = 0;
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCDR (frames))
+ FOR_EACH_FRAME (frames, this)
{
- f = XFRAME (XCAR (frames));
+ f = XFRAME (this);
if (!FRAME_MINIBUF_ONLY_P (f))
{
last_nonminibuf_frame = f;
@@ -1370,27 +1315,13 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
single-kboard state if we're in it for this kboard. */
if (kb != NULL)
{
- Lisp_Object frames;
+ Lisp_Object frames, this;
/* Some frame we found on the same kboard, or nil if there are none. */
- Lisp_Object frame_on_same_kboard;
-
- frame_on_same_kboard = Qnil;
-
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCDR (frames))
- {
- Lisp_Object this;
- struct frame *f1;
-
- this = XCAR (frames);
- if (!FRAMEP (this))
- abort ();
- f1 = XFRAME (this);
+ Lisp_Object frame_on_same_kboard = Qnil;
- if (kb == FRAME_KBOARD (f1))
- frame_on_same_kboard = this;
- }
+ FOR_EACH_FRAME (frames, this)
+ if (kb == FRAME_KBOARD (XFRAME (this)))
+ frame_on_same_kboard = this;
if (NILP (frame_on_same_kboard))
not_single_kboard_state (kb);
@@ -1402,27 +1333,16 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
frames with other windows. */
if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
{
- Lisp_Object frames;
+ Lisp_Object frames, this;
/* The last frame we saw with a minibuffer, minibuffer-only or not. */
- Lisp_Object frame_with_minibuf;
+ Lisp_Object frame_with_minibuf = Qnil;
/* Some frame we found on the same kboard, or nil if there are none. */
- Lisp_Object frame_on_same_kboard;
-
- frame_on_same_kboard = Qnil;
- frame_with_minibuf = Qnil;
+ Lisp_Object frame_on_same_kboard = Qnil;
- for (frames = Vframe_list;
- CONSP (frames);
- frames = XCDR (frames))
+ FOR_EACH_FRAME (frames, this)
{
- Lisp_Object this;
- struct frame *f1;
-
- this = XCAR (frames);
- if (!FRAMEP (this))
- abort ();
- f1 = XFRAME (this);
+ struct frame *f1 = XFRAME (this);
/* Consider only frames on the same kboard
and only those with minibuffers. */
@@ -1447,7 +1367,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
that is prohibited at the top; you can't delete surrogate
minibuffer frames. */
if (NILP (frame_with_minibuf))
- abort ();
+ emacs_abort ();
kset_default_minibuffer_frame (kb, frame_with_minibuf);
}
@@ -1457,7 +1377,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
}
/* Cause frame titles to update--necessary if we now have just one frame. */
- if (!tooltip_frame)
+ if (!is_tooltip_frame)
update_mode_lines = 1;
return Qnil;
@@ -1497,31 +1417,31 @@ and returns whatever that function returns. */)
{
FRAME_PTR f;
Lisp_Object lispy_dummy;
- enum scroll_bar_part party_dummy;
Lisp_Object x, y, retval;
- int col, row;
- Time long_dummy;
struct gcpro gcpro1;
f = SELECTED_FRAME ();
x = y = Qnil;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
/* It's okay for the hook to refrain from storing anything. */
if (FRAME_TERMINAL (f)->mouse_position_hook)
- (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
- &lispy_dummy, &party_dummy,
- &x, &y,
- &long_dummy);
+ {
+ enum scroll_bar_part party_dummy;
+ Time time_dummy;
+ (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
+ &lispy_dummy, &party_dummy,
+ &x, &y,
+ &time_dummy);
+ }
+
if (! NILP (x))
{
- col = XINT (x);
- row = XINT (y);
+ int col = XINT (x);
+ int row = XINT (y);
pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
XSETINT (x, col);
XSETINT (y, row);
}
-#endif
XSETFRAME (lispy_dummy, f);
retval = Fcons (lispy_dummy, Fcons (x, y));
GCPRO1 (retval);
@@ -1543,21 +1463,22 @@ and nil for X and Y. */)
{
FRAME_PTR f;
Lisp_Object lispy_dummy;
- enum scroll_bar_part party_dummy;
Lisp_Object x, y;
- Time long_dummy;
f = SELECTED_FRAME ();
x = y = Qnil;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
/* It's okay for the hook to refrain from storing anything. */
if (FRAME_TERMINAL (f)->mouse_position_hook)
- (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
- &lispy_dummy, &party_dummy,
- &x, &y,
- &long_dummy);
-#endif
+ {
+ enum scroll_bar_part party_dummy;
+ Time time_dummy;
+ (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
+ &lispy_dummy, &party_dummy,
+ &x, &y,
+ &time_dummy);
+ }
+
XSETFRAME (lispy_dummy, f);
return Fcons (lispy_dummy, Fcons (x, y));
}
@@ -1588,7 +1509,7 @@ before calling this function on it, like this.
/* Warping the mouse will cause enternotify and focus events. */
x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
#else
-#if defined (MSDOS) && defined (HAVE_MOUSE)
+#if defined (MSDOS)
if (FRAME_MSDOS_P (XFRAME (frame)))
{
Fselect_frame (frame, Qnil);
@@ -1629,7 +1550,7 @@ before calling this function on it, like this.
/* Warping the mouse will cause enternotify and focus events. */
x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
#else
-#if defined (MSDOS) && defined (HAVE_MOUSE)
+#if defined (MSDOS)
if (FRAME_MSDOS_P (XFRAME (frame)))
{
Fselect_frame (frame, Qnil);
@@ -1656,25 +1577,23 @@ DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
If omitted, FRAME defaults to the currently selected frame. */)
(Lisp_Object frame)
{
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_LIVE_FRAME (frame);
+ struct frame *f = decode_live_frame (frame);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
+ if (FRAME_WINDOW_P (f))
{
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
- x_make_frame_visible (XFRAME (frame));
+ FRAME_SAMPLE_VISIBILITY (f);
+ x_make_frame_visible (f);
}
#endif
- make_frame_visible_1 (XFRAME (frame)->root_window);
+ make_frame_visible_1 (f->root_window);
/* Make menu bar update for the Buffers and Frames menus. */
windows_or_buffers_changed++;
+ XSETFRAME (frame, f);
return frame;
}
@@ -1715,16 +1634,13 @@ always considered visible, whether or not they are currently being
displayed in the terminal. */)
(Lisp_Object frame, Lisp_Object force)
{
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_LIVE_FRAME (frame);
+ struct frame *f = decode_live_frame (frame);
- if (NILP (force) && !other_visible_frames (XFRAME (frame)))
+ if (NILP (force) && !other_visible_frames (f))
error ("Attempt to make invisible the sole visible or iconified frame");
/* Don't allow minibuf_window to remain on a deleted frame. */
- if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
+ if (EQ (f->minibuffer_window, minibuf_window))
{
struct frame *sf = XFRAME (selected_frame);
/* Use set_window_buffer instead of Fset_window_buffer (see
@@ -1736,8 +1652,8 @@ displayed in the terminal. */)
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- x_make_frame_invisible (XFRAME (frame));
+ if (FRAME_WINDOW_P (f))
+ x_make_frame_invisible (f);
#endif
/* Make menu bar update for the Buffers and Frames menus. */
@@ -1752,19 +1668,10 @@ DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
If omitted, FRAME defaults to the currently selected frame. */)
(Lisp_Object frame)
{
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_LIVE_FRAME (frame);
-
-#if 0 /* This isn't logically necessary, and it can do GC. */
- /* Don't let the frame remain selected. */
- if (EQ (frame, selected_frame))
- Fhandle_switch_frame (next_frame (frame, Qt));
-#endif
+ struct frame *f = decode_live_frame (frame);
/* Don't allow minibuf_window to remain on an iconified frame. */
- if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
+ if (EQ (f->minibuffer_window, minibuf_window))
{
struct frame *sf = XFRAME (selected_frame);
/* Use set_window_buffer instead of Fset_window_buffer (see
@@ -1776,8 +1683,8 @@ If omitted, FRAME defaults to the currently selected frame. */)
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (XFRAME (frame)))
- x_iconify_frame (XFRAME (frame));
+ if (FRAME_WINDOW_P (f))
+ x_iconify_frame (f);
#endif
/* Make menu bar update for the Buffers and Frames menus. */
@@ -1815,20 +1722,12 @@ DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
doc: /* Return a list of all frames now \"visible\" (being updated). */)
(void)
{
- Lisp_Object tail, frame;
- struct frame *f;
- Lisp_Object value;
+ Lisp_Object tail, frame, value = Qnil;
+
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_VISIBLE_P (XFRAME (frame)))
+ value = Fcons (frame, value);
- value = Qnil;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (FRAME_VISIBLE_P (f))
- value = Fcons (frame, value);
- }
return value;
}
@@ -1841,13 +1740,9 @@ If Emacs is displaying on an ordinary terminal or some other device which
doesn't support multiple overlapping frames, this function selects FRAME. */)
(Lisp_Object frame)
{
- struct frame *f;
- if (NILP (frame))
- frame = selected_frame;
+ struct frame *f = decode_live_frame (frame);
- CHECK_LIVE_FRAME (frame);
-
- f = XFRAME (frame);
+ XSETFRAME (frame, f);
if (FRAME_TERMCAP_P (f))
/* On a text terminal select FRAME. */
@@ -1870,14 +1765,7 @@ If Emacs is displaying on an ordinary terminal or some other device which
doesn't support multiple overlapping frames, this function does nothing. */)
(Lisp_Object frame)
{
- struct frame *f;
-
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_LIVE_FRAME (frame);
-
- f = XFRAME (frame);
+ struct frame *f = decode_live_frame (frame);
if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
(*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
@@ -1913,18 +1801,14 @@ is affected by `select-frame', while the latter is not.
The redirection lasts until `redirect-frame-focus' is called to change it. */)
(Lisp_Object frame, Lisp_Object focus_frame)
{
- struct frame *f;
-
/* Note that we don't check for a live frame here. It's reasonable
to redirect the focus of a frame you're about to delete, if you
know what other frame should receive those keystrokes. */
- CHECK_FRAME (frame);
+ struct frame *f = decode_any_frame (frame);
if (! NILP (focus_frame))
CHECK_LIVE_FRAME (focus_frame);
- f = XFRAME (frame);
-
fset_focus_frame (f, focus_frame);
if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
@@ -1934,15 +1818,14 @@ The redirection lasts until `redirect-frame-focus' is called to change it. */)
}
-DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 1, 1, 0,
+DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
-This returns nil if FRAME's focus is not redirected.
+If FRAME is omitted or nil, the selected frame is used.
+Return nil if FRAME's focus is not redirected.
See `redirect-frame-focus'. */)
(Lisp_Object frame)
{
- CHECK_LIVE_FRAME (frame);
-
- return FRAME_FOCUS_FRAME (XFRAME (frame));
+ return FRAME_FOCUS_FRAME (decode_live_frame (frame));
}
@@ -1965,22 +1848,6 @@ get_frame_param (register struct frame *frame, Lisp_Object prop)
}
#endif
-/* Return the buffer-predicate of the selected frame. */
-
-Lisp_Object
-frame_buffer_predicate (Lisp_Object frame)
-{
- return XFRAME (frame)->buffer_predicate;
-}
-
-/* Return the buffer-list of the selected frame. */
-
-static Lisp_Object
-frame_buffer_list (Lisp_Object frame)
-{
- return XFRAME (frame)->buffer_list;
-}
-
/* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
void
@@ -2108,7 +1975,7 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
swap_in_global_binding (sym);
break;
}
- default: abort ();
+ default: emacs_abort ();
}
}
@@ -2159,20 +2026,14 @@ 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.
The meaningful PARMs depend on the kind of frame.
-If FRAME is omitted, return information on the currently selected frame. */)
+If FRAME is omitted or nil, return information on the currently selected frame. */)
(Lisp_Object frame)
{
Lisp_Object alist;
- FRAME_PTR f;
+ struct frame *f = decode_any_frame (frame);
int height, width;
struct gcpro gcpro1;
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_FRAME (frame);
- f = XFRAME (frame);
-
if (!FRAME_LIVE_P (f))
return Qnil;
@@ -2233,9 +2094,8 @@ If FRAME is omitted, return information on the currently selected frame. */)
: FRAME_MINIBUF_ONLY_P (f) ? Qonly
: FRAME_MINIBUF_WINDOW (f)));
store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
- store_in_alist (&alist, Qbuffer_list, frame_buffer_list (frame));
- store_in_alist (&alist, Qburied_buffer_list,
- XFRAME (frame)->buried_buffer_list);
+ store_in_alist (&alist, Qbuffer_list, f->buffer_list);
+ store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
@@ -2260,17 +2120,12 @@ DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
If FRAME is nil, describe the currently selected frame. */)
(Lisp_Object frame, Lisp_Object parameter)
{
- struct frame *f;
- Lisp_Object value;
+ struct frame *f = decode_any_frame (frame);
+ Lisp_Object value = Qnil;
- if (NILP (frame))
- frame = selected_frame;
- else
- CHECK_FRAME (frame);
CHECK_SYMBOL (parameter);
- f = XFRAME (frame);
- value = Qnil;
+ XSETFRAME (frame, f);
if (FRAME_LIVE_P (f))
{
@@ -2350,14 +2205,9 @@ Note that this functionality is obsolete as of Emacs 22.2, and its
use is not recommended. Explicitly check for a frame-parameter instead. */)
(Lisp_Object frame, Lisp_Object alist)
{
- FRAME_PTR f;
+ struct frame *f = decode_live_frame (frame);
register Lisp_Object tail, prop, val;
- if (EQ (frame, Qnil))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
-
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
@@ -2412,20 +2262,15 @@ use is not recommended. Explicitly check for a frame-parameter instead. */)
DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
0, 1, 0,
doc: /* Height in pixels of a line in the font in frame FRAME.
-If FRAME is omitted, the selected frame is used.
+If FRAME is omitted or nil, the selected frame is used.
For a terminal frame, the value is always 1. */)
(Lisp_Object frame)
{
- struct frame *f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_FRAME (frame);
- f = XFRAME (frame);
-
#ifdef HAVE_WINDOW_SYSTEM
+ struct frame *f = decode_any_frame (frame);
+
if (FRAME_WINDOW_P (f))
- return make_number (x_char_height (f));
+ return make_number (FRAME_LINE_HEIGHT (f));
else
#endif
return make_number (1);
@@ -2435,21 +2280,16 @@ For a terminal frame, the value is always 1. */)
DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
0, 1, 0,
doc: /* Width in pixels of characters in the font in frame FRAME.
-If FRAME is omitted, the selected frame is used.
+If FRAME is omitted or nil, the selected frame is used.
On a graphical screen, the width is the standard width of the default font.
For a terminal screen, the value is always 1. */)
(Lisp_Object frame)
{
- struct frame *f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_FRAME (frame);
- f = XFRAME (frame);
-
#ifdef HAVE_WINDOW_SYSTEM
+ struct frame *f = decode_any_frame (frame);
+
if (FRAME_WINDOW_P (f))
- return make_number (x_char_width (f));
+ return make_number (FRAME_COLUMN_WIDTH (f));
else
#endif
return make_number (1);
@@ -2458,30 +2298,22 @@ For a terminal screen, the value is always 1. */)
DEFUN ("frame-pixel-height", Fframe_pixel_height,
Sframe_pixel_height, 0, 1, 0,
doc: /* Return a FRAME's height in pixels.
-If FRAME is omitted, the selected frame is used. The exact value
+If FRAME is omitted or nil, the selected frame is used. The exact value
of the result depends on the window-system and toolkit in use:
In the Gtk+ version of Emacs, it includes only any window (including
the minibuffer or echo area), mode line, and header line. It does not
include the tool bar or menu bar.
-With the Motif or Lucid toolkits, it also includes the tool bar (but
-not the menu bar).
-
-In a graphical version with no toolkit, it includes both the tool bar
-and menu bar.
+With other graphical versions, it also includes the tool bar and the
+menu bar.
For a text terminal, it includes the menu bar. In this case, the
result is really in characters rather than pixels (i.e., is identical
to `frame-height'). */)
(Lisp_Object frame)
{
- struct frame *f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_FRAME (frame);
- f = XFRAME (frame);
+ struct frame *f = decode_any_frame (frame);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
@@ -2495,15 +2327,10 @@ DEFUN ("frame-pixel-width", Fframe_pixel_width,
Sframe_pixel_width, 0, 1, 0,
doc: /* Return FRAME's width in pixels.
For a terminal frame, the result really gives the width in characters.
-If FRAME is omitted, the selected frame is used. */)
+If FRAME is omitted or nil, the selected frame is used. */)
(Lisp_Object frame)
{
- struct frame *f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_FRAME (frame);
- f = XFRAME (frame);
+ struct frame *f = decode_any_frame (frame);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
@@ -2517,17 +2344,15 @@ DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
Stool_bar_pixel_width, 0, 1, 0,
doc: /* Return width in pixels of FRAME's tool bar.
The result is greater than zero only when the tool bar is on the left
-or right side of FRAME. If FRAME is omitted, the selected frame is
-used. */)
+or right side of FRAME. If FRAME is omitted or nil, the selected frame
+is used. */)
(Lisp_Object frame)
{
- if (NILP (frame))
- frame = selected_frame;
- CHECK_FRAME (frame);
-
#ifdef FRAME_TOOLBAR_WIDTH
- if (FRAME_WINDOW_P (XFRAME (frame)))
- return make_number (FRAME_TOOLBAR_WIDTH (XFRAME (frame)));
+ struct frame *f = decode_any_frame (frame);
+
+ if (FRAME_WINDOW_P (f))
+ return make_number (FRAME_TOOLBAR_WIDTH (f));
#endif
return make_number (0);
}
@@ -2538,13 +2363,9 @@ Optional third arg non-nil means that redisplay should use LINES lines
but that the idea of the actual height of the frame should not be changed. */)
(Lisp_Object frame, Lisp_Object lines, Lisp_Object pretend)
{
- register struct frame *f;
+ register struct frame *f = decode_live_frame (frame);
CHECK_TYPE_RANGED_INTEGER (int, lines);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
@@ -2566,12 +2387,9 @@ Optional third arg non-nil means that redisplay should use COLS columns
but that the idea of the actual width of the frame should not be changed. */)
(Lisp_Object frame, Lisp_Object cols, Lisp_Object pretend)
{
- register struct frame *f;
+ register struct frame *f = decode_live_frame (frame);
+
CHECK_TYPE_RANGED_INTEGER (int, cols);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
@@ -2693,7 +2511,7 @@ static const struct frame_parm_table frame_parms[] =
{"tool-bar-position", &Qtool_bar_position},
};
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
wanted positions of the WM window (not Emacs window).
@@ -2737,7 +2555,7 @@ x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int
*height = newheight;
}
-#endif /* WINDOWSNT */
+#endif /* HAVE_NTGUI */
#ifdef HAVE_WINDOW_SYSTEM
@@ -3024,9 +2842,9 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
void
x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
{
- char buf[16];
Lisp_Object tem;
- unsigned long w;
+ uprintmax_t w;
+ char buf[INT_BUFSIZE_BOUND (w)];
/* Represent negative positions (off the top or left screen edge)
in a way that Fmodify_frame_parameters will understand correctly. */
@@ -3063,17 +2881,17 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
MS-Windows it returns a value whose type is HANDLE, which is
actually a pointer. Explicit casting avoids compiler
warnings. */
- w = (unsigned long) FRAME_X_WINDOW (f);
+ w = (uintptr_t) FRAME_X_WINDOW (f);
store_in_alist (alistptr, Qwindow_id,
- make_formatted_string (buf, "%lu", w));
+ make_formatted_string (buf, "%"pMu, w));
#ifdef HAVE_X_WINDOWS
#ifdef USE_X_TOOLKIT
/* Tooltip frame may not have this widget. */
if (FRAME_X_OUTPUT (f)->widget)
#endif
- w = (unsigned long) FRAME_OUTER_WINDOW (f);
+ w = (uintptr_t) FRAME_OUTER_WINDOW (f);
store_in_alist (alistptr, Qouter_window_id,
- make_formatted_string (buf, "%lu", w));
+ make_formatted_string (buf, "%"pMu, w));
#endif
store_in_alist (alistptr, Qicon_name, f->icon_name);
FRAME_SAMPLE_VISIBILITY (f);
@@ -3233,6 +3051,9 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Lisp_Object ascii_font = fontset_ascii (fontset);
Lisp_Object spec = font_spec_from_name (ascii_font);
+ if (NILP (spec))
+ signal_error ("Invalid font name", ascii_font);
+
if (! font_match_p (spec, font_object))
fontset = -1;
}
@@ -3529,9 +3350,9 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
f->alpha[i] = newval[i];
#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
- BLOCK_INPUT;
+ block_input ();
x_set_frame_alpha (f);
- UNBLOCK_INPUT;
+ unblock_input ();
#endif
return;
@@ -3835,7 +3656,7 @@ x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
}
default:
- abort ();
+ emacs_abort ();
}
}
else
@@ -3893,6 +3714,95 @@ x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
}
+#if !defined (HAVE_X_WINDOWS) && defined (NoValue)
+
+/*
+ * XParseGeometry parses strings of the form
+ * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
+ * width, height, xoffset, and yoffset are unsigned integers.
+ * Example: "=80x24+300-49"
+ * The equal sign is optional.
+ * It returns a bitmask that indicates which of the four values
+ * were actually found in the string. For each value found,
+ * the corresponding argument is updated; for each value
+ * not found, the corresponding argument is left unchanged.
+ */
+
+static int
+XParseGeometry (char *string,
+ int *x, int *y,
+ unsigned int *width, unsigned int *height)
+{
+ int mask = NoValue;
+ char *strind;
+ unsigned long int tempWidth, tempHeight;
+ long int tempX, tempY;
+ char *nextCharacter;
+
+ if (string == NULL || *string == '\0')
+ return mask;
+ if (*string == '=')
+ string++; /* ignore possible '=' at beg of geometry spec */
+
+ strind = string;
+ if (*strind != '+' && *strind != '-' && *strind != 'x')
+ {
+ tempWidth = strtoul (strind, &nextCharacter, 10);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= WidthValue;
+ }
+
+ if (*strind == 'x' || *strind == 'X')
+ {
+ strind++;
+ tempHeight = strtoul (strind, &nextCharacter, 10);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= HeightValue;
+ }
+
+ if (*strind == '+' || *strind == '-')
+ {
+ if (*strind == '-')
+ mask |= XNegative;
+ tempX = strtol (strind, &nextCharacter, 10);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= XValue;
+ if (*strind == '+' || *strind == '-')
+ {
+ if (*strind == '-')
+ mask |= YNegative;
+ tempY = strtol (strind, &nextCharacter, 10);
+ if (strind == nextCharacter)
+ return 0;
+ strind = nextCharacter;
+ mask |= YValue;
+ }
+ }
+
+ /* If strind isn't at the end of the string then it's an invalid
+ geometry specification. */
+
+ if (*strind != '\0')
+ return 0;
+
+ if (mask & XValue)
+ *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
+ if (mask & YValue)
+ *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
+ if (mask & WidthValue)
+ *width = min (tempWidth, UINT_MAX);
+ if (mask & HeightValue)
+ *height = min (tempHeight, UINT_MAX);
+ return mask;
+}
+
+#endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
/* NS used to define x-parse-geometry in ns-win.el, but that confused
@@ -3913,15 +3823,16 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.
On Nextstep, this just calls `ns-parse-geometry'. */)
(Lisp_Object string)
{
-#ifdef HAVE_NS
- return call1 (Qns_parse_geometry, string);
-#else
int geometry, x, y;
unsigned int width, height;
Lisp_Object result;
CHECK_STRING (string);
+#ifdef HAVE_NS
+ if (strchr (SSDATA (string), ' ') != NULL)
+ return call1 (Qns_parse_geometry, string);
+#endif
geometry = XParseGeometry (SSDATA (string),
&x, &y, &width, &height);
result = Qnil;
@@ -3957,7 +3868,6 @@ On Nextstep, this just calls `ns-parse-geometry'. */)
result = Fcons (Fcons (Qheight, make_number (height)), result);
return result;
-#endif /* HAVE_NS */
}
@@ -4196,12 +4106,7 @@ Otherwise it returns nil. FRAME omitted or nil means the
selected frame. This is useful when `make-pointer-invisible' is set. */)
(Lisp_Object frame)
{
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_FRAME (frame);
-
- return (XFRAME (frame)->pointer_invisible ? Qnil : Qt);
+ return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
}
diff --git a/src/frame.h b/src/frame.h
index 1fe3ebd9182..589b45fc0ff 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -81,9 +81,6 @@ enum fullscreen_type
#define FRAME_FOREGROUND_PIXEL(f) ((f)->foreground_pixel)
#define FRAME_BACKGROUND_PIXEL(f) ((f)->background_pixel)
-struct terminal;
-
-struct font_driver_list;
struct frame
{
@@ -240,7 +237,7 @@ struct frame
#if defined (USE_GTK) || defined (HAVE_NS)
/* Nonzero means using a tool bar that comes from the toolkit. */
- int external_tool_bar;
+ unsigned external_tool_bar : 1;
#endif
/* Margin at the top of the frame. Used to display the tool-bar. */
@@ -304,9 +301,6 @@ struct frame
/* Canonical X unit. Width of default font, in pixels. */
int column_width;
- /* Width of space glyph of default font, in pixels. */
- int space_width;
-
/* Canonical Y unit. Height of a line, in pixels. */
int line_height;
@@ -360,9 +354,6 @@ struct frame
unsigned int external_menu_bar : 1;
#endif
- /* Nonzero if last attempt at redisplay on this frame was preempted. */
- unsigned display_preempted : 1;
-
/* visible is nonzero if the frame is currently displayed; we check
it to see if we should bother updating the frame's contents.
DON'T SET IT DIRECTLY; instead, use FRAME_SET_VISIBLE.
@@ -412,10 +403,6 @@ struct frame
show no modeline for that window. */
unsigned wants_modeline : 1;
- /* Non-zero if the hardware device this frame is displaying on can
- support scroll bars. */
- char can_have_scroll_bars;
-
/* Non-0 means raise this frame to the top of the heap when selected. */
unsigned auto_raise : 1;
@@ -441,8 +428,7 @@ struct frame
/* Nonzero means that the pointer is invisible. */
unsigned pointer_invisible :1;
- /* If can_have_scroll_bars is non-zero, this is non-zero if we should
- actually display them on this frame. */
+ /* 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?
@@ -621,7 +607,7 @@ typedef struct frame *FRAME_PTR;
#define FRAME_INITIAL_P(f) ((f)->output_method == output_initial)
#define FRAME_TERMCAP_P(f) ((f)->output_method == output_termcap)
#define FRAME_X_P(f) ((f)->output_method == output_x_window)
-#ifndef WINDOWSNT
+#ifndef HAVE_NTGUI
#define FRAME_W32_P(f) (0)
#else
#define FRAME_W32_P(f) ((f)->output_method == output_w32)
@@ -649,7 +635,7 @@ typedef struct frame *FRAME_PTR;
#define FRAME_WINDOW_P(f) FRAME_NS_P(f)
#endif
#ifndef FRAME_WINDOW_P
-#define FRAME_WINDOW_P(f) (0)
+#define FRAME_WINDOW_P(f) ((void) (f), 0)
#endif
/* Return a pointer to the structure holding information about the
@@ -770,11 +756,6 @@ typedef struct frame *FRAME_PTR;
#define FRAME_SCROLL_BOTTOM_VPOS(f) (f)->scroll_bottom_vpos
#define FRAME_FOCUS_FRAME(f) f->focus_frame
-/* Nonzero if frame F supports scroll bars.
- If this is zero, then it is impossible to enable scroll bars
- on frame F. */
-#define FRAME_CAN_HAVE_SCROLL_BARS(f) ((f)->can_have_scroll_bars)
-
/* 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)
@@ -946,6 +927,21 @@ typedef struct frame *FRAME_PTR;
&& (frame_var = XCAR (list_var), 1)); \
list_var = XCDR (list_var))
+/* Reflect mouse movement when a complete frame update is performed. */
+
+#define FRAME_MOUSE_UPDATE(frame) \
+ do { \
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (frame); \
+ if (frame == hlinfo->mouse_face_mouse_frame) \
+ { \
+ block_input (); \
+ if (hlinfo->mouse_face_mouse_frame) \
+ note_mouse_highlight (hlinfo->mouse_face_mouse_frame, \
+ hlinfo->mouse_face_mouse_x, \
+ hlinfo->mouse_face_mouse_y); \
+ unblock_input (); \
+ } \
+ } while (0)
extern Lisp_Object Qframep, Qframe_live_p;
extern Lisp_Object Qtty, Qtty_type;
@@ -956,6 +952,8 @@ extern Lisp_Object Qnoelisp;
extern struct frame *last_nonminibuf_frame;
extern void set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
+extern struct frame *decode_live_frame (Lisp_Object);
+extern struct frame *decode_any_frame (Lisp_Object);
extern struct frame *make_initial_frame (void);
extern struct frame *make_frame (int);
#ifdef HAVE_WINDOW_SYSTEM
@@ -981,7 +979,7 @@ extern Lisp_Object selected_frame;
((FRAMEP (selected_frame) \
&& FRAME_LIVE_P (XFRAME (selected_frame))) \
? XFRAME (selected_frame) \
- : (abort (), (struct frame *) 0))
+ : (emacs_abort (), (struct frame *) 0))
/***********************************************************************
@@ -999,11 +997,6 @@ extern Lisp_Object selected_frame;
#define FRAME_COLUMN_WIDTH(F) ((F)->column_width)
-/* Space glyph width of the default font of frame F. */
-
-#define FRAME_SPACE_WIDTH(F) ((F)->space_width)
-
-
/* Pixel width of areas used to display truncation marks, continuation
marks, overlay arrows. This is 0 for terminal frames. */
@@ -1206,14 +1199,14 @@ extern Lisp_Object Qrun_hook_with_args;
extern void x_set_scroll_bar_default_width (struct frame *);
extern void x_set_offset (struct frame *, int, int, int);
extern void x_wm_set_icon_position (struct frame *, int, int);
-extern void x_wm_set_size_hint (FRAME_PTR f, long flags, int user_position);
+extern void x_wm_set_size_hint (FRAME_PTR 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 WINDOWSNT
+#ifdef HAVE_NTGUI
extern void x_fullscreen_adjust (struct frame *f, int *, int *,
int *, int *);
#endif
@@ -1252,7 +1245,7 @@ extern Lisp_Object display_x_get_resource (Display_Info *,
Lisp_Object component,
Lisp_Object subclass);
-extern void set_frame_menubar (struct frame *f, int first_time, int deep_p);
+extern void set_frame_menubar (struct frame *f, bool first_time, bool deep_p);
extern void x_set_window_size (struct frame *f, int change_grav,
int cols, int rows);
extern void x_sync (struct frame *);
@@ -1262,8 +1255,6 @@ 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);
-extern int x_char_width (struct frame *f);
-extern int x_char_height (struct frame *f);
extern int x_pixel_width (struct frame *f);
extern int x_pixel_height (struct frame *f);
extern void x_set_frame_alpha (struct frame *f);
@@ -1285,9 +1276,7 @@ extern char *x_get_resource_string (const char *, const char *);
#endif
extern void x_query_colors (struct frame *f, XColor *, int);
-
-/* In xmenu.c */
-extern void set_frame_menubar (FRAME_PTR, int, int);
+extern void x_query_color (struct frame *f, XColor *);
#endif /* HAVE_WINDOW_SYSTEM */
diff --git a/src/fringe.c b/src/fringe.c
index 97d03a2bfae..ce31fd01763 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -18,7 +18,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "frame.h"
@@ -659,7 +658,14 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o
{
/* If W has a vertical border to its left, don't draw over it. */
wd -= ((!WINDOW_LEFTMOST_P (w)
- && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+ && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
+ /* But don't reduce the fringe width if the window
+ has a left margin, because that means we are not
+ in danger of drawing over the vertical border,
+ and OTOH leaving out that one pixel leaves behind
+ traces of the cursor, if it was in column zero
+ before drawing non-empty margin area. */
+ && NILP (w->left_margin_cols))
? 1 : 0);
p.bx = x - wd;
p.nx = wd;
@@ -866,7 +872,7 @@ draw_fringe_bitmap (struct window *w, struct glyph_row *row, int left_p)
void
draw_row_fringe_bitmaps (struct window *w, struct glyph_row *row)
{
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
/* If row is completely invisible, because of vscrolling, we
don't have to draw anything. */
@@ -1725,10 +1731,8 @@ Return nil if POS is not visible in WINDOW. */)
struct glyph_row *row;
ptrdiff_t textpos;
- if (NILP (window))
- window = selected_window;
- CHECK_WINDOW (window);
- w = XWINDOW (window);
+ w = decode_any_window (window);
+ XSETWINDOW (window, w);
if (!NILP (pos))
{
@@ -1740,7 +1744,7 @@ Return nil if POS is not visible in WINDOW. */)
else if (w == XWINDOW (selected_window))
textpos = PT;
else
- textpos = XMARKER (w->pointm)->charpos;
+ textpos = marker_position (w->pointm);
row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
row = row_containing_pos (w, textpos, row, NULL, 0);
diff --git a/src/ftfont.c b/src/ftfont.c
index e16f967f596..f07ad6f33c7 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -21,8 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
-
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
@@ -45,7 +43,7 @@ static Lisp_Object Qfreetype;
static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
/* Flag to tell if FcInit is already called or not. */
-static int fc_initialized;
+static bool fc_initialized;
/* Handle to a FreeType library instance. */
static FT_Library ft_library;
@@ -65,7 +63,7 @@ struct ftfont_info
#ifdef HAVE_LIBOTF
/* The following four members must be here in this order to be
compatible with struct xftfont_info (in xftfont.c). */
- int maybe_otf; /* Flag to tell if this may be OTF or not. */
+ bool maybe_otf; /* Flag to tell if this may be OTF or not. */
OTF *otf;
#endif /* HAVE_LIBOTF */
FT_Size ft_size;
@@ -543,9 +541,9 @@ struct font_driver ftfont_driver =
/* We can't draw a text without device dependent functions. */
NULL, /* draw */
ftfont_get_bitmap,
- NULL, /* get_bitmap */
NULL, /* free_bitmap */
NULL, /* get_outline */
+ NULL, /* free_outline */
ftfont_anchor_point,
#ifdef HAVE_LIBOTF
ftfont_otf_capability,
@@ -661,7 +659,8 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec)
{
struct OpenTypeSpec *spec = malloc (sizeof *spec);
Lisp_Object val;
- int i, j, negative;
+ int i, j;
+ bool negative;
if (! spec)
return NULL;
@@ -1185,7 +1184,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
FT_Size ft_size;
FT_UInt size;
Lisp_Object val, filename, idx, cache, font_object;
- int scalable;
+ bool scalable;
int spacing;
char name[256];
int i, len;
@@ -1243,7 +1242,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
ftfont_info->ft_size = ft_face->size;
ftfont_info->index = XINT (idx);
#ifdef HAVE_LIBOTF
- ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
+ ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
ftfont_info->otf = NULL;
#endif /* HAVE_LIBOTF */
/* This means that there's no need of transformation. */
@@ -1392,7 +1391,8 @@ ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
FT_Face ft_face = ftfont_info->ft_size->face;
int width = 0;
- int i, first;
+ int i;
+ bool first;
if (ftfont_info->ft_size != ft_face->size)
FT_Activate_Size (ftfont_info->ft_size);
@@ -1630,7 +1630,7 @@ ftfont_get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
FT_Glyph_Metrics *m;
if (FT_Load_Glyph (ft_face, g->code, FT_LOAD_DEFAULT) != 0)
- abort ();
+ emacs_abort ();
m = &ft_face->glyph->metrics;
if (flt_font_ft->matrix)
{
@@ -1682,10 +1682,12 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
OTF *otf = flt_font_ft->otf;
OTF_Tag *tags;
- int i, n, negative;
+ int i, n;
+ bool negative;
if (FEATURE_ANY (0) && FEATURE_ANY (1))
- /* Return 1 iff any of GSUB or GPOS support the script (and language). */
+ /* Return true iff any of GSUB or GPOS support the script (and
+ language). */
return (otf
&& (OTF_check_features (otf, 0, spec->script, spec->langsys,
NULL, 0) > 0
@@ -2390,7 +2392,7 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
static MFLTGlyphString gstring;
-static int m17n_flt_initialized;
+static bool m17n_flt_initialized;
static Lisp_Object
ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
@@ -2400,7 +2402,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
ptrdiff_t i;
struct MFLTFontFT flt_font_ft;
MFLT *flt = NULL;
- int with_variation_selector = 0;
+ bool with_variation_selector = 0;
if (! m17n_flt_initialized)
{
@@ -2421,7 +2423,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
break;
c = LGLYPH_CHAR (g);
if (CHAR_VARIATION_SELECTOR_P (c))
- with_variation_selector++;
+ with_variation_selector = 1;
}
len = i;
diff --git a/src/ftxfont.c b/src/ftxfont.c
index 6ebe0798b4e..5effe6e9104 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include <X11/Xlib.h>
#include "lisp.h"
@@ -43,14 +42,6 @@ static
#endif
struct font_driver ftxfont_driver;
-/* Prototypes for helper function. */
-static GC *ftxfont_get_gcs (FRAME_PTR, unsigned long, unsigned long);
-static int ftxfont_draw_bitmap (FRAME_PTR, GC, GC *, struct font *,
- unsigned, int, int, XPoint *, int, int *,
- int);
-static void ftxfont_draw_background (FRAME_PTR, struct font *, GC,
- int, int, int);
-
struct ftxfont_frame_data
{
/* Background and foreground colors. */
@@ -107,7 +98,7 @@ ftxfont_get_gcs (FRAME_PTR f, long unsigned int foreground, long unsigned int ba
new->colors[0].pixel = background;
new->colors[1].pixel = foreground;
- BLOCK_INPUT;
+ block_input ();
XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), new->colors, 2);
for (i = 1; i < 7; i++)
{
@@ -124,14 +115,14 @@ ftxfont_get_gcs (FRAME_PTR f, long unsigned int foreground, long unsigned int ba
new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
GCForeground, &xgcv);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (i < 7)
{
- BLOCK_INPUT;
+ block_input ();
for (i--; i >= 0; i--)
XFreeGC (FRAME_X_DISPLAY (f), new->gcs[i]);
- UNBLOCK_INPUT;
+ unblock_input ();
if (prev)
prev->next = new->next;
else if (data)
@@ -143,7 +134,9 @@ ftxfont_get_gcs (FRAME_PTR f, long unsigned int foreground, long unsigned int ba
}
static int
-ftxfont_draw_bitmap (FRAME_PTR f, GC gc_fore, GC *gcs, struct font *font, unsigned int code, int x, int y, XPoint *p, int size, int *n, int flush)
+ftxfont_draw_bitmap (FRAME_PTR f, GC gc_fore, GC *gcs, struct font *font,
+ unsigned int code, int x, int y, XPoint *p, int size,
+ int *n, bool flush)
{
struct font_bitmap bitmap;
unsigned char *b;
@@ -232,13 +225,6 @@ ftxfont_draw_background (FRAME_PTR f, struct font *font, GC gc, int x, int y,
XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
}
-/* Prototypes for font-driver methods. */
-static Lisp_Object ftxfont_list (Lisp_Object, Lisp_Object);
-static Lisp_Object ftxfont_match (Lisp_Object, Lisp_Object);
-static Lisp_Object ftxfont_open (FRAME_PTR, Lisp_Object, int);
-static void ftxfont_close (FRAME_PTR, struct font *);
-static int ftxfont_draw (struct glyph_string *, int, int, int, int, int);
-
static Lisp_Object
ftxfont_list (Lisp_Object frame, Lisp_Object spec)
{
@@ -280,7 +266,8 @@ ftxfont_close (FRAME_PTR f, struct font *font)
}
static int
-ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_background)
+ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
+ bool with_background)
{
FRAME_PTR f = s->f;
struct face *face = s->face;
@@ -295,7 +282,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_b
n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
- BLOCK_INPUT;
+ block_input ();
if (with_background)
ftxfont_draw_background (f, font, s->gc, x, y, s->width);
code = alloca (sizeof (unsigned) * len);
@@ -345,7 +332,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_b
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return len;
}
@@ -355,7 +342,7 @@ ftxfont_end_for_frame (FRAME_PTR f)
{
struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver);
- BLOCK_INPUT;
+ block_input ();
while (data)
{
struct ftxfont_frame_data *next = data->next;
@@ -366,7 +353,7 @@ ftxfont_end_for_frame (FRAME_PTR f)
free (data);
data = next;
}
- UNBLOCK_INPUT;
+ unblock_input ();
font_put_frame_data (f, &ftxfont_driver, NULL);
return 0;
}
diff --git a/src/gmalloc.c b/src/gmalloc.c
index 78d6934755b..c325ca79910 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -36,6 +36,10 @@ Fifth Floor, Boston, MA 02110-1301, USA.
#include <pthread.h>
#endif
+#ifdef WINDOWSNT
+#include <w32heap.h> /* for sbrk */
+#endif
+
#ifdef __cplusplus
extern "C"
{
@@ -460,7 +464,7 @@ get_contiguous_space (ptrdiff_t size, void *position)
/* This is called when `_heapinfo' and `heapsize' have just
been set to describe a new info table. Set up the table
to describe itself and account for it in the statistics. */
-static inline void
+static void
register_heapinfo (void)
{
size_t block, blocks;
@@ -1289,7 +1293,9 @@ Fifth Floor, Boston, MA 02110-1301, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
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
@@ -1639,14 +1645,6 @@ memalign (size_t alignment, size_t size)
return result;
}
-#ifndef ENOMEM
-#define ENOMEM 12
-#endif
-
-#ifndef EINVAL
-#define EINVAL 22
-#endif
-
int
posix_memalign (void **memptr, size_t alignment, size_t size)
{
diff --git a/src/gnutls.c b/src/gnutls.c
index a2573f6bd99..03f753fa8cc 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -18,7 +18,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <errno.h>
-#include <setjmp.h>
#include "lisp.h"
#include "process.h"
@@ -31,15 +30,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "w32.h"
#endif
-static int
-emacs_gnutls_handle_error (gnutls_session_t, int err);
+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 int gnutls_global_initialized;
+static bool gnutls_global_initialized;
/* The following are for the property list of `gnutls-boot'. */
static Lisp_Object QCgnutls_bootprop_priority;
@@ -142,13 +140,13 @@ DEF_GNUTLS_FN (int, gnutls_x509_crt_import,
gnutls_x509_crt_fmt_t));
DEF_GNUTLS_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
-static int
-init_gnutls_functions (Lisp_Object libraries)
+static bool
+init_gnutls_functions (void)
{
HMODULE library;
int max_log_level = 1;
- if (!(library = w32_delayed_load (libraries, Qgnutls_dll)))
+ if (!(library = w32_delayed_load (Qgnutls_dll)))
{
GNUTLS_LOG (1, max_log_level, "GnuTLS library not found");
return 0;
@@ -361,12 +359,7 @@ emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
{
-#ifdef EWOULDBLOCK
- errno = EWOULDBLOCK;
-#endif
-#ifdef EAGAIN
errno = EAGAIN;
-#endif
return 0;
}
@@ -386,14 +379,7 @@ emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
appropriately so that send_process retries the
correct way instead of erroring out. */
if (rtnval == GNUTLS_E_AGAIN)
- {
-#ifdef EWOULDBLOCK
- errno = EWOULDBLOCK;
-#endif
-#ifdef EAGAIN
- errno = EAGAIN;
-#endif
- }
+ errno = EAGAIN;
break;
}
}
@@ -439,7 +425,7 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
else if (rtnval == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
/* The peer closed the connection. */
return 0;
- else if (emacs_gnutls_handle_error (state, rtnval) == 0)
+ else if (emacs_gnutls_handle_error (state, rtnval))
/* non-fatal error */
return -1;
else {
@@ -448,19 +434,19 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
}
}
-/* report a GnuTLS error to the user.
- Returns zero if the error code was successfully handled. */
-static int
+/* Report a GnuTLS error to the user.
+ Return true if the error code was successfully handled. */
+static bool
emacs_gnutls_handle_error (gnutls_session_t session, int err)
{
int max_log_level = 0;
- int ret;
+ bool ret;
const char *str;
/* TODO: use a Lisp_Object generated by gnutls_make_error? */
if (err >= 0)
- return 0;
+ return 1;
max_log_level = global_gnutls_log_level;
@@ -472,12 +458,12 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
if (fn_gnutls_error_is_fatal (err))
{
- ret = err;
+ ret = 0;
GNUTLS_LOG2 (0, max_log_level, "fatal error:", str);
}
else
{
- ret = 0;
+ ret = 1;
GNUTLS_LOG2 (1, max_log_level, "non-fatal error:", str);
/* TODO: EAGAIN AKA Qgnutls_e_again should be level 2. */
}
@@ -657,7 +643,7 @@ DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
else
{
Lisp_Object status;
- status = init_gnutls_functions (Vdynamic_library_alist) ? Qt : Qnil;
+ status = init_gnutls_functions () ? Qt : Qnil;
Vlibrary_cache = Fcons (Fcons (Qgnutls_dll, status), Vlibrary_cache);
return status;
}
diff --git a/src/gtkutil.c b/src/gtkutil.c
index f0d2c022f0c..9f2b652525f 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -21,9 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef USE_GTK
#include <float.h>
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#include <c-ctype.h>
@@ -254,7 +252,7 @@ void
free_widget_value (widget_value *wv)
{
if (wv->free_list)
- abort ();
+ emacs_abort ();
if (malloc_cpt > 25)
{
@@ -578,21 +576,21 @@ get_utf8_string (const char *str)
/* Check for special colors used in face spec for region face.
The colors are fetched from the Gtk+ theme.
- Return 1 if color was found, 0 if not. */
+ Return true if color was found, false if not. */
-int
+bool
xg_check_special_colors (struct frame *f,
const char *color_name,
XColor *color)
{
- int success_p = 0;
- int get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0;
- int get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0;
+ bool success_p = 0;
+ bool get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0;
+ bool get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0;
if (! FRAME_GTK_WIDGET (f) || ! (get_bg || get_fg))
return success_p;
- BLOCK_INPUT;
+ block_input ();
{
#ifdef HAVE_GTK3
GtkStyleContext *gsty
@@ -606,8 +604,9 @@ xg_check_special_colors (struct frame *f,
gtk_style_context_get_background_color (gsty, state, &col);
sprintf (buf, "rgbi:%lf/%lf/%lf", col.red, col.green, col.blue);
- success_p = XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- buf, color);
+ success_p = (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ buf, color)
+ != 0);
#else
GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
GdkColor *grgb = get_bg
@@ -622,7 +621,7 @@ xg_check_special_colors (struct frame *f,
#endif
}
- UNBLOCK_INPUT;
+ unblock_input ();
return success_p;
}
@@ -705,9 +704,9 @@ qttip_cb (GtkWidget *widget,
#endif /* USE_GTK_TOOLTIP */
/* Prepare a tooltip to be shown, i.e. calculate WIDTH and HEIGHT.
- Return zero if no system tooltip available, non-zero otherwise. */
+ Return true if a system tooltip is available. */
-int
+bool
xg_prepare_tooltip (FRAME_PTR f,
Lisp_Object string,
int *width,
@@ -727,7 +726,7 @@ xg_prepare_tooltip (FRAME_PTR f,
if (!x->ttip_lbl) return 0;
- BLOCK_INPUT;
+ block_input ();
encoded_string = ENCODE_UTF_8 (string);
widget = GTK_WIDGET (x->ttip_lbl);
gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window));
@@ -755,7 +754,7 @@ xg_prepare_tooltip (FRAME_PTR f,
if (width) *width = req.width;
if (height) *height = req.height;
- UNBLOCK_INPUT;
+ unblock_input ();
return 1;
#endif /* USE_GTK_TOOLTIP */
@@ -771,27 +770,27 @@ xg_show_tooltip (FRAME_PTR f, int root_x, int root_y)
struct x_output *x = f->output_data.x;
if (x->ttip_window)
{
- BLOCK_INPUT;
+ block_input ();
gtk_window_move (x->ttip_window, root_x, root_y);
gtk_widget_show_all (GTK_WIDGET (x->ttip_window));
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
}
/* Hide tooltip if shown. Do nothing if not shown.
- Return non-zero if tip was hidden, non-zero if not (i.e. not using
+ Return true if tip was hidden, false if not (i.e. not using
system tooltips). */
-int
+bool
xg_hide_tooltip (FRAME_PTR f)
{
- int ret = 0;
+ bool ret = 0;
#ifdef USE_GTK_TOOLTIP
if (f->output_data.x->ttip_window)
{
GtkWindow *win = f->output_data.x->ttip_window;
- BLOCK_INPUT;
+ block_input ();
gtk_widget_hide (GTK_WIDGET (win));
if (g_object_get_data (G_OBJECT (win), "restore-tt"))
@@ -801,7 +800,7 @@ xg_hide_tooltip (FRAME_PTR f)
GtkSettings *settings = gtk_settings_get_for_screen (screen);
g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
}
- UNBLOCK_INPUT;
+ unblock_input ();
ret = 1;
}
@@ -814,6 +813,14 @@ xg_hide_tooltip (FRAME_PTR f)
General functions for creating widgets, resizing, events, e.t.c.
***********************************************************************/
+static void
+my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *msg, gpointer user_data)
+{
+ if (!strstr (msg, "visible children"))
+ fprintf (stderr, "XX %s-WARNING **: %s\n", log_domain, msg);
+}
+
/* Make a geometry string and pass that to GTK. It seems this is the
only way to get geometry position right if the user explicitly
asked for a position when starting Emacs.
@@ -829,6 +836,7 @@ xg_set_geometry (FRAME_PTR f)
int top = f->top_pos;
int yneg = f->size_hint_flags & YNegative;
char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)];
+ guint id;
if (xneg)
left = -left;
@@ -841,9 +849,15 @@ xg_set_geometry (FRAME_PTR f)
(xneg ? '-' : '+'), left,
(yneg ? '-' : '+'), top);
+ /* Silence warning about visible children. */
+ id = g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
+ | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
+
if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
geom_str))
fprintf (stderr, "Failed to parse: '%s'\n", geom_str);
+
+ g_log_remove_handler ("Gtk", id);
}
}
@@ -1009,7 +1023,7 @@ xg_win_to_widget (Display *dpy, Window wdesc)
gpointer gdkwin;
GtkWidget *gwdesc = 0;
- BLOCK_INPUT;
+ block_input ();
gdkwin = gdk_x11_window_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
wdesc);
@@ -1021,7 +1035,7 @@ xg_win_to_widget (Display *dpy, Window wdesc)
gwdesc = gtk_get_event_widget (&event);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return gwdesc;
}
@@ -1036,9 +1050,9 @@ xg_set_widget_bg (FRAME_PTR f, GtkWidget *w, long unsigned int pixel)
xbg.pixel = pixel;
if (XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &xbg))
{
- bg.red = (double)xbg.red/65536.0;
- bg.green = (double)xbg.green/65536.0;
- bg.blue = (double)xbg.blue/65536.0;
+ bg.red = (double)xbg.red/65535.0;
+ bg.green = (double)xbg.green/65535.0;
+ bg.blue = (double)xbg.blue/65535.0;
bg.alpha = 1.0;
gtk_widget_override_background_color (w, GTK_STATE_FLAG_NORMAL, &bg);
}
@@ -1112,9 +1126,9 @@ delete_cb (GtkWidget *widget,
}
/* Create and set up the GTK widgets for frame F.
- Return 0 if creation failed, non-zero otherwise. */
+ Return true if creation succeeded. */
-int
+bool
xg_create_frame_widgets (FRAME_PTR f)
{
GtkWidget *wtop;
@@ -1125,7 +1139,7 @@ xg_create_frame_widgets (FRAME_PTR f)
#endif
char *title = 0;
- BLOCK_INPUT;
+ block_input ();
if (FRAME_X_EMBEDDED_P (f))
{
@@ -1163,7 +1177,7 @@ xg_create_frame_widgets (FRAME_PTR f)
if (whbox) gtk_widget_destroy (whbox);
if (wfixed) gtk_widget_destroy (wfixed);
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -1277,7 +1291,7 @@ xg_create_frame_widgets (FRAME_PTR f)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return 1;
}
@@ -1311,11 +1325,11 @@ xg_free_frame_widgets (FRAME_PTR f)
/* Set the normal size hints for the window manager, for frame F.
FLAGS is the flags word to use--or 0 meaning preserve the flags
that the window now has.
- If USER_POSITION is nonzero, we set the User Position
+ If USER_POSITION, set the User Position
flag (this is useful when FLAGS is 0). */
void
-x_wm_set_size_hint (FRAME_PTR f, long int flags, int user_position)
+x_wm_set_size_hint (FRAME_PTR f, long int flags, bool user_position)
{
/* Must use GTK routines here, otherwise GTK resets the size hints
to its own defaults. */
@@ -1399,12 +1413,12 @@ x_wm_set_size_hint (FRAME_PTR f, long int flags, int user_position)
&f->output_data.x->size_hints,
sizeof (size_hints)) != 0)
{
- BLOCK_INPUT;
+ block_input ();
gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
NULL, &size_hints, hint_flags);
f->output_data.x->size_hints = size_hints;
f->output_data.x->hint_flags = hint_flags;
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1419,9 +1433,9 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
{
if (FRAME_GTK_WIDGET (f))
{
- BLOCK_INPUT;
+ block_input ();
xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1521,7 +1535,7 @@ create_dialog (widget_value *wv,
/* If the number of buttons is greater than 4, make two rows of buttons
instead. This looks better. */
- int make_two_rows = total_buttons > 4;
+ bool make_two_rows = total_buttons > 4;
if (right_buttons == 0) right_buttons = total_buttons/2;
left_buttons = total_buttons - right_buttons;
@@ -1639,14 +1653,14 @@ pop_down_dialog (Lisp_Object arg)
struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
struct xg_dialog_data *dd = (struct xg_dialog_data *) p->pointer;
- BLOCK_INPUT;
+ block_input ();
if (dd->w) gtk_widget_destroy (dd->w);
if (dd->timerid != 0) g_source_remove (dd->timerid);
g_main_loop_quit (dd->loop);
g_main_loop_unref (dd->loop);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -1718,10 +1732,9 @@ xg_dialog_run (FRAME_PTR f, GtkWidget *w)
/***********************************************************************
File dialog functions
***********************************************************************/
-/* Return non-zero if the old file selection dialog is being used.
- Return zero if not. */
+/* Return true if the old file selection dialog is being used. */
-int
+bool
xg_uses_old_file_dialog (void)
{
#ifdef HAVE_GTK_FILE_SELECTION_NEW
@@ -1792,7 +1805,7 @@ xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data)
F is the current frame.
PROMPT is a prompt to show to the user. May not be NULL.
DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
- If MUSTMATCH_P is non-zero, the returned file name must be an existing
+ If MUSTMATCH_P, the returned file name must be an existing
file. (Actually, this only has cosmetic effects, the user can
still enter a non-existing file.) *FUNC is set to a function that
can be used to retrieve the selected file name from the returned widget.
@@ -1803,7 +1816,7 @@ static GtkWidget *
xg_get_file_with_chooser (FRAME_PTR f,
char *prompt,
char *default_filename,
- int mustmatch_p, int only_dir_p,
+ bool mustmatch_p, bool only_dir_p,
xg_get_file_func *func)
{
char msgbuf[1024];
@@ -1915,7 +1928,7 @@ xg_get_file_name_from_selector (GtkWidget *w)
F is the current frame.
PROMPT is a prompt to show to the user. May not be NULL.
DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
- If MUSTMATCH_P is non-zero, the returned file name must be an existing
+ If MUSTMATCH_P, the returned file name must be an existing
file. *FUNC is set to a function that can be used to retrieve the
selected file name from the returned widget.
@@ -1925,7 +1938,7 @@ static GtkWidget *
xg_get_file_with_selection (FRAME_PTR f,
char *prompt,
char *default_filename,
- int mustmatch_p, int only_dir_p,
+ bool mustmatch_p, bool only_dir_p,
xg_get_file_func *func)
{
GtkWidget *filewin;
@@ -1957,7 +1970,7 @@ xg_get_file_with_selection (FRAME_PTR f,
F is the current frame.
PROMPT is a prompt to show to the user. May not be NULL.
DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
- If MUSTMATCH_P is non-zero, the returned file name must be an existing
+ If MUSTMATCH_P, the returned file name must be an existing
file.
Returns a file name or NULL if no file was selected.
@@ -1967,21 +1980,14 @@ char *
xg_get_file_name (FRAME_PTR f,
char *prompt,
char *default_filename,
- int mustmatch_p,
- int only_dir_p)
+ bool mustmatch_p,
+ bool only_dir_p)
{
GtkWidget *w = 0;
char *fn = 0;
int filesel_done = 0;
xg_get_file_func func;
-#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
- /* I really don't know why this is needed, but without this the GLIBC add on
- library linuxthreads hangs when the Gnome file chooser backend creates
- threads. */
- sigblock (sigmask (__SIGRTMIN));
-#endif /* HAVE_PTHREAD */
-
#ifdef HAVE_GTK_FILE_SELECTION_NEW
if (xg_uses_old_file_dialog ())
@@ -1999,11 +2005,6 @@ xg_get_file_name (FRAME_PTR f,
gtk_widget_set_name (w, "emacs-filedialog");
filesel_done = xg_dialog_run (f, w);
-
-#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
- sigunblock (sigmask (__SIGRTMIN));
-#endif
-
if (filesel_done == GTK_RESPONSE_OK)
fn = (*func) (w);
@@ -2056,10 +2057,6 @@ xg_get_font (FRAME_PTR f, const char *default_name)
int done = 0;
Lisp_Object font = Qnil;
-#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
- sigblock (sigmask (__SIGRTMIN));
-#endif /* HAVE_PTHREAD */
-
w = gtk_font_chooser_dialog_new
("Pick a font", GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
@@ -2084,11 +2081,6 @@ xg_get_font (FRAME_PTR f, const char *default_name)
gtk_widget_set_name (w, "emacs-fontdialog");
done = xg_dialog_run (f, w);
-
-#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
- sigunblock (sigmask (__SIGRTMIN));
-#endif
-
if (done == GTK_RESPONSE_OK)
{
#if USE_NEW_GTK_FONT_CHOOSER
@@ -2426,9 +2418,9 @@ make_menu_item (const char *utf8_label,
static int xg_detached_menus;
-/* Returns non-zero if there are detached menus. */
+/* Return true if there are detached menus. */
-int
+bool
xg_have_tear_offs (void)
{
return xg_detached_menus > 0;
@@ -2532,10 +2524,9 @@ xg_create_one_menuitem (widget_value *item,
SELECT_CB is the callback to use when a menu item is selected.
DEACTIVATE_CB is the callback to use when a sub menu is not shown anymore.
HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
- POP_UP_P is non-zero if we shall create a popup menu.
- MENU_BAR_P is non-zero if we shall create a menu bar.
- ADD_TEAROFF_P is non-zero if we shall add a tearoff menu item. Ignored
- if MENU_BAR_P is non-zero.
+ 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.
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)
@@ -2555,9 +2546,9 @@ create_menus (widget_value *data,
GCallback select_cb,
GCallback deactivate_cb,
GCallback highlight_cb,
- int pop_up_p,
- int menu_bar_p,
- int add_tearoff_p,
+ bool pop_up_p,
+ bool menu_bar_p,
+ bool add_tearoff_p,
GtkWidget *topmenu,
xg_menu_cb_data *cl_data,
const char *name)
@@ -2697,8 +2688,8 @@ xg_create_widget (const char *type, const char *name, FRAME_PTR f, widget_value
GCallback highlight_cb)
{
GtkWidget *w = 0;
- int menu_bar_p = strcmp (type, "menubar") == 0;
- int pop_up_p = strcmp (type, "popup") == 0;
+ bool menu_bar_p = strcmp (type, "menubar") == 0;
+ bool pop_up_p = strcmp (type, "popup") == 0;
if (strcmp (type, "dialog") == 0)
{
@@ -2751,12 +2742,12 @@ xg_get_menu_item_label (GtkMenuItem *witem)
return gtk_label_get_label (wlabel);
}
-/* Return non-zero if the menu item WITEM has the text LABEL. */
+/* Return true if the menu item WITEM has the text LABEL. */
-static int
+static bool
xg_item_label_same_p (GtkMenuItem *witem, const char *label)
{
- int is_same = 0;
+ bool is_same = 0;
char *utf8_label = get_utf8_string (label);
const char *old_label = witem ? xg_get_menu_item_label (witem) : 0;
@@ -2847,8 +2838,8 @@ xg_update_menubar (GtkWidget *menubar,
{
GtkMenuItem *witem = GTK_MENU_ITEM (iter->data);
GtkMenuItem *witem2 = 0;
- int val_in_menubar = 0;
- int iter_in_new_menubar = 0;
+ bool val_in_menubar = 0;
+ bool iter_in_new_menubar = 0;
GList *iter2;
widget_value *cur;
@@ -3126,7 +3117,7 @@ xg_update_submenu (GtkWidget *submenu,
GList *list = 0;
GList *iter;
widget_value *cur;
- int has_tearoff_p = 0;
+ bool has_tearoff_p = 0;
GList *first_radio = 0;
if (submenu)
@@ -3248,7 +3239,7 @@ xg_update_submenu (GtkWidget *submenu,
/* Update the MENUBAR.
F is the frame the menu bar belongs to.
VAL describes the contents of the menu bar.
- If DEEP_P is non-zero, rebuild all but the top level menu names in
+ If DEEP_P, rebuild all but the top level menu names in
the MENUBAR. If DEEP_P is zero, just rebuild the names in the menubar.
SELECT_CB is the callback to use when a menu item is selected.
DEACTIVATE_CB is the callback to use when a sub menu is not shown anymore.
@@ -3256,7 +3247,7 @@ xg_update_submenu (GtkWidget *submenu,
void
xg_modify_menubar_widgets (GtkWidget *menubar, FRAME_PTR f, widget_value *val,
- int deep_p,
+ bool deep_p,
GCallback select_cb, GCallback deactivate_cb,
GCallback highlight_cb)
{
@@ -3340,21 +3331,21 @@ menubar_map_cb (GtkWidget *w, gpointer user_data)
}
/* Recompute all the widgets of frame F, when the menu bar has been
- changed. Value is non-zero if widgets were updated. */
+ changed. */
-int
+void
xg_update_frame_menubar (FRAME_PTR f)
{
struct x_output *x = f->output_data.x;
GtkRequisition req;
if (!x->menubar_widget || gtk_widget_get_mapped (x->menubar_widget))
- return 0;
+ return;
if (x->menubar_widget && gtk_widget_get_parent (x->menubar_widget))
- return 0; /* Already done this, happens for frames created invisible. */
+ return; /* Already done this, happens for frames created invisible. */
- BLOCK_INPUT;
+ block_input ();
gtk_box_pack_start (GTK_BOX (x->vbox_widget), x->menubar_widget,
FALSE, FALSE, 0);
@@ -3374,9 +3365,7 @@ xg_update_frame_menubar (FRAME_PTR f)
FRAME_MENUBAR_HEIGHT (f) = req.height;
xg_height_or_width_changed (f);
}
- UNBLOCK_INPUT;
-
- return 1;
+ unblock_input ();
}
/* Get rid of the menu bar of frame F, and free its storage.
@@ -3389,7 +3378,7 @@ free_frame_menubar (FRAME_PTR f)
if (x->menubar_widget)
{
- BLOCK_INPUT;
+ block_input ();
gtk_container_remove (GTK_CONTAINER (x->vbox_widget), x->menubar_widget);
/* The menubar and its children shall be deleted when removed from
@@ -3397,11 +3386,11 @@ free_frame_menubar (FRAME_PTR f)
x->menubar_widget = 0;
FRAME_MENUBAR_HEIGHT (f) = 0;
xg_height_or_width_changed (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
-int
+bool
xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
{
struct x_output *x = f->output_data.x;
@@ -3448,7 +3437,7 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
break;
}
g_list_free (list);
- return iter == 0 ? 0 : 1;
+ return iter != 0;
}
@@ -3461,7 +3450,7 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
/* Setting scroll bar values invokes the callback. Use this variable
to indicate that callback should do nothing. */
-int xg_ignore_gtk_scrollbar;
+bool xg_ignore_gtk_scrollbar;
/* The width of the scroll bar for the current theme. */
@@ -3519,7 +3508,7 @@ xg_store_widget_in_map (GtkWidget *w)
}
/* Should never end up here */
- abort ();
+ emacs_abort ();
}
/* Remove pointer at IDX from id_to_widget.
@@ -3787,7 +3776,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
int size, value;
int old_size;
int new_step;
- int changed = 0;
+ bool changed = 0;
adj = gtk_range_get_adjustment (GTK_RANGE (wscroll));
@@ -3807,13 +3796,8 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
shown = (gdouble) portion / whole;
}
- size = shown * XG_SB_RANGE;
- size = min (size, XG_SB_RANGE);
- size = max (size, 1);
-
- value = top * XG_SB_RANGE;
- value = min (value, XG_SB_MAX - size);
- value = max (value, XG_SB_MIN);
+ size = clip_to_bounds (1, shown * XG_SB_RANGE, XG_SB_RANGE);
+ value = clip_to_bounds (XG_SB_MIN, top * XG_SB_RANGE, XG_SB_MAX - size);
/* Assume all lines are of equal size. */
new_step = size / max (1, FRAME_LINES (f));
@@ -3834,7 +3818,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
{
- BLOCK_INPUT;
+ block_input ();
/* gtk_range_set_value invokes the callback. Set
ignore_gtk_scrollbar to make the callback do nothing */
@@ -3847,22 +3831,20 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
xg_ignore_gtk_scrollbar = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
}
-/* Return non-zero if EVENT is for a scroll bar in frame F.
+/* 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
- frame. This function does additional checks.
-
- Return non-zero if the event is for a scroll bar, zero otherwise. */
+ frame. This function does additional checks. */
-int
+bool
xg_event_is_for_scrollbar (FRAME_PTR f, XEvent *event)
{
- int retval = 0;
+ bool retval = 0;
if (f && event->type == ButtonPress && event->xbutton.button < 4)
{
@@ -4087,7 +4069,7 @@ xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
else
{
fprintf (stderr, "internal error: GTK_IMAGE_PIXBUF failed\n");
- abort ();
+ emacs_abort ();
}
}
else if (store_type == GTK_IMAGE_ICON_NAME)
@@ -4102,7 +4084,7 @@ xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
else
{
fprintf (stderr, "internal error: store_type is %d\n", store_type);
- abort ();
+ emacs_abort ();
}
}
if (wmenuimage)
@@ -4293,7 +4275,7 @@ static void
xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
{
struct x_output *x = f->output_data.x;
- int into_hbox = EQ (pos, Qleft) || EQ (pos, Qright);
+ bool into_hbox = EQ (pos, Qleft) || EQ (pos, Qright);
toolbar_set_orientation (x->toolbar_widget,
into_hbox
@@ -4325,7 +4307,7 @@ xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
}
else
{
- int vbox_pos = x->menubar_widget ? 1 : 0;
+ bool vbox_pos = x->menubar_widget != 0;
gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (x->handlebox_widget),
GTK_POS_LEFT);
gtk_box_pack_start (GTK_BOX (x->vbox_widget), x->handlebox_widget,
@@ -4416,7 +4398,7 @@ xg_make_tool_item (FRAME_PTR f,
GtkWidget *wimage,
GtkWidget **wbutton,
const char *label,
- int i, int horiz, int text_image)
+ int i, bool horiz, bool text_image)
{
GtkToolItem *ti = gtk_tool_item_new ();
GtkWidget *vb = gtk_box_new (horiz
@@ -4511,11 +4493,11 @@ xg_make_tool_item (FRAME_PTR f,
return ti;
}
-static int
-is_box_type (GtkWidget *vb, int is_horizontal)
+static bool
+is_box_type (GtkWidget *vb, bool is_horizontal)
{
#ifdef HAVE_GTK3
- int ret = 0;
+ bool ret = 0;
if (GTK_IS_BOX (vb))
{
GtkOrientation ori = gtk_orientable_get_orientation (GTK_ORIENTABLE (vb));
@@ -4529,10 +4511,10 @@ is_box_type (GtkWidget *vb, int is_horizontal)
}
-static int
+static bool
xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
const char *icon_name, const struct image *img,
- const char *label, int horiz)
+ const char *label, bool horiz)
{
gpointer old;
GtkWidget *wimage;
@@ -4574,7 +4556,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
return 0;
}
-static int
+static bool
xg_update_tool_bar_sizes (FRAME_PTR f)
{
struct x_output *x = f->output_data.x;
@@ -4630,15 +4612,15 @@ update_frame_tool_bar (FRAME_PTR f)
GtkToolbar *wtoolbar;
GtkToolItem *ti;
GtkTextDirection dir;
- int pack_tool_bar = x->handlebox_widget == NULL;
+ bool pack_tool_bar = x->handlebox_widget == NULL;
Lisp_Object style;
- int text_image, horiz;
+ bool text_image, horiz;
struct xg_frame_tb_info *tbinfo;
if (! FRAME_GTK_WIDGET (f))
return;
- BLOCK_INPUT;
+ block_input ();
if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
{
@@ -4680,7 +4662,7 @@ update_frame_tool_bar (FRAME_PTR f)
&& ! NILP (Fequal (tbinfo->style, style))
&& ! NILP (Fequal (tbinfo->last_tool_bar, f->tool_bar_items)))
{
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
@@ -4696,8 +4678,8 @@ update_frame_tool_bar (FRAME_PTR f)
for (i = j = 0; i < f->n_tool_bar_items; ++i)
{
- int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
- int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
+ bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
+ bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
int idx;
ptrdiff_t img_id;
int icon_size = 0;
@@ -4710,7 +4692,7 @@ update_frame_tool_bar (FRAME_PTR f)
Lisp_Object rtl;
GtkWidget *wbutton = NULL;
Lisp_Object specified_file;
- int vert_only = ! NILP (PROP (TOOL_BAR_ITEM_VERT_ONLY));
+ bool vert_only = ! NILP (PROP (TOOL_BAR_ITEM_VERT_ONLY));
const char *label
= (EQ (style, Qimage) || (vert_only && horiz)) ? NULL
: STRINGP (PROP (TOOL_BAR_ITEM_LABEL))
@@ -4891,7 +4873,7 @@ update_frame_tool_bar (FRAME_PTR f)
xg_height_or_width_changed (f);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Deallocate all resources for the tool bar on frame F.
@@ -4905,8 +4887,8 @@ free_frame_tool_bar (FRAME_PTR f)
if (x->toolbar_widget)
{
struct xg_frame_tb_info *tbinfo;
- int is_packed = x->handlebox_widget != 0;
- BLOCK_INPUT;
+ bool is_packed = x->handlebox_widget != 0;
+ 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 (is_packed)
@@ -4938,19 +4920,19 @@ free_frame_tool_bar (FRAME_PTR f)
xg_height_or_width_changed (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
-int
+void
xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos)
{
struct x_output *x = f->output_data.x;
if (! x->toolbar_widget || ! x->handlebox_widget)
- return 1;
+ return;
- BLOCK_INPUT;
+ block_input ();
g_object_ref (x->handlebox_widget);
if (x->toolbar_in_hbox)
gtk_container_remove (GTK_CONTAINER (x->hbox_widget),
@@ -4963,8 +4945,7 @@ xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos)
if (xg_update_tool_bar_sizes (f))
xg_height_or_width_changed (f);
- UNBLOCK_INPUT;
- return 1;
+ unblock_input ();
}
diff --git a/src/gtkutil.h b/src/gtkutil.h
index 926478dd728..43f2b237a68 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -79,13 +79,13 @@ struct _widget_value;
extern struct _widget_value *malloc_widget_value (void);
extern void free_widget_value (struct _widget_value *);
-extern int xg_uses_old_file_dialog (void) ATTRIBUTE_CONST;
+extern bool xg_uses_old_file_dialog (void) ATTRIBUTE_CONST;
extern char *xg_get_file_name (FRAME_PTR f,
char *prompt,
char *default_filename,
- int mustmatch_p,
- int only_dir_p);
+ bool mustmatch_p,
+ bool only_dir_p);
extern Lisp_Object xg_get_font (FRAME_PTR f, const char *);
@@ -100,16 +100,16 @@ extern GtkWidget *xg_create_widget (const char *type,
extern void xg_modify_menubar_widgets (GtkWidget *menubar,
FRAME_PTR f,
struct _widget_value *val,
- int deep_p,
+ bool deep_p,
GCallback select_cb,
GCallback deactivate_cb,
GCallback highlight_cb);
-extern int xg_update_frame_menubar (FRAME_PTR f);
+extern void xg_update_frame_menubar (FRAME_PTR f);
-extern int xg_event_is_for_menubar (FRAME_PTR f, XEvent *event);
+extern bool xg_event_is_for_menubar (FRAME_PTR f, XEvent *event);
-extern int xg_have_tear_offs (void);
+extern bool xg_have_tear_offs (void);
extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid);
@@ -131,12 +131,12 @@ extern void xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
int portion,
int position,
int whole);
-extern int xg_event_is_for_scrollbar (FRAME_PTR f, XEvent *event);
+extern bool xg_event_is_for_scrollbar (FRAME_PTR f, XEvent *event);
extern int xg_get_default_scrollbar_width (void);
extern void update_frame_tool_bar (FRAME_PTR f);
extern void free_frame_tool_bar (FRAME_PTR f);
-extern int xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos);
+extern void xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos);
extern void xg_frame_resized (FRAME_PTR f,
int pixelwidth,
@@ -148,23 +148,23 @@ extern void xg_display_open (char *display_name, Display **dpy);
extern void xg_display_close (Display *dpy);
extern GdkCursor * xg_create_default_cursor (Display *dpy);
-extern int xg_create_frame_widgets (FRAME_PTR f);
+extern bool xg_create_frame_widgets (FRAME_PTR f);
extern void xg_free_frame_widgets (FRAME_PTR f);
extern void xg_set_background_color (FRAME_PTR f, unsigned long bg);
-extern int xg_check_special_colors (struct frame *f,
- const char *color_name,
- XColor *color);
+extern bool xg_check_special_colors (struct frame *f,
+ const char *color_name,
+ XColor *color);
extern void xg_set_frame_icon (FRAME_PTR f,
Pixmap icon_pixmap,
Pixmap icon_mask);
-extern int xg_prepare_tooltip (FRAME_PTR f,
- Lisp_Object string,
- int *width,
- int *height);
+extern bool xg_prepare_tooltip (FRAME_PTR f,
+ Lisp_Object string,
+ int *width,
+ int *height);
extern void xg_show_tooltip (FRAME_PTR f, int root_x, int root_y);
-extern int xg_hide_tooltip (FRAME_PTR f);
+extern bool xg_hide_tooltip (FRAME_PTR f);
/* Mark all callback data that are Lisp_object:s during GC. */
@@ -175,7 +175,7 @@ extern void xg_initialize (void);
/* Setting scrollbar values invokes the callback. Use this variable
to indicate that the callback should do nothing. */
-extern int xg_ignore_gtk_scrollbar;
+extern bool xg_ignore_gtk_scrollbar;
#endif /* USE_GTK */
#endif /* GTKUTIL_H */
diff --git a/src/image.c b/src/image.c
index 3e021677e09..07db6cece1f 100644
--- a/src/image.c
+++ b/src/image.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <math.h>
#include <unistd.h>
#ifdef HAVE_PNG
@@ -76,7 +75,12 @@ typedef struct x_bitmap_record Bitmap_Record;
#endif /* HAVE_X_WINDOWS */
#ifdef HAVE_NTGUI
-#include "w32.h"
+
+/* We need (or want) w32.h only when we're _not_ compiling for Cygwin. */
+#ifdef WINDOWSNT
+# include "w32.h"
+#endif
+
/* W32_TODO : Color tables on W32. */
#undef COLOR_TABLE_SUPPORT
@@ -187,11 +191,11 @@ x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
}
#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
-int
+ptrdiff_t
x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
{
/* HAVE_NTGUI needs the explicit cast here. */
- return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
+ return (ptrdiff_t) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
}
#endif
@@ -408,9 +412,9 @@ x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id)
if (--bm->refcount == 0)
{
- BLOCK_INPUT;
+ block_input ();
free_bitmap_record (dpyinfo, bm);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
}
@@ -430,6 +434,9 @@ x_destroy_all_bitmaps (Display_Info *dpyinfo)
dpyinfo->bitmaps_last = 0;
}
+static bool x_create_x_image_and_pixmap (struct frame *, int, int, int,
+ XImagePtr *, Pixmap *);
+static void x_destroy_x_image (XImagePtr ximg);
#ifdef HAVE_X_WINDOWS
@@ -441,23 +448,17 @@ static unsigned long four_corners_best (XImagePtr ximg,
unsigned long width,
unsigned long height);
-static int x_create_x_image_and_pixmap (struct frame *f, int width, int height,
- int depth, XImagePtr *ximg,
- Pixmap *pixmap);
-
-static void x_destroy_x_image (XImagePtr ximg);
-
/* Create a mask of a bitmap. Note is this not a perfect mask.
It's nicer with some borders in this context */
-int
+void
x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
{
Pixmap pixmap, mask;
XImagePtr ximg, mask_img;
unsigned long width, height;
- int result;
+ bool result;
unsigned long bg;
unsigned long x, y, xp, xm, yp, ym;
GC gc;
@@ -465,29 +466,29 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
if (!(id > 0))
- return -1;
+ return;
pixmap = x_bitmap_pixmap (f, id);
width = x_bitmap_width (f, id);
height = x_bitmap_height (f, id);
- BLOCK_INPUT;
+ block_input ();
ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
~0, ZPixmap);
if (!ximg)
{
- UNBLOCK_INPUT;
- return -1;
+ unblock_input ();
+ return;
}
result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
- UNBLOCK_INPUT;
+ unblock_input ();
if (!result)
{
XDestroyImage (ximg);
- return -1;
+ return;
}
bg = four_corners_best (ximg, NULL, width, height);
@@ -515,7 +516,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
}
}
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
width, height);
@@ -526,8 +527,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
XDestroyImage (ximg);
x_destroy_x_image (mask_img);
-
- return 0;
}
#endif /* HAVE_X_WINDOWS */
@@ -560,16 +559,15 @@ static Lisp_Object QCcrop, QCrotation;
static Lisp_Object Qcount, Qextension_data, Qdelay;
static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
-/* Function prototypes. */
+/* Forward function prototypes. */
-static Lisp_Object define_image_type (struct image_type *type, int loaded);
-static struct image_type *lookup_image_type (Lisp_Object symbol);
-static void image_error (const char *format, Lisp_Object, Lisp_Object);
+static struct image_type *lookup_image_type (Lisp_Object);
static void x_laplace (struct frame *, struct image *);
static void x_emboss (struct frame *, struct image *);
-static int x_build_heuristic_mask (struct frame *, struct image *,
- Lisp_Object);
-#ifdef HAVE_NTGUI
+static void x_build_heuristic_mask (struct frame *, struct image *,
+ Lisp_Object);
+#ifdef WINDOWSNT
+extern Lisp_Object Vlibrary_cache;
#define CACHE_IMAGE_TYPE(type, status) \
do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
#else
@@ -582,60 +580,61 @@ static int x_build_heuristic_mask (struct frame *, struct image *,
/* Define a new image type from TYPE. This adds a copy of TYPE to
image_types and caches the loading status of TYPE. */
-static Lisp_Object
-define_image_type (struct image_type *type, int loaded)
+static struct image_type *
+define_image_type (struct image_type *type)
{
- Lisp_Object success;
+ struct image_type *p = NULL;
+ Lisp_Object target_type = *type->type;
+ bool type_valid = 1;
- if (!loaded)
- success = Qnil;
- else
+ block_input ();
+
+ for (p = image_types; p; p = p->next)
+ if (EQ (*p->type, target_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);
+ if (CONSP (tested) && NILP (XCDR (tested)))
+ type_valid = 0;
+ else
+#endif
+ {
+ type_valid = type->init ();
+ CACHE_IMAGE_TYPE (target_type, type_valid ? Qt : Qnil);
+ }
+ }
+
+ if (type_valid)
{
/* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
The initialized data segment is read-only. */
- struct image_type *p = xmalloc (sizeof *p);
- memcpy (p, type, sizeof *p);
+ p = xmalloc (sizeof *p);
+ *p = *type;
p->next = image_types;
image_types = p;
- success = Qt;
}
- CACHE_IMAGE_TYPE (*type->type, success);
- return success;
-}
-
-
-/* Look up image type SYMBOL, and return a pointer to its image_type
- structure. Value is null if SYMBOL is not a known image type. */
-
-static inline struct image_type *
-lookup_image_type (Lisp_Object symbol)
-{
- struct image_type *type;
-
- /* We must initialize the image-type if it hasn't been already. */
- if (NILP (Finit_image_library (symbol, Vdynamic_library_alist)))
- return 0; /* unimplemented */
-
- for (type = image_types; type; type = type->next)
- if (EQ (symbol, *type->type))
- break;
-
- return type;
+ done:
+ unblock_input ();
+ return p;
}
-/* Value is non-zero if OBJECT is a valid Lisp image specification. A
+/* Value is true if OBJECT is a valid Lisp image specification. A
valid image specification is a list whose car is the symbol
`image', and whose rest is a property list. The property list must
contain a value for key `:type'. That value must be the name of a
supported image type. The rest of the property list depends on the
image type. */
-int
+bool
valid_image_p (Lisp_Object object)
{
- int valid_p = 0;
+ bool valid_p = 0;
if (IMAGEP (object))
{
@@ -705,8 +704,8 @@ struct image_keyword
/* The type of value allowed. */
enum image_value_type type;
- /* Non-zero means key must be present. */
- int mandatory_p;
+ /* True means key must be present. */
+ bool mandatory_p;
/* Used to recognize duplicate keywords in a property list. */
int count;
@@ -716,18 +715,13 @@ struct image_keyword
};
-static int parse_image_spec (Lisp_Object, struct image_keyword *,
- int, Lisp_Object);
-static Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, int *);
-
-
/* Parse image spec SPEC according to KEYWORDS. A valid image spec
has the format (image KEYWORD VALUE ...). One of the keyword/
value pairs must be `:type TYPE'. KEYWORDS is a vector of
image_keywords structures of size NKEYWORDS describing other
- allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
+ allowed keyword/value pairs. Value is true if SPEC is valid. */
-static int
+static bool
parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
int nkeywords, Lisp_Object type)
{
@@ -841,7 +835,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
break;
default:
- abort ();
+ emacs_abort ();
break;
}
@@ -859,11 +853,11 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
/* Return the value of KEY in image specification SPEC. Value is nil
- if KEY is not present in SPEC. if FOUND is not null, set *FOUND
- to 1 if KEY was found in SPEC, set it to 0 otherwise. */
+ if KEY is not present in SPEC. Set *FOUND depending on whether KEY
+ was found in SPEC. */
static Lisp_Object
-image_spec_value (Lisp_Object spec, Lisp_Object key, int *found)
+image_spec_value (Lisp_Object spec, Lisp_Object key, bool *found)
{
Lisp_Object tail;
@@ -967,8 +961,6 @@ or omitted means use the selected frame. */)
Image type independent image structures
***********************************************************************/
-static void free_image (struct frame *f, struct image *img);
-
#define MAX_IMAGE_SIZE 10.0
/* Allocate and return a new image structure for image specification
SPEC. SPEC has a hash value of HASH. */
@@ -1018,10 +1010,9 @@ free_image (struct frame *f, struct image *img)
}
}
-/* Return 1 if the given widths and heights are valid for display;
- otherwise, return 0. */
+/* Return true if the given widths and heights are valid for display. */
-static int
+static bool
check_image_size (struct frame *f, int width, int height)
{
int w, h;
@@ -1060,7 +1051,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
- img->load_failed_p = img->type->load (f, img) == 0;
+ img->load_failed_p = ! img->type->load (f, img);
}
@@ -1193,7 +1184,7 @@ image_background (struct image *img, struct frame *f, XImagePtr_or_DC ximg)
if (! img->background_valid)
/* IMG doesn't have a background yet, try to guess a reasonable value. */
{
- int free_ximg = !ximg;
+ bool free_ximg = !ximg;
#ifdef HAVE_NTGUI
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
@@ -1234,7 +1225,7 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
{
if (img->mask)
{
- int free_mask = !mask;
+ bool free_mask = !mask;
#ifdef HAVE_NTGUI
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
@@ -1272,23 +1263,13 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
Helper functions for X image types
***********************************************************************/
-static void x_clear_image_1 (struct frame *, struct image *, int,
- int, int);
-static void x_clear_image (struct frame *f, struct image *img);
-static unsigned long x_alloc_image_color (struct frame *f,
- struct image *img,
- Lisp_Object color_name,
- unsigned long dflt);
-
-
-/* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
- free the pixmap if any. MASK_P non-zero means clear the mask
- pixmap if any. COLORS_P non-zero means free colors allocated for
- the image, if any. */
+/* Clear X resources of image IMG on frame F. PIXMAP_P means free the
+ pixmap if any. MASK_P means clear the mask pixmap if any.
+ COLORS_P means free colors allocated for the image, if any. */
static void
-x_clear_image_1 (struct frame *f, struct image *img, int pixmap_p, int mask_p,
- int colors_p)
+x_clear_image_1 (struct frame *f, struct image *img, bool pixmap_p,
+ bool mask_p, bool colors_p)
{
if (pixmap_p && img->pixmap)
{
@@ -1323,9 +1304,9 @@ x_clear_image_1 (struct frame *f, struct image *img, int pixmap_p, int mask_p,
static void
x_clear_image (struct frame *f, struct image *img)
{
- BLOCK_INPUT;
+ block_input ();
x_clear_image_1 (f, img, 1, 1, 1);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1368,7 +1349,6 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
***********************************************************************/
static void cache_image (struct frame *f, struct image *img);
-static void postprocess_image (struct frame *, struct image *);
/* Return a new, initialized image cache that is allocated from the
heap. Call free_image_cache to free an image cache. */
@@ -1480,7 +1460,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
/* Block input so that we won't be interrupted by a SIGIO
while being in an inconsistent state. */
- BLOCK_INPUT;
+ block_input ();
if (!NILP (filter))
{
@@ -1546,7 +1526,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
++windows_or_buffers_changed;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1641,7 +1621,7 @@ postprocess_image (struct frame *f, struct image *img)
x_build_heuristic_mask (f, img, mask);
else
{
- int found_p;
+ bool found_p;
mask = image_spec_value (spec, QCmask, &found_p);
@@ -1711,10 +1691,10 @@ lookup_image (struct frame *f, Lisp_Object spec)
/* If not found, create a new image and cache it. */
if (img == NULL)
{
- BLOCK_INPUT;
+ block_input ();
img = make_image (spec, hash);
cache_image (f, img);
- img->load_failed_p = img->type->load (f, img) == 0;
+ img->load_failed_p = ! img->type->load (f, img);
img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
img->frame_background = FRAME_BACKGROUND_PIXEL (f);
@@ -1782,7 +1762,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
postprocess_image (f, img);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* We're using IMG, so set its timestamp to `now'. */
@@ -1860,7 +1840,7 @@ mark_image_cache (struct image_cache *c)
X / NS / W32 support code
***********************************************************************/
-#ifdef HAVE_NTGUI
+#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
@@ -1871,18 +1851,13 @@ mark_image_cache (struct image_cache *c)
if (!fn_##func) return 0; \
}
-#endif /* HAVE_NTGUI */
-
-static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
- XImagePtr *, Pixmap *);
-static void x_destroy_x_image (XImagePtr);
-static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int);
+#endif /* WINDOWSNT */
-/* Return nonzero if XIMG's size WIDTH x HEIGHT doesn't break the
+/* Return true if XIMG's size WIDTH x HEIGHT doesn't break the
windowing system.
WIDTH and HEIGHT must both be positive.
If XIMG is null, assume it is a bitmap. */
-static int
+static bool
x_check_image_size (XImagePtr ximg, int width, int height)
{
#ifdef HAVE_X_WINDOWS
@@ -1921,12 +1896,12 @@ x_check_image_size (XImagePtr ximg, int width, int height)
frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
via xmalloc. Print error messages via image_error if an error
- occurs. Value is non-zero if successful.
+ occurs. Value is true if successful.
On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
should indicate the bit depth of the image. */
-static int
+static bool
x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
XImagePtr *ximg, Pixmap *pixmap)
{
@@ -1935,7 +1910,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
Window window = FRAME_X_WINDOW (f);
Screen *screen = FRAME_X_SCREEN (f);
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
if (depth <= 0)
depth = DefaultDepthOfScreen (screen);
@@ -2073,7 +2048,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
static void
x_destroy_x_image (XImagePtr ximg)
{
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
if (ximg)
{
#ifdef HAVE_X_WINDOWS
@@ -2102,7 +2077,7 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
#ifdef HAVE_X_WINDOWS
GC gc;
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
XFreeGC (FRAME_X_DISPLAY (f), gc);
@@ -2165,12 +2140,11 @@ x_find_image_file (Lisp_Object file)
static unsigned char *
slurp_file (char *file, ptrdiff_t *size)
{
- FILE *fp = NULL;
+ FILE *fp = fopen (file, "rb");
unsigned char *buf = NULL;
struct stat st;
- if (stat (file, &st) == 0
- && (fp = fopen (file, "rb")) != NULL
+ if (fp && fstat (fileno (fp), &st) == 0
&& 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
&& (buf = xmalloc (st.st_size),
fread (buf, 1, st.st_size, fp) == st.st_size))
@@ -2198,15 +2172,9 @@ slurp_file (char *file, ptrdiff_t *size)
XBM images
***********************************************************************/
-static int xbm_scan (unsigned char **, unsigned char *, char *, int *);
-static int xbm_load (struct frame *f, struct image *img);
-static int xbm_load_image (struct frame *f, struct image *img,
- unsigned char *, unsigned char *);
-static int xbm_image_p (Lisp_Object object);
-static int xbm_read_bitmap_data (struct frame *f,
- unsigned char *, unsigned char *,
- int *, int *, char **, int);
-static int xbm_file_p (Lisp_Object);
+static bool xbm_load (struct frame *f, struct image *img);
+static bool xbm_image_p (Lisp_Object object);
+static bool xbm_file_p (Lisp_Object);
/* Indices of image specification fields in xbm_format, below. */
@@ -2257,6 +2225,7 @@ static struct image_type xbm_type =
xbm_image_p,
xbm_load,
x_clear_image,
+ NULL,
NULL
};
@@ -2269,10 +2238,10 @@ enum xbm_token
};
-/* Return non-zero if OBJECT is a valid XBM-type image specification.
+/* Return true if OBJECT is a valid XBM-type image specification.
A valid specification is a list starting with the symbol `image'
The rest of the list is a property list which must contain an
- entry `:type xbm..
+ entry `:type xbm'.
If the specification specifies a file to load, it must contain
an entry `:file FILENAME' where FILENAME is a string.
@@ -2298,7 +2267,7 @@ enum xbm_token
foreground and background of the frame on which the image is
displayed is used. */
-static int
+static bool
xbm_image_p (Lisp_Object object)
{
struct image_keyword kw[XBM_LAST];
@@ -2556,7 +2525,7 @@ convert_mono_to_color_image (struct frame *f, struct image *img,
static void
Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg,
- int non_default_colors)
+ bool non_default_colors)
{
#ifdef HAVE_NTGUI
img->pixmap
@@ -2588,20 +2557,20 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
X versions. CONTENTS is a pointer to a buffer to parse; END is the
buffer's end. Set *WIDTH and *HEIGHT to the width and height of
the image. Return in *DATA the bitmap data allocated with xmalloc.
- Value is non-zero if successful. DATA null means just test if
- CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR
- is non-zero, inhibit the call to image_error when the image size is
- invalid (the bitmap remains unread). */
+ Value is true if successful. DATA null means just test if
+ CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR,
+ inhibit the call to image_error when the image size is invalid (the
+ bitmap remains unread). */
-static int
+static bool
xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *end,
int *width, int *height, char **data,
- int inhibit_image_error)
+ bool inhibit_image_error)
{
unsigned char *s = contents;
char buffer[BUFSIZ];
- int padding_p = 0;
- int v10 = 0;
+ bool padding_p = 0;
+ bool v10 = 0;
int bytes_per_line, i, nbytes;
char *p;
int value;
@@ -2748,16 +2717,16 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e
/* Load XBM image IMG which will be displayed on frame F from buffer
- CONTENTS. END is the end of the buffer. Value is non-zero if
+ CONTENTS. END is the end of the buffer. Value is true if
successful. */
-static int
+static bool
xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
unsigned char *end)
{
- int rc;
+ bool rc;
char *data;
- int success_p = 0;
+ bool success_p = 0;
rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
&data, 0);
@@ -2765,7 +2734,7 @@ xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
{
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
unsigned long background = FRAME_BACKGROUND_PIXEL (f);
- int non_default_colors = 0;
+ bool non_default_colors = 0;
Lisp_Object value;
eassert (img->width > 0 && img->height > 0);
@@ -2806,9 +2775,9 @@ xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
}
-/* Value is non-zero if DATA looks like an in-memory XBM file. */
+/* Value is true if DATA looks like an in-memory XBM file. */
-static int
+static bool
xbm_file_p (Lisp_Object data)
{
int w, h;
@@ -2820,12 +2789,12 @@ xbm_file_p (Lisp_Object data)
/* Fill image IMG which is used on frame F with pixmap data. Value is
- non-zero if successful. */
+ true if successful. */
-static int
+static bool
xbm_load (struct frame *f, struct image *img)
{
- int success_p = 0;
+ bool success_p = 0;
Lisp_Object file_name;
eassert (xbm_image_p (img->spec));
@@ -2861,10 +2830,10 @@ xbm_load (struct frame *f, struct image *img)
Lisp_Object data;
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
unsigned long background = FRAME_BACKGROUND_PIXEL (f);
- int non_default_colors = 0;
+ bool non_default_colors = 0;
char *bits;
- int parsed_p;
- int in_memory_file_p = 0;
+ bool parsed_p;
+ bool in_memory_file_p = 0;
/* See if data looks like an in-memory XBM file. */
data = image_spec_value (img->spec, QCdata, NULL);
@@ -2873,7 +2842,6 @@ xbm_load (struct frame *f, struct image *img)
/* Parse the image specification. */
memcpy (fmt, xbm_format, sizeof fmt);
parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
- (void) parsed_p;
eassert (parsed_p);
/* Get specified width, and height. */
@@ -2934,7 +2902,7 @@ xbm_load (struct frame *f, struct image *img)
else
bits = (char *) XBOOL_VECTOR (data)->data;
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
{
char *invertedBits;
int nbytes, i;
@@ -2978,9 +2946,8 @@ xbm_load (struct frame *f, struct image *img)
#if defined (HAVE_XPM) || defined (HAVE_NS)
-static int xpm_image_p (Lisp_Object object);
-static int xpm_load (struct frame *f, struct image *img);
-static int xpm_valid_color_symbols_p (Lisp_Object);
+static bool xpm_image_p (Lisp_Object object);
+static bool xpm_load (struct frame *f, struct image *img);
#endif /* HAVE_XPM || HAVE_NS */
@@ -3046,6 +3013,12 @@ static const struct image_keyword xpm_format[XPM_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_xpm_functions (void);
+#else
+#define init_xpm_functions NULL
+#endif
+
/* Structure describing the image type XPM. */
static struct image_type xpm_type =
@@ -3054,6 +3027,7 @@ static struct image_type xpm_type =
xpm_image_p,
xpm_load,
x_clear_image,
+ init_xpm_functions,
NULL
};
@@ -3071,10 +3045,6 @@ static struct image_type xpm_type =
#ifdef ALLOC_XPM_COLORS
-static void xpm_init_color_cache (struct frame *, XpmAttributes *);
-static void xpm_free_color_cache (void);
-static int xpm_lookup_color (struct frame *, char *, XColor *);
-static int xpm_color_bucket (char *);
static struct xpm_cached_color *xpm_cache_color (struct frame *, char *,
XColor *, int);
@@ -3181,10 +3151,10 @@ xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
/* Look up color COLOR_NAME for frame F in the color cache. If found,
return the cached definition in *COLOR. Otherwise, make a new
- entry in the cache and allocate the color. Value is zero if color
+ entry in the cache and allocate the color. Value is false if color
allocation failed. */
-static int
+static bool
xpm_lookup_color (struct frame *f, char *color_name, XColor *color)
{
struct xpm_cached_color *p;
@@ -3242,7 +3212,7 @@ xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *
#endif /* ALLOC_XPM_COLORS */
-#ifdef HAVE_NTGUI
+#ifdef WINDOWSNT
/* XPM library details. */
@@ -3253,12 +3223,12 @@ DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **,
xpm_XImage **, XpmAttributes *));
DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *));
-static int
-init_xpm_functions (Lisp_Object libraries)
+static bool
+init_xpm_functions (void)
{
HMODULE library;
- if (!(library = w32_delayed_load (libraries, Qxpm)))
+ if (!(library = w32_delayed_load (Qxpm)))
return 0;
LOAD_IMGLIB_FN (library, XpmFreeAttributes);
@@ -3268,14 +3238,21 @@ init_xpm_functions (Lisp_Object libraries)
return 1;
}
-#endif /* HAVE_NTGUI */
+#endif /* WINDOWSNT */
+#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 */
-/* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
+/* 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
cdr are strings. */
-static int
+static bool
xpm_valid_color_symbols_p (Lisp_Object color_symbols)
{
while (CONSP (color_symbols))
@@ -3292,9 +3269,9 @@ xpm_valid_color_symbols_p (Lisp_Object color_symbols)
}
-/* Value is non-zero if OBJECT is a valid XPM image specification. */
+/* Value is true if OBJECT is a valid XPM image specification. */
-static int
+static bool
xpm_image_p (Lisp_Object object)
{
struct image_keyword fmt[XPM_LAST];
@@ -3351,11 +3328,11 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
/* Load image IMG which will be displayed on frame F. Value is
- non-zero if successful. */
+ true if successful. */
#ifdef HAVE_XPM
-static int
+static bool
xpm_load (struct frame *f, struct image *img)
{
int rc;
@@ -3754,10 +3731,10 @@ xpm_make_color_table_h (void (**put_func) (Lisp_Object,
{
*put_func = xpm_put_color_table_h;
*get_func = xpm_get_color_table_h;
- return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
+ return make_hash_table (hashtest_equal, make_number (DEFAULT_HASH_SIZE),
make_float (DEFAULT_REHASH_SIZE),
make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
+ Qnil);
}
static void
@@ -3809,7 +3786,7 @@ xpm_str_to_color_key (const char *s)
return -1;
}
-static int
+static bool
xpm_load_image (struct frame *f,
struct image *img,
const unsigned char *contents,
@@ -3824,7 +3801,8 @@ xpm_load_image (struct frame *f,
void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
Lisp_Object frame, color_symbols, color_table;
- int best_key, have_mask = 0;
+ int best_key;
+ bool have_mask = 0;
XImagePtr ximg = NULL, mask_img = NULL;
#define match() \
@@ -4044,11 +4022,11 @@ xpm_load_image (struct frame *f,
#undef expect_ident
}
-static int
+static bool
xpm_load (struct frame *f,
struct image *img)
{
- int success_p = 0;
+ bool success_p = 0;
Lisp_Object file_name;
/* If IMG->spec specifies a file name, create a non-file spec from it. */
@@ -4219,7 +4197,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b)
#ifdef HAVE_X_WINDOWS
XColor color;
Colormap cmap;
- int rc;
+ bool rc;
#else
COLORREF color;
#endif
@@ -4287,7 +4265,7 @@ lookup_pixel_color (struct frame *f, unsigned long pixel)
{
XColor color;
Colormap cmap;
- int rc;
+ bool rc;
if (ct_colors_allocated_max <= ct_colors_allocated)
return FRAME_FOREGROUND_PIXEL (f);
@@ -4298,12 +4276,12 @@ lookup_pixel_color (struct frame *f, unsigned long pixel)
x_query_color (f, &color);
rc = x_alloc_nearest_color (f, cmap, &color);
#else
- BLOCK_INPUT;
+ block_input ();
cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
color.pixel = pixel;
XQueryColor (NULL, cmap, &color);
rc = x_alloc_nearest_color (f, cmap, &color);
- UNBLOCK_INPUT;
+ unblock_input ();
#endif /* HAVE_X_WINDOWS */
if (rc)
@@ -4381,14 +4359,6 @@ init_color_table (void)
Algorithms
***********************************************************************/
-static XColor *x_to_xcolors (struct frame *, struct image *, int);
-static void x_from_xcolors (struct frame *, struct image *, XColor *);
-static void x_detect_edges (struct frame *, struct image *, int[9], int);
-
-#ifdef HAVE_NTGUI
-static void XPutPixel (XImagePtr , int, int, COLORREF);
-#endif /* HAVE_NTGUI */
-
/* Edge detection matrices for different edge-detection
strategies. */
@@ -4414,12 +4384,12 @@ static int laplace_matrix[9] = {
/* On frame F, return an array of XColor structures describing image
IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
- non-zero means also fill the red/green/blue members of the XColor
+ means also fill the red/green/blue members of the XColor
structures. Value is a pointer to the array of XColors structures,
allocated with xmalloc; it must be freed by the caller. */
static XColor *
-x_to_xcolors (struct frame *f, struct image *img, int rgb_p)
+x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
{
int x, y;
XColor *colors, *p;
@@ -4795,9 +4765,9 @@ x_disable_image (struct frame *f, struct image *img)
determine the background color of IMG. If it is a list '(R G B)',
with R, G, and B being integers >= 0, take that as the color of the
background. Otherwise, determine the background color of IMG
- heuristically. Value is non-zero if successful. */
+ heuristically. */
-static int
+static void
x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
{
XImagePtr_or_DC ximg;
@@ -4809,7 +4779,8 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
char *mask_img;
int row_width;
#endif /* HAVE_NTGUI */
- int x, y, rc, use_img_background;
+ int x, y;
+ bool rc, use_img_background;
unsigned long bg = 0;
if (img->mask)
@@ -4825,7 +4796,7 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
&mask_img, &img->mask);
if (!rc)
- return 0;
+ return;
#endif /* !HAVE_NS */
/* Get the X image of IMG->pixmap. */
@@ -4915,8 +4886,6 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
#endif /* HAVE_NTGUI */
Destroy_Image (ximg, prev);
-
- return 1;
}
@@ -4924,9 +4893,8 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
PBM (mono, gray, color)
***********************************************************************/
-static int pbm_image_p (Lisp_Object object);
-static int pbm_load (struct frame *f, struct image *img);
-static int pbm_scan_number (unsigned char **, unsigned char *);
+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. */
@@ -4976,13 +4944,14 @@ static struct image_type pbm_type =
pbm_image_p,
pbm_load,
x_clear_image,
+ NULL,
NULL
};
-/* Return non-zero if OBJECT is a valid PBM image specification. */
+/* Return true if OBJECT is a valid PBM image specification. */
-static int
+static bool
pbm_image_p (Lisp_Object object)
{
struct image_keyword fmt[PBM_LAST];
@@ -5034,51 +5003,13 @@ pbm_scan_number (unsigned char **s, unsigned char *end)
}
-#ifdef HAVE_NTGUI
-#if 0 /* Unused. ++kfs */
-
-/* Read FILE into memory. Value is a pointer to a buffer allocated
- with xmalloc holding FILE's contents. Value is null if an error
- occurred. *SIZE is set to the size of the file. */
-
-static char *
-pbm_read_file (Lisp_Object file, int *size)
-{
- FILE *fp = NULL;
- char *buf = NULL;
- struct stat st;
-
- if (stat (SDATA (file), &st) == 0
- && (fp = fopen (SDATA (file), "rb")) != NULL
- && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
- && (buf = xmalloc (st.st_size),
- fread (buf, 1, st.st_size, fp) == st.st_size))
- {
- *size = st.st_size;
- fclose (fp);
- }
- else
- {
- if (fp)
- fclose (fp);
- if (buf)
- {
- xfree (buf);
- buf = NULL;
- }
- }
-
- return buf;
-}
-#endif
-#endif /* HAVE_NTGUI */
-
/* Load PBM image IMG for use on frame F. */
-static int
+static bool
pbm_load (struct frame *f, struct image *img)
{
- int raw_p, x, y;
+ bool raw_p;
+ int x, y;
int width, height, max_color_idx = 0;
XImagePtr ximg;
Lisp_Object file, specified_file;
@@ -5341,8 +5272,8 @@ pbm_load (struct frame *f, struct image *img)
/* Function prototypes. */
-static int png_image_p (Lisp_Object object);
-static int png_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. */
@@ -5382,6 +5313,12 @@ static const struct image_keyword png_format[PNG_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_png_functions (void);
+#else
+#define init_png_functions NULL
+#endif
+
/* Structure describing the image type `png'. */
static struct image_type png_type =
@@ -5390,12 +5327,13 @@ static struct image_type png_type =
png_image_p,
png_load,
x_clear_image,
+ init_png_functions,
NULL
};
-/* Return non-zero if OBJECT is a valid PNG image specification. */
+/* Return true if OBJECT is a valid PNG image specification. */
-static int
+static bool
png_image_p (Lisp_Object object)
{
struct image_keyword fmt[PNG_LAST];
@@ -5413,7 +5351,7 @@ png_image_p (Lisp_Object object)
#ifdef HAVE_PNG
-#ifdef HAVE_NTGUI
+#ifdef WINDOWSNT
/* PNG library details. */
DEF_IMGLIB_FN (png_voidp, png_get_io_ptr, (png_structp));
@@ -5447,12 +5385,12 @@ DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int));
DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t));
#endif /* libpng version >= 1.5 */
-static int
-init_png_functions (Lisp_Object libraries)
+static bool
+init_png_functions (void)
{
HMODULE library;
- if (!(library = w32_delayed_load (libraries, Qpng)))
+ if (!(library = w32_delayed_load (Qpng)))
return 0;
LOAD_IMGLIB_FN (library, png_get_io_ptr);
@@ -5513,8 +5451,17 @@ init_png_functions (Lisp_Object libraries)
#define fn_png_set_longjmp_fn png_set_longjmp_fn
#endif /* libpng version >= 1.5 */
-#endif /* HAVE_NTGUI */
+#endif /* WINDOWSNT */
+/* Possibly inefficient/inexact substitutes for _setjmp and _longjmp.
+ Do not use sys_setjmp, as PNG supports only jmp_buf. The _longjmp
+ substitute may munge the signal mask, but that should be OK here.
+ MinGW (MS-Windows) uses _setjmp and defines setjmp to _setjmp in
+ the system header setjmp.h; don't mess up that. */
+#ifndef HAVE__SETJMP
+# define _setjmp(j) setjmp (j)
+# define _longjmp longjmp
+#endif
#if (PNG_LIBPNG_VER < 10500)
#define PNG_LONGJMP(ptr) (_longjmp ((ptr)->jmpbuf, 1))
@@ -5589,28 +5536,39 @@ png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
}
-/* Load PNG image IMG for use on frame F. Value is non-zero if
+/* Load PNG image IMG for use on frame F. Value is true if
successful. */
-static int
-png_load (struct frame *f, struct image *img)
+struct png_load_context
+{
+ /* These are members so that longjmp doesn't munge local variables. */
+ png_struct *png_ptr;
+ png_info *info_ptr;
+ png_info *end_info;
+ FILE *fp;
+ png_byte *pixels;
+ png_byte **rows;
+};
+
+static bool
+png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
{
Lisp_Object file, specified_file;
Lisp_Object specified_data;
int x, y;
ptrdiff_t i;
XImagePtr ximg, mask_img = NULL;
- png_struct *png_ptr = NULL;
+ png_struct *png_ptr;
png_info *info_ptr = NULL, *end_info = NULL;
- FILE *volatile fp = NULL;
+ FILE *fp = NULL;
png_byte sig[8];
- png_byte * volatile pixels = NULL;
- png_byte ** volatile rows = NULL;
+ png_byte *pixels = NULL;
+ png_byte **rows = NULL;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
png_byte channels;
png_uint_32 row_bytes;
- int transparent_p;
+ bool transparent_p;
struct png_memory_storage tbr; /* Data to be read */
/* Find out what file to load. */
@@ -5672,24 +5630,26 @@ png_load (struct frame *f, struct image *img)
png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
NULL, my_png_error,
my_png_warning);
- if (!png_ptr)
+ if (png_ptr)
{
- if (fp) fclose (fp);
- return 0;
+ info_ptr = fn_png_create_info_struct (png_ptr);
+ end_info = fn_png_create_info_struct (png_ptr);
}
- info_ptr = fn_png_create_info_struct (png_ptr);
- if (!info_ptr)
+ c->png_ptr = png_ptr;
+ c->info_ptr = info_ptr;
+ c->end_info = end_info;
+ c->fp = fp;
+ c->pixels = pixels;
+ c->rows = rows;
+
+ if (! (info_ptr && end_info))
{
- fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
- if (fp) fclose (fp);
- return 0;
+ fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+ png_ptr = 0;
}
-
- end_info = fn_png_create_info_struct (png_ptr);
- if (!end_info)
+ if (! png_ptr)
{
- fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
if (fp) fclose (fp);
return 0;
}
@@ -5699,14 +5659,18 @@ png_load (struct frame *f, struct image *img)
if (_setjmp (PNG_JMPBUF (png_ptr)))
{
error:
- if (png_ptr)
- fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
- xfree (pixels);
- xfree (rows);
- if (fp) fclose (fp);
+ if (c->png_ptr)
+ fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+ xfree (c->pixels);
+ xfree (c->rows);
+ if (c->fp)
+ fclose (c->fp);
return 0;
}
+ /* Silence a bogus diagnostic; see GCC bug 54561. */
+ IF_LINT (fp = c->fp);
+
/* Read image info. */
if (!NILP (specified_data))
fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
@@ -5822,8 +5786,8 @@ png_load (struct frame *f, struct image *img)
if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
|| min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
memory_full (SIZE_MAX);
- pixels = xmalloc (sizeof *pixels * row_bytes * height);
- rows = xmalloc (height * sizeof *rows);
+ c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
+ c->rows = rows = xmalloc (height * sizeof *rows);
for (i = 0; i < height; ++i)
rows[i] = pixels + i * row_bytes;
@@ -5833,7 +5797,7 @@ png_load (struct frame *f, struct image *img)
if (fp)
{
fclose (fp);
- fp = NULL;
+ c->fp = NULL;
}
/* Create an image and pixmap serving as mask if the PNG image
@@ -5908,7 +5872,7 @@ png_load (struct frame *f, struct image *img)
#endif /* COLOR_TABLE_SUPPORT */
/* Clean up. */
- fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+ fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
xfree (rows);
xfree (pixels);
@@ -5937,10 +5901,17 @@ png_load (struct frame *f, struct image *img)
return 1;
}
+static bool
+png_load (struct frame *f, struct image *img)
+{
+ struct png_load_context c;
+ return png_load_body (f, img, &c);
+}
+
#else /* HAVE_PNG */
#ifdef HAVE_NS
-static int
+static bool
png_load (struct frame *f, struct image *img)
{
return ns_load_image (f, img,
@@ -5960,8 +5931,8 @@ png_load (struct frame *f, struct image *img)
#if defined (HAVE_JPEG) || defined (HAVE_NS)
-static int jpeg_image_p (Lisp_Object object);
-static int jpeg_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. */
@@ -6001,6 +5972,12 @@ static const struct image_keyword jpeg_format[JPEG_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_jpeg_functions (void);
+#else
+#define init_jpeg_functions NULL
+#endif
+
/* Structure describing the image type `jpeg'. */
static struct image_type jpeg_type =
@@ -6009,12 +5986,13 @@ static struct image_type jpeg_type =
jpeg_image_p,
jpeg_load,
x_clear_image,
+ init_jpeg_functions,
NULL
};
-/* Return non-zero if OBJECT is a valid JPEG image specification. */
+/* Return true if OBJECT is a valid JPEG image specification. */
-static int
+static bool
jpeg_image_p (Lisp_Object object)
{
struct image_keyword fmt[JPEG_LAST];
@@ -6044,14 +6022,27 @@ jpeg_image_p (Lisp_Object object)
#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,
+ using the Windows boolean type instead of the jpeglib boolean type
+ if so. Cygwin jpeglib, however, doesn't try to detect whether its
+ headers are included along with windows.h, so under Cygwin, jpeglib
+ attempts to define a conflicting boolean type. Worse, forcing
+ Cygwin jpeglib headers to use the Windows boolean type doesn't work
+ because it created an ABI incompatibility between the
+ already-compiled jpeg library and the header interface definition.
+
+ The best we can do is to define jpeglib's boolean type to a
+ 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>
-#ifdef HAVE_STLIB_H_1
-#define HAVE_STDLIB_H 1
-#endif
-
-#ifdef HAVE_NTGUI
+#ifdef WINDOWSNT
/* JPEG library details. */
DEF_IMGLIB_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
@@ -6063,12 +6054,12 @@ DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines, (j_decompress_ptr, JSAMPARRAY, J
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));
-static int
-init_jpeg_functions (Lisp_Object libraries)
+static bool
+init_jpeg_functions (void)
{
HMODULE library;
- if (!(library = w32_delayed_load (libraries, Qjpeg)))
+ if (!(library = w32_delayed_load (Qjpeg)))
return 0;
LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
@@ -6101,12 +6092,25 @@ jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
#define fn_jpeg_std_error jpeg_std_error
#define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
-#endif /* HAVE_NTGUI */
+#endif /* WINDOWSNT */
struct my_jpeg_error_mgr
{
struct jpeg_error_mgr pub;
- jmp_buf setjmp_buffer;
+ sys_jmp_buf setjmp_buffer;
+
+ /* The remaining members are so that longjmp doesn't munge local
+ variables. */
+ struct jpeg_decompress_struct cinfo;
+ enum
+ {
+ MY_JPEG_ERROR_EXIT,
+ MY_JPEG_INVALID_IMAGE_SIZE,
+ MY_JPEG_CANNOT_CREATE_X
+ } failure_code;
+#ifdef lint
+ FILE *fp;
+#endif
};
@@ -6114,7 +6118,8 @@ static _Noreturn void
my_error_exit (j_common_ptr cinfo)
{
struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
- _longjmp (mgr->setjmp_buffer, 1);
+ mgr->failure_code = MY_JPEG_ERROR_EXIT;
+ sys_longjmp (mgr->setjmp_buffer, 1);
}
@@ -6182,7 +6187,7 @@ our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
reading the image. */
static void
-jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
+jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len)
{
struct jpeg_source_mgr *src;
@@ -6319,18 +6324,16 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
/* Load image IMG for use on frame F. Patterned after example.c
from the JPEG lib. */
-static int
-jpeg_load (struct frame *f, struct image *img)
+static bool
+jpeg_load_body (struct frame *f, struct image *img,
+ struct my_jpeg_error_mgr *mgr)
{
- struct jpeg_decompress_struct cinfo;
- struct my_jpeg_error_mgr mgr;
Lisp_Object file, specified_file;
Lisp_Object specified_data;
- FILE * volatile fp = NULL;
+ FILE *fp = NULL;
JSAMPARRAY buffer;
int row_stride, x, y;
XImagePtr ximg = NULL;
- int rc;
unsigned long *colors;
int width, height;
@@ -6360,26 +6363,37 @@ jpeg_load (struct frame *f, struct image *img)
return 0;
}
+ IF_LINT (mgr->fp = fp);
+
/* Customize libjpeg's error handling to call my_error_exit when an
error is detected. This function will perform a longjmp. */
- cinfo.err = fn_jpeg_std_error (&mgr.pub);
- mgr.pub.error_exit = my_error_exit;
-
- if ((rc = _setjmp (mgr.setjmp_buffer)) != 0)
+ mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
+ mgr->pub.error_exit = my_error_exit;
+ if (sys_setjmp (mgr->setjmp_buffer))
{
- if (rc == 1)
+ switch (mgr->failure_code)
{
- /* Called from my_error_exit. Display a JPEG error. */
- char buf[JMSG_LENGTH_MAX];
- cinfo.err->format_message ((j_common_ptr) &cinfo, buf);
- image_error ("Error reading JPEG image `%s': %s", img->spec,
- build_string (buf));
+ case MY_JPEG_ERROR_EXIT:
+ {
+ char buf[JMSG_LENGTH_MAX];
+ mgr->cinfo.err->format_message ((j_common_ptr) &mgr->cinfo, buf);
+ image_error ("Error reading JPEG image `%s': %s", img->spec,
+ build_string (buf));
+ break;
+ }
+
+ case MY_JPEG_INVALID_IMAGE_SIZE:
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+ break;
+
+ case MY_JPEG_CANNOT_CREATE_X:
+ break;
}
/* Close the input file and destroy the JPEG object. */
if (fp)
- fclose ((FILE *) fp);
- fn_jpeg_destroy_decompress (&cinfo);
+ fclose (fp);
+ fn_jpeg_destroy_decompress (&mgr->cinfo);
/* If we already have an XImage, free that. */
x_destroy_x_image (ximg);
@@ -6389,46 +6403,52 @@ jpeg_load (struct frame *f, struct image *img)
return 0;
}
+ /* Silence a bogus diagnostic; see GCC bug 54561. */
+ IF_LINT (fp = mgr->fp);
+
/* Create the JPEG decompression object. Let it read from fp.
Read the JPEG image header. */
- fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
+ fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
if (NILP (specified_data))
- jpeg_file_src (&cinfo, (FILE *) fp);
+ jpeg_file_src (&mgr->cinfo, fp);
else
- jpeg_memory_src (&cinfo, SDATA (specified_data),
+ jpeg_memory_src (&mgr->cinfo, SDATA (specified_data),
SBYTES (specified_data));
- fn_jpeg_read_header (&cinfo, 1);
+ fn_jpeg_read_header (&mgr->cinfo, 1);
/* Customize decompression so that color quantization will be used.
Start decompression. */
- cinfo.quantize_colors = 1;
- fn_jpeg_start_decompress (&cinfo);
- width = img->width = cinfo.output_width;
- height = img->height = cinfo.output_height;
+ mgr->cinfo.quantize_colors = 1;
+ fn_jpeg_start_decompress (&mgr->cinfo);
+ width = img->width = mgr->cinfo.output_width;
+ height = img->height = mgr->cinfo.output_height;
if (!check_image_size (f, width, height))
{
- image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
- _longjmp (mgr.setjmp_buffer, 2);
+ mgr->failure_code = MY_JPEG_INVALID_IMAGE_SIZE;
+ sys_longjmp (mgr->setjmp_buffer, 1);
}
/* Create X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
- _longjmp (mgr.setjmp_buffer, 2);
+ {
+ mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
+ sys_longjmp (mgr->setjmp_buffer, 1);
+ }
/* Allocate colors. When color quantization is used,
- cinfo.actual_number_of_colors has been set with the number of
- colors generated, and cinfo.colormap is a two-dimensional array
- of color indices in the range 0..cinfo.actual_number_of_colors.
+ mgr->cinfo.actual_number_of_colors has been set with the number of
+ 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. */
{
int i, ir, ig, ib;
- if (cinfo.out_color_components > 2)
+ if (mgr->cinfo.out_color_components > 2)
ir = 0, ig = 1, ib = 2;
- else if (cinfo.out_color_components > 1)
+ else if (mgr->cinfo.out_color_components > 1)
ir = 0, ig = 1, ib = 0;
else
ir = 0, ig = 0, ib = 0;
@@ -6438,15 +6458,15 @@ jpeg_load (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 (cinfo.actual_number_of_colors * sizeof *colors);
+ colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors);
- for (i = 0; i < cinfo.actual_number_of_colors; ++i)
+ for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i)
{
/* Multiply RGB values with 255 because X expects RGB values
in the range 0..0xffff. */
- int r = cinfo.colormap[ir][i] << 8;
- int g = cinfo.colormap[ig][i] << 8;
- int b = cinfo.colormap[ib][i] << 8;
+ int r = mgr->cinfo.colormap[ir][i] << 8;
+ int g = mgr->cinfo.colormap[ig][i] << 8;
+ int b = mgr->cinfo.colormap[ib][i] << 8;
colors[i] = lookup_rgb_color (f, r, g, b);
}
@@ -6458,21 +6478,21 @@ jpeg_load (struct frame *f, struct image *img)
}
/* Read pixels. */
- row_stride = width * cinfo.output_components;
- buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
- row_stride, 1);
+ row_stride = width * mgr->cinfo.output_components;
+ buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
+ JPOOL_IMAGE, row_stride, 1);
for (y = 0; y < height; ++y)
{
- fn_jpeg_read_scanlines (&cinfo, buffer, 1);
- for (x = 0; x < cinfo.output_width; ++x)
+ fn_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 (&cinfo);
- fn_jpeg_destroy_decompress (&cinfo);
+ fn_jpeg_finish_decompress (&mgr->cinfo);
+ fn_jpeg_destroy_decompress (&mgr->cinfo);
if (fp)
- fclose ((FILE *) fp);
+ fclose (fp);
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
@@ -6485,10 +6505,17 @@ jpeg_load (struct frame *f, struct image *img)
return 1;
}
+static bool
+jpeg_load (struct frame *f, struct image *img)
+{
+ struct my_jpeg_error_mgr mgr;
+ return jpeg_load_body (f, img, &mgr);
+}
+
#else /* HAVE_JPEG */
#ifdef HAVE_NS
-static int
+static bool
jpeg_load (struct frame *f, struct image *img)
{
return ns_load_image (f, img,
@@ -6507,8 +6534,8 @@ jpeg_load (struct frame *f, struct image *img)
#if defined (HAVE_TIFF) || defined (HAVE_NS)
-static int tiff_image_p (Lisp_Object object);
-static int tiff_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. */
@@ -6550,6 +6577,12 @@ static const struct image_keyword tiff_format[TIFF_LAST] =
{":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_tiff_functions (void);
+#else
+#define init_tiff_functions NULL
+#endif
+
/* Structure describing the image type `tiff'. */
static struct image_type tiff_type =
@@ -6558,12 +6591,13 @@ static struct image_type tiff_type =
tiff_image_p,
tiff_load,
x_clear_image,
+ init_tiff_functions,
NULL
};
-/* Return non-zero if OBJECT is a valid TIFF image specification. */
+/* Return true if OBJECT is a valid TIFF image specification. */
-static int
+static bool
tiff_image_p (Lisp_Object object)
{
struct image_keyword fmt[TIFF_LAST];
@@ -6582,7 +6616,7 @@ tiff_image_p (Lisp_Object object)
#include <tiffio.h>
-#ifdef HAVE_NTGUI
+#ifdef WINDOWSNT
/* TIFF library details. */
DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
@@ -6597,12 +6631,12 @@ DEF_IMGLIB_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
DEF_IMGLIB_FN (void, TIFFClose, (TIFF *));
DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
-static int
-init_tiff_functions (Lisp_Object libraries)
+static bool
+init_tiff_functions (void)
{
HMODULE library;
- if (!(library = w32_delayed_load (libraries, Qtiff)))
+ if (!(library = w32_delayed_load (Qtiff)))
return 0;
LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
@@ -6626,7 +6660,7 @@ init_tiff_functions (Lisp_Object libraries)
#define fn_TIFFReadRGBAImage TIFFReadRGBAImage
#define fn_TIFFClose TIFFClose
#define fn_TIFFSetDirectory TIFFSetDirectory
-#endif /* HAVE_NTGUI */
+#endif /* WINDOWSNT */
/* Reading from a memory buffer for TIFF images Based on the PNG
@@ -6767,10 +6801,10 @@ tiff_warning_handler (const char *title, const char *format, va_list ap)
}
-/* Load TIFF image IMG for use on frame F. Value is non-zero if
+/* Load TIFF image IMG for use on frame F. Value is true if
successful. */
-static int
+static bool
tiff_load (struct frame *f, struct image *img)
{
Lisp_Object file, specified_file;
@@ -6935,7 +6969,7 @@ tiff_load (struct frame *f, struct image *img)
#else /* HAVE_TIFF */
#ifdef HAVE_NS
-static int
+static bool
tiff_load (struct frame *f, struct image *img)
{
return ns_load_image (f, img,
@@ -6954,8 +6988,8 @@ tiff_load (struct frame *f, struct image *img)
#if defined (HAVE_GIF) || defined (HAVE_NS)
-static int gif_image_p (Lisp_Object object);
-static int gif_load (struct frame *f, struct image *img);
+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. */
@@ -6998,6 +7032,12 @@ static const struct image_keyword gif_format[GIF_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_gif_functions (void);
+#else
+#define init_gif_functions NULL
+#endif
+
/* Structure describing the image type `gif'. */
static struct image_type gif_type =
@@ -7006,6 +7046,7 @@ static struct image_type gif_type =
gif_image_p,
gif_load,
gif_clear_image,
+ init_gif_functions,
NULL
};
@@ -7018,9 +7059,9 @@ gif_clear_image (struct frame *f, struct image *img)
x_clear_image (f, img);
}
-/* Return non-zero if OBJECT is a valid GIF image specification. */
+/* Return true if OBJECT is a valid GIF image specification. */
-static int
+static bool
gif_image_p (Lisp_Object object)
{
struct image_keyword fmt[GIF_LAST];
@@ -7055,7 +7096,7 @@ gif_image_p (Lisp_Object object)
#endif /* HAVE_NTGUI */
-#ifdef HAVE_NTGUI
+#ifdef WINDOWSNT
/* GIF library details. */
DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *));
@@ -7063,12 +7104,12 @@ DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *));
DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc));
DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *));
-static int
-init_gif_functions (Lisp_Object libraries)
+static bool
+init_gif_functions (void)
{
HMODULE library;
- if (!(library = w32_delayed_load (libraries, Qgif)))
+ if (!(library = w32_delayed_load (Qgif)))
return 0;
LOAD_IMGLIB_FN (library, DGifCloseFile);
@@ -7085,7 +7126,7 @@ init_gif_functions (Lisp_Object libraries)
#define fn_DGifOpen DGifOpen
#define fn_DGifOpenFileName DGifOpenFileName
-#endif /* HAVE_NTGUI */
+#endif /* WINDOWSNT */
/* Reading a GIF image from memory
Based on the PNG memory stuff to a certain extent. */
@@ -7117,7 +7158,7 @@ gif_read_from_memory (GifFileType *file, GifByteType *buf, int len)
}
-/* Load GIF image IMG for use on frame F. Value is non-zero if
+/* Load GIF image IMG for use on frame F. Value is true if
successful. */
static const int interlace_start[] = {0, 4, 2, 1};
@@ -7125,7 +7166,7 @@ static const int interlace_increment[] = {8, 8, 4, 2};
#define GIF_LOCAL_DESCRIPTOR_EXTENSION 249
-static int
+static bool
gif_load (struct frame *f, struct image *img)
{
Lisp_Object file;
@@ -7423,7 +7464,7 @@ gif_load (struct frame *f, struct image *img)
#else /* !HAVE_GIF */
#ifdef HAVE_NS
-static int
+static bool
gif_load (struct frame *f, struct image *img)
{
return ns_load_image (f, img,
@@ -7442,8 +7483,8 @@ gif_load (struct frame *f, struct image *img)
static Lisp_Object Qimagemagick;
-static int imagemagick_image_p (Lisp_Object);
-static int imagemagick_load (struct frame *, struct image *);
+static bool imagemagick_image_p (Lisp_Object);
+static bool imagemagick_load (struct frame *, struct image *);
static void imagemagick_clear_image (struct frame *, struct image *);
/* Indices of image specification fields in imagemagick_format. */
@@ -7488,6 +7529,12 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
{":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_imagemagick_functions (void);
+#else
+#define init_imagemagick_functions NULL
+#endif
+
/* Structure describing the image type for any image handled via
ImageMagick. */
@@ -7497,6 +7544,7 @@ static struct image_type imagemagick_type =
imagemagick_image_p,
imagemagick_load,
imagemagick_clear_image,
+ init_imagemagick_functions,
NULL
};
@@ -7509,11 +7557,11 @@ imagemagick_clear_image (struct frame *f,
x_clear_image (f, img);
}
-/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do
+/* Return true if OBJECT is a valid IMAGEMAGICK image specification. Do
this by calling parse_image_spec and supplying the keywords that
identify the IMAGEMAGICK format. */
-static int
+static bool
imagemagick_image_p (Lisp_Object object)
{
struct image_keyword fmt[IMAGEMAGICK_LAST];
@@ -7565,9 +7613,9 @@ imagemagick_error (MagickWand *wand)
be parsed; SIZE is the number of bytes of data; and FILENAME is
either the file name or the image data.
- Return non-zero if successful. */
+ Return true if successful. */
-static int
+static bool
imagemagick_load_image (struct frame *f, struct image *img,
unsigned char *contents, unsigned int size,
char *filename)
@@ -7905,14 +7953,14 @@ imagemagick_load_image (struct frame *f, struct image *img,
}
-/* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if
+/* Load IMAGEMAGICK image IMG for use on frame F. Value is true if
successful. this function will go into the imagemagick_type structure, and
the prototype thus needs to be compatible with that structure. */
-static int
+static bool
imagemagick_load (struct frame *f, struct image *img)
{
- int success_p = 0;
+ bool success_p = 0;
Lisp_Object file_name;
/* If IMG->spec specifies a file name, create a non-file spec from it. */
@@ -7991,11 +8039,11 @@ and `imagemagick-types-inhibit'. */)
/* Function prototypes. */
-static int svg_image_p (Lisp_Object object);
-static int svg_load (struct frame *f, struct image *img);
+static bool svg_image_p (Lisp_Object object);
+static bool svg_load (struct frame *f, struct image *img);
-static int svg_load_image (struct frame *, struct image *,
- unsigned char *, ptrdiff_t);
+static bool svg_load_image (struct frame *, struct image *,
+ unsigned char *, ptrdiff_t);
/* The symbol `svg' identifying images of this type. */
@@ -8035,31 +8083,32 @@ static const struct image_keyword svg_format[SVG_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
+#if defined HAVE_NTGUI && defined WINDOWSNT
+static bool init_svg_functions (void);
+#else
+#define init_svg_functions NULL
+#endif
+
/* Structure describing the image type `svg'. Its the same type of
structure defined for all image formats, handled by emacs image
functions. See struct image_type in dispextern.h. */
static struct image_type svg_type =
{
- /* An identifier showing that this is an image structure for the SVG format. */
&Qsvg,
- /* Handle to a function that can be used to identify a SVG file. */
svg_image_p,
- /* Handle to function used to load a SVG file. */
svg_load,
- /* Handle to function to free sresources for SVG. */
x_clear_image,
- /* An internal field to link to the next image type in a list of
- image types, will be filled in when registering the format. */
+ init_svg_functions,
NULL
};
-/* Return non-zero if OBJECT is a valid SVG image specification. Do
+/* Return true if OBJECT is a valid SVG image specification. Do
this by calling parse_image_spec and supplying the keywords that
identify the SVG format. */
-static int
+static bool
svg_image_p (Lisp_Object object)
{
struct image_keyword fmt[SVG_LAST];
@@ -8074,7 +8123,7 @@ svg_image_p (Lisp_Object object)
#include <librsvg/rsvg.h>
-#ifdef HAVE_NTGUI
+#ifdef WINDOWSNT
/* SVG library functions. */
DEF_IMGLIB_FN (RsvgHandle *, rsvg_handle_new);
@@ -8098,15 +8147,15 @@ DEF_IMGLIB_FN (void, g_error_free);
Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
-static int
-init_svg_functions (Lisp_Object libraries)
+static bool
+init_svg_functions (void)
{
HMODULE library, gdklib, glib, gobject;
- if (!(glib = w32_delayed_load (libraries, Qglib))
- || !(gobject = w32_delayed_load (libraries, Qgobject))
- || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
- || !(library = w32_delayed_load (libraries, Qsvg)))
+ if (!(glib = w32_delayed_load (Qglib))
+ || !(gobject = w32_delayed_load (Qgobject))
+ || !(gdklib = w32_delayed_load (Qgdk_pixbuf))
+ || !(library = w32_delayed_load (Qsvg)))
return 0;
LOAD_IMGLIB_FN (library, rsvg_handle_new);
@@ -8152,16 +8201,15 @@ init_svg_functions (Lisp_Object libraries)
#define fn_g_type_init g_type_init
#define fn_g_object_unref g_object_unref
#define fn_g_error_free g_error_free
-#endif /* !HAVE_NTGUI */
+#endif /* !WINDOWSNT */
-/* Load SVG image IMG for use on frame F. Value is non-zero if
- successful. this function will go into the svg_type structure, and
- the prototype thus needs to be compatible with that structure. */
+/* Load SVG image IMG for use on frame F. Value is true if
+ successful. */
-static int
+static bool
svg_load (struct frame *f, struct image *img)
{
- int success_p = 0;
+ bool success_p = 0;
Lisp_Object file_name;
/* If IMG->spec specifies a file name, create a non-file spec from it. */
@@ -8214,8 +8262,8 @@ svg_load (struct frame *f, struct image *img)
Uses librsvg to do most of the image processing.
- Returns non-zero when successful. */
-static int
+ Returns true when successful. */
+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. */
@@ -8382,8 +8430,8 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
#ifdef HAVE_GHOSTSCRIPT
-static int gs_image_p (Lisp_Object object);
-static int gs_load (struct frame *f, struct image *img);
+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. */
@@ -8438,6 +8486,7 @@ static struct image_type gs_type =
gs_image_p,
gs_load,
gs_clear_image,
+ NULL,
NULL
};
@@ -8451,10 +8500,10 @@ gs_clear_image (struct frame *f, struct image *img)
}
-/* Return non-zero if OBJECT is a valid Ghostscript image
+/* Return true if OBJECT is a valid Ghostscript image
specification. */
-static int
+static bool
gs_image_p (Lisp_Object object)
{
struct image_keyword fmt[GS_LAST];
@@ -8491,10 +8540,10 @@ gs_image_p (Lisp_Object object)
}
-/* Load Ghostscript image IMG for use on frame F. Value is non-zero
+/* Load Ghostscript image IMG for use on frame F. Value is true
if successful. */
-static int
+static bool
gs_load (struct frame *f, struct image *img)
{
uprintmax_t printnum1, printnum2;
@@ -8530,11 +8579,11 @@ gs_load (struct frame *f, struct image *img)
if (x_check_image_size (0, img->width, img->height))
{
/* Only W32 version did BLOCK_INPUT here. ++kfs */
- BLOCK_INPUT;
+ block_input ();
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
img->width, img->height,
DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (!img->pixmap)
@@ -8610,7 +8659,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
{
XImagePtr ximg;
- BLOCK_INPUT;
+ block_input ();
/* Try to get an XImage for img->pixmep. */
ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
@@ -8653,15 +8702,15 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
image_error ("Cannot get X image of `%s'; colors will not be freed",
img->spec, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* HAVE_X_WINDOWS */
/* Now that we have the pixmap, compute mask and transform the
image if requested. */
- BLOCK_INPUT;
+ block_input ();
postprocess_image (f, img);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* HAVE_GHOSTSCRIPT */
@@ -8700,88 +8749,92 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
Initialization
***********************************************************************/
-#ifdef HAVE_NTGUI
-/* Image types that rely on external libraries are loaded dynamically
- if the library is available. */
-#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
- define_image_type (image_type, init_lib_fn (libraries))
-#else
-#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
- define_image_type (image_type, 1)
-#endif /* HAVE_NTGUI */
-
-DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
+DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0,
doc: /* Initialize image library implementing image type TYPE.
Return non-nil if TYPE is a supported image type.
-Image types pbm and xbm are prebuilt; other types are loaded here.
-Libraries to load are specified in alist LIBRARIES (usually, the value
-of `dynamic-library-alist', which see). */)
- (Lisp_Object type, Lisp_Object libraries)
+If image libraries are loaded dynamically (currently only the case on
+MS-Windows), load the library for TYPE if it is not yet loaded, using
+the library file(s) specified by `dynamic-library-alist'. */)
+ (Lisp_Object type)
{
-#ifdef HAVE_NTGUI
- /* Don't try to reload the library. */
- Lisp_Object tested = Fassq (type, Vlibrary_cache);
- if (CONSP (tested))
- return XCDR (tested);
-#endif
+ return lookup_image_type (type) ? Qt : Qnil;
+}
+/* Look up image type TYPE, and return a pointer to its image_type
+ structure. Return 0 if TYPE is not a known image type. */
+
+static struct image_type *
+lookup_image_type (Lisp_Object type)
+{
/* Types pbm and xbm are built-in and always available. */
- if (EQ (type, Qpbm) || EQ (type, Qxbm))
- return Qt;
+ if (EQ (type, Qpbm))
+ return define_image_type (&pbm_type);
+
+ if (EQ (type, Qxbm))
+ return define_image_type (&xbm_type);
#if defined (HAVE_XPM) || defined (HAVE_NS)
if (EQ (type, Qxpm))
- return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
+ return define_image_type (&xpm_type);
#endif
#if defined (HAVE_JPEG) || defined (HAVE_NS)
if (EQ (type, Qjpeg))
- return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
+ return define_image_type (&jpeg_type);
#endif
#if defined (HAVE_TIFF) || defined (HAVE_NS)
if (EQ (type, Qtiff))
- return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
+ return define_image_type (&tiff_type);
#endif
#if defined (HAVE_GIF) || defined (HAVE_NS)
if (EQ (type, Qgif))
- return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
+ return define_image_type (&gif_type);
#endif
#if defined (HAVE_PNG) || defined (HAVE_NS)
if (EQ (type, Qpng))
- return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
+ return define_image_type (&png_type);
#endif
#if defined (HAVE_RSVG)
if (EQ (type, Qsvg))
- return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
+ return define_image_type (&svg_type);
#endif
#if defined (HAVE_IMAGEMAGICK)
if (EQ (type, Qimagemagick))
- return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
- libraries);
+ return define_image_type (&imagemagick_type);
#endif
#ifdef HAVE_GHOSTSCRIPT
if (EQ (type, Qpostscript))
- return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
+ return define_image_type (&gs_type);
#endif
- /* If the type is not recognized, avoid testing it ever again. */
- CACHE_IMAGE_TYPE (type, Qnil);
- return Qnil;
+ return NULL;
+}
+
+/* Reset image_types before dumping.
+ Called from Fdump_emacs. */
+
+void
+reset_image_types (void)
+{
+ while (image_types)
+ {
+ struct image_type *next = image_types->next;
+ xfree (image_types);
+ image_types = next;
+ }
}
void
syms_of_image (void)
{
- /* Initialize this only once, since that's what we do with Vimage_types
- and they are supposed to be in sync. Initializing here gives correct
- operation on GNU/Linux of calling dump-emacs after loading some images. */
+ /* Initialize this only once; it will be reset before dumping. */
image_types = NULL;
/* Must be defined now because we're going to update it below, while
@@ -8804,15 +8857,6 @@ 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);
- DEFSYM (Qpbm, "pbm");
- ADD_IMAGE_TYPE (Qpbm);
-
- DEFSYM (Qxbm, "xbm");
- ADD_IMAGE_TYPE (Qxbm);
-
- define_image_type (&xbm_type, 1);
- define_image_type (&pbm_type, 1);
-
DEFSYM (Qcount, "count");
DEFSYM (Qextension_data, "extension-data");
DEFSYM (Qdelay, "delay");
@@ -8856,6 +8900,12 @@ non-numeric, there is no explicit limit on the size of images. */);
);
#endif
+ DEFSYM (Qpbm, "pbm");
+ ADD_IMAGE_TYPE (Qpbm);
+
+ DEFSYM (Qxbm, "xbm");
+ ADD_IMAGE_TYPE (Qxbm);
+
#if defined (HAVE_XPM) || defined (HAVE_NS)
DEFSYM (Qxpm, "xpm");
ADD_IMAGE_TYPE (Qxpm);
diff --git a/src/indent.c b/src/indent.c
index 160b8c7479e..3dbf372cf17 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -31,7 +30,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "frame.h"
#include "window.h"
#include "termchar.h"
-#include "termopts.h"
#include "disptab.h"
#include "intervals.h"
#include "dispextern.h"
@@ -116,13 +114,12 @@ character_width (int c, struct Lisp_Char_Table *dp)
for characters as WIDTHTAB. We use this to decide when to
invalidate the buffer's width_run_cache. */
-int
+bool
disptab_matches_widthtab (struct Lisp_Char_Table *disptab, struct Lisp_Vector *widthtab)
{
int i;
- if (widthtab->header.size != 256)
- abort ();
+ eassert (widthtab->header.size == 256);
for (i = 0; i < 256; i++)
if (character_width (i, disptab)
@@ -143,8 +140,7 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab)
if (!VECTORP (BVAR (buf, width_table)))
bset_width_table (buf, Fmake_vector (make_number (256), make_number (0)));
widthtab = XVECTOR (BVAR (buf, width_table));
- if (widthtab->header.size != 256)
- abort ();
+ eassert (widthtab->header.size == 256);
for (i = 0; i < 256; i++)
XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
@@ -321,14 +317,14 @@ invalidate_current_column (void)
ptrdiff_t
current_column (void)
{
- register ptrdiff_t col;
- register unsigned char *ptr, *stop;
- register int tab_seen;
+ ptrdiff_t col;
+ unsigned char *ptr, *stop;
+ bool tab_seen;
ptrdiff_t post_tab;
- register int c;
+ int c;
int tab_width = SANE_TAB_WIDTH (current_buffer);
- int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
- register struct Lisp_Char_Table *dp = buffer_display_table ();
+ bool ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
+ struct Lisp_Char_Table *dp = buffer_display_table ();
if (PT == last_known_column_point
&& MODIFF == last_known_column_modified)
@@ -513,9 +509,9 @@ static void
scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
{
int tab_width = SANE_TAB_WIDTH (current_buffer);
- register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
- register struct Lisp_Char_Table *dp = buffer_display_table ();
- int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
+ bool ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
+ struct Lisp_Char_Table *dp = buffer_display_table ();
+ bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
struct composition_it cmp_it;
Lisp_Object window;
struct window *w;
@@ -723,14 +719,14 @@ current_column_1 (void)
static double
string_display_width (Lisp_Object string, Lisp_Object beg, Lisp_Object end)
{
- register int col;
- register unsigned char *ptr, *stop;
- register int tab_seen;
+ int col;
+ unsigned char *ptr, *stop;
+ bool tab_seen;
int post_tab;
- register int c;
+ int c;
int tab_width = SANE_TAB_WIDTH (current_buffer);
- int ctl_arrow = !NILP (current_buffer->ctl_arrow);
- register struct Lisp_Char_Table *dp = buffer_display_table ();
+ bool ctl_arrow = !NILP (current_buffer->ctl_arrow);
+ struct Lisp_Char_Table *dp = buffer_display_table ();
int b, e;
if (NILP (end))
@@ -946,7 +942,7 @@ position_indentation (ptrdiff_t pos_byte)
Blank lines are treated as if they had the same indentation as the
preceding line. */
-int
+bool
indented_beyond_p (ptrdiff_t pos, ptrdiff_t pos_byte, EMACS_INT column)
{
ptrdiff_t val;
@@ -1048,11 +1044,11 @@ static struct position val_compute_motion;
can't hit the requested column exactly (because of a tab or other
multi-column character), overshoot.
- DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
+ DID_MOTION is true if FROMHPOS has already accounted for overlay strings
at FROM. This is the case if FROMVPOS and FROMVPOS came from an
earlier call to compute_motion. The other common case is that FROMHPOS
is zero and FROM is a position that "belongs" at column zero, but might
- be shifted by overlay strings; in this case DID_MOTION should be 0.
+ be shifted by overlay strings; in this case DID_MOTION should be false.
WIDTH is the number of columns available to display text;
compute_motion uses this to handle continuation lines and such.
@@ -1105,17 +1101,20 @@ static struct position val_compute_motion;
the scroll bars if they are turned on. */
struct position *
-compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_motion, ptrdiff_t to, EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width, ptrdiff_t hscroll, int tab_offset, struct window *win)
+compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
+ bool did_motion, ptrdiff_t to,
+ EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width,
+ ptrdiff_t hscroll, int tab_offset, struct window *win)
{
- register EMACS_INT hpos = fromhpos;
- register EMACS_INT vpos = fromvpos;
+ EMACS_INT hpos = fromhpos;
+ EMACS_INT vpos = fromvpos;
- register ptrdiff_t pos;
+ ptrdiff_t pos;
ptrdiff_t pos_byte;
- register int c = 0;
+ int c = 0;
int tab_width = SANE_TAB_WIDTH (current_buffer);
- register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
- register struct Lisp_Char_Table *dp = window_display_table (win);
+ bool ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow));
+ struct Lisp_Char_Table *dp = window_display_table (win);
EMACS_INT selective
= (INTEGERP (BVAR (current_buffer, selective_display))
? XINT (BVAR (current_buffer, selective_display))
@@ -1140,7 +1139,7 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_
ptrdiff_t next_width_run = from;
Lisp_Object window;
- int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
+ bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
/* If previous char scanned was a wide character,
this is the column where it ended. Otherwise, this is 0. */
EMACS_INT wide_column_end_hpos = 0;
@@ -1309,7 +1308,7 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_
if (hpos > width)
{
EMACS_INT total_width = width + continuation_glyph_width;
- int truncate = 0;
+ bool truncate = 0;
if (!NILP (Vtruncate_partial_width_windows)
&& (total_width < FRAME_COLS (XFRAME (WINDOW_FRAME (win)))))
@@ -1765,11 +1764,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */)
else
hscroll = tab_offset = 0;
- if (NILP (window))
- window = Fselected_window ();
- else
- CHECK_LIVE_WINDOW (window);
- w = XWINDOW (window);
+ w = decode_live_window (window);
if (XINT (from) < BEGV || XINT (from) > ZV)
args_out_of_range_3 (from, make_number (BEGV), make_number (ZV));
@@ -1791,8 +1786,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */)
1))
: XINT (XCAR (topos))),
(NILP (width) ? -1 : XINT (width)),
- hscroll, tab_offset,
- XWINDOW (window));
+ hscroll, tab_offset, w);
XSETFASTINT (bufpos, pos->bufpos);
XSETINT (hpos, pos->hpos);
@@ -1828,7 +1822,7 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
PTRDIFF_MAX)
: !NILP (BVAR (current_buffer, selective_display)) ? -1 : 0);
Lisp_Object window;
- int did_motion;
+ bool did_motion;
/* This is the object we use for fetching character properties. */
Lisp_Object text_prop_object;
@@ -1989,11 +1983,7 @@ whether or not it is currently displayed in some window. */)
}
CHECK_NUMBER (lines);
- if (! NILP (window))
- CHECK_WINDOW (window);
- else
- window = selected_window;
- w = XWINDOW (window);
+ w = decode_live_window (window);
old_buffer = Qnil;
GCPRO3 (old_buffer, old_charpos, old_bytepos);
@@ -2001,8 +1991,8 @@ whether or not it is currently displayed in some window. */)
{
/* Set the window's buffer temporarily to the current buffer. */
old_buffer = w->buffer;
- old_charpos = XMARKER (w->pointm)->charpos;
- old_bytepos = XMARKER (w->pointm)->bytepos;
+ old_charpos = marker_position (w->pointm);
+ old_bytepos = marker_byte_position (w->pointm);
wset_buffer (w, Fcurrent_buffer ());
set_marker_both (w->pointm, w->buffer,
BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
@@ -2018,8 +2008,8 @@ whether or not it is currently displayed in some window. */)
{
ptrdiff_t it_start, it_overshoot_count = 0;
int first_x;
- int overshoot_handled = 0;
- int disp_string_at_start_p = 0;
+ bool overshoot_handled = 0;
+ bool disp_string_at_start_p = 0;
itdata = bidi_shelve_cache ();
SET_TEXT_POS (pt, PT, PT_BYTE);
@@ -2035,7 +2025,11 @@ whether or not it is currently displayed in some window. */)
const char *s = SSDATA (it.string);
const char *e = s + SBYTES (it.string);
- disp_string_at_start_p = it.string_from_display_prop_p;
+ /* If it.area is anything but TEXT_AREA, we need not bother
+ about the display string, as it doesn't affect cursor
+ positioning. */
+ disp_string_at_start_p =
+ it.string_from_display_prop_p && it.area == TEXT_AREA;
while (s < e)
{
if (*s++ == '\n')
@@ -2058,7 +2052,13 @@ whether or not it is currently displayed in some window. */)
comment said this is "so we don't move too far" (2005-01-19
checkin by kfs). But this does nothing useful that I can
tell, and it causes Bug#2694 . -- cyd */
- move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+ /* When the position we started from is covered by a display
+ string, move_it_to will overshoot it, while vertical-motion
+ wants to put the cursor _before_ the display string. So in
+ that case, we move to buffer position before the display
+ string, and avoid overshooting. */
+ move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT,
+ -1, -1, -1, MOVE_TO_POS);
/* IT may move too far if truncate-lines is on and PT lies
beyond the right margin. IT may also move too far if the
diff --git a/src/indent.h b/src/indent.h
index e198137a756..abcd06036d1 100644
--- a/src/indent.h
+++ b/src/indent.h
@@ -27,7 +27,7 @@ struct position
};
struct position *compute_motion (ptrdiff_t from, EMACS_INT fromvpos,
- EMACS_INT fromhpos, int did_motion,
+ EMACS_INT fromhpos, bool did_motion,
ptrdiff_t to, EMACS_INT tovpos,
EMACS_INT tohpos,
EMACS_INT width, ptrdiff_t hscroll,
@@ -45,8 +45,8 @@ extern ptrdiff_t last_known_column_point;
/* Return true if the display table DISPTAB specifies the same widths
for characters as WIDTHTAB. We use this to decide when to
invalidate the buffer's column_cache. */
-int disptab_matches_widthtab (struct Lisp_Char_Table *disptab,
- struct Lisp_Vector *widthtab);
+bool disptab_matches_widthtab (struct Lisp_Char_Table *disptab,
+ struct Lisp_Vector *widthtab);
/* Recompute BUF's width table, using the display table DISPTAB. */
void recompute_width_table (struct buffer *buf,
diff --git a/src/inotify.c b/src/inotify.c
new file mode 100644
index 00000000000..8a52c27985c
--- /dev/null
+++ b/src/inotify.c
@@ -0,0 +1,437 @@
+/* Inotify support for Emacs
+
+Copyright (C) 2012
+ Free Software Foundation, Inc.
+
+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 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/>. */
+
+#include <config.h>
+
+#ifdef HAVE_INOTIFY
+
+#include "lisp.h"
+#include "coding.h"
+#include "process.h"
+#include "keyboard.h"
+#include "character.h"
+#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>
+
+/* Ignore bits that might be undefined on old GNU/Linux systems. */
+#ifndef IN_EXCL_UNLINK
+# define IN_EXCL_UNLINK 0
+#endif
+#ifndef IN_DONT_FOLLOW
+# define IN_DONT_FOLLOW 0
+#endif
+#ifndef IN_ONLYDIR
+# define IN_ONLYDIR 0
+#endif
+
+enum { uninitialized = -100 };
+/* File handle for inotify. */
+static int inotifyfd = uninitialized;
+
+/* Assoc list of files being watched.
+ Format:
+ (watch-descriptor . callback)
+ */
+static Lisp_Object watch_list;
+
+static Lisp_Object
+make_watch_descriptor (int wd)
+{
+ /* TODO replace this with a Misc Object! */
+ return make_number (wd);
+}
+
+static Lisp_Object
+mask_to_aspects (uint32_t mask) {
+ Lisp_Object aspects = Qnil;
+ if (mask & IN_ACCESS)
+ aspects = Fcons (Qaccess, aspects);
+ if (mask & IN_ATTRIB)
+ aspects = Fcons (Qattrib, aspects);
+ if (mask & IN_CLOSE_WRITE)
+ aspects = Fcons (Qclose_write, aspects);
+ if (mask & IN_CLOSE_NOWRITE)
+ aspects = Fcons (Qclose_nowrite, aspects);
+ if (mask & IN_CREATE)
+ aspects = Fcons (Qcreate, aspects);
+ if (mask & IN_DELETE)
+ aspects = Fcons (Qdelete, aspects);
+ if (mask & IN_DELETE_SELF)
+ aspects = Fcons (Qdelete_self, aspects);
+ if (mask & IN_MODIFY)
+ aspects = Fcons (Qmodify, aspects);
+ if (mask & IN_MOVE_SELF)
+ aspects = Fcons (Qmove_self, aspects);
+ if (mask & IN_MOVED_FROM)
+ aspects = Fcons (Qmoved_from, aspects);
+ if (mask & IN_MOVED_TO)
+ aspects = Fcons (Qmoved_to, aspects);
+ if (mask & IN_OPEN)
+ aspects = Fcons (Qopen, aspects);
+ if (mask & IN_IGNORED)
+ aspects = Fcons (Qignored, aspects);
+ if (mask & IN_ISDIR)
+ aspects = Fcons (Qisdir, aspects);
+ if (mask & IN_Q_OVERFLOW)
+ aspects = Fcons (Qq_overflow, aspects);
+ if (mask & IN_UNMOUNT)
+ aspects = Fcons (Qunmount, aspects);
+ return aspects;
+}
+
+static Lisp_Object
+inotifyevent_to_event (Lisp_Object watch_object, struct inotify_event const *ev)
+{
+ Lisp_Object name = Qnil;
+ if (ev->len > 0)
+ {
+ size_t const len = strlen (ev->name);
+ name = make_unibyte_string (ev->name, min (len, ev->len));
+ name = DECODE_FILE (name);
+ }
+
+ return list2 (list4 (make_watch_descriptor (ev->wd),
+ mask_to_aspects (ev->mask),
+ make_number (ev->cookie),
+ name),
+ XCDR (watch_object));
+}
+
+/* This callback is called when the FD is available for read. The inotify
+ events are read from FD and converted into input_events. */
+static void
+inotify_callback (int fd, void *_)
+{
+ struct input_event event;
+ Lisp_Object watch_object;
+ int to_read;
+ char *buffer;
+ ssize_t n;
+ size_t i;
+
+ to_read = 0;
+ if (ioctl (fd, FIONREAD, &to_read) == -1)
+ report_file_error ("Error while trying to retrieve file system events",
+ Qnil);
+ buffer = xmalloc (to_read);
+ n = read (fd, buffer, to_read);
+ if (n < 0)
+ {
+ xfree (buffer);
+ report_file_error ("Error while trying to read file system events",
+ Qnil);
+ }
+
+ EVENT_INIT (event);
+ event.kind = FILE_NOTIFY_EVENT;
+
+ i = 0;
+ while (i < (size_t)n)
+ {
+ struct inotify_event *ev = (struct inotify_event*)&buffer[i];
+
+ watch_object = Fassoc (make_watch_descriptor (ev->wd), watch_list);
+ if (!NILP (watch_object))
+ {
+ event.arg = inotifyevent_to_event (watch_object, ev);
+
+ /* If event was removed automatically: Drop it from watch list. */
+ if (ev->mask & IN_IGNORED)
+ watch_list = Fdelete (watch_object, watch_list);
+
+ if (!NILP (event.arg))
+ kbd_buffer_store_event (&event);
+ }
+
+ i += sizeof (*ev) + ev->len;
+ }
+
+ xfree (buffer);
+}
+
+static uint32_t
+symbol_to_inotifymask (Lisp_Object symb)
+{
+ if (EQ (symb, Qaccess))
+ return IN_ACCESS;
+ else if (EQ (symb, Qattrib))
+ return IN_ATTRIB;
+ else if (EQ (symb, Qclose_write))
+ return IN_CLOSE_WRITE;
+ else if (EQ (symb, Qclose_nowrite))
+ return IN_CLOSE_NOWRITE;
+ else if (EQ (symb, Qcreate))
+ return IN_CREATE;
+ else if (EQ (symb, Qdelete))
+ return IN_DELETE;
+ else if (EQ (symb, Qdelete_self))
+ return IN_DELETE_SELF;
+ else if (EQ (symb, Qmodify))
+ return IN_MODIFY;
+ else if (EQ (symb, Qmove_self))
+ return IN_MOVE_SELF;
+ else if (EQ (symb, Qmoved_from))
+ return IN_MOVED_FROM;
+ else if (EQ (symb, Qmoved_to))
+ return IN_MOVED_TO;
+ else if (EQ (symb, Qopen))
+ return IN_OPEN;
+ else if (EQ (symb, Qmove))
+ return IN_MOVE;
+ else if (EQ (symb, Qclose))
+ return IN_CLOSE;
+
+ else if (EQ (symb, Qdont_follow))
+ return IN_DONT_FOLLOW;
+ else if (EQ (symb, Qexcl_unlink))
+ return IN_EXCL_UNLINK;
+ else if (EQ (symb, Qmask_add))
+ return IN_MASK_ADD;
+ else if (EQ (symb, Qoneshot))
+ return IN_ONESHOT;
+ else if (EQ (symb, Qonlydir))
+ return IN_ONLYDIR;
+
+ else if (EQ (symb, Qt) || EQ (symb, Qall_events))
+ return IN_ALL_EVENTS;
+ else
+ signal_error ("Unknown aspect", symb);
+}
+
+static uint32_t
+aspect_to_inotifymask (Lisp_Object aspect)
+{
+ if (CONSP (aspect))
+ {
+ Lisp_Object x = aspect;
+ uint32_t mask = 0;
+ while (CONSP (x))
+ {
+ mask |= symbol_to_inotifymask (XCAR (x));
+ x = XCDR (x);
+ }
+ return mask;
+ }
+ else
+ return symbol_to_inotifymask (aspect);
+}
+
+DEFUN ("inotify-add-watch", Finotify_add_watch, Sinotify_add_watch, 3, 3, 0,
+ doc: /* Add a watch for FILE-NAME to inotify.
+
+A WATCH-DESCRIPTOR is returned on success. ASPECT might be one of the following
+symbols or a list of those symbols:
+
+access
+attrib
+close-write
+close-nowrite
+create
+delete
+delete-self
+modify
+move-self
+moved-from
+moved-to
+open
+
+all-events or t
+move
+close
+
+The following symbols can also be added to a list of aspects
+
+dont-follow
+excl-unlink
+mask-add
+oneshot
+onlydir
+
+Watching a directory is not recursive. CALLBACK gets called in case of an
+event. It gets passed a single argument EVENT which contains an event structure
+of the format
+
+(WATCH-DESCRIPTOR ASPECTS COOKIE NAME)
+
+WATCH-DESCRIPTOR is the same object that was returned by this function. It can
+be tested for equality using `equal'. ASPECTS describes the event. It is a
+list of ASPECT symbols described above and can also contain one of the following
+symbols
+
+ignored
+isdir
+q-overflow
+unmount
+
+COOKIE is an object that can be compared using `equal' to identify two matching
+renames (moved-from and moved-to).
+
+If a directory is watched then NAME is the name of file that caused the event.
+
+See inotify(7) and inotify_add_watch(2) for further information. The inotify fd
+is managed internally and there is no corresponding inotify_init. Use
+`inotify-rm-watch' to remove a watch.
+ */)
+ (Lisp_Object file_name, Lisp_Object aspect, Lisp_Object callback)
+{
+ uint32_t mask;
+ Lisp_Object watch_object;
+ Lisp_Object encoded_file_name;
+ Lisp_Object watch_descriptor;
+ int watchdesc = -1;
+
+ CHECK_STRING (file_name);
+
+ if (inotifyfd == uninitialized)
+ {
+ inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC);
+ if (inotifyfd == -1)
+ {
+ inotifyfd = uninitialized;
+ report_file_error ("File watching feature (inotify) is not available",
+ Qnil);
+ }
+ watch_list = Qnil;
+ add_read_fd (inotifyfd, &inotify_callback, NULL);
+ }
+
+ mask = aspect_to_inotifymask (aspect);
+ encoded_file_name = ENCODE_FILE (file_name);
+ watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask);
+ if (watchdesc == -1)
+ report_file_error ("Could not add watch for file", Fcons (file_name, Qnil));
+
+ watch_descriptor = make_watch_descriptor (watchdesc);
+
+ /* Delete existing watch object. */
+ watch_object = Fassoc (watch_descriptor, watch_list);
+ if (!NILP (watch_object))
+ watch_list = Fdelete (watch_object, watch_list);
+
+ /* Store watch object in watch list. */
+ watch_object = Fcons (watch_descriptor, callback);
+ watch_list = Fcons (watch_object, watch_list);
+
+ return watch_descriptor;
+}
+
+DEFUN ("inotify-rm-watch", Finotify_rm_watch, Sinotify_rm_watch, 1, 1, 0,
+ doc: /* Remove an existing WATCH-DESCRIPTOR.
+
+WATCH-DESCRIPTOR should be an object returned by `inotify-add-watch'.
+
+See inotify_rm_watch(2) for more information.
+ */)
+ (Lisp_Object watch_descriptor)
+{
+ Lisp_Object watch_object;
+ int wd = XINT (watch_descriptor);
+
+ if (inotify_rm_watch (inotifyfd, wd) == -1)
+ report_file_error ("Could not rm watch", Fcons (watch_descriptor,
+ Qnil));
+
+ /* Remove watch descriptor from watch list. */
+ watch_object = Fassoc (watch_descriptor, watch_list);
+ if (!NILP (watch_object))
+ watch_list = Fdelete (watch_object, watch_list);
+
+ /* Cleanup if no more files are watched. */
+ if (NILP (watch_list))
+ {
+ close (inotifyfd);
+ delete_read_fd (inotifyfd);
+ inotifyfd = uninitialized;
+ }
+
+ return Qt;
+}
+
+void
+syms_of_inotify (void)
+{
+ DEFSYM (Qaccess, "access");
+ DEFSYM (Qattrib, "attrib");
+ DEFSYM (Qclose_write, "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");
+
+ defsubr (&Sinotify_add_watch);
+ defsubr (&Sinotify_rm_watch);
+
+ staticpro (&watch_list);
+
+ Fprovide (intern_c_string ("inotify"), Qnil);
+}
+
+#endif /* HAVE_INOTIFY */
diff --git a/src/insdel.c b/src/insdel.c
index da258c19a1e..74e938c4b8c 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
#include <intprops.h>
@@ -69,13 +68,13 @@ check_markers (void)
for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
{
if (tail->buffer->text != current_buffer->text)
- abort ();
+ emacs_abort ();
if (tail->charpos > Z)
- abort ();
+ emacs_abort ();
if (tail->bytepos > Z_BYTE)
- abort ();
+ emacs_abort ();
if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
- abort ();
+ emacs_abort ();
}
}
@@ -808,7 +807,7 @@ insert_1_both (const char *string,
#ifdef BYTE_COMBINING_DEBUG
if (count_combining_before (string, nbytes, PT, PT_BYTE)
|| count_combining_after (string, nbytes, PT, PT_BYTE))
- abort ();
+ emacs_abort ();
#endif
/* Record deletion of the surrounding text that combines with
@@ -840,8 +839,7 @@ insert_1_both (const char *string,
PT + nchars, PT_BYTE + nbytes,
before_markers);
- if (buffer_intervals (current_buffer))
- offset_intervals (current_buffer, PT, nchars);
+ offset_intervals (current_buffer, PT, nchars);
if (!inherit && buffer_intervals (current_buffer))
set_text_properties (make_number (PT), make_number (PT + nchars),
@@ -943,7 +941,7 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
|| count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
- abort ();
+ emacs_abort ();
#endif
record_insert (PT, nchars);
@@ -1126,7 +1124,7 @@ insert_from_buffer_1 (struct buffer *buf,
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
|| count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
- abort ();
+ emacs_abort ();
#endif
record_insert (PT, nchars);
@@ -1153,8 +1151,7 @@ insert_from_buffer_1 (struct buffer *buf,
PT_BYTE + outgoing_nbytes,
0);
- if (buffer_intervals (current_buffer))
- offset_intervals (current_buffer, PT, nchars);
+ offset_intervals (current_buffer, PT, nchars);
/* Get the intervals for the part of the string we are inserting. */
intervals = buffer_intervals (buf);
@@ -1187,7 +1184,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
#ifdef BYTE_COMBINING_DEBUG
if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
|| count_combining_after (GPT_ADDR, len_byte, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
if (STRINGP (prev_text))
@@ -1222,8 +1219,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
else if (len < nchars_del)
adjust_overlays_for_delete (from, nchars_del - len);
- if (buffer_intervals (current_buffer))
- offset_intervals (current_buffer, from, len - nchars_del);
+ offset_intervals (current_buffer, from, len - nchars_del);
if (from < PT)
adjust_point (len - nchars_del, len_byte - nbytes_del);
@@ -1370,7 +1366,7 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
|| count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
if (! EQ (BVAR (current_buffer, undo_list), Qt))
@@ -1394,16 +1390,16 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
eassert (GPT <= GPT_BYTE);
- /* Adjust the overlay center as needed. This must be done after
- adjusting the markers that bound the overlays. */
- adjust_overlays_for_delete (from, nchars_del);
- adjust_overlays_for_insert (from, inschars);
-
/* Adjust markers for the deletion and the insertion. */
if (markers)
adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
inschars, outgoing_insbytes);
+ /* Adjust the overlay center as needed. This must be done after
+ adjusting the markers that bound the overlays. */
+ adjust_overlays_for_delete (from, nchars_del);
+ adjust_overlays_for_insert (from, inschars);
+
offset_intervals (current_buffer, from, inschars - nchars_del);
/* Get the intervals for the part of the string we are inserting--
@@ -1496,7 +1492,7 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
the text that has been stored by copy_text. */
if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
|| count_combining_after (GPT_ADDR, insbytes, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
GAP_SIZE -= insbytes;
@@ -1510,6 +1506,12 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
eassert (GPT <= GPT_BYTE);
+ /* Adjust markers for the deletion and the insertion. */
+ if (markers
+ && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
+ adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
+ inschars, insbytes);
+
/* Adjust the overlay center as needed. This must be done after
adjusting the markers that bound the overlays. */
if (nchars_del != inschars)
@@ -1518,12 +1520,6 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
adjust_overlays_for_delete (from + inschars, nchars_del);
}
- /* Adjust markers for the deletion and the insertion. */
- if (markers
- && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
- adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
- inschars, insbytes);
-
offset_intervals (current_buffer, from, inschars - nchars_del);
/* Relocate point as if it were a marker. */
@@ -1704,7 +1700,7 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
#ifdef BYTE_COMBINING_DEBUG
if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
Z_BYTE - to_byte, from, from_byte))
- abort ();
+ emacs_abort ();
#endif
if (ret_string || ! EQ (BVAR (current_buffer, undo_list), Qt))
@@ -1759,9 +1755,9 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
return deletion;
}
-
-/* Call this if you're about to change the region of BUFFER from
- character positions START to END. This checks the read-only
+
+/* Call this if you're about to change the region of current buffer
+ from character positions START to END. This checks the read-only
properties of the region, calls the necessary modification hooks,
and warns the next redisplay that it should pay attention to that
area.
@@ -1770,16 +1766,11 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
Otherwise set CHARS_MODIFF to the new value of MODIFF. */
void
-modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end,
- bool preserve_chars_modiff)
+modify_region_1 (ptrdiff_t start, ptrdiff_t end, bool preserve_chars_modiff)
{
- struct buffer *old_buffer = current_buffer;
-
- set_buffer_internal (buffer);
-
prepare_to_modify_buffer (start, end, NULL);
- BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
+ BUF_COMPUTE_UNCHANGED (current_buffer, start - 1, end);
if (MODIFF <= SAVE_MODIFF)
record_first_change ();
@@ -1787,11 +1778,9 @@ modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end,
if (! preserve_chars_modiff)
CHARS_MODIFF = MODIFF;
- bset_point_before_scroll (buffer, Qnil);
-
- set_buffer_internal (old_buffer);
+ bset_point_before_scroll (current_buffer, Qnil);
}
-
+
/* Check that it is okay to modify the buffer between START and END,
which are char positions.
@@ -1811,9 +1800,10 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
if (!NILP (BVAR (current_buffer, read_only)))
Fbarf_if_buffer_read_only ();
- /* Let redisplay consider other windows than selected_window
- if modifying another buffer. */
- if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+ /* If we're modifying the buffer other than shown in a selected window,
+ let redisplay consider other windows if this buffer is visible. */
+ if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer
+ && buffer_window_count (current_buffer))
++windows_or_buffers_changed;
if (buffer_intervals (current_buffer))
@@ -1865,7 +1855,7 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
: (!NILP (Vselect_active_regions)
&& !NILP (Vtransient_mark_mode))))
{
- ptrdiff_t b = XMARKER (BVAR (current_buffer, mark))->charpos;
+ ptrdiff_t b = marker_position (BVAR (current_buffer, mark));
ptrdiff_t e = PT;
if (b < e)
Vsaved_region_selection = make_buffer_string (b, e, 0);
@@ -2107,7 +2097,7 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
non-nil, and insertion calls a file handler (e.g. through
lock_file) which scribbles into a temp file -- cyd */
if (!BUFFERP (combine_after_change_buffer)
- || NILP (BVAR (XBUFFER (combine_after_change_buffer), name)))
+ || !BUFFER_LIVE_P (XBUFFER (combine_after_change_buffer)))
{
combine_after_change_list = Qnil;
return Qnil;
diff --git a/src/intervals.c b/src/intervals.c
index 49d61b2f9b0..1ed93e1302d 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -41,7 +41,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define INTERVALS_INLINE EXTERN_INLINE
-#include <setjmp.h>
#include <intprops.h>
#include "lisp.h"
#include "intervals.h"
@@ -65,7 +64,7 @@ static INTERVAL reproduce_tree (INTERVAL, INTERVAL);
/* Use these functions to set Lisp_Object
or pointer slots of struct interval. */
-static inline void
+static void
set_interval_object (INTERVAL i, Lisp_Object obj)
{
eassert (BUFFERP (obj) || STRINGP (obj));
@@ -73,13 +72,13 @@ set_interval_object (INTERVAL i, Lisp_Object obj)
i->up.obj = obj;
}
-static inline void
+static void
set_interval_left (INTERVAL i, INTERVAL left)
{
i->left = left;
}
-static inline void
+static void
set_interval_right (INTERVAL i, INTERVAL right)
{
i->right = right;
@@ -88,7 +87,7 @@ set_interval_right (INTERVAL i, INTERVAL right)
/* Make the parent of D be whatever the parent of S is, regardless
of the type. This is used when balancing an interval tree. */
-static inline void
+static void
copy_interval_parent (INTERVAL d, INTERVAL s)
{
d->up = s->up;
@@ -199,13 +198,13 @@ intervals_equal (INTERVAL i0, INTERVAL i1)
i0_sym = XCAR (i0_cdr);
i0_cdr = XCDR (i0_cdr);
if (!CONSP (i0_cdr))
- return 0; /* abort (); */
+ return 0;
i1_val = i1->plist;
while (CONSP (i1_val) && !EQ (XCAR (i1_val), i0_sym))
{
i1_val = XCDR (i1_val);
if (!CONSP (i1_val))
- return 0; /* abort (); */
+ return 0;
i1_val = XCDR (i1_val);
}
@@ -223,7 +222,7 @@ intervals_equal (INTERVAL i0, INTERVAL i1)
i1_cdr = XCDR (i1_cdr);
if (!CONSP (i1_cdr))
- return 0; /* abort (); */
+ return 0;
i1_cdr = XCDR (i1_cdr);
}
@@ -342,7 +341,7 @@ root_interval (INTERVAL interval)
c c
*/
-static inline INTERVAL
+static INTERVAL
rotate_right (INTERVAL interval)
{
INTERVAL i;
@@ -389,7 +388,7 @@ rotate_right (INTERVAL interval)
c c
*/
-static inline INTERVAL
+static INTERVAL
rotate_left (INTERVAL interval)
{
INTERVAL i;
@@ -467,7 +466,7 @@ balance_an_interval (INTERVAL i)
/* Balance INTERVAL, potentially stuffing it back into its parent
Lisp Object. */
-static inline INTERVAL
+static INTERVAL
balance_possible_root_interval (INTERVAL interval)
{
Lisp_Object parent;
@@ -674,8 +673,7 @@ find_interval (register INTERVAL tree, register ptrdiff_t position)
eassert (relative_position <= TOTAL_LENGTH (tree));
- if (!handling_signal)
- tree = balance_possible_root_interval (tree);
+ tree = balance_possible_root_interval (tree);
while (1)
{
@@ -1253,7 +1251,7 @@ delete_interval (register INTERVAL i)
else if (STRINGP (owner))
set_string_intervals (owner, parent);
else
- abort ();
+ emacs_abort ();
return;
}
@@ -1408,7 +1406,7 @@ offset_intervals (struct buffer *buffer, ptrdiff_t start, ptrdiff_t length)
start, length);
else
{
- IF_LINT (if (length < - TYPE_MAXIMUM (ptrdiff_t)) abort ();)
+ lint_assume (- TYPE_MAXIMUM (ptrdiff_t) <= length);
adjust_intervals_for_deletion (buffer, start, -length);
}
}
@@ -1468,7 +1466,7 @@ merge_interval_right (register INTERVAL i)
/* This must be the rightmost or last interval and cannot
be merged right. The caller should have known. */
- abort ();
+ emacs_abort ();
}
/* Merge interval I with its lexicographic predecessor. The resulting
@@ -1524,7 +1522,7 @@ merge_interval_left (register INTERVAL i)
/* This must be the leftmost or first interval and cannot
be merged left. The caller should have known. */
- abort ();
+ emacs_abort ();
}
/* Create a copy of SOURCE but with the default value of UP. */
@@ -2170,7 +2168,7 @@ get_property_and_range (ptrdiff_t pos, Lisp_Object prop, Lisp_Object *val,
else if (STRINGP (object))
i = find_interval (string_intervals (object), pos);
else
- abort ();
+ emacs_abort ();
if (!i || (i->position + LENGTH (i) <= pos))
return 0;
@@ -2209,7 +2207,7 @@ get_local_map (register ptrdiff_t position, register struct buffer *buffer,
/* Perhaps we should just change `position' to the limit. */
if (position > BUF_ZV (buffer) || position < BUF_BEGV (buffer))
- abort ();
+ emacs_abort ();
/* Ignore narrowing, so that a local map continues to be valid even if
the visible region contains no characters and hence no properties. */
diff --git a/src/keyboard.c b/src/keyboard.c
index 464c3ae0d66..e2a0e23dd4a 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -19,11 +19,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
+#define BLOCKINPUT_INLINE EXTERN_INLINE
#define KEYBOARD_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "termchar.h"
#include "termopts.h"
@@ -57,6 +57,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/ioctl.h>
#endif /* not MSDOS */
+#if defined USABLE_FIONREAD && defined USG5_4
+# include <sys/filio.h>
+#endif
+
#include "syssignal.h"
#include <sys/types.h>
@@ -69,21 +73,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Variables for blockinput.h: */
-/* Non-zero if interrupt input is blocked right now. */
+/* Positive if interrupt input is blocked right now. */
volatile int interrupt_input_blocked;
-/* Nonzero means an input interrupt has arrived
- during the current critical section. */
-int interrupt_input_pending;
-
-/* This var should be (interrupt_input_pending || pending_atimers).
- The QUIT macro checks this instead of interrupt_input_pending and
- pending_atimers separately, to reduce code size. So, any code that
- changes interrupt_input_pending or pending_atimers should update
- this too. */
-#ifdef SYNC_INPUT
-int pending_signals;
-#endif
+/* True means an input interrupt or alarm signal has arrived.
+ The QUIT macro checks this. */
+volatile bool pending_signals;
#define KBD_BUFFER_SIZE 4096
@@ -91,8 +86,8 @@ KBOARD *initial_kboard;
KBOARD *current_kboard;
KBOARD *all_kboards;
-/* Nonzero in the single-kboard state, 0 in the any-kboard state. */
-static int single_kboard;
+/* 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. */
@@ -118,9 +113,9 @@ static Lisp_Object recent_keys;
Lisp_Object this_command_keys;
ptrdiff_t this_command_key_count;
-/* 1 after calling Freset_this_command_lengths.
- Usually it is 0. */
-static int this_command_key_count_reset;
+/* True after calling Freset_this_command_lengths.
+ Usually it is false. */
+static bool this_command_key_count_reset;
/* This vector is used as a buffer to record the events that were actually read
by read_key_sequence. */
@@ -142,14 +137,14 @@ static ptrdiff_t before_command_echo_length;
/* For longjmp to where kbd input is being done. */
-static jmp_buf getcjmp;
+static sys_jmp_buf getcjmp;
/* True while doing kbd input. */
-int waiting_for_input;
+bool waiting_for_input;
/* True while displaying for echoing. Delays C-g throwing. */
-static int echoing;
+static bool echoing;
/* Non-null means we can start echoing at the next input pause even
though there is something in the echo area. */
@@ -168,8 +163,8 @@ struct kboard *echo_kboard;
Lisp_Object echo_message_buffer;
-/* Nonzero means C-g should cause immediate error-signal. */
-int immediate_quit;
+/* True means C-g should cause immediate error-signal. */
+bool immediate_quit;
/* Character that causes a quit. Normally C-g.
@@ -224,7 +219,11 @@ static Lisp_Object last_point_position_window;
last event came from a macro. We use this to determine when to
generate switch-frame events. This may be cleared by functions
like Fselect_frame, to make sure that a switch-frame event is
- generated by the next character. */
+ generated by the next character.
+
+ FIXME: This is modified by a signal handler so it should be volatile.
+ It's exported to Lisp, though, so it can't simply be marked
+ 'volatile' here. */
Lisp_Object internal_last_event_frame;
/* The timestamp of the last input event we received from the X server.
@@ -271,7 +270,7 @@ static Lisp_Object Qhelp_form_show;
static FILE *dribble;
/* Nonzero if input is available. */
-int input_pending;
+bool input_pending;
/* Circular buffer for pre-read keyboard input. */
@@ -307,21 +306,25 @@ static Lisp_Object Qmake_frame_visible;
static Lisp_Object Qselect_window;
Lisp_Object Qhelp_echo;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
static Lisp_Object Qmouse_fixup_help_message;
-#endif
/* Symbols to denote kinds of events. */
static Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
-#if defined (WINDOWSNT)
+#ifdef HAVE_NTGUI
Lisp_Object Qlanguage_change;
+#ifdef WINDOWSNT
+Lisp_Object Qfile_w32notify;
+#endif
#endif
static Lisp_Object Qdrag_n_drop;
static Lisp_Object Qsave_session;
#ifdef HAVE_DBUS
static Lisp_Object Qdbus_event;
#endif
+#ifdef HAVE_INOTIFY
+static Lisp_Object Qfile_inotify;
+#endif /* HAVE_INOTIFY */
static Lisp_Object Qconfig_changed_event;
/* Lisp_Object Qmouse_movement; - also an event header */
@@ -366,42 +369,28 @@ static Lisp_Object command_loop (void);
static Lisp_Object Qextended_command_history;
EMACS_TIME timer_check (void);
-static void record_menu_key (Lisp_Object c);
static void echo_now (void);
static ptrdiff_t echo_length (void);
static Lisp_Object Qpolling_period;
/* Incremented whenever a timer is run. */
-int timers_run;
+unsigned timers_run;
/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
happens. */
EMACS_TIME *input_available_clear_time;
-/* Nonzero means use SIGIO interrupts; zero means use CBREAK mode.
- Default is 1 if INTERRUPT_INPUT is defined. */
-int interrupt_input;
+/* True means use SIGIO interrupts; false means use CBREAK mode.
+ Default is true if INTERRUPT_INPUT is defined. */
+bool interrupt_input;
/* Nonzero while interrupts are temporarily deferred during redisplay. */
-int interrupts_deferred;
-
-/* Allow configure to inhibit use of FIONREAD. */
-#ifdef BROKEN_FIONREAD
-#undef FIONREAD
-#endif
-
-/* We are unable to use interrupts if FIONREAD is not available,
- so flush SIGIO so we won't try. */
-#if !defined (FIONREAD)
-#ifdef SIGIO
-#undef SIGIO
-#endif
-#endif
+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. */
-#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_ASYNC_EVENTS)
+#ifdef HAVE_WINDOW_SYSTEM
#define POLL_FOR_INPUT
#endif
@@ -425,86 +414,82 @@ static EMACS_TIME timer_last_idleness_start_time;
/* Function for init_keyboard to call with no args (if nonzero). */
static void (*keyboard_init_hook) (void);
-static int read_avail_input (int);
-static void get_input_pending (int *, int);
-static int readable_events (int);
+static bool get_input_pending (int);
+static bool readable_events (int);
static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *,
- Lisp_Object, int *);
+ Lisp_Object, bool *);
static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t,
Lisp_Object *);
static Lisp_Object make_lispy_event (struct input_event *);
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object,
enum scroll_bar_part,
Lisp_Object, Lisp_Object,
Time);
-#endif
static Lisp_Object modify_event_symbol (ptrdiff_t, int, Lisp_Object,
Lisp_Object, const char *const *,
Lisp_Object *, ptrdiff_t);
static Lisp_Object make_lispy_switch_frame (Lisp_Object);
-static int help_char_p (Lisp_Object);
-static void save_getcjmp (jmp_buf);
-static void restore_getcjmp (jmp_buf);
+static bool help_char_p (Lisp_Object);
+static void save_getcjmp (sys_jmp_buf);
+static void restore_getcjmp (sys_jmp_buf);
static Lisp_Object apply_modifiers (int, Lisp_Object);
static void clear_event (struct input_event *);
static Lisp_Object restore_kboard_configuration (Lisp_Object);
-static void interrupt_signal (int signalnum);
-#ifdef SIGIO
-static void input_available_signal (int signo);
+#ifdef USABLE_SIGIO
+static void deliver_input_available_signal (int signo);
#endif
-static void handle_interrupt (void);
-static _Noreturn void quit_throw_to_read_char (int);
+static void handle_interrupt (bool);
+static _Noreturn void quit_throw_to_read_char (bool);
static void process_special_events (void);
static void timer_start_idle (void);
static void timer_stop_idle (void);
static void timer_resume_idle (void);
-static void handle_user_signal (int);
+static void deliver_user_signal (int);
static char *find_user_signal_name (int);
-static int store_user_signal_events (void);
+static void store_user_signal_events (void);
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
kset_echo_string (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (echo_string) = val;
}
-static inline void
+static void
kset_kbd_queue (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (kbd_queue) = val;
}
-static inline void
+static void
kset_keyboard_translate_table (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vkeyboard_translate_table) = val;
}
-static inline void
+static void
kset_last_prefix_arg (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vlast_prefix_arg) = val;
}
-static inline void
+static void
kset_last_repeatable_command (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vlast_repeatable_command) = val;
}
-static inline void
+static void
kset_local_function_key_map (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vlocal_function_key_map) = val;
}
-static inline void
+static void
kset_overriding_terminal_local_map (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Voverriding_terminal_local_map) = val;
}
-static inline void
+static void
kset_real_last_command (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vreal_last_command) = val;
}
-static inline void
+static void
kset_system_key_syms (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (system_key_syms) = val;
@@ -532,7 +517,7 @@ echo_char (Lisp_Object c)
if (INTEGERP (c))
{
- ptr = push_key_description (XINT (c), ptr, 1);
+ ptr = push_key_description (XINT (c), ptr);
}
else if (SYMBOLP (c))
{
@@ -836,7 +821,7 @@ This function is called by the editor initialization to begin editing. */)
/* If we enter while input is blocked, don't lock up here.
This may happen through the debugger during redisplay. */
- if (INPUT_BLOCKED_P)
+ if (input_blocked_p ())
return Qnil;
command_loop_level++;
@@ -941,7 +926,7 @@ pop_kboard (void)
{
struct terminal *t;
struct kboard_stack *p = kboard_stack;
- int found = 0;
+ bool found = 0;
for (t = terminal_list; t; t = t->next_terminal)
{
if (t->kboard == p->kboard)
@@ -974,7 +959,7 @@ pop_kboard (void)
void
temporarily_switch_to_single_kboard (struct frame *f)
{
- int was_locked = single_kboard;
+ bool was_locked = single_kboard;
if (was_locked)
{
if (f != NULL && FRAME_KBOARD (f) != current_kboard)
@@ -1023,7 +1008,7 @@ restore_kboard_configuration (Lisp_Object was_locked)
pop_kboard ();
/* The pop should not change the kboard. */
if (single_kboard && current_kboard != prev)
- abort ();
+ emacs_abort ();
}
return Qnil;
}
@@ -1073,12 +1058,7 @@ cmd_error (Lisp_Object data)
Vprint_length = old_length;
Vquit_flag = Qnil;
-
Vinhibit_quit = Qnil;
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- if (command_loop_level == 0 && minibuf_level == 0)
- any_kboard_state ();
-#endif
return make_number (0);
}
@@ -1142,8 +1122,7 @@ cmd_error_internal (Lisp_Object data, const char *context)
Vsignaling_function = Qnil;
}
-
-Lisp_Object command_loop_1 (void);
+
static Lisp_Object command_loop_2 (Lisp_Object);
static Lisp_Object top_level_1 (Lisp_Object);
@@ -1165,12 +1144,6 @@ command_loop (void)
while (1)
{
internal_catch (Qtop_level, top_level_1, Qnil);
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- /* Reset single_kboard in case top-level set it while
- evaluating an -f option, or we are stuck there for some
- other reason. */
- any_kboard_state ();
-#endif
internal_catch (Qtop_level, command_loop_2, Qnil);
executing_kbd_macro = Qnil;
@@ -1186,7 +1159,7 @@ command_loop (void)
value to us. A value of nil means that command_loop_1 itself
returned due to end of file (or end of kbd macro). */
-Lisp_Object
+static Lisp_Object
command_loop_2 (Lisp_Object ignore)
{
register Lisp_Object val;
@@ -1204,7 +1177,7 @@ top_level_2 (void)
return Feval (Vtop_level, Qnil);
}
-Lisp_Object
+static Lisp_Object
top_level_1 (Lisp_Object ignore)
{
/* On entry to the outer level, run the startup file */
@@ -1229,8 +1202,7 @@ This also exits all active minibuffers. */)
/* Unblock input if we enter with input blocked. This may happen if
redisplay traps e.g. during tool-bar update with input blocked. */
- while (INPUT_BLOCKED_P)
- UNBLOCK_INPUT;
+ totally_unblock_input ();
Fthrow (Qtop_level, Qnil);
}
@@ -1263,8 +1235,6 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0,
user_error ("No recursive edit is in progress");
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-
/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
of this function. */
@@ -1282,8 +1252,7 @@ tracking_off (Lisp_Object old_value)
if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
{
redisplay_preserve_echo_area (6);
- get_input_pending (&input_pending,
- READABLE_EVENTS_DO_TIMERS_NOW);
+ get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
}
}
return Qnil;
@@ -1318,7 +1287,7 @@ usage: (track-mouse BODY...) */)
#if !defined HAVE_WINDOW_SYSTEM || defined USE_GTK || defined HAVE_NS
static
#endif
-int ignore_mouse_drag_p;
+bool ignore_mouse_drag_p;
static FRAME_PTR
some_mouse_moved (void)
@@ -1340,15 +1309,14 @@ some_mouse_moved (void)
return 0;
}
-#endif /* HAVE_MOUSE || HAVE_GPM */
/* This is the actual command reading loop,
sans error-handling encapsulation. */
static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
- int, int, int);
+ bool, bool, bool);
void safe_run_hooks (Lisp_Object);
-static void adjust_point_for_property (ptrdiff_t, int);
+static void adjust_point_for_property (ptrdiff_t, bool);
/* Cancel hourglass from protect_unwind.
ARG is not used. */
@@ -1376,10 +1344,7 @@ command_loop_1 (void)
int i;
EMACS_INT prev_modiff = 0;
struct buffer *prev_buffer = NULL;
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- int was_locked = single_kboard;
-#endif
- int already_adjusted = 0;
+ bool already_adjusted = 0;
kset_prefix_arg (current_kboard, Qnil);
kset_last_prefix_arg (current_kboard, Qnil);
@@ -1435,14 +1400,11 @@ command_loop_1 (void)
Vdeactivate_mark = Qnil;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-
/* Don't ignore mouse movements for more than a single command
loop. (This flag is set in xdisp.c whenever the tool bar is
resized, because the resize moves text up or down, and would
generate false mouse drag events if we don't ignore them.) */
ignore_mouse_drag_p = 0;
-#endif
/* If minibuffer on and echo area in use,
wait a short time and redraw minibuffer. */
@@ -1473,15 +1435,6 @@ command_loop_1 (void)
}
}
-#if 0
- /* Select the frame that the last event came from. Usually,
- switch-frame events will take care of this, but if some lisp
- code swallows a switch-frame event, we'll fix things up here.
- Is this a good idea? */
- if (FRAMEP (internal_last_event_frame)
- && !EQ (internal_last_event_frame, selected_frame))
- Fselect_frame (internal_last_event_frame, Qnil);
-#endif
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag)
@@ -1757,10 +1710,6 @@ command_loop_1 (void)
if (!NILP (KVAR (current_kboard, defining_kbd_macro))
&& NILP (KVAR (current_kboard, Vprefix_arg)))
finalize_kbd_macro_chars ();
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- if (!was_locked)
- any_kboard_state ();
-#endif
}
}
@@ -1770,7 +1719,7 @@ command_loop_1 (void)
LAST_PT is the last position of point. */
static void
-adjust_point_for_property (ptrdiff_t last_pt, int modified)
+adjust_point_for_property (ptrdiff_t last_pt, bool modified)
{
ptrdiff_t beg, end;
Lisp_Object val, overlay, tmp;
@@ -1778,7 +1727,7 @@ adjust_point_for_property (ptrdiff_t last_pt, int modified)
suppress the point adjustment for automatic composition so that a
user can keep inserting another character at point or keep
deleting characters around point. */
- int check_composition = ! modified, check_display = 1, check_invisible = 1;
+ bool check_composition = ! modified, check_display = 1, check_invisible = 1;
ptrdiff_t orig_pt = PT;
/* FIXME: cycling is probably not necessary because these properties
@@ -1817,7 +1766,8 @@ adjust_point_for_property (ptrdiff_t last_pt, int modified)
check_display = 0;
if (check_invisible && PT > BEGV && PT < ZV)
{
- int inv, ellipsis = 0;
+ int inv;
+ bool ellipsis = 0;
beg = end = PT;
/* Find boundaries `beg' and `end' of the invisible area, if any. */
@@ -1946,7 +1896,7 @@ safe_run_hooks_error (Lisp_Object error_data)
if (SYMBOLP (hook))
{
Lisp_Object val;
- int found = 0;
+ bool found = 0;
Lisp_Object newval = Qnil;
for (val = find_symbol_value (hook); CONSP (val); val = XCDR (val))
if (EQ (fun, XCAR (val)))
@@ -2007,12 +1957,12 @@ safe_run_hooks (Lisp_Object hook)
int poll_suppress_count;
-/* Asynchronous timer for polling. */
-static struct atimer *poll_timer;
+#ifdef POLL_FOR_INPUT
+/* Asynchronous timer for polling. */
-#ifdef POLL_FOR_INPUT
+static struct atimer *poll_timer;
/* Poll for input, so that we catch a C-g if it comes in. This
function is called from x_make_frame_visible, see comment
@@ -2021,17 +1971,9 @@ static struct atimer *poll_timer;
void
poll_for_input_1 (void)
{
-/* Tell ns_read_socket() it is being called asynchronously so it can avoid
- doing anything dangerous. */
-#ifdef HAVE_NS
- ++handling_signal;
-#endif
- if (interrupt_input_blocked == 0
+ if (! input_blocked_p ()
&& !waiting_for_input)
- read_avail_input (0);
-#ifdef HAVE_NS
- --handling_signal;
-#endif
+ gobble_input ();
}
/* Timer callback function for poll_timer. TIMER is equal to
@@ -2041,14 +1983,7 @@ static void
poll_for_input (struct atimer *timer)
{
if (poll_suppress_count == 0)
- {
-#ifdef SYNC_INPUT
- interrupt_input_pending = 1;
- pending_signals = 1;
-#else
- poll_for_input_1 ();
-#endif
- }
+ pending_signals = 1;
}
#endif /* POLL_FOR_INPUT */
@@ -2091,9 +2026,9 @@ start_polling (void)
#endif
}
-/* Nonzero if we are using polling to handle input asynchronously. */
+/* True if we are using polling to handle input asynchronously. */
-int
+bool
input_polling_used (void)
{
#ifdef POLL_FOR_INPUT
@@ -2242,7 +2177,6 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
return;
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!noninteractive && STRINGP (help))
{
/* The mouse-fixup-help-message Lisp function can call
@@ -2255,7 +2189,6 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
if (f)
f->mouse_moved = 1;
}
-#endif
if (STRINGP (help) || NILP (help))
{
@@ -2269,7 +2202,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
/* Input of single characters from keyboard */
-static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, int *used_mouse_menu,
+static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
EMACS_TIME *end_time);
static void record_char (Lisp_Object c);
@@ -2306,9 +2239,9 @@ do { if (polling_stopped_here) start_polling (); \
not to run input methods, but in other respects to act as if
not reading a key sequence.
- If USED_MOUSE_MENU is non-null, then we set *USED_MOUSE_MENU to 1
- if we used a mouse menu to read the input, or zero otherwise. If
- USED_MOUSE_MENU is null, we don't dereference it.
+ If USED_MOUSE_MENU is non-null, then set *USED_MOUSE_MENU to true
+ if we used a mouse menu to read the input, or false otherwise. If
+ USED_MOUSE_MENU is null, don't dereference it.
Value is -2 when we find input on another keyboard. A second call
to read_char will read it.
@@ -2322,19 +2255,18 @@ do { if (polling_stopped_here) start_polling (); \
Lisp_Object
read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
Lisp_Object prev_event,
- int *used_mouse_menu, EMACS_TIME *end_time)
+ bool *used_mouse_menu, EMACS_TIME *end_time)
{
- volatile Lisp_Object c;
+ Lisp_Object c;
ptrdiff_t jmpcount;
- jmp_buf local_getcjmp;
- jmp_buf save_jump;
- volatile int key_already_recorded = 0;
+ sys_jmp_buf local_getcjmp;
+ sys_jmp_buf save_jump;
Lisp_Object tem, save;
volatile Lisp_Object previous_echo_area_message;
volatile Lisp_Object also_record;
- volatile int reread;
+ volatile bool reread;
struct gcpro gcpro1, gcpro2;
- int volatile polling_stopped_here = 0;
+ bool volatile polling_stopped_here = 0;
struct kboard *orig_kboard = current_kboard;
also_record = Qnil;
@@ -2368,18 +2300,9 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
goto reread_first;
}
- if (unread_command_char != -1)
- {
- XSETINT (c, unread_command_char);
- unread_command_char = -1;
-
- reread = 1;
- goto reread_first;
- }
-
if (CONSP (Vunread_command_events))
{
- int was_disabled = 0;
+ bool was_disabled = 0;
c = XCAR (Vunread_command_events);
Vunread_command_events = XCDR (Vunread_command_events);
@@ -2481,7 +2404,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
/* if redisplay was requested */
if (commandflag >= 0)
{
- int echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
+ bool echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
/* If there is pending input, process any events which are not
user-visible, such as X selection_request events. */
@@ -2561,7 +2484,6 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
&& !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
/* Don't bring up a menu if we already have another event. */
&& NILP (Vunread_command_events)
- && unread_command_char < 0
&& !detect_input_pending_run_timers (0))
{
c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
@@ -2570,10 +2492,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
return c; /* wrong_kboard_jmpbuf */
if (! NILP (c))
- {
- key_already_recorded = 1;
- goto non_reread_1;
- }
+ goto exit;
}
/* Make a longjmp point for quits to use, but don't alter getcjmp just yet.
@@ -2583,7 +2502,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
it *must not* be in effect when we call redisplay. */
jmpcount = SPECPDL_INDEX ();
- if (_setjmp (local_getcjmp))
+ if (sys_setjmp (local_getcjmp))
{
/* Handle quits while reading the keyboard. */
/* We must have saved the outer value of getcjmp here,
@@ -2605,13 +2524,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
Lisp_Object last = KVAR (kb, kbd_queue);
/* We shouldn't get here if we were in single-kboard mode! */
if (single_kboard)
- abort ();
+ emacs_abort ();
if (CONSP (last))
{
while (CONSP (XCDR (last)))
last = XCDR (last);
if (!NILP (XCDR (last)))
- abort ();
+ emacs_abort ();
}
if (!CONSP (last))
kset_kbd_queue (kb, Fcons (c, Qnil));
@@ -2697,8 +2616,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
&& !EQ (XCAR (prev_event), Qmenu_bar)
&& !EQ (XCAR (prev_event), Qtool_bar)
/* Don't bring up a menu if we already have another event. */
- && NILP (Vunread_command_events)
- && unread_command_char < 0)
+ && NILP (Vunread_command_events))
{
c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
@@ -2784,7 +2702,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
if (current_kboard->kbd_queue_has_data)
{
if (!CONSP (KVAR (current_kboard, kbd_queue)))
- abort ();
+ emacs_abort ();
c = XCAR (KVAR (current_kboard, kbd_queue));
kset_kbd_queue (current_kboard,
XCDR (KVAR (current_kboard, kbd_queue)));
@@ -2851,7 +2769,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
while (CONSP (XCDR (last)))
last = XCDR (last);
if (!NILP (XCDR (last)))
- abort ();
+ emacs_abort ();
}
if (!CONSP (last))
kset_kbd_queue (kb, Fcons (c, Qnil));
@@ -2902,12 +2820,10 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
goto wrong_kboard;
}
- non_reread_1:
-
/* Buffer switch events are only for internal wakeups
so don't show them to the user.
Also, don't record a key if we already did. */
- if (BUFFERP (c) || key_already_recorded)
+ if (BUFFERP (c))
goto exit;
/* Process special events within read_char
@@ -2920,12 +2836,6 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
if (!NILP (tem))
{
struct buffer *prev_buffer = current_buffer;
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- int was_locked = single_kboard;
- ptrdiff_t count = SPECPDL_INDEX ();
- record_single_kboard_state ();
-#endif
-
last_input_event = c;
Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt);
@@ -2936,13 +2846,6 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
example banishing the mouse under mouse-avoidance-mode. */
timer_resume_idle ();
-#if 0 /* This shouldn't be necessary anymore. --lorentey */
- /* Resume allowing input from any kboard, if that was true before. */
- if (!was_locked)
- any_kboard_state ();
- unbind_to (count, Qnil);
-#endif
-
if (current_buffer != prev_buffer)
{
/* The command may have changed the keymaps. Pretend there
@@ -3050,15 +2953,15 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
{
Lisp_Object keys;
ptrdiff_t key_count;
- int key_count_reset;
+ bool key_count_reset;
struct gcpro gcpro1;
ptrdiff_t count = SPECPDL_INDEX ();
/* Save the echo status. */
- int saved_immediate_echo = current_kboard->immediate_echo;
+ bool saved_immediate_echo = current_kboard->immediate_echo;
struct kboard *saved_ok_to_echo = ok_to_echo_at_next_pause;
Lisp_Object saved_echo_string = KVAR (current_kboard, echo_string);
- int saved_echo_after_prompt = current_kboard->echo_after_prompt;
+ ptrdiff_t saved_echo_after_prompt = current_kboard->echo_after_prompt;
#if 0
if (before_command_restore_flag)
@@ -3259,9 +3162,9 @@ record_menu_key (Lisp_Object c)
num_input_events++;
}
-/* Return 1 if should recognize C as "the help character". */
+/* Return true if should recognize C as "the help character". */
-static int
+static bool
help_char_p (Lisp_Object c)
{
Lisp_Object tail;
@@ -3380,7 +3283,7 @@ record_char (Lisp_Object c)
If you, dear reader, have a better idea, you've got the source. :-) */
if (dribble)
{
- BLOCK_INPUT;
+ block_input ();
if (INTEGERP (c))
{
if (XUINT (c) < 0x100)
@@ -3406,7 +3309,7 @@ record_char (Lisp_Object c)
}
fflush (dribble);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -3416,13 +3319,13 @@ record_char (Lisp_Object c)
See read_process_output. */
static void
-save_getcjmp (jmp_buf temp)
+save_getcjmp (sys_jmp_buf temp)
{
memcpy (temp, getcjmp, sizeof getcjmp);
}
static void
-restore_getcjmp (jmp_buf temp)
+restore_getcjmp (sys_jmp_buf temp)
{
memcpy (getcjmp, temp, sizeof getcjmp);
}
@@ -3433,7 +3336,7 @@ restore_getcjmp (jmp_buf temp)
/* Return true if there are any events in the queue that read-char
would return. If this returns false, a read-char would block. */
-static int
+static bool
readable_events (int flags)
{
if (flags & READABLE_EVENTS_DO_TIMERS_NOW)
@@ -3480,11 +3383,9 @@ readable_events (int flags)
return 1;
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
&& !NILP (do_mouse_tracking) && some_mouse_moved ())
return 1;
-#endif
if (single_kboard)
{
if (current_kboard->kbd_queue_has_data)
@@ -3506,20 +3407,20 @@ int stop_character EXTERNALLY_VISIBLE;
static KBOARD *
event_to_kboard (struct input_event *event)
{
- Lisp_Object frame;
- frame = event->frame_or_window;
- if (CONSP (frame))
- frame = XCAR (frame);
- else if (WINDOWP (frame))
- frame = WINDOW_FRAME (XWINDOW (frame));
-
- /* There are still some events that don't set this field.
- For now, just ignore the problem.
- Also ignore dead frames here. */
- if (!FRAMEP (frame) || !FRAME_LIVE_P (XFRAME (frame)))
- return 0;
+ /* Not applicable for these special events. */
+ if (event->kind == SELECTION_REQUEST_EVENT
+ || event->kind == SELECTION_CLEAR_EVENT)
+ return NULL;
else
- return FRAME_KBOARD (XFRAME (frame));
+ {
+ Lisp_Object obj = event->frame_or_window;
+ /* There are some events that set this field to nil or string. */
+ if (WINDOWP (obj))
+ obj = WINDOW_FRAME (XWINDOW (obj));
+ /* Also ignore dead frames here. */
+ return ((FRAMEP (obj) && FRAME_LIVE_P (XFRAME (obj)))
+ ? FRAME_KBOARD (XFRAME (obj)) : NULL);
+ }
}
#ifdef subprocesses
@@ -3550,17 +3451,15 @@ kbd_buffer_store_event (register struct input_event *event)
Else, if EVENT is a quit event, store the quit event
in HOLD_QUIT, and return (thus ignoring further events).
- This is used in read_avail_input to postpone the processing
- of the quit event until all subsequent input events have been
- parsed (and discarded).
- */
+ This is used to postpone the processing of the quit event until all
+ subsequent input events have been parsed (and discarded). */
void
kbd_buffer_store_event_hold (register struct input_event *event,
struct input_event *hold_quit)
{
if (event->kind == NO_EVENT)
- abort ();
+ emacs_abort ();
if (hold_quit && hold_quit->kind != NO_EVENT)
return;
@@ -3604,7 +3503,7 @@ kbd_buffer_store_event_hold (register struct input_event *event,
if (hold_quit)
{
- memcpy (hold_quit, event, sizeof (*event));
+ *hold_quit = *event;
return;
}
@@ -3623,7 +3522,8 @@ kbd_buffer_store_event_hold (register struct input_event *event,
}
last_event_timestamp = event->timestamp;
- handle_interrupt ();
+
+ handle_interrupt (0);
return;
}
@@ -3659,10 +3559,8 @@ kbd_buffer_store_event_hold (register struct input_event *event,
/* Don't read keyboard input until we have processed kbd_buffer.
This happens when pasting text longer than KBD_BUFFER_SIZE/2. */
hold_keyboard_input ();
-#ifdef SIGIO
if (!noninteractive)
- signal (SIGIO, SIG_IGN);
-#endif
+ ignore_sigio ();
stop_polling ();
}
#endif /* subprocesses */
@@ -3681,7 +3579,6 @@ kbd_buffer_store_event_hold (register struct input_event *event,
if (immediate_quit && NILP (Vinhibit_quit))
{
immediate_quit = 0;
- sigfree ();
QUIT;
}
}
@@ -3776,15 +3673,14 @@ discard_mouse_events (void)
}
-/* Return non-zero if there are any real events waiting in the event
+/* Return true if there are any real events waiting in the event
buffer, not counting `NO_EVENT's.
- If DISCARD is non-zero, discard NO_EVENT events at the front of
- the input queue, possibly leaving the input queue empty if there
- are no real input events. */
+ Discard NO_EVENT events at the front of the input queue, possibly
+ leaving the input queue empty if there are no real input events. */
-int
-kbd_buffer_events_waiting (int discard)
+bool
+kbd_buffer_events_waiting (void)
{
struct input_event *sp;
@@ -3796,16 +3692,14 @@ kbd_buffer_events_waiting (int discard)
sp = kbd_buffer;
}
- if (discard)
- kbd_fetch_ptr = sp;
-
+ kbd_fetch_ptr = sp;
return sp != kbd_store_ptr && sp->kind != NO_EVENT;
}
/* Clear input event EVENT. */
-static inline void
+static void
clear_event (struct input_event *event)
{
event->kind = NO_EVENT;
@@ -3820,7 +3714,7 @@ clear_event (struct input_event *event)
static Lisp_Object
kbd_buffer_get_event (KBOARD **kbp,
- int *used_mouse_menu,
+ bool *used_mouse_menu,
EMACS_TIME *end_time)
{
Lisp_Object obj;
@@ -3828,13 +3722,9 @@ kbd_buffer_get_event (KBOARD **kbp,
#ifdef subprocesses
if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE/4)
{
- /* Start reading input again, we have processed enough so we can
- accept new events again. */
+ /* Start reading input again because we have processed enough to
+ be able to accept new events again. */
unhold_keyboard_input ();
-#ifdef SIGIO
- if (!noninteractive)
- signal (SIGIO, input_available_signal);
-#endif /* SIGIO */
start_polling ();
}
#endif /* subprocesses */
@@ -3863,10 +3753,8 @@ kbd_buffer_get_event (KBOARD **kbp,
if (kbd_fetch_ptr != kbd_store_ptr)
break;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
break;
-#endif
/* If the quit flag is set, then read_char will return
quit_char, so that counts as "available input." */
@@ -3876,16 +3764,13 @@ kbd_buffer_get_event (KBOARD **kbp,
/* One way or another, wait until input is available; then, if
interrupt handlers have not read it, read it now. */
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
-#ifdef SIGIO
- gobble_input (0);
-#endif /* SIGIO */
+#ifdef USABLE_SIGIO
+ gobble_input ();
+#endif
if (kbd_fetch_ptr != kbd_store_ptr)
break;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
break;
-#endif
if (end_time)
{
EMACS_TIME now = current_emacs_time ();
@@ -3904,8 +3789,7 @@ kbd_buffer_get_event (KBOARD **kbp,
wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
- /* Pass 1 for EXPECT since we just waited to have input. */
- read_avail_input (1);
+ gobble_input ();
}
if (CONSP (Vunread_command_events))
@@ -3955,7 +3839,7 @@ kbd_buffer_get_event (KBOARD **kbp,
#else
/* We're getting selection request events, but we don't have
a window system. */
- abort ();
+ emacs_abort ();
#endif
}
@@ -4015,7 +3899,7 @@ kbd_buffer_get_event (KBOARD **kbp,
x_activate_menubar (XFRAME (event->frame_or_window));
}
#endif
-#if defined (WINDOWSNT)
+#ifdef HAVE_NTGUI
else if (event->kind == LANGUAGE_CHANGE_EVENT)
{
/* Make an event (language-change (FRAME CODEPAGE LANGUAGE-ID)). */
@@ -4026,6 +3910,18 @@ kbd_buffer_get_event (KBOARD **kbp,
kbd_fetch_ptr = event + 1;
}
#endif
+#ifdef WINDOWSNT
+ else if (event->kind == FILE_NOTIFY_EVENT)
+ {
+ /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */
+ obj = Fcons (Qfile_w32notify,
+ list2 (list3 (make_number (event->code),
+ XCAR (event->arg),
+ XCDR (event->arg)),
+ event->frame_or_window));
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
else if (event->kind == SAVE_SESSION_EVENT)
{
obj = Fcons (Qsave_session, Fcons (event->arg, Qnil));
@@ -4083,6 +3979,13 @@ kbd_buffer_get_event (KBOARD **kbp,
kbd_fetch_ptr = event + 1;
}
#endif
+#ifdef HAVE_INOTIFY
+ else if (event->kind == FILE_NOTIFY_EVENT)
+ {
+ obj = make_lispy_event (event);
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
else if (event->kind == CONFIG_CHANGED_EVENT)
{
obj = make_lispy_event (event);
@@ -4131,7 +4034,7 @@ kbd_buffer_get_event (KBOARD **kbp,
*used_mouse_menu = 1;
#endif
#ifdef HAVE_NS
- /* certain system events are non-key events */
+ /* Certain system events are non-key events. */
if (used_mouse_menu
&& event->kind == NS_NONKEY_EVENT)
*used_mouse_menu = 1;
@@ -4143,7 +4046,6 @@ kbd_buffer_get_event (KBOARD **kbp,
}
}
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
/* Try generating a mouse motion event. */
else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
{
@@ -4159,7 +4061,7 @@ kbd_buffer_get_event (KBOARD **kbp,
so x remains nil. */
x = Qnil;
- /* XXX Can f or mouse_position_hook be NULL here? */
+ /* XXX Can f or mouse_position_hook be NULL here? */
if (f && FRAME_TERMINAL (f)->mouse_position_hook)
(*FRAME_TERMINAL (f)->mouse_position_hook) (&f, 0, &bar_window,
&part, &x, &y, &t);
@@ -4188,11 +4090,10 @@ kbd_buffer_get_event (KBOARD **kbp,
if (!NILP (x) && NILP (obj))
obj = make_lispy_movement (f, bar_window, part, x, y, t);
}
-#endif /* HAVE_MOUSE || HAVE GPM */
else
/* We were promised by the above while loop that there was
something for us to read! */
- abort ();
+ emacs_abort ();
input_pending = readable_events (0);
@@ -4261,7 +4162,7 @@ process_special_events (void)
#else
/* We're getting selection request events, but we don't have
a window system. */
- abort ();
+ emacs_abort ();
#endif
}
}
@@ -4271,14 +4172,14 @@ process_special_events (void)
are ripe, and return, without reading any user-visible events. */
void
-swallow_events (int do_display)
+swallow_events (bool do_display)
{
- int old_timers_run;
+ unsigned old_timers_run;
process_special_events ();
old_timers_run = timers_run;
- get_input_pending (&input_pending, READABLE_EVENTS_DO_TIMERS_NOW);
+ get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
if (timers_run != old_timers_run && do_display)
redisplay_preserve_echo_area (7);
@@ -4351,7 +4252,7 @@ decode_timer (Lisp_Object timer, EMACS_TIME *result)
if (! NILP (vector[0]))
return 0;
- return decode_time_components (vector[1], vector[2], vector[3], vector[4],
+ return decode_time_components (vector[1], vector[2], vector[3], vector[8],
result, 0);
}
@@ -4369,25 +4270,18 @@ decode_timer (Lisp_Object timer, EMACS_TIME *result)
should be done. */
static EMACS_TIME
-timer_check_2 (void)
+timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{
EMACS_TIME nexttime;
EMACS_TIME now;
EMACS_TIME idleness_now;
- Lisp_Object timers, idle_timers, chosen_timer;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ Lisp_Object chosen_timer;
+ struct gcpro gcpro1;
nexttime = invalid_emacs_time ();
- /* Always consider the ordinary timers. */
- timers = Vtimer_list;
- /* Consider the idle timers only if Emacs is idle. */
- if (EMACS_TIME_VALID_P (timer_idleness_start_time))
- idle_timers = Vtimer_idle_list;
- else
- idle_timers = Qnil;
chosen_timer = Qnil;
- GCPRO3 (timers, idle_timers, chosen_timer);
+ GCPRO1 (chosen_timer);
/* First run the code that was delayed. */
while (CONSP (pending_funcalls))
@@ -4412,7 +4306,7 @@ timer_check_2 (void)
EMACS_TIME difference;
EMACS_TIME timer_difference = invalid_emacs_time ();
EMACS_TIME idle_timer_difference = invalid_emacs_time ();
- int ripe, timer_ripe = 0, idle_timer_ripe = 0;
+ bool ripe, timer_ripe = 0, idle_timer_ripe = 0;
/* Set TIMER and TIMER_DIFFERENCE
based on the next ordinary timer.
@@ -4536,13 +4430,35 @@ EMACS_TIME
timer_check (void)
{
EMACS_TIME nexttime;
+ Lisp_Object timers, idle_timers;
+ struct gcpro gcpro1, gcpro2;
+
+ Lisp_Object tem = Vinhibit_quit;
+ Vinhibit_quit = Qt;
+
+ /* We use copies of the timers' lists to allow a timer to add itself
+ again, without locking up Emacs if the newly added timer is
+ already ripe when added. */
+
+ /* Always consider the ordinary timers. */
+ timers = Fcopy_sequence (Vtimer_list);
+ /* Consider the idle timers only if Emacs is idle. */
+ if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+ idle_timers = Fcopy_sequence (Vtimer_idle_list);
+ else
+ idle_timers = Qnil;
+
+ Vinhibit_quit = tem;
+
+ GCPRO2 (timers, idle_timers);
do
{
- nexttime = timer_check_2 ();
+ nexttime = timer_check_2 (timers, idle_timers);
}
while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
+ UNGCPRO;
return nexttime;
}
@@ -4553,7 +4469,7 @@ in the same style as (current-time).
The value when Emacs is not idle is nil.
-NSEC is a multiple of the system clock resolution. */)
+PSEC is a multiple of the system clock resolution. */)
(void)
{
if (EMACS_TIME_VALID_P (timer_idleness_start_time))
@@ -5222,7 +5138,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
string_info = Fcons (string, make_number (charpos));
textpos = (w == XWINDOW (selected_window)
&& current_buffer == XBUFFER (w->buffer))
- ? PT : XMARKER (w->pointm)->charpos;
+ ? PT : marker_position (w->pointm);
xret = wx;
yret = wy;
@@ -5470,7 +5386,7 @@ make_lispy_event (struct input_event *event)
(sizeof (lispy_function_keys)
/ sizeof (lispy_function_keys[0])));
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
case MULTIMEDIA_KEY_EVENT:
if (event->code < (sizeof (lispy_multimedia_keys)
/ sizeof (lispy_multimedia_keys[0]))
@@ -5485,7 +5401,6 @@ make_lispy_event (struct input_event *event)
return Qnil;
#endif
-#ifdef HAVE_MOUSE
/* A mouse click. Figure out where it is, decide whether it's
a press, click or drag, and build the appropriate structure. */
case MOUSE_CLICK_EVENT:
@@ -5494,7 +5409,7 @@ make_lispy_event (struct input_event *event)
#endif
{
int button = event->code;
- int is_double;
+ bool is_double;
Lisp_Object position;
Lisp_Object *start_pos_ptr;
Lisp_Object start_pos;
@@ -5614,7 +5529,7 @@ make_lispy_event (struct input_event *event)
else if (FRAMEP (event->frame_or_window))
f = XFRAME (event->frame_or_window);
else
- abort ();
+ emacs_abort ();
if (FRAME_WINDOW_P (f))
fuzz = double_click_fuzz;
@@ -5721,7 +5636,7 @@ make_lispy_event (struct input_event *event)
else
/* Every mouse event should either have the down_modifier or
the up_modifier set. */
- abort ();
+ emacs_abort ();
{
/* Get the symbol we should use for the mouse click. */
@@ -5775,14 +5690,14 @@ make_lispy_event (struct input_event *event)
struct frame *fr;
int fuzz;
int symbol_num;
- int is_double;
+ bool is_double;
if (WINDOWP (event->frame_or_window))
fr = XFRAME (XWINDOW (event->frame_or_window)->frame);
else if (FRAMEP (event->frame_or_window))
fr = XFRAME (event->frame_or_window);
else
- abort ();
+ emacs_abort ();
fuzz = FRAME_WINDOW_P (fr)
? double_click_fuzz : double_click_fuzz / 8;
@@ -5802,7 +5717,7 @@ make_lispy_event (struct input_event *event)
else
/* Every wheel event should either have the down_modifier or
the up_modifier set. */
- abort ();
+ emacs_abort ();
if (event->kind == HORIZ_WHEEL_EVENT)
symbol_num += 2;
@@ -5937,7 +5852,6 @@ make_lispy_event (struct input_event *event)
Fcons (files,
Qnil)));
}
-#endif /* HAVE_MOUSE */
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS) || defined (USE_GTK)
@@ -5971,7 +5885,7 @@ make_lispy_event (struct input_event *event)
{
char *name = find_user_signal_name (event->code);
if (!name)
- abort ();
+ emacs_abort ();
return intern (name);
}
@@ -5985,6 +5899,13 @@ make_lispy_event (struct input_event *event)
}
#endif /* HAVE_DBUS */
+#ifdef HAVE_INOTIFY
+ case FILE_NOTIFY_EVENT:
+ {
+ return Fcons (Qfile_inotify, event->arg);
+ }
+#endif /* HAVE_INOTIFY */
+
case CONFIG_CHANGED_EVENT:
return Fcons (Qconfig_changed_event,
Fcons (event->arg,
@@ -6052,12 +5973,10 @@ make_lispy_event (struct input_event *event)
/* The 'kind' field of the event is something we don't recognize. */
default:
- abort ();
+ emacs_abort ();
}
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-
static Lisp_Object
make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_part part,
Lisp_Object x, Lisp_Object y, Time t)
@@ -6085,8 +6004,6 @@ make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_pa
}
}
-#endif /* HAVE_MOUSE || HAVE GPM */
-
/* Construct a switch frame event. */
static Lisp_Object
make_lispy_switch_frame (Lisp_Object frame)
@@ -6229,7 +6146,7 @@ apply_modifiers_uncached (int modifiers, char *base, int base_len, int base_len_
/* Only the event queue may use the `up' modifier; it should always
be turned into a click or drag event before presented to lisp code. */
if (modifiers & up_modifier)
- abort ();
+ emacs_abort ();
if (modifiers & alt_modifier) { *p++ = 'A'; *p++ = '-'; }
if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; }
@@ -6324,7 +6241,7 @@ parse_modifiers (Lisp_Object symbol)
Qnil);
if (modifiers & ~INTMASK)
- abort ();
+ emacs_abort ();
XSETFASTINT (mask, modifiers);
elements = Fcons (unmodified, Fcons (mask, Qnil));
@@ -6717,11 +6634,11 @@ parse_solitary_modifier (Lisp_Object symbol)
return 0;
}
-/* Return 1 if EVENT is a list whose elements are all integers or symbols.
+/* Return true if EVENT is a list whose elements are all integers or symbols.
Such a list is not valid as an event,
but it can be a Lucid-style event type list. */
-int
+bool
lucid_event_type_list_p (Lisp_Object object)
{
Lisp_Object tail;
@@ -6746,8 +6663,10 @@ lucid_event_type_list_p (Lisp_Object object)
return NILP (tail);
}
-/* Store into *addr a value nonzero if terminal input chars are available.
- Serves the purpose of ioctl (0, FIONREAD, addr)
+/* Return true if terminal input chars are available.
+ Also, store the return value into INPUT_PENDING.
+
+ Serves the purpose of ioctl (0, FIONREAD, ...)
but works even if FIONREAD does not exist.
(In fact, this may actually read some input.)
@@ -6758,50 +6677,21 @@ lucid_event_type_list_p (Lisp_Object object)
If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse
movements and toolkit scroll bar thumb drags. */
-static void
-get_input_pending (int *addr, int flags)
+static bool
+get_input_pending (int flags)
{
/* First of all, have we already counted some input? */
- *addr = (!NILP (Vquit_flag) || readable_events (flags));
+ input_pending = (!NILP (Vquit_flag) || readable_events (flags));
/* If input is being read as it arrives, and we have none, there is none. */
- if (*addr > 0 || (interrupt_input && ! interrupts_deferred))
- return;
-
- /* Try to read some input and see how much we get. */
- gobble_input (0);
- *addr = (!NILP (Vquit_flag) || readable_events (flags));
-}
-
-/* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary. */
-
-void
-gobble_input (int expected)
-{
-#ifdef SIGIO
- if (interrupt_input)
- {
- SIGMASKTYPE mask;
- mask = sigblock (sigmask (SIGIO));
- read_avail_input (expected);
- sigsetmask (mask);
- }
- else
-#ifdef POLL_FOR_INPUT
- /* XXX This condition was (read_socket_hook && !interrupt_input),
- but read_socket_hook is not global anymore. Let's pretend that
- it's always set. */
- if (!interrupt_input && poll_suppress_count == 0)
+ if (!input_pending && (!interrupt_input || interrupts_deferred))
{
- SIGMASKTYPE mask;
- mask = sigblock (sigmask (SIGALRM));
- read_avail_input (expected);
- sigsetmask (mask);
+ /* Try to read some input and see how much we get. */
+ gobble_input ();
+ input_pending = (!NILP (Vquit_flag) || readable_events (flags));
}
- else
-#endif
-#endif
- read_avail_input (expected);
+
+ return input_pending;
}
/* Put a BUFFER_SWITCH_EVENT in the buffer
@@ -6829,14 +6719,9 @@ record_asynch_buffer_change (void)
return;
/* Make sure no interrupt happens while storing the event. */
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
if (interrupt_input)
- {
- SIGMASKTYPE mask;
- mask = sigblock (sigmask (SIGIO));
- kbd_buffer_store_event (&event);
- sigsetmask (mask);
- }
+ kbd_buffer_store_event (&event);
else
#endif
{
@@ -6849,21 +6734,18 @@ record_asynch_buffer_change (void)
/* Read any terminal input already buffered up by the system
into the kbd_buffer, but do not wait.
- EXPECTED should be nonzero if the caller knows there is some input.
-
- Returns the number of keyboard chars read, or -1 meaning
+ Return the number of keyboard chars read, or -1 meaning
this is a bad time to try to read input. */
-static int
-read_avail_input (int expected)
+int
+gobble_input (void)
{
int nread = 0;
- int err = 0;
+ bool err = 0;
struct terminal *t;
/* Store pending user signal events, if any. */
- if (store_user_signal_events ())
- expected = 0;
+ store_user_signal_events ();
/* Loop through the available terminals, and call their input hooks. */
t = terminal_list;
@@ -6876,15 +6758,18 @@ read_avail_input (int expected)
int nr;
struct input_event hold_quit;
+ if (input_blocked_p ())
+ {
+ pending_signals = 1;
+ break;
+ }
+
EVENT_INIT (hold_quit);
hold_quit.kind = NO_EVENT;
/* No need for FIONREAD or fcntl; just say don't wait. */
- while (nr = (*t->read_socket_hook) (t, expected, &hold_quit), nr > 0)
- {
- nread += nr;
- expected = 0;
- }
+ while (0 < (nr = (*t->read_socket_hook) (t, &hold_quit)))
+ nread += nr;
if (nr == -1) /* Not OK to read input now. */
{
@@ -6904,7 +6789,7 @@ read_avail_input (int expected)
this process rather than to the whole process
group? Perhaps on systems with FIONREAD Emacs is
alone in its group. */
- kill (getpid (), SIGHUP);
+ terminate_due_to_signal (SIGHUP, 10);
/* XXX Is calling delete_terminal safe here? It calls delete_frame. */
{
@@ -6979,7 +6864,6 @@ decode_keyboard_code (struct tty_display_info *tty,
int
tty_read_avail_input (struct terminal *terminal,
- int expected,
struct input_event *hold_quit)
{
/* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
@@ -7001,7 +6885,7 @@ tty_read_avail_input (struct terminal *terminal,
if (terminal->type != output_termcap
&& terminal->type != output_msdos_raw)
- abort ();
+ emacs_abort ();
/* XXX I think the following code should be moved to separate hook
functions in system-dependent files. */
@@ -7053,7 +6937,7 @@ tty_read_avail_input (struct terminal *terminal,
#endif /* HAVE_GPM */
/* Determine how many characters we should *try* to read. */
-#ifdef FIONREAD
+#ifdef USABLE_FIONREAD
/* Find out how much input is available. */
if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0)
{
@@ -7066,14 +6950,12 @@ tty_read_avail_input (struct terminal *terminal,
return 0;
if (n_to_read > sizeof cbuf)
n_to_read = sizeof cbuf;
-#else /* no FIONREAD */
-#if defined (USG) || defined (CYGWIN)
+#elif defined USG || defined CYGWIN
/* Read some input if available, but don't wait. */
n_to_read = sizeof cbuf;
- fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
+ fcntl (fileno (tty->input), F_SETFL, O_NONBLOCK);
#else
- you lose;
-#endif
+# error "Cannot read without possibly delaying"
#endif
#ifdef subprocesses
@@ -7105,14 +6987,11 @@ tty_read_avail_input (struct terminal *terminal,
}
while (
/* We used to retry the read if it was interrupted.
- But this does the wrong thing when O_NDELAY causes
+ But this does the wrong thing when O_NONBLOCK causes
an EAGAIN error. Does anybody know of a situation
where a retry is actually needed? */
#if 0
- nread < 0 && (errno == EAGAIN
-#ifdef EFAULT
- || errno == EFAULT
-#endif
+ nread < 0 && (errno == EAGAIN || errno == EFAULT
#ifdef EBADSLT
|| errno == EBADSLT
#endif
@@ -7122,7 +7001,7 @@ tty_read_avail_input (struct terminal *terminal,
#endif
);
-#ifndef FIONREAD
+#ifndef USABLE_FIONREAD
#if defined (USG) || defined (CYGWIN)
fcntl (fileno (tty->input), F_SETFL, 0);
#endif /* USG or CYGWIN */
@@ -7193,85 +7072,83 @@ tty_read_avail_input (struct terminal *terminal,
return nread;
}
-#if defined SYNC_INPUT || defined SIGIO
static void
handle_async_input (void)
{
- interrupt_input_pending = 0;
-#ifdef SYNC_INPUT
- pending_signals = pending_atimers;
-#endif
-/* Tell ns_read_socket() it is being called asynchronously so it can avoid
- doing anything dangerous. */
-#ifdef HAVE_NS
- ++handling_signal;
-#endif
+#ifdef USABLE_SIGIO
while (1)
{
- int nread;
- nread = read_avail_input (1);
+ int nread = gobble_input ();
/* -1 means it's not ok to read the input now.
UNBLOCK_INPUT will read it later; now, avoid infinite loop.
0 means there was no keyboard input available. */
if (nread <= 0)
break;
}
-#ifdef HAVE_NS
- --handling_signal;
#endif
}
-#endif /* SYNC_INPUT || SIGIO */
-#ifdef SYNC_INPUT
void
process_pending_signals (void)
{
- if (interrupt_input_pending)
- handle_async_input ();
+ pending_signals = 0;
+ handle_async_input ();
do_pending_atimers ();
}
-#endif
-#ifdef SIGIO /* for entire page */
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
+/* Undo any number of BLOCK_INPUT calls down to level LEVEL,
+ and also (if the level is now 0) reinvoke any pending signal. */
-static void
-input_available_signal (int signo)
+void
+unblock_input_to (int level)
{
- /* Must preserve main program's value of errno. */
- int old_errno = errno;
- SIGNAL_THREAD_CHECK (signo);
+ interrupt_input_blocked = level;
+ if (level == 0)
+ {
+ if (pending_signals)
+ process_pending_signals ();
+ }
+ else if (level < 0)
+ emacs_abort ();
+}
-#ifdef SYNC_INPUT
- interrupt_input_pending = 1;
- pending_signals = 1;
-#endif
+/* End critical section.
- if (input_available_clear_time)
- *input_available_clear_time = make_emacs_time (0, 0);
+ If doing signal-driven input, and a signal came in when input was
+ blocked, reinvoke the signal handler now to deal with it. */
-#ifndef SYNC_INPUT
- handle_async_input ();
-#endif
+void
+unblock_input (void)
+{
+ unblock_input_to (interrupt_input_blocked - 1);
+}
+
+/* Undo any number of BLOCK_INPUT calls,
+ and also reinvoke any pending signal. */
- errno = old_errno;
+void
+totally_unblock_input (void)
+{
+ unblock_input_to (0);
}
-#endif /* SIGIO */
-/* Send ourselves a SIGIO.
+#ifdef USABLE_SIGIO
- This function exists so that the UNBLOCK_INPUT macro in
- blockinput.h can have some way to take care of input we put off
- dealing with, without assuming that every file which uses
- UNBLOCK_INPUT also has #included the files necessary to get SIGIO. */
void
-reinvoke_input_signal (void)
+handle_input_available_signal (int sig)
{
-#ifdef SIGIO
- handle_async_input ();
-#endif
+ pending_signals = 1;
+
+ if (input_available_clear_time)
+ *input_available_clear_time = make_emacs_time (0, 0);
}
+static void
+deliver_input_available_signal (int sig)
+{
+ deliver_process_signal (sig, handle_input_available_signal);
+}
+#endif /* USABLE_SIGIO */
/* User signal events. */
@@ -7296,6 +7173,7 @@ static struct user_signal_info *user_signals = NULL;
void
add_user_signal (int sig, const char *name)
{
+ struct sigaction action;
struct user_signal_info *p;
for (p = user_signals; p; p = p->next)
@@ -7310,18 +7188,16 @@ add_user_signal (int sig, const char *name)
p->next = user_signals;
user_signals = p;
- signal (sig, handle_user_signal);
+ emacs_sigaction_init (&action, deliver_user_signal);
+ sigaction (sig, &action, 0);
}
static void
handle_user_signal (int sig)
{
- int old_errno = errno;
struct user_signal_info *p;
const char *special_event_name = NULL;
- SIGNAL_THREAD_CHECK (sig);
-
if (SYMBOLP (Vdebug_on_event))
special_event_name = SSDATA (SYMBOL_NAME (Vdebug_on_event));
@@ -7342,9 +7218,9 @@ handle_user_signal (int sig)
}
p->npending++;
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
if (interrupt_input)
- kill (getpid (), SIGIO);
+ handle_input_available_signal (sig);
else
#endif
{
@@ -7355,8 +7231,12 @@ handle_user_signal (int sig)
}
break;
}
+}
- errno = old_errno;
+static void
+deliver_user_signal (int sig)
+{
+ deliver_process_signal (sig, handle_user_signal);
}
static char *
@@ -7371,27 +7251,24 @@ find_user_signal_name (int sig)
return NULL;
}
-static int
+static void
store_user_signal_events (void)
{
struct user_signal_info *p;
struct input_event buf;
- int nstored = 0;
+ bool buf_initialized = 0;
for (p = user_signals; p; p = p->next)
if (p->npending > 0)
{
- SIGMASKTYPE mask;
-
- if (nstored == 0)
+ if (! buf_initialized)
{
memset (&buf, 0, sizeof buf);
buf.kind = USER_SIGNAL_EVENT;
buf.frame_or_window = selected_frame;
+ buf_initialized = 1;
}
- nstored += p->npending;
- mask = sigblock (sigmask (p->sig));
do
{
buf.code = p->sig;
@@ -7399,10 +7276,7 @@ store_user_signal_events (void)
p->npending--;
}
while (p->npending > 0);
- sigsetmask (mask);
}
-
- return nstored;
}
@@ -7434,9 +7308,9 @@ static const char* separator_names[] = {
0,
};
-/* Return non-zero if LABEL specifies a separator. */
+/* Return true if LABEL specifies a separator. */
-int
+bool
menu_separator_name_p (const char *label)
{
if (!label)
@@ -7611,6 +7485,7 @@ menu_bar_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy1, void *dumm
{
struct gcpro gcpro1;
int i;
+ bool parsed;
Lisp_Object tem;
if (EQ (item, Qundefined))
@@ -7642,9 +7517,9 @@ menu_bar_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy1, void *dumm
parse_menu_item, so that if it turns out it wasn't a menu item,
it still correctly hides any further menu item. */
GCPRO1 (key);
- i = parse_menu_item (item, 1);
+ parsed = parse_menu_item (item, 1);
UNGCPRO;
- if (!i)
+ if (!parsed)
return;
item = AREF (item_properties, ITEM_PROPERTY_DEF);
@@ -7720,7 +7595,7 @@ menu_item_eval_property (Lisp_Object sexpr)
parse_menu_item returns true if the item is a menu item and false
otherwise. */
-int
+bool
parse_menu_item (Lisp_Object item, int inmenubar)
{
Lisp_Object def, tem, item_string, start;
@@ -8020,7 +7895,7 @@ static Lisp_Object QCrtl;
static void init_tool_bar_items (Lisp_Object);
static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*);
-static int parse_tool_bar_item (Lisp_Object, Lisp_Object);
+static bool parse_tool_bar_item (Lisp_Object, Lisp_Object);
static void append_tool_bar_item (void);
@@ -8145,7 +8020,7 @@ process_tool_bar_item (Lisp_Object key, Lisp_Object def, Lisp_Object data, void
/* Access slot with index IDX of vector tool_bar_item_properties. */
#define PROP(IDX) AREF (tool_bar_item_properties, (IDX))
-static inline void
+static void
set_prop (ptrdiff_t idx, Lisp_Object val)
{
ASET (tool_bar_item_properties, idx, val);
@@ -8153,7 +8028,7 @@ set_prop (ptrdiff_t idx, Lisp_Object val)
/* Parse a tool bar item specification ITEM for key KEY and return the
- result in tool_bar_item_properties. Value is zero if ITEM is
+ result in tool_bar_item_properties. Value is false if ITEM is
invalid.
ITEM is a list `(menu-item CAPTION BINDING PROPS...)'.
@@ -8198,12 +8073,13 @@ set_prop (ptrdiff_t idx, Lisp_Object val)
A text label to show with the tool bar button if labels are enabled. */
-static int
+static bool
parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
{
Lisp_Object filter = Qnil;
Lisp_Object caption;
- int i, have_label = 0;
+ int i;
+ bool have_label = 0;
/* Definition looks like `(menu-item CAPTION BINDING PROPS...)'.
Rule out items that aren't lists, don't start with
@@ -8460,9 +8336,9 @@ append_tool_bar_item (void)
PREV_EVENT is the previous input event, or nil if we are reading
the first event of a key sequence.
- If USED_MOUSE_MENU is non-null, then we set *USED_MOUSE_MENU to 1
- if we used a mouse menu to read the input, or zero otherwise. If
- USED_MOUSE_MENU is null, we don't dereference it.
+ If USED_MOUSE_MENU is non-null, set *USED_MOUSE_MENU to true
+ if we used a mouse menu to read the input, or false otherwise. If
+ USED_MOUSE_MENU is null, don't dereference it.
The prompting is done based on the prompt-string of the map
and the strings associated with various map elements.
@@ -8475,7 +8351,7 @@ append_tool_bar_item (void)
static Lisp_Object
read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
- Lisp_Object prev_event, int *used_mouse_menu)
+ Lisp_Object prev_event, bool *used_mouse_menu)
{
#ifdef HAVE_MENUS
ptrdiff_t mapno;
@@ -8569,7 +8445,7 @@ read_char_minibuf_menu_prompt (int commandflag,
/* FIXME: Use the minibuffer's frame width. */
ptrdiff_t width = FRAME_COLS (SELECTED_FRAME ()) - 4;
ptrdiff_t idx = -1;
- int nobindings = 1;
+ bool nobindings = 1;
Lisp_Object rest, vector;
char *menu;
@@ -8617,7 +8493,7 @@ read_char_minibuf_menu_prompt (int commandflag,
/* Present the documented bindings, a line at a time. */
while (1)
{
- int notfirst = 0;
+ bool notfirst = 0;
ptrdiff_t i = nlength;
Lisp_Object obj;
Lisp_Object orig_defn_macro;
@@ -8673,8 +8549,8 @@ read_char_minibuf_menu_prompt (int commandflag,
/* Ignore the element if it has no prompt string. */
if (INTEGERP (event) && parse_menu_item (elt, -1))
{
- /* 1 if the char to type matches the string. */
- int char_matches;
+ /* True if the char to type matches the string. */
+ bool char_matches;
Lisp_Object upcased_event, downcased_event;
Lisp_Object desc = Qnil;
Lisp_Object s
@@ -8726,7 +8602,7 @@ read_char_minibuf_menu_prompt (int commandflag,
i += 2;
}
notfirst = 1;
- nobindings = 0 ;
+ nobindings = 0;
/* If the char to type doesn't match the string's
first char, explicitly show what char to type. */
@@ -8860,14 +8736,14 @@ typedef struct keyremap
/* Lookup KEY in MAP.
MAP is a keymap mapping keys to key vectors or functions.
- If the mapping is a function and DO_FUNCTION is non-zero, then
+ If the mapping is a function and DO_FUNCALL is true,
the function is called with PROMPT as parameter and its return
value is used as the return value of this function (after checking
that it is indeed a vector). */
static Lisp_Object
access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
- int do_funcall)
+ bool do_funcall)
{
Lisp_Object next;
@@ -8906,15 +8782,15 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
BUFSIZE is its maximum size.
FKEY is a pointer to the keyremap structure to use.
INPUT is the index of the last element in KEYBUF.
- DOIT if non-zero says that the remapping can actually take place.
+ DOIT if true says that the remapping can actually take place.
DIFF is used to return the number of keys added/removed by the remapping.
PARENT is the root of the keymap.
PROMPT is the prompt to use if the remapping happens through a function.
- The return value is non-zero if the remapping actually took place. */
+ Return true if the remapping actually took place. */
-static int
+static bool
keyremap_step (Lisp_Object *keybuf, int bufsize, volatile keyremap *fkey,
- int input, int doit, int *diff, Lisp_Object prompt)
+ int input, bool doit, int *diff, Lisp_Object prompt)
{
Lisp_Object next, key;
@@ -8968,7 +8844,7 @@ keyremap_step (Lisp_Object *keybuf, int bufsize, volatile keyremap *fkey,
return 0;
}
-static int
+static bool
test_undefined (Lisp_Object binding)
{
return (EQ (binding, Qundefined)
@@ -9010,13 +8886,13 @@ test_undefined (Lisp_Object binding)
off the switch-frame event until later; the next call to
read_char will return it.
- If FIX_CURRENT_BUFFER is nonzero, we restore current_buffer
+ If FIX_CURRENT_BUFFER, we restore current_buffer
from the selected window's buffer. */
static int
read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
- int dont_downcase_last, int can_return_switch_frame,
- int fix_current_buffer)
+ bool dont_downcase_last, bool can_return_switch_frame,
+ bool fix_current_buffer)
{
Lisp_Object from_string;
ptrdiff_t count = SPECPDL_INDEX ();
@@ -9049,7 +8925,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
key sequence. */
Lisp_Object orig_keymap;
- /* 1 if we have already considered switching to the local-map property
+ /* Positive if we have already considered switching to the local-map property
of the place where a mouse click occurred. */
int localized_local_map = 0;
@@ -9089,10 +8965,10 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
/* Likewise, for key_translation_map and input-decode-map. */
keyremap keytran, indec;
- /* Non-zero if we are trying to map a key by changing an upper-case
+ /* True if we are trying to map a key by changing an upper-case
letter to lower case, or a shifted function key to an unshifted
one. */
- int shift_translated = 0;
+ bool shift_translated = 0;
/* If we receive a `switch-frame' or `select-window' event in the middle of
a key sequence, we put it off for later.
@@ -9108,7 +8984,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
int original_uppercase_position = -1;
/* Gets around Microsoft compiler limitations. */
- int dummyflag = 0;
+ bool dummyflag = 0;
struct buffer *starting_buffer;
@@ -9270,7 +9146,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
: (/* indec.start < t || fkey.start < t || */ keytran.start < t))
{
Lisp_Object key;
- int used_mouse_menu = 0;
+ bool used_mouse_menu = 0;
/* Where the last real key started. If we need to throw away a
key that has expanded into more than one element of keybuf
@@ -9364,7 +9240,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
return. Any better way to fix this? -- cyd */
|| (interrupted_kboard != current_kboard))
{
- int found = 0;
+ bool found = 0;
struct kboard *k;
for (k = all_kboards; k; k = k->next_kboard)
@@ -9918,7 +9794,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
while (indec.end < t)
{
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- int done, diff;
+ bool done;
+ int diff;
GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
done = keyremap_step (keybuf, bufsize, &indec, max (t, mock_input),
@@ -9952,7 +9829,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
while (fkey.end < indec.start)
{
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- int done, diff;
+ bool done;
+ int diff;
GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
done = keyremap_step (keybuf, bufsize, &fkey,
@@ -9981,7 +9859,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
while (keytran.end < fkey.start)
{
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- int done, diff;
+ bool done;
+ int diff;
GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input),
@@ -10367,38 +10246,32 @@ a special event, so ignore the prefix argument and don't clear it. */)
-/* Return nonzero if input events are pending. */
+/* Return true if input events are pending. */
-int
+bool
detect_input_pending (void)
{
- if (!input_pending)
- get_input_pending (&input_pending, 0);
-
- return input_pending;
+ return input_pending || get_input_pending (0);
}
-/* Return nonzero if input events other than mouse movements are
+/* Return true if input events other than mouse movements are
pending. */
-int
+bool
detect_input_pending_ignore_squeezables (void)
{
- if (!input_pending)
- get_input_pending (&input_pending, READABLE_EVENTS_IGNORE_SQUEEZABLES);
-
- return input_pending;
+ return input_pending || get_input_pending (READABLE_EVENTS_IGNORE_SQUEEZABLES);
}
-/* Return nonzero if input events are pending, and run any pending timers. */
+/* Return true if input events are pending, and run any pending timers. */
-int
-detect_input_pending_run_timers (int do_display)
+bool
+detect_input_pending_run_timers (bool do_display)
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
if (!input_pending)
- get_input_pending (&input_pending, READABLE_EVENTS_DO_TIMERS_NOW);
+ get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
if (old_timers_run != timers_run && do_display)
{
@@ -10429,16 +10302,16 @@ clear_input_pending (void)
input_pending = 0;
}
-/* Return nonzero if there are pending requeued events.
+/* Return true if there are pending requeued events.
This isn't used yet. The hope is to make wait_reading_process_output
call it, and return if it runs Lisp code that unreads something.
The problem is, kbd_buffer_get_event needs to be fixed to know what
to do in that case. It isn't trivial. */
-int
+bool
requeued_events_pending_p (void)
{
- return (!NILP (Vunread_command_events) || unread_command_char != -1);
+ return (!NILP (Vunread_command_events));
}
@@ -10448,7 +10321,7 @@ Actually, the value is nil only if we can be sure that no input is available;
if there is a doubt, the value is t. */)
(void)
{
- if (!NILP (Vunread_command_events) || unread_command_char != -1
+ if (!NILP (Vunread_command_events)
|| !NILP (Vunread_post_input_method_events)
|| !NILP (Vunread_input_method_events))
return (Qt);
@@ -10456,10 +10329,9 @@ if there is a doubt, the value is t. */)
/* Process non-user-visible events (Bug#10195). */
process_special_events ();
- get_input_pending (&input_pending,
- READABLE_EVENTS_DO_TIMERS_NOW
- | READABLE_EVENTS_FILTER_EVENTS);
- return input_pending > 0 ? Qt : Qnil;
+ return (get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW
+ | READABLE_EVENTS_FILTER_EVENTS)
+ ? Qt : Qnil);
}
DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0,
@@ -10606,9 +10478,9 @@ The file will be closed when Emacs exits. */)
{
if (dribble)
{
- BLOCK_INPUT;
+ block_input ();
fclose (dribble);
- UNBLOCK_INPUT;
+ unblock_input ();
dribble = 0;
}
if (!NILP (file))
@@ -10636,7 +10508,6 @@ Also end any kbd macro being defined. */)
update_mode_lines++;
Vunread_command_events = Qnil;
- unread_command_char = -1;
discard_tty_input ();
@@ -10776,17 +10647,10 @@ clear_waiting_for_input (void)
Otherwise, tell QUIT to kill Emacs. */
static void
-interrupt_signal (int signalnum) /* If we don't have an argument, some */
- /* compilers complain in signal calls. */
+handle_interrupt_signal (int sig)
{
- /* Must preserve main program's value of errno. */
- int old_errno = errno;
- struct terminal *terminal;
-
- SIGNAL_THREAD_CHECK (signalnum);
-
/* See if we have an active terminal on our controlling tty. */
- terminal = get_named_tty ("/dev/tty");
+ struct terminal *terminal = get_named_tty ("/dev/tty");
if (!terminal)
{
/* If there are no frames there, let's pretend that we are a
@@ -10805,16 +10669,21 @@ interrupt_signal (int signalnum) /* If we don't have an argument, some */
from the controlling tty. */
internal_last_event_frame = terminal->display_info.tty->top_frame;
- handle_interrupt ();
+ handle_interrupt (1);
}
+}
- errno = old_errno;
+static void
+deliver_interrupt_signal (int sig)
+{
+ deliver_process_signal (sig, handle_interrupt_signal);
}
+
/* If Emacs is stuck because `inhibit-quit' is true, then keep track
of the number of times C-g has been requested. If C-g is pressed
enough times, then quit anyway. See bug#6585. */
-static int force_quit_count;
+static int volatile force_quit_count;
/* This routine is called at interrupt level in response to C-g.
@@ -10828,7 +10697,7 @@ static int force_quit_count;
non-nil, it stops the job right away. */
static void
-handle_interrupt (void)
+handle_interrupt (bool in_signal_handler)
{
char c;
@@ -10837,15 +10706,21 @@ handle_interrupt (void)
/* XXX This code needs to be revised for multi-tty support. */
if (!NILP (Vquit_flag) && get_named_tty ("/dev/tty"))
{
- /* If SIGINT isn't blocked, don't let us be interrupted by
- another SIGINT, it might be harmful due to non-reentrancy
- in I/O functions. */
- sigblock (sigmask (SIGINT));
+ if (! in_signal_handler)
+ {
+ /* If SIGINT isn't blocked, don't let us be interrupted by
+ a SIGINT. It might be harmful due to non-reentrancy
+ in I/O functions. */
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGINT);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+ }
fflush (stdout);
reset_all_sys_modes ();
-#ifdef SIGTSTP /* Support possible in later USG versions */
+#ifdef SIGTSTP
/*
* On systems which can suspend the current process and return to the original
* shell, this command causes the user to end up back at the shell.
@@ -10902,7 +10777,7 @@ handle_interrupt (void)
#endif /* not MSDOS */
fflush (stdout);
if (((c = getchar ()) & ~040) == 'Y')
- abort ();
+ emacs_abort ();
while (c != '\n') c = getchar ();
#ifdef MSDOS
printf ("\r\nContinuing...\r\n");
@@ -10911,7 +10786,6 @@ handle_interrupt (void)
#endif /* not MSDOS */
fflush (stdout);
init_all_sys_modes ();
- sigfree ();
}
else
{
@@ -10924,20 +10798,19 @@ handle_interrupt (void)
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
immediate_quit = 0;
- sigfree ();
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
saved = gl_state;
GCPRO4 (saved.object, saved.global_code,
saved.current_syntax_table, saved.old_prop);
Fsignal (Qquit, Qnil);
- /* FIXME: AFAIK, `quit' can never return, so this code is dead! */
gl_state = saved;
UNGCPRO;
}
else
{ /* Else request quit when it's safe. */
- if (NILP (Vquit_flag))
- force_quit_count = 0;
- if (++force_quit_count == 3)
+ int count = NILP (Vquit_flag) ? 1 : force_quit_count + 1;
+ force_quit_count = count;
+ if (count == 3)
{
immediate_quit = 1;
Vinhibit_quit = Qnil;
@@ -10946,6 +10819,8 @@ handle_interrupt (void)
}
}
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+
/* TODO: The longjmp in this call throws the NS event loop integration off,
and it seems to do fine without this. Probably some attention
needs to be paid to the setting of waiting_for_input in
@@ -10955,43 +10830,32 @@ handle_interrupt (void)
separate event loop thread like W32. */
#ifndef HAVE_NS
if (waiting_for_input && !echoing)
- quit_throw_to_read_char (1);
+ quit_throw_to_read_char (in_signal_handler);
#endif
}
/* Handle a C-g by making read_char return C-g. */
static void
-quit_throw_to_read_char (int from_signal)
+quit_throw_to_read_char (bool from_signal)
{
/* When not called from a signal handler it is safe to call
Lisp. */
if (!from_signal && EQ (Vquit_flag, Qkill_emacs))
Fkill_emacs (Qnil);
- sigfree ();
/* Prevent another signal from doing this before we finish. */
clear_waiting_for_input ();
input_pending = 0;
Vunread_command_events = Qnil;
- unread_command_char = -1;
-#if 0 /* Currently, sit_for is called from read_char without turning
- off polling. And that can call set_waiting_for_input.
- It seems to be harmless. */
-#ifdef POLL_FOR_INPUT
- /* May be > 1 if in recursive minibuffer. */
- if (poll_suppress_count == 0)
- abort ();
-#endif
-#endif
if (FRAMEP (internal_last_event_frame)
&& !EQ (internal_last_event_frame, selected_frame))
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
0, 0, Qnil);
- _longjmp (getcjmp, 1);
+ sys_longjmp (getcjmp, 1);
}
DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,
@@ -11003,9 +10867,8 @@ otherwise Emacs uses CBREAK mode.
See also `current-input-mode'. */)
(Lisp_Object interrupt)
{
- int new_interrupt_input;
-#ifdef SIGIO
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
+ bool new_interrupt_input;
+#ifdef USABLE_SIGIO
#ifdef HAVE_X_WINDOWS
if (x_display_list != NULL)
{
@@ -11016,9 +10879,9 @@ See also `current-input-mode'. */)
else
#endif /* HAVE_X_WINDOWS */
new_interrupt_input = !NILP (interrupt);
-#else /* not SIGIO */
+#else /* not USABLE_SIGIO */
new_interrupt_input = 0;
-#endif /* not SIGIO */
+#endif /* not USABLE_SIGIO */
if (new_interrupt_input != interrupt_input)
{
@@ -11341,7 +11204,7 @@ delete_kboard (KBOARD *kb)
for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard)
if (*kbp == NULL)
- abort ();
+ emacs_abort ();
*kbp = kb->next_kboard;
/* Prevent a dangling reference to KB. */
@@ -11352,7 +11215,7 @@ delete_kboard (KBOARD *kb)
current_kboard = FRAME_KBOARD (XFRAME (selected_frame));
single_kboard = 0;
if (current_kboard == kb)
- abort ();
+ emacs_abort ();
}
wipe_kboard (kb);
@@ -11362,26 +11225,20 @@ delete_kboard (KBOARD *kb)
void
init_keyboard (void)
{
- /* This is correct before outermost invocation of the editor loop */
+ /* This is correct before outermost invocation of the editor loop. */
command_loop_level = -1;
immediate_quit = 0;
quit_char = Ctl ('g');
Vunread_command_events = Qnil;
- unread_command_char = -1;
timer_idleness_start_time = invalid_emacs_time ();
total_keys = 0;
recent_keys_index = 0;
kbd_fetch_ptr = kbd_buffer;
kbd_store_ptr = kbd_buffer;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
do_mouse_tracking = Qnil;
-#endif
input_pending = 0;
interrupt_input_blocked = 0;
- interrupt_input_pending = 0;
-#ifdef SYNC_INPUT
pending_signals = 0;
-#endif
/* This means that command_loop_1 won't try to select anything the first
time through. */
@@ -11401,21 +11258,26 @@ init_keyboard (void)
/* Before multi-tty support, these handlers used to be installed
only if the current session was a tty session. Now an Emacs
session may have multiple display types, so we always handle
- SIGINT. There is special code in interrupt_signal to exit
+ SIGINT. There is special code in handle_interrupt_signal to exit
Emacs on SIGINT when there are no termcap frames on the
controlling terminal. */
- signal (SIGINT, interrupt_signal);
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_interrupt_signal);
+ sigaction (SIGINT, &action, 0);
#ifndef DOS_NT
/* For systems with SysV TERMIO, C-g is set up for both SIGINT and
SIGQUIT and we can't tell which one it will give us. */
- signal (SIGQUIT, interrupt_signal);
+ sigaction (SIGQUIT, &action, 0);
#endif /* not DOS_NT */
}
-/* Note SIGIO has been undef'd if FIONREAD is missing. */
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
if (!noninteractive)
- signal (SIGIO, input_available_signal);
-#endif /* SIGIO */
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_input_available_signal);
+ sigaction (SIGIO, &action, 0);
+ }
+#endif
/* Use interrupt input by default, if it works and noninterrupt input
has deficiencies. */
@@ -11426,7 +11288,7 @@ init_keyboard (void)
interrupt_input = 0;
#endif
- sigfree ();
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
dribble = 0;
if (keyboard_init_hook)
@@ -11499,14 +11361,22 @@ syms_of_keyboard (void)
DEFSYM (Qconfig_changed_event, "config-changed-event");
DEFSYM (Qmenu_enable, "menu-enable");
-#if defined (WINDOWSNT)
+#ifdef HAVE_NTGUI
DEFSYM (Qlanguage_change, "language-change");
#endif
+#ifdef WINDOWSNT
+ DEFSYM (Qfile_w32notify, "file-w32notify");
+#endif
+
#ifdef HAVE_DBUS
DEFSYM (Qdbus_event, "dbus-event");
#endif
+#ifdef HAVE_INOTIFY
+ DEFSYM (Qfile_inotify, "file-inotify");
+#endif /* HAVE_INOTIFY */
+
DEFSYM (QCenable, ":enable");
DEFSYM (QCvisible, ":visible");
DEFSYM (QChelp, ":help");
@@ -11524,9 +11394,7 @@ syms_of_keyboard (void)
DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar");
DEFSYM (Qmenu_bar, "menu-bar");
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
DEFSYM (Qmouse_fixup_help_message, "mouse-fixup-help-message");
-#endif
DEFSYM (Qabove_handle, "above-handle");
DEFSYM (Qhandle, "handle");
@@ -11646,9 +11514,7 @@ syms_of_keyboard (void)
defsubr (&Sread_key_sequence);
defsubr (&Sread_key_sequence_vector);
defsubr (&Srecursive_edit);
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
defsubr (&Strack_mouse);
-#endif
defsubr (&Sinput_pending_p);
defsubr (&Scommand_execute);
defsubr (&Srecent_keys);
@@ -11694,9 +11560,6 @@ as they will already have been added once as they were read for the first time.
An element of the form (t . EVENT) forces EVENT to be added to that list. */);
Vunread_command_events = Qnil;
- DEFVAR_INT ("unread-command-char", unread_command_char,
- doc: /* If not -1, an object to be read as next command input event. */);
-
DEFVAR_LISP ("unread-post-input-method-events", Vunread_post_input_method_events,
doc: /* List of events to be processed as input by input methods.
These events are processed before `unread-command-events'
@@ -12270,11 +12133,20 @@ keys_of_keyboard (void)
"dbus-handle-event");
#endif
+#ifdef HAVE_INOTIFY
+ /* Define a special event which is raised for inotify callback
+ functions. */
+ initial_define_lispy_key (Vspecial_event_map, "file-inotify",
+ "inotify-handle-event");
+#endif /* HAVE_INOTIFY */
+
initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
"ignore");
#if defined (WINDOWSNT)
initial_define_lispy_key (Vspecial_event_map, "language-change",
"ignore");
+ initial_define_lispy_key (Vspecial_event_map, "file-w32notify",
+ "w32notify-handle-event");
#endif
}
@@ -12314,14 +12186,15 @@ mark_kboards (void)
{
if (event == kbd_buffer + KBD_BUFFER_SIZE)
event = kbd_buffer;
+ /* These two special event types has no Lisp_Objects to mark. */
if (event->kind != SELECTION_REQUEST_EVENT
&& event->kind != SELECTION_CLEAR_EVENT)
{
mark_object (event->x);
mark_object (event->y);
+ mark_object (event->frame_or_window);
+ mark_object (event->arg);
}
- mark_object (event->frame_or_window);
- mark_object (event->arg);
}
}
}
diff --git a/src/keyboard.h b/src/keyboard.h
index 91484b3649b..e57c8cc7193 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -169,12 +169,12 @@ struct kboard
reading from this KBOARD again until more input arrives. */
char kbd_queue_has_data;
- /* Nonzero means echo each character as typed. */
- char immediate_echo;
+ /* True means echo each character as typed. */
+ unsigned immediate_echo : 1;
/* If we have echoed a prompt string specified by the user,
this is its length in characters. Otherwise this is -1. */
- char echo_after_prompt;
+ ptrdiff_t echo_after_prompt;
};
KEYBOARD_INLINE void
@@ -463,14 +463,14 @@ extern Lisp_Object Qhelp_echo;
extern Lisp_Object Qmode_line, Qvertical_line, Qheader_line;
/* True while doing kbd input. */
-extern int waiting_for_input;
+extern bool waiting_for_input;
/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
happens. */
extern EMACS_TIME *input_available_clear_time;
#if defined HAVE_WINDOW_SYSTEM && !defined USE_GTK && !defined HAVE_NS
-extern int ignore_mouse_drag_p;
+extern bool ignore_mouse_drag_p;
#endif
/* The primary selection. */
@@ -482,7 +482,7 @@ struct input_event;
extern Lisp_Object parse_modifiers (Lisp_Object);
extern Lisp_Object reorder_modifiers (Lisp_Object);
extern Lisp_Object read_char (int, ptrdiff_t, Lisp_Object *, Lisp_Object,
- int *, EMACS_TIME *);
+ bool *, EMACS_TIME *);
extern int parse_solitary_modifier (Lisp_Object symbol);
@@ -506,10 +506,10 @@ extern Time last_event_timestamp;
extern int quit_char;
-extern int timers_run;
+extern unsigned int timers_run;
-extern int menu_separator_name_p (const char *);
-extern int parse_menu_item (Lisp_Object, int);
+extern bool menu_separator_name_p (const char *);
+extern bool parse_menu_item (Lisp_Object, int);
extern void init_kboard (KBOARD *);
extern void delete_kboard (KBOARD *);
@@ -523,16 +523,16 @@ extern void input_poll_signal (int);
extern void start_polling (void);
extern void stop_polling (void);
extern void set_poll_suppress_count (int);
-extern void gobble_input (int);
-extern int input_polling_used (void);
+extern int gobble_input (void);
+extern bool input_polling_used (void);
extern void clear_input_pending (void);
-extern int requeued_events_pending_p (void);
+extern bool requeued_events_pending_p (void);
extern void bind_polling_period (int);
extern int make_ctrl_char (int) ATTRIBUTE_CONST;
extern void stuff_buffered_input (Lisp_Object);
extern void clear_waiting_for_input (void);
-extern void swallow_events (int);
-extern int lucid_event_type_list_p (Lisp_Object);
+extern void swallow_events (bool);
+extern bool lucid_event_type_list_p (Lisp_Object);
extern void kbd_buffer_store_event (struct input_event *);
extern void kbd_buffer_store_event_hold (struct input_event *,
struct input_event *);
@@ -544,15 +544,14 @@ extern void gen_help_event (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, ptrdiff_t);
extern void kbd_buffer_store_help_event (Lisp_Object, Lisp_Object);
extern Lisp_Object menu_item_eval_property (Lisp_Object);
-extern int kbd_buffer_events_waiting (int);
+extern bool kbd_buffer_events_waiting (void);
extern void add_user_signal (int, const char *);
-extern int tty_read_avail_input (struct terminal *, int,
- struct input_event *);
+extern int tty_read_avail_input (struct terminal *, struct input_event *);
extern EMACS_TIME timer_check (void);
extern void mark_kboards (void);
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
extern const char *const lispy_function_keys[];
#endif
diff --git a/src/keymap.c b/src/keymap.c
index 85c384b8180..fbdd31e0de3 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "commands.h"
#include "character.h"
@@ -99,12 +99,12 @@ static void describe_command (Lisp_Object, Lisp_Object);
static void describe_translation (Lisp_Object, Lisp_Object);
static void describe_map (Lisp_Object, Lisp_Object,
void (*) (Lisp_Object, Lisp_Object),
- int, Lisp_Object, Lisp_Object*, int, int);
+ bool, Lisp_Object, Lisp_Object*, bool, bool);
static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object,
- void (*) (Lisp_Object, Lisp_Object), int,
- Lisp_Object, Lisp_Object, int, int);
+ void (*) (Lisp_Object, Lisp_Object), bool,
+ Lisp_Object, Lisp_Object, bool, bool);
static void silly_event_symbol_error (Lisp_Object);
-static Lisp_Object get_keyelt (Lisp_Object, int);
+static Lisp_Object get_keyelt (Lisp_Object, bool);
/* Keymap object support - constructors and predicates. */
@@ -207,15 +207,12 @@ when reading a key-sequence to be looked-up in this keymap. */)
/* Check that OBJECT is a keymap (after dereferencing through any
symbols). If it is, return it.
- If AUTOLOAD is non-zero and OBJECT is a symbol whose function value
+ If AUTOLOAD and if OBJECT is a symbol whose function value
is an autoload form, do the autoload and try again.
- If AUTOLOAD is nonzero, callers must assume GC is possible.
-
- If the map needs to be autoloaded, but AUTOLOAD is zero (and ERROR
- is zero as well), return Qt.
+ If AUTOLOAD, callers must assume GC is possible.
ERROR_IF_NOT_KEYMAP controls how we respond if OBJECT isn't a keymap.
- If ERROR_IF_NOT_KEYMAP is non-zero, signal an error; otherwise,
+ If ERROR_IF_NOT_KEYMAP, signal an error; otherwise,
just return Qnil.
Note that most of the time, we don't want to pursue autoloads.
@@ -224,11 +221,11 @@ when reading a key-sequence to be looked-up in this keymap. */)
but it seems to me that only read_key_sequence, Flookup_key, and
Fdefine_key should cause keymaps to be autoloaded.
- This function can GC when AUTOLOAD is non-zero, because it calls
+ This function can GC when AUTOLOAD is true, because it calls
Fautoload_do_load which can GC. */
Lisp_Object
-get_keymap (Lisp_Object object, int error_if_not_keymap, int autoload)
+get_keymap (Lisp_Object object, bool error_if_not_keymap, bool autoload)
{
Lisp_Object tem;
@@ -280,7 +277,7 @@ get_keymap (Lisp_Object object, int error_if_not_keymap, int autoload)
We assume that KEYMAP is a valid keymap. */
static Lisp_Object
-keymap_parent (Lisp_Object keymap, int autoload)
+keymap_parent (Lisp_Object keymap, bool autoload)
{
Lisp_Object list;
@@ -307,7 +304,7 @@ If KEYMAP has no parent, return nil. */)
}
/* Check whether MAP is one of MAPS parents. */
-static int
+static bool
keymap_memberp (Lisp_Object map, Lisp_Object maps)
{
if (NILP (map)) return 0;
@@ -365,19 +362,20 @@ Return PARENT. PARENT should be nil or another keymap. */)
MAP must be a keymap or a list of keymaps.
- If T_OK is non-zero, bindings for Qt are treated as default
+ If T_OK, bindings for Qt are treated as default
bindings; any key left unmentioned by other tables and bindings is
given the binding of Qt.
- If T_OK is zero, bindings for Qt are not treated specially.
+ If not T_OK, bindings for Qt are not treated specially.
If NOINHERIT, don't accept a subkeymap found in an inherited keymap.
- Returns Qunbound if no binding was found (and returns Qnil if a nil
+ Return Qunbound if no binding was found (and return Qnil if a nil
binding was found). */
static Lisp_Object
-access_keymap_1 (Lisp_Object map, Lisp_Object idx, int t_ok, int noinherit, int autoload)
+access_keymap_1 (Lisp_Object map, Lisp_Object idx,
+ bool t_ok, bool noinherit, bool autoload)
{
/* If idx is a list (some sort of mouse click, perhaps?),
the index we want to use is the car of the list, which
@@ -547,7 +545,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, int t_ok, int noinherit, int
Lisp_Object
access_keymap (Lisp_Object map, Lisp_Object idx,
- int t_ok, int noinherit, int autoload)
+ bool t_ok, bool noinherit, bool autoload)
{
Lisp_Object val = access_keymap_1 (map, idx, t_ok, noinherit, autoload);
return EQ (val, Qunbound) ? Qnil : val;
@@ -630,9 +628,10 @@ map_keymap_call (Lisp_Object key, Lisp_Object val, Lisp_Object fun, void *dummy)
}
/* Same as map_keymap_internal, but traverses parent keymaps as well.
- A non-zero AUTOLOAD indicates that autoloaded keymaps should be loaded. */
+ AUTOLOAD indicates that autoloaded keymaps should be loaded. */
void
-map_keymap (Lisp_Object map, map_keymap_function_t fun, Lisp_Object args, void *data, int autoload)
+map_keymap (Lisp_Object map, map_keymap_function_t fun, Lisp_Object args,
+ void *data, bool autoload)
{
struct gcpro gcpro1;
GCPRO1 (args);
@@ -711,13 +710,13 @@ usage: (map-keymap FUNCTION KEYMAP) */)
Also if OBJECT has a menu string as the first element,
remove that. Also remove a menu help string as second element.
- If AUTOLOAD is nonzero, load autoloadable keymaps
+ If AUTOLOAD, load autoloadable keymaps
that are referred to with indirection.
This can GC because menu_item_eval_property calls Feval. */
static Lisp_Object
-get_keyelt (Lisp_Object object, int autoload)
+get_keyelt (Lisp_Object object, bool autoload)
{
while (1)
{
@@ -1114,10 +1113,10 @@ binding is altered. If there is no binding for KEY, the new pair
binding KEY to DEF is added at the front of KEYMAP. */)
(Lisp_Object keymap, Lisp_Object key, Lisp_Object def)
{
- register ptrdiff_t idx;
- register Lisp_Object c;
- register Lisp_Object cmd;
- int metized = 0;
+ ptrdiff_t idx;
+ Lisp_Object c;
+ Lisp_Object cmd;
+ bool metized = 0;
int meta_bit;
ptrdiff_t length;
struct gcpro gcpro1, gcpro2, gcpro3;
@@ -1271,11 +1270,11 @@ third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will
recognize the default bindings, just as `read-key-sequence' does. */)
(Lisp_Object keymap, Lisp_Object key, Lisp_Object accept_default)
{
- register ptrdiff_t idx;
- register Lisp_Object cmd;
- register Lisp_Object c;
+ ptrdiff_t idx;
+ Lisp_Object cmd;
+ Lisp_Object c;
ptrdiff_t length;
- int t_ok = !NILP (accept_default);
+ bool t_ok = !NILP (accept_default);
struct gcpro gcpro1, gcpro2;
GCPRO2 (keymap, key);
@@ -1477,7 +1476,7 @@ current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr)
/* Use malloc here. See the comment above this function.
Avoid realloc here; it causes spurious traps on GNU/Linux [KFS] */
- BLOCK_INPUT;
+ block_input ();
newmodes = malloc (allocsize);
if (newmodes)
{
@@ -1501,7 +1500,7 @@ current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr)
}
cmm_maps = newmaps;
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (newmodes == NULL || newmaps == NULL)
break;
@@ -1887,7 +1886,7 @@ DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_
struct accessible_keymaps_data {
Lisp_Object maps, tail, thisseq;
/* Does the current sequence end in the meta-prefix-char? */
- int is_metized;
+ bool is_metized;
};
static void
@@ -1898,7 +1897,7 @@ accessible_keymaps_1 (Lisp_Object key, Lisp_Object cmd, Lisp_Object args, void *
Lisp_Object maps = d->maps;
Lisp_Object tail = d->tail;
Lisp_Object thisseq = d->thisseq;
- int is_metized = d->is_metized && INTEGERP (key);
+ bool is_metized = d->is_metized && INTEGERP (key);
Lisp_Object tem;
cmd = get_keymap (get_keyelt (cmd, 0), 0, 0);
@@ -2060,7 +2059,7 @@ The `kbd' macro is an approximate inverse of this. */)
Lisp_Object sep = build_string (" ");
Lisp_Object key;
Lisp_Object result;
- int add_meta = 0;
+ bool add_meta = 0;
USE_SAFE_ALLOCA;
if (!NILP (prefix))
@@ -2155,9 +2154,10 @@ The `kbd' macro is an approximate inverse of this. */)
char *
-push_key_description (EMACS_INT ch, char *p, int force_multibyte)
+push_key_description (EMACS_INT ch, char *p)
{
- int c, c2, tab_as_ci;
+ int c, c2;
+ bool tab_as_ci;
/* Clear all the meaningless bits above the meta bit. */
c = ch & (meta_modifier | ~ - meta_modifier);
@@ -2256,21 +2256,12 @@ push_key_description (EMACS_INT ch, char *p, int force_multibyte)
*p++ = 'P';
*p++ = 'C';
}
- else if (c < 128
- || (NILP (BVAR (current_buffer, enable_multibyte_characters))
- && SINGLE_BYTE_CHAR_P (c)
- && !force_multibyte))
- {
- *p++ = c;
- }
+ else if (c < 128)
+ *p++ = c;
else
{
/* Now we are sure that C is a valid character code. */
- if (NILP (BVAR (current_buffer, enable_multibyte_characters))
- && ! force_multibyte)
- *p++ = multibyte_char_to_unibyte (c);
- else
- p += CHAR_STRING (c, (unsigned char *) p);
+ p += CHAR_STRING (c, (unsigned char *) p);
}
return p;
@@ -2299,9 +2290,8 @@ around function keys and event symbols. */)
if (INTEGERP (key)) /* Normal character. */
{
- char tem[KEY_DESCRIPTION_SIZE], *p;
-
- p = push_key_description (XINT (key), tem, 1);
+ char tem[KEY_DESCRIPTION_SIZE];
+ char *p = push_key_description (XINT (key), tem);
*p = 0;
return make_specified_string (tem, -1, p - tem, 1);
}
@@ -2429,7 +2419,7 @@ static void where_is_internal_1 (Lisp_Object key, Lisp_Object binding,
static Lisp_Object
shadow_lookup (Lisp_Object shadow, Lisp_Object key, Lisp_Object flag,
- int remap)
+ bool remap)
{
Lisp_Object tail, value;
@@ -2461,7 +2451,7 @@ static Lisp_Object Vmouse_events;
struct where_is_internal_data {
Lisp_Object definition, this, last;
- int last_is_meta, noindirect;
+ bool last_is_meta, noindirect;
Lisp_Object sequences;
};
@@ -2474,7 +2464,7 @@ struct where_is_internal_data {
static Lisp_Object
where_is_internal (Lisp_Object definition, Lisp_Object keymaps,
- int noindirect, int nomenus)
+ bool noindirect, bool nomenus)
{
Lisp_Object maps = Qnil;
Lisp_Object found;
@@ -2523,7 +2513,7 @@ where_is_internal (Lisp_Object definition, Lisp_Object keymaps,
[M-CHAR] sequences, check if last character of the sequence
is the meta-prefix char. */
Lisp_Object last;
- int last_is_meta;
+ bool last_is_meta;
this = Fcar (XCAR (maps));
map = Fcdr (XCAR (maps));
@@ -2606,7 +2596,7 @@ The optional 5th arg NO-REMAP alters how command remapping is handled:
/* Actually relevant bindings. */
Lisp_Object found = Qnil;
/* 1 means ignore all menu bindings entirely. */
- int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii);
+ bool nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii);
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
/* List of sequences found via remapping. Keep them in a separate
variable, so as to push them later, since we prefer
@@ -2615,7 +2605,7 @@ The optional 5th arg NO-REMAP alters how command remapping is handled:
/* Whether or not we're handling remapped sequences. This is needed
because remapping is not done recursively by Fcommand_remapping: you
can't remap a remapped command. */
- int remapped = 0;
+ bool remapped = 0;
Lisp_Object tem = Qnil;
/* Refresh the C version of the modifier preference. */
@@ -2767,10 +2757,10 @@ where_is_internal_1 (Lisp_Object key, Lisp_Object binding, Lisp_Object args, voi
{
struct where_is_internal_data *d = data; /* Cast! */
Lisp_Object definition = d->definition;
- int noindirect = d->noindirect;
+ bool noindirect = d->noindirect;
Lisp_Object this = d->this;
Lisp_Object last = d->last;
- int last_is_meta = d->last_is_meta;
+ bool last_is_meta = d->last_is_meta;
Lisp_Object sequence;
/* Search through indirections unless that's not wanted. */
@@ -2821,8 +2811,8 @@ The optional argument MENUS, if non-nil, says to mention menu bindings.
(Lisp_Object buffer, Lisp_Object prefix, Lisp_Object menus)
{
Lisp_Object outbuf, shadow;
- int nomenu = NILP (menus);
- register Lisp_Object start1;
+ bool nomenu = NILP (menus);
+ Lisp_Object start1;
struct gcpro gcpro1;
const char *alternate_heading
@@ -2857,10 +2847,10 @@ You type Translation\n\
alternate_heading = 0;
}
- bufend = push_key_description (translate[c], buf, 1);
+ bufend = push_key_description (translate[c], buf);
insert (buf, bufend - buf);
Findent_to (make_number (16), make_number (1));
- bufend = push_key_description (c, buf, 1);
+ bufend = push_key_description (c, buf);
insert (buf, bufend - buf);
insert ("\n", 1);
@@ -2923,7 +2913,7 @@ You type Translation\n\
char *title, *p;
if (!SYMBOLP (modes[i]))
- abort ();
+ emacs_abort ();
p = title = alloca (42 + SCHARS (SYMBOL_NAME (modes[i])));
*p++ = '\f';
@@ -2977,34 +2967,34 @@ You type Translation\n\
/* Insert a description of the key bindings in STARTMAP,
followed by those of all maps reachable through STARTMAP.
- If PARTIAL is nonzero, omit certain "uninteresting" commands
+ If PARTIAL, omit certain "uninteresting" commands
(such as `undefined').
If SHADOW is non-nil, it is a list of maps;
don't mention keys which would be shadowed by any of them.
PREFIX, if non-nil, says mention only keys that start with PREFIX.
TITLE, if not 0, is a string to insert at the beginning.
TITLE should not end with a colon or a newline; we supply that.
- If NOMENU is not 0, then omit menu-bar commands.
+ If NOMENU, then omit menu-bar commands.
- If TRANSL is nonzero, the definitions are actually key translations
+ If TRANSL, the definitions are actually key translations
so print strings and vectors differently.
- If ALWAYS_TITLE is nonzero, print the title even if there are no maps
+ If ALWAYS_TITLE, print the title even if there are no maps
to look through.
- If MENTION_SHADOW is nonzero, then when something is shadowed by SHADOW,
+ If MENTION_SHADOW, then when something is shadowed by SHADOW,
don't omit it; instead, mention it but say it is shadowed.
Any inserted text ends in two newlines (used by `help-make-xrefs'). */
void
-describe_map_tree (Lisp_Object startmap, int partial, Lisp_Object shadow,
- Lisp_Object prefix, const char *title, int nomenu, int transl,
- int always_title, int mention_shadow)
+describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow,
+ Lisp_Object prefix, const char *title, bool nomenu,
+ bool transl, bool always_title, bool mention_shadow)
{
Lisp_Object maps, orig_maps, seen, sub_shadows;
struct gcpro gcpro1, gcpro2, gcpro3;
- int something = 0;
+ bool something = 0;
const char *key_heading
= "\
key binding\n\
@@ -3179,7 +3169,12 @@ describe_translation (Lisp_Object definition, Lisp_Object args)
into an array of `struct describe_map_elt',
then sorts them by the events. */
-struct describe_map_elt { Lisp_Object event; Lisp_Object definition; int shadowed; };
+struct describe_map_elt
+{
+ Lisp_Object event;
+ Lisp_Object definition;
+ bool shadowed;
+};
/* qsort comparison function for sorting `struct describe_map_elt' by
the event field. */
@@ -3209,14 +3204,14 @@ describe_map_compare (const void *aa, const void *bb)
static void
describe_map (Lisp_Object map, Lisp_Object prefix,
void (*elt_describer) (Lisp_Object, Lisp_Object),
- int partial, Lisp_Object shadow,
- Lisp_Object *seen, int nomenu, int mention_shadow)
+ bool partial, Lisp_Object shadow,
+ Lisp_Object *seen, bool nomenu, bool mention_shadow)
{
Lisp_Object tail, definition, event;
Lisp_Object tem;
Lisp_Object suppress;
Lisp_Object kludge;
- int first = 1;
+ bool first = 1;
struct gcpro gcpro1, gcpro2, gcpro3;
/* These accumulate the values from sparse keymap bindings,
@@ -3258,7 +3253,7 @@ describe_map (Lisp_Object map, Lisp_Object prefix,
1, mention_shadow);
else if (CONSP (XCAR (tail)))
{
- int this_shadowed = 0;
+ bool this_shadowed = 0;
event = XCAR (XCAR (tail));
@@ -3428,7 +3423,7 @@ DESCRIBER is the output function used; nil means use `princ'. */)
of bytes that lead to the character set or portion of a character
set described by this chartable.
- If PARTIAL is nonzero, it means do not mention suppressed commands
+ If PARTIAL, it means do not mention suppressed commands
(that assumes the vector is in a keymap).
SHADOW is a list of keymaps that shadow this map.
@@ -3448,8 +3443,8 @@ DESCRIBER is the output function used; nil means use `princ'. */)
static void
describe_vector (Lisp_Object vector, Lisp_Object prefix, Lisp_Object args,
void (*elt_describer) (Lisp_Object, Lisp_Object),
- int partial, Lisp_Object shadow, Lisp_Object entire_map,
- int keymap_p, int mention_shadow)
+ bool partial, Lisp_Object shadow, Lisp_Object entire_map,
+ bool keymap_p, bool mention_shadow)
{
Lisp_Object definition;
Lisp_Object tem2;
@@ -3457,7 +3452,7 @@ describe_vector (Lisp_Object vector, Lisp_Object prefix, Lisp_Object args,
int i;
Lisp_Object suppress;
Lisp_Object kludge;
- int first = 1;
+ bool first = 1;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
/* Range of elements to be handled. */
int from, to, stop;
@@ -3497,7 +3492,7 @@ describe_vector (Lisp_Object vector, Lisp_Object prefix, Lisp_Object args,
for (i = from; ; i++)
{
- int this_shadowed = 0;
+ bool this_shadowed = 0;
int range_beg, range_end;
Lisp_Object val;
diff --git a/src/keymap.h b/src/keymap.h
index 5ed70c67b85..c704ee0b050 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -34,11 +34,11 @@ 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 *, int);
-extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, int, int, int);
-extern Lisp_Object get_keymap (Lisp_Object, int, int);
-extern void describe_map_tree (Lisp_Object, int, Lisp_Object, Lisp_Object,
- const char *, int, int, int, int);
+extern char *push_key_description (EMACS_INT, char *);
+extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool);
+extern Lisp_Object get_keymap (Lisp_Object, bool, bool);
+extern void describe_map_tree (Lisp_Object, bool, Lisp_Object, Lisp_Object,
+ const char *, bool, bool, bool, bool);
extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **);
extern void initial_define_key (Lisp_Object, int, const char *);
extern void initial_define_lispy_key (Lisp_Object, const char *, const char *);
@@ -47,7 +47,8 @@ extern void keys_of_keymap (void);
typedef void (*map_keymap_function_t)
(Lisp_Object key, Lisp_Object val, Lisp_Object args, void* data);
-extern void map_keymap (Lisp_Object map, map_keymap_function_t fun, Lisp_Object largs, void* cargs, int autoload);
+extern void map_keymap (Lisp_Object, map_keymap_function_t, Lisp_Object,
+ void *, bool);
extern void map_keymap_canonical (Lisp_Object map,
map_keymap_function_t fun,
Lisp_Object args, void *data);
diff --git a/src/lisp.h b/src/lisp.h
index 07a3ae17469..82bf621b62f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -20,10 +20,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef EMACS_LISP_H
#define EMACS_LISP_H
+#include <setjmp.h>
#include <stdalign.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
+#include <float.h>
#include <inttypes.h>
#include <limits.h>
@@ -160,11 +162,9 @@ enum Lisp_Bits
#define GCTYPEBITS 3
GCTYPEBITS,
- /* 2**GCTYPEBITS. This must also be a macro that expands to a
- literal integer constant, for MSVC. */
- GCALIGNMENT =
+ /* 2**GCTYPEBITS. This must be a macro that expands to a literal
+ integer constant, for MSVC. */
#define GCALIGNMENT 8
- GCALIGNMENT,
/* Number of bits in a Lisp_Object value, not counting the tag. */
VALBITS = BITS_PER_EMACS_INT - GCTYPEBITS,
@@ -222,7 +222,9 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
/* Define the fundamental Lisp data structures. */
-/* This is the set of Lisp data types. */
+/* This is the set of Lisp data types. If you want to define a new
+ data type, read the comments after Lisp_Fwd_Type definition
+ below. */
/* Lisp integers use 2 tags, to give them one extra bit, thus
extending their range from, e.g., -2^28..2^28-1 to -2^29..2^29-1. */
@@ -298,6 +300,53 @@ enum Lisp_Fwd_Type
Lisp_Fwd_Kboard_Obj, /* Fwd to a Lisp_Object field of kboards. */
};
+/* If you want to define a new Lisp data type, here are some
+ instructions. See the thread at
+ http://lists.gnu.org/archive/html/emacs-devel/2012-10/msg00561.html
+ for more info.
+
+ First, there are already a couple of Lisp types that can be used if
+ your new type does not need to be exposed to Lisp programs nor
+ displayed to users. These are Lisp_Save_Value, a Lisp_Misc
+ subtype; and PVEC_OTHER, a kind of vectorlike object. The former
+ is suitable for temporarily stashing away pointers and integers in
+ a Lisp object (see the existing uses of make_save_value and
+ XSAVE_VALUE). The latter is useful for vector-like Lisp objects
+ that need to be used as part of other objects, but which are never
+ shown to users or Lisp code (search for PVEC_OTHER in xterm.c for
+ an example).
+
+ These two types don't look pretty when printed, so they are
+ unsuitable for Lisp objects that can be exposed to users.
+
+ To define a new data type, add one more Lisp_Misc subtype or one
+ more pseudovector subtype. Pseudovectors are more suitable for
+ objects with several slots that need to support fast random access,
+ while Lisp_Misc types are for everything else. A pseudovector object
+ provides one or more slots for Lisp objects, followed by struct
+ members that are accessible only from C. A Lisp_Misc object is a
+ wrapper for a C struct that can contain anything you like.
+
+ To add a new pseudovector type, extend the pvec_type enumeration;
+ to add a new Lisp_Misc, extend the Lisp_Misc_Type enumeration.
+
+ For a Lisp_Misc, you will also need to add your entry to union
+ Lisp_Misc (but make sure the first word has the same structure as
+ the others, starting with a 16-bit member of the Lisp_Misc_Type
+ enumeration and a 1-bit GC markbit) and make sure the overall size
+ of the union is not increased by your addition.
+
+ Then you will need to add switch branches in print.c (in
+ print_object, to print your object, and possibly also in
+ print_preprocess) and to alloc.c, to mark your object (in
+ mark_object) and to free it (in gc_sweep). The latter is also the
+ right place to call any code specific to your data type that needs
+ to run when the object is recycled -- e.g., free any additional
+ resources allocated for it that are not Lisp objects. You can even
+ make a pointer to the function that frees the resources a slot in
+ your object -- this way, the same object could be used to represent
+ several disparate C structures. */
+
#ifdef CHECK_LISP_OBJECT_TYPE
typedef struct { EMACS_INT i; } Lisp_Object;
@@ -327,7 +376,7 @@ enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = 1 };
typedef EMACS_INT Lisp_Object;
#define XLI(o) (o)
#define XIL(i) (i)
-#define LISP_MAKE_RVALUE(o) (0+(o))
+#define LISP_MAKE_RVALUE(o) (0 + (o))
#define LISP_INITIALLY_ZERO 0
enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = 0 };
#endif /* CHECK_LISP_OBJECT_TYPE */
@@ -345,15 +394,11 @@ static ptrdiff_t const PSEUDOVECTOR_FLAG
= PSEUDOVECTOR_FLAG;
/* In a pseudovector, the size field actually contains a word with one
- PSEUDOVECTOR_FLAG bit set, and exactly one of the following bits to
- indicate the actual type.
- We use a bitset, even tho only one of the bits can be set at any
- particular time just so as to be able to use micro-optimizations such as
- testing membership of a particular subset of pseudovectors in Fequal.
- It is not crucial, but there are plenty of bits here, so why not do it? */
+ PSEUDOVECTOR_FLAG bit set, and one of the following values extracted
+ with PVEC_TYPE_MASK to indicate the actual type. */
enum pvec_type
{
- PVEC_NORMAL_VECTOR = 0, /* Unused! */
+ PVEC_NORMAL_VECTOR,
PVEC_FREE,
PVEC_PROCESS,
PVEC_FRAME,
@@ -368,14 +413,11 @@ enum pvec_type
PVEC_THREAD,
PVEC_MUTEX,
PVEC_CONDVAR,
- /* These last 4 are special because we OR them in fns.c:internal_equal,
- so they have to use a disjoint bit pattern:
- if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE
- | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */
- PVEC_COMPILED = 0x10,
- PVEC_CHAR_TABLE = 0x20,
- PVEC_SUB_CHAR_TABLE = 0x30,
- PVEC_FONT = 0x40
+ /* These should be last, check internal_equal to see why. */
+ PVEC_COMPILED,
+ PVEC_CHAR_TABLE,
+ PVEC_SUB_CHAR_TABLE,
+ 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
@@ -395,9 +437,18 @@ enum More_Lisp_Bits
only the number of Lisp_Object fields (that need to be traced by GC).
The distinction is used, e.g., by Lisp_Process, which places extra
non-Lisp_Object fields at the end of the structure. */
- PSEUDOVECTOR_SIZE_BITS = 16,
+ PSEUDOVECTOR_SIZE_BITS = 12,
PSEUDOVECTOR_SIZE_MASK = (1 << PSEUDOVECTOR_SIZE_BITS) - 1,
- PVEC_TYPE_MASK = 0x0fff << PSEUDOVECTOR_SIZE_BITS,
+
+ /* To calculate the memory footprint of the pseudovector, it's useful
+ to store the size of non-Lisp area in word_size units here. */
+ PSEUDOVECTOR_REST_BITS = 12,
+ PSEUDOVECTOR_REST_MASK = (((1 << PSEUDOVECTOR_REST_BITS) - 1)
+ << PSEUDOVECTOR_SIZE_BITS),
+
+ /* Used to extract pseudovector subtype information. */
+ PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS,
+ PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS,
/* Number of bits to put in each character in the internal representation
of bool vectors. This should not vary across implementations. */
@@ -408,9 +459,6 @@ enum More_Lisp_Bits
For example, if tem is a Lisp_Object whose type is Lisp_Cons,
XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons. */
-/* Return a perfect hash of the Lisp_Object representation. */
-#define XHASH(a) XLI (a)
-
#if USE_LSB_TAG
enum lsb_bits
@@ -422,9 +470,9 @@ enum lsb_bits
#define XINT(a) (XLI (a) >> INTTYPEBITS)
#define XUINT(a) ((EMACS_UINT) XLI (a) >> INTTYPEBITS)
#define make_number(N) XIL ((EMACS_INT) (N) << INTTYPEBITS)
-#define XSET(var, type, ptr) \
+#define make_lisp_ptr(ptr, type) \
(eassert (XTYPE (XIL ((intptr_t) (ptr))) == 0), /* Check alignment. */ \
- (var) = XIL ((type) | (intptr_t) (ptr)))
+ XIL ((type) | (intptr_t) (ptr)))
#define XPNTR(a) ((intptr_t) (XLI (a) & ~TYPEMASK))
#define XUNTAG(a, type) ((intptr_t) (XLI (a) - (type)))
@@ -449,13 +497,13 @@ static EMACS_INT const VALMASK
#define XUINT(a) ((EMACS_UINT) (XLI (a) & INTMASK))
#define make_number(N) XIL ((EMACS_INT) (N) & INTMASK)
-#define XSET(var, type, ptr) \
- ((var) = XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \
- + ((intptr_t) (ptr) & VALMASK)))
+#define make_lisp_ptr(ptr, type) \
+ (XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \
+ + ((intptr_t) (ptr) & VALMASK)))
#if DATA_SEG_BITS
/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
- which were stored in a Lisp_Object */
+ which were stored in a Lisp_Object. */
#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK)) | DATA_SEG_BITS))
#else
#define XPNTR(a) ((uintptr_t) (XLI (a) & VALMASK))
@@ -463,6 +511,11 @@ static EMACS_INT const VALMASK
#endif /* not USE_LSB_TAG */
+/* Return a (Lisp-integer sized) hash of the Lisp_Object value. Happens to be
+ like XUINT right now, but XUINT should only be applied to objects we know
+ are integers. */
+#define XHASH(a) XUINT (a)
+
/* For integers known to be positive, XFASTINT sometimes provides
faster retrieval and XSETFASTINT provides faster storage.
If not, fallback on the non-accelerated path. */
@@ -478,17 +531,12 @@ static EMACS_INT const VALMASK
# define XUNTAG(a, type) XPNTR (a)
#endif
-#define EQ(x, y) (XHASH (x) == XHASH (y))
+#define EQ(x, y) (XLI (x) == XLI (y))
/* Largest and smallest representable fixnum values. These are the C
- values. They are macros for use in static initializers, and
- constants for visibility to GDB. */
-static EMACS_INT const MOST_POSITIVE_FIXNUM =
+ values. They are macros for use in static initializers. */
#define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS)
- MOST_POSITIVE_FIXNUM;
-static EMACS_INT const MOST_NEGATIVE_FIXNUM =
#define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
- MOST_NEGATIVE_FIXNUM;
/* Value is non-zero if I doesn't fit into a Lisp fixnum. It is
written this way so that it also works if I is of unsigned
@@ -562,27 +610,27 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
/* Construct a Lisp_Object from a value or address. */
-#define XSETINT(a, b) (a) = make_number (b)
-#define XSETCONS(a, b) XSET (a, Lisp_Cons, b)
-#define XSETVECTOR(a, b) XSET (a, Lisp_Vectorlike, b)
-#define XSETSTRING(a, b) XSET (a, Lisp_String, b)
-#define XSETSYMBOL(a, b) XSET (a, Lisp_Symbol, b)
-#define XSETFLOAT(a, b) XSET (a, Lisp_Float, b)
+#define XSETINT(a, b) ((a) = make_number (b))
+#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 XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float))
/* Misc types. */
-#define XSETMISC(a, b) XSET (a, Lisp_Misc, b)
+#define XSETMISC(a, b) ((a) = make_lisp_ptr (b, Lisp_Misc))
#define XSETMARKER(a, b) (XSETMISC (a, b), XMISCTYPE (a) = Lisp_Misc_Marker)
/* Pseudovector types. */
-#define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code)
-#define XSETTYPED_PVECTYPE(v, size_member, code) \
- ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))
-#define XSETPVECTYPESIZE(v, code, sizeval) \
+#define XSETPVECTYPE(v, code) \
+ ((v)->header.size |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))
+#define XSETPVECTYPESIZE(v, code, lispsize, restsize) \
((v)->header.size = (PSEUDOVECTOR_FLAG \
- | ((code) << PSEUDOVECTOR_SIZE_BITS) \
- | (sizeval)))
+ | ((code) << PSEUDOVECTOR_AREA_BITS) \
+ | ((restsize) << PSEUDOVECTOR_SIZE_BITS) \
+ | (lispsize)))
/* The cast to struct vectorlike_header * avoids aliasing issues. */
#define XSETPSEUDOVECTOR(a, b, code) \
@@ -594,16 +642,14 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
#define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \
(XSETVECTOR (a, b), \
eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
- == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS))))
+ == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS))))
#define XSETWINDOW_CONFIGURATION(a, b) \
(XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
#define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
#define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
-/* XSETSUBR is special since Lisp_Subr lacks struct vectorlike_header. */
-#define XSETSUBR(a, b) \
- XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR)
+#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
#define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
@@ -773,7 +819,7 @@ struct Lisp_String
};
/* Header of vector-like objects. This documents the layout constraints on
- vectors and pseudovectors other than struct Lisp_Subr. It also prevents
+ vectors and pseudovectors (objects of PVEC_xxx subtype). It also prevents
compilers from being fooled by Emacs's type punning: the XSETPSEUDOVECTOR
and PSEUDOVECTORP macros cast their pointers to struct vectorlike_header *,
because when two such pointers potentially alias, a compiler won't
@@ -781,43 +827,26 @@ struct Lisp_String
<http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */
struct vectorlike_header
{
- /* This field contains various pieces of information:
+ /* The only field contains various pieces of information:
- The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit.
- The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain
vector (0) or a pseudovector (1).
- If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number
of slots) of the vector.
- - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into
- a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest
- PSEUDOVECTOR_SIZE_BITS. That size normally indicates the number of
- Lisp_Object slots at the beginning of the object that need to be
- traced by the GC, tho some types use it slightly differently.
- - E.g. if the pvec type is PVEC_FREE it means this is an unallocated
- vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size
- in bytes. */
+ - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into three fields:
+ - a) pseudovector subtype held in PVEC_TYPE_MASK field;
+ - b) number of Lisp_Objects slots at the beginning of the object
+ held in PSEUDOVECTOR_SIZE_MASK field. These objects are always
+ traced by the GC;
+ - c) size of the rest fields held in PSEUDOVECTOR_REST_MASK and
+ measured in word_size units. Rest fields may also include
+ Lisp_Objects, but these objects usually needs some special treatment
+ during GC.
+ There are some exceptions. For PVEC_FREE, b) is always zero. For
+ PVEC_BOOL_VECTOR and PVEC_SUBR, both b) and c) are always zero.
+ Current layout limits the pseudovectors to 63 PVEC_xxx subtypes,
+ 4095 Lisp_Objects in GC-ed area and 4095 word-sized other slots. */
ptrdiff_t size;
-
- /* When the vector is allocated from a vector block, NBYTES is used
- if the vector is not on a free list, and VECTOR is used otherwise.
- For large vector-like objects, BUFFER or VECTOR is used as a pointer
- to the next vector-like object. It is generally a buffer or a
- Lisp_Vector alias, so for convenience it is a union instead of a
- pointer: this way, one can write P->next.vector instead of ((struct
- Lisp_Vector *) P->next). */
- union {
- /* This is only needed for small vectors that are not free because the
- `size' field only gives us the number of Lisp_Object slots, whereas we
- need to know the total size, including non-Lisp_Object data.
- FIXME: figure out a way to store this info elsewhere so we can
- finally get rid of this extra word of overhead. */
- ptrdiff_t nbytes;
- struct buffer *buffer;
- /* FIXME: This can be removed: For large vectors, this field could be
- placed *before* the vector itself. And for small vectors on a free
- list, this field could be stored in the vector's bytes, since the
- empty vector is handled specially anyway. */
- struct Lisp_Vector *vector;
- } next;
};
/* Regular vector is just a header plus array of Lisp_Objects. */
@@ -920,14 +949,6 @@ enum
(ASCII_CHAR_P (IDX) ? CHAR_TABLE_REF_ASCII ((CT), (IDX)) \
: char_table_ref ((CT), (IDX)))
-/* Almost equivalent to Faref (CT, IDX). However, if the result is
- not a character, return IDX.
-
- For these characters, do not check validity of CT
- and do not follow parent. */
-#define CHAR_TABLE_TRANSLATE(CT, IDX) \
- char_table_translate (CT, IDX)
-
/* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
8-bit European characters. Do not check validity of CT. */
#define CHAR_TABLE_SET(CT, IDX, VAL) \
@@ -999,15 +1020,11 @@ struct Lisp_Sub_Char_Table
/* This structure describes a built-in function.
It is generated by the DEFUN macro only.
- defsubr makes it into a Lisp object.
-
- This type is treated in most respects as a pseudovector,
- but since we never dynamically allocate or free them,
- we don't need a struct vectorlike_header and its 'next' field. */
+ defsubr makes it into a Lisp object. */
struct Lisp_Subr
{
- ptrdiff_t size;
+ struct vectorlike_header header;
union {
Lisp_Object (*a0) (void);
Lisp_Object (*a1) (Lisp_Object);
@@ -1098,7 +1115,7 @@ struct Lisp_Symbol
union Lisp_Fwd *fwd;
} val;
- /* Function value of the symbol or Qunbound if not fboundp. */
+ /* Function value of the symbol or Qnil if not fboundp. */
Lisp_Object function;
/* The symbol's property list. */
@@ -1155,14 +1172,29 @@ struct Lisp_Symbol
/* The structure of a Lisp hash table. */
+struct hash_table_test
+{
+ /* Name of the function used to compare keys. */
+ Lisp_Object name;
+
+ /* User-supplied hash function, or nil. */
+ Lisp_Object user_hash_function;
+
+ /* User-supplied key comparison function, or nil. */
+ Lisp_Object user_cmp_function;
+
+ /* C function to compare two keys. */
+ bool (*cmpfn) (struct hash_table_test *t, Lisp_Object, Lisp_Object);
+
+ /* C function to compute hash code. */
+ EMACS_UINT (*hashfn) (struct hash_table_test *t, Lisp_Object);
+};
+
struct Lisp_Hash_Table
{
/* This is for Lisp; the hash table code does not refer to it. */
struct vectorlike_header header;
- /* Function used to compare keys. */
- Lisp_Object test;
-
/* Nil if table is non-weak. Otherwise a symbol describing the
weakness of the table. */
Lisp_Object weak;
@@ -1193,12 +1225,6 @@ struct Lisp_Hash_Table
hash table size to reduce collisions. */
Lisp_Object index;
- /* User-supplied hash function, or nil. */
- Lisp_Object user_hash_function;
-
- /* User-supplied key comparison function, or nil. */
- Lisp_Object user_cmp_function;
-
/* Only the fields above are traced normally by the GC. The ones below
`count' are special and are either ignored by the GC or traced in
a special way (e.g. because of weakness). */
@@ -1211,17 +1237,12 @@ struct Lisp_Hash_Table
This is gc_marked specially if the table is weak. */
Lisp_Object key_and_value;
+ /* The comparison and hash functions. */
+ struct hash_table_test test;
+
/* Next weak hash table if this is a weak hash table. The head
of the list is in weak_hash_tables. */
struct Lisp_Hash_Table *next_weak;
-
- /* C function to compare two keys. */
- int (*cmpfn) (struct Lisp_Hash_Table *,
- Lisp_Object, EMACS_UINT,
- Lisp_Object, EMACS_UINT);
-
- /* C function to compute hash code. */
- EMACS_UINT (*hashfn) (struct Lisp_Hash_Table *, Lisp_Object);
};
@@ -1276,6 +1297,15 @@ static double const DEFAULT_REHASH_THRESHOLD = 0.8;
static double const DEFAULT_REHASH_SIZE = 1.5;
+/* Combine two integers X and Y for hashing. The result might not fit
+ into a Lisp integer. */
+
+LISP_INLINE EMACS_UINT
+sxhash_combine (EMACS_UINT x, EMACS_UINT y)
+{
+ return (x << 4) + (x >> (BITS_PER_EMACS_INT - 4)) + y;
+}
+
/* These structures are used for various misc types. */
struct Lisp_Misc_Any /* Supertype of all Misc types. */
@@ -1505,6 +1535,16 @@ struct Lisp_Float
#define XFLOAT_DATA(f) (0 ? XFLOAT (f)->u.data : XFLOAT (f)->u.data)
#define XFLOAT_INIT(f, n) (XFLOAT (f)->u.data = (n))
+/* Most hosts nowadays use IEEE floating point, so they use IEC 60559
+ representations, have infinities and NaNs, and do not trap on
+ exceptions. Define IEEE_FLOATING_POINT if this host is one of the
+ typical ones. The C11 macro __STDC_IEC_559__ is close to what is
+ wanted here, but is not quite right because Emacs does not require
+ all the features of C11 Annex F (and does not require C11 at all,
+ for that matter). */
+#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
+ && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
+
/* A character, declared with the following typedef, is a member
of some character set associated with the current buffer. */
#ifndef _UCHAR_T /* Protect against something in ctab.h on AIX. */
@@ -1615,30 +1655,27 @@ typedef struct {
int mouse_face_beg_x, mouse_face_beg_y;
int mouse_face_end_row, mouse_face_end_col;
int mouse_face_end_x, mouse_face_end_y;
- int mouse_face_past_end;
Lisp_Object mouse_face_window;
int mouse_face_face_id;
Lisp_Object mouse_face_overlay;
- /* 1 if a mouse motion event came and we didn't handle it right away because
- gc was in progress. */
- int mouse_face_deferred_gc;
-
/* FRAME and X, Y position of mouse when last checked for
highlighting. X and Y can be negative or out of range for the frame. */
struct frame *mouse_face_mouse_frame;
int mouse_face_mouse_x, mouse_face_mouse_y;
+ /* Nonzero if part of the text currently shown in
+ its mouse-face is beyond the window end. */
+ unsigned mouse_face_past_end : 1;
+
/* Nonzero means defer mouse-motion highlighting. */
- int mouse_face_defer;
+ unsigned mouse_face_defer : 1;
/* Nonzero means that the mouse highlight should not be shown. */
- int mouse_face_hidden;
-
- int mouse_face_image_state;
+ unsigned mouse_face_hidden : 1;
} Mouse_HLInfo;
-/* Data type checking */
+/* Data type checking. */
#define NILP(x) EQ (x, Qnil)
@@ -1665,6 +1702,8 @@ typedef struct {
#define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
#define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value)
+#define AUTOLOADP(x) (CONSP (x) && EQ (Qautoload, XCAR (x)))
+
#define INTFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Int)
#define BOOLFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Bool)
#define OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Obj)
@@ -1678,7 +1717,7 @@ typedef struct {
#define PSEUDOVECTOR_TYPEP(v, code) \
(((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
- == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)))
+ == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS)))
/* True if object X, with internal type struct T *, is a pseudovector whose
code is CODE. */
@@ -1691,8 +1730,7 @@ typedef struct {
#define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
#define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
#define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
-/* SUBRP is special since Lisp_Subr lacks struct vectorlike_header. */
-#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
+#define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
#define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
#define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
#define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
@@ -1756,20 +1794,6 @@ typedef struct {
#define CHECK_WINDOW_CONFIGURATION(x) \
CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x)
-/* A window of any sort, leaf or interior, is "valid" if one of its
- buffer, vchild, or hchild members is non-nil. */
-#define CHECK_VALID_WINDOW(x) \
- CHECK_TYPE (WINDOWP (x) \
- && (!NILP (XWINDOW (x)->buffer) \
- || !NILP (XWINDOW (x)->vchild) \
- || !NILP (XWINDOW (x)->hchild)), \
- Qwindow_valid_p, x)
-
-/* A window is "live" if and only if it shows a buffer. */
-#define CHECK_LIVE_WINDOW(x) \
- CHECK_TYPE (WINDOWP (x) && !NILP (XWINDOW (x)->buffer), \
- Qwindow_live_p, x)
-
#define CHECK_PROCESS(x) \
CHECK_TYPE (PROCESSP (x), Qprocessp, x)
@@ -1893,8 +1917,8 @@ typedef struct {
#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_SIZE_BITS) \
- | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \
+ { { (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) \
+ | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)) }, \
{ (Lisp_Object (__cdecl *)(void))fnname }, \
minargs, maxargs, lname, intspec, 0}; \
Lisp_Object fnname
@@ -1902,8 +1926,8 @@ typedef struct {
#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_SIZE_BITS, \
- { .a ## maxargs = fnname }, \
+ { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \
+ { .a ## maxargs = fnname }, \
minargs, maxargs, lname, intspec, 0}; \
Lisp_Object fnname
#endif
@@ -1994,7 +2018,25 @@ extern void defvar_kboard (struct Lisp_Kboard_Objfwd *, const char *, int);
static struct Lisp_Kboard_Objfwd ko_fwd; \
defvar_kboard (&ko_fwd, lname, offsetof (KBOARD, vname ## _)); \
} while (0)
-
+
+/* Save and restore the instruction and environment pointers,
+ without affecting the signal mask. */
+
+#ifdef HAVE__SETJMP
+typedef jmp_buf sys_jmp_buf;
+# define sys_setjmp(j) _setjmp (j)
+# define sys_longjmp(j, v) _longjmp (j, v)
+#elif defined HAVE_SIGSETJMP
+typedef sigjmp_buf sys_jmp_buf;
+# define sys_setjmp(j) sigsetjmp (j, 0)
+# define sys_longjmp(j, v) siglongjmp (j, v)
+#else
+/* A platform that uses neither _longjmp nor siglongjmp; assume
+ longjmp does not affect the sigmask. */
+typedef jmp_buf sys_jmp_buf;
+# define sys_setjmp(j) setjmp (j)
+# define sys_longjmp(j, v) longjmp (j, v)
+#endif
/* Structure for recording Lisp call stack for backtrace purposes. */
@@ -2030,7 +2072,22 @@ struct specbinding
#define SPECPDL_INDEX() (specpdl_ptr - specpdl)
-/* Everything needed to describe an active condition case. */
+struct backtrace
+{
+ struct backtrace *next;
+ Lisp_Object function;
+ Lisp_Object *args; /* Points to vector of args. */
+ ptrdiff_t nargs; /* Length of vector. */
+ /* Nonzero means call value of debugger when done with this operation. */
+ unsigned int debug_on_exit : 1;
+};
+
+extern struct backtrace *backtrace_list;
+
+/* Everything needed to describe an active condition case.
+
+ Members are volatile if their values need to survive _longjmp when
+ a 'struct handler' is a local variable. */
struct handler
{
/* The handler clauses and variable from the condition-case form. */
@@ -2041,10 +2098,12 @@ struct handler
error: handle all conditions, and errors can run the debugger
or display a backtrace. */
Lisp_Object handler;
- Lisp_Object var;
+
+ Lisp_Object volatile var;
+
/* Fsignal stores here the condition-case clause that applies,
and Fcondition_case thus knows which clause to run. */
- Lisp_Object chosen_clause;
+ Lisp_Object volatile chosen_clause;
/* Used to effect the longjump out to the handler. */
struct catchtag *tag;
@@ -2070,19 +2129,21 @@ struct handler
of the catch form.
All the other members are concerned with restoring the interpreter
- state. */
+ state.
+ Members are volatile if their values need to survive _longjmp when
+ a 'struct catchtag' is a local variable. */
struct catchtag
{
Lisp_Object tag;
- Lisp_Object val;
- struct catchtag *next;
+ Lisp_Object volatile val;
+ struct catchtag *volatile next;
struct gcpro *gcpro;
- jmp_buf jmp;
+ sys_jmp_buf jmp;
struct backtrace *backlist;
struct handler *f_handlerlist;
EMACS_INT f_lisp_eval_depth;
- ptrdiff_t pdlcount;
+ ptrdiff_t volatile pdlcount;
int poll_suppress_count;
int interrupt_input_blocked;
struct byte_stack *byte_stack;
@@ -2106,22 +2167,16 @@ extern Lisp_Object memory_signal_data;
If quit-flag is set to `kill-emacs' the SIGINT handler has received
a request to exit Emacs when it is safe to do. */
-#ifdef SYNC_INPUT
extern void process_pending_signals (void);
-extern int pending_signals;
-#define ELSE_PENDING_SIGNALS \
- else if (pending_signals) \
- process_pending_signals ();
-#else /* not SYNC_INPUT */
-#define ELSE_PENDING_SIGNALS
-#endif /* not SYNC_INPUT */
+extern bool volatile pending_signals;
extern void process_quit_flag (void);
#define QUIT \
do { \
if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
process_quit_flag (); \
- ELSE_PENDING_SIGNALS \
+ else if (pending_signals) \
+ process_pending_signals (); \
} while (0)
@@ -2301,7 +2356,7 @@ struct gcpro
#define UNGCPRO \
((--gcpro_level != gcpro1.level) \
- ? (abort (), 0) \
+ ? (emacs_abort (), 0) \
: ((gcprolist = gcpro1.next), 0))
#endif /* DEBUG_GCPRO */
@@ -2581,8 +2636,7 @@ extern Lisp_Object Qthreadp, Qmutexp, Qcondition_variablep;
extern Lisp_Object Qcdr;
-extern Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
-extern Lisp_Object Qoverflow_error, Qunderflow_error;
+extern Lisp_Object Qrange_error, Qoverflow_error;
extern Lisp_Object Qfloatp;
extern Lisp_Object Qnumberp, Qnumber_or_marker_p;
@@ -2593,10 +2647,7 @@ extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST;
-/* Defined in frame.c */
-extern Lisp_Object Qframep;
-
-/* Defined in data.c */
+/* Defined in data.c. */
extern Lisp_Object indirect_function (Lisp_Object);
extern Lisp_Object find_symbol_value (Lisp_Object);
@@ -2636,14 +2687,13 @@ 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);
-extern void init_data (void);
extern void swap_in_global_binding (struct Lisp_Symbol *);
/* Defined in cmds.c */
extern void syms_of_cmds (void);
extern void keys_of_cmds (void);
-/* Defined in coding.c */
+/* 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);
@@ -2651,7 +2701,7 @@ extern void init_coding (void);
extern void init_coding_once (void);
extern void syms_of_coding (void);
-/* Defined in character.c */
+/* 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);
@@ -2659,21 +2709,21 @@ 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 */
+/* Defined in charset.c. */
extern void init_charset (void);
extern void init_charset_once (void);
extern void syms_of_charset (void);
/* Structure forward declarations. */
struct charset;
-/* Defined in composite.c */
+/* Defined in composite.c. */
extern void syms_of_composite (void);
-/* Defined in syntax.c */
+/* Defined in syntax.c. */
extern void init_syntax_once (void);
extern void syms_of_syntax (void);
-/* Defined in fns.c */
+/* Defined in fns.c. */
extern Lisp_Object QCrehash_size, QCrehash_threshold;
enum { NEXT_ALMOST_PRIME_LIMIT = 11 };
EXFUN (Fidentity, 1) ATTRIBUTE_CONST;
@@ -2682,15 +2732,15 @@ 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, Qeql;
+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 (Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object);
+Lisp_Object make_hash_table (struct hash_table_test, Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object);
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 Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t);
@@ -2707,13 +2757,12 @@ extern Lisp_Object string_to_multibyte (Lisp_Object);
extern Lisp_Object string_make_unibyte (Lisp_Object);
extern void syms_of_fns (void);
-/* Defined in floatfns.c */
+/* Defined in floatfns.c. */
extern double extract_float (Lisp_Object);
-extern void init_floatfns (void);
extern void syms_of_floatfns (void);
extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y);
-/* Defined in fringe.c */
+/* Defined in fringe.c. */
extern void syms_of_fringe (void);
extern void init_fringe (void);
#ifdef HAVE_WINDOW_SYSTEM
@@ -2721,13 +2770,14 @@ extern void mark_fringe_data (void);
extern void init_fringe_once (void);
#endif /* HAVE_WINDOW_SYSTEM */
-/* Defined in image.c */
+/* 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 */
+/* Defined in insdel.c. */
extern Lisp_Object Qinhibit_modification_hooks;
extern void move_gap (ptrdiff_t);
extern void move_gap_both (ptrdiff_t, ptrdiff_t);
@@ -2761,7 +2811,7 @@ extern void del_range_byte (ptrdiff_t, ptrdiff_t, bool);
extern void del_range_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool);
extern Lisp_Object del_range_2 (ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t, bool);
-extern void modify_region (struct buffer *, ptrdiff_t, ptrdiff_t, bool);
+extern void modify_region_1 (ptrdiff_t, ptrdiff_t, bool);
extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
extern void signal_after_change (ptrdiff_t, ptrdiff_t, ptrdiff_t);
extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t,
@@ -2773,7 +2823,7 @@ extern void replace_range_2 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
const char *, ptrdiff_t, ptrdiff_t, bool);
extern void syms_of_insdel (void);
-/* Defined in dispnew.c */
+/* Defined in dispnew.c. */
#if (defined PROFILING \
&& (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__))
_Noreturn void __executable_start (void);
@@ -2784,7 +2834,7 @@ extern Lisp_Object sit_for (Lisp_Object, bool, int);
extern void init_display (void);
extern void syms_of_display (void);
-/* Defined in xdisp.c */
+/* Defined in xdisp.c. */
extern Lisp_Object Qinhibit_point_motion_hooks;
extern Lisp_Object Qinhibit_redisplay, Qdisplay;
extern Lisp_Object Qmenu_bar_update_hook;
@@ -2835,17 +2885,15 @@ extern Lisp_Object safe_eval (Lisp_Object);
extern int pos_visible_p (struct window *, ptrdiff_t, int *,
int *, int *, int *, int *, int *);
-/* Defined in xsettings.c */
+/* Defined in xsettings.c. */
extern void syms_of_xsettings (void);
/* Defined in vm-limit.c. */
extern void memory_warnings (void *, void (*warnfun) (const char *));
-/* Defined in alloc.c */
+/* Defined in alloc.c. */
extern void check_pure_size (void);
extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
-extern void reset_malloc_hooks (void);
-extern void uninterrupt_malloc (void);
extern void malloc_warning (const char *);
extern _Noreturn void memory_full (size_t);
extern _Noreturn void buffer_memory_full (ptrdiff_t);
@@ -2914,9 +2962,10 @@ 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);
-extern struct Lisp_Vector *allocate_pseudovector (int memlen, int lisplen, int tag);
+extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type);
#define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \
((typ*) \
allocate_pseudovector \
@@ -2932,6 +2981,7 @@ extern Lisp_Object make_float (double);
extern void display_malloc_warning (void);
extern ptrdiff_t inhibit_garbage_collection (void);
extern Lisp_Object make_save_value (void *, ptrdiff_t);
+extern void free_save_value (Lisp_Object);
extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
extern void free_marker (Lisp_Object);
extern void free_cons (struct Lisp_Cons *);
@@ -2947,7 +2997,7 @@ extern void check_cons_list (void);
#endif
#ifdef REL_ALLOC
-/* Defined in ralloc.c */
+/* Defined in ralloc.c. */
extern void *r_alloc (void **, size_t);
extern void r_alloc_free (void **);
extern void *r_re_alloc (void **, size_t);
@@ -2955,7 +3005,7 @@ extern void r_alloc_reset_variable (void **, void **);
extern void r_alloc_inhibit_buffer_relocation (int);
#endif
-/* Defined in chartab.c */
+/* 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,
@@ -2973,7 +3023,7 @@ extern void map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Ob
extern Lisp_Object uniprop_table (Lisp_Object);
extern void syms_of_chartab (void);
-/* Defined in print.c */
+/* Defined in print.c. */
extern Lisp_Object Vprin1_to_string_buffer;
extern void debug_print (Lisp_Object) EXTERNALLY_VISIBLE;
extern Lisp_Object Qstandard_output;
@@ -2990,7 +3040,7 @@ enum FLOAT_TO_STRING_BUFSIZE { FLOAT_TO_STRING_BUFSIZE = 350 };
extern int float_to_string (char *, double);
extern void syms_of_print (void);
-/* Defined in doprnt.c */
+/* Defined in doprnt.c. */
extern ptrdiff_t doprnt (char *, ptrdiff_t, const char *, const char *,
va_list);
extern ptrdiff_t esprintf (char *, char const *, ...)
@@ -3016,7 +3066,7 @@ extern Lisp_Object oblookup (Lisp_Object, const char *, ptrdiff_t, ptrdiff_t);
} while (0)
extern int openp (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object *, Lisp_Object);
-Lisp_Object string_to_number (char const *, int, int);
+extern Lisp_Object string_to_number (char const *, int, bool);
extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
Lisp_Object);
extern void dir_warning (const char *, Lisp_Object);
@@ -3095,6 +3145,7 @@ extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
extern _Noreturn void verror (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
extern Lisp_Object un_autoload (Lisp_Object);
+extern Lisp_Object call_debugger (Lisp_Object arg);
extern void init_eval_once (void);
extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
@@ -3118,7 +3169,6 @@ extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
ptrdiff_t, bool);
extern void init_editfns (void);
-const char *get_system_name (void);
extern void syms_of_editfns (void);
extern void set_time_zone_rule (const char *);
@@ -3157,7 +3207,7 @@ extern Lisp_Object set_marker_restricted_both (Lisp_Object, Lisp_Object,
extern Lisp_Object build_marker (struct buffer *, ptrdiff_t, ptrdiff_t);
extern void syms_of_marker (void);
-/* Defined in fileio.c */
+/* Defined in fileio.c. */
extern Lisp_Object Qfile_error;
extern Lisp_Object Qfile_exists_p;
@@ -3165,16 +3215,19 @@ 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);
-EXFUN (Fread_file_name, 6); /* not a normal DEFUN */
+EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */
extern Lisp_Object close_file_unwind (Lisp_Object);
extern Lisp_Object restore_point_unwind (Lisp_Object);
extern _Noreturn void report_file_error (const char *, Lisp_Object);
-extern int internal_delete_file (Lisp_Object);
+extern bool internal_delete_file (Lisp_Object);
+extern bool file_directory_p (const char *);
+extern bool file_accessible_directory_p (const char *);
extern void syms_of_fileio (void);
-extern Lisp_Object make_temp_name (Lisp_Object, int);
+extern Lisp_Object make_temp_name (Lisp_Object, bool);
extern Lisp_Object Qdelete_file;
+extern bool check_existing (const char *);
-/* Defined in search.c */
+/* Defined in search.c. */
extern void shrink_regexp_cache (void);
extern void restore_search_regs (void);
extern void record_unwind_save_match_data (void);
@@ -3189,9 +3242,9 @@ 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 scan_buffer (int, ptrdiff_t, ptrdiff_t, ptrdiff_t,
- ptrdiff_t *, int);
+ ptrdiff_t *, bool);
extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
- EMACS_INT, int);
+ EMACS_INT, bool);
extern ptrdiff_t find_next_newline (ptrdiff_t, int);
extern ptrdiff_t find_next_newline_no_quit (ptrdiff_t, ptrdiff_t);
extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t);
@@ -3234,22 +3287,23 @@ extern Lisp_Object Qdisabled, QCfilter;
extern Lisp_Object Qup, Qdown, Qbottom;
extern Lisp_Object Qtop;
extern Lisp_Object last_undo_boundary;
-extern int input_pending;
+extern bool input_pending;
extern Lisp_Object menu_bar_items (Lisp_Object);
extern Lisp_Object tool_bar_items (Lisp_Object, int *);
extern void discard_mouse_events (void);
+#ifdef USABLE_SIGIO
+void handle_input_available_signal (int);
+#endif
extern Lisp_Object pending_funcalls;
-extern int detect_input_pending (void);
-extern int detect_input_pending_ignore_squeezables (void);
-extern int detect_input_pending_run_timers (int);
+extern bool detect_input_pending (void);
+extern bool detect_input_pending_ignore_squeezables (void);
+extern bool detect_input_pending_run_timers (bool);
extern void safe_run_hooks (Lisp_Object);
extern void cmd_error_internal (Lisp_Object, const char *);
extern Lisp_Object command_loop_1 (void);
extern Lisp_Object recursive_edit_1 (void);
extern void record_auto_save (void);
-#ifdef SIGDANGER
extern void force_auto_save_soon (void);
-#endif
extern void init_keyboard (void);
extern void syms_of_keyboard (void);
extern void keys_of_keyboard (void);
@@ -3257,7 +3311,7 @@ extern void keys_of_keyboard (void);
/* Defined in indent.c. */
extern ptrdiff_t current_column (void);
extern void invalidate_current_column (void);
-extern int indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
+extern bool indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
extern void syms_of_indent (void);
/* Defined in frame.c. */
@@ -3269,7 +3323,6 @@ extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
#if HAVE_NS
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
#endif
-extern Lisp_Object frame_buffer_predicate (Lisp_Object);
extern void frames_discard_buffer (Lisp_Object);
extern void syms_of_frame (void);
@@ -3282,10 +3335,11 @@ extern bool display_arg;
extern Lisp_Object decode_env_path (const char *, const char *);
extern Lisp_Object empty_unibyte_string, empty_multibyte_string;
extern Lisp_Object Qfile_name_handler_alist;
-#ifdef FLOAT_CATCH_SIGILL
-extern void fatal_error_signal (int);
-#endif
+extern _Noreturn void terminate_due_to_signal (int, int);
extern Lisp_Object Qkill_emacs;
+#ifdef WINDOWSNT
+extern Lisp_Object Vlibrary_cache;
+#endif
#if HAVE_SETLOCALE
void fixup_locale (void);
void synchronize_system_messages_locale (void);
@@ -3321,7 +3375,7 @@ extern bool running_asynch_code;
extern Lisp_Object QCtype, Qlocal;
extern Lisp_Object Qprocessp;
extern void kill_buffer_processes (Lisp_Object);
-extern int wait_reading_process_output (intmax_t, int, int, int,
+extern int wait_reading_process_output (intmax_t, int, int, bool,
Lisp_Object,
struct Lisp_Process *,
int);
@@ -3353,15 +3407,14 @@ extern void init_callproc (void);
extern void set_initial_environment (void);
extern void syms_of_callproc (void);
-/* Defined in doc.c */
+/* 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);
extern int read_bytecode_char (bool);
-/* Defined in bytecode.c */
-extern Lisp_Object Qbytecode;
+/* Defined in bytecode.c. */
extern void syms_of_bytecode (void);
#if BYTE_MARK_STACK
extern void mark_byte_stack (struct byte_stack *);
@@ -3370,12 +3423,12 @@ extern void unmark_byte_stack (struct byte_stack *);
extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, ptrdiff_t, Lisp_Object *);
-/* Defined in macros.c */
+/* Defined in macros.c. */
extern Lisp_Object Qexecute_kbd_macro;
extern void init_macros (void);
extern void syms_of_macros (void);
-/* Defined in undo.c */
+/* Defined in undo.c. */
extern Lisp_Object Qapply;
extern Lisp_Object Qinhibit_read_only;
extern void truncate_undo_list (struct buffer *);
@@ -3388,7 +3441,7 @@ 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 */
+/* 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;
@@ -3396,23 +3449,24 @@ extern Lisp_Object Qminibuffer_prompt;
extern void report_interval_modification (Lisp_Object, Lisp_Object);
-/* Defined in menu.c */
+/* Defined in menu.c. */
extern void syms_of_menu (void);
-/* Defined in xmenu.c */
+/* Defined in xmenu.c. */
extern void syms_of_xmenu (void);
-/* Defined in termchar.h */
+/* Defined in termchar.h. */
struct tty_display_info;
-/* Defined in termhooks.h */
+/* Defined in termhooks.h. */
struct terminal;
-/* Defined in sysdep.c */
+/* Defined in sysdep.c. */
#ifndef HAVE_GET_CURRENT_DIR_NAME
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);
@@ -3421,8 +3475,6 @@ 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);
extern void reset_all_sys_modes (void);
-extern void wait_for_termination (pid_t);
-extern void interruptible_wait_for_termination (pid_t);
extern void flush_pending_output (int) ATTRIBUTE_CONST;
extern void child_setup_tty (int);
extern void setup_pty (int);
@@ -3430,6 +3482,8 @@ extern int set_window_size (int, int, int);
extern EMACS_INT get_random (void);
extern void seed_random (void *, ptrdiff_t);
extern void init_random (void);
+extern void emacs_backtrace (int);
+extern _Noreturn void emacs_abort (void) NO_INLINE;
extern int emacs_open (const char *, int, int);
extern int emacs_close (int);
extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
@@ -3443,45 +3497,55 @@ extern void unlock_file (Lisp_Object);
extern void unlock_buffer (struct buffer *);
extern void syms_of_filelock (void);
-/* Defined in sound.c */
+/* Defined in sound.c. */
extern void syms_of_sound (void);
-/* Defined in category.c */
+/* Defined in category.c. */
extern void init_category_once (void);
extern Lisp_Object char_category_set (int);
extern void syms_of_category (void);
-/* Defined in ccl.c */
+/* Defined in ccl.c. */
extern void syms_of_ccl (void);
-/* Defined in dired.c */
+/* Defined in dired.c. */
extern void syms_of_dired (void);
extern Lisp_Object directory_files_internal (Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object,
bool, Lisp_Object);
-/* Defined in term.c */
+/* Defined in term.c. */
extern int *char_ins_del_vector;
extern void syms_of_term (void);
extern _Noreturn void fatal (const char *msgid, ...)
ATTRIBUTE_FORMAT_PRINTF (1, 2);
-/* Defined in terminal.c */
+/* Defined in terminal.c. */
extern void syms_of_terminal (void);
-/* Defined in font.c */
+/* Defined in font.c. */
extern void syms_of_font (void);
extern void init_font (void);
#ifdef HAVE_WINDOW_SYSTEM
-/* Defined in fontset.c */
+/* Defined in fontset.c. */
extern void syms_of_fontset (void);
-/* Defined in xfns.c, w32fns.c, or macfns.c */
+/* Defined in xfns.c, w32fns.c, or macfns.c. */
extern Lisp_Object Qfont_param;
#endif
-/* Defined in xfaces.c */
+#ifdef WINDOWSNT
+/* Defined on w32notify.c. */
+extern void syms_of_w32notify (void);
+#endif
+
+/* Defined in inotify.c */
+#ifdef HAVE_INOTIFY
+extern void syms_of_inotify (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;
@@ -3497,26 +3561,26 @@ extern Lisp_Object Vface_alternative_font_registry_alist;
extern void syms_of_xfaces (void);
#ifdef HAVE_X_WINDOWS
-/* Defined in xfns.c */
+/* Defined in xfns.c. */
extern void syms_of_xfns (void);
-/* Defined in xsmfns.c */
+/* Defined in xsmfns.c. */
extern void syms_of_xsmfns (void);
-/* Defined in xselect.c */
+/* Defined in xselect.c. */
extern void syms_of_xselect (void);
-/* Defined in xterm.c */
+/* Defined in xterm.c. */
extern void syms_of_xterm (void);
#endif /* HAVE_X_WINDOWS */
#ifdef HAVE_WINDOW_SYSTEM
-/* Defined in xterm.c, nsterm.m, w32term.c */
+/* Defined in xterm.c, nsterm.m, w32term.c. */
extern char *x_get_keysym_name (int);
#endif /* HAVE_WINDOW_SYSTEM */
#ifdef HAVE_LIBXML2
-/* Defined in xml.c */
+/* Defined in xml.c. */
extern void syms_of_xml (void);
extern void xml_cleanup_parser (void);
#endif
@@ -3527,12 +3591,19 @@ extern int have_menus_p (void);
#endif
#ifdef HAVE_DBUS
-/* Defined in dbusbind.c */
+/* Defined in dbusbind.c. */
void syms_of_dbusbind (void);
#endif
+
+/* Defined in profiler.c. */
+extern bool profiler_memory_running;
+extern void malloc_probe (size_t);
+extern void syms_of_profiler (void);
+
+
#ifdef DOS_NT
-/* Defined in msdos.c, w32.c */
+/* Defined in msdos.c, w32.c. */
extern char *emacs_root_dir (void);
#endif /* DOS_NT */
@@ -3540,7 +3611,8 @@ extern char *emacs_root_dir (void);
Used during startup to detect startup of dumped Emacs. */
extern bool initialized;
-extern int immediate_quit; /* Nonzero means ^G can quit instantly */
+/* True means ^G can quit instantly. */
+extern bool immediate_quit;
extern void *xmalloc (size_t);
extern void *xzalloc (size_t);
@@ -3551,6 +3623,7 @@ extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t);
extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t);
extern char *xstrdup (const char *);
+extern void xputenv (const char *);
extern char *egetenv (const char *);
@@ -3570,36 +3643,10 @@ extern void init_system_name (void);
#define make_fixnum_or_float(val) \
(FIXNUM_OVERFLOW_P (val) ? make_float (val) : make_number (val))
-
-/* Checks the `cycle check' variable CHECK to see if it indicates that
- EL is part of a cycle; CHECK must be either Qnil or a value returned
- by an earlier use of CYCLE_CHECK. SUSPICIOUS is the number of
- elements after which a cycle might be suspected; after that many
- elements, this macro begins consing in order to keep more precise
- track of elements.
-
- Returns nil if a cycle was detected, otherwise a new value for CHECK
- that includes EL.
-
- CHECK is evaluated multiple times, EL and SUSPICIOUS 0 or 1 times, so
- the caller should make sure that's ok. */
-
-#define CYCLE_CHECK(check, el, suspicious) \
- (NILP (check) \
- ? make_number (0) \
- : (INTEGERP (check) \
- ? (XFASTINT (check) < (suspicious) \
- ? make_number (XFASTINT (check) + 1) \
- : Fcons (el, Qnil)) \
- : (!NILP (Fmemq ((el), (check))) \
- ? Qnil \
- : Fcons ((el), (check)))))
-
-
/* SAFE_ALLOCA normally allocates memory on the stack, but if size is
larger than MAX_ALLOCA, use xmalloc to avoid overflowing the stack. */
-enum MAX_ALLOCA { MAX_ALLOCA = 16*1024 };
+enum MAX_ALLOCA { MAX_ALLOCA = 16 * 1024 };
extern Lisp_Object safe_alloca_unwind (Lisp_Object);
extern void *record_xmalloc (size_t);
diff --git a/src/lisp.mk b/src/lisp.mk
index 162d8819917..8c2710110e3 100644
--- a/src/lisp.mk
+++ b/src/lisp.mk
@@ -34,8 +34,9 @@
## that does not have an explicit .el extension, but beware of any
## no-byte-compile ones.
-## Confusingly, term/internal is not in loadup, but is unconditionally
-## loaded by pc-win, which is.
+## Confusingly, international/cp51932 and international/eucjp-ms are
+## unconditionally loaded from language/japanese, instead of being
+## loaded directly from loadup.el; FIXME.
## Note that this list should not include lisp files which might not
## be present, like site-load.el and site-init.el; this makefile
@@ -65,6 +66,7 @@ lisp = \
$(lispsource)/format.elc \
$(lispsource)/bindings.elc \
$(lispsource)/files.elc \
+ $(lispsource)/emacs-lisp/macroexp.elc \
$(lispsource)/cus-face.elc \
$(lispsource)/faces.elc \
$(lispsource)/button.elc \
@@ -93,6 +95,8 @@ lisp = \
$(lispsource)/language/greek.elc \
$(lispsource)/language/hebrew.elc \
$(lispsource)/language/japanese.elc \
+ $(lispsource)/international/cp51932.el \
+ $(lispsource)/international/eucjp-ms.el \
$(lispsource)/language/korean.elc \
$(lispsource)/language/lao.elc \
$(lispsource)/language/tai-viet.elc \
diff --git a/src/lread.c b/src/lread.c
index 1dd6275684b..2f385797ca0 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -25,7 +25,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/file.h>
#include <errno.h>
#include <limits.h> /* For CHAR_BIT. */
-#include <setjmp.h>
#include <stat-time.h>
#include "lisp.h"
#include "intervals.h"
@@ -50,7 +49,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif
#include <unistd.h>
-#include <math.h>
#ifdef HAVE_SETLOCALE
#include <locale.h>
@@ -97,10 +95,10 @@ static Lisp_Object Qload_in_progress;
It must be set to nil before all top-level calls to read0. */
static Lisp_Object read_objects;
-/* Nonzero means READCHAR should read bytes one by one (not character)
+/* True means READCHAR should read bytes one by one (not character)
when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char.
- This is set to 1 by read1 temporarily while handling #@NUMBER. */
-static int load_each_byte;
+ This is set by read1 temporarily while handling #@NUMBER. */
+static bool load_each_byte;
/* List of descriptors now open for Fload. */
static Lisp_Object load_descriptor_list;
@@ -137,11 +135,11 @@ static ptrdiff_t prev_saved_doc_string_length;
/* This is the file position that string came from. */
static file_offset prev_saved_doc_string_position;
-/* Nonzero means inside a new-style backquote
+/* True means inside a new-style backquote
with no surrounding parentheses.
- Fread initializes this to zero, so we need not specbind it
+ Fread initializes this to false, so we need not specbind it
or worry about what happens to it when there is an error. */
-static int new_backquote_flag;
+static bool new_backquote_flag;
static Lisp_Object Qold_style_backquotes;
/* A list of file names for files being loaded in Fload. Used to
@@ -152,7 +150,7 @@ static Lisp_Object Vloads_in_progress;
static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
Lisp_Object);
-static void readevalloop (Lisp_Object, FILE*, Lisp_Object, int,
+static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool,
Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
static Lisp_Object load_unwind (Lisp_Object);
@@ -194,7 +192,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
int (*readbyte) (int, Lisp_Object);
unsigned char buf[MAX_MULTIBYTE_LENGTH];
int i, len;
- int emacs_mule_encoding = 0;
+ bool emacs_mule_encoding = 0;
if (multibyte)
*multibyte = 0;
@@ -410,9 +408,9 @@ unreadchar (Lisp_Object readcharfun, int c)
{
if (load_each_byte)
{
- BLOCK_INPUT;
+ block_input ();
ungetc (c, instream);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
unread_char = c;
@@ -433,28 +431,26 @@ readbyte_from_file (int c, Lisp_Object readcharfun)
{
if (c >= 0)
{
- BLOCK_INPUT;
+ block_input ();
ungetc (c, instream);
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
- BLOCK_INPUT;
+ block_input ();
c = getc (instream);
-#ifdef EINTR
/* Interrupted reads have been observed while reading over the network. */
while (c == EOF && ferror (instream) && errno == EINTR)
{
- UNBLOCK_INPUT;
+ unblock_input ();
QUIT;
- BLOCK_INPUT;
+ block_input ();
clearerr (instream);
c = getc (instream);
}
-#endif
- UNBLOCK_INPUT;
+ unblock_input ();
return (c == EOF ? -1 : c);
}
@@ -548,10 +544,10 @@ read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object rea
static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object,
Lisp_Object);
static Lisp_Object read0 (Lisp_Object);
-static Lisp_Object read1 (Lisp_Object, int *, int);
+static Lisp_Object read1 (Lisp_Object, int *, bool);
-static Lisp_Object read_list (int, Lisp_Object);
-static Lisp_Object read_vector (Lisp_Object, int);
+static Lisp_Object read_list (bool, Lisp_Object);
+static Lisp_Object read_vector (Lisp_Object, bool);
static Lisp_Object substitute_object_recurse (Lisp_Object, Lisp_Object,
Lisp_Object);
@@ -564,28 +560,28 @@ static void substitute_in_interval (INTERVAL, Lisp_Object);
/* Read input events until we get one that's acceptable for our purposes.
- If NO_SWITCH_FRAME is non-zero, switch-frame events are stashed
+ If NO_SWITCH_FRAME, switch-frame events are stashed
until we get a character we like, and then stuffed into
unread_switch_frame.
- If ASCII_REQUIRED is non-zero, we check function key events to see
+ If ASCII_REQUIRED, check function key events to see
if the unmodified version of the symbol has a Qascii_character
property, and use that character, if present.
- If ERROR_NONASCII is non-zero, we signal an error if the input we
- get isn't an ASCII character with modifiers. If it's zero but
- ASCII_REQUIRED is non-zero, we just re-read until we get an ASCII
+ If ERROR_NONASCII, signal an error if the input we
+ get isn't an ASCII character with modifiers. If it's false but
+ ASCII_REQUIRED is true, just re-read until we get an ASCII
character.
- If INPUT_METHOD is nonzero, we invoke the current input method
+ If INPUT_METHOD, invoke the current input method
if the character warrants that.
- If SECONDS is a number, we wait that many seconds for input, and
+ If SECONDS is a number, wait that many seconds for input, and
return Qnil if no input arrives within that time. */
static Lisp_Object
-read_filtered_event (int no_switch_frame, int ascii_required,
- int error_nonascii, int input_method, Lisp_Object seconds)
+read_filtered_event (bool no_switch_frame, bool ascii_required,
+ bool error_nonascii, bool input_method, Lisp_Object seconds)
{
Lisp_Object val, delayed_switch_frame;
EMACS_TIME end_time;
@@ -755,9 +751,9 @@ DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
(void)
{
register Lisp_Object val;
- BLOCK_INPUT;
+ block_input ();
XSETINT (val, getc (instream));
- UNBLOCK_INPUT;
+ unblock_input ();
return val;
}
@@ -766,13 +762,30 @@ DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
/* Return true if the lisp code read using READCHARFUN defines a non-nil
`lexical-binding' file variable. After returning, the stream is
- positioned following the first line, if it is a comment, otherwise
- nothing is read. */
+ positioned following the first line, if it is a comment or #! line,
+ otherwise nothing is read. */
-static int
+static bool
lisp_file_lexically_bound_p (Lisp_Object readcharfun)
{
int ch = READCHAR;
+
+ if (ch == '#')
+ {
+ ch = READCHAR;
+ if (ch != '!')
+ {
+ UNREAD (ch);
+ UNREAD ('#');
+ return 0;
+ }
+ while (ch != '\n' && ch != EOF)
+ ch = READCHAR;
+ if (ch == '\n') ch = READCHAR;
+ /* It is OK to leave the position after a #! line, since
+ that is what read1 does. */
+ }
+
if (ch != ';')
/* The first line isn't a comment, just give up. */
{
@@ -782,11 +795,11 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
else
/* Look for an appropriate file-variable in the first line. */
{
- int rv = 0;
+ bool rv = 0;
enum {
NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX,
} beg_end_state = NOMINAL;
- int in_file_vars = 0;
+ bool in_file_vars = 0;
#define UPDATE_BEG_END_STATE(ch) \
if (beg_end_state == NOMINAL) \
@@ -882,20 +895,17 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
because of an incompatible change in the byte compiler. */
static int
-safe_to_load_p (int fd)
+safe_to_load_version (int fd)
{
char buf[512];
int nbytes, i;
- int safe_p = 1;
int version = 1;
/* Read the first few bytes from the file, and look for a line
specifying the byte compiler version used. */
- nbytes = emacs_read (fd, buf, sizeof buf - 1);
+ nbytes = emacs_read (fd, buf, sizeof buf);
if (nbytes > 0)
{
- buf[nbytes] = '\0';
-
/* Skip to the next newline, skipping over the initial `ELC'
with NUL bytes following it, but note the version. */
for (i = 0; i < nbytes && buf[i] != '\n'; ++i)
@@ -905,13 +915,11 @@ safe_to_load_p (int fd)
if (i >= nbytes
|| fast_c_string_match_ignore_case (Vbytecomp_version_regexp,
buf + i, nbytes - i) < 0)
- safe_p = 0;
+ version = 0;
}
- if (safe_p)
- safe_p = version;
lseek (fd, 0, SEEK_SET);
- return safe_p;
+ return version;
}
@@ -986,18 +994,17 @@ If optional fifth arg MUST-SUFFIX is non-nil, insist on
the suffix `.elc' or `.el'; don't accept just FILE unless
it ends in one of those suffixes or includes a directory name.
-If this function fails to find a file, it may look for different
-representations of that file before trying another file.
-It does so by adding the non-empty suffixes in `load-file-rep-suffixes'
-to the file name. Emacs uses this feature mainly to find compressed
-versions of files when Auto Compression mode is enabled.
+If NOSUFFIX is nil, then if a file could not be found, try looking for
+a different representation of the file by adding non-empty suffixes to
+its name, before trying another file. Emacs uses this feature to find
+compressed versions of files when Auto Compression mode is enabled.
+If NOSUFFIX is non-nil, disable this feature.
-The exact suffixes that this function tries out, in the exact order,
-are given by the value of the variable `load-file-rep-suffixes' if
-NOSUFFIX is non-nil and by the return value of the function
-`get-load-suffixes' if MUST-SUFFIX is non-nil. If both NOSUFFIX and
-MUST-SUFFIX are nil, this function first tries out the latter suffixes
-and then the former.
+The suffixes that this function tries out, when NOSUFFIX is nil, are
+given by the return value of `get-load-suffixes' and the values listed
+in `load-file-rep-suffixes'. If MUST-SUFFIX is non-nil, only the
+return value of `get-load-suffixes' is used, i.e. the file name is
+required to have a non-empty suffix.
Loading a file records its definitions, and its `provide' and
`require' calls, in an element of `load-history' whose
@@ -1015,12 +1022,12 @@ Return t if the file exists and loads successfully. */)
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3;
Lisp_Object found, efound, hist_file_name;
- /* 1 means we printed the ".el is newer" message. */
- int newer = 0;
- /* 1 means we are loading a compiled file. */
- int compiled = 0;
+ /* True means we printed the ".el is newer" message. */
+ bool newer = 0;
+ /* True means we are loading a compiled file. */
+ bool compiled = 0;
Lisp_Object handler;
- int safe_p = 1;
+ bool safe_p = 1;
const char *fmode = "r";
Lisp_Object tmp[2];
int version;
@@ -1175,7 +1182,7 @@ Return t if the file exists and loads successfully. */)
record_unwind_protect (load_warn_old_style_backquotes, file);
if (!memcmp (SDATA (found) + SBYTES (found) - 4, ".elc", 4)
- || (fd >= 0 && (version = safe_to_load_p (fd)) > 0))
+ || (fd >= 0 && (version = safe_to_load_version (fd)) > 0))
/* Load .elc files directly, but not when they are
remote and have no handler! */
{
@@ -1187,7 +1194,7 @@ Return t if the file exists and loads successfully. */)
GCPRO3 (file, found, hist_file_name);
if (version < 0
- && ! (version = safe_to_load_p (fd)))
+ && ! (version = safe_to_load_version (fd)))
{
safe_p = 0;
if (!load_dangerous_libraries)
@@ -1352,9 +1359,9 @@ load_unwind (Lisp_Object arg) /* Used as unwind-protect function in load. */
FILE *stream = (FILE *) XSAVE_VALUE (arg)->pointer;
if (stream != NULL)
{
- BLOCK_INPUT;
+ block_input ();
fclose (stream);
- UNBLOCK_INPUT;
+ unblock_input ();
}
return Qnil;
}
@@ -1379,10 +1386,10 @@ close_load_descs (void)
#endif
}
-static int
+static bool
complete_filename_p (Lisp_Object pathname)
{
- register const unsigned char *s = SDATA (pathname);
+ const unsigned char *s = SDATA (pathname);
return (IS_DIRECTORY_SEP (s[0])
|| (SCHARS (pathname) > 2
&& IS_DEVICE_SEP (s[1]) && IS_DIRECTORY_SEP (s[2])));
@@ -1394,7 +1401,7 @@ Returns the file's name in absolute form, or nil if not found.
If SUFFIXES is non-nil, it should be a list of suffixes to append to
file name when searching.
If non-nil, PREDICATE is used instead of `file-readable-p'.
-PREDICATE can also be an integer to pass to the access(2) function,
+PREDICATE can also be an integer to pass to the faccessat(2) function,
in which case file-name-handlers are ignored.
This function will normally skip directories, so if you want it to find
directories, make sure the PREDICATE function returns `dir-ok' for them. */)
@@ -1432,14 +1439,12 @@ static Lisp_Object Qdir_ok;
int
openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate)
{
- register int fd;
ptrdiff_t fn_size = 100;
char buf[100];
- register char *fn = buf;
- int absolute = 0;
+ char *fn = buf;
+ bool absolute = 0;
ptrdiff_t want_length;
Lisp_Object filename;
- struct stat st;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
Lisp_Object string, tail, encoded_fn;
ptrdiff_t max_suffix_len = 0;
@@ -1488,7 +1493,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
{
ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail));
Lisp_Object handler;
- int exists;
/* Concatenate path element/specified name with the suffix.
If the directory starts with /:, remove that. */
@@ -1512,6 +1516,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
handler = Ffind_file_name_handler (string, Qfile_exists_p);
if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate))
{
+ bool exists;
if (NILP (predicate))
exists = !NILP (Ffile_readable_p (string));
else
@@ -1533,30 +1538,40 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
}
else
{
+ int fd;
const char *pfn;
encoded_fn = ENCODE_FILE (string);
pfn = SSDATA (encoded_fn);
- exists = (stat (pfn, &st) == 0 && ! S_ISDIR (st.st_mode));
- if (exists)
- {
- /* Check that we can access or open it. */
- if (NATNUMP (predicate))
- fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
- && access (pfn, XFASTINT (predicate)) == 0)
- ? 1 : -1);
- else
- fd = emacs_open (pfn, O_RDONLY, 0);
- if (fd >= 0)
+ /* Check that we can access or open it. */
+ if (NATNUMP (predicate))
+ fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
+ && (faccessat (AT_FDCWD, pfn, XFASTINT (predicate),
+ AT_EACCESS)
+ == 0)
+ && ! file_directory_p (pfn))
+ ? 1 : -1);
+ else
+ {
+ struct stat st;
+ fd = emacs_open (pfn, O_RDONLY, 0);
+ if (0 <= fd
+ && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode)))
{
- /* We succeeded; return this descriptor and filename. */
- if (storeptr)
- *storeptr = string;
- UNGCPRO;
- return fd;
+ emacs_close (fd);
+ fd = -1;
}
}
+
+ if (fd >= 0)
+ {
+ /* We succeeded; return this descriptor and filename. */
+ if (storeptr)
+ *storeptr = string;
+ UNGCPRO;
+ return fd;
+ }
}
}
if (absolute)
@@ -1573,14 +1588,16 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
the source has an associated file name or not.
FILENAME is the file name that we are loading from.
- ENTIRE is 1 if loading that entire file, 0 if evaluating part of it. */
+
+ ENTIRE is true if loading that entire file, false if evaluating
+ part of it. */
static void
-build_load_history (Lisp_Object filename, int entire)
+build_load_history (Lisp_Object filename, bool entire)
{
- register Lisp_Object tail, prev, newelt;
- register Lisp_Object tem, tem2;
- register int foundit = 0;
+ Lisp_Object tail, prev, newelt;
+ Lisp_Object tem, tem2;
+ bool foundit = 0;
tail = Vload_history;
prev = Qnil;
@@ -1665,7 +1682,7 @@ static void
readevalloop (Lisp_Object readcharfun,
FILE *stream,
Lisp_Object sourcename,
- int printflag,
+ bool printflag,
Lisp_Object unibyte, Lisp_Object readfun,
Lisp_Object start, Lisp_Object end)
{
@@ -1674,12 +1691,23 @@ readevalloop (Lisp_Object readcharfun,
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
struct buffer *b = 0;
- int continue_reading_p;
+ bool continue_reading_p;
Lisp_Object lex_bound;
- /* Nonzero if reading an entire buffer. */
- int whole_buffer = 0;
- /* 1 on the first time around. */
- int first_sexp = 1;
+ /* True if reading an entire buffer. */
+ bool whole_buffer = 0;
+ /* True on the first time around. */
+ bool first_sexp = 1;
+ Lisp_Object macroexpand = intern ("internal-macroexpand-for-load");
+
+ if (NILP (Ffboundp (macroexpand))
+ /* Don't macroexpand in .elc files, since it should have been done
+ already. We actually don't know whether we're in a .elc file or not,
+ so we use circumstantial evidence: .el files normally go through
+ Vload_source_file_function -> load-with-code-conversion
+ -> eval-buffer. */
+ || EQ (readcharfun, Qget_file_char)
+ || EQ (readcharfun, Qget_emacs_mule_file_char))
+ macroexpand = Qnil;
if (MARKERP (readcharfun))
{
@@ -1694,7 +1722,7 @@ readevalloop (Lisp_Object readcharfun,
/* We assume START is nil when input is not from a buffer. */
if (! NILP (start) && !b)
- abort ();
+ emacs_abort ();
specbind (Qstandard_input, readcharfun); /* GCPROs readcharfun. */
specbind (Qcurrent_load_list, Qnil);
@@ -1724,7 +1752,7 @@ readevalloop (Lisp_Object readcharfun,
{
ptrdiff_t count1 = SPECPDL_INDEX ();
- if (b != 0 && NILP (BVAR (b, name)))
+ if (b != 0 && !BUFFER_LIVE_P (b))
error ("Reading from killed buffer");
if (!NILP (start))
@@ -1809,6 +1837,8 @@ readevalloop (Lisp_Object readcharfun,
unbind_to (count1, Qnil);
/* Now eval what we just read. */
+ if (!NILP (macroexpand))
+ val = call1 (macroexpand, val);
val = eval_sub (val);
if (printflag)
@@ -2044,9 +2074,9 @@ static char *read_buffer;
If the escape sequence forces unibyte, return eight-bit char. */
static int
-read_escape (Lisp_Object readcharfun, int stringp)
+read_escape (Lisp_Object readcharfun, bool stringp)
{
- register int c = READCHAR;
+ int c = READCHAR;
/* \u allows up to four hex digits, \U up to eight. Default to the
behavior for \u, and change this value in the case that \U is seen. */
int unicode_hex_count = 4;
@@ -2255,7 +2285,7 @@ read_escape (Lisp_Object readcharfun, int stringp)
/* Return the digit that CHARACTER stands for in the given BASE.
Return -1 if CHARACTER is out of range for BASE,
and -2 if CHARACTER is not valid for any supported BASE. */
-static inline int
+static int
digit_to_number (int character, int base)
{
int digit;
@@ -2347,10 +2377,10 @@ read_integer (Lisp_Object readcharfun, EMACS_INT radix)
in *PCH and the return value is not interesting. Else, we store
zero in *PCH and we read and return one lisp object.
- FIRST_IN_LIST is nonzero if this is the first element of a list. */
+ FIRST_IN_LIST is true if this is the first element of a list. */
static Lisp_Object
-read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
+read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
{
int c;
bool uninterned_symbol = 0;
@@ -2775,10 +2805,11 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
else
{
Lisp_Object value;
+ bool saved_new_backquote_flag = new_backquote_flag;
- new_backquote_flag++;
+ new_backquote_flag = 1;
value = read0 (readcharfun);
- new_backquote_flag--;
+ new_backquote_flag = saved_new_backquote_flag;
return Fcons (Qbackquote, Fcons (value, Qnil));
}
@@ -2830,7 +2861,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
{
int modifiers;
int next_char;
- int ok;
+ bool ok;
c = READCHAR;
if (c < 0)
@@ -2866,14 +2897,14 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
{
char *p = read_buffer;
char *end = read_buffer + read_buffer_size;
- register int ch;
- /* Nonzero if we saw an escape sequence specifying
+ int ch;
+ /* True if we saw an escape sequence specifying
a multibyte character. */
- int force_multibyte = 0;
- /* Nonzero if we saw an escape sequence specifying
+ bool force_multibyte = 0;
+ /* True if we saw an escape sequence specifying
a single-byte character. */
- int force_singlebyte = 0;
- int cancel = 0;
+ bool force_singlebyte = 0;
+ bool cancel = 0;
ptrdiff_t nchars = 0;
while ((ch = READCHAR) >= 0
@@ -3005,7 +3036,7 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list)
read_symbol:
{
char *p = read_buffer;
- int quoted = 0;
+ bool quoted = 0;
EMACS_INT start_position = readchar_count - 1;
{
@@ -3222,17 +3253,17 @@ substitute_in_interval (INTERVAL interval, Lisp_Object arg)
/* Convert STRING to a number, assuming base BASE. Return a fixnum if CP has
integer syntax and fits in a fixnum, else return the nearest float if CP has
either floating point or integer syntax and BASE is 10, else return nil. If
- IGNORE_TRAILING is nonzero, consider just the longest prefix of CP that has
+ IGNORE_TRAILING, consider just the longest prefix of CP that has
valid floating point syntax. Signal an overflow if BASE is not 10 and the
number has integer syntax but does not fit. */
Lisp_Object
-string_to_number (char const *string, int base, int ignore_trailing)
+string_to_number (char const *string, int base, bool ignore_trailing)
{
int state;
char const *cp = string;
int leading_digit;
- int float_syntax = 0;
+ bool float_syntax = 0;
double value = 0;
/* Compute NaN and infinities using a variable, to cope with compilers that
@@ -3242,9 +3273,9 @@ string_to_number (char const *string, int base, int ignore_trailing)
/* Negate the value ourselves. This treats 0, NaNs, and infinity properly on
IEEE floating point hosts, and works around a formerly-common bug where
atof ("-0.0") drops the sign. */
- int negative = *cp == '-';
+ bool negative = *cp == '-';
- int signedp = negative || *cp == '+';
+ bool signedp = negative || *cp == '+';
cp += signedp;
state = 0;
@@ -3337,7 +3368,7 @@ string_to_number (char const *string, int base, int ignore_trailing)
uintmax_t n;
/* Fast special case for single-digit integers. This also avoids a
- glitch when BASE is 16 and IGNORE_TRAILING is nonzero, because in that
+ glitch when BASE is 16 and IGNORE_TRAILING, because in that
case some versions of strtoumax accept numbers like "0x1" that Emacs
does not allow. */
if (digit_to_number (string[signedp + 1], base) < 0)
@@ -3373,12 +3404,12 @@ string_to_number (char const *string, int base, int ignore_trailing)
static Lisp_Object
-read_vector (Lisp_Object readcharfun, int bytecodeflag)
+read_vector (Lisp_Object readcharfun, bool bytecodeflag)
{
ptrdiff_t i, size;
- register Lisp_Object *ptr;
- register Lisp_Object tem, item, vector;
- register struct Lisp_Cons *otem;
+ Lisp_Object *ptr;
+ Lisp_Object tem, item, vector;
+ struct Lisp_Cons *otem;
Lisp_Object len;
tem = read_list (1, readcharfun);
@@ -3450,13 +3481,13 @@ read_vector (Lisp_Object readcharfun, int bytecodeflag)
return vector;
}
-/* FLAG = 1 means check for ] to terminate rather than ) and . */
+/* FLAG means check for ] to terminate rather than ) and . */
static Lisp_Object
-read_list (int flag, register Lisp_Object readcharfun)
+read_list (bool flag, Lisp_Object readcharfun)
{
Lisp_Object val, tail;
- register Lisp_Object elt, tem;
+ Lisp_Object elt, tem;
struct gcpro gcpro1, gcpro2;
/* 0 is the normal case.
1 means this list is a doc reference; replace it with the number 0.
@@ -3464,7 +3495,7 @@ read_list (int flag, register Lisp_Object readcharfun)
int doc_reference = 0;
/* Initialize this to 1 if we are reading a list. */
- int first_in_list = flag <= 0;
+ bool first_in_list = flag <= 0;
val = Qnil;
tail = Qnil;
@@ -3671,7 +3702,7 @@ intern_c_string_1 (const char *str, ptrdiff_t len)
/* 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. */
- abort ();
+ emacs_abort ();
return Fintern (make_pure_c_string (str, len), obarray);
}
@@ -3924,12 +3955,13 @@ init_obarray (void)
/* 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, Qunbound);
+ set_symbol_function (Qunbound, Qnil);
set_symbol_plist (Qunbound, Qnil);
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);
Qt = intern_c_string ("t");
SET_SYMBOL_VAL (XSYMBOL (Qt), Qt);
@@ -3950,7 +3982,7 @@ defsubr (struct Lisp_Subr *sname)
{
Lisp_Object sym, tem;
sym = intern_c_string (sname->symbol_name);
- XSETTYPED_PVECTYPE (sname, size, PVEC_SUBR);
+ XSETPVECTYPE (sname, PVEC_SUBR);
XSETSUBR (tem, sname);
set_symbol_function (sym, tem);
}
@@ -4056,9 +4088,8 @@ load_path_check (void)
if (STRINGP (dirfile))
{
dirfile = Fdirectory_file_name (dirfile);
- if (access (SSDATA (dirfile), 0) < 0)
- dir_warning ("Warning: Lisp directory `%s' does not exist.\n",
- XCAR (path_tail));
+ if (! file_accessible_directory_p (SSDATA (dirfile)))
+ dir_warning ("Lisp directory", XCAR (path_tail));
}
}
}
@@ -4170,11 +4201,11 @@ init_lread (void)
Lisp_Object tem, tem1;
/* Add to the path the lisp subdir of the installation
- dir, if it exists. Note: in out-of-tree builds,
+ dir, if it is accessible. Note: in out-of-tree builds,
this directory is empty save for Makefile. */
tem = Fexpand_file_name (build_string ("lisp"),
Vinstallation_directory);
- tem1 = Ffile_exists_p (tem);
+ tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, Vload_path)))
@@ -4191,10 +4222,10 @@ init_lread (void)
Lisp dirs instead. */
Vload_path = nconc2 (Vload_path, dump_path);
- /* Add leim under the installation dir, if it exists. */
+ /* Add leim under the installation dir, if it is accessible. */
tem = Fexpand_file_name (build_string ("leim"),
Vinstallation_directory);
- tem1 = Ffile_exists_p (tem);
+ tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, Vload_path)))
@@ -4206,7 +4237,7 @@ init_lread (void)
{
tem = Fexpand_file_name (build_string ("site-lisp"),
Vinstallation_directory);
- tem1 = Ffile_exists_p (tem);
+ tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, Vload_path)))
@@ -4251,7 +4282,7 @@ init_lread (void)
{
tem = Fexpand_file_name (build_string ("site-lisp"),
Vsource_directory);
- tem1 = Ffile_exists_p (tem);
+ tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, Vload_path)))
@@ -4307,21 +4338,28 @@ init_lread (void)
Vloads_in_progress = Qnil;
}
-/* Print a warning, using format string FORMAT, that directory DIRNAME
- does not exist. Print it on stderr and put it in *Messages*. */
+/* Print a warning that directory intended for use USE and with name
+ DIRNAME cannot be accessed. On entry, errno should correspond to
+ the access failure. Print the warning on stderr and put it in
+ *Messages*. */
void
-dir_warning (const char *format, Lisp_Object dirname)
+dir_warning (char const *use, Lisp_Object dirname)
{
- fprintf (stderr, format, SDATA (dirname));
+ static char const format[] = "Warning: %s `%s': %s\n";
+ int access_errno = errno;
+ fprintf (stderr, format, use, SSDATA (dirname), strerror (access_errno));
/* Don't log the warning before we've initialized!! */
if (initialized)
{
+ char const *diagnostic = emacs_strerror (access_errno);
USE_SAFE_ALLOCA;
- char *buffer = SAFE_ALLOCA (SBYTES (dirname)
- + strlen (format) - (sizeof "%s" - 1) + 1);
- ptrdiff_t message_len = esprintf (buffer, format, SDATA (dirname));
+ char *buffer = SAFE_ALLOCA (sizeof format - 3 * (sizeof "%s" - 1)
+ + strlen (use) + SBYTES (dirname)
+ + strlen (diagnostic));
+ ptrdiff_t message_len = esprintf (buffer, format, use, SSDATA (dirname),
+ diagnostic);
message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname));
SAFE_FREE ();
}
@@ -4487,12 +4525,16 @@ The default is nil, which means use the function `read'. */);
Vload_read_function = Qnil;
DEFVAR_LISP ("load-source-file-function", Vload_source_file_function,
- doc: /* Function called in `load' for loading an Emacs Lisp source file.
-This function is for doing code conversion before reading the source file.
-If nil, loading is done without any code conversion.
-Arguments are FULLNAME, FILE, NOERROR, NOMESSAGE, where
- FULLNAME is the full name of FILE.
-See `load' for the meaning of the remaining arguments. */);
+ doc: /* Function called in `load' to load an Emacs Lisp source file.
+The value should be a function for doing code conversion before
+reading a source file. It can also be nil, in which case loading is
+done without any code conversion.
+
+If the value is a function, it is called with four arguments,
+FULLNAME, FILE, NOERROR, NOMESSAGE. FULLNAME is the absolute name of
+the file to load, FILE is the non-absolute name (for messages etc.),
+and NOERROR and NOMESSAGE are the corresponding arguments passed to
+`load'. The function should return t if the file was loaded. */);
Vload_source_file_function = Qnil;
DEFVAR_BOOL ("load-force-doc-strings", load_force_doc_strings,
diff --git a/src/macros.c b/src/macros.c
index e81068181b9..632c851ee8c 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -19,7 +19,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "macros.h"
#include "commands.h"
@@ -84,7 +84,7 @@ macro before appending to it. */)
{
ptrdiff_t i;
EMACS_INT len;
- int cvt;
+ 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));
diff --git a/src/makefile.w32-in b/src/makefile.w32-in
index a8dcf5f2ae8..b595defdf6b 100644
--- a/src/makefile.w32-in
+++ b/src/makefile.w32-in
@@ -25,9 +25,9 @@ ALL = emacs
EMACSLOADPATH=$(CURDIR)/../lisp
# Size in MBs of the static heap in temacs.exe.
-HEAPSIZE = 27
+HEAPSIZE = $(EMACS_HEAPSIZE)
-LOCAL_FLAGS = -Demacs=1 -I../lib -I../nt/inc -DHAVE_NTGUI=1 $(EMACS_EXTRA_C_FLAGS)
+LOCAL_FLAGS = -Demacs=1 -I../lib -I../nt/inc $(EMACS_EXTRA_C_FLAGS)
SRC = .
EMACS = $(BLD)/emacs.exe
@@ -125,6 +125,7 @@ OBJ2 = $(BLD)/sysdep.$(O) \
$(BLD)/terminal.$(O) \
$(BLD)/menu.$(O) \
$(BLD)/xml.$(O) \
+ $(BLD)/profiler.$(O) \
$(BLD)/w32term.$(O) \
$(BLD)/w32xfns.$(O) \
$(BLD)/w32fns.$(O) \
@@ -133,6 +134,7 @@ OBJ2 = $(BLD)/sysdep.$(O) \
$(BLD)/w32menu.$(O) \
$(BLD)/w32reg.$(O) \
$(BLD)/w32font.$(O) \
+ $(BLD)/w32notify.$(O) \
$(BLD)/w32uniscribe.$(O)
LIBS = $(TLIB0) \
@@ -206,9 +208,9 @@ make-buildobj-SH:
GLOBAL_SOURCES = dosfns.c msdos.c \
xterm.c xfns.c xmenu.c xselect.c xrdb.c xsmfns.c fringe.c image.c \
fontset.c menu.c dbusbind.c \
- w32.c w32console.c w32fns.c w32heap.c w32inevt.c \
+ w32.c w32console.c w32fns.c w32heap.c w32inevt.c cygw32.c \
w32menu.c w32proc.c w32reg.c w32select.c w32term.c w32xfns.c \
- font.c w32font.c w32uniscribe.c \
+ font.c w32font.c w32uniscribe.c w32notify.c \
dispnew.c frame.c scroll.c xdisp.c window.c bidi.c \
charset.c coding.c category.c ccl.c character.c chartab.c \
cm.c term.c terminal.c xfaces.c \
@@ -222,18 +224,18 @@ GLOBAL_SOURCES = dosfns.c msdos.c \
process.c callproc.c unexw32.c \
region-cache.c sound.c atimer.c \
doprnt.c intervals.c textprop.c composite.c \
- gnutls.c xml.c
+ gnutls.c xml.c profiler.c
SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o dbusbind.o
obj = $(GLOBAL_SOURCES:.c=.o)
globals.h: gl-stamp
- @cmd /c rem true
+ @cmd $(SWITCHCHAR)c rem true
gl-stamp: ../lib-src/$(BLD)/make-docfile.exe $(GLOBAL_SOURCES)
- $(DEL) gl-tmp
"$(THISDIR)/../lib-src/$(BLD)/make-docfile" -d . -g $(SOME_MACHINE_OBJECTS) $(obj) > gl-tmp
- cmd /c "fc /b gl-tmp globals.h >nul 2>&1 || $(CP) gl-tmp globals.h"
+ fc.exe $(SWITCHCHAR)b gl-tmp globals.h >nul 2>&1 || $(CP) gl-tmp globals.h
- $(DEL) gl-tmp
echo timestamp > $@
@@ -246,10 +248,10 @@ bootstrap: bootstrap-emacs
# WARNING: Do NOT split the part inside $(ARGQUOTE)s into multiple lines as
# this can break with GNU Make 3.81 and later if sh.exe is used.
bootstrap-temacs-CMD:
- $(MAKE) $(MFLAGS) $(XMFLAGS) temacs CFLAGS=$(ARGQUOTE)$(ESC_CFLAGS) -DPURESIZE=5000000$(ARGQUOTE)
+ $(MAKE) $(MFLAGS) $(XMFLAGS) temacs CFLAGS=$(ARGQUOTE)$(ESC_CFLAGS) -DPURESIZE=$(EMACS_PURESIZE)$(ARGQUOTE)
bootstrap-temacs-SH:
- $(MAKE) $(MFLAGS) $(XMFLAGS) temacs CFLAGS=$(ARGQUOTE)$(CFLAGS) -DPURESIZE=5000000$(ARGQUOTE)
+ $(MAKE) $(MFLAGS) $(XMFLAGS) temacs CFLAGS=$(ARGQUOTE)$(CFLAGS) -DPURESIZE=$(EMACS_PURESIZE)$(ARGQUOTE)
bootstrap-temacs:
$(MAKE) $(MFLAGS) bootstrap-temacs-$(SHELLTYPE)
@@ -392,8 +394,6 @@ SYSTIME_H = $(SRC)/systime.h \
ATIMER_H = $(SRC)/atimer.h \
$(NT_INC)/stdbool.h \
$(SYSTIME_H)
-BLOCKINPUT_H = $(SRC)/blockinput.h \
- $(ATIMER_H)
BUFFER_H = $(SRC)/buffer.h \
$(SYSTIME_H)
C_CTYPE_H = $(GNU_LIB)/c-ctype.h \
@@ -414,8 +414,6 @@ CONF_POST_H = $(SRC)/conf_post.h \
$(MS_W32_H)
CONFIG_H = $(SRC)/config.h \
$(CONF_POST_H)
-DIR_H = $(NT_INC)/sys/dir.h \
- $(SRC)/ndir.h
W32GUI_H = $(SRC)/w32gui.h \
$(SYSTIME_H)
DISPEXTERN_H = $(SRC)/dispextern.h \
@@ -424,10 +422,11 @@ DISPEXTERN_H = $(SRC)/dispextern.h \
$(W32GUI_H)
FILEMODE_H = $(GNU_LIB)/filemode.h \
$(NT_INC)/sys/stat.h
-FONT_H = $(SRC)/font.h \
- $(CCL_H)
FRAME_H = $(SRC)/frame.h \
$(DISPEXTERN_H)
+FONT_H = $(SRC)/font.h \
+ $(CCL_H) \
+ $(FRAME_H)
FTOASTR_H = $(GNU_LIB)/ftoastr.h \
$(GNU_LIB)/intprops.h
GRP_H = $(NT_INC)/grp.h \
@@ -463,30 +462,39 @@ U64_H = $(GNU_LIB)/u64.h \
$(NT_INC)/stdint.h
SHA512_H = $(GNU_LIB)/sha512.h \
$(U64_H)
+SIG2STR_H = $(GNU_LIB)/sig2str.h \
+ $(GNU_LIB)/intprops.h
SOCKET_H = $(NT_INC)/sys/socket.h \
$(SRC)/w32.h
STAT_TIME_H = $(GNU_LIB)/stat-time.h \
$(NT_INC)/sys/stat.h
+SYSSIGNAL_H = $(SRC)/syssignal.h \
+ $(NT_INC)/stdbool.h
SYSTTY_H = $(SRC)/systty.h \
$(NT_INC)/sys/ioctl.h \
$(NT_INC)/unistd.h
+SYSWAIT_H = $(SRC)/syswait.h \
+ $(NT_INC)/stdbool.h \
+ $(NT_INC)/sys/wait.h
TERMHOOKS_H = $(SRC)/termhooks.h \
$(SYSTIME_H)
W32FONT_H = $(SRC)/w32font.h \
$(FONT_H)
W32TERM_H = $(SRC)/w32term.h \
+ $(ATIMER_H) \
+ $(FRAME_H) \
$(W32GUI_H)
WINDOW_H = $(SRC)/window.h \
$(DISPEXTERN_H)
$(BLD)/alloc.$(O) : \
$(SRC)/alloc.c \
+ $(SRC)/blockinput.h \
$(SRC)/puresize.h \
- $(SRC)/syssignal.h \
$(SRC)/w32.h \
+ $(SRC)/w32heap.h \
$(NT_INC)/unistd.h \
$(GNU_LIB)/verify.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -500,12 +508,12 @@ $(BLD)/alloc.$(O) : \
$(BLD)/atimer.$(O) : \
$(SRC)/atimer.c \
- $(SRC)/syssignal.h \
+ $(SRC)/blockinput.h \
$(NT_INC)/unistd.h \
$(ATIMER_H) \
- $(BLOCKINPUT_H) \
$(CONFIG_H) \
$(LISP_H) \
+ $(SYSSIGNAL_H) \
$(SYSTIME_H)
$(BLD)/bidi.$(O) : \
@@ -518,6 +526,7 @@ $(BLD)/bidi.$(O) : \
$(BLD)/buffer.$(O) : \
$(SRC)/buffer.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/indent.h \
$(SRC)/keymap.h \
@@ -526,7 +535,6 @@ $(BLD)/buffer.$(O) : \
$(NT_INC)/sys/stat.h \
$(NT_INC)/unistd.h \
$(GNU_LIB)/verify.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -558,14 +566,13 @@ $(BLD)/callint.$(O) : \
$(BLD)/callproc.$(O) : \
$(SRC)/callproc.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/composite.h \
$(SRC)/epaths.h \
- $(SRC)/syssignal.h \
$(SRC)/w32.h \
$(NT_INC)/sys/file.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CCL_H) \
$(CHARACTER_H) \
@@ -574,7 +581,9 @@ $(BLD)/callproc.$(O) : \
$(FRAME_H) \
$(LISP_H) \
$(PROCESS_H) \
+ $(SYSSIGNAL_H) \
$(SYSTTY_H) \
+ $(SYSWAIT_H) \
$(TERMHOOKS_H)
$(BLD)/casefiddle.$(O) : \
@@ -691,7 +700,6 @@ $(BLD)/data.$(O) : \
$(SRC)/data.c \
$(SRC)/keymap.h \
$(SRC)/puresize.h \
- $(SRC)/syssignal.h \
$(GNU_LIB)/intprops.h \
$(BUFFER_H) \
$(CHARACTER_H) \
@@ -700,22 +708,23 @@ $(BLD)/data.$(O) : \
$(FRAME_H) \
$(KEYBOARD_H) \
$(LISP_H) \
+ $(SYSSIGNAL_H) \
$(TERMHOOKS_H)
$(BLD)/dired.$(O) : \
$(SRC)/dired.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/regex.h \
+ $(NT_INC)/dirent.h \
$(NT_INC)/pwd.h \
$(NT_INC)/sys/stat.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
$(CODING_H) \
$(CONFIG_H) \
- $(DIR_H) \
$(FILEMODE_H) \
$(GRP_H) \
$(LISP_H) \
@@ -724,15 +733,15 @@ $(BLD)/dired.$(O) : \
$(BLD)/dispnew.$(O) : \
$(SRC)/dispnew.c \
+ $(SRC)/blockinput.h \
$(SRC)/cm.h \
$(SRC)/commands.h \
$(SRC)/disptab.h \
$(SRC)/indent.h \
- $(SRC)/syssignal.h \
$(SRC)/termchar.h \
- $(SRC)/termopts.h \
+ $(SRC)/w32.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
+ $(GNU_LIB)/fpending.h \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -742,6 +751,7 @@ $(BLD)/dispnew.$(O) : \
$(KEYBOARD_H) \
$(LISP_H) \
$(PROCESS_H) \
+ $(SYSSIGNAL_H) \
$(SYSTIME_H) \
$(TERMHOOKS_H) \
$(W32TERM_H) \
@@ -769,12 +779,13 @@ $(BLD)/doprnt.$(O) : \
$(BLD)/editfns.$(O) : \
$(SRC)/editfns.c \
+ $(SRC)/blockinput.h \
$(NT_INC)/pwd.h \
+ $(NT_INC)/grp.h \
$(NT_INC)/unistd.h \
$(GNU_LIB)/intprops.h \
$(GNU_LIB)/strftime.h \
$(GNU_LIB)/verify.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CODING_H) \
@@ -787,16 +798,20 @@ $(BLD)/editfns.$(O) : \
$(BLD)/emacs.$(O) : \
$(SRC)/emacs.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/gnutls.h \
$(SRC)/keymap.h \
- $(SRC)/syssignal.h \
$(SRC)/unexec.h \
$(SRC)/w32.h \
+ $(SRC)/w32common.h \
$(SRC)/w32heap.h \
+ $(SRC)/w32select.h \
$(NT_INC)/sys/file.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
+ $(GNU_LIB)/close-stream.h \
+ $(GNU_LIB)/ignore-value.h \
+ $(ATIMER_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -805,15 +820,17 @@ $(BLD)/emacs.$(O) : \
$(KEYBOARD_H) \
$(LISP_H) \
$(PROCESS_H) \
+ $(SYSSIGNAL_H) \
$(SYSTTY_H) \
$(TERMHOOKS_H) \
+ $(W32FONT_H) \
$(W32TERM_H) \
$(WINDOW_H)
$(BLD)/eval.$(O) : \
$(SRC)/eval.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
- $(BLOCKINPUT_H) \
$(CONFIG_H) \
$(DISPEXTERN_H) \
$(FRAME_H) \
@@ -822,11 +839,13 @@ $(BLD)/eval.$(O) : \
$(BLD)/fileio.$(O) : \
$(SRC)/fileio.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
+ $(SRC)/w32.h \
$(NT_INC)/pwd.h \
+ $(NT_INC)/sys/file.h \
$(NT_INC)/sys/stat.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CODING_H) \
@@ -859,17 +878,16 @@ $(BLD)/firstfile.$(O) : \
$(BLD)/floatfns.$(O) : \
$(SRC)/floatfns.c \
- $(SRC)/syssignal.h \
$(CONFIG_H) \
$(LISP_H)
$(BLD)/fns.$(O) : \
$(SRC)/fns.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/keymap.h \
$(NT_INC)/unistd.h \
$(GNU_LIB)/intprops.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CODING_H) \
@@ -903,8 +921,8 @@ $(BLD)/font.$(O) : \
$(BLD)/fontset.$(O) : \
$(SRC)/fontset.c \
+ $(SRC)/blockinput.h \
$(SRC)/fontset.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CCL_H) \
$(CHARACTER_H) \
@@ -922,10 +940,10 @@ $(BLD)/fontset.$(O) : \
$(BLD)/frame.$(O) : \
$(SRC)/frame.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/fontset.h \
$(SRC)/termchar.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -941,7 +959,7 @@ $(BLD)/frame.$(O) : \
$(BLD)/fringe.$(O) : \
$(SRC)/fringe.c \
- $(BLOCKINPUT_H) \
+ $(SRC)/blockinput.h \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -953,6 +971,7 @@ $(BLD)/fringe.$(O) : \
$(BLD)/gmalloc.$(O) : \
$(SRC)/gmalloc.c \
+ $(SRC)/w32heap.h \
$(NT_INC)/stdint.h \
$(NT_INC)/unistd.h \
$(CONFIG_H)
@@ -972,12 +991,19 @@ $(BLD)/xml.$(O) : \
$(CONFIG_H) \
$(LISP_H)
+$(BLD)/profiler.$(O) : \
+ $(SRC)/profiler.c \
+ $(CONFIG_H) \
+ $(LISP_H) \
+ $(SYSSIGNAL_H) \
+ $(SYSTIME_H)
+
$(BLD)/image.$(O) : \
$(SRC)/image.c \
+ $(SRC)/blockinput.h \
$(SRC)/epaths.h \
$(SRC)/w32.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(CHARACTER_H) \
$(CODING_H) \
$(CONFIG_H) \
@@ -999,7 +1025,6 @@ $(BLD)/indent.$(O) : \
$(SRC)/indent.h \
$(SRC)/region-cache.h \
$(SRC)/termchar.h \
- $(SRC)/termopts.h \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -1012,9 +1037,9 @@ $(BLD)/indent.$(O) : \
$(BLD)/insdel.$(O) : \
$(SRC)/insdel.c \
+ $(SRC)/blockinput.h \
$(SRC)/region-cache.h \
$(GNU_LIB)/intprops.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -1036,19 +1061,18 @@ $(BLD)/intervals.$(O) : \
$(BLD)/keyboard.$(O) : \
$(SRC)/keyboard.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/disptab.h \
$(SRC)/keymap.h \
$(SRC)/macros.h \
$(SRC)/puresize.h \
$(SRC)/syntax.h \
- $(SRC)/syssignal.h \
$(SRC)/termchar.h \
$(SRC)/termopts.h \
$(NT_INC)/sys/ioctl.h \
$(NT_INC)/unistd.h \
$(ATIMER_H) \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -1058,6 +1082,7 @@ $(BLD)/keyboard.$(O) : \
$(KEYBOARD_H) \
$(LISP_H) \
$(PROCESS_H) \
+ $(SYSSIGNAL_H) \
$(SYSTIME_H) \
$(TERMHOOKS_H) \
$(W32TERM_H) \
@@ -1065,10 +1090,10 @@ $(BLD)/keyboard.$(O) : \
$(BLD)/keymap.$(O) : \
$(SRC)/keymap.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/keymap.h \
$(SRC)/puresize.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1086,12 +1111,12 @@ $(BLD)/lastfile.$(O) : \
$(BLD)/lread.$(O) : \
$(SRC)/lread.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/epaths.h \
$(NT_INC)/sys/file.h \
$(NT_INC)/sys/stat.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1124,8 +1149,8 @@ $(BLD)/marker.$(O) : \
$(BLD)/menu.$(O) : \
$(SRC)/menu.c \
+ $(SRC)/blockinput.h \
$(SRC)/keymap.h \
- $(BLOCKINPUT_H) \
$(CONFIG_H) \
$(DISPEXTERN_H) \
$(FRAME_H) \
@@ -1154,9 +1179,11 @@ $(BLD)/minibuf.$(O) : \
$(BLD)/w32.$(O) : \
$(SRC)/w32.c \
- $(SRC)/ndir.h \
$(SRC)/w32.h \
+ $(SRC)/w32common.h \
$(SRC)/w32heap.h \
+ $(SRC)/w32select.h \
+ $(NT_INC)/dirent.h \
$(NT_INC)/pwd.h \
$(NT_INC)/sys/file.h \
$(NT_INC)/sys/time.h \
@@ -1173,16 +1200,17 @@ $(BLD)/w32.$(O) : \
$(BLD)/w32heap.$(O) : \
$(SRC)/w32heap.c \
+ $(SRC)/w32common.h \
$(SRC)/w32heap.h \
$(CONFIG_H) \
$(LISP_H)
$(BLD)/w32inevt.$(O) : \
$(SRC)/w32inevt.c \
+ $(SRC)/blockinput.h \
$(SRC)/termchar.h \
$(SRC)/w32heap.h \
$(SRC)/w32inevt.h \
- $(BLOCKINPUT_H) \
$(CONFIG_H) \
$(DISPEXTERN_H) \
$(FRAME_H) \
@@ -1194,9 +1222,8 @@ $(BLD)/w32inevt.$(O) : \
$(BLD)/w32proc.$(O) : \
$(SRC)/w32proc.c \
- $(SRC)/syssignal.h \
- $(SRC)/syswait.h \
$(SRC)/w32.h \
+ $(SRC)/w32common.h \
$(SRC)/w32heap.h \
$(NT_INC)/nl_types.h \
$(NT_INC)/sys/file.h \
@@ -1206,14 +1233,16 @@ $(BLD)/w32proc.$(O) : \
$(LANGINFO_H) \
$(LISP_H) \
$(PROCESS_H) \
+ $(SYSSIGNAL_H) \
$(SYSTIME_H) \
+ $(SYSWAIT_H) \
$(W32TERM_H)
$(BLD)/w32console.$(O) : \
$(SRC)/w32console.c \
$(SRC)/disptab.h \
$(SRC)/termchar.h \
- $(SRC)/w32heap.h \
+ $(SRC)/w32common.h \
$(SRC)/w32inevt.h \
$(CHARACTER_H) \
$(CODING_H) \
@@ -1222,12 +1251,13 @@ $(BLD)/w32console.$(O) : \
$(FRAME_H) \
$(LISP_H) \
$(TERMHOOKS_H) \
+ $(W32TERM_H) \
$(WINDOW_H)
$(BLD)/print.$(O) : \
$(SRC)/print.c \
+ $(SRC)/blockinput.h \
$(SRC)/termchar.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1245,12 +1275,11 @@ $(BLD)/print.$(O) : \
$(BLD)/process.$(O) : \
$(SRC)/process.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/composite.h \
$(SRC)/gnutls.h \
$(SRC)/sysselect.h \
- $(SRC)/syssignal.h \
- $(SRC)/syswait.h \
$(SRC)/termopts.h \
$(NT_INC)/arpa/inet.h \
$(NT_INC)/netdb.h \
@@ -1260,28 +1289,31 @@ $(BLD)/process.$(O) : \
$(NT_INC)/sys/stat.h \
$(NT_INC)/unistd.h \
$(ATIMER_H) \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CODING_H) \
$(CONFIG_H) \
+ $(C_CTYPE_H) \
$(DISPEXTERN_H) \
$(FRAME_H) \
$(KEYBOARD_H) \
$(LISP_H) \
$(PROCESS_H) \
+ $(SIG2STR_H) \
$(SOCKET_H) \
+ $(SYSSIGNAL_H) \
$(SYSTIME_H) \
$(SYSTTY_H) \
+ $(SYSWAIT_H) \
$(TERMHOOKS_H) \
$(W32TERM_H) \
$(WINDOW_H)
$(BLD)/ralloc.$(O) : \
$(SRC)/ralloc.c \
+ $(SRC)/blockinput.h \
$(SRC)/getpagesize.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(CONFIG_H) \
$(LISP_H)
@@ -1316,12 +1348,12 @@ $(BLD)/scroll.$(O) : \
$(BLD)/search.$(O) : \
$(SRC)/search.c \
+ $(SRC)/blockinput.h \
$(SRC)/category.h \
$(SRC)/commands.h \
$(SRC)/regex.h \
$(SRC)/region-cache.h \
$(SRC)/syntax.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1331,12 +1363,12 @@ $(BLD)/search.$(O) : \
$(BLD)/sound.$(O) : \
$(SRC)/sound.c \
- $(SRC)/syssignal.h \
$(NT_INC)/unistd.h \
$(ATIMER_H) \
$(CONFIG_H) \
$(DISPEXTERN_H) \
- $(LISP_H)
+ $(LISP_H) \
+ $(SYSSIGNAL_H)
$(BLD)/syntax.$(O) : \
$(SRC)/syntax.c \
@@ -1353,10 +1385,9 @@ $(BLD)/syntax.$(O) : \
$(BLD)/sysdep.$(O) : \
$(SRC)/sysdep.c \
+ $(SRC)/blockinput.h \
$(SRC)/cm.h \
$(SRC)/sysselect.h \
- $(SRC)/syssignal.h \
- $(SRC)/syswait.h \
$(SRC)/termchar.h \
$(SRC)/termopts.h \
$(NT_INC)/netdb.h \
@@ -1365,9 +1396,9 @@ $(BLD)/sysdep.$(O) : \
$(NT_INC)/sys/stat.h \
$(NT_INC)/unistd.h \
$(GNU_LIB)/allocator.h \
+ $(GNU_LIB)/execinfo.h \
$(GNU_LIB)/ignore-value.h \
$(GNU_LIB)/utimens.h \
- $(BLOCKINPUT_H) \
$(CAREADLINKAT_H) \
$(CONFIG_H) \
$(C_CTYPE_H) \
@@ -1378,25 +1409,25 @@ $(BLD)/sysdep.$(O) : \
$(LISP_H) \
$(PROCESS_H) \
$(SOCKET_H) \
+ $(SYSSIGNAL_H) \
$(SYSTIME_H) \
$(SYSTTY_H) \
+ $(SYSWAIT_H) \
$(TERMHOOKS_H) \
$(WINDOW_H)
$(BLD)/term.$(O) : \
$(SRC)/term.c \
+ $(SRC)/blockinput.h \
$(SRC)/cm.h \
$(SRC)/composite.h \
$(SRC)/disptab.h \
$(SRC)/keymap.h \
- $(SRC)/syssignal.h \
$(SRC)/termchar.h \
- $(SRC)/termopts.h \
$(SRC)/tparam.h \
$(NT_INC)/sys/file.h \
$(NT_INC)/sys/time.h \
$(NT_INC)/unistd.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1407,8 +1438,10 @@ $(BLD)/term.$(O) : \
$(INTERVALS_H) \
$(KEYBOARD_H) \
$(LISP_H) \
+ $(SYSSIGNAL_H) \
$(SYSTTY_H) \
$(TERMHOOKS_H) \
+ $(W32TERM_H) \
$(WINDOW_H)
$(BLD)/terminal.$(O) : \
@@ -1449,24 +1482,28 @@ $(BLD)/undo.$(O) : \
$(BLD)/unexw32.$(O) : \
$(SRC)/unexw32.c \
$(SRC)/unexec.h \
+ $(SRC)/w32.h \
+ $(SRC)/w32common.h \
$(SRC)/w32heap.h \
- $(CONFIG_H)
+ $(CONFIG_H) \
+ $(LISP_H)
$(BLD)/vm-limit.$(O) : \
$(SRC)/vm-limit.c \
$(SRC)/mem-limits.h \
+ $(SRC)/w32heap.h \
$(NT_INC)/unistd.h \
$(CONFIG_H) \
$(LISP_H)
$(BLD)/window.$(O) : \
$(SRC)/window.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/disptab.h \
$(SRC)/indent.h \
$(SRC)/keymap.h \
$(SRC)/termchar.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CONFIG_H) \
@@ -1481,6 +1518,7 @@ $(BLD)/window.$(O) : \
$(BLD)/xdisp.$(O) : \
$(SRC)/xdisp.c \
+ $(SRC)/blockinput.h \
$(SRC)/commands.h \
$(SRC)/disptab.h \
$(SRC)/fontset.h \
@@ -1490,7 +1528,7 @@ $(BLD)/xdisp.$(O) : \
$(SRC)/region-cache.h \
$(SRC)/termchar.h \
$(SRC)/termopts.h \
- $(BLOCKINPUT_H) \
+ $(ATIMER_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1509,10 +1547,10 @@ $(BLD)/xdisp.$(O) : \
$(BLD)/xfaces.$(O) : \
$(SRC)/xfaces.c \
+ $(SRC)/blockinput.h \
$(SRC)/fontset.h \
$(SRC)/termchar.h \
$(NT_INC)/sys/stat.h \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1530,11 +1568,13 @@ $(BLD)/xfaces.$(O) : \
$(BLD)/w32fns.$(O) : \
$(SRC)/w32fns.c \
+ $(SRC)/blockinput.h \
$(SRC)/epaths.h \
$(SRC)/fontset.h \
$(SRC)/w32.h \
+ $(SRC)/w32common.h \
$(SRC)/w32heap.h \
- $(BLOCKINPUT_H) \
+ $(NT_INC)/unistd.h \
$(BUFFER_H) \
$(CCL_H) \
$(CHARACTER_H) \
@@ -1555,9 +1595,9 @@ $(BLD)/w32fns.$(O) : \
$(BLD)/w32menu.$(O) : \
$(SRC)/w32menu.c \
+ $(SRC)/blockinput.h \
$(SRC)/keymap.h \
- $(SRC)/w32heap.h \
- $(BLOCKINPUT_H) \
+ $(SRC)/w32common.h \
$(BUFFER_H) \
$(CHARACTER_H) \
$(CHARSET_H) \
@@ -1574,6 +1614,7 @@ $(BLD)/w32menu.$(O) : \
$(BLD)/w32term.$(O) : \
$(SRC)/w32term.c \
+ $(SRC)/blockinput.h \
$(SRC)/disptab.h \
$(SRC)/fontset.h \
$(SRC)/keymap.h \
@@ -1582,7 +1623,6 @@ $(BLD)/w32term.$(O) : \
$(SRC)/w32heap.h \
$(NT_INC)/sys/stat.h \
$(ATIMER_H) \
- $(BLOCKINPUT_H) \
$(BUFFER_H) \
$(CCL_H) \
$(CHARACTER_H) \
@@ -1605,26 +1645,27 @@ $(BLD)/w32term.$(O) : \
$(BLD)/w32select.$(O) : \
$(SRC)/w32select.c \
+ $(SRC)/blockinput.h \
$(SRC)/composite.h \
- $(SRC)/w32heap.h \
- $(BLOCKINPUT_H) \
+ $(SRC)/w32common.h \
$(CHARSET_H) \
$(CODING_H) \
$(CONFIG_H) \
+ $(KEYBOARD_H) \
$(LISP_H) \
$(W32TERM_H)
$(BLD)/w32reg.$(O) : \
$(SRC)/w32reg.c \
- $(BLOCKINPUT_H) \
+ $(SRC)/blockinput.h \
$(CONFIG_H) \
$(LISP_H) \
$(W32TERM_H)
$(BLD)/w32xfns.$(O) : \
$(SRC)/w32xfns.c \
+ $(SRC)/blockinput.h \
$(SRC)/fontset.h \
- $(BLOCKINPUT_H) \
$(CHARSET_H) \
$(CONFIG_H) \
$(FRAME_H) \
@@ -1660,6 +1701,18 @@ $(BLD)/w32uniscribe.$(O) : \
$(W32FONT_H) \
$(W32TERM_H)
+$(BLD)/w32notify.$(O) : \
+ $(SRC)/w32notify.c \
+ $(SRC)/w32.h \
+ $(SRC)/w32common.h \
+ $(CODING_H) \
+ $(CONFIG_H) \
+ $(FRAME_H) \
+ $(KEYBOARD_H) \
+ $(LISP_H) \
+ $(TERMHOOKS_H) \
+ $(W32TERM_H)
+
# Each object file depends on stamp_BLD, because in parallel builds we must
# make sure $(BLD) exists before starting compilations.
#
diff --git a/src/marker.c b/src/marker.c
index 4ea06c7cd57..69be4faec3a 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -18,7 +18,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -29,7 +29,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
static ptrdiff_t cached_charpos;
static ptrdiff_t cached_bytepos;
static struct buffer *cached_buffer;
-static int cached_modiff;
+static EMACS_INT cached_modiff;
/* Juanma Barranquero <lekktu@gmail.com> reported ~3x increased
bootstrap time when byte_char_debug_check is enabled; so this
@@ -59,7 +59,7 @@ byte_char_debug_check (struct buffer *b, ptrdiff_t charpos, ptrdiff_t bytepos)
bytepos - BUF_BEG_BYTE (b));
if (charpos - 1 != nchars)
- abort ();
+ emacs_abort ();
}
#else /* not MARKER_DEBUG */
@@ -67,7 +67,7 @@ byte_char_debug_check (struct buffer *b, ptrdiff_t charpos, ptrdiff_t bytepos)
#define byte_char_debug_check(b, charpos, bytepos) do { } while (0)
#endif /* MARKER_DEBUG */
-
+
void
clear_charpos_cache (struct buffer *b)
{
@@ -91,7 +91,7 @@ clear_charpos_cache (struct buffer *b)
#define CONSIDER(CHARPOS, BYTEPOS) \
{ \
ptrdiff_t this_charpos = (CHARPOS); \
- int changed = 0; \
+ bool changed = 0; \
\
if (this_charpos == charpos) \
{ \
@@ -142,7 +142,7 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
ptrdiff_t best_below, best_below_byte;
if (charpos < BUF_BEG (b) || charpos > BUF_Z (b))
- abort ();
+ emacs_abort ();
best_above = BUF_Z (b);
best_above_byte = BUF_Z_BYTE (b);
@@ -190,7 +190,7 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
if (charpos - best_below < best_above - charpos)
{
- int record = charpos - best_below > 5000;
+ bool record = charpos - best_below > 5000;
while (best_below != charpos)
{
@@ -215,7 +215,7 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
}
else
{
- int record = best_above - charpos > 5000;
+ bool record = best_above - charpos > 5000;
while (best_above != charpos)
{
@@ -296,7 +296,7 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos)
ptrdiff_t best_below, best_below_byte;
if (bytepos < BUF_BEG_BYTE (b) || bytepos > BUF_Z_BYTE (b))
- abort ();
+ emacs_abort ();
best_above = BUF_Z (b);
best_above_byte = BUF_Z_BYTE (b);
@@ -335,7 +335,7 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos)
if (bytepos - best_below_byte < best_above_byte - bytepos)
{
- int record = bytepos - best_below_byte > 5000;
+ bool record = bytepos - best_below_byte > 5000;
while (best_below_byte < bytepos)
{
@@ -362,7 +362,7 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos)
}
else
{
- int record = best_above_byte - bytepos > 5000;
+ bool record = best_above_byte - bytepos > 5000;
while (best_above_byte > bytepos)
{
@@ -407,7 +407,7 @@ Returns nil if MARKER points into a dead buffer. */)
does not preserve the buffer from being GC'd (it's weak), so
markers have to be unlinked from their buffer as soon as the buffer
is killed. */
- eassert (!NILP (BVAR (XBUFFER (buf), name)));
+ eassert (BUFFER_LIVE_P (XBUFFER (buf)));
return buf;
}
return Qnil;
@@ -427,7 +427,7 @@ Returns nil if MARKER points nowhere. */)
/* Change M so it points to B at CHARPOS and BYTEPOS. */
-static inline void
+static void
attach_marker (struct Lisp_Marker *m, struct buffer *b,
ptrdiff_t charpos, ptrdiff_t bytepos)
{
@@ -454,7 +454,7 @@ attach_marker (struct Lisp_Marker *m, struct buffer *b,
whether BUFFER is a buffer object and return buffer pointer
corresponding to BUFFER if BUFFER is live, or NULL otherwise. */
-static inline struct buffer *
+static struct buffer *
live_buffer (Lisp_Object buffer)
{
struct buffer *b;
@@ -462,13 +462,13 @@ live_buffer (Lisp_Object buffer)
if (NILP (buffer))
{
b = current_buffer;
- eassert (!NILP (BVAR (b, name)));
+ eassert (BUFFER_LIVE_P (b));
}
else
{
CHECK_BUFFER (buffer);
b = XBUFFER (buffer);
- if (NILP (BVAR (b, name)))
+ if (!BUFFER_LIVE_P (b))
b = NULL;
}
return b;
@@ -477,12 +477,12 @@ live_buffer (Lisp_Object buffer)
/* Internal function to set MARKER in BUFFER at POSITION. Non-zero
RESTRICTED means limit the POSITION by the visible part of BUFFER. */
-static inline Lisp_Object
+static Lisp_Object
set_marker_internal (Lisp_Object marker, Lisp_Object position,
- Lisp_Object buffer, int restricted)
+ Lisp_Object buffer, bool restricted)
{
- register struct Lisp_Marker *m;
- register struct buffer *b = live_buffer (buffer);
+ struct Lisp_Marker *m;
+ struct buffer *b = live_buffer (buffer);
CHECK_MARKER (marker);
m = XMARKER (marker);
@@ -506,7 +506,7 @@ set_marker_internal (Lisp_Object marker, Lisp_Object position,
else
{
register ptrdiff_t charpos, bytepos;
-
+
CHECK_NUMBER_COERCE_MARKER (position);
charpos = clip_to_bounds (restricted ? BUF_BEGV (b) : BUF_BEG (b),
XINT (position),
@@ -570,8 +570,8 @@ set_marker_restricted_both (Lisp_Object marker, Lisp_Object buffer,
if (b)
{
- attach_marker
- (m, b,
+ attach_marker
+ (m, b,
clip_to_bounds (BUF_BEGV (b), charpos, BUF_ZV (b)),
clip_to_bounds (BUF_BEGV_BYTE (b), bytepos, BUF_ZV_BYTE (b)));
}
@@ -595,7 +595,7 @@ unchain_marker (register struct Lisp_Marker *marker)
register struct Lisp_Marker *tail, **prev;
/* No dead buffers here. */
- eassert (!NILP (BVAR (b, name)));
+ eassert (BUFFER_LIVE_P (b));
marker->buffer = NULL;
prev = &BUF_MARKERS (b);
@@ -605,12 +605,12 @@ unchain_marker (register struct Lisp_Marker *marker)
{
if (*prev == BUF_MARKERS (b))
{
- /* Deleting first marker from the buffer's chain. Crash
+ /* Deleting first marker from the buffer's chain. Crash
if new first marker in chain does not say it belongs
to the same buffer, or at least that they have the same
base buffer. */
if (tail->next && b->text != tail->next->buffer->text)
- abort ();
+ emacs_abort ();
}
*prev = tail->next;
/* We have removed the marker from the chain;
diff --git a/src/menu.c b/src/menu.c
index 20770537326..7cc110ce7e2 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include <limits.h> /* for INT_MAX */
#include "lisp.h"
@@ -41,7 +40,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif /* HAVE_WINDOW_SYSTEM */
#ifdef HAVE_NTGUI
+# ifdef NTGUI_UNICODE
+# define unicode_append_menu AppendMenuW
+# else /* !NTGUI_UNICODE */
extern AppendMenuW_Proc unicode_append_menu;
+# endif /* NTGUI_UNICODE */
extern HMENU current_popup_menu;
#endif /* HAVE_NTGUI */
@@ -328,7 +331,7 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk
{
Lisp_Object map, item_string, enabled;
struct gcpro gcpro1, gcpro2;
- int res;
+ bool res;
struct skp *skp = skp_v;
/* Parse the menu item and leave the result in item_properties. */
@@ -516,14 +519,15 @@ list_of_panes (Lisp_Object menu)
/* Set up data in menu_items for a menu bar item
whose event type is ITEM_KEY (with string ITEM_NAME)
and whose contents come from the list of keymaps MAPS. */
-int
-parse_single_submenu (Lisp_Object item_key, Lisp_Object item_name, Lisp_Object maps)
+bool
+parse_single_submenu (Lisp_Object item_key, Lisp_Object item_name,
+ Lisp_Object maps)
{
Lisp_Object length;
EMACS_INT len;
Lisp_Object *mapvec;
ptrdiff_t i;
- int top_level_items = 0;
+ bool top_level_items = 0;
USE_SAFE_ALLOCA;
length = Flength (maps);
@@ -574,9 +578,9 @@ xmalloc_widget_value (void)
{
widget_value *value;
- BLOCK_INPUT;
+ block_input ();
value = malloc_widget_value ();
- UNBLOCK_INPUT;
+ unblock_input ();
return value;
}
@@ -603,9 +607,9 @@ free_menubar_widget_value_tree (widget_value *wv)
free_menubar_widget_value_tree (wv->next);
wv->next = (widget_value *) 0xDEADBEEF;
}
- BLOCK_INPUT;
+ block_input ();
free_widget_value (wv);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Create a tree of widget_value objects
@@ -613,13 +617,13 @@ free_menubar_widget_value_tree (widget_value *wv)
in menu_items starting at index START, up to index END. */
widget_value *
-digest_single_submenu (int start, int end, int top_level_items)
+digest_single_submenu (int start, int end, bool top_level_items)
{
widget_value *wv, *prev_wv, *save_wv, *first_wv;
int i;
int submenu_depth = 0;
widget_value **submenu_stack;
- int panes_seen = 0;
+ bool panes_seen = 0;
submenu_stack = alloca (menu_items_used * sizeof *submenu_stack);
wv = xmalloc_widget_value ();
@@ -665,7 +669,7 @@ digest_single_submenu (int start, int end, int top_level_items)
Lisp_Object pane_name;
const char *pane_string;
- panes_seen++;
+ panes_seen = 1;
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
@@ -732,8 +736,8 @@ digest_single_submenu (int start, int end, int top_level_items)
Lisp_Object help;
/* All items should be contained in panes. */
- if (panes_seen == 0)
- abort ();
+ if (! panes_seen)
+ emacs_abort ();
item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
@@ -807,7 +811,7 @@ digest_single_submenu (int start, int end, int top_level_items)
else if (EQ (type, QCtoggle))
wv->button_type = BUTTON_TYPE_TOGGLE;
else
- abort ();
+ emacs_abort ();
wv->selected = !NILP (selected);
if (! STRINGP (help))
@@ -954,9 +958,9 @@ find_and_call_menu_selection (FRAME_PTR f, int menu_bar_items_used, Lisp_Object
#ifdef HAVE_NS
/* As above, but return the menu selection instead of storing in kb buffer.
- If keymaps==1, return full prefixes to selection. */
+ If KEYMAPS, return full prefixes to selection. */
Lisp_Object
-find_and_return_menu_selection (FRAME_PTR f, int keymaps, void *client_data)
+find_and_return_menu_selection (FRAME_PTR f, bool keymaps, void *client_data)
{
Lisp_Object prefix, entry;
int i;
@@ -996,7 +1000,7 @@ find_and_return_menu_selection (FRAME_PTR f, int keymaps, void *client_data)
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (aref_addr (menu_items, i) == client_data)
{
- if (keymaps != 0)
+ if (keymaps)
{
int j;
@@ -1068,8 +1072,8 @@ no quit occurs and `x-popup-menu' returns nil. */)
Lisp_Object selection = Qnil;
FRAME_PTR f = NULL;
Lisp_Object x, y, window;
- int keymaps = 0;
- int for_click = 0;
+ bool keymaps = 0;
+ bool for_click = 0;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
struct gcpro gcpro1;
@@ -1080,7 +1084,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
#ifdef HAVE_MENUS
{
- int get_current_pos_p = 0;
+ bool get_current_pos_p = 0;
/* FIXME!! check_w32 (); or check_x (); or check_ns (); */
/* Decode the first argument: find the window and the coordinates. */
@@ -1314,7 +1318,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
#endif
/* Display them in a menu. */
- BLOCK_INPUT;
+ block_input ();
/* FIXME: Use a terminal hook! */
#if defined HAVE_NTGUI
@@ -1333,7 +1337,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
last_event_timestamp);
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
#ifdef HAVE_NS
unbind_to (specpdl_count, Qnil);
diff --git a/src/menu.h b/src/menu.h
index 3406928a8d5..67934c42d76 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -29,7 +29,7 @@ extern void init_menu_items (void);
extern void finish_menu_items (void) ATTRIBUTE_CONST;
extern void discard_menu_items (void);
extern void save_menu_items (void);
-extern int parse_single_submenu (Lisp_Object, Lisp_Object, Lisp_Object);
+extern bool parse_single_submenu (Lisp_Object, Lisp_Object, Lisp_Object);
extern void list_of_panes (Lisp_Object);
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS)
@@ -38,7 +38,7 @@ extern void update_submenu_strings (widget_value *);
extern void find_and_call_menu_selection (FRAME_PTR, int,
Lisp_Object, void *);
extern widget_value *xmalloc_widget_value (void);
-extern widget_value *digest_single_submenu (int, int, int);
+extern widget_value *digest_single_submenu (int, int, bool);
#endif
#ifdef HAVE_X_WINDOWS
@@ -47,8 +47,8 @@ extern void mouse_position_for_popup (FRAME_PTR f, int *x, int *y);
extern Lisp_Object w32_menu_show (FRAME_PTR, int, int, int, int,
Lisp_Object, const char **);
-extern Lisp_Object ns_menu_show (FRAME_PTR, int, int, int, int,
+extern Lisp_Object ns_menu_show (FRAME_PTR, int, int, bool, bool,
Lisp_Object, const char **);
-extern Lisp_Object xmenu_show (FRAME_PTR, int, int, int, int,
+extern Lisp_Object xmenu_show (FRAME_PTR, int, int, bool, bool,
Lisp_Object, const char **, Time);
#endif /* MENU_H */
diff --git a/src/minibuf.c b/src/minibuf.c
index 2035a3e3985..dcc4af37c13 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <errno.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "commands.h"
@@ -110,7 +109,7 @@ choose_minibuf_frame (void)
/* I don't think that any frames may validly have a null minibuffer
window anymore. */
if (NILP (sf->minibuffer_window))
- abort ();
+ emacs_abort ();
/* Under X, we come here with minibuf_window being the
minibuffer window of the unused termcap window created in
@@ -174,17 +173,6 @@ without invoking the usual minibuffer commands. */)
static Lisp_Object read_minibuf_unwind (Lisp_Object);
static Lisp_Object run_exit_minibuf_hook (Lisp_Object);
-static Lisp_Object read_minibuf (Lisp_Object, Lisp_Object,
- Lisp_Object,
- int, Lisp_Object,
- Lisp_Object, Lisp_Object,
- int, int);
-static Lisp_Object read_minibuf_noninteractive (Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object,
- int, Lisp_Object,
- Lisp_Object, Lisp_Object,
- int, int);
-static Lisp_Object string_to_object (Lisp_Object, Lisp_Object);
/* Read a Lisp object from VAL and return it. If VAL is an empty
@@ -234,10 +222,10 @@ string_to_object (Lisp_Object val, Lisp_Object defalt)
static Lisp_Object
read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt, Lisp_Object backup_n,
- int expflag,
+ bool expflag,
Lisp_Object histvar, Lisp_Object histpos,
Lisp_Object defalt,
- int allow_props, int inherit_input_method)
+ bool allow_props, bool inherit_input_method)
{
ptrdiff_t size, len;
char *line;
@@ -377,23 +365,23 @@ If the current buffer is not a minibuffer, return its entire contents. */)
beginning of INITIAL if N <= 0.
Normally return the result as a string (the text that was read),
- but if EXPFLAG is nonzero, read it and return the object read.
+ but if EXPFLAG, read it and return the object read.
If HISTVAR is given, save the value read on that history only if it doesn't
match the front of that history list exactly. The value is pushed onto
the list as the string that was read.
DEFALT specifies the default value for the sake of history commands.
- If ALLOW_PROPS is nonzero, we do not throw away text properties.
+ If ALLOW_PROPS, do not throw away text properties.
- if INHERIT_INPUT_METHOD is nonzero, the minibuffer inherits the
+ if INHERIT_INPUT_METHOD, the minibuffer inherits the
current input method. */
static Lisp_Object
read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
- int expflag,
+ bool expflag,
Lisp_Object histvar, Lisp_Object histpos, Lisp_Object defalt,
- int allow_props, int inherit_input_method)
+ bool allow_props, bool inherit_input_method)
{
Lisp_Object val;
ptrdiff_t count = SPECPDL_INDEX ();
@@ -484,6 +472,10 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
/* Choose the minibuffer window and frame, and take action on them. */
+ /* Prepare for restoring the current buffer since choose_minibuf_frame
+ calling Fset_frame_selected_window may change it (Bug#12766). */
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
choose_minibuf_frame ();
record_unwind_protect (choose_minibuf_frame_1, Qnil);
@@ -798,7 +790,7 @@ get_minibuffer (EMACS_INT depth)
Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
}
buf = Fcar (tail);
- if (NILP (buf) || NILP (BVAR (XBUFFER (buf), name)))
+ if (NILP (buf) || !BUFFER_LIVE_P (XBUFFER (buf)))
{
buf = Fget_buffer_create
(make_formatted_string (name, " *Minibuf-%"pI"d*", depth));
@@ -1448,7 +1440,7 @@ is used to further constrain the set of candidates. */)
if (bestmatchsize != SCHARS (eltstring)
|| bestmatchsize != matchsize)
/* Don't count the same string multiple times. */
- matchcount++;
+ matchcount += matchcount <= 1;
bestmatchsize = matchsize;
if (matchsize <= SCHARS (string)
/* If completion-ignore-case is non-nil, don't
@@ -1704,7 +1696,7 @@ If INITIAL-INPUT is non-nil, insert it in the minibuffer initially,
functions, which use one-indexing for POSITION.) This feature is
deprecated--it is best to pass nil for INITIAL-INPUT and supply the
default value DEF instead. The user can yank the default value into
- the minibuffer easily using \\[next-history-element].
+ the minibuffer easily using \\<minibuffer-local-map>\\[next-history-element].
HIST, if non-nil, specifies a history list and optionally the initial
position in the list. It can be a symbol, which is the history list
@@ -1863,11 +1855,11 @@ static Lisp_Object Qmetadata;
DEFUN ("internal-complete-buffer", Finternal_complete_buffer, Sinternal_complete_buffer, 3, 3, 0,
doc: /* Perform completion on buffer names.
-If the argument FLAG is nil, invoke `try-completion', if it's t, invoke
-`all-completions', otherwise invoke `test-completion'.
+STRING and PREDICATE have the same meanings as in `try-completion',
+`all-completions', and `test-completion'.
-The arguments STRING and PREDICATE are as in `try-completion',
-`all-completions', and `test-completion'. */)
+If FLAG is nil, invoke `try-completion'; if it is t, invoke
+`all-completions'; otherwise invoke `test-completion'. */)
(Lisp_Object string, Lisp_Object predicate, Lisp_Object flag)
{
if (NILP (flag))
diff --git a/src/msdos.c b/src/msdos.c
index ac348e94375..433bf1074d8 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -796,7 +796,7 @@ IT_set_face (int face)
/* The default face for the frame should always be realized and
cached. */
if (!fp)
- abort ();
+ emacs_abort ();
}
screen_face = face;
fg = fp->foreground;
@@ -1229,7 +1229,7 @@ IT_update_begin (struct frame *f)
if (display_info->termscript)
fprintf (display_info->termscript, "\n\n<UPDATE_BEGIN");
- BLOCK_INPUT;
+ block_input ();
if (f && f == mouse_face_frame)
{
@@ -1275,11 +1275,10 @@ IT_update_begin (struct frame *f)
hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_window = Qnil;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_mouse_frame = NULL;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
static void
@@ -1295,21 +1294,10 @@ IT_update_end (struct frame *f)
static void
IT_frame_up_to_date (struct frame *f)
{
- Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
Lisp_Object new_cursor, frame_desired_cursor;
struct window *sw;
- if (hlinfo->mouse_face_deferred_gc
- || (f && f == hlinfo->mouse_face_mouse_frame))
- {
- BLOCK_INPUT;
- if (hlinfo->mouse_face_mouse_frame)
- note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
- hlinfo->mouse_face_mouse_x,
- hlinfo->mouse_face_mouse_y);
- hlinfo->mouse_face_deferred_gc = 0;
- UNBLOCK_INPUT;
- }
+ FRAME_MOUSE_UPDATE (f);
/* Set the cursor type to whatever they wanted. In a minibuffer
window, we want the cursor to appear only if we are reading input
@@ -1393,7 +1381,7 @@ IT_insert_glyphs (struct frame *f, struct glyph *start, int len)
static void
IT_delete_glyphs (struct frame *f, int n)
{
- abort ();
+ emacs_abort ();
}
/* set-window-configuration on window.c needs this. */
@@ -1849,7 +1837,6 @@ internal_terminal_init (void)
FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = colors[1];
}
the_only_display_info.mouse_highlight.mouse_face_mouse_frame = NULL;
- the_only_display_info.mouse_highlight.mouse_face_deferred_gc = 0;
the_only_display_info.mouse_highlight.mouse_face_beg_row =
the_only_display_info.mouse_highlight.mouse_face_beg_col = -1;
the_only_display_info.mouse_highlight.mouse_face_end_row =
@@ -3013,7 +3000,7 @@ XMenuAddPane (Display *foo, XMenu *menu, const char *txt, int enable)
const char *p;
if (!enable)
- abort ();
+ emacs_abort ();
IT_menu_make_room (menu);
menu->submenu[menu->count] = IT_menu_create ();
@@ -3305,7 +3292,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
Emacs will process them after we return and surprise the user. */
discard_mouse_events ();
mouse_clear_clicks ();
- if (!kbd_buffer_events_waiting (1))
+ if (!kbd_buffer_events_waiting ())
clear_input_pending ();
/* Allow mouse events generation by dos_rawgetc. */
mouse_preempted--;
@@ -3927,8 +3914,10 @@ croak (char *badfunc)
/*
* A few unimplemented functions that we silently ignore.
*/
-int setpgrp (void) {return 0; }
+pid_t tcgetpgrp (int fd) { return 0; }
+int setpgid (int pid, int pgid) { return 0; }
int setpriority (int x, int y, int z) { return 0; }
+pid_t setsid (void) { return 0; }
#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
ssize_t
@@ -4119,7 +4108,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
FD_ZERO (efds);
if (nfds != 1)
- abort ();
+ emacs_abort ();
/* If we are looking only for the terminal, with no timeout,
just read it and wait -- that's more efficient. */
@@ -4214,26 +4203,8 @@ init_gettimeofday (void)
}
#endif
-#ifdef abort
-#undef abort
-void
-dos_abort (char *file, int line)
-{
- char buffer1[200], buffer2[400];
- int i, j;
-
- sprintf (buffer1, "<EMACS FATAL ERROR IN %s LINE %d>", file, line);
- for (i = j = 0; buffer1[i]; i++) {
- buffer2[j++] = buffer1[i];
- buffer2[j++] = 0x70;
- }
- dosmemput (buffer2, j, (int)ScreenPrimary);
- ScreenSetCursor (2, 0);
- abort ();
-}
-#else
-void
-abort (void)
+static void
+msdos_abort (void)
{
dos_ttcooked ();
ScreenSetCursor (10, 0);
@@ -4249,7 +4220,15 @@ abort (void)
#endif /* __DJGPP_MINOR__ >= 2 */
exit (2);
}
-#endif
+
+void
+msdos_fatal_signal (int sig)
+{
+ if (sig == SIGABRT)
+ msdos_abort ();
+ else
+ raise (sig);
+}
void
syms_of_msdos (void)
diff --git a/src/ndir.h b/src/ndir.h
deleted file mode 100644
index cd7cdbe55f5..00000000000
--- a/src/ndir.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- <dir.h> -- definitions for 4.2BSD-compatible directory access
-
- last edit: 09-Jul-1983 D A Gwyn
-
- * The code here is forced by the interface, and is not subject to
- * copyright, constituting the only possible expression of the
- * algorithm in this format.
- */
-
-#define DIRBLKSIZ 512 /* size of directory block */
-#ifdef WINDOWSNT
-#define MAXNAMLEN 255
-#else /* not WINDOWSNT */
-#define MAXNAMLEN 15 /* maximum filename length */
-#endif /* not WINDOWSNT */
- /* NOTE: MAXNAMLEN must be one less than a multiple of 4 */
-
-struct direct /* data from readdir() */
- {
- long d_ino; /* inode number of entry */
- unsigned short d_reclen; /* length of this record */
- unsigned short d_namlen; /* length of string in d_name */
- char d_name[MAXNAMLEN+1]; /* name of file */
- };
-
-typedef struct
- {
- int dd_fd; /* file descriptor */
- int dd_loc; /* offset in block */
- int dd_size; /* amount of valid data */
- char dd_buf[DIRBLKSIZ]; /* directory block */
- } DIR; /* stream data from opendir() */
-
-extern DIR *opendir (char *);
-extern struct direct *readdir (DIR *);
-extern void seekdir (DIR *, long);
-extern void closedir (DIR *);
-
-#define rewinddir( dirp ) seekdir( dirp, 0L )
-
diff --git a/src/ns.mk b/src/ns.mk
deleted file mode 100644
index 77fbf5845d9..00000000000
--- a/src/ns.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-### autodeps.mk --- src/Makefile fragment for GNU Emacs
-
-## Copyright (C) 2008-2012 Free Software Foundation, Inc.
-
-## 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 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/>.
-
-### Commentary:
-
-## This is inserted in src/Makefile if HAVE_NS.
-
-## The only reason this is in a separate file is because $ns_appdir,
-## which appears as a target, is empty on non-NS builds. Some makes
-## do not like empty targets, even if they are never used.
-
-${ns_appdir}: ${ns_appsrc}
- rm -fr ${ns_appdir}
- ${MKDIR_P} ${ns_appdir}
- ( cd ${ns_appsrc} ; tar cfh - . ) | ( cd ${ns_appdir} ; umask 022; tar xf - )
-
-${ns_appbindir}/Emacs: emacs${EXEEXT}
- ${MKDIR_P} ${ns_appbindir}
- cp -f emacs${EXEEXT} ${ns_appbindir}/Emacs
-
-ns-app: ${ns_appdir} ${ns_appbindir}/Emacs
-
-### ns.mk ends here
diff --git a/src/nsfns.m b/src/nsfns.m
index e8b5d22077a..428cfcb9a10 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -30,9 +30,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
interpretation of even the system includes. */
#include <config.h>
-#include <signal.h>
#include <math.h>
-#include <setjmp.h>
#include <c-strcase.h>
#include "lisp.h"
@@ -95,8 +93,6 @@ EmacsTooltip *ns_tooltip;
/* Need forward declaration here to preserve organizational integrity of file */
Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
-extern BOOL ns_in_resize;
-
/* Static variables to handle applescript execution. */
static Lisp_Object as_script, *as_result;
static int as_status;
@@ -435,9 +431,6 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
NSView *view = FRAME_NS_VIEW (f);
NSTRACE (x_set_icon_name);
- if (ns_in_resize)
- return;
-
/* see if it's changed */
if (STRINGP (arg))
{
@@ -513,9 +506,6 @@ ns_set_name (struct frame *f, Lisp_Object name, int explicit)
{
NSTRACE (ns_set_name);
- if (ns_in_resize)
- return;
-
/* Make sure that requests from lisp code override requests from
Emacs redisplay code. */
if (explicit)
@@ -614,10 +604,10 @@ ns_set_name_as_filename (struct frame *f)
NSString *str;
NSTRACE (ns_set_name_as_filename);
- if (f->explicit_name || ! NILP (f->title) || ns_in_resize)
+ if (f->explicit_name || ! NILP (f->title))
return;
- BLOCK_INPUT;
+ block_input ();
pool = [[NSAutoreleasePool alloc] init];
filename = BVAR (XBUFFER (buf), filename);
name = BVAR (XBUFFER (buf), name);
@@ -642,7 +632,7 @@ ns_set_name_as_filename (struct frame *f)
if (title && (! strcmp (title, SSDATA (encoded_name))))
{
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
@@ -680,7 +670,7 @@ ns_set_name_as_filename (struct frame *f)
}
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -691,11 +681,11 @@ ns_set_doc_edited (struct frame *f, Lisp_Object arg)
NSAutoreleasePool *pool;
if (!MINI_WINDOW_P (XWINDOW (f->selected_window)))
{
- BLOCK_INPUT;
+ block_input ();
pool = [[NSAutoreleasePool alloc] init];
[[view window] setDocumentEdited: !NILP (arg)];
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -773,14 +763,14 @@ ns_implicitly_set_icon_type (struct frame *f)
NSTRACE (ns_implicitly_set_icon_type);
- BLOCK_INPUT;
+ block_input ();
pool = [[NSAutoreleasePool alloc] init];
if (f->output_data.ns->miniimage
&& [[NSString stringWithUTF8String: SSDATA (f->name)]
isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
{
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
@@ -788,7 +778,7 @@ ns_implicitly_set_icon_type (struct frame *f)
if (CONSP (tem) && ! NILP (XCDR (tem)))
{
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
@@ -828,7 +818,7 @@ ns_implicitly_set_icon_type (struct frame *f)
f->output_data.ns->miniimage = image;
[view setMiniwindowImage: setMini];
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -872,16 +862,6 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
-/* Xism; we stub out (we do implement this in ns-win.el) */
-int
-XParseGeometry (char *string, int *x, int *y,
- unsigned int *width, unsigned int *height)
-{
- message1 ("Warning: XParseGeometry not supported under NS.\n");
- return 0;
-}
-
-
/* TODO: move to nsterm? */
int
ns_lisp_to_cursor_type (Lisp_Object arg)
@@ -1030,7 +1010,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
x_set_fringe_width, /* generic OK */
x_set_fringe_width, /* generic OK */
0, /* x_set_wait_for_wm, will ignore */
- 0, /* x_set_fullscreen will ignore */
+ x_set_fullscreen, /* generic OK */
x_set_font_backend, /* generic OK */
x_set_alpha,
0, /* x_set_sticky */
@@ -1195,7 +1175,6 @@ This function is an internal primitive--use `make-frame' instead. */)
f = make_frame (1);
XSETFRAME (frame, f);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
f->terminal = dpyinfo->terminal;
@@ -1244,7 +1223,7 @@ This function is an internal primitive--use `make-frame' instead. */)
f->resx = dpyinfo->resx;
f->resy = dpyinfo->resy;
- BLOCK_INPUT;
+ block_input ();
register_font_driver (&nsfont_driver, f);
x_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
@@ -1259,7 +1238,7 @@ This function is an internal primitive--use `make-frame' instead. */)
build_string ([[font fontName] UTF8String]),
"font", "Font", RES_TYPE_STRING);
}
- UNBLOCK_INPUT;
+ unblock_input ();
x_default_parameter (f, parms, Qborder_width, make_number (0),
"borderwidth", "BorderWidth", RES_TYPE_NUMBER);
@@ -1358,6 +1337,8 @@ This function is an internal primitive--use `make-frame' instead. */)
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_COLS (f);
height = FRAME_LINES (f);
@@ -1401,6 +1382,9 @@ This function is an internal primitive--use `make-frame' instead. */)
UNGCPRO;
+ if (window_prompting & USPosition)
+ x_set_offset (f, f->left_pos, f->top_pos, 1);
+
/* Make sure windows on this frame appear in calls to next-window
and similar functions. */
Vwindow_list = Qnil;
@@ -1420,10 +1404,10 @@ FRAME nil means use the selected frame. */)
if (dpyinfo->x_focus_frame != f)
{
EmacsView *view = FRAME_NS_VIEW (f);
- BLOCK_INPUT;
+ block_input ();
[NSApp activateIgnoringOtherApps: YES];
[[view window] makeKeyAndOrderFront: view];
- UNBLOCK_INPUT;
+ unblock_input ();
}
return Qnil;
@@ -1476,13 +1460,15 @@ DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
}
-DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0,
+DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
Optional arg DIR, if non-nil, supplies a default directory.
Optional arg MUSTMATCH, if non-nil, means the returned file or
directory must exist.
-Optional arg INIT, if non-nil, provides a default file name to use. */)
- (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch, Lisp_Object init)
+Optional arg INIT, if non-nil, provides a default file name to use.
+Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
+ (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
+ Lisp_Object init, Lisp_Object dir_only_p)
{
static id fileDelegate = nil;
int ret;
@@ -1507,21 +1493,36 @@ Optional arg INIT, if non-nil, provides a default file name to use. */)
if ([dirS characterAtIndex: 0] == '~')
dirS = [dirS stringByExpandingTildeInPath];
- panel = NILP (mustmatch) ?
+ panel = NILP (mustmatch) && NILP (dir_only_p) ?
(id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
[panel setTitle: promptS];
- /* Puma (10.1) does not have */
- if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)])
- [panel setAllowsOtherFileTypes: YES];
-
+ [panel setAllowsOtherFileTypes: YES];
[panel setTreatsFilePackagesAsDirectories: YES];
[panel setDelegate: fileDelegate];
panelOK = 0;
- BLOCK_INPUT;
- if (NILP (mustmatch))
+ if (! NILP (dir_only_p))
+ {
+ [panel setCanChooseDirectories: YES];
+ [panel setCanChooseFiles: NO];
+ }
+
+ block_input ();
+#if defined (NS_IMPL_COCOA) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ if (! NILP (mustmatch) || ! NILP (dir_only_p))
+ [panel setAllowedFileTypes: nil];
+ if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
+ if (initS && NILP (Ffile_directory_p (init)))
+ [panel setNameFieldStringValue: [initS lastPathComponent]];
+ else
+ [panel setNameFieldStringValue: @""];
+
+ ret = [panel runModal];
+#else
+ if (NILP (mustmatch) && NILP (dir_only_p))
{
ret = [panel runModalForDirectory: dirS file: initS];
}
@@ -1530,6 +1531,7 @@ Optional arg INIT, if non-nil, provides a default file name to use. */)
[panel setCanChooseDirectories: YES];
ret = [panel runModalForDirectory: dirS file: initS types: nil];
}
+#endif
ret = (ret == NSOKButton) || panelOK;
@@ -1537,7 +1539,7 @@ Optional arg INIT, if non-nil, provides a default file name to use. */)
fname = build_string ([[panel filename] UTF8String]);
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
- UNBLOCK_INPUT;
+ unblock_input ();
return ret ? fname : Qnil;
}
@@ -1798,19 +1800,6 @@ terminate Emacs if we can't open the connection.
SSDATA (display));
}
- /* Register our external input/output types, used for determining
- applicable services and also drag/drop eligibility. */
- ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
- ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
- retain];
- ns_drag_types = [[NSArray arrayWithObjects:
- NSStringPboardType,
- NSTabularTextPboardType,
- NSFilenamesPboardType,
- NSURLPboardType,
- NSColorPboardType,
- NSFontPboardType, nil] retain];
-
return Qnil;
}
@@ -1921,7 +1910,7 @@ The optional argument FRAME is currently ignored. */)
error ("non-Nextstep frame used in `ns-list-colors'");
}
- BLOCK_INPUT;
+ block_input ();
colorlists = [[NSColorList availableColorLists] objectEnumerator];
while ((clist = [colorlists nextObject]))
@@ -1939,7 +1928,7 @@ The optional argument FRAME is currently ignored. */)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return list;
}
@@ -1959,32 +1948,29 @@ DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
check_ns ();
svcs = [[NSMenu alloc] initWithTitle: @"Services"];
- [NSApp setServicesMenu: svcs]; /* this and next rebuild on <10.4 */
+ [NSApp setServicesMenu: svcs];
[NSApp registerServicesMenuSendTypes: ns_send_types
returnTypes: ns_return_types];
/* On Tiger, services menu updating was made lazier (waits for user to
actually click on the menu), so we have to force things along: */
#ifdef NS_IMPL_COCOA
- if (NSAppKitVersionNumber >= 744.0)
+ delegate = [svcs delegate];
+ if (delegate != nil)
{
- delegate = [svcs delegate];
- if (delegate != nil)
+ if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
+ [delegate menuNeedsUpdate: svcs];
+ if ([delegate respondsToSelector:
+ @selector (menu:updateItem:atIndex:shouldCancel:)])
{
- if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
- [delegate menuNeedsUpdate: svcs];
- if ([delegate respondsToSelector:
- @selector (menu:updateItem:atIndex:shouldCancel:)])
- {
- int i, len = [delegate numberOfItemsInMenu: svcs];
- for (i =0; i<len; i++)
- [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
- for (i =0; i<len; i++)
- if (![delegate menu: svcs
- updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
- atIndex: i shouldCancel: NO])
- break;
- }
+ int i, len = [delegate numberOfItemsInMenu: svcs];
+ for (i =0; i<len; i++)
+ [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
+ for (i =0; i<len; i++)
+ if (![delegate menu: svcs
+ updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
+ atIndex: i shouldCancel: NO])
+ break;
}
}
#endif
@@ -2085,7 +2071,7 @@ ns_do_applescript (Lisp_Object script, Lisp_Object *result)
*result = Qt;
// script returned an AppleScript result
if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+#if defined (NS_IMPL_COCOA)
(typeUTF16ExternalRepresentation
== [returnDescriptor descriptorType]) ||
#endif
@@ -2137,7 +2123,7 @@ In case the execution fails, an error is signaled. */)
CHECK_STRING (script);
check_ns ();
- BLOCK_INPUT;
+ block_input ();
as_script = script;
as_result = &result;
@@ -2163,7 +2149,7 @@ In case the execution fails, an error is signaled. */)
as_status = 0;
as_script = Qnil;
as_result = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
if (status == 0)
return result;
else if (!STRINGP (result))
@@ -2257,20 +2243,6 @@ x_pixel_height (struct frame *f)
int
-x_char_width (struct frame *f)
-{
- return FRAME_COLUMN_WIDTH (f);
-}
-
-
-int
-x_char_height (struct frame *f)
-{
- return FRAME_LINE_HEIGHT (f);
-}
-
-
-int
x_screen_planes (struct frame *f)
{
return FRAME_NS_DISPLAY_INFO (f)->n_planes;
@@ -2570,7 +2542,7 @@ Text larger than the specified size is clipped. */)
else
CHECK_NUMBER (dy);
- BLOCK_INPUT;
+ block_input ();
if (ns_tooltip == nil)
ns_tooltip = [[EmacsTooltip alloc] init];
else
@@ -2585,7 +2557,7 @@ Text larger than the specified size is clipped. */)
&root_x, &root_y);
[ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
- UNBLOCK_INPUT;
+ unblock_input ();
UNGCPRO;
return unbind_to (count, Qnil);
diff --git a/src/nsfont.m b/src/nsfont.m
index 412a6777c64..2ba38b7570e 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -23,7 +23,6 @@ Author: 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. */
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
#include "dispextern.h"
@@ -47,13 +46,15 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu)
#define NSFONT_TRACE 0
extern Lisp_Object Qns;
-extern Lisp_Object Qnormal, Qbold, Qitalic, Qcondensed, Qexpanded;
+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;
extern int ns_tmp_flags;
extern struct nsfont_info *ns_tmp_font;
+
/* font glyph and metrics caching functions, implemented at end */
static void ns_uni_to_glyphs (struct nsfont_info *font_info,
unsigned char block);
@@ -201,8 +202,8 @@ ns_descriptor_to_entity (NSFontDescriptor *desc,
make_number (100 + 100
* ns_attribute_fvalue (desc, NSFontSlantTrait)));*/
FONT_SET_STYLE (font_entity, FONT_WIDTH_INDEX,
- traits & NSFontCondensedTrait ? Qcondensed :
- traits & NSFontExpandedTrait ? Qexpanded : Qnormal);
+ traits & NSFontCondensedTrait ? Qcondensed :
+ traits & NSFontExpandedTrait ? Qexpanded : Qnormal);
/* FONT_SET_STYLE (font_entity, FONT_WIDTH_INDEX,
make_number (100 + 100
* ns_attribute_fvalue (desc, NSFontWidthTrait)));*/
@@ -559,7 +560,11 @@ ns_findfonts (Lisp_Object font_spec, BOOL isMatch)
if (isMatch)
[fkeys removeObject: NSFontFamilyAttribute];
- matchingDescs = [fdesc matchingFontDescriptorsWithMandatoryKeys: fkeys];
+ if ([fkeys count] > 0)
+ matchingDescs = [fdesc matchingFontDescriptorsWithMandatoryKeys: fkeys];
+ else
+ matchingDescs = [NSMutableArray array];
+
if (NSFONT_TRACE)
NSLog(@"Got desc %@ and found %d matching fonts from it: ", fdesc,
[matchingDescs count]);
@@ -625,7 +630,7 @@ 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 int nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
- int with_background);
+ bool with_background);
struct font_driver nsfont_driver =
{
@@ -729,16 +734,6 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
NSRect brect;
Lisp_Object font_object;
int fixLeopardBug;
- static NSMutableDictionary *fontCache = nil;
- NSNumber *cached;
-
- /* 2008/03/08: The same font may end up being requested for different
- entities, due to small differences in numeric values or other issues,
- or for different copies of the same entity. Therefore we cache to
- avoid creating multiple struct font objects (with metrics cache, etc.)
- for the same NSFont object. */
- if (fontCache == nil)
- fontCache = [[NSMutableDictionary alloc] init];
if (NSFONT_TRACE)
{
@@ -794,26 +789,8 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
if (NSFONT_TRACE)
NSLog (@"%@\n", nsfont);
- /* Check the cache */
- cached = [fontCache objectForKey: nsfont];
- if (cached != nil && !synthItal)
- {
- if (NSFONT_TRACE)
- fprintf(stderr, "*** nsfont_open CACHE HIT!\n");
- /* FIXME: Cast from (unsigned long) to Lisp_Object. */
- XHASH (font_object) = [cached unsignedLongValue];
- return font_object;
- }
- else
- {
- font_object = font_make_object (VECSIZE (struct nsfont_info),
- font_entity, pixel_size);
- if (!synthItal)
- [fontCache setObject: [NSNumber numberWithUnsignedLong:
- (unsigned long) XHASH (font_object)]
- forKey: nsfont];
- }
-
+ font_object = font_make_object (VECSIZE (struct nsfont_info),
+ font_entity, pixel_size);
font_info = (struct nsfont_info *) XFONT_OBJECT (font_object);
font = (struct font *) font_info;
if (!font)
@@ -822,10 +799,16 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
font_info->glyphs = xzalloc (0x100 * sizeof *font_info->glyphs);
font_info->metrics = xzalloc (0x100 * sizeof *font_info->metrics);
- BLOCK_INPUT;
+ block_input ();
/* for metrics */
+#ifdef NS_IMPL_COCOA
+ sfont = [nsfont screenFontWithRenderingMode:
+ NSFontAntialiasedIntegerAdvancementsRenderingMode];
+#else
sfont = [nsfont screenFont];
+#endif
+
if (sfont == nil)
sfont = nsfont;
@@ -833,7 +816,6 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
font = (struct font *) font_info;
font->pixel_size = [sfont pointSize];
font->driver = &nsfont_driver;
- font->encoding_type = FONT_ENCODING_NOT_DECIDED;
font->encoding_charset = -1;
font->repertory_charset = -1;
font->default_ascent = 0;
@@ -934,7 +916,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
font->props[FONT_FULLNAME_INDEX] =
make_unibyte_string (font_info->name, strlen (font_info->name));
}
- UNBLOCK_INPUT;
+ unblock_input ();
return font_object;
}
@@ -1042,12 +1024,12 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs,
/* Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
- position of frame F with S->FACE and S->GC. If WITH_BACKGROUND
- is nonzero, fill the background in advance. It is assured that
- WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars). */
+ position of frame F with S->FACE and S->GC. If WITH_BACKGROUND,
+ fill the background in advance. It is assured that WITH_BACKGROUND
+ is false when (FROM > 0 || TO < S->nchars). */
static int
nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
- int with_background)
+ bool with_background)
/* NOTE: focus and clip must be set
also, currently assumed (true in nsterm.m call) from ==0, to ==nchars */
{
@@ -1258,6 +1240,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
else
CGContextSetShouldAntialias (gcontext, 1);
+ CGContextSetShouldSmoothFonts (gcontext, NO);
CGContextSetTextMatrix (gcontext, fliptf);
if (bgCol != nil)
@@ -1318,7 +1301,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block)
fprintf (stderr, "%p\tFinding glyphs for glyphs in block %d\n",
font_info, block);
- BLOCK_INPUT;
+ block_input ();
#ifdef NS_IMPL_COCOA
if (firstTime)
@@ -1330,7 +1313,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block)
font_info->glyphs[block] = xmalloc (0x100 * sizeof (unsigned short));
if (!unichars || !(font_info->glyphs[block]))
- abort ();
+ emacs_abort ();
/* create a string containing all Unicode characters in this block */
for (idx = block<<8, i = 0; i < 0x100; idx++, i++)
@@ -1375,7 +1358,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block)
#endif
}
- UNBLOCK_INPUT;
+ unblock_input ();
xfree (unichars);
}
@@ -1400,12 +1383,17 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
numGlyphs = 0x10000;
#endif
- BLOCK_INPUT;
- sfont = [font_info->nsfont screenFont];
+ block_input ();
+#ifdef NS_IMPL_COCOA
+ sfont = [font_info->nsfont screenFontWithRenderingMode:
+ NSFontAntialiasedIntegerAdvancementsRenderingMode];
+#else
+ sfont = [font_info->nsfont screenFont];
+#endif
font_info->metrics[block] = xzalloc (0x100 * sizeof (struct font_metrics));
if (!(font_info->metrics[block]))
- abort ();
+ emacs_abort ();
metrics = font_info->metrics[block];
for (g = block<<8, i =0; i<0x100 && g < numGlyphs; g++, i++, metrics++)
@@ -1429,7 +1417,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
metrics->ascent = r.size.height - metrics->descent;
/*-lrint (hshrink* [sfont descender] - expand * hd/2); */
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1524,6 +1512,8 @@ syms_of_nsfont (void)
{
nsfont_driver.type = Qns;
register_font_driver (&nsfont_driver, NULL);
+ DEFSYM (Qcondensed, "condensed");
+ DEFSYM (Qexpanded, "expanded");
DEFSYM (Qapple, "apple");
DEFSYM (Qroman, "roman");
DEFSYM (Qmedium, "medium");
diff --git a/src/nsimage.m b/src/nsimage.m
index 8a8a3ddaae4..884c0763fd4 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -28,7 +28,6 @@ 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. */
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
#include "dispextern.h"
@@ -79,7 +78,7 @@ ns_image_from_file (Lisp_Object file)
return [EmacsImage allocInitFromFile: file];
}
-int
+bool
ns_load_image (struct frame *f, struct image *img,
Lisp_Object spec_file, Lisp_Object spec_data)
{
@@ -404,7 +403,6 @@ static EmacsImage *ImageList = nil;
if ([rep respondsToSelector: @selector (getBitmapDataPlanes:)])
{
bmRep = (NSBitmapImageRep *) rep;
- onTiger = [bmRep respondsToSelector: @selector (colorAtX:y:)];
if ([bmRep numberOfPlanes] >= 3)
[bmRep getBitmapDataPlanes: pixmapData];
@@ -436,7 +434,7 @@ static EmacsImage *ImageList = nil;
| (pixmapData[0][loc] << 16) | (pixmapData[1][loc] << 8)
| (pixmapData[2][loc]);
}
- else if (onTiger)
+ else
{
NSColor *color = [bmRep colorAtX: x y: y];
CGFloat r, g, b, a;
@@ -446,7 +444,6 @@ static EmacsImage *ImageList = nil;
| ((int)(b * 255.0));
}
- return 0;
}
- (void) setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r
@@ -464,7 +461,7 @@ static EmacsImage *ImageList = nil;
pixmapData[2][loc] = b;
pixmapData[3][loc] = a;
}
- else if (onTiger)
+ else
{
[bmRep setColor:
[NSColor colorWithCalibratedRed: (r/255.0) green: (g/255.0)
@@ -484,7 +481,7 @@ static EmacsImage *ImageList = nil;
pixmapData[3][loc] = a;
}
- else if (onTiger)
+ else
{
NSColor *color = [bmRep colorAtX: x y: y];
color = [color colorWithAlphaComponent: (a / 255.0)];
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 9e290486213..d0ea8f5a47a 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -24,7 +24,6 @@ Carbon version by Yamamoto Mitsuharu. */
/* This should be the first include, as it may set up #defines affecting
interpretation of even the system includes. */
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
#include "window.h"
@@ -116,21 +115,20 @@ popup_activated (void)
/* --------------------------------------------------------------------------
Update menubar. Three cases:
- 1) deep_p = 0, submenu = nil: Fresh switch onto a frame -- either set up
+ 1) ! deep_p, submenu = nil: Fresh switch onto a frame -- either set up
just top-level menu strings (OS X), or goto case (2) (GNUstep).
- 2) deep_p = 1, submenu = nil: Recompute all submenus.
- 3) deep_p = 1, submenu = non-nil: Update contents of a single submenu.
+ 2) deep_p, submenu = nil: Recompute all submenus.
+ 3) deep_p, submenu = non-nil: Update contents of a single submenu.
-------------------------------------------------------------------------- */
void
-ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
+ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
{
NSAutoreleasePool *pool;
id menu = [NSApp mainMenu];
static EmacsMenu *last_submenu = nil;
BOOL needsSet = NO;
const char *submenuTitle = [[submenu title] UTF8String];
- extern int waiting_for_input;
- int owfi;
+ bool owfi;
Lisp_Object items;
widget_value *wv, *first_wv, *prev_wv = 0;
int i;
@@ -147,7 +145,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
XSETFRAME (Vmenu_updating_frame, f);
/*fprintf (stderr, "ns_update_menubar: frame: %p\tdeep: %d\tsub: %p\n", f, deep_p, submenu); */
- BLOCK_INPUT;
+ block_input ();
pool = [[NSAutoreleasePool alloc] init];
/* Menu may have been created automatically; if so, discard it. */
@@ -183,7 +181,8 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
/* Fully parse one or more of the submenus. */
int n = 0;
int *submenu_start, *submenu_end;
- int *submenu_top_level_items, *submenu_n_panes;
+ bool *submenu_top_level_items;
+ int *submenu_n_panes;
struct buffer *prev = current_buffer;
Lisp_Object buffer;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
@@ -272,7 +271,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
discard_menu_items ();
unbind_to (specpdl_count, Qnil);
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
@@ -334,7 +333,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
discard_menu_items ();
unbind_to (specpdl_count, Qnil);
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
}
@@ -405,7 +404,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
{
free_menubar_widget_value_tree (first_wv);
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
@@ -436,7 +435,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
{
free_menubar_widget_value_tree (first_wv);
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
}
@@ -499,7 +498,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
[NSApp setMainMenu: menu];
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -508,7 +507,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
frame's menus have changed, and the *step representation should be updated
from Lisp. */
void
-set_frame_menubar (struct frame *f, int first_time, int deep_p)
+set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
{
ns_update_menubar (f, deep_p, nil);
}
@@ -589,10 +588,7 @@ extern NSString *NSMenuDidBeginTrackingNotification;
From 10.6 on, we could also use -[NSMenu propertiesToUpdate]: In the
key press case, NSMenuPropertyItemImage (e.g.) won't be set.
*/
- if (trackingMenu == 0
- /* Also, don't try this if from an event picked up asynchronously,
- as lots of lisp evaluation happens in ns_update_menubar. */
- || handling_signal != 0)
+ if (trackingMenu == 0)
return;
/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
ns_update_menubar (frame, 1, self);
@@ -726,11 +722,6 @@ extern NSString *NSMenuDidBeginTrackingNotification;
#ifdef NS_IMPL_GNUSTEP
if ([[self window] isVisible])
[self sizeToFit];
-#else
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_2
- if ([self supermenu] == nil)
- [self sizeToFit];
-#endif
#endif
}
@@ -750,7 +741,7 @@ extern NSString *NSMenuDidBeginTrackingNotification;
/* run a menu in popup mode */
- (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
- keymaps: (int)keymaps
+ keymaps: (bool)keymaps
{
EmacsView *view = FRAME_NS_VIEW (f);
NSEvent *e, *event;
@@ -789,7 +780,7 @@ extern NSString *NSMenuDidBeginTrackingNotification;
========================================================================== */
Lisp_Object
-ns_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
Lisp_Object title, const char **error)
{
EmacsMenu *pmenu;
@@ -811,7 +802,7 @@ ns_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
#if 0
/* FIXME: a couple of one-line differences prevent reuse */
- wv = digest_single_submenu (0, menu_items_used, Qnil);
+ wv = digest_single_submenu (0, menu_items_used, 0);
#else
{
widget_value *save_wv = 0, *prev_wv = 0;
@@ -948,7 +939,7 @@ ns_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
else if (EQ (type, QCradio))
wv->button_type = BUTTON_TYPE_RADIO;
else
- abort ();
+ emacs_abort ();
wv->selected = !NILP (selected);
@@ -1016,10 +1007,10 @@ free_frame_tool_bar (FRAME_PTR f)
Under NS we just hide the toolbar until it might be needed again.
-------------------------------------------------------------------------- */
{
- BLOCK_INPUT;
+ block_input ();
[[FRAME_NS_VIEW (f) toolbar] setVisible: NO];
FRAME_TOOLBAR_HEIGHT (f) = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
void
@@ -1033,7 +1024,7 @@ update_frame_tool_bar (FRAME_PTR f)
NSWindow *window = [view window];
EmacsToolbar *toolbar = [view toolbar];
- BLOCK_INPUT;
+ block_input ();
[toolbar clearActive];
/* update EmacsToolbar as in GtkUtils, build items list */
@@ -1119,7 +1110,7 @@ update_frame_tool_bar (FRAME_PTR f)
FRAME_TOOLBAR_HEIGHT (f) =
NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
- FRAME_NS_TITLEBAR_HEIGHT (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1359,7 +1350,7 @@ pop_down_menu (Lisp_Object arg)
struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
struct Popdown_data *unwind_data = (struct Popdown_data *) p->pointer;
- BLOCK_INPUT;
+ block_input ();
if (popup_activated_flag)
{
EmacsDialogPanel *panel = unwind_data->dialog;
@@ -1370,7 +1361,7 @@ pop_down_menu (Lisp_Object arg)
}
xfree (unwind_data);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -1438,7 +1429,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
the dialog. */
contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
- BLOCK_INPUT;
+ block_input ();
pool = [[NSAutoreleasePool alloc] init];
dialog = [[EmacsDialogPanel alloc] initFromContents: contents
isQuestion: isQ];
@@ -1456,7 +1447,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */
}
- UNBLOCK_INPUT;
+ unblock_input ();
return tem;
}
@@ -1770,7 +1761,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
}
-
+
- (void)timeout_handler: (NSTimer *)timedEntry
{
NSEvent *nxev = [NSEvent otherEventWithType: NSApplicationDefined
diff --git a/src/nsselect.m b/src/nsselect.m
index e0bbfe58636..c0c412c6fb2 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -28,7 +28,6 @@ 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. */
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
#include "nsterm.h"
@@ -296,7 +295,7 @@ ns_string_from_pasteboard (id pb)
utfStr = [mstr UTF8String];
length = [mstr lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
-#if ! defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
+#if ! defined (NS_IMPL_COCOA)
if (!utfStr)
{
utfStr = [mstr cString];
@@ -307,7 +306,7 @@ ns_string_from_pasteboard (id pb)
NS_HANDLER
{
message1 ("ns_string_from_pasteboard: UTF8String failed\n");
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+#if defined (NS_IMPL_COCOA)
utfStr = "Conversion failed";
#else
utfStr = [str lossyCString];
diff --git a/src/nsterm.h b/src/nsterm.h
index f0cae193005..005701ed415 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -26,9 +26,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_3
-#define MAC_OS_X_VERSION_10_3 1030
-#endif
#ifndef MAC_OS_X_VERSION_10_4
#define MAC_OS_X_VERSION_10_4 1040
#endif
@@ -38,6 +35,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef MAC_OS_X_VERSION_10_6
#define MAC_OS_X_VERSION_10_6 1060
#endif
+#ifndef MAC_OS_X_VERSION_10_7
+#define MAC_OS_X_VERSION_10_7 1070
+#endif
+#ifndef MAC_OS_X_VERSION_10_8
+#define MAC_OS_X_VERSION_10_8 1080
+#endif
#endif /* NS_IMPL_COCOA */
#ifdef __OBJC__
@@ -80,6 +83,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
BOOL windowClosing;
NSString *workingText;
BOOL processingCompose;
+ int fs_state, fs_before_fs, next_maximized;
+ int tibar_height, tobar_height, bwidth;
+ int maximized_width, maximized_height;
+ NSWindow *nonfs_window;
@public
struct frame *emacsframe;
int rows, cols;
@@ -103,6 +110,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
- (void) setWindowClosing: (BOOL)closing;
- (EmacsToolbar *) toolbar;
- (void) deleteWorkingText;
+- (void) updateFrameSize: (BOOL) delay;
+- (void) handleFS;
+- (void) setFSValue: (int)value;
+- (void) toggleFullScreen: (id) sender;
#ifdef NS_IMPL_GNUSTEP
/* Not declared, but useful. */
@@ -119,6 +130,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
@end
+/* Fullscreen version of the above. */
+@interface EmacsFSWindow : EmacsWindow
+{
+}
+@end
+
/* ==========================================================================
The main menu implementation
@@ -144,7 +161,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
- (EmacsMenu *)addSubmenuWithTitle: (const char *)title forFrame: (struct frame *)f;
- (void) clear;
- (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
- keymaps: (int)keymaps;
+ keymaps: (bool)keymaps;
@end
@@ -266,7 +283,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
int refCount;
NSBitmapImageRep *bmRep; /* used for accessing pixel data */
unsigned char *pixmapData[5]; /* shortcut to access pixel data */
- BOOL onTiger;
NSColor *stippleMask;
}
+ allocInitFromFile: (Lisp_Object)file;
@@ -335,7 +351,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* ==========================================================================
- Rendering on Panther and above
+ Rendering
========================================================================== */
@@ -360,7 +376,7 @@ extern NSString *ns_app_name;
extern EmacsMenu *mainMenu, *svcsMenu, *dockMenu;
/* Apple removed the declaration, but kept the implementation */
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+#if defined (NS_IMPL_COCOA)
@interface NSApplication (EmacsApp)
- (void)setAppleMenu: (NSMenu *)menu;
@end
@@ -463,10 +479,9 @@ struct nsfont_info
float size;
#ifdef __OBJC__
NSFont *nsfont;
- /* cgfont and synthItal are used only on OS X 10.3+ */
-#if defined (NS_IMPL_COCOA) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+#if defined (NS_IMPL_COCOA)
CGFontRef cgfont;
-#else /* GNUstep or OS X < 10.3 */
+#else /* GNUstep */
void *cgfont;
#endif
#else /* ! OBJC */
@@ -615,8 +630,7 @@ struct ns_output
/* this dummy decl needed to support TTYs */
struct x_output
{
- unsigned long background_pixel;
- unsigned long foreground_pixel;
+ int unused;
};
@@ -748,11 +762,11 @@ extern Lisp_Object ns_cursor_type_to_lisp (int arg);
extern void ns_set_name_as_filename (struct frame *f);
extern void ns_set_doc_edited (struct frame *f, Lisp_Object arg);
-extern int
+extern bool
ns_defined_color (struct frame *f,
const char *name,
- XColor *color_def, int alloc,
- char makeIndex);
+ XColor *color_def, bool alloc,
+ bool makeIndex);
extern void
ns_query_color (void *col, XColor *color_def, int setPixel);
@@ -777,7 +791,7 @@ extern void free_frame_tool_bar (FRAME_PTR f);
extern void find_and_call_menu_selection (FRAME_PTR f,
int menu_bar_items_used, Lisp_Object vector, void *client_data);
extern Lisp_Object find_and_return_menu_selection (FRAME_PTR f,
- int keymaps,
+ bool keymaps,
void *client_data);
extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents,
Lisp_Object header);
@@ -798,8 +812,8 @@ struct image;
extern void *ns_image_from_XBM (unsigned char *bits, int width, int height);
extern void *ns_image_for_XPM (int width, int height, int depth);
extern void *ns_image_from_file (Lisp_Object file);
-extern int ns_load_image (struct frame *f, struct image *img,
- Lisp_Object spec_file, Lisp_Object spec_data);
+extern bool ns_load_image (struct frame *f, struct image *img,
+ Lisp_Object spec_file, Lisp_Object spec_data);
extern int ns_image_width (void *img);
extern int ns_image_height (void *img);
extern unsigned long ns_get_pixel (void *img, int x, int y);
diff --git a/src/nsterm.m b/src/nsterm.m
index c892a5486a7..80dc0ba6fc3 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -30,21 +30,18 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
interpretation of even the system includes. */
#include <config.h>
+#include <fcntl.h>
#include <math.h>
+#include <pthread.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
-#include <setjmp.h>
#include <c-ctype.h>
#include <c-strcase.h>
#include <ftoastr.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
#include "lisp.h"
#include "blockinput.h"
#include "sysselect.h"
@@ -56,7 +53,6 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
#include "ccl.h"
#include "termhooks.h"
-#include "termopts.h"
#include "termchar.h"
#include "window.h"
@@ -73,6 +69,11 @@ int term_trace_num = 0;
#define NSTRACE(x)
#endif
+#if defined (NS_IMPL_COCOA) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+#define NEW_STYLE_FS
+#endif
+
extern NSString *NSMenuDidBeginTrackingNotification;
/* ==========================================================================
@@ -97,6 +98,7 @@ static unsigned convert_ns_to_X_keysym[] =
NSBeginFunctionKey, 0x58,
NSSelectFunctionKey, 0x60,
NSPrintFunctionKey, 0x61,
+ NSClearLineFunctionKey, 0x0B,
NSExecuteFunctionKey, 0x62,
NSInsertFunctionKey, 0x63,
NSUndoFunctionKey, 0x65,
@@ -141,6 +143,23 @@ static unsigned convert_ns_to_X_keysym[] =
NSNewlineCharacter, 0x0D,
NSEnterCharacter, 0x8D,
+ 0x41|NSNumericPadKeyMask, 0xAE, /* KP_Decimal */
+ 0x43|NSNumericPadKeyMask, 0xAA, /* KP_Multiply */
+ 0x45|NSNumericPadKeyMask, 0xAB, /* KP_Add */
+ 0x4B|NSNumericPadKeyMask, 0xAF, /* KP_Divide */
+ 0x4E|NSNumericPadKeyMask, 0xAD, /* KP_Subtract */
+ 0x51|NSNumericPadKeyMask, 0xBD, /* KP_Equal */
+ 0x52|NSNumericPadKeyMask, 0xB0, /* KP_0 */
+ 0x53|NSNumericPadKeyMask, 0xB1, /* KP_1 */
+ 0x54|NSNumericPadKeyMask, 0xB2, /* KP_2 */
+ 0x55|NSNumericPadKeyMask, 0xB3, /* KP_3 */
+ 0x56|NSNumericPadKeyMask, 0xB4, /* KP_4 */
+ 0x57|NSNumericPadKeyMask, 0xB5, /* KP_5 */
+ 0x58|NSNumericPadKeyMask, 0xB6, /* KP_6 */
+ 0x59|NSNumericPadKeyMask, 0xB7, /* KP_7 */
+ 0x5B|NSNumericPadKeyMask, 0xB8, /* KP_8 */
+ 0x5C|NSNumericPadKeyMask, 0xB9, /* KP_9 */
+
0x1B, 0x1B /* escape */
};
@@ -179,7 +198,6 @@ static int ns_window_num = 0;
static NSRect uRect;
#endif
static BOOL gsaved = NO;
-BOOL ns_in_resize = NO;
static BOOL ns_fake_keydown = NO;
int ns_tmp_flags; /* FIXME */
struct nsfont_info *ns_tmp_font; /* FIXME */
@@ -188,7 +206,8 @@ static BOOL ns_menu_bar_is_hidden = NO;
/* event loop */
static BOOL send_appdefined = YES;
-static NSEvent *last_appdefined_event = 0;
+#define NO_APPDEFINED_DATA (-8)
+static int last_appdefined_event_data = NO_APPDEFINED_DATA;
static NSTimer *timed_entry = 0;
static NSTimer *scroll_repeat_entry = nil;
static fd_set select_readfds, select_writefds;
@@ -206,6 +225,13 @@ static NSMutableArray *ns_pending_files, *ns_pending_service_names,
*ns_pending_service_args;
static BOOL ns_do_open_file = NO;
+static struct {
+ struct input_event *q;
+ int nr, cap;
+} hold_event_q = {
+ NULL, 0, 0
+};
+
/* Convert modifiers in a NeXTstep event to emacs style modifiers. */
#define NS_FUNCTION_KEY_MASK 0x800000
#define NSLeftControlKeyMask (0x000001 | NSControlKeyMask)
@@ -271,7 +297,7 @@ static BOOL ns_do_open_file = NO;
kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
} \
else \
- kbd_buffer_store_event (emacs_event); \
+ hold_event (emacs_event); \
EVENT_INIT (*emacs_event); \
ns_send_appdefined (-1); \
}
@@ -290,6 +316,22 @@ void x_set_frame_alpha (struct frame *f);
========================================================================== */
+static void
+hold_event (struct input_event *event)
+{
+ if (hold_event_q.nr == hold_event_q.cap)
+ {
+ if (hold_event_q.cap == 0) hold_event_q.cap = 10;
+ else hold_event_q.cap *= 2;
+ hold_event_q.q = (struct input_event *)
+ xrealloc (hold_event_q.q, hold_event_q.cap * sizeof (*hold_event_q.q));
+ }
+
+ hold_event_q.q[hold_event_q.nr++] = *event;
+ /* Make sure ns_read_socket is called, i.e. we have input. */
+ raise (SIGIO);
+ send_appdefined = YES;
+}
static Lisp_Object
append2 (Lisp_Object list, Lisp_Object item)
@@ -489,17 +531,6 @@ ns_release_autorelease_pool (void *pool)
========================================================================== */
-static NSRect
-ns_resize_handle_rect (NSWindow *window)
-{
- NSRect r = [window frame];
- r.origin.x = r.size.width - RESIZE_HANDLE_SIZE;
- r.origin.y = 0;
- r.size.width = r.size.height = RESIZE_HANDLE_SIZE;
- return r;
-}
-
-
//
// Window constraining
// -------------------
@@ -577,12 +608,9 @@ ns_menu_bar_should_be_hidden (void)
static void
ns_update_auto_hide_menu_bar (void)
{
-#ifndef MAC_OS_X_VERSION_10_6
-#define MAC_OS_X_VERSION_10_6 1060
-#endif
#ifdef NS_IMPL_COCOA
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- BLOCK_INPUT;
+ block_input ();
NSTRACE (ns_update_auto_hide_menu_bar);
@@ -613,7 +641,7 @@ ns_update_auto_hide_menu_bar (void)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
#endif
#endif
}
@@ -627,6 +655,8 @@ ns_update_begin (struct frame *f)
-------------------------------------------------------------------------- */
{
NSView *view = FRAME_NS_VIEW (f);
+ NSRect r = [view frame];
+ NSBezierPath *bp;
NSTRACE (ns_update_begin);
ns_update_auto_hide_menu_bar ();
@@ -634,6 +664,14 @@ ns_update_begin (struct frame *f)
ns_updating_frame = f;
[view lockFocus];
+ /* drawRect may have been called for say the minibuffer, and then clip path
+ is for the minibuffer. But the display engine may draw more because
+ we have set the frame as garbaged. So reset clip path to the whole
+ view. */
+ bp = [[NSBezierPath bezierPathWithRect: r] retain];
+ [bp setClip];
+ [bp release];
+
#ifdef NS_IMPL_GNUSTEP
uRect = NSMakeRect (0, 0, 0, 0);
#endif
@@ -650,11 +688,10 @@ ns_update_window_begin (struct window *w)
struct frame *f = XFRAME (WINDOW_FRAME (w));
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
NSTRACE (ns_update_window_begin);
-
updated_window = w;
set_output_cursor (&w->cursor);
- BLOCK_INPUT;
+ block_input ();
if (f == hlinfo->mouse_face_mouse_frame)
{
@@ -669,7 +706,7 @@ ns_update_window_begin (struct window *w)
/* (further code for mouse faces ifdef'd out in other terms elided) */
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -686,7 +723,7 @@ ns_update_window_end (struct window *w, int cursor_on_p,
/* note: this fn is nearly identical in all terms */
if (!w->pseudo_window_p)
{
- BLOCK_INPUT;
+ block_input ();
if (cursor_on_p)
display_and_set_cursor (w, 1,
@@ -696,7 +733,7 @@ ns_update_window_end (struct window *w, int cursor_on_p,
if (draw_window_fringes (w, 1))
x_draw_vertical_border (w);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* If a row with mouse-face was overwritten, arrange for
@@ -725,7 +762,7 @@ ns_update_end (struct frame *f)
/* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
MOUSE_HL_INFO (f)->mouse_face_defer = 0;
- BLOCK_INPUT;
+ block_input ();
#ifdef NS_IMPL_GNUSTEP
/* trigger flush only in the rectangle we tracked as being drawn */
@@ -737,7 +774,7 @@ ns_update_end (struct frame *f)
[view unlockFocus];
[[view window] flushWindow];
- UNBLOCK_INPUT;
+ unblock_input ();
ns_updating_frame = NULL;
NSTRACE (ns_update_end);
}
@@ -871,25 +908,12 @@ ns_clip_to_row (struct window *w, struct glyph_row *row, int area, BOOL gc)
window_box (w, area, &window_x, &window_y, &window_width, 0);
- clip_rect.origin.x = window_x - FRAME_INTERNAL_BORDER_WIDTH (f);
+ clip_rect.origin.x = window_x;
clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
clip_rect.origin.y = max (clip_rect.origin.y, window_y);
- clip_rect.size.width = window_width + 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
+ clip_rect.size.width = window_width;
clip_rect.size.height = row->visible_height;
- /* allow a full-height row at the top when requested
- (used to draw fringe all the way through internal border area) */
- if (gc && clip_rect.origin.y < 5)
- {
- clip_rect.origin.y -= FRAME_INTERNAL_BORDER_WIDTH (f);
- clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f);
- }
-
- /* likewise at bottom */
- if (gc &&
- FRAME_PIXEL_HEIGHT (f) - (clip_rect.origin.y + clip_rect.size.height) < 5)
- clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f);
-
ns_focus (f, &clip_rect, 1);
}
@@ -907,7 +931,7 @@ ns_ring_bell (struct frame *f)
struct frame *frame = SELECTED_FRAME ();
NSView *view;
- BLOCK_INPUT;
+ block_input ();
pool = [[NSAutoreleasePool alloc] init];
view = FRAME_NS_VIEW (frame);
@@ -934,7 +958,7 @@ ns_ring_bell (struct frame *f)
ns_unfocus (frame);
}
[pool release];
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
{
@@ -975,13 +999,13 @@ ns_raise_frame (struct frame *f)
{
NSView *view = FRAME_NS_VIEW (f);
check_ns ();
- BLOCK_INPUT;
+ block_input ();
FRAME_SAMPLE_VISIBILITY (f);
if (FRAME_VISIBLE_P (f))
{
[[view window] makeKeyAndOrderFront: NSApp];
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -993,9 +1017,9 @@ ns_lower_frame (struct frame *f)
{
NSView *view = FRAME_NS_VIEW (f);
check_ns ();
- BLOCK_INPUT;
+ block_input ();
[[view window] orderBack: NSApp];
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1068,8 +1092,23 @@ x_make_frame_visible (struct frame *f)
if this ends up the case again, comment this out again. */
if (!FRAME_VISIBLE_P (f))
{
+ EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
f->async_visible = 1;
ns_raise_frame (f);
+
+#ifdef NEW_STYLE_FS
+ /* Making a new frame from a fullscreen frame will make the new frame
+ fullscreen also. So skip handleFS as this will print an error. */
+ if (f->want_fullscreen == FULLSCREEN_BOTH
+ && ([[view window] styleMask] & NSFullScreenWindowMask) != 0)
+ return;
+#endif
+ if (f->want_fullscreen != FULLSCREEN_NONE)
+ {
+ block_input ();
+ [view handleFS];
+ unblock_input ();
+ }
}
}
@@ -1131,7 +1170,7 @@ x_free_frame_resources (struct frame *f)
[(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
- BLOCK_INPUT;
+ block_input ();
free_frame_menubar (f);
@@ -1147,7 +1186,6 @@ x_free_frame_resources (struct frame *f)
hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_window = Qnil;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_mouse_frame = 0;
}
@@ -1159,7 +1197,7 @@ x_free_frame_resources (struct frame *f)
xfree (f->output_data.ns);
- UNBLOCK_INPUT;
+ unblock_input ();
}
void
@@ -1188,7 +1226,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
NSTRACE (x_set_offset);
- BLOCK_INPUT;
+ block_input ();
f->left_pos = xoff;
f->top_pos = yoff;
@@ -1220,7 +1258,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
f->size_hint_flags &= ~(XNegative|YNegative);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1237,31 +1275,17 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
NSRect wr = [window frame];
int tb = FRAME_EXTERNAL_TOOL_BAR (f);
int pixelwidth, pixelheight;
- static int oldRows, oldCols, oldFontWidth, oldFontHeight;
- static int oldTB;
- static struct frame *oldF;
NSTRACE (x_set_window_size);
- if (view == nil ||
- (f == oldF
- && rows == oldRows && cols == oldCols
- && oldFontWidth == FRAME_COLUMN_WIDTH (f)
- && oldFontHeight == FRAME_LINE_HEIGHT (f)
- && oldTB == tb))
+ if (view == nil)
return;
/*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
- BLOCK_INPUT;
+ block_input ();
check_frame_size (f, &rows, &cols);
- oldF = f;
- oldRows = rows;
- oldCols = cols;
- oldFontWidth = FRAME_COLUMN_WIDTH (f);
- oldFontHeight = FRAME_LINE_HEIGHT (f);
- oldTB = tb;
f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
compute_fringe_widths (f, 0);
@@ -1321,10 +1345,33 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
mark_window_cursors_off (XWINDOW (f->root_window));
cancel_mouse_face (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
+static void
+ns_fullscreen_hook (FRAME_PTR f)
+{
+ EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
+
+ if (! f->async_visible) return;
+#ifndef NEW_STYLE_FS
+ if (f->want_fullscreen == FULLSCREEN_BOTH)
+ {
+ /* Old style fs don't initiate correctly if created from
+ init/default-frame alist, so use a timer (not nice...).
+ */
+ [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view
+ selector: @selector (handleFS)
+ userInfo: nil repeats: NO];
+ return;
+ }
+#endif
+
+ block_input ();
+ [view handleFS];
+ unblock_input ();
+}
/* ==========================================================================
@@ -1433,7 +1480,7 @@ ns_get_color (const char *name, NSColor **col)
NSString *nsname = [NSString stringWithUTF8String: name];
/*fprintf (stderr, "ns_get_color: '%s'\n", name); */
- BLOCK_INPUT;
+ block_input ();
if ([nsname isEqualToString: @"ns_selection_color"])
{
@@ -1480,7 +1527,7 @@ ns_get_color (const char *name, NSColor **col)
if (r >= 0.0)
{
*col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0];
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -1512,7 +1559,7 @@ ns_get_color (const char *name, NSColor **col)
if (new)
*col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
- UNBLOCK_INPUT;
+ unblock_input ();
return new ? 0 : 1;
}
@@ -1543,12 +1590,12 @@ ns_color_to_lisp (NSColor *col)
const char *str;
NSTRACE (ns_color_to_lisp);
- BLOCK_INPUT;
+ block_input ();
if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
if ((str =[[col colorNameComponent] UTF8String]))
{
- UNBLOCK_INPUT;
+ unblock_input ();
return build_string ((char *)str);
}
@@ -1560,14 +1607,14 @@ ns_color_to_lisp (NSColor *col)
getWhite: &gray alpha: &alpha];
snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
lrint (gray * 0xff), lrint (gray * 0xff), lrint (gray * 0xff));
- UNBLOCK_INPUT;
+ unblock_input ();
return build_string (buf);
}
snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx",
lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
- UNBLOCK_INPUT;
+ unblock_input ();
return build_string (buf);
}
@@ -1594,33 +1641,33 @@ ns_query_color(void *col, XColor *color_def, int setPixel)
}
-int
+bool
ns_defined_color (struct frame *f,
const char *name,
XColor *color_def,
- int alloc,
- char makeIndex)
+ bool alloc,
+ bool makeIndex)
/* --------------------------------------------------------------------------
- Return 1 if named color found, and set color_def rgb accordingly.
+ Return true if named color found, and set color_def rgb accordingly.
If makeIndex and alloc are nonzero put the color in the color_table,
and set color_def pixel to the resulting index.
If makeIndex is zero, set color_def pixel to ARGB.
- Return 0 if not found
+ Return false if not found
-------------------------------------------------------------------------- */
{
NSColor *col;
NSTRACE (ns_defined_color);
- BLOCK_INPUT;
+ block_input ();
if (ns_get_color (name, &col) != 0) /* Color not found */
{
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
if (makeIndex && alloc)
color_def->pixel = ns_index_color (col, f);
ns_query_color (col, color_def, !makeIndex);
- UNBLOCK_INPUT;
+ unblock_input ();
return 1;
}
@@ -1786,7 +1833,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
dpyinfo = FRAME_NS_DISPLAY_INFO (*fp);
- BLOCK_INPUT;
+ block_input ();
if (last_mouse_scroll_bar != nil && insist == 0)
{
@@ -1831,7 +1878,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1839,8 +1886,7 @@ static void
ns_frame_up_to_date (struct frame *f)
/* --------------------------------------------------------------------------
External (hook): Fix up mouse highlighting right after a full update.
- Some highlighting was deferred if GC was happening during
- note_mouse_highlight (), while other highlighting was deferred for update.
+ Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls.
-------------------------------------------------------------------------- */
{
NSTRACE (ns_frame_up_to_date);
@@ -1848,19 +1894,17 @@ ns_frame_up_to_date (struct frame *f)
if (FRAME_NS_P (f))
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
- if ((hlinfo->mouse_face_deferred_gc || f ==hlinfo->mouse_face_mouse_frame)
- /*&& hlinfo->mouse_face_mouse_frame*/)
- {
- BLOCK_INPUT;
+ if (f == hlinfo->mouse_face_mouse_frame)
+ {
+ block_input ();
ns_update_begin(f);
- if (hlinfo->mouse_face_mouse_frame)
- note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
- hlinfo->mouse_face_mouse_x,
- hlinfo->mouse_face_mouse_y);
- hlinfo->mouse_face_deferred_gc = 0;
+ if (hlinfo->mouse_face_mouse_frame)
+ note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
+ hlinfo->mouse_face_mouse_x,
+ hlinfo->mouse_face_mouse_y);
ns_update_end(f);
- UNBLOCK_INPUT;
- }
+ unblock_input ();
+ }
}
}
@@ -1939,7 +1983,7 @@ ns_redraw_scroll_bars (struct frame *f)
int i;
id view;
NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
- NSTRACE (ns_judge_scroll_bars);
+ NSTRACE (ns_redraw_scroll_bars);
for (i =[subviews count]-1; i >= 0; i--)
{
view = [subviews objectAtIndex: i];
@@ -1959,8 +2003,6 @@ ns_clear_frame (struct frame *f)
NSRect r;
NSTRACE (ns_clear_frame);
- if (ns_in_resize)
- return;
/* comes on initial frame because we have
after-make-frame-functions = select-frame */
@@ -1974,19 +2016,15 @@ ns_clear_frame (struct frame *f)
r = [view bounds];
- BLOCK_INPUT;
+ block_input ();
ns_focus (f, &r, 1);
[ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
NSRectFill (r);
ns_unfocus (f);
-#ifdef NS_IMPL_COCOA
- [[view window] display]; /* redraw resize handle */
-#endif
-
/* as of 2006/11 or so this is now needed */
ns_redraw_scroll_bars (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2009,35 +2047,8 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
ns_focus (f, &r, 1);
[ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
-#ifdef NS_IMPL_COCOA
- {
- /* clip out the resize handle */
- NSWindow *window = [FRAME_NS_VIEW (f) window];
- NSRect ir
- = [view convertRect: ns_resize_handle_rect (window) fromView: nil];
-
- ir = NSIntersectionRect (r, ir);
- if (NSIsEmptyRect (ir))
- {
-#endif
-
NSRectFill (r);
-#ifdef NS_IMPL_COCOA
- }
- else
- {
- NSRect r1 = r, r2 = r; /* upper and lower non-intersecting */
- r1.size.height -= ir.size.height;
- r2.origin.y += r1.size.height;
- r2.size.width -= ir.size.width;
- r2.size.height = ir.size.height;
- NSRectFill (r1);
- NSRectFill (r2);
- }
- }
-#endif
-
ns_unfocus (f);
return;
}
@@ -2087,7 +2098,7 @@ ns_scroll_run (struct window *w, struct run *run)
if (height == 0)
return;
- BLOCK_INPUT;
+ block_input ();
updated_window = w;
x_clear_cursor (w);
@@ -2102,7 +2113,7 @@ ns_scroll_run (struct window *w, struct run *run)
ns_unfocus (f);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2125,9 +2136,9 @@ ns_after_update_window_line (struct glyph_row *desired_row)
desired_row->redraw_fringe_bitmaps_p = 1;
/* When a window has disappeared, make sure that no rest of
- full-width rows stays visible in the internal border.
- Under NS this is drawn inside the fringes. */
+ full-width rows stays visible in the internal border. */
if (windows_or_buffers_changed
+ && desired_row->full_width_p
&& (f = XFRAME (w->frame),
width = FRAME_INTERNAL_BORDER_WIDTH (f),
width != 0)
@@ -2136,25 +2147,12 @@ ns_after_update_window_line (struct glyph_row *desired_row)
{
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
- /* Internal border is drawn below the tool bar. */
- if (WINDOWP (f->tool_bar_window)
- && w == XWINDOW (f->tool_bar_window))
- y -= width;
- /* end copy from other terms */
-
- BLOCK_INPUT;
- if (!desired_row->full_width_p)
- {
- int x1 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
- + WINDOW_LEFT_FRINGE_WIDTH (w);
- int x2 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
- + FRAME_PIXEL_WIDTH (f) - NS_SCROLL_BAR_WIDTH (f)
- - WINDOW_RIGHT_FRINGE_WIDTH (w)
- - FRAME_INTERNAL_BORDER_WIDTH (f);
- ns_clear_frame_area (f, x1, y, width, height);
- ns_clear_frame_area (f, x2, y, width, height);
- }
- UNBLOCK_INPUT;
+ block_input ();
+ ns_clear_frame_area (f, 0, y, width, height);
+ ns_clear_frame_area (f,
+ FRAME_PIXEL_WIDTH (f) - width,
+ y, width, height);
+ unblock_input ();
}
}
@@ -2187,7 +2185,7 @@ ns_shift_glyphs_for_insert (struct frame *f,
========================================================================== */
-static inline void
+static void
ns_compute_glyph_string_overhangs (struct glyph_string *s)
/* --------------------------------------------------------------------------
External (RIF); compute left/right overhang of whole string and set in s
@@ -2238,17 +2236,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
int rowY;
static EmacsImage **bimgs = NULL;
static int nBimgs = 0;
- /* NS-specific: move internal border inside fringe */
- int x = p->bx < 0 ? p->x : p->bx;
- int wd = p->bx < 0 ? p->wd : p->nx;
- BOOL fringeOnVeryLeft
- = x - WINDOW_LEFT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w)
- - FRAME_INTERNAL_BORDER_WIDTH (f) < 10;
- BOOL fringeOnVeryRight
- = FRAME_PIXEL_WIDTH (f) - x - wd - FRAME_INTERNAL_BORDER_WIDTH (f)
- - WINDOW_RIGHT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) < 10;
- int xAdjust = FRAME_INTERNAL_BORDER_WIDTH (f) *
- (fringeOnVeryLeft ? -1 : (fringeOnVeryRight ? 1 : 0));
/* grow bimgs if needed */
if (nBimgs < max_used_fringe_bitmap)
@@ -2263,22 +2250,68 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
ns_clip_to_row (w, row, -1, YES);
- if (p->bx >= 0 && !p->overlay_p)
+ if (!p->overlay_p)
{
- int yAdjust = rowY - FRAME_INTERNAL_BORDER_WIDTH (f) < 5 ?
- -FRAME_INTERNAL_BORDER_WIDTH (f) : 0;
- int yIncr = FRAME_PIXEL_HEIGHT (f) - (p->by+yAdjust + p->ny) < 5 ?
- FRAME_INTERNAL_BORDER_WIDTH (f) : 0
- + (yAdjust ? FRAME_INTERNAL_BORDER_WIDTH (f) : 0);
- NSRect r = NSMakeRect (p->bx+xAdjust, p->by+yAdjust, p->nx, p->ny+yIncr);
- NSRectClip (r);
- [ns_lookup_indexed_color(face->background, f) set];
- NSRectFill (r);
+ 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);
+ NSRectClip (r);
+ [ns_lookup_indexed_color (face->background, f) set];
+ NSRectFill (r);
+ }
}
if (p->which)
{
- NSRect r = NSMakeRect (p->x+xAdjust, p->y, p->wd, p->h);
+ NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h);
EmacsImage *img = bimgs[p->which - 1];
if (!img)
@@ -2288,7 +2321,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
int i;
unsigned char *cbits = xmalloc (len);
- for (i =0; i<len; i++)
+ for (i = 0; i < len; i++)
cbits[i] = ~(bits[i] & 0xff);
img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
flip: NO];
@@ -2302,12 +2335,20 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
[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
[img drawInRect: r
fromRect: NSZeroRect
operation: NSCompositeSourceOver
fraction: 1.0
respectFlipped: YES
hints: nil];
+#else
+ {
+ NSPoint pt = r.origin;
+ pt.y += p->h;
+ [img compositeToPoint: pt operation: NSCompositeSourceOver];
+ }
+#endif
}
ns_unfocus (f);
}
@@ -2386,14 +2427,6 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
r.size.height = h;
r.size.width = w->phys_cursor_width;
- /* FIXME: if we overwrite the internal border area, it does not get erased;
- fix by truncating cursor, but better would be to erase properly */
- overspill = r.origin.x + r.size.width -
- WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w)
- - WINDOW_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f));
- if (overspill > 0)
- r.size.width -= overspill;
-
/* TODO: only needed in rare cases with last-resort font in HELLO..
should we do this more efficiently? */
ns_clip_to_row (w, glyph_row, -1, NO); /* do ns_focus(f, &r, 1); if remove */
@@ -2486,12 +2519,12 @@ show_hourglass (struct atimer *timer)
if (hourglass_shown_p)
return;
- BLOCK_INPUT;
+ block_input ();
/* TODO: add NSProgressIndicator to selected frame (see macfns.c) */
hourglass_shown_p = 1;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2501,12 +2534,12 @@ hide_hourglass (void)
if (!hourglass_shown_p)
return;
- BLOCK_INPUT;
+ block_input ();
/* TODO: remove NSProgressIndicator from all frames */
hourglass_shown_p = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2517,31 +2550,6 @@ hide_hourglass (void)
========================================================================== */
-
-static inline NSRect
-ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width)
-/* --------------------------------------------------------------------------
- Under NS we draw internal borders inside fringes, and want full-width
- rendering to go all the way to edge. This function makes that correction.
- -------------------------------------------------------------------------- */
-{
- if (r.origin.y <= fibw+1)
- {
- r.size.height += r.origin.y;
- r.origin.y = 0;
- }
- if (r.origin.x <= fibw+1)
- {
- r.size.width += r.origin.x;
- r.origin.x = 0;
- }
- if (frame_pixel_width - (r.origin.x+r.size.width) <= fibw+1)
- r.size.width += fibw;
-
- return r;
-}
-
-
static int
ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
/* --------------------------------------------------------------------------
@@ -2551,14 +2559,6 @@ ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
-------------------------------------------------------------------------- */
{
int n = get_glyph_string_clip_rects (s, nr, 2);
- if (s->row->full_width_p)
- {
- *nr = ns_fix_rect_ibw (*nr, FRAME_INTERNAL_BORDER_WIDTH (s->f),
- FRAME_PIXEL_WIDTH (s->f));
- if (n == 2)
- *nr = ns_fix_rect_ibw (*(nr+1), FRAME_INTERNAL_BORDER_WIDTH (s->f),
- FRAME_PIXEL_WIDTH (s->f));
- }
return n;
}
@@ -2883,11 +2883,6 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s)
r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
- /* expand full-width row over internal borders */
- if (s->row->full_width_p)
- r = ns_fix_rect_ibw (r, FRAME_INTERNAL_BORDER_WIDTH (s->f),
- FRAME_PIXEL_WIDTH (s->f));
-
/* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
{
@@ -2943,26 +2938,6 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
NSRect r = NSMakeRect (s->x, s->y + box_line_width,
s->background_width,
s->height-2*box_line_width);
-
- /* expand full-width row over internal borders */
- if (s->row->full_width_p)
- {
- int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
- if (r.origin.y <= fibw+1 + box_line_width)
- {
- r.size.height += r.origin.y;
- r.origin.y = 0;
- }
- if (r.origin.x <= fibw+1)
- {
- r.size.width += 2*r.origin.x;
- r.origin.x = 0;
- }
- if (FRAME_PIXEL_WIDTH (s->f) - (r.origin.x + r.size.width)
- <= fibw+1)
- r.size.width += fibw;
- }
-
NSRectFill (r);
}
@@ -3028,34 +3003,26 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
br = NSMakeRect (x, y, s->slice.width, s->slice.height);
}
- /* expand full-width row over internal borders */
- if (s->row->full_width_p)
- {
- int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
- if (br.origin.y <= fibw+1 + box_line_vwidth)
- {
- br.size.height += br.origin.y;
- br.origin.y = 0;
- }
- if (br.origin.x <= fibw+1 + box_line_vwidth)
- {
- br.size.width += br.origin.x;
- br.origin.x = 0;
- }
- if (FRAME_PIXEL_WIDTH (s->f) - (br.origin.x + br.size.width) <= fibw+1)
- br.size.width += fibw;
- }
-
NSRectFill (br);
/* Draw the image.. do we need to draw placeholder if img ==nil? */
if (img != nil)
- [img drawInRect: br
- fromRect: NSZeroRect
+ {
+#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ 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);
+ [img drawInRect: dr
+ fromRect: ir
operation: NSCompositeSourceOver
fraction: 1.0
respectFlipped: YES
hints: nil];
+#else
+ [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
+ operation: NSCompositeSourceOver];
+#endif
+ }
if (s->hl == DRAW_CURSOR)
{
@@ -3143,7 +3110,7 @@ ns_dumpglyphs_stretch (struct glyph_string *s)
bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
- for (i=0; i<n; i++)
+ for (i = 0; i < n; ++i)
{
if (!s->row->full_width_p)
{
@@ -3173,13 +3140,6 @@ ns_dumpglyphs_stretch (struct glyph_string *s)
r[i].size.height = min (s->height, s->row->visible_height);
}
- /* expand full-width rows over internal borders */
- else
- {
- r[i] = ns_fix_rect_ibw (r[i], FRAME_INTERNAL_BORDER_WIDTH (s->f),
- FRAME_PIXEL_WIDTH (s->f));
- }
-
[bgCol set];
/* NOTE: under NS this is NOT used to draw cursors, but we must avoid
@@ -3340,7 +3300,7 @@ ns_draw_glyph_string (struct glyph_string *s)
break;
default:
- abort ();
+ emacs_abort ();
}
/* Draw box if not done already. */
@@ -3409,8 +3369,7 @@ ns_send_appdefined (int value)
}
static int
-ns_read_socket (struct terminal *terminal, int expected,
- struct input_event *hold_quit)
+ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
/* --------------------------------------------------------------------------
External (hook): Post an event to ourself and keep reading events until
we read it back again. In effect process all events which were waiting.
@@ -3425,21 +3384,16 @@ ns_read_socket (struct terminal *terminal, int expected,
if ([NSApp modalWindow] != nil)
return -1;
- if (interrupt_input_blocked)
+ if (hold_event_q.nr > 0)
{
- interrupt_input_pending = 1;
-#ifdef SYNC_INPUT
- pending_signals = 1;
-#endif
- return -1;
+ int i;
+ for (i = 0; i < hold_event_q.nr; ++i)
+ kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit);
+ hold_event_q.nr = 0;
+ return i;
}
- interrupt_input_pending = 0;
-#ifdef SYNC_INPUT
- pending_signals = pending_atimers;
-#endif
-
- BLOCK_INPUT;
+ block_input ();
n_emacs_events_pending = 0;
EVENT_INIT (ev);
emacs_event = &ev;
@@ -3475,7 +3429,7 @@ ns_read_socket (struct terminal *terminal, int expected,
if (++apploopnr != 1)
{
- abort ();
+ emacs_abort ();
}
[NSApp run];
--apploopnr;
@@ -3484,7 +3438,7 @@ ns_read_socket (struct terminal *terminal, int expected,
nevents = n_emacs_events_pending;
n_emacs_events_pending = 0;
emacs_event = q_event_ptr = NULL;
- UNBLOCK_INPUT;
+ unblock_input ();
return nevents;
}
@@ -3498,15 +3452,25 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
-------------------------------------------------------------------------- */
{
int result;
- NSEvent *ev;
- int k, nr = 0;
+ int t, k, nr = 0;
struct input_event event;
char c;
/* NSTRACE (ns_select); */
- for (k = 0; readfds && k < nfds+1; k++)
- if (FD_ISSET(k, readfds)) ++nr;
+ if (hold_event_q.nr > 0)
+ {
+ /* We already have events pending. */
+ raise (SIGIO);
+ errno = EINTR;
+ return -1;
+ }
+
+ for (k = 0; k < nfds+1; k++)
+ {
+ if (readfds && FD_ISSET(k, readfds)) ++nr;
+ if (writefds && FD_ISSET(k, writefds)) ++nr;
+ }
if (NSApp == nil
|| (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
@@ -3515,7 +3479,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
[outerpool release];
outerpool = [[NSAutoreleasePool alloc] init];
-
+
send_appdefined = YES;
if (nr > 0)
{
@@ -3543,7 +3507,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
/* Inform fd_handler that select should be called */
c = 'g';
- write (selfds[1], &c, 1);
+ emacs_write (selfds[1], &c, 1);
}
else if (nr == 0 && timeout)
{
@@ -3564,11 +3528,11 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
}
EVENT_INIT (event);
- BLOCK_INPUT;
+ block_input ();
emacs_event = &event;
if (++apploopnr != 1)
{
- abort();
+ emacs_abort ();
}
[NSApp run];
--apploopnr;
@@ -3576,20 +3540,15 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
if (nr > 0 && readfds)
{
c = 's';
- write (selfds[1], &c, 1);
+ emacs_write (selfds[1], &c, 1);
}
- UNBLOCK_INPUT;
+ unblock_input ();
- ev = last_appdefined_event;
+ t = last_appdefined_event_data;
- if (ev)
+ if (t != NO_APPDEFINED_DATA)
{
- int t;
- if ([ev type] != NSApplicationDefined)
- abort ();
-
- t = [ev data1];
- last_appdefined_event = 0;
+ last_appdefined_event_data = NO_APPDEFINED_DATA;
if (t == -2)
{
@@ -3639,9 +3598,9 @@ ns_set_vertical_scroll_bar (struct window *window,
struct frame *f = XFRAME (WINDOW_FRAME (window));
EmacsView *view = FRAME_NS_VIEW (f);
int window_y, window_height;
- BOOL barOnVeryLeft, barOnVeryRight;
int top, left, height, width, sb_width, sb_left;
EmacsScroller *bar;
+ BOOL fringe_extended_p;
/* optimization; display engine sends WAY too many of these.. */
if (!NILP (window->vertical_scroll_bar))
@@ -3668,28 +3627,29 @@ 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);
- if (top < 5) /* top scrollbar adjustment */
- {
- top -= FRAME_INTERNAL_BORDER_WIDTH (f);
- height += FRAME_INTERNAL_BORDER_WIDTH (f);
- }
-
/* 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;
-
- barOnVeryLeft = left < 5;
- barOnVeryRight = FRAME_PIXEL_WIDTH (f) - left - width < 5;
- sb_left = left + FRAME_INTERNAL_BORDER_WIDTH (f)
- * (barOnVeryLeft ? -1 : (barOnVeryRight ? 1 : 0));
+ sb_left = left;
r = NSMakeRect (sb_left, top, sb_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);
+ if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (window))
+ fringe_extended_p = (WINDOW_LEFTMOST_P (window)
+ && WINDOW_LEFT_FRINGE_WIDTH (window)
+ && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (window)
+ || WINDOW_LEFT_MARGIN_COLS (window) == 0));
+ else
+ fringe_extended_p = (WINDOW_RIGHTMOST_P (window)
+ && WINDOW_RIGHT_FRINGE_WIDTH (window)
+ && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (window)
+ || WINDOW_RIGHT_MARGIN_COLS (window) == 0));
+
XSETWINDOW (win, window);
- BLOCK_INPUT;
+ block_input ();
/* we want at least 5 lines to display a scrollbar */
if (WINDOW_TOTAL_LINES (window) < 5)
@@ -3701,13 +3661,20 @@ ns_set_vertical_scroll_bar (struct window *window,
wset_vertical_scroll_bar (window, Qnil);
}
ns_clear_frame_area (f, sb_left, top, width, height);
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
if (NILP (window->vertical_scroll_bar))
{
- ns_clear_frame_area (f, sb_left, top, width, height);
+ 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);
+ }
+
bar = [[EmacsScroller alloc] initFrame: r window: win];
wset_vertical_scroll_bar (window, make_save_value (bar, 0));
}
@@ -3726,7 +3693,7 @@ ns_set_vertical_scroll_bar (struct window *window,
}
[bar setPosition: position portion: portion whole: whole];
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3778,14 +3745,21 @@ ns_judge_scroll_bars (struct frame *f)
{
int i;
id view;
- NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
+ EmacsView *eview = FRAME_NS_VIEW (f);
+ NSArray *subviews = [[eview superview] subviews];
+ BOOL removed = NO;
+
NSTRACE (ns_judge_scroll_bars);
- for (i =[subviews count]-1; i >= 0; i--)
+ for (i = [subviews count]-1; i >= 0; --i)
{
view = [subviews objectAtIndex: i];
if (![view isKindOfClass: [EmacsScroller class]]) continue;
[view judge];
+ removed = YES;
}
+
+ if (removed)
+ [eview updateFrameSize: NO];
}
@@ -3891,7 +3865,6 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo)
dpyinfo->root_window = 42; /* a placeholder.. */
hlinfo->mouse_face_mouse_frame = NULL;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
@@ -3963,11 +3936,11 @@ ns_delete_terminal (struct terminal *terminal)
if (!terminal->name)
return;
- BLOCK_INPUT;
+ block_input ();
x_destroy_all_bitmaps (dpyinfo);
ns_delete_display (dpyinfo);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -4004,7 +3977,7 @@ ns_create_terminal (struct ns_display_info *dpyinfo)
terminal->frame_rehighlight_hook = ns_frame_rehighlight;
terminal->frame_raise_lower_hook = ns_frame_raise_lower;
- terminal->fullscreen_hook = 0; /* see XTfullscreen_hook */
+ terminal->fullscreen_hook = ns_fullscreen_hook;
terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
@@ -4035,33 +4008,34 @@ ns_term_init (Lisp_Object display_name)
static int ns_initialized = 0;
Lisp_Object tmp;
+ if (ns_initialized) return x_display_list;
+ ns_initialized = 1;
+
NSTRACE (ns_term_init);
+ [outerpool release];
+ outerpool = [[NSAutoreleasePool alloc] init];
+
/* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
/*GSDebugAllocationActive (YES); */
- BLOCK_INPUT;
- handling_signal = 0;
+ block_input ();
- if (!ns_initialized)
- {
- baud_rate = 38400;
- Fset_input_interrupt_mode (Qnil);
+ baud_rate = 38400;
+ Fset_input_interrupt_mode (Qnil);
- if (selfds[0] == -1)
+ if (selfds[0] == -1)
+ {
+ if (pipe (selfds) == -1)
{
- if (pipe (selfds) == -1)
- {
- fprintf (stderr, "Failed to create pipe: %s\n",
- emacs_strerror (errno));
- abort ();
- }
-
- fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
- FD_ZERO (&select_readfds);
- FD_ZERO (&select_writefds);
- pthread_mutex_init (&select_mutex, NULL);
+ fprintf (stderr, "Failed to create pipe: %s\n",
+ emacs_strerror (errno));
+ emacs_abort ();
}
- ns_initialized = 1;
+
+ fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
+ FD_ZERO (&select_readfds);
+ FD_ZERO (&select_writefds);
+ pthread_mutex_init (&select_mutex, NULL);
}
ns_pending_files = [[NSMutableArray alloc] init];
@@ -4113,7 +4087,7 @@ ns_term_init (Lisp_Object display_name)
terminal->name = xstrdup (SSDATA (display_name));
- UNBLOCK_INPUT;
+ unblock_input ();
if (!inhibit_x_resources)
{
@@ -4142,8 +4116,6 @@ ns_term_init (Lisp_Object display_name)
color_file = Fexpand_file_name (build_string ("rgb.txt"),
Fsymbol_value (intern ("data-directory")));
- if (NILP (Ffile_readable_p (color_file)))
- fatal ("Could not find %s.\n", SDATA (color_file));
color_map = Fx_load_color_file (color_file);
if (NILP (color_map))
@@ -4252,6 +4224,25 @@ ns_term_init (Lisp_Object display_name)
}
#endif /* MAC OS X menu setup */
+ /* Register our external input/output types, used for determining
+ applicable services and also drag/drop eligibility. */
+ ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
+ ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
+ retain];
+ ns_drag_types = [[NSArray arrayWithObjects:
+ NSStringPboardType,
+ NSTabularTextPboardType,
+ NSFilenamesPboardType,
+ NSURLPboardType,
+ NSColorPboardType,
+ NSFontPboardType, nil] retain];
+
+#ifndef NEW_STYLE_FS
+ /* If fullscreen is in init/default-frame-alist, focus isn't set
+ right for fullscreen windows, so set this. */
+ [NSApp activateIgnoringOtherApps:YES];
+#endif
+
[NSApp run];
ns_do_open_file = YES;
return dpyinfo;
@@ -4273,7 +4264,7 @@ ns_term_shutdown (int sig)
}
else // force a stack trace to happen
{
- abort();
+ emacs_abort ();
}
}
@@ -4323,34 +4314,6 @@ ns_term_shutdown (int sig)
return;
}
-#ifdef NS_IMPL_COCOA
- /* pass mouse down in resize handle and subsequent drags directly to
- EmacsWindow so we can generate continuous redisplays */
- if (ns_in_resize)
- {
- if (type == NSLeftMouseDragged)
- {
- [window mouseDragged: theEvent];
- return;
- }
- else if (type == NSLeftMouseUp)
- {
- [window mouseUp: theEvent];
- return;
- }
- }
- else if (type == NSLeftMouseDown)
- {
- NSRect r = ns_resize_handle_rect (window);
- if (NSPointInRect ([theEvent locationInWindow], r))
- {
- ns_in_resize = YES;
- [window mouseDown: theEvent];
- return;
- }
- }
-#endif
-
if (type == NSApplicationDefined)
{
/* Events posted by ns_send_appdefined interrupt the run loop here.
@@ -4359,7 +4322,7 @@ ns_term_shutdown (int sig)
modal loop. Just defer it until later. */
if ([NSApp modalWindow] == nil)
{
- last_appdefined_event = theEvent;
+ last_appdefined_event_data = [theEvent data1];
[self stop: self];
}
else
@@ -4534,10 +4497,10 @@ not_in_argv (NSString *arg)
/* Don't open files from the command line unconditionally,
Cocoa parses the command line wrong, --option value tries to open value
if --option is the last option. */
- while ((file = [files nextObject]) != nil)
+ while ((file = [files nextObject]) != nil)
if (ns_do_open_file || not_in_argv (file))
[ns_pending_files addObject: file];
-
+
[self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
}
@@ -4604,7 +4567,7 @@ not_in_argv (NSString *arg)
/* NSTRACE (fd_handler); */
- for (;;)
+ for (;;)
{
[pool release];
pool = [[NSAutoreleasePool alloc] init];
@@ -4612,14 +4575,11 @@ not_in_argv (NSString *arg)
if (waiting)
{
SELECT_TYPE fds;
-
+ FD_ZERO (&fds);
FD_SET (selfds[0], &fds);
result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
- if (result > 0)
- {
- read (selfds[0], &c, 1);
- if (c == 'g') waiting = 0;
- }
+ if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
+ waiting = 0;
}
else
{
@@ -4659,8 +4619,8 @@ not_in_argv (NSString *arg)
{
if (FD_ISSET (selfds[0], &readfds))
{
- read (selfds[0], &c, 1);
- if (c == 's') waiting = 1;
+ if (read (selfds[0], &c, 1) == 1 && c == 's')
+ waiting = 1;
}
else
{
@@ -4744,6 +4704,8 @@ not_in_argv (NSString *arg)
{
NSTRACE (EmacsView_dealloc);
[toolbar release];
+ if (fs_state == FULLSCREEN_BOTH)
+ [nonfs_window release];
[super dealloc];
}
@@ -4809,12 +4771,12 @@ not_in_argv (NSString *arg)
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
int code;
unsigned fnKeysym = 0;
- int flags;
static NSMutableArray *nsEvArray;
#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
static BOOL firstTime = YES;
#endif
int left_is_none;
+ unsigned int flags = [theEvent modifierFlags];
NSTRACE (keyDown);
@@ -4865,7 +4827,10 @@ not_in_argv (NSString *arg)
/* (Carbon way: [theEvent keyCode]) */
/* is it a "function key"? */
- fnKeysym = ns_convert_key (code);
+ fnKeysym = (code < 0x00ff && (flags&NSNumericPadKeyMask))
+ ? ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask)
+ : ns_convert_key (code);
+
if (fnKeysym)
{
/* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
@@ -4878,7 +4843,6 @@ not_in_argv (NSString *arg)
/* are there modifiers? */
emacs_event->modifiers = 0;
- flags = [theEvent modifierFlags];
if (flags & NSHelpKeyMask)
emacs_event->modifiers |= hyper_modifier;
@@ -4889,7 +4853,7 @@ not_in_argv (NSString *arg)
is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask;
is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
|| (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask);
-
+
if (is_right_key)
emacs_event->modifiers |= parse_solitary_modifier
(EQ (ns_right_command_modifier, Qleft)
@@ -5420,6 +5384,51 @@ not_in_argv (NSString *arg)
return NO;
}
+- (void) updateFrameSize: (BOOL) delay;
+{
+ NSWindow *window = [self window];
+ NSRect wr = [window frame];
+#ifdef NS_IMPL_GNUSTEP
+ int extra = 3;
+#else
+ int extra = 0;
+#endif
+
+ int oldc = cols, oldr = rows;
+ int oldw = FRAME_PIXEL_WIDTH (emacsframe),
+ oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+ int neww, newh;
+
+ cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + extra);
+
+ if (cols < MINWIDTH)
+ cols = MINWIDTH;
+
+ rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES
+ (emacsframe, wr.size.height
+ - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + extra
+ - FRAME_TOOLBAR_HEIGHT (emacsframe));
+
+ if (rows < MINHEIGHT)
+ rows = MINHEIGHT;
+
+ neww = (int)wr.size.width - emacsframe->border_width;
+ newh = ((int)wr.size.height
+ - FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
+ - FRAME_TOOLBAR_HEIGHT (emacsframe));
+
+ if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
+ {
+ NSView *view = FRAME_NS_VIEW (emacsframe);
+ FRAME_PIXEL_WIDTH (emacsframe) = neww;
+ FRAME_PIXEL_HEIGHT (emacsframe) = newh;
+ change_frame_size (emacsframe, rows, cols, 0, delay, 0);
+ SET_FRAME_GARBAGED (emacsframe);
+ cancel_mouse_face (emacsframe);
+ [view setFrame: NSMakeRect (0, 0, neww, newh)];
+ [self windowDidMove:nil]; // Update top/left.
+ }
+}
- (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
/* normalize frame to gridded text size */
@@ -5427,6 +5436,19 @@ not_in_argv (NSString *arg)
NSTRACE (windowWillResize);
/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
+ if (fs_state == FULLSCREEN_MAXIMIZED
+ && (maximized_width != (int)frameSize.width
+ || maximized_height != (int)frameSize.height))
+ [self setFSValue: FULLSCREEN_NONE];
+ else if (fs_state == FULLSCREEN_WIDTH
+ && maximized_width != (int)frameSize.width)
+ [self setFSValue: FULLSCREEN_NONE];
+ else if (fs_state == FULLSCREEN_HEIGHT
+ && maximized_height != (int)frameSize.height)
+ [self setFSValue: FULLSCREEN_NONE];
+ if (fs_state == FULLSCREEN_NONE)
+ maximized_width = maximized_height = -1;
+
cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
#ifdef NS_IMPL_GNUSTEP
frameSize.width + 3);
@@ -5486,10 +5508,17 @@ not_in_argv (NSString *arg)
- (void)windowDidResize: (NSNotification *)notification
{
+
+#if !defined (NEW_STYLE_FS) && ! defined (NS_IMPL_GNUSTEP)
+ NSWindow *theWindow = [notification object];
+ /* We can get notification on the non-FS window when in fullscreen mode. */
+ if ([self window] != theWindow) return;
+#endif
+
#ifdef NS_IMPL_GNUSTEP
NSWindow *theWindow = [notification object];
- /* in GNUstep, at least currently, it's possible to get a didResize
+ /* In GNUstep, at least currently, it's possible to get a didResize
without getting a willResize.. therefore we need to act as if we got
the willResize now */
NSSize sz = [theWindow frame].size;
@@ -5507,29 +5536,10 @@ not_in_argv (NSString *arg)
}
#endif /* NS_IMPL_COCOA */
- /* Avoid loop under GNUstep due to call at beginning of this function.
- (x_set_window_size causes a resize which causes
- a "windowDidResize" which calls x_set_window_size). */
-#ifndef NS_IMPL_GNUSTEP
if (cols > 0 && rows > 0)
{
- if (ns_in_resize)
- x_set_window_size (emacsframe, 0, cols, rows);
- else
- {
- NSWindow *window = [self window];
- NSRect wr = [window frame];
- FRAME_PIXEL_WIDTH (emacsframe) = (int)wr.size.width
- - emacsframe->border_width;
- FRAME_PIXEL_HEIGHT (emacsframe) = (int)wr.size.height
- - FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
- - FRAME_TOOLBAR_HEIGHT (emacsframe);
- change_frame_size (emacsframe, rows, cols, 0, 0, 1);
- SET_FRAME_GARBAGED (emacsframe);
- cancel_mouse_face (emacsframe);
- }
+ [self updateFrameSize: YES];
}
-#endif
ns_send_appdefined (-1);
}
@@ -5617,6 +5627,10 @@ not_in_argv (NSString *arg)
windowClosing = NO;
processingCompose = NO;
scrollbarsNeedingUpdate = 0;
+ fs_state = FULLSCREEN_NONE;
+ fs_before_fs = next_maximized = -1;
+ maximized_width = maximized_height = -1;
+ nonfs_window = nil;
/*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
@@ -5641,9 +5655,13 @@ not_in_argv (NSString *arg)
backing: NSBackingStoreBuffered
defer: YES];
+#ifdef NEW_STYLE_FS
+ [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+#endif
+
wr = [win frame];
- f->border_width = wr.size.width - r.size.width;
- FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
+ bwidth = f->border_width = wr.size.width - r.size.width;
+ tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
[win setAcceptsMouseMovedEvents: YES];
[win setDelegate: self];
@@ -5749,27 +5767,50 @@ not_in_argv (NSString *arg)
NSTRACE (windowWillUseStandardFrame);
- if (abs (defaultFrame.size.height - result.size.height)
- > FRAME_LINE_HEIGHT (emacsframe))
+ if (fs_before_fs != -1) /* Entering fullscreen */
+ {
+ result = defaultFrame;
+ }
+ else if (next_maximized == FULLSCREEN_HEIGHT
+ || (next_maximized == -1
+ && abs (defaultFrame.size.height - result.size.height)
+ > FRAME_LINE_HEIGHT (emacsframe)))
{
/* first click */
ns_userRect = result;
- result.size.height = defaultFrame.size.height;
+ maximized_height = result.size.height = defaultFrame.size.height;
+ maximized_width = -1;
result.origin.y = defaultFrame.origin.y;
+ [self setFSValue: FULLSCREEN_HEIGHT];
+ }
+ else if (next_maximized == FULLSCREEN_WIDTH)
+ {
+ ns_userRect = result;
+ maximized_width = result.size.width = defaultFrame.size.width;
+ maximized_height = -1;
+ result.origin.x = defaultFrame.origin.x;
+ [self setFSValue: FULLSCREEN_WIDTH];
+ }
+ else if (next_maximized == FULLSCREEN_MAXIMIZED
+ || (next_maximized == -1
+ && abs (defaultFrame.size.width - result.size.width)
+ > FRAME_COLUMN_WIDTH (emacsframe)))
+ {
+ result = defaultFrame; /* second click */
+ maximized_width = result.size.width;
+ maximized_height = result.size.height;
+ [self setFSValue: FULLSCREEN_MAXIMIZED];
}
else
{
- if (abs (defaultFrame.size.width - result.size.width)
- > FRAME_COLUMN_WIDTH (emacsframe))
- result = defaultFrame; /* second click */
- else
- {
- /* restore */
- result = ns_userRect.size.height ? ns_userRect : result;
- ns_userRect = NSMakeRect (0, 0, 0, 0);
- }
+ /* restore */
+ result = ns_userRect.size.height ? ns_userRect : result;
+ ns_userRect = NSMakeRect (0, 0, 0, 0);
+ [self setFSValue: FULLSCREEN_NONE];
+ maximized_width = maximized_width = -1;
}
+ if (fs_before_fs == -1) next_maximized = -1;
[self windowWillResize: sender toSize: result.size];
return result;
}
@@ -5821,6 +5862,211 @@ not_in_argv (NSString *arg)
}
}
+- (void)windowWillEnterFullScreen:(NSNotification *)notification
+{
+ fs_before_fs = fs_state;
+}
+
+- (void)windowDidEnterFullScreen:(NSNotification *)notification
+{
+ [self setFSValue: FULLSCREEN_BOTH];
+#ifdef NEW_STYLE_FS
+ // Fix bad background.
+ if ([toolbar isVisible])
+ {
+ [toolbar setVisible:NO];
+ [toolbar setVisible:YES];
+ }
+#else
+ [self windowDidBecomeKey:notification];
+ [nonfs_window orderOut:self];
+#endif
+}
+
+- (void)windowWillExitFullScreen:(NSNotification *)notification
+{
+ if (next_maximized != -1)
+ fs_before_fs = next_maximized;
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification
+{
+ [self setFSValue: fs_before_fs];
+ fs_before_fs = -1;
+ if (next_maximized != -1)
+ [[self window] performZoom:self];
+}
+
+- (void)toggleFullScreen: (id)sender
+{
+#ifdef NEW_STYLE_FS
+ [[self window] toggleFullScreen:sender];
+#else
+ NSWindow *w = [self window], *fw;
+ BOOL onFirstScreen = [[w screen]
+ isEqual:[[NSScreen screens] objectAtIndex:0]];
+ struct frame *f = emacsframe;
+ NSSize sz;
+ NSRect r, wr = [w frame];
+ NSColor *col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
+ (FRAME_DEFAULT_FACE (f)),
+ f);
+
+ sz.width = FRAME_COLUMN_WIDTH (f);
+ sz.height = FRAME_LINE_HEIGHT (f);
+
+ if (fs_state != FULLSCREEN_BOTH)
+ {
+ /* 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
+ NSApplicationPresentationOptions options
+ = NSApplicationPresentationAutoHideDock
+ | NSApplicationPresentationAutoHideMenuBar;
+
+ [NSApp setPresentationOptions: options];
+#else
+ [NSMenu setMenuBarVisible:NO];
+#endif
+ }
+
+ fw = [[EmacsFSWindow alloc]
+ initWithContentRect:[w contentRectForFrameRect:wr]
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES
+ screen:[w screen]];
+
+ [fw setContentView:[w contentView]];
+ [fw setTitle:[w title]];
+ [fw setDelegate:self];
+ [fw setAcceptsMouseMovedEvents: YES];
+ [fw useOptimizedDrawing: YES];
+ [fw setResizeIncrements: sz];
+ [fw setBackgroundColor: col];
+ if ([col alphaComponent] != 1.0)
+ [fw setOpaque: NO];
+
+ f->border_width = 0;
+ FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
+ tobar_height = FRAME_TOOLBAR_HEIGHT (f);
+ FRAME_TOOLBAR_HEIGHT (f) = 0;
+ FRAME_EXTERNAL_TOOL_BAR (f) = 0;
+
+ nonfs_window = w;
+
+ [self windowWillEnterFullScreen:nil];
+ [fw makeKeyAndOrderFront:NSApp];
+ [fw makeFirstResponder:self];
+ [w orderOut:self];
+ r = [fw frameRectForContentRect:[[fw screen] frame]];
+ [fw setFrame: r display:YES animate:YES];
+ [self windowDidEnterFullScreen:nil];
+ [fw display];
+ }
+ else
+ {
+ fw = w;
+ w = nonfs_window;
+ nonfs_window = nil;
+
+ if (onFirstScreen)
+ {
+#if defined (NS_IMPL_COCOA) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ [NSApp setPresentationOptions: NSApplicationPresentationDefault];
+#else
+ [NSMenu setMenuBarVisible:YES];
+#endif
+ }
+
+ [w setContentView:[fw contentView]];
+ [w setResizeIncrements: sz];
+ [w setBackgroundColor: col];
+ if ([col alphaComponent] != 1.0)
+ [w setOpaque: NO];
+
+ f->border_width = bwidth;
+ FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
+ FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
+ if (tobar_height)
+ FRAME_EXTERNAL_TOOL_BAR (f) = 1;
+
+ [self windowWillExitFullScreen:nil];
+ [fw setFrame: [w frame] display:YES animate:YES];
+ [fw close];
+ [w makeKeyAndOrderFront:NSApp];
+ [self windowDidExitFullScreen:nil];
+ }
+#endif
+}
+
+- (void)handleFS
+{
+ if (fs_state != emacsframe->want_fullscreen)
+ {
+ if (fs_state == FULLSCREEN_BOTH)
+ {
+ [self toggleFullScreen:self];
+ }
+
+ switch (emacsframe->want_fullscreen)
+ {
+ case FULLSCREEN_BOTH:
+ [self toggleFullScreen:self];
+ break;
+ case FULLSCREEN_WIDTH:
+ next_maximized = FULLSCREEN_WIDTH;
+ if (fs_state != FULLSCREEN_BOTH)
+ [[self window] performZoom:self];
+ break;
+ case FULLSCREEN_HEIGHT:
+ next_maximized = FULLSCREEN_HEIGHT;
+ if (fs_state != FULLSCREEN_BOTH)
+ [[self window] performZoom:self];
+ break;
+ case FULLSCREEN_MAXIMIZED:
+ next_maximized = FULLSCREEN_MAXIMIZED;
+ if (fs_state != FULLSCREEN_BOTH)
+ [[self window] performZoom:self];
+ break;
+ case FULLSCREEN_NONE:
+ if (fs_state != FULLSCREEN_BOTH)
+ {
+ next_maximized = FULLSCREEN_NONE;
+ [[self window] performZoom:self];
+ }
+ break;
+ }
+
+ emacsframe->want_fullscreen = FULLSCREEN_NONE;
+ }
+
+}
+
+- (void) setFSValue: (int)value
+{
+ Lisp_Object lval = Qnil;
+ switch (value)
+ {
+ case FULLSCREEN_BOTH:
+ lval = Qfullboth;
+ break;
+ case FULLSCREEN_WIDTH:
+ lval = Qfullwidth;
+ break;
+ case FULLSCREEN_HEIGHT:
+ lval = Qfullheight;
+ break;
+ case FULLSCREEN_MAXIMIZED:
+ lval = Qmaximized;
+ break;
+ }
+ store_frame_param (emacsframe, Qfullscreen, lval);
+ fs_state = value;
+}
- (void)mouseEntered: (NSEvent *)theEvent
{
@@ -5853,7 +6099,7 @@ not_in_argv (NSString *arg)
NSTRACE (menuDown);
if (context_menu_value == -1)
context_menu_value = [sender tag];
- else
+ else
{
NSInteger tag = [sender tag];
find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
@@ -5918,7 +6164,7 @@ not_in_argv (NSString *arg)
NSTRACE (drawRect);
- if (!emacsframe || !emacsframe->output_data.ns || ns_in_resize)
+ if (!emacsframe || !emacsframe->output_data.ns)
return;
ns_clear_frame_area (emacsframe, x, y, width, height);
@@ -6180,7 +6426,7 @@ not_in_argv (NSString *arg)
Lisp_Object str = Qnil;
struct frame *f = SELECTED_FRAME ();
struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer);
-
+
if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
return NSAccessibilityTextFieldRole;
@@ -6193,13 +6439,13 @@ not_in_argv (NSString *arg)
{
if (! NILP (BVAR (curbuf, mark_active)))
str = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
-
+
if (NILP (str))
{
ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf);
ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte;
ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf);
-
+
if (! NILP (BVAR (curbuf, enable_multibyte_characters)))
str = make_uninit_multibyte_string (range, byte_range);
else
@@ -6209,9 +6455,9 @@ not_in_argv (NSString *arg)
memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range);
}
}
-
-
- if (! NILP (str))
+
+
+ if (! NILP (str))
{
if (CONSP (str) && SYMBOLP (XCAR (str)))
{
@@ -6226,7 +6472,7 @@ not_in_argv (NSString *arg)
return nsStr;
}
}
-
+
return [super accessibilityAttributeValue:attribute];
}
#endif /* NS_IMPL_COCOA */
@@ -6242,7 +6488,10 @@ not_in_argv (NSString *arg)
NSTRACE (constrainFrameRect);
if (nr_screens == 1)
- return [super constrainFrameRect:frameRect toScreen:screen];
+ {
+ NSRect r = [super constrainFrameRect:frameRect toScreen:screen];
+ return r;
+ }
if (f->output_data.ns->dont_constrain
|| ns_menu_bar_should_be_hidden ())
@@ -6252,62 +6501,22 @@ not_in_argv (NSString *arg)
return [super constrainFrameRect:frameRect toScreen:screen];
}
+@end /* EmacsWindow */
-/* called only on resize clicks by special case in EmacsApp-sendEvent */
-- (void)mouseDown: (NSEvent *)theEvent
-{
- if (ns_in_resize)
- {
- NSSize size = [[theEvent window] frame].size;
- grabOffset = [theEvent locationInWindow];
- grabOffset.x = size.width - grabOffset.x;
- }
- else
- [super mouseDown: theEvent];
-}
+@implementation EmacsFSWindow
-/* stop resizing */
-- (void)mouseUp: (NSEvent *)theEvent
+- (BOOL)canBecomeKeyWindow
{
- if (ns_in_resize)
- {
- struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
- ns_in_resize = NO;
- ns_set_name_as_filename (f);
- [self display];
- ns_send_appdefined (-1);
- }
- else
- [super mouseUp: theEvent];
+ return YES;
}
-
-/* send resize events */
-- (void)mouseDragged: (NSEvent *)theEvent
+- (BOOL)canBecomeMainWindow
{
- if (ns_in_resize)
- {
- NSPoint p = [theEvent locationInWindow];
- NSSize size, vettedSize, origSize = [self frame].size;
-
- size.width = p.x + grabOffset.x;
- size.height = origSize.height - p.y + grabOffset.y;
-
- if (size.width == origSize.width && size.height == origSize.height)
- return;
-
- vettedSize = [[self delegate] windowWillResize: self toSize: size];
- [[NSNotificationCenter defaultCenter]
- postNotificationName: NSWindowDidResizeNotification
- object: self];
- }
- else
- [super mouseDragged: theEvent];
+ return YES;
}
-@end /* EmacsWindow */
-
+@end
/* ==========================================================================
@@ -6379,13 +6588,13 @@ not_in_argv (NSString *arg)
- (void)setFrame: (NSRect)newRect
{
NSTRACE (EmacsScroller_setFrame);
-/* BLOCK_INPUT; */
+/* block_input (); */
pixel_height = NSHeight (newRect);
if (pixel_height == 0) pixel_height = 1;
min_portion = 20 / pixel_height;
[super setFrame: newRect];
[self display];
-/* UNBLOCK_INPUT; */
+/* unblock_input (); */
}
@@ -6420,14 +6629,14 @@ not_in_argv (NSString *arg)
if (condemned)
{
EmacsView *view;
- BLOCK_INPUT;
+ block_input ();
/* ensure other scrollbar updates after deletion */
view = (EmacsView *)FRAME_NS_VIEW (frame);
if (view != nil)
view->scrollbarsNeedingUpdate++;
[self removeFromSuperview];
[self release];
- UNBLOCK_INPUT;
+ unblock_input ();
}
return self;
}
@@ -6482,6 +6691,12 @@ not_in_argv (NSString *arg)
[self setFloatValue: pos knobProportion: por];
#endif
}
+
+ /* Events may come here even if the event loop is not running.
+ If we don't enter the event loop, the scroll bar will not update.
+ So send SIGIO to ourselves. */
+ if (apploopnr == 0) raise (SIGIO);
+
return self;
}
@@ -6522,7 +6737,7 @@ not_in_argv (NSString *arg)
kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
}
else
- kbd_buffer_store_event (emacs_event);
+ hold_event (emacs_event);
EVENT_INIT (*emacs_event);
ns_send_appdefined (-1);
}
@@ -6739,7 +6954,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_SPACE_WIDTH (f) = font->space_width;
FRAME_LINE_HEIGHT (f) = font->height;
compute_fringe_widths (f, 1);
@@ -6922,7 +7136,7 @@ allowing it to be used at a lower level for accented character entry.");
ns_function_modifier = Qnone;
DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
- "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above.");
+ "Non-nil (the default) means to render text antialiased.");
ns_antialias_text = Qt;
DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
diff --git a/src/print.c b/src/print.c
index 3cf5fc7348d..71efb61e732 100644
--- a/src/print.c
+++ b/src/print.c
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
@@ -45,15 +45,9 @@ static Lisp_Object Qtemp_buffer_setup_hook;
static Lisp_Object Qfloat_output_format;
-#include <math.h>
#include <float.h>
#include <ftoastr.h>
-/* Default to values appropriate for IEEE floating point. */
-#ifndef DBL_DIG
-#define DBL_DIG 15
-#endif
-
/* Avoid actual stack overflow in print. */
static ptrdiff_t print_depth;
@@ -759,9 +753,9 @@ append to existing target file. */)
{
if (initial_stderr_stream != NULL)
{
- BLOCK_INPUT;
+ block_input ();
fclose (stderr);
- UNBLOCK_INPUT;
+ unblock_input ();
}
stderr = initial_stderr_stream;
initial_stderr_stream = NULL;
@@ -804,7 +798,7 @@ safe_debug_print (Lisp_Object arg)
else
fprintf (stderr, "#<%s_LISP_OBJECT 0x%08"pI"x>\r\n",
!valid ? "INVALID" : "SOME",
- XHASH (arg));
+ XLI (arg));
}
@@ -1821,14 +1815,14 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
#endif
/* Implement a readable output, e.g.:
#s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
- /* Always print the size. */
+ /* Always print the size. */
len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next));
strout (buf, len, len, printcharfun);
- if (!NILP (h->test))
+ if (!NILP (h->test.name))
{
strout (" test ", -1, -1, printcharfun);
- print_object (h->test, printcharfun, escapeflag);
+ print_object (h->test.name, printcharfun, escapeflag);
}
if (!NILP (h->weak))
@@ -1879,7 +1873,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
}
else if (BUFFERP (obj))
{
- if (NILP (BVAR (XBUFFER (obj), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (obj)))
strout ("#<killed buffer>", -1, -1, printcharfun);
else if (escapeflag)
{
@@ -2096,7 +2090,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
{
int len;
/* We're in trouble if this happens!
- Probably should just abort () */
+ Probably should just emacs_abort (). */
strout ("#<EMACS BUG: INVALID DATATYPE ", -1, -1, printcharfun);
if (MISCP (obj))
len = sprintf (buf, "(MISC 0x%04x)", (int) XMISCTYPE (obj));
@@ -2117,7 +2111,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
/* Print a description of INTERVAL using PRINTCHARFUN.
This is part of printing a string that has text properties. */
-void
+static void
print_interval (INTERVAL interval, Lisp_Object printcharfun)
{
if (NILP (interval->plist))
diff --git a/src/process.c b/src/process.c
index dbbb23b8627..7f647d44a93 100644
--- a/src/process.c
+++ b/src/process.c
@@ -23,15 +23,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define PROCESS_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
#include <errno.h>
-#include <setjmp.h>
#include <sys/types.h> /* Some typedefs are used in sys/file.h. */
#include <sys/file.h>
#include <sys/stat.h>
-#include <setjmp.h>
-
#include <unistd.h>
#include <fcntl.h>
@@ -76,6 +72,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <bsdtty.h>
#endif
+#ifdef USG5_4
+# include <sys/stream.h>
+# include <sys/stropts.h>
+#endif
+
#ifdef HAVE_RES_INIT
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -90,6 +91,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <pty.h>
#endif
+#include <c-ctype.h>
+#include <sig2str.h>
+
#endif /* subprocesses */
#include "systime.h"
@@ -124,6 +128,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "xgselect.h"
#endif
+#ifdef WINDOWSNT
+extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+ EMACS_TIME *, void *);
+#endif
+
/* Work around GCC 4.7.0 bug with strict overflow checking; see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
These lines can be removed once the GCC bug is fixed. */
@@ -190,11 +199,9 @@ static EMACS_INT update_tick;
#ifndef NON_BLOCKING_CONNECT
#ifdef HAVE_SELECT
#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
-#if defined (O_NONBLOCK) || defined (O_NDELAY)
#if defined (EWOULDBLOCK) || defined (EINPROGRESS)
#define NON_BLOCKING_CONNECT
#endif /* EWOULDBLOCK || EINPROGRESS */
-#endif /* O_NONBLOCK || O_NDELAY */
#endif /* HAVE_GETPEERNAME || GNU_LINUX */
#endif /* HAVE_SELECT */
#endif /* NON_BLOCKING_CONNECT */
@@ -205,17 +212,13 @@ static EMACS_INT update_tick;
"non-destructive" select. So we require either native select,
or emulation of select using FIONREAD. */
-#ifdef BROKEN_DATAGRAM_SOCKETS
-#undef DATAGRAM_SOCKETS
-#else
-#ifndef DATAGRAM_SOCKETS
-#if defined (HAVE_SELECT) || defined (FIONREAD)
-#if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE)
-#define DATAGRAM_SOCKETS
-#endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */
-#endif /* HAVE_SELECT || FIONREAD */
-#endif /* DATAGRAM_SOCKETS */
-#endif /* BROKEN_DATAGRAM_SOCKETS */
+#ifndef BROKEN_DATAGRAM_SOCKETS
+# if defined HAVE_SELECT || defined USABLE_FIONREAD
+# if defined HAVE_SENDTO && defined HAVE_RECVFROM && defined EMSGSIZE
+# define DATAGRAM_SOCKETS
+# endif
+# endif
+#endif
#if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS
# define HAVE_SEQPACKET
@@ -244,17 +247,18 @@ static int process_output_skip;
#endif
static void create_process (Lisp_Object, char **, Lisp_Object);
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
static int keyboard_bit_set (SELECT_TYPE *);
#endif
static void deactivate_process (Lisp_Object);
static void status_notify (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. */
-#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_ASYNC_EVENTS)
+#ifdef HAVE_WINDOW_SYSTEM
#define POLL_FOR_INPUT
#endif
@@ -303,91 +307,88 @@ static struct sockaddr_and_len {
#define DATAGRAM_CONN_P(proc) (0)
#endif
-/* Maximum number of bytes to send to a pty without an eof. */
-static int pty_max_bytes;
-
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
pset_buffer (struct Lisp_Process *p, Lisp_Object val)
{
p->buffer = val;
}
-static inline void
+static void
pset_command (struct Lisp_Process *p, Lisp_Object val)
{
p->command = val;
}
-static inline void
+static void
pset_decode_coding_system (struct Lisp_Process *p, Lisp_Object val)
{
p->decode_coding_system = val;
}
-static inline void
+static void
pset_decoding_buf (struct Lisp_Process *p, Lisp_Object val)
{
p->decoding_buf = val;
}
-static inline void
+static void
pset_encode_coding_system (struct Lisp_Process *p, Lisp_Object val)
{
p->encode_coding_system = val;
}
-static inline void
+static void
pset_encoding_buf (struct Lisp_Process *p, Lisp_Object val)
{
p->encoding_buf = val;
}
-static inline void
+static void
pset_filter (struct Lisp_Process *p, Lisp_Object val)
{
p->filter = val;
}
-static inline void
+static void
pset_log (struct Lisp_Process *p, Lisp_Object val)
{
p->log = val;
}
-static inline void
+static void
pset_mark (struct Lisp_Process *p, Lisp_Object val)
{
p->mark = val;
}
-static inline void
+static void
pset_thread (struct Lisp_Process *p, Lisp_Object val)
{
p->thread = val;
}
-static inline void
+static void
pset_name (struct Lisp_Process *p, Lisp_Object val)
{
p->name = val;
}
-static inline void
+static void
pset_plist (struct Lisp_Process *p, Lisp_Object val)
{
p->plist = val;
}
-static inline void
+static void
pset_sentinel (struct Lisp_Process *p, Lisp_Object val)
{
p->sentinel = val;
}
-static inline void
+static void
pset_status (struct Lisp_Process *p, Lisp_Object val)
{
p->status = val;
}
-static inline void
+static void
pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
{
p->tty_name = val;
}
-static inline void
+static void
pset_type (struct Lisp_Process *p, Lisp_Object val)
{
p->type = val;
}
-static inline void
+static void
pset_write_queue (struct Lisp_Process *p, Lisp_Object val)
{
p->write_queue = val;
@@ -703,7 +704,7 @@ status_message (struct Lisp_Process *p)
if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
{
- char *signame;
+ char const *signame;
synchronize_system_messages_locale ();
signame = strsignal (code);
if (signame == 0)
@@ -778,30 +779,7 @@ allocate_pty (void)
#ifdef PTY_OPEN
PTY_OPEN;
#else /* no PTY_OPEN */
- {
- { /* Some systems name their pseudoterminals so that there are gaps in
- the usual sequence - for example, on HP9000/S700 systems, there
- are no pseudoterminals with names ending in 'f'. So we wait for
- three failures in a row before deciding that we've reached the
- end of the ptys. */
- int failed_count = 0;
- struct stat stb;
-
- if (stat (pty_name, &stb) < 0)
- {
- failed_count++;
- if (failed_count >= 3)
- return -1;
- }
- else
- failed_count = 0;
- }
-# ifdef O_NONBLOCK
- fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
-# else
- fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
-# endif
- }
+ fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
#endif /* no PTY_OPEN */
if (fd >= 0)
@@ -813,7 +791,7 @@ allocate_pty (void)
#else
sprintf (pty_name, "/dev/tty%c%x", c, i);
#endif /* no PTY_TTY_NAME_SPRINTF */
- if (access (pty_name, 6) != 0)
+ if (faccessat (AT_FDCWD, pty_name, R_OK | W_OK, AT_EACCESS) != 0)
{
emacs_close (fd);
# ifndef __sgi
@@ -959,14 +937,22 @@ get_process (register Lisp_Object name)
}
-#ifdef SIGCHLD
/* Fdelete_process promises to immediately forget about the process, but in
reality, Emacs needs to remember those processes until they have been
- treated by sigchld_handler; otherwise this handler would consider the
- process as being synchronous and say that the synchronous process is
- dead. */
+ treated by the SIGCHLD handler and waitpid has been invoked on them;
+ otherwise they might fill up the kernel's process table.
+
+ Some processes created by call-process are also put onto this list. */
static Lisp_Object deleted_pid_list;
-#endif
+
+void
+record_deleted_pid (pid_t pid)
+{
+ deleted_pid_list = Fcons (make_fixnum_or_float (pid),
+ /* GC treated elements set to nil. */
+ Fdelq (Qnil, deleted_pid_list));
+
+}
DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
doc: /* Delete PROCESS: kill it and forget about it immediately.
@@ -987,31 +973,22 @@ nil, indicating the current buffer's process. */)
status_notify (p);
redisplay_preserve_echo_area (13);
}
- else if (p->infd >= 0)
+ else
{
-#ifdef SIGCHLD
- Lisp_Object symbol;
- pid_t pid = p->pid;
-
- /* No problem storing the pid here, as it is still in Vprocess_alist. */
- deleted_pid_list = Fcons (make_fixnum_or_float (pid),
- /* GC treated elements set to nil. */
- Fdelq (Qnil, deleted_pid_list));
- /* If the process has already signaled, remove it from the list. */
- if (p->raw_status_new)
- update_status (p);
- symbol = p->status;
- if (CONSP (p->status))
- symbol = XCAR (p->status);
- if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
- deleted_pid_list
- = Fdelete (make_fixnum_or_float (pid), deleted_pid_list);
- else
-#endif
+ if (p->alive)
+ record_kill_process (p);
+
+ if (p->infd >= 0)
{
- Fkill_process (process, Qnil);
- /* Do this now, since remove_process will make sigchld_handler do nothing. */
- pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)));
+ /* Update P's status, since record_kill_process will make the
+ SIGCHLD handler update deleted_pid_list, not *P. */
+ Lisp_Object symbol;
+ if (p->raw_status_new)
+ update_status (p);
+ symbol = CONSP (p->status) ? XCAR (p->status) : p->status;
+ if (! (EQ (symbol, Qsignal) || EQ (symbol, Qexit)))
+ pset_status (p, list2 (Qsignal, make_number (SIGKILL)));
+
p->tick = ++process_tick;
status_notify (p);
redisplay_preserve_echo_area (13);
@@ -1768,7 +1745,7 @@ static Lisp_Object
start_process_unwind (Lisp_Object proc)
{
if (!PROCESSP (proc))
- abort ();
+ emacs_abort ();
/* Was PROC started successfully?
-2 is used for a pty with no process, eg for gdb. */
@@ -1791,20 +1768,15 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
int inchannel, outchannel;
pid_t pid;
int sv[2];
-#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+#ifndef WINDOWSNT
int wait_child_setup[2];
#endif
- sigset_t procmask;
sigset_t blocked;
- struct sigaction sigint_action;
- struct sigaction sigquit_action;
- struct sigaction sigpipe_action;
-#ifdef AIX
- struct sigaction sighup_action;
-#endif
- /* Use volatile to protect variables from being clobbered by longjmp. */
+ /* Use volatile to protect variables from being clobbered by vfork. */
volatile int forkin, forkout;
volatile int pty_flag = 0;
+ volatile Lisp_Object lisp_pty_name = Qnil;
+ volatile Lisp_Object encoded_current_dir;
inchannel = outchannel = -1;
@@ -1817,19 +1789,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
/* On most USG systems it does not work to open the pty's tty here,
then close it and reopen it in the child. */
-#ifdef O_NOCTTY
/* Don't let this terminal become our controlling terminal
(in case we don't have one). */
forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
-#else
- forkout = forkin = emacs_open (pty_name, O_RDWR, 0);
-#endif
if (forkin < 0)
report_file_error ("Opening pty", Qnil);
#else
forkin = forkout = -1;
#endif /* not USG, or USG_SUBTTY_WORKS */
pty_flag = 1;
+ lisp_pty_name = build_string (pty_name);
}
else
#endif /* HAVE_PTYS */
@@ -1851,7 +1820,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
forkin = sv[0];
}
-#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+#ifndef WINDOWSNT
{
int tem;
@@ -1870,15 +1839,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
}
#endif
-#ifdef O_NONBLOCK
fcntl (inchannel, F_SETFL, O_NONBLOCK);
fcntl (outchannel, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
- fcntl (inchannel, F_SETFL, O_NDELAY);
- fcntl (outchannel, F_SETFL, O_NDELAY);
-#endif
-#endif
/* Record this as an active process, with its channels.
As a result, child_setup will close Emacs's side of the pipes. */
@@ -1894,202 +1856,152 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
XPROCESS (process)->pty_flag = pty_flag;
pset_status (XPROCESS (process), Qrun);
- /* Delay interrupts until we have a chance to store
- the new fork's pid in its process structure */
- sigemptyset (&blocked);
-#ifdef SIGCHLD
- sigaddset (&blocked, SIGCHLD);
-#endif
-#ifdef HAVE_WORKING_VFORK
- /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal',
- this sets the parent's signal handlers as well as the child's.
- So delay all interrupts whose handlers the child might munge,
- and record the current handlers so they can be restored later. */
- sigaddset (&blocked, SIGINT ); sigaction (SIGINT , 0, &sigint_action );
- sigaddset (&blocked, SIGQUIT); sigaction (SIGQUIT, 0, &sigquit_action);
- sigaddset (&blocked, SIGPIPE); sigaction (SIGPIPE, 0, &sigpipe_action);
-#ifdef AIX
- sigaddset (&blocked, SIGHUP ); sigaction (SIGHUP , 0, &sighup_action );
-#endif
-#endif /* HAVE_WORKING_VFORK */
- pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
-
add_non_keyboard_read_fd (inchannel);
- /* Until we store the proper pid, enable sigchld_handler
- to recognize an unknown pid as standing for this process.
- It is very important not to let this `marker' value stay
- in the table after this function has returned; if it does
- it might cause call-process to hang and subsequent asynchronous
- processes to get their return values scrambled. */
- XPROCESS (process)->pid = -1;
-
- /* This must be called after the above line because it may signal an
- error. */
+ /* This may signal an error. */
setup_process_coding_systems (process);
- BLOCK_INPUT;
+ encoded_current_dir = ENCODE_FILE (current_dir);
- {
- /* child_setup must clobber environ on systems with true vfork.
- Protect it from permanent change. */
- char **save_environ = environ;
- volatile Lisp_Object encoded_current_dir = ENCODE_FILE (current_dir);
+ block_input ();
+
+ /* Block SIGCHLD until we have a chance to store the new fork's
+ pid in its process structure. */
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGCHLD);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
#ifndef WINDOWSNT
- pid = vfork ();
- if (pid == 0)
+ pid = vfork ();
+ if (pid == 0)
#endif /* not WINDOWSNT */
- {
- int xforkin = forkin;
- int xforkout = forkout;
-
-#if 0 /* This was probably a mistake--it duplicates code later on,
- but fails to handle all the cases. */
- /* Make sure SIGCHLD is not blocked in the child. */
- sigsetmask (SIGEMPTYMASK);
-#endif
+ {
+ int xforkin = forkin;
+ int xforkout = forkout;
- /* Make the pty be the controlling terminal of the process. */
+ /* Make the pty be the controlling terminal of the process. */
#ifdef HAVE_PTYS
- /* First, disconnect its current controlling terminal. */
-#ifdef HAVE_SETSID
- /* We tried doing setsid only if pty_flag, but it caused
- process_set_signal to fail on SGI when using a pipe. */
- setsid ();
- /* Make the pty's terminal the controlling terminal. */
- if (pty_flag && xforkin >= 0)
- {
+ /* First, disconnect its current controlling terminal. */
+ /* We tried doing setsid only if pty_flag, but it caused
+ process_set_signal to fail on SGI when using a pipe. */
+ setsid ();
+ /* Make the pty's terminal the controlling terminal. */
+ if (pty_flag && xforkin >= 0)
+ {
#ifdef TIOCSCTTY
- /* We ignore the return value
- because faith@cs.unc.edu says that is necessary on Linux. */
- ioctl (xforkin, TIOCSCTTY, 0);
+ /* We ignore the return value
+ because faith@cs.unc.edu says that is necessary on Linux. */
+ ioctl (xforkin, TIOCSCTTY, 0);
#endif
- }
-#else /* not HAVE_SETSID */
-#ifdef USG
- /* It's very important to call setpgrp here and no time
- afterwards. Otherwise, we lose our controlling tty which
- is set when we open the pty. */
- setpgrp ();
-#endif /* USG */
-#endif /* not HAVE_SETSID */
+ }
#if defined (LDISC1)
- if (pty_flag && xforkin >= 0)
- {
- struct termios t;
- tcgetattr (xforkin, &t);
- t.c_lflag = LDISC1;
- if (tcsetattr (xforkin, TCSANOW, &t) < 0)
- emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
- }
+ if (pty_flag && xforkin >= 0)
+ {
+ struct termios t;
+ tcgetattr (xforkin, &t);
+ t.c_lflag = LDISC1;
+ if (tcsetattr (xforkin, TCSANOW, &t) < 0)
+ emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
+ }
#else
#if defined (NTTYDISC) && defined (TIOCSETD)
- if (pty_flag && xforkin >= 0)
- {
- /* Use new line discipline. */
- int ldisc = NTTYDISC;
- ioctl (xforkin, TIOCSETD, &ldisc);
- }
+ if (pty_flag && xforkin >= 0)
+ {
+ /* Use new line discipline. */
+ int ldisc = NTTYDISC;
+ ioctl (xforkin, TIOCSETD, &ldisc);
+ }
#endif
#endif
#ifdef TIOCNOTTY
- /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
- can do TIOCSPGRP only to the process's controlling tty. */
- if (pty_flag)
- {
- /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
- I can't test it since I don't have 4.3. */
- int j = emacs_open ("/dev/tty", O_RDWR, 0);
- if (j >= 0)
- {
- ioctl (j, TIOCNOTTY, 0);
- emacs_close (j);
- }
-#ifndef USG
- /* In order to get a controlling terminal on some versions
- of BSD, it is necessary to put the process in pgrp 0
- before it opens the terminal. */
-#ifdef HAVE_SETPGID
- setpgid (0, 0);
-#else
- setpgrp (0, 0);
-#endif
-#endif
- }
+ /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
+ can do TIOCSPGRP only to the process's controlling tty. */
+ if (pty_flag)
+ {
+ /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
+ I can't test it since I don't have 4.3. */
+ int j = emacs_open ("/dev/tty", O_RDWR, 0);
+ if (j >= 0)
+ {
+ ioctl (j, TIOCNOTTY, 0);
+ emacs_close (j);
+ }
+ }
#endif /* TIOCNOTTY */
#if !defined (DONT_REOPEN_PTY)
/*** There is a suggestion that this ought to be a
- conditional on TIOCSPGRP,
- or !(defined (HAVE_SETSID) && defined (TIOCSCTTY)).
+ conditional on TIOCSPGRP, or !defined TIOCSCTTY.
Trying the latter gave the wrong results on Debian GNU/Linux 1.1;
that system does seem to need this code, even though
- both HAVE_SETSID and TIOCSCTTY are defined. */
+ both TIOCSCTTY is defined. */
/* Now close the pty (if we had it open) and reopen it.
This makes the pty the controlling terminal of the subprocess. */
- if (pty_flag)
- {
+ if (pty_flag)
+ {
- /* I wonder if emacs_close (emacs_open (pty_name, ...))
- would work? */
- if (xforkin >= 0)
- emacs_close (xforkin);
- xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
+ /* I wonder if emacs_close (emacs_open (pty_name, ...))
+ would work? */
+ if (xforkin >= 0)
+ emacs_close (xforkin);
+ xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
- if (xforkin < 0)
- {
- emacs_write (1, "Couldn't open the pty terminal ", 31);
- emacs_write (1, pty_name, strlen (pty_name));
- emacs_write (1, "\n", 1);
- _exit (1);
- }
+ if (xforkin < 0)
+ {
+ emacs_write (1, "Couldn't open the pty terminal ", 31);
+ emacs_write (1, pty_name, strlen (pty_name));
+ emacs_write (1, "\n", 1);
+ _exit (1);
+ }
- }
+ }
#endif /* not DONT_REOPEN_PTY */
#ifdef SETUP_SLAVE_PTY
- if (pty_flag)
- {
- SETUP_SLAVE_PTY;
- }
+ if (pty_flag)
+ {
+ SETUP_SLAVE_PTY;
+ }
#endif /* SETUP_SLAVE_PTY */
#ifdef AIX
- /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
- Now reenable it in the child, so it will die when we want it to. */
- if (pty_flag)
- signal (SIGHUP, SIG_DFL);
+ /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
+ Now reenable it in the child, so it will die when we want it to. */
+ if (pty_flag)
+ signal (SIGHUP, SIG_DFL);
#endif
#endif /* HAVE_PTYS */
- signal (SIGINT, SIG_DFL);
- signal (SIGQUIT, SIG_DFL);
- /* GConf causes us to ignore SIGPIPE, make sure it is restored
- in the child. */
- signal (SIGPIPE, SIG_DFL);
+ signal (SIGINT, SIG_DFL);
+ signal (SIGQUIT, SIG_DFL);
+
+ /* Emacs ignores SIGPIPE, but the child should not. */
+ signal (SIGPIPE, SIG_DFL);
/* Stop blocking signals in the child. */
- pthread_sigmask (SIG_SETMASK, &procmask, 0);
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
- if (pty_flag)
- child_setup_tty (xforkout);
+ if (pty_flag)
+ child_setup_tty (xforkout);
#ifdef WINDOWSNT
- pid = child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, encoded_current_dir);
+ pid = child_setup (xforkin, xforkout, xforkout,
+ new_argv, 1, encoded_current_dir);
#else /* not WINDOWSNT */
-#ifdef FD_CLOEXEC
- emacs_close (wait_child_setup[0]);
-#endif
- child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, encoded_current_dir);
+ emacs_close (wait_child_setup[0]);
+ child_setup (xforkin, xforkout, xforkout,
+ new_argv, 1, encoded_current_dir);
#endif /* not WINDOWSNT */
- }
- environ = save_environ;
- }
+ }
+
+ /* Back in the parent process. */
- UNBLOCK_INPUT;
+ XPROCESS (process)->pid = pid;
+ if (0 <= pid)
+ XPROCESS (process)->alive = 1;
+
+ /* Stop blocking signals in the parent. */
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+ unblock_input ();
- /* This runs in the Emacs process. */
if (pid < 0)
{
if (forkin >= 0)
@@ -2100,7 +2012,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
else
{
/* vfork succeeded. */
- XPROCESS (process)->pid = pid;
#ifdef WINDOWSNT
register_child (pid, inchannel);
@@ -2126,18 +2037,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
if (forkin != forkout && forkout >= 0)
emacs_close (forkout);
-#ifdef HAVE_PTYS
- if (pty_flag)
- pset_tty_name (XPROCESS (process), build_string (pty_name));
- else
-#endif
- pset_tty_name (XPROCESS (process), Qnil);
+ pset_tty_name (XPROCESS (process), lisp_pty_name);
-#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+#ifndef WINDOWSNT
/* Wait for child_setup to complete in case that vfork is
actually defined as fork. The descriptor wait_child_setup[1]
of a pipe is closed at the child side either by close-on-exec
- on successful execvp or the _exit call in child_setup. */
+ on successful execve or the _exit call in child_setup. */
{
char dummy;
@@ -2148,20 +2054,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
#endif
}
- /* Restore the signal state whether vfork succeeded or not.
- (We will signal an error, below, if it failed.) */
-#ifdef HAVE_WORKING_VFORK
- /* Restore the parent's signal handlers. */
- sigaction (SIGINT, &sigint_action, 0);
- sigaction (SIGQUIT, &sigquit_action, 0);
- sigaction (SIGPIPE, &sigpipe_action, 0);
-#ifdef AIX
- sigaction (SIGHUP, &sighup_action, 0);
-#endif
-#endif /* HAVE_WORKING_VFORK */
- /* Stop blocking signals in the parent. */
- pthread_sigmask (SIG_SETMASK, &procmask, 0);
-
/* Now generate the error if vfork failed. */
if (pid < 0)
report_file_error ("Doing vfork", Qnil);
@@ -2184,13 +2076,9 @@ create_pty (Lisp_Object process)
#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
/* On most USG systems it does not work to open the pty's tty here,
then close it and reopen it in the child. */
-#ifdef O_NOCTTY
/* Don't let this terminal become our controlling terminal
(in case we don't have one). */
int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
-#else
- int forkout = emacs_open (pty_name, O_RDWR, 0);
-#endif
if (forkout < 0)
report_file_error ("Opening pty", Qnil);
#if defined (DONT_REOPEN_PTY)
@@ -2204,15 +2092,8 @@ create_pty (Lisp_Object process)
}
#endif /* HAVE_PTYS */
-#ifdef O_NONBLOCK
fcntl (inchannel, F_SETFL, O_NONBLOCK);
fcntl (outchannel, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
- fcntl (inchannel, F_SETFL, O_NDELAY);
- fcntl (outchannel, F_SETFL, O_NDELAY);
-#endif
-#endif
/* Record this as an active process, with its channels.
As a result, child_setup will close Emacs's side of the pipes. */
@@ -2735,7 +2616,7 @@ static Lisp_Object
make_serial_process_unwind (Lisp_Object proc)
{
if (!PROCESSP (proc))
- abort ();
+ emacs_abort ();
remove_process (proc);
return Qnil;
}
@@ -3162,13 +3043,9 @@ usage: (make-network-process &rest ARGS) */)
{
/* Don't support network sockets when non-blocking mode is
not available, since a blocked Emacs is not useful. */
-#if !defined (O_NONBLOCK) && !defined (O_NDELAY)
- error ("Network servers not supported");
-#else
is_server = 1;
if (TYPE_RANGED_INTEGERP (int, tem))
backlog = XINT (tem);
-#endif
}
/* Make QCaddress an alias for :local (server) or :remote (client). */
@@ -3428,11 +3305,7 @@ usage: (make-network-process &rest ARGS) */)
#ifdef NON_BLOCKING_CONNECT
if (is_non_blocking_client)
{
-#ifdef O_NONBLOCK
ret = fcntl (s, F_SETFL, O_NONBLOCK);
-#else
- ret = fcntl (s, F_SETFL, O_NDELAY);
-#endif
if (ret < 0)
{
xerrno = errno;
@@ -3569,7 +3442,7 @@ usage: (make-network-process &rest ARGS) */)
if (socktype == SOCK_DGRAM)
{
if (datagram_address[s].sa)
- abort ();
+ emacs_abort ();
datagram_address[s].sa = xmalloc (lres->ai_addrlen);
datagram_address[s].len = lres->ai_addrlen;
if (is_server)
@@ -3608,9 +3481,9 @@ usage: (make-network-process &rest ARGS) */)
#ifdef HAVE_GETADDRINFO
if (res != &ai)
{
- BLOCK_INPUT;
+ block_input ();
freeaddrinfo (res);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
@@ -3645,13 +3518,7 @@ usage: (make-network-process &rest ARGS) */)
chan_process[inch] = proc;
-#ifdef O_NONBLOCK
fcntl (inch, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
- fcntl (inch, F_SETFL, O_NDELAY);
-#endif
-#endif
p = XPROCESS (proc);
@@ -4377,13 +4244,7 @@ server_accept_connection (Lisp_Object server, int channel)
chan_process[s] = proc;
-#ifdef O_NONBLOCK
fcntl (s, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
- fcntl (s, F_SETFL, O_NDELAY);
-#endif
-#endif
p = XPROCESS (proc);
@@ -4482,7 +4343,7 @@ wait_reading_process_output_1 (void)
-1 meaning caller will actually read the input, so don't throw to
the quit handler, or
- DO_DISPLAY != 0 means redisplay should be done to show subprocess
+ DO_DISPLAY means redisplay should be done to show subprocess
output that arrives.
If WAIT_FOR_CELL is a cons cell, wait until its car is non-nil
@@ -4502,7 +4363,7 @@ wait_reading_process_output_1 (void)
int
wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
- int do_display,
+ bool do_display,
Lisp_Object wait_for_cell,
struct Lisp_Process *wait_proc, int just_wait_proc)
{
@@ -4563,10 +4424,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
Otherwise, do pending quit if requested. */
if (read_kbd >= 0)
QUIT;
-#ifdef SYNC_INPUT
- else
+ else if (pending_signals)
process_pending_signals ();
-#endif
/* Exit now if the cell we're waiting for became non-nil. */
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
@@ -4605,7 +4464,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
do
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
struct buffer *old_buffer = current_buffer;
Lisp_Object old_window = selected_window;
@@ -4641,7 +4500,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (EMACS_TIME_LT (timer_delay, timeout))
{
timeout = timer_delay;
- timeout_reduced_for_timers = 1;
+ timeout_reduced_for_timers = 1;
}
}
else
@@ -4722,14 +4581,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
total_nread += nread;
got_some_input = 1;
}
-#ifdef EIO
- else if (nread == -1 && EIO == errno)
+ else if (nread == -1 && (errno == EIO || errno == EAGAIN))
break;
-#endif
-#ifdef EAGAIN
- else if (nread == -1 && EAGAIN == errno)
- break;
-#endif
#ifdef EWOULDBLOCK
else if (nread == -1 && EWOULDBLOCK == errno)
break;
@@ -4918,10 +4771,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
yielding EBADF here or at select() call above.
So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
in m/ibmrt-aix.h), and here we just ignore the select error.
- Cleanup occurs c/o status_notify after SIGCLD. */
+ Cleanup occurs c/o status_notify after SIGCHLD. */
no_avail = 1; /* Cannot depend on values returned */
#else
- abort ();
+ emacs_abort ();
#endif
}
else
@@ -4934,28 +4787,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
check_write = 0;
}
-#if 0 /* When polling is used, interrupt_input is 0,
- so get_input_pending should read the input.
- So this should not be needed. */
- /* If we are using polling for input,
- and we see input available, make it get read now.
- Otherwise it might not actually get read for a second.
- And on hpux, since we turn off polling in wait_reading_process_output,
- it might never get read at all if we don't spend much time
- outside of wait_reading_process_output. */
- if (read_kbd && interrupt_input
- && keyboard_bit_set (&Available)
- && input_polling_used ())
- kill (getpid (), SIGALRM);
-#endif
-
/* Check for keyboard input */
/* If there is any, return immediately
to give it higher priority than subprocesses */
if (read_kbd != 0)
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
struct buffer *old_buffer = current_buffer;
Lisp_Object old_window = selected_window;
int leave = 0;
@@ -5004,7 +4842,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
break;
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
/* If we think we have keyboard input waiting, but didn't get SIGIO,
go read it. This can happen with X on BSD after logging out.
In that case, there really is no input and no SIGIO,
@@ -5012,7 +4850,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (read_kbd && interrupt_input
&& keyboard_bit_set (&Available) && ! noninteractive)
- kill (getpid (), SIGIO);
+ handle_input_available_signal (SIGIO);
#endif
if (! wait_proc)
@@ -5085,23 +4923,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
else if (nread == -1 && errno == EWOULDBLOCK)
;
#endif
- /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
- and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */
-#ifdef O_NONBLOCK
- else if (nread == -1 && errno == EAGAIN)
- ;
-#else
-#ifdef O_NDELAY
else if (nread == -1 && errno == EAGAIN)
;
+#ifdef WINDOWSNT
+ /* FIXME: Is this special case still needed? */
/* Note that we cannot distinguish between no input
available now and a closed pipe.
With luck, a closed pipe will be accompanied by
subprocess termination and SIGCHLD. */
else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc))
;
-#endif /* O_NDELAY */
-#endif /* O_NONBLOCK */
+#endif
#ifdef HAVE_PTYS
/* On some OSs with ptys, when the process on one end of
a pty exits, the other end gets an error reading with
@@ -5124,22 +4956,20 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (p->pid == -2)
{
- /* If the EIO occurs on a pty, sigchld_handler's
- waitpid() will not find the process object to
+ /* If the EIO occurs on a pty, the SIGCHLD handler's
+ waitpid call will not find the process object to
delete. Do it here. */
p->tick = ++process_tick;
pset_status (p, Qfailed);
}
else
- kill (getpid (), SIGCHLD);
+ handle_child_signal (SIGCHLD);
}
#endif /* HAVE_PTYS */
/* If we can detect process termination, don't consider the
process gone just because its pipe is closed. */
-#ifdef SIGCHLD
else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc))
;
-#endif
else
{
/* Preserve status of processes already terminated. */
@@ -5460,7 +5290,7 @@ read_process_output (Lisp_Object proc, register int channel)
}
/* If no filter, write into buffer if it isn't dead. */
- else if (!NILP (p->buffer) && !NILP (BVAR (XBUFFER (p->buffer), name)))
+ else if (!NILP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
{
Lisp_Object old_read_only;
ptrdiff_t old_begv, old_zv;
@@ -5582,21 +5412,6 @@ read_process_output (Lisp_Object proc, register int channel)
/* Sending data to subprocess */
-static jmp_buf send_process_frame;
-static Lisp_Object process_sent_to;
-
-#ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
-static _Noreturn void send_process_trap (int);
-#endif
-
-static void
-send_process_trap (int ignore)
-{
- SIGNAL_THREAD_CHECK (SIGPIPE);
- sigunblock (sigmask (SIGPIPE));
- _longjmp (send_process_frame, 1);
-}
-
/* In send_process, when a write fails temporarily,
wait_reading_process_output is called. It may execute user code,
e.g. timers, that attempts to write new data to the same process.
@@ -5680,14 +5495,12 @@ write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
This function can evaluate Lisp code and can garbage collect. */
static void
-send_process (volatile Lisp_Object proc, const char *volatile buf,
- volatile ptrdiff_t len, volatile Lisp_Object object)
+send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
+ Lisp_Object object)
{
- /* Use volatile to protect variables from being clobbered by longjmp. */
struct Lisp_Process *p = XPROCESS (proc);
ssize_t rv;
struct coding_system *coding;
- void (*volatile old_sigpipe) (int);
if (p->raw_status_new)
update_status (p);
@@ -5781,156 +5594,123 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
buf = SSDATA (object);
}
- if (pty_max_bytes == 0)
- {
-#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
- pty_max_bytes = fpathconf (p->outfd, _PC_MAX_CANON);
- if (pty_max_bytes < 0)
- pty_max_bytes = 250;
-#else
- pty_max_bytes = 250;
-#endif
- /* Deduct one, to leave space for the eof. */
- pty_max_bytes--;
- }
+ /* If there is already data in the write_queue, put the new data
+ in the back of queue. Otherwise, ignore it. */
+ if (!NILP (p->write_queue))
+ write_queue_push (p, object, buf, len, 0);
- /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2,
- CFLAGS="-g -O": The value of the parameter `proc' is clobbered
- when returning with longjmp despite being declared volatile. */
- if (!_setjmp (send_process_frame))
+ do /* while !NILP (p->write_queue) */
{
- p = XPROCESS (proc); /* Repair any setjmp clobbering. */
- process_sent_to = proc;
-
- /* If there is already data in the write_queue, put the new data
- in the back of queue. Otherwise, ignore it. */
- if (!NILP (p->write_queue))
- write_queue_push (p, object, buf, len, 0);
+ ptrdiff_t cur_len = -1;
+ const char *cur_buf;
+ Lisp_Object cur_object;
- do /* while !NILP (p->write_queue) */
+ /* If write_queue is empty, ignore it. */
+ if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
{
- ptrdiff_t cur_len = -1;
- const char *cur_buf;
- Lisp_Object cur_object;
+ cur_len = len;
+ cur_buf = buf;
+ cur_object = object;
+ }
- /* If write_queue is empty, ignore it. */
- if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
+ while (cur_len > 0)
+ {
+ /* Send this batch, using one or more write calls. */
+ ptrdiff_t written = 0;
+ int outfd = p->outfd;
+#ifdef DATAGRAM_SOCKETS
+ if (DATAGRAM_CHAN_P (outfd))
{
- cur_len = len;
- cur_buf = buf;
- cur_object = object;
+ rv = sendto (outfd, cur_buf, cur_len,
+ 0, datagram_address[outfd].sa,
+ datagram_address[outfd].len);
+ if (0 <= rv)
+ written = rv;
+ else if (errno == EMSGSIZE)
+ report_file_error ("sending datagram", Fcons (proc, Qnil));
}
-
- while (cur_len > 0)
- {
- /* Send this batch, using one or more write calls. */
- ptrdiff_t written = 0;
- int outfd = p->outfd;
- old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
-#ifdef DATAGRAM_SOCKETS
- if (DATAGRAM_CHAN_P (outfd))
- {
- rv = sendto (outfd, cur_buf, cur_len,
- 0, datagram_address[outfd].sa,
- datagram_address[outfd].len);
- if (0 <= rv)
- written = rv;
- else if (errno == EMSGSIZE)
- {
- signal (SIGPIPE, old_sigpipe);
- report_file_error ("sending datagram",
- Fcons (proc, Qnil));
- }
- }
- else
+ else
#endif
- {
+ {
#ifdef HAVE_GNUTLS
- if (p->gnutls_p)
- written = emacs_gnutls_write (p, cur_buf, cur_len);
- else
+ if (p->gnutls_p)
+ written = emacs_gnutls_write (p, cur_buf, cur_len);
+ else
#endif
- written = emacs_write (outfd, cur_buf, cur_len);
- rv = (written ? 0 : -1);
+ written = emacs_write (outfd, cur_buf, cur_len);
+ rv = (written ? 0 : -1);
#ifdef ADAPTIVE_READ_BUFFERING
- if (p->read_output_delay > 0
- && p->adaptive_read_buffering == 1)
- {
- p->read_output_delay = 0;
- process_output_delay_count--;
- p->read_output_skip = 0;
- }
-#endif
+ if (p->read_output_delay > 0
+ && p->adaptive_read_buffering == 1)
+ {
+ p->read_output_delay = 0;
+ process_output_delay_count--;
+ p->read_output_skip = 0;
}
- signal (SIGPIPE, old_sigpipe);
+#endif
+ }
- if (rv < 0)
- {
- if (0
+ if (rv < 0)
+ {
+ if (errno == EAGAIN
#ifdef EWOULDBLOCK
- || errno == EWOULDBLOCK
+ || errno == EWOULDBLOCK
#endif
-#ifdef EAGAIN
- || errno == EAGAIN
-#endif
- )
- /* Buffer is full. Wait, accepting input;
- that may allow the program
- to finish doing output and read more. */
- {
+ )
+ /* Buffer is full. Wait, accepting input;
+ that may allow the program
+ to finish doing output and read more. */
+ {
#ifdef BROKEN_PTY_READ_AFTER_EAGAIN
- /* A gross hack to work around a bug in FreeBSD.
- In the following sequence, read(2) returns
- bogus data:
-
- write(2) 1022 bytes
- write(2) 954 bytes, get EAGAIN
- read(2) 1024 bytes in process_read_output
- read(2) 11 bytes in process_read_output
-
- That is, read(2) returns more bytes than have
- ever been written successfully. The 1033 bytes
- read are the 1022 bytes written successfully
- after processing (for example with CRs added if
- the terminal is set up that way which it is
- here). The same bytes will be seen again in a
- later read(2), without the CRs. */
-
- if (errno == EAGAIN)
- {
- int flags = FWRITE;
- ioctl (p->outfd, TIOCFLUSH, &flags);
- }
+ /* A gross hack to work around a bug in FreeBSD.
+ In the following sequence, read(2) returns
+ bogus data:
+
+ write(2) 1022 bytes
+ write(2) 954 bytes, get EAGAIN
+ read(2) 1024 bytes in process_read_output
+ read(2) 11 bytes in process_read_output
+
+ That is, read(2) returns more bytes than have
+ ever been written successfully. The 1033 bytes
+ read are the 1022 bytes written successfully
+ after processing (for example with CRs added if
+ the terminal is set up that way which it is
+ here). The same bytes will be seen again in a
+ later read(2), without the CRs. */
+
+ if (errno == EAGAIN)
+ {
+ int flags = FWRITE;
+ ioctl (p->outfd, TIOCFLUSH, &flags);
+ }
#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
- /* Put what we should have written in wait_queue. */
- write_queue_push (p, cur_object, cur_buf, cur_len, 1);
- wait_reading_process_output (0, 20 * 1000 * 1000,
- 0, 0, Qnil, NULL, 0);
- /* Reread queue, to see what is left. */
- break;
- }
- else
- /* This is a real error. */
- report_file_error ("writing to process", Fcons (proc, Qnil));
+ /* Put what we should have written in wait_queue. */
+ write_queue_push (p, cur_object, cur_buf, cur_len, 1);
+ wait_reading_process_output (0, 20 * 1000 * 1000,
+ 0, 0, Qnil, NULL, 0);
+ /* Reread queue, to see what is left. */
+ break;
}
- cur_buf += written;
- cur_len -= written;
+ else if (errno == EPIPE)
+ {
+ p->raw_status_new = 0;
+ pset_status (p, list2 (Qexit, make_number (256)));
+ p->tick = ++process_tick;
+ deactivate_process (proc);
+ error ("process %s no longer connected to pipe; closed it",
+ SDATA (p->name));
+ }
+ else
+ /* This is a real error. */
+ report_file_error ("writing to process", Fcons (proc, Qnil));
}
+ cur_buf += written;
+ cur_len -= written;
}
- while (!NILP (p->write_queue));
- }
- else
- {
- signal (SIGPIPE, old_sigpipe);
- proc = process_sent_to;
- p = XPROCESS (proc);
- p->raw_status_new = 0;
- pset_status (p, Fcons (Qexit, Fcons (make_number (256), Qnil)));
- p->tick = ++process_tick;
- deactivate_process (proc);
- error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
}
+ while (!NILP (p->write_queue));
}
DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
@@ -6047,7 +5827,7 @@ return t unconditionally. */)
If we can, we try to signal PROCESS by sending control characters
down the pty. This allows us to signal inferiors who have changed
- their uid, for which killpg would return an EPERM error. */
+ their uid, for which kill would return an EPERM error. */
static void
process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
@@ -6185,7 +5965,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
if (!NILP (current_group))
{
if (ioctl (p->infd, TIOCSIGSEND, signo) == -1)
- EMACS_KILLPG (gid, signo);
+ kill (-gid, signo);
}
else
{
@@ -6193,7 +5973,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
kill (gid, signo);
}
#else /* ! defined (TIOCSIGSEND) */
- EMACS_KILLPG (gid, signo);
+ kill (-gid, signo);
#endif /* ! defined (TIOCSIGSEND) */
}
@@ -6294,6 +6074,27 @@ traffic. */)
return process;
}
+/* Return the integer value of the signal whose abbreviation is ABBR,
+ or a negative number if there is no such signal. */
+static int
+abbr_to_signal (char const *name)
+{
+ int i, signo;
+ char sigbuf[20]; /* Large enough for all valid signal abbreviations. */
+
+ if (!strncmp (name, "SIG", 3) || !strncmp (name, "sig", 3))
+ name += 3;
+
+ for (i = 0; i < sizeof sigbuf; i++)
+ {
+ sigbuf[i] = c_toupper (name[i]);
+ if (! sigbuf[i])
+ return str2sig (sigbuf, &signo) == 0 ? signo : -1;
+ }
+
+ return -1;
+}
+
DEFUN ("signal-process", Fsignal_process, Ssignal_process,
2, 2, "sProcess (name or number): \nnSignal code: ",
doc: /* Send PROCESS the signal with code SIGCODE.
@@ -6304,6 +6105,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */)
(Lisp_Object process, Lisp_Object sigcode)
{
pid_t pid;
+ int signo;
if (STRINGP (process))
{
@@ -6333,12 +6135,11 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */)
error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
}
-#define parse_signal(NAME, VALUE) \
- else if (!xstrcasecmp (name, NAME)) \
- XSETINT (sigcode, VALUE)
-
if (INTEGERP (sigcode))
- CHECK_TYPE_RANGED_INTEGER (int, sigcode);
+ {
+ CHECK_TYPE_RANGED_INTEGER (int, sigcode);
+ signo = XINT (sigcode);
+ }
else
{
char *name;
@@ -6346,108 +6147,12 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */)
CHECK_SYMBOL (sigcode);
name = SSDATA (SYMBOL_NAME (sigcode));
- if (!strncmp (name, "SIG", 3) || !strncmp (name, "sig", 3))
- name += 3;
-
- if (0)
- ;
-#ifdef SIGUSR1
- parse_signal ("usr1", SIGUSR1);
-#endif
-#ifdef SIGUSR2
- parse_signal ("usr2", SIGUSR2);
-#endif
-#ifdef SIGTERM
- parse_signal ("term", SIGTERM);
-#endif
-#ifdef SIGHUP
- parse_signal ("hup", SIGHUP);
-#endif
-#ifdef SIGINT
- parse_signal ("int", SIGINT);
-#endif
-#ifdef SIGQUIT
- parse_signal ("quit", SIGQUIT);
-#endif
-#ifdef SIGILL
- parse_signal ("ill", SIGILL);
-#endif
-#ifdef SIGABRT
- parse_signal ("abrt", SIGABRT);
-#endif
-#ifdef SIGEMT
- parse_signal ("emt", SIGEMT);
-#endif
-#ifdef SIGKILL
- parse_signal ("kill", SIGKILL);
-#endif
-#ifdef SIGFPE
- parse_signal ("fpe", SIGFPE);
-#endif
-#ifdef SIGBUS
- parse_signal ("bus", SIGBUS);
-#endif
-#ifdef SIGSEGV
- parse_signal ("segv", SIGSEGV);
-#endif
-#ifdef SIGSYS
- parse_signal ("sys", SIGSYS);
-#endif
-#ifdef SIGPIPE
- parse_signal ("pipe", SIGPIPE);
-#endif
-#ifdef SIGALRM
- parse_signal ("alrm", SIGALRM);
-#endif
-#ifdef SIGURG
- parse_signal ("urg", SIGURG);
-#endif
-#ifdef SIGSTOP
- parse_signal ("stop", SIGSTOP);
-#endif
-#ifdef SIGTSTP
- parse_signal ("tstp", SIGTSTP);
-#endif
-#ifdef SIGCONT
- parse_signal ("cont", SIGCONT);
-#endif
-#ifdef SIGCHLD
- parse_signal ("chld", SIGCHLD);
-#endif
-#ifdef SIGTTIN
- parse_signal ("ttin", SIGTTIN);
-#endif
-#ifdef SIGTTOU
- parse_signal ("ttou", SIGTTOU);
-#endif
-#ifdef SIGIO
- parse_signal ("io", SIGIO);
-#endif
-#ifdef SIGXCPU
- parse_signal ("xcpu", SIGXCPU);
-#endif
-#ifdef SIGXFSZ
- parse_signal ("xfsz", SIGXFSZ);
-#endif
-#ifdef SIGVTALRM
- parse_signal ("vtalrm", SIGVTALRM);
-#endif
-#ifdef SIGPROF
- parse_signal ("prof", SIGPROF);
-#endif
-#ifdef SIGWINCH
- parse_signal ("winch", SIGWINCH);
-#endif
-#ifdef SIGINFO
- parse_signal ("info", SIGINFO);
-#endif
- else
+ signo = abbr_to_signal (name);
+ if (signo < 0)
error ("Undefined signal name %s", name);
}
-#undef parse_signal
-
- return make_number (kill (pid, XINT (sigcode)));
+ return make_number (kill (pid, signo));
}
DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
@@ -6513,15 +6218,14 @@ process has been transmitted to the serial port. */)
#endif /* not HAVE_SHUTDOWN */
new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
if (new_outfd < 0)
- abort ();
+ emacs_abort ();
old_outfd = XPROCESS (proc)->outfd;
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
= xmalloc (sizeof (struct coding_system));
- memcpy (proc_encode_coding_system[new_outfd],
- proc_encode_coding_system[old_outfd],
- sizeof (struct coding_system));
+ *proc_encode_coding_system[new_outfd]
+ = *proc_encode_coding_system[old_outfd];
memset (proc_encode_coding_system[old_outfd], 0,
sizeof (struct coding_system));
@@ -6530,9 +6234,35 @@ process has been transmitted to the serial port. */)
return process;
}
-/* On receipt of a signal that a child status has changed, loop asking
- about children with changed statuses until the system says there
- are no more.
+/* The main Emacs thread records child processes in three places:
+
+ - Vprocess_alist, for asynchronous subprocesses, which are child
+ processes visible to Lisp.
+
+ - deleted_pid_list, for child processes invisible to Lisp,
+ typically because of delete-process. These are recorded so that
+ the processes can be reaped when they exit, so that the operating
+ system's process table is not cluttered by zombies.
+
+ - the local variable PID in Fcall_process, call_process_cleanup and
+ call_process_kill, for synchronous subprocesses.
+ record_unwind_protect is used to make sure this process is not
+ forgotten: if the user interrupts call-process and the child
+ process refuses to exit immediately even with two C-g's,
+ call_process_kill adds PID's contents to deleted_pid_list before
+ returning.
+
+ The main Emacs thread invokes waitpid only on child processes that
+ it creates and that have not been reaped. This avoid races on
+ platforms such as GTK, where other threads create their own
+ subprocesses which the main thread should not reap. For example,
+ if the main thread attempted to reap an already-reaped child, it
+ might inadvertently reap a GTK-created process that happened to
+ have the same process ID. */
+
+/* Handle a SIGCHLD signal by looking for known child processes of
+ Emacs whose status have changed. For each one found, record its
+ new status.
All we do is change the status; we do not run sentinels or print
notifications. That is saved for the next time keyboard input is
@@ -6555,142 +6285,72 @@ process has been transmitted to the serial port. */)
** Malloc WARNING: This should never call malloc either directly or
indirectly; if it does, that is a bug */
-#ifdef SIGCHLD
static void
-sigchld_handler (int signo)
+handle_child_signal (int sig)
{
- int old_errno = errno;
- Lisp_Object proc;
- struct Lisp_Process *p;
+ Lisp_Object tail;
- SIGNAL_THREAD_CHECK (signo);
+ /* Find the process that signaled us, and record its status. */
- while (1)
+ /* The process can have been deleted by Fdelete_process, or have
+ been started asynchronously by Fcall_process. */
+ for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
{
- pid_t pid;
- int w;
- Lisp_Object tail;
-
-#ifdef WNOHANG
-#ifndef WUNTRACED
-#define WUNTRACED 0
-#endif /* no WUNTRACED */
- /* Keep trying to get a status until we get a definitive result. */
- do
- {
- errno = 0;
- pid = waitpid (-1, &w, WNOHANG | WUNTRACED);
- }
- while (pid < 0 && errno == EINTR);
-
- if (pid <= 0)
+ bool all_pids_are_fixnums
+ = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t)
+ && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM);
+ Lisp_Object xpid = XCAR (tail);
+ if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid))
{
- /* PID == 0 means no processes found, PID == -1 means a real
- failure. We have done all our job, so return. */
-
- errno = old_errno;
- return;
- }
-#else
- pid = wait (&w);
-#endif /* no WNOHANG */
-
- /* Find the process that signaled us, and record its status. */
-
- /* The process can have been deleted by Fdelete_process. */
- for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object xpid = XCAR (tail);
- if ((INTEGERP (xpid) && pid == XINT (xpid))
- || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
- {
- XSETCAR (tail, Qnil);
- goto sigchld_end_of_loop;
- }
- }
-
- /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */
- p = 0;
- for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
- {
- proc = XCDR (XCAR (tail));
- p = XPROCESS (proc);
- if (EQ (p->type, Qreal) && p->pid == pid)
- break;
- p = 0;
+ pid_t deleted_pid;
+ if (INTEGERP (xpid))
+ deleted_pid = XINT (xpid);
+ else
+ deleted_pid = XFLOAT_DATA (xpid);
+ if (child_status_changed (deleted_pid, 0, 0))
+ XSETCAR (tail, Qnil);
}
+ }
- /* Look for an asynchronous process whose pid hasn't been filled
- in yet. */
- if (p == 0)
- for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
- {
- proc = XCDR (XCAR (tail));
- p = XPROCESS (proc);
- if (p->pid == -1)
- break;
- p = 0;
- }
+ /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */
+ for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object proc = XCDR (XCAR (tail));
+ struct Lisp_Process *p = XPROCESS (proc);
+ int status;
- /* Change the status of the process that was found. */
- if (p != 0)
+ if (p->alive && child_status_changed (p->pid, &status, WUNTRACED))
{
- int clear_desc_flag = 0;
-
+ /* Change the status of the process that was found. */
p->tick = ++process_tick;
- p->raw_status = w;
+ p->raw_status = status;
p->raw_status_new = 1;
/* If process has terminated, stop waiting for its output. */
- if ((WIFSIGNALED (w) || WIFEXITED (w))
- && p->infd >= 0)
- clear_desc_flag = 1;
-
- /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */
- if (clear_desc_flag)
- delete_read_fd (p->infd);
-
- /* Tell wait_reading_process_output that it needs to wake up and
- look around. */
- if (input_available_clear_time)
- *input_available_clear_time = make_emacs_time (0, 0);
- }
-
- /* There was no asynchronous process found for that pid: we have
- a synchronous process. */
- else
- {
- synch_process_alive = 0;
-
- /* Report the status of the synchronous process. */
- if (WIFEXITED (w))
- synch_process_retcode = WEXITSTATUS (w);
- else if (WIFSIGNALED (w))
- synch_process_termsig = WTERMSIG (w);
-
- /* Tell wait_reading_process_output that it needs to wake up and
- look around. */
- if (input_available_clear_time)
- *input_available_clear_time = make_emacs_time (0, 0);
+ if (WIFSIGNALED (status) || WIFEXITED (status))
+ {
+ int clear_desc_flag = 0;
+ p->alive = 0;
+ if (p->infd >= 0)
+ clear_desc_flag = 1;
+
+ /* clear_desc_flag avoids a compiler bug in Microsoft C. */
+ if (clear_desc_flag)
+ delete_read_fd (p->infd);
+ {
+ FD_CLR (p->infd, &input_wait_mask);
+ FD_CLR (p->infd, &non_keyboard_wait_mask);
+ }
+ }
}
-
- sigchld_end_of_loop:
- ;
-
- /* On some systems, we must return right away.
- If any more processes want to signal us, we will
- get another signal.
- Otherwise (on systems that have WNOHANG), loop around
- to use up all the processes that have something to tell us. */
-#if (defined WINDOWSNT \
- || (defined USG && !defined GNU_LINUX \
- && !(defined HPUX && defined WNOHANG)))
- errno = old_errno;
- return;
-#endif /* USG, but not HPUX with WNOHANG */
}
}
-#endif /* SIGCHLD */
+
+static void
+deliver_child_signal (int sig)
+{
+ deliver_process_signal (sig, handle_child_signal);
+}
static Lisp_Object
@@ -6879,7 +6539,7 @@ status_notify (struct Lisp_Process *deleting_process)
/* Avoid error if buffer is deleted
(probably that's why the process is dead, too) */
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
continue;
Fset_buffer (buffer);
@@ -7011,7 +6671,7 @@ delete_gpm_wait_descriptor (int desc)
# endif
-# ifdef SIGIO
+# ifdef USABLE_SIGIO
/* Return nonzero if *MASK has a bit set
that corresponds to one of the keyboard input descriptors. */
@@ -7061,14 +6721,14 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
see full version for other parameters. We know that wait_proc will
always be NULL, since `subprocesses' isn't defined.
- DO_DISPLAY != 0 means redisplay should be done to show subprocess
+ DO_DISPLAY means redisplay should be done to show subprocess
output that arrives.
Return true if we received input from any process. */
int
wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
- int do_display,
+ bool do_display,
Lisp_Object wait_for_cell,
struct Lisp_Process *wait_proc, int just_wait_proc)
{
@@ -7144,7 +6804,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
do
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
timer_delay = timer_check ();
if (timers_run != old_timers_run && do_display)
/* We must retry, since a timer may have requeued itself
@@ -7545,12 +7205,14 @@ init_process_emacs (void)
inhibit_sentinels = 0;
-#ifdef SIGCHLD
#ifndef CANNOT_DUMP
if (! noninteractive || initialized)
#endif
- signal (SIGCHLD, sigchld_handler);
-#endif
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_child_signal);
+ sigaction (SIGCHLD, &action, 0);
+ }
max_process_desc = 0;
memset (fd_callback_info, 0, sizeof (fd_callback_info));
@@ -7572,9 +7234,7 @@ init_process_emacs (void)
#endif
Vprocess_alist = Qnil;
-#ifdef SIGCHLD
deleted_pid_list = Qnil;
-#endif
for (i = 0; i < MAXDESC; i++)
{
chan_process[i] = Qnil;
@@ -7612,9 +7272,7 @@ init_process_emacs (void)
#ifdef HAVE_GETSOCKNAME
ADD_SUBFEATURE (QCservice, Qt);
#endif
-#if defined (O_NONBLOCK) || defined (O_NDELAY)
ADD_SUBFEATURE (QCserver, Qt);
-#endif
for (sopt = socket_options; sopt->name; sopt++)
subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);
@@ -7703,9 +7361,7 @@ syms_of_process (void)
DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event");
staticpro (&Vprocess_alist);
-#ifdef SIGCHLD
staticpro (&deleted_pid_list);
-#endif
#endif /* subprocesses */
diff --git a/src/process.h b/src/process.h
index e89ba478187..01f7fd50ffa 100644
--- a/src/process.h
+++ b/src/process.h
@@ -145,6 +145,9 @@ struct Lisp_Process
/* Flag to set coding-system of the process buffer from the
coding_system used to decode process output. */
unsigned int inherit_coding_system_flag : 1;
+ /* Whether the process is alive, i.e., can be waited for. Running
+ processes can be waited for, but exited and fake processes cannot. */
+ unsigned int alive : 1;
/* Record the process status in the raw form in which it comes from `wait'.
This is to avoid consing in a signal handler. The `raw_status_new'
flag indicates that `raw_status' contains a new status that still
@@ -185,23 +188,6 @@ pset_gnutls_cred_type (struct Lisp_Process *p, Lisp_Object val)
}
#endif
-/* True if we are about to fork off a synchronous process or if we
- are waiting for it. */
-extern bool synch_process_alive;
-
-/* Communicate exit status of sync process to from sigchld_handler
- to Fcall_process. */
-
-/* Nonzero => this is a string explaining death of synchronous subprocess. */
-extern const char *synch_process_death;
-
-/* Nonzero => this is the signal number that terminated the subprocess. */
-extern int synch_process_termsig;
-
-/* If synch_process_death is zero,
- this is exit code of synchronous subprocess. */
-extern int synch_process_retcode;
-
/* Nonzero means don't run process sentinels. This is used
when exiting. */
extern int inhibit_sentinels;
@@ -215,6 +201,12 @@ extern Lisp_Object QCspeed;
extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
+/* Defined in callproc.c. */
+
+extern void record_kill_process (struct Lisp_Process *);
+
+/* Defined in process.c. */
+
extern Lisp_Object list_system_processes (void);
extern Lisp_Object system_process_attributes (Lisp_Object);
diff --git a/src/profiler.c b/src/profiler.c
new file mode 100644
index 00000000000..3d8f7243d2f
--- /dev/null
+++ b/src/profiler.c
@@ -0,0 +1,607 @@
+/* Profiler implementation.
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+
+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 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/>. */
+
+#include <config.h>
+#include "lisp.h"
+#include "syssignal.h"
+#include "systime.h"
+
+/* Return A + B, but return the maximum fixnum if the result would overflow.
+ Assume A and B are nonnegative and in fixnum range. */
+
+static EMACS_INT
+saturated_add (EMACS_INT a, EMACS_INT b)
+{
+ return min (a + b, MOST_POSITIVE_FIXNUM);
+}
+
+/* Logs. */
+
+typedef struct Lisp_Hash_Table log_t;
+
+static Lisp_Object Qprofiler_backtrace_equal;
+static struct hash_table_test hashtest_profiler;
+
+static Lisp_Object
+make_log (int heap_size, int max_stack_depth)
+{
+ /* We use a standard Elisp hash-table object, but we use it in
+ a special way. This is OK as long as the object is not exposed
+ to Elisp, i.e. until it is returned by *-profiler-log, after which
+ it can't be used any more. */
+ Lisp_Object log = make_hash_table (hashtest_profiler,
+ make_number (heap_size),
+ make_float (DEFAULT_REHASH_SIZE),
+ make_float (DEFAULT_REHASH_THRESHOLD),
+ Qnil);
+ struct Lisp_Hash_Table *h = XHASH_TABLE (log);
+
+ /* What is special about our hash-tables is that the keys are pre-filled
+ with the vectors we'll put in them. */
+ int i = ASIZE (h->key_and_value) / 2;
+ while (0 < i)
+ set_hash_key_slot (h, --i,
+ Fmake_vector (make_number (max_stack_depth), Qnil));
+ return log;
+}
+
+/* Evict the least used half of the hash_table.
+
+ When the table is full, we have to evict someone.
+ The easiest and most efficient is to evict the value we're about to add
+ (i.e. once the table is full, stop sampling).
+
+ We could also pick the element with the lowest count and evict it,
+ but finding it is O(N) and for that amount of work we get very
+ little in return: for the next sample, this latest sample will have
+ count==1 and will hence be a prime candidate for eviction :-(
+
+ So instead, we take O(N) time to eliminate more or less half of the
+ entries (the half with the lowest counts). So we get an amortized
+ cost of O(1) and we get O(N) time for a new entry to grow larger
+ than the other least counts before a new round of eviction. */
+
+static EMACS_INT approximate_median (log_t *log,
+ ptrdiff_t start, ptrdiff_t size)
+{
+ eassert (size > 0);
+ if (size < 2)
+ return XINT (HASH_VALUE (log, start));
+ if (size < 3)
+ /* Not an actual median, but better for our application than
+ choosing either of the two numbers. */
+ return ((XINT (HASH_VALUE (log, start))
+ + XINT (HASH_VALUE (log, start + 1)))
+ / 2);
+ else
+ {
+ ptrdiff_t newsize = size / 3;
+ ptrdiff_t start2 = start + newsize;
+ EMACS_INT i1 = approximate_median (log, start, newsize);
+ EMACS_INT i2 = approximate_median (log, start2, newsize);
+ EMACS_INT i3 = approximate_median (log, start2 + newsize,
+ size - 2 * newsize);
+ return (i1 < i2
+ ? (i2 < i3 ? i2 : (i1 < i3 ? i3 : i1))
+ : (i1 < i3 ? i1 : (i2 < i3 ? i3 : i2)));
+ }
+}
+
+static void evict_lower_half (log_t *log)
+{
+ ptrdiff_t size = ASIZE (log->key_and_value) / 2;
+ EMACS_INT median = approximate_median (log, 0, size);
+ ptrdiff_t i;
+
+ for (i = 0; i < size; i++)
+ /* Evict not only values smaller but also values equal to the median,
+ so as to make sure we evict something no matter what. */
+ if (XINT (HASH_VALUE (log, i)) <= median)
+ {
+ Lisp_Object key = HASH_KEY (log, i);
+ { /* FIXME: we could make this more efficient. */
+ Lisp_Object tmp;
+ XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */
+ Fremhash (key, tmp);
+ }
+ eassert (EQ (log->next_free, make_number (i)));
+ {
+ int j;
+ eassert (VECTORP (key));
+ for (j = 0; j < ASIZE (key); j++)
+ ASET (key, j, Qnil);
+ }
+ set_hash_key_slot (log, i, key);
+ }
+}
+
+/* Record the current backtrace in LOG. COUNT is the weight of this
+ current backtrace: interrupt counts for CPU, and the allocation
+ size for memory. */
+
+static void
+record_backtrace (log_t *log, EMACS_INT count)
+{
+ struct backtrace *backlist = backtrace_list;
+ Lisp_Object backtrace;
+ ptrdiff_t index, i = 0;
+ ptrdiff_t asize;
+
+ if (!INTEGERP (log->next_free))
+ /* FIXME: transfer the evicted counts to a special entry rather
+ than dropping them on the floor. */
+ evict_lower_half (log);
+ index = XINT (log->next_free);
+
+ /* Get a "working memory" vector. */
+ backtrace = HASH_KEY (log, index);
+ asize = ASIZE (backtrace);
+
+ /* Copy the backtrace contents into working memory. */
+ for (; i < asize && backlist; i++, backlist = backlist->next)
+ /* FIXME: For closures we should ignore the environment. */
+ ASET (backtrace, i, backlist->function);
+
+ /* Make sure that unused space of working memory is filled with nil. */
+ for (; i < asize; i++)
+ ASET (backtrace, i, Qnil);
+
+ { /* We basically do a `gethash+puthash' here, except that we have to be
+ careful to avoid memory allocation since we're in a signal
+ handler, and we optimize the code to try and avoid computing the
+ hash+lookup twice. See fns.c:Fputhash for reference. */
+ EMACS_UINT hash;
+ ptrdiff_t j = hash_lookup (log, backtrace, &hash);
+ if (j >= 0)
+ {
+ EMACS_INT old_val = XINT (HASH_VALUE (log, j));
+ EMACS_INT new_val = saturated_add (old_val, count);
+ set_hash_value_slot (log, j, make_number (new_val));
+ }
+ else
+ { /* BEWARE! hash_put in general can allocate memory.
+ But currently it only does that if log->next_free is nil. */
+ int j;
+ eassert (!NILP (log->next_free));
+ j = hash_put (log, backtrace, make_number (count), hash);
+ /* Let's make sure we've put `backtrace' right where it
+ already was to start with. */
+ eassert (index == j);
+
+ /* FIXME: If the hash-table is almost full, we should set
+ some global flag so that some Elisp code can offload its
+ data elsewhere, so as to avoid the eviction code.
+ There are 2 ways to do that, AFAICT:
+ - Set a flag checked in QUIT, such that QUIT can then call
+ Fprofiler_cpu_log and stash the full log for later use.
+ - Set a flag check in post-gc-hook, so that Elisp code can call
+ profiler-cpu-log. That gives us more flexibility since that
+ Elisp code can then do all kinds of fun stuff like write
+ the log to disk. Or turn it right away into a call tree.
+ Of course, using Elisp is generally preferable, but it may
+ take longer until we get a chance to run the Elisp code, so
+ there's more risk that the table will get full before we
+ get there. */
+ }
+ }
+}
+
+/* Sampling profiler. */
+
+#ifdef PROFILER_CPU_SUPPORT
+
+/* The profiler timer and whether it was properly initialized, if
+ POSIX timers are available. */
+#ifdef HAVE_ITIMERSPEC
+static timer_t profiler_timer;
+static bool profiler_timer_ok;
+#endif
+
+/* Status of sampling profiler. */
+static enum profiler_cpu_running
+ { NOT_RUNNING, TIMER_SETTIME_RUNNING, SETITIMER_RUNNING }
+ profiler_cpu_running;
+
+/* Hash-table log of CPU profiler. */
+static Lisp_Object cpu_log;
+
+/* Separate counter for the time spent in the GC. */
+static EMACS_INT cpu_gc_count;
+
+/* The current sampling interval in nanoseconds. */
+static EMACS_INT current_sampling_interval;
+
+/* Signal handler for sampling profiler. */
+
+static void
+handle_profiler_signal (int signal)
+{
+ if (backtrace_list && EQ (backtrace_list->function, Qautomatic_gc))
+ /* Special case the time-count inside GC because the hash-table
+ code is not prepared to be used while the GC is running.
+ More specifically it uses ASIZE at many places where it does
+ not expect the ARRAY_MARK_FLAG to be set. We could try and
+ harden the hash-table code, but it doesn't seem worth the
+ effort. */
+ cpu_gc_count = saturated_add (cpu_gc_count, 1);
+ else
+ {
+ EMACS_INT count = 1;
+#ifdef HAVE_ITIMERSPEC
+ if (profiler_timer_ok)
+ {
+ int overruns = timer_getoverrun (profiler_timer);
+ eassert (0 <= overruns);
+ count += overruns;
+ }
+#endif
+ eassert (HASH_TABLE_P (cpu_log));
+ record_backtrace (XHASH_TABLE (cpu_log), count);
+ }
+}
+
+static void
+deliver_profiler_signal (int signal)
+{
+ deliver_process_signal (signal, handle_profiler_signal);
+}
+
+static enum profiler_cpu_running
+setup_cpu_timer (Lisp_Object sampling_interval)
+{
+ struct sigaction action;
+ struct itimerval timer;
+ struct timespec interval;
+ int billion = 1000000000;
+
+ if (! RANGED_INTEGERP (1, sampling_interval,
+ (TYPE_MAXIMUM (time_t) < EMACS_INT_MAX / billion
+ ? ((EMACS_INT) TYPE_MAXIMUM (time_t) * billion
+ + (billion - 1))
+ : EMACS_INT_MAX)))
+ return NOT_RUNNING;
+
+ current_sampling_interval = XINT (sampling_interval);
+ interval = make_emacs_time (current_sampling_interval / billion,
+ current_sampling_interval % billion);
+ emacs_sigaction_init (&action, deliver_profiler_signal);
+ sigaction (SIGPROF, &action, 0);
+
+#ifdef HAVE_ITIMERSPEC
+ if (! profiler_timer_ok)
+ {
+ /* System clocks to try, in decreasing order of desirability. */
+ static clockid_t const system_clock[] = {
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ CLOCK_THREAD_CPUTIME_ID,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_MONOTONIC
+ CLOCK_MONOTONIC,
+#endif
+ CLOCK_REALTIME
+ };
+ int i;
+ struct sigevent sigev;
+ sigev.sigev_value.sival_ptr = &profiler_timer;
+ sigev.sigev_signo = SIGPROF;
+ sigev.sigev_notify = SIGEV_SIGNAL;
+
+ for (i = 0; i < sizeof system_clock / sizeof *system_clock; i++)
+ if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0)
+ {
+ profiler_timer_ok = 1;
+ break;
+ }
+ }
+
+ if (profiler_timer_ok)
+ {
+ struct itimerspec ispec;
+ ispec.it_value = ispec.it_interval = interval;
+ if (timer_settime (profiler_timer, 0, &ispec, 0) == 0)
+ return TIMER_SETTIME_RUNNING;
+ }
+#endif
+
+#ifdef HAVE_SETITIMER
+ timer.it_value = timer.it_interval = make_timeval (interval);
+ if (setitimer (ITIMER_PROF, &timer, 0) == 0)
+ return SETITIMER_RUNNING;
+#endif
+
+ return NOT_RUNNING;
+}
+
+DEFUN ("profiler-cpu-start", Fprofiler_cpu_start, Sprofiler_cpu_start,
+ 1, 1, 0,
+ doc: /* Start or restart the cpu profiler.
+It takes call-stack samples each SAMPLING-INTERVAL nanoseconds, approximately.
+See also `profiler-log-size' and `profiler-max-stack-depth'. */)
+ (Lisp_Object sampling_interval)
+{
+ if (profiler_cpu_running)
+ error ("CPU profiler is already running");
+
+ if (NILP (cpu_log))
+ {
+ cpu_gc_count = 0;
+ cpu_log = make_log (profiler_log_size,
+ profiler_max_stack_depth);
+ }
+
+ profiler_cpu_running = setup_cpu_timer (sampling_interval);
+ if (! profiler_cpu_running)
+ error ("Invalid sampling interval");
+
+ return Qt;
+}
+
+DEFUN ("profiler-cpu-stop", Fprofiler_cpu_stop, Sprofiler_cpu_stop,
+ 0, 0, 0,
+ doc: /* Stop the cpu profiler. The profiler log is not affected.
+Return non-nil if the profiler was running. */)
+ (void)
+{
+ switch (profiler_cpu_running)
+ {
+ case NOT_RUNNING:
+ return Qnil;
+
+#ifdef HAVE_ITIMERSPEC
+ case TIMER_SETTIME_RUNNING:
+ {
+ struct itimerspec disable;
+ memset (&disable, 0, sizeof disable);
+ timer_settime (profiler_timer, 0, &disable, 0);
+ }
+ break;
+#endif
+
+#ifdef HAVE_SETITIMER
+ case SETITIMER_RUNNING:
+ {
+ struct itimerval disable;
+ memset (&disable, 0, sizeof disable);
+ setitimer (ITIMER_PROF, &disable, 0);
+ }
+ break;
+#endif
+ }
+
+ signal (SIGPROF, SIG_IGN);
+ profiler_cpu_running = NOT_RUNNING;
+ return Qt;
+}
+
+DEFUN ("profiler-cpu-running-p",
+ Fprofiler_cpu_running_p, Sprofiler_cpu_running_p,
+ 0, 0, 0,
+ doc: /* Return non-nil iff cpu profiler is running. */)
+ (void)
+{
+ return profiler_cpu_running ? Qt : Qnil;
+}
+
+DEFUN ("profiler-cpu-log", Fprofiler_cpu_log, Sprofiler_cpu_log,
+ 0, 0, 0,
+ doc: /* Return the current cpu profiler log.
+The log is a hash-table mapping backtraces to counters which represent
+the amount of time spent at those points. Every backtrace is a vector
+of functions, where the last few elements may be nil.
+Before returning, a new log is allocated for future samples. */)
+ (void)
+{
+ Lisp_Object result = cpu_log;
+ /* Here we're making the log visible to Elisp, so it's not safe any
+ more for our use afterwards since we can't rely on its special
+ pre-allocated keys anymore. So we have to allocate a new one. */
+ cpu_log = (profiler_cpu_running
+ ? make_log (profiler_log_size, profiler_max_stack_depth)
+ : Qnil);
+ Fputhash (Fmake_vector (make_number (1), Qautomatic_gc),
+ make_number (cpu_gc_count),
+ result);
+ cpu_gc_count = 0;
+ return result;
+}
+#endif /* PROFILER_CPU_SUPPORT */
+
+/* Memory profiler. */
+
+/* True if memory profiler is running. */
+bool profiler_memory_running;
+
+static Lisp_Object memory_log;
+
+DEFUN ("profiler-memory-start", Fprofiler_memory_start, Sprofiler_memory_start,
+ 0, 0, 0,
+ doc: /* Start/restart the memory profiler.
+The memory profiler will take samples of the call-stack whenever a new
+allocation takes place. Note that most small allocations only trigger
+the profiler occasionally.
+See also `profiler-log-size' and `profiler-max-stack-depth'. */)
+ (void)
+{
+ if (profiler_memory_running)
+ error ("Memory profiler is already running");
+
+ if (NILP (memory_log))
+ memory_log = make_log (profiler_log_size,
+ profiler_max_stack_depth);
+
+ profiler_memory_running = true;
+
+ return Qt;
+}
+
+DEFUN ("profiler-memory-stop",
+ Fprofiler_memory_stop, Sprofiler_memory_stop,
+ 0, 0, 0,
+ doc: /* Stop the memory profiler. The profiler log is not affected.
+Return non-nil if the profiler was running. */)
+ (void)
+{
+ if (!profiler_memory_running)
+ return Qnil;
+ profiler_memory_running = false;
+ return Qt;
+}
+
+DEFUN ("profiler-memory-running-p",
+ Fprofiler_memory_running_p, Sprofiler_memory_running_p,
+ 0, 0, 0,
+ doc: /* Return non-nil if memory profiler is running. */)
+ (void)
+{
+ return profiler_memory_running ? Qt : Qnil;
+}
+
+DEFUN ("profiler-memory-log",
+ Fprofiler_memory_log, Sprofiler_memory_log,
+ 0, 0, 0,
+ doc: /* Return the current memory profiler log.
+The log is a hash-table mapping backtraces to counters which represent
+the amount of memory allocated at those points. Every backtrace is a vector
+of functions, where the last few elements may be nil.
+Before returning, a new log is allocated for future samples. */)
+ (void)
+{
+ Lisp_Object result = memory_log;
+ /* Here we're making the log visible to Elisp , so it's not safe any
+ more for our use afterwards since we can't rely on its special
+ pre-allocated keys anymore. So we have to allocate a new one. */
+ memory_log = (profiler_memory_running
+ ? make_log (profiler_log_size, profiler_max_stack_depth)
+ : Qnil);
+ return result;
+}
+
+
+/* Signals and probes. */
+
+/* Record that the current backtrace allocated SIZE bytes. */
+void
+malloc_probe (size_t size)
+{
+ eassert (HASH_TABLE_P (memory_log));
+ record_backtrace (XHASH_TABLE (memory_log), min (size, MOST_POSITIVE_FIXNUM));
+}
+
+DEFUN ("function-equal", Ffunction_equal, Sfunction_equal, 2, 2, 0,
+ doc: /* Return non-nil if F1 and F2 come from the same source.
+Used to determine if different closures are just different instances of
+the same lambda expression, or are really unrelated function. */)
+ (Lisp_Object f1, Lisp_Object f2)
+{
+ bool res;
+ if (EQ (f1, f2))
+ res = true;
+ else if (COMPILEDP (f1) && COMPILEDP (f2))
+ res = EQ (AREF (f1, COMPILED_BYTECODE), AREF (f2, COMPILED_BYTECODE));
+ else if (CONSP (f1) && CONSP (f2) && CONSP (XCDR (f1)) && CONSP (XCDR (f2))
+ && EQ (Qclosure, XCAR (f1))
+ && EQ (Qclosure, XCAR (f2)))
+ res = EQ (XCDR (XCDR (f1)), XCDR (XCDR (f2)));
+ else
+ res = false;
+ return res ? Qt : Qnil;
+}
+
+static bool
+cmpfn_profiler (struct hash_table_test *t,
+ Lisp_Object bt1, Lisp_Object bt2)
+{
+ if (VECTORP (bt1) && VECTORP (bt2))
+ {
+ ptrdiff_t i, l = ASIZE (bt1);
+ if (l != ASIZE (bt2))
+ return false;
+ for (i = 0; i < l; i++)
+ if (NILP (Ffunction_equal (AREF (bt1, i), AREF (bt2, i))))
+ return false;
+ return true;
+ }
+ else
+ return EQ (bt1, bt2);
+}
+
+static EMACS_UINT
+hashfn_profiler (struct hash_table_test *ht, Lisp_Object bt)
+{
+ if (VECTORP (bt))
+ {
+ EMACS_UINT hash = 0;
+ ptrdiff_t i, l = ASIZE (bt);
+ for (i = 0; i < l; i++)
+ {
+ Lisp_Object f = AREF (bt, i);
+ EMACS_UINT hash1
+ = (COMPILEDP (f) ? XHASH (AREF (f, COMPILED_BYTECODE))
+ : (CONSP (f) && CONSP (XCDR (f)) && EQ (Qclosure, XCAR (f)))
+ ? XHASH (XCDR (XCDR (f))) : XHASH (f));
+ hash = sxhash_combine (hash, hash1);
+ }
+ return (hash & INTMASK);
+ }
+ else
+ return XHASH (bt);
+}
+
+void
+syms_of_profiler (void)
+{
+ DEFVAR_INT ("profiler-max-stack-depth", profiler_max_stack_depth,
+ doc: /* Number of elements from the call-stack recorded in the log. */);
+ profiler_max_stack_depth = 16;
+ DEFVAR_INT ("profiler-log-size", profiler_log_size,
+ doc: /* Number of distinct call-stacks that can be recorded in a profiler log.
+If the log gets full, some of the least-seen call-stacks will be evicted
+to make room for new entries. */);
+ profiler_log_size = 10000;
+
+ DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal");
+ {
+ struct hash_table_test test
+ = { Qprofiler_backtrace_equal, Qnil, Qnil,
+ cmpfn_profiler, hashfn_profiler };
+ hashtest_profiler = test;
+ }
+
+ defsubr (&Sfunction_equal);
+
+#ifdef PROFILER_CPU_SUPPORT
+ profiler_cpu_running = NOT_RUNNING;
+ cpu_log = Qnil;
+ staticpro (&cpu_log);
+ defsubr (&Sprofiler_cpu_start);
+ defsubr (&Sprofiler_cpu_stop);
+ defsubr (&Sprofiler_cpu_running_p);
+ defsubr (&Sprofiler_cpu_log);
+#endif
+ profiler_memory_running = false;
+ memory_log = Qnil;
+ staticpro (&memory_log);
+ defsubr (&Sprofiler_memory_start);
+ defsubr (&Sprofiler_memory_stop);
+ defsubr (&Sprofiler_memory_running_p);
+ defsubr (&Sprofiler_memory_log);
+}
diff --git a/src/puresize.h b/src/puresize.h
index 2f024345d61..26395a5729d 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 (1620000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA)
+#define BASE_PURESIZE (1700000 + 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 3877e21d4f6..e5bf76b0e6d 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -25,7 +25,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef emacs
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h" /* Needed for VALBITS. */
#include "blockinput.h"
@@ -72,7 +72,7 @@ static void r_alloc_init (void);
/* Declarations for working with the malloc, ralloc, and system breaks. */
/* Function to set the real break value. */
-POINTER (*real_morecore) (long int);
+POINTER (*real_morecore) (ptrdiff_t);
/* The break value, as seen by malloc. */
static POINTER virtual_break_value;
@@ -91,18 +91,18 @@ static int extra_bytes;
/* Macros for rounding. Note that rounding to any value is possible
by changing the definition of PAGE. */
#define PAGE (getpagesize ())
-#define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \
- & ~(page_size - 1))
+#define ROUNDUP(size) (((size_t) (size) + page_size - 1) \
+ & ~((size_t)(page_size - 1)))
#define MEM_ALIGN sizeof (double)
-#define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \
- & ~(MEM_ALIGN - 1))
+#define MEM_ROUNDUP(addr) (((size_t)(addr) + MEM_ALIGN - 1) \
+ & ~(MEM_ALIGN - 1))
/* The hook `malloc' uses for the function which gets more space
from the system. */
#ifndef SYSTEM_MALLOC
-extern POINTER (*__morecore) (long int);
+extern POINTER (*__morecore) (ptrdiff_t);
#endif
@@ -237,7 +237,7 @@ obtain (POINTER address, SIZE size)
}
if (! heap)
- abort ();
+ emacs_abort ();
/* If we can't fit SIZE bytes in that heap,
try successive later heaps. */
@@ -308,7 +308,7 @@ static void
relinquish (void)
{
register heap_ptr h;
- long excess = 0;
+ ptrdiff_t excess = 0;
/* Add the amount of space beyond break_value
in all heaps which have extend beyond break_value at all. */
@@ -327,35 +327,36 @@ relinquish (void)
if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess)
{
- /* This heap should have no blocs in it. */
+ heap_ptr lh_prev;
+
+ /* This heap should have no blocs in it. If it does, we
+ cannot return it to the system. */
if (last_heap->first_bloc != NIL_BLOC
|| last_heap->last_bloc != NIL_BLOC)
- abort ();
+ return;
/* Return the last heap, with its header, to the system. */
excess = (char *)last_heap->end - (char *)last_heap->start;
- last_heap = last_heap->prev;
- last_heap->next = NIL_HEAP;
+ lh_prev = last_heap->prev;
+ /* If the system doesn't want that much memory back, leave
+ last_heap unaltered to reflect that. This can occur if
+ break_value is still within the original data segment. */
+ if ((*real_morecore) (- excess) != 0)
+ {
+ last_heap = lh_prev;
+ last_heap->next = NIL_HEAP;
+ }
}
else
{
excess = (char *) last_heap->end
- (char *) ROUNDUP ((char *)last_heap->end - excess);
- last_heap->end = (char *) last_heap->end - excess;
- }
-
- if ((*real_morecore) (- excess) == 0)
- {
- /* If the system didn't want that much memory back, adjust
- the end of the last heap to reflect that. This can occur
- if break_value is still within the original data segment. */
- last_heap->end = (char *) last_heap->end + excess;
- /* Make sure that the result of the adjustment is accurate.
- It should be, for the else clause above; the other case,
- which returns the entire last heap to the system, seems
- unlikely to trigger this mode of failure. */
- if (last_heap->end != (*real_morecore) (0))
- abort ();
+ /* If the system doesn't want that much memory back, leave
+ the end of the last heap unchanged to reflect that. This
+ can occur if break_value is still within the original
+ data segment. */
+ if ((*real_morecore) (- excess) != 0)
+ last_heap->end = (char *) last_heap->end - excess;
}
}
}
@@ -452,7 +453,7 @@ relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address)
/* No need to ever call this if arena is frozen, bug somewhere! */
if (r_alloc_freeze_level)
- abort ();
+ emacs_abort ();
while (b)
{
@@ -576,7 +577,7 @@ resize_bloc (bloc_ptr bloc, SIZE size)
/* No need to ever call this if arena is frozen, bug somewhere! */
if (r_alloc_freeze_level)
- abort ();
+ emacs_abort ();
if (bloc == NIL_BLOC || size == bloc->size)
return 1;
@@ -588,7 +589,7 @@ resize_bloc (bloc_ptr bloc, SIZE size)
}
if (heap == NIL_HEAP)
- abort ();
+ emacs_abort ();
old_size = bloc->size;
bloc->size = size;
@@ -752,7 +753,7 @@ free_bloc (bloc_ptr bloc)
GNU malloc package. */
static POINTER
-r_alloc_sbrk (long int size)
+r_alloc_sbrk (ptrdiff_t size)
{
register bloc_ptr b;
POINTER address;
@@ -937,7 +938,7 @@ r_alloc_free (register POINTER *ptr)
dead_bloc = find_bloc (ptr);
if (dead_bloc == NIL_BLOC)
- abort (); /* Double free? PTR not originally used to allocate? */
+ emacs_abort (); /* Double free? PTR not originally used to allocate? */
free_bloc (dead_bloc);
*ptr = 0;
@@ -979,7 +980,7 @@ r_re_alloc (POINTER *ptr, SIZE size)
bloc = find_bloc (ptr);
if (bloc == NIL_BLOC)
- abort (); /* Already freed? PTR not originally used to allocate? */
+ emacs_abort (); /* Already freed? PTR not originally used to allocate? */
if (size < bloc->size)
{
@@ -1152,7 +1153,7 @@ r_alloc_reset_variable (POINTER *old, POINTER *new)
}
if (bloc == NIL_BLOC || bloc->variable != old)
- abort (); /* Already freed? OLD not originally used to allocate? */
+ emacs_abort (); /* Already freed? OLD not originally used to allocate? */
/* Update variable to point to the new location. */
bloc->variable = new;
@@ -1193,20 +1194,26 @@ r_alloc_init (void)
first_heap->start = first_heap->bloc_start
= virtual_break_value = break_value = (*real_morecore) (0);
if (break_value == NIL)
- abort ();
+ emacs_abort ();
extra_bytes = ROUNDUP (50000);
#endif
#ifdef DOUG_LEA_MALLOC
- BLOCK_INPUT;
+ block_input ();
mallopt (M_TOP_PAD, 64 * 4096);
- UNBLOCK_INPUT;
+ unblock_input ();
#else
#ifndef SYSTEM_MALLOC
- /* Give GNU malloc's morecore some hysteresis
- so that we move all the relocatable blocks much less often. */
- __malloc_extra_blocks = 64;
+ /* 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
+ removed when SYNC_INPUT became the only input handling mode.
+ That code was conditioned on !DOUG_LEA_MALLOC, so the call to
+ mallopt above is left unchanged. (Actually, I think there's no
+ system nowadays that uses DOUG_LEA_MALLOC and also uses
+ REL_ALLOC.) */
+ __malloc_extra_blocks = 32;
#endif
#endif
diff --git a/src/regex.c b/src/regex.c
index b995538e30d..878b629fbbf 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -28,7 +28,7 @@
rather than at run-time, so that re_match can be reentrant.
*/
-/* AIX requires this to be the first thing in the file. */
+/* AIX requires this to be the first thing in the file. */
#if defined _AIX && !defined REGEX_MALLOC
#pragma alloca
#endif
@@ -126,7 +126,6 @@
that make sense only in Emacs. */
#ifdef emacs
-# include <setjmp.h>
# include "lisp.h"
# include "character.h"
# include "buffer.h"
@@ -1836,10 +1835,9 @@ typedef struct
/* The next available element. */
#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
-/* Explicit quit checking is only used on NTemacs and whenever we
- use polling to process input events. */
-#if defined emacs && (defined WINDOWSNT || defined SYNC_INPUT) && defined QUIT
-extern int immediate_quit;
+/* Explicit quit checking is needed for Emacs, which uses polling to
+ process input events. */
+#ifdef emacs
# define IMMEDIATE_QUIT_CHECK \
do { \
if (immediate_quit) QUIT; \
diff --git a/src/region-cache.c b/src/region-cache.c
index d2bba8c11b2..832f4bfd214 100644
--- a/src/region-cache.c
+++ b/src/region-cache.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -194,7 +193,7 @@ find_cache_boundary (struct region_cache *c, ptrdiff_t pos)
if (BOUNDARY_POS (c, low) > pos
|| (low + 1 < c->cache_len
&& BOUNDARY_POS (c, low + 1) <= pos))
- abort ();
+ emacs_abort ();
return low;
}
@@ -217,12 +216,12 @@ move_cache_gap (struct region_cache *c, ptrdiff_t pos, ptrdiff_t min_size)
if (pos < 0
|| pos > c->cache_len)
- abort ();
+ emacs_abort ();
/* We mustn't ever try to put the gap before the dummy start
boundary. That must always be start-relative. */
if (pos == 0)
- abort ();
+ emacs_abort ();
/* Need we move the gap right? */
while (gap_start < pos)
@@ -291,24 +290,24 @@ insert_cache_boundary (struct region_cache *c, ptrdiff_t i, ptrdiff_t pos,
{
/* i must be a valid cache index. */
if (i < 0 || i > c->cache_len)
- abort ();
+ emacs_abort ();
/* We must never want to insert something before the dummy first
boundary. */
if (i == 0)
- abort ();
+ emacs_abort ();
/* We must only be inserting things in order. */
if (! (BOUNDARY_POS (c, i - 1) < pos
&& (i == c->cache_len
|| pos < BOUNDARY_POS (c, i))))
- abort ();
+ emacs_abort ();
/* The value must be different from the ones around it. However, we
temporarily create boundaries that establish the same value as
the subsequent boundary, so we're not going to flag that case. */
if (BOUNDARY_VALUE (c, i - 1) == value)
- abort ();
+ emacs_abort ();
move_cache_gap (c, i, 1);
@@ -331,16 +330,16 @@ delete_cache_boundaries (struct region_cache *c,
/* Gotta be in range. */
if (start < 0
|| end > c->cache_len)
- abort ();
+ emacs_abort ();
/* Gotta be in order. */
if (start > end)
- abort ();
+ emacs_abort ();
/* Can't delete the dummy entry. */
if (start == 0
&& end >= 1)
- abort ();
+ emacs_abort ();
/* Minimize gap motion. If we're deleting nothing, do nothing. */
if (len == 0)
@@ -380,10 +379,10 @@ set_cache_region (struct region_cache *c,
ptrdiff_t start, ptrdiff_t end, int value)
{
if (start > end)
- abort ();
+ emacs_abort ();
if (start < c->buffer_beg
|| end > c->buffer_end)
- abort ();
+ emacs_abort ();
/* Eliminate this case; then we can assume that start and end-1 are
both the locations of real characters in the buffer. */
diff --git a/src/scroll.c b/src/scroll.c
index 78ebe65bdcc..71ce43b2e48 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "termchar.h"
#include "dispextern.h"
@@ -195,13 +195,13 @@ calculate_scrolling (FRAME_PTR frame,
{
cost = p1->writecost + first_insert_cost[i];
if ((int) p1->insertcount > i)
- abort ();
+ emacs_abort ();
cost1 = p1->insertcost + next_insert_cost[i - p1->insertcount];
}
p->insertcost = min (cost, cost1) + draw_cost[i] + extra_cost;
p->insertcount = (cost < cost1) ? 1 : p1->insertcount + 1;
if ((int) p->insertcount > i)
- abort ();
+ emacs_abort ();
/* Calculate the cost if we do a delete line after
outputting this line.
diff --git a/src/search.c b/src/search.c
index dac1a8d4dfc..ae038a45f9c 100644
--- a/src/search.c
+++ b/src/search.c
@@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "syntax.h"
#include "category.h"
@@ -156,7 +156,7 @@ compile_pattern_1 (struct regexp_cache *cp, Lisp_Object pattern, Lisp_Object tra
re_set_whitespace_regexp (NULL);
re_set_syntax (old);
- /* UNBLOCK_INPUT; */
+ /* unblock_input (); */
if (val)
xsignal1 (Qinvalid_regexp, build_string (val));
@@ -636,12 +636,12 @@ newline_cache_on_off (struct buffer *buf)
If we don't find COUNT instances before reaching END, set *SHORTAGE
to the number of TARGETs left unfound, and return END.
- If ALLOW_QUIT is non-zero, set immediate_quit. That's good to do
+ If ALLOW_QUIT, set immediate_quit. That's good to do
except when inside redisplay. */
ptrdiff_t
-scan_buffer (register int target, ptrdiff_t start, ptrdiff_t end,
- ptrdiff_t count, ptrdiff_t *shortage, int allow_quit)
+scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
+ ptrdiff_t count, ptrdiff_t *shortage, bool allow_quit)
{
struct region_cache *newline_cache;
int direction;
@@ -674,7 +674,7 @@ scan_buffer (register int target, ptrdiff_t start, ptrdiff_t end,
obstacle --- the last character the dumb search loop should
examine. */
ptrdiff_t ceiling_byte = CHAR_TO_BYTE (end) - 1;
- ptrdiff_t start_byte = CHAR_TO_BYTE (start);
+ ptrdiff_t start_byte;
ptrdiff_t tem;
/* If we're looking for a newline, consult the newline cache
@@ -684,18 +684,22 @@ scan_buffer (register int target, ptrdiff_t start, ptrdiff_t end,
ptrdiff_t next_change;
immediate_quit = 0;
while (region_cache_forward
- (current_buffer, newline_cache, start_byte, &next_change))
- start_byte = next_change;
+ (current_buffer, newline_cache, start, &next_change))
+ start = next_change;
immediate_quit = allow_quit;
+ start_byte = CHAR_TO_BYTE (start);
+
/* START should never be after END. */
if (start_byte > ceiling_byte)
start_byte = ceiling_byte;
/* Now the text after start is an unknown region, and
next_change is the position of the next known region. */
- ceiling_byte = min (next_change - 1, ceiling_byte);
+ ceiling_byte = min (CHAR_TO_BYTE (next_change) - 1, ceiling_byte);
}
+ else
+ start_byte = CHAR_TO_BYTE (start);
/* The dumb loop can only scan text stored in contiguous
bytes. BUFFER_CEILING_OF returns the last character
@@ -747,7 +751,7 @@ scan_buffer (register int target, ptrdiff_t start, ptrdiff_t end,
{
/* The last character to check before the next obstacle. */
ptrdiff_t ceiling_byte = CHAR_TO_BYTE (end);
- ptrdiff_t start_byte = CHAR_TO_BYTE (start);
+ ptrdiff_t start_byte;
ptrdiff_t tem;
/* Consult the newline cache, if appropriate. */
@@ -756,18 +760,22 @@ scan_buffer (register int target, ptrdiff_t start, ptrdiff_t end,
ptrdiff_t next_change;
immediate_quit = 0;
while (region_cache_backward
- (current_buffer, newline_cache, start_byte, &next_change))
- start_byte = next_change;
+ (current_buffer, newline_cache, start, &next_change))
+ start = next_change;
immediate_quit = allow_quit;
+ start_byte = CHAR_TO_BYTE (start);
+
/* Start should never be at or before end. */
if (start_byte <= ceiling_byte)
start_byte = ceiling_byte + 1;
/* Now the text before start is an unknown region, and
next_change is the position of the next known region. */
- ceiling_byte = max (next_change, ceiling_byte);
+ ceiling_byte = max (CHAR_TO_BYTE (next_change), ceiling_byte);
}
+ else
+ start_byte = CHAR_TO_BYTE (start);
/* Stop scanning before the gap. */
tem = BUFFER_FLOOR_OF (start_byte - 1);
@@ -829,23 +837,23 @@ scan_buffer (register int target, ptrdiff_t start, ptrdiff_t end,
the number of line boundaries left unfound, and position at
the limit we bumped up against.
- If ALLOW_QUIT is non-zero, set immediate_quit. That's good to do
+ If ALLOW_QUIT, set immediate_quit. That's good to do
except in special cases. */
EMACS_INT
scan_newline (ptrdiff_t start, ptrdiff_t start_byte,
ptrdiff_t limit, ptrdiff_t limit_byte,
- register EMACS_INT count, int allow_quit)
+ EMACS_INT count, bool allow_quit)
{
int direction = ((count > 0) ? 1 : -1);
- register unsigned char *cursor;
+ unsigned char *cursor;
unsigned char *base;
ptrdiff_t ceiling;
- register unsigned char *ceiling_addr;
+ unsigned char *ceiling_addr;
- int old_immediate_quit = immediate_quit;
+ bool old_immediate_quit = immediate_quit;
/* The code that follows is like scan_buffer
but checks for either newline or carriage return. */
@@ -1009,7 +1017,7 @@ search_command (Lisp_Object string, Lisp_Object bound, Lisp_Object noerror,
if (!EQ (noerror, Qt))
{
if (lim < BEGV || lim > ZV)
- abort ();
+ emacs_abort ();
SET_PT_BOTH (lim, lim_byte);
return Qnil;
#if 0 /* This would be clean, but maybe programs depend on
@@ -1022,7 +1030,7 @@ search_command (Lisp_Object string, Lisp_Object bound, Lisp_Object noerror,
}
if (np < BEGV || np > ZV)
- abort ();
+ emacs_abort ();
SET_PT (np);
@@ -1398,7 +1406,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
char_base = 0;
while (--len >= 0)
{
- int c, translated;
+ int c, translated, inverse;
/* If we got here and the RE flag is set, it's because we're
dealing with a regexp known to be trivial, so the backslash
@@ -1412,6 +1420,20 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
c = *base_pat++;
TRANSLATE (translated, trt, c);
*pat++ = translated;
+ /* Check that none of C's equivalents violates the
+ assumptions of boyer_moore. */
+ TRANSLATE (inverse, inverse_trt, c);
+ while (1)
+ {
+ if (inverse >= 0200)
+ {
+ boyer_moore_ok = 0;
+ break;
+ }
+ if (c == inverse)
+ break;
+ TRANSLATE (inverse, inverse_trt, inverse);
+ }
}
}
@@ -2212,15 +2234,14 @@ DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 5, 0,
doc: /* Replace text matched by last search with NEWTEXT.
Leave point at the end of the replacement text.
-If second arg FIXEDCASE is non-nil, do not alter case of replacement text.
-Otherwise maybe capitalize the whole text, or maybe just word initials,
-based on the replaced text.
-If the replaced text has only capital letters
-and has at least one multiletter word, convert NEWTEXT to all caps.
-Otherwise if all words are capitalized in the replaced text,
-capitalize each word in NEWTEXT.
+If optional second arg FIXEDCASE is non-nil, do not alter the case of
+the replacement text. Otherwise, maybe capitalize the whole text, or
+maybe just word initials, based on the replaced text. If the replaced
+text has only capital letters and has at least one multiletter word,
+convert NEWTEXT to all caps. Otherwise if all words are capitalized
+in the replaced text, capitalize each word in NEWTEXT.
-If third arg LITERAL is non-nil, insert NEWTEXT literally.
+If optional third arg LITERAL is non-nil, insert NEWTEXT literally.
Otherwise treat `\\' as special:
`\\&' in NEWTEXT means substitute original matched text.
`\\N' means substitute what matched the Nth `\\(...\\)'.
@@ -2231,13 +2252,11 @@ Otherwise treat `\\' as special:
Any other character following `\\' signals an error.
Case conversion does not apply to these substitutions.
-FIXEDCASE and LITERAL are optional arguments.
-
-The optional fourth argument STRING can be a string to modify.
-This is meaningful when the previous match was done against STRING,
-using `string-match'. When used this way, `replace-match'
-creates and returns a new string made by copying STRING and replacing
-the part of STRING that was matched.
+If optional fourth argument STRING is non-nil, it should be a string
+to act on; this should be the string on which the previous match was
+done via `string-match'. In this case, `replace-match' creates and
+returns a new string, made by copying STRING and replacing the part of
+STRING that was matched (the original STRING itself is not altered).
The optional fifth argument SUBEXP specifies a subexpression;
it says to replace just that subexpression with NEWTEXT,
@@ -2770,7 +2789,7 @@ Return value is undefined if the last search failed. */)
}
else
/* last_thing_searched must always be Qt, a buffer, or Qnil. */
- abort ();
+ emacs_abort ();
len = 2 * i + 2;
}
diff --git a/src/sheap.c b/src/sheap.c
index 3ae14b5daec..f6022ea3ce7 100644
--- a/src/sheap.c
+++ b/src/sheap.c
@@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include <unistd.h>
@@ -93,4 +93,3 @@ report_sheap_usage (int die_if_pure_storage_exceeded)
bss_sbrk_ptr - bss_sbrk_buffer, STATIC_HEAP_SIZE);
message ("%s", buf);
}
-
diff --git a/src/sound.c b/src/sound.c
index 403f08240ce..0ee85312fd3 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -44,11 +44,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "dispextern.h"
#include "atimer.h"
-#include <signal.h>
#include "syssignal.h"
/* END: Common Includes */
@@ -315,8 +314,13 @@ sound_perror (const char *msg)
int saved_errno = errno;
turn_on_atimers (1);
-#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
+#ifdef USABLE_SIGIO
+ {
+ sigset_t unblocked;
+ sigemptyset (&unblocked);
+ sigaddset (&unblocked, SIGIO);
+ pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
+ }
#endif
if (saved_errno != 0)
error ("%s: %s", msg, strerror (saved_errno));
@@ -728,6 +732,9 @@ static void
vox_configure (struct sound_device *sd)
{
int val;
+#ifdef USABLE_SIGIO
+ sigset_t blocked;
+#endif
eassert (sd->fd >= 0);
@@ -735,8 +742,10 @@ vox_configure (struct sound_device *sd)
interrupted by a signal. Block the ones we know to cause
troubles. */
turn_on_atimers (0);
-#ifdef SIGIO
- sigblock (sigmask (SIGIO));
+#ifdef USABLE_SIGIO
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGIO);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
#endif
val = sd->format;
@@ -769,8 +778,8 @@ vox_configure (struct sound_device *sd)
}
turn_on_atimers (1);
-#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
+#ifdef USABLE_SIGIO
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
#endif
}
@@ -785,8 +794,11 @@ vox_close (struct sound_device *sd)
/* On GNU/Linux, it seems that the device driver doesn't like to
be interrupted by a signal. Block the ones we know to cause
troubles. */
-#ifdef SIGIO
- sigblock (sigmask (SIGIO));
+#ifdef USABLE_SIGIO
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGIO);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
#endif
turn_on_atimers (0);
@@ -794,8 +806,8 @@ vox_close (struct sound_device *sd)
ioctl (sd->fd, SNDCTL_DSP_SYNC, NULL);
turn_on_atimers (1);
-#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
+#ifdef USABLE_SIGIO
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
#endif
/* Close the device. */
@@ -843,7 +855,7 @@ vox_choose_format (struct sound_device *sd, struct sound *s)
}
}
else
- abort ();
+ emacs_abort ();
}
@@ -1138,7 +1150,7 @@ alsa_choose_format (struct sound_device *sd, struct sound *s)
}
}
else
- abort ();
+ emacs_abort ();
}
diff --git a/src/syntax.c b/src/syntax.c
index f995b8f2cac..d3cafcc472e 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <sys/types.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "commands.h"
#include "character.h"
@@ -151,7 +151,7 @@ static void scan_sexps_forward (struct lisp_parse_state *,
static int in_classes (int, Lisp_Object);
/* This setter is used only in this file, so it can be private. */
-static inline void
+static void
bset_syntax_table (struct buffer *b, Lisp_Object val)
{
b->INTERNAL_FIELD (syntax_table) = val;
@@ -372,7 +372,7 @@ char_quoted (ptrdiff_t charpos, ptrdiff_t bytepos)
/* Return the bytepos one character before BYTEPOS.
We assume that BYTEPOS is not at the start of the buffer. */
-static inline ptrdiff_t
+static ptrdiff_t
dec_bytepos (ptrdiff_t bytepos)
{
if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
@@ -921,11 +921,11 @@ DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0,
}
DEFUN ("string-to-syntax", Fstring_to_syntax, Sstring_to_syntax, 1, 1, 0,
- doc: /* Convert a syntax specification STRING into syntax cell form.
-STRING should be a string as it is allowed as argument of
-`modify-syntax-entry'. Value is the equivalent cons cell
-\(CODE . MATCHING-CHAR) that can be used as value of a `syntax-table'
-text property. */)
+ doc: /* Convert a syntax descriptor STRING into a raw syntax descriptor.
+STRING should be a string of the form allowed as argument of
+`modify-syntax-entry'. The return value is a raw syntax descriptor: a
+cons cell \(CODE . MATCHING-CHAR) which can be used, for example, as
+the value of a `syntax-table' text property. */)
(Lisp_Object string)
{
register const unsigned char *p;
diff --git a/src/sysdep.c b/src/sysdep.c
index b84e6a4ea3a..5291c5d59aa 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -21,9 +21,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define SYSTIME_INLINE EXTERN_INLINE
-#include <signal.h>
+#include <execinfo.h>
#include <stdio.h>
-#include <setjmp.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#include <grp.h>
@@ -55,6 +54,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef WINDOWSNT
#define read sys_read
#define write sys_write
+#ifndef STDERR_FILENO
+#define STDERR_FILENO fileno(GetStdHandle(STD_ERROR_HANDLE))
+#endif
#include <windows.h>
#endif /* not WINDOWSNT */
@@ -99,7 +101,6 @@ 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);
-extern char *getwd (char *);
#endif
#include "syssignal.h"
@@ -107,9 +108,6 @@ extern char *getwd (char *);
static int emacs_get_tty (int, struct emacs_tty *);
static int emacs_set_tty (int, struct emacs_tty *, int);
-#if defined TIOCNOTTY || defined USG5 || defined CYGWIN
-static _Noreturn void croak (char *);
-#endif
/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */
#ifndef ULLONG_MAX
@@ -135,12 +133,12 @@ char*
get_current_dir_name (void)
{
char *buf;
- char *pwd;
+ char *pwd = getenv ("PWD");
struct stat dotstat, pwdstat;
- /* If PWD is accurate, use it instead of calling getwd. PWD is
+ /* If PWD is accurate, use it instead of calling getcwd. PWD is
sometimes a nicer name, and using it may avoid a fatal error if a
parent directory is searchable but not readable. */
- if ((pwd = getenv ("PWD")) != 0
+ if (pwd
&& (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
&& stat (pwd, &pwdstat) == 0
&& stat (".", &dotstat) == 0
@@ -156,7 +154,6 @@ get_current_dir_name (void)
return NULL;
strcpy (buf, pwd);
}
-#ifdef HAVE_GETCWD
else
{
size_t buf_size = 1024;
@@ -180,22 +177,6 @@ get_current_dir_name (void)
return NULL;
}
}
-#else
- else
- {
- /* We need MAXPATHLEN here. */
- buf = malloc (MAXPATHLEN + 1);
- if (!buf)
- return NULL;
- if (getwd (buf) == NULL)
- {
- int tmp_errno = errno;
- free (buf);
- errno = tmp_errno;
- return NULL;
- }
- }
-#endif
return buf;
}
#endif
@@ -283,71 +264,76 @@ init_baud_rate (int fd)
-/* Set nonzero to make following function work under dbx
- (at least for bsd). */
-int wait_debugging EXTERNALLY_VISIBLE;
-
#ifndef MSDOS
-static void
-wait_for_termination_1 (pid_t pid, int interruptible)
+/* Wait for the subprocess with process id CHILD to terminate or change status.
+ CHILD must be a child process that has not been reaped.
+ If STATUS is non-null, store the waitpid-style exit status into *STATUS
+ and tell wait_reading_process_output that it needs to look around.
+ Use waitpid-style OPTIONS when waiting.
+ If INTERRUPTIBLE, this function is interruptible by a signal.
+
+ Return CHILD if successful, 0 if no status is available;
+ the latter is possible only when options & NOHANG. */
+static pid_t
+get_child_status (pid_t child, int *status, int options, bool interruptible)
{
- while (1)
- {
-#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined (__GNU__)
- /* Note that kill returns -1 even if the process is just a zombie now.
- But inevitably a SIGCHLD interrupt should be generated
- and child_sig will do waitpid and make the process go away. */
- /* There is some indication that there is a bug involved with
- termination of subprocesses, perhaps involving a kernel bug too,
- but no idea what it is. Just as a hunch we signal SIGCHLD to see
- if that causes the problem to go away or get worse. */
- sigsetmask (sigmask (SIGCHLD));
- if (0 > kill (pid, 0))
- {
- sigsetmask (SIGEMPTYMASK);
- kill (getpid (), SIGCHLD);
- break;
- }
- if (wait_debugging)
- sleep (1);
- else
- sigpause (SIGEMPTYMASK);
-#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#ifdef WINDOWSNT
- wait (0);
- break;
-#else /* not WINDOWSNT */
- sigblock (sigmask (SIGCHLD));
- errno = 0;
- if (kill (pid, 0) == -1 && errno == ESRCH)
- {
- sigunblock (sigmask (SIGCHLD));
- break;
- }
+ pid_t pid;
- sigsuspend (&empty_mask);
-#endif /* not WINDOWSNT */
-#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
+ /* Invoke waitpid only with a known process ID; do not invoke
+ waitpid with a nonpositive argument. Otherwise, Emacs might
+ reap an unwanted process by mistake. For example, invoking
+ waitpid (-1, ...) can mess up glib by reaping glib's subprocesses,
+ so that another thread running glib won't find them. */
+ eassert (0 < child);
+
+ while ((pid = waitpid (child, status, options)) < 0)
+ {
+ /* Check that CHILD is a child process that has not been reaped,
+ and that STATUS and OPTIONS are valid. Otherwise abort,
+ as continuing after this internal error could cause Emacs to
+ become confused and kill innocent-victim processes. */
+ if (errno != EINTR)
+ emacs_abort ();
+
+ /* Note: the MS-Windows emulation of waitpid calls QUIT
+ internally. */
if (interruptible)
QUIT;
}
-}
-/* Wait for subprocess with process id `pid' to terminate and
- make sure it will get eliminated (not remain forever as a zombie) */
+ /* If successful and status is requested, tell wait_reading_process_output
+ that it needs to wake up and look around. */
+ if (pid && status && input_available_clear_time)
+ *input_available_clear_time = make_emacs_time (0, 0);
+ return pid;
+}
+
+/* Wait for the subprocess with process id CHILD to terminate.
+ CHILD must be a child process that has not been reaped.
+ If STATUS is non-null, store the waitpid-style exit status into *STATUS
+ and tell wait_reading_process_output that it needs to look around.
+ If INTERRUPTIBLE, this function is interruptible by a signal. */
void
-wait_for_termination (pid_t pid)
+wait_for_termination (pid_t child, int *status, bool interruptible)
{
- wait_for_termination_1 (pid, 0);
+ get_child_status (child, status, 0, interruptible);
}
-/* Like the above, but allow keyboard interruption. */
-void
-interruptible_wait_for_termination (pid_t pid)
+/* Report whether the subprocess with process id CHILD has changed status.
+ Termination counts as a change of status.
+ CHILD must be a child process that has not been reaped.
+ If STATUS is non-null, store the waitpid-style exit status into *STATUS
+ and tell wait_reading_process_output that it needs to look around.
+ Use waitpid-style OPTIONS to check status, but do not wait.
+
+ Return CHILD if successful, 0 if no status is available because
+ the process's state has not changed. */
+pid_t
+child_status_changed (pid_t child, int *status, int options)
{
- wait_for_termination_1 (pid, 1);
+ return get_child_status (child, status, WNOHANG | options, 0);
}
/*
@@ -456,11 +442,11 @@ child_setup_tty (int out)
#endif /* not MSDOS */
-/* Record a signal code and the handler for it. */
+/* Record a signal code and the action for it. */
struct save_signal
{
int code;
- void (*handler) (int);
+ struct sigaction action;
};
static void save_signal_handlers (struct save_signal *);
@@ -471,20 +457,15 @@ static void restore_signal_handlers (struct save_signal *);
void
sys_suspend (void)
{
-#if defined (SIGTSTP) && !defined (MSDOS)
-
- {
- int pgrp = EMACS_GETPGRP (0);
- EMACS_KILLPG (pgrp, SIGTSTP);
- }
-
-#else /* No SIGTSTP */
+#ifndef DOS_NT
+ kill (0, SIGTSTP);
+#else
/* On a system where suspending is not implemented,
instead fork a subshell and let it talk directly to the terminal
while we wait. */
sys_subshell ();
-#endif /* no SIGTSTP */
+#endif
}
/* Fork a subshell. */
@@ -496,7 +477,8 @@ sys_subshell (void)
int st;
char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
#endif
- int pid;
+ pid_t pid;
+ int status;
struct save_signal saved_handlers[5];
Lisp_Object dir;
unsigned char *volatile str_volatile = 0;
@@ -506,7 +488,7 @@ sys_subshell (void)
saved_handlers[0].code = SIGINT;
saved_handlers[1].code = SIGQUIT;
saved_handlers[2].code = SIGTERM;
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
saved_handlers[3].code = SIGIO;
saved_handlers[4].code = 0;
#else
@@ -534,7 +516,6 @@ sys_subshell (void)
#ifdef DOS_NT
pid = 0;
save_signal_handlers (saved_handlers);
- synch_process_alive = 1;
#else
pid = vfork ();
if (pid == -1)
@@ -546,7 +527,7 @@ sys_subshell (void)
const char *sh = 0;
#ifdef DOS_NT /* MW, Aug 1993 */
- getwd (oldwd);
+ getcwd (oldwd, sizeof oldwd);
if (sh == 0)
sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
#endif
@@ -603,14 +584,12 @@ sys_subshell (void)
/* Do this now if we did not do it before. */
#ifndef MSDOS
save_signal_handlers (saved_handlers);
- synch_process_alive = 1;
#endif
#ifndef DOS_NT
- wait_for_termination (pid);
+ wait_for_termination (pid, &status, 0);
#endif
restore_signal_handlers (saved_handlers);
- synch_process_alive = 0;
}
static void
@@ -618,8 +597,9 @@ save_signal_handlers (struct save_signal *saved_handlers)
{
while (saved_handlers->code)
{
- saved_handlers->handler
- = (void (*) (int)) signal (saved_handlers->code, SIG_IGN);
+ struct sigaction action;
+ emacs_sigaction_init (&action, SIG_IGN);
+ sigaction (saved_handlers->code, &action, &saved_handlers->action);
saved_handlers++;
}
}
@@ -629,118 +609,149 @@ restore_signal_handlers (struct save_signal *saved_handlers)
{
while (saved_handlers->code)
{
- signal (saved_handlers->code, saved_handlers->handler);
+ sigaction (saved_handlers->code, &saved_handlers->action, 0);
saved_handlers++;
}
}
-#ifndef SIGIO
-/* If SIGIO is broken, don't do anything. */
-void
-init_sigio (int fd)
-{
-}
-
-static void
-reset_sigio (int fd)
-{
-}
-
-void
-request_sigio (void)
-{
-}
-
-void
-unrequest_sigio (void)
-{
-}
-
-#else
-#ifdef F_SETFL
-
+#ifdef USABLE_SIGIO
static int old_fcntl_flags[MAXDESC];
+#endif
void
init_sigio (int fd)
{
-#ifdef FASYNC
+#ifdef USABLE_SIGIO
old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
-#endif
interrupts_deferred = 0;
+#endif
}
static void
reset_sigio (int fd)
{
-#ifdef FASYNC
+#ifdef USABLE_SIGIO
fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
#endif
}
-#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
-/* XXX Uhm, FASYNC is not used anymore here. */
-/* XXX Yeah, but you need it for SIGIO, don't you? */
-
void
request_sigio (void)
{
+#ifdef USABLE_SIGIO
+ sigset_t unblocked;
+
if (noninteractive)
return;
-#ifdef SIGWINCH
- sigunblock (sigmask (SIGWINCH));
-#endif
- sigunblock (sigmask (SIGIO));
+ sigemptyset (&unblocked);
+# ifdef SIGWINCH
+ sigaddset (&unblocked, SIGWINCH);
+# endif
+ sigaddset (&unblocked, SIGIO);
+ pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
interrupts_deferred = 0;
+#endif
}
void
unrequest_sigio (void)
{
+#ifdef USABLE_SIGIO
+ sigset_t blocked;
+
if (noninteractive)
return;
-#if 0 /* XXX What's wrong with blocking SIGIO under X? */
- if (x_display_list)
- return;
+ sigemptyset (&blocked);
+# ifdef SIGWINCH
+ sigaddset (&blocked, SIGWINCH);
+# endif
+ sigaddset (&blocked, SIGIO);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+ interrupts_deferred = 1;
#endif
+}
-#ifdef SIGWINCH
- sigblock (sigmask (SIGWINCH));
+void
+ignore_sigio (void)
+{
+#ifdef USABLE_SIGIO
+ signal (SIGIO, SIG_IGN);
#endif
- sigblock (sigmask (SIGIO));
- interrupts_deferred = 1;
}
-#else /* no FASYNC */
-#ifndef MSDOS
+
+/* Saving and restoring the process group of Emacs's terminal. */
-void
-request_sigio (void)
-{
- if (noninteractive || read_socket_hook)
- return;
+/* The process group of which Emacs was a member when it initially
+ started.
- croak ("request_sigio");
-}
+ If Emacs was in its own process group (i.e. inherited_pgroup ==
+ getpid ()), then we know we're running under a shell with job
+ control (Emacs would never be run as part of a pipeline).
+ Everything is fine.
+
+ If Emacs was not in its own process group, then we know we're
+ running under a shell (or a caller) that doesn't know how to
+ separate itself from Emacs (like sh). Emacs must be in its own
+ process group in order to receive SIGIO correctly. In this
+ situation, we put ourselves in our own pgroup, forcibly set the
+ tty's pgroup to our pgroup, and make sure to restore and reinstate
+ the tty's pgroup just like any other terminal setting. If
+ inherited_group was not the tty's pgroup, then we'll get a
+ SIGTTmumble when we try to change the tty's pgroup, and a CONT if
+ it goes foreground in the future, which is what should happen. */
+
+static pid_t inherited_pgroup;
void
-unrequest_sigio (void)
+init_foreground_group (void)
{
- if (noninteractive || read_socket_hook)
- return;
+ pid_t pgrp = getpgrp ();
+ inherited_pgroup = getpid () == pgrp ? 0 : pgrp;
+}
+
+/* Safely set a controlling terminal FD's process group to PGID.
+ If we are not in the foreground already, POSIX requires tcsetpgrp
+ to deliver a SIGTTOU signal, which would stop us. This is an
+ annoyance, so temporarily ignore the signal.
- croak ("unrequest_sigio");
+ In practice, platforms lacking SIGTTOU also lack tcsetpgrp, so
+ skip all this unless SIGTTOU is defined. */
+static void
+tcsetpgrp_without_stopping (int fd, pid_t pgid)
+{
+#ifdef SIGTTOU
+ signal_handler_t handler;
+ block_input ();
+ handler = signal (SIGTTOU, SIG_IGN);
+ tcsetpgrp (fd, pgid);
+ signal (SIGTTOU, handler);
+ unblock_input ();
+#endif
}
-#endif /* MSDOS */
-#endif /* FASYNC */
-#endif /* F_SETFL */
-#endif /* SIGIO */
+/* Split off the foreground process group to Emacs alone. When we are
+ in the foreground, but not started in our own process group,
+ redirect the tty device handle FD to point to our own process
+ group. FD must be the file descriptor of the controlling tty. */
+static void
+narrow_foreground_group (int fd)
+{
+ if (inherited_pgroup && setpgid (0, 0) == 0)
+ tcsetpgrp_without_stopping (fd, getpid ());
+}
+/* Set the tty to our original foreground group. */
+static void
+widen_foreground_group (int fd)
+{
+ if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0)
+ tcsetpgrp_without_stopping (fd, inherited_pgroup);
+}
/* Getting and setting emacs_tty structures. */
@@ -858,6 +869,8 @@ init_sys_modes (struct tty_display_info *tty_out)
if (!tty_out->output)
return; /* The tty is suspended. */
+ narrow_foreground_group (fileno (tty_out->input));
+
if (! tty_out->old_tty)
tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
@@ -1027,8 +1040,7 @@ init_sys_modes (struct tty_display_info *tty_out)
#endif
#endif
-#ifdef F_SETFL
-#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
+#ifdef F_GETOWN
if (interrupt_input)
{
old_fcntl_owner[fileno (tty_out->input)] =
@@ -1046,7 +1058,6 @@ init_sys_modes (struct tty_display_info *tty_out)
#endif /* HAVE_GPM */
}
#endif /* F_GETOWN */
-#endif /* F_SETFL */
#ifdef _IOFBF
/* This symbol is defined on recent USG systems.
@@ -1266,8 +1277,8 @@ reset_sys_modes (struct tty_display_info *tty_out)
fsync (fileno (tty_out->output));
#endif
-#ifdef F_SETFL
-#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
+#ifndef DOS_NT
+#ifdef F_SETOWN
if (interrupt_input)
{
reset_sigio (fileno (tty_out->input));
@@ -1275,11 +1286,9 @@ reset_sys_modes (struct tty_display_info *tty_out)
old_fcntl_owner[fileno (tty_out->input)]);
}
#endif /* F_SETOWN */
-#ifdef O_NDELAY
fcntl (fileno (tty_out->input), F_SETFL,
- fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
+ fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NONBLOCK);
#endif
-#endif /* F_SETFL */
if (tty_out->old_tty)
while (emacs_set_tty (fileno (tty_out->input),
@@ -1290,6 +1299,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
dos_ttcooked ();
#endif
+ widen_foreground_group (fileno (tty_out->input));
}
#ifdef HAVE_PTYS
@@ -1470,121 +1480,224 @@ init_system_name (void)
}
}
-/* POSIX signals support - DJB */
-/* Anyone with POSIX signals should have ANSI C declarations */
-
sigset_t empty_mask;
-#ifndef WINDOWSNT
+static struct sigaction process_fatal_action;
-signal_handler_t
-sys_signal (int signal_number, signal_handler_t action)
-{
- struct sigaction new_action, old_action;
- sigemptyset (&new_action.sa_mask);
- new_action.sa_handler = action;
- new_action.sa_flags = 0;
-#if defined (SA_RESTART)
- /* Emacs mostly works better with restartable system services. If this
- flag exists, we probably want to turn it on here.
- However, on some systems (only hpux11 at present) this resets the
- timeout of `select' which means that `select' never finishes if
- it keeps getting signals.
- We define BROKEN_SA_RESTART on those systems. */
- /* It's not clear why the comment above says "mostly works better". --Stef
- When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
+static int
+emacs_sigaction_flags (void)
+{
+#ifdef SA_RESTART
+ /* SA_RESTART causes interruptible functions with timeouts (e.g.,
+ 'select') to reset their timeout on some platforms (e.g.,
+ HP-UX 11), which is not what we want. Also, when Emacs is
+ interactive, we don't want SA_RESTART because we need to poll
for pending input so we need long-running syscalls to be interrupted
- after a signal that sets the interrupt_input_pending flag. */
- /* Non-interactive keyboard input goes through stdio, where we always
- want restartable system calls. */
-# if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
+ after a signal that sets pending_signals.
+
+ Non-interactive keyboard input goes through stdio, where we
+ always want restartable system calls. */
if (noninteractive)
-# endif
- new_action.sa_flags = SA_RESTART;
+ return SA_RESTART;
+#endif
+ return 0;
+}
+
+/* Store into *ACTION a signal action suitable for Emacs, with handler
+ HANDLER. */
+void
+emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
+{
+ sigemptyset (&action->sa_mask);
+
+ /* When handling a signal, block nonfatal system signals that are caught
+ by Emacs. This makes race conditions less likely. */
+ sigaddset (&action->sa_mask, SIGALRM);
+ sigaddset (&action->sa_mask, SIGCHLD);
+#ifdef SIGDANGER
+ sigaddset (&action->sa_mask, SIGDANGER);
+#endif
+#ifdef PROFILER_CPU_SUPPORT
+ sigaddset (&action->sa_mask, SIGPROF);
+#endif
+#ifdef SIGWINCH
+ sigaddset (&action->sa_mask, SIGWINCH);
+#endif
+ if (! noninteractive)
+ {
+ sigaddset (&action->sa_mask, SIGINT);
+ sigaddset (&action->sa_mask, SIGQUIT);
+#ifdef USABLE_SIGIO
+ sigaddset (&action->sa_mask, SIGIO);
#endif
- sigaction (signal_number, &new_action, &old_action);
- return (old_action.sa_handler);
+ }
+
+ if (! IEEE_FLOATING_POINT)
+ sigaddset (&action->sa_mask, SIGFPE);
+
+ action->sa_handler = handler;
+ action->sa_flags = emacs_sigaction_flags ();
}
-#endif /* WINDOWSNT */
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+static pthread_t main_thread;
+#endif
+
+/* SIG has arrived at the current process. Deliver it to the main
+ thread, which should handle it with HANDLER.
+
+ If we are on the main thread, handle the signal SIG with HANDLER.
+ Otherwise, redirect the signal to the main thread, blocking it from
+ this thread. POSIX says any thread can receive a signal that is
+ associated with a process, process group, or asynchronous event.
+ On GNU/Linux that is not true, but for other systems (FreeBSD at
+ least) it is. */
+void
+deliver_process_signal (int sig, signal_handler_t handler)
+{
+ /* Preserve errno, to avoid race conditions with signal handlers that
+ might change errno. Races can occur even in single-threaded hosts. */
+ int old_errno = errno;
-#ifndef __GNUC__
-/* If we're compiling with GCC, we don't need this function, since it
- can be written as a macro. */
-sigset_t
-sys_sigmask (int sig)
+ bool on_main_thread = true;
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+ if (! pthread_equal (pthread_self (), main_thread))
+ {
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, sig);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+ pthread_kill (main_thread, sig);
+ on_main_thread = false;
+ }
+#endif
+ if (on_main_thread)
+ handler (sig);
+
+ errno = old_errno;
+}
+
+/* Static location to save a fatal backtrace in a thread.
+ FIXME: If two subsidiary threads fail simultaneously, the resulting
+ backtrace may be garbage. */
+enum { BACKTRACE_LIMIT_MAX = 500 };
+static void *thread_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
+static int thread_backtrace_npointers;
+
+/* SIG has arrived at the current thread.
+ If we are on the main thread, handle the signal SIG with HANDLER.
+ Otherwise, this is a fatal error in the handling thread. */
+static void
+deliver_thread_signal (int sig, signal_handler_t handler)
{
- sigset_t mask;
- sigemptyset (&mask);
- sigaddset (&mask, sig);
- return mask;
+ int old_errno = errno;
+
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+ if (! pthread_equal (pthread_self (), main_thread))
+ {
+ thread_backtrace_npointers
+ = backtrace (thread_backtrace_buffer, BACKTRACE_LIMIT_MAX);
+ sigaction (sig, &process_fatal_action, 0);
+ pthread_kill (main_thread, sig);
+
+ /* Avoid further damage while the main thread is exiting. */
+ while (1)
+ sigsuspend (&empty_mask);
+ }
+#endif
+
+ handler (sig);
+ errno = old_errno;
}
+
+#if !HAVE_DECL_SYS_SIGLIST
+# undef sys_siglist
+# ifdef _sys_siglist
+# define sys_siglist _sys_siglist
+# else
+# define sys_siglist my_sys_siglist
+static char const *sys_siglist[NSIG];
+# endif
#endif
-/* I'd like to have these guys return pointers to the mask storage in here,
- but there'd be trouble if the code was saving multiple masks. I'll be
- safe and pass the structure. It normally won't be more than 2 bytes
- anyhow. - DJB */
+#ifdef _sys_nsig
+# define sys_siglist_entries _sys_nsig
+#else
+# define sys_siglist_entries NSIG
+#endif
-sigset_t
-sys_sigblock (sigset_t new_mask)
+/* Handle bus errors, invalid instruction, etc. */
+static void
+handle_fatal_signal (int sig)
{
- sigset_t old_mask;
- pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
- return (old_mask);
+ terminate_due_to_signal (sig, 40);
}
-sigset_t
-sys_sigunblock (sigset_t new_mask)
+static void
+deliver_fatal_signal (int sig)
{
- sigset_t old_mask;
- pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
- return (old_mask);
+ deliver_process_signal (sig, handle_fatal_signal);
}
-sigset_t
-sys_sigsetmask (sigset_t new_mask)
+static void
+deliver_fatal_thread_signal (int sig)
{
- sigset_t old_mask;
- pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
- return (old_mask);
+ deliver_thread_signal (sig, handle_fatal_signal);
}
-
-#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
-static char *my_sys_siglist[NSIG];
-# ifdef sys_siglist
-# undef sys_siglist
-# endif
-# define sys_siglist my_sys_siglist
-#endif
+static _Noreturn void
+handle_arith_signal (int sig)
+{
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+ xsignal0 (Qarith_error);
+}
+
+static void
+deliver_arith_signal (int sig)
+{
+ deliver_thread_signal (sig, handle_arith_signal);
+}
+
+/* Treat SIG as a terminating signal, unless it is already ignored and
+ we are in --batch mode. Among other things, this makes nohup work. */
+static void
+maybe_fatal_sig (int sig)
+{
+ bool catch_sig = !noninteractive;
+ if (!catch_sig)
+ {
+ struct sigaction old_action;
+ sigaction (sig, 0, &old_action);
+ catch_sig = old_action.sa_handler != SIG_IGN;
+ }
+ if (catch_sig)
+ sigaction (sig, &process_fatal_action, 0);
+}
void
-init_signals (void)
+init_signals (bool dumping)
{
+ struct sigaction thread_fatal_action;
+ struct sigaction action;
+
sigemptyset (&empty_mask);
-#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+ main_thread = pthread_self ();
+#endif
+
+#if !HAVE_DECL_SYS_SIGLIST && !defined _sys_siglist
if (! initialized)
{
-# ifdef SIGABRT
sys_siglist[SIGABRT] = "Aborted";
-# endif
# ifdef SIGAIO
sys_siglist[SIGAIO] = "LAN I/O interrupt";
# endif
-# ifdef SIGALRM
sys_siglist[SIGALRM] = "Alarm clock";
-# endif
# ifdef SIGBUS
sys_siglist[SIGBUS] = "Bus error";
# endif
-# ifdef SIGCLD
- sys_siglist[SIGCLD] = "Child status changed";
-# endif
-# ifdef SIGCHLD
sys_siglist[SIGCHLD] = "Child status changed";
-# endif
# ifdef SIGCONT
sys_siglist[SIGCONT] = "Continued";
# endif
@@ -1597,24 +1710,16 @@ init_signals (void)
# ifdef SIGEMT
sys_siglist[SIGEMT] = "Emulation trap";
# endif
-# ifdef SIGFPE
sys_siglist[SIGFPE] = "Arithmetic exception";
-# endif
# ifdef SIGFREEZE
sys_siglist[SIGFREEZE] = "SIGFREEZE";
# endif
# ifdef SIGGRANT
sys_siglist[SIGGRANT] = "Monitor mode granted";
# endif
-# ifdef SIGHUP
sys_siglist[SIGHUP] = "Hangup";
-# endif
-# ifdef SIGILL
sys_siglist[SIGILL] = "Illegal instruction";
-# endif
-# ifdef SIGINT
sys_siglist[SIGINT] = "Interrupt";
-# endif
# ifdef SIGIO
sys_siglist[SIGIO] = "I/O possible";
# endif
@@ -1624,9 +1729,7 @@ init_signals (void)
# ifdef SIGIOT
sys_siglist[SIGIOT] = "IOT trap";
# endif
-# ifdef SIGKILL
sys_siglist[SIGKILL] = "Killed";
-# endif
# ifdef SIGLOST
sys_siglist[SIGLOST] = "Resource lost";
# endif
@@ -1639,9 +1742,7 @@ init_signals (void)
# ifdef SIGPHONE
sys_siglist[SIGWIND] = "SIGPHONE";
# endif
-# ifdef SIGPIPE
sys_siglist[SIGPIPE] = "Broken pipe";
-# endif
# ifdef SIGPOLL
sys_siglist[SIGPOLL] = "Pollable event occurred";
# endif
@@ -1654,18 +1755,14 @@ init_signals (void)
# ifdef SIGPWR
sys_siglist[SIGPWR] = "Power-fail restart";
# endif
-# ifdef SIGQUIT
sys_siglist[SIGQUIT] = "Quit";
-# endif
# ifdef SIGRETRACT
sys_siglist[SIGRETRACT] = "Need to relinquish monitor mode";
# endif
# ifdef SIGSAK
sys_siglist[SIGSAK] = "Secure attention";
# endif
-# ifdef SIGSEGV
sys_siglist[SIGSEGV] = "Segmentation violation";
-# endif
# ifdef SIGSOUND
sys_siglist[SIGSOUND] = "Sound completed";
# endif
@@ -1678,9 +1775,7 @@ init_signals (void)
# ifdef SIGSYS
sys_siglist[SIGSYS] = "Bad argument to system call";
# endif
-# ifdef SIGTERM
sys_siglist[SIGTERM] = "Terminated";
-# endif
# ifdef SIGTHAW
sys_siglist[SIGTHAW] = "SIGTHAW";
# endif
@@ -1724,7 +1819,130 @@ init_signals (void)
sys_siglist[SIGXFSZ] = "File size limit exceeded";
# endif
}
-#endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
+#endif /* !HAVE_DECL_SYS_SIGLIST && !_sys_siglist */
+
+ /* Don't alter signal handlers if dumping. On some machines,
+ changing signal handlers sets static data that would make signals
+ fail to work right when the dumped Emacs is run. */
+ if (dumping)
+ return;
+
+ sigfillset (&process_fatal_action.sa_mask);
+ process_fatal_action.sa_handler = deliver_fatal_signal;
+ process_fatal_action.sa_flags = emacs_sigaction_flags ();
+
+ sigfillset (&thread_fatal_action.sa_mask);
+ thread_fatal_action.sa_handler = deliver_fatal_thread_signal;
+ thread_fatal_action.sa_flags = process_fatal_action.sa_flags;
+
+ /* SIGINT may need special treatment on MS-Windows. See
+ http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html
+ Please update the doc of kill-emacs, kill-emacs-hook, and
+ NEWS if you change this. */
+
+ maybe_fatal_sig (SIGHUP);
+ maybe_fatal_sig (SIGINT);
+ maybe_fatal_sig (SIGTERM);
+
+ /* Emacs checks for write errors, so it can safely ignore SIGPIPE.
+ However, in batch mode leave SIGPIPE alone, as that causes Emacs
+ to behave more like typical batch applications do. */
+ if (! noninteractive)
+ signal (SIGPIPE, SIG_IGN);
+
+ sigaction (SIGQUIT, &process_fatal_action, 0);
+ sigaction (SIGILL, &thread_fatal_action, 0);
+ sigaction (SIGTRAP, &thread_fatal_action, 0);
+
+ /* Typically SIGFPE is thread-specific and is fatal, like SIGILL.
+ But on a non-IEEE host SIGFPE can come from a trap in the Lisp
+ interpreter's floating point operations, so treat SIGFPE as an
+ arith-error if it arises in the main thread. */
+ if (IEEE_FLOATING_POINT)
+ sigaction (SIGFPE, &thread_fatal_action, 0);
+ else
+ {
+ emacs_sigaction_init (&action, deliver_arith_signal);
+ sigaction (SIGFPE, &action, 0);
+ }
+
+#ifdef SIGUSR1
+ add_user_signal (SIGUSR1, "sigusr1");
+#endif
+#ifdef SIGUSR2
+ add_user_signal (SIGUSR2, "sigusr2");
+#endif
+ sigaction (SIGABRT, &thread_fatal_action, 0);
+#ifdef SIGPRE
+ sigaction (SIGPRE, &thread_fatal_action, 0);
+#endif
+#ifdef SIGORE
+ sigaction (SIGORE, &thread_fatal_action, 0);
+#endif
+#ifdef SIGUME
+ sigaction (SIGUME, &thread_fatal_action, 0);
+#endif
+#ifdef SIGDLK
+ sigaction (SIGDLK, &process_fatal_action, 0);
+#endif
+#ifdef SIGCPULIM
+ sigaction (SIGCPULIM, &process_fatal_action, 0);
+#endif
+#ifdef SIGIOT
+ sigaction (SIGIOT, &thread_fatal_action, 0);
+#endif
+#ifdef SIGEMT
+ sigaction (SIGEMT, &thread_fatal_action, 0);
+#endif
+#ifdef SIGBUS
+ sigaction (SIGBUS, &thread_fatal_action, 0);
+#endif
+ sigaction (SIGSEGV, &thread_fatal_action, 0);
+#ifdef SIGSYS
+ sigaction (SIGSYS, &thread_fatal_action, 0);
+#endif
+ sigaction (SIGTERM, &process_fatal_action, 0);
+#ifdef SIGPROF
+ signal (SIGPROF, SIG_IGN);
+#endif
+#ifdef SIGVTALRM
+ sigaction (SIGVTALRM, &process_fatal_action, 0);
+#endif
+#ifdef SIGXCPU
+ sigaction (SIGXCPU, &process_fatal_action, 0);
+#endif
+#ifdef SIGXFSZ
+ sigaction (SIGXFSZ, &process_fatal_action, 0);
+#endif
+
+#ifdef SIGDANGER
+ /* This just means available memory is getting low. */
+ emacs_sigaction_init (&action, deliver_danger_signal);
+ sigaction (SIGDANGER, &action, 0);
+#endif
+
+ /* AIX-specific signals. */
+#ifdef SIGGRANT
+ sigaction (SIGGRANT, &process_fatal_action, 0);
+#endif
+#ifdef SIGMIGRATE
+ sigaction (SIGMIGRATE, &process_fatal_action, 0);
+#endif
+#ifdef SIGMSG
+ sigaction (SIGMSG, &process_fatal_action, 0);
+#endif
+#ifdef SIGRETRACT
+ sigaction (SIGRETRACT, &process_fatal_action, 0);
+#endif
+#ifdef SIGSAK
+ sigaction (SIGSAK, &process_fatal_action, 0);
+#endif
+#ifdef SIGSOUND
+ sigaction (SIGSOUND, &process_fatal_action, 0);
+#endif
+#ifdef SIGTALRM
+ sigaction (SIGTALRM, &thread_fatal_action, 0);
+#endif
}
#ifndef HAVE_RANDOM
@@ -1856,6 +2074,46 @@ snprintf (char *buf, size_t bufsize, char const *format, ...)
}
#endif
+/* If a backtrace is available, output the top lines of it to stderr.
+ Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines.
+ This function may be called from a signal handler, so it should
+ not invoke async-unsafe functions like malloc. */
+void
+emacs_backtrace (int backtrace_limit)
+{
+ void *main_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
+ int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX);
+ void *buffer;
+ int npointers;
+
+ if (thread_backtrace_npointers)
+ {
+ buffer = thread_backtrace_buffer;
+ npointers = thread_backtrace_npointers;
+ }
+ else
+ {
+ buffer = main_backtrace_buffer;
+ npointers = backtrace (buffer, bounded_limit + 1);
+ }
+
+ if (npointers)
+ {
+ ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12));
+ backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
+ if (bounded_limit < npointers)
+ ignore_value (write (STDERR_FILENO, "...\n", 4));
+ }
+}
+
+#ifndef HAVE_NTGUI
+void
+emacs_abort (void)
+{
+ terminate_due_to_signal (SIGABRT, 10);
+}
+#endif
+
int
emacs_open (const char *path, int oflag, int mode)
{
@@ -1933,11 +2191,10 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
{
if (errno == EINTR)
{
-#ifdef SYNC_INPUT
/* I originally used `QUIT' but that might causes files to
be truncated if you hit C-g in the middle of it. --Stef */
- process_pending_signals ();
-#endif
+ if (pending_signals)
+ process_pending_signals ();
continue;
}
else
@@ -1968,95 +2225,6 @@ emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
&emacs_norealloc_allocator, careadlinkatcwd);
}
-#ifdef USG
-/*
- * All of the following are for USG.
- *
- * On USG systems the system calls are INTERRUPTIBLE by signals
- * that the user program has elected to catch. Thus the system call
- * must be retried in these cases. To handle this without massive
- * changes in the source code, we remap the standard system call names
- * to names for our own functions in sysdep.c that do the system call
- * with retries. Actually, for portability reasons, it is good
- * programming practice, as this example shows, to limit all actual
- * system calls to a single occurrence in the source. Sure, this
- * adds an extra level of function call overhead but it is almost
- * always negligible. Fred Fish, Unisoft Systems Inc.
- */
-
-/*
- * Warning, this function may not duplicate 4.2 action properly
- * under error conditions.
- */
-
-#if !defined (HAVE_GETWD) || defined (BROKEN_GETWD)
-
-#ifndef MAXPATHLEN
-/* In 4.1, param.h fails to define this. */
-#define MAXPATHLEN 1024
-#endif
-
-char *
-getwd (char *pathname)
-{
- char *npath, *spath;
- extern char *getcwd (char *, size_t);
-
- BLOCK_INPUT; /* getcwd uses malloc */
- spath = npath = getcwd ((char *) 0, MAXPATHLEN);
- if (spath == 0)
- {
- UNBLOCK_INPUT;
- return spath;
- }
- /* On Altos 3068, getcwd can return @hostname/dir, so discard
- up to first slash. Should be harmless on other systems. */
- while (*npath && *npath != '/')
- npath++;
- strcpy (pathname, npath);
- free (spath); /* getcwd uses malloc */
- UNBLOCK_INPUT;
- return pathname;
-}
-
-#endif /* !defined (HAVE_GETWD) || defined (BROKEN_GETWD) */
-
-/*
- * This function will go away as soon as all the stubs fixed. (fnf)
- */
-
-void
-croak (char *badfunc)
-{
- printf ("%s not yet implemented\r\n", badfunc);
- reset_all_sys_modes ();
- exit (1);
-}
-
-#endif /* USG */
-
-/* Directory routines for systems that don't have them. */
-
-#ifdef HAVE_DIRENT_H
-
-#include <dirent.h>
-
-#if !defined (HAVE_CLOSEDIR)
-
-int
-closedir (DIR *dirp /* stream from opendir */)
-{
- int rtnval;
-
- rtnval = emacs_close (dirp->dd_fd);
- xfree (dirp);
-
- return rtnval;
-}
-#endif /* not HAVE_CLOSEDIR */
-#endif /* HAVE_DIRENT_H */
-
-
/* Return a struct timeval that is roughly equivalent to T.
Use the least timeval not less than T.
Return an extremal value if the result would overflow. */
@@ -2096,40 +2264,27 @@ set_file_times (int fd, const char *filename,
return fdutimens (fd, filename, timespec);
}
-#ifndef HAVE_STRSIGNAL
-char *
-strsignal (int code)
+/* Like strsignal, except async-signal-safe, and this function typically
+ returns a string in the C locale rather than the current locale. */
+char const *
+safe_strsignal (int code)
{
- char *signame = 0;
+ char const *signame = 0;
- if (0 <= code && code < NSIG)
- {
- /* Cast to suppress warning if the table has const char *. */
- signame = (char *) sys_siglist[code];
- }
+ if (0 <= code && code < sys_siglist_entries)
+ signame = sys_siglist[code];
+ if (! signame)
+ signame = "Unknown signal";
return signame;
}
-#endif /* HAVE_STRSIGNAL */
#ifndef DOS_NT
/* For make-serial-process */
int
serial_open (char *port)
{
- int fd = -1;
-
- fd = emacs_open ((char*) port,
- O_RDWR
-#ifdef O_NONBLOCK
- | O_NONBLOCK
-#else
- | O_NDELAY
-#endif
-#ifdef O_NOCTTY
- | O_NOCTTY
-#endif
- , 0);
+ int fd = emacs_open (port, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
if (fd < 0)
{
error ("Could not open %s: %s",
@@ -2462,7 +2617,7 @@ get_up_time (void)
FILE *fup;
EMACS_TIME up = make_emacs_time (0, 0);
- BLOCK_INPUT;
+ block_input ();
fup = fopen ("/proc/uptime", "r");
if (fup)
@@ -2493,7 +2648,7 @@ get_up_time (void)
}
fclose (fup);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return up;
}
@@ -2507,7 +2662,7 @@ procfs_ttyname (int rdev)
FILE *fdev = NULL;
char name[PATH_MAX];
- BLOCK_INPUT;
+ block_input ();
fdev = fopen ("/proc/tty/drivers", "r");
if (fdev)
@@ -2539,7 +2694,7 @@ procfs_ttyname (int rdev)
}
fclose (fdev);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return build_string (name);
}
@@ -2549,7 +2704,7 @@ procfs_get_total_memory (void)
FILE *fmem = NULL;
unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
- BLOCK_INPUT;
+ block_input ();
fmem = fopen ("/proc/meminfo", "r");
if (fmem)
@@ -2568,7 +2723,7 @@ procfs_get_total_memory (void)
}
fclose (fmem);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return retval;
}
@@ -2614,17 +2769,17 @@ system_process_attributes (Lisp_Object pid)
/* euid egid */
uid = st.st_uid;
attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
- BLOCK_INPUT;
+ block_input ();
pw = getpwuid (uid);
- UNBLOCK_INPUT;
+ unblock_input ();
if (pw)
attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
gid = st.st_gid;
attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
- BLOCK_INPUT;
+ block_input ();
gr = getgrgid (gid);
- UNBLOCK_INPUT;
+ unblock_input ();
if (gr)
attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
@@ -2852,17 +3007,17 @@ system_process_attributes (Lisp_Object pid)
/* euid egid */
uid = st.st_uid;
attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
- BLOCK_INPUT;
+ block_input ();
pw = getpwuid (uid);
- UNBLOCK_INPUT;
+ unblock_input ();
if (pw)
attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
gid = st.st_gid;
attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
- BLOCK_INPUT;
+ block_input ();
gr = getgrgid (gid);
- UNBLOCK_INPUT;
+ unblock_input ();
if (gr)
attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
@@ -2983,17 +3138,17 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
- BLOCK_INPUT;
+ block_input ();
pw = getpwuid (proc.ki_uid);
- UNBLOCK_INPUT;
+ unblock_input ();
if (pw)
attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (proc.ki_svgid)), attrs);
- BLOCK_INPUT;
+ block_input ();
gr = getgrgid (proc.ki_svgid);
- UNBLOCK_INPUT;
+ unblock_input ();
if (gr)
attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
@@ -3033,9 +3188,9 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (proc.ki_pgid)), attrs);
attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (proc.ki_sid)), attrs);
- BLOCK_INPUT;
+ block_input ();
ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
- UNBLOCK_INPUT;
+ unblock_input ();
if (ttyname)
attrs = Fcons (Fcons (Qtty, build_string (ttyname)), attrs);
diff --git a/src/syssignal.h b/src/syssignal.h
index 71151ed4c6a..8f9b5f0546a 100644
--- a/src/syssignal.h
+++ b/src/syssignal.h
@@ -17,7 +17,10 @@ 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/>. */
-extern void init_signals (void);
+#include <signal.h>
+#include <stdbool.h>
+
+extern void init_signals (bool);
#ifdef HAVE_PTHREAD
#include <pthread.h>
@@ -26,131 +29,33 @@ extern void init_signals (void);
#define FORWARD_SIGNAL_TO_MAIN_THREAD
#endif
-/* Don't #include <signal.h>. That header should always be #included
- before "config.h", because some configuration files (like s/hpux.h)
- indicate that SIGIO doesn't work by #undef-ing SIGIO. If this file
- #includes <signal.h>, then that will re-#define SIGIO and confuse
- things. */
-/* XXX This is not correct anymore, there is a BROKEN_SIGIO macro. */
-
-#define SIGMASKTYPE sigset_t
-
-#define SIGEMPTYMASK (empty_mask)
-extern sigset_t empty_mask;
-
-/* POSIX pretty much destroys any possibility of writing sigmask as a
- macro in standard C. We always define our own version because the
- predefined macro in Glibc 2.1 is only provided for compatibility for old
- programs that use int as signal mask type. */
-#undef sigmask
-#ifdef __GNUC__
-#define sigmask(SIG) \
- ({ \
- sigset_t _mask; \
- sigemptyset (&_mask); \
- sigaddset (&_mask, SIG); \
- _mask; \
- })
-#else /* ! defined (__GNUC__) */
-extern sigset_t sys_sigmask ();
-#define sigmask(SIG) (sys_sigmask (SIG))
-#endif /* ! defined (__GNUC__) */
-
-#undef sigpause
-#define sigpause(MASK) sigsuspend (&(MASK))
-
-#define sigblock(SIG) sys_sigblock (SIG)
-#define sigunblock(SIG) sys_sigunblock (SIG)
-#ifndef sigsetmask
-#define sigsetmask(SIG) sys_sigsetmask (SIG)
+#if defined HAVE_TIMER_SETTIME && defined SIGEV_SIGNAL
+# define HAVE_ITIMERSPEC
#endif
-#undef signal
-#define signal(SIG,ACT) sys_signal(SIG,ACT)
-
-/* Whether this is what all systems want or not, this is what
- appears to be assumed in the source, for example data.c:arith_error. */
-typedef void (*signal_handler_t) (int);
-signal_handler_t sys_signal (int signal_number, signal_handler_t action);
-sigset_t sys_sigblock (sigset_t new_mask);
-sigset_t sys_sigunblock (sigset_t new_mask);
-sigset_t sys_sigsetmask (sigset_t new_mask);
-#if ! (defined TIOCNOTTY || defined USG5 || defined CYGWIN)
-_Noreturn void croak (char *);
+#if (defined SIGPROF && !defined PROFILING \
+ && (defined HAVE_SETITIMER || defined HAVE_ITIMERSPEC))
+# define PROFILER_CPU_SUPPORT
#endif
-#define sys_sigdel(MASK,SIG) sigdelset (&MASK,SIG)
-
-#define sigfree() sigsetmask (SIGEMPTYMASK)
+extern sigset_t empty_mask;
-#if defined (SIGIO) && defined (BROKEN_SIGIO)
-# undef SIGIO
-#endif
-/* These are only used by AIX */
-#if defined (SIGPOLL) && defined (BROKEN_SIGPOLL)
-#undef SIGPOLL
-#endif
-#if defined (SIGAIO) && defined (BROKEN_SIGAIO)
-#undef SIGAIO
-#endif
-#if defined (SIGPTY) && defined (BROKEN_SIGPTY)
-#undef SIGPTY
-#endif
+typedef void (*signal_handler_t) (int);
+extern void emacs_sigaction_init (struct sigaction *, signal_handler_t);
+char const *safe_strsignal (int) ATTRIBUTE_CONST;
-/* FIXME? Emacs only defines NSIG_MINIMUM on some platforms? */
#if NSIG < NSIG_MINIMUM
-# ifdef NSIG
-# undef NSIG
-# endif
+# undef NSIG
# define NSIG NSIG_MINIMUM
#endif
-/* On bsd, [man says] kill does not accept a negative number to kill a pgrp.
- Must do that using the killpg call. */
-#ifdef BSD_SYSTEM
-#define EMACS_KILLPG(gid, signo) (killpg ( (gid), (signo)))
-#else
-#ifdef WINDOWSNT
-#define EMACS_KILLPG(gid, signo) (kill (gid, signo))
-#else
-#define EMACS_KILLPG(gid, signo) (kill (-(gid), (signo)))
+#ifndef emacs_raise
+# define emacs_raise(sig) raise (sig)
#endif
-#endif
-
-/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
- testing SIGCHLD. */
-#ifdef SIGCLD
-#ifndef SIGCHLD
-#define SIGCHLD SIGCLD
-#endif /* SIGCHLD */
-#endif /* ! defined (SIGCLD) */
#ifndef HAVE_STRSIGNAL
-/* strsignal is in sysdep.c */
-char *strsignal (int);
+# define strsignal(sig) safe_strsignal (sig)
#endif
-#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
-extern pthread_t main_thread;
-#define SIGNAL_THREAD_CHECK(signo) \
- do { \
- if (!pthread_equal (pthread_self (), main_thread)) \
- { \
- /* POSIX says any thread can receive the signal. On GNU/Linux \
- that is not true, but for other systems (FreeBSD at least) \
- it is. So direct the signal to the correct thread and block \
- it from this thread. */ \
- sigset_t new_mask; \
- \
- sigemptyset (&new_mask); \
- sigaddset (&new_mask, signo); \
- pthread_sigmask (SIG_BLOCK, &new_mask, 0); \
- pthread_kill (main_thread, signo); \
- return; \
- } \
- } while (0)
-
-#else /* not FORWARD_SIGNAL_TO_MAIN_THREAD */
-#define SIGNAL_THREAD_CHECK(signo)
-#endif /* not FORWARD_SIGNAL_TO_MAIN_THREAD */
+void deliver_process_signal (int, signal_handler_t);
diff --git a/src/systty.h b/src/systty.h
index ae98f123f2a..80bcaedf740 100644
--- a/src/systty.h
+++ b/src/systty.h
@@ -17,10 +17,8 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Include the proper files. */
+
#ifndef DOS_NT
-#ifndef NO_TERMIO
-#include <termio.h>
-#endif /* not NO_TERMIO */
#include <termios.h>
#include <fcntl.h>
#endif /* not DOS_NT */
@@ -39,20 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
-/* Special cases - inhibiting the use of certain features. */
-
-/* Allow configure to inhibit use of FIONREAD. */
-#ifdef BROKEN_FIONREAD
-#undef FIONREAD
-#undef ASYNC
-#endif
-
-/* Interrupt input is not used if there is no FIONREAD. */
-#ifndef FIONREAD
-#undef SIGIO
-#endif
-
-
/* Try to establish the correct character to disable terminal functions
in a system-independent manner. Note that USG (at least) define
_POSIX_VDISABLE as 0! */
@@ -68,27 +52,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif /* not CDEL */
#endif /* not _POSIX_VDISABLE */
-/* Get the number of characters queued for output. */
-
-/* EMACS_OUTQSIZE(FD, int *SIZE) stores the number of characters
- queued for output to the terminal FD in *SIZE, if FD is a tty.
- Returns -1 if there was an error (i.e. FD is not a tty), 0
- otherwise. */
-#ifdef TIOCOUTQ
-#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TIOCOUTQ, (size)))
-#endif
-
-
-/* Manipulate a terminal's current process group. */
-
-/* EMACS_GETPGRP (arg) returns the process group of the process. */
-
-#if defined (GETPGRP_VOID)
-# define EMACS_GETPGRP(x) getpgrp()
-#else /* !GETPGRP_VOID */
-# define EMACS_GETPGRP(x) getpgrp(x)
-#endif /* !GETPGRP_VOID */
-
/* Manipulate a TTY's input/output processing parameters. */
/* struct emacs_tty is a structure used to hold the current tty
diff --git a/src/syswait.h b/src/syswait.h
index 9d84876d4be..360407d558e 100644
--- a/src/syswait.h
+++ b/src/syswait.h
@@ -23,6 +23,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef EMACS_SYSWAIT_H
#define EMACS_SYSWAIT_H
+#include <stdbool.h>
#include <sys/types.h>
#ifdef HAVE_SYS_WAIT_H /* We have sys/wait.h with POSIXoid definitions. */
@@ -51,4 +52,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define WTERMSIG(status) ((status) & 0x7f)
#endif
+/* Defined in process.c. */
+extern void record_deleted_pid (pid_t);
+
+/* Defined in sysdep.c. */
+extern void wait_for_termination (pid_t, int *, bool);
+extern pid_t child_status_changed (pid_t, int *, int);
+
#endif /* EMACS_SYSWAIT_H */
diff --git a/src/term.c b/src/term.c
index f1a09b39cf9..241875de52f 100644
--- a/src/term.c
+++ b/src/term.c
@@ -20,17 +20,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
#include <config.h>
-#include <stdio.h>
#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
#include <sys/file.h>
#include <sys/time.h>
#include <unistd.h>
-#include <signal.h>
-#include <setjmp.h>
#include "lisp.h"
#include "termchar.h"
-#include "termopts.h"
#include "tparam.h"
#include "character.h"
#include "buffer.h"
@@ -58,17 +56,10 @@ static int been_here = -1;
#include "xterm.h"
#endif
-#ifndef O_RDWR
-#define O_RDWR 2
-#endif
-
-#ifndef O_NOCTTY
-#define O_NOCTTY 0
-#endif
-
/* The name of the default console device. */
#ifdef WINDOWSNT
#define DEV_TTY "CONOUT$"
+#include "w32term.h"
#else
#define DEV_TTY "/dev/tty"
#endif
@@ -135,10 +126,6 @@ enum no_color_bit
static int max_frame_cols;
-/* Non-zero if we have dropped our controlling tty and therefore
- should not open a frame on stdout. */
-static int no_controlling_tty;
-
#ifdef HAVE_GPM
@@ -755,13 +742,13 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
conversion_buffer = encode_terminal_code (string, n, coding);
if (coding->produced > 0)
{
- BLOCK_INPUT;
+ block_input ();
fwrite (conversion_buffer, 1, coding->produced, tty->output);
if (ferror (tty->output))
clearerr (tty->output);
if (tty->termscript)
fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
- UNBLOCK_INPUT;
+ unblock_input ();
}
string += n;
@@ -816,13 +803,13 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
conversion_buffer = encode_terminal_code (string, len, coding);
if (coding->produced > 0)
{
- BLOCK_INPUT;
+ block_input ();
fwrite (conversion_buffer, 1, coding->produced, tty->output);
if (ferror (tty->output))
clearerr (tty->output);
if (tty->termscript)
fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Turn appearance modes off. */
@@ -902,13 +889,13 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
if (coding->produced > 0)
{
- BLOCK_INPUT;
+ block_input ();
fwrite (conversion_buffer, 1, coding->produced, tty->output);
if (ferror (tty->output))
clearerr (tty->output);
if (tty->termscript)
fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
- UNBLOCK_INPUT;
+ unblock_input ();
}
OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
@@ -1498,7 +1485,7 @@ append_glyph (struct it *it)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
@@ -1695,7 +1682,7 @@ append_composite_glyph (struct it *it)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
@@ -1780,7 +1767,7 @@ append_glyphless_glyph (struct it *it, int face_id, const char *str)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
@@ -2250,7 +2237,7 @@ get_named_tty (const char *name)
struct terminal *t;
if (!name)
- abort ();
+ emacs_abort ();
for (t = terminal_list; t; t = t->next_terminal)
{
@@ -2798,7 +2785,7 @@ create_tty_output (struct frame *f)
struct tty_output *t = xzalloc (sizeof *t);
if (! FRAME_TERMCAP_P (f))
- abort ();
+ emacs_abort ();
t->display_info = FRAME_TERMINAL (f)->display_info.tty;
@@ -2811,7 +2798,7 @@ static void
tty_free_frame_resources (struct frame *f)
{
if (! FRAME_TERMCAP_P (f))
- abort ();
+ emacs_abort ();
if (FRAME_FACE_CACHE (f))
free_frame_faces (f);
@@ -2827,7 +2814,7 @@ static void
tty_free_frame_resources (struct frame *f)
{
if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
- abort ();
+ emacs_abort ();
if (FRAME_FACE_CACHE (f))
free_frame_faces (f);
@@ -2920,34 +2907,9 @@ set_tty_hooks (struct terminal *terminal)
static void
dissociate_if_controlling_tty (int fd)
{
-#ifndef DOS_NT
- int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
- if (pgid != -1)
- {
-#if defined (USG5)
- setpgrp ();
- no_controlling_tty = 1;
-#elif defined (CYGWIN)
- setsid ();
- no_controlling_tty = 1;
-#else
-#ifdef TIOCNOTTY /* Try BSD ioctls. */
- sigblock (sigmask (SIGTTOU));
- fd = emacs_open (DEV_TTY, O_RDWR, 0);
- if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
- {
- no_controlling_tty = 1;
- }
- if (fd != -1)
- emacs_close (fd);
- sigunblock (sigmask (SIGTTOU));
-#else
- /* Unknown system. */
- croak ();
-#endif /* ! TIOCNOTTY */
-#endif /* ! USG */
- }
-#endif /* !DOS_NT */
+ pid_t pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
+ if (0 <= pgid)
+ setsid ();
}
/* Create a termcap display on the tty device with the given name and
@@ -3020,22 +2982,18 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
set_tty_hooks (terminal);
{
- int fd;
+ /* Open the terminal device. */
FILE *file;
-#ifdef O_IGNORE_CTTY
- if (!ctty)
- /* Open the terminal device. Don't recognize it as our
- controlling terminal, and don't make it the controlling tty
- if we don't have one at the moment. */
- fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
- else
-#endif /* O_IGNORE_CTTY */
- /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
- defined on Hurd. On other systems, we need to explicitly
- dissociate ourselves from the controlling tty when we want to
- open a frame on the same terminal. */
- fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
+ /* If !ctty, don't recognize it as our controlling terminal, and
+ don't make it the controlling tty if we don't have one now.
+
+ Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
+ defined on Hurd. On other systems, we need to explicitly
+ dissociate ourselves from the controlling tty when we want to
+ 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->name = xstrdup (name);
terminal->name = xstrdup (name);
@@ -3054,10 +3012,8 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
name);
}
-#ifndef O_IGNORE_CTTY
- if (!ctty)
+ if (!O_IGNORE_CTTY && !ctty)
dissociate_if_controlling_tty (fd);
-#endif
file = fdopen (fd, "w+");
tty->input = file;
@@ -3074,9 +3030,14 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
/* On some systems, tgetent tries to access the controlling
terminal. */
- sigblock (sigmask (SIGTTOU));
- status = tgetent (tty->termcap_term_buffer, terminal_type);
- sigunblock (sigmask (SIGTTOU));
+ {
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGTTOU);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+ status = tgetent (tty->termcap_term_buffer, terminal_type);
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
+ }
if (status < 0)
{
@@ -3108,7 +3069,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
#ifndef TERMINFO
if (strlen (tty->termcap_term_buffer) >= buffer_size)
- abort ();
+ emacs_abort ();
buffer_size = strlen (tty->termcap_term_buffer);
#endif
tty->termcap_strings_buffer = area = xmalloc (buffer_size);
@@ -3230,7 +3191,6 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
FrameCols (tty) = FRAME_COLS (f);
tty->specified_window = FRAME_LINES (f);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
terminal->char_ins_del_ok = 1;
baud_rate = 19200;
@@ -3402,10 +3362,6 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
= tty->TS_delete_mode && tty->TS_insert_mode
&& !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
- tty->se_is_so = (tty->TS_standout_mode
- && tty->TS_end_standout_mode
- && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
-
UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
terminal->scroll_region_ok
@@ -3467,7 +3423,7 @@ maybe_fatal (int must_succeed, struct terminal *terminal,
verror (str1, ap);
va_end (ap);
- abort ();
+ emacs_abort ();
}
void
@@ -3494,7 +3450,7 @@ delete_tty (struct terminal *terminal)
return;
if (terminal->type != output_termcap)
- abort ();
+ emacs_abort ();
tty = terminal->display_info.tty;
@@ -3508,7 +3464,7 @@ delete_tty (struct terminal *terminal)
if (! p)
/* This should not happen. */
- abort ();
+ emacs_abort ();
p->next = tty->next;
tty->next = 0;
diff --git a/src/termcap.c b/src/termcap.c
index d1b05e8df94..e494cd113d9 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -19,7 +19,6 @@ Boston, MA 02110-1301, USA. */
/* Emacs config.h may rename various library functions such as malloc. */
#include <config.h>
-#include <setjmp.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
diff --git a/src/termchar.h b/src/termchar.h
index 102fe45350e..8bffd3e546b 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -50,8 +50,7 @@ struct tty_display_info
struct emacs_tty *old_tty; /* The initial tty mode bits */
- int term_initted; /* 1 if we have been through init_sys_modes. */
-
+ unsigned term_initted : 1; /* 1 if we have been through init_sys_modes. */
int reference_count; /* Number of frames that are on this display. */
@@ -164,17 +163,12 @@ struct tty_display_info
int RPov; /* # chars to start a TS_repeat */
- int delete_in_insert_mode; /* delete mode == insert mode */
-
- int se_is_so; /* 1 if same string both enters and leaves
- standout mode */
-
- int costs_set; /* Nonzero if costs have been calculated. */
-
- int insert_mode; /* Nonzero when in insert mode. */
- int standout_mode; /* Nonzero when in standout mode. */
+ unsigned delete_in_insert_mode : 1; /* delete mode == insert mode */
+ unsigned costs_set : 1; /* Nonzero if costs have been calculated. */
+ unsigned insert_mode : 1; /* Nonzero when in insert mode. */
+ unsigned standout_mode : 1; /* Nonzero when in standout mode. */
/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should
keep 0200 bit in input chars. 0 to ignore the 0200 bit. */
@@ -192,11 +186,11 @@ struct tty_display_info
/* Flag used in tty_show/hide_cursor. */
- int cursor_hidden;
+ unsigned cursor_hidden : 1;
/* Nonzero means use ^S/^Q for flow control. */
- int flow_control;
+ unsigned flow_control : 1;
};
/* A chain of structures for all tty devices currently in use. */
@@ -207,6 +201,6 @@ extern struct tty_display_info *tty_list;
(((f)->output_method == output_termcap \
|| (f)->output_method == output_msdos_raw) \
? (f)->terminal->display_info.tty \
- : (abort (), (struct tty_display_info *) 0))
+ : (emacs_abort (), (struct tty_display_info *) 0))
#define CURTTY() FRAME_TTY (SELECTED_FRAME())
diff --git a/src/termhooks.h b/src/termhooks.h
index 46962a1217d..1a261bacdc5 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -107,9 +107,9 @@ enum event_kind
HORIZ_WHEEL_EVENT, /* A wheel event generated by a second
horizontal wheel that is present on some
mice. See WHEEL_EVENT. */
-#if defined (WINDOWSNT)
+#ifdef HAVE_NTGUI
LANGUAGE_CHANGE_EVENT, /* A LANGUAGE_CHANGE_EVENT is
- generated on WINDOWSNT or Mac OS
+ generated when HAVE_NTGUI or on Mac OS
when the keyboard layout or input
language is changed by the
user. */
@@ -188,7 +188,7 @@ enum event_kind
, CONFIG_CHANGED_EVENT
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
/* Generated when an APPCOMMAND event is received, in response to
Multimedia or Internet buttons on some keyboards.
Such keys are available as normal function keys on X through the
@@ -211,6 +211,11 @@ enum event_kind
, NS_NONKEY_EVENT
#endif
+#if defined (HAVE_INOTIFY) || defined (HAVE_NTGUI)
+ /* File or directory was changed. */
+ , FILE_NOTIFY_EVENT
+#endif
+
};
/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT
@@ -242,16 +247,8 @@ struct input_event
Lisp_Object x, y;
Time timestamp;
- /* This is padding just to put the frame_or_window field
- past the size of struct selection_input_event. */
- int *padding[2];
-
- /* This field is copied into a vector while the event is in the queue,
- so that garbage collections won't kill it. */
- /* In a menu_bar_event, this is a cons cell whose car is the frame
- and whose cdr is the Lisp object that is the event's value. */
- /* This field is last so that struct selection_input_event
- does not overlap with it. */
+ /* 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
@@ -422,14 +419,6 @@ struct terminal
int memory_below_frame; /* Terminal remembers lines scrolled
off bottom */
-#if 0 /* These are not used anywhere. */
- /* EMACS_INT baud_rate; */ /* Output speed in baud */
- int min_padding_speed; /* Speed below which no padding necessary. */
- int dont_calculate_costs; /* Nonzero means don't bother computing
- various cost tables; we won't use them. */
-#endif
-
-
/* Window-based redisplay interface for this device (0 for tty
devices). */
struct redisplay_interface *rif;
@@ -477,10 +466,7 @@ struct terminal
Otherwise, set *bar_window to Qnil, and *x and *y to the column and
row of the character cell the mouse is over.
- Set *time to the time the mouse was at the returned position.
-
- This should clear mouse_moved until the next motion
- event arrives. */
+ Set *time to the time the mouse was at the returned position. */
void (*mouse_position_hook) (struct frame **f, int,
Lisp_Object *bar_window,
enum scroll_bar_part *part,
@@ -488,11 +474,6 @@ struct terminal
Lisp_Object *y,
Time *);
- /* The window system handling code should set this if the mouse has
- moved since the last call to the mouse_position_hook. Calling that
- hook should clear this. */
- int mouse_moved;
-
/* When a frame's focus redirection is changed, this hook tells the
window system code to re-decide where to put the highlight. Under
X, this means that Emacs lies about where the focus is. */
@@ -591,24 +572,14 @@ struct terminal
/* Called to read input events.
TERMINAL indicates which terminal device to read from. Input
- events should be read into BUF, the size of which is given in
- SIZE. EXPECTED is non-zero if the caller suspects that new input
- is available.
+ events should be read into HOLD_QUIT.
A positive return value indicates that that many input events
- where read into BUF.
+ were read into BUF.
Zero means no events were immediately available.
A value of -1 means a transient read error, while -2 indicates
- that the device was closed (hangup), and it should be deleted.
-
- XXX Please note that a non-zero value of EXPECTED only means that
- there is available input on at least one of the currently opened
- terminal devices -- but not necessarily on this device.
- Therefore, in most cases EXPECTED should be simply ignored.
-
- XXX This documentation needs to be updated. */
+ that the device was closed (hangup), and it should be deleted. */
int (*read_socket_hook) (struct terminal *terminal,
- int expected,
struct input_event *hold_quit);
/* Called when a frame's display becomes entirely up to date. */
diff --git a/src/terminal.c b/src/terminal.c
index d94164a4e40..854ca61f19c 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define TERMHOOKS_INLINE EXTERN_INLINE
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "frame.h"
@@ -43,7 +42,7 @@ struct terminal *initial_terminal;
static void delete_initial_terminal (struct terminal *);
/* This setter is used only in this file, so it can be private. */
-static inline void
+static void
tset_param_alist (struct terminal *t, Lisp_Object val)
{
t->param_alist = val;
@@ -294,7 +293,7 @@ delete_terminal (struct terminal *terminal)
for (tp = &terminal_list; *tp != terminal; tp = &(*tp)->next_terminal)
if (! *tp)
- abort ();
+ emacs_abort ();
*tp = terminal->next_terminal;
xfree (terminal->keyboard_coding);
@@ -361,14 +360,7 @@ If FRAME is nil, the selected frame is used.
The terminal device is represented by its integer identifier. */)
(Lisp_Object frame)
{
- struct terminal *t;
-
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_LIVE_FRAME (frame);
-
- t = FRAME_TERMINAL (XFRAME (frame));
+ struct terminal *t = FRAME_TERMINAL (decode_live_frame (frame));
if (!t)
return Qnil;
@@ -411,7 +403,7 @@ possible return values. */)
case output_ns:
return Qns;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -519,7 +511,7 @@ struct terminal *
init_initial_terminal (void)
{
if (initialized || terminal_list || tty_list)
- abort ();
+ emacs_abort ();
initial_terminal = create_terminal ();
initial_terminal->type = output_initial;
@@ -538,7 +530,7 @@ static void
delete_initial_terminal (struct terminal *terminal)
{
if (terminal != initial_terminal)
- abort ();
+ emacs_abort ();
delete_terminal (terminal);
initial_terminal = NULL;
diff --git a/src/terminfo.c b/src/terminfo.c
index dce7af77bcf..124c452a4a9 100644
--- a/src/terminfo.c
+++ b/src/terminfo.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "tparam.h"
-#include <setjmp.h>
#include "lisp.h"
/* Define these variables that serve as global parameters to termcap,
@@ -46,7 +45,7 @@ tparam (const char *string, char *outstring, int len,
/* Emacs always should pass a null OUTSTRING and zero LEN. */
if (outstring || len)
- abort ();
+ emacs_abort ();
temp = tparm (string, arg1, arg2, arg3, arg4);
return xstrdup (temp);
diff --git a/src/termopts.h b/src/termopts.h
index 7bf71aeefe7..05fa0a52eee 100644
--- a/src/termopts.h
+++ b/src/termopts.h
@@ -17,15 +17,8 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-/* Nonzero means use ^S/^Q as cretinous flow control. */
-extern int flow_control;
-
/* Nonzero means use interrupt-driven input. */
-extern int interrupt_input;
+extern bool interrupt_input;
/* Nonzero while interrupts are temporarily deferred during redisplay. */
-extern int interrupts_deferred;
-
-/* Terminal has meta key */
-extern int meta_key;
-
+extern bool interrupts_deferred;
diff --git a/src/textprop.c b/src/textprop.c
index b6895fc426a..1ce44ad60ac 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "intervals.h"
#include "character.h"
@@ -85,8 +85,18 @@ text_read_only (Lisp_Object propval)
xsignal0 (Qtext_read_only);
}
+/* Prepare to modify the region of BUFFER from START to END. */
+
+static void
+modify_region (Lisp_Object buffer, Lisp_Object start, Lisp_Object end)
+{
+ struct buffer *buf = XBUFFER (buffer), *old = current_buffer;
+
+ set_buffer_internal (buf);
+ modify_region_1 (XINT (start), XINT (end), true);
+ set_buffer_internal (old);
+}
-
/* Extract the interval at the position pointed to by BEGIN from
OBJECT, a string or buffer. Additionally, check that the positions
pointed to by BEGIN and END are within the bounds of OBJECT, and
@@ -241,7 +251,7 @@ interval_has_all_properties (Lisp_Object plist, INTERVAL i)
/* Return nonzero if the plist of interval I has any of the
properties of PLIST, regardless of their values. */
-static inline int
+static int
interval_has_some_properties (Lisp_Object plist, INTERVAL i)
{
register Lisp_Object tail1, tail2, sym;
@@ -263,7 +273,7 @@ interval_has_some_properties (Lisp_Object plist, INTERVAL i)
/* Return nonzero if the plist of interval I has any of the
property names in LIST, regardless of their values. */
-static inline int
+static int
interval_has_some_properties_list (Lisp_Object list, INTERVAL i)
{
register Lisp_Object tail1, tail2, sym;
@@ -556,7 +566,8 @@ If POSITION is at the end of OBJECT, the value is nil. */)
DEFUN ("get-text-property", Fget_text_property, Sget_text_property, 2, 3, 0,
doc: /* Return the value of POSITION's property PROP, in OBJECT.
-OBJECT is optional and defaults to the current buffer.
+OBJECT should be a buffer or a string; if omitted or nil, it defaults
+to the current buffer.
If POSITION is at the end of OBJECT, the value is nil. */)
(Lisp_Object position, Lisp_Object prop, Lisp_Object object)
{
@@ -1163,7 +1174,7 @@ Return t if any property value actually changed, nil otherwise. */)
}
if (BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ modify_region (object, start, end);
/* We are at the beginning of interval I, with LEN chars to scan. */
for (;;)
@@ -1301,7 +1312,7 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties,
}
if (BUFFERP (object) && !NILP (coherent_change_p))
- modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ modify_region (object, start, end);
set_text_properties_1 (start, end, properties, object, i);
@@ -1450,7 +1461,7 @@ Use `set-text-properties' if you want to remove all text properties. */)
}
if (BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ modify_region (object, start, end);
/* We are at the beginning of an interval, with len to scan */
for (;;)
@@ -1564,7 +1575,7 @@ Return t if any property was actually removed, nil otherwise. */)
else if (LENGTH (i) == len)
{
if (!modified && BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ modify_region (object, start, end);
remove_properties (Qnil, properties, i, object);
if (BUFFERP (object))
signal_after_change (XINT (start), XINT (end) - XINT (start),
@@ -1577,7 +1588,7 @@ Return t if any property was actually removed, nil otherwise. */)
i = split_interval_left (i, len);
copy_properties (unchanged, i);
if (!modified && BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ modify_region (object, start, end);
remove_properties (Qnil, properties, i, object);
if (BUFFERP (object))
signal_after_change (XINT (start), XINT (end) - XINT (start),
@@ -1588,7 +1599,7 @@ Return t if any property was actually removed, nil otherwise. */)
if (interval_has_some_properties_list (properties, i))
{
if (!modified && BUFFERP (object))
- modify_region (XBUFFER (object), XINT (start), XINT (end), 1);
+ modify_region (object, start, end);
remove_properties (Qnil, properties, i, object);
modified = 1;
}
diff --git a/src/tparam.c b/src/tparam.c
index 9492d9dee36..164f61d471b 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -19,7 +19,7 @@ Boston, MA 02110-1301, USA. */
/* Emacs config.h may rename various library functions such as malloc. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h" /* for xmalloc */
#include "tparam.h"
@@ -247,7 +247,7 @@ tparam1 (const char *string, char *outstring, int len,
break;
default:
- abort ();
+ emacs_abort ();
}
}
else
diff --git a/src/undo.c b/src/undo.c
index 9cd1d5f9f67..e878ef4dcf9 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -18,7 +18,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "character.h"
#include "buffer.h"
diff --git a/src/unexaix.c b/src/unexaix.c
index c09156296f7..c01a22a79f6 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -89,7 +89,6 @@ static int adjust_lnnoptrs (int, int, const char *);
static int pagemask;
-#include <setjmp.h>
#include "lisp.h"
static void
diff --git a/src/unexcoff.c b/src/unexcoff.c
index e83042a379d..6e29951a962 100644
--- a/src/unexcoff.c
+++ b/src/unexcoff.c
@@ -120,7 +120,6 @@ static int pagemask;
#define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
-#include <setjmp.h>
#include "lisp.h"
static void
@@ -333,11 +332,7 @@ write_segment (int new, const char *ptr, const char *end)
a gap between the old text segment and the old data segment.
This gap has probably been remapped into part of the text segment.
So write zeros for it. */
- if (ret == -1
-#ifdef EFAULT
- && errno == EFAULT
-#endif
- )
+ if (ret == -1 && errno == EFAULT)
{
/* Write only a page of zeros at once,
so that we don't overshoot the start
diff --git a/src/unexcw.c b/src/unexcw.c
index eae534cf4dd..7d1a72e0009 100644
--- a/src/unexcw.c
+++ b/src/unexcw.c
@@ -20,8 +20,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "unexec.h"
+#include "w32common.h"
-#include <setjmp.h>
#include <lisp.h>
#include <stdio.h>
#include <fcntl.h>
@@ -183,6 +183,19 @@ fixup_executable (int fd)
exe_header->file_optional_header.FileAlignment *
exe_header->file_optional_header.FileAlignment;
+ /* Make sure the generated bootstrap binary isn't
+ * sparse. NT doesn't use a file cache for sparse
+ * executables, so if we bootstrap Emacs using a sparse
+ * bootstrap-emacs.exe, bootstrap takes about twenty
+ * times longer than it would otherwise. */
+
+ ret = posix_fallocate (fd,
+ ( exe_header->section_header[i].s_scnptr +
+ exe_header->section_header[i].s_size ),
+ 1);
+
+ assert (ret != -1);
+
ret =
lseek (fd,
(long) (exe_header->section_header[i].s_scnptr +
diff --git a/src/unexelf.c b/src/unexelf.c
index f35b53aeab3..b9f8e05e959 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -461,7 +461,7 @@ typedef struct {
/*
* NetBSD does not have normal-looking user-land ELF support.
*/
-# if defined __alpha__ || defined __sparc_v9__
+# if defined __alpha__ || defined __sparc_v9__ || defined _LP64
# define ELFSIZE 64
# else
# define ELFSIZE 32
@@ -507,10 +507,12 @@ typedef struct {
#ifndef ElfW
# define ElfBitsW(bits, type) Elf##bits##_##type
-# ifdef _LP64
-# define ELFSIZE 64
-# else
-# define ELFSIZE 32
+# ifndef ELFSIZE
+# ifdef _LP64
+# define ELFSIZE 64
+# else
+# define ELFSIZE 32
+# endif
# endif
/* This macro expands `bits' before invoking ElfBitsW. */
# define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
index 05a16466dfb..d304e85d490 100644
--- a/src/unexmacosx.c
+++ b/src/unexmacosx.c
@@ -117,6 +117,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <assert.h>
+/* LC_DATA_IN_CODE is not defined in mach-o/loader.h on OS X 10.7.
+ But it is used if we build with "Command Line Tools for Xcode 4.5
+ (OS X Lion) - September 2012". */
+#ifndef LC_DATA_IN_CODE
+#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */
+#endif
+
#ifdef _LP64
#define mach_header mach_header_64
#define segment_command segment_command_64
@@ -612,6 +619,11 @@ print_load_command_name (int lc)
printf ("LC_MAIN ");
break;
#endif
+#ifdef LC_DATA_IN_CODE
+ case LC_DATA_IN_CODE:
+ printf ("LC_DATA_IN_CODE ");
+ break;
+#endif
#ifdef LC_SOURCE_VERSION
case LC_SOURCE_VERSION:
printf ("LC_SOURCE_VERSION");
@@ -1178,9 +1190,9 @@ copy_dyld_info (struct load_command *lc, long delta)
#endif
#ifdef LC_FUNCTION_STARTS
-/* Copy a LC_FUNCTION_STARTS/LC_DYLIB_CODE_SIGN_DRS load command from
- the input file to the output file, adjusting the data offset
- field. */
+/* Copy a LC_FUNCTION_STARTS/LC_DATA_IN_CODE/LC_DYLIB_CODE_SIGN_DRS
+ load command from the input file to the output file, adjusting the
+ data offset field. */
static void
copy_linkedit_data (struct load_command *lc, long delta)
{
@@ -1274,6 +1286,9 @@ dump_it (void)
#endif
#ifdef LC_FUNCTION_STARTS
case LC_FUNCTION_STARTS:
+#ifdef LC_DATA_IN_CODE
+ case LC_DATA_IN_CODE:
+#endif
#ifdef LC_DYLIB_CODE_SIGN_DRS
case LC_DYLIB_CODE_SIGN_DRS:
#endif
diff --git a/src/unexsol.c b/src/unexsol.c
index 336f3b4faea..470206d5838 100644
--- a/src/unexsol.c
+++ b/src/unexsol.c
@@ -4,7 +4,6 @@
#include "unexec.h"
#include <dlfcn.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
diff --git a/src/unexw32.c b/src/unexw32.c
index 52b2ec4bf2b..ee1deb5f92e 100644
--- a/src/unexw32.c
+++ b/src/unexw32.c
@@ -22,6 +22,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "unexec.h"
+#include "lisp.h"
+#include "w32common.h"
+#include "w32.h"
#include <stdio.h>
#include <fcntl.h>
@@ -67,28 +70,21 @@ void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile);
/* Cached info about the .data section in the executable. */
PIMAGE_SECTION_HEADER data_section;
PCHAR data_start = 0;
-DWORD data_size = 0;
+DWORD_PTR data_size = 0;
/* Cached info about the .bss section in the executable. */
PIMAGE_SECTION_HEADER bss_section;
PCHAR bss_start = 0;
-DWORD bss_size = 0;
-DWORD extra_bss_size = 0;
+DWORD_PTR bss_size = 0;
+DWORD_PTR extra_bss_size = 0;
/* bss data that is static might be discontiguous from non-static. */
PIMAGE_SECTION_HEADER bss_section_static;
PCHAR bss_start_static = 0;
-DWORD bss_size_static = 0;
-DWORD extra_bss_size_static = 0;
+DWORD_PTR bss_size_static = 0;
+DWORD_PTR extra_bss_size_static = 0;
PIMAGE_SECTION_HEADER heap_section;
-#ifdef HAVE_NTGUI
-HINSTANCE hinst = NULL;
-HINSTANCE hprevinst = NULL;
-LPSTR lpCmdLine = "";
-int nCmdShow = 0;
-#endif /* HAVE_NTGUI */
-
/* Startup code for running on NT. When we are running as the dumped
version, we need to bootstrap our heap and .bss section into our
address space before we can actually hand off control to the startup
@@ -118,15 +114,6 @@ _start (void)
/* Prevent Emacs from being locked up (eg. in batch mode) when
accessing devices that aren't mounted (eg. removable media drives). */
SetErrorMode (SEM_FAILCRITICALERRORS);
-
- /* Invoke the NT CRT startup routine now that our housecleaning
- is finished. */
-#ifdef HAVE_NTGUI
- /* determine WinMain args like crt0.c does */
- hinst = GetModuleHandle (NULL);
- lpCmdLine = GetCommandLine ();
- nCmdShow = SW_SHOWDEFAULT;
-#endif
mainCRTStartup ();
}
@@ -231,7 +218,7 @@ find_section (char * name, IMAGE_NT_HEADERS * nt_header)
/* Return pointer to section header for section containing the given
relative virtual address. */
IMAGE_SECTION_HEADER *
-rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
+rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header)
{
PIMAGE_SECTION_HEADER section;
int i;
@@ -246,7 +233,7 @@ rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
some very old exes (eg. gzip dated Dec 1993). Since
w32_executable_type relies on this function to work reliably,
we need to cope with this. */
- DWORD real_size = max (section->SizeOfRawData,
+ DWORD_PTR real_size = max (section->SizeOfRawData,
section->Misc.VirtualSize);
if (rva >= section->VirtualAddress
&& rva < section->VirtualAddress + real_size)
@@ -259,7 +246,7 @@ rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
/* Return pointer to section header for section containing the given
offset in its raw data area. */
IMAGE_SECTION_HEADER *
-offset_to_section (DWORD offset, IMAGE_NT_HEADERS * nt_header)
+offset_to_section (DWORD_PTR offset, IMAGE_NT_HEADERS * nt_header)
{
PIMAGE_SECTION_HEADER section;
int i;
@@ -279,8 +266,8 @@ offset_to_section (DWORD offset, IMAGE_NT_HEADERS * nt_header)
/* Return offset to an object in dst, given offset in src. We assume
there is at least one section in both src and dst images, and that
the some sections may have been added to dst (after sections in src). */
-DWORD
-relocate_offset (DWORD offset,
+DWORD_PTR
+relocate_offset (DWORD_PTR offset,
IMAGE_NT_HEADERS * src_nt_header,
IMAGE_NT_HEADERS * dst_nt_header)
{
@@ -314,25 +301,25 @@ relocate_offset (DWORD offset,
}
#define OFFSET_TO_RVA(offset, section) \
- (section->VirtualAddress + ((DWORD)(offset) - section->PointerToRawData))
+ ((section)->VirtualAddress + ((DWORD_PTR)(offset) - (section)->PointerToRawData))
#define RVA_TO_OFFSET(rva, section) \
- (section->PointerToRawData + ((DWORD)(rva) - section->VirtualAddress))
+ ((section)->PointerToRawData + ((DWORD_PTR)(rva) - (section)->VirtualAddress))
#define RVA_TO_SECTION_OFFSET(rva, section) \
- ((DWORD)(rva) - section->VirtualAddress)
+ ((DWORD_PTR)(rva) - (section)->VirtualAddress)
/* Convert address in executing image to RVA. */
-#define PTR_TO_RVA(ptr) ((DWORD)(ptr) - (DWORD) GetModuleHandle (NULL))
+#define PTR_TO_RVA(ptr) ((DWORD_PTR)(ptr) - (DWORD_PTR) GetModuleHandle (NULL))
#define RVA_TO_PTR(var,section,filedata) \
- ((void *)(RVA_TO_OFFSET (var,section) + (filedata).file_base))
+ ((unsigned char *)(RVA_TO_OFFSET (var,section) + (filedata).file_base))
#define PTR_TO_OFFSET(ptr, pfile_data) \
((unsigned char *)(ptr) - (pfile_data)->file_base)
#define OFFSET_TO_PTR(offset, pfile_data) \
- ((pfile_data)->file_base + (DWORD)(offset))
+ ((pfile_data)->file_base + (DWORD_PTR)(offset))
/* Flip through the executable and cache the info necessary for dumping. */
@@ -349,7 +336,7 @@ get_section_info (file_data *p_infile)
printf ("Unknown EXE header in %s...bailing.\n", p_infile->name);
exit (1);
}
- nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
+ nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
dos_header->e_lfanew);
if (nt_header == NULL)
{
@@ -488,7 +475,7 @@ copy_executable_and_dump_data (file_data *p_infile,
PIMAGE_NT_HEADERS dst_nt_header;
PIMAGE_SECTION_HEADER section;
PIMAGE_SECTION_HEADER dst_section;
- DWORD offset;
+ DWORD_PTR offset;
int i;
int be_verbose = GetEnvironmentVariable ("DEBUG_DUMP", NULL, 0) > 0;
@@ -541,17 +528,17 @@ copy_executable_and_dump_data (file_data *p_infile,
Note that dst is updated implicitly by each COPY_CHUNK. */
dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
- nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
+ nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
dos_header->e_lfanew);
section = IMAGE_FIRST_SECTION (nt_header);
dst = (unsigned char *) p_outfile->file_base;
COPY_CHUNK ("Copying DOS header...", dos_header,
- (DWORD) nt_header - (DWORD) dos_header, be_verbose);
+ (DWORD_PTR) nt_header - (DWORD_PTR) dos_header, be_verbose);
dst_nt_header = (PIMAGE_NT_HEADERS) dst;
COPY_CHUNK ("Copying NT header...", nt_header,
- (DWORD) section - (DWORD) nt_header, be_verbose);
+ (DWORD_PTR) section - (DWORD_PTR) nt_header, be_verbose);
dst_section = (PIMAGE_SECTION_HEADER) dst;
COPY_CHUNK ("Copying section table...", section,
nt_header->FileHeader.NumberOfSections * sizeof (*section),
@@ -627,8 +614,8 @@ copy_executable_and_dump_data (file_data *p_infile,
}
if (section == heap_section)
{
- DWORD heap_start = (DWORD) get_heap_start ();
- DWORD heap_size = get_committed_heap_size ();
+ 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. */
diff --git a/src/vm-limit.c b/src/vm-limit.c
index cf697b56fdf..befc01d400f 100644
--- a/src/vm-limit.c
+++ b/src/vm-limit.c
@@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
#include <unistd.h> /* for 'environ', on AIX */
#include "lisp.h"
#include "mem-limits.h"
@@ -42,61 +41,41 @@ static void (*warn_function) (const char *);
static POINTER data_space_start;
/* Number of bytes of writable memory we can expect to be able to get. */
-static unsigned long lim_data;
+static size_t lim_data;
-#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_AS)
-static void
-get_lim_data (void)
-{
- struct rlimit rlimit;
-
- getrlimit (RLIMIT_AS, &rlimit);
- if (rlimit.rlim_cur == RLIM_INFINITY)
- lim_data = -1;
- else
- lim_data = rlimit.rlim_cur;
-}
+#ifdef HAVE_GETRLIMIT
-#else /* not HAVE_GETRLIMIT */
-
-#ifdef USG
+# ifndef RLIMIT_AS
+# define RLIMIT_AS RLIMIT_DATA
+# endif
static void
get_lim_data (void)
{
- extern long ulimit ();
-
- lim_data = -1;
-
- /* Use the ulimit call, if we seem to have it. */
-#if !defined (ULIMIT_BREAK_VALUE) || defined (GNU_LINUX)
- lim_data = ulimit (3, 0);
-#endif
-
- /* If that didn't work, just use the macro's value. */
-#ifdef ULIMIT_BREAK_VALUE
- if (lim_data == -1)
- lim_data = ULIMIT_BREAK_VALUE;
-#endif
-
- lim_data -= (long) data_space_start;
+ /* Set LIM_DATA to the minimum of the maximum object size and the
+ maximum address space. Don't bother to check for values like
+ RLIM_INFINITY since in practice they are not much less than SIZE_MAX. */
+ struct rlimit rlimit;
+ lim_data
+ = (getrlimit (RLIMIT_AS, &rlimit) == 0 && rlimit.rlim_cur <= SIZE_MAX
+ ? rlimit.rlim_cur
+ : SIZE_MAX);
}
-#else /* not USG */
-#ifdef WINDOWSNT
+#elif defined WINDOWSNT
+
+#include "w32heap.h"
static void
get_lim_data (void)
{
- extern unsigned long reserved_heap_size;
+ extern size_t reserved_heap_size;
lim_data = reserved_heap_size;
}
-#else
-#if !defined (BSD4_2) && !defined (CYGWIN)
+#elif defined MSDOS
-#ifdef MSDOS
void
get_lim_data (void)
{
@@ -134,32 +113,9 @@ ret_lim_data (void)
get_lim_data ();
return lim_data;
}
-#else /* not MSDOS */
-static void
-get_lim_data (void)
-{
- lim_data = vlimit (LIM_DATA, -1);
-}
-#endif /* not MSDOS */
-
-#else /* BSD4_2 || CYGWIN */
-
-static void
-get_lim_data (void)
-{
- struct rlimit XXrlimit;
-
- getrlimit (RLIMIT_DATA, &XXrlimit);
-#ifdef RLIM_INFINITY
- lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
#else
- lim_data = XXrlimit.rlim_cur; /* soft limit */
+# error "get_lim_data not implemented on this machine"
#endif
-}
-#endif /* BSD4_2 */
-#endif /* not WINDOWSNT */
-#endif /* not USG */
-#endif /* not HAVE_GETRLIMIT */
/* Verify amount of memory available, complaining if we're near the end. */
@@ -167,13 +123,13 @@ static void
check_memory_limits (void)
{
#ifdef REL_ALLOC
- extern POINTER (*real_morecore) (long);
+ extern POINTER (*real_morecore) (ptrdiff_t);
#endif
- extern POINTER (*__morecore) (long);
+ extern POINTER (*__morecore) (ptrdiff_t);
register POINTER cp;
- unsigned long five_percent;
- unsigned long data_size;
+ size_t five_percent;
+ size_t data_size;
enum warnlevel new_warnlevel;
if (lim_data == 0)
diff --git a/src/w16select.c b/src/w16select.c
index 2026de7421d..b8aaa3619ba 100644
--- a/src/w16select.c
+++ b/src/w16select.c
@@ -31,7 +31,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <dpmi.h>
#include <go32.h>
#include <sys/farptr.h>
-#include <setjmp.h>
#include "lisp.h"
#include "dispextern.h" /* frame.h seems to want this */
#include "frame.h" /* Need this to get the X window of selected_frame */
@@ -460,7 +459,7 @@ DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_dat
if ( !FRAME_MSDOS_P (XFRAME (frame)))
goto done;
- BLOCK_INPUT;
+ block_input ();
if (!open_clipboard ())
goto error;
@@ -521,7 +520,7 @@ DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_dat
unblock:
xfree (dst);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Notify user if the text is too large to fit into DOS memory.
(This will happen somewhere after 600K bytes (470K in DJGPP v1.x),
@@ -566,7 +565,7 @@ DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_dat
if ( !FRAME_MSDOS_P (XFRAME (frame)))
goto done;
- BLOCK_INPUT;
+ block_input ();
if (!open_clipboard ())
goto unblock;
@@ -627,7 +626,7 @@ DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_dat
close_clipboard ();
unblock:
- UNBLOCK_INPUT;
+ unblock_input ();
done:
diff --git a/src/w32.c b/src/w32.c
index fe612687f48..50c81f88c72 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -31,14 +31,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/file.h>
#include <sys/time.h>
#include <sys/utime.h>
-#include <mbstring.h> /* for _mbspbrk */
#include <math.h>
-#include <setjmp.h>
#include <time.h>
/* must include CRT headers *before* config.h */
#include <config.h>
+#include <mbstring.h> /* for _mbspbrk */
#undef access
#undef chdir
@@ -102,17 +101,17 @@ typedef struct _MEMORY_STATUS_EX {
_WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
defines it in psapi.h */
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
- DWORD cb;
- DWORD PageFaultCount;
- DWORD PeakWorkingSetSize;
- DWORD WorkingSetSize;
- DWORD QuotaPeakPagedPoolUsage;
- DWORD QuotaPagedPoolUsage;
- DWORD QuotaPeakNonPagedPoolUsage;
- DWORD QuotaNonPagedPoolUsage;
- DWORD PagefileUsage;
- DWORD PeakPagefileUsage;
- DWORD PrivateUsage;
+ DWORD cb;
+ DWORD PageFaultCount;
+ SIZE_T PeakWorkingSetSize;
+ SIZE_T WorkingSetSize;
+ SIZE_T QuotaPeakPagedPoolUsage;
+ SIZE_T QuotaPagedPoolUsage;
+ SIZE_T QuotaPeakNonPagedPoolUsage;
+ SIZE_T QuotaNonPagedPoolUsage;
+ SIZE_T PagefileUsage;
+ SIZE_T PeakPagefileUsage;
+ SIZE_T PrivateUsage;
} PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
#endif
@@ -120,9 +119,10 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
#include <aclapi.h>
#ifdef _MSC_VER
-/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER, except
- on ntifs.h, which cannot be included because it triggers conflicts
- with other Windows API headers. So we define it here by hand. */
+/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the
+ associated macros, except on ntifs.h, which cannot be included
+ because it triggers conflicts with other Windows API headers. So
+ we define it here by hand. */
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
@@ -150,6 +150,20 @@ typedef struct _REPARSE_DATA_BUFFER {
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+#ifndef FILE_DEVICE_FILE_SYSTEM
+#define FILE_DEVICE_FILE_SYSTEM 9
+#endif
+#ifndef METHOD_BUFFERED
+#define METHOD_BUFFERED 0
+#endif
+#ifndef FILE_ANY_ACCESS
+#define FILE_ANY_ACCESS 0x00000000
+#endif
+#ifndef CTL_CODE
+#define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
+#endif
+#define FSCTL_GET_REPARSE_POINT \
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
/* TCP connection support. */
@@ -173,8 +187,10 @@ typedef struct _REPARSE_DATA_BUFFER {
#undef sendto
#include "w32.h"
-#include "ndir.h"
+#include <dirent.h>
+#include "w32common.h"
#include "w32heap.h"
+#include "w32select.h"
#include "systime.h"
#include "dispextern.h" /* for xstrcasecmp */
#include "coding.h" /* for Vlocale_coding_system */
@@ -198,6 +214,12 @@ static int enable_privilege (LPCTSTR, BOOL, TOKEN_PRIVILEGES *);
static int restore_privilege (TOKEN_PRIVILEGES *);
static BOOL WINAPI revert_to_self (void);
+extern int sys_access (const char *, int);
+extern void *e_malloc (size_t);
+extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+ EMACS_TIME *, void *);
+
+
/* Initialization states.
@@ -329,8 +351,8 @@ typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
DWORD cb);
typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
HANDLE hProcess,
- DWORD * lpMinimumWorkingSetSize,
- DWORD * lpMaximumWorkingSetSize);
+ PSIZE_T lpMinimumWorkingSetSize,
+ PSIZE_T lpMaximumWorkingSetSize);
typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
LPMEMORYSTATUS lpBuffer);
typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
@@ -867,23 +889,6 @@ create_symbolic_link (LPTSTR lpSymlinkFilename,
return retval;
}
-/* Equivalent of strerror for W32 error codes. */
-char *
-w32_strerror (int error_no)
-{
- static char buf[500];
-
- if (error_no == 0)
- error_no = GetLastError ();
-
- buf[0] = '\0';
- if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
- error_no,
- 0, /* choose most suitable language */
- buf, sizeof (buf), NULL))
- sprintf (buf, "w32 error %u", error_no);
- return buf;
-}
/* Return 1 if P is a valid pointer to an object of size SIZE. Return
0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
@@ -911,8 +916,18 @@ static char startup_dir[MAXPATHLEN];
/* Get the current working directory. */
char *
-getwd (char *dir)
+getcwd (char *dir, int dirsize)
{
+ if (!dirsize)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (dirsize <= strlen (startup_dir))
+ {
+ errno = ERANGE;
+ return NULL;
+ }
#if 0
if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
return dir;
@@ -1273,9 +1288,9 @@ init_user_info (void)
/* Ensure HOME and SHELL are defined. */
if (getenv ("HOME") == NULL)
- abort ();
+ emacs_abort ();
if (getenv ("SHELL") == NULL)
- abort ();
+ emacs_abort ();
/* Set dir and shell from environment variables. */
strcpy (dflt_passwd.pw_dir, getenv ("HOME"));
@@ -1529,74 +1544,48 @@ is_unc_volume (const char *filename)
return 1;
}
-/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
-
-int
-sigsetmask (int signal_mask)
-{
- return 0;
-}
-
+/* Emulate the Posix unsetenv. */
int
-sigmask (int sig)
+unsetenv (const char *name)
{
- return 0;
-}
+ char *var;
+ size_t name_len;
+ int retval;
-int
-sigblock (int sig)
-{
- return 0;
-}
-
-int
-sigunblock (int sig)
-{
- return 0;
-}
-
-int
-sigemptyset (sigset_t *set)
-{
- return 0;
-}
-
-int
-sigaddset (sigset_t *set, int signo)
-{
- return 0;
-}
-
-int
-sigfillset (sigset_t *set)
-{
- return 0;
-}
-
-int
-sigprocmask (int how, const sigset_t *set, sigset_t *oset)
-{
- return 0;
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ name_len = strlen (name);
+ /* MS docs says an environment variable cannot be longer than 32K. */
+ if (name_len > 32767)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ /* It is safe to use 'alloca' with 32K size, since the stack is at
+ least 2MB, and we set it to 8MB in the link command line. */
+ var = alloca (name_len + 2);
+ var[name_len++] = '=';
+ var[name_len] = '\0';
+ return _putenv (var);
}
+/* MS _putenv doesn't support removing a variable when the argument
+ does not include the '=' character, so we fix that here. */
int
-pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
+sys_putenv (char *str)
{
- if (sigprocmask (how, set, oset) == -1)
- return EINVAL;
- return 0;
-}
+ const char *const name_end = strchr (str, '=');
-int
-setpgrp (int pid, int gid)
-{
- return 0;
-}
+ if (name_end == NULL)
+ {
+ /* Remove the variable from the environment. */
+ return unsetenv (str);
+ }
-int
-alarm (int seconds)
-{
- return 0;
+ return _putenv (str);
}
#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
@@ -1677,7 +1666,7 @@ init_environment (char ** argv)
see if it succeeds. But I think that's too much to ask. */
/* MSVCRT's _access crashes with D_OK. */
- if (tmp && sys_access (tmp, D_OK) == 0)
+ if (tmp && faccessat (AT_FDCWD, tmp, D_OK, AT_EACCESS) == 0)
{
char * var = alloca (strlen (tmp) + 8);
sprintf (var, "TMPDIR=%s", tmp);
@@ -1699,7 +1688,6 @@ init_environment (char ** argv)
LPBYTE lpval;
DWORD dwType;
char locale_name[32];
- struct stat ignored;
char default_home[MAX_PATH];
int appdata = 0;
@@ -1740,7 +1728,7 @@ init_environment (char ** argv)
/* For backwards compatibility, check if a .emacs file exists in C:/
If not, then we can try to default to the appdata directory under the
user's profile, which is more likely to be writable. */
- if (stat ("C:/.emacs", &ignored) < 0)
+ if (!check_existing ("C:/.emacs"))
{
HRESULT profile_result;
/* Dynamically load ShGetFolderPath, as it won't exist on versions
@@ -1788,9 +1776,9 @@ init_environment (char ** argv)
char modname[MAX_PATH];
if (!GetModuleFileName (NULL, modname, MAX_PATH))
- abort ();
+ emacs_abort ();
if ((p = strrchr (modname, '\\')) == NULL)
- abort ();
+ emacs_abort ();
*p = 0;
if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
@@ -1809,7 +1797,8 @@ init_environment (char ** argv)
/* FIXME: should use substring of get_emacs_configuration ().
But I don't think the Windows build supports alpha, mips etc
anymore, so have taken the easy option for now. */
- else if (p && xstrcasecmp (p, "\\i386") == 0)
+ else if (p && (xstrcasecmp (p, "\\i386") == 0
+ || xstrcasecmp (p, "\\AMD64") == 0))
{
*p = 0;
p = strrchr (modname, '\\');
@@ -1898,17 +1887,17 @@ init_environment (char ** argv)
memcpy (*envp, "COMSPEC=", 8);
}
- /* Remember the initial working directory for getwd. */
+ /* Remember the initial working directory for getcwd. */
/* FIXME: Do we need to resolve possible symlinks in startup_dir?
Does it matter anywhere in Emacs? */
if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
- abort ();
+ emacs_abort ();
{
static char modname[MAX_PATH];
if (!GetModuleFileName (NULL, modname, MAX_PATH))
- abort ();
+ emacs_abort ();
argv[0] = modname;
}
@@ -1930,7 +1919,7 @@ emacs_root_dir (void)
p = getenv ("emacs_dir");
if (p == NULL)
- abort ();
+ emacs_abort ();
strcpy (root_dir, p);
root_dir[parse_root (root_dir, NULL)] = '\0';
dostounix_filename (root_dir);
@@ -1957,7 +1946,16 @@ get_emacs_configuration (void)
case PROCESSOR_INTEL_386:
case PROCESSOR_INTEL_486:
case PROCESSOR_INTEL_PENTIUM:
+#ifdef _WIN64
+ arch = "amd64";
+#else
arch = "i386";
+#endif
+ break;
+#endif
+#ifdef PROCESSOR_AMD_X8664
+ case PROCESSOR_AMD_X8664:
+ arch = "amd64";
break;
#endif
@@ -2502,7 +2500,7 @@ is_exec (const char * name)
and readdir. We can't use the procedures supplied in sysdep.c,
so we provide them here. */
-struct direct dir_static; /* simulated directory contents */
+struct dirent dir_static; /* simulated directory contents */
static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
static int dir_is_fat;
static char dir_pathname[MAXPATHLEN+1];
@@ -2572,7 +2570,7 @@ closedir (DIR *dirp)
xfree ((char *) dirp);
}
-struct direct *
+struct dirent *
readdir (DIR *dirp)
{
int downcase = !NILP (Vw32_downcase_file_names);
@@ -2626,7 +2624,7 @@ readdir (DIR *dirp)
downcase = 1; /* 8+3 aliases are returned in all caps */
}
dir_static.d_namlen = strlen (dir_static.d_name);
- dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
+ dir_static.d_reclen = sizeof (struct dirent) - MAXNAMLEN + 3 +
dir_static.d_namlen - dir_static.d_namlen % 4;
/* If the file name in cFileName[] includes `?' characters, it means
@@ -2779,16 +2777,20 @@ logon_network_drive (const char *path)
WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE);
}
-/* Shadow some MSVC runtime functions to map requests for long filenames
- to reasonable short names if necessary. This was originally added to
- permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
- long file names. */
-
+/* Emulate faccessat(2). */
int
-sys_access (const char * path, int mode)
+faccessat (int dirfd, const char * path, int mode, int flags)
{
DWORD attributes;
+ if (dirfd != AT_FDCWD
+ && !(IS_DIRECTORY_SEP (path[0])
+ || IS_DEVICE_SEP (path[1])))
+ {
+ errno = EBADF;
+ return -1;
+ }
+
/* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
newer versions blow up when passed D_OK. */
path = map_w32_filename (path, NULL);
@@ -2796,7 +2798,8 @@ sys_access (const char * path, int mode)
to get the attributes of its target file. Note: any symlinks in
PATH elements other than the last one are transparently resolved
by GetFileAttributes below. */
- if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+ if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0
+ && (flags & AT_SYMLINK_NOFOLLOW) == 0)
path = chase_symlinks (path);
if ((attributes = GetFileAttributes (path)) == -1)
@@ -2828,7 +2831,8 @@ sys_access (const char * path, int mode)
}
return -1;
}
- if ((mode & X_OK) != 0 && !is_exec (path))
+ if ((mode & X_OK) != 0
+ && !(is_exec (path) || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
{
errno = EACCES;
return -1;
@@ -2846,6 +2850,11 @@ sys_access (const char * path, int mode)
return 0;
}
+/* Shadow some MSVC runtime functions to map requests for long filenames
+ to reasonable short names if necessary. This was originally added to
+ permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
+ long file names. */
+
int
sys_chdir (const char * path)
{
@@ -3031,7 +3040,7 @@ sys_mktemp (char * template)
{
int save_errno = errno;
p[0] = first_char[i];
- if (sys_access (template, 0) < 0)
+ if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0)
{
errno = save_errno;
return template;
@@ -3287,7 +3296,7 @@ generate_inode_val (const char * name)
doesn't resolve aliasing due to subst commands, or recognize hard
links. */
if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
- abort ();
+ emacs_abort ();
parse_root (fullname, &p);
/* Normal W32 filesystems are still case insensitive. */
@@ -3528,6 +3537,10 @@ is_slow_fs (const char *name)
return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
}
+/* If this is non-zero, the caller wants accurate information about
+ file's owner and group, which could be expensive to get. */
+int w32_stat_get_owner_group;
+
/* MSVC stat function can't cope with UNC names and has other bugs, so
replace it with our own. This also allows us to calculate consistent
inode values and owner/group without hacks in the main Emacs code. */
@@ -3699,6 +3712,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
/* We produce the fallback owner and group data, based on the
current user that runs Emacs, in the following cases:
+ . caller didn't request owner and group info
. this is Windows 9X
. getting security by handle failed, and we need to produce
information for the target of a symlink (this is better
@@ -3707,23 +3721,25 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
If getting security by handle fails, and we don't need to
resolve symlinks, we try getting security by name. */
- if (is_windows_9x () != TRUE)
- psd = get_file_security_desc_by_handle (fh);
- if (psd)
- {
- get_file_owner_and_group (psd, name, buf);
- LocalFree (psd);
- }
- else if (is_windows_9x () == TRUE)
+ if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
get_file_owner_and_group (NULL, name, buf);
- else if (!(is_a_symlink && follow_symlinks))
+ else
{
- psd = get_file_security_desc_by_name (name);
- get_file_owner_and_group (psd, name, buf);
- xfree (psd);
+ psd = get_file_security_desc_by_handle (fh);
+ if (psd)
+ {
+ get_file_owner_and_group (psd, name, buf);
+ LocalFree (psd);
+ }
+ else if (!(is_a_symlink && follow_symlinks))
+ {
+ psd = get_file_security_desc_by_name (name);
+ get_file_owner_and_group (psd, name, buf);
+ xfree (psd);
+ }
+ else
+ get_file_owner_and_group (NULL, name, buf);
}
- else
- get_file_owner_and_group (NULL, name, buf);
CloseHandle (fh);
}
else
@@ -4013,9 +4029,13 @@ utime (const char *name, struct utimbuf *times)
}
/* Need write access to set times. */
- fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
- 0, OPEN_EXISTING, 0, NULL);
- if (fh)
+ fh = CreateFile (name, FILE_WRITE_ATTRIBUTES,
+ /* If NAME specifies a directory, FILE_SHARE_DELETE
+ allows other processes to delete files inside it,
+ while we have the directory open. */
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (fh != INVALID_HANDLE_VALUE)
{
convert_from_time_t (times->actime, &atime);
convert_from_time_t (times->modtime, &mtime);
@@ -4078,7 +4098,7 @@ symlink (char const *filename, char const *linkname)
{
/* Non-absolute FILENAME is understood as being relative to
LINKNAME's directory. We need to prepend that directory to
- FILENAME to get correct results from sys_access below, since
+ FILENAME to get correct results from faccessat below, since
otherwise it will interpret FILENAME relative to the
directory where the Emacs process runs. Note that
make-symbolic-link always makes sure LINKNAME is a fully
@@ -4092,10 +4112,10 @@ symlink (char const *filename, char const *linkname)
strncpy (tem, linkfn, p - linkfn);
tem[p - linkfn] = '\0';
strcat (tem, filename);
- dir_access = sys_access (tem, D_OK);
+ dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
}
else
- dir_access = sys_access (filename, D_OK);
+ dir_access = faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
/* Since Windows distinguishes between symlinks to directories and
to files, we provide a kludgy feature: if FILENAME doesn't
@@ -4672,8 +4692,8 @@ get_process_memory_info (HANDLE h_proc,
static BOOL WINAPI
get_process_working_set_size (HANDLE h_proc,
- DWORD *minrss,
- DWORD *maxrss)
+ PSIZE_T minrss,
+ PSIZE_T maxrss)
{
static GetProcessWorkingSetSize_Proc
s_pfn_Get_Process_Working_Set_Size = NULL;
@@ -4918,7 +4938,7 @@ system_process_attributes (Lisp_Object pid)
unsigned egid;
PROCESS_MEMORY_COUNTERS mem;
PROCESS_MEMORY_COUNTERS_EX mem_ex;
- DWORD minrss, maxrss;
+ SIZE_T minrss, maxrss;
MEMORYSTATUS memst;
MEMORY_STATUS_EX memstex;
double totphys = 0.0;
@@ -5146,7 +5166,7 @@ system_process_attributes (Lisp_Object pid)
&& get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
sizeof (mem_ex)))
{
- DWORD rss = mem_ex.WorkingSetSize / 1024;
+ SIZE_T rss = mem_ex.WorkingSetSize / 1024;
attrs = Fcons (Fcons (Qmajflt,
make_fixnum_or_float (mem_ex.PageFaultCount)),
@@ -5161,7 +5181,7 @@ system_process_attributes (Lisp_Object pid)
else if (h_proc
&& get_process_memory_info (h_proc, &mem, sizeof (mem)))
{
- DWORD rss = mem_ex.WorkingSetSize / 1024;
+ SIZE_T rss = mem_ex.WorkingSetSize / 1024;
attrs = Fcons (Fcons (Qmajflt,
make_fixnum_or_float (mem.PageFaultCount)),
@@ -5587,7 +5607,7 @@ socket_to_fd (SOCKET s)
if (fd_info[ fd ].cp != NULL)
{
DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
- abort ();
+ emacs_abort ();
}
fd_info[ fd ].cp = cp;
@@ -5910,7 +5930,7 @@ fcntl (int s, int cmd, int options)
check_errno ();
if (fd_info[s].flags & FILE_SOCKET)
{
- if (cmd == F_SETFL && options == O_NDELAY)
+ if (cmd == F_SETFL && options == O_NONBLOCK)
{
unsigned long nblock = 1;
int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
@@ -5966,7 +5986,7 @@ sys_close (int fd)
{
if (fd_info[fd].flags & FILE_SOCKET)
{
- if (winsock_lib == NULL) abort ();
+ if (winsock_lib == NULL) emacs_abort ();
pfn_shutdown (SOCK_HANDLE (fd), 2);
rc = pfn_closesocket (SOCK_HANDLE (fd));
@@ -6065,7 +6085,8 @@ sys_pipe (int * phandles)
}
/* Function to do blocking read of one byte, needed to implement
- select. It is only allowed on sockets and pipes. */
+ select. It is only allowed on communication ports, sockets, or
+ pipes. */
int
_sys_read_ahead (int fd)
{
@@ -6084,7 +6105,7 @@ _sys_read_ahead (int fd)
|| (fd_info[fd].flags & FILE_READ) == 0)
{
DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
- abort ();
+ emacs_abort ();
}
cp->status = STATUS_READ_IN_PROGRESS;
@@ -6220,7 +6241,7 @@ sys_read (int fd, char * buffer, unsigned int count)
/* re-read CR carried over from last read */
if (fd_info[fd].flags & FILE_LAST_CR)
{
- if (fd_info[fd].flags & FILE_BINARY) abort ();
+ if (fd_info[fd].flags & FILE_BINARY) emacs_abort ();
*buffer++ = 0x0d;
count--;
nchars++;
@@ -6323,7 +6344,7 @@ sys_read (int fd, char * buffer, unsigned int count)
}
else /* FILE_SOCKET */
{
- if (winsock_lib == NULL) abort ();
+ if (winsock_lib == NULL) emacs_abort ();
/* do the equivalent of a non-blocking read */
pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
@@ -6474,7 +6495,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
else if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
{
unsigned long nblock = 0;
- if (winsock_lib == NULL) abort ();
+ if (winsock_lib == NULL) emacs_abort ();
/* TODO: implement select() properly so non-blocking I/O works. */
/* For now, make sure the write blocks. */
@@ -6546,33 +6567,27 @@ sys_localtime (const time_t *t)
-/* Delayed loading of libraries. */
-
-Lisp_Object Vlibrary_cache;
-
-/* The argument LIBRARIES is an alist that associates a symbol
- LIBRARY_ID, identifying an external DLL library known to Emacs, to
- a list of filenames under which the library is usually found. In
- most cases, the argument passed as LIBRARIES is the variable
- `dynamic-library-alist', which is initialized to a list of common
- library names. If the function loads the library successfully, it
- returns the handle of the DLL, and records the filename in the
- property :loaded-from of LIBRARY_ID; it returns NULL if the library
- could not be found, or when it was already loaded (because the
- handle is not recorded anywhere, and so is lost after use). It
- would be trivial to save the handle too in :loaded-from, but
- currently there's no use case for it. */
+/* Try loading LIBRARY_ID from the file(s) specified in
+ Vdynamic_library_alist. If the library is loaded successfully,
+ return the handle of the DLL, and record the filename in the
+ property :loaded-from of LIBRARY_ID. If the library could not be
+ found, or when it was already loaded (because the handle is not
+ recorded anywhere, and so is lost after use), return NULL.
+
+ We could also save the handle in :loaded-from, but currently
+ there's no use case for it. */
HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object library_id)
+w32_delayed_load (Lisp_Object library_id)
{
HMODULE library_dll = NULL;
CHECK_SYMBOL (library_id);
- if (CONSP (libraries) && NILP (Fassq (library_id, Vlibrary_cache)))
+ if (CONSP (Vdynamic_library_alist)
+ && NILP (Fassq (library_id, Vlibrary_cache)))
{
Lisp_Object found = Qnil;
- Lisp_Object dlls = Fassq (library_id, libraries);
+ Lisp_Object dlls = Fassq (library_id, Vdynamic_library_alist);
if (CONSP (dlls))
for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
@@ -6640,8 +6655,7 @@ check_windows_init_file (void)
buffer,
"Emacs Abort Dialog",
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
- /* Use the low-level Emacs abort. */
-#undef abort
+ /* Use the low-level system abort. */
abort ();
}
else
@@ -6652,8 +6666,12 @@ check_windows_init_file (void)
}
void
-term_ntproc (void)
+term_ntproc (int ignored)
{
+ (void)ignored;
+
+ term_timers ();
+
/* shutdown the socket interface if necessary */
term_winsock ();
@@ -6661,8 +6679,10 @@ term_ntproc (void)
}
void
-init_ntproc (void)
+init_ntproc (int dumping)
{
+ sigset_t initial_mask = 0;
+
/* Initialize the socket interface now if available and requested by
the user by defining PRELOAD_WINSOCK; otherwise loading will be
delayed until open-network-stream is called (w32-has-winsock can
@@ -6718,19 +6738,19 @@ init_ntproc (void)
fclose (stderr);
if (stdin_save != INVALID_HANDLE_VALUE)
- _open_osfhandle ((long) stdin_save, O_TEXT);
+ _open_osfhandle ((intptr_t) stdin_save, O_TEXT);
else
_open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
_fdopen (0, "r");
if (stdout_save != INVALID_HANDLE_VALUE)
- _open_osfhandle ((long) stdout_save, O_TEXT);
+ _open_osfhandle ((intptr_t) stdout_save, O_TEXT);
else
_open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
_fdopen (1, "w");
if (stderr_save != INVALID_HANDLE_VALUE)
- _open_osfhandle ((long) stderr_save, O_TEXT);
+ _open_osfhandle ((intptr_t) stderr_save, O_TEXT);
else
_open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
_fdopen (2, "w");
@@ -6738,7 +6758,13 @@ init_ntproc (void)
/* unfortunately, atexit depends on implementation of malloc */
/* atexit (term_ntproc); */
- signal (SIGABRT, term_ntproc);
+ if (!dumping)
+ {
+ /* Make sure we start with all signals unblocked. */
+ sigprocmask (SIG_SETMASK, &initial_mask, NULL);
+ signal (SIGABRT, term_ntproc);
+ }
+ init_timers ();
/* determine which drives are fixed, for GetCachedVolumeInformation */
{
@@ -6795,9 +6821,6 @@ globals_of_w32 (void)
DEFSYM (QCloaded_from, ":loaded-from");
- Vlibrary_cache = Qnil;
- staticpro (&Vlibrary_cache);
-
g_b_init_is_windows_9x = 0;
g_b_init_open_process_token = 0;
g_b_init_get_token_information = 0;
@@ -6834,6 +6857,9 @@ globals_of_w32 (void)
/* "None" is the default group name on standalone workstations. */
strcpy (dflt_group_name, "None");
+
+ /* Reset, in case it has some value inherited from dump time. */
+ w32_stat_get_owner_group = 0;
}
/* For make-serial-process */
@@ -6848,7 +6874,7 @@ serial_open (char *port)
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hnd == INVALID_HANDLE_VALUE)
error ("Could not open %s", port);
- fd = (int) _open_osfhandle ((int) hnd, 0);
+ fd = (int) _open_osfhandle ((intptr_t) hnd, 0);
if (fd == -1)
error ("Could not open %s", port);
@@ -7033,7 +7059,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
{
int n, sc, err;
SELECT_TYPE fdset;
- struct timeval timeout;
+ EMACS_TIME timeout;
struct Lisp_Process *process = (struct Lisp_Process *)p;
int fd = process->infd;
@@ -7049,8 +7075,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
if (err == EWOULDBLOCK)
{
/* Set a small timeout. */
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ timeout = make_emacs_time (1, 0);
FD_ZERO (&fdset);
FD_SET ((int)fd, &fdset);
diff --git a/src/w32.h b/src/w32.h
index 73d57a65a4a..a43a5133eb4 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -19,6 +19,12 @@ 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/>. */
+#ifdef CYGWIN
+#error "w32.h is not compatible with Cygwin"
+#endif
+
+#include <windows.h>
+
/* File descriptor set emulation. */
@@ -62,17 +68,47 @@ enum {
a socket, the process handle in pi is NULL. */
typedef struct _child_process
{
- int fd;
- int pid;
- HANDLE char_avail;
- HANDLE char_consumed;
- HANDLE thrd;
- HWND hwnd;
- PROCESS_INFORMATION procinfo;
- volatile int status;
- char chr;
- OVERLAPPED ovl_read;
- OVERLAPPED ovl_write;
+ /* File descriptor for sockets and serial port connections, and for
+ reading output from async subprocesses; otherwise -1. */
+ int fd;
+ /* PID for subprocess, either async or not; otherwise -1. */
+ int pid;
+ /* Handle to an event object that is signaled when a read operation
+ is completed, either successfully (in which case there're indeed
+ "characters available") or not. Used by sys_select to wait for
+ output from subprocesses or socket/serial connections. */
+ HANDLE char_avail;
+ /* Handle to an event that is signaled to wake up the reader thread
+ and tell it to try reading more output from a subprocess. */
+ HANDLE char_consumed;
+ /* Handle to the reader thread to read output from a subprocess or a
+ socket or a comm port. */
+ HANDLE thrd;
+ /* Handle to the console window of a subprocess. Used to forcibly
+ terminate it by sys_kill. */
+ HWND hwnd;
+ /* Information about subprocess returned by CreateProcess. Includes
+ handles to the subprocess and its primary thread, and the
+ corresponding process ID and thread ID numbers. The PID is
+ mirrored by the 'pid' member above. The process handle is used
+ to wait on it. */
+ PROCESS_INFORMATION procinfo;
+ /* Status of subprocess/connection and of reading its output. For
+ values, see the enumeration above. */
+ volatile int status;
+ /* Holds a single character read by _sys_read_ahead, when a
+ subprocess has some output ready. */
+ char chr;
+ /* Used for async read operations on serial comm ports. */
+ OVERLAPPED ovl_read;
+ /* Used for async write operations on serial comm ports. */
+ OVERLAPPED ovl_write;
+ /* Input file, if any, for this subprocess. Should only be non-NULL
+ for async subprocesses. */
+ char *input_file;
+ /* If non-zero, the subprocess input file is temporary and should be
+ deleted when the subprocess exits. */
+ int pending_deletion;
} child_process;
#define MAXDESC FD_SETSIZE
@@ -127,26 +163,41 @@ extern void reset_standard_handles (int in, int out,
/* Return the string resource associated with KEY of type TYPE. */
extern LPBYTE w32_get_resource (char * key, LPDWORD type);
-extern void init_ntproc (void);
-extern void term_ntproc (void);
+extern void init_ntproc (int);
+extern void term_ntproc (int);
extern void globals_of_w32 (void);
-extern void syms_of_w32term (void);
-extern void syms_of_w32fns (void);
-extern void globals_of_w32fns (void);
-extern void syms_of_w32select (void);
-extern void globals_of_w32select (void);
-extern void term_w32select (void);
-extern void syms_of_w32menu (void);
-extern void globals_of_w32menu (void);
-extern void syms_of_fontset (void);
-extern void syms_of_w32font (void);
-extern void check_windows_init_file (void);
+
+extern void term_timers (void);
+extern void init_timers (void);
extern int _sys_read_ahead (int fd);
extern int _sys_wait_accept (int fd);
-extern Lisp_Object Vlibrary_cache, QCloaded_from;
-extern HMODULE w32_delayed_load (Lisp_Object, Lisp_Object);
+extern Lisp_Object QCloaded_from;
+extern HMODULE w32_delayed_load (Lisp_Object);
+
+extern void init_environment (char **);
+extern void check_windows_init_file (void);
+extern void syms_of_ntproc (void);
+extern void syms_of_ntterm (void);
+extern void dostounix_filename (register char *);
+extern void unixtodos_filename (register char *);
+extern BOOL init_winsock (int load_now);
+extern void srandom (int);
+extern int random (void);
+
+extern int sys_pipe (int *);
+
+extern void set_process_dir (char *);
+extern int sys_spawnve (int, char *, char **, char **);
+extern void register_child (pid_t, int);
+extern void record_infile (pid_t, char *);
+extern void record_pending_deletion (char *);
+
+extern void sys_sleep (int);
+extern int sys_link (const char *, const char *);
+
+
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
@@ -161,4 +212,3 @@ extern ssize_t emacs_gnutls_push (gnutls_transport_ptr_t p,
#endif /* HAVE_GNUTLS */
#endif /* EMACS_W32_H */
-
diff --git a/src/w32common.h b/src/w32common.h
new file mode 100644
index 00000000000..5e9b61824ae
--- /dev/null
+++ b/src/w32common.h
@@ -0,0 +1,53 @@
+/* Common functions for Microsoft Windows builds of Emacs
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+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 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/>.
+
+*/
+
+#ifndef W32COMMON_H
+#define W32COMMON_H
+
+#include <windows.h>
+
+#define ROUND_UP(p, align) (((DWORD_PTR)(p) + (align)-1) & ~((DWORD_PTR)(align)-1))
+#define ROUND_DOWN(p, align) ((DWORD_PTR)(p) & ~((DWORD_PTR)(align)-1))
+
+#define get_page_size() sysinfo_cache.dwPageSize
+#define get_allocation_unit() sysinfo_cache.dwAllocationGranularity
+#define get_processor_type() sysinfo_cache.dwProcessorType
+#define get_w32_major_version() w32_major_version
+#define get_w32_minor_version() w32_minor_version
+
+extern SYSTEM_INFO sysinfo_cache;
+extern OSVERSIONINFO osinfo_cache;
+extern DWORD_PTR syspage_mask;
+
+extern int w32_major_version;
+extern int w32_minor_version;
+extern int w32_build_number;
+
+enum {
+ OS_9X = 1,
+ OS_NT
+};
+
+extern int os_subtype;
+
+/* Cache system info, e.g., the NT page size. */
+extern void cache_system_info (void);
+
+#endif /* W32COMMON_H */
diff --git a/src/w32console.c b/src/w32console.c
index 76585851e7f..f201ff190c2 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -26,7 +26,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <windows.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -37,7 +36,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "termhooks.h"
#include "termchar.h"
#include "dispextern.h"
-#include "w32heap.h" /* for os_subtype */
+#include "w32term.h"
+#include "w32common.h" /* for os_subtype */
#include "w32inevt.h"
/* from window.c */
@@ -431,53 +431,6 @@ w32con_delete_glyphs (struct frame *f, int n)
scroll_line (f, n, LEFT);
}
-static unsigned int sound_type = 0xFFFFFFFF;
-#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
-
-void
-w32_sys_ring_bell (struct frame *f)
-{
- if (sound_type == 0xFFFFFFFF)
- {
- Beep (666, 100);
- }
- else if (sound_type == MB_EMACS_SILENT)
- {
- /* Do nothing. */
- }
- else
- MessageBeep (sound_type);
-}
-
-DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
- doc: /* Set the sound generated when the bell is rung.
-SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
-to use the corresponding system sound for the bell. The 'silent sound
-prevents Emacs from making any sound at all.
-SOUND is nil to use the normal beep. */)
- (Lisp_Object sound)
-{
- CHECK_SYMBOL (sound);
-
- if (NILP (sound))
- sound_type = 0xFFFFFFFF;
- else if (EQ (sound, intern ("asterisk")))
- sound_type = MB_ICONASTERISK;
- else if (EQ (sound, intern ("exclamation")))
- sound_type = MB_ICONEXCLAMATION;
- else if (EQ (sound, intern ("hand")))
- sound_type = MB_ICONHAND;
- else if (EQ (sound, intern ("question")))
- sound_type = MB_ICONQUESTION;
- else if (EQ (sound, intern ("ok")))
- sound_type = MB_OK;
- else if (EQ (sound, intern ("silent")))
- sound_type = MB_EMACS_SILENT;
- else
- sound_type = 0xFFFFFFFF;
-
- return sound;
-}
static void
w32con_reset_terminal_modes (struct terminal *t)
@@ -793,6 +746,9 @@ initialize_w32_display (struct terminal *term)
else
w32_console_unicode_input = 0;
+ /* This is needed by w32notify.c:send_notifications. */
+ dwMainThreadId = GetCurrentThreadId ();
+
/* Setup w32_display_info structure for this frame. */
w32_initialize_display_info (build_string ("Console"));
@@ -851,5 +807,4 @@ scroll-back buffer. */);
defsubr (&Sset_screen_color);
defsubr (&Sget_screen_color);
defsubr (&Sset_cursor_size);
- defsubr (&Sset_message_beep);
}
diff --git a/src/w32fns.c b/src/w32fns.c
index 5a1b6dfabab..f69fbe05a6d 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -26,7 +26,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <limits.h>
#include <errno.h>
#include <math.h>
-#include <setjmp.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "lisp.h"
#include "w32term.h"
@@ -45,8 +46,18 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "fontset.h"
#include "systime.h"
#include "termhooks.h"
+
+#include "w32common.h"
+
+#ifdef WINDOWSNT
#include "w32heap.h"
+#endif /* WINDOWSNT */
+
+#if CYGWIN
+#include "cygw32.h"
+#else
#include "w32.h"
+#endif
#include "bitmaps/gray.xbm"
@@ -59,9 +70,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <dlgs.h>
#include <imm.h>
-#define FILE_NAME_TEXT_FIELD edt1
-#define FILE_NAME_COMBO_BOX cmb13
-#define FILE_NAME_LIST lst1
#include "font.h"
#include "w32font.h"
@@ -74,15 +82,13 @@ void syms_of_w32fns (void);
void globals_of_w32fns (void);
extern void free_frame_menubar (struct frame *);
-extern double atof (const char *);
extern int w32_console_toggle_lock_key (int, Lisp_Object);
extern void w32_menu_display_help (HWND, HMENU, UINT, UINT);
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-zero, a w32 timer that, when it expires, displays an
- hourglass cursor on all frames. */
-static unsigned hourglass_timer = 0;
+/* If non-NULL, a handle to a frame where to display the hourglass cursor. */
static HWND hourglass_hwnd = NULL;
#ifndef IDC_HAND
@@ -140,7 +146,7 @@ struct MONITOR_INFO
};
/* Reportedly, MSVC does not have this in its headers. */
-#ifdef _MSC_VER
+#if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
DECLARE_HANDLE(HMONITOR);
#endif
@@ -164,7 +170,11 @@ ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
MonitorFromPoint_Proc monitor_from_point_fn = NULL;
GetMonitorInfo_Proc get_monitor_info_fn = NULL;
+#ifdef NTGUI_UNICODE
+#define unicode_append_menu AppendMenuW
+#else /* !NTGUI_UNICODE */
extern AppendMenuW_Proc unicode_append_menu;
+#endif /* NTGUI_UNICODE */
/* Flag to selectively ignore WM_IME_CHAR messages. */
static int ignore_ime_char = 0;
@@ -176,7 +186,6 @@ unsigned int msh_mousewheel = 0;
#define MOUSE_BUTTON_ID 1
#define MOUSE_MOVE_ID 2
#define MENU_FREE_ID 3
-#define HOURGLASS_ID 4
/* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
is received. */
#define MENU_FREE_DELAY 1000
@@ -202,6 +211,33 @@ extern int uniscribe_available;
static void w32_show_hourglass (struct frame *);
static void w32_hide_hourglass (void);
+#ifdef WINDOWSNT
+/* From w32inevt.c */
+extern int faked_key;
+#endif /* WINDOWSNT */
+
+/* This gives us the page size and the size of the allocation unit on NT. */
+SYSTEM_INFO sysinfo_cache;
+
+/* This gives us version, build, and platform identification. */
+OSVERSIONINFO osinfo_cache;
+
+DWORD_PTR syspage_mask = 0;
+
+/* The major and minor versions of NT. */
+int w32_major_version;
+int w32_minor_version;
+int w32_build_number;
+
+/* Distinguish between Windows NT and Windows 95. */
+int os_subtype;
+
+#ifdef HAVE_NTGUI
+HINSTANCE hinst = NULL;
+#endif
+
+static unsigned int sound_type = 0xFFFFFFFF;
+#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
/* Error if we are not connected to MS-Windows. */
@@ -227,12 +263,8 @@ have_menus_p (void)
FRAME_PTR
check_x_frame (Lisp_Object frame)
{
- FRAME_PTR f;
+ struct frame *f = decode_live_frame (frame);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
if (! FRAME_W32_P (f))
error ("Non-W32 frame used");
return f;
@@ -271,19 +303,14 @@ check_x_display_info (Lisp_Object frame)
/* Return the Emacs frame-object corresponding to an w32 window.
It could be the frame's main window or an icon window. */
-/* This function can be called during GC, so use GC_xxx type test macros. */
-
struct frame *
x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc)
{
Lisp_Object tail, frame;
struct frame *f;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
f = XFRAME (frame);
if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
continue;
@@ -365,7 +392,7 @@ if the entry is new. */)
XSETINT (rgb, RGB (XUINT (red), XUINT (green), XUINT (blue)));
- BLOCK_INPUT;
+ block_input ();
/* replace existing entry in w32-color-map or add new entry. */
entry = Fassoc (name, Vw32_color_map);
@@ -380,7 +407,7 @@ if the entry is new. */)
Fsetcdr (entry, rgb);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return (oldrgb);
}
@@ -643,7 +670,7 @@ w32_default_color_map (void)
colormap_t *pc = w32_color_map;
Lisp_Object cmap;
- BLOCK_INPUT;
+ block_input ();
cmap = Qnil;
@@ -653,7 +680,7 @@ w32_default_color_map (void)
make_number (pc->colorref)),
cmap);
- UNBLOCK_INPUT;
+ unblock_input ();
return (cmap);
}
@@ -666,11 +693,11 @@ DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
}
static Lisp_Object
-w32_color_map_lookup (char *colorname)
+w32_color_map_lookup (const char *colorname)
{
Lisp_Object tail, ret = Qnil;
- BLOCK_INPUT;
+ block_input ();
for (tail = Vw32_color_map; CONSP (tail); tail = XCDR (tail))
{
@@ -690,7 +717,7 @@ w32_color_map_lookup (char *colorname)
QUIT;
}
- UNBLOCK_INPUT;
+ unblock_input ();
return ret;
}
@@ -702,7 +729,7 @@ add_system_logical_colors_to_map (Lisp_Object *system_colors)
HKEY colors_key;
/* Other registry operations are done with input blocked. */
- BLOCK_INPUT;
+ block_input ();
/* Look for "Control Panel/Colors" under User and Machine registry
settings. */
@@ -740,25 +767,24 @@ add_system_logical_colors_to_map (Lisp_Object *system_colors)
RegCloseKey (colors_key);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
static Lisp_Object
-x_to_w32_color (char * colorname)
+x_to_w32_color (const char * colorname)
{
register Lisp_Object ret = Qnil;
- BLOCK_INPUT;
+ block_input ();
if (colorname[0] == '#')
{
/* Could be an old-style RGB Device specification. */
- char *color;
- int size;
- color = colorname + 1;
+ int size = strlen (colorname + 1);
+ char *color = alloca (size + 1);
- size = strlen (color);
+ strcpy (color, colorname + 1);
if (size == 3 || size == 6 || size == 9 || size == 12)
{
UINT colorval;
@@ -802,7 +828,7 @@ x_to_w32_color (char * colorname)
pos += 0x8;
if (i == 2)
{
- UNBLOCK_INPUT;
+ unblock_input ();
XSETINT (ret, colorval);
return ret;
}
@@ -812,7 +838,7 @@ x_to_w32_color (char * colorname)
}
else if (strnicmp (colorname, "rgb:", 4) == 0)
{
- char *color;
+ const char *color;
UINT colorval;
int i, pos;
pos = 0;
@@ -856,7 +882,7 @@ x_to_w32_color (char * colorname)
{
if (*end != '\0')
break;
- UNBLOCK_INPUT;
+ unblock_input ();
XSETINT (ret, colorval);
return ret;
}
@@ -868,7 +894,7 @@ x_to_w32_color (char * colorname)
else if (strnicmp (colorname, "rgbi:", 5) == 0)
{
/* This is an RGB Intensity specification. */
- char *color;
+ const char *color;
UINT colorval;
int i, pos;
pos = 0;
@@ -898,7 +924,7 @@ x_to_w32_color (char * colorname)
{
if (*end != '\0')
break;
- UNBLOCK_INPUT;
+ unblock_input ();
XSETINT (ret, colorval);
return ret;
}
@@ -933,7 +959,7 @@ x_to_w32_color (char * colorname)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return ret;
}
@@ -1072,7 +1098,7 @@ gamma_correct (struct frame *f, COLORREF *color)
If ALLOC is nonzero, allocate a new colormap cell. */
int
-w32_defined_color (FRAME_PTR f, char *color, XColor *color_def, int alloc)
+w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc)
{
register Lisp_Object tem;
COLORREF w32_color_ref;
@@ -1236,7 +1262,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
#if 0 /* TODO : Mouse cursor customization. */
- BLOCK_INPUT;
+ block_input ();
/* It's not okay to crash if the user selects a screwy cursor. */
count = x_catch_errors (FRAME_W32_DISPLAY (f));
@@ -1359,7 +1385,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
f->output_data.w32->hand_cursor = hand_cursor;
XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
update_face_from_frame_parameter (f, Qmouse_color, arg);
#endif /* TODO */
@@ -1391,12 +1417,12 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (FRAME_W32_WINDOW (f) != 0)
{
- BLOCK_INPUT;
+ block_input ();
/* Update frame's cursor_gc. */
f->output_data.w32->cursor_gc->foreground = fore_pixel;
f->output_data.w32->cursor_gc->background = pixel;
- UNBLOCK_INPUT;
+ unblock_input ();
if (FRAME_VISIBLE_P (f))
{
@@ -1467,16 +1493,16 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
return;
- BLOCK_INPUT;
+ block_input ();
result = x_bitmap_icon (f, arg);
if (result)
{
- UNBLOCK_INPUT;
+ unblock_input ();
error ("No icon window available");
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
void
@@ -1496,7 +1522,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (f->output_data.w32->icon_bitmap != 0)
return;
- BLOCK_INPUT;
+ block_input ();
result = x_text_icon (f,
SSDATA ((!NILP (f->icon_name)
@@ -1507,7 +1533,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (result)
{
- UNBLOCK_INPUT;
+ unblock_input ();
error ("No icon window available");
}
@@ -1522,7 +1548,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
#endif
}
@@ -1624,13 +1650,13 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
int width = FRAME_PIXEL_WIDTH (f);
int y = nlines * FRAME_LINE_HEIGHT (f);
- BLOCK_INPUT;
+ block_input ();
{
HDC hdc = get_frame_dc (f);
w32_clear_area (f, hdc, 0, y, width, height);
release_frame_dc (f, hdc);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (WINDOWP (f->tool_bar_window))
clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
@@ -1698,9 +1724,9 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit)
if (STRING_MULTIBYTE (name))
name = ENCODE_SYSTEM (name);
- BLOCK_INPUT;
+ block_input ();
SetWindowText (FRAME_W32_WINDOW (f), SDATA (name));
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1744,9 +1770,9 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
if (STRING_MULTIBYTE (name))
name = ENCODE_SYSTEM (name);
- BLOCK_INPUT;
+ block_input ();
SetWindowText (FRAME_W32_WINDOW (f), SDATA (name));
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1795,7 +1821,6 @@ static LRESULT CALLBACK w32_wnd_proc (HWND, UINT, WPARAM, LPARAM);
static BOOL
w32_init_class (HINSTANCE hinst)
{
-
if (w32_unicode_gui)
{
WNDCLASSW uwc;
@@ -1847,10 +1872,7 @@ w32_createwindow (struct frame *f)
/* Do first time app init */
- if (!hprevinst)
- {
- w32_init_class (hinst);
- }
+ w32_init_class (hinst);
if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
{
@@ -2056,8 +2078,35 @@ sync_modifiers (void)
static int
modifier_set (int vkey)
{
- if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
- return (GetKeyState (vkey) & 0x1);
+ /* Warning: The fact that VK_NUMLOCK is not treated as the other 2
+ toggle keys is not an omission! If you want to add it, you will
+ have to make changes in the default sub-case of the WM_KEYDOWN
+ switch, because if the NUMLOCK modifier is set, the code there
+ will directly convert any key that looks like an ASCII letter,
+ and also downcase those that look like upper-case ASCII. */
+ if (vkey == VK_CAPITAL)
+ {
+ if (NILP (Vw32_enable_caps_lock))
+ return 0;
+ else
+ return (GetKeyState (vkey) & 0x1);
+ }
+ if (vkey == VK_SCROLL)
+ {
+ if (NILP (Vw32_scroll_lock_modifier)
+ /* w32-scroll-lock-modifier can be any non-nil value that is
+ not one of the modifiers, in which case it shall be ignored. */
+ || !( EQ (Vw32_scroll_lock_modifier, Qhyper)
+ || EQ (Vw32_scroll_lock_modifier, Qsuper)
+ || EQ (Vw32_scroll_lock_modifier, Qmeta)
+ || EQ (Vw32_scroll_lock_modifier, Qalt)
+ || EQ (Vw32_scroll_lock_modifier, Qcontrol)
+ || EQ (Vw32_scroll_lock_modifier, Qshift)))
+ return 0;
+ else
+ return (GetKeyState (vkey) & 0x1);
+ }
+
if (!modifiers_recorded)
return (GetKeyState (vkey) & 0x8000);
@@ -2250,19 +2299,103 @@ unregister_hot_keys (HWND hwnd)
}
}
+#if EMACSDEBUG
+const char*
+w32_name_of_message (UINT msg)
+{
+ unsigned i;
+ static char buf[64];
+ static const struct {
+ UINT msg;
+ const char* name;
+ } msgnames[] = {
+#define M(msg) { msg, # msg }
+ M (WM_PAINT),
+ M (WM_TIMER),
+ M (WM_USER),
+ M (WM_MOUSEMOVE),
+ M (WM_LBUTTONUP),
+ M (WM_KEYDOWN),
+ M (WM_EMACS_KILL),
+ M (WM_EMACS_CREATEWINDOW),
+ M (WM_EMACS_DONE),
+ M (WM_EMACS_CREATESCROLLBAR),
+ M (WM_EMACS_SHOWWINDOW),
+ M (WM_EMACS_SETWINDOWPOS),
+ M (WM_EMACS_DESTROYWINDOW),
+ M (WM_EMACS_TRACKPOPUPMENU),
+ M (WM_EMACS_SETFOCUS),
+ M (WM_EMACS_SETFOREGROUND),
+ M (WM_EMACS_SETLOCALE),
+ M (WM_EMACS_SETKEYBOARDLAYOUT),
+ M (WM_EMACS_REGISTER_HOT_KEY),
+ M (WM_EMACS_UNREGISTER_HOT_KEY),
+ M (WM_EMACS_TOGGLE_LOCK_KEY),
+ M (WM_EMACS_TRACK_CARET),
+ M (WM_EMACS_DESTROY_CARET),
+ M (WM_EMACS_SHOW_CARET),
+ M (WM_EMACS_HIDE_CARET),
+ M (WM_EMACS_SETCURSOR),
+ M (WM_EMACS_PAINT),
+ M (WM_CHAR),
+#undef M
+ { 0, 0 }
+ };
+
+ for (i = 0; msgnames[i].name; ++i)
+ if (msgnames[i].msg == msg)
+ return msgnames[i].name;
+
+ sprintf (buf, "message 0x%04x", (unsigned)msg);
+ return buf;
+}
+#endif /* EMACSDEBUG */
+
+/* Here's an overview of how Emacs input works in GUI sessions on
+ MS-Windows. (For description of non-GUI input, see the commentary
+ before w32_console_read_socket in w32inevt.c.)
+
+ System messages are read and processed by w32_msg_pump below. This
+ function runs in a separate thread. It handles a small number of
+ custom WM_EMACS_* messages (posted by the main thread, look for
+ PostMessage calls), and dispatches the rest to w32_wnd_proc, which
+ is the main window procedure for the entire Emacs application.
+
+ w32_wnd_proc also runs in the same separate input thread. It
+ handles some messages, mostly those that need GDI calls, by itself.
+ For the others, it calls my_post_msg, which inserts the messages
+ into the input queue serviced by w32_read_socket.
+
+ w32_read_socket runs in the main (a.k.a. "Lisp") thread, and is
+ called synchronously from keyboard.c when it is known or suspected
+ that some input is available. w32_read_socket either handles
+ messages immediately, or converts them into Emacs input events and
+ stuffs them into kbd_buffer, where kbd_buffer_get_event can get at
+ them and process them when read_char and its callers require
+ input.
+
+ Under Cygwin with the W32 toolkit, the use of /dev/windows with
+ select(2) takes the place of w32_read_socket.
+
+ */
+
/* Main message dispatch loop. */
static void
w32_msg_pump (deferred_msg * msg_buf)
{
MSG msg;
- int result;
+ WPARAM result;
HWND focus_window;
msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
while ((w32_unicode_gui ? GetMessageW : GetMessageA) (&msg, NULL, 0, 0))
{
+
+ /* DebPrint (("w32_msg_pump: %s time:%u\n", */
+ /* w32_name_of_message (msg.message), msg.time)); */
+
if (msg.hwnd == NULL)
{
switch (msg.message)
@@ -2280,17 +2413,17 @@ w32_msg_pump (deferred_msg * msg_buf)
CoInitialize (NULL);
w32_createwindow ((struct frame *) msg.wParam);
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
- abort ();
+ emacs_abort ();
break;
case WM_EMACS_SETLOCALE:
SetThreadLocale (msg.wParam);
/* Reply is not expected. */
break;
case WM_EMACS_SETKEYBOARDLAYOUT:
- result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
+ result = (WPARAM) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
result, 0))
- abort ();
+ emacs_abort ();
break;
case WM_EMACS_REGISTER_HOT_KEY:
focus_window = GetFocus ();
@@ -2309,15 +2442,15 @@ 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 ((Lisp_Object) ((EMACS_INT) msg.lParam), Qnil);
+ XSETCAR (XIL ((EMACS_INT) msg.lParam), Qnil);
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
- abort ();
+ emacs_abort ();
break;
case WM_EMACS_TOGGLE_LOCK_KEY:
{
int vk_code = (int) msg.wParam;
int cur_state = (GetKeyState (vk_code) & 1);
- Lisp_Object new_state = (Lisp_Object) ((EMACS_INT) msg.lParam);
+ 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,
@@ -2343,14 +2476,14 @@ w32_msg_pump (deferred_msg * msg_buf)
}
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
cur_state, 0))
- abort ();
+ emacs_abort ();
}
break;
#ifdef MSG_DEBUG
/* Broadcast messages make it here, so you need to be looking
for something in particular for this to be useful. */
default:
- DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
+ DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
#endif
}
}
@@ -2398,11 +2531,11 @@ send_deferred_msg (deferred_msg * msg_buf,
{
/* Only input thread can send deferred messages. */
if (GetCurrentThreadId () != dwWindowsThreadId)
- abort ();
+ emacs_abort ();
/* It is an error to send a message that is already deferred. */
if (find_deferred_msg (hwnd, msg) != NULL)
- abort ();
+ emacs_abort ();
/* Enforced synchronization is not needed because this is the only
function that alters deferred_msg_head, and the following critical
@@ -2475,7 +2608,7 @@ w32_msg_worker (void *arg)
PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
- abort ();
+ emacs_abort ();
memset (&dummy_buf, 0, sizeof (dummy_buf));
dummy_buf.w32msg.msg.hwnd = NULL;
@@ -3136,7 +3269,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
msg = WM_MBUTTONUP;
button_state &= ~MMOUSE;
- if (button_state) abort ();
+ if (button_state) emacs_abort ();
}
else
return 0;
@@ -3216,7 +3349,19 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
versions, there is no way of telling when the mouse leaves the
frame, so we just have to put up with help-echo and mouse
highlighting remaining while the frame is not active. */
- if (track_mouse_event_fn && !track_mouse_window)
+ if (track_mouse_event_fn && !track_mouse_window
+ /* If the menu bar is active, turning on tracking of mouse
+ movement events might send these events to the tooltip
+ frame, if the user happens to move the mouse pointer over
+ the tooltip. But since we don't process events for
+ tooltip frames, this causes Windows to present a
+ hourglass cursor, which is ugly and unexpected. So don't
+ enable tracking mouse events in this case; they will be
+ restarted when the menu pops down. (Confusingly, the
+ menubar_active member of f->output_data.w32, tested
+ above, is only set when a menu was popped up _not_ from
+ the frame's menu bar, but via x-popup-menu.) */
+ && !menubar_in_use)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof (tme);
@@ -3314,12 +3459,6 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
menubar_in_use = 0;
}
}
- else if (wParam == hourglass_timer)
- {
- KillTimer (hwnd, hourglass_timer);
- hourglass_timer = 0;
- w32_show_hourglass (x_window_to_frame (dpyinfo, hwnd));
- }
return 0;
case WM_NCACTIVATE:
@@ -3367,7 +3506,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Detect if message has already been deferred; in this case
we cannot return any sensible value to ignore this. */
if (find_deferred_msg (hwnd, msg) != NULL)
- abort ();
+ emacs_abort ();
menubar_in_use = 1;
@@ -3817,6 +3956,9 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
return retval;
}
+ case WM_EMACS_FILENOTIFY:
+ my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+ return 1;
default:
/* Check for messages registered at runtime. */
@@ -3842,7 +3984,7 @@ my_create_window (struct frame * f)
MSG msg;
if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
- abort ();
+ emacs_abort ();
GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
}
@@ -3897,7 +4039,7 @@ my_create_tip_window (struct frame *f)
static void
w32_window (struct frame *f, long window_prompting, int minibuffer_only)
{
- BLOCK_INPUT;
+ block_input ();
/* Use the resource name as the top-level window name
for looking up resources. Make a non-Lisp copy
@@ -3929,7 +4071,7 @@ w32_window (struct frame *f, long window_prompting, int minibuffer_only)
x_set_name (f, name, explicit);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
initialize_frame_menubar (f);
@@ -3960,7 +4102,7 @@ x_icon (struct frame *f, Lisp_Object parms)
else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
error ("Both left and top icon corners of icon must be specified");
- BLOCK_INPUT;
+ block_input ();
if (! EQ (icon_x, Qunbound))
x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
@@ -3977,7 +4119,7 @@ x_icon (struct frame *f, Lisp_Object parms)
: f->name)));
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3986,7 +4128,7 @@ x_make_gc (struct frame *f)
{
XGCValues gc_values;
- BLOCK_INPUT;
+ block_input ();
/* Create the GC's of this frame.
Note that many default values are used. */
@@ -4006,7 +4148,7 @@ x_make_gc (struct frame *f)
f->output_data.w32->white_relief.gc = 0;
f->output_data.w32->black_relief.gc = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -4162,9 +4304,6 @@ This function is an internal primitive--use `make-frame' instead. */)
XSETFRAME (frame, f);
- /* Note that Windows does support scroll bars. */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-
/* By default, make scrollbars the system standard width. */
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
@@ -4352,9 +4491,9 @@ This function is an internal primitive--use `make-frame' instead. */)
/* 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;
+ block_input ();
x_wm_set_size_hint (f, window_prompting, 0);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Make the window appear on the frame and enable display, unless
the caller says not to. However, with explicit parent, Emacs
@@ -4535,22 +4674,14 @@ If omitted or nil, that stands for the selected frame's display. */)
(Lisp_Object display)
{
struct w32_display_info *dpyinfo = check_x_display_info (display);
- HDC hdc;
int cap;
- hdc = GetDC (dpyinfo->root_window);
- if (dpyinfo->has_palette)
- cap = GetDeviceCaps (hdc, SIZEPALETTE);
- else
- cap = GetDeviceCaps (hdc, NUMCOLORS);
-
- /* We force 24+ bit depths to 24-bit, both to prevent an overflow
- and because probably is more meaningful on Windows anyway */
- if (cap < 0)
- cap = 1 << min (dpyinfo->n_planes * dpyinfo->n_cbits, 24);
-
- ReleaseDC (dpyinfo->root_window, hdc);
+ /* Don't use NCOLORS: it returns incorrect results under remote
+ * desktop. We force 24+ bit depths to 24-bit, both to prevent an
+ * overflow and because probably is more meaningful on Windows
+ * anyway. */
+ cap = 1 << min (dpyinfo->n_planes * dpyinfo->n_cbits, 24);
return make_number (cap);
}
@@ -4692,6 +4823,37 @@ If omitted or nil, that stands for the selected frame's display. */)
{
return Qnil;
}
+
+DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
+ doc: /* Set the sound generated when the bell is rung.
+SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
+to use the corresponding system sound for the bell. The 'silent sound
+prevents Emacs from making any sound at all.
+SOUND is nil to use the normal beep. */)
+ (Lisp_Object sound)
+{
+ CHECK_SYMBOL (sound);
+
+ if (NILP (sound))
+ sound_type = 0xFFFFFFFF;
+ else if (EQ (sound, intern ("asterisk")))
+ sound_type = MB_ICONASTERISK;
+ else if (EQ (sound, intern ("exclamation")))
+ sound_type = MB_ICONEXCLAMATION;
+ else if (EQ (sound, intern ("hand")))
+ sound_type = MB_ICONHAND;
+ else if (EQ (sound, intern ("question")))
+ sound_type = MB_ICONQUESTION;
+ else if (EQ (sound, intern ("ok")))
+ sound_type = MB_OK;
+ else if (EQ (sound, intern ("silent")))
+ sound_type = MB_EMACS_SILENT;
+ else
+ sound_type = 0xFFFFFFFF;
+
+ return sound;
+}
+
int
x_pixel_width (register struct frame *f)
@@ -4706,18 +4868,6 @@ x_pixel_height (register struct frame *f)
}
int
-x_char_width (register struct frame *f)
-{
- return FRAME_COLUMN_WIDTH (f);
-}
-
-int
-x_char_height (register struct frame *f)
-{
- return FRAME_LINE_HEIGHT (f);
-}
-
-int
x_screen_planes (register struct frame *f)
{
return FRAME_W32_DISPLAY_INFO (f)->n_planes;
@@ -4773,12 +4923,21 @@ terminate Emacs if we can't open the connection.
unsigned char *xrm_option;
struct w32_display_info *dpyinfo;
+ CHECK_STRING (display);
+
+ /* Signal an error in order to encourage correct use from callers.
+ * If we ever support multiple window systems in the same Emacs,
+ * we'll need callers to be precise about what window system they
+ * want. */
+
+ if (strcmp (SSDATA (display), "w32") != 0)
+ error ("The name of the display in this Emacs must be \"w32\"");
+
/* If initialization has already been done, return now to avoid
overwriting critical parts of one_w32_display_info. */
if (w32_in_use)
return Qnil;
- CHECK_STRING (display);
if (! NILP (xrm_string))
CHECK_STRING (xrm_string);
@@ -4863,11 +5022,11 @@ If DISPLAY is nil, that stands for the selected frame's display. */)
if (dpyinfo->reference_count > 0)
error ("Display still has frames on it");
- BLOCK_INPUT;
+ block_input ();
x_destroy_all_bitmaps (dpyinfo);
x_delete_display (dpyinfo);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -4936,7 +5095,7 @@ FRAME. Default is to change on the edit X window. */)
CHECK_STRING (prop);
CHECK_STRING (value);
- BLOCK_INPUT;
+ block_input ();
prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
prop_atom, XA_STRING, 8, PropModeReplace,
@@ -4944,7 +5103,7 @@ FRAME. Default is to change on the edit X window. */)
/* Make sure the property is set when we return. */
XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
return value;
}
@@ -4960,13 +5119,13 @@ FRAME nil or omitted means use the selected frame. Value is PROP. */)
Atom prop_atom;
CHECK_STRING (prop);
- BLOCK_INPUT;
+ block_input ();
prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
/* Make sure the property is removed when we return. */
XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
return prop;
}
@@ -5002,7 +5161,7 @@ no value of TYPE (always string in the MS Windows case). */)
unsigned long actual_size, bytes_remaining;
CHECK_STRING (prop);
- BLOCK_INPUT;
+ block_input ();
prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
prop_atom, 0, 0, False, XA_STRING,
@@ -5027,7 +5186,7 @@ no value of TYPE (always string in the MS Windows case). */)
XFree (tmp_data);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return prop_value;
@@ -5041,66 +5200,50 @@ no value of TYPE (always string in the MS Windows case). */)
Busy cursor
***********************************************************************/
-/* Default number of seconds to wait before displaying an hourglass
- cursor. Duplicated from xdisp.c, but cannot use the version there
- due to lack of atimers on w32. */
-#define DEFAULT_HOURGLASS_DELAY 1
-
-/* Cancel a currently active hourglass timer, and start a new one. */
-
void
-start_hourglass (void)
+w32_note_current_window (void)
{
- DWORD delay;
- int secs, msecs = 0;
struct frame * f = SELECTED_FRAME ();
- /* No cursors on non GUI frames. */
if (!FRAME_W32_P (f))
return;
- cancel_hourglass ();
-
- if (INTEGERP (Vhourglass_delay)
- && XINT (Vhourglass_delay) > 0)
- secs = XFASTINT (Vhourglass_delay);
- else if (FLOATP (Vhourglass_delay)
- && XFLOAT_DATA (Vhourglass_delay) > 0)
- {
- Lisp_Object tem;
- tem = Ftruncate (Vhourglass_delay, Qnil);
- secs = XFASTINT (tem);
- msecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000;
- }
- else
- secs = DEFAULT_HOURGLASS_DELAY;
-
- delay = secs * 1000 + msecs;
hourglass_hwnd = FRAME_W32_WINDOW (f);
- hourglass_timer = SetTimer (hourglass_hwnd, HOURGLASS_ID, delay, NULL);
}
-
-/* Cancel the hourglass cursor timer if active, hide an hourglass
- cursor if shown. */
-
void
-cancel_hourglass (void)
+show_hourglass (struct atimer *timer)
{
- if (hourglass_timer)
- {
- KillTimer (hourglass_hwnd, hourglass_timer);
- hourglass_timer = 0;
- }
+ struct frame *f;
- if (hourglass_shown_p)
- w32_hide_hourglass ();
+ 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))
+ return;
+
+ w32_show_hourglass (f);
+ unblock_input ();
}
+void
+hide_hourglass (void)
+{
+ block_input ();
+ w32_hide_hourglass ();
+ unblock_input ();
+}
-/* Timer function of hourglass_timer.
- Display an hourglass cursor. Set the hourglass_p flag in display info
+/* Display an hourglass cursor. Set the hourglass_p flag in display info
to indicate that an hourglass cursor is shown. */
static void
@@ -5249,7 +5392,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
Finsert (1, &text);
set_buffer_internal_1 (old_buffer);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
record_unwind_protect (unwind_create_tip_frame, frame);
/* By setting the output method, we're essentially saying that
@@ -5350,9 +5492,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
f->left_fringe_width = 0;
f->right_fringe_width = 0;
- BLOCK_INPUT;
+ block_input ();
my_create_tip_window (f);
- UNBLOCK_INPUT;
+ unblock_input ();
x_make_gc (f);
@@ -5458,11 +5600,11 @@ compute_tip_xy (struct frame *f,
max_x = x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f));
max_y = x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f));
- BLOCK_INPUT;
+ block_input ();
GetCursorPos (&pt);
*root_x = pt.x;
*root_y = pt.y;
- UNBLOCK_INPUT;
+ unblock_input ();
/* If multiple monitor support is available, constrain the tip onto
the current monitor. This improves the above by allowing negative
@@ -5597,7 +5739,7 @@ Text larger than the specified size is clipped. */)
call1 (Qcancel_timer, timer);
}
- BLOCK_INPUT;
+ block_input ();
compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
@@ -5611,7 +5753,7 @@ Text larger than the specified size is clipped. */)
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- UNBLOCK_INPUT;
+ unblock_input ();
goto start_timer;
}
}
@@ -5638,7 +5780,7 @@ Text larger than the specified size is clipped. */)
/* Block input until the tip has been fully drawn, to avoid crashes
when drawing tips in menus. */
- BLOCK_INPUT;
+ block_input ();
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
@@ -5810,7 +5952,7 @@ Text larger than the specified size is clipped. */)
w->must_be_updated_p = 1;
update_single_window (w, 1);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Restore original current buffer. */
set_buffer_internal_1 (old_buffer);
@@ -5865,17 +6007,33 @@ Value is t if tooltip was open, nil otherwise. */)
File selection dialog
***********************************************************************/
+#define FILE_NAME_TEXT_FIELD edt1
+#define FILE_NAME_COMBO_BOX cmb13
+#define FILE_NAME_LIST lst1
+
+#ifdef NTGUI_UNICODE
+#define GUISTR(x) (L ## x)
+typedef wchar_t guichar_t;
+#else /* !NTGUI_UNICODE */
+#define GUISTR(x) x
+typedef char guichar_t;
+#endif /* NTGUI_UNICODE */
+
/* Callback for altering the behavior of the Open File dialog.
Makes the Filename text field contain "Current Directory" and be
read-only when "Directories" is selected in the filter. This
allows us to work around the fact that the standard Open File
dialog does not support directories. */
-static UINT CALLBACK
+static UINT_PTR CALLBACK
file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_NOTIFY)
{
- OFNOTIFY * notify = (OFNOTIFY *)lParam;
+#ifdef NTGUI_UNICODE
+ OFNOTIFYW * notify = (OFNOTIFYW *)lParam;
+#else /* !NTGUI_UNICODE */
+ OFNOTIFYA * notify = (OFNOTIFYA *)lParam;
+#endif /* NTGUI_UNICODE */
/* Detect when the Filter dropdown is changed. */
if (notify->hdr.code == CDN_TYPECHANGE
|| notify->hdr.code == CDN_INITDONE)
@@ -5903,7 +6061,7 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (notify->lpOFN->nFilterIndex == 2)
{
CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD,
- "Current Directory");
+ GUISTR ("Current Directory"));
EnableWindow (edit_control, FALSE);
/* Note that at least on Windows 7, the above call to EnableWindow
disables the window that would ordinarily have focus. If we
@@ -5919,7 +6077,8 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Don't override default filename on init done. */
if (notify->hdr.code == CDN_TYPECHANGE)
CommDlg_OpenSave_SetControlText (dialog,
- FILE_NAME_TEXT_FIELD, "");
+ FILE_NAME_TEXT_FIELD,
+ GUISTR (""));
EnableWindow (edit_control, TRUE);
}
}
@@ -5927,158 +6086,216 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
return 0;
}
-/* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility)
- we end up with the old file dialogs. Define a big enough struct for the
- new dialog to trick GetOpenFileName into giving us the new dialogs on
- Windows 2000 and XP. */
-typedef struct
-{
- OPENFILENAME real_details;
- void * pReserved;
- DWORD dwReserved;
- DWORD FlagsEx;
-} NEWOPENFILENAME;
-
-
DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
doc: /* Read file name, prompting with PROMPT in directory DIR.
Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
selection box, if specified. If MUSTMATCH is non-nil, the returned file
or directory must exist.
-This function is only defined on MS Windows, and X Windows with the
+This function is only defined on NS, MS Windows, and X Windows with the
Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
(Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
{
+ /* Filter index: 1: All Files, 2: Directories only */
+ static const guichar_t filter[] =
+ GUISTR ("All Files (*.*)\0*.*\0Directories\0*|*\0");
+
+ Lisp_Object filename = default_filename;
struct frame *f = SELECTED_FRAME ();
- Lisp_Object file = Qnil;
- ptrdiff_t count = SPECPDL_INDEX ();
+ BOOL file_opened = FALSE;
+ Lisp_Object orig_dir = dir;
+ Lisp_Object orig_prompt = prompt;
+
+ /* If we compile with _WIN32_WINNT set to 0x0400 (for NT4
+ compatibility) we end up with the old file dialogs. Define a big
+ enough struct for the new dialog to trick GetOpenFileName into
+ giving us the new dialogs on newer versions of Windows. */
+ struct {
+#ifdef NTGUI_UNICODE
+ OPENFILENAMEW details;
+#else /* !NTGUI_UNICODE */
+ OPENFILENAMEA details;
+#endif /* NTGUI_UNICODE */
+
+#if _WIN32_WINNT < 0x500 /* < win2k */
+ PVOID pvReserved;
+ DWORD dwReserved;
+ DWORD FlagsEx;
+#endif /* < win2k */
+ } new_file_details;
+
+#ifdef NTGUI_UNICODE
+ wchar_t filename_buf[32*1024 + 1]; // NT kernel maximum
+ OPENFILENAMEW * file_details = &new_file_details.details;
+#else /* not NTGUI_UNICODE */
+ char filename_buf[MAX_PATH + 1];
+ OPENFILENAMEA * file_details = &new_file_details.details;
+#endif /* NTGUI_UNICODE */
+
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
- char filename[MAX_PATH + 1];
- char init_dir[MAX_PATH + 1];
- int default_filter_index = 1; /* 1: All Files, 2: Directories only */
-
- GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
- CHECK_STRING (prompt);
- CHECK_STRING (dir);
-
- /* Create the dialog with PROMPT as title, using DIR as initial
- directory and using "*" as pattern. */
- dir = Fexpand_file_name (dir, Qnil);
- strncpy (init_dir, SDATA (ENCODE_FILE (dir)), MAX_PATH);
- init_dir[MAX_PATH] = '\0';
- unixtodos_filename (init_dir);
-
- if (STRINGP (default_filename))
- {
- char *file_name_only;
- char *full_path_name = SDATA (ENCODE_FILE (default_filename));
+ GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, filename);
- unixtodos_filename (full_path_name);
+ {
+ struct gcpro gcpro1, gcpro2;
+ GCPRO2 (orig_dir, orig_prompt); /* There is no GCPRON, N>6. */
- file_name_only = strrchr (full_path_name, '\\');
- if (!file_name_only)
- file_name_only = full_path_name;
- else
- file_name_only++;
+ /* Note: under NTGUI_UNICODE, we do _NOT_ use ENCODE_FILE: the
+ system file encoding expected by the platform APIs (e.g. Cygwin's
+ POSIX implementation) may not be the same as the encoding expected
+ by the Windows "ANSI" APIs! */
- strncpy (filename, file_name_only, MAX_PATH);
- filename[MAX_PATH] = '\0';
- }
- else
- filename[0] = '\0';
+ CHECK_STRING (prompt);
+ CHECK_STRING (dir);
- /* The code in file_dialog_callback that attempts to set the text
- of the file name edit window when handling the CDN_INITDONE
- WM_NOTIFY message does not work. Setting filename to "Current
- Directory" in the only_dir_p case here does work however. */
- if (filename[0] == 0 && ! NILP (only_dir_p))
- strcpy (filename, "Current Directory");
+ dir = Fexpand_file_name (dir, Qnil);
- {
- NEWOPENFILENAME new_file_details;
- BOOL file_opened = FALSE;
- OPENFILENAME * file_details = &new_file_details.real_details;
+ if (STRINGP (filename))
+ filename = Ffile_name_nondirectory (filename);
+ else
+ filename = empty_unibyte_string;
- /* Prevent redisplay. */
- specbind (Qinhibit_redisplay, Qt);
- BLOCK_INPUT;
+#ifdef CYGWIN
+ dir = Fcygwin_convert_file_name_to_windows (dir, Qt);
+ if (SCHARS (filename) > 0)
+ filename = Fcygwin_convert_file_name_to_windows (filename, Qnil);
+#endif
+ CHECK_STRING (dir);
+ CHECK_STRING (filename);
+
+ /* The code in file_dialog_callback that attempts to set the text
+ of the file name edit window when handling the CDN_INITDONE
+ WM_NOTIFY message does not work. Setting filename to "Current
+ Directory" in the only_dir_p case here does work however. */
+ if (SCHARS (filename) == 0 && ! NILP (only_dir_p))
+ filename = build_string ("Current Directory");
+
+ /* Convert the values we've computed so far to system form. */
+#ifdef NTGUI_UNICODE
+ to_unicode (prompt, &prompt);
+ to_unicode (dir, &dir);
+ to_unicode (filename, &filename);
+#else /* !NTGUI_UNICODE */
+ prompt = ENCODE_FILE (prompt);
+ dir = ENCODE_FILE (dir);
+ filename = ENCODE_FILE (filename);
+
+ /* We modify these in-place, so make copies for safety. */
+ dir = Fcopy_sequence (dir);
+ unixtodos_filename (SDATA (dir));
+ filename = Fcopy_sequence (filename);
+ unixtodos_filename (SDATA (filename));
+#endif /* NTGUI_UNICODE */
+
+ /* Fill in the structure for the call to GetOpenFileName below.
+ For NTGUI_UNICODE builds (which run only on NT), we just use
+ the actual size of the structure. For non-NTGUI_UNICODE
+ builds, we tell the OS we're using an old version of the
+ structure if the OS isn't new enough to support the newer
+ version. */
memset (&new_file_details, 0, sizeof (new_file_details));
- /* Apparently NT4 crashes if you give it an unexpected size.
- I'm not sure about Windows 9x, so play it safe. */
+
if (w32_major_version > 4 && w32_major_version < 95)
- file_details->lStructSize = sizeof (NEWOPENFILENAME);
+ file_details->lStructSize = sizeof (new_file_details);
else
- file_details->lStructSize = sizeof (OPENFILENAME);
+ file_details->lStructSize = sizeof (*file_details);
+
+ /* Set up the inout parameter for the selected file name. */
+ if (SBYTES (filename) + 1 > sizeof (filename_buf))
+ report_file_error ("filename too long", default_filename);
+
+ memcpy (filename_buf, SDATA (filename), SBYTES (filename) + 1);
+ file_details->lpstrFile = filename_buf;
+ file_details->nMaxFile = sizeof (filename_buf) / sizeof (*filename_buf);
file_details->hwndOwner = FRAME_W32_WINDOW (f);
/* Undocumented Bug in Common File Dialog:
If a filter is not specified, shell links are not resolved. */
- file_details->lpstrFilter = "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
- file_details->lpstrFile = filename;
- file_details->nMaxFile = sizeof (filename);
- file_details->lpstrInitialDir = init_dir;
- file_details->lpstrTitle = SDATA (prompt);
-
- if (! NILP (only_dir_p))
- default_filter_index = 2;
-
- file_details->nFilterIndex = default_filter_index;
-
+ file_details->lpstrFilter = filter;
+ file_details->lpstrInitialDir = (guichar_t*) SDATA (dir);
+ file_details->lpstrTitle = (guichar_t*) SDATA (prompt);
+ file_details->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
file_details->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
- | OFN_EXPLORER | OFN_ENABLEHOOK);
+ | OFN_EXPLORER | OFN_ENABLEHOOK);
+
if (!NILP (mustmatch))
{
- /* Require that the path to the parent directory exists. */
- file_details->Flags |= OFN_PATHMUSTEXIST;
- /* If we are looking for a file, require that it exists. */
- if (NILP (only_dir_p))
- file_details->Flags |= OFN_FILEMUSTEXIST;
+ /* Require that the path to the parent directory exists. */
+ file_details->Flags |= OFN_PATHMUSTEXIST;
+ /* If we are looking for a file, require that it exists. */
+ if (NILP (only_dir_p))
+ file_details->Flags |= OFN_FILEMUSTEXIST;
}
- file_details->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
-
- file_opened = GetOpenFileName (file_details);
-
- UNBLOCK_INPUT;
+ {
+ int count = SPECPDL_INDEX ();
+ /* Prevent redisplay. */
+ specbind (Qinhibit_redisplay, Qt);
+ block_input ();
+ file_details->lpfnHook = file_dialog_callback;
+
+#ifdef NTGUI_UNICODE
+ file_opened = GetOpenFileNameW (file_details);
+#else /* !NTGUI_UNICODE */
+ file_opened = GetOpenFileNameA (file_details);
+#endif /* NTGUI_UNICODE */
+ unblock_input ();
+ unbind_to (count, Qnil);
+ }
if (file_opened)
{
- dostounix_filename (filename);
-
- if (file_details->nFilterIndex == 2)
- {
- /* "Directories" selected - strip dummy file name. */
- char * last = strrchr (filename, '/');
- *last = '\0';
- }
-
- file = DECODE_FILE (build_string (filename));
+ /* Get an Emacs string from the value Windows gave us. */
+#ifdef NTGUI_UNICODE
+ filename = from_unicode (
+ make_unibyte_string (
+ (char*) filename_buf,
+ /* we get one of the two final 0 bytes for free. */
+ 1 + sizeof (wchar_t) * wcslen (filename_buf)));
+#else /* !NTGUI_UNICODE */
+ dostounix_filename (filename_buf);
+ filename = DECODE_FILE (build_string (filename_buf));
+#endif /* NTGUI_UNICODE */
+
+#ifdef CYGWIN
+ filename = Fcygwin_convert_file_name_from_windows (filename, Qt);
+#endif /* CYGWIN */
+
+ /* Strip the dummy filename off the end of the string if we
+ added it to select a directory. */
+ if (file_details->nFilterIndex == 2)
+ {
+ filename = Ffile_name_directory (filename);
+ }
}
/* User canceled the dialog without making a selection. */
else if (!CommDlgExtendedError ())
- file = Qnil;
+ filename = Qnil;
/* An error occurred, fallback on reading from the mini-buffer. */
else
- file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch, dir, Qfile_name_history,
- default_filename, Qnil);
+ filename = Fcompleting_read (
+ orig_prompt,
+ intern ("read-file-name-internal"),
+ orig_dir,
+ mustmatch,
+ orig_dir,
+ Qfile_name_history,
+ default_filename,
+ Qnil);
- file = unbind_to (count, file);
+ UNGCPRO;
}
- UNGCPRO;
-
/* Make "Cancel" equivalent to C-g. */
- if (NILP (file))
+ if (NILP (filename))
Fsignal (Qquit, Qnil);
- return unbind_to (count, file);
+ RETURN_UNGCPRO (filename);
}
-
+
+#ifdef WINDOWSNT
/* Moving files to the system recycle bin.
Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
@@ -6132,6 +6349,8 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
return Qnil;
}
+#endif /* WINDOWSNT */
+
/***********************************************************************
w32 specialized functions
@@ -6287,7 +6506,7 @@ w32_parse_hot_key (Lisp_Object key)
lisp_modifiers = XINT (Fcar (Fcdr (c)));
c = Fcar (c);
if (!SYMBOLP (c))
- abort ();
+ emacs_abort ();
vk_code = lookup_vk_code (SDATA (SYMBOL_NAME (c)));
}
else if (INTEGERP (c))
@@ -6549,7 +6768,7 @@ The following %-sequences are provided:
else
{
char buffer[16];
- _snprintf (buffer, 16, "%d", system_status.BatteryLifePercent);
+ snprintf (buffer, 16, "%d", system_status.BatteryLifePercent);
load_percentage = build_string (buffer);
}
@@ -6560,18 +6779,18 @@ The following %-sequences are provided:
long m;
float h;
char buffer[16];
- _snprintf (buffer, 16, "%ld", seconds_left);
+ snprintf (buffer, 16, "%ld", seconds_left);
seconds = build_string (buffer);
m = seconds_left / 60;
- _snprintf (buffer, 16, "%ld", m);
+ snprintf (buffer, 16, "%ld", m);
minutes = build_string (buffer);
h = seconds_left / 3600.0;
- _snprintf (buffer, 16, "%3.1f", h);
+ snprintf (buffer, 16, "%3.1f", h);
hours = build_string (buffer);
- _snprintf (buffer, 16, "%ld:%02ld", m / 60, m % 60);
+ snprintf (buffer, 16, "%ld:%02ld", m / 60, m % 60);
remain = build_string (buffer);
}
@@ -6733,10 +6952,10 @@ DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
{
/* a remote printer */
if (*ppi2->pServerName == '\\')
- _snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName,
+ snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName,
ppi2->pShareName);
else
- _snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName,
+ snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName,
ppi2->pShareName);
pname_buf[sizeof (pname_buf) - 1] = '\0';
}
@@ -6755,6 +6974,297 @@ DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
return build_string (pname_buf);
}
+
+/* Equivalent of strerror for W32 error codes. */
+char *
+w32_strerror (int error_no)
+{
+ static char buf[500];
+ DWORD ret;
+
+ if (error_no == 0)
+ error_no = GetLastError ();
+
+ ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ error_no,
+ 0, /* choose most suitable language */
+ buf, sizeof (buf), NULL);
+
+ while (ret > 0 && (buf[ret - 1] == '\n' ||
+ buf[ret - 1] == '\r' ))
+ --ret;
+ buf[ret] = '\0';
+ if (!ret)
+ sprintf (buf, "w32 error %u", error_no);
+
+ return buf;
+}
+
+/* For convenience when debugging. (You cannot call GetLastError
+ directly from GDB: it will crash, because it uses the __stdcall
+ calling convention, not the _cdecl convention assumed by GDB.) */
+DWORD
+w32_last_error (void)
+{
+ return GetLastError ();
+}
+
+/* Cache information describing the NT system for later use. */
+void
+cache_system_info (void)
+{
+ union
+ {
+ struct info
+ {
+ char major;
+ char minor;
+ short platform;
+ } info;
+ DWORD data;
+ } version;
+
+ /* Cache the module handle of Emacs itself. */
+ hinst = GetModuleHandle (NULL);
+
+ /* Cache the version of the operating system. */
+ version.data = GetVersion ();
+ w32_major_version = version.info.major;
+ w32_minor_version = version.info.minor;
+
+ if (version.info.platform & 0x8000)
+ os_subtype = OS_9X;
+ else
+ os_subtype = OS_NT;
+
+ /* Cache page size, allocation unit, processor type, etc. */
+ GetSystemInfo (&sysinfo_cache);
+ syspage_mask = (DWORD_PTR)sysinfo_cache.dwPageSize - 1;
+
+ /* Cache os info. */
+ osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ GetVersionEx (&osinfo_cache);
+
+ w32_build_number = osinfo_cache.dwBuildNumber;
+ if (os_subtype == OS_9X)
+ w32_build_number &= 0xffff;
+
+ w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
+}
+
+#ifdef EMACSDEBUG
+void
+_DebPrint (const char *fmt, ...)
+{
+ char buf[1024];
+ va_list args;
+
+ va_start (args, fmt);
+ vsprintf (buf, fmt, args);
+ va_end (args);
+#if CYGWIN
+ fprintf (stderr, "%s", buf);
+#endif
+ OutputDebugString (buf);
+}
+#endif
+
+int
+w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
+{
+ int cur_state = (GetKeyState (vk_code) & 1);
+
+ if (NILP (new_state)
+ || (NUMBERP (new_state)
+ && ((XUINT (new_state)) & 1) != cur_state))
+ {
+#ifdef WINDOWSNT
+ faked_key = vk_code;
+#endif /* WINDOWSNT */
+
+ keybd_event ((BYTE) vk_code,
+ (BYTE) MapVirtualKey (vk_code, 0),
+ KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+ keybd_event ((BYTE) vk_code,
+ (BYTE) MapVirtualKey (vk_code, 0),
+ KEYEVENTF_EXTENDEDKEY | 0, 0);
+ keybd_event ((BYTE) vk_code,
+ (BYTE) MapVirtualKey (vk_code, 0),
+ KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+ cur_state = !cur_state;
+ }
+
+ return cur_state;
+}
+
+/* Translate console modifiers to emacs modifiers.
+ German keyboard support (Kai Morgan Zeise 2/18/95). */
+int
+w32_kbd_mods_to_emacs (DWORD mods, WORD key)
+{
+ int retval = 0;
+
+ /* If we recognize right-alt and left-ctrl as AltGr, and it has been
+ pressed, first remove those modifiers. */
+ if (!NILP (Vw32_recognize_altgr)
+ && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
+ == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
+ mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
+
+ if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
+ retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
+
+ if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
+ {
+ retval |= ctrl_modifier;
+ if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
+ == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
+ retval |= meta_modifier;
+ }
+
+ if (mods & LEFT_WIN_PRESSED)
+ retval |= w32_key_to_modifier (VK_LWIN);
+ if (mods & RIGHT_WIN_PRESSED)
+ retval |= w32_key_to_modifier (VK_RWIN);
+ if (mods & APPS_PRESSED)
+ retval |= w32_key_to_modifier (VK_APPS);
+ if (mods & SCROLLLOCK_ON)
+ retval |= w32_key_to_modifier (VK_SCROLL);
+
+ /* Just in case someone wanted the original behavior, make it
+ optional by setting w32-capslock-is-shiftlock to t. */
+ if (NILP (Vw32_capslock_is_shiftlock)
+ /* Keys that should _not_ be affected by CapsLock. */
+ && ( (key == VK_BACK)
+ || (key == VK_TAB)
+ || (key == VK_CLEAR)
+ || (key == VK_RETURN)
+ || (key == VK_ESCAPE)
+ || ((key >= VK_SPACE) && (key <= VK_HELP))
+ || ((key >= VK_NUMPAD0) && (key <= VK_F24))
+ || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
+ ))
+ {
+ /* Only consider shift state. */
+ if ((mods & SHIFT_PRESSED) != 0)
+ retval |= shift_modifier;
+ }
+ else
+ {
+ /* Ignore CapsLock state if not enabled. */
+ if (NILP (Vw32_enable_caps_lock))
+ mods &= ~CAPSLOCK_ON;
+ if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
+ retval |= shift_modifier;
+ }
+
+ return retval;
+}
+
+/* The return code indicates key code size. cpID is the codepage to
+ use for translation to Unicode; -1 means use the current console
+ input codepage. */
+int
+w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
+{
+ unsigned int key_code = event->wVirtualKeyCode;
+ unsigned int mods = event->dwControlKeyState;
+ BYTE keystate[256];
+ static BYTE ansi_code[4];
+ static int isdead = 0;
+
+ if (isdead == 2)
+ {
+ event->uChar.AsciiChar = ansi_code[2];
+ isdead = 0;
+ return 1;
+ }
+ if (event->uChar.AsciiChar != 0)
+ return 1;
+
+ memset (keystate, 0, sizeof (keystate));
+ keystate[key_code] = 0x80;
+ if (mods & SHIFT_PRESSED)
+ keystate[VK_SHIFT] = 0x80;
+ if (mods & CAPSLOCK_ON)
+ keystate[VK_CAPITAL] = 1;
+ /* If we recognize right-alt and left-ctrl as AltGr, set the key
+ states accordingly before invoking ToAscii. */
+ if (!NILP (Vw32_recognize_altgr)
+ && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
+ {
+ keystate[VK_CONTROL] = 0x80;
+ keystate[VK_LCONTROL] = 0x80;
+ keystate[VK_MENU] = 0x80;
+ keystate[VK_RMENU] = 0x80;
+ }
+
+#if 0
+ /* Because of an OS bug, ToAscii corrupts the stack when called to
+ convert a dead key in console mode on NT4. Unfortunately, trying
+ to check for dead keys using MapVirtualKey doesn't work either -
+ these functions apparently use internal information about keyboard
+ layout which doesn't get properly updated in console programs when
+ changing layout (though apparently it gets partly updated,
+ otherwise ToAscii wouldn't crash). */
+ if (is_dead_key (event->wVirtualKeyCode))
+ return 0;
+#endif
+
+ /* On NT, call ToUnicode instead and then convert to the current
+ console input codepage. */
+ if (os_subtype == OS_NT)
+ {
+ WCHAR buf[128];
+
+ isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
+ keystate, buf, 128, 0);
+ if (isdead > 0)
+ {
+ /* When we are called from the GUI message processing code,
+ we are passed the current keyboard codepage, a positive
+ number, to use below. */
+ if (cpId == -1)
+ cpId = GetConsoleCP ();
+
+ event->uChar.UnicodeChar = buf[isdead - 1];
+ isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
+ ansi_code, 4, NULL, NULL);
+ }
+ else
+ isdead = 0;
+ }
+ else
+ {
+ isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
+ keystate, (LPWORD) ansi_code, 0);
+ }
+
+ if (isdead == 0)
+ return 0;
+ event->uChar.AsciiChar = ansi_code[0];
+ return isdead;
+}
+
+
+void
+w32_sys_ring_bell (struct frame *f)
+{
+ if (sound_type == 0xFFFFFFFF)
+ {
+ Beep (666, 100);
+ }
+ else if (sound_type == MB_EMACS_SILENT)
+ {
+ /* Do nothing. */
+ }
+ else
+ MessageBeep (sound_type);
+}
+
+
/***********************************************************************
Initialization
***********************************************************************/
@@ -7121,11 +7631,10 @@ only be necessary if the default setting causes problems. */);
defsubr (&Sfile_system_info);
defsubr (&Sdefault_printer_name);
+ defsubr (&Sset_message_beep);
check_window_system_func = check_w32;
-
- hourglass_timer = 0;
hourglass_hwnd = NULL;
defsubr (&Sx_show_tip);
@@ -7139,7 +7648,9 @@ only be necessary if the default setting causes problems. */);
staticpro (&last_show_tip_args);
defsubr (&Sx_file_dialog);
+#ifdef WINDOWSNT
defsubr (&Ssystem_move_file_to_trash);
+#endif
}
@@ -7194,16 +7705,41 @@ globals_of_w32fns (void)
syms_of_w32uniscribe ();
}
-#undef abort
+typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
+ PULONG);
+
+#define BACKTRACE_LIMIT_MAX 62
+
+int
+w32_backtrace (void **buffer, int limit)
+{
+ static CaptureStackBackTrace_proc s_pfn_CaptureStackBackTrace = NULL;
+ HMODULE hm_kernel32 = NULL;
+
+ if (!s_pfn_CaptureStackBackTrace)
+ {
+ hm_kernel32 = LoadLibrary ("Kernel32.dll");
+ s_pfn_CaptureStackBackTrace =
+ (CaptureStackBackTrace_proc) GetProcAddress (hm_kernel32,
+ "RtlCaptureStackBackTrace");
+ }
+ if (s_pfn_CaptureStackBackTrace)
+ return s_pfn_CaptureStackBackTrace (0, min (BACKTRACE_LIMIT_MAX, limit),
+ buffer, NULL);
+ return 0;
+}
void
-w32_abort (void)
+emacs_abort (void)
{
int button;
button = MessageBox (NULL,
"A fatal error has occurred!\n\n"
"Would you like to attach a debugger?\n\n"
- "Select YES to debug, NO to abort Emacs"
+ "Select:\n"
+ "YES -- to debug Emacs, or\n"
+ "NO -- to abort Emacs and produce a backtrace\n"
+ " (emacs_backtrace.txt in current directory)."
#if __GNUC__
"\n\n(type \"gdb -p <emacs-PID>\" and\n"
"\"continue\" inside GDB before clicking YES.)"
@@ -7218,14 +7754,59 @@ w32_abort (void)
exit (2); /* tell the compiler we will never return */
case IDNO:
default:
- abort ();
- break;
- }
-}
+ {
+ void *stack[BACKTRACE_LIMIT_MAX + 1];
+ int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1);
-/* For convenience when debugging. */
-int
-w32_last_error (void)
-{
- return GetLastError ();
+ if (i)
+ {
+#ifdef CYGWIN
+ int stderr_fd = 2;
+#else
+ HANDLE errout = GetStdHandle (STD_ERROR_HANDLE);
+ int stderr_fd = -1;
+#endif
+ int errfile_fd = -1;
+ int j;
+
+#ifndef CYGWIN
+ if (errout && errout != INVALID_HANDLE_VALUE)
+ stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY);
+#endif
+ if (stderr_fd >= 0)
+ write (stderr_fd, "\r\nBacktrace:\r\n", 14);
+ errfile_fd = _open ("emacs_backtrace.txt", O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
+ if (errfile_fd >= 0)
+ {
+ lseek (errfile_fd, 0L, SEEK_END);
+ write (errfile_fd, "\r\nBacktrace:\r\n", 14);
+ }
+
+ for (j = 0; j < i; j++)
+ {
+ char buf[INT_BUFSIZE_BOUND (void *)];
+
+ /* stack[] gives the return addresses, whereas we want
+ the address of the call, so decrease each address
+ by approximate size of 1 CALL instruction. */
+ sprintf (buf, "0x%p\r\n", (char *)stack[j] - sizeof(void *));
+ if (stderr_fd >= 0)
+ write (stderr_fd, buf, strlen (buf));
+ if (errfile_fd >= 0)
+ write (errfile_fd, buf, strlen (buf));
+ }
+ if (i == BACKTRACE_LIMIT_MAX)
+ {
+ if (stderr_fd >= 0)
+ write (stderr_fd, "...\r\n", 5);
+ if (errfile_fd >= 0)
+ write (errfile_fd, "...\r\n", 5);
+ }
+ if (errfile_fd >= 0)
+ close (errfile_fd);
+ }
+ abort ();
+ break;
+ }
+ }
}
diff --git a/src/w32font.c b/src/w32font.c
index cfd453282dd..d7d25d89939 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -18,10 +18,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <windows.h>
+#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <commdlg.h>
-#include <setjmp.h>
#include "lisp.h"
#include "w32term.h"
@@ -635,9 +635,9 @@ w32font_text_extents (struct font *font, unsigned *code,
/* w32 implementation of draw for font backend.
Optional.
Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
- position of frame F with S->FACE and S->GC. If WITH_BACKGROUND
- is nonzero, fill the background in advance. It is assured that
- WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars).
+ position of frame F with S->FACE and S->GC. If WITH_BACKGROUND,
+ fill the background in advance. It is assured that WITH_BACKGROUND
+ is false when (FROM > 0 || TO < S->nchars).
TODO: Currently this assumes that the colors and fonts are already
set in the DC. This seems to be true now, but maybe only due to
@@ -647,7 +647,7 @@ w32font_text_extents (struct font *font, unsigned *code,
int
w32font_draw (struct glyph_string *s, int from, int to,
- int x, int y, int with_background)
+ int x, int y, bool with_background)
{
UINT options;
HRGN orig_clip = NULL;
@@ -804,7 +804,7 @@ static int
w32font_otf_drive (struct font *font, Lisp_Object features,
Lisp_Object gstring_in, int from, int to,
Lisp_Object gstring_out, int idx,
- int alternate_subst);
+ bool alternate_subst);
*/
/* Internal implementation of w32font_list.
@@ -987,7 +987,6 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
font->space_width = font->average_width = w32_font->metrics.tmAveCharWidth;
font->vertical_centering = 0;
- font->encoding_type = 0;
font->baseline_offset = 0;
font->relative_compose = 0;
font->default_ascent = w32_font->metrics.tmAscent;
@@ -1436,6 +1435,9 @@ w32font_coverage_ok (FONTSIGNATURE * coverage, BYTE charset)
return 1;
}
+#ifndef WINDOWSNT
+#define _strlwr strlwr
+#endif /* !WINDOWSNT */
static int
check_face_name (LOGFONT *font, char *full_name)
diff --git a/src/w32font.h b/src/w32font.h
index a29ddbe778c..8fa00a9b524 100644
--- a/src/w32font.h
+++ b/src/w32font.h
@@ -77,7 +77,7 @@ int w32font_has_char (Lisp_Object entity, int c);
int 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, int with_background);
+ int x, int y, bool with_background);
int uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec);
diff --git a/src/w32gui.h b/src/w32gui.h
index 1ea185bfaa1..fe2bb2334b5 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -79,9 +79,6 @@ typedef struct _XImage
#define FACE_DEFAULT (~0)
extern HINSTANCE hinst;
-extern HINSTANCE hprevinst;
-extern LPSTR lpCmdLine;
-extern int nCmdShow;
/* Bit Gravity */
@@ -118,9 +115,6 @@ extern int nCmdShow;
#define PBaseSize (1L << 8) /* program specified base for incrementing */
#define PWinGravity (1L << 9) /* program specified window gravity */
-extern int XParseGeometry (char *, int *, int *, unsigned *, unsigned *);
-
-
typedef struct {
int x, y;
unsigned width, height;
diff --git a/src/w32heap.c b/src/w32heap.c
index 26cc9aa0a0f..311e1064434 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -22,66 +22,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
+#include "w32common.h"
#include "w32heap.h"
#include "lisp.h" /* for VALMASK */
-#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD)(rva) + (DWORD)GetModuleHandle (NULL)))
-
-/* This gives us the page size and the size of the allocation unit on NT. */
-SYSTEM_INFO sysinfo_cache;
-
-/* This gives us version, build, and platform identification. */
-OSVERSIONINFO osinfo_cache;
-
-unsigned long syspage_mask = 0;
-
-/* The major and minor versions of NT. */
-int w32_major_version;
-int w32_minor_version;
-int w32_build_number;
-
-/* Distinguish between Windows NT and Windows 95. */
-int os_subtype;
-
-/* Cache information describing the NT system for later use. */
-void
-cache_system_info (void)
-{
- union
- {
- struct info
- {
- char major;
- char minor;
- short platform;
- } info;
- DWORD data;
- } version;
-
- /* Cache the version of the operating system. */
- version.data = GetVersion ();
- w32_major_version = version.info.major;
- w32_minor_version = version.info.minor;
-
- if (version.info.platform & 0x8000)
- os_subtype = OS_9X;
- else
- os_subtype = OS_NT;
-
- /* Cache page size, allocation unit, processor type, etc. */
- GetSystemInfo (&sysinfo_cache);
- syspage_mask = sysinfo_cache.dwPageSize - 1;
-
- /* Cache os info. */
- osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- GetVersionEx (&osinfo_cache);
-
- w32_build_number = osinfo_cache.dwBuildNumber;
- if (os_subtype == OS_9X)
- w32_build_number &= 0xffff;
-}
+#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD_PTR)(rva) + (DWORD_PTR)GetModuleHandle (NULL)))
/* Emulate getpagesize. */
int
@@ -98,7 +44,7 @@ PIMAGE_SECTION_HEADER preload_heap_section;
unsigned char *data_region_base = NULL;
unsigned char *data_region_end = NULL;
unsigned char *real_data_region_end = NULL;
-unsigned long reserved_heap_size = 0;
+size_t reserved_heap_size = 0;
/* The start of the data segment. */
unsigned char *
@@ -122,16 +68,20 @@ allocate_heap (void)
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. */
- unsigned long base =
+ DWORD_PTR base =
ROUND_UP ((RVA_TO_PTR (preload_heap_section->VirtualAddress)
+ preload_heap_section->Misc.VirtualSize),
get_allocation_unit ());
- unsigned long end = 1 << VALBITS; /* 256MB */
+ DWORD_PTR end = ((unsigned __int64)1) << VALBITS; /* 256MB */
void *ptr = NULL;
while (!ptr && (base < end))
{
+#ifdef _WIN64
+ reserved_heap_size = min(end - base, 0x4000000000i64); /* Limit to 256Gb */
+#else
reserved_heap_size = end - base;
+#endif
ptr = VirtualAlloc ((void *) base,
get_reserved_heap_size (),
MEM_RESERVE,
@@ -145,7 +95,11 @@ allocate_heap (void)
static char *
allocate_heap (void)
{
- unsigned long size = 0x80000000; /* start by asking for 2GB */
+#ifdef _WIN64
+ size_t size = 0x4000000000i64; /* start by asking for 32GB */
+#else
+ size_t size = 0x80000000; /* start by asking for 2GB */
+#endif
void *ptr = NULL;
while (!ptr && size > 0x00100000)
@@ -167,17 +121,17 @@ allocate_heap (void)
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 (unsigned long increment)
+sbrk (ptrdiff_t increment)
{
void *result;
- long size = (long) increment;
+ ptrdiff_t size = increment;
result = data_region_end;
/* If size is negative, shrink the heap by decommitting pages. */
if (size < 0)
{
- int new_size;
+ ptrdiff_t new_size;
unsigned char *new_data_region_end;
size = -size;
@@ -190,7 +144,7 @@ sbrk (unsigned long increment)
partial deallocation [cga]. */
new_data_region_end = (data_region_end - size);
new_data_region_end = (unsigned char *)
- ((long) (new_data_region_end + syspage_mask) & ~syspage_mask);
+ ((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)
@@ -221,7 +175,7 @@ sbrk (unsigned long increment)
/* We really only commit full pages, so record where
the real end of committed memory is [cga]. */
real_data_region_end = (unsigned char *)
- ((long) (data_region_end + syspage_mask) & ~syspage_mask);
+ ((DWORD_PTR) (data_region_end + syspage_mask) & ~syspage_mask);
}
return result;
@@ -246,7 +200,7 @@ init_heap (void)
PIMAGE_NT_HEADERS nt_header;
dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0);
- nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
+ nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
dos_header->e_lfanew);
preload_heap_section = find_section ("EMHEAP", nt_header);
@@ -262,7 +216,7 @@ init_heap (void)
#if !USE_LSB_TAG
/* Ensure that the addresses don't use the upper tag bits since
the Lisp type goes there. */
- if (((unsigned long) data_region_base & ~VALMASK) != 0)
+ if (((DWORD_PTR) data_region_base & ~VALMASK) != 0)
{
printf ("Error: The heap was allocated in upper memory.\n");
exit (1);
@@ -285,13 +239,13 @@ init_heap (void)
/* Round the heap up to the given alignment. */
void
-round_heap (unsigned long align)
+round_heap (size_t align)
{
- unsigned long needs_to_be;
- unsigned long need_to_alloc;
+ DWORD_PTR needs_to_be;
+ DWORD_PTR need_to_alloc;
- needs_to_be = (unsigned long) ROUND_UP (get_heap_end (), align);
- need_to_alloc = needs_to_be - (unsigned long) get_heap_end ();
+ needs_to_be = (DWORD_PTR) ROUND_UP (get_heap_end (), align);
+ need_to_alloc = needs_to_be - (DWORD_PTR) get_heap_end ();
if (need_to_alloc)
sbrk (need_to_alloc);
diff --git a/src/w32heap.h b/src/w32heap.h
index fda3c58bf01..1630864875f 100644
--- a/src/w32heap.h
+++ b/src/w32heap.h
@@ -24,9 +24,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
#include <windows.h>
-#define ROUND_UP(p, align) (((DWORD)(p) + (align)-1) & ~((align)-1))
-#define ROUND_DOWN(p, align) ((DWORD)(p) & ~((align)-1))
-
/*
* Heap related stuff.
*/
@@ -34,40 +31,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
#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 ()
-#define get_page_size() sysinfo_cache.dwPageSize
-#define get_allocation_unit() sysinfo_cache.dwAllocationGranularity
-#define get_processor_type() sysinfo_cache.dwProcessorType
-#define get_w32_major_version() w32_major_version
-#define get_w32_minor_version() w32_minor_version
extern unsigned char *get_data_start (void);
extern unsigned char *get_data_end (void);
-extern unsigned long reserved_heap_size;
-extern SYSTEM_INFO sysinfo_cache;
-extern OSVERSIONINFO osinfo_cache;
+extern size_t reserved_heap_size;
extern BOOL using_dynamic_heap;
-extern int w32_major_version;
-extern int w32_minor_version;
-extern int w32_build_number;
-
-enum {
- OS_9X = 1,
- OS_NT
-};
-
-extern int os_subtype;
/* Emulation of Unix sbrk(). */
-extern void *sbrk (unsigned long size);
+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 (unsigned long size);
-
-/* Cache system info, e.g., the NT page size. */
-extern void cache_system_info (void);
+extern void round_heap (size_t size);
/* ----------------------------------------------------------------- */
/* Useful routines for manipulating memory-mapped files. */
@@ -89,6 +66,6 @@ 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. */
-IMAGE_SECTION_HEADER * rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header);
+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 731dd6715dc..2cbf31efda3 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -25,7 +25,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <windows.h>
-#include <setjmp.h>
#ifndef MOUSE_MOVED
#define MOUSE_MOVED 1
@@ -71,6 +70,9 @@ w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
: ReadConsoleInputA (h, rec, recsize, waiting));
}
+/* Set by w32_console_toggle_lock_key. */
+int faked_key;
+
static int
fill_queue (BOOL block)
{
@@ -111,67 +113,7 @@ get_frame (void)
/* Translate console modifiers to emacs modifiers.
German keyboard support (Kai Morgan Zeise 2/18/95). */
-int
-w32_kbd_mods_to_emacs (DWORD mods, WORD key)
-{
- int retval = 0;
-
- /* If we recognize right-alt and left-ctrl as AltGr, and it has been
- pressed, first remove those modifiers. */
- if (!NILP (Vw32_recognize_altgr)
- && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
- == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
- mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
-
- if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
- retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
- if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
- {
- retval |= ctrl_modifier;
- if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
- == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
- retval |= meta_modifier;
- }
-
- if (mods & LEFT_WIN_PRESSED)
- retval |= w32_key_to_modifier (VK_LWIN);
- if (mods & RIGHT_WIN_PRESSED)
- retval |= w32_key_to_modifier (VK_RWIN);
- if (mods & APPS_PRESSED)
- retval |= w32_key_to_modifier (VK_APPS);
- if (mods & SCROLLLOCK_ON)
- retval |= w32_key_to_modifier (VK_SCROLL);
-
- /* Just in case someone wanted the original behavior, make it
- optional by setting w32-capslock-is-shiftlock to t. */
- if (NILP (Vw32_capslock_is_shiftlock)
- /* Keys that should _not_ be affected by CapsLock. */
- && ( (key == VK_BACK)
- || (key == VK_TAB)
- || (key == VK_CLEAR)
- || (key == VK_RETURN)
- || (key == VK_ESCAPE)
- || ((key >= VK_SPACE) && (key <= VK_HELP))
- || ((key >= VK_NUMPAD0) && (key <= VK_F24))
- || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
- ))
- {
- /* Only consider shift state. */
- if ((mods & SHIFT_PRESSED) != 0)
- retval |= shift_modifier;
- }
- else
- {
- /* Ignore CapsLock state if not enabled. */
- if (NILP (Vw32_enable_caps_lock))
- mods &= ~CAPSLOCK_ON;
- if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
- retval |= shift_modifier;
- }
-
- return retval;
-}
#if 0
/* Return nonzero if the virtual key is a dead key. */
@@ -188,90 +130,7 @@ is_dead_key (int wparam)
/* The return code indicates key code size. cpID is the codepage to
use for translation to Unicode; -1 means use the current console
input codepage. */
-int
-w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
-{
- unsigned int key_code = event->wVirtualKeyCode;
- unsigned int mods = event->dwControlKeyState;
- BYTE keystate[256];
- static BYTE ansi_code[4];
- static int isdead = 0;
- if (isdead == 2)
- {
- event->uChar.AsciiChar = ansi_code[2];
- isdead = 0;
- return 1;
- }
- if (event->uChar.AsciiChar != 0)
- return 1;
-
- memset (keystate, 0, sizeof (keystate));
- keystate[key_code] = 0x80;
- if (mods & SHIFT_PRESSED)
- keystate[VK_SHIFT] = 0x80;
- if (mods & CAPSLOCK_ON)
- keystate[VK_CAPITAL] = 1;
- /* If we recognize right-alt and left-ctrl as AltGr, set the key
- states accordingly before invoking ToAscii. */
- if (!NILP (Vw32_recognize_altgr)
- && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
- {
- keystate[VK_CONTROL] = 0x80;
- keystate[VK_LCONTROL] = 0x80;
- keystate[VK_MENU] = 0x80;
- keystate[VK_RMENU] = 0x80;
- }
-
-#if 0
- /* Because of an OS bug, ToAscii corrupts the stack when called to
- convert a dead key in console mode on NT4. Unfortunately, trying
- to check for dead keys using MapVirtualKey doesn't work either -
- these functions apparently use internal information about keyboard
- layout which doesn't get properly updated in console programs when
- changing layout (though apparently it gets partly updated,
- otherwise ToAscii wouldn't crash). */
- if (is_dead_key (event->wVirtualKeyCode))
- return 0;
-#endif
-
- /* On NT, call ToUnicode instead and then convert to the current
- console input codepage. */
- if (os_subtype == OS_NT)
- {
- WCHAR buf[128];
-
- isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
- keystate, buf, 128, 0);
- if (isdead > 0)
- {
- /* When we are called from the GUI message processing code,
- we are passed the current keyboard codepage, a positive
- number, to use below. */
- if (cpId == -1)
- cpId = GetConsoleCP ();
-
- event->uChar.UnicodeChar = buf[isdead - 1];
- isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
- ansi_code, 4, NULL, NULL);
- }
- else
- isdead = 0;
- }
- else
- {
- isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
- keystate, (LPWORD) ansi_code, 0);
- }
-
- if (isdead == 0)
- return 0;
- event->uChar.AsciiChar = ansi_code[0];
- return isdead;
-}
-
-
-static int faked_key = 0;
/* return code -1 means that event_queue_ptr won't be incremented.
In other word, this event makes two key codes. (by himi) */
@@ -532,32 +391,6 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
return 1;
}
-int
-w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
-{
- int cur_state = (GetKeyState (vk_code) & 1);
-
- if (NILP (new_state)
- || (NUMBERP (new_state)
- && ((XUINT (new_state)) & 1) != cur_state))
- {
- faked_key = vk_code;
-
- keybd_event ((BYTE) vk_code,
- (BYTE) MapVirtualKey (vk_code, 0),
- KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
- keybd_event ((BYTE) vk_code,
- (BYTE) MapVirtualKey (vk_code, 0),
- KEYEVENTF_EXTENDEDKEY | 0, 0);
- keybd_event ((BYTE) vk_code,
- (BYTE) MapVirtualKey (vk_code, 0),
- KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
- cur_state = !cur_state;
- }
-
- return cur_state;
-}
-
/* Mouse position hook. */
void
w32_console_mouse_position (FRAME_PTR *f,
@@ -568,7 +401,7 @@ w32_console_mouse_position (FRAME_PTR *f,
Lisp_Object *y,
Time *time)
{
- BLOCK_INPUT;
+ block_input ();
insist = insist;
@@ -581,7 +414,7 @@ w32_console_mouse_position (FRAME_PTR *f,
XSETINT (*y, movement_pos.Y);
*time = movement_time;
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Remember mouse motion and notify emacs. */
@@ -743,33 +576,128 @@ maybe_generate_resize_event (void)
0, 0, 0);
}
+static int
+handle_file_notifications (struct input_event *hold_quit)
+{
+ BYTE *p = file_notifications;
+ FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
+ const DWORD min_size
+ = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+ struct input_event inev;
+ int nevents = 0;
+
+ /* We cannot process notification before Emacs is fully initialized,
+ since we need the UTF-16LE coding-system to be set up. */
+ if (!initialized)
+ {
+ notification_buffer_in_use = 0;
+ return nevents;
+ }
+
+ enter_crit ();
+ if (notification_buffer_in_use)
+ {
+ DWORD info_size = notifications_size;
+ Lisp_Object cs = intern ("utf-16le");
+ Lisp_Object obj = w32_get_watch_object (notifications_desc);
+
+ /* notifications_size could be zero when the buffer of
+ notifications overflowed on the OS level, or when the
+ directory being watched was itself deleted. Do nothing in
+ that case. */
+ if (info_size
+ && !NILP (obj) && CONSP (obj))
+ {
+ Lisp_Object callback = XCDR (obj);
+
+ EVENT_INIT (inev);
+
+ while (info_size >= min_size)
+ {
+ Lisp_Object utf_16_fn
+ = make_unibyte_string ((char *)fni->FileName,
+ fni->FileNameLength);
+ /* Note: mule-conf is preloaded, so utf-16le must
+ already be defined at this point. */
+ Lisp_Object fname
+ = code_convert_string_norecord (utf_16_fn, cs, 0);
+ 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);
+ kbd_buffer_store_event_hold (&inev, hold_quit);
+
+ if (!fni->NextEntryOffset)
+ break;
+ p += fni->NextEntryOffset;
+ fni = (PFILE_NOTIFY_INFORMATION)p;
+ info_size -= fni->NextEntryOffset;
+ }
+ }
+ notification_buffer_in_use = 0;
+ }
+ leave_crit ();
+ return nevents;
+}
+
+/* Here's an overview of how Emacs input works in non-GUI sessions on
+ MS-Windows. (For description of the GUI input, see the commentary
+ before w32_msg_pump in w32fns.c.)
+
+ When Emacs is idle, it loops inside wait_reading_process_output,
+ calling pselect periodically to check whether any input is
+ available. On Windows, pselect is redirected to sys_select, which
+ uses MsgWaitForMultipleObjects to wait for input, either from the
+ keyboard or from any of the Emacs subprocesses. In addition,
+ MsgWaitForMultipleObjects wakes up when some Windows message is
+ posted to the input queue of the Emacs's main thread (which is the
+ thread in which sys_select runs).
+
+ When the Emacs's console window has focus, Windows sends input
+ events that originate from the keyboard or the mouse; these events
+ wake up MsgWaitForMultipleObjects, which reports that input is
+ available. Emacs then calls w32_console_read_socket, below, to
+ read the input. w32_console_read_socket uses
+ GetNumberOfConsoleInputEvents and ReadConsoleInput to peek at and
+ read the console input events.
+
+ One type of non-keyboard input event that gets reported as input
+ available is due to the Emacs's console window receiving focus.
+ When that happens, Emacs gets the FOCUS_EVENT event and sys_select
+ reports some input; however, w32_console_read_socket ignores such
+ events when called to read them.
+
+ Note that any other Windows message sent to the main thread will
+ also wake up MsgWaitForMultipleObjects. These messages get
+ immediately dispatched to their destinations by calling
+ drain_message_queue. */
+
int
w32_console_read_socket (struct terminal *terminal,
- int expected,
struct input_event *hold_quit)
{
- int nev, ret = 0, add;
+ int nev, add;
int isdead;
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
+ block_input ();
for (;;)
{
+ int nfnotify = handle_file_notifications (hold_quit);
+
nev = fill_queue (0);
if (nev <= 0)
{
/* If nev == -1, there was some kind of error
- If nev == 0 then waitp must be zero and no events were available
+ If nev == 0 then no events were available
so return. */
- UNBLOCK_INPUT;
- return nev;
+ if (nfnotify)
+ nev = 0;
+ break;
}
while (nev > 0)
@@ -813,9 +741,6 @@ w32_console_read_socket (struct terminal *terminal,
queue_ptr++;
nev--;
}
-
- if (ret > 0 || expected == 0)
- break;
}
/* We don't get told about changes in the window size (only the buffer
@@ -824,6 +749,6 @@ w32_console_read_socket (struct terminal *terminal,
if (!w32_use_full_screen_buffer)
maybe_generate_resize_event ();
- UNBLOCK_INPUT;
- return ret;
+ unblock_input ();
+ return nev;
}
diff --git a/src/w32inevt.h b/src/w32inevt.h
index c874e58ef39..319688b877b 100644
--- a/src/w32inevt.h
+++ b/src/w32inevt.h
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
extern int w32_console_unicode_input;
-extern int w32_console_read_socket (struct terminal *term, int numchars,
+extern int w32_console_read_socket (struct terminal *term,
struct input_event *hold_quit);
extern void w32_console_mouse_position (FRAME_PTR *f, int insist,
Lisp_Object *bar_window,
diff --git a/src/w32menu.c b/src/w32menu.c
index 3aa4c8bc96d..84fb1bdc71e 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <stdio.h>
-#include <mbstring.h>
#include <setjmp.h>
#include "lisp.h"
@@ -41,6 +40,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
if this is not done before the other system files. */
#include "w32term.h"
+/* Cygwin does not support the multibyte string functions declared in
+ * mbstring.h below --- but that's okay: because Cygwin is
+ * UNICODE-only, we don't need to use these functions anyway. */
+
+#ifndef NTGUI_UNICODE
+#include <mbstring.h>
+#endif /* !NTGUI_UNICODE */
+
/* Load sys/types.h if not already loaded.
In some systems loading it twice is suicidal. */
#ifndef makedev
@@ -49,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "dispextern.h"
-#include "w32heap.h" /* for osinfo_cache */
+#include "w32common.h" /* for osinfo_cache */
#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
@@ -79,14 +86,21 @@ typedef int (WINAPI * MessageBoxW_Proc) (
IN WCHAR *caption,
IN UINT type);
+#ifdef NTGUI_UNICODE
+#define get_menu_item_info GetMenuItemInfoA
+#define set_menu_item_info SetMenuItemInfoA
+#define unicode_append_menu AppendMenuW
+#define unicode_message_box MessageBoxW
+#else /* !NTGUI_UNICODE */
GetMenuItemInfoA_Proc get_menu_item_info = NULL;
SetMenuItemInfoA_Proc set_menu_item_info = NULL;
AppendMenuW_Proc unicode_append_menu = NULL;
MessageBoxW_Proc unicode_message_box = NULL;
+#endif /* NTGUI_UNICODE */
Lisp_Object Qdebug_on_next_call;
-void set_frame_menubar (FRAME_PTR, int, int);
+void set_frame_menubar (FRAME_PTR, bool, bool);
#ifdef HAVE_DIALOGS
static Lisp_Object w32_dialog_show (FRAME_PTR, int, Lisp_Object, char**);
@@ -99,17 +113,7 @@ static void utf8to16 (unsigned char *, int, WCHAR *);
static int fill_in_menu (HMENU, widget_value *);
void w32_free_menu_strings (HWND);
-
-/* This is set nonzero after the user activates the menu bar, and set
- to zero again after the menu bars are redisplayed by prepare_menu_bar.
- While it is nonzero, all calls to set_frame_menubar go deep.
-
- I don't understand why this is needed, but it does seem to be
- needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
-
-int pending_menu_activation;
-
#ifdef HAVE_MENUS
DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
@@ -222,9 +226,9 @@ otherwise it is "Question". */)
list_of_panes (Fcons (contents, Qnil));
/* Display them in a dialog box. */
- BLOCK_INPUT;
+ block_input ();
selection = w32_dialog_show (f, 0, title, header, &error_name);
- UNBLOCK_INPUT;
+ unblock_input ();
discard_menu_items ();
FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
@@ -357,7 +361,7 @@ menubar_selection_callback (FRAME_PTR f, void * client_data)
it is set the first time this is called, from initialize_frame_menubar. */
void
-set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
+set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p)
{
HMENU menubar_widget = f->output_data.w32->menubar_widget;
Lisp_Object items;
@@ -374,8 +378,6 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
if (! menubar_widget)
deep_p = 1;
- else if (pending_menu_activation && !deep_p)
- deep_p = 1;
if (deep_p)
{
@@ -572,7 +574,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
/* Create or update the menu bar widget. */
- BLOCK_INPUT;
+ block_input ();
if (menubar_widget)
{
@@ -602,7 +604,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Called from Fx_create_frame to create the initial menubar of a frame
@@ -625,7 +627,7 @@ initialize_frame_menubar (FRAME_PTR f)
void
free_frame_menubar (FRAME_PTR f)
{
- BLOCK_INPUT;
+ block_input ();
{
HMENU old = GetMenu (FRAME_W32_WINDOW (f));
@@ -634,7 +636,7 @@ free_frame_menubar (FRAME_PTR f)
DestroyMenu (old);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -820,7 +822,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
else if (EQ (type, QCradio))
wv->button_type = BUTTON_TYPE_RADIO;
else
- abort ();
+ emacs_abort ();
wv->selected = !NILP (selected);
@@ -1406,6 +1408,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
nlen++;
}
}
+#ifndef NTGUI_UNICODE
else
{
/* If encoded with the system codepage, use multibyte string
@@ -1416,6 +1419,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
nlen++;
}
}
+#endif /* !NTGUI_UNICODE */
if (nlen > orig_len)
{
@@ -1430,6 +1434,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
*q++ = *p;
*q++ = *p++;
}
+#ifndef NTGUI_UNICODE
else
{
if (_mbsnextc (p) == '&')
@@ -1441,6 +1446,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
p = _mbsinc (p);
q = _mbsinc (q);
}
+#endif /* !NTGUI_UNICODE */
}
*q = '\0';
}
@@ -1484,9 +1490,11 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
utf8to16 (out_string, utf8_len, utf16_string);
return_value = unicode_append_menu (menu, fuFlags,
- item != NULL ? (UINT) item
- : (UINT) wv->call_data,
+ item != NULL ? (UINT_PTR) item
+ : (UINT_PTR) wv->call_data,
utf16_string);
+
+#ifndef NTGUI_UNICODE /* Fallback does not apply when always UNICODE */
if (!return_value)
{
/* On W9x/ME, Unicode menus are not supported, though AppendMenuW
@@ -1497,7 +1505,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
of minor importance compared with menus not working at all. */
return_value =
AppendMenu (menu, fuFlags,
- item != NULL ? (UINT) item: (UINT) wv->call_data,
+ item != NULL ? (UINT_PTR) item: (UINT_PTR) wv->call_data,
out_string);
/* Don't use Unicode menus in future, unless this is Windows
NT or later, where a failure of AppendMenuW does NOT mean
@@ -1505,6 +1513,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT)
unicode_append_menu = NULL;
}
+#endif /* NTGUI_UNICODE */
if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
local_free (out_string);
@@ -1514,7 +1523,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
return_value =
AppendMenu (menu,
fuFlags,
- item != NULL ? (UINT) item : (UINT) wv->call_data,
+ item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
out_string );
}
@@ -1551,7 +1560,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
}
set_menu_item_info (menu,
- item != NULL ? (UINT) item : (UINT) wv->call_data,
+ item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
FALSE, &info);
}
}
@@ -1724,10 +1733,12 @@ syms_of_w32menu (void)
void
globals_of_w32menu (void)
{
+#ifndef NTGUI_UNICODE
/* See if Get/SetMenuItemInfo functions are available. */
HMODULE user32 = GetModuleHandle ("user32.dll");
get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW");
+#endif /* !NTGUI_UNICODE */
}
diff --git a/src/w32notify.c b/src/w32notify.c
new file mode 100644
index 00000000000..0b7dc9a1110
--- /dev/null
+++ b/src/w32notify.c
@@ -0,0 +1,631 @@
+/* Filesystem notifications support for GNU Emacs on the Microsoft Windows API.
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+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 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/>. */
+
+/* Written by Eli Zaretskii <eliz@gnu.org>.
+
+ Design overview:
+
+ For each watch request, we launch a separate worker thread. The
+ worker thread runs the watch_worker function, which issues an
+ asynchronous call to ReadDirectoryChangesW, and then waits in
+ SleepEx for that call to complete. Waiting in SleepEx puts the
+ thread in an "alertable" state, so it wakes up when either (a) the
+ call to ReadDirectoryChangesW completes, or (b) the main thread
+ instructs the worker thread to terminate by sending it an APC, see
+ below.
+
+ When the ReadDirectoryChangesW call completes, its completion
+ routine watch_completion is automatically called. watch_completion
+ stashes the received file events in a buffer used to communicate
+ them to the main thread (using a critical section, so that several
+ threads could use the same buffer), posts a special message,
+ WM_EMACS_FILENOTIFY, to the Emacs's message queue, and returns.
+ That causes the SleepEx function call inside watch_worker to
+ return, and watch_worker then issues another call to
+ ReadDirectoryChangesW. (Except when it does not, see below.)
+
+ In a GUI session, The WM_EMACS_FILENOTIFY message, posted to the
+ message queue gets dispatched to the main Emacs window procedure,
+ which queues it for processing by w32_read_socket. When
+ w32_read_socket sees this message, it accesses the buffer with file
+ notifications (using a critical section), extracts the information,
+ converts it to a series of FILE_NOTIFY_EVENT events, and stuffs
+ them into the input event queue to be processed by keyboard.c input
+ machinery (read_char via a call to kbd_buffer_get_event).
+
+ In a non-GUI session, we send the WM_EMACS_FILENOTIFY message to
+ the main (a.k.a. "Lisp") thread instead, since there are no window
+ procedures in console programs. That message wakes up
+ MsgWaitForMultipleObjects inside sys_select, which then signals to
+ its caller that some keyboard input is available. This causes
+ w32_console_read_socket to be called, which accesses the buffer
+ with file notifications and stuffs them into the input event queue
+ for keyboard.c to process.
+
+ When the FILE_NOTIFY_EVENT event is processed by keyboard.c's
+ kbd_buffer_get_event, it is converted to a Lispy event that can be
+ bound to a command. The default binding is w32notify-handle-event,
+ defined on subr.el.
+
+ After w32_read_socket or w32_console_read_socket are done
+ processing the notifications, they reset a flag signaling to all
+ watch worker threads that the notifications buffer is available for
+ more input.
+
+ When the watch is removed by a call to w32notify-rm-watch, the main
+ thread requests that the worker thread terminates by queuing an APC
+ for the worker thread. The APC specifies the watch_end function to
+ be called. watch_end calls CancelIo on the outstanding
+ ReadDirectoryChangesW call and closes the handle on which the
+ watched directory was open. When watch_end returns, the
+ watch_completion function is called one last time with the
+ ERROR_OPERATION_ABORTED status, which causes it to clean up and set
+ a flag telling watch_worker to exit without issuing another
+ ReadDirectoryChangesW call. Since watch_worker is the thread
+ procedure of the worker thread, exiting it causes the thread to
+ exit. The main thread waits for some time for the worker thread to
+ exit, and if it doesn't, terminates it forcibly. */
+
+#include <stddef.h>
+#include <errno.h>
+
+/* must include CRT headers *before* config.h */
+#include <config.h>
+
+#include <windows.h>
+
+#include "lisp.h"
+#include "w32term.h" /* for enter_crit/leave_crit and WM_EMACS_FILENOTIFY */
+#include "w32common.h" /* for OS version data */
+#include "w32.h" /* for w32_strerror */
+#include "coding.h"
+#include "keyboard.h"
+#include "frame.h" /* needed by termhooks.h */
+#include "termhooks.h" /* for FILE_NOTIFY_EVENT */
+
+#define DIRWATCH_SIGNATURE 0x01233210
+
+struct notification {
+ BYTE *buf; /* buffer for ReadDirectoryChangesW */
+ OVERLAPPED *io_info; /* the OVERLAPPED structure for async I/O */
+ BOOL subtree; /* whether to watch subdirectories */
+ DWORD filter; /* bit mask for events to watch */
+ char *watchee; /* the file we are interested in */
+ HANDLE dir; /* handle to the watched directory */
+ HANDLE thr; /* handle to the thread that watches */
+ volatile int terminate; /* if non-zero, request for the thread to terminate */
+ unsigned signature;
+};
+
+/* Used for communicating notifications to the main thread. */
+volatile int notification_buffer_in_use;
+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;
+
+/* Signal to the main thread that we have file notifications for it to
+ process. */
+static void
+send_notifications (BYTE *info, DWORD info_size, void *desc,
+ volatile int *terminate)
+{
+ int done = 0;
+ FRAME_PTR f = SELECTED_FRAME ();
+
+ /* A single buffer is used to communicate all notifications to the
+ main thread. Since both the main thread and several watcher
+ threads could be active at the same time, we use a critical area
+ and an "in-use" flag to synchronize them. A watcher thread can
+ only put its notifications in the buffer if it acquires the
+ critical area and finds the "in-use" flag reset. The main thread
+ resets the flag after it is done processing notifications.
+
+ FIXME: is there a better way of dealing with this? */
+ while (!done && !*terminate)
+ {
+ enter_crit ();
+ if (!notification_buffer_in_use)
+ {
+ if (info_size)
+ memcpy (file_notifications, info, info_size);
+ notifications_size = info_size;
+ notifications_desc = desc;
+ /* If PostMessage fails, the message queue is full. If that
+ happens, the last thing they will worry about is file
+ notifications. So we effectively discard the
+ notification in that case. */
+ if ((FRAME_TERMCAP_P (f)
+ /* We send the message to the main (a.k.a. "Lisp")
+ thread, where it will wake up MsgWaitForMultipleObjects
+ inside sys_select, causing it to report that there's
+ some keyboard input available. This will in turn cause
+ w32_console_read_socket to be called, which will pick
+ up the file notifications. */
+ && PostThreadMessage (dwMainThreadId, WM_EMACS_FILENOTIFY, 0, 0))
+ || (FRAME_W32_P (f)
+ && PostMessage (FRAME_W32_WINDOW (f),
+ WM_EMACS_FILENOTIFY, 0, 0)))
+ notification_buffer_in_use = 1;
+ done = 1;
+ }
+ leave_crit ();
+ if (!done)
+ Sleep (5);
+ }
+}
+
+/* An APC routine to cancel outstanding directory watch. Invoked by
+ the main thread via QueueUserAPC. This is needed because only the
+ thread that issued the ReadDirectoryChangesW call can call CancelIo
+ to cancel that. (CancelIoEx is only available since Vista, so we
+ cannot use it on XP.) */
+VOID CALLBACK
+watch_end (ULONG_PTR arg)
+{
+ HANDLE hdir = (HANDLE)arg;
+
+ if (hdir && hdir != INVALID_HANDLE_VALUE)
+ {
+ CancelIo (hdir);
+ CloseHandle (hdir);
+ }
+}
+
+/* A completion routine (a.k.a. "APC function") for handling events
+ read by ReadDirectoryChangesW. Called by the OS when the thread
+ which issued the asynchronous ReadDirectoryChangesW call is in the
+ "alertable state", i.e. waiting inside SleepEx call. */
+VOID CALLBACK
+watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
+{
+ struct notification *dirwatch;
+
+ /* Who knows what happened? Perhaps the OVERLAPPED structure was
+ freed by someone already? In any case, we cannot do anything
+ with this request, so just punt and skip it. FIXME: should we
+ raise the 'terminate' flag in this case? */
+ if (!io_info)
+ return;
+
+ /* We have a pointer to our dirwatch structure conveniently stashed
+ away in the hEvent member of the OVERLAPPED struct. According to
+ MSDN documentation of ReadDirectoryChangesW: "The hEvent member
+ of the OVERLAPPED structure is not used by the system, so you can
+ use it yourself." */
+ dirwatch = (struct notification *)io_info->hEvent;
+ if (status == ERROR_OPERATION_ABORTED)
+ {
+ /* We've been called because the main thread told us to issue
+ CancelIo on the directory we watch, and watch_end did so.
+ The directory handle is already closed. We should clean up
+ and exit, signaling to the thread worker routine not to
+ issue another call to ReadDirectoryChangesW. Note that we
+ don't free the dirwatch object itself nor the memory consumed
+ by its buffers; this is done by the main thread in
+ remove_watch. Calling malloc/free from a thread other than
+ the main thread is a no-no. */
+ dirwatch->dir = NULL;
+ dirwatch->terminate = 1;
+ }
+ else
+ {
+ /* Tell the main thread we have notifications for it. */
+ send_notifications (dirwatch->buf, bytes_ret, dirwatch,
+ &dirwatch->terminate);
+ }
+}
+
+/* Worker routine for the watch thread. */
+static DWORD WINAPI
+watch_worker (LPVOID arg)
+{
+ struct notification *dirwatch = (struct notification *)arg;
+
+ do {
+ BOOL status;
+ DWORD sleep_result;
+ DWORD bytes_ret = 0;
+
+ if (dirwatch->dir)
+ {
+ status = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, 16384,
+ dirwatch->subtree, dirwatch->filter,
+ &bytes_ret,
+ dirwatch->io_info, watch_completion);
+ if (!status)
+ {
+ DebPrint (("watch_worker, abnormal exit: %lu\n", GetLastError ()));
+ /* We cannot remove the dirwatch object from watch_list,
+ because we are in a separate thread. For the same
+ reason, we also cannot free memory consumed by the
+ buffers allocated for the dirwatch object. So we close
+ the directory handle, but do not free the object itself
+ or its buffers. We also don't touch the signature.
+ This way, remove_watch can still identify the object,
+ remove it, and free its memory. */
+ CloseHandle (dirwatch->dir);
+ dirwatch->dir = NULL;
+ return 1;
+ }
+ }
+ /* 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);
+ } while (!dirwatch->terminate);
+
+ return 0;
+}
+
+/* Launch a thread to watch changes to FILE in a directory open on
+ handle HDIR. */
+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);
+ dirwatch->io_info = xzalloc (sizeof(OVERLAPPED));
+ /* Stash a pointer to dirwatch structure for use by the completion
+ routine. According to MSDN documentation of ReadDirectoryChangesW:
+ "The hEvent member of the OVERLAPPED structure is not used by the
+ system, so you can use it yourself." */
+ dirwatch->io_info->hEvent = dirwatch;
+ dirwatch->subtree = subdirs;
+ dirwatch->filter = flags;
+ dirwatch->watchee = xstrdup (file);
+ dirwatch->terminate = 0;
+ dirwatch->dir = hdir;
+
+ /* See w32proc.c where it calls CreateThread for the story behind
+ the 2nd and 5th argument in the call to CreateThread. */
+ dirwatch->thr = CreateThread (NULL, 64 * 1024, watch_worker, (void *)dirwatch,
+ 0x00010000, NULL);
+
+ if (!dirwatch->thr)
+ {
+ xfree (dirwatch->buf);
+ xfree (dirwatch->io_info);
+ xfree (dirwatch->watchee);
+ xfree (dirwatch);
+ dirwatch = NULL;
+ }
+ return dirwatch;
+}
+
+/* Called from the main thread to start watching FILE in PARENT_DIR,
+ subject to FLAGS. If SUBDIRS is TRUE, watch the subdirectories of
+ PARENT_DIR as well. Value is a pointer to 'struct notification'
+ used by the thread that watches the changes. */
+static struct notification *
+add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags)
+{
+ HANDLE hdir;
+ struct notification *dirwatch = NULL;
+
+ if (!file || !*file)
+ return NULL;
+
+ hdir = CreateFile (parent_dir,
+ FILE_LIST_DIRECTORY,
+ /* FILE_SHARE_DELETE doesn't preclude other
+ processes from deleting files inside
+ parent_dir. */
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+ NULL);
+ if (hdir == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ if ((dirwatch = start_watching (file, hdir, subdirs, flags)) == NULL)
+ CloseHandle (hdir);
+
+ return dirwatch;
+}
+
+/* Stop watching a directory specified by a pointer to its dirwatch object. */
+static int
+remove_watch (struct notification *dirwatch)
+{
+ if (dirwatch && dirwatch->signature == DIRWATCH_SIGNATURE)
+ {
+ int i;
+ BOOL status;
+ DWORD exit_code, err;
+
+ /* Only the thread that issued the outstanding I/O call can call
+ CancelIo on it. (CancelIoEx is available only since Vista.)
+ So we need to queue an APC for the worker thread telling it
+ to terminate. */
+ if (!QueueUserAPC (watch_end, dirwatch->thr, (ULONG_PTR)dirwatch->dir))
+ DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ()));
+ /* We also set the terminate flag, for when the thread is
+ waiting on the critical section that never gets acquired.
+ FIXME: is there a cleaner method? Using SleepEx there is a
+ no-no, as that will lead to recursive APC invocations and
+ stack overflow. */
+ dirwatch->terminate = 1;
+ /* Wait for the thread to exit. FIXME: is there a better method
+ that is not overly complex? */
+ for (i = 0; i < 50; i++)
+ {
+ if (!((status = GetExitCodeThread (dirwatch->thr, &exit_code))
+ && exit_code == STILL_ACTIVE))
+ break;
+ Sleep (10);
+ }
+ if ((status == FALSE && (err = GetLastError ()) == ERROR_INVALID_HANDLE)
+ || exit_code == STILL_ACTIVE)
+ {
+ if (!(status == FALSE && err == ERROR_INVALID_HANDLE))
+ {
+ TerminateThread (dirwatch->thr, 0);
+ if (dirwatch->dir)
+ CloseHandle (dirwatch->dir);
+ }
+ }
+
+ /* Clean up. */
+ if (dirwatch->thr)
+ {
+ CloseHandle (dirwatch->thr);
+ dirwatch->thr = NULL;
+ }
+ xfree (dirwatch->buf);
+ xfree (dirwatch->io_info);
+ xfree (dirwatch->watchee);
+ xfree (dirwatch);
+
+ return 0;
+ }
+ else
+ {
+ DebPrint (("Unknown dirwatch object!\n"));
+ return -1;
+ }
+}
+
+static DWORD
+filter_list_to_flags (Lisp_Object filter_list)
+{
+ DWORD flags = 0;
+
+ if (NILP (filter_list))
+ return flags;
+
+ if (!NILP (Fmember (Qfile_name, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_FILE_NAME;
+ if (!NILP (Fmember (Qdirectory_name, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_DIR_NAME;
+ if (!NILP (Fmember (Qattributes, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+ if (!NILP (Fmember (Qsize, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_SIZE;
+ if (!NILP (Fmember (Qlast_write_time, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+ if (!NILP (Fmember (Qlast_access_time, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
+ if (!NILP (Fmember (Qcreation_time, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_CREATION;
+ if (!NILP (Fmember (Qsecurity_desc, filter_list)))
+ flags |= FILE_NOTIFY_CHANGE_SECURITY;
+
+ return flags;
+}
+
+DEFUN ("w32notify-add-watch", Fw32notify_add_watch,
+ Sw32notify_add_watch, 3, 3, 0,
+ doc: /* Add a watch for filesystem events pertaining to FILE.
+
+This arranges for filesystem events pertaining to FILE to be reported
+to Emacs. Use `w32notify-rm-watch' to cancel the watch.
+
+Value is a descriptor for the added watch, or nil if the file
+cannot be watched.
+
+FILTER is a list of conditions for reporting an event. It can include
+the following symbols:
+
+ 'file-name' -- report file creation, deletion, or renaming
+ 'directory-name' -- report directory creation, deletion, or renaming
+ 'attributes' -- report changes in attributes
+ 'size' -- report changes in file-size
+ 'last-write-time' -- report changes in last-write time
+ 'last-access-time' -- report changes in last-access time
+ 'creation-time' -- report changes in creation time
+ 'security-desc' -- report changes in security descriptor
+
+If FILE is a directory, and FILTER includes 'subtree', then all the
+subdirectories will also be watched and changes in them reported.
+
+When any event happens that satisfies the conditions specified by
+FILTER, Emacs will call the CALLBACK function passing it a single
+argument EVENT, which is of the form
+
+ (DESCRIPTOR ACTION FILE)
+
+DESCRIPTOR is the same object as the one returned by this function.
+ACTION is the description of the event. It could be any one of the
+following:
+
+ 'added' -- FILE was added
+ 'removed' -- FILE was deleted
+ 'modified' -- FILE's contents or its attributes were modified
+ 'renamed-from' -- a file was renamed whose old name was FILE
+ 'renamed-to' -- a file was renamed and its new name is FILE
+
+FILE is the name of the file whose event is being reported. */)
+ (Lisp_Object file, Lisp_Object filter, Lisp_Object callback)
+{
+ Lisp_Object encoded_file, watch_object, watch_descriptor;
+ char parent_dir[MAX_PATH], *basename;
+ size_t fn_len;
+ DWORD flags;
+ BOOL subdirs = FALSE;
+ struct notification *dirwatch = NULL;
+ Lisp_Object lisp_errstr;
+ char *errstr;
+
+ CHECK_LIST (filter);
+
+ /* The underlying features are available only since XP. */
+ if (os_subtype == OS_9X
+ || (w32_major_version == 5 && w32_major_version < 1))
+ {
+ errno = ENOSYS;
+ report_file_error ("Watching filesystem events is not supported",
+ Qnil);
+ }
+
+ /* We need a full absolute file name of FILE, and we need to remove
+ any trailing slashes from it, so that GetFullPathName below gets
+ the basename part correctly. */
+ file = Fdirectory_file_name (Fexpand_file_name (file, Qnil));
+ encoded_file = ENCODE_FILE (file);
+
+ fn_len = GetFullPathName (SDATA (encoded_file), MAX_PATH, parent_dir,
+ &basename);
+ if (!fn_len)
+ {
+ errstr = w32_strerror (0);
+ errno = EINVAL;
+ if (!NILP (Vlocale_coding_system))
+ lisp_errstr
+ = code_convert_string_norecord (build_unibyte_string (errstr),
+ Vlocale_coding_system, 0);
+ else
+ lisp_errstr = build_string (errstr);
+ report_file_error ("GetFullPathName failed",
+ Fcons (lisp_errstr, Fcons (file, Qnil)));
+ }
+ /* We need the parent directory without the slash that follows it.
+ If BASENAME is NULL, the argument was the root directory on its
+ drive. */
+ if (basename)
+ basename[-1] = '\0';
+ else
+ subdirs = TRUE;
+
+ if (!NILP (Fmember (Qsubtree, filter)))
+ subdirs = TRUE;
+
+ flags = filter_list_to_flags (filter);
+
+ dirwatch = add_watch (parent_dir, basename, subdirs, flags);
+ if (!dirwatch)
+ {
+ DWORD err = GetLastError ();
+
+ errno = EINVAL;
+ if (err)
+ {
+ errstr = w32_strerror (err);
+ if (!NILP (Vlocale_coding_system))
+ lisp_errstr
+ = code_convert_string_norecord (build_unibyte_string (errstr),
+ Vlocale_coding_system, 0);
+ else
+ lisp_errstr = build_string (errstr);
+ report_file_error ("Cannot watch file",
+ Fcons (lisp_errstr, Fcons (file, Qnil)));
+ }
+ else
+ report_file_error ("Cannot watch file", Fcons (file, Qnil));
+ }
+ /* Store watch object in watch list. */
+ watch_descriptor = XIL ((EMACS_INT)dirwatch);
+ watch_object = Fcons (watch_descriptor, callback);
+ watch_list = Fcons (watch_object, watch_list);
+
+ return watch_descriptor;
+}
+
+DEFUN ("w32notify-rm-watch", Fw32notify_rm_watch,
+ Sw32notify_rm_watch, 1, 1, 0,
+ doc: /* Remove an existing watch specified by its WATCH-DESCRIPTOR.
+
+WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */)
+ (Lisp_Object watch_descriptor)
+{
+ Lisp_Object watch_object;
+ struct notification *dirwatch;
+ int status = -1;
+
+ /* Remove the watch object from watch list. Do this before freeing
+ the object, do that even if we fail to free it, watch_list is
+ kept free of junk. */
+ watch_object = Fassoc (watch_descriptor, watch_list);
+ if (!NILP (watch_object))
+ {
+ watch_list = Fdelete (watch_object, watch_list);
+ dirwatch = (struct notification *)XLI (watch_descriptor);
+ if (w32_valid_pointer_p (dirwatch, sizeof(struct notification)))
+ status = remove_watch (dirwatch);
+ }
+
+ if (status == -1)
+ report_file_error ("Invalid watch descriptor", Fcons (watch_descriptor,
+ Qnil));
+
+ return Qnil;
+}
+
+Lisp_Object
+w32_get_watch_object (void *desc)
+{
+ Lisp_Object descriptor = XIL ((EMACS_INT)desc);
+
+ /* This is called from the input queue handling code, inside a
+ critical section, so we cannot possibly QUIT if watch_list is not
+ in the right condition. */
+ return NILP (watch_list) ? Qnil : assoc_no_quit (descriptor, watch_list);
+}
+
+void
+globals_of_w32notify (void)
+{
+ watch_list = Qnil;
+}
+
+void
+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");
+ DEFSYM (Qsecurity_desc, "security-desc");
+ DEFSYM (Qsubtree, "subtree");
+
+ defsubr (&Sw32notify_add_watch);
+ defsubr (&Sw32notify_rm_watch);
+
+ staticpro (&watch_list);
+
+ Fprovide (intern_c_string ("w32notify"), Qnil);
+}
diff --git a/src/w32proc.c b/src/w32proc.c
index 33aed5eb8e3..43ecf4d68f3 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -24,11 +24,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/file.h>
-#include <setjmp.h>
/* must include CRT headers *before* config.h */
#include <config.h>
@@ -52,6 +52,7 @@ extern BOOL WINAPI IsValidLocale (LCID, DWORD);
#include "lisp.h"
#include "w32.h"
+#include "w32common.h"
#include "w32heap.h"
#include "systime.h"
#include "syswait.h"
@@ -63,53 +64,731 @@ extern BOOL WINAPI IsValidLocale (LCID, DWORD);
#define RVA_TO_PTR(var,section,filedata) \
((void *)((section)->PointerToRawData \
- + ((DWORD)(var) - (section)->VirtualAddress) \
+ + ((DWORD_PTR)(var) - (section)->VirtualAddress) \
+ (filedata).file_base))
Lisp_Object Qhigh, Qlow;
-#ifdef EMACSDEBUG
-void
-_DebPrint (const char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- va_start (args, fmt);
- vsprintf (buf, fmt, args);
- va_end (args);
- OutputDebugString (buf);
-}
-#endif
-
-typedef void (_CALLBACK_ *signal_handler) (int);
-
/* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
static signal_handler sig_handlers[NSIG];
-/* Fake signal implementation to record the SIGCHLD handler. */
+static sigset_t sig_mask;
+
+static CRITICAL_SECTION crit_sig;
+
+/* Improve on the CRT 'signal' implementation so that we could record
+ the SIGCHLD handler and fake interval timers. */
signal_handler
sys_signal (int sig, signal_handler handler)
{
signal_handler old;
- if (sig != SIGCHLD)
+ /* SIGCHLD is needed for supporting subprocesses, see sys_kill
+ below. SIGALRM and SIGPROF are used by setitimer. All the
+ others are the only ones supported by the MS runtime. */
+ if (!(sig == SIGCHLD || sig == SIGSEGV || sig == SIGILL
+ || sig == SIGFPE || sig == SIGABRT || sig == SIGTERM
+ || sig == SIGALRM || sig == SIGPROF))
{
errno = EINVAL;
return SIG_ERR;
}
old = sig_handlers[sig];
- sig_handlers[sig] = handler;
+ /* SIGABRT is treated specially because w32.c installs term_ntproc
+ as its handler, so we don't want to override that afterwards.
+ Aborting Emacs works specially anyway: either by calling
+ emacs_abort directly or through terminate_due_to_signal, which
+ calls emacs_abort through emacs_raise. */
+ if (!(sig == SIGABRT && old == term_ntproc))
+ {
+ sig_handlers[sig] = handler;
+ if (!(sig == SIGCHLD || sig == SIGALRM || sig == SIGPROF))
+ signal (sig, handler);
+ }
return old;
}
+/* Emulate sigaction. */
+int
+sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
+{
+ signal_handler old = SIG_DFL;
+ int retval = 0;
+
+ if (act)
+ old = sys_signal (sig, act->sa_handler);
+ else if (oact)
+ old = sig_handlers[sig];
+
+ if (old == SIG_ERR)
+ {
+ errno = EINVAL;
+ retval = -1;
+ }
+ if (oact)
+ {
+ oact->sa_handler = old;
+ oact->sa_flags = 0;
+ oact->sa_mask = empty_mask;
+ }
+ return retval;
+}
+
+/* Emulate signal sets and blocking of signals used by timers. */
+
+int
+sigemptyset (sigset_t *set)
+{
+ *set = 0;
+ return 0;
+}
+
+int
+sigaddset (sigset_t *set, int signo)
+{
+ if (!set)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (signo < 0 || signo >= NSIG)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *set |= (1U << signo);
+
+ return 0;
+}
+
+int
+sigfillset (sigset_t *set)
+{
+ if (!set)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *set = 0xFFFFFFFF;
+ return 0;
+}
+
+int
+sigprocmask (int how, const sigset_t *set, sigset_t *oset)
+{
+ if (!(how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (oset)
+ *oset = sig_mask;
+
+ if (!set)
+ return 0;
+
+ switch (how)
+ {
+ case SIG_BLOCK:
+ sig_mask |= *set;
+ break;
+ case SIG_SETMASK:
+ sig_mask = *set;
+ break;
+ case SIG_UNBLOCK:
+ /* FIXME: Catch signals that are blocked and reissue them when
+ they are unblocked. Important for SIGALRM and SIGPROF only. */
+ sig_mask &= ~(*set);
+ break;
+ }
+
+ return 0;
+}
+
+int
+pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
+{
+ if (sigprocmask (how, set, oset) == -1)
+ return EINVAL;
+ return 0;
+}
+
+int
+sigismember (const sigset_t *set, int signo)
+{
+ if (signo < 0 || signo >= NSIG)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (signo > sizeof (*set) * BITS_PER_CHAR)
+ emacs_abort ();
+
+ return (*set & (1U << signo)) != 0;
+}
+
+pid_t
+getpgrp (void)
+{
+ return getpid ();
+}
+
+pid_t
+tcgetpgrp (int fd)
+{
+ return getpid ();
+}
+
+int
+setpgid (pid_t pid, pid_t pgid)
+{
+ return 0;
+}
+
+pid_t
+setsid (void)
+{
+ return getpid ();
+}
+
+/* Emulations of interval timers.
+
+ Limitations: only ITIMER_REAL and ITIMER_PROF are supported.
+
+ Implementation: a separate thread is started for each timer type,
+ the thread calls the appropriate signal handler when the timer
+ expires, after stopping the thread which installed the timer. */
+
+struct itimer_data {
+ volatile ULONGLONG expire;
+ volatile ULONGLONG reload;
+ volatile int terminate;
+ int type;
+ HANDLE caller_thread;
+ HANDLE timer_thread;
+};
+
+static ULONGLONG ticks_now;
+static struct itimer_data real_itimer, prof_itimer;
+static ULONGLONG clocks_min;
+/* If non-zero, itimers are disabled. Used during shutdown, when we
+ delete the critical sections used by the timer threads. */
+static int disable_itimers;
+
+static CRITICAL_SECTION crit_real, crit_prof;
+
+/* GetThreadTimes is not available on Windows 9X and possibly also on 2K. */
+typedef BOOL (WINAPI *GetThreadTimes_Proc) (
+ HANDLE hThread,
+ LPFILETIME lpCreationTime,
+ LPFILETIME lpExitTime,
+ LPFILETIME lpKernelTime,
+ LPFILETIME lpUserTime);
+
+static GetThreadTimes_Proc s_pfn_Get_Thread_Times;
+
+#define MAX_SINGLE_SLEEP 30
+#define TIMER_TICKS_PER_SEC 1000
+
+/* Return a suitable time value, in 1-ms units, for THREAD, a handle
+ to a thread. If THREAD is NULL or an invalid handle, return the
+ current wall-clock time since January 1, 1601 (UTC). Otherwise,
+ return the sum of kernel and user times used by THREAD since it was
+ created, plus its creation time. */
+static ULONGLONG
+w32_get_timer_time (HANDLE thread)
+{
+ ULONGLONG retval;
+ int use_system_time = 1;
+ /* The functions below return times in 100-ns units. */
+ const int tscale = 10 * TIMER_TICKS_PER_SEC;
+
+ if (thread && thread != INVALID_HANDLE_VALUE
+ && s_pfn_Get_Thread_Times != NULL)
+ {
+ FILETIME creation_ftime, exit_ftime, kernel_ftime, user_ftime;
+ ULARGE_INTEGER temp_creation, temp_kernel, temp_user;
+
+ if (s_pfn_Get_Thread_Times (thread, &creation_ftime, &exit_ftime,
+ &kernel_ftime, &user_ftime))
+ {
+ use_system_time = 0;
+ temp_creation.LowPart = creation_ftime.dwLowDateTime;
+ temp_creation.HighPart = creation_ftime.dwHighDateTime;
+ temp_kernel.LowPart = kernel_ftime.dwLowDateTime;
+ temp_kernel.HighPart = kernel_ftime.dwHighDateTime;
+ temp_user.LowPart = user_ftime.dwLowDateTime;
+ temp_user.HighPart = user_ftime.dwHighDateTime;
+ retval =
+ temp_creation.QuadPart / tscale + temp_kernel.QuadPart / tscale
+ + temp_user.QuadPart / tscale;
+ }
+ else
+ DebPrint (("GetThreadTimes failed with error code %lu\n",
+ GetLastError ()));
+ }
+
+ if (use_system_time)
+ {
+ FILETIME current_ftime;
+ ULARGE_INTEGER temp;
+
+ GetSystemTimeAsFileTime (&current_ftime);
+
+ temp.LowPart = current_ftime.dwLowDateTime;
+ temp.HighPart = current_ftime.dwHighDateTime;
+
+ retval = temp.QuadPart / tscale;
+ }
+
+ return retval;
+}
+
+/* Thread function for a timer thread. */
+static DWORD WINAPI
+timer_loop (LPVOID arg)
+{
+ struct itimer_data *itimer = (struct itimer_data *)arg;
+ int which = itimer->type;
+ int sig = (which == ITIMER_REAL) ? SIGALRM : SIGPROF;
+ CRITICAL_SECTION *crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
+ const DWORD max_sleep = MAX_SINGLE_SLEEP * 1000 / TIMER_TICKS_PER_SEC;
+ HANDLE hth = (which == ITIMER_REAL) ? NULL : itimer->caller_thread;
+
+ while (1)
+ {
+ DWORD sleep_time;
+ signal_handler handler;
+ ULONGLONG now, expire, reload;
+
+ /* Load new values if requested by setitimer. */
+ EnterCriticalSection (crit);
+ expire = itimer->expire;
+ reload = itimer->reload;
+ LeaveCriticalSection (crit);
+ if (itimer->terminate)
+ return 0;
+
+ if (expire == 0)
+ {
+ /* We are idle. */
+ Sleep (max_sleep);
+ continue;
+ }
+
+ if (expire > (now = w32_get_timer_time (hth)))
+ sleep_time = expire - now;
+ else
+ sleep_time = 0;
+ /* Don't sleep too long at a time, to be able to see the
+ termination flag without too long a delay. */
+ while (sleep_time > max_sleep)
+ {
+ if (itimer->terminate)
+ return 0;
+ Sleep (max_sleep);
+ EnterCriticalSection (crit);
+ expire = itimer->expire;
+ LeaveCriticalSection (crit);
+ sleep_time =
+ (expire > (now = w32_get_timer_time (hth))) ? expire - now : 0;
+ }
+ if (itimer->terminate)
+ return 0;
+ if (sleep_time > 0)
+ {
+ Sleep (sleep_time * 1000 / TIMER_TICKS_PER_SEC);
+ /* Always sleep past the expiration time, to make sure we
+ never call the handler _before_ the expiration time,
+ always slightly after it. Sleep(5) makes sure we don't
+ hog the CPU by calling 'w32_get_timer_time' with high
+ frequency, and also let other threads work. */
+ while (w32_get_timer_time (hth) < expire)
+ Sleep (5);
+ }
+
+ EnterCriticalSection (crit);
+ expire = itimer->expire;
+ LeaveCriticalSection (crit);
+ if (expire == 0)
+ continue;
+
+ /* Time's up. */
+ handler = sig_handlers[sig];
+ if (!(handler == SIG_DFL || handler == SIG_IGN || handler == SIG_ERR)
+ /* FIXME: Don't ignore masked signals. Instead, record that
+ they happened and reissue them when the signal is
+ unblocked. */
+ && !sigismember (&sig_mask, sig)
+ /* Simulate masking of SIGALRM and SIGPROF when processing
+ fatal signals. */
+ && !fatal_error_in_progress
+ && itimer->caller_thread)
+ {
+ /* Simulate a signal delivered to the thread which installed
+ the timer, by suspending that thread while the handler
+ runs. */
+ HANDLE th = itimer->caller_thread;
+ DWORD result = SuspendThread (th);
+
+ if (result == (DWORD)-1)
+ return 2;
+
+ handler (sig);
+ ResumeThread (th);
+ }
+
+ /* Update expiration time and loop. */
+ EnterCriticalSection (crit);
+ expire = itimer->expire;
+ if (expire == 0)
+ {
+ LeaveCriticalSection (crit);
+ continue;
+ }
+ reload = itimer->reload;
+ if (reload > 0)
+ {
+ now = w32_get_timer_time (hth);
+ if (expire <= now)
+ {
+ ULONGLONG lag = now - expire;
+
+ /* If we missed some opportunities (presumably while
+ sleeping or while the signal handler ran), skip
+ them. */
+ if (lag > reload)
+ expire = now - (lag % reload);
+
+ expire += reload;
+ }
+ }
+ else
+ expire = 0; /* become idle */
+ itimer->expire = expire;
+ LeaveCriticalSection (crit);
+ }
+ return 0;
+}
+
+static void
+stop_timer_thread (int which)
+{
+ struct itimer_data *itimer =
+ (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
+ int i;
+ DWORD err, exit_code = 255;
+ BOOL status;
+
+ /* Signal the thread that it should terminate. */
+ itimer->terminate = 1;
+
+ if (itimer->timer_thread == NULL)
+ return;
+
+ /* Wait for the timer thread to terminate voluntarily, then kill it
+ if it doesn't. This loop waits twice more than the maximum
+ amount of time a timer thread sleeps, see above. */
+ for (i = 0; i < MAX_SINGLE_SLEEP / 5; i++)
+ {
+ if (!((status = GetExitCodeThread (itimer->timer_thread, &exit_code))
+ && exit_code == STILL_ACTIVE))
+ break;
+ Sleep (10);
+ }
+ if ((status == FALSE && (err = GetLastError ()) == ERROR_INVALID_HANDLE)
+ || exit_code == STILL_ACTIVE)
+ {
+ if (!(status == FALSE && err == ERROR_INVALID_HANDLE))
+ TerminateThread (itimer->timer_thread, 0);
+ }
+
+ /* Clean up. */
+ CloseHandle (itimer->timer_thread);
+ itimer->timer_thread = NULL;
+ if (itimer->caller_thread)
+ {
+ CloseHandle (itimer->caller_thread);
+ itimer->caller_thread = NULL;
+ }
+}
+
+/* This is called at shutdown time from term_ntproc. */
+void
+term_timers (void)
+{
+ if (real_itimer.timer_thread)
+ stop_timer_thread (ITIMER_REAL);
+ if (prof_itimer.timer_thread)
+ stop_timer_thread (ITIMER_PROF);
+
+ /* We are going to delete the critical sections, so timers cannot
+ work after this. */
+ disable_itimers = 1;
+
+ DeleteCriticalSection (&crit_real);
+ DeleteCriticalSection (&crit_prof);
+ DeleteCriticalSection (&crit_sig);
+}
+
+/* This is called at initialization time from init_ntproc. */
+void
+init_timers (void)
+{
+ /* GetThreadTimes is not available on all versions of Windows, so
+ need to probe for its availability dynamically, and call it
+ through a pointer. */
+ s_pfn_Get_Thread_Times = NULL; /* in case dumped Emacs comes with a value */
+ if (os_subtype != OS_9X)
+ s_pfn_Get_Thread_Times =
+ (GetThreadTimes_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
+ "GetThreadTimes");
+
+ /* Make sure we start with zeroed out itimer structures, since
+ dumping may have left there traces of threads long dead. */
+ memset (&real_itimer, 0, sizeof real_itimer);
+ memset (&prof_itimer, 0, sizeof prof_itimer);
+
+ InitializeCriticalSection (&crit_real);
+ InitializeCriticalSection (&crit_prof);
+ InitializeCriticalSection (&crit_sig);
+
+ disable_itimers = 0;
+}
+
+static int
+start_timer_thread (int which)
+{
+ DWORD exit_code;
+ HANDLE th;
+ struct itimer_data *itimer =
+ (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
+
+ if (itimer->timer_thread
+ && GetExitCodeThread (itimer->timer_thread, &exit_code)
+ && exit_code == STILL_ACTIVE)
+ return 0;
+
+ /* Clean up after possibly exited thread. */
+ if (itimer->timer_thread)
+ {
+ CloseHandle (itimer->timer_thread);
+ itimer->timer_thread = NULL;
+ }
+ if (itimer->caller_thread)
+ {
+ CloseHandle (itimer->caller_thread);
+ itimer->caller_thread = NULL;
+ }
+
+ /* Start a new thread. */
+ if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+ GetCurrentProcess (), &th, 0, FALSE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errno = ESRCH;
+ return -1;
+ }
+ itimer->terminate = 0;
+ itimer->type = which;
+ itimer->caller_thread = th;
+ /* Request that no more than 64KB of stack be reserved for this
+ thread, to avoid reserving too much memory, which would get in
+ the way of threads we start to wait for subprocesses. See also
+ new_child below. */
+ itimer->timer_thread = CreateThread (NULL, 64 * 1024, timer_loop,
+ (void *)itimer, 0x00010000, NULL);
+
+ if (!itimer->timer_thread)
+ {
+ CloseHandle (itimer->caller_thread);
+ itimer->caller_thread = NULL;
+ errno = EAGAIN;
+ return -1;
+ }
+
+ /* This is needed to make sure that the timer thread running for
+ profiling gets CPU as soon as the Sleep call terminates. */
+ if (which == ITIMER_PROF)
+ SetThreadPriority (itimer->timer_thread, THREAD_PRIORITY_TIME_CRITICAL);
+
+ return 0;
+}
+
+/* Most of the code of getitimer and setitimer (but not of their
+ subroutines) was shamelessly stolen from itimer.c in the DJGPP
+ library, see www.delorie.com/djgpp. */
+int
+getitimer (int which, struct itimerval *value)
+{
+ volatile ULONGLONG *t_expire;
+ volatile ULONGLONG *t_reload;
+ ULONGLONG expire, reload;
+ __int64 usecs;
+ CRITICAL_SECTION *crit;
+ struct itimer_data *itimer;
+
+ if (disable_itimers)
+ return -1;
+
+ if (!value)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (which != ITIMER_REAL && which != ITIMER_PROF)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
+
+ ticks_now = w32_get_timer_time ((which == ITIMER_REAL)
+ ? NULL
+ : GetCurrentThread ());
+
+ t_expire = &itimer->expire;
+ t_reload = &itimer->reload;
+ crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
+
+ EnterCriticalSection (crit);
+ reload = *t_reload;
+ expire = *t_expire;
+ LeaveCriticalSection (crit);
+
+ if (expire)
+ expire -= ticks_now;
+
+ value->it_value.tv_sec = expire / TIMER_TICKS_PER_SEC;
+ usecs =
+ (expire % TIMER_TICKS_PER_SEC) * (__int64)1000000 / TIMER_TICKS_PER_SEC;
+ value->it_value.tv_usec = usecs;
+ value->it_interval.tv_sec = reload / TIMER_TICKS_PER_SEC;
+ usecs =
+ (reload % TIMER_TICKS_PER_SEC) * (__int64)1000000 / TIMER_TICKS_PER_SEC;
+ value->it_interval.tv_usec= usecs;
+
+ return 0;
+}
+
+int
+setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+{
+ volatile ULONGLONG *t_expire, *t_reload;
+ ULONGLONG expire, reload, expire_old, reload_old;
+ __int64 usecs;
+ CRITICAL_SECTION *crit;
+ struct itimerval tem, *ptem;
+
+ if (disable_itimers)
+ return -1;
+
+ /* Posix systems expect timer values smaller than the resolution of
+ the system clock be rounded up to the clock resolution. First
+ time we are called, measure the clock tick resolution. */
+ if (!clocks_min)
+ {
+ ULONGLONG t1, t2;
+
+ for (t1 = w32_get_timer_time (NULL);
+ (t2 = w32_get_timer_time (NULL)) == t1; )
+ ;
+ clocks_min = t2 - t1;
+ }
+
+ if (ovalue)
+ ptem = ovalue;
+ else
+ ptem = &tem;
+
+ if (getitimer (which, ptem)) /* also sets ticks_now */
+ return -1; /* errno already set */
+
+ t_expire =
+ (which == ITIMER_REAL) ? &real_itimer.expire : &prof_itimer.expire;
+ t_reload =
+ (which == ITIMER_REAL) ? &real_itimer.reload : &prof_itimer.reload;
+
+ crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
+
+ if (!value
+ || (value->it_value.tv_sec == 0 && value->it_value.tv_usec == 0))
+ {
+ EnterCriticalSection (crit);
+ /* Disable the timer. */
+ *t_expire = 0;
+ *t_reload = 0;
+ LeaveCriticalSection (crit);
+ return 0;
+ }
+
+ reload = value->it_interval.tv_sec * TIMER_TICKS_PER_SEC;
+
+ usecs = value->it_interval.tv_usec;
+ if (value->it_interval.tv_sec == 0
+ && usecs && usecs * TIMER_TICKS_PER_SEC < clocks_min * 1000000)
+ reload = clocks_min;
+ else
+ {
+ usecs *= TIMER_TICKS_PER_SEC;
+ reload += usecs / 1000000;
+ }
+
+ expire = value->it_value.tv_sec * TIMER_TICKS_PER_SEC;
+ usecs = value->it_value.tv_usec;
+ if (value->it_value.tv_sec == 0
+ && usecs * TIMER_TICKS_PER_SEC < clocks_min * 1000000)
+ expire = clocks_min;
+ else
+ {
+ usecs *= TIMER_TICKS_PER_SEC;
+ expire += usecs / 1000000;
+ }
+
+ expire += ticks_now;
+
+ EnterCriticalSection (crit);
+ expire_old = *t_expire;
+ reload_old = *t_reload;
+ if (!(expire == expire_old && reload == reload_old))
+ {
+ *t_reload = reload;
+ *t_expire = expire;
+ }
+ LeaveCriticalSection (crit);
+
+ return start_timer_thread (which);
+}
+
+int
+alarm (int seconds)
+{
+#ifdef HAVE_SETITIMER
+ struct itimerval new_values, old_values;
+
+ new_values.it_value.tv_sec = seconds;
+ new_values.it_value.tv_usec = 0;
+ new_values.it_interval.tv_sec = new_values.it_interval.tv_usec = 0;
+
+ if (setitimer (ITIMER_REAL, &new_values, &old_values) < 0)
+ return 0;
+ return old_values.it_value.tv_sec;
+#else
+ return seconds;
+#endif
+}
+
/* Defined in <process.h> which conflicts with the local copy */
#define _P_NOWAIT 1
/* Child process management list. */
int child_proc_count = 0;
child_process child_procs[ MAX_CHILDREN ];
-child_process *dead_child = NULL;
static DWORD WINAPI reader_thread (void *arg);
@@ -133,6 +812,8 @@ new_child (void)
cp->pid = -1;
cp->procinfo.hProcess = NULL;
cp->status = STATUS_READ_ERROR;
+ cp->input_file = NULL;
+ cp->pending_deletion = 0;
/* use manual reset event so that select() will function properly */
cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
@@ -176,11 +857,26 @@ delete_child (child_process *cp)
/* Should not be deleting a child that is still needed. */
for (i = 0; i < MAXDESC; i++)
if (fd_info[i].cp == cp)
- abort ();
+ emacs_abort ();
if (!CHILD_ACTIVE (cp))
return;
+ /* Delete the child's temporary input file, if any, that is pending
+ deletion. */
+ if (cp->input_file)
+ {
+ if (cp->pending_deletion)
+ {
+ if (unlink (cp->input_file))
+ DebPrint (("delete_child.unlink (%s) failed, errno: %d\n",
+ cp->input_file, errno));
+ cp->pending_deletion = 0;
+ }
+ xfree (cp->input_file);
+ cp->input_file = NULL;
+ }
+
/* reap thread if necessary */
if (cp->thrd)
{
@@ -316,7 +1012,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
DWORD flags;
char dir[ MAXPATHLEN ];
- if (cp == NULL) abort ();
+ if (cp == NULL) emacs_abort ();
memset (&start, 0, sizeof (start));
start.cb = sizeof (start);
@@ -362,9 +1058,6 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
if (cp->pid < 0)
cp->pid = -cp->pid;
- /* pid must fit in a Lisp_Int */
- cp->pid = cp->pid & INTMASK;
-
*pPid = cp->pid;
return TRUE;
@@ -380,11 +1073,11 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
This way the select emulator knows how to match file handles with
entries in child_procs. */
void
-register_child (int pid, int fd)
+register_child (pid_t pid, int fd)
{
child_process *cp;
- cp = find_child_pid (pid);
+ cp = find_child_pid ((DWORD)pid);
if (cp == NULL)
{
DebPrint (("register_child unable to find pid %lu\n", pid));
@@ -405,16 +1098,52 @@ register_child (int pid, int fd)
if (fd_info[fd].cp != NULL)
{
DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd));
- abort ();
+ emacs_abort ();
}
fd_info[fd].cp = cp;
}
-/* When a process dies its pipe will break so the reader thread will
- signal failure to the select emulator.
- The select emulator then calls this routine to clean up.
- Since the thread signaled failure we can assume it is exiting. */
+/* Record INFILE as an input file for process PID. */
+void
+record_infile (pid_t pid, char *infile)
+{
+ child_process *cp;
+
+ /* INFILE should never be NULL, since xstrdup would have signaled
+ memory full condition in that case, see callproc.c where this
+ function is called. */
+ eassert (infile);
+
+ cp = find_child_pid ((DWORD)pid);
+ if (cp == NULL)
+ {
+ DebPrint (("record_infile is unable to find pid %lu\n", pid));
+ return;
+ }
+
+ cp->input_file = infile;
+}
+
+/* Mark the input file INFILE of the corresponding subprocess as
+ temporary, to be deleted when the subprocess exits. */
+void
+record_pending_deletion (char *infile)
+{
+ child_process *cp;
+
+ eassert (infile);
+
+ for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
+ if (CHILD_ACTIVE (cp)
+ && cp->input_file && xstrcasecmp (cp->input_file, infile) == 0)
+ {
+ cp->pending_deletion = 1;
+ break;
+ }
+}
+
+/* Called from waitpid when a process exits. */
static void
reap_subprocess (child_process *cp)
{
@@ -424,7 +1153,7 @@ reap_subprocess (child_process *cp)
#ifdef FULL_DEBUG
/* Process should have already died before we are called. */
if (WaitForSingleObject (cp->procinfo.hProcess, 0) != WAIT_OBJECT_0)
- DebPrint (("reap_subprocess: child fpr fd %d has not died yet!", cp->fd));
+ DebPrint (("reap_subprocess: child for fd %d has not died yet!", cp->fd));
#endif
CloseHandle (cp->procinfo.hProcess);
cp->procinfo.hProcess = NULL;
@@ -440,62 +1169,126 @@ reap_subprocess (child_process *cp)
delete_child (cp);
}
-/* Wait for any of our existing child processes to die
- When it does, close its handle
- Return the pid and fill in the status if non-NULL. */
+/* Wait for a child process specified by PID, or for any of our
+ existing child processes (if PID is nonpositive) to die. When it
+ does, close its handle. Return the pid of the process that died
+ and fill in STATUS if non-NULL. */
-int
-sys_wait (int *status)
+pid_t
+waitpid (pid_t pid, int *status, int options)
{
DWORD active, retval;
int nh;
- int pid;
child_process *cp, *cps[MAX_CHILDREN];
HANDLE wait_hnd[MAX_CHILDREN];
+ DWORD timeout_ms;
+ int dont_wait = (options & WNOHANG) != 0;
nh = 0;
- if (dead_child != NULL)
+ /* According to Posix:
+
+ PID = -1 means status is requested for any child process.
+
+ PID > 0 means status is requested for a single child process
+ whose pid is PID.
+
+ PID = 0 means status is requested for any child process whose
+ process group ID is equal to that of the calling process. But
+ since Windows has only a limited support for process groups (only
+ for console processes and only for the purposes of passing
+ Ctrl-BREAK signal to them), and since we have no documented way
+ of determining whether a given process belongs to our group, we
+ treat 0 as -1.
+
+ PID < -1 means status is requested for any child process whose
+ process group ID is equal to the absolute value of PID. Again,
+ since we don't support process groups, we treat that as -1. */
+ if (pid > 0)
{
- /* We want to wait for a specific child */
- wait_hnd[nh] = dead_child->procinfo.hProcess;
- cps[nh] = dead_child;
- if (!wait_hnd[nh]) abort ();
- nh++;
- active = 0;
- goto get_result;
+ int our_child = 0;
+
+ /* We are requested to wait for a specific child. */
+ for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
+ {
+ /* Some child_procs might be sockets; ignore them. Also
+ ignore subprocesses whose output is not yet completely
+ read. */
+ if (CHILD_ACTIVE (cp)
+ && cp->procinfo.hProcess
+ && cp->pid == pid)
+ {
+ our_child = 1;
+ break;
+ }
+ }
+ if (our_child)
+ {
+ if (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
+ {
+ wait_hnd[nh] = cp->procinfo.hProcess;
+ cps[nh] = cp;
+ nh++;
+ }
+ else if (dont_wait)
+ {
+ /* PID specifies our subprocess, but its status is not
+ yet available. */
+ return 0;
+ }
+ }
+ if (nh == 0)
+ {
+ /* No such child process, or nothing to wait for, so fail. */
+ errno = ECHILD;
+ return -1;
+ }
}
else
{
for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
- /* some child_procs might be sockets; ignore them */
- if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
- && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
- {
- wait_hnd[nh] = cp->procinfo.hProcess;
- cps[nh] = cp;
- nh++;
- }
+ {
+ if (CHILD_ACTIVE (cp)
+ && cp->procinfo.hProcess
+ && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
+ {
+ wait_hnd[nh] = cp->procinfo.hProcess;
+ cps[nh] = cp;
+ nh++;
+ }
+ }
+ if (nh == 0)
+ {
+ /* Nothing to wait on, so fail. */
+ errno = ECHILD;
+ return -1;
+ }
}
- if (nh == 0)
- {
- /* Nothing to wait on, so fail */
- errno = ECHILD;
- return -1;
- }
+ if (dont_wait)
+ timeout_ms = 0;
+ else
+ timeout_ms = 1000; /* check for quit about once a second. */
do
{
- /* Check for quit about once a second. */
QUIT;
- active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000);
- } while (active == WAIT_TIMEOUT);
+ active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms);
+ } while (active == WAIT_TIMEOUT && !dont_wait);
if (active == WAIT_FAILED)
{
errno = EBADF;
return -1;
}
+ else if (active == WAIT_TIMEOUT && dont_wait)
+ {
+ /* PID specifies our subprocess, but it didn't exit yet, so its
+ status is not yet available. */
+#ifdef FULL_DEBUG
+ DebPrint (("Wait: PID %d not reap yet\n", cp->pid));
+#endif
+ return 0;
+ }
else if (active >= WAIT_OBJECT_0
&& active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
{
@@ -507,9 +1300,8 @@ sys_wait (int *status)
active -= WAIT_ABANDONED_0;
}
else
- abort ();
+ emacs_abort ();
-get_result:
if (!GetExitCodeProcess (wait_hnd[active], &retval))
{
DebPrint (("Wait.GetExitCodeProcess failed with %lu\n",
@@ -518,8 +1310,10 @@ get_result:
}
if (retval == STILL_ACTIVE)
{
- /* Should never happen */
+ /* Should never happen. */
DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
+ if (pid > 0 && dont_wait)
+ return 0;
errno = EINVAL;
return -1;
}
@@ -533,6 +1327,8 @@ get_result:
else
retval <<= 8;
+ if (pid > 0 && active != 0)
+ emacs_abort ();
cp = cps[active];
pid = cp->pid;
#ifdef FULL_DEBUG
@@ -540,33 +1336,7 @@ get_result:
#endif
if (status)
- {
- *status = retval;
- }
- else if (synch_process_alive)
- {
- synch_process_alive = 0;
-
- /* Report the status of the synchronous process. */
- if (WIFEXITED (retval))
- synch_process_retcode = WEXITSTATUS (retval);
- else if (WIFSIGNALED (retval))
- {
- int code = WTERMSIG (retval);
- char *signame;
-
- synchronize_system_messages_locale ();
- signame = strsignal (code);
-
- if (signame == 0)
- signame = "unknown";
-
- synch_process_death = signame;
- }
-
- reap_subprocess (cp);
- }
-
+ *status = retval;
reap_subprocess (cp);
return pid;
@@ -628,7 +1398,7 @@ w32_executable_type (char * filename,
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
goto unwind;
- nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
+ nt_header = (PIMAGE_NT_HEADERS) ((unsigned char *) dos_header + dos_header->e_lfanew);
if ((char *) nt_header > (char *) dos_header + executable.size)
{
@@ -751,7 +1521,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
Lisp_Object program, full;
char *cmdline, *env, *parg, **targ;
int arglen, numenv;
- int pid;
+ pid_t pid;
child_process *cp;
int is_dos_app, is_cygnus_app, is_gui_app;
int do_quoting = 0;
@@ -1012,7 +1782,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
numenv++;
}
/* extra env vars... */
- sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d",
+ sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%lu",
GetCurrentProcessId ());
arglen += strlen (ppid_env_var_buffer) + 1;
numenv++;
@@ -1140,7 +1910,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
}
else
{
- /* Child process and socket input */
+ /* Child process and socket/comm port input. */
cp = fd_info[i].cp;
if (cp)
{
@@ -1153,7 +1923,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
/* Wake up the reader thread for this process */
cp->status = STATUS_READ_READY;
if (!SetEvent (cp->char_consumed))
- DebPrint (("nt_select.SetEvent failed with "
+ DebPrint (("sys_select.SetEvent failed with "
"%lu for fd %ld\n", GetLastError (), i));
}
@@ -1189,7 +1959,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
#endif
wait_hnd[nh] = cp->char_avail;
fdindex[nh] = i;
- if (!wait_hnd[nh]) abort ();
+ if (!wait_hnd[nh]) emacs_abort ();
nh++;
#ifdef FULL_DEBUG
DebPrint (("select waiting on child %d fd %d\n",
@@ -1276,7 +2046,7 @@ count_children:
active -= WAIT_ABANDONED_0;
}
else
- abort ();
+ emacs_abort ();
/* Loop over all handles after active (now officially documented as
being the first signaled handle in the array). We do this to
@@ -1301,7 +2071,24 @@ count_children:
(*) Note that MsgWaitForMultipleObjects above is an
internal dispatch point for messages that are sent to
windows created by this thread. */
- drain_message_queue ();
+ if (drain_message_queue ()
+ /* If drain_message_queue returns non-zero, that means
+ we received a WM_EMACS_FILENOTIFY message. If this
+ is a TTY frame, we must signal the caller that keyboard
+ input is available, so that w32_console_read_socket
+ will be called to pick up the notifications. If we
+ don't do that, file notifications will only work when
+ the Emacs TTY frame has focus. */
+ && FRAME_TERMCAP_P (SELECTED_FRAME ())
+ /* they asked for stdin reads */
+ && FD_ISSET (0, &orfds)
+ /* the stdin handle is valid */
+ && keyboard_handle)
+ {
+ FD_SET (0, rfds);
+ if (nr == 0)
+ nr = 1;
+ }
}
else if (active >= nh)
{
@@ -1321,9 +2108,7 @@ count_children:
DebPrint (("select calling SIGCHLD handler for pid %d\n",
cp->pid));
#endif
- dead_child = cp;
sig_handlers[SIGCHLD] (SIGCHLD);
- dead_child = NULL;
}
}
else if (fdindex[active] == -1)
@@ -1398,14 +2183,19 @@ find_child_console (HWND hwnd, LPARAM arg)
return TRUE;
}
+/* Emulate 'kill', but only for other processes. */
int
-sys_kill (int pid, int sig)
+sys_kill (pid_t pid, int sig)
{
child_process *cp;
HANDLE proc_hand;
int need_to_free = 0;
int rc = 0;
+ /* Each process is in its own process group. */
+ if (pid < 0)
+ pid = -pid;
+
/* Only handle signals that will result in the process dying */
if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
{
@@ -1416,6 +2206,11 @@ sys_kill (int pid, int sig)
cp = find_child_pid (pid);
if (cp == NULL)
{
+ /* We were passed a PID of something other than our subprocess.
+ If that is our own PID, we will send to ourself a message to
+ close the selected frame, which does not necessarily
+ terminates Emacs. But then we are not supposed to call
+ sys_kill with our own PID. */
proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
if (proc_hand == NULL)
{
diff --git a/src/w32reg.c b/src/w32reg.c
index 9c727ae5ab7..8b6c76503a6 100644
--- a/src/w32reg.c
+++ b/src/w32reg.c
@@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Kevin Gallo */
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
#include "w32term.h"
#include "blockinput.h"
@@ -85,7 +84,7 @@ w32_get_string_resource (char *name, char *class, DWORD dwexptype)
trykey:
- BLOCK_INPUT;
+ block_input ();
/* Check both the current user and the local machine to see if we have
any resources */
@@ -116,7 +115,7 @@ w32_get_string_resource (char *name, char *class, DWORD dwexptype)
RegCloseKey (hrootkey);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (!ok)
{
diff --git a/src/w32select.c b/src/w32select.c
index 59ff4405368..6a2a840f914 100644
--- a/src/w32select.c
+++ b/src/w32select.c
@@ -73,15 +73,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
*/
#include <config.h>
-#include <setjmp.h>
#include "lisp.h"
+#include "w32common.h" /* os_subtype */
#include "w32term.h" /* for all of the w32 includes */
-#include "w32heap.h" /* os_subtype */
+#include "keyboard.h"
#include "blockinput.h"
#include "charset.h"
#include "coding.h"
#include "composite.h"
+#ifdef CYGWIN
+#include <string.h>
+#include <stdio.h>
+#define _memccpy memccpy
+#endif
static HGLOBAL convert_to_handle_as_ascii (void);
static HGLOBAL convert_to_handle_as_coded (Lisp_Object coding_system);
@@ -389,12 +394,11 @@ run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg)
with global variables and calling strange looking functions. Is
this really the right way to run Lisp callbacks? */
- extern int waiting_for_input; /* from keyboard.c */
int owfi;
- BLOCK_INPUT;
+ block_input ();
- /* Fsignal calls abort() if it sees that waiting_for_input is
+ /* Fsignal calls emacs_abort () if it sees that waiting_for_input is
set. */
owfi = waiting_for_input;
waiting_for_input = 0;
@@ -403,7 +407,7 @@ run_protected (Lisp_Object (*code) (Lisp_Object), Lisp_Object arg)
waiting_for_input = owfi;
- UNBLOCK_INPUT;
+ unblock_input ();
}
static Lisp_Object
@@ -475,7 +479,10 @@ term_w32select (void)
{
/* This is needed to trigger WM_RENDERALLFORMATS. */
if (clipboard_owner != NULL)
- DestroyWindow (clipboard_owner);
+ {
+ DestroyWindow (clipboard_owner);
+ clipboard_owner = NULL;
+ }
}
static void
@@ -695,7 +702,7 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data,
current_num_nls = 0;
current_requires_encoding = 0;
- BLOCK_INPUT;
+ block_input ();
/* Check for non-ASCII characters. While we are at it, count the
number of LFs, so we know how many CRs we will have to add later
@@ -783,7 +790,7 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data,
current_coding_system = Qnil;
done:
- UNBLOCK_INPUT;
+ unblock_input ();
return (ok ? string : Qnil);
}
@@ -811,7 +818,7 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
setup_config ();
actual_clipboard_type = cfg_clipboard_type;
- BLOCK_INPUT;
+ block_input ();
if (!OpenClipboard (clipboard_owner))
goto done;
@@ -1001,7 +1008,7 @@ DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
CloseClipboard ();
done:
- UNBLOCK_INPUT;
+ unblock_input ();
return (ret);
}
diff --git a/src/w32select.h b/src/w32select.h
new file mode 100644
index 00000000000..4f4de59f7fe
--- /dev/null
+++ b/src/w32select.h
@@ -0,0 +1,28 @@
+/* Selection processing for Emacs on the Microsoft W32 API.
+
+Copyright (C) 1993-1994, 2001-2012 Free Software Foundation, Inc.
+
+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 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/>. */
+
+#ifndef W32SELECT_H
+#define W32SELECT_H
+#include <windows.h>
+
+extern void syms_of_w32select (void);
+extern void globals_of_w32select (void);
+extern void term_w32select (void);
+
+#endif
diff --git a/src/w32term.c b/src/w32term.c
index 6948a98998e..7c53097e313 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "blockinput.h"
#include "w32term.h"
@@ -52,7 +51,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "atimer.h"
#include "keymap.h"
+#ifdef WINDOWSNT
#include "w32heap.h"
+#endif
+
+#ifndef WINDOWSNT
+#include <io.h> /* for get_osfhandle */
+#endif
+
#include <shellapi.h>
#include "font.h"
@@ -103,7 +109,7 @@ struct w32_display_info *x_display_list;
Lisp_Object w32_display_name_list;
-#ifndef GLYPHSET
+#if _WIN32_WINNT < 0x0500
/* Pre Windows 2000, this was not available, but define it here so
that Emacs compiled on such a platform will run on newer versions. */
@@ -122,7 +128,7 @@ typedef struct tagGLYPHSET
WCRANGE ranges[1];
} GLYPHSET;
-#endif
+#endif /* compiling for pre-Win2k */
/* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
@@ -191,6 +197,10 @@ static int volatile input_signal_count;
static int input_signal_count;
#endif
+#ifdef CYGWIN
+int w32_message_fd = -1;
+#endif /* CYGWIN */
+
static void x_update_window_end (struct window *, int, int);
static void w32_handle_tool_bar_click (struct frame *,
struct input_event *);
@@ -198,7 +208,7 @@ static void w32_define_cursor (Window, Cursor);
void x_lower_frame (struct frame *);
void x_scroll_bar_clear (struct frame *);
-void x_wm_set_size_hint (struct frame *, long, int);
+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);
void x_wm_set_window_state (struct frame *, int);
@@ -236,6 +246,8 @@ 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;
/***********************************************************************
@@ -361,7 +373,11 @@ w32_draw_underwave (struct glyph_string *s, COLORREF color)
/* Find and set clipping rectangle */
- wave_clip = (XRectangle){ x0, y0, width, wave_height };
+ wave_clip.x = x0;
+ wave_clip.y = y0;
+ wave_clip.width = width;
+ wave_clip.height = wave_height;
+
get_glyph_string_clip_rect (s, &w32_string_clip);
CONVERT_TO_XRECT (string_clip, w32_string_clip);
@@ -564,7 +580,7 @@ x_update_window_begin (struct window *w)
updated_window = w;
set_output_cursor (&w->cursor);
- BLOCK_INPUT;
+ block_input ();
if (f == hlinfo->mouse_face_mouse_frame)
{
@@ -603,7 +619,7 @@ x_update_window_begin (struct window *w)
#endif /* 0 */
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Draw a vertical window border from (x,y0) to (x,y1) */
@@ -653,7 +669,7 @@ x_update_window_end (struct window *w, int cursor_on_p,
if (!w->pseudo_window_p)
{
- BLOCK_INPUT;
+ block_input ();
if (cursor_on_p)
display_and_set_cursor (w, 1, output_cursor.hpos,
@@ -663,7 +679,7 @@ x_update_window_end (struct window *w, int cursor_on_p,
if (draw_window_fringes (w, 1))
x_draw_vertical_border (w);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* If a row with mouse-face was overwritten, arrange for
@@ -709,21 +725,7 @@ static void
w32_frame_up_to_date (struct frame *f)
{
if (FRAME_W32_P (f))
- {
- Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-
- if (hlinfo->mouse_face_deferred_gc
- || f == hlinfo->mouse_face_mouse_frame)
- {
- BLOCK_INPUT;
- if (hlinfo->mouse_face_mouse_frame)
- note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
- hlinfo->mouse_face_mouse_x,
- hlinfo->mouse_face_mouse_y);
- hlinfo->mouse_face_deferred_gc = 0;
- UNBLOCK_INPUT;
- }
- }
+ FRAME_MOUSE_UPDATE (f);
}
@@ -762,7 +764,7 @@ x_after_update_window_line (struct glyph_row *desired_row)
{
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
- BLOCK_INPUT;
+ block_input ();
{
HDC hdc = get_frame_dc (f);
w32_clear_area (f, hdc, 0, y, width, height);
@@ -770,7 +772,7 @@ x_after_update_window_line (struct glyph_row *desired_row)
y, width, height);
release_frame_dc (f, hdc);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1738,8 +1740,8 @@ w32_draw_relief_rect (struct frame *f,
if (left_p)
for (i = 0; i < width; ++i)
w32_fill_area (f, hdc, gc.foreground,
- left_x + i, top_y + i, 1,
- bottom_y - top_y - 2 * i + 1);
+ left_x + i, top_y + (i + 1) * top_p, 1,
+ bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
if (raised_p)
gc.foreground = f->output_data.w32->black_relief.gc->foreground;
@@ -1757,8 +1759,8 @@ w32_draw_relief_rect (struct frame *f,
if (right_p)
for (i = 0; i < width; ++i)
w32_fill_area (f, hdc, gc.foreground,
- right_x - i, top_y + i + 1, 1,
- bottom_y - top_y - 2 * i - 1);
+ right_x - i, top_y + (i + 1) * top_p, 1,
+ bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
w32_set_clip_rectangle (hdc, NULL);
@@ -1952,7 +1954,7 @@ x_draw_image_foreground (struct glyph_string *s)
static void
x_draw_image_relief (struct glyph_string *s)
{
- int x0, y0, x1, y1, thick, raised_p;
+ int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
RECT r;
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
@@ -1984,19 +1986,23 @@ x_draw_image_relief (struct glyph_string *s)
raised_p = s->img->relief > 0;
}
- x0 = x - thick;
- y0 = y - thick;
- x1 = x + s->slice.width + thick - 1;
- y1 = y + s->slice.height + thick - 1;
+ x1 = x + s->slice.width - 1;
+ y1 = y + s->slice.height - 1;
+ top_p = bot_p = left_p = right_p = 0;
+
+ if (s->slice.x == 0)
+ x -= thick, left_p = 1;
+ if (s->slice.y == 0)
+ y -= thick, top_p = 1;
+ if (s->slice.x + s->slice.width == s->img->width)
+ x1 += thick, right_p = 1;
+ if (s->slice.y + s->slice.height == s->img->height)
+ y1 += thick, bot_p = 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
- w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
- s->slice.y == 0,
- s->slice.y + s->slice.height == s->img->height,
- s->slice.x == 0,
- s->slice.x + s->slice.width == s->img->width,
- &r);
+ w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+ top_p, bot_p, left_p, right_p, &r);
}
@@ -2426,7 +2432,7 @@ x_draw_glyph_string (struct glyph_string *s)
break;
default:
- abort ();
+ emacs_abort ();
}
if (!s->for_overlaps)
@@ -2591,6 +2597,7 @@ x_draw_glyph_string (struct glyph_string *s)
w32_set_clip_rectangle (next->hdc, NULL);
next->hl = save;
next->num_clips = 0;
+ next->clip_head = s->next;
}
}
}
@@ -2626,7 +2633,7 @@ x_delete_glyphs (struct frame *f, register int n)
if (! FRAME_W32_P (f))
return;
- abort ();
+ emacs_abort ();
}
@@ -2646,7 +2653,7 @@ x_clear_frame (struct frame *f)
/* We don't set the output cursor here because there will always
follow an explicit cursor_to. */
- BLOCK_INPUT;
+ block_input ();
w32_clear_window (f);
@@ -2654,7 +2661,7 @@ x_clear_frame (struct frame *f)
colors or something like that, then they should be notified. */
x_scroll_bar_clear (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2663,7 +2670,7 @@ x_clear_frame (struct frame *f)
static void
w32_ring_bell (struct frame *f)
{
- BLOCK_INPUT;
+ block_input ();
if (FRAME_W32_P (f) && visible_bell)
{
@@ -2680,7 +2687,7 @@ w32_ring_bell (struct frame *f)
else
w32_sys_ring_bell (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2709,7 +2716,7 @@ x_ins_del_lines (struct frame *f, int vpos, int n)
if (! FRAME_W32_P (f))
return;
- abort ();
+ emacs_abort ();
}
@@ -2779,7 +2786,7 @@ x_scroll_run (struct window *w, struct run *run)
expect_dirty = CreateRectRgn (x, y, x + width, to_y);
}
- BLOCK_INPUT;
+ block_input ();
/* Cursor off. Will be switched on again in x_update_window_end. */
updated_window = w;
@@ -2813,7 +2820,7 @@ x_scroll_run (struct window *w, struct run *run)
DeleteObject (combined);
}
- UNBLOCK_INPUT;
+ unblock_input ();
DeleteObject (expect_dirty);
}
@@ -2998,9 +3005,9 @@ x_get_keysym_name (int keysym)
/* Make static so we can always return it */
static char value[100];
- BLOCK_INPUT;
+ block_input ();
GetKeyNameText (keysym, value, 100);
- UNBLOCK_INPUT;
+ unblock_input ();
return value;
}
@@ -3199,6 +3206,124 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
}
+/* File event notifications (see w32notify.c). */
+
+Lisp_Object
+lispy_file_action (DWORD action)
+{
+ static char unknown_fmt[] = "unknown-action(%d)";
+ Lisp_Object retval;
+
+ switch (action)
+ {
+ case FILE_ACTION_ADDED:
+ retval = Qadded;
+ break;
+ case FILE_ACTION_REMOVED:
+ retval = Qremoved;
+ break;
+ case FILE_ACTION_MODIFIED:
+ retval = Qmodified;
+ break;
+ case FILE_ACTION_RENAMED_OLD_NAME:
+ retval = Qrenamed_from;
+ break;
+ case FILE_ACTION_RENAMED_NEW_NAME:
+ retval = Qrenamed_to;
+ break;
+ default:
+ {
+ char buf[sizeof(unknown_fmt) - 1 + INT_STRLEN_BOUND (DWORD)];
+
+ sprintf (buf, unknown_fmt, action);
+ retval = intern (buf);
+ }
+ break;
+ }
+
+ return retval;
+}
+
+#ifdef WINDOWSNT
+/* Put file notifications into the Emacs input event queue. This
+ function runs when the WM_EMACS_FILENOTIFY message arrives from a
+ watcher thread. */
+static void
+queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
+ int *evcount)
+{
+ BYTE *p = file_notifications;
+ FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
+ const DWORD min_size
+ = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+ Lisp_Object frame;
+
+ /* We cannot process notification before Emacs is fully initialized,
+ since we need the UTF-16LE coding-system to be set up. */
+ if (!initialized)
+ {
+ notification_buffer_in_use = 0;
+ return;
+ }
+
+ XSETFRAME (frame, f);
+
+ enter_crit ();
+ if (notification_buffer_in_use)
+ {
+ DWORD info_size = notifications_size;
+ Lisp_Object cs = intern ("utf-16le");
+ Lisp_Object obj = w32_get_watch_object (notifications_desc);
+
+ /* notifications_size could be zero when the buffer of
+ notifications overflowed on the OS level, or when the
+ directory being watched was itself deleted. Do nothing in
+ that case. */
+ if (info_size
+ && !NILP (obj) && CONSP (obj))
+ {
+ Lisp_Object callback = XCDR (obj);
+
+ while (info_size >= min_size)
+ {
+ Lisp_Object utf_16_fn
+ = make_unibyte_string ((char *)fni->FileName,
+ fni->FileNameLength);
+ /* Note: mule-conf is preloaded, so utf-16le must
+ already be defined at this point. */
+ Lisp_Object fname
+ = code_convert_string_norecord (utf_16_fn, cs, 0);
+ 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);
+ kbd_buffer_store_event (event);
+ (*evcount)++;
+
+ if (!fni->NextEntryOffset)
+ break;
+ p += fni->NextEntryOffset;
+ fni = (PFILE_NOTIFY_INFORMATION)p;
+ info_size -= fni->NextEntryOffset;
+ }
+ }
+ notification_buffer_in_use = 0;
+ }
+ else
+ DebPrint (("We were promised notifications, but in-use flag is zero!\n"));
+ leave_crit ();
+
+ /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */
+ event->kind = NO_EVENT;
+}
+#endif
+
+
/* Function to report a mouse movement to the mainstream Emacs code.
The input handler calls this.
@@ -3308,7 +3433,7 @@ w32_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
{
FRAME_PTR f1;
- BLOCK_INPUT;
+ block_input ();
if (! NILP (last_mouse_scroll_bar) && insist == 0)
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
@@ -3382,7 +3507,7 @@ w32_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3422,16 +3547,11 @@ w32_handle_tool_bar_click (struct frame *f, struct input_event *button_event)
static struct scroll_bar *
x_window_to_scroll_bar (Window window_id)
{
- Lisp_Object tail;
+ Lisp_Object tail, frame;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- Lisp_Object frame, bar, condemned;
-
- frame = XCAR (tail);
- /* All elements of Vframe_list should be frames. */
- if (! FRAMEP (frame))
- abort ();
+ Lisp_Object bar, condemned;
/* Scan this frame's scroll bar list for a scroll bar with the
right window ID. */
@@ -3480,12 +3600,12 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar,
if (draggingp)
{
int near_bottom_p;
- BLOCK_INPUT;
+ block_input ();
si.cbSize = sizeof (si);
si.fMask = SIF_POS | SIF_PAGE;
GetScrollInfo (w, SB_CTL, &si);
near_bottom_p = si.nPos + si.nPage >= range;
- UNBLOCK_INPUT;
+ unblock_input ();
if (!near_bottom_p)
return;
}
@@ -3514,7 +3634,7 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar,
sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
- BLOCK_INPUT;
+ block_input ();
si.cbSize = sizeof (si);
si.fMask = SIF_PAGE | SIF_POS;
@@ -3523,7 +3643,7 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar,
SetScrollInfo (w, SB_CTL, &si, TRUE);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3611,10 +3731,10 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
HWND hwnd;
SCROLLINFO si;
struct scroll_bar *bar
- = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
+ = XSCROLL_BAR (Fmake_vector (make_number (VECSIZE (struct scroll_bar)), Qnil));
Lisp_Object barobj;
- BLOCK_INPUT;
+ block_input ();
XSETWINDOW (bar->window, w);
XSETINT (bar->top, top);
@@ -3650,7 +3770,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
if (! NILP (bar->next))
XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
- UNBLOCK_INPUT;
+ unblock_input ();
return bar;
}
@@ -3664,7 +3784,7 @@ x_scroll_bar_remove (struct scroll_bar *bar)
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- BLOCK_INPUT;
+ block_input ();
/* Destroy the window. */
my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
@@ -3672,7 +3792,7 @@ x_scroll_bar_remove (struct scroll_bar *bar)
/* Dissociate this scroll bar from its window. */
wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Set the handle of the vertical scroll bar for WINDOW to indicate
@@ -3727,7 +3847,7 @@ w32_set_vertical_scroll_bar (struct window *w,
if (NILP (w->vertical_scroll_bar))
{
HDC hdc;
- BLOCK_INPUT;
+ block_input ();
if (width > 0 && height > 0)
{
hdc = get_frame_dc (f);
@@ -3737,7 +3857,7 @@ w32_set_vertical_scroll_bar (struct window *w,
w32_clear_area (f, hdc, left, top, width, height);
release_frame_dc (f, hdc);
}
- UNBLOCK_INPUT;
+ unblock_input ();
bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
}
@@ -3765,7 +3885,7 @@ w32_set_vertical_scroll_bar (struct window *w,
HDC hdc;
SCROLLINFO si;
- BLOCK_INPUT;
+ block_input ();
if (width && height)
{
hdc = get_frame_dc (f);
@@ -3801,7 +3921,7 @@ w32_set_vertical_scroll_bar (struct window *w,
XSETINT (bar->width, sb_width);
XSETINT (bar->height, height);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
@@ -3854,7 +3974,7 @@ w32_redeem_scroll_bar (struct window *window)
/* We can't redeem this window's scroll bar if it doesn't have one. */
if (NILP (window->vertical_scroll_bar))
- abort ();
+ emacs_abort ();
bar = XSCROLL_BAR (window->vertical_scroll_bar);
@@ -3873,7 +3993,7 @@ w32_redeem_scroll_bar (struct window *window)
else
/* If its prev pointer is nil, it must be at the front of
one or the other! */
- abort ();
+ emacs_abort ();
}
else
XSCROLL_BAR (bar->prev)->next = bar->next;
@@ -3928,7 +4048,7 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
struct input_event *emacs_event)
{
if (! WINDOWP (bar->window))
- abort ();
+ emacs_abort ();
emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
emacs_event->code = 0;
@@ -4043,7 +4163,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
SCROLLINFO si;
- BLOCK_INPUT;
+ block_input ();
*fp = f;
*bar_window = bar->window;
@@ -4080,7 +4200,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
*time = last_mouse_movement_time;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -4134,11 +4254,12 @@ static char dbcs_lead = 0;
This routine is called by the SIGIO handler.
We return as soon as there are no more events to be read.
+ For an overview of how Emacs input works on MS-Windows, see the
+ commentary before w32_msg_pump in w32fns.c.
+
We return the number of characters stored into the buffer,
thus pretending to be `read'.
- EXPECTED is nonzero if the caller knows input is available.
-
Some of these messages are reposted back to the message queue since the
system calls the windows proc directly in a context where we cannot return
the data nor can we guarantee the state we are in. So if we dispatch them
@@ -4149,7 +4270,7 @@ static char dbcs_lead = 0;
*/
static int
-w32_read_socket (struct terminal *terminal, int expected,
+w32_read_socket (struct terminal *terminal,
struct input_event *hold_quit)
{
int count = 0;
@@ -4158,25 +4279,26 @@ w32_read_socket (struct terminal *terminal, int expected,
struct frame *f;
struct w32_display_info *dpyinfo = &one_w32_display_info;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
+ static char buf[1];
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
+ block_input ();
/* So people can tell when we have read the available input. */
input_signal_count++;
+ /* Process any incoming thread messages. */
+ drain_message_queue ();
+
/* TODO: ghostscript integration. */
while (get_next_msg (&msg, FALSE))
{
struct input_event inev;
int do_help = 0;
+ /* DebPrint (("w32_read_socket: %s time:%u\n", */
+ /* w32_name_of_message (msg.msg.message), */
+ /* msg.msg.time)); */
+
EVENT_INIT (inev);
inev.kind = NO_EVENT;
inev.arg = Qnil;
@@ -4834,6 +4956,14 @@ w32_read_socket (struct terminal *terminal, int expected,
check_visibility = 1;
break;
+#ifdef WINDOWSNT
+ case WM_EMACS_FILENOTIFY:
+ f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+ if (f)
+ queue_notifications (&inev, &msg, f, &count);
+ break;
+#endif
+
default:
/* Check for messages registered at runtime. */
if (msg.msg.message == msh_mousewheel)
@@ -4962,7 +5092,7 @@ w32_read_socket (struct terminal *terminal, int expected,
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return count;
}
@@ -5233,7 +5363,7 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
break;
default:
- abort ();
+ emacs_abort ();
}
}
}
@@ -5346,7 +5476,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_SPACE_WIDTH (f) = font->space_width;
FRAME_LINE_HEIGHT (f) = font->height;
compute_fringe_widths (f, 1);
@@ -5477,7 +5606,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
}
x_calc_absolute_position (f);
- BLOCK_INPUT;
+ block_input ();
x_wm_set_size_hint (f, (long) 0, 0);
modified_left = f->left_pos;
@@ -5488,7 +5617,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
modified_left, modified_top,
0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5529,7 +5658,7 @@ x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
{
int pixelwidth, pixelheight;
- BLOCK_INPUT;
+ block_input ();
check_frame_size (f, &rows, &cols);
f->scroll_bar_actual_width
@@ -5609,7 +5738,7 @@ x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
cancel_mouse_face (f);
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Mouse warping. */
@@ -5639,7 +5768,7 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
RECT rect;
POINT pt;
- BLOCK_INPUT;
+ block_input ();
GetClientRect (FRAME_W32_WINDOW (f), &rect);
pt.x = rect.left + pix_x;
@@ -5648,7 +5777,7 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
SetCursorPos (pt.x, pt.y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5660,7 +5789,7 @@ x_focus_on_frame (struct frame *f)
struct w32_display_info *dpyinfo = &one_w32_display_info;
/* Give input focus to frame. */
- BLOCK_INPUT;
+ block_input ();
#if 0
/* Try not to change its Z-order if possible. */
if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
@@ -5668,7 +5797,7 @@ x_focus_on_frame (struct frame *f)
else
#endif
my_set_foreground_window (FRAME_W32_WINDOW (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
void
@@ -5680,7 +5809,7 @@ x_unfocus_frame (struct frame *f)
void
x_raise_frame (struct frame *f)
{
- BLOCK_INPUT;
+ block_input ();
/* Strictly speaking, raise-frame should only change the frame's Z
order, leaving input focus unchanged. This is reasonable behavior
@@ -5735,19 +5864,19 @@ x_raise_frame (struct frame *f)
my_bring_window_to_top (FRAME_W32_WINDOW (f));
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Lower frame F. */
void
x_lower_frame (struct frame *f)
{
- BLOCK_INPUT;
+ block_input ();
my_set_window_pos (FRAME_W32_WINDOW (f),
HWND_BOTTOM,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
- UNBLOCK_INPUT;
+ unblock_input ();
}
static void
@@ -5776,7 +5905,7 @@ x_make_frame_visible (struct frame *f)
{
Lisp_Object type;
- BLOCK_INPUT;
+ block_input ();
type = x_icon_type (f);
if (!NILP (type))
@@ -5828,7 +5957,7 @@ x_make_frame_visible (struct frame *f)
int count;
/* This must come after we set COUNT. */
- UNBLOCK_INPUT;
+ unblock_input ();
XSETFRAME (frame, f);
@@ -5871,7 +6000,7 @@ x_make_frame_invisible (struct frame *f)
if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
- BLOCK_INPUT;
+ block_input ();
my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
@@ -5885,7 +6014,7 @@ x_make_frame_invisible (struct frame *f)
f->async_visible = 0;
f->async_iconified = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Change window state from mapped to iconified. */
@@ -5902,7 +6031,7 @@ x_iconify_frame (struct frame *f)
if (f->async_iconified)
return;
- BLOCK_INPUT;
+ block_input ();
type = x_icon_type (f);
if (!NILP (type))
@@ -5911,7 +6040,7 @@ x_iconify_frame (struct frame *f)
/* Simulate the user minimizing the frame. */
SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5923,7 +6052,7 @@ x_free_frame_resources (struct frame *f)
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
- BLOCK_INPUT;
+ block_input ();
/* We must free faces before destroying windows because some
font-driver (e.g. xft) access a window while finishing a
@@ -5967,11 +6096,10 @@ x_free_frame_resources (struct frame *f)
hlinfo->mouse_face_end_row
= hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_window = Qnil;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_mouse_frame = 0;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5991,10 +6119,10 @@ x_destroy_window (struct frame *f)
/* Set the normal size hints for the window manager, for frame F.
FLAGS is the flags word to use--or 0 meaning preserve the flags
that the window now has.
- If USER_POSITION is nonzero, we set the USPosition
+ If USER_POSITION, set the USPosition
flag (this is useful when FLAGS is 0). */
void
-x_wm_set_size_hint (struct frame *f, long flags, int user_position)
+x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
{
Window window = FRAME_W32_WINDOW (f);
@@ -6255,10 +6383,10 @@ x_delete_terminal (struct terminal *terminal)
if (!terminal->name)
return;
- BLOCK_INPUT;
+ block_input ();
x_delete_display (dpyinfo);
- UNBLOCK_INPUT;
+ unblock_input ();
}
struct w32_display_info *
@@ -6268,7 +6396,7 @@ w32_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
struct terminal *terminal;
HDC hdc;
- BLOCK_INPUT;
+ block_input ();
if (!w32_initialized)
{
@@ -6309,8 +6437,15 @@ w32_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
w32_defined_color (0, "black", &color, 1);
}
- /* Add the default keyboard. */
+#ifdef WINDOWSNT
+ /* Add the default keyboard. When !WINDOWSNT, we're using the
+ standard Emacs console handling machinery and don't need an
+ explicit FD here. */
add_keyboard_wait_descriptor (0);
+#elif CYGWIN
+ /* /dev/windows wakes us up when we have a thread message pending. */
+ add_keyboard_wait_descriptor (w32_message_fd);
+#endif
/* Create Fringe Bitmaps and store them for later use.
@@ -6321,16 +6456,7 @@ w32_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
the bitmaps. */
w32_init_fringe (terminal->rif);
-#ifdef F_SETOWN
- fcntl (connection, F_SETOWN, getpid ());
-#endif /* ! defined (F_SETOWN) */
-
-#ifdef SIGIO
- if (interrupt_input)
- init_sigio (connection);
-#endif /* ! defined (SIGIO) */
-
- UNBLOCK_INPUT;
+ unblock_input ();
return dpyinfo;
}
@@ -6379,6 +6505,7 @@ x_delete_display (struct w32_display_info *dpyinfo)
w32_reset_fringes ();
}
+
/* Set up use of W32. */
@@ -6416,6 +6543,11 @@ w32_initialize (void)
set_user_model (L"GNU.Emacs");
}
+#ifdef CYGWIN
+ if ((w32_message_fd = open ("/dev/windows", O_RDWR | O_CLOEXEC)) == -1)
+ fatal ("opening /dev/windows: %s", strerror (errno));
+#endif /* CYGWIN */
+
/* Initialize w32_use_visible_system_caret based on whether a screen
reader is in use. */
if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
@@ -6499,6 +6631,12 @@ syms_of_w32term (void)
DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
+ DEFSYM (Qadded, "added");
+ DEFSYM (Qremoved, "removed");
+ DEFSYM (Qmodified, "modified");
+ DEFSYM (Qrenamed_from, "renamed-from");
+ DEFSYM (Qrenamed_to, "renamed-to");
+
DEFVAR_INT ("w32-num-mouse-buttons",
w32_num_mouse_buttons,
doc: /* Number of physical mouse buttons. */);
@@ -6576,4 +6714,6 @@ With MS Windows or Nextstep, the value is t. */);
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
+
+ Fprovide (intern_c_string ("w32"), Qnil);
}
diff --git a/src/w32term.h b/src/w32term.h
index 5d756f435e4..35842e60c16 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -19,6 +19,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Added by Kevin Gallo */
#include "w32gui.h"
+#include "frame.h"
+#include "atimer.h"
#define BLACK_PIX_DEFAULT(f) PALETTERGB(0,0,0)
@@ -195,11 +197,45 @@ Lisp_Object display_x_get_resource (struct w32_display_info *,
Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
+extern void x_focus_on_frame (struct frame *f);
+
+/* also defined in xterm.h XXX: factor out to common header */
+
extern struct w32_display_info *w32_term_init (Lisp_Object,
char *, char *);
-
+extern void check_w32 (void);
+extern int w32_defined_color (FRAME_PTR f, const char *color,
+ XColor *color_def, int alloc);
+extern void x_set_window_size (struct frame *f, int change_grav,
+ int cols, int rows);
extern int x_display_pixel_height (struct w32_display_info *);
extern int x_display_pixel_width (struct w32_display_info *);
+extern void x_sync (struct frame *);
+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);
+extern int x_pixel_width (struct frame *f);
+extern int x_pixel_height (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 *f,
+ Lisp_Object value,
+ Lisp_Object oldval);
+extern void x_activate_menubar (struct frame *);
+extern int x_bitmap_icon (struct frame *, Lisp_Object);
+extern void initialize_frame_menubar (struct frame *);
+extern void x_free_frame_resources (struct frame *);
+extern void x_real_positions (struct frame *, int *, int *);
+
+/* w32inevt.c */
+extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId);
+extern int w32_kbd_mods_to_emacs (DWORD mods, WORD key);
+
+
+extern Lisp_Object x_get_focus_frame (struct frame *);
#define PIX_TYPE COLORREF
@@ -213,16 +249,10 @@ extern int x_display_pixel_width (struct w32_display_info *);
diffs between X and w32 code. */
struct x_output
{
-#if 0 /* These are also defined in struct frame. Use that instead. */
- PIX_TYPE background_pixel;
- PIX_TYPE foreground_pixel;
-#endif
-
/* Keep track of focus. May be EXPLICIT if we received a FocusIn for this
frame, or IMPLICIT if we received an EnterNotify.
FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
int focus_state;
-
};
enum
@@ -309,17 +339,13 @@ struct w32_output
/* Nonzero means our parent is another application's window
and was explicitly specified. */
- char explicit_parent;
+ unsigned explicit_parent : 1;
/* Nonzero means tried already to make this frame visible. */
- char asked_for_visible;
+ unsigned asked_for_visible : 1;
/* Nonzero means menubar is currently active. */
- char menubar_active;
-
- /* Nonzero means menubar is about to become active, but should be
- brought up to date first. */
- volatile char pending_menu_activation;
+ unsigned menubar_active : 1;
/* Relief GCs, colors etc. */
struct relief
@@ -377,9 +403,8 @@ extern struct w32_output w32term_display;
struct scroll_bar {
- /* These fields are shared by all vectors. */
- EMACS_INT size_from_Lisp_Vector_struct;
- struct Lisp_Vector *next_from_Lisp_Vector_struct;
+ /* This field is shared by all vectors. */
+ struct vectorlike_header header;
/* The window we're a scroll bar for. */
Lisp_Object window;
@@ -422,16 +447,18 @@ struct scroll_bar {
Lisp_Object fringe_extended_p;
};
-/* The number of elements a vector holding a struct scroll_bar needs. */
-#define SCROLL_BAR_VEC_SIZE \
- ((sizeof (struct scroll_bar) \
- - sizeof (EMACS_INT) - sizeof (struct Lisp_Vector *)) \
- / word_size)
-
/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
+#ifdef _WIN64
+/* Building a 64-bit C integer from two 32-bit lisp integers. */
+#define SCROLL_BAR_PACK(low, high) (XINT (high) << 32 | XINT (low))
+/* Setting two lisp integers to the low and high words of a 64-bit C int. */
+#define SCROLL_BAR_UNPACK(low, high, int64) \
+ (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))
@@ -439,7 +466,7 @@ struct scroll_bar {
#define SCROLL_BAR_UNPACK(low, high, int32) \
(XSETINT ((low), (int32) & 0xffff), \
XSETINT ((high), ((int32) >> 16) & 0xffff))
-
+#endif /* not _WIN64 */
/* Extract the window id of the scroll bar from a struct scroll_bar. */
#define SCROLL_BAR_W32_WINDOW(ptr) \
@@ -447,7 +474,7 @@ struct scroll_bar {
/* Store a window id in a struct scroll_bar. */
#define SET_SCROLL_BAR_W32_WINDOW(ptr, id) \
- (SCROLL_BAR_UNPACK ((ptr)->w32_window_low, (ptr)->w32_window_high, (int) id))
+ (SCROLL_BAR_UNPACK ((ptr)->w32_window_low, (ptr)->w32_window_high, (intptr_t) id))
/* Extract the X widget of the scroll bar from a struct scroll_bar. */
#define SCROLL_BAR_X_WIDGET(ptr) \
@@ -574,7 +601,9 @@ do { \
#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_END (WM_EMACS_START + 22)
+#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 WND_FONTWIDTH_INDEX (0)
#define WND_LINEHEIGHT_INDEX (4)
@@ -596,6 +625,8 @@ typedef struct W32Msg {
RECT rect;
} W32Msg;
+extern BOOL prepend_msg (W32Msg *lpmsg);
+
/* Structure for recording message when input thread must return a
result that depends on lisp thread to compute. Lisp thread can
complete deferred messages out of order. */
@@ -622,7 +653,7 @@ extern void deselect_palette (struct frame * f, HDC hdc);
extern HDC get_frame_dc (struct frame * f);
extern int release_frame_dc (struct frame * f, HDC hDC);
-extern void drain_message_queue (void);
+extern int drain_message_queue (void);
extern BOOL get_next_msg (W32Msg *, BOOL);
extern BOOL post_msg (W32Msg *);
@@ -633,6 +664,16 @@ extern BOOL parse_button (int, int, int *, int *);
extern void w32_sys_ring_bell (struct frame *f);
extern void x_delete_display (struct w32_display_info *dpyinfo);
+extern volatile int notification_buffer_in_use;
+extern BYTE file_notifications[16384];
+extern DWORD notifications_size;
+extern void *notifications_desc;
+extern Lisp_Object w32_get_watch_object (void *);
+extern Lisp_Object lispy_file_action (DWORD);
+
+extern void w32_initialize_display_info (Lisp_Object);
+extern void initialize_w32_display (struct terminal *);
+
/* Keypad command key support. W32 doesn't have virtual keys defined
for the function keys on the keypad (they are mapped to the standard
function keys), so we define our own. */
@@ -699,3 +740,35 @@ extern HWND w32_system_caret_hwnd;
extern int w32_system_caret_height;
extern int w32_system_caret_x;
extern int w32_system_caret_y;
+
+#ifdef _MSC_VER
+#ifndef EnumSystemLocales
+/* MSVC headers define these only for _WIN32_WINNT >= 0x0500. */
+typedef BOOL (CALLBACK *LOCALE_ENUMPROCA)(LPSTR);
+typedef BOOL (CALLBACK *LOCALE_ENUMPROCW)(LPWSTR);
+BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA,DWORD);
+BOOL WINAPI EnumSystemLocalesW(LOCALE_ENUMPROCW,DWORD);
+#ifdef UNICODE
+#define EnumSystemLocales EnumSystemLocalesW
+#else
+#define EnumSystemLocales EnumSystemLocalesA
+#endif
+#endif
+#endif
+
+#if EMACSDEBUG
+extern const char*
+w32_name_of_message (UINT msg);
+#endif /* EMACSDEBUG */
+
+extern void syms_of_w32term (void);
+extern void syms_of_w32menu (void);
+extern void syms_of_w32fns (void);
+
+extern void globals_of_w32menu (void);
+extern void globals_of_w32fns (void);
+extern void globals_of_w32notify (void);
+
+#ifdef CYGWIN
+extern int w32_message_fd;
+#endif /* CYGWIN */
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index bc45e2c648c..5d160b9d42f 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -27,7 +27,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define _WIN32_WINNT 0x500
#include <windows.h>
#include <usp10.h>
-#include <setjmp.h>
#include "lisp.h"
#include "w32term.h"
@@ -454,7 +453,11 @@ uniscribe_shape (Lisp_Object lgstring)
}
else
ASET (vec, 0, make_number (offsets[j].du + adj_offset));
- ASET (vec, 1, make_number (offsets[j].dv));
+ /* In the font definition coordinate system, the
+ Y coordinate points up, while in our screen
+ coordinates Y grows downwards. So we need to
+ reverse the sign of Y-OFFSET here. */
+ ASET (vec, 1, make_number (-offsets[j].dv));
/* Based on what ftfont.c does... */
ASET (vec, 2, make_number (advances[j]));
LGLYPH_SET_ADJUSTMENT (lglyph, vec);
diff --git a/src/w32xfns.c b/src/w32xfns.c
index 62e45dd987b..8820edda6c2 100644
--- a/src/w32xfns.c
+++ b/src/w32xfns.c
@@ -19,7 +19,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "keyboard.h"
#include "frame.h"
@@ -33,7 +33,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define myfree(lp) GlobalFreePtr (lp)
CRITICAL_SECTION critsect;
+
+#ifdef WINDOWSNT
extern HANDLE keyboard_handle;
+#endif /* WINDOWSNT */
+
HANDLE input_available = NULL;
HANDLE interrupt_handle = NULL;
@@ -44,7 +48,11 @@ init_crit (void)
/* For safety, input_available should only be reset by get_next_msg
when the input queue is empty, so make it a manual reset event. */
- keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
+ input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
+
+#ifdef WINDOWSNT
+ keyboard_handle = input_available;
+#endif /* WINDOWSNT */
/* interrupt_handle is signaled when quit (C-g) is detected, so that
blocking system calls can be interrupted. We make it a manual
@@ -122,7 +130,7 @@ get_frame_dc (FRAME_PTR f)
HDC hdc;
if (f->output_method != output_w32)
- abort ();
+ emacs_abort ();
enter_crit ();
@@ -241,6 +249,22 @@ get_next_msg (W32Msg * lpmsg, BOOL bWait)
return (bRet);
}
+extern char * w32_strerror (int error_no);
+
+/* Tell the main thread that we have input available; if the main
+ thread is blocked in select(), we wake it up here. */
+static void
+notify_msg_ready (void)
+{
+ SetEvent (input_available);
+
+#ifdef CYGWIN
+ /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
+ among other files. */
+ (void) PostThreadMessage (dwMainThreadId, WM_EMACS_INPUT_READY, 0, 0);
+#endif /* CYGWIN */
+}
+
BOOL
post_msg (W32Msg * lpmsg)
{
@@ -264,8 +288,7 @@ post_msg (W32Msg * lpmsg)
}
lpTail = lpNew;
- SetEvent (input_available);
-
+ notify_msg_ready ();
leave_crit ();
return (TRUE);
@@ -286,154 +309,28 @@ prepend_msg (W32Msg *lpmsg)
nQueue++;
lpNew->lpNext = lpHead;
lpHead = lpNew;
-
+ notify_msg_ready ();
leave_crit ();
return (TRUE);
}
-/* Process all messages in the current thread's queue. */
-void
+/* Process all messages in the current thread's queue. Value is 1 if
+ one of these messages was WM_EMACS_FILENOTIFY, zero otherwise. */
+int
drain_message_queue (void)
{
MSG msg;
+ int retval = 0;
+
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
+ if (msg.message == WM_EMACS_FILENOTIFY)
+ retval = 1;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
-}
-
-
-/*
- * XParseGeometry parses strings of the form
- * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
- * width, height, xoffset, and yoffset are unsigned integers.
- * Example: "=80x24+300-49"
- * The equal sign is optional.
- * It returns a bitmask that indicates which of the four values
- * were actually found in the string. For each value found,
- * the corresponding argument is updated; for each value
- * not found, the corresponding argument is left unchanged.
- */
-
-static int
-read_integer (register char *string, char **NextString)
-{
- register int Result = 0;
- int Sign = 1;
-
- if (*string == '+')
- string++;
- else if (*string == '-')
- {
- string++;
- Sign = -1;
- }
- for (; (*string >= '0') && (*string <= '9'); string++)
- {
- Result = (Result * 10) + (*string - '0');
- }
- *NextString = string;
- if (Sign >= 0)
- return (Result);
- else
- return (-Result);
-}
-
-int
-XParseGeometry (char *string,
- int *x, int *y,
- unsigned int *width, unsigned int *height)
-{
- int mask = NoValue;
- register char *strind;
- unsigned int tempWidth, tempHeight;
- int tempX, tempY;
- char *nextCharacter;
-
- if ((string == NULL) || (*string == '\0')) return (mask);
- if (*string == '=')
- string++; /* ignore possible '=' at beg of geometry spec */
-
- strind = (char *)string;
- if (*strind != '+' && *strind != '-' && *strind != 'x')
- {
- tempWidth = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= WidthValue;
- }
-
- if (*strind == 'x' || *strind == 'X')
- {
- strind++;
- tempHeight = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= HeightValue;
- }
-
- if ((*strind == '+') || (*strind == '-'))
- {
- if (*strind == '-')
- {
- strind++;
- tempX = -read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= XNegative;
-
- }
- else
- {
- strind++;
- tempX = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- }
- mask |= XValue;
- if ((*strind == '+') || (*strind == '-'))
- {
- if (*strind == '-')
- {
- strind++;
- tempY = -read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- mask |= YNegative;
- }
- else
- {
- strind++;
- tempY = read_integer (strind, &nextCharacter);
- if (strind == nextCharacter)
- return (0);
- strind = nextCharacter;
- }
- mask |= YValue;
- }
- }
-
- /* If strind isn't at the end of the string then it's an invalid
- geometry specification. */
-
- if (*strind != '\0') return (0);
-
- if (mask & XValue)
- *x = tempX;
- if (mask & YValue)
- *y = tempY;
- if (mask & WidthValue)
- *width = tempWidth;
- if (mask & HeightValue)
- *height = tempHeight;
- return (mask);
+ return retval;
}
/* x_sync is a no-op on W32. */
diff --git a/src/widget.c b/src/widget.c
index ea9bdb61b13..b4f7335c652 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -30,7 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
+
#include "lisp.h"
#include "xterm.h"
@@ -50,9 +50,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <X11/ShellP.h>
#include "../lwlib/lwlib.h"
-#include <signal.h>
-#include "syssignal.h"
-
#include "character.h"
#include "font.h"
@@ -226,7 +223,7 @@ get_wm_shell (Widget w)
static void
mark_shell_size_user_specified (Widget wmshell)
{
- if (! XtIsWMShell (wmshell)) abort ();
+ if (! XtIsWMShell (wmshell)) emacs_abort ();
/* This is kind of sleazy, but I can't see how else to tell it to make it
mark the WM_SIZE_HINTS size as user specified when appropriate. */
((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
@@ -290,7 +287,7 @@ set_frame_size (EmacsFrame ew)
Widget wmshell = get_wm_shell ((Widget) ew);
/* Each Emacs shell is now independent and top-level. */
- if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
+ if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort ();
/* We don't need this for the moment. The geometry is computed in
xfns.c. */
@@ -653,6 +650,16 @@ EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
set_frame_size (ew);
}
+static void
+resize_cb (Widget widget,
+ XtPointer closure,
+ XEvent* event,
+ Boolean* continue_to_dispatch)
+{
+ EmacsFrame ew = (EmacsFrame) widget;
+ EmacsFrameResize (widget);
+}
+
static void
EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
@@ -668,6 +675,9 @@ EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs
*mask |= CWEventMask;
XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
attrs);
+ /* Some ConfigureNotify events does not end up in EmacsFrameResize so
+ make sure we get them all. Seen with xfcwm4 for example. */
+ XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL);
update_wm_hints (ew);
}
@@ -677,16 +687,16 @@ EmacsFrameDestroy (Widget widget)
EmacsFrame ew = (EmacsFrame) widget;
struct frame* s = ew->emacs_frame.frame;
- if (! s) abort ();
- if (! s->output_data.x) abort ();
+ if (! s) emacs_abort ();
+ if (! s->output_data.x) emacs_abort ();
- BLOCK_INPUT;
+ block_input ();
x_free_gcs (s);
if (s->output_data.x->white_relief.gc)
XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
if (s->output_data.x->black_relief.gc)
XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
- UNBLOCK_INPUT;
+ unblock_input ();
}
static void
@@ -694,15 +704,22 @@ EmacsFrameResize (Widget widget)
{
EmacsFrame ew = (EmacsFrame)widget;
struct frame *f = ew->emacs_frame.frame;
+ struct x_output *x = f->output_data.x;
int columns;
int rows;
pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
- change_frame_size (f, rows, columns, 0, 1, 0);
- update_wm_hints (ew);
- update_various_frame_slots (ew);
+ if (columns != FRAME_COLS (f)
+ || rows != FRAME_LINES (f)
+ || ew->core.width != FRAME_PIXEL_WIDTH (f)
+ || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
+ {
+ change_frame_size (f, rows, columns, 0, 1, 0);
+ update_wm_hints (ew);
+ update_various_frame_slots (ew);
- cancel_mouse_face (f);
+ cancel_mouse_face (f);
+ }
}
static Boolean
diff --git a/src/window.c b/src/window.c
index 732d5060d29..7fa55df3c5e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -23,7 +23,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define WINDOW_INLINE EXTERN_INLINE
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -44,7 +43,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif /* HAVE_X_WINDOWS */
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
#include "w32term.h"
#endif
#ifdef MSDOS
@@ -61,8 +60,7 @@ 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 Qscroll_up, Qscroll_down, Qscroll_command;
-static Lisp_Object Qsafe, Qabove, Qbelow;
-static Lisp_Object Qclone_of;
+static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
static int displayed_window_lines (struct window *);
static int count_windows (struct window *);
@@ -135,112 +133,102 @@ static EMACS_INT window_scroll_preserve_hpos;
static EMACS_INT window_scroll_preserve_vpos;
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
wset_combination_limit (struct window *w, Lisp_Object val)
{
w->combination_limit = val;
}
-static inline void
+static void
wset_dedicated (struct window *w, Lisp_Object val)
{
w->dedicated = val;
}
-static inline void
+static void
wset_display_table (struct window *w, Lisp_Object val)
{
w->display_table = val;
}
-static inline void
+static void
wset_hchild (struct window *w, Lisp_Object val)
{
w->hchild = val;
}
-static inline void
+static void
wset_left_fringe_width (struct window *w, Lisp_Object val)
{
w->left_fringe_width = val;
}
-static inline void
+static void
wset_left_margin_cols (struct window *w, Lisp_Object val)
{
w->left_margin_cols = val;
}
-static inline void
+static void
wset_new_normal (struct window *w, Lisp_Object val)
{
w->new_normal = val;
}
-static inline void
+static void
wset_new_total (struct window *w, Lisp_Object val)
{
w->new_total = val;
}
-static inline void
-wset_next_buffers (struct window *w, Lisp_Object val)
-{
- w->next_buffers = val;
-}
-static inline void
+static void
wset_normal_cols (struct window *w, Lisp_Object val)
{
w->normal_cols = val;
}
-static inline void
+static void
wset_normal_lines (struct window *w, Lisp_Object val)
{
w->normal_lines = val;
}
-static inline void
+static void
wset_parent (struct window *w, Lisp_Object val)
{
w->parent = val;
}
-static inline void
+static void
wset_pointm (struct window *w, Lisp_Object val)
{
w->pointm = val;
}
-static inline void
-wset_prev_buffers (struct window *w, Lisp_Object val)
-{
- w->prev_buffers = val;
-}
-static inline void
+static void
wset_right_fringe_width (struct window *w, Lisp_Object val)
{
w->right_fringe_width = val;
}
-static inline void
+static void
wset_right_margin_cols (struct window *w, Lisp_Object val)
{
w->right_margin_cols = val;
}
-static inline void
+static void
wset_scroll_bar_width (struct window *w, Lisp_Object val)
{
w->scroll_bar_width = val;
}
-static inline void
+static void
wset_start (struct window *w, Lisp_Object val)
{
w->start = val;
}
-static inline void
+static void
wset_temslot (struct window *w, Lisp_Object val)
{
w->temslot = val;
}
-static inline void
+static void
wset_vchild (struct window *w, Lisp_Object val)
{
w->vchild = val;
}
-static inline void
+static void
wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
{
w->vertical_scroll_bar_type = val;
}
-static inline void
+static void
wset_window_parameters (struct window *w, Lisp_Object val)
{
w->window_parameters = val;
@@ -256,7 +244,7 @@ decode_live_window (register Lisp_Object window)
return XWINDOW (window);
}
-static struct window *
+struct window *
decode_any_window (register Lisp_Object window)
{
struct window *w;
@@ -282,6 +270,44 @@ decode_valid_window (register Lisp_Object window)
return w;
}
+/* Called when W's buffer slot is changed. ARG -1 means that W is about to
+ cease its buffer, and 1 means that W is about to set up the new one. */
+
+static void
+adjust_window_count (struct window *w, int arg)
+{
+ eassert (eabs (arg) == 1);
+ if (BUFFERP (w->buffer))
+ {
+ struct buffer *b = XBUFFER (w->buffer);
+
+ if (b->base_buffer)
+ b = b->base_buffer;
+ b->window_count += arg;
+ eassert (b->window_count >= 0);
+ }
+}
+
+/* Set W's buffer slot to VAL and recompute number
+ of windows showing VAL if it is a buffer. */
+
+void
+wset_buffer (struct window *w, Lisp_Object val)
+{
+ adjust_window_count (w, -1);
+ w->buffer = val;
+ adjust_window_count (w, 1);
+}
+
+/* Build a frequently used 4-integer (X Y W H) list. */
+
+static Lisp_Object
+list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h)
+{
+ return list4 (make_number (x), make_number (y),
+ make_number (w), make_number (h));
+}
+
DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
doc: /* Return t if OBJECT is a window and nil otherwise. */)
(Lisp_Object object)
@@ -308,7 +334,7 @@ Internal windows and deleted windows are not live. */)
}
/* Frames and windows. */
-DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
+DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
doc: /* Return the frame that window WINDOW is on.
WINDOW must be a valid window and defaults to the selected one. */)
(Lisp_Object window)
@@ -343,10 +369,7 @@ DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
If FRAME is omitted or nil, it defaults to the selected frame. */)
(Lisp_Object frame)
{
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- return FRAME_MINIBUF_WINDOW (XFRAME (frame));
+ return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
}
DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
@@ -386,7 +409,7 @@ the first window of that frame. */)
else if (! NILP (XWINDOW (window)->vchild))
window = XWINDOW (window)->vchild;
else
- abort ();
+ emacs_abort ();
}
return window;
@@ -568,7 +591,7 @@ Return nil for a window with no parent (e.g. a root window). */)
return decode_valid_window (window)->parent;
}
-DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 1, 1, 0,
+DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
doc: /* Return the topmost child window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil if WINDOW is a live window (live windows have no children).
@@ -576,11 +599,10 @@ Return nil if WINDOW is an internal window whose children form a
horizontal combination. */)
(Lisp_Object window)
{
- CHECK_WINDOW (window);
return decode_valid_window (window)->vchild;
}
-DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 1, 1, 0,
+DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
doc: /* Return the leftmost child window of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
Return nil if WINDOW is a live window (live windows have no children).
@@ -588,7 +610,6 @@ Return nil if WINDOW is an internal window whose children form a
vertical combination. */)
(Lisp_Object window)
{
- CHECK_WINDOW (window);
return decode_valid_window (window)->hchild;
}
@@ -612,22 +633,27 @@ Return nil if WINDOW has no previous sibling. */)
DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
doc: /* Return combination limit of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.
If the return value is nil, child windows of WINDOW can be recombined with
WINDOW's siblings. A return value of t means that child windows of
-WINDOW are never \(re-)combined with WINDOW's siblings. */)
+WINDOW are never \(re-)combined with WINDOW's siblings.
+
+WINDOW must be a valid window. The return value is meaningful for
+internal windows only. */)
(Lisp_Object window)
{
- return decode_valid_window (window)->combination_limit;
+ CHECK_VALID_WINDOW (window);
+ return XWINDOW (window)->combination_limit;
}
DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
-WINDOW must be a valid window and defaults to the selected one.
-If LIMIT is nil, child windows of WINDOW can be recombined with
-WINDOW's siblings. LIMIT t means that child windows of WINDOW are
-never \(re-)combined with WINDOW's siblings. Other values are reserved
-for future use. */)
+If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
+siblings. LIMIT t means that child windows of WINDOW are never
+\(re-)combined with WINDOW's siblings. Other values are reserved for
+future use.
+
+WINDOW must be a valid window. Setting the combination limit is
+meaningful for internal windows only. */)
(Lisp_Object window, Lisp_Object limit)
{
wset_combination_limit (decode_valid_window (window), limit);
@@ -786,8 +812,7 @@ area is only partially visible, that counts as a whole line; to
exclude partially-visible lines, use `window-text-height'. */)
(Lisp_Object window)
{
- struct window *w = decode_live_window (window);
- return make_number (window_body_lines (w));
+ return make_number (window_body_lines (decode_live_window (window)));
}
DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
@@ -799,8 +824,7 @@ marginal areas, or scroll bars. On a graphical display, the width is
expressed as an integer multiple of the default character width. */)
(Lisp_Object window)
{
- struct window *w = decode_live_window (window);
- return make_number (window_body_cols (w));
+ return make_number (window_body_cols (decode_live_window (window)));
}
DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
@@ -843,10 +867,8 @@ Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
window so that the location of point moves off-window. */)
(Lisp_Object window, Lisp_Object ncol)
{
- struct window *w = decode_live_window (window);
-
CHECK_NUMBER (ncol);
- return set_window_hscroll (w, XINT (ncol));
+ return set_window_hscroll (decode_live_window (window), XINT (ncol));
}
DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
@@ -891,11 +913,8 @@ header line, and/or mode line. For the edges of just the text area, use
{
register struct window *w = decode_valid_window (window);
- return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
- Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
- Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
- Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
- Qnil))));
+ return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
+ WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
}
DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
@@ -914,11 +933,8 @@ of just the text area, use `window-inside-pixel-edges'. */)
{
register struct window *w = decode_valid_window (window);
- return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
- Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
- Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
- Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
- Qnil))));
+ return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
+ WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
}
static void
@@ -960,13 +976,13 @@ of just the text area, use `window-inside-absolute-pixel-edges'. */)
{
register struct window *w = decode_valid_window (window);
int add_x, add_y;
+
calc_absolute_offset (w, &add_x, &add_y);
- return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
- Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
- Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
- Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
- Qnil))));
+ return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
+ WINDOW_TOP_EDGE_Y (w) + add_y,
+ WINDOW_RIGHT_EDGE_X (w) + add_x,
+ WINDOW_BOTTOM_EDGE_Y (w) + add_y);
}
DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
@@ -985,16 +1001,16 @@ display margins, fringes, header line, and/or mode line. */)
{
register struct window *w = decode_live_window (window);
- return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
- + WINDOW_LEFT_MARGIN_COLS (w)
- + WINDOW_LEFT_FRINGE_COLS (w)),
- make_number (WINDOW_TOP_EDGE_LINE (w)
- + WINDOW_HEADER_LINE_LINES (w)),
- make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
- - WINDOW_RIGHT_MARGIN_COLS (w)
- - WINDOW_RIGHT_FRINGE_COLS (w)),
- make_number (WINDOW_BOTTOM_EDGE_LINE (w)
- - WINDOW_MODE_LINE_LINES (w)));
+ return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
+ + WINDOW_LEFT_MARGIN_COLS (w)
+ + WINDOW_LEFT_FRINGE_COLS (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_BOTTOM_EDGE_LINE (w)
+ - WINDOW_MODE_LINE_LINES (w)));
}
DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
@@ -1012,16 +1028,16 @@ display margins, fringes, header line, and/or mode line. */)
{
register struct window *w = decode_live_window (window);
- return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
- + WINDOW_LEFT_MARGIN_WIDTH (w)
- + WINDOW_LEFT_FRINGE_WIDTH (w)),
- make_number (WINDOW_TOP_EDGE_Y (w)
- + WINDOW_HEADER_LINE_HEIGHT (w)),
- make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
- - WINDOW_RIGHT_MARGIN_WIDTH (w)
- - WINDOW_RIGHT_FRINGE_WIDTH (w)),
- make_number (WINDOW_BOTTOM_EDGE_Y (w)
- - WINDOW_MODE_LINE_HEIGHT (w)));
+ return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w)
+ + WINDOW_LEFT_FRINGE_WIDTH (w)),
+ (WINDOW_TOP_EDGE_Y (w)
+ + WINDOW_HEADER_LINE_HEIGHT (w)),
+ (WINDOW_BOX_RIGHT_EDGE_X (w)
+ - WINDOW_RIGHT_MARGIN_WIDTH (w)
+ - WINDOW_RIGHT_FRINGE_WIDTH (w)),
+ (WINDOW_BOTTOM_EDGE_Y (w)
+ - WINDOW_MODE_LINE_HEIGHT (w)));
}
DEFUN ("window-inside-absolute-pixel-edges",
@@ -1041,18 +1057,19 @@ display margins, fringes, header line, and/or mode line. */)
{
register struct window *w = decode_live_window (window);
int add_x, add_y;
+
calc_absolute_offset (w, &add_x, &add_y);
- return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
- + WINDOW_LEFT_MARGIN_WIDTH (w)
- + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
- make_number (WINDOW_TOP_EDGE_Y (w)
- + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
- make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
- - WINDOW_RIGHT_MARGIN_WIDTH (w)
- - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
- make_number (WINDOW_BOTTOM_EDGE_Y (w)
- - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
+ return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w)
+ + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
+ (WINDOW_TOP_EDGE_Y (w)
+ + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
+ (WINDOW_BOX_RIGHT_EDGE_X (w)
+ - WINDOW_RIGHT_MARGIN_WIDTH (w)
+ - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
+ (WINDOW_BOTTOM_EDGE_Y (w)
+ - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
}
/* Test if the character at column X, row Y is within window W.
@@ -1289,7 +1306,7 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
return Qnil;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -1385,12 +1402,7 @@ The top left corner of the frame is considered to be row 0,
column 0. */)
(Lisp_Object x, Lisp_Object y, Lisp_Object frame)
{
- struct frame *f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
+ struct frame *f = decode_live_frame (frame);
/* Check that arguments are integers or floats. */
CHECK_NUMBER_OR_FLOAT (x);
@@ -1476,12 +1488,11 @@ if it isn't already recorded. */)
#endif
if (! NILP (update)
- && ! (! NILP (w->window_end_valid)
- && w->last_modified >= BUF_MODIFF (b)
- && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
+ && (windows_or_buffers_changed || NILP (w->window_end_valid))
&& !noninteractive)
{
struct text_pos startp;
+ ptrdiff_t charpos = marker_position (w->start);
struct it it;
struct buffer *old_buffer = NULL;
void *itdata = NULL;
@@ -1499,9 +1510,9 @@ if it isn't already recorded. */)
`-l' containing a call to `rmail' with subsequent other
commands. At the end, W->start happened to be BEG, while
rmail had already narrowed the buffer. */
- if (XMARKER (w->start)->charpos < BEGV)
+ if (charpos < BEGV)
SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
- else if (XMARKER (w->start)->charpos > ZV)
+ else if (charpos > ZV)
SET_TEXT_POS (startp, ZV, ZV_BYTE);
else
SET_TEXT_POS_FROM_MARKER (startp, w->start);
@@ -1624,7 +1635,7 @@ display row, and VPOS is the row number (0-based) containing POS. */)
else if (w == XWINDOW (selected_window))
posint = PT;
else
- posint = XMARKER (w->pointm)->charpos;
+ posint = marker_position (w->pointm);
/* If position is above window start or outside buffer boundaries,
or if window start is out of range, position is not visible. */
@@ -1640,8 +1651,7 @@ display row, and VPOS is the row number (0-based) containing POS. */)
{
Lisp_Object part = Qnil;
if (!fully_p)
- part = list4 (make_number (rtop), make_number (rbot),
- make_number (rowh), make_number (vpos));
+ part = list4i (rtop, rbot, rowh, vpos);
in_window = Fcons (make_number (x),
Fcons (make_number (y), part));
}
@@ -1707,23 +1717,19 @@ Return nil if window display is not up-to-date. In that case, use
if (!WINDOW_WANTS_HEADER_LINE_P (w))
return Qnil;
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
- if (!row->enabled_p)
- return Qnil;
- return list4 (make_number (row->height),
- make_number (0), make_number (0),
- make_number (0));
+ return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
}
if (EQ (line, Qmode_line))
{
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
- if (!row->enabled_p)
- return Qnil;
- return list4 (make_number (row->height),
- make_number (0), /* not accurate */
- make_number (WINDOW_HEADER_LINE_HEIGHT (w)
- + window_text_bottom_y (w)),
- make_number (0));
+ return (row->enabled_p ?
+ list4i (row->height,
+ 0, /* not accurate */
+ (WINDOW_HEADER_LINE_HEIGHT (w)
+ + window_text_bottom_y (w)),
+ 0)
+ : Qnil);
}
CHECK_NUMBER (line);
@@ -1752,10 +1758,7 @@ Return nil if window display is not up-to-date. In that case, use
found_row:
crop = max (0, (row->y + row->height) - max_y);
- return list4 (make_number (row->height + min (0, row->y) - crop),
- make_number (i),
- make_number (row->y),
- make_number (crop));
+ return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
}
DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
@@ -1866,23 +1869,23 @@ return value is a list of elements of the form (PARAMETER . VALUE). */)
DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
2, 2, 0,
doc: /* Return WINDOW's value for PARAMETER.
-WINDOW must be a valid window and defaults to the selected one. */)
+WINDOW can be any window and defaults to the selected one. */)
(Lisp_Object window, Lisp_Object parameter)
{
Lisp_Object result;
- result = Fassq (parameter, decode_valid_window (window)->window_parameters);
+ result = Fassq (parameter, decode_any_window (window)->window_parameters);
return CDR_SAFE (result);
}
DEFUN ("set-window-parameter", Fset_window_parameter,
Sset_window_parameter, 3, 3, 0,
doc: /* Set WINDOW's value of PARAMETER to VALUE.
-WINDOW must be a valid window and defaults to the selected one.
+WINDOW can be any window and defaults to the selected one.
Return VALUE. */)
(Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
{
- register struct window *w = decode_valid_window (window);
+ register struct window *w = decode_any_window (window);
Lisp_Object old_alist_elt;
old_alist_elt = Fassq (parameter, w->window_parameters);
@@ -1948,7 +1951,7 @@ unshow_buffer (register struct window *w)
buf = w->buffer;
b = XBUFFER (buf);
if (b != XMARKER (w->pointm)->buffer)
- abort ();
+ emacs_abort ();
#if 0
if (w == XWINDOW (selected_window)
@@ -1978,7 +1981,7 @@ unshow_buffer (register struct window *w)
&& EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
temp_set_point_both (b,
clip_to_bounds (BUF_BEGV (b),
- XMARKER (w->pointm)->charpos,
+ marker_position (w->pointm),
BUF_ZV (b)),
clip_to_bounds (BUF_BEGV_BYTE (b),
marker_byte_position (w->pointm),
@@ -2160,10 +2163,10 @@ window_list (void)
{
if (!CONSP (Vwindow_list))
{
- Lisp_Object tail;
+ Lisp_Object tail, frame;
Vwindow_list = Qnil;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
Lisp_Object args[2];
@@ -2171,7 +2174,7 @@ window_list (void)
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 (XCAR (tail)), add_window_to_list, &args[1]);
+ foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
args[0] = Vwindow_list;
args[1] = Fnreverse (args[1]);
Vwindow_list = Fnconc (2, args);
@@ -2266,11 +2269,9 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf
static void
decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
{
- if (NILP (*window))
- *window = selected_window;
- else
- CHECK_LIVE_WINDOW (*window);
+ struct window *w = decode_live_window (*window);
+ XSETWINDOW (*window, w);
/* MINIBUF nil may or may not include minibuffers. Decide if it
does. */
if (NILP (*minibuf))
@@ -2286,7 +2287,7 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
if (NILP (*all_frames))
*all_frames
= (!EQ (*minibuf, Qlambda)
- ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
+ ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
: Qnil);
else if (EQ (*all_frames, Qvisible))
;
@@ -2668,8 +2669,8 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
/* Check for a window that has a killed buffer. */
case CHECK_ALL_WINDOWS:
if (! NILP (w->buffer)
- && NILP (BVAR (XBUFFER (w->buffer), name)))
- abort ();
+ && !BUFFER_LIVE_P (XBUFFER (w->buffer)))
+ emacs_abort ();
break;
case WINDOW_LOOP_UNUSED:
@@ -2831,7 +2832,7 @@ window-start value is reasonable when this function is called. */)
}
}
- BLOCK_INPUT;
+ block_input ();
if (!FRAME_INITIAL_P (f))
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
@@ -2973,7 +2974,7 @@ window-start value is reasonable when this function is called. */)
}
adjust_glyphs (f);
- UNBLOCK_INPUT;
+ unblock_input ();
run_window_configuration_change_hook (f);
@@ -2987,22 +2988,24 @@ replace_buffer_in_windows (Lisp_Object buffer)
call1 (Qreplace_buffer_in_windows, buffer);
}
-
-/* Safely replace BUFFER with some other buffer in all windows of all
- frames, even those on other keyboards. */
+/* If BUFFER is shown in a window, safely replace it with some other
+ buffer in all windows of all frames, even those on other keyboards. */
void
replace_buffer_in_windows_safely (Lisp_Object buffer)
{
- Lisp_Object tail, frame;
+ if (buffer_window_count (XBUFFER (buffer)))
+ {
+ Lisp_Object tail, frame;
- /* A single call to window_loop won't do the job because it only
- considers frames on the current keyboard. So loop manually over
- frames, and handle each one. */
- FOR_EACH_FRAME (tail, frame)
- window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
+ /* A single call to window_loop won't do the job because it only
+ considers frames on the current keyboard. So loop manually over
+ frames, and handle each one. */
+ FOR_EACH_FRAME (tail, frame)
+ window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
+ }
}
-
+
/* If *ROWS or *COLS are too small a size for FRAME, set them to the
minimum allowable size. */
@@ -3136,12 +3139,12 @@ run_window_configuration_change_hook (struct frame *f)
}
DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
- Srun_window_configuration_change_hook, 1, 1, 0,
- doc: /* Run `window-configuration-change-hook' for FRAME. */)
+ Srun_window_configuration_change_hook, 0, 1, 0,
+ doc: /* Run `window-configuration-change-hook' for FRAME.
+If FRAME is omitted or nil, it defaults to the selected frame. */)
(Lisp_Object frame)
{
- CHECK_LIVE_FRAME (frame);
- run_window_configuration_change_hook (XFRAME (frame));
+ run_window_configuration_change_hook (decode_live_frame (frame));
return Qnil;
}
@@ -3273,14 +3276,13 @@ This function runs `window-scroll-functions' before running
XSETWINDOW (window, w);
buffer = Fget_buffer (buffer_or_name);
CHECK_BUFFER (buffer);
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
error ("Attempt to display deleted buffer");
tem = w->buffer;
if (NILP (tem))
error ("Window is deleted");
- else if (!EQ (tem, Qt))
- /* w->buffer is t when the window is first being set up. */
+ else
{
if (!EQ (tem, buffer))
{
@@ -3338,11 +3340,11 @@ displaying that buffer. */)
if (STRINGP (object))
object = Fget_buffer (object);
- if (BUFFERP (object) && !NILP (BVAR (XBUFFER (object), name)))
+ if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
+ && buffer_window_count (XBUFFER (object)))
{
- /* Walk all windows looking for buffer, and force update
- of each of those windows. */
-
+ /* If buffer is live and shown in at least one window, find
+ all windows showing this buffer and force update of them. */
object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
return NILP (object) ? Qnil : Qt;
}
@@ -3353,7 +3355,7 @@ displaying that buffer. */)
return Qnil;
}
-
+/* Obsolete since 24.3. */
void
temp_output_buffer_show (register Lisp_Object buf)
{
@@ -3406,16 +3408,6 @@ temp_output_buffer_show (register Lisp_Object buf)
}
}
}
-
-DEFUN ("internal-temp-output-buffer-show",
- Ftemp_output_buffer_show, Stemp_output_buffer_show,
- 1, 1, 0,
- doc: /* Internal function for `with-output-to-temp-buffer'. */)
- (Lisp_Object buf)
-{
- temp_output_buffer_show (buf);
- return Qnil;
-}
/* Make new window, have it replace WINDOW in window-tree, and make
WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
@@ -3431,6 +3423,8 @@ make_parent_window (Lisp_Object window, int horflag)
memcpy ((char *) p + sizeof (struct vectorlike_header),
(char *) o + sizeof (struct vectorlike_header),
word_size * VECSIZE (struct window));
+ /* P's buffer slot may change from nil to a buffer. */
+ adjust_window_count (p, 1);
XSETWINDOW (parent, p);
p->sequence_number = ++sequence_number;
@@ -3473,6 +3467,10 @@ make_window (void)
wset_vertical_scroll_bar_type (w, Qt);
wset_window_end_pos (w, make_number (0));
wset_window_end_vpos (w, make_number (0));
+ /* These Lisp fields are marked specially so they're not set to nil by
+ allocate_window. */
+ wset_prev_buffers (w, Qnil);
+ wset_next_buffers (w, Qnil);
/* Initialize non-Lisp data. Note that allocate_window zeroes out all
non-Lisp data, so do it only for slots which should not be zero. */
@@ -3674,10 +3672,12 @@ window_resize_apply (struct window *w, int horflag)
}
-DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 1, 2, 0,
+DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
doc: /* Apply requested size values for window-tree of FRAME.
-Optional argument HORIZONTAL omitted or nil means apply requested height
-values. HORIZONTAL non-nil means apply requested width values.
+If FRAME is omitted or nil, it defaults to the selected frame.
+
+Optional argument HORIZONTAL omitted or nil means apply requested
+height values. HORIZONTAL non-nil means apply requested width values.
This function checks whether the requested values sum up to a valid
window layout, recursively assigns the new sizes of all child windows
@@ -3688,30 +3688,23 @@ Note: This function does not check any of `window-fixed-size-p',
be applied on the Elisp level. */)
(Lisp_Object frame, Lisp_Object horizontal)
{
- struct frame *f;
- struct window *r;
+ struct frame *f = decode_live_frame (frame);
+ struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
int horflag = !NILP (horizontal);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
-
- f = XFRAME (frame);
- r = XWINDOW (FRAME_ROOT_WINDOW (f));
-
if (!window_resize_check (r, horflag)
|| ! EQ (r->new_total,
(horflag ? r->total_cols : r->total_lines)))
return Qnil;
- BLOCK_INPUT;
+ block_input ();
window_resize_apply (r, horflag);
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
adjust_glyphs (f);
- UNBLOCK_INPUT;
+ unblock_input ();
run_window_configuration_change_hook (f);
@@ -3803,6 +3796,8 @@ resize_frame_windows (struct frame *f, int size, int horflag)
(m, make_number (XINT (r->top_line) + XINT (r->total_lines)));
}
}
+
+ windows_or_buffers_changed++;
}
@@ -3855,7 +3850,7 @@ set correctly. See the code of `split-window' for how this is done. */)
We do that if either `window-combination-limit' is t, or OLD has no
parent, or OLD is ortho-combined. */
combination_limit =
- !NILP (Vwindow_combination_limit)
+ EQ (Vwindow_combination_limit, Qt)
|| NILP (o->parent)
|| NILP (horflag
? (XWINDOW (o->parent)->hchild)
@@ -3910,9 +3905,10 @@ set correctly. See the code of `split-window' for how this is done. */)
make_parent_window (old, horflag);
p = XWINDOW (o->parent);
- /* Store value of `window-combination-limit' in new parent's
- combination_limit slot. */
- wset_combination_limit (p, Vwindow_combination_limit);
+ if (EQ (Vwindow_combination_limit, Qt))
+ /* Store t in the new parent's combination_limit slot to avoid
+ that its children get merged into another window. */
+ wset_combination_limit (p, Qt);
/* These get applied below. */
wset_new_total (p, horflag ? o->total_cols : o->total_lines);
wset_new_normal (p, new_normal);
@@ -3951,7 +3947,6 @@ set correctly. See the code of `split-window' for how this is done. */)
wset_next (o, new);
}
- wset_buffer (n, Qt);
wset_window_end_valid (n, Qnil);
memset (&n->last_cursor, 0, sizeof n->last_cursor);
@@ -3981,13 +3976,13 @@ set correctly. See the code of `split-window' for how this is done. */)
wset_new_total (n, total_size);
wset_new_normal (n, normal_size);
- BLOCK_INPUT;
+ block_input ();
window_resize_apply (p, horflag);
adjust_glyphs (f);
/* Set buffer of NEW to buffer of reference window. Don't run
any hooks. */
set_window_buffer (new, r->buffer, 0, 1);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Maybe we should run the scroll functions in Elisp (which already
runs the configuration change hook). */
@@ -4068,7 +4063,7 @@ Signal an error when WINDOW is the only window on its frame. */)
{
/* Block input. */
- BLOCK_INPUT;
+ block_input ();
window_resize_apply (p, horflag);
/* If this window is referred to by the dpyinfo's mouse
@@ -4140,7 +4135,7 @@ Signal an error when WINDOW is the only window on its frame. */)
else
fset_selected_window (f, new_selected_window);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Now look whether `get-mru-window' gets us something. */
mru_window = call1 (Qget_mru_window, frame);
@@ -4155,7 +4150,7 @@ Signal an error when WINDOW is the only window on its frame. */)
fset_selected_window (f, new_selected_window);
}
else
- UNBLOCK_INPUT;
+ unblock_input ();
/* Must be run by the caller:
run_window_configuration_change_hook (f); */
@@ -4205,7 +4200,7 @@ grow_mini_window (struct window *w, int delta)
root, make_number (- delta));
if (INTEGERP (value) && window_resize_check (r, 0))
{
- BLOCK_INPUT;
+ block_input ();
window_resize_apply (r, 0);
/* Grow the mini-window. */
@@ -4216,8 +4211,9 @@ grow_mini_window (struct window *w, int delta)
w->last_modified = 0;
w->last_overlay_modified = 0;
+ windows_or_buffers_changed++;
adjust_glyphs (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -4242,7 +4238,7 @@ shrink_mini_window (struct window *w)
root, make_number (size - 1));
if (INTEGERP (value) && window_resize_check (r, 0))
{
- BLOCK_INPUT;
+ block_input ();
window_resize_apply (r, 0);
/* Shrink the mini-window. */
@@ -4253,8 +4249,9 @@ shrink_mini_window (struct window *w)
w->last_modified = 0;
w->last_overlay_modified = 0;
+ windows_or_buffers_changed++;
adjust_glyphs (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* If the above failed for whatever strange reason we must make a
one window frame here. The same routine will be needed when
@@ -4286,7 +4283,7 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
&& XINT (w->new_total) > 0
&& height == XINT (r->new_total) + XINT (w->new_total))
{
- BLOCK_INPUT;
+ block_input ();
window_resize_apply (r, 0);
wset_total_lines (w, w->new_total);
@@ -4296,7 +4293,7 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
adjust_glyphs (f);
- UNBLOCK_INPUT;
+ unblock_input ();
run_window_configuration_change_hook (f);
return Qt;
@@ -4622,7 +4619,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
/* Set the window start, and set up the window for redisplay. */
set_marker_restricted (w->start, make_number (pos),
w->buffer);
- bytepos = XMARKER (w->start)->bytepos;
+ bytepos = marker_byte_position (w->start);
w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
w->update_mode_line = 1;
w->last_modified = 0;
@@ -5122,6 +5119,7 @@ displayed_window_lines (struct window *w)
{
struct it it;
struct text_pos start;
+ ptrdiff_t charpos = marker_position (w->start);
int height = window_box_height (w);
struct buffer *old_buffer;
int bottom_y;
@@ -5138,9 +5136,9 @@ displayed_window_lines (struct window *w)
/* In case W->start is out of the accessible range, do something
reasonable. This happens in Info mode when Info-scroll-down
calls (recenter -1) while W->start is 1. */
- if (XMARKER (w->start)->charpos < BEGV)
+ if (charpos < BEGV)
SET_TEXT_POS (start, BEGV, BEGV_BYTE);
- else if (XMARKER (w->start)->charpos > ZV)
+ else if (charpos > ZV)
SET_TEXT_POS (start, ZV, ZV_BYTE);
else
SET_TEXT_POS_FROM_MARKER (start, w->start);
@@ -5349,8 +5347,8 @@ and redisplay normally--don't erase and redraw the frame. */)
iarg += ht;
/* Don't let it get into the margin at either top or bottom. */
- iarg = max (iarg, this_scroll_margin);
- iarg = min (iarg, ht - this_scroll_margin - 1);
+ iarg = clip_to_bounds (this_scroll_margin, iarg,
+ ht - this_scroll_margin - 1);
pos = *vmotion (PT, - iarg, w);
charpos = pos.bufpos;
@@ -5549,7 +5547,7 @@ the return value is nil. Otherwise the value is t. */)
saved_windows = XVECTOR (data->saved_windows);
new_current_buffer = data->f_current_buffer;
- if (NILP (BVAR (XBUFFER (new_current_buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
new_current_buffer = Qnil;
else
{
@@ -5568,7 +5566,7 @@ the return value is nil. Otherwise the value is t. */)
&& WINDOWP (selected_window)
&& EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
&& !EQ (selected_window, data->current_window))
- old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
+ old_point = marker_position (XWINDOW (data->current_window)->pointm);
else
old_point = PT;
else
@@ -5583,7 +5581,7 @@ the return value is nil. Otherwise the value is t. */)
if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
/* If current_window = selected_window, its point is in BUF_PT. */
&& !EQ (selected_window, data->current_window))
- old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
+ old_point = marker_position (XWINDOW (data->current_window)->pointm);
else
old_point = BUF_PT (XBUFFER (new_current_buffer));
}
@@ -5624,7 +5622,7 @@ the return value is nil. Otherwise the value is t. */)
w = XWINDOW (window);
if (!NILP (w->buffer)
&& !EQ (w->buffer, p->buffer)
- && !NILP (BVAR (XBUFFER (p->buffer), name)))
+ && BUFFER_LIVE_P (XBUFFER (p->buffer)))
/* If a window we restore gets another buffer, record the
window's old buffer. */
call1 (Qrecord_window_buffer, window);
@@ -5632,7 +5630,7 @@ the return value is nil. Otherwise the value is t. */)
/* The mouse highlighting code could get screwed up
if it runs during this. */
- BLOCK_INPUT;
+ block_input ();
if (data->frame_lines != previous_frame_lines
|| data->frame_cols != previous_frame_cols)
@@ -5774,7 +5772,7 @@ the return value is nil. Otherwise the value is t. */)
if (NILP (p->buffer))
/* An internal window. */
wset_buffer (w, p->buffer);
- else if (!NILP (BVAR (XBUFFER (p->buffer), name)))
+ else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
/* If saved buffer is alive, install it. */
{
wset_buffer (w, p->buffer);
@@ -5793,7 +5791,7 @@ the return value is nil. Otherwise the value is t. */)
Fgoto_char (w->pointm);
}
else if (!NILP (w->buffer)
- && !NILP (BVAR (XBUFFER (w->buffer), name)))
+ && BUFFER_LIVE_P (XBUFFER (w->buffer)))
/* Keep window's old buffer; make sure the markers are
real. */
{
@@ -5883,7 +5881,7 @@ the return value is nil. Otherwise the value is t. */)
}
adjust_glyphs (f);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Scan dead buffer windows. */
for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
@@ -6177,12 +6175,7 @@ saved by this function. */)
register int n_windows;
register struct save_window_data *data;
register int i;
- FRAME_PTR f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
+ struct frame *f = decode_live_frame (frame);
n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
@@ -6335,10 +6328,9 @@ Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
{
struct window *w = decode_live_window (window);
- return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
- Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
- Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
- ? Qt : Qnil), Qnil)));
+ return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
+ make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
+ WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
}
@@ -6407,12 +6399,12 @@ value. */)
(Lisp_Object window)
{
struct window *w = decode_live_window (window);
- return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
+
+ return list4 (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
: WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
- Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
- Fcons (w->vertical_scroll_bar_type,
- Fcons (Qnil, Qnil))));
+ make_number (WINDOW_SCROLL_BAR_COLS (w)),
+ w->vertical_scroll_bar_type, Qnil);
}
@@ -6429,15 +6421,8 @@ optional second arg PIXELS-P means value is measured in pixels. */)
(Lisp_Object window, Lisp_Object pixels_p)
{
Lisp_Object result;
- struct frame *f;
- struct window *w;
-
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window);
- w = XWINDOW (window);
- f = XFRAME (w->frame);
+ struct window *w = decode_live_window (window);
+ struct frame *f = XFRAME (w->frame);
if (FRAME_WINDOW_P (f))
result = (NILP (pixels_p)
@@ -6461,18 +6446,11 @@ result of this rounding.
If PIXELS-P is non-nil, the return value is VSCROLL. */)
(Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
{
- struct window *w;
- struct frame *f;
+ struct window *w = decode_live_window (window);
+ struct frame *f = XFRAME (w->frame);
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window);
CHECK_NUMBER_OR_FLOAT (vscroll);
- w = XWINDOW (window);
- f = XFRAME (w->frame);
-
if (FRAME_WINDOW_P (f))
{
int old_dy = w->vscroll;
@@ -6576,15 +6554,17 @@ freeze_window_starts (struct frame *f, int freeze_p)
/* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
describe the same state of affairs. This is used by Fequal.
- ignore_positions non-zero means ignore non-matching scroll positions
+ IGNORE_POSITIONS means ignore non-matching scroll positions
and the like.
This ignores a couple of things like the dedication status of
window, combination_limit and the like. This might have to be
fixed. */
-int
-compare_window_configurations (Lisp_Object configuration1, Lisp_Object configuration2, int ignore_positions)
+bool
+compare_window_configurations (Lisp_Object configuration1,
+ Lisp_Object configuration2,
+ bool ignore_positions)
{
register struct save_window_data *d1, *d2;
struct Lisp_Vector *sws1, *sws2;
@@ -6710,6 +6690,7 @@ syms_of_window (void)
DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
DEFSYM (Qrecord_window_buffer, "record-window-buffer");
DEFSYM (Qget_mru_window, "get-mru-window");
+ DEFSYM (Qwindow_size, "window-size");
DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
DEFSYM (Qabove, "above");
DEFSYM (Qbelow, "below");
@@ -6805,23 +6786,36 @@ This variable takes no effect if `window-combination-limit' is non-nil. */);
Vwindow_combination_resize = Qnil;
DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
- doc: /* If t, splitting a window makes a new parent window.
-If this variable is nil, splitting a window will create a new parent
-window only if the window has no parent window or the window shall
-become a combination orthogonal to the one it is part of.
+ doc: /* If non-nil, splitting a window makes a new parent window.
+The following values are recognized:
-If this variable is t, splitting a window always creates a new parent
-window. If all splits behave this way, each frame's window tree is a
-binary tree and every window but the frame's root window has exactly one
-sibling.
+nil means splitting a window will create a new parent window only if the
+ window has no parent window or the window shall become part of a
+ combination orthogonal to the one it is part of.
-Other values are reserved for future use.
+`window-size' means that splitting a window for displaying a buffer
+ makes a new parent window provided `display-buffer' is supposed to
+ explicitly set the window's size due to the presence of a
+ `window-height' or `window-width' entry in the alist used by
+ `display-buffer'. Otherwise, this value is handled like nil.
+
+`temp-buffer' means that splitting a window for displaying a temporary
+ buffer always makes a new parent window. Otherwise, this value is
+ handled like nil.
+
+`display-buffer' means that splitting a window for displaying a buffer
+ always makes a new parent window. Since temporary buffers are
+ displayed by the function `display-buffer', this value is stronger
+ than `temp-buffer'. Splitting a window for other purpose makes a
+ new parent window only if needed.
+
+t means that splitting a window always creates a new parent window. If
+ all splits behave this way, each frame's window tree is a binary
+ tree and every window but the frame's root window has exactly one
+ sibling.
-The value of this variable is also assigned to the combination limit of
-the new parent window. The combination limit of a window can be
-retrieved via the function `window-combination-limit' and altered by the
-function `set-window-combination-limit'. */);
- Vwindow_combination_limit = Qnil;
+Other values are reserved for future use. */);
+ Vwindow_combination_limit = Qwindow_size;
DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
doc: /* Alist of persistent window parameters.
@@ -6913,7 +6907,6 @@ respectively are not installed by `window-state-put'. */);
defsubr (&Srun_window_configuration_change_hook);
defsubr (&Sselect_window);
defsubr (&Sforce_window_update);
- defsubr (&Stemp_output_buffer_show);
defsubr (&Ssplit_window_internal);
defsubr (&Sscroll_up);
defsubr (&Sscroll_down);
diff --git a/src/window.h b/src/window.h
index dfb88b2cf3c..f4f42a25af4 100644
--- a/src/window.h
+++ b/src/window.h
@@ -27,8 +27,6 @@ INLINE_HEADER_BEGIN
# define WINDOW_INLINE INLINE
#endif
-extern Lisp_Object Qleft, Qright;
-
/* Windows are allocated as if they were vectors, but then the
Lisp data type is changed to Lisp_Window. They are garbage
collected along with the vectors.
@@ -222,13 +220,6 @@ struct window
/* t means this window's child windows are not (re-)combined. */
Lisp_Object combination_limit;
- /* Alist of <buffer, window-start, window-point> triples listing
- buffers previously shown in this window. */
- Lisp_Object prev_buffers;
-
- /* List of buffers re-shown in this window. */
- Lisp_Object next_buffers;
-
/* An alist with parameters. */
Lisp_Object window_parameters;
@@ -240,6 +231,14 @@ struct window
struct glyph_matrix *current_matrix;
struct glyph_matrix *desired_matrix;
+ /* The two Lisp_Object fields below are marked in a special way,
+ which is why they're placed after `current_matrix'. */
+ /* Alist of <buffer, window-start, window-point> triples listing
+ buffers previously shown in this window. */
+ Lisp_Object prev_buffers;
+ /* List of buffers re-shown in this window. */
+ Lisp_Object next_buffers;
+
/* Number saying how recently window was selected. */
int use_time;
@@ -352,11 +351,6 @@ struct window
/* Most code should use these functions to set Lisp fields in struct
window. */
WINDOW_INLINE void
-wset_buffer (struct window *w, Lisp_Object val)
-{
- w->buffer = val;
-}
-WINDOW_INLINE void
wset_frame (struct window *w, Lisp_Object val)
{
w->frame = val;
@@ -416,7 +410,16 @@ wset_window_end_vpos (struct window *w, Lisp_Object val)
{
w->window_end_vpos = val;
}
-
+WINDOW_INLINE void
+wset_prev_buffers (struct window *w, Lisp_Object val)
+{
+ w->prev_buffers = val;
+}
+WINDOW_INLINE void
+wset_next_buffers (struct window *w, Lisp_Object val)
+{
+ w->next_buffers = val;
+}
/* 1 if W is a minibuffer window. */
@@ -939,11 +942,6 @@ extern int windows_or_buffers_changed;
extern int cursor_type_changed;
-/* Number of windows displaying the selected buffer. Normally this is
- 1, but it can be more. */
-
-extern int buffer_shared;
-
/* If *ROWS or *COLS are too small a size for FRAME, set them to the
minimum allowable size. */
@@ -962,24 +960,35 @@ struct glyph *get_phys_cursor_glyph (struct window *w);
|| !NILP (XWINDOW (WINDOW)->vchild) \
|| !NILP (XWINDOW (WINDOW)->hchild)))
+/* A window of any sort, leaf or interior, is "valid" if one
+ of its buffer, vchild, or hchild members is non-nil. */
+#define CHECK_VALID_WINDOW(WINDOW) \
+ CHECK_TYPE (WINDOW_VALID_P (WINDOW), Qwindow_valid_p, WINDOW)
/* Value is non-zero if WINDOW is a live window. */
#define WINDOW_LIVE_P(WINDOW) \
(WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->buffer))
+/* A window is "live" if and only if it shows a buffer. */
+#define CHECK_LIVE_WINDOW(WINDOW) \
+ CHECK_TYPE (WINDOW_LIVE_P (WINDOW), Qwindow_live_p, WINDOW)
+
/* These used to be in lisp.h. */
extern Lisp_Object Qwindowp, Qwindow_live_p;
extern Lisp_Object Vwindow_list;
extern struct window *decode_live_window (Lisp_Object);
-extern int compare_window_configurations (Lisp_Object, Lisp_Object, int);
+extern struct window *decode_any_window (Lisp_Object);
+extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
extern void mark_window_cursors_off (struct window *);
extern int window_internal_height (struct window *);
extern int window_body_cols (struct window *w);
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);
+/* This looks like a setter, but it is a bit special. */
+extern void wset_buffer (struct window *, Lisp_Object);
extern void init_window_once (void);
extern void init_window (void);
extern void syms_of_window (void);
diff --git a/src/xdisp.c b/src/xdisp.c
index 86f041dea4d..f7fc75f8c25 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -273,9 +273,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <limits.h>
-#include <setjmp.h>
#include "lisp.h"
+#include "atimer.h"
#include "keyboard.h"
#include "frame.h"
#include "window.h"
@@ -302,7 +302,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
#include "w32term.h"
#endif
#ifdef HAVE_NS
@@ -333,10 +333,10 @@ 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 */
+/* Cursor shapes. */
Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
-/* Pointer shapes */
+/* Pointer shapes. */
static Lisp_Object Qarrow, Qhand;
Lisp_Object Qtext;
@@ -347,6 +347,7 @@ 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. */
@@ -366,22 +367,22 @@ static Lisp_Object Qmargin, Qpointer;
static Lisp_Object Qline_height;
/* These setters are used only in this file, so they can be private. */
-static inline void
+static void
wset_base_line_number (struct window *w, Lisp_Object val)
{
w->base_line_number = val;
}
-static inline void
+static void
wset_base_line_pos (struct window *w, Lisp_Object val)
{
w->base_line_pos = val;
}
-static inline void
+static void
wset_column_number_displayed (struct window *w, Lisp_Object val)
{
w->column_number_displayed = val;
}
-static inline void
+static void
wset_region_showing (struct window *w, Lisp_Object val)
{
w->region_showing = val;
@@ -514,12 +515,6 @@ Lisp_Object Qmenu_bar_update_hook;
static int overlay_arrow_seen;
-/* Number of windows showing the buffer of the selected window (or
- another buffer with the same base buffer). keyboard.c refers to
- this. */
-
-int buffer_shared;
-
/* Vector containing glyphs for an ellipsis `...'. */
static Lisp_Object default_invis_vector[3];
@@ -927,6 +922,7 @@ static enum move_it_result
move_it_in_display_line_to (struct it *, ptrdiff_t, int,
enum move_operation_enum);
void move_it_vertically_backward (struct it *, int);
+static void get_visually_first_element (struct it *);
static void init_to_row_start (struct it *, struct window *,
struct glyph_row *);
static int init_to_row_end (struct it *, struct window *,
@@ -1190,7 +1186,7 @@ window_box (struct window *w, int area, int *box_x, int *box_y,
*BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
box. */
-static inline void
+static void
window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
int *bottom_right_x, int *bottom_right_y)
{
@@ -1277,7 +1273,7 @@ string_from_display_spec (Lisp_Object spec)
/* Limit insanely large values of W->hscroll on frame F to the largest
value that will still prevent first_visible_x and last_visible_x of
'struct it' from overflowing an int. */
-static inline int
+static int
window_hscroll_limited (struct window *w, struct frame *f)
{
ptrdiff_t window_hscroll = w->hscroll;
@@ -1624,7 +1620,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
returns an invalid character. If we find one, we return a `?', but
with the length of the invalid character. */
-static inline int
+static int
string_char_and_length (const unsigned char *str, int *len)
{
int c;
@@ -1672,7 +1668,7 @@ string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t ncha
/* Value is the text position, i.e. character and byte position,
for character position CHARPOS in STRING. */
-static inline struct text_pos
+static struct text_pos
string_pos (ptrdiff_t charpos, Lisp_Object string)
{
struct text_pos pos;
@@ -2563,8 +2559,24 @@ check_window_end (struct window *w)
#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
+/* Return mark position if current buffer has the region of non-zero length,
+ or -1 otherwise. */
+
+static ptrdiff_t
+markpos_of_region (void)
+{
+ if (!NILP (Vtransient_mark_mode)
+ && !NILP (BVAR (current_buffer, mark_active))
+ && XMARKER (BVAR (current_buffer, mark))->buffer != NULL)
+ {
+ ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos;
+
+ if (markpos != PT)
+ return markpos;
+ }
+ return -1;
+}
-
/***********************************************************************
Iterator initialization
***********************************************************************/
@@ -2593,7 +2605,7 @@ init_iterator (struct it *it, struct window *w,
ptrdiff_t charpos, ptrdiff_t bytepos,
struct glyph_row *row, enum face_id base_face_id)
{
- int highlight_region_p;
+ ptrdiff_t markpos;
enum face_id remapped_base_face_id = base_face_id;
/* Some precondition checks. */
@@ -2696,16 +2708,11 @@ init_iterator (struct it *it, struct window *w,
/* Are multibyte characters enabled in current_buffer? */
it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
- /* Non-zero if we should highlight the region. */
- highlight_region_p
- = (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active))
- && XMARKER (BVAR (current_buffer, mark))->buffer != 0);
-
- /* Set IT->region_beg_charpos and IT->region_end_charpos to the
- start and end of a visible region in window IT->w. Set both to
- -1 to indicate no region. */
- if (highlight_region_p
+ /* If visible region is of non-zero length, set IT->region_beg_charpos
+ and IT->region_end_charpos to the start and end of a visible region
+ in window IT->w. Set both to -1 to indicate no region. */
+ markpos = markpos_of_region ();
+ if (0 <= markpos
/* Maybe highlight only in selected window. */
&& (/* Either show region everywhere. */
highlight_nonselected_windows
@@ -2717,7 +2724,6 @@ init_iterator (struct it *it, struct window *w,
&& WINDOWP (minibuf_selected_window)
&& w == XWINDOW (minibuf_selected_window))))
{
- ptrdiff_t markpos = marker_position (BVAR (current_buffer, mark));
it->region_beg_charpos = min (PT, markpos);
it->region_end_charpos = max (PT, markpos);
}
@@ -3112,6 +3118,40 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
eassert (STRINGP (it->string));
it->current.string_pos = pos->string_pos;
it->method = GET_FROM_STRING;
+ it->end_charpos = SCHARS (it->string);
+ /* Set up the bidi iterator for this overlay string. */
+ if (it->bidi_p)
+ {
+ it->bidi_it.string.lstring = it->string;
+ it->bidi_it.string.s = NULL;
+ it->bidi_it.string.schars = SCHARS (it->string);
+ it->bidi_it.string.bufpos = it->overlay_strings_charpos;
+ it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
+ it->bidi_it.string.unibyte = !it->multibyte_p;
+ bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+ FRAME_WINDOW_P (it->f), &it->bidi_it);
+
+ /* Synchronize the state of the bidi iterator with
+ pos->string_pos. For any string position other than
+ zero, this will be done automagically when we resume
+ iteration over the string and get_visually_first_element
+ is called. But if string_pos is zero, and the string is
+ to be reordered for display, we need to resync manually,
+ since it could be that the iteration state recorded in
+ pos ended at string_pos of 0 moving backwards in string. */
+ if (CHARPOS (pos->string_pos) == 0)
+ {
+ get_visually_first_element (it);
+ if (IT_STRING_CHARPOS (*it) != 0)
+ do {
+ /* Paranoia. */
+ eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
+ bidi_move_to_visually_next (&it->bidi_it);
+ } while (it->bidi_it.charpos != 0);
+ }
+ eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
+ && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
+ }
}
if (CHARPOS (pos->string_pos) >= 0)
@@ -3121,6 +3161,9 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
IT should already be filled with that string. */
it->current.string_pos = pos->string_pos;
eassert (STRINGP (it->string));
+ if (it->bidi_p)
+ bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+ FRAME_WINDOW_P (it->f), &it->bidi_it);
}
/* Restore position in display vector translations, control
@@ -3666,7 +3709,7 @@ handle_fontified_prop (struct it *it)
}
/* There isn't much we can reasonably do to protect against
misbehaving fontification, but here's a fig leaf. */
- else if (!NILP (BVAR (obuf, name)))
+ else if (BUFFER_LIVE_P (obuf))
set_buffer_internal_1 (obuf);
/* The fontification code may have added/removed text.
@@ -3722,18 +3765,26 @@ handle_face_prop (struct it *it)
if (new_face_id != it->face_id)
{
struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
+ /* If it->face_id is -1, old_face below will be NULL, see
+ the definition of FACE_FROM_ID. This will happen if this
+ is the initial call that gets the face. */
+ struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
- /* If new face has a box but old face has not, this is
- the start of a run of characters with box, i.e. it has
- a shadow on the left side. The value of face_id of the
- iterator will be -1 if this is the initial call that gets
- the face. In this case, we have to look in front of IT's
- position and see whether there is a face != new_face_id. */
- it->start_of_box_run_p
- = (new_face->box != FACE_NO_BOX
- && (it->face_id >= 0
- || IT_CHARPOS (*it) == BEG
- || new_face_id != face_before_it_pos (it)));
+ /* If the value of face_id of the iterator is -1, we have to
+ look in front of IT's position and see whether there is a
+ face there that's different from new_face_id. */
+ if (!old_face && IT_CHARPOS (*it) > BEG)
+ {
+ int prev_face_id = face_before_it_pos (it);
+
+ old_face = FACE_FROM_ID (it->f, prev_face_id);
+ }
+
+ /* If the new face has a box, but the old face does not,
+ this is the start of a run of characters with box face,
+ i.e. this character has a shadow on the left side. */
+ it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
+ && (old_face == NULL || !old_face->box));
it->face_box_p = new_face->box != FACE_NO_BOX;
}
}
@@ -5347,6 +5398,7 @@ next_overlay_string (struct it *it)
SET_TEXT_POS (it->current.string_pos, 0, 0);
it->method = GET_FROM_STRING;
it->stop_charpos = 0;
+ it->end_charpos = SCHARS (it->string);
if (it->cmp_it.stop_pos >= 0)
it->cmp_it.stop_pos = 0;
it->prev_stop = 0;
@@ -6300,6 +6352,8 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
it->stop_charpos = CHARPOS (pos);
it->base_level_stop = CHARPOS (pos);
}
+ /* This make the information stored in it->cmp_it invalidate. */
+ it->cmp_it.id = -1;
}
@@ -7306,7 +7360,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
default:
/* There are no other methods defined, so this should be a bug. */
- abort ();
+ emacs_abort ();
}
eassert (it->method != GET_FROM_STRING
@@ -7756,12 +7810,12 @@ compute_stop_pos_backwards (struct it *it)
{
it->end_charpos = min (charpos + 1, ZV);
charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
- SET_TEXT_POS (pos, charpos, BYTE_TO_CHAR (charpos));
+ SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
reseat_1 (it, pos, 0);
compute_stop_pos (it);
/* We must advance forward, right? */
if (it->stop_charpos <= charpos)
- abort ();
+ emacs_abort ();
}
while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
@@ -7810,7 +7864,7 @@ handle_stop_backwards (struct it *it, ptrdiff_t charpos)
compute_stop_pos (it);
/* We must advance forward, right? */
if (it->stop_charpos <= it->prev_stop)
- abort ();
+ emacs_abort ();
charpos = it->stop_charpos;
}
while (charpos <= where_we_are);
@@ -8898,7 +8952,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
break;
default:
- abort ();
+ emacs_abort ();
}
/* Reset/increment for the next run. */
@@ -9291,12 +9345,6 @@ add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
USE_SAFE_ALLOCA;
- /* Do nothing if called asynchronously. Inserting text into
- a buffer may call after-change-functions and alike and
- that would means running Lisp asynchronously. */
- if (handling_signal)
- return;
-
fmt = msg = Qnil;
GCPRO4 (fmt, msg, arg1, arg2);
@@ -9465,7 +9513,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
}
}
- BEGV = XMARKER (oldbegv)->charpos;
+ BEGV = marker_position (oldbegv);
BEGV_BYTE = marker_byte_position (oldbegv);
if (zv_at_end)
@@ -9475,7 +9523,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
}
else
{
- ZV = XMARKER (oldzv)->charpos;
+ ZV = marker_position (oldzv);
ZV_BYTE = marker_byte_position (oldzv);
}
@@ -9484,8 +9532,8 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
else
/* We can't do Fgoto_char (oldpoint) because it will run some
Lisp code. */
- TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
- XMARKER (oldpoint)->bytepos);
+ TEMP_SET_PT_BOTH (marker_position (oldpoint),
+ marker_byte_position (oldpoint));
UNGCPRO;
unchain_marker (XMARKER (oldpoint));
@@ -9607,7 +9655,7 @@ message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte)
do_pending_window_change (0);
echo_area_display (1);
do_pending_window_change (0);
- if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
}
@@ -9704,7 +9752,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
do_pending_window_change (0);
echo_area_display (1);
do_pending_window_change (0);
- if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
}
@@ -9909,7 +9957,7 @@ ensure_echo_area_buffers (void)
for (i = 0; i < 2; ++i)
if (!BUFFERP (echo_buffer[i])
- || NILP (BVAR (XBUFFER (echo_buffer[i]), name)))
+ || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
{
char name[30];
Lisp_Object old_buffer;
@@ -10057,8 +10105,8 @@ with_echo_area_buffer_unwind_data (struct window *w)
{
XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
ASET (vector, i, w->buffer); ++i;
- ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
- ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
+ ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
+ ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
}
else
{
@@ -10355,8 +10403,7 @@ resize_mini_window (struct window *w, int exact_p)
max_height = total_height / 4;
/* Correct that max. height if it's bogus. */
- max_height = max (1, max_height);
- max_height = min (total_height, max_height);
+ max_height = clip_to_bounds (1, max_height, total_height);
/* Find out the height of the text in the window. */
if (it.line_wrap == TRUNCATE)
@@ -10532,7 +10579,7 @@ void
check_message_stack (void)
{
if (!NILP (Vmessage_stack))
- abort ();
+ emacs_abort ();
}
@@ -10571,7 +10618,6 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4
return 0;
}
-
/* Set the current message to a substring of S or STRING.
If STRING is a Lisp string, set the message to the first NBYTES
@@ -10598,6 +10644,10 @@ set_message (const char *s, Lisp_Object string,
(intptr_t) s, string, nbytes, multibyte_p);
message_buf_print = 0;
help_echo_showing_p = 0;
+
+ if (STRINGP (Vdebug_on_message)
+ && fast_string_match (Vdebug_on_message, string) >= 0)
+ call_debugger (list2 (Qerror, string));
}
@@ -10730,7 +10780,7 @@ clear_garbaged_frames (void)
{
if (f->resized_p)
{
- Fredraw_frame (frame);
+ redraw_frame (f);
f->force_flush_display_p = 1;
}
clear_current_matrices (f);
@@ -10777,8 +10827,7 @@ echo_area_display (int update_frame_p)
#endif /* HAVE_WINDOW_SYSTEM */
/* Redraw garbaged frames. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
{
@@ -10851,8 +10900,52 @@ echo_area_display (int update_frame_p)
return window_height_changed_p;
}
+/* Nonzero if the current window's buffer is shown in more than one
+ window and was modified since last redisplay. */
+
+static int
+buffer_shared_and_changed (void)
+{
+ return (buffer_window_count (current_buffer) > 1
+ && UNCHANGED_MODIFIED < MODIFF);
+}
+
+/* Nonzero if W doesn't reflect the actual state of current buffer due
+ to its text or overlays change. FIXME: this may be called when
+ XBUFFER (w->buffer) != current_buffer, which looks suspicious. */
+
+static int
+window_outdated (struct window *w)
+{
+ return (w->last_modified < MODIFF
+ || w->last_overlay_modified < OVERLAY_MODIFF);
+}
+
+/* Nonzero if W's buffer was changed but not saved or Transient Mark mode
+ is enabled and mark of W's buffer was changed since last W's update. */
+
+static int
+window_buffer_changed (struct window *w)
+{
+ struct buffer *b = XBUFFER (w->buffer);
+
+ eassert (BUFFER_LIVE_P (b));
+
+ return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
+ || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
+ != !NILP (w->region_showing)));
+}
+
+/* Nonzero if W has %c in its mode line and mode line should be updated. */
+
+static int
+mode_line_update_needed (struct window *w)
+{
+ return (!NILP (w->column_number_displayed)
+ && !(PT == w->last_point && !window_outdated (w))
+ && (XFASTINT (w->column_number_displayed) != current_column ()));
+}
-
/***********************************************************************
Mode Lines and Frame Titles
***********************************************************************/
@@ -11057,17 +11150,15 @@ x_consider_frame_title (Lisp_Object frame)
|| f->explicit_name)
{
/* Do we have more than one visible frame on this X display? */
- Lisp_Object tail;
- Lisp_Object fmt;
+ Lisp_Object tail, other_frame, fmt;
ptrdiff_t title_start;
char *title;
ptrdiff_t len;
struct it it;
ptrdiff_t count = SPECPDL_INDEX ();
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, other_frame)
{
- Lisp_Object other_frame = XCAR (tail);
struct frame *tf = XFRAME (other_frame);
if (tf != f
@@ -11160,7 +11251,7 @@ prepare_menu_bars (void)
/* Update the menu bar item lists, if appropriate. This has to be
done before any actual redisplay or generation of display lines. */
all_windows = (update_mode_lines
- || buffer_shared > 1
+ || buffer_shared_and_changed ()
|| windows_or_buffers_changed);
if (all_windows)
{
@@ -11274,12 +11365,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
/* This used to test w->update_mode_line, but we believe
there is no need to recompute the menu in that case. */
|| update_mode_lines
- || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- < BUF_MODIFF (XBUFFER (w->buffer)))
- != w->last_had_star)
- || ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
- != !NILP (w->region_showing)))
+ || window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
ptrdiff_t count = SPECPDL_INDEX ();
@@ -11405,11 +11491,11 @@ x_cursor_to (int vpos, int hpos, int y, int x)
This will also set the cursor position of W. */
if (updated_window == NULL)
{
- BLOCK_INPUT;
+ block_input ();
display_and_set_cursor (w, 1, hpos, vpos, x, y);
if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -11431,11 +11517,18 @@ FRAME_PTR last_mouse_frame;
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
+ when `norecord' is set. */
static Lisp_Object
-update_tool_bar_unwind (Lisp_Object frame)
+fast_set_selected_frame (Lisp_Object frame)
{
- selected_frame = frame;
+ if (!EQ (selected_frame, frame))
+ {
+ selected_frame = frame;
+ selected_window = XFRAME (frame)->selected_window;
+ }
return Qnil;
}
@@ -11472,12 +11565,7 @@ update_tool_bar (struct frame *f, int save_match_data)
if (windows_or_buffers_changed
|| w->update_mode_line
|| update_mode_lines
- || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- < BUF_MODIFF (XBUFFER (w->buffer)))
- != w->last_had_star)
- || ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
- != !NILP (w->region_showing)))
+ || window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
ptrdiff_t count = SPECPDL_INDEX ();
@@ -11507,9 +11595,13 @@ update_tool_bar (struct frame *f, int save_match_data)
before calling tool_bar_items, because the calculation of
the tool-bar keymap uses the selected frame (see
`tool-bar-make-keymap' in tool-bar.el). */
- record_unwind_protect (update_tool_bar_unwind, selected_frame);
+ eassert (EQ (selected_window,
+ /* Since we only explicitly preserve selected_frame,
+ check that selected_window would be redundant. */
+ XFRAME (selected_frame)->selected_window));
+ record_unwind_protect (fast_set_selected_frame, selected_frame);
XSETFRAME (frame, f);
- selected_frame = frame;
+ fast_set_selected_frame (frame);
/* Build desired tool-bar items from keymaps. */
new_tool_bar
@@ -11523,11 +11615,11 @@ update_tool_bar (struct frame *f, int save_match_data)
/* Redisplay that happens asynchronously due to an expose event
may access f->tool_bar_items. Make sure we update both
variables within BLOCK_INPUT so no such event interrupts. */
- BLOCK_INPUT;
+ block_input ();
fset_tool_bar_items (f, new_tool_bar);
f->n_tool_bar_items = new_n_tool_bar;
w->update_mode_line = 1;
- UNBLOCK_INPUT;
+ unblock_input ();
}
UNGCPRO;
@@ -11877,19 +11969,14 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
0, 1, 0,
- doc: /* Return the number of lines occupied by the tool bar of FRAME. */)
+ doc: /* Return the number of lines occupied by the tool bar of FRAME.
+If FRAME is nil or omitted, use the selected frame. */)
(Lisp_Object frame)
{
- struct frame *f;
+ struct frame *f = decode_any_frame (frame);
struct window *w;
int nlines = 0;
- if (NILP (frame))
- frame = selected_frame;
- else
- CHECK_FRAME (frame);
- f = XFRAME (frame);
-
if (WINDOWP (f->tool_bar_window)
&& (w = XWINDOW (f->tool_bar_window),
WINDOW_TOTAL_LINES (w) > 0))
@@ -12189,7 +12276,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
{
/* Show item in pressed state. */
show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
- hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
last_tool_bar_item = prop_idx;
}
else
@@ -12200,7 +12286,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
/* Show item in released state. */
show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
- hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
@@ -12269,7 +12354,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
&& last_tool_bar_item != prop_idx)
return;
- hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
/* If tool-bar item is not enabled, don't highlight it. */
@@ -12298,7 +12382,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
/* Display it as active. */
show_mouse_face (hlinfo, draw);
- hlinfo->mouse_face_image_state = draw;
}
set_help_echo:
@@ -12422,11 +12505,7 @@ hscroll_window_tree (Lisp_Object window)
if (w == XWINDOW (selected_window))
pt = PT;
else
- {
- pt = marker_position (w->pointm);
- pt = max (BEGV, pt);
- pt = min (ZV, pt);
- }
+ pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
/* Move iterator to pt starting at cursor_row->start in
a line with infinite width. */
@@ -12578,15 +12657,14 @@ debug_method_add (struct window *w, char const *fmt, ...)
buffer position, END is given as a distance from Z. Used in
redisplay_internal for display optimization. */
-static inline int
+static int
text_outside_line_unchanged_p (struct window *w,
ptrdiff_t start, ptrdiff_t end)
{
int unchanged_p = 1;
/* If text or overlays have changed, see where. */
- if (w->last_modified < MODIFF
- || w->last_overlay_modified < OVERLAY_MODIFF)
+ if (window_outdated (w))
{
/* Gap in the line? */
if (GPT < start || Z - GPT < end)
@@ -12789,7 +12867,7 @@ overlay_arrow_at_row (struct it *it, struct glyph_row *row)
return make_number (fringe_bitmap);
}
#endif
- return make_number (-1); /* Use default arrow bitmap */
+ return make_number (-1); /* Use default arrow bitmap. */
}
return overlay_arrow_string_or_property (var);
}
@@ -12839,7 +12917,7 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
/* Reconsider the setting of B->clip_changed which is displayed
in window W. */
-static inline void
+static void
reconsider_clip_changes (struct window *w, struct buffer *b)
{
if (b->clip_changed
@@ -12888,6 +12966,7 @@ select_frame_for_redisplay (Lisp_Object frame)
eassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
selected_frame = frame;
+ selected_window = XFRAME (frame)->selected_window;
do {
for (tail = XFRAME (frame)->param_alist;
@@ -12904,6 +12983,15 @@ select_frame_for_redisplay (Lisp_Object frame)
} while (!EQ (frame, old) && (frame = old, 1));
}
+/* Make sure that previously selected OLD_FRAME is selected unless it has been
+ deleted (by an X connection failure during redisplay, for example). */
+
+static void
+ensure_selected_frame (Lisp_Object frame)
+{
+ if (!EQ (frame, selected_frame) && FRAME_LIVE_P (XFRAME (frame)))
+ select_frame_for_redisplay (frame);
+}
#define STOP_POLLING \
do { if (! polling_stopped_here) stop_polling (); \
@@ -12930,13 +13018,14 @@ redisplay_internal (void)
ptrdiff_t count, count1;
struct frame *sf;
int polling_stopped_here = 0;
- Lisp_Object old_frame = selected_frame;
+ Lisp_Object tail, frame, old_frame = selected_frame;
+ struct backtrace backtrace;
/* Non-zero means redisplay has to consider all windows on all
frames. Zero means, only selected_window is considered. */
int consider_all_windows_p;
- /* Non-zero means redisplay has to redisplay the miniwindow */
+ /* Non-zero means redisplay has to redisplay the miniwindow. */
int update_miniwindow_p = 0;
TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
@@ -12973,27 +13062,26 @@ redisplay_internal (void)
redisplaying_p = 1;
specbind (Qinhibit_free_realized_faces, Qnil);
- {
- Lisp_Object tail, frame;
+ /* Record this function, so it appears on the profiler's backtraces. */
+ backtrace.next = backtrace_list;
+ backtrace.function = Qredisplay_internal;
+ backtrace.args = &Qnil;
+ backtrace.nargs = 0;
+ backtrace.debug_on_exit = 0;
+ backtrace_list = &backtrace;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
- f->already_hscrolled_p = 0;
- }
- }
+ FOR_EACH_FRAME (tail, frame)
+ XFRAME (frame)->already_hscrolled_p = 0;
retry:
/* Remember the currently selected window. */
sw = w;
- if (!EQ (old_frame, selected_frame)
- && FRAME_LIVE_P (XFRAME (old_frame)))
- /* When running redisplay, we play a bit fast-and-loose and allow e.g.
- selected_frame and selected_window to be temporarily out-of-sync so
- when we come back here via `goto retry', we need to resync because we
- may need to run Elisp code (via prepare_menu_bars). */
- select_frame_for_redisplay (old_frame);
+ /* When running redisplay, we play a bit fast-and-loose and allow e.g.
+ selected_frame and selected_window to be temporarily out-of-sync so
+ when we come back here via `goto retry', we need to resync because we
+ may need to run Elisp code (via prepare_menu_bars). */
+ ensure_selected_frame (old_frame);
pending = 0;
reconsider_clip_changes (w, current_buffer);
@@ -13031,25 +13119,20 @@ redisplay_internal (void)
FRAME_TTY (sf)->previous_frame = sf;
}
- /* Set the visible flags for all frames. Do this before checking
- for resized or garbaged frames; they want to know if their frames
- are visible. See the comment in frame.h for
- FRAME_SAMPLE_VISIBILITY. */
- {
- Lisp_Object tail, frame;
-
- number_of_visible_frames = 0;
+ /* Set the visible flags for all frames. Do this before checking for
+ resized or garbaged frames; they want to know if their frames are
+ visible. See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
+ number_of_visible_frames = 0;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
- FRAME_SAMPLE_VISIBILITY (f);
- if (FRAME_VISIBLE_P (f))
- ++number_of_visible_frames;
- clear_desired_matrices (f);
- }
- }
+ FRAME_SAMPLE_VISIBILITY (f);
+ if (FRAME_VISIBLE_P (f))
+ ++number_of_visible_frames;
+ clear_desired_matrices (f);
+ }
/* Notice any pending interrupt request to change frame size. */
do_pending_window_change (1);
@@ -13063,8 +13146,7 @@ redisplay_internal (void)
}
/* Clear frames marked as garbaged. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
/* Build menubar and tool-bar items. */
if (NILP (Vmemory_full))
@@ -13077,7 +13159,7 @@ redisplay_internal (void)
if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
{
w->update_mode_line = 1;
- if (buffer_shared > 1)
+ if (buffer_shared_and_changed ())
update_mode_lines++;
}
@@ -13085,24 +13167,15 @@ redisplay_internal (void)
count1 = SPECPDL_INDEX ();
specbind (Qinhibit_point_motion_hooks, Qt);
- /* If %c is in the mode line, update it if needed. */
- if (!NILP (w->column_number_displayed)
- /* This alternative quickly identifies a common case
- where no change is needed. */
- && !(PT == w->last_point
- && w->last_modified >= MODIFF
- && w->last_overlay_modified >= OVERLAY_MODIFF)
- && (XFASTINT (w->column_number_displayed) != current_column ()))
+ if (mode_line_update_needed (w))
w->update_mode_line = 1;
unbind_to (count1, Qnil);
FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
- /* The variable buffer_shared is set in redisplay_window and
- indicates that we redisplay a buffer in different windows. See
- there. */
- consider_all_windows_p = (update_mode_lines || buffer_shared > 1
+ consider_all_windows_p = (update_mode_lines
+ || buffer_shared_and_changed ()
|| cursor_type_changed);
/* If specs for an arrow have changed, do thorough redisplay
@@ -13148,23 +13221,20 @@ redisplay_internal (void)
/* If window configuration was changed, frames may have been
marked garbaged. Clear them or we will experience
surprises wrt scrolling. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
}
}
else if (EQ (selected_window, minibuf_window)
- && (current_buffer->clip_changed
- || w->last_modified < MODIFF
- || w->last_overlay_modified < OVERLAY_MODIFF)
+ && (current_buffer->clip_changed || window_outdated (w))
&& resize_mini_window (w, 0))
{
/* Resized active mini-window to fit the size of what it is
showing if its contents might have changed. */
must_finish = 1;
-/* FIXME: this causes all frames to be updated, which seems unnecessary
- since only the current frame needs to be considered. This function needs
- to be rewritten with two variables, consider_all_windows and
- consider_all_frames. */
+ /* FIXME: this causes all frames to be updated, which seems unnecessary
+ since only the current frame needs to be considered. This function
+ needs to be rewritten with two variables, consider_all_windows and
+ consider_all_frames. */
consider_all_windows_p = 1;
++windows_or_buffers_changed;
++update_mode_lines;
@@ -13172,8 +13242,7 @@ redisplay_internal (void)
/* If window configuration was changed, frames may have been
marked garbaged. Clear them or we will experience
surprises wrt scrolling. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
}
@@ -13220,9 +13289,7 @@ redisplay_internal (void)
|| FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
/* Former continuation line has disappeared by becoming empty. */
goto cancel;
- else if (w->last_modified < MODIFF
- || w->last_overlay_modified < OVERLAY_MODIFF
- || MINI_WINDOW_P (w))
+ else if (window_outdated (w) || MINI_WINDOW_P (w))
{
/* We have to handle the case of continuation around a
wide-column character (see the comment in indent.c around
@@ -13396,7 +13463,7 @@ redisplay_internal (void)
}
CHARPOS (this_line_start_pos) = 0;
- consider_all_windows_p |= buffer_shared > 1;
+ consider_all_windows_p |= buffer_shared_and_changed ();
++clear_face_cache_count;
#ifdef HAVE_WINDOW_SYSTEM
++clear_image_cache_count;
@@ -13408,15 +13475,9 @@ redisplay_internal (void)
if (consider_all_windows_p)
{
- Lisp_Object tail, frame;
-
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->updated_p = 0;
- /* Recompute # windows showing selected buffer. This will be
- incremented each time such a window is displayed. */
- buffer_shared = 0;
-
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
@@ -13483,14 +13544,11 @@ redisplay_internal (void)
}
}
- if (!EQ (old_frame, selected_frame)
- && FRAME_LIVE_P (XFRAME (old_frame)))
- /* We played a bit fast-and-loose above and allowed selected_frame
- and selected_window to be temporarily out-of-sync but let's make
- sure this stays contained. */
- select_frame_for_redisplay (old_frame);
- eassert (EQ (XFRAME (selected_frame)->selected_window,
- selected_window));
+ /* We played a bit fast-and-loose above and allowed selected_frame
+ and selected_window to be temporarily out-of-sync but let's make
+ sure this stays contained. */
+ ensure_selected_frame (old_frame);
+ eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
if (!pending)
{
@@ -13619,7 +13677,6 @@ redisplay_internal (void)
frames here explicitly. */
if (!pending)
{
- Lisp_Object tail, frame;
int new_count = 0;
FOR_EACH_FRAME (tail, frame)
@@ -13670,6 +13727,7 @@ redisplay_internal (void)
#endif /* HAVE_WINDOW_SYSTEM */
end_of_redisplay:
+ backtrace_list = backtrace.next;
unbind_to (count, Qnil);
RESUME_POLLING;
}
@@ -13709,17 +13767,13 @@ redisplay_preserve_echo_area (int from_where)
/* Function registered with record_unwind_protect in redisplay_internal.
- Clear redisplaying_p. Also, select the previously
- selected frame, unless it has been deleted (by an X connection
- failure during redisplay, for example). */
+ Clear redisplaying_p. Also select the previously selected frame. */
static Lisp_Object
unwind_redisplay (Lisp_Object old_frame)
{
redisplaying_p = 0;
- if (! EQ (old_frame, selected_frame)
- && FRAME_LIVE_P (XFRAME (old_frame)))
- select_frame_for_redisplay (old_frame);
+ ensure_selected_frame (old_frame);
return Qnil;
}
@@ -13761,7 +13815,7 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
if (w == XWINDOW (selected_window))
w->last_point = BUF_PT (b);
else
- w->last_point = XMARKER (w->pointm)->charpos;
+ w->last_point = marker_position (w->pointm);
}
}
@@ -14183,7 +14237,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
GLYPH_BEFORE and GLYPH_AFTER. */
if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
&& BUFFERP (glyph->object) && glyph->charpos == pt_old)
- && bpos_covered < pt_old)
+ && !(bpos_max < pt_old && pt_old <= bpos_covered))
{
/* An empty line has a single glyph whose OBJECT is zero and
whose CHARPOS is the position of a newline on that line.
@@ -14415,7 +14469,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
{
if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
- abort ();
+ emacs_abort ();
x += g->pixel_width;
}
}
@@ -14529,14 +14583,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
We assume that the window's buffer is really current. */
-static inline struct text_pos
+static struct text_pos
run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
{
struct window *w = XWINDOW (window);
SET_MARKER_FROM_TEXT_POS (w->start, startp);
if (current_buffer != XBUFFER (w->buffer))
- abort ();
+ emacs_abort ();
if (!NILP (Vwindow_scroll_functions))
{
@@ -14742,13 +14796,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
if (NUMBERP (aggressive))
{
double float_amount = XFLOATINT (aggressive) * height;
- amount_to_scroll = float_amount;
- if (amount_to_scroll == 0 && float_amount > 0)
- amount_to_scroll = 1;
+ int aggressive_scroll = float_amount;
+ if (aggressive_scroll == 0 && float_amount > 0)
+ aggressive_scroll = 1;
/* Don't let point enter the scroll margin near top of
- the window. */
- if (amount_to_scroll > height - 2*this_scroll_margin + dy)
- amount_to_scroll = height - 2*this_scroll_margin + dy;
+ the window. This could happen if the value of
+ scroll_up_aggressively is too large and there are
+ 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;
+ amount_to_scroll = dy + aggressive_scroll;
}
}
@@ -14808,7 +14867,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
/* Compute the vertical distance from PT to the scroll
margin position. Move as far as scroll_max allows, or
one screenful, or 10 screen lines, whichever is largest.
- Give up if distance is greater than scroll_max. */
+ Give up if distance is greater than scroll_max or if we
+ didn't reach the scroll margin position. */
SET_TEXT_POS (pos, PT, PT_BYTE);
start_display (&it, w, pos);
y0 = it.current_y;
@@ -14818,7 +14878,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
y_to_move, -1,
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
dy = it.current_y - y0;
- if (dy > scroll_max)
+ if (dy > scroll_max
+ || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
return SCROLLING_FAILED;
/* Compute new window start. */
@@ -14836,15 +14897,16 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
if (NUMBERP (aggressive))
{
double float_amount = XFLOATINT (aggressive) * height;
- amount_to_scroll = float_amount;
- if (amount_to_scroll == 0 && float_amount > 0)
- amount_to_scroll = 1;
- amount_to_scroll -=
- this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
+ int aggressive_scroll = float_amount;
+ if (aggressive_scroll == 0 && float_amount > 0)
+ aggressive_scroll = 1;
/* Don't let point enter the scroll margin near
- bottom of the window. */
- if (amount_to_scroll > height - 2*this_scroll_margin + dy)
- amount_to_scroll = height - 2*this_scroll_margin + dy;
+ 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;
+ amount_to_scroll = dy + aggressive_scroll;
}
}
@@ -15022,8 +15084,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
/* Can't use this case if highlighting a region. When a
region exists, cursor movement has to do more than just
set the cursor. */
- && !(!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ && markpos_of_region () < 0
&& NILP (w->region_showing)
&& NILP (Vshow_trailing_whitespace)
/* This code is not used for mini-buffer for the sake of the case
@@ -15464,8 +15525,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
= (!NILP (w->window_end_valid)
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
- && w->last_modified >= MODIFF
- && w->last_overlay_modified >= OVERLAY_MODIFF);
+ && !window_outdated (w));
/* Run the window-bottom-change-functions
if it is possible that the text on the screen has changed
@@ -15487,8 +15547,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
buffer_unchanged_p
= (!NILP (w->window_end_valid)
&& !current_buffer->clip_changed
- && w->last_modified >= MODIFF
- && w->last_overlay_modified >= OVERLAY_MODIFF);
+ && !window_outdated (w));
/* When windows_or_buffers_changed is non-zero, we can't rely on
the window end being valid, so set it to nil there. */
@@ -15505,40 +15564,18 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
/* Some sanity checks. */
CHECK_WINDOW_END (w);
if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
- abort ();
+ emacs_abort ();
if (BYTEPOS (opoint) < CHARPOS (opoint))
- abort ();
-
- /* If %c is in mode line, update it if needed. */
- if (!NILP (w->column_number_displayed)
- /* This alternative quickly identifies a common case
- where no change is needed. */
- && !(PT == w->last_point
- && w->last_modified >= MODIFF
- && w->last_overlay_modified >= OVERLAY_MODIFF)
- && (XFASTINT (w->column_number_displayed) != current_column ()))
- update_mode_line = 1;
+ emacs_abort ();
- /* Count number of windows showing the selected buffer. An indirect
- buffer counts as its base buffer. */
- if (!just_this_one_p)
- {
- struct buffer *current_base, *window_base;
- current_base = current_buffer;
- window_base = XBUFFER (XWINDOW (selected_window)->buffer);
- if (current_base->base_buffer)
- current_base = current_base->base_buffer;
- if (window_base->base_buffer)
- window_base = window_base->base_buffer;
- if (current_base == window_base)
- buffer_shared++;
- }
+ if (mode_line_update_needed (w))
+ update_mode_line = 1;
/* Point refers normally to the selected window. For any other
window, set up appropriate value. */
if (!EQ (window, selected_window))
{
- ptrdiff_t new_pt = XMARKER (w->pointm)->charpos;
+ ptrdiff_t new_pt = marker_position (w->pointm);
ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
if (new_pt < BEGV)
{
@@ -15664,6 +15701,35 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
Move it back to a fully-visible line. */
new_vpos = window_box_height (w);
}
+ else if (w->cursor.vpos >=0)
+ {
+ /* Some people insist on not letting point enter the scroll
+ margin, even though this part handles windows that didn't
+ scroll at all. */
+ struct frame *f = XFRAME (w->frame);
+ int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+ int pixel_margin = margin * FRAME_LINE_HEIGHT (f);
+ bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
+
+ /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
+ below, which finds the row to move point to, advances by
+ the Y coordinate of the _next_ row, see the definition of
+ MATRIX_ROW_BOTTOM_Y. */
+ if (w->cursor.vpos < margin + header_line)
+ new_vpos
+ = pixel_margin + (header_line
+ ? CURRENT_HEADER_LINE_HEIGHT (w)
+ : 0) + FRAME_LINE_HEIGHT (f);
+ else
+ {
+ int window_height = window_box_height (w);
+
+ if (header_line)
+ window_height += CURRENT_HEADER_LINE_HEIGHT (w);
+ if (w->cursor.y >= window_height - pixel_margin)
+ new_vpos = window_height - pixel_margin;
+ }
+ }
/* If we need to move point for either of the above reasons,
now actually do it. */
@@ -15687,8 +15753,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
/* If we are highlighting the region, then we just changed
the region, so redisplay to show it. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ())
{
clear_glyph_matrix (w->desired_matrix);
if (!try_window (window, startp, 0))
@@ -15719,7 +15784,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
goto try_to_scroll;
default:
- abort ();
+ emacs_abort ();
}
}
/* If current starting point was originally the beginning of a line
@@ -15757,8 +15822,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
&& (CHARPOS (startp) < ZV
/* Avoid starting at end of buffer. */
|| CHARPOS (startp) == BEGV
- || (w->last_modified >= MODIFF
- && w->last_overlay_modified >= OVERLAY_MODIFF)))
+ || !window_outdated (w)))
{
int d1, d2, d3, d4, d5, d6;
@@ -15882,7 +15946,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
break;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -16208,10 +16272,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
|| w->pseudo_window_p)))
{
update_begin (f);
- BLOCK_INPUT;
+ block_input ();
if (draw_window_fringes (w, 1))
x_draw_vertical_border (w);
- UNBLOCK_INPUT;
+ unblock_input ();
update_end (f);
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -16394,8 +16458,7 @@ try_window_reusing_current_matrix (struct window *w)
return 0;
/* Can't do this if region may have changed. */
- if ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ()
|| !NILP (w->region_showing)
|| !NILP (Vshow_trailing_whitespace))
return 0;
@@ -16748,28 +16811,33 @@ try_window_reusing_current_matrix (struct window *w)
}
if (row < bottom_row)
{
- struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
- struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
-
- /* Can't use this optimization with bidi-reordered glyph
- rows, unless cursor is already at point. */
+ /* Can't simply scan the row for point with
+ bidi-reordered glyph rows. Let set_cursor_from_row
+ figure out where to put the cursor, and if it fails,
+ give up. */
if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
{
- if (!(w->cursor.hpos >= 0
- && w->cursor.hpos < row->used[TEXT_AREA]
- && BUFFERP (glyph->object)
- && glyph->charpos == PT))
- return 0;
+ if (!set_cursor_from_row (w, row, w->current_matrix,
+ 0, 0, 0, 0))
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ return 0;
+ }
}
else
- for (; glyph < end
- && (!BUFFERP (glyph->object)
- || glyph->charpos < PT);
- glyph++)
- {
- w->cursor.hpos++;
- w->cursor.x += glyph->pixel_width;
- }
+ {
+ struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
+ struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
+
+ for (; glyph < end
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < PT);
+ glyph++)
+ {
+ w->cursor.hpos++;
+ w->cursor.x += glyph->pixel_width;
+ }
+ }
}
}
@@ -17222,8 +17290,7 @@ try_window_id (struct window *w)
/* Can't use this if highlighting a region because a cursor movement
will do more than just set the cursor. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ())
GIVE_UP (9);
/* Likewise if highlighting trailing whitespace. */
@@ -17330,7 +17397,7 @@ try_window_id (struct window *w)
if (row)
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
else
- abort ();
+ emacs_abort ();
return 1;
}
}
@@ -17374,7 +17441,7 @@ try_window_id (struct window *w)
if (row)
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
else
- abort ();
+ emacs_abort ();
return 2;
}
}
@@ -17863,7 +17930,7 @@ try_window_id (struct window *w)
IF_DEBUG (debug_method_add (w, "C"));
}
else
- abort ();
+ emacs_abort ();
IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
debug_end_vpos = XFASTINT (w->window_end_vpos));
@@ -18556,6 +18623,7 @@ append_space_for_newline (struct it *it, int default_face_p)
int saved_char_to_display = it->char_to_display;
int saved_x = it->current_x;
int saved_face_id = it->face_id;
+ int saved_box_end = it->end_of_box_run_p;
struct text_pos saved_pos;
Lisp_Object saved_object;
struct face *face;
@@ -18577,6 +18645,16 @@ append_space_for_newline (struct it *it, int default_face_p)
it->face_id = it->saved_face_id;
face = FACE_FROM_ID (it->f, it->face_id);
it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
+ /* In R2L rows, we will prepend a stretch glyph that will
+ have the end_of_box_run_p flag set for it, so there's no
+ need for the appended newline glyph to have that flag
+ set. */
+ if (it->glyph_row->reversed_p
+ /* But if the appended newline glyph goes all the way to
+ the end of the row, there will be no stretch glyph,
+ so leave the box flag set. */
+ && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
+ it->end_of_box_run_p = 0;
PRODUCE_GLYPHS (it);
@@ -18590,6 +18668,7 @@ append_space_for_newline (struct it *it, int default_face_p)
it->len = saved_len;
it->c = saved_c;
it->char_to_display = saved_char_to_display;
+ it->end_of_box_run_p = saved_box_end;
return 1;
}
}
@@ -18679,7 +18758,7 @@ extend_face_to_end_of_line (struct it *it)
struct glyph *g;
int row_width, stretch_ascent, stretch_width;
struct text_pos saved_pos;
- int saved_face_id, saved_avoid_cursor;
+ int saved_face_id, saved_avoid_cursor, saved_box_start;
for (row_width = 0, g = row_start; g < row_end; g++)
row_width += g->pixel_width;
@@ -18694,6 +18773,7 @@ extend_face_to_end_of_line (struct it *it)
saved_avoid_cursor = it->avoid_cursor_p;
it->avoid_cursor_p = 1;
saved_face_id = it->face_id;
+ saved_box_start = it->start_of_box_run_p;
/* The last row's stretch glyph should get the default
face, to avoid painting the rest of the window with
the region face, if the region ends at ZV. */
@@ -18701,11 +18781,13 @@ extend_face_to_end_of_line (struct it *it)
it->face_id = default_face->id;
else
it->face_id = face->id;
+ it->start_of_box_run_p = 0;
append_stretch_glyph (it, make_number (0), stretch_width,
it->ascent + it->descent, stretch_ascent);
it->position = saved_pos;
it->avoid_cursor_p = saved_avoid_cursor;
it->face_id = saved_face_id;
+ it->start_of_box_run_p = saved_box_start;
}
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -19240,7 +19322,7 @@ find_row_edges (struct it *it, struct glyph_row *row,
/* A line that is entirely from a string/image/stretch... */
row->maxpos = row->minpos;
else
- abort ();
+ emacs_abort ();
}
else
row->maxpos = it->current.pos;
@@ -20081,7 +20163,7 @@ See also `bidi-paragraph-direction'. */)
return Qright_to_left;
break;
default:
- abort ();
+ emacs_abort ();
}
}
}
@@ -20159,10 +20241,6 @@ display_menu_bar (struct window *w)
this. */
it.paragraph_embedding = L2R;
- if (! mode_line_inverse_video)
- /* Force the menu-bar to be displayed in the default face. */
- it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
/* Clear all rows of the menu bar. */
for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
{
@@ -20276,12 +20354,13 @@ redisplay_mode_lines (Lisp_Object window, int force)
static int
display_mode_lines (struct window *w)
{
- Lisp_Object old_selected_window, old_selected_frame;
+ Lisp_Object old_selected_window = selected_window;
+ Lisp_Object old_selected_frame = selected_frame;
+ Lisp_Object new_frame = w->frame;
+ Lisp_Object old_frame_selected_window = XFRAME (new_frame)->selected_window;
int n = 0;
- old_selected_frame = selected_frame;
selected_frame = w->frame;
- old_selected_window = selected_window;
XSETWINDOW (selected_window, w);
/* These will be set while the mode line specs are processed. */
@@ -20305,6 +20384,7 @@ display_mode_lines (struct window *w)
++n;
}
+ XFRAME (new_frame)->selected_window = old_frame_selected_window;
selected_frame = old_selected_frame;
selected_window = old_selected_window;
return n;
@@ -20332,10 +20412,6 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
it.glyph_row->mode_line_p = 1;
- if (! mode_line_inverse_video)
- /* Force the mode-line to be displayed in the default face. */
- it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
/* FIXME: This should be controlled by a user option. But
supporting such an option is not trivial, since the mode line is
made up of many separate strings. */
@@ -21010,10 +21086,8 @@ are the selected window and the WINDOW's buffer). */)
Lisp_Object str;
int string_start = 0;
- if (NILP (window))
- window = selected_window;
- CHECK_WINDOW (window);
- w = XWINDOW (window);
+ w = decode_any_window (window);
+ XSETWINDOW (window, w);
if (NILP (buffer))
buffer = w->buffer;
@@ -21036,20 +21110,18 @@ are the selected window and the WINDOW's buffer). */)
: EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
: DEFAULT_FACE_ID;
- if (XBUFFER (buffer) != current_buffer)
- old_buffer = current_buffer;
+ old_buffer = current_buffer;
/* Save things including mode_line_proptrans_alist,
and set that to nil so that we don't alter the outer value. */
record_unwind_protect (unwind_format_mode_line,
format_mode_line_unwind_data
- (XFRAME (WINDOW_FRAME (XWINDOW (window))),
+ (XFRAME (WINDOW_FRAME (w)),
old_buffer, selected_window, 1));
mode_line_proptrans_alist = Qnil;
Fselect_window (window, Qt);
- if (old_buffer)
- set_buffer_internal_1 (XBUFFER (buffer));
+ set_buffer_internal_1 (XBUFFER (buffer));
init_iterator (&it, w, -1, -1, NULL, face_id);
@@ -21328,6 +21400,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
Lisp_Object obj;
struct frame *f = XFRAME (WINDOW_FRAME (w));
char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
+ /* We are going to use f->decode_mode_spec_buffer as the buffer to
+ produce strings from numerical values, so limit preposterously
+ large values of FIELD_WIDTH to avoid overrunning the buffer's
+ end. The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE
+ bytes plus the terminating null. */
+ int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
struct buffer *b = current_buffer;
obj = Qnil;
@@ -21392,8 +21470,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
register int i;
/* Let lots_of_dashes be a string of infinite length. */
- if (mode_line_target == MODE_LINE_NOPROP ||
- mode_line_target == MODE_LINE_STRING)
+ if (mode_line_target == MODE_LINE_NOPROP
+ || mode_line_target == MODE_LINE_STRING)
return "--";
if (field_width <= 0
|| field_width > sizeof (lots_of_dashes))
@@ -21423,7 +21501,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
{
ptrdiff_t col = current_column ();
wset_column_number_displayed (w, make_number (col));
- pint2str (decode_mode_spec_buf, field_width, col);
+ pint2str (decode_mode_spec_buf, width, col);
return decode_mode_spec_buf;
}
@@ -21454,14 +21532,14 @@ decode_mode_spec (struct window *w, register int c, int field_width,
case 'i':
{
ptrdiff_t size = ZV - BEGV;
- pint2str (decode_mode_spec_buf, field_width, size);
+ pint2str (decode_mode_spec_buf, width, size);
return decode_mode_spec_buf;
}
case 'I':
{
ptrdiff_t size = ZV - BEGV;
- pint2hrstr (decode_mode_spec_buf, field_width, size);
+ pint2hrstr (decode_mode_spec_buf, width, size);
return decode_mode_spec_buf;
}
@@ -21475,7 +21553,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
if (mode_line_target == MODE_LINE_TITLE)
return "";
- startpos = XMARKER (w->start)->charpos;
+ startpos = marker_position (w->start);
startpos_byte = marker_byte_position (w->start);
height = WINDOW_TOTAL_LINES (w);
@@ -21568,12 +21646,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
line_number_displayed = 1;
/* Make the string to show. */
- pint2str (decode_mode_spec_buf, field_width, topline + nlines);
+ pint2str (decode_mode_spec_buf, width, topline + nlines);
return decode_mode_spec_buf;
no_value:
{
char* p = decode_mode_spec_buf;
- int pad = field_width - 2;
+ int pad = width - 2;
while (pad-- > 0)
*p++ = ' ';
*p++ = '?';
@@ -21994,7 +22072,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
{
/* Glyph is off the left margin of the display area.
Should not happen. */
- abort ();
+ emacs_abort ();
}
row->ascent = max (row->ascent, it->max_ascent);
@@ -22487,7 +22565,7 @@ init_glyph_string (struct glyph_string *s,
/* Append the list of glyph strings with head H and tail T to the list
with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
-static inline void
+static void
append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
struct glyph_string *h, struct glyph_string *t)
{
@@ -22507,7 +22585,7 @@ append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tai
list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
result. */
-static inline void
+static void
prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
struct glyph_string *h, struct glyph_string *t)
{
@@ -22526,7 +22604,7 @@ prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **ta
/* Append glyph string S to the list with head *HEAD and tail *TAIL.
Set *HEAD and *TAIL to the resulting list. */
-static inline void
+static void
append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
struct glyph_string *s)
{
@@ -22541,7 +22619,7 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
Value is a pointer to a realized face that is ready for display if
DISPLAY_P is non-zero. */
-static inline struct face *
+static struct face *
get_char_face_and_encoding (struct frame *f, int c, int face_id,
XChar2b *char2b, int display_p)
{
@@ -22574,7 +22652,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
a pointer to a realized face that is ready for display. */
-static inline struct face *
+static struct face *
get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
XChar2b *char2b, int *two_byte_p)
{
@@ -22611,7 +22689,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
/* Get glyph code of character C in FONT in the two-byte form CHAR2B.
Return 1 if FONT has a glyph for C, otherwise return 0. */
-static inline int
+static int
get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
{
unsigned code;
@@ -23039,7 +23117,8 @@ right_overwritten (struct glyph_string *s)
{
int x = 0, i;
struct glyph *glyphs = s->row->glyphs[s->area];
- int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+ int first = (s->first_glyph - glyphs
+ + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
int end = s->row->used[s->area];
for (i = first; i < end && s->right_overhang > x; ++i)
@@ -23062,7 +23141,8 @@ right_overwriting (struct glyph_string *s)
int i, k, x;
int end = s->row->used[s->area];
struct glyph *glyphs = s->row->glyphs[s->area];
- int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+ int first = (s->first_glyph - glyphs
+ + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
k = -1;
x = 0;
@@ -23083,7 +23163,7 @@ right_overwriting (struct glyph_string *s)
first glyph following S. LAST_X is the right-most x-position + 1
in the drawing area. */
-static inline void
+static void
set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
{
/* If the face of this glyph string has to be drawn to the end of
@@ -23359,7 +23439,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
break; \
\
default: \
- abort (); \
+ emacs_abort (); \
} \
\
if (s) \
@@ -23409,8 +23489,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
/* Let's rather be paranoid than getting a SEGV. */
end = min (end, row->used[area]);
- start = max (0, start);
- start = min (end, start);
+ start = clip_to_bounds (0, start, end);
/* Translate X to frame coordinates. Set last_x to the right
end of the drawing area. */
@@ -23452,7 +23531,9 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
/* If mouse highlighting is on, we may need to draw adjacent
glyphs using mouse-face highlighting. */
- if (area == TEXT_AREA && row->mouse_face_p)
+ if (area == TEXT_AREA && row->mouse_face_p
+ && hlinfo->mouse_face_beg_row >= 0
+ && hlinfo->mouse_face_end_row >= 0)
{
struct glyph_row *mouse_beg_row, *mouse_end_row;
@@ -23644,7 +23725,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
/* Store one glyph for IT->char_to_display in IT->glyph_row.
Called from x_produce_glyphs when IT->glyph_row is non-null. */
-static inline void
+static void
append_glyph (struct it *it)
{
struct glyph *glyph;
@@ -23687,8 +23768,18 @@ append_glyph (struct it *it)
glyph->type = CHAR_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->glyph_not_available_p = it->glyph_not_available_p;
@@ -23700,7 +23791,7 @@ append_glyph (struct it *it)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
@@ -23718,7 +23809,7 @@ append_glyph (struct it *it)
IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is
non-null. */
-static inline void
+static void
append_composite_glyph (struct it *it)
{
struct glyph *glyph;
@@ -23762,8 +23853,18 @@ append_composite_glyph (struct it *it)
}
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
@@ -23774,7 +23875,7 @@ append_composite_glyph (struct it *it)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
@@ -23787,7 +23888,7 @@ append_composite_glyph (struct it *it)
/* Change IT->ascent and IT->height according to the setting of
IT->voffset. */
-static inline void
+static void
take_vertical_position_into_account (struct it *it)
{
if (it->voffset)
@@ -23940,8 +24041,18 @@ produce_image_glyph (struct it *it)
glyph->type = IMAGE_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
@@ -23953,7 +24064,7 @@ produce_image_glyph (struct it *it)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
@@ -24000,8 +24111,18 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
glyph->type = STRETCH_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
@@ -24014,7 +24135,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
@@ -24068,17 +24189,16 @@ produce_stretch_glyph (struct it *it)
Lisp_Object prop, plist;
int width = 0, height = 0, align_to = -1;
int zero_width_ok_p = 0;
- int ascent = 0;
double tem;
- struct face *face = NULL;
struct font *font = NULL;
#ifdef HAVE_WINDOW_SYSTEM
+ int ascent = 0;
int zero_height_ok_p = 0;
if (FRAME_WINDOW_P (it->f))
{
- face = FACE_FROM_ID (it->f, it->face_id);
+ 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);
}
@@ -24269,7 +24389,7 @@ produce_special_glyphs (struct it *it, enum display_element_type what)
}
}
else
- abort ();
+ emacs_abort ();
#ifdef HAVE_WINDOW_SYSTEM
/* On a GUI frame, when the right fringe (left fringe for R2L rows)
@@ -24454,8 +24574,18 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
glyph->slice.glyphless.lower_yoff = lower_yoff;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
@@ -24466,7 +24596,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
@@ -25325,7 +25455,7 @@ x_write_glyphs (struct glyph *start, int len)
if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
chpos = updated_row->used[TEXT_AREA] - 1;
- BLOCK_INPUT;
+ block_input ();
/* Write glyphs. */
@@ -25343,7 +25473,7 @@ x_write_glyphs (struct glyph *start, int len)
&& chpos < hpos + len)
updated_window->phys_cursor_on_p = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
/* Advance the output cursor. */
output_cursor.hpos += len;
@@ -25366,7 +25496,7 @@ x_insert_glyphs (struct glyph *start, int len)
ptrdiff_t hpos;
eassert (updated_window && updated_row);
- BLOCK_INPUT;
+ block_input ();
w = updated_window;
f = XFRAME (WINDOW_FRAME (w));
@@ -25400,7 +25530,7 @@ x_insert_glyphs (struct glyph *start, int len)
/* Advance the output cursor. */
output_cursor.hpos += len;
output_cursor.x += shift_by_width;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -25469,10 +25599,10 @@ x_clear_end_of_line (int to_x)
/* Prevent inadvertently clearing to end of the X window. */
if (to_x > from_x && to_y > from_y)
{
- BLOCK_INPUT;
+ block_input ();
FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
to_x - from_x, to_y - from_y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -25799,7 +25929,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
{
int i, x;
- BLOCK_INPUT;
+ block_input ();
x = 0;
for (i = 0; i < row->used[area];)
@@ -25827,7 +25957,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -26045,7 +26175,7 @@ display_and_set_cursor (struct window *w, int on,
|| (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
/* Set new_cursor_type to the cursor we want to be displayed. */
new_cursor_type = get_window_cursor_type (w, glyph,
@@ -26115,10 +26245,10 @@ update_window_cursor (struct window *w, int on)
if (row->reversed_p && hpos >= row->used[TEXT_AREA])
hpos = row->used[TEXT_AREA] - 1;
- BLOCK_INPUT;
+ block_input ();
display_and_set_cursor (w, on, hpos, vpos,
w->phys_cursor.x, w->phys_cursor.y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -26296,10 +26426,10 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
if (row->reversed_p && hpos >= row->used[TEXT_AREA])
hpos = row->used[TEXT_AREA] - 1;
- BLOCK_INPUT;
+ block_input ();
display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos,
w->phys_cursor.x, w->phys_cursor.y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* HAVE_WINDOW_SYSTEM */
}
@@ -27632,12 +27762,6 @@ note_mouse_highlight (struct frame *f, int x, int y)
if (hlinfo->mouse_face_defer)
return;
- if (gc_in_progress)
- {
- hlinfo->mouse_face_deferred_gc = 1;
- return;
- }
-
/* Which window is that in? */
window = window_from_coordinates (f, x, y, &part, 1);
@@ -28114,11 +28238,11 @@ x_clear_window_mouse_face (struct window *w)
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
Lisp_Object window;
- BLOCK_INPUT;
+ block_input ();
XSETWINDOW (window, w);
if (EQ (window, hlinfo->mouse_face_window))
clear_mouse_face (hlinfo);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -28688,6 +28812,7 @@ syms_of_xdisp (void)
staticpro (&Vmessage_stack);
DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
+ DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
message_dolog_marker1 = Fmake_marker ();
staticpro (&message_dolog_marker1);
@@ -28927,12 +29052,6 @@ A value of nil means to respect the value of `truncate-lines'.
If `word-wrap' is enabled, you might want to reduce this. */);
Vtruncate_partial_width_windows = make_number (50);
- DEFVAR_BOOL ("mode-line-inverse-video", mode_line_inverse_video,
- doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
-Any other value means to use the appropriate face, `mode-line',
-`header-line', or `menu' respectively. */);
- mode_line_inverse_video = 1;
-
DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
doc: /* Maximum buffer size for which line number should be displayed.
If the buffer is bigger than this, the line number does not appear
@@ -28985,7 +29104,7 @@ and is used only on frames for which no explicit name has been set
doc: /* Maximum number of lines to keep in the message log buffer.
If nil, disable message logging. If t, log messages but don't truncate
the buffer when it becomes large. */);
- Vmessage_log_max = make_number (100);
+ Vmessage_log_max = make_number (1000);
DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
doc: /* Functions called before redisplay, if window sizes have changed.
@@ -29299,6 +29418,10 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or
Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
Qempty_box);
+
+ DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
+ doc: /* If non-nil, debug if a message matching this regexp is displayed. */);
+ Vdebug_on_message = Qnil;
}
@@ -29352,11 +29475,7 @@ init_xdisp (void)
help_echo_showing_p = 0;
}
-/* Since w32 does not support atimers, it defines its own implementation of
- the following three functions in w32fns.c. */
-#ifndef WINDOWSNT
-
-/* Platform-independent portion of hourglass implementation. */
+/* Platform-independent portion of hourglass implementation. */
/* Cancel a currently active hourglass timer, and start a new one. */
void
@@ -29378,6 +29497,13 @@ start_hourglass (void)
else
delay = make_emacs_time (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);
#endif
@@ -29400,4 +29526,3 @@ cancel_hourglass (void)
hide_hourglass ();
#endif
}
-#endif /* ! WINDOWSNT */
diff --git a/src/xfaces.c b/src/xfaces.c
index 4df5caf6f2a..1e27d5cc043 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -204,7 +204,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h> /* This needs to be before termchar.h */
-#include <setjmp.h>
#include "lisp.h"
#include "character.h"
@@ -228,13 +227,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
#include "fontset.h"
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
#undef FRAME_X_DISPLAY_INFO
#define FRAME_X_DISPLAY_INFO FRAME_W32_DISPLAY_INFO
#define x_display_info w32_display_info
#define check_x check_w32
#define GCGraphicsExposures 0
-#endif /* WINDOWSNT */
+#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
#undef FRAME_X_DISPLAY_INFO
@@ -315,16 +314,10 @@ static Lisp_Object QCfontset;
Lisp_Object Qnormal;
Lisp_Object Qbold;
static Lisp_Object Qline, Qwave;
-static Lisp_Object Qultra_light, Qreverse_oblique, Qreverse_italic;
Lisp_Object Qextra_light, Qlight;
Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold;
Lisp_Object Qoblique;
Lisp_Object Qitalic;
-static Lisp_Object Qultra_condensed, Qextra_condensed;
-Lisp_Object Qcondensed;
-static Lisp_Object Qsemi_condensed, Qsemi_expanded, Qextra_expanded;
-Lisp_Object Qexpanded;
-static Lisp_Object Qultra_expanded;
static Lisp_Object Qreleased_button, Qpressed_button;
static Lisp_Object QCstyle, QCcolor, QCline_width;
Lisp_Object Qunspecified; /* used in dosfns.c */
@@ -372,8 +365,6 @@ Lisp_Object Vface_alternative_font_registry_alist;
static Lisp_Object Qscalable_fonts_allowed;
-#define DEFAULT_FONT_LIST_LIMIT 100
-
/* 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. */
@@ -510,7 +501,7 @@ unregister_color (unsigned long pixel)
if (color_count[pixel] > 0)
--color_count[pixel];
else
- abort ();
+ emacs_abort ();
}
@@ -602,13 +593,13 @@ x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap,
/* Create and return a GC for use on frame F. GC values and mask
are given by XGCV and MASK. */
-static inline GC
+static GC
x_create_gc (struct frame *f, long unsigned int mask, XGCValues *xgcv)
{
GC gc;
- BLOCK_INPUT;
+ block_input ();
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv);
- UNBLOCK_INPUT;
+ unblock_input ();
IF_DEBUG (++ngcs);
return gc;
}
@@ -616,26 +607,26 @@ x_create_gc (struct frame *f, long unsigned int mask, XGCValues *xgcv)
/* Free GC which was used on frame F. */
-static inline void
+static void
x_free_gc (struct frame *f, GC gc)
{
- eassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
IF_DEBUG (eassert (--ngcs >= 0));
XFreeGC (FRAME_X_DISPLAY (f), gc);
}
#endif /* HAVE_X_WINDOWS */
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
/* W32 emulation of GCs */
-static inline GC
+static GC
x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
{
GC gc;
- BLOCK_INPUT;
+ block_input ();
gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, xgcv);
- UNBLOCK_INPUT;
+ unblock_input ();
IF_DEBUG (++ngcs);
return gc;
}
@@ -643,52 +634,35 @@ x_create_gc (struct frame *f, unsigned long mask, XGCValues *xgcv)
/* Free GC which was used on frame F. */
-static inline void
+static void
x_free_gc (struct frame *f, GC gc)
{
IF_DEBUG (eassert (--ngcs >= 0));
xfree (gc);
}
-#endif /* WINDOWSNT */
+#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
/* NS emulation of GCs */
-static inline GC
+static GC
x_create_gc (struct frame *f,
unsigned long mask,
XGCValues *xgcv)
{
GC gc = xmalloc (sizeof *gc);
- memcpy (gc, xgcv, sizeof (XGCValues));
+ *gc = *xgcv;
return gc;
}
-static inline void
+static void
x_free_gc (struct frame *f, GC gc)
{
xfree (gc);
}
#endif /* HAVE_NS */
-/* If FRAME is nil, return a pointer to the selected frame.
- Otherwise, check that FRAME is a live frame, and return a pointer
- to it. NPARAM is the parameter number of FRAME, for
- CHECK_LIVE_FRAME. This is here because it's a frequent pattern in
- Lisp function definitions. */
-
-static inline struct frame *
-frame_or_selected_frame (Lisp_Object frame, int nparam)
-{
- if (NILP (frame))
- frame = selected_frame;
-
- CHECK_LIVE_FRAME (frame);
- return XFRAME (frame);
-}
-
-
/***********************************************************************
Frames and faces
***********************************************************************/
@@ -720,14 +694,14 @@ init_frame_faces (struct frame *f)
#ifdef HAVE_X_WINDOWS
if (!FRAME_X_P (f) || FRAME_X_WINDOW (f))
#endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
if (!FRAME_WINDOW_P (f) || FRAME_W32_WINDOW (f))
#endif
#ifdef HAVE_NS
if (!FRAME_NS_P (f) || FRAME_NS_WINDOW (f))
#endif
if (!realize_basic_faces (f))
- abort ();
+ emacs_abort ();
}
@@ -771,7 +745,7 @@ recompute_basic_faces (struct frame *f)
{
clear_face_cache (0);
if (!realize_basic_faces (f))
- abort ();
+ emacs_abort ();
}
}
@@ -908,7 +882,7 @@ load_pixmap (FRAME_PTR f, Lisp_Object name, unsigned int *w_ptr,
CHECK_TYPE (!NILP (Fbitmap_spec_p (name)), Qbitmap_spec_p, name);
- BLOCK_INPUT;
+ block_input ();
if (CONSP (name))
{
/* Decode a bitmap spec into a bitmap. */
@@ -928,7 +902,7 @@ load_pixmap (FRAME_PTR f, Lisp_Object name, unsigned int *w_ptr,
/* It must be a string -- a file name. */
bitmap_id = x_create_bitmap_from_file (f, name);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (bitmap_id < 0)
{
@@ -992,7 +966,7 @@ parse_rgb_list (Lisp_Object rgb_list, XColor *color)
non-zero, then the `standard' definition of the same color is
returned in it. */
-static int
+static bool
tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
XColor *std_color)
{
@@ -1053,11 +1027,11 @@ tty_lookup_color (struct frame *f, Lisp_Object color, XColor *tty_color,
/* A version of defined_color for non-X frames. */
-static int
+static bool
tty_defined_color (struct frame *f, const char *color_name,
- XColor *color_def, int alloc)
+ XColor *color_def, bool alloc)
{
- int status = 1;
+ bool status = 1;
/* Defaults. */
color_def->pixel = FACE_TTY_DEFAULT_COLOR;
@@ -1085,13 +1059,13 @@ tty_defined_color (struct frame *f, const char *color_name,
/* Decide if color named COLOR_NAME is valid for the display
associated with the frame F; if so, return the rgb values in
- COLOR_DEF. If ALLOC is nonzero, allocate a new colormap cell.
+ COLOR_DEF. If ALLOC, allocate a new colormap cell.
This does the right thing for any type of frame. */
-static int
+static bool
defined_color (struct frame *f, const char *color_name, XColor *color_def,
- int alloc)
+ bool alloc)
{
if (!FRAME_WINDOW_P (f))
return tty_defined_color (f, color_name, color_def, alloc);
@@ -1099,7 +1073,7 @@ defined_color (struct frame *f, const char *color_name, XColor *color_def,
else if (FRAME_X_P (f))
return x_defined_color (f, color_name, color_def, alloc);
#endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
else if (FRAME_W32_P (f))
return w32_defined_color (f, color_name, color_def, alloc);
#endif
@@ -1108,7 +1082,7 @@ defined_color (struct frame *f, const char *color_name, XColor *color_def,
return ns_defined_color (f, color_name, color_def, alloc, 1);
#endif
else
- abort ();
+ emacs_abort ();
}
@@ -1207,15 +1181,9 @@ FRAME specifies the frame and thus the display for interpreting COLOR.
If FRAME is nil or omitted, use the selected frame. */)
(Lisp_Object color, Lisp_Object frame)
{
- struct frame *f;
-
CHECK_STRING (color);
- if (NILP (frame))
- frame = selected_frame;
- else
- CHECK_FRAME (frame);
- f = XFRAME (frame);
- return face_color_gray_p (f, SSDATA (color)) ? Qt : Qnil;
+ return (face_color_gray_p (decode_any_frame (frame), SSDATA (color))
+ ? Qt : Qnil);
}
@@ -1228,17 +1196,10 @@ If FRAME is nil or omitted, use the selected frame.
COLOR must be a valid color name. */)
(Lisp_Object color, Lisp_Object frame, Lisp_Object background_p)
{
- struct frame *f;
-
CHECK_STRING (color);
- if (NILP (frame))
- frame = selected_frame;
- else
- CHECK_FRAME (frame);
- f = XFRAME (frame);
- if (face_color_supported_p (f, SSDATA (color), !NILP (background_p)))
- return Qt;
- return Qnil;
+ return (face_color_supported_p (decode_any_frame (frame),
+ SSDATA (color), !NILP (background_p))
+ ? Qt : Qnil);
}
@@ -1304,7 +1265,7 @@ load_color (struct frame *f, struct face *face, Lisp_Object name,
break;
default:
- abort ();
+ emacs_abort ();
}
}
#ifdef GLYPH_DEBUG
@@ -1324,7 +1285,8 @@ load_color (struct frame *f, struct face *face, Lisp_Object name,
try to emulate gray colors with a stipple from Vface_default_stipple. */
static void
-load_face_colors (struct frame *f, struct face *face, Lisp_Object *attrs)
+load_face_colors (struct frame *f, struct face *face,
+ Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
Lisp_Object fg, bg;
@@ -1365,9 +1327,9 @@ unload_color (struct frame *f, long unsigned int pixel)
#ifdef HAVE_X_WINDOWS
if (pixel != -1)
{
- BLOCK_INPUT;
+ block_input ();
x_free_colors (f, &pixel, 1);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
}
@@ -1383,7 +1345,7 @@ free_face_colors (struct frame *f, struct face *face)
if (face->colors_copied_bitwise_p)
return;
- BLOCK_INPUT;
+ block_input ();
if (!face->foreground_defaulted_p)
{
@@ -1425,7 +1387,7 @@ free_face_colors (struct frame *f, struct face *face)
IF_DEBUG (--ncolors_allocated);
}
- UNBLOCK_INPUT;
+ unblock_input ();
#endif /* HAVE_X_WINDOWS */
}
@@ -1685,9 +1647,7 @@ the WIDTH times as wide as FACE on FRAME. */)
/* We can't simply call check_x_frame because this function may be
called before any frame is created. */
- if (NILP (frame))
- frame = selected_frame;
- f = frame_or_selected_frame (frame, 2);
+ f = decode_live_frame (frame);
if (! FRAME_WINDOW_P (f))
{
/* Perhaps we have not yet created any frame. */
@@ -1695,6 +1655,8 @@ the WIDTH times as wide as FACE on FRAME. */)
frame = Qnil;
face = Qnil;
}
+ else
+ XSETFRAME (frame, f);
/* Determine the width standard for comparison with the fonts we find. */
@@ -1803,7 +1765,7 @@ the WIDTH times as wide as FACE on FRAME. */)
/* Check consistency of Lisp face attribute vector ATTRS. */
static void
-check_lface_attrs (Lisp_Object *attrs)
+check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
@@ -1921,7 +1883,7 @@ struct named_merge_point
FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
pointed to by NAMED_MERGE_POINTS, and return 1. */
-static inline int
+static int
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,
@@ -2005,7 +1967,7 @@ resolve_face_name (Lisp_Object face_name, int signal_p)
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. */
-static inline Lisp_Object
+static Lisp_Object
lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
int signal_p)
{
@@ -2034,7 +1996,7 @@ lface_from_face_name_no_resolve (struct frame *f, Lisp_Object face_name,
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. */
-static inline Lisp_Object
+static Lisp_Object
lface_from_face_name (struct frame *f, Lisp_Object face_name, int signal_p)
{
face_name = resolve_face_name (face_name, signal_p);
@@ -2048,9 +2010,10 @@ lface_from_face_name (struct frame *f, Lisp_Object face_name, int 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. */
-static inline int
+static int
get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
- Lisp_Object *attrs, int signal_p)
+ Lisp_Object attrs[LFACE_VECTOR_SIZE],
+ int signal_p)
{
Lisp_Object lface;
@@ -2070,9 +2033,9 @@ get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
non-zero, signal an error if FACE_NAME does not name a face.
Otherwise, value is zero if FACE_NAME is not a face. */
-static inline int
+static int
get_lface_attributes (struct frame *f, Lisp_Object face_name,
- Lisp_Object *attrs, int signal_p,
+ Lisp_Object attrs[LFACE_VECTOR_SIZE], int signal_p,
struct named_merge_point *named_merge_points)
{
Lisp_Object face_remapping;
@@ -2109,7 +2072,7 @@ get_lface_attributes (struct frame *f, Lisp_Object face_name,
specified, i.e. are non-nil. */
static int
-lface_fully_specified_p (Lisp_Object *attrs)
+lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
int i;
@@ -2235,7 +2198,7 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
loops in face inheritance/remapping; it should be 0 when called from
other places. */
-static inline void
+static void
merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
struct named_merge_point *named_merge_points)
{
@@ -2907,6 +2870,12 @@ FRAME 0 means change the face on all frames, and change the default
Lisp_Object key, val, list;
list = value;
+ /* FIXME? This errs on the side of acceptance. Eg it accepts:
+ (defface foo '((t :underline 'foo) "doc")
+ Maybe this is intentional, maybe it isn't.
+ Non-nil symbols other than t are not documented as being valid.
+ Eg compare with inverse-video, which explicitly rejects them.
+ */
valid_p = 1;
while (!NILP (CAR_SAFE(list)))
@@ -3246,7 +3215,7 @@ FRAME 0 means change the face on all frames, and change the default
param = Qbackground_color;
}
#ifdef HAVE_WINDOW_SYSTEM
-#ifndef WINDOWSNT
+#ifndef HAVE_NTGUI
else if (EQ (face, Qscroll_bar))
{
/* Changing the colors of `scroll-bar' sets frame parameters
@@ -3256,7 +3225,7 @@ FRAME 0 means change the face on all frames, and change the default
else if (EQ (attr, QCbackground))
param = Qscroll_bar_background;
}
-#endif /* not WINDOWSNT */
+#endif /* not HAVE_NTGUI */
else if (EQ (face, Qborder))
{
/* Changing background color of `border' sets frame parameter
@@ -3439,10 +3408,10 @@ DEFUN ("internal-face-x-get-resource", Finternal_face_x_get_resource,
CHECK_STRING (resource);
CHECK_STRING (class);
CHECK_LIVE_FRAME (frame);
- BLOCK_INPUT;
+ block_input ();
value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
resource, class, Qnil, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
return value;
}
@@ -3680,21 +3649,12 @@ frame. If FRAME is t, report on the defaults for face SYMBOL (for new
frames). If FRAME is omitted or nil, use the selected frame. */)
(Lisp_Object symbol, Lisp_Object keyword, Lisp_Object frame)
{
- Lisp_Object lface, value = Qnil;
+ struct frame *f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
+ Lisp_Object lface = lface_from_face_name (f, symbol, 1), value = Qnil;
CHECK_SYMBOL (symbol);
CHECK_SYMBOL (keyword);
- if (EQ (frame, Qt))
- lface = lface_from_face_name (NULL, symbol, 1);
- else
- {
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- lface = lface_from_face_name (XFRAME (frame), symbol, 1);
- }
-
if (EQ (keyword, QCfamily))
value = LFACE_FAMILY (lface);
else if (EQ (keyword, QCfoundry))
@@ -3877,7 +3837,7 @@ return the font name used for CHARACTER. */)
}
else
{
- struct frame *f = frame_or_selected_frame (frame, 1);
+ struct frame *f = decode_live_frame (frame);
int face_id = lookup_named_face (f, face, 1);
struct face *fface = FACE_FROM_ID (f, face_id);
@@ -3907,7 +3867,7 @@ return the font name used for CHARACTER. */)
all attributes are `equal'. Tries to be fast because this function
is called quite often. */
-static inline int
+static int
face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
{
/* Type can differ, e.g. when one attribute is unspecified, i.e. nil,
@@ -3940,7 +3900,7 @@ face_attr_equal_p (Lisp_Object v1, Lisp_Object v2)
all attributes are `equal'. Tries to be fast because this function
is called quite often. */
-static inline int
+static int
lface_equal_p (Lisp_Object *v1, Lisp_Object *v2)
{
int i, equal_p = 1;
@@ -3964,14 +3924,11 @@ If FRAME is omitted or nil, use the selected frame. */)
struct frame *f;
Lisp_Object lface1, lface2;
- if (EQ (frame, Qt))
- f = NULL;
- else
- /* Don't use check_x_frame here because this function is called
- before X frames exist. At that time, if FRAME is nil,
- selected_frame will be used which is the frame dumped with
- Emacs. That frame is not an X frame. */
- f = frame_or_selected_frame (frame, 2);
+ /* Don't use check_x_frame here because this function is called
+ before X frames exist. At that time, if FRAME is nil,
+ selected_frame will be used which is the frame dumped with
+ 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);
@@ -3989,20 +3946,10 @@ If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame. */)
(Lisp_Object face, Lisp_Object frame)
{
- struct frame *f;
- Lisp_Object lface;
+ struct frame *f = EQ (frame, Qt) ? NULL : decode_live_frame (frame);
+ Lisp_Object lface = lface_from_face_name (f, face, 1);
int i;
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
-
- if (EQ (frame, Qt))
- lface = lface_from_face_name (NULL, face, 1);
- else
- lface = lface_from_face_name (f, face, 1);
-
for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
if (!UNSPECIFIEDP (AREF (lface, i)))
break;
@@ -4017,15 +3964,14 @@ DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist,
For internal use only. */)
(Lisp_Object frame)
{
- struct frame *f = frame_or_selected_frame (frame, 0);
- return f->face_alist;
+ return decode_live_frame (frame)->face_alist;
}
/* Return a hash code for Lisp string STRING with case ignored. Used
below in computing a hash value for a Lisp face. */
-static inline unsigned
+static unsigned
hash_string_case_insensitive (Lisp_Object string)
{
const unsigned char *s;
@@ -4039,7 +3985,7 @@ hash_string_case_insensitive (Lisp_Object string)
/* Return a hash code for face attribute vector V. */
-static inline unsigned
+static unsigned
lface_hash (Lisp_Object *v)
{
return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
@@ -4058,7 +4004,7 @@ lface_hash (Lisp_Object *v)
family, point size, weight, width, slant, and font. Both
LFACE1 and LFACE2 must be fully-specified. */
-static inline int
+static int
lface_same_font_attributes_p (Lisp_Object *lface1, Lisp_Object *lface2)
{
eassert (lface_fully_specified_p (lface1)
@@ -4115,12 +4061,12 @@ free_realized_face (struct frame *f, struct face *face)
free_face_fontset (f, face);
if (face->gc)
{
- BLOCK_INPUT;
+ block_input ();
if (face->font)
font_done_for_face (f, face);
x_free_gc (f, face->gc);
face->gc = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
free_face_colors (f, face);
@@ -4154,7 +4100,7 @@ prepare_face_for_display (struct frame *f, struct face *face)
xgcv.graphics_exposures = False;
#endif
- BLOCK_INPUT;
+ block_input ();
#ifdef HAVE_X_WINDOWS
if (face->stipple)
{
@@ -4166,7 +4112,7 @@ prepare_face_for_display (struct frame *f, struct face *face)
face->gc = x_create_gc (f, mask, &xgcv);
if (face->font)
font_prepare_for_face (f, face);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* HAVE_WINDOW_SYSTEM */
}
@@ -4206,14 +4152,9 @@ or lists of the form (RED GREEN BLUE).
If FRAME is unspecified or nil, the current frame is used. */)
(Lisp_Object color1, Lisp_Object color2, Lisp_Object frame)
{
- struct frame *f;
+ struct frame *f = decode_live_frame (frame);
XColor cdef1, cdef2;
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
-
if (!(CONSP (color1) && parse_rgb_list (color1, &cdef1))
&& !(STRINGP (color1) && defined_color (f, SSDATA (color1), &cdef1, 0)))
signal_error ("Invalid color", color1);
@@ -4264,12 +4205,12 @@ clear_face_gcs (struct face_cache *c)
struct face *face = c->faces_by_id[i];
if (face && face->gc)
{
- BLOCK_INPUT;
+ block_input ();
if (face->font)
font_done_for_face (c->f, face);
x_free_gc (c->f, face->gc);
face->gc = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -4293,7 +4234,7 @@ free_realized_faces (struct face_cache *c)
/* We must block input here because we can't process X events
safely while only some faces are freed, or when the frame's
current matrix still references freed faces. */
- BLOCK_INPUT;
+ block_input ();
for (i = 0; i < c->used; ++i)
{
@@ -4315,7 +4256,7 @@ free_realized_faces (struct face_cache *c)
++windows_or_buffers_changed;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -4454,7 +4395,7 @@ uncache_face (struct face_cache *c, struct face *face)
Value is the ID of the face found. If no suitable face is found,
realize a new one. */
-static inline int
+static int
lookup_face (struct frame *f, Lisp_Object *attr)
{
struct face_cache *cache = FRAME_FACE_CACHE (f);
@@ -4548,7 +4489,7 @@ lookup_named_face (struct frame *f, Lisp_Object symbol, int signal_p)
return -1;
default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
if (default_face == NULL)
- abort (); /* realize_basic_faces must have set it up */
+ emacs_abort (); /* realize_basic_faces must have set it up */
}
if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
@@ -4591,7 +4532,7 @@ lookup_basic_face (struct frame *f, int face_id)
case MENU_FACE_ID: name = Qmenu; break;
default:
- abort (); /* the caller is supposed to pass us a basic face id */
+ emacs_abort (); /* the caller is supposed to pass us a basic face id */
}
/* Do a quick scan through Vface_remapping_alist, and return immediately
@@ -4712,7 +4653,7 @@ lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id,
struct face *default_face = FACE_FROM_ID (f, face_id);
if (!default_face)
- abort ();
+ emacs_abort ();
if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
return -1;
@@ -4761,7 +4702,8 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
\(2) `close in spirit' to what the attributes specify, if not exact. */
static int
-x_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
+x_supports_face_attributes_p (struct frame *f,
+ Lisp_Object attrs[LFACE_VECTOR_SIZE],
struct face *def_face)
{
Lisp_Object *def_attrs = def_face->lface;
@@ -4863,7 +4805,8 @@ x_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
substitution of a `dim' face for italic. */
static int
-tty_supports_face_attributes_p (struct frame *f, Lisp_Object *attrs,
+tty_supports_face_attributes_p (struct frame *f,
+ Lisp_Object attrs[LFACE_VECTOR_SIZE],
struct face *def_face)
{
int weight, slant;
@@ -5075,17 +5018,14 @@ face for italic. */)
else
{
/* Find any frame on DISPLAY. */
- Lisp_Object fl_tail;
+ Lisp_Object tail;
frame = Qnil;
- for (fl_tail = Vframe_list; CONSP (fl_tail); fl_tail = XCDR (fl_tail))
- {
- frame = XCAR (fl_tail);
- if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
- XFRAME (frame)->param_alist)),
- display)))
- break;
- }
+ FOR_EACH_FRAME (tail, frame)
+ if (!NILP (Fequal (Fcdr (Fassq (Qdisplay,
+ XFRAME (frame)->param_alist)),
+ display)))
+ break;
}
CHECK_LIVE_FRAME (frame);
@@ -5102,7 +5042,7 @@ face for italic. */)
error ("Cannot realize default face");
def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
if (def_face == NULL)
- abort (); /* realize_basic_faces must have set it up */
+ emacs_abort (); /* realize_basic_faces must have set it up */
}
/* Dispatch to the appropriate handler. */
@@ -5246,7 +5186,7 @@ be found. Value is ALIST. */)
attribute of ATTRS doesn't name a fontset. */
static int
-face_fontset (Lisp_Object *attrs)
+face_fontset (Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
Lisp_Object name;
@@ -5276,7 +5216,7 @@ realize_basic_faces (struct frame *f)
/* Block input here so that we won't be surprised by an X expose
event, for instance, without having the faces set up. */
- BLOCK_INPUT;
+ block_input ();
specbind (Qscalable_fonts_allowed, Qt);
if (realize_default_face (f))
@@ -5307,7 +5247,7 @@ realize_basic_faces (struct frame *f)
}
unbind_to (count, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
return success_p;
}
@@ -5387,7 +5327,7 @@ realize_default_face (struct frame *f)
else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ASET (lface, LFACE_FOREGROUND_INDEX, build_string (unspecified_fg));
else
- abort ();
+ emacs_abort ();
}
if (UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
@@ -5402,7 +5342,7 @@ realize_default_face (struct frame *f)
else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
ASET (lface, LFACE_BACKGROUND_INDEX, build_string (unspecified_bg));
else
- abort ();
+ emacs_abort ();
}
if (UNSPECIFIEDP (LFACE_STIPPLE (lface)))
@@ -5475,7 +5415,8 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id)
face. Value is a pointer to the newly created realized face. */
static struct face *
-realize_face (struct face_cache *cache, Lisp_Object *attrs, int former_face_id)
+realize_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE],
+ int former_face_id)
{
struct face *face;
@@ -5502,7 +5443,7 @@ realize_face (struct face_cache *cache, Lisp_Object *attrs, int former_face_id)
face = make_realized_face (attrs);
}
else
- abort ();
+ emacs_abort ();
/* Insert the new face. */
cache_face (cache, face, lface_hash (attrs));
@@ -5552,7 +5493,7 @@ realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
created realized face. */
static struct face *
-realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
+realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
struct face *face = NULL;
#ifdef HAVE_WINDOW_SYSTEM
@@ -5597,7 +5538,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
if (default_face)
fontset = default_face->fontset;
if (fontset == -1)
- abort ();
+ emacs_abort ();
}
if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
attrs[LFACE_FONT_INDEX]
@@ -5725,6 +5666,8 @@ realize_x_face (struct face_cache *cache, Lisp_Object *attrs)
face->underline_defaulted_p = 1;
face->underline_type = FACE_UNDER_LINE;
+ /* FIXME? This is also not robust about checking the precise form.
+ See comments in Finternal_set_lisp_face_attribute. */
while (CONSP (underline))
{
Lisp_Object keyword, value;
@@ -5879,7 +5822,8 @@ map_tty_color (struct frame *f, struct face *face,
Value is a pointer to the newly created realized face. */
static struct face *
-realize_tty_face (struct face_cache *cache, Lisp_Object *attrs)
+realize_tty_face (struct face_cache *cache,
+ Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
struct face *face;
int weight, slant;
@@ -6353,7 +6297,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
int red, green, blue;
int num;
- BLOCK_INPUT;
+ block_input ();
while (fgets (buf, sizeof (buf), fp) != NULL) {
if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
@@ -6363,7 +6307,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
if (num >= 0 && name[num] == '\n')
name[num] = 0;
cmap = Fcons (Fcons (build_string (name),
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
make_number (RGB (red, green, blue))),
#else
make_number ((red << 16) | (green << 8) | blue)),
@@ -6373,7 +6317,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
}
fclose (fp);
- UNBLOCK_INPUT;
+ unblock_input ();
}
return cmap;
@@ -6506,7 +6450,6 @@ syms_of_xfaces (void)
DEFSYM (Qreleased_button, "released-button");
DEFSYM (Qpressed_button, "pressed-button");
DEFSYM (Qnormal, "normal");
- DEFSYM (Qultra_light, "ultra-light");
DEFSYM (Qextra_light, "extra-light");
DEFSYM (Qlight, "light");
DEFSYM (Qsemi_light, "semi-light");
@@ -6516,16 +6459,6 @@ syms_of_xfaces (void)
DEFSYM (Qultra_bold, "ultra-bold");
DEFSYM (Qoblique, "oblique");
DEFSYM (Qitalic, "italic");
- DEFSYM (Qreverse_oblique, "reverse-oblique");
- DEFSYM (Qreverse_italic, "reverse-italic");
- DEFSYM (Qultra_condensed, "ultra-condensed");
- DEFSYM (Qextra_condensed, "extra-condensed");
- DEFSYM (Qcondensed, "condensed");
- DEFSYM (Qsemi_condensed, "semi-condensed");
- DEFSYM (Qsemi_expanded, "semi-expanded");
- DEFSYM (Qexpanded, "expanded");
- DEFSYM (Qextra_expanded, "extra-expanded");
- DEFSYM (Qultra_expanded, "ultra-expanded");
DEFSYM (Qbackground_color, "background-color");
DEFSYM (Qforeground_color, "foreground-color");
DEFSYM (Qunspecified, "unspecified");
@@ -6595,12 +6528,6 @@ syms_of_xfaces (void)
defsubr (&Sdump_colors);
#endif
- DEFVAR_LISP ("font-list-limit", Vfont_list_limit,
- doc: /* Limit for font matching.
-If an integer > 0, font matching functions won't load more than
-that number of fonts when searching for a matching font. */);
- Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
-
DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults,
doc: /* List of global face definitions (for internal use only.) */);
Vface_new_frame_defaults = Qnil;
diff --git a/src/xfns.c b/src/xfns.c
index 90b54d12345..7e832c3a95f 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <math.h>
-#include <setjmp.h>
#include <unistd.h>
/* This makes the fields of a Display accessible, in Xlib header files. */
@@ -165,12 +164,8 @@ have_menus_p (void)
FRAME_PTR
check_x_frame (Lisp_Object frame)
{
- FRAME_PTR f;
+ struct frame *f = decode_live_frame (frame);
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
if (! FRAME_X_P (f))
error ("Non-X frame used");
return f;
@@ -229,13 +224,11 @@ x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
Lisp_Object tail, frame;
struct frame *f;
- if (wdesc == None) return 0;
+ if (wdesc == None)
+ return NULL;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
f = XFRAME (frame);
if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
@@ -275,18 +268,16 @@ struct frame *
x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
{
Lisp_Object tail, frame;
- struct frame *f, *found;
+ struct frame *f, *found = NULL;
struct x_output *x;
- if (wdesc == None) return NULL;
+ if (wdesc == None)
+ return NULL;
- found = NULL;
- for (tail = Vframe_list; CONSP (tail) && !found; tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
-
+ if (found)
+ break;
f = XFRAME (frame);
if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
{
@@ -330,13 +321,11 @@ x_menubar_window_to_frame (struct x_display_info *dpyinfo, XEvent *event)
struct frame *f;
struct x_output *x;
- if (wdesc == None) return 0;
+ if (wdesc == None)
+ return NULL;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
f = XFRAME (frame);
if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
@@ -364,13 +353,11 @@ x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
struct frame *f;
struct x_output *x;
- if (wdesc == None) return 0;
+ if (wdesc == None)
+ return NULL;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
f = XFRAME (frame);
if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
@@ -426,7 +413,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
unsigned char *tmp_data = NULL;
Atom target_type = XA_CARDINAL;
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpy);
@@ -544,7 +531,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
if (had_errors) return;
@@ -576,27 +563,27 @@ gamma_correct (struct frame *f, XColor *color)
/* Decide if color named COLOR_NAME is valid for use on frame F. If
- so, return the RGB values in COLOR. If ALLOC_P is non-zero,
- allocate the color. Value is zero if COLOR_NAME is invalid, or
+ so, return the RGB values in COLOR. If ALLOC_P,
+ allocate the color. Value is false if COLOR_NAME is invalid, or
no color could be allocated. */
-int
+bool
x_defined_color (struct frame *f, const char *color_name,
- XColor *color, int alloc_p)
+ XColor *color, bool alloc_p)
{
- int success_p = 0;
+ bool success_p = 0;
Display *dpy = FRAME_X_DISPLAY (f);
Colormap cmap = FRAME_X_COLORMAP (f);
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_GTK
success_p = xg_check_special_colors (f, color_name, color);
#endif
if (!success_p)
- success_p = XParseColor (dpy, cmap, color_name, color);
+ success_p = XParseColor (dpy, cmap, color_name, color) != 0;
if (success_p && alloc_p)
success_p = x_alloc_nearest_color (f, cmap, color);
- UNBLOCK_INPUT;
+ unblock_input ();
return success_p;
}
@@ -657,8 +644,8 @@ x_set_tool_bar_position (struct frame *f,
if (EQ (new_value, old_value)) return;
#ifdef USE_GTK
- if (xg_change_toolbar_position (f, new_value))
- fset_tool_bar_position (f, new_value);
+ xg_change_toolbar_position (f, new_value);
+ fset_tool_bar_position (f, new_value);
#endif
}
@@ -680,7 +667,7 @@ xg_set_icon (FRAME_PTR f, Lisp_Object file)
GdkPixbuf *pixbuf;
GError *err = NULL;
char *filename = SSDATA (found);
- BLOCK_INPUT;
+ block_input ();
pixbuf = gdk_pixbuf_new_from_file (filename, &err);
@@ -695,7 +682,7 @@ xg_set_icon (FRAME_PTR f, Lisp_Object file)
else
g_error_free (err);
- UNBLOCK_INPUT;
+ unblock_input ();
}
return result;
@@ -738,7 +725,7 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
Display *dpy = FRAME_X_DISPLAY (f);
- BLOCK_INPUT;
+ block_input ();
XSetForeground (dpy, x->normal_gc, fg);
XSetBackground (dpy, x->reverse_gc, fg);
@@ -749,7 +736,7 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
}
- UNBLOCK_INPUT;
+ unblock_input ();
update_face_from_frame_parameter (f, Qforeground_color, arg);
@@ -774,7 +761,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
Display *dpy = FRAME_X_DISPLAY (f);
- BLOCK_INPUT;
+ block_input ();
XSetBackground (dpy, x->normal_gc, bg);
XSetForeground (dpy, x->reverse_gc, bg);
XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
@@ -798,7 +785,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
#endif /* USE_TOOLKIT_SCROLL_BARS */
- UNBLOCK_INPUT;
+ unblock_input ();
update_face_from_frame_parameter (f, Qbackground_color, arg);
if (FRAME_VISIBLE_P (f))
@@ -855,7 +842,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
unload_color (f, x->mouse_pixel);
x->mouse_pixel = pixel;
- BLOCK_INPUT;
+ block_input ();
/* It's not okay to crash if the user selects a screwy cursor. */
x_catch_errors (dpy);
@@ -975,7 +962,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
x->horizontal_drag_cursor = horizontal_drag_cursor;
XFlush (dpy);
- UNBLOCK_INPUT;
+ unblock_input ();
update_face_from_frame_parameter (f, Qmouse_color, arg);
}
@@ -1032,10 +1019,10 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (FRAME_X_WINDOW (f) != 0)
{
- BLOCK_INPUT;
+ block_input ();
XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
- UNBLOCK_INPUT;
+ unblock_input ();
if (FRAME_VISIBLE_P (f))
{
@@ -1059,9 +1046,9 @@ x_set_border_pixel (struct frame *f, int pix)
if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
{
- BLOCK_INPUT;
+ block_input ();
XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
- UNBLOCK_INPUT;
+ unblock_input ();
if (FRAME_VISIBLE_P (f))
redraw_frame (f);
@@ -1113,7 +1100,7 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
return;
- BLOCK_INPUT;
+ block_input ();
if (NILP (arg))
result = x_text_icon (f,
SSDATA ((!NILP (f->icon_name)
@@ -1124,12 +1111,12 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (result)
{
- UNBLOCK_INPUT;
+ unblock_input ();
error ("No icon window available");
}
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
static void
@@ -1150,7 +1137,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (f->output_data.x->icon_bitmap != 0)
return;
- BLOCK_INPUT;
+ block_input ();
result = x_text_icon (f,
SSDATA ((!NILP (f->icon_name)
@@ -1161,12 +1148,12 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (result)
{
- UNBLOCK_INPUT;
+ unblock_input ();
error ("No icon window available");
}
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -1229,10 +1216,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
y = FRAME_TOP_MARGIN_HEIGHT (f);
- BLOCK_INPUT;
+ block_input ();
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
0, y, width, height, False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (nlines > 1 && nlines > olines)
@@ -1240,10 +1227,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
height = nlines * FRAME_LINE_HEIGHT (f) - y;
- BLOCK_INPUT;
+ block_input ();
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
0, y, width, height, False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (nlines == 0 && WINDOWP (f->menu_bar_window))
@@ -1339,10 +1326,10 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
/* height can be zero here. */
if (height > 0 && width > 0)
{
- BLOCK_INPUT;
+ block_input ();
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
0, y, width, height, False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (WINDOWP (f->tool_bar_window))
@@ -1495,7 +1482,7 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name)
{
if (FRAME_X_WINDOW (f))
{
- BLOCK_INPUT;
+ block_input ();
{
XTextProperty text, icon;
ptrdiff_t bytes;
@@ -1587,7 +1574,7 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name)
if (do_free_text_value)
xfree (text.value);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -1780,7 +1767,7 @@ hack_wm_protocols (FRAME_PTR f, Widget widget)
int need_focus = 1;
int need_save = 1;
- BLOCK_INPUT;
+ block_input ();
{
Atom type;
unsigned char *catoms;
@@ -1828,7 +1815,7 @@ hack_wm_protocols (FRAME_PTR f, Widget widget)
XA_ATOM, 32, PropModeAppend,
(unsigned char *) props, count);
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
@@ -2351,7 +2338,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
Arg al [25];
int ac;
- BLOCK_INPUT;
+ block_input ();
/* Use the resource name as the top-level widget name
for looking up resources. Make a non-Lisp copy
@@ -2573,7 +2560,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only)
f->output_data.x->current_cursor
= f->output_data.x->text_cursor);
- UNBLOCK_INPUT;
+ unblock_input ();
/* This is a no-op, except under Motif. Make sure main areas are
set to something reasonable, in case we get an error later. */
@@ -2592,7 +2579,7 @@ x_window (FRAME_PTR f)
FRAME_XIC (f) = NULL;
if (use_xim)
{
- BLOCK_INPUT;
+ block_input ();
create_frame_xic (f);
if (FRAME_XIC (f))
{
@@ -2614,7 +2601,7 @@ x_window (FRAME_PTR f)
attribute_mask, &attributes);
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
}
@@ -2639,7 +2626,7 @@ x_window (struct frame *f)
attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
| CWColormap);
- BLOCK_INPUT;
+ block_input ();
FRAME_X_WINDOW (f)
= XCreateWindow (FRAME_X_DISPLAY (f),
f->output_data.x->parent_desc,
@@ -2716,7 +2703,7 @@ x_window (struct frame *f)
f->output_data.x->current_cursor
= f->output_data.x->text_cursor);
- UNBLOCK_INPUT;
+ unblock_input ();
if (FRAME_X_WINDOW (f) == 0)
error ("Unable to create window");
@@ -2769,7 +2756,7 @@ x_icon (struct frame *f, Lisp_Object parms)
else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
error ("Both left and top icon corners of icon must be specified");
- BLOCK_INPUT;
+ block_input ();
if (! EQ (icon_x, Qunbound))
x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
@@ -2788,7 +2775,7 @@ x_icon (struct frame *f, Lisp_Object parms)
? f->icon_name
: f->name)));
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Make the GCs needed for this window, setting the
@@ -2800,7 +2787,7 @@ x_make_gc (struct frame *f)
{
XGCValues gc_values;
- BLOCK_INPUT;
+ block_input ();
/* Create the GCs of this frame.
Note that many default values are used. */
@@ -2848,7 +2835,7 @@ x_make_gc (struct frame *f)
FRAME_BACKGROUND_PIXEL (f),
DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -2859,7 +2846,7 @@ x_free_gcs (struct frame *f)
{
Display *dpy = FRAME_X_DISPLAY (f);
- BLOCK_INPUT;
+ block_input ();
if (f->output_data.x->normal_gc)
{
@@ -2885,7 +2872,7 @@ x_free_gcs (struct frame *f)
f->output_data.x->border_tile = 0;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3001,17 +2988,15 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
DEFUN ("x-wm-set-size-hint", Fx_wm_set_size_hint, Sx_wm_set_size_hint,
0, 1, 0,
doc: /* Send the size hints for frame FRAME to the window manager.
-If FRAME is nil, use the selected frame. */)
+If FRAME is omitted or nil, use the selected frame.
+Signal error if FRAME is not an X frame. */)
(Lisp_Object frame)
{
- struct frame *f;
- if (NILP (frame))
- frame = selected_frame;
- f = XFRAME (frame);
- BLOCK_INPUT;
- if (FRAME_X_P (f))
- x_wm_set_size_hint (f, 0, 0);
- UNBLOCK_INPUT;
+ struct frame *f = check_x_frame (frame);
+
+ block_input ();
+ x_wm_set_size_hint (f, 0, 0);
+ unblock_input ();
return Qnil;
}
@@ -3112,9 +3097,6 @@ This function is an internal primitive--use `make-frame' instead. */)
XSETFRAME (frame, f);
- /* Note that X Windows does support scroll bars. */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-
f->terminal = dpyinfo->terminal;
f->output_method = output_x_window;
@@ -3406,9 +3388,9 @@ This function is an internal primitive--use `make-frame' instead. */)
/* 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;
+ block_input ();
x_wm_set_size_hint (f, window_prompting, 0);
- UNBLOCK_INPUT;
+ unblock_input ();
/* Make the window appear on the frame and enable display, unless
the caller says not to. However, with explicit parent, Emacs
@@ -3432,7 +3414,7 @@ This function is an internal primitive--use `make-frame' instead. */)
}
}
- BLOCK_INPUT;
+ block_input ();
/* Set machine name and pid for the purpose of window managers. */
set_machine_and_pid_properties (f);
@@ -3448,7 +3430,7 @@ This function is an internal primitive--use `make-frame' instead. */)
(unsigned char *) &dpyinfo->client_leader_window, 1);
}
- UNBLOCK_INPUT;
+ unblock_input ();
/* Initialize `default-minibuffer-frame' in case this is the first
frame on this terminal. */
@@ -3507,7 +3489,7 @@ FRAME nil means use the selected frame. */)
struct frame *f = check_x_frame (frame);
Display *dpy = FRAME_X_DISPLAY (f);
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpy);
if (FRAME_X_EMBEDDED_P (f))
@@ -3525,7 +3507,7 @@ FRAME nil means use the selected frame. */)
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -3866,20 +3848,6 @@ x_pixel_height (register struct frame *f)
return FRAME_PIXEL_HEIGHT (f);
}
-int
-x_char_width (register struct frame *f)
-{
- return FRAME_COLUMN_WIDTH (f);
-}
-
-int
-x_char_height (register struct frame *f)
-{
- return FRAME_LINE_HEIGHT (f);
-}
-
-
-
/************************************************************************
X Displays
************************************************************************/
@@ -4153,9 +4121,9 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display. */
void
x_sync (FRAME_PTR f)
{
- BLOCK_INPUT;
+ block_input ();
XSync (FRAME_X_DISPLAY (f), False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -4230,7 +4198,7 @@ FRAME. Default is to change on the edit X window. */)
nelements = SBYTES (value);
}
- BLOCK_INPUT;
+ block_input ();
prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
if (! NILP (type))
{
@@ -4249,7 +4217,7 @@ FRAME. Default is to change on the edit X window. */)
/* Make sure the property is set when we return. */
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
return value;
}
@@ -4265,13 +4233,13 @@ FRAME nil or omitted means use the selected frame. Value is PROP. */)
Atom prop_atom;
CHECK_STRING (prop);
- BLOCK_INPUT;
+ block_input ();
prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), prop_atom);
/* Make sure the property is removed when we return. */
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
return prop;
}
@@ -4319,7 +4287,7 @@ no value of TYPE (always string in the MS Windows case). */)
target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
}
- BLOCK_INPUT;
+ block_input ();
if (STRINGP (type))
{
if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
@@ -4385,7 +4353,7 @@ no value of TYPE (always string in the MS Windows case). */)
if (tmp_data) XFree (tmp_data);
}
- UNBLOCK_INPUT;
+ unblock_input ();
UNGCPRO;
return prop_value;
}
@@ -4416,7 +4384,7 @@ show_hourglass (struct atimer *timer)
{
Lisp_Object rest, frame;
- BLOCK_INPUT;
+ block_input ();
FOR_EACH_FRAME (rest, frame)
{
@@ -4460,7 +4428,7 @@ show_hourglass (struct atimer *timer)
}
hourglass_shown_p = 1;
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -4475,7 +4443,7 @@ hide_hourglass (void)
{
Lisp_Object rest, frame;
- BLOCK_INPUT;
+ block_input ();
FOR_EACH_FRAME (rest, frame)
{
struct frame *f = XFRAME (frame);
@@ -4494,7 +4462,7 @@ hide_hourglass (void)
}
hourglass_shown_p = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -4597,7 +4565,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
Finsert (1, &text);
set_buffer_internal_1 (old_buffer);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
record_unwind_protect (unwind_create_tip_frame, frame);
f->terminal = dpyinfo->terminal;
@@ -4744,7 +4711,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
unsigned long mask;
Atom type = FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
- BLOCK_INPUT;
+ block_input ();
mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
if (DoesSaveUnders (dpyinfo->screen))
mask |= CWSaveUnder;
@@ -4771,7 +4738,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type,
XA_ATOM, 32, PropModeReplace,
(unsigned char *)&type, 1);
- UNBLOCK_INPUT;
+ unblock_input ();
}
x_make_gc (f);
@@ -4885,10 +4852,10 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object
show it. */
if (!INTEGERP (left) || !INTEGERP (top))
{
- BLOCK_INPUT;
+ block_input ();
XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
&root, &child, root_x, root_y, &win_x, &win_y, &pmask);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (INTEGERP (top))
@@ -4986,20 +4953,21 @@ Text larger than the specified size is clipped. */)
#ifdef USE_GTK
if (x_gtk_use_system_tooltips)
{
- int ok;
+ bool ok;
/* Hide a previous tip, if any. */
Fx_hide_tip ();
- BLOCK_INPUT;
- if ((ok = xg_prepare_tooltip (f, string, &width, &height)) != 0)
+ block_input ();
+ ok = xg_prepare_tooltip (f, string, &width, &height);
+ if (ok)
{
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
xg_show_tooltip (f, root_x, root_y);
/* This is used in Fx_hide_tip. */
XSETFRAME (tip_frame, f);
}
- UNBLOCK_INPUT;
+ unblock_input ();
if (ok) goto start_timer;
}
#endif /* USE_GTK */
@@ -5027,12 +4995,12 @@ Text larger than the specified size is clipped. */)
call1 (Qcancel_timer, timer);
}
- BLOCK_INPUT;
+ block_input ();
compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
root_x, root_y);
- UNBLOCK_INPUT;
+ unblock_input ();
goto start_timer;
}
}
@@ -5186,11 +5154,11 @@ Text larger than the specified size is clipped. */)
show it. */
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
- BLOCK_INPUT;
+ block_input ();
XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
root_x, root_y, width, height);
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- UNBLOCK_INPUT;
+ unblock_input ();
/* Draw into the window. */
w->must_be_updated_p = 1;
@@ -5262,9 +5230,9 @@ Value is t if tooltip was open, nil otherwise. */)
if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
&& w != NULL)
{
- BLOCK_INPUT;
+ block_input ();
xlwmenu_redisplay (w);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
#endif /* USE_LUCID */
@@ -5328,11 +5296,11 @@ clean_up_file_dialog (Lisp_Object arg)
Widget dialog = (Widget) p->pointer;
/* Clean up. */
- BLOCK_INPUT;
+ block_input ();
XtUnmanageChild (dialog);
XtDestroyWidget (dialog);
x_menu_set_in_use (0);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -5344,7 +5312,7 @@ Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
selection box, if specified. If MUSTMATCH is non-nil, the returned file
or directory must exist.
-This function is only defined on MS Windows, and X Windows with the
+This function is only defined on NS, MS Windows, and X Windows with the
Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
(Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
@@ -5373,7 +5341,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
- BLOCK_INPUT;
+ block_input ();
/* Create the dialog with PROMPT as title, using DIR as initial
directory and using "*" as pattern. */
@@ -5487,7 +5455,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
else
file = Qnil;
- UNBLOCK_INPUT;
+ unblock_input ();
UNGCPRO;
/* Make "Cancel" equivalent to C-g. */
@@ -5517,7 +5485,7 @@ Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
selection box, if specified. If MUSTMATCH is non-nil, the returned file
or directory must exist.
-This function is only defined on MS Windows, and X Windows with the
+This function is only defined on NS, MS Windows, and X Windows with the
Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
(Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
@@ -5544,7 +5512,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
specbind (Qinhibit_redisplay, Qt);
record_unwind_protect (clean_up_dialog, Qnil);
- BLOCK_INPUT;
+ block_input ();
if (STRINGP (default_filename))
cdef_file = SSDATA (default_filename);
@@ -5561,7 +5529,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
xfree (fn);
}
- UNBLOCK_INPUT;
+ unblock_input ();
UNGCPRO;
/* Make "Cancel" equivalent to C-g. */
@@ -5601,7 +5569,7 @@ nil, it defaults to the selected frame. */)
specbind (Qinhibit_redisplay, Qt);
record_unwind_protect (clean_up_dialog, Qnil);
- BLOCK_INPUT;
+ block_input ();
GCPRO2 (font_param, font);
@@ -5619,7 +5587,7 @@ nil, it defaults to the selected frame. */)
font = xg_get_font (f, default_name);
xfree (default_name);
- UNBLOCK_INPUT;
+ unblock_input ();
if (NILP (font))
Fsignal (Qquit, Qnil);
@@ -5656,14 +5624,14 @@ present and mapped to the usual X keysyms. */)
Lisp_Object have_keys;
int major, minor, op, event, error_code;
- BLOCK_INPUT;
+ block_input ();
/* Check library version in case we're dynamically linked. */
major = XkbMajorVersion;
minor = XkbMinorVersion;
if (!XkbLibraryVersion (&major, &minor))
{
- UNBLOCK_INPUT;
+ unblock_input ();
return Qlambda;
}
@@ -5672,7 +5640,7 @@ present and mapped to the usual X keysyms. */)
minor = XkbMinorVersion;
if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor))
{
- UNBLOCK_INPUT;
+ unblock_input ();
return Qlambda;
}
@@ -5725,7 +5693,7 @@ present and mapped to the usual X keysyms. */)
&& XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
have_keys = Qt;
}
- UNBLOCK_INPUT;
+ unblock_input ();
return have_keys;
#else /* not HAVE_XKBGETKEYBOARD */
return Qlambda;
diff --git a/src/xfont.c b/src/xfont.c
index be9556d585a..2d493088b0b 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include <X11/Xlib.h>
#include "lisp.h"
@@ -126,7 +125,7 @@ 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 int xfont_draw (struct glyph_string *, int, int, int, int, int);
+static int xfont_draw (struct glyph_string *, int, int, int, int, bool);
static int xfont_check (FRAME_PTR, struct font *);
struct font_driver xfont_driver =
@@ -217,9 +216,9 @@ xfont_encode_coding_xlfd (char *xlfd)
/* Check if CHARS (cons or vector) is supported by XFONT whose
encoding charset is ENCODING (XFONT is NULL) or by a font whose
registry corresponds to ENCODING and REPERTORY.
- Return 1 if supported, return 0 otherwise. */
+ Return true if supported. */
-static int
+static bool
xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
struct charset *encoding, struct charset *repertory)
{
@@ -363,7 +362,7 @@ xfont_list_pattern (Display *display, const char *pattern,
}
}
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (display);
for (limit = 512; ; limit *= 2)
@@ -480,7 +479,7 @@ xfont_list_pattern (Display *display, const char *pattern,
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
return list;
@@ -589,7 +588,7 @@ xfont_match (Lisp_Object frame, Lisp_Object spec)
if (xfont_encode_coding_xlfd (name) < 0)
return Qnil;
- BLOCK_INPUT;
+ block_input ();
entity = Qnil;
xfont = XLoadQueryFont (display, name);
if (xfont)
@@ -616,7 +615,7 @@ xfont_match (Lisp_Object frame, Lisp_Object spec)
}
XFreeFont (display, xfont);
}
- UNBLOCK_INPUT;
+ unblock_input ();
FONT_ADD_LOG ("xfont-match", spec, entity);
return entity;
@@ -633,7 +632,7 @@ xfont_list_family (Lisp_Object frame)
char *last_family IF_LINT (= 0);
int last_len;
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpyinfo->display);
names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
0x8000, &num_fonts);
@@ -674,7 +673,7 @@ xfont_list_family (Lisp_Object frame)
XFreeFontNames (names);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return list;
}
@@ -718,7 +717,7 @@ xfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
return Qnil;
}
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (display);
xfont = XLoadQueryFont (display, name);
if (x_had_errors_p (display))
@@ -785,7 +784,7 @@ xfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
XFree (p0);
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
if (! xfont)
{
@@ -867,7 +866,7 @@ xfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
}
}
- BLOCK_INPUT;
+ block_input ();
font->underline_thickness
= (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
? (long) value : 0);
@@ -883,7 +882,7 @@ xfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
font->default_ascent
= (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
? (long) value : 0);
- UNBLOCK_INPUT;
+ unblock_input ();
if (NILP (fullname))
fullname = AREF (font_object, FONT_NAME_INDEX);
@@ -898,18 +897,18 @@ xfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
static void
xfont_close (FRAME_PTR f, struct font *font)
{
- BLOCK_INPUT;
+ block_input ();
XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
- UNBLOCK_INPUT;
+ unblock_input ();
}
static int
xfont_prepare_face (FRAME_PTR f, struct face *face)
{
- BLOCK_INPUT;
+ block_input ();
XSetFont (FRAME_X_DISPLAY (f), face->gc,
((struct xfont_info *) face->font)->xfont->fid);
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -1019,7 +1018,8 @@ xfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct f
}
static int
-xfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_background)
+xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
+ bool with_background)
{
XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
int len = to - from;
@@ -1028,9 +1028,9 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_bac
if (s->gc != s->face->gc)
{
- BLOCK_INPUT;
+ block_input ();
XSetFont (s->display, gc, xfont->fid);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
@@ -1039,8 +1039,8 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_bac
char *str = SAFE_ALLOCA (len);
for (i = 0; i < len ; i++)
str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
- BLOCK_INPUT;
- if (with_background > 0)
+ block_input ();
+ if (with_background)
{
if (s->padding_p)
for (i = 0; i < len; i++)
@@ -1060,13 +1060,13 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_bac
XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
gc, x, y, str, len);
}
- UNBLOCK_INPUT;
+ unblock_input ();
SAFE_FREE ();
return s->nchars;
}
- BLOCK_INPUT;
- if (with_background > 0)
+ block_input ();
+ if (with_background)
{
if (s->padding_p)
for (i = 0; i < len; i++)
@@ -1086,7 +1086,7 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_bac
XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
gc, x, y, s->char2b + from, len);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return len;
}
diff --git a/src/xftfont.c b/src/xftfont.c
index 5e60ab0c4d3..181a1da9b38 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
@@ -52,7 +51,7 @@ struct xftfont_info
/* The following five members must be here in this order to be
compatible with struct ftfont_info (in ftfont.c). */
#ifdef HAVE_LIBOTF
- int maybe_otf; /* Flag to tell if this may be OTF or not. */
+ bool maybe_otf; /* Flag to tell if this may be OTF or not. */
OTF *otf;
#endif /* HAVE_LIBOTF */
FT_Size ft_size;
@@ -92,9 +91,9 @@ xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *
else
{
XGCValues xgcv;
- int fg_done = 0, bg_done = 0;
+ bool fg_done = 0, bg_done = 0;
- BLOCK_INPUT;
+ block_input ();
XGetGCValues (FRAME_X_DISPLAY (f), gc,
GCForeground | GCBackground, &xgcv);
if (xftface_info)
@@ -111,7 +110,7 @@ xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *
*bg = xftface_info->xft_fg, bg_done = 1;
}
- if (fg_done + bg_done < 2)
+ if (! (fg_done & bg_done))
{
XColor colors[2];
@@ -132,24 +131,11 @@ xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *
bg->color.blue = colors[1].blue;
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
-static Lisp_Object xftfont_list (Lisp_Object, Lisp_Object);
-static Lisp_Object xftfont_match (Lisp_Object, Lisp_Object);
-static Lisp_Object xftfont_open (FRAME_PTR, Lisp_Object, int);
-static void xftfont_close (FRAME_PTR, struct font *);
-static int xftfont_prepare_face (FRAME_PTR, struct face *);
-static void xftfont_done_face (FRAME_PTR, struct face *);
-static int xftfont_has_char (Lisp_Object, int);
-static unsigned xftfont_encode_char (struct font *, int);
-static int xftfont_text_extents (struct font *, unsigned *, int,
- struct font_metrics *);
-static int xftfont_draw (struct glyph_string *, int, int, int, int, int);
-static int xftfont_end_for_frame (FRAME_PTR f);
-
struct font_driver xftfont_driver;
static Lisp_Object
@@ -338,7 +324,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
- BLOCK_INPUT;
+ 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
@@ -359,12 +345,12 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
xftfont = XftFontOpenPattern (display, match);
if (!xftfont)
{
- UNBLOCK_INPUT;
+ unblock_input ();
XftPatternDestroy (match);
return Qnil;
}
ft_face = XftLockFace (xftfont);
- UNBLOCK_INPUT;
+ unblock_input ();
/* We should not destroy PAT here because it is kept in XFTFONT and
destroyed automatically when XFTFONT is closed. */
@@ -383,7 +369,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
ASET (font_object, FONT_FORMAT_INDEX,
ftfont_font_format (xftfont->pattern, filename));
font = XFONT_OBJECT (font_object);
- font->pixel_size = pixel_size;
+ font->pixel_size = size;
font->driver = &xftfont_driver;
font->encoding_charset = font->repertory_charset = -1;
@@ -401,8 +387,6 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
xftfont_info->matrix.xy = 0x10000L * matrix->xy;
xftfont_info->matrix.yx = 0x10000L * matrix->yx;
}
- font->pixel_size = size;
- font->driver = &xftfont_driver;
if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
else
@@ -413,7 +397,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
for (ch = 0; ch < 95; ch++)
ascii_printable[ch] = ' ' + ch;
}
- BLOCK_INPUT;
+ block_input ();
/* Unfortunately Xft doesn't provide a way to get minimum char
width. So, we set min_width to space_width. */
@@ -439,7 +423,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
font->average_width = (font->space_width + extents.xOff) / 95;
}
- UNBLOCK_INPUT;
+ unblock_input ();
font->ascent = xftfont->ascent;
font->descent = xftfont->descent;
@@ -470,7 +454,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
font->underline_thickness = 0;
}
#ifdef HAVE_LIBOTF
- xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
+ xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
xftfont_info->otf = NULL;
#endif /* HAVE_LIBOTF */
xftfont_info->ft_size = ft_face->size;
@@ -508,10 +492,10 @@ xftfont_close (FRAME_PTR f, struct font *font)
if (xftfont_info->otf)
OTF_close (xftfont_info->otf);
#endif
- BLOCK_INPUT;
+ block_input ();
XftUnlockFace (xftfont_info->xftfont);
XftFontClose (xftfont_info->display, xftfont_info->xftfont);
- UNBLOCK_INPUT;
+ unblock_input ();
}
static int
@@ -595,10 +579,10 @@ xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
XGlyphInfo extents;
- BLOCK_INPUT;
+ block_input ();
XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
&extents);
- UNBLOCK_INPUT;
+ unblock_input ();
if (metrics)
{
metrics->lbearing = - extents.x;
@@ -617,12 +601,12 @@ xftfont_get_xft_draw (FRAME_PTR f)
if (! xft_draw)
{
- BLOCK_INPUT;
+ block_input ();
xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
FRAME_X_WINDOW (f),
FRAME_X_VISUAL (f),
FRAME_X_COLORMAP (f));
- UNBLOCK_INPUT;
+ unblock_input ();
eassert (xft_draw != NULL);
font_put_frame_data (f, &xftfont_driver, xft_draw);
}
@@ -630,7 +614,8 @@ xftfont_get_xft_draw (FRAME_PTR f)
}
static int
-xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_background)
+xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
+ bool with_background)
{
FRAME_PTR f = s->f;
struct face *face = s->face;
@@ -646,7 +631,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_b
xftface_info = (struct xftface_info *) face->extra;
xftfont_get_colors (f, face, s->gc, xftface_info,
&fg, with_background ? &bg : NULL);
- BLOCK_INPUT;
+ block_input ();
if (s->num_clips > 0)
XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
else
@@ -667,7 +652,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_b
else
XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
x, y, code, len);
- UNBLOCK_INPUT;
+ unblock_input ();
return len;
}
@@ -703,23 +688,25 @@ xftfont_end_for_frame (FRAME_PTR f)
if (xft_draw)
{
- BLOCK_INPUT;
+ block_input ();
XftDrawDestroy (xft_draw);
- UNBLOCK_INPUT;
+ unblock_input ();
font_put_frame_data (f, &xftfont_driver, NULL);
}
return 0;
}
-static int
-xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, Lisp_Object entity)
+static bool
+xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
+ Lisp_Object entity)
{
struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
FcPattern *oldpat = info->xftfont->pattern;
Display *display = FRAME_X_DISPLAY (f);
FcPattern *pat = FcPatternCreate ();
FcBool b1, b2;
- int ok = 0, i1, i2, r1, r2;
+ bool ok = 0;
+ int i1, i2, r1, r2;
xftfont_add_rendering_parameters (pat, entity);
XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
diff --git a/src/xgselect.c b/src/xgselect.c
index 0c00d815820..c161564a322 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -19,14 +19,12 @@ along with GNU Emacs. If not, see <http§://www.gnu.org/licenses/>. */
#include <config.h>
-#include <setjmp.h>
#include "xgselect.h"
#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
#include <glib.h>
#include <errno.h>
-#include <setjmp.h>
#include "xterm.h"
int
@@ -49,9 +47,9 @@ xg_select (int fds_lim, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
&& g_main_context_pending (context = g_main_context_default ())))
return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask);
- if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds));
+ if (rfds) all_rfds = *rfds;
else FD_ZERO (&all_rfds);
- if (wfds) memcpy (&all_wfds, wfds, sizeof (all_rfds));
+ if (wfds) all_wfds = *wfds;
else FD_ZERO (&all_wfds);
n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec,
diff --git a/src/xmenu.c b/src/xmenu.c
index 54a7849218a..b585df2125b 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -32,13 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#if 0 /* Why was this included? And without syssignal.h? */
-/* On 4.3 this loses if it comes after xterm.h. */
-#include <signal.h>
-#endif
-
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "keyboard.h"
@@ -117,7 +111,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
static Lisp_Object Qdebug_on_next_call;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-static Lisp_Object xdialog_show (FRAME_PTR, int, Lisp_Object, Lisp_Object,
+static Lisp_Object xdialog_show (FRAME_PTR, bool, Lisp_Object, Lisp_Object,
const char **);
#endif
@@ -138,11 +132,8 @@ menubar_id_to_frame (LWLIB_ID id)
Lisp_Object tail, frame;
FRAME_PTR f;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- frame = XCAR (tail);
- if (!FRAMEP (frame))
- continue;
f = XFRAME (frame);
if (!FRAME_WINDOW_P (f))
continue;
@@ -169,9 +160,9 @@ mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
int dummy;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
- BLOCK_INPUT;
+ block_input ();
XQueryPointer (FRAME_X_DISPLAY (f),
DefaultRootWindow (FRAME_X_DISPLAY (f)),
@@ -192,7 +183,7 @@ mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
we don't care. */
(unsigned int *) &dummy);
- UNBLOCK_INPUT;
+ unblock_input ();
/* xmenu_show expects window coordinates, not root window
coordinates. Translate. */
@@ -334,9 +325,9 @@ for instance using the window manager, then this produces a quit and
list_of_panes (Fcons (contents, Qnil));
/* Display them in a dialog box. */
- BLOCK_INPUT;
+ block_input ();
selection = xdialog_show (f, 0, title, header, &error_name);
- UNBLOCK_INPUT;
+ unblock_input ();
unbind_to (specpdl_count, Qnil);
discard_menu_items ();
@@ -496,7 +487,7 @@ If FRAME is nil or not given, use the selected frame. */)
XEvent ev;
FRAME_PTR f = check_x_frame (frame);
Widget menubar;
- BLOCK_INPUT;
+ block_input ();
if (FRAME_EXTERNAL_MENU_BAR (f))
set_frame_menubar (f, 0, 1);
@@ -554,7 +545,7 @@ If FRAME is nil or not given, use the selected frame. */)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -575,9 +566,9 @@ If FRAME is nil or not given, use the selected frame. */)
FRAME_PTR f;
/* gcc 2.95 doesn't accept the FRAME_PTR declaration after
- BLOCK_INPUT. */
+ block_input (). */
- BLOCK_INPUT;
+ block_input ();
f = check_x_frame (frame);
if (FRAME_EXTERNAL_MENU_BAR (f))
@@ -596,7 +587,7 @@ If FRAME is nil or not given, use the selected frame. */)
g_list_free (children);
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -636,7 +627,7 @@ void
x_activate_menubar (FRAME_PTR f)
{
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
if (!f->output_data.x->saved_menu_event->type)
return;
@@ -648,7 +639,7 @@ x_activate_menubar (FRAME_PTR f)
#endif
set_frame_menubar (f, 0, 1);
- BLOCK_INPUT;
+ block_input ();
popup_activated_flag = 1;
#ifdef USE_GTK
XPutBackEvent (f->output_data.x->display_info->display,
@@ -656,7 +647,7 @@ x_activate_menubar (FRAME_PTR f)
#else
XtDispatchEvent (f->output_data.x->saved_menu_event);
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
/* Ignore this if we get it a second time. */
f->output_data.x->saved_menu_event->type = 0;
@@ -809,10 +800,10 @@ menubar_selection_callback (GtkWidget *widget, gpointer client_data)
sit-for will exit at once if the focus event follows the menu selection
event. */
- BLOCK_INPUT;
+ block_input ();
while (gtk_events_pending ())
gtk_main_iteration ();
- UNBLOCK_INPUT;
+ unblock_input ();
find_and_call_menu_selection (cb_data->cl_data->f,
cb_data->cl_data->menu_bar_items_used,
@@ -840,26 +831,26 @@ menubar_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
#endif /* not USE_GTK */
/* Recompute all the widgets of frame F, when the menu bar has been
- changed. Value is non-zero if widgets were updated. */
+ changed. */
-static int
+static void
update_frame_menubar (FRAME_PTR f)
{
#ifdef USE_GTK
- return xg_update_frame_menubar (f);
+ xg_update_frame_menubar (f);
#else
struct x_output *x;
int columns, rows;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
x = f->output_data.x;
if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
- return 0;
+ return;
- BLOCK_INPUT;
+ 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);
@@ -886,9 +877,8 @@ update_frame_menubar (FRAME_PTR f)
/* Force the pane widget to resize itself with the right values. */
EmacsFrameSetCharSize (x->edit_widget, columns, rows);
- UNBLOCK_INPUT;
+ unblock_input ();
#endif
- return 1;
}
#ifdef USE_LUCID
@@ -927,7 +917,7 @@ apply_systemfont_to_menu (struct frame *f, Widget w)
it is set the first time this is called, from initialize_frame_menubar. */
void
-set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
+set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p)
{
xt_or_gtk_widget menubar_widget;
#ifdef USE_X_TOOLKIT
@@ -937,10 +927,11 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
widget_value *wv, *first_wv, *prev_wv = 0;
int i;
int *submenu_start, *submenu_end;
- int *submenu_top_level_items, *submenu_n_panes;
+ bool *submenu_top_level_items;
+ int *submenu_n_panes;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
menubar_widget = f->output_data.x->menubar_widget;
@@ -1170,7 +1161,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
/* Create or update the menu bar widget. */
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_GTK
xg_crazy_callback_abort = 1;
@@ -1270,7 +1261,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
xg_crazy_callback_abort = 0;
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Called from Fx_create_frame to create the initial menubar of a frame
@@ -1299,7 +1290,7 @@ free_frame_menubar (FRAME_PTR f)
Widget menubar_widget;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
menubar_widget = f->output_data.x->menubar_widget;
@@ -1319,7 +1310,7 @@ free_frame_menubar (FRAME_PTR f)
Position x0, y0, x1, y1;
#endif
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_MOTIF
if (f->output_data.x->widget)
@@ -1338,7 +1329,7 @@ free_frame_menubar (FRAME_PTR f)
#endif
x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
#endif /* not USE_GTK */
@@ -1353,8 +1344,8 @@ free_frame_menubar (FRAME_PTR 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;
+ FOR_CLICK is true if this menu was invoked for a mouse click.
+ KEYMAPS is true 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.
@@ -1423,9 +1414,9 @@ pop_down_menu (Lisp_Object arg)
struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
popup_activated_flag = 0;
- BLOCK_INPUT;
+ block_input ();
gtk_widget_destroy (GTK_WIDGET (p->pointer));
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -1434,14 +1425,14 @@ pop_down_menu (Lisp_Object arg)
menu_item_selection will be set to the selection. */
static void
create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
- int for_click, Time timestamp)
+ bool for_click, Time timestamp)
{
int i;
GtkWidget *menu;
GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
struct next_popup_x_y popup_x_y;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
- int use_pos_func = ! for_click;
+ bool use_pos_func = ! for_click;
#ifdef HAVE_GTK3
/* Always use position function for Gtk3. Otherwise menus may become
@@ -1450,7 +1441,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
#endif
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
xg_crazy_callback_abort = 1;
menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
@@ -1533,9 +1524,9 @@ pop_down_menu (Lisp_Object arg)
LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
| XINT (XCDR (arg)));
- BLOCK_INPUT;
+ block_input ();
lw_destroy_all_widgets (id);
- UNBLOCK_INPUT;
+ unblock_input ();
popup_activated_flag = 0;
return Qnil;
@@ -1546,7 +1537,7 @@ pop_down_menu (Lisp_Object arg)
menu_item_selection will be set to the selection. */
static void
create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
- int x, int y, int for_click, Time timestamp)
+ int x, int y, bool for_click, Time timestamp)
{
int i;
Arg av[2];
@@ -1557,7 +1548,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
Widget menu;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
#ifdef USE_LUCID
apply_systemfont_to_menu (f, f->output_data.x->widget);
@@ -1630,7 +1621,7 @@ cleanup_widget_value_tree (Lisp_Object arg)
}
Lisp_Object
-xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
Lisp_Object title, const char **error_name, Time timestamp)
{
int i;
@@ -1646,7 +1637,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
*error_name = NULL;
@@ -1792,7 +1783,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
else if (EQ (type, QCradio))
wv->button_type = BUTTON_TYPE_RADIO;
else
- abort ();
+ emacs_abort ();
wv->selected = !NILP (selected);
@@ -1885,7 +1876,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == aref_addr (menu_items, i))
{
- if (keymaps != 0)
+ if (keymaps)
{
int j;
@@ -1930,7 +1921,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
GtkWidget *menu;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
G_CALLBACK (dialog_selection_callback),
@@ -1961,9 +1952,9 @@ dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
if ((intptr_t) client_data != -1)
menu_item_selection = (Lisp_Object *) client_data;
- BLOCK_INPUT;
+ block_input ();
lw_destroy_all_widgets (id);
- UNBLOCK_INPUT;
+ unblock_input ();
popup_activated_flag = 0;
}
@@ -1977,7 +1968,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
LWLIB_ID dialog_id;
if (!FRAME_X_P (f))
- abort ();
+ emacs_abort ();
dialog_id = widget_id_tick++;
#ifdef USE_LUCID
@@ -2018,7 +2009,7 @@ static const char * button_names [] = {
static Lisp_Object
xdialog_show (FRAME_PTR f,
- int keymaps,
+ bool keymaps,
Lisp_Object title,
Lisp_Object header,
const char **error_name)
@@ -2036,7 +2027,7 @@ xdialog_show (FRAME_PTR f,
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
*error_name = NULL;
@@ -2257,7 +2248,7 @@ pop_down_menu (Lisp_Object arg)
FRAME_PTR f = p1->pointer;
XMenu *menu = p2->pointer;
- BLOCK_INPUT;
+ block_input ();
#ifndef MSDOS
XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
@@ -2277,14 +2268,14 @@ pop_down_menu (Lisp_Object arg)
#endif /* HAVE_X_WINDOWS */
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
Lisp_Object
-xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
Lisp_Object title, const char **error_name, Time timestamp)
{
Window root;
@@ -2301,7 +2292,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
- abort ();
+ emacs_abort ();
*error_name = 0;
if (menu_items_n_panes == 0)
@@ -2535,7 +2526,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
{
entry
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
- if (keymaps != 0)
+ if (keymaps)
{
entry = Fcons (entry, Qnil);
if (!NILP (pane_prefix))
diff --git a/src/xml.c b/src/xml.c
index 7bc6130b8b1..a0c4fe17fc4 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_LIBXML2
-#include <setjmp.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/HTMLparser.h>
@@ -74,7 +73,7 @@ libxml2_loaded_p (void)
#define fn_xmlCleanupParser xmlCleanupParser
#define fn_xmlCheckVersion xmlCheckVersion
-static inline int
+static int
libxml2_loaded_p (void)
{
return 1;
@@ -83,7 +82,7 @@ libxml2_loaded_p (void)
#endif /* !WINDOWSNT */
static int
-init_libxml2_functions (Lisp_Object libraries)
+init_libxml2_functions (void)
{
#ifdef WINDOWSNT
if (libxml2_loaded_p ())
@@ -92,7 +91,7 @@ init_libxml2_functions (Lisp_Object libraries)
{
HMODULE library;
- if (!(library = w32_delayed_load (libraries, Qlibxml2_dll)))
+ if (!(library = w32_delayed_load (Qlibxml2_dll)))
{
message ("%s", "libxml2 library not found");
return 0;
@@ -258,7 +257,7 @@ DEFUN ("libxml-parse-html-region", Flibxml_parse_html_region,
If BASE-URL is non-nil, it is used to expand relative URLs. */)
(Lisp_Object start, Lisp_Object end, Lisp_Object base_url)
{
- if (init_libxml2_functions (Vdynamic_library_alist))
+ if (init_libxml2_functions ())
return parse_region (start, end, base_url, 1);
return Qnil;
}
@@ -270,7 +269,7 @@ DEFUN ("libxml-parse-xml-region", Flibxml_parse_xml_region,
If BASE-URL is non-nil, it is used to expand relative URLs. */)
(Lisp_Object start, Lisp_Object end, Lisp_Object base_url)
{
- if (init_libxml2_functions (Vdynamic_library_alist))
+ if (init_libxml2_functions ())
return parse_region (start, end, base_url, 0);
return Qnil;
}
diff --git a/src/xrdb.c b/src/xrdb.c
index 624bafa5e92..59b0876ebf8 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -24,9 +24,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <errno.h>
#include <epaths.h>
-
+#include <stdlib.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
@@ -42,21 +41,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
-#include <sys/stat.h>
#ifdef USE_MOTIF
/* For Vdouble_click_time. */
#include "keyboard.h"
#endif
-extern char *getenv (const char *);
-
-extern struct passwd *getpwuid (uid_t);
-extern struct passwd *getpwnam (const char *);
-
char *x_get_string_resource (XrmDatabase rdb, const char *name,
const char *class);
-static int file_p (const char *filename);
/* X file search path processing. */
@@ -114,7 +106,7 @@ x_get_customization_string (XrmDatabase db, const char *name,
database associated with display.
(This is x_customization_string.)
- Return the expanded file name if it exists and is readable, and
+ Return the resource database if its file was read successfully, and
refers to %L only when the LANG environment variable is set, or
otherwise provided by X.
@@ -123,10 +115,11 @@ x_get_customization_string (XrmDatabase db, const char *name,
Return NULL otherwise. */
-static char *
-magic_file_p (const char *string, ptrdiff_t string_len, const char *class,
- const char *escaped_suffix)
+static XrmDatabase
+magic_db (const char *string, ptrdiff_t string_len, const char *class,
+ const char *escaped_suffix)
{
+ XrmDatabase db;
char *lang = getenv ("LANG");
ptrdiff_t path_size = 100;
@@ -223,14 +216,9 @@ magic_file_p (const char *string, ptrdiff_t string_len, const char *class,
}
path[path_len] = '\0';
-
- if (! file_p (path))
- {
- xfree (path);
- return NULL;
- }
-
- return path;
+ db = XrmGetFileDatabase (path);
+ xfree (path);
+ return db;
}
@@ -264,22 +252,11 @@ gethomedir (void)
}
-static int
-file_p (const char *filename)
-{
- struct stat status;
-
- return (access (filename, 4) == 0 /* exists and is readable */
- && stat (filename, &status) == 0 /* get the status */
- && (S_ISDIR (status.st_mode)) == 0); /* not a directory */
-}
-
-
/* Find the first element of SEARCH_PATH which exists and is readable,
after expanding the %-escapes. Return 0 if we didn't find any, and
the path name of the one we found otherwise. */
-static char *
+static XrmDatabase
search_magic_path (const char *search_path, const char *class,
const char *escaped_suffix)
{
@@ -292,18 +269,16 @@ search_magic_path (const char *search_path, const char *class,
if (p > s)
{
- char *path = magic_file_p (s, p - s, class, escaped_suffix);
- if (path)
- return path;
+ XrmDatabase db = magic_db (s, p - s, class, escaped_suffix);
+ if (db)
+ return db;
}
else if (*p == ':')
{
- char *path;
-
- s = "%N%S";
- path = magic_file_p (s, strlen (s), class, escaped_suffix);
- if (path)
- return path;
+ static char const ns[] = "%N%S";
+ XrmDatabase db = magic_db (ns, strlen (ns), class, escaped_suffix);
+ if (db)
+ return db;
}
if (*p == ':')
@@ -318,21 +293,12 @@ search_magic_path (const char *search_path, const char *class,
static XrmDatabase
get_system_app (const char *class)
{
- XrmDatabase db = NULL;
const char *path;
- char *p;
path = getenv ("XFILESEARCHPATH");
if (! path) path = PATH_X_DEFAULTS;
- p = search_magic_path (path, class, 0);
- if (p)
- {
- db = XrmGetFileDatabase (p);
- xfree (p);
- }
-
- return db;
+ return search_magic_path (path, class, 0);
}
@@ -346,35 +312,40 @@ get_fallback (Display *display)
static XrmDatabase
get_user_app (const char *class)
{
+ XrmDatabase db = 0;
const char *path;
- char *file = 0;
- char *free_it = 0;
/* Check for XUSERFILESEARCHPATH. It is a path of complete file
names, not directories. */
- if (((path = getenv ("XUSERFILESEARCHPATH"))
- && (file = search_magic_path (path, class, 0)))
+ path = getenv ("XUSERFILESEARCHPATH");
+ if (path)
+ db = search_magic_path (path, class, 0);
+ if (! db)
+ {
/* Check for APPLRESDIR; it is a path of directories. In each,
we have to search for LANG/CLASS and then CLASS. */
- || ((path = getenv ("XAPPLRESDIR"))
- && ((file = search_magic_path (path, class, "/%L/%N"))
- || (file = search_magic_path (path, class, "/%N"))))
+ path = getenv ("XAPPLRESDIR");
+ if (path)
+ {
+ db = search_magic_path (path, class, "/%L/%N");
+ if (!db)
+ db = search_magic_path (path, class, "/%N");
+ }
+ }
+ if (! db)
+ {
/* Check in the home directory. This is a bit of a hack; let's
hope one's home directory doesn't contain any %-escapes. */
- || (free_it = gethomedir (),
- ((file = search_magic_path (free_it, class, "%L/%N"))
- || (file = search_magic_path (free_it, class, "%N")))))
- {
- XrmDatabase db = XrmGetFileDatabase (file);
- xfree (file);
- xfree (free_it);
- return db;
+ char *home = gethomedir ();
+ db = search_magic_path (home, class, "%L/%N");
+ if (! db)
+ db = search_magic_path (home, class, "%N");
+ xfree (home);
}
- xfree (free_it);
- return NULL;
+ return db;
}
@@ -430,8 +401,9 @@ get_environ_db (void)
{
static char const xdefaults[] = ".Xdefaults-";
char *home = gethomedir ();
- char const *host = get_system_name ();
- ptrdiff_t pathsize = strlen (home) + sizeof xdefaults + strlen (host);
+ 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;
diff --git a/src/xselect.c b/src/xselect.c
index 463bd6e37b0..64c64fa0c76 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <limits.h>
#include <stdio.h> /* termhooks.h needs this */
-#include <setjmp.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -193,7 +192,7 @@ static void
x_start_queuing_selection_requests (void)
{
if (x_queue_selection_requests)
- abort ();
+ emacs_abort ();
x_queue_selection_requests++;
TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests);
@@ -245,12 +244,12 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym)
if (EQ (sym, QEMACS_TMP)) return dpyinfo->Xatom_EMACS_TMP;
if (EQ (sym, QTARGETS)) return dpyinfo->Xatom_TARGETS;
if (EQ (sym, QNULL)) return dpyinfo->Xatom_NULL;
- if (!SYMBOLP (sym)) abort ();
+ if (!SYMBOLP (sym)) emacs_abort ();
TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym)));
- BLOCK_INPUT;
+ block_input ();
val = XInternAtom (dpyinfo->display, SSDATA (SYMBOL_NAME (sym)), False);
- UNBLOCK_INPUT;
+ unblock_input ();
return val;
}
@@ -308,16 +307,16 @@ x_atom_to_symbol (Display *dpy, Atom atom)
if (atom == dpyinfo->Xatom_NULL)
return QNULL;
- BLOCK_INPUT;
+ block_input ();
str = XGetAtomName (dpy, atom);
- UNBLOCK_INPUT;
+ unblock_input ();
TRACE1 ("XGetAtomName --> %s", str);
if (! str) return Qnil;
val = intern (str);
- BLOCK_INPUT;
+ block_input ();
/* This was allocated by Xlib, so use XFree. */
XFree (str);
- UNBLOCK_INPUT;
+ unblock_input ();
return val;
}
@@ -337,12 +336,12 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
Time timestamp = last_event_timestamp;
Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_name);
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (display);
XSetSelectionOwner (display, selection_atom, selecting_window, timestamp);
x_check_errors (display, "Can't set selection: %s");
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
/* Now update the local cache */
{
@@ -470,12 +469,12 @@ x_decline_selection_request (struct input_event *event)
/* The reason for the error may be that the receiver has
died in the meantime. Handle that case. */
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (reply->display);
XSendEvent (reply->display, reply->requestor, False, 0L, &reply_base);
XFlush (reply->display);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* This is the selection request currently being processed.
@@ -537,9 +536,9 @@ x_selection_request_lisp_error (Lisp_Object ignore)
static Lisp_Object
x_catch_errors_unwind (Lisp_Object dummy)
{
- BLOCK_INPUT;
+ block_input ();
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
@@ -611,7 +610,7 @@ x_reply_selection_request (struct input_event *event,
if (reply->property == None)
reply->property = reply->target;
- BLOCK_INPUT;
+ block_input ();
/* The protected block contains wait_for_property_change, which can
run random lisp code (process handlers) or signal. Therefore, we
put the x_uncatch_errors call in an unwind. */
@@ -683,7 +682,7 @@ x_reply_selection_request (struct input_event *event,
{
int format_bytes = cs->format / 8;
int had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
+ unblock_input ();
bytes_remaining = cs->size;
bytes_remaining *= format_bytes;
@@ -704,7 +703,7 @@ x_reply_selection_request (struct input_event *event,
int i = ((bytes_remaining < max_bytes)
? bytes_remaining
: max_bytes) / format_bytes;
- BLOCK_INPUT;
+ block_input ();
cs->wait_object
= expect_property_change (display, window, cs->property,
@@ -723,7 +722,7 @@ x_reply_selection_request (struct input_event *event,
: format_bytes);
XFlush (display);
had_errors = x_had_errors_p (display);
- UNBLOCK_INPUT;
+ unblock_input ();
if (had_errors) break;
@@ -736,7 +735,7 @@ x_reply_selection_request (struct input_event *event,
/* Now write a zero-length chunk to the property to tell the
requestor that we're done. */
- BLOCK_INPUT;
+ block_input ();
if (! waiting_for_other_props_on_window (display, window))
XSelectInput (display, window, 0L);
@@ -758,15 +757,15 @@ x_reply_selection_request (struct input_event *event,
/* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are
delivered before uncatch errors. */
XSync (display, False);
- UNBLOCK_INPUT;
+ unblock_input ();
/* GTK queues events in addition to the queue in Xlib. So we
UNBLOCK to enter the event loop and get possible errors delivered,
and then BLOCK again because x_uncatch_errors requires it. */
- BLOCK_INPUT;
+ block_input ();
/* This calls x_uncatch_errors. */
unbind_to (count, Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Handle a SelectionRequest event EVENT.
@@ -1138,7 +1137,7 @@ wait_for_property_change (struct prop_location *location)
ptrdiff_t count = SPECPDL_INDEX ();
if (property_change_reply_object)
- abort ();
+ emacs_abort ();
/* Make sure to do unexpect_property_change if we quit or err. */
record_unwind_protect (wait_for_property_change_unwind,
@@ -1233,7 +1232,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
if (! NILP (time_stamp))
CONS_TO_INTEGER (time_stamp, Time, requestor_time);
- BLOCK_INPUT;
+ block_input ();
TRACE2 ("Get selection %s, type %s",
XGetAtomName (display, type_atom),
XGetAtomName (display, target_property));
@@ -1258,7 +1257,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
record_unwind_protect (queue_selection_requests_unwind, Qnil);
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
/* This allows quits. Also, don't wait forever. */
timeout = max (0, x_selection_timeout);
@@ -1310,7 +1309,7 @@ x_get_window_property (Display *display, Window window, Atom property,
? min (PTRDIFF_MAX, SIZE_MAX) - 1
: LONG_MAX * x_long_size);
- BLOCK_INPUT;
+ block_input ();
/* First probe the thing to find out how big it is. */
result = XGetWindowProperty (display, window, property,
@@ -1411,19 +1410,19 @@ x_get_window_property (Display *display, Window window, Atom property,
data[offset] = '\0';
done:
- UNBLOCK_INPUT;
+ unblock_input ();
*data_ret = data;
*bytes_ret = offset;
return;
size_overflow:
free (data);
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (SIZE_MAX);
memory_exhausted:
free (data);
- UNBLOCK_INPUT;
+ unblock_input ();
memory_full (total_size + 1);
}
@@ -1455,7 +1454,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
that property, then reading the property, then deleting it to ack.
We are done when the sender places a property of length 0.
*/
- BLOCK_INPUT;
+ block_input ();
XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
TRACE1 (" Delete property %s",
SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
@@ -1465,7 +1464,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
wait_object = expect_property_change (display, window, property,
PropertyNewValue);
XFlush (display);
- UNBLOCK_INPUT;
+ unblock_input ();
while (1)
{
@@ -1497,14 +1496,14 @@ receive_incremental_selection (Display *display, Window window, Atom property,
break;
}
- BLOCK_INPUT;
+ block_input ();
TRACE1 (" ACK by deleting property %s",
XGetAtomName (display, property));
XDeleteProperty (display, window, property);
wait_object = expect_property_change (display, window, property,
PropertyNewValue);
XFlush (display);
- UNBLOCK_INPUT;
+ unblock_input ();
if (*size_bytes_ret - offset < tmp_size_bytes)
*data_ret = xpalloc (*data_ret, size_bytes_ret,
@@ -1546,10 +1545,10 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
if (! data)
{
int there_is_a_selection_owner;
- BLOCK_INPUT;
+ block_input ();
there_is_a_selection_owner
= XGetSelectionOwner (display, selection_atom);
- UNBLOCK_INPUT;
+ unblock_input ();
if (there_is_a_selection_owner)
signal_error ("Selection owner couldn't convert",
actual_type
@@ -1566,22 +1565,22 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
/* That wasn't really the data, just the beginning. */
unsigned int min_size_bytes = * ((unsigned int *) data);
- BLOCK_INPUT;
+ block_input ();
/* Use xfree, not XFree, because x_get_window_property
calls xmalloc itself. */
xfree (data);
- UNBLOCK_INPUT;
+ unblock_input ();
receive_incremental_selection (display, window, property, target_type,
min_size_bytes, &data, &bytes,
&actual_type, &actual_format,
&actual_size);
}
- BLOCK_INPUT;
+ block_input ();
TRACE1 (" Delete property %s", XGetAtomName (display, property));
XDeleteProperty (display, window, property);
XFlush (display);
- UNBLOCK_INPUT;
+ unblock_input ();
/* It's been read. Now convert it to a lisp object in some semi-rational
manner. */
@@ -1941,7 +1940,7 @@ x_handle_selection_notify (XSelectionEvent *event)
static struct frame *
frame_for_x_selection (Lisp_Object object)
{
- Lisp_Object tail;
+ Lisp_Object tail, frame;
struct frame *f;
if (NILP (object))
@@ -1950,9 +1949,9 @@ frame_for_x_selection (Lisp_Object object)
if (FRAME_X_P (f) && FRAME_LIVE_P (f))
return f;
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- f = XFRAME (XCAR (tail));
+ f = XFRAME (frame);
if (FRAME_X_P (f) && FRAME_LIVE_P (f))
return f;
}
@@ -1960,15 +1959,14 @@ frame_for_x_selection (Lisp_Object object)
else if (TERMINALP (object))
{
struct terminal *t = get_terminal (object, 1);
+
if (t->type == output_x_window)
- {
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- f = XFRAME (XCAR (tail));
- if (FRAME_LIVE_P (f) && f->terminal == t)
- return f;
- }
- }
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+ if (FRAME_LIVE_P (f) && f->terminal == t)
+ return f;
+ }
}
else if (FRAMEP (object))
{
@@ -2097,13 +2095,13 @@ On MS-DOS, all this does is return non-nil if we own the selection. */)
selection_atom = symbol_to_x_atom (dpyinfo, selection);
- BLOCK_INPUT;
+ block_input ();
if (NILP (time_object))
timestamp = last_event_timestamp;
else
CONS_TO_INTEGER (time_object, Time, timestamp);
XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp);
- UNBLOCK_INPUT;
+ unblock_input ();
/* It doesn't seem to be guaranteed that a SelectionClear event will be
generated for a window which owns the selection when that window sets
@@ -2180,9 +2178,9 @@ On Nextstep, TERMINAL is unused. */)
atom = symbol_to_x_atom (dpyinfo, selection);
if (atom == 0) return Qnil;
- BLOCK_INPUT;
+ block_input ();
owner = XGetSelectionOwner (dpyinfo->display, atom);
- UNBLOCK_INPUT;
+ unblock_input ();
return (owner ? Qt : Qnil);
}
@@ -2354,9 +2352,9 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
val = cons_to_signed (o, LONG_MIN, LONG_MAX);
else if (STRINGP (o))
{
- BLOCK_INPUT;
+ block_input ();
val = (long) XInternAtom (dpy, SSDATA (o), False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
error ("Wrong type, must be string, number or cons");
@@ -2414,7 +2412,7 @@ mouse_position_for_drop (FRAME_PTR f, int *x, int *y)
Window root, dummy_window;
int dummy;
- BLOCK_INPUT;
+ block_input ();
XQueryPointer (FRAME_X_DISPLAY (f),
DefaultRootWindow (FRAME_X_DISPLAY (f)),
@@ -2440,7 +2438,7 @@ mouse_position_for_drop (FRAME_PTR f, int *x, int *y)
*x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
*y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
DEFUN ("x-get-atom-name", Fx_get_atom_name,
@@ -2463,7 +2461,7 @@ If the value is 0 or the atom is not known, return the empty string. */)
CONS_TO_INTEGER (value, Atom, atom);
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpy);
name = atom ? XGetAtomName (dpy, atom) : empty;
had_errors = x_had_errors_p (dpy);
@@ -2475,7 +2473,7 @@ If the value is 0 or the atom is not known, return the empty string. */)
if (atom && name) XFree (name);
if (NILP (ret)) ret = empty_unibyte_string;
- UNBLOCK_INPUT;
+ unblock_input ();
return ret;
}
@@ -2497,9 +2495,9 @@ FRAME is on. If FRAME is nil, the selected frame is used. */)
x_atom = symbol_to_x_atom (dpyinfo, atom);
else if (STRINGP (atom))
{
- BLOCK_INPUT;
+ block_input ();
x_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (atom), False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
else
error ("ATOM must be a symbol or a string");
@@ -2658,7 +2656,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
if (wdest == 0) wdest = dpyinfo->root_window;
to_root = wdest == dpyinfo->root_window;
- BLOCK_INPUT;
+ block_input ();
event.xclient.message_type = message_type;
event.xclient.display = dpyinfo->display;
@@ -2684,7 +2682,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
XFlush (dpyinfo->display);
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
}
diff --git a/src/xsettings.c b/src/xsettings.c
index a28d75d9422..d23070791d8 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <float.h>
#include <limits.h>
-#include <setjmp.h>
#include <fcntl.h>
#include "lisp.h"
#include "xterm.h"
@@ -30,7 +29,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "blockinput.h"
#include "termhooks.h"
-#include "termopts.h"
#include <X11/Xproto.h>
@@ -711,12 +709,12 @@ apply_xft_settings (struct x_display_info *dpyinfo,
if (send_event_p)
store_config_changed_event (Qfont_render,
XCAR (dpyinfo->name_list_element));
- Vxft_settings
+ Vxft_settings
= make_formatted_string (buf, format,
oldsettings.aa, oldsettings.hinting,
oldsettings.rgba, oldsettings.lcdfilter,
oldsettings.hintstyle, oldsettings.dpi);
-
+
}
else
FcPatternDestroy (pat);
@@ -930,7 +928,7 @@ init_xsettings (struct x_display_info *dpyinfo)
{
Display *dpy = dpyinfo->display;
- BLOCK_INPUT;
+ block_input ();
/* Select events so we can detect client messages sent when selection
owner changes. */
@@ -940,7 +938,7 @@ init_xsettings (struct x_display_info *dpyinfo)
if (dpyinfo->xsettings_window != None)
read_and_apply_settings (dpyinfo, False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
void
diff --git a/src/xsmfns.c b/src/xsmfns.c
index cddbb2aae86..289aac8492b 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -29,14 +29,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <sys/param.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "systime.h"
#include "sysselect.h"
#include "frame.h"
#include "termhooks.h"
-#include "termopts.h"
#include "xterm.h"
#include "process.h"
#include "keyboard.h"
diff --git a/src/xterm.c b/src/xterm.c
index f497b5322bf..374b6287458 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -21,17 +21,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Xt features made by Fred Pierresteguy. */
#include <config.h>
-#include <signal.h>
#include <stdio.h>
-#include <setjmp.h>
#ifdef HAVE_X_WINDOWS
#include "lisp.h"
#include "blockinput.h"
-
-/* Need syssignal.h for various externs and definitions that may be required
- by some configurations for calls to signal later in this source file. */
#include "syssignal.h"
/* This may include sys/types.h, and that somehow loses
@@ -51,7 +46,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <fcntl.h>
#include <errno.h>
-#include <setjmp.h>
#include <sys/stat.h>
/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
/* #include <sys/param.h> */
@@ -293,7 +287,7 @@ enum xembed_message
/* Used in x_flush. */
-static int x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
+static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
static void x_set_window_size_1 (struct frame *, int, int, int);
static void x_raise_frame (struct frame *);
static void x_lower_frame (struct frame *);
@@ -359,7 +353,7 @@ x_flush (struct frame *f)
if (!NILP (Vinhibit_redisplay))
return;
- BLOCK_INPUT;
+ block_input ();
if (f == NULL)
{
Lisp_Object rest, frame;
@@ -369,7 +363,7 @@ x_flush (struct frame *f)
}
else if (FRAME_X_P (f))
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -570,7 +564,7 @@ x_update_window_begin (struct window *w)
updated_window = w;
set_output_cursor (&w->cursor);
- BLOCK_INPUT;
+ block_input ();
if (f == hlinfo->mouse_face_mouse_frame)
{
@@ -583,7 +577,7 @@ x_update_window_begin (struct window *w)
hlinfo->mouse_face_window = Qnil;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -624,7 +618,7 @@ x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritt
if (!w->pseudo_window_p)
{
- BLOCK_INPUT;
+ block_input ();
if (cursor_on_p)
display_and_set_cursor (w, 1, output_cursor.hpos,
@@ -634,7 +628,7 @@ x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritt
if (draw_window_fringes (w, 1))
x_draw_vertical_border (w);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* If a row with mouse-face was overwritten, arrange for
@@ -660,9 +654,9 @@ x_update_end (struct frame *f)
MOUSE_HL_INFO (f)->mouse_face_defer = 0;
#ifndef XFlush
- BLOCK_INPUT;
+ block_input ();
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
#endif
}
@@ -675,21 +669,7 @@ static void
XTframe_up_to_date (struct frame *f)
{
if (FRAME_X_P (f))
- {
- Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-
- if (hlinfo->mouse_face_deferred_gc
- || f == hlinfo->mouse_face_mouse_frame)
- {
- BLOCK_INPUT;
- if (hlinfo->mouse_face_mouse_frame)
- note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
- hlinfo->mouse_face_mouse_x,
- hlinfo->mouse_face_mouse_y);
- hlinfo->mouse_face_deferred_gc = 0;
- UNBLOCK_INPUT;
- }
- }
+ FRAME_MOUSE_UPDATE (f);
}
@@ -728,13 +708,13 @@ x_after_update_window_line (struct glyph_row *desired_row)
{
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
- BLOCK_INPUT;
+ block_input ();
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
0, y, width, height, False);
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
FRAME_PIXEL_WIDTH (f) - width,
y, width, height, False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -905,8 +885,8 @@ static void x_compute_glyph_string_overhangs (struct glyph_string *);
static void x_set_cursor_gc (struct glyph_string *);
static void x_set_mode_line_face_gc (struct glyph_string *);
static void x_set_mouse_face_gc (struct glyph_string *);
-static int x_alloc_lighter_color (struct frame *, Display *, Colormap,
- unsigned long *, double, int);
+static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
+ unsigned long *, double, int);
static void x_setup_relief_color (struct frame *, struct relief *,
double, int, unsigned long);
static void x_setup_relief_colors (struct glyph_string *);
@@ -1033,7 +1013,7 @@ x_set_mouse_face_gc (struct glyph_string *s)
Faces to use in the mode line have already been computed when the
matrix was built, so there isn't much to do, here. */
-static inline void
+static void
x_set_mode_line_face_gc (struct glyph_string *s)
{
s->gc = s->face->gc;
@@ -1044,7 +1024,7 @@ x_set_mode_line_face_gc (struct glyph_string *s)
S->stippled_p to a non-zero value if the face of S has a stipple
pattern. */
-static inline void
+static void
x_set_glyph_string_gc (struct glyph_string *s)
{
PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
@@ -1089,7 +1069,7 @@ x_set_glyph_string_gc (struct glyph_string *s)
/* Set clipping for output of glyph string S. S may be part of a mode
line or menu if we don't have X toolkit support. */
-static inline void
+static void
x_set_glyph_string_clipping (struct glyph_string *s)
{
XRectangle *r = s->clip;
@@ -1162,7 +1142,7 @@ x_compute_glyph_string_overhangs (struct glyph_string *s)
/* Fill rectangle X, Y, W, H with background color of glyph string S. */
-static inline void
+static void
x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
{
XGCValues xgcv;
@@ -1444,7 +1424,7 @@ static struct frame *
x_frame_of_widget (Widget widget)
{
struct x_display_info *dpyinfo;
- Lisp_Object tail;
+ Lisp_Object tail, frame;
struct frame *f;
dpyinfo = x_display_info_for_display (XtDisplay (widget));
@@ -1458,16 +1438,16 @@ x_frame_of_widget (Widget widget)
/* Look for a frame with that top-level widget. Allocate the color
on that frame to get the right gamma correction value. */
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- if (FRAMEP (XCAR (tail))
- && (f = XFRAME (XCAR (tail)),
- (FRAME_X_P (f)
- && f->output_data.nothing != 1
- && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
- && f->output_data.x->widget == widget)
- return f;
-
- abort ();
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+ if (FRAME_X_P (f)
+ && f->output_data.nothing != 1
+ && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+ && f->output_data.x->widget == widget)
+ return f;
+ }
+ emacs_abort ();
}
/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
@@ -1475,9 +1455,9 @@ x_frame_of_widget (Widget widget)
If this produces the same color as PIXEL, try a color where all RGB
values have DELTA added. Return the allocated color in *PIXEL.
DISPLAY is the X display, CMAP is the colormap to operate on.
- Value is non-zero if successful. */
+ Value is true if successful. */
-int
+bool
x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
unsigned long *pixel, double factor, int delta)
{
@@ -1702,15 +1682,15 @@ x_query_color (struct frame *f, XColor *color)
/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
exact match can't be allocated, try the nearest color available.
- Value is non-zero if successful. Set *COLOR to the color
+ Value is true if successful. Set *COLOR to the color
allocated. */
-static int
+static bool
x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
{
- int rc;
+ bool rc;
- rc = XAllocColor (dpy, cmap, color);
+ rc = XAllocColor (dpy, cmap, color) != 0;
if (rc == 0)
{
/* If we got to this point, the colormap is full, so we're going
@@ -1741,7 +1721,7 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
color->red = cells[nearest].red;
color->green = cells[nearest].green;
color->blue = cells[nearest].blue;
- rc = XAllocColor (dpy, cmap, color);
+ rc = XAllocColor (dpy, cmap, color) != 0;
}
else
{
@@ -1774,10 +1754,10 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
/* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
exact match can't be allocated, try the nearest color available.
- Value is non-zero if successful. Set *COLOR to the color
+ Value is true if successful. Set *COLOR to the color
allocated. */
-int
+bool
x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
{
gamma_correct (f, color);
@@ -1795,10 +1775,10 @@ x_copy_color (struct frame *f, long unsigned int pixel)
XColor color;
color.pixel = pixel;
- BLOCK_INPUT;
+ block_input ();
x_query_color (f, &color);
XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
- UNBLOCK_INPUT;
+ unblock_input ();
#ifdef DEBUG_X_COLORS
register_color (pixel);
#endif
@@ -1827,12 +1807,12 @@ x_copy_color (struct frame *f, long unsigned int pixel)
DISPLAY is the X display, CMAP is the colormap to operate on.
Value is non-zero if successful. */
-static int
+static bool
x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
{
XColor color, new;
long bright;
- int success_p;
+ bool success_p;
/* Get RGB color values. */
color.pixel = *pixel;
@@ -2039,7 +2019,8 @@ x_draw_relief_rect (struct frame *f,
for (i = (width > 1 ? 1 : 0); i < width; ++i)
XDrawLine (dpy, window, gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
+ left_x + i, top_y + (i + 1) * top_p,
+ left_x + i, bottom_y + 1 - (i + 1) * bot_p);
}
XSetClipMask (dpy, gc, None);
@@ -2081,7 +2062,8 @@ x_draw_relief_rect (struct frame *f,
XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
for (i = 0; i < width; ++i)
XDrawLine (dpy, window, gc,
- right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
+ right_x - i, top_y + (i + 1) * top_p,
+ right_x - i, bottom_y + 1 - (i + 1) * bot_p);
}
XSetClipMask (dpy, gc, None);
@@ -2275,8 +2257,7 @@ x_draw_image_foreground (struct glyph_string *s)
static void
x_draw_image_relief (struct glyph_string *s)
{
- int x0, y0, x1, y1, thick, raised_p;
- int extra_x, extra_y;
+ int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
XRectangle r;
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
@@ -2307,33 +2288,23 @@ x_draw_image_relief (struct glyph_string *s)
raised_p = s->img->relief > 0;
}
- extra_x = extra_y = 0;
- if (s->face->id == TOOL_BAR_FACE_ID)
- {
- if (CONSP (Vtool_bar_button_margin)
- && INTEGERP (XCAR (Vtool_bar_button_margin))
- && INTEGERP (XCDR (Vtool_bar_button_margin)))
- {
- extra_x = XINT (XCAR (Vtool_bar_button_margin));
- extra_y = XINT (XCDR (Vtool_bar_button_margin));
- }
- else if (INTEGERP (Vtool_bar_button_margin))
- extra_x = extra_y = XINT (Vtool_bar_button_margin);
- }
+ x1 = x + s->slice.width - 1;
+ y1 = y + s->slice.height - 1;
+ top_p = bot_p = left_p = right_p = 0;
- x0 = x - thick - extra_x;
- y0 = y - thick - extra_y;
- x1 = x + s->slice.width + thick - 1 + extra_x;
- y1 = y + s->slice.height + thick - 1 + extra_y;
+ if (s->slice.x == 0)
+ x -= thick, left_p = 1;
+ if (s->slice.y == 0)
+ y -= thick, top_p = 1;
+ if (s->slice.x + s->slice.width == s->img->width)
+ x1 += thick, right_p = 1;
+ if (s->slice.y + s->slice.height == s->img->height)
+ y1 += thick, bot_p = 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
- x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
- s->slice.y == 0,
- s->slice.y + s->slice.height == s->img->height,
- s->slice.x == 0,
- s->slice.x + s->slice.width == s->img->width,
- &r);
+ x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+ top_p, bot_p, left_p, right_p, &r);
}
@@ -2696,7 +2667,7 @@ x_draw_underwave (struct glyph_string *s)
y2 += dy;
if (INT_MAX - dx < xmax)
- abort ();
+ emacs_abort ();
while (x1 <= xmax)
{
@@ -2805,7 +2776,7 @@ x_draw_glyph_string (struct glyph_string *s)
break;
default:
- abort ();
+ emacs_abort ();
}
if (!s->for_overlaps)
@@ -2979,6 +2950,7 @@ x_draw_glyph_string (struct glyph_string *s)
XSetClipMask (next->display, next->gc, None);
next->hl = save;
next->num_clips = 0;
+ next->clip_head = s->next;
}
}
}
@@ -3005,7 +2977,7 @@ x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height,
static void
x_delete_glyphs (struct frame *f, register int n)
{
- abort ();
+ emacs_abort ();
}
@@ -3033,7 +3005,7 @@ x_clear_frame (struct frame *f)
/* We don't set the output cursor here because there will always
follow an explicit cursor_to. */
- BLOCK_INPUT;
+ block_input ();
XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
@@ -3050,7 +3022,7 @@ x_clear_frame (struct frame *f)
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3060,7 +3032,7 @@ x_clear_frame (struct frame *f)
static void
XTflash (struct frame *f)
{
- BLOCK_INPUT;
+ block_input ();
{
#ifdef USE_GTK
@@ -3213,14 +3185,14 @@ XTflash (struct frame *f)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
static void
XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
{
- BLOCK_INPUT;
+ block_input ();
if (invisible)
{
if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0)
@@ -3231,7 +3203,7 @@ XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->current_cursor);
f->pointer_invisible = invisible;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3246,10 +3218,10 @@ XTring_bell (struct frame *f)
XTflash (f);
else
{
- BLOCK_INPUT;
+ block_input ();
XBell (FRAME_X_DISPLAY (f), 0);
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
}
@@ -3278,7 +3250,7 @@ XTset_terminal_window (struct frame *f, int n)
static void
x_ins_del_lines (struct frame *f, int vpos, int n)
{
- abort ();
+ emacs_abort ();
}
@@ -3346,7 +3318,7 @@ x_scroll_run (struct window *w, struct run *run)
height = run->height;
}
- BLOCK_INPUT;
+ block_input ();
/* Cursor off. Will be switched on again in x_update_window_end. */
updated_window = w;
@@ -3359,7 +3331,7 @@ x_scroll_run (struct window *w, struct run *run)
width, height,
x, to_y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -3376,7 +3348,7 @@ frame_highlight (struct frame *f)
the ICCCM (section 4.1.6) says that the window's border pixmap
and border pixel are window attributes which are "private to the
client", so we can always change it to whatever we want. */
- BLOCK_INPUT;
+ block_input ();
/* I recently started to get errors in this XSetWindowBorder, depending on
the window-manager in use, tho something more is at play since I've been
using that same window-manager binary for ever. Let's not crash just
@@ -3385,7 +3357,7 @@ frame_highlight (struct frame *f)
XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_pixel);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
x_update_cursor (f, 1);
x_set_frame_alpha (f);
}
@@ -3397,13 +3369,13 @@ frame_unhighlight (struct frame *f)
the ICCCM (section 4.1.6) says that the window's border pixmap
and border pixel are window attributes which are "private to the
client", so we can always change it to whatever we want. */
- BLOCK_INPUT;
+ block_input ();
/* Same as above for XSetWindowBorder (bug#9310). */
x_catch_errors (FRAME_X_DISPLAY (f));
XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_tile);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
x_update_cursor (f, 1);
x_set_frame_alpha (f);
}
@@ -3453,7 +3425,8 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
/* Don't stop displaying the initial startup message
for a switch-frame event we don't need. */
- if (NILP (Vterminal_frame)
+ /* When run as a daemon, Vterminal_frame is always NIL. */
+ if ((NILP (Vterminal_frame) || EQ (Fdaemonp(), Qt))
&& CONSP (Vframe_list)
&& !NILP (XCDR (Vframe_list)))
{
@@ -3770,9 +3743,9 @@ x_get_keysym_name (int keysym)
{
char *value;
- BLOCK_INPUT;
+ block_input ();
value = XKeysymToString (keysym);
- UNBLOCK_INPUT;
+ unblock_input ();
return value;
}
@@ -3902,7 +3875,7 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
{
FRAME_PTR f1;
- BLOCK_INPUT;
+ block_input ();
if (! NILP (last_mouse_scroll_bar) && insist == 0)
x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
@@ -4083,7 +4056,7 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -4102,20 +4075,15 @@ XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
static struct scroll_bar *
x_window_to_scroll_bar (Display *display, Window window_id)
{
- Lisp_Object tail;
+ Lisp_Object tail, frame;
#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- Lisp_Object frame, bar, condemned;
-
- frame = XCAR (tail);
- /* All elements of Vframe_list should be frames. */
- if (! FRAMEP (frame))
- abort ();
+ Lisp_Object bar, condemned;
if (! FRAME_X_P (XFRAME (frame)))
continue;
@@ -4147,20 +4115,16 @@ x_window_to_scroll_bar (Display *display, Window window_id)
static Widget
x_window_to_menu_bar (Window window)
{
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- if (FRAME_X_P (XFRAME (XCAR (tail))))
- {
- Lisp_Object frame = XCAR (tail);
- Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+ Lisp_Object tail, frame;
- if (menu_bar && xlwmenu_window_p (menu_bar, window))
- return menu_bar;
- }
- }
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_X_P (XFRAME (frame)))
+ {
+ Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+ if (menu_bar && xlwmenu_window_p (menu_bar, window))
+ return menu_bar;
+ }
return NULL;
}
@@ -4272,7 +4236,7 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
struct frame *f = XFRAME (w->frame);
ptrdiff_t i;
- BLOCK_INPUT;
+ block_input ();
/* Construct a ClientMessage event to send to the frame. */
ev->type = ClientMessage;
@@ -4319,7 +4283,7 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
be sent to the client that created the window, and if that
window no longer exists, no event will be sent. */
XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -4410,9 +4374,9 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
int slider_size;
/* Get the slider size. */
- BLOCK_INPUT;
+ block_input ();
XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
- UNBLOCK_INPUT;
+ unblock_input ();
whole = XM_SB_MAX - slider_size;
portion = min (cs->value, whole);
@@ -4533,9 +4497,9 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
int part;
/* Get the size of the thumb, a value between 0 and 1. */
- BLOCK_INPUT;
+ block_input ();
XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
- UNBLOCK_INPUT;
+ unblock_input ();
whole = 10000000;
portion = shown < 1 ? top * whole : 0;
@@ -4575,9 +4539,9 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
int part;
/* Get the height of the scroll bar. */
- BLOCK_INPUT;
+ block_input ();
XtVaGetValues (widget, XtNheight, &height, NULL);
- UNBLOCK_INPUT;
+ unblock_input ();
if (eabs (position) >= height)
part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
@@ -4608,11 +4572,11 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
{
const char *scroll_bar_name = SCROLL_BAR_NAME;
- BLOCK_INPUT;
+ block_input ();
xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
G_CALLBACK (xg_end_scroll_callback),
scroll_bar_name);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#else /* not USE_GTK */
@@ -4627,7 +4591,7 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
const char *scroll_bar_name = SCROLL_BAR_NAME;
unsigned long pixel;
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_MOTIF
/* Set resources. Create the widget. */
@@ -4811,7 +4775,7 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
xwindow = XtWindow (widget);
bar->x_window = xwindow;
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* not USE_GTK */
@@ -4835,7 +4799,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
float top, shown;
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_MOTIF
@@ -4870,9 +4834,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
/* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
is the scroll bar's maximum and MIN is the scroll bar's minimum
value. */
- size = shown * XM_SB_MAX;
- size = min (size, XM_SB_MAX);
- size = max (size, 1);
+ size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
/* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
value = top * XM_SB_MAX;
@@ -4926,7 +4888,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
}
#endif /* !USE_MOTIF */
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* not USE_GTK */
@@ -4951,7 +4913,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
= ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
Lisp_Object barobj;
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_TOOLKIT_SCROLL_BARS
x_create_toolkit_scroll_bar (f, bar);
@@ -5039,7 +5001,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
- UNBLOCK_INPUT;
+ unblock_input ();
return bar;
}
@@ -5073,7 +5035,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild
&& end == bar->end)
return;
- BLOCK_INPUT;
+ block_input ();
{
int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
@@ -5149,7 +5111,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* !USE_TOOLKIT_SCROLL_BARS */
@@ -5161,7 +5123,7 @@ static void
x_scroll_bar_remove (struct scroll_bar *bar)
{
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_TOOLKIT_SCROLL_BARS
#ifdef USE_GTK
@@ -5176,7 +5138,7 @@ x_scroll_bar_remove (struct scroll_bar *bar)
/* Dissociate this scroll bar from its window. */
wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5244,7 +5206,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
{
if (width > 0 && height > 0)
{
- BLOCK_INPUT;
+ block_input ();
#ifdef USE_TOOLKIT_SCROLL_BARS
if (fringe_extended_p)
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -5253,7 +5215,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
#endif
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
left, top, width, height, False);
- UNBLOCK_INPUT;
+ unblock_input ();
}
bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
@@ -5265,7 +5227,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
bar = XSCROLL_BAR (w->vertical_scroll_bar);
- BLOCK_INPUT;
+ block_input ();
if (sb_left != bar->left)
mask |= CWX;
@@ -5362,7 +5324,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
bar->width = sb_width;
bar->height = height;
- UNBLOCK_INPUT;
+ unblock_input ();
}
#ifdef USE_TOOLKIT_SCROLL_BARS
@@ -5434,7 +5396,7 @@ XTredeem_scroll_bar (struct window *window)
/* We can't redeem this window's scroll bar if it doesn't have one. */
if (NILP (window->vertical_scroll_bar))
- abort ();
+ emacs_abort ();
bar = XSCROLL_BAR (window->vertical_scroll_bar);
@@ -5453,7 +5415,7 @@ XTredeem_scroll_bar (struct window *window)
else
/* If its prev pointer is nil, it must be at the front of
one or the other! */
- abort ();
+ emacs_abort ();
}
else
XSCROLL_BAR (bar->prev)->next = bar->next;
@@ -5513,7 +5475,7 @@ x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
GC gc = f->output_data.x->normal_gc;
int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
- BLOCK_INPUT;
+ block_input ();
x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
@@ -5535,7 +5497,7 @@ x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
XSetForeground (FRAME_X_DISPLAY (f), gc,
FRAME_FOREGROUND_PIXEL (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -5551,7 +5513,7 @@ static void
x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event)
{
if (! WINDOWP (bar->window))
- abort ();
+ emacs_abort ();
emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
emacs_event->code = event->xbutton.button - Button1;
@@ -5648,7 +5610,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
int dummy_coord;
unsigned int dummy_mask;
- BLOCK_INPUT;
+ block_input ();
/* Get the mouse's position relative to the scroll bar window, and
report that. */
@@ -5700,7 +5662,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
*timestamp = last_mouse_movement_time;
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -5821,7 +5783,7 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
{
XEvent *xev = (XEvent *) gxev;
- BLOCK_INPUT;
+ block_input ();
if (current_count >= 0)
{
struct x_display_info *dpyinfo;
@@ -5836,7 +5798,7 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
&& dpyinfo
&& x_filter_event (dpyinfo, xev))
{
- UNBLOCK_INPUT;
+ unblock_input ();
return GDK_FILTER_REMOVE;
}
#endif
@@ -5851,7 +5813,7 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
else
current_finish = x_dispatch_event (xev, xev->xany.display);
- UNBLOCK_INPUT;
+ unblock_input ();
if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
return GDK_FILTER_REMOVE;
@@ -6112,7 +6074,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
- inev.ie.frame_or_window = Qnil;
}
break;
@@ -6132,7 +6093,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
- inev.ie.frame_or_window = Qnil;
}
break;
@@ -6457,7 +6417,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
}
else if (status_return != XLookupKeySym
&& status_return != XLookupBoth)
- abort ();
+ emacs_abort ();
}
else
nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
@@ -7046,10 +7006,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
default:
OTHER:
#ifdef USE_X_TOOLKIT
- BLOCK_INPUT;
+ block_input ();
if (*finish != X_EVENT_DROP)
XtDispatchEvent (&event);
- UNBLOCK_INPUT;
+ unblock_input ();
#endif /* USE_X_TOOLKIT */
break;
}
@@ -7114,45 +7074,24 @@ x_dispatch_event (XEvent *event, Display *display)
/* Read events coming from the X server.
- This routine is called by the SIGIO handler only if SYNC_INPUT is
- not defined.
- We return as soon as there are no more events to be read.
+ Return as soon as there are no more events to be read.
- We return the number of characters stored into the buffer,
+ Return the number of characters stored into the buffer,
thus pretending to be `read' (except the characters we store
in the keyboard buffer can be multibyte, so are not necessarily
- C chars).
-
- EXPECTED is nonzero if the caller knows input is available. */
+ C chars). */
static int
-XTread_socket (struct terminal *terminal, int expected, struct input_event *hold_quit)
+XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
{
int count = 0;
int event_found = 0;
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
-#ifdef SYNC_INPUT
- pending_signals = 1;
-#endif
- return -1;
- }
-
- interrupt_input_pending = 0;
-#ifdef SYNC_INPUT
- pending_signals = pending_atimers;
-#endif
- BLOCK_INPUT;
+ block_input ();
/* So people can tell when we have read the available input. */
input_signal_count++;
-#ifndef SYNC_INPUT
- ++handling_signal;
-#endif
-
/* For debugging, this gives a way to fake an I/O error. */
if (terminal->display_info.x == XTread_socket_fake_io_error)
{
@@ -7241,10 +7180,7 @@ XTread_socket (struct terminal *terminal, int expected, struct input_event *hold
pending_autoraise_frame = 0;
}
-#ifndef SYNC_INPUT
- --handling_signal;
-#endif
- UNBLOCK_INPUT;
+ unblock_input ();
return count;
}
@@ -7496,7 +7432,7 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int
break;
default:
- abort ();
+ emacs_abort ();
}
}
@@ -7680,7 +7616,7 @@ x_uncatch_errors (void)
{
struct x_error_message_stack *tmp;
- BLOCK_INPUT;
+ block_input ();
/* The display may have been closed before this function is called.
Check if it is still open before calling XSync. */
@@ -7690,7 +7626,7 @@ x_uncatch_errors (void)
tmp = x_error_message;
x_error_message = x_error_message->prev;
xfree (tmp);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* If any X protocol errors have arrived since the last call to
@@ -7753,24 +7689,6 @@ x_trace_wire (void)
#endif /* ! 0 */
-/* Handle SIGPIPE, which can happen when the connection to a server
- simply goes away. SIGPIPE is handled by x_connection_signal.
- Don't need to do anything, because the write which caused the
- SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
- which will do the appropriate cleanup for us. */
-
-static void
-x_connection_signal (int signalnum) /* If we don't have an argument, */
- /* some compilers complain in signal calls. */
-{
-#ifdef USG
- /* USG systems forget handlers when they are used;
- must reestablish each time */
- signal (signalnum, x_connection_signal);
-#endif /* USG */
-}
-
-
/************************************************************************
Handling X errors
************************************************************************/
@@ -7791,7 +7709,6 @@ x_connection_closed (Display *dpy, const char *error_message)
error_msg = alloca (strlen (error_message) + 1);
strcpy (error_msg, error_message);
- handling_signal = 0;
/* Inhibit redisplay while frames are being deleted. */
specbind (Qinhibit_redisplay, Qt);
@@ -7849,7 +7766,7 @@ When compiled with GTK, Emacs cannot recover from X disconnects.\n\
This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
For details, see etc/PROBLEMS.\n",
error_msg);
- abort ();
+ emacs_abort ();
#endif /* USE_GTK */
/* Indicate that this display is dead. */
@@ -7859,7 +7776,7 @@ For details, see etc/PROBLEMS.\n",
dpyinfo->terminal->reference_count--;
if (dpyinfo->reference_count != 0)
/* We have just closed all frames on this display. */
- abort ();
+ emacs_abort ();
{
Lisp_Object tmp;
@@ -7875,12 +7792,7 @@ For details, see etc/PROBLEMS.\n",
/* NOTREACHED */
}
- /* Ordinary stack unwind doesn't deal with these. */
-#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
-#endif
- sigunblock (sigmask (SIGALRM));
- TOTALLY_UNBLOCK_INPUT;
+ totally_unblock_input ();
unbind_to (idx, Qnil);
clear_waiting_for_input ();
@@ -7988,7 +7900,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_SPACE_WIDTH (f) = font->space_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
compute_fringe_widths (f, 1);
@@ -8019,9 +7930,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
if (FRAME_XIC (f)
&& (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
{
- BLOCK_INPUT;
+ block_input ();
xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
@@ -8047,7 +7958,7 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
Lisp_Object frame, tail;
- BLOCK_INPUT;
+ block_input ();
/* No need to call XDestroyIC.. */
FOR_EACH_FRAME (tail, frame)
@@ -8063,7 +7974,7 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
/* No need to call XCloseIM. */
dpyinfo->xim = NULL;
XFree (dpyinfo->xim_styles);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* HAVE_X11R6 */
@@ -8138,7 +8049,7 @@ xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_
{
Lisp_Object tail, frame;
- BLOCK_INPUT;
+ block_input ();
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
@@ -8158,7 +8069,7 @@ xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -8305,7 +8216,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
}
x_calc_absolute_position (f);
- BLOCK_INPUT;
+ block_input ();
x_wm_set_size_hint (f, (long) 0, 0);
modified_left = f->left_pos;
@@ -8344,7 +8255,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
&& FRAME_X_OUTPUT (f)->move_offset_top == 0))))
x_check_expected_move (f, modified_left, modified_top);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
@@ -8367,7 +8278,7 @@ wm_supports (struct frame *f, Atom want_atom)
unsigned char *tmp_data = NULL;
Atom target_type = XA_WINDOW;
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpy);
rc = XGetWindowProperty (dpy, target_window,
@@ -8380,7 +8291,7 @@ wm_supports (struct frame *f, Atom want_atom)
{
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -8393,7 +8304,7 @@ wm_supports (struct frame *f, Atom want_atom)
if (x_had_errors_p (dpy))
{
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -8418,7 +8329,7 @@ wm_supports (struct frame *f, Atom want_atom)
{
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -8433,7 +8344,7 @@ wm_supports (struct frame *f, Atom want_atom)
rc = dpyinfo->net_supported_atoms[i] == want_atom;
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return rc;
}
@@ -8492,7 +8403,7 @@ get_current_wm_state (struct frame *f,
*sticky = 0;
*size_state = FULLSCREEN_NONE;
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpy);
rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
0, max_len, False, target_type,
@@ -8503,7 +8414,7 @@ get_current_wm_state (struct frame *f,
{
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return ! f->iconified;
}
@@ -8538,7 +8449,7 @@ get_current_wm_state (struct frame *f,
}
if (tmp_data) XFree (tmp_data);
- UNBLOCK_INPUT;
+ unblock_input ();
return ! is_hidden;
}
@@ -8618,10 +8529,10 @@ XTfullscreen_hook (FRAME_PTR f)
{
if (f->async_visible)
{
- BLOCK_INPUT;
+ block_input ();
x_check_fullscreen (f);
x_sync (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -8806,10 +8717,10 @@ x_wait_for_event (struct frame *f, int eventtype)
while (pending_event_wait.eventtype)
{
- interrupt_input_pending = 1;
- TOTALLY_UNBLOCK_INPUT;
+ pending_signals = 1;
+ totally_unblock_input ();
/* XTread_socket is called after unblock. */
- BLOCK_INPUT;
+ block_input ();
interrupt_input_blocked = level;
FD_ZERO (&fds);
@@ -8900,7 +8811,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
void
x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
{
- BLOCK_INPUT;
+ block_input ();
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
@@ -8948,7 +8859,7 @@ x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
so don't try--just let the highlighting be done afresh with new size. */
cancel_mouse_face (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Mouse warping. */
@@ -8967,11 +8878,11 @@ x_set_mouse_position (struct frame *f, int x, int y)
if (pix_y < 0) pix_y = 0;
if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
- BLOCK_INPUT;
+ block_input ();
XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
0, 0, 0, 0, pix_x, pix_y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
@@ -8979,11 +8890,11 @@ x_set_mouse_position (struct frame *f, int x, int y)
void
x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
{
- BLOCK_INPUT;
+ block_input ();
XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
0, 0, 0, 0, pix_x, pix_y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Raise frame F. */
@@ -8991,12 +8902,12 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
void
x_raise_frame (struct frame *f)
{
- BLOCK_INPUT;
+ block_input ();
if (f->async_visible)
XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Lower frame F. */
@@ -9006,10 +8917,10 @@ x_lower_frame (struct frame *f)
{
if (f->async_visible)
{
- BLOCK_INPUT;
+ block_input ();
XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
@@ -9118,7 +9029,7 @@ x_make_frame_visible (struct frame *f)
retry:
- BLOCK_INPUT;
+ block_input ();
type = x_icon_type (f);
if (!NILP (type))
@@ -9177,7 +9088,7 @@ x_make_frame_visible (struct frame *f)
original_top = f->top_pos;
/* This must come after we set COUNT. */
- UNBLOCK_INPUT;
+ unblock_input ();
/* We unblock here so that arriving X events are processed. */
@@ -9200,7 +9111,7 @@ x_make_frame_visible (struct frame *f)
int x, y;
unsigned int width, height, border, depth;
- BLOCK_INPUT;
+ block_input ();
/* On some window managers (such as FVWM) moving an existing
window, even to the same place, causes the window manager
@@ -9216,7 +9127,7 @@ x_make_frame_visible (struct frame *f)
XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
original_left, original_top);
- UNBLOCK_INPUT;
+ unblock_input ();
}
XSETFRAME (frame, f);
@@ -9283,7 +9194,7 @@ x_make_frame_invisible (struct frame *f)
if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
- BLOCK_INPUT;
+ block_input ();
/* Before unmapping the window, update the WM_SIZE_HINTS property to claim
that the current position of the window is user-specified, rather than
@@ -9306,7 +9217,7 @@ x_make_frame_invisible (struct frame *f)
if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
DefaultScreen (FRAME_X_DISPLAY (f))))
{
- UNBLOCK_INPUT_RESIGNAL;
+ unblock_input ();
error ("Can't notify window manager of window withdrawal");
}
}
@@ -9323,7 +9234,7 @@ x_make_frame_invisible (struct frame *f)
x_sync (f);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Change window state from mapped to iconified. */
@@ -9343,7 +9254,7 @@ x_iconify_frame (struct frame *f)
if (f->async_iconified)
return;
- BLOCK_INPUT;
+ block_input ();
FRAME_SAMPLE_VISIBILITY (f);
@@ -9362,7 +9273,7 @@ x_iconify_frame (struct frame *f)
f->visible = 1;
f->async_iconified = 1;
f->async_visible = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
#endif
@@ -9382,14 +9293,14 @@ x_iconify_frame (struct frame *f)
f->visible = 1;
f->async_iconified = 1;
f->async_visible = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
return;
}
result = XIconifyWindow (FRAME_X_DISPLAY (f),
XtWindow (f->output_data.x->widget),
DefaultScreen (FRAME_X_DISPLAY (f)));
- UNBLOCK_INPUT;
+ unblock_input ();
if (!result)
error ("Can't notify window manager of iconification");
@@ -9398,9 +9309,9 @@ x_iconify_frame (struct frame *f)
f->async_visible = 0;
- BLOCK_INPUT;
+ block_input ();
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
#else /* not USE_X_TOOLKIT */
/* Make sure the X server knows where the window should be positioned,
@@ -9430,7 +9341,7 @@ x_iconify_frame (struct frame *f)
SubstructureRedirectMask | SubstructureNotifyMask,
&msg))
{
- UNBLOCK_INPUT_RESIGNAL;
+ unblock_input ();
error ("Can't notify window manager of iconification");
}
}
@@ -9449,7 +9360,7 @@ x_iconify_frame (struct frame *f)
f->async_visible = 0;
XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
+ unblock_input ();
#endif /* not USE_X_TOOLKIT */
}
@@ -9466,7 +9377,7 @@ x_free_frame_resources (struct frame *f)
struct scroll_bar *b;
#endif
- BLOCK_INPUT;
+ block_input ();
/* If a display connection is dead, don't try sending more
commands to the X server. */
@@ -9565,11 +9476,10 @@ x_free_frame_resources (struct frame *f)
hlinfo->mouse_face_end_row
= hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_window = Qnil;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_mouse_frame = 0;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
@@ -9594,13 +9504,13 @@ x_destroy_window (struct frame *f)
/* Set the normal size hints for the window manager, for frame F.
FLAGS is the flags word to use--or 0 meaning preserve the flags
that the window now has.
- If USER_POSITION is nonzero, we set the USPosition
+ If USER_POSITION, set the USPosition
flag (this is useful when FLAGS is 0).
- The GTK version is in gtkutils.c */
+ The GTK version is in gtkutils.c. */
#ifndef USE_GTK
void
-x_wm_set_size_hint (struct frame *f, long flags, int user_position)
+x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
{
XSizeHints size_hints;
Window window = FRAME_OUTER_WINDOW (f);
@@ -9949,7 +9859,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
Mouse_HLInfo *hlinfo;
ptrdiff_t lim;
- BLOCK_INPUT;
+ block_input ();
if (!x_initialized)
{
@@ -9996,10 +9906,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
/* Emacs can only handle core input events, so make sure
Gtk doesn't use Xinput or Xinput2 extensions. */
- {
- static char fix_events[] = "GDK_CORE_DEVICE_EVENTS=1";
- putenv (fix_events);
- }
+ 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. */
@@ -10010,11 +9917,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
Call before gtk_init so Gtk+ event filters comes after our. */
gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+ /* gtk_init does set_locale. Fix locale before and after. */
+ fixup_locale ();
gtk_init (&argc, &argv2);
+ fixup_locale ();
+
g_log_remove_handler ("GLib", id);
- /* gtk_init does set_locale. We must fix locale after calling it. */
- fixup_locale ();
xg_initialize ();
dpy = DEFAULT_GDK_DISPLAY ();
@@ -10081,7 +9990,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
/* Detect failure. */
if (dpy == 0)
{
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
@@ -10128,12 +10037,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
/* Temporarily hide the partially initialized terminal. */
terminal_list = terminal->next_terminal;
- UNBLOCK_INPUT;
+ unblock_input ();
kset_system_key_alist
(terminal->kboard,
call1 (Qvendor_specific_keysyms,
vendor ? build_string (vendor) : empty_unibyte_string));
- BLOCK_INPUT;
+ block_input ();
terminal->next_terminal = terminal_list;
terminal_list = terminal;
UNGCPRO;
@@ -10214,7 +10123,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->bitmaps_last = 0;
dpyinfo->scratch_cursor_gc = 0;
hlinfo->mouse_face_mouse_frame = 0;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
@@ -10417,10 +10325,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
fcntl (connection, F_SETOWN, getpid ());
#endif /* ! defined (F_SETOWN) */
-#ifdef SIGIO
if (interrupt_input)
init_sigio (connection);
-#endif /* ! defined (SIGIO) */
#ifdef USE_LUCID
{
@@ -10436,7 +10342,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
to.addr = (XPointer)&font;
x_catch_errors (dpy);
if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
- abort ();
+ emacs_abort ();
if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
x_uncatch_errors ();
@@ -10484,7 +10390,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
x_session_initialize (dpyinfo);
#endif
- UNBLOCK_INPUT;
+ unblock_input ();
return dpyinfo;
}
@@ -10564,7 +10470,7 @@ x_delete_display (struct x_display_info *dpyinfo)
static void
x_process_timeouts (struct atimer *timer)
{
- BLOCK_INPUT;
+ block_input ();
x_timeout_atimer_activated_flag = 0;
if (toolkit_scroll_bar_interaction || popup_activated ())
{
@@ -10573,7 +10479,7 @@ x_process_timeouts (struct atimer *timer)
/* Reactivate the atimer for next time. */
x_activate_timeout_atimer ();
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Install an asynchronous timer that processes Xt timeout events
@@ -10587,14 +10493,14 @@ x_process_timeouts (struct atimer *timer)
void
x_activate_timeout_atimer (void)
{
- BLOCK_INPUT;
+ block_input ();
if (!x_timeout_atimer_activated_flag)
{
EMACS_TIME interval = make_emacs_time (0, 100 * 1000 * 1000);
start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
x_timeout_atimer_activated_flag = 1;
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* USE_X_TOOLKIT */
@@ -10647,7 +10553,7 @@ x_delete_terminal (struct terminal *terminal)
if (!terminal->name)
return;
- BLOCK_INPUT;
+ block_input ();
#ifdef HAVE_X_I18N
/* We must close our connection to the XIM server before closing the
X display. */
@@ -10702,7 +10608,7 @@ x_delete_terminal (struct terminal *terminal)
/* Mark as dead. */
dpyinfo->display = NULL;
x_delete_display (dpyinfo);
- UNBLOCK_INPUT;
+ unblock_input ();
}
/* Create a struct terminal, initialize it with the X11 specific
@@ -10804,8 +10710,6 @@ x_initialize (void)
original error handler. */
XSetErrorHandler (x_error_handler);
XSetIOErrorHandler (x_io_error_quitter);
-
- signal (SIGPIPE, x_connection_signal);
}
@@ -10924,10 +10828,10 @@ default is nil, which is the same as `super'. */);
DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
doc: /* Hash table of character codes indexed by X keysym codes. */);
- Vx_keysym_table = make_hash_table (Qeql, make_number (900),
+ Vx_keysym_table = make_hash_table (hashtest_eql, make_number (900),
make_float (DEFAULT_REHASH_SIZE),
make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
+ Qnil);
}
#endif /* HAVE_X_WINDOWS */
diff --git a/src/xterm.h b/src/xterm.h
index 2d718f49118..d63ed1c4583 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -506,12 +506,6 @@ struct x_output
value contains an ID of the fontset, else -1. */
int fontset;
- /* Pixel values used for various purposes.
- border_pixel may be -1 meaning use a gray tile. */
-#if 0 /* These are also defined in struct frame. Use that instead. */
- unsigned long background_pixel;
- unsigned long foreground_pixel;
-#endif
unsigned long cursor_pixel;
unsigned long border_pixel;
unsigned long mouse_pixel;
@@ -574,13 +568,13 @@ struct x_output
/* Nonzero means our parent is another application's window
and was explicitly specified. */
- char explicit_parent;
+ unsigned explicit_parent : 1;
/* Nonzero means tried already to make this frame visible. */
- char asked_for_visible;
+ unsigned asked_for_visible : 1;
/* Nonzero if this frame was ever previously visible. */
- char has_been_visible;
+ unsigned has_been_visible : 1;
#ifdef HAVE_X_I18N
/* Input context (currently, this means Compose key handler setup). */
@@ -634,7 +628,7 @@ struct x_output
int top_before_move;
/* Non-zero if _NET_WM_STATE_HIDDEN is set for this frame. */
- int net_wm_state_hidden_seen;
+ unsigned net_wm_state_hidden_seen : 1;
};
#define No_Cursor (None)
@@ -890,10 +884,8 @@ struct scroll_bar
by this structure. */
/* For an event of kind SELECTION_REQUEST_EVENT,
- this structure really describes the contents.
- **Don't make this struct longer!**
- If it overlaps the frame_or_window field of struct input_event,
- that will cause GC to crash. */
+ this structure really describes the contents. */
+
struct selection_input_event
{
int kind;
@@ -962,11 +954,11 @@ extern XtAppContext Xt_app_con;
extern void x_activate_timeout_atimer (void);
#endif
#ifdef USE_LUCID
-extern int x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
- unsigned long *,
- double, int);
+extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
+ unsigned long *,
+ double, int);
#endif
-extern int x_alloc_nearest_color (struct frame *, Colormap, XColor *);
+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, int);
#if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
@@ -1034,7 +1026,7 @@ extern void xic_set_statusarea (struct frame *);
extern void xic_set_xfontset (struct frame *, const char *);
extern int x_pixel_width (struct frame *);
extern int x_pixel_height (struct frame *);
-extern int x_defined_color (struct frame *, const char *, XColor *, int);
+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