diff options
| author | Tom Tromey <tromey@redhat.com> | 2013-03-08 11:57:29 -0700 |
|---|---|---|
| committer | Tom Tromey <tromey@redhat.com> | 2013-03-08 11:57:29 -0700 |
| commit | 71f91792e3013b397996905224f387da5cc539a9 (patch) | |
| tree | 4c3d3ba909e76deea1cdf73b73fca67a57149465 /src | |
| parent | 6f4de085f065e11f4df3195d47479f28f5ef08ba (diff) | |
| parent | b5426561089d39f18b42bed9dbfcb531f43ed562 (diff) | |
| download | emacs-71f91792e3013b397996905224f387da5cc539a9.tar.gz | |
merge from trunk
Diffstat (limited to 'src')
| -rw-r--r-- | src/.gdbinit | 3 | ||||
| -rw-r--r-- | src/ChangeLog | 1259 | ||||
| -rw-r--r-- | src/ChangeLog.10 | 2 | ||||
| -rw-r--r-- | src/Makefile.in | 34 | ||||
| -rw-r--r-- | src/alloc.c | 49 | ||||
| -rw-r--r-- | src/autodeps.mk | 1 | ||||
| -rw-r--r-- | src/bidi.c | 38 | ||||
| -rw-r--r-- | src/buffer.c | 14 | ||||
| -rw-r--r-- | src/buffer.h | 61 | ||||
| -rw-r--r-- | src/callint.c | 58 | ||||
| -rw-r--r-- | src/callproc.c | 82 | ||||
| -rw-r--r-- | src/ccl.c | 3 | ||||
| -rw-r--r-- | src/charset.c | 4 | ||||
| -rw-r--r-- | src/cm.c | 3 | ||||
| -rw-r--r-- | src/coding.c | 86 | ||||
| -rw-r--r-- | src/coding.h | 34 | ||||
| -rw-r--r-- | src/composite.c | 27 | ||||
| -rw-r--r-- | src/conf_post.h | 4 | ||||
| -rw-r--r-- | src/deps.mk | 2 | ||||
| -rw-r--r-- | src/dired.c | 126 | ||||
| -rw-r--r-- | src/dispnew.c | 108 | ||||
| -rw-r--r-- | src/doc.c | 19 | ||||
| -rw-r--r-- | src/doprnt.c | 2 | ||||
| -rw-r--r-- | src/editfns.c | 51 | ||||
| -rw-r--r-- | src/emacs.c | 41 | ||||
| -rw-r--r-- | src/eval.c | 2 | ||||
| -rw-r--r-- | src/fileio.c | 498 | ||||
| -rw-r--r-- | src/filelock.c | 477 | ||||
| -rw-r--r-- | src/fns.c | 29 | ||||
| -rw-r--r-- | src/font.c | 58 | ||||
| -rw-r--r-- | src/font.h | 2 | ||||
| -rw-r--r-- | src/fontset.c | 5 | ||||
| -rw-r--r-- | src/frame.c | 45 | ||||
| -rw-r--r-- | src/frame.h | 104 | ||||
| -rw-r--r-- | src/ftfont.c | 7 | ||||
| -rw-r--r-- | src/gtkutil.c | 21 | ||||
| -rw-r--r-- | src/image.c | 10 | ||||
| -rw-r--r-- | src/indent.c | 119 | ||||
| -rw-r--r-- | src/indent.h | 12 | ||||
| -rw-r--r-- | src/insdel.c | 16 | ||||
| -rw-r--r-- | src/intervals.h | 4 | ||||
| -rw-r--r-- | src/keyboard.c | 668 | ||||
| -rw-r--r-- | src/keyboard.h | 2 | ||||
| -rw-r--r-- | src/keymap.c | 8 | ||||
| -rw-r--r-- | src/lisp.h | 168 | ||||
| -rw-r--r-- | src/lread.c | 75 | ||||
| -rw-r--r-- | src/macros.c | 12 | ||||
| -rw-r--r-- | src/makefile.w32-in | 6 | ||||
| -rw-r--r-- | src/marker.c | 28 | ||||
| -rw-r--r-- | src/mem-limits.h | 43 | ||||
| -rw-r--r-- | src/msdos.c | 45 | ||||
| -rw-r--r-- | src/msdos.h | 2 | ||||
| -rw-r--r-- | src/nsfns.m | 18 | ||||
| -rw-r--r-- | src/nsfont.m | 16 | ||||
| -rw-r--r-- | src/nsmenu.m | 4 | ||||
| -rw-r--r-- | src/nsselect.m | 2 | ||||
| -rw-r--r-- | src/nsterm.h | 11 | ||||
| -rw-r--r-- | src/nsterm.m | 273 | ||||
| -rw-r--r-- | src/pre-crt0.c | 10 | ||||
| -rw-r--r-- | src/print.c | 43 | ||||
| -rw-r--r-- | src/process.c | 90 | ||||
| -rw-r--r-- | src/process.h | 8 | ||||
| -rw-r--r-- | src/profiler.c | 2 | ||||
| -rw-r--r-- | src/ralloc.c | 188 | ||||
| -rw-r--r-- | src/region-cache.h | 2 | ||||
| -rw-r--r-- | src/search.c | 258 | ||||
| -rw-r--r-- | src/sheap.c | 4 | ||||
| -rw-r--r-- | src/sound.c | 2 | ||||
| -rw-r--r-- | src/syntax.c | 12 | ||||
| -rw-r--r-- | src/sysdep.c | 30 | ||||
| -rw-r--r-- | src/term.c | 4 | ||||
| -rw-r--r-- | src/termcap.c | 2 | ||||
| -rw-r--r-- | src/textprop.c | 241 | ||||
| -rw-r--r-- | src/unexaix.c | 95 | ||||
| -rw-r--r-- | src/unexcoff.c | 4 | ||||
| -rw-r--r-- | src/unexw32.c | 2 | ||||
| -rw-r--r-- | src/vm-limit.c | 111 | ||||
| -rw-r--r-- | src/w16select.c | 6 | ||||
| -rw-r--r-- | src/w32.c | 748 | ||||
| -rw-r--r-- | src/w32.h | 4 | ||||
| -rw-r--r-- | src/w32fns.c | 21 | ||||
| -rw-r--r-- | src/w32heap.c | 6 | ||||
| -rw-r--r-- | src/w32notify.c | 12 | ||||
| -rw-r--r-- | src/w32proc.c | 95 | ||||
| -rw-r--r-- | src/w32term.c | 163 | ||||
| -rw-r--r-- | src/w32uniscribe.c | 6 | ||||
| -rw-r--r-- | src/window.c | 97 | ||||
| -rw-r--r-- | src/window.h | 63 | ||||
| -rw-r--r-- | src/xdisp.c | 771 | ||||
| -rw-r--r-- | src/xfaces.c | 4 | ||||
| -rw-r--r-- | src/xfns.c | 11 | ||||
| -rw-r--r-- | src/xgselect.c | 2 | ||||
| -rw-r--r-- | src/xmenu.c | 10 | ||||
| -rw-r--r-- | src/xml.c | 2 | ||||
| -rw-r--r-- | src/xselect.c | 23 | ||||
| -rw-r--r-- | src/xterm.c | 113 |
96 files changed, 4662 insertions, 3504 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 4688b0a4421..c4604e6e2b0 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -358,7 +358,6 @@ end define pwinx set $w = $arg0 - xgetint $w->sequence_number if ($w->mini_p != Qnil) printf "Mini " end @@ -607,7 +606,7 @@ Pretty print all glyphs in it->glyph_row. end define prowlims - printf "edges=(%d,%d),r2l=%d,cont=%d,trunc=(%d,%d),at_zv=%d\n", $arg0->minpos.charpos, $arg0->maxpos.charpos, $arg0->reversed_p, $arg0->continued_p, $arg0->truncated_on_left_p, $arg0->truncated_on_right_p, $arg0->ends_at_zv_p + printf "edges=(%d,%d),enb=%d,r2l=%d,cont=%d,trunc=(%d,%d),at_zv=%d\n", $arg0->minpos.charpos, $arg0->maxpos.charpos, $arg0->enabled_p, $arg0->reversed_p, $arg0->continued_p, $arg0->truncated_on_left_p, $arg0->truncated_on_right_p, $arg0->ends_at_zv_p end document prowlims Print important attributes of a glyph_row structure. diff --git a/src/ChangeLog b/src/ChangeLog index 115b8d42915..fe084b160c4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,1254 @@ +2013-03-08 Dmitry Antipov <dmantipov@yandex.ru> + + * search.c (find_newline): Accept start and end byte positions + as arguments and allow -1 if not known. + (find_newline_no_quit): Likewise for start position. + * lisp.h (find_newline, find_newline_no_quit): Adjust prototype. + * bidi.c (bidi_find_paragraph_start): Pass byte position to + find_newline_no_quit, thus eliminating CHAR_TO_BYTE. + * editfns.c (Fconstrain_to_field): Break long line. Adjust + call to find_newline. + * indent.c (vmotion): Adjust calls to find_newline_no_quit. + Use DEC_BOTH to start next search from the previous buffer + position, where appropriate. + * xdisp.c (back_to_previous_line_start, forward_to_next_line_start) + (get_visually_first_element, move_it_vertically_backward): Likewise. + Obtain byte position from the display iterator, where appropriate. + +2013-03-08 Paul Eggert <eggert@cs.ucla.edu> + + print.c, process.c: Use bool for booleans. + * lisp.h (wait_reading_process_output): + * print.c (print_output_debug_flag, PRINTDECLARE, printchar) + (strout, debug_output_compilation_hack, float_to_string, print) + (print_object): + * process.c (kbd_is_on_hold, inhibit_sentinels, process_output_skip) + (decode_status, status_message, create_process, create_pty) + (Fmake_network_process, Fnetwork_interface_info) + (wait_reading_process_output, read_process_output) + (write_queue_push, write_queue_pop, process_send_signal) + (handle_child_signal, keyboard_bit_set, kbd_on_hold_p): + * process.h (struct Lisp_Process, inhibit_sentinels, kbd_on_hold_p): + Use bool for booleans. + * process.c (Fnetwork_interface_list): Remove unused local. + (connect_counter): Now EMACS_INT, not int. + +2013-03-08 Dmitry Antipov <dmantipov@yandex.ru> + + * bidi.c (bidi_fetch_char): Swap first and second arguments + to match other functions accepting character and byte positions. + Adjust comment. + (bidi_resolve_explicit_1, bidi_level_of_next_char): Adjust users. + (bidi_paragraph_init): Likewise. Use DEC_BOTH which is faster + when you need just to move to the previous buffer position. + * xdisp.c (Fcurrent_bidi_paragraph_direction): Use DEC_BOTH. + +2013-03-07 Eli Zaretskii <eliz@gnu.org> + + * .gdbinit (prowlims): Display the enabled_p flag of the row. + +2013-03-07 Dmitry Antipov <dmantipov@yandex.ru> + + Avoid character to byte conversions in motion subroutines. + * indent.h (compute_motion, vmotion): Add byte position argument. + * indent.c (compute_motion): Use it and avoid CHAR_TO_BYTE. + Add eassert. + (Fcompute_motion): Break long line. Adjust call to compute_motion. + Use list5 for return value. + (vmotion): Use byte position argument and avoid call to CHAR_TO_BYTE. + Adjust comments, style and calls to compute_motion. + (Fvertical_motion): Adjust call to vmotion. + * window.c (Fdelete_other_windows_internal): Record window start + byte position and adjust call to vmotion. + (window_scroll_line_based): Likewise with call to compute_motion. + Use SET_PT_BOTH. + (Frecenter): Adjust calls to vmotion. + +2013-03-07 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (list2i, list3i): New functions. + (list4i): Move from window.c and make LISP_INLINE. + * editfns.c (make_lisp_time): + * fns.c (Flocale_info): + * keyboard.c (parse_modifiers): + * xterm.c (x_ewmh_activate_frame): Use list2i. + * instel.c (signal_after_change): + * nsfns.m (Fx_server_version, Fxw_color_values): + * w32fns.c (Fxw_color_values, Fx_server_version): + * xfns.c (Fxw_color_values, Fx_server_version): Use list3i. + * fileio.c (Fvisited_file_modtime): + * nsfns.m (Fns_display_usable_bounds): + * w32.c (ltime): Use list4i. + +2013-03-06 Eli Zaretskii <eliz@gnu.org> + + * search.c (find_newline_no_quit): Rename from find_next_newline. + Add commentary. + + * lisp.h (find_newline_no_quit): Rename prototype. + + * xdisp.c (back_to_previous_line_start) + (forward_to_next_line_start, get_visually_first_element) + (move_it_vertically_backward): Callers of find_newline_no_quit changed. + * indent.c (vmotion): Callers of find_newline_no_quit changed. + * bidi.c (bidi_find_paragraph_start): Callers of + find_newline_no_quit changed. + + * msdos.c: Change encoding to cp850. (Bug#13879) + (fr_keyboard, it_keyboard, dk_keyboard): Update keyboard layouts. + +2013-03-06 Dmitry Antipov <dmantipov@yandex.ru> + + Coding system support cleanup and minor refactoring. + * coding.h (enum coding_result_code): Remove + CODING_RESULT_INCONSISTENT_EOL and CODING_RESULT_INSUFFICIENT_MEM. + (toplevel): Remove unused CODING_MODE_INHIBIT_INCONSISTENT_EOL. + (CODING_MODE_LAST_BLOCK, CODING_MODE_SELECTIVE_DISPLAY) + (CODING_MODE_DIRECTION, CODING_MODE_FIXED_DESTINATION) + (CODING_MODE_SAFE_ENCODING): Rearrange bit values. + (decode_coding_region, encode_coding_region, decode_coding_string): + Remove unused compatibility macros. + * coding.c (Qinconsistent_eol, Qinsufficient_memory): Remove. + (record_conversion_result): Adjust user. + (syms_of_coding): Likewise. + (ALLOC_CONVERSION_WORK_AREA): Use SAFE_ALLOCA. + (decode_coding, encode_coding): Add USE_SAFE_ALLOCA and SAFE_FREE. + (decode_coding_object): Simplify since xrealloc never returns NULL. + Add eassert. + +2013-03-06 Paul Eggert <eggert@cs.ucla.edu> + + Fix a build failure on OpenBSD 4.x and MirBSD (Bug#13881). + * sysdep.c (list_system_processes) + [BSD_SYSTEM && !DARWIN_OS && !__FreeBSD__]: + Make it a stub in this case; otherwise the build might fail, + and this code hasn't been tested on such hosts anyway. + Problem reported by Nelson H. F. Beebe in + <http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00021.html> + and analyzed by JĂ©rĂ©mie Courrèges-Anglas in + <http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00062.html>. + +2013-03-06 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (find_next_newline_no_quit): Rename to find_next_newline. + * xdisp.c (back_to_previous_line_start, forward_to_next_line_start) + (get_visually_first_element, move_it_vertically_backward): Ajust users. + * bidi.c (bidi_find_paragraph_start): Likewise. + * indent.c (vmotion): Likewise. + +2013-03-05 Paul Eggert <eggert@cs.ucla.edu> + + FILE's lock is now always .#FILE and may be a regular file (Bug#13807). + * filelock.c: Include <c-ctype.h>. + (MAX_LFINFO): New top-level constant. + (lock_info_type): Remove members pid, boot_time. Add members at, + dot, colon. Change user member to be the entire buffer, not a + pointer. This allows us to handle the case where a foreign + pid or boot time exceeds the local range. All uses changed. + (LINKS_MIGHT_NOT_WORK): New constant. + (FREE_LOCK_INFO): Remove, as the pieces no longer need freeing. + (defined_WINDOWSNT): Remove. + (MAKE_LOCK_NAME, file_in_lock_file_name): + Always use .#FILE (not .#-FILE) for the file lock, + even if it is a regular file. + (rename_lock_file): New function. + (create_lock_file): Use it. + (create_lock_file, read_lock_data): + Prefer a symbolic link for the lock file, falling back on a + regular file if symlinks don't work. Do not try to create + symlinks on MS-Windows, due to security hassles. Stick with + POSIXish functions (open, read, write, close, fchmod, readlink, symlink, + link, rename, unlink, mkstemp) when creating locks, as a GNUish + host may be using a Windowsish file system, and cannot use + MS-Windows-only system calls. Fall back on mktemp if mkstemp + doesn't work. Don't fail merely because of a symlink-contents + length limit in the current file system; fall back on regular + files. Increase the symlink contents length limit to 8 KiB, this + should be big enough for any real use and doesn't crunch the + stack. + (create_lock_file, lock_file_1, read_lock_data): + Simplify allocation of lock file buffers now that they fit in 8 KiB. + (lock_file_1): Return error number, not bool. All callers changed. + (ELOOP): New macro, if not already defined. + (read_lock_data): Return size of lock file contents, not Lisp object. + All callers changed. Handle a race condition if some other process + replaces a regular-file lock with a symlink lock or vice versa, + while we're trying to read the lock. + (current_lock_owner): Parse contents more carefully, to help avoid + confusing a regular-file lock with some other application's use + of the file. Check for lock file contents being too long, or + not parsing correctly. + (current_lock_owner, lock_file): + Allow foreign pid and boot times that exceed the local range. + (current_lock_owner, lock_if_free, lock_file): + Simplify allocation of lock file contents. + * w32.c (sys_rename_replace): New function, containing most of + the contents of the old sys_rename. + (sys_rename): Use it. + (fchmod): New dummy function. + * w32.h (sys_rename_replace, fchmod): New decls. + +2013-03-05 Eli Zaretskii <eliz@gnu.org> + + * bidi.c (bidi_resolve_explicit_1): Don't call CHAR_TO_BYTE or + bidi_count_bytes, as the callers now arrange for bidi_it->charpos + to be in sync with bidi_it->bytepos. Suggested by Dmitry Antipov + <dmantipov@yandex.ru>. + +2013-03-05 Dmitry Antipov <dmantipov@yandex.ru> + + * composite.c (get_composition_id, fill_gstring_header): + Use make_uninit_vector where appropriate. + * font.c (Ffont_get_glyphs, build_style_table): Likewise. + * xselect.c (clean_local_selection_data): Likewise. + +2013-03-04 Paul Eggert <eggert@cs.ucla.edu> + + Fix misuse of ImageMagick that caused core dump (Bug#13846). + * image.c (imagemagick_load_image): Calculate height and width + after flattening the image, not before. + +2013-03-04 Dmitry Antipov <dmantipov@yandex.ru> + + * font.c (Ffont_get_glyphs): Use convenient LGLYPH_NEW. + * ftfont.c (ftfont_shape_by_flt): Likewise. + * w32uniscribe.c (uniscribe_shape): Likewise. + +2013-03-02 Paul Eggert <eggert@cs.ucla.edu> + + The lock for FILE is now .#FILE or .#-FILE (Bug#13807). + The old approach, which fell back on DIR/.#FILE.0 through + DIR/.#FILE.9, had race conditions that could not be easily fixed. + If DIR/.#FILE is a non-symlink file, Emacs now does not create a + lock file for DIR/FILE; that is, DIR/FILE is no longer partly + protected by a lock if DIR/.#FILE is a non-symlink file ("partly" + because the locking mechanism was never reliable in that case). + This patch fixes this and other bugs discovered by a code + inspection that was prompted by + <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00531.html>. + Also, this patch switches to .#-FILE (not .#FILE) on MS-Windows, + to avoid interoperability problems between the MS-Windows and + non-MS-Windows implementations. MS-Windows and non-MS-Windows + instances of Emacs now ignore each others' locks. + * filelock.c (defined_WINDOWSNT): New constant. + (MAKE_LOCK_NAME, fill_in_lock_file_name): + Don't create DIR/.#FILE.0 through DIR/.#FILE.9. Instead, create + DIR/.#FILE symlinks on non-MS-Windows hosts, and DIR/.#-FILE + regular files on MS-Windows hosts. + (MAKE_LOCK_NAME, unlock_file, Ffile_locked_p): + Use SAFE_ALLOCA to avoid problems with long file names. + (MAX_LFINFO): Now a local constant, not a global macro. + (IS_LOCK_FILE): Remove. + (lock_file_1): Don't inspect errno if symlink call succeeds; + that's not portable. + (lock_file): Document that this function can return if lock + creation fails. + (lock_file): Don't access freed storage. + +2013-03-02 Andreas Schwab <schwab@linux-m68k.org> + + * lisp.h (XPNTR) [!USE_LSB_TAG]: Remove extra paren. (Bug#13734) + +2013-03-02 Paul Eggert <eggert@cs.ucla.edu> + + * textprop.c: Use bool for booleans. + (validate_interval_range, Fadd_text_properties) + (Fremove_text_properties): Prefer bool to int when either works. + +2013-03-02 Eli Zaretskii <eliz@gnu.org> + + * textprop.c (Fadd_text_properties, Fremove_text_properties): If + the interval tree changes as a side effect of calling + modify_region, re-do processing starting from the call to + validate_interval_range. (Bug#13743) + +2013-02-28 Eli Zaretskii <eliz@gnu.org> + + * w32.c (sys_open): Don't reset the flags for FD in fd_info[]. + (Bug#13546). + +2013-02-27 Eli Zaretskii <eliz@gnu.org> + + * filelock.c (create_lock_file) [WINDOWSNT]: Use _sopen with + _SH_DENYRW flag, instead of emacs_open, to deny any other process + access to the lock file until it is written and closed. + (Bug#13807) + +2013-02-27 Paul Eggert <eggert@cs.ucla.edu> + + * callint.c (Qcall_interactively): + * macros.c (Qexecute_kbd_macro): + Now static. + +2013-02-26 Bastien Guerry <bzg@gnu.org> + + * window.c (Frecenter): Tiny docstring enhancement. + +2013-02-26 Paul Eggert <eggert@cs.ucla.edu> + + Minor textprop integer cleanup. + * intervals.h, textprop.c (add_text_properties_from_list): + Return void, not int, since nobody uses the return value. + * textprop.c (validate_plist, add_properties, remove_properties) + (Fadd_text_properties): + Don't assume list length fits in int. + (interval_has_all_properties, interval_has_some_properties) + (interval_has_some_properties_list, add_properties, remove_properties) + (Fadd_text_properties, Fremove_text_properties) + (Fremove_list_of_text_properties, text_property_stickiness): + Use bool for booleans. + (Fadd_text_properties, Fremove_text_properties): + (Fremove_list_of_text_properties): + Reindent do-while as per GNU style. + +2013-02-25 Eli Zaretskii <eliz@gnu.org> + + Implement CLASH_DETECTION for MS-Windows. + + * filelock.c [WINDOWSNT]: Include w32.h. + (MAKE_LOCK_NAME): Don't use 'lock', it clashes with MS runtime + function of that name. Up-case the macro arguments. + (IS_LOCK_FILE): New macro. + (fill_in_lock_file_name): Use IS_LOCK_FILE instead of S_ISLNK. + (create_lock_file): New function, with body extracted from + lock_file_1. + [WINDOWSNT]: Implement lock files by writing a regular file with + the lock information as its contents. + (read_lock_data): New function, on Posix platforms just calls + emacs_readlinkat. + [WINDOWSNT]: Read the lock info from the file. + (current_lock_owner): Call read_lock_data instead of calling + emacs_readlinkat directly. + (lock_file) [WINDOWSNT]: Run the file name through + dostounix_filename. + + * w32proc.c (sys_kill): Support the case of SIG = 0, in which case + just check if the process by that PID exists. + + * w32.c (sys_open): Don't reset the _O_CREAT flag if _O_EXCL is + also present, as doing so will fail to error out if the file + already exists. + + * makefile.w32-in ($(BLD)/filelock.$(O)): Depend on src/w32.h. + + * textprop.c (Fadd_text_properties, Fremove_text_properties) + (Fremove_list_of_text_properties): Skip all of the intervals in + the region between START and END that already have resp. don't + have the requested properties, not just the first one. Add + assertions that the loop afterwards always modifies the + properties. (Bug#13743) + +2013-02-25 Stefan Monnier <monnier@iro.umontreal.ca> + + * callint.c (Fcall_interactively): Use the right lexical environment + for `interactive' specs (bug#13811). + * eval.c (Feval): Accept a lexical environment. + +2013-02-25 Paul Eggert <eggert@cs.ucla.edu> + + Simplify data_start configuration (Bug#13783). + This is a followon simplification to the fix for Bug#13650. + * Makefile.in (LD_FIRSTFLAG, LIB_GCC, CRT_DIR, LIB_STANDARD) + (START_FILES): Remove. All uses removed. + (otherobj): Remove $(VMLIMIT_OBJ), as it's now first. + (ALLOBJS): Move here from autodeps.mk, and with VMLIMITS_OBJ first. + (buildobj.h): Use it. + ($(ALLOBJS)): Depend on globals.h. + (temacs$(EXEEXT)): Use $(ALLOBJS). + * autodeps.mk (ALLOBJS): Move to Makefile.in. + * deps.mk (vm-limit.o): + * makefile.w32-in ($(BLD)/vm-limit.$(O)): + Do not depend on mem-limits.h. + * emacs.c (__do_global_ctors, __do_global_ctors_aux) + (__do_global_dtors, __CTOR_LIST__, __DTOR_LIST__) + [__GNUC__ && !ORDINARY_LINK]: Remove. + * mem-limits.h, pre-crt0.c: Remove. + * unexaix.c, unexcoff.c: Don't include mem-limits.h. + * unexcoff.c (etext): New decl. + (make_hdr): Use DATA_START instead of start_of_data. + * vm-limit.c: Move most of mem-limits.h's contents here. + (data_start): New decl. It's OK if this is approximate, + so simplify-away some unnecessary exactness. + (POINTER): Remove; all uses removed. + (data_space_start): Now char *, to avoid casts. + (exceeds_lisp_ptr): New function, replacing the old + EXCEEDS_LISP_PTR macro. All uses changed. + (check_memory_limits): Simplify and remove casts. + (start_of_data) [!CANNOT_DUMP || !SYSTEM_MALLOC]: Remove. + (memory_warnings): Use data_start instead of start_of_data. + +2013-02-24 Andreas Schwab <schwab@linux-m68k.org> + + * xdisp.c (set_message): Only check for debug-on-message if STRING + is a string. (Bug#13797) + +2013-02-24 Paul Eggert <eggert@cs.ucla.edu> + + Fix regression introduced by July 10 filelock.c patch. + * filelock.c (fill_in_lock_file_name): Fix crash caused by the + 2012-07-10 patch to this file. Reported by Eli Zaretskii in + <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00533.html> + and diagnosed by Andreas Schwab in + <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00534.html>. + +2013-02-22 Paul Eggert <eggert@cs.ucla.edu> + + Assume C89 or better. + * ralloc.c (SIZE, POINTER, NIL): + * vm-limit.c (POINTER): + Remove, replacing all uses with C89 equivalents. These old + symbols were present only for porting to pre-C89 platforms. + +2013-02-22 Claudio Bley <claudio.bley@gmail.com> + + * w32.c (emacs_gnutls_pull): Don't call 'select', and don't loop. + This avoids warning messages reported as part of Bug#13546. + +2013-02-21 Ken Brown <kbrown@cornell.edu> + + * sheap.c (report_sheap_usage): Fix arguments of message1_no_log. + +2013-02-20 Stefan Monnier <monnier@iro.umontreal.ca> + + * sheap.c (report_sheap_usage): Prefer message1_nolog. + + * keyboard.c (Qcommand_execute): New var. + (command_loop_1, read_char): Use it. + (Fcommand_execute): Remove, replace by an Elisp implementation. + (syms_of_keyboard): Adjust accordingly. + +2013-02-19 Daniel Colascione <dancol@dancol.org> + + * sheap.c (report_sheap_usage): Use message, not message1, so + that we don't try to create a buffer while we're in the middle + of dumping Emacs. Explain why. + +2013-02-20 Dmitry Antipov <dmantipov@yandex.ru> + + * search.c (find_newline): Return byte position in bytepos. + Adjust comment. + (find_next_newline_no_quit, find_before_next_newline): + Add bytepos argument. + * lisp.h (find_newline, find_next_newline_no_quit) + (find_before_next_newline): Adjust prototypes. + * bidi.c (bidi_find_paragraph_start): + * editfns.c (Fconstrain_to_field, Fline_end_position): + * indent.c (compute_motion, vmotion): + * xdisp.c (back_to_previous_line_start, forward_to_next_line_start): + (get_visually_first_element, move_it_vertically_backward): + Adjust users and avoid calls to CHAR_TO_BYTE where appropriate. + +2013-02-19 Eli Zaretskii <eliz@gnu.org> + + * w32proc.c (new_child): Avoid leaking handles if the subprocess + resources were not orderly released. + +2013-02-17 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (x_draw_vertical_border): For a window that is neither + the leftmost nor the rightmost, redraw both the left and the right + vertical borders. (Bug#13723) + +2013-02-17 Stefan Monnier <monnier@iro.umontreal.ca> + + * xml.c (init_libxml2_functions): + * sound.c (sound_warning): + * sheap.c (report_sheap_usage): + * process.c (wait_reading_process_output): + * msdos.c (XMenuActivate): + * macros.c (Fstart_kbd_macro, Fend_kbd_macro): + * keyboard.c (top_level_1): + * editfns.c (Fmessage, Fmessage_box): + * callint.c (Fcall_interactively): + * fns.c (Fyes_or_no_p): Prefer `message1' over `message'. + +2013-02-17 Jan Djärv <jan.h.d@swipnet.se> + + * xterm.c (syms_of_xterm): Move scroll-bar-adjust-thumb-portion ... + * frame.c (syms_of_frame): ... to here. + +2013-02-16 Eli Zaretskii <eliz@gnu.org> + + * w32.c (sys_chown): Remove unused function. + + * w32term.c <input_signal_count>: Declare 'volatile' + unconditionally. (Bug#9066) + + * w32.c (set_errno): Reset h_errno and don't set it to any other + value. Set errno instead. + (check_errno): Reset h_errno. + (sys_socket, socket_to_fd, sys_bind, sys_connect) + (sys_gethostname, sys_getservbyname, sys_getpeername) + (sys_shutdown, sys_setsockopt, sys_listen, sys_getsockname) + (sys_accept, sys_recvfrom, sys_sendto, fcntl, sys_read): Don't set + h_errno. + (sys_gethostbyname): Set h_errno only errors detected. + +2013-02-15 Paul Eggert <eggert@cs.ucla.edu> + + * process.c (h_errno) [!HAVE_H_ERRNO]: Remove unused decl. + +2013-02-15 Eli Zaretskii <eliz@gnu.org> + + * keyboard.c (read_char): Fix calculation of auto-save time out + when auto-save-timeout is less than 4. (Bug#13720) + + * w32proc.c (new_child): Free up to 2 slots of dead processes at a + time. Improve diagnostics in DebPrint. (Bug#13546) + + * w32.c (sys_socket, sys_bind, sys_connect, sys_gethostname) + (sys_gethostbyname, sys_getservbyname, sys_getpeername) + (sys_shutdown, sys_setsockopt, sys_listen, sys_getsockname) + (sys_accept, sys_recvfrom, sys_sendto, fcntl): In case of failure, + make sure errno is set to an appropriate value. (Bug#13546) + (socket_to_fd): Add assertion against indexing fd_info[] with a + value that is out of bounds. + (sys_accept): If fd is negative, do not set up the child_process + structure for reading. + +2013-02-15 Dmitry Antipov <dmantipov@yandex.ru> + + * composite.c (fill_gstring_header): Remove useless prototype. + Break long line. + * lisp.h (message_dolog, compile_pattern): Adjust prototype. + * print.c (PRINTDECLARE, print_object): + * search.c (compile_pattern, fast_looking_at, search_buffer): + (simple_search, boyer_moore, Freplace_match): + * xdisp.c (c_string_pos, number_of_chars, message_dolog): + (get_overlay_arrow_glyph_row, display_mode_element): + (decode_mode_spec_coding, message3): + * xfaces.c (face_at_string_position): Use bool for booleans. + Adjust comments. + +2013-02-15 Paul Eggert <eggert@cs.ucla.edu> + + Fix AIX port (Bug#13650). + * lisp.h (XPNTR) [!USE_LSB_TAG && DATA_SEG_BITS]: + Fix bug introduced in 2012-07-27 change. DATA_SEG_BITS, if set, + was #undeffed earlier, so it cannot be used as a macro here. + Use the constant and not the macro. + +2013-02-15 Eli Zaretskii <eliz@gnu.org> + + * w32proc.c (new_child): If no vacant slots are found in + child_procs[], make another pass looking for slots whose process + has exited or died. (Bug#13546) + + * w32.c (sys_pipe): When failing due to file descriptors above + MAXDESC, set errno to EMFILE. + (_sys_read_ahead): Update cp->status when failing to read serial + communications input, so that the status doesn't stay at + STATUS_READ_IN_PROGRESS. (Bug#13546) + +2013-02-14 Jan Djärv <jan.h.d@swipnet.se> + + * gtkutil.c (tb_size_cb): New function. + (xg_create_tool_bar): Connect size-allocate to tb_size_cb (Bug#13512). + +2013-02-14 Stefan Monnier <monnier@iro.umontreal.ca> + + * keyboard.c (active_maps): Fcurrent_active_maps expects a position, not + an event. + +2013-02-13 Stefan Monnier <monnier@iro.umontreal.ca> + + * keyboard.c (syms_of_keyboard): Further tweaks of docstring. + +2013-02-13 Dmitry Antipov <dmantipov@yandex.ru> + + * font.c (font_range): Add pos_byte argument. Adjust comment + and break long line. + * font.h (font_range): Adjust prototype. + * composite.c (autocmp_chars): Pass byte position to font_range. + Break long line. Remove useless prototype and format comment. + +2013-02-13 Glenn Morris <rgm@gnu.org> + + * keyboard.c (input-decode-map, key-translation-map): Doc fixes. + +2013-02-13 Paul Eggert <eggert@cs.ucla.edu> + + Improve AIX port some more (Bug#13650). + With this, it should be as good as it was in 23.3, though it's + still pretty bad: the dumped emacs does not run. See Mark Fleishman in + http://lists.gnu.org/archive/html/help-gnu-emacs/2011-04/msg00287.html + * unexaix.c (start_of_text): Remove. + (_data, _text): Declare as char[], not int, as AIX manual suggests. + (bias, lnnoptr, text_scnptr, data_scnptr, load_scnptr) + (orig_load_scnptr, orig_data_scnptr): + Now off_t, not long, since they are file offsets. + (make_hdr): Use _data, not start_of_data (). + This is the key part of the fix. + (make_hdr, unrelocate_symbols): Use off_t for file offsets. + (unrelocate_symbols): Cast pointers to intptr_t, not to ulong. + + * pre-crt0.c (data_start): Initialize to 1. + This ports to compilers that optimize the external declaration + 'int x = 0;' as if it were 'int x;' to shrink the executable. + + Improve AIX port (Bug#13650). + This doesn't fix the bug, but it makes progress: Emacs builds now. + * unexaix.c: Include inttypes.h, stdarg.h. + (report_error, report_error_1): Mark as _Noreturn. + (report_error): Don't report the wrong errno. + (report_error_1): Now varargs. All callers changed. + (make_hdr): Use uintptr_t, not unsigned, when converting pointers + to unsigned. Don't use ADDR_CORRECT, as it no longer exists. + (write_ptr): Use %p to print address rather than %lx and a cast + to unsigned long. Grow buffer a bit, to be safer. + +2013-02-13 Eli Zaretskii <eliz@gnu.org> + + * bidi.c (bidi_resolve_neutral): After finding the next + non-neutral character, accept NEUTRAL_ON type as well, because + directional control characters, such as LRE and RLE, have their + type converted to that by bidi_resolve_weak. This avoids aborts + when LRE/RLE follows a run of neutrals. + (bidi_move_to_visually_next): Assert that return value of + bidi_peek_at_next_level is non-negative. Negative values will + cause an infloop. + +2013-02-13 Paul Eggert <eggert@cs.ucla.edu> + + Minor getenv-related fixes. + * callproc.c (Fcall_process_region) [!DOS_NT]: + Avoid unnecessary duplicate call to getenv. + * callproc.c (init_callproc): + * dispnew.c (init_display): + * sysdep.c (sys_subshell): + Omit unnecessary cast of getenv or egetenv. + +2013-02-13 Juanma Barranquero <lekktu@gmail.com> + + * makefile.w32-in ($(BLD)/filelock.$(O), $(BLD)/sysdep.$(O)): + Update dependencies. + +2013-02-12 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (redisplay_internal): Don't set w->region_showing to the + marker's position. + (display_line): Set w->region_showing to the value of + it->region_beg_charpos, not to -1. This fixes redisplay + optimization when cursor is moved up after M->. (Bug#13623) + (Bug#13626) + (try_scrolling): Scroll text up more if point is too close to ZV + and inside the scroll margin. This makes sure point is moved + outside the scroll margin in these cases. + + * window.h (struct window): region_showing can no longer be + negative. + +2013-02-11 Paul Eggert <eggert@cs.ucla.edu> + + Tune by using memchr and memrchr. + * doc.c (Fsnarf_documentation): + * fileio.c (Fsubstitute_in_file_name): + * search.c (find_newline, scan_newline): + * xdisp.c (pos_visible_p, display_count_lines): + Use memchr and memrchr rather than scanning byte-by-byte. + * search.c (find_newline): Rename from scan_buffer. + Omit first arg TARGET, as it's always '\n'. All callers changed. + + Clean up read_key_sequence a tiny bit more. + * keyboard.c (read_char_x_menu_prompt) [HAVE_MENUS]: + (read_key_sequence): Remove unused locals. + +2013-02-11 Stefan Monnier <monnier@iro.umontreal.ca> + + Clean up read_key_sequence a bit; reread active keymaps after first event. + * keyboard.c (read_char, read_char_x_menu_prompt) + (read_char_minibuf_menu_prompt): + Replace nmaps+maps with a single `map' arg. + (follow_key): Operate on a single map. + (active_maps): New function. + (test_undefined): Also return true for nil bindings. + (read_key_sequence): Use active_maps to replace the arrays of keymaps with + a single (composed) keymap. Remember `first_event' to choose the right + set of active keymaps. Recompute the set of keymaps after receiving + the first event. Remove GOBBLE_FIRST_EVENT. + (syms_of_keyboard): Remove inhibit_local_menu_bar_menus. + * keyboard.h (read_char): Update declaration. + * lread.c (read_filtered_event): Adjust call to read_char. + +2013-02-11 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (move_it_vertically_backward, move_it_by_lines): + Don't use the limitation on backwards movement when lines are truncated + in the window. (Bug#13675) + +2013-02-11 Dmitry Antipov <dmantipov@yandex.ru> + + * marker.c (set_marker_internal): If desired position is passed + as a marker, avoid call to buf_charpos_to_bytepos. + * window.c (Fset_window_point): Omit redundant type checking. + (Fset_window_start): Likewise. Format comment. + (window_scroll_pixel_based): Use set_marker_restricted_both + with character and byte positions obtained from an iterator. + (Fset_window_configuration): Use set_marker_restricted_both. + * xdisp.c (message_dolog): Likewise. + +2013-02-10 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (move_it_vertically_backward, move_it_by_lines): + When text lines are longer than window's screen lines, don't move back + too far. This speeds up some redisplay operations. (Bug#13675) + +2013-02-10 Dmitry Antipov <dmantipov@yandex.ru> + + * syntax.c (scan_sexps_forward): Fix byte position calculation + Bug#13664 (a.k.a Bug#13667) introduced with 2013-02-08 change. + +2013-02-10 Paul Eggert <eggert@cs.ucla.edu> + + * fileio.c (Fexpand_file_name): Omit confusing pointer comparison + that was not needed. + +2013-02-09 Paul Eggert <eggert@cs.ucla.edu> + + Minor hashing refactoring. + * fns.c (SXHASH_REDUCE): Move to lisp.h. + (sxhash_float): Return EMACS_UINT, for consistency with the other + hash functions. + * lisp.h (INTMASK): Now a macro, since SXHASH_REDUCE is now a + non-static inline function and therefore can't use static vars. + (SXHASH_REDUCE): Move here from fns.c, and make it inline. + * profiler.c (hashfn_profiler): Use SXHASH_REDUCE, to be consistent + with the other hash functions. + +2013-02-09 Eli Zaretskii <eliz@gnu.org> + + * callproc.c (Fcall_process_region) [WINDOWSNT]: Make sure the + XXXXXX part of the temporary file pattern is not downcased even + when w32-downcase-file-names is non-nil. (Bug#13661) + + * xdisp.c (decode_mode_spec): Remove handling of %t. + + * msdos.c (careadlinkatcwd): Remove. + +2013-02-08 Stefan Monnier <monnier@iro.umontreal.ca> + + * lread.c (skip_dyn_bytes): New function (bug#12598). + (read1): Use it. Use getc instead of READCHAR to read bytes. + (load_each_byte): Remove. Update users. + +2013-02-08 Dmitry Antipov <dmantipov@yandex.ru> + + * search.c (scan_buffer): Calculate end byte position just once. + (scan_newline): Do not recalculate start_byte. + (search_command): Use eassert. + * syntax.c (struct lisp_parse_state): New member location_byte. + (scan_sexps_forward): Record from_byte and avoid redundant + character to byte position calculation ... + (Fparse_partial_sexp): ... here. Break too long line. + +2013-02-08 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (make_uninit_vector): New function. + * alloc.c (Fvector, Fmake_byte_code): + * ccl.c (Fregister_ccl_program): + * charset.c (Fdefine_charset_internal, define_charset_internal): + * coding.c (make_subsidiaries, Fdefine_coding_system_internal): + * composite.c (syms_of_composite): + * font.c (Fquery_font, Ffont_info, syms_of_font): + * fontset.c (FONT_DEF_NEW, Fset_fontset_font): + * ftfont.c (ftfont_shape_by_flt): + * indent.c (recompute_width_table): + * nsselect.m (clean_local_selection_data): + * syntax.c (init_syntax_once): + * w32unsubscribe.c (uniscribe_shape): + * window.c (Fcurrent_window_configuration): + * xfaces.c (Fx_family_fonts): + * xselect.c (selection_data_to_lisp_data): Use it. + +2013-02-07 Dmitry Antipov <dmantipov@yandex.ru> + + * coding.c (Fdefine_coding_system_internal): Use AREF where + argument is known to be a vector. + * fns.c (Flocale_info): Likewise for ASET. + * xselect.c (selection_data_to_lisp_data): Likewise for ASET. + * w32fns.c (w32_parse_hot_key): Likewise for ASIZE and AREF. + +2013-02-05 Jan Djärv <jan.h.d@swipnet.se> + + * nsmenu.m (update_frame_tool_bar): Check for negative tool bar + height. + + * nsterm.h (HAVE_NATIVE_FS): Define if OSX => 10.7. + (EmacsView): Add fs_is_native, fsIsNative, isFullscreen and + updateCollectionBehaviour. + + * nsterm.m (NEW_STYLE_FS): Remove. + (ns_last_use_native_fullscreen): New variable. + (x_make_frame_visible): Replace NEW_STYLE_FS with isFullscreen. + (x_set_window_size): Do not take title bar and tool bar into account + if isFullscreen returns YES. + (ns_fullscreen_hook): Replace NEW_STYLE_FS with isFullscreen. + (check_native_fs): New function. + (ns_select, ns_read_socket): Call check_native_fs if HAVE_NATIVE_FS. + (ns_term_init): Remove NEW_STYLE_FS. + (updateFrameSize:, windowWillResize:toSize:): Only adjust for title bar + and tool bar if isFullscreen returns NO. + (windowDidResize:): Replace NEW_STYLE_FS with fsIsNative. + (initFrameFromEmacs:): Initialize fs_is_native. Replace NEW_STYLE_FS + with HAVE_NATIVE_FS. + (window:willUseFullScreenPresentationOptions:): New method. + (windowDidEnterFullScreen:): Replace NEW_STYLE_FS with fsIsNative. + Hide toolbar if not enabled (Bug#13444). + (windowDidExitFullScreen:): Call updateCollectionBehaviour. + Restore tool bar if enabled, hide it otherwise (Bug#13444). + (fsIsNative, isFullscreen, updateCollectionBehaviour): New methods. + (toggleFullScreen:): If fs_is_native, call toggleFullScreen on + window. Do no set FRAME_EXTERNAL_TOOL_BAR (f) to 0. + Check FRAME_EXTERNAL_TOOL_BAR (f) before restoring + FRAME_TOOLBAR_HEIGHT (f). Call updateFrameSize when going non-fs. + (syms_of_nsterm): Add ns-use-native-fullscreen. + +2013-02-04 Paul Eggert <eggert@cs.ucla.edu> + + * fileio.c (Qchoose_write_coding_system): Now static. + +2013-02-04 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (window_buffer_changed): region_showing can be negative, + which still means region is being displayed. + (redisplay_internal): Resurrect code that forced redisplay of the + whole window when showing region and the mark has changed. + Record the new mark position to allow redisplay optimizations. + (display_line): If it->region_beg_charpos is non-zero, set the + window's region_showing member to -1. (Bug#13623) (Bug#13626) + + * window.h (struct window) <region_showing>: Declare ptrdiff_t, + not bitfield of 1 bit. + +2013-02-03 Daniel Colascione <dancol@dancol.org> + + * emacs.c: Use execvp, not execv, when DAEMON_MUST_EXEC, so that + daemon mode works on cygw32 when Emacs is installed and not just + during development. + +2013-02-02 Paul Eggert <eggert@cs.ucla.edu> + + Avoid file time stamp bug on MS-Windows (Bug#13149). + * fileio.c (Fwrite_region): Don't use the heuristic on empty files, + as FAT32 doesn't update time stamps when truncating them. + Also, check that a file time stamp is not a multiple of 100 ns; + this should catch all instances of the problem on MS-Windows, + as its native file system resolution is 100 ns or worse, and + checking for a non-multiple of 100 ns should impose only a small + overhead on systems with ns resolution. + +2013-02-02 Eli Zaretskii <eliz@gnu.org> + + Avoid encoding file names on MS-Windows when they need to be run + through dostounix_filename. + * w32.c (normalize_filename): Accept an additional argument + MULTIBYTE; if non-zero, traverse the file name by bytes and don't + downcase it even if w32-downcase-file-names is non-nil. + (dostounix_filename): Accept an additional argument MULTIBYTE and + pass it to normalize_filename. + (emacs_root_dir): Adjust. + + * msdos.h (dostounix_filename): Adjust prototype. + + * w32.h (dostounix_filename): Adjust prototype. + + * msdos.c (dostounix_filename): Accept an additional argument and + ignore it. + (init_environment): Adjust callers of dostounix_filename. + + * fileio.c (Ffile_name_directory, file_name_as_directory) + (directory_file_name, Fexpand_file_name) + (Fsubstitute_in_file_name): [DOS_NT] Adjust call to + dostounix_filename. + [WINDOWSNT]: Downcase file names if w32-downcase-file-names is + non-nil. + (Fsubstitute_in_file_name): [DOS_NT] Don't downcase environment + variables, as egetenv is case-insensitive for DOS_NT. + + * dired.c (file_name_completion): Don't call Fdirectory_file_name + with an encoded file name. + + * w32proc.c (Fw32_short_file_name, Fw32_long_file_name): + Adjust calls to dostounix_filename. + + * w32fns.c (Fx_file_dialog): Adjust call to dostounix_filename. + + * unexw32.c (unexec): Adjust call to dostounix_filename. + + * termcap.c (tgetent) [MSDOS]: Adjust call to dostounix_filename. + + * emacs.c (decode_env_path) [DOS_NT]: Adjust call to + dostounix_filename. + + * callproc.c (Fcall_process) [MSDOS]: Adjust call to + dostounix_filename. + + * callproc.c (Fcall_process): Make sure program name in PATH and + new_argv[0] is encoded, if needed. Otherwise, un-encoded string + is passed to exec/spawnve, which fails unless the file-name + encoding is UTF-8. + + * w32proc.c (sys_spawnve): Make sure escape_char is initialized, + even if w32-quote-process-args is nil. + +2013-02-01 Paul Eggert <eggert@cs.ucla.edu> + + Fix timestamp bug when write-region appends nothing (Bug#13149). + * fileio.c (Fwrite_region): When neither O_EXCL nor O_TRUNC is used, + the file's time stamp doesn't change if Emacs happens to write nothing + to the file, and on a buggy file system this could cause Emacs to + incorrectly infer that the file system doesn't have the bug. + Avoid this problem by inhibiting the inference in this case. + +2013-02-01 Dmitry Antipov <dmantipov@yandex.ru> + + * window.h (struct window): Convert base_line_number, base_line_pos + and column_number_displayed members from Lisp_Object to ptrdiff_t. + Convert region_showing member from Lisp_Object to bitfield. + Remove sequence_number member. Adjust comments. + * window.c (sequence_number): Remove. + (make_window): Initialize column_number_displayed. + * print.c (print_object): Follow the printed representation of + frames and print window pointer to distinguish between windows. + (adjust_window_count): Invalidate base_line_pos. Adjust comment. + * xdisp.c (wset_base_line_number, wset_base_line_pos) + (wset_column_number_displayed, wset_region_showing): Remove. + (window_buffer_changed, mode_line_update_needed, redisplay_internal) + (try_scrolling, try_cursor_movement, redisplay_window) + (try_window_reusing_current_matrix, try_window_id, display_line) + (display_mode_lines, decode_mode_spec): Adjust users. + * .gdbinit (pwinx): Do not print sequence_number. + +2013-02-01 Paul Eggert <eggert@cs.ucla.edu> + + Use fdopendir, fstatat and readlinkat, for efficiency (Bug#13539). + * conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): Remove. + * dired.c: Include <fcntl.h>. + (open_directory): New function, which uses open and fdopendir + rather than opendir. DOS_NT platforms still use opendir, though. + (directory_files_internal, file_name_completion): Use it. + (file_attributes): New function, with most of the old Ffile_attributes. + (directory_files_internal, Ffile_attributes): Use it. + (file_attributes, file_name_completion_stat): First arg is now fd, + not dir name. All uses changed. Use fstatat rather than lstat + + stat. + (file_attributes): Use emacs_readlinkat rather than Ffile_symlink_p. + * fileio.c: Include <allocator.h>, <careadlinkat.h>. + (emacs_readlinkat): New function, with much of the old + Ffile_symlink_p, but with an fd argument for speed. + It uses readlinkat rather than careadlinkatcwd, so that it + need not assume the working directory. + (Ffile_symlink_p): Use it. + * filelock.c (current_lock_owner): Use emacs_readlinkat + rather than emacs_readlink. + * lisp.h (emacs_readlinkat): New decl. + (READLINK_BUFSIZE, emacs_readlink): Remove. + * sysdep.c: Do not include <allocator.h>, <careadlinkat.h>. + (emacs_norealloc_allocator, emacs_readlink): Remove. + This stuff is moved to fileio.c. + * w32.c (fstatat, readlinkat): New functions. + (careadlinkat): Don't check that fd == AT_FDCWD. + (careadlinkatcwd): Remove; no longer needed. + +2013-01-31 Glenn Morris <rgm@gnu.org> + + * fileio.c (choose_write_coding_system): Make it callable from Lisp. + (Fwrite_region): Update for new choose_write_coding_system args. + Move the last piece of choose_write_coding_system here. (Bug#13522) + (syms_of_fileio): Add choose-write-coding-system. + +2013-01-30 Eli Zaretskii <eliz@gnu.org> + + * w32.c (sys_open): Zero out the flags for the new file descriptor. + (sys_close): Zero out the flags for the file descriptor before + closing it. (Bug#13546) + + * w32.c (parse_root, get_volume_info, readdir, read_unc_volume) + (logon_network_drive, stat_worker, symlink, chase_symlinks): + Use CharNextExA and CharPrevExA to iterate over file names encoded in + DBCS. (Bug#13553) + + * w32.c (w32_get_long_filename, init_environment, readlink): + Support file names encoded in DBCS codepages. + (readlink): Use the current file-name-coding-system, not the ANSI + codepage, to decode and handle targets of symlinks. + +2013-01-28 Eli Zaretskii <eliz@gnu.org> + + * w32.c (opendir): Now accepts a 'const char *'. + +2013-01-28 Dmitry Antipov <dmantipov@yandex.ru> + + Remove obsolete redisplay code. See the discussion at + http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00576.html. + * dispnew.c (preemption_period, preemption_next_check): Remove. + (Vredisplay_preemption_period): Likewise. + (update_frame, update_single_window, update_window, update_frame_1): + Adjust users. Always assume that PERIODIC_PREEMPTION_CHECKING is not + used, following the 2012-06-22 change. + +2013-01-25 Eli Zaretskii <eliz@gnu.org> + + * w32notify.c (Fw32notify_add_watch): Doc fix. (Bug#13540) + +2013-01-25 Dmitry Antipov <dmantipov@yandex.ru> + + * font.c (num_fonts): Remove the leftover from old + debugging code. Adjust comment style here and there. + * insdel.c (insert_1): Remove. + * lisp.h (insert_1): Remove prototype. + * xdisp.c (message_dolog): Adjust users to call insert_1_both. + +2013-01-25 Eli Zaretskii <eliz@gnu.org> + + * w32.c (max_filename_mbslen): New function. + (normalize_filename, readdir): Use it to detect locales where ANSI + encoding of file names uses a double-byte character set (DBCS). + If a DBCS encoding is used, advance by characters using + CharNextExA, instead of incrementing a 'char *' pointer. + Use _mbslwr instead of _strlwr. (Bug#13515) + + * w32heap.c (allocate_heap) [!_WIN64]: Decrease the initial + request of memory reservation to 1.7GB. (Bug#13065) + +2013-01-25 Andreas Schwab <schwab@linux-m68k.org> + + * coding.c (detect_coding_iso_2022): Move back mis-reordered code + at check_extra_latin label. (Bug#13505) + +2013-01-24 Dmitry Antipov <dmantipov@yandex.ru> + + * nsfont.m (ns_escape_name, ns_unescape_name, ns_registry_to_script): + Avoid redundant calls to strlen. + +2013-01-24 Dmitry Antipov <dmantipov@yandex.ru> + + Drop async_visible and async_iconified fields of struct frame. + This is possible because async input is gone; for details, see + http://lists.gnu.org/archive/html/emacs-devel/2012-12/msg00734.html. + * frame.h (struct frame): Remove async_visible and async_iconified + members, convert garbaged to unsigned bitfield. Adjust comments. + (FRAME_SAMPLE_VISIBILITY): Remove. Adjust all users. + (SET_FRAME_VISIBLE, SET_FRAME_ICONIFIED): New macros. + * frame.c, gtkutil.c, term.c, w32fns.c, window.c, xdisp.c: + Consistently use SET_FRAME_VISIBLE, SET_FRAME_ICONIFIED, + FRAME_VISIBLE_P and FRAME_ICONIFIED_P macros where appropriate. + * w32term.c: Ditto. + (w32_read_socket): Save iconified state to generate DEICONIFY_EVENT + properly. Likewise for obscured. + * xterm.c: Ditto. + (handle_one_xevent): Save visible state to generate ICONIFY_EVENT + properly. + * nsterm.m: Ditto. + (windowDidDeminiaturize): Generate DEICONIFY_EVENT. + +2013-01-24 Dmitry Antipov <dmantipov@yandex.ru> + + * insdel.c (prepare_to_modify_buffer): Revert last change as suggested + in http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00555.html. + +2013-01-23 Stefan Monnier <monnier@iro.umontreal.ca> + + * xdisp.c (message2, message2_nolog): Remove functions. + (message3, message3_nolog): Extract nbytes and multibyteness directly + from the string. Change all callers. + (message3_nolog): Don't set message_enable_multibyte since set_message + will reset it anyway. + (message1, message1_nolog): Use message3. + (vmessage): Use a stack allocated buffer rather than f->message_buf. + (with_echo_area_buffer): Remove last two arguments. Update all callers. + (set_message): Drop all but the second arg, which has to be a string. + (set_message_1): Simplify now that we know that a1 is NULL and the + second arg is a string. + * frame.h (struct frame): Remove `message_buf' field. + Use glyphs_initialized_p instead. + (FRAME_MESSAGE_BUF): Remove macro. + * w16select.c (Fw16_set_clipboard_data): Prefer message3 to message2. + * lisp.h (message2, message2_nolog): Remove declarations. + (message3, message3_nolog): Update declarations. + * keyboard.c (read_char_minibuf_menu_text) + (read_char_minibuf_menu_width): Remove vars. + (read_char_minibuf_menu_prompt): Rewrite the menu's construction so as + to correctly handle multibyte strings. + * frame.c (delete_frame): Don't free message_buf any more. + * editfns.c (message_text, message_length): Remove vars. + (Fmessage_box): Don't copy the Lisp string's bytes any longer. + * fileio.c (auto_save_error): Use message3 instead of message2. + * dispnew.c (adjust_frame_message_buffer): Remove function. + +2013-01-23 Eli Zaretskii <eliz@gnu.org> + + * w32term.c (w32fullscreen_hook): Account correctly for the screen + real estate used for the tool bar and the menu bar. + +2013-01-23 Dmitry Antipov <dmantipov@yandex.ru> + + * insdel.c (prepare_to_modify_buffer): Force redisplay if + hidden buffer is prepared to modification (Bug#13164). + +2013-01-22 Dmitry Antipov <dmantipov@yandex.ru> + + * window.h (struct window): Change window_end_valid member from + Lisp_Object to a bitfield. Adjust comments. + (wset_window_end_valid): Remove. + * window.c (adjust_window_count): Clear window_end_valid. + (Fwindow_end): Adjust user. Remove ancient #if 0 code. + (Fwindow_line_height, set_window_buffer, Frecenter) + (Fsplit_window_internal, Fdelete_other_windows_internal) + (Fset_window_fringes, Fset_window_scroll_bars): Adjust users. + * dispnew.c (adjust_glyph_matrix, clear_window_matrices): Likewise. + * xdisp.c (check_window_end, reconsider_clip_changes) + (redisplay_internal, mark_window_display_accurate_1, redisplay_window) + (try_window, try_window_reusing_current_matrix, note_mouse_highlight) + (find_first_unchanged_at_end_row, try_window_id): Likewise. + +2013-01-22 Dmitry Antipov <dmantipov@yandex.ru> + + * xdisp.c (mark_window_display_accurate): Simplify the loop + assuming that the only one of vchild, hchild or buffer window + slots is non-nil. Call mark_window_display_accurate_1 for + the leaf windows only. + (mark_window_display_accurate_1): Always assume leaf window. + Adjust comment. + +2013-01-22 Paul Eggert <eggert@cs.ucla.edu> + + * emacs.c (Qkill_emacs_hook): Now static. + + * fileio.c (Finsert_file_contents): Simplify. + Remove unnecessary assignments and tests. + +2013-01-21 Eli Zaretskii <eliz@gnu.org> + + * w32.c (acl_set_file): Don't test for errors unless + set_file_security returns FALSE. Avoids spurious errors when + saving files. + +2013-01-21 Dmitry Antipov <dmantipov@yandex.ru> + + * fileio.c (Finsert_file_contents): Revert code introduced at + 2013-01-18 in favor of the simpler and generally better fix. + Save stack space by removing 'buffer' and reusing 'read_buf' + where appropriate. + +2013-01-19 Paul Eggert <eggert@cs.ucla.edu> + + * lisp.h (eabs): Define unconditionally (Bug#13419). + The old "#if !defined (eabs)" was an unnecessary revenant of back + when this macro was called "abs". Document 'eabs' better. + +2013-01-19 Glenn Morris <rgm@gnu.org> + + * fns.c (Frandom): Doc fix. + +2013-01-19 Eli Zaretskii <eliz@gnu.org> + + * editfns.c (get_pos_property): Use SAFE_ALLOCA_LISP, to avoid + segfault when there are lots of overlays. + + * buffer.c (sort_overlays): Use SAFE_NALLOCA, to avoid segfault + when there are lots of overlays. + See http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00421.html + for the details and a way to reproduce. + +2013-01-19 Paul Eggert <eggert@cs.ucla.edu> + + * fileio.c: Use O_APPEND to append. + This corresponds better to the natural interpretation of "append", + and avoids the need to open the output file twice, or to invoke + lseek when APPEND is neither nil nor a number. + This relies on POSIX 1003.1-1988 or later, which is OK nowadays. + (Fwrite_region): Simplify. Use O_APPEND instead of opening the + file possibly twice, and lseeking to its end; this avoids the + need to lseek on non-regular files. Do not use O_EXCL and O_TRUNC + at the same time: the combination is never needed and apparently + it doesn't work with DOS_NT. + + Fix size bug on DOS_NT introduced by CIFS workaround (Bug#13149). + * fileio.c (Fwrite_region): Use O_BINARY in checking code, too. + + Allow floating-point file offsets. + Problem reported by Vitalie Spinu in + <http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00411.html>. + * fileio.c (emacs_lseek): Remove. + (file_offset): New function. + (Finsert_file_contents, Fwrite_region): Use it. + +2013-01-19 Chong Yidong <cyd@gnu.org> + + * emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid + aborting on Fsignal (Bug#13289). + +2013-01-19 Eli Zaretskii <eliz@gnu.org> + + * w32.c (acl_set_file): Treat ERROR_ACCESS_DENIED from + set_file_security as failure due to insufficient privileges. + Reported by Fabrice Popineau <fabrice.popineau@supelec.fr>. + (fstat): Return owner and group like 'stat' and 'lstat' do. + +2013-01-19 Paul Eggert <eggert@cs.ucla.edu> + + Work around bug in CIFS and vboxsf file systems (Bug#13149). + The bug was observed on Ubuntu operating inside a virtual machine, + editing files mounted via CIFS or vboxsf from the MS Windows 7 host. + The workaround introduces a race condition on non-buggy hosts, + but it's an unlikely race and anyway there's a nearly identical + nearby race that can't be fixed. + * fileio.c (valid_timestamp_file_system, timestamp_file_system): + New static vars. + (Fwrite_region): Test for file system time stamp bug. + (init_fileio): New function. + * lisp.h (init_fileio): Declare it. + * emacs.c (main): Call it. + + * fileio.c (Finsert_file_contents): Simplify new diagnostic + and make it more consistent with other stat-failure diagnostics. + +2013-01-18 Dmitry Antipov <dmantipov@yandex.ru> + + Fix crash when inserting data from non-regular files. + See http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00406.html + for the error description produced by valgrind. + * fileio.c (read_non_regular): Rename to read_contents. + Free Lisp_Save_Value object used to pass parameters. + (read_non_regular_quit): Rename to read_contents_quit. + (Finsert_file_contents): Redesign internal file reading loop to adjust + gap and end positions after each read and so help make_gap to work + properly. Do not signal an I/O error too early and so do not leave + not yet decoded characters in a buffer, which was the reason of + redisplay crash. Use list2 to build return value. Adjust comments. + +2013-01-17 Paul Eggert <eggert@cs.ucla.edu> + + Close a race when statting and reading files (Bug#13149). + * fileio.c (Finsert_file_contents): Use open+fstat, not stat+open. + This avoids a race if the file is renamed between stat and open. + This race is not the problem originally noted in Bug#13149; + see <http://bugs.gnu.org/13149#73> and later messages in the thread. + +2013-01-17 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (toplevel): Add comment about using Lisp_Save_Value + objects, related functions and macros. + (make_save_value): Adjust prototype. + (make_save_pointer): New prototype. + (SAFE_NALLOCA): Fix indentation. Use make_save_pointer. + (SAFE_ALLOCA_LISP): Adjust make_save_value usage. + * alloc.c (format_save_value): Rename to make_save_value. + (make_save_pointer): New function. + (record_xmalloc): Use make_save_pointer. + * dired.c, editfns.c, fileio.c, font.c, gtkutil.c, lread.c: + * nsmenu.m, nsterm.m, xfns.c, xmenu.c, xselect.c, keymap.c: + Change users of make_save_value to make_save_pointer. + Likewise for format_save_value and make_save_value. + +2013-01-17 Dmitry Antipov <dmantipov@yandex.ru> + + * buffer.h (NARROWED, BUF_NARROWED): Drop unused macros. + (DECODE_POSITION, BUFFER_CHECK_INDIRECTION): Fix indentation. + * buffer.c (toplevel, syms_of_buffer): Drop old commented-out + debugging stubs. + 2013-01-15 Paul Eggert <eggert@cs.ucla.edu> * alloc.c (free_save_value): Now static. @@ -8,8 +1259,8 @@ (map_keymap_char_table_item): Adjust accordingly. * fileio.c (non_regular_fd, non_regular_inserted) (non_regular_nbytes): Remove. - (Finsert_file_contents): Convert trytry to ptrdiff_t. Use - format_save_value to pass parameters to read_non_regular. + (Finsert_file_contents): Convert trytry to ptrdiff_t. + Use format_save_value to pass parameters to read_non_regular. (read_non_regular): Use XSAVE_ macros to extract parameters. Adjust comment. * xmenu.c (xmenu_show) [!USE_X_TOOLKIT && !USE_GTK]: Use @@ -136,8 +1387,8 @@ 2013-01-11 Aaron S. Hawley <Aaron.Hawley@vtinfo.com> - * insdel.c (Fcombine_after_change_execute, syms_of_insdel): Fix - ambiguous doc string cross-reference(s). + * insdel.c (Fcombine_after_change_execute, syms_of_insdel): + Fix ambiguous doc string cross-reference(s). * keyboard.c (Fcommand_execute, syms_of_keyboard): Fix ambiguous doc string cross-reference(s). diff --git a/src/ChangeLog.10 b/src/ChangeLog.10 index c878c48a4f4..508a2a9dd4c 100644 --- a/src/ChangeLog.10 +++ b/src/ChangeLog.10 @@ -19171,7 +19171,7 @@ * coding.c (code_convert_region_unwind): Set Vlast_coding_system_used to the argument. (code_convert_region): If post-read-conversion function changed - the value of last-coding-sytem, keep the new value in + the value of last-coding-system, keep the new value in coding->symbol so that it won't be overridden. (run_pre_post_conversion_on_str): Likewise. (coding_system_accept_latin_extra_p): New function. diff --git a/src/Makefile.in b/src/Makefile.in index 7a17f823df5..b42fc7faf02 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -36,7 +36,6 @@ WINDRES = @WINDRES@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ -LD_FIRSTFLAG=@LD_FIRSTFLAG@ EXEEXT = @EXEEXT@ version = @version@ # Substitute an assignment for the MAKE variable, because @@ -102,10 +101,8 @@ LD_SWITCH_X_SITE_RPATH=@LD_SWITCH_X_SITE_RPATH@ ## System-specific LDFLAGS. LD_SWITCH_SYSTEM=@LD_SWITCH_SYSTEM@ -## This holds any special options for linking temacs only (ie, not -## used by configure). Not used elsewhere because it sometimes -## contains options that have to do with using Emacs's crt0, -## which are only good with temacs. +## This holds any special options for linking temacs only (i.e., not +## used by configure). LD_SWITCH_SYSTEM_TEMACS=@LD_SWITCH_SYSTEM_TEMACS@ ## Flags to pass to ld only for temacs. @@ -120,14 +117,6 @@ PAXCTL = @PAXCTL@ ## Some systems define this to request special libraries. LIBS_SYSTEM=@LIBS_SYSTEM@ -## Where to find libgcc.a, if using gcc and necessary. -LIB_GCC=@LIB_GCC@ - -CRT_DIR=@CRT_DIR@ -## May use $CRT_DIR. -LIB_STANDARD=@LIB_STANDARD@ -START_FILES = @START_FILES@ - ## -lm, or empty. LIB_MATH=@LIB_MATH@ @@ -390,17 +379,16 @@ POST_ALLOC_OBJ=@POST_ALLOC_OBJ@ ## List of object files that make-docfile should not be told about. otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \ - $(POST_ALLOC_OBJ) $(VMLIMIT_OBJ) $(WIDGET_OBJ) $(LIBOBJS) + $(POST_ALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS) +## All object files linked into temacs. $(VMLIMIT_OBJ) should be first. +ALLOBJS = $(VMLIMIT_OBJ) $(obj) $(otherobj) ## Configure inserts the file lisp.mk at this point, defining $lisp. @lisp_frag@ ## Construct full set of libraries to be linked. -## Note that SunOS needs -lm to come before -lc; otherwise, you get -## duplicated symbols. If the standard libraries were compiled -## with GCC, we might need LIB_GCC again after them. LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \ @@ -410,7 +398,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ $(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \ - $(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC) + $(LIB_MATH) all: emacs$(EXEEXT) $(OTHER_FILES) .PHONY: all @@ -457,7 +445,7 @@ $(libsrc)/make-docfile$(EXEEXT): cd $(libsrc); $(MAKE) $(MFLAGS) make-docfile$(EXEEXT) buildobj.h: Makefile - echo "#define BUILDOBJ \"$(obj) $(otherobj) " "\"" > buildobj.h + echo "#define BUILDOBJ \"$(ALLOBJS) " "\"" >$@ globals.h: gl-stamp; @true @@ -469,15 +457,15 @@ gl-stamp: $(libsrc)/make-docfile$(EXEEXT) $(GLOBAL_SOURCES) $(srcdir)/../build-aux/move-if-change gl-tmp globals.h echo timestamp > $@ -$(obj) $(otherobj): globals.h +$(ALLOBJS): globals.h $(lib)/libgnu.a: $(config_h) cd $(lib) && $(MAKE) libgnu.a -temacs$(EXEEXT): $(START_FILES) stamp-oldxmenu $(obj) $(otherobj) \ +temacs$(EXEEXT): stamp-oldxmenu $(ALLOBJS) \ $(lib)/libgnu.a $(W32_RES) - $(CC) $(LD_FIRSTFLAG) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \ - -o temacs $(START_FILES) $(obj) $(otherobj) $(lib)/libgnu.a $(LIBES) \ + $(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \ + -o temacs $(ALLOBJS) $(lib)/libgnu.a $(LIBES) \ $(W32_RES_LINK) test "$(CANNOT_DUMP)" = "yes" || \ test "X$(PAXCTL)" = X || $(PAXCTL) -r temacs$(EXEEXT) diff --git a/src/alloc.c b/src/alloc.c index b7c17fbd6fb..63fd973ffce 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -26,7 +26,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <limits.h> /* For CHAR_BIT. */ #ifdef ENABLE_CHECKING -#include <signal.h> /* For SIGABRT. */ +#include <signal.h> /* For SIGABRT. */ #endif #ifdef HAVE_PTHREAD @@ -836,7 +836,7 @@ void * record_xmalloc (size_t size) { void *p = xmalloc (size); - record_unwind_protect (safe_alloca_unwind, make_save_value (p, 0)); + record_unwind_protect (safe_alloca_unwind, make_save_pointer (p)); return p; } @@ -1675,7 +1675,7 @@ allocate_string_data (struct Lisp_String *s, b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ + /* Back to a reasonable maximum of mmap'ed areas. */ mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif @@ -1892,7 +1892,7 @@ compact_small_strings (void) #ifdef GC_CHECK_STRING_BYTES /* Check that the string size recorded in the string is the - same as the one recorded in the sdata structure. */ + same as the one recorded in the sdata structure. */ if (s && string_bytes (s) != SDATA_NBYTES (from)) emacs_abort (); #endif /* GC_CHECK_STRING_BYTES */ @@ -3103,13 +3103,10 @@ Any number of arguments, even zero arguments, are allowed. usage: (vector &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - register Lisp_Object len, val; ptrdiff_t i; - register struct Lisp_Vector *p; + register Lisp_Object val = make_uninit_vector (nargs); + register struct Lisp_Vector *p = XVECTOR (val); - XSETFASTINT (len, nargs); - val = Fmake_vector (len, Qnil); - p = XVECTOR (val); for (i = 0; i < nargs; i++) p->contents[i] = args[i]; return val; @@ -3147,9 +3144,9 @@ stack before executing the byte-code. usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - register Lisp_Object len, val; ptrdiff_t i; - register struct Lisp_Vector *p; + register Lisp_Object val = make_uninit_vector (nargs); + register struct Lisp_Vector *p = XVECTOR (val); /* We used to purecopy everything here, if purify-flag was set. This worked OK for Emacs-23, but with Emacs-24's lexical binding code, it can be @@ -3159,10 +3156,6 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT just wasteful and other times plainly wrong (e.g. those free vars may want to be setcar'd). */ - XSETFASTINT (len, nargs); - val = Fmake_vector (len, Qnil); - - p = XVECTOR (val); for (i = 0; i < nargs; i++) p->contents[i] = args[i]; make_byte_code (p); @@ -3354,7 +3347,7 @@ free_misc (Lisp_Object misc) and `o' for Lisp_Object. Up to 4 objects can be specified. */ Lisp_Object -format_save_value (const char *fmt, ...) +make_save_value (const char *fmt, ...) { va_list ap; int len = strlen (fmt); @@ -3402,15 +3395,19 @@ format_save_value (const char *fmt, ...) return val; } -/* Return a Lisp_Save_Value object containing POINTER and INTEGER. - Most code should use this to package C integers and pointers - to call record_unwind_protect. The unwind function can get the - C values back using XSAVE_POINTER and XSAVE_INTEGER. */ +/* The most common task it to save just one C pointer. */ Lisp_Object -make_save_value (void *pointer, ptrdiff_t integer) +make_save_pointer (void *pointer) { - return format_save_value ("pi", pointer, integer); + Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); + struct Lisp_Save_Value *p = XSAVE_VALUE (val); + + p->area = 0; + p->type0 = SAVE_POINTER; + p->data[0].pointer = pointer; + p->type1 = p->type2 = p->type3 = SAVE_UNUSED; + return val; } /* Free a Lisp_Save_Value object. Do not use this function @@ -6533,7 +6530,7 @@ die (const char *msg, const char *file, int line) } #endif -/* Initialization */ +/* Initialization. */ void init_alloc_once (void) @@ -6548,9 +6545,9 @@ init_alloc_once (void) #endif #ifdef DOUG_LEA_MALLOC - mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ - mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* max. number of mmap'ed areas */ + mallopt (M_TRIM_THRESHOLD, 128 * 1024); /* Trim threshold. */ + mallopt (M_MMAP_THRESHOLD, 64 * 1024); /* Mmap threshold. */ + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* Max. number of mmap'ed areas. */ #endif init_strings (); init_vectors (); diff --git a/src/autodeps.mk b/src/autodeps.mk index fb0e21366c7..8b014a7508c 100644 --- a/src/autodeps.mk +++ b/src/autodeps.mk @@ -2,5 +2,4 @@ ## This is inserted in src/Makefile if AUTO_DEPEND=yes. -ALLOBJS=$(START_FILES) ${obj} ${otherobj} -include $(ALLOBJS:%.o=${DEPDIR}/%.d) diff --git a/src/bidi.c b/src/bidi.c index b067c8134e3..c6bea62f67b 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -910,7 +910,7 @@ bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, bool unibyte) return STRING_CHAR (s); } -/* Fetch and return the character at BYTEPOS/CHARPOS. If that +/* Fetch and return the character at CHARPOS/BYTEPOS. If that character is covered by a display string, treat the entire run of covered characters as a single character, either u+2029 or u+FFFC, and return their combined length in CH_LEN and NCHARS. DISP_POS @@ -925,7 +925,7 @@ bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, bool unibyte) string to iterate, or NULL if iterating over a buffer or a Lisp string; in the latter case, STRING->lstring is the Lisp string. */ static int -bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos, +bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, int *disp_prop, struct bidi_string_data *string, bool frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars) { @@ -1109,8 +1109,8 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte) display string? And what if a display string covering some of the text over which we scan back includes paragraph_start_re? */ - pos = find_next_newline_no_quit (pos - 1, -1); - pos_byte = CHAR_TO_BYTE (pos); + DEC_BOTH (pos, pos_byte); + pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte); } if (n >= MAX_PARAGRAPH_SEARCH) pos_byte = BEGV_BYTE; @@ -1223,7 +1223,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) bytepos = pstartbyte; if (!string_p) pos = BYTE_TO_CHAR (bytepos); - ch = bidi_fetch_char (bytepos, pos, &disp_pos, &disp_prop, + ch = bidi_fetch_char (pos, bytepos, &disp_pos, &disp_prop, &bidi_it->string, bidi_it->frame_window_p, &ch_len, &nchars); type = bidi_get_type (ch, NEUTRAL_DIR); @@ -1251,7 +1251,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) && bidi_at_paragraph_end (pos, bytepos) >= -1) break; /* Fetch next character and advance to get past it. */ - ch = bidi_fetch_char (bytepos, pos, &disp_pos, + ch = bidi_fetch_char (pos, bytepos, &disp_pos, &disp_prop, &bidi_it->string, bidi_it->frame_window_p, &ch_len, &nchars); pos += nchars; @@ -1282,8 +1282,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) /* FXIME: What if p is covered by a display string? See also a FIXME inside bidi_find_paragraph_start. */ - p--; - pbyte = CHAR_TO_BYTE (p); + DEC_BOTH (p, pbyte); prevpbyte = bidi_find_paragraph_start (p, pbyte); } pstartbyte = prevpbyte; @@ -1356,15 +1355,19 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) : bidi_it->string.s); if (bidi_it->charpos < 0) - bidi_it->charpos = 0; - bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos, - bidi_it->string.unibyte); + bidi_it->charpos = bidi_it->bytepos = 0; + eassert (bidi_it->bytepos == bidi_count_bytes (p, 0, 0, + bidi_it->charpos, + bidi_it->string.unibyte)); } else { if (bidi_it->charpos < BEGV) - bidi_it->charpos = BEGV; - bidi_it->bytepos = CHAR_TO_BYTE (bidi_it->charpos); + { + bidi_it->charpos = BEGV; + bidi_it->bytepos = BEGV_BYTE; + } + eassert (bidi_it->bytepos == CHAR_TO_BYTE (bidi_it->charpos)); } } /* Don't move at end of buffer/string. */ @@ -1397,7 +1400,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) /* Fetch the character at BYTEPOS. If it is covered by a display string, treat the entire run of covered characters as a single character u+FFFC. */ - curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos, + curchar = bidi_fetch_char (bidi_it->charpos, bidi_it->bytepos, &bidi_it->disp_pos, &bidi_it->disp_prop, &bidi_it->string, bidi_it->frame_window_p, &bidi_it->ch_len, &bidi_it->nchars); @@ -1973,6 +1976,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it) next_type = STRONG_R; break; case WEAK_BN: + case NEUTRAL_ON: /* W6/Retaining */ if (!bidi_explicit_dir_char (bidi_it->ch)) emacs_abort (); /* can't happen: BNs are skipped */ /* FALLTHROUGH */ @@ -2189,7 +2193,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) if (bidi_it->nchars <= 0) emacs_abort (); do { - ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &dpp, &bs, + ch = bidi_fetch_char (cpos += nc, bpos += clen, &disp_pos, &dpp, &bs, fwp, &clen, &nc); if (ch == '\n' || ch == BIDI_EOB) chtype = NEUTRAL_B; @@ -2391,6 +2395,10 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) next_level = bidi_peek_at_next_level (bidi_it); while (next_level != expected_next_level) { + /* If next_level is -1, it means we have an unresolved level + in the cache, which at this point should not happen. If + it does, we will infloop. */ + eassert (next_level >= 0); expected_next_level += incr; level_to_search += incr; bidi_find_other_level_edge (bidi_it, level_to_search, !ascending); diff --git a/src/buffer.c b/src/buffer.c index a06868ec6c3..4d24f970792 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -370,9 +370,6 @@ bset_zv_marker (struct buffer *b, Lisp_Object val) b->INTERNAL_FIELD (zv_marker) = val; } -/* For debugging; temporary. See set_buffer_internal. */ -/* Lisp_Object Qlisp_mode, Vcheck_symbol; */ - void nsberror (Lisp_Object spec) { @@ -3152,7 +3149,10 @@ ptrdiff_t sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) { ptrdiff_t i, j; - struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec); + USE_SAFE_ALLOCA; + struct sortvec *sortvec; + + SAFE_NALLOCA (sortvec, 1, noverlays); /* Put the valid and relevant overlays into sortvec. */ @@ -3198,6 +3198,8 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) for (i = 0; i < noverlays; i++) overlay_vec[i] = sortvec[i].overlay; + + SAFE_FREE (); return (noverlays); } @@ -6001,10 +6003,6 @@ simple case that you moved off with C-b means scrolling just one line. window scrolls by a full window height. Meaningful values are between 0.0 and 1.0, inclusive. */); -/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol, - "Don't ask."); -*/ - DEFVAR_LISP ("before-change-functions", Vbefore_change_functions, doc: /* List of functions to call before each text change. Two arguments are passed to each function: the positions of diff --git a/src/buffer.h b/src/buffer.h index c0b0e227725..2b0b49dddad 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -82,9 +82,6 @@ INLINE_HEADER_BEGIN /* Size of gap. */ #define GAP_SIZE (current_buffer->text->gap_size) -/* Is the current buffer narrowed? */ -#define NARROWED ((BEGV != BEG) || (ZV != Z)) - /* Modification count. */ #define MODIFF (current_buffer->text->modiff) @@ -173,10 +170,6 @@ INLINE_HEADER_BEGIN /* Size of gap. */ #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size) -/* Is this buffer narrowed? */ -#define BUF_NARROWED(buf) ((BUF_BEGV (buf) != BUF_BEG (buf)) \ - || (BUF_ZV (buf) != BUF_Z (buf))) - /* Modification count. */ #define BUF_MODIFF(buf) ((buf)->text->modiff) @@ -294,24 +287,24 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); /* Access a Lisp position value in POS, and store the charpos in CHARPOS and the bytepos in BYTEPOS. */ -#define DECODE_POSITION(charpos, bytepos, pos) \ -do \ - { \ - Lisp_Object __pos = (pos); \ - if (NUMBERP (__pos)) \ - { \ - charpos = __pos; \ - bytepos = buf_charpos_to_bytepos (current_buffer, __pos); \ - } \ - else if (MARKERP (__pos)) \ - { \ - charpos = marker_position (__pos); \ - bytepos = marker_byte_position (__pos); \ - } \ - else \ - wrong_type_argument (Qinteger_or_marker_p, __pos); \ - } \ -while (0) +#define DECODE_POSITION(charpos, bytepos, pos) \ + do \ + { \ + Lisp_Object __pos = (pos); \ + if (NUMBERP (__pos)) \ + { \ + charpos = __pos; \ + bytepos = buf_charpos_to_bytepos (current_buffer, __pos); \ + } \ + else if (MARKERP (__pos)) \ + { \ + charpos = marker_position (__pos); \ + bytepos = marker_byte_position (__pos); \ + } \ + else \ + wrong_type_argument (Qinteger_or_marker_p, __pos); \ + } \ + while (0) /* Maximum number of bytes in a buffer. A buffer cannot contain more bytes than a 1-origin fixnum can represent, @@ -1009,15 +1002,15 @@ bset_width_table (struct buffer *b, Lisp_Object val) #define BUFFER_CHECK_INDIRECTION(b) \ do { \ if (BUFFER_LIVE_P (b)) \ - { \ - if (b->base_buffer) \ - { \ - eassert (b->indirections == -1); \ - eassert (b->base_buffer->indirections > 0); \ - } \ - else \ - eassert (b->indirections >= 0); \ - } \ + { \ + if (b->base_buffer) \ + { \ + eassert (b->indirections == -1); \ + eassert (b->base_buffer->indirections > 0); \ + } \ + else \ + eassert (b->indirections >= 0); \ + } \ } while (0) /* Chain of all buffers, including killed ones. */ diff --git a/src/callint.c b/src/callint.c index cd303908f69..212dd2e3d62 100644 --- a/src/callint.c +++ b/src/callint.c @@ -29,7 +29,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "keymap.h" Lisp_Object Qminus, Qplus; -Lisp_Object Qcall_interactively; +static Lisp_Object Qcall_interactively; static Lisp_Object Qcommand_debug_status; static Lisp_Object Qenable_recursive_minibuffers; @@ -342,8 +342,8 @@ invoke it. If KEYS is omitted or nil, the return value of /* Compute the arg values using the user's expression. */ GCPRO2 (input, filter_specs); specs = Feval (specs, - CONSP (funval) && EQ (Qclosure, XCAR (funval)) - ? Qt : Qnil); + CONSP (funval) && EQ (Qclosure, XCAR (funval)) + ? CAR_SAFE (XCDR (funval)) : Qnil); UNGCPRO; if (events != num_input_events || !NILP (record_flag)) { @@ -497,47 +497,47 @@ invoke it. If KEYS is omitted or nil, the return value of switch (*tem) { - case 'a': /* Symbol defined as a function */ + case 'a': /* Symbol defined as a function. */ visargs[i] = Fcompleting_read (callint_message, Vobarray, Qfboundp, Qt, Qnil, Qnil, Qnil, Qnil); - /* Passing args[i] directly stimulates compiler bug */ + /* Passing args[i] directly stimulates compiler bug. */ teml = visargs[i]; args[i] = Fintern (teml, Qnil); break; - case 'b': /* Name of existing buffer */ + case 'b': /* Name of existing buffer. */ args[i] = Fcurrent_buffer (); if (EQ (selected_window, minibuf_window)) args[i] = Fother_buffer (args[i], Qnil, Qnil); args[i] = Fread_buffer (callint_message, args[i], Qt); break; - case 'B': /* Name of buffer, possibly nonexistent */ + case 'B': /* Name of buffer, possibly nonexistent. */ args[i] = Fread_buffer (callint_message, Fother_buffer (Fcurrent_buffer (), Qnil, Qnil), Qnil); break; - case 'c': /* Character */ + case 'c': /* Character. */ /* Prompt in `minibuffer-prompt' face. */ Fput_text_property (make_number (0), make_number (SCHARS (callint_message)), Qface, Qminibuffer_prompt, callint_message); args[i] = Fread_char (callint_message, Qnil, Qnil); message1_nolog ((char *) 0); - /* Passing args[i] directly stimulates compiler bug */ + /* Passing args[i] directly stimulates compiler bug. */ teml = args[i]; /* See bug#8479. */ if (! CHARACTERP (teml)) error ("Non-character input-event"); visargs[i] = Fchar_to_string (teml); break; - case 'C': /* Command: symbol with interactive function */ + case 'C': /* Command: symbol with interactive function. */ visargs[i] = Fcompleting_read (callint_message, Vobarray, Qcommandp, Qt, Qnil, Qnil, Qnil, Qnil); - /* Passing args[i] directly stimulates compiler bug */ + /* Passing args[i] directly stimulates compiler bug. */ teml = visargs[i]; args[i] = Fintern (teml, Qnil); break; @@ -549,33 +549,33 @@ invoke it. If KEYS is omitted or nil, the return value of varies[i] = 1; break; - case 'D': /* Directory name. */ + case 'D': /* Directory name. */ args[i] = Fread_file_name (callint_message, Qnil, BVAR (current_buffer, directory), Qlambda, Qnil, Qfile_directory_p); break; - case 'f': /* Existing file name. */ + case 'f': /* Existing file name. */ args[i] = Fread_file_name (callint_message, Qnil, Qnil, Qlambda, Qnil, Qnil); break; - case 'F': /* Possibly nonexistent file name. */ + case 'F': /* Possibly nonexistent file name. */ args[i] = Fread_file_name (callint_message, Qnil, Qnil, Qnil, Qnil, Qnil); break; case 'G': /* Possibly nonexistent file name, - default to directory alone. */ + default to directory alone. */ args[i] = Fread_file_name (callint_message, Qnil, Qnil, Qnil, empty_unibyte_string, Qnil); break; - case 'i': /* Ignore an argument -- Does not do I/O */ + case 'i': /* Ignore an argument -- Does not do I/O. */ varies[i] = -1; break; - case 'k': /* Key sequence. */ + case 'k': /* Key sequence. */ { ptrdiff_t speccount1 = SPECPDL_INDEX (); specbind (Qcursor_in_echo_area, Qt); @@ -607,7 +607,7 @@ invoke it. If KEYS is omitted or nil, the return value of } break; - case 'K': /* Key sequence to be defined. */ + case 'K': /* Key sequence to be defined. */ { ptrdiff_t speccount1 = SPECPDL_INDEX (); specbind (Qcursor_in_echo_area, Qt); @@ -639,7 +639,7 @@ invoke it. If KEYS is omitted or nil, the return value of } break; - case 'U': /* Up event from last k or K */ + case 'U': /* Up event from last k or K. */ if (!NILP (up_event)) { args[i] = Fmake_vector (make_number (1), up_event); @@ -679,7 +679,7 @@ invoke it. If KEYS is omitted or nil, the return value of Qnil, Qnil, Qnil, Qt); break; - case 'N': /* Prefix arg as number, else number from minibuffer */ + case 'N': /* Prefix arg as number, else number from minibuffer. */ if (!NILP (prefix_arg)) goto have_prefix_arg; case 'n': /* Read number from minibuffer. */ @@ -690,7 +690,7 @@ invoke it. If KEYS is omitted or nil, the return value of Lisp_Object str; if (! first) { - message ("Please enter a number."); + message1 ("Please enter a number."); sit_for (make_number (1), 0, 0); } first = 0; @@ -714,14 +714,14 @@ invoke it. If KEYS is omitted or nil, the return value of varies[i] = -1; break; - case 'p': /* Prefix arg converted to number. No I/O. */ + case 'p': /* Prefix arg converted to number. No I/O. */ have_prefix_arg: args[i] = Fprefix_numeric_value (prefix_arg); /* visargs[i] = Qnil; */ varies[i] = -1; break; - case 'r': /* Region, point and mark as 2 args. */ + case 'r': /* Region, point and mark as 2 args. */ check_mark (1); set_marker_both (point_marker, Qnil, PT, PT_BYTE); /* visargs[i+1] = Qnil; */ @@ -742,29 +742,29 @@ invoke it. If KEYS is omitted or nil, the return value of case 'S': /* Any symbol. */ visargs[i] = Fread_string (callint_message, Qnil, Qnil, Qnil, Qnil); - /* Passing args[i] directly stimulates compiler bug */ + /* Passing args[i] directly stimulates compiler bug. */ teml = visargs[i]; args[i] = Fintern (teml, Qnil); break; case 'v': /* Variable name: symbol that is - custom-variable-p. */ + custom-variable-p. */ args[i] = Fread_variable (callint_message, Qnil); visargs[i] = last_minibuf_string; break; - case 'x': /* Lisp expression read but not evaluated */ + case 'x': /* Lisp expression read but not evaluated. */ args[i] = Fread_minibuffer (callint_message, Qnil); visargs[i] = last_minibuf_string; break; - case 'X': /* Lisp expression read and evaluated */ + case 'X': /* Lisp expression read and evaluated. */ args[i] = Feval_minibuffer (callint_message, Qnil); visargs[i] = last_minibuf_string; break; case 'Z': /* Coding-system symbol, or ignore the - argument if no prefix */ + argument if no prefix. */ if (NILP (prefix_arg)) { args[i] = Qnil; @@ -778,7 +778,7 @@ invoke it. If KEYS is omitted or nil, the return value of } break; - case 'z': /* Coding-system symbol or nil */ + case 'z': /* Coding-system symbol or nil. */ args[i] = Fread_coding_system (callint_message, Qnil); visargs[i] = last_minibuf_string; break; diff --git a/src/callproc.c b/src/callproc.c index 5eba3271358..9132c0dd976 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -445,28 +445,34 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) path = Fsubstring (path, make_number (2), Qnil); new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); - if (nargs > 4) - { - ptrdiff_t i; - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; - GCPRO5 (infile, buffer, current_dir, path, error_file); - argument_coding.dst_multibyte = 0; - for (i = 4; i < nargs; i++) - { - argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]); - if (CODING_REQUIRE_ENCODING (&argument_coding)) - /* We must encode this argument. */ - args[i] = encode_coding_string (&argument_coding, args[i], 1); - } - UNGCPRO; - for (i = 4; i < nargs; i++) - new_argv[i - 3] = SSDATA (args[i]); - new_argv[i - 3] = 0; - } - else - new_argv[1] = 0; - new_argv[0] = SSDATA (path); + { + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + + GCPRO5 (infile, buffer, current_dir, path, error_file); + if (nargs > 4) + { + ptrdiff_t i; + + argument_coding.dst_multibyte = 0; + for (i = 4; i < nargs; i++) + { + argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]); + if (CODING_REQUIRE_ENCODING (&argument_coding)) + /* We must encode this argument. */ + args[i] = encode_coding_string (&argument_coding, args[i], 1); + } + for (i = 4; i < nargs; i++) + new_argv[i - 3] = SSDATA (args[i]); + new_argv[i - 3] = 0; + } + else + new_argv[1] = 0; + if (STRING_MULTIBYTE (path)) + path = ENCODE_FILE (path); + new_argv[0] = SSDATA (path); + UNGCPRO; + } #ifdef MSDOS /* MW, July 1993 */ @@ -481,7 +487,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) tempfile = alloca (20); *tempfile = '\0'; } - dostounix_filename (tempfile); + dostounix_filename (tempfile, 0); if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') strcat (tempfile, "/"); strcat (tempfile, "detmp.XXX"); @@ -991,13 +997,11 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r tmpdir = Vtemporary_file_directory; else { + char *outf; #ifndef DOS_NT - if (getenv ("TMPDIR")) - tmpdir = build_string (getenv ("TMPDIR")); - else - tmpdir = build_string ("/tmp/"); + outf = getenv ("TMPDIR"); + tmpdir = build_string (outf ? outf : "/tmp/"); #else /* DOS_NT */ - char *outf; if ((outf = egetenv ("TMPDIR")) || (outf = egetenv ("TMP")) || (outf = egetenv ("TEMP"))) @@ -1010,8 +1014,26 @@ 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); - Lisp_Object encoded_tem = ENCODE_FILE (pattern); - char *tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1); + Lisp_Object encoded_tem; + char *tempfile; + +#ifdef WINDOWSNT + /* Cannot use the result of Fexpand_file_name, because it + downcases the XXXXXX part of the pattern, and mktemp then + doesn't recognize it. */ + if (!NILP (Vw32_downcase_file_names)) + { + Lisp_Object dirname = Ffile_name_directory (pattern); + + if (NILP (dirname)) + pattern = Vtemp_file_name_pattern; + else + pattern = concat2 (dirname, Vtemp_file_name_pattern); + } +#endif + + encoded_tem = ENCODE_FILE (pattern); + tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1); memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); coding_systems = Qt; @@ -1631,7 +1653,7 @@ init_callproc (void) if (! file_accessible_directory_p (SSDATA (tempdir))) dir_warning ("arch-independent data dir", Vdata_directory); - sh = (char *) getenv ("SHELL"); + sh = getenv ("SHELL"); Vshell_file_name = build_string (sh ? sh : "/bin/sh"); #ifdef DOS_NT diff --git a/src/ccl.c b/src/ccl.c index 9bfd437d885..7f77e1d22fa 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -2228,9 +2228,8 @@ Return index number of the registered CCL program. */) Vccl_program_table = larger_vector (Vccl_program_table, 1, -1); { - Lisp_Object elt; + Lisp_Object elt = make_uninit_vector (4); - elt = Fmake_vector (make_number (4), Qnil); ASET (elt, 0, name); ASET (elt, 1, ccl_prog); ASET (elt, 2, resolved); diff --git a/src/charset.c b/src/charset.c index c3a4538f223..fdb8eebde8b 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1053,7 +1053,7 @@ usage: (define-charset-internal ...) */) CHECK_NATNUM (parent_max_code); parent_code_offset = Fnth (make_number (3), val); CHECK_NUMBER (parent_code_offset); - val = Fmake_vector (make_number (4), Qnil); + val = make_uninit_vector (4); ASET (val, 0, make_number (parent_charset->id)); ASET (val, 1, parent_min_code); ASET (val, 2, parent_max_code); @@ -1259,7 +1259,7 @@ define_charset_internal (Lisp_Object name, args[charset_arg_name] = name; args[charset_arg_dimension] = make_number (dimension); - val = Fmake_vector (make_number (8), make_number (0)); + val = make_uninit_vector (8); for (i = 0; i < 8; i++) ASET (val, i, make_number (code_space[i])); args[charset_arg_code_space] = val; @@ -28,8 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "termchar.h" #include "tparam.h" -#define BIG 9999 /* 9999 good on VAXen. For 16 bit machines - use about 2000.... */ +#define BIG 9999 /* Good on 32-bit hosts. */ int cost; /* sums up costs */ diff --git a/src/coding.c b/src/coding.c index a9bf9032a69..32da72ab626 100644 --- a/src/coding.c +++ b/src/coding.c @@ -322,8 +322,7 @@ Lisp_Object Qcall_process, Qcall_process_region; Lisp_Object Qstart_process, Qopen_network_stream; static Lisp_Object Qtarget_idx; -static Lisp_Object Qinsufficient_source, Qinconsistent_eol, Qinvalid_source; -static Lisp_Object Qinterrupted, Qinsufficient_memory; +static Lisp_Object Qinsufficient_source, Qinvalid_source, Qinterrupted; /* If a symbol has this property, evaluate the value to define the symbol as a coding system. */ @@ -820,18 +819,12 @@ record_conversion_result (struct coding_system *coding, case CODING_RESULT_INSUFFICIENT_SRC: Vlast_code_conversion_error = Qinsufficient_source; break; - case CODING_RESULT_INCONSISTENT_EOL: - Vlast_code_conversion_error = Qinconsistent_eol; - break; case CODING_RESULT_INVALID_SRC: Vlast_code_conversion_error = Qinvalid_source; break; case CODING_RESULT_INTERRUPT: Vlast_code_conversion_error = Qinterrupted; break; - case CODING_RESULT_INSUFFICIENT_MEM: - Vlast_code_conversion_error = Qinsufficient_memory; - break; case CODING_RESULT_INSUFFICIENT_DST: /* Don't record this error in Vlast_code_conversion_error because it happens just temporarily and is resolved when the @@ -3057,20 +3050,7 @@ detect_coding_iso_2022 (struct coding_system *coding, } if (single_shifting) break; - check_extra_latin: - if (! VECTORP (Vlatin_extra_code_table) - || NILP (AREF (Vlatin_extra_code_table, c))) - { - rejected = CATEGORY_MASK_ISO; - break; - } - if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_1]) - & CODING_ISO_FLAG_LATIN_EXTRA) - found |= CATEGORY_MASK_ISO_8_1; - else - rejected |= CATEGORY_MASK_ISO_8_1; - rejected |= CATEGORY_MASK_ISO_8_2; - break; + goto check_extra_latin; default: if (c < 0) @@ -3121,6 +3101,20 @@ detect_coding_iso_2022 (struct coding_system *coding, } break; } + check_extra_latin: + if (! VECTORP (Vlatin_extra_code_table) + || NILP (AREF (Vlatin_extra_code_table, c))) + { + rejected = CATEGORY_MASK_ISO; + break; + } + if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_1]) + & CODING_ISO_FLAG_LATIN_EXTRA) + found |= CATEGORY_MASK_ISO_8_1; + else + rejected |= CATEGORY_MASK_ISO_8_1; + rejected |= CATEGORY_MASK_ISO_8_2; + break; } } detect_info->rejected |= CATEGORY_MASK_ISO; @@ -6883,22 +6877,8 @@ produce_charset (struct coding_system *coding, int *charbuf, ptrdiff_t pos) #define ALLOC_CONVERSION_WORK_AREA(coding) \ do { \ - int size = CHARBUF_SIZE; \ - \ - coding->charbuf = NULL; \ - while (size > 1024) \ - { \ - coding->charbuf = alloca (sizeof (int) * size); \ - if (coding->charbuf) \ - break; \ - size >>= 1; \ - } \ - if (! coding->charbuf) \ - { \ - record_conversion_result (coding, CODING_RESULT_INSUFFICIENT_MEM); \ - return; \ - } \ - coding->charbuf_size = size; \ + coding->charbuf = SAFE_ALLOCA (CHARBUF_SIZE * sizeof (int)); \ + coding->charbuf_size = CHARBUF_SIZE; \ } while (0) @@ -6967,6 +6947,8 @@ decode_coding (struct coding_system *coding) int carryover; int i; + USE_SAFE_ALLOCA; + if (BUFFERP (coding->src_object) && coding->src_pos > 0 && coding->src_pos < GPT @@ -7089,6 +7071,8 @@ decode_coding (struct coding_system *coding) bset_undo_list (current_buffer, undo_list); record_insert (coding->dst_pos, coding->produced_char); } + + SAFE_FREE (); } @@ -7372,6 +7356,8 @@ encode_coding (struct coding_system *coding) int max_lookup; struct ccl_spec cclspec; + USE_SAFE_ALLOCA; + attrs = CODING_ID_ATTRS (coding->id); if (coding->encoder == encode_coding_raw_text) translation_table = Qnil, max_lookup = 0; @@ -7406,6 +7392,8 @@ encode_coding (struct coding_system *coding) if (BUFFERP (coding->dst_object) && coding->produced_char > 0) insert_from_gap (coding->produced_char, coding->produced); + + SAFE_FREE (); } @@ -7694,14 +7682,8 @@ decode_coding_object (struct coding_system *coding, set_buffer_internal (XBUFFER (coding->dst_object)); if (dst_bytes < coding->produced) { + eassert (coding->produced > 0); destination = xrealloc (destination, coding->produced); - if (! destination) - { - record_conversion_result (coding, - CODING_RESULT_INSUFFICIENT_MEM); - unbind_to (count, Qnil); - return; - } if (BEGV < GPT && GPT < BEGV + coding->produced_char) move_gap_both (BEGV, BEGV_BYTE); memcpy (destination, BEGV_ADDR, coding->produced); @@ -9482,7 +9464,7 @@ make_subsidiaries (Lisp_Object base) int i; memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len); - subsidiaries = Fmake_vector (make_number (3), Qnil); + subsidiaries = make_uninit_vector (3); for (i = 0; i < 3; i++) { strcpy (buf + base_name_len, suffixes[i]); @@ -9782,7 +9764,7 @@ usage: (define-coding-system-internal ...) */) CHECK_VECTOR (initial); for (i = 0; i < 4; i++) { - val = Faref (initial, make_number (i)); + val = AREF (initial, i); if (! NILP (val)) { struct charset *charset; @@ -9987,7 +9969,8 @@ usage: (define-coding-system-internal ...) */) this_name = AREF (eol_type, i); this_aliases = Fcons (this_name, Qnil); this_eol_type = (i == 0 ? Qunix : i == 1 ? Qdos : Qmac); - this_spec = Fmake_vector (make_number (3), attrs); + this_spec = make_uninit_vector (3); + ASET (this_spec, 0, attrs); ASET (this_spec, 1, this_aliases); ASET (this_spec, 2, this_eol_type); Fputhash (this_name, this_spec, Vcoding_system_hash_table); @@ -10000,7 +9983,8 @@ usage: (define-coding-system-internal ...) */) } } - spec_vec = Fmake_vector (make_number (3), attrs); + spec_vec = make_uninit_vector (3); + ASET (spec_vec, 0, attrs); ASET (spec_vec, 1, aliases); ASET (spec_vec, 2, eol_type); @@ -10405,10 +10389,8 @@ syms_of_coding (void) intern_c_string ("coding-category-undecided")); DEFSYM (Qinsufficient_source, "insufficient-source"); - DEFSYM (Qinconsistent_eol, "inconsistent-eol"); DEFSYM (Qinvalid_source, "invalid-source"); DEFSYM (Qinterrupted, "interrupted"); - DEFSYM (Qinsufficient_memory, "insufficient-memory"); DEFSYM (Qcoding_system_define_form, "coding-system-define-form"); defsubr (&Scoding_system_p); @@ -10709,7 +10691,7 @@ reading if you suppress escape sequence detection. The other way to read escape sequences in a file without decoding is to explicitly specify some coding system that doesn't use ISO-2022 -escape sequence (e.g `latin-1') on reading by \\[universal-coding-system-argument]. */); +escape sequence (e.g., `latin-1') on reading by \\[universal-coding-system-argument]. */); inhibit_iso_escape_detection = 0; DEFVAR_BOOL ("inhibit-null-byte-detection", diff --git a/src/coding.h b/src/coding.h index eb95fa13ddb..28a7d776b63 100644 --- a/src/coding.h +++ b/src/coding.h @@ -272,37 +272,31 @@ enum coding_result_code CODING_RESULT_SUCCESS, CODING_RESULT_INSUFFICIENT_SRC, CODING_RESULT_INSUFFICIENT_DST, - CODING_RESULT_INCONSISTENT_EOL, CODING_RESULT_INVALID_SRC, - CODING_RESULT_INTERRUPT, - CODING_RESULT_INSUFFICIENT_MEM + CODING_RESULT_INTERRUPT }; /* Macros used for the member `mode' of the struct coding_system. */ -/* If set, recover the original CR or LF of the already decoded text - when the decoding routine encounters an inconsistent eol format. */ -#define CODING_MODE_INHIBIT_INCONSISTENT_EOL 0x01 - /* If set, the decoding/encoding routines treat the current data as the last block of the whole text to be converted, and do the appropriate finishing job. */ -#define CODING_MODE_LAST_BLOCK 0x02 +#define CODING_MODE_LAST_BLOCK 0x01 /* If set, it means that the current source text is in a buffer which enables selective display. */ -#define CODING_MODE_SELECTIVE_DISPLAY 0x04 +#define CODING_MODE_SELECTIVE_DISPLAY 0x02 /* This flag is used by the decoding/encoding routines on the fly. If set, it means that right-to-left text is being processed. */ -#define CODING_MODE_DIRECTION 0x08 +#define CODING_MODE_DIRECTION 0x04 -#define CODING_MODE_FIXED_DESTINATION 0x10 +#define CODING_MODE_FIXED_DESTINATION 0x08 /* If set, it means that the encoding routines produces some safe ASCII characters (usually '?') for unsupported characters. */ -#define CODING_MODE_SAFE_ENCODING 0x20 +#define CODING_MODE_SAFE_ENCODING 0x10 /* For handling composition sequence. */ #include "composite.h" @@ -725,22 +719,6 @@ extern Lisp_Object from_unicode (Lisp_Object str); /* Macros for backward compatibility. */ -#define decode_coding_region(coding, from, to) \ - decode_coding_object (coding, Fcurrent_buffer (), \ - from, CHAR_TO_BYTE (from), \ - to, CHAR_TO_BYTE (to), Fcurrent_buffer ()) - - -#define encode_coding_region(coding, from, to) \ - encode_coding_object (coding, Fcurrent_buffer (), \ - from, CHAR_TO_BYTE (from), \ - to, CHAR_TO_BYTE (to), Fcurrent_buffer ()) - - -#define decode_coding_string(coding, string, nocopy) \ - decode_coding_object (coding, string, 0, 0, SCHARS (string), \ - SBYTES (string), Qt) - #define encode_coding_string(coding, string, nocopy) \ (STRING_MULTIBYTE(string) ? \ (encode_coding_object (coding, string, 0, 0, SCHARS (string), \ diff --git a/src/composite.c b/src/composite.c index ddd92389725..8b1f0171a60 100644 --- a/src/composite.c +++ b/src/composite.c @@ -234,7 +234,7 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars, key = components; else if (NILP (components)) { - key = Fmake_vector (make_number (nchars), Qnil); + key = make_uninit_vector (nchars); if (STRINGP (string)) for (i = 0; i < nchars; i++) { @@ -642,13 +642,7 @@ compose_text (ptrdiff_t start, ptrdiff_t end, Lisp_Object components, Qcomposition, prop, string); } - -static Lisp_Object autocmp_chars (Lisp_Object, ptrdiff_t, ptrdiff_t, - ptrdiff_t, struct window *, - struct face *, Lisp_Object); - - -/* Lisp glyph-string handlers */ +/* Lisp glyph-string handlers. */ /* Hash table for automatic composition. The key is a header of a lgstring (Lispy glyph-string), and the value is a body of a @@ -704,10 +698,6 @@ composition_gstring_from_id (ptrdiff_t id) return HASH_VALUE (h, id); } -static Lisp_Object fill_gstring_header (Lisp_Object, Lisp_Object, - Lisp_Object, Lisp_Object, - Lisp_Object); - bool composition_gstring_p (Lisp_Object gstring) { @@ -797,7 +787,8 @@ static Lisp_Object gstring_work; static Lisp_Object gstring_work_headers; static Lisp_Object -fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lisp_Object font_object, Lisp_Object string) +fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, + Lisp_Object font_object, Lisp_Object string) { ptrdiff_t from, to, from_byte; ptrdiff_t len, i; @@ -837,7 +828,7 @@ fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lis if (len <= 8) header = AREF (gstring_work_headers, len - 1); else - header = Fmake_vector (make_number (len + 1), Qnil); + header = make_uninit_vector (len + 1); } ASET (header, 0, font_object); @@ -905,7 +896,9 @@ fill_gstring_body (Lisp_Object gstring) object. Otherwise return nil. */ static Lisp_Object -autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t limit, struct window *win, struct face *face, Lisp_Object string) +autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, + ptrdiff_t limit, struct window *win, struct face *face, + Lisp_Object string) { ptrdiff_t count = SPECPDL_INDEX (); FRAME_PTR f = XFRAME (win->frame); @@ -935,7 +928,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f)) { - font_object = font_range (charpos, &to, win, face, string); + font_object = font_range (charpos, bytepos, &to, win, face, string); if (! FONT_OBJECT_P (font_object) || (! NILP (re) && to < limit @@ -1958,7 +1951,7 @@ syms_of_composite (void) } staticpro (&gstring_work_headers); - gstring_work_headers = Fmake_vector (make_number (8), Qnil); + gstring_work_headers = make_uninit_vector (8); for (i = 0; i < 8; i++) ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil)); staticpro (&gstring_work); diff --git a/src/conf_post.h b/src/conf_post.h index cd1e35bea7a..6c9747a436c 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -182,10 +182,6 @@ extern void _DebPrint (const char *fmt, ...); #endif #endif -/* Tell gnulib to omit support for openat-related functions having a - first argument other than AT_FDCWD. */ -#define GNULIB_SUPPORT_ONLY_AT_FDCWD - #include <string.h> #include <stdlib.h> diff --git a/src/deps.mk b/src/deps.mk index 47185c9262c..83444474c59 100644 --- a/src/deps.mk +++ b/src/deps.mk @@ -144,7 +144,7 @@ macros.o: macros.c window.h buffer.h commands.h macros.h keyboard.h msdos.h \ dispextern.h lisp.h globals.h $(config_h) systime.h coding.h composite.h gmalloc.o: gmalloc.c $(config_h) ralloc.o: ralloc.c lisp.h $(config_h) -vm-limit.o: vm-limit.c mem-limits.h lisp.h globals.h $(config_h) +vm-limit.o: vm-limit.c lisp.h globals.h $(config_h) marker.o: marker.c buffer.h character.h lisp.h globals.h $(config_h) minibuf.o: minibuf.c syntax.h frame.h window.h keyboard.h systime.h \ buffer.h commands.h character.h msdos.h $(INTERVALS_H) keymap.h \ diff --git a/src/dired.c b/src/dired.c index 3dca9d24f67..0e37568f211 100644 --- a/src/dired.c +++ b/src/dired.c @@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <grp.h> #include <errno.h> +#include <fcntl.h> #include <unistd.h> #include <dirent.h> @@ -54,6 +55,7 @@ static Lisp_Object Qfile_attributes; static Lisp_Object Qfile_attributes_lessp; static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); +static Lisp_Object file_attributes (int, char const *, Lisp_Object); /* Return the number of bytes in DP's name. */ static ptrdiff_t @@ -66,6 +68,44 @@ dirent_namelen (struct dirent *dp) #endif } +static DIR * +open_directory (char const *name, int *fdp) +{ + DIR *d; + int fd, opendir_errno; + + block_input (); + +#ifdef DOS_NT + /* Directories cannot be opened. The emulation assumes that any + file descriptor other than AT_FDCWD corresponds to the most + recently opened directory. This hack is good enough for Emacs. */ + fd = 0; + d = opendir (name); + opendir_errno = errno; +#else + fd = emacs_open (name, O_RDONLY | O_DIRECTORY, 0); + if (fd < 0) + { + opendir_errno = errno; + d = 0; + } + else + { + d = fdopendir (fd); + opendir_errno = errno; + if (! d) + close (fd); + } +#endif + + unblock_input (); + + *fdp = fd; + errno = opendir_errno; + return d; +} + #ifdef WINDOWSNT Lisp_Object directory_files_internal_w32_unwind (Lisp_Object arg) @@ -96,6 +136,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object id_format) { DIR *d; + int fd; ptrdiff_t directory_nbytes; Lisp_Object list, dirfilename, encoded_directory; struct re_pattern_buffer *bufp = NULL; @@ -142,9 +183,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, /* Now *bufp is the compiled form of MATCH; don't call anything which might compile a new regexp until we're done with the loop! */ - block_input (); - d = opendir (SSDATA (dirfilename)); - unblock_input (); + d = open_directory (SSDATA (dirfilename), &fd); if (d == NULL) report_file_error ("Opening directory", Fcons (directory, Qnil)); @@ -152,7 +191,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, file-attributes on filenames, both of which can throw, so we must do a proper unwind-protect. */ record_unwind_protect (directory_files_internal_unwind, - make_save_value (d, 0)); + make_save_pointer (d)); #ifdef WINDOWSNT if (attrs) @@ -259,20 +298,9 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, 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); - + Lisp_Object fileattrs + = file_attributes (fd, dp->d_name, id_format); list = Fcons (Fcons (finalname, fileattrs), list); - UNGCPRO; } else list = Fcons (finalname, list); @@ -413,8 +441,7 @@ 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, struct dirent *dp, - struct stat *st_addr); +static int file_name_completion_stat (int, struct dirent *, struct stat *); static Lisp_Object Qdefault_directory; static Lisp_Object @@ -422,6 +449,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, Lisp_Object predicate) { DIR *d; + int fd; ptrdiff_t bestmatchsize = 0; int matchcount = 0; /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded. @@ -456,16 +484,14 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, on the encoded file name. */ encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; - encoded_dir = ENCODE_FILE (dirname); + encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname)); - block_input (); - d = opendir (SSDATA (Fdirectory_file_name (encoded_dir))); - unblock_input (); + d = open_directory (SSDATA (encoded_dir), &fd); if (!d) report_file_error ("Opening directory", Fcons (dirname, Qnil)); record_unwind_protect (directory_files_internal_unwind, - make_save_value (d, 0)); + make_save_pointer (d)); /* Loop reading blocks */ /* (att3b compiler bug requires do a null comparison this way) */ @@ -495,7 +521,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, SCHARS (encoded_file))) continue; - if (file_name_completion_stat (encoded_dir, dp, &st) < 0) + if (file_name_completion_stat (fd, dp, &st) < 0) continue; directoryp = S_ISDIR (st.st_mode) != 0; @@ -772,14 +798,9 @@ scmp (const char *s1, const char *s2, ptrdiff_t len) } static int -file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, - struct stat *st_addr) +file_name_completion_stat (int fd, struct dirent *dp, struct stat *st_addr) { - ptrdiff_t len = dirent_namelen (dp); - ptrdiff_t pos = SCHARS (dirname); int value; - USE_SAFE_ALLOCA; - char *fullname = SAFE_ALLOCA (len + pos + 2); #ifdef MSDOS /* Some fields of struct stat are *very* expensive to compute on MS-DOS, @@ -792,23 +813,15 @@ file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; #endif /* MSDOS */ - memcpy (fullname, SDATA (dirname), pos); - if (!IS_DIRECTORY_SEP (fullname[pos - 1])) - fullname[pos++] = DIRECTORY_SEP; - - memcpy (fullname + pos, dp->d_name, len); - fullname[pos + len] = 0; - /* We want to return success if a link points to a nonexistent file, but we want to return the status for what the link points to, in case it is a directory. */ - value = lstat (fullname, st_addr); + value = fstatat (fd, dp->d_name, st_addr, AT_SYMLINK_NOFOLLOW); if (value == 0 && S_ISLNK (st_addr->st_mode)) - stat (fullname, st_addr); + fstatat (fd, dp->d_name, st_addr, 0); #ifdef MSDOS _djstat_flags = save_djstat_flags; #endif /* MSDOS */ - SAFE_FREE (); return value; } @@ -886,18 +899,8 @@ On some FAT-based filesystems, only the date of last access is recorded, so last access time will always be midnight of that day. */) (Lisp_Object filename, Lisp_Object id_format) { - Lisp_Object values[12]; Lisp_Object encoded; - struct stat s; - int lstat_result; - - /* An array to hold the mode string generated by filemodestring, - including its terminating space and null byte. */ - char modes[sizeof "-rwxr-xr-x "]; - Lisp_Object handler; - struct gcpro gcpro1; - char *uname = NULL, *gname = NULL; filename = Fexpand_file_name (filename, Qnil); @@ -913,9 +916,22 @@ so last access time will always be midnight of that day. */) return call3 (handler, Qfile_attributes, filename, id_format); } - GCPRO1 (filename); encoded = ENCODE_FILE (filename); - UNGCPRO; + return file_attributes (AT_FDCWD, SSDATA (encoded), id_format); +} + +static Lisp_Object +file_attributes (int fd, char const *name, Lisp_Object id_format) +{ + Lisp_Object values[12]; + struct stat s; + int lstat_result; + + /* An array to hold the mode string generated by filemodestring, + including its terminating space and null byte. */ + char modes[sizeof "-rwxr-xr-x "]; + + char *uname = NULL, *gname = NULL; #ifdef WINDOWSNT /* We usually don't request accurate owner and group info, because @@ -925,7 +941,7 @@ so last access time will always be midnight of that day. */) w32_stat_get_owner_group = 1; #endif - lstat_result = lstat (SSDATA (encoded), &s); + lstat_result = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW); #ifdef WINDOWSNT w32_stat_get_owner_group = 0; @@ -934,7 +950,7 @@ so last access time will always be midnight of that day. */) if (lstat_result < 0) return Qnil; - values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename) + values[0] = (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name) : S_ISDIR (s.st_mode) ? Qt : Qnil); values[1] = make_number (s.st_nlink); diff --git a/src/dispnew.c b/src/dispnew.c index 1e9d94f3789..f9fed7de406 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -87,7 +87,6 @@ static void build_frame_matrix_from_window_tree (struct glyph_matrix *, struct window *); static void build_frame_matrix_from_leaf_window (struct glyph_matrix *, struct window *); -static void adjust_frame_message_buffer (struct frame *); static void adjust_decode_mode_spec_buffer (struct frame *); static void fill_up_glyph_row_with_spaces (struct glyph_row *); static void clear_window_matrices (struct window *, bool); @@ -108,12 +107,6 @@ static void set_window_cursor_after_update (struct window *); static void adjust_frame_glyphs_for_window_redisplay (struct frame *); static void adjust_frame_glyphs_for_frame_redisplay (struct frame *); - -/* Redisplay preemption timers. */ - -static EMACS_TIME preemption_period; -static EMACS_TIME preemption_next_check; - /* True upon entry to redisplay means do not assume anything about current contents of actual terminal frame; clear and redraw it. */ @@ -607,7 +600,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y are invalidated below. */ if (INTEGERP (w->window_end_vpos) && XFASTINT (w->window_end_vpos) >= i) - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; while (i < matrix->nrows) matrix->rows[i++].enabled_p = 0; @@ -862,7 +855,7 @@ clear_window_matrices (struct window *w, bool desired_p) else { clear_glyph_matrix (w->current_matrix); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; } } @@ -1857,9 +1850,7 @@ adjust_frame_glyphs (struct frame *f) else adjust_frame_glyphs_for_frame_redisplay (f); - /* Don't forget the message buffer and the buffer for - decode_mode_spec. */ - adjust_frame_message_buffer (f); + /* Don't forget the buffer for decode_mode_spec. */ adjust_decode_mode_spec_buffer (f); f->glyphs_initialized_p = 1; @@ -2159,23 +2150,6 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f) } -/* Adjust/ allocate message buffer of frame F. - - Note that the message buffer is never freed. Since I could not - find a free in 19.34, I assume that freeing it would be - problematic in some way and don't do it either. - - (Implementation note: It should be checked if we can free it - eventually without causing trouble). */ - -static void -adjust_frame_message_buffer (struct frame *f) -{ - FRAME_MESSAGE_BUF (f) = xrealloc (FRAME_MESSAGE_BUF (f), - FRAME_MESSAGE_BUF_SIZE (f) + 1); -} - - /* Re-allocate buffer for decode_mode_spec on frame F. */ static void @@ -3100,21 +3074,10 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p) if (redisplay_dont_pause) force_p = 1; - else if (NILP (Vredisplay_preemption_period)) - force_p = 1; - else if (!force_p && NUMBERP (Vredisplay_preemption_period)) + else if (!force_p && detect_input_pending_ignore_squeezables ()) { - double p = XFLOATINT (Vredisplay_preemption_period); - - if (detect_input_pending_ignore_squeezables ()) - { - paused_p = 1; - goto do_pause; - } - - preemption_period = EMACS_TIME_FROM_DOUBLE (p); - preemption_next_check = add_emacs_time (current_emacs_time (), - preemption_period); + paused_p = 1; + goto do_pause; } if (FRAME_WINDOW_P (f)) @@ -3252,15 +3215,6 @@ update_single_window (struct window *w, bool force_p) if (redisplay_dont_pause) force_p = 1; - else if (NILP (Vredisplay_preemption_period)) - force_p = 1; - else if (!force_p && NUMBERP (Vredisplay_preemption_period)) - { - double p = XFLOATINT (Vredisplay_preemption_period); - preemption_period = EMACS_TIME_FROM_DOUBLE (p); - preemption_next_check = add_emacs_time (current_emacs_time (), - preemption_period); - } /* Update W. */ update_begin (f); @@ -3414,9 +3368,7 @@ update_window (struct window *w, bool force_p) { struct glyph_matrix *desired_matrix = w->desired_matrix; bool paused_p; -#if !PERIODIC_PREEMPTION_CHECKING int preempt_count = baud_rate / 2400 + 1; -#endif struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); #ifdef GLYPH_DEBUG /* Check that W's frame doesn't have glyph matrices. */ @@ -3424,10 +3376,8 @@ update_window (struct window *w, bool force_p) #endif /* Check pending input the first time so that we can quickly return. */ -#if !PERIODIC_PREEMPTION_CHECKING if (!force_p) detect_input_pending_ignore_squeezables (); -#endif /* If forced to complete the update, or if no input is pending, do the update. */ @@ -3438,9 +3388,7 @@ update_window (struct window *w, bool force_p) struct glyph_row *header_line_row; int yb; bool changed_p = 0, mouse_face_overwritten_p = 0; -#if ! PERIODIC_PREEMPTION_CHECKING int n_updated = 0; -#endif rif->update_window_begin_hook (w); yb = window_text_bottom_y (w); @@ -3504,22 +3452,8 @@ update_window (struct window *w, bool force_p) detect_input_pending. If it's done too often, scrolling large windows with repeated scroll-up commands will too quickly pause redisplay. */ -#if PERIODIC_PREEMPTION_CHECKING - if (!force_p) - { - EMACS_TIME tm = current_emacs_time (); - if (EMACS_TIME_LT (preemption_next_check, tm)) - { - preemption_next_check = add_emacs_time (tm, - preemption_period); - if (detect_input_pending_ignore_squeezables ()) - break; - } - } -#else if (!force_p && ++n_updated % preempt_count == 0) detect_input_pending_ignore_squeezables (); -#endif changed_p |= update_window_line (w, vpos, &mouse_face_overwritten_p); @@ -4551,13 +4485,11 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p) if (preempt_count <= 0) preempt_count = 1; -#if !PERIODIC_PREEMPTION_CHECKING if (!force_p && detect_input_pending_ignore_squeezables ()) { pause_p = 1; goto do_pause; } -#endif /* If we cannot insert/delete lines, it's no use trying it. */ if (!FRAME_LINE_INS_DEL_OK (f)) @@ -4598,21 +4530,8 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p) } } -#if PERIODIC_PREEMPTION_CHECKING - if (!force_p) - { - EMACS_TIME tm = current_emacs_time (); - if (EMACS_TIME_LT (preemption_next_check, tm)) - { - preemption_next_check = add_emacs_time (tm, preemption_period); - if (detect_input_pending_ignore_squeezables ()) - break; - } - } -#else if (!force_p && (i - 1) % preempt_count == 0) detect_input_pending_ignore_squeezables (); -#endif update_frame_line (f, i); } @@ -4718,9 +4637,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p) } } -#if !PERIODIC_PREEMPTION_CHECKING do_pause: -#endif clear_desired_matrices (f); return pause_p; @@ -6097,7 +6014,6 @@ init_display (void) inverse_video = 0; cursor_in_echo_area = 0; - terminal_type = (char *) 0; /* Now is the time to initialize this; it's used by init_sys_modes during startup. */ @@ -6192,8 +6108,7 @@ init_display (void) #ifdef WINDOWSNT terminal_type = "w32console"; #else - /* Look at the TERM variable. */ - terminal_type = (char *) getenv ("TERM"); + terminal_type = getenv ("TERM"); #endif if (!terminal_type) { @@ -6430,15 +6345,6 @@ See `buffer-display-table' for more information. */); doc: /* Non-nil means display update isn't paused when input is detected. */); redisplay_dont_pause = 1; -#if PERIODIC_PREEMPTION_CHECKING - DEFVAR_LISP ("redisplay-preemption-period", Vredisplay_preemption_period, - doc: /* Period in seconds between checking for input during redisplay. -This has an effect only if `redisplay-dont-pause' is nil; in that -case, arriving input preempts redisplay until the input is processed. -If the value is nil, redisplay is never preempted. */); - Vredisplay_preemption_period = make_float (0.10); -#endif - #ifdef CANNOT_DUMP if (noninteractive) #endif diff --git a/src/doc.c b/src/doc.c index 16c0d4090a0..7234fb38bf9 100644 --- a/src/doc.c +++ b/src/doc.c @@ -176,9 +176,9 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) if (space_left <= 0) { ptrdiff_t in_buffer = p - get_doc_string_buffer; - get_doc_string_buffer = - xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size, - 16 * 1024, -1, 1); + get_doc_string_buffer + = xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size, + 16 * 1024, -1, 1); p = get_doc_string_buffer + in_buffer; space_left = (get_doc_string_buffer_size - 1 - (p - get_doc_string_buffer)); @@ -279,10 +279,10 @@ Invalid data in documentation file -- %c followed by code %03o", else { /* The data determines whether the string is multibyte. */ - ptrdiff_t nchars = - multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer - + offset), - to - (get_doc_string_buffer + offset)); + ptrdiff_t nchars + = multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer + + offset), + to - (get_doc_string_buffer + offset)); return make_string_from_bytes (get_doc_string_buffer + offset, nchars, to - (get_doc_string_buffer + offset)); @@ -630,11 +630,10 @@ the same file name is found in the `doc-directory'. */) break; buf[filled] = 0; - p = buf; end = buf + (filled < 512 ? filled : filled - 128); - while (p != end && *p != '\037') p++; + p = memchr (buf, '\037', end - buf); /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */ - if (p != end) + if (p) { end = strchr (p, '\n'); diff --git a/src/doprnt.c b/src/doprnt.c index b8e1b547268..471e35c7b43 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -38,7 +38,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ could include embedded null characters. . It signals an error if the length of the formatted string is about to - overflow MOST_POSITIVE_FIXNUM, to avoid producing strings longer than what + overflow ptrdiff_t or size_t, to avoid producing strings longer than what Emacs can handle. OTOH, this function supports only a small subset of the standard C formatted diff --git a/src/editfns.c b/src/editfns.c index 8910b66e4d3..f34c574cae3 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -386,6 +386,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o ptrdiff_t noverlays; Lisp_Object *overlay_vec, tem; struct buffer *obuf = current_buffer; + USE_SAFE_ALLOCA; set_buffer_temp (XBUFFER (object)); @@ -398,7 +399,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o make enough space for all, and try again. */ if (noverlays > 40) { - overlay_vec = alloca (noverlays * sizeof *overlay_vec); + SAFE_ALLOCA_LISP (overlay_vec, noverlays); noverlays = overlays_around (posn, overlay_vec, noverlays); } noverlays = sort_overlays (overlay_vec, noverlays, NULL); @@ -421,10 +422,12 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o ; /* The overlay will not cover a char inserted at point. */ else { + SAFE_FREE (); return tem; } } } + SAFE_FREE (); { /* Now check the text properties. */ int stickiness = text_property_stickiness (prop, position, object); @@ -666,7 +669,8 @@ If the optional argument INHIBIT-CAPTURE-PROPERTY is non-nil, and OLD-POS has a non-nil property of that name, then any field boundaries are ignored. Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) - (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, Lisp_Object only_in_line, Lisp_Object inhibit_capture_property) + (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, + Lisp_Object only_in_line, Lisp_Object inhibit_capture_property) { /* If non-zero, then the original point, before re-positioning. */ ptrdiff_t orig_point = 0; @@ -732,9 +736,9 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) /* This is the ONLY_IN_LINE case, check that NEW_POS and FIELD_BOUND are on the same line by seeing whether there's an intervening newline or not. */ - || (scan_buffer ('\n', - XFASTINT (new_pos), XFASTINT (field_bound), - fwd ? -1 : 1, &shortage, 1), + || (find_newline (XFASTINT (new_pos), -1, + XFASTINT (field_bound), -1, + fwd ? -1 : 1, &shortage, NULL, 1), shortage != 0))) /* Constrain NEW_POS to FIELD_BOUND. */ new_pos = field_bound; @@ -819,7 +823,8 @@ This function does not move point. */) CHECK_NUMBER (n); clipped_n = clip_to_bounds (PTRDIFF_MIN + 1, XINT (n), PTRDIFF_MAX); - end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0)); + end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0), + NULL); /* Return END_POS constrained to the current input field. */ return Fconstrain_to_field (make_number (end_pos), make_number (orig), @@ -833,7 +838,7 @@ This function does not move point. */) Lisp_Object save_excursion_save (void) { - return format_save_value + return make_save_value ("oooo", Fpoint_marker (), /* Do not copy the mark if it points to nowhere. */ @@ -1481,9 +1486,7 @@ Lisp_Object make_lisp_time (EMACS_TIME t) { int ns = EMACS_NSECS (t); - return make_time_tail (EMACS_SECS (t), - list2 (make_number (ns / 1000), - make_number (ns % 1000 * 1000))); + return make_time_tail (EMACS_SECS (t), list2i (ns / 1000, ns % 1000 * 1000)); } /* Decode a Lisp list SPECIFIED_TIME that represents a time. @@ -3426,12 +3429,6 @@ usage: (save-restriction &rest BODY) */) return unbind_to (count, val); } -/* Buffer for the most recent text displayed by Fmessage_box. */ -static char *message_text; - -/* Allocated length of that buffer. */ -static ptrdiff_t message_length; - DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, doc: /* Display a message at the bottom of the screen. The message also goes into the `*Messages*' buffer, if `message-log-max' @@ -3455,14 +3452,14 @@ usage: (message FORMAT-STRING &rest ARGS) */) || (STRINGP (args[0]) && SBYTES (args[0]) == 0)) { - message (0); + message1 (0); return args[0]; } else { register Lisp_Object val; val = Fformat (nargs, args); - message3 (val, SBYTES (val), STRING_MULTIBYTE (val)); + message3 (val); return val; } } @@ -3481,13 +3478,12 @@ usage: (message-box FORMAT-STRING &rest ARGS) */) { if (NILP (args[0])) { - message (0); + message1 (0); return Qnil; } else { - register Lisp_Object val; - val = Fformat (nargs, args); + Lisp_Object val = Fformat (nargs, args); #ifdef HAVE_MENUS /* The MS-DOS frames support popup menus even though they are not FRAME_WINDOW_P. */ @@ -3504,16 +3500,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */) return val; } #endif /* HAVE_MENUS */ - /* Copy the data so that it won't move when we GC. */ - if (SBYTES (val) > message_length) - { - ptrdiff_t new_length = SBYTES (val) + 80; - message_text = xrealloc (message_text, new_length); - message_length = new_length; - } - memcpy (message_text, SDATA (val), SBYTES (val)); - message2 (message_text, SBYTES (val), - STRING_MULTIBYTE (val)); + message3 (val); return val; } } @@ -4249,7 +4236,7 @@ usage: (format STRING &rest OBJECTS) */) { buf = xmalloc (bufsize); sa_must_free = 1; - buf_save_value = make_save_value (buf, 0); + buf_save_value = make_save_pointer (buf); record_unwind_protect (safe_alloca_unwind, buf_save_value); memcpy (buf, initial_buffer, used); } diff --git a/src/emacs.c b/src/emacs.c index 1848c71a22f..7b6f147619b 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -134,6 +134,7 @@ Lisp_Object Qfile_name_handler_alist; Lisp_Object Qrisky_local_variable; Lisp_Object Qkill_emacs; +static Lisp_Object Qkill_emacs_hook; /* If true, Emacs should not attempt to use a window-specific code, but instead should use the virtual terminal under which it was started. */ @@ -516,32 +517,6 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory, static char const dump_tz[] = "UtC0"; #endif -#ifndef ORDINARY_LINK -/* We don't include crtbegin.o and crtend.o in the link, - so these functions and variables might be missed. - Provide dummy definitions to avoid error. - (We don't have any real constructors or destructors.) */ -#ifdef __GNUC__ - -/* Define a dummy function F. Declare F too, to pacify gcc - -Wmissing-prototypes. */ -#define DEFINE_DUMMY_FUNCTION(f) \ - void f (void) ATTRIBUTE_CONST EXTERNALLY_VISIBLE; void f (void) {} - -#ifndef GCC_CTORS_IN_LIBC -DEFINE_DUMMY_FUNCTION (__do_global_ctors) -DEFINE_DUMMY_FUNCTION (__do_global_ctors_aux) -DEFINE_DUMMY_FUNCTION (__do_global_dtors) -/* GNU/Linux has a bug in its library; avoid an error. */ -#ifndef GNU_LINUX -char * __CTOR_LIST__[2] EXTERNALLY_VISIBLE = { (char *) (-1), 0 }; -#endif -char * __DTOR_LIST__[2] EXTERNALLY_VISIBLE = { (char *) (-1), 0 }; -#endif /* GCC_CTORS_IN_LIBC */ -DEFINE_DUMMY_FUNCTION (__main) -#endif /* __GNUC__ */ -#endif /* ORDINARY_LINK */ - /* Test whether the next argument in ARGV matches SSTR or a prefix of LSTR (at least MINLEN characters). If so, then if VALPTR is non-null (the argument is supposed to have a value) store in *VALPTR either @@ -1047,7 +1022,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem argv[skip_args] = fdStr; - execv (argv[0], argv); + execvp (argv[0], argv); fprintf (stderr, "emacs daemon: exec failed: %d\n", errno); exit (1); } @@ -1308,6 +1283,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem } init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ + init_fileio (); init_lread (); #ifdef WINDOWSNT /* Check to see if Emacs has been installed correctly. */ @@ -1832,7 +1808,6 @@ all of which are called before Emacs is actually killed. */) (Lisp_Object arg) { struct gcpro gcpro1; - Lisp_Object hook; int exit_code; GCPRO1 (arg); @@ -1840,9 +1815,10 @@ all of which are called before Emacs is actually killed. */) if (feof (stdin)) arg = Qt; - hook = intern ("kill-emacs-hook"); - Frun_hooks (1, &hook); - + /* Fsignal calls emacs_abort () if it sees that waiting_for_input is + set. */ + waiting_for_input = 0; + Frun_hooks (1, &Qkill_emacs_hook); UNGCPRO; #ifdef HAVE_X_WINDOWS @@ -2142,7 +2118,7 @@ decode_env_path (const char *evarname, const char *defalt) { char *path_copy = alloca (strlen (path) + 1); strcpy (path_copy, path); - dostounix_filename (path_copy); + dostounix_filename (path_copy, 0); path = path_copy; } #endif @@ -2254,6 +2230,7 @@ syms_of_emacs (void) DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist"); DEFSYM (Qrisky_local_variable, "risky-local-variable"); DEFSYM (Qkill_emacs, "kill-emacs"); + DEFSYM (Qkill_emacs_hook, "kill-emacs-hook"); #ifndef CANNOT_DUMP defsubr (&Sdump_emacs); diff --git a/src/eval.c b/src/eval.c index 18031236c7d..6d34cd80802 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1917,7 +1917,7 @@ If LEXICAL is t, evaluate using lexical scoping. */) { ptrdiff_t count = SPECPDL_INDEX (); specbind (Qinternal_interpreter_environment, - NILP (lexical) ? Qnil : Fcons (Qt, Qnil)); + CONSP (lexical) || NILP (lexical) ? lexical : Fcons (Qt, Qnil)); return unbind_to (count, eval_sub (form)); } diff --git a/src/fileio.c b/src/fileio.c index 87d945c1e5e..d7363077b35 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -82,6 +82,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif #include "systime.h" +#include <allocator.h> +#include <careadlinkat.h> #include <stat-time.h> #ifdef HPUX @@ -103,6 +105,11 @@ static mode_t auto_save_mode_bits; /* Set by auto_save_1 if an error occurred during the last auto-save. */ static bool auto_save_error_occurred; +/* If VALID_TIMESTAMP_FILE_SYSTEM, then TIMESTAMP_FILE_SYSTEM is the device + number of a file system where time stamps were observed to to work. */ +static bool valid_timestamp_file_system; +static dev_t timestamp_file_system; + /* The symbol bound to coding-system-for-read when insert-file-contents is called for recovering a file. This is not an actual coding system name, but just an indicator to tell @@ -126,9 +133,6 @@ static Lisp_Object Qwrite_region_annotate_functions; is added here. */ static Lisp_Object Vwrite_region_annotation_buffers; -#ifdef HAVE_FSYNC -#endif - static Lisp_Object Qdelete_by_moving_to_trash; /* Lisp function for moving files to trash. */ @@ -244,6 +248,7 @@ static Lisp_Object Qfile_acl; static Lisp_Object Qset_file_acl; static Lisp_Object Qfile_newer_than_file_p; Lisp_Object Qinsert_file_contents; +static Lisp_Object Qchoose_write_coding_system; Lisp_Object Qwrite_region; static Lisp_Object Qverify_visited_file_modtime; static Lisp_Object Qset_visited_file_modtime; @@ -375,11 +380,13 @@ Given a Unix syntax file name, returns a string ending in slash. */) if (getdefdir (c_toupper (*beg) - 'A' + 1, r)) { - if (!IS_DIRECTORY_SEP (res[strlen (res) - 1])) + size_t l = strlen (res); + + if (l > 3 || !IS_DIRECTORY_SEP (res[l - 1])) strcat (res, "/"); beg = res; p = beg + strlen (beg); - dostounix_filename (beg); + dostounix_filename (beg, 0); tem_fn = make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); } @@ -389,13 +396,16 @@ Given a Unix syntax file name, returns a string ending in slash. */) } else if (STRING_MULTIBYTE (filename)) { - tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1)); - dostounix_filename (SSDATA (tem_fn)); - tem_fn = DECODE_FILE (tem_fn); + tem_fn = make_specified_string (beg, -1, p - beg, 1); + dostounix_filename (SSDATA (tem_fn), 1); +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + tem_fn = Fdowncase (tem_fn); +#endif } else { - dostounix_filename (beg); + dostounix_filename (beg, 0); tem_fn = make_specified_string (beg, -1, p - beg, 0); } return tem_fn; @@ -499,17 +509,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen, srclen++; } #ifdef DOS_NT - if (multibyte) - { - 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); - } - else - dostounix_filename (dst); + dostounix_filename (dst, multibyte); #endif return srclen; } @@ -544,6 +544,10 @@ For a Unix-syntax file name, just appends a slash. */) error ("Invalid handler in `file-name-handler-alist'"); } +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + file = Fdowncase (file); +#endif buf = alloca (SBYTES (file) + 10); length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), STRING_MULTIBYTE (file)); @@ -572,17 +576,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) srclen--; } #ifdef DOS_NT - if (multibyte) - { - 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); - } - else - dostounix_filename (dst); + dostounix_filename (dst, multibyte); #endif return srclen; } @@ -617,6 +611,10 @@ In Unix-syntax, this function just removes the final slash. */) error ("Invalid handler in `file-name-handler-alist'"); } +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + directory = Fdowncase (directory); +#endif buf = alloca (SBYTES (directory) + 20); length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), STRING_MULTIBYTE (directory)); @@ -917,6 +915,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) } } +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + default_directory = Fdowncase (default_directory); +#endif + /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ nm = alloca (SBYTES (name) + 1); memcpy (nm, SSDATA (name), SBYTES (name) + 1); @@ -1000,18 +1003,7 @@ 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. */ - 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); + dostounix_filename (nm, multibyte); #ifdef WINDOWSNT if (IS_DIRECTORY_SEP (nm[1])) { @@ -1029,6 +1021,10 @@ filesystem tree, not (expand-file-name ".." dirname). */) temp[0] = DRIVE_LETTER (drive); name = concat2 (build_string (temp), name); } +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + name = Fdowncase (name); +#endif return name; #else /* not DOS_NT */ if (strcmp (nm, SSDATA (name)) == 0) @@ -1349,8 +1345,8 @@ filesystem tree, not (expand-file-name ".." dirname). */) #ifdef WINDOWSNT char *prev_o = o; #endif - while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) - ; + while (o != target && (--o, !IS_DIRECTORY_SEP (*o))) + continue; #ifdef WINDOWSNT /* Don't go below server level in UNC filenames. */ if (o == target + 1 && IS_DIRECTORY_SEP (*o) @@ -1392,14 +1388,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) target[1] = ':'; } result = make_specified_string (target, -1, o - target, multibyte); - if (multibyte) - { - result = ENCODE_FILE (result); - dostounix_filename (SSDATA (result)); - result = DECODE_FILE (result); - } - else - dostounix_filename (SSDATA (result)); + dostounix_filename (SSDATA (result), multibyte); +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + result = Fdowncase (result); +#endif #else /* !DOS_NT */ result = make_specified_string (target, -1, o - target, multibyte); #endif /* !DOS_NT */ @@ -1681,24 +1674,8 @@ those `/' is discarded. */) memcpy (nm, SDATA (filename), SBYTES (filename) + 1); #ifdef DOS_NT - if (multibyte) - { - 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; - } - else - { - dostounix_filename (nm); - substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); - } + dostounix_filename (nm, multibyte); + substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); #endif endp = nm + SBYTES (filename); @@ -1733,8 +1710,9 @@ those `/' is discarded. */) else if (*p == '{') { o = ++p; - while (p != endp && *p != '}') p++; - if (*p != '}') goto missingclose; + p = memchr (p, '}', endp - p); + if (! p) + goto missingclose; s = p; } else @@ -1772,7 +1750,13 @@ those `/' is discarded. */) } if (!substituted) - return filename; + { +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + filename = Fdowncase (filename); +#endif + return filename; + } /* If substitution required, recopy the string and do it. */ /* Make space in stack frame for the new copy. */ @@ -1796,8 +1780,9 @@ those `/' is discarded. */) else if (*p == '{') { o = ++p; - while (p != endp && *p != '}') p++; - if (*p != '}') goto missingclose; + p = memchr (p, '}', endp - p); + if (! p) + goto missingclose; s = p++; } else @@ -1811,9 +1796,6 @@ those `/' is discarded. */) target = alloca (s - o + 1); memcpy (target, o, s - o); target[s - o] = 0; -#ifdef DOS_NT - strupr (target); /* $home == $HOME etc. */ -#endif /* DOS_NT */ /* Get variable value. */ o = egetenv (target); @@ -1850,6 +1832,16 @@ those `/' is discarded. */) need to quote some $ to $$ first. */ xnm = p; +#ifdef WINDOWSNT + if (!NILP (Vw32_downcase_file_names)) + { + Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte); + + xname = Fdowncase (xname); + return xname; + } + else +#endif return make_specified_string (xnm, -1, x - xnm, multibyte); badsubst: @@ -2753,6 +2745,29 @@ If there is no error, returns nil. */) return Qnil; } +/* Relative to directory FD, return the symbolic link value of FILENAME. + On failure, return nil. */ +Lisp_Object +emacs_readlinkat (int fd, char const *filename) +{ + static struct allocator const emacs_norealloc_allocator = + { xmalloc, NULL, xfree, memory_full }; + Lisp_Object val; + char readlink_buf[1024]; + char *buf = careadlinkat (fd, filename, readlink_buf, sizeof readlink_buf, + &emacs_norealloc_allocator, readlinkat); + if (!buf) + return Qnil; + + val = build_string (buf); + if (buf[0] == '/' && strchr (buf, ':')) + val = concat2 (build_string ("/:"), val); + if (buf != readlink_buf) + xfree (buf); + val = DECODE_FILE (val); + return val; +} + DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, doc: /* Return non-nil if file FILENAME is the name of a symbolic link. The value is the link target, as a string. @@ -2763,9 +2778,6 @@ points to a nonexistent file. */) (Lisp_Object filename) { Lisp_Object handler; - char *buf; - Lisp_Object val; - char readlink_buf[READLINK_BUFSIZE]; CHECK_STRING (filename); filename = Fexpand_file_name (filename, Qnil); @@ -2778,17 +2790,7 @@ points to a nonexistent file. */) filename = ENCODE_FILE (filename); - buf = emacs_readlink (SSDATA (filename), readlink_buf); - if (! buf) - return Qnil; - - val = build_string (buf); - if (buf[0] == '/' && strchr (buf, ':')) - val = concat2 (build_string ("/:"), val); - if (buf != readlink_buf) - xfree (buf); - val = DECODE_FILE (val); - return val; + return emacs_readlinkat (AT_FDCWD, SSDATA (filename)); } DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, @@ -3425,6 +3427,8 @@ read_non_regular (Lisp_Object state) + XSAVE_INTEGER (state, 1)), XSAVE_INTEGER (state, 2)); immediate_quit = 0; + /* Fast recycle this object for the likely next call. */ + free_misc (state); return make_number (nbytes); } @@ -3438,19 +3442,25 @@ read_non_regular_quit (Lisp_Object ignore) return Qnil; } -/* Reposition FD to OFFSET, based on WHENCE. This acts like lseek - except that it also tests for OFFSET being out of lseek's range. */ +/* Return the file offset that VAL represents, checking for type + errors and overflow. */ static off_t -emacs_lseek (int fd, EMACS_INT offset, int whence) +file_offset (Lisp_Object val) { - /* Use "&" rather than "&&" to suppress a bogus GCC warning; see - <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>. */ - if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t)))) + if (RANGED_INTEGERP (0, val, TYPE_MAXIMUM (off_t))) + return XINT (val); + + if (FLOATP (val)) { - errno = EINVAL; - return -1; + double v = XFLOAT_DATA (val); + if (0 <= v + && (sizeof (off_t) < sizeof v + ? v <= TYPE_MAXIMUM (off_t) + : v < TYPE_MAXIMUM (off_t))) + return v; } - return lseek (fd, offset, whence); + + wrong_type_argument (intern ("file-offset"), val); } /* Return a special time value indicating the error number ERRNUM. */ @@ -3492,7 +3502,6 @@ by calling `format-decode', which see. */) (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace) { struct stat st; - int file_status; EMACS_TIME mtime; int fd; ptrdiff_t inserted = 0; @@ -3509,7 +3518,6 @@ by calling `format-decode', which see. */) int save_errno = 0; char read_buf[READ_BUF_SIZE]; struct coding_system coding; - char buffer[1 << 14]; bool replace_handled = 0; bool set_coding_system = 0; Lisp_Object coding_system; @@ -3554,37 +3562,29 @@ by calling `format-decode', which see. */) orig_filename = filename; filename = ENCODE_FILE (filename); - fd = -1; - -#ifdef WINDOWSNT - { - Lisp_Object tem = Vw32_get_true_file_attributes; - - /* Tell stat to use expensive method to get accurate info. */ - Vw32_get_true_file_attributes = Qt; - file_status = stat (SSDATA (filename), &st); - Vw32_get_true_file_attributes = tem; - } -#else - file_status = stat (SSDATA (filename), &st); -#endif /* WINDOWSNT */ - - if (file_status == 0) - mtime = get_stat_mtime (&st); - else + fd = emacs_open (SSDATA (filename), O_RDONLY, 0); + if (fd < 0) { - badopen: save_errno = errno; if (NILP (visit)) report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); mtime = time_error_value (save_errno); st.st_size = -1; - how_much = 0; if (!NILP (Vcoding_system_for_read)) Fset (Qbuffer_file_coding_system, Vcoding_system_for_read); goto notfound; } + /* Replacement should preserve point as it preserves markers. */ + if (!NILP (replace)) + record_unwind_protect (restore_point_unwind, Fpoint_marker ()); + + record_unwind_protect (close_file_unwind, make_number (fd)); + + if (fstat (fd, &st) != 0) + report_file_error ("Input file status", Fcons (orig_filename, Qnil)); + mtime = get_stat_mtime (&st); + /* This code will need to be changed in order to work on named pipes, and it's probably just not worth it. So we should at least signal an error. */ @@ -3600,17 +3600,6 @@ by calling `format-decode', which see. */) build_string ("not a regular file"), orig_filename); } - if (fd < 0) - if ((fd = emacs_open (SSDATA (filename), O_RDONLY, 0)) < 0) - goto badopen; - - /* Replacement should preserve point as it preserves markers. */ - if (!NILP (replace)) - record_unwind_protect (restore_point_unwind, Fpoint_marker ()); - - record_unwind_protect (close_file_unwind, make_number (fd)); - - if (!NILP (visit)) { if (!NILP (beg) || !NILP (end)) @@ -3620,20 +3609,12 @@ by calling `format-decode', which see. */) } if (!NILP (beg)) - { - if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))) - wrong_type_argument (intern ("file-offset"), beg); - beg_offset = XFASTINT (beg); - } + beg_offset = file_offset (beg); else beg_offset = 0; if (!NILP (end)) - { - if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))) - wrong_type_argument (intern ("file-offset"), end); - end_offset = XFASTINT (end); - } + end_offset = file_offset (end); else { if (not_regular) @@ -3838,7 +3819,7 @@ by calling `format-decode', which see. */) { int nread, bufpos; - nread = emacs_read (fd, buffer, sizeof buffer); + nread = emacs_read (fd, read_buf, sizeof read_buf); if (nread < 0) error ("IO error reading %s: %s", SSDATA (orig_filename), emacs_strerror (errno)); @@ -3847,7 +3828,7 @@ by calling `format-decode', which see. */) if (CODING_REQUIRE_DETECTION (&coding)) { - coding_system = detect_coding_system ((unsigned char *) buffer, + coding_system = detect_coding_system ((unsigned char *) read_buf, nread, nread, 1, 0, coding_system); setup_coding_system (coding_system, &coding); @@ -3863,7 +3844,7 @@ by calling `format-decode', which see. */) bufpos = 0; while (bufpos < nread && same_at_start < ZV_BYTE - && FETCH_BYTE (same_at_start) == buffer[bufpos]) + && FETCH_BYTE (same_at_start) == read_buf[bufpos]) same_at_start++, bufpos++; /* If we found a discrepancy, stop the scan. Otherwise loop around and scan the next bufferful. */ @@ -3897,7 +3878,7 @@ by calling `format-decode', which see. */) if (curpos == 0) break; /* How much can we scan in the next step? */ - trial = min (curpos, sizeof buffer); + trial = min (curpos, sizeof read_buf); if (lseek (fd, curpos - trial, SEEK_SET) < 0) report_file_error ("Setting file position", Fcons (orig_filename, Qnil)); @@ -3905,7 +3886,7 @@ by calling `format-decode', which see. */) total_read = nread = 0; while (total_read < trial) { - nread = emacs_read (fd, buffer + total_read, trial - total_read); + nread = emacs_read (fd, read_buf + total_read, trial - total_read); if (nread < 0) error ("IO error reading %s: %s", SDATA (orig_filename), emacs_strerror (errno)); @@ -3921,7 +3902,7 @@ by calling `format-decode', which see. */) /* Compare with same_at_start to avoid counting some buffer text as matching both at the file's beginning and at the end. */ while (bufpos > 0 && same_at_end > same_at_start - && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1]) + && FETCH_BYTE (same_at_end - 1) == read_buf[bufpos - 1]) same_at_end--, bufpos--; /* If we found a discrepancy, stop the scan. @@ -4023,30 +4004,25 @@ by calling `format-decode', which see. */) report_file_error ("Setting file position", Fcons (orig_filename, Qnil)); - total = st.st_size; /* Total bytes in the file. */ - how_much = 0; /* Bytes read from file so far. */ inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */ unprocessed = 0; /* Bytes not processed in previous loop. */ GCPRO1 (conversion_buffer); - while (how_much < total) + while (1) { - /* We read one bunch by one (READ_BUF_SIZE bytes) to allow - quitting while reading a huge while. */ - /* `try'' is reserved in some compilers (Microsoft C). */ - int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed); + /* Read at most READ_BUF_SIZE bytes at a time, to allow + quitting while reading a huge file. */ /* Allow quitting out of the actual I/O. */ immediate_quit = 1; QUIT; - this = emacs_read (fd, read_buf + unprocessed, trytry); + this = emacs_read (fd, read_buf + unprocessed, + READ_BUF_SIZE - unprocessed); immediate_quit = 0; if (this <= 0) break; - how_much += this; - BUF_TEMP_SET_PT (XBUFFER (conversion_buffer), BUF_Z (XBUFFER (conversion_buffer))); decode_coding_c_string (&coding, (unsigned char *) read_buf, @@ -4063,9 +4039,6 @@ by calling `format-decode', which see. */) so defer the removal till we reach the `handled' label. */ deferred_remove_unwind_protect = 1; - /* At this point, HOW_MUCH should equal TOTAL, or should be <= 0 - if we couldn't read the file. */ - if (this < 0) error ("IO error reading %s: %s", SDATA (orig_filename), emacs_strerror (errno)); @@ -4240,8 +4213,8 @@ by calling `format-decode', which see. */) /* Maybe make more room. */ if (gap_size < trytry) { - make_gap (total - gap_size); - gap_size = GAP_SIZE; + make_gap (trytry - gap_size); + gap_size = GAP_SIZE - inserted; } /* Read from the file, capturing `quit'. When an @@ -4249,7 +4222,7 @@ by calling `format-decode', which see. */) to be signaled after decoding the text we read. */ nbytes = internal_condition_case_1 (read_non_regular, - format_save_value ("iii", (ptrdiff_t) fd, inserted, trytry), + make_save_value ("iii", (ptrdiff_t) fd, inserted, trytry), Qerror, read_non_regular_quit); if (NILP (nbytes)) @@ -4293,8 +4266,9 @@ by calling `format-decode', which see. */) } } - /* Now we have read all the file data into the gap. - If it was empty, undo marking the buffer modified. */ + /* Now we have either read all the file data into the gap, + or stop reading on I/O error or quit. If nothing was + read, undo marking the buffer modified. */ if (inserted == 0) { @@ -4307,6 +4281,15 @@ by calling `format-decode', which see. */) else Vdeactivate_mark = Qt; + emacs_close (fd); + + /* Discard the unwind protect for closing the file. */ + specpdl_ptr--; + + if (how_much < 0) + error ("IO error reading %s: %s", + SDATA (orig_filename), emacs_strerror (errno)); + /* Make the text read part of the buffer. */ GAP_SIZE -= inserted; GPT += inserted; @@ -4320,15 +4303,6 @@ by calling `format-decode', which see. */) /* Put an anchor to ensure multi-byte form ends at gap. */ *GPT_ADDR = 0; - emacs_close (fd); - - /* Discard the unwind protect for closing the file. */ - specpdl_ptr--; - - if (how_much < 0) - error ("IO error reading %s: %s", - SDATA (orig_filename), emacs_strerror (errno)); - notfound: if (NILP (coding_system)) @@ -4620,11 +4594,9 @@ by calling `format-decode', which see. */) if (read_quit) Fsignal (Qquit, Qnil); - /* ??? Retval needs to be dealt with in all cases consistently. */ + /* Retval needs to be dealt with in all cases consistently. */ if (NILP (val)) - val = Fcons (orig_filename, - Fcons (make_number (inserted), - Qnil)); + val = list2 (orig_filename, make_number (inserted)); RETURN_UNGCPRO (unbind_to (count, val)); } @@ -4640,14 +4612,24 @@ build_annotations_unwind (Lisp_Object arg) /* Decide the coding-system to encode the data with. */ -static Lisp_Object -choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object filename, - Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, - struct coding_system *coding) +DEFUN ("choose-write-coding-system", Fchoose_write_coding_system, + Schoose_write_coding_system, 3, 6, 0, + doc: /* Choose the coding system for writing a file. +Arguments are as for `write-region'. +This function is for internal use only. It may prompt the user. */ ) + (Lisp_Object start, Lisp_Object end, Lisp_Object filename, + Lisp_Object append, Lisp_Object visit, Lisp_Object lockname) { Lisp_Object val; Lisp_Object eol_parent = Qnil; + /* Mimic write-region behavior. */ + if (NILP (start)) + { + XSETFASTINT (start, BEGV); + XSETFASTINT (end, ZV); + } + if (auto_saving && NILP (Fstring_equal (BVAR (current_buffer, filename), BVAR (current_buffer, auto_save_file_name)))) @@ -4740,10 +4722,6 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file } val = coding_inherit_eol_type (val, eol_parent); - setup_coding_system (val, coding); - - if (!STRINGP (start) && !NILP (BVAR (current_buffer, selective_display))) - coding->mode |= CODING_MODE_SELECTIVE_DISPLAY; return val; } @@ -4758,7 +4736,7 @@ If START is a string, then output that string to the file instead of any buffer contents; END is ignored. Optional fourth argument APPEND if non-nil means - append to existing file contents (if any). If it is an integer, + append to existing file contents (if any). If it is a number, seek to that offset in the file before writing. Optional fifth argument VISIT, if t or a string, means set the last-save-file-modtime of buffer to this file's modtime @@ -4787,6 +4765,9 @@ This calls `write-region-annotate-functions' at the start, and (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) { int desc; + int open_flags; + int mode; + off_t offset IF_LINT (= 0); bool ok; int save_errno = 0; const char *fn; @@ -4896,9 +4877,14 @@ This calls `write-region-annotate-functions' at the start, and We used to make this choice before calling build_annotations, but that leads to problems when a write-annotate-function takes care of unsavable chars (as was the case with X-Symbol). */ - Vlast_coding_system_used - = choose_write_coding_system (start, end, filename, - append, visit, lockname, &coding); + Vlast_coding_system_used = + Fchoose_write_coding_system (start, end, filename, + append, visit, lockname); + + setup_coding_system (Vlast_coding_system_used, &coding); + + if (!STRINGP (start) && !NILP (BVAR (current_buffer, selective_display))) + coding.mode |= CODING_MODE_SELECTIVE_DISPLAY; #ifdef CLASH_DETECTION if (!auto_saving) @@ -4906,27 +4892,20 @@ This calls `write-region-annotate-functions' at the start, and #endif /* CLASH_DETECTION */ encoded_filename = ENCODE_FILE (filename); - fn = SSDATA (encoded_filename); - desc = -1; - if (!NILP (append)) + open_flags = O_WRONLY | O_BINARY | O_CREAT; + open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC; + if (NUMBERP (append)) + offset = file_offset (append); + else if (!NILP (append)) + open_flags |= O_APPEND; #ifdef DOS_NT - desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); -#else /* not DOS_NT */ - desc = emacs_open (fn, O_WRONLY, 0); -#endif /* not DOS_NT */ + mode = S_IREAD | S_IWRITE; +#else + mode = auto_saving ? auto_save_mode_bits : 0666; +#endif - if (desc < 0 && (NILP (append) || errno == ENOENT)) -#ifdef DOS_NT - desc = emacs_open (fn, - O_WRONLY | O_CREAT | O_BINARY - | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC), - S_IREAD | S_IWRITE); -#else /* not DOS_NT */ - desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT - | (EQ (mustbenew, Qexcl) ? O_EXCL : 0), - auto_saving ? auto_save_mode_bits : 0666); -#endif /* not DOS_NT */ + desc = emacs_open (fn, open_flags, mode); if (desc < 0) { @@ -4941,14 +4920,9 @@ This calls `write-region-annotate-functions' at the start, and record_unwind_protect (close_file_unwind, make_number (desc)); - if (!NILP (append) && !NILP (Ffile_regular_p (filename))) + if (NUMBERP (append)) { - off_t ret; - - if (NUMBERP (append)) - ret = emacs_lseek (desc, XINT (append), SEEK_CUR); - else - ret = lseek (desc, 0, SEEK_END); + off_t ret = lseek (desc, offset, SEEK_SET); if (ret < 0) { #ifdef CLASH_DETECTION @@ -4990,7 +4964,7 @@ This calls `write-region-annotate-functions' at the start, and immediate_quit = 0; #ifdef HAVE_FSYNC - /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun). + /* fsync appears to change the modtime on BSD4.2. Disk full in NFS may be reported here. */ /* mib says that closing the file will try to write as fast as NFS can do it, and that means the fsync here is not crucial for autosave files. */ @@ -5020,6 +4994,63 @@ This calls `write-region-annotate-functions' at the start, and /* Discard the unwind protect for close_file_unwind. */ specpdl_ptr = specpdl + count1; + /* Some file systems have a bug where st_mtime is not updated + properly after a write. For example, CIFS might not see the + st_mtime change until after the file is opened again. + + Attempt to detect this file system bug, and update MODTIME to the + newer st_mtime if the bug appears to be present. This introduces + a race condition, so to avoid most instances of the race condition + on non-buggy file systems, skip this check if the most recently + encountered non-buggy file system was the current file system. + + A race condition can occur if some other process modifies the + file between the fstat above and the fstat below, but the race is + unlikely and a similar race between the last write and the fstat + above cannot possibly be closed anyway. */ + + if (EMACS_TIME_VALID_P (modtime) + && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system)) + { + int desc1 = emacs_open (fn, O_WRONLY | O_BINARY, 0); + if (0 <= desc1) + { + struct stat st1; + if (fstat (desc1, &st1) == 0 + && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) + { + /* Use the heuristic if it appears to be valid. With neither + O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the + file, the time stamp won't change. Also, some non-POSIX + systems don't update an empty file's time stamp when + truncating it. Finally, file systems with 100 ns or worse + resolution sometimes seem to have bugs: on a system with ns + resolution, checking ns % 100 incorrectly avoids the heuristic + 1% of the time, but the problem should be temporary as we will + try again on the next time stamp. */ + bool use_heuristic + = ((open_flags & (O_EXCL | O_TRUNC)) != 0 + && st.st_size != 0 + && EMACS_NSECS (modtime) % 100 != 0); + + EMACS_TIME modtime1 = get_stat_mtime (&st1); + if (use_heuristic + && EMACS_TIME_EQ (modtime, modtime1) + && st.st_size == st1.st_size) + { + timestamp_file_system = st.st_dev; + valid_timestamp_file_system = 1; + } + else + { + st.st_size = st1.st_size; + modtime = modtime1; + } + } + emacs_close (desc1); + } + } + /* Call write-region-post-annotation-function. */ while (CONSP (Vwrite_region_annotation_buffers)) { @@ -5072,7 +5103,7 @@ This calls `write-region-annotate-functions' at the start, and } if (!auto_saving) - message_with_string ((INTEGERP (append) + message_with_string ((NUMBERP (append) ? "Updated %s" : ! NILP (append) ? "Added to %s" @@ -5382,8 +5413,7 @@ See Info node `(elisp)Modification Time' for more details. */) if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) { /* make_lisp_time won't work here if time_t is unsigned. */ - return list4 (make_number (-1), make_number (65535), - make_number (0), make_number (0)); + return list4i (-1, 65535, 0, 0); } return make_number (0); } @@ -5436,10 +5466,8 @@ static Lisp_Object auto_save_error (Lisp_Object error_val) { Lisp_Object args[3], msg; - int i, nbytes; + int i; struct gcpro gcpro1; - char *msgbuf; - USE_SAFE_ALLOCA; auto_save_error_occurred = 1; @@ -5450,20 +5478,16 @@ auto_save_error (Lisp_Object error_val) args[2] = Ferror_message_string (error_val); msg = Fformat (3, args); GCPRO1 (msg); - nbytes = SBYTES (msg); - msgbuf = SAFE_ALLOCA (nbytes); - memcpy (msgbuf, SDATA (msg), nbytes); for (i = 0; i < 3; ++i) { if (i == 0) - message2 (msgbuf, nbytes, STRING_MULTIBYTE (msg)); + message3 (msg); else - message2_nolog (msgbuf, nbytes, STRING_MULTIBYTE (msg)); + message3_nolog (msg); Fsleep_for (make_number (1), Qnil); } - SAFE_FREE (); UNGCPRO; return Qnil; } @@ -5608,7 +5632,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) } record_unwind_protect (do_auto_save_unwind, - make_save_value (stream, 0)); + make_save_pointer (stream)); record_unwind_protect (do_auto_save_unwind_1, make_number (minibuffer_auto_raise)); minibuffer_auto_raise = 0; @@ -5817,6 +5841,12 @@ Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filena void +init_fileio (void) +{ + valid_timestamp_file_system = 0; +} + +void syms_of_fileio (void) { DEFSYM (Qoperations, "operations"); @@ -5853,6 +5883,7 @@ syms_of_fileio (void) DEFSYM (Qset_file_acl, "set-file-acl"); DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p"); DEFSYM (Qinsert_file_contents, "insert-file-contents"); + DEFSYM (Qchoose_write_coding_system, "choose-write-coding-system"); DEFSYM (Qwrite_region, "write-region"); DEFSYM (Qverify_visited_file_modtime, "verify-visited-file-modtime"); DEFSYM (Qset_visited_file_modtime, "set-visited-file-modtime"); @@ -6077,6 +6108,7 @@ This includes interactive calls to `delete-file' and defsubr (&Sdefault_file_modes); defsubr (&Sfile_newer_than_file_p); defsubr (&Sinsert_file_contents); + defsubr (&Schoose_write_coding_system); defsubr (&Swrite_region); defsubr (&Scar_less_than_car); defsubr (&Sverify_visited_file_modtime); diff --git a/src/filelock.c b/src/filelock.c index f21240f8340..32992896c2b 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -38,11 +38,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <errno.h> +#include <c-ctype.h> + #include "lisp.h" #include "character.h" #include "buffer.h" #include "coding.h" #include "systime.h" +#ifdef WINDOWSNT +#include <share.h> +#include "w32.h" /* for dostounix_filename */ +#endif #ifdef CLASH_DETECTION @@ -60,7 +66,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define WTMP_FILE "/var/log/wtmp" #endif -/* The strategy: to lock a file FN, create a symlink .#FN in FN's +/* Normally use a symbolic link to represent a lock. + The strategy: to lock a file FN, create a symlink .#FN in FN's directory, with link data `user@host.pid'. This avoids a single mount (== failure) point for lock files. @@ -93,7 +100,23 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ has contributed this implementation for Emacs), and was designed by Ethan Jacobson, Kimbo Mundy, and others. - --karl@cs.umb.edu/karl@hq.ileaf.com. */ + --karl@cs.umb.edu/karl@hq.ileaf.com. + + On some file systems, notably those of MS-Windows, symbolic links + do not work well, so instead of a symlink .#FN -> 'user@host.pid', + the lock is a regular file .#FN with contents 'user@host.pid'. To + establish a lock, a nonce file is created and then renamed to .#FN. + On MS-Windows this renaming is atomic unless the lock is forcibly + acquired. On other systems the renaming is atomic if the lock is + forcibly acquired; if not, the renaming is done via hard links, + which is good enough for lock-file purposes. + + To summarize, race conditions can occur with either: + + * Forced locks on MS-Windows systems. + + * Non-forced locks on non-MS-Windows systems that support neither + hard nor symbolic links. */ /* Return the time of the last system boot. */ @@ -274,72 +297,167 @@ get_boot_time_1 (const char *filename, bool newest) } #endif /* BOOT_TIME */ +/* An arbitrary limit on lock contents length. 8 K should be plenty + big enough in practice. */ +enum { MAX_LFINFO = 8 * 1024 }; + /* Here is the structure that stores information about a lock. */ typedef struct { - char *user; - char *host; - pid_t pid; - time_t boot_time; + /* Location of '@', '.', ':' in USER. If there's no colon, COLON + points to the end of USER. */ + char *at, *dot, *colon; + + /* Lock file contents USER@HOST.PID with an optional :BOOT_TIME + appended. This memory is used as a lock file contents buffer, so + it needs room for MAX_LFINFO + 1 bytes. A string " (pid NNNN)" + may be appended to the USER@HOST while generating a diagnostic, + so make room for its extra bytes (as opposed to ".NNNN") too. */ + char user[MAX_LFINFO + 1 + sizeof " (pid )" - sizeof "."]; } lock_info_type; -/* Free the two dynamically-allocated pieces in PTR. */ -#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) +/* Write the name of the lock file for FNAME into LOCKNAME. Length + will be that of FNAME plus two more for the leading ".#", plus one + for the null. */ +#define MAKE_LOCK_NAME(lockname, fname) \ + (lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + 1), \ + fill_in_lock_file_name (lockname, fname)) +static void +fill_in_lock_file_name (char *lockfile, Lisp_Object fn) +{ + char *last_slash = memrchr (SSDATA (fn), '/', SBYTES (fn)); + char *base = last_slash + 1; + ptrdiff_t dirlen = base - SSDATA (fn); + memcpy (lockfile, SSDATA (fn), dirlen); + lockfile[dirlen] = '.'; + lockfile[dirlen + 1] = '#'; + strcpy (lockfile + dirlen + 2, base); +} -/* Write the name of the lock file for FN into LFNAME. Length will be - that of FN plus two more for the leading `.#' plus 1 for the - trailing period plus one for the digit after it plus one for the - null. */ -#define MAKE_LOCK_NAME(lock, file) \ - (lock = alloca (SBYTES (file) + 2 + 1 + 1 + 1), \ - fill_in_lock_file_name (lock, (file))) +/* For some reason Linux kernels return EPERM on file systems that do + not support hard or symbolic links. This symbol documents the quirk. + There is no way to tell whether a symlink call fails due to + permissions issues or because links are not supported, but luckily + the lock file code should work either way. */ +enum { LINKS_MIGHT_NOT_WORK = EPERM }; -static void -fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) +/* Rename OLD to NEW. If FORCE, replace any existing NEW. + It is OK if there are temporarily two hard links to OLD. + Return 0 if successful, -1 (setting errno) otherwise. */ +static int +rename_lock_file (char const *old, char const *new, bool force) { - ptrdiff_t length = SBYTES (fn); - register char *p; - struct stat st; - int count = 0; +#ifdef WINDOWSNT + return sys_rename_replace (old, new, force); +#else + if (! force) + { + struct stat st; - strcpy (lockfile, SSDATA (fn)); + if (link (old, new) == 0) + return unlink (old) == 0 || errno == ENOENT ? 0 : -1; + if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK) + return -1; - /* Shift the nondirectory part of the file name (including the null) - right two characters. Here is one of the places where we'd have to - do something to support 14-character-max file names. */ - for (p = lockfile + length; p != lockfile && *p != '/'; p--) - p[2] = *p; + /* 'link' does not work on this file system. This can occur on + a GNU/Linux host mounting a FAT32 file system. Fall back on + 'rename' after checking that NEW does not exist. There is a + potential race condition since some other process may create + NEW immediately after the existence check, but it's the best + we can portably do here. */ + if (lstat (new, &st) == 0 || errno == EOVERFLOW) + { + errno = EEXIST; + return -1; + } + if (errno != ENOENT) + return -1; + } - /* Insert the `.#'. */ - p[1] = '.'; - p[2] = '#'; + return rename (old, new); +#endif +} - p = p + length + 2; +/* Create the lock file FILE with contents CONTENTS. Return 0 if + successful, an errno value on failure. If FORCE, remove any + existing FILE if necessary. */ - while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode)) +static int +create_lock_file (char *lfname, char *lock_info_str, bool force) +{ +#ifdef WINDOWSNT + /* Symlinks are supported only by later versions of Windows, and + creating them is a privileged operation that often triggers + User Account Control elevation prompts. Avoid the problem by + pretending that 'symlink' does not work. */ + int err = ENOSYS; +#else + int err = symlink (lock_info_str, lfname) == 0 ? 0 : errno; +#endif + + if (err == EEXIST && force) + { + unlink (lfname); + err = symlink (lock_info_str, lfname) == 0 ? 0 : errno; + } + + if (err == ENOSYS || err == LINKS_MIGHT_NOT_WORK || err == ENAMETOOLONG) { - if (count > 9) + static char const nonce_base[] = ".#-emacsXXXXXX"; + char *last_slash = strrchr (lfname, '/'); + ptrdiff_t lfdirlen = last_slash + 1 - lfname; + USE_SAFE_ALLOCA; + char *nonce = SAFE_ALLOCA (lfdirlen + sizeof nonce_base); + int fd; + bool need_fchmod; + mode_t world_readable = S_IRUSR | S_IRGRP | S_IROTH; + memcpy (nonce, lfname, lfdirlen); + strcpy (nonce + lfdirlen, nonce_base); + +#if HAVE_MKSTEMP + /* Prefer mkstemp if available, as it avoids a race between + mktemp and emacs_open. */ + fd = mkstemp (nonce); + need_fchmod = 1; +#else + mktemp (nonce); + fd = emacs_open (nonce, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, + world_readable); + need_fchmod = 0; +#endif + + if (fd < 0) + err = errno; + else { - *p = '\0'; - return; + ptrdiff_t lock_info_len = strlen (lock_info_str); + err = 0; + if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len + || (need_fchmod && fchmod (fd, world_readable) != 0)) + err = errno; + if (emacs_close (fd) != 0) + err = errno; + if (!err && rename_lock_file (nonce, lfname, force) != 0) + err = errno; + if (err) + unlink (nonce); } - sprintf (p, ".%d", count++); + + SAFE_FREE (); } + + return err; } /* Lock the lock file named LFNAME. If FORCE, do so even if it is already locked. - Return true if successful. */ + Return 0 if successful, an error number on failure. */ -static bool +static int lock_file_1 (char *lfname, bool force) { - int err; - int symlink_errno; - USE_SAFE_ALLOCA; - /* Call this first because it can GC. */ printmax_t boot = get_boot_time (); @@ -347,26 +465,16 @@ lock_file_1 (char *lfname, bool force) char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : ""; Lisp_Object lhost_name = Fsystem_name (); char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : ""; - ptrdiff_t lock_info_size = (strlen (user_name) + strlen (host_name) - + 2 * INT_STRLEN_BOUND (printmax_t) - + sizeof "@.:"); - char *lock_info_str = SAFE_ALLOCA (lock_info_size); + char lock_info_str[MAX_LFINFO + 1]; printmax_t pid = getpid (); - esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, - user_name, host_name, pid, boot); - - err = symlink (lock_info_str, lfname); - if (errno == EEXIST && force) - { - unlink (lfname); - err = symlink (lock_info_str, lfname); - } + if (sizeof lock_info_str + <= snprintf (lock_info_str, sizeof lock_info_str, + boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, + user_name, host_name, pid, boot)) + return ENAMETOOLONG; - symlink_errno = errno; - SAFE_FREE (); - errno = symlink_errno; - return err == 0; + return create_lock_file (lfname, lock_info_str, force); } /* Return true if times A and B are no more than one second apart. */ @@ -377,6 +485,46 @@ within_one_second (time_t a, time_t b) return (a - b >= -1 && a - b <= 1); } +/* On systems lacking ELOOP, test for an errno value that shouldn't occur. */ +#ifndef ELOOP +# define ELOOP (-1) +#endif + +/* Read the data for the lock file LFNAME into LFINFO. Read at most + MAX_LFINFO + 1 bytes. Return the number of bytes read, or -1 + (setting errno) on error. */ + +static ptrdiff_t +read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1]) +{ + ptrdiff_t nbytes; + + while ((nbytes = readlinkat (AT_FDCWD, lfname, lfinfo, MAX_LFINFO + 1)) < 0 + && errno == EINVAL) + { + int fd = emacs_open (lfname, O_RDONLY | O_BINARY | O_NOFOLLOW, 0); + if (0 <= fd) + { + ptrdiff_t read_bytes = emacs_read (fd, lfinfo, MAX_LFINFO + 1); + int read_errno = errno; + if (emacs_close (fd) != 0) + return -1; + errno = read_errno; + return read_bytes; + } + + if (errno != ELOOP) + return -1; + + /* readlinkat saw a non-symlink, but emacs_open saw a symlink. + The former must have been removed and replaced by the latter. + Try again. */ + QUIT; + } + + return nbytes; +} + /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, 1 if another process owns it (and set OWNER (if non-null) to info), 2 if the current process owns it, @@ -386,85 +534,78 @@ static int current_lock_owner (lock_info_type *owner, char *lfname) { int ret; - ptrdiff_t len; lock_info_type local_owner; - intmax_t n; - char *at, *dot, *colon; - char readlink_buf[READLINK_BUFSIZE]; - char *lfinfo = emacs_readlink (lfname, readlink_buf); - - /* If nonexistent lock file, all is well; otherwise, got strange error. */ - if (!lfinfo) - return errno == ENOENT ? 0 : -1; + ptrdiff_t lfinfolen; + intmax_t pid, boot_time; + char *at, *dot, *lfinfo_end; /* Even if the caller doesn't want the owner info, we still have to read it to determine return value. */ if (!owner) owner = &local_owner; + /* If nonexistent lock file, all is well; otherwise, got strange error. */ + lfinfolen = read_lock_data (lfname, owner->user); + if (lfinfolen < 0) + return errno == ENOENT ? 0 : -1; + if (MAX_LFINFO < lfinfolen) + return -1; + owner->user[lfinfolen] = 0; + /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */ /* The USER is everything before the last @. */ - at = strrchr (lfinfo, '@'); - dot = strrchr (lfinfo, '.'); - if (!at || !dot) - { - if (lfinfo != readlink_buf) - xfree (lfinfo); - return -1; - } - len = at - lfinfo; - owner->user = xmalloc (len + 1); - memcpy (owner->user, lfinfo, len); - owner->user[len] = 0; + owner->at = at = memrchr (owner->user, '@', lfinfolen); + if (!at) + return -1; + owner->dot = dot = strrchr (at, '.'); + if (!dot) + return -1; /* The PID is everything from the last `.' to the `:'. */ + if (! c_isdigit (dot[1])) + return -1; errno = 0; - n = strtoimax (dot + 1, NULL, 10); - owner->pid = - ((0 <= n && n <= TYPE_MAXIMUM (pid_t) - && (TYPE_MAXIMUM (pid_t) < INTMAX_MAX || errno != ERANGE)) - ? n : 0); + pid = strtoimax (dot + 1, &owner->colon, 10); + if (errno == ERANGE) + pid = -1; - colon = strchr (dot + 1, ':'); /* After the `:', if there is one, comes the boot time. */ - n = 0; - if (colon) + switch (owner->colon[0]) { - errno = 0; - n = strtoimax (colon + 1, NULL, 10); - } - owner->boot_time = - ((0 <= n && n <= TYPE_MAXIMUM (time_t) - && (TYPE_MAXIMUM (time_t) < INTMAX_MAX || errno != ERANGE)) - ? n : 0); + case 0: + boot_time = 0; + lfinfo_end = owner->colon; + break; - /* The host is everything in between. */ - len = dot - at - 1; - owner->host = xmalloc (len + 1); - memcpy (owner->host, at + 1, len); - owner->host[len] = 0; + case ':': + if (! c_isdigit (owner->colon[1])) + return -1; + boot_time = strtoimax (owner->colon + 1, &lfinfo_end, 10); + break; - /* We're done looking at the link info. */ - if (lfinfo != readlink_buf) - xfree (lfinfo); + default: + return -1; + } + if (lfinfo_end != owner->user + lfinfolen) + return -1; /* On current host? */ - if (STRINGP (Fsystem_name ()) - && strcmp (owner->host, SSDATA (Fsystem_name ())) == 0) + if (STRINGP (Vsystem_name) + && dot - (at + 1) == SBYTES (Vsystem_name) + && memcmp (at + 1, SSDATA (Vsystem_name), SBYTES (Vsystem_name)) == 0) { - if (owner->pid == getpid ()) + if (pid == getpid ()) ret = 2; /* We own it. */ - else if (owner->pid > 0 - && (kill (owner->pid, 0) >= 0 || errno == EPERM) - && (owner->boot_time == 0 - || within_one_second (owner->boot_time, get_boot_time ()))) + else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t) + && (kill (pid, 0) >= 0 || errno == EPERM) + && (boot_time == 0 + || (boot_time <= TYPE_MAXIMUM (time_t) + && within_one_second (boot_time, get_boot_time ())))) ret = 1; /* An existing process on this machine owns it. */ - /* The owner process is dead or has a strange pid (<=0), so try to + /* The owner process is dead or has a strange pid, so try to zap the lockfile. */ - else if (unlink (lfname) < 0) - ret = -1; else - ret = 0; + return unlink (lfname); } else { /* If we wanted to support the check for stale locks on remote machines, @@ -472,11 +613,6 @@ current_lock_owner (lock_info_type *owner, char *lfname) ret = 1; } - /* Avoid garbage. */ - if (owner == &local_owner || ret <= 0) - { - FREE_LOCK_INFO (*owner); - } return ret; } @@ -488,29 +624,25 @@ current_lock_owner (lock_info_type *owner, char *lfname) Return -1 if cannot lock for any other reason. */ static int -lock_if_free (lock_info_type *clasher, register char *lfname) +lock_if_free (lock_info_type *clasher, char *lfname) { - while (! lock_file_1 (lfname, 0)) + int err; + while ((err = lock_file_1 (lfname, 0)) == EEXIST) { - int locker; - - if (errno != EEXIST) - return -1; - - locker = current_lock_owner (clasher, lfname); - if (locker == 2) - { - FREE_LOCK_INFO (*clasher); - return 0; /* We ourselves locked it. */ - } - else if (locker == 1) - return 1; /* Someone else has it. */ - else if (locker == -1) - return -1; /* current_lock_owner returned strange error. */ + switch (current_lock_owner (clasher, lfname)) + { + case 2: + return 0; /* We ourselves locked it. */ + case 1: + return 1; /* Someone else has it. */ + case -1: + return -1; /* current_lock_owner returned strange error. */ + } /* We deleted a stale lock; try again to lock the file. */ } - return 0; + + return err ? -1 : 0; } /* lock_file locks file FN, @@ -522,6 +654,7 @@ lock_if_free (lock_info_type *clasher, register char *lfname) decided to go ahead without locking. When this returns, either the lock is locked for us, + or lock creation failed, or the user has said to go ahead without locking. If the file is locked by someone else, this calls @@ -533,11 +666,9 @@ lock_if_free (lock_info_type *clasher, register char *lfname) void lock_file (Lisp_Object fn) { - register Lisp_Object attack, orig_fn, encoded_fn; - register char *lfname, *locker; - ptrdiff_t locker_size; + Lisp_Object orig_fn, encoded_fn; + char *lfname; lock_info_type lock_info; - printmax_t pid; struct gcpro gcpro1; USE_SAFE_ALLOCA; @@ -554,6 +685,12 @@ lock_file (Lisp_Object fn) orig_fn = fn; GCPRO1 (fn); fn = Fexpand_file_name (fn, Qnil); +#ifdef WINDOWSNT + /* Ensure we have only '/' separators, to avoid problems with + looking (inside fill_in_lock_file_name) for backslashes in file + names encoded by some DBCS codepage. */ + dostounix_filename (SSDATA (fn), 1); +#endif encoded_fn = ENCODE_FILE (fn); /* Create the name of the lock-file for file fn */ @@ -572,38 +709,35 @@ lock_file (Lisp_Object fn) call1 (intern ("ask-user-about-supersession-threat"), fn); } - UNGCPRO; - /* Try to lock the lock. */ - if (lock_if_free (&lock_info, lfname) <= 0) - /* Return now if we have locked it, or if lock creation failed */ - return; - - /* Else consider breaking the lock */ - locker_size = (strlen (lock_info.user) + strlen (lock_info.host) - + INT_STRLEN_BOUND (printmax_t) - + sizeof "@ (pid )"); - locker = SAFE_ALLOCA (locker_size); - pid = lock_info.pid; - esprintf (locker, "%s@%s (pid %"pMd")", - lock_info.user, lock_info.host, pid); - FREE_LOCK_INFO (lock_info); - - attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker)); - SAFE_FREE (); - if (!NILP (attack)) - /* User says take the lock */ + /* Try to lock the lock. */ + if (0 < lock_if_free (&lock_info, lfname)) { - lock_file_1 (lfname, 1); - return; + /* Someone else has the lock. Consider breaking it. */ + Lisp_Object attack; + char *dot = lock_info.dot; + ptrdiff_t pidlen = lock_info.colon - (dot + 1); + static char const replacement[] = " (pid "; + int replacementlen = sizeof replacement - 1; + memmove (dot + replacementlen, dot + 1, pidlen); + strcpy (dot + replacementlen + pidlen, ")"); + memcpy (dot, replacement, replacementlen); + attack = call2 (intern ("ask-user-about-lock"), fn, + build_string (lock_info.user)); + /* Take the lock if the user said so. */ + if (!NILP (attack)) + lock_file_1 (lfname, 1); } - /* User says ignore the lock */ + + UNGCPRO; + SAFE_FREE (); } void -unlock_file (register Lisp_Object fn) +unlock_file (Lisp_Object fn) { - register char *lfname; + char *lfname; + USE_SAFE_ALLOCA; fn = Fexpand_file_name (fn, Qnil); fn = ENCODE_FILE (fn); @@ -612,6 +746,8 @@ unlock_file (register Lisp_Object fn) if (current_lock_owner (0, lfname) == 2) unlink (lfname); + + SAFE_FREE (); } void @@ -677,9 +813,10 @@ t if it is locked by you, else a string saying which user has locked it. */) (Lisp_Object filename) { Lisp_Object ret; - register char *lfname; + char *lfname; int owner; lock_info_type locker; + USE_SAFE_ALLOCA; filename = Fexpand_file_name (filename, Qnil); @@ -691,11 +828,9 @@ t if it is locked by you, else a string saying which user has locked it. */) else if (owner == 2) ret = Qt; else - ret = build_string (locker.user); - - if (owner > 0) - FREE_LOCK_INFO (locker); + ret = make_string (locker.user, locker.at - locker.user); + SAFE_FREE (); return ret; } diff --git a/src/fns.c b/src/fns.c index 687c3f6ff39..b3a1dc2317a 100644 --- a/src/fns.c +++ b/src/fns.c @@ -66,7 +66,10 @@ and `most-positive-fixnum', inclusive, are equally likely. With positive integer LIMIT, return random number in interval [0,LIMIT). With argument t, set the random number seed from the current time and pid. -Other values of LIMIT are ignored. */) +With a string argument, set the seed based on the string's contents. +Other values of LIMIT are ignored. + +See Info node `(elisp)Random Numbers' for more details. */) (Lisp_Object limit) { EMACS_INT val; @@ -2482,7 +2485,7 @@ is nil, and `use-dialog-box' is non-nil. */) Fding (Qnil); Fdiscard_input (); - message ("Please answer yes or no."); + message1 ("Please answer yes or no."); Fsleep_for (make_number (2), Qnil); } } @@ -2742,7 +2745,7 @@ ARGS are passed as extra arguments to the function. usage: (widget-apply WIDGET PROPERTY &rest ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - /* This function can GC. */ + /* This function can GC. */ Lisp_Object newargs[3]; struct gcpro gcpro1, gcpro2; Lisp_Object result; @@ -2804,9 +2807,8 @@ The data read from the system are decoded using `locale-coding-system'. */) val = build_unibyte_string (str); /* Fixme: Is this coding system necessarily right, even if it is consistent with CODESET? If not, what to do? */ - Faset (v, make_number (i), - code_convert_string_norecord (val, Vlocale_coding_system, - 0)); + ASET (v, i, code_convert_string_norecord (val, Vlocale_coding_system, + 0)); } UNGCPRO; return v; @@ -2826,8 +2828,8 @@ The data read from the system are decoded using `locale-coding-system'. */) { str = nl_langinfo (months[i]); val = build_unibyte_string (str); - Faset (v, make_number (i), - code_convert_string_norecord (val, Vlocale_coding_system, 0)); + ASET (v, i, code_convert_string_norecord (val, Vlocale_coding_system, + 0)); } UNGCPRO; return v; @@ -2837,10 +2839,7 @@ The data read from the system are decoded using `locale-coding-system'. */) but is in the locale files. This could be used by ps-print. */ #ifdef PAPER_WIDTH else if (EQ (item, Qpaper)) - { - return list2 (make_number (nl_langinfo (PAPER_WIDTH)), - make_number (nl_langinfo (PAPER_HEIGHT))); - } + return list2i (nl_langinfo (PAPER_WIDTH), nl_langinfo (PAPER_HEIGHT)); #endif /* PAPER_WIDTH */ #endif /* HAVE_LANGINFO_CODESET*/ return Qnil; @@ -4043,10 +4042,6 @@ sweep_weak_hash_tables (void) #define SXHASH_MAX_LEN 7 -/* Hash X, returning a value that fits into a Lisp integer. */ -#define SXHASH_REDUCE(X) \ - ((((X) ^ (X) >> (BITS_PER_EMACS_INT - FIXNUM_BITS))) & INTMASK) - /* Return a hash for string PTR which has length LEN. The hash value can be any EMACS_UINT value. */ @@ -4079,7 +4074,7 @@ sxhash_string (char const *ptr, ptrdiff_t len) /* Return a hash for the floating point value VAL. */ -static EMACS_INT +static EMACS_UINT sxhash_float (double val) { EMACS_UINT hash = 0; diff --git a/src/font.c b/src/font.c index 89931f6ec76..db7bf352c94 100644 --- a/src/font.c +++ b/src/font.c @@ -717,7 +717,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val) } -/* Font name parser and unparser */ +/* Font name parser and unparser. */ static int parse_matrix (const char *); static int font_expand_wildcards (Lisp_Object *, int); @@ -1746,7 +1746,7 @@ font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Objec /* This part (through the next ^L) is still experimental and not tested much. We may drastically change codes. */ -/* OTF handler */ +/* OTF handler. */ #if 0 @@ -1861,7 +1861,7 @@ otf_open (Lisp_Object file) else { otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL; - val = make_save_value (otf, 0); + val = make_save_pointer (otf); otf_list = Fcons (Fcons (file, val), otf_list); } return otf; @@ -2035,7 +2035,7 @@ font_otf_Anchor (OTF_Anchor *anchor) #endif /* 0 */ -/* Font sorting */ +/* Font sorting. */ static unsigned font_score (Lisp_Object, Lisp_Object *); static int font_compare (const void *, const void *); @@ -2565,7 +2565,6 @@ font_get_cache (FRAME_PTR f, struct font_driver *driver) return val; } -static int num_fonts; static void font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver) @@ -2598,7 +2597,6 @@ font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver) { eassert (font && driver == font->driver); driver->close (f, font); - num_fonts--; } } if (driver->free_entity) @@ -2856,7 +2854,6 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size) return Qnil; ASET (entity, FONT_OBJLIST_INDEX, Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX))); - num_fonts++; font = XFONT_OBJECT (font_object); min_width = (font->min_width ? font->min_width @@ -2901,7 +2898,6 @@ font_close_object (FRAME_PTR f, Lisp_Object font_object) eassert (FRAME_X_DISPLAY_INFO (f)->n_fonts); FRAME_X_DISPLAY_INFO (f)->n_fonts--; #endif - num_fonts--; } @@ -3578,7 +3574,7 @@ font_filter_properties (Lisp_Object font, Lisp_Object it; int i; - /* Set boolean values to Qt or Qnil */ + /* Set boolean values to Qt or Qnil. */ for (i = 0; boolean_properties[i] != NULL; ++i) for (it = alist; ! NILP (it); it = XCDR (it)) { @@ -3693,11 +3689,11 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w, #ifdef HAVE_WINDOW_SYSTEM -/* Check how many characters after POS (at most to *LIMIT) can be - displayed by the same font in the window W. FACE, if non-NULL, is - the face selected for the character at POS. If STRING is not nil, - it is the string to check instead of the current buffer. In that - case, FACE must be not NULL. +/* Check how many characters after character/byte position POS/POS_BYTE + (at most to *LIMIT) can be displayed by the same font in the window W. + FACE, if non-NULL, is the face selected for the character at POS. + If STRING is not nil, it is the string to check instead of the current + buffer. In that case, FACE must be not NULL. The return value is the font-object for the character at POS. *LIMIT is set to the position where that font can't be used. @@ -3705,15 +3701,15 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w, It is assured that the current buffer (or STRING) is multibyte. */ Lisp_Object -font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face, Lisp_Object string) +font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit, + struct window *w, struct face *face, Lisp_Object string) { - ptrdiff_t pos_byte, ignore; + ptrdiff_t ignore; int c; Lisp_Object font_object = Qnil; if (NILP (string)) { - pos_byte = CHAR_TO_BYTE (pos); if (! face) { int face_id; @@ -3724,10 +3720,7 @@ font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face } } else - { - eassert (face); - pos_byte = string_char_to_byte (string, pos); - } + eassert (face); while (pos < *limit) { @@ -3757,7 +3750,7 @@ font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face #endif -/* Lisp API */ +/* Lisp API. */ DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0, doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object. @@ -4607,7 +4600,7 @@ If the font is not OpenType font, CAPABILITY is nil. */) CHECK_FONT_GET_OBJECT (font_object, font); - val = Fmake_vector (make_number (9), Qnil); + val = make_uninit_vector (9); ASET (val, 0, AREF (font_object, FONT_NAME_INDEX)); ASET (val, 1, AREF (font_object, FONT_FILE_INDEX)); ASET (val, 2, make_number (font->pixel_size)); @@ -4618,6 +4611,8 @@ If the font is not OpenType font, CAPABILITY is nil. */) ASET (val, 7, make_number (font->average_width)); if (font->driver->otf_capability) ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font))); + else + ASET (val, 8, Qnil); return val; } @@ -4710,7 +4705,7 @@ the corresponding element is nil. */) chars = aref_addr (object, XFASTINT (from)); } - vec = Fmake_vector (make_number (len), Qnil); + vec = make_uninit_vector (len); for (i = 0; i < len; i++) { Lisp_Object g; @@ -4720,8 +4715,11 @@ the corresponding element is nil. */) code = font->driver->encode_char (font, c); if (code == FONT_INVALID_CODE) - continue; - g = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); + { + ASET (vec, i, Qnil); + continue; + } + g = LGLYPH_NEW (); LGLYPH_SET_FROM (g, i); LGLYPH_SET_TO (g, i); LGLYPH_SET_CHAR (g, c); @@ -4833,7 +4831,7 @@ where OPENED-NAME is the name used for opening the font, FULL-NAME is the full name of the font, SIZE is the pixelsize of the font, - HEIGHT is the pixel-height of the font (i.e ascent + descent), + HEIGHT is the pixel-height of the font (i.e., ascent + descent), BASELINE-OFFSET is the upward offset pixels from ASCII baseline, RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling how to compose characters. @@ -4874,7 +4872,7 @@ If the named font is not yet loaded, return nil. */) return Qnil; font = XFONT_OBJECT (font_object); - info = Fmake_vector (make_number (7), Qnil); + info = make_uninit_vector (7); ASET (info, 0, AREF (font_object, FONT_NAME_INDEX)); ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX)); ASET (info, 2, make_number (font->pixel_size)); @@ -4903,7 +4901,7 @@ build_style_table (const struct table_entry *entry, int nelement) int i, j; Lisp_Object table, elt; - table = Fmake_vector (make_number (nelement), Qnil); + table = make_uninit_vector (nelement); for (i = 0; i < nelement; i++) { for (j = 0; entry[i].names[j]; j++); @@ -5167,7 +5165,7 @@ See `font-weight-table' for the format of the vector. */); XSYMBOL (intern_c_string ("font-width-table"))->constant = 1; staticpro (&font_style_table); - font_style_table = Fmake_vector (make_number (3), Qnil); + font_style_table = make_uninit_vector (3); ASET (font_style_table, 0, Vfont_weight_table); ASET (font_style_table, 1, Vfont_slant_table); ASET (font_style_table, 2, Vfont_width_table); diff --git a/src/font.h b/src/font.h index b565fb4b01b..ffed0461ff7 100644 --- a/src/font.h +++ b/src/font.h @@ -781,7 +781,7 @@ extern int font_unparse_fcname (Lisp_Object font, int pixel_size, extern void register_font_driver (struct font_driver *driver, FRAME_PTR f); extern void free_font_driver_list (FRAME_PTR f); extern Lisp_Object font_update_drivers (FRAME_PTR f, Lisp_Object list); -extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t *, +extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *, struct window *, struct face *, Lisp_Object); extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object); diff --git a/src/fontset.c b/src/fontset.c index b7f3e46d69c..3578bc9403d 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -271,7 +271,8 @@ set_fontset_fallback (Lisp_Object fontset, Lisp_Object fallback) /* Macros for FONT-DEF and RFONT-DEF of fontset. */ #define FONT_DEF_NEW(font_def, font_spec, encoding, repertory) \ do { \ - (font_def) = Fmake_vector (make_number (3), (font_spec)); \ + (font_def) = make_uninit_vector (3); \ + ASET ((font_def), 0, font_spec); \ ASET ((font_def), 1, encoding); \ ASET ((font_def), 2, repertory); \ } while (0) @@ -1591,7 +1592,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */) { Lisp_Object arg; - arg = Fmake_vector (make_number (5), Qnil); + arg = make_uninit_vector (5); ASET (arg, 0, fontset); ASET (arg, 1, font_def); ASET (arg, 2, add); diff --git a/src/frame.c b/src/frame.c index 514b338df5b..0fa821682f3 100644 --- a/src/frame.c +++ b/src/frame.c @@ -500,8 +500,7 @@ make_initial_frame (void) tty_frame_count = 1; fset_name (f, build_pure_c_string ("F1")); - f->visible = 1; - f->async_visible = 1; + SET_FRAME_VISIBLE (f, 1); f->output_method = terminal->type; f->terminal = terminal; @@ -540,8 +539,8 @@ make_terminal_frame (struct terminal *terminal) fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count)); - f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */ - f->async_visible = 1; /* Don't let visible be cleared later. */ + SET_FRAME_VISIBLE (f, 1); + f->terminal = terminal; f->terminal->reference_count++; #ifdef MSDOS @@ -565,7 +564,7 @@ make_terminal_frame (struct terminal *terminal) /* Set the top frame to the newly created frame. */ if (FRAMEP (FRAME_TTY (f)->top_frame) && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame))) - XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */ + SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */ FRAME_TTY (f)->top_frame = frame; @@ -806,8 +805,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor { if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame)) /* Mark previously displayed frame as now obscured. */ - XFRAME (FRAME_TTY (XFRAME (frame))->top_frame)->async_visible = 2; - XFRAME (frame)->async_visible = 1; + SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (XFRAME (frame))->top_frame), 2); + SET_FRAME_VISIBLE (XFRAME (frame), 1); FRAME_TTY (XFRAME (frame))->top_frame = frame; } @@ -914,7 +913,6 @@ candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf) } else if (EQ (minibuf, Qvisible)) { - FRAME_SAMPLE_VISIBILITY (c); if (FRAME_VISIBLE_P (c)) return candidate; } @@ -928,7 +926,6 @@ candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf) } else if (XFASTINT (minibuf) == 0) { - FRAME_SAMPLE_VISIBILITY (c); if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c)) return candidate; } @@ -1052,10 +1049,7 @@ other_visible_frames (FRAME_PTR f) and note any recent change in visibility. */ #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (this))) - { - x_sync (XFRAME (this)); - FRAME_SAMPLE_VISIBILITY (XFRAME (this)); - } + x_sync (XFRAME (this)); #endif if (FRAME_VISIBLE_P (XFRAME (this)) @@ -1231,7 +1225,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) fset_root_window (f, Qnil); Vframe_list = Fdelq (frame, Vframe_list); - FRAME_SET_VISIBLE (f, 0); + SET_FRAME_VISIBLE (f, 0); /* Allow the vector of menu bar contents to be freed in the next garbage collection. The frame object itself may not be garbage @@ -1251,7 +1245,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force) xfree (FRAME_DELETEN_COST (f)); xfree (FRAME_INSERTN_COST (f)); xfree (FRAME_DELETE_COST (f)); - xfree (FRAME_MESSAGE_BUF (f)); /* Since some events are handled at the interrupt level, we may get an event for f at any time; if we zero out the frame's terminal @@ -1266,10 +1259,10 @@ delete_frame (Lisp_Object frame, Lisp_Object force) { struct terminal *terminal = FRAME_TERMINAL (f); f->output_data.nothing = 0; - f->terminal = 0; /* Now the frame is dead. */ + f->terminal = 0; /* Now the frame is dead. */ /* If needed, delete the terminal that this frame was on. - (This must be done after the frame is killed.) */ + (This must be done after the frame is killed.) */ terminal->reference_count--; #ifdef USE_GTK /* FIXME: Deleting the terminal crashes emacs because of a GTK @@ -1580,10 +1573,7 @@ If omitted, FRAME defaults to the currently selected frame. */) /* I think this should be done with a hook. */ #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f)) - { - FRAME_SAMPLE_VISIBILITY (f); - x_make_frame_visible (f); - } + x_make_frame_visible (f); #endif make_frame_visible_1 (f->root_window); @@ -1706,8 +1696,6 @@ currently being displayed on the terminal. */) { CHECK_LIVE_FRAME (frame); - FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); - if (FRAME_VISIBLE_P (XFRAME (frame))) return Qt; if (FRAME_ICONIFIED_P (XFRAME (frame))) @@ -2892,7 +2880,6 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) make_formatted_string (buf, "%"pMu, w)); #endif store_in_alist (alistptr, Qicon_name, f->icon_name); - FRAME_SAMPLE_VISIBILITY (f); store_in_alist (alistptr, Qvisibility, (FRAME_VISIBLE_P (f) ? Qt : FRAME_ICONIFIED_P (f) ? Qicon : Qnil)); @@ -4246,6 +4233,16 @@ Setting this variable does not affect existing frames, only new ones. */); Vdefault_frame_scroll_bars = Qnil; #endif + DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion", + scroll_bar_adjust_thumb_portion_p, + doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF. +Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards +even if the end of the buffer is shown (i.e. overscrolling). +Set to nil if you want the thumb to be at the bottom when the end of the buffer +is shown. Also, the thumb fills the whole scroll bar when the entire buffer +is visible. In this case you can not overscroll. */); + scroll_bar_adjust_thumb_portion_p = 1; + DEFVAR_LISP ("terminal-frame", Vterminal_frame, doc: /* The initial frame-object, which represents Emacs's stdout. */); diff --git a/src/frame.h b/src/frame.h index ec535d4448f..c18b7662079 100644 --- a/src/frame.h +++ b/src/frame.h @@ -18,7 +18,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* Don't multiply include: dispextern.h includes macterm.h which includes frame.h some emacs source includes both dispextern.h and - frame.h */ + frame.h. */ #ifndef EMACS_FRAME_H #define EMACS_FRAME_H @@ -33,7 +33,7 @@ INLINE_HEADER_BEGIN /* Miscellanea. */ -/* Nonzero means there is at least one garbaged frame. */ +/* Nonzero means there is at least one garbaged frame. */ extern bool frame_garbaged; @@ -200,7 +200,7 @@ struct frame string's pointer (`name', above) because it might get relocated. */ char *namebuf; - /* Glyph pool and matrix. */ + /* Glyph pool and matrix. */ struct glyph_pool *current_pool; struct glyph_pool *desired_pool; struct glyph_matrix *desired_matrix; @@ -353,46 +353,30 @@ struct frame unsigned int external_menu_bar : 1; #endif - /* visible is nonzero if the frame is currently displayed; we check + /* Next two bitfields are mutually exclusive. They might both be + zero if the frame has been made invisible without an icon. */ + + /* Nonzero if the frame is currently displayed; we check it to see if we should bother updating the frame's contents. - DON'T SET IT DIRECTLY; instead, use FRAME_SET_VISIBLE. Note that, since invisible frames aren't updated, whenever a - frame becomes visible again, it must be marked as garbaged. The - FRAME_SAMPLE_VISIBILITY macro takes care of this. + frame becomes visible again, it must be marked as garbaged. On ttys and on Windows NT/9X, to avoid wasting effort updating visible frames that are actually completely obscured by other windows on the display, we bend the meaning of visible slightly: - if greater than 1, then the frame is obscured - we still consider + if equal to 2, then the frame is obscured - we still consider it to be "visible" as seen from lisp, but we don't bother updating it. We must take care to garbage the frame when it - ceases to be obscured though. - - iconified is nonzero if the frame is currently iconified. - - Asynchronous input handlers should NOT change these directly; - instead, they should change async_visible or async_iconified, and - let the FRAME_SAMPLE_VISIBILITY macro set visible and iconified - at the next redisplay. - - These should probably be considered read-only by everyone except - FRAME_SAMPLE_VISIBILITY. - - These two are mutually exclusive. They might both be zero, if the - frame has been made invisible without an icon. */ + ceases to be obscured though. See SET_FRAME_VISIBLE below. */ unsigned visible : 2; - unsigned iconified : 1; - /* Let's not use bitfields for volatile variables. */ - - /* Asynchronous input handlers change these, and - FRAME_SAMPLE_VISIBILITY copies them into visible and iconified. - See FRAME_SAMPLE_VISIBILITY, below. */ - volatile char async_visible, async_iconified; + /* Nonzero if the frame is currently iconified. Do not + set this directly, use SET_FRAME_ICONIFIED instead. */ + unsigned iconified : 1; /* Nonzero if this frame should be redrawn. */ - volatile char garbaged; + unsigned garbaged : 1; /* True if frame actually has a minibuffer window on it. 0 if using a minibuffer window that isn't on this frame. */ @@ -444,9 +428,6 @@ struct frame /* Width of bar cursor (if we are using that) for blink-off state. */ int blink_off_cursor_width; - /* Storage for messages to this frame. */ - char *message_buf; - /* Nonnegative if current redisplay should not do scroll computation for lines beyond a certain vpos. This is the vpos. */ int scroll_bottom_vpos; @@ -714,7 +695,7 @@ typedef struct frame *FRAME_PTR; #else #define FRAME_EXTERNAL_MENU_BAR(f) 0 #endif -#define FRAME_VISIBLE_P(f) ((f)->visible != 0) +#define FRAME_VISIBLE_P(f) (f)->visible /* Nonzero if frame F is currently visible but hidden. */ #define FRAME_OBSCURED_P(f) ((f)->visible > 1) @@ -722,9 +703,10 @@ typedef struct frame *FRAME_PTR; /* Nonzero if frame F is currently iconified. */ #define FRAME_ICONIFIED_P(f) (f)->iconified -#define FRAME_SET_VISIBLE(f,p) \ - ((f)->async_visible = (p), FRAME_SAMPLE_VISIBILITY (f)) +/* Mark frame F as currently garbaged. */ #define SET_FRAME_GARBAGED(f) (frame_garbaged = 1, f->garbaged = 1) + +/* Nonzero if frame F is currently garbaged. */ #define FRAME_GARBAGED_P(f) (f)->garbaged /* Nonzero means do not allow splitting this frame's window. */ @@ -751,7 +733,6 @@ typedef struct frame *FRAME_PTR; #define FRAME_DELETE_COST(f) (f)->delete_line_cost #define FRAME_INSERTN_COST(f) (f)->insert_n_lines_cost #define FRAME_DELETEN_COST(f) (f)->delete_n_lines_cost -#define FRAME_MESSAGE_BUF(f) (f)->message_buf #define FRAME_SCROLL_BOTTOM_VPOS(f) (f)->scroll_bottom_vpos #define FRAME_FOCUS_FRAME(f) f->focus_frame @@ -870,39 +851,6 @@ typedef struct frame *FRAME_PTR; #define FRAME_MESSAGE_BUF_SIZE(f) (((int) FRAME_COLS (f)) * 4) -/* Emacs's redisplay code could become confused if a frame's - visibility changes at arbitrary times. For example, if a frame is - visible while the desired glyphs are being built, but becomes - invisible before they are updated, then some rows of the - desired_glyphs will be left marked as enabled after redisplay is - complete, which should never happen. The next time the frame - becomes visible, redisplay will probably barf. - - Currently, there are no similar situations involving iconified, but - the principle is the same. - - So instead of having asynchronous input handlers directly set and - clear the frame's visibility and iconification flags, they just set - the async_visible and async_iconified flags; the redisplay code - calls the FRAME_SAMPLE_VISIBILITY macro before doing any redisplay, - which sets visible and iconified from their asynchronous - counterparts. - - Synchronous code must use the FRAME_SET_VISIBLE macro. - - Also, if a frame used to be invisible, but has just become visible, - it must be marked as garbaged, since redisplay hasn't been keeping - up its contents. - - Note that a tty frame is visible if and only if it is the topmost - frame. */ - -#define FRAME_SAMPLE_VISIBILITY(f) \ - (((f)->async_visible && (f)->visible != (f)->async_visible) ? \ - SET_FRAME_GARBAGED (f) : 0, \ - (f)->visible = (f)->async_visible, \ - (f)->iconified = (f)->async_iconified) - #define CHECK_FRAME(x) \ CHECK_TYPE (FRAMEP (x), Qframep, x) @@ -936,12 +884,24 @@ typedef struct frame *FRAME_PTR; 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_mouse_x, \ + hlinfo->mouse_face_mouse_y); \ unblock_input (); \ } \ } while (0) +/* Set visibility of frame F, marking F as garbaged if needed. */ + +#define SET_FRAME_VISIBLE(f, v) \ + (((f)->visible == 0 || ((f)->visible == 2)) \ + && ((v) == 1) ? SET_FRAME_GARBAGED (f) : 0, \ + (f)->visible = (eassert (0 <= (v) && (v) <= 2), (v))) + +/* Set iconify of frame F. */ + +#define SET_FRAME_ICONIFIED(f, i) \ + (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i)) + extern Lisp_Object Qframep, Qframe_live_p; extern Lisp_Object Qtty, Qtty_type; extern Lisp_Object Qtty_color_mode; diff --git a/src/ftfont.c b/src/ftfont.c index 5bf91832c7c..867e25a7a25 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -393,7 +393,7 @@ ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for) cache_data = xmalloc (sizeof *cache_data); cache_data->ft_face = NULL; cache_data->fc_charset = NULL; - val = make_save_value (cache_data, 0); + val = make_save_value ("pi", cache_data, 0); cache = Fcons (Qnil, val); Fputhash (key, cache, ft_face_cache); } @@ -2541,7 +2541,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, if (NILP (lglyph)) { - lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); + lglyph = LGLYPH_NEW (); LGSTRING_SET_GLYPH (lgstring, i, lglyph); } LGLYPH_SET_FROM (lglyph, g->from); @@ -2555,9 +2555,8 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, LGLYPH_SET_DESCENT (lglyph, g->descent >> 6); if (g->adjusted) { - Lisp_Object vec; + Lisp_Object vec = make_uninit_vector (3); - vec = Fmake_vector (make_number (3), Qnil); ASET (vec, 0, make_number (g->xoff >> 6)); ASET (vec, 1, make_number (g->yoff >> 6)); ASET (vec, 2, make_number (g->xadv >> 6)); diff --git a/src/gtkutil.c b/src/gtkutil.c index f045deacd33..d6e4dcebcd3 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -983,7 +983,7 @@ xg_frame_set_char_size (FRAME_PTR f, int cols, int rows) size as fast as possible. For unmapped windows, we can set rows/cols. When the frame is mapped again we will (hopefully) get the correct size. */ - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) { /* Must call this to flush out events */ (void)gtk_events_pending (); @@ -1716,7 +1716,7 @@ xg_dialog_run (FRAME_PTR f, GtkWidget *w) g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL); gtk_widget_show (w); - record_unwind_protect (pop_down_dialog, make_save_value (&dd, 0)); + record_unwind_protect (pop_down_dialog, make_save_pointer (&dd)); (void) xg_maybe_add_timer (&dd); g_main_loop_run (dd.loop); @@ -4353,6 +4353,21 @@ xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos) x->toolbar_is_packed = true; } +static bool xg_update_tool_bar_sizes (FRAME_PTR f); + +static void +tb_size_cb (GtkWidget *widget, + GdkRectangle *allocation, + gpointer user_data) +{ + /* When tool bar is created it has one preferred size. But when size is + allocated between widgets, it may get another. So we must update + size hints if tool bar size changes. Seen on Fedora 18 at least. */ + FRAME_PTR f = (FRAME_PTR) user_data; + if (xg_update_tool_bar_sizes (f)) + x_wm_set_size_hint (f, 0, 0); +} + /* Create a tool bar for frame F. */ static void @@ -4384,6 +4399,8 @@ xg_create_tool_bar (FRAME_PTR f) gtk_toolbar_set_style (GTK_TOOLBAR (x->toolbar_widget), GTK_TOOLBAR_ICONS); toolbar_set_orientation (x->toolbar_widget, GTK_ORIENTATION_HORIZONTAL); + g_signal_connect (x->toolbar_widget, "size-allocate", + G_CALLBACK (tb_size_cb), f); #if GTK_CHECK_VERSION (3, 3, 6) gsty = gtk_widget_get_style_context (x->toolbar_widget); gtk_style_context_add_class (gsty, "primary-toolbar"); diff --git a/src/image.c b/src/image.c index 726b65d7338..2d4e7e731ad 100644 --- a/src/image.c +++ b/src/image.c @@ -7792,11 +7792,6 @@ imagemagick_load_image (struct frame *f, struct image *img, } } - /* Finally we are done manipulating the image. Figure out the - resulting width/height and transfer ownership to Emacs. */ - height = MagickGetImageHeight (image_wand); - width = MagickGetImageWidth (image_wand); - /* Set the canvas background color to the frame or specified background, and flatten the image. Note: as of ImageMagick 6.6.0, SVG image transparency is not handled properly @@ -7813,6 +7808,11 @@ imagemagick_load_image (struct frame *f, struct image *img, image_wand = new_wand; } + /* Finally we are done manipulating the image. Figure out the + resulting width/height and transfer ownership to Emacs. */ + height = MagickGetImageHeight (image_wand); + width = MagickGetImageWidth (image_wand); + if (! (width <= INT_MAX && height <= INT_MAX && check_image_size (f, width, height))) { diff --git a/src/indent.c b/src/indent.c index 45b6afbd395..d1f95da6bcf 100644 --- a/src/indent.c +++ b/src/indent.c @@ -138,7 +138,7 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab) struct Lisp_Vector *widthtab; if (!VECTORP (BVAR (buf, width_table))) - bset_width_table (buf, Fmake_vector (make_number (256), make_number (0))); + bset_width_table (buf, make_uninit_vector (256)); widthtab = XVECTOR (BVAR (buf, width_table)); eassert (widthtab->header.size == 256); @@ -291,7 +291,7 @@ DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, doc: /* Return the horizontal position of point. Beginning of line is column 0. This is calculated by adding together the widths of all the displayed representations of the character between the start of the previous line -and point (eg. control characters will have a width of 2 or 4, tabs +and point (e.g., control characters will have a width of 2 or 4, tabs will have a variable width). Ignores finite width of frame, which means that this function may return values greater than (frame-width). @@ -1102,8 +1102,8 @@ static struct position val_compute_motion; the scroll bars if they are turned on. */ struct position * -compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, - bool did_motion, ptrdiff_t to, +compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, + EMACS_INT fromhpos, bool did_motion, ptrdiff_t to, EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width, ptrdiff_t hscroll, int tab_offset, struct window *win) { @@ -1186,8 +1186,11 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, immediate_quit = 1; QUIT; + /* It's just impossible to be too paranoid here. */ + eassert (from == BYTE_TO_CHAR (frombyte) && frombyte == CHAR_TO_BYTE (from)); + pos = prev_pos = from; - pos_byte = prev_pos_byte = CHAR_TO_BYTE (from); + pos_byte = prev_pos_byte = frombyte; contin_hpos = 0; prev_tab_offset = tab_offset; memset (&cmp_it, 0, sizeof cmp_it); @@ -1328,8 +1331,7 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, TO (we need to go back below). */ if (pos <= to) { - pos = find_before_next_newline (pos, to, 1); - pos_byte = CHAR_TO_BYTE (pos); + pos = find_before_next_newline (pos, to, 1, &pos_byte); hpos = width; /* If we just skipped next_boundary, loop around in the main while @@ -1583,10 +1585,9 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, /* Skip any number of invisible lines all at once */ do { - pos = find_before_next_newline (pos, to, 1); + pos = find_before_next_newline (pos, to, 1, &pos_byte); if (pos < to) - pos++; - pos_byte = CHAR_TO_BYTE (pos); + INC_BOTH (pos, pos_byte); } while (pos < to && indented_beyond_p (pos, pos_byte, @@ -1622,10 +1623,7 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, everything from a ^M to the end of the line is invisible. Stop *before* the real newline. */ if (pos < to) - { - pos = find_before_next_newline (pos, to, 1); - pos_byte = CHAR_TO_BYTE (pos); - } + pos = find_before_next_newline (pos, to, 1, &pos_byte); /* If we just skipped next_boundary, loop around in the main while and handle it. */ @@ -1729,7 +1727,8 @@ of a certain window, pass the window's starting location as FROM and the window's upper-left coordinates as FROMPOS. Pass the buffer's (point-max) as TO, to limit the scan to the end of the visible section of the buffer, and pass LINE and COL as TOPOS. */) - (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, Lisp_Object width, Lisp_Object offsets, Lisp_Object window) + (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, + Lisp_Object width, Lisp_Object offsets, Lisp_Object window) { struct window *w; Lisp_Object bufpos, hpos, vpos, prevhpos; @@ -1772,7 +1771,8 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) if (XINT (to) < BEGV || XINT (to) > ZV) args_out_of_range_3 (to, make_number (BEGV), make_number (ZV)); - pos = compute_motion (XINT (from), XINT (XCDR (frompos)), + pos = compute_motion (XINT (from), CHAR_TO_BYTE (XINT (from)), + XINT (XCDR (frompos)), XINT (XCAR (frompos)), 0, XINT (to), (NILP (topos) @@ -1794,28 +1794,23 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) XSETINT (vpos, pos->vpos); XSETINT (prevhpos, pos->prevhpos); - return Fcons (bufpos, - Fcons (hpos, - Fcons (vpos, - Fcons (prevhpos, - Fcons (pos->contin ? Qt : Qnil, Qnil))))); - + return list5 (bufpos, hpos, vpos, prevhpos, pos->contin ? Qt : Qnil); } - -/* Fvertical_motion and vmotion */ + +/* Fvertical_motion and vmotion. */ static struct position val_vmotion; struct position * -vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) +vmotion (register ptrdiff_t from, register ptrdiff_t from_byte, + register EMACS_INT vtarget, struct window *w) { ptrdiff_t hscroll = w->hscroll; struct position pos; - /* vpos is cumulative vertical position, changed as from is changed */ + /* VPOS is cumulative vertical position, changed as from is changed. */ register EMACS_INT vpos = 0; ptrdiff_t prevline; register ptrdiff_t first; - ptrdiff_t from_byte; ptrdiff_t lmargin = hscroll > 0 ? 1 - hscroll : 0; ptrdiff_t selective = (INTEGERP (BVAR (current_buffer, selective_display)) @@ -1845,44 +1840,44 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) while ((vpos > vtarget || first) && from > BEGV) { + ptrdiff_t bytepos = from_byte; Lisp_Object propval; - prevline = find_next_newline_no_quit (from - 1, -1); + prevline = from; + DEC_BOTH (prevline, bytepos); + prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos); + while (prevline > BEGV && ((selective > 0 - && indented_beyond_p (prevline, - CHAR_TO_BYTE (prevline), - selective)) + && indented_beyond_p (prevline, bytepos, selective)) /* Watch out for newlines with `invisible' property. When moving upward, check the newline before. */ || (propval = Fget_char_property (make_number (prevline - 1), Qinvisible, text_prop_object), TEXT_PROP_MEANS_INVISIBLE (propval)))) - prevline = find_next_newline_no_quit (prevline - 1, -1); - pos = *compute_motion (prevline, 0, - lmargin, - 0, - from, + { + DEC_BOTH (prevline, bytepos); + prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos); + } + pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from, /* Don't care for VPOS... */ 1 << (BITS_PER_SHORT - 1), /* ... nor HPOS. */ 1 << (BITS_PER_SHORT - 1), - -1, hscroll, - 0, - w); + -1, hscroll, 0, w); vpos -= pos.vpos; first = 0; from = prevline; + from_byte = bytepos; } - /* If we made exactly the desired vertical distance, - or if we hit beginning of buffer, - return point found */ + /* If we made exactly the desired vertical distance, or + if we hit beginning of buffer, return point found. */ if (vpos >= vtarget) { val_vmotion.bufpos = from; - val_vmotion.bytepos = CHAR_TO_BYTE (from); + val_vmotion.bytepos = from_byte; val_vmotion.vpos = vpos; val_vmotion.hpos = lmargin; val_vmotion.contin = 0; @@ -1890,39 +1885,37 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) return &val_vmotion; } - /* Otherwise find the correct spot by moving down */ + /* Otherwise find the correct spot by moving down. */ } - /* Moving downward is simple, but must calculate from beg of line - to determine hpos of starting point */ - from_byte = CHAR_TO_BYTE (from); + + /* Moving downward is simple, but must calculate from + beg of line to determine hpos of starting point. */ + if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n') { + ptrdiff_t bytepos; Lisp_Object propval; - prevline = find_next_newline_no_quit (from, -1); + prevline = find_newline_no_quit (from, from_byte, -1, &bytepos); while (prevline > BEGV && ((selective > 0 - && indented_beyond_p (prevline, - CHAR_TO_BYTE (prevline), - selective)) + && indented_beyond_p (prevline, bytepos, selective)) /* Watch out for newlines with `invisible' property. When moving downward, check the newline after. */ || (propval = Fget_char_property (make_number (prevline), Qinvisible, text_prop_object), TEXT_PROP_MEANS_INVISIBLE (propval)))) - prevline = find_next_newline_no_quit (prevline - 1, -1); - pos = *compute_motion (prevline, 0, - lmargin, - 0, - from, + { + DEC_BOTH (prevline, bytepos); + prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos); + } + pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from, /* Don't care for VPOS... */ 1 << (BITS_PER_SHORT - 1), /* ... nor HPOS. */ 1 << (BITS_PER_SHORT - 1), - -1, hscroll, - 0, - w); + -1, hscroll, 0, w); did_motion = 1; } else @@ -1931,11 +1924,9 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) pos.vpos = 0; did_motion = 0; } - return compute_motion (from, vpos, pos.hpos, did_motion, + return compute_motion (from, from_byte, vpos, pos.hpos, did_motion, ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)), - -1, hscroll, - 0, - w); + -1, hscroll, 0, w); } DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0, @@ -2002,7 +1993,7 @@ whether or not it is currently displayed in some window. */) if (noninteractive) { struct position pos; - pos = *vmotion (PT, XINT (lines), w); + pos = *vmotion (PT, PT_BYTE, XINT (lines), w); SET_PT_BOTH (pos.bufpos, pos.bytepos); } else diff --git a/src/indent.h b/src/indent.h index acfd952754e..4eb3fed6a11 100644 --- a/src/indent.h +++ b/src/indent.h @@ -26,14 +26,14 @@ struct position int contin; }; -struct position *compute_motion (ptrdiff_t from, EMACS_INT fromvpos, - EMACS_INT fromhpos, bool did_motion, - ptrdiff_t to, EMACS_INT tovpos, - EMACS_INT tohpos, +struct position *compute_motion (ptrdiff_t from, ptrdiff_t frombyte, + EMACS_INT fromvpos, EMACS_INT fromhpos, + bool did_motion, ptrdiff_t to, + EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width, ptrdiff_t hscroll, int tab_offset, struct window *); -struct position *vmotion (ptrdiff_t from, EMACS_INT vtarget, - struct window *); +struct position *vmotion (ptrdiff_t from, ptrdiff_t from_byte, + EMACS_INT vtarget, struct window *); ptrdiff_t skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p, ptrdiff_t to, Lisp_Object window); diff --git a/src/insdel.c b/src/insdel.c index 303247816ca..fc5a4576dc2 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -658,17 +658,6 @@ insert_before_markers_and_inherit (const char *string, } } -/* Subroutine used by the insert functions above. */ - -void -insert_1 (const char *string, ptrdiff_t nbytes, - bool inherit, bool prepare, bool before_markers) -{ - insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes), - nbytes, inherit, prepare, before_markers); -} - - #ifdef BYTE_COMBINING_DEBUG /* See if the bytes before POS/POS_BYTE combine with bytes @@ -2024,9 +2013,8 @@ signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins) && current_buffer != XBUFFER (combine_after_change_buffer)) Fcombine_after_change_execute (); - elt = Fcons (make_number (charpos - BEG), - Fcons (make_number (Z - (charpos - lendel + lenins)), - Fcons (make_number (lenins - lendel), Qnil))); + elt = list3i (charpos - BEG, Z - (charpos - lendel + lenins), + lenins - lendel); combine_after_change_list = Fcons (elt, combine_after_change_list); combine_after_change_buffer = Fcurrent_buffer (); diff --git a/src/intervals.h b/src/intervals.h index cded8c0abb2..a38e83cf10e 100644 --- a/src/intervals.h +++ b/src/intervals.h @@ -259,7 +259,7 @@ extern Lisp_Object get_local_map (ptrdiff_t, struct buffer *, Lisp_Object); extern INTERVAL update_interval (INTERVAL, ptrdiff_t); extern void set_intervals_multibyte (bool); extern INTERVAL validate_interval_range (Lisp_Object, Lisp_Object *, - Lisp_Object *, int); + Lisp_Object *, bool); extern INTERVAL interval_of (ptrdiff_t, Lisp_Object); /* Defined in xdisp.c. */ @@ -293,7 +293,7 @@ extern void set_text_properties_1 (Lisp_Object, Lisp_Object, Lisp_Object text_property_list (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); -int add_text_properties_from_list (Lisp_Object, Lisp_Object, Lisp_Object); +void add_text_properties_from_list (Lisp_Object, Lisp_Object, Lisp_Object); Lisp_Object extend_property_ranges (Lisp_Object, Lisp_Object); Lisp_Object get_char_property_and_overlay (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object*); diff --git a/src/keyboard.c b/src/keyboard.c index 7594a4f72fc..914378947ed 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -367,7 +367,7 @@ Lisp_Object Qmenu_bar; static Lisp_Object recursive_edit_unwind (Lisp_Object buffer); static Lisp_Object command_loop (void); -static Lisp_Object Qextended_command_history; +static Lisp_Object Qcommand_execute; EMACS_TIME timer_check (void); static void echo_now (void); @@ -417,10 +417,9 @@ static void (*keyboard_init_hook) (void); static bool get_input_pending (int); static bool readable_events (int); -static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *, +static Lisp_Object read_char_x_menu_prompt (Lisp_Object, Lisp_Object, bool *); -static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t, - Lisp_Object *); +static Lisp_Object read_char_minibuf_menu_prompt (int, Lisp_Object); static Lisp_Object make_lispy_event (struct input_event *); static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object, enum scroll_bar_part, @@ -675,9 +674,8 @@ echo_now (void) } echoing = 1; - message3_nolog (KVAR (current_kboard, echo_string), - SBYTES (KVAR (current_kboard, echo_string)), - STRING_MULTIBYTE (KVAR (current_kboard, echo_string))); + /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak). */ + message3_nolog (KVAR (current_kboard, echo_string)); echoing = 0; /* Record in what buffer we echoed, and from which kboard. */ @@ -1187,13 +1185,13 @@ top_level_2 (void) static Lisp_Object top_level_1 (Lisp_Object ignore) { - /* On entry to the outer level, run the startup file */ + /* On entry to the outer level, run the startup file. */ if (!NILP (Vtop_level)) internal_condition_case (top_level_2, Qerror, cmd_error); else if (!NILP (Vpurify_flag)) - message ("Bare impure Emacs (standard Lisp code not loaded)"); + message1 ("Bare impure Emacs (standard Lisp code not loaded)"); else - message ("Bare Emacs (standard Lisp code not loaded)"); + message1 ("Bare Emacs (standard Lisp code not loaded)"); return Qnil; } @@ -1429,7 +1427,7 @@ command_loop_1 (void) sit_for (Vminibuffer_message_timeout, 0, 2); /* Clear the echo area. */ - message2 (0, 0, 0); + message1 (0); safe_run_hooks (Qecho_area_clear_hook); unbind_to (count, Qnil); @@ -1585,11 +1583,11 @@ command_loop_1 (void) = (EQ (undo, BVAR (current_buffer, undo_list)) ? Qnil : BVAR (current_buffer, undo_list)); } - Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil); + call1 (Qcommand_execute, Vthis_command); #ifdef HAVE_WINDOW_SYSTEM /* Do not check display_hourglass_p here, because - Fcommand_execute could change it, but we should cancel + `command-execute' could change it, but we should cancel hourglass cursor anyway. But don't cancel the hourglass within a macro just because a command in the macro finishes. */ @@ -2232,13 +2230,12 @@ do { if (! polling_stopped_here) stop_polling (); \ do { if (polling_stopped_here) start_polling (); \ polling_stopped_here = 0; } while (0) -/* read a character from the keyboard; call the redisplay if needed */ +/* Read a character from the keyboard; call the redisplay if needed. */ /* commandflag 0 means do not autosave, but do redisplay. -1 means do not redisplay, but do autosave. 1 means do both. */ -/* The arguments MAPS and NMAPS are for menu prompting. - MAPS is an array of keymaps; NMAPS is the length of MAPS. +/* The arguments MAP is for menu prompting. MAP is a keymap. PREV_EVENT is the previous input event, or nil if we are reading the first event of a key sequence (or not reading a key sequence). @@ -2260,7 +2257,7 @@ do { if (polling_stopped_here) start_polling (); \ Value is t if we showed a menu and the user rejected it. */ Lisp_Object -read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, +read_char (int commandflag, Lisp_Object map, Lisp_Object prev_event, bool *used_mouse_menu, EMACS_TIME *end_time) { @@ -2408,7 +2405,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, goto reread_first; } - /* if redisplay was requested */ + /* If redisplay was requested. */ if (commandflag >= 0) { bool echo_current = EQ (echo_message_buffer, echo_area_buffer[0]); @@ -2417,7 +2414,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, user-visible, such as X selection_request events. */ if (input_pending || detect_input_pending_run_timers (0)) - swallow_events (0); /* may clear input_pending */ + swallow_events (0); /* May clear input_pending. */ /* Redisplay if no pending input. */ while (!input_pending) @@ -2487,13 +2484,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, menu prompting. If EVENT_HAS_PARAMETERS then we are reading after a mouse event so don't try a minibuf menu. */ c = Qnil; - if (nmaps > 0 && INTERACTIVE + if (KEYMAPP (map) && INTERACTIVE && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event) /* Don't bring up a menu if we already have another event. */ && NILP (Vunread_command_events) && !detect_input_pending_run_timers (0)) { - c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps); + c = read_char_minibuf_menu_prompt (commandflag, map); if (INTEGERP (c) && XINT (c) == -2) return c; /* wrong_kboard_jmpbuf */ @@ -2617,7 +2614,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, because the recursive call of read_char in read_char_minibuf_menu_prompt does not pass on any keymaps. */ - if (nmaps > 0 && INTERACTIVE + if (KEYMAPP (map) && INTERACTIVE && !NILP (prev_event) && EVENT_HAS_PARAMETERS (prev_event) && !EQ (XCAR (prev_event), Qmenu_bar) @@ -2625,7 +2622,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, /* Don't bring up a menu if we already have another event. */ && NILP (Vunread_command_events)) { - c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu); + c = read_char_x_menu_prompt (map, prev_event, used_mouse_menu); /* Now that we have read an event, Emacs is not idle. */ if (!end_time) @@ -2660,9 +2657,10 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, && XINT (Vauto_save_timeout) > 0) { Lisp_Object tem0; - EMACS_INT timeout = (delay_level - * min (XFASTINT (Vauto_save_timeout) / 4, - MOST_POSITIVE_FIXNUM / delay_level)); + EMACS_INT timeout = XFASTINT (Vauto_save_timeout); + + timeout = min (timeout, MOST_POSITIVE_FIXNUM / delay_level * 4); + timeout = delay_level * timeout / 4; save_getcjmp (save_jump); restore_getcjmp (local_getcjmp); tem0 = sit_for (make_number (timeout), 1, 1); @@ -2844,7 +2842,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, { struct buffer *prev_buffer = current_buffer; last_input_event = c; - Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt); + call4 (Qcommand_execute, tem, Qnil, Fvector (1, &last_input_event), Qt); if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time) /* We stopped being idle for this event; undo that. This @@ -3003,7 +3001,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, /* If we are not reading a key sequence, never use the echo area. */ - if (maps == 0) + if (!KEYMAPP (map)) { specbind (Qinput_method_use_echo_area, Qt); } @@ -3096,7 +3094,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, last_input_event = c; num_input_events++; - /* Process the help character specially if enabled */ + /* Process the help character specially if enabled. */ if (!NILP (Vhelp_form) && help_char_p (c)) { ptrdiff_t count = SPECPDL_INDEX (); @@ -3110,13 +3108,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, cancel_echoing (); do { - c = read_char (0, 0, 0, Qnil, 0, NULL); + c = read_char (0, Qnil, Qnil, 0, NULL); if (EVENT_HAS_PARAMETERS (c) && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_click)) XSETCAR (help_form_saved_window_configs, Qnil); } while (BUFFERP (c)); - /* Remove the help from the frame */ + /* Remove the help from the frame. */ unbind_to (count, Qnil); redisplay (); @@ -3124,7 +3122,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, { cancel_echoing (); do - c = read_char (0, 0, 0, Qnil, 0, NULL); + c = read_char (0, Qnil, Qnil, 0, NULL); while (BUFFERP (c)); } } @@ -6227,9 +6225,7 @@ parse_modifiers (Lisp_Object symbol) Lisp_Object elements; if (INTEGERP (symbol)) - return (Fcons (make_number (KEY_TO_CHAR (symbol)), - Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK), - Qnil))); + return list2i (KEY_TO_CHAR (symbol), XINT (symbol) & CHAR_MODIFIER_MASK); else if (!SYMBOLP (symbol)) return Qnil; @@ -8314,9 +8310,9 @@ init_tool_bar_items (Lisp_Object reuse) static void append_tool_bar_item (void) { - ptrdiff_t incr = - (ntool_bar_items - - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS)); + ptrdiff_t incr + = (ntool_bar_items + - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS)); /* Enlarge tool_bar_items_vector if necessary. */ if (0 < incr) @@ -8334,8 +8330,8 @@ append_tool_bar_item (void) -/* Read a character using menus based on maps in the array MAPS. - NMAPS is the length of MAPS. Return nil if there are no menus in the maps. +/* Read a character using menus based on the keymap MAP. + Return nil if there are no menus in the maps. Return t if we displayed a menu but the user rejected it. PREV_EVENT is the previous input event, or nil if we are reading @@ -8355,28 +8351,17 @@ append_tool_bar_item (void) and do auto-saving in the inner call of read_char. */ static Lisp_Object -read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps, +read_char_x_menu_prompt (Lisp_Object map, Lisp_Object prev_event, bool *used_mouse_menu) { -#ifdef HAVE_MENUS - ptrdiff_t mapno; -#endif - if (used_mouse_menu) *used_mouse_menu = 0; - /* Use local over global Menu maps */ + /* Use local over global Menu maps. */ if (! menu_prompting) return Qnil; - /* Optionally disregard all but the global map. */ - if (inhibit_local_menu_bar_menus) - { - maps += (nmaps - 1); - nmaps = 1; - } - #ifdef HAVE_MENUS /* If we got to this point via a mouse click, use a real menu for mouse selection. */ @@ -8385,16 +8370,9 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps, && !EQ (XCAR (prev_event), Qtool_bar)) { /* Display the menu and get the selection. */ - Lisp_Object *realmaps = alloca (nmaps * sizeof *realmaps); Lisp_Object value; - ptrdiff_t nmaps1 = 0; - /* Use the maps that are not nil. */ - for (mapno = 0; mapno < nmaps; mapno++) - if (!NILP (maps[mapno])) - realmaps[nmaps1++] = maps[mapno]; - - value = Fx_popup_menu (prev_event, Flist (nmaps1, realmaps)); + value = Fx_popup_menu (prev_event, get_keymap (map, 0, 1)); if (CONSP (value)) { Lisp_Object tem; @@ -8434,17 +8412,10 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps, return Qnil ; } -/* Buffer in use so far for the minibuf prompts for menu keymaps. - We make this bigger when necessary, and never free it. */ -static char *read_char_minibuf_menu_text; -/* Size of that buffer. */ -static ptrdiff_t read_char_minibuf_menu_width; - static Lisp_Object read_char_minibuf_menu_prompt (int commandflag, - ptrdiff_t nmaps, Lisp_Object *maps) + Lisp_Object map) { - ptrdiff_t mapno; register Lisp_Object name; ptrdiff_t nlength; /* FIXME: Use the minibuffer's frame width. */ @@ -8452,53 +8423,35 @@ read_char_minibuf_menu_prompt (int commandflag, ptrdiff_t idx = -1; bool nobindings = 1; Lisp_Object rest, vector; - char *menu; + Lisp_Object prompt_strings = Qnil; vector = Qnil; - name = Qnil; if (! menu_prompting) return Qnil; - /* Get the menu name from the first map that has one (a prompt string). */ - for (mapno = 0; mapno < nmaps; mapno++) - { - name = Fkeymap_prompt (maps[mapno]); - if (!NILP (name)) - break; - } + map = get_keymap (map, 0, 1); + name = Fkeymap_prompt (map); /* If we don't have any menus, just read a character normally. */ if (!STRINGP (name)) return Qnil; - /* Make sure we have a big enough buffer for the menu text. */ - width = max (width, SBYTES (name)); - if (STRING_BYTES_BOUND - 4 < width) - memory_full (SIZE_MAX); - if (width + 4 > read_char_minibuf_menu_width) - { - read_char_minibuf_menu_text - = xrealloc (read_char_minibuf_menu_text, width + 4); - read_char_minibuf_menu_width = width + 4; - } - menu = read_char_minibuf_menu_text; +#define PUSH_C_STR(str, listvar) \ + listvar = Fcons (make_unibyte_string (str, strlen (str)), listvar) /* Prompt string always starts with map's prompt, and a space. */ - strcpy (menu, SSDATA (name)); - nlength = SBYTES (name); - menu[nlength++] = ':'; - menu[nlength++] = ' '; - menu[nlength] = 0; + prompt_strings = Fcons (name, prompt_strings); + PUSH_C_STR (": ", prompt_strings); + nlength = SCHARS (name) + 2; - /* Start prompting at start of first map. */ - mapno = 0; - rest = maps[mapno]; + rest = map; /* Present the documented bindings, a line at a time. */ while (1) { bool notfirst = 0; + Lisp_Object menu_strings = prompt_strings; ptrdiff_t i = nlength; Lisp_Object obj; Lisp_Object orig_defn_macro; @@ -8508,18 +8461,16 @@ read_char_minibuf_menu_prompt (int commandflag, { Lisp_Object elt; - /* If reached end of map, start at beginning of next map. */ + /* FIXME: Use map_keymap to handle new keymap formats. */ + + /* At end of map, wrap around if just starting, + or end this line if already have something on it. */ if (NILP (rest)) { - mapno++; - /* At end of last map, wrap around to first map if just starting, - or end this line if already have something on it. */ - if (mapno == nmaps) - { - mapno = 0; - if (notfirst || nobindings) break; - } - rest = maps[mapno]; + if (notfirst || nobindings) + break; + else + rest = map; } /* Look at the next element of the map. */ @@ -8603,7 +8554,7 @@ read_char_minibuf_menu_prompt (int commandflag, /* Punctuate between strings. */ if (notfirst) { - strcpy (menu + i, ", "); + PUSH_C_STR (", ", menu_strings); i += 2; } notfirst = 1; @@ -8615,23 +8566,28 @@ read_char_minibuf_menu_prompt (int commandflag, { /* Add as much of string as fits. */ thiswidth = min (SCHARS (desc), width - i); - memcpy (menu + i, SDATA (desc), thiswidth); + menu_strings + = Fcons (Fsubstring (desc, make_number (0), + make_number (thiswidth)), + menu_strings); i += thiswidth; - strcpy (menu + i, " = "); + PUSH_C_STR (" = ", menu_strings); i += 3; } /* Add as much of string as fits. */ thiswidth = min (SCHARS (s), width - i); - memcpy (menu + i, SDATA (s), thiswidth); + menu_strings + = Fcons (Fsubstring (s, make_number (0), + make_number (thiswidth)), + menu_strings); i += thiswidth; - menu[i] = 0; } else { /* If this element does not fit, end the line now, and save the element for the next line. */ - strcpy (menu + i, "..."); + PUSH_C_STR ("...", menu_strings); break; } } @@ -8648,23 +8604,19 @@ read_char_minibuf_menu_prompt (int commandflag, } /* Prompt with that and read response. */ - message2_nolog (menu, strlen (menu), - ! NILP (BVAR (current_buffer, enable_multibyte_characters))); + message3_nolog (apply1 (intern ("concat"), Fnreverse (menu_strings))); - /* Make believe its not a keyboard macro in case the help char + /* Make believe it's not a keyboard macro in case the help char is pressed. Help characters are not recorded because menu prompting - is not used on replay. - */ + is not used on replay. */ orig_defn_macro = KVAR (current_kboard, defining_kbd_macro); kset_defining_kbd_macro (current_kboard, Qnil); do - obj = read_char (commandflag, 0, 0, Qt, 0, NULL); + obj = read_char (commandflag, Qnil, Qt, 0, NULL); while (BUFFERP (obj)); kset_defining_kbd_macro (current_kboard, orig_defn_macro); - if (!INTEGERP (obj)) - return obj; - else if (XINT (obj) == -2) + if (!INTEGERP (obj) || XINT (obj) == -2) return obj; if (! EQ (obj, menu_prompt_more_char) @@ -8675,52 +8627,25 @@ read_char_minibuf_menu_prompt (int commandflag, store_kbd_macro_char (obj); return obj; } - /* Help char - go round again */ + /* Help char - go round again. */ } } /* Reading key sequences. */ -/* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings - in DEFS[0..NMAPS-1]. Set NEXT[i] to DEFS[i] if DEFS[i] is a - keymap, or nil otherwise. Return the index of the first keymap in - which KEY has any binding, or NMAPS if no map has a binding. - - If KEY is a meta ASCII character, treat it like meta-prefix-char - followed by the corresponding non-meta character. Keymaps in - CURRENT with non-prefix bindings for meta-prefix-char become nil in - NEXT. - - If KEY has no bindings in any of the CURRENT maps, NEXT is left - unmodified. - - NEXT may be the same array as CURRENT. */ - -static int -follow_key (Lisp_Object key, ptrdiff_t nmaps, Lisp_Object *current, - Lisp_Object *defs, Lisp_Object *next) +static Lisp_Object +follow_key (Lisp_Object keymap, Lisp_Object key) { - ptrdiff_t i, first_binding; - - first_binding = nmaps; - for (i = nmaps - 1; i >= 0; i--) - { - if (! NILP (current[i])) - { - defs[i] = access_keymap (current[i], key, 1, 0, 1); - if (! NILP (defs[i])) - first_binding = i; - } - else - defs[i] = Qnil; - } - - /* Given the set of bindings we've found, produce the next set of maps. */ - if (first_binding < nmaps) - for (i = 0; i < nmaps; i++) - next[i] = NILP (defs[i]) ? Qnil : get_keymap (defs[i], 0, 1); + return access_keymap (get_keymap (keymap, 0, 1), + key, 1, 0, 1); +} - return first_binding; +static Lisp_Object +active_maps (Lisp_Object first_event) +{ + Lisp_Object position + = CONSP (first_event) ? CAR_SAFE (XCDR (first_event)) : Qnil; + return Fcons (Qkeymap, Fcurrent_active_maps (Qt, position)); } /* Structure used to keep track of partial application of key remapping @@ -8852,8 +8777,9 @@ keyremap_step (Lisp_Object *keybuf, int bufsize, volatile keyremap *fkey, static bool test_undefined (Lisp_Object binding) { - return (EQ (binding, Qundefined) - || (!NILP (binding) && SYMBOLP (binding) + return (NILP (binding) + || EQ (binding, Qundefined) + || (SYMBOLP (binding) && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined))); } @@ -8899,7 +8825,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, bool dont_downcase_last, bool can_return_switch_frame, bool fix_current_buffer) { - Lisp_Object from_string; ptrdiff_t count = SPECPDL_INDEX (); /* How many keys there are in the current key sequence. */ @@ -8910,34 +8835,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, ptrdiff_t echo_start IF_LINT (= 0); ptrdiff_t keys_start; - /* The number of keymaps we're scanning right now, and the number of - keymaps we have allocated space for. */ - ptrdiff_t nmaps; - ptrdiff_t nmaps_allocated = 0; - - /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in - the current keymaps. */ - Lisp_Object *defs = NULL; - - /* submaps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1] - in the current keymaps, or nil where it is not a prefix. */ - Lisp_Object *submaps = NULL; - - /* The local map to start out with at start of key sequence. */ - Lisp_Object orig_local_map; + Lisp_Object current_binding = Qnil; + Lisp_Object first_event = Qnil; - /* The map from the `keymap' property to start out with at start of - key sequence. */ - Lisp_Object orig_keymap; - - /* Positive if we have already considered switching to the local-map property - of the place where a mouse click occurred. */ - int localized_local_map = 0; - - /* The index in submaps[] of the first keymap that has a binding for - this key sequence. In other words, the lowest i such that - submaps[i] is non-nil. */ - ptrdiff_t first_binding; /* Index of the first key that has no binding. It is useless to try fkey.start larger than that. */ int first_unbound; @@ -8980,11 +8880,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, While we're reading, we keep the event here. */ Lisp_Object delayed_switch_frame; - /* See the comment below... */ -#if defined (GOBBLE_FIRST_EVENT) - Lisp_Object first_event; -#endif - Lisp_Object original_uppercase IF_LINT (= Qnil); int original_uppercase_position = -1; @@ -8996,10 +8891,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, /* List of events for which a fake prefix key has been generated. */ Lisp_Object fake_prefixed_keys = Qnil; -#if defined (GOBBLE_FIRST_EVENT) - int junk; -#endif - struct gcpro gcpro1; GCPRO1 (fake_prefixed_keys); @@ -9035,21 +8926,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, keys_start = this_command_key_count; this_single_command_key_start = keys_start; -#if defined (GOBBLE_FIRST_EVENT) - /* This doesn't quite work, because some of the things that read_char - does cannot safely be bypassed. It seems too risky to try to make - this work right. */ - - /* Read the first char of the sequence specially, before setting - up any keymaps, in case a filter runs and switches buffers on us. */ - first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event, - &junk, NULL); -#endif /* GOBBLE_FIRST_EVENT */ - - orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); - orig_keymap = get_local_map (PT, current_buffer, Qkeymap); - from_string = Qnil; - /* We jump here when we need to reinitialize fkey and keytran; this happens if we switch keyboards between rescans. */ replay_entire_sequence: @@ -9074,59 +8950,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, keybuf with its symbol, or if the sequence starts with a mouse click and we need to switch buffers, we jump back here to rebuild the initial keymaps from the current buffer. */ - nmaps = 0; - - if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) - { - if (2 > nmaps_allocated) - { - submaps = alloca (2 * sizeof *submaps); - defs = alloca (2 * sizeof *defs); - nmaps_allocated = 2; - } - submaps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); - } - else if (!NILP (Voverriding_local_map)) - { - if (2 > nmaps_allocated) - { - submaps = alloca (2 * sizeof *submaps); - defs = alloca (2 * sizeof *defs); - nmaps_allocated = 2; - } - submaps[nmaps++] = Voverriding_local_map; - } - else - { - ptrdiff_t nminor; - ptrdiff_t total; - Lisp_Object *maps; - - nminor = current_minor_maps (0, &maps); - total = nminor + (!NILP (orig_keymap) ? 3 : 2); - - if (total > nmaps_allocated) - { - submaps = alloca (total * sizeof *submaps); - defs = alloca (total * sizeof *defs); - nmaps_allocated = total; - } - - if (!NILP (orig_keymap)) - submaps[nmaps++] = orig_keymap; - - memcpy (submaps + nmaps, maps, nminor * sizeof (submaps[0])); - - nmaps += nminor; - - submaps[nmaps++] = orig_local_map; - } - submaps[nmaps++] = current_global_map; - - /* Find an accurate initial value for first_binding. */ - for (first_binding = 0; first_binding < nmaps; first_binding++) - if (! NILP (submaps[first_binding])) - break; + current_binding = active_maps (first_event); /* Start from the beginning in keybuf. */ t = 0; @@ -9140,9 +8964,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, /* If the best binding for the current key sequence is a keymap, or we may be looking at a function key's escape sequence, keep on reading. */ - while (first_binding < nmaps + while (!NILP (current_binding) /* Keep reading as long as there's a prefix binding. */ - ? !NILP (submaps[first_binding]) + ? KEYMAPP (current_binding) /* Don't return in the middle of a possible function key sequence, if the only bindings we found were via case conversion. Thus, if ESC O a has a function-key-map translation @@ -9166,7 +8990,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, just one key. */ ptrdiff_t echo_local_start IF_LINT (= 0); int keys_local_start; - ptrdiff_t local_first_binding; + Lisp_Object new_binding; eassert (indec.end == t || (indec.end > t && indec.end <= mock_input)); eassert (indec.start <= indec.end); @@ -9203,7 +9027,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, if (INTERACTIVE) echo_local_start = echo_length (); keys_local_start = this_command_key_count; - local_first_binding = first_binding; replay_key: /* These are no-ops, unless we throw away a keystroke below and @@ -9213,7 +9036,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, if (INTERACTIVE && t < mock_input) echo_truncate (echo_local_start); this_command_key_count = keys_local_start; - first_binding = local_first_binding; /* By default, assume each event is "real". */ last_real_key_start = t; @@ -9238,8 +9060,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, { KBOARD *interrupted_kboard = current_kboard; struct frame *interrupted_frame = SELECTED_FRAME (); - key = read_char (NILP (prompt), nmaps, - (Lisp_Object *) submaps, last_nonmenu_event, + key = read_char (NILP (prompt), + current_binding, last_nonmenu_event, &used_mouse_menu, NULL); if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */ /* When switching to a new tty (with a new keyboard), @@ -9294,8 +9116,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, KVAR (interrupted_kboard, kbd_queue))); } mock_input = 0; - orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); - orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_entire_sequence; } } @@ -9336,12 +9156,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, { if (! FRAME_LIVE_P (XFRAME (selected_frame))) Fkill_emacs (Qnil); - if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer) + if (XBUFFER (XWINDOW (selected_window)->buffer) + != current_buffer) Fset_buffer (XWINDOW (selected_window)->buffer); } - orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); - orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } @@ -9358,8 +9177,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, keybuf[t++] = key; mock_input = t; Vquit_flag = Qnil; - orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); - orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } @@ -9379,6 +9196,22 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, } } + if (NILP (first_event)) + { + first_event = key; + /* Even if first_event does not specify a particular + window/position, it's important to recompute the maps here + since a long time might have passed since we entered + read_key_sequence, and a timer (or process-filter or + special-event-map, ...) might have switched the current buffer + or the selected window from under us in the mean time. */ + if (fix_current_buffer + && (XBUFFER (XWINDOW (selected_window)->buffer) + != current_buffer)) + Fset_buffer (XWINDOW (selected_window)->buffer); + current_binding = active_maps (first_event); + } + GROW_RAW_KEYBUF; ASET (raw_keybuf, raw_keybuf_count, key); raw_keybuf_count++; @@ -9400,16 +9233,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, or when user programs play with this-command-keys. */ if (EVENT_HAS_PARAMETERS (key)) { - Lisp_Object kind; - Lisp_Object string; - - kind = EVENT_HEAD_KIND (EVENT_HEAD (key)); + Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key)); if (EQ (kind, Qmouse_click)) { - Lisp_Object window, posn; - - window = POSN_WINDOW (EVENT_START (key)); - posn = POSN_POSN (EVENT_START (key)); + Lisp_Object window = POSN_WINDOW (EVENT_START (key)); + Lisp_Object posn = POSN_POSN (EVENT_START (key)); if (CONSP (posn) || (!NILP (fake_prefixed_keys) @@ -9452,58 +9280,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, if (! FRAME_LIVE_P (XFRAME (selected_frame))) Fkill_emacs (Qnil); set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); - orig_local_map = get_local_map (PT, current_buffer, - Qlocal_map); - orig_keymap = get_local_map (PT, current_buffer, - Qkeymap); goto replay_sequence; } - - /* For a mouse click, get the local text-property keymap - of the place clicked on, rather than point. */ - if (CONSP (XCDR (key)) - && ! localized_local_map) - { - Lisp_Object map_here, start, pos; - - localized_local_map = 1; - start = EVENT_START (key); - - if (CONSP (start) && POSN_INBUFFER_P (start)) - { - pos = POSN_BUFFER_POSN (start); - if (INTEGERP (pos) - && XINT (pos) >= BEGV - && XINT (pos) <= ZV) - { - map_here = get_local_map (XINT (pos), - current_buffer, - Qlocal_map); - if (!EQ (map_here, orig_local_map)) - { - orig_local_map = map_here; - ++localized_local_map; - } - - map_here = get_local_map (XINT (pos), - current_buffer, - Qkeymap); - if (!EQ (map_here, orig_keymap)) - { - orig_keymap = map_here; - ++localized_local_map; - } - - if (localized_local_map > 1) - { - keybuf[t] = key; - mock_input = t + 1; - - goto replay_sequence; - } - } - } - } } /* Expand mode-line and scroll-bar events into two events: @@ -9524,63 +9302,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, prevent proper action when the event is pushed back into unread-command-events. */ fake_prefixed_keys = Fcons (key, fake_prefixed_keys); - - /* If on a mode line string with a local keymap, - reconsider the key sequence with that keymap. */ - if (string = POSN_STRING (EVENT_START (key)), - (CONSP (string) && STRINGP (XCAR (string)))) - { - Lisp_Object pos, map, map2; - - pos = XCDR (string); - string = XCAR (string); - if (XINT (pos) >= 0 - && XINT (pos) < SCHARS (string)) - { - map = Fget_text_property (pos, Qlocal_map, string); - if (!NILP (map)) - orig_local_map = map; - map2 = Fget_text_property (pos, Qkeymap, string); - if (!NILP (map2)) - orig_keymap = map2; - if (!NILP (map) || !NILP (map2)) - goto replay_sequence; - } - } - goto replay_key; } - else if (NILP (from_string) - && (string = POSN_STRING (EVENT_START (key)), - (CONSP (string) && STRINGP (XCAR (string))))) - { - /* For a click on a string, i.e. overlay string or a - string displayed via the `display' property, - consider `local-map' and `keymap' properties of - that string. */ - Lisp_Object pos, map, map2; - - pos = XCDR (string); - string = XCAR (string); - if (XINT (pos) >= 0 - && XINT (pos) < SCHARS (string)) - { - map = Fget_text_property (pos, Qlocal_map, string); - if (!NILP (map)) - orig_local_map = map; - map2 = Fget_text_property (pos, Qkeymap, string); - if (!NILP (map2)) - orig_keymap = map2; - - if (!NILP (map) || !NILP (map2)) - { - from_string = string; - keybuf[t++] = key; - mock_input = t; - goto replay_sequence; - } - } - } } else if (CONSP (XCDR (key)) && CONSP (EVENT_START (key)) @@ -9596,7 +9319,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, if (bufsize - t <= 1) error ("Key sequence too long"); keybuf[t] = posn; - keybuf[t+1] = key; + keybuf[t + 1] = key; /* Zap the position in key, so we know that we've expanded it, and don't try to do so again. */ @@ -9619,15 +9342,10 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, /* We have finally decided that KEY is something we might want to look up. */ - first_binding = (follow_key (key, - nmaps - first_binding, - submaps + first_binding, - defs + first_binding, - submaps + first_binding) - + first_binding); + new_binding = follow_key (current_binding, key); /* If KEY wasn't bound, we'll try some fallbacks. */ - if (first_binding < nmaps) + if (!NILP (new_binding)) /* This is needed for the following scenario: event 0: a down-event that gets dropped by calling replay_key. event 1: some normal prefix like C-h. @@ -9764,20 +9482,13 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, new_click = Fcons (new_head, Fcons (EVENT_START (key), Qnil)); - /* Look for a binding for this new key. follow_key - promises that it didn't munge submaps the - last time we called it, since key was unbound. */ - first_binding - = (follow_key (new_click, - nmaps - local_first_binding, - submaps + local_first_binding, - defs + local_first_binding, - submaps + local_first_binding) - + local_first_binding); + /* Look for a binding for this new key. */ + new_binding = follow_key (current_binding, new_click); /* If that click is bound, go for it. */ - if (first_binding < nmaps) + if (!NILP (new_binding)) { + current_binding = new_binding; key = new_click; break; } @@ -9786,6 +9497,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, } } } + current_binding = new_binding; keybuf[t++] = key; /* Normally, last_nonmenu_event gets the previous key we read. @@ -9817,9 +9529,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, } } - if (first_binding < nmaps - && NILP (submaps[first_binding]) - && !test_undefined (defs[first_binding]) + if (!KEYMAPP (current_binding) + && !test_undefined (current_binding) && indec.start >= t) /* There is a binding and it's not a prefix. (and it doesn't have any input-decode-map translation pending). @@ -9848,8 +9559,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, first_binding >= nmaps) we don't want to apply this function-key-mapping. */ fkey.end + 1 == t - && (first_binding >= nmaps - || test_undefined (defs[first_binding])), + && (test_undefined (current_binding)), &diff, prompt); UNGCPRO; if (done) @@ -9892,7 +9602,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, and cannot be part of a function key or translation, and is an upper case letter use the corresponding lower-case letter instead. */ - if (first_binding >= nmaps + if (NILP (current_binding) && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t && INTEGERP (key) && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK)) @@ -9923,7 +9633,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, and cannot be part of a function key or translation, and is a shifted function key, use the corresponding unshifted function key instead. */ - if (first_binding >= nmaps + if (NILP (current_binding) && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t) { Lisp_Object breakdown = parse_modifiers (key); @@ -9964,9 +9674,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, } } if (!dummyflag) - read_key_sequence_cmd = (first_binding < nmaps - ? defs[first_binding] - : Qnil); + read_key_sequence_cmd = current_binding; read_key_sequence_remapped /* Remap command through active keymaps. Do the remapping here, before the unbind_to so it uses the keymaps @@ -9980,7 +9688,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, /* Don't downcase the last character if the caller says don't. Don't downcase it if the result is undefined, either. */ - if ((dont_downcase_last || first_binding >= nmaps) + if ((dont_downcase_last || NILP (current_binding)) && t > 0 && t - 1 == original_uppercase_position) { @@ -10077,7 +9785,7 @@ will read just one key sequence. */) memset (keybuf, 0, sizeof keybuf); GCPRO1 (keybuf[0]); - gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0])); + gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0])); if (NILP (continue_echo)) { @@ -10091,7 +9799,7 @@ will read just one key sequence. */) cancel_hourglass (); #endif - i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])), + i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), prompt, ! NILP (dont_downcase_last), ! NILP (can_return_switch_frame), 0); @@ -10166,95 +9874,6 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, return unbind_to (count, Fvector (i, keybuf)); } -DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0, - doc: /* Execute CMD as an editor command. -CMD must be a symbol that satisfies the `commandp' predicate. -Optional second arg RECORD-FLAG non-nil -means unconditionally put this command in the variable `command-history'. -Otherwise, that is done only if an arg is read using the minibuffer. -The argument KEYS specifies the value to use instead of (this-command-keys) -when reading the arguments; if it is nil, (this-command-keys) is used. -The argument SPECIAL, if non-nil, means that this command is executing -a special event, so ignore the prefix argument and don't clear it. */) - (Lisp_Object cmd, Lisp_Object record_flag, Lisp_Object keys, Lisp_Object special) -{ - register Lisp_Object final; - register Lisp_Object tem; - Lisp_Object prefixarg; - - debug_on_next_call = 0; - - if (NILP (special)) - { - prefixarg = KVAR (current_kboard, Vprefix_arg); - Vcurrent_prefix_arg = prefixarg; - kset_prefix_arg (current_kboard, Qnil); - } - else - prefixarg = Qnil; - - if (SYMBOLP (cmd)) - { - tem = Fget (cmd, Qdisabled); - if (!NILP (tem)) - { - tem = Fsymbol_value (Qdisabled_command_function); - if (!NILP (tem)) - return Frun_hooks (1, &Qdisabled_command_function); - } - } - - while (1) - { - final = Findirect_function (cmd, Qnil); - - if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload))) - { - struct gcpro gcpro1, gcpro2; - - GCPRO2 (cmd, prefixarg); - Fautoload_do_load (final, cmd, Qnil); - UNGCPRO; - } - else - break; - } - - if (STRINGP (final) || VECTORP (final)) - { - /* If requested, place the macro in the command history. For - other sorts of commands, call-interactively takes care of - this. */ - if (!NILP (record_flag)) - { - Vcommand_history - = Fcons (Fcons (Qexecute_kbd_macro, - Fcons (final, Fcons (prefixarg, Qnil))), - Vcommand_history); - - /* Don't keep command history around forever. */ - if (NUMBERP (Vhistory_length) && XINT (Vhistory_length) > 0) - { - tem = Fnthcdr (Vhistory_length, Vcommand_history); - if (CONSP (tem)) - XSETCDR (tem, Qnil); - } - } - - return Fexecute_kbd_macro (final, prefixarg, Qnil); - } - - if (CONSP (final) || SUBRP (final) || COMPILEDP (final)) - /* Don't call Fcall_interactively directly because we want to make - sure the backtrace has an entry for `call-interactively'. - For the same reason, pass `cmd' rather than `final'. */ - return call3 (Qcall_interactively, cmd, record_flag, keys); - - return Qnil; -} - - - /* Return true if input events are pending. */ bool @@ -11485,8 +11104,7 @@ syms_of_keyboard (void) raw_keybuf = Fmake_vector (make_number (30), Qnil); staticpro (&raw_keybuf); - DEFSYM (Qextended_command_history, "extended-command-history"); - Fset (Qextended_command_history, Qnil); + DEFSYM (Qcommand_execute, "command-execute"); accent_key_syms = Qnil; staticpro (&accent_key_syms); @@ -11525,7 +11143,6 @@ syms_of_keyboard (void) defsubr (&Srecursive_edit); defsubr (&Strack_mouse); defsubr (&Sinput_pending_p); - defsubr (&Scommand_execute); defsubr (&Srecent_keys); defsubr (&Sthis_command_keys); defsubr (&Sthis_command_keys_vector); @@ -11683,10 +11300,6 @@ This variable is also the threshold for motion of the mouse to count as a drag. */); double_click_fuzz = 3; - DEFVAR_BOOL ("inhibit-local-menu-bar-menus", inhibit_local_menu_bar_menus, - doc: /* Non-nil means inhibit local map menu bar menus. */); - inhibit_local_menu_bar_menus = 0; - DEFVAR_INT ("num-input-keys", num_input_keys, doc: /* Number of complete key sequences read as input so far. This includes key sequences read from keyboard macros. @@ -11914,9 +11527,7 @@ If the binding is a function, it is called with one argument (the prompt) and its return value (a key sequence) is used. The events that come from bindings in `input-decode-map' are not -themselves looked up in `input-decode-map'. - -This variable is keyboard-local. */); +themselves looked up in `input-decode-map'. */); DEFVAR_LISP ("function-key-map", Vfunction_key_map, doc: /* The parent keymap of all `local-function-key-map' instances. @@ -11928,9 +11539,8 @@ definition will take precedence. */); DEFVAR_LISP ("key-translation-map", Vkey_translation_map, doc: /* Keymap of key translations that can override keymaps. -This keymap works like `function-key-map', but comes after that, -and its non-prefix bindings override ordinary bindings. -Another difference is that it is global rather than keyboard-local. */); +This keymap works like `input-decode-map', but comes after `function-key-map'. +Another difference is that it is global rather than terminal-local. */); Vkey_translation_map = Fmake_sparse_keymap (Qnil); DEFVAR_LISP ("deferred-action-list", Vdeferred_action_list, diff --git a/src/keyboard.h b/src/keyboard.h index 7ffb436754b..c6ade35dd52 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -482,7 +482,7 @@ struct input_event; extern Lisp_Object parse_modifiers (Lisp_Object); extern Lisp_Object reorder_modifiers (Lisp_Object); -extern Lisp_Object read_char (int, ptrdiff_t, Lisp_Object *, Lisp_Object, +extern Lisp_Object read_char (int, Lisp_Object, Lisp_Object, bool *, EMACS_TIME *); extern int parse_solitary_modifier (Lisp_Object symbol); diff --git a/src/keymap.c b/src/keymap.c index a9266120e86..922c1703edf 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -610,7 +610,7 @@ map_keymap_internal (Lisp_Object map, } else if (CHAR_TABLE_P (binding)) map_char_table (map_keymap_char_table_item, Qnil, binding, - format_save_value ("ppo", fun, data, args)); + make_save_value ("ppo", fun, data, args)); } UNGCPRO; return tail; @@ -1244,7 +1244,7 @@ remapping in all currently active keymaps. */) return INTEGERP (command) ? Qnil : command; } -/* Value is number if KEY is too long; nil if valid but has no definition. */ +/* Value is number if KEY is too long; nil if valid but has no definition. */ /* GC is possible in this function. */ DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0, @@ -1536,7 +1536,7 @@ DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps, doc: /* Return a list of the currently active keymaps. OLP if non-nil indicates that we should obey `overriding-local-map' and `overriding-terminal-local-map'. POSITION can specify a click position -like in the respective argument of `key-binding'. */) +like in the respective argument of `key-binding'. */) (Lisp_Object olp, Lisp_Object position) { ptrdiff_t count = SPECPDL_INDEX (); @@ -1545,7 +1545,7 @@ like in the respective argument of `key-binding'. */) /* If a mouse click position is given, our variables are based on the buffer clicked on, not the current buffer. So we may have to - switch the buffer here. */ + switch the buffer here. */ if (CONSP (position)) { diff --git a/src/lisp.h b/src/lisp.h index 9cebdef2b20..735cf8097dd 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -229,7 +229,7 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; /* Lisp integers use 2 tags, to give them one extra bit, thus extending their range from, e.g., -2^28..2^28-1 to -2^29..2^29-1. */ -static EMACS_INT const INTMASK = EMACS_INT_MAX >> (INTTYPEBITS - 1); +#define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1)) #define case_Lisp_Int case Lisp_Int0: case Lisp_Int1 #define LISP_INT_TAG_P(x) (((x) & ~Lisp_Int1) == 0) @@ -510,13 +510,9 @@ static EMACS_INT const VALMASK (XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \ + ((intptr_t) (ptr) & VALMASK))) -#if DATA_SEG_BITS /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers which were stored in a Lisp_Object. */ -#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK)) | DATA_SEG_BITS)) -#else -#define XPNTR(a) ((uintptr_t) (XLI (a) & VALMASK)) -#endif +#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK) | DATA_SEG_BITS)) #endif /* not USE_LSB_TAG */ @@ -1315,6 +1311,14 @@ sxhash_combine (EMACS_UINT x, EMACS_UINT y) return (x << 4) + (x >> (BITS_PER_EMACS_INT - 4)) + y; } +/* Hash X, returning a value that fits into a fixnum. */ + +LISP_INLINE EMACS_UINT +SXHASH_REDUCE (EMACS_UINT x) +{ + return (x ^ x >> (BITS_PER_EMACS_INT - FIXNUM_BITS)) & INTMASK; +} + /* These structures are used for various misc types. */ struct Lisp_Misc_Any /* Supertype of all Misc types. */ @@ -1399,7 +1403,50 @@ enum SAVE_OBJECT }; -/* Special object used to hold a different values for later use. */ +/* Special object used to hold a different values for later use. + + This is mostly used to package C integers and pointers to call + record_unwind_protect. Typical task is to pass just one C pointer + to unwind function. You should pack pointer with make_save_pointer + and then get it back with XSAVE_POINTER, e.g.: + + ... + struct my_data *md = get_my_data (); + record_unwind_protect (my_unwind, make_save_pointer (md)); + ... + + Lisp_Object my_unwind (Lisp_Object arg) + { + struct my_data *md = XSAVE_POINTER (arg, 0); + ... + } + + If yon need to pass more than just one C pointer, you should + use make_save_value. This function allows you to pack up to + 4 integers, pointers or Lisp_Objects and conveniently get them + back with XSAVE_POINTER, XSAVE_INTEGER and XSAVE_OBJECT macros: + + ... + struct my_data *md = get_my_data (); + ptrdiff_t my_offset = get_my_offset (); + Lisp_Object my_object = get_my_object (); + record_unwind_protect + (my_unwind, make_save_value ("pio", md, my_offset, my_object)); + ... + + Lisp_Object my_unwind (Lisp_Object arg) + { + struct my_data *md = XSAVE_POINTER (arg, 0); + ptrdiff_t my_offset = XSAVE_INTEGER (arg, 1); + Lisp_Object my_object = XSAVE_OBJECT (arg, 2); + ... + } + + If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the + saved objects and raise eassert if type of the saved object doesn't match + the type which is extracted. In the example above, XSAVE_INTEGER (arg, 2) + or XSAVE_OBJECT (arg, 1) are wrong because integer was saved in slot 1 and + Lisp_Object was saved in slot 2 of ARG. */ struct Lisp_Save_Value { @@ -2845,7 +2892,6 @@ extern int count_combining_after (const unsigned char *, ptrdiff_t, ptrdiff_t, ptrdiff_t); extern void insert (const char *, ptrdiff_t); extern void insert_and_inherit (const char *, ptrdiff_t); -extern void insert_1 (const char *, ptrdiff_t, bool, bool, bool); extern void insert_1_both (const char *, ptrdiff_t, ptrdiff_t, bool, bool, bool); extern void insert_from_gap (ptrdiff_t, ptrdiff_t); @@ -2919,11 +2965,9 @@ extern void clear_message (int, int); extern void message (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); extern void message1 (const char *); extern void message1_nolog (const char *); -extern void message2 (const char *, ptrdiff_t, int); -extern void message2_nolog (const char *, ptrdiff_t, int); -extern void message3 (Lisp_Object, ptrdiff_t, int); -extern void message3_nolog (Lisp_Object, ptrdiff_t, int); -extern void message_dolog (const char *, ptrdiff_t, int, int); +extern void message3 (Lisp_Object); +extern void message3_nolog (Lisp_Object); +extern void message_dolog (const char *, ptrdiff_t, bool, bool); extern void message_with_string (const char *, Lisp_Object, int); extern void message_log_maybe_newline (void); extern void update_echo_area (void); @@ -2974,6 +3018,28 @@ extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}; extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...); + +/* Build a frequently used 2/3/4-integer lists. */ + +LISP_INLINE Lisp_Object +list2i (EMACS_INT x, EMACS_INT y) +{ + return list2 (make_number (x), make_number (y)); +} + +LISP_INLINE Lisp_Object +list3i (EMACS_INT x, EMACS_INT y, EMACS_INT w) +{ + return list3 (make_number (x), make_number (y), make_number (w)); +} + +LISP_INLINE Lisp_Object +list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h) +{ + return list4 (make_number (x), make_number (y), + make_number (w), make_number (h)); +} + extern _Noreturn void string_overflow (void); extern Lisp_Object make_string (const char *, ptrdiff_t); extern Lisp_Object make_formatted_string (char *, const char *, ...) @@ -3020,6 +3086,27 @@ extern void make_byte_code (struct Lisp_Vector *); extern Lisp_Object Qautomatic_gc; extern Lisp_Object Qchar_table_extra_slots; extern struct Lisp_Vector *allocate_vector (EMACS_INT); + +/* Make an uninitialized vector for SIZE objects. NOTE: you must + be sure that GC cannot happen until the vector is completely + initialized. E.g. the following code is likely to crash: + + v = make_uninit_vector (3); + ASET (v, 0, obj0); + ASET (v, 1, Ffunction_can_gc ()); + ASET (v, 2, obj1); */ + +LISP_INLINE Lisp_Object +make_uninit_vector (ptrdiff_t size) +{ + Lisp_Object v; + struct Lisp_Vector *p; + + p = allocate_vector (size); + XSETVECTOR (v, p); + return v; +} + extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type); #define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ ((typ*) \ @@ -3035,8 +3122,8 @@ extern bool abort_on_gc; extern Lisp_Object make_float (double); extern void display_malloc_warning (void); extern ptrdiff_t inhibit_garbage_collection (void); -extern Lisp_Object format_save_value (const char *, ...); -extern Lisp_Object make_save_value (void *, ptrdiff_t); +extern Lisp_Object make_save_value (const char *, ...); +extern Lisp_Object make_save_pointer (void *); extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); extern void free_marker (Lisp_Object); extern void free_cons (struct Lisp_Cons *); @@ -3274,8 +3361,10 @@ extern Lisp_Object close_file_unwind (Lisp_Object); extern Lisp_Object restore_point_unwind (Lisp_Object); extern _Noreturn void report_file_error (const char *, Lisp_Object); extern bool internal_delete_file (Lisp_Object); +extern Lisp_Object emacs_readlinkat (int, const char *); extern bool file_directory_p (const char *); extern bool file_accessible_directory_p (const char *); +extern void init_fileio (void); extern void syms_of_fileio (void); extern Lisp_Object make_temp_name (Lisp_Object, bool); extern Lisp_Object Qdelete_file; @@ -3288,20 +3377,21 @@ extern void record_unwind_save_match_data (void); struct re_registers; extern struct re_pattern_buffer *compile_pattern (Lisp_Object, struct re_registers *, - Lisp_Object, int, int); + Lisp_Object, int, bool); extern ptrdiff_t fast_string_match (Lisp_Object, Lisp_Object); extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *, ptrdiff_t); extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object); extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, Lisp_Object); -extern ptrdiff_t scan_buffer (int, ptrdiff_t, ptrdiff_t, ptrdiff_t, - ptrdiff_t *, bool); +extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, + ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool); extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, EMACS_INT, bool); -extern ptrdiff_t find_next_newline (ptrdiff_t, int); -extern ptrdiff_t find_next_newline_no_quit (ptrdiff_t, ptrdiff_t); -extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t); +extern ptrdiff_t find_newline_no_quit (ptrdiff_t, ptrdiff_t, + ptrdiff_t, ptrdiff_t *); +extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, + ptrdiff_t, ptrdiff_t *); extern void syms_of_search (void); extern void clear_regexp_cache (void); @@ -3318,7 +3408,7 @@ extern void syms_of_minibuf (void); extern Lisp_Object Qminus, Qplus; extern Lisp_Object Qwhen; -extern Lisp_Object Qcall_interactively, Qmouse_leave_buffer_hook; +extern Lisp_Object Qmouse_leave_buffer_hook; extern void syms_of_callint (void); /* Defined in casefiddle.c. */ @@ -3429,10 +3519,10 @@ extern bool running_asynch_code; extern Lisp_Object QCtype, Qlocal; extern Lisp_Object Qprocessp; extern void kill_buffer_processes (Lisp_Object); -extern int wait_reading_process_output (intmax_t, int, int, bool, - Lisp_Object, - struct Lisp_Process *, - int); +extern bool wait_reading_process_output (intmax_t, int, int, bool, + Lisp_Object, + struct Lisp_Process *, + int); /* Max value for the first argument of wait_reading_process_output. */ #if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) /* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3. @@ -3478,7 +3568,6 @@ extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, ptrdiff_t, Lisp_Object *); /* Defined in macros.c. */ -extern Lisp_Object Qexecute_kbd_macro; extern void init_macros (void); extern void syms_of_macros (void); @@ -3544,8 +3633,6 @@ extern int emacs_open (const char *, int, int); extern int emacs_close (int); extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); -enum { READLINK_BUFSIZE = 1024 }; -extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]); extern void unlock_all_files (void); extern void lock_file (Lisp_Object); @@ -3686,12 +3773,11 @@ extern char *egetenv (const char *); /* Set up the name of the machine we're running on. */ extern void init_system_name (void); -/* We used to use `abs', but that clashes with system headers on some - platforms, and using a name reserved by Standard C is a bad idea - anyway. */ -#if !defined (eabs) +/* Return the absolute value of X. X should be a signed integer + expression without side effects, and X's absolute value should not + exceed the maximum for its promoted type. This is called 'eabs' + because 'abs' is reserved by the C standard. */ #define eabs(x) ((x) < 0 ? -(x) : (x)) -#endif /* Return a fixnum or float, depending on whether VAL fits in a Lisp fixnum. */ @@ -3720,16 +3806,16 @@ extern void *record_xmalloc (size_t); NITEMS items, each of the same type as *BUF. MULTIPLIER must positive. The code is tuned for MULTIPLIER being a constant. */ -#define SAFE_NALLOCA(buf, multiplier, nitems) \ - do { \ - if ((nitems) <= MAX_ALLOCA / sizeof *(buf) / (multiplier)) \ - (buf) = alloca (sizeof *(buf) * (multiplier) * (nitems)); \ - else \ +#define SAFE_NALLOCA(buf, multiplier, nitems) \ + do { \ + if ((nitems) <= MAX_ALLOCA / sizeof *(buf) / (multiplier)) \ + (buf) = alloca (sizeof *(buf) * (multiplier) * (nitems)); \ + else \ { \ (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \ sa_must_free = 1; \ record_unwind_protect (safe_alloca_unwind, \ - make_save_value (buf, 0)); \ + make_save_pointer (buf)); \ } \ } while (0) @@ -3754,7 +3840,7 @@ extern void *record_xmalloc (size_t); { \ Lisp_Object arg_; \ buf = xmalloc ((nelt) * word_size); \ - arg_ = make_save_value (buf, nelt); \ + arg_ = make_save_value ("pi", buf, nelt); \ XSAVE_VALUE (arg_)->area = 1; \ sa_must_free = 1; \ record_unwind_protect (safe_alloca_unwind, arg_); \ diff --git a/src/lread.c b/src/lread.c index a01cf099b49..e7af86aa664 100644 --- a/src/lread.c +++ b/src/lread.c @@ -96,11 +96,6 @@ static Lisp_Object Qload_in_progress; It must be set to nil before all top-level calls to read0. */ static Lisp_Object read_objects; -/* True means READCHAR should read bytes one by one (not character) - when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char. - This is set by read1 temporarily while handling #@NUMBER. */ -static bool load_each_byte; - /* List of descriptors now open for Fload. */ static Lisp_Object load_descriptor_list; @@ -328,7 +323,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) return c; } c = (*readbyte) (-1, readcharfun); - if (c < 0 || load_each_byte) + if (c < 0) return c; if (multibyte) *multibyte = 1; @@ -353,6 +348,30 @@ readchar (Lisp_Object readcharfun, bool *multibyte) return STRING_CHAR (buf); } +static void +skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n) +{ + if (EQ (readcharfun, Qget_file_char) + || EQ (readcharfun, Qget_emacs_mule_file_char)) + { + block_input (); /* FIXME: Not sure if it's needed. */ + fseek (instream, n, SEEK_CUR); + unblock_input (); + } + else + { /* We're not reading directly from a file. In that case, it's difficult + to reliably count bytes, since these are usually meant for the file's + encoding, whereas we're now typically in the internal encoding. + But luckily, skip_dyn_bytes is used to skip over a single + dynamic-docstring (or dynamic byte-code) which is always quoted such + that \037 is the final char. */ + int c; + do { + c = READCHAR; + } while (c >= 0 && c != '\037'); + } +} + /* Unread the character C in the way appropriate for the stream READCHARFUN. If the stream is a user function, call it with the char as argument. */ @@ -407,14 +426,7 @@ unreadchar (Lisp_Object readcharfun, int c) else if (EQ (readcharfun, Qget_file_char) || EQ (readcharfun, Qget_emacs_mule_file_char)) { - if (load_each_byte) - { - block_input (); - ungetc (c, instream); - unblock_input (); - } - else - unread_char = c; + unread_char = c; } else call1 (readcharfun, make_number (c)); @@ -602,17 +614,17 @@ read_filtered_event (bool no_switch_frame, bool ascii_required, end_time = add_emacs_time (current_emacs_time (), wait_time); } -/* Read until we get an acceptable event. */ + /* Read until we get an acceptable event. */ retry: do - val = read_char (0, 0, 0, (input_method ? Qnil : Qt), 0, + val = read_char (0, Qnil, (input_method ? Qnil : Qt), 0, NUMBERP (seconds) ? &end_time : NULL); while (INTEGERP (val) && XINT (val) == -2); /* wrong_kboard_jmpbuf */ if (BUFFERP (val)) goto retry; - /* switch-frame events are put off until after the next ASCII + /* `switch-frame' events are put off until after the next ASCII character. This is better than signaling an error just because the last characters were typed to a separate minibuffer frame, for example. Eventually, some code which can deal with @@ -1298,7 +1310,7 @@ Return t if the file exists and loads successfully. */) message_with_string ("Loading %s...", file, 1); } - record_unwind_protect (load_unwind, make_save_value (stream, 0)); + record_unwind_protect (load_unwind, make_save_pointer (stream)); record_unwind_protect (load_descriptor_unwind, load_descriptor_list); specbind (Qload_file_name, found); specbind (Qinhibit_file_name_operation, Qnil); @@ -2388,7 +2400,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) bool multibyte; *pch = 0; - load_each_byte = 0; retry: @@ -2598,7 +2609,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) return tmp; } - /* #@NUMBER is used to skip NUMBER following characters. + /* #@NUMBER is used to skip NUMBER following bytes. That's used in .elc files to skip over doc strings and function definitions. */ if (c == '@') @@ -2606,7 +2617,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) enum { extra = 100 }; ptrdiff_t i, nskip = 0; - load_each_byte = 1; /* Read a decimal integer. */ while ((c = READCHAR) >= 0 && c >= '0' && c <= '9') @@ -2616,8 +2626,15 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) nskip *= 10; nskip += c - '0'; } - UNREAD (c); - + if (nskip > 0) + /* We can't use UNREAD here, because in the code below we side-step + READCHAR. Instead, assume the first char after #@NNN occupies + a single byte, which is the case normally since it's just + a space. */ + nskip--; + else + UNREAD (c); + if (load_force_doc_strings && (EQ (readcharfun, Qget_file_char) || EQ (readcharfun, Qget_emacs_mule_file_char))) @@ -2659,19 +2676,17 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) saved_doc_string_position = file_tell (instream); /* Copy that many characters into saved_doc_string. */ + block_input (); for (i = 0; i < nskip && c >= 0; i++) - saved_doc_string[i] = c = READCHAR; + saved_doc_string[i] = c = getc (instream); + unblock_input (); saved_doc_string_length = i; } else - { - /* Skip that many characters. */ - for (i = 0; i < nskip && c >= 0; i++) - c = READCHAR; - } + /* Skip that many bytes. */ + skip_dyn_bytes (readcharfun, nskip); - load_each_byte = 0; goto retry; } if (c == '!') diff --git a/src/macros.c b/src/macros.c index 1eef9b678f4..48d23a977b1 100644 --- a/src/macros.c +++ b/src/macros.c @@ -28,7 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "window.h" #include "keyboard.h" -Lisp_Object Qexecute_kbd_macro; +static Lisp_Object Qexecute_kbd_macro; static Lisp_Object Qkbd_macro_termination_hook; /* Number of successful iterations so far @@ -78,7 +78,7 @@ macro before appending to it. */) } current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer; current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer; - message ("Defining kbd macro..."); + message1 ("Defining kbd macro..."); } else { @@ -125,7 +125,7 @@ macro before appending to it. */) Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), make_number (1), Qnil); - message ("Appending to kbd macro..."); + message1 ("Appending to kbd macro..."); } kset_defining_kbd_macro (current_kboard, Qt); @@ -172,21 +172,21 @@ each iteration of the macro. Iteration stops if LOOPFUNC returns nil. */) if (!NILP (KVAR (current_kboard, defining_kbd_macro))) { end_kbd_macro (); - message ("Keyboard macro defined"); + message1 ("Keyboard macro defined"); } if (XFASTINT (repeat) == 0) Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc); else if (XINT (repeat) > 1) { - XSETINT (repeat, XINT (repeat)-1); + XSETINT (repeat, XINT (repeat) - 1); Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc); } return Qnil; } -/* Store character c into kbd macro being defined */ +/* Store character c into kbd macro being defined. */ void store_kbd_macro_char (Lisp_Object c) diff --git a/src/makefile.w32-in b/src/makefile.w32-in index bbd9fd907b6..93f12900dde 100644 --- a/src/makefile.w32-in +++ b/src/makefile.w32-in @@ -847,7 +847,9 @@ $(BLD)/fileio.$(O) : \ $(NT_INC)/sys/file.h \ $(NT_INC)/sys/stat.h \ $(NT_INC)/unistd.h \ + $(GNU_LIB)/allocator.h \ $(BUFFER_H) \ + $(CAREADLINKAT_H) \ $(CHARACTER_H) \ $(CODING_H) \ $(CONFIG_H) \ @@ -862,6 +864,7 @@ $(BLD)/fileio.$(O) : \ $(BLD)/filelock.$(O) : \ $(SRC)/filelock.c \ + $(SRC)/w32.h \ $(NT_INC)/pwd.h \ $(NT_INC)/sys/file.h \ $(NT_INC)/sys/stat.h \ @@ -1397,11 +1400,9 @@ $(BLD)/sysdep.$(O) : \ $(NT_INC)/sys/file.h \ $(NT_INC)/sys/stat.h \ $(NT_INC)/unistd.h \ - $(GNU_LIB)/allocator.h \ $(GNU_LIB)/execinfo.h \ $(GNU_LIB)/ignore-value.h \ $(GNU_LIB)/utimens.h \ - $(CAREADLINKAT_H) \ $(CONFIG_H) \ $(C_CTYPE_H) \ $(DISPEXTERN_H) \ @@ -1492,7 +1493,6 @@ $(BLD)/unexw32.$(O) : \ $(BLD)/vm-limit.$(O) : \ $(SRC)/vm-limit.c \ - $(SRC)/mem-limits.h \ $(SRC)/w32heap.h \ $(NT_INC)/unistd.h \ $(CONFIG_H) \ diff --git a/src/marker.c b/src/marker.c index a03a0b104ca..63027d3be5e 100644 --- a/src/marker.c +++ b/src/marker.c @@ -499,11 +499,29 @@ set_marker_internal (Lisp_Object marker, Lisp_Object position, { register ptrdiff_t charpos, bytepos; - CHECK_NUMBER_COERCE_MARKER (position); - charpos = clip_to_bounds (restricted ? BUF_BEGV (b) : BUF_BEG (b), - XINT (position), - restricted ? BUF_ZV (b) : BUF_Z (b)); - bytepos = buf_charpos_to_bytepos (b, charpos); + /* Do not use CHECK_NUMBER_COERCE_MARKER because we + don't want to call buf_charpos_to_bytepos if POSITION + is a marker and so we know the bytepos already. */ + if (INTEGERP (position)) + charpos = XINT (position), bytepos = -1; + else if (MARKERP (position)) + { + charpos = XMARKER (position)->charpos; + bytepos = XMARKER (position)->bytepos; + } + else + wrong_type_argument (Qinteger_or_marker_p, position); + + charpos = clip_to_bounds + (restricted ? BUF_BEGV (b) : BUF_BEG (b), charpos, + restricted ? BUF_ZV (b) : BUF_Z (b)); + if (bytepos == -1) + bytepos = buf_charpos_to_bytepos (b, charpos); + else + bytepos = clip_to_bounds + (restricted ? BUF_BEGV_BYTE (b) : BUF_BEG_BYTE (b), + bytepos, restricted ? BUF_ZV_BYTE (b) : BUF_Z_BYTE (b)); + attach_marker (m, b, charpos, bytepos); } return marker; diff --git a/src/mem-limits.h b/src/mem-limits.h deleted file mode 100644 index 941ccf5f121..00000000000 --- a/src/mem-limits.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Includes for memory limit warnings. - Copyright (C) 1990, 1993-1996, 2001-2013 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/>. */ - -#ifdef MSDOS -#include <dpmi.h> -extern int etext; -#endif - -/* Some systems need this before <sys/resource.h>. */ -#include <sys/types.h> - -#ifdef HAVE_SYS_RESOURCE_H -# include <sys/time.h> -# include <sys/resource.h> -#else -# if HAVE_SYS_VLIMIT_H -# include <sys/vlimit.h> /* Obsolete, says glibc */ -# endif -#endif - -extern char *start_of_data (void) ATTRIBUTE_CONST; -#if USE_LSB_TAG || UINTPTR_MAX <= VAL_MAX -#define EXCEEDS_LISP_PTR(ptr) 0 -#else -#define EXCEEDS_LISP_PTR(ptr) \ - (((uintptr_t) (ptr) & ~DATA_SEG_BITS) >> VALBITS) -#endif diff --git a/src/msdos.c b/src/msdos.c index 5174bc4dfcd..ee47109d5f2 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -1,4 +1,4 @@ -/* MS-DOS specific C utilities. -*- coding: raw-text -*- +/* MS-DOS specific C utilities. -*- coding: cp850 -*- Copyright (C) 1993-1997, 1999-2013 Free Software Foundation, Inc. @@ -20,6 +20,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* Contributed by Morten Welinder */ /* New display, keyboard, and mouse control by Kim F. Storm */ +/* Note: This file MUST use a unibyte encoding, to both display the + keys on the non-US keyboard layout as their respective labels, and + provide the correct byte values for the keyboard input to inject + into Emacs. See 'struct dos_keyboard_map' below. As long as there + are only European keyboard layouts here, we are OK with DOS + codepage 850 encoding. */ + /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */ #include <config.h> @@ -1965,10 +1972,10 @@ struct dos_keyboard_map static struct dos_keyboard_map us_keyboard = { /* 0 1 2 3 4 5 */ -/* 01234567890123456789012345678901234567890 12345678901234 */ - "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ", +/* 01234567890123456789012345678901234567890 123 45678901234 */ + "`1234567890-= qwertyuiop[] asdfghjkl;'\\ \\zxcvbnm,./ ", /* 0123456789012345678901234567890123456789 012345678901234 */ - "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ", + "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| |ZXCVBNM<>? ", 0, /* no Alt-Gr key */ 0 /* no translate table */ }; @@ -1976,9 +1983,9 @@ static struct dos_keyboard_map us_keyboard = { static struct dos_keyboard_map fr_keyboard = { /* 0 1 2 3 4 5 */ /* 012 3456789012345678901234567890123456789012345678901234 */ - "ý&‚\",(-Š_€…)= azertyuiop^$ qsdfghjklm—* wxcvbnm;:! ", + "ý&‚\"'(-Š_€…)= azertyuiop^$ qsdfghjklm—* <wxcvbn,;:! ", /* 0123456789012345678901234567890123456789012345678901234 */ - " 1234567890ř+ AZERTYUIOPůś QSDFGHJKLM%ć WXCVBN?./ő ", + " 1234567890ř+ AZERTYUIOPůś QSDFGHJKLM%ć >WXCVBN?./ő ", /* 01234567 89012345678901234567890123456789012345678901234 */ " ~#{[|`\\^@]} Ď ", 0 /* no translate table */ @@ -2000,9 +2007,9 @@ static struct kbd_translate it_kbd_translate_table[] = { static struct dos_keyboard_map it_keyboard = { /* 0 1 2 3 4 5 */ /* 0 123456789012345678901234567890123456789012345678901234 */ - "\\1234567890'Ť< qwertyuiopŠ+> asdfghjkl•…— zxcvbnm,.- ", + "\\1234567890'Ť< qwertyuiopŠ+> asdfghjkl•…— <zxcvbnm,.- ", /* 01 23456789012345678901234567890123456789012345678901234 */ - "|!\"ś$%&/()=?^> QWERTYUIOP‚* ASDFGHJKL‡řő ZXCVBNM;:_ ", + "|!\"ś$%&/()=?^> QWERTYUIOP‚* ASDFGHJKL‡řő >ZXCVBNM;:_ ", /* 0123456789012345678901234567890123456789012345678901234 */ " {}~` [] @# ", it_kbd_translate_table @@ -2011,9 +2018,9 @@ static struct dos_keyboard_map it_keyboard = { static struct dos_keyboard_map dk_keyboard = { /* 0 1 2 3 4 5 */ /* 0123456789012345678901234567890123456789012345678901234 */ - "«1234567890+| qwertyuiop†~ asdfghjkl‘›' zxcvbnm,.- ", + "«1234567890+| qwertyuiop†~ asdfghjkl‘›' <zxcvbnm,.- ", /* 01 23456789012345678901234567890123456789012345678901234 */ - "ő!\"#$%&/()=?` QWERTYUIOPŹ^ ASDFGHJKL’ť* ZXCVBNM;:_ ", + "ő!\"#$%&/()=?` QWERTYUIOPŹ^ ASDFGHJKL’ť* >ZXCVBNM;:_ ", /* 0123456789012345678901234567890123456789012345678901234 */ " @ś$ {[]} | ", 0 /* no translate table */ @@ -3281,10 +3288,10 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, erasing it works correctly... */ if (! NILP (saved_echo_area_message)) message_with_string ("%s", saved_echo_area_message, 0); - message (0); + message1 (0); while (statecount--) xfree (state[statecount].screen_behind); - IT_display_cursor (1); /* turn cursor back on */ + IT_display_cursor (1); /* Turn cursor back on. */ /* Clean up any mouse events that are waiting inside Emacs event queue. These events are likely to be generated before the menu was even displayed, probably because the user pressed and released the button @@ -3339,7 +3346,7 @@ void msdos_downcase_filename (unsigned char *); /* Destructively turn backslashes into slashes. */ void -dostounix_filename (char *p) +dostounix_filename (char *p, int ignore) { msdos_downcase_filename (p); @@ -3603,7 +3610,7 @@ init_environment (int argc, char **argv, int skip_args) if (!s) s = "c:/command.com"; t = alloca (strlen (s) + 1); strcpy (t, s); - dostounix_filename (t); + dostounix_filename (t, 0); setenv ("SHELL", t, 0); /* PATH is also downcased and backslashes mirrored. */ @@ -3613,7 +3620,7 @@ init_environment (int argc, char **argv, int skip_args) /* Current directory is always considered part of MsDos's path but it is not normally mentioned. Now it is. */ strcat (strcpy (t, ".;"), s); - dostounix_filename (t); /* Not a single file name, but this should work. */ + dostounix_filename (t, 0); /* Not a single file name, but this should work. */ setenv ("PATH", t, 1); /* In some sense all dos users have root privileges, so... */ @@ -3957,14 +3964,6 @@ careadlinkat (int fd, char const *filename, return buffer; } -ssize_t -careadlinkatcwd (int fd, char const *filename, char *buffer, - size_t buffer_size) -{ - (void) fd; - return readlink (filename, buffer, buffer_size); -} - #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2 diff --git a/src/msdos.h b/src/msdos.h index 57609d62218..ee0d49464ae 100644 --- a/src/msdos.h +++ b/src/msdos.h @@ -29,7 +29,7 @@ void dos_set_window_size (int *, int *); int getdefdir (int, char*); void unixtodos_filename (char *); -void dostounix_filename (char *); +void dostounix_filename (char *, int); char *rootrelativepath (char *); void init_environment (int, char **, int); void internal_terminal_init (void); diff --git a/src/nsfns.m b/src/nsfns.m index fac61d2ab53..e4dde5fb894 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1649,9 +1649,7 @@ If omitted or nil, that stands for the selected frame's display. */) The last number is where we distinguish between the Apple and GNUstep implementations ("distributor-specific release number") and give int'ized versions of major.minor. */ - return Fcons (make_number (10), - Fcons (make_number (3), - Fcons (make_number (ns_appkit_version_int()), Qnil))); + return list3i (10, 3, ns_appkit_version_int ()); } @@ -2296,9 +2294,8 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace] getRed: &red green: &green blue: &blue alpha: &alpha]; - return list3 (make_number (lrint (red*65280)), - make_number (lrint (green*65280)), - make_number (lrint (blue*65280))); + return list3i (lrint (red * 65280), lrint (green * 65280), + lrint (blue * 65280)); } @@ -2385,11 +2382,10 @@ that stands for the selected frame's display. */) /* NS coordinate system is upside-down. Transform to screen-specific coordinates. */ - return list4 (make_number ((int) vScreen.origin.x), - make_number ((int) [screen frame].size.height - - vScreen.size.height - vScreen.origin.y), - make_number ((int) vScreen.size.width), - make_number ((int) vScreen.size.height)); + return list4i (vScreen.origin.x, + [screen frame].size.height + - vScreen.size.height - vScreen.origin.y, + vScreen.size.width, vScreen.size.height); } diff --git a/src/nsfont.m b/src/nsfont.m index 5039f0c9013..ebee363651f 100644 --- a/src/nsfont.m +++ b/src/nsfont.m @@ -75,10 +75,9 @@ static void ns_glyph_metrics (struct nsfont_info *font_info, static void ns_escape_name (char *name) { - int i =0, len =strlen (name); - for ( ; i<len; i++) - if (name[i] == ' ') - name[i] = '_'; + for (; *name; name++) + if (*name == ' ') + *name = '_'; } @@ -86,10 +85,9 @@ ns_escape_name (char *name) static void ns_unescape_name (char *name) { - int i =0, len =strlen (name); - for ( ; i<len; i++) - if (name[i] == '_') - name[i] = ' '; + for (; *name; name++) + if (*name == '_') + *name = ' '; } @@ -364,7 +362,7 @@ static NSString while CONSP (rts) { r = XCAR (XCAR (rts)); - if (!strncmp(SSDATA(r), reg, strlen(SSDATA(r)))) + if (!strncmp (SSDATA (r), reg, SBYTES (r))) { script = XCDR (XCAR (rts)); return [NSString stringWithUTF8String: SSDATA (SYMBOL_NAME (script))]; diff --git a/src/nsmenu.m b/src/nsmenu.m index b0369e76a27..22ff4dd0b53 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1110,6 +1110,8 @@ update_frame_tool_bar (FRAME_PTR f) FRAME_TOOLBAR_HEIGHT (f) = NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)]) - FRAME_NS_TITLEBAR_HEIGHT (f); + if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen. + FRAME_TOOLBAR_HEIGHT (f) = 0; unblock_input (); } @@ -1440,7 +1442,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) unwind_data->pool = pool; unwind_data->dialog = dialog; - record_unwind_protect (pop_down_menu, make_save_value (unwind_data, 0)); + record_unwind_protect (pop_down_menu, make_save_pointer (unwind_data)); popup_activated_flag = 1; tem = [dialog runDialogAt: p]; unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */ diff --git a/src/nsselect.m b/src/nsselect.m index 903448ce0a5..49380f87945 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -117,7 +117,7 @@ clean_local_selection_data (Lisp_Object obj) if (size == 1) return clean_local_selection_data (AREF (obj, 0)); - copy = Fmake_vector (make_number (size), Qnil); + copy = make_uninit_vector (size); for (i = 0; i < size; i++) ASET (copy, i, clean_local_selection_data (AREF (obj, i))); return copy; diff --git a/src/nsterm.h b/src/nsterm.h index 0cf4aa60d08..41dbaf3c0f7 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -42,6 +42,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #ifndef MAC_OS_X_VERSION_10_8 #define MAC_OS_X_VERSION_10_8 1080 #endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#define HAVE_NATIVE_FS +#endif + #endif /* NS_IMPL_COCOA */ #ifdef __OBJC__ @@ -88,6 +93,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ int tibar_height, tobar_height, bwidth; int maximized_width, maximized_height; NSWindow *nonfs_window; + BOOL fs_is_native; @public struct frame *emacsframe; int rows, cols; @@ -115,6 +121,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ - (void) handleFS; - (void) setFSValue: (int)value; - (void) toggleFullScreen: (id) sender; +- (BOOL) fsIsNative; +- (BOOL) isFullscreen; +#ifdef HAVE_NATIVE_FS +- (void) updateCollectionBehaviour; +#endif #ifdef NS_IMPL_GNUSTEP /* Not declared, but useful. */ diff --git a/src/nsterm.m b/src/nsterm.m index 48efac3f70b..1f09e031592 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -69,11 +69,6 @@ int term_trace_num = 0; #define NSTRACE(x) #endif -#if defined (NS_IMPL_COCOA) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 -#define NEW_STYLE_FS -#endif - extern NSString *NSMenuDidBeginTrackingNotification; /* ========================================================================== @@ -224,6 +219,7 @@ static int n_emacs_events_pending = 0; static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; static BOOL ns_do_open_file = NO; +static BOOL ns_last_use_native_fullscreen; static struct { struct input_event *q; @@ -1000,11 +996,8 @@ ns_raise_frame (struct frame *f) NSView *view = FRAME_NS_VIEW (f); check_ns (); block_input (); - FRAME_SAMPLE_VISIBILITY (f); if (FRAME_VISIBLE_P (f)) - { - [[view window] makeKeyAndOrderFront: NSApp]; - } + [[view window] makeKeyAndOrderFront: NSApp]; unblock_input (); } @@ -1093,16 +1086,16 @@ x_make_frame_visible (struct frame *f) if (!FRAME_VISIBLE_P (f)) { EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); - f->async_visible = 1; + + SET_FRAME_VISIBLE (f, 1); ns_raise_frame (f); -#ifdef NEW_STYLE_FS /* Making a new frame from a fullscreen frame will make the new frame fullscreen also. So skip handleFS as this will print an error. */ - if (f->want_fullscreen == FULLSCREEN_BOTH - && ([[view window] styleMask] & NSFullScreenWindowMask) != 0) + if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH + && [view isFullscreen]) return; -#endif + if (f->want_fullscreen != FULLSCREEN_NONE) { block_input (); @@ -1123,8 +1116,8 @@ x_make_frame_invisible (struct frame *f) NSTRACE (x_make_frame_invisible); check_ns (); [[view window] orderOut: NSApp]; - f->async_visible = 0; - f->async_iconified = 0; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 0); } @@ -1294,7 +1287,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); /* If we have a toolbar, take its height into account. */ - if (tb) + if (tb && ! [view isFullscreen]) /* NOTE: previously this would generate wrong result if toolbar not yet displayed and fixing toolbar_height=32 helped, but now (200903) seems no longer needed */ @@ -1305,8 +1298,10 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) FRAME_TOOLBAR_HEIGHT (f) = 0; wr.size.width = pixelwidth + f->border_width; - wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f) - + FRAME_TOOLBAR_HEIGHT (f); + wr.size.height = pixelheight; + if (! [view isFullscreen]) + wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f) + + FRAME_TOOLBAR_HEIGHT (f); /* Do not try to constrain to this screen. We may have multiple screens, and want Emacs to span those. Constraining to screen @@ -1354,9 +1349,10 @@ ns_fullscreen_hook (FRAME_PTR f) { EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); - if (! f->async_visible) return; -#ifndef NEW_STYLE_FS - if (f->want_fullscreen == FULLSCREEN_BOTH) + if (!FRAME_VISIBLE_P (f)) + return; + + if (! [view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH) { /* Old style fs don't initiate correctly if created from init/default-frame alist, so use a timer (not nice...). @@ -1366,7 +1362,6 @@ ns_fullscreen_hook (FRAME_PTR f) userInfo: nil repeats: NO]; return; } -#endif block_input (); [view handleFS]; @@ -3369,6 +3364,30 @@ ns_send_appdefined (int value) } } +#ifdef HAVE_NATIVE_FS +static void +check_native_fs () +{ + Lisp_Object frame, tail; + + if (ns_last_use_native_fullscreen == ns_use_native_fullscreen) + return; + + ns_last_use_native_fullscreen = ns_use_native_fullscreen; + + /* Clear the mouse-moved flag for every frame on this display. */ + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_NS_P (f)) + { + EmacsView *view = FRAME_NS_VIEW (f); + [view updateCollectionBehaviour]; + } + } +} +#endif + static int ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) /* -------------------------------------------------------------------------- @@ -3382,6 +3401,10 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) /* NSTRACE (ns_read_socket); */ +#ifdef HAVE_NATIVE_FS + check_native_fs (); +#endif + if ([NSApp modalWindow] != nil) return -1; @@ -3459,6 +3482,10 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, /* NSTRACE (ns_select); */ +#ifdef HAVE_NATIVE_FS + check_native_fs (); +#endif + if (hold_event_q.nr > 0) { /* We already have events pending. */ @@ -3677,7 +3704,7 @@ ns_set_vertical_scroll_bar (struct window *window, } bar = [[EmacsScroller alloc] initFrame: r window: win]; - wset_vertical_scroll_bar (window, make_save_value (bar, 0)); + wset_vertical_scroll_bar (window, make_save_pointer (bar)); } else { @@ -4238,11 +4265,9 @@ ns_term_init (Lisp_Object display_name) NSColorPboardType, NSFontPboardType, nil] retain]; -#ifndef NEW_STYLE_FS /* If fullscreen is in init/default-frame-alist, focus isn't set right for fullscreen windows, so set this. */ [NSApp activateIgnoringOtherApps:YES]; -#endif [NSApp run]; ns_do_open_file = YES; @@ -5391,10 +5416,10 @@ not_in_argv (NSString *arg) { NSWindow *window = [self window]; NSRect wr = [window frame]; -#ifdef NS_IMPL_GNUSTEP - int extra = 3; -#else int extra = 0; + int gsextra = 0; +#ifdef NS_IMPL_GNUSTEP + gsextra = 3; #endif int oldc = cols, oldr = rows; @@ -5402,23 +5427,24 @@ not_in_argv (NSString *arg) oldh = FRAME_PIXEL_HEIGHT (emacsframe); int neww, newh; - cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + extra); + cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + gsextra); if (cols < MINWIDTH) cols = MINWIDTH; - rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES - (emacsframe, wr.size.height - - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + extra - - FRAME_TOOLBAR_HEIGHT (emacsframe)); + if (! [self isFullscreen]) + { + extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + + FRAME_TOOLBAR_HEIGHT (emacsframe) - gsextra; + } + + rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, wr.size.height - extra); if (rows < MINHEIGHT) rows = MINHEIGHT; neww = (int)wr.size.width - emacsframe->border_width; - newh = ((int)wr.size.height - - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) - - FRAME_TOOLBAR_HEIGHT (emacsframe)); + newh = (int)wr.size.height - extra; if (oldr != rows || oldc != cols || neww != oldw || newh != oldh) { @@ -5436,6 +5462,12 @@ not_in_argv (NSString *arg) - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize /* normalize frame to gridded text size */ { + int extra = 0; + int gsextra = 0; +#ifdef NS_IMPL_GNUSTEP + gsextra = 3; +#endif + NSTRACE (windowWillResize); /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */ @@ -5453,22 +5485,12 @@ not_in_argv (NSString *arg) maximized_width = maximized_height = -1; cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, -#ifdef NS_IMPL_GNUSTEP - frameSize.width + 3); -#else - frameSize.width); -#endif + frameSize.width + gsextra); if (cols < MINWIDTH) cols = MINWIDTH; - rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, frameSize.height -#ifdef NS_IMPL_GNUSTEP - - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + 3 - - FRAME_TOOLBAR_HEIGHT (emacsframe)); -#else - - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) - - FRAME_TOOLBAR_HEIGHT (emacsframe)); -#endif + rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, + frameSize.height - extra); if (rows < MINHEIGHT) rows = MINHEIGHT; #ifdef NS_IMPL_COCOA @@ -5511,12 +5533,13 @@ not_in_argv (NSString *arg) - (void)windowDidResize: (NSNotification *)notification { - -#if !defined (NEW_STYLE_FS) && ! defined (NS_IMPL_GNUSTEP) - NSWindow *theWindow = [notification object]; - /* We can get notification on the non-FS window when in fullscreen mode. */ - if ([self window] != theWindow) return; -#endif + if (! [self fsIsNative]) + { + NSWindow *theWindow = [notification object]; + /* We can get notification on the non-FS window when in + fullscreen mode. */ + if ([self window] != theWindow) return; + } #ifdef NS_IMPL_GNUSTEP NSWindow *theWindow = [notification object]; @@ -5632,6 +5655,11 @@ not_in_argv (NSString *arg) scrollbarsNeedingUpdate = 0; fs_state = FULLSCREEN_NONE; fs_before_fs = next_maximized = -1; +#ifdef HAVE_NATIVE_FS + fs_is_native = ns_use_native_fullscreen; +#else + fs_is_native = NO; +#endif maximized_width = maximized_height = -1; nonfs_window = nil; @@ -5658,7 +5686,7 @@ not_in_argv (NSString *arg) backing: NSBackingStoreBuffered defer: YES]; -#ifdef NEW_STYLE_FS +#ifdef HAVE_NATIVE_FS [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; #endif @@ -5824,13 +5852,14 @@ not_in_argv (NSString *arg) NSTRACE (windowDidDeminiaturize); if (!emacsframe->output_data.ns) return; - emacsframe->async_iconified = 0; - emacsframe->async_visible = 1; + + SET_FRAME_ICONIFIED (emacsframe, 0); + SET_FRAME_VISIBLE (emacsframe, 1); windows_or_buffers_changed++; if (emacs_event) { - emacs_event->kind = ICONIFY_EVENT; + emacs_event->kind = DEICONIFY_EVENT; EV_TRAILER ((id)nil); } } @@ -5841,7 +5870,8 @@ not_in_argv (NSString *arg) NSTRACE (windowDidExpose); if (!emacsframe->output_data.ns) return; - emacsframe->async_visible = 1; + + SET_FRAME_VISIBLE (emacsframe, 1); SET_FRAME_GARBAGED (emacsframe); if (send_appdefined) @@ -5855,8 +5885,8 @@ not_in_argv (NSString *arg) if (!emacsframe->output_data.ns) return; - emacsframe->async_iconified = 1; - emacsframe->async_visible = 0; + SET_FRAME_ICONIFIED (emacsframe, 1); + SET_FRAME_VISIBLE (emacsframe, 0); if (emacs_event) { @@ -5865,6 +5895,15 @@ not_in_argv (NSString *arg) } } +#ifdef HAVE_NATIVE_FS +- (NSApplicationPresentationOptions)window:(NSWindow *)window + willUseFullScreenPresentationOptions: + (NSApplicationPresentationOptions)proposedOptions +{ + return proposedOptions|NSApplicationPresentationAutoHideToolbar; +} +#endif + - (void)windowWillEnterFullScreen:(NSNotification *)notification { fs_before_fs = fs_state; @@ -5873,17 +5912,13 @@ not_in_argv (NSString *arg) - (void)windowDidEnterFullScreen:(NSNotification *)notification { [self setFSValue: FULLSCREEN_BOTH]; -#ifdef NEW_STYLE_FS - // Fix bad background. - if ([toolbar isVisible]) + if (! [self fsIsNative]) { - [toolbar setVisible:NO]; - [toolbar setVisible:YES]; + [self windowDidBecomeKey:notification]; + [nonfs_window orderOut:self]; } -#else - [self windowDidBecomeKey:notification]; - [nonfs_window orderOut:self]; -#endif + else if (! FRAME_EXTERNAL_TOOL_BAR (emacsframe)) + [toolbar setVisible:NO]; } - (void)windowWillExitFullScreen:(NSNotification *)notification @@ -5896,24 +5931,76 @@ not_in_argv (NSString *arg) { [self setFSValue: fs_before_fs]; fs_before_fs = -1; + [self updateCollectionBehaviour]; + if (FRAME_EXTERNAL_TOOL_BAR (emacsframe)) + { + [toolbar setVisible:YES]; + update_frame_tool_bar (emacsframe); + [self updateFrameSize:YES]; + [[self window] display]; + } + else + [toolbar setVisible:NO]; + if (next_maximized != -1) [[self window] performZoom:self]; } -- (void)toggleFullScreen: (id)sender +- (BOOL)fsIsNative +{ + return fs_is_native; +} + +- (BOOL)isFullscreen { -#ifdef NEW_STYLE_FS - [[self window] toggleFullScreen:sender]; + if (! fs_is_native) return nonfs_window != nil; +#ifdef HAVE_NATIVE_FS + return ([[self window] styleMask] & NSFullScreenWindowMask) != 0; #else - NSWindow *w = [self window], *fw; - BOOL onFirstScreen = [[w screen] - isEqual:[[NSScreen screens] objectAtIndex:0]]; - struct frame *f = emacsframe; + return NO; +#endif +} + +#ifdef HAVE_NATIVE_FS +- (void)updateCollectionBehaviour +{ + if (! [self isFullscreen]) + { + NSWindow *win = [self window]; + NSWindowCollectionBehavior b = [win collectionBehavior]; + if (ns_use_native_fullscreen) + b |= NSWindowCollectionBehaviorFullScreenPrimary; + else + b &= ~NSWindowCollectionBehaviorFullScreenPrimary; + + [win setCollectionBehavior: b]; + fs_is_native = ns_use_native_fullscreen; + } +} +#endif + +- (void)toggleFullScreen: (id)sender +{ + NSWindow *w, *fw; + BOOL onFirstScreen; + struct frame *f; NSSize sz; - NSRect r, wr = [w frame]; - NSColor *col = ns_lookup_indexed_color (NS_FACE_BACKGROUND - (FRAME_DEFAULT_FACE (f)), - f); + NSRect r, wr; + NSColor *col; + + if (fs_is_native) + { + [[self window] toggleFullScreen:sender]; + return; + } + + w = [self window]; + onFirstScreen = [[w screen] isEqual:[[NSScreen screens] objectAtIndex:0]]; + f = emacsframe; + wr = [w frame]; + col = ns_lookup_indexed_color (NS_FACE_BACKGROUND + (FRAME_DEFAULT_FACE (f)), + f); sz.width = FRAME_COLUMN_WIDTH (f); sz.height = FRAME_LINE_HEIGHT (f); @@ -5956,7 +6043,6 @@ not_in_argv (NSString *arg) FRAME_NS_TITLEBAR_HEIGHT (f) = 0; tobar_height = FRAME_TOOLBAR_HEIGHT (f); FRAME_TOOLBAR_HEIGHT (f) = 0; - FRAME_EXTERNAL_TOOL_BAR (f) = 0; nonfs_window = w; @@ -5993,17 +6079,16 @@ not_in_argv (NSString *arg) f->border_width = bwidth; FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height; - FRAME_TOOLBAR_HEIGHT (f) = tobar_height; - if (tobar_height) - FRAME_EXTERNAL_TOOL_BAR (f) = 1; + if (FRAME_EXTERNAL_TOOL_BAR (f)) + FRAME_TOOLBAR_HEIGHT (f) = tobar_height; [self windowWillExitFullScreen:nil]; [fw setFrame: [w frame] display:YES animate:YES]; [fw close]; [w makeKeyAndOrderFront:NSApp]; [self windowDidExitFullScreen:nil]; + [self updateFrameSize:YES]; } -#endif } - (void)handleFS @@ -7157,6 +7242,18 @@ allowing it to be used at a lower level for accented character entry."); Only works on OSX 10.6 or later. */); ns_auto_hide_menu_bar = Qnil; + DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen, + doc: /*Non-nil means to use native fullscreen on OSX >= 10.7. +Nil means use fullscreen the old (< 10.7) way. The old way works better with +multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7. +Default is t for OSX >= 10.7, nil otherwise. */); +#ifdef HAVE_NATIVE_FS + ns_use_native_fullscreen = YES; +#else + ns_use_native_fullscreen = NO; +#endif + ns_last_use_native_fullscreen = ns_use_native_fullscreen; + /* TODO: move to common code */ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, doc: /* Which toolkit scroll bars Emacs uses, if any. diff --git a/src/pre-crt0.c b/src/pre-crt0.c deleted file mode 100644 index ea5736eba2a..00000000000 --- a/src/pre-crt0.c +++ /dev/null @@ -1,10 +0,0 @@ -/* This file is loaded before crt0.o on machines where we do not - remap part of the data space into text space in unexec. - On these machines, there is no problem with standard crt0.o's - that make environ an initialized variable. However, we do - need to make sure the label data_start exists anyway. */ - -/* Create a label to appear at the beginning of data space. */ - -int data_start = 0; - diff --git a/src/print.c b/src/print.c index 62009e17686..74fab475ac0 100644 --- a/src/print.c +++ b/src/print.c @@ -84,7 +84,7 @@ static ptrdiff_t print_number_index; static void print_interval (INTERVAL interval, Lisp_Object printcharfun); /* GDB resets this to zero on W32 to disable OutputDebugString calls. */ -int print_output_debug_flag EXTERNALLY_VISIBLE = 1; +bool print_output_debug_flag EXTERNALLY_VISIBLE = 1; /* Low level output routines for characters and strings. */ @@ -101,8 +101,9 @@ int print_output_debug_flag EXTERNALLY_VISIBLE = 1; ptrdiff_t old_point = -1, start_point = -1; \ ptrdiff_t old_point_byte = -1, start_point_byte = -1; \ ptrdiff_t specpdl_count = SPECPDL_INDEX (); \ - int free_print_buffer = 0; \ - int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \ + bool free_print_buffer = 0; \ + bool multibyte \ + = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \ Lisp_Object original #define PRINTPREPARE \ @@ -240,7 +241,7 @@ printchar (unsigned int ch, Lisp_Object fun) } else { - int multibyte_p + bool multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); setup_echo_area_for_printing (multibyte_p); @@ -289,7 +290,7 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte, here, that's the reason we don't call printchar to do the job. */ int i; - int multibyte_p + bool multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); setup_echo_area_for_printing (multibyte_p); @@ -507,10 +508,10 @@ temp_output_buffer_setup (const char *bufname) specbind (Qstandard_output, buf); } -static void print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag); -static void print_preprocess (Lisp_Object obj); -static void print_preprocess_string (INTERVAL interval, Lisp_Object arg); -static void print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag); +static void print (Lisp_Object, Lisp_Object, bool); +static void print_preprocess (Lisp_Object); +static void print_preprocess_string (INTERVAL, Lisp_Object); +static void print_object (Lisp_Object, Lisp_Object, bool); DEFUN ("terpri", Fterpri, Sterpri, 0, 1, 0, doc: /* Output a newline to stream PRINTCHARFUN. @@ -726,9 +727,9 @@ to make it write to the debugging output. */) /* This function is never called. Its purpose is to prevent print_output_debug_flag from being optimized away. */ -extern void debug_output_compilation_hack (int) EXTERNALLY_VISIBLE; +extern void debug_output_compilation_hack (bool) EXTERNALLY_VISIBLE; void -debug_output_compilation_hack (int x) +debug_output_compilation_hack (bool x) { print_output_debug_flag = x; } @@ -966,7 +967,7 @@ float_to_string (char *buf, double data) static char const NaN_string[] = "0.0e+NaN"; int i; union { double d; char c[sizeof (double)]; } u_data, u_minus_zero; - int negative = 0; + bool negative = 0; u_data.d = data; u_minus_zero.d = - 0.0; for (i = 0; i < sizeof (double); i++) @@ -1063,7 +1064,7 @@ float_to_string (char *buf, double data) static void -print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag) +print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) { new_backquote_output = 0; @@ -1313,7 +1314,7 @@ print_prune_string_charset (Lisp_Object string) } static void -print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag) +print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) { char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), @@ -1395,8 +1396,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag ptrdiff_t size_byte; /* 1 means we must ensure that the next character we output cannot be taken as part of a hex character escape. */ - int need_nonhex = 0; - int multibyte = STRING_MULTIBYTE (obj); + bool need_nonhex = 0; + bool multibyte = STRING_MULTIBYTE (obj); GCPRO1 (obj); @@ -1507,10 +1508,10 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag case Lisp_Symbol: { - register int confusing; - register unsigned char *p = SDATA (SYMBOL_NAME (obj)); - register unsigned char *end = p + SBYTES (SYMBOL_NAME (obj)); - register int c; + bool confusing; + unsigned char *p = SDATA (SYMBOL_NAME (obj)); + unsigned char *end = p + SBYTES (SYMBOL_NAME (obj)); + int c; ptrdiff_t i, i_byte; ptrdiff_t size_byte; Lisp_Object name; @@ -1766,7 +1767,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag { int len; strout ("#<window ", -1, -1, printcharfun); - len = sprintf (buf, "%d", XWINDOW (obj)->sequence_number); + len = sprintf (buf, "%p", XWINDOW (obj)); strout (buf, len, len, printcharfun); if (!NILP (XWINDOW (obj)->buffer)) { diff --git a/src/process.c b/src/process.c index d56819da67a..044e0c54772 100644 --- a/src/process.c +++ b/src/process.c @@ -146,13 +146,13 @@ Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs; Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime; Lisp_Object QCname, QCtype; -/* Non-zero if keyboard input is on hold, zero otherwise. */ +/* True if keyboard input is on hold, zero otherwise. */ -static int kbd_is_on_hold; +static bool kbd_is_on_hold; /* Nonzero means don't run process sentinels. This is used when exiting. */ -int inhibit_sentinels; +bool inhibit_sentinels; #ifdef subprocesses @@ -180,10 +180,6 @@ static Lisp_Object Qlast_nonmenu_event; #define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial)) #define SERIALCONN1_P(p) (EQ (p->type, Qserial)) -#ifndef HAVE_H_ERRNO -extern int h_errno; -#endif - /* Number of events of change of status of a process. */ static EMACS_INT process_tick; /* Number of events for which the user or sentinel has been notified. */ @@ -238,9 +234,9 @@ static EMACS_INT update_tick; static int process_output_delay_count; -/* Non-zero if any process has non-nil read_output_skip. */ +/* True if any process has non-nil read_output_skip. */ -static int process_output_skip; +static bool process_output_skip; #else #define process_output_delay_count 0 @@ -248,7 +244,7 @@ static int process_output_skip; static void create_process (Lisp_Object, char **, Lisp_Object); #ifdef USABLE_SIGIO -static int keyboard_bit_set (SELECT_TYPE *); +static bool keyboard_bit_set (SELECT_TYPE *); #endif static void deactivate_process (Lisp_Object); static void status_notify (struct Lisp_Process *); @@ -670,7 +666,7 @@ status_convert (int w) and store them individually through the three pointers. */ static void -decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, int *coredump) +decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, bool *coredump) { Lisp_Object tem; @@ -697,7 +693,8 @@ status_message (struct Lisp_Process *p) { Lisp_Object status = p->status; Lisp_Object symbol; - int code, coredump; + int code; + bool coredump; Lisp_Object string, string2; decode_status (status, &symbol, &code, &coredump); @@ -1774,7 +1771,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) sigset_t blocked; /* Use volatile to protect variables from being clobbered by vfork. */ volatile int forkin, forkout; - volatile int pty_flag = 0; + volatile bool pty_flag = 0; volatile Lisp_Object lisp_pty_name = Qnil; volatile Lisp_Object encoded_current_dir; @@ -2063,7 +2060,7 @@ void create_pty (Lisp_Object process) { int inchannel, outchannel; - int pty_flag = 0; + bool pty_flag = 0; inchannel = outchannel = -1; @@ -3005,8 +3002,9 @@ usage: (make-network-process &rest ARGS) */) Lisp_Object tem; Lisp_Object name, buffer, host, service, address; Lisp_Object filter, sentinel; - int is_non_blocking_client = 0; - int is_server = 0, backlog = 5; + bool is_non_blocking_client = 0; + bool is_server = 0; + int backlog = 5; int socktype; int family = -1; @@ -3676,7 +3674,7 @@ format; see the description of ADDRESS in `make-network-process'. */) struct ifreq *ifreq; void *buf = NULL; ptrdiff_t buf_size = 512; - int s, i; + int s; Lisp_Object res; s = socket (AF_INET, SOCK_STREAM, 0); @@ -3714,7 +3712,6 @@ format; see the description of ADDRESS in `make-network-process'. */) int len = sizeof (*ifreq); #endif char namebuf[sizeof (ifq->ifr_name) + 1]; - i += len; ifreq = (struct ifreq *) ((char *) ifreq + len); if (ifq->ifr_addr.sa_family != AF_INET) @@ -3824,7 +3821,7 @@ FLAGS is the current flags of the interface. */) Lisp_Object res = Qnil; Lisp_Object elt; int s; - int any = 0; + bool any = 0; #if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \ && defined HAVE_GETIFADDRS && defined LLADDR) struct ifaddrs *ifap; @@ -4114,7 +4111,7 @@ Return non-nil if we received any output before the timeout expired. */) /* Accept a connection for server process SERVER on CHANNEL. */ -static int connect_counter = 0; +static EMACS_INT connect_counter = 0; static void server_accept_connection (Lisp_Object server, int channel) @@ -4353,7 +4350,7 @@ wait_reading_process_output_1 (void) process. The return value is true if we read some input from that process. - If JUST_WAIT_PROC is non-nil, handle only output from WAIT_PROC + If JUST_WAIT_PROC is nonzero, handle only output from WAIT_PROC (suspending output from other processes). A negative value means don't run any timers either. @@ -4361,22 +4358,23 @@ wait_reading_process_output_1 (void) received input from that process before the timeout elapsed. Otherwise, return true if we received input from any process. */ -int +bool wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, struct Lisp_Process *wait_proc, int just_wait_proc) { - register int channel, nfds; + int channel, nfds; SELECT_TYPE Available; SELECT_TYPE Writeok; - int check_write; - int check_delay, no_avail; + bool check_write; + int check_delay; + bool no_avail; int xerrno; Lisp_Object proc; EMACS_TIME timeout, end_time; int wait_channel = -1; - int got_some_input = 0; + bool got_some_input = 0; ptrdiff_t count = SPECPDL_INDEX (); eassert (wait_proc == NULL @@ -4389,7 +4387,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit) && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit))) - message ("Blocking call to accept-process-output with quit inhibited!!"); + message1 ("Blocking call to accept-process-output with quit inhibited!!"); /* If wait_proc is a process to watch, set wait_channel accordingly. */ if (wait_proc != NULL) @@ -4417,7 +4415,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { - int timeout_reduced_for_timers = 0; + bool timeout_reduced_for_timers = 0; /* If calling from keyboard input, do not quit since we want to return C-g as an input character. @@ -4796,7 +4794,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, unsigned old_timers_run = timers_run; struct buffer *old_buffer = current_buffer; Lisp_Object old_window = selected_window; - int leave = 0; + bool leave = 0; if (detect_input_pending_run_timers (do_display)) { @@ -5111,7 +5109,7 @@ read_process_output (Lisp_Object proc, register int channel) else #endif { - int buffered = 0 <= proc_buffered_char[channel]; + bool buffered = 0 <= proc_buffered_char[channel]; if (buffered) { chars[carryover] = proc_buffered_char[channel]; @@ -5427,7 +5425,7 @@ read_process_output (Lisp_Object proc, register int channel) static void write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj, - const char *buf, ptrdiff_t len, int front) + const char *buf, ptrdiff_t len, bool front) { ptrdiff_t offset; Lisp_Object entry, obj; @@ -5452,10 +5450,10 @@ write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj, } /* Remove the first element in the write_queue of process P, put its - contents in OBJ, BUF and LEN, and return non-zero. If the - write_queue is empty, return zero. */ + contents in OBJ, BUF and LEN, and return true. If the + write_queue is empty, return false. */ -static int +static bool write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj, const char **buf, ptrdiff_t *len) { @@ -5729,7 +5727,7 @@ Output from processes can arrive in between bunches. */) if (XINT (start) < GPT && XINT (end) > GPT) move_gap_both (XINT (start), start_byte); - send_process (proc, (char *) BYTE_POS_ADDR (start_byte), + send_process (proc, (char *) BYTE_POS_ADDR (start_byte), end_byte - start_byte, Fcurrent_buffer ()); return Qnil; @@ -5816,7 +5814,7 @@ return t unconditionally. */) If CURRENT_GROUP is lambda, that means send to the process group that currently owns the terminal, but only if it is NOT the shell itself. - If NOMSG is zero, insert signal-announcements into process's buffers + If NOMSG is false, insert signal-announcements into process's buffers right away. If we can, we try to signal PROCESS by sending control characters @@ -5825,12 +5823,12 @@ return t unconditionally. */) static void process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, - int nomsg) + bool nomsg) { Lisp_Object proc; - register struct Lisp_Process *p; + struct Lisp_Process *p; pid_t gid; - int no_pgrp = 0; + bool no_pgrp = 0; proc = get_process (process); p = XPROCESS (proc); @@ -6323,7 +6321,7 @@ handle_child_signal (int sig) /* If process has terminated, stop waiting for its output. */ if (WIFSIGNALED (status) || WIFEXITED (status)) { - int clear_desc_flag = 0; + bool clear_desc_flag = 0; p->alive = 0; if (p->infd >= 0) clear_desc_flag = 1; @@ -6663,10 +6661,10 @@ delete_gpm_wait_descriptor (int desc) # ifdef USABLE_SIGIO -/* Return nonzero if *MASK has a bit set +/* Return true if *MASK has a bit set that corresponds to one of the keyboard input descriptors. */ -static int +static bool keyboard_bit_set (fd_set *mask) { int fd; @@ -6716,7 +6714,7 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, Return true if we received input from any process. */ -int +bool wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -6748,7 +6746,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { - int timeout_reduced_for_timers = 0; + bool timeout_reduced_for_timers = 0; SELECT_TYPE waitchannels; int xerrno; @@ -7105,9 +7103,9 @@ unhold_keyboard_input (void) kbd_is_on_hold = 0; } -/* Return non-zero if keyboard input is on hold, zero otherwise. */ +/* Return true if keyboard input is on hold, zero otherwise. */ -int +bool kbd_on_hold_p (void) { return kbd_is_on_hold; diff --git a/src/process.h b/src/process.h index 0dc35f42993..7d13a8e5042 100644 --- a/src/process.h +++ b/src/process.h @@ -162,7 +162,7 @@ struct Lisp_Process gnutls_anon_client_credentials_t gnutls_anon_cred; int gnutls_log_level; int gnutls_handshakes_tried; - int gnutls_p; + unsigned int gnutls_p : 1; #endif }; @@ -188,9 +188,9 @@ pset_gnutls_cred_type (struct Lisp_Process *p, Lisp_Object val) } #endif -/* Nonzero means don't run process sentinels. This is used +/* True means don't run process sentinels. This is used when exiting. */ -extern int inhibit_sentinels; +extern bool inhibit_sentinels; extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname; extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime; @@ -212,7 +212,7 @@ extern Lisp_Object system_process_attributes (Lisp_Object); extern void hold_keyboard_input (void); extern void unhold_keyboard_input (void); -extern int kbd_on_hold_p (void); +extern bool kbd_on_hold_p (void); typedef void (*fd_callback) (int fd, void *data); diff --git a/src/profiler.c b/src/profiler.c index f6503cf182e..85d9c1ca88a 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -560,7 +560,7 @@ hashfn_profiler (struct hash_table_test *ht, Lisp_Object bt) ? XHASH (XCDR (XCDR (f))) : XHASH (f)); hash = sxhash_combine (hash, hash1); } - return (hash & INTMASK); + return SXHASH_REDUCE (hash); } else return XHASH (bt); diff --git a/src/ralloc.c b/src/ralloc.c index ec1ac40414c..13fd65cbb0c 100644 --- a/src/ralloc.c +++ b/src/ralloc.c @@ -52,10 +52,6 @@ extern size_t __malloc_extra_blocks; #include "getpagesize.h" -typedef size_t SIZE; -typedef void *POINTER; -#define NIL ((POINTER) 0) - /* A flag to indicate whether we have initialized ralloc yet. For Emacs's sake, please do not make this local to malloc_init; on some machines, the dumping procedure makes all static variables @@ -72,14 +68,14 @@ static void r_alloc_init (void); /* Declarations for working with the malloc, ralloc, and system breaks. */ /* Function to set the real break value. */ -POINTER (*real_morecore) (ptrdiff_t); +void *(*real_morecore) (ptrdiff_t); /* The break value, as seen by malloc. */ -static POINTER virtual_break_value; +static void *virtual_break_value; /* The address of the end of the last data in use by ralloc, including relocatable blocs as well as malloc data. */ -static POINTER break_value; +static void *break_value; /* This is the size of a page. We round memory requests to this boundary. */ static int page_size; @@ -92,17 +88,17 @@ static int extra_bytes; by changing the definition of PAGE. */ #define PAGE (getpagesize ()) #define ROUNDUP(size) (((size_t) (size) + page_size - 1) \ - & ~((size_t)(page_size - 1))) + & ~((size_t) (page_size - 1))) #define MEM_ALIGN sizeof (double) -#define MEM_ROUNDUP(addr) (((size_t)(addr) + MEM_ALIGN - 1) \ +#define MEM_ROUNDUP(addr) (((size_t) (addr) + MEM_ALIGN - 1) \ & ~(MEM_ALIGN - 1)) /* The hook `malloc' uses for the function which gets more space from the system. */ #ifndef SYSTEM_MALLOC -extern POINTER (*__morecore) (ptrdiff_t); +extern void *(*__morecore) (ptrdiff_t); #endif @@ -131,13 +127,13 @@ typedef struct heap struct heap *next; struct heap *prev; /* Start of memory range of this heap. */ - POINTER start; + void *start; /* End of memory range of this heap. */ - POINTER end; + void *end; /* Start of relocatable data in this heap. */ - POINTER bloc_start; + void *bloc_start; /* Start of unused space in this heap. */ - POINTER free; + void *free; /* First bloc in this heap. */ struct bp *first_bloc; /* Last bloc in this heap. */ @@ -159,7 +155,7 @@ static heap_ptr first_heap, last_heap; The data blocks abut each other; if b->next is non-nil, then b->data + b->size == b->next->data. - An element with variable==NIL denotes a freed block, which has not yet + An element with variable==NULL denotes a freed block, which has not yet been collected. They may only appear while r_alloc_freeze_level > 0, and will be freed when the arena is thawed. Currently, these blocs are not reusable, while the arena is frozen. Very inefficient. */ @@ -168,10 +164,10 @@ typedef struct bp { struct bp *next; struct bp *prev; - POINTER *variable; - POINTER data; - SIZE size; - POINTER new_data; /* temporarily used for relocation */ + void **variable; + void *data; + size_t size; + void *new_data; /* temporarily used for relocation */ struct heap *heap; /* Heap this bloc is in. */ } *bloc_ptr; @@ -192,7 +188,7 @@ static int r_alloc_freeze_level; /* Find the heap that ADDRESS falls within. */ static heap_ptr -find_heap (POINTER address) +find_heap (void *address) { heap_ptr heap; @@ -223,11 +219,11 @@ find_heap (POINTER address) Return the address of the space if all went well, or zero if we couldn't allocate the memory. */ -static POINTER -obtain (POINTER address, SIZE size) +static void * +obtain (void *address, size_t size) { heap_ptr heap; - SIZE already_available; + size_t already_available; /* Find the heap that ADDRESS falls within. */ for (heap = last_heap; heap; heap = heap->prev) @@ -253,19 +249,19 @@ obtain (POINTER address, SIZE size) get more space. */ if (heap == NIL_HEAP) { - POINTER new = (*real_morecore)(0); - SIZE get; + void *new = real_morecore (0); + size_t get; - already_available = (char *)last_heap->end - (char *)address; + already_available = (char *) last_heap->end - (char *) address; if (new != last_heap->end) { /* Someone else called sbrk. Make a new heap. */ heap_ptr new_heap = (heap_ptr) MEM_ROUNDUP (new); - POINTER bloc_start = (POINTER) MEM_ROUNDUP ((POINTER)(new_heap + 1)); + void *bloc_start = (void *) MEM_ROUNDUP ((void *) (new_heap + 1)); - if ((*real_morecore) ((char *) bloc_start - (char *) new) != new) + if (real_morecore ((char *) bloc_start - (char *) new) != new) return 0; new_heap->start = new; @@ -287,10 +283,10 @@ obtain (POINTER address, SIZE size) Get some extra, so we can come here less often. */ get = size + extra_bytes - already_available; - get = (char *) ROUNDUP ((char *)last_heap->end + get) + get = (char *) ROUNDUP ((char *) last_heap->end + get) - (char *) last_heap->end; - if ((*real_morecore) (get) != last_heap->end) + if (real_morecore (get) != last_heap->end) return 0; last_heap->end = (char *) last_heap->end + get; @@ -319,13 +315,13 @@ relinquish (void) ? h->bloc_start : break_value); } - if (excess > extra_bytes * 2 && (*real_morecore) (0) == last_heap->end) + if (excess > extra_bytes * 2 && real_morecore (0) == last_heap->end) { /* Keep extra_bytes worth of empty space. And don't free anything unless we can free at least extra_bytes. */ excess -= extra_bytes; - if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess) + if ((char *) last_heap->end - (char *) last_heap->bloc_start <= excess) { heap_ptr lh_prev; @@ -336,12 +332,12 @@ relinquish (void) return; /* Return the last heap, with its header, to the system. */ - excess = (char *)last_heap->end - (char *)last_heap->start; + excess = (char *) last_heap->end - (char *) last_heap->start; lh_prev = last_heap->prev; /* If the system doesn't want that much memory back, leave last_heap unaltered to reflect that. This can occur if break_value is still within the original data segment. */ - if ((*real_morecore) (- excess) != 0) + if (real_morecore (- excess) != 0) { last_heap = lh_prev; last_heap->next = NIL_HEAP; @@ -349,13 +345,13 @@ relinquish (void) } else { - excess = (char *) last_heap->end - - (char *) ROUNDUP ((char *)last_heap->end - excess); + excess = ((char *) last_heap->end + - (char *) ROUNDUP ((char *) last_heap->end - excess)); /* If the system doesn't want that much memory back, leave the end of the last heap unchanged to reflect that. This can occur if break_value is still within the original data segment. */ - if ((*real_morecore) (- excess) != 0) + if (real_morecore (- excess) != 0) last_heap->end = (char *) last_heap->end - excess; } } @@ -367,9 +363,9 @@ relinquish (void) to that block. */ static bloc_ptr -find_bloc (POINTER *ptr) +find_bloc (void **ptr) { - register bloc_ptr p = first_bloc; + bloc_ptr p = first_bloc; while (p != NIL_BLOC) { @@ -392,10 +388,10 @@ find_bloc (POINTER *ptr) memory for the new block. */ static bloc_ptr -get_bloc (SIZE size) +get_bloc (size_t size) { - register bloc_ptr new_bloc; - register heap_ptr heap; + bloc_ptr new_bloc; + heap_ptr heap; if (! (new_bloc = malloc (BLOC_PTR_SIZE)) || ! (new_bloc->data = obtain (break_value, size))) @@ -409,7 +405,7 @@ get_bloc (SIZE size) new_bloc->size = size; new_bloc->next = NIL_BLOC; - new_bloc->variable = (POINTER *) NIL; + new_bloc->variable = NULL; new_bloc->new_data = 0; /* Record in the heap that this space is in use. */ @@ -447,9 +443,9 @@ get_bloc (SIZE size) Do not touch the contents of blocs or break_value. */ static int -relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address) +relocate_blocs (bloc_ptr bloc, heap_ptr heap, void *address) { - register bloc_ptr b = bloc; + bloc_ptr b = bloc; /* No need to ever call this if arena is frozen, bug somewhere! */ if (r_alloc_freeze_level) @@ -471,8 +467,8 @@ relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address) get enough new space to hold BLOC and all following blocs. */ if (heap == NIL_HEAP) { - register bloc_ptr tb = b; - register SIZE s = 0; + bloc_ptr tb = b; + size_t s = 0; /* Add up the size of all the following blocs. */ while (tb != NIL_BLOC) @@ -568,12 +564,12 @@ update_heap_bloc_correspondence (bloc_ptr bloc, heap_ptr heap) that come after BLOC in memory. */ static int -resize_bloc (bloc_ptr bloc, SIZE size) +resize_bloc (bloc_ptr bloc, size_t size) { - register bloc_ptr b; + bloc_ptr b; heap_ptr heap; - POINTER address; - SIZE old_size; + void *address; + size_t old_size; /* No need to ever call this if arena is frozen, bug somewhere! */ if (r_alloc_freeze_level) @@ -675,7 +671,7 @@ free_bloc (bloc_ptr bloc) if (r_alloc_freeze_level) { - bloc->variable = (POINTER *) NIL; + bloc->variable = NULL; return; } @@ -752,17 +748,17 @@ free_bloc (bloc_ptr bloc) __morecore hook values - in particular, __default_morecore in the GNU malloc package. */ -static POINTER +static void * r_alloc_sbrk (ptrdiff_t size) { - register bloc_ptr b; - POINTER address; + bloc_ptr b; + void *address; if (! r_alloc_initialized) r_alloc_init (); if (use_relocatable_buffers <= 0) - return (*real_morecore) (size); + return real_morecore (size); if (size == 0) return virtual_break_value; @@ -772,19 +768,19 @@ r_alloc_sbrk (ptrdiff_t size) /* Allocate a page-aligned space. GNU malloc would reclaim an extra space if we passed an unaligned one. But we could not always find a space which is contiguous to the previous. */ - POINTER new_bloc_start; + void *new_bloc_start; heap_ptr h = first_heap; - SIZE get = ROUNDUP (size); + size_t get = ROUNDUP (size); - address = (POINTER) ROUNDUP (virtual_break_value); + address = (void *) ROUNDUP (virtual_break_value); /* Search the list upward for a heap which is large enough. */ - while ((char *) h->end < (char *) MEM_ROUNDUP ((char *)address + get)) + while ((char *) h->end < (char *) MEM_ROUNDUP ((char *) address + get)) { h = h->next; if (h == NIL_HEAP) break; - address = (POINTER) ROUNDUP (h->start); + address = (void *) ROUNDUP (h->start); } /* If not found, obtain more space. */ @@ -796,19 +792,19 @@ r_alloc_sbrk (ptrdiff_t size) return 0; if (first_heap == last_heap) - address = (POINTER) ROUNDUP (virtual_break_value); + address = (void *) ROUNDUP (virtual_break_value); else - address = (POINTER) ROUNDUP (last_heap->start); + address = (void *) ROUNDUP (last_heap->start); h = last_heap; } - new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get); + new_bloc_start = (void *) MEM_ROUNDUP ((char *) address + get); if (first_heap->bloc_start < new_bloc_start) { /* This is no clean solution - no idea how to do it better. */ if (r_alloc_freeze_level) - return NIL; + return NULL; /* There is a bug here: if the above obtain call succeeded, but the relocate_blocs call below does not succeed, we need to free @@ -818,7 +814,7 @@ r_alloc_sbrk (ptrdiff_t size) if (! relocate_blocs (first_bloc, h, new_bloc_start)) return 0; - /* Note that (POINTER)(h+1) <= new_bloc_start since + /* Note that (char *) (h + 1) <= (char *) new_bloc_start since get >= page_size, so the following does not destroy the heap header. */ for (b = last_bloc; b != NIL_BLOC; b = b->prev) @@ -855,8 +851,8 @@ r_alloc_sbrk (ptrdiff_t size) } else /* size < 0 */ { - SIZE excess = (char *)first_heap->bloc_start - - ((char *)virtual_break_value + size); + size_t excess = ((char *) first_heap->bloc_start + - ((char *) virtual_break_value + size)); address = virtual_break_value; @@ -864,7 +860,7 @@ r_alloc_sbrk (ptrdiff_t size) { excess -= extra_bytes; first_heap->bloc_start - = (POINTER) MEM_ROUNDUP ((char *)first_heap->bloc_start - excess); + = (void *) MEM_ROUNDUP ((char *) first_heap->bloc_start - excess); relocate_blocs (first_bloc, first_heap, first_heap->bloc_start); @@ -876,14 +872,14 @@ r_alloc_sbrk (ptrdiff_t size) } } - if ((char *)virtual_break_value + size < (char *)first_heap->start) + if ((char *) virtual_break_value + size < (char *) first_heap->start) { /* We found an additional space below the first heap */ - first_heap->start = (POINTER) ((char *)virtual_break_value + size); + first_heap->start = (void *) ((char *) virtual_break_value + size); } } - virtual_break_value = (POINTER) ((char *)address + size); + virtual_break_value = (void *) ((char *) address + size); break_value = (last_bloc ? (char *) last_bloc->data + last_bloc->size : (char *) first_heap->bloc_start); @@ -905,10 +901,10 @@ r_alloc_sbrk (ptrdiff_t size) If we can't allocate the necessary memory, set *PTR to zero, and return zero. */ -POINTER -r_alloc (POINTER *ptr, SIZE size) +void * +r_alloc (void **ptr, size_t size) { - register bloc_ptr new_bloc; + bloc_ptr new_bloc; if (! r_alloc_initialized) r_alloc_init (); @@ -929,9 +925,9 @@ r_alloc (POINTER *ptr, SIZE size) Store 0 in *PTR to show there's no block allocated. */ void -r_alloc_free (register POINTER *ptr) +r_alloc_free (void **ptr) { - register bloc_ptr dead_bloc; + bloc_ptr dead_bloc; if (! r_alloc_initialized) r_alloc_init (); @@ -962,10 +958,10 @@ r_alloc_free (register POINTER *ptr) If more memory cannot be allocated, then leave *PTR unchanged, and return zero. */ -POINTER -r_re_alloc (POINTER *ptr, SIZE size) +void * +r_re_alloc (void **ptr, size_t size) { - register bloc_ptr bloc; + bloc_ptr bloc; if (! r_alloc_initialized) r_alloc_init (); @@ -1004,15 +1000,15 @@ r_re_alloc (POINTER *ptr, SIZE size) { new_bloc->variable = ptr; *ptr = new_bloc->data; - bloc->variable = (POINTER *) NIL; + bloc->variable = NULL; } else - return NIL; + return NULL; } else { if (! resize_bloc (bloc, MEM_ROUNDUP (size))) - return NIL; + return NULL; } } return *ptr; @@ -1052,27 +1048,27 @@ r_alloc_check (void) return; assert (first_heap); - assert (last_heap->end <= (POINTER) sbrk (0)); - assert ((POINTER) first_heap < first_heap->start); + assert (last_heap->end <= (void *) sbrk (0)); + assert ((void *) first_heap < first_heap->start); assert (first_heap->start <= virtual_break_value); assert (virtual_break_value <= first_heap->end); for (h = first_heap; h; h = h->next) { assert (h->prev == ph); - assert ((POINTER) ROUNDUP (h->end) == h->end); + assert ((void *) ROUNDUP (h->end) == h->end); #if 0 /* ??? The code in ralloc.c does not really try to ensure the heap start has any sort of alignment. Perhaps it should. */ - assert ((POINTER) MEM_ROUNDUP (h->start) == h->start); + assert ((void *) MEM_ROUNDUP (h->start) == h->start); #endif - assert ((POINTER) MEM_ROUNDUP (h->bloc_start) == h->bloc_start); + assert ((void *) MEM_ROUNDUP (h->bloc_start) == h->bloc_start); assert (h->start <= h->bloc_start && h->bloc_start <= h->end); if (ph) { assert (ph->end < h->start); - assert (h->start <= (POINTER)h && (POINTER)(h+1) <= h->bloc_start); + assert (h->start <= (void *) h && (void *) (h + 1) <= h->bloc_start); } if (h->bloc_start <= break_value && break_value <= h->end) @@ -1087,8 +1083,8 @@ r_alloc_check (void) for (b = first_bloc; b; b = b->next) { assert (b->prev == pb); - assert ((POINTER) MEM_ROUNDUP (b->data) == b->data); - assert ((SIZE) MEM_ROUNDUP (b->size) == b->size); + assert ((void *) MEM_ROUNDUP (b->data) == b->data); + assert ((size_t) MEM_ROUNDUP (b->size) == b->size); ph = 0; for (h = first_heap; h; h = h->next) @@ -1137,7 +1133,7 @@ r_alloc_check (void) is checked to ensure that memory corruption does not occur due to misuse. */ void -r_alloc_reset_variable (POINTER *old, POINTER *new) +r_alloc_reset_variable (void **old, void **new) { bloc_ptr bloc = first_bloc; @@ -1192,8 +1188,8 @@ r_alloc_init (void) first_heap = last_heap = &heap_base; first_heap->next = first_heap->prev = NIL_HEAP; first_heap->start = first_heap->bloc_start - = virtual_break_value = break_value = (*real_morecore) (0); - if (break_value == NIL) + = virtual_break_value = break_value = real_morecore (0); + if (break_value == NULL) emacs_abort (); extra_bytes = ROUNDUP (50000); @@ -1218,7 +1214,7 @@ r_alloc_init (void) #endif #ifndef SYSTEM_MALLOC - first_heap->end = (POINTER) ROUNDUP (first_heap->start); + first_heap->end = (void *) ROUNDUP (first_heap->start); /* The extra call to real_morecore guarantees that the end of the address space is a multiple of page_size, even if page_size is @@ -1226,7 +1222,7 @@ r_alloc_init (void) which page_size is stored. This allows a binary to be built on a system with one page size and run on a system with a smaller page size. */ - (*real_morecore) ((char *) first_heap->end - (char *) first_heap->start); + real_morecore ((char *) first_heap->end - (char *) first_heap->start); /* Clear the rest of the last page; this memory is in our address space even though it is after the sbrk value. */ diff --git a/src/region-cache.h b/src/region-cache.h index 697ae1c791f..e4c6b59ee95 100644 --- a/src/region-cache.h +++ b/src/region-cache.h @@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ existing data structure, and disturb as little of the existing code as possible. - So here's the tack. We add some caching to the scan_buffer + So here's the tack. We add some caching to the find_newline function, so that when it searches for a newline, it notes that the region between the start and end of the search contained no newlines; then, the next time around, it consults this cache to see diff --git a/src/search.c b/src/search.c index a7fabf19399..32ad6927442 100644 --- a/src/search.c +++ b/src/search.c @@ -209,7 +209,8 @@ clear_regexp_cache (void) for this pattern. 0 means backtrack only enough to get a valid match. */ struct re_pattern_buffer * -compile_pattern (Lisp_Object pattern, struct re_registers *regp, Lisp_Object translate, int posix, int multibyte) +compile_pattern (Lisp_Object pattern, struct re_registers *regp, + Lisp_Object translate, int posix, bool multibyte) { struct regexp_cache *cp, **cpp; @@ -534,9 +535,10 @@ fast_string_match_ignore_case (Lisp_Object regexp, Lisp_Object string) data. */ ptrdiff_t -fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t limit, ptrdiff_t limit_byte, Lisp_Object string) +fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte, + ptrdiff_t limit, ptrdiff_t limit_byte, Lisp_Object string) { - int multibyte; + bool multibyte; struct re_pattern_buffer *buf; unsigned char *p1, *p2; ptrdiff_t s1, s2; @@ -619,7 +621,7 @@ newline_cache_on_off (struct buffer *buf) } -/* Search for COUNT instances of the character TARGET between START and END. +/* Search for COUNT newlines between START/START_BYTE and END/END_BYTE. If COUNT is positive, search forwards; END must be >= START. If COUNT is negative, search backwards for the -COUNTth instance; @@ -634,14 +636,18 @@ newline_cache_on_off (struct buffer *buf) this is not the same as the usual convention for Emacs motion commands. If we don't find COUNT instances before reaching END, set *SHORTAGE - to the number of TARGETs left unfound, and return END. + to the number of newlines left unfound, and return END. + + If BYTEPOS is not NULL, set *BYTEPOS to the byte position corresponding + to the returned character position. If ALLOW_QUIT, set immediate_quit. That's good to do except when inside redisplay. */ ptrdiff_t -scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, - ptrdiff_t count, ptrdiff_t *shortage, bool allow_quit) +find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, + ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage, + ptrdiff_t *bytepos, bool allow_quit) { struct region_cache *newline_cache; int direction; @@ -649,13 +655,17 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, if (count > 0) { direction = 1; - if (! end) end = ZV; + if (!end) + end = ZV, end_byte = ZV_BYTE; } else { direction = -1; - if (! end) end = BEGV; + if (!end) + end = BEGV, end_byte = BEGV_BYTE; } + if (end_byte == -1) + end_byte = CHAR_TO_BYTE (end); newline_cache_on_off (current_buffer); newline_cache = current_buffer->newline_cache; @@ -673,13 +683,11 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, the position of the last character before the next such obstacle --- the last character the dumb search loop should examine. */ - ptrdiff_t ceiling_byte = CHAR_TO_BYTE (end) - 1; - ptrdiff_t start_byte; - ptrdiff_t tem; + ptrdiff_t tem, ceiling_byte = end_byte - 1; /* If we're looking for a newline, consult the newline cache to see where we can avoid some scanning. */ - if (target == '\n' && newline_cache) + if (newline_cache) { ptrdiff_t next_change; immediate_quit = 0; @@ -698,7 +706,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, next_change is the position of the next known region. */ ceiling_byte = min (CHAR_TO_BYTE (next_change) - 1, ceiling_byte); } - else + else if (start_byte == -1) start_byte = CHAR_TO_BYTE (start); /* The dumb loop can only scan text stored in contiguous @@ -718,44 +726,45 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, while (cursor < ceiling_addr) { - unsigned char *scan_start = cursor; - /* The dumb loop. */ - while (*cursor != target && ++cursor < ceiling_addr) - ; + unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor); /* If we're looking for newlines, cache the fact that the region from start to cursor is free of them. */ - if (target == '\n' && newline_cache) - know_region_cache (current_buffer, newline_cache, - BYTE_TO_CHAR (start_byte + scan_start - base), - BYTE_TO_CHAR (start_byte + cursor - base)); - - /* Did we find the target character? */ - if (cursor < ceiling_addr) - { - if (--count == 0) - { - immediate_quit = 0; - return BYTE_TO_CHAR (start_byte + cursor - base + 1); - } - cursor++; - } + if (newline_cache) + { + unsigned char *low = cursor; + unsigned char *lim = nl ? nl : ceiling_addr; + know_region_cache (current_buffer, newline_cache, + BYTE_TO_CHAR (low - base + start_byte), + BYTE_TO_CHAR (lim - base + start_byte)); + } + + if (! nl) + break; + + if (--count == 0) + { + immediate_quit = 0; + if (bytepos) + *bytepos = nl + 1 - base + start_byte; + return BYTE_TO_CHAR (nl + 1 - base + start_byte); + } + cursor = nl + 1; } - start = BYTE_TO_CHAR (start_byte + cursor - base); + start_byte += ceiling_addr - base; + start = BYTE_TO_CHAR (start_byte); } } else while (start > end) { /* The last character to check before the next obstacle. */ - ptrdiff_t ceiling_byte = CHAR_TO_BYTE (end); - ptrdiff_t start_byte; - ptrdiff_t tem; + ptrdiff_t tem, ceiling_byte = end_byte; /* Consult the newline cache, if appropriate. */ - if (target == '\n' && newline_cache) + if (newline_cache) { ptrdiff_t next_change; immediate_quit = 0; @@ -774,7 +783,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, next_change is the position of the next known region. */ ceiling_byte = max (CHAR_TO_BYTE (next_change), ceiling_byte); } - else + else if (start_byte == -1) start_byte = CHAR_TO_BYTE (start); /* Stop scanning before the gap. */ @@ -789,42 +798,50 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, while (cursor >= ceiling_addr) { - unsigned char *scan_start = cursor; - - while (*cursor != target && --cursor >= ceiling_addr) - ; + unsigned char *nl = memrchr (ceiling_addr, '\n', + cursor + 1 - ceiling_addr); /* If we're looking for newlines, cache the fact that the region from after the cursor to start is free of them. */ - if (target == '\n' && newline_cache) - know_region_cache (current_buffer, newline_cache, - BYTE_TO_CHAR (start_byte + cursor - base), - BYTE_TO_CHAR (start_byte + scan_start - base)); - - /* Did we find the target character? */ - if (cursor >= ceiling_addr) - { - if (++count >= 0) - { - immediate_quit = 0; - return BYTE_TO_CHAR (start_byte + cursor - base); - } - cursor--; - } + if (newline_cache) + { + unsigned char *low = nl ? nl : ceiling_addr - 1; + unsigned char *lim = cursor; + know_region_cache (current_buffer, newline_cache, + BYTE_TO_CHAR (low - base + start_byte), + BYTE_TO_CHAR (lim - base + start_byte)); + } + + if (! nl) + break; + + if (++count >= 0) + { + immediate_quit = 0; + if (bytepos) + *bytepos = nl - base + start_byte; + return BYTE_TO_CHAR (nl - base + start_byte); + } + cursor = nl - 1; } - start = BYTE_TO_CHAR (start_byte + cursor - base); + start_byte += ceiling_addr - 1 - base; + start = BYTE_TO_CHAR (start_byte); } } immediate_quit = 0; - if (shortage != 0) + if (shortage) *shortage = count * direction; + if (bytepos) + { + *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte; + eassert (*bytepos == CHAR_TO_BYTE (start)); + } return start; } -/* Search for COUNT instances of a line boundary, which means either a - newline or (if selective display enabled) a carriage return. +/* Search for COUNT instances of a line boundary. Start at START. If COUNT is negative, search backwards. We report the resulting position by calling TEMP_SET_PT_BOTH. @@ -855,14 +872,9 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, bool old_immediate_quit = immediate_quit; - /* The code that follows is like scan_buffer - but checks for either newline or carriage return. */ - if (allow_quit) immediate_quit++; - start_byte = CHAR_TO_BYTE (start); - if (count > 0) { while (start_byte < limit_byte) @@ -871,29 +883,25 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, ceiling = min (limit_byte - 1, ceiling); ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; base = (cursor = BYTE_POS_ADDR (start_byte)); - while (1) - { - while (*cursor != '\n' && ++cursor != ceiling_addr) - ; - if (cursor != ceiling_addr) + do + { + unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor); + if (! nl) + break; + if (--count == 0) { - if (--count == 0) - { - immediate_quit = old_immediate_quit; - start_byte = start_byte + cursor - base + 1; - start = BYTE_TO_CHAR (start_byte); - TEMP_SET_PT_BOTH (start, start_byte); - return 0; - } - else - if (++cursor == ceiling_addr) - break; + immediate_quit = old_immediate_quit; + start_byte += nl - base + 1; + start = BYTE_TO_CHAR (start_byte); + TEMP_SET_PT_BOTH (start, start_byte); + return 0; } - else - break; + cursor = nl + 1; } - start_byte += cursor - base; + while (cursor < ceiling_addr); + + start_byte += ceiling_addr - base; } } else @@ -902,31 +910,28 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, { ceiling = BUFFER_FLOOR_OF (start_byte - 1); ceiling = max (limit_byte, ceiling); - ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; + ceiling_addr = BYTE_POS_ADDR (ceiling); base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); while (1) { - while (--cursor != ceiling_addr && *cursor != '\n') - ; + unsigned char *nl = memrchr (ceiling_addr, '\n', + cursor - ceiling_addr); + if (! nl) + break; - if (cursor != ceiling_addr) + if (++count == 0) { - if (++count == 0) - { - immediate_quit = old_immediate_quit; - /* Return the position AFTER the match we found. */ - start_byte = start_byte + cursor - base + 1; - start = BYTE_TO_CHAR (start_byte); - TEMP_SET_PT_BOTH (start, start_byte); - return 0; - } + immediate_quit = old_immediate_quit; + /* Return the position AFTER the match we found. */ + start_byte += nl - base + 1; + start = BYTE_TO_CHAR (start_byte); + TEMP_SET_PT_BOTH (start, start_byte); + return 0; } - else - break; + + cursor = nl; } - /* Here we add 1 to compensate for the last decrement - of CURSOR, which took it past the valid range. */ - start_byte += cursor - base + 1; + start_byte += ceiling_addr - base; } } @@ -936,25 +941,33 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, return count * direction; } +/* Like find_newline, but doesn't allow QUITting and doesn't return + SHORTAGE. */ ptrdiff_t -find_next_newline_no_quit (ptrdiff_t from, ptrdiff_t cnt) +find_newline_no_quit (ptrdiff_t from, ptrdiff_t frombyte, + ptrdiff_t cnt, ptrdiff_t *bytepos) { - return scan_buffer ('\n', from, 0, cnt, (ptrdiff_t *) 0, 0); + return find_newline (from, frombyte, 0, -1, cnt, NULL, bytepos, 0); } -/* Like find_next_newline, but returns position before the newline, - not after, and only search up to TO. This isn't just - find_next_newline (...)-1, because you might hit TO. */ +/* Like find_newline, but returns position before the newline, not + after, and only search up to TO. + This isn't just find_newline_no_quit (...)-1, because you might hit TO. */ ptrdiff_t -find_before_next_newline (ptrdiff_t from, ptrdiff_t to, ptrdiff_t cnt) +find_before_next_newline (ptrdiff_t from, ptrdiff_t to, + ptrdiff_t cnt, ptrdiff_t *bytepos) { ptrdiff_t shortage; - ptrdiff_t pos = scan_buffer ('\n', from, to, cnt, &shortage, 1); + ptrdiff_t pos = find_newline (from, -1, to, -1, cnt, &shortage, bytepos, 1); if (shortage == 0) - pos--; - + { + if (bytepos) + DEC_BOTH (pos, *bytepos); + else + pos--; + } return pos; } @@ -1016,8 +1029,7 @@ search_command (Lisp_Object string, Lisp_Object bound, Lisp_Object noerror, if (!EQ (noerror, Qt)) { - if (lim < BEGV || lim > ZV) - emacs_abort (); + eassert (BEGV <= lim && lim <= ZV); SET_PT_BOTH (lim, lim_byte); return Qnil; #if 0 /* This would be clean, but maybe programs depend on @@ -1029,9 +1041,7 @@ search_command (Lisp_Object string, Lisp_Object bound, Lisp_Object noerror, return Qnil; } - if (np < BEGV || np > ZV) - emacs_abort (); - + eassert (BEGV <= np && np <= ZV); SET_PT (np); return make_number (np); @@ -1258,7 +1268,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t raw_pattern_size; ptrdiff_t raw_pattern_size_byte; unsigned char *patbuf; - int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); + bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); unsigned char *base_pat; /* Set to positive if we find a non-ASCII char that need translation. Otherwise set to zero later. */ @@ -1471,8 +1481,8 @@ simple_search (EMACS_INT n, unsigned char *pat, ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t lim, ptrdiff_t lim_byte) { - int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); - int forward = n > 0; + bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); + bool forward = n > 0; /* Number of buffer bytes matched. Note that this may be different from len_byte in a multibyte buffer. */ ptrdiff_t match_byte = PTRDIFF_MIN; @@ -1691,7 +1701,7 @@ boyer_moore (EMACS_INT n, unsigned char *base_pat, register ptrdiff_t i; register int j; unsigned char *pat, *pat_end; - int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); + bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); unsigned char simple_translate[0400]; /* These are set to the preceding bytes of a byte to be translated @@ -2517,8 +2527,8 @@ since only regular expressions have distinguished subexpressions. */) ptrdiff_t length = SBYTES (newtext); unsigned char *substed; ptrdiff_t substed_alloc_size, substed_len; - int buf_multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); - int str_multibyte = STRING_MULTIBYTE (newtext); + bool buf_multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); + bool str_multibyte = STRING_MULTIBYTE (newtext); int really_changed = 0; substed_alloc_size = ((STRING_BYTES_BOUND - 100) / 2 < length diff --git a/src/sheap.c b/src/sheap.c index 972c04c9552..f8eec753268 100644 --- a/src/sheap.c +++ b/src/sheap.c @@ -91,5 +91,7 @@ report_sheap_usage (int die_if_pure_storage_exceeded) char buf[200]; sprintf (buf, "Static heap usage: %d of %d bytes", bss_sbrk_ptr - bss_sbrk_buffer, STATIC_HEAP_SIZE); - message ("%s", buf); + /* Don't log messages, cause at this point, we're not allowed to create + buffers. */ + message1_nolog (buf); } diff --git a/src/sound.c b/src/sound.c index 802f1ce740d..9c472fb0263 100644 --- a/src/sound.c +++ b/src/sound.c @@ -334,7 +334,7 @@ sound_perror (const char *msg) static void sound_warning (const char *msg) { - message ("%s", msg); + message1 (msg); } diff --git a/src/syntax.c b/src/syntax.c index 72d904914ec..390d732944d 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -121,6 +121,7 @@ struct lisp_parse_state /* Char number of start of containing expression */ ptrdiff_t prevlevelstart; ptrdiff_t location; /* Char number at which parsing stopped. */ + ptrdiff_t location_byte; /* Corresponding byte position. */ ptrdiff_t comstr_start; /* Position of last comment/string starter. */ Lisp_Object levelstarts; /* Char numbers of starts-of-expression of levels (starting from outermost). */ @@ -3277,6 +3278,7 @@ do { prev_from = from; \ stop: /* Here if stopping before start of sexp. */ from = prev_from; /* We have just fetched the char that starts it; */ + from_byte = prev_from_byte; goto done; /* but return the position before it. */ endquoted: @@ -3288,6 +3290,7 @@ do { prev_from = from; \ state.prevlevelstart = (curlevel == levelstart) ? -1 : (curlevel - 1)->last; state.location = from; + state.location_byte = from_byte; state.levelstarts = Qnil; while (curlevel > levelstart) state.levelstarts = Fcons (make_number ((--curlevel)->last), @@ -3327,7 +3330,8 @@ Fifth arg OLDSTATE is a list like what this function returns. Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. If it is symbol `syntax-table', stop after the start of a comment or a string, or after end of a comment or a string. */) - (Lisp_Object from, Lisp_Object to, Lisp_Object targetdepth, Lisp_Object stopbefore, Lisp_Object oldstate, Lisp_Object commentstop) + (Lisp_Object from, Lisp_Object to, Lisp_Object targetdepth, + Lisp_Object stopbefore, Lisp_Object oldstate, Lisp_Object commentstop) { struct lisp_parse_state state; EMACS_INT target; @@ -3347,7 +3351,7 @@ Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. (NILP (commentstop) ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1))); - SET_PT (state.location); + SET_PT_BOTH (state.location, state.location_byte); return Fcons (make_number (state.depth), Fcons (state.prevlevelstart < 0 @@ -3389,8 +3393,8 @@ init_syntax_once (void) Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots"); /* Create objects which can be shared among syntax tables. */ - Vsyntax_code_object = Fmake_vector (make_number (Smax), Qnil); - for (i = 0; i < ASIZE (Vsyntax_code_object); i++) + Vsyntax_code_object = make_uninit_vector (Smax); + for (i = 0; i < Smax; i++) ASET (Vsyntax_code_object, i, Fcons (make_number (i), Qnil)); /* Now we are ready to set up this property, so we can diff --git a/src/sysdep.c b/src/sysdep.c index 0e9a6826005..fe6371623a9 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -30,9 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <limits.h> #include <unistd.h> -#include <allocator.h> #include <c-ctype.h> -#include <careadlinkat.h> #include <ignore-value.h> #include <utimens.h> @@ -529,10 +527,10 @@ sys_subshell (void) #ifdef DOS_NT /* MW, Aug 1993 */ getcwd (oldwd, sizeof oldwd); if (sh == 0) - sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */ + sh = egetenv ("SUSPEND"); /* KFS, 1994-12-14 */ #endif if (sh == 0) - sh = (char *) egetenv ("SHELL"); + sh = egetenv ("SHELL"); if (sh == 0) sh = "sh"; @@ -2247,22 +2245,6 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) return (bytes_written); } - -static struct allocator const emacs_norealloc_allocator = - { xmalloc, NULL, xfree, memory_full }; - -/* Get the symbolic link value of FILENAME. Return a pointer to a - NUL-terminated string. If readlink fails, return NULL and set - errno. If the value fits in INITIAL_BUF, return INITIAL_BUF. - Otherwise, allocate memory and return a pointer to that memory. If - memory allocation fails, diagnose and fail without returning. If - successful, store the length of the symbolic link into *LINKLEN. */ -char * -emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE]) -{ - return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE, - &emacs_norealloc_allocator, careadlinkatcwd); -} /* Return a struct timeval that is roughly equivalent to T. Use the least timeval not less than T. @@ -2559,12 +2541,12 @@ list_system_processes (void) return proclist; } -#elif defined BSD_SYSTEM +#elif defined DARWIN_OS || defined __FreeBSD__ Lisp_Object list_system_processes (void) { -#if defined DARWIN_OS || defined __NetBSD__ || defined __OpenBSD__ +#ifdef DARWIN_OS int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; #else int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC}; @@ -2590,10 +2572,8 @@ list_system_processes (void) len /= sizeof (struct kinfo_proc); for (i = 0; i < len; i++) { -#if defined DARWIN_OS || defined __NetBSD__ +#ifdef DARWIN_OS proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.p_pid), proclist); -#elif defined __OpenBSD__ - proclist = Fcons (make_fixnum_or_float (procs[i].p_pid), proclist); #else proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist); #endif diff --git a/src/term.c b/src/term.c index f66a0bddc33..a31fd51084e 100644 --- a/src/term.c +++ b/src/term.c @@ -2374,7 +2374,7 @@ A suspended tty may be resumed by calling `resume-tty' on it. */) t->display_info.tty->output = 0; if (FRAMEP (t->display_info.tty->top_frame)) - FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0); + SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0); } @@ -2444,7 +2444,7 @@ frame's terminal). */) get_tty_size (fileno (t->display_info.tty->input), &width, &height); if (width != old_width || height != old_height) change_frame_size (f, height, width, 0, 0, 0); - FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); + SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); } set_tty_hooks (t); diff --git a/src/termcap.c b/src/termcap.c index 82c2b1fda07..99bbfce27f5 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -393,7 +393,7 @@ tgetent (char *bp, const char *name) if (termcap_name && (*termcap_name == '\\' || *termcap_name == '/' || termcap_name[1] == ':')) - dostounix_filename (termcap_name); + dostounix_filename (termcap_name, 0); #endif filep = termcap_name && valid_filename_p (termcap_name); diff --git a/src/textprop.c b/src/textprop.c index c1f6e59bf2e..18e893b3ef2 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -125,9 +125,10 @@ modify_region (Lisp_Object buffer, Lisp_Object start, Lisp_Object end) #define hard 1 INTERVAL -validate_interval_range (Lisp_Object object, Lisp_Object *begin, Lisp_Object *end, int force) +validate_interval_range (Lisp_Object object, Lisp_Object *begin, + Lisp_Object *end, bool force) { - register INTERVAL i; + INTERVAL i; ptrdiff_t searchpos; CHECK_STRING_OR_BUFFER (object); @@ -198,14 +199,14 @@ validate_plist (Lisp_Object list) if (CONSP (list)) { - register int i; - register Lisp_Object tail; - for (i = 0, tail = list; CONSP (tail); i++) + bool odd_length = 0; + Lisp_Object tail; + for (tail = list; CONSP (tail); tail = XCDR (tail)) { - tail = XCDR (tail); + odd_length ^= 1; QUIT; } - if (i & 1) + if (odd_length) error ("Odd length text property list"); return list; } @@ -213,20 +214,19 @@ validate_plist (Lisp_Object list) return Fcons (list, Fcons (Qnil, Qnil)); } -/* Return nonzero if interval I has all the properties, +/* Return true if interval I has all the properties, with the same values, of list PLIST. */ -static int +static bool interval_has_all_properties (Lisp_Object plist, INTERVAL i) { - register Lisp_Object tail1, tail2, sym1; - register int found; + Lisp_Object tail1, tail2; /* Go through each element of PLIST. */ for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) { - sym1 = XCAR (tail1); - found = 0; + Lisp_Object sym1 = XCAR (tail1); + bool found = 0; /* Go through I's plist, looking for sym1 */ for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) @@ -249,13 +249,13 @@ interval_has_all_properties (Lisp_Object plist, INTERVAL i) return 1; } -/* Return nonzero if the plist of interval I has any of the +/* Return true if the plist of interval I has any of the properties of PLIST, regardless of their values. */ -static int +static bool interval_has_some_properties (Lisp_Object plist, INTERVAL i) { - register Lisp_Object tail1, tail2, sym; + Lisp_Object tail1, tail2, sym; /* Go through each element of PLIST. */ for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) @@ -274,10 +274,10 @@ interval_has_some_properties (Lisp_Object plist, INTERVAL i) /* Return nonzero if the plist of interval I has any of the property names in LIST, regardless of their values. */ -static int +static bool interval_has_some_properties_list (Lisp_Object list, INTERVAL i) { - register Lisp_Object tail1, tail2, sym; + Lisp_Object tail1, tail2, sym; /* Go through each element of LIST. */ for (tail1 = list; CONSP (tail1); tail1 = XCDR (tail1)) @@ -358,15 +358,14 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object) OBJECT should be the string or buffer the interval is in. - Return nonzero if this changes I (i.e., if any members of PLIST + Return true if this changes I (i.e., if any members of PLIST are actually added to I's plist) */ -static int +static bool add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) { Lisp_Object tail1, tail2, sym1, val1; - register int changed = 0; - register int found; + bool changed = 0; struct gcpro gcpro1, gcpro2, gcpro3; tail1 = plist; @@ -380,9 +379,9 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) /* Go through each element of PLIST. */ for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) { + bool found = 0; sym1 = XCAR (tail1); val1 = Fcar (XCDR (tail1)); - found = 0; /* Go through I's plist, looking for sym1 */ for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) @@ -410,7 +409,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) /* I's property has a different value -- change it */ Fsetcar (this_cdr, val1); - changed++; + changed = 1; break; } @@ -423,7 +422,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) sym1, Qnil, object); } set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist))); - changed++; + changed = 1; } } @@ -437,14 +436,14 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) (If PLIST is non-nil, use that, otherwise use LIST.) OBJECT is the string or buffer containing I. */ -static int +static bool remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object) { - register Lisp_Object tail1, tail2, sym, current_plist; - register int changed = 0; + Lisp_Object tail1, tail2, sym, current_plist; + bool changed = 0; - /* Nonzero means tail1 is a plist, otherwise it is a list. */ - int use_plist; + /* True means tail1 is a plist, otherwise it is a list. */ + bool use_plist; current_plist = i->plist; @@ -467,7 +466,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object); current_plist = XCDR (XCDR (current_plist)); - changed++; + changed = 1; } /* Go through I's plist, looking for SYM. */ @@ -483,7 +482,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object sym, XCAR (XCDR (this)), object); Fsetcdr (XCDR (tail2), XCDR (XCDR (this))); - changed++; + changed = 1; } tail2 = this; } @@ -1129,10 +1128,11 @@ If OBJECT is a string, START and END are 0-based indices into it. Return t if any property value actually changed, nil otherwise. */) (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) { - register INTERVAL i, unchanged; - register ptrdiff_t s, len; - register int modified = 0; + INTERVAL i, unchanged; + ptrdiff_t s, len; + bool modified = 0; struct gcpro gcpro1; + bool first_time = 1; properties = validate_plist (properties); if (NILP (properties)) @@ -1141,6 +1141,7 @@ Return t if any property value actually changed, nil otherwise. */) if (NILP (object)) XSETBUFFER (object, current_buffer); + retry: i = validate_interval_range (object, &start, &end, hard); if (!i) return Qnil; @@ -1152,31 +1153,50 @@ Return t if any property value actually changed, nil otherwise. */) and live buffers are always protected. */ GCPRO1 (properties); - /* If we're not starting on an interval boundary, we have to - split this interval. */ - if (i->position != s) + /* If this interval already has the properties, we can skip it. */ + if (interval_has_all_properties (properties, i)) { - /* If this interval already has the properties, we can - skip it. */ - if (interval_has_all_properties (properties, i)) + ptrdiff_t got = LENGTH (i) - (s - i->position); + + do { - ptrdiff_t got = (LENGTH (i) - (s - i->position)); if (got >= len) RETURN_UNGCPRO (Qnil); len -= got; i = next_interval (i); + got = LENGTH (i); } - else + while (interval_has_all_properties (properties, i)); + } + else if (i->position != s) + { + /* If we're not starting on an interval boundary, we have to + split this interval. */ + unchanged = i; + i = split_interval_right (unchanged, s - unchanged->position); + copy_properties (unchanged, i); + } + + if (BUFFERP (object) && first_time) + { + ptrdiff_t prev_total_length = TOTAL_LENGTH (i); + ptrdiff_t prev_pos = i->position; + + modify_region (object, start, end); + /* If someone called us recursively as a side effect of + modify_region, and changed the intervals behind our back + (could happen if lock_file, called by prepare_to_modify_buffer, + triggers redisplay, and that calls add-text-properties again + in the same buffer), we cannot continue with I, because its + data changed. So we restart the interval analysis anew. */ + if (TOTAL_LENGTH (i) != prev_total_length + || i->position != prev_pos) { - unchanged = i; - i = split_interval_right (unchanged, s - unchanged->position); - copy_properties (unchanged, i); + first_time = 0; + goto retry; } } - if (BUFFERP (object)) - modify_region (object, start, end); - /* We are at the beginning of interval I, with LEN chars to scan. */ for (;;) { @@ -1195,7 +1215,8 @@ Return t if any property value actually changed, nil otherwise. */) signal_after_change (XINT (start), XINT (end) - XINT (start), XINT (end) - XINT (start)); - return modified ? Qt : Qnil; + eassert (modified); + return Qt; } if (LENGTH (i) == len) @@ -1219,7 +1240,7 @@ Return t if any property value actually changed, nil otherwise. */) } len -= LENGTH (i); - modified += add_properties (properties, i, object); + modified |= add_properties (properties, i, object); i = next_interval (i); } } @@ -1423,13 +1444,15 @@ Return t if any property was actually removed, nil otherwise. Use `set-text-properties' if you want to remove all text properties. */) (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) { - register INTERVAL i, unchanged; - register ptrdiff_t s, len; - register int modified = 0; + INTERVAL i, unchanged; + ptrdiff_t s, len; + bool modified = 0; + bool first_time = 1; if (NILP (object)) XSETBUFFER (object, current_buffer); + retry: i = validate_interval_range (object, &start, &end, soft); if (!i) return Qnil; @@ -1437,31 +1460,50 @@ Use `set-text-properties' if you want to remove all text properties. */) s = XINT (start); len = XINT (end) - s; - if (i->position != s) + /* If there are no properties on this entire interval, return. */ + if (! interval_has_some_properties (properties, i)) { - /* No properties on this first interval -- return if - it covers the entire region. */ - if (! interval_has_some_properties (properties, i)) + ptrdiff_t got = LENGTH (i) - (s - i->position); + + do { - ptrdiff_t got = (LENGTH (i) - (s - i->position)); if (got >= len) return Qnil; len -= got; i = next_interval (i); + got = LENGTH (i); } - /* Split away the beginning of this interval; what we don't - want to modify. */ - else + while (! interval_has_some_properties (properties, i)); + } + /* Split away the beginning of this interval; what we don't + want to modify. */ + else if (i->position != s) + { + unchanged = i; + i = split_interval_right (unchanged, s - unchanged->position); + copy_properties (unchanged, i); + } + + if (BUFFERP (object) && first_time) + { + ptrdiff_t prev_total_length = TOTAL_LENGTH (i); + ptrdiff_t prev_pos = i->position; + + modify_region (object, start, end); + /* If someone called us recursively as a side effect of + modify_region, and changed the intervals behind our back + (could happen if lock_file, called by prepare_to_modify_buffer, + triggers redisplay, and that calls add-text-properties again + in the same buffer), we cannot continue with I, because its + data changed. So we restart the interval analysis anew. */ + if (TOTAL_LENGTH (i) != prev_total_length + || i->position != prev_pos) { - unchanged = i; - i = split_interval_right (unchanged, s - unchanged->position); - copy_properties (unchanged, i); + first_time = 0; + goto retry; } } - if (BUFFERP (object)) - modify_region (object, start, end); - /* We are at the beginning of an interval, with len to scan */ for (;;) { @@ -1470,7 +1512,13 @@ Use `set-text-properties' if you want to remove all text properties. */) if (LENGTH (i) >= len) { if (! interval_has_some_properties (properties, i)) - return modified ? Qt : Qnil; + { + eassert (modified); + if (BUFFERP (object)) + signal_after_change (XINT (start), XINT (end) - XINT (start), + XINT (end) - XINT (start)); + return Qt; + } if (LENGTH (i) == len) { @@ -1493,7 +1541,7 @@ Use `set-text-properties' if you want to remove all text properties. */) } len -= LENGTH (i); - modified += remove_properties (properties, Qnil, i, object); + modified |= remove_properties (properties, Qnil, i, object); i = next_interval (i); } } @@ -1508,9 +1556,9 @@ markers). If OBJECT is a string, START and END are 0-based indices into it. Return t if any property was actually removed, nil otherwise. */) (Lisp_Object start, Lisp_Object end, Lisp_Object list_of_properties, Lisp_Object object) { - register INTERVAL i, unchanged; - register ptrdiff_t s, len; - register int modified = 0; + INTERVAL i, unchanged; + ptrdiff_t s, len; + bool modified = 0; Lisp_Object properties; properties = list_of_properties; @@ -1524,26 +1572,28 @@ Return t if any property was actually removed, nil otherwise. */) s = XINT (start); len = XINT (end) - s; - if (i->position != s) + /* If there are no properties on the interval, return. */ + if (! interval_has_some_properties_list (properties, i)) { - /* No properties on this first interval -- return if - it covers the entire region. */ - if (! interval_has_some_properties_list (properties, i)) + ptrdiff_t got = LENGTH (i) - (s - i->position); + + do { - ptrdiff_t got = (LENGTH (i) - (s - i->position)); if (got >= len) return Qnil; len -= got; i = next_interval (i); + got = LENGTH (i); } - /* Split away the beginning of this interval; what we don't - want to modify. */ - else - { - unchanged = i; - i = split_interval_right (unchanged, s - unchanged->position); - copy_properties (unchanged, i); - } + while (! interval_has_some_properties_list (properties, i)); + } + /* Split away the beginning of this interval; what we don't + want to modify. */ + else if (i->position != s) + { + unchanged = i; + i = split_interval_right (unchanged, s - unchanged->position); + copy_properties (unchanged, i); } /* We are at the beginning of an interval, with len to scan. @@ -1690,7 +1740,7 @@ int text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer) { Lisp_Object prev_pos, front_sticky; - int is_rear_sticky = 1, is_front_sticky = 0; /* defaults */ + bool is_rear_sticky = 1, is_front_sticky = 0; /* defaults */ Lisp_Object defalt = Fassq (prop, Vtext_property_default_nonsticky); if (NILP (buffer)) @@ -1765,7 +1815,7 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_ Lisp_Object stuff; Lisp_Object plist; ptrdiff_t s, e, e2, p, len; - int modified = 0; + bool modified = 0; struct gcpro gcpro1, gcpro2; i = validate_interval_range (src, &start, &end, soft); @@ -1836,7 +1886,7 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_ res = Fadd_text_properties (Fcar (res), Fcar (Fcdr (res)), Fcar (Fcdr (Fcdr (res))), dest); if (! NILP (res)) - modified++; + modified = 1; stuff = Fcdr (stuff); } @@ -1907,33 +1957,28 @@ text_property_list (Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp /* Add text properties to OBJECT from LIST. LIST is a list of triples (START END PLIST), where START and END are positions and PLIST is a property list containing the text properties to add. Adjust START - and END positions by DELTA before adding properties. Value is - non-zero if OBJECT was modified. */ + and END positions by DELTA before adding properties. */ -int +void add_text_properties_from_list (Lisp_Object object, Lisp_Object list, Lisp_Object delta) { struct gcpro gcpro1, gcpro2; - int modified_p = 0; GCPRO2 (list, object); for (; CONSP (list); list = XCDR (list)) { - Lisp_Object item, start, end, plist, tem; + Lisp_Object item, start, end, plist; item = XCAR (list); start = make_number (XINT (XCAR (item)) + XINT (delta)); end = make_number (XINT (XCAR (XCDR (item))) + XINT (delta)); plist = XCAR (XCDR (XCDR (item))); - tem = Fadd_text_properties (start, end, plist, object); - if (!NILP (tem)) - modified_p = 1; + Fadd_text_properties (start, end, plist, object); } UNGCPRO; - return modified_p; } diff --git a/src/unexaix.c b/src/unexaix.c index 92ebd2e3ceb..44a824b8c12 100644 --- a/src/unexaix.c +++ b/src/unexaix.c @@ -51,18 +51,16 @@ what you give them. Help stamp out software-hoarding! */ #include "getpagesize.h" #include <sys/types.h> +#include <inttypes.h> +#include <stdarg.h> #include <stdio.h> #include <sys/stat.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> -#include "mem-limits.h" - -char *start_of_text (void); /* Start of text */ - -extern int _data; -extern int _text; +extern char _data[]; +extern char _text[]; #include <filehdr.h> #include <aouthdr.h> @@ -71,15 +69,15 @@ extern int _text; static struct filehdr f_hdr; /* File header */ static struct aouthdr f_ohdr; /* Optional file header (a.out) */ -static long bias; /* Bias to add for growth */ -static long lnnoptr; /* Pointer to line-number info within file */ +static off_t bias; /* Bias to add for growth */ +static off_t lnnoptr; /* Pointer to line-number info within file */ -static long text_scnptr; -static long data_scnptr; +static off_t text_scnptr; +static off_t data_scnptr; #define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) -static long load_scnptr; -static long orig_load_scnptr; -static long orig_data_scnptr; +static off_t load_scnptr; +static off_t orig_load_scnptr; +static off_t orig_data_scnptr; static int unrelocate_symbols (int, int, const char *, const char *); #ifndef MAX_SECTIONS @@ -92,23 +90,30 @@ static int pagemask; #include "lisp.h" -static void +static _Noreturn void report_error (const char *file, int fd) { if (fd) - close (fd); + { + int failed_errno = errno; + close (fd); + errno = failed_errno; + } report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); } -#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 -#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 -#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 +#define ERROR0(msg) report_error_1 (new, msg) +#define ERROR1(msg,x) report_error_1 (new, msg, x) +#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y) -static void -report_error_1 (int fd, const char *msg, int a1, int a2) +static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3) +report_error_1 (int fd, const char *msg, ...) { + va_list ap; close (fd); - error (msg, a1, a2); + va_start (ap, msg); + verror (msg, ap); + va_end (ap); } static int make_hdr (int, int, const char *, const char *); @@ -163,8 +168,8 @@ make_hdr (int new, int a_out, const char *a_name, const char *new_name) { int scns; - unsigned int bss_start; - unsigned int data_start; + uintptr_t bss_start; + uintptr_t data_start; struct scnhdr section[MAX_SECTIONS]; struct scnhdr * f_thdr; /* Text section header */ @@ -179,17 +184,17 @@ make_hdr (int new, int a_out, pagemask = getpagesize () - 1; /* Adjust text/data boundary. */ - data_start = (long) start_of_data (); - data_start = ADDR_CORRECT (data_start); + data_start = (uintptr_t) _data; data_start = data_start & ~pagemask; /* (Down) to page boundary. */ - bss_start = ADDR_CORRECT (sbrk (0)) + pagemask; + bss_start = (uintptr_t) sbrk (0) + pagemask; bss_start &= ~ pagemask; if (data_start > bss_start) /* Can't have negative data size. */ { - ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", + ERROR2 (("unexec: data_start (0x%"PRIxPTR + ") can't be greater than bss_start (0x%"PRIxPTR")"), data_start, bss_start); } @@ -279,7 +284,7 @@ make_hdr (int new, int a_out, /* fix scnptr's */ { - ulong ptr = section[0].s_scnptr; + off_t ptr = section[0].s_scnptr; bias = -1; for (scns = 0; scns < f_hdr.f_nscns; scns++) @@ -375,12 +380,12 @@ copy_text_and_data (int new) char *end; char *ptr; - lseek (new, (long) text_scnptr, SEEK_SET); - ptr = start_of_text () + text_scnptr; + lseek (new, text_scnptr, SEEK_SET); + ptr = _text + text_scnptr; end = ptr + f_ohdr.tsize; write_segment (new, ptr, end); - lseek (new, (long) data_scnptr, SEEK_SET); + lseek (new, data_scnptr, SEEK_SET); ptr = (char *) f_ohdr.data_start; end = ptr + f_ohdr.dsize; write_segment (new, ptr, end); @@ -393,7 +398,6 @@ static void write_segment (int new, char *ptr, char *end) { int i, nwrite, ret; - char buf[80]; char zeros[UnexBlockSz]; for (i = 0; ptr < end;) @@ -414,9 +418,13 @@ write_segment (int new, char *ptr, char *end) } else if (nwrite != ret) { + int write_errno = errno; + char buf[1000]; + void *addr = ptr; sprintf (buf, - "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d", - (unsigned long)ptr, new, nwrite, ret, errno); + "unexec write failure: addr %p, fileno %d, size 0x%x, wrote 0x%x, errno %d", + addr, new, nwrite, ret, errno); + errno = write_errno; PERROR (buf); } i += nwrite; @@ -537,13 +545,13 @@ unrelocate_symbols (int new, int a_out, int i; LDHDR ldhdr; LDREL ldrel; - ulong t_reloc = (ulong) &_text - f_ohdr.text_start; + off_t t_reloc = (intptr_t) _text - f_ohdr.text_start; #ifndef ALIGN_DATA_RELOC - ulong d_reloc = (ulong) &_data - f_ohdr.data_start; + off_t d_reloc = (intptr_t) _data - f_ohdr.data_start; #else /* This worked (and was needed) before AIX 4.2. I have no idea why. -- Mike */ - ulong d_reloc = (ulong) &_data - ALIGN (f_ohdr.data_start, 2); + off_t d_reloc = (intptr_t) _data - ALIGN (f_ohdr.data_start, 2); #endif int * p; @@ -628,16 +636,3 @@ unrelocate_symbols (int new, int a_out, } return 0; } - -/* - * Return the address of the start of the text segment prior to - * doing an unexec. After unexec the return value is undefined. - * See crt0.c for further explanation and _start. - * - */ - -char * -start_of_text (void) -{ - return ((char *) 0x10000000); -} diff --git a/src/unexcoff.c b/src/unexcoff.c index 466a5c0e491..2e662a34145 100644 --- a/src/unexcoff.c +++ b/src/unexcoff.c @@ -99,7 +99,7 @@ struct aouthdr #include <sys/file.h> -#include "mem-limits.h" +extern int etext; static long block_copy_start; /* Old executable start point */ static struct filehdr f_hdr; /* File header */ @@ -168,7 +168,7 @@ make_hdr (int new, int a_out, pagemask = getpagesize () - 1; /* Adjust text/data boundary. */ - data_start = (int) start_of_data (); + data_start = (int) DATA_START; data_start = ADDR_CORRECT (data_start); data_start = data_start & ~pagemask; /* (Down) to page boundary. */ diff --git a/src/unexw32.c b/src/unexw32.c index 66071295727..e8b553a87d3 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -722,7 +722,7 @@ unexec (const char *new_name, const char *old_name) /* Ignore old_name, and get our actual location from the OS. */ if (!GetModuleFileName (NULL, in_filename, MAX_PATH)) abort (); - dostounix_filename (in_filename); + dostounix_filename (in_filename, 0); strcpy (out_filename, in_filename); /* Change the base of the output filename to match the requested name. */ diff --git a/src/vm-limit.c b/src/vm-limit.c index 9dbb1b884b7..3fca8bd26c1 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c @@ -19,7 +19,37 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <unistd.h> /* for 'environ', on AIX */ #include "lisp.h" -#include "mem-limits.h" + +#ifdef MSDOS +#include <dpmi.h> +extern int etext; +#endif + +/* Some systems need this before <sys/resource.h>. */ +#include <sys/types.h> + +#ifdef HAVE_SYS_RESOURCE_H +# include <sys/time.h> +# include <sys/resource.h> +#else +# if HAVE_SYS_VLIMIT_H +# include <sys/vlimit.h> /* Obsolete, says glibc */ +# endif +#endif + +/* Start of data. It is OK if this is approximate; it's used only as + a heuristic. */ +#ifdef DATA_START +# define data_start ((char *) DATA_START) +#else +extern char data_start[]; +# ifndef HAVE_DATA_START +/* Initialize to nonzero, so that it's put into data and not bss. + Link this file's object code first, so that this symbol is near the + start of data. */ +char data_start[1] = { 1 }; +# endif +#endif /* Level number of warnings already issued. @@ -31,18 +61,24 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ enum warnlevel { not_warned, warned_75, warned_85, warned_95 }; static enum warnlevel warnlevel; -typedef void *POINTER; - /* Function to call to issue a warning; 0 means don't issue them. */ static void (*warn_function) (const char *); -/* Start of data space; can be changed by calling malloc_init. */ -static POINTER data_space_start; +/* Start of data space; can be changed by calling memory_warnings. */ +static char *data_space_start; /* Number of bytes of writable memory we can expect to be able to get. */ static size_t lim_data; +/* Return true if PTR cannot be represented as an Emacs Lisp object. */ +static bool +exceeds_lisp_ptr (void *ptr) +{ + return (! USE_LSB_TAG + && VAL_MAX < UINTPTR_MAX + && ((uintptr_t) ptr & ~DATA_SEG_BITS) >> VALBITS != 0); +} #ifdef HAVE_GETRLIMIT @@ -123,11 +159,13 @@ static void check_memory_limits (void) { #ifdef REL_ALLOC - extern POINTER (*real_morecore) (ptrdiff_t); + extern void *(*real_morecore) (ptrdiff_t); +#else + void *(*real_morecore) (ptrdiff_t) = 0; #endif - extern POINTER (*__morecore) (ptrdiff_t); + extern void *(*__morecore) (ptrdiff_t); - register POINTER cp; + char *cp; size_t five_percent; size_t data_size; enum warnlevel new_warnlevel; @@ -137,13 +175,8 @@ check_memory_limits (void) five_percent = lim_data / 20; /* Find current end of memory and issue warning if getting near max */ -#ifdef REL_ALLOC - if (real_morecore) - cp = (char *) (*real_morecore) (0); - else -#endif - cp = (char *) (*__morecore) (0); - data_size = (char *) cp - (char *) data_space_start; + cp = (real_morecore ? real_morecore : __morecore) (0); + data_size = cp - data_space_start; if (!warn_function) return; @@ -190,62 +223,20 @@ check_memory_limits (void) warnlevel = warned_85; } - if (EXCEEDS_LISP_PTR (cp)) + if (exceeds_lisp_ptr (cp)) (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); } -#if !defined (CANNOT_DUMP) || !defined (SYSTEM_MALLOC) -/* Some systems that cannot dump also cannot implement these. */ - -/* - * Return the address of the start of the data segment prior to - * doing an unexec. After unexec the return value is undefined. - * See crt0.c for further information and definition of data_start. - * - * Apparently, on BSD systems this is etext at startup. On - * USG systems (swapping) this is highly mmu dependent and - * is also dependent on whether or not the program is running - * with shared text. Generally there is a (possibly large) - * gap between end of text and start of data with shared text. - * - */ - -char * -start_of_data (void) -{ -#ifdef BSD_SYSTEM - extern char etext; - return (POINTER)(&etext); -#elif defined DATA_START - return ((POINTER) DATA_START); -#elif defined ORDINARY_LINK - /* - * This is a hack. Since we're not linking crt0.c or pre_crt0.c, - * data_start isn't defined. We take the address of environ, which - * is known to live at or near the start of the system crt0.c, and - * we don't sweat the handful of bytes that might lose. - */ - return ((POINTER) &environ); -#else - extern int data_start; - return ((POINTER) &data_start); -#endif -} -#endif /* (not CANNOT_DUMP or not SYSTEM_MALLOC) */ - /* Enable memory usage warnings. START says where the end of pure storage is. WARNFUN specifies the function to call to issue a warning. */ void -memory_warnings (POINTER start, void (*warnfun) (const char *)) +memory_warnings (void *start, void (*warnfun) (const char *)) { extern void (* __after_morecore_hook) (void); /* From gmalloc.c */ - if (start) - data_space_start = start; - else - data_space_start = start_of_data (); + data_space_start = start ? start : data_start; warn_function = warnfun; __after_morecore_hook = check_memory_limits; diff --git a/src/w16select.c b/src/w16select.c index c92276b1d29..3bcc663e565 100644 --- a/src/w16select.c +++ b/src/w16select.c @@ -532,13 +532,13 @@ DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_dat switch (put_status) { case 1: - message2 (no_mem_msg, sizeof (no_mem_msg) - 1, 0); + message3 (make_unibyte_string (no_mem_msg, sizeof (no_mem_msg) - 1)); break; case 2: - message2 (binary_msg, sizeof (binary_msg) - 1, 0); + message3 (make_unibyte_string (binary_msg, sizeof (binary_msg) - 1)); break; case 3: - message2 (system_error_msg, sizeof (system_error_msg) - 1, 0); + message3 (make_unibyte_string (system_error_msg, sizeof (system_error_msg) - 1)); break; } sit_for (make_number (2), 0, 2); diff --git a/src/w32.c b/src/w32.c index 812003e96c0..647faf94ef1 100644 --- a/src/w32.c +++ b/src/w32.c @@ -37,7 +37,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* must include CRT headers *before* config.h */ #include <config.h> -#include <mbstring.h> /* for _mbspbrk */ +#include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */ #undef access #undef chdir @@ -1531,35 +1531,110 @@ srandom (int seed) srand (seed); } +/* Current codepage for encoding file names. */ +static int file_name_codepage; + +/* Return the maximum length in bytes of a multibyte character + sequence encoded in the current ANSI codepage. This is required to + correctly walk the encoded file names one character at a time. */ +static int +max_filename_mbslen (void) +{ + /* A simple cache to avoid calling GetCPInfo every time we need to + normalize a file name. The file-name encoding is not supposed to + be changed too frequently, if ever. */ + static Lisp_Object last_file_name_encoding; + static int last_max_mbslen; + Lisp_Object current_encoding; + + current_encoding = Vfile_name_coding_system; + if (NILP (current_encoding)) + current_encoding = Vdefault_file_name_coding_system; + + if (!EQ (last_file_name_encoding, current_encoding)) + { + CPINFO cp_info; + + last_file_name_encoding = current_encoding; + /* Default to the current ANSI codepage. */ + file_name_codepage = w32_ansi_code_page; + if (!NILP (current_encoding)) + { + char *cpname = SDATA (SYMBOL_NAME (current_encoding)); + char *cp = NULL, *end; + int cpnum; + + if (strncmp (cpname, "cp", 2) == 0) + cp = cpname + 2; + else if (strncmp (cpname, "windows-", 8) == 0) + cp = cpname + 8; + + if (cp) + { + end = cp; + cpnum = strtol (cp, &end, 10); + if (cpnum && *end == '\0' && end - cp >= 2) + file_name_codepage = cpnum; + } + } + + if (!file_name_codepage) + file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */ + + if (!GetCPInfo (file_name_codepage, &cp_info)) + { + file_name_codepage = CP_ACP; + if (!GetCPInfo (file_name_codepage, &cp_info)) + emacs_abort (); + } + last_max_mbslen = cp_info.MaxCharSize; + } + + return last_max_mbslen; +} /* Normalize filename by converting all path separators to the specified separator. Also conditionally convert upper case path name components to lower case. */ static void -normalize_filename (register char *fp, char path_sep) +normalize_filename (register char *fp, char path_sep, int multibyte) { char sep; - char *elem; + char *elem, *p2; + int dbcs_p = max_filename_mbslen () > 1; + + /* Multibyte file names are in the Emacs internal representation, so + we can traverse them by bytes with no problems. */ + if (multibyte) + dbcs_p = 0; /* Always lower-case drive letters a-z, even if the filesystem preserves case in filenames. This is so filenames can be compared by string comparison functions that are case-sensitive. Even case-preserving filesystems do not distinguish case in drive letters. */ - if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z') + if (dbcs_p) + p2 = CharNextExA (file_name_codepage, fp, 0); + else + p2 = fp + 1; + + if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z') { *fp += 'a' - 'A'; fp += 2; } - if (NILP (Vw32_downcase_file_names)) + if (multibyte || NILP (Vw32_downcase_file_names)) { while (*fp) { if (*fp == '/' || *fp == '\\') *fp = path_sep; - fp++; + if (!dbcs_p) + fp++; + else + fp = CharNextExA (file_name_codepage, fp, 0); } return; } @@ -1582,27 +1657,36 @@ normalize_filename (register char *fp, char path_sep) if (elem && elem != fp) { *fp = 0; /* temporary end of string */ - _strlwr (elem); /* while we convert to lower case */ + _mbslwr (elem); /* while we convert to lower case */ } *fp = sep; /* convert (or restore) path separator */ elem = fp + 1; /* next element starts after separator */ sep = path_sep; } - } while (*fp++); + if (*fp) + { + if (!dbcs_p) + fp++; + else + fp = CharNextExA (file_name_codepage, fp, 0); + } + } while (*fp); } -/* Destructively turn backslashes into slashes. */ +/* Destructively turn backslashes into slashes. MULTIBYTE non-zero + means the file name is a multibyte string in Emacs's internal + representation. */ void -dostounix_filename (register char *p) +dostounix_filename (register char *p, int multibyte) { - normalize_filename (p, '/'); + normalize_filename (p, '/', multibyte); } /* Destructively turn slashes into backslashes. */ void unixtodos_filename (register char *p) { - normalize_filename (p, '\\'); + normalize_filename (p, '\\', 0); } /* Remove all CR's that are followed by a LF. @@ -1653,12 +1737,17 @@ parse_root (char * name, char ** pPath) else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) { int slashes = 2; + int dbcs_p = max_filename_mbslen () > 1; + name += 2; do { if (IS_DIRECTORY_SEP (*name) && --slashes == 0) break; - name++; + if (dbcs_p) + name = CharNextExA (file_name_codepage, name, 0); + else + name++; } while ( *name ); if (IS_DIRECTORY_SEP (name[0])) @@ -1723,7 +1812,7 @@ w32_get_long_filename (char * name, char * buf, int size) while (p != NULL && *p) { q = p; - p = strchr (q, '\\'); + p = _mbschr (q, '\\'); if (p) *p = '\0'; len = get_long_basename (full, o, size); if (len > 0) @@ -1995,16 +2084,16 @@ init_environment (char ** argv) if (!GetModuleFileName (NULL, modname, MAX_PATH)) emacs_abort (); - if ((p = strrchr (modname, '\\')) == NULL) + if ((p = _mbsrchr (modname, '\\')) == NULL) emacs_abort (); *p = 0; - if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) + if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) { char buf[SET_ENV_BUF_SIZE]; *p = 0; - for (p = modname; *p; p++) + for (p = modname; *p; p = CharNext (p)) if (*p == '\\') *p = '/'; _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); @@ -2019,17 +2108,17 @@ init_environment (char ** argv) || xstrcasecmp (p, "\\AMD64") == 0)) { *p = 0; - p = strrchr (modname, '\\'); + p = _mbsrchr (modname, '\\'); if (p != NULL) { *p = 0; - p = strrchr (modname, '\\'); + p = _mbsrchr (modname, '\\'); if (p && xstrcasecmp (p, "\\src") == 0) { char buf[SET_ENV_BUF_SIZE]; *p = 0; - for (p = modname; *p; p++) + for (p = modname; *p; p = CharNext (p)) if (*p == '\\') *p = '/'; _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); @@ -2140,7 +2229,7 @@ emacs_root_dir (void) emacs_abort (); strcpy (root_dir, p); root_dir[parse_root (root_dir, NULL)] = '\0'; - dostounix_filename (root_dir); + dostounix_filename (root_dir, 0); return root_dir; } @@ -2564,12 +2653,23 @@ get_volume_info (const char * name, const char ** pPath) { char *str = temp; int slashes = 4; + int dbcs_p = max_filename_mbslen () > 1; + rootname = temp; do { if (IS_DIRECTORY_SEP (*name) && --slashes == 0) break; - *str++ = *name++; + if (!dbcs_p) + *str++ = *name++; + else + { + const char *p = name; + + name = CharNextExA (file_name_codepage, name, 0); + memcpy (str, p, name - p); + str += name - p; + } } while ( *name ); @@ -2732,7 +2832,7 @@ static char *read_unc_volume (HANDLE, char *, int); static void close_unc_volume (HANDLE); DIR * -opendir (char *filename) +opendir (const char *filename) { DIR *dirp; @@ -2805,11 +2905,23 @@ readdir (DIR *dirp) { char filename[MAXNAMLEN + 3]; int ln; + int dbcs_p = max_filename_mbslen () > 1; strcpy (filename, dir_pathname); ln = strlen (filename) - 1; - if (!IS_DIRECTORY_SEP (filename[ln])) - strcat (filename, "\\"); + if (!dbcs_p) + { + if (!IS_DIRECTORY_SEP (filename[ln])) + strcat (filename, "\\"); + } + else + { + char *end = filename + ln + 1; + char *last_char = CharPrevExA (file_name_codepage, filename, end, 0); + + if (!IS_DIRECTORY_SEP (*last_char)) + strcat (filename, "\\"); + } strcat (filename, "*"); /* Note: No need to resolve symlinks in FILENAME, because @@ -2860,15 +2972,22 @@ readdir (DIR *dirp) strcpy (dir_static.d_name, dir_find_data.cFileName); dir_static.d_namlen = strlen (dir_static.d_name); if (dir_is_fat) - _strlwr (dir_static.d_name); + _mbslwr (dir_static.d_name); else if (downcase) { register char *p; - for (p = dir_static.d_name; *p; p++) - if (*p >= 'a' && *p <= 'z') - break; + int dbcs_p = max_filename_mbslen () > 1; + for (p = dir_static.d_name; *p; ) + { + if (*p >= 'a' && *p <= 'z') + break; + if (dbcs_p) + p = CharNextExA (file_name_codepage, p, 0); + else + p++; + } if (!*p) - _strlwr (dir_static.d_name); + _mbslwr (dir_static.d_name); } return &dir_static; @@ -2907,6 +3026,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size) DWORD bufsize = 512; char *buffer; char *ptr; + int dbcs_p = max_filename_mbslen () > 1; count = 1; buffer = alloca (bufsize); @@ -2917,7 +3037,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size) /* WNetEnumResource returns \\resource\share...skip forward to "share". */ ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; ptr += 2; - while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; + if (!dbcs_p) + while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; + else + { + while (*ptr && !IS_DIRECTORY_SEP (*ptr)) + ptr = CharNextExA (file_name_codepage, ptr, 0); + } ptr++; strncpy (readbuf, ptr, size); @@ -2954,9 +3080,11 @@ logon_network_drive (const char *path) { NETRESOURCE resource; char share[MAX_PATH]; - int i, n_slashes; + int n_slashes; char drive[4]; UINT drvtype; + char *p; + int dbcs_p; if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) drvtype = DRIVE_REMOTE; @@ -2978,13 +3106,18 @@ logon_network_drive (const char *path) n_slashes = 2; strncpy (share, path, MAX_PATH); /* Truncate to just server and share name. */ - for (i = 2; i < MAX_PATH; i++) + dbcs_p = max_filename_mbslen () > 1; + for (p = share + 2; *p && p < share + MAX_PATH; ) { - if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) + if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3) { - share[i] = '\0'; + *p = '\0'; break; } + if (dbcs_p) + p = CharNextExA (file_name_codepage, p, 0); + else + p++; } resource.dwType = RESOURCETYPE_DISK; @@ -3087,14 +3220,6 @@ sys_chmod (const char * path, int mode) } int -sys_chown (const char *path, uid_t owner, gid_t group) -{ - if (sys_chmod (path, S_IREAD) == -1) /* check if file exists */ - return -1; - return 0; -} - -int sys_creat (const char * path, int mode) { return _creat (map_w32_filename (path, NULL), mode); @@ -3277,17 +3402,27 @@ int sys_open (const char * path, int oflag, int mode) { const char* mpath = map_w32_filename (path, NULL); - /* Try to open file without _O_CREAT, to be able to write to hidden - and system files. Force all file handles to be - non-inheritable. */ - int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); - if (res >= 0) - return res; - return _open (mpath, oflag | _O_NOINHERIT, mode); + int res = -1; + + /* If possible, try to open file without _O_CREAT, to be able to + write to existing hidden and system files. Force all file + handles to be non-inheritable. */ + if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL)) + res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); + if (res < 0) + res = _open (mpath, oflag | _O_NOINHERIT, mode); + + return res; +} + +int +fchmod (int fd, mode_t mode) +{ + return 0; } int -sys_rename (const char * oldname, const char * newname) +sys_rename_replace (const char *oldname, const char *newname, BOOL force) { BOOL result; char temp[MAX_PATH]; @@ -3343,7 +3478,7 @@ sys_rename (const char * oldname, const char * newname) return -1; } - /* Emulate Unix behavior - newname is deleted if it already exists + /* If FORCE, emulate Unix behavior - newname is deleted if it already exists (at least if it is a file; don't do this for directories). Since we mustn't do this if we are just changing the case of the @@ -3361,7 +3496,7 @@ sys_rename (const char * oldname, const char * newname) result = rename (temp, newname); - if (result < 0) + if (result < 0 && force) { DWORD w32err = GetLastError (); @@ -3401,6 +3536,12 @@ sys_rename (const char * oldname, const char * newname) } int +sys_rename (char const *old, char const *new) +{ + return sys_rename_replace (old, new, TRUE); +} + +int sys_rmdir (const char * path) { return _rmdir (map_w32_filename (path, NULL)); @@ -3759,6 +3900,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) DWORD access_rights = 0; DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; FILETIME ctime, atime, wtime; + int dbcs_p; if (path == NULL || buf == NULL) { @@ -3956,6 +4098,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) did not ask for extra precision, resolving symlinks will fly in the face of that request, since the user then wants the lightweight version of the code. */ + dbcs_p = max_filename_mbslen () > 1; rootdir = (path >= save_name + len - 1 && (IS_DIRECTORY_SEP (*path) || *path == 0)); @@ -3983,8 +4126,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) } else if (rootdir) { - if (!IS_DIRECTORY_SEP (name[len-1])) - strcat (name, "\\"); + if (!dbcs_p) + { + if (!IS_DIRECTORY_SEP (name[len-1])) + strcat (name, "\\"); + } + else + { + char *end = name + len; + char *n = CharPrevExA (file_name_codepage, name, end, 0); + + if (!IS_DIRECTORY_SEP (*n)) + strcat (name, "\\"); + } if (GetDriveType (name) < 2) { errno = ENOENT; @@ -3996,15 +4150,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) } else { - if (IS_DIRECTORY_SEP (name[len-1])) - name[len - 1] = 0; + if (!dbcs_p) + { + if (IS_DIRECTORY_SEP (name[len-1])) + name[len - 1] = 0; + } + else + { + char *end = name + len; + char *n = CharPrevExA (file_name_codepage, name, end, 0); + + if (IS_DIRECTORY_SEP (*n)) + *n = 0; + } /* (This is hacky, but helps when doing file completions on network drives.) Optimize by using information available from active readdir if possible. */ len = strlen (dir_pathname); - if (IS_DIRECTORY_SEP (dir_pathname[len-1])) - len--; + if (!dbcs_p) + { + if (IS_DIRECTORY_SEP (dir_pathname[len-1])) + len--; + } + else + { + char *end = dir_pathname + len; + char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0); + + if (IS_DIRECTORY_SEP (*n)) + len--; + } if (dir_find_handle != INVALID_HANDLE_VALUE && !(is_a_symlink && follow_symlinks) && strnicmp (save_name, dir_pathname, len) == 0 @@ -4110,6 +4286,30 @@ lstat (const char * path, struct stat * buf) return stat_worker (path, buf, 0); } +int +fstatat (int fd, char const *name, struct stat *st, int flags) +{ + /* Rely on a hack: an open directory is modeled as file descriptor 0. + This is good enough for the current usage in Emacs, but is fragile. + + FIXME: Add proper support for fdopendir, fstatat, readlinkat. + Gnulib does this and can serve as a model. */ + char fullname[MAX_PATH]; + + if (fd != AT_FDCWD) + { + if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name) + < 0) + { + errno = ENAMETOOLONG; + return -1; + } + name = fullname; + } + + return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW)); +} + /* Provide fstat and utime as well as stat for consistent handling of file timestamps. */ int @@ -4164,13 +4364,23 @@ fstat (int desc, struct stat * buf) else buf->st_ino = fake_inode; - /* Consider files to belong to current user. - FIXME: this should use GetSecurityInfo API, but it is only - available for _WIN32_WINNT >= 0x501. */ - buf->st_uid = dflt_passwd.pw_uid; - buf->st_gid = dflt_passwd.pw_gid; - strcpy (buf->st_uname, dflt_passwd.pw_name); - strcpy (buf->st_gname, dflt_group.gr_name); + /* If the caller so requested, get the true file owner and group. + Otherwise, consider the file to belong to the current user. */ + if (!w32_stat_get_owner_group || is_windows_9x () == TRUE) + get_file_owner_and_group (NULL, buf); + else + { + PSECURITY_DESCRIPTOR psd = NULL; + + psd = get_file_security_desc_by_handle (fh); + if (psd) + { + get_file_owner_and_group (psd, buf); + LocalFree (psd); + } + else + get_file_owner_and_group (NULL, buf); + } buf->st_dev = info.dwVolumeSerialNumber; buf->st_rdev = info.dwVolumeSerialNumber; @@ -4265,6 +4475,7 @@ symlink (char const *filename, char const *linkname) char linkfn[MAX_PATH], *tgtfn; DWORD flags = 0; int dir_access, filename_ends_in_slash; + int dbcs_p; /* Diagnostics follows Posix as much as possible. */ if (filename == NULL || linkname == NULL) @@ -4290,6 +4501,8 @@ symlink (char const *filename, char const *linkname) return -1; } + dbcs_p = max_filename_mbslen () > 1; + /* Note: since empty FILENAME was already rejected, we can safely refer to FILENAME[1]. */ if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) @@ -4304,8 +4517,21 @@ symlink (char const *filename, char const *linkname) char tem[MAX_PATH]; char *p = linkfn + strlen (linkfn); - while (p > linkfn && !IS_ANY_SEP (p[-1])) - p--; + if (!dbcs_p) + { + while (p > linkfn && !IS_ANY_SEP (p[-1])) + p--; + } + else + { + char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0); + + while (p > linkfn && !IS_ANY_SEP (*p1)) + { + p = p1; + p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0); + } + } if (p > linkfn) strncpy (tem, linkfn, p - linkfn); tem[p - linkfn] = '\0'; @@ -4320,7 +4546,15 @@ symlink (char const *filename, char const *linkname) exist, but ends in a slash, we create a symlink to directory. If FILENAME exists and is a directory, we always create a symlink to directory. */ - filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); + if (!dbcs_p) + filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); + else + { + const char *end = filename + strlen (filename); + const char *n = CharPrevExA (file_name_codepage, filename, end, 0); + + filename_ends_in_slash = IS_DIRECTORY_SEP (*n); + } if (dir_access == 0 || filename_ends_in_slash) flags = SYMBOLIC_LINK_FLAG_DIRECTORY; @@ -4510,6 +4744,8 @@ readlink (const char *name, char *buf, size_t buf_size) WCHAR *lwname_src = reparse_data->SymbolicLinkReparseBuffer.PathBuffer + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); + /* This updates file_name_codepage which we need below. */ + int dbcs_p = max_filename_mbslen () > 1; /* According to MSDN, PrintNameLength does not include the terminating null character. */ @@ -4517,9 +4753,7 @@ readlink (const char *name, char *buf, size_t buf_size) memcpy (lwname, lwname_src, lwname_len); lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ - /* FIXME: Should we use the current file-name coding system - instead of the fixed value of the ANSI codepage? */ - lname_len = WideCharToMultiByte (w32_ansi_code_page, 0, lwname, -1, + lname_len = WideCharToMultiByte (file_name_codepage, 0, lwname, -1, lname, MAX_PATH, NULL, NULL); if (!lname_len) { @@ -4545,18 +4779,33 @@ readlink (const char *name, char *buf, size_t buf_size) else { size_t size_to_copy = buf_size; - BYTE *p = lname; + BYTE *p = lname, *p2; BYTE *pend = p + lname_len; /* Normalize like dostounix_filename does, but we don't want to assume that lname is null-terminated. */ - if (*p && p[1] == ':' && *p >= 'A' && *p <= 'Z') - *p += 'a' - 'A'; + if (dbcs_p) + p2 = CharNextExA (file_name_codepage, p, 0); + else + p2 = p + 1; + if (*p && *p2 == ':' && *p >= 'A' && *p <= 'Z') + { + *p += 'a' - 'A'; + p += 2; + } while (p <= pend) { if (*p == '\\') *p = '/'; - ++p; + if (dbcs_p) + { + p = CharNextExA (file_name_codepage, p, 0); + /* CharNextExA doesn't advance at null character. */ + if (!*p) + break; + } + else + ++p; } /* Testing for null-terminated LNAME is paranoia: WideCharToMultiByte should always return a @@ -4603,6 +4852,28 @@ readlink (const char *name, char *buf, size_t buf_size) return retval; } +ssize_t +readlinkat (int fd, char const *name, char *buffer, + size_t buffer_size) +{ + /* Rely on a hack: an open directory is modeled as file descriptor 0, + as in fstatat. FIXME: Add proper support for readlinkat. */ + char fullname[MAX_PATH]; + + if (fd != AT_FDCWD) + { + if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name) + < 0) + { + errno = ENAMETOOLONG; + return -1; + } + name = fullname; + } + + return readlink (name, buffer, buffer_size); +} + /* If FILE is a symlink, return its target (stored in a static buffer); otherwise return FILE. @@ -4630,6 +4901,7 @@ chase_symlinks (const char *file) char link[MAX_PATH]; ssize_t res, link_len; int loop_count = 0; + int dbcs_p; if (is_windows_9x () == TRUE || !is_symlink (file)) return (char *)file; @@ -4637,13 +4909,27 @@ chase_symlinks (const char *file) if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) return (char *)file; + dbcs_p = max_filename_mbslen () > 1; target[0] = '\0'; do { /* Remove trailing slashes, as we want to resolve the last non-trivial part of the link name. */ - while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) - link[link_len--] = '\0'; + if (!dbcs_p) + { + while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) + link[link_len--] = '\0'; + } + else if (link_len > 3) + { + char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0); + + while (n >= link + 2 && IS_DIRECTORY_SEP (*n)) + { + n[1] = '\0'; + n = CharPrevExA (file_name_codepage, link, n, 0); + } + } res = readlink (link, target, MAX_PATH); if (res > 0) @@ -4656,8 +4942,21 @@ chase_symlinks (const char *file) the symlink, then copy the result back to target. */ char *p = link + link_len; - while (p > link && !IS_ANY_SEP (p[-1])) - p--; + if (!dbcs_p) + { + while (p > link && !IS_ANY_SEP (p[-1])) + p--; + } + else + { + char *p1 = CharPrevExA (file_name_codepage, link, p, 0); + + while (p > link && !IS_ANY_SEP (*p1)) + { + p = p1; + p1 = CharPrevExA (file_name_codepage, link, p1, 0); + } + } strcpy (p, target); strcpy (target, link); } @@ -4858,50 +5157,57 @@ acl_set_file (const char *fname, acl_type_t type, acl_t acl) e = errno; errno = 0; - set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl); - err = GetLastError (); - if (st) + if (!set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl)) { - if (st >= 2) - restore_privilege (&old2); - restore_privilege (&old1); - revert_to_self (); - } - - if (errno == ENOTSUP) - ; - else if (err == ERROR_SUCCESS) - { - retval = 0; - errno = e; - } - else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED) - { - /* Maybe the requested ACL and the one the file already has are - identical, in which case we can silently ignore the - failure. (And no, Windows doesn't.) */ - acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS); + err = GetLastError (); - errno = EPERM; - if (current_acl) + if (errno == ENOTSUP) + ; + else if (err == ERROR_INVALID_OWNER + || err == ERROR_NOT_ALL_ASSIGNED + || err == ERROR_ACCESS_DENIED) { - char *acl_from = acl_to_text (current_acl, NULL); - char *acl_to = acl_to_text (acl, NULL); + /* Maybe the requested ACL and the one the file already has + are identical, in which case we can silently ignore the + failure. (And no, Windows doesn't.) */ + acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS); - if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0) + errno = EPERM; + if (current_acl) { - retval = 0; - errno = e; + char *acl_from = acl_to_text (current_acl, NULL); + char *acl_to = acl_to_text (acl, NULL); + + if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0) + { + retval = 0; + errno = e; + } + if (acl_from) + acl_free (acl_from); + if (acl_to) + acl_free (acl_to); + acl_free (current_acl); } - if (acl_from) - acl_free (acl_from); - if (acl_to) - acl_free (acl_to); - acl_free (current_acl); } + else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + errno = ENOENT; + else + errno = EACCES; + } + else + { + retval = 0; + errno = e; + } + + if (st) + { + if (st >= 2) + restore_privilege (&old2); + restore_privilege (&old1); + revert_to_self (); } - else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) - errno = ENOENT; return retval; } @@ -4920,12 +5226,6 @@ careadlinkat (int fd, char const *filename, char linkname[MAX_PATH]; ssize_t link_size; - if (fd != AT_FDCWD) - { - errno = EINVAL; - return NULL; - } - link_size = preadlinkat (fd, filename, linkname, sizeof(linkname)); if (link_size > 0) @@ -4943,14 +5243,6 @@ careadlinkat (int fd, char const *filename, return NULL; } -ssize_t -careadlinkatcwd (int fd, char const *filename, char *buffer, - size_t buffer_size) -{ - (void) fd; - return readlink (filename, buffer, buffer_size); -} - /* Support for browsing other processes and their attributes. See process.c for the Lisp bindings. */ @@ -5288,10 +5580,8 @@ ltime (ULONGLONG time_100ns) { ULONGLONG time_sec = time_100ns / 10000000; int subsec = time_100ns % 10000000; - return list4 (make_number (time_sec >> 16), - make_number (time_sec & 0xffff), - make_number (subsec / 10), - make_number (subsec % 10 * 100000)); + return list4i (time_sec >> 16, time_sec & 0xffff, + subsec / 10, subsec % 10 * 100000); } #define U64_TO_LISP_TIME(time) ltime (time) @@ -5805,35 +6095,39 @@ init_winsock (int load_now) int h_errno = 0; -/* function to set h_errno for compatibility; map winsock error codes to - normal system codes where they overlap (non-overlapping definitions - are already in <sys/socket.h> */ +/* Function to map winsock error codes to errno codes for those errno + code defined in errno.h (errno values not defined by errno.h are + already in nt/inc/sys/socket.h). */ static void set_errno (void) { + int wsa_err; + + h_errno = 0; if (winsock_lib == NULL) - h_errno = EINVAL; + wsa_err = EINVAL; else - h_errno = pfn_WSAGetLastError (); + wsa_err = pfn_WSAGetLastError (); - switch (h_errno) + switch (wsa_err) { - case WSAEACCES: h_errno = EACCES; break; - case WSAEBADF: h_errno = EBADF; break; - case WSAEFAULT: h_errno = EFAULT; break; - case WSAEINTR: h_errno = EINTR; break; - case WSAEINVAL: h_errno = EINVAL; break; - case WSAEMFILE: h_errno = EMFILE; break; - case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break; - case WSAENOTEMPTY: h_errno = ENOTEMPTY; break; + case WSAEACCES: errno = EACCES; break; + case WSAEBADF: errno = EBADF; break; + case WSAEFAULT: errno = EFAULT; break; + case WSAEINTR: errno = EINTR; break; + case WSAEINVAL: errno = EINVAL; break; + case WSAEMFILE: errno = EMFILE; break; + case WSAENAMETOOLONG: errno = ENAMETOOLONG; break; + case WSAENOTEMPTY: errno = ENOTEMPTY; break; + default: errno = wsa_err; break; } - errno = h_errno; } static void check_errno (void) { - if (h_errno == 0 && winsock_lib != NULL) + h_errno = 0; + if (winsock_lib != NULL) pfn_WSASetLastError (0); } @@ -5945,7 +6239,7 @@ sys_socket (int af, int type, int protocol) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return INVALID_SOCKET; } @@ -6022,6 +6316,7 @@ socket_to_fd (SOCKET s) } } } + eassert (fd < MAXDESC); fd_info[fd].hnd = (HANDLE) s; /* set our own internal flags */ @@ -6050,8 +6345,9 @@ socket_to_fd (SOCKET s) /* clean up */ _close (fd); } + else pfn_closesocket (s); - h_errno = EMFILE; + errno = EMFILE; return -1; } @@ -6060,7 +6356,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen) { if (winsock_lib == NULL) { - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6072,7 +6368,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6081,7 +6377,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen) { if (winsock_lib == NULL) { - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6093,7 +6389,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6122,12 +6418,20 @@ int sys_gethostname (char * name, int namelen) { if (winsock_lib != NULL) - return pfn_gethostname (name, namelen); + { + int retval; + + check_errno (); + retval = pfn_gethostname (name, namelen); + if (retval == SOCKET_ERROR) + set_errno (); + return retval; + } if (namelen > MAX_COMPUTERNAME_LENGTH) return !GetComputerName (name, (DWORD *)&namelen); - h_errno = EFAULT; + errno = EFAULT; return SOCKET_ERROR; } @@ -6135,17 +6439,24 @@ struct hostent * sys_gethostbyname (const char * name) { struct hostent * host; + int h_err = h_errno; if (winsock_lib == NULL) { - h_errno = ENETDOWN; + h_errno = NO_RECOVERY; + errno = ENETDOWN; return NULL; } check_errno (); host = pfn_gethostbyname (name); if (!host) - set_errno (); + { + set_errno (); + h_errno = errno; + } + else + h_errno = h_err; return host; } @@ -6156,7 +6467,7 @@ sys_getservbyname (const char * name, const char * proto) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return NULL; } @@ -6172,7 +6483,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6184,7 +6495,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6193,7 +6504,7 @@ sys_shutdown (int s, int how) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6205,7 +6516,7 @@ sys_shutdown (int s, int how) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6214,7 +6525,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6227,7 +6538,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6236,7 +6547,7 @@ sys_listen (int s, int backlog) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6250,7 +6561,7 @@ sys_listen (int s, int backlog) fd_info[s].flags |= FILE_LISTEN; return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6259,7 +6570,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6271,7 +6582,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6280,7 +6591,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return -1; } @@ -6294,11 +6605,14 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen) else fd = socket_to_fd (t); - fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; - ResetEvent (fd_info[s].cp->char_avail); + if (fd >= 0) + { + fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; + ResetEvent (fd_info[s].cp->char_avail); + } return fd; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return -1; } @@ -6308,7 +6622,7 @@ sys_recvfrom (int s, char * buf, int len, int flags, { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6320,7 +6634,7 @@ sys_recvfrom (int s, char * buf, int len, int flags, set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6330,7 +6644,7 @@ sys_sendto (int s, const char * buf, int len, int flags, { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6342,7 +6656,7 @@ sys_sendto (int s, const char * buf, int len, int flags, set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6353,7 +6667,7 @@ fcntl (int s, int cmd, int options) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return -1; } @@ -6372,11 +6686,11 @@ fcntl (int s, int cmd, int options) } else { - h_errno = EINVAL; + errno = EINVAL; return SOCKET_ERROR; } } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6442,15 +6756,15 @@ sys_close (int fd) } } + if (fd >= 0 && fd < MAXDESC) + fd_info[fd].flags = 0; + /* Note that sockets do not need special treatment here (at least on NT and Windows 95 using the standard tcp/ip stacks) - it appears that closesocket is equivalent to CloseHandle, which is to be expected because socket handles are fully fledged kernel handles. */ rc = _close (fd); - if (rc == 0 && fd < MAXDESC) - fd_info[fd].flags = 0; - return rc; } @@ -6513,6 +6827,7 @@ sys_pipe (int * phandles) { _close (phandles[0]); _close (phandles[1]); + errno = EMFILE; rc = -1; } else @@ -6586,19 +6901,31 @@ _sys_read_ahead (int fd) /* Configure timeouts for blocking read. */ if (!GetCommTimeouts (hnd, &ct)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } ct.ReadIntervalTimeout = 0; ct.ReadTotalTimeoutMultiplier = 0; ct.ReadTotalTimeoutConstant = 0; if (!SetCommTimeouts (hnd, &ct)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl)) { if (GetLastError () != ERROR_IO_PENDING) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } } } else if (fd_info[fd].flags & FILE_SOCKET) @@ -6794,7 +7121,7 @@ sys_read (int fd, char * buffer, unsigned int count) pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); if (waiting == 0 && nchars == 0) { - h_errno = errno = EWOULDBLOCK; + errno = EWOULDBLOCK; return -1; } @@ -7506,47 +7833,26 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) ssize_t emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz) { - int n, sc, err; + int n, err; SELECT_TYPE fdset; EMACS_TIME timeout; struct Lisp_Process *process = (struct Lisp_Process *)p; int fd = process->infd; - for (;;) - { - n = sys_read (fd, (char*)buf, sz); + n = sys_read (fd, (char*)buf, sz); - if (n >= 0) - return n; + if (n >= 0) + return n; - err = errno; + err = errno; - if (err == EWOULDBLOCK) - { - /* Set a small timeout. */ - timeout = make_emacs_time (1, 0); - FD_ZERO (&fdset); - FD_SET ((int)fd, &fdset); - - /* Use select with the timeout to poll the selector. */ - sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0, - &timeout, NULL); - - if (sc > 0) - continue; /* Try again. */ - - /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. - Also accept select return 0 as an indicator to EAGAIN. */ - if (sc == 0 || errno == EWOULDBLOCK) - err = EAGAIN; - else - err = errno; /* Other errors are just passed on. */ - } + /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */ + if (err == EWOULDBLOCK) + err = EAGAIN; - emacs_gnutls_transport_set_errno (process->gnutls_state, err); + emacs_gnutls_transport_set_errno (process->gnutls_state, err); - return -1; - } + return -1; } ssize_t diff --git a/src/w32.h b/src/w32.h index 895e7f31d63..17da0778db1 100644 --- a/src/w32.h +++ b/src/w32.h @@ -180,12 +180,14 @@ extern void init_environment (char **); extern void check_windows_init_file (void); extern void syms_of_ntproc (void); extern void syms_of_ntterm (void); -extern void dostounix_filename (register char *); +extern void dostounix_filename (register char *, int); extern void unixtodos_filename (register char *); extern BOOL init_winsock (int load_now); extern void srandom (int); extern int random (void); +extern int fchmod (int, mode_t); +extern int sys_rename_replace (char const *, char const *, BOOL); extern int sys_pipe (int *); extern void set_process_dir (char *); diff --git a/src/w32fns.c b/src/w32fns.c index 355ee96b9f3..6fd980c6b70 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -4587,12 +4587,9 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, CHECK_STRING (color); if (w32_defined_color (f, SDATA (color), &foo, 0)) - return list3 (make_number ((GetRValue (foo.pixel) << 8) - | GetRValue (foo.pixel)), - make_number ((GetGValue (foo.pixel) << 8) - | GetGValue (foo.pixel)), - make_number ((GetBValue (foo.pixel) << 8) - | GetBValue (foo.pixel))); + return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel), + (GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel), + (GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel)); else return Qnil; } @@ -4718,9 +4715,7 @@ DISPLAY should be either a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. */) (Lisp_Object display) { - return Fcons (make_number (w32_major_version), - Fcons (make_number (w32_minor_version), - Fcons (make_number (w32_build_number), Qnil))); + return list3i (w32_major_version, w32_minor_version, w32_build_number); } DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, @@ -5943,7 +5938,7 @@ Text larger than the specified size is clipped. */) SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); /* Let redisplay know that we have made the frame visible already. */ - f->async_visible = 1; + SET_FRAME_VISIBLE (f, 1); ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE); } @@ -6254,7 +6249,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) /* we get one of the two final 0 bytes for free. */ 1 + sizeof (wchar_t) * wcslen (filename_buf))); #else /* !NTGUI_UNICODE */ - dostounix_filename (filename_buf); + dostounix_filename (filename_buf, 0); filename = DECODE_FILE (build_string (filename_buf)); #endif /* NTGUI_UNICODE */ @@ -6484,12 +6479,12 @@ w32_parse_hot_key (Lisp_Object key) CHECK_VECTOR (key); - if (XFASTINT (Flength (key)) != 1) + if (ASIZE (key) != 1) return Qnil; GCPRO1 (key); - c = Faref (key, make_number (0)); + c = AREF (key, 0); if (CONSP (c) && lucid_event_type_list_p (c)) c = Fevent_convert_list (c); diff --git a/src/w32heap.c b/src/w32heap.c index 9c189dbda6d..81206ce2834 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -98,7 +98,11 @@ allocate_heap (void) #ifdef _WIN64 size_t size = 0x4000000000i64; /* start by asking for 32GB */ #else - size_t size = 0x80000000; /* start by asking for 2GB */ + /* We used to start with 2GB here, but on Windows 7 that would leave + too little room in the address space for threads started by + Windows on our behalf, e.g. when we pop up the file selection + dialog. */ + size_t size = 0x68000000; /* start by asking for 1.7GB */ #endif void *ptr = NULL; diff --git a/src/w32notify.c b/src/w32notify.c index d78e55f43ed..1bcaa794565 100644 --- a/src/w32notify.c +++ b/src/w32notify.c @@ -442,8 +442,8 @@ DEFUN ("w32notify-add-watch", Fw32notify_add_watch, This arranges for filesystem events pertaining to FILE to be reported to Emacs. Use `w32notify-rm-watch' to cancel the watch. -Value is a descriptor for the added watch, or nil if the file -cannot be watched. +Value is a descriptor for the added watch. If the file cannot be +watched for some reason, this function signals a `file-error' error. FILTER is a list of conditions for reporting an event. It can include the following symbols: @@ -476,7 +476,13 @@ following: 'renamed-from' -- a file was renamed whose old name was FILE 'renamed-to' -- a file was renamed and its new name is FILE -FILE is the name of the file whose event is being reported. */) +FILE is the name of the file whose event is being reported. + +Note that some networked filesystems, such as Samba-mounted Unix +volumes, might not send notifications about file changes. In these +cases, this function will return a valid descriptor, but notifications +will never come in. Volumes shared from remote Windows machines do +generate notifications correctly, though. */) (Lisp_Object file, Lisp_Object filter, Lisp_Object callback) { Lisp_Object encoded_file, watch_object, watch_descriptor; diff --git a/src/w32proc.c b/src/w32proc.c index 0fcb2993020..84589388cd7 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -803,10 +803,58 @@ new_child (void) if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL) goto Initialize; if (child_proc_count == MAX_CHILDREN) + { + int i = 0; + child_process *dead_cp = NULL; + + DebPrint (("new_child: No vacant slots, looking for dead processes\n")); + for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) + if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess) + { + DWORD status = 0; + + if (!GetExitCodeProcess (cp->procinfo.hProcess, &status)) + { + DebPrint (("new_child.GetExitCodeProcess: error %lu for PID %lu\n", + GetLastError (), cp->procinfo.dwProcessId)); + status = STILL_ACTIVE; + } + if (status != STILL_ACTIVE + || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0) + { + DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n", + cp->procinfo.dwProcessId, cp->fd)); + CloseHandle (cp->procinfo.hProcess); + cp->procinfo.hProcess = NULL; + CloseHandle (cp->procinfo.hThread); + cp->procinfo.hThread = NULL; + /* Free up to 2 dead slots at a time, so that if we + have a lot of them, they will eventually all be + freed when the tornado ends. */ + if (i == 0) + dead_cp = cp; + else + break; + i++; + } + } + if (dead_cp) + { + cp = dead_cp; + goto Initialize; + } + } + if (child_proc_count == MAX_CHILDREN) return NULL; cp = &child_procs[child_proc_count++]; Initialize: + /* Last opportunity to avoid leaking handles before we forget them + for good. */ + if (cp->procinfo.hProcess) + CloseHandle (cp->procinfo.hProcess); + if (cp->procinfo.hThread) + CloseHandle (cp->procinfo.hThread); memset (cp, 0, sizeof (*cp)); cp->fd = -1; cp->pid = -1; @@ -979,8 +1027,9 @@ reader_thread (void *arg) read-ahead has completed, whether successfully or not. */ if (!SetEvent (cp->char_avail)) { - DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n", - GetLastError (), cp->fd)); + DebPrint (("reader_thread.SetEvent(0x%x) failed with %lu for fd %ld (PID %d)\n", + (DWORD_PTR)cp->char_avail, GetLastError (), + cp->fd, cp->pid)); return 1; } @@ -1541,7 +1590,6 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) child_process *cp; int is_dos_app, is_cygnus_app, is_gui_app; int do_quoting = 0; - char escape_char; /* We pass our process ID to our children by setting up an environment variable in their environment. */ char ppid_env_var_buffer[64]; @@ -1554,6 +1602,8 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) Some extra whitespace characters need quoting in Cygwin programs, so this list is conditionally modified below. */ char *sepchars = " \t*?"; + /* This is for native w32 apps; modified below for Cygwin apps. */ + char escape_char = '\\'; /* We don't care about the other modes */ if (mode != _P_NOWAIT) @@ -2007,7 +2057,7 @@ count_children: /* Some child_procs might be sockets; ignore them. Also some children may have died already, but we haven't finished reading the process output; ignore them too. */ - if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess + if ((CHILD_ACTIVE (cp) && cp->procinfo.hProcess) && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) @@ -2213,12 +2263,42 @@ sys_kill (pid_t pid, int sig) pid = -pid; /* Only handle signals that will result in the process dying */ - if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) + if (sig != 0 + && sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) { errno = EINVAL; return -1; } + if (sig == 0) + { + /* It will take _some_ time before PID 4 or less on Windows will + be Emacs... */ + if (pid <= 4) + { + errno = EPERM; + return -1; + } + proc_hand = OpenProcess (PROCESS_QUERY_INFORMATION, 0, pid); + if (proc_hand == NULL) + { + DWORD err = GetLastError (); + + switch (err) + { + case ERROR_ACCESS_DENIED: /* existing process, but access denied */ + errno = EPERM; + return -1; + case ERROR_INVALID_PARAMETER: /* process PID does not exist */ + errno = ESRCH; + return -1; + } + } + else + CloseHandle (proc_hand); + return 0; + } + cp = find_child_pid (pid); if (cp == NULL) { @@ -2557,8 +2637,9 @@ All path elements in FILENAME are converted to their short names. */) if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0) return Qnil; - dostounix_filename (shortname); + dostounix_filename (shortname, 0); + /* No need to DECODE_FILE, because 8.3 names are pure ASCII. */ return build_string (shortname); } @@ -2585,7 +2666,7 @@ All path elements in FILENAME are converted to their long names. */) if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH)) return Qnil; - dostounix_filename (longname); + dostounix_filename (longname, 0); /* If we were passed only a drive, make sure that a slash is not appended for consistency with directories. Allow for drive mapping via SUBST diff --git a/src/w32term.c b/src/w32term.c index 16c7bd415a5..170f33ecd67 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -191,11 +191,7 @@ static Time last_mouse_movement_time; /* Incremented by w32_read_socket whenever it really tries to read events. */ -#ifdef __STDC__ static int volatile input_signal_count; -#else -static int input_signal_count; -#endif #ifdef CYGWIN int w32_message_fd = -1; @@ -4319,24 +4315,25 @@ w32_read_socket (struct terminal *terminal, DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f, SDATA (f->name))); } - else if (f->async_visible != 1) + else if (FRAME_VISIBLE_P (f) != 1) { + bool iconified = FRAME_ICONIFIED_P (f); + /* Definitely not obscured, so mark as visible. */ - f->async_visible = 1; - f->async_iconified = 0; + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, 0); SET_FRAME_GARBAGED (f); DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f, SDATA (f->name))); /* WM_PAINT serves as MapNotify as well, so report visibility changes properly. */ - if (f->iconified) + if (iconified) { inev.kind = DEICONIFY_EVENT; XSETFRAME (inev.frame_or_window, f); } - else if (! NILP (Vframe_list) - && ! NILP (XCDR (Vframe_list))) + else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list))) /* Force a redisplay sooner or later to update the frame titles in case this is the second frame. */ record_asynch_buffer_change (); @@ -4379,7 +4376,7 @@ w32_read_socket (struct terminal *terminal, case WM_SYSKEYDOWN: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); - if (f && !f->iconified) + if (f && !FRAME_ICONIFIED_P (f)) { if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) && !EQ (f->tool_bar_window, hlinfo->mouse_face_window)) @@ -4404,7 +4401,7 @@ w32_read_socket (struct terminal *terminal, case WM_CHAR: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); - if (f && !f->iconified) + if (f && !FRAME_ICONIFIED_P (f)) { if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) && !EQ (f->tool_bar_window, hlinfo->mouse_face_window)) @@ -4482,7 +4479,7 @@ w32_read_socket (struct terminal *terminal, case WM_APPCOMMAND: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); - if (f && !f->iconified) + if (f && !FRAME_ICONIFIED_P (f)) { if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) && !EQ (f->tool_bar_window, hlinfo->mouse_face_window)) @@ -4722,7 +4719,7 @@ w32_read_socket (struct terminal *terminal, case WM_MOVE: f = x_window_to_frame (dpyinfo, msg.msg.hwnd); - if (f && !f->async_iconified) + if (f && !FRAME_ICONIFIED_P (f)) { int x, y; @@ -4770,8 +4767,8 @@ w32_read_socket (struct terminal *terminal, switch (msg.msg.wParam) { case SIZE_MINIMIZED: - f->async_visible = 0; - f->async_iconified = 1; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 1); inev.kind = ICONIFY_EVENT; XSETFRAME (inev.frame_or_window, f); @@ -4779,40 +4776,44 @@ w32_read_socket (struct terminal *terminal, case SIZE_MAXIMIZED: case SIZE_RESTORED: - f->async_visible = 1; - f->async_iconified = 0; - - /* wait_reading_process_output will notice this and update - the frame's display structures. */ - SET_FRAME_GARBAGED (f); + { + bool iconified = FRAME_ICONIFIED_P (f); - if (f->iconified) - { - int x, y; + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, 0); - /* Reset top and left positions of the Window - here since Windows sends a WM_MOVE message - BEFORE telling us the Window is minimized - when the Window is iconified, with 3000,3000 - as the co-ords. */ - x_real_positions (f, &x, &y); - f->left_pos = x; - f->top_pos = y; + /* wait_reading_process_output will notice this + and update the frame's display structures. */ + SET_FRAME_GARBAGED (f); - inev.kind = DEICONIFY_EVENT; - XSETFRAME (inev.frame_or_window, f); - } - else if (! NILP (Vframe_list) - && ! NILP (XCDR (Vframe_list))) - /* Force a redisplay sooner or later - to update the frame titles - in case this is the second frame. */ - record_asynch_buffer_change (); + if (iconified) + { + int x, y; + + /* Reset top and left positions of the Window + here since Windows sends a WM_MOVE message + BEFORE telling us the Window is minimized + when the Window is iconified, with 3000,3000 + as the co-ords. */ + x_real_positions (f, &x, &y); + f->left_pos = x; + f->top_pos = y; + + inev.kind = DEICONIFY_EVENT; + XSETFRAME (inev.frame_or_window, f); + } + else if (! NILP (Vframe_list) + && ! NILP (XCDR (Vframe_list))) + /* Force a redisplay sooner or later + to update the frame titles + in case this is the second frame. */ + record_asynch_buffer_change (); + } break; } } - if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED) + if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED) { RECT rect; int rows; @@ -5040,12 +5041,13 @@ w32_read_socket (struct terminal *terminal, continue; /* Check "visible" frames and mark each as obscured or not. - Note that async_visible is nonzero for unobscured and - obscured frames, but zero for hidden and iconified frames. */ - if (FRAME_W32_P (f) && f->async_visible) + Note that visible is nonzero for unobscured and obscured + frames, but zero for hidden and iconified frames. */ + if (FRAME_W32_P (f) && FRAME_VISIBLE_P (f)) { RECT clipbox; HDC hdc; + bool obscured; enter_crit (); /* Query clipping rectangle for the entire window area @@ -5059,31 +5061,28 @@ w32_read_socket (struct terminal *terminal, ReleaseDC (FRAME_W32_WINDOW (f), hdc); leave_crit (); - if (clipbox.right == clipbox.left - || clipbox.bottom == clipbox.top) + obscured = FRAME_OBSCURED_P (f); + + if (clipbox.right == clipbox.left || clipbox.bottom == clipbox.top) { - /* Frame has become completely obscured so mark as - such (we do this by setting async_visible to 2 so - that FRAME_VISIBLE_P is still true, but redisplay - will skip it). */ - f->async_visible = 2; + /* Frame has become completely obscured so mark as such (we + do this by setting visible to 2 so that FRAME_VISIBLE_P + is still true, but redisplay will skip it). */ + SET_FRAME_VISIBLE (f, 2); - if (!FRAME_OBSCURED_P (f)) - { - DebPrint (("frame %p (%s) obscured\n", f, - SDATA (f->name))); - } + if (!obscured) + DebPrint (("frame %p (%s) obscured\n", f, SDATA (f->name))); } else { /* Frame is not obscured, so mark it as such. */ - f->async_visible = 1; + SET_FRAME_VISIBLE (f, 1); - if (FRAME_OBSCURED_P (f)) + if (obscured) { SET_FRAME_GARBAGED (f); - DebPrint (("obscured frame %p (%s) found to be visible\n", f, - SDATA (f->name))); + DebPrint (("obscured frame %p (%s) found to be visible\n", + f, SDATA (f->name))); /* Force a redisplay sooner or later. */ record_asynch_buffer_change (); @@ -5654,7 +5653,7 @@ w32fullscreen_hook (FRAME_PTR f) { static int normal_width, normal_height; - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) { int width, height, top_pos, left_pos, pixel_height, pixel_width; int cur_w = FRAME_COLS (f), cur_h = FRAME_LINES (f); @@ -5674,24 +5673,33 @@ w32fullscreen_hook (FRAME_PTR f) switch (f->want_fullscreen) { - /* No difference between these two when there is no WM */ case FULLSCREEN_MAXIMIZED: - PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, 0xf030, 0); + PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MAXIMIZE, 0); break; case FULLSCREEN_BOTH: - height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height) - 2; - width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width); + height = + FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height) + - XINT (Ftool_bar_lines_needed (selected_frame)) + + (NILP (Vmenu_bar_mode) ? 1 : 0); + width = + FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width) + - FRAME_SCROLL_BAR_COLS (f); left_pos = workarea_rect.left; top_pos = workarea_rect.top; break; case FULLSCREEN_WIDTH: - width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width); + width = + FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width) + - FRAME_SCROLL_BAR_COLS (f); if (normal_height > 0) height = normal_height; left_pos = workarea_rect.left; break; case FULLSCREEN_HEIGHT: - height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height) - 2; + height = + FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height) + - XINT (Ftool_bar_lines_needed (selected_frame)) + + (NILP (Vmenu_bar_mode) ? 1 : 0); if (normal_width > 0) width = normal_width; top_pos = workarea_rect.top; @@ -6014,11 +6022,11 @@ x_make_frame_visible (struct frame *f) causes unexpected behavior when unminimizing frames that were previously maximized. But only SW_SHOWNORMAL works properly for frames that were truely hidden (using make-frame-invisible), so - we need it to avoid Bug#5482. It seems that async_iconified - is only set for minimized windows that are still visible, so - use that to determine the appropriate flag to pass ShowWindow. */ + we need it to avoid Bug#5482. It seems that iconified is only + set for minimized windows that are still visible, so use that to + determine the appropriate flag to pass ShowWindow. */ my_show_window (f, FRAME_W32_WINDOW (f), - f->async_iconified ? SW_RESTORE : SW_SHOWNORMAL); + FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL); } /* Synchronize to ensure Emacs knows the frame is visible @@ -6057,7 +6065,6 @@ x_make_frame_visible (struct frame *f) poll_suppress_count = old_poll_suppress_count; } } - FRAME_SAMPLE_VISIBILITY (f); } } @@ -6081,10 +6088,8 @@ x_make_frame_invisible (struct frame *f) So we can't win using the usual strategy of letting FRAME_SAMPLE_VISIBILITY set this. So do it by hand, and synchronize with the server to make sure we agree. */ - f->visible = 0; - FRAME_ICONIFIED_P (f) = 0; - f->async_visible = 0; - f->async_iconified = 0; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 0); unblock_input (); } @@ -6100,7 +6105,7 @@ x_iconify_frame (struct frame *f) if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f) FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0; - if (f->async_iconified) + if (FRAME_ICONIFIED_P (f)) return; block_input (); diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index 88227487d35..c153c8f3565 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -333,7 +333,7 @@ uniscribe_shape (Lisp_Object lgstring) if (NILP (lglyph)) { - lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); + lglyph = LGLYPH_NEW (); LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph); } /* Copy to a 32-bit data type to shut up the @@ -435,8 +435,8 @@ uniscribe_shape (Lisp_Object lgstring) are zero. */ || (!attributes[j].fClusterStart && items[i].a.fRTL)) { - Lisp_Object vec; - vec = Fmake_vector (make_number (3), Qnil); + Lisp_Object vec = make_uninit_vector (3); + if (items[i].a.fRTL) { /* Empirically, it looks like Uniscribe diff --git a/src/window.c b/src/window.c index 32a6759f9f4..4b30a9d55da 100644 --- a/src/window.c +++ b/src/window.c @@ -116,9 +116,6 @@ Lisp_Object minibuf_selected_window; /* Hook run at end of temp_output_buffer_show. */ static Lisp_Object Qtemp_buffer_show_hook; -/* Incremented for each window created. */ -static int sequence_number; - /* Nonzero after init_window_once has finished. */ static int window_initialized; @@ -286,6 +283,9 @@ adjust_window_count (struct window *w, int arg) b = b->base_buffer; b->window_count += arg; eassert (b->window_count >= 0); + /* These should be recalculated by redisplay code. */ + w->window_end_valid = 0; + w->base_line_pos = 0; } } @@ -300,15 +300,6 @@ wset_buffer (struct window *w, Lisp_Object val) adjust_window_count (w, 1); } -/* Build a frequently used 4-integer (X Y W H) list. */ - -static Lisp_Object -list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h) -{ - return list4 (make_number (x), make_number (y), - make_number (w), make_number (h)); -} - DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0, doc: /* Return t if OBJECT is a window and nil otherwise. */) (Lisp_Object object) @@ -1489,17 +1480,8 @@ if it isn't already recorded. */) CHECK_BUFFER (buf); b = XBUFFER (buf); -#if 0 /* This change broke some things. We should make it later. */ - /* If we don't know the end position, return nil. - The user can compute it with vertical-motion if he wants to. - It would be nicer to do it automatically, - but that's so slow that it would probably bother people. */ - if (NILP (w->window_end_valid)) - return Qnil; -#endif - if (! NILP (update) - && (windows_or_buffers_changed || NILP (w->window_end_valid)) + && (windows_or_buffers_changed || !w->window_end_valid) && !noninteractive) { struct text_pos startp; @@ -1553,7 +1535,7 @@ Return POS. */) { register struct window *w = decode_live_window (window); - CHECK_NUMBER_COERCE_MARKER (pos); + /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */ if (w == XWINDOW (selected_window)) { @@ -1563,6 +1545,8 @@ Return POS. */) { struct buffer *old_buffer = current_buffer; + /* ... but here we want to catch type error before buffer change. */ + CHECK_NUMBER_COERCE_MARKER (pos); set_buffer_internal (XBUFFER (w->buffer)); Fgoto_char (pos); set_buffer_internal (old_buffer); @@ -1588,9 +1572,8 @@ overriding motion of point in order to display at this exact start. */) { register struct window *w = decode_live_window (window); - CHECK_NUMBER_COERCE_MARKER (pos); set_marker_restricted (w->start, pos, w->buffer); - /* this is not right, but much easier than doing what is right. */ + /* This is not right, but much easier than doing what is right. */ w->start_at_line_beg = 0; if (NILP (noforce)) w->force_start = 1; @@ -1706,7 +1689,7 @@ Return nil if window display is not up-to-date. In that case, use b = XBUFFER (w->buffer); /* Fail if current matrix is not up-to-date. */ - if (NILP (w->window_end_valid) + if (!w->window_end_valid || current_buffer->clip_changed || current_buffer->prevent_redisplay_optimizations_p || w->last_modified < BUF_MODIFF (b) @@ -2038,7 +2021,7 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag) n->pseudo_window_p = 0; wset_window_end_vpos (n, make_number (0)); wset_window_end_pos (n, make_number (0)); - wset_window_end_valid (n, Qnil); + n->window_end_valid = 0; n->frozen_window_start_p = 0; } @@ -2238,7 +2221,6 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf } else if (EQ (all_frames, Qvisible)) { - FRAME_SAMPLE_VISIBILITY (f); candidate_p = FRAME_VISIBLE_P (f) && (FRAME_TERMINAL (XFRAME (w->frame)) == FRAME_TERMINAL (XFRAME (selected_frame))); @@ -2246,7 +2228,6 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf } else if (INTEGERP (all_frames) && XINT (all_frames) == 0) { - FRAME_SAMPLE_VISIBILITY (f); candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f) #ifdef HAVE_X_WINDOWS /* Yuck!! If we've just created the frame and the @@ -2762,7 +2743,7 @@ window-start value is reasonable when this function is called. */) struct window *w, *r, *s; struct frame *f; Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; - ptrdiff_t startpos IF_LINT (= 0); + ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0); int top IF_LINT (= 0), new_top, resize_failed; w = decode_valid_window (window); @@ -2801,6 +2782,7 @@ window-start value is reasonable when this function is called. */) if (!NILP (w->buffer)) { startpos = marker_position (w->start); + startbyte = marker_byte_position (w->start); top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))); /* Make sure WINDOW is the frame's selected window. */ @@ -2970,10 +2952,10 @@ window-start value is reasonable when this function is called. */) Fset_buffer (w->buffer); /* This computation used to temporarily move point, but that can have unwanted side effects due to text properties. */ - pos = *vmotion (startpos, -top, w); + pos = *vmotion (startpos, startbyte, -top, w); set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; w->start_at_line_beg = (pos.bytepos == BEGV_BYTE || FETCH_BYTE (pos.bytepos - 1) == '\n'); /* We need to do this, so that the window-scroll-functions @@ -3189,7 +3171,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int wset_window_end_pos (w, make_number (0)); wset_window_end_vpos (w, make_number (0)); memset (&w->last_cursor, 0, sizeof w->last_cursor); - wset_window_end_valid (w, Qnil); + if (!(keep_margins_p && samebuf)) { /* If we're not actually changing the buffer, don't reset hscroll and vscroll. This case happens for example when called from @@ -3438,8 +3420,6 @@ make_parent_window (Lisp_Object window, int horflag) adjust_window_count (p, 1); XSETWINDOW (parent, p); - p->sequence_number = ++sequence_number; - replace_window (window, parent, 1); wset_next (o, Qnil); @@ -3488,7 +3468,7 @@ make_window (void) w->nrows_scale_factor = w->ncols_scale_factor = 1; w->phys_cursor_type = -1; w->phys_cursor_width = -1; - w->sequence_number = ++sequence_number; + w->column_number_displayed = -1; /* Reset window_list. */ Vwindow_list = Qnil; @@ -3958,7 +3938,7 @@ set correctly. See the code of `split-window' for how this is done. */) wset_next (o, new); } - wset_window_end_valid (n, Qnil); + n->window_end_valid = 0; memset (&n->last_cursor, 0, sizeof n->last_cursor); /* Get special geometry settings from reference window. */ @@ -4628,8 +4608,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) } /* Set the window start, and set up the window for redisplay. */ - set_marker_restricted (w->start, make_number (pos), - w->buffer); + set_marker_restricted_both (w->start, w->buffer, IT_CHARPOS (it), + IT_BYTEPOS (it)); bytepos = marker_byte_position (w->start); w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n'); w->update_mode_line = 1; @@ -4769,7 +4749,8 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) register Lisp_Object tem; int lose; Lisp_Object bolp; - ptrdiff_t startpos; + ptrdiff_t startpos = marker_position (w->start); + ptrdiff_t startbyte = marker_byte_position (w->start); Lisp_Object original_pos = Qnil; /* If scrolling screen-fulls, compute the number of lines to @@ -4777,8 +4758,6 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) if (whole) n *= max (1, ht - next_screen_context_lines); - startpos = marker_position (w->start); - if (!NILP (Vscroll_preserve_screen_position)) { if (window_scroll_preserve_vpos <= 0 @@ -4786,10 +4765,8 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command))) { struct position posit - = *compute_motion (startpos, 0, 0, 0, - PT, ht, 0, - -1, w->hscroll, - 0, w); + = *compute_motion (startpos, startbyte, 0, 0, 0, + PT, ht, 0, -1, w->hscroll, 0, w); window_scroll_preserve_vpos = posit.vpos; window_scroll_preserve_hpos = posit.hpos + w->hscroll; } @@ -4805,9 +4782,10 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) { Fvertical_motion (make_number (- (ht / 2)), window); startpos = PT; + startbyte = PT_BYTE; } - SET_PT (startpos); + SET_PT_BOTH (startpos, startbyte); lose = n < 0 && PT == BEGV; Fvertical_motion (make_number (n), window); pos = PT; @@ -5185,7 +5163,7 @@ displayed_window_lines (struct window *w) DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P", doc: /* Center point in selected window and maybe redisplay frame. -With prefix argument ARG, recenter putting point on screen line ARG +With a numeric prefix argument ARG, recenter putting point on screen line ARG relative to the selected window. If ARG is negative, it counts up from the bottom of the window. (ARG should be less than the height of the window.) @@ -5342,7 +5320,7 @@ and redisplay normally--don't erase and redraw the frame. */) iarg = max (iarg, this_scroll_margin); - pos = *vmotion (PT, -iarg, w); + pos = *vmotion (PT, PT_BYTE, -iarg, w); charpos = pos.bufpos; bytepos = pos.bytepos; } @@ -5361,14 +5339,14 @@ and redisplay normally--don't erase and redraw the frame. */) iarg = clip_to_bounds (this_scroll_margin, iarg, ht - this_scroll_margin - 1); - pos = *vmotion (PT, - iarg, w); + pos = *vmotion (PT, PT_BYTE, - iarg, w); charpos = pos.bufpos; bytepos = pos.bytepos; } /* Set the new window start. */ set_marker_both (w->start, w->buffer, charpos, bytepos); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; w->optional_new_start = 1; @@ -5808,8 +5786,7 @@ the return value is nil. Otherwise the value is t. */) { /* Set window markers at start of visible range. */ if (XMARKER (w->start)->buffer == 0) - set_marker_restricted (w->start, make_number (0), - w->buffer); + set_marker_restricted_both (w->start, w->buffer, 0, 0); if (XMARKER (w->pointm)->buffer == 0) set_marker_restricted_both (w->pointm, w->buffer, @@ -5827,10 +5804,8 @@ the return value is nil. Otherwise the value is t. */) wset_buffer (w, other_buffer_safely (Fcurrent_buffer ())); /* This will set the markers to beginning of visible range. */ - set_marker_restricted (w->start, - make_number (0), w->buffer); - set_marker_restricted (w->pointm, - make_number (0), w->buffer); + set_marker_restricted_both (w->start, w->buffer, 0, 0); + set_marker_restricted_both (w->pointm, w->buffer, 0, 0); w->start_at_line_beg = 1; if (!NILP (w->dedicated)) /* Record this window as dead. */ @@ -6203,11 +6178,11 @@ saved by this function. */) data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil; data->root_window = FRAME_ROOT_WINDOW (f); data->focus_frame = FRAME_FOCUS_FRAME (f); - tem = Fmake_vector (make_number (n_windows), Qnil); + tem = make_uninit_vector (n_windows); data->saved_windows = tem; for (i = 0; i < n_windows; i++) ASET (tem, i, - Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil)); + Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil)); save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0); XSETWINDOW_CONFIGURATION (tem, data); return (tem); @@ -6319,7 +6294,7 @@ display marginal areas and the text area. */) adjust_window_margins (w); clear_glyph_matrix (w->current_matrix); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; ++windows_or_buffers_changed; adjust_glyphs (XFRAME (WINDOW_FRAME (w))); @@ -6389,7 +6364,7 @@ Fourth parameter HORIZONTAL-TYPE is currently unused. */) adjust_window_margins (w); clear_glyph_matrix (w->current_matrix); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; ++windows_or_buffers_changed; adjust_glyphs (XFRAME (WINDOW_FRAME (w))); diff --git a/src/window.h b/src/window.h index 1ebd35a7c64..dcef37abb4c 100644 --- a/src/window.h +++ b/src/window.h @@ -175,17 +175,13 @@ struct window no scroll bar. A value of t means use frame value. */ Lisp_Object vertical_scroll_bar_type; - /* Z - the buffer position of the last glyph in the current matrix - of W. Only valid if WINDOW_END_VALID is not nil. */ + /* Z - the buffer position of the last glyph in the current + matrix of W. Only valid if window_end_valid is nonzero. */ Lisp_Object window_end_pos; + /* Glyph matrix row of the last glyph in the current matrix - of W. Only valid if WINDOW_END_VALID is not nil. */ + of W. Only valid if window_end_valid is nonzero. */ Lisp_Object window_end_vpos; - /* t if window_end_pos is truly valid. - This is nil if nontrivial redisplay is preempted - since in that case the frame image that window_end_pos - did not get onto the frame. */ - Lisp_Object window_end_valid; /* Display-table to use for displaying chars in this window. Nil means use the buffer's own display-table. */ @@ -196,23 +192,6 @@ struct window and Qt, so bitfield can't be used here. */ Lisp_Object dedicated; - /* Line number and position of a line somewhere above the top of the - screen. If this field is nil, it means we don't have a base - line. */ - Lisp_Object base_line_number; - /* If this field is nil, it means we don't have a base line. - If it is a buffer, it means don't display the line number - as long as the window shows that buffer. */ - Lisp_Object base_line_pos; - - /* If we have highlighted the region (or any part of it), - this is the mark position that we used, as an integer. */ - Lisp_Object region_showing; - - /* The column number currently displayed in this window's mode line, - or nil if column numbers are not being displayed. */ - Lisp_Object column_number_displayed; - /* If redisplay in this window goes beyond this buffer position, must run the redisplay-end-trigger-hook. */ Lisp_Object redisplay_end_trigger; @@ -242,9 +221,6 @@ struct window /* Number saying how recently window was selected. */ int use_time; - /* Unique number of window assigned when it was created. */ - int sequence_number; - /* Number of columns display within the window is scrolled to the left. */ ptrdiff_t hscroll; @@ -264,6 +240,19 @@ struct window it should be positive. */ ptrdiff_t last_point; + /* Line number and position of a line somewhere above the top of the + screen. If this field is zero, it means we don't have a base line. */ + ptrdiff_t base_line_number; + + /* If this field is zero, it means we don't have a base line. + If it is -1, it means don't display the line number as long + as the window shows its buffer. */ + ptrdiff_t base_line_pos; + + /* The column number currently displayed in this window's mode + line, or -1 if column numbers are not being displayed. */ + ptrdiff_t column_number_displayed; + /* Scaling factor for the glyph_matrix size calculation in this window. Used if window contains many small images or uses proportional fonts, as the normal may yield a matrix which is too small. */ @@ -339,12 +328,21 @@ struct window Otherwise draw them between margin areas and text. */ unsigned fringes_outside_margins : 1; + /* Nonzero if window_end_pos and window_end_vpos are truly valid. + This is zero if nontrivial redisplay is preempted since in that case + the frame image that window_end_pos did not get onto the frame. */ + unsigned window_end_valid : 1; + /* Amount by which lines of this window are scrolled in y-direction (smooth scrolling). */ int vscroll; - /* Z_BYTE - Buffer position of the last glyph in the current matrix of W. - Should be nonnegative, and only valid if window_end_valid is not nil. */ + /* If we have highlighted the region (or any part of it), the mark + (region start) position; otherwise zero. */ + ptrdiff_t region_showing; + + /* Z_BYTE - buffer position of the last glyph in the current matrix of W. + Should be nonnegative, and only valid if window_end_valid is nonzero. */ ptrdiff_t window_end_bytepos; }; @@ -401,11 +399,6 @@ wset_window_end_pos (struct window *w, Lisp_Object val) w->window_end_pos = val; } WINDOW_INLINE void -wset_window_end_valid (struct window *w, Lisp_Object val) -{ - w->window_end_valid = val; -} -WINDOW_INLINE void wset_window_end_vpos (struct window *w, Lisp_Object val) { w->window_end_vpos = val; diff --git a/src/xdisp.c b/src/xdisp.c index b75362b1446..c6e204702ce 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -367,28 +367,6 @@ Lisp_Object Qcenter; static Lisp_Object Qmargin, Qpointer; static Lisp_Object Qline_height; -/* These setters are used only in this file, so they can be private. */ -static void -wset_base_line_number (struct window *w, Lisp_Object val) -{ - w->base_line_number = val; -} -static void -wset_base_line_pos (struct window *w, Lisp_Object val) -{ - w->base_line_pos = val; -} -static void -wset_column_number_displayed (struct window *w, Lisp_Object val) -{ - w->column_number_displayed = val; -} -static void -wset_region_showing (struct window *w, Lisp_Object val) -{ - w->region_showing = val; -} - #ifdef HAVE_WINDOW_SYSTEM /* Test if overflow newline into fringe. Called with iterator IT @@ -840,17 +818,17 @@ static void ensure_echo_area_buffers (void); static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); static Lisp_Object with_echo_area_buffer_unwind_data (struct window *); static int with_echo_area_buffer (struct window *, int, - int (*) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t), - ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); + int (*) (ptrdiff_t, Lisp_Object), + ptrdiff_t, Lisp_Object); static void clear_garbaged_frames (void); -static int current_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); +static int current_message_1 (ptrdiff_t, Lisp_Object); static void pop_message (void); -static int truncate_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); -static void set_message (const char *, Lisp_Object, ptrdiff_t, int); -static int set_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); +static int truncate_message_1 (ptrdiff_t, Lisp_Object); +static void set_message (Lisp_Object); +static int set_message_1 (ptrdiff_t, Lisp_Object); static int display_echo_area (struct window *); -static int display_echo_area_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); -static int resize_mini_window_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); +static int display_echo_area_1 (ptrdiff_t, Lisp_Object); +static int resize_mini_window_1 (ptrdiff_t, Lisp_Object); static Lisp_Object unwind_redisplay (Lisp_Object); static int string_char_and_length (const unsigned char *, int *); static struct text_pos display_prop_end (struct it *, Lisp_Object, @@ -932,8 +910,8 @@ static int forward_to_next_line_start (struct it *, int *, struct bidi_it *); static struct text_pos string_pos_nchars_ahead (struct text_pos, Lisp_Object, ptrdiff_t); static struct text_pos string_pos (ptrdiff_t, Lisp_Object); -static struct text_pos c_string_pos (ptrdiff_t, const char *, int); -static ptrdiff_t number_of_chars (const char *, int); +static struct text_pos c_string_pos (ptrdiff_t, const char *, bool); +static ptrdiff_t number_of_chars (const char *, bool); static void compute_stop_pos (struct it *); static void compute_string_pos (struct text_pos *, struct text_pos, Lisp_Object); @@ -1414,21 +1392,9 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, Lisp_Object cpos = make_number (charpos); Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); Lisp_Object string = string_from_display_spec (spec); - int newline_in_string = 0; - - if (STRINGP (string)) - { - const char *s = SSDATA (string); - const char *e = s + SBYTES (string); - while (s < e) - { - if (*s++ == '\n') - { - newline_in_string = 1; - break; - } - } - } + bool newline_in_string + = (STRINGP (string) + && memchr (SDATA (string), '\n', SBYTES (string))); /* The tricky code below is needed because there's a discrepancy between move_it_to and how we set cursor when the display line ends in a newline from a @@ -1684,7 +1650,7 @@ string_pos (ptrdiff_t charpos, Lisp_Object string) means recognize multibyte characters. */ static struct text_pos -c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p) +c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p) { struct text_pos pos; @@ -1715,7 +1681,7 @@ c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p) non-zero means recognize multibyte characters. */ static ptrdiff_t -number_of_chars (const char *s, int multibyte_p) +number_of_chars (const char *s, bool multibyte_p) { ptrdiff_t nchars; @@ -2539,8 +2505,7 @@ check_it (struct it *it) static void check_window_end (struct window *w) { - if (!MINI_WINDOW_P (w) - && !NILP (w->window_end_valid)) + if (!MINI_WINDOW_P (w) && w->window_end_valid) { struct glyph_row *row; eassert ((row = MATRIX_ROW (w->current_matrix, @@ -5940,8 +5905,10 @@ pop_it (struct it *it) static void back_to_previous_line_start (struct it *it) { - IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1); - IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); + ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); + + DEC_BOTH (cp, bp); + IT_CHARPOS (*it) = find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)); } @@ -5957,7 +5924,7 @@ back_to_previous_line_start (struct it *it) Newlines may come from buffer text, overlay strings, or strings displayed via the `display' property. That's the reason we can't - simply use find_next_newline_no_quit. + simply use find_newline_no_quit. Note that this function may not skip over invisible text that is so because of text properties and immediately follows a newline. If @@ -6012,8 +5979,9 @@ forward_to_next_line_start (struct it *it, int *skipped_p, short-cut. */ if (!newline_found_p) { - ptrdiff_t start = IT_CHARPOS (*it); - ptrdiff_t limit = find_next_newline_no_quit (start, 1); + ptrdiff_t bytepos, start = IT_CHARPOS (*it); + ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it), + 1, &bytepos); Lisp_Object pos; eassert (!STRINGP (it->string)); @@ -6031,7 +5999,7 @@ forward_to_next_line_start (struct it *it, int *skipped_p, if (!it->bidi_p) { IT_CHARPOS (*it) = limit; - IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit); + IT_BYTEPOS (*it) = bytepos; } else { @@ -7467,11 +7435,9 @@ get_visually_first_element (struct it *it) if (string_p) it->bidi_it.charpos = it->bidi_it.bytepos = 0; else - { - it->bidi_it.charpos = find_next_newline_no_quit (IT_CHARPOS (*it), - -1); - it->bidi_it.bytepos = CHAR_TO_BYTE (it->bidi_it.charpos); - } + it->bidi_it.charpos = find_newline_no_quit (IT_CHARPOS (*it), + IT_BYTEPOS (*it), -1, + &it->bidi_it.bytepos); bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); do { @@ -9015,6 +8981,9 @@ move_it_vertically_backward (struct it *it, int dy) struct it it2, it3; void *it2data = NULL, *it3data = NULL; ptrdiff_t start_pos; + int nchars_per_row + = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); + ptrdiff_t pos_limit; move_further_back: eassert (dy >= 0); @@ -9023,9 +8992,15 @@ move_it_vertically_backward (struct it *it, int dy) /* Estimate how many newlines we must move back. */ nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f)); + if (it->line_wrap == TRUNCATE) + pos_limit = BEGV; + else + pos_limit = max (start_pos - nlines * nchars_per_row, BEGV); - /* Set the iterator's position that many lines back. */ - while (nlines-- && IT_CHARPOS (*it) > BEGV) + /* Set the iterator's position that many lines back. But don't go + back more than NLINES full screen lines -- this wins a day with + buffers which have very long lines. */ + while (nlines-- && IT_CHARPOS (*it) > pos_limit) back_to_previous_visible_line_start (it); /* Reseat the iterator here. When moving backward, we don't want @@ -9096,10 +9071,11 @@ move_it_vertically_backward (struct it *it, int dy) && IT_CHARPOS (*it) > BEGV && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n') { - ptrdiff_t nl_pos = - find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1); + ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); - move_it_to (it, nl_pos, -1, -1, -1, MOVE_TO_POS); + DEC_BOTH (cp, bp); + cp = find_newline_no_quit (cp, bp, -1, NULL); + move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); } bidi_unshelve_cache (it3data, 1); } @@ -9256,6 +9232,9 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) struct it it2; void *it2data = NULL; ptrdiff_t start_charpos, i; + int nchars_per_row + = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); + ptrdiff_t pos_limit; /* Start at the beginning of the screen line containing IT's position. This may actually move vertically backwards, @@ -9264,9 +9243,14 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) move_it_vertically_backward (it, 0); dvpos -= it->vpos; - /* Go back -DVPOS visible lines and reseat the iterator there. */ + /* Go back -DVPOS buffer lines, but no farther than -DVPOS full + screen lines, and reseat the iterator there. */ start_charpos = IT_CHARPOS (*it); - for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i) + if (it->line_wrap == TRUNCATE) + pos_limit = BEGV; + else + pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV); + for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i) back_to_previous_visible_line_start (it); reseat (it, it->current.pos, 1); @@ -9375,8 +9359,8 @@ message_log_maybe_newline (void) /* Add a string M of length NBYTES to the message log, optionally - terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if - nonzero, means interpret the contents of M as multibyte. This + terminated with a newline when NLFLAG is true. MULTIBYTE, if + true, means interpret the contents of M as multibyte. This function calls low-level routines in order to bypass text property hooks, etc. which might not be safe to run. @@ -9384,7 +9368,7 @@ message_log_maybe_newline (void) so the buffer M must NOT point to a Lisp string. */ void -message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) +message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte) { const unsigned char *msg = (const unsigned char *) m; @@ -9408,11 +9392,11 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) bset_undo_list (current_buffer, Qt); oldpoint = message_dolog_marker1; - set_marker_restricted (oldpoint, make_number (PT), Qnil); + set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE); oldbegv = message_dolog_marker2; - set_marker_restricted (oldbegv, make_number (BEGV), Qnil); + set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE); oldzv = message_dolog_marker3; - set_marker_restricted (oldzv, make_number (ZV), Qnil); + set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE); GCPRO1 (old_deactivate_mark); if (PT == Z) @@ -9463,13 +9447,14 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) } } else if (nbytes) - insert_1 (m, nbytes, 1, 0, 0); + insert_1_both (m, chars_in_text (msg, nbytes), nbytes, 1, 0, 0); if (nlflag) { ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte; printmax_t dups; - insert_1 ("\n", 1, 1, 0, 0); + + insert_1_both ("\n", 1, 1, 1, 0, 0); scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0); this_bol = PT; @@ -9498,7 +9483,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) change message_log_check_duplicate. */ int duplen = sprintf (dupstr, " [%"pMd" times]", dups); TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1); - insert_1 (dupstr, duplen, 1, 0, 1); + insert_1_both (dupstr, duplen, duplen, 1, 0, 1); } } } @@ -9568,7 +9553,7 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte) for (i = 0; i < len; i++) { - if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.') + if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.') seen_dots = 1; if (p1[i] != p2[i]) return seen_dots; @@ -9581,88 +9566,13 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte) char *pend; intmax_t n = strtoimax ((char *) p1, &pend, 10); if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0) - return n+1; + return n + 1; } return 0; } /* Display an echo area message M with a specified length of NBYTES - bytes. The string may include null characters. If M is 0, clear - out any existing message, and let the mini-buffer text show - through. - - This may GC, so the buffer M must NOT point to a Lisp string. */ - -void -message2 (const char *m, ptrdiff_t nbytes, int multibyte) -{ - /* First flush out any partial line written with print. */ - message_log_maybe_newline (); - if (m) - message_dolog (m, nbytes, 1, multibyte); - message2_nolog (m, nbytes, multibyte); -} - - -/* The non-logging counterpart of message2. */ - -void -message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte) -{ - struct frame *sf = SELECTED_FRAME (); - message_enable_multibyte = multibyte; - - if (FRAME_INITIAL_P (sf)) - { - if (noninteractive_need_newline) - putc ('\n', stderr); - noninteractive_need_newline = 0; - if (m) - fwrite (m, nbytes, 1, stderr); - if (cursor_in_echo_area == 0) - fprintf (stderr, "\n"); - fflush (stderr); - } - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ - else if (INTERACTIVE - && sf->glyphs_initialized_p - && FRAME_MESSAGE_BUF (sf)) - { - Lisp_Object mini_window; - struct frame *f; - - /* Get the frame containing the mini-buffer - that the selected frame is using. */ - mini_window = FRAME_MINIBUF_WINDOW (sf); - f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - - FRAME_SAMPLE_VISIBILITY (f); - if (FRAME_VISIBLE_P (sf) - && ! FRAME_VISIBLE_P (f)) - Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window))); - - if (m) - { - set_message (m, Qnil, nbytes, multibyte); - if (minibuffer_auto_raise) - Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window))); - } - else - clear_message (1, 1); - - do_pending_window_change (0); - echo_area_display (1); - do_pending_window_change (0); - if (FRAME_TERMINAL (f)->frame_up_to_date_hook) - (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f); - } -} - - -/* Display an echo area message M with a specified length of NBYTES bytes. The string may include null characters. If M is not a string, clear out any existing message, and let the mini-buffer text show through. @@ -9670,7 +9580,7 @@ message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte) This function cancels echoing. */ void -message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) +message3 (Lisp_Object m) { struct gcpro gcpro1; @@ -9682,13 +9592,15 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) message_log_maybe_newline (); if (STRINGP (m)) { + ptrdiff_t nbytes = SBYTES (m); + bool multibyte = STRING_MULTIBYTE (m); USE_SAFE_ALLOCA; char *buffer = SAFE_ALLOCA (nbytes); memcpy (buffer, SDATA (m), nbytes); message_dolog (buffer, nbytes, 1, multibyte); SAFE_FREE (); } - message3_nolog (m, nbytes, multibyte); + message3_nolog (m); UNGCPRO; } @@ -9700,10 +9612,9 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) and make this cancel echoing. */ void -message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) +message3_nolog (Lisp_Object m) { struct frame *sf = SELECTED_FRAME (); - message_enable_multibyte = multibyte; if (FRAME_INITIAL_P (sf)) { @@ -9711,36 +9622,28 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) putc ('\n', stderr); noninteractive_need_newline = 0; if (STRINGP (m)) - fwrite (SDATA (m), nbytes, 1, stderr); + fwrite (SDATA (m), SBYTES (m), 1, stderr); if (cursor_in_echo_area == 0) fprintf (stderr, "\n"); fflush (stderr); } - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ - else if (INTERACTIVE - && sf->glyphs_initialized_p - && FRAME_MESSAGE_BUF (sf)) + /* Error messages get reported properly by cmd_error, so this must be just an + informative message; if the frame hasn't really been initialized yet, just + toss it. */ + else if (INTERACTIVE && sf->glyphs_initialized_p) { - Lisp_Object mini_window; - Lisp_Object frame; - struct frame *f; - /* Get the frame containing the mini-buffer that the selected frame is using. */ - mini_window = FRAME_MINIBUF_WINDOW (sf); - frame = XWINDOW (mini_window)->frame; - f = XFRAME (frame); + Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf); + Lisp_Object frame = XWINDOW (mini_window)->frame; + struct frame *f = XFRAME (frame); - FRAME_SAMPLE_VISIBILITY (f); - if (FRAME_VISIBLE_P (sf) - && !FRAME_VISIBLE_P (f)) + if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f)) Fmake_frame_visible (frame); if (STRINGP (m) && SCHARS (m) > 0) { - set_message (NULL, m, nbytes, multibyte); + set_message (m); if (minibuffer_auto_raise) Fraise_frame (frame); /* Assume we are not echoing. @@ -9770,7 +9673,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) void message1 (const char *m) { - message2 (m, (m ? strlen (m) : 0), 0); + message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil); } @@ -9779,7 +9682,7 @@ message1 (const char *m) void message1_nolog (const char *m) { - message2_nolog (m, (m ? strlen (m) : 0), 0); + message3_nolog (m ? make_unibyte_string (m, strlen (m)) : Qnil); } /* Display a message M which contains a single %s @@ -9816,10 +9719,10 @@ message_with_string (const char *m, Lisp_Object string, int log) mini_window = FRAME_MINIBUF_WINDOW (sf); f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ - if (FRAME_MESSAGE_BUF (f)) + /* Error messages get reported properly by cmd_error, so this must be + just an informative message; if the frame hasn't really been + initialized yet, just toss it. */ + if (f->glyphs_initialized_p) { Lisp_Object args[2], msg; struct gcpro gcpro1, gcpro2; @@ -9832,9 +9735,9 @@ message_with_string (const char *m, Lisp_Object string, int log) msg = Fformat (2, args); if (log) - message3 (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); + message3 (msg); else - message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); + message3_nolog (msg); UNGCPRO; @@ -9878,20 +9781,20 @@ vmessage (const char *m, va_list ap) mini_window = FRAME_MINIBUF_WINDOW (sf); f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss - it. */ - if (FRAME_MESSAGE_BUF (f)) + /* Error messages get reported properly by cmd_error, so this must be + just an informative message; if the frame hasn't really been + initialized yet, just toss it. */ + if (f->glyphs_initialized_p) { if (m) { ptrdiff_t len; + ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f); + char *message_buf = alloca (maxsize + 1); - len = doprnt (FRAME_MESSAGE_BUF (f), - FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap); + len = doprnt (message_buf, maxsize, m, (char *)0, ap); - message2 (FRAME_MESSAGE_BUF (f), len, 1); + message3 (make_string (message_buf, len)); } else message1 (0); @@ -9942,8 +9845,7 @@ update_echo_area (void) { Lisp_Object string; string = Fcurrent_message (); - message3 (string, SBYTES (string), - !NILP (BVAR (current_buffer, enable_multibyte_characters))); + message3 (string); } } @@ -9979,7 +9881,7 @@ ensure_echo_area_buffers (void) } -/* Call FN with args A1..A4 with either the current or last displayed +/* Call FN with args A1..A2 with either the current or last displayed echo_area_buffer as current buffer. WHICH zero means use the current message buffer @@ -9997,8 +9899,8 @@ ensure_echo_area_buffers (void) static int with_echo_area_buffer (struct window *w, int which, - int (*fn) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t), - ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) + int (*fn) (ptrdiff_t, Lisp_Object), + ptrdiff_t a1, Lisp_Object a2) { Lisp_Object buffer; int this_one, the_other, clear_buffer_p, rc; @@ -10071,7 +9973,7 @@ with_echo_area_buffer (struct window *w, int which, eassert (BEGV >= BEG); eassert (ZV <= Z && ZV >= BEGV); - rc = fn (a1, a2, a3, a4); + rc = fn (a1, a2); eassert (BEGV >= BEG); eassert (ZV <= Z && ZV >= BEGV); @@ -10250,7 +10152,7 @@ display_echo_area (struct window *w) window_height_changed_p = with_echo_area_buffer (w, display_last_displayed_message_p, display_echo_area_1, - (intptr_t) w, Qnil, 0, 0); + (intptr_t) w, Qnil); if (no_message_p) echo_area_buffer[i] = Qnil; @@ -10267,7 +10169,7 @@ display_echo_area (struct window *w) Value is non-zero if height of W was changed. */ static int -display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) +display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2) { intptr_t i1 = a1; struct window *w = (struct window *) i1; @@ -10312,8 +10214,7 @@ resize_echo_area_exactly (void) resize_exactly = Qnil; resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1, - (intptr_t) w, resize_exactly, - 0, 0); + (intptr_t) w, resize_exactly); if (resized_p) { ++windows_or_buffers_changed; @@ -10331,7 +10232,7 @@ resize_echo_area_exactly (void) resize_mini_window returns. */ static int -resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly, ptrdiff_t a3, ptrdiff_t a4) +resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly) { intptr_t i1 = a1; return resize_mini_window ((struct window *) i1, !NILP (exactly)); @@ -10500,7 +10401,7 @@ current_message (void) else { with_echo_area_buffer (0, 0, current_message_1, - (intptr_t) &msg, Qnil, 0, 0); + (intptr_t) &msg, Qnil); if (NILP (msg)) echo_area_buffer[0] = Qnil; } @@ -10510,7 +10411,7 @@ current_message (void) static int -current_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) +current_message_1 (ptrdiff_t a1, Lisp_Object a2) { intptr_t i1 = a1; Lisp_Object *msg = (Lisp_Object *) i1; @@ -10542,14 +10443,8 @@ push_message (void) void restore_message (void) { - Lisp_Object msg; - eassert (CONSP (Vmessage_stack)); - msg = XCAR (Vmessage_stack); - if (STRINGP (msg)) - message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); - else - message3_nolog (msg, 0, 0); + message3_nolog (XCAR (Vmessage_stack)); } @@ -10592,16 +10487,16 @@ truncate_echo_area (ptrdiff_t nchars) { if (nchars == 0) echo_area_buffer[0] = Qnil; - /* A null message buffer means that the frame hasn't really been - initialized yet. Error messages get reported properly by - cmd_error, so this must be just an informative message; toss it. */ else if (!noninteractive && INTERACTIVE && !NILP (echo_area_buffer[0])) { struct frame *sf = SELECTED_FRAME (); - if (FRAME_MESSAGE_BUF (sf)) - with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0); + /* Error messages get reported properly by cmd_error, so this must be + just an informative message; if the frame hasn't really been + initialized yet, just toss it. */ + if (sf->glyphs_initialized_p) + with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil); } } @@ -10610,7 +10505,7 @@ truncate_echo_area (ptrdiff_t nchars) message to at most NCHARS characters. */ static int -truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) +truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2) { if (BEG + nchars < Z) del_range (BEG + nchars, Z); @@ -10619,51 +10514,34 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4 return 0; } -/* Set the current message to a substring of S or STRING. - - If STRING is a Lisp string, set the message to the first NBYTES - bytes from STRING. NBYTES zero means use the whole string. If - STRING is multibyte, the message will be displayed multibyte. - - If S is not null, set the message to the first LEN bytes of S. LEN - zero means use the whole string. MULTIBYTE_P non-zero means S is - multibyte. Display the message multibyte in that case. - - Doesn't GC, as with_echo_area_buffer binds Qinhibit_modification_hooks - to t before calling set_message_1 (which calls insert). - */ +/* Set the current message to STRING. */ static void -set_message (const char *s, Lisp_Object string, - ptrdiff_t nbytes, int multibyte_p) +set_message (Lisp_Object string) { - message_enable_multibyte - = ((s && multibyte_p) - || (STRINGP (string) && STRING_MULTIBYTE (string))); + eassert (STRINGP (string)); + + message_enable_multibyte = STRING_MULTIBYTE (string); - with_echo_area_buffer (0, -1, set_message_1, - (intptr_t) s, string, nbytes, multibyte_p); + with_echo_area_buffer (0, -1, set_message_1, 0, string); message_buf_print = 0; help_echo_showing_p = 0; if (STRINGP (Vdebug_on_message) + && STRINGP (string) && fast_string_match (Vdebug_on_message, string) >= 0) call_debugger (list2 (Qerror, string)); } -/* Helper function for set_message. Arguments have the same meaning - as there, with A1 corresponding to S and A2 corresponding to STRING - This function is called with the echo area buffer being - current. */ +/* Helper function for set_message. First argument is ignored and second + argument has the same meaning as for set_message. + This function is called with the echo area buffer being current. */ static int -set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multibyte_p) +set_message_1 (ptrdiff_t a1, Lisp_Object string) { - intptr_t i1 = a1; - const char *s = (const char *) i1; - const unsigned char *msg = (const unsigned char *) s; - Lisp_Object string = a2; + eassert (STRINGP (string)); /* Change multibyteness of the echo buffer appropriately. */ if (message_enable_multibyte @@ -10677,61 +10555,10 @@ set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multiby /* Insert new message at BEG. */ TEMP_SET_PT_BOTH (BEG, BEG_BYTE); - if (STRINGP (string)) - { - ptrdiff_t nchars; - - if (nbytes == 0) - nbytes = SBYTES (string); - nchars = string_byte_to_char (string, nbytes); - - /* This function takes care of single/multibyte conversion. We - just have to ensure that the echo area buffer has the right - setting of enable_multibyte_characters. */ - insert_from_string (string, 0, 0, nchars, nbytes, 1); - } - else if (s) - { - if (nbytes == 0) - nbytes = strlen (s); - - if (multibyte_p && NILP (BVAR (current_buffer, enable_multibyte_characters))) - { - /* Convert from multi-byte to single-byte. */ - ptrdiff_t i; - int c, n; - char work[1]; - - /* Convert a multibyte string to single-byte. */ - for (i = 0; i < nbytes; i += n) - { - c = string_char_and_length (msg + i, &n); - work[0] = (ASCII_CHAR_P (c) - ? c - : multibyte_char_to_unibyte (c)); - insert_1_both (work, 1, 1, 1, 0, 0); - } - } - else if (!multibyte_p - && !NILP (BVAR (current_buffer, enable_multibyte_characters))) - { - /* Convert from single-byte to multi-byte. */ - ptrdiff_t i; - int c, n; - unsigned char str[MAX_MULTIBYTE_LENGTH]; - - /* Convert a single-byte string to multibyte. */ - for (i = 0; i < nbytes; i++) - { - c = msg[i]; - MAKE_CHAR_MULTIBYTE (c); - n = CHAR_STRING (c, str); - insert_1_both ((char *) str, 1, n, 1, 0, 0); - } - } - else - insert_1 (s, nbytes, 1, 0, 0); - } + /* This function takes care of single/multibyte conversion. + We just have to ensure that the echo area buffer has the right + setting of enable_multibyte_characters. */ + insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), 1); return 0; } @@ -10934,7 +10761,7 @@ window_buffer_changed (struct window *w) 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))); + != (w->region_showing != 0))); } /* Nonzero if W has %c in its mode line and mode line should be updated. */ @@ -10942,9 +10769,9 @@ window_buffer_changed (struct window *w) static int mode_line_update_needed (struct window *w) { - return (!NILP (w->column_number_displayed) + return (w->column_number_displayed != -1 && !(PT == w->last_point && !window_outdated (w)) - && (XFASTINT (w->column_number_displayed) != current_column ())); + && (w->column_number_displayed != current_column ())); } /*********************************************************************** @@ -12922,10 +12749,10 @@ static void reconsider_clip_changes (struct window *w, struct buffer *b) { if (b->clip_changed - && !NILP (w->window_end_valid) - && w->current_matrix->buffer == b - && w->current_matrix->zv == BUF_ZV (b) - && w->current_matrix->begv == BUF_BEGV (b)) + && w->window_end_valid + && w->current_matrix->buffer == b + && w->current_matrix->zv == BUF_ZV (b) + && w->current_matrix->begv == BUF_BEGV (b)) b->clip_changed = 0; /* If display wasn't paused, and W is not a tool bar window, see if @@ -12933,8 +12760,7 @@ reconsider_clip_changes (struct window *w, struct buffer *b) we set b->clip_changed to 1 to force updating the screen. If b->clip_changed has already been set to 1, we can skip this check. */ - if (!b->clip_changed - && BUFFERP (w->buffer) && !NILP (w->window_end_valid)) + if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid) { ptrdiff_t pt; @@ -13082,7 +12908,6 @@ redisplay_internal (void) { struct frame *f = XFRAME (frame); - FRAME_SAMPLE_VISIBILITY (f); if (FRAME_VISIBLE_P (f)) ++number_of_visible_frames; clear_desired_matrices (f); @@ -13199,16 +13024,15 @@ redisplay_internal (void) clear_garbaged_frames (); } - /* If showing the region, and mark has changed, we must redisplay the whole window. The assignment to this_line_start_pos prevents the optimization directly below this if-statement. */ if (((!NILP (Vtransient_mark_mode) && !NILP (BVAR (XBUFFER (w->buffer), mark_active))) - != !NILP (w->region_showing)) - || (!NILP (w->region_showing) - && !EQ (w->region_showing, - Fmarker_position (BVAR (XBUFFER (w->buffer), mark))))) + != (w->region_showing > 0)) + || (w->region_showing + && w->region_showing + != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark))))) CHARPOS (this_line_start_pos) = 0; /* Optimize the case that only the line containing the cursor in the @@ -13328,7 +13152,7 @@ redisplay_internal (void) else if (XFASTINT (w->window_end_vpos) == this_line_vpos && this_line_vpos > 0) wset_window_end_vpos (w, make_number (this_line_vpos - 1)); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; /* Update hint: No need to try to scroll in update_window. */ w->desired_matrix->no_scrolling_p = 1; @@ -13374,7 +13198,7 @@ redisplay_internal (void) && (EQ (selected_window, BVAR (current_buffer, last_selected_window)) || highlight_nonselected_windows) - && NILP (w->region_showing) + && !w->region_showing && NILP (Vshow_trailing_whitespace) && !cursor_in_echo_area) { @@ -13630,9 +13454,6 @@ redisplay_internal (void) if (XFRAME (frame)->visible) this_is_visible = 1; - FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); - if (XFRAME (frame)->visible) - this_is_visible = 1; if (this_is_visible) new_count++; @@ -13722,50 +13543,43 @@ unwind_redisplay (Lisp_Object old_frame) } -/* Mark the display of window W as accurate or inaccurate. If - ACCURATE_P is non-zero mark display of W as accurate. If - ACCURATE_P is zero, arrange for W to be redisplayed the next time - redisplay_internal is called. */ +/* Mark the display of leaf window W as accurate or inaccurate. + If ACCURATE_P is non-zero mark display of W as accurate. If + ACCURATE_P is zero, arrange for W to be redisplayed the next + time redisplay_internal is called. */ static void mark_window_display_accurate_1 (struct window *w, int accurate_p) { - if (BUFFERP (w->buffer)) - { - struct buffer *b = XBUFFER (w->buffer); + struct buffer *b = XBUFFER (w->buffer); - w->last_modified = accurate_p ? BUF_MODIFF (b) : 0; - w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0; - w->last_had_star - = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b); + w->last_modified = accurate_p ? BUF_MODIFF (b) : 0; + w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0; + w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b); - if (accurate_p) - { - b->clip_changed = 0; - b->prevent_redisplay_optimizations_p = 0; + if (accurate_p) + { + b->clip_changed = 0; + b->prevent_redisplay_optimizations_p = 0; - BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b); - BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b); - BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b); - BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b); + BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b); + BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b); + BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b); + BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b); - w->current_matrix->buffer = b; - w->current_matrix->begv = BUF_BEGV (b); - w->current_matrix->zv = BUF_ZV (b); + w->current_matrix->buffer = b; + w->current_matrix->begv = BUF_BEGV (b); + w->current_matrix->zv = BUF_ZV (b); - w->last_cursor = w->cursor; - w->last_cursor_off_p = w->cursor_off_p; + w->last_cursor = w->cursor; + w->last_cursor_off_p = w->cursor_off_p; - if (w == XWINDOW (selected_window)) - w->last_point = BUF_PT (b); - else - w->last_point = marker_position (w->pointm); - } - } + if (w == XWINDOW (selected_window)) + w->last_point = BUF_PT (b); + else + w->last_point = marker_position (w->pointm); - if (accurate_p) - { - wset_window_end_valid (w, w->buffer); + w->window_end_valid = 1; w->update_mode_line = 0; } } @@ -13784,25 +13598,21 @@ mark_window_display_accurate (Lisp_Object window, int accurate_p) for (; !NILP (window); window = w->next) { w = XWINDOW (window); - mark_window_display_accurate_1 (w, accurate_p); - if (!NILP (w->vchild)) mark_window_display_accurate (w->vchild, accurate_p); - if (!NILP (w->hchild)) + else if (!NILP (w->hchild)) mark_window_display_accurate (w->hchild, accurate_p); + else if (BUFFERP (w->buffer)) + mark_window_display_accurate_1 (w, accurate_p); } if (accurate_p) - { - update_overlay_arrows (1); - } + update_overlay_arrows (1); else - { - /* Force a thorough redisplay the next time by setting - last_arrow_position and last_arrow_string to t, which is - unequal to any useful value of Voverlay_arrow_... */ - update_overlay_arrows (-1); - } + /* Force a thorough redisplay the next time by setting + last_arrow_position and last_arrow_string to t, which is + unequal to any useful value of Voverlay_arrow_... */ + update_overlay_arrows (-1); } @@ -14797,14 +14607,24 @@ try_scrolling (Lisp_Object window, int just_this_one_p, else { struct text_pos scroll_margin_pos = startp; + int y_offset = 0; /* See if point is inside the scroll margin at the top of the window. */ if (this_scroll_margin) { + int y_start; + start_display (&it, w, startp); + y_start = it.current_y; move_it_vertically (&it, this_scroll_margin); scroll_margin_pos = it.current.pos; + /* If we didn't move enough before hitting ZV, request + additional amount of scroll, to move point out of the + scroll margin. */ + if (IT_CHARPOS (it) == ZV + && it.current_y - y_start < this_scroll_margin) + y_offset = this_scroll_margin - (it.current_y - y_start); } if (PT < CHARPOS (scroll_margin_pos)) @@ -14831,6 +14651,9 @@ try_scrolling (Lisp_Object window, int just_this_one_p, || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos)) return SCROLLING_FAILED; + /* Additional scroll for when ZV was too close to point. */ + dy += y_offset; + /* Compute new window start. */ start_display (&it, w, startp); @@ -14885,7 +14708,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, if (!just_this_one_p || current_buffer->clip_changed || BEG_UNCHANGED < CHARPOS (startp)) - wset_base_line_number (w, Qnil); + w->base_line_number = 0; /* If cursor ends up on a partially visible line, treat that as being off the bottom of the screen. */ @@ -14938,7 +14761,7 @@ compute_window_start_on_continuation_line (struct window *w) SET_TEXT_POS (start_pos, ZV, ZV_BYTE); /* Find the start of the continued line. This should be fast - because scan_buffer is fast (newline cache). */ + because find_newline is fast (newline cache). */ row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0); init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), row, DEFAULT_FACE_ID); @@ -15034,7 +14857,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste region exists, cursor movement has to do more than just set the cursor. */ && markpos_of_region () < 0 - && NILP (w->region_showing) + && !w->region_showing && NILP (Vshow_trailing_whitespace) /* This code is not used for mini-buffer for the sake of the case of redisplaying to replace an echo area message; since in @@ -15471,7 +15294,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) set_buffer_internal_1 (XBUFFER (w->buffer)); current_matrix_up_to_date_p - = (!NILP (w->window_end_valid) + = (w->window_end_valid && !current_buffer->clip_changed && !current_buffer->prevent_redisplay_optimizations_p && !window_outdated (w)); @@ -15494,7 +15317,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) specbind (Qinhibit_point_motion_hooks, Qt); buffer_unchanged_p - = (!NILP (w->window_end_valid) + = (w->window_end_valid && !current_buffer->clip_changed && !window_outdated (w)); @@ -15507,7 +15330,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) if (XMARKER (w->start)->buffer == current_buffer) compute_window_start_on_continuation_line (w); - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; } /* Some sanity checks. */ @@ -15596,11 +15419,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p) w->force_start = 0; w->vscroll = 0; - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; /* Forget any recorded base line for line number display. */ if (!buffer_unchanged_p) - wset_base_line_number (w, Qnil); + w->base_line_number = 0; /* Redisplay the mode line. Select the buffer properly for that. Also, run the hook window-scroll-functions @@ -15840,7 +15663,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) || current_buffer->clip_changed || BEG_UNCHANGED < CHARPOS (startp)) /* Forget any recorded base line for line number display. */ - wset_base_line_number (w, Qnil); + w->base_line_number = 0; if (!cursor_row_fully_visible_p (w, 1, 0)) { @@ -15907,11 +15730,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p) debug_method_add (w, "recenter"); #endif - /* w->vscroll = 0; */ - /* Forget any previously recorded base line for line number display. */ if (!buffer_unchanged_p) - wset_base_line_number (w, Qnil); + w->base_line_number = 0; /* Determine the window start relative to point. */ init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); @@ -16045,8 +15866,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) line.) */ if (w->cursor.vpos < 0) { - if (!NILP (w->window_end_valid) - && PT >= Z - XFASTINT (w->window_end_pos)) + if (w->window_end_valid && PT >= Z - XFASTINT (w->window_end_pos)) { clear_glyph_matrix (w->desired_matrix); move_it_by_lines (&it, 1); @@ -16132,10 +15952,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) && !FRAME_WINDOW_P (f) && !WINDOW_FULL_WIDTH_P (w)) /* Line number to display. */ - || INTEGERP (w->base_line_pos) + || w->base_line_pos > 0 /* Column number is displayed and different from the one displayed. */ - || (!NILP (w->column_number_displayed) - && (XFASTINT (w->column_number_displayed) != current_column ()))) + || (w->column_number_displayed != -1 + && (w->column_number_displayed != current_column ()))) /* This means that the window has a mode line. */ && (WINDOW_WANTS_MODELINE_P (w) || WINDOW_WANTS_HEADER_LINE_P (w))) @@ -16166,11 +15986,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) goto need_larger_matrices; } - if (!line_number_displayed - && !BUFFERP (w->base_line_pos)) + if (!line_number_displayed && w->base_line_pos != -1) { - wset_base_line_pos (w, Qnil); - wset_base_line_number (w, Qnil); + w->base_line_pos = 0; + w->base_line_number = 0; } finish_menu_bars: @@ -16363,7 +16182,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) } /* But that is not valid info until redisplay finishes. */ - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; return 1; } @@ -16407,7 +16226,7 @@ try_window_reusing_current_matrix (struct window *w) /* Can't do this if region may have changed. */ if (0 <= markpos_of_region () - || !NILP (w->region_showing) + || w->region_showing || !NILP (Vshow_trailing_whitespace)) return 0; @@ -16610,7 +16429,7 @@ try_window_reusing_current_matrix (struct window *w) wset_window_end_pos (w, make_number (Z - ZV)); wset_window_end_vpos (w, make_number (0)); } - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; /* Update hint: don't try scrolling again in update_window. */ w->desired_matrix->no_scrolling_p = 1; @@ -16808,7 +16627,7 @@ try_window_reusing_current_matrix (struct window *w) (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled)); } - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; w->desired_matrix->no_scrolling_p = 1; #ifdef GLYPH_DEBUG @@ -16941,7 +16760,7 @@ find_first_unchanged_at_end_row (struct window *w, /* Display must not have been paused, otherwise the current matrix is not up to date. */ - eassert (!NILP (w->window_end_valid)); + eassert (w->window_end_valid); /* A value of window_end_pos >= END_UNCHANGED means that the window end is in the range of changed text. If so, there is no @@ -17125,7 +16944,7 @@ row_containing_pos (struct window *w, ptrdiff_t charpos, /* Try to redisplay window W by reusing its existing display. W's current matrix must be up to date when this function is called, - i.e. window_end_valid must not be nil. + i.e. window_end_valid must be nonzero. Value is @@ -17233,7 +17052,7 @@ try_window_id (struct window *w) GIVE_UP (7); /* Verify that display wasn't paused. */ - if (NILP (w->window_end_valid)) + if (!w->window_end_valid) GIVE_UP (8); /* Can't use this if highlighting a region because a cursor movement @@ -17246,7 +17065,7 @@ try_window_id (struct window *w) GIVE_UP (11); /* Likewise if showing a region. */ - if (!NILP (w->region_showing)) + if (w->region_showing) GIVE_UP (10); /* Can't use this if overlay arrow position and/or string have @@ -17884,7 +17703,7 @@ try_window_id (struct window *w) debug_end_vpos = XFASTINT (w->window_end_vpos)); /* Record that display has not been completed. */ - wset_window_end_valid (w, Qnil); + w->window_end_valid = 0; w->desired_matrix->no_scrolling_p = 1; return 3; @@ -18248,7 +18067,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) const unsigned char *arrow_end = arrow_string + arrow_len; const unsigned char *p; struct it it; - int multibyte_p; + bool multibyte_p; int n_glyphs_before; set_buffer_temp (buffer); @@ -19333,7 +19152,7 @@ display_line (struct it *it) } /* Is IT->w showing the region? */ - wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil); + it->w->region_showing = it->region_beg_charpos > 0 ? it->region_beg_charpos : 0; /* Clear the result glyph row and enable it. */ prepare_desired_row (row); @@ -20096,10 +19915,7 @@ See also `bidi-paragraph-direction'. */) to make sure we are within that paragraph. To that end, find the previous non-empty line. */ if (pos >= ZV && pos > BEGV) - { - pos--; - bytepos = CHAR_TO_BYTE (pos); - } + DEC_BOTH (pos, bytepos); if (fast_looking_at (build_string ("[\f\t ]*\n"), pos, bytepos, ZV, ZV_BYTE, Qnil) > 0) { @@ -20337,7 +20153,7 @@ display_mode_lines (struct window *w) /* These will be set while the mode line specs are processed. */ line_number_displayed = 0; - wset_column_number_displayed (w, Qnil); + w->column_number_displayed = -1; if (WINDOW_WANTS_MODELINE_P (w)) { @@ -20679,7 +20495,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision, risky); else if (c != 0) { - int multibyte; + bool multibyte; ptrdiff_t bytepos, charpos; const char *spec; Lisp_Object string; @@ -21284,7 +21100,7 @@ static char * decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_flag) { Lisp_Object val; - int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); + bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); const unsigned char *eol_str; int eol_str_len; /* The EOL conversion we are using. */ @@ -21360,8 +21176,7 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_ returned with spaces to that value. Return a Lisp string in *STRING if the resulting string is taken from that Lisp string. - Note we operate on the current buffer for most purposes, - the exception being w->base_line_pos. */ + Note we operate on the current buffer for most purposes. */ static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; @@ -21472,7 +21287,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, else { ptrdiff_t col = current_column (); - wset_column_number_displayed (w, make_number (col)); + w->column_number_displayed = col; pint2str (decode_mode_spec_buf, width, col); return decode_mode_spec_buf; } @@ -21531,27 +21346,24 @@ decode_mode_spec (struct window *w, register int c, int field_width, /* If we decided that this buffer isn't suitable for line numbers, don't forget that too fast. */ - if (EQ (w->base_line_pos, w->buffer)) + if (w->base_line_pos == -1) goto no_value; - /* But do forget it, if the window shows a different buffer now. */ - else if (BUFFERP (w->base_line_pos)) - wset_base_line_pos (w, Qnil); /* If the buffer is very big, don't waste time. */ if (INTEGERP (Vline_number_display_limit) && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit)) { - wset_base_line_pos (w, Qnil); - wset_base_line_number (w, Qnil); + w->base_line_pos = 0; + w->base_line_number = 0; goto no_value; } - if (INTEGERP (w->base_line_number) - && INTEGERP (w->base_line_pos) - && XFASTINT (w->base_line_pos) <= startpos) + if (w->base_line_number > 0 + && w->base_line_pos > 0 + && w->base_line_pos <= startpos) { - line = XFASTINT (w->base_line_number); - linepos = XFASTINT (w->base_line_pos); + line = w->base_line_number; + linepos = w->base_line_pos; linepos_byte = buf_charpos_to_bytepos (b, linepos); } else @@ -21574,8 +21386,8 @@ decode_mode_spec (struct window *w, register int c, int field_width, go back past it. */ if (startpos == BUF_BEGV (b)) { - wset_base_line_number (w, make_number (topline)); - wset_base_line_pos (w, make_number (BUF_BEGV (b))); + w->base_line_number = topline; + w->base_line_pos = BUF_BEGV (b); } else if (nlines < height + 25 || nlines > height * 3 + 50 || linepos == BUF_BEGV (b)) @@ -21601,13 +21413,13 @@ decode_mode_spec (struct window *w, register int c, int field_width, give up on line numbers for this window. */ if (position == limit_byte && limit == startpos - distance) { - wset_base_line_pos (w, w->buffer); - wset_base_line_number (w, Qnil); + w->base_line_pos = -1; + w->base_line_number = 0; goto no_value; } - wset_base_line_number (w, make_number (topline - nlines)); - wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position))); + w->base_line_number = topline - nlines; + w->base_line_pos = BYTE_TO_CHAR (position); } /* Now count lines from the start pos to point. */ @@ -21729,9 +21541,6 @@ decode_mode_spec (struct window *w, register int c, int field_width, return "@"; } - case 't': /* indicate TEXT or BINARY */ - return "T"; - case 'z': /* coding-system (not including end-of-line format) */ case 'Z': @@ -21781,11 +21590,15 @@ decode_mode_spec (struct window *w, register int c, int field_width, } -/* Count up to COUNT lines starting from START_BYTE. - But don't go beyond LIMIT_BYTE. - Return the number of lines thus found (always nonnegative). +/* Count up to COUNT lines starting from START_BYTE. COUNT negative + means count lines back from START_BYTE. But don't go beyond + LIMIT_BYTE. Return the number of lines thus found (always + nonnegative). - Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */ + Set *BYTE_POS_PTR to the byte position where we stopped. This is + either the position COUNT lines after/before START_BYTE, if we + found COUNT lines, or LIMIT_BYTE if we hit the limit before finding + COUNT lines. */ static ptrdiff_t display_count_lines (ptrdiff_t start_byte, @@ -21812,31 +21625,36 @@ display_count_lines (ptrdiff_t start_byte, ceiling = min (limit_byte - 1, ceiling); ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; base = (cursor = BYTE_POS_ADDR (start_byte)); - while (1) + + do { if (selective_display) - while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr) - ; + { + while (*cursor != '\n' && *cursor != 015 + && ++cursor != ceiling_addr) + continue; + if (cursor == ceiling_addr) + break; + } else - while (*cursor != '\n' && ++cursor != ceiling_addr) - ; + { + cursor = memchr (cursor, '\n', ceiling_addr - cursor); + if (! cursor) + break; + } - if (cursor != ceiling_addr) + cursor++; + + if (--count == 0) { - if (--count == 0) - { - start_byte += cursor - base + 1; - *byte_pos_ptr = start_byte; - return orig_count; - } - else - if (++cursor == ceiling_addr) - break; + start_byte += cursor - base; + *byte_pos_ptr = start_byte; + return orig_count; } - else - break; } - start_byte += cursor - base; + while (cursor < ceiling_addr); + + start_byte += ceiling_addr - base; } } else @@ -21845,35 +21663,35 @@ display_count_lines (ptrdiff_t start_byte, { ceiling = BUFFER_FLOOR_OF (start_byte - 1); ceiling = max (limit_byte, ceiling); - ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; + ceiling_addr = BYTE_POS_ADDR (ceiling); base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); while (1) { if (selective_display) - while (--cursor != ceiling_addr - && *cursor != '\n' && *cursor != 015) - ; + { + while (--cursor >= ceiling_addr + && *cursor != '\n' && *cursor != 015) + continue; + if (cursor < ceiling_addr) + break; + } else - while (--cursor != ceiling_addr && *cursor != '\n') - ; + { + cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr); + if (! cursor) + break; + } - if (cursor != ceiling_addr) + if (++count == 0) { - if (++count == 0) - { - start_byte += cursor - base + 1; - *byte_pos_ptr = start_byte; - /* When scanning backwards, we should - not count the newline posterior to which we stop. */ - return - orig_count - 1; - } + start_byte += cursor - base + 1; + *byte_pos_ptr = start_byte; + /* When scanning backwards, we should + not count the newline posterior to which we stop. */ + return - orig_count - 1; } - else - break; } - /* Here we add 1 to compensate for the last decrement - of CURSOR, which took it past the valid range. */ - start_byte += cursor - base + 1; + start_byte += ceiling_addr - base; } } @@ -27793,7 +27611,7 @@ note_mouse_highlight (struct frame *f, int x, int y) And verify the buffer's text has not changed. */ b = XBUFFER (w->buffer); if (part == ON_TEXT - && EQ (w->window_end_valid, w->buffer) + && w->window_end_valid && w->last_modified == BUF_MODIFF (b) && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b)) { @@ -28426,6 +28244,9 @@ x_draw_vertical_border (struct window *w) if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame))) return; + /* Note: It is necessary to redraw both the left and the right + borders, for when only this single window W is being + redisplayed. */ if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) { @@ -28439,8 +28260,8 @@ x_draw_vertical_border (struct window *w) FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1); } - else if (!WINDOW_LEFTMOST_P (w) - && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) + if (!WINDOW_LEFTMOST_P (w) + && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) { int x0, x1, y0, y1; diff --git a/src/xfaces.c b/src/xfaces.c index 43535b9ea0c..71709446c1d 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -1585,7 +1585,7 @@ the face font sort order. */) for (i = nfonts - 1; i >= 0; --i) { Lisp_Object font = AREF (vec, i); - Lisp_Object v = Fmake_vector (make_number (8), Qnil); + Lisp_Object v = make_uninit_vector (8); int point; Lisp_Object spacing; @@ -6152,7 +6152,7 @@ face_at_string_position (struct window *w, Lisp_Object string, struct frame *f = XFRAME (WINDOW_FRAME (w)); Lisp_Object attrs[LFACE_VECTOR_SIZE]; struct face *base_face; - int multibyte_p = STRING_MULTIBYTE (string); + bool multibyte_p = STRING_MULTIBYTE (string); Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface; /* Get the value of the face property at the current position within diff --git a/src/xfns.c b/src/xfns.c index 65148d1c9e1..5c93b8ef4da 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3539,9 +3539,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, CHECK_STRING (color); if (x_defined_color (f, SSDATA (color), &foo, 0)) - return list3 (make_number (foo.red), - make_number (foo.green), - make_number (foo.blue)); + return list3i (foo.red, foo.green, foo.blue); else return Qnil; } @@ -3703,9 +3701,8 @@ If omitted or nil, that stands for the selected frame's display. */) struct x_display_info *dpyinfo = check_x_display_info (terminal); Display *dpy = dpyinfo->display; - return Fcons (make_number (ProtocolVersion (dpy)), - Fcons (make_number (ProtocolRevision (dpy)), - Fcons (make_number (VendorRelease (dpy)), Qnil))); + return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy), + VendorRelease (dpy)); } DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, @@ -5416,7 +5413,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) XmStringFree (default_xmstring); } - record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0)); + record_unwind_protect (clean_up_file_dialog, make_save_pointer (dialog)); /* Process events until the user presses Cancel or OK. */ x_menu_set_in_use (1); diff --git a/src/xgselect.c b/src/xgselect.c index db7dce10ad0..2c8e9671abb 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -15,7 +15,7 @@ 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/>. */ +along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> diff --git a/src/xmenu.c b/src/xmenu.c index 7f6914d26ac..958cd220393 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1477,7 +1477,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, timestamp ? timestamp : gtk_get_current_event_time ()); - record_unwind_protect (pop_down_menu, make_save_value (menu, 0)); + record_unwind_protect (pop_down_menu, make_save_pointer (menu)); if (gtk_widget_get_mapped (menu)) { @@ -1826,7 +1826,7 @@ xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, /* Make sure to free the widget_value objects we used to specify the contents even with longjmp. */ record_unwind_protect (cleanup_widget_value_tree, - make_save_value (first_wv, 0)); + make_save_pointer (first_wv)); /* Actually create and show the menu until popped down. */ create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp); @@ -1925,7 +1925,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv) if (menu) { ptrdiff_t specpdl_count = SPECPDL_INDEX (); - record_unwind_protect (pop_down_menu, make_save_value (menu, 0)); + record_unwind_protect (pop_down_menu, make_save_pointer (menu)); /* Display the menu. */ gtk_widget_show_all (menu); @@ -2136,7 +2136,7 @@ xdialog_show (FRAME_PTR f, /* Make sure to free the widget_value objects we used to specify the contents even with longjmp. */ record_unwind_protect (cleanup_widget_value_tree, - make_save_value (first_wv, 0)); + make_save_pointer (first_wv)); /* Actually create and show the dialog. */ create_and_show_dialog (f, first_wv); @@ -2479,7 +2479,7 @@ xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, #endif record_unwind_protect (pop_down_menu, - format_save_value ("pp", f, menu)); + make_save_value ("pp", f, menu)); /* Help display under X won't work because XMenuActivate contains a loop that doesn't give Emacs a chance to process it. */ diff --git a/src/xml.c b/src/xml.c index 5a52b0c2a1e..4b466dc1bca 100644 --- a/src/xml.c +++ b/src/xml.c @@ -93,7 +93,7 @@ init_libxml2_functions (void) if (!(library = w32_delayed_load (Qlibxml2_dll))) { - message ("%s", "libxml2 library not found"); + message1 ("libxml2 library not found"); return 0; } diff --git a/src/xselect.c b/src/xselect.c index b7cdf70ff77..5b90d7def22 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -1141,7 +1141,7 @@ wait_for_property_change (struct prop_location *location) /* Make sure to do unexpect_property_change if we quit or err. */ record_unwind_protect (wait_for_property_change_unwind, - make_save_value (location, 0)); + make_save_pointer (location)); XSETCAR (property_change_reply, Qnil); property_change_reply_object = location; @@ -1670,11 +1670,10 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, return x_atom_to_symbol (display, (Atom) idata[0]); else { - Lisp_Object v = Fmake_vector (make_number (size / sizeof (int)), - make_number (0)); + Lisp_Object v = make_uninit_vector (size / sizeof (int)); + for (i = 0; i < size / sizeof (int); i++) - Faset (v, make_number (i), - x_atom_to_symbol (display, (Atom) idata[i])); + ASET (v, i, x_atom_to_symbol (display, (Atom) idata[i])); return v; } } @@ -1694,24 +1693,24 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, else if (format == 16) { ptrdiff_t i; - Lisp_Object v; - v = Fmake_vector (make_number (size / 2), make_number (0)); + Lisp_Object v = make_uninit_vector (size / 2); + for (i = 0; i < size / 2; i++) { short j = ((short *) data) [i]; - Faset (v, make_number (i), make_number (j)); + ASET (v, i, make_number (j)); } return v; } else { ptrdiff_t i; - Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE), - make_number (0)); + Lisp_Object v = make_uninit_vector (size / X_LONG_SIZE); + for (i = 0; i < size / X_LONG_SIZE; i++) { int j = ((int *) data) [i]; - Faset (v, make_number (i), INTEGER_TO_CONS (j)); + ASET (v, i, INTEGER_TO_CONS (j)); } return v; } @@ -1904,7 +1903,7 @@ clean_local_selection_data (Lisp_Object obj) Lisp_Object copy; if (size == 1) return clean_local_selection_data (AREF (obj, 0)); - copy = Fmake_vector (make_number (size), Qnil); + copy = make_uninit_vector (size); for (i = 0; i < size; i++) ASET (copy, i, clean_local_selection_data (AREF (obj, i))); return copy; diff --git a/src/xterm.c b/src/xterm.c index 26d40859ed3..88433b6c0b3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6102,16 +6102,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, last_user_time = event.xproperty.time; f = x_top_window_to_frame (dpyinfo, event.xproperty.window); if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state) - if (x_handle_net_wm_state (f, &event.xproperty) && f->iconified - && f->output_data.x->net_wm_state_hidden_seen) + if (x_handle_net_wm_state (f, &event.xproperty) + && FRAME_ICONIFIED_P (f) + && f->output_data.x->net_wm_state_hidden_seen) { - /* Gnome shell does not iconify us when C-z is pressed. It hides - the frame. So if our state says we aren't hidden anymore, - treat it as deiconified. */ - if (! f->async_iconified) - SET_FRAME_GARBAGED (f); - f->async_visible = 1; - f->async_iconified = 0; + /* Gnome shell does not iconify us when C-z is pressed. + It hides the frame. So if our state says we aren't + hidden anymore, treat it as deiconified. */ + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, 0); f->output_data.x->has_been_visible = 1; f->output_data.x->net_wm_state_hidden_seen = 0; inev.ie.kind = DEICONIFY_EVENT; @@ -6152,10 +6151,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, event.xexpose.width, event.xexpose.height, FALSE); #endif - if (f->async_visible == 0) + if (!FRAME_VISIBLE_P (f)) { - f->async_visible = 1; - f->async_iconified = 0; + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, 0); f->output_data.x->has_been_visible = 1; SET_FRAME_GARBAGED (f); } @@ -6232,20 +6231,20 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (f) /* F may no longer exist if the frame was deleted. */ { + bool visible = FRAME_VISIBLE_P (f); /* While a frame is unmapped, display generation is disabled; you don't want to spend time updating a display that won't ever be seen. */ - f->async_visible = 0; + SET_FRAME_VISIBLE (f, 0); /* We can't distinguish, from the event, whether the window has become iconified or invisible. So assume, if it was previously visible, than now it is iconified. But x_make_frame_invisible clears both the visible flag and the iconified flag; and that way, we know the window is not iconified now. */ - if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)) + if (visible || FRAME_ICONIFIED_P (f)) { - f->async_iconified = 1; - + SET_FRAME_ICONIFIED (f, 1); inev.ie.kind = ICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); } @@ -6264,13 +6263,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, f = x_top_window_to_frame (dpyinfo, event.xmap.window); if (f) { + bool iconified = FRAME_ICONIFIED_P (f); /* wait_reading_process_output will notice this and update the frame's display structures. If we where iconified, we should not set garbaged, because that stops redrawing on Expose events. This looks bad if we are called from a recursive event loop (x_dispatch_event), for example when a dialog is up. */ - if (! f->async_iconified) + if (!iconified) SET_FRAME_GARBAGED (f); /* Check if fullscreen was specified before we where mapped the @@ -6278,20 +6278,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (!f->output_data.x->has_been_visible) x_check_fullscreen (f); - f->async_visible = 1; - f->async_iconified = 0; + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, 0); f->output_data.x->has_been_visible = 1; - if (f->iconified) + if (iconified) { inev.ie.kind = DEICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); } - else if (! NILP (Vframe_list) - && ! NILP (XCDR (Vframe_list))) - /* Force a redisplay sooner or later - to update the frame titles - in case this is the second frame. */ + else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) + /* Force a redisplay sooner or later to update the + frame titles in case this is the second frame. */ record_asynch_buffer_change (); #ifdef USE_GTK @@ -8417,7 +8415,7 @@ get_current_wm_state (struct frame *f, if (tmp_data) XFree (tmp_data); x_uncatch_errors (); unblock_input (); - return ! f->iconified; + return !FRAME_ICONIFIED_P (f); } x_uncatch_errors (); @@ -8529,7 +8527,7 @@ do_ewmh_fullscreen (struct frame *f) static void XTfullscreen_hook (FRAME_PTR f) { - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) { block_input (); x_check_fullscreen (f); @@ -8793,7 +8791,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows) /* But the ConfigureNotify may in fact never arrive, and then this is not right if the frame is visible. Instead wait (with timeout) for the ConfigureNotify. */ - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) x_wait_for_event (f, ConfigureNotify); else { @@ -8905,9 +8903,8 @@ void x_raise_frame (struct frame *f) { block_input (); - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); - XFlush (FRAME_X_DISPLAY (f)); unblock_input (); } @@ -8917,7 +8914,7 @@ x_raise_frame (struct frame *f) static void x_lower_frame (struct frame *f) { - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) { block_input (); XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); @@ -8933,7 +8930,7 @@ xembed_request_focus (FRAME_PTR f) { /* See XEmbed Protocol Specification at http://freedesktop.org/wiki/Specifications/xembed-spec */ - if (f->async_visible) + if (FRAME_VISIBLE_P (f)) xembed_send_message (f, CurrentTime, XEMBED_REQUEST_FOCUS, 0, 0, 0); } @@ -8947,16 +8944,14 @@ x_ewmh_activate_frame (FRAME_PTR f) http://freedesktop.org/wiki/Specifications/wm-spec */ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - if (f->async_visible && wm_supports (f, dpyinfo->Xatom_net_active_window)) + + if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window)) { Lisp_Object frame; XSETFRAME (frame, f); x_send_client_event (frame, make_number (0), frame, dpyinfo->Xatom_net_active_window, - make_number (32), - Fcons (make_number (1), - Fcons (make_number (last_user_time), - Qnil))); + make_number (32), list2i (1, last_user_time)); } } @@ -9159,9 +9154,6 @@ x_make_frame_visible (struct frame *f) poll_for_input_1 (); poll_suppress_count = old_poll_suppress_count; } - - /* See if a MapNotify event has been processed. */ - FRAME_SAMPLE_VISIBILITY (f); } /* 2000-09-28: In @@ -9229,10 +9221,8 @@ x_make_frame_invisible (struct frame *f) So we can't win using the usual strategy of letting FRAME_SAMPLE_VISIBILITY set this. So do it by hand, and synchronize with the server to make sure we agree. */ - f->visible = 0; - FRAME_ICONIFIED_P (f) = 0; - f->async_visible = 0; - f->async_iconified = 0; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 0); x_sync (f); @@ -9253,13 +9243,11 @@ x_iconify_frame (struct frame *f) if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f) FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0; - if (f->async_iconified) + if (FRAME_ICONIFIED_P (f)) return; block_input (); - FRAME_SAMPLE_VISIBILITY (f); - type = x_icon_type (f); if (!NILP (type)) x_bitmap_icon (f, type); @@ -9271,10 +9259,8 @@ x_iconify_frame (struct frame *f) gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); - f->iconified = 1; - f->visible = 1; - f->async_iconified = 1; - f->async_visible = 0; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 1); unblock_input (); return; } @@ -9291,10 +9277,8 @@ x_iconify_frame (struct frame *f) /* The server won't give us any event to indicate that an invisible frame was changed to an icon, so we have to record it here. */ - f->iconified = 1; - f->visible = 1; - f->async_iconified = 1; - f->async_visible = 0; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 1); unblock_input (); return; } @@ -9307,9 +9291,8 @@ x_iconify_frame (struct frame *f) if (!result) error ("Can't notify window manager of iconification"); - f->async_iconified = 1; - f->async_visible = 0; - + SET_FRAME_ICONIFIED (f, 1); + SET_FRAME_VISIBLE (f, 0); block_input (); XFlush (FRAME_X_DISPLAY (f)); @@ -9358,8 +9341,8 @@ x_iconify_frame (struct frame *f) XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); } - f->async_iconified = 1; - f->async_visible = 0; + SET_FRAME_ICONIFIED (f, 1); + SET_FRAME_VISIBLE (f, 0); XFlush (FRAME_X_DISPLAY (f)); unblock_input (); @@ -10787,16 +10770,6 @@ With MS Windows or Nextstep, the value is t. */); Vx_toolkit_scroll_bars = Qnil; #endif - DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion", - scroll_bar_adjust_thumb_portion_p, - doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF. -Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards -even if the end of the buffer is shown (i.e. overscrolling). -Set to nil if you want the thumb to be at the bottom when the end of the buffer -is shown. Also, the thumb fills the whole scroll bar when the entire buffer -is visible. In this case you can not overscroll. */); - scroll_bar_adjust_thumb_portion_p = 1; - staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; |
