diff options
author | Eli Zaretskii <eliz@gnu.org> | 2012-12-10 14:08:02 +0200 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2012-12-10 14:08:02 +0200 |
commit | 3907e630a71d48e693062b350571990d7ba08bbb (patch) | |
tree | 2be1ecc0796e42c7a453a9fd5131eb5866f79876 /src | |
parent | cf2d22b874ca2df0072e32ee641e8efffe4abd6d (diff) | |
parent | 81606b10501169a5671061b8461bbc32dcec8705 (diff) | |
download | emacs-3907e630a71d48e693062b350571990d7ba08bbb.tar.gz |
Merge from trunk + rename the event. Not tested yet.
Diffstat (limited to 'src')
-rw-r--r-- | src/.gdbinit | 3 | ||||
-rw-r--r-- | src/ChangeLog | 672 | ||||
-rw-r--r-- | src/Makefile.in | 2 | ||||
-rw-r--r-- | src/alloc.c | 53 | ||||
-rw-r--r-- | src/buffer.c | 25 | ||||
-rw-r--r-- | src/buffer.h | 5 | ||||
-rw-r--r-- | src/bytecode.c | 8 | ||||
-rw-r--r-- | src/callproc.c | 374 | ||||
-rw-r--r-- | src/casefiddle.c | 2 | ||||
-rw-r--r-- | src/charset.c | 4 | ||||
-rw-r--r-- | src/cygw32.c | 20 | ||||
-rw-r--r-- | src/data.c | 29 | ||||
-rw-r--r-- | src/dbusbind.c | 2 | ||||
-rw-r--r-- | src/dired.c | 247 | ||||
-rw-r--r-- | src/dispextern.h | 12 | ||||
-rw-r--r-- | src/doc.c | 8 | ||||
-rw-r--r-- | src/doprnt.c | 5 | ||||
-rw-r--r-- | src/editfns.c | 310 | ||||
-rw-r--r-- | src/emacs.c | 19 | ||||
-rw-r--r-- | src/eval.c | 132 | ||||
-rw-r--r-- | src/fileio.c | 78 | ||||
-rw-r--r-- | src/font.c | 15 | ||||
-rw-r--r-- | src/fontset.c | 2 | ||||
-rw-r--r-- | src/frame.c | 196 | ||||
-rw-r--r-- | src/frame.h | 28 | ||||
-rw-r--r-- | src/gmalloc.c | 8 | ||||
-rw-r--r-- | src/gnutls.c | 14 | ||||
-rw-r--r-- | src/gtkutil.c | 15 | ||||
-rw-r--r-- | src/indent.c | 14 | ||||
-rw-r--r-- | src/inotify.c | 438 | ||||
-rw-r--r-- | src/insdel.c | 21 | ||||
-rw-r--r-- | src/keyboard.c | 86 | ||||
-rw-r--r-- | src/lisp.h | 27 | ||||
-rw-r--r-- | src/lread.c | 21 | ||||
-rw-r--r-- | src/makefile.w32-in | 20 | ||||
-rw-r--r-- | src/msdos.c | 15 | ||||
-rw-r--r-- | src/ndir.h | 41 | ||||
-rw-r--r-- | src/nsfns.m | 14 | ||||
-rw-r--r-- | src/nsterm.h | 3 | ||||
-rw-r--r-- | src/nsterm.m | 42 | ||||
-rw-r--r-- | src/process.c | 428 | ||||
-rw-r--r-- | src/process.h | 23 | ||||
-rw-r--r-- | src/sysdep.c | 243 | ||||
-rw-r--r-- | src/syssignal.h | 20 | ||||
-rw-r--r-- | src/syswait.h | 7 | ||||
-rw-r--r-- | src/term.c | 43 | ||||
-rw-r--r-- | src/termchar.h | 20 | ||||
-rw-r--r-- | src/termhooks.h | 5 | ||||
-rw-r--r-- | src/textprop.c | 24 | ||||
-rw-r--r-- | src/unexcoff.c | 6 | ||||
-rw-r--r-- | src/unexelf.c | 2 | ||||
-rw-r--r-- | src/vm-limit.c | 75 | ||||
-rw-r--r-- | src/w32.c | 125 | ||||
-rw-r--r-- | src/w32.h | 2 | ||||
-rw-r--r-- | src/w32common.h | 2 | ||||
-rw-r--r-- | src/w32fns.c | 27 | ||||
-rw-r--r-- | src/w32menu.c | 13 | ||||
-rw-r--r-- | src/w32proc.c | 44 | ||||
-rw-r--r-- | src/w32select.c | 2 | ||||
-rw-r--r-- | src/w32term.c | 52 | ||||
-rw-r--r-- | src/w32term.h | 33 | ||||
-rw-r--r-- | src/window.c | 4 | ||||
-rw-r--r-- | src/xdisp.c | 281 | ||||
-rw-r--r-- | src/xfns.c | 14 | ||||
-rw-r--r-- | src/xftfont.c | 4 | ||||
-rw-r--r-- | src/xterm.c | 69 | ||||
-rw-r--r-- | src/xterm.h | 14 |
67 files changed, 2585 insertions, 2027 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index fa580cc99bf..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 diff --git a/src/ChangeLog b/src/ChangeLog index cea22d498ed..ac2299a4f79 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,671 @@ +2012-12-10 Rüdiger Sonderfeld <ruediger@c-plusplus.de> + + * 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 @@ -240,8 +908,8 @@ * 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 + 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) diff --git a/src/Makefile.in b/src/Makefile.in index 330066d0103..cd0b9318ccb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -344,7 +344,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ syntax.o $(UNEXEC_OBJ) bytecode.o \ process.o gnutls.o callproc.o \ region-cache.o sound.o atimer.o \ - doprnt.o intervals.o textprop.o composite.o xml.o \ + doprnt.o intervals.o textprop.o composite.o xml.o inotify.o \ profiler.o \ $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) diff --git a/src/alloc.c b/src/alloc.c index a66a752f5dc..5a3ba465d81 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -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 @@ -765,13 +761,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, @@ -820,18 +820,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; } @@ -3212,7 +3216,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; @@ -3249,7 +3253,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; @@ -3365,6 +3369,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 @@ -5335,12 +5352,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; diff --git a/src/buffer.c b/src/buffer.c index 619a729a859..6e2191dc22f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1529,6 +1529,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 @@ -1550,9 +1560,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */) for (; CONSP (tail); tail = XCDR (tail)) { buf = XCAR (tail); - if (BUFFERP (buf) && !EQ (buf, buffer) - && BUFFER_LIVE_P (XBUFFER (buf)) - && (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)))) @@ -1570,9 +1578,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) - && BUFFER_LIVE_P (XBUFFER (buf)) - && (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)))) @@ -1608,13 +1614,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) - && BUFFER_LIVE_P (XBUFFER (buf)) - && (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')) + if (candidate_buffer (buf, buffer)) return buf; } diff --git a/src/buffer.h b/src/buffer.h index fbbbf1b8434..1129840bd47 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -982,6 +982,11 @@ bset_width_table (struct buffer *b, Lisp_Object val) #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) \ diff --git a/src/bytecode.c b/src/bytecode.c index 648813aed86..4c5ac151de1 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -87,8 +87,6 @@ Lisp_Object Qbyte_code_meter; #endif /* BYTE_CODE_METER */ -Lisp_Object Qbytecode; - /* Byte codes: */ #define BYTE_CODES \ @@ -1579,7 +1577,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): @@ -1961,8 +1961,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/callproc.c b/src/callproc.c index 8ecaba2b408..70e349d0d3a 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -67,88 +67,122 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* 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. */ + +/* If nonzero, a process-ID that has not been reaped. */ +static pid_t synch_process_pid; + +/* If nonnegative, a file descriptor that has not been closed. */ +static int synch_process_fd; + +/* Block SIGCHLD. */ -/* Nonzero => this is a string explaining death of synchronous subprocess. */ -const char *synch_process_death; +static void +block_child_signal (void) +{ + sigset_t blocked; + sigemptyset (&blocked); + sigaddset (&blocked, SIGCHLD); + pthread_sigmask (SIG_BLOCK, &blocked, 0); +} -/* Nonzero => this is the signal number that terminated the subprocess. */ -int synch_process_termsig; +/* Unblock SIGCHLD. */ -/* If synch_process_death is zero, - this is exit code of synchronous subprocess. */ -int synch_process_retcode; +static void +unblock_child_signal (void) +{ + pthread_sigmask (SIG_SETMASK, &empty_mask, 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. */ +/* 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 (); -/* True if this is termination due to exit. */ -static bool call_process_exited; + 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; } @@ -181,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; @@ -204,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 */ @@ -432,12 +463,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 */ @@ -466,44 +497,37 @@ 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; if (fd_output >= 0) fd1 = fd_output; - /* 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); else if (STRINGP (error_file)) @@ -520,8 +544,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 @@ -536,31 +560,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); @@ -569,14 +590,29 @@ 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 */ + + /* 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_child_signal (); + +#ifdef WINDOWSNT + pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); +#else /* not WINDOWSNT */ /* vfork, and prevent local vars from being clobbered by the vfork. */ { @@ -589,50 +625,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]); + unblock_child_signal (); + + if (fd0 >= 0) + emacs_close (fd0); setsid (); /* Emacs ignores SIGPIPE, but the child should not. */ signal (SIGPIPE, SIG_DFL); - 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; + + if (0 < pid) + { + if (INTEGERP (buffer)) + record_deleted_pid (pid); + else + synch_process_pid = pid; + } + + 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) @@ -643,31 +696,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); @@ -723,6 +757,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; @@ -739,7 +777,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) @@ -850,38 +888,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 @@ -955,8 +989,9 @@ 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 @@ -973,7 +1008,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); @@ -1079,10 +1122,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 @@ -1285,11 +1324,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, 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])); @@ -1317,16 +1352,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: "; diff --git a/src/casefiddle.c b/src/casefiddle.c index e3654627576..d9c6a078973 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c @@ -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/charset.c b/src/charset.c index c9133c780e8..43be0e9c780 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1142,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. diff --git a/src/cygw32.c b/src/cygw32.c index 54f2076a891..d9777d5e22e 100644 --- a/src/cygw32.c +++ b/src/cygw32.c @@ -106,22 +106,24 @@ conv_filename_from_w32_unicode (const wchar_t* in, int absolute_p) return unbind_to (count, DECODE_FILE (converted)); } -DEFUN ("cygwin-convert-path-to-windows", - Fcygwin_convert_path_to_windows, Scygwin_convert_path_to_windows, +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 if - non-nil, return an absolute path.*/) + 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-path-from-windows", - Fcygwin_convert_path_from_windows, Scygwin_convert_path_from_windows, +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 - if non-nil, return an absolute path.*/) +is non-nil, return an absolute path.*/) (Lisp_Object path, Lisp_Object absolute_p) { return conv_filename_from_w32_unicode (to_unicode (path, &path), @@ -131,6 +133,6 @@ DEFUN ("cygwin-convert-path-from-windows", void syms_of_cygw32 (void) { - defsubr (&Scygwin_convert_path_from_windows); - defsubr (&Scygwin_convert_path_to_windows); + defsubr (&Scygwin_convert_file_name_from_windows); + defsubr (&Scygwin_convert_file_name_to_windows); } diff --git a/src/data.c b/src/data.c index 09899400b68..a72fa3e2b5f 100644 --- a/src/data.c +++ b/src/data.c @@ -506,7 +506,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; @@ -543,12 +545,13 @@ DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0, 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, @@ -564,14 +567,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; } @@ -580,9 +583,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, @@ -613,7 +614,7 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, 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 (AUTOLOADP (function)) @@ -714,7 +715,7 @@ 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 @@ -1048,7 +1049,9 @@ find_symbol_value (Lisp_Object symbol) } 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; @@ -2008,10 +2011,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; @@ -2038,10 +2041,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)) diff --git a/src/dbusbind.c b/src/dbusbind.c index 80086946fc4..da8bbb1e5d7 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -1203,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/dired.c b/src/dired.c index 4986f845101..bdb71c46364 100644 --- a/src/dired.c +++ b/src/dired.c @@ -31,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" @@ -88,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) @@ -124,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 @@ -209,105 +186,98 @@ 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); + + /* Note: DECODE_FILE can GC; it should protect its argument, + though. */ + name = DECODE_FILE (name); + len = SBYTES (name); + + /* Now that we have unwind_protect in place, we might as well + allow matching to be interrupted. */ + immediate_quit = 1; + QUIT; - if (dp == NULL) - break; + if (NILP (match) + || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0))) + wanted = 1; - if (DIRENTRY_NONEMPTY (dp)) + 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) - emacs_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 (); @@ -442,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 @@ -499,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; @@ -806,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; @@ -851,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; @@ -866,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; diff --git a/src/dispextern.h b/src/dispextern.h index c5ebb808b05..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 diff --git a/src/doc.c b/src/doc.c index 1d3d1e64442..76008295add 100644 --- a/src/doc.c +++ b/src/doc.c @@ -338,6 +338,14 @@ string is passed through `substitute-command-keys'. */) doc = Qnil; + if (SYMBOLP (function)) + { + Lisp_Object tem = Fget (function, Qfunction_documentation); + if (!NILP (tem)) + return Fdocumentation_property (function, Qfunction_documentation, + raw); + } + fun = Findirect_function (function, Qnil); if (CONSP (fun) && EQ (XCAR (fun), Qmacro)) fun = XCDR (fun); diff --git a/src/doprnt.c b/src/doprnt.c index caa56d6ae88..8cab219aafa 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -521,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/editfns.c b/src/editfns.c index 8122ffdd0d4..eb909f73697 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -78,6 +78,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) @@ -96,6 +105,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 @@ -813,38 +825,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); + Lisp_Object save, *data = xmalloc (word_size * 4); + + data[0] = Fpoint_marker (); /* Do not copy the mark if it points to nowhere. */ - Lisp_Object mark = (XMARKER (BVAR (current_buffer, mark))->buffer - ? Fcopy_marker (BVAR (current_buffer, mark), Qnil) - : Qnil); - - return Fcons (Fpoint_marker (), - Fcons (mark, - Fcons (visible ? Qt : Qnil, - Fcons (BVAR (current_buffer, mark_active), - selected_window)))); + 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); @@ -852,13 +869,12 @@ 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)); if (NILP (tem)) unchain_marker (XMARKER (BVAR (current_buffer, mark))); @@ -869,23 +885,8 @@ save_excursion_restore (Lisp_Object info) 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); @@ -909,8 +910,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... */ @@ -920,6 +921,10 @@ save_excursion_restore (Lisp_Object info) Fset_window_point (tem, make_number (PT)); UNGCPRO; + + out: + + free_save_value (info); return Qnil; } @@ -1907,9 +1912,11 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) } 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"; @@ -1921,13 +1928,20 @@ 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"); + 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 @@ -1936,15 +1950,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); + SAFE_FREE (); } if (value == (time_t) -1) @@ -2074,16 +2085,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. @@ -2096,18 +2097,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)) @@ -2115,106 +2108,97 @@ only the former. */) else tzstring = SSDATA (tz); + block_input (); set_time_zone_rule (tzstring); - environbuf = environ; - 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 } @@ -2358,9 +2342,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: @@ -2650,10 +2635,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. */) @@ -2929,7 +2914,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)) { @@ -3105,7 +3090,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; ) @@ -4629,7 +4614,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); @@ -4688,8 +4673,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); @@ -4722,7 +4707,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); @@ -4755,7 +4740,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); @@ -4806,9 +4791,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, diff --git a/src/emacs.c b/src/emacs.c index 1afc7c189df..2e580ea700a 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -95,10 +95,6 @@ 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; @@ -539,7 +535,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 @@ -719,9 +715,9 @@ main (int argc, char **argv) stack_base = &dummy; #endif -#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 @@ -807,9 +803,8 @@ main (int argc, char **argv) #ifdef HAVE_PERSONALITY_LINUX32 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 */ @@ -1314,7 +1309,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. */ @@ -1448,6 +1443,10 @@ 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 */ diff --git a/src/eval.c b/src/eval.c index f8a76646352..34b20f6fc8e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -114,7 +114,6 @@ Lisp_Object Vsignaling_function; 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. */ @@ -489,102 +488,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 && 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. @@ -696,8 +599,9 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) 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; } } @@ -717,8 +621,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. @@ -971,7 +875,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; @@ -986,7 +890,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)) @@ -1811,12 +1715,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)) { @@ -1876,7 +1780,7 @@ 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) + if (!NILP (XSYMBOL (function)->function) && !AUTOLOADP (XSYMBOL (function)->function)) return Qnil; @@ -2055,7 +1959,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); @@ -2177,7 +2081,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); @@ -2251,10 +2155,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]; @@ -2728,7 +2632,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); @@ -2816,7 +2720,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); @@ -3551,8 +3455,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 572f6d8ef83..56c340bfa40 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -315,6 +315,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; @@ -374,10 +375,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, @@ -451,7 +455,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) @@ -473,7 +477,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; } @@ -515,7 +526,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) @@ -534,7 +545,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; } @@ -951,7 +969,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,7 +1056,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) o [p - nm] = 0; block_input (); - pw = (struct passwd *) getpwnam (o + 1); + pw = getpwnam (o + 1); unblock_input (); if (pw) { @@ -1133,7 +1162,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) newdir = "/"; } else - getwd (adir); + getcwd (adir, MAXPATHLEN + 1); newdir = adir; } @@ -1305,10 +1334,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 @@ -1558,7 +1590,7 @@ those `/' is discarded. */) { char *nm, *s, *p, *o, *x, *endp; char *target = NULL; - int total = 0; + ptrdiff_t total = 0; bool substituted = 0; bool multibyte; char *xnm; @@ -1587,8 +1619,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); @@ -1967,10 +2009,8 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) { 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)); } } @@ -5745,7 +5785,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; diff --git a/src/font.c b/src/font.c index 41dbfd7a757..f6b6fa026c0 100644 --- a/src/font.c +++ b/src/font.c @@ -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; + } } } diff --git a/src/fontset.c b/src/fontset.c index b76a216bac2..660ca432fad 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -1876,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 d580bf7f148..5cefad6ca46 100644 --- a/src/frame.c +++ b/src/frame.c @@ -346,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 @@ -366,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); @@ -895,13 +889,58 @@ 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) @@ -910,72 +949,24 @@ next_frame (Lisp_Object frame, Lisp_Object minibuf) int passed = 0; /* There must always be at least one frame in Vframe_list. */ - if (! CONSP (Vframe_list)) - emacs_abort (); - - /* If this frame is dead, it won't be in Vframe_list, and we'll loop - forever. Forestall that. */ - CHECK_LIVE_FRAME (frame); + eassert (CONSP (Vframe_list)); - while (1) + while (passed < 2) FOR_EACH_FRAME (tail, f) { - 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) @@ -989,43 +980,9 @@ prev_frame (Lisp_Object frame, Lisp_Object minibuf) { 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. */ @@ -1056,7 +1013,6 @@ Otherwise, include all frames. */) { if (NILP (frame)) frame = selected_frame; - CHECK_LIVE_FRAME (frame); return next_frame (frame, miniframe); } @@ -1467,7 +1423,6 @@ and returns whatever that function returns. */) 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) { @@ -1487,7 +1442,6 @@ and returns whatever that function returns. */) XSETINT (x, col); XSETINT (y, row); } -#endif XSETFRAME (lispy_dummy, f); retval = Fcons (lispy_dummy, Fcons (x, y)); GCPRO1 (retval); @@ -1514,7 +1468,6 @@ and nil for X and Y. */) 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) { @@ -1526,7 +1479,6 @@ and nil for X and Y. */) &time_dummy); } -#endif XSETFRAME (lispy_dummy, f); return Fcons (lispy_dummy, Fcons (x, y)); } @@ -1557,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); @@ -1598,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); @@ -2318,7 +2270,7 @@ For a terminal frame, the value is always 1. */) 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); @@ -2337,7 +2289,7 @@ For a terminal screen, the value is always 1. */) 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); diff --git a/src/frame.h b/src/frame.h index 35cbc44becc..589b45fc0ff 100644 --- a/src/frame.h +++ b/src/frame.h @@ -301,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; @@ -357,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. @@ -933,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; @@ -988,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. */ @@ -1251,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); diff --git a/src/gmalloc.c b/src/gmalloc.c index dc584955661..c325ca79910 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -1645,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 e3d84a0b61b..03f753fa8cc 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -359,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; } @@ -384,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; } } diff --git a/src/gtkutil.c b/src/gtkutil.c index 4367b534cb9..52a6c37b0d5 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -813,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. @@ -828,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; @@ -840,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); } } diff --git a/src/indent.c b/src/indent.c index eee96061e25..327526eae2d 100644 --- a/src/indent.c +++ b/src/indent.c @@ -2025,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') @@ -2048,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/inotify.c b/src/inotify.c new file mode 100644 index 00000000000..4db95a069fe --- /dev/null +++ b/src/inotify.c @@ -0,0 +1,438 @@ +/* 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; + event.arg = Qnil; + + 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); + } + + i += sizeof (*ev) + ev->len; + } + + if (!NILP (event.arg)) + kbd_buffer_store_event (&event); + + 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 decoded_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); + decoded_file_name = ENCODE_FILE (file_name); + watchdesc = inotify_add_watch (inotifyfd, SSDATA (decoded_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 87010cd8251..892ca3d5216 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1755,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. @@ -1766,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 (); @@ -1783,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. diff --git a/src/keyboard.c b/src/keyboard.c index 98c1cc0b78b..ecf1551622f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -306,9 +306,7 @@ 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; @@ -316,7 +314,7 @@ Lisp_Object Qmouse_click; #ifdef HAVE_NTGUI Lisp_Object Qlanguage_change; #ifdef WINDOWSNT -Lisp_Object Qfile_notify; +Lisp_Object Qfile_w32notify; #endif #endif static Lisp_Object Qdrag_n_drop; @@ -324,6 +322,9 @@ 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 */ @@ -420,12 +421,10 @@ static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *, 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); @@ -1123,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); @@ -1161,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; @@ -1179,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 */ @@ -1237,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. */ @@ -1313,7 +1309,6 @@ some_mouse_moved (void) return 0; } -#endif /* HAVE_MOUSE || HAVE_GPM */ /* This is the actual command reading loop, sans error-handling encapsulation. */ @@ -1405,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. */ @@ -2185,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 @@ -2198,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)) { @@ -3393,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) @@ -3765,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." */ @@ -3783,10 +3769,8 @@ kbd_buffer_get_event (KBOARD **kbp, #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 (); @@ -3928,7 +3912,7 @@ kbd_buffer_get_event (KBOARD **kbp, else if (event->kind == FILE_NOTIFY_EVENT) { /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */ - obj = Fcons (Qfile_notify, + obj = Fcons (Qfile_w32notify, list2 (list3 (make_number (event->code), XCAR (event->arg), XCDR (event->arg)), @@ -3993,6 +3977,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); @@ -4053,7 +4044,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 ()) { @@ -4098,7 +4088,6 @@ 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! */ @@ -5410,7 +5399,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: @@ -5862,7 +5850,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) @@ -5910,6 +5897,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, @@ -5981,8 +5975,6 @@ make_lispy_event (struct input_event *event) } } -#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) @@ -6010,8 +6002,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) @@ -6961,7 +6951,7 @@ tty_read_avail_input (struct terminal *terminal, #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 # error "Cannot read without possibly delaying" #endif @@ -6995,14 +6985,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 @@ -10731,7 +10718,7 @@ handle_interrupt (bool in_signal_handler) 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. @@ -11246,9 +11233,7 @@ init_keyboard (void) 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; pending_signals = 0; @@ -11376,13 +11361,17 @@ syms_of_keyboard (void) #ifdef HAVE_NTGUI DEFSYM (Qlanguage_change, "language-change"); - DEFSYM (Qfile_notify, "file-notify"); + 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"); @@ -11400,9 +11389,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"); @@ -11522,9 +11509,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); @@ -12143,12 +12128,19 @@ 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-notify", + initial_define_lispy_key (Vspecial_event_map, "file-w32notify", "w32notify-handle-event"); #endif } diff --git a/src/lisp.h b/src/lisp.h index 2148a623cc7..c7a70feced7 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1104,7 +1104,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. */ @@ -1644,27 +1644,24 @@ 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. */ @@ -2800,7 +2797,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, @@ -2967,6 +2964,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 *); @@ -3397,7 +3395,6 @@ extern void syms_of_doc (void); extern int read_bytecode_char (bool); /* Defined in bytecode.c. */ -extern Lisp_Object Qbytecode; extern void syms_of_bytecode (void); extern struct byte_stack *byte_stack_list; #if BYTE_MARK_STACK @@ -3524,6 +3521,11 @@ extern Lisp_Object Qfont_param; 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; @@ -3602,6 +3604,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 *); diff --git a/src/lread.c b/src/lread.c index 5859a2f85a9..2f385797ca0 100644 --- a/src/lread.c +++ b/src/lread.c @@ -440,7 +440,6 @@ readbyte_from_file (int c, Lisp_Object readcharfun) block_input (); c = getc (instream); -#ifdef EINTR /* Interrupted reads have been observed while reading over the network. */ while (c == EOF && ferror (instream) && errno == EINTR) { @@ -450,7 +449,6 @@ readbyte_from_file (int c, Lisp_Object readcharfun) clearerr (instream); c = getc (instream); } -#endif unblock_input (); @@ -3957,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); @@ -4526,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/makefile.w32-in b/src/makefile.w32-in index 71cafeb4d8b..388c097a066 100644 --- a/src/makefile.w32-in +++ b/src/makefile.w32-in @@ -230,12 +230,12 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.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 > $@ @@ -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 \ @@ -473,6 +471,8 @@ SYSSIGNAL_H = $(SRC)/syssignal.h \ SYSTTY_H = $(SRC)/systty.h \ $(NT_INC)/sys/ioctl.h \ $(NT_INC)/unistd.h +SYSWAIT_H = $(SRC)/syswait.h \ + $(NT_INC)/sys/wait.h TERMHOOKS_H = $(SRC)/termhooks.h \ $(SYSTIME_H) W32FONT_H = $(SRC)/w32font.h \ @@ -567,7 +567,6 @@ $(BLD)/callproc.$(O) : \ $(SRC)/commands.h \ $(SRC)/composite.h \ $(SRC)/epaths.h \ - $(SRC)/syswait.h \ $(SRC)/w32.h \ $(NT_INC)/sys/file.h \ $(NT_INC)/unistd.h \ @@ -581,6 +580,7 @@ $(BLD)/callproc.$(O) : \ $(PROCESS_H) \ $(SYSSIGNAL_H) \ $(SYSTTY_H) \ + $(SYSWAIT_H) \ $(TERMHOOKS_H) $(BLD)/casefiddle.$(O) : \ @@ -713,6 +713,7 @@ $(BLD)/dired.$(O) : \ $(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 \ @@ -721,7 +722,6 @@ $(BLD)/dired.$(O) : \ $(CHARSET_H) \ $(CODING_H) \ $(CONFIG_H) \ - $(DIR_H) \ $(FILEMODE_H) \ $(GRP_H) \ $(LISP_H) \ @@ -1174,11 +1174,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 \ @@ -1217,7 +1217,6 @@ $(BLD)/w32inevt.$(O) : \ $(BLD)/w32proc.$(O) : \ $(SRC)/w32proc.c \ - $(SRC)/syswait.h \ $(SRC)/w32.h \ $(SRC)/w32common.h \ $(SRC)/w32heap.h \ @@ -1231,6 +1230,7 @@ $(BLD)/w32proc.$(O) : \ $(PROCESS_H) \ $(SYSSIGNAL_H) \ $(SYSTIME_H) \ + $(SYSWAIT_H) \ $(W32TERM_H) $(BLD)/w32console.$(O) : \ @@ -1275,7 +1275,6 @@ $(BLD)/process.$(O) : \ $(SRC)/composite.h \ $(SRC)/gnutls.h \ $(SRC)/sysselect.h \ - $(SRC)/syswait.h \ $(SRC)/termopts.h \ $(NT_INC)/arpa/inet.h \ $(NT_INC)/netdb.h \ @@ -1298,6 +1297,7 @@ $(BLD)/process.$(O) : \ $(SYSSIGNAL_H) \ $(SYSTIME_H) \ $(SYSTTY_H) \ + $(SYSWAIT_H) \ $(TERMHOOKS_H) \ $(W32TERM_H) \ $(WINDOW_H) @@ -1381,7 +1381,6 @@ $(BLD)/sysdep.$(O) : \ $(SRC)/blockinput.h \ $(SRC)/cm.h \ $(SRC)/sysselect.h \ - $(SRC)/syswait.h \ $(SRC)/termchar.h \ $(SRC)/termopts.h \ $(NT_INC)/netdb.h \ @@ -1406,6 +1405,7 @@ $(BLD)/sysdep.$(O) : \ $(SYSSIGNAL_H) \ $(SYSTIME_H) \ $(SYSTTY_H) \ + $(SYSWAIT_H) \ $(TERMHOOKS_H) \ $(WINDOW_H) diff --git a/src/msdos.c b/src/msdos.c index dd05a8b2c5d..433bf1074d8 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -1275,7 +1275,6 @@ 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; } @@ -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 @@ -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 = 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/nsfns.m b/src/nsfns.m index e8bf696e7f5..428cfcb9a10 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2243,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; diff --git a/src/nsterm.h b/src/nsterm.h index 2e868b86caf..005701ed415 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -630,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; }; diff --git a/src/nsterm.m b/src/nsterm.m index 3640ac0c5e8..80dc0ba6fc3 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -30,6 +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 <fcntl.h> #include <math.h> #include <pthread.h> #include <sys/types.h> @@ -41,10 +42,6 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include <c-strcase.h> #include <ftoastr.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - #include "lisp.h" #include "blockinput.h" #include "sysselect.h" @@ -333,6 +330,7 @@ hold_event (struct input_event *event) 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 @@ -1188,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; } @@ -1889,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); @@ -1898,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 (); + } } } @@ -3464,6 +3458,14 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, /* NSTRACE (ns_select); */ + 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; @@ -3863,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; @@ -4574,7 +4575,7 @@ 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) == 1 && c == 'g') @@ -6953,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); diff --git a/src/process.c b/src/process.c index 5fe6a6540f3..7b21d060cf8 100644 --- a/src/process.c +++ b/src/process.c @@ -91,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" @@ -196,11 +199,9 @@ static EMACS_INT update_tick; #ifndef NON_BLOCKING_CONNECT #ifdef HAVE_SELECT #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX) -#if O_NONBLOCK || 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 */ @@ -639,13 +640,7 @@ allocate_pty (void) #ifdef PTY_OPEN PTY_OPEN; #else /* no PTY_OPEN */ - { -# if 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) @@ -781,13 +776,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 the SIGCHLD handler and waitpid has been invoked on them; - otherwise they might fill up the kernel's process table. */ + 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. @@ -808,32 +812,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 the - 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); @@ -1583,20 +1577,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 -#ifdef SIGCHLD sigset_t blocked; -#endif /* 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; -#if HAVE_WORKING_VFORK - char **volatile save_environ; -#endif inchannel = outchannel = -1; @@ -1609,13 +1598,9 @@ 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. */ -#if 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 @@ -1644,7 +1629,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; @@ -1663,15 +1648,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) } #endif -#if O_NONBLOCK fcntl (inchannel, F_SETFL, O_NONBLOCK); fcntl (outchannel, F_SETFL, O_NONBLOCK); -#else -#if 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. */ @@ -1699,19 +1677,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) block_input (); -#ifdef SIGCHLD /* 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); -#endif - -#if HAVE_WORKING_VFORK - /* child_setup must clobber environ on systems with true vfork. - Protect it from permanent change. */ - save_environ = environ; -#endif #ifndef WINDOWSNT pid = vfork (); @@ -1819,10 +1789,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Emacs ignores SIGPIPE, but the child should not. */ signal (SIGPIPE, SIG_DFL); -#ifdef SIGCHLD /* Stop blocking signals in the child. */ pthread_sigmask (SIG_SETMASK, &empty_mask, 0); -#endif if (pty_flag) child_setup_tty (xforkout); @@ -1830,9 +1798,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object 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); #endif /* not WINDOWSNT */ @@ -1840,18 +1806,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Back in the parent process. */ -#if HAVE_WORKING_VFORK - environ = save_environ; -#endif - XPROCESS (process)->pid = pid; if (0 <= pid) XPROCESS (process)->alive = 1; /* Stop blocking signals in the parent. */ -#ifdef SIGCHLD pthread_sigmask (SIG_SETMASK, &empty_mask, 0); -#endif unblock_input (); if (pid < 0) @@ -1891,11 +1851,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) 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; @@ -1928,13 +1888,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. */ -#if 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) @@ -1948,15 +1904,8 @@ create_pty (Lisp_Object process) } #endif /* HAVE_PTYS */ -#if O_NONBLOCK fcntl (inchannel, F_SETFL, O_NONBLOCK); fcntl (outchannel, F_SETFL, O_NONBLOCK); -#else -#if 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. */ @@ -2912,13 +2861,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 !O_NONBLOCK && !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). */ @@ -3178,11 +3123,7 @@ usage: (make-network-process &rest ARGS) */) #ifdef NON_BLOCKING_CONNECT if (is_non_blocking_client) { -#if O_NONBLOCK ret = fcntl (s, F_SETFL, O_NONBLOCK); -#else - ret = fcntl (s, F_SETFL, O_NDELAY); -#endif if (ret < 0) { xerrno = errno; @@ -3395,13 +3336,7 @@ usage: (make-network-process &rest ARGS) */) chan_process[inch] = proc; -#if O_NONBLOCK fcntl (inch, F_SETFL, O_NONBLOCK); -#else -#if O_NDELAY - fcntl (inch, F_SETFL, O_NDELAY); -#endif -#endif p = XPROCESS (proc); @@ -4130,13 +4065,7 @@ server_accept_connection (Lisp_Object server, int channel) chan_process[s] = proc; -#if O_NONBLOCK fcntl (s, F_SETFL, O_NONBLOCK); -#else -#if O_NDELAY - fcntl (s, F_SETFL, O_NDELAY); -#endif -#endif p = XPROCESS (proc); @@ -4484,14 +4413,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; @@ -4680,7 +4603,7 @@ 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 emacs_abort (); @@ -4832,23 +4755,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. */ -#if O_NONBLOCK - else if (nread == -1 && errno == EAGAIN) - ; -#else -#if 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 @@ -4884,10 +4801,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, #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. */ @@ -5575,13 +5490,10 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, if (rv < 0) { - if (0 + if (errno == EAGAIN #ifdef EWOULDBLOCK || errno == EWOULDBLOCK #endif -#ifdef EAGAIN - || errno == EAGAIN -#endif ) /* Buffer is full. Wait, accepting input; that may allow the program @@ -5753,7 +5665,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, @@ -5891,7 +5803,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 { @@ -5899,7 +5811,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) */ } @@ -6004,6 +5916,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. @@ -6014,6 +5947,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)) { @@ -6043,12 +5977,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; @@ -6056,96 +5989,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 - parse_signal ("term", SIGTERM); -#ifdef SIGHUP - parse_signal ("hup", SIGHUP); -#endif - parse_signal ("int", SIGINT); -#ifdef SIGQUIT - parse_signal ("quit", SIGQUIT); -#endif - parse_signal ("ill", SIGILL); - parse_signal ("abrt", SIGABRT); -#ifdef SIGEMT - parse_signal ("emt", SIGEMT); -#endif -#ifdef SIGKILL - parse_signal ("kill", SIGKILL); -#endif - parse_signal ("fpe", SIGFPE); -#ifdef SIGBUS - parse_signal ("bus", SIGBUS); -#endif - parse_signal ("segv", SIGSEGV); -#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, @@ -6227,35 +6076,35 @@ process has been transmitted to the serial port. */) return process; } -/* If the status of the process DESIRED has changed, return true and - set *STATUS to its exit status; otherwise, return false. - If HAVE is nonnegative, assume that HAVE = waitpid (HAVE, STATUS, ...) - has already been invoked, and do not invoke waitpid again. */ - -static bool -process_status_retrieved (pid_t desired, pid_t have, int *status) -{ - if (have < 0) - { - /* 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. */ - do - have = waitpid (desired, status, WNOHANG | WUNTRACED); - while (have < 0 && errno == EINTR); - } - - return have == desired; -} - -/* If PID is nonnegative, the child process PID with wait status W has - changed its status; record this and return true. - - If PID is negative, ignore W, and look for known child processes - of Emacs whose status have changed. For each one found, record its new - status. +/* 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 @@ -6278,20 +6127,15 @@ process_status_retrieved (pid_t desired, pid_t have, int *status) ** Malloc WARNING: This should never call malloc either directly or indirectly; if it does, that is a bug */ -void -record_child_status_change (pid_t pid, int w) +static void +handle_child_signal (int sig) { -#ifdef SIGCHLD - - /* On POSIXish hosts, record at most one child only if we already - know one child that has exited. */ - bool record_at_most_one_child = 0 <= pid; - Lisp_Object tail; /* Find the process that signaled us, and record its status. */ - /* The process can have been deleted by Fdelete_process. */ + /* 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)) { bool all_pids_are_fixnums @@ -6305,12 +6149,8 @@ record_child_status_change (pid_t pid, int w) deleted_pid = XINT (xpid); else deleted_pid = XFLOAT_DATA (xpid); - if (process_status_retrieved (deleted_pid, pid, &w)) - { - XSETCAR (tail, Qnil); - if (record_at_most_one_child) - return; - } + if (child_status_changed (deleted_pid, 0, 0)) + XSETCAR (tail, Qnil); } } @@ -6319,15 +6159,17 @@ record_child_status_change (pid_t pid, int w) { Lisp_Object proc = XCDR (XCAR (tail)); struct Lisp_Process *p = XPROCESS (proc); - if (p->alive && process_status_retrieved (p->pid, pid, &w)) + int status; + + if (p->alive && child_status_changed (p->pid, &status, WUNTRACED)) { /* 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)) + if (WIFSIGNALED (status) || WIFEXITED (status)) { int clear_desc_flag = 0; p->alive = 0; @@ -6341,44 +6183,8 @@ record_child_status_change (pid_t pid, int w) FD_CLR (p->infd, &non_keyboard_wait_mask); } } - - /* 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 (record_at_most_one_child) - return; } } - - if (0 <= pid) - { - /* The caller successfully waited for a pid but no asynchronous - process was found for it, so this is a synchronous process. */ - - 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); - } -#endif -} - -#ifdef SIGCHLD - -static void -handle_child_signal (int sig) -{ - record_child_status_change (-1, 0); } static void @@ -6386,8 +6192,6 @@ deliver_child_signal (int sig) { deliver_process_signal (sig, handle_child_signal); } - -#endif /* SIGCHLD */ static Lisp_Object @@ -7236,7 +7040,6 @@ init_process_emacs (void) inhibit_sentinels = 0; -#ifdef SIGCHLD #ifndef CANNOT_DUMP if (! noninteractive || initialized) #endif @@ -7245,7 +7048,6 @@ init_process_emacs (void) emacs_sigaction_init (&action, deliver_child_signal); sigaction (SIGCHLD, &action, 0); } -#endif FD_ZERO (&input_wait_mask); FD_ZERO (&non_keyboard_wait_mask); @@ -7272,9 +7074,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; @@ -7312,9 +7112,7 @@ init_process_emacs (void) #ifdef HAVE_GETSOCKNAME ADD_SUBFEATURE (QCservice, Qt); #endif -#if O_NONBLOCK || O_NDELAY ADD_SUBFEATURE (QCserver, Qt); -#endif for (sopt = socket_options; sopt->name; sopt++) subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures); @@ -7403,9 +7201,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 74d1a124060..a0521689abf 100644 --- a/src/process.h +++ b/src/process.h @@ -185,23 +185,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 +198,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/sysdep.c b/src/sysdep.c index 06dc41b511e..5291c5d59aa 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -101,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" @@ -134,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 @@ -155,7 +154,6 @@ get_current_dir_name (void) return NULL; strcpy (buf, pwd); } -#ifdef HAVE_GETCWD else { size_t buf_size = 1024; @@ -179,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 @@ -284,45 +266,74 @@ init_baud_rate (int fd) #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) + pid_t pid; + + /* 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) { - int status; - int wait_result = waitpid (pid, &status, 0); - if (wait_result < 0) - { - if (errno != EINTR) - break; - } - else - { - record_child_status_change (wait_result, status); - break; - } + /* 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); } /* @@ -446,20 +457,15 @@ static void restore_signal_handlers (struct save_signal *); void sys_suspend (void) { -#if defined (SIGTSTP) && !defined (MSDOS) - - { - pid_t pgrp = getpgrp (); - 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. */ @@ -471,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; @@ -509,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) @@ -521,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 @@ -578,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 @@ -1036,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)] = @@ -1055,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. @@ -1275,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)); @@ -1284,11 +1286,9 @@ reset_sys_modes (struct tty_display_info *tty_out) old_fcntl_owner[fileno (tty_out->input)]); } #endif /* F_SETOWN */ -#if 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), @@ -1513,9 +1513,7 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler) /* When handling a signal, block nonfatal system signals that are caught by Emacs. This makes race conditions less likely. */ sigaddset (&action->sa_mask, SIGALRM); -#ifdef SIGCHLD sigaddset (&action->sa_mask, SIGCHLD); -#endif #ifdef SIGDANGER sigaddset (&action->sa_mask, SIGDANGER); #endif @@ -1695,18 +1693,11 @@ init_signals (bool dumping) # 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 @@ -1726,9 +1717,7 @@ init_signals (bool dumping) # ifdef SIGGRANT sys_siglist[SIGGRANT] = "Monitor mode granted"; # endif -# ifdef SIGHUP sys_siglist[SIGHUP] = "Hangup"; -# endif sys_siglist[SIGILL] = "Illegal instruction"; sys_siglist[SIGINT] = "Interrupt"; # ifdef SIGIO @@ -1740,9 +1729,7 @@ init_signals (bool dumping) # ifdef SIGIOT sys_siglist[SIGIOT] = "IOT trap"; # endif -# ifdef SIGKILL sys_siglist[SIGKILL] = "Killed"; -# endif # ifdef SIGLOST sys_siglist[SIGLOST] = "Resource lost"; # endif @@ -1755,9 +1742,7 @@ init_signals (bool dumping) # ifdef SIGPHONE sys_siglist[SIGWIND] = "SIGPHONE"; # endif -# ifdef SIGPIPE sys_siglist[SIGPIPE] = "Broken pipe"; -# endif # ifdef SIGPOLL sys_siglist[SIGPOLL] = "Pollable event occurred"; # endif @@ -1770,9 +1755,7 @@ init_signals (bool dumping) # 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 @@ -2242,82 +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) */ -#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. */ @@ -2377,19 +2284,7 @@ safe_strsignal (int code) int serial_open (char *port) { - int fd = -1; - - fd = emacs_open ((char*) port, - O_RDWR -#if O_NONBLOCK - | O_NONBLOCK -#else - | O_NDELAY -#endif -#if 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", diff --git a/src/syssignal.h b/src/syssignal.h index 2bf2f046aa5..8f9b5f0546a 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -54,26 +54,6 @@ char const *safe_strsignal (int) ATTRIBUTE_CONST; # define emacs_raise(sig) raise (sig) #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))) -#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 # define strsignal(sig) safe_strsignal (sig) #endif diff --git a/src/syswait.h b/src/syswait.h index aa4c4bcf527..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. */ @@ -52,10 +53,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif /* Defined in process.c. */ -extern void record_child_status_change (pid_t, int); +extern void record_deleted_pid (pid_t); /* Defined in sysdep.c. */ -extern void wait_for_termination (pid_t); -extern void interruptible_wait_for_termination (pid_t); +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 96549290da5..241875de52f 100644 --- a/src/term.c +++ b/src/term.c @@ -20,8 +20,9 @@ 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> @@ -55,14 +56,6 @@ 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$" @@ -2989,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; -#if 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); @@ -3023,10 +3012,8 @@ init_tty (const char *name, const char *terminal_type, int must_succeed) name); } -#if !O_IGNORE_CTTY - if (!ctty) + if (!O_IGNORE_CTTY && !ctty) dissociate_if_controlling_tty (fd); -#endif file = fdopen (fd, "w+"); tty->input = file; @@ -3375,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 diff --git a/src/termchar.h b/src/termchar.h index 5c57593c04f..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. */ diff --git a/src/termhooks.h b/src/termhooks.h index d1ee7138d67..5e73127a699 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -212,6 +212,11 @@ enum event_kind , NS_NONKEY_EVENT #endif +#ifdef HAVE_INOTIFY + /* File or directory was changed. */ + , FILE_NOTIFY_EVENT +#endif + }; /* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT diff --git a/src/textprop.c b/src/textprop.c index 379eafb73f7..1ce44ad60ac 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -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 @@ -1164,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 (;;) @@ -1302,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); @@ -1451,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 (;;) @@ -1565,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), @@ -1578,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), @@ -1589,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/unexcoff.c b/src/unexcoff.c index 966dd58cb6e..6e29951a962 100644 --- a/src/unexcoff.c +++ b/src/unexcoff.c @@ -332,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/unexelf.c b/src/unexelf.c index 121e6042fc9..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 diff --git a/src/vm-limit.c b/src/vm-limit.c index 2a71e88695a..befc01d400f 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c @@ -44,46 +44,26 @@ static POINTER data_space_start; 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" @@ -94,10 +74,8 @@ get_lim_data (void) lim_data = reserved_heap_size; } -#else -#if !defined (BSD4_2) && !defined (CYGWIN) +#elif defined MSDOS -#ifdef MSDOS void get_lim_data (void) { @@ -135,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. */ diff --git a/src/w32.c b/src/w32.c index 46433626802..e163a3a1ee3 100644 --- a/src/w32.c +++ b/src/w32.c @@ -101,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 @@ -119,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; @@ -149,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. */ @@ -172,7 +187,7 @@ 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" @@ -336,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) ( @@ -901,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; @@ -1519,6 +1544,50 @@ is_unc_volume (const char *filename) return 1; } +/* Emulate the Posix unsetenv. */ +int +unsetenv (const char *name) +{ + char *var; + size_t name_len; + int retval; + + 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 +sys_putenv (char *str) +{ + const char *const name_end = strchr (str, '='); + + if (name_end == NULL) + { + /* Remove the variable from the environment. */ + return unsetenv (str); + } + + return _putenv (str); +} + #define REG_ROOT "SOFTWARE\\GNU\\Emacs" LPBYTE @@ -1818,7 +1887,7 @@ 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)) @@ -2431,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]; @@ -2501,7 +2570,7 @@ closedir (DIR *dirp) xfree ((char *) dirp); } -struct direct * +struct dirent * readdir (DIR *dirp) { int downcase = !NILP (Vw32_downcase_file_names); @@ -2555,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 @@ -4616,8 +4685,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; @@ -4862,7 +4931,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; @@ -5090,7 +5159,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)), @@ -5105,7 +5174,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)), @@ -5854,7 +5923,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); diff --git a/src/w32.h b/src/w32.h index 8309a3cc23d..23eda830268 100644 --- a/src/w32.h +++ b/src/w32.h @@ -163,7 +163,6 @@ extern int sys_spawnve (int, char *, char **, char **); extern void register_child (int, int); extern void sys_sleep (int); -extern char *getwd (char *); extern int sys_link (const char *, const char *); @@ -181,4 +180,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 index 50724e5553c..5e9b61824ae 100644 --- a/src/w32common.h +++ b/src/w32common.h @@ -34,7 +34,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. extern SYSTEM_INFO sysinfo_cache; extern OSVERSIONINFO osinfo_cache; -extern unsigned long syspage_mask; +extern DWORD_PTR syspage_mask; extern int w32_major_version; extern int w32_minor_version; diff --git a/src/w32fns.c b/src/w32fns.c index 6458054013f..9aee60d7079 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -82,7 +82,6 @@ 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); @@ -223,7 +222,7 @@ SYSTEM_INFO sysinfo_cache; /* This gives us version, build, and platform identification. */ OSVERSIONINFO osinfo_cache; -unsigned long syspage_mask = 0; +DWORD_PTR syspage_mask = 0; /* The major and minor versions of NT. */ int w32_major_version; @@ -4870,18 +4869,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; @@ -6038,7 +6025,7 @@ typedef char guichar_t; 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) @@ -6170,9 +6157,9 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) filename = empty_unibyte_string; #ifdef CYGWIN - dir = Fcygwin_convert_path_to_windows (dir, Qt); + dir = Fcygwin_convert_file_name_to_windows (dir, Qt); if (SCHARS (filename) > 0) - filename = Fcygwin_convert_path_to_windows (filename, Qnil); + filename = Fcygwin_convert_file_name_to_windows (filename, Qnil); #endif CHECK_STRING (dir); @@ -6273,7 +6260,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) #endif /* NTGUI_UNICODE */ #ifdef CYGWIN - filename = Fcygwin_convert_path_from_windows (filename, Qt); + filename = Fcygwin_convert_file_name_from_windows (filename, Qt); #endif /* CYGWIN */ /* Strip the dummy filename off the end of the string if we @@ -7052,7 +7039,7 @@ cache_system_info (void) /* Cache page size, allocation unit, processor type, etc. */ GetSystemInfo (&sysinfo_cache); - syspage_mask = sysinfo_cache.dwPageSize - 1; + syspage_mask = (DWORD_PTR)sysinfo_cache.dwPageSize - 1; /* Cache os info. */ osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); @@ -7800,7 +7787,7 @@ emacs_abort (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", stack[j] - sizeof(void *)); + 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) diff --git a/src/w32menu.c b/src/w32menu.c index 36bf9574fdc..84fb1bdc71e 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -114,17 +114,6 @@ 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, @@ -389,8 +378,6 @@ set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p) if (! menubar_widget) deep_p = 1; - else if (pending_menu_activation && !deep_p) - deep_p = 1; if (deep_p) { diff --git a/src/w32proc.c b/src/w32proc.c index 2951df7ed89..ddc6826df98 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -1220,13 +1220,22 @@ waitpid (pid_t pid, int *status, int options) { QUIT; active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); - } while (active == WAIT_TIMEOUT); + } 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) { @@ -1240,7 +1249,6 @@ waitpid (pid_t pid, int *status, int options) else emacs_abort (); -get_result: if (!GetExitCodeProcess (wait_hnd[active], &retval)) { DebPrint (("Wait.GetExitCodeProcess failed with %lu\n", @@ -1275,33 +1283,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); - const 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; @@ -2157,6 +2139,10 @@ sys_kill (int pid, int sig) 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) { diff --git a/src/w32select.c b/src/w32select.c index 1b10c74cfe9..6a2a840f914 100644 --- a/src/w32select.c +++ b/src/w32select.c @@ -74,8 +74,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include "lisp.h" -#include "w32term.h" /* for all of the w32 includes */ #include "w32common.h" /* os_subtype */ +#include "w32term.h" /* for all of the w32 includes */ #include "keyboard.h" #include "blockinput.h" #include "charset.h" diff --git a/src/w32term.c b/src/w32term.c index e53fa5e7756..d7c5d075416 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -725,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); } @@ -1754,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; @@ -1773,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); @@ -1968,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); @@ -2000,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); } @@ -5482,7 +5472,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); @@ -6103,7 +6092,6 @@ 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; } diff --git a/src/w32term.h b/src/w32term.h index 98186a7d363..35842e60c16 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -217,8 +217,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); @@ -251,16 +249,10 @@ extern Lisp_Object x_get_focus_frame (struct frame *); 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 @@ -347,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 @@ -753,6 +741,21 @@ 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); diff --git a/src/window.c b/src/window.c index 9f3474fcd53..d7c2e8b236e 100644 --- a/src/window.c +++ b/src/window.c @@ -3250,8 +3250,7 @@ This function runs `window-scroll-functions' before running 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)) { @@ -3914,7 +3913,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); diff --git a/src/xdisp.c b/src/xdisp.c index 27d9fff0b7d..9464e87b362 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -515,9 +515,8 @@ 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. */ +/* Number of windows showing the buffer of the selected + window (or another buffer with the same base buffer). */ int buffer_shared; @@ -9643,7 +9642,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); } } @@ -9740,7 +9739,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); } } @@ -10889,8 +10888,53 @@ 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) +{ + /* The variable buffer_shared is set in redisplay_window and + indicates that we redisplay a buffer in different windows. */ + return (buffer_shared > 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 ***********************************************************************/ @@ -11196,7 +11240,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) { @@ -11310,12 +11354,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 (); @@ -11467,11 +11506,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; } @@ -11508,12 +11554,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 (); @@ -11543,9 +11584,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 @@ -12220,7 +12265,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 @@ -12231,7 +12275,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); @@ -12300,7 +12343,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. */ @@ -12329,7 +12371,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: @@ -12616,8 +12657,7 @@ text_outside_line_unchanged_p (struct window *w, 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) @@ -12935,6 +12975,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 old_frame) +{ + if (!EQ (old_frame, selected_frame) && FRAME_LIVE_P (XFRAME (old_frame))) + select_frame_for_redisplay (old_frame); +} #define STOP_POLLING \ do { if (! polling_stopped_here) stop_polling (); \ @@ -12961,7 +13010,7 @@ 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 @@ -13013,27 +13062,18 @@ redisplay_internal (void) backtrace.debug_on_exit = 0; backtrace_list = &backtrace; - { - Lisp_Object tail, frame; - - 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); @@ -13071,25 +13111,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); @@ -13116,7 +13151,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++; } @@ -13124,24 +13159,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 @@ -13191,18 +13217,16 @@ redisplay_internal (void) } } 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; @@ -13257,9 +13281,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 @@ -13433,7 +13455,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; @@ -13445,8 +13467,6 @@ redisplay_internal (void) if (consider_all_windows_p) { - Lisp_Object tail, frame; - FOR_EACH_FRAME (tail, frame) XFRAME (frame)->updated_p = 0; @@ -13520,14 +13540,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) { @@ -13656,7 +13673,6 @@ redisplay_internal (void) frames here explicitly. */ if (!pending) { - Lisp_Object tail, frame; int new_count = 0; FOR_EACH_FRAME (tail, frame) @@ -13747,17 +13763,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; } @@ -14221,7 +14233,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. @@ -15510,8 +15522,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 @@ -15533,8 +15544,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. */ @@ -15555,14 +15565,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) if (BYTEPOS (opoint) < CHARPOS (opoint)) emacs_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 ())) + if (mode_line_update_needed (w)) update_mode_line = 1; /* Count number of windows showing the selected buffer. An indirect @@ -15710,6 +15713,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. */ @@ -15803,8 +15835,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; @@ -23499,7 +23530,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; @@ -27678,12 +27711,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); diff --git a/src/xfns.c b/src/xfns.c index 1f98e9fc8c7..7e832c3a95f 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3848,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 ************************************************************************/ diff --git a/src/xftfont.c b/src/xftfont.c index 372ed87705f..181a1da9b38 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -369,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; @@ -387,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 diff --git a/src/xterm.c b/src/xterm.c index 463d82b4ee2..e9e99574663 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -669,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); } @@ -2033,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); @@ -2075,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); @@ -2269,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); @@ -2301,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); } @@ -7925,7 +7902,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); @@ -9502,7 +9478,6 @@ 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; } @@ -9933,10 +9908,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. */ @@ -10153,7 +10125,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; diff --git a/src/xterm.h b/src/xterm.h index 6ef3d11fe48..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) |