aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Tromey2013-03-08 11:57:29 -0700
committerTom Tromey2013-03-08 11:57:29 -0700
commit71f91792e3013b397996905224f387da5cc539a9 (patch)
tree4c3d3ba909e76deea1cdf73b73fca67a57149465 /src
parent6f4de085f065e11f4df3195d47479f28f5ef08ba (diff)
parentb5426561089d39f18b42bed9dbfcb531f43ed562 (diff)
downloademacs-71f91792e3013b397996905224f387da5cc539a9.tar.gz
emacs-71f91792e3013b397996905224f387da5cc539a9.zip
merge from trunk
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit3
-rw-r--r--src/ChangeLog1259
-rw-r--r--src/ChangeLog.102
-rw-r--r--src/Makefile.in34
-rw-r--r--src/alloc.c49
-rw-r--r--src/autodeps.mk1
-rw-r--r--src/bidi.c38
-rw-r--r--src/buffer.c14
-rw-r--r--src/buffer.h61
-rw-r--r--src/callint.c58
-rw-r--r--src/callproc.c82
-rw-r--r--src/ccl.c3
-rw-r--r--src/charset.c4
-rw-r--r--src/cm.c3
-rw-r--r--src/coding.c86
-rw-r--r--src/coding.h34
-rw-r--r--src/composite.c27
-rw-r--r--src/conf_post.h4
-rw-r--r--src/deps.mk2
-rw-r--r--src/dired.c126
-rw-r--r--src/dispnew.c108
-rw-r--r--src/doc.c19
-rw-r--r--src/doprnt.c2
-rw-r--r--src/editfns.c51
-rw-r--r--src/emacs.c41
-rw-r--r--src/eval.c2
-rw-r--r--src/fileio.c498
-rw-r--r--src/filelock.c477
-rw-r--r--src/fns.c29
-rw-r--r--src/font.c58
-rw-r--r--src/font.h2
-rw-r--r--src/fontset.c5
-rw-r--r--src/frame.c45
-rw-r--r--src/frame.h104
-rw-r--r--src/ftfont.c7
-rw-r--r--src/gtkutil.c21
-rw-r--r--src/image.c10
-rw-r--r--src/indent.c119
-rw-r--r--src/indent.h12
-rw-r--r--src/insdel.c16
-rw-r--r--src/intervals.h4
-rw-r--r--src/keyboard.c668
-rw-r--r--src/keyboard.h2
-rw-r--r--src/keymap.c8
-rw-r--r--src/lisp.h168
-rw-r--r--src/lread.c75
-rw-r--r--src/macros.c12
-rw-r--r--src/makefile.w32-in6
-rw-r--r--src/marker.c28
-rw-r--r--src/mem-limits.h43
-rw-r--r--src/msdos.c45
-rw-r--r--src/msdos.h2
-rw-r--r--src/nsfns.m18
-rw-r--r--src/nsfont.m16
-rw-r--r--src/nsmenu.m4
-rw-r--r--src/nsselect.m2
-rw-r--r--src/nsterm.h11
-rw-r--r--src/nsterm.m273
-rw-r--r--src/pre-crt0.c10
-rw-r--r--src/print.c43
-rw-r--r--src/process.c90
-rw-r--r--src/process.h8
-rw-r--r--src/profiler.c2
-rw-r--r--src/ralloc.c188
-rw-r--r--src/region-cache.h2
-rw-r--r--src/search.c258
-rw-r--r--src/sheap.c4
-rw-r--r--src/sound.c2
-rw-r--r--src/syntax.c12
-rw-r--r--src/sysdep.c30
-rw-r--r--src/term.c4
-rw-r--r--src/termcap.c2
-rw-r--r--src/textprop.c241
-rw-r--r--src/unexaix.c95
-rw-r--r--src/unexcoff.c4
-rw-r--r--src/unexw32.c2
-rw-r--r--src/vm-limit.c111
-rw-r--r--src/w16select.c6
-rw-r--r--src/w32.c748
-rw-r--r--src/w32.h4
-rw-r--r--src/w32fns.c21
-rw-r--r--src/w32heap.c6
-rw-r--r--src/w32notify.c12
-rw-r--r--src/w32proc.c95
-rw-r--r--src/w32term.c163
-rw-r--r--src/w32uniscribe.c6
-rw-r--r--src/window.c97
-rw-r--r--src/window.h63
-rw-r--r--src/xdisp.c771
-rw-r--r--src/xfaces.c4
-rw-r--r--src/xfns.c11
-rw-r--r--src/xgselect.c2
-rw-r--r--src/xmenu.c10
-rw-r--r--src/xml.c2
-rw-r--r--src/xselect.c23
-rw-r--r--src/xterm.c113
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
358 358
359define pwinx 359define pwinx
360 set $w = $arg0 360 set $w = $arg0
361 xgetint $w->sequence_number
362 if ($w->mini_p != Qnil) 361 if ($w->mini_p != Qnil)
363 printf "Mini " 362 printf "Mini "
364 end 363 end
@@ -607,7 +606,7 @@ Pretty print all glyphs in it->glyph_row.
607end 606end
608 607
609define prowlims 608define prowlims
610 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 609 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
611end 610end
612document prowlims 611document prowlims
613Print important attributes of a glyph_row structure. 612Print 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 @@
12013-03-08 Dmitry Antipov <dmantipov@yandex.ru>
2
3 * search.c (find_newline): Accept start and end byte positions
4 as arguments and allow -1 if not known.
5 (find_newline_no_quit): Likewise for start position.
6 * lisp.h (find_newline, find_newline_no_quit): Adjust prototype.
7 * bidi.c (bidi_find_paragraph_start): Pass byte position to
8 find_newline_no_quit, thus eliminating CHAR_TO_BYTE.
9 * editfns.c (Fconstrain_to_field): Break long line. Adjust
10 call to find_newline.
11 * indent.c (vmotion): Adjust calls to find_newline_no_quit.
12 Use DEC_BOTH to start next search from the previous buffer
13 position, where appropriate.
14 * xdisp.c (back_to_previous_line_start, forward_to_next_line_start)
15 (get_visually_first_element, move_it_vertically_backward): Likewise.
16 Obtain byte position from the display iterator, where appropriate.
17
182013-03-08 Paul Eggert <eggert@cs.ucla.edu>
19
20 print.c, process.c: Use bool for booleans.
21 * lisp.h (wait_reading_process_output):
22 * print.c (print_output_debug_flag, PRINTDECLARE, printchar)
23 (strout, debug_output_compilation_hack, float_to_string, print)
24 (print_object):
25 * process.c (kbd_is_on_hold, inhibit_sentinels, process_output_skip)
26 (decode_status, status_message, create_process, create_pty)
27 (Fmake_network_process, Fnetwork_interface_info)
28 (wait_reading_process_output, read_process_output)
29 (write_queue_push, write_queue_pop, process_send_signal)
30 (handle_child_signal, keyboard_bit_set, kbd_on_hold_p):
31 * process.h (struct Lisp_Process, inhibit_sentinels, kbd_on_hold_p):
32 Use bool for booleans.
33 * process.c (Fnetwork_interface_list): Remove unused local.
34 (connect_counter): Now EMACS_INT, not int.
35
362013-03-08 Dmitry Antipov <dmantipov@yandex.ru>
37
38 * bidi.c (bidi_fetch_char): Swap first and second arguments
39 to match other functions accepting character and byte positions.
40 Adjust comment.
41 (bidi_resolve_explicit_1, bidi_level_of_next_char): Adjust users.
42 (bidi_paragraph_init): Likewise. Use DEC_BOTH which is faster
43 when you need just to move to the previous buffer position.
44 * xdisp.c (Fcurrent_bidi_paragraph_direction): Use DEC_BOTH.
45
462013-03-07 Eli Zaretskii <eliz@gnu.org>
47
48 * .gdbinit (prowlims): Display the enabled_p flag of the row.
49
502013-03-07 Dmitry Antipov <dmantipov@yandex.ru>
51
52 Avoid character to byte conversions in motion subroutines.
53 * indent.h (compute_motion, vmotion): Add byte position argument.
54 * indent.c (compute_motion): Use it and avoid CHAR_TO_BYTE.
55 Add eassert.
56 (Fcompute_motion): Break long line. Adjust call to compute_motion.
57 Use list5 for return value.
58 (vmotion): Use byte position argument and avoid call to CHAR_TO_BYTE.
59 Adjust comments, style and calls to compute_motion.
60 (Fvertical_motion): Adjust call to vmotion.
61 * window.c (Fdelete_other_windows_internal): Record window start
62 byte position and adjust call to vmotion.
63 (window_scroll_line_based): Likewise with call to compute_motion.
64 Use SET_PT_BOTH.
65 (Frecenter): Adjust calls to vmotion.
66
672013-03-07 Dmitry Antipov <dmantipov@yandex.ru>
68
69 * lisp.h (list2i, list3i): New functions.
70 (list4i): Move from window.c and make LISP_INLINE.
71 * editfns.c (make_lisp_time):
72 * fns.c (Flocale_info):
73 * keyboard.c (parse_modifiers):
74 * xterm.c (x_ewmh_activate_frame): Use list2i.
75 * instel.c (signal_after_change):
76 * nsfns.m (Fx_server_version, Fxw_color_values):
77 * w32fns.c (Fxw_color_values, Fx_server_version):
78 * xfns.c (Fxw_color_values, Fx_server_version): Use list3i.
79 * fileio.c (Fvisited_file_modtime):
80 * nsfns.m (Fns_display_usable_bounds):
81 * w32.c (ltime): Use list4i.
82
832013-03-06 Eli Zaretskii <eliz@gnu.org>
84
85 * search.c (find_newline_no_quit): Rename from find_next_newline.
86 Add commentary.
87
88 * lisp.h (find_newline_no_quit): Rename prototype.
89
90 * xdisp.c (back_to_previous_line_start)
91 (forward_to_next_line_start, get_visually_first_element)
92 (move_it_vertically_backward): Callers of find_newline_no_quit changed.
93 * indent.c (vmotion): Callers of find_newline_no_quit changed.
94 * bidi.c (bidi_find_paragraph_start): Callers of
95 find_newline_no_quit changed.
96
97 * msdos.c: Change encoding to cp850. (Bug#13879)
98 (fr_keyboard, it_keyboard, dk_keyboard): Update keyboard layouts.
99
1002013-03-06 Dmitry Antipov <dmantipov@yandex.ru>
101
102 Coding system support cleanup and minor refactoring.
103 * coding.h (enum coding_result_code): Remove
104 CODING_RESULT_INCONSISTENT_EOL and CODING_RESULT_INSUFFICIENT_MEM.
105 (toplevel): Remove unused CODING_MODE_INHIBIT_INCONSISTENT_EOL.
106 (CODING_MODE_LAST_BLOCK, CODING_MODE_SELECTIVE_DISPLAY)
107 (CODING_MODE_DIRECTION, CODING_MODE_FIXED_DESTINATION)
108 (CODING_MODE_SAFE_ENCODING): Rearrange bit values.
109 (decode_coding_region, encode_coding_region, decode_coding_string):
110 Remove unused compatibility macros.
111 * coding.c (Qinconsistent_eol, Qinsufficient_memory): Remove.
112 (record_conversion_result): Adjust user.
113 (syms_of_coding): Likewise.
114 (ALLOC_CONVERSION_WORK_AREA): Use SAFE_ALLOCA.
115 (decode_coding, encode_coding): Add USE_SAFE_ALLOCA and SAFE_FREE.
116 (decode_coding_object): Simplify since xrealloc never returns NULL.
117 Add eassert.
118
1192013-03-06 Paul Eggert <eggert@cs.ucla.edu>
120
121 Fix a build failure on OpenBSD 4.x and MirBSD (Bug#13881).
122 * sysdep.c (list_system_processes)
123 [BSD_SYSTEM && !DARWIN_OS && !__FreeBSD__]:
124 Make it a stub in this case; otherwise the build might fail,
125 and this code hasn't been tested on such hosts anyway.
126 Problem reported by Nelson H. F. Beebe in
127 <http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00021.html>
128 and analyzed by Jérémie Courrèges-Anglas in
129 <http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00062.html>.
130
1312013-03-06 Dmitry Antipov <dmantipov@yandex.ru>
132
133 * lisp.h (find_next_newline_no_quit): Rename to find_next_newline.
134 * xdisp.c (back_to_previous_line_start, forward_to_next_line_start)
135 (get_visually_first_element, move_it_vertically_backward): Ajust users.
136 * bidi.c (bidi_find_paragraph_start): Likewise.
137 * indent.c (vmotion): Likewise.
138
1392013-03-05 Paul Eggert <eggert@cs.ucla.edu>
140
141 FILE's lock is now always .#FILE and may be a regular file (Bug#13807).
142 * filelock.c: Include <c-ctype.h>.
143 (MAX_LFINFO): New top-level constant.
144 (lock_info_type): Remove members pid, boot_time. Add members at,
145 dot, colon. Change user member to be the entire buffer, not a
146 pointer. This allows us to handle the case where a foreign
147 pid or boot time exceeds the local range. All uses changed.
148 (LINKS_MIGHT_NOT_WORK): New constant.
149 (FREE_LOCK_INFO): Remove, as the pieces no longer need freeing.
150 (defined_WINDOWSNT): Remove.
151 (MAKE_LOCK_NAME, file_in_lock_file_name):
152 Always use .#FILE (not .#-FILE) for the file lock,
153 even if it is a regular file.
154 (rename_lock_file): New function.
155 (create_lock_file): Use it.
156 (create_lock_file, read_lock_data):
157 Prefer a symbolic link for the lock file, falling back on a
158 regular file if symlinks don't work. Do not try to create
159 symlinks on MS-Windows, due to security hassles. Stick with
160 POSIXish functions (open, read, write, close, fchmod, readlink, symlink,
161 link, rename, unlink, mkstemp) when creating locks, as a GNUish
162 host may be using a Windowsish file system, and cannot use
163 MS-Windows-only system calls. Fall back on mktemp if mkstemp
164 doesn't work. Don't fail merely because of a symlink-contents
165 length limit in the current file system; fall back on regular
166 files. Increase the symlink contents length limit to 8 KiB, this
167 should be big enough for any real use and doesn't crunch the
168 stack.
169 (create_lock_file, lock_file_1, read_lock_data):
170 Simplify allocation of lock file buffers now that they fit in 8 KiB.
171 (lock_file_1): Return error number, not bool. All callers changed.
172 (ELOOP): New macro, if not already defined.
173 (read_lock_data): Return size of lock file contents, not Lisp object.
174 All callers changed. Handle a race condition if some other process
175 replaces a regular-file lock with a symlink lock or vice versa,
176 while we're trying to read the lock.
177 (current_lock_owner): Parse contents more carefully, to help avoid
178 confusing a regular-file lock with some other application's use
179 of the file. Check for lock file contents being too long, or
180 not parsing correctly.
181 (current_lock_owner, lock_file):
182 Allow foreign pid and boot times that exceed the local range.
183 (current_lock_owner, lock_if_free, lock_file):
184 Simplify allocation of lock file contents.
185 * w32.c (sys_rename_replace): New function, containing most of
186 the contents of the old sys_rename.
187 (sys_rename): Use it.
188 (fchmod): New dummy function.
189 * w32.h (sys_rename_replace, fchmod): New decls.
190
1912013-03-05 Eli Zaretskii <eliz@gnu.org>
192
193 * bidi.c (bidi_resolve_explicit_1): Don't call CHAR_TO_BYTE or
194 bidi_count_bytes, as the callers now arrange for bidi_it->charpos
195 to be in sync with bidi_it->bytepos. Suggested by Dmitry Antipov
196 <dmantipov@yandex.ru>.
197
1982013-03-05 Dmitry Antipov <dmantipov@yandex.ru>
199
200 * composite.c (get_composition_id, fill_gstring_header):
201 Use make_uninit_vector where appropriate.
202 * font.c (Ffont_get_glyphs, build_style_table): Likewise.
203 * xselect.c (clean_local_selection_data): Likewise.
204
2052013-03-04 Paul Eggert <eggert@cs.ucla.edu>
206
207 Fix misuse of ImageMagick that caused core dump (Bug#13846).
208 * image.c (imagemagick_load_image): Calculate height and width
209 after flattening the image, not before.
210
2112013-03-04 Dmitry Antipov <dmantipov@yandex.ru>
212
213 * font.c (Ffont_get_glyphs): Use convenient LGLYPH_NEW.
214 * ftfont.c (ftfont_shape_by_flt): Likewise.
215 * w32uniscribe.c (uniscribe_shape): Likewise.
216
2172013-03-02 Paul Eggert <eggert@cs.ucla.edu>
218
219 The lock for FILE is now .#FILE or .#-FILE (Bug#13807).
220 The old approach, which fell back on DIR/.#FILE.0 through
221 DIR/.#FILE.9, had race conditions that could not be easily fixed.
222 If DIR/.#FILE is a non-symlink file, Emacs now does not create a
223 lock file for DIR/FILE; that is, DIR/FILE is no longer partly
224 protected by a lock if DIR/.#FILE is a non-symlink file ("partly"
225 because the locking mechanism was never reliable in that case).
226 This patch fixes this and other bugs discovered by a code
227 inspection that was prompted by
228 <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00531.html>.
229 Also, this patch switches to .#-FILE (not .#FILE) on MS-Windows,
230 to avoid interoperability problems between the MS-Windows and
231 non-MS-Windows implementations. MS-Windows and non-MS-Windows
232 instances of Emacs now ignore each others' locks.
233 * filelock.c (defined_WINDOWSNT): New constant.
234 (MAKE_LOCK_NAME, fill_in_lock_file_name):
235 Don't create DIR/.#FILE.0 through DIR/.#FILE.9. Instead, create
236 DIR/.#FILE symlinks on non-MS-Windows hosts, and DIR/.#-FILE
237 regular files on MS-Windows hosts.
238 (MAKE_LOCK_NAME, unlock_file, Ffile_locked_p):
239 Use SAFE_ALLOCA to avoid problems with long file names.
240 (MAX_LFINFO): Now a local constant, not a global macro.
241 (IS_LOCK_FILE): Remove.
242 (lock_file_1): Don't inspect errno if symlink call succeeds;
243 that's not portable.
244 (lock_file): Document that this function can return if lock
245 creation fails.
246 (lock_file): Don't access freed storage.
247
2482013-03-02 Andreas Schwab <schwab@linux-m68k.org>
249
250 * lisp.h (XPNTR) [!USE_LSB_TAG]: Remove extra paren. (Bug#13734)
251
2522013-03-02 Paul Eggert <eggert@cs.ucla.edu>
253
254 * textprop.c: Use bool for booleans.
255 (validate_interval_range, Fadd_text_properties)
256 (Fremove_text_properties): Prefer bool to int when either works.
257
2582013-03-02 Eli Zaretskii <eliz@gnu.org>
259
260 * textprop.c (Fadd_text_properties, Fremove_text_properties): If
261 the interval tree changes as a side effect of calling
262 modify_region, re-do processing starting from the call to
263 validate_interval_range. (Bug#13743)
264
2652013-02-28 Eli Zaretskii <eliz@gnu.org>
266
267 * w32.c (sys_open): Don't reset the flags for FD in fd_info[].
268 (Bug#13546).
269
2702013-02-27 Eli Zaretskii <eliz@gnu.org>
271
272 * filelock.c (create_lock_file) [WINDOWSNT]: Use _sopen with
273 _SH_DENYRW flag, instead of emacs_open, to deny any other process
274 access to the lock file until it is written and closed.
275 (Bug#13807)
276
2772013-02-27 Paul Eggert <eggert@cs.ucla.edu>
278
279 * callint.c (Qcall_interactively):
280 * macros.c (Qexecute_kbd_macro):
281 Now static.
282
2832013-02-26 Bastien Guerry <bzg@gnu.org>
284
285 * window.c (Frecenter): Tiny docstring enhancement.
286
2872013-02-26 Paul Eggert <eggert@cs.ucla.edu>
288
289 Minor textprop integer cleanup.
290 * intervals.h, textprop.c (add_text_properties_from_list):
291 Return void, not int, since nobody uses the return value.
292 * textprop.c (validate_plist, add_properties, remove_properties)
293 (Fadd_text_properties):
294 Don't assume list length fits in int.
295 (interval_has_all_properties, interval_has_some_properties)
296 (interval_has_some_properties_list, add_properties, remove_properties)
297 (Fadd_text_properties, Fremove_text_properties)
298 (Fremove_list_of_text_properties, text_property_stickiness):
299 Use bool for booleans.
300 (Fadd_text_properties, Fremove_text_properties):
301 (Fremove_list_of_text_properties):
302 Reindent do-while as per GNU style.
303
3042013-02-25 Eli Zaretskii <eliz@gnu.org>
305
306 Implement CLASH_DETECTION for MS-Windows.
307
308 * filelock.c [WINDOWSNT]: Include w32.h.
309 (MAKE_LOCK_NAME): Don't use 'lock', it clashes with MS runtime
310 function of that name. Up-case the macro arguments.
311 (IS_LOCK_FILE): New macro.
312 (fill_in_lock_file_name): Use IS_LOCK_FILE instead of S_ISLNK.
313 (create_lock_file): New function, with body extracted from
314 lock_file_1.
315 [WINDOWSNT]: Implement lock files by writing a regular file with
316 the lock information as its contents.
317 (read_lock_data): New function, on Posix platforms just calls
318 emacs_readlinkat.
319 [WINDOWSNT]: Read the lock info from the file.
320 (current_lock_owner): Call read_lock_data instead of calling
321 emacs_readlinkat directly.
322 (lock_file) [WINDOWSNT]: Run the file name through
323 dostounix_filename.
324
325 * w32proc.c (sys_kill): Support the case of SIG = 0, in which case
326 just check if the process by that PID exists.
327
328 * w32.c (sys_open): Don't reset the _O_CREAT flag if _O_EXCL is
329 also present, as doing so will fail to error out if the file
330 already exists.
331
332 * makefile.w32-in ($(BLD)/filelock.$(O)): Depend on src/w32.h.
333
334 * textprop.c (Fadd_text_properties, Fremove_text_properties)
335 (Fremove_list_of_text_properties): Skip all of the intervals in
336 the region between START and END that already have resp. don't
337 have the requested properties, not just the first one. Add
338 assertions that the loop afterwards always modifies the
339 properties. (Bug#13743)
340
3412013-02-25 Stefan Monnier <monnier@iro.umontreal.ca>
342
343 * callint.c (Fcall_interactively): Use the right lexical environment
344 for `interactive' specs (bug#13811).
345 * eval.c (Feval): Accept a lexical environment.
346
3472013-02-25 Paul Eggert <eggert@cs.ucla.edu>
348
349 Simplify data_start configuration (Bug#13783).
350 This is a followon simplification to the fix for Bug#13650.
351 * Makefile.in (LD_FIRSTFLAG, LIB_GCC, CRT_DIR, LIB_STANDARD)
352 (START_FILES): Remove. All uses removed.
353 (otherobj): Remove $(VMLIMIT_OBJ), as it's now first.
354 (ALLOBJS): Move here from autodeps.mk, and with VMLIMITS_OBJ first.
355 (buildobj.h): Use it.
356 ($(ALLOBJS)): Depend on globals.h.
357 (temacs$(EXEEXT)): Use $(ALLOBJS).
358 * autodeps.mk (ALLOBJS): Move to Makefile.in.
359 * deps.mk (vm-limit.o):
360 * makefile.w32-in ($(BLD)/vm-limit.$(O)):
361 Do not depend on mem-limits.h.
362 * emacs.c (__do_global_ctors, __do_global_ctors_aux)
363 (__do_global_dtors, __CTOR_LIST__, __DTOR_LIST__)
364 [__GNUC__ && !ORDINARY_LINK]: Remove.
365 * mem-limits.h, pre-crt0.c: Remove.
366 * unexaix.c, unexcoff.c: Don't include mem-limits.h.
367 * unexcoff.c (etext): New decl.
368 (make_hdr): Use DATA_START instead of start_of_data.
369 * vm-limit.c: Move most of mem-limits.h's contents here.
370 (data_start): New decl. It's OK if this is approximate,
371 so simplify-away some unnecessary exactness.
372 (POINTER): Remove; all uses removed.
373 (data_space_start): Now char *, to avoid casts.
374 (exceeds_lisp_ptr): New function, replacing the old
375 EXCEEDS_LISP_PTR macro. All uses changed.
376 (check_memory_limits): Simplify and remove casts.
377 (start_of_data) [!CANNOT_DUMP || !SYSTEM_MALLOC]: Remove.
378 (memory_warnings): Use data_start instead of start_of_data.
379
3802013-02-24 Andreas Schwab <schwab@linux-m68k.org>
381
382 * xdisp.c (set_message): Only check for debug-on-message if STRING
383 is a string. (Bug#13797)
384
3852013-02-24 Paul Eggert <eggert@cs.ucla.edu>
386
387 Fix regression introduced by July 10 filelock.c patch.
388 * filelock.c (fill_in_lock_file_name): Fix crash caused by the
389 2012-07-10 patch to this file. Reported by Eli Zaretskii in
390 <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00533.html>
391 and diagnosed by Andreas Schwab in
392 <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00534.html>.
393
3942013-02-22 Paul Eggert <eggert@cs.ucla.edu>
395
396 Assume C89 or better.
397 * ralloc.c (SIZE, POINTER, NIL):
398 * vm-limit.c (POINTER):
399 Remove, replacing all uses with C89 equivalents. These old
400 symbols were present only for porting to pre-C89 platforms.
401
4022013-02-22 Claudio Bley <claudio.bley@gmail.com>
403
404 * w32.c (emacs_gnutls_pull): Don't call 'select', and don't loop.
405 This avoids warning messages reported as part of Bug#13546.
406
4072013-02-21 Ken Brown <kbrown@cornell.edu>
408
409 * sheap.c (report_sheap_usage): Fix arguments of message1_no_log.
410
4112013-02-20 Stefan Monnier <monnier@iro.umontreal.ca>
412
413 * sheap.c (report_sheap_usage): Prefer message1_nolog.
414
415 * keyboard.c (Qcommand_execute): New var.
416 (command_loop_1, read_char): Use it.
417 (Fcommand_execute): Remove, replace by an Elisp implementation.
418 (syms_of_keyboard): Adjust accordingly.
419
4202013-02-19 Daniel Colascione <dancol@dancol.org>
421
422 * sheap.c (report_sheap_usage): Use message, not message1, so
423 that we don't try to create a buffer while we're in the middle
424 of dumping Emacs. Explain why.
425
4262013-02-20 Dmitry Antipov <dmantipov@yandex.ru>
427
428 * search.c (find_newline): Return byte position in bytepos.
429 Adjust comment.
430 (find_next_newline_no_quit, find_before_next_newline):
431 Add bytepos argument.
432 * lisp.h (find_newline, find_next_newline_no_quit)
433 (find_before_next_newline): Adjust prototypes.
434 * bidi.c (bidi_find_paragraph_start):
435 * editfns.c (Fconstrain_to_field, Fline_end_position):
436 * indent.c (compute_motion, vmotion):
437 * xdisp.c (back_to_previous_line_start, forward_to_next_line_start):
438 (get_visually_first_element, move_it_vertically_backward):
439 Adjust users and avoid calls to CHAR_TO_BYTE where appropriate.
440
4412013-02-19 Eli Zaretskii <eliz@gnu.org>
442
443 * w32proc.c (new_child): Avoid leaking handles if the subprocess
444 resources were not orderly released.
445
4462013-02-17 Eli Zaretskii <eliz@gnu.org>
447
448 * xdisp.c (x_draw_vertical_border): For a window that is neither
449 the leftmost nor the rightmost, redraw both the left and the right
450 vertical borders. (Bug#13723)
451
4522013-02-17 Stefan Monnier <monnier@iro.umontreal.ca>
453
454 * xml.c (init_libxml2_functions):
455 * sound.c (sound_warning):
456 * sheap.c (report_sheap_usage):
457 * process.c (wait_reading_process_output):
458 * msdos.c (XMenuActivate):
459 * macros.c (Fstart_kbd_macro, Fend_kbd_macro):
460 * keyboard.c (top_level_1):
461 * editfns.c (Fmessage, Fmessage_box):
462 * callint.c (Fcall_interactively):
463 * fns.c (Fyes_or_no_p): Prefer `message1' over `message'.
464
4652013-02-17 Jan Djärv <jan.h.d@swipnet.se>
466
467 * xterm.c (syms_of_xterm): Move scroll-bar-adjust-thumb-portion ...
468 * frame.c (syms_of_frame): ... to here.
469
4702013-02-16 Eli Zaretskii <eliz@gnu.org>
471
472 * w32.c (sys_chown): Remove unused function.
473
474 * w32term.c <input_signal_count>: Declare 'volatile'
475 unconditionally. (Bug#9066)
476
477 * w32.c (set_errno): Reset h_errno and don't set it to any other
478 value. Set errno instead.
479 (check_errno): Reset h_errno.
480 (sys_socket, socket_to_fd, sys_bind, sys_connect)
481 (sys_gethostname, sys_getservbyname, sys_getpeername)
482 (sys_shutdown, sys_setsockopt, sys_listen, sys_getsockname)
483 (sys_accept, sys_recvfrom, sys_sendto, fcntl, sys_read): Don't set
484 h_errno.
485 (sys_gethostbyname): Set h_errno only errors detected.
486
4872013-02-15 Paul Eggert <eggert@cs.ucla.edu>
488
489 * process.c (h_errno) [!HAVE_H_ERRNO]: Remove unused decl.
490
4912013-02-15 Eli Zaretskii <eliz@gnu.org>
492
493 * keyboard.c (read_char): Fix calculation of auto-save time out
494 when auto-save-timeout is less than 4. (Bug#13720)
495
496 * w32proc.c (new_child): Free up to 2 slots of dead processes at a
497 time. Improve diagnostics in DebPrint. (Bug#13546)
498
499 * w32.c (sys_socket, sys_bind, sys_connect, sys_gethostname)
500 (sys_gethostbyname, sys_getservbyname, sys_getpeername)
501 (sys_shutdown, sys_setsockopt, sys_listen, sys_getsockname)
502 (sys_accept, sys_recvfrom, sys_sendto, fcntl): In case of failure,
503 make sure errno is set to an appropriate value. (Bug#13546)
504 (socket_to_fd): Add assertion against indexing fd_info[] with a
505 value that is out of bounds.
506 (sys_accept): If fd is negative, do not set up the child_process
507 structure for reading.
508
5092013-02-15 Dmitry Antipov <dmantipov@yandex.ru>
510
511 * composite.c (fill_gstring_header): Remove useless prototype.
512 Break long line.
513 * lisp.h (message_dolog, compile_pattern): Adjust prototype.
514 * print.c (PRINTDECLARE, print_object):
515 * search.c (compile_pattern, fast_looking_at, search_buffer):
516 (simple_search, boyer_moore, Freplace_match):
517 * xdisp.c (c_string_pos, number_of_chars, message_dolog):
518 (get_overlay_arrow_glyph_row, display_mode_element):
519 (decode_mode_spec_coding, message3):
520 * xfaces.c (face_at_string_position): Use bool for booleans.
521 Adjust comments.
522
5232013-02-15 Paul Eggert <eggert@cs.ucla.edu>
524
525 Fix AIX port (Bug#13650).
526 * lisp.h (XPNTR) [!USE_LSB_TAG && DATA_SEG_BITS]:
527 Fix bug introduced in 2012-07-27 change. DATA_SEG_BITS, if set,
528 was #undeffed earlier, so it cannot be used as a macro here.
529 Use the constant and not the macro.
530
5312013-02-15 Eli Zaretskii <eliz@gnu.org>
532
533 * w32proc.c (new_child): If no vacant slots are found in
534 child_procs[], make another pass looking for slots whose process
535 has exited or died. (Bug#13546)
536
537 * w32.c (sys_pipe): When failing due to file descriptors above
538 MAXDESC, set errno to EMFILE.
539 (_sys_read_ahead): Update cp->status when failing to read serial
540 communications input, so that the status doesn't stay at
541 STATUS_READ_IN_PROGRESS. (Bug#13546)
542
5432013-02-14 Jan Djärv <jan.h.d@swipnet.se>
544
545 * gtkutil.c (tb_size_cb): New function.
546 (xg_create_tool_bar): Connect size-allocate to tb_size_cb (Bug#13512).
547
5482013-02-14 Stefan Monnier <monnier@iro.umontreal.ca>
549
550 * keyboard.c (active_maps): Fcurrent_active_maps expects a position, not
551 an event.
552
5532013-02-13 Stefan Monnier <monnier@iro.umontreal.ca>
554
555 * keyboard.c (syms_of_keyboard): Further tweaks of docstring.
556
5572013-02-13 Dmitry Antipov <dmantipov@yandex.ru>
558
559 * font.c (font_range): Add pos_byte argument. Adjust comment
560 and break long line.
561 * font.h (font_range): Adjust prototype.
562 * composite.c (autocmp_chars): Pass byte position to font_range.
563 Break long line. Remove useless prototype and format comment.
564
5652013-02-13 Glenn Morris <rgm@gnu.org>
566
567 * keyboard.c (input-decode-map, key-translation-map): Doc fixes.
568
5692013-02-13 Paul Eggert <eggert@cs.ucla.edu>
570
571 Improve AIX port some more (Bug#13650).
572 With this, it should be as good as it was in 23.3, though it's
573 still pretty bad: the dumped emacs does not run. See Mark Fleishman in
574 http://lists.gnu.org/archive/html/help-gnu-emacs/2011-04/msg00287.html
575 * unexaix.c (start_of_text): Remove.
576 (_data, _text): Declare as char[], not int, as AIX manual suggests.
577 (bias, lnnoptr, text_scnptr, data_scnptr, load_scnptr)
578 (orig_load_scnptr, orig_data_scnptr):
579 Now off_t, not long, since they are file offsets.
580 (make_hdr): Use _data, not start_of_data ().
581 This is the key part of the fix.
582 (make_hdr, unrelocate_symbols): Use off_t for file offsets.
583 (unrelocate_symbols): Cast pointers to intptr_t, not to ulong.
584
585 * pre-crt0.c (data_start): Initialize to 1.
586 This ports to compilers that optimize the external declaration
587 'int x = 0;' as if it were 'int x;' to shrink the executable.
588
589 Improve AIX port (Bug#13650).
590 This doesn't fix the bug, but it makes progress: Emacs builds now.
591 * unexaix.c: Include inttypes.h, stdarg.h.
592 (report_error, report_error_1): Mark as _Noreturn.
593 (report_error): Don't report the wrong errno.
594 (report_error_1): Now varargs. All callers changed.
595 (make_hdr): Use uintptr_t, not unsigned, when converting pointers
596 to unsigned. Don't use ADDR_CORRECT, as it no longer exists.
597 (write_ptr): Use %p to print address rather than %lx and a cast
598 to unsigned long. Grow buffer a bit, to be safer.
599
6002013-02-13 Eli Zaretskii <eliz@gnu.org>
601
602 * bidi.c (bidi_resolve_neutral): After finding the next
603 non-neutral character, accept NEUTRAL_ON type as well, because
604 directional control characters, such as LRE and RLE, have their
605 type converted to that by bidi_resolve_weak. This avoids aborts
606 when LRE/RLE follows a run of neutrals.
607 (bidi_move_to_visually_next): Assert that return value of
608 bidi_peek_at_next_level is non-negative. Negative values will
609 cause an infloop.
610
6112013-02-13 Paul Eggert <eggert@cs.ucla.edu>
612
613 Minor getenv-related fixes.
614 * callproc.c (Fcall_process_region) [!DOS_NT]:
615 Avoid unnecessary duplicate call to getenv.
616 * callproc.c (init_callproc):
617 * dispnew.c (init_display):
618 * sysdep.c (sys_subshell):
619 Omit unnecessary cast of getenv or egetenv.
620
6212013-02-13 Juanma Barranquero <lekktu@gmail.com>
622
623 * makefile.w32-in ($(BLD)/filelock.$(O), $(BLD)/sysdep.$(O)):
624 Update dependencies.
625
6262013-02-12 Eli Zaretskii <eliz@gnu.org>
627
628 * xdisp.c (redisplay_internal): Don't set w->region_showing to the
629 marker's position.
630 (display_line): Set w->region_showing to the value of
631 it->region_beg_charpos, not to -1. This fixes redisplay
632 optimization when cursor is moved up after M->. (Bug#13623)
633 (Bug#13626)
634 (try_scrolling): Scroll text up more if point is too close to ZV
635 and inside the scroll margin. This makes sure point is moved
636 outside the scroll margin in these cases.
637
638 * window.h (struct window): region_showing can no longer be
639 negative.
640
6412013-02-11 Paul Eggert <eggert@cs.ucla.edu>
642
643 Tune by using memchr and memrchr.
644 * doc.c (Fsnarf_documentation):
645 * fileio.c (Fsubstitute_in_file_name):
646 * search.c (find_newline, scan_newline):
647 * xdisp.c (pos_visible_p, display_count_lines):
648 Use memchr and memrchr rather than scanning byte-by-byte.
649 * search.c (find_newline): Rename from scan_buffer.
650 Omit first arg TARGET, as it's always '\n'. All callers changed.
651
652 Clean up read_key_sequence a tiny bit more.
653 * keyboard.c (read_char_x_menu_prompt) [HAVE_MENUS]:
654 (read_key_sequence): Remove unused locals.
655
6562013-02-11 Stefan Monnier <monnier@iro.umontreal.ca>
657
658 Clean up read_key_sequence a bit; reread active keymaps after first event.
659 * keyboard.c (read_char, read_char_x_menu_prompt)
660 (read_char_minibuf_menu_prompt):
661 Replace nmaps+maps with a single `map' arg.
662 (follow_key): Operate on a single map.
663 (active_maps): New function.
664 (test_undefined): Also return true for nil bindings.
665 (read_key_sequence): Use active_maps to replace the arrays of keymaps with
666 a single (composed) keymap. Remember `first_event' to choose the right
667 set of active keymaps. Recompute the set of keymaps after receiving
668 the first event. Remove GOBBLE_FIRST_EVENT.
669 (syms_of_keyboard): Remove inhibit_local_menu_bar_menus.
670 * keyboard.h (read_char): Update declaration.
671 * lread.c (read_filtered_event): Adjust call to read_char.
672
6732013-02-11 Eli Zaretskii <eliz@gnu.org>
674
675 * xdisp.c (move_it_vertically_backward, move_it_by_lines):
676 Don't use the limitation on backwards movement when lines are truncated
677 in the window. (Bug#13675)
678
6792013-02-11 Dmitry Antipov <dmantipov@yandex.ru>
680
681 * marker.c (set_marker_internal): If desired position is passed
682 as a marker, avoid call to buf_charpos_to_bytepos.
683 * window.c (Fset_window_point): Omit redundant type checking.
684 (Fset_window_start): Likewise. Format comment.
685 (window_scroll_pixel_based): Use set_marker_restricted_both
686 with character and byte positions obtained from an iterator.
687 (Fset_window_configuration): Use set_marker_restricted_both.
688 * xdisp.c (message_dolog): Likewise.
689
6902013-02-10 Eli Zaretskii <eliz@gnu.org>
691
692 * xdisp.c (move_it_vertically_backward, move_it_by_lines):
693 When text lines are longer than window's screen lines, don't move back
694 too far. This speeds up some redisplay operations. (Bug#13675)
695
6962013-02-10 Dmitry Antipov <dmantipov@yandex.ru>
697
698 * syntax.c (scan_sexps_forward): Fix byte position calculation
699 Bug#13664 (a.k.a Bug#13667) introduced with 2013-02-08 change.
700
7012013-02-10 Paul Eggert <eggert@cs.ucla.edu>
702
703 * fileio.c (Fexpand_file_name): Omit confusing pointer comparison
704 that was not needed.
705
7062013-02-09 Paul Eggert <eggert@cs.ucla.edu>
707
708 Minor hashing refactoring.
709 * fns.c (SXHASH_REDUCE): Move to lisp.h.
710 (sxhash_float): Return EMACS_UINT, for consistency with the other
711 hash functions.
712 * lisp.h (INTMASK): Now a macro, since SXHASH_REDUCE is now a
713 non-static inline function and therefore can't use static vars.
714 (SXHASH_REDUCE): Move here from fns.c, and make it inline.
715 * profiler.c (hashfn_profiler): Use SXHASH_REDUCE, to be consistent
716 with the other hash functions.
717
7182013-02-09 Eli Zaretskii <eliz@gnu.org>
719
720 * callproc.c (Fcall_process_region) [WINDOWSNT]: Make sure the
721 XXXXXX part of the temporary file pattern is not downcased even
722 when w32-downcase-file-names is non-nil. (Bug#13661)
723
724 * xdisp.c (decode_mode_spec): Remove handling of %t.
725
726 * msdos.c (careadlinkatcwd): Remove.
727
7282013-02-08 Stefan Monnier <monnier@iro.umontreal.ca>
729
730 * lread.c (skip_dyn_bytes): New function (bug#12598).
731 (read1): Use it. Use getc instead of READCHAR to read bytes.
732 (load_each_byte): Remove. Update users.
733
7342013-02-08 Dmitry Antipov <dmantipov@yandex.ru>
735
736 * search.c (scan_buffer): Calculate end byte position just once.
737 (scan_newline): Do not recalculate start_byte.
738 (search_command): Use eassert.
739 * syntax.c (struct lisp_parse_state): New member location_byte.
740 (scan_sexps_forward): Record from_byte and avoid redundant
741 character to byte position calculation ...
742 (Fparse_partial_sexp): ... here. Break too long line.
743
7442013-02-08 Dmitry Antipov <dmantipov@yandex.ru>
745
746 * lisp.h (make_uninit_vector): New function.
747 * alloc.c (Fvector, Fmake_byte_code):
748 * ccl.c (Fregister_ccl_program):
749 * charset.c (Fdefine_charset_internal, define_charset_internal):
750 * coding.c (make_subsidiaries, Fdefine_coding_system_internal):
751 * composite.c (syms_of_composite):
752 * font.c (Fquery_font, Ffont_info, syms_of_font):
753 * fontset.c (FONT_DEF_NEW, Fset_fontset_font):
754 * ftfont.c (ftfont_shape_by_flt):
755 * indent.c (recompute_width_table):
756 * nsselect.m (clean_local_selection_data):
757 * syntax.c (init_syntax_once):
758 * w32unsubscribe.c (uniscribe_shape):
759 * window.c (Fcurrent_window_configuration):
760 * xfaces.c (Fx_family_fonts):
761 * xselect.c (selection_data_to_lisp_data): Use it.
762
7632013-02-07 Dmitry Antipov <dmantipov@yandex.ru>
764
765 * coding.c (Fdefine_coding_system_internal): Use AREF where
766 argument is known to be a vector.
767 * fns.c (Flocale_info): Likewise for ASET.
768 * xselect.c (selection_data_to_lisp_data): Likewise for ASET.
769 * w32fns.c (w32_parse_hot_key): Likewise for ASIZE and AREF.
770
7712013-02-05 Jan Djärv <jan.h.d@swipnet.se>
772
773 * nsmenu.m (update_frame_tool_bar): Check for negative tool bar
774 height.
775
776 * nsterm.h (HAVE_NATIVE_FS): Define if OSX => 10.7.
777 (EmacsView): Add fs_is_native, fsIsNative, isFullscreen and
778 updateCollectionBehaviour.
779
780 * nsterm.m (NEW_STYLE_FS): Remove.
781 (ns_last_use_native_fullscreen): New variable.
782 (x_make_frame_visible): Replace NEW_STYLE_FS with isFullscreen.
783 (x_set_window_size): Do not take title bar and tool bar into account
784 if isFullscreen returns YES.
785 (ns_fullscreen_hook): Replace NEW_STYLE_FS with isFullscreen.
786 (check_native_fs): New function.
787 (ns_select, ns_read_socket): Call check_native_fs if HAVE_NATIVE_FS.
788 (ns_term_init): Remove NEW_STYLE_FS.
789 (updateFrameSize:, windowWillResize:toSize:): Only adjust for title bar
790 and tool bar if isFullscreen returns NO.
791 (windowDidResize:): Replace NEW_STYLE_FS with fsIsNative.
792 (initFrameFromEmacs:): Initialize fs_is_native. Replace NEW_STYLE_FS
793 with HAVE_NATIVE_FS.
794 (window:willUseFullScreenPresentationOptions:): New method.
795 (windowDidEnterFullScreen:): Replace NEW_STYLE_FS with fsIsNative.
796 Hide toolbar if not enabled (Bug#13444).
797 (windowDidExitFullScreen:): Call updateCollectionBehaviour.
798 Restore tool bar if enabled, hide it otherwise (Bug#13444).
799 (fsIsNative, isFullscreen, updateCollectionBehaviour): New methods.
800 (toggleFullScreen:): If fs_is_native, call toggleFullScreen on
801 window. Do no set FRAME_EXTERNAL_TOOL_BAR (f) to 0.
802 Check FRAME_EXTERNAL_TOOL_BAR (f) before restoring
803 FRAME_TOOLBAR_HEIGHT (f). Call updateFrameSize when going non-fs.
804 (syms_of_nsterm): Add ns-use-native-fullscreen.
805
8062013-02-04 Paul Eggert <eggert@cs.ucla.edu>
807
808 * fileio.c (Qchoose_write_coding_system): Now static.
809
8102013-02-04 Eli Zaretskii <eliz@gnu.org>
811
812 * xdisp.c (window_buffer_changed): region_showing can be negative,
813 which still means region is being displayed.
814 (redisplay_internal): Resurrect code that forced redisplay of the
815 whole window when showing region and the mark has changed.
816 Record the new mark position to allow redisplay optimizations.
817 (display_line): If it->region_beg_charpos is non-zero, set the
818 window's region_showing member to -1. (Bug#13623) (Bug#13626)
819
820 * window.h (struct window) <region_showing>: Declare ptrdiff_t,
821 not bitfield of 1 bit.
822
8232013-02-03 Daniel Colascione <dancol@dancol.org>
824
825 * emacs.c: Use execvp, not execv, when DAEMON_MUST_EXEC, so that
826 daemon mode works on cygw32 when Emacs is installed and not just
827 during development.
828
8292013-02-02 Paul Eggert <eggert@cs.ucla.edu>
830
831 Avoid file time stamp bug on MS-Windows (Bug#13149).
832 * fileio.c (Fwrite_region): Don't use the heuristic on empty files,
833 as FAT32 doesn't update time stamps when truncating them.
834 Also, check that a file time stamp is not a multiple of 100 ns;
835 this should catch all instances of the problem on MS-Windows,
836 as its native file system resolution is 100 ns or worse, and
837 checking for a non-multiple of 100 ns should impose only a small
838 overhead on systems with ns resolution.
839
8402013-02-02 Eli Zaretskii <eliz@gnu.org>
841
842 Avoid encoding file names on MS-Windows when they need to be run
843 through dostounix_filename.
844 * w32.c (normalize_filename): Accept an additional argument
845 MULTIBYTE; if non-zero, traverse the file name by bytes and don't
846 downcase it even if w32-downcase-file-names is non-nil.
847 (dostounix_filename): Accept an additional argument MULTIBYTE and
848 pass it to normalize_filename.
849 (emacs_root_dir): Adjust.
850
851 * msdos.h (dostounix_filename): Adjust prototype.
852
853 * w32.h (dostounix_filename): Adjust prototype.
854
855 * msdos.c (dostounix_filename): Accept an additional argument and
856 ignore it.
857 (init_environment): Adjust callers of dostounix_filename.
858
859 * fileio.c (Ffile_name_directory, file_name_as_directory)
860 (directory_file_name, Fexpand_file_name)
861 (Fsubstitute_in_file_name): [DOS_NT] Adjust call to
862 dostounix_filename.
863 [WINDOWSNT]: Downcase file names if w32-downcase-file-names is
864 non-nil.
865 (Fsubstitute_in_file_name): [DOS_NT] Don't downcase environment
866 variables, as egetenv is case-insensitive for DOS_NT.
867
868 * dired.c (file_name_completion): Don't call Fdirectory_file_name
869 with an encoded file name.
870
871 * w32proc.c (Fw32_short_file_name, Fw32_long_file_name):
872 Adjust calls to dostounix_filename.
873
874 * w32fns.c (Fx_file_dialog): Adjust call to dostounix_filename.
875
876 * unexw32.c (unexec): Adjust call to dostounix_filename.
877
878 * termcap.c (tgetent) [MSDOS]: Adjust call to dostounix_filename.
879
880 * emacs.c (decode_env_path) [DOS_NT]: Adjust call to
881 dostounix_filename.
882
883 * callproc.c (Fcall_process) [MSDOS]: Adjust call to
884 dostounix_filename.
885
886 * callproc.c (Fcall_process): Make sure program name in PATH and
887 new_argv[0] is encoded, if needed. Otherwise, un-encoded string
888 is passed to exec/spawnve, which fails unless the file-name
889 encoding is UTF-8.
890
891 * w32proc.c (sys_spawnve): Make sure escape_char is initialized,
892 even if w32-quote-process-args is nil.
893
8942013-02-01 Paul Eggert <eggert@cs.ucla.edu>
895
896 Fix timestamp bug when write-region appends nothing (Bug#13149).
897 * fileio.c (Fwrite_region): When neither O_EXCL nor O_TRUNC is used,
898 the file's time stamp doesn't change if Emacs happens to write nothing
899 to the file, and on a buggy file system this could cause Emacs to
900 incorrectly infer that the file system doesn't have the bug.
901 Avoid this problem by inhibiting the inference in this case.
902
9032013-02-01 Dmitry Antipov <dmantipov@yandex.ru>
904
905 * window.h (struct window): Convert base_line_number, base_line_pos
906 and column_number_displayed members from Lisp_Object to ptrdiff_t.
907 Convert region_showing member from Lisp_Object to bitfield.
908 Remove sequence_number member. Adjust comments.
909 * window.c (sequence_number): Remove.
910 (make_window): Initialize column_number_displayed.
911 * print.c (print_object): Follow the printed representation of
912 frames and print window pointer to distinguish between windows.
913 (adjust_window_count): Invalidate base_line_pos. Adjust comment.
914 * xdisp.c (wset_base_line_number, wset_base_line_pos)
915 (wset_column_number_displayed, wset_region_showing): Remove.
916 (window_buffer_changed, mode_line_update_needed, redisplay_internal)
917 (try_scrolling, try_cursor_movement, redisplay_window)
918 (try_window_reusing_current_matrix, try_window_id, display_line)
919 (display_mode_lines, decode_mode_spec): Adjust users.
920 * .gdbinit (pwinx): Do not print sequence_number.
921
9222013-02-01 Paul Eggert <eggert@cs.ucla.edu>
923
924 Use fdopendir, fstatat and readlinkat, for efficiency (Bug#13539).
925 * conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): Remove.
926 * dired.c: Include <fcntl.h>.
927 (open_directory): New function, which uses open and fdopendir
928 rather than opendir. DOS_NT platforms still use opendir, though.
929 (directory_files_internal, file_name_completion): Use it.
930 (file_attributes): New function, with most of the old Ffile_attributes.
931 (directory_files_internal, Ffile_attributes): Use it.
932 (file_attributes, file_name_completion_stat): First arg is now fd,
933 not dir name. All uses changed. Use fstatat rather than lstat +
934 stat.
935 (file_attributes): Use emacs_readlinkat rather than Ffile_symlink_p.
936 * fileio.c: Include <allocator.h>, <careadlinkat.h>.
937 (emacs_readlinkat): New function, with much of the old
938 Ffile_symlink_p, but with an fd argument for speed.
939 It uses readlinkat rather than careadlinkatcwd, so that it
940 need not assume the working directory.
941 (Ffile_symlink_p): Use it.
942 * filelock.c (current_lock_owner): Use emacs_readlinkat
943 rather than emacs_readlink.
944 * lisp.h (emacs_readlinkat): New decl.
945 (READLINK_BUFSIZE, emacs_readlink): Remove.
946 * sysdep.c: Do not include <allocator.h>, <careadlinkat.h>.
947 (emacs_norealloc_allocator, emacs_readlink): Remove.
948 This stuff is moved to fileio.c.
949 * w32.c (fstatat, readlinkat): New functions.
950 (careadlinkat): Don't check that fd == AT_FDCWD.
951 (careadlinkatcwd): Remove; no longer needed.
952
9532013-01-31 Glenn Morris <rgm@gnu.org>
954
955 * fileio.c (choose_write_coding_system): Make it callable from Lisp.
956 (Fwrite_region): Update for new choose_write_coding_system args.
957 Move the last piece of choose_write_coding_system here. (Bug#13522)
958 (syms_of_fileio): Add choose-write-coding-system.
959
9602013-01-30 Eli Zaretskii <eliz@gnu.org>
961
962 * w32.c (sys_open): Zero out the flags for the new file descriptor.
963 (sys_close): Zero out the flags for the file descriptor before
964 closing it. (Bug#13546)
965
966 * w32.c (parse_root, get_volume_info, readdir, read_unc_volume)
967 (logon_network_drive, stat_worker, symlink, chase_symlinks):
968 Use CharNextExA and CharPrevExA to iterate over file names encoded in
969 DBCS. (Bug#13553)
970
971 * w32.c (w32_get_long_filename, init_environment, readlink):
972 Support file names encoded in DBCS codepages.
973 (readlink): Use the current file-name-coding-system, not the ANSI
974 codepage, to decode and handle targets of symlinks.
975
9762013-01-28 Eli Zaretskii <eliz@gnu.org>
977
978 * w32.c (opendir): Now accepts a 'const char *'.
979
9802013-01-28 Dmitry Antipov <dmantipov@yandex.ru>
981
982 Remove obsolete redisplay code. See the discussion at
983 http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00576.html.
984 * dispnew.c (preemption_period, preemption_next_check): Remove.
985 (Vredisplay_preemption_period): Likewise.
986 (update_frame, update_single_window, update_window, update_frame_1):
987 Adjust users. Always assume that PERIODIC_PREEMPTION_CHECKING is not
988 used, following the 2012-06-22 change.
989
9902013-01-25 Eli Zaretskii <eliz@gnu.org>
991
992 * w32notify.c (Fw32notify_add_watch): Doc fix. (Bug#13540)
993
9942013-01-25 Dmitry Antipov <dmantipov@yandex.ru>
995
996 * font.c (num_fonts): Remove the leftover from old
997 debugging code. Adjust comment style here and there.
998 * insdel.c (insert_1): Remove.
999 * lisp.h (insert_1): Remove prototype.
1000 * xdisp.c (message_dolog): Adjust users to call insert_1_both.
1001
10022013-01-25 Eli Zaretskii <eliz@gnu.org>
1003
1004 * w32.c (max_filename_mbslen): New function.
1005 (normalize_filename, readdir): Use it to detect locales where ANSI
1006 encoding of file names uses a double-byte character set (DBCS).
1007 If a DBCS encoding is used, advance by characters using
1008 CharNextExA, instead of incrementing a 'char *' pointer.
1009 Use _mbslwr instead of _strlwr. (Bug#13515)
1010
1011 * w32heap.c (allocate_heap) [!_WIN64]: Decrease the initial
1012 request of memory reservation to 1.7GB. (Bug#13065)
1013
10142013-01-25 Andreas Schwab <schwab@linux-m68k.org>
1015
1016 * coding.c (detect_coding_iso_2022): Move back mis-reordered code
1017 at check_extra_latin label. (Bug#13505)
1018
10192013-01-24 Dmitry Antipov <dmantipov@yandex.ru>
1020
1021 * nsfont.m (ns_escape_name, ns_unescape_name, ns_registry_to_script):
1022 Avoid redundant calls to strlen.
1023
10242013-01-24 Dmitry Antipov <dmantipov@yandex.ru>
1025
1026 Drop async_visible and async_iconified fields of struct frame.
1027 This is possible because async input is gone; for details, see
1028 http://lists.gnu.org/archive/html/emacs-devel/2012-12/msg00734.html.
1029 * frame.h (struct frame): Remove async_visible and async_iconified
1030 members, convert garbaged to unsigned bitfield. Adjust comments.
1031 (FRAME_SAMPLE_VISIBILITY): Remove. Adjust all users.
1032 (SET_FRAME_VISIBLE, SET_FRAME_ICONIFIED): New macros.
1033 * frame.c, gtkutil.c, term.c, w32fns.c, window.c, xdisp.c:
1034 Consistently use SET_FRAME_VISIBLE, SET_FRAME_ICONIFIED,
1035 FRAME_VISIBLE_P and FRAME_ICONIFIED_P macros where appropriate.
1036 * w32term.c: Ditto.
1037 (w32_read_socket): Save iconified state to generate DEICONIFY_EVENT
1038 properly. Likewise for obscured.
1039 * xterm.c: Ditto.
1040 (handle_one_xevent): Save visible state to generate ICONIFY_EVENT
1041 properly.
1042 * nsterm.m: Ditto.
1043 (windowDidDeminiaturize): Generate DEICONIFY_EVENT.
1044
10452013-01-24 Dmitry Antipov <dmantipov@yandex.ru>
1046
1047 * insdel.c (prepare_to_modify_buffer): Revert last change as suggested
1048 in http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00555.html.
1049
10502013-01-23 Stefan Monnier <monnier@iro.umontreal.ca>
1051
1052 * xdisp.c (message2, message2_nolog): Remove functions.
1053 (message3, message3_nolog): Extract nbytes and multibyteness directly
1054 from the string. Change all callers.
1055 (message3_nolog): Don't set message_enable_multibyte since set_message
1056 will reset it anyway.
1057 (message1, message1_nolog): Use message3.
1058 (vmessage): Use a stack allocated buffer rather than f->message_buf.
1059 (with_echo_area_buffer): Remove last two arguments. Update all callers.
1060 (set_message): Drop all but the second arg, which has to be a string.
1061 (set_message_1): Simplify now that we know that a1 is NULL and the
1062 second arg is a string.
1063 * frame.h (struct frame): Remove `message_buf' field.
1064 Use glyphs_initialized_p instead.
1065 (FRAME_MESSAGE_BUF): Remove macro.
1066 * w16select.c (Fw16_set_clipboard_data): Prefer message3 to message2.
1067 * lisp.h (message2, message2_nolog): Remove declarations.
1068 (message3, message3_nolog): Update declarations.
1069 * keyboard.c (read_char_minibuf_menu_text)
1070 (read_char_minibuf_menu_width): Remove vars.
1071 (read_char_minibuf_menu_prompt): Rewrite the menu's construction so as
1072 to correctly handle multibyte strings.
1073 * frame.c (delete_frame): Don't free message_buf any more.
1074 * editfns.c (message_text, message_length): Remove vars.
1075 (Fmessage_box): Don't copy the Lisp string's bytes any longer.
1076 * fileio.c (auto_save_error): Use message3 instead of message2.
1077 * dispnew.c (adjust_frame_message_buffer): Remove function.
1078
10792013-01-23 Eli Zaretskii <eliz@gnu.org>
1080
1081 * w32term.c (w32fullscreen_hook): Account correctly for the screen
1082 real estate used for the tool bar and the menu bar.
1083
10842013-01-23 Dmitry Antipov <dmantipov@yandex.ru>
1085
1086 * insdel.c (prepare_to_modify_buffer): Force redisplay if
1087 hidden buffer is prepared to modification (Bug#13164).
1088
10892013-01-22 Dmitry Antipov <dmantipov@yandex.ru>
1090
1091 * window.h (struct window): Change window_end_valid member from
1092 Lisp_Object to a bitfield. Adjust comments.
1093 (wset_window_end_valid): Remove.
1094 * window.c (adjust_window_count): Clear window_end_valid.
1095 (Fwindow_end): Adjust user. Remove ancient #if 0 code.
1096 (Fwindow_line_height, set_window_buffer, Frecenter)
1097 (Fsplit_window_internal, Fdelete_other_windows_internal)
1098 (Fset_window_fringes, Fset_window_scroll_bars): Adjust users.
1099 * dispnew.c (adjust_glyph_matrix, clear_window_matrices): Likewise.
1100 * xdisp.c (check_window_end, reconsider_clip_changes)
1101 (redisplay_internal, mark_window_display_accurate_1, redisplay_window)
1102 (try_window, try_window_reusing_current_matrix, note_mouse_highlight)
1103 (find_first_unchanged_at_end_row, try_window_id): Likewise.
1104
11052013-01-22 Dmitry Antipov <dmantipov@yandex.ru>
1106
1107 * xdisp.c (mark_window_display_accurate): Simplify the loop
1108 assuming that the only one of vchild, hchild or buffer window
1109 slots is non-nil. Call mark_window_display_accurate_1 for
1110 the leaf windows only.
1111 (mark_window_display_accurate_1): Always assume leaf window.
1112 Adjust comment.
1113
11142013-01-22 Paul Eggert <eggert@cs.ucla.edu>
1115
1116 * emacs.c (Qkill_emacs_hook): Now static.
1117
1118 * fileio.c (Finsert_file_contents): Simplify.
1119 Remove unnecessary assignments and tests.
1120
11212013-01-21 Eli Zaretskii <eliz@gnu.org>
1122
1123 * w32.c (acl_set_file): Don't test for errors unless
1124 set_file_security returns FALSE. Avoids spurious errors when
1125 saving files.
1126
11272013-01-21 Dmitry Antipov <dmantipov@yandex.ru>
1128
1129 * fileio.c (Finsert_file_contents): Revert code introduced at
1130 2013-01-18 in favor of the simpler and generally better fix.
1131 Save stack space by removing 'buffer' and reusing 'read_buf'
1132 where appropriate.
1133
11342013-01-19 Paul Eggert <eggert@cs.ucla.edu>
1135
1136 * lisp.h (eabs): Define unconditionally (Bug#13419).
1137 The old "#if !defined (eabs)" was an unnecessary revenant of back
1138 when this macro was called "abs". Document 'eabs' better.
1139
11402013-01-19 Glenn Morris <rgm@gnu.org>
1141
1142 * fns.c (Frandom): Doc fix.
1143
11442013-01-19 Eli Zaretskii <eliz@gnu.org>
1145
1146 * editfns.c (get_pos_property): Use SAFE_ALLOCA_LISP, to avoid
1147 segfault when there are lots of overlays.
1148
1149 * buffer.c (sort_overlays): Use SAFE_NALLOCA, to avoid segfault
1150 when there are lots of overlays.
1151 See http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00421.html
1152 for the details and a way to reproduce.
1153
11542013-01-19 Paul Eggert <eggert@cs.ucla.edu>
1155
1156 * fileio.c: Use O_APPEND to append.
1157 This corresponds better to the natural interpretation of "append",
1158 and avoids the need to open the output file twice, or to invoke
1159 lseek when APPEND is neither nil nor a number.
1160 This relies on POSIX 1003.1-1988 or later, which is OK nowadays.
1161 (Fwrite_region): Simplify. Use O_APPEND instead of opening the
1162 file possibly twice, and lseeking to its end; this avoids the
1163 need to lseek on non-regular files. Do not use O_EXCL and O_TRUNC
1164 at the same time: the combination is never needed and apparently
1165 it doesn't work with DOS_NT.
1166
1167 Fix size bug on DOS_NT introduced by CIFS workaround (Bug#13149).
1168 * fileio.c (Fwrite_region): Use O_BINARY in checking code, too.
1169
1170 Allow floating-point file offsets.
1171 Problem reported by Vitalie Spinu in
1172 <http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00411.html>.
1173 * fileio.c (emacs_lseek): Remove.
1174 (file_offset): New function.
1175 (Finsert_file_contents, Fwrite_region): Use it.
1176
11772013-01-19 Chong Yidong <cyd@gnu.org>
1178
1179 * emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid
1180 aborting on Fsignal (Bug#13289).
1181
11822013-01-19 Eli Zaretskii <eliz@gnu.org>
1183
1184 * w32.c (acl_set_file): Treat ERROR_ACCESS_DENIED from
1185 set_file_security as failure due to insufficient privileges.
1186 Reported by Fabrice Popineau <fabrice.popineau@supelec.fr>.
1187 (fstat): Return owner and group like 'stat' and 'lstat' do.
1188
11892013-01-19 Paul Eggert <eggert@cs.ucla.edu>
1190
1191 Work around bug in CIFS and vboxsf file systems (Bug#13149).
1192 The bug was observed on Ubuntu operating inside a virtual machine,
1193 editing files mounted via CIFS or vboxsf from the MS Windows 7 host.
1194 The workaround introduces a race condition on non-buggy hosts,
1195 but it's an unlikely race and anyway there's a nearly identical
1196 nearby race that can't be fixed.
1197 * fileio.c (valid_timestamp_file_system, timestamp_file_system):
1198 New static vars.
1199 (Fwrite_region): Test for file system time stamp bug.
1200 (init_fileio): New function.
1201 * lisp.h (init_fileio): Declare it.
1202 * emacs.c (main): Call it.
1203
1204 * fileio.c (Finsert_file_contents): Simplify new diagnostic
1205 and make it more consistent with other stat-failure diagnostics.
1206
12072013-01-18 Dmitry Antipov <dmantipov@yandex.ru>
1208
1209 Fix crash when inserting data from non-regular files.
1210 See http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00406.html
1211 for the error description produced by valgrind.
1212 * fileio.c (read_non_regular): Rename to read_contents.
1213 Free Lisp_Save_Value object used to pass parameters.
1214 (read_non_regular_quit): Rename to read_contents_quit.
1215 (Finsert_file_contents): Redesign internal file reading loop to adjust
1216 gap and end positions after each read and so help make_gap to work
1217 properly. Do not signal an I/O error too early and so do not leave
1218 not yet decoded characters in a buffer, which was the reason of
1219 redisplay crash. Use list2 to build return value. Adjust comments.
1220
12212013-01-17 Paul Eggert <eggert@cs.ucla.edu>
1222
1223 Close a race when statting and reading files (Bug#13149).
1224 * fileio.c (Finsert_file_contents): Use open+fstat, not stat+open.
1225 This avoids a race if the file is renamed between stat and open.
1226 This race is not the problem originally noted in Bug#13149;
1227 see <http://bugs.gnu.org/13149#73> and later messages in the thread.
1228
12292013-01-17 Dmitry Antipov <dmantipov@yandex.ru>
1230
1231 * lisp.h (toplevel): Add comment about using Lisp_Save_Value
1232 objects, related functions and macros.
1233 (make_save_value): Adjust prototype.
1234 (make_save_pointer): New prototype.
1235 (SAFE_NALLOCA): Fix indentation. Use make_save_pointer.
1236 (SAFE_ALLOCA_LISP): Adjust make_save_value usage.
1237 * alloc.c (format_save_value): Rename to make_save_value.
1238 (make_save_pointer): New function.
1239 (record_xmalloc): Use make_save_pointer.
1240 * dired.c, editfns.c, fileio.c, font.c, gtkutil.c, lread.c:
1241 * nsmenu.m, nsterm.m, xfns.c, xmenu.c, xselect.c, keymap.c:
1242 Change users of make_save_value to make_save_pointer.
1243 Likewise for format_save_value and make_save_value.
1244
12452013-01-17 Dmitry Antipov <dmantipov@yandex.ru>
1246
1247 * buffer.h (NARROWED, BUF_NARROWED): Drop unused macros.
1248 (DECODE_POSITION, BUFFER_CHECK_INDIRECTION): Fix indentation.
1249 * buffer.c (toplevel, syms_of_buffer): Drop old commented-out
1250 debugging stubs.
1251
12013-01-15 Paul Eggert <eggert@cs.ucla.edu> 12522013-01-15 Paul Eggert <eggert@cs.ucla.edu>
2 1253
3 * alloc.c (free_save_value): Now static. 1254 * alloc.c (free_save_value): Now static.
@@ -8,8 +1259,8 @@
8 (map_keymap_char_table_item): Adjust accordingly. 1259 (map_keymap_char_table_item): Adjust accordingly.
9 * fileio.c (non_regular_fd, non_regular_inserted) 1260 * fileio.c (non_regular_fd, non_regular_inserted)
10 (non_regular_nbytes): Remove. 1261 (non_regular_nbytes): Remove.
11 (Finsert_file_contents): Convert trytry to ptrdiff_t. Use 1262 (Finsert_file_contents): Convert trytry to ptrdiff_t.
12 format_save_value to pass parameters to read_non_regular. 1263 Use format_save_value to pass parameters to read_non_regular.
13 (read_non_regular): Use XSAVE_ macros to extract parameters. 1264 (read_non_regular): Use XSAVE_ macros to extract parameters.
14 Adjust comment. 1265 Adjust comment.
15 * xmenu.c (xmenu_show) [!USE_X_TOOLKIT && !USE_GTK]: Use 1266 * xmenu.c (xmenu_show) [!USE_X_TOOLKIT && !USE_GTK]: Use
@@ -136,8 +1387,8 @@
136 1387
1372013-01-11 Aaron S. Hawley <Aaron.Hawley@vtinfo.com> 13882013-01-11 Aaron S. Hawley <Aaron.Hawley@vtinfo.com>
138 1389
139 * insdel.c (Fcombine_after_change_execute, syms_of_insdel): Fix 1390 * insdel.c (Fcombine_after_change_execute, syms_of_insdel):
140 ambiguous doc string cross-reference(s). 1391 Fix ambiguous doc string cross-reference(s).
141 1392
142 * keyboard.c (Fcommand_execute, syms_of_keyboard): Fix ambiguous 1393 * keyboard.c (Fcommand_execute, syms_of_keyboard): Fix ambiguous
143 doc string cross-reference(s). 1394 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 @@
19171 * coding.c (code_convert_region_unwind): 19171 * coding.c (code_convert_region_unwind):
19172 Set Vlast_coding_system_used to the argument. 19172 Set Vlast_coding_system_used to the argument.
19173 (code_convert_region): If post-read-conversion function changed 19173 (code_convert_region): If post-read-conversion function changed
19174 the value of last-coding-sytem, keep the new value in 19174 the value of last-coding-system, keep the new value in
19175 coding->symbol so that it won't be overridden. 19175 coding->symbol so that it won't be overridden.
19176 (run_pre_post_conversion_on_str): Likewise. 19176 (run_pre_post_conversion_on_str): Likewise.
19177 (coding_system_accept_latin_extra_p): New function. 19177 (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@
36CFLAGS = @CFLAGS@ 36CFLAGS = @CFLAGS@
37CPPFLAGS = @CPPFLAGS@ 37CPPFLAGS = @CPPFLAGS@
38LDFLAGS = @LDFLAGS@ 38LDFLAGS = @LDFLAGS@
39LD_FIRSTFLAG=@LD_FIRSTFLAG@
40EXEEXT = @EXEEXT@ 39EXEEXT = @EXEEXT@
41version = @version@ 40version = @version@
42# Substitute an assignment for the MAKE variable, because 41# Substitute an assignment for the MAKE variable, because
@@ -102,10 +101,8 @@ LD_SWITCH_X_SITE_RPATH=@LD_SWITCH_X_SITE_RPATH@
102## System-specific LDFLAGS. 101## System-specific LDFLAGS.
103LD_SWITCH_SYSTEM=@LD_SWITCH_SYSTEM@ 102LD_SWITCH_SYSTEM=@LD_SWITCH_SYSTEM@
104 103
105## This holds any special options for linking temacs only (ie, not 104## This holds any special options for linking temacs only (i.e., not
106## used by configure). Not used elsewhere because it sometimes 105## used by configure).
107## contains options that have to do with using Emacs's crt0,
108## which are only good with temacs.
109LD_SWITCH_SYSTEM_TEMACS=@LD_SWITCH_SYSTEM_TEMACS@ 106LD_SWITCH_SYSTEM_TEMACS=@LD_SWITCH_SYSTEM_TEMACS@
110 107
111## Flags to pass to ld only for temacs. 108## Flags to pass to ld only for temacs.
@@ -120,14 +117,6 @@ PAXCTL = @PAXCTL@
120## Some systems define this to request special libraries. 117## Some systems define this to request special libraries.
121LIBS_SYSTEM=@LIBS_SYSTEM@ 118LIBS_SYSTEM=@LIBS_SYSTEM@
122 119
123## Where to find libgcc.a, if using gcc and necessary.
124LIB_GCC=@LIB_GCC@
125
126CRT_DIR=@CRT_DIR@
127## May use $CRT_DIR.
128LIB_STANDARD=@LIB_STANDARD@
129START_FILES = @START_FILES@
130
131## -lm, or empty. 120## -lm, or empty.
132LIB_MATH=@LIB_MATH@ 121LIB_MATH=@LIB_MATH@
133 122
@@ -390,17 +379,16 @@ POST_ALLOC_OBJ=@POST_ALLOC_OBJ@
390 379
391## List of object files that make-docfile should not be told about. 380## List of object files that make-docfile should not be told about.
392otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \ 381otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
393 $(POST_ALLOC_OBJ) $(VMLIMIT_OBJ) $(WIDGET_OBJ) $(LIBOBJS) 382 $(POST_ALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS)
394 383
384## All object files linked into temacs. $(VMLIMIT_OBJ) should be first.
385ALLOBJS = $(VMLIMIT_OBJ) $(obj) $(otherobj)
395 386
396## Configure inserts the file lisp.mk at this point, defining $lisp. 387## Configure inserts the file lisp.mk at this point, defining $lisp.
397@lisp_frag@ 388@lisp_frag@
398 389
399 390
400## Construct full set of libraries to be linked. 391## Construct full set of libraries to be linked.
401## Note that SunOS needs -lm to come before -lc; otherwise, you get
402## duplicated symbols. If the standard libraries were compiled
403## with GCC, we might need LIB_GCC again after them.
404LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ 392LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
405 $(LIBX_OTHER) $(LIBSOUND) \ 393 $(LIBX_OTHER) $(LIBSOUND) \
406 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \ 394 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \
@@ -410,7 +398,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
410 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 398 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
411 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 399 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
412 $(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \ 400 $(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
413 $(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC) 401 $(LIB_MATH)
414 402
415all: emacs$(EXEEXT) $(OTHER_FILES) 403all: emacs$(EXEEXT) $(OTHER_FILES)
416.PHONY: all 404.PHONY: all
@@ -457,7 +445,7 @@ $(libsrc)/make-docfile$(EXEEXT):
457 cd $(libsrc); $(MAKE) $(MFLAGS) make-docfile$(EXEEXT) 445 cd $(libsrc); $(MAKE) $(MFLAGS) make-docfile$(EXEEXT)
458 446
459buildobj.h: Makefile 447buildobj.h: Makefile
460 echo "#define BUILDOBJ \"$(obj) $(otherobj) " "\"" > buildobj.h 448 echo "#define BUILDOBJ \"$(ALLOBJS) " "\"" >$@
461 449
462globals.h: gl-stamp; @true 450globals.h: gl-stamp; @true
463 451
@@ -469,15 +457,15 @@ gl-stamp: $(libsrc)/make-docfile$(EXEEXT) $(GLOBAL_SOURCES)
469 $(srcdir)/../build-aux/move-if-change gl-tmp globals.h 457 $(srcdir)/../build-aux/move-if-change gl-tmp globals.h
470 echo timestamp > $@ 458 echo timestamp > $@
471 459
472$(obj) $(otherobj): globals.h 460$(ALLOBJS): globals.h
473 461
474$(lib)/libgnu.a: $(config_h) 462$(lib)/libgnu.a: $(config_h)
475 cd $(lib) && $(MAKE) libgnu.a 463 cd $(lib) && $(MAKE) libgnu.a
476 464
477temacs$(EXEEXT): $(START_FILES) stamp-oldxmenu $(obj) $(otherobj) \ 465temacs$(EXEEXT): stamp-oldxmenu $(ALLOBJS) \
478 $(lib)/libgnu.a $(W32_RES) 466 $(lib)/libgnu.a $(W32_RES)
479 $(CC) $(LD_FIRSTFLAG) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \ 467 $(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \
480 -o temacs $(START_FILES) $(obj) $(otherobj) $(lib)/libgnu.a $(LIBES) \ 468 -o temacs $(ALLOBJS) $(lib)/libgnu.a $(LIBES) \
481 $(W32_RES_LINK) 469 $(W32_RES_LINK)
482 test "$(CANNOT_DUMP)" = "yes" || \ 470 test "$(CANNOT_DUMP)" = "yes" || \
483 test "X$(PAXCTL)" = X || $(PAXCTL) -r temacs$(EXEEXT) 471 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/>. */
26#include <limits.h> /* For CHAR_BIT. */ 26#include <limits.h> /* For CHAR_BIT. */
27 27
28#ifdef ENABLE_CHECKING 28#ifdef ENABLE_CHECKING
29#include <signal.h> /* For SIGABRT. */ 29#include <signal.h> /* For SIGABRT. */
30#endif 30#endif
31 31
32#ifdef HAVE_PTHREAD 32#ifdef HAVE_PTHREAD
@@ -836,7 +836,7 @@ void *
836record_xmalloc (size_t size) 836record_xmalloc (size_t size)
837{ 837{
838 void *p = xmalloc (size); 838 void *p = xmalloc (size);
839 record_unwind_protect (safe_alloca_unwind, make_save_value (p, 0)); 839 record_unwind_protect (safe_alloca_unwind, make_save_pointer (p));
840 return p; 840 return p;
841} 841}
842 842
@@ -1675,7 +1675,7 @@ allocate_string_data (struct Lisp_String *s,
1675 b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); 1675 b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP);
1676 1676
1677#ifdef DOUG_LEA_MALLOC 1677#ifdef DOUG_LEA_MALLOC
1678 /* Back to a reasonable maximum of mmap'ed areas. */ 1678 /* Back to a reasonable maximum of mmap'ed areas. */
1679 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); 1679 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
1680#endif 1680#endif
1681 1681
@@ -1892,7 +1892,7 @@ compact_small_strings (void)
1892 1892
1893#ifdef GC_CHECK_STRING_BYTES 1893#ifdef GC_CHECK_STRING_BYTES
1894 /* Check that the string size recorded in the string is the 1894 /* Check that the string size recorded in the string is the
1895 same as the one recorded in the sdata structure. */ 1895 same as the one recorded in the sdata structure. */
1896 if (s && string_bytes (s) != SDATA_NBYTES (from)) 1896 if (s && string_bytes (s) != SDATA_NBYTES (from))
1897 emacs_abort (); 1897 emacs_abort ();
1898#endif /* GC_CHECK_STRING_BYTES */ 1898#endif /* GC_CHECK_STRING_BYTES */
@@ -3103,13 +3103,10 @@ Any number of arguments, even zero arguments, are allowed.
3103usage: (vector &rest OBJECTS) */) 3103usage: (vector &rest OBJECTS) */)
3104 (ptrdiff_t nargs, Lisp_Object *args) 3104 (ptrdiff_t nargs, Lisp_Object *args)
3105{ 3105{
3106 register Lisp_Object len, val;
3107 ptrdiff_t i; 3106 ptrdiff_t i;
3108 register struct Lisp_Vector *p; 3107 register Lisp_Object val = make_uninit_vector (nargs);
3108 register struct Lisp_Vector *p = XVECTOR (val);
3109 3109
3110 XSETFASTINT (len, nargs);
3111 val = Fmake_vector (len, Qnil);
3112 p = XVECTOR (val);
3113 for (i = 0; i < nargs; i++) 3110 for (i = 0; i < nargs; i++)
3114 p->contents[i] = args[i]; 3111 p->contents[i] = args[i];
3115 return val; 3112 return val;
@@ -3147,9 +3144,9 @@ stack before executing the byte-code.
3147usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */) 3144usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */)
3148 (ptrdiff_t nargs, Lisp_Object *args) 3145 (ptrdiff_t nargs, Lisp_Object *args)
3149{ 3146{
3150 register Lisp_Object len, val;
3151 ptrdiff_t i; 3147 ptrdiff_t i;
3152 register struct Lisp_Vector *p; 3148 register Lisp_Object val = make_uninit_vector (nargs);
3149 register struct Lisp_Vector *p = XVECTOR (val);
3153 3150
3154 /* We used to purecopy everything here, if purify-flag was set. This worked 3151 /* We used to purecopy everything here, if purify-flag was set. This worked
3155 OK for Emacs-23, but with Emacs-24's lexical binding code, it can be 3152 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
3159 just wasteful and other times plainly wrong (e.g. those free vars may want 3156 just wasteful and other times plainly wrong (e.g. those free vars may want
3160 to be setcar'd). */ 3157 to be setcar'd). */
3161 3158
3162 XSETFASTINT (len, nargs);
3163 val = Fmake_vector (len, Qnil);
3164
3165 p = XVECTOR (val);
3166 for (i = 0; i < nargs; i++) 3159 for (i = 0; i < nargs; i++)
3167 p->contents[i] = args[i]; 3160 p->contents[i] = args[i];
3168 make_byte_code (p); 3161 make_byte_code (p);
@@ -3354,7 +3347,7 @@ free_misc (Lisp_Object misc)
3354 and `o' for Lisp_Object. Up to 4 objects can be specified. */ 3347 and `o' for Lisp_Object. Up to 4 objects can be specified. */
3355 3348
3356Lisp_Object 3349Lisp_Object
3357format_save_value (const char *fmt, ...) 3350make_save_value (const char *fmt, ...)
3358{ 3351{
3359 va_list ap; 3352 va_list ap;
3360 int len = strlen (fmt); 3353 int len = strlen (fmt);
@@ -3402,15 +3395,19 @@ format_save_value (const char *fmt, ...)
3402 return val; 3395 return val;
3403} 3396}
3404 3397
3405/* Return a Lisp_Save_Value object containing POINTER and INTEGER. 3398/* The most common task it to save just one C pointer. */
3406 Most code should use this to package C integers and pointers
3407 to call record_unwind_protect. The unwind function can get the
3408 C values back using XSAVE_POINTER and XSAVE_INTEGER. */
3409 3399
3410Lisp_Object 3400Lisp_Object
3411make_save_value (void *pointer, ptrdiff_t integer) 3401make_save_pointer (void *pointer)
3412{ 3402{
3413 return format_save_value ("pi", pointer, integer); 3403 Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
3404 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
3405
3406 p->area = 0;
3407 p->type0 = SAVE_POINTER;
3408 p->data[0].pointer = pointer;
3409 p->type1 = p->type2 = p->type3 = SAVE_UNUSED;
3410 return val;
3414} 3411}
3415 3412
3416/* Free a Lisp_Save_Value object. Do not use this function 3413/* Free a Lisp_Save_Value object. Do not use this function
@@ -6533,7 +6530,7 @@ die (const char *msg, const char *file, int line)
6533} 6530}
6534#endif 6531#endif
6535 6532
6536/* Initialization */ 6533/* Initialization. */
6537 6534
6538void 6535void
6539init_alloc_once (void) 6536init_alloc_once (void)
@@ -6548,9 +6545,9 @@ init_alloc_once (void)
6548#endif 6545#endif
6549 6546
6550#ifdef DOUG_LEA_MALLOC 6547#ifdef DOUG_LEA_MALLOC
6551 mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ 6548 mallopt (M_TRIM_THRESHOLD, 128 * 1024); /* Trim threshold. */
6552 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */ 6549 mallopt (M_MMAP_THRESHOLD, 64 * 1024); /* Mmap threshold. */
6553 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* max. number of mmap'ed areas */ 6550 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* Max. number of mmap'ed areas. */
6554#endif 6551#endif
6555 init_strings (); 6552 init_strings ();
6556 init_vectors (); 6553 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 @@
2 2
3## This is inserted in src/Makefile if AUTO_DEPEND=yes. 3## This is inserted in src/Makefile if AUTO_DEPEND=yes.
4 4
5ALLOBJS=$(START_FILES) ${obj} ${otherobj}
6-include $(ALLOBJS:%.o=${DEPDIR}/%.d) 5-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)
910 return STRING_CHAR (s); 910 return STRING_CHAR (s);
911} 911}
912 912
913/* Fetch and return the character at BYTEPOS/CHARPOS. If that 913/* Fetch and return the character at CHARPOS/BYTEPOS. If that
914 character is covered by a display string, treat the entire run of 914 character is covered by a display string, treat the entire run of
915 covered characters as a single character, either u+2029 or u+FFFC, 915 covered characters as a single character, either u+2029 or u+FFFC,
916 and return their combined length in CH_LEN and NCHARS. DISP_POS 916 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)
925 string to iterate, or NULL if iterating over a buffer or a Lisp 925 string to iterate, or NULL if iterating over a buffer or a Lisp
926 string; in the latter case, STRING->lstring is the Lisp string. */ 926 string; in the latter case, STRING->lstring is the Lisp string. */
927static int 927static int
928bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos, 928bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos,
929 int *disp_prop, struct bidi_string_data *string, 929 int *disp_prop, struct bidi_string_data *string,
930 bool frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars) 930 bool frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars)
931{ 931{
@@ -1109,8 +1109,8 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
1109 display string? And what if a display string covering some 1109 display string? And what if a display string covering some
1110 of the text over which we scan back includes 1110 of the text over which we scan back includes
1111 paragraph_start_re? */ 1111 paragraph_start_re? */
1112 pos = find_next_newline_no_quit (pos - 1, -1); 1112 DEC_BOTH (pos, pos_byte);
1113 pos_byte = CHAR_TO_BYTE (pos); 1113 pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte);
1114 } 1114 }
1115 if (n >= MAX_PARAGRAPH_SEARCH) 1115 if (n >= MAX_PARAGRAPH_SEARCH)
1116 pos_byte = BEGV_BYTE; 1116 pos_byte = BEGV_BYTE;
@@ -1223,7 +1223,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
1223 bytepos = pstartbyte; 1223 bytepos = pstartbyte;
1224 if (!string_p) 1224 if (!string_p)
1225 pos = BYTE_TO_CHAR (bytepos); 1225 pos = BYTE_TO_CHAR (bytepos);
1226 ch = bidi_fetch_char (bytepos, pos, &disp_pos, &disp_prop, 1226 ch = bidi_fetch_char (pos, bytepos, &disp_pos, &disp_prop,
1227 &bidi_it->string, 1227 &bidi_it->string,
1228 bidi_it->frame_window_p, &ch_len, &nchars); 1228 bidi_it->frame_window_p, &ch_len, &nchars);
1229 type = bidi_get_type (ch, NEUTRAL_DIR); 1229 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)
1251 && bidi_at_paragraph_end (pos, bytepos) >= -1) 1251 && bidi_at_paragraph_end (pos, bytepos) >= -1)
1252 break; 1252 break;
1253 /* Fetch next character and advance to get past it. */ 1253 /* Fetch next character and advance to get past it. */
1254 ch = bidi_fetch_char (bytepos, pos, &disp_pos, 1254 ch = bidi_fetch_char (pos, bytepos, &disp_pos,
1255 &disp_prop, &bidi_it->string, 1255 &disp_prop, &bidi_it->string,
1256 bidi_it->frame_window_p, &ch_len, &nchars); 1256 bidi_it->frame_window_p, &ch_len, &nchars);
1257 pos += nchars; 1257 pos += nchars;
@@ -1282,8 +1282,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
1282 /* FXIME: What if p is covered by a display 1282 /* FXIME: What if p is covered by a display
1283 string? See also a FIXME inside 1283 string? See also a FIXME inside
1284 bidi_find_paragraph_start. */ 1284 bidi_find_paragraph_start. */
1285 p--; 1285 DEC_BOTH (p, pbyte);
1286 pbyte = CHAR_TO_BYTE (p);
1287 prevpbyte = bidi_find_paragraph_start (p, pbyte); 1286 prevpbyte = bidi_find_paragraph_start (p, pbyte);
1288 } 1287 }
1289 pstartbyte = prevpbyte; 1288 pstartbyte = prevpbyte;
@@ -1356,15 +1355,19 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1356 : bidi_it->string.s); 1355 : bidi_it->string.s);
1357 1356
1358 if (bidi_it->charpos < 0) 1357 if (bidi_it->charpos < 0)
1359 bidi_it->charpos = 0; 1358 bidi_it->charpos = bidi_it->bytepos = 0;
1360 bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos, 1359 eassert (bidi_it->bytepos == bidi_count_bytes (p, 0, 0,
1361 bidi_it->string.unibyte); 1360 bidi_it->charpos,
1361 bidi_it->string.unibyte));
1362 } 1362 }
1363 else 1363 else
1364 { 1364 {
1365 if (bidi_it->charpos < BEGV) 1365 if (bidi_it->charpos < BEGV)
1366 bidi_it->charpos = BEGV; 1366 {
1367 bidi_it->bytepos = CHAR_TO_BYTE (bidi_it->charpos); 1367 bidi_it->charpos = BEGV;
1368 bidi_it->bytepos = BEGV_BYTE;
1369 }
1370 eassert (bidi_it->bytepos == CHAR_TO_BYTE (bidi_it->charpos));
1368 } 1371 }
1369 } 1372 }
1370 /* Don't move at end of buffer/string. */ 1373 /* Don't move at end of buffer/string. */
@@ -1397,7 +1400,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1397 /* Fetch the character at BYTEPOS. If it is covered by a 1400 /* Fetch the character at BYTEPOS. If it is covered by a
1398 display string, treat the entire run of covered characters as 1401 display string, treat the entire run of covered characters as
1399 a single character u+FFFC. */ 1402 a single character u+FFFC. */
1400 curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos, 1403 curchar = bidi_fetch_char (bidi_it->charpos, bidi_it->bytepos,
1401 &bidi_it->disp_pos, &bidi_it->disp_prop, 1404 &bidi_it->disp_pos, &bidi_it->disp_prop,
1402 &bidi_it->string, bidi_it->frame_window_p, 1405 &bidi_it->string, bidi_it->frame_window_p,
1403 &bidi_it->ch_len, &bidi_it->nchars); 1406 &bidi_it->ch_len, &bidi_it->nchars);
@@ -1973,6 +1976,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
1973 next_type = STRONG_R; 1976 next_type = STRONG_R;
1974 break; 1977 break;
1975 case WEAK_BN: 1978 case WEAK_BN:
1979 case NEUTRAL_ON: /* W6/Retaining */
1976 if (!bidi_explicit_dir_char (bidi_it->ch)) 1980 if (!bidi_explicit_dir_char (bidi_it->ch))
1977 emacs_abort (); /* can't happen: BNs are skipped */ 1981 emacs_abort (); /* can't happen: BNs are skipped */
1978 /* FALLTHROUGH */ 1982 /* FALLTHROUGH */
@@ -2189,7 +2193,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2189 if (bidi_it->nchars <= 0) 2193 if (bidi_it->nchars <= 0)
2190 emacs_abort (); 2194 emacs_abort ();
2191 do { 2195 do {
2192 ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &dpp, &bs, 2196 ch = bidi_fetch_char (cpos += nc, bpos += clen, &disp_pos, &dpp, &bs,
2193 fwp, &clen, &nc); 2197 fwp, &clen, &nc);
2194 if (ch == '\n' || ch == BIDI_EOB) 2198 if (ch == '\n' || ch == BIDI_EOB)
2195 chtype = NEUTRAL_B; 2199 chtype = NEUTRAL_B;
@@ -2391,6 +2395,10 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
2391 next_level = bidi_peek_at_next_level (bidi_it); 2395 next_level = bidi_peek_at_next_level (bidi_it);
2392 while (next_level != expected_next_level) 2396 while (next_level != expected_next_level)
2393 { 2397 {
2398 /* If next_level is -1, it means we have an unresolved level
2399 in the cache, which at this point should not happen. If
2400 it does, we will infloop. */
2401 eassert (next_level >= 0);
2394 expected_next_level += incr; 2402 expected_next_level += incr;
2395 level_to_search += incr; 2403 level_to_search += incr;
2396 bidi_find_other_level_edge (bidi_it, level_to_search, !ascending); 2404 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)
370 b->INTERNAL_FIELD (zv_marker) = val; 370 b->INTERNAL_FIELD (zv_marker) = val;
371} 371}
372 372
373/* For debugging; temporary. See set_buffer_internal. */
374/* Lisp_Object Qlisp_mode, Vcheck_symbol; */
375
376void 373void
377nsberror (Lisp_Object spec) 374nsberror (Lisp_Object spec)
378{ 375{
@@ -3152,7 +3149,10 @@ ptrdiff_t
3152sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w) 3149sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
3153{ 3150{
3154 ptrdiff_t i, j; 3151 ptrdiff_t i, j;
3155 struct sortvec *sortvec = alloca (noverlays * sizeof *sortvec); 3152 USE_SAFE_ALLOCA;
3153 struct sortvec *sortvec;
3154
3155 SAFE_NALLOCA (sortvec, 1, noverlays);
3156 3156
3157 /* Put the valid and relevant overlays into sortvec. */ 3157 /* Put the valid and relevant overlays into sortvec. */
3158 3158
@@ -3198,6 +3198,8 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
3198 3198
3199 for (i = 0; i < noverlays; i++) 3199 for (i = 0; i < noverlays; i++)
3200 overlay_vec[i] = sortvec[i].overlay; 3200 overlay_vec[i] = sortvec[i].overlay;
3201
3202 SAFE_FREE ();
3201 return (noverlays); 3203 return (noverlays);
3202} 3204}
3203 3205
@@ -6001,10 +6003,6 @@ simple case that you moved off with C-b means scrolling just one line.
6001window scrolls by a full window height. Meaningful values are 6003window scrolls by a full window height. Meaningful values are
6002between 0.0 and 1.0, inclusive. */); 6004between 0.0 and 1.0, inclusive. */);
6003 6005
6004/*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
6005 "Don't ask.");
6006*/
6007
6008 DEFVAR_LISP ("before-change-functions", Vbefore_change_functions, 6006 DEFVAR_LISP ("before-change-functions", Vbefore_change_functions,
6009 doc: /* List of functions to call before each text change. 6007 doc: /* List of functions to call before each text change.
6010Two arguments are passed to each function: the positions of 6008Two 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
82/* Size of gap. */ 82/* Size of gap. */
83#define GAP_SIZE (current_buffer->text->gap_size) 83#define GAP_SIZE (current_buffer->text->gap_size)
84 84
85/* Is the current buffer narrowed? */
86#define NARROWED ((BEGV != BEG) || (ZV != Z))
87
88/* Modification count. */ 85/* Modification count. */
89#define MODIFF (current_buffer->text->modiff) 86#define MODIFF (current_buffer->text->modiff)
90 87
@@ -173,10 +170,6 @@ INLINE_HEADER_BEGIN
173/* Size of gap. */ 170/* Size of gap. */
174#define BUF_GAP_SIZE(buf) ((buf)->text->gap_size) 171#define BUF_GAP_SIZE(buf) ((buf)->text->gap_size)
175 172
176/* Is this buffer narrowed? */
177#define BUF_NARROWED(buf) ((BUF_BEGV (buf) != BUF_BEG (buf)) \
178 || (BUF_ZV (buf) != BUF_Z (buf)))
179
180/* Modification count. */ 173/* Modification count. */
181#define BUF_MODIFF(buf) ((buf)->text->modiff) 174#define BUF_MODIFF(buf) ((buf)->text->modiff)
182 175
@@ -294,24 +287,24 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t);
294/* Access a Lisp position value in POS, 287/* Access a Lisp position value in POS,
295 and store the charpos in CHARPOS and the bytepos in BYTEPOS. */ 288 and store the charpos in CHARPOS and the bytepos in BYTEPOS. */
296 289
297#define DECODE_POSITION(charpos, bytepos, pos) \ 290#define DECODE_POSITION(charpos, bytepos, pos) \
298do \ 291 do \
299 { \ 292 { \
300 Lisp_Object __pos = (pos); \ 293 Lisp_Object __pos = (pos); \
301 if (NUMBERP (__pos)) \ 294 if (NUMBERP (__pos)) \
302 { \ 295 { \
303 charpos = __pos; \ 296 charpos = __pos; \
304 bytepos = buf_charpos_to_bytepos (current_buffer, __pos); \ 297 bytepos = buf_charpos_to_bytepos (current_buffer, __pos); \
305 } \ 298 } \
306 else if (MARKERP (__pos)) \ 299 else if (MARKERP (__pos)) \
307 { \ 300 { \
308 charpos = marker_position (__pos); \ 301 charpos = marker_position (__pos); \
309 bytepos = marker_byte_position (__pos); \ 302 bytepos = marker_byte_position (__pos); \
310 } \ 303 } \
311 else \ 304 else \
312 wrong_type_argument (Qinteger_or_marker_p, __pos); \ 305 wrong_type_argument (Qinteger_or_marker_p, __pos); \
313 } \ 306 } \
314while (0) 307 while (0)
315 308
316/* Maximum number of bytes in a buffer. 309/* Maximum number of bytes in a buffer.
317 A buffer cannot contain more bytes than a 1-origin fixnum can represent, 310 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)
1009#define BUFFER_CHECK_INDIRECTION(b) \ 1002#define BUFFER_CHECK_INDIRECTION(b) \
1010 do { \ 1003 do { \
1011 if (BUFFER_LIVE_P (b)) \ 1004 if (BUFFER_LIVE_P (b)) \
1012 { \ 1005 { \
1013 if (b->base_buffer) \ 1006 if (b->base_buffer) \
1014 { \ 1007 { \
1015 eassert (b->indirections == -1); \ 1008 eassert (b->indirections == -1); \
1016 eassert (b->base_buffer->indirections > 0); \ 1009 eassert (b->base_buffer->indirections > 0); \
1017 } \ 1010 } \
1018 else \ 1011 else \
1019 eassert (b->indirections >= 0); \ 1012 eassert (b->indirections >= 0); \
1020 } \ 1013 } \
1021 } while (0) 1014 } while (0)
1022 1015
1023/* Chain of all buffers, including killed ones. */ 1016/* 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/>. */
29#include "keymap.h" 29#include "keymap.h"
30 30
31Lisp_Object Qminus, Qplus; 31Lisp_Object Qminus, Qplus;
32Lisp_Object Qcall_interactively; 32static Lisp_Object Qcall_interactively;
33static Lisp_Object Qcommand_debug_status; 33static Lisp_Object Qcommand_debug_status;
34static Lisp_Object Qenable_recursive_minibuffers; 34static Lisp_Object Qenable_recursive_minibuffers;
35 35
@@ -342,8 +342,8 @@ invoke it. If KEYS is omitted or nil, the return value of
342 /* Compute the arg values using the user's expression. */ 342 /* Compute the arg values using the user's expression. */
343 GCPRO2 (input, filter_specs); 343 GCPRO2 (input, filter_specs);
344 specs = Feval (specs, 344 specs = Feval (specs,
345 CONSP (funval) && EQ (Qclosure, XCAR (funval)) 345 CONSP (funval) && EQ (Qclosure, XCAR (funval))
346 ? Qt : Qnil); 346 ? CAR_SAFE (XCDR (funval)) : Qnil);
347 UNGCPRO; 347 UNGCPRO;
348 if (events != num_input_events || !NILP (record_flag)) 348 if (events != num_input_events || !NILP (record_flag))
349 { 349 {
@@ -497,47 +497,47 @@ invoke it. If KEYS is omitted or nil, the return value of
497 497
498 switch (*tem) 498 switch (*tem)
499 { 499 {
500 case 'a': /* Symbol defined as a function */ 500 case 'a': /* Symbol defined as a function. */
501 visargs[i] = Fcompleting_read (callint_message, 501 visargs[i] = Fcompleting_read (callint_message,
502 Vobarray, Qfboundp, Qt, 502 Vobarray, Qfboundp, Qt,
503 Qnil, Qnil, Qnil, Qnil); 503 Qnil, Qnil, Qnil, Qnil);
504 /* Passing args[i] directly stimulates compiler bug */ 504 /* Passing args[i] directly stimulates compiler bug. */
505 teml = visargs[i]; 505 teml = visargs[i];
506 args[i] = Fintern (teml, Qnil); 506 args[i] = Fintern (teml, Qnil);
507 break; 507 break;
508 508
509 case 'b': /* Name of existing buffer */ 509 case 'b': /* Name of existing buffer. */
510 args[i] = Fcurrent_buffer (); 510 args[i] = Fcurrent_buffer ();
511 if (EQ (selected_window, minibuf_window)) 511 if (EQ (selected_window, minibuf_window))
512 args[i] = Fother_buffer (args[i], Qnil, Qnil); 512 args[i] = Fother_buffer (args[i], Qnil, Qnil);
513 args[i] = Fread_buffer (callint_message, args[i], Qt); 513 args[i] = Fread_buffer (callint_message, args[i], Qt);
514 break; 514 break;
515 515
516 case 'B': /* Name of buffer, possibly nonexistent */ 516 case 'B': /* Name of buffer, possibly nonexistent. */
517 args[i] = Fread_buffer (callint_message, 517 args[i] = Fread_buffer (callint_message,
518 Fother_buffer (Fcurrent_buffer (), Qnil, Qnil), 518 Fother_buffer (Fcurrent_buffer (), Qnil, Qnil),
519 Qnil); 519 Qnil);
520 break; 520 break;
521 521
522 case 'c': /* Character */ 522 case 'c': /* Character. */
523 /* Prompt in `minibuffer-prompt' face. */ 523 /* Prompt in `minibuffer-prompt' face. */
524 Fput_text_property (make_number (0), 524 Fput_text_property (make_number (0),
525 make_number (SCHARS (callint_message)), 525 make_number (SCHARS (callint_message)),
526 Qface, Qminibuffer_prompt, callint_message); 526 Qface, Qminibuffer_prompt, callint_message);
527 args[i] = Fread_char (callint_message, Qnil, Qnil); 527 args[i] = Fread_char (callint_message, Qnil, Qnil);
528 message1_nolog ((char *) 0); 528 message1_nolog ((char *) 0);
529 /* Passing args[i] directly stimulates compiler bug */ 529 /* Passing args[i] directly stimulates compiler bug. */
530 teml = args[i]; 530 teml = args[i];
531 /* See bug#8479. */ 531 /* See bug#8479. */
532 if (! CHARACTERP (teml)) error ("Non-character input-event"); 532 if (! CHARACTERP (teml)) error ("Non-character input-event");
533 visargs[i] = Fchar_to_string (teml); 533 visargs[i] = Fchar_to_string (teml);
534 break; 534 break;
535 535
536 case 'C': /* Command: symbol with interactive function */ 536 case 'C': /* Command: symbol with interactive function. */
537 visargs[i] = Fcompleting_read (callint_message, 537 visargs[i] = Fcompleting_read (callint_message,
538 Vobarray, Qcommandp, 538 Vobarray, Qcommandp,
539 Qt, Qnil, Qnil, Qnil, Qnil); 539 Qt, Qnil, Qnil, Qnil, Qnil);
540 /* Passing args[i] directly stimulates compiler bug */ 540 /* Passing args[i] directly stimulates compiler bug. */
541 teml = visargs[i]; 541 teml = visargs[i];
542 args[i] = Fintern (teml, Qnil); 542 args[i] = Fintern (teml, Qnil);
543 break; 543 break;
@@ -549,33 +549,33 @@ invoke it. If KEYS is omitted or nil, the return value of
549 varies[i] = 1; 549 varies[i] = 1;
550 break; 550 break;
551 551
552 case 'D': /* Directory name. */ 552 case 'D': /* Directory name. */
553 args[i] = Fread_file_name (callint_message, Qnil, 553 args[i] = Fread_file_name (callint_message, Qnil,
554 BVAR (current_buffer, directory), Qlambda, Qnil, 554 BVAR (current_buffer, directory), Qlambda, Qnil,
555 Qfile_directory_p); 555 Qfile_directory_p);
556 break; 556 break;
557 557
558 case 'f': /* Existing file name. */ 558 case 'f': /* Existing file name. */
559 args[i] = Fread_file_name (callint_message, 559 args[i] = Fread_file_name (callint_message,
560 Qnil, Qnil, Qlambda, Qnil, Qnil); 560 Qnil, Qnil, Qlambda, Qnil, Qnil);
561 break; 561 break;
562 562
563 case 'F': /* Possibly nonexistent file name. */ 563 case 'F': /* Possibly nonexistent file name. */
564 args[i] = Fread_file_name (callint_message, 564 args[i] = Fread_file_name (callint_message,
565 Qnil, Qnil, Qnil, Qnil, Qnil); 565 Qnil, Qnil, Qnil, Qnil, Qnil);
566 break; 566 break;
567 567
568 case 'G': /* Possibly nonexistent file name, 568 case 'G': /* Possibly nonexistent file name,
569 default to directory alone. */ 569 default to directory alone. */
570 args[i] = Fread_file_name (callint_message, 570 args[i] = Fread_file_name (callint_message,
571 Qnil, Qnil, Qnil, empty_unibyte_string, Qnil); 571 Qnil, Qnil, Qnil, empty_unibyte_string, Qnil);
572 break; 572 break;
573 573
574 case 'i': /* Ignore an argument -- Does not do I/O */ 574 case 'i': /* Ignore an argument -- Does not do I/O. */
575 varies[i] = -1; 575 varies[i] = -1;
576 break; 576 break;
577 577
578 case 'k': /* Key sequence. */ 578 case 'k': /* Key sequence. */
579 { 579 {
580 ptrdiff_t speccount1 = SPECPDL_INDEX (); 580 ptrdiff_t speccount1 = SPECPDL_INDEX ();
581 specbind (Qcursor_in_echo_area, Qt); 581 specbind (Qcursor_in_echo_area, Qt);
@@ -607,7 +607,7 @@ invoke it. If KEYS is omitted or nil, the return value of
607 } 607 }
608 break; 608 break;
609 609
610 case 'K': /* Key sequence to be defined. */ 610 case 'K': /* Key sequence to be defined. */
611 { 611 {
612 ptrdiff_t speccount1 = SPECPDL_INDEX (); 612 ptrdiff_t speccount1 = SPECPDL_INDEX ();
613 specbind (Qcursor_in_echo_area, Qt); 613 specbind (Qcursor_in_echo_area, Qt);
@@ -639,7 +639,7 @@ invoke it. If KEYS is omitted or nil, the return value of
639 } 639 }
640 break; 640 break;
641 641
642 case 'U': /* Up event from last k or K */ 642 case 'U': /* Up event from last k or K. */
643 if (!NILP (up_event)) 643 if (!NILP (up_event))
644 { 644 {
645 args[i] = Fmake_vector (make_number (1), up_event); 645 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
679 Qnil, Qnil, Qnil, Qt); 679 Qnil, Qnil, Qnil, Qt);
680 break; 680 break;
681 681
682 case 'N': /* Prefix arg as number, else number from minibuffer */ 682 case 'N': /* Prefix arg as number, else number from minibuffer. */
683 if (!NILP (prefix_arg)) 683 if (!NILP (prefix_arg))
684 goto have_prefix_arg; 684 goto have_prefix_arg;
685 case 'n': /* Read number from minibuffer. */ 685 case 'n': /* Read number from minibuffer. */
@@ -690,7 +690,7 @@ invoke it. If KEYS is omitted or nil, the return value of
690 Lisp_Object str; 690 Lisp_Object str;
691 if (! first) 691 if (! first)
692 { 692 {
693 message ("Please enter a number."); 693 message1 ("Please enter a number.");
694 sit_for (make_number (1), 0, 0); 694 sit_for (make_number (1), 0, 0);
695 } 695 }
696 first = 0; 696 first = 0;
@@ -714,14 +714,14 @@ invoke it. If KEYS is omitted or nil, the return value of
714 varies[i] = -1; 714 varies[i] = -1;
715 break; 715 break;
716 716
717 case 'p': /* Prefix arg converted to number. No I/O. */ 717 case 'p': /* Prefix arg converted to number. No I/O. */
718 have_prefix_arg: 718 have_prefix_arg:
719 args[i] = Fprefix_numeric_value (prefix_arg); 719 args[i] = Fprefix_numeric_value (prefix_arg);
720 /* visargs[i] = Qnil; */ 720 /* visargs[i] = Qnil; */
721 varies[i] = -1; 721 varies[i] = -1;
722 break; 722 break;
723 723
724 case 'r': /* Region, point and mark as 2 args. */ 724 case 'r': /* Region, point and mark as 2 args. */
725 check_mark (1); 725 check_mark (1);
726 set_marker_both (point_marker, Qnil, PT, PT_BYTE); 726 set_marker_both (point_marker, Qnil, PT, PT_BYTE);
727 /* visargs[i+1] = Qnil; */ 727 /* visargs[i+1] = Qnil; */
@@ -742,29 +742,29 @@ invoke it. If KEYS is omitted or nil, the return value of
742 case 'S': /* Any symbol. */ 742 case 'S': /* Any symbol. */
743 visargs[i] = Fread_string (callint_message, 743 visargs[i] = Fread_string (callint_message,
744 Qnil, Qnil, Qnil, Qnil); 744 Qnil, Qnil, Qnil, Qnil);
745 /* Passing args[i] directly stimulates compiler bug */ 745 /* Passing args[i] directly stimulates compiler bug. */
746 teml = visargs[i]; 746 teml = visargs[i];
747 args[i] = Fintern (teml, Qnil); 747 args[i] = Fintern (teml, Qnil);
748 break; 748 break;
749 749
750 case 'v': /* Variable name: symbol that is 750 case 'v': /* Variable name: symbol that is
751 custom-variable-p. */ 751 custom-variable-p. */
752 args[i] = Fread_variable (callint_message, Qnil); 752 args[i] = Fread_variable (callint_message, Qnil);
753 visargs[i] = last_minibuf_string; 753 visargs[i] = last_minibuf_string;
754 break; 754 break;
755 755
756 case 'x': /* Lisp expression read but not evaluated */ 756 case 'x': /* Lisp expression read but not evaluated. */
757 args[i] = Fread_minibuffer (callint_message, Qnil); 757 args[i] = Fread_minibuffer (callint_message, Qnil);
758 visargs[i] = last_minibuf_string; 758 visargs[i] = last_minibuf_string;
759 break; 759 break;
760 760
761 case 'X': /* Lisp expression read and evaluated */ 761 case 'X': /* Lisp expression read and evaluated. */
762 args[i] = Feval_minibuffer (callint_message, Qnil); 762 args[i] = Feval_minibuffer (callint_message, Qnil);
763 visargs[i] = last_minibuf_string; 763 visargs[i] = last_minibuf_string;
764 break; 764 break;
765 765
766 case 'Z': /* Coding-system symbol, or ignore the 766 case 'Z': /* Coding-system symbol, or ignore the
767 argument if no prefix */ 767 argument if no prefix. */
768 if (NILP (prefix_arg)) 768 if (NILP (prefix_arg))
769 { 769 {
770 args[i] = Qnil; 770 args[i] = Qnil;
@@ -778,7 +778,7 @@ invoke it. If KEYS is omitted or nil, the return value of
778 } 778 }
779 break; 779 break;
780 780
781 case 'z': /* Coding-system symbol or nil */ 781 case 'z': /* Coding-system symbol or nil. */
782 args[i] = Fread_coding_system (callint_message, Qnil); 782 args[i] = Fread_coding_system (callint_message, Qnil);
783 visargs[i] = last_minibuf_string; 783 visargs[i] = last_minibuf_string;
784 break; 784 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) */)
445 path = Fsubstring (path, make_number (2), Qnil); 445 path = Fsubstring (path, make_number (2), Qnil);
446 446
447 new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); 447 new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv);
448 if (nargs > 4)
449 {
450 ptrdiff_t i;
451 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
452 448
453 GCPRO5 (infile, buffer, current_dir, path, error_file); 449 {
454 argument_coding.dst_multibyte = 0; 450 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
455 for (i = 4; i < nargs; i++) 451
456 { 452 GCPRO5 (infile, buffer, current_dir, path, error_file);
457 argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]); 453 if (nargs > 4)
458 if (CODING_REQUIRE_ENCODING (&argument_coding)) 454 {
459 /* We must encode this argument. */ 455 ptrdiff_t i;
460 args[i] = encode_coding_string (&argument_coding, args[i], 1); 456
461 } 457 argument_coding.dst_multibyte = 0;
462 UNGCPRO; 458 for (i = 4; i < nargs; i++)
463 for (i = 4; i < nargs; i++) 459 {
464 new_argv[i - 3] = SSDATA (args[i]); 460 argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]);
465 new_argv[i - 3] = 0; 461 if (CODING_REQUIRE_ENCODING (&argument_coding))
466 } 462 /* We must encode this argument. */
467 else 463 args[i] = encode_coding_string (&argument_coding, args[i], 1);
468 new_argv[1] = 0; 464 }
469 new_argv[0] = SSDATA (path); 465 for (i = 4; i < nargs; i++)
466 new_argv[i - 3] = SSDATA (args[i]);
467 new_argv[i - 3] = 0;
468 }
469 else
470 new_argv[1] = 0;
471 if (STRING_MULTIBYTE (path))
472 path = ENCODE_FILE (path);
473 new_argv[0] = SSDATA (path);
474 UNGCPRO;
475 }
470 476
471#ifdef MSDOS /* MW, July 1993 */ 477#ifdef MSDOS /* MW, July 1993 */
472 478
@@ -481,7 +487,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
481 tempfile = alloca (20); 487 tempfile = alloca (20);
482 *tempfile = '\0'; 488 *tempfile = '\0';
483 } 489 }
484 dostounix_filename (tempfile); 490 dostounix_filename (tempfile, 0);
485 if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') 491 if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
486 strcat (tempfile, "/"); 492 strcat (tempfile, "/");
487 strcat (tempfile, "detmp.XXX"); 493 strcat (tempfile, "detmp.XXX");
@@ -991,13 +997,11 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
991 tmpdir = Vtemporary_file_directory; 997 tmpdir = Vtemporary_file_directory;
992 else 998 else
993 { 999 {
1000 char *outf;
994#ifndef DOS_NT 1001#ifndef DOS_NT
995 if (getenv ("TMPDIR")) 1002 outf = getenv ("TMPDIR");
996 tmpdir = build_string (getenv ("TMPDIR")); 1003 tmpdir = build_string (outf ? outf : "/tmp/");
997 else
998 tmpdir = build_string ("/tmp/");
999#else /* DOS_NT */ 1004#else /* DOS_NT */
1000 char *outf;
1001 if ((outf = egetenv ("TMPDIR")) 1005 if ((outf = egetenv ("TMPDIR"))
1002 || (outf = egetenv ("TMP")) 1006 || (outf = egetenv ("TMP"))
1003 || (outf = egetenv ("TEMP"))) 1007 || (outf = egetenv ("TEMP")))
@@ -1010,8 +1014,26 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1010 { 1014 {
1011 USE_SAFE_ALLOCA; 1015 USE_SAFE_ALLOCA;
1012 Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); 1016 Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir);
1013 Lisp_Object encoded_tem = ENCODE_FILE (pattern); 1017 Lisp_Object encoded_tem;
1014 char *tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1); 1018 char *tempfile;
1019
1020#ifdef WINDOWSNT
1021 /* Cannot use the result of Fexpand_file_name, because it
1022 downcases the XXXXXX part of the pattern, and mktemp then
1023 doesn't recognize it. */
1024 if (!NILP (Vw32_downcase_file_names))
1025 {
1026 Lisp_Object dirname = Ffile_name_directory (pattern);
1027
1028 if (NILP (dirname))
1029 pattern = Vtemp_file_name_pattern;
1030 else
1031 pattern = concat2 (dirname, Vtemp_file_name_pattern);
1032 }
1033#endif
1034
1035 encoded_tem = ENCODE_FILE (pattern);
1036 tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1);
1015 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); 1037 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
1016 coding_systems = Qt; 1038 coding_systems = Qt;
1017 1039
@@ -1631,7 +1653,7 @@ init_callproc (void)
1631 if (! file_accessible_directory_p (SSDATA (tempdir))) 1653 if (! file_accessible_directory_p (SSDATA (tempdir)))
1632 dir_warning ("arch-independent data dir", Vdata_directory); 1654 dir_warning ("arch-independent data dir", Vdata_directory);
1633 1655
1634 sh = (char *) getenv ("SHELL"); 1656 sh = getenv ("SHELL");
1635 Vshell_file_name = build_string (sh ? sh : "/bin/sh"); 1657 Vshell_file_name = build_string (sh ? sh : "/bin/sh");
1636 1658
1637#ifdef DOS_NT 1659#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. */)
2228 Vccl_program_table = larger_vector (Vccl_program_table, 1, -1); 2228 Vccl_program_table = larger_vector (Vccl_program_table, 1, -1);
2229 2229
2230 { 2230 {
2231 Lisp_Object elt; 2231 Lisp_Object elt = make_uninit_vector (4);
2232 2232
2233 elt = Fmake_vector (make_number (4), Qnil);
2234 ASET (elt, 0, name); 2233 ASET (elt, 0, name);
2235 ASET (elt, 1, ccl_prog); 2234 ASET (elt, 1, ccl_prog);
2236 ASET (elt, 2, resolved); 2235 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 ...) */)
1053 CHECK_NATNUM (parent_max_code); 1053 CHECK_NATNUM (parent_max_code);
1054 parent_code_offset = Fnth (make_number (3), val); 1054 parent_code_offset = Fnth (make_number (3), val);
1055 CHECK_NUMBER (parent_code_offset); 1055 CHECK_NUMBER (parent_code_offset);
1056 val = Fmake_vector (make_number (4), Qnil); 1056 val = make_uninit_vector (4);
1057 ASET (val, 0, make_number (parent_charset->id)); 1057 ASET (val, 0, make_number (parent_charset->id));
1058 ASET (val, 1, parent_min_code); 1058 ASET (val, 1, parent_min_code);
1059 ASET (val, 2, parent_max_code); 1059 ASET (val, 2, parent_max_code);
@@ -1259,7 +1259,7 @@ define_charset_internal (Lisp_Object name,
1259 1259
1260 args[charset_arg_name] = name; 1260 args[charset_arg_name] = name;
1261 args[charset_arg_dimension] = make_number (dimension); 1261 args[charset_arg_dimension] = make_number (dimension);
1262 val = Fmake_vector (make_number (8), make_number (0)); 1262 val = make_uninit_vector (8);
1263 for (i = 0; i < 8; i++) 1263 for (i = 0; i < 8; i++)
1264 ASET (val, i, make_number (code_space[i])); 1264 ASET (val, i, make_number (code_space[i]));
1265 args[charset_arg_code_space] = val; 1265 args[charset_arg_code_space] = val;
diff --git a/src/cm.c b/src/cm.c
index 842633aceec..3a5f927eda3 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -28,8 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include "termchar.h" 28#include "termchar.h"
29#include "tparam.h" 29#include "tparam.h"
30 30
31#define BIG 9999 /* 9999 good on VAXen. For 16 bit machines 31#define BIG 9999 /* Good on 32-bit hosts. */
32 use about 2000.... */
33 32
34int cost; /* sums up costs */ 33int cost; /* sums up costs */
35 34
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;
322Lisp_Object Qstart_process, Qopen_network_stream; 322Lisp_Object Qstart_process, Qopen_network_stream;
323static Lisp_Object Qtarget_idx; 323static Lisp_Object Qtarget_idx;
324 324
325static Lisp_Object Qinsufficient_source, Qinconsistent_eol, Qinvalid_source; 325static Lisp_Object Qinsufficient_source, Qinvalid_source, Qinterrupted;
326static Lisp_Object Qinterrupted, Qinsufficient_memory;
327 326
328/* If a symbol has this property, evaluate the value to define the 327/* If a symbol has this property, evaluate the value to define the
329 symbol as a coding system. */ 328 symbol as a coding system. */
@@ -820,18 +819,12 @@ record_conversion_result (struct coding_system *coding,
820 case CODING_RESULT_INSUFFICIENT_SRC: 819 case CODING_RESULT_INSUFFICIENT_SRC:
821 Vlast_code_conversion_error = Qinsufficient_source; 820 Vlast_code_conversion_error = Qinsufficient_source;
822 break; 821 break;
823 case CODING_RESULT_INCONSISTENT_EOL:
824 Vlast_code_conversion_error = Qinconsistent_eol;
825 break;
826 case CODING_RESULT_INVALID_SRC: 822 case CODING_RESULT_INVALID_SRC:
827 Vlast_code_conversion_error = Qinvalid_source; 823 Vlast_code_conversion_error = Qinvalid_source;
828 break; 824 break;
829 case CODING_RESULT_INTERRUPT: 825 case CODING_RESULT_INTERRUPT:
830 Vlast_code_conversion_error = Qinterrupted; 826 Vlast_code_conversion_error = Qinterrupted;
831 break; 827 break;
832 case CODING_RESULT_INSUFFICIENT_MEM:
833 Vlast_code_conversion_error = Qinsufficient_memory;
834 break;
835 case CODING_RESULT_INSUFFICIENT_DST: 828 case CODING_RESULT_INSUFFICIENT_DST:
836 /* Don't record this error in Vlast_code_conversion_error 829 /* Don't record this error in Vlast_code_conversion_error
837 because it happens just temporarily and is resolved when the 830 because it happens just temporarily and is resolved when the
@@ -3057,20 +3050,7 @@ detect_coding_iso_2022 (struct coding_system *coding,
3057 } 3050 }
3058 if (single_shifting) 3051 if (single_shifting)
3059 break; 3052 break;
3060 check_extra_latin: 3053 goto check_extra_latin;
3061 if (! VECTORP (Vlatin_extra_code_table)
3062 || NILP (AREF (Vlatin_extra_code_table, c)))
3063 {
3064 rejected = CATEGORY_MASK_ISO;
3065 break;
3066 }
3067 if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_1])
3068 & CODING_ISO_FLAG_LATIN_EXTRA)
3069 found |= CATEGORY_MASK_ISO_8_1;
3070 else
3071 rejected |= CATEGORY_MASK_ISO_8_1;
3072 rejected |= CATEGORY_MASK_ISO_8_2;
3073 break;
3074 3054
3075 default: 3055 default:
3076 if (c < 0) 3056 if (c < 0)
@@ -3121,6 +3101,20 @@ detect_coding_iso_2022 (struct coding_system *coding,
3121 } 3101 }
3122 break; 3102 break;
3123 } 3103 }
3104 check_extra_latin:
3105 if (! VECTORP (Vlatin_extra_code_table)
3106 || NILP (AREF (Vlatin_extra_code_table, c)))
3107 {
3108 rejected = CATEGORY_MASK_ISO;
3109 break;
3110 }
3111 if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_1])
3112 & CODING_ISO_FLAG_LATIN_EXTRA)
3113 found |= CATEGORY_MASK_ISO_8_1;
3114 else
3115 rejected |= CATEGORY_MASK_ISO_8_1;
3116 rejected |= CATEGORY_MASK_ISO_8_2;
3117 break;
3124 } 3118 }
3125 } 3119 }
3126 detect_info->rejected |= CATEGORY_MASK_ISO; 3120 detect_info->rejected |= CATEGORY_MASK_ISO;
@@ -6883,22 +6877,8 @@ produce_charset (struct coding_system *coding, int *charbuf, ptrdiff_t pos)
6883 6877
6884#define ALLOC_CONVERSION_WORK_AREA(coding) \ 6878#define ALLOC_CONVERSION_WORK_AREA(coding) \
6885 do { \ 6879 do { \
6886 int size = CHARBUF_SIZE; \ 6880 coding->charbuf = SAFE_ALLOCA (CHARBUF_SIZE * sizeof (int)); \
6887 \ 6881 coding->charbuf_size = CHARBUF_SIZE; \
6888 coding->charbuf = NULL; \
6889 while (size > 1024) \
6890 { \
6891 coding->charbuf = alloca (sizeof (int) * size); \
6892 if (coding->charbuf) \
6893 break; \
6894 size >>= 1; \
6895 } \
6896 if (! coding->charbuf) \
6897 { \
6898 record_conversion_result (coding, CODING_RESULT_INSUFFICIENT_MEM); \
6899 return; \
6900 } \
6901 coding->charbuf_size = size; \
6902 } while (0) 6882 } while (0)
6903 6883
6904 6884
@@ -6967,6 +6947,8 @@ decode_coding (struct coding_system *coding)
6967 int carryover; 6947 int carryover;
6968 int i; 6948 int i;
6969 6949
6950 USE_SAFE_ALLOCA;
6951
6970 if (BUFFERP (coding->src_object) 6952 if (BUFFERP (coding->src_object)
6971 && coding->src_pos > 0 6953 && coding->src_pos > 0
6972 && coding->src_pos < GPT 6954 && coding->src_pos < GPT
@@ -7089,6 +7071,8 @@ decode_coding (struct coding_system *coding)
7089 bset_undo_list (current_buffer, undo_list); 7071 bset_undo_list (current_buffer, undo_list);
7090 record_insert (coding->dst_pos, coding->produced_char); 7072 record_insert (coding->dst_pos, coding->produced_char);
7091 } 7073 }
7074
7075 SAFE_FREE ();
7092} 7076}
7093 7077
7094 7078
@@ -7372,6 +7356,8 @@ encode_coding (struct coding_system *coding)
7372 int max_lookup; 7356 int max_lookup;
7373 struct ccl_spec cclspec; 7357 struct ccl_spec cclspec;
7374 7358
7359 USE_SAFE_ALLOCA;
7360
7375 attrs = CODING_ID_ATTRS (coding->id); 7361 attrs = CODING_ID_ATTRS (coding->id);
7376 if (coding->encoder == encode_coding_raw_text) 7362 if (coding->encoder == encode_coding_raw_text)
7377 translation_table = Qnil, max_lookup = 0; 7363 translation_table = Qnil, max_lookup = 0;
@@ -7406,6 +7392,8 @@ encode_coding (struct coding_system *coding)
7406 7392
7407 if (BUFFERP (coding->dst_object) && coding->produced_char > 0) 7393 if (BUFFERP (coding->dst_object) && coding->produced_char > 0)
7408 insert_from_gap (coding->produced_char, coding->produced); 7394 insert_from_gap (coding->produced_char, coding->produced);
7395
7396 SAFE_FREE ();
7409} 7397}
7410 7398
7411 7399
@@ -7694,14 +7682,8 @@ decode_coding_object (struct coding_system *coding,
7694 set_buffer_internal (XBUFFER (coding->dst_object)); 7682 set_buffer_internal (XBUFFER (coding->dst_object));
7695 if (dst_bytes < coding->produced) 7683 if (dst_bytes < coding->produced)
7696 { 7684 {
7685 eassert (coding->produced > 0);
7697 destination = xrealloc (destination, coding->produced); 7686 destination = xrealloc (destination, coding->produced);
7698 if (! destination)
7699 {
7700 record_conversion_result (coding,
7701 CODING_RESULT_INSUFFICIENT_MEM);
7702 unbind_to (count, Qnil);
7703 return;
7704 }
7705 if (BEGV < GPT && GPT < BEGV + coding->produced_char) 7687 if (BEGV < GPT && GPT < BEGV + coding->produced_char)
7706 move_gap_both (BEGV, BEGV_BYTE); 7688 move_gap_both (BEGV, BEGV_BYTE);
7707 memcpy (destination, BEGV_ADDR, coding->produced); 7689 memcpy (destination, BEGV_ADDR, coding->produced);
@@ -9482,7 +9464,7 @@ make_subsidiaries (Lisp_Object base)
9482 int i; 9464 int i;
9483 9465
9484 memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len); 9466 memcpy (buf, SDATA (SYMBOL_NAME (base)), base_name_len);
9485 subsidiaries = Fmake_vector (make_number (3), Qnil); 9467 subsidiaries = make_uninit_vector (3);
9486 for (i = 0; i < 3; i++) 9468 for (i = 0; i < 3; i++)
9487 { 9469 {
9488 strcpy (buf + base_name_len, suffixes[i]); 9470 strcpy (buf + base_name_len, suffixes[i]);
@@ -9782,7 +9764,7 @@ usage: (define-coding-system-internal ...) */)
9782 CHECK_VECTOR (initial); 9764 CHECK_VECTOR (initial);
9783 for (i = 0; i < 4; i++) 9765 for (i = 0; i < 4; i++)
9784 { 9766 {
9785 val = Faref (initial, make_number (i)); 9767 val = AREF (initial, i);
9786 if (! NILP (val)) 9768 if (! NILP (val))
9787 { 9769 {
9788 struct charset *charset; 9770 struct charset *charset;
@@ -9987,7 +9969,8 @@ usage: (define-coding-system-internal ...) */)
9987 this_name = AREF (eol_type, i); 9969 this_name = AREF (eol_type, i);
9988 this_aliases = Fcons (this_name, Qnil); 9970 this_aliases = Fcons (this_name, Qnil);
9989 this_eol_type = (i == 0 ? Qunix : i == 1 ? Qdos : Qmac); 9971 this_eol_type = (i == 0 ? Qunix : i == 1 ? Qdos : Qmac);
9990 this_spec = Fmake_vector (make_number (3), attrs); 9972 this_spec = make_uninit_vector (3);
9973 ASET (this_spec, 0, attrs);
9991 ASET (this_spec, 1, this_aliases); 9974 ASET (this_spec, 1, this_aliases);
9992 ASET (this_spec, 2, this_eol_type); 9975 ASET (this_spec, 2, this_eol_type);
9993 Fputhash (this_name, this_spec, Vcoding_system_hash_table); 9976 Fputhash (this_name, this_spec, Vcoding_system_hash_table);
@@ -10000,7 +9983,8 @@ usage: (define-coding-system-internal ...) */)
10000 } 9983 }
10001 } 9984 }
10002 9985
10003 spec_vec = Fmake_vector (make_number (3), attrs); 9986 spec_vec = make_uninit_vector (3);
9987 ASET (spec_vec, 0, attrs);
10004 ASET (spec_vec, 1, aliases); 9988 ASET (spec_vec, 1, aliases);
10005 ASET (spec_vec, 2, eol_type); 9989 ASET (spec_vec, 2, eol_type);
10006 9990
@@ -10405,10 +10389,8 @@ syms_of_coding (void)
10405 intern_c_string ("coding-category-undecided")); 10389 intern_c_string ("coding-category-undecided"));
10406 10390
10407 DEFSYM (Qinsufficient_source, "insufficient-source"); 10391 DEFSYM (Qinsufficient_source, "insufficient-source");
10408 DEFSYM (Qinconsistent_eol, "inconsistent-eol");
10409 DEFSYM (Qinvalid_source, "invalid-source"); 10392 DEFSYM (Qinvalid_source, "invalid-source");
10410 DEFSYM (Qinterrupted, "interrupted"); 10393 DEFSYM (Qinterrupted, "interrupted");
10411 DEFSYM (Qinsufficient_memory, "insufficient-memory");
10412 DEFSYM (Qcoding_system_define_form, "coding-system-define-form"); 10394 DEFSYM (Qcoding_system_define_form, "coding-system-define-form");
10413 10395
10414 defsubr (&Scoding_system_p); 10396 defsubr (&Scoding_system_p);
@@ -10709,7 +10691,7 @@ reading if you suppress escape sequence detection.
10709 10691
10710The other way to read escape sequences in a file without decoding is 10692The other way to read escape sequences in a file without decoding is
10711to explicitly specify some coding system that doesn't use ISO-2022 10693to explicitly specify some coding system that doesn't use ISO-2022
10712escape sequence (e.g `latin-1') on reading by \\[universal-coding-system-argument]. */); 10694escape sequence (e.g., `latin-1') on reading by \\[universal-coding-system-argument]. */);
10713 inhibit_iso_escape_detection = 0; 10695 inhibit_iso_escape_detection = 0;
10714 10696
10715 DEFVAR_BOOL ("inhibit-null-byte-detection", 10697 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
272 CODING_RESULT_SUCCESS, 272 CODING_RESULT_SUCCESS,
273 CODING_RESULT_INSUFFICIENT_SRC, 273 CODING_RESULT_INSUFFICIENT_SRC,
274 CODING_RESULT_INSUFFICIENT_DST, 274 CODING_RESULT_INSUFFICIENT_DST,
275 CODING_RESULT_INCONSISTENT_EOL,
276 CODING_RESULT_INVALID_SRC, 275 CODING_RESULT_INVALID_SRC,
277 CODING_RESULT_INTERRUPT, 276 CODING_RESULT_INTERRUPT
278 CODING_RESULT_INSUFFICIENT_MEM
279 }; 277 };
280 278
281 279
282/* Macros used for the member `mode' of the struct coding_system. */ 280/* Macros used for the member `mode' of the struct coding_system. */
283 281
284/* If set, recover the original CR or LF of the already decoded text
285 when the decoding routine encounters an inconsistent eol format. */
286#define CODING_MODE_INHIBIT_INCONSISTENT_EOL 0x01
287
288/* If set, the decoding/encoding routines treat the current data as 282/* If set, the decoding/encoding routines treat the current data as
289 the last block of the whole text to be converted, and do the 283 the last block of the whole text to be converted, and do the
290 appropriate finishing job. */ 284 appropriate finishing job. */
291#define CODING_MODE_LAST_BLOCK 0x02 285#define CODING_MODE_LAST_BLOCK 0x01
292 286
293/* If set, it means that the current source text is in a buffer which 287/* If set, it means that the current source text is in a buffer which
294 enables selective display. */ 288 enables selective display. */
295#define CODING_MODE_SELECTIVE_DISPLAY 0x04 289#define CODING_MODE_SELECTIVE_DISPLAY 0x02
296 290
297/* This flag is used by the decoding/encoding routines on the fly. If 291/* This flag is used by the decoding/encoding routines on the fly. If
298 set, it means that right-to-left text is being processed. */ 292 set, it means that right-to-left text is being processed. */
299#define CODING_MODE_DIRECTION 0x08 293#define CODING_MODE_DIRECTION 0x04
300 294
301#define CODING_MODE_FIXED_DESTINATION 0x10 295#define CODING_MODE_FIXED_DESTINATION 0x08
302 296
303/* If set, it means that the encoding routines produces some safe 297/* If set, it means that the encoding routines produces some safe
304 ASCII characters (usually '?') for unsupported characters. */ 298 ASCII characters (usually '?') for unsupported characters. */
305#define CODING_MODE_SAFE_ENCODING 0x20 299#define CODING_MODE_SAFE_ENCODING 0x10
306 300
307 /* For handling composition sequence. */ 301 /* For handling composition sequence. */
308#include "composite.h" 302#include "composite.h"
@@ -725,22 +719,6 @@ extern Lisp_Object from_unicode (Lisp_Object str);
725 719
726/* Macros for backward compatibility. */ 720/* Macros for backward compatibility. */
727 721
728#define decode_coding_region(coding, from, to) \
729 decode_coding_object (coding, Fcurrent_buffer (), \
730 from, CHAR_TO_BYTE (from), \
731 to, CHAR_TO_BYTE (to), Fcurrent_buffer ())
732
733
734#define encode_coding_region(coding, from, to) \
735 encode_coding_object (coding, Fcurrent_buffer (), \
736 from, CHAR_TO_BYTE (from), \
737 to, CHAR_TO_BYTE (to), Fcurrent_buffer ())
738
739
740#define decode_coding_string(coding, string, nocopy) \
741 decode_coding_object (coding, string, 0, 0, SCHARS (string), \
742 SBYTES (string), Qt)
743
744#define encode_coding_string(coding, string, nocopy) \ 722#define encode_coding_string(coding, string, nocopy) \
745 (STRING_MULTIBYTE(string) ? \ 723 (STRING_MULTIBYTE(string) ? \
746 (encode_coding_object (coding, string, 0, 0, SCHARS (string), \ 724 (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,
234 key = components; 234 key = components;
235 else if (NILP (components)) 235 else if (NILP (components))
236 { 236 {
237 key = Fmake_vector (make_number (nchars), Qnil); 237 key = make_uninit_vector (nchars);
238 if (STRINGP (string)) 238 if (STRINGP (string))
239 for (i = 0; i < nchars; i++) 239 for (i = 0; i < nchars; i++)
240 { 240 {
@@ -642,13 +642,7 @@ compose_text (ptrdiff_t start, ptrdiff_t end, Lisp_Object components,
642 Qcomposition, prop, string); 642 Qcomposition, prop, string);
643} 643}
644 644
645 645/* Lisp glyph-string handlers. */
646static Lisp_Object autocmp_chars (Lisp_Object, ptrdiff_t, ptrdiff_t,
647 ptrdiff_t, struct window *,
648 struct face *, Lisp_Object);
649
650
651/* Lisp glyph-string handlers */
652 646
653/* Hash table for automatic composition. The key is a header of a 647/* Hash table for automatic composition. The key is a header of a
654 lgstring (Lispy glyph-string), and the value is a body of a 648 lgstring (Lispy glyph-string), and the value is a body of a
@@ -704,10 +698,6 @@ composition_gstring_from_id (ptrdiff_t id)
704 return HASH_VALUE (h, id); 698 return HASH_VALUE (h, id);
705} 699}
706 700
707static Lisp_Object fill_gstring_header (Lisp_Object, Lisp_Object,
708 Lisp_Object, Lisp_Object,
709 Lisp_Object);
710
711bool 701bool
712composition_gstring_p (Lisp_Object gstring) 702composition_gstring_p (Lisp_Object gstring)
713{ 703{
@@ -797,7 +787,8 @@ static Lisp_Object gstring_work;
797static Lisp_Object gstring_work_headers; 787static Lisp_Object gstring_work_headers;
798 788
799static Lisp_Object 789static Lisp_Object
800fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lisp_Object font_object, Lisp_Object string) 790fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end,
791 Lisp_Object font_object, Lisp_Object string)
801{ 792{
802 ptrdiff_t from, to, from_byte; 793 ptrdiff_t from, to, from_byte;
803 ptrdiff_t len, i; 794 ptrdiff_t len, i;
@@ -837,7 +828,7 @@ fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lis
837 if (len <= 8) 828 if (len <= 8)
838 header = AREF (gstring_work_headers, len - 1); 829 header = AREF (gstring_work_headers, len - 1);
839 else 830 else
840 header = Fmake_vector (make_number (len + 1), Qnil); 831 header = make_uninit_vector (len + 1);
841 } 832 }
842 833
843 ASET (header, 0, font_object); 834 ASET (header, 0, font_object);
@@ -905,7 +896,9 @@ fill_gstring_body (Lisp_Object gstring)
905 object. Otherwise return nil. */ 896 object. Otherwise return nil. */
906 897
907static Lisp_Object 898static Lisp_Object
908autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t limit, struct window *win, struct face *face, Lisp_Object string) 899autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
900 ptrdiff_t limit, struct window *win, struct face *face,
901 Lisp_Object string)
909{ 902{
910 ptrdiff_t count = SPECPDL_INDEX (); 903 ptrdiff_t count = SPECPDL_INDEX ();
911 FRAME_PTR f = XFRAME (win->frame); 904 FRAME_PTR f = XFRAME (win->frame);
@@ -935,7 +928,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t
935#ifdef HAVE_WINDOW_SYSTEM 928#ifdef HAVE_WINDOW_SYSTEM
936 if (FRAME_WINDOW_P (f)) 929 if (FRAME_WINDOW_P (f))
937 { 930 {
938 font_object = font_range (charpos, &to, win, face, string); 931 font_object = font_range (charpos, bytepos, &to, win, face, string);
939 if (! FONT_OBJECT_P (font_object) 932 if (! FONT_OBJECT_P (font_object)
940 || (! NILP (re) 933 || (! NILP (re)
941 && to < limit 934 && to < limit
@@ -1958,7 +1951,7 @@ syms_of_composite (void)
1958 } 1951 }
1959 1952
1960 staticpro (&gstring_work_headers); 1953 staticpro (&gstring_work_headers);
1961 gstring_work_headers = Fmake_vector (make_number (8), Qnil); 1954 gstring_work_headers = make_uninit_vector (8);
1962 for (i = 0; i < 8; i++) 1955 for (i = 0; i < 8; i++)
1963 ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil)); 1956 ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil));
1964 staticpro (&gstring_work); 1957 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, ...);
182#endif 182#endif
183#endif 183#endif
184 184
185/* Tell gnulib to omit support for openat-related functions having a
186 first argument other than AT_FDCWD. */
187#define GNULIB_SUPPORT_ONLY_AT_FDCWD
188
189#include <string.h> 185#include <string.h>
190#include <stdlib.h> 186#include <stdlib.h>
191 187
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 \
144 dispextern.h lisp.h globals.h $(config_h) systime.h coding.h composite.h 144 dispextern.h lisp.h globals.h $(config_h) systime.h coding.h composite.h
145gmalloc.o: gmalloc.c $(config_h) 145gmalloc.o: gmalloc.c $(config_h)
146ralloc.o: ralloc.c lisp.h $(config_h) 146ralloc.o: ralloc.c lisp.h $(config_h)
147vm-limit.o: vm-limit.c mem-limits.h lisp.h globals.h $(config_h) 147vm-limit.o: vm-limit.c lisp.h globals.h $(config_h)
148marker.o: marker.c buffer.h character.h lisp.h globals.h $(config_h) 148marker.o: marker.c buffer.h character.h lisp.h globals.h $(config_h)
149minibuf.o: minibuf.c syntax.h frame.h window.h keyboard.h systime.h \ 149minibuf.o: minibuf.c syntax.h frame.h window.h keyboard.h systime.h \
150 buffer.h commands.h character.h msdos.h $(INTERVALS_H) keymap.h \ 150 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/>. */
30#include <grp.h> 30#include <grp.h>
31 31
32#include <errno.h> 32#include <errno.h>
33#include <fcntl.h>
33#include <unistd.h> 34#include <unistd.h>
34 35
35#include <dirent.h> 36#include <dirent.h>
@@ -54,6 +55,7 @@ static Lisp_Object Qfile_attributes;
54static Lisp_Object Qfile_attributes_lessp; 55static Lisp_Object Qfile_attributes_lessp;
55 56
56static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); 57static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
58static Lisp_Object file_attributes (int, char const *, Lisp_Object);
57 59
58/* Return the number of bytes in DP's name. */ 60/* Return the number of bytes in DP's name. */
59static ptrdiff_t 61static ptrdiff_t
@@ -66,6 +68,44 @@ dirent_namelen (struct dirent *dp)
66#endif 68#endif
67} 69}
68 70
71static DIR *
72open_directory (char const *name, int *fdp)
73{
74 DIR *d;
75 int fd, opendir_errno;
76
77 block_input ();
78
79#ifdef DOS_NT
80 /* Directories cannot be opened. The emulation assumes that any
81 file descriptor other than AT_FDCWD corresponds to the most
82 recently opened directory. This hack is good enough for Emacs. */
83 fd = 0;
84 d = opendir (name);
85 opendir_errno = errno;
86#else
87 fd = emacs_open (name, O_RDONLY | O_DIRECTORY, 0);
88 if (fd < 0)
89 {
90 opendir_errno = errno;
91 d = 0;
92 }
93 else
94 {
95 d = fdopendir (fd);
96 opendir_errno = errno;
97 if (! d)
98 close (fd);
99 }
100#endif
101
102 unblock_input ();
103
104 *fdp = fd;
105 errno = opendir_errno;
106 return d;
107}
108
69#ifdef WINDOWSNT 109#ifdef WINDOWSNT
70Lisp_Object 110Lisp_Object
71directory_files_internal_w32_unwind (Lisp_Object arg) 111directory_files_internal_w32_unwind (Lisp_Object arg)
@@ -96,6 +136,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
96 Lisp_Object id_format) 136 Lisp_Object id_format)
97{ 137{
98 DIR *d; 138 DIR *d;
139 int fd;
99 ptrdiff_t directory_nbytes; 140 ptrdiff_t directory_nbytes;
100 Lisp_Object list, dirfilename, encoded_directory; 141 Lisp_Object list, dirfilename, encoded_directory;
101 struct re_pattern_buffer *bufp = NULL; 142 struct re_pattern_buffer *bufp = NULL;
@@ -142,9 +183,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
142 /* Now *bufp is the compiled form of MATCH; don't call anything 183 /* Now *bufp is the compiled form of MATCH; don't call anything
143 which might compile a new regexp until we're done with the loop! */ 184 which might compile a new regexp until we're done with the loop! */
144 185
145 block_input (); 186 d = open_directory (SSDATA (dirfilename), &fd);
146 d = opendir (SSDATA (dirfilename));
147 unblock_input ();
148 if (d == NULL) 187 if (d == NULL)
149 report_file_error ("Opening directory", Fcons (directory, Qnil)); 188 report_file_error ("Opening directory", Fcons (directory, Qnil));
150 189
@@ -152,7 +191,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
152 file-attributes on filenames, both of which can throw, so we must 191 file-attributes on filenames, both of which can throw, so we must
153 do a proper unwind-protect. */ 192 do a proper unwind-protect. */
154 record_unwind_protect (directory_files_internal_unwind, 193 record_unwind_protect (directory_files_internal_unwind,
155 make_save_value (d, 0)); 194 make_save_pointer (d));
156 195
157#ifdef WINDOWSNT 196#ifdef WINDOWSNT
158 if (attrs) 197 if (attrs)
@@ -259,20 +298,9 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
259 298
260 if (attrs) 299 if (attrs)
261 { 300 {
262 /* Construct an expanded filename for the directory entry. 301 Lisp_Object fileattrs
263 Use the decoded names for input to Ffile_attributes. */ 302 = file_attributes (fd, dp->d_name, id_format);
264 Lisp_Object decoded_fullname, fileattrs;
265 struct gcpro gcpro1, gcpro2;
266
267 decoded_fullname = fileattrs = Qnil;
268 GCPRO2 (decoded_fullname, fileattrs);
269
270 /* Both Fexpand_file_name and Ffile_attributes can GC. */
271 decoded_fullname = Fexpand_file_name (name, directory);
272 fileattrs = Ffile_attributes (decoded_fullname, id_format);
273
274 list = Fcons (Fcons (finalname, fileattrs), list); 303 list = Fcons (Fcons (finalname, fileattrs), list);
275 UNGCPRO;
276 } 304 }
277 else 305 else
278 list = Fcons (finalname, list); 306 list = Fcons (finalname, list);
@@ -413,8 +441,7 @@ These are all file names in directory DIRECTORY which begin with FILE. */)
413 return file_name_completion (file, directory, 1, Qnil); 441 return file_name_completion (file, directory, 1, Qnil);
414} 442}
415 443
416static int file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, 444static int file_name_completion_stat (int, struct dirent *, struct stat *);
417 struct stat *st_addr);
418static Lisp_Object Qdefault_directory; 445static Lisp_Object Qdefault_directory;
419 446
420static Lisp_Object 447static Lisp_Object
@@ -422,6 +449,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
422 Lisp_Object predicate) 449 Lisp_Object predicate)
423{ 450{
424 DIR *d; 451 DIR *d;
452 int fd;
425 ptrdiff_t bestmatchsize = 0; 453 ptrdiff_t bestmatchsize = 0;
426 int matchcount = 0; 454 int matchcount = 0;
427 /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded. 455 /* 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,
456 on the encoded file name. */ 484 on the encoded file name. */
457 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; 485 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
458 486
459 encoded_dir = ENCODE_FILE (dirname); 487 encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname));
460 488
461 block_input (); 489 d = open_directory (SSDATA (encoded_dir), &fd);
462 d = opendir (SSDATA (Fdirectory_file_name (encoded_dir)));
463 unblock_input ();
464 if (!d) 490 if (!d)
465 report_file_error ("Opening directory", Fcons (dirname, Qnil)); 491 report_file_error ("Opening directory", Fcons (dirname, Qnil));
466 492
467 record_unwind_protect (directory_files_internal_unwind, 493 record_unwind_protect (directory_files_internal_unwind,
468 make_save_value (d, 0)); 494 make_save_pointer (d));
469 495
470 /* Loop reading blocks */ 496 /* Loop reading blocks */
471 /* (att3b compiler bug requires do a null comparison this way) */ 497 /* (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,
495 SCHARS (encoded_file))) 521 SCHARS (encoded_file)))
496 continue; 522 continue;
497 523
498 if (file_name_completion_stat (encoded_dir, dp, &st) < 0) 524 if (file_name_completion_stat (fd, dp, &st) < 0)
499 continue; 525 continue;
500 526
501 directoryp = S_ISDIR (st.st_mode) != 0; 527 directoryp = S_ISDIR (st.st_mode) != 0;
@@ -772,14 +798,9 @@ scmp (const char *s1, const char *s2, ptrdiff_t len)
772} 798}
773 799
774static int 800static int
775file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, 801file_name_completion_stat (int fd, struct dirent *dp, struct stat *st_addr)
776 struct stat *st_addr)
777{ 802{
778 ptrdiff_t len = dirent_namelen (dp);
779 ptrdiff_t pos = SCHARS (dirname);
780 int value; 803 int value;
781 USE_SAFE_ALLOCA;
782 char *fullname = SAFE_ALLOCA (len + pos + 2);
783 804
784#ifdef MSDOS 805#ifdef MSDOS
785 /* Some fields of struct stat are *very* expensive to compute on MS-DOS, 806 /* 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,
792 _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; 813 _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
793#endif /* MSDOS */ 814#endif /* MSDOS */
794 815
795 memcpy (fullname, SDATA (dirname), pos);
796 if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
797 fullname[pos++] = DIRECTORY_SEP;
798
799 memcpy (fullname + pos, dp->d_name, len);
800 fullname[pos + len] = 0;
801
802 /* We want to return success if a link points to a nonexistent file, 816 /* We want to return success if a link points to a nonexistent file,
803 but we want to return the status for what the link points to, 817 but we want to return the status for what the link points to,
804 in case it is a directory. */ 818 in case it is a directory. */
805 value = lstat (fullname, st_addr); 819 value = fstatat (fd, dp->d_name, st_addr, AT_SYMLINK_NOFOLLOW);
806 if (value == 0 && S_ISLNK (st_addr->st_mode)) 820 if (value == 0 && S_ISLNK (st_addr->st_mode))
807 stat (fullname, st_addr); 821 fstatat (fd, dp->d_name, st_addr, 0);
808#ifdef MSDOS 822#ifdef MSDOS
809 _djstat_flags = save_djstat_flags; 823 _djstat_flags = save_djstat_flags;
810#endif /* MSDOS */ 824#endif /* MSDOS */
811 SAFE_FREE ();
812 return value; 825 return value;
813} 826}
814 827
@@ -886,18 +899,8 @@ On some FAT-based filesystems, only the date of last access is recorded,
886so last access time will always be midnight of that day. */) 899so last access time will always be midnight of that day. */)
887 (Lisp_Object filename, Lisp_Object id_format) 900 (Lisp_Object filename, Lisp_Object id_format)
888{ 901{
889 Lisp_Object values[12];
890 Lisp_Object encoded; 902 Lisp_Object encoded;
891 struct stat s;
892 int lstat_result;
893
894 /* An array to hold the mode string generated by filemodestring,
895 including its terminating space and null byte. */
896 char modes[sizeof "-rwxr-xr-x "];
897
898 Lisp_Object handler; 903 Lisp_Object handler;
899 struct gcpro gcpro1;
900 char *uname = NULL, *gname = NULL;
901 904
902 filename = Fexpand_file_name (filename, Qnil); 905 filename = Fexpand_file_name (filename, Qnil);
903 906
@@ -913,9 +916,22 @@ so last access time will always be midnight of that day. */)
913 return call3 (handler, Qfile_attributes, filename, id_format); 916 return call3 (handler, Qfile_attributes, filename, id_format);
914 } 917 }
915 918
916 GCPRO1 (filename);
917 encoded = ENCODE_FILE (filename); 919 encoded = ENCODE_FILE (filename);
918 UNGCPRO; 920 return file_attributes (AT_FDCWD, SSDATA (encoded), id_format);
921}
922
923static Lisp_Object
924file_attributes (int fd, char const *name, Lisp_Object id_format)
925{
926 Lisp_Object values[12];
927 struct stat s;
928 int lstat_result;
929
930 /* An array to hold the mode string generated by filemodestring,
931 including its terminating space and null byte. */
932 char modes[sizeof "-rwxr-xr-x "];
933
934 char *uname = NULL, *gname = NULL;
919 935
920#ifdef WINDOWSNT 936#ifdef WINDOWSNT
921 /* We usually don't request accurate owner and group info, because 937 /* 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. */)
925 w32_stat_get_owner_group = 1; 941 w32_stat_get_owner_group = 1;
926#endif 942#endif
927 943
928 lstat_result = lstat (SSDATA (encoded), &s); 944 lstat_result = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW);
929 945
930#ifdef WINDOWSNT 946#ifdef WINDOWSNT
931 w32_stat_get_owner_group = 0; 947 w32_stat_get_owner_group = 0;
@@ -934,7 +950,7 @@ so last access time will always be midnight of that day. */)
934 if (lstat_result < 0) 950 if (lstat_result < 0)
935 return Qnil; 951 return Qnil;
936 952
937 values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename) 953 values[0] = (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name)
938 : S_ISDIR (s.st_mode) ? Qt : Qnil); 954 : S_ISDIR (s.st_mode) ? Qt : Qnil);
939 values[1] = make_number (s.st_nlink); 955 values[1] = make_number (s.st_nlink);
940 956
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 *,
87 struct window *); 87 struct window *);
88static void build_frame_matrix_from_leaf_window (struct glyph_matrix *, 88static void build_frame_matrix_from_leaf_window (struct glyph_matrix *,
89 struct window *); 89 struct window *);
90static void adjust_frame_message_buffer (struct frame *);
91static void adjust_decode_mode_spec_buffer (struct frame *); 90static void adjust_decode_mode_spec_buffer (struct frame *);
92static void fill_up_glyph_row_with_spaces (struct glyph_row *); 91static void fill_up_glyph_row_with_spaces (struct glyph_row *);
93static void clear_window_matrices (struct window *, bool); 92static void clear_window_matrices (struct window *, bool);
@@ -108,12 +107,6 @@ static void set_window_cursor_after_update (struct window *);
108static void adjust_frame_glyphs_for_window_redisplay (struct frame *); 107static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
109static void adjust_frame_glyphs_for_frame_redisplay (struct frame *); 108static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
110 109
111
112/* Redisplay preemption timers. */
113
114static EMACS_TIME preemption_period;
115static EMACS_TIME preemption_next_check;
116
117/* True upon entry to redisplay means do not assume anything about 110/* True upon entry to redisplay means do not assume anything about
118 current contents of actual terminal frame; clear and redraw it. */ 111 current contents of actual terminal frame; clear and redraw it. */
119 112
@@ -607,7 +600,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
607 are invalidated below. */ 600 are invalidated below. */
608 if (INTEGERP (w->window_end_vpos) 601 if (INTEGERP (w->window_end_vpos)
609 && XFASTINT (w->window_end_vpos) >= i) 602 && XFASTINT (w->window_end_vpos) >= i)
610 wset_window_end_valid (w, Qnil); 603 w->window_end_valid = 0;
611 604
612 while (i < matrix->nrows) 605 while (i < matrix->nrows)
613 matrix->rows[i++].enabled_p = 0; 606 matrix->rows[i++].enabled_p = 0;
@@ -862,7 +855,7 @@ clear_window_matrices (struct window *w, bool desired_p)
862 else 855 else
863 { 856 {
864 clear_glyph_matrix (w->current_matrix); 857 clear_glyph_matrix (w->current_matrix);
865 wset_window_end_valid (w, Qnil); 858 w->window_end_valid = 0;
866 } 859 }
867 } 860 }
868 861
@@ -1857,9 +1850,7 @@ adjust_frame_glyphs (struct frame *f)
1857 else 1850 else
1858 adjust_frame_glyphs_for_frame_redisplay (f); 1851 adjust_frame_glyphs_for_frame_redisplay (f);
1859 1852
1860 /* Don't forget the message buffer and the buffer for 1853 /* Don't forget the buffer for decode_mode_spec. */
1861 decode_mode_spec. */
1862 adjust_frame_message_buffer (f);
1863 adjust_decode_mode_spec_buffer (f); 1854 adjust_decode_mode_spec_buffer (f);
1864 1855
1865 f->glyphs_initialized_p = 1; 1856 f->glyphs_initialized_p = 1;
@@ -2159,23 +2150,6 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
2159} 2150}
2160 2151
2161 2152
2162/* Adjust/ allocate message buffer of frame F.
2163
2164 Note that the message buffer is never freed. Since I could not
2165 find a free in 19.34, I assume that freeing it would be
2166 problematic in some way and don't do it either.
2167
2168 (Implementation note: It should be checked if we can free it
2169 eventually without causing trouble). */
2170
2171static void
2172adjust_frame_message_buffer (struct frame *f)
2173{
2174 FRAME_MESSAGE_BUF (f) = xrealloc (FRAME_MESSAGE_BUF (f),
2175 FRAME_MESSAGE_BUF_SIZE (f) + 1);
2176}
2177
2178
2179/* Re-allocate buffer for decode_mode_spec on frame F. */ 2153/* Re-allocate buffer for decode_mode_spec on frame F. */
2180 2154
2181static void 2155static void
@@ -3100,21 +3074,10 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
3100 3074
3101 if (redisplay_dont_pause) 3075 if (redisplay_dont_pause)
3102 force_p = 1; 3076 force_p = 1;
3103 else if (NILP (Vredisplay_preemption_period)) 3077 else if (!force_p && detect_input_pending_ignore_squeezables ())
3104 force_p = 1;
3105 else if (!force_p && NUMBERP (Vredisplay_preemption_period))
3106 { 3078 {
3107 double p = XFLOATINT (Vredisplay_preemption_period); 3079 paused_p = 1;
3108 3080 goto do_pause;
3109 if (detect_input_pending_ignore_squeezables ())
3110 {
3111 paused_p = 1;
3112 goto do_pause;
3113 }
3114
3115 preemption_period = EMACS_TIME_FROM_DOUBLE (p);
3116 preemption_next_check = add_emacs_time (current_emacs_time (),
3117 preemption_period);
3118 } 3081 }
3119 3082
3120 if (FRAME_WINDOW_P (f)) 3083 if (FRAME_WINDOW_P (f))
@@ -3252,15 +3215,6 @@ update_single_window (struct window *w, bool force_p)
3252 3215
3253 if (redisplay_dont_pause) 3216 if (redisplay_dont_pause)
3254 force_p = 1; 3217 force_p = 1;
3255 else if (NILP (Vredisplay_preemption_period))
3256 force_p = 1;
3257 else if (!force_p && NUMBERP (Vredisplay_preemption_period))
3258 {
3259 double p = XFLOATINT (Vredisplay_preemption_period);
3260 preemption_period = EMACS_TIME_FROM_DOUBLE (p);
3261 preemption_next_check = add_emacs_time (current_emacs_time (),
3262 preemption_period);
3263 }
3264 3218
3265 /* Update W. */ 3219 /* Update W. */
3266 update_begin (f); 3220 update_begin (f);
@@ -3414,9 +3368,7 @@ update_window (struct window *w, bool force_p)
3414{ 3368{
3415 struct glyph_matrix *desired_matrix = w->desired_matrix; 3369 struct glyph_matrix *desired_matrix = w->desired_matrix;
3416 bool paused_p; 3370 bool paused_p;
3417#if !PERIODIC_PREEMPTION_CHECKING
3418 int preempt_count = baud_rate / 2400 + 1; 3371 int preempt_count = baud_rate / 2400 + 1;
3419#endif
3420 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3372 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3421#ifdef GLYPH_DEBUG 3373#ifdef GLYPH_DEBUG
3422 /* Check that W's frame doesn't have glyph matrices. */ 3374 /* Check that W's frame doesn't have glyph matrices. */
@@ -3424,10 +3376,8 @@ update_window (struct window *w, bool force_p)
3424#endif 3376#endif
3425 3377
3426 /* Check pending input the first time so that we can quickly return. */ 3378 /* Check pending input the first time so that we can quickly return. */
3427#if !PERIODIC_PREEMPTION_CHECKING
3428 if (!force_p) 3379 if (!force_p)
3429 detect_input_pending_ignore_squeezables (); 3380 detect_input_pending_ignore_squeezables ();
3430#endif
3431 3381
3432 /* If forced to complete the update, or if no input is pending, do 3382 /* If forced to complete the update, or if no input is pending, do
3433 the update. */ 3383 the update. */
@@ -3438,9 +3388,7 @@ update_window (struct window *w, bool force_p)
3438 struct glyph_row *header_line_row; 3388 struct glyph_row *header_line_row;
3439 int yb; 3389 int yb;
3440 bool changed_p = 0, mouse_face_overwritten_p = 0; 3390 bool changed_p = 0, mouse_face_overwritten_p = 0;
3441#if ! PERIODIC_PREEMPTION_CHECKING
3442 int n_updated = 0; 3391 int n_updated = 0;
3443#endif
3444 3392
3445 rif->update_window_begin_hook (w); 3393 rif->update_window_begin_hook (w);
3446 yb = window_text_bottom_y (w); 3394 yb = window_text_bottom_y (w);
@@ -3504,22 +3452,8 @@ update_window (struct window *w, bool force_p)
3504 detect_input_pending. If it's done too often, 3452 detect_input_pending. If it's done too often,
3505 scrolling large windows with repeated scroll-up 3453 scrolling large windows with repeated scroll-up
3506 commands will too quickly pause redisplay. */ 3454 commands will too quickly pause redisplay. */
3507#if PERIODIC_PREEMPTION_CHECKING
3508 if (!force_p)
3509 {
3510 EMACS_TIME tm = current_emacs_time ();
3511 if (EMACS_TIME_LT (preemption_next_check, tm))
3512 {
3513 preemption_next_check = add_emacs_time (tm,
3514 preemption_period);
3515 if (detect_input_pending_ignore_squeezables ())
3516 break;
3517 }
3518 }
3519#else
3520 if (!force_p && ++n_updated % preempt_count == 0) 3455 if (!force_p && ++n_updated % preempt_count == 0)
3521 detect_input_pending_ignore_squeezables (); 3456 detect_input_pending_ignore_squeezables ();
3522#endif
3523 changed_p |= update_window_line (w, vpos, 3457 changed_p |= update_window_line (w, vpos,
3524 &mouse_face_overwritten_p); 3458 &mouse_face_overwritten_p);
3525 3459
@@ -4551,13 +4485,11 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
4551 if (preempt_count <= 0) 4485 if (preempt_count <= 0)
4552 preempt_count = 1; 4486 preempt_count = 1;
4553 4487
4554#if !PERIODIC_PREEMPTION_CHECKING
4555 if (!force_p && detect_input_pending_ignore_squeezables ()) 4488 if (!force_p && detect_input_pending_ignore_squeezables ())
4556 { 4489 {
4557 pause_p = 1; 4490 pause_p = 1;
4558 goto do_pause; 4491 goto do_pause;
4559 } 4492 }
4560#endif
4561 4493
4562 /* If we cannot insert/delete lines, it's no use trying it. */ 4494 /* If we cannot insert/delete lines, it's no use trying it. */
4563 if (!FRAME_LINE_INS_DEL_OK (f)) 4495 if (!FRAME_LINE_INS_DEL_OK (f))
@@ -4598,21 +4530,8 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
4598 } 4530 }
4599 } 4531 }
4600 4532
4601#if PERIODIC_PREEMPTION_CHECKING
4602 if (!force_p)
4603 {
4604 EMACS_TIME tm = current_emacs_time ();
4605 if (EMACS_TIME_LT (preemption_next_check, tm))
4606 {
4607 preemption_next_check = add_emacs_time (tm, preemption_period);
4608 if (detect_input_pending_ignore_squeezables ())
4609 break;
4610 }
4611 }
4612#else
4613 if (!force_p && (i - 1) % preempt_count == 0) 4533 if (!force_p && (i - 1) % preempt_count == 0)
4614 detect_input_pending_ignore_squeezables (); 4534 detect_input_pending_ignore_squeezables ();
4615#endif
4616 4535
4617 update_frame_line (f, i); 4536 update_frame_line (f, i);
4618 } 4537 }
@@ -4718,9 +4637,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
4718 } 4637 }
4719 } 4638 }
4720 4639
4721#if !PERIODIC_PREEMPTION_CHECKING
4722 do_pause: 4640 do_pause:
4723#endif
4724 4641
4725 clear_desired_matrices (f); 4642 clear_desired_matrices (f);
4726 return pause_p; 4643 return pause_p;
@@ -6097,7 +6014,6 @@ init_display (void)
6097 6014
6098 inverse_video = 0; 6015 inverse_video = 0;
6099 cursor_in_echo_area = 0; 6016 cursor_in_echo_area = 0;
6100 terminal_type = (char *) 0;
6101 6017
6102 /* Now is the time to initialize this; it's used by init_sys_modes 6018 /* Now is the time to initialize this; it's used by init_sys_modes
6103 during startup. */ 6019 during startup. */
@@ -6192,8 +6108,7 @@ init_display (void)
6192#ifdef WINDOWSNT 6108#ifdef WINDOWSNT
6193 terminal_type = "w32console"; 6109 terminal_type = "w32console";
6194#else 6110#else
6195 /* Look at the TERM variable. */ 6111 terminal_type = getenv ("TERM");
6196 terminal_type = (char *) getenv ("TERM");
6197#endif 6112#endif
6198 if (!terminal_type) 6113 if (!terminal_type)
6199 { 6114 {
@@ -6430,15 +6345,6 @@ See `buffer-display-table' for more information. */);
6430 doc: /* Non-nil means display update isn't paused when input is detected. */); 6345 doc: /* Non-nil means display update isn't paused when input is detected. */);
6431 redisplay_dont_pause = 1; 6346 redisplay_dont_pause = 1;
6432 6347
6433#if PERIODIC_PREEMPTION_CHECKING
6434 DEFVAR_LISP ("redisplay-preemption-period", Vredisplay_preemption_period,
6435 doc: /* Period in seconds between checking for input during redisplay.
6436This has an effect only if `redisplay-dont-pause' is nil; in that
6437case, arriving input preempts redisplay until the input is processed.
6438If the value is nil, redisplay is never preempted. */);
6439 Vredisplay_preemption_period = make_float (0.10);
6440#endif
6441
6442#ifdef CANNOT_DUMP 6348#ifdef CANNOT_DUMP
6443 if (noninteractive) 6349 if (noninteractive)
6444#endif 6350#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)
176 if (space_left <= 0) 176 if (space_left <= 0)
177 { 177 {
178 ptrdiff_t in_buffer = p - get_doc_string_buffer; 178 ptrdiff_t in_buffer = p - get_doc_string_buffer;
179 get_doc_string_buffer = 179 get_doc_string_buffer
180 xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size, 180 = xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size,
181 16 * 1024, -1, 1); 181 16 * 1024, -1, 1);
182 p = get_doc_string_buffer + in_buffer; 182 p = get_doc_string_buffer + in_buffer;
183 space_left = (get_doc_string_buffer_size - 1 183 space_left = (get_doc_string_buffer_size - 1
184 - (p - get_doc_string_buffer)); 184 - (p - get_doc_string_buffer));
@@ -279,10 +279,10 @@ Invalid data in documentation file -- %c followed by code %03o",
279 else 279 else
280 { 280 {
281 /* The data determines whether the string is multibyte. */ 281 /* The data determines whether the string is multibyte. */
282 ptrdiff_t nchars = 282 ptrdiff_t nchars
283 multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer 283 = multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer
284 + offset), 284 + offset),
285 to - (get_doc_string_buffer + offset)); 285 to - (get_doc_string_buffer + offset));
286 return make_string_from_bytes (get_doc_string_buffer + offset, 286 return make_string_from_bytes (get_doc_string_buffer + offset,
287 nchars, 287 nchars,
288 to - (get_doc_string_buffer + offset)); 288 to - (get_doc_string_buffer + offset));
@@ -630,11 +630,10 @@ the same file name is found in the `doc-directory'. */)
630 break; 630 break;
631 631
632 buf[filled] = 0; 632 buf[filled] = 0;
633 p = buf;
634 end = buf + (filled < 512 ? filled : filled - 128); 633 end = buf + (filled < 512 ? filled : filled - 128);
635 while (p != end && *p != '\037') p++; 634 p = memchr (buf, '\037', end - buf);
636 /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */ 635 /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */
637 if (p != end) 636 if (p)
638 { 637 {
639 end = strchr (p, '\n'); 638 end = strchr (p, '\n');
640 639
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/>. */
38 could include embedded null characters. 38 could include embedded null characters.
39 39
40 . It signals an error if the length of the formatted string is about to 40 . It signals an error if the length of the formatted string is about to
41 overflow MOST_POSITIVE_FIXNUM, to avoid producing strings longer than what 41 overflow ptrdiff_t or size_t, to avoid producing strings longer than what
42 Emacs can handle. 42 Emacs can handle.
43 43
44 OTOH, this function supports only a small subset of the standard C formatted 44 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
386 ptrdiff_t noverlays; 386 ptrdiff_t noverlays;
387 Lisp_Object *overlay_vec, tem; 387 Lisp_Object *overlay_vec, tem;
388 struct buffer *obuf = current_buffer; 388 struct buffer *obuf = current_buffer;
389 USE_SAFE_ALLOCA;
389 390
390 set_buffer_temp (XBUFFER (object)); 391 set_buffer_temp (XBUFFER (object));
391 392
@@ -398,7 +399,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o
398 make enough space for all, and try again. */ 399 make enough space for all, and try again. */
399 if (noverlays > 40) 400 if (noverlays > 40)
400 { 401 {
401 overlay_vec = alloca (noverlays * sizeof *overlay_vec); 402 SAFE_ALLOCA_LISP (overlay_vec, noverlays);
402 noverlays = overlays_around (posn, overlay_vec, noverlays); 403 noverlays = overlays_around (posn, overlay_vec, noverlays);
403 } 404 }
404 noverlays = sort_overlays (overlay_vec, noverlays, NULL); 405 noverlays = sort_overlays (overlay_vec, noverlays, NULL);
@@ -421,10 +422,12 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o
421 ; /* The overlay will not cover a char inserted at point. */ 422 ; /* The overlay will not cover a char inserted at point. */
422 else 423 else
423 { 424 {
425 SAFE_FREE ();
424 return tem; 426 return tem;
425 } 427 }
426 } 428 }
427 } 429 }
430 SAFE_FREE ();
428 431
429 { /* Now check the text properties. */ 432 { /* Now check the text properties. */
430 int stickiness = text_property_stickiness (prop, position, object); 433 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
666a non-nil property of that name, then any field boundaries are ignored. 669a non-nil property of that name, then any field boundaries are ignored.
667 670
668Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) 671Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */)
669 (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, Lisp_Object only_in_line, Lisp_Object inhibit_capture_property) 672 (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge,
673 Lisp_Object only_in_line, Lisp_Object inhibit_capture_property)
670{ 674{
671 /* If non-zero, then the original point, before re-positioning. */ 675 /* If non-zero, then the original point, before re-positioning. */
672 ptrdiff_t orig_point = 0; 676 ptrdiff_t orig_point = 0;
@@ -732,9 +736,9 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */)
732 /* This is the ONLY_IN_LINE case, check that NEW_POS and 736 /* This is the ONLY_IN_LINE case, check that NEW_POS and
733 FIELD_BOUND are on the same line by seeing whether 737 FIELD_BOUND are on the same line by seeing whether
734 there's an intervening newline or not. */ 738 there's an intervening newline or not. */
735 || (scan_buffer ('\n', 739 || (find_newline (XFASTINT (new_pos), -1,
736 XFASTINT (new_pos), XFASTINT (field_bound), 740 XFASTINT (field_bound), -1,
737 fwd ? -1 : 1, &shortage, 1), 741 fwd ? -1 : 1, &shortage, NULL, 1),
738 shortage != 0))) 742 shortage != 0)))
739 /* Constrain NEW_POS to FIELD_BOUND. */ 743 /* Constrain NEW_POS to FIELD_BOUND. */
740 new_pos = field_bound; 744 new_pos = field_bound;
@@ -819,7 +823,8 @@ This function does not move point. */)
819 CHECK_NUMBER (n); 823 CHECK_NUMBER (n);
820 824
821 clipped_n = clip_to_bounds (PTRDIFF_MIN + 1, XINT (n), PTRDIFF_MAX); 825 clipped_n = clip_to_bounds (PTRDIFF_MIN + 1, XINT (n), PTRDIFF_MAX);
822 end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0)); 826 end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0),
827 NULL);
823 828
824 /* Return END_POS constrained to the current input field. */ 829 /* Return END_POS constrained to the current input field. */
825 return Fconstrain_to_field (make_number (end_pos), make_number (orig), 830 return Fconstrain_to_field (make_number (end_pos), make_number (orig),
@@ -833,7 +838,7 @@ This function does not move point. */)
833Lisp_Object 838Lisp_Object
834save_excursion_save (void) 839save_excursion_save (void)
835{ 840{
836 return format_save_value 841 return make_save_value
837 ("oooo", 842 ("oooo",
838 Fpoint_marker (), 843 Fpoint_marker (),
839 /* Do not copy the mark if it points to nowhere. */ 844 /* Do not copy the mark if it points to nowhere. */
@@ -1481,9 +1486,7 @@ Lisp_Object
1481make_lisp_time (EMACS_TIME t) 1486make_lisp_time (EMACS_TIME t)
1482{ 1487{
1483 int ns = EMACS_NSECS (t); 1488 int ns = EMACS_NSECS (t);
1484 return make_time_tail (EMACS_SECS (t), 1489 return make_time_tail (EMACS_SECS (t), list2i (ns / 1000, ns % 1000 * 1000));
1485 list2 (make_number (ns / 1000),
1486 make_number (ns % 1000 * 1000)));
1487} 1490}
1488 1491
1489/* Decode a Lisp list SPECIFIED_TIME that represents a time. 1492/* Decode a Lisp list SPECIFIED_TIME that represents a time.
@@ -3426,12 +3429,6 @@ usage: (save-restriction &rest BODY) */)
3426 return unbind_to (count, val); 3429 return unbind_to (count, val);
3427} 3430}
3428 3431
3429/* Buffer for the most recent text displayed by Fmessage_box. */
3430static char *message_text;
3431
3432/* Allocated length of that buffer. */
3433static ptrdiff_t message_length;
3434
3435DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, 3432DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
3436 doc: /* Display a message at the bottom of the screen. 3433 doc: /* Display a message at the bottom of the screen.
3437The message also goes into the `*Messages*' buffer, if `message-log-max' 3434The message also goes into the `*Messages*' buffer, if `message-log-max'
@@ -3455,14 +3452,14 @@ usage: (message FORMAT-STRING &rest ARGS) */)
3455 || (STRINGP (args[0]) 3452 || (STRINGP (args[0])
3456 && SBYTES (args[0]) == 0)) 3453 && SBYTES (args[0]) == 0))
3457 { 3454 {
3458 message (0); 3455 message1 (0);
3459 return args[0]; 3456 return args[0];
3460 } 3457 }
3461 else 3458 else
3462 { 3459 {
3463 register Lisp_Object val; 3460 register Lisp_Object val;
3464 val = Fformat (nargs, args); 3461 val = Fformat (nargs, args);
3465 message3 (val, SBYTES (val), STRING_MULTIBYTE (val)); 3462 message3 (val);
3466 return val; 3463 return val;
3467 } 3464 }
3468} 3465}
@@ -3481,13 +3478,12 @@ usage: (message-box FORMAT-STRING &rest ARGS) */)
3481{ 3478{
3482 if (NILP (args[0])) 3479 if (NILP (args[0]))
3483 { 3480 {
3484 message (0); 3481 message1 (0);
3485 return Qnil; 3482 return Qnil;
3486 } 3483 }
3487 else 3484 else
3488 { 3485 {
3489 register Lisp_Object val; 3486 Lisp_Object val = Fformat (nargs, args);
3490 val = Fformat (nargs, args);
3491#ifdef HAVE_MENUS 3487#ifdef HAVE_MENUS
3492 /* The MS-DOS frames support popup menus even though they are 3488 /* The MS-DOS frames support popup menus even though they are
3493 not FRAME_WINDOW_P. */ 3489 not FRAME_WINDOW_P. */
@@ -3504,16 +3500,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */)
3504 return val; 3500 return val;
3505 } 3501 }
3506#endif /* HAVE_MENUS */ 3502#endif /* HAVE_MENUS */
3507 /* Copy the data so that it won't move when we GC. */ 3503 message3 (val);
3508 if (SBYTES (val) > message_length)
3509 {
3510 ptrdiff_t new_length = SBYTES (val) + 80;
3511 message_text = xrealloc (message_text, new_length);
3512 message_length = new_length;
3513 }
3514 memcpy (message_text, SDATA (val), SBYTES (val));
3515 message2 (message_text, SBYTES (val),
3516 STRING_MULTIBYTE (val));
3517 return val; 3504 return val;
3518 } 3505 }
3519} 3506}
@@ -4249,7 +4236,7 @@ usage: (format STRING &rest OBJECTS) */)
4249 { 4236 {
4250 buf = xmalloc (bufsize); 4237 buf = xmalloc (bufsize);
4251 sa_must_free = 1; 4238 sa_must_free = 1;
4252 buf_save_value = make_save_value (buf, 0); 4239 buf_save_value = make_save_pointer (buf);
4253 record_unwind_protect (safe_alloca_unwind, buf_save_value); 4240 record_unwind_protect (safe_alloca_unwind, buf_save_value);
4254 memcpy (buf, initial_buffer, used); 4241 memcpy (buf, initial_buffer, used);
4255 } 4242 }
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;
134Lisp_Object Qrisky_local_variable; 134Lisp_Object Qrisky_local_variable;
135 135
136Lisp_Object Qkill_emacs; 136Lisp_Object Qkill_emacs;
137static Lisp_Object Qkill_emacs_hook;
137 138
138/* If true, Emacs should not attempt to use a window-specific code, 139/* If true, Emacs should not attempt to use a window-specific code,
139 but instead should use the virtual terminal under which it was started. */ 140 but instead should use the virtual terminal under which it was started. */
@@ -516,32 +517,6 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
516static char const dump_tz[] = "UtC0"; 517static char const dump_tz[] = "UtC0";
517#endif 518#endif
518 519
519#ifndef ORDINARY_LINK
520/* We don't include crtbegin.o and crtend.o in the link,
521 so these functions and variables might be missed.
522 Provide dummy definitions to avoid error.
523 (We don't have any real constructors or destructors.) */
524#ifdef __GNUC__
525
526/* Define a dummy function F. Declare F too, to pacify gcc
527 -Wmissing-prototypes. */
528#define DEFINE_DUMMY_FUNCTION(f) \
529 void f (void) ATTRIBUTE_CONST EXTERNALLY_VISIBLE; void f (void) {}
530
531#ifndef GCC_CTORS_IN_LIBC
532DEFINE_DUMMY_FUNCTION (__do_global_ctors)
533DEFINE_DUMMY_FUNCTION (__do_global_ctors_aux)
534DEFINE_DUMMY_FUNCTION (__do_global_dtors)
535/* GNU/Linux has a bug in its library; avoid an error. */
536#ifndef GNU_LINUX
537char * __CTOR_LIST__[2] EXTERNALLY_VISIBLE = { (char *) (-1), 0 };
538#endif
539char * __DTOR_LIST__[2] EXTERNALLY_VISIBLE = { (char *) (-1), 0 };
540#endif /* GCC_CTORS_IN_LIBC */
541DEFINE_DUMMY_FUNCTION (__main)
542#endif /* __GNUC__ */
543#endif /* ORDINARY_LINK */
544
545/* Test whether the next argument in ARGV matches SSTR or a prefix of 520/* Test whether the next argument in ARGV matches SSTR or a prefix of
546 LSTR (at least MINLEN characters). If so, then if VALPTR is non-null 521 LSTR (at least MINLEN characters). If so, then if VALPTR is non-null
547 (the argument is supposed to have a value) store in *VALPTR either 522 (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
1047 1022
1048 argv[skip_args] = fdStr; 1023 argv[skip_args] = fdStr;
1049 1024
1050 execv (argv[0], argv); 1025 execvp (argv[0], argv);
1051 fprintf (stderr, "emacs daemon: exec failed: %d\n", errno); 1026 fprintf (stderr, "emacs daemon: exec failed: %d\n", errno);
1052 exit (1); 1027 exit (1);
1053 } 1028 }
@@ -1308,6 +1283,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1308 } 1283 }
1309 1284
1310 init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ 1285 init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */
1286 init_fileio ();
1311 init_lread (); 1287 init_lread ();
1312#ifdef WINDOWSNT 1288#ifdef WINDOWSNT
1313 /* Check to see if Emacs has been installed correctly. */ 1289 /* Check to see if Emacs has been installed correctly. */
@@ -1832,7 +1808,6 @@ all of which are called before Emacs is actually killed. */)
1832 (Lisp_Object arg) 1808 (Lisp_Object arg)
1833{ 1809{
1834 struct gcpro gcpro1; 1810 struct gcpro gcpro1;
1835 Lisp_Object hook;
1836 int exit_code; 1811 int exit_code;
1837 1812
1838 GCPRO1 (arg); 1813 GCPRO1 (arg);
@@ -1840,9 +1815,10 @@ all of which are called before Emacs is actually killed. */)
1840 if (feof (stdin)) 1815 if (feof (stdin))
1841 arg = Qt; 1816 arg = Qt;
1842 1817
1843 hook = intern ("kill-emacs-hook"); 1818 /* Fsignal calls emacs_abort () if it sees that waiting_for_input is
1844 Frun_hooks (1, &hook); 1819 set. */
1845 1820 waiting_for_input = 0;
1821 Frun_hooks (1, &Qkill_emacs_hook);
1846 UNGCPRO; 1822 UNGCPRO;
1847 1823
1848#ifdef HAVE_X_WINDOWS 1824#ifdef HAVE_X_WINDOWS
@@ -2142,7 +2118,7 @@ decode_env_path (const char *evarname, const char *defalt)
2142 { 2118 {
2143 char *path_copy = alloca (strlen (path) + 1); 2119 char *path_copy = alloca (strlen (path) + 1);
2144 strcpy (path_copy, path); 2120 strcpy (path_copy, path);
2145 dostounix_filename (path_copy); 2121 dostounix_filename (path_copy, 0);
2146 path = path_copy; 2122 path = path_copy;
2147 } 2123 }
2148#endif 2124#endif
@@ -2254,6 +2230,7 @@ syms_of_emacs (void)
2254 DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist"); 2230 DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist");
2255 DEFSYM (Qrisky_local_variable, "risky-local-variable"); 2231 DEFSYM (Qrisky_local_variable, "risky-local-variable");
2256 DEFSYM (Qkill_emacs, "kill-emacs"); 2232 DEFSYM (Qkill_emacs, "kill-emacs");
2233 DEFSYM (Qkill_emacs_hook, "kill-emacs-hook");
2257 2234
2258#ifndef CANNOT_DUMP 2235#ifndef CANNOT_DUMP
2259 defsubr (&Sdump_emacs); 2236 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. */)
1917{ 1917{
1918 ptrdiff_t count = SPECPDL_INDEX (); 1918 ptrdiff_t count = SPECPDL_INDEX ();
1919 specbind (Qinternal_interpreter_environment, 1919 specbind (Qinternal_interpreter_environment,
1920 NILP (lexical) ? Qnil : Fcons (Qt, Qnil)); 1920 CONSP (lexical) || NILP (lexical) ? lexical : Fcons (Qt, Qnil));
1921 return unbind_to (count, eval_sub (form)); 1921 return unbind_to (count, eval_sub (form));
1922} 1922}
1923 1923
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/>. */
82#endif 82#endif
83 83
84#include "systime.h" 84#include "systime.h"
85#include <allocator.h>
86#include <careadlinkat.h>
85#include <stat-time.h> 87#include <stat-time.h>
86 88
87#ifdef HPUX 89#ifdef HPUX
@@ -103,6 +105,11 @@ static mode_t auto_save_mode_bits;
103/* Set by auto_save_1 if an error occurred during the last auto-save. */ 105/* Set by auto_save_1 if an error occurred during the last auto-save. */
104static bool auto_save_error_occurred; 106static bool auto_save_error_occurred;
105 107
108/* If VALID_TIMESTAMP_FILE_SYSTEM, then TIMESTAMP_FILE_SYSTEM is the device
109 number of a file system where time stamps were observed to to work. */
110static bool valid_timestamp_file_system;
111static dev_t timestamp_file_system;
112
106/* The symbol bound to coding-system-for-read when 113/* The symbol bound to coding-system-for-read when
107 insert-file-contents is called for recovering a file. This is not 114 insert-file-contents is called for recovering a file. This is not
108 an actual coding system name, but just an indicator to tell 115 an actual coding system name, but just an indicator to tell
@@ -126,9 +133,6 @@ static Lisp_Object Qwrite_region_annotate_functions;
126 is added here. */ 133 is added here. */
127static Lisp_Object Vwrite_region_annotation_buffers; 134static Lisp_Object Vwrite_region_annotation_buffers;
128 135
129#ifdef HAVE_FSYNC
130#endif
131
132static Lisp_Object Qdelete_by_moving_to_trash; 136static Lisp_Object Qdelete_by_moving_to_trash;
133 137
134/* Lisp function for moving files to trash. */ 138/* Lisp function for moving files to trash. */
@@ -244,6 +248,7 @@ static Lisp_Object Qfile_acl;
244static Lisp_Object Qset_file_acl; 248static Lisp_Object Qset_file_acl;
245static Lisp_Object Qfile_newer_than_file_p; 249static Lisp_Object Qfile_newer_than_file_p;
246Lisp_Object Qinsert_file_contents; 250Lisp_Object Qinsert_file_contents;
251static Lisp_Object Qchoose_write_coding_system;
247Lisp_Object Qwrite_region; 252Lisp_Object Qwrite_region;
248static Lisp_Object Qverify_visited_file_modtime; 253static Lisp_Object Qverify_visited_file_modtime;
249static Lisp_Object Qset_visited_file_modtime; 254static Lisp_Object Qset_visited_file_modtime;
@@ -375,11 +380,13 @@ Given a Unix syntax file name, returns a string ending in slash. */)
375 380
376 if (getdefdir (c_toupper (*beg) - 'A' + 1, r)) 381 if (getdefdir (c_toupper (*beg) - 'A' + 1, r))
377 { 382 {
378 if (!IS_DIRECTORY_SEP (res[strlen (res) - 1])) 383 size_t l = strlen (res);
384
385 if (l > 3 || !IS_DIRECTORY_SEP (res[l - 1]))
379 strcat (res, "/"); 386 strcat (res, "/");
380 beg = res; 387 beg = res;
381 p = beg + strlen (beg); 388 p = beg + strlen (beg);
382 dostounix_filename (beg); 389 dostounix_filename (beg, 0);
383 tem_fn = make_specified_string (beg, -1, p - beg, 390 tem_fn = make_specified_string (beg, -1, p - beg,
384 STRING_MULTIBYTE (filename)); 391 STRING_MULTIBYTE (filename));
385 } 392 }
@@ -389,13 +396,16 @@ Given a Unix syntax file name, returns a string ending in slash. */)
389 } 396 }
390 else if (STRING_MULTIBYTE (filename)) 397 else if (STRING_MULTIBYTE (filename))
391 { 398 {
392 tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1)); 399 tem_fn = make_specified_string (beg, -1, p - beg, 1);
393 dostounix_filename (SSDATA (tem_fn)); 400 dostounix_filename (SSDATA (tem_fn), 1);
394 tem_fn = DECODE_FILE (tem_fn); 401#ifdef WINDOWSNT
402 if (!NILP (Vw32_downcase_file_names))
403 tem_fn = Fdowncase (tem_fn);
404#endif
395 } 405 }
396 else 406 else
397 { 407 {
398 dostounix_filename (beg); 408 dostounix_filename (beg, 0);
399 tem_fn = make_specified_string (beg, -1, p - beg, 0); 409 tem_fn = make_specified_string (beg, -1, p - beg, 0);
400 } 410 }
401 return tem_fn; 411 return tem_fn;
@@ -499,17 +509,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
499 srclen++; 509 srclen++;
500 } 510 }
501#ifdef DOS_NT 511#ifdef DOS_NT
502 if (multibyte) 512 dostounix_filename (dst, multibyte);
503 {
504 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
505
506 tem_fn = ENCODE_FILE (tem_fn);
507 dostounix_filename (SSDATA (tem_fn));
508 tem_fn = DECODE_FILE (tem_fn);
509 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
510 }
511 else
512 dostounix_filename (dst);
513#endif 513#endif
514 return srclen; 514 return srclen;
515} 515}
@@ -544,6 +544,10 @@ For a Unix-syntax file name, just appends a slash. */)
544 error ("Invalid handler in `file-name-handler-alist'"); 544 error ("Invalid handler in `file-name-handler-alist'");
545 } 545 }
546 546
547#ifdef WINDOWSNT
548 if (!NILP (Vw32_downcase_file_names))
549 file = Fdowncase (file);
550#endif
547 buf = alloca (SBYTES (file) + 10); 551 buf = alloca (SBYTES (file) + 10);
548 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), 552 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
549 STRING_MULTIBYTE (file)); 553 STRING_MULTIBYTE (file));
@@ -572,17 +576,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
572 srclen--; 576 srclen--;
573 } 577 }
574#ifdef DOS_NT 578#ifdef DOS_NT
575 if (multibyte) 579 dostounix_filename (dst, multibyte);
576 {
577 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
578
579 tem_fn = ENCODE_FILE (tem_fn);
580 dostounix_filename (SSDATA (tem_fn));
581 tem_fn = DECODE_FILE (tem_fn);
582 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
583 }
584 else
585 dostounix_filename (dst);
586#endif 580#endif
587 return srclen; 581 return srclen;
588} 582}
@@ -617,6 +611,10 @@ In Unix-syntax, this function just removes the final slash. */)
617 error ("Invalid handler in `file-name-handler-alist'"); 611 error ("Invalid handler in `file-name-handler-alist'");
618 } 612 }
619 613
614#ifdef WINDOWSNT
615 if (!NILP (Vw32_downcase_file_names))
616 directory = Fdowncase (directory);
617#endif
620 buf = alloca (SBYTES (directory) + 20); 618 buf = alloca (SBYTES (directory) + 20);
621 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), 619 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
622 STRING_MULTIBYTE (directory)); 620 STRING_MULTIBYTE (directory));
@@ -917,6 +915,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
917 } 915 }
918 } 916 }
919 917
918#ifdef WINDOWSNT
919 if (!NILP (Vw32_downcase_file_names))
920 default_directory = Fdowncase (default_directory);
921#endif
922
920 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ 923 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */
921 nm = alloca (SBYTES (name) + 1); 924 nm = alloca (SBYTES (name) + 1);
922 memcpy (nm, SSDATA (name), SBYTES (name) + 1); 925 memcpy (nm, SSDATA (name), SBYTES (name) + 1);
@@ -1000,18 +1003,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1000#ifdef DOS_NT 1003#ifdef DOS_NT
1001 /* Make sure directories are all separated with /, but 1004 /* Make sure directories are all separated with /, but
1002 avoid allocation of a new string when not required. */ 1005 avoid allocation of a new string when not required. */
1003 if (multibyte) 1006 dostounix_filename (nm, multibyte);
1004 {
1005 Lisp_Object tem_name = make_specified_string (nm, -1, strlen (nm),
1006 multibyte);
1007
1008 tem_name = ENCODE_FILE (tem_name);
1009 dostounix_filename (SSDATA (tem_name));
1010 tem_name = DECODE_FILE (tem_name);
1011 memcpy (nm, SSDATA (tem_name), SBYTES (tem_name) + 1);
1012 }
1013 else
1014 dostounix_filename (nm);
1015#ifdef WINDOWSNT 1007#ifdef WINDOWSNT
1016 if (IS_DIRECTORY_SEP (nm[1])) 1008 if (IS_DIRECTORY_SEP (nm[1]))
1017 { 1009 {
@@ -1029,6 +1021,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1029 temp[0] = DRIVE_LETTER (drive); 1021 temp[0] = DRIVE_LETTER (drive);
1030 name = concat2 (build_string (temp), name); 1022 name = concat2 (build_string (temp), name);
1031 } 1023 }
1024#ifdef WINDOWSNT
1025 if (!NILP (Vw32_downcase_file_names))
1026 name = Fdowncase (name);
1027#endif
1032 return name; 1028 return name;
1033#else /* not DOS_NT */ 1029#else /* not DOS_NT */
1034 if (strcmp (nm, SSDATA (name)) == 0) 1030 if (strcmp (nm, SSDATA (name)) == 0)
@@ -1349,8 +1345,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1349#ifdef WINDOWSNT 1345#ifdef WINDOWSNT
1350 char *prev_o = o; 1346 char *prev_o = o;
1351#endif 1347#endif
1352 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) 1348 while (o != target && (--o, !IS_DIRECTORY_SEP (*o)))
1353 ; 1349 continue;
1354#ifdef WINDOWSNT 1350#ifdef WINDOWSNT
1355 /* Don't go below server level in UNC filenames. */ 1351 /* Don't go below server level in UNC filenames. */
1356 if (o == target + 1 && IS_DIRECTORY_SEP (*o) 1352 if (o == target + 1 && IS_DIRECTORY_SEP (*o)
@@ -1392,14 +1388,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1392 target[1] = ':'; 1388 target[1] = ':';
1393 } 1389 }
1394 result = make_specified_string (target, -1, o - target, multibyte); 1390 result = make_specified_string (target, -1, o - target, multibyte);
1395 if (multibyte) 1391 dostounix_filename (SSDATA (result), multibyte);
1396 { 1392#ifdef WINDOWSNT
1397 result = ENCODE_FILE (result); 1393 if (!NILP (Vw32_downcase_file_names))
1398 dostounix_filename (SSDATA (result)); 1394 result = Fdowncase (result);
1399 result = DECODE_FILE (result); 1395#endif
1400 }
1401 else
1402 dostounix_filename (SSDATA (result));
1403#else /* !DOS_NT */ 1396#else /* !DOS_NT */
1404 result = make_specified_string (target, -1, o - target, multibyte); 1397 result = make_specified_string (target, -1, o - target, multibyte);
1405#endif /* !DOS_NT */ 1398#endif /* !DOS_NT */
@@ -1681,24 +1674,8 @@ those `/' is discarded. */)
1681 memcpy (nm, SDATA (filename), SBYTES (filename) + 1); 1674 memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
1682 1675
1683#ifdef DOS_NT 1676#ifdef DOS_NT
1684 if (multibyte) 1677 dostounix_filename (nm, multibyte);
1685 { 1678 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1686 Lisp_Object encoded_filename = ENCODE_FILE (filename);
1687 Lisp_Object tem_fn;
1688
1689 dostounix_filename (SDATA (encoded_filename));
1690 tem_fn = DECODE_FILE (encoded_filename);
1691 nm = alloca (SBYTES (tem_fn) + 1);
1692 memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
1693 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1694 if (substituted)
1695 filename = tem_fn;
1696 }
1697 else
1698 {
1699 dostounix_filename (nm);
1700 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1701 }
1702#endif 1679#endif
1703 endp = nm + SBYTES (filename); 1680 endp = nm + SBYTES (filename);
1704 1681
@@ -1733,8 +1710,9 @@ those `/' is discarded. */)
1733 else if (*p == '{') 1710 else if (*p == '{')
1734 { 1711 {
1735 o = ++p; 1712 o = ++p;
1736 while (p != endp && *p != '}') p++; 1713 p = memchr (p, '}', endp - p);
1737 if (*p != '}') goto missingclose; 1714 if (! p)
1715 goto missingclose;
1738 s = p; 1716 s = p;
1739 } 1717 }
1740 else 1718 else
@@ -1772,7 +1750,13 @@ those `/' is discarded. */)
1772 } 1750 }
1773 1751
1774 if (!substituted) 1752 if (!substituted)
1775 return filename; 1753 {
1754#ifdef WINDOWSNT
1755 if (!NILP (Vw32_downcase_file_names))
1756 filename = Fdowncase (filename);
1757#endif
1758 return filename;
1759 }
1776 1760
1777 /* If substitution required, recopy the string and do it. */ 1761 /* If substitution required, recopy the string and do it. */
1778 /* Make space in stack frame for the new copy. */ 1762 /* Make space in stack frame for the new copy. */
@@ -1796,8 +1780,9 @@ those `/' is discarded. */)
1796 else if (*p == '{') 1780 else if (*p == '{')
1797 { 1781 {
1798 o = ++p; 1782 o = ++p;
1799 while (p != endp && *p != '}') p++; 1783 p = memchr (p, '}', endp - p);
1800 if (*p != '}') goto missingclose; 1784 if (! p)
1785 goto missingclose;
1801 s = p++; 1786 s = p++;
1802 } 1787 }
1803 else 1788 else
@@ -1811,9 +1796,6 @@ those `/' is discarded. */)
1811 target = alloca (s - o + 1); 1796 target = alloca (s - o + 1);
1812 memcpy (target, o, s - o); 1797 memcpy (target, o, s - o);
1813 target[s - o] = 0; 1798 target[s - o] = 0;
1814#ifdef DOS_NT
1815 strupr (target); /* $home == $HOME etc. */
1816#endif /* DOS_NT */
1817 1799
1818 /* Get variable value. */ 1800 /* Get variable value. */
1819 o = egetenv (target); 1801 o = egetenv (target);
@@ -1850,6 +1832,16 @@ those `/' is discarded. */)
1850 need to quote some $ to $$ first. */ 1832 need to quote some $ to $$ first. */
1851 xnm = p; 1833 xnm = p;
1852 1834
1835#ifdef WINDOWSNT
1836 if (!NILP (Vw32_downcase_file_names))
1837 {
1838 Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte);
1839
1840 xname = Fdowncase (xname);
1841 return xname;
1842 }
1843 else
1844#endif
1853 return make_specified_string (xnm, -1, x - xnm, multibyte); 1845 return make_specified_string (xnm, -1, x - xnm, multibyte);
1854 1846
1855 badsubst: 1847 badsubst:
@@ -2753,6 +2745,29 @@ If there is no error, returns nil. */)
2753 return Qnil; 2745 return Qnil;
2754} 2746}
2755 2747
2748/* Relative to directory FD, return the symbolic link value of FILENAME.
2749 On failure, return nil. */
2750Lisp_Object
2751emacs_readlinkat (int fd, char const *filename)
2752{
2753 static struct allocator const emacs_norealloc_allocator =
2754 { xmalloc, NULL, xfree, memory_full };
2755 Lisp_Object val;
2756 char readlink_buf[1024];
2757 char *buf = careadlinkat (fd, filename, readlink_buf, sizeof readlink_buf,
2758 &emacs_norealloc_allocator, readlinkat);
2759 if (!buf)
2760 return Qnil;
2761
2762 val = build_string (buf);
2763 if (buf[0] == '/' && strchr (buf, ':'))
2764 val = concat2 (build_string ("/:"), val);
2765 if (buf != readlink_buf)
2766 xfree (buf);
2767 val = DECODE_FILE (val);
2768 return val;
2769}
2770
2756DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, 2771DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2757 doc: /* Return non-nil if file FILENAME is the name of a symbolic link. 2772 doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
2758The value is the link target, as a string. 2773The value is the link target, as a string.
@@ -2763,9 +2778,6 @@ points to a nonexistent file. */)
2763 (Lisp_Object filename) 2778 (Lisp_Object filename)
2764{ 2779{
2765 Lisp_Object handler; 2780 Lisp_Object handler;
2766 char *buf;
2767 Lisp_Object val;
2768 char readlink_buf[READLINK_BUFSIZE];
2769 2781
2770 CHECK_STRING (filename); 2782 CHECK_STRING (filename);
2771 filename = Fexpand_file_name (filename, Qnil); 2783 filename = Fexpand_file_name (filename, Qnil);
@@ -2778,17 +2790,7 @@ points to a nonexistent file. */)
2778 2790
2779 filename = ENCODE_FILE (filename); 2791 filename = ENCODE_FILE (filename);
2780 2792
2781 buf = emacs_readlink (SSDATA (filename), readlink_buf); 2793 return emacs_readlinkat (AT_FDCWD, SSDATA (filename));
2782 if (! buf)
2783 return Qnil;
2784
2785 val = build_string (buf);
2786 if (buf[0] == '/' && strchr (buf, ':'))
2787 val = concat2 (build_string ("/:"), val);
2788 if (buf != readlink_buf)
2789 xfree (buf);
2790 val = DECODE_FILE (val);
2791 return val;
2792} 2794}
2793 2795
2794DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, 2796DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
@@ -3425,6 +3427,8 @@ read_non_regular (Lisp_Object state)
3425 + XSAVE_INTEGER (state, 1)), 3427 + XSAVE_INTEGER (state, 1)),
3426 XSAVE_INTEGER (state, 2)); 3428 XSAVE_INTEGER (state, 2));
3427 immediate_quit = 0; 3429 immediate_quit = 0;
3430 /* Fast recycle this object for the likely next call. */
3431 free_misc (state);
3428 return make_number (nbytes); 3432 return make_number (nbytes);
3429} 3433}
3430 3434
@@ -3438,19 +3442,25 @@ read_non_regular_quit (Lisp_Object ignore)
3438 return Qnil; 3442 return Qnil;
3439} 3443}
3440 3444
3441/* Reposition FD to OFFSET, based on WHENCE. This acts like lseek 3445/* Return the file offset that VAL represents, checking for type
3442 except that it also tests for OFFSET being out of lseek's range. */ 3446 errors and overflow. */
3443static off_t 3447static off_t
3444emacs_lseek (int fd, EMACS_INT offset, int whence) 3448file_offset (Lisp_Object val)
3445{ 3449{
3446 /* Use "&" rather than "&&" to suppress a bogus GCC warning; see 3450 if (RANGED_INTEGERP (0, val, TYPE_MAXIMUM (off_t)))
3447 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>. */ 3451 return XINT (val);
3448 if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t)))) 3452
3453 if (FLOATP (val))
3449 { 3454 {
3450 errno = EINVAL; 3455 double v = XFLOAT_DATA (val);
3451 return -1; 3456 if (0 <= v
3457 && (sizeof (off_t) < sizeof v
3458 ? v <= TYPE_MAXIMUM (off_t)
3459 : v < TYPE_MAXIMUM (off_t)))
3460 return v;
3452 } 3461 }
3453 return lseek (fd, offset, whence); 3462
3463 wrong_type_argument (intern ("file-offset"), val);
3454} 3464}
3455 3465
3456/* Return a special time value indicating the error number ERRNUM. */ 3466/* Return a special time value indicating the error number ERRNUM. */
@@ -3492,7 +3502,6 @@ by calling `format-decode', which see. */)
3492 (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace) 3502 (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace)
3493{ 3503{
3494 struct stat st; 3504 struct stat st;
3495 int file_status;
3496 EMACS_TIME mtime; 3505 EMACS_TIME mtime;
3497 int fd; 3506 int fd;
3498 ptrdiff_t inserted = 0; 3507 ptrdiff_t inserted = 0;
@@ -3509,7 +3518,6 @@ by calling `format-decode', which see. */)
3509 int save_errno = 0; 3518 int save_errno = 0;
3510 char read_buf[READ_BUF_SIZE]; 3519 char read_buf[READ_BUF_SIZE];
3511 struct coding_system coding; 3520 struct coding_system coding;
3512 char buffer[1 << 14];
3513 bool replace_handled = 0; 3521 bool replace_handled = 0;
3514 bool set_coding_system = 0; 3522 bool set_coding_system = 0;
3515 Lisp_Object coding_system; 3523 Lisp_Object coding_system;
@@ -3554,37 +3562,29 @@ by calling `format-decode', which see. */)
3554 orig_filename = filename; 3562 orig_filename = filename;
3555 filename = ENCODE_FILE (filename); 3563 filename = ENCODE_FILE (filename);
3556 3564
3557 fd = -1; 3565 fd = emacs_open (SSDATA (filename), O_RDONLY, 0);
3558 3566 if (fd < 0)
3559#ifdef WINDOWSNT
3560 {
3561 Lisp_Object tem = Vw32_get_true_file_attributes;
3562
3563 /* Tell stat to use expensive method to get accurate info. */
3564 Vw32_get_true_file_attributes = Qt;
3565 file_status = stat (SSDATA (filename), &st);
3566 Vw32_get_true_file_attributes = tem;
3567 }
3568#else
3569 file_status = stat (SSDATA (filename), &st);
3570#endif /* WINDOWSNT */
3571
3572 if (file_status == 0)
3573 mtime = get_stat_mtime (&st);
3574 else
3575 { 3567 {
3576 badopen:
3577 save_errno = errno; 3568 save_errno = errno;
3578 if (NILP (visit)) 3569 if (NILP (visit))
3579 report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); 3570 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
3580 mtime = time_error_value (save_errno); 3571 mtime = time_error_value (save_errno);
3581 st.st_size = -1; 3572 st.st_size = -1;
3582 how_much = 0;
3583 if (!NILP (Vcoding_system_for_read)) 3573 if (!NILP (Vcoding_system_for_read))
3584 Fset (Qbuffer_file_coding_system, Vcoding_system_for_read); 3574 Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
3585 goto notfound; 3575 goto notfound;
3586 } 3576 }
3587 3577
3578 /* Replacement should preserve point as it preserves markers. */
3579 if (!NILP (replace))
3580 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3581
3582 record_unwind_protect (close_file_unwind, make_number (fd));
3583
3584 if (fstat (fd, &st) != 0)
3585 report_file_error ("Input file status", Fcons (orig_filename, Qnil));
3586 mtime = get_stat_mtime (&st);
3587
3588 /* This code will need to be changed in order to work on named 3588 /* This code will need to be changed in order to work on named
3589 pipes, and it's probably just not worth it. So we should at 3589 pipes, and it's probably just not worth it. So we should at
3590 least signal an error. */ 3590 least signal an error. */
@@ -3600,17 +3600,6 @@ by calling `format-decode', which see. */)
3600 build_string ("not a regular file"), orig_filename); 3600 build_string ("not a regular file"), orig_filename);
3601 } 3601 }
3602 3602
3603 if (fd < 0)
3604 if ((fd = emacs_open (SSDATA (filename), O_RDONLY, 0)) < 0)
3605 goto badopen;
3606
3607 /* Replacement should preserve point as it preserves markers. */
3608 if (!NILP (replace))
3609 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3610
3611 record_unwind_protect (close_file_unwind, make_number (fd));
3612
3613
3614 if (!NILP (visit)) 3603 if (!NILP (visit))
3615 { 3604 {
3616 if (!NILP (beg) || !NILP (end)) 3605 if (!NILP (beg) || !NILP (end))
@@ -3620,20 +3609,12 @@ by calling `format-decode', which see. */)
3620 } 3609 }
3621 3610
3622 if (!NILP (beg)) 3611 if (!NILP (beg))
3623 { 3612 beg_offset = file_offset (beg);
3624 if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t)))
3625 wrong_type_argument (intern ("file-offset"), beg);
3626 beg_offset = XFASTINT (beg);
3627 }
3628 else 3613 else
3629 beg_offset = 0; 3614 beg_offset = 0;
3630 3615
3631 if (!NILP (end)) 3616 if (!NILP (end))
3632 { 3617 end_offset = file_offset (end);
3633 if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t)))
3634 wrong_type_argument (intern ("file-offset"), end);
3635 end_offset = XFASTINT (end);
3636 }
3637 else 3618 else
3638 { 3619 {
3639 if (not_regular) 3620 if (not_regular)
@@ -3838,7 +3819,7 @@ by calling `format-decode', which see. */)
3838 { 3819 {
3839 int nread, bufpos; 3820 int nread, bufpos;
3840 3821
3841 nread = emacs_read (fd, buffer, sizeof buffer); 3822 nread = emacs_read (fd, read_buf, sizeof read_buf);
3842 if (nread < 0) 3823 if (nread < 0)
3843 error ("IO error reading %s: %s", 3824 error ("IO error reading %s: %s",
3844 SSDATA (orig_filename), emacs_strerror (errno)); 3825 SSDATA (orig_filename), emacs_strerror (errno));
@@ -3847,7 +3828,7 @@ by calling `format-decode', which see. */)
3847 3828
3848 if (CODING_REQUIRE_DETECTION (&coding)) 3829 if (CODING_REQUIRE_DETECTION (&coding))
3849 { 3830 {
3850 coding_system = detect_coding_system ((unsigned char *) buffer, 3831 coding_system = detect_coding_system ((unsigned char *) read_buf,
3851 nread, nread, 1, 0, 3832 nread, nread, 1, 0,
3852 coding_system); 3833 coding_system);
3853 setup_coding_system (coding_system, &coding); 3834 setup_coding_system (coding_system, &coding);
@@ -3863,7 +3844,7 @@ by calling `format-decode', which see. */)
3863 3844
3864 bufpos = 0; 3845 bufpos = 0;
3865 while (bufpos < nread && same_at_start < ZV_BYTE 3846 while (bufpos < nread && same_at_start < ZV_BYTE
3866 && FETCH_BYTE (same_at_start) == buffer[bufpos]) 3847 && FETCH_BYTE (same_at_start) == read_buf[bufpos])
3867 same_at_start++, bufpos++; 3848 same_at_start++, bufpos++;
3868 /* If we found a discrepancy, stop the scan. 3849 /* If we found a discrepancy, stop the scan.
3869 Otherwise loop around and scan the next bufferful. */ 3850 Otherwise loop around and scan the next bufferful. */
@@ -3897,7 +3878,7 @@ by calling `format-decode', which see. */)
3897 if (curpos == 0) 3878 if (curpos == 0)
3898 break; 3879 break;
3899 /* How much can we scan in the next step? */ 3880 /* How much can we scan in the next step? */
3900 trial = min (curpos, sizeof buffer); 3881 trial = min (curpos, sizeof read_buf);
3901 if (lseek (fd, curpos - trial, SEEK_SET) < 0) 3882 if (lseek (fd, curpos - trial, SEEK_SET) < 0)
3902 report_file_error ("Setting file position", 3883 report_file_error ("Setting file position",
3903 Fcons (orig_filename, Qnil)); 3884 Fcons (orig_filename, Qnil));
@@ -3905,7 +3886,7 @@ by calling `format-decode', which see. */)
3905 total_read = nread = 0; 3886 total_read = nread = 0;
3906 while (total_read < trial) 3887 while (total_read < trial)
3907 { 3888 {
3908 nread = emacs_read (fd, buffer + total_read, trial - total_read); 3889 nread = emacs_read (fd, read_buf + total_read, trial - total_read);
3909 if (nread < 0) 3890 if (nread < 0)
3910 error ("IO error reading %s: %s", 3891 error ("IO error reading %s: %s",
3911 SDATA (orig_filename), emacs_strerror (errno)); 3892 SDATA (orig_filename), emacs_strerror (errno));
@@ -3921,7 +3902,7 @@ by calling `format-decode', which see. */)
3921 /* Compare with same_at_start to avoid counting some buffer text 3902 /* Compare with same_at_start to avoid counting some buffer text
3922 as matching both at the file's beginning and at the end. */ 3903 as matching both at the file's beginning and at the end. */
3923 while (bufpos > 0 && same_at_end > same_at_start 3904 while (bufpos > 0 && same_at_end > same_at_start
3924 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1]) 3905 && FETCH_BYTE (same_at_end - 1) == read_buf[bufpos - 1])
3925 same_at_end--, bufpos--; 3906 same_at_end--, bufpos--;
3926 3907
3927 /* If we found a discrepancy, stop the scan. 3908 /* If we found a discrepancy, stop the scan.
@@ -4023,30 +4004,25 @@ by calling `format-decode', which see. */)
4023 report_file_error ("Setting file position", 4004 report_file_error ("Setting file position",
4024 Fcons (orig_filename, Qnil)); 4005 Fcons (orig_filename, Qnil));
4025 4006
4026 total = st.st_size; /* Total bytes in the file. */
4027 how_much = 0; /* Bytes read from file so far. */
4028 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */ 4007 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
4029 unprocessed = 0; /* Bytes not processed in previous loop. */ 4008 unprocessed = 0; /* Bytes not processed in previous loop. */
4030 4009
4031 GCPRO1 (conversion_buffer); 4010 GCPRO1 (conversion_buffer);
4032 while (how_much < total) 4011 while (1)
4033 { 4012 {
4034 /* We read one bunch by one (READ_BUF_SIZE bytes) to allow 4013 /* Read at most READ_BUF_SIZE bytes at a time, to allow
4035 quitting while reading a huge while. */ 4014 quitting while reading a huge file. */
4036 /* `try'' is reserved in some compilers (Microsoft C). */
4037 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
4038 4015
4039 /* Allow quitting out of the actual I/O. */ 4016 /* Allow quitting out of the actual I/O. */
4040 immediate_quit = 1; 4017 immediate_quit = 1;
4041 QUIT; 4018 QUIT;
4042 this = emacs_read (fd, read_buf + unprocessed, trytry); 4019 this = emacs_read (fd, read_buf + unprocessed,
4020 READ_BUF_SIZE - unprocessed);
4043 immediate_quit = 0; 4021 immediate_quit = 0;
4044 4022
4045 if (this <= 0) 4023 if (this <= 0)
4046 break; 4024 break;
4047 4025
4048 how_much += this;
4049
4050 BUF_TEMP_SET_PT (XBUFFER (conversion_buffer), 4026 BUF_TEMP_SET_PT (XBUFFER (conversion_buffer),
4051 BUF_Z (XBUFFER (conversion_buffer))); 4027 BUF_Z (XBUFFER (conversion_buffer)));
4052 decode_coding_c_string (&coding, (unsigned char *) read_buf, 4028 decode_coding_c_string (&coding, (unsigned char *) read_buf,
@@ -4063,9 +4039,6 @@ by calling `format-decode', which see. */)
4063 so defer the removal till we reach the `handled' label. */ 4039 so defer the removal till we reach the `handled' label. */
4064 deferred_remove_unwind_protect = 1; 4040 deferred_remove_unwind_protect = 1;
4065 4041
4066 /* At this point, HOW_MUCH should equal TOTAL, or should be <= 0
4067 if we couldn't read the file. */
4068
4069 if (this < 0) 4042 if (this < 0)
4070 error ("IO error reading %s: %s", 4043 error ("IO error reading %s: %s",
4071 SDATA (orig_filename), emacs_strerror (errno)); 4044 SDATA (orig_filename), emacs_strerror (errno));
@@ -4240,8 +4213,8 @@ by calling `format-decode', which see. */)
4240 /* Maybe make more room. */ 4213 /* Maybe make more room. */
4241 if (gap_size < trytry) 4214 if (gap_size < trytry)
4242 { 4215 {
4243 make_gap (total - gap_size); 4216 make_gap (trytry - gap_size);
4244 gap_size = GAP_SIZE; 4217 gap_size = GAP_SIZE - inserted;
4245 } 4218 }
4246 4219
4247 /* Read from the file, capturing `quit'. When an 4220 /* Read from the file, capturing `quit'. When an
@@ -4249,7 +4222,7 @@ by calling `format-decode', which see. */)
4249 to be signaled after decoding the text we read. */ 4222 to be signaled after decoding the text we read. */
4250 nbytes = internal_condition_case_1 4223 nbytes = internal_condition_case_1
4251 (read_non_regular, 4224 (read_non_regular,
4252 format_save_value ("iii", (ptrdiff_t) fd, inserted, trytry), 4225 make_save_value ("iii", (ptrdiff_t) fd, inserted, trytry),
4253 Qerror, read_non_regular_quit); 4226 Qerror, read_non_regular_quit);
4254 4227
4255 if (NILP (nbytes)) 4228 if (NILP (nbytes))
@@ -4293,8 +4266,9 @@ by calling `format-decode', which see. */)
4293 } 4266 }
4294 } 4267 }
4295 4268
4296 /* Now we have read all the file data into the gap. 4269 /* Now we have either read all the file data into the gap,
4297 If it was empty, undo marking the buffer modified. */ 4270 or stop reading on I/O error or quit. If nothing was
4271 read, undo marking the buffer modified. */
4298 4272
4299 if (inserted == 0) 4273 if (inserted == 0)
4300 { 4274 {
@@ -4307,6 +4281,15 @@ by calling `format-decode', which see. */)
4307 else 4281 else
4308 Vdeactivate_mark = Qt; 4282 Vdeactivate_mark = Qt;
4309 4283
4284 emacs_close (fd);
4285
4286 /* Discard the unwind protect for closing the file. */
4287 specpdl_ptr--;
4288
4289 if (how_much < 0)
4290 error ("IO error reading %s: %s",
4291 SDATA (orig_filename), emacs_strerror (errno));
4292
4310 /* Make the text read part of the buffer. */ 4293 /* Make the text read part of the buffer. */
4311 GAP_SIZE -= inserted; 4294 GAP_SIZE -= inserted;
4312 GPT += inserted; 4295 GPT += inserted;
@@ -4320,15 +4303,6 @@ by calling `format-decode', which see. */)
4320 /* Put an anchor to ensure multi-byte form ends at gap. */ 4303 /* Put an anchor to ensure multi-byte form ends at gap. */
4321 *GPT_ADDR = 0; 4304 *GPT_ADDR = 0;
4322 4305
4323 emacs_close (fd);
4324
4325 /* Discard the unwind protect for closing the file. */
4326 specpdl_ptr--;
4327
4328 if (how_much < 0)
4329 error ("IO error reading %s: %s",
4330 SDATA (orig_filename), emacs_strerror (errno));
4331
4332 notfound: 4306 notfound:
4333 4307
4334 if (NILP (coding_system)) 4308 if (NILP (coding_system))
@@ -4620,11 +4594,9 @@ by calling `format-decode', which see. */)
4620 if (read_quit) 4594 if (read_quit)
4621 Fsignal (Qquit, Qnil); 4595 Fsignal (Qquit, Qnil);
4622 4596
4623 /* ??? Retval needs to be dealt with in all cases consistently. */ 4597 /* Retval needs to be dealt with in all cases consistently. */
4624 if (NILP (val)) 4598 if (NILP (val))
4625 val = Fcons (orig_filename, 4599 val = list2 (orig_filename, make_number (inserted));
4626 Fcons (make_number (inserted),
4627 Qnil));
4628 4600
4629 RETURN_UNGCPRO (unbind_to (count, val)); 4601 RETURN_UNGCPRO (unbind_to (count, val));
4630} 4602}
@@ -4640,14 +4612,24 @@ build_annotations_unwind (Lisp_Object arg)
4640 4612
4641/* Decide the coding-system to encode the data with. */ 4613/* Decide the coding-system to encode the data with. */
4642 4614
4643static Lisp_Object 4615DEFUN ("choose-write-coding-system", Fchoose_write_coding_system,
4644choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object filename, 4616 Schoose_write_coding_system, 3, 6, 0,
4645 Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, 4617 doc: /* Choose the coding system for writing a file.
4646 struct coding_system *coding) 4618Arguments are as for `write-region'.
4619This function is for internal use only. It may prompt the user. */ )
4620 (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
4621 Lisp_Object append, Lisp_Object visit, Lisp_Object lockname)
4647{ 4622{
4648 Lisp_Object val; 4623 Lisp_Object val;
4649 Lisp_Object eol_parent = Qnil; 4624 Lisp_Object eol_parent = Qnil;
4650 4625
4626 /* Mimic write-region behavior. */
4627 if (NILP (start))
4628 {
4629 XSETFASTINT (start, BEGV);
4630 XSETFASTINT (end, ZV);
4631 }
4632
4651 if (auto_saving 4633 if (auto_saving
4652 && NILP (Fstring_equal (BVAR (current_buffer, filename), 4634 && NILP (Fstring_equal (BVAR (current_buffer, filename),
4653 BVAR (current_buffer, auto_save_file_name)))) 4635 BVAR (current_buffer, auto_save_file_name))))
@@ -4740,10 +4722,6 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
4740 } 4722 }
4741 4723
4742 val = coding_inherit_eol_type (val, eol_parent); 4724 val = coding_inherit_eol_type (val, eol_parent);
4743 setup_coding_system (val, coding);
4744
4745 if (!STRINGP (start) && !NILP (BVAR (current_buffer, selective_display)))
4746 coding->mode |= CODING_MODE_SELECTIVE_DISPLAY;
4747 return val; 4725 return val;
4748} 4726}
4749 4727
@@ -4758,7 +4736,7 @@ If START is a string, then output that string to the file
4758instead of any buffer contents; END is ignored. 4736instead of any buffer contents; END is ignored.
4759 4737
4760Optional fourth argument APPEND if non-nil means 4738Optional fourth argument APPEND if non-nil means
4761 append to existing file contents (if any). If it is an integer, 4739 append to existing file contents (if any). If it is a number,
4762 seek to that offset in the file before writing. 4740 seek to that offset in the file before writing.
4763Optional fifth argument VISIT, if t or a string, means 4741Optional fifth argument VISIT, if t or a string, means
4764 set the last-save-file-modtime of buffer to this file's modtime 4742 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
4787 (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) 4765 (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
4788{ 4766{
4789 int desc; 4767 int desc;
4768 int open_flags;
4769 int mode;
4770 off_t offset IF_LINT (= 0);
4790 bool ok; 4771 bool ok;
4791 int save_errno = 0; 4772 int save_errno = 0;
4792 const char *fn; 4773 const char *fn;
@@ -4896,9 +4877,14 @@ This calls `write-region-annotate-functions' at the start, and
4896 We used to make this choice before calling build_annotations, but that 4877 We used to make this choice before calling build_annotations, but that
4897 leads to problems when a write-annotate-function takes care of 4878 leads to problems when a write-annotate-function takes care of
4898 unsavable chars (as was the case with X-Symbol). */ 4879 unsavable chars (as was the case with X-Symbol). */
4899 Vlast_coding_system_used 4880 Vlast_coding_system_used =
4900 = choose_write_coding_system (start, end, filename, 4881 Fchoose_write_coding_system (start, end, filename,
4901 append, visit, lockname, &coding); 4882 append, visit, lockname);
4883
4884 setup_coding_system (Vlast_coding_system_used, &coding);
4885
4886 if (!STRINGP (start) && !NILP (BVAR (current_buffer, selective_display)))
4887 coding.mode |= CODING_MODE_SELECTIVE_DISPLAY;
4902 4888
4903#ifdef CLASH_DETECTION 4889#ifdef CLASH_DETECTION
4904 if (!auto_saving) 4890 if (!auto_saving)
@@ -4906,27 +4892,20 @@ This calls `write-region-annotate-functions' at the start, and
4906#endif /* CLASH_DETECTION */ 4892#endif /* CLASH_DETECTION */
4907 4893
4908 encoded_filename = ENCODE_FILE (filename); 4894 encoded_filename = ENCODE_FILE (filename);
4909
4910 fn = SSDATA (encoded_filename); 4895 fn = SSDATA (encoded_filename);
4911 desc = -1; 4896 open_flags = O_WRONLY | O_BINARY | O_CREAT;
4912 if (!NILP (append)) 4897 open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC;
4898 if (NUMBERP (append))
4899 offset = file_offset (append);
4900 else if (!NILP (append))
4901 open_flags |= O_APPEND;
4913#ifdef DOS_NT 4902#ifdef DOS_NT
4914 desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); 4903 mode = S_IREAD | S_IWRITE;
4915#else /* not DOS_NT */ 4904#else
4916 desc = emacs_open (fn, O_WRONLY, 0); 4905 mode = auto_saving ? auto_save_mode_bits : 0666;
4917#endif /* not DOS_NT */ 4906#endif
4918 4907
4919 if (desc < 0 && (NILP (append) || errno == ENOENT)) 4908 desc = emacs_open (fn, open_flags, mode);
4920#ifdef DOS_NT
4921 desc = emacs_open (fn,
4922 O_WRONLY | O_CREAT | O_BINARY
4923 | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC),
4924 S_IREAD | S_IWRITE);
4925#else /* not DOS_NT */
4926 desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
4927 | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
4928 auto_saving ? auto_save_mode_bits : 0666);
4929#endif /* not DOS_NT */
4930 4909
4931 if (desc < 0) 4910 if (desc < 0)
4932 { 4911 {
@@ -4941,14 +4920,9 @@ This calls `write-region-annotate-functions' at the start, and
4941 4920
4942 record_unwind_protect (close_file_unwind, make_number (desc)); 4921 record_unwind_protect (close_file_unwind, make_number (desc));
4943 4922
4944 if (!NILP (append) && !NILP (Ffile_regular_p (filename))) 4923 if (NUMBERP (append))
4945 { 4924 {
4946 off_t ret; 4925 off_t ret = lseek (desc, offset, SEEK_SET);
4947
4948 if (NUMBERP (append))
4949 ret = emacs_lseek (desc, XINT (append), SEEK_CUR);
4950 else
4951 ret = lseek (desc, 0, SEEK_END);
4952 if (ret < 0) 4926 if (ret < 0)
4953 { 4927 {
4954#ifdef CLASH_DETECTION 4928#ifdef CLASH_DETECTION
@@ -4990,7 +4964,7 @@ This calls `write-region-annotate-functions' at the start, and
4990 immediate_quit = 0; 4964 immediate_quit = 0;
4991 4965
4992#ifdef HAVE_FSYNC 4966#ifdef HAVE_FSYNC
4993 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun). 4967 /* fsync appears to change the modtime on BSD4.2.
4994 Disk full in NFS may be reported here. */ 4968 Disk full in NFS may be reported here. */
4995 /* mib says that closing the file will try to write as fast as NFS can do 4969 /* mib says that closing the file will try to write as fast as NFS can do
4996 it, and that means the fsync here is not crucial for autosave files. */ 4970 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
5020 /* Discard the unwind protect for close_file_unwind. */ 4994 /* Discard the unwind protect for close_file_unwind. */
5021 specpdl_ptr = specpdl + count1; 4995 specpdl_ptr = specpdl + count1;
5022 4996
4997 /* Some file systems have a bug where st_mtime is not updated
4998 properly after a write. For example, CIFS might not see the
4999 st_mtime change until after the file is opened again.
5000
5001 Attempt to detect this file system bug, and update MODTIME to the
5002 newer st_mtime if the bug appears to be present. This introduces
5003 a race condition, so to avoid most instances of the race condition
5004 on non-buggy file systems, skip this check if the most recently
5005 encountered non-buggy file system was the current file system.
5006
5007 A race condition can occur if some other process modifies the
5008 file between the fstat above and the fstat below, but the race is
5009 unlikely and a similar race between the last write and the fstat
5010 above cannot possibly be closed anyway. */
5011
5012 if (EMACS_TIME_VALID_P (modtime)
5013 && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system))
5014 {
5015 int desc1 = emacs_open (fn, O_WRONLY | O_BINARY, 0);
5016 if (0 <= desc1)
5017 {
5018 struct stat st1;
5019 if (fstat (desc1, &st1) == 0
5020 && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
5021 {
5022 /* Use the heuristic if it appears to be valid. With neither
5023 O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the
5024 file, the time stamp won't change. Also, some non-POSIX
5025 systems don't update an empty file's time stamp when
5026 truncating it. Finally, file systems with 100 ns or worse
5027 resolution sometimes seem to have bugs: on a system with ns
5028 resolution, checking ns % 100 incorrectly avoids the heuristic
5029 1% of the time, but the problem should be temporary as we will
5030 try again on the next time stamp. */
5031 bool use_heuristic
5032 = ((open_flags & (O_EXCL | O_TRUNC)) != 0
5033 && st.st_size != 0
5034 && EMACS_NSECS (modtime) % 100 != 0);
5035
5036 EMACS_TIME modtime1 = get_stat_mtime (&st1);
5037 if (use_heuristic
5038 && EMACS_TIME_EQ (modtime, modtime1)
5039 && st.st_size == st1.st_size)
5040 {
5041 timestamp_file_system = st.st_dev;
5042 valid_timestamp_file_system = 1;
5043 }
5044 else
5045 {
5046 st.st_size = st1.st_size;
5047 modtime = modtime1;
5048 }
5049 }
5050 emacs_close (desc1);
5051 }
5052 }
5053
5023 /* Call write-region-post-annotation-function. */ 5054 /* Call write-region-post-annotation-function. */
5024 while (CONSP (Vwrite_region_annotation_buffers)) 5055 while (CONSP (Vwrite_region_annotation_buffers))
5025 { 5056 {
@@ -5072,7 +5103,7 @@ This calls `write-region-annotate-functions' at the start, and
5072 } 5103 }
5073 5104
5074 if (!auto_saving) 5105 if (!auto_saving)
5075 message_with_string ((INTEGERP (append) 5106 message_with_string ((NUMBERP (append)
5076 ? "Updated %s" 5107 ? "Updated %s"
5077 : ! NILP (append) 5108 : ! NILP (append)
5078 ? "Added to %s" 5109 ? "Added to %s"
@@ -5382,8 +5413,7 @@ See Info node `(elisp)Modification Time' for more details. */)
5382 if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) 5413 if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
5383 { 5414 {
5384 /* make_lisp_time won't work here if time_t is unsigned. */ 5415 /* make_lisp_time won't work here if time_t is unsigned. */
5385 return list4 (make_number (-1), make_number (65535), 5416 return list4i (-1, 65535, 0, 0);
5386 make_number (0), make_number (0));
5387 } 5417 }
5388 return make_number (0); 5418 return make_number (0);
5389 } 5419 }
@@ -5436,10 +5466,8 @@ static Lisp_Object
5436auto_save_error (Lisp_Object error_val) 5466auto_save_error (Lisp_Object error_val)
5437{ 5467{
5438 Lisp_Object args[3], msg; 5468 Lisp_Object args[3], msg;
5439 int i, nbytes; 5469 int i;
5440 struct gcpro gcpro1; 5470 struct gcpro gcpro1;
5441 char *msgbuf;
5442 USE_SAFE_ALLOCA;
5443 5471
5444 auto_save_error_occurred = 1; 5472 auto_save_error_occurred = 1;
5445 5473
@@ -5450,20 +5478,16 @@ auto_save_error (Lisp_Object error_val)
5450 args[2] = Ferror_message_string (error_val); 5478 args[2] = Ferror_message_string (error_val);
5451 msg = Fformat (3, args); 5479 msg = Fformat (3, args);
5452 GCPRO1 (msg); 5480 GCPRO1 (msg);
5453 nbytes = SBYTES (msg);
5454 msgbuf = SAFE_ALLOCA (nbytes);
5455 memcpy (msgbuf, SDATA (msg), nbytes);
5456 5481
5457 for (i = 0; i < 3; ++i) 5482 for (i = 0; i < 3; ++i)
5458 { 5483 {
5459 if (i == 0) 5484 if (i == 0)
5460 message2 (msgbuf, nbytes, STRING_MULTIBYTE (msg)); 5485 message3 (msg);
5461 else 5486 else
5462 message2_nolog (msgbuf, nbytes, STRING_MULTIBYTE (msg)); 5487 message3_nolog (msg);
5463 Fsleep_for (make_number (1), Qnil); 5488 Fsleep_for (make_number (1), Qnil);
5464 } 5489 }
5465 5490
5466 SAFE_FREE ();
5467 UNGCPRO; 5491 UNGCPRO;
5468 return Qnil; 5492 return Qnil;
5469} 5493}
@@ -5608,7 +5632,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5608 } 5632 }
5609 5633
5610 record_unwind_protect (do_auto_save_unwind, 5634 record_unwind_protect (do_auto_save_unwind,
5611 make_save_value (stream, 0)); 5635 make_save_pointer (stream));
5612 record_unwind_protect (do_auto_save_unwind_1, 5636 record_unwind_protect (do_auto_save_unwind_1,
5613 make_number (minibuffer_auto_raise)); 5637 make_number (minibuffer_auto_raise));
5614 minibuffer_auto_raise = 0; 5638 minibuffer_auto_raise = 0;
@@ -5817,6 +5841,12 @@ Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filena
5817 5841
5818 5842
5819void 5843void
5844init_fileio (void)
5845{
5846 valid_timestamp_file_system = 0;
5847}
5848
5849void
5820syms_of_fileio (void) 5850syms_of_fileio (void)
5821{ 5851{
5822 DEFSYM (Qoperations, "operations"); 5852 DEFSYM (Qoperations, "operations");
@@ -5853,6 +5883,7 @@ syms_of_fileio (void)
5853 DEFSYM (Qset_file_acl, "set-file-acl"); 5883 DEFSYM (Qset_file_acl, "set-file-acl");
5854 DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p"); 5884 DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p");
5855 DEFSYM (Qinsert_file_contents, "insert-file-contents"); 5885 DEFSYM (Qinsert_file_contents, "insert-file-contents");
5886 DEFSYM (Qchoose_write_coding_system, "choose-write-coding-system");
5856 DEFSYM (Qwrite_region, "write-region"); 5887 DEFSYM (Qwrite_region, "write-region");
5857 DEFSYM (Qverify_visited_file_modtime, "verify-visited-file-modtime"); 5888 DEFSYM (Qverify_visited_file_modtime, "verify-visited-file-modtime");
5858 DEFSYM (Qset_visited_file_modtime, "set-visited-file-modtime"); 5889 DEFSYM (Qset_visited_file_modtime, "set-visited-file-modtime");
@@ -6077,6 +6108,7 @@ This includes interactive calls to `delete-file' and
6077 defsubr (&Sdefault_file_modes); 6108 defsubr (&Sdefault_file_modes);
6078 defsubr (&Sfile_newer_than_file_p); 6109 defsubr (&Sfile_newer_than_file_p);
6079 defsubr (&Sinsert_file_contents); 6110 defsubr (&Sinsert_file_contents);
6111 defsubr (&Schoose_write_coding_system);
6080 defsubr (&Swrite_region); 6112 defsubr (&Swrite_region);
6081 defsubr (&Scar_less_than_car); 6113 defsubr (&Scar_less_than_car);
6082 defsubr (&Sverify_visited_file_modtime); 6114 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/>. */
38 38
39#include <errno.h> 39#include <errno.h>
40 40
41#include <c-ctype.h>
42
41#include "lisp.h" 43#include "lisp.h"
42#include "character.h" 44#include "character.h"
43#include "buffer.h" 45#include "buffer.h"
44#include "coding.h" 46#include "coding.h"
45#include "systime.h" 47#include "systime.h"
48#ifdef WINDOWSNT
49#include <share.h>
50#include "w32.h" /* for dostounix_filename */
51#endif
46 52
47#ifdef CLASH_DETECTION 53#ifdef CLASH_DETECTION
48 54
@@ -60,7 +66,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
60#define WTMP_FILE "/var/log/wtmp" 66#define WTMP_FILE "/var/log/wtmp"
61#endif 67#endif
62 68
63/* The strategy: to lock a file FN, create a symlink .#FN in FN's 69/* Normally use a symbolic link to represent a lock.
70 The strategy: to lock a file FN, create a symlink .#FN in FN's
64 directory, with link data `user@host.pid'. This avoids a single 71 directory, with link data `user@host.pid'. This avoids a single
65 mount (== failure) point for lock files. 72 mount (== failure) point for lock files.
66 73
@@ -93,7 +100,23 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
93 has contributed this implementation for Emacs), and was designed by 100 has contributed this implementation for Emacs), and was designed by
94 Ethan Jacobson, Kimbo Mundy, and others. 101 Ethan Jacobson, Kimbo Mundy, and others.
95 102
96 --karl@cs.umb.edu/karl@hq.ileaf.com. */ 103 --karl@cs.umb.edu/karl@hq.ileaf.com.
104
105 On some file systems, notably those of MS-Windows, symbolic links
106 do not work well, so instead of a symlink .#FN -> 'user@host.pid',
107 the lock is a regular file .#FN with contents 'user@host.pid'. To
108 establish a lock, a nonce file is created and then renamed to .#FN.
109 On MS-Windows this renaming is atomic unless the lock is forcibly
110 acquired. On other systems the renaming is atomic if the lock is
111 forcibly acquired; if not, the renaming is done via hard links,
112 which is good enough for lock-file purposes.
113
114 To summarize, race conditions can occur with either:
115
116 * Forced locks on MS-Windows systems.
117
118 * Non-forced locks on non-MS-Windows systems that support neither
119 hard nor symbolic links. */
97 120
98 121
99/* Return the time of the last system boot. */ 122/* Return the time of the last system boot. */
@@ -274,72 +297,167 @@ get_boot_time_1 (const char *filename, bool newest)
274} 297}
275#endif /* BOOT_TIME */ 298#endif /* BOOT_TIME */
276 299
300/* An arbitrary limit on lock contents length. 8 K should be plenty
301 big enough in practice. */
302enum { MAX_LFINFO = 8 * 1024 };
303
277/* Here is the structure that stores information about a lock. */ 304/* Here is the structure that stores information about a lock. */
278 305
279typedef struct 306typedef struct
280{ 307{
281 char *user; 308 /* Location of '@', '.', ':' in USER. If there's no colon, COLON
282 char *host; 309 points to the end of USER. */
283 pid_t pid; 310 char *at, *dot, *colon;
284 time_t boot_time; 311
312 /* Lock file contents USER@HOST.PID with an optional :BOOT_TIME
313 appended. This memory is used as a lock file contents buffer, so
314 it needs room for MAX_LFINFO + 1 bytes. A string " (pid NNNN)"
315 may be appended to the USER@HOST while generating a diagnostic,
316 so make room for its extra bytes (as opposed to ".NNNN") too. */
317 char user[MAX_LFINFO + 1 + sizeof " (pid )" - sizeof "."];
285} lock_info_type; 318} lock_info_type;
286 319
287/* Free the two dynamically-allocated pieces in PTR. */ 320/* Write the name of the lock file for FNAME into LOCKNAME. Length
288#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) 321 will be that of FNAME plus two more for the leading ".#", plus one
322 for the null. */
323#define MAKE_LOCK_NAME(lockname, fname) \
324 (lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + 1), \
325 fill_in_lock_file_name (lockname, fname))
289 326
327static void
328fill_in_lock_file_name (char *lockfile, Lisp_Object fn)
329{
330 char *last_slash = memrchr (SSDATA (fn), '/', SBYTES (fn));
331 char *base = last_slash + 1;
332 ptrdiff_t dirlen = base - SSDATA (fn);
333 memcpy (lockfile, SSDATA (fn), dirlen);
334 lockfile[dirlen] = '.';
335 lockfile[dirlen + 1] = '#';
336 strcpy (lockfile + dirlen + 2, base);
337}
290 338
291/* Write the name of the lock file for FN into LFNAME. Length will be 339/* For some reason Linux kernels return EPERM on file systems that do
292 that of FN plus two more for the leading `.#' plus 1 for the 340 not support hard or symbolic links. This symbol documents the quirk.
293 trailing period plus one for the digit after it plus one for the 341 There is no way to tell whether a symlink call fails due to
294 null. */ 342 permissions issues or because links are not supported, but luckily
295#define MAKE_LOCK_NAME(lock, file) \ 343 the lock file code should work either way. */
296 (lock = alloca (SBYTES (file) + 2 + 1 + 1 + 1), \ 344enum { LINKS_MIGHT_NOT_WORK = EPERM };
297 fill_in_lock_file_name (lock, (file)))
298 345
299static void 346/* Rename OLD to NEW. If FORCE, replace any existing NEW.
300fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) 347 It is OK if there are temporarily two hard links to OLD.
348 Return 0 if successful, -1 (setting errno) otherwise. */
349static int
350rename_lock_file (char const *old, char const *new, bool force)
301{ 351{
302 ptrdiff_t length = SBYTES (fn); 352#ifdef WINDOWSNT
303 register char *p; 353 return sys_rename_replace (old, new, force);
304 struct stat st; 354#else
305 int count = 0; 355 if (! force)
356 {
357 struct stat st;
306 358
307 strcpy (lockfile, SSDATA (fn)); 359 if (link (old, new) == 0)
360 return unlink (old) == 0 || errno == ENOENT ? 0 : -1;
361 if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK)
362 return -1;
308 363
309 /* Shift the nondirectory part of the file name (including the null) 364 /* 'link' does not work on this file system. This can occur on
310 right two characters. Here is one of the places where we'd have to 365 a GNU/Linux host mounting a FAT32 file system. Fall back on
311 do something to support 14-character-max file names. */ 366 'rename' after checking that NEW does not exist. There is a
312 for (p = lockfile + length; p != lockfile && *p != '/'; p--) 367 potential race condition since some other process may create
313 p[2] = *p; 368 NEW immediately after the existence check, but it's the best
369 we can portably do here. */
370 if (lstat (new, &st) == 0 || errno == EOVERFLOW)
371 {
372 errno = EEXIST;
373 return -1;
374 }
375 if (errno != ENOENT)
376 return -1;
377 }
314 378
315 /* Insert the `.#'. */ 379 return rename (old, new);
316 p[1] = '.'; 380#endif
317 p[2] = '#'; 381}
318 382
319 p = p + length + 2; 383/* Create the lock file FILE with contents CONTENTS. Return 0 if
384 successful, an errno value on failure. If FORCE, remove any
385 existing FILE if necessary. */
320 386
321 while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode)) 387static int
388create_lock_file (char *lfname, char *lock_info_str, bool force)
389{
390#ifdef WINDOWSNT
391 /* Symlinks are supported only by later versions of Windows, and
392 creating them is a privileged operation that often triggers
393 User Account Control elevation prompts. Avoid the problem by
394 pretending that 'symlink' does not work. */
395 int err = ENOSYS;
396#else
397 int err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
398#endif
399
400 if (err == EEXIST && force)
401 {
402 unlink (lfname);
403 err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
404 }
405
406 if (err == ENOSYS || err == LINKS_MIGHT_NOT_WORK || err == ENAMETOOLONG)
322 { 407 {
323 if (count > 9) 408 static char const nonce_base[] = ".#-emacsXXXXXX";
409 char *last_slash = strrchr (lfname, '/');
410 ptrdiff_t lfdirlen = last_slash + 1 - lfname;
411 USE_SAFE_ALLOCA;
412 char *nonce = SAFE_ALLOCA (lfdirlen + sizeof nonce_base);
413 int fd;
414 bool need_fchmod;
415 mode_t world_readable = S_IRUSR | S_IRGRP | S_IROTH;
416 memcpy (nonce, lfname, lfdirlen);
417 strcpy (nonce + lfdirlen, nonce_base);
418
419#if HAVE_MKSTEMP
420 /* Prefer mkstemp if available, as it avoids a race between
421 mktemp and emacs_open. */
422 fd = mkstemp (nonce);
423 need_fchmod = 1;
424#else
425 mktemp (nonce);
426 fd = emacs_open (nonce, O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
427 world_readable);
428 need_fchmod = 0;
429#endif
430
431 if (fd < 0)
432 err = errno;
433 else
324 { 434 {
325 *p = '\0'; 435 ptrdiff_t lock_info_len = strlen (lock_info_str);
326 return; 436 err = 0;
437 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
438 || (need_fchmod && fchmod (fd, world_readable) != 0))
439 err = errno;
440 if (emacs_close (fd) != 0)
441 err = errno;
442 if (!err && rename_lock_file (nonce, lfname, force) != 0)
443 err = errno;
444 if (err)
445 unlink (nonce);
327 } 446 }
328 sprintf (p, ".%d", count++); 447
448 SAFE_FREE ();
329 } 449 }
450
451 return err;
330} 452}
331 453
332/* Lock the lock file named LFNAME. 454/* Lock the lock file named LFNAME.
333 If FORCE, do so even if it is already locked. 455 If FORCE, do so even if it is already locked.
334 Return true if successful. */ 456 Return 0 if successful, an error number on failure. */
335 457
336static bool 458static int
337lock_file_1 (char *lfname, bool force) 459lock_file_1 (char *lfname, bool force)
338{ 460{
339 int err;
340 int symlink_errno;
341 USE_SAFE_ALLOCA;
342
343 /* Call this first because it can GC. */ 461 /* Call this first because it can GC. */
344 printmax_t boot = get_boot_time (); 462 printmax_t boot = get_boot_time ();
345 463
@@ -347,26 +465,16 @@ lock_file_1 (char *lfname, bool force)
347 char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : ""; 465 char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : "";
348 Lisp_Object lhost_name = Fsystem_name (); 466 Lisp_Object lhost_name = Fsystem_name ();
349 char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : ""; 467 char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : "";
350 ptrdiff_t lock_info_size = (strlen (user_name) + strlen (host_name) 468 char lock_info_str[MAX_LFINFO + 1];
351 + 2 * INT_STRLEN_BOUND (printmax_t)
352 + sizeof "@.:");
353 char *lock_info_str = SAFE_ALLOCA (lock_info_size);
354 printmax_t pid = getpid (); 469 printmax_t pid = getpid ();
355 470
356 esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, 471 if (sizeof lock_info_str
357 user_name, host_name, pid, boot); 472 <= snprintf (lock_info_str, sizeof lock_info_str,
358 473 boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd,
359 err = symlink (lock_info_str, lfname); 474 user_name, host_name, pid, boot))
360 if (errno == EEXIST && force) 475 return ENAMETOOLONG;
361 {
362 unlink (lfname);
363 err = symlink (lock_info_str, lfname);
364 }
365 476
366 symlink_errno = errno; 477 return create_lock_file (lfname, lock_info_str, force);
367 SAFE_FREE ();
368 errno = symlink_errno;
369 return err == 0;
370} 478}
371 479
372/* Return true if times A and B are no more than one second apart. */ 480/* 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)
377 return (a - b >= -1 && a - b <= 1); 485 return (a - b >= -1 && a - b <= 1);
378} 486}
379 487
488/* On systems lacking ELOOP, test for an errno value that shouldn't occur. */
489#ifndef ELOOP
490# define ELOOP (-1)
491#endif
492
493/* Read the data for the lock file LFNAME into LFINFO. Read at most
494 MAX_LFINFO + 1 bytes. Return the number of bytes read, or -1
495 (setting errno) on error. */
496
497static ptrdiff_t
498read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
499{
500 ptrdiff_t nbytes;
501
502 while ((nbytes = readlinkat (AT_FDCWD, lfname, lfinfo, MAX_LFINFO + 1)) < 0
503 && errno == EINVAL)
504 {
505 int fd = emacs_open (lfname, O_RDONLY | O_BINARY | O_NOFOLLOW, 0);
506 if (0 <= fd)
507 {
508 ptrdiff_t read_bytes = emacs_read (fd, lfinfo, MAX_LFINFO + 1);
509 int read_errno = errno;
510 if (emacs_close (fd) != 0)
511 return -1;
512 errno = read_errno;
513 return read_bytes;
514 }
515
516 if (errno != ELOOP)
517 return -1;
518
519 /* readlinkat saw a non-symlink, but emacs_open saw a symlink.
520 The former must have been removed and replaced by the latter.
521 Try again. */
522 QUIT;
523 }
524
525 return nbytes;
526}
527
380/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, 528/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
381 1 if another process owns it (and set OWNER (if non-null) to info), 529 1 if another process owns it (and set OWNER (if non-null) to info),
382 2 if the current process owns it, 530 2 if the current process owns it,
@@ -386,85 +534,78 @@ static int
386current_lock_owner (lock_info_type *owner, char *lfname) 534current_lock_owner (lock_info_type *owner, char *lfname)
387{ 535{
388 int ret; 536 int ret;
389 ptrdiff_t len;
390 lock_info_type local_owner; 537 lock_info_type local_owner;
391 intmax_t n; 538 ptrdiff_t lfinfolen;
392 char *at, *dot, *colon; 539 intmax_t pid, boot_time;
393 char readlink_buf[READLINK_BUFSIZE]; 540 char *at, *dot, *lfinfo_end;
394 char *lfinfo = emacs_readlink (lfname, readlink_buf);
395
396 /* If nonexistent lock file, all is well; otherwise, got strange error. */
397 if (!lfinfo)
398 return errno == ENOENT ? 0 : -1;
399 541
400 /* Even if the caller doesn't want the owner info, we still have to 542 /* Even if the caller doesn't want the owner info, we still have to
401 read it to determine return value. */ 543 read it to determine return value. */
402 if (!owner) 544 if (!owner)
403 owner = &local_owner; 545 owner = &local_owner;
404 546
547 /* If nonexistent lock file, all is well; otherwise, got strange error. */
548 lfinfolen = read_lock_data (lfname, owner->user);
549 if (lfinfolen < 0)
550 return errno == ENOENT ? 0 : -1;
551 if (MAX_LFINFO < lfinfolen)
552 return -1;
553 owner->user[lfinfolen] = 0;
554
405 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */ 555 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */
406 /* The USER is everything before the last @. */ 556 /* The USER is everything before the last @. */
407 at = strrchr (lfinfo, '@'); 557 owner->at = at = memrchr (owner->user, '@', lfinfolen);
408 dot = strrchr (lfinfo, '.'); 558 if (!at)
409 if (!at || !dot) 559 return -1;
410 { 560 owner->dot = dot = strrchr (at, '.');
411 if (lfinfo != readlink_buf) 561 if (!dot)
412 xfree (lfinfo); 562 return -1;
413 return -1;
414 }
415 len = at - lfinfo;
416 owner->user = xmalloc (len + 1);
417 memcpy (owner->user, lfinfo, len);
418 owner->user[len] = 0;
419 563
420 /* The PID is everything from the last `.' to the `:'. */ 564 /* The PID is everything from the last `.' to the `:'. */
565 if (! c_isdigit (dot[1]))
566 return -1;
421 errno = 0; 567 errno = 0;
422 n = strtoimax (dot + 1, NULL, 10); 568 pid = strtoimax (dot + 1, &owner->colon, 10);
423 owner->pid = 569 if (errno == ERANGE)
424 ((0 <= n && n <= TYPE_MAXIMUM (pid_t) 570 pid = -1;
425 && (TYPE_MAXIMUM (pid_t) < INTMAX_MAX || errno != ERANGE))
426 ? n : 0);
427 571
428 colon = strchr (dot + 1, ':');
429 /* After the `:', if there is one, comes the boot time. */ 572 /* After the `:', if there is one, comes the boot time. */
430 n = 0; 573 switch (owner->colon[0])
431 if (colon)
432 { 574 {
433 errno = 0; 575 case 0:
434 n = strtoimax (colon + 1, NULL, 10); 576 boot_time = 0;
435 } 577 lfinfo_end = owner->colon;
436 owner->boot_time = 578 break;
437 ((0 <= n && n <= TYPE_MAXIMUM (time_t)
438 && (TYPE_MAXIMUM (time_t) < INTMAX_MAX || errno != ERANGE))
439 ? n : 0);
440 579
441 /* The host is everything in between. */ 580 case ':':
442 len = dot - at - 1; 581 if (! c_isdigit (owner->colon[1]))
443 owner->host = xmalloc (len + 1); 582 return -1;
444 memcpy (owner->host, at + 1, len); 583 boot_time = strtoimax (owner->colon + 1, &lfinfo_end, 10);
445 owner->host[len] = 0; 584 break;
446 585
447 /* We're done looking at the link info. */ 586 default:
448 if (lfinfo != readlink_buf) 587 return -1;
449 xfree (lfinfo); 588 }
589 if (lfinfo_end != owner->user + lfinfolen)
590 return -1;
450 591
451 /* On current host? */ 592 /* On current host? */
452 if (STRINGP (Fsystem_name ()) 593 if (STRINGP (Vsystem_name)
453 && strcmp (owner->host, SSDATA (Fsystem_name ())) == 0) 594 && dot - (at + 1) == SBYTES (Vsystem_name)
595 && memcmp (at + 1, SSDATA (Vsystem_name), SBYTES (Vsystem_name)) == 0)
454 { 596 {
455 if (owner->pid == getpid ()) 597 if (pid == getpid ())
456 ret = 2; /* We own it. */ 598 ret = 2; /* We own it. */
457 else if (owner->pid > 0 599 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
458 && (kill (owner->pid, 0) >= 0 || errno == EPERM) 600 && (kill (pid, 0) >= 0 || errno == EPERM)
459 && (owner->boot_time == 0 601 && (boot_time == 0
460 || within_one_second (owner->boot_time, get_boot_time ()))) 602 || (boot_time <= TYPE_MAXIMUM (time_t)
603 && within_one_second (boot_time, get_boot_time ()))))
461 ret = 1; /* An existing process on this machine owns it. */ 604 ret = 1; /* An existing process on this machine owns it. */
462 /* The owner process is dead or has a strange pid (<=0), so try to 605 /* The owner process is dead or has a strange pid, so try to
463 zap the lockfile. */ 606 zap the lockfile. */
464 else if (unlink (lfname) < 0)
465 ret = -1;
466 else 607 else
467 ret = 0; 608 return unlink (lfname);
468 } 609 }
469 else 610 else
470 { /* If we wanted to support the check for stale locks on remote machines, 611 { /* 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)
472 ret = 1; 613 ret = 1;
473 } 614 }
474 615
475 /* Avoid garbage. */
476 if (owner == &local_owner || ret <= 0)
477 {
478 FREE_LOCK_INFO (*owner);
479 }
480 return ret; 616 return ret;
481} 617}
482 618
@@ -488,29 +624,25 @@ current_lock_owner (lock_info_type *owner, char *lfname)
488 Return -1 if cannot lock for any other reason. */ 624 Return -1 if cannot lock for any other reason. */
489 625
490static int 626static int
491lock_if_free (lock_info_type *clasher, register char *lfname) 627lock_if_free (lock_info_type *clasher, char *lfname)
492{ 628{
493 while (! lock_file_1 (lfname, 0)) 629 int err;
630 while ((err = lock_file_1 (lfname, 0)) == EEXIST)
494 { 631 {
495 int locker; 632 switch (current_lock_owner (clasher, lfname))
496 633 {
497 if (errno != EEXIST) 634 case 2:
498 return -1; 635 return 0; /* We ourselves locked it. */
499 636 case 1:
500 locker = current_lock_owner (clasher, lfname); 637 return 1; /* Someone else has it. */
501 if (locker == 2) 638 case -1:
502 { 639 return -1; /* current_lock_owner returned strange error. */
503 FREE_LOCK_INFO (*clasher); 640 }
504 return 0; /* We ourselves locked it. */
505 }
506 else if (locker == 1)
507 return 1; /* Someone else has it. */
508 else if (locker == -1)
509 return -1; /* current_lock_owner returned strange error. */
510 641
511 /* We deleted a stale lock; try again to lock the file. */ 642 /* We deleted a stale lock; try again to lock the file. */
512 } 643 }
513 return 0; 644
645 return err ? -1 : 0;
514} 646}
515 647
516/* lock_file locks file FN, 648/* lock_file locks file FN,
@@ -522,6 +654,7 @@ lock_if_free (lock_info_type *clasher, register char *lfname)
522 decided to go ahead without locking. 654 decided to go ahead without locking.
523 655
524 When this returns, either the lock is locked for us, 656 When this returns, either the lock is locked for us,
657 or lock creation failed,
525 or the user has said to go ahead without locking. 658 or the user has said to go ahead without locking.
526 659
527 If the file is locked by someone else, this calls 660 If the file is locked by someone else, this calls
@@ -533,11 +666,9 @@ lock_if_free (lock_info_type *clasher, register char *lfname)
533void 666void
534lock_file (Lisp_Object fn) 667lock_file (Lisp_Object fn)
535{ 668{
536 register Lisp_Object attack, orig_fn, encoded_fn; 669 Lisp_Object orig_fn, encoded_fn;
537 register char *lfname, *locker; 670 char *lfname;
538 ptrdiff_t locker_size;
539 lock_info_type lock_info; 671 lock_info_type lock_info;
540 printmax_t pid;
541 struct gcpro gcpro1; 672 struct gcpro gcpro1;
542 USE_SAFE_ALLOCA; 673 USE_SAFE_ALLOCA;
543 674
@@ -554,6 +685,12 @@ lock_file (Lisp_Object fn)
554 orig_fn = fn; 685 orig_fn = fn;
555 GCPRO1 (fn); 686 GCPRO1 (fn);
556 fn = Fexpand_file_name (fn, Qnil); 687 fn = Fexpand_file_name (fn, Qnil);
688#ifdef WINDOWSNT
689 /* Ensure we have only '/' separators, to avoid problems with
690 looking (inside fill_in_lock_file_name) for backslashes in file
691 names encoded by some DBCS codepage. */
692 dostounix_filename (SSDATA (fn), 1);
693#endif
557 encoded_fn = ENCODE_FILE (fn); 694 encoded_fn = ENCODE_FILE (fn);
558 695
559 /* Create the name of the lock-file for file fn */ 696 /* Create the name of the lock-file for file fn */
@@ -572,38 +709,35 @@ lock_file (Lisp_Object fn)
572 call1 (intern ("ask-user-about-supersession-threat"), fn); 709 call1 (intern ("ask-user-about-supersession-threat"), fn);
573 710
574 } 711 }
575 UNGCPRO;
576 712
577 /* Try to lock the lock. */ 713 /* Try to lock the lock. */
578 if (lock_if_free (&lock_info, lfname) <= 0) 714 if (0 < lock_if_free (&lock_info, lfname))
579 /* Return now if we have locked it, or if lock creation failed */
580 return;
581
582 /* Else consider breaking the lock */
583 locker_size = (strlen (lock_info.user) + strlen (lock_info.host)
584 + INT_STRLEN_BOUND (printmax_t)
585 + sizeof "@ (pid )");
586 locker = SAFE_ALLOCA (locker_size);
587 pid = lock_info.pid;
588 esprintf (locker, "%s@%s (pid %"pMd")",
589 lock_info.user, lock_info.host, pid);
590 FREE_LOCK_INFO (lock_info);
591
592 attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
593 SAFE_FREE ();
594 if (!NILP (attack))
595 /* User says take the lock */
596 { 715 {
597 lock_file_1 (lfname, 1); 716 /* Someone else has the lock. Consider breaking it. */
598 return; 717 Lisp_Object attack;
718 char *dot = lock_info.dot;
719 ptrdiff_t pidlen = lock_info.colon - (dot + 1);
720 static char const replacement[] = " (pid ";
721 int replacementlen = sizeof replacement - 1;
722 memmove (dot + replacementlen, dot + 1, pidlen);
723 strcpy (dot + replacementlen + pidlen, ")");
724 memcpy (dot, replacement, replacementlen);
725 attack = call2 (intern ("ask-user-about-lock"), fn,
726 build_string (lock_info.user));
727 /* Take the lock if the user said so. */
728 if (!NILP (attack))
729 lock_file_1 (lfname, 1);
599 } 730 }
600 /* User says ignore the lock */ 731
732 UNGCPRO;
733 SAFE_FREE ();
601} 734}
602 735
603void 736void
604unlock_file (register Lisp_Object fn) 737unlock_file (Lisp_Object fn)
605{ 738{
606 register char *lfname; 739 char *lfname;
740 USE_SAFE_ALLOCA;
607 741
608 fn = Fexpand_file_name (fn, Qnil); 742 fn = Fexpand_file_name (fn, Qnil);
609 fn = ENCODE_FILE (fn); 743 fn = ENCODE_FILE (fn);
@@ -612,6 +746,8 @@ unlock_file (register Lisp_Object fn)
612 746
613 if (current_lock_owner (0, lfname) == 2) 747 if (current_lock_owner (0, lfname) == 2)
614 unlink (lfname); 748 unlink (lfname);
749
750 SAFE_FREE ();
615} 751}
616 752
617void 753void
@@ -677,9 +813,10 @@ t if it is locked by you, else a string saying which user has locked it. */)
677 (Lisp_Object filename) 813 (Lisp_Object filename)
678{ 814{
679 Lisp_Object ret; 815 Lisp_Object ret;
680 register char *lfname; 816 char *lfname;
681 int owner; 817 int owner;
682 lock_info_type locker; 818 lock_info_type locker;
819 USE_SAFE_ALLOCA;
683 820
684 filename = Fexpand_file_name (filename, Qnil); 821 filename = Fexpand_file_name (filename, Qnil);
685 822
@@ -691,11 +828,9 @@ t if it is locked by you, else a string saying which user has locked it. */)
691 else if (owner == 2) 828 else if (owner == 2)
692 ret = Qt; 829 ret = Qt;
693 else 830 else
694 ret = build_string (locker.user); 831 ret = make_string (locker.user, locker.at - locker.user);
695
696 if (owner > 0)
697 FREE_LOCK_INFO (locker);
698 832
833 SAFE_FREE ();
699 return ret; 834 return ret;
700} 835}
701 836
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.
66 66
67With positive integer LIMIT, return random number in interval [0,LIMIT). 67With positive integer LIMIT, return random number in interval [0,LIMIT).
68With argument t, set the random number seed from the current time and pid. 68With argument t, set the random number seed from the current time and pid.
69Other values of LIMIT are ignored. */) 69With a string argument, set the seed based on the string's contents.
70Other values of LIMIT are ignored.
71
72See Info node `(elisp)Random Numbers' for more details. */)
70 (Lisp_Object limit) 73 (Lisp_Object limit)
71{ 74{
72 EMACS_INT val; 75 EMACS_INT val;
@@ -2482,7 +2485,7 @@ is nil, and `use-dialog-box' is non-nil. */)
2482 2485
2483 Fding (Qnil); 2486 Fding (Qnil);
2484 Fdiscard_input (); 2487 Fdiscard_input ();
2485 message ("Please answer yes or no."); 2488 message1 ("Please answer yes or no.");
2486 Fsleep_for (make_number (2), Qnil); 2489 Fsleep_for (make_number (2), Qnil);
2487 } 2490 }
2488} 2491}
@@ -2742,7 +2745,7 @@ ARGS are passed as extra arguments to the function.
2742usage: (widget-apply WIDGET PROPERTY &rest ARGS) */) 2745usage: (widget-apply WIDGET PROPERTY &rest ARGS) */)
2743 (ptrdiff_t nargs, Lisp_Object *args) 2746 (ptrdiff_t nargs, Lisp_Object *args)
2744{ 2747{
2745 /* This function can GC. */ 2748 /* This function can GC. */
2746 Lisp_Object newargs[3]; 2749 Lisp_Object newargs[3];
2747 struct gcpro gcpro1, gcpro2; 2750 struct gcpro gcpro1, gcpro2;
2748 Lisp_Object result; 2751 Lisp_Object result;
@@ -2804,9 +2807,8 @@ The data read from the system are decoded using `locale-coding-system'. */)
2804 val = build_unibyte_string (str); 2807 val = build_unibyte_string (str);
2805 /* Fixme: Is this coding system necessarily right, even if 2808 /* Fixme: Is this coding system necessarily right, even if
2806 it is consistent with CODESET? If not, what to do? */ 2809 it is consistent with CODESET? If not, what to do? */
2807 Faset (v, make_number (i), 2810 ASET (v, i, code_convert_string_norecord (val, Vlocale_coding_system,
2808 code_convert_string_norecord (val, Vlocale_coding_system, 2811 0));
2809 0));
2810 } 2812 }
2811 UNGCPRO; 2813 UNGCPRO;
2812 return v; 2814 return v;
@@ -2826,8 +2828,8 @@ The data read from the system are decoded using `locale-coding-system'. */)
2826 { 2828 {
2827 str = nl_langinfo (months[i]); 2829 str = nl_langinfo (months[i]);
2828 val = build_unibyte_string (str); 2830 val = build_unibyte_string (str);
2829 Faset (v, make_number (i), 2831 ASET (v, i, code_convert_string_norecord (val, Vlocale_coding_system,
2830 code_convert_string_norecord (val, Vlocale_coding_system, 0)); 2832 0));
2831 } 2833 }
2832 UNGCPRO; 2834 UNGCPRO;
2833 return v; 2835 return v;
@@ -2837,10 +2839,7 @@ The data read from the system are decoded using `locale-coding-system'. */)
2837 but is in the locale files. This could be used by ps-print. */ 2839 but is in the locale files. This could be used by ps-print. */
2838#ifdef PAPER_WIDTH 2840#ifdef PAPER_WIDTH
2839 else if (EQ (item, Qpaper)) 2841 else if (EQ (item, Qpaper))
2840 { 2842 return list2i (nl_langinfo (PAPER_WIDTH), nl_langinfo (PAPER_HEIGHT));
2841 return list2 (make_number (nl_langinfo (PAPER_WIDTH)),
2842 make_number (nl_langinfo (PAPER_HEIGHT)));
2843 }
2844#endif /* PAPER_WIDTH */ 2843#endif /* PAPER_WIDTH */
2845#endif /* HAVE_LANGINFO_CODESET*/ 2844#endif /* HAVE_LANGINFO_CODESET*/
2846 return Qnil; 2845 return Qnil;
@@ -4043,10 +4042,6 @@ sweep_weak_hash_tables (void)
4043 4042
4044#define SXHASH_MAX_LEN 7 4043#define SXHASH_MAX_LEN 7
4045 4044
4046/* Hash X, returning a value that fits into a Lisp integer. */
4047#define SXHASH_REDUCE(X) \
4048 ((((X) ^ (X) >> (BITS_PER_EMACS_INT - FIXNUM_BITS))) & INTMASK)
4049
4050/* Return a hash for string PTR which has length LEN. The hash value 4045/* Return a hash for string PTR which has length LEN. The hash value
4051 can be any EMACS_UINT value. */ 4046 can be any EMACS_UINT value. */
4052 4047
@@ -4079,7 +4074,7 @@ sxhash_string (char const *ptr, ptrdiff_t len)
4079 4074
4080/* Return a hash for the floating point value VAL. */ 4075/* Return a hash for the floating point value VAL. */
4081 4076
4082static EMACS_INT 4077static EMACS_UINT
4083sxhash_float (double val) 4078sxhash_float (double val)
4084{ 4079{
4085 EMACS_UINT hash = 0; 4080 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)
717} 717}
718 718
719 719
720/* Font name parser and unparser */ 720/* Font name parser and unparser. */
721 721
722static int parse_matrix (const char *); 722static int parse_matrix (const char *);
723static int font_expand_wildcards (Lisp_Object *, int); 723static int font_expand_wildcards (Lisp_Object *, int);
@@ -1746,7 +1746,7 @@ font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Objec
1746/* This part (through the next ^L) is still experimental and not 1746/* This part (through the next ^L) is still experimental and not
1747 tested much. We may drastically change codes. */ 1747 tested much. We may drastically change codes. */
1748 1748
1749/* OTF handler */ 1749/* OTF handler. */
1750 1750
1751#if 0 1751#if 0
1752 1752
@@ -1861,7 +1861,7 @@ otf_open (Lisp_Object file)
1861 else 1861 else
1862 { 1862 {
1863 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL; 1863 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
1864 val = make_save_value (otf, 0); 1864 val = make_save_pointer (otf);
1865 otf_list = Fcons (Fcons (file, val), otf_list); 1865 otf_list = Fcons (Fcons (file, val), otf_list);
1866 } 1866 }
1867 return otf; 1867 return otf;
@@ -2035,7 +2035,7 @@ font_otf_Anchor (OTF_Anchor *anchor)
2035#endif /* 0 */ 2035#endif /* 0 */
2036 2036
2037 2037
2038/* Font sorting */ 2038/* Font sorting. */
2039 2039
2040static unsigned font_score (Lisp_Object, Lisp_Object *); 2040static unsigned font_score (Lisp_Object, Lisp_Object *);
2041static int font_compare (const void *, const void *); 2041static int font_compare (const void *, const void *);
@@ -2565,7 +2565,6 @@ font_get_cache (FRAME_PTR f, struct font_driver *driver)
2565 return val; 2565 return val;
2566} 2566}
2567 2567
2568static int num_fonts;
2569 2568
2570static void 2569static void
2571font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver) 2570font_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)
2598 { 2597 {
2599 eassert (font && driver == font->driver); 2598 eassert (font && driver == font->driver);
2600 driver->close (f, font); 2599 driver->close (f, font);
2601 num_fonts--;
2602 } 2600 }
2603 } 2601 }
2604 if (driver->free_entity) 2602 if (driver->free_entity)
@@ -2856,7 +2854,6 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
2856 return Qnil; 2854 return Qnil;
2857 ASET (entity, FONT_OBJLIST_INDEX, 2855 ASET (entity, FONT_OBJLIST_INDEX,
2858 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX))); 2856 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2859 num_fonts++;
2860 2857
2861 font = XFONT_OBJECT (font_object); 2858 font = XFONT_OBJECT (font_object);
2862 min_width = (font->min_width ? font->min_width 2859 min_width = (font->min_width ? font->min_width
@@ -2901,7 +2898,6 @@ font_close_object (FRAME_PTR f, Lisp_Object font_object)
2901 eassert (FRAME_X_DISPLAY_INFO (f)->n_fonts); 2898 eassert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2902 FRAME_X_DISPLAY_INFO (f)->n_fonts--; 2899 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2903#endif 2900#endif
2904 num_fonts--;
2905} 2901}
2906 2902
2907 2903
@@ -3578,7 +3574,7 @@ font_filter_properties (Lisp_Object font,
3578 Lisp_Object it; 3574 Lisp_Object it;
3579 int i; 3575 int i;
3580 3576
3581 /* Set boolean values to Qt or Qnil */ 3577 /* Set boolean values to Qt or Qnil. */
3582 for (i = 0; boolean_properties[i] != NULL; ++i) 3578 for (i = 0; boolean_properties[i] != NULL; ++i)
3583 for (it = alist; ! NILP (it); it = XCDR (it)) 3579 for (it = alist; ! NILP (it); it = XCDR (it))
3584 { 3580 {
@@ -3693,11 +3689,11 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
3693 3689
3694#ifdef HAVE_WINDOW_SYSTEM 3690#ifdef HAVE_WINDOW_SYSTEM
3695 3691
3696/* Check how many characters after POS (at most to *LIMIT) can be 3692/* Check how many characters after character/byte position POS/POS_BYTE
3697 displayed by the same font in the window W. FACE, if non-NULL, is 3693 (at most to *LIMIT) can be displayed by the same font in the window W.
3698 the face selected for the character at POS. If STRING is not nil, 3694 FACE, if non-NULL, is the face selected for the character at POS.
3699 it is the string to check instead of the current buffer. In that 3695 If STRING is not nil, it is the string to check instead of the current
3700 case, FACE must be not NULL. 3696 buffer. In that case, FACE must be not NULL.
3701 3697
3702 The return value is the font-object for the character at POS. 3698 The return value is the font-object for the character at POS.
3703 *LIMIT is set to the position where that font can't be used. 3699 *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,
3705 It is assured that the current buffer (or STRING) is multibyte. */ 3701 It is assured that the current buffer (or STRING) is multibyte. */
3706 3702
3707Lisp_Object 3703Lisp_Object
3708font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face, Lisp_Object string) 3704font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
3705 struct window *w, struct face *face, Lisp_Object string)
3709{ 3706{
3710 ptrdiff_t pos_byte, ignore; 3707 ptrdiff_t ignore;
3711 int c; 3708 int c;
3712 Lisp_Object font_object = Qnil; 3709 Lisp_Object font_object = Qnil;
3713 3710
3714 if (NILP (string)) 3711 if (NILP (string))
3715 { 3712 {
3716 pos_byte = CHAR_TO_BYTE (pos);
3717 if (! face) 3713 if (! face)
3718 { 3714 {
3719 int face_id; 3715 int face_id;
@@ -3724,10 +3720,7 @@ font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face
3724 } 3720 }
3725 } 3721 }
3726 else 3722 else
3727 { 3723 eassert (face);
3728 eassert (face);
3729 pos_byte = string_char_to_byte (string, pos);
3730 }
3731 3724
3732 while (pos < *limit) 3725 while (pos < *limit)
3733 { 3726 {
@@ -3757,7 +3750,7 @@ font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face
3757#endif 3750#endif
3758 3751
3759 3752
3760/* Lisp API */ 3753/* Lisp API. */
3761 3754
3762DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0, 3755DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3763 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object. 3756 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. */)
4607 4600
4608 CHECK_FONT_GET_OBJECT (font_object, font); 4601 CHECK_FONT_GET_OBJECT (font_object, font);
4609 4602
4610 val = Fmake_vector (make_number (9), Qnil); 4603 val = make_uninit_vector (9);
4611 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX)); 4604 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4612 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX)); 4605 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4613 ASET (val, 2, make_number (font->pixel_size)); 4606 ASET (val, 2, make_number (font->pixel_size));
@@ -4618,6 +4611,8 @@ If the font is not OpenType font, CAPABILITY is nil. */)
4618 ASET (val, 7, make_number (font->average_width)); 4611 ASET (val, 7, make_number (font->average_width));
4619 if (font->driver->otf_capability) 4612 if (font->driver->otf_capability)
4620 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font))); 4613 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4614 else
4615 ASET (val, 8, Qnil);
4621 return val; 4616 return val;
4622} 4617}
4623 4618
@@ -4710,7 +4705,7 @@ the corresponding element is nil. */)
4710 chars = aref_addr (object, XFASTINT (from)); 4705 chars = aref_addr (object, XFASTINT (from));
4711 } 4706 }
4712 4707
4713 vec = Fmake_vector (make_number (len), Qnil); 4708 vec = make_uninit_vector (len);
4714 for (i = 0; i < len; i++) 4709 for (i = 0; i < len; i++)
4715 { 4710 {
4716 Lisp_Object g; 4711 Lisp_Object g;
@@ -4720,8 +4715,11 @@ the corresponding element is nil. */)
4720 4715
4721 code = font->driver->encode_char (font, c); 4716 code = font->driver->encode_char (font, c);
4722 if (code == FONT_INVALID_CODE) 4717 if (code == FONT_INVALID_CODE)
4723 continue; 4718 {
4724 g = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); 4719 ASET (vec, i, Qnil);
4720 continue;
4721 }
4722 g = LGLYPH_NEW ();
4725 LGLYPH_SET_FROM (g, i); 4723 LGLYPH_SET_FROM (g, i);
4726 LGLYPH_SET_TO (g, i); 4724 LGLYPH_SET_TO (g, i);
4727 LGLYPH_SET_CHAR (g, c); 4725 LGLYPH_SET_CHAR (g, c);
@@ -4833,7 +4831,7 @@ where
4833 OPENED-NAME is the name used for opening the font, 4831 OPENED-NAME is the name used for opening the font,
4834 FULL-NAME is the full name of the font, 4832 FULL-NAME is the full name of the font,
4835 SIZE is the pixelsize of the font, 4833 SIZE is the pixelsize of the font,
4836 HEIGHT is the pixel-height of the font (i.e ascent + descent), 4834 HEIGHT is the pixel-height of the font (i.e., ascent + descent),
4837 BASELINE-OFFSET is the upward offset pixels from ASCII baseline, 4835 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4838 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling 4836 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4839 how to compose characters. 4837 how to compose characters.
@@ -4874,7 +4872,7 @@ If the named font is not yet loaded, return nil. */)
4874 return Qnil; 4872 return Qnil;
4875 font = XFONT_OBJECT (font_object); 4873 font = XFONT_OBJECT (font_object);
4876 4874
4877 info = Fmake_vector (make_number (7), Qnil); 4875 info = make_uninit_vector (7);
4878 ASET (info, 0, AREF (font_object, FONT_NAME_INDEX)); 4876 ASET (info, 0, AREF (font_object, FONT_NAME_INDEX));
4879 ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX)); 4877 ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX));
4880 ASET (info, 2, make_number (font->pixel_size)); 4878 ASET (info, 2, make_number (font->pixel_size));
@@ -4903,7 +4901,7 @@ build_style_table (const struct table_entry *entry, int nelement)
4903 int i, j; 4901 int i, j;
4904 Lisp_Object table, elt; 4902 Lisp_Object table, elt;
4905 4903
4906 table = Fmake_vector (make_number (nelement), Qnil); 4904 table = make_uninit_vector (nelement);
4907 for (i = 0; i < nelement; i++) 4905 for (i = 0; i < nelement; i++)
4908 { 4906 {
4909 for (j = 0; entry[i].names[j]; j++); 4907 for (j = 0; entry[i].names[j]; j++);
@@ -5167,7 +5165,7 @@ See `font-weight-table' for the format of the vector. */);
5167 XSYMBOL (intern_c_string ("font-width-table"))->constant = 1; 5165 XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
5168 5166
5169 staticpro (&font_style_table); 5167 staticpro (&font_style_table);
5170 font_style_table = Fmake_vector (make_number (3), Qnil); 5168 font_style_table = make_uninit_vector (3);
5171 ASET (font_style_table, 0, Vfont_weight_table); 5169 ASET (font_style_table, 0, Vfont_weight_table);
5172 ASET (font_style_table, 1, Vfont_slant_table); 5170 ASET (font_style_table, 1, Vfont_slant_table);
5173 ASET (font_style_table, 2, Vfont_width_table); 5171 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,
781extern void register_font_driver (struct font_driver *driver, FRAME_PTR f); 781extern void register_font_driver (struct font_driver *driver, FRAME_PTR f);
782extern void free_font_driver_list (FRAME_PTR f); 782extern void free_font_driver_list (FRAME_PTR f);
783extern Lisp_Object font_update_drivers (FRAME_PTR f, Lisp_Object list); 783extern Lisp_Object font_update_drivers (FRAME_PTR f, Lisp_Object list);
784extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t *, 784extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *,
785 struct window *, struct face *, 785 struct window *, struct face *,
786 Lisp_Object); 786 Lisp_Object);
787extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object); 787extern 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)
271/* Macros for FONT-DEF and RFONT-DEF of fontset. */ 271/* Macros for FONT-DEF and RFONT-DEF of fontset. */
272#define FONT_DEF_NEW(font_def, font_spec, encoding, repertory) \ 272#define FONT_DEF_NEW(font_def, font_spec, encoding, repertory) \
273 do { \ 273 do { \
274 (font_def) = Fmake_vector (make_number (3), (font_spec)); \ 274 (font_def) = make_uninit_vector (3); \
275 ASET ((font_def), 0, font_spec); \
275 ASET ((font_def), 1, encoding); \ 276 ASET ((font_def), 1, encoding); \
276 ASET ((font_def), 2, repertory); \ 277 ASET ((font_def), 2, repertory); \
277 } while (0) 278 } while (0)
@@ -1591,7 +1592,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
1591 { 1592 {
1592 Lisp_Object arg; 1593 Lisp_Object arg;
1593 1594
1594 arg = Fmake_vector (make_number (5), Qnil); 1595 arg = make_uninit_vector (5);
1595 ASET (arg, 0, fontset); 1596 ASET (arg, 0, fontset);
1596 ASET (arg, 1, font_def); 1597 ASET (arg, 1, font_def);
1597 ASET (arg, 2, add); 1598 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)
500 tty_frame_count = 1; 500 tty_frame_count = 1;
501 fset_name (f, build_pure_c_string ("F1")); 501 fset_name (f, build_pure_c_string ("F1"));
502 502
503 f->visible = 1; 503 SET_FRAME_VISIBLE (f, 1);
504 f->async_visible = 1;
505 504
506 f->output_method = terminal->type; 505 f->output_method = terminal->type;
507 f->terminal = terminal; 506 f->terminal = terminal;
@@ -540,8 +539,8 @@ make_terminal_frame (struct terminal *terminal)
540 539
541 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count)); 540 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
542 541
543 f->visible = 1; /* FRAME_SET_VISIBLE wd set frame_garbaged. */ 542 SET_FRAME_VISIBLE (f, 1);
544 f->async_visible = 1; /* Don't let visible be cleared later. */ 543
545 f->terminal = terminal; 544 f->terminal = terminal;
546 f->terminal->reference_count++; 545 f->terminal->reference_count++;
547#ifdef MSDOS 546#ifdef MSDOS
@@ -565,7 +564,7 @@ make_terminal_frame (struct terminal *terminal)
565 /* Set the top frame to the newly created frame. */ 564 /* Set the top frame to the newly created frame. */
566 if (FRAMEP (FRAME_TTY (f)->top_frame) 565 if (FRAMEP (FRAME_TTY (f)->top_frame)
567 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame))) 566 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
568 XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */ 567 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
569 568
570 FRAME_TTY (f)->top_frame = frame; 569 FRAME_TTY (f)->top_frame = frame;
571 570
@@ -806,8 +805,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
806 { 805 {
807 if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame)) 806 if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame))
808 /* Mark previously displayed frame as now obscured. */ 807 /* Mark previously displayed frame as now obscured. */
809 XFRAME (FRAME_TTY (XFRAME (frame))->top_frame)->async_visible = 2; 808 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (XFRAME (frame))->top_frame), 2);
810 XFRAME (frame)->async_visible = 1; 809 SET_FRAME_VISIBLE (XFRAME (frame), 1);
811 FRAME_TTY (XFRAME (frame))->top_frame = frame; 810 FRAME_TTY (XFRAME (frame))->top_frame = frame;
812 } 811 }
813 812
@@ -914,7 +913,6 @@ candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
914 } 913 }
915 else if (EQ (minibuf, Qvisible)) 914 else if (EQ (minibuf, Qvisible))
916 { 915 {
917 FRAME_SAMPLE_VISIBILITY (c);
918 if (FRAME_VISIBLE_P (c)) 916 if (FRAME_VISIBLE_P (c))
919 return candidate; 917 return candidate;
920 } 918 }
@@ -928,7 +926,6 @@ candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
928 } 926 }
929 else if (XFASTINT (minibuf) == 0) 927 else if (XFASTINT (minibuf) == 0)
930 { 928 {
931 FRAME_SAMPLE_VISIBILITY (c);
932 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c)) 929 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
933 return candidate; 930 return candidate;
934 } 931 }
@@ -1052,10 +1049,7 @@ other_visible_frames (FRAME_PTR f)
1052 and note any recent change in visibility. */ 1049 and note any recent change in visibility. */
1053#ifdef HAVE_WINDOW_SYSTEM 1050#ifdef HAVE_WINDOW_SYSTEM
1054 if (FRAME_WINDOW_P (XFRAME (this))) 1051 if (FRAME_WINDOW_P (XFRAME (this)))
1055 { 1052 x_sync (XFRAME (this));
1056 x_sync (XFRAME (this));
1057 FRAME_SAMPLE_VISIBILITY (XFRAME (this));
1058 }
1059#endif 1053#endif
1060 1054
1061 if (FRAME_VISIBLE_P (XFRAME (this)) 1055 if (FRAME_VISIBLE_P (XFRAME (this))
@@ -1231,7 +1225,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1231 fset_root_window (f, Qnil); 1225 fset_root_window (f, Qnil);
1232 1226
1233 Vframe_list = Fdelq (frame, Vframe_list); 1227 Vframe_list = Fdelq (frame, Vframe_list);
1234 FRAME_SET_VISIBLE (f, 0); 1228 SET_FRAME_VISIBLE (f, 0);
1235 1229
1236 /* Allow the vector of menu bar contents to be freed in the next 1230 /* Allow the vector of menu bar contents to be freed in the next
1237 garbage collection. The frame object itself may not be garbage 1231 garbage collection. The frame object itself may not be garbage
@@ -1251,7 +1245,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1251 xfree (FRAME_DELETEN_COST (f)); 1245 xfree (FRAME_DELETEN_COST (f));
1252 xfree (FRAME_INSERTN_COST (f)); 1246 xfree (FRAME_INSERTN_COST (f));
1253 xfree (FRAME_DELETE_COST (f)); 1247 xfree (FRAME_DELETE_COST (f));
1254 xfree (FRAME_MESSAGE_BUF (f));
1255 1248
1256 /* Since some events are handled at the interrupt level, we may get 1249 /* Since some events are handled at the interrupt level, we may get
1257 an event for f at any time; if we zero out the frame's terminal 1250 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)
1266 { 1259 {
1267 struct terminal *terminal = FRAME_TERMINAL (f); 1260 struct terminal *terminal = FRAME_TERMINAL (f);
1268 f->output_data.nothing = 0; 1261 f->output_data.nothing = 0;
1269 f->terminal = 0; /* Now the frame is dead. */ 1262 f->terminal = 0; /* Now the frame is dead. */
1270 1263
1271 /* If needed, delete the terminal that this frame was on. 1264 /* If needed, delete the terminal that this frame was on.
1272 (This must be done after the frame is killed.) */ 1265 (This must be done after the frame is killed.) */
1273 terminal->reference_count--; 1266 terminal->reference_count--;
1274#ifdef USE_GTK 1267#ifdef USE_GTK
1275 /* FIXME: Deleting the terminal crashes emacs because of a GTK 1268 /* FIXME: Deleting the terminal crashes emacs because of a GTK
@@ -1580,10 +1573,7 @@ If omitted, FRAME defaults to the currently selected frame. */)
1580 /* I think this should be done with a hook. */ 1573 /* I think this should be done with a hook. */
1581#ifdef HAVE_WINDOW_SYSTEM 1574#ifdef HAVE_WINDOW_SYSTEM
1582 if (FRAME_WINDOW_P (f)) 1575 if (FRAME_WINDOW_P (f))
1583 { 1576 x_make_frame_visible (f);
1584 FRAME_SAMPLE_VISIBILITY (f);
1585 x_make_frame_visible (f);
1586 }
1587#endif 1577#endif
1588 1578
1589 make_frame_visible_1 (f->root_window); 1579 make_frame_visible_1 (f->root_window);
@@ -1706,8 +1696,6 @@ currently being displayed on the terminal. */)
1706{ 1696{
1707 CHECK_LIVE_FRAME (frame); 1697 CHECK_LIVE_FRAME (frame);
1708 1698
1709 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1710
1711 if (FRAME_VISIBLE_P (XFRAME (frame))) 1699 if (FRAME_VISIBLE_P (XFRAME (frame)))
1712 return Qt; 1700 return Qt;
1713 if (FRAME_ICONIFIED_P (XFRAME (frame))) 1701 if (FRAME_ICONIFIED_P (XFRAME (frame)))
@@ -2892,7 +2880,6 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
2892 make_formatted_string (buf, "%"pMu, w)); 2880 make_formatted_string (buf, "%"pMu, w));
2893#endif 2881#endif
2894 store_in_alist (alistptr, Qicon_name, f->icon_name); 2882 store_in_alist (alistptr, Qicon_name, f->icon_name);
2895 FRAME_SAMPLE_VISIBILITY (f);
2896 store_in_alist (alistptr, Qvisibility, 2883 store_in_alist (alistptr, Qvisibility,
2897 (FRAME_VISIBLE_P (f) ? Qt 2884 (FRAME_VISIBLE_P (f) ? Qt
2898 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil)); 2885 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
@@ -4246,6 +4233,16 @@ Setting this variable does not affect existing frames, only new ones. */);
4246 Vdefault_frame_scroll_bars = Qnil; 4233 Vdefault_frame_scroll_bars = Qnil;
4247#endif 4234#endif
4248 4235
4236 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
4237 scroll_bar_adjust_thumb_portion_p,
4238 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
4239Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
4240even if the end of the buffer is shown (i.e. overscrolling).
4241Set to nil if you want the thumb to be at the bottom when the end of the buffer
4242is shown. Also, the thumb fills the whole scroll bar when the entire buffer
4243is visible. In this case you can not overscroll. */);
4244 scroll_bar_adjust_thumb_portion_p = 1;
4245
4249 DEFVAR_LISP ("terminal-frame", Vterminal_frame, 4246 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
4250 doc: /* The initial frame-object, which represents Emacs's stdout. */); 4247 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4251 4248
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/>. */
18 18
19/* Don't multiply include: dispextern.h includes macterm.h which 19/* Don't multiply include: dispextern.h includes macterm.h which
20 includes frame.h some emacs source includes both dispextern.h and 20 includes frame.h some emacs source includes both dispextern.h and
21 frame.h */ 21 frame.h. */
22 22
23#ifndef EMACS_FRAME_H 23#ifndef EMACS_FRAME_H
24#define EMACS_FRAME_H 24#define EMACS_FRAME_H
@@ -33,7 +33,7 @@ INLINE_HEADER_BEGIN
33 33
34/* Miscellanea. */ 34/* Miscellanea. */
35 35
36/* Nonzero means there is at least one garbaged frame. */ 36/* Nonzero means there is at least one garbaged frame. */
37extern bool frame_garbaged; 37extern bool frame_garbaged;
38 38
39 39
@@ -200,7 +200,7 @@ struct frame
200 string's pointer (`name', above) because it might get relocated. */ 200 string's pointer (`name', above) because it might get relocated. */
201 char *namebuf; 201 char *namebuf;
202 202
203 /* Glyph pool and matrix. */ 203 /* Glyph pool and matrix. */
204 struct glyph_pool *current_pool; 204 struct glyph_pool *current_pool;
205 struct glyph_pool *desired_pool; 205 struct glyph_pool *desired_pool;
206 struct glyph_matrix *desired_matrix; 206 struct glyph_matrix *desired_matrix;
@@ -353,46 +353,30 @@ struct frame
353 unsigned int external_menu_bar : 1; 353 unsigned int external_menu_bar : 1;
354#endif 354#endif
355 355
356 /* visible is nonzero if the frame is currently displayed; we check 356 /* Next two bitfields are mutually exclusive. They might both be
357 zero if the frame has been made invisible without an icon. */
358
359 /* Nonzero if the frame is currently displayed; we check
357 it to see if we should bother updating the frame's contents. 360 it to see if we should bother updating the frame's contents.
358 DON'T SET IT DIRECTLY; instead, use FRAME_SET_VISIBLE.
359 361
360 Note that, since invisible frames aren't updated, whenever a 362 Note that, since invisible frames aren't updated, whenever a
361 frame becomes visible again, it must be marked as garbaged. The 363 frame becomes visible again, it must be marked as garbaged.
362 FRAME_SAMPLE_VISIBILITY macro takes care of this.
363 364
364 On ttys and on Windows NT/9X, to avoid wasting effort updating 365 On ttys and on Windows NT/9X, to avoid wasting effort updating
365 visible frames that are actually completely obscured by other 366 visible frames that are actually completely obscured by other
366 windows on the display, we bend the meaning of visible slightly: 367 windows on the display, we bend the meaning of visible slightly:
367 if greater than 1, then the frame is obscured - we still consider 368 if equal to 2, then the frame is obscured - we still consider
368 it to be "visible" as seen from lisp, but we don't bother 369 it to be "visible" as seen from lisp, but we don't bother
369 updating it. We must take care to garbage the frame when it 370 updating it. We must take care to garbage the frame when it
370 ceases to be obscured though. 371 ceases to be obscured though. See SET_FRAME_VISIBLE below. */
371
372 iconified is nonzero if the frame is currently iconified.
373
374 Asynchronous input handlers should NOT change these directly;
375 instead, they should change async_visible or async_iconified, and
376 let the FRAME_SAMPLE_VISIBILITY macro set visible and iconified
377 at the next redisplay.
378
379 These should probably be considered read-only by everyone except
380 FRAME_SAMPLE_VISIBILITY.
381
382 These two are mutually exclusive. They might both be zero, if the
383 frame has been made invisible without an icon. */
384 unsigned visible : 2; 372 unsigned visible : 2;
385 unsigned iconified : 1;
386 373
387 /* Let's not use bitfields for volatile variables. */ 374 /* Nonzero if the frame is currently iconified. Do not
388 375 set this directly, use SET_FRAME_ICONIFIED instead. */
389 /* Asynchronous input handlers change these, and 376 unsigned iconified : 1;
390 FRAME_SAMPLE_VISIBILITY copies them into visible and iconified.
391 See FRAME_SAMPLE_VISIBILITY, below. */
392 volatile char async_visible, async_iconified;
393 377
394 /* Nonzero if this frame should be redrawn. */ 378 /* Nonzero if this frame should be redrawn. */
395 volatile char garbaged; 379 unsigned garbaged : 1;
396 380
397 /* True if frame actually has a minibuffer window on it. 381 /* True if frame actually has a minibuffer window on it.
398 0 if using a minibuffer window that isn't on this frame. */ 382 0 if using a minibuffer window that isn't on this frame. */
@@ -444,9 +428,6 @@ struct frame
444 /* Width of bar cursor (if we are using that) for blink-off state. */ 428 /* Width of bar cursor (if we are using that) for blink-off state. */
445 int blink_off_cursor_width; 429 int blink_off_cursor_width;
446 430
447 /* Storage for messages to this frame. */
448 char *message_buf;
449
450 /* Nonnegative if current redisplay should not do scroll computation 431 /* Nonnegative if current redisplay should not do scroll computation
451 for lines beyond a certain vpos. This is the vpos. */ 432 for lines beyond a certain vpos. This is the vpos. */
452 int scroll_bottom_vpos; 433 int scroll_bottom_vpos;
@@ -714,7 +695,7 @@ typedef struct frame *FRAME_PTR;
714#else 695#else
715#define FRAME_EXTERNAL_MENU_BAR(f) 0 696#define FRAME_EXTERNAL_MENU_BAR(f) 0
716#endif 697#endif
717#define FRAME_VISIBLE_P(f) ((f)->visible != 0) 698#define FRAME_VISIBLE_P(f) (f)->visible
718 699
719/* Nonzero if frame F is currently visible but hidden. */ 700/* Nonzero if frame F is currently visible but hidden. */
720#define FRAME_OBSCURED_P(f) ((f)->visible > 1) 701#define FRAME_OBSCURED_P(f) ((f)->visible > 1)
@@ -722,9 +703,10 @@ typedef struct frame *FRAME_PTR;
722/* Nonzero if frame F is currently iconified. */ 703/* Nonzero if frame F is currently iconified. */
723#define FRAME_ICONIFIED_P(f) (f)->iconified 704#define FRAME_ICONIFIED_P(f) (f)->iconified
724 705
725#define FRAME_SET_VISIBLE(f,p) \ 706/* Mark frame F as currently garbaged. */
726 ((f)->async_visible = (p), FRAME_SAMPLE_VISIBILITY (f))
727#define SET_FRAME_GARBAGED(f) (frame_garbaged = 1, f->garbaged = 1) 707#define SET_FRAME_GARBAGED(f) (frame_garbaged = 1, f->garbaged = 1)
708
709/* Nonzero if frame F is currently garbaged. */
728#define FRAME_GARBAGED_P(f) (f)->garbaged 710#define FRAME_GARBAGED_P(f) (f)->garbaged
729 711
730/* Nonzero means do not allow splitting this frame's window. */ 712/* Nonzero means do not allow splitting this frame's window. */
@@ -751,7 +733,6 @@ typedef struct frame *FRAME_PTR;
751#define FRAME_DELETE_COST(f) (f)->delete_line_cost 733#define FRAME_DELETE_COST(f) (f)->delete_line_cost
752#define FRAME_INSERTN_COST(f) (f)->insert_n_lines_cost 734#define FRAME_INSERTN_COST(f) (f)->insert_n_lines_cost
753#define FRAME_DELETEN_COST(f) (f)->delete_n_lines_cost 735#define FRAME_DELETEN_COST(f) (f)->delete_n_lines_cost
754#define FRAME_MESSAGE_BUF(f) (f)->message_buf
755#define FRAME_SCROLL_BOTTOM_VPOS(f) (f)->scroll_bottom_vpos 736#define FRAME_SCROLL_BOTTOM_VPOS(f) (f)->scroll_bottom_vpos
756#define FRAME_FOCUS_FRAME(f) f->focus_frame 737#define FRAME_FOCUS_FRAME(f) f->focus_frame
757 738
@@ -870,39 +851,6 @@ typedef struct frame *FRAME_PTR;
870 851
871#define FRAME_MESSAGE_BUF_SIZE(f) (((int) FRAME_COLS (f)) * 4) 852#define FRAME_MESSAGE_BUF_SIZE(f) (((int) FRAME_COLS (f)) * 4)
872 853
873/* Emacs's redisplay code could become confused if a frame's
874 visibility changes at arbitrary times. For example, if a frame is
875 visible while the desired glyphs are being built, but becomes
876 invisible before they are updated, then some rows of the
877 desired_glyphs will be left marked as enabled after redisplay is
878 complete, which should never happen. The next time the frame
879 becomes visible, redisplay will probably barf.
880
881 Currently, there are no similar situations involving iconified, but
882 the principle is the same.
883
884 So instead of having asynchronous input handlers directly set and
885 clear the frame's visibility and iconification flags, they just set
886 the async_visible and async_iconified flags; the redisplay code
887 calls the FRAME_SAMPLE_VISIBILITY macro before doing any redisplay,
888 which sets visible and iconified from their asynchronous
889 counterparts.
890
891 Synchronous code must use the FRAME_SET_VISIBLE macro.
892
893 Also, if a frame used to be invisible, but has just become visible,
894 it must be marked as garbaged, since redisplay hasn't been keeping
895 up its contents.
896
897 Note that a tty frame is visible if and only if it is the topmost
898 frame. */
899
900#define FRAME_SAMPLE_VISIBILITY(f) \
901 (((f)->async_visible && (f)->visible != (f)->async_visible) ? \
902 SET_FRAME_GARBAGED (f) : 0, \
903 (f)->visible = (f)->async_visible, \
904 (f)->iconified = (f)->async_iconified)
905
906#define CHECK_FRAME(x) \ 854#define CHECK_FRAME(x) \
907 CHECK_TYPE (FRAMEP (x), Qframep, x) 855 CHECK_TYPE (FRAMEP (x), Qframep, x)
908 856
@@ -936,12 +884,24 @@ typedef struct frame *FRAME_PTR;
936 block_input (); \ 884 block_input (); \
937 if (hlinfo->mouse_face_mouse_frame) \ 885 if (hlinfo->mouse_face_mouse_frame) \
938 note_mouse_highlight (hlinfo->mouse_face_mouse_frame, \ 886 note_mouse_highlight (hlinfo->mouse_face_mouse_frame, \
939 hlinfo->mouse_face_mouse_x, \ 887 hlinfo->mouse_face_mouse_x, \
940 hlinfo->mouse_face_mouse_y); \ 888 hlinfo->mouse_face_mouse_y); \
941 unblock_input (); \ 889 unblock_input (); \
942 } \ 890 } \
943 } while (0) 891 } while (0)
944 892
893/* Set visibility of frame F, marking F as garbaged if needed. */
894
895#define SET_FRAME_VISIBLE(f, v) \
896 (((f)->visible == 0 || ((f)->visible == 2)) \
897 && ((v) == 1) ? SET_FRAME_GARBAGED (f) : 0, \
898 (f)->visible = (eassert (0 <= (v) && (v) <= 2), (v)))
899
900/* Set iconify of frame F. */
901
902#define SET_FRAME_ICONIFIED(f, i) \
903 (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i))
904
945extern Lisp_Object Qframep, Qframe_live_p; 905extern Lisp_Object Qframep, Qframe_live_p;
946extern Lisp_Object Qtty, Qtty_type; 906extern Lisp_Object Qtty, Qtty_type;
947extern Lisp_Object Qtty_color_mode; 907extern 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)
393 cache_data = xmalloc (sizeof *cache_data); 393 cache_data = xmalloc (sizeof *cache_data);
394 cache_data->ft_face = NULL; 394 cache_data->ft_face = NULL;
395 cache_data->fc_charset = NULL; 395 cache_data->fc_charset = NULL;
396 val = make_save_value (cache_data, 0); 396 val = make_save_value ("pi", cache_data, 0);
397 cache = Fcons (Qnil, val); 397 cache = Fcons (Qnil, val);
398 Fputhash (key, cache, ft_face_cache); 398 Fputhash (key, cache, ft_face_cache);
399 } 399 }
@@ -2541,7 +2541,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2541 2541
2542 if (NILP (lglyph)) 2542 if (NILP (lglyph))
2543 { 2543 {
2544 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); 2544 lglyph = LGLYPH_NEW ();
2545 LGSTRING_SET_GLYPH (lgstring, i, lglyph); 2545 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2546 } 2546 }
2547 LGLYPH_SET_FROM (lglyph, g->from); 2547 LGLYPH_SET_FROM (lglyph, g->from);
@@ -2555,9 +2555,8 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2555 LGLYPH_SET_DESCENT (lglyph, g->descent >> 6); 2555 LGLYPH_SET_DESCENT (lglyph, g->descent >> 6);
2556 if (g->adjusted) 2556 if (g->adjusted)
2557 { 2557 {
2558 Lisp_Object vec; 2558 Lisp_Object vec = make_uninit_vector (3);
2559 2559
2560 vec = Fmake_vector (make_number (3), Qnil);
2561 ASET (vec, 0, make_number (g->xoff >> 6)); 2560 ASET (vec, 0, make_number (g->xoff >> 6));
2562 ASET (vec, 1, make_number (g->yoff >> 6)); 2561 ASET (vec, 1, make_number (g->yoff >> 6));
2563 ASET (vec, 2, make_number (g->xadv >> 6)); 2562 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)
983 size as fast as possible. 983 size as fast as possible.
984 For unmapped windows, we can set rows/cols. When 984 For unmapped windows, we can set rows/cols. When
985 the frame is mapped again we will (hopefully) get the correct size. */ 985 the frame is mapped again we will (hopefully) get the correct size. */
986 if (f->async_visible) 986 if (FRAME_VISIBLE_P (f))
987 { 987 {
988 /* Must call this to flush out events */ 988 /* Must call this to flush out events */
989 (void)gtk_events_pending (); 989 (void)gtk_events_pending ();
@@ -1716,7 +1716,7 @@ xg_dialog_run (FRAME_PTR f, GtkWidget *w)
1716 g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL); 1716 g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL);
1717 gtk_widget_show (w); 1717 gtk_widget_show (w);
1718 1718
1719 record_unwind_protect (pop_down_dialog, make_save_value (&dd, 0)); 1719 record_unwind_protect (pop_down_dialog, make_save_pointer (&dd));
1720 1720
1721 (void) xg_maybe_add_timer (&dd); 1721 (void) xg_maybe_add_timer (&dd);
1722 g_main_loop_run (dd.loop); 1722 g_main_loop_run (dd.loop);
@@ -4353,6 +4353,21 @@ xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
4353 x->toolbar_is_packed = true; 4353 x->toolbar_is_packed = true;
4354} 4354}
4355 4355
4356static bool xg_update_tool_bar_sizes (FRAME_PTR f);
4357
4358static void
4359tb_size_cb (GtkWidget *widget,
4360 GdkRectangle *allocation,
4361 gpointer user_data)
4362{
4363 /* When tool bar is created it has one preferred size. But when size is
4364 allocated between widgets, it may get another. So we must update
4365 size hints if tool bar size changes. Seen on Fedora 18 at least. */
4366 FRAME_PTR f = (FRAME_PTR) user_data;
4367 if (xg_update_tool_bar_sizes (f))
4368 x_wm_set_size_hint (f, 0, 0);
4369}
4370
4356/* Create a tool bar for frame F. */ 4371/* Create a tool bar for frame F. */
4357 4372
4358static void 4373static void
@@ -4384,6 +4399,8 @@ xg_create_tool_bar (FRAME_PTR f)
4384 4399
4385 gtk_toolbar_set_style (GTK_TOOLBAR (x->toolbar_widget), GTK_TOOLBAR_ICONS); 4400 gtk_toolbar_set_style (GTK_TOOLBAR (x->toolbar_widget), GTK_TOOLBAR_ICONS);
4386 toolbar_set_orientation (x->toolbar_widget, GTK_ORIENTATION_HORIZONTAL); 4401 toolbar_set_orientation (x->toolbar_widget, GTK_ORIENTATION_HORIZONTAL);
4402 g_signal_connect (x->toolbar_widget, "size-allocate",
4403 G_CALLBACK (tb_size_cb), f);
4387#if GTK_CHECK_VERSION (3, 3, 6) 4404#if GTK_CHECK_VERSION (3, 3, 6)
4388 gsty = gtk_widget_get_style_context (x->toolbar_widget); 4405 gsty = gtk_widget_get_style_context (x->toolbar_widget);
4389 gtk_style_context_add_class (gsty, "primary-toolbar"); 4406 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,
7792 } 7792 }
7793 } 7793 }
7794 7794
7795 /* Finally we are done manipulating the image. Figure out the
7796 resulting width/height and transfer ownership to Emacs. */
7797 height = MagickGetImageHeight (image_wand);
7798 width = MagickGetImageWidth (image_wand);
7799
7800 /* Set the canvas background color to the frame or specified 7795 /* Set the canvas background color to the frame or specified
7801 background, and flatten the image. Note: as of ImageMagick 7796 background, and flatten the image. Note: as of ImageMagick
7802 6.6.0, SVG image transparency is not handled properly 7797 6.6.0, SVG image transparency is not handled properly
@@ -7813,6 +7808,11 @@ imagemagick_load_image (struct frame *f, struct image *img,
7813 image_wand = new_wand; 7808 image_wand = new_wand;
7814 } 7809 }
7815 7810
7811 /* Finally we are done manipulating the image. Figure out the
7812 resulting width/height and transfer ownership to Emacs. */
7813 height = MagickGetImageHeight (image_wand);
7814 width = MagickGetImageWidth (image_wand);
7815
7816 if (! (width <= INT_MAX && height <= INT_MAX 7816 if (! (width <= INT_MAX && height <= INT_MAX
7817 && check_image_size (f, width, height))) 7817 && check_image_size (f, width, height)))
7818 { 7818 {
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)
138 struct Lisp_Vector *widthtab; 138 struct Lisp_Vector *widthtab;
139 139
140 if (!VECTORP (BVAR (buf, width_table))) 140 if (!VECTORP (BVAR (buf, width_table)))
141 bset_width_table (buf, Fmake_vector (make_number (256), make_number (0))); 141 bset_width_table (buf, make_uninit_vector (256));
142 widthtab = XVECTOR (BVAR (buf, width_table)); 142 widthtab = XVECTOR (BVAR (buf, width_table));
143 eassert (widthtab->header.size == 256); 143 eassert (widthtab->header.size == 256);
144 144
@@ -291,7 +291,7 @@ DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
291 doc: /* Return the horizontal position of point. Beginning of line is column 0. 291 doc: /* Return the horizontal position of point. Beginning of line is column 0.
292This is calculated by adding together the widths of all the displayed 292This is calculated by adding together the widths of all the displayed
293representations of the character between the start of the previous line 293representations of the character between the start of the previous line
294and point (eg. control characters will have a width of 2 or 4, tabs 294and point (e.g., control characters will have a width of 2 or 4, tabs
295will have a variable width). 295will have a variable width).
296Ignores finite width of frame, which means that this function may return 296Ignores finite width of frame, which means that this function may return
297values greater than (frame-width). 297values greater than (frame-width).
@@ -1102,8 +1102,8 @@ static struct position val_compute_motion;
1102 the scroll bars if they are turned on. */ 1102 the scroll bars if they are turned on. */
1103 1103
1104struct position * 1104struct position *
1105compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, 1105compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
1106 bool did_motion, ptrdiff_t to, 1106 EMACS_INT fromhpos, bool did_motion, ptrdiff_t to,
1107 EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width, 1107 EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width,
1108 ptrdiff_t hscroll, int tab_offset, struct window *win) 1108 ptrdiff_t hscroll, int tab_offset, struct window *win)
1109{ 1109{
@@ -1186,8 +1186,11 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
1186 immediate_quit = 1; 1186 immediate_quit = 1;
1187 QUIT; 1187 QUIT;
1188 1188
1189 /* It's just impossible to be too paranoid here. */
1190 eassert (from == BYTE_TO_CHAR (frombyte) && frombyte == CHAR_TO_BYTE (from));
1191
1189 pos = prev_pos = from; 1192 pos = prev_pos = from;
1190 pos_byte = prev_pos_byte = CHAR_TO_BYTE (from); 1193 pos_byte = prev_pos_byte = frombyte;
1191 contin_hpos = 0; 1194 contin_hpos = 0;
1192 prev_tab_offset = tab_offset; 1195 prev_tab_offset = tab_offset;
1193 memset (&cmp_it, 0, sizeof cmp_it); 1196 memset (&cmp_it, 0, sizeof cmp_it);
@@ -1328,8 +1331,7 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
1328 TO (we need to go back below). */ 1331 TO (we need to go back below). */
1329 if (pos <= to) 1332 if (pos <= to)
1330 { 1333 {
1331 pos = find_before_next_newline (pos, to, 1); 1334 pos = find_before_next_newline (pos, to, 1, &pos_byte);
1332 pos_byte = CHAR_TO_BYTE (pos);
1333 hpos = width; 1335 hpos = width;
1334 /* If we just skipped next_boundary, 1336 /* If we just skipped next_boundary,
1335 loop around in the main while 1337 loop around in the main while
@@ -1583,10 +1585,9 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
1583 /* Skip any number of invisible lines all at once */ 1585 /* Skip any number of invisible lines all at once */
1584 do 1586 do
1585 { 1587 {
1586 pos = find_before_next_newline (pos, to, 1); 1588 pos = find_before_next_newline (pos, to, 1, &pos_byte);
1587 if (pos < to) 1589 if (pos < to)
1588 pos++; 1590 INC_BOTH (pos, pos_byte);
1589 pos_byte = CHAR_TO_BYTE (pos);
1590 } 1591 }
1591 while (pos < to 1592 while (pos < to
1592 && indented_beyond_p (pos, pos_byte, 1593 && indented_beyond_p (pos, pos_byte,
@@ -1622,10 +1623,7 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
1622 everything from a ^M to the end of the line is invisible. 1623 everything from a ^M to the end of the line is invisible.
1623 Stop *before* the real newline. */ 1624 Stop *before* the real newline. */
1624 if (pos < to) 1625 if (pos < to)
1625 { 1626 pos = find_before_next_newline (pos, to, 1, &pos_byte);
1626 pos = find_before_next_newline (pos, to, 1);
1627 pos_byte = CHAR_TO_BYTE (pos);
1628 }
1629 /* If we just skipped next_boundary, 1627 /* If we just skipped next_boundary,
1630 loop around in the main while 1628 loop around in the main while
1631 and handle it. */ 1629 and handle it. */
@@ -1729,7 +1727,8 @@ of a certain window, pass the window's starting location as FROM
1729and the window's upper-left coordinates as FROMPOS. 1727and the window's upper-left coordinates as FROMPOS.
1730Pass the buffer's (point-max) as TO, to limit the scan to the end of the 1728Pass the buffer's (point-max) as TO, to limit the scan to the end of the
1731visible section of the buffer, and pass LINE and COL as TOPOS. */) 1729visible section of the buffer, and pass LINE and COL as TOPOS. */)
1732 (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, Lisp_Object width, Lisp_Object offsets, Lisp_Object window) 1730 (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos,
1731 Lisp_Object width, Lisp_Object offsets, Lisp_Object window)
1733{ 1732{
1734 struct window *w; 1733 struct window *w;
1735 Lisp_Object bufpos, hpos, vpos, prevhpos; 1734 Lisp_Object bufpos, hpos, vpos, prevhpos;
@@ -1772,7 +1771,8 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */)
1772 if (XINT (to) < BEGV || XINT (to) > ZV) 1771 if (XINT (to) < BEGV || XINT (to) > ZV)
1773 args_out_of_range_3 (to, make_number (BEGV), make_number (ZV)); 1772 args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
1774 1773
1775 pos = compute_motion (XINT (from), XINT (XCDR (frompos)), 1774 pos = compute_motion (XINT (from), CHAR_TO_BYTE (XINT (from)),
1775 XINT (XCDR (frompos)),
1776 XINT (XCAR (frompos)), 0, 1776 XINT (XCAR (frompos)), 0,
1777 XINT (to), 1777 XINT (to),
1778 (NILP (topos) 1778 (NILP (topos)
@@ -1794,28 +1794,23 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */)
1794 XSETINT (vpos, pos->vpos); 1794 XSETINT (vpos, pos->vpos);
1795 XSETINT (prevhpos, pos->prevhpos); 1795 XSETINT (prevhpos, pos->prevhpos);
1796 1796
1797 return Fcons (bufpos, 1797 return list5 (bufpos, hpos, vpos, prevhpos, pos->contin ? Qt : Qnil);
1798 Fcons (hpos,
1799 Fcons (vpos,
1800 Fcons (prevhpos,
1801 Fcons (pos->contin ? Qt : Qnil, Qnil)))));
1802
1803} 1798}
1804 1799
1805/* Fvertical_motion and vmotion */ 1800/* Fvertical_motion and vmotion. */
1806 1801
1807static struct position val_vmotion; 1802static struct position val_vmotion;
1808 1803
1809struct position * 1804struct position *
1810vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) 1805vmotion (register ptrdiff_t from, register ptrdiff_t from_byte,
1806 register EMACS_INT vtarget, struct window *w)
1811{ 1807{
1812 ptrdiff_t hscroll = w->hscroll; 1808 ptrdiff_t hscroll = w->hscroll;
1813 struct position pos; 1809 struct position pos;
1814 /* vpos is cumulative vertical position, changed as from is changed */ 1810 /* VPOS is cumulative vertical position, changed as from is changed. */
1815 register EMACS_INT vpos = 0; 1811 register EMACS_INT vpos = 0;
1816 ptrdiff_t prevline; 1812 ptrdiff_t prevline;
1817 register ptrdiff_t first; 1813 register ptrdiff_t first;
1818 ptrdiff_t from_byte;
1819 ptrdiff_t lmargin = hscroll > 0 ? 1 - hscroll : 0; 1814 ptrdiff_t lmargin = hscroll > 0 ? 1 - hscroll : 0;
1820 ptrdiff_t selective 1815 ptrdiff_t selective
1821 = (INTEGERP (BVAR (current_buffer, selective_display)) 1816 = (INTEGERP (BVAR (current_buffer, selective_display))
@@ -1845,44 +1840,44 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
1845 1840
1846 while ((vpos > vtarget || first) && from > BEGV) 1841 while ((vpos > vtarget || first) && from > BEGV)
1847 { 1842 {
1843 ptrdiff_t bytepos = from_byte;
1848 Lisp_Object propval; 1844 Lisp_Object propval;
1849 1845
1850 prevline = find_next_newline_no_quit (from - 1, -1); 1846 prevline = from;
1847 DEC_BOTH (prevline, bytepos);
1848 prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
1849
1851 while (prevline > BEGV 1850 while (prevline > BEGV
1852 && ((selective > 0 1851 && ((selective > 0
1853 && indented_beyond_p (prevline, 1852 && indented_beyond_p (prevline, bytepos, selective))
1854 CHAR_TO_BYTE (prevline),
1855 selective))
1856 /* Watch out for newlines with `invisible' property. 1853 /* Watch out for newlines with `invisible' property.
1857 When moving upward, check the newline before. */ 1854 When moving upward, check the newline before. */
1858 || (propval = Fget_char_property (make_number (prevline - 1), 1855 || (propval = Fget_char_property (make_number (prevline - 1),
1859 Qinvisible, 1856 Qinvisible,
1860 text_prop_object), 1857 text_prop_object),
1861 TEXT_PROP_MEANS_INVISIBLE (propval)))) 1858 TEXT_PROP_MEANS_INVISIBLE (propval))))
1862 prevline = find_next_newline_no_quit (prevline - 1, -1); 1859 {
1863 pos = *compute_motion (prevline, 0, 1860 DEC_BOTH (prevline, bytepos);
1864 lmargin, 1861 prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
1865 0, 1862 }
1866 from, 1863 pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from,
1867 /* Don't care for VPOS... */ 1864 /* Don't care for VPOS... */
1868 1 << (BITS_PER_SHORT - 1), 1865 1 << (BITS_PER_SHORT - 1),
1869 /* ... nor HPOS. */ 1866 /* ... nor HPOS. */
1870 1 << (BITS_PER_SHORT - 1), 1867 1 << (BITS_PER_SHORT - 1),
1871 -1, hscroll, 1868 -1, hscroll, 0, w);
1872 0,
1873 w);
1874 vpos -= pos.vpos; 1869 vpos -= pos.vpos;
1875 first = 0; 1870 first = 0;
1876 from = prevline; 1871 from = prevline;
1872 from_byte = bytepos;
1877 } 1873 }
1878 1874
1879 /* If we made exactly the desired vertical distance, 1875 /* If we made exactly the desired vertical distance, or
1880 or if we hit beginning of buffer, 1876 if we hit beginning of buffer, return point found. */
1881 return point found */
1882 if (vpos >= vtarget) 1877 if (vpos >= vtarget)
1883 { 1878 {
1884 val_vmotion.bufpos = from; 1879 val_vmotion.bufpos = from;
1885 val_vmotion.bytepos = CHAR_TO_BYTE (from); 1880 val_vmotion.bytepos = from_byte;
1886 val_vmotion.vpos = vpos; 1881 val_vmotion.vpos = vpos;
1887 val_vmotion.hpos = lmargin; 1882 val_vmotion.hpos = lmargin;
1888 val_vmotion.contin = 0; 1883 val_vmotion.contin = 0;
@@ -1890,39 +1885,37 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
1890 return &val_vmotion; 1885 return &val_vmotion;
1891 } 1886 }
1892 1887
1893 /* Otherwise find the correct spot by moving down */ 1888 /* Otherwise find the correct spot by moving down. */
1894 } 1889 }
1895 /* Moving downward is simple, but must calculate from beg of line 1890
1896 to determine hpos of starting point */ 1891 /* Moving downward is simple, but must calculate from
1897 from_byte = CHAR_TO_BYTE (from); 1892 beg of line to determine hpos of starting point. */
1893
1898 if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n') 1894 if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
1899 { 1895 {
1896 ptrdiff_t bytepos;
1900 Lisp_Object propval; 1897 Lisp_Object propval;
1901 1898
1902 prevline = find_next_newline_no_quit (from, -1); 1899 prevline = find_newline_no_quit (from, from_byte, -1, &bytepos);
1903 while (prevline > BEGV 1900 while (prevline > BEGV
1904 && ((selective > 0 1901 && ((selective > 0
1905 && indented_beyond_p (prevline, 1902 && indented_beyond_p (prevline, bytepos, selective))
1906 CHAR_TO_BYTE (prevline),
1907 selective))
1908 /* Watch out for newlines with `invisible' property. 1903 /* Watch out for newlines with `invisible' property.
1909 When moving downward, check the newline after. */ 1904 When moving downward, check the newline after. */
1910 || (propval = Fget_char_property (make_number (prevline), 1905 || (propval = Fget_char_property (make_number (prevline),
1911 Qinvisible, 1906 Qinvisible,
1912 text_prop_object), 1907 text_prop_object),
1913 TEXT_PROP_MEANS_INVISIBLE (propval)))) 1908 TEXT_PROP_MEANS_INVISIBLE (propval))))
1914 prevline = find_next_newline_no_quit (prevline - 1, -1); 1909 {
1915 pos = *compute_motion (prevline, 0, 1910 DEC_BOTH (prevline, bytepos);
1916 lmargin, 1911 prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
1917 0, 1912 }
1918 from, 1913 pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from,
1919 /* Don't care for VPOS... */ 1914 /* Don't care for VPOS... */
1920 1 << (BITS_PER_SHORT - 1), 1915 1 << (BITS_PER_SHORT - 1),
1921 /* ... nor HPOS. */ 1916 /* ... nor HPOS. */
1922 1 << (BITS_PER_SHORT - 1), 1917 1 << (BITS_PER_SHORT - 1),
1923 -1, hscroll, 1918 -1, hscroll, 0, w);
1924 0,
1925 w);
1926 did_motion = 1; 1919 did_motion = 1;
1927 } 1920 }
1928 else 1921 else
@@ -1931,11 +1924,9 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
1931 pos.vpos = 0; 1924 pos.vpos = 0;
1932 did_motion = 0; 1925 did_motion = 0;
1933 } 1926 }
1934 return compute_motion (from, vpos, pos.hpos, did_motion, 1927 return compute_motion (from, from_byte, vpos, pos.hpos, did_motion,
1935 ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)), 1928 ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
1936 -1, hscroll, 1929 -1, hscroll, 0, w);
1937 0,
1938 w);
1939} 1930}
1940 1931
1941DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0, 1932DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
@@ -2002,7 +1993,7 @@ whether or not it is currently displayed in some window. */)
2002 if (noninteractive) 1993 if (noninteractive)
2003 { 1994 {
2004 struct position pos; 1995 struct position pos;
2005 pos = *vmotion (PT, XINT (lines), w); 1996 pos = *vmotion (PT, PT_BYTE, XINT (lines), w);
2006 SET_PT_BOTH (pos.bufpos, pos.bytepos); 1997 SET_PT_BOTH (pos.bufpos, pos.bytepos);
2007 } 1998 }
2008 else 1999 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
26 int contin; 26 int contin;
27 }; 27 };
28 28
29struct position *compute_motion (ptrdiff_t from, EMACS_INT fromvpos, 29struct position *compute_motion (ptrdiff_t from, ptrdiff_t frombyte,
30 EMACS_INT fromhpos, bool did_motion, 30 EMACS_INT fromvpos, EMACS_INT fromhpos,
31 ptrdiff_t to, EMACS_INT tovpos, 31 bool did_motion, ptrdiff_t to,
32 EMACS_INT tohpos, 32 EMACS_INT tovpos, EMACS_INT tohpos,
33 EMACS_INT width, ptrdiff_t hscroll, 33 EMACS_INT width, ptrdiff_t hscroll,
34 int tab_offset, struct window *); 34 int tab_offset, struct window *);
35struct position *vmotion (ptrdiff_t from, EMACS_INT vtarget, 35struct position *vmotion (ptrdiff_t from, ptrdiff_t from_byte,
36 struct window *); 36 EMACS_INT vtarget, struct window *);
37ptrdiff_t skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p, 37ptrdiff_t skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p,
38 ptrdiff_t to, Lisp_Object window); 38 ptrdiff_t to, Lisp_Object window);
39 39
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,
658 } 658 }
659} 659}
660 660
661/* Subroutine used by the insert functions above. */
662
663void
664insert_1 (const char *string, ptrdiff_t nbytes,
665 bool inherit, bool prepare, bool before_markers)
666{
667 insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes),
668 nbytes, inherit, prepare, before_markers);
669}
670
671
672#ifdef BYTE_COMBINING_DEBUG 661#ifdef BYTE_COMBINING_DEBUG
673 662
674/* See if the bytes before POS/POS_BYTE combine with bytes 663/* 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)
2024 && current_buffer != XBUFFER (combine_after_change_buffer)) 2013 && current_buffer != XBUFFER (combine_after_change_buffer))
2025 Fcombine_after_change_execute (); 2014 Fcombine_after_change_execute ();
2026 2015
2027 elt = Fcons (make_number (charpos - BEG), 2016 elt = list3i (charpos - BEG, Z - (charpos - lendel + lenins),
2028 Fcons (make_number (Z - (charpos - lendel + lenins)), 2017 lenins - lendel);
2029 Fcons (make_number (lenins - lendel), Qnil)));
2030 combine_after_change_list 2018 combine_after_change_list
2031 = Fcons (elt, combine_after_change_list); 2019 = Fcons (elt, combine_after_change_list);
2032 combine_after_change_buffer = Fcurrent_buffer (); 2020 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);
259extern INTERVAL update_interval (INTERVAL, ptrdiff_t); 259extern INTERVAL update_interval (INTERVAL, ptrdiff_t);
260extern void set_intervals_multibyte (bool); 260extern void set_intervals_multibyte (bool);
261extern INTERVAL validate_interval_range (Lisp_Object, Lisp_Object *, 261extern INTERVAL validate_interval_range (Lisp_Object, Lisp_Object *,
262 Lisp_Object *, int); 262 Lisp_Object *, bool);
263extern INTERVAL interval_of (ptrdiff_t, Lisp_Object); 263extern INTERVAL interval_of (ptrdiff_t, Lisp_Object);
264 264
265/* Defined in xdisp.c. */ 265/* Defined in xdisp.c. */
@@ -293,7 +293,7 @@ extern void set_text_properties_1 (Lisp_Object, Lisp_Object,
293 293
294Lisp_Object text_property_list (Lisp_Object, Lisp_Object, Lisp_Object, 294Lisp_Object text_property_list (Lisp_Object, Lisp_Object, Lisp_Object,
295 Lisp_Object); 295 Lisp_Object);
296int add_text_properties_from_list (Lisp_Object, Lisp_Object, Lisp_Object); 296void add_text_properties_from_list (Lisp_Object, Lisp_Object, Lisp_Object);
297Lisp_Object extend_property_ranges (Lisp_Object, Lisp_Object); 297Lisp_Object extend_property_ranges (Lisp_Object, Lisp_Object);
298Lisp_Object get_char_property_and_overlay (Lisp_Object, Lisp_Object, 298Lisp_Object get_char_property_and_overlay (Lisp_Object, Lisp_Object,
299 Lisp_Object, Lisp_Object*); 299 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;
367 367
368static Lisp_Object recursive_edit_unwind (Lisp_Object buffer); 368static Lisp_Object recursive_edit_unwind (Lisp_Object buffer);
369static Lisp_Object command_loop (void); 369static Lisp_Object command_loop (void);
370static Lisp_Object Qextended_command_history; 370static Lisp_Object Qcommand_execute;
371EMACS_TIME timer_check (void); 371EMACS_TIME timer_check (void);
372 372
373static void echo_now (void); 373static void echo_now (void);
@@ -417,10 +417,9 @@ static void (*keyboard_init_hook) (void);
417 417
418static bool get_input_pending (int); 418static bool get_input_pending (int);
419static bool readable_events (int); 419static bool readable_events (int);
420static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *, 420static Lisp_Object read_char_x_menu_prompt (Lisp_Object,
421 Lisp_Object, bool *); 421 Lisp_Object, bool *);
422static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t, 422static Lisp_Object read_char_minibuf_menu_prompt (int, Lisp_Object);
423 Lisp_Object *);
424static Lisp_Object make_lispy_event (struct input_event *); 423static Lisp_Object make_lispy_event (struct input_event *);
425static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object, 424static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object,
426 enum scroll_bar_part, 425 enum scroll_bar_part,
@@ -675,9 +674,8 @@ echo_now (void)
675 } 674 }
676 675
677 echoing = 1; 676 echoing = 1;
678 message3_nolog (KVAR (current_kboard, echo_string), 677 /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak). */
679 SBYTES (KVAR (current_kboard, echo_string)), 678 message3_nolog (KVAR (current_kboard, echo_string));
680 STRING_MULTIBYTE (KVAR (current_kboard, echo_string)));
681 echoing = 0; 679 echoing = 0;
682 680
683 /* Record in what buffer we echoed, and from which kboard. */ 681 /* Record in what buffer we echoed, and from which kboard. */
@@ -1187,13 +1185,13 @@ top_level_2 (void)
1187static Lisp_Object 1185static Lisp_Object
1188top_level_1 (Lisp_Object ignore) 1186top_level_1 (Lisp_Object ignore)
1189{ 1187{
1190 /* On entry to the outer level, run the startup file */ 1188 /* On entry to the outer level, run the startup file. */
1191 if (!NILP (Vtop_level)) 1189 if (!NILP (Vtop_level))
1192 internal_condition_case (top_level_2, Qerror, cmd_error); 1190 internal_condition_case (top_level_2, Qerror, cmd_error);
1193 else if (!NILP (Vpurify_flag)) 1191 else if (!NILP (Vpurify_flag))
1194 message ("Bare impure Emacs (standard Lisp code not loaded)"); 1192 message1 ("Bare impure Emacs (standard Lisp code not loaded)");
1195 else 1193 else
1196 message ("Bare Emacs (standard Lisp code not loaded)"); 1194 message1 ("Bare Emacs (standard Lisp code not loaded)");
1197 return Qnil; 1195 return Qnil;
1198} 1196}
1199 1197
@@ -1429,7 +1427,7 @@ command_loop_1 (void)
1429 sit_for (Vminibuffer_message_timeout, 0, 2); 1427 sit_for (Vminibuffer_message_timeout, 0, 2);
1430 1428
1431 /* Clear the echo area. */ 1429 /* Clear the echo area. */
1432 message2 (0, 0, 0); 1430 message1 (0);
1433 safe_run_hooks (Qecho_area_clear_hook); 1431 safe_run_hooks (Qecho_area_clear_hook);
1434 1432
1435 unbind_to (count, Qnil); 1433 unbind_to (count, Qnil);
@@ -1585,11 +1583,11 @@ command_loop_1 (void)
1585 = (EQ (undo, BVAR (current_buffer, undo_list)) 1583 = (EQ (undo, BVAR (current_buffer, undo_list))
1586 ? Qnil : BVAR (current_buffer, undo_list)); 1584 ? Qnil : BVAR (current_buffer, undo_list));
1587 } 1585 }
1588 Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil); 1586 call1 (Qcommand_execute, Vthis_command);
1589 1587
1590#ifdef HAVE_WINDOW_SYSTEM 1588#ifdef HAVE_WINDOW_SYSTEM
1591 /* Do not check display_hourglass_p here, because 1589 /* Do not check display_hourglass_p here, because
1592 Fcommand_execute could change it, but we should cancel 1590 `command-execute' could change it, but we should cancel
1593 hourglass cursor anyway. 1591 hourglass cursor anyway.
1594 But don't cancel the hourglass within a macro 1592 But don't cancel the hourglass within a macro
1595 just because a command in the macro finishes. */ 1593 just because a command in the macro finishes. */
@@ -2232,13 +2230,12 @@ do { if (! polling_stopped_here) stop_polling (); \
2232do { if (polling_stopped_here) start_polling (); \ 2230do { if (polling_stopped_here) start_polling (); \
2233 polling_stopped_here = 0; } while (0) 2231 polling_stopped_here = 0; } while (0)
2234 2232
2235/* read a character from the keyboard; call the redisplay if needed */ 2233/* Read a character from the keyboard; call the redisplay if needed. */
2236/* commandflag 0 means do not autosave, but do redisplay. 2234/* commandflag 0 means do not autosave, but do redisplay.
2237 -1 means do not redisplay, but do autosave. 2235 -1 means do not redisplay, but do autosave.
2238 1 means do both. */ 2236 1 means do both. */
2239 2237
2240/* The arguments MAPS and NMAPS are for menu prompting. 2238/* The arguments MAP is for menu prompting. MAP is a keymap.
2241 MAPS is an array of keymaps; NMAPS is the length of MAPS.
2242 2239
2243 PREV_EVENT is the previous input event, or nil if we are reading 2240 PREV_EVENT is the previous input event, or nil if we are reading
2244 the first event of a key sequence (or not reading a key sequence). 2241 the first event of a key sequence (or not reading a key sequence).
@@ -2260,7 +2257,7 @@ do { if (polling_stopped_here) start_polling (); \
2260 Value is t if we showed a menu and the user rejected it. */ 2257 Value is t if we showed a menu and the user rejected it. */
2261 2258
2262Lisp_Object 2259Lisp_Object
2263read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, 2260read_char (int commandflag, Lisp_Object map,
2264 Lisp_Object prev_event, 2261 Lisp_Object prev_event,
2265 bool *used_mouse_menu, EMACS_TIME *end_time) 2262 bool *used_mouse_menu, EMACS_TIME *end_time)
2266{ 2263{
@@ -2408,7 +2405,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
2408 goto reread_first; 2405 goto reread_first;
2409 } 2406 }
2410 2407
2411 /* if redisplay was requested */ 2408 /* If redisplay was requested. */
2412 if (commandflag >= 0) 2409 if (commandflag >= 0)
2413 { 2410 {
2414 bool echo_current = EQ (echo_message_buffer, echo_area_buffer[0]); 2411 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,
2417 user-visible, such as X selection_request events. */ 2414 user-visible, such as X selection_request events. */
2418 if (input_pending 2415 if (input_pending
2419 || detect_input_pending_run_timers (0)) 2416 || detect_input_pending_run_timers (0))
2420 swallow_events (0); /* may clear input_pending */ 2417 swallow_events (0); /* May clear input_pending. */
2421 2418
2422 /* Redisplay if no pending input. */ 2419 /* Redisplay if no pending input. */
2423 while (!input_pending) 2420 while (!input_pending)
@@ -2487,13 +2484,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
2487 menu prompting. If EVENT_HAS_PARAMETERS then we are reading 2484 menu prompting. If EVENT_HAS_PARAMETERS then we are reading
2488 after a mouse event so don't try a minibuf menu. */ 2485 after a mouse event so don't try a minibuf menu. */
2489 c = Qnil; 2486 c = Qnil;
2490 if (nmaps > 0 && INTERACTIVE 2487 if (KEYMAPP (map) && INTERACTIVE
2491 && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event) 2488 && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
2492 /* Don't bring up a menu if we already have another event. */ 2489 /* Don't bring up a menu if we already have another event. */
2493 && NILP (Vunread_command_events) 2490 && NILP (Vunread_command_events)
2494 && !detect_input_pending_run_timers (0)) 2491 && !detect_input_pending_run_timers (0))
2495 { 2492 {
2496 c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps); 2493 c = read_char_minibuf_menu_prompt (commandflag, map);
2497 2494
2498 if (INTEGERP (c) && XINT (c) == -2) 2495 if (INTEGERP (c) && XINT (c) == -2)
2499 return c; /* wrong_kboard_jmpbuf */ 2496 return c; /* wrong_kboard_jmpbuf */
@@ -2617,7 +2614,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
2617 because the recursive call of read_char in read_char_minibuf_menu_prompt 2614 because the recursive call of read_char in read_char_minibuf_menu_prompt
2618 does not pass on any keymaps. */ 2615 does not pass on any keymaps. */
2619 2616
2620 if (nmaps > 0 && INTERACTIVE 2617 if (KEYMAPP (map) && INTERACTIVE
2621 && !NILP (prev_event) 2618 && !NILP (prev_event)
2622 && EVENT_HAS_PARAMETERS (prev_event) 2619 && EVENT_HAS_PARAMETERS (prev_event)
2623 && !EQ (XCAR (prev_event), Qmenu_bar) 2620 && !EQ (XCAR (prev_event), Qmenu_bar)
@@ -2625,7 +2622,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
2625 /* Don't bring up a menu if we already have another event. */ 2622 /* Don't bring up a menu if we already have another event. */
2626 && NILP (Vunread_command_events)) 2623 && NILP (Vunread_command_events))
2627 { 2624 {
2628 c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu); 2625 c = read_char_x_menu_prompt (map, prev_event, used_mouse_menu);
2629 2626
2630 /* Now that we have read an event, Emacs is not idle. */ 2627 /* Now that we have read an event, Emacs is not idle. */
2631 if (!end_time) 2628 if (!end_time)
@@ -2660,9 +2657,10 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
2660 && XINT (Vauto_save_timeout) > 0) 2657 && XINT (Vauto_save_timeout) > 0)
2661 { 2658 {
2662 Lisp_Object tem0; 2659 Lisp_Object tem0;
2663 EMACS_INT timeout = (delay_level 2660 EMACS_INT timeout = XFASTINT (Vauto_save_timeout);
2664 * min (XFASTINT (Vauto_save_timeout) / 4, 2661
2665 MOST_POSITIVE_FIXNUM / delay_level)); 2662 timeout = min (timeout, MOST_POSITIVE_FIXNUM / delay_level * 4);
2663 timeout = delay_level * timeout / 4;
2666 save_getcjmp (save_jump); 2664 save_getcjmp (save_jump);
2667 restore_getcjmp (local_getcjmp); 2665 restore_getcjmp (local_getcjmp);
2668 tem0 = sit_for (make_number (timeout), 1, 1); 2666 tem0 = sit_for (make_number (timeout), 1, 1);
@@ -2844,7 +2842,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
2844 { 2842 {
2845 struct buffer *prev_buffer = current_buffer; 2843 struct buffer *prev_buffer = current_buffer;
2846 last_input_event = c; 2844 last_input_event = c;
2847 Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt); 2845 call4 (Qcommand_execute, tem, Qnil, Fvector (1, &last_input_event), Qt);
2848 2846
2849 if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time) 2847 if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
2850 /* We stopped being idle for this event; undo that. This 2848 /* We stopped being idle for this event; undo that. This
@@ -3003,7 +3001,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
3003 3001
3004 /* If we are not reading a key sequence, 3002 /* If we are not reading a key sequence,
3005 never use the echo area. */ 3003 never use the echo area. */
3006 if (maps == 0) 3004 if (!KEYMAPP (map))
3007 { 3005 {
3008 specbind (Qinput_method_use_echo_area, Qt); 3006 specbind (Qinput_method_use_echo_area, Qt);
3009 } 3007 }
@@ -3096,7 +3094,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
3096 last_input_event = c; 3094 last_input_event = c;
3097 num_input_events++; 3095 num_input_events++;
3098 3096
3099 /* Process the help character specially if enabled */ 3097 /* Process the help character specially if enabled. */
3100 if (!NILP (Vhelp_form) && help_char_p (c)) 3098 if (!NILP (Vhelp_form) && help_char_p (c))
3101 { 3099 {
3102 ptrdiff_t count = SPECPDL_INDEX (); 3100 ptrdiff_t count = SPECPDL_INDEX ();
@@ -3110,13 +3108,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
3110 cancel_echoing (); 3108 cancel_echoing ();
3111 do 3109 do
3112 { 3110 {
3113 c = read_char (0, 0, 0, Qnil, 0, NULL); 3111 c = read_char (0, Qnil, Qnil, 0, NULL);
3114 if (EVENT_HAS_PARAMETERS (c) 3112 if (EVENT_HAS_PARAMETERS (c)
3115 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_click)) 3113 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_click))
3116 XSETCAR (help_form_saved_window_configs, Qnil); 3114 XSETCAR (help_form_saved_window_configs, Qnil);
3117 } 3115 }
3118 while (BUFFERP (c)); 3116 while (BUFFERP (c));
3119 /* Remove the help from the frame */ 3117 /* Remove the help from the frame. */
3120 unbind_to (count, Qnil); 3118 unbind_to (count, Qnil);
3121 3119
3122 redisplay (); 3120 redisplay ();
@@ -3124,7 +3122,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
3124 { 3122 {
3125 cancel_echoing (); 3123 cancel_echoing ();
3126 do 3124 do
3127 c = read_char (0, 0, 0, Qnil, 0, NULL); 3125 c = read_char (0, Qnil, Qnil, 0, NULL);
3128 while (BUFFERP (c)); 3126 while (BUFFERP (c));
3129 } 3127 }
3130 } 3128 }
@@ -6227,9 +6225,7 @@ parse_modifiers (Lisp_Object symbol)
6227 Lisp_Object elements; 6225 Lisp_Object elements;
6228 6226
6229 if (INTEGERP (symbol)) 6227 if (INTEGERP (symbol))
6230 return (Fcons (make_number (KEY_TO_CHAR (symbol)), 6228 return list2i (KEY_TO_CHAR (symbol), XINT (symbol) & CHAR_MODIFIER_MASK);
6231 Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK),
6232 Qnil)));
6233 else if (!SYMBOLP (symbol)) 6229 else if (!SYMBOLP (symbol))
6234 return Qnil; 6230 return Qnil;
6235 6231
@@ -8314,9 +8310,9 @@ init_tool_bar_items (Lisp_Object reuse)
8314static void 8310static void
8315append_tool_bar_item (void) 8311append_tool_bar_item (void)
8316{ 8312{
8317 ptrdiff_t incr = 8313 ptrdiff_t incr
8318 (ntool_bar_items 8314 = (ntool_bar_items
8319 - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS)); 8315 - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
8320 8316
8321 /* Enlarge tool_bar_items_vector if necessary. */ 8317 /* Enlarge tool_bar_items_vector if necessary. */
8322 if (0 < incr) 8318 if (0 < incr)
@@ -8334,8 +8330,8 @@ append_tool_bar_item (void)
8334 8330
8335 8331
8336 8332
8337/* Read a character using menus based on maps in the array MAPS. 8333/* Read a character using menus based on the keymap MAP.
8338 NMAPS is the length of MAPS. Return nil if there are no menus in the maps. 8334 Return nil if there are no menus in the maps.
8339 Return t if we displayed a menu but the user rejected it. 8335 Return t if we displayed a menu but the user rejected it.
8340 8336
8341 PREV_EVENT is the previous input event, or nil if we are reading 8337 PREV_EVENT is the previous input event, or nil if we are reading
@@ -8355,28 +8351,17 @@ append_tool_bar_item (void)
8355 and do auto-saving in the inner call of read_char. */ 8351 and do auto-saving in the inner call of read_char. */
8356 8352
8357static Lisp_Object 8353static Lisp_Object
8358read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps, 8354read_char_x_menu_prompt (Lisp_Object map,
8359 Lisp_Object prev_event, bool *used_mouse_menu) 8355 Lisp_Object prev_event, bool *used_mouse_menu)
8360{ 8356{
8361#ifdef HAVE_MENUS
8362 ptrdiff_t mapno;
8363#endif
8364
8365 if (used_mouse_menu) 8357 if (used_mouse_menu)
8366 *used_mouse_menu = 0; 8358 *used_mouse_menu = 0;
8367 8359
8368 /* Use local over global Menu maps */ 8360 /* Use local over global Menu maps. */
8369 8361
8370 if (! menu_prompting) 8362 if (! menu_prompting)
8371 return Qnil; 8363 return Qnil;
8372 8364
8373 /* Optionally disregard all but the global map. */
8374 if (inhibit_local_menu_bar_menus)
8375 {
8376 maps += (nmaps - 1);
8377 nmaps = 1;
8378 }
8379
8380#ifdef HAVE_MENUS 8365#ifdef HAVE_MENUS
8381 /* If we got to this point via a mouse click, 8366 /* If we got to this point via a mouse click,
8382 use a real menu for mouse selection. */ 8367 use a real menu for mouse selection. */
@@ -8385,16 +8370,9 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
8385 && !EQ (XCAR (prev_event), Qtool_bar)) 8370 && !EQ (XCAR (prev_event), Qtool_bar))
8386 { 8371 {
8387 /* Display the menu and get the selection. */ 8372 /* Display the menu and get the selection. */
8388 Lisp_Object *realmaps = alloca (nmaps * sizeof *realmaps);
8389 Lisp_Object value; 8373 Lisp_Object value;
8390 ptrdiff_t nmaps1 = 0;
8391 8374
8392 /* Use the maps that are not nil. */ 8375 value = Fx_popup_menu (prev_event, get_keymap (map, 0, 1));
8393 for (mapno = 0; mapno < nmaps; mapno++)
8394 if (!NILP (maps[mapno]))
8395 realmaps[nmaps1++] = maps[mapno];
8396
8397 value = Fx_popup_menu (prev_event, Flist (nmaps1, realmaps));
8398 if (CONSP (value)) 8376 if (CONSP (value))
8399 { 8377 {
8400 Lisp_Object tem; 8378 Lisp_Object tem;
@@ -8434,17 +8412,10 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
8434 return Qnil ; 8412 return Qnil ;
8435} 8413}
8436 8414
8437/* Buffer in use so far for the minibuf prompts for menu keymaps.
8438 We make this bigger when necessary, and never free it. */
8439static char *read_char_minibuf_menu_text;
8440/* Size of that buffer. */
8441static ptrdiff_t read_char_minibuf_menu_width;
8442
8443static Lisp_Object 8415static Lisp_Object
8444read_char_minibuf_menu_prompt (int commandflag, 8416read_char_minibuf_menu_prompt (int commandflag,
8445 ptrdiff_t nmaps, Lisp_Object *maps) 8417 Lisp_Object map)
8446{ 8418{
8447 ptrdiff_t mapno;
8448 register Lisp_Object name; 8419 register Lisp_Object name;
8449 ptrdiff_t nlength; 8420 ptrdiff_t nlength;
8450 /* FIXME: Use the minibuffer's frame width. */ 8421 /* FIXME: Use the minibuffer's frame width. */
@@ -8452,53 +8423,35 @@ read_char_minibuf_menu_prompt (int commandflag,
8452 ptrdiff_t idx = -1; 8423 ptrdiff_t idx = -1;
8453 bool nobindings = 1; 8424 bool nobindings = 1;
8454 Lisp_Object rest, vector; 8425 Lisp_Object rest, vector;
8455 char *menu; 8426 Lisp_Object prompt_strings = Qnil;
8456 8427
8457 vector = Qnil; 8428 vector = Qnil;
8458 name = Qnil;
8459 8429
8460 if (! menu_prompting) 8430 if (! menu_prompting)
8461 return Qnil; 8431 return Qnil;
8462 8432
8463 /* Get the menu name from the first map that has one (a prompt string). */ 8433 map = get_keymap (map, 0, 1);
8464 for (mapno = 0; mapno < nmaps; mapno++) 8434 name = Fkeymap_prompt (map);
8465 {
8466 name = Fkeymap_prompt (maps[mapno]);
8467 if (!NILP (name))
8468 break;
8469 }
8470 8435
8471 /* If we don't have any menus, just read a character normally. */ 8436 /* If we don't have any menus, just read a character normally. */
8472 if (!STRINGP (name)) 8437 if (!STRINGP (name))
8473 return Qnil; 8438 return Qnil;
8474 8439
8475 /* Make sure we have a big enough buffer for the menu text. */ 8440#define PUSH_C_STR(str, listvar) \
8476 width = max (width, SBYTES (name)); 8441 listvar = Fcons (make_unibyte_string (str, strlen (str)), listvar)
8477 if (STRING_BYTES_BOUND - 4 < width)
8478 memory_full (SIZE_MAX);
8479 if (width + 4 > read_char_minibuf_menu_width)
8480 {
8481 read_char_minibuf_menu_text
8482 = xrealloc (read_char_minibuf_menu_text, width + 4);
8483 read_char_minibuf_menu_width = width + 4;
8484 }
8485 menu = read_char_minibuf_menu_text;
8486 8442
8487 /* Prompt string always starts with map's prompt, and a space. */ 8443 /* Prompt string always starts with map's prompt, and a space. */
8488 strcpy (menu, SSDATA (name)); 8444 prompt_strings = Fcons (name, prompt_strings);
8489 nlength = SBYTES (name); 8445 PUSH_C_STR (": ", prompt_strings);
8490 menu[nlength++] = ':'; 8446 nlength = SCHARS (name) + 2;
8491 menu[nlength++] = ' ';
8492 menu[nlength] = 0;
8493 8447
8494 /* Start prompting at start of first map. */ 8448 rest = map;
8495 mapno = 0;
8496 rest = maps[mapno];
8497 8449
8498 /* Present the documented bindings, a line at a time. */ 8450 /* Present the documented bindings, a line at a time. */
8499 while (1) 8451 while (1)
8500 { 8452 {
8501 bool notfirst = 0; 8453 bool notfirst = 0;
8454 Lisp_Object menu_strings = prompt_strings;
8502 ptrdiff_t i = nlength; 8455 ptrdiff_t i = nlength;
8503 Lisp_Object obj; 8456 Lisp_Object obj;
8504 Lisp_Object orig_defn_macro; 8457 Lisp_Object orig_defn_macro;
@@ -8508,18 +8461,16 @@ read_char_minibuf_menu_prompt (int commandflag,
8508 { 8461 {
8509 Lisp_Object elt; 8462 Lisp_Object elt;
8510 8463
8511 /* If reached end of map, start at beginning of next map. */ 8464 /* FIXME: Use map_keymap to handle new keymap formats. */
8465
8466 /* At end of map, wrap around if just starting,
8467 or end this line if already have something on it. */
8512 if (NILP (rest)) 8468 if (NILP (rest))
8513 { 8469 {
8514 mapno++; 8470 if (notfirst || nobindings)
8515 /* At end of last map, wrap around to first map if just starting, 8471 break;
8516 or end this line if already have something on it. */ 8472 else
8517 if (mapno == nmaps) 8473 rest = map;
8518 {
8519 mapno = 0;
8520 if (notfirst || nobindings) break;
8521 }
8522 rest = maps[mapno];
8523 } 8474 }
8524 8475
8525 /* Look at the next element of the map. */ 8476 /* Look at the next element of the map. */
@@ -8603,7 +8554,7 @@ read_char_minibuf_menu_prompt (int commandflag,
8603 /* Punctuate between strings. */ 8554 /* Punctuate between strings. */
8604 if (notfirst) 8555 if (notfirst)
8605 { 8556 {
8606 strcpy (menu + i, ", "); 8557 PUSH_C_STR (", ", menu_strings);
8607 i += 2; 8558 i += 2;
8608 } 8559 }
8609 notfirst = 1; 8560 notfirst = 1;
@@ -8615,23 +8566,28 @@ read_char_minibuf_menu_prompt (int commandflag,
8615 { 8566 {
8616 /* Add as much of string as fits. */ 8567 /* Add as much of string as fits. */
8617 thiswidth = min (SCHARS (desc), width - i); 8568 thiswidth = min (SCHARS (desc), width - i);
8618 memcpy (menu + i, SDATA (desc), thiswidth); 8569 menu_strings
8570 = Fcons (Fsubstring (desc, make_number (0),
8571 make_number (thiswidth)),
8572 menu_strings);
8619 i += thiswidth; 8573 i += thiswidth;
8620 strcpy (menu + i, " = "); 8574 PUSH_C_STR (" = ", menu_strings);
8621 i += 3; 8575 i += 3;
8622 } 8576 }
8623 8577
8624 /* Add as much of string as fits. */ 8578 /* Add as much of string as fits. */
8625 thiswidth = min (SCHARS (s), width - i); 8579 thiswidth = min (SCHARS (s), width - i);
8626 memcpy (menu + i, SDATA (s), thiswidth); 8580 menu_strings
8581 = Fcons (Fsubstring (s, make_number (0),
8582 make_number (thiswidth)),
8583 menu_strings);
8627 i += thiswidth; 8584 i += thiswidth;
8628 menu[i] = 0;
8629 } 8585 }
8630 else 8586 else
8631 { 8587 {
8632 /* If this element does not fit, end the line now, 8588 /* If this element does not fit, end the line now,
8633 and save the element for the next line. */ 8589 and save the element for the next line. */
8634 strcpy (menu + i, "..."); 8590 PUSH_C_STR ("...", menu_strings);
8635 break; 8591 break;
8636 } 8592 }
8637 } 8593 }
@@ -8648,23 +8604,19 @@ read_char_minibuf_menu_prompt (int commandflag,
8648 } 8604 }
8649 8605
8650 /* Prompt with that and read response. */ 8606 /* Prompt with that and read response. */
8651 message2_nolog (menu, strlen (menu), 8607 message3_nolog (apply1 (intern ("concat"), Fnreverse (menu_strings)));
8652 ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
8653 8608
8654 /* Make believe its not a keyboard macro in case the help char 8609 /* Make believe it's not a keyboard macro in case the help char
8655 is pressed. Help characters are not recorded because menu prompting 8610 is pressed. Help characters are not recorded because menu prompting
8656 is not used on replay. 8611 is not used on replay. */
8657 */
8658 orig_defn_macro = KVAR (current_kboard, defining_kbd_macro); 8612 orig_defn_macro = KVAR (current_kboard, defining_kbd_macro);
8659 kset_defining_kbd_macro (current_kboard, Qnil); 8613 kset_defining_kbd_macro (current_kboard, Qnil);
8660 do 8614 do
8661 obj = read_char (commandflag, 0, 0, Qt, 0, NULL); 8615 obj = read_char (commandflag, Qnil, Qt, 0, NULL);
8662 while (BUFFERP (obj)); 8616 while (BUFFERP (obj));
8663 kset_defining_kbd_macro (current_kboard, orig_defn_macro); 8617 kset_defining_kbd_macro (current_kboard, orig_defn_macro);
8664 8618
8665 if (!INTEGERP (obj)) 8619 if (!INTEGERP (obj) || XINT (obj) == -2)
8666 return obj;
8667 else if (XINT (obj) == -2)
8668 return obj; 8620 return obj;
8669 8621
8670 if (! EQ (obj, menu_prompt_more_char) 8622 if (! EQ (obj, menu_prompt_more_char)
@@ -8675,52 +8627,25 @@ read_char_minibuf_menu_prompt (int commandflag,
8675 store_kbd_macro_char (obj); 8627 store_kbd_macro_char (obj);
8676 return obj; 8628 return obj;
8677 } 8629 }
8678 /* Help char - go round again */ 8630 /* Help char - go round again. */
8679 } 8631 }
8680} 8632}
8681 8633
8682/* Reading key sequences. */ 8634/* Reading key sequences. */
8683 8635
8684/* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings 8636static Lisp_Object
8685 in DEFS[0..NMAPS-1]. Set NEXT[i] to DEFS[i] if DEFS[i] is a 8637follow_key (Lisp_Object keymap, Lisp_Object key)
8686 keymap, or nil otherwise. Return the index of the first keymap in
8687 which KEY has any binding, or NMAPS if no map has a binding.
8688
8689 If KEY is a meta ASCII character, treat it like meta-prefix-char
8690 followed by the corresponding non-meta character. Keymaps in
8691 CURRENT with non-prefix bindings for meta-prefix-char become nil in
8692 NEXT.
8693
8694 If KEY has no bindings in any of the CURRENT maps, NEXT is left
8695 unmodified.
8696
8697 NEXT may be the same array as CURRENT. */
8698
8699static int
8700follow_key (Lisp_Object key, ptrdiff_t nmaps, Lisp_Object *current,
8701 Lisp_Object *defs, Lisp_Object *next)
8702{ 8638{
8703 ptrdiff_t i, first_binding; 8639 return access_keymap (get_keymap (keymap, 0, 1),
8704 8640 key, 1, 0, 1);
8705 first_binding = nmaps; 8641}
8706 for (i = nmaps - 1; i >= 0; i--)
8707 {
8708 if (! NILP (current[i]))
8709 {
8710 defs[i] = access_keymap (current[i], key, 1, 0, 1);
8711 if (! NILP (defs[i]))
8712 first_binding = i;
8713 }
8714 else
8715 defs[i] = Qnil;
8716 }
8717
8718 /* Given the set of bindings we've found, produce the next set of maps. */
8719 if (first_binding < nmaps)
8720 for (i = 0; i < nmaps; i++)
8721 next[i] = NILP (defs[i]) ? Qnil : get_keymap (defs[i], 0, 1);
8722 8642
8723 return first_binding; 8643static Lisp_Object
8644active_maps (Lisp_Object first_event)
8645{
8646 Lisp_Object position
8647 = CONSP (first_event) ? CAR_SAFE (XCDR (first_event)) : Qnil;
8648 return Fcons (Qkeymap, Fcurrent_active_maps (Qt, position));
8724} 8649}
8725 8650
8726/* Structure used to keep track of partial application of key remapping 8651/* 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,
8852static bool 8777static bool
8853test_undefined (Lisp_Object binding) 8778test_undefined (Lisp_Object binding)
8854{ 8779{
8855 return (EQ (binding, Qundefined) 8780 return (NILP (binding)
8856 || (!NILP (binding) && SYMBOLP (binding) 8781 || EQ (binding, Qundefined)
8782 || (SYMBOLP (binding)
8857 && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined))); 8783 && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined)));
8858} 8784}
8859 8785
@@ -8899,7 +8825,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
8899 bool dont_downcase_last, bool can_return_switch_frame, 8825 bool dont_downcase_last, bool can_return_switch_frame,
8900 bool fix_current_buffer) 8826 bool fix_current_buffer)
8901{ 8827{
8902 Lisp_Object from_string;
8903 ptrdiff_t count = SPECPDL_INDEX (); 8828 ptrdiff_t count = SPECPDL_INDEX ();
8904 8829
8905 /* How many keys there are in the current key sequence. */ 8830 /* 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,
8910 ptrdiff_t echo_start IF_LINT (= 0); 8835 ptrdiff_t echo_start IF_LINT (= 0);
8911 ptrdiff_t keys_start; 8836 ptrdiff_t keys_start;
8912 8837
8913 /* The number of keymaps we're scanning right now, and the number of 8838 Lisp_Object current_binding = Qnil;
8914 keymaps we have allocated space for. */ 8839 Lisp_Object first_event = Qnil;
8915 ptrdiff_t nmaps;
8916 ptrdiff_t nmaps_allocated = 0;
8917
8918 /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in
8919 the current keymaps. */
8920 Lisp_Object *defs = NULL;
8921
8922 /* submaps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1]
8923 in the current keymaps, or nil where it is not a prefix. */
8924 Lisp_Object *submaps = NULL;
8925
8926 /* The local map to start out with at start of key sequence. */
8927 Lisp_Object orig_local_map;
8928 8840
8929 /* The map from the `keymap' property to start out with at start of
8930 key sequence. */
8931 Lisp_Object orig_keymap;
8932
8933 /* Positive if we have already considered switching to the local-map property
8934 of the place where a mouse click occurred. */
8935 int localized_local_map = 0;
8936
8937 /* The index in submaps[] of the first keymap that has a binding for
8938 this key sequence. In other words, the lowest i such that
8939 submaps[i] is non-nil. */
8940 ptrdiff_t first_binding;
8941 /* Index of the first key that has no binding. 8841 /* Index of the first key that has no binding.
8942 It is useless to try fkey.start larger than that. */ 8842 It is useless to try fkey.start larger than that. */
8943 int first_unbound; 8843 int first_unbound;
@@ -8980,11 +8880,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
8980 While we're reading, we keep the event here. */ 8880 While we're reading, we keep the event here. */
8981 Lisp_Object delayed_switch_frame; 8881 Lisp_Object delayed_switch_frame;
8982 8882
8983 /* See the comment below... */
8984#if defined (GOBBLE_FIRST_EVENT)
8985 Lisp_Object first_event;
8986#endif
8987
8988 Lisp_Object original_uppercase IF_LINT (= Qnil); 8883 Lisp_Object original_uppercase IF_LINT (= Qnil);
8989 int original_uppercase_position = -1; 8884 int original_uppercase_position = -1;
8990 8885
@@ -8996,10 +8891,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
8996 /* List of events for which a fake prefix key has been generated. */ 8891 /* List of events for which a fake prefix key has been generated. */
8997 Lisp_Object fake_prefixed_keys = Qnil; 8892 Lisp_Object fake_prefixed_keys = Qnil;
8998 8893
8999#if defined (GOBBLE_FIRST_EVENT)
9000 int junk;
9001#endif
9002
9003 struct gcpro gcpro1; 8894 struct gcpro gcpro1;
9004 8895
9005 GCPRO1 (fake_prefixed_keys); 8896 GCPRO1 (fake_prefixed_keys);
@@ -9035,21 +8926,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9035 keys_start = this_command_key_count; 8926 keys_start = this_command_key_count;
9036 this_single_command_key_start = keys_start; 8927 this_single_command_key_start = keys_start;
9037 8928
9038#if defined (GOBBLE_FIRST_EVENT)
9039 /* This doesn't quite work, because some of the things that read_char
9040 does cannot safely be bypassed. It seems too risky to try to make
9041 this work right. */
9042
9043 /* Read the first char of the sequence specially, before setting
9044 up any keymaps, in case a filter runs and switches buffers on us. */
9045 first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
9046 &junk, NULL);
9047#endif /* GOBBLE_FIRST_EVENT */
9048
9049 orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
9050 orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
9051 from_string = Qnil;
9052
9053 /* We jump here when we need to reinitialize fkey and keytran; this 8929 /* We jump here when we need to reinitialize fkey and keytran; this
9054 happens if we switch keyboards between rescans. */ 8930 happens if we switch keyboards between rescans. */
9055 replay_entire_sequence: 8931 replay_entire_sequence:
@@ -9074,59 +8950,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9074 keybuf with its symbol, or if the sequence starts with a mouse 8950 keybuf with its symbol, or if the sequence starts with a mouse
9075 click and we need to switch buffers, we jump back here to rebuild 8951 click and we need to switch buffers, we jump back here to rebuild
9076 the initial keymaps from the current buffer. */ 8952 the initial keymaps from the current buffer. */
9077 nmaps = 0; 8953 current_binding = active_maps (first_event);
9078
9079 if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map)))
9080 {
9081 if (2 > nmaps_allocated)
9082 {
9083 submaps = alloca (2 * sizeof *submaps);
9084 defs = alloca (2 * sizeof *defs);
9085 nmaps_allocated = 2;
9086 }
9087 submaps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
9088 }
9089 else if (!NILP (Voverriding_local_map))
9090 {
9091 if (2 > nmaps_allocated)
9092 {
9093 submaps = alloca (2 * sizeof *submaps);
9094 defs = alloca (2 * sizeof *defs);
9095 nmaps_allocated = 2;
9096 }
9097 submaps[nmaps++] = Voverriding_local_map;
9098 }
9099 else
9100 {
9101 ptrdiff_t nminor;
9102 ptrdiff_t total;
9103 Lisp_Object *maps;
9104
9105 nminor = current_minor_maps (0, &maps);
9106 total = nminor + (!NILP (orig_keymap) ? 3 : 2);
9107
9108 if (total > nmaps_allocated)
9109 {
9110 submaps = alloca (total * sizeof *submaps);
9111 defs = alloca (total * sizeof *defs);
9112 nmaps_allocated = total;
9113 }
9114
9115 if (!NILP (orig_keymap))
9116 submaps[nmaps++] = orig_keymap;
9117
9118 memcpy (submaps + nmaps, maps, nminor * sizeof (submaps[0]));
9119
9120 nmaps += nminor;
9121
9122 submaps[nmaps++] = orig_local_map;
9123 }
9124 submaps[nmaps++] = current_global_map;
9125
9126 /* Find an accurate initial value for first_binding. */
9127 for (first_binding = 0; first_binding < nmaps; first_binding++)
9128 if (! NILP (submaps[first_binding]))
9129 break;
9130 8954
9131 /* Start from the beginning in keybuf. */ 8955 /* Start from the beginning in keybuf. */
9132 t = 0; 8956 t = 0;
@@ -9140,9 +8964,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9140 /* If the best binding for the current key sequence is a keymap, or 8964 /* If the best binding for the current key sequence is a keymap, or
9141 we may be looking at a function key's escape sequence, keep on 8965 we may be looking at a function key's escape sequence, keep on
9142 reading. */ 8966 reading. */
9143 while (first_binding < nmaps 8967 while (!NILP (current_binding)
9144 /* Keep reading as long as there's a prefix binding. */ 8968 /* Keep reading as long as there's a prefix binding. */
9145 ? !NILP (submaps[first_binding]) 8969 ? KEYMAPP (current_binding)
9146 /* Don't return in the middle of a possible function key sequence, 8970 /* Don't return in the middle of a possible function key sequence,
9147 if the only bindings we found were via case conversion. 8971 if the only bindings we found were via case conversion.
9148 Thus, if ESC O a has a function-key-map translation 8972 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,
9166 just one key. */ 8990 just one key. */
9167 ptrdiff_t echo_local_start IF_LINT (= 0); 8991 ptrdiff_t echo_local_start IF_LINT (= 0);
9168 int keys_local_start; 8992 int keys_local_start;
9169 ptrdiff_t local_first_binding; 8993 Lisp_Object new_binding;
9170 8994
9171 eassert (indec.end == t || (indec.end > t && indec.end <= mock_input)); 8995 eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
9172 eassert (indec.start <= indec.end); 8996 eassert (indec.start <= indec.end);
@@ -9203,7 +9027,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9203 if (INTERACTIVE) 9027 if (INTERACTIVE)
9204 echo_local_start = echo_length (); 9028 echo_local_start = echo_length ();
9205 keys_local_start = this_command_key_count; 9029 keys_local_start = this_command_key_count;
9206 local_first_binding = first_binding;
9207 9030
9208 replay_key: 9031 replay_key:
9209 /* These are no-ops, unless we throw away a keystroke below and 9032 /* 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,
9213 if (INTERACTIVE && t < mock_input) 9036 if (INTERACTIVE && t < mock_input)
9214 echo_truncate (echo_local_start); 9037 echo_truncate (echo_local_start);
9215 this_command_key_count = keys_local_start; 9038 this_command_key_count = keys_local_start;
9216 first_binding = local_first_binding;
9217 9039
9218 /* By default, assume each event is "real". */ 9040 /* By default, assume each event is "real". */
9219 last_real_key_start = t; 9041 last_real_key_start = t;
@@ -9238,8 +9060,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9238 { 9060 {
9239 KBOARD *interrupted_kboard = current_kboard; 9061 KBOARD *interrupted_kboard = current_kboard;
9240 struct frame *interrupted_frame = SELECTED_FRAME (); 9062 struct frame *interrupted_frame = SELECTED_FRAME ();
9241 key = read_char (NILP (prompt), nmaps, 9063 key = read_char (NILP (prompt),
9242 (Lisp_Object *) submaps, last_nonmenu_event, 9064 current_binding, last_nonmenu_event,
9243 &used_mouse_menu, NULL); 9065 &used_mouse_menu, NULL);
9244 if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */ 9066 if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
9245 /* When switching to a new tty (with a new keyboard), 9067 /* 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,
9294 KVAR (interrupted_kboard, kbd_queue))); 9116 KVAR (interrupted_kboard, kbd_queue)));
9295 } 9117 }
9296 mock_input = 0; 9118 mock_input = 0;
9297 orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
9298 orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
9299 goto replay_entire_sequence; 9119 goto replay_entire_sequence;
9300 } 9120 }
9301 } 9121 }
@@ -9336,12 +9156,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9336 { 9156 {
9337 if (! FRAME_LIVE_P (XFRAME (selected_frame))) 9157 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
9338 Fkill_emacs (Qnil); 9158 Fkill_emacs (Qnil);
9339 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer) 9159 if (XBUFFER (XWINDOW (selected_window)->buffer)
9160 != current_buffer)
9340 Fset_buffer (XWINDOW (selected_window)->buffer); 9161 Fset_buffer (XWINDOW (selected_window)->buffer);
9341 } 9162 }
9342 9163
9343 orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
9344 orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
9345 goto replay_sequence; 9164 goto replay_sequence;
9346 } 9165 }
9347 9166
@@ -9358,8 +9177,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9358 keybuf[t++] = key; 9177 keybuf[t++] = key;
9359 mock_input = t; 9178 mock_input = t;
9360 Vquit_flag = Qnil; 9179 Vquit_flag = Qnil;
9361 orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
9362 orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
9363 goto replay_sequence; 9180 goto replay_sequence;
9364 } 9181 }
9365 9182
@@ -9379,6 +9196,22 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9379 } 9196 }
9380 } 9197 }
9381 9198
9199 if (NILP (first_event))
9200 {
9201 first_event = key;
9202 /* Even if first_event does not specify a particular
9203 window/position, it's important to recompute the maps here
9204 since a long time might have passed since we entered
9205 read_key_sequence, and a timer (or process-filter or
9206 special-event-map, ...) might have switched the current buffer
9207 or the selected window from under us in the mean time. */
9208 if (fix_current_buffer
9209 && (XBUFFER (XWINDOW (selected_window)->buffer)
9210 != current_buffer))
9211 Fset_buffer (XWINDOW (selected_window)->buffer);
9212 current_binding = active_maps (first_event);
9213 }
9214
9382 GROW_RAW_KEYBUF; 9215 GROW_RAW_KEYBUF;
9383 ASET (raw_keybuf, raw_keybuf_count, key); 9216 ASET (raw_keybuf, raw_keybuf_count, key);
9384 raw_keybuf_count++; 9217 raw_keybuf_count++;
@@ -9400,16 +9233,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9400 or when user programs play with this-command-keys. */ 9233 or when user programs play with this-command-keys. */
9401 if (EVENT_HAS_PARAMETERS (key)) 9234 if (EVENT_HAS_PARAMETERS (key))
9402 { 9235 {
9403 Lisp_Object kind; 9236 Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
9404 Lisp_Object string;
9405
9406 kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
9407 if (EQ (kind, Qmouse_click)) 9237 if (EQ (kind, Qmouse_click))
9408 { 9238 {
9409 Lisp_Object window, posn; 9239 Lisp_Object window = POSN_WINDOW (EVENT_START (key));
9410 9240 Lisp_Object posn = POSN_POSN (EVENT_START (key));
9411 window = POSN_WINDOW (EVENT_START (key));
9412 posn = POSN_POSN (EVENT_START (key));
9413 9241
9414 if (CONSP (posn) 9242 if (CONSP (posn)
9415 || (!NILP (fake_prefixed_keys) 9243 || (!NILP (fake_prefixed_keys)
@@ -9452,58 +9280,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9452 if (! FRAME_LIVE_P (XFRAME (selected_frame))) 9280 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
9453 Fkill_emacs (Qnil); 9281 Fkill_emacs (Qnil);
9454 set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); 9282 set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
9455 orig_local_map = get_local_map (PT, current_buffer,
9456 Qlocal_map);
9457 orig_keymap = get_local_map (PT, current_buffer,
9458 Qkeymap);
9459 goto replay_sequence; 9283 goto replay_sequence;
9460 } 9284 }
9461
9462 /* For a mouse click, get the local text-property keymap
9463 of the place clicked on, rather than point. */
9464 if (CONSP (XCDR (key))
9465 && ! localized_local_map)
9466 {
9467 Lisp_Object map_here, start, pos;
9468
9469 localized_local_map = 1;
9470 start = EVENT_START (key);
9471
9472 if (CONSP (start) && POSN_INBUFFER_P (start))
9473 {
9474 pos = POSN_BUFFER_POSN (start);
9475 if (INTEGERP (pos)
9476 && XINT (pos) >= BEGV
9477 && XINT (pos) <= ZV)
9478 {
9479 map_here = get_local_map (XINT (pos),
9480 current_buffer,
9481 Qlocal_map);
9482 if (!EQ (map_here, orig_local_map))
9483 {
9484 orig_local_map = map_here;
9485 ++localized_local_map;
9486 }
9487
9488 map_here = get_local_map (XINT (pos),
9489 current_buffer,
9490 Qkeymap);
9491 if (!EQ (map_here, orig_keymap))
9492 {
9493 orig_keymap = map_here;
9494 ++localized_local_map;
9495 }
9496
9497 if (localized_local_map > 1)
9498 {
9499 keybuf[t] = key;
9500 mock_input = t + 1;
9501
9502 goto replay_sequence;
9503 }
9504 }
9505 }
9506 }
9507 } 9285 }
9508 9286
9509 /* Expand mode-line and scroll-bar events into two events: 9287 /* 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,
9524 prevent proper action when the event is pushed 9302 prevent proper action when the event is pushed
9525 back into unread-command-events. */ 9303 back into unread-command-events. */
9526 fake_prefixed_keys = Fcons (key, fake_prefixed_keys); 9304 fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
9527
9528 /* If on a mode line string with a local keymap,
9529 reconsider the key sequence with that keymap. */
9530 if (string = POSN_STRING (EVENT_START (key)),
9531 (CONSP (string) && STRINGP (XCAR (string))))
9532 {
9533 Lisp_Object pos, map, map2;
9534
9535 pos = XCDR (string);
9536 string = XCAR (string);
9537 if (XINT (pos) >= 0
9538 && XINT (pos) < SCHARS (string))
9539 {
9540 map = Fget_text_property (pos, Qlocal_map, string);
9541 if (!NILP (map))
9542 orig_local_map = map;
9543 map2 = Fget_text_property (pos, Qkeymap, string);
9544 if (!NILP (map2))
9545 orig_keymap = map2;
9546 if (!NILP (map) || !NILP (map2))
9547 goto replay_sequence;
9548 }
9549 }
9550
9551 goto replay_key; 9305 goto replay_key;
9552 } 9306 }
9553 else if (NILP (from_string)
9554 && (string = POSN_STRING (EVENT_START (key)),
9555 (CONSP (string) && STRINGP (XCAR (string)))))
9556 {
9557 /* For a click on a string, i.e. overlay string or a
9558 string displayed via the `display' property,
9559 consider `local-map' and `keymap' properties of
9560 that string. */
9561 Lisp_Object pos, map, map2;
9562
9563 pos = XCDR (string);
9564 string = XCAR (string);
9565 if (XINT (pos) >= 0
9566 && XINT (pos) < SCHARS (string))
9567 {
9568 map = Fget_text_property (pos, Qlocal_map, string);
9569 if (!NILP (map))
9570 orig_local_map = map;
9571 map2 = Fget_text_property (pos, Qkeymap, string);
9572 if (!NILP (map2))
9573 orig_keymap = map2;
9574
9575 if (!NILP (map) || !NILP (map2))
9576 {
9577 from_string = string;
9578 keybuf[t++] = key;
9579 mock_input = t;
9580 goto replay_sequence;
9581 }
9582 }
9583 }
9584 } 9307 }
9585 else if (CONSP (XCDR (key)) 9308 else if (CONSP (XCDR (key))
9586 && CONSP (EVENT_START (key)) 9309 && CONSP (EVENT_START (key))
@@ -9596,7 +9319,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9596 if (bufsize - t <= 1) 9319 if (bufsize - t <= 1)
9597 error ("Key sequence too long"); 9320 error ("Key sequence too long");
9598 keybuf[t] = posn; 9321 keybuf[t] = posn;
9599 keybuf[t+1] = key; 9322 keybuf[t + 1] = key;
9600 9323
9601 /* Zap the position in key, so we know that we've 9324 /* Zap the position in key, so we know that we've
9602 expanded it, and don't try to do so again. */ 9325 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,
9619 9342
9620 /* We have finally decided that KEY is something we might want 9343 /* We have finally decided that KEY is something we might want
9621 to look up. */ 9344 to look up. */
9622 first_binding = (follow_key (key, 9345 new_binding = follow_key (current_binding, key);
9623 nmaps - first_binding,
9624 submaps + first_binding,
9625 defs + first_binding,
9626 submaps + first_binding)
9627 + first_binding);
9628 9346
9629 /* If KEY wasn't bound, we'll try some fallbacks. */ 9347 /* If KEY wasn't bound, we'll try some fallbacks. */
9630 if (first_binding < nmaps) 9348 if (!NILP (new_binding))
9631 /* This is needed for the following scenario: 9349 /* This is needed for the following scenario:
9632 event 0: a down-event that gets dropped by calling replay_key. 9350 event 0: a down-event that gets dropped by calling replay_key.
9633 event 1: some normal prefix like C-h. 9351 event 1: some normal prefix like C-h.
@@ -9764,20 +9482,13 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9764 new_click 9482 new_click
9765 = Fcons (new_head, Fcons (EVENT_START (key), Qnil)); 9483 = Fcons (new_head, Fcons (EVENT_START (key), Qnil));
9766 9484
9767 /* Look for a binding for this new key. follow_key 9485 /* Look for a binding for this new key. */
9768 promises that it didn't munge submaps the 9486 new_binding = follow_key (current_binding, new_click);
9769 last time we called it, since key was unbound. */
9770 first_binding
9771 = (follow_key (new_click,
9772 nmaps - local_first_binding,
9773 submaps + local_first_binding,
9774 defs + local_first_binding,
9775 submaps + local_first_binding)
9776 + local_first_binding);
9777 9487
9778 /* If that click is bound, go for it. */ 9488 /* If that click is bound, go for it. */
9779 if (first_binding < nmaps) 9489 if (!NILP (new_binding))
9780 { 9490 {
9491 current_binding = new_binding;
9781 key = new_click; 9492 key = new_click;
9782 break; 9493 break;
9783 } 9494 }
@@ -9786,6 +9497,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9786 } 9497 }
9787 } 9498 }
9788 } 9499 }
9500 current_binding = new_binding;
9789 9501
9790 keybuf[t++] = key; 9502 keybuf[t++] = key;
9791 /* Normally, last_nonmenu_event gets the previous key we read. 9503 /* 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,
9817 } 9529 }
9818 } 9530 }
9819 9531
9820 if (first_binding < nmaps 9532 if (!KEYMAPP (current_binding)
9821 && NILP (submaps[first_binding]) 9533 && !test_undefined (current_binding)
9822 && !test_undefined (defs[first_binding])
9823 && indec.start >= t) 9534 && indec.start >= t)
9824 /* There is a binding and it's not a prefix. 9535 /* There is a binding and it's not a prefix.
9825 (and it doesn't have any input-decode-map translation pending). 9536 (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,
9848 first_binding >= nmaps) we don't want 9559 first_binding >= nmaps) we don't want
9849 to apply this function-key-mapping. */ 9560 to apply this function-key-mapping. */
9850 fkey.end + 1 == t 9561 fkey.end + 1 == t
9851 && (first_binding >= nmaps 9562 && (test_undefined (current_binding)),
9852 || test_undefined (defs[first_binding])),
9853 &diff, prompt); 9563 &diff, prompt);
9854 UNGCPRO; 9564 UNGCPRO;
9855 if (done) 9565 if (done)
@@ -9892,7 +9602,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9892 and cannot be part of a function key or translation, 9602 and cannot be part of a function key or translation,
9893 and is an upper case letter 9603 and is an upper case letter
9894 use the corresponding lower-case letter instead. */ 9604 use the corresponding lower-case letter instead. */
9895 if (first_binding >= nmaps 9605 if (NILP (current_binding)
9896 && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t 9606 && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
9897 && INTEGERP (key) 9607 && INTEGERP (key)
9898 && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK)) 9608 && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK))
@@ -9923,7 +9633,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9923 and cannot be part of a function key or translation, 9633 and cannot be part of a function key or translation,
9924 and is a shifted function key, 9634 and is a shifted function key,
9925 use the corresponding unshifted function key instead. */ 9635 use the corresponding unshifted function key instead. */
9926 if (first_binding >= nmaps 9636 if (NILP (current_binding)
9927 && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t) 9637 && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t)
9928 { 9638 {
9929 Lisp_Object breakdown = parse_modifiers (key); 9639 Lisp_Object breakdown = parse_modifiers (key);
@@ -9964,9 +9674,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
9964 } 9674 }
9965 } 9675 }
9966 if (!dummyflag) 9676 if (!dummyflag)
9967 read_key_sequence_cmd = (first_binding < nmaps 9677 read_key_sequence_cmd = current_binding;
9968 ? defs[first_binding]
9969 : Qnil);
9970 read_key_sequence_remapped 9678 read_key_sequence_remapped
9971 /* Remap command through active keymaps. 9679 /* Remap command through active keymaps.
9972 Do the remapping here, before the unbind_to so it uses the keymaps 9680 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,
9980 9688
9981 /* Don't downcase the last character if the caller says don't. 9689 /* Don't downcase the last character if the caller says don't.
9982 Don't downcase it if the result is undefined, either. */ 9690 Don't downcase it if the result is undefined, either. */
9983 if ((dont_downcase_last || first_binding >= nmaps) 9691 if ((dont_downcase_last || NILP (current_binding))
9984 && t > 0 9692 && t > 0
9985 && t - 1 == original_uppercase_position) 9693 && t - 1 == original_uppercase_position)
9986 { 9694 {
@@ -10077,7 +9785,7 @@ will read just one key sequence. */)
10077 9785
10078 memset (keybuf, 0, sizeof keybuf); 9786 memset (keybuf, 0, sizeof keybuf);
10079 GCPRO1 (keybuf[0]); 9787 GCPRO1 (keybuf[0]);
10080 gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0])); 9788 gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0]));
10081 9789
10082 if (NILP (continue_echo)) 9790 if (NILP (continue_echo))
10083 { 9791 {
@@ -10091,7 +9799,7 @@ will read just one key sequence. */)
10091 cancel_hourglass (); 9799 cancel_hourglass ();
10092#endif 9800#endif
10093 9801
10094 i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])), 9802 i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
10095 prompt, ! NILP (dont_downcase_last), 9803 prompt, ! NILP (dont_downcase_last),
10096 ! NILP (can_return_switch_frame), 0); 9804 ! NILP (can_return_switch_frame), 0);
10097 9805
@@ -10166,95 +9874,6 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
10166 return unbind_to (count, Fvector (i, keybuf)); 9874 return unbind_to (count, Fvector (i, keybuf));
10167} 9875}
10168 9876
10169DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
10170 doc: /* Execute CMD as an editor command.
10171CMD must be a symbol that satisfies the `commandp' predicate.
10172Optional second arg RECORD-FLAG non-nil
10173means unconditionally put this command in the variable `command-history'.
10174Otherwise, that is done only if an arg is read using the minibuffer.
10175The argument KEYS specifies the value to use instead of (this-command-keys)
10176when reading the arguments; if it is nil, (this-command-keys) is used.
10177The argument SPECIAL, if non-nil, means that this command is executing
10178a special event, so ignore the prefix argument and don't clear it. */)
10179 (Lisp_Object cmd, Lisp_Object record_flag, Lisp_Object keys, Lisp_Object special)
10180{
10181 register Lisp_Object final;
10182 register Lisp_Object tem;
10183 Lisp_Object prefixarg;
10184
10185 debug_on_next_call = 0;
10186
10187 if (NILP (special))
10188 {
10189 prefixarg = KVAR (current_kboard, Vprefix_arg);
10190 Vcurrent_prefix_arg = prefixarg;
10191 kset_prefix_arg (current_kboard, Qnil);
10192 }
10193 else
10194 prefixarg = Qnil;
10195
10196 if (SYMBOLP (cmd))
10197 {
10198 tem = Fget (cmd, Qdisabled);
10199 if (!NILP (tem))
10200 {
10201 tem = Fsymbol_value (Qdisabled_command_function);
10202 if (!NILP (tem))
10203 return Frun_hooks (1, &Qdisabled_command_function);
10204 }
10205 }
10206
10207 while (1)
10208 {
10209 final = Findirect_function (cmd, Qnil);
10210
10211 if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
10212 {
10213 struct gcpro gcpro1, gcpro2;
10214
10215 GCPRO2 (cmd, prefixarg);
10216 Fautoload_do_load (final, cmd, Qnil);
10217 UNGCPRO;
10218 }
10219 else
10220 break;
10221 }
10222
10223 if (STRINGP (final) || VECTORP (final))
10224 {
10225 /* If requested, place the macro in the command history. For
10226 other sorts of commands, call-interactively takes care of
10227 this. */
10228 if (!NILP (record_flag))
10229 {
10230 Vcommand_history
10231 = Fcons (Fcons (Qexecute_kbd_macro,
10232 Fcons (final, Fcons (prefixarg, Qnil))),
10233 Vcommand_history);
10234
10235 /* Don't keep command history around forever. */
10236 if (NUMBERP (Vhistory_length) && XINT (Vhistory_length) > 0)
10237 {
10238 tem = Fnthcdr (Vhistory_length, Vcommand_history);
10239 if (CONSP (tem))
10240 XSETCDR (tem, Qnil);
10241 }
10242 }
10243
10244 return Fexecute_kbd_macro (final, prefixarg, Qnil);
10245 }
10246
10247 if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
10248 /* Don't call Fcall_interactively directly because we want to make
10249 sure the backtrace has an entry for `call-interactively'.
10250 For the same reason, pass `cmd' rather than `final'. */
10251 return call3 (Qcall_interactively, cmd, record_flag, keys);
10252
10253 return Qnil;
10254}
10255
10256
10257
10258/* Return true if input events are pending. */ 9877/* Return true if input events are pending. */
10259 9878
10260bool 9879bool
@@ -11485,8 +11104,7 @@ syms_of_keyboard (void)
11485 raw_keybuf = Fmake_vector (make_number (30), Qnil); 11104 raw_keybuf = Fmake_vector (make_number (30), Qnil);
11486 staticpro (&raw_keybuf); 11105 staticpro (&raw_keybuf);
11487 11106
11488 DEFSYM (Qextended_command_history, "extended-command-history"); 11107 DEFSYM (Qcommand_execute, "command-execute");
11489 Fset (Qextended_command_history, Qnil);
11490 11108
11491 accent_key_syms = Qnil; 11109 accent_key_syms = Qnil;
11492 staticpro (&accent_key_syms); 11110 staticpro (&accent_key_syms);
@@ -11525,7 +11143,6 @@ syms_of_keyboard (void)
11525 defsubr (&Srecursive_edit); 11143 defsubr (&Srecursive_edit);
11526 defsubr (&Strack_mouse); 11144 defsubr (&Strack_mouse);
11527 defsubr (&Sinput_pending_p); 11145 defsubr (&Sinput_pending_p);
11528 defsubr (&Scommand_execute);
11529 defsubr (&Srecent_keys); 11146 defsubr (&Srecent_keys);
11530 defsubr (&Sthis_command_keys); 11147 defsubr (&Sthis_command_keys);
11531 defsubr (&Sthis_command_keys_vector); 11148 defsubr (&Sthis_command_keys_vector);
@@ -11683,10 +11300,6 @@ This variable is also the threshold for motion of the mouse
11683to count as a drag. */); 11300to count as a drag. */);
11684 double_click_fuzz = 3; 11301 double_click_fuzz = 3;
11685 11302
11686 DEFVAR_BOOL ("inhibit-local-menu-bar-menus", inhibit_local_menu_bar_menus,
11687 doc: /* Non-nil means inhibit local map menu bar menus. */);
11688 inhibit_local_menu_bar_menus = 0;
11689
11690 DEFVAR_INT ("num-input-keys", num_input_keys, 11303 DEFVAR_INT ("num-input-keys", num_input_keys,
11691 doc: /* Number of complete key sequences read as input so far. 11304 doc: /* Number of complete key sequences read as input so far.
11692This includes key sequences read from keyboard macros. 11305This 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)
11914and its return value (a key sequence) is used. 11527and its return value (a key sequence) is used.
11915 11528
11916The events that come from bindings in `input-decode-map' are not 11529The events that come from bindings in `input-decode-map' are not
11917themselves looked up in `input-decode-map'. 11530themselves looked up in `input-decode-map'. */);
11918
11919This variable is keyboard-local. */);
11920 11531
11921 DEFVAR_LISP ("function-key-map", Vfunction_key_map, 11532 DEFVAR_LISP ("function-key-map", Vfunction_key_map,
11922 doc: /* The parent keymap of all `local-function-key-map' instances. 11533 doc: /* The parent keymap of all `local-function-key-map' instances.
@@ -11928,9 +11539,8 @@ definition will take precedence. */);
11928 11539
11929 DEFVAR_LISP ("key-translation-map", Vkey_translation_map, 11540 DEFVAR_LISP ("key-translation-map", Vkey_translation_map,
11930 doc: /* Keymap of key translations that can override keymaps. 11541 doc: /* Keymap of key translations that can override keymaps.
11931This keymap works like `function-key-map', but comes after that, 11542This keymap works like `input-decode-map', but comes after `function-key-map'.
11932and its non-prefix bindings override ordinary bindings. 11543Another difference is that it is global rather than terminal-local. */);
11933Another difference is that it is global rather than keyboard-local. */);
11934 Vkey_translation_map = Fmake_sparse_keymap (Qnil); 11544 Vkey_translation_map = Fmake_sparse_keymap (Qnil);
11935 11545
11936 DEFVAR_LISP ("deferred-action-list", Vdeferred_action_list, 11546 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;
482 482
483extern Lisp_Object parse_modifiers (Lisp_Object); 483extern Lisp_Object parse_modifiers (Lisp_Object);
484extern Lisp_Object reorder_modifiers (Lisp_Object); 484extern Lisp_Object reorder_modifiers (Lisp_Object);
485extern Lisp_Object read_char (int, ptrdiff_t, Lisp_Object *, Lisp_Object, 485extern Lisp_Object read_char (int, Lisp_Object, Lisp_Object,
486 bool *, EMACS_TIME *); 486 bool *, EMACS_TIME *);
487extern int parse_solitary_modifier (Lisp_Object symbol); 487extern int parse_solitary_modifier (Lisp_Object symbol);
488 488
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,
610 } 610 }
611 else if (CHAR_TABLE_P (binding)) 611 else if (CHAR_TABLE_P (binding))
612 map_char_table (map_keymap_char_table_item, Qnil, binding, 612 map_char_table (map_keymap_char_table_item, Qnil, binding,
613 format_save_value ("ppo", fun, data, args)); 613 make_save_value ("ppo", fun, data, args));
614 } 614 }
615 UNGCPRO; 615 UNGCPRO;
616 return tail; 616 return tail;
@@ -1244,7 +1244,7 @@ remapping in all currently active keymaps. */)
1244 return INTEGERP (command) ? Qnil : command; 1244 return INTEGERP (command) ? Qnil : command;
1245} 1245}
1246 1246
1247/* Value is number if KEY is too long; nil if valid but has no definition. */ 1247/* Value is number if KEY is too long; nil if valid but has no definition. */
1248/* GC is possible in this function. */ 1248/* GC is possible in this function. */
1249 1249
1250DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0, 1250DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0,
@@ -1536,7 +1536,7 @@ DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps,
1536 doc: /* Return a list of the currently active keymaps. 1536 doc: /* Return a list of the currently active keymaps.
1537OLP if non-nil indicates that we should obey `overriding-local-map' and 1537OLP if non-nil indicates that we should obey `overriding-local-map' and
1538`overriding-terminal-local-map'. POSITION can specify a click position 1538`overriding-terminal-local-map'. POSITION can specify a click position
1539like in the respective argument of `key-binding'. */) 1539like in the respective argument of `key-binding'. */)
1540 (Lisp_Object olp, Lisp_Object position) 1540 (Lisp_Object olp, Lisp_Object position)
1541{ 1541{
1542 ptrdiff_t count = SPECPDL_INDEX (); 1542 ptrdiff_t count = SPECPDL_INDEX ();
@@ -1545,7 +1545,7 @@ like in the respective argument of `key-binding'. */)
1545 1545
1546 /* If a mouse click position is given, our variables are based on 1546 /* If a mouse click position is given, our variables are based on
1547 the buffer clicked on, not the current buffer. So we may have to 1547 the buffer clicked on, not the current buffer. So we may have to
1548 switch the buffer here. */ 1548 switch the buffer here. */
1549 1549
1550 if (CONSP (position)) 1550 if (CONSP (position))
1551 { 1551 {
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 };
229 229
230/* Lisp integers use 2 tags, to give them one extra bit, thus 230/* Lisp integers use 2 tags, to give them one extra bit, thus
231 extending their range from, e.g., -2^28..2^28-1 to -2^29..2^29-1. */ 231 extending their range from, e.g., -2^28..2^28-1 to -2^29..2^29-1. */
232static EMACS_INT const INTMASK = EMACS_INT_MAX >> (INTTYPEBITS - 1); 232#define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1))
233#define case_Lisp_Int case Lisp_Int0: case Lisp_Int1 233#define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
234#define LISP_INT_TAG_P(x) (((x) & ~Lisp_Int1) == 0) 234#define LISP_INT_TAG_P(x) (((x) & ~Lisp_Int1) == 0)
235 235
@@ -510,13 +510,9 @@ static EMACS_INT const VALMASK
510 (XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \ 510 (XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \
511 + ((intptr_t) (ptr) & VALMASK))) 511 + ((intptr_t) (ptr) & VALMASK)))
512 512
513#if DATA_SEG_BITS
514/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers 513/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
515 which were stored in a Lisp_Object. */ 514 which were stored in a Lisp_Object. */
516#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK)) | DATA_SEG_BITS)) 515#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK) | DATA_SEG_BITS))
517#else
518#define XPNTR(a) ((uintptr_t) (XLI (a) & VALMASK))
519#endif
520 516
521#endif /* not USE_LSB_TAG */ 517#endif /* not USE_LSB_TAG */
522 518
@@ -1315,6 +1311,14 @@ sxhash_combine (EMACS_UINT x, EMACS_UINT y)
1315 return (x << 4) + (x >> (BITS_PER_EMACS_INT - 4)) + y; 1311 return (x << 4) + (x >> (BITS_PER_EMACS_INT - 4)) + y;
1316} 1312}
1317 1313
1314/* Hash X, returning a value that fits into a fixnum. */
1315
1316LISP_INLINE EMACS_UINT
1317SXHASH_REDUCE (EMACS_UINT x)
1318{
1319 return (x ^ x >> (BITS_PER_EMACS_INT - FIXNUM_BITS)) & INTMASK;
1320}
1321
1318/* These structures are used for various misc types. */ 1322/* These structures are used for various misc types. */
1319 1323
1320struct Lisp_Misc_Any /* Supertype of all Misc types. */ 1324struct Lisp_Misc_Any /* Supertype of all Misc types. */
@@ -1399,7 +1403,50 @@ enum
1399 SAVE_OBJECT 1403 SAVE_OBJECT
1400 }; 1404 };
1401 1405
1402/* Special object used to hold a different values for later use. */ 1406/* Special object used to hold a different values for later use.
1407
1408 This is mostly used to package C integers and pointers to call
1409 record_unwind_protect. Typical task is to pass just one C pointer
1410 to unwind function. You should pack pointer with make_save_pointer
1411 and then get it back with XSAVE_POINTER, e.g.:
1412
1413 ...
1414 struct my_data *md = get_my_data ();
1415 record_unwind_protect (my_unwind, make_save_pointer (md));
1416 ...
1417
1418 Lisp_Object my_unwind (Lisp_Object arg)
1419 {
1420 struct my_data *md = XSAVE_POINTER (arg, 0);
1421 ...
1422 }
1423
1424 If yon need to pass more than just one C pointer, you should
1425 use make_save_value. This function allows you to pack up to
1426 4 integers, pointers or Lisp_Objects and conveniently get them
1427 back with XSAVE_POINTER, XSAVE_INTEGER and XSAVE_OBJECT macros:
1428
1429 ...
1430 struct my_data *md = get_my_data ();
1431 ptrdiff_t my_offset = get_my_offset ();
1432 Lisp_Object my_object = get_my_object ();
1433 record_unwind_protect
1434 (my_unwind, make_save_value ("pio", md, my_offset, my_object));
1435 ...
1436
1437 Lisp_Object my_unwind (Lisp_Object arg)
1438 {
1439 struct my_data *md = XSAVE_POINTER (arg, 0);
1440 ptrdiff_t my_offset = XSAVE_INTEGER (arg, 1);
1441 Lisp_Object my_object = XSAVE_OBJECT (arg, 2);
1442 ...
1443 }
1444
1445 If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the
1446 saved objects and raise eassert if type of the saved object doesn't match
1447 the type which is extracted. In the example above, XSAVE_INTEGER (arg, 2)
1448 or XSAVE_OBJECT (arg, 1) are wrong because integer was saved in slot 1 and
1449 Lisp_Object was saved in slot 2 of ARG. */
1403 1450
1404struct Lisp_Save_Value 1451struct Lisp_Save_Value
1405 { 1452 {
@@ -2845,7 +2892,6 @@ extern int count_combining_after (const unsigned char *,
2845 ptrdiff_t, ptrdiff_t, ptrdiff_t); 2892 ptrdiff_t, ptrdiff_t, ptrdiff_t);
2846extern void insert (const char *, ptrdiff_t); 2893extern void insert (const char *, ptrdiff_t);
2847extern void insert_and_inherit (const char *, ptrdiff_t); 2894extern void insert_and_inherit (const char *, ptrdiff_t);
2848extern void insert_1 (const char *, ptrdiff_t, bool, bool, bool);
2849extern void insert_1_both (const char *, ptrdiff_t, ptrdiff_t, 2895extern void insert_1_both (const char *, ptrdiff_t, ptrdiff_t,
2850 bool, bool, bool); 2896 bool, bool, bool);
2851extern void insert_from_gap (ptrdiff_t, ptrdiff_t); 2897extern void insert_from_gap (ptrdiff_t, ptrdiff_t);
@@ -2919,11 +2965,9 @@ extern void clear_message (int, int);
2919extern void message (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); 2965extern void message (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
2920extern void message1 (const char *); 2966extern void message1 (const char *);
2921extern void message1_nolog (const char *); 2967extern void message1_nolog (const char *);
2922extern void message2 (const char *, ptrdiff_t, int); 2968extern void message3 (Lisp_Object);
2923extern void message2_nolog (const char *, ptrdiff_t, int); 2969extern void message3_nolog (Lisp_Object);
2924extern void message3 (Lisp_Object, ptrdiff_t, int); 2970extern void message_dolog (const char *, ptrdiff_t, bool, bool);
2925extern void message3_nolog (Lisp_Object, ptrdiff_t, int);
2926extern void message_dolog (const char *, ptrdiff_t, int, int);
2927extern void message_with_string (const char *, Lisp_Object, int); 2971extern void message_with_string (const char *, Lisp_Object, int);
2928extern void message_log_maybe_newline (void); 2972extern void message_log_maybe_newline (void);
2929extern void update_echo_area (void); 2973extern void update_echo_area (void);
@@ -2974,6 +3018,28 @@ extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object,
2974 Lisp_Object); 3018 Lisp_Object);
2975enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}; 3019enum constype {CONSTYPE_HEAP, CONSTYPE_PURE};
2976extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...); 3020extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...);
3021
3022/* Build a frequently used 2/3/4-integer lists. */
3023
3024LISP_INLINE Lisp_Object
3025list2i (EMACS_INT x, EMACS_INT y)
3026{
3027 return list2 (make_number (x), make_number (y));
3028}
3029
3030LISP_INLINE Lisp_Object
3031list3i (EMACS_INT x, EMACS_INT y, EMACS_INT w)
3032{
3033 return list3 (make_number (x), make_number (y), make_number (w));
3034}
3035
3036LISP_INLINE Lisp_Object
3037list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h)
3038{
3039 return list4 (make_number (x), make_number (y),
3040 make_number (w), make_number (h));
3041}
3042
2977extern _Noreturn void string_overflow (void); 3043extern _Noreturn void string_overflow (void);
2978extern Lisp_Object make_string (const char *, ptrdiff_t); 3044extern Lisp_Object make_string (const char *, ptrdiff_t);
2979extern Lisp_Object make_formatted_string (char *, const char *, ...) 3045extern Lisp_Object make_formatted_string (char *, const char *, ...)
@@ -3020,6 +3086,27 @@ extern void make_byte_code (struct Lisp_Vector *);
3020extern Lisp_Object Qautomatic_gc; 3086extern Lisp_Object Qautomatic_gc;
3021extern Lisp_Object Qchar_table_extra_slots; 3087extern Lisp_Object Qchar_table_extra_slots;
3022extern struct Lisp_Vector *allocate_vector (EMACS_INT); 3088extern struct Lisp_Vector *allocate_vector (EMACS_INT);
3089
3090/* Make an uninitialized vector for SIZE objects. NOTE: you must
3091 be sure that GC cannot happen until the vector is completely
3092 initialized. E.g. the following code is likely to crash:
3093
3094 v = make_uninit_vector (3);
3095 ASET (v, 0, obj0);
3096 ASET (v, 1, Ffunction_can_gc ());
3097 ASET (v, 2, obj1); */
3098
3099LISP_INLINE Lisp_Object
3100make_uninit_vector (ptrdiff_t size)
3101{
3102 Lisp_Object v;
3103 struct Lisp_Vector *p;
3104
3105 p = allocate_vector (size);
3106 XSETVECTOR (v, p);
3107 return v;
3108}
3109
3023extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type); 3110extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type);
3024#define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ 3111#define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \
3025 ((typ*) \ 3112 ((typ*) \
@@ -3035,8 +3122,8 @@ extern bool abort_on_gc;
3035extern Lisp_Object make_float (double); 3122extern Lisp_Object make_float (double);
3036extern void display_malloc_warning (void); 3123extern void display_malloc_warning (void);
3037extern ptrdiff_t inhibit_garbage_collection (void); 3124extern ptrdiff_t inhibit_garbage_collection (void);
3038extern Lisp_Object format_save_value (const char *, ...); 3125extern Lisp_Object make_save_value (const char *, ...);
3039extern Lisp_Object make_save_value (void *, ptrdiff_t); 3126extern Lisp_Object make_save_pointer (void *);
3040extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); 3127extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
3041extern void free_marker (Lisp_Object); 3128extern void free_marker (Lisp_Object);
3042extern void free_cons (struct Lisp_Cons *); 3129extern void free_cons (struct Lisp_Cons *);
@@ -3274,8 +3361,10 @@ extern Lisp_Object close_file_unwind (Lisp_Object);
3274extern Lisp_Object restore_point_unwind (Lisp_Object); 3361extern Lisp_Object restore_point_unwind (Lisp_Object);
3275extern _Noreturn void report_file_error (const char *, Lisp_Object); 3362extern _Noreturn void report_file_error (const char *, Lisp_Object);
3276extern bool internal_delete_file (Lisp_Object); 3363extern bool internal_delete_file (Lisp_Object);
3364extern Lisp_Object emacs_readlinkat (int, const char *);
3277extern bool file_directory_p (const char *); 3365extern bool file_directory_p (const char *);
3278extern bool file_accessible_directory_p (const char *); 3366extern bool file_accessible_directory_p (const char *);
3367extern void init_fileio (void);
3279extern void syms_of_fileio (void); 3368extern void syms_of_fileio (void);
3280extern Lisp_Object make_temp_name (Lisp_Object, bool); 3369extern Lisp_Object make_temp_name (Lisp_Object, bool);
3281extern Lisp_Object Qdelete_file; 3370extern Lisp_Object Qdelete_file;
@@ -3288,20 +3377,21 @@ extern void record_unwind_save_match_data (void);
3288struct re_registers; 3377struct re_registers;
3289extern struct re_pattern_buffer *compile_pattern (Lisp_Object, 3378extern struct re_pattern_buffer *compile_pattern (Lisp_Object,
3290 struct re_registers *, 3379 struct re_registers *,
3291 Lisp_Object, int, int); 3380 Lisp_Object, int, bool);
3292extern ptrdiff_t fast_string_match (Lisp_Object, Lisp_Object); 3381extern ptrdiff_t fast_string_match (Lisp_Object, Lisp_Object);
3293extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *, 3382extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
3294 ptrdiff_t); 3383 ptrdiff_t);
3295extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object); 3384extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object);
3296extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, 3385extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
3297 ptrdiff_t, ptrdiff_t, Lisp_Object); 3386 ptrdiff_t, ptrdiff_t, Lisp_Object);
3298extern ptrdiff_t scan_buffer (int, ptrdiff_t, ptrdiff_t, ptrdiff_t, 3387extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
3299 ptrdiff_t *, bool); 3388 ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
3300extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, 3389extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
3301 EMACS_INT, bool); 3390 EMACS_INT, bool);
3302extern ptrdiff_t find_next_newline (ptrdiff_t, int); 3391extern ptrdiff_t find_newline_no_quit (ptrdiff_t, ptrdiff_t,
3303extern ptrdiff_t find_next_newline_no_quit (ptrdiff_t, ptrdiff_t); 3392 ptrdiff_t, ptrdiff_t *);
3304extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t); 3393extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t,
3394 ptrdiff_t, ptrdiff_t *);
3305extern void syms_of_search (void); 3395extern void syms_of_search (void);
3306extern void clear_regexp_cache (void); 3396extern void clear_regexp_cache (void);
3307 3397
@@ -3318,7 +3408,7 @@ extern void syms_of_minibuf (void);
3318 3408
3319extern Lisp_Object Qminus, Qplus; 3409extern Lisp_Object Qminus, Qplus;
3320extern Lisp_Object Qwhen; 3410extern Lisp_Object Qwhen;
3321extern Lisp_Object Qcall_interactively, Qmouse_leave_buffer_hook; 3411extern Lisp_Object Qmouse_leave_buffer_hook;
3322extern void syms_of_callint (void); 3412extern void syms_of_callint (void);
3323 3413
3324/* Defined in casefiddle.c. */ 3414/* Defined in casefiddle.c. */
@@ -3429,10 +3519,10 @@ extern bool running_asynch_code;
3429extern Lisp_Object QCtype, Qlocal; 3519extern Lisp_Object QCtype, Qlocal;
3430extern Lisp_Object Qprocessp; 3520extern Lisp_Object Qprocessp;
3431extern void kill_buffer_processes (Lisp_Object); 3521extern void kill_buffer_processes (Lisp_Object);
3432extern int wait_reading_process_output (intmax_t, int, int, bool, 3522extern bool wait_reading_process_output (intmax_t, int, int, bool,
3433 Lisp_Object, 3523 Lisp_Object,
3434 struct Lisp_Process *, 3524 struct Lisp_Process *,
3435 int); 3525 int);
3436/* Max value for the first argument of wait_reading_process_output. */ 3526/* Max value for the first argument of wait_reading_process_output. */
3437#if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) 3527#if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)
3438/* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3. 3528/* 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,
3478 Lisp_Object, ptrdiff_t, Lisp_Object *); 3568 Lisp_Object, ptrdiff_t, Lisp_Object *);
3479 3569
3480/* Defined in macros.c. */ 3570/* Defined in macros.c. */
3481extern Lisp_Object Qexecute_kbd_macro;
3482extern void init_macros (void); 3571extern void init_macros (void);
3483extern void syms_of_macros (void); 3572extern void syms_of_macros (void);
3484 3573
@@ -3544,8 +3633,6 @@ extern int emacs_open (const char *, int, int);
3544extern int emacs_close (int); 3633extern int emacs_close (int);
3545extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); 3634extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
3546extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); 3635extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t);
3547enum { READLINK_BUFSIZE = 1024 };
3548extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]);
3549 3636
3550extern void unlock_all_files (void); 3637extern void unlock_all_files (void);
3551extern void lock_file (Lisp_Object); 3638extern void lock_file (Lisp_Object);
@@ -3686,12 +3773,11 @@ extern char *egetenv (const char *);
3686/* Set up the name of the machine we're running on. */ 3773/* Set up the name of the machine we're running on. */
3687extern void init_system_name (void); 3774extern void init_system_name (void);
3688 3775
3689/* We used to use `abs', but that clashes with system headers on some 3776/* Return the absolute value of X. X should be a signed integer
3690 platforms, and using a name reserved by Standard C is a bad idea 3777 expression without side effects, and X's absolute value should not
3691 anyway. */ 3778 exceed the maximum for its promoted type. This is called 'eabs'
3692#if !defined (eabs) 3779 because 'abs' is reserved by the C standard. */
3693#define eabs(x) ((x) < 0 ? -(x) : (x)) 3780#define eabs(x) ((x) < 0 ? -(x) : (x))
3694#endif
3695 3781
3696/* Return a fixnum or float, depending on whether VAL fits in a Lisp 3782/* Return a fixnum or float, depending on whether VAL fits in a Lisp
3697 fixnum. */ 3783 fixnum. */
@@ -3720,16 +3806,16 @@ extern void *record_xmalloc (size_t);
3720 NITEMS items, each of the same type as *BUF. MULTIPLIER must 3806 NITEMS items, each of the same type as *BUF. MULTIPLIER must
3721 positive. The code is tuned for MULTIPLIER being a constant. */ 3807 positive. The code is tuned for MULTIPLIER being a constant. */
3722 3808
3723#define SAFE_NALLOCA(buf, multiplier, nitems) \ 3809#define SAFE_NALLOCA(buf, multiplier, nitems) \
3724 do { \ 3810 do { \
3725 if ((nitems) <= MAX_ALLOCA / sizeof *(buf) / (multiplier)) \ 3811 if ((nitems) <= MAX_ALLOCA / sizeof *(buf) / (multiplier)) \
3726 (buf) = alloca (sizeof *(buf) * (multiplier) * (nitems)); \ 3812 (buf) = alloca (sizeof *(buf) * (multiplier) * (nitems)); \
3727 else \ 3813 else \
3728 { \ 3814 { \
3729 (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \ 3815 (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \
3730 sa_must_free = 1; \ 3816 sa_must_free = 1; \
3731 record_unwind_protect (safe_alloca_unwind, \ 3817 record_unwind_protect (safe_alloca_unwind, \
3732 make_save_value (buf, 0)); \ 3818 make_save_pointer (buf)); \
3733 } \ 3819 } \
3734 } while (0) 3820 } while (0)
3735 3821
@@ -3754,7 +3840,7 @@ extern void *record_xmalloc (size_t);
3754 { \ 3840 { \
3755 Lisp_Object arg_; \ 3841 Lisp_Object arg_; \
3756 buf = xmalloc ((nelt) * word_size); \ 3842 buf = xmalloc ((nelt) * word_size); \
3757 arg_ = make_save_value (buf, nelt); \ 3843 arg_ = make_save_value ("pi", buf, nelt); \
3758 XSAVE_VALUE (arg_)->area = 1; \ 3844 XSAVE_VALUE (arg_)->area = 1; \
3759 sa_must_free = 1; \ 3845 sa_must_free = 1; \
3760 record_unwind_protect (safe_alloca_unwind, arg_); \ 3846 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;
96 It must be set to nil before all top-level calls to read0. */ 96 It must be set to nil before all top-level calls to read0. */
97static Lisp_Object read_objects; 97static Lisp_Object read_objects;
98 98
99/* True means READCHAR should read bytes one by one (not character)
100 when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char.
101 This is set by read1 temporarily while handling #@NUMBER. */
102static bool load_each_byte;
103
104/* List of descriptors now open for Fload. */ 99/* List of descriptors now open for Fload. */
105static Lisp_Object load_descriptor_list; 100static Lisp_Object load_descriptor_list;
106 101
@@ -328,7 +323,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
328 return c; 323 return c;
329 } 324 }
330 c = (*readbyte) (-1, readcharfun); 325 c = (*readbyte) (-1, readcharfun);
331 if (c < 0 || load_each_byte) 326 if (c < 0)
332 return c; 327 return c;
333 if (multibyte) 328 if (multibyte)
334 *multibyte = 1; 329 *multibyte = 1;
@@ -353,6 +348,30 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
353 return STRING_CHAR (buf); 348 return STRING_CHAR (buf);
354} 349}
355 350
351static void
352skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n)
353{
354 if (EQ (readcharfun, Qget_file_char)
355 || EQ (readcharfun, Qget_emacs_mule_file_char))
356 {
357 block_input (); /* FIXME: Not sure if it's needed. */
358 fseek (instream, n, SEEK_CUR);
359 unblock_input ();
360 }
361 else
362 { /* We're not reading directly from a file. In that case, it's difficult
363 to reliably count bytes, since these are usually meant for the file's
364 encoding, whereas we're now typically in the internal encoding.
365 But luckily, skip_dyn_bytes is used to skip over a single
366 dynamic-docstring (or dynamic byte-code) which is always quoted such
367 that \037 is the final char. */
368 int c;
369 do {
370 c = READCHAR;
371 } while (c >= 0 && c != '\037');
372 }
373}
374
356/* Unread the character C in the way appropriate for the stream READCHARFUN. 375/* Unread the character C in the way appropriate for the stream READCHARFUN.
357 If the stream is a user function, call it with the char as argument. */ 376 If the stream is a user function, call it with the char as argument. */
358 377
@@ -407,14 +426,7 @@ unreadchar (Lisp_Object readcharfun, int c)
407 else if (EQ (readcharfun, Qget_file_char) 426 else if (EQ (readcharfun, Qget_file_char)
408 || EQ (readcharfun, Qget_emacs_mule_file_char)) 427 || EQ (readcharfun, Qget_emacs_mule_file_char))
409 { 428 {
410 if (load_each_byte) 429 unread_char = c;
411 {
412 block_input ();
413 ungetc (c, instream);
414 unblock_input ();
415 }
416 else
417 unread_char = c;
418 } 430 }
419 else 431 else
420 call1 (readcharfun, make_number (c)); 432 call1 (readcharfun, make_number (c));
@@ -602,17 +614,17 @@ read_filtered_event (bool no_switch_frame, bool ascii_required,
602 end_time = add_emacs_time (current_emacs_time (), wait_time); 614 end_time = add_emacs_time (current_emacs_time (), wait_time);
603 } 615 }
604 616
605/* Read until we get an acceptable event. */ 617 /* Read until we get an acceptable event. */
606 retry: 618 retry:
607 do 619 do
608 val = read_char (0, 0, 0, (input_method ? Qnil : Qt), 0, 620 val = read_char (0, Qnil, (input_method ? Qnil : Qt), 0,
609 NUMBERP (seconds) ? &end_time : NULL); 621 NUMBERP (seconds) ? &end_time : NULL);
610 while (INTEGERP (val) && XINT (val) == -2); /* wrong_kboard_jmpbuf */ 622 while (INTEGERP (val) && XINT (val) == -2); /* wrong_kboard_jmpbuf */
611 623
612 if (BUFFERP (val)) 624 if (BUFFERP (val))
613 goto retry; 625 goto retry;
614 626
615 /* switch-frame events are put off until after the next ASCII 627 /* `switch-frame' events are put off until after the next ASCII
616 character. This is better than signaling an error just because 628 character. This is better than signaling an error just because
617 the last characters were typed to a separate minibuffer frame, 629 the last characters were typed to a separate minibuffer frame,
618 for example. Eventually, some code which can deal with 630 for example. Eventually, some code which can deal with
@@ -1298,7 +1310,7 @@ Return t if the file exists and loads successfully. */)
1298 message_with_string ("Loading %s...", file, 1); 1310 message_with_string ("Loading %s...", file, 1);
1299 } 1311 }
1300 1312
1301 record_unwind_protect (load_unwind, make_save_value (stream, 0)); 1313 record_unwind_protect (load_unwind, make_save_pointer (stream));
1302 record_unwind_protect (load_descriptor_unwind, load_descriptor_list); 1314 record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
1303 specbind (Qload_file_name, found); 1315 specbind (Qload_file_name, found);
1304 specbind (Qinhibit_file_name_operation, Qnil); 1316 specbind (Qinhibit_file_name_operation, Qnil);
@@ -2388,7 +2400,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2388 bool multibyte; 2400 bool multibyte;
2389 2401
2390 *pch = 0; 2402 *pch = 0;
2391 load_each_byte = 0;
2392 2403
2393 retry: 2404 retry:
2394 2405
@@ -2598,7 +2609,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2598 return tmp; 2609 return tmp;
2599 } 2610 }
2600 2611
2601 /* #@NUMBER is used to skip NUMBER following characters. 2612 /* #@NUMBER is used to skip NUMBER following bytes.
2602 That's used in .elc files to skip over doc strings 2613 That's used in .elc files to skip over doc strings
2603 and function definitions. */ 2614 and function definitions. */
2604 if (c == '@') 2615 if (c == '@')
@@ -2606,7 +2617,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2606 enum { extra = 100 }; 2617 enum { extra = 100 };
2607 ptrdiff_t i, nskip = 0; 2618 ptrdiff_t i, nskip = 0;
2608 2619
2609 load_each_byte = 1;
2610 /* Read a decimal integer. */ 2620 /* Read a decimal integer. */
2611 while ((c = READCHAR) >= 0 2621 while ((c = READCHAR) >= 0
2612 && c >= '0' && c <= '9') 2622 && c >= '0' && c <= '9')
@@ -2616,8 +2626,15 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2616 nskip *= 10; 2626 nskip *= 10;
2617 nskip += c - '0'; 2627 nskip += c - '0';
2618 } 2628 }
2619 UNREAD (c); 2629 if (nskip > 0)
2620 2630 /* We can't use UNREAD here, because in the code below we side-step
2631 READCHAR. Instead, assume the first char after #@NNN occupies
2632 a single byte, which is the case normally since it's just
2633 a space. */
2634 nskip--;
2635 else
2636 UNREAD (c);
2637
2621 if (load_force_doc_strings 2638 if (load_force_doc_strings
2622 && (EQ (readcharfun, Qget_file_char) 2639 && (EQ (readcharfun, Qget_file_char)
2623 || EQ (readcharfun, Qget_emacs_mule_file_char))) 2640 || EQ (readcharfun, Qget_emacs_mule_file_char)))
@@ -2659,19 +2676,17 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2659 saved_doc_string_position = file_tell (instream); 2676 saved_doc_string_position = file_tell (instream);
2660 2677
2661 /* Copy that many characters into saved_doc_string. */ 2678 /* Copy that many characters into saved_doc_string. */
2679 block_input ();
2662 for (i = 0; i < nskip && c >= 0; i++) 2680 for (i = 0; i < nskip && c >= 0; i++)
2663 saved_doc_string[i] = c = READCHAR; 2681 saved_doc_string[i] = c = getc (instream);
2682 unblock_input ();
2664 2683
2665 saved_doc_string_length = i; 2684 saved_doc_string_length = i;
2666 } 2685 }
2667 else 2686 else
2668 { 2687 /* Skip that many bytes. */
2669 /* Skip that many characters. */ 2688 skip_dyn_bytes (readcharfun, nskip);
2670 for (i = 0; i < nskip && c >= 0; i++)
2671 c = READCHAR;
2672 }
2673 2689
2674 load_each_byte = 0;
2675 goto retry; 2690 goto retry;
2676 } 2691 }
2677 if (c == '!') 2692 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/>. */
28#include "window.h" 28#include "window.h"
29#include "keyboard.h" 29#include "keyboard.h"
30 30
31Lisp_Object Qexecute_kbd_macro; 31static Lisp_Object Qexecute_kbd_macro;
32static Lisp_Object Qkbd_macro_termination_hook; 32static Lisp_Object Qkbd_macro_termination_hook;
33 33
34/* Number of successful iterations so far 34/* Number of successful iterations so far
@@ -78,7 +78,7 @@ macro before appending to it. */)
78 } 78 }
79 current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer; 79 current_kboard->kbd_macro_ptr = current_kboard->kbd_macro_buffer;
80 current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer; 80 current_kboard->kbd_macro_end = current_kboard->kbd_macro_buffer;
81 message ("Defining kbd macro..."); 81 message1 ("Defining kbd macro...");
82 } 82 }
83 else 83 else
84 { 84 {
@@ -125,7 +125,7 @@ macro before appending to it. */)
125 Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), 125 Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro),
126 make_number (1), Qnil); 126 make_number (1), Qnil);
127 127
128 message ("Appending to kbd macro..."); 128 message1 ("Appending to kbd macro...");
129 } 129 }
130 kset_defining_kbd_macro (current_kboard, Qt); 130 kset_defining_kbd_macro (current_kboard, Qt);
131 131
@@ -172,21 +172,21 @@ each iteration of the macro. Iteration stops if LOOPFUNC returns nil. */)
172 if (!NILP (KVAR (current_kboard, defining_kbd_macro))) 172 if (!NILP (KVAR (current_kboard, defining_kbd_macro)))
173 { 173 {
174 end_kbd_macro (); 174 end_kbd_macro ();
175 message ("Keyboard macro defined"); 175 message1 ("Keyboard macro defined");
176 } 176 }
177 177
178 if (XFASTINT (repeat) == 0) 178 if (XFASTINT (repeat) == 0)
179 Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc); 179 Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), repeat, loopfunc);
180 else if (XINT (repeat) > 1) 180 else if (XINT (repeat) > 1)
181 { 181 {
182 XSETINT (repeat, XINT (repeat)-1); 182 XSETINT (repeat, XINT (repeat) - 1);
183 Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro), 183 Fexecute_kbd_macro (KVAR (current_kboard, Vlast_kbd_macro),
184 repeat, loopfunc); 184 repeat, loopfunc);
185 } 185 }
186 return Qnil; 186 return Qnil;
187} 187}
188 188
189/* Store character c into kbd macro being defined */ 189/* Store character c into kbd macro being defined. */
190 190
191void 191void
192store_kbd_macro_char (Lisp_Object c) 192store_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) : \
847 $(NT_INC)/sys/file.h \ 847 $(NT_INC)/sys/file.h \
848 $(NT_INC)/sys/stat.h \ 848 $(NT_INC)/sys/stat.h \
849 $(NT_INC)/unistd.h \ 849 $(NT_INC)/unistd.h \
850 $(GNU_LIB)/allocator.h \
850 $(BUFFER_H) \ 851 $(BUFFER_H) \
852 $(CAREADLINKAT_H) \
851 $(CHARACTER_H) \ 853 $(CHARACTER_H) \
852 $(CODING_H) \ 854 $(CODING_H) \
853 $(CONFIG_H) \ 855 $(CONFIG_H) \
@@ -862,6 +864,7 @@ $(BLD)/fileio.$(O) : \
862 864
863$(BLD)/filelock.$(O) : \ 865$(BLD)/filelock.$(O) : \
864 $(SRC)/filelock.c \ 866 $(SRC)/filelock.c \
867 $(SRC)/w32.h \
865 $(NT_INC)/pwd.h \ 868 $(NT_INC)/pwd.h \
866 $(NT_INC)/sys/file.h \ 869 $(NT_INC)/sys/file.h \
867 $(NT_INC)/sys/stat.h \ 870 $(NT_INC)/sys/stat.h \
@@ -1397,11 +1400,9 @@ $(BLD)/sysdep.$(O) : \
1397 $(NT_INC)/sys/file.h \ 1400 $(NT_INC)/sys/file.h \
1398 $(NT_INC)/sys/stat.h \ 1401 $(NT_INC)/sys/stat.h \
1399 $(NT_INC)/unistd.h \ 1402 $(NT_INC)/unistd.h \
1400 $(GNU_LIB)/allocator.h \
1401 $(GNU_LIB)/execinfo.h \ 1403 $(GNU_LIB)/execinfo.h \
1402 $(GNU_LIB)/ignore-value.h \ 1404 $(GNU_LIB)/ignore-value.h \
1403 $(GNU_LIB)/utimens.h \ 1405 $(GNU_LIB)/utimens.h \
1404 $(CAREADLINKAT_H) \
1405 $(CONFIG_H) \ 1406 $(CONFIG_H) \
1406 $(C_CTYPE_H) \ 1407 $(C_CTYPE_H) \
1407 $(DISPEXTERN_H) \ 1408 $(DISPEXTERN_H) \
@@ -1492,7 +1493,6 @@ $(BLD)/unexw32.$(O) : \
1492 1493
1493$(BLD)/vm-limit.$(O) : \ 1494$(BLD)/vm-limit.$(O) : \
1494 $(SRC)/vm-limit.c \ 1495 $(SRC)/vm-limit.c \
1495 $(SRC)/mem-limits.h \
1496 $(SRC)/w32heap.h \ 1496 $(SRC)/w32heap.h \
1497 $(NT_INC)/unistd.h \ 1497 $(NT_INC)/unistd.h \
1498 $(CONFIG_H) \ 1498 $(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,
499 { 499 {
500 register ptrdiff_t charpos, bytepos; 500 register ptrdiff_t charpos, bytepos;
501 501
502 CHECK_NUMBER_COERCE_MARKER (position); 502 /* Do not use CHECK_NUMBER_COERCE_MARKER because we
503 charpos = clip_to_bounds (restricted ? BUF_BEGV (b) : BUF_BEG (b), 503 don't want to call buf_charpos_to_bytepos if POSITION
504 XINT (position), 504 is a marker and so we know the bytepos already. */
505 restricted ? BUF_ZV (b) : BUF_Z (b)); 505 if (INTEGERP (position))
506 bytepos = buf_charpos_to_bytepos (b, charpos); 506 charpos = XINT (position), bytepos = -1;
507 else if (MARKERP (position))
508 {
509 charpos = XMARKER (position)->charpos;
510 bytepos = XMARKER (position)->bytepos;
511 }
512 else
513 wrong_type_argument (Qinteger_or_marker_p, position);
514
515 charpos = clip_to_bounds
516 (restricted ? BUF_BEGV (b) : BUF_BEG (b), charpos,
517 restricted ? BUF_ZV (b) : BUF_Z (b));
518 if (bytepos == -1)
519 bytepos = buf_charpos_to_bytepos (b, charpos);
520 else
521 bytepos = clip_to_bounds
522 (restricted ? BUF_BEGV_BYTE (b) : BUF_BEG_BYTE (b),
523 bytepos, restricted ? BUF_ZV_BYTE (b) : BUF_Z_BYTE (b));
524
507 attach_marker (m, b, charpos, bytepos); 525 attach_marker (m, b, charpos, bytepos);
508 } 526 }
509 return marker; 527 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 @@
1/* Includes for memory limit warnings.
2 Copyright (C) 1990, 1993-1996, 2001-2013 Free Software Foundation,
3 Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifdef MSDOS
21#include <dpmi.h>
22extern int etext;
23#endif
24
25/* Some systems need this before <sys/resource.h>. */
26#include <sys/types.h>
27
28#ifdef HAVE_SYS_RESOURCE_H
29# include <sys/time.h>
30# include <sys/resource.h>
31#else
32# if HAVE_SYS_VLIMIT_H
33# include <sys/vlimit.h> /* Obsolete, says glibc */
34# endif
35#endif
36
37extern char *start_of_data (void) ATTRIBUTE_CONST;
38#if USE_LSB_TAG || UINTPTR_MAX <= VAL_MAX
39#define EXCEEDS_LISP_PTR(ptr) 0
40#else
41#define EXCEEDS_LISP_PTR(ptr) \
42 (((uintptr_t) (ptr) & ~DATA_SEG_BITS) >> VALBITS)
43#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 @@
1/* MS-DOS specific C utilities. -*- coding: raw-text -*- 1/* MS-DOS specific C utilities. -*- coding: cp850 -*-
2 2
3Copyright (C) 1993-1997, 1999-2013 Free Software Foundation, Inc. 3Copyright (C) 1993-1997, 1999-2013 Free Software Foundation, Inc.
4 4
@@ -20,6 +20,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20/* Contributed by Morten Welinder */ 20/* Contributed by Morten Welinder */
21/* New display, keyboard, and mouse control by Kim F. Storm */ 21/* New display, keyboard, and mouse control by Kim F. Storm */
22 22
23/* Note: This file MUST use a unibyte encoding, to both display the
24 keys on the non-US keyboard layout as their respective labels, and
25 provide the correct byte values for the keyboard input to inject
26 into Emacs. See 'struct dos_keyboard_map' below. As long as there
27 are only European keyboard layouts here, we are OK with DOS
28 codepage 850 encoding. */
29
23/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */ 30/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
24 31
25#include <config.h> 32#include <config.h>
@@ -1965,10 +1972,10 @@ struct dos_keyboard_map
1965 1972
1966static struct dos_keyboard_map us_keyboard = { 1973static struct dos_keyboard_map us_keyboard = {
1967/* 0 1 2 3 4 5 */ 1974/* 0 1 2 3 4 5 */
1968/* 01234567890123456789012345678901234567890 12345678901234 */ 1975/* 01234567890123456789012345678901234567890 123 45678901234 */
1969 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ", 1976 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ \\zxcvbnm,./ ",
1970/* 0123456789012345678901234567890123456789 012345678901234 */ 1977/* 0123456789012345678901234567890123456789 012345678901234 */
1971 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ", 1978 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| |ZXCVBNM<>? ",
1972 0, /* no Alt-Gr key */ 1979 0, /* no Alt-Gr key */
1973 0 /* no translate table */ 1980 0 /* no translate table */
1974}; 1981};
@@ -1976,9 +1983,9 @@ static struct dos_keyboard_map us_keyboard = {
1976static struct dos_keyboard_map fr_keyboard = { 1983static struct dos_keyboard_map fr_keyboard = {
1977/* 0 1 2 3 4 5 */ 1984/* 0 1 2 3 4 5 */
1978/* 012 3456789012345678901234567890123456789012345678901234 */ 1985/* 012 3456789012345678901234567890123456789012345678901234 */
1979 "ý&‚\",(-Š_€…)= azertyuiop^$ qsdfghjklm—* wxcvbnm;:! ", 1986 "ý&‚\"'(-Š_€…)= azertyuiop^$ qsdfghjklm—* <wxcvbn,;:! ",
1980/* 0123456789012345678901234567890123456789012345678901234 */ 1987/* 0123456789012345678901234567890123456789012345678901234 */
1981 " 1234567890ø+ AZERTYUIOPùœ QSDFGHJKLM%æ WXCVBN?./õ ", 1988 " 1234567890ø+ AZERTYUIOPùœ QSDFGHJKLM%æ >WXCVBN?./õ ",
1982/* 01234567 89012345678901234567890123456789012345678901234 */ 1989/* 01234567 89012345678901234567890123456789012345678901234 */
1983 " ~#{[|`\\^@]} Ï ", 1990 " ~#{[|`\\^@]} Ï ",
1984 0 /* no translate table */ 1991 0 /* no translate table */
@@ -2000,9 +2007,9 @@ static struct kbd_translate it_kbd_translate_table[] = {
2000static struct dos_keyboard_map it_keyboard = { 2007static struct dos_keyboard_map it_keyboard = {
2001/* 0 1 2 3 4 5 */ 2008/* 0 1 2 3 4 5 */
2002/* 0 123456789012345678901234567890123456789012345678901234 */ 2009/* 0 123456789012345678901234567890123456789012345678901234 */
2003 "\\1234567890'< qwertyuiopŠ+> asdfghjkl•…— zxcvbnm,.- ", 2010 "\\1234567890'< qwertyuiopŠ+> asdfghjkl•…— <zxcvbnm,.- ",
2004/* 01 23456789012345678901234567890123456789012345678901234 */ 2011/* 01 23456789012345678901234567890123456789012345678901234 */
2005 "|!\"œ$%&/()=?^> QWERTYUIOP‚* ASDFGHJKL‡øõ ZXCVBNM;:_ ", 2012 "|!\"œ$%&/()=?^> QWERTYUIOP‚* ASDFGHJKL‡øõ >ZXCVBNM;:_ ",
2006/* 0123456789012345678901234567890123456789012345678901234 */ 2013/* 0123456789012345678901234567890123456789012345678901234 */
2007 " {}~` [] @# ", 2014 " {}~` [] @# ",
2008 it_kbd_translate_table 2015 it_kbd_translate_table
@@ -2011,9 +2018,9 @@ static struct dos_keyboard_map it_keyboard = {
2011static struct dos_keyboard_map dk_keyboard = { 2018static struct dos_keyboard_map dk_keyboard = {
2012/* 0 1 2 3 4 5 */ 2019/* 0 1 2 3 4 5 */
2013/* 0123456789012345678901234567890123456789012345678901234 */ 2020/* 0123456789012345678901234567890123456789012345678901234 */
2014 "«1234567890+| qwertyuiop†~ asdfghjkl‘›' zxcvbnm,.- ", 2021 "«1234567890+| qwertyuiop†~ asdfghjkl‘›' <zxcvbnm,.- ",
2015/* 01 23456789012345678901234567890123456789012345678901234 */ 2022/* 01 23456789012345678901234567890123456789012345678901234 */
2016 "õ!\"#$%&/()=?` QWERTYUIOP^ ASDFGHJKL’* ZXCVBNM;:_ ", 2023 "õ!\"#$%&/()=?` QWERTYUIOP^ ASDFGHJKL’* >ZXCVBNM;:_ ",
2017/* 0123456789012345678901234567890123456789012345678901234 */ 2024/* 0123456789012345678901234567890123456789012345678901234 */
2018 " @œ$ {[]} | ", 2025 " @œ$ {[]} | ",
2019 0 /* no translate table */ 2026 0 /* no translate table */
@@ -3281,10 +3288,10 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
3281 erasing it works correctly... */ 3288 erasing it works correctly... */
3282 if (! NILP (saved_echo_area_message)) 3289 if (! NILP (saved_echo_area_message))
3283 message_with_string ("%s", saved_echo_area_message, 0); 3290 message_with_string ("%s", saved_echo_area_message, 0);
3284 message (0); 3291 message1 (0);
3285 while (statecount--) 3292 while (statecount--)
3286 xfree (state[statecount].screen_behind); 3293 xfree (state[statecount].screen_behind);
3287 IT_display_cursor (1); /* turn cursor back on */ 3294 IT_display_cursor (1); /* Turn cursor back on. */
3288 /* Clean up any mouse events that are waiting inside Emacs event queue. 3295 /* Clean up any mouse events that are waiting inside Emacs event queue.
3289 These events are likely to be generated before the menu was even 3296 These events are likely to be generated before the menu was even
3290 displayed, probably because the user pressed and released the button 3297 displayed, probably because the user pressed and released the button
@@ -3339,7 +3346,7 @@ void msdos_downcase_filename (unsigned char *);
3339/* Destructively turn backslashes into slashes. */ 3346/* Destructively turn backslashes into slashes. */
3340 3347
3341void 3348void
3342dostounix_filename (char *p) 3349dostounix_filename (char *p, int ignore)
3343{ 3350{
3344 msdos_downcase_filename (p); 3351 msdos_downcase_filename (p);
3345 3352
@@ -3603,7 +3610,7 @@ init_environment (int argc, char **argv, int skip_args)
3603 if (!s) s = "c:/command.com"; 3610 if (!s) s = "c:/command.com";
3604 t = alloca (strlen (s) + 1); 3611 t = alloca (strlen (s) + 1);
3605 strcpy (t, s); 3612 strcpy (t, s);
3606 dostounix_filename (t); 3613 dostounix_filename (t, 0);
3607 setenv ("SHELL", t, 0); 3614 setenv ("SHELL", t, 0);
3608 3615
3609 /* PATH is also downcased and backslashes mirrored. */ 3616 /* PATH is also downcased and backslashes mirrored. */
@@ -3613,7 +3620,7 @@ init_environment (int argc, char **argv, int skip_args)
3613 /* Current directory is always considered part of MsDos's path but it is 3620 /* Current directory is always considered part of MsDos's path but it is
3614 not normally mentioned. Now it is. */ 3621 not normally mentioned. Now it is. */
3615 strcat (strcpy (t, ".;"), s); 3622 strcat (strcpy (t, ".;"), s);
3616 dostounix_filename (t); /* Not a single file name, but this should work. */ 3623 dostounix_filename (t, 0); /* Not a single file name, but this should work. */
3617 setenv ("PATH", t, 1); 3624 setenv ("PATH", t, 1);
3618 3625
3619 /* In some sense all dos users have root privileges, so... */ 3626 /* In some sense all dos users have root privileges, so... */
@@ -3957,14 +3964,6 @@ careadlinkat (int fd, char const *filename,
3957 return buffer; 3964 return buffer;
3958} 3965}
3959 3966
3960ssize_t
3961careadlinkatcwd (int fd, char const *filename, char *buffer,
3962 size_t buffer_size)
3963{
3964 (void) fd;
3965 return readlink (filename, buffer, buffer_size);
3966}
3967
3968 3967
3969#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2 3968#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
3970 3969
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 *);
29 29
30int getdefdir (int, char*); 30int getdefdir (int, char*);
31void unixtodos_filename (char *); 31void unixtodos_filename (char *);
32void dostounix_filename (char *); 32void dostounix_filename (char *, int);
33char *rootrelativepath (char *); 33char *rootrelativepath (char *);
34void init_environment (int, char **, int); 34void init_environment (int, char **, int);
35void internal_terminal_init (void); 35void 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. */)
1649 The last number is where we distinguish between the Apple 1649 The last number is where we distinguish between the Apple
1650 and GNUstep implementations ("distributor-specific release 1650 and GNUstep implementations ("distributor-specific release
1651 number") and give int'ized versions of major.minor. */ 1651 number") and give int'ized versions of major.minor. */
1652 return Fcons (make_number (10), 1652 return list3i (10, 3, ns_appkit_version_int ());
1653 Fcons (make_number (3),
1654 Fcons (make_number (ns_appkit_version_int()), Qnil)));
1655} 1653}
1656 1654
1657 1655
@@ -2296,9 +2294,8 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2296 2294
2297 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace] 2295 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
2298 getRed: &red green: &green blue: &blue alpha: &alpha]; 2296 getRed: &red green: &green blue: &blue alpha: &alpha];
2299 return list3 (make_number (lrint (red*65280)), 2297 return list3i (lrint (red * 65280), lrint (green * 65280),
2300 make_number (lrint (green*65280)), 2298 lrint (blue * 65280));
2301 make_number (lrint (blue*65280)));
2302} 2299}
2303 2300
2304 2301
@@ -2385,11 +2382,10 @@ that stands for the selected frame's display. */)
2385 2382
2386 /* NS coordinate system is upside-down. 2383 /* NS coordinate system is upside-down.
2387 Transform to screen-specific coordinates. */ 2384 Transform to screen-specific coordinates. */
2388 return list4 (make_number ((int) vScreen.origin.x), 2385 return list4i (vScreen.origin.x,
2389 make_number ((int) [screen frame].size.height 2386 [screen frame].size.height
2390 - vScreen.size.height - vScreen.origin.y), 2387 - vScreen.size.height - vScreen.origin.y,
2391 make_number ((int) vScreen.size.width), 2388 vScreen.size.width, vScreen.size.height);
2392 make_number ((int) vScreen.size.height));
2393} 2389}
2394 2390
2395 2391
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,
75static void 75static void
76ns_escape_name (char *name) 76ns_escape_name (char *name)
77{ 77{
78 int i =0, len =strlen (name); 78 for (; *name; name++)
79 for ( ; i<len; i++) 79 if (*name == ' ')
80 if (name[i] == ' ') 80 *name = '_';
81 name[i] = '_';
82} 81}
83 82
84 83
@@ -86,10 +85,9 @@ ns_escape_name (char *name)
86static void 85static void
87ns_unescape_name (char *name) 86ns_unescape_name (char *name)
88{ 87{
89 int i =0, len =strlen (name); 88 for (; *name; name++)
90 for ( ; i<len; i++) 89 if (*name == '_')
91 if (name[i] == '_') 90 *name = ' ';
92 name[i] = ' ';
93} 91}
94 92
95 93
@@ -364,7 +362,7 @@ static NSString
364 while CONSP (rts) 362 while CONSP (rts)
365 { 363 {
366 r = XCAR (XCAR (rts)); 364 r = XCAR (XCAR (rts));
367 if (!strncmp(SSDATA(r), reg, strlen(SSDATA(r)))) 365 if (!strncmp (SSDATA (r), reg, SBYTES (r)))
368 { 366 {
369 script = XCDR (XCAR (rts)); 367 script = XCDR (XCAR (rts));
370 return [NSString stringWithUTF8String: SSDATA (SYMBOL_NAME (script))]; 368 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)
1110 FRAME_TOOLBAR_HEIGHT (f) = 1110 FRAME_TOOLBAR_HEIGHT (f) =
1111 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)]) 1111 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1112 - FRAME_NS_TITLEBAR_HEIGHT (f); 1112 - FRAME_NS_TITLEBAR_HEIGHT (f);
1113 if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen.
1114 FRAME_TOOLBAR_HEIGHT (f) = 0;
1113 unblock_input (); 1115 unblock_input ();
1114} 1116}
1115 1117
@@ -1440,7 +1442,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
1440 unwind_data->pool = pool; 1442 unwind_data->pool = pool;
1441 unwind_data->dialog = dialog; 1443 unwind_data->dialog = dialog;
1442 1444
1443 record_unwind_protect (pop_down_menu, make_save_value (unwind_data, 0)); 1445 record_unwind_protect (pop_down_menu, make_save_pointer (unwind_data));
1444 popup_activated_flag = 1; 1446 popup_activated_flag = 1;
1445 tem = [dialog runDialogAt: p]; 1447 tem = [dialog runDialogAt: p];
1446 unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */ 1448 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)
117 117
118 if (size == 1) 118 if (size == 1)
119 return clean_local_selection_data (AREF (obj, 0)); 119 return clean_local_selection_data (AREF (obj, 0));
120 copy = Fmake_vector (make_number (size), Qnil); 120 copy = make_uninit_vector (size);
121 for (i = 0; i < size; i++) 121 for (i = 0; i < size; i++)
122 ASET (copy, i, clean_local_selection_data (AREF (obj, i))); 122 ASET (copy, i, clean_local_selection_data (AREF (obj, i)));
123 return copy; 123 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/>. */
42#ifndef MAC_OS_X_VERSION_10_8 42#ifndef MAC_OS_X_VERSION_10_8
43#define MAC_OS_X_VERSION_10_8 1080 43#define MAC_OS_X_VERSION_10_8 1080
44#endif 44#endif
45
46#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
47#define HAVE_NATIVE_FS
48#endif
49
45#endif /* NS_IMPL_COCOA */ 50#endif /* NS_IMPL_COCOA */
46 51
47#ifdef __OBJC__ 52#ifdef __OBJC__
@@ -88,6 +93,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
88 int tibar_height, tobar_height, bwidth; 93 int tibar_height, tobar_height, bwidth;
89 int maximized_width, maximized_height; 94 int maximized_width, maximized_height;
90 NSWindow *nonfs_window; 95 NSWindow *nonfs_window;
96 BOOL fs_is_native;
91@public 97@public
92 struct frame *emacsframe; 98 struct frame *emacsframe;
93 int rows, cols; 99 int rows, cols;
@@ -115,6 +121,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
115- (void) handleFS; 121- (void) handleFS;
116- (void) setFSValue: (int)value; 122- (void) setFSValue: (int)value;
117- (void) toggleFullScreen: (id) sender; 123- (void) toggleFullScreen: (id) sender;
124- (BOOL) fsIsNative;
125- (BOOL) isFullscreen;
126#ifdef HAVE_NATIVE_FS
127- (void) updateCollectionBehaviour;
128#endif
118 129
119#ifdef NS_IMPL_GNUSTEP 130#ifdef NS_IMPL_GNUSTEP
120/* Not declared, but useful. */ 131/* 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;
69#define NSTRACE(x) 69#define NSTRACE(x)
70#endif 70#endif
71 71
72#if defined (NS_IMPL_COCOA) && \
73 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
74#define NEW_STYLE_FS
75#endif
76
77extern NSString *NSMenuDidBeginTrackingNotification; 72extern NSString *NSMenuDidBeginTrackingNotification;
78 73
79/* ========================================================================== 74/* ==========================================================================
@@ -224,6 +219,7 @@ static int n_emacs_events_pending = 0;
224static NSMutableArray *ns_pending_files, *ns_pending_service_names, 219static NSMutableArray *ns_pending_files, *ns_pending_service_names,
225 *ns_pending_service_args; 220 *ns_pending_service_args;
226static BOOL ns_do_open_file = NO; 221static BOOL ns_do_open_file = NO;
222static BOOL ns_last_use_native_fullscreen;
227 223
228static struct { 224static struct {
229 struct input_event *q; 225 struct input_event *q;
@@ -1000,11 +996,8 @@ ns_raise_frame (struct frame *f)
1000 NSView *view = FRAME_NS_VIEW (f); 996 NSView *view = FRAME_NS_VIEW (f);
1001 check_ns (); 997 check_ns ();
1002 block_input (); 998 block_input ();
1003 FRAME_SAMPLE_VISIBILITY (f);
1004 if (FRAME_VISIBLE_P (f)) 999 if (FRAME_VISIBLE_P (f))
1005 { 1000 [[view window] makeKeyAndOrderFront: NSApp];
1006 [[view window] makeKeyAndOrderFront: NSApp];
1007 }
1008 unblock_input (); 1001 unblock_input ();
1009} 1002}
1010 1003
@@ -1093,16 +1086,16 @@ x_make_frame_visible (struct frame *f)
1093 if (!FRAME_VISIBLE_P (f)) 1086 if (!FRAME_VISIBLE_P (f))
1094 { 1087 {
1095 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); 1088 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1096 f->async_visible = 1; 1089
1090 SET_FRAME_VISIBLE (f, 1);
1097 ns_raise_frame (f); 1091 ns_raise_frame (f);
1098 1092
1099#ifdef NEW_STYLE_FS
1100 /* Making a new frame from a fullscreen frame will make the new frame 1093 /* Making a new frame from a fullscreen frame will make the new frame
1101 fullscreen also. So skip handleFS as this will print an error. */ 1094 fullscreen also. So skip handleFS as this will print an error. */
1102 if (f->want_fullscreen == FULLSCREEN_BOTH 1095 if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH
1103 && ([[view window] styleMask] & NSFullScreenWindowMask) != 0) 1096 && [view isFullscreen])
1104 return; 1097 return;
1105#endif 1098
1106 if (f->want_fullscreen != FULLSCREEN_NONE) 1099 if (f->want_fullscreen != FULLSCREEN_NONE)
1107 { 1100 {
1108 block_input (); 1101 block_input ();
@@ -1123,8 +1116,8 @@ x_make_frame_invisible (struct frame *f)
1123 NSTRACE (x_make_frame_invisible); 1116 NSTRACE (x_make_frame_invisible);
1124 check_ns (); 1117 check_ns ();
1125 [[view window] orderOut: NSApp]; 1118 [[view window] orderOut: NSApp];
1126 f->async_visible = 0; 1119 SET_FRAME_VISIBLE (f, 0);
1127 f->async_iconified = 0; 1120 SET_FRAME_ICONIFIED (f, 0);
1128} 1121}
1129 1122
1130 1123
@@ -1294,7 +1287,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
1294 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); 1287 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1295 1288
1296 /* If we have a toolbar, take its height into account. */ 1289 /* If we have a toolbar, take its height into account. */
1297 if (tb) 1290 if (tb && ! [view isFullscreen])
1298 /* NOTE: previously this would generate wrong result if toolbar not 1291 /* NOTE: previously this would generate wrong result if toolbar not
1299 yet displayed and fixing toolbar_height=32 helped, but 1292 yet displayed and fixing toolbar_height=32 helped, but
1300 now (200903) seems no longer needed */ 1293 now (200903) seems no longer needed */
@@ -1305,8 +1298,10 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
1305 FRAME_TOOLBAR_HEIGHT (f) = 0; 1298 FRAME_TOOLBAR_HEIGHT (f) = 0;
1306 1299
1307 wr.size.width = pixelwidth + f->border_width; 1300 wr.size.width = pixelwidth + f->border_width;
1308 wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f) 1301 wr.size.height = pixelheight;
1309 + FRAME_TOOLBAR_HEIGHT (f); 1302 if (! [view isFullscreen])
1303 wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f)
1304 + FRAME_TOOLBAR_HEIGHT (f);
1310 1305
1311 /* Do not try to constrain to this screen. We may have multiple 1306 /* Do not try to constrain to this screen. We may have multiple
1312 screens, and want Emacs to span those. Constraining to screen 1307 screens, and want Emacs to span those. Constraining to screen
@@ -1354,9 +1349,10 @@ ns_fullscreen_hook (FRAME_PTR f)
1354{ 1349{
1355 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); 1350 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1356 1351
1357 if (! f->async_visible) return; 1352 if (!FRAME_VISIBLE_P (f))
1358#ifndef NEW_STYLE_FS 1353 return;
1359 if (f->want_fullscreen == FULLSCREEN_BOTH) 1354
1355 if (! [view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH)
1360 { 1356 {
1361 /* Old style fs don't initiate correctly if created from 1357 /* Old style fs don't initiate correctly if created from
1362 init/default-frame alist, so use a timer (not nice...). 1358 init/default-frame alist, so use a timer (not nice...).
@@ -1366,7 +1362,6 @@ ns_fullscreen_hook (FRAME_PTR f)
1366 userInfo: nil repeats: NO]; 1362 userInfo: nil repeats: NO];
1367 return; 1363 return;
1368 } 1364 }
1369#endif
1370 1365
1371 block_input (); 1366 block_input ();
1372 [view handleFS]; 1367 [view handleFS];
@@ -3369,6 +3364,30 @@ ns_send_appdefined (int value)
3369 } 3364 }
3370} 3365}
3371 3366
3367#ifdef HAVE_NATIVE_FS
3368static void
3369check_native_fs ()
3370{
3371 Lisp_Object frame, tail;
3372
3373 if (ns_last_use_native_fullscreen == ns_use_native_fullscreen)
3374 return;
3375
3376 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
3377
3378 /* Clear the mouse-moved flag for every frame on this display. */
3379 FOR_EACH_FRAME (tail, frame)
3380 {
3381 struct frame *f = XFRAME (frame);
3382 if (FRAME_NS_P (f))
3383 {
3384 EmacsView *view = FRAME_NS_VIEW (f);
3385 [view updateCollectionBehaviour];
3386 }
3387 }
3388}
3389#endif
3390
3372static int 3391static int
3373ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) 3392ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3374/* -------------------------------------------------------------------------- 3393/* --------------------------------------------------------------------------
@@ -3382,6 +3401,10 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3382 3401
3383/* NSTRACE (ns_read_socket); */ 3402/* NSTRACE (ns_read_socket); */
3384 3403
3404#ifdef HAVE_NATIVE_FS
3405 check_native_fs ();
3406#endif
3407
3385 if ([NSApp modalWindow] != nil) 3408 if ([NSApp modalWindow] != nil)
3386 return -1; 3409 return -1;
3387 3410
@@ -3459,6 +3482,10 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3459 3482
3460/* NSTRACE (ns_select); */ 3483/* NSTRACE (ns_select); */
3461 3484
3485#ifdef HAVE_NATIVE_FS
3486 check_native_fs ();
3487#endif
3488
3462 if (hold_event_q.nr > 0) 3489 if (hold_event_q.nr > 0)
3463 { 3490 {
3464 /* We already have events pending. */ 3491 /* We already have events pending. */
@@ -3677,7 +3704,7 @@ ns_set_vertical_scroll_bar (struct window *window,
3677 } 3704 }
3678 3705
3679 bar = [[EmacsScroller alloc] initFrame: r window: win]; 3706 bar = [[EmacsScroller alloc] initFrame: r window: win];
3680 wset_vertical_scroll_bar (window, make_save_value (bar, 0)); 3707 wset_vertical_scroll_bar (window, make_save_pointer (bar));
3681 } 3708 }
3682 else 3709 else
3683 { 3710 {
@@ -4238,11 +4265,9 @@ ns_term_init (Lisp_Object display_name)
4238 NSColorPboardType, 4265 NSColorPboardType,
4239 NSFontPboardType, nil] retain]; 4266 NSFontPboardType, nil] retain];
4240 4267
4241#ifndef NEW_STYLE_FS
4242 /* If fullscreen is in init/default-frame-alist, focus isn't set 4268 /* If fullscreen is in init/default-frame-alist, focus isn't set
4243 right for fullscreen windows, so set this. */ 4269 right for fullscreen windows, so set this. */
4244 [NSApp activateIgnoringOtherApps:YES]; 4270 [NSApp activateIgnoringOtherApps:YES];
4245#endif
4246 4271
4247 [NSApp run]; 4272 [NSApp run];
4248 ns_do_open_file = YES; 4273 ns_do_open_file = YES;
@@ -5391,10 +5416,10 @@ not_in_argv (NSString *arg)
5391{ 5416{
5392 NSWindow *window = [self window]; 5417 NSWindow *window = [self window];
5393 NSRect wr = [window frame]; 5418 NSRect wr = [window frame];
5394#ifdef NS_IMPL_GNUSTEP
5395 int extra = 3;
5396#else
5397 int extra = 0; 5419 int extra = 0;
5420 int gsextra = 0;
5421#ifdef NS_IMPL_GNUSTEP
5422 gsextra = 3;
5398#endif 5423#endif
5399 5424
5400 int oldc = cols, oldr = rows; 5425 int oldc = cols, oldr = rows;
@@ -5402,23 +5427,24 @@ not_in_argv (NSString *arg)
5402 oldh = FRAME_PIXEL_HEIGHT (emacsframe); 5427 oldh = FRAME_PIXEL_HEIGHT (emacsframe);
5403 int neww, newh; 5428 int neww, newh;
5404 5429
5405 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + extra); 5430 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + gsextra);
5406 5431
5407 if (cols < MINWIDTH) 5432 if (cols < MINWIDTH)
5408 cols = MINWIDTH; 5433 cols = MINWIDTH;
5409 5434
5410 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES 5435 if (! [self isFullscreen])
5411 (emacsframe, wr.size.height 5436 {
5412 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + extra 5437 extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5413 - FRAME_TOOLBAR_HEIGHT (emacsframe)); 5438 + FRAME_TOOLBAR_HEIGHT (emacsframe) - gsextra;
5439 }
5440
5441 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, wr.size.height - extra);
5414 5442
5415 if (rows < MINHEIGHT) 5443 if (rows < MINHEIGHT)
5416 rows = MINHEIGHT; 5444 rows = MINHEIGHT;
5417 5445
5418 neww = (int)wr.size.width - emacsframe->border_width; 5446 neww = (int)wr.size.width - emacsframe->border_width;
5419 newh = ((int)wr.size.height 5447 newh = (int)wr.size.height - extra;
5420 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5421 - FRAME_TOOLBAR_HEIGHT (emacsframe));
5422 5448
5423 if (oldr != rows || oldc != cols || neww != oldw || newh != oldh) 5449 if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
5424 { 5450 {
@@ -5436,6 +5462,12 @@ not_in_argv (NSString *arg)
5436- (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize 5462- (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
5437/* normalize frame to gridded text size */ 5463/* normalize frame to gridded text size */
5438{ 5464{
5465 int extra = 0;
5466 int gsextra = 0;
5467#ifdef NS_IMPL_GNUSTEP
5468 gsextra = 3;
5469#endif
5470
5439 NSTRACE (windowWillResize); 5471 NSTRACE (windowWillResize);
5440/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */ 5472/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
5441 5473
@@ -5453,22 +5485,12 @@ not_in_argv (NSString *arg)
5453 maximized_width = maximized_height = -1; 5485 maximized_width = maximized_height = -1;
5454 5486
5455 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, 5487 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
5456#ifdef NS_IMPL_GNUSTEP 5488 frameSize.width + gsextra);
5457 frameSize.width + 3);
5458#else
5459 frameSize.width);
5460#endif
5461 if (cols < MINWIDTH) 5489 if (cols < MINWIDTH)
5462 cols = MINWIDTH; 5490 cols = MINWIDTH;
5463 5491
5464 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, frameSize.height 5492 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe,
5465#ifdef NS_IMPL_GNUSTEP 5493 frameSize.height - extra);
5466 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + 3
5467 - FRAME_TOOLBAR_HEIGHT (emacsframe));
5468#else
5469 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5470 - FRAME_TOOLBAR_HEIGHT (emacsframe));
5471#endif
5472 if (rows < MINHEIGHT) 5494 if (rows < MINHEIGHT)
5473 rows = MINHEIGHT; 5495 rows = MINHEIGHT;
5474#ifdef NS_IMPL_COCOA 5496#ifdef NS_IMPL_COCOA
@@ -5511,12 +5533,13 @@ not_in_argv (NSString *arg)
5511 5533
5512- (void)windowDidResize: (NSNotification *)notification 5534- (void)windowDidResize: (NSNotification *)notification
5513{ 5535{
5514 5536 if (! [self fsIsNative])
5515#if !defined (NEW_STYLE_FS) && ! defined (NS_IMPL_GNUSTEP) 5537 {
5516 NSWindow *theWindow = [notification object]; 5538 NSWindow *theWindow = [notification object];
5517 /* We can get notification on the non-FS window when in fullscreen mode. */ 5539 /* We can get notification on the non-FS window when in
5518 if ([self window] != theWindow) return; 5540 fullscreen mode. */
5519#endif 5541 if ([self window] != theWindow) return;
5542 }
5520 5543
5521#ifdef NS_IMPL_GNUSTEP 5544#ifdef NS_IMPL_GNUSTEP
5522 NSWindow *theWindow = [notification object]; 5545 NSWindow *theWindow = [notification object];
@@ -5632,6 +5655,11 @@ not_in_argv (NSString *arg)
5632 scrollbarsNeedingUpdate = 0; 5655 scrollbarsNeedingUpdate = 0;
5633 fs_state = FULLSCREEN_NONE; 5656 fs_state = FULLSCREEN_NONE;
5634 fs_before_fs = next_maximized = -1; 5657 fs_before_fs = next_maximized = -1;
5658#ifdef HAVE_NATIVE_FS
5659 fs_is_native = ns_use_native_fullscreen;
5660#else
5661 fs_is_native = NO;
5662#endif
5635 maximized_width = maximized_height = -1; 5663 maximized_width = maximized_height = -1;
5636 nonfs_window = nil; 5664 nonfs_window = nil;
5637 5665
@@ -5658,7 +5686,7 @@ not_in_argv (NSString *arg)
5658 backing: NSBackingStoreBuffered 5686 backing: NSBackingStoreBuffered
5659 defer: YES]; 5687 defer: YES];
5660 5688
5661#ifdef NEW_STYLE_FS 5689#ifdef HAVE_NATIVE_FS
5662 [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; 5690 [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
5663#endif 5691#endif
5664 5692
@@ -5824,13 +5852,14 @@ not_in_argv (NSString *arg)
5824 NSTRACE (windowDidDeminiaturize); 5852 NSTRACE (windowDidDeminiaturize);
5825 if (!emacsframe->output_data.ns) 5853 if (!emacsframe->output_data.ns)
5826 return; 5854 return;
5827 emacsframe->async_iconified = 0; 5855
5828 emacsframe->async_visible = 1; 5856 SET_FRAME_ICONIFIED (emacsframe, 0);
5857 SET_FRAME_VISIBLE (emacsframe, 1);
5829 windows_or_buffers_changed++; 5858 windows_or_buffers_changed++;
5830 5859
5831 if (emacs_event) 5860 if (emacs_event)
5832 { 5861 {
5833 emacs_event->kind = ICONIFY_EVENT; 5862 emacs_event->kind = DEICONIFY_EVENT;
5834 EV_TRAILER ((id)nil); 5863 EV_TRAILER ((id)nil);
5835 } 5864 }
5836} 5865}
@@ -5841,7 +5870,8 @@ not_in_argv (NSString *arg)
5841 NSTRACE (windowDidExpose); 5870 NSTRACE (windowDidExpose);
5842 if (!emacsframe->output_data.ns) 5871 if (!emacsframe->output_data.ns)
5843 return; 5872 return;
5844 emacsframe->async_visible = 1; 5873
5874 SET_FRAME_VISIBLE (emacsframe, 1);
5845 SET_FRAME_GARBAGED (emacsframe); 5875 SET_FRAME_GARBAGED (emacsframe);
5846 5876
5847 if (send_appdefined) 5877 if (send_appdefined)
@@ -5855,8 +5885,8 @@ not_in_argv (NSString *arg)
5855 if (!emacsframe->output_data.ns) 5885 if (!emacsframe->output_data.ns)
5856 return; 5886 return;
5857 5887
5858 emacsframe->async_iconified = 1; 5888 SET_FRAME_ICONIFIED (emacsframe, 1);
5859 emacsframe->async_visible = 0; 5889 SET_FRAME_VISIBLE (emacsframe, 0);
5860 5890
5861 if (emacs_event) 5891 if (emacs_event)
5862 { 5892 {
@@ -5865,6 +5895,15 @@ not_in_argv (NSString *arg)
5865 } 5895 }
5866} 5896}
5867 5897
5898#ifdef HAVE_NATIVE_FS
5899- (NSApplicationPresentationOptions)window:(NSWindow *)window
5900 willUseFullScreenPresentationOptions:
5901 (NSApplicationPresentationOptions)proposedOptions
5902{
5903 return proposedOptions|NSApplicationPresentationAutoHideToolbar;
5904}
5905#endif
5906
5868- (void)windowWillEnterFullScreen:(NSNotification *)notification 5907- (void)windowWillEnterFullScreen:(NSNotification *)notification
5869{ 5908{
5870 fs_before_fs = fs_state; 5909 fs_before_fs = fs_state;
@@ -5873,17 +5912,13 @@ not_in_argv (NSString *arg)
5873- (void)windowDidEnterFullScreen:(NSNotification *)notification 5912- (void)windowDidEnterFullScreen:(NSNotification *)notification
5874{ 5913{
5875 [self setFSValue: FULLSCREEN_BOTH]; 5914 [self setFSValue: FULLSCREEN_BOTH];
5876#ifdef NEW_STYLE_FS 5915 if (! [self fsIsNative])
5877 // Fix bad background.
5878 if ([toolbar isVisible])
5879 { 5916 {
5880 [toolbar setVisible:NO]; 5917 [self windowDidBecomeKey:notification];
5881 [toolbar setVisible:YES]; 5918 [nonfs_window orderOut:self];
5882 } 5919 }
5883#else 5920 else if (! FRAME_EXTERNAL_TOOL_BAR (emacsframe))
5884 [self windowDidBecomeKey:notification]; 5921 [toolbar setVisible:NO];
5885 [nonfs_window orderOut:self];
5886#endif
5887} 5922}
5888 5923
5889- (void)windowWillExitFullScreen:(NSNotification *)notification 5924- (void)windowWillExitFullScreen:(NSNotification *)notification
@@ -5896,24 +5931,76 @@ not_in_argv (NSString *arg)
5896{ 5931{
5897 [self setFSValue: fs_before_fs]; 5932 [self setFSValue: fs_before_fs];
5898 fs_before_fs = -1; 5933 fs_before_fs = -1;
5934 [self updateCollectionBehaviour];
5935 if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
5936 {
5937 [toolbar setVisible:YES];
5938 update_frame_tool_bar (emacsframe);
5939 [self updateFrameSize:YES];
5940 [[self window] display];
5941 }
5942 else
5943 [toolbar setVisible:NO];
5944
5899 if (next_maximized != -1) 5945 if (next_maximized != -1)
5900 [[self window] performZoom:self]; 5946 [[self window] performZoom:self];
5901} 5947}
5902 5948
5903- (void)toggleFullScreen: (id)sender 5949- (BOOL)fsIsNative
5950{
5951 return fs_is_native;
5952}
5953
5954- (BOOL)isFullscreen
5904{ 5955{
5905#ifdef NEW_STYLE_FS 5956 if (! fs_is_native) return nonfs_window != nil;
5906 [[self window] toggleFullScreen:sender]; 5957#ifdef HAVE_NATIVE_FS
5958 return ([[self window] styleMask] & NSFullScreenWindowMask) != 0;
5907#else 5959#else
5908 NSWindow *w = [self window], *fw; 5960 return NO;
5909 BOOL onFirstScreen = [[w screen] 5961#endif
5910 isEqual:[[NSScreen screens] objectAtIndex:0]]; 5962}
5911 struct frame *f = emacsframe; 5963
5964#ifdef HAVE_NATIVE_FS
5965- (void)updateCollectionBehaviour
5966{
5967 if (! [self isFullscreen])
5968 {
5969 NSWindow *win = [self window];
5970 NSWindowCollectionBehavior b = [win collectionBehavior];
5971 if (ns_use_native_fullscreen)
5972 b |= NSWindowCollectionBehaviorFullScreenPrimary;
5973 else
5974 b &= ~NSWindowCollectionBehaviorFullScreenPrimary;
5975
5976 [win setCollectionBehavior: b];
5977 fs_is_native = ns_use_native_fullscreen;
5978 }
5979}
5980#endif
5981
5982- (void)toggleFullScreen: (id)sender
5983{
5984 NSWindow *w, *fw;
5985 BOOL onFirstScreen;
5986 struct frame *f;
5912 NSSize sz; 5987 NSSize sz;
5913 NSRect r, wr = [w frame]; 5988 NSRect r, wr;
5914 NSColor *col = ns_lookup_indexed_color (NS_FACE_BACKGROUND 5989 NSColor *col;
5915 (FRAME_DEFAULT_FACE (f)), 5990
5916 f); 5991 if (fs_is_native)
5992 {
5993 [[self window] toggleFullScreen:sender];
5994 return;
5995 }
5996
5997 w = [self window];
5998 onFirstScreen = [[w screen] isEqual:[[NSScreen screens] objectAtIndex:0]];
5999 f = emacsframe;
6000 wr = [w frame];
6001 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
6002 (FRAME_DEFAULT_FACE (f)),
6003 f);
5917 6004
5918 sz.width = FRAME_COLUMN_WIDTH (f); 6005 sz.width = FRAME_COLUMN_WIDTH (f);
5919 sz.height = FRAME_LINE_HEIGHT (f); 6006 sz.height = FRAME_LINE_HEIGHT (f);
@@ -5956,7 +6043,6 @@ not_in_argv (NSString *arg)
5956 FRAME_NS_TITLEBAR_HEIGHT (f) = 0; 6043 FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
5957 tobar_height = FRAME_TOOLBAR_HEIGHT (f); 6044 tobar_height = FRAME_TOOLBAR_HEIGHT (f);
5958 FRAME_TOOLBAR_HEIGHT (f) = 0; 6045 FRAME_TOOLBAR_HEIGHT (f) = 0;
5959 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
5960 6046
5961 nonfs_window = w; 6047 nonfs_window = w;
5962 6048
@@ -5993,17 +6079,16 @@ not_in_argv (NSString *arg)
5993 6079
5994 f->border_width = bwidth; 6080 f->border_width = bwidth;
5995 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height; 6081 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
5996 FRAME_TOOLBAR_HEIGHT (f) = tobar_height; 6082 if (FRAME_EXTERNAL_TOOL_BAR (f))
5997 if (tobar_height) 6083 FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
5998 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
5999 6084
6000 [self windowWillExitFullScreen:nil]; 6085 [self windowWillExitFullScreen:nil];
6001 [fw setFrame: [w frame] display:YES animate:YES]; 6086 [fw setFrame: [w frame] display:YES animate:YES];
6002 [fw close]; 6087 [fw close];
6003 [w makeKeyAndOrderFront:NSApp]; 6088 [w makeKeyAndOrderFront:NSApp];
6004 [self windowDidExitFullScreen:nil]; 6089 [self windowDidExitFullScreen:nil];
6090 [self updateFrameSize:YES];
6005 } 6091 }
6006#endif
6007} 6092}
6008 6093
6009- (void)handleFS 6094- (void)handleFS
@@ -7157,6 +7242,18 @@ allowing it to be used at a lower level for accented character entry.");
7157Only works on OSX 10.6 or later. */); 7242Only works on OSX 10.6 or later. */);
7158 ns_auto_hide_menu_bar = Qnil; 7243 ns_auto_hide_menu_bar = Qnil;
7159 7244
7245 DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen,
7246 doc: /*Non-nil means to use native fullscreen on OSX >= 10.7.
7247Nil means use fullscreen the old (< 10.7) way. The old way works better with
7248multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7.
7249Default is t for OSX >= 10.7, nil otherwise. */);
7250#ifdef HAVE_NATIVE_FS
7251 ns_use_native_fullscreen = YES;
7252#else
7253 ns_use_native_fullscreen = NO;
7254#endif
7255 ns_last_use_native_fullscreen = ns_use_native_fullscreen;
7256
7160 /* TODO: move to common code */ 7257 /* TODO: move to common code */
7161 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, 7258 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
7162 doc: /* Which toolkit scroll bars Emacs uses, if any. 7259 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 @@
1/* This file is loaded before crt0.o on machines where we do not
2 remap part of the data space into text space in unexec.
3 On these machines, there is no problem with standard crt0.o's
4 that make environ an initialized variable. However, we do
5 need to make sure the label data_start exists anyway. */
6
7/* Create a label to appear at the beginning of data space. */
8
9int data_start = 0;
10
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;
84static void print_interval (INTERVAL interval, Lisp_Object printcharfun); 84static void print_interval (INTERVAL interval, Lisp_Object printcharfun);
85 85
86/* GDB resets this to zero on W32 to disable OutputDebugString calls. */ 86/* GDB resets this to zero on W32 to disable OutputDebugString calls. */
87int print_output_debug_flag EXTERNALLY_VISIBLE = 1; 87bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
88 88
89 89
90/* Low level output routines for characters and strings. */ 90/* Low level output routines for characters and strings. */
@@ -101,8 +101,9 @@ int print_output_debug_flag EXTERNALLY_VISIBLE = 1;
101 ptrdiff_t old_point = -1, start_point = -1; \ 101 ptrdiff_t old_point = -1, start_point = -1; \
102 ptrdiff_t old_point_byte = -1, start_point_byte = -1; \ 102 ptrdiff_t old_point_byte = -1, start_point_byte = -1; \
103 ptrdiff_t specpdl_count = SPECPDL_INDEX (); \ 103 ptrdiff_t specpdl_count = SPECPDL_INDEX (); \
104 int free_print_buffer = 0; \ 104 bool free_print_buffer = 0; \
105 int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \ 105 bool multibyte \
106 = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \
106 Lisp_Object original 107 Lisp_Object original
107 108
108#define PRINTPREPARE \ 109#define PRINTPREPARE \
@@ -240,7 +241,7 @@ printchar (unsigned int ch, Lisp_Object fun)
240 } 241 }
241 else 242 else
242 { 243 {
243 int multibyte_p 244 bool multibyte_p
244 = !NILP (BVAR (current_buffer, enable_multibyte_characters)); 245 = !NILP (BVAR (current_buffer, enable_multibyte_characters));
245 246
246 setup_echo_area_for_printing (multibyte_p); 247 setup_echo_area_for_printing (multibyte_p);
@@ -289,7 +290,7 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
289 here, that's the reason we don't call printchar to do the 290 here, that's the reason we don't call printchar to do the
290 job. */ 291 job. */
291 int i; 292 int i;
292 int multibyte_p 293 bool multibyte_p
293 = !NILP (BVAR (current_buffer, enable_multibyte_characters)); 294 = !NILP (BVAR (current_buffer, enable_multibyte_characters));
294 295
295 setup_echo_area_for_printing (multibyte_p); 296 setup_echo_area_for_printing (multibyte_p);
@@ -507,10 +508,10 @@ temp_output_buffer_setup (const char *bufname)
507 specbind (Qstandard_output, buf); 508 specbind (Qstandard_output, buf);
508} 509}
509 510
510static void print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag); 511static void print (Lisp_Object, Lisp_Object, bool);
511static void print_preprocess (Lisp_Object obj); 512static void print_preprocess (Lisp_Object);
512static void print_preprocess_string (INTERVAL interval, Lisp_Object arg); 513static void print_preprocess_string (INTERVAL, Lisp_Object);
513static void print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag); 514static void print_object (Lisp_Object, Lisp_Object, bool);
514 515
515DEFUN ("terpri", Fterpri, Sterpri, 0, 1, 0, 516DEFUN ("terpri", Fterpri, Sterpri, 0, 1, 0,
516 doc: /* Output a newline to stream PRINTCHARFUN. 517 doc: /* Output a newline to stream PRINTCHARFUN.
@@ -726,9 +727,9 @@ to make it write to the debugging output. */)
726/* This function is never called. Its purpose is to prevent 727/* This function is never called. Its purpose is to prevent
727 print_output_debug_flag from being optimized away. */ 728 print_output_debug_flag from being optimized away. */
728 729
729extern void debug_output_compilation_hack (int) EXTERNALLY_VISIBLE; 730extern void debug_output_compilation_hack (bool) EXTERNALLY_VISIBLE;
730void 731void
731debug_output_compilation_hack (int x) 732debug_output_compilation_hack (bool x)
732{ 733{
733 print_output_debug_flag = x; 734 print_output_debug_flag = x;
734} 735}
@@ -966,7 +967,7 @@ float_to_string (char *buf, double data)
966 static char const NaN_string[] = "0.0e+NaN"; 967 static char const NaN_string[] = "0.0e+NaN";
967 int i; 968 int i;
968 union { double d; char c[sizeof (double)]; } u_data, u_minus_zero; 969 union { double d; char c[sizeof (double)]; } u_data, u_minus_zero;
969 int negative = 0; 970 bool negative = 0;
970 u_data.d = data; 971 u_data.d = data;
971 u_minus_zero.d = - 0.0; 972 u_minus_zero.d = - 0.0;
972 for (i = 0; i < sizeof (double); i++) 973 for (i = 0; i < sizeof (double); i++)
@@ -1063,7 +1064,7 @@ float_to_string (char *buf, double data)
1063 1064
1064 1065
1065static void 1066static void
1066print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag) 1067print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1067{ 1068{
1068 new_backquote_output = 0; 1069 new_backquote_output = 0;
1069 1070
@@ -1313,7 +1314,7 @@ print_prune_string_charset (Lisp_Object string)
1313} 1314}
1314 1315
1315static void 1316static void
1316print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag) 1317print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1317{ 1318{
1318 char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), 1319 char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT),
1319 max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), 1320 max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t),
@@ -1395,8 +1396,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
1395 ptrdiff_t size_byte; 1396 ptrdiff_t size_byte;
1396 /* 1 means we must ensure that the next character we output 1397 /* 1 means we must ensure that the next character we output
1397 cannot be taken as part of a hex character escape. */ 1398 cannot be taken as part of a hex character escape. */
1398 int need_nonhex = 0; 1399 bool need_nonhex = 0;
1399 int multibyte = STRING_MULTIBYTE (obj); 1400 bool multibyte = STRING_MULTIBYTE (obj);
1400 1401
1401 GCPRO1 (obj); 1402 GCPRO1 (obj);
1402 1403
@@ -1507,10 +1508,10 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
1507 1508
1508 case Lisp_Symbol: 1509 case Lisp_Symbol:
1509 { 1510 {
1510 register int confusing; 1511 bool confusing;
1511 register unsigned char *p = SDATA (SYMBOL_NAME (obj)); 1512 unsigned char *p = SDATA (SYMBOL_NAME (obj));
1512 register unsigned char *end = p + SBYTES (SYMBOL_NAME (obj)); 1513 unsigned char *end = p + SBYTES (SYMBOL_NAME (obj));
1513 register int c; 1514 int c;
1514 ptrdiff_t i, i_byte; 1515 ptrdiff_t i, i_byte;
1515 ptrdiff_t size_byte; 1516 ptrdiff_t size_byte;
1516 Lisp_Object name; 1517 Lisp_Object name;
@@ -1766,7 +1767,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
1766 { 1767 {
1767 int len; 1768 int len;
1768 strout ("#<window ", -1, -1, printcharfun); 1769 strout ("#<window ", -1, -1, printcharfun);
1769 len = sprintf (buf, "%d", XWINDOW (obj)->sequence_number); 1770 len = sprintf (buf, "%p", XWINDOW (obj));
1770 strout (buf, len, len, printcharfun); 1771 strout (buf, len, len, printcharfun);
1771 if (!NILP (XWINDOW (obj)->buffer)) 1772 if (!NILP (XWINDOW (obj)->buffer))
1772 { 1773 {
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;
146Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime; 146Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
147Lisp_Object QCname, QCtype; 147Lisp_Object QCname, QCtype;
148 148
149/* Non-zero if keyboard input is on hold, zero otherwise. */ 149/* True if keyboard input is on hold, zero otherwise. */
150 150
151static int kbd_is_on_hold; 151static bool kbd_is_on_hold;
152 152
153/* Nonzero means don't run process sentinels. This is used 153/* Nonzero means don't run process sentinels. This is used
154 when exiting. */ 154 when exiting. */
155int inhibit_sentinels; 155bool inhibit_sentinels;
156 156
157#ifdef subprocesses 157#ifdef subprocesses
158 158
@@ -180,10 +180,6 @@ static Lisp_Object Qlast_nonmenu_event;
180#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial)) 180#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
181#define SERIALCONN1_P(p) (EQ (p->type, Qserial)) 181#define SERIALCONN1_P(p) (EQ (p->type, Qserial))
182 182
183#ifndef HAVE_H_ERRNO
184extern int h_errno;
185#endif
186
187/* Number of events of change of status of a process. */ 183/* Number of events of change of status of a process. */
188static EMACS_INT process_tick; 184static EMACS_INT process_tick;
189/* Number of events for which the user or sentinel has been notified. */ 185/* Number of events for which the user or sentinel has been notified. */
@@ -238,9 +234,9 @@ static EMACS_INT update_tick;
238 234
239static int process_output_delay_count; 235static int process_output_delay_count;
240 236
241/* Non-zero if any process has non-nil read_output_skip. */ 237/* True if any process has non-nil read_output_skip. */
242 238
243static int process_output_skip; 239static bool process_output_skip;
244 240
245#else 241#else
246#define process_output_delay_count 0 242#define process_output_delay_count 0
@@ -248,7 +244,7 @@ static int process_output_skip;
248 244
249static void create_process (Lisp_Object, char **, Lisp_Object); 245static void create_process (Lisp_Object, char **, Lisp_Object);
250#ifdef USABLE_SIGIO 246#ifdef USABLE_SIGIO
251static int keyboard_bit_set (SELECT_TYPE *); 247static bool keyboard_bit_set (SELECT_TYPE *);
252#endif 248#endif
253static void deactivate_process (Lisp_Object); 249static void deactivate_process (Lisp_Object);
254static void status_notify (struct Lisp_Process *); 250static void status_notify (struct Lisp_Process *);
@@ -670,7 +666,7 @@ status_convert (int w)
670 and store them individually through the three pointers. */ 666 and store them individually through the three pointers. */
671 667
672static void 668static void
673decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, int *coredump) 669decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, bool *coredump)
674{ 670{
675 Lisp_Object tem; 671 Lisp_Object tem;
676 672
@@ -697,7 +693,8 @@ status_message (struct Lisp_Process *p)
697{ 693{
698 Lisp_Object status = p->status; 694 Lisp_Object status = p->status;
699 Lisp_Object symbol; 695 Lisp_Object symbol;
700 int code, coredump; 696 int code;
697 bool coredump;
701 Lisp_Object string, string2; 698 Lisp_Object string, string2;
702 699
703 decode_status (status, &symbol, &code, &coredump); 700 decode_status (status, &symbol, &code, &coredump);
@@ -1774,7 +1771,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1774 sigset_t blocked; 1771 sigset_t blocked;
1775 /* Use volatile to protect variables from being clobbered by vfork. */ 1772 /* Use volatile to protect variables from being clobbered by vfork. */
1776 volatile int forkin, forkout; 1773 volatile int forkin, forkout;
1777 volatile int pty_flag = 0; 1774 volatile bool pty_flag = 0;
1778 volatile Lisp_Object lisp_pty_name = Qnil; 1775 volatile Lisp_Object lisp_pty_name = Qnil;
1779 volatile Lisp_Object encoded_current_dir; 1776 volatile Lisp_Object encoded_current_dir;
1780 1777
@@ -2063,7 +2060,7 @@ void
2063create_pty (Lisp_Object process) 2060create_pty (Lisp_Object process)
2064{ 2061{
2065 int inchannel, outchannel; 2062 int inchannel, outchannel;
2066 int pty_flag = 0; 2063 bool pty_flag = 0;
2067 2064
2068 inchannel = outchannel = -1; 2065 inchannel = outchannel = -1;
2069 2066
@@ -3005,8 +3002,9 @@ usage: (make-network-process &rest ARGS) */)
3005 Lisp_Object tem; 3002 Lisp_Object tem;
3006 Lisp_Object name, buffer, host, service, address; 3003 Lisp_Object name, buffer, host, service, address;
3007 Lisp_Object filter, sentinel; 3004 Lisp_Object filter, sentinel;
3008 int is_non_blocking_client = 0; 3005 bool is_non_blocking_client = 0;
3009 int is_server = 0, backlog = 5; 3006 bool is_server = 0;
3007 int backlog = 5;
3010 int socktype; 3008 int socktype;
3011 int family = -1; 3009 int family = -1;
3012 3010
@@ -3676,7 +3674,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
3676 struct ifreq *ifreq; 3674 struct ifreq *ifreq;
3677 void *buf = NULL; 3675 void *buf = NULL;
3678 ptrdiff_t buf_size = 512; 3676 ptrdiff_t buf_size = 512;
3679 int s, i; 3677 int s;
3680 Lisp_Object res; 3678 Lisp_Object res;
3681 3679
3682 s = socket (AF_INET, SOCK_STREAM, 0); 3680 s = socket (AF_INET, SOCK_STREAM, 0);
@@ -3714,7 +3712,6 @@ format; see the description of ADDRESS in `make-network-process'. */)
3714 int len = sizeof (*ifreq); 3712 int len = sizeof (*ifreq);
3715#endif 3713#endif
3716 char namebuf[sizeof (ifq->ifr_name) + 1]; 3714 char namebuf[sizeof (ifq->ifr_name) + 1];
3717 i += len;
3718 ifreq = (struct ifreq *) ((char *) ifreq + len); 3715 ifreq = (struct ifreq *) ((char *) ifreq + len);
3719 3716
3720 if (ifq->ifr_addr.sa_family != AF_INET) 3717 if (ifq->ifr_addr.sa_family != AF_INET)
@@ -3824,7 +3821,7 @@ FLAGS is the current flags of the interface. */)
3824 Lisp_Object res = Qnil; 3821 Lisp_Object res = Qnil;
3825 Lisp_Object elt; 3822 Lisp_Object elt;
3826 int s; 3823 int s;
3827 int any = 0; 3824 bool any = 0;
3828#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \ 3825#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
3829 && defined HAVE_GETIFADDRS && defined LLADDR) 3826 && defined HAVE_GETIFADDRS && defined LLADDR)
3830 struct ifaddrs *ifap; 3827 struct ifaddrs *ifap;
@@ -4114,7 +4111,7 @@ Return non-nil if we received any output before the timeout expired. */)
4114 4111
4115/* Accept a connection for server process SERVER on CHANNEL. */ 4112/* Accept a connection for server process SERVER on CHANNEL. */
4116 4113
4117static int connect_counter = 0; 4114static EMACS_INT connect_counter = 0;
4118 4115
4119static void 4116static void
4120server_accept_connection (Lisp_Object server, int channel) 4117server_accept_connection (Lisp_Object server, int channel)
@@ -4353,7 +4350,7 @@ wait_reading_process_output_1 (void)
4353 process. The return value is true if we read some input from 4350 process. The return value is true if we read some input from
4354 that process. 4351 that process.
4355 4352
4356 If JUST_WAIT_PROC is non-nil, handle only output from WAIT_PROC 4353 If JUST_WAIT_PROC is nonzero, handle only output from WAIT_PROC
4357 (suspending output from other processes). A negative value 4354 (suspending output from other processes). A negative value
4358 means don't run any timers either. 4355 means don't run any timers either.
4359 4356
@@ -4361,22 +4358,23 @@ wait_reading_process_output_1 (void)
4361 received input from that process before the timeout elapsed. 4358 received input from that process before the timeout elapsed.
4362 Otherwise, return true if we received input from any process. */ 4359 Otherwise, return true if we received input from any process. */
4363 4360
4364int 4361bool
4365wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, 4362wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4366 bool do_display, 4363 bool do_display,
4367 Lisp_Object wait_for_cell, 4364 Lisp_Object wait_for_cell,
4368 struct Lisp_Process *wait_proc, int just_wait_proc) 4365 struct Lisp_Process *wait_proc, int just_wait_proc)
4369{ 4366{
4370 register int channel, nfds; 4367 int channel, nfds;
4371 SELECT_TYPE Available; 4368 SELECT_TYPE Available;
4372 SELECT_TYPE Writeok; 4369 SELECT_TYPE Writeok;
4373 int check_write; 4370 bool check_write;
4374 int check_delay, no_avail; 4371 int check_delay;
4372 bool no_avail;
4375 int xerrno; 4373 int xerrno;
4376 Lisp_Object proc; 4374 Lisp_Object proc;
4377 EMACS_TIME timeout, end_time; 4375 EMACS_TIME timeout, end_time;
4378 int wait_channel = -1; 4376 int wait_channel = -1;
4379 int got_some_input = 0; 4377 bool got_some_input = 0;
4380 ptrdiff_t count = SPECPDL_INDEX (); 4378 ptrdiff_t count = SPECPDL_INDEX ();
4381 4379
4382 eassert (wait_proc == NULL 4380 eassert (wait_proc == NULL
@@ -4389,7 +4387,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4389 if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit) 4387 if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
4390 && !(CONSP (wait_proc->status) 4388 && !(CONSP (wait_proc->status)
4391 && EQ (XCAR (wait_proc->status), Qexit))) 4389 && EQ (XCAR (wait_proc->status), Qexit)))
4392 message ("Blocking call to accept-process-output with quit inhibited!!"); 4390 message1 ("Blocking call to accept-process-output with quit inhibited!!");
4393 4391
4394 /* If wait_proc is a process to watch, set wait_channel accordingly. */ 4392 /* If wait_proc is a process to watch, set wait_channel accordingly. */
4395 if (wait_proc != NULL) 4393 if (wait_proc != NULL)
@@ -4417,7 +4415,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4417 4415
4418 while (1) 4416 while (1)
4419 { 4417 {
4420 int timeout_reduced_for_timers = 0; 4418 bool timeout_reduced_for_timers = 0;
4421 4419
4422 /* If calling from keyboard input, do not quit 4420 /* If calling from keyboard input, do not quit
4423 since we want to return C-g as an input character. 4421 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,
4796 unsigned old_timers_run = timers_run; 4794 unsigned old_timers_run = timers_run;
4797 struct buffer *old_buffer = current_buffer; 4795 struct buffer *old_buffer = current_buffer;
4798 Lisp_Object old_window = selected_window; 4796 Lisp_Object old_window = selected_window;
4799 int leave = 0; 4797 bool leave = 0;
4800 4798
4801 if (detect_input_pending_run_timers (do_display)) 4799 if (detect_input_pending_run_timers (do_display))
4802 { 4800 {
@@ -5111,7 +5109,7 @@ read_process_output (Lisp_Object proc, register int channel)
5111 else 5109 else
5112#endif 5110#endif
5113 { 5111 {
5114 int buffered = 0 <= proc_buffered_char[channel]; 5112 bool buffered = 0 <= proc_buffered_char[channel];
5115 if (buffered) 5113 if (buffered)
5116 { 5114 {
5117 chars[carryover] = proc_buffered_char[channel]; 5115 chars[carryover] = proc_buffered_char[channel];
@@ -5427,7 +5425,7 @@ read_process_output (Lisp_Object proc, register int channel)
5427 5425
5428static void 5426static void
5429write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj, 5427write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
5430 const char *buf, ptrdiff_t len, int front) 5428 const char *buf, ptrdiff_t len, bool front)
5431{ 5429{
5432 ptrdiff_t offset; 5430 ptrdiff_t offset;
5433 Lisp_Object entry, obj; 5431 Lisp_Object entry, obj;
@@ -5452,10 +5450,10 @@ write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
5452} 5450}
5453 5451
5454/* Remove the first element in the write_queue of process P, put its 5452/* Remove the first element in the write_queue of process P, put its
5455 contents in OBJ, BUF and LEN, and return non-zero. If the 5453 contents in OBJ, BUF and LEN, and return true. If the
5456 write_queue is empty, return zero. */ 5454 write_queue is empty, return false. */
5457 5455
5458static int 5456static bool
5459write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj, 5457write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
5460 const char **buf, ptrdiff_t *len) 5458 const char **buf, ptrdiff_t *len)
5461{ 5459{
@@ -5729,7 +5727,7 @@ Output from processes can arrive in between bunches. */)
5729 if (XINT (start) < GPT && XINT (end) > GPT) 5727 if (XINT (start) < GPT && XINT (end) > GPT)
5730 move_gap_both (XINT (start), start_byte); 5728 move_gap_both (XINT (start), start_byte);
5731 5729
5732 send_process (proc, (char *) BYTE_POS_ADDR (start_byte), 5730 send_process (proc, (char *) BYTE_POS_ADDR (start_byte),
5733 end_byte - start_byte, Fcurrent_buffer ()); 5731 end_byte - start_byte, Fcurrent_buffer ());
5734 5732
5735 return Qnil; 5733 return Qnil;
@@ -5816,7 +5814,7 @@ return t unconditionally. */)
5816 If CURRENT_GROUP is lambda, that means send to the process group 5814 If CURRENT_GROUP is lambda, that means send to the process group
5817 that currently owns the terminal, but only if it is NOT the shell itself. 5815 that currently owns the terminal, but only if it is NOT the shell itself.
5818 5816
5819 If NOMSG is zero, insert signal-announcements into process's buffers 5817 If NOMSG is false, insert signal-announcements into process's buffers
5820 right away. 5818 right away.
5821 5819
5822 If we can, we try to signal PROCESS by sending control characters 5820 If we can, we try to signal PROCESS by sending control characters
@@ -5825,12 +5823,12 @@ return t unconditionally. */)
5825 5823
5826static void 5824static void
5827process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, 5825process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
5828 int nomsg) 5826 bool nomsg)
5829{ 5827{
5830 Lisp_Object proc; 5828 Lisp_Object proc;
5831 register struct Lisp_Process *p; 5829 struct Lisp_Process *p;
5832 pid_t gid; 5830 pid_t gid;
5833 int no_pgrp = 0; 5831 bool no_pgrp = 0;
5834 5832
5835 proc = get_process (process); 5833 proc = get_process (process);
5836 p = XPROCESS (proc); 5834 p = XPROCESS (proc);
@@ -6323,7 +6321,7 @@ handle_child_signal (int sig)
6323 /* If process has terminated, stop waiting for its output. */ 6321 /* If process has terminated, stop waiting for its output. */
6324 if (WIFSIGNALED (status) || WIFEXITED (status)) 6322 if (WIFSIGNALED (status) || WIFEXITED (status))
6325 { 6323 {
6326 int clear_desc_flag = 0; 6324 bool clear_desc_flag = 0;
6327 p->alive = 0; 6325 p->alive = 0;
6328 if (p->infd >= 0) 6326 if (p->infd >= 0)
6329 clear_desc_flag = 1; 6327 clear_desc_flag = 1;
@@ -6663,10 +6661,10 @@ delete_gpm_wait_descriptor (int desc)
6663 6661
6664# ifdef USABLE_SIGIO 6662# ifdef USABLE_SIGIO
6665 6663
6666/* Return nonzero if *MASK has a bit set 6664/* Return true if *MASK has a bit set
6667 that corresponds to one of the keyboard input descriptors. */ 6665 that corresponds to one of the keyboard input descriptors. */
6668 6666
6669static int 6667static bool
6670keyboard_bit_set (fd_set *mask) 6668keyboard_bit_set (fd_set *mask)
6671{ 6669{
6672 int fd; 6670 int fd;
@@ -6716,7 +6714,7 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
6716 6714
6717 Return true if we received input from any process. */ 6715 Return true if we received input from any process. */
6718 6716
6719int 6717bool
6720wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, 6718wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
6721 bool do_display, 6719 bool do_display,
6722 Lisp_Object wait_for_cell, 6720 Lisp_Object wait_for_cell,
@@ -6748,7 +6746,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
6748 6746
6749 while (1) 6747 while (1)
6750 { 6748 {
6751 int timeout_reduced_for_timers = 0; 6749 bool timeout_reduced_for_timers = 0;
6752 SELECT_TYPE waitchannels; 6750 SELECT_TYPE waitchannels;
6753 int xerrno; 6751 int xerrno;
6754 6752
@@ -7105,9 +7103,9 @@ unhold_keyboard_input (void)
7105 kbd_is_on_hold = 0; 7103 kbd_is_on_hold = 0;
7106} 7104}
7107 7105
7108/* Return non-zero if keyboard input is on hold, zero otherwise. */ 7106/* Return true if keyboard input is on hold, zero otherwise. */
7109 7107
7110int 7108bool
7111kbd_on_hold_p (void) 7109kbd_on_hold_p (void)
7112{ 7110{
7113 return kbd_is_on_hold; 7111 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
162 gnutls_anon_client_credentials_t gnutls_anon_cred; 162 gnutls_anon_client_credentials_t gnutls_anon_cred;
163 int gnutls_log_level; 163 int gnutls_log_level;
164 int gnutls_handshakes_tried; 164 int gnutls_handshakes_tried;
165 int gnutls_p; 165 unsigned int gnutls_p : 1;
166#endif 166#endif
167}; 167};
168 168
@@ -188,9 +188,9 @@ pset_gnutls_cred_type (struct Lisp_Process *p, Lisp_Object val)
188} 188}
189#endif 189#endif
190 190
191/* Nonzero means don't run process sentinels. This is used 191/* True means don't run process sentinels. This is used
192 when exiting. */ 192 when exiting. */
193extern int inhibit_sentinels; 193extern bool inhibit_sentinels;
194 194
195extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname; 195extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname;
196extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime; 196extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime;
@@ -212,7 +212,7 @@ extern Lisp_Object system_process_attributes (Lisp_Object);
212 212
213extern void hold_keyboard_input (void); 213extern void hold_keyboard_input (void);
214extern void unhold_keyboard_input (void); 214extern void unhold_keyboard_input (void);
215extern int kbd_on_hold_p (void); 215extern bool kbd_on_hold_p (void);
216 216
217typedef void (*fd_callback) (int fd, void *data); 217typedef void (*fd_callback) (int fd, void *data);
218 218
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)
560 ? XHASH (XCDR (XCDR (f))) : XHASH (f)); 560 ? XHASH (XCDR (XCDR (f))) : XHASH (f));
561 hash = sxhash_combine (hash, hash1); 561 hash = sxhash_combine (hash, hash1);
562 } 562 }
563 return (hash & INTMASK); 563 return SXHASH_REDUCE (hash);
564 } 564 }
565 else 565 else
566 return XHASH (bt); 566 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;
52 52
53#include "getpagesize.h" 53#include "getpagesize.h"
54 54
55typedef size_t SIZE;
56typedef void *POINTER;
57#define NIL ((POINTER) 0)
58
59/* A flag to indicate whether we have initialized ralloc yet. For 55/* A flag to indicate whether we have initialized ralloc yet. For
60 Emacs's sake, please do not make this local to malloc_init; on some 56 Emacs's sake, please do not make this local to malloc_init; on some
61 machines, the dumping procedure makes all static variables 57 machines, the dumping procedure makes all static variables
@@ -72,14 +68,14 @@ static void r_alloc_init (void);
72/* Declarations for working with the malloc, ralloc, and system breaks. */ 68/* Declarations for working with the malloc, ralloc, and system breaks. */
73 69
74/* Function to set the real break value. */ 70/* Function to set the real break value. */
75POINTER (*real_morecore) (ptrdiff_t); 71void *(*real_morecore) (ptrdiff_t);
76 72
77/* The break value, as seen by malloc. */ 73/* The break value, as seen by malloc. */
78static POINTER virtual_break_value; 74static void *virtual_break_value;
79 75
80/* The address of the end of the last data in use by ralloc, 76/* The address of the end of the last data in use by ralloc,
81 including relocatable blocs as well as malloc data. */ 77 including relocatable blocs as well as malloc data. */
82static POINTER break_value; 78static void *break_value;
83 79
84/* This is the size of a page. We round memory requests to this boundary. */ 80/* This is the size of a page. We round memory requests to this boundary. */
85static int page_size; 81static int page_size;
@@ -92,17 +88,17 @@ static int extra_bytes;
92 by changing the definition of PAGE. */ 88 by changing the definition of PAGE. */
93#define PAGE (getpagesize ()) 89#define PAGE (getpagesize ())
94#define ROUNDUP(size) (((size_t) (size) + page_size - 1) \ 90#define ROUNDUP(size) (((size_t) (size) + page_size - 1) \
95 & ~((size_t)(page_size - 1))) 91 & ~((size_t) (page_size - 1)))
96 92
97#define MEM_ALIGN sizeof (double) 93#define MEM_ALIGN sizeof (double)
98#define MEM_ROUNDUP(addr) (((size_t)(addr) + MEM_ALIGN - 1) \ 94#define MEM_ROUNDUP(addr) (((size_t) (addr) + MEM_ALIGN - 1) \
99 & ~(MEM_ALIGN - 1)) 95 & ~(MEM_ALIGN - 1))
100 96
101/* The hook `malloc' uses for the function which gets more space 97/* The hook `malloc' uses for the function which gets more space
102 from the system. */ 98 from the system. */
103 99
104#ifndef SYSTEM_MALLOC 100#ifndef SYSTEM_MALLOC
105extern POINTER (*__morecore) (ptrdiff_t); 101extern void *(*__morecore) (ptrdiff_t);
106#endif 102#endif
107 103
108 104
@@ -131,13 +127,13 @@ typedef struct heap
131 struct heap *next; 127 struct heap *next;
132 struct heap *prev; 128 struct heap *prev;
133 /* Start of memory range of this heap. */ 129 /* Start of memory range of this heap. */
134 POINTER start; 130 void *start;
135 /* End of memory range of this heap. */ 131 /* End of memory range of this heap. */
136 POINTER end; 132 void *end;
137 /* Start of relocatable data in this heap. */ 133 /* Start of relocatable data in this heap. */
138 POINTER bloc_start; 134 void *bloc_start;
139 /* Start of unused space in this heap. */ 135 /* Start of unused space in this heap. */
140 POINTER free; 136 void *free;
141 /* First bloc in this heap. */ 137 /* First bloc in this heap. */
142 struct bp *first_bloc; 138 struct bp *first_bloc;
143 /* Last bloc in this heap. */ 139 /* Last bloc in this heap. */
@@ -159,7 +155,7 @@ static heap_ptr first_heap, last_heap;
159 The data blocks abut each other; if b->next is non-nil, then 155 The data blocks abut each other; if b->next is non-nil, then
160 b->data + b->size == b->next->data. 156 b->data + b->size == b->next->data.
161 157
162 An element with variable==NIL denotes a freed block, which has not yet 158 An element with variable==NULL denotes a freed block, which has not yet
163 been collected. They may only appear while r_alloc_freeze_level > 0, 159 been collected. They may only appear while r_alloc_freeze_level > 0,
164 and will be freed when the arena is thawed. Currently, these blocs are 160 and will be freed when the arena is thawed. Currently, these blocs are
165 not reusable, while the arena is frozen. Very inefficient. */ 161 not reusable, while the arena is frozen. Very inefficient. */
@@ -168,10 +164,10 @@ typedef struct bp
168{ 164{
169 struct bp *next; 165 struct bp *next;
170 struct bp *prev; 166 struct bp *prev;
171 POINTER *variable; 167 void **variable;
172 POINTER data; 168 void *data;
173 SIZE size; 169 size_t size;
174 POINTER new_data; /* temporarily used for relocation */ 170 void *new_data; /* temporarily used for relocation */
175 struct heap *heap; /* Heap this bloc is in. */ 171 struct heap *heap; /* Heap this bloc is in. */
176} *bloc_ptr; 172} *bloc_ptr;
177 173
@@ -192,7 +188,7 @@ static int r_alloc_freeze_level;
192/* Find the heap that ADDRESS falls within. */ 188/* Find the heap that ADDRESS falls within. */
193 189
194static heap_ptr 190static heap_ptr
195find_heap (POINTER address) 191find_heap (void *address)
196{ 192{
197 heap_ptr heap; 193 heap_ptr heap;
198 194
@@ -223,11 +219,11 @@ find_heap (POINTER address)
223 Return the address of the space if all went well, or zero if we couldn't 219 Return the address of the space if all went well, or zero if we couldn't
224 allocate the memory. */ 220 allocate the memory. */
225 221
226static POINTER 222static void *
227obtain (POINTER address, SIZE size) 223obtain (void *address, size_t size)
228{ 224{
229 heap_ptr heap; 225 heap_ptr heap;
230 SIZE already_available; 226 size_t already_available;
231 227
232 /* Find the heap that ADDRESS falls within. */ 228 /* Find the heap that ADDRESS falls within. */
233 for (heap = last_heap; heap; heap = heap->prev) 229 for (heap = last_heap; heap; heap = heap->prev)
@@ -253,19 +249,19 @@ obtain (POINTER address, SIZE size)
253 get more space. */ 249 get more space. */
254 if (heap == NIL_HEAP) 250 if (heap == NIL_HEAP)
255 { 251 {
256 POINTER new = (*real_morecore)(0); 252 void *new = real_morecore (0);
257 SIZE get; 253 size_t get;
258 254
259 already_available = (char *)last_heap->end - (char *)address; 255 already_available = (char *) last_heap->end - (char *) address;
260 256
261 if (new != last_heap->end) 257 if (new != last_heap->end)
262 { 258 {
263 /* Someone else called sbrk. Make a new heap. */ 259 /* Someone else called sbrk. Make a new heap. */
264 260
265 heap_ptr new_heap = (heap_ptr) MEM_ROUNDUP (new); 261 heap_ptr new_heap = (heap_ptr) MEM_ROUNDUP (new);
266 POINTER bloc_start = (POINTER) MEM_ROUNDUP ((POINTER)(new_heap + 1)); 262 void *bloc_start = (void *) MEM_ROUNDUP ((void *) (new_heap + 1));
267 263
268 if ((*real_morecore) ((char *) bloc_start - (char *) new) != new) 264 if (real_morecore ((char *) bloc_start - (char *) new) != new)
269 return 0; 265 return 0;
270 266
271 new_heap->start = new; 267 new_heap->start = new;
@@ -287,10 +283,10 @@ obtain (POINTER address, SIZE size)
287 Get some extra, so we can come here less often. */ 283 Get some extra, so we can come here less often. */
288 284
289 get = size + extra_bytes - already_available; 285 get = size + extra_bytes - already_available;
290 get = (char *) ROUNDUP ((char *)last_heap->end + get) 286 get = (char *) ROUNDUP ((char *) last_heap->end + get)
291 - (char *) last_heap->end; 287 - (char *) last_heap->end;
292 288
293 if ((*real_morecore) (get) != last_heap->end) 289 if (real_morecore (get) != last_heap->end)
294 return 0; 290 return 0;
295 291
296 last_heap->end = (char *) last_heap->end + get; 292 last_heap->end = (char *) last_heap->end + get;
@@ -319,13 +315,13 @@ relinquish (void)
319 ? h->bloc_start : break_value); 315 ? h->bloc_start : break_value);
320 } 316 }
321 317
322 if (excess > extra_bytes * 2 && (*real_morecore) (0) == last_heap->end) 318 if (excess > extra_bytes * 2 && real_morecore (0) == last_heap->end)
323 { 319 {
324 /* Keep extra_bytes worth of empty space. 320 /* Keep extra_bytes worth of empty space.
325 And don't free anything unless we can free at least extra_bytes. */ 321 And don't free anything unless we can free at least extra_bytes. */
326 excess -= extra_bytes; 322 excess -= extra_bytes;
327 323
328 if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess) 324 if ((char *) last_heap->end - (char *) last_heap->bloc_start <= excess)
329 { 325 {
330 heap_ptr lh_prev; 326 heap_ptr lh_prev;
331 327
@@ -336,12 +332,12 @@ relinquish (void)
336 return; 332 return;
337 333
338 /* Return the last heap, with its header, to the system. */ 334 /* Return the last heap, with its header, to the system. */
339 excess = (char *)last_heap->end - (char *)last_heap->start; 335 excess = (char *) last_heap->end - (char *) last_heap->start;
340 lh_prev = last_heap->prev; 336 lh_prev = last_heap->prev;
341 /* If the system doesn't want that much memory back, leave 337 /* If the system doesn't want that much memory back, leave
342 last_heap unaltered to reflect that. This can occur if 338 last_heap unaltered to reflect that. This can occur if
343 break_value is still within the original data segment. */ 339 break_value is still within the original data segment. */
344 if ((*real_morecore) (- excess) != 0) 340 if (real_morecore (- excess) != 0)
345 { 341 {
346 last_heap = lh_prev; 342 last_heap = lh_prev;
347 last_heap->next = NIL_HEAP; 343 last_heap->next = NIL_HEAP;
@@ -349,13 +345,13 @@ relinquish (void)
349 } 345 }
350 else 346 else
351 { 347 {
352 excess = (char *) last_heap->end 348 excess = ((char *) last_heap->end
353 - (char *) ROUNDUP ((char *)last_heap->end - excess); 349 - (char *) ROUNDUP ((char *) last_heap->end - excess));
354 /* If the system doesn't want that much memory back, leave 350 /* If the system doesn't want that much memory back, leave
355 the end of the last heap unchanged to reflect that. This 351 the end of the last heap unchanged to reflect that. This
356 can occur if break_value is still within the original 352 can occur if break_value is still within the original
357 data segment. */ 353 data segment. */
358 if ((*real_morecore) (- excess) != 0) 354 if (real_morecore (- excess) != 0)
359 last_heap->end = (char *) last_heap->end - excess; 355 last_heap->end = (char *) last_heap->end - excess;
360 } 356 }
361 } 357 }
@@ -367,9 +363,9 @@ relinquish (void)
367 to that block. */ 363 to that block. */
368 364
369static bloc_ptr 365static bloc_ptr
370find_bloc (POINTER *ptr) 366find_bloc (void **ptr)
371{ 367{
372 register bloc_ptr p = first_bloc; 368 bloc_ptr p = first_bloc;
373 369
374 while (p != NIL_BLOC) 370 while (p != NIL_BLOC)
375 { 371 {
@@ -392,10 +388,10 @@ find_bloc (POINTER *ptr)
392 memory for the new block. */ 388 memory for the new block. */
393 389
394static bloc_ptr 390static bloc_ptr
395get_bloc (SIZE size) 391get_bloc (size_t size)
396{ 392{
397 register bloc_ptr new_bloc; 393 bloc_ptr new_bloc;
398 register heap_ptr heap; 394 heap_ptr heap;
399 395
400 if (! (new_bloc = malloc (BLOC_PTR_SIZE)) 396 if (! (new_bloc = malloc (BLOC_PTR_SIZE))
401 || ! (new_bloc->data = obtain (break_value, size))) 397 || ! (new_bloc->data = obtain (break_value, size)))
@@ -409,7 +405,7 @@ get_bloc (SIZE size)
409 405
410 new_bloc->size = size; 406 new_bloc->size = size;
411 new_bloc->next = NIL_BLOC; 407 new_bloc->next = NIL_BLOC;
412 new_bloc->variable = (POINTER *) NIL; 408 new_bloc->variable = NULL;
413 new_bloc->new_data = 0; 409 new_bloc->new_data = 0;
414 410
415 /* Record in the heap that this space is in use. */ 411 /* Record in the heap that this space is in use. */
@@ -447,9 +443,9 @@ get_bloc (SIZE size)
447 Do not touch the contents of blocs or break_value. */ 443 Do not touch the contents of blocs or break_value. */
448 444
449static int 445static int
450relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address) 446relocate_blocs (bloc_ptr bloc, heap_ptr heap, void *address)
451{ 447{
452 register bloc_ptr b = bloc; 448 bloc_ptr b = bloc;
453 449
454 /* No need to ever call this if arena is frozen, bug somewhere! */ 450 /* No need to ever call this if arena is frozen, bug somewhere! */
455 if (r_alloc_freeze_level) 451 if (r_alloc_freeze_level)
@@ -471,8 +467,8 @@ relocate_blocs (bloc_ptr bloc, heap_ptr heap, POINTER address)
471 get enough new space to hold BLOC and all following blocs. */ 467 get enough new space to hold BLOC and all following blocs. */
472 if (heap == NIL_HEAP) 468 if (heap == NIL_HEAP)
473 { 469 {
474 register bloc_ptr tb = b; 470 bloc_ptr tb = b;
475 register SIZE s = 0; 471 size_t s = 0;
476 472
477 /* Add up the size of all the following blocs. */ 473 /* Add up the size of all the following blocs. */
478 while (tb != NIL_BLOC) 474 while (tb != NIL_BLOC)
@@ -568,12 +564,12 @@ update_heap_bloc_correspondence (bloc_ptr bloc, heap_ptr heap)
568 that come after BLOC in memory. */ 564 that come after BLOC in memory. */
569 565
570static int 566static int
571resize_bloc (bloc_ptr bloc, SIZE size) 567resize_bloc (bloc_ptr bloc, size_t size)
572{ 568{
573 register bloc_ptr b; 569 bloc_ptr b;
574 heap_ptr heap; 570 heap_ptr heap;
575 POINTER address; 571 void *address;
576 SIZE old_size; 572 size_t old_size;
577 573
578 /* No need to ever call this if arena is frozen, bug somewhere! */ 574 /* No need to ever call this if arena is frozen, bug somewhere! */
579 if (r_alloc_freeze_level) 575 if (r_alloc_freeze_level)
@@ -675,7 +671,7 @@ free_bloc (bloc_ptr bloc)
675 671
676 if (r_alloc_freeze_level) 672 if (r_alloc_freeze_level)
677 { 673 {
678 bloc->variable = (POINTER *) NIL; 674 bloc->variable = NULL;
679 return; 675 return;
680 } 676 }
681 677
@@ -752,17 +748,17 @@ free_bloc (bloc_ptr bloc)
752 __morecore hook values - in particular, __default_morecore in the 748 __morecore hook values - in particular, __default_morecore in the
753 GNU malloc package. */ 749 GNU malloc package. */
754 750
755static POINTER 751static void *
756r_alloc_sbrk (ptrdiff_t size) 752r_alloc_sbrk (ptrdiff_t size)
757{ 753{
758 register bloc_ptr b; 754 bloc_ptr b;
759 POINTER address; 755 void *address;
760 756
761 if (! r_alloc_initialized) 757 if (! r_alloc_initialized)
762 r_alloc_init (); 758 r_alloc_init ();
763 759
764 if (use_relocatable_buffers <= 0) 760 if (use_relocatable_buffers <= 0)
765 return (*real_morecore) (size); 761 return real_morecore (size);
766 762
767 if (size == 0) 763 if (size == 0)
768 return virtual_break_value; 764 return virtual_break_value;
@@ -772,19 +768,19 @@ r_alloc_sbrk (ptrdiff_t size)
772 /* Allocate a page-aligned space. GNU malloc would reclaim an 768 /* Allocate a page-aligned space. GNU malloc would reclaim an
773 extra space if we passed an unaligned one. But we could 769 extra space if we passed an unaligned one. But we could
774 not always find a space which is contiguous to the previous. */ 770 not always find a space which is contiguous to the previous. */
775 POINTER new_bloc_start; 771 void *new_bloc_start;
776 heap_ptr h = first_heap; 772 heap_ptr h = first_heap;
777 SIZE get = ROUNDUP (size); 773 size_t get = ROUNDUP (size);
778 774
779 address = (POINTER) ROUNDUP (virtual_break_value); 775 address = (void *) ROUNDUP (virtual_break_value);
780 776
781 /* Search the list upward for a heap which is large enough. */ 777 /* Search the list upward for a heap which is large enough. */
782 while ((char *) h->end < (char *) MEM_ROUNDUP ((char *)address + get)) 778 while ((char *) h->end < (char *) MEM_ROUNDUP ((char *) address + get))
783 { 779 {
784 h = h->next; 780 h = h->next;
785 if (h == NIL_HEAP) 781 if (h == NIL_HEAP)
786 break; 782 break;
787 address = (POINTER) ROUNDUP (h->start); 783 address = (void *) ROUNDUP (h->start);
788 } 784 }
789 785
790 /* If not found, obtain more space. */ 786 /* If not found, obtain more space. */
@@ -796,19 +792,19 @@ r_alloc_sbrk (ptrdiff_t size)
796 return 0; 792 return 0;
797 793
798 if (first_heap == last_heap) 794 if (first_heap == last_heap)
799 address = (POINTER) ROUNDUP (virtual_break_value); 795 address = (void *) ROUNDUP (virtual_break_value);
800 else 796 else
801 address = (POINTER) ROUNDUP (last_heap->start); 797 address = (void *) ROUNDUP (last_heap->start);
802 h = last_heap; 798 h = last_heap;
803 } 799 }
804 800
805 new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get); 801 new_bloc_start = (void *) MEM_ROUNDUP ((char *) address + get);
806 802
807 if (first_heap->bloc_start < new_bloc_start) 803 if (first_heap->bloc_start < new_bloc_start)
808 { 804 {
809 /* This is no clean solution - no idea how to do it better. */ 805 /* This is no clean solution - no idea how to do it better. */
810 if (r_alloc_freeze_level) 806 if (r_alloc_freeze_level)
811 return NIL; 807 return NULL;
812 808
813 /* There is a bug here: if the above obtain call succeeded, but the 809 /* There is a bug here: if the above obtain call succeeded, but the
814 relocate_blocs call below does not succeed, we need to free 810 relocate_blocs call below does not succeed, we need to free
@@ -818,7 +814,7 @@ r_alloc_sbrk (ptrdiff_t size)
818 if (! relocate_blocs (first_bloc, h, new_bloc_start)) 814 if (! relocate_blocs (first_bloc, h, new_bloc_start))
819 return 0; 815 return 0;
820 816
821 /* Note that (POINTER)(h+1) <= new_bloc_start since 817 /* Note that (char *) (h + 1) <= (char *) new_bloc_start since
822 get >= page_size, so the following does not destroy the heap 818 get >= page_size, so the following does not destroy the heap
823 header. */ 819 header. */
824 for (b = last_bloc; b != NIL_BLOC; b = b->prev) 820 for (b = last_bloc; b != NIL_BLOC; b = b->prev)
@@ -855,8 +851,8 @@ r_alloc_sbrk (ptrdiff_t size)
855 } 851 }
856 else /* size < 0 */ 852 else /* size < 0 */
857 { 853 {
858 SIZE excess = (char *)first_heap->bloc_start 854 size_t excess = ((char *) first_heap->bloc_start
859 - ((char *)virtual_break_value + size); 855 - ((char *) virtual_break_value + size));
860 856
861 address = virtual_break_value; 857 address = virtual_break_value;
862 858
@@ -864,7 +860,7 @@ r_alloc_sbrk (ptrdiff_t size)
864 { 860 {
865 excess -= extra_bytes; 861 excess -= extra_bytes;
866 first_heap->bloc_start 862 first_heap->bloc_start
867 = (POINTER) MEM_ROUNDUP ((char *)first_heap->bloc_start - excess); 863 = (void *) MEM_ROUNDUP ((char *) first_heap->bloc_start - excess);
868 864
869 relocate_blocs (first_bloc, first_heap, first_heap->bloc_start); 865 relocate_blocs (first_bloc, first_heap, first_heap->bloc_start);
870 866
@@ -876,14 +872,14 @@ r_alloc_sbrk (ptrdiff_t size)
876 } 872 }
877 } 873 }
878 874
879 if ((char *)virtual_break_value + size < (char *)first_heap->start) 875 if ((char *) virtual_break_value + size < (char *) first_heap->start)
880 { 876 {
881 /* We found an additional space below the first heap */ 877 /* We found an additional space below the first heap */
882 first_heap->start = (POINTER) ((char *)virtual_break_value + size); 878 first_heap->start = (void *) ((char *) virtual_break_value + size);
883 } 879 }
884 } 880 }
885 881
886 virtual_break_value = (POINTER) ((char *)address + size); 882 virtual_break_value = (void *) ((char *) address + size);
887 break_value = (last_bloc 883 break_value = (last_bloc
888 ? (char *) last_bloc->data + last_bloc->size 884 ? (char *) last_bloc->data + last_bloc->size
889 : (char *) first_heap->bloc_start); 885 : (char *) first_heap->bloc_start);
@@ -905,10 +901,10 @@ r_alloc_sbrk (ptrdiff_t size)
905 If we can't allocate the necessary memory, set *PTR to zero, and 901 If we can't allocate the necessary memory, set *PTR to zero, and
906 return zero. */ 902 return zero. */
907 903
908POINTER 904void *
909r_alloc (POINTER *ptr, SIZE size) 905r_alloc (void **ptr, size_t size)
910{ 906{
911 register bloc_ptr new_bloc; 907 bloc_ptr new_bloc;
912 908
913 if (! r_alloc_initialized) 909 if (! r_alloc_initialized)
914 r_alloc_init (); 910 r_alloc_init ();
@@ -929,9 +925,9 @@ r_alloc (POINTER *ptr, SIZE size)
929 Store 0 in *PTR to show there's no block allocated. */ 925 Store 0 in *PTR to show there's no block allocated. */
930 926
931void 927void
932r_alloc_free (register POINTER *ptr) 928r_alloc_free (void **ptr)
933{ 929{
934 register bloc_ptr dead_bloc; 930 bloc_ptr dead_bloc;
935 931
936 if (! r_alloc_initialized) 932 if (! r_alloc_initialized)
937 r_alloc_init (); 933 r_alloc_init ();
@@ -962,10 +958,10 @@ r_alloc_free (register POINTER *ptr)
962 If more memory cannot be allocated, then leave *PTR unchanged, and 958 If more memory cannot be allocated, then leave *PTR unchanged, and
963 return zero. */ 959 return zero. */
964 960
965POINTER 961void *
966r_re_alloc (POINTER *ptr, SIZE size) 962r_re_alloc (void **ptr, size_t size)
967{ 963{
968 register bloc_ptr bloc; 964 bloc_ptr bloc;
969 965
970 if (! r_alloc_initialized) 966 if (! r_alloc_initialized)
971 r_alloc_init (); 967 r_alloc_init ();
@@ -1004,15 +1000,15 @@ r_re_alloc (POINTER *ptr, SIZE size)
1004 { 1000 {
1005 new_bloc->variable = ptr; 1001 new_bloc->variable = ptr;
1006 *ptr = new_bloc->data; 1002 *ptr = new_bloc->data;
1007 bloc->variable = (POINTER *) NIL; 1003 bloc->variable = NULL;
1008 } 1004 }
1009 else 1005 else
1010 return NIL; 1006 return NULL;
1011 } 1007 }
1012 else 1008 else
1013 { 1009 {
1014 if (! resize_bloc (bloc, MEM_ROUNDUP (size))) 1010 if (! resize_bloc (bloc, MEM_ROUNDUP (size)))
1015 return NIL; 1011 return NULL;
1016 } 1012 }
1017 } 1013 }
1018 return *ptr; 1014 return *ptr;
@@ -1052,27 +1048,27 @@ r_alloc_check (void)
1052 return; 1048 return;
1053 1049
1054 assert (first_heap); 1050 assert (first_heap);
1055 assert (last_heap->end <= (POINTER) sbrk (0)); 1051 assert (last_heap->end <= (void *) sbrk (0));
1056 assert ((POINTER) first_heap < first_heap->start); 1052 assert ((void *) first_heap < first_heap->start);
1057 assert (first_heap->start <= virtual_break_value); 1053 assert (first_heap->start <= virtual_break_value);
1058 assert (virtual_break_value <= first_heap->end); 1054 assert (virtual_break_value <= first_heap->end);
1059 1055
1060 for (h = first_heap; h; h = h->next) 1056 for (h = first_heap; h; h = h->next)
1061 { 1057 {
1062 assert (h->prev == ph); 1058 assert (h->prev == ph);
1063 assert ((POINTER) ROUNDUP (h->end) == h->end); 1059 assert ((void *) ROUNDUP (h->end) == h->end);
1064#if 0 /* ??? The code in ralloc.c does not really try to ensure 1060#if 0 /* ??? The code in ralloc.c does not really try to ensure
1065 the heap start has any sort of alignment. 1061 the heap start has any sort of alignment.
1066 Perhaps it should. */ 1062 Perhaps it should. */
1067 assert ((POINTER) MEM_ROUNDUP (h->start) == h->start); 1063 assert ((void *) MEM_ROUNDUP (h->start) == h->start);
1068#endif 1064#endif
1069 assert ((POINTER) MEM_ROUNDUP (h->bloc_start) == h->bloc_start); 1065 assert ((void *) MEM_ROUNDUP (h->bloc_start) == h->bloc_start);
1070 assert (h->start <= h->bloc_start && h->bloc_start <= h->end); 1066 assert (h->start <= h->bloc_start && h->bloc_start <= h->end);
1071 1067
1072 if (ph) 1068 if (ph)
1073 { 1069 {
1074 assert (ph->end < h->start); 1070 assert (ph->end < h->start);
1075 assert (h->start <= (POINTER)h && (POINTER)(h+1) <= h->bloc_start); 1071 assert (h->start <= (void *) h && (void *) (h + 1) <= h->bloc_start);
1076 } 1072 }
1077 1073
1078 if (h->bloc_start <= break_value && break_value <= h->end) 1074 if (h->bloc_start <= break_value && break_value <= h->end)
@@ -1087,8 +1083,8 @@ r_alloc_check (void)
1087 for (b = first_bloc; b; b = b->next) 1083 for (b = first_bloc; b; b = b->next)
1088 { 1084 {
1089 assert (b->prev == pb); 1085 assert (b->prev == pb);
1090 assert ((POINTER) MEM_ROUNDUP (b->data) == b->data); 1086 assert ((void *) MEM_ROUNDUP (b->data) == b->data);
1091 assert ((SIZE) MEM_ROUNDUP (b->size) == b->size); 1087 assert ((size_t) MEM_ROUNDUP (b->size) == b->size);
1092 1088
1093 ph = 0; 1089 ph = 0;
1094 for (h = first_heap; h; h = h->next) 1090 for (h = first_heap; h; h = h->next)
@@ -1137,7 +1133,7 @@ r_alloc_check (void)
1137 is checked to ensure that memory corruption does not occur due to 1133 is checked to ensure that memory corruption does not occur due to
1138 misuse. */ 1134 misuse. */
1139void 1135void
1140r_alloc_reset_variable (POINTER *old, POINTER *new) 1136r_alloc_reset_variable (void **old, void **new)
1141{ 1137{
1142 bloc_ptr bloc = first_bloc; 1138 bloc_ptr bloc = first_bloc;
1143 1139
@@ -1192,8 +1188,8 @@ r_alloc_init (void)
1192 first_heap = last_heap = &heap_base; 1188 first_heap = last_heap = &heap_base;
1193 first_heap->next = first_heap->prev = NIL_HEAP; 1189 first_heap->next = first_heap->prev = NIL_HEAP;
1194 first_heap->start = first_heap->bloc_start 1190 first_heap->start = first_heap->bloc_start
1195 = virtual_break_value = break_value = (*real_morecore) (0); 1191 = virtual_break_value = break_value = real_morecore (0);
1196 if (break_value == NIL) 1192 if (break_value == NULL)
1197 emacs_abort (); 1193 emacs_abort ();
1198 1194
1199 extra_bytes = ROUNDUP (50000); 1195 extra_bytes = ROUNDUP (50000);
@@ -1218,7 +1214,7 @@ r_alloc_init (void)
1218#endif 1214#endif
1219 1215
1220#ifndef SYSTEM_MALLOC 1216#ifndef SYSTEM_MALLOC
1221 first_heap->end = (POINTER) ROUNDUP (first_heap->start); 1217 first_heap->end = (void *) ROUNDUP (first_heap->start);
1222 1218
1223 /* The extra call to real_morecore guarantees that the end of the 1219 /* The extra call to real_morecore guarantees that the end of the
1224 address space is a multiple of page_size, even if page_size is 1220 address space is a multiple of page_size, even if page_size is
@@ -1226,7 +1222,7 @@ r_alloc_init (void)
1226 which page_size is stored. This allows a binary to be built on a 1222 which page_size is stored. This allows a binary to be built on a
1227 system with one page size and run on a system with a smaller page 1223 system with one page size and run on a system with a smaller page
1228 size. */ 1224 size. */
1229 (*real_morecore) ((char *) first_heap->end - (char *) first_heap->start); 1225 real_morecore ((char *) first_heap->end - (char *) first_heap->start);
1230 1226
1231 /* Clear the rest of the last page; this memory is in our address space 1227 /* Clear the rest of the last page; this memory is in our address space
1232 even though it is after the sbrk value. */ 1228 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/>. */
40 existing data structure, and disturb as little of the existing code 40 existing data structure, and disturb as little of the existing code
41 as possible. 41 as possible.
42 42
43 So here's the tack. We add some caching to the scan_buffer 43 So here's the tack. We add some caching to the find_newline
44 function, so that when it searches for a newline, it notes that the 44 function, so that when it searches for a newline, it notes that the
45 region between the start and end of the search contained no 45 region between the start and end of the search contained no
46 newlines; then, the next time around, it consults this cache to see 46 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)
209 for this pattern. 0 means backtrack only enough to get a valid match. */ 209 for this pattern. 0 means backtrack only enough to get a valid match. */
210 210
211struct re_pattern_buffer * 211struct re_pattern_buffer *
212compile_pattern (Lisp_Object pattern, struct re_registers *regp, Lisp_Object translate, int posix, int multibyte) 212compile_pattern (Lisp_Object pattern, struct re_registers *regp,
213 Lisp_Object translate, int posix, bool multibyte)
213{ 214{
214 struct regexp_cache *cp, **cpp; 215 struct regexp_cache *cp, **cpp;
215 216
@@ -534,9 +535,10 @@ fast_string_match_ignore_case (Lisp_Object regexp, Lisp_Object string)
534 data. */ 535 data. */
535 536
536ptrdiff_t 537ptrdiff_t
537fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t limit, ptrdiff_t limit_byte, Lisp_Object string) 538fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte,
539 ptrdiff_t limit, ptrdiff_t limit_byte, Lisp_Object string)
538{ 540{
539 int multibyte; 541 bool multibyte;
540 struct re_pattern_buffer *buf; 542 struct re_pattern_buffer *buf;
541 unsigned char *p1, *p2; 543 unsigned char *p1, *p2;
542 ptrdiff_t s1, s2; 544 ptrdiff_t s1, s2;
@@ -619,7 +621,7 @@ newline_cache_on_off (struct buffer *buf)
619} 621}
620 622
621 623
622/* Search for COUNT instances of the character TARGET between START and END. 624/* Search for COUNT newlines between START/START_BYTE and END/END_BYTE.
623 625
624 If COUNT is positive, search forwards; END must be >= START. 626 If COUNT is positive, search forwards; END must be >= START.
625 If COUNT is negative, search backwards for the -COUNTth instance; 627 If COUNT is negative, search backwards for the -COUNTth instance;
@@ -634,14 +636,18 @@ newline_cache_on_off (struct buffer *buf)
634 this is not the same as the usual convention for Emacs motion commands. 636 this is not the same as the usual convention for Emacs motion commands.
635 637
636 If we don't find COUNT instances before reaching END, set *SHORTAGE 638 If we don't find COUNT instances before reaching END, set *SHORTAGE
637 to the number of TARGETs left unfound, and return END. 639 to the number of newlines left unfound, and return END.
640
641 If BYTEPOS is not NULL, set *BYTEPOS to the byte position corresponding
642 to the returned character position.
638 643
639 If ALLOW_QUIT, set immediate_quit. That's good to do 644 If ALLOW_QUIT, set immediate_quit. That's good to do
640 except when inside redisplay. */ 645 except when inside redisplay. */
641 646
642ptrdiff_t 647ptrdiff_t
643scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, 648find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
644 ptrdiff_t count, ptrdiff_t *shortage, bool allow_quit) 649 ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage,
650 ptrdiff_t *bytepos, bool allow_quit)
645{ 651{
646 struct region_cache *newline_cache; 652 struct region_cache *newline_cache;
647 int direction; 653 int direction;
@@ -649,13 +655,17 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
649 if (count > 0) 655 if (count > 0)
650 { 656 {
651 direction = 1; 657 direction = 1;
652 if (! end) end = ZV; 658 if (!end)
659 end = ZV, end_byte = ZV_BYTE;
653 } 660 }
654 else 661 else
655 { 662 {
656 direction = -1; 663 direction = -1;
657 if (! end) end = BEGV; 664 if (!end)
665 end = BEGV, end_byte = BEGV_BYTE;
658 } 666 }
667 if (end_byte == -1)
668 end_byte = CHAR_TO_BYTE (end);
659 669
660 newline_cache_on_off (current_buffer); 670 newline_cache_on_off (current_buffer);
661 newline_cache = current_buffer->newline_cache; 671 newline_cache = current_buffer->newline_cache;
@@ -673,13 +683,11 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
673 the position of the last character before the next such 683 the position of the last character before the next such
674 obstacle --- the last character the dumb search loop should 684 obstacle --- the last character the dumb search loop should
675 examine. */ 685 examine. */
676 ptrdiff_t ceiling_byte = CHAR_TO_BYTE (end) - 1; 686 ptrdiff_t tem, ceiling_byte = end_byte - 1;
677 ptrdiff_t start_byte;
678 ptrdiff_t tem;
679 687
680 /* If we're looking for a newline, consult the newline cache 688 /* If we're looking for a newline, consult the newline cache
681 to see where we can avoid some scanning. */ 689 to see where we can avoid some scanning. */
682 if (target == '\n' && newline_cache) 690 if (newline_cache)
683 { 691 {
684 ptrdiff_t next_change; 692 ptrdiff_t next_change;
685 immediate_quit = 0; 693 immediate_quit = 0;
@@ -698,7 +706,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
698 next_change is the position of the next known region. */ 706 next_change is the position of the next known region. */
699 ceiling_byte = min (CHAR_TO_BYTE (next_change) - 1, ceiling_byte); 707 ceiling_byte = min (CHAR_TO_BYTE (next_change) - 1, ceiling_byte);
700 } 708 }
701 else 709 else if (start_byte == -1)
702 start_byte = CHAR_TO_BYTE (start); 710 start_byte = CHAR_TO_BYTE (start);
703 711
704 /* The dumb loop can only scan text stored in contiguous 712 /* The dumb loop can only scan text stored in contiguous
@@ -718,44 +726,45 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
718 726
719 while (cursor < ceiling_addr) 727 while (cursor < ceiling_addr)
720 { 728 {
721 unsigned char *scan_start = cursor;
722
723 /* The dumb loop. */ 729 /* The dumb loop. */
724 while (*cursor != target && ++cursor < ceiling_addr) 730 unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor);
725 ;
726 731
727 /* If we're looking for newlines, cache the fact that 732 /* If we're looking for newlines, cache the fact that
728 the region from start to cursor is free of them. */ 733 the region from start to cursor is free of them. */
729 if (target == '\n' && newline_cache) 734 if (newline_cache)
730 know_region_cache (current_buffer, newline_cache, 735 {
731 BYTE_TO_CHAR (start_byte + scan_start - base), 736 unsigned char *low = cursor;
732 BYTE_TO_CHAR (start_byte + cursor - base)); 737 unsigned char *lim = nl ? nl : ceiling_addr;
733 738 know_region_cache (current_buffer, newline_cache,
734 /* Did we find the target character? */ 739 BYTE_TO_CHAR (low - base + start_byte),
735 if (cursor < ceiling_addr) 740 BYTE_TO_CHAR (lim - base + start_byte));
736 { 741 }
737 if (--count == 0) 742
738 { 743 if (! nl)
739 immediate_quit = 0; 744 break;
740 return BYTE_TO_CHAR (start_byte + cursor - base + 1); 745
741 } 746 if (--count == 0)
742 cursor++; 747 {
743 } 748 immediate_quit = 0;
749 if (bytepos)
750 *bytepos = nl + 1 - base + start_byte;
751 return BYTE_TO_CHAR (nl + 1 - base + start_byte);
752 }
753 cursor = nl + 1;
744 } 754 }
745 755
746 start = BYTE_TO_CHAR (start_byte + cursor - base); 756 start_byte += ceiling_addr - base;
757 start = BYTE_TO_CHAR (start_byte);
747 } 758 }
748 } 759 }
749 else 760 else
750 while (start > end) 761 while (start > end)
751 { 762 {
752 /* The last character to check before the next obstacle. */ 763 /* The last character to check before the next obstacle. */
753 ptrdiff_t ceiling_byte = CHAR_TO_BYTE (end); 764 ptrdiff_t tem, ceiling_byte = end_byte;
754 ptrdiff_t start_byte;
755 ptrdiff_t tem;
756 765
757 /* Consult the newline cache, if appropriate. */ 766 /* Consult the newline cache, if appropriate. */
758 if (target == '\n' && newline_cache) 767 if (newline_cache)
759 { 768 {
760 ptrdiff_t next_change; 769 ptrdiff_t next_change;
761 immediate_quit = 0; 770 immediate_quit = 0;
@@ -774,7 +783,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
774 next_change is the position of the next known region. */ 783 next_change is the position of the next known region. */
775 ceiling_byte = max (CHAR_TO_BYTE (next_change), ceiling_byte); 784 ceiling_byte = max (CHAR_TO_BYTE (next_change), ceiling_byte);
776 } 785 }
777 else 786 else if (start_byte == -1)
778 start_byte = CHAR_TO_BYTE (start); 787 start_byte = CHAR_TO_BYTE (start);
779 788
780 /* Stop scanning before the gap. */ 789 /* Stop scanning before the gap. */
@@ -789,42 +798,50 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end,
789 798
790 while (cursor >= ceiling_addr) 799 while (cursor >= ceiling_addr)
791 { 800 {
792 unsigned char *scan_start = cursor; 801 unsigned char *nl = memrchr (ceiling_addr, '\n',
793 802 cursor + 1 - ceiling_addr);
794 while (*cursor != target && --cursor >= ceiling_addr)
795 ;
796 803
797 /* If we're looking for newlines, cache the fact that 804 /* If we're looking for newlines, cache the fact that
798 the region from after the cursor to start is free of them. */ 805 the region from after the cursor to start is free of them. */
799 if (target == '\n' && newline_cache) 806 if (newline_cache)
800 know_region_cache (current_buffer, newline_cache, 807 {
801 BYTE_TO_CHAR (start_byte + cursor - base), 808 unsigned char *low = nl ? nl : ceiling_addr - 1;
802 BYTE_TO_CHAR (start_byte + scan_start - base)); 809 unsigned char *lim = cursor;
803 810 know_region_cache (current_buffer, newline_cache,
804 /* Did we find the target character? */ 811 BYTE_TO_CHAR (low - base + start_byte),
805 if (cursor >= ceiling_addr) 812 BYTE_TO_CHAR (lim - base + start_byte));
806 { 813 }
807 if (++count >= 0) 814
808 { 815 if (! nl)
809 immediate_quit = 0; 816 break;
810 return BYTE_TO_CHAR (start_byte + cursor - base); 817
811 } 818 if (++count >= 0)
812 cursor--; 819 {
813 } 820 immediate_quit = 0;
821 if (bytepos)
822 *bytepos = nl - base + start_byte;
823 return BYTE_TO_CHAR (nl - base + start_byte);
824 }
825 cursor = nl - 1;
814 } 826 }
815 827
816 start = BYTE_TO_CHAR (start_byte + cursor - base); 828 start_byte += ceiling_addr - 1 - base;
829 start = BYTE_TO_CHAR (start_byte);
817 } 830 }
818 } 831 }
819 832
820 immediate_quit = 0; 833 immediate_quit = 0;
821 if (shortage != 0) 834 if (shortage)
822 *shortage = count * direction; 835 *shortage = count * direction;
836 if (bytepos)
837 {
838 *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte;
839 eassert (*bytepos == CHAR_TO_BYTE (start));
840 }
823 return start; 841 return start;
824} 842}
825 843
826/* Search for COUNT instances of a line boundary, which means either a 844/* Search for COUNT instances of a line boundary.
827 newline or (if selective display enabled) a carriage return.
828 Start at START. If COUNT is negative, search backwards. 845 Start at START. If COUNT is negative, search backwards.
829 846
830 We report the resulting position by calling TEMP_SET_PT_BOTH. 847 We report the resulting position by calling TEMP_SET_PT_BOTH.
@@ -855,14 +872,9 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte,
855 872
856 bool old_immediate_quit = immediate_quit; 873 bool old_immediate_quit = immediate_quit;
857 874
858 /* The code that follows is like scan_buffer
859 but checks for either newline or carriage return. */
860
861 if (allow_quit) 875 if (allow_quit)
862 immediate_quit++; 876 immediate_quit++;
863 877
864 start_byte = CHAR_TO_BYTE (start);
865
866 if (count > 0) 878 if (count > 0)
867 { 879 {
868 while (start_byte < limit_byte) 880 while (start_byte < limit_byte)
@@ -871,29 +883,25 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte,
871 ceiling = min (limit_byte - 1, ceiling); 883 ceiling = min (limit_byte - 1, ceiling);
872 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; 884 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
873 base = (cursor = BYTE_POS_ADDR (start_byte)); 885 base = (cursor = BYTE_POS_ADDR (start_byte));
874 while (1)
875 {
876 while (*cursor != '\n' && ++cursor != ceiling_addr)
877 ;
878 886
879 if (cursor != ceiling_addr) 887 do
888 {
889 unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor);
890 if (! nl)
891 break;
892 if (--count == 0)
880 { 893 {
881 if (--count == 0) 894 immediate_quit = old_immediate_quit;
882 { 895 start_byte += nl - base + 1;
883 immediate_quit = old_immediate_quit; 896 start = BYTE_TO_CHAR (start_byte);
884 start_byte = start_byte + cursor - base + 1; 897 TEMP_SET_PT_BOTH (start, start_byte);
885 start = BYTE_TO_CHAR (start_byte); 898 return 0;
886 TEMP_SET_PT_BOTH (start, start_byte);
887 return 0;
888 }
889 else
890 if (++cursor == ceiling_addr)
891 break;
892 } 899 }
893 else 900 cursor = nl + 1;
894 break;
895 } 901 }
896 start_byte += cursor - base; 902 while (cursor < ceiling_addr);
903
904 start_byte += ceiling_addr - base;
897 } 905 }
898 } 906 }
899 else 907 else
@@ -902,31 +910,28 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte,
902 { 910 {
903 ceiling = BUFFER_FLOOR_OF (start_byte - 1); 911 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
904 ceiling = max (limit_byte, ceiling); 912 ceiling = max (limit_byte, ceiling);
905 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; 913 ceiling_addr = BYTE_POS_ADDR (ceiling);
906 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); 914 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
907 while (1) 915 while (1)
908 { 916 {
909 while (--cursor != ceiling_addr && *cursor != '\n') 917 unsigned char *nl = memrchr (ceiling_addr, '\n',
910 ; 918 cursor - ceiling_addr);
919 if (! nl)
920 break;
911 921
912 if (cursor != ceiling_addr) 922 if (++count == 0)
913 { 923 {
914 if (++count == 0) 924 immediate_quit = old_immediate_quit;
915 { 925 /* Return the position AFTER the match we found. */
916 immediate_quit = old_immediate_quit; 926 start_byte += nl - base + 1;
917 /* Return the position AFTER the match we found. */ 927 start = BYTE_TO_CHAR (start_byte);
918 start_byte = start_byte + cursor - base + 1; 928 TEMP_SET_PT_BOTH (start, start_byte);
919 start = BYTE_TO_CHAR (start_byte); 929 return 0;
920 TEMP_SET_PT_BOTH (start, start_byte);
921 return 0;
922 }
923 } 930 }
924 else 931
925 break; 932 cursor = nl;
926 } 933 }
927 /* Here we add 1 to compensate for the last decrement 934 start_byte += ceiling_addr - base;
928 of CURSOR, which took it past the valid range. */
929 start_byte += cursor - base + 1;
930 } 935 }
931 } 936 }
932 937
@@ -936,25 +941,33 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte,
936 return count * direction; 941 return count * direction;
937} 942}
938 943
944/* Like find_newline, but doesn't allow QUITting and doesn't return
945 SHORTAGE. */
939ptrdiff_t 946ptrdiff_t
940find_next_newline_no_quit (ptrdiff_t from, ptrdiff_t cnt) 947find_newline_no_quit (ptrdiff_t from, ptrdiff_t frombyte,
948 ptrdiff_t cnt, ptrdiff_t *bytepos)
941{ 949{
942 return scan_buffer ('\n', from, 0, cnt, (ptrdiff_t *) 0, 0); 950 return find_newline (from, frombyte, 0, -1, cnt, NULL, bytepos, 0);
943} 951}
944 952
945/* Like find_next_newline, but returns position before the newline, 953/* Like find_newline, but returns position before the newline, not
946 not after, and only search up to TO. This isn't just 954 after, and only search up to TO.
947 find_next_newline (...)-1, because you might hit TO. */ 955 This isn't just find_newline_no_quit (...)-1, because you might hit TO. */
948 956
949ptrdiff_t 957ptrdiff_t
950find_before_next_newline (ptrdiff_t from, ptrdiff_t to, ptrdiff_t cnt) 958find_before_next_newline (ptrdiff_t from, ptrdiff_t to,
959 ptrdiff_t cnt, ptrdiff_t *bytepos)
951{ 960{
952 ptrdiff_t shortage; 961 ptrdiff_t shortage;
953 ptrdiff_t pos = scan_buffer ('\n', from, to, cnt, &shortage, 1); 962 ptrdiff_t pos = find_newline (from, -1, to, -1, cnt, &shortage, bytepos, 1);
954 963
955 if (shortage == 0) 964 if (shortage == 0)
956 pos--; 965 {
957 966 if (bytepos)
967 DEC_BOTH (pos, *bytepos);
968 else
969 pos--;
970 }
958 return pos; 971 return pos;
959} 972}
960 973
@@ -1016,8 +1029,7 @@ search_command (Lisp_Object string, Lisp_Object bound, Lisp_Object noerror,
1016 1029
1017 if (!EQ (noerror, Qt)) 1030 if (!EQ (noerror, Qt))
1018 { 1031 {
1019 if (lim < BEGV || lim > ZV) 1032 eassert (BEGV <= lim && lim <= ZV);
1020 emacs_abort ();
1021 SET_PT_BOTH (lim, lim_byte); 1033 SET_PT_BOTH (lim, lim_byte);
1022 return Qnil; 1034 return Qnil;
1023#if 0 /* This would be clean, but maybe programs depend on 1035#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,
1029 return Qnil; 1041 return Qnil;
1030 } 1042 }
1031 1043
1032 if (np < BEGV || np > ZV) 1044 eassert (BEGV <= np && np <= ZV);
1033 emacs_abort ();
1034
1035 SET_PT (np); 1045 SET_PT (np);
1036 1046
1037 return make_number (np); 1047 return make_number (np);
@@ -1258,7 +1268,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1258 ptrdiff_t raw_pattern_size; 1268 ptrdiff_t raw_pattern_size;
1259 ptrdiff_t raw_pattern_size_byte; 1269 ptrdiff_t raw_pattern_size_byte;
1260 unsigned char *patbuf; 1270 unsigned char *patbuf;
1261 int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); 1271 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
1262 unsigned char *base_pat; 1272 unsigned char *base_pat;
1263 /* Set to positive if we find a non-ASCII char that need 1273 /* Set to positive if we find a non-ASCII char that need
1264 translation. Otherwise set to zero later. */ 1274 translation. Otherwise set to zero later. */
@@ -1471,8 +1481,8 @@ simple_search (EMACS_INT n, unsigned char *pat,
1471 ptrdiff_t pos, ptrdiff_t pos_byte, 1481 ptrdiff_t pos, ptrdiff_t pos_byte,
1472 ptrdiff_t lim, ptrdiff_t lim_byte) 1482 ptrdiff_t lim, ptrdiff_t lim_byte)
1473{ 1483{
1474 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); 1484 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
1475 int forward = n > 0; 1485 bool forward = n > 0;
1476 /* Number of buffer bytes matched. Note that this may be different 1486 /* Number of buffer bytes matched. Note that this may be different
1477 from len_byte in a multibyte buffer. */ 1487 from len_byte in a multibyte buffer. */
1478 ptrdiff_t match_byte = PTRDIFF_MIN; 1488 ptrdiff_t match_byte = PTRDIFF_MIN;
@@ -1691,7 +1701,7 @@ boyer_moore (EMACS_INT n, unsigned char *base_pat,
1691 register ptrdiff_t i; 1701 register ptrdiff_t i;
1692 register int j; 1702 register int j;
1693 unsigned char *pat, *pat_end; 1703 unsigned char *pat, *pat_end;
1694 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); 1704 bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
1695 1705
1696 unsigned char simple_translate[0400]; 1706 unsigned char simple_translate[0400];
1697 /* These are set to the preceding bytes of a byte to be translated 1707 /* These are set to the preceding bytes of a byte to be translated
@@ -2517,8 +2527,8 @@ since only regular expressions have distinguished subexpressions. */)
2517 ptrdiff_t length = SBYTES (newtext); 2527 ptrdiff_t length = SBYTES (newtext);
2518 unsigned char *substed; 2528 unsigned char *substed;
2519 ptrdiff_t substed_alloc_size, substed_len; 2529 ptrdiff_t substed_alloc_size, substed_len;
2520 int buf_multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); 2530 bool buf_multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
2521 int str_multibyte = STRING_MULTIBYTE (newtext); 2531 bool str_multibyte = STRING_MULTIBYTE (newtext);
2522 int really_changed = 0; 2532 int really_changed = 0;
2523 2533
2524 substed_alloc_size = ((STRING_BYTES_BOUND - 100) / 2 < length 2534 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)
91 char buf[200]; 91 char buf[200];
92 sprintf (buf, "Static heap usage: %d of %d bytes", 92 sprintf (buf, "Static heap usage: %d of %d bytes",
93 bss_sbrk_ptr - bss_sbrk_buffer, STATIC_HEAP_SIZE); 93 bss_sbrk_ptr - bss_sbrk_buffer, STATIC_HEAP_SIZE);
94 message ("%s", buf); 94 /* Don't log messages, cause at this point, we're not allowed to create
95 buffers. */
96 message1_nolog (buf);
95} 97}
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)
334static void 334static void
335sound_warning (const char *msg) 335sound_warning (const char *msg)
336{ 336{
337 message ("%s", msg); 337 message1 (msg);
338} 338}
339 339
340 340
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
121 /* Char number of start of containing expression */ 121 /* Char number of start of containing expression */
122 ptrdiff_t prevlevelstart; 122 ptrdiff_t prevlevelstart;
123 ptrdiff_t location; /* Char number at which parsing stopped. */ 123 ptrdiff_t location; /* Char number at which parsing stopped. */
124 ptrdiff_t location_byte; /* Corresponding byte position. */
124 ptrdiff_t comstr_start; /* Position of last comment/string starter. */ 125 ptrdiff_t comstr_start; /* Position of last comment/string starter. */
125 Lisp_Object levelstarts; /* Char numbers of starts-of-expression 126 Lisp_Object levelstarts; /* Char numbers of starts-of-expression
126 of levels (starting from outermost). */ 127 of levels (starting from outermost). */
@@ -3277,6 +3278,7 @@ do { prev_from = from; \
3277 3278
3278 stop: /* Here if stopping before start of sexp. */ 3279 stop: /* Here if stopping before start of sexp. */
3279 from = prev_from; /* We have just fetched the char that starts it; */ 3280 from = prev_from; /* We have just fetched the char that starts it; */
3281 from_byte = prev_from_byte;
3280 goto done; /* but return the position before it. */ 3282 goto done; /* but return the position before it. */
3281 3283
3282 endquoted: 3284 endquoted:
@@ -3288,6 +3290,7 @@ do { prev_from = from; \
3288 state.prevlevelstart 3290 state.prevlevelstart
3289 = (curlevel == levelstart) ? -1 : (curlevel - 1)->last; 3291 = (curlevel == levelstart) ? -1 : (curlevel - 1)->last;
3290 state.location = from; 3292 state.location = from;
3293 state.location_byte = from_byte;
3291 state.levelstarts = Qnil; 3294 state.levelstarts = Qnil;
3292 while (curlevel > levelstart) 3295 while (curlevel > levelstart)
3293 state.levelstarts = Fcons (make_number ((--curlevel)->last), 3296 state.levelstarts = Fcons (make_number ((--curlevel)->last),
@@ -3327,7 +3330,8 @@ Fifth arg OLDSTATE is a list like what this function returns.
3327Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. 3330Sixth arg COMMENTSTOP non-nil means stop at the start of a comment.
3328 If it is symbol `syntax-table', stop after the start of a comment or a 3331 If it is symbol `syntax-table', stop after the start of a comment or a
3329 string, or after end of a comment or a string. */) 3332 string, or after end of a comment or a string. */)
3330 (Lisp_Object from, Lisp_Object to, Lisp_Object targetdepth, Lisp_Object stopbefore, Lisp_Object oldstate, Lisp_Object commentstop) 3333 (Lisp_Object from, Lisp_Object to, Lisp_Object targetdepth,
3334 Lisp_Object stopbefore, Lisp_Object oldstate, Lisp_Object commentstop)
3331{ 3335{
3332 struct lisp_parse_state state; 3336 struct lisp_parse_state state;
3333 EMACS_INT target; 3337 EMACS_INT target;
@@ -3347,7 +3351,7 @@ Sixth arg COMMENTSTOP non-nil means stop at the start of a comment.
3347 (NILP (commentstop) 3351 (NILP (commentstop)
3348 ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1))); 3352 ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1)));
3349 3353
3350 SET_PT (state.location); 3354 SET_PT_BOTH (state.location, state.location_byte);
3351 3355
3352 return Fcons (make_number (state.depth), 3356 return Fcons (make_number (state.depth),
3353 Fcons (state.prevlevelstart < 0 3357 Fcons (state.prevlevelstart < 0
@@ -3389,8 +3393,8 @@ init_syntax_once (void)
3389 Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots"); 3393 Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
3390 3394
3391 /* Create objects which can be shared among syntax tables. */ 3395 /* Create objects which can be shared among syntax tables. */
3392 Vsyntax_code_object = Fmake_vector (make_number (Smax), Qnil); 3396 Vsyntax_code_object = make_uninit_vector (Smax);
3393 for (i = 0; i < ASIZE (Vsyntax_code_object); i++) 3397 for (i = 0; i < Smax; i++)
3394 ASET (Vsyntax_code_object, i, Fcons (make_number (i), Qnil)); 3398 ASET (Vsyntax_code_object, i, Fcons (make_number (i), Qnil));
3395 3399
3396 /* Now we are ready to set up this property, so we can 3400 /* 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/>. */
30#include <limits.h> 30#include <limits.h>
31#include <unistd.h> 31#include <unistd.h>
32 32
33#include <allocator.h>
34#include <c-ctype.h> 33#include <c-ctype.h>
35#include <careadlinkat.h>
36#include <ignore-value.h> 34#include <ignore-value.h>
37#include <utimens.h> 35#include <utimens.h>
38 36
@@ -529,10 +527,10 @@ sys_subshell (void)
529#ifdef DOS_NT /* MW, Aug 1993 */ 527#ifdef DOS_NT /* MW, Aug 1993 */
530 getcwd (oldwd, sizeof oldwd); 528 getcwd (oldwd, sizeof oldwd);
531 if (sh == 0) 529 if (sh == 0)
532 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */ 530 sh = egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
533#endif 531#endif
534 if (sh == 0) 532 if (sh == 0)
535 sh = (char *) egetenv ("SHELL"); 533 sh = egetenv ("SHELL");
536 if (sh == 0) 534 if (sh == 0)
537 sh = "sh"; 535 sh = "sh";
538 536
@@ -2247,22 +2245,6 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
2247 2245
2248 return (bytes_written); 2246 return (bytes_written);
2249} 2247}
2250
2251static struct allocator const emacs_norealloc_allocator =
2252 { xmalloc, NULL, xfree, memory_full };
2253
2254/* Get the symbolic link value of FILENAME. Return a pointer to a
2255 NUL-terminated string. If readlink fails, return NULL and set
2256 errno. If the value fits in INITIAL_BUF, return INITIAL_BUF.
2257 Otherwise, allocate memory and return a pointer to that memory. If
2258 memory allocation fails, diagnose and fail without returning. If
2259 successful, store the length of the symbolic link into *LINKLEN. */
2260char *
2261emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
2262{
2263 return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE,
2264 &emacs_norealloc_allocator, careadlinkatcwd);
2265}
2266 2248
2267/* Return a struct timeval that is roughly equivalent to T. 2249/* Return a struct timeval that is roughly equivalent to T.
2268 Use the least timeval not less than T. 2250 Use the least timeval not less than T.
@@ -2559,12 +2541,12 @@ list_system_processes (void)
2559 return proclist; 2541 return proclist;
2560} 2542}
2561 2543
2562#elif defined BSD_SYSTEM 2544#elif defined DARWIN_OS || defined __FreeBSD__
2563 2545
2564Lisp_Object 2546Lisp_Object
2565list_system_processes (void) 2547list_system_processes (void)
2566{ 2548{
2567#if defined DARWIN_OS || defined __NetBSD__ || defined __OpenBSD__ 2549#ifdef DARWIN_OS
2568 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; 2550 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
2569#else 2551#else
2570 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC}; 2552 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
@@ -2590,10 +2572,8 @@ list_system_processes (void)
2590 len /= sizeof (struct kinfo_proc); 2572 len /= sizeof (struct kinfo_proc);
2591 for (i = 0; i < len; i++) 2573 for (i = 0; i < len; i++)
2592 { 2574 {
2593#if defined DARWIN_OS || defined __NetBSD__ 2575#ifdef DARWIN_OS
2594 proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.p_pid), proclist); 2576 proclist = Fcons (make_fixnum_or_float (procs[i].kp_proc.p_pid), proclist);
2595#elif defined __OpenBSD__
2596 proclist = Fcons (make_fixnum_or_float (procs[i].p_pid), proclist);
2597#else 2577#else
2598 proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist); 2578 proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist);
2599#endif 2579#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. */)
2374 t->display_info.tty->output = 0; 2374 t->display_info.tty->output = 0;
2375 2375
2376 if (FRAMEP (t->display_info.tty->top_frame)) 2376 if (FRAMEP (t->display_info.tty->top_frame))
2377 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0); 2377 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2378 2378
2379 } 2379 }
2380 2380
@@ -2444,7 +2444,7 @@ frame's terminal). */)
2444 get_tty_size (fileno (t->display_info.tty->input), &width, &height); 2444 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2445 if (width != old_width || height != old_height) 2445 if (width != old_width || height != old_height)
2446 change_frame_size (f, height, width, 0, 0, 0); 2446 change_frame_size (f, height, width, 0, 0, 0);
2447 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); 2447 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2448 } 2448 }
2449 2449
2450 set_tty_hooks (t); 2450 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)
393 if (termcap_name && (*termcap_name == '\\' 393 if (termcap_name && (*termcap_name == '\\'
394 || *termcap_name == '/' 394 || *termcap_name == '/'
395 || termcap_name[1] == ':')) 395 || termcap_name[1] == ':'))
396 dostounix_filename (termcap_name); 396 dostounix_filename (termcap_name, 0);
397#endif 397#endif
398 398
399 filep = termcap_name && valid_filename_p (termcap_name); 399 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)
125#define hard 1 125#define hard 1
126 126
127INTERVAL 127INTERVAL
128validate_interval_range (Lisp_Object object, Lisp_Object *begin, Lisp_Object *end, int force) 128validate_interval_range (Lisp_Object object, Lisp_Object *begin,
129 Lisp_Object *end, bool force)
129{ 130{
130 register INTERVAL i; 131 INTERVAL i;
131 ptrdiff_t searchpos; 132 ptrdiff_t searchpos;
132 133
133 CHECK_STRING_OR_BUFFER (object); 134 CHECK_STRING_OR_BUFFER (object);
@@ -198,14 +199,14 @@ validate_plist (Lisp_Object list)
198 199
199 if (CONSP (list)) 200 if (CONSP (list))
200 { 201 {
201 register int i; 202 bool odd_length = 0;
202 register Lisp_Object tail; 203 Lisp_Object tail;
203 for (i = 0, tail = list; CONSP (tail); i++) 204 for (tail = list; CONSP (tail); tail = XCDR (tail))
204 { 205 {
205 tail = XCDR (tail); 206 odd_length ^= 1;
206 QUIT; 207 QUIT;
207 } 208 }
208 if (i & 1) 209 if (odd_length)
209 error ("Odd length text property list"); 210 error ("Odd length text property list");
210 return list; 211 return list;
211 } 212 }
@@ -213,20 +214,19 @@ validate_plist (Lisp_Object list)
213 return Fcons (list, Fcons (Qnil, Qnil)); 214 return Fcons (list, Fcons (Qnil, Qnil));
214} 215}
215 216
216/* Return nonzero if interval I has all the properties, 217/* Return true if interval I has all the properties,
217 with the same values, of list PLIST. */ 218 with the same values, of list PLIST. */
218 219
219static int 220static bool
220interval_has_all_properties (Lisp_Object plist, INTERVAL i) 221interval_has_all_properties (Lisp_Object plist, INTERVAL i)
221{ 222{
222 register Lisp_Object tail1, tail2, sym1; 223 Lisp_Object tail1, tail2;
223 register int found;
224 224
225 /* Go through each element of PLIST. */ 225 /* Go through each element of PLIST. */
226 for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) 226 for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
227 { 227 {
228 sym1 = XCAR (tail1); 228 Lisp_Object sym1 = XCAR (tail1);
229 found = 0; 229 bool found = 0;
230 230
231 /* Go through I's plist, looking for sym1 */ 231 /* Go through I's plist, looking for sym1 */
232 for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) 232 for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
@@ -249,13 +249,13 @@ interval_has_all_properties (Lisp_Object plist, INTERVAL i)
249 return 1; 249 return 1;
250} 250}
251 251
252/* Return nonzero if the plist of interval I has any of the 252/* Return true if the plist of interval I has any of the
253 properties of PLIST, regardless of their values. */ 253 properties of PLIST, regardless of their values. */
254 254
255static int 255static bool
256interval_has_some_properties (Lisp_Object plist, INTERVAL i) 256interval_has_some_properties (Lisp_Object plist, INTERVAL i)
257{ 257{
258 register Lisp_Object tail1, tail2, sym; 258 Lisp_Object tail1, tail2, sym;
259 259
260 /* Go through each element of PLIST. */ 260 /* Go through each element of PLIST. */
261 for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) 261 for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
@@ -274,10 +274,10 @@ interval_has_some_properties (Lisp_Object plist, INTERVAL i)
274/* Return nonzero if the plist of interval I has any of the 274/* Return nonzero if the plist of interval I has any of the
275 property names in LIST, regardless of their values. */ 275 property names in LIST, regardless of their values. */
276 276
277static int 277static bool
278interval_has_some_properties_list (Lisp_Object list, INTERVAL i) 278interval_has_some_properties_list (Lisp_Object list, INTERVAL i)
279{ 279{
280 register Lisp_Object tail1, tail2, sym; 280 Lisp_Object tail1, tail2, sym;
281 281
282 /* Go through each element of LIST. */ 282 /* Go through each element of LIST. */
283 for (tail1 = list; CONSP (tail1); tail1 = XCDR (tail1)) 283 for (tail1 = list; CONSP (tail1); tail1 = XCDR (tail1))
@@ -358,15 +358,14 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
358 358
359 OBJECT should be the string or buffer the interval is in. 359 OBJECT should be the string or buffer the interval is in.
360 360
361 Return nonzero if this changes I (i.e., if any members of PLIST 361 Return true if this changes I (i.e., if any members of PLIST
362 are actually added to I's plist) */ 362 are actually added to I's plist) */
363 363
364static int 364static bool
365add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) 365add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object)
366{ 366{
367 Lisp_Object tail1, tail2, sym1, val1; 367 Lisp_Object tail1, tail2, sym1, val1;
368 register int changed = 0; 368 bool changed = 0;
369 register int found;
370 struct gcpro gcpro1, gcpro2, gcpro3; 369 struct gcpro gcpro1, gcpro2, gcpro3;
371 370
372 tail1 = plist; 371 tail1 = plist;
@@ -380,9 +379,9 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object)
380 /* Go through each element of PLIST. */ 379 /* Go through each element of PLIST. */
381 for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) 380 for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1)))
382 { 381 {
382 bool found = 0;
383 sym1 = XCAR (tail1); 383 sym1 = XCAR (tail1);
384 val1 = Fcar (XCDR (tail1)); 384 val1 = Fcar (XCDR (tail1));
385 found = 0;
386 385
387 /* Go through I's plist, looking for sym1 */ 386 /* Go through I's plist, looking for sym1 */
388 for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) 387 for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2)))
@@ -410,7 +409,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object)
410 409
411 /* I's property has a different value -- change it */ 410 /* I's property has a different value -- change it */
412 Fsetcar (this_cdr, val1); 411 Fsetcar (this_cdr, val1);
413 changed++; 412 changed = 1;
414 break; 413 break;
415 } 414 }
416 415
@@ -423,7 +422,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object)
423 sym1, Qnil, object); 422 sym1, Qnil, object);
424 } 423 }
425 set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist))); 424 set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist)));
426 changed++; 425 changed = 1;
427 } 426 }
428 } 427 }
429 428
@@ -437,14 +436,14 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object)
437 (If PLIST is non-nil, use that, otherwise use LIST.) 436 (If PLIST is non-nil, use that, otherwise use LIST.)
438 OBJECT is the string or buffer containing I. */ 437 OBJECT is the string or buffer containing I. */
439 438
440static int 439static bool
441remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object) 440remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object)
442{ 441{
443 register Lisp_Object tail1, tail2, sym, current_plist; 442 Lisp_Object tail1, tail2, sym, current_plist;
444 register int changed = 0; 443 bool changed = 0;
445 444
446 /* Nonzero means tail1 is a plist, otherwise it is a list. */ 445 /* True means tail1 is a plist, otherwise it is a list. */
447 int use_plist; 446 bool use_plist;
448 447
449 current_plist = i->plist; 448 current_plist = i->plist;
450 449
@@ -467,7 +466,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
467 object); 466 object);
468 467
469 current_plist = XCDR (XCDR (current_plist)); 468 current_plist = XCDR (XCDR (current_plist));
470 changed++; 469 changed = 1;
471 } 470 }
472 471
473 /* Go through I's plist, looking for SYM. */ 472 /* Go through I's plist, looking for SYM. */
@@ -483,7 +482,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
483 sym, XCAR (XCDR (this)), object); 482 sym, XCAR (XCDR (this)), object);
484 483
485 Fsetcdr (XCDR (tail2), XCDR (XCDR (this))); 484 Fsetcdr (XCDR (tail2), XCDR (XCDR (this)));
486 changed++; 485 changed = 1;
487 } 486 }
488 tail2 = this; 487 tail2 = this;
489 } 488 }
@@ -1129,10 +1128,11 @@ If OBJECT is a string, START and END are 0-based indices into it.
1129Return t if any property value actually changed, nil otherwise. */) 1128Return t if any property value actually changed, nil otherwise. */)
1130 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) 1129 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object)
1131{ 1130{
1132 register INTERVAL i, unchanged; 1131 INTERVAL i, unchanged;
1133 register ptrdiff_t s, len; 1132 ptrdiff_t s, len;
1134 register int modified = 0; 1133 bool modified = 0;
1135 struct gcpro gcpro1; 1134 struct gcpro gcpro1;
1135 bool first_time = 1;
1136 1136
1137 properties = validate_plist (properties); 1137 properties = validate_plist (properties);
1138 if (NILP (properties)) 1138 if (NILP (properties))
@@ -1141,6 +1141,7 @@ Return t if any property value actually changed, nil otherwise. */)
1141 if (NILP (object)) 1141 if (NILP (object))
1142 XSETBUFFER (object, current_buffer); 1142 XSETBUFFER (object, current_buffer);
1143 1143
1144 retry:
1144 i = validate_interval_range (object, &start, &end, hard); 1145 i = validate_interval_range (object, &start, &end, hard);
1145 if (!i) 1146 if (!i)
1146 return Qnil; 1147 return Qnil;
@@ -1152,31 +1153,50 @@ Return t if any property value actually changed, nil otherwise. */)
1152 and live buffers are always protected. */ 1153 and live buffers are always protected. */
1153 GCPRO1 (properties); 1154 GCPRO1 (properties);
1154 1155
1155 /* If we're not starting on an interval boundary, we have to 1156 /* If this interval already has the properties, we can skip it. */
1156 split this interval. */ 1157 if (interval_has_all_properties (properties, i))
1157 if (i->position != s)
1158 { 1158 {
1159 /* If this interval already has the properties, we can 1159 ptrdiff_t got = LENGTH (i) - (s - i->position);
1160 skip it. */ 1160
1161 if (interval_has_all_properties (properties, i)) 1161 do
1162 { 1162 {
1163 ptrdiff_t got = (LENGTH (i) - (s - i->position));
1164 if (got >= len) 1163 if (got >= len)
1165 RETURN_UNGCPRO (Qnil); 1164 RETURN_UNGCPRO (Qnil);
1166 len -= got; 1165 len -= got;
1167 i = next_interval (i); 1166 i = next_interval (i);
1167 got = LENGTH (i);
1168 } 1168 }
1169 else 1169 while (interval_has_all_properties (properties, i));
1170 }
1171 else if (i->position != s)
1172 {
1173 /* If we're not starting on an interval boundary, we have to
1174 split this interval. */
1175 unchanged = i;
1176 i = split_interval_right (unchanged, s - unchanged->position);
1177 copy_properties (unchanged, i);
1178 }
1179
1180 if (BUFFERP (object) && first_time)
1181 {
1182 ptrdiff_t prev_total_length = TOTAL_LENGTH (i);
1183 ptrdiff_t prev_pos = i->position;
1184
1185 modify_region (object, start, end);
1186 /* If someone called us recursively as a side effect of
1187 modify_region, and changed the intervals behind our back
1188 (could happen if lock_file, called by prepare_to_modify_buffer,
1189 triggers redisplay, and that calls add-text-properties again
1190 in the same buffer), we cannot continue with I, because its
1191 data changed. So we restart the interval analysis anew. */
1192 if (TOTAL_LENGTH (i) != prev_total_length
1193 || i->position != prev_pos)
1170 { 1194 {
1171 unchanged = i; 1195 first_time = 0;
1172 i = split_interval_right (unchanged, s - unchanged->position); 1196 goto retry;
1173 copy_properties (unchanged, i);
1174 } 1197 }
1175 } 1198 }
1176 1199
1177 if (BUFFERP (object))
1178 modify_region (object, start, end);
1179
1180 /* We are at the beginning of interval I, with LEN chars to scan. */ 1200 /* We are at the beginning of interval I, with LEN chars to scan. */
1181 for (;;) 1201 for (;;)
1182 { 1202 {
@@ -1195,7 +1215,8 @@ Return t if any property value actually changed, nil otherwise. */)
1195 signal_after_change (XINT (start), XINT (end) - XINT (start), 1215 signal_after_change (XINT (start), XINT (end) - XINT (start),
1196 XINT (end) - XINT (start)); 1216 XINT (end) - XINT (start));
1197 1217
1198 return modified ? Qt : Qnil; 1218 eassert (modified);
1219 return Qt;
1199 } 1220 }
1200 1221
1201 if (LENGTH (i) == len) 1222 if (LENGTH (i) == len)
@@ -1219,7 +1240,7 @@ Return t if any property value actually changed, nil otherwise. */)
1219 } 1240 }
1220 1241
1221 len -= LENGTH (i); 1242 len -= LENGTH (i);
1222 modified += add_properties (properties, i, object); 1243 modified |= add_properties (properties, i, object);
1223 i = next_interval (i); 1244 i = next_interval (i);
1224 } 1245 }
1225} 1246}
@@ -1423,13 +1444,15 @@ Return t if any property was actually removed, nil otherwise.
1423Use `set-text-properties' if you want to remove all text properties. */) 1444Use `set-text-properties' if you want to remove all text properties. */)
1424 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) 1445 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object)
1425{ 1446{
1426 register INTERVAL i, unchanged; 1447 INTERVAL i, unchanged;
1427 register ptrdiff_t s, len; 1448 ptrdiff_t s, len;
1428 register int modified = 0; 1449 bool modified = 0;
1450 bool first_time = 1;
1429 1451
1430 if (NILP (object)) 1452 if (NILP (object))
1431 XSETBUFFER (object, current_buffer); 1453 XSETBUFFER (object, current_buffer);
1432 1454
1455 retry:
1433 i = validate_interval_range (object, &start, &end, soft); 1456 i = validate_interval_range (object, &start, &end, soft);
1434 if (!i) 1457 if (!i)
1435 return Qnil; 1458 return Qnil;
@@ -1437,31 +1460,50 @@ Use `set-text-properties' if you want to remove all text properties. */)
1437 s = XINT (start); 1460 s = XINT (start);
1438 len = XINT (end) - s; 1461 len = XINT (end) - s;
1439 1462
1440 if (i->position != s) 1463 /* If there are no properties on this entire interval, return. */
1464 if (! interval_has_some_properties (properties, i))
1441 { 1465 {
1442 /* No properties on this first interval -- return if 1466 ptrdiff_t got = LENGTH (i) - (s - i->position);
1443 it covers the entire region. */ 1467
1444 if (! interval_has_some_properties (properties, i)) 1468 do
1445 { 1469 {
1446 ptrdiff_t got = (LENGTH (i) - (s - i->position));
1447 if (got >= len) 1470 if (got >= len)
1448 return Qnil; 1471 return Qnil;
1449 len -= got; 1472 len -= got;
1450 i = next_interval (i); 1473 i = next_interval (i);
1474 got = LENGTH (i);
1451 } 1475 }
1452 /* Split away the beginning of this interval; what we don't 1476 while (! interval_has_some_properties (properties, i));
1453 want to modify. */ 1477 }
1454 else 1478 /* Split away the beginning of this interval; what we don't
1479 want to modify. */
1480 else if (i->position != s)
1481 {
1482 unchanged = i;
1483 i = split_interval_right (unchanged, s - unchanged->position);
1484 copy_properties (unchanged, i);
1485 }
1486
1487 if (BUFFERP (object) && first_time)
1488 {
1489 ptrdiff_t prev_total_length = TOTAL_LENGTH (i);
1490 ptrdiff_t prev_pos = i->position;
1491
1492 modify_region (object, start, end);
1493 /* If someone called us recursively as a side effect of
1494 modify_region, and changed the intervals behind our back
1495 (could happen if lock_file, called by prepare_to_modify_buffer,
1496 triggers redisplay, and that calls add-text-properties again
1497 in the same buffer), we cannot continue with I, because its
1498 data changed. So we restart the interval analysis anew. */
1499 if (TOTAL_LENGTH (i) != prev_total_length
1500 || i->position != prev_pos)
1455 { 1501 {
1456 unchanged = i; 1502 first_time = 0;
1457 i = split_interval_right (unchanged, s - unchanged->position); 1503 goto retry;
1458 copy_properties (unchanged, i);
1459 } 1504 }
1460 } 1505 }
1461 1506
1462 if (BUFFERP (object))
1463 modify_region (object, start, end);
1464
1465 /* We are at the beginning of an interval, with len to scan */ 1507 /* We are at the beginning of an interval, with len to scan */
1466 for (;;) 1508 for (;;)
1467 { 1509 {
@@ -1470,7 +1512,13 @@ Use `set-text-properties' if you want to remove all text properties. */)
1470 if (LENGTH (i) >= len) 1512 if (LENGTH (i) >= len)
1471 { 1513 {
1472 if (! interval_has_some_properties (properties, i)) 1514 if (! interval_has_some_properties (properties, i))
1473 return modified ? Qt : Qnil; 1515 {
1516 eassert (modified);
1517 if (BUFFERP (object))
1518 signal_after_change (XINT (start), XINT (end) - XINT (start),
1519 XINT (end) - XINT (start));
1520 return Qt;
1521 }
1474 1522
1475 if (LENGTH (i) == len) 1523 if (LENGTH (i) == len)
1476 { 1524 {
@@ -1493,7 +1541,7 @@ Use `set-text-properties' if you want to remove all text properties. */)
1493 } 1541 }
1494 1542
1495 len -= LENGTH (i); 1543 len -= LENGTH (i);
1496 modified += remove_properties (properties, Qnil, i, object); 1544 modified |= remove_properties (properties, Qnil, i, object);
1497 i = next_interval (i); 1545 i = next_interval (i);
1498 } 1546 }
1499} 1547}
@@ -1508,9 +1556,9 @@ markers). If OBJECT is a string, START and END are 0-based indices into it.
1508Return t if any property was actually removed, nil otherwise. */) 1556Return t if any property was actually removed, nil otherwise. */)
1509 (Lisp_Object start, Lisp_Object end, Lisp_Object list_of_properties, Lisp_Object object) 1557 (Lisp_Object start, Lisp_Object end, Lisp_Object list_of_properties, Lisp_Object object)
1510{ 1558{
1511 register INTERVAL i, unchanged; 1559 INTERVAL i, unchanged;
1512 register ptrdiff_t s, len; 1560 ptrdiff_t s, len;
1513 register int modified = 0; 1561 bool modified = 0;
1514 Lisp_Object properties; 1562 Lisp_Object properties;
1515 properties = list_of_properties; 1563 properties = list_of_properties;
1516 1564
@@ -1524,26 +1572,28 @@ Return t if any property was actually removed, nil otherwise. */)
1524 s = XINT (start); 1572 s = XINT (start);
1525 len = XINT (end) - s; 1573 len = XINT (end) - s;
1526 1574
1527 if (i->position != s) 1575 /* If there are no properties on the interval, return. */
1576 if (! interval_has_some_properties_list (properties, i))
1528 { 1577 {
1529 /* No properties on this first interval -- return if 1578 ptrdiff_t got = LENGTH (i) - (s - i->position);
1530 it covers the entire region. */ 1579
1531 if (! interval_has_some_properties_list (properties, i)) 1580 do
1532 { 1581 {
1533 ptrdiff_t got = (LENGTH (i) - (s - i->position));
1534 if (got >= len) 1582 if (got >= len)
1535 return Qnil; 1583 return Qnil;
1536 len -= got; 1584 len -= got;
1537 i = next_interval (i); 1585 i = next_interval (i);
1586 got = LENGTH (i);
1538 } 1587 }
1539 /* Split away the beginning of this interval; what we don't 1588 while (! interval_has_some_properties_list (properties, i));
1540 want to modify. */ 1589 }
1541 else 1590 /* Split away the beginning of this interval; what we don't
1542 { 1591 want to modify. */
1543 unchanged = i; 1592 else if (i->position != s)
1544 i = split_interval_right (unchanged, s - unchanged->position); 1593 {
1545 copy_properties (unchanged, i); 1594 unchanged = i;
1546 } 1595 i = split_interval_right (unchanged, s - unchanged->position);
1596 copy_properties (unchanged, i);
1547 } 1597 }
1548 1598
1549 /* We are at the beginning of an interval, with len to scan. 1599 /* We are at the beginning of an interval, with len to scan.
@@ -1690,7 +1740,7 @@ int
1690text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer) 1740text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer)
1691{ 1741{
1692 Lisp_Object prev_pos, front_sticky; 1742 Lisp_Object prev_pos, front_sticky;
1693 int is_rear_sticky = 1, is_front_sticky = 0; /* defaults */ 1743 bool is_rear_sticky = 1, is_front_sticky = 0; /* defaults */
1694 Lisp_Object defalt = Fassq (prop, Vtext_property_default_nonsticky); 1744 Lisp_Object defalt = Fassq (prop, Vtext_property_default_nonsticky);
1695 1745
1696 if (NILP (buffer)) 1746 if (NILP (buffer))
@@ -1765,7 +1815,7 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_
1765 Lisp_Object stuff; 1815 Lisp_Object stuff;
1766 Lisp_Object plist; 1816 Lisp_Object plist;
1767 ptrdiff_t s, e, e2, p, len; 1817 ptrdiff_t s, e, e2, p, len;
1768 int modified = 0; 1818 bool modified = 0;
1769 struct gcpro gcpro1, gcpro2; 1819 struct gcpro gcpro1, gcpro2;
1770 1820
1771 i = validate_interval_range (src, &start, &end, soft); 1821 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_
1836 res = Fadd_text_properties (Fcar (res), Fcar (Fcdr (res)), 1886 res = Fadd_text_properties (Fcar (res), Fcar (Fcdr (res)),
1837 Fcar (Fcdr (Fcdr (res))), dest); 1887 Fcar (Fcdr (Fcdr (res))), dest);
1838 if (! NILP (res)) 1888 if (! NILP (res))
1839 modified++; 1889 modified = 1;
1840 stuff = Fcdr (stuff); 1890 stuff = Fcdr (stuff);
1841 } 1891 }
1842 1892
@@ -1907,33 +1957,28 @@ text_property_list (Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp
1907/* Add text properties to OBJECT from LIST. LIST is a list of triples 1957/* Add text properties to OBJECT from LIST. LIST is a list of triples
1908 (START END PLIST), where START and END are positions and PLIST is a 1958 (START END PLIST), where START and END are positions and PLIST is a
1909 property list containing the text properties to add. Adjust START 1959 property list containing the text properties to add. Adjust START
1910 and END positions by DELTA before adding properties. Value is 1960 and END positions by DELTA before adding properties. */
1911 non-zero if OBJECT was modified. */
1912 1961
1913int 1962void
1914add_text_properties_from_list (Lisp_Object object, Lisp_Object list, Lisp_Object delta) 1963add_text_properties_from_list (Lisp_Object object, Lisp_Object list, Lisp_Object delta)
1915{ 1964{
1916 struct gcpro gcpro1, gcpro2; 1965 struct gcpro gcpro1, gcpro2;
1917 int modified_p = 0;
1918 1966
1919 GCPRO2 (list, object); 1967 GCPRO2 (list, object);
1920 1968
1921 for (; CONSP (list); list = XCDR (list)) 1969 for (; CONSP (list); list = XCDR (list))
1922 { 1970 {
1923 Lisp_Object item, start, end, plist, tem; 1971 Lisp_Object item, start, end, plist;
1924 1972
1925 item = XCAR (list); 1973 item = XCAR (list);
1926 start = make_number (XINT (XCAR (item)) + XINT (delta)); 1974 start = make_number (XINT (XCAR (item)) + XINT (delta));
1927 end = make_number (XINT (XCAR (XCDR (item))) + XINT (delta)); 1975 end = make_number (XINT (XCAR (XCDR (item))) + XINT (delta));
1928 plist = XCAR (XCDR (XCDR (item))); 1976 plist = XCAR (XCDR (XCDR (item)));
1929 1977
1930 tem = Fadd_text_properties (start, end, plist, object); 1978 Fadd_text_properties (start, end, plist, object);
1931 if (!NILP (tem))
1932 modified_p = 1;
1933 } 1979 }
1934 1980
1935 UNGCPRO; 1981 UNGCPRO;
1936 return modified_p;
1937} 1982}
1938 1983
1939 1984
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! */
51#include "getpagesize.h" 51#include "getpagesize.h"
52 52
53#include <sys/types.h> 53#include <sys/types.h>
54#include <inttypes.h>
55#include <stdarg.h>
54#include <stdio.h> 56#include <stdio.h>
55#include <sys/stat.h> 57#include <sys/stat.h>
56#include <errno.h> 58#include <errno.h>
57#include <unistd.h> 59#include <unistd.h>
58#include <fcntl.h> 60#include <fcntl.h>
59 61
60#include "mem-limits.h" 62extern char _data[];
61 63extern char _text[];
62char *start_of_text (void); /* Start of text */
63
64extern int _data;
65extern int _text;
66 64
67#include <filehdr.h> 65#include <filehdr.h>
68#include <aouthdr.h> 66#include <aouthdr.h>
@@ -71,15 +69,15 @@ extern int _text;
71 69
72static struct filehdr f_hdr; /* File header */ 70static struct filehdr f_hdr; /* File header */
73static struct aouthdr f_ohdr; /* Optional file header (a.out) */ 71static struct aouthdr f_ohdr; /* Optional file header (a.out) */
74static long bias; /* Bias to add for growth */ 72static off_t bias; /* Bias to add for growth */
75static long lnnoptr; /* Pointer to line-number info within file */ 73static off_t lnnoptr; /* Pointer to line-number info within file */
76 74
77static long text_scnptr; 75static off_t text_scnptr;
78static long data_scnptr; 76static off_t data_scnptr;
79#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) 77#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
80static long load_scnptr; 78static off_t load_scnptr;
81static long orig_load_scnptr; 79static off_t orig_load_scnptr;
82static long orig_data_scnptr; 80static off_t orig_data_scnptr;
83static int unrelocate_symbols (int, int, const char *, const char *); 81static int unrelocate_symbols (int, int, const char *, const char *);
84 82
85#ifndef MAX_SECTIONS 83#ifndef MAX_SECTIONS
@@ -92,23 +90,30 @@ static int pagemask;
92 90
93#include "lisp.h" 91#include "lisp.h"
94 92
95static void 93static _Noreturn void
96report_error (const char *file, int fd) 94report_error (const char *file, int fd)
97{ 95{
98 if (fd) 96 if (fd)
99 close (fd); 97 {
98 int failed_errno = errno;
99 close (fd);
100 errno = failed_errno;
101 }
100 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); 102 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
101} 103}
102 104
103#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 105#define ERROR0(msg) report_error_1 (new, msg)
104#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 106#define ERROR1(msg,x) report_error_1 (new, msg, x)
105#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 107#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y)
106 108
107static void 109static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3)
108report_error_1 (int fd, const char *msg, int a1, int a2) 110report_error_1 (int fd, const char *msg, ...)
109{ 111{
112 va_list ap;
110 close (fd); 113 close (fd);
111 error (msg, a1, a2); 114 va_start (ap, msg);
115 verror (msg, ap);
116 va_end (ap);
112} 117}
113 118
114static int make_hdr (int, int, const char *, const char *); 119static int make_hdr (int, int, const char *, const char *);
@@ -163,8 +168,8 @@ make_hdr (int new, int a_out,
163 const char *a_name, const char *new_name) 168 const char *a_name, const char *new_name)
164{ 169{
165 int scns; 170 int scns;
166 unsigned int bss_start; 171 uintptr_t bss_start;
167 unsigned int data_start; 172 uintptr_t data_start;
168 173
169 struct scnhdr section[MAX_SECTIONS]; 174 struct scnhdr section[MAX_SECTIONS];
170 struct scnhdr * f_thdr; /* Text section header */ 175 struct scnhdr * f_thdr; /* Text section header */
@@ -179,17 +184,17 @@ make_hdr (int new, int a_out,
179 pagemask = getpagesize () - 1; 184 pagemask = getpagesize () - 1;
180 185
181 /* Adjust text/data boundary. */ 186 /* Adjust text/data boundary. */
182 data_start = (long) start_of_data (); 187 data_start = (uintptr_t) _data;
183 data_start = ADDR_CORRECT (data_start);
184 188
185 data_start = data_start & ~pagemask; /* (Down) to page boundary. */ 189 data_start = data_start & ~pagemask; /* (Down) to page boundary. */
186 190
187 bss_start = ADDR_CORRECT (sbrk (0)) + pagemask; 191 bss_start = (uintptr_t) sbrk (0) + pagemask;
188 bss_start &= ~ pagemask; 192 bss_start &= ~ pagemask;
189 193
190 if (data_start > bss_start) /* Can't have negative data size. */ 194 if (data_start > bss_start) /* Can't have negative data size. */
191 { 195 {
192 ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", 196 ERROR2 (("unexec: data_start (0x%"PRIxPTR
197 ") can't be greater than bss_start (0x%"PRIxPTR")"),
193 data_start, bss_start); 198 data_start, bss_start);
194 } 199 }
195 200
@@ -279,7 +284,7 @@ make_hdr (int new, int a_out,
279 284
280 /* fix scnptr's */ 285 /* fix scnptr's */
281 { 286 {
282 ulong ptr = section[0].s_scnptr; 287 off_t ptr = section[0].s_scnptr;
283 288
284 bias = -1; 289 bias = -1;
285 for (scns = 0; scns < f_hdr.f_nscns; scns++) 290 for (scns = 0; scns < f_hdr.f_nscns; scns++)
@@ -375,12 +380,12 @@ copy_text_and_data (int new)
375 char *end; 380 char *end;
376 char *ptr; 381 char *ptr;
377 382
378 lseek (new, (long) text_scnptr, SEEK_SET); 383 lseek (new, text_scnptr, SEEK_SET);
379 ptr = start_of_text () + text_scnptr; 384 ptr = _text + text_scnptr;
380 end = ptr + f_ohdr.tsize; 385 end = ptr + f_ohdr.tsize;
381 write_segment (new, ptr, end); 386 write_segment (new, ptr, end);
382 387
383 lseek (new, (long) data_scnptr, SEEK_SET); 388 lseek (new, data_scnptr, SEEK_SET);
384 ptr = (char *) f_ohdr.data_start; 389 ptr = (char *) f_ohdr.data_start;
385 end = ptr + f_ohdr.dsize; 390 end = ptr + f_ohdr.dsize;
386 write_segment (new, ptr, end); 391 write_segment (new, ptr, end);
@@ -393,7 +398,6 @@ static void
393write_segment (int new, char *ptr, char *end) 398write_segment (int new, char *ptr, char *end)
394{ 399{
395 int i, nwrite, ret; 400 int i, nwrite, ret;
396 char buf[80];
397 char zeros[UnexBlockSz]; 401 char zeros[UnexBlockSz];
398 402
399 for (i = 0; ptr < end;) 403 for (i = 0; ptr < end;)
@@ -414,9 +418,13 @@ write_segment (int new, char *ptr, char *end)
414 } 418 }
415 else if (nwrite != ret) 419 else if (nwrite != ret)
416 { 420 {
421 int write_errno = errno;
422 char buf[1000];
423 void *addr = ptr;
417 sprintf (buf, 424 sprintf (buf,
418 "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d", 425 "unexec write failure: addr %p, fileno %d, size 0x%x, wrote 0x%x, errno %d",
419 (unsigned long)ptr, new, nwrite, ret, errno); 426 addr, new, nwrite, ret, errno);
427 errno = write_errno;
420 PERROR (buf); 428 PERROR (buf);
421 } 429 }
422 i += nwrite; 430 i += nwrite;
@@ -537,13 +545,13 @@ unrelocate_symbols (int new, int a_out,
537 int i; 545 int i;
538 LDHDR ldhdr; 546 LDHDR ldhdr;
539 LDREL ldrel; 547 LDREL ldrel;
540 ulong t_reloc = (ulong) &_text - f_ohdr.text_start; 548 off_t t_reloc = (intptr_t) _text - f_ohdr.text_start;
541#ifndef ALIGN_DATA_RELOC 549#ifndef ALIGN_DATA_RELOC
542 ulong d_reloc = (ulong) &_data - f_ohdr.data_start; 550 off_t d_reloc = (intptr_t) _data - f_ohdr.data_start;
543#else 551#else
544 /* This worked (and was needed) before AIX 4.2. 552 /* This worked (and was needed) before AIX 4.2.
545 I have no idea why. -- Mike */ 553 I have no idea why. -- Mike */
546 ulong d_reloc = (ulong) &_data - ALIGN (f_ohdr.data_start, 2); 554 off_t d_reloc = (intptr_t) _data - ALIGN (f_ohdr.data_start, 2);
547#endif 555#endif
548 int * p; 556 int * p;
549 557
@@ -628,16 +636,3 @@ unrelocate_symbols (int new, int a_out,
628 } 636 }
629 return 0; 637 return 0;
630} 638}
631
632/*
633 * Return the address of the start of the text segment prior to
634 * doing an unexec. After unexec the return value is undefined.
635 * See crt0.c for further explanation and _start.
636 *
637 */
638
639char *
640start_of_text (void)
641{
642 return ((char *) 0x10000000);
643}
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
99 99
100#include <sys/file.h> 100#include <sys/file.h>
101 101
102#include "mem-limits.h" 102extern int etext;
103 103
104static long block_copy_start; /* Old executable start point */ 104static long block_copy_start; /* Old executable start point */
105static struct filehdr f_hdr; /* File header */ 105static struct filehdr f_hdr; /* File header */
@@ -168,7 +168,7 @@ make_hdr (int new, int a_out,
168 pagemask = getpagesize () - 1; 168 pagemask = getpagesize () - 1;
169 169
170 /* Adjust text/data boundary. */ 170 /* Adjust text/data boundary. */
171 data_start = (int) start_of_data (); 171 data_start = (int) DATA_START;
172 data_start = ADDR_CORRECT (data_start); 172 data_start = ADDR_CORRECT (data_start);
173 data_start = data_start & ~pagemask; /* (Down) to page boundary. */ 173 data_start = data_start & ~pagemask; /* (Down) to page boundary. */
174 174
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)
722 /* Ignore old_name, and get our actual location from the OS. */ 722 /* Ignore old_name, and get our actual location from the OS. */
723 if (!GetModuleFileName (NULL, in_filename, MAX_PATH)) 723 if (!GetModuleFileName (NULL, in_filename, MAX_PATH))
724 abort (); 724 abort ();
725 dostounix_filename (in_filename); 725 dostounix_filename (in_filename, 0);
726 strcpy (out_filename, in_filename); 726 strcpy (out_filename, in_filename);
727 727
728 /* Change the base of the output filename to match the requested name. */ 728 /* 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/>. */
19#include <config.h> 19#include <config.h>
20#include <unistd.h> /* for 'environ', on AIX */ 20#include <unistd.h> /* for 'environ', on AIX */
21#include "lisp.h" 21#include "lisp.h"
22#include "mem-limits.h" 22
23#ifdef MSDOS
24#include <dpmi.h>
25extern int etext;
26#endif
27
28/* Some systems need this before <sys/resource.h>. */
29#include <sys/types.h>
30
31#ifdef HAVE_SYS_RESOURCE_H
32# include <sys/time.h>
33# include <sys/resource.h>
34#else
35# if HAVE_SYS_VLIMIT_H
36# include <sys/vlimit.h> /* Obsolete, says glibc */
37# endif
38#endif
39
40/* Start of data. It is OK if this is approximate; it's used only as
41 a heuristic. */
42#ifdef DATA_START
43# define data_start ((char *) DATA_START)
44#else
45extern char data_start[];
46# ifndef HAVE_DATA_START
47/* Initialize to nonzero, so that it's put into data and not bss.
48 Link this file's object code first, so that this symbol is near the
49 start of data. */
50char data_start[1] = { 1 };
51# endif
52#endif
23 53
24/* 54/*
25 Level number of warnings already issued. 55 Level number of warnings already issued.
@@ -31,18 +61,24 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31enum warnlevel { not_warned, warned_75, warned_85, warned_95 }; 61enum warnlevel { not_warned, warned_75, warned_85, warned_95 };
32static enum warnlevel warnlevel; 62static enum warnlevel warnlevel;
33 63
34typedef void *POINTER;
35
36/* Function to call to issue a warning; 64/* Function to call to issue a warning;
37 0 means don't issue them. */ 65 0 means don't issue them. */
38static void (*warn_function) (const char *); 66static void (*warn_function) (const char *);
39 67
40/* Start of data space; can be changed by calling malloc_init. */ 68/* Start of data space; can be changed by calling memory_warnings. */
41static POINTER data_space_start; 69static char *data_space_start;
42 70
43/* Number of bytes of writable memory we can expect to be able to get. */ 71/* Number of bytes of writable memory we can expect to be able to get. */
44static size_t lim_data; 72static size_t lim_data;
45 73
74/* Return true if PTR cannot be represented as an Emacs Lisp object. */
75static bool
76exceeds_lisp_ptr (void *ptr)
77{
78 return (! USE_LSB_TAG
79 && VAL_MAX < UINTPTR_MAX
80 && ((uintptr_t) ptr & ~DATA_SEG_BITS) >> VALBITS != 0);
81}
46 82
47#ifdef HAVE_GETRLIMIT 83#ifdef HAVE_GETRLIMIT
48 84
@@ -123,11 +159,13 @@ static void
123check_memory_limits (void) 159check_memory_limits (void)
124{ 160{
125#ifdef REL_ALLOC 161#ifdef REL_ALLOC
126 extern POINTER (*real_morecore) (ptrdiff_t); 162 extern void *(*real_morecore) (ptrdiff_t);
163#else
164 void *(*real_morecore) (ptrdiff_t) = 0;
127#endif 165#endif
128 extern POINTER (*__morecore) (ptrdiff_t); 166 extern void *(*__morecore) (ptrdiff_t);
129 167
130 register POINTER cp; 168 char *cp;
131 size_t five_percent; 169 size_t five_percent;
132 size_t data_size; 170 size_t data_size;
133 enum warnlevel new_warnlevel; 171 enum warnlevel new_warnlevel;
@@ -137,13 +175,8 @@ check_memory_limits (void)
137 five_percent = lim_data / 20; 175 five_percent = lim_data / 20;
138 176
139 /* Find current end of memory and issue warning if getting near max */ 177 /* Find current end of memory and issue warning if getting near max */
140#ifdef REL_ALLOC 178 cp = (real_morecore ? real_morecore : __morecore) (0);
141 if (real_morecore) 179 data_size = cp - data_space_start;
142 cp = (char *) (*real_morecore) (0);
143 else
144#endif
145 cp = (char *) (*__morecore) (0);
146 data_size = (char *) cp - (char *) data_space_start;
147 180
148 if (!warn_function) 181 if (!warn_function)
149 return; 182 return;
@@ -190,62 +223,20 @@ check_memory_limits (void)
190 warnlevel = warned_85; 223 warnlevel = warned_85;
191 } 224 }
192 225
193 if (EXCEEDS_LISP_PTR (cp)) 226 if (exceeds_lisp_ptr (cp))
194 (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); 227 (*warn_function) ("Warning: memory in use exceeds lisp pointer size");
195} 228}
196 229
197#if !defined (CANNOT_DUMP) || !defined (SYSTEM_MALLOC)
198/* Some systems that cannot dump also cannot implement these. */
199
200/*
201 * Return the address of the start of the data segment prior to
202 * doing an unexec. After unexec the return value is undefined.
203 * See crt0.c for further information and definition of data_start.
204 *
205 * Apparently, on BSD systems this is etext at startup. On
206 * USG systems (swapping) this is highly mmu dependent and
207 * is also dependent on whether or not the program is running
208 * with shared text. Generally there is a (possibly large)
209 * gap between end of text and start of data with shared text.
210 *
211 */
212
213char *
214start_of_data (void)
215{
216#ifdef BSD_SYSTEM
217 extern char etext;
218 return (POINTER)(&etext);
219#elif defined DATA_START
220 return ((POINTER) DATA_START);
221#elif defined ORDINARY_LINK
222 /*
223 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
224 * data_start isn't defined. We take the address of environ, which
225 * is known to live at or near the start of the system crt0.c, and
226 * we don't sweat the handful of bytes that might lose.
227 */
228 return ((POINTER) &environ);
229#else
230 extern int data_start;
231 return ((POINTER) &data_start);
232#endif
233}
234#endif /* (not CANNOT_DUMP or not SYSTEM_MALLOC) */
235
236/* Enable memory usage warnings. 230/* Enable memory usage warnings.
237 START says where the end of pure storage is. 231 START says where the end of pure storage is.
238 WARNFUN specifies the function to call to issue a warning. */ 232 WARNFUN specifies the function to call to issue a warning. */
239 233
240void 234void
241memory_warnings (POINTER start, void (*warnfun) (const char *)) 235memory_warnings (void *start, void (*warnfun) (const char *))
242{ 236{
243 extern void (* __after_morecore_hook) (void); /* From gmalloc.c */ 237 extern void (* __after_morecore_hook) (void); /* From gmalloc.c */
244 238
245 if (start) 239 data_space_start = start ? start : data_start;
246 data_space_start = start;
247 else
248 data_space_start = start_of_data ();
249 240
250 warn_function = warnfun; 241 warn_function = warnfun;
251 __after_morecore_hook = check_memory_limits; 242 __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
532 switch (put_status) 532 switch (put_status)
533 { 533 {
534 case 1: 534 case 1:
535 message2 (no_mem_msg, sizeof (no_mem_msg) - 1, 0); 535 message3 (make_unibyte_string (no_mem_msg, sizeof (no_mem_msg) - 1));
536 break; 536 break;
537 case 2: 537 case 2:
538 message2 (binary_msg, sizeof (binary_msg) - 1, 0); 538 message3 (make_unibyte_string (binary_msg, sizeof (binary_msg) - 1));
539 break; 539 break;
540 case 3: 540 case 3:
541 message2 (system_error_msg, sizeof (system_error_msg) - 1, 0); 541 message3 (make_unibyte_string (system_error_msg, sizeof (system_error_msg) - 1));
542 break; 542 break;
543 } 543 }
544 sit_for (make_number (2), 0, 2); 544 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/>. */
37/* must include CRT headers *before* config.h */ 37/* must include CRT headers *before* config.h */
38 38
39#include <config.h> 39#include <config.h>
40#include <mbstring.h> /* for _mbspbrk */ 40#include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
41 41
42#undef access 42#undef access
43#undef chdir 43#undef chdir
@@ -1531,35 +1531,110 @@ srandom (int seed)
1531 srand (seed); 1531 srand (seed);
1532} 1532}
1533 1533
1534/* Current codepage for encoding file names. */
1535static int file_name_codepage;
1536
1537/* Return the maximum length in bytes of a multibyte character
1538 sequence encoded in the current ANSI codepage. This is required to
1539 correctly walk the encoded file names one character at a time. */
1540static int
1541max_filename_mbslen (void)
1542{
1543 /* A simple cache to avoid calling GetCPInfo every time we need to
1544 normalize a file name. The file-name encoding is not supposed to
1545 be changed too frequently, if ever. */
1546 static Lisp_Object last_file_name_encoding;
1547 static int last_max_mbslen;
1548 Lisp_Object current_encoding;
1549
1550 current_encoding = Vfile_name_coding_system;
1551 if (NILP (current_encoding))
1552 current_encoding = Vdefault_file_name_coding_system;
1553
1554 if (!EQ (last_file_name_encoding, current_encoding))
1555 {
1556 CPINFO cp_info;
1557
1558 last_file_name_encoding = current_encoding;
1559 /* Default to the current ANSI codepage. */
1560 file_name_codepage = w32_ansi_code_page;
1561 if (!NILP (current_encoding))
1562 {
1563 char *cpname = SDATA (SYMBOL_NAME (current_encoding));
1564 char *cp = NULL, *end;
1565 int cpnum;
1566
1567 if (strncmp (cpname, "cp", 2) == 0)
1568 cp = cpname + 2;
1569 else if (strncmp (cpname, "windows-", 8) == 0)
1570 cp = cpname + 8;
1571
1572 if (cp)
1573 {
1574 end = cp;
1575 cpnum = strtol (cp, &end, 10);
1576 if (cpnum && *end == '\0' && end - cp >= 2)
1577 file_name_codepage = cpnum;
1578 }
1579 }
1580
1581 if (!file_name_codepage)
1582 file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */
1583
1584 if (!GetCPInfo (file_name_codepage, &cp_info))
1585 {
1586 file_name_codepage = CP_ACP;
1587 if (!GetCPInfo (file_name_codepage, &cp_info))
1588 emacs_abort ();
1589 }
1590 last_max_mbslen = cp_info.MaxCharSize;
1591 }
1592
1593 return last_max_mbslen;
1594}
1534 1595
1535/* Normalize filename by converting all path separators to 1596/* Normalize filename by converting all path separators to
1536 the specified separator. Also conditionally convert upper 1597 the specified separator. Also conditionally convert upper
1537 case path name components to lower case. */ 1598 case path name components to lower case. */
1538 1599
1539static void 1600static void
1540normalize_filename (register char *fp, char path_sep) 1601normalize_filename (register char *fp, char path_sep, int multibyte)
1541{ 1602{
1542 char sep; 1603 char sep;
1543 char *elem; 1604 char *elem, *p2;
1605 int dbcs_p = max_filename_mbslen () > 1;
1606
1607 /* Multibyte file names are in the Emacs internal representation, so
1608 we can traverse them by bytes with no problems. */
1609 if (multibyte)
1610 dbcs_p = 0;
1544 1611
1545 /* Always lower-case drive letters a-z, even if the filesystem 1612 /* Always lower-case drive letters a-z, even if the filesystem
1546 preserves case in filenames. 1613 preserves case in filenames.
1547 This is so filenames can be compared by string comparison 1614 This is so filenames can be compared by string comparison
1548 functions that are case-sensitive. Even case-preserving filesystems 1615 functions that are case-sensitive. Even case-preserving filesystems
1549 do not distinguish case in drive letters. */ 1616 do not distinguish case in drive letters. */
1550 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z') 1617 if (dbcs_p)
1618 p2 = CharNextExA (file_name_codepage, fp, 0);
1619 else
1620 p2 = fp + 1;
1621
1622 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
1551 { 1623 {
1552 *fp += 'a' - 'A'; 1624 *fp += 'a' - 'A';
1553 fp += 2; 1625 fp += 2;
1554 } 1626 }
1555 1627
1556 if (NILP (Vw32_downcase_file_names)) 1628 if (multibyte || NILP (Vw32_downcase_file_names))
1557 { 1629 {
1558 while (*fp) 1630 while (*fp)
1559 { 1631 {
1560 if (*fp == '/' || *fp == '\\') 1632 if (*fp == '/' || *fp == '\\')
1561 *fp = path_sep; 1633 *fp = path_sep;
1562 fp++; 1634 if (!dbcs_p)
1635 fp++;
1636 else
1637 fp = CharNextExA (file_name_codepage, fp, 0);
1563 } 1638 }
1564 return; 1639 return;
1565 } 1640 }
@@ -1582,27 +1657,36 @@ normalize_filename (register char *fp, char path_sep)
1582 if (elem && elem != fp) 1657 if (elem && elem != fp)
1583 { 1658 {
1584 *fp = 0; /* temporary end of string */ 1659 *fp = 0; /* temporary end of string */
1585 _strlwr (elem); /* while we convert to lower case */ 1660 _mbslwr (elem); /* while we convert to lower case */
1586 } 1661 }
1587 *fp = sep; /* convert (or restore) path separator */ 1662 *fp = sep; /* convert (or restore) path separator */
1588 elem = fp + 1; /* next element starts after separator */ 1663 elem = fp + 1; /* next element starts after separator */
1589 sep = path_sep; 1664 sep = path_sep;
1590 } 1665 }
1591 } while (*fp++); 1666 if (*fp)
1667 {
1668 if (!dbcs_p)
1669 fp++;
1670 else
1671 fp = CharNextExA (file_name_codepage, fp, 0);
1672 }
1673 } while (*fp);
1592} 1674}
1593 1675
1594/* Destructively turn backslashes into slashes. */ 1676/* Destructively turn backslashes into slashes. MULTIBYTE non-zero
1677 means the file name is a multibyte string in Emacs's internal
1678 representation. */
1595void 1679void
1596dostounix_filename (register char *p) 1680dostounix_filename (register char *p, int multibyte)
1597{ 1681{
1598 normalize_filename (p, '/'); 1682 normalize_filename (p, '/', multibyte);
1599} 1683}
1600 1684
1601/* Destructively turn slashes into backslashes. */ 1685/* Destructively turn slashes into backslashes. */
1602void 1686void
1603unixtodos_filename (register char *p) 1687unixtodos_filename (register char *p)
1604{ 1688{
1605 normalize_filename (p, '\\'); 1689 normalize_filename (p, '\\', 0);
1606} 1690}
1607 1691
1608/* Remove all CR's that are followed by a LF. 1692/* Remove all CR's that are followed by a LF.
@@ -1653,12 +1737,17 @@ parse_root (char * name, char ** pPath)
1653 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) 1737 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1654 { 1738 {
1655 int slashes = 2; 1739 int slashes = 2;
1740 int dbcs_p = max_filename_mbslen () > 1;
1741
1656 name += 2; 1742 name += 2;
1657 do 1743 do
1658 { 1744 {
1659 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 1745 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1660 break; 1746 break;
1661 name++; 1747 if (dbcs_p)
1748 name = CharNextExA (file_name_codepage, name, 0);
1749 else
1750 name++;
1662 } 1751 }
1663 while ( *name ); 1752 while ( *name );
1664 if (IS_DIRECTORY_SEP (name[0])) 1753 if (IS_DIRECTORY_SEP (name[0]))
@@ -1723,7 +1812,7 @@ w32_get_long_filename (char * name, char * buf, int size)
1723 while (p != NULL && *p) 1812 while (p != NULL && *p)
1724 { 1813 {
1725 q = p; 1814 q = p;
1726 p = strchr (q, '\\'); 1815 p = _mbschr (q, '\\');
1727 if (p) *p = '\0'; 1816 if (p) *p = '\0';
1728 len = get_long_basename (full, o, size); 1817 len = get_long_basename (full, o, size);
1729 if (len > 0) 1818 if (len > 0)
@@ -1995,16 +2084,16 @@ init_environment (char ** argv)
1995 2084
1996 if (!GetModuleFileName (NULL, modname, MAX_PATH)) 2085 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1997 emacs_abort (); 2086 emacs_abort ();
1998 if ((p = strrchr (modname, '\\')) == NULL) 2087 if ((p = _mbsrchr (modname, '\\')) == NULL)
1999 emacs_abort (); 2088 emacs_abort ();
2000 *p = 0; 2089 *p = 0;
2001 2090
2002 if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) 2091 if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
2003 { 2092 {
2004 char buf[SET_ENV_BUF_SIZE]; 2093 char buf[SET_ENV_BUF_SIZE];
2005 2094
2006 *p = 0; 2095 *p = 0;
2007 for (p = modname; *p; p++) 2096 for (p = modname; *p; p = CharNext (p))
2008 if (*p == '\\') *p = '/'; 2097 if (*p == '\\') *p = '/';
2009 2098
2010 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); 2099 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
@@ -2019,17 +2108,17 @@ init_environment (char ** argv)
2019 || xstrcasecmp (p, "\\AMD64") == 0)) 2108 || xstrcasecmp (p, "\\AMD64") == 0))
2020 { 2109 {
2021 *p = 0; 2110 *p = 0;
2022 p = strrchr (modname, '\\'); 2111 p = _mbsrchr (modname, '\\');
2023 if (p != NULL) 2112 if (p != NULL)
2024 { 2113 {
2025 *p = 0; 2114 *p = 0;
2026 p = strrchr (modname, '\\'); 2115 p = _mbsrchr (modname, '\\');
2027 if (p && xstrcasecmp (p, "\\src") == 0) 2116 if (p && xstrcasecmp (p, "\\src") == 0)
2028 { 2117 {
2029 char buf[SET_ENV_BUF_SIZE]; 2118 char buf[SET_ENV_BUF_SIZE];
2030 2119
2031 *p = 0; 2120 *p = 0;
2032 for (p = modname; *p; p++) 2121 for (p = modname; *p; p = CharNext (p))
2033 if (*p == '\\') *p = '/'; 2122 if (*p == '\\') *p = '/';
2034 2123
2035 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); 2124 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
@@ -2140,7 +2229,7 @@ emacs_root_dir (void)
2140 emacs_abort (); 2229 emacs_abort ();
2141 strcpy (root_dir, p); 2230 strcpy (root_dir, p);
2142 root_dir[parse_root (root_dir, NULL)] = '\0'; 2231 root_dir[parse_root (root_dir, NULL)] = '\0';
2143 dostounix_filename (root_dir); 2232 dostounix_filename (root_dir, 0);
2144 return root_dir; 2233 return root_dir;
2145} 2234}
2146 2235
@@ -2564,12 +2653,23 @@ get_volume_info (const char * name, const char ** pPath)
2564 { 2653 {
2565 char *str = temp; 2654 char *str = temp;
2566 int slashes = 4; 2655 int slashes = 4;
2656 int dbcs_p = max_filename_mbslen () > 1;
2657
2567 rootname = temp; 2658 rootname = temp;
2568 do 2659 do
2569 { 2660 {
2570 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 2661 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2571 break; 2662 break;
2572 *str++ = *name++; 2663 if (!dbcs_p)
2664 *str++ = *name++;
2665 else
2666 {
2667 const char *p = name;
2668
2669 name = CharNextExA (file_name_codepage, name, 0);
2670 memcpy (str, p, name - p);
2671 str += name - p;
2672 }
2573 } 2673 }
2574 while ( *name ); 2674 while ( *name );
2575 2675
@@ -2732,7 +2832,7 @@ static char *read_unc_volume (HANDLE, char *, int);
2732static void close_unc_volume (HANDLE); 2832static void close_unc_volume (HANDLE);
2733 2833
2734DIR * 2834DIR *
2735opendir (char *filename) 2835opendir (const char *filename)
2736{ 2836{
2737 DIR *dirp; 2837 DIR *dirp;
2738 2838
@@ -2805,11 +2905,23 @@ readdir (DIR *dirp)
2805 { 2905 {
2806 char filename[MAXNAMLEN + 3]; 2906 char filename[MAXNAMLEN + 3];
2807 int ln; 2907 int ln;
2908 int dbcs_p = max_filename_mbslen () > 1;
2808 2909
2809 strcpy (filename, dir_pathname); 2910 strcpy (filename, dir_pathname);
2810 ln = strlen (filename) - 1; 2911 ln = strlen (filename) - 1;
2811 if (!IS_DIRECTORY_SEP (filename[ln])) 2912 if (!dbcs_p)
2812 strcat (filename, "\\"); 2913 {
2914 if (!IS_DIRECTORY_SEP (filename[ln]))
2915 strcat (filename, "\\");
2916 }
2917 else
2918 {
2919 char *end = filename + ln + 1;
2920 char *last_char = CharPrevExA (file_name_codepage, filename, end, 0);
2921
2922 if (!IS_DIRECTORY_SEP (*last_char))
2923 strcat (filename, "\\");
2924 }
2813 strcat (filename, "*"); 2925 strcat (filename, "*");
2814 2926
2815 /* Note: No need to resolve symlinks in FILENAME, because 2927 /* Note: No need to resolve symlinks in FILENAME, because
@@ -2860,15 +2972,22 @@ readdir (DIR *dirp)
2860 strcpy (dir_static.d_name, dir_find_data.cFileName); 2972 strcpy (dir_static.d_name, dir_find_data.cFileName);
2861 dir_static.d_namlen = strlen (dir_static.d_name); 2973 dir_static.d_namlen = strlen (dir_static.d_name);
2862 if (dir_is_fat) 2974 if (dir_is_fat)
2863 _strlwr (dir_static.d_name); 2975 _mbslwr (dir_static.d_name);
2864 else if (downcase) 2976 else if (downcase)
2865 { 2977 {
2866 register char *p; 2978 register char *p;
2867 for (p = dir_static.d_name; *p; p++) 2979 int dbcs_p = max_filename_mbslen () > 1;
2868 if (*p >= 'a' && *p <= 'z') 2980 for (p = dir_static.d_name; *p; )
2869 break; 2981 {
2982 if (*p >= 'a' && *p <= 'z')
2983 break;
2984 if (dbcs_p)
2985 p = CharNextExA (file_name_codepage, p, 0);
2986 else
2987 p++;
2988 }
2870 if (!*p) 2989 if (!*p)
2871 _strlwr (dir_static.d_name); 2990 _mbslwr (dir_static.d_name);
2872 } 2991 }
2873 2992
2874 return &dir_static; 2993 return &dir_static;
@@ -2907,6 +3026,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2907 DWORD bufsize = 512; 3026 DWORD bufsize = 512;
2908 char *buffer; 3027 char *buffer;
2909 char *ptr; 3028 char *ptr;
3029 int dbcs_p = max_filename_mbslen () > 1;
2910 3030
2911 count = 1; 3031 count = 1;
2912 buffer = alloca (bufsize); 3032 buffer = alloca (bufsize);
@@ -2917,7 +3037,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2917 /* WNetEnumResource returns \\resource\share...skip forward to "share". */ 3037 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
2918 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; 3038 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
2919 ptr += 2; 3039 ptr += 2;
2920 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; 3040 if (!dbcs_p)
3041 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
3042 else
3043 {
3044 while (*ptr && !IS_DIRECTORY_SEP (*ptr))
3045 ptr = CharNextExA (file_name_codepage, ptr, 0);
3046 }
2921 ptr++; 3047 ptr++;
2922 3048
2923 strncpy (readbuf, ptr, size); 3049 strncpy (readbuf, ptr, size);
@@ -2954,9 +3080,11 @@ logon_network_drive (const char *path)
2954{ 3080{
2955 NETRESOURCE resource; 3081 NETRESOURCE resource;
2956 char share[MAX_PATH]; 3082 char share[MAX_PATH];
2957 int i, n_slashes; 3083 int n_slashes;
2958 char drive[4]; 3084 char drive[4];
2959 UINT drvtype; 3085 UINT drvtype;
3086 char *p;
3087 int dbcs_p;
2960 3088
2961 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) 3089 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
2962 drvtype = DRIVE_REMOTE; 3090 drvtype = DRIVE_REMOTE;
@@ -2978,13 +3106,18 @@ logon_network_drive (const char *path)
2978 n_slashes = 2; 3106 n_slashes = 2;
2979 strncpy (share, path, MAX_PATH); 3107 strncpy (share, path, MAX_PATH);
2980 /* Truncate to just server and share name. */ 3108 /* Truncate to just server and share name. */
2981 for (i = 2; i < MAX_PATH; i++) 3109 dbcs_p = max_filename_mbslen () > 1;
3110 for (p = share + 2; *p && p < share + MAX_PATH; )
2982 { 3111 {
2983 if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) 3112 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
2984 { 3113 {
2985 share[i] = '\0'; 3114 *p = '\0';
2986 break; 3115 break;
2987 } 3116 }
3117 if (dbcs_p)
3118 p = CharNextExA (file_name_codepage, p, 0);
3119 else
3120 p++;
2988 } 3121 }
2989 3122
2990 resource.dwType = RESOURCETYPE_DISK; 3123 resource.dwType = RESOURCETYPE_DISK;
@@ -3087,14 +3220,6 @@ sys_chmod (const char * path, int mode)
3087} 3220}
3088 3221
3089int 3222int
3090sys_chown (const char *path, uid_t owner, gid_t group)
3091{
3092 if (sys_chmod (path, S_IREAD) == -1) /* check if file exists */
3093 return -1;
3094 return 0;
3095}
3096
3097int
3098sys_creat (const char * path, int mode) 3223sys_creat (const char * path, int mode)
3099{ 3224{
3100 return _creat (map_w32_filename (path, NULL), mode); 3225 return _creat (map_w32_filename (path, NULL), mode);
@@ -3277,17 +3402,27 @@ int
3277sys_open (const char * path, int oflag, int mode) 3402sys_open (const char * path, int oflag, int mode)
3278{ 3403{
3279 const char* mpath = map_w32_filename (path, NULL); 3404 const char* mpath = map_w32_filename (path, NULL);
3280 /* Try to open file without _O_CREAT, to be able to write to hidden 3405 int res = -1;
3281 and system files. Force all file handles to be 3406
3282 non-inheritable. */ 3407 /* If possible, try to open file without _O_CREAT, to be able to
3283 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); 3408 write to existing hidden and system files. Force all file
3284 if (res >= 0) 3409 handles to be non-inheritable. */
3285 return res; 3410 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
3286 return _open (mpath, oflag | _O_NOINHERIT, mode); 3411 res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
3412 if (res < 0)
3413 res = _open (mpath, oflag | _O_NOINHERIT, mode);
3414
3415 return res;
3416}
3417
3418int
3419fchmod (int fd, mode_t mode)
3420{
3421 return 0;
3287} 3422}
3288 3423
3289int 3424int
3290sys_rename (const char * oldname, const char * newname) 3425sys_rename_replace (const char *oldname, const char *newname, BOOL force)
3291{ 3426{
3292 BOOL result; 3427 BOOL result;
3293 char temp[MAX_PATH]; 3428 char temp[MAX_PATH];
@@ -3343,7 +3478,7 @@ sys_rename (const char * oldname, const char * newname)
3343 return -1; 3478 return -1;
3344 } 3479 }
3345 3480
3346 /* Emulate Unix behavior - newname is deleted if it already exists 3481 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
3347 (at least if it is a file; don't do this for directories). 3482 (at least if it is a file; don't do this for directories).
3348 3483
3349 Since we mustn't do this if we are just changing the case of the 3484 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)
3361 3496
3362 result = rename (temp, newname); 3497 result = rename (temp, newname);
3363 3498
3364 if (result < 0) 3499 if (result < 0 && force)
3365 { 3500 {
3366 DWORD w32err = GetLastError (); 3501 DWORD w32err = GetLastError ();
3367 3502
@@ -3401,6 +3536,12 @@ sys_rename (const char * oldname, const char * newname)
3401} 3536}
3402 3537
3403int 3538int
3539sys_rename (char const *old, char const *new)
3540{
3541 return sys_rename_replace (old, new, TRUE);
3542}
3543
3544int
3404sys_rmdir (const char * path) 3545sys_rmdir (const char * path)
3405{ 3546{
3406 return _rmdir (map_w32_filename (path, NULL)); 3547 return _rmdir (map_w32_filename (path, NULL));
@@ -3759,6 +3900,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3759 DWORD access_rights = 0; 3900 DWORD access_rights = 0;
3760 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; 3901 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
3761 FILETIME ctime, atime, wtime; 3902 FILETIME ctime, atime, wtime;
3903 int dbcs_p;
3762 3904
3763 if (path == NULL || buf == NULL) 3905 if (path == NULL || buf == NULL)
3764 { 3906 {
@@ -3956,6 +4098,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3956 did not ask for extra precision, resolving symlinks will fly 4098 did not ask for extra precision, resolving symlinks will fly
3957 in the face of that request, since the user then wants the 4099 in the face of that request, since the user then wants the
3958 lightweight version of the code. */ 4100 lightweight version of the code. */
4101 dbcs_p = max_filename_mbslen () > 1;
3959 rootdir = (path >= save_name + len - 1 4102 rootdir = (path >= save_name + len - 1
3960 && (IS_DIRECTORY_SEP (*path) || *path == 0)); 4103 && (IS_DIRECTORY_SEP (*path) || *path == 0));
3961 4104
@@ -3983,8 +4126,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3983 } 4126 }
3984 else if (rootdir) 4127 else if (rootdir)
3985 { 4128 {
3986 if (!IS_DIRECTORY_SEP (name[len-1])) 4129 if (!dbcs_p)
3987 strcat (name, "\\"); 4130 {
4131 if (!IS_DIRECTORY_SEP (name[len-1]))
4132 strcat (name, "\\");
4133 }
4134 else
4135 {
4136 char *end = name + len;
4137 char *n = CharPrevExA (file_name_codepage, name, end, 0);
4138
4139 if (!IS_DIRECTORY_SEP (*n))
4140 strcat (name, "\\");
4141 }
3988 if (GetDriveType (name) < 2) 4142 if (GetDriveType (name) < 2)
3989 { 4143 {
3990 errno = ENOENT; 4144 errno = ENOENT;
@@ -3996,15 +4150,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3996 } 4150 }
3997 else 4151 else
3998 { 4152 {
3999 if (IS_DIRECTORY_SEP (name[len-1])) 4153 if (!dbcs_p)
4000 name[len - 1] = 0; 4154 {
4155 if (IS_DIRECTORY_SEP (name[len-1]))
4156 name[len - 1] = 0;
4157 }
4158 else
4159 {
4160 char *end = name + len;
4161 char *n = CharPrevExA (file_name_codepage, name, end, 0);
4162
4163 if (IS_DIRECTORY_SEP (*n))
4164 *n = 0;
4165 }
4001 4166
4002 /* (This is hacky, but helps when doing file completions on 4167 /* (This is hacky, but helps when doing file completions on
4003 network drives.) Optimize by using information available from 4168 network drives.) Optimize by using information available from
4004 active readdir if possible. */ 4169 active readdir if possible. */
4005 len = strlen (dir_pathname); 4170 len = strlen (dir_pathname);
4006 if (IS_DIRECTORY_SEP (dir_pathname[len-1])) 4171 if (!dbcs_p)
4007 len--; 4172 {
4173 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
4174 len--;
4175 }
4176 else
4177 {
4178 char *end = dir_pathname + len;
4179 char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0);
4180
4181 if (IS_DIRECTORY_SEP (*n))
4182 len--;
4183 }
4008 if (dir_find_handle != INVALID_HANDLE_VALUE 4184 if (dir_find_handle != INVALID_HANDLE_VALUE
4009 && !(is_a_symlink && follow_symlinks) 4185 && !(is_a_symlink && follow_symlinks)
4010 && strnicmp (save_name, dir_pathname, len) == 0 4186 && strnicmp (save_name, dir_pathname, len) == 0
@@ -4110,6 +4286,30 @@ lstat (const char * path, struct stat * buf)
4110 return stat_worker (path, buf, 0); 4286 return stat_worker (path, buf, 0);
4111} 4287}
4112 4288
4289int
4290fstatat (int fd, char const *name, struct stat *st, int flags)
4291{
4292 /* Rely on a hack: an open directory is modeled as file descriptor 0.
4293 This is good enough for the current usage in Emacs, but is fragile.
4294
4295 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
4296 Gnulib does this and can serve as a model. */
4297 char fullname[MAX_PATH];
4298
4299 if (fd != AT_FDCWD)
4300 {
4301 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
4302 < 0)
4303 {
4304 errno = ENAMETOOLONG;
4305 return -1;
4306 }
4307 name = fullname;
4308 }
4309
4310 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
4311}
4312
4113/* Provide fstat and utime as well as stat for consistent handling of 4313/* Provide fstat and utime as well as stat for consistent handling of
4114 file timestamps. */ 4314 file timestamps. */
4115int 4315int
@@ -4164,13 +4364,23 @@ fstat (int desc, struct stat * buf)
4164 else 4364 else
4165 buf->st_ino = fake_inode; 4365 buf->st_ino = fake_inode;
4166 4366
4167 /* Consider files to belong to current user. 4367 /* If the caller so requested, get the true file owner and group.
4168 FIXME: this should use GetSecurityInfo API, but it is only 4368 Otherwise, consider the file to belong to the current user. */
4169 available for _WIN32_WINNT >= 0x501. */ 4369 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
4170 buf->st_uid = dflt_passwd.pw_uid; 4370 get_file_owner_and_group (NULL, buf);
4171 buf->st_gid = dflt_passwd.pw_gid; 4371 else
4172 strcpy (buf->st_uname, dflt_passwd.pw_name); 4372 {
4173 strcpy (buf->st_gname, dflt_group.gr_name); 4373 PSECURITY_DESCRIPTOR psd = NULL;
4374
4375 psd = get_file_security_desc_by_handle (fh);
4376 if (psd)
4377 {
4378 get_file_owner_and_group (psd, buf);
4379 LocalFree (psd);
4380 }
4381 else
4382 get_file_owner_and_group (NULL, buf);
4383 }
4174 4384
4175 buf->st_dev = info.dwVolumeSerialNumber; 4385 buf->st_dev = info.dwVolumeSerialNumber;
4176 buf->st_rdev = info.dwVolumeSerialNumber; 4386 buf->st_rdev = info.dwVolumeSerialNumber;
@@ -4265,6 +4475,7 @@ symlink (char const *filename, char const *linkname)
4265 char linkfn[MAX_PATH], *tgtfn; 4475 char linkfn[MAX_PATH], *tgtfn;
4266 DWORD flags = 0; 4476 DWORD flags = 0;
4267 int dir_access, filename_ends_in_slash; 4477 int dir_access, filename_ends_in_slash;
4478 int dbcs_p;
4268 4479
4269 /* Diagnostics follows Posix as much as possible. */ 4480 /* Diagnostics follows Posix as much as possible. */
4270 if (filename == NULL || linkname == NULL) 4481 if (filename == NULL || linkname == NULL)
@@ -4290,6 +4501,8 @@ symlink (char const *filename, char const *linkname)
4290 return -1; 4501 return -1;
4291 } 4502 }
4292 4503
4504 dbcs_p = max_filename_mbslen () > 1;
4505
4293 /* Note: since empty FILENAME was already rejected, we can safely 4506 /* Note: since empty FILENAME was already rejected, we can safely
4294 refer to FILENAME[1]. */ 4507 refer to FILENAME[1]. */
4295 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) 4508 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
@@ -4304,8 +4517,21 @@ symlink (char const *filename, char const *linkname)
4304 char tem[MAX_PATH]; 4517 char tem[MAX_PATH];
4305 char *p = linkfn + strlen (linkfn); 4518 char *p = linkfn + strlen (linkfn);
4306 4519
4307 while (p > linkfn && !IS_ANY_SEP (p[-1])) 4520 if (!dbcs_p)
4308 p--; 4521 {
4522 while (p > linkfn && !IS_ANY_SEP (p[-1]))
4523 p--;
4524 }
4525 else
4526 {
4527 char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0);
4528
4529 while (p > linkfn && !IS_ANY_SEP (*p1))
4530 {
4531 p = p1;
4532 p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0);
4533 }
4534 }
4309 if (p > linkfn) 4535 if (p > linkfn)
4310 strncpy (tem, linkfn, p - linkfn); 4536 strncpy (tem, linkfn, p - linkfn);
4311 tem[p - linkfn] = '\0'; 4537 tem[p - linkfn] = '\0';
@@ -4320,7 +4546,15 @@ symlink (char const *filename, char const *linkname)
4320 exist, but ends in a slash, we create a symlink to directory. If 4546 exist, but ends in a slash, we create a symlink to directory. If
4321 FILENAME exists and is a directory, we always create a symlink to 4547 FILENAME exists and is a directory, we always create a symlink to
4322 directory. */ 4548 directory. */
4323 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); 4549 if (!dbcs_p)
4550 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
4551 else
4552 {
4553 const char *end = filename + strlen (filename);
4554 const char *n = CharPrevExA (file_name_codepage, filename, end, 0);
4555
4556 filename_ends_in_slash = IS_DIRECTORY_SEP (*n);
4557 }
4324 if (dir_access == 0 || filename_ends_in_slash) 4558 if (dir_access == 0 || filename_ends_in_slash)
4325 flags = SYMBOLIC_LINK_FLAG_DIRECTORY; 4559 flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
4326 4560
@@ -4510,6 +4744,8 @@ readlink (const char *name, char *buf, size_t buf_size)
4510 WCHAR *lwname_src = 4744 WCHAR *lwname_src =
4511 reparse_data->SymbolicLinkReparseBuffer.PathBuffer 4745 reparse_data->SymbolicLinkReparseBuffer.PathBuffer
4512 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); 4746 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
4747 /* This updates file_name_codepage which we need below. */
4748 int dbcs_p = max_filename_mbslen () > 1;
4513 4749
4514 /* According to MSDN, PrintNameLength does not include the 4750 /* According to MSDN, PrintNameLength does not include the
4515 terminating null character. */ 4751 terminating null character. */
@@ -4517,9 +4753,7 @@ readlink (const char *name, char *buf, size_t buf_size)
4517 memcpy (lwname, lwname_src, lwname_len); 4753 memcpy (lwname, lwname_src, lwname_len);
4518 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ 4754 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */
4519 4755
4520 /* FIXME: Should we use the current file-name coding system 4756 lname_len = WideCharToMultiByte (file_name_codepage, 0, lwname, -1,
4521 instead of the fixed value of the ANSI codepage? */
4522 lname_len = WideCharToMultiByte (w32_ansi_code_page, 0, lwname, -1,
4523 lname, MAX_PATH, NULL, NULL); 4757 lname, MAX_PATH, NULL, NULL);
4524 if (!lname_len) 4758 if (!lname_len)
4525 { 4759 {
@@ -4545,18 +4779,33 @@ readlink (const char *name, char *buf, size_t buf_size)
4545 else 4779 else
4546 { 4780 {
4547 size_t size_to_copy = buf_size; 4781 size_t size_to_copy = buf_size;
4548 BYTE *p = lname; 4782 BYTE *p = lname, *p2;
4549 BYTE *pend = p + lname_len; 4783 BYTE *pend = p + lname_len;
4550 4784
4551 /* Normalize like dostounix_filename does, but we don't 4785 /* Normalize like dostounix_filename does, but we don't
4552 want to assume that lname is null-terminated. */ 4786 want to assume that lname is null-terminated. */
4553 if (*p && p[1] == ':' && *p >= 'A' && *p <= 'Z') 4787 if (dbcs_p)
4554 *p += 'a' - 'A'; 4788 p2 = CharNextExA (file_name_codepage, p, 0);
4789 else
4790 p2 = p + 1;
4791 if (*p && *p2 == ':' && *p >= 'A' && *p <= 'Z')
4792 {
4793 *p += 'a' - 'A';
4794 p += 2;
4795 }
4555 while (p <= pend) 4796 while (p <= pend)
4556 { 4797 {
4557 if (*p == '\\') 4798 if (*p == '\\')
4558 *p = '/'; 4799 *p = '/';
4559 ++p; 4800 if (dbcs_p)
4801 {
4802 p = CharNextExA (file_name_codepage, p, 0);
4803 /* CharNextExA doesn't advance at null character. */
4804 if (!*p)
4805 break;
4806 }
4807 else
4808 ++p;
4560 } 4809 }
4561 /* Testing for null-terminated LNAME is paranoia: 4810 /* Testing for null-terminated LNAME is paranoia:
4562 WideCharToMultiByte should always return a 4811 WideCharToMultiByte should always return a
@@ -4603,6 +4852,28 @@ readlink (const char *name, char *buf, size_t buf_size)
4603 return retval; 4852 return retval;
4604} 4853}
4605 4854
4855ssize_t
4856readlinkat (int fd, char const *name, char *buffer,
4857 size_t buffer_size)
4858{
4859 /* Rely on a hack: an open directory is modeled as file descriptor 0,
4860 as in fstatat. FIXME: Add proper support for readlinkat. */
4861 char fullname[MAX_PATH];
4862
4863 if (fd != AT_FDCWD)
4864 {
4865 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
4866 < 0)
4867 {
4868 errno = ENAMETOOLONG;
4869 return -1;
4870 }
4871 name = fullname;
4872 }
4873
4874 return readlink (name, buffer, buffer_size);
4875}
4876
4606/* If FILE is a symlink, return its target (stored in a static 4877/* If FILE is a symlink, return its target (stored in a static
4607 buffer); otherwise return FILE. 4878 buffer); otherwise return FILE.
4608 4879
@@ -4630,6 +4901,7 @@ chase_symlinks (const char *file)
4630 char link[MAX_PATH]; 4901 char link[MAX_PATH];
4631 ssize_t res, link_len; 4902 ssize_t res, link_len;
4632 int loop_count = 0; 4903 int loop_count = 0;
4904 int dbcs_p;
4633 4905
4634 if (is_windows_9x () == TRUE || !is_symlink (file)) 4906 if (is_windows_9x () == TRUE || !is_symlink (file))
4635 return (char *)file; 4907 return (char *)file;
@@ -4637,13 +4909,27 @@ chase_symlinks (const char *file)
4637 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) 4909 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0)
4638 return (char *)file; 4910 return (char *)file;
4639 4911
4912 dbcs_p = max_filename_mbslen () > 1;
4640 target[0] = '\0'; 4913 target[0] = '\0';
4641 do { 4914 do {
4642 4915
4643 /* Remove trailing slashes, as we want to resolve the last 4916 /* Remove trailing slashes, as we want to resolve the last
4644 non-trivial part of the link name. */ 4917 non-trivial part of the link name. */
4645 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) 4918 if (!dbcs_p)
4646 link[link_len--] = '\0'; 4919 {
4920 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
4921 link[link_len--] = '\0';
4922 }
4923 else if (link_len > 3)
4924 {
4925 char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0);
4926
4927 while (n >= link + 2 && IS_DIRECTORY_SEP (*n))
4928 {
4929 n[1] = '\0';
4930 n = CharPrevExA (file_name_codepage, link, n, 0);
4931 }
4932 }
4647 4933
4648 res = readlink (link, target, MAX_PATH); 4934 res = readlink (link, target, MAX_PATH);
4649 if (res > 0) 4935 if (res > 0)
@@ -4656,8 +4942,21 @@ chase_symlinks (const char *file)
4656 the symlink, then copy the result back to target. */ 4942 the symlink, then copy the result back to target. */
4657 char *p = link + link_len; 4943 char *p = link + link_len;
4658 4944
4659 while (p > link && !IS_ANY_SEP (p[-1])) 4945 if (!dbcs_p)
4660 p--; 4946 {
4947 while (p > link && !IS_ANY_SEP (p[-1]))
4948 p--;
4949 }
4950 else
4951 {
4952 char *p1 = CharPrevExA (file_name_codepage, link, p, 0);
4953
4954 while (p > link && !IS_ANY_SEP (*p1))
4955 {
4956 p = p1;
4957 p1 = CharPrevExA (file_name_codepage, link, p1, 0);
4958 }
4959 }
4661 strcpy (p, target); 4960 strcpy (p, target);
4662 strcpy (target, link); 4961 strcpy (target, link);
4663 } 4962 }
@@ -4858,50 +5157,57 @@ acl_set_file (const char *fname, acl_type_t type, acl_t acl)
4858 5157
4859 e = errno; 5158 e = errno;
4860 errno = 0; 5159 errno = 0;
4861 set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl); 5160 if (!set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl))
4862 err = GetLastError ();
4863 if (st)
4864 { 5161 {
4865 if (st >= 2) 5162 err = GetLastError ();
4866 restore_privilege (&old2);
4867 restore_privilege (&old1);
4868 revert_to_self ();
4869 }
4870
4871 if (errno == ENOTSUP)
4872 ;
4873 else if (err == ERROR_SUCCESS)
4874 {
4875 retval = 0;
4876 errno = e;
4877 }
4878 else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED)
4879 {
4880 /* Maybe the requested ACL and the one the file already has are
4881 identical, in which case we can silently ignore the
4882 failure. (And no, Windows doesn't.) */
4883 acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
4884 5163
4885 errno = EPERM; 5164 if (errno == ENOTSUP)
4886 if (current_acl) 5165 ;
5166 else if (err == ERROR_INVALID_OWNER
5167 || err == ERROR_NOT_ALL_ASSIGNED
5168 || err == ERROR_ACCESS_DENIED)
4887 { 5169 {
4888 char *acl_from = acl_to_text (current_acl, NULL); 5170 /* Maybe the requested ACL and the one the file already has
4889 char *acl_to = acl_to_text (acl, NULL); 5171 are identical, in which case we can silently ignore the
5172 failure. (And no, Windows doesn't.) */
5173 acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
4890 5174
4891 if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0) 5175 errno = EPERM;
5176 if (current_acl)
4892 { 5177 {
4893 retval = 0; 5178 char *acl_from = acl_to_text (current_acl, NULL);
4894 errno = e; 5179 char *acl_to = acl_to_text (acl, NULL);
5180
5181 if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
5182 {
5183 retval = 0;
5184 errno = e;
5185 }
5186 if (acl_from)
5187 acl_free (acl_from);
5188 if (acl_to)
5189 acl_free (acl_to);
5190 acl_free (current_acl);
4895 } 5191 }
4896 if (acl_from)
4897 acl_free (acl_from);
4898 if (acl_to)
4899 acl_free (acl_to);
4900 acl_free (current_acl);
4901 } 5192 }
5193 else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
5194 errno = ENOENT;
5195 else
5196 errno = EACCES;
5197 }
5198 else
5199 {
5200 retval = 0;
5201 errno = e;
5202 }
5203
5204 if (st)
5205 {
5206 if (st >= 2)
5207 restore_privilege (&old2);
5208 restore_privilege (&old1);
5209 revert_to_self ();
4902 } 5210 }
4903 else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
4904 errno = ENOENT;
4905 5211
4906 return retval; 5212 return retval;
4907} 5213}
@@ -4920,12 +5226,6 @@ careadlinkat (int fd, char const *filename,
4920 char linkname[MAX_PATH]; 5226 char linkname[MAX_PATH];
4921 ssize_t link_size; 5227 ssize_t link_size;
4922 5228
4923 if (fd != AT_FDCWD)
4924 {
4925 errno = EINVAL;
4926 return NULL;
4927 }
4928
4929 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname)); 5229 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname));
4930 5230
4931 if (link_size > 0) 5231 if (link_size > 0)
@@ -4943,14 +5243,6 @@ careadlinkat (int fd, char const *filename,
4943 return NULL; 5243 return NULL;
4944} 5244}
4945 5245
4946ssize_t
4947careadlinkatcwd (int fd, char const *filename, char *buffer,
4948 size_t buffer_size)
4949{
4950 (void) fd;
4951 return readlink (filename, buffer, buffer_size);
4952}
4953
4954 5246
4955/* Support for browsing other processes and their attributes. See 5247/* Support for browsing other processes and their attributes. See
4956 process.c for the Lisp bindings. */ 5248 process.c for the Lisp bindings. */
@@ -5288,10 +5580,8 @@ ltime (ULONGLONG time_100ns)
5288{ 5580{
5289 ULONGLONG time_sec = time_100ns / 10000000; 5581 ULONGLONG time_sec = time_100ns / 10000000;
5290 int subsec = time_100ns % 10000000; 5582 int subsec = time_100ns % 10000000;
5291 return list4 (make_number (time_sec >> 16), 5583 return list4i (time_sec >> 16, time_sec & 0xffff,
5292 make_number (time_sec & 0xffff), 5584 subsec / 10, subsec % 10 * 100000);
5293 make_number (subsec / 10),
5294 make_number (subsec % 10 * 100000));
5295} 5585}
5296 5586
5297#define U64_TO_LISP_TIME(time) ltime (time) 5587#define U64_TO_LISP_TIME(time) ltime (time)
@@ -5805,35 +6095,39 @@ init_winsock (int load_now)
5805 6095
5806int h_errno = 0; 6096int h_errno = 0;
5807 6097
5808/* function to set h_errno for compatibility; map winsock error codes to 6098/* Function to map winsock error codes to errno codes for those errno
5809 normal system codes where they overlap (non-overlapping definitions 6099 code defined in errno.h (errno values not defined by errno.h are
5810 are already in <sys/socket.h> */ 6100 already in nt/inc/sys/socket.h). */
5811static void 6101static void
5812set_errno (void) 6102set_errno (void)
5813{ 6103{
6104 int wsa_err;
6105
6106 h_errno = 0;
5814 if (winsock_lib == NULL) 6107 if (winsock_lib == NULL)
5815 h_errno = EINVAL; 6108 wsa_err = EINVAL;
5816 else 6109 else
5817 h_errno = pfn_WSAGetLastError (); 6110 wsa_err = pfn_WSAGetLastError ();
5818 6111
5819 switch (h_errno) 6112 switch (wsa_err)
5820 { 6113 {
5821 case WSAEACCES: h_errno = EACCES; break; 6114 case WSAEACCES: errno = EACCES; break;
5822 case WSAEBADF: h_errno = EBADF; break; 6115 case WSAEBADF: errno = EBADF; break;
5823 case WSAEFAULT: h_errno = EFAULT; break; 6116 case WSAEFAULT: errno = EFAULT; break;
5824 case WSAEINTR: h_errno = EINTR; break; 6117 case WSAEINTR: errno = EINTR; break;
5825 case WSAEINVAL: h_errno = EINVAL; break; 6118 case WSAEINVAL: errno = EINVAL; break;
5826 case WSAEMFILE: h_errno = EMFILE; break; 6119 case WSAEMFILE: errno = EMFILE; break;
5827 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break; 6120 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break;
5828 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break; 6121 case WSAENOTEMPTY: errno = ENOTEMPTY; break;
6122 default: errno = wsa_err; break;
5829 } 6123 }
5830 errno = h_errno;
5831} 6124}
5832 6125
5833static void 6126static void
5834check_errno (void) 6127check_errno (void)
5835{ 6128{
5836 if (h_errno == 0 && winsock_lib != NULL) 6129 h_errno = 0;
6130 if (winsock_lib != NULL)
5837 pfn_WSASetLastError (0); 6131 pfn_WSASetLastError (0);
5838} 6132}
5839 6133
@@ -5945,7 +6239,7 @@ sys_socket (int af, int type, int protocol)
5945 6239
5946 if (winsock_lib == NULL) 6240 if (winsock_lib == NULL)
5947 { 6241 {
5948 h_errno = ENETDOWN; 6242 errno = ENETDOWN;
5949 return INVALID_SOCKET; 6243 return INVALID_SOCKET;
5950 } 6244 }
5951 6245
@@ -6022,6 +6316,7 @@ socket_to_fd (SOCKET s)
6022 } 6316 }
6023 } 6317 }
6024 } 6318 }
6319 eassert (fd < MAXDESC);
6025 fd_info[fd].hnd = (HANDLE) s; 6320 fd_info[fd].hnd = (HANDLE) s;
6026 6321
6027 /* set our own internal flags */ 6322 /* set our own internal flags */
@@ -6050,8 +6345,9 @@ socket_to_fd (SOCKET s)
6050 /* clean up */ 6345 /* clean up */
6051 _close (fd); 6346 _close (fd);
6052 } 6347 }
6348 else
6053 pfn_closesocket (s); 6349 pfn_closesocket (s);
6054 h_errno = EMFILE; 6350 errno = EMFILE;
6055 return -1; 6351 return -1;
6056} 6352}
6057 6353
@@ -6060,7 +6356,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
6060{ 6356{
6061 if (winsock_lib == NULL) 6357 if (winsock_lib == NULL)
6062 { 6358 {
6063 h_errno = ENOTSOCK; 6359 errno = ENOTSOCK;
6064 return SOCKET_ERROR; 6360 return SOCKET_ERROR;
6065 } 6361 }
6066 6362
@@ -6072,7 +6368,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
6072 set_errno (); 6368 set_errno ();
6073 return rc; 6369 return rc;
6074 } 6370 }
6075 h_errno = ENOTSOCK; 6371 errno = ENOTSOCK;
6076 return SOCKET_ERROR; 6372 return SOCKET_ERROR;
6077} 6373}
6078 6374
@@ -6081,7 +6377,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
6081{ 6377{
6082 if (winsock_lib == NULL) 6378 if (winsock_lib == NULL)
6083 { 6379 {
6084 h_errno = ENOTSOCK; 6380 errno = ENOTSOCK;
6085 return SOCKET_ERROR; 6381 return SOCKET_ERROR;
6086 } 6382 }
6087 6383
@@ -6093,7 +6389,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
6093 set_errno (); 6389 set_errno ();
6094 return rc; 6390 return rc;
6095 } 6391 }
6096 h_errno = ENOTSOCK; 6392 errno = ENOTSOCK;
6097 return SOCKET_ERROR; 6393 return SOCKET_ERROR;
6098} 6394}
6099 6395
@@ -6122,12 +6418,20 @@ int
6122sys_gethostname (char * name, int namelen) 6418sys_gethostname (char * name, int namelen)
6123{ 6419{
6124 if (winsock_lib != NULL) 6420 if (winsock_lib != NULL)
6125 return pfn_gethostname (name, namelen); 6421 {
6422 int retval;
6423
6424 check_errno ();
6425 retval = pfn_gethostname (name, namelen);
6426 if (retval == SOCKET_ERROR)
6427 set_errno ();
6428 return retval;
6429 }
6126 6430
6127 if (namelen > MAX_COMPUTERNAME_LENGTH) 6431 if (namelen > MAX_COMPUTERNAME_LENGTH)
6128 return !GetComputerName (name, (DWORD *)&namelen); 6432 return !GetComputerName (name, (DWORD *)&namelen);
6129 6433
6130 h_errno = EFAULT; 6434 errno = EFAULT;
6131 return SOCKET_ERROR; 6435 return SOCKET_ERROR;
6132} 6436}
6133 6437
@@ -6135,17 +6439,24 @@ struct hostent *
6135sys_gethostbyname (const char * name) 6439sys_gethostbyname (const char * name)
6136{ 6440{
6137 struct hostent * host; 6441 struct hostent * host;
6442 int h_err = h_errno;
6138 6443
6139 if (winsock_lib == NULL) 6444 if (winsock_lib == NULL)
6140 { 6445 {
6141 h_errno = ENETDOWN; 6446 h_errno = NO_RECOVERY;
6447 errno = ENETDOWN;
6142 return NULL; 6448 return NULL;
6143 } 6449 }
6144 6450
6145 check_errno (); 6451 check_errno ();
6146 host = pfn_gethostbyname (name); 6452 host = pfn_gethostbyname (name);
6147 if (!host) 6453 if (!host)
6148 set_errno (); 6454 {
6455 set_errno ();
6456 h_errno = errno;
6457 }
6458 else
6459 h_errno = h_err;
6149 return host; 6460 return host;
6150} 6461}
6151 6462
@@ -6156,7 +6467,7 @@ sys_getservbyname (const char * name, const char * proto)
6156 6467
6157 if (winsock_lib == NULL) 6468 if (winsock_lib == NULL)
6158 { 6469 {
6159 h_errno = ENETDOWN; 6470 errno = ENETDOWN;
6160 return NULL; 6471 return NULL;
6161 } 6472 }
6162 6473
@@ -6172,7 +6483,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
6172{ 6483{
6173 if (winsock_lib == NULL) 6484 if (winsock_lib == NULL)
6174 { 6485 {
6175 h_errno = ENETDOWN; 6486 errno = ENETDOWN;
6176 return SOCKET_ERROR; 6487 return SOCKET_ERROR;
6177 } 6488 }
6178 6489
@@ -6184,7 +6495,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
6184 set_errno (); 6495 set_errno ();
6185 return rc; 6496 return rc;
6186 } 6497 }
6187 h_errno = ENOTSOCK; 6498 errno = ENOTSOCK;
6188 return SOCKET_ERROR; 6499 return SOCKET_ERROR;
6189} 6500}
6190 6501
@@ -6193,7 +6504,7 @@ sys_shutdown (int s, int how)
6193{ 6504{
6194 if (winsock_lib == NULL) 6505 if (winsock_lib == NULL)
6195 { 6506 {
6196 h_errno = ENETDOWN; 6507 errno = ENETDOWN;
6197 return SOCKET_ERROR; 6508 return SOCKET_ERROR;
6198 } 6509 }
6199 6510
@@ -6205,7 +6516,7 @@ sys_shutdown (int s, int how)
6205 set_errno (); 6516 set_errno ();
6206 return rc; 6517 return rc;
6207 } 6518 }
6208 h_errno = ENOTSOCK; 6519 errno = ENOTSOCK;
6209 return SOCKET_ERROR; 6520 return SOCKET_ERROR;
6210} 6521}
6211 6522
@@ -6214,7 +6525,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
6214{ 6525{
6215 if (winsock_lib == NULL) 6526 if (winsock_lib == NULL)
6216 { 6527 {
6217 h_errno = ENETDOWN; 6528 errno = ENETDOWN;
6218 return SOCKET_ERROR; 6529 return SOCKET_ERROR;
6219 } 6530 }
6220 6531
@@ -6227,7 +6538,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
6227 set_errno (); 6538 set_errno ();
6228 return rc; 6539 return rc;
6229 } 6540 }
6230 h_errno = ENOTSOCK; 6541 errno = ENOTSOCK;
6231 return SOCKET_ERROR; 6542 return SOCKET_ERROR;
6232} 6543}
6233 6544
@@ -6236,7 +6547,7 @@ sys_listen (int s, int backlog)
6236{ 6547{
6237 if (winsock_lib == NULL) 6548 if (winsock_lib == NULL)
6238 { 6549 {
6239 h_errno = ENETDOWN; 6550 errno = ENETDOWN;
6240 return SOCKET_ERROR; 6551 return SOCKET_ERROR;
6241 } 6552 }
6242 6553
@@ -6250,7 +6561,7 @@ sys_listen (int s, int backlog)
6250 fd_info[s].flags |= FILE_LISTEN; 6561 fd_info[s].flags |= FILE_LISTEN;
6251 return rc; 6562 return rc;
6252 } 6563 }
6253 h_errno = ENOTSOCK; 6564 errno = ENOTSOCK;
6254 return SOCKET_ERROR; 6565 return SOCKET_ERROR;
6255} 6566}
6256 6567
@@ -6259,7 +6570,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen)
6259{ 6570{
6260 if (winsock_lib == NULL) 6571 if (winsock_lib == NULL)
6261 { 6572 {
6262 h_errno = ENETDOWN; 6573 errno = ENETDOWN;
6263 return SOCKET_ERROR; 6574 return SOCKET_ERROR;
6264 } 6575 }
6265 6576
@@ -6271,7 +6582,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen)
6271 set_errno (); 6582 set_errno ();
6272 return rc; 6583 return rc;
6273 } 6584 }
6274 h_errno = ENOTSOCK; 6585 errno = ENOTSOCK;
6275 return SOCKET_ERROR; 6586 return SOCKET_ERROR;
6276} 6587}
6277 6588
@@ -6280,7 +6591,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
6280{ 6591{
6281 if (winsock_lib == NULL) 6592 if (winsock_lib == NULL)
6282 { 6593 {
6283 h_errno = ENETDOWN; 6594 errno = ENETDOWN;
6284 return -1; 6595 return -1;
6285 } 6596 }
6286 6597
@@ -6294,11 +6605,14 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
6294 else 6605 else
6295 fd = socket_to_fd (t); 6606 fd = socket_to_fd (t);
6296 6607
6297 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; 6608 if (fd >= 0)
6298 ResetEvent (fd_info[s].cp->char_avail); 6609 {
6610 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
6611 ResetEvent (fd_info[s].cp->char_avail);
6612 }
6299 return fd; 6613 return fd;
6300 } 6614 }
6301 h_errno = ENOTSOCK; 6615 errno = ENOTSOCK;
6302 return -1; 6616 return -1;
6303} 6617}
6304 6618
@@ -6308,7 +6622,7 @@ sys_recvfrom (int s, char * buf, int len, int flags,
6308{ 6622{
6309 if (winsock_lib == NULL) 6623 if (winsock_lib == NULL)
6310 { 6624 {
6311 h_errno = ENETDOWN; 6625 errno = ENETDOWN;
6312 return SOCKET_ERROR; 6626 return SOCKET_ERROR;
6313 } 6627 }
6314 6628
@@ -6320,7 +6634,7 @@ sys_recvfrom (int s, char * buf, int len, int flags,
6320 set_errno (); 6634 set_errno ();
6321 return rc; 6635 return rc;
6322 } 6636 }
6323 h_errno = ENOTSOCK; 6637 errno = ENOTSOCK;
6324 return SOCKET_ERROR; 6638 return SOCKET_ERROR;
6325} 6639}
6326 6640
@@ -6330,7 +6644,7 @@ sys_sendto (int s, const char * buf, int len, int flags,
6330{ 6644{
6331 if (winsock_lib == NULL) 6645 if (winsock_lib == NULL)
6332 { 6646 {
6333 h_errno = ENETDOWN; 6647 errno = ENETDOWN;
6334 return SOCKET_ERROR; 6648 return SOCKET_ERROR;
6335 } 6649 }
6336 6650
@@ -6342,7 +6656,7 @@ sys_sendto (int s, const char * buf, int len, int flags,
6342 set_errno (); 6656 set_errno ();
6343 return rc; 6657 return rc;
6344 } 6658 }
6345 h_errno = ENOTSOCK; 6659 errno = ENOTSOCK;
6346 return SOCKET_ERROR; 6660 return SOCKET_ERROR;
6347} 6661}
6348 6662
@@ -6353,7 +6667,7 @@ fcntl (int s, int cmd, int options)
6353{ 6667{
6354 if (winsock_lib == NULL) 6668 if (winsock_lib == NULL)
6355 { 6669 {
6356 h_errno = ENETDOWN; 6670 errno = ENETDOWN;
6357 return -1; 6671 return -1;
6358 } 6672 }
6359 6673
@@ -6372,11 +6686,11 @@ fcntl (int s, int cmd, int options)
6372 } 6686 }
6373 else 6687 else
6374 { 6688 {
6375 h_errno = EINVAL; 6689 errno = EINVAL;
6376 return SOCKET_ERROR; 6690 return SOCKET_ERROR;
6377 } 6691 }
6378 } 6692 }
6379 h_errno = ENOTSOCK; 6693 errno = ENOTSOCK;
6380 return SOCKET_ERROR; 6694 return SOCKET_ERROR;
6381} 6695}
6382 6696
@@ -6442,15 +6756,15 @@ sys_close (int fd)
6442 } 6756 }
6443 } 6757 }
6444 6758
6759 if (fd >= 0 && fd < MAXDESC)
6760 fd_info[fd].flags = 0;
6761
6445 /* Note that sockets do not need special treatment here (at least on 6762 /* Note that sockets do not need special treatment here (at least on
6446 NT and Windows 95 using the standard tcp/ip stacks) - it appears that 6763 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
6447 closesocket is equivalent to CloseHandle, which is to be expected 6764 closesocket is equivalent to CloseHandle, which is to be expected
6448 because socket handles are fully fledged kernel handles. */ 6765 because socket handles are fully fledged kernel handles. */
6449 rc = _close (fd); 6766 rc = _close (fd);
6450 6767
6451 if (rc == 0 && fd < MAXDESC)
6452 fd_info[fd].flags = 0;
6453
6454 return rc; 6768 return rc;
6455} 6769}
6456 6770
@@ -6513,6 +6827,7 @@ sys_pipe (int * phandles)
6513 { 6827 {
6514 _close (phandles[0]); 6828 _close (phandles[0]);
6515 _close (phandles[1]); 6829 _close (phandles[1]);
6830 errno = EMFILE;
6516 rc = -1; 6831 rc = -1;
6517 } 6832 }
6518 else 6833 else
@@ -6586,19 +6901,31 @@ _sys_read_ahead (int fd)
6586 6901
6587 /* Configure timeouts for blocking read. */ 6902 /* Configure timeouts for blocking read. */
6588 if (!GetCommTimeouts (hnd, &ct)) 6903 if (!GetCommTimeouts (hnd, &ct))
6589 return STATUS_READ_ERROR; 6904 {
6905 cp->status = STATUS_READ_ERROR;
6906 return STATUS_READ_ERROR;
6907 }
6590 ct.ReadIntervalTimeout = 0; 6908 ct.ReadIntervalTimeout = 0;
6591 ct.ReadTotalTimeoutMultiplier = 0; 6909 ct.ReadTotalTimeoutMultiplier = 0;
6592 ct.ReadTotalTimeoutConstant = 0; 6910 ct.ReadTotalTimeoutConstant = 0;
6593 if (!SetCommTimeouts (hnd, &ct)) 6911 if (!SetCommTimeouts (hnd, &ct))
6594 return STATUS_READ_ERROR; 6912 {
6913 cp->status = STATUS_READ_ERROR;
6914 return STATUS_READ_ERROR;
6915 }
6595 6916
6596 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl)) 6917 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
6597 { 6918 {
6598 if (GetLastError () != ERROR_IO_PENDING) 6919 if (GetLastError () != ERROR_IO_PENDING)
6599 return STATUS_READ_ERROR; 6920 {
6921 cp->status = STATUS_READ_ERROR;
6922 return STATUS_READ_ERROR;
6923 }
6600 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE)) 6924 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
6601 return STATUS_READ_ERROR; 6925 {
6926 cp->status = STATUS_READ_ERROR;
6927 return STATUS_READ_ERROR;
6928 }
6602 } 6929 }
6603 } 6930 }
6604 else if (fd_info[fd].flags & FILE_SOCKET) 6931 else if (fd_info[fd].flags & FILE_SOCKET)
@@ -6794,7 +7121,7 @@ sys_read (int fd, char * buffer, unsigned int count)
6794 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); 7121 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
6795 if (waiting == 0 && nchars == 0) 7122 if (waiting == 0 && nchars == 0)
6796 { 7123 {
6797 h_errno = errno = EWOULDBLOCK; 7124 errno = EWOULDBLOCK;
6798 return -1; 7125 return -1;
6799 } 7126 }
6800 7127
@@ -7506,47 +7833,26 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
7506ssize_t 7833ssize_t
7507emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz) 7834emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
7508{ 7835{
7509 int n, sc, err; 7836 int n, err;
7510 SELECT_TYPE fdset; 7837 SELECT_TYPE fdset;
7511 EMACS_TIME timeout; 7838 EMACS_TIME timeout;
7512 struct Lisp_Process *process = (struct Lisp_Process *)p; 7839 struct Lisp_Process *process = (struct Lisp_Process *)p;
7513 int fd = process->infd; 7840 int fd = process->infd;
7514 7841
7515 for (;;) 7842 n = sys_read (fd, (char*)buf, sz);
7516 {
7517 n = sys_read (fd, (char*)buf, sz);
7518 7843
7519 if (n >= 0) 7844 if (n >= 0)
7520 return n; 7845 return n;
7521 7846
7522 err = errno; 7847 err = errno;
7523 7848
7524 if (err == EWOULDBLOCK) 7849 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
7525 { 7850 if (err == EWOULDBLOCK)
7526 /* Set a small timeout. */ 7851 err = EAGAIN;
7527 timeout = make_emacs_time (1, 0);
7528 FD_ZERO (&fdset);
7529 FD_SET ((int)fd, &fdset);
7530
7531 /* Use select with the timeout to poll the selector. */
7532 sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
7533 &timeout, NULL);
7534
7535 if (sc > 0)
7536 continue; /* Try again. */
7537
7538 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN.
7539 Also accept select return 0 as an indicator to EAGAIN. */
7540 if (sc == 0 || errno == EWOULDBLOCK)
7541 err = EAGAIN;
7542 else
7543 err = errno; /* Other errors are just passed on. */
7544 }
7545 7852
7546 emacs_gnutls_transport_set_errno (process->gnutls_state, err); 7853 emacs_gnutls_transport_set_errno (process->gnutls_state, err);
7547 7854
7548 return -1; 7855 return -1;
7549 }
7550} 7856}
7551 7857
7552ssize_t 7858ssize_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 **);
180extern void check_windows_init_file (void); 180extern void check_windows_init_file (void);
181extern void syms_of_ntproc (void); 181extern void syms_of_ntproc (void);
182extern void syms_of_ntterm (void); 182extern void syms_of_ntterm (void);
183extern void dostounix_filename (register char *); 183extern void dostounix_filename (register char *, int);
184extern void unixtodos_filename (register char *); 184extern void unixtodos_filename (register char *);
185extern BOOL init_winsock (int load_now); 185extern BOOL init_winsock (int load_now);
186extern void srandom (int); 186extern void srandom (int);
187extern int random (void); 187extern int random (void);
188 188
189extern int fchmod (int, mode_t);
190extern int sys_rename_replace (char const *, char const *, BOOL);
189extern int sys_pipe (int *); 191extern int sys_pipe (int *);
190 192
191extern void set_process_dir (char *); 193extern 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,
4587 CHECK_STRING (color); 4587 CHECK_STRING (color);
4588 4588
4589 if (w32_defined_color (f, SDATA (color), &foo, 0)) 4589 if (w32_defined_color (f, SDATA (color), &foo, 0))
4590 return list3 (make_number ((GetRValue (foo.pixel) << 8) 4590 return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel),
4591 | GetRValue (foo.pixel)), 4591 (GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel),
4592 make_number ((GetGValue (foo.pixel) << 8) 4592 (GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel));
4593 | GetGValue (foo.pixel)),
4594 make_number ((GetBValue (foo.pixel) << 8)
4595 | GetBValue (foo.pixel)));
4596 else 4593 else
4597 return Qnil; 4594 return Qnil;
4598} 4595}
@@ -4718,9 +4715,7 @@ DISPLAY should be either a frame or a display name (a string).
4718If omitted or nil, that stands for the selected frame's display. */) 4715If omitted or nil, that stands for the selected frame's display. */)
4719 (Lisp_Object display) 4716 (Lisp_Object display)
4720{ 4717{
4721 return Fcons (make_number (w32_major_version), 4718 return list3i (w32_major_version, w32_minor_version, w32_build_number);
4722 Fcons (make_number (w32_minor_version),
4723 Fcons (make_number (w32_build_number), Qnil)));
4724} 4719}
4725 4720
4726DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, 4721DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
@@ -5943,7 +5938,7 @@ Text larger than the specified size is clipped. */)
5943 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 5938 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
5944 5939
5945 /* Let redisplay know that we have made the frame visible already. */ 5940 /* Let redisplay know that we have made the frame visible already. */
5946 f->async_visible = 1; 5941 SET_FRAME_VISIBLE (f, 1);
5947 5942
5948 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE); 5943 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
5949 } 5944 }
@@ -6254,7 +6249,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
6254 /* we get one of the two final 0 bytes for free. */ 6249 /* we get one of the two final 0 bytes for free. */
6255 1 + sizeof (wchar_t) * wcslen (filename_buf))); 6250 1 + sizeof (wchar_t) * wcslen (filename_buf)));
6256#else /* !NTGUI_UNICODE */ 6251#else /* !NTGUI_UNICODE */
6257 dostounix_filename (filename_buf); 6252 dostounix_filename (filename_buf, 0);
6258 filename = DECODE_FILE (build_string (filename_buf)); 6253 filename = DECODE_FILE (build_string (filename_buf));
6259#endif /* NTGUI_UNICODE */ 6254#endif /* NTGUI_UNICODE */
6260 6255
@@ -6484,12 +6479,12 @@ w32_parse_hot_key (Lisp_Object key)
6484 6479
6485 CHECK_VECTOR (key); 6480 CHECK_VECTOR (key);
6486 6481
6487 if (XFASTINT (Flength (key)) != 1) 6482 if (ASIZE (key) != 1)
6488 return Qnil; 6483 return Qnil;
6489 6484
6490 GCPRO1 (key); 6485 GCPRO1 (key);
6491 6486
6492 c = Faref (key, make_number (0)); 6487 c = AREF (key, 0);
6493 6488
6494 if (CONSP (c) && lucid_event_type_list_p (c)) 6489 if (CONSP (c) && lucid_event_type_list_p (c))
6495 c = Fevent_convert_list (c); 6490 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)
98#ifdef _WIN64 98#ifdef _WIN64
99 size_t size = 0x4000000000i64; /* start by asking for 32GB */ 99 size_t size = 0x4000000000i64; /* start by asking for 32GB */
100#else 100#else
101 size_t size = 0x80000000; /* start by asking for 2GB */ 101 /* We used to start with 2GB here, but on Windows 7 that would leave
102 too little room in the address space for threads started by
103 Windows on our behalf, e.g. when we pop up the file selection
104 dialog. */
105 size_t size = 0x68000000; /* start by asking for 1.7GB */
102#endif 106#endif
103 void *ptr = NULL; 107 void *ptr = NULL;
104 108
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,
442This arranges for filesystem events pertaining to FILE to be reported 442This arranges for filesystem events pertaining to FILE to be reported
443to Emacs. Use `w32notify-rm-watch' to cancel the watch. 443to Emacs. Use `w32notify-rm-watch' to cancel the watch.
444 444
445Value is a descriptor for the added watch, or nil if the file 445Value is a descriptor for the added watch. If the file cannot be
446cannot be watched. 446watched for some reason, this function signals a `file-error' error.
447 447
448FILTER is a list of conditions for reporting an event. It can include 448FILTER is a list of conditions for reporting an event. It can include
449the following symbols: 449the following symbols:
@@ -476,7 +476,13 @@ following:
476 'renamed-from' -- a file was renamed whose old name was FILE 476 'renamed-from' -- a file was renamed whose old name was FILE
477 'renamed-to' -- a file was renamed and its new name is FILE 477 'renamed-to' -- a file was renamed and its new name is FILE
478 478
479FILE is the name of the file whose event is being reported. */) 479FILE is the name of the file whose event is being reported.
480
481Note that some networked filesystems, such as Samba-mounted Unix
482volumes, might not send notifications about file changes. In these
483cases, this function will return a valid descriptor, but notifications
484will never come in. Volumes shared from remote Windows machines do
485generate notifications correctly, though. */)
480 (Lisp_Object file, Lisp_Object filter, Lisp_Object callback) 486 (Lisp_Object file, Lisp_Object filter, Lisp_Object callback)
481{ 487{
482 Lisp_Object encoded_file, watch_object, watch_descriptor; 488 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)
803 if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL) 803 if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL)
804 goto Initialize; 804 goto Initialize;
805 if (child_proc_count == MAX_CHILDREN) 805 if (child_proc_count == MAX_CHILDREN)
806 {
807 int i = 0;
808 child_process *dead_cp = NULL;
809
810 DebPrint (("new_child: No vacant slots, looking for dead processes\n"));
811 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
812 if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
813 {
814 DWORD status = 0;
815
816 if (!GetExitCodeProcess (cp->procinfo.hProcess, &status))
817 {
818 DebPrint (("new_child.GetExitCodeProcess: error %lu for PID %lu\n",
819 GetLastError (), cp->procinfo.dwProcessId));
820 status = STILL_ACTIVE;
821 }
822 if (status != STILL_ACTIVE
823 || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0)
824 {
825 DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n",
826 cp->procinfo.dwProcessId, cp->fd));
827 CloseHandle (cp->procinfo.hProcess);
828 cp->procinfo.hProcess = NULL;
829 CloseHandle (cp->procinfo.hThread);
830 cp->procinfo.hThread = NULL;
831 /* Free up to 2 dead slots at a time, so that if we
832 have a lot of them, they will eventually all be
833 freed when the tornado ends. */
834 if (i == 0)
835 dead_cp = cp;
836 else
837 break;
838 i++;
839 }
840 }
841 if (dead_cp)
842 {
843 cp = dead_cp;
844 goto Initialize;
845 }
846 }
847 if (child_proc_count == MAX_CHILDREN)
806 return NULL; 848 return NULL;
807 cp = &child_procs[child_proc_count++]; 849 cp = &child_procs[child_proc_count++];
808 850
809 Initialize: 851 Initialize:
852 /* Last opportunity to avoid leaking handles before we forget them
853 for good. */
854 if (cp->procinfo.hProcess)
855 CloseHandle (cp->procinfo.hProcess);
856 if (cp->procinfo.hThread)
857 CloseHandle (cp->procinfo.hThread);
810 memset (cp, 0, sizeof (*cp)); 858 memset (cp, 0, sizeof (*cp));
811 cp->fd = -1; 859 cp->fd = -1;
812 cp->pid = -1; 860 cp->pid = -1;
@@ -979,8 +1027,9 @@ reader_thread (void *arg)
979 read-ahead has completed, whether successfully or not. */ 1027 read-ahead has completed, whether successfully or not. */
980 if (!SetEvent (cp->char_avail)) 1028 if (!SetEvent (cp->char_avail))
981 { 1029 {
982 DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n", 1030 DebPrint (("reader_thread.SetEvent(0x%x) failed with %lu for fd %ld (PID %d)\n",
983 GetLastError (), cp->fd)); 1031 (DWORD_PTR)cp->char_avail, GetLastError (),
1032 cp->fd, cp->pid));
984 return 1; 1033 return 1;
985 } 1034 }
986 1035
@@ -1541,7 +1590,6 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
1541 child_process *cp; 1590 child_process *cp;
1542 int is_dos_app, is_cygnus_app, is_gui_app; 1591 int is_dos_app, is_cygnus_app, is_gui_app;
1543 int do_quoting = 0; 1592 int do_quoting = 0;
1544 char escape_char;
1545 /* We pass our process ID to our children by setting up an environment 1593 /* We pass our process ID to our children by setting up an environment
1546 variable in their environment. */ 1594 variable in their environment. */
1547 char ppid_env_var_buffer[64]; 1595 char ppid_env_var_buffer[64];
@@ -1554,6 +1602,8 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
1554 Some extra whitespace characters need quoting in Cygwin programs, 1602 Some extra whitespace characters need quoting in Cygwin programs,
1555 so this list is conditionally modified below. */ 1603 so this list is conditionally modified below. */
1556 char *sepchars = " \t*?"; 1604 char *sepchars = " \t*?";
1605 /* This is for native w32 apps; modified below for Cygwin apps. */
1606 char escape_char = '\\';
1557 1607
1558 /* We don't care about the other modes */ 1608 /* We don't care about the other modes */
1559 if (mode != _P_NOWAIT) 1609 if (mode != _P_NOWAIT)
@@ -2007,7 +2057,7 @@ count_children:
2007 /* Some child_procs might be sockets; ignore them. Also some 2057 /* Some child_procs might be sockets; ignore them. Also some
2008 children may have died already, but we haven't finished reading 2058 children may have died already, but we haven't finished reading
2009 the process output; ignore them too. */ 2059 the process output; ignore them too. */
2010 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess 2060 if ((CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
2011 && (cp->fd < 0 2061 && (cp->fd < 0
2012 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 2062 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0
2013 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) 2063 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
@@ -2213,12 +2263,42 @@ sys_kill (pid_t pid, int sig)
2213 pid = -pid; 2263 pid = -pid;
2214 2264
2215 /* Only handle signals that will result in the process dying */ 2265 /* Only handle signals that will result in the process dying */
2216 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) 2266 if (sig != 0
2267 && sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
2217 { 2268 {
2218 errno = EINVAL; 2269 errno = EINVAL;
2219 return -1; 2270 return -1;
2220 } 2271 }
2221 2272
2273 if (sig == 0)
2274 {
2275 /* It will take _some_ time before PID 4 or less on Windows will
2276 be Emacs... */
2277 if (pid <= 4)
2278 {
2279 errno = EPERM;
2280 return -1;
2281 }
2282 proc_hand = OpenProcess (PROCESS_QUERY_INFORMATION, 0, pid);
2283 if (proc_hand == NULL)
2284 {
2285 DWORD err = GetLastError ();
2286
2287 switch (err)
2288 {
2289 case ERROR_ACCESS_DENIED: /* existing process, but access denied */
2290 errno = EPERM;
2291 return -1;
2292 case ERROR_INVALID_PARAMETER: /* process PID does not exist */
2293 errno = ESRCH;
2294 return -1;
2295 }
2296 }
2297 else
2298 CloseHandle (proc_hand);
2299 return 0;
2300 }
2301
2222 cp = find_child_pid (pid); 2302 cp = find_child_pid (pid);
2223 if (cp == NULL) 2303 if (cp == NULL)
2224 { 2304 {
@@ -2557,8 +2637,9 @@ All path elements in FILENAME are converted to their short names. */)
2557 if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0) 2637 if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
2558 return Qnil; 2638 return Qnil;
2559 2639
2560 dostounix_filename (shortname); 2640 dostounix_filename (shortname, 0);
2561 2641
2642 /* No need to DECODE_FILE, because 8.3 names are pure ASCII. */
2562 return build_string (shortname); 2643 return build_string (shortname);
2563} 2644}
2564 2645
@@ -2585,7 +2666,7 @@ All path elements in FILENAME are converted to their long names. */)
2585 if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH)) 2666 if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
2586 return Qnil; 2667 return Qnil;
2587 2668
2588 dostounix_filename (longname); 2669 dostounix_filename (longname, 0);
2589 2670
2590 /* If we were passed only a drive, make sure that a slash is not appended 2671 /* If we were passed only a drive, make sure that a slash is not appended
2591 for consistency with directories. Allow for drive mapping via SUBST 2672 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;
191 191
192/* Incremented by w32_read_socket whenever it really tries to read 192/* Incremented by w32_read_socket whenever it really tries to read
193 events. */ 193 events. */
194#ifdef __STDC__
195static int volatile input_signal_count; 194static int volatile input_signal_count;
196#else
197static int input_signal_count;
198#endif
199 195
200#ifdef CYGWIN 196#ifdef CYGWIN
201int w32_message_fd = -1; 197int w32_message_fd = -1;
@@ -4319,24 +4315,25 @@ w32_read_socket (struct terminal *terminal,
4319 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f, 4315 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4320 SDATA (f->name))); 4316 SDATA (f->name)));
4321 } 4317 }
4322 else if (f->async_visible != 1) 4318 else if (FRAME_VISIBLE_P (f) != 1)
4323 { 4319 {
4320 bool iconified = FRAME_ICONIFIED_P (f);
4321
4324 /* Definitely not obscured, so mark as visible. */ 4322 /* Definitely not obscured, so mark as visible. */
4325 f->async_visible = 1; 4323 SET_FRAME_VISIBLE (f, 1);
4326 f->async_iconified = 0; 4324 SET_FRAME_ICONIFIED (f, 0);
4327 SET_FRAME_GARBAGED (f); 4325 SET_FRAME_GARBAGED (f);
4328 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f, 4326 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4329 SDATA (f->name))); 4327 SDATA (f->name)));
4330 4328
4331 /* WM_PAINT serves as MapNotify as well, so report 4329 /* WM_PAINT serves as MapNotify as well, so report
4332 visibility changes properly. */ 4330 visibility changes properly. */
4333 if (f->iconified) 4331 if (iconified)
4334 { 4332 {
4335 inev.kind = DEICONIFY_EVENT; 4333 inev.kind = DEICONIFY_EVENT;
4336 XSETFRAME (inev.frame_or_window, f); 4334 XSETFRAME (inev.frame_or_window, f);
4337 } 4335 }
4338 else if (! NILP (Vframe_list) 4336 else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list)))
4339 && ! NILP (XCDR (Vframe_list)))
4340 /* Force a redisplay sooner or later to update the 4337 /* Force a redisplay sooner or later to update the
4341 frame titles in case this is the second frame. */ 4338 frame titles in case this is the second frame. */
4342 record_asynch_buffer_change (); 4339 record_asynch_buffer_change ();
@@ -4379,7 +4376,7 @@ w32_read_socket (struct terminal *terminal,
4379 case WM_SYSKEYDOWN: 4376 case WM_SYSKEYDOWN:
4380 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 4377 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4381 4378
4382 if (f && !f->iconified) 4379 if (f && !FRAME_ICONIFIED_P (f))
4383 { 4380 {
4384 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) 4381 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4385 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window)) 4382 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
@@ -4404,7 +4401,7 @@ w32_read_socket (struct terminal *terminal,
4404 case WM_CHAR: 4401 case WM_CHAR:
4405 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 4402 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4406 4403
4407 if (f && !f->iconified) 4404 if (f && !FRAME_ICONIFIED_P (f))
4408 { 4405 {
4409 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) 4406 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4410 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window)) 4407 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
@@ -4482,7 +4479,7 @@ w32_read_socket (struct terminal *terminal,
4482 case WM_APPCOMMAND: 4479 case WM_APPCOMMAND:
4483 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 4480 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4484 4481
4485 if (f && !f->iconified) 4482 if (f && !FRAME_ICONIFIED_P (f))
4486 { 4483 {
4487 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) 4484 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4488 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window)) 4485 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
@@ -4722,7 +4719,7 @@ w32_read_socket (struct terminal *terminal,
4722 case WM_MOVE: 4719 case WM_MOVE:
4723 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 4720 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4724 4721
4725 if (f && !f->async_iconified) 4722 if (f && !FRAME_ICONIFIED_P (f))
4726 { 4723 {
4727 int x, y; 4724 int x, y;
4728 4725
@@ -4770,8 +4767,8 @@ w32_read_socket (struct terminal *terminal,
4770 switch (msg.msg.wParam) 4767 switch (msg.msg.wParam)
4771 { 4768 {
4772 case SIZE_MINIMIZED: 4769 case SIZE_MINIMIZED:
4773 f->async_visible = 0; 4770 SET_FRAME_VISIBLE (f, 0);
4774 f->async_iconified = 1; 4771 SET_FRAME_ICONIFIED (f, 1);
4775 4772
4776 inev.kind = ICONIFY_EVENT; 4773 inev.kind = ICONIFY_EVENT;
4777 XSETFRAME (inev.frame_or_window, f); 4774 XSETFRAME (inev.frame_or_window, f);
@@ -4779,40 +4776,44 @@ w32_read_socket (struct terminal *terminal,
4779 4776
4780 case SIZE_MAXIMIZED: 4777 case SIZE_MAXIMIZED:
4781 case SIZE_RESTORED: 4778 case SIZE_RESTORED:
4782 f->async_visible = 1; 4779 {
4783 f->async_iconified = 0; 4780 bool iconified = FRAME_ICONIFIED_P (f);
4784
4785 /* wait_reading_process_output will notice this and update
4786 the frame's display structures. */
4787 SET_FRAME_GARBAGED (f);
4788 4781
4789 if (f->iconified) 4782 SET_FRAME_VISIBLE (f, 1);
4790 { 4783 SET_FRAME_ICONIFIED (f, 0);
4791 int x, y;
4792 4784
4793 /* Reset top and left positions of the Window 4785 /* wait_reading_process_output will notice this
4794 here since Windows sends a WM_MOVE message 4786 and update the frame's display structures. */
4795 BEFORE telling us the Window is minimized 4787 SET_FRAME_GARBAGED (f);
4796 when the Window is iconified, with 3000,3000
4797 as the co-ords. */
4798 x_real_positions (f, &x, &y);
4799 f->left_pos = x;
4800 f->top_pos = y;
4801 4788
4802 inev.kind = DEICONIFY_EVENT; 4789 if (iconified)
4803 XSETFRAME (inev.frame_or_window, f); 4790 {
4804 } 4791 int x, y;
4805 else if (! NILP (Vframe_list) 4792
4806 && ! NILP (XCDR (Vframe_list))) 4793 /* Reset top and left positions of the Window
4807 /* Force a redisplay sooner or later 4794 here since Windows sends a WM_MOVE message
4808 to update the frame titles 4795 BEFORE telling us the Window is minimized
4809 in case this is the second frame. */ 4796 when the Window is iconified, with 3000,3000
4810 record_asynch_buffer_change (); 4797 as the co-ords. */
4798 x_real_positions (f, &x, &y);
4799 f->left_pos = x;
4800 f->top_pos = y;
4801
4802 inev.kind = DEICONIFY_EVENT;
4803 XSETFRAME (inev.frame_or_window, f);
4804 }
4805 else if (! NILP (Vframe_list)
4806 && ! NILP (XCDR (Vframe_list)))
4807 /* Force a redisplay sooner or later
4808 to update the frame titles
4809 in case this is the second frame. */
4810 record_asynch_buffer_change ();
4811 }
4811 break; 4812 break;
4812 } 4813 }
4813 } 4814 }
4814 4815
4815 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED) 4816 if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED)
4816 { 4817 {
4817 RECT rect; 4818 RECT rect;
4818 int rows; 4819 int rows;
@@ -5040,12 +5041,13 @@ w32_read_socket (struct terminal *terminal,
5040 continue; 5041 continue;
5041 5042
5042 /* Check "visible" frames and mark each as obscured or not. 5043 /* Check "visible" frames and mark each as obscured or not.
5043 Note that async_visible is nonzero for unobscured and 5044 Note that visible is nonzero for unobscured and obscured
5044 obscured frames, but zero for hidden and iconified frames. */ 5045 frames, but zero for hidden and iconified frames. */
5045 if (FRAME_W32_P (f) && f->async_visible) 5046 if (FRAME_W32_P (f) && FRAME_VISIBLE_P (f))
5046 { 5047 {
5047 RECT clipbox; 5048 RECT clipbox;
5048 HDC hdc; 5049 HDC hdc;
5050 bool obscured;
5049 5051
5050 enter_crit (); 5052 enter_crit ();
5051 /* Query clipping rectangle for the entire window area 5053 /* Query clipping rectangle for the entire window area
@@ -5059,31 +5061,28 @@ w32_read_socket (struct terminal *terminal,
5059 ReleaseDC (FRAME_W32_WINDOW (f), hdc); 5061 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
5060 leave_crit (); 5062 leave_crit ();
5061 5063
5062 if (clipbox.right == clipbox.left 5064 obscured = FRAME_OBSCURED_P (f);
5063 || clipbox.bottom == clipbox.top) 5065
5066 if (clipbox.right == clipbox.left || clipbox.bottom == clipbox.top)
5064 { 5067 {
5065 /* Frame has become completely obscured so mark as 5068 /* Frame has become completely obscured so mark as such (we
5066 such (we do this by setting async_visible to 2 so 5069 do this by setting visible to 2 so that FRAME_VISIBLE_P
5067 that FRAME_VISIBLE_P is still true, but redisplay 5070 is still true, but redisplay will skip it). */
5068 will skip it). */ 5071 SET_FRAME_VISIBLE (f, 2);
5069 f->async_visible = 2;
5070 5072
5071 if (!FRAME_OBSCURED_P (f)) 5073 if (!obscured)
5072 { 5074 DebPrint (("frame %p (%s) obscured\n", f, SDATA (f->name)));
5073 DebPrint (("frame %p (%s) obscured\n", f,
5074 SDATA (f->name)));
5075 }
5076 } 5075 }
5077 else 5076 else
5078 { 5077 {
5079 /* Frame is not obscured, so mark it as such. */ 5078 /* Frame is not obscured, so mark it as such. */
5080 f->async_visible = 1; 5079 SET_FRAME_VISIBLE (f, 1);
5081 5080
5082 if (FRAME_OBSCURED_P (f)) 5081 if (obscured)
5083 { 5082 {
5084 SET_FRAME_GARBAGED (f); 5083 SET_FRAME_GARBAGED (f);
5085 DebPrint (("obscured frame %p (%s) found to be visible\n", f, 5084 DebPrint (("obscured frame %p (%s) found to be visible\n",
5086 SDATA (f->name))); 5085 f, SDATA (f->name)));
5087 5086
5088 /* Force a redisplay sooner or later. */ 5087 /* Force a redisplay sooner or later. */
5089 record_asynch_buffer_change (); 5088 record_asynch_buffer_change ();
@@ -5654,7 +5653,7 @@ w32fullscreen_hook (FRAME_PTR f)
5654{ 5653{
5655 static int normal_width, normal_height; 5654 static int normal_width, normal_height;
5656 5655
5657 if (f->async_visible) 5656 if (FRAME_VISIBLE_P (f))
5658 { 5657 {
5659 int width, height, top_pos, left_pos, pixel_height, pixel_width; 5658 int width, height, top_pos, left_pos, pixel_height, pixel_width;
5660 int cur_w = FRAME_COLS (f), cur_h = FRAME_LINES (f); 5659 int cur_w = FRAME_COLS (f), cur_h = FRAME_LINES (f);
@@ -5674,24 +5673,33 @@ w32fullscreen_hook (FRAME_PTR f)
5674 5673
5675 switch (f->want_fullscreen) 5674 switch (f->want_fullscreen)
5676 { 5675 {
5677 /* No difference between these two when there is no WM */
5678 case FULLSCREEN_MAXIMIZED: 5676 case FULLSCREEN_MAXIMIZED:
5679 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, 0xf030, 0); 5677 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MAXIMIZE, 0);
5680 break; 5678 break;
5681 case FULLSCREEN_BOTH: 5679 case FULLSCREEN_BOTH:
5682 height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height) - 2; 5680 height =
5683 width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width); 5681 FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height)
5682 - XINT (Ftool_bar_lines_needed (selected_frame))
5683 + (NILP (Vmenu_bar_mode) ? 1 : 0);
5684 width =
5685 FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width)
5686 - FRAME_SCROLL_BAR_COLS (f);
5684 left_pos = workarea_rect.left; 5687 left_pos = workarea_rect.left;
5685 top_pos = workarea_rect.top; 5688 top_pos = workarea_rect.top;
5686 break; 5689 break;
5687 case FULLSCREEN_WIDTH: 5690 case FULLSCREEN_WIDTH:
5688 width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width); 5691 width =
5692 FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width)
5693 - FRAME_SCROLL_BAR_COLS (f);
5689 if (normal_height > 0) 5694 if (normal_height > 0)
5690 height = normal_height; 5695 height = normal_height;
5691 left_pos = workarea_rect.left; 5696 left_pos = workarea_rect.left;
5692 break; 5697 break;
5693 case FULLSCREEN_HEIGHT: 5698 case FULLSCREEN_HEIGHT:
5694 height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height) - 2; 5699 height =
5700 FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height)
5701 - XINT (Ftool_bar_lines_needed (selected_frame))
5702 + (NILP (Vmenu_bar_mode) ? 1 : 0);
5695 if (normal_width > 0) 5703 if (normal_width > 0)
5696 width = normal_width; 5704 width = normal_width;
5697 top_pos = workarea_rect.top; 5705 top_pos = workarea_rect.top;
@@ -6014,11 +6022,11 @@ x_make_frame_visible (struct frame *f)
6014 causes unexpected behavior when unminimizing frames that were 6022 causes unexpected behavior when unminimizing frames that were
6015 previously maximized. But only SW_SHOWNORMAL works properly for 6023 previously maximized. But only SW_SHOWNORMAL works properly for
6016 frames that were truely hidden (using make-frame-invisible), so 6024 frames that were truely hidden (using make-frame-invisible), so
6017 we need it to avoid Bug#5482. It seems that async_iconified 6025 we need it to avoid Bug#5482. It seems that iconified is only
6018 is only set for minimized windows that are still visible, so 6026 set for minimized windows that are still visible, so use that to
6019 use that to determine the appropriate flag to pass ShowWindow. */ 6027 determine the appropriate flag to pass ShowWindow. */
6020 my_show_window (f, FRAME_W32_WINDOW (f), 6028 my_show_window (f, FRAME_W32_WINDOW (f),
6021 f->async_iconified ? SW_RESTORE : SW_SHOWNORMAL); 6029 FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL);
6022 } 6030 }
6023 6031
6024 /* Synchronize to ensure Emacs knows the frame is visible 6032 /* Synchronize to ensure Emacs knows the frame is visible
@@ -6057,7 +6065,6 @@ x_make_frame_visible (struct frame *f)
6057 poll_suppress_count = old_poll_suppress_count; 6065 poll_suppress_count = old_poll_suppress_count;
6058 } 6066 }
6059 } 6067 }
6060 FRAME_SAMPLE_VISIBILITY (f);
6061 } 6068 }
6062} 6069}
6063 6070
@@ -6081,10 +6088,8 @@ x_make_frame_invisible (struct frame *f)
6081 So we can't win using the usual strategy of letting 6088 So we can't win using the usual strategy of letting
6082 FRAME_SAMPLE_VISIBILITY set this. So do it by hand, 6089 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
6083 and synchronize with the server to make sure we agree. */ 6090 and synchronize with the server to make sure we agree. */
6084 f->visible = 0; 6091 SET_FRAME_VISIBLE (f, 0);
6085 FRAME_ICONIFIED_P (f) = 0; 6092 SET_FRAME_ICONIFIED (f, 0);
6086 f->async_visible = 0;
6087 f->async_iconified = 0;
6088 6093
6089 unblock_input (); 6094 unblock_input ();
6090} 6095}
@@ -6100,7 +6105,7 @@ x_iconify_frame (struct frame *f)
6100 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f) 6105 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
6101 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0; 6106 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
6102 6107
6103 if (f->async_iconified) 6108 if (FRAME_ICONIFIED_P (f))
6104 return; 6109 return;
6105 6110
6106 block_input (); 6111 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)
333 333
334 if (NILP (lglyph)) 334 if (NILP (lglyph))
335 { 335 {
336 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil); 336 lglyph = LGLYPH_NEW ();
337 LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph); 337 LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph);
338 } 338 }
339 /* Copy to a 32-bit data type to shut up the 339 /* Copy to a 32-bit data type to shut up the
@@ -435,8 +435,8 @@ uniscribe_shape (Lisp_Object lgstring)
435 are zero. */ 435 are zero. */
436 || (!attributes[j].fClusterStart && items[i].a.fRTL)) 436 || (!attributes[j].fClusterStart && items[i].a.fRTL))
437 { 437 {
438 Lisp_Object vec; 438 Lisp_Object vec = make_uninit_vector (3);
439 vec = Fmake_vector (make_number (3), Qnil); 439
440 if (items[i].a.fRTL) 440 if (items[i].a.fRTL)
441 { 441 {
442 /* Empirically, it looks like Uniscribe 442 /* 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;
116/* Hook run at end of temp_output_buffer_show. */ 116/* Hook run at end of temp_output_buffer_show. */
117static Lisp_Object Qtemp_buffer_show_hook; 117static Lisp_Object Qtemp_buffer_show_hook;
118 118
119/* Incremented for each window created. */
120static int sequence_number;
121
122/* Nonzero after init_window_once has finished. */ 119/* Nonzero after init_window_once has finished. */
123static int window_initialized; 120static int window_initialized;
124 121
@@ -286,6 +283,9 @@ adjust_window_count (struct window *w, int arg)
286 b = b->base_buffer; 283 b = b->base_buffer;
287 b->window_count += arg; 284 b->window_count += arg;
288 eassert (b->window_count >= 0); 285 eassert (b->window_count >= 0);
286 /* These should be recalculated by redisplay code. */
287 w->window_end_valid = 0;
288 w->base_line_pos = 0;
289 } 289 }
290} 290}
291 291
@@ -300,15 +300,6 @@ wset_buffer (struct window *w, Lisp_Object val)
300 adjust_window_count (w, 1); 300 adjust_window_count (w, 1);
301} 301}
302 302
303/* Build a frequently used 4-integer (X Y W H) list. */
304
305static Lisp_Object
306list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h)
307{
308 return list4 (make_number (x), make_number (y),
309 make_number (w), make_number (h));
310}
311
312DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0, 303DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
313 doc: /* Return t if OBJECT is a window and nil otherwise. */) 304 doc: /* Return t if OBJECT is a window and nil otherwise. */)
314 (Lisp_Object object) 305 (Lisp_Object object)
@@ -1489,17 +1480,8 @@ if it isn't already recorded. */)
1489 CHECK_BUFFER (buf); 1480 CHECK_BUFFER (buf);
1490 b = XBUFFER (buf); 1481 b = XBUFFER (buf);
1491 1482
1492#if 0 /* This change broke some things. We should make it later. */
1493 /* If we don't know the end position, return nil.
1494 The user can compute it with vertical-motion if he wants to.
1495 It would be nicer to do it automatically,
1496 but that's so slow that it would probably bother people. */
1497 if (NILP (w->window_end_valid))
1498 return Qnil;
1499#endif
1500
1501 if (! NILP (update) 1483 if (! NILP (update)
1502 && (windows_or_buffers_changed || NILP (w->window_end_valid)) 1484 && (windows_or_buffers_changed || !w->window_end_valid)
1503 && !noninteractive) 1485 && !noninteractive)
1504 { 1486 {
1505 struct text_pos startp; 1487 struct text_pos startp;
@@ -1553,7 +1535,7 @@ Return POS. */)
1553{ 1535{
1554 register struct window *w = decode_live_window (window); 1536 register struct window *w = decode_live_window (window);
1555 1537
1556 CHECK_NUMBER_COERCE_MARKER (pos); 1538 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1557 1539
1558 if (w == XWINDOW (selected_window)) 1540 if (w == XWINDOW (selected_window))
1559 { 1541 {
@@ -1563,6 +1545,8 @@ Return POS. */)
1563 { 1545 {
1564 struct buffer *old_buffer = current_buffer; 1546 struct buffer *old_buffer = current_buffer;
1565 1547
1548 /* ... but here we want to catch type error before buffer change. */
1549 CHECK_NUMBER_COERCE_MARKER (pos);
1566 set_buffer_internal (XBUFFER (w->buffer)); 1550 set_buffer_internal (XBUFFER (w->buffer));
1567 Fgoto_char (pos); 1551 Fgoto_char (pos);
1568 set_buffer_internal (old_buffer); 1552 set_buffer_internal (old_buffer);
@@ -1588,9 +1572,8 @@ overriding motion of point in order to display at this exact start. */)
1588{ 1572{
1589 register struct window *w = decode_live_window (window); 1573 register struct window *w = decode_live_window (window);
1590 1574
1591 CHECK_NUMBER_COERCE_MARKER (pos);
1592 set_marker_restricted (w->start, pos, w->buffer); 1575 set_marker_restricted (w->start, pos, w->buffer);
1593 /* this is not right, but much easier than doing what is right. */ 1576 /* This is not right, but much easier than doing what is right. */
1594 w->start_at_line_beg = 0; 1577 w->start_at_line_beg = 0;
1595 if (NILP (noforce)) 1578 if (NILP (noforce))
1596 w->force_start = 1; 1579 w->force_start = 1;
@@ -1706,7 +1689,7 @@ Return nil if window display is not up-to-date. In that case, use
1706 b = XBUFFER (w->buffer); 1689 b = XBUFFER (w->buffer);
1707 1690
1708 /* Fail if current matrix is not up-to-date. */ 1691 /* Fail if current matrix is not up-to-date. */
1709 if (NILP (w->window_end_valid) 1692 if (!w->window_end_valid
1710 || current_buffer->clip_changed 1693 || current_buffer->clip_changed
1711 || current_buffer->prevent_redisplay_optimizations_p 1694 || current_buffer->prevent_redisplay_optimizations_p
1712 || w->last_modified < BUF_MODIFF (b) 1695 || w->last_modified < BUF_MODIFF (b)
@@ -2038,7 +2021,7 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag)
2038 n->pseudo_window_p = 0; 2021 n->pseudo_window_p = 0;
2039 wset_window_end_vpos (n, make_number (0)); 2022 wset_window_end_vpos (n, make_number (0));
2040 wset_window_end_pos (n, make_number (0)); 2023 wset_window_end_pos (n, make_number (0));
2041 wset_window_end_valid (n, Qnil); 2024 n->window_end_valid = 0;
2042 n->frozen_window_start_p = 0; 2025 n->frozen_window_start_p = 0;
2043 } 2026 }
2044 2027
@@ -2238,7 +2221,6 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf
2238 } 2221 }
2239 else if (EQ (all_frames, Qvisible)) 2222 else if (EQ (all_frames, Qvisible))
2240 { 2223 {
2241 FRAME_SAMPLE_VISIBILITY (f);
2242 candidate_p = FRAME_VISIBLE_P (f) 2224 candidate_p = FRAME_VISIBLE_P (f)
2243 && (FRAME_TERMINAL (XFRAME (w->frame)) 2225 && (FRAME_TERMINAL (XFRAME (w->frame))
2244 == FRAME_TERMINAL (XFRAME (selected_frame))); 2226 == FRAME_TERMINAL (XFRAME (selected_frame)));
@@ -2246,7 +2228,6 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf
2246 } 2228 }
2247 else if (INTEGERP (all_frames) && XINT (all_frames) == 0) 2229 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2248 { 2230 {
2249 FRAME_SAMPLE_VISIBILITY (f);
2250 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f) 2231 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2251#ifdef HAVE_X_WINDOWS 2232#ifdef HAVE_X_WINDOWS
2252 /* Yuck!! If we've just created the frame and the 2233 /* Yuck!! If we've just created the frame and the
@@ -2762,7 +2743,7 @@ window-start value is reasonable when this function is called. */)
2762 struct window *w, *r, *s; 2743 struct window *w, *r, *s;
2763 struct frame *f; 2744 struct frame *f;
2764 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; 2745 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2765 ptrdiff_t startpos IF_LINT (= 0); 2746 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
2766 int top IF_LINT (= 0), new_top, resize_failed; 2747 int top IF_LINT (= 0), new_top, resize_failed;
2767 2748
2768 w = decode_valid_window (window); 2749 w = decode_valid_window (window);
@@ -2801,6 +2782,7 @@ window-start value is reasonable when this function is called. */)
2801 if (!NILP (w->buffer)) 2782 if (!NILP (w->buffer))
2802 { 2783 {
2803 startpos = marker_position (w->start); 2784 startpos = marker_position (w->start);
2785 startbyte = marker_byte_position (w->start);
2804 top = WINDOW_TOP_EDGE_LINE (w) 2786 top = WINDOW_TOP_EDGE_LINE (w)
2805 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))); 2787 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2806 /* Make sure WINDOW is the frame's selected window. */ 2788 /* Make sure WINDOW is the frame's selected window. */
@@ -2970,10 +2952,10 @@ window-start value is reasonable when this function is called. */)
2970 Fset_buffer (w->buffer); 2952 Fset_buffer (w->buffer);
2971 /* This computation used to temporarily move point, but that 2953 /* This computation used to temporarily move point, but that
2972 can have unwanted side effects due to text properties. */ 2954 can have unwanted side effects due to text properties. */
2973 pos = *vmotion (startpos, -top, w); 2955 pos = *vmotion (startpos, startbyte, -top, w);
2974 2956
2975 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos); 2957 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2976 wset_window_end_valid (w, Qnil); 2958 w->window_end_valid = 0;
2977 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE 2959 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2978 || FETCH_BYTE (pos.bytepos - 1) == '\n'); 2960 || FETCH_BYTE (pos.bytepos - 1) == '\n');
2979 /* We need to do this, so that the window-scroll-functions 2961 /* 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
3189 wset_window_end_pos (w, make_number (0)); 3171 wset_window_end_pos (w, make_number (0));
3190 wset_window_end_vpos (w, make_number (0)); 3172 wset_window_end_vpos (w, make_number (0));
3191 memset (&w->last_cursor, 0, sizeof w->last_cursor); 3173 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3192 wset_window_end_valid (w, Qnil); 3174
3193 if (!(keep_margins_p && samebuf)) 3175 if (!(keep_margins_p && samebuf))
3194 { /* If we're not actually changing the buffer, don't reset hscroll and 3176 { /* If we're not actually changing the buffer, don't reset hscroll and
3195 vscroll. This case happens for example when called from 3177 vscroll. This case happens for example when called from
@@ -3438,8 +3420,6 @@ make_parent_window (Lisp_Object window, int horflag)
3438 adjust_window_count (p, 1); 3420 adjust_window_count (p, 1);
3439 XSETWINDOW (parent, p); 3421 XSETWINDOW (parent, p);
3440 3422
3441 p->sequence_number = ++sequence_number;
3442
3443 replace_window (window, parent, 1); 3423 replace_window (window, parent, 1);
3444 3424
3445 wset_next (o, Qnil); 3425 wset_next (o, Qnil);
@@ -3488,7 +3468,7 @@ make_window (void)
3488 w->nrows_scale_factor = w->ncols_scale_factor = 1; 3468 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3489 w->phys_cursor_type = -1; 3469 w->phys_cursor_type = -1;
3490 w->phys_cursor_width = -1; 3470 w->phys_cursor_width = -1;
3491 w->sequence_number = ++sequence_number; 3471 w->column_number_displayed = -1;
3492 3472
3493 /* Reset window_list. */ 3473 /* Reset window_list. */
3494 Vwindow_list = Qnil; 3474 Vwindow_list = Qnil;
@@ -3958,7 +3938,7 @@ set correctly. See the code of `split-window' for how this is done. */)
3958 wset_next (o, new); 3938 wset_next (o, new);
3959 } 3939 }
3960 3940
3961 wset_window_end_valid (n, Qnil); 3941 n->window_end_valid = 0;
3962 memset (&n->last_cursor, 0, sizeof n->last_cursor); 3942 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3963 3943
3964 /* Get special geometry settings from reference window. */ 3944 /* Get special geometry settings from reference window. */
@@ -4628,8 +4608,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4628 } 4608 }
4629 4609
4630 /* Set the window start, and set up the window for redisplay. */ 4610 /* Set the window start, and set up the window for redisplay. */
4631 set_marker_restricted (w->start, make_number (pos), 4611 set_marker_restricted_both (w->start, w->buffer, IT_CHARPOS (it),
4632 w->buffer); 4612 IT_BYTEPOS (it));
4633 bytepos = marker_byte_position (w->start); 4613 bytepos = marker_byte_position (w->start);
4634 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n'); 4614 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4635 w->update_mode_line = 1; 4615 w->update_mode_line = 1;
@@ -4769,7 +4749,8 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4769 register Lisp_Object tem; 4749 register Lisp_Object tem;
4770 int lose; 4750 int lose;
4771 Lisp_Object bolp; 4751 Lisp_Object bolp;
4772 ptrdiff_t startpos; 4752 ptrdiff_t startpos = marker_position (w->start);
4753 ptrdiff_t startbyte = marker_byte_position (w->start);
4773 Lisp_Object original_pos = Qnil; 4754 Lisp_Object original_pos = Qnil;
4774 4755
4775 /* If scrolling screen-fulls, compute the number of lines to 4756 /* 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)
4777 if (whole) 4758 if (whole)
4778 n *= max (1, ht - next_screen_context_lines); 4759 n *= max (1, ht - next_screen_context_lines);
4779 4760
4780 startpos = marker_position (w->start);
4781
4782 if (!NILP (Vscroll_preserve_screen_position)) 4761 if (!NILP (Vscroll_preserve_screen_position))
4783 { 4762 {
4784 if (window_scroll_preserve_vpos <= 0 4763 if (window_scroll_preserve_vpos <= 0
@@ -4786,10 +4765,8 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4786 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command))) 4765 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4787 { 4766 {
4788 struct position posit 4767 struct position posit
4789 = *compute_motion (startpos, 0, 0, 0, 4768 = *compute_motion (startpos, startbyte, 0, 0, 0,
4790 PT, ht, 0, 4769 PT, ht, 0, -1, w->hscroll, 0, w);
4791 -1, w->hscroll,
4792 0, w);
4793 window_scroll_preserve_vpos = posit.vpos; 4770 window_scroll_preserve_vpos = posit.vpos;
4794 window_scroll_preserve_hpos = posit.hpos + w->hscroll; 4771 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
4795 } 4772 }
@@ -4805,9 +4782,10 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4805 { 4782 {
4806 Fvertical_motion (make_number (- (ht / 2)), window); 4783 Fvertical_motion (make_number (- (ht / 2)), window);
4807 startpos = PT; 4784 startpos = PT;
4785 startbyte = PT_BYTE;
4808 } 4786 }
4809 4787
4810 SET_PT (startpos); 4788 SET_PT_BOTH (startpos, startbyte);
4811 lose = n < 0 && PT == BEGV; 4789 lose = n < 0 && PT == BEGV;
4812 Fvertical_motion (make_number (n), window); 4790 Fvertical_motion (make_number (n), window);
4813 pos = PT; 4791 pos = PT;
@@ -5185,7 +5163,7 @@ displayed_window_lines (struct window *w)
5185 5163
5186DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P", 5164DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5187 doc: /* Center point in selected window and maybe redisplay frame. 5165 doc: /* Center point in selected window and maybe redisplay frame.
5188With prefix argument ARG, recenter putting point on screen line ARG 5166With a numeric prefix argument ARG, recenter putting point on screen line ARG
5189relative to the selected window. If ARG is negative, it counts up from the 5167relative to the selected window. If ARG is negative, it counts up from the
5190bottom of the window. (ARG should be less than the height of the window.) 5168bottom of the window. (ARG should be less than the height of the window.)
5191 5169
@@ -5342,7 +5320,7 @@ and redisplay normally--don't erase and redraw the frame. */)
5342 5320
5343 iarg = max (iarg, this_scroll_margin); 5321 iarg = max (iarg, this_scroll_margin);
5344 5322
5345 pos = *vmotion (PT, -iarg, w); 5323 pos = *vmotion (PT, PT_BYTE, -iarg, w);
5346 charpos = pos.bufpos; 5324 charpos = pos.bufpos;
5347 bytepos = pos.bytepos; 5325 bytepos = pos.bytepos;
5348 } 5326 }
@@ -5361,14 +5339,14 @@ and redisplay normally--don't erase and redraw the frame. */)
5361 iarg = clip_to_bounds (this_scroll_margin, iarg, 5339 iarg = clip_to_bounds (this_scroll_margin, iarg,
5362 ht - this_scroll_margin - 1); 5340 ht - this_scroll_margin - 1);
5363 5341
5364 pos = *vmotion (PT, - iarg, w); 5342 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5365 charpos = pos.bufpos; 5343 charpos = pos.bufpos;
5366 bytepos = pos.bytepos; 5344 bytepos = pos.bytepos;
5367 } 5345 }
5368 5346
5369 /* Set the new window start. */ 5347 /* Set the new window start. */
5370 set_marker_both (w->start, w->buffer, charpos, bytepos); 5348 set_marker_both (w->start, w->buffer, charpos, bytepos);
5371 wset_window_end_valid (w, Qnil); 5349 w->window_end_valid = 0;
5372 5350
5373 w->optional_new_start = 1; 5351 w->optional_new_start = 1;
5374 5352
@@ -5808,8 +5786,7 @@ the return value is nil. Otherwise the value is t. */)
5808 { 5786 {
5809 /* Set window markers at start of visible range. */ 5787 /* Set window markers at start of visible range. */
5810 if (XMARKER (w->start)->buffer == 0) 5788 if (XMARKER (w->start)->buffer == 0)
5811 set_marker_restricted (w->start, make_number (0), 5789 set_marker_restricted_both (w->start, w->buffer, 0, 0);
5812 w->buffer);
5813 if (XMARKER (w->pointm)->buffer == 0) 5790 if (XMARKER (w->pointm)->buffer == 0)
5814 set_marker_restricted_both 5791 set_marker_restricted_both
5815 (w->pointm, w->buffer, 5792 (w->pointm, w->buffer,
@@ -5827,10 +5804,8 @@ the return value is nil. Otherwise the value is t. */)
5827 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ())); 5804 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
5828 /* This will set the markers to beginning of visible 5805 /* This will set the markers to beginning of visible
5829 range. */ 5806 range. */
5830 set_marker_restricted (w->start, 5807 set_marker_restricted_both (w->start, w->buffer, 0, 0);
5831 make_number (0), w->buffer); 5808 set_marker_restricted_both (w->pointm, w->buffer, 0, 0);
5832 set_marker_restricted (w->pointm,
5833 make_number (0), w->buffer);
5834 w->start_at_line_beg = 1; 5809 w->start_at_line_beg = 1;
5835 if (!NILP (w->dedicated)) 5810 if (!NILP (w->dedicated))
5836 /* Record this window as dead. */ 5811 /* Record this window as dead. */
@@ -6203,11 +6178,11 @@ saved by this function. */)
6203 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil; 6178 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6204 data->root_window = FRAME_ROOT_WINDOW (f); 6179 data->root_window = FRAME_ROOT_WINDOW (f);
6205 data->focus_frame = FRAME_FOCUS_FRAME (f); 6180 data->focus_frame = FRAME_FOCUS_FRAME (f);
6206 tem = Fmake_vector (make_number (n_windows), Qnil); 6181 tem = make_uninit_vector (n_windows);
6207 data->saved_windows = tem; 6182 data->saved_windows = tem;
6208 for (i = 0; i < n_windows; i++) 6183 for (i = 0; i < n_windows; i++)
6209 ASET (tem, i, 6184 ASET (tem, i,
6210 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil)); 6185 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6211 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0); 6186 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6212 XSETWINDOW_CONFIGURATION (tem, data); 6187 XSETWINDOW_CONFIGURATION (tem, data);
6213 return (tem); 6188 return (tem);
@@ -6319,7 +6294,7 @@ display marginal areas and the text area. */)
6319 adjust_window_margins (w); 6294 adjust_window_margins (w);
6320 6295
6321 clear_glyph_matrix (w->current_matrix); 6296 clear_glyph_matrix (w->current_matrix);
6322 wset_window_end_valid (w, Qnil); 6297 w->window_end_valid = 0;
6323 6298
6324 ++windows_or_buffers_changed; 6299 ++windows_or_buffers_changed;
6325 adjust_glyphs (XFRAME (WINDOW_FRAME (w))); 6300 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
@@ -6389,7 +6364,7 @@ Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6389 adjust_window_margins (w); 6364 adjust_window_margins (w);
6390 6365
6391 clear_glyph_matrix (w->current_matrix); 6366 clear_glyph_matrix (w->current_matrix);
6392 wset_window_end_valid (w, Qnil); 6367 w->window_end_valid = 0;
6393 6368
6394 ++windows_or_buffers_changed; 6369 ++windows_or_buffers_changed;
6395 adjust_glyphs (XFRAME (WINDOW_FRAME (w))); 6370 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
175 no scroll bar. A value of t means use frame value. */ 175 no scroll bar. A value of t means use frame value. */
176 Lisp_Object vertical_scroll_bar_type; 176 Lisp_Object vertical_scroll_bar_type;
177 177
178 /* Z - the buffer position of the last glyph in the current matrix 178 /* Z - the buffer position of the last glyph in the current
179 of W. Only valid if WINDOW_END_VALID is not nil. */ 179 matrix of W. Only valid if window_end_valid is nonzero. */
180 Lisp_Object window_end_pos; 180 Lisp_Object window_end_pos;
181
181 /* Glyph matrix row of the last glyph in the current matrix 182 /* Glyph matrix row of the last glyph in the current matrix
182 of W. Only valid if WINDOW_END_VALID is not nil. */ 183 of W. Only valid if window_end_valid is nonzero. */
183 Lisp_Object window_end_vpos; 184 Lisp_Object window_end_vpos;
184 /* t if window_end_pos is truly valid.
185 This is nil if nontrivial redisplay is preempted
186 since in that case the frame image that window_end_pos
187 did not get onto the frame. */
188 Lisp_Object window_end_valid;
189 185
190 /* Display-table to use for displaying chars in this window. 186 /* Display-table to use for displaying chars in this window.
191 Nil means use the buffer's own display-table. */ 187 Nil means use the buffer's own display-table. */
@@ -196,23 +192,6 @@ struct window
196 and Qt, so bitfield can't be used here. */ 192 and Qt, so bitfield can't be used here. */
197 Lisp_Object dedicated; 193 Lisp_Object dedicated;
198 194
199 /* Line number and position of a line somewhere above the top of the
200 screen. If this field is nil, it means we don't have a base
201 line. */
202 Lisp_Object base_line_number;
203 /* If this field is nil, it means we don't have a base line.
204 If it is a buffer, it means don't display the line number
205 as long as the window shows that buffer. */
206 Lisp_Object base_line_pos;
207
208 /* If we have highlighted the region (or any part of it),
209 this is the mark position that we used, as an integer. */
210 Lisp_Object region_showing;
211
212 /* The column number currently displayed in this window's mode line,
213 or nil if column numbers are not being displayed. */
214 Lisp_Object column_number_displayed;
215
216 /* If redisplay in this window goes beyond this buffer position, 195 /* If redisplay in this window goes beyond this buffer position,
217 must run the redisplay-end-trigger-hook. */ 196 must run the redisplay-end-trigger-hook. */
218 Lisp_Object redisplay_end_trigger; 197 Lisp_Object redisplay_end_trigger;
@@ -242,9 +221,6 @@ struct window
242 /* Number saying how recently window was selected. */ 221 /* Number saying how recently window was selected. */
243 int use_time; 222 int use_time;
244 223
245 /* Unique number of window assigned when it was created. */
246 int sequence_number;
247
248 /* Number of columns display within the window is scrolled to the left. */ 224 /* Number of columns display within the window is scrolled to the left. */
249 ptrdiff_t hscroll; 225 ptrdiff_t hscroll;
250 226
@@ -264,6 +240,19 @@ struct window
264 it should be positive. */ 240 it should be positive. */
265 ptrdiff_t last_point; 241 ptrdiff_t last_point;
266 242
243 /* Line number and position of a line somewhere above the top of the
244 screen. If this field is zero, it means we don't have a base line. */
245 ptrdiff_t base_line_number;
246
247 /* If this field is zero, it means we don't have a base line.
248 If it is -1, it means don't display the line number as long
249 as the window shows its buffer. */
250 ptrdiff_t base_line_pos;
251
252 /* The column number currently displayed in this window's mode
253 line, or -1 if column numbers are not being displayed. */
254 ptrdiff_t column_number_displayed;
255
267 /* Scaling factor for the glyph_matrix size calculation in this window. 256 /* Scaling factor for the glyph_matrix size calculation in this window.
268 Used if window contains many small images or uses proportional fonts, 257 Used if window contains many small images or uses proportional fonts,
269 as the normal may yield a matrix which is too small. */ 258 as the normal may yield a matrix which is too small. */
@@ -339,12 +328,21 @@ struct window
339 Otherwise draw them between margin areas and text. */ 328 Otherwise draw them between margin areas and text. */
340 unsigned fringes_outside_margins : 1; 329 unsigned fringes_outside_margins : 1;
341 330
331 /* Nonzero if window_end_pos and window_end_vpos are truly valid.
332 This is zero if nontrivial redisplay is preempted since in that case
333 the frame image that window_end_pos did not get onto the frame. */
334 unsigned window_end_valid : 1;
335
342 /* Amount by which lines of this window are scrolled in 336 /* Amount by which lines of this window are scrolled in
343 y-direction (smooth scrolling). */ 337 y-direction (smooth scrolling). */
344 int vscroll; 338 int vscroll;
345 339
346 /* Z_BYTE - Buffer position of the last glyph in the current matrix of W. 340 /* If we have highlighted the region (or any part of it), the mark
347 Should be nonnegative, and only valid if window_end_valid is not nil. */ 341 (region start) position; otherwise zero. */
342 ptrdiff_t region_showing;
343
344 /* Z_BYTE - buffer position of the last glyph in the current matrix of W.
345 Should be nonnegative, and only valid if window_end_valid is nonzero. */
348 ptrdiff_t window_end_bytepos; 346 ptrdiff_t window_end_bytepos;
349}; 347};
350 348
@@ -401,11 +399,6 @@ wset_window_end_pos (struct window *w, Lisp_Object val)
401 w->window_end_pos = val; 399 w->window_end_pos = val;
402} 400}
403WINDOW_INLINE void 401WINDOW_INLINE void
404wset_window_end_valid (struct window *w, Lisp_Object val)
405{
406 w->window_end_valid = val;
407}
408WINDOW_INLINE void
409wset_window_end_vpos (struct window *w, Lisp_Object val) 402wset_window_end_vpos (struct window *w, Lisp_Object val)
410{ 403{
411 w->window_end_vpos = val; 404 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;
367static Lisp_Object Qmargin, Qpointer; 367static Lisp_Object Qmargin, Qpointer;
368static Lisp_Object Qline_height; 368static Lisp_Object Qline_height;
369 369
370/* These setters are used only in this file, so they can be private. */
371static void
372wset_base_line_number (struct window *w, Lisp_Object val)
373{
374 w->base_line_number = val;
375}
376static void
377wset_base_line_pos (struct window *w, Lisp_Object val)
378{
379 w->base_line_pos = val;
380}
381static void
382wset_column_number_displayed (struct window *w, Lisp_Object val)
383{
384 w->column_number_displayed = val;
385}
386static void
387wset_region_showing (struct window *w, Lisp_Object val)
388{
389 w->region_showing = val;
390}
391
392#ifdef HAVE_WINDOW_SYSTEM 370#ifdef HAVE_WINDOW_SYSTEM
393 371
394/* Test if overflow newline into fringe. Called with iterator IT 372/* Test if overflow newline into fringe. Called with iterator IT
@@ -840,17 +818,17 @@ static void ensure_echo_area_buffers (void);
840static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); 818static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
841static Lisp_Object with_echo_area_buffer_unwind_data (struct window *); 819static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
842static int with_echo_area_buffer (struct window *, int, 820static int with_echo_area_buffer (struct window *, int,
843 int (*) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t), 821 int (*) (ptrdiff_t, Lisp_Object),
844 ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); 822 ptrdiff_t, Lisp_Object);
845static void clear_garbaged_frames (void); 823static void clear_garbaged_frames (void);
846static int current_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); 824static int current_message_1 (ptrdiff_t, Lisp_Object);
847static void pop_message (void); 825static void pop_message (void);
848static int truncate_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); 826static int truncate_message_1 (ptrdiff_t, Lisp_Object);
849static void set_message (const char *, Lisp_Object, ptrdiff_t, int); 827static void set_message (Lisp_Object);
850static int set_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); 828static int set_message_1 (ptrdiff_t, Lisp_Object);
851static int display_echo_area (struct window *); 829static int display_echo_area (struct window *);
852static int display_echo_area_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); 830static int display_echo_area_1 (ptrdiff_t, Lisp_Object);
853static int resize_mini_window_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t); 831static int resize_mini_window_1 (ptrdiff_t, Lisp_Object);
854static Lisp_Object unwind_redisplay (Lisp_Object); 832static Lisp_Object unwind_redisplay (Lisp_Object);
855static int string_char_and_length (const unsigned char *, int *); 833static int string_char_and_length (const unsigned char *, int *);
856static struct text_pos display_prop_end (struct it *, Lisp_Object, 834static 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 *);
932static struct text_pos string_pos_nchars_ahead (struct text_pos, 910static struct text_pos string_pos_nchars_ahead (struct text_pos,
933 Lisp_Object, ptrdiff_t); 911 Lisp_Object, ptrdiff_t);
934static struct text_pos string_pos (ptrdiff_t, Lisp_Object); 912static struct text_pos string_pos (ptrdiff_t, Lisp_Object);
935static struct text_pos c_string_pos (ptrdiff_t, const char *, int); 913static struct text_pos c_string_pos (ptrdiff_t, const char *, bool);
936static ptrdiff_t number_of_chars (const char *, int); 914static ptrdiff_t number_of_chars (const char *, bool);
937static void compute_stop_pos (struct it *); 915static void compute_stop_pos (struct it *);
938static void compute_string_pos (struct text_pos *, struct text_pos, 916static void compute_string_pos (struct text_pos *, struct text_pos,
939 Lisp_Object); 917 Lisp_Object);
@@ -1414,21 +1392,9 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1414 Lisp_Object cpos = make_number (charpos); 1392 Lisp_Object cpos = make_number (charpos);
1415 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); 1393 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1416 Lisp_Object string = string_from_display_spec (spec); 1394 Lisp_Object string = string_from_display_spec (spec);
1417 int newline_in_string = 0; 1395 bool newline_in_string
1418 1396 = (STRINGP (string)
1419 if (STRINGP (string)) 1397 && memchr (SDATA (string), '\n', SBYTES (string)));
1420 {
1421 const char *s = SSDATA (string);
1422 const char *e = s + SBYTES (string);
1423 while (s < e)
1424 {
1425 if (*s++ == '\n')
1426 {
1427 newline_in_string = 1;
1428 break;
1429 }
1430 }
1431 }
1432 /* The tricky code below is needed because there's a 1398 /* The tricky code below is needed because there's a
1433 discrepancy between move_it_to and how we set cursor 1399 discrepancy between move_it_to and how we set cursor
1434 when the display line ends in a newline from a 1400 when the display line ends in a newline from a
@@ -1684,7 +1650,7 @@ string_pos (ptrdiff_t charpos, Lisp_Object string)
1684 means recognize multibyte characters. */ 1650 means recognize multibyte characters. */
1685 1651
1686static struct text_pos 1652static struct text_pos
1687c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p) 1653c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
1688{ 1654{
1689 struct text_pos pos; 1655 struct text_pos pos;
1690 1656
@@ -1715,7 +1681,7 @@ c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p)
1715 non-zero means recognize multibyte characters. */ 1681 non-zero means recognize multibyte characters. */
1716 1682
1717static ptrdiff_t 1683static ptrdiff_t
1718number_of_chars (const char *s, int multibyte_p) 1684number_of_chars (const char *s, bool multibyte_p)
1719{ 1685{
1720 ptrdiff_t nchars; 1686 ptrdiff_t nchars;
1721 1687
@@ -2539,8 +2505,7 @@ check_it (struct it *it)
2539static void 2505static void
2540check_window_end (struct window *w) 2506check_window_end (struct window *w)
2541{ 2507{
2542 if (!MINI_WINDOW_P (w) 2508 if (!MINI_WINDOW_P (w) && w->window_end_valid)
2543 && !NILP (w->window_end_valid))
2544 { 2509 {
2545 struct glyph_row *row; 2510 struct glyph_row *row;
2546 eassert ((row = MATRIX_ROW (w->current_matrix, 2511 eassert ((row = MATRIX_ROW (w->current_matrix,
@@ -5940,8 +5905,10 @@ pop_it (struct it *it)
5940static void 5905static void
5941back_to_previous_line_start (struct it *it) 5906back_to_previous_line_start (struct it *it)
5942{ 5907{
5943 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1); 5908 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
5944 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); 5909
5910 DEC_BOTH (cp, bp);
5911 IT_CHARPOS (*it) = find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it));
5945} 5912}
5946 5913
5947 5914
@@ -5957,7 +5924,7 @@ back_to_previous_line_start (struct it *it)
5957 5924
5958 Newlines may come from buffer text, overlay strings, or strings 5925 Newlines may come from buffer text, overlay strings, or strings
5959 displayed via the `display' property. That's the reason we can't 5926 displayed via the `display' property. That's the reason we can't
5960 simply use find_next_newline_no_quit. 5927 simply use find_newline_no_quit.
5961 5928
5962 Note that this function may not skip over invisible text that is so 5929 Note that this function may not skip over invisible text that is so
5963 because of text properties and immediately follows a newline. If 5930 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,
6012 short-cut. */ 5979 short-cut. */
6013 if (!newline_found_p) 5980 if (!newline_found_p)
6014 { 5981 {
6015 ptrdiff_t start = IT_CHARPOS (*it); 5982 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
6016 ptrdiff_t limit = find_next_newline_no_quit (start, 1); 5983 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
5984 1, &bytepos);
6017 Lisp_Object pos; 5985 Lisp_Object pos;
6018 5986
6019 eassert (!STRINGP (it->string)); 5987 eassert (!STRINGP (it->string));
@@ -6031,7 +5999,7 @@ forward_to_next_line_start (struct it *it, int *skipped_p,
6031 if (!it->bidi_p) 5999 if (!it->bidi_p)
6032 { 6000 {
6033 IT_CHARPOS (*it) = limit; 6001 IT_CHARPOS (*it) = limit;
6034 IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit); 6002 IT_BYTEPOS (*it) = bytepos;
6035 } 6003 }
6036 else 6004 else
6037 { 6005 {
@@ -7467,11 +7435,9 @@ get_visually_first_element (struct it *it)
7467 if (string_p) 7435 if (string_p)
7468 it->bidi_it.charpos = it->bidi_it.bytepos = 0; 7436 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
7469 else 7437 else
7470 { 7438 it->bidi_it.charpos = find_newline_no_quit (IT_CHARPOS (*it),
7471 it->bidi_it.charpos = find_next_newline_no_quit (IT_CHARPOS (*it), 7439 IT_BYTEPOS (*it), -1,
7472 -1); 7440 &it->bidi_it.bytepos);
7473 it->bidi_it.bytepos = CHAR_TO_BYTE (it->bidi_it.charpos);
7474 }
7475 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1); 7441 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1);
7476 do 7442 do
7477 { 7443 {
@@ -9015,6 +8981,9 @@ move_it_vertically_backward (struct it *it, int dy)
9015 struct it it2, it3; 8981 struct it it2, it3;
9016 void *it2data = NULL, *it3data = NULL; 8982 void *it2data = NULL, *it3data = NULL;
9017 ptrdiff_t start_pos; 8983 ptrdiff_t start_pos;
8984 int nchars_per_row
8985 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
8986 ptrdiff_t pos_limit;
9018 8987
9019 move_further_back: 8988 move_further_back:
9020 eassert (dy >= 0); 8989 eassert (dy >= 0);
@@ -9023,9 +8992,15 @@ move_it_vertically_backward (struct it *it, int dy)
9023 8992
9024 /* Estimate how many newlines we must move back. */ 8993 /* Estimate how many newlines we must move back. */
9025 nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f)); 8994 nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
8995 if (it->line_wrap == TRUNCATE)
8996 pos_limit = BEGV;
8997 else
8998 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
9026 8999
9027 /* Set the iterator's position that many lines back. */ 9000 /* Set the iterator's position that many lines back. But don't go
9028 while (nlines-- && IT_CHARPOS (*it) > BEGV) 9001 back more than NLINES full screen lines -- this wins a day with
9002 buffers which have very long lines. */
9003 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
9029 back_to_previous_visible_line_start (it); 9004 back_to_previous_visible_line_start (it);
9030 9005
9031 /* Reseat the iterator here. When moving backward, we don't want 9006 /* Reseat the iterator here. When moving backward, we don't want
@@ -9096,10 +9071,11 @@ move_it_vertically_backward (struct it *it, int dy)
9096 && IT_CHARPOS (*it) > BEGV 9071 && IT_CHARPOS (*it) > BEGV
9097 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n') 9072 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
9098 { 9073 {
9099 ptrdiff_t nl_pos = 9074 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
9100 find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
9101 9075
9102 move_it_to (it, nl_pos, -1, -1, -1, MOVE_TO_POS); 9076 DEC_BOTH (cp, bp);
9077 cp = find_newline_no_quit (cp, bp, -1, NULL);
9078 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
9103 } 9079 }
9104 bidi_unshelve_cache (it3data, 1); 9080 bidi_unshelve_cache (it3data, 1);
9105 } 9081 }
@@ -9256,6 +9232,9 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
9256 struct it it2; 9232 struct it it2;
9257 void *it2data = NULL; 9233 void *it2data = NULL;
9258 ptrdiff_t start_charpos, i; 9234 ptrdiff_t start_charpos, i;
9235 int nchars_per_row
9236 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
9237 ptrdiff_t pos_limit;
9259 9238
9260 /* Start at the beginning of the screen line containing IT's 9239 /* Start at the beginning of the screen line containing IT's
9261 position. This may actually move vertically backwards, 9240 position. This may actually move vertically backwards,
@@ -9264,9 +9243,14 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
9264 move_it_vertically_backward (it, 0); 9243 move_it_vertically_backward (it, 0);
9265 dvpos -= it->vpos; 9244 dvpos -= it->vpos;
9266 9245
9267 /* Go back -DVPOS visible lines and reseat the iterator there. */ 9246 /* Go back -DVPOS buffer lines, but no farther than -DVPOS full
9247 screen lines, and reseat the iterator there. */
9268 start_charpos = IT_CHARPOS (*it); 9248 start_charpos = IT_CHARPOS (*it);
9269 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i) 9249 if (it->line_wrap == TRUNCATE)
9250 pos_limit = BEGV;
9251 else
9252 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
9253 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
9270 back_to_previous_visible_line_start (it); 9254 back_to_previous_visible_line_start (it);
9271 reseat (it, it->current.pos, 1); 9255 reseat (it, it->current.pos, 1);
9272 9256
@@ -9375,8 +9359,8 @@ message_log_maybe_newline (void)
9375 9359
9376 9360
9377/* Add a string M of length NBYTES to the message log, optionally 9361/* Add a string M of length NBYTES to the message log, optionally
9378 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if 9362 terminated with a newline when NLFLAG is true. MULTIBYTE, if
9379 nonzero, means interpret the contents of M as multibyte. This 9363 true, means interpret the contents of M as multibyte. This
9380 function calls low-level routines in order to bypass text property 9364 function calls low-level routines in order to bypass text property
9381 hooks, etc. which might not be safe to run. 9365 hooks, etc. which might not be safe to run.
9382 9366
@@ -9384,7 +9368,7 @@ message_log_maybe_newline (void)
9384 so the buffer M must NOT point to a Lisp string. */ 9368 so the buffer M must NOT point to a Lisp string. */
9385 9369
9386void 9370void
9387message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte) 9371message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
9388{ 9372{
9389 const unsigned char *msg = (const unsigned char *) m; 9373 const unsigned char *msg = (const unsigned char *) m;
9390 9374
@@ -9408,11 +9392,11 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
9408 bset_undo_list (current_buffer, Qt); 9392 bset_undo_list (current_buffer, Qt);
9409 9393
9410 oldpoint = message_dolog_marker1; 9394 oldpoint = message_dolog_marker1;
9411 set_marker_restricted (oldpoint, make_number (PT), Qnil); 9395 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
9412 oldbegv = message_dolog_marker2; 9396 oldbegv = message_dolog_marker2;
9413 set_marker_restricted (oldbegv, make_number (BEGV), Qnil); 9397 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
9414 oldzv = message_dolog_marker3; 9398 oldzv = message_dolog_marker3;
9415 set_marker_restricted (oldzv, make_number (ZV), Qnil); 9399 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
9416 GCPRO1 (old_deactivate_mark); 9400 GCPRO1 (old_deactivate_mark);
9417 9401
9418 if (PT == Z) 9402 if (PT == Z)
@@ -9463,13 +9447,14 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
9463 } 9447 }
9464 } 9448 }
9465 else if (nbytes) 9449 else if (nbytes)
9466 insert_1 (m, nbytes, 1, 0, 0); 9450 insert_1_both (m, chars_in_text (msg, nbytes), nbytes, 1, 0, 0);
9467 9451
9468 if (nlflag) 9452 if (nlflag)
9469 { 9453 {
9470 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte; 9454 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
9471 printmax_t dups; 9455 printmax_t dups;
9472 insert_1 ("\n", 1, 1, 0, 0); 9456
9457 insert_1_both ("\n", 1, 1, 1, 0, 0);
9473 9458
9474 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0); 9459 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
9475 this_bol = PT; 9460 this_bol = PT;
@@ -9498,7 +9483,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
9498 change message_log_check_duplicate. */ 9483 change message_log_check_duplicate. */
9499 int duplen = sprintf (dupstr, " [%"pMd" times]", dups); 9484 int duplen = sprintf (dupstr, " [%"pMd" times]", dups);
9500 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1); 9485 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
9501 insert_1 (dupstr, duplen, 1, 0, 1); 9486 insert_1_both (dupstr, duplen, duplen, 1, 0, 1);
9502 } 9487 }
9503 } 9488 }
9504 } 9489 }
@@ -9568,7 +9553,7 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
9568 9553
9569 for (i = 0; i < len; i++) 9554 for (i = 0; i < len; i++)
9570 { 9555 {
9571 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.') 9556 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
9572 seen_dots = 1; 9557 seen_dots = 1;
9573 if (p1[i] != p2[i]) 9558 if (p1[i] != p2[i])
9574 return seen_dots; 9559 return seen_dots;
@@ -9581,88 +9566,13 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
9581 char *pend; 9566 char *pend;
9582 intmax_t n = strtoimax ((char *) p1, &pend, 10); 9567 intmax_t n = strtoimax ((char *) p1, &pend, 10);
9583 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0) 9568 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
9584 return n+1; 9569 return n + 1;
9585 } 9570 }
9586 return 0; 9571 return 0;
9587} 9572}
9588 9573
9589 9574
9590/* Display an echo area message M with a specified length of NBYTES 9575/* Display an echo area message M with a specified length of NBYTES
9591 bytes. The string may include null characters. If M is 0, clear
9592 out any existing message, and let the mini-buffer text show
9593 through.
9594
9595 This may GC, so the buffer M must NOT point to a Lisp string. */
9596
9597void
9598message2 (const char *m, ptrdiff_t nbytes, int multibyte)
9599{
9600 /* First flush out any partial line written with print. */
9601 message_log_maybe_newline ();
9602 if (m)
9603 message_dolog (m, nbytes, 1, multibyte);
9604 message2_nolog (m, nbytes, multibyte);
9605}
9606
9607
9608/* The non-logging counterpart of message2. */
9609
9610void
9611message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte)
9612{
9613 struct frame *sf = SELECTED_FRAME ();
9614 message_enable_multibyte = multibyte;
9615
9616 if (FRAME_INITIAL_P (sf))
9617 {
9618 if (noninteractive_need_newline)
9619 putc ('\n', stderr);
9620 noninteractive_need_newline = 0;
9621 if (m)
9622 fwrite (m, nbytes, 1, stderr);
9623 if (cursor_in_echo_area == 0)
9624 fprintf (stderr, "\n");
9625 fflush (stderr);
9626 }
9627 /* A null message buffer means that the frame hasn't really been
9628 initialized yet. Error messages get reported properly by
9629 cmd_error, so this must be just an informative message; toss it. */
9630 else if (INTERACTIVE
9631 && sf->glyphs_initialized_p
9632 && FRAME_MESSAGE_BUF (sf))
9633 {
9634 Lisp_Object mini_window;
9635 struct frame *f;
9636
9637 /* Get the frame containing the mini-buffer
9638 that the selected frame is using. */
9639 mini_window = FRAME_MINIBUF_WINDOW (sf);
9640 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
9641
9642 FRAME_SAMPLE_VISIBILITY (f);
9643 if (FRAME_VISIBLE_P (sf)
9644 && ! FRAME_VISIBLE_P (f))
9645 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
9646
9647 if (m)
9648 {
9649 set_message (m, Qnil, nbytes, multibyte);
9650 if (minibuffer_auto_raise)
9651 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
9652 }
9653 else
9654 clear_message (1, 1);
9655
9656 do_pending_window_change (0);
9657 echo_area_display (1);
9658 do_pending_window_change (0);
9659 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
9660 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
9661 }
9662}
9663
9664
9665/* Display an echo area message M with a specified length of NBYTES
9666 bytes. The string may include null characters. If M is not a 9576 bytes. The string may include null characters. If M is not a
9667 string, clear out any existing message, and let the mini-buffer 9577 string, clear out any existing message, and let the mini-buffer
9668 text show through. 9578 text show through.
@@ -9670,7 +9580,7 @@ message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte)
9670 This function cancels echoing. */ 9580 This function cancels echoing. */
9671 9581
9672void 9582void
9673message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte) 9583message3 (Lisp_Object m)
9674{ 9584{
9675 struct gcpro gcpro1; 9585 struct gcpro gcpro1;
9676 9586
@@ -9682,13 +9592,15 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
9682 message_log_maybe_newline (); 9592 message_log_maybe_newline ();
9683 if (STRINGP (m)) 9593 if (STRINGP (m))
9684 { 9594 {
9595 ptrdiff_t nbytes = SBYTES (m);
9596 bool multibyte = STRING_MULTIBYTE (m);
9685 USE_SAFE_ALLOCA; 9597 USE_SAFE_ALLOCA;
9686 char *buffer = SAFE_ALLOCA (nbytes); 9598 char *buffer = SAFE_ALLOCA (nbytes);
9687 memcpy (buffer, SDATA (m), nbytes); 9599 memcpy (buffer, SDATA (m), nbytes);
9688 message_dolog (buffer, nbytes, 1, multibyte); 9600 message_dolog (buffer, nbytes, 1, multibyte);
9689 SAFE_FREE (); 9601 SAFE_FREE ();
9690 } 9602 }
9691 message3_nolog (m, nbytes, multibyte); 9603 message3_nolog (m);
9692 9604
9693 UNGCPRO; 9605 UNGCPRO;
9694} 9606}
@@ -9700,10 +9612,9 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
9700 and make this cancel echoing. */ 9612 and make this cancel echoing. */
9701 9613
9702void 9614void
9703message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte) 9615message3_nolog (Lisp_Object m)
9704{ 9616{
9705 struct frame *sf = SELECTED_FRAME (); 9617 struct frame *sf = SELECTED_FRAME ();
9706 message_enable_multibyte = multibyte;
9707 9618
9708 if (FRAME_INITIAL_P (sf)) 9619 if (FRAME_INITIAL_P (sf))
9709 { 9620 {
@@ -9711,36 +9622,28 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
9711 putc ('\n', stderr); 9622 putc ('\n', stderr);
9712 noninteractive_need_newline = 0; 9623 noninteractive_need_newline = 0;
9713 if (STRINGP (m)) 9624 if (STRINGP (m))
9714 fwrite (SDATA (m), nbytes, 1, stderr); 9625 fwrite (SDATA (m), SBYTES (m), 1, stderr);
9715 if (cursor_in_echo_area == 0) 9626 if (cursor_in_echo_area == 0)
9716 fprintf (stderr, "\n"); 9627 fprintf (stderr, "\n");
9717 fflush (stderr); 9628 fflush (stderr);
9718 } 9629 }
9719 /* A null message buffer means that the frame hasn't really been 9630 /* Error messages get reported properly by cmd_error, so this must be just an
9720 initialized yet. Error messages get reported properly by 9631 informative message; if the frame hasn't really been initialized yet, just
9721 cmd_error, so this must be just an informative message; toss it. */ 9632 toss it. */
9722 else if (INTERACTIVE 9633 else if (INTERACTIVE && sf->glyphs_initialized_p)
9723 && sf->glyphs_initialized_p
9724 && FRAME_MESSAGE_BUF (sf))
9725 { 9634 {
9726 Lisp_Object mini_window;
9727 Lisp_Object frame;
9728 struct frame *f;
9729
9730 /* Get the frame containing the mini-buffer 9635 /* Get the frame containing the mini-buffer
9731 that the selected frame is using. */ 9636 that the selected frame is using. */
9732 mini_window = FRAME_MINIBUF_WINDOW (sf); 9637 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
9733 frame = XWINDOW (mini_window)->frame; 9638 Lisp_Object frame = XWINDOW (mini_window)->frame;
9734 f = XFRAME (frame); 9639 struct frame *f = XFRAME (frame);
9735 9640
9736 FRAME_SAMPLE_VISIBILITY (f); 9641 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
9737 if (FRAME_VISIBLE_P (sf)
9738 && !FRAME_VISIBLE_P (f))
9739 Fmake_frame_visible (frame); 9642 Fmake_frame_visible (frame);
9740 9643
9741 if (STRINGP (m) && SCHARS (m) > 0) 9644 if (STRINGP (m) && SCHARS (m) > 0)
9742 { 9645 {
9743 set_message (NULL, m, nbytes, multibyte); 9646 set_message (m);
9744 if (minibuffer_auto_raise) 9647 if (minibuffer_auto_raise)
9745 Fraise_frame (frame); 9648 Fraise_frame (frame);
9746 /* Assume we are not echoing. 9649 /* Assume we are not echoing.
@@ -9770,7 +9673,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
9770void 9673void
9771message1 (const char *m) 9674message1 (const char *m)
9772{ 9675{
9773 message2 (m, (m ? strlen (m) : 0), 0); 9676 message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil);
9774} 9677}
9775 9678
9776 9679
@@ -9779,7 +9682,7 @@ message1 (const char *m)
9779void 9682void
9780message1_nolog (const char *m) 9683message1_nolog (const char *m)
9781{ 9684{
9782 message2_nolog (m, (m ? strlen (m) : 0), 0); 9685 message3_nolog (m ? make_unibyte_string (m, strlen (m)) : Qnil);
9783} 9686}
9784 9687
9785/* Display a message M which contains a single %s 9688/* Display a message M which contains a single %s
@@ -9816,10 +9719,10 @@ message_with_string (const char *m, Lisp_Object string, int log)
9816 mini_window = FRAME_MINIBUF_WINDOW (sf); 9719 mini_window = FRAME_MINIBUF_WINDOW (sf);
9817 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); 9720 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
9818 9721
9819 /* A null message buffer means that the frame hasn't really been 9722 /* Error messages get reported properly by cmd_error, so this must be
9820 initialized yet. Error messages get reported properly by 9723 just an informative message; if the frame hasn't really been
9821 cmd_error, so this must be just an informative message; toss it. */ 9724 initialized yet, just toss it. */
9822 if (FRAME_MESSAGE_BUF (f)) 9725 if (f->glyphs_initialized_p)
9823 { 9726 {
9824 Lisp_Object args[2], msg; 9727 Lisp_Object args[2], msg;
9825 struct gcpro gcpro1, gcpro2; 9728 struct gcpro gcpro1, gcpro2;
@@ -9832,9 +9735,9 @@ message_with_string (const char *m, Lisp_Object string, int log)
9832 msg = Fformat (2, args); 9735 msg = Fformat (2, args);
9833 9736
9834 if (log) 9737 if (log)
9835 message3 (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); 9738 message3 (msg);
9836 else 9739 else
9837 message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); 9740 message3_nolog (msg);
9838 9741
9839 UNGCPRO; 9742 UNGCPRO;
9840 9743
@@ -9878,20 +9781,20 @@ vmessage (const char *m, va_list ap)
9878 mini_window = FRAME_MINIBUF_WINDOW (sf); 9781 mini_window = FRAME_MINIBUF_WINDOW (sf);
9879 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); 9782 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
9880 9783
9881 /* A null message buffer means that the frame hasn't really been 9784 /* Error messages get reported properly by cmd_error, so this must be
9882 initialized yet. Error messages get reported properly by 9785 just an informative message; if the frame hasn't really been
9883 cmd_error, so this must be just an informative message; toss 9786 initialized yet, just toss it. */
9884 it. */ 9787 if (f->glyphs_initialized_p)
9885 if (FRAME_MESSAGE_BUF (f))
9886 { 9788 {
9887 if (m) 9789 if (m)
9888 { 9790 {
9889 ptrdiff_t len; 9791 ptrdiff_t len;
9792 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
9793 char *message_buf = alloca (maxsize + 1);
9890 9794
9891 len = doprnt (FRAME_MESSAGE_BUF (f), 9795 len = doprnt (message_buf, maxsize, m, (char *)0, ap);
9892 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
9893 9796
9894 message2 (FRAME_MESSAGE_BUF (f), len, 1); 9797 message3 (make_string (message_buf, len));
9895 } 9798 }
9896 else 9799 else
9897 message1 (0); 9800 message1 (0);
@@ -9942,8 +9845,7 @@ update_echo_area (void)
9942 { 9845 {
9943 Lisp_Object string; 9846 Lisp_Object string;
9944 string = Fcurrent_message (); 9847 string = Fcurrent_message ();
9945 message3 (string, SBYTES (string), 9848 message3 (string);
9946 !NILP (BVAR (current_buffer, enable_multibyte_characters)));
9947 } 9849 }
9948} 9850}
9949 9851
@@ -9979,7 +9881,7 @@ ensure_echo_area_buffers (void)
9979} 9881}
9980 9882
9981 9883
9982/* Call FN with args A1..A4 with either the current or last displayed 9884/* Call FN with args A1..A2 with either the current or last displayed
9983 echo_area_buffer as current buffer. 9885 echo_area_buffer as current buffer.
9984 9886
9985 WHICH zero means use the current message buffer 9887 WHICH zero means use the current message buffer
@@ -9997,8 +9899,8 @@ ensure_echo_area_buffers (void)
9997 9899
9998static int 9900static int
9999with_echo_area_buffer (struct window *w, int which, 9901with_echo_area_buffer (struct window *w, int which,
10000 int (*fn) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t), 9902 int (*fn) (ptrdiff_t, Lisp_Object),
10001 ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) 9903 ptrdiff_t a1, Lisp_Object a2)
10002{ 9904{
10003 Lisp_Object buffer; 9905 Lisp_Object buffer;
10004 int this_one, the_other, clear_buffer_p, rc; 9906 int this_one, the_other, clear_buffer_p, rc;
@@ -10071,7 +9973,7 @@ with_echo_area_buffer (struct window *w, int which,
10071 eassert (BEGV >= BEG); 9973 eassert (BEGV >= BEG);
10072 eassert (ZV <= Z && ZV >= BEGV); 9974 eassert (ZV <= Z && ZV >= BEGV);
10073 9975
10074 rc = fn (a1, a2, a3, a4); 9976 rc = fn (a1, a2);
10075 9977
10076 eassert (BEGV >= BEG); 9978 eassert (BEGV >= BEG);
10077 eassert (ZV <= Z && ZV >= BEGV); 9979 eassert (ZV <= Z && ZV >= BEGV);
@@ -10250,7 +10152,7 @@ display_echo_area (struct window *w)
10250 window_height_changed_p 10152 window_height_changed_p
10251 = with_echo_area_buffer (w, display_last_displayed_message_p, 10153 = with_echo_area_buffer (w, display_last_displayed_message_p,
10252 display_echo_area_1, 10154 display_echo_area_1,
10253 (intptr_t) w, Qnil, 0, 0); 10155 (intptr_t) w, Qnil);
10254 10156
10255 if (no_message_p) 10157 if (no_message_p)
10256 echo_area_buffer[i] = Qnil; 10158 echo_area_buffer[i] = Qnil;
@@ -10267,7 +10169,7 @@ display_echo_area (struct window *w)
10267 Value is non-zero if height of W was changed. */ 10169 Value is non-zero if height of W was changed. */
10268 10170
10269static int 10171static int
10270display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) 10172display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
10271{ 10173{
10272 intptr_t i1 = a1; 10174 intptr_t i1 = a1;
10273 struct window *w = (struct window *) i1; 10175 struct window *w = (struct window *) i1;
@@ -10312,8 +10214,7 @@ resize_echo_area_exactly (void)
10312 resize_exactly = Qnil; 10214 resize_exactly = Qnil;
10313 10215
10314 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1, 10216 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
10315 (intptr_t) w, resize_exactly, 10217 (intptr_t) w, resize_exactly);
10316 0, 0);
10317 if (resized_p) 10218 if (resized_p)
10318 { 10219 {
10319 ++windows_or_buffers_changed; 10220 ++windows_or_buffers_changed;
@@ -10331,7 +10232,7 @@ resize_echo_area_exactly (void)
10331 resize_mini_window returns. */ 10232 resize_mini_window returns. */
10332 10233
10333static int 10234static int
10334resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly, ptrdiff_t a3, ptrdiff_t a4) 10235resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly)
10335{ 10236{
10336 intptr_t i1 = a1; 10237 intptr_t i1 = a1;
10337 return resize_mini_window ((struct window *) i1, !NILP (exactly)); 10238 return resize_mini_window ((struct window *) i1, !NILP (exactly));
@@ -10500,7 +10401,7 @@ current_message (void)
10500 else 10401 else
10501 { 10402 {
10502 with_echo_area_buffer (0, 0, current_message_1, 10403 with_echo_area_buffer (0, 0, current_message_1,
10503 (intptr_t) &msg, Qnil, 0, 0); 10404 (intptr_t) &msg, Qnil);
10504 if (NILP (msg)) 10405 if (NILP (msg))
10505 echo_area_buffer[0] = Qnil; 10406 echo_area_buffer[0] = Qnil;
10506 } 10407 }
@@ -10510,7 +10411,7 @@ current_message (void)
10510 10411
10511 10412
10512static int 10413static int
10513current_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) 10414current_message_1 (ptrdiff_t a1, Lisp_Object a2)
10514{ 10415{
10515 intptr_t i1 = a1; 10416 intptr_t i1 = a1;
10516 Lisp_Object *msg = (Lisp_Object *) i1; 10417 Lisp_Object *msg = (Lisp_Object *) i1;
@@ -10542,14 +10443,8 @@ push_message (void)
10542void 10443void
10543restore_message (void) 10444restore_message (void)
10544{ 10445{
10545 Lisp_Object msg;
10546
10547 eassert (CONSP (Vmessage_stack)); 10446 eassert (CONSP (Vmessage_stack));
10548 msg = XCAR (Vmessage_stack); 10447 message3_nolog (XCAR (Vmessage_stack));
10549 if (STRINGP (msg))
10550 message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
10551 else
10552 message3_nolog (msg, 0, 0);
10553} 10448}
10554 10449
10555 10450
@@ -10592,16 +10487,16 @@ truncate_echo_area (ptrdiff_t nchars)
10592{ 10487{
10593 if (nchars == 0) 10488 if (nchars == 0)
10594 echo_area_buffer[0] = Qnil; 10489 echo_area_buffer[0] = Qnil;
10595 /* A null message buffer means that the frame hasn't really been
10596 initialized yet. Error messages get reported properly by
10597 cmd_error, so this must be just an informative message; toss it. */
10598 else if (!noninteractive 10490 else if (!noninteractive
10599 && INTERACTIVE 10491 && INTERACTIVE
10600 && !NILP (echo_area_buffer[0])) 10492 && !NILP (echo_area_buffer[0]))
10601 { 10493 {
10602 struct frame *sf = SELECTED_FRAME (); 10494 struct frame *sf = SELECTED_FRAME ();
10603 if (FRAME_MESSAGE_BUF (sf)) 10495 /* Error messages get reported properly by cmd_error, so this must be
10604 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0); 10496 just an informative message; if the frame hasn't really been
10497 initialized yet, just toss it. */
10498 if (sf->glyphs_initialized_p)
10499 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil);
10605 } 10500 }
10606} 10501}
10607 10502
@@ -10610,7 +10505,7 @@ truncate_echo_area (ptrdiff_t nchars)
10610 message to at most NCHARS characters. */ 10505 message to at most NCHARS characters. */
10611 10506
10612static int 10507static int
10613truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4) 10508truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2)
10614{ 10509{
10615 if (BEG + nchars < Z) 10510 if (BEG + nchars < Z)
10616 del_range (BEG + nchars, Z); 10511 del_range (BEG + nchars, Z);
@@ -10619,51 +10514,34 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4
10619 return 0; 10514 return 0;
10620} 10515}
10621 10516
10622/* Set the current message to a substring of S or STRING. 10517/* Set the current message to STRING. */
10623
10624 If STRING is a Lisp string, set the message to the first NBYTES
10625 bytes from STRING. NBYTES zero means use the whole string. If
10626 STRING is multibyte, the message will be displayed multibyte.
10627
10628 If S is not null, set the message to the first LEN bytes of S. LEN
10629 zero means use the whole string. MULTIBYTE_P non-zero means S is
10630 multibyte. Display the message multibyte in that case.
10631
10632 Doesn't GC, as with_echo_area_buffer binds Qinhibit_modification_hooks
10633 to t before calling set_message_1 (which calls insert).
10634 */
10635 10518
10636static void 10519static void
10637set_message (const char *s, Lisp_Object string, 10520set_message (Lisp_Object string)
10638 ptrdiff_t nbytes, int multibyte_p)
10639{ 10521{
10640 message_enable_multibyte 10522 eassert (STRINGP (string));
10641 = ((s && multibyte_p) 10523
10642 || (STRINGP (string) && STRING_MULTIBYTE (string))); 10524 message_enable_multibyte = STRING_MULTIBYTE (string);
10643 10525
10644 with_echo_area_buffer (0, -1, set_message_1, 10526 with_echo_area_buffer (0, -1, set_message_1, 0, string);
10645 (intptr_t) s, string, nbytes, multibyte_p);
10646 message_buf_print = 0; 10527 message_buf_print = 0;
10647 help_echo_showing_p = 0; 10528 help_echo_showing_p = 0;
10648 10529
10649 if (STRINGP (Vdebug_on_message) 10530 if (STRINGP (Vdebug_on_message)
10531 && STRINGP (string)
10650 && fast_string_match (Vdebug_on_message, string) >= 0) 10532 && fast_string_match (Vdebug_on_message, string) >= 0)
10651 call_debugger (list2 (Qerror, string)); 10533 call_debugger (list2 (Qerror, string));
10652} 10534}
10653 10535
10654 10536
10655/* Helper function for set_message. Arguments have the same meaning 10537/* Helper function for set_message. First argument is ignored and second
10656 as there, with A1 corresponding to S and A2 corresponding to STRING 10538 argument has the same meaning as for set_message.
10657 This function is called with the echo area buffer being 10539 This function is called with the echo area buffer being current. */
10658 current. */
10659 10540
10660static int 10541static int
10661set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multibyte_p) 10542set_message_1 (ptrdiff_t a1, Lisp_Object string)
10662{ 10543{
10663 intptr_t i1 = a1; 10544 eassert (STRINGP (string));
10664 const char *s = (const char *) i1;
10665 const unsigned char *msg = (const unsigned char *) s;
10666 Lisp_Object string = a2;
10667 10545
10668 /* Change multibyteness of the echo buffer appropriately. */ 10546 /* Change multibyteness of the echo buffer appropriately. */
10669 if (message_enable_multibyte 10547 if (message_enable_multibyte
@@ -10677,61 +10555,10 @@ set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multiby
10677 /* Insert new message at BEG. */ 10555 /* Insert new message at BEG. */
10678 TEMP_SET_PT_BOTH (BEG, BEG_BYTE); 10556 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
10679 10557
10680 if (STRINGP (string)) 10558 /* This function takes care of single/multibyte conversion.
10681 { 10559 We just have to ensure that the echo area buffer has the right
10682 ptrdiff_t nchars; 10560 setting of enable_multibyte_characters. */
10683 10561 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), 1);
10684 if (nbytes == 0)
10685 nbytes = SBYTES (string);
10686 nchars = string_byte_to_char (string, nbytes);
10687
10688 /* This function takes care of single/multibyte conversion. We
10689 just have to ensure that the echo area buffer has the right
10690 setting of enable_multibyte_characters. */
10691 insert_from_string (string, 0, 0, nchars, nbytes, 1);
10692 }
10693 else if (s)
10694 {
10695 if (nbytes == 0)
10696 nbytes = strlen (s);
10697
10698 if (multibyte_p && NILP (BVAR (current_buffer, enable_multibyte_characters)))
10699 {
10700 /* Convert from multi-byte to single-byte. */
10701 ptrdiff_t i;
10702 int c, n;
10703 char work[1];
10704
10705 /* Convert a multibyte string to single-byte. */
10706 for (i = 0; i < nbytes; i += n)
10707 {
10708 c = string_char_and_length (msg + i, &n);
10709 work[0] = (ASCII_CHAR_P (c)
10710 ? c
10711 : multibyte_char_to_unibyte (c));
10712 insert_1_both (work, 1, 1, 1, 0, 0);
10713 }
10714 }
10715 else if (!multibyte_p
10716 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
10717 {
10718 /* Convert from single-byte to multi-byte. */
10719 ptrdiff_t i;
10720 int c, n;
10721 unsigned char str[MAX_MULTIBYTE_LENGTH];
10722
10723 /* Convert a single-byte string to multibyte. */
10724 for (i = 0; i < nbytes; i++)
10725 {
10726 c = msg[i];
10727 MAKE_CHAR_MULTIBYTE (c);
10728 n = CHAR_STRING (c, str);
10729 insert_1_both ((char *) str, 1, n, 1, 0, 0);
10730 }
10731 }
10732 else
10733 insert_1 (s, nbytes, 1, 0, 0);
10734 }
10735 10562
10736 return 0; 10563 return 0;
10737} 10564}
@@ -10934,7 +10761,7 @@ window_buffer_changed (struct window *w)
10934 10761
10935 return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star) 10762 return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
10936 || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active))) 10763 || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
10937 != !NILP (w->region_showing))); 10764 != (w->region_showing != 0)));
10938} 10765}
10939 10766
10940/* Nonzero if W has %c in its mode line and mode line should be updated. */ 10767/* 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)
10942static int 10769static int
10943mode_line_update_needed (struct window *w) 10770mode_line_update_needed (struct window *w)
10944{ 10771{
10945 return (!NILP (w->column_number_displayed) 10772 return (w->column_number_displayed != -1
10946 && !(PT == w->last_point && !window_outdated (w)) 10773 && !(PT == w->last_point && !window_outdated (w))
10947 && (XFASTINT (w->column_number_displayed) != current_column ())); 10774 && (w->column_number_displayed != current_column ()));
10948} 10775}
10949 10776
10950/*********************************************************************** 10777/***********************************************************************
@@ -12922,10 +12749,10 @@ static void
12922reconsider_clip_changes (struct window *w, struct buffer *b) 12749reconsider_clip_changes (struct window *w, struct buffer *b)
12923{ 12750{
12924 if (b->clip_changed 12751 if (b->clip_changed
12925 && !NILP (w->window_end_valid) 12752 && w->window_end_valid
12926 && w->current_matrix->buffer == b 12753 && w->current_matrix->buffer == b
12927 && w->current_matrix->zv == BUF_ZV (b) 12754 && w->current_matrix->zv == BUF_ZV (b)
12928 && w->current_matrix->begv == BUF_BEGV (b)) 12755 && w->current_matrix->begv == BUF_BEGV (b))
12929 b->clip_changed = 0; 12756 b->clip_changed = 0;
12930 12757
12931 /* If display wasn't paused, and W is not a tool bar window, see if 12758 /* 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)
12933 we set b->clip_changed to 1 to force updating the screen. If 12760 we set b->clip_changed to 1 to force updating the screen. If
12934 b->clip_changed has already been set to 1, we can skip this 12761 b->clip_changed has already been set to 1, we can skip this
12935 check. */ 12762 check. */
12936 if (!b->clip_changed 12763 if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid)
12937 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
12938 { 12764 {
12939 ptrdiff_t pt; 12765 ptrdiff_t pt;
12940 12766
@@ -13082,7 +12908,6 @@ redisplay_internal (void)
13082 { 12908 {
13083 struct frame *f = XFRAME (frame); 12909 struct frame *f = XFRAME (frame);
13084 12910
13085 FRAME_SAMPLE_VISIBILITY (f);
13086 if (FRAME_VISIBLE_P (f)) 12911 if (FRAME_VISIBLE_P (f))
13087 ++number_of_visible_frames; 12912 ++number_of_visible_frames;
13088 clear_desired_matrices (f); 12913 clear_desired_matrices (f);
@@ -13199,16 +13024,15 @@ redisplay_internal (void)
13199 clear_garbaged_frames (); 13024 clear_garbaged_frames ();
13200 } 13025 }
13201 13026
13202
13203 /* If showing the region, and mark has changed, we must redisplay 13027 /* If showing the region, and mark has changed, we must redisplay
13204 the whole window. The assignment to this_line_start_pos prevents 13028 the whole window. The assignment to this_line_start_pos prevents
13205 the optimization directly below this if-statement. */ 13029 the optimization directly below this if-statement. */
13206 if (((!NILP (Vtransient_mark_mode) 13030 if (((!NILP (Vtransient_mark_mode)
13207 && !NILP (BVAR (XBUFFER (w->buffer), mark_active))) 13031 && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
13208 != !NILP (w->region_showing)) 13032 != (w->region_showing > 0))
13209 || (!NILP (w->region_showing) 13033 || (w->region_showing
13210 && !EQ (w->region_showing, 13034 && w->region_showing
13211 Fmarker_position (BVAR (XBUFFER (w->buffer), mark))))) 13035 != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
13212 CHARPOS (this_line_start_pos) = 0; 13036 CHARPOS (this_line_start_pos) = 0;
13213 13037
13214 /* Optimize the case that only the line containing the cursor in the 13038 /* Optimize the case that only the line containing the cursor in the
@@ -13328,7 +13152,7 @@ redisplay_internal (void)
13328 else if (XFASTINT (w->window_end_vpos) == this_line_vpos 13152 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
13329 && this_line_vpos > 0) 13153 && this_line_vpos > 0)
13330 wset_window_end_vpos (w, make_number (this_line_vpos - 1)); 13154 wset_window_end_vpos (w, make_number (this_line_vpos - 1));
13331 wset_window_end_valid (w, Qnil); 13155 w->window_end_valid = 0;
13332 13156
13333 /* Update hint: No need to try to scroll in update_window. */ 13157 /* Update hint: No need to try to scroll in update_window. */
13334 w->desired_matrix->no_scrolling_p = 1; 13158 w->desired_matrix->no_scrolling_p = 1;
@@ -13374,7 +13198,7 @@ redisplay_internal (void)
13374 && (EQ (selected_window, 13198 && (EQ (selected_window,
13375 BVAR (current_buffer, last_selected_window)) 13199 BVAR (current_buffer, last_selected_window))
13376 || highlight_nonselected_windows) 13200 || highlight_nonselected_windows)
13377 && NILP (w->region_showing) 13201 && !w->region_showing
13378 && NILP (Vshow_trailing_whitespace) 13202 && NILP (Vshow_trailing_whitespace)
13379 && !cursor_in_echo_area) 13203 && !cursor_in_echo_area)
13380 { 13204 {
@@ -13630,9 +13454,6 @@ redisplay_internal (void)
13630 13454
13631 if (XFRAME (frame)->visible) 13455 if (XFRAME (frame)->visible)
13632 this_is_visible = 1; 13456 this_is_visible = 1;
13633 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
13634 if (XFRAME (frame)->visible)
13635 this_is_visible = 1;
13636 13457
13637 if (this_is_visible) 13458 if (this_is_visible)
13638 new_count++; 13459 new_count++;
@@ -13722,50 +13543,43 @@ unwind_redisplay (Lisp_Object old_frame)
13722} 13543}
13723 13544
13724 13545
13725/* Mark the display of window W as accurate or inaccurate. If 13546/* Mark the display of leaf window W as accurate or inaccurate.
13726 ACCURATE_P is non-zero mark display of W as accurate. If 13547 If ACCURATE_P is non-zero mark display of W as accurate. If
13727 ACCURATE_P is zero, arrange for W to be redisplayed the next time 13548 ACCURATE_P is zero, arrange for W to be redisplayed the next
13728 redisplay_internal is called. */ 13549 time redisplay_internal is called. */
13729 13550
13730static void 13551static void
13731mark_window_display_accurate_1 (struct window *w, int accurate_p) 13552mark_window_display_accurate_1 (struct window *w, int accurate_p)
13732{ 13553{
13733 if (BUFFERP (w->buffer)) 13554 struct buffer *b = XBUFFER (w->buffer);
13734 {
13735 struct buffer *b = XBUFFER (w->buffer);
13736 13555
13737 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0; 13556 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
13738 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0; 13557 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
13739 w->last_had_star 13558 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
13740 = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
13741 13559
13742 if (accurate_p) 13560 if (accurate_p)
13743 { 13561 {
13744 b->clip_changed = 0; 13562 b->clip_changed = 0;
13745 b->prevent_redisplay_optimizations_p = 0; 13563 b->prevent_redisplay_optimizations_p = 0;
13746 13564
13747 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b); 13565 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
13748 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b); 13566 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
13749 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b); 13567 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
13750 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b); 13568 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
13751 13569
13752 w->current_matrix->buffer = b; 13570 w->current_matrix->buffer = b;
13753 w->current_matrix->begv = BUF_BEGV (b); 13571 w->current_matrix->begv = BUF_BEGV (b);
13754 w->current_matrix->zv = BUF_ZV (b); 13572 w->current_matrix->zv = BUF_ZV (b);
13755 13573
13756 w->last_cursor = w->cursor; 13574 w->last_cursor = w->cursor;
13757 w->last_cursor_off_p = w->cursor_off_p; 13575 w->last_cursor_off_p = w->cursor_off_p;
13758 13576
13759 if (w == XWINDOW (selected_window)) 13577 if (w == XWINDOW (selected_window))
13760 w->last_point = BUF_PT (b); 13578 w->last_point = BUF_PT (b);
13761 else 13579 else
13762 w->last_point = marker_position (w->pointm); 13580 w->last_point = marker_position (w->pointm);
13763 }
13764 }
13765 13581
13766 if (accurate_p) 13582 w->window_end_valid = 1;
13767 {
13768 wset_window_end_valid (w, w->buffer);
13769 w->update_mode_line = 0; 13583 w->update_mode_line = 0;
13770 } 13584 }
13771} 13585}
@@ -13784,25 +13598,21 @@ mark_window_display_accurate (Lisp_Object window, int accurate_p)
13784 for (; !NILP (window); window = w->next) 13598 for (; !NILP (window); window = w->next)
13785 { 13599 {
13786 w = XWINDOW (window); 13600 w = XWINDOW (window);
13787 mark_window_display_accurate_1 (w, accurate_p);
13788
13789 if (!NILP (w->vchild)) 13601 if (!NILP (w->vchild))
13790 mark_window_display_accurate (w->vchild, accurate_p); 13602 mark_window_display_accurate (w->vchild, accurate_p);
13791 if (!NILP (w->hchild)) 13603 else if (!NILP (w->hchild))
13792 mark_window_display_accurate (w->hchild, accurate_p); 13604 mark_window_display_accurate (w->hchild, accurate_p);
13605 else if (BUFFERP (w->buffer))
13606 mark_window_display_accurate_1 (w, accurate_p);
13793 } 13607 }
13794 13608
13795 if (accurate_p) 13609 if (accurate_p)
13796 { 13610 update_overlay_arrows (1);
13797 update_overlay_arrows (1);
13798 }
13799 else 13611 else
13800 { 13612 /* Force a thorough redisplay the next time by setting
13801 /* Force a thorough redisplay the next time by setting 13613 last_arrow_position and last_arrow_string to t, which is
13802 last_arrow_position and last_arrow_string to t, which is 13614 unequal to any useful value of Voverlay_arrow_... */
13803 unequal to any useful value of Voverlay_arrow_... */ 13615 update_overlay_arrows (-1);
13804 update_overlay_arrows (-1);
13805 }
13806} 13616}
13807 13617
13808 13618
@@ -14797,14 +14607,24 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14797 else 14607 else
14798 { 14608 {
14799 struct text_pos scroll_margin_pos = startp; 14609 struct text_pos scroll_margin_pos = startp;
14610 int y_offset = 0;
14800 14611
14801 /* See if point is inside the scroll margin at the top of the 14612 /* See if point is inside the scroll margin at the top of the
14802 window. */ 14613 window. */
14803 if (this_scroll_margin) 14614 if (this_scroll_margin)
14804 { 14615 {
14616 int y_start;
14617
14805 start_display (&it, w, startp); 14618 start_display (&it, w, startp);
14619 y_start = it.current_y;
14806 move_it_vertically (&it, this_scroll_margin); 14620 move_it_vertically (&it, this_scroll_margin);
14807 scroll_margin_pos = it.current.pos; 14621 scroll_margin_pos = it.current.pos;
14622 /* If we didn't move enough before hitting ZV, request
14623 additional amount of scroll, to move point out of the
14624 scroll margin. */
14625 if (IT_CHARPOS (it) == ZV
14626 && it.current_y - y_start < this_scroll_margin)
14627 y_offset = this_scroll_margin - (it.current_y - y_start);
14808 } 14628 }
14809 14629
14810 if (PT < CHARPOS (scroll_margin_pos)) 14630 if (PT < CHARPOS (scroll_margin_pos))
@@ -14831,6 +14651,9 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14831 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos)) 14651 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
14832 return SCROLLING_FAILED; 14652 return SCROLLING_FAILED;
14833 14653
14654 /* Additional scroll for when ZV was too close to point. */
14655 dy += y_offset;
14656
14834 /* Compute new window start. */ 14657 /* Compute new window start. */
14835 start_display (&it, w, startp); 14658 start_display (&it, w, startp);
14836 14659
@@ -14885,7 +14708,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14885 if (!just_this_one_p 14708 if (!just_this_one_p
14886 || current_buffer->clip_changed 14709 || current_buffer->clip_changed
14887 || BEG_UNCHANGED < CHARPOS (startp)) 14710 || BEG_UNCHANGED < CHARPOS (startp))
14888 wset_base_line_number (w, Qnil); 14711 w->base_line_number = 0;
14889 14712
14890 /* If cursor ends up on a partially visible line, 14713 /* If cursor ends up on a partially visible line,
14891 treat that as being off the bottom of the screen. */ 14714 treat that as being off the bottom of the screen. */
@@ -14938,7 +14761,7 @@ compute_window_start_on_continuation_line (struct window *w)
14938 SET_TEXT_POS (start_pos, ZV, ZV_BYTE); 14761 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
14939 14762
14940 /* Find the start of the continued line. This should be fast 14763 /* Find the start of the continued line. This should be fast
14941 because scan_buffer is fast (newline cache). */ 14764 because find_newline is fast (newline cache). */
14942 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0); 14765 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
14943 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), 14766 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
14944 row, DEFAULT_FACE_ID); 14767 row, DEFAULT_FACE_ID);
@@ -15034,7 +14857,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
15034 region exists, cursor movement has to do more than just 14857 region exists, cursor movement has to do more than just
15035 set the cursor. */ 14858 set the cursor. */
15036 && markpos_of_region () < 0 14859 && markpos_of_region () < 0
15037 && NILP (w->region_showing) 14860 && !w->region_showing
15038 && NILP (Vshow_trailing_whitespace) 14861 && NILP (Vshow_trailing_whitespace)
15039 /* This code is not used for mini-buffer for the sake of the case 14862 /* This code is not used for mini-buffer for the sake of the case
15040 of redisplaying to replace an echo area message; since in 14863 of redisplaying to replace an echo area message; since in
@@ -15471,7 +15294,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15471 set_buffer_internal_1 (XBUFFER (w->buffer)); 15294 set_buffer_internal_1 (XBUFFER (w->buffer));
15472 15295
15473 current_matrix_up_to_date_p 15296 current_matrix_up_to_date_p
15474 = (!NILP (w->window_end_valid) 15297 = (w->window_end_valid
15475 && !current_buffer->clip_changed 15298 && !current_buffer->clip_changed
15476 && !current_buffer->prevent_redisplay_optimizations_p 15299 && !current_buffer->prevent_redisplay_optimizations_p
15477 && !window_outdated (w)); 15300 && !window_outdated (w));
@@ -15494,7 +15317,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15494 specbind (Qinhibit_point_motion_hooks, Qt); 15317 specbind (Qinhibit_point_motion_hooks, Qt);
15495 15318
15496 buffer_unchanged_p 15319 buffer_unchanged_p
15497 = (!NILP (w->window_end_valid) 15320 = (w->window_end_valid
15498 && !current_buffer->clip_changed 15321 && !current_buffer->clip_changed
15499 && !window_outdated (w)); 15322 && !window_outdated (w));
15500 15323
@@ -15507,7 +15330,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15507 if (XMARKER (w->start)->buffer == current_buffer) 15330 if (XMARKER (w->start)->buffer == current_buffer)
15508 compute_window_start_on_continuation_line (w); 15331 compute_window_start_on_continuation_line (w);
15509 15332
15510 wset_window_end_valid (w, Qnil); 15333 w->window_end_valid = 0;
15511 } 15334 }
15512 15335
15513 /* Some sanity checks. */ 15336 /* Some sanity checks. */
@@ -15596,11 +15419,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15596 15419
15597 w->force_start = 0; 15420 w->force_start = 0;
15598 w->vscroll = 0; 15421 w->vscroll = 0;
15599 wset_window_end_valid (w, Qnil); 15422 w->window_end_valid = 0;
15600 15423
15601 /* Forget any recorded base line for line number display. */ 15424 /* Forget any recorded base line for line number display. */
15602 if (!buffer_unchanged_p) 15425 if (!buffer_unchanged_p)
15603 wset_base_line_number (w, Qnil); 15426 w->base_line_number = 0;
15604 15427
15605 /* Redisplay the mode line. Select the buffer properly for that. 15428 /* Redisplay the mode line. Select the buffer properly for that.
15606 Also, run the hook window-scroll-functions 15429 Also, run the hook window-scroll-functions
@@ -15840,7 +15663,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15840 || current_buffer->clip_changed 15663 || current_buffer->clip_changed
15841 || BEG_UNCHANGED < CHARPOS (startp)) 15664 || BEG_UNCHANGED < CHARPOS (startp))
15842 /* Forget any recorded base line for line number display. */ 15665 /* Forget any recorded base line for line number display. */
15843 wset_base_line_number (w, Qnil); 15666 w->base_line_number = 0;
15844 15667
15845 if (!cursor_row_fully_visible_p (w, 1, 0)) 15668 if (!cursor_row_fully_visible_p (w, 1, 0))
15846 { 15669 {
@@ -15907,11 +15730,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15907 debug_method_add (w, "recenter"); 15730 debug_method_add (w, "recenter");
15908#endif 15731#endif
15909 15732
15910 /* w->vscroll = 0; */
15911
15912 /* Forget any previously recorded base line for line number display. */ 15733 /* Forget any previously recorded base line for line number display. */
15913 if (!buffer_unchanged_p) 15734 if (!buffer_unchanged_p)
15914 wset_base_line_number (w, Qnil); 15735 w->base_line_number = 0;
15915 15736
15916 /* Determine the window start relative to point. */ 15737 /* Determine the window start relative to point. */
15917 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); 15738 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)
16045 line.) */ 15866 line.) */
16046 if (w->cursor.vpos < 0) 15867 if (w->cursor.vpos < 0)
16047 { 15868 {
16048 if (!NILP (w->window_end_valid) 15869 if (w->window_end_valid && PT >= Z - XFASTINT (w->window_end_pos))
16049 && PT >= Z - XFASTINT (w->window_end_pos))
16050 { 15870 {
16051 clear_glyph_matrix (w->desired_matrix); 15871 clear_glyph_matrix (w->desired_matrix);
16052 move_it_by_lines (&it, 1); 15872 move_it_by_lines (&it, 1);
@@ -16132,10 +15952,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
16132 && !FRAME_WINDOW_P (f) 15952 && !FRAME_WINDOW_P (f)
16133 && !WINDOW_FULL_WIDTH_P (w)) 15953 && !WINDOW_FULL_WIDTH_P (w))
16134 /* Line number to display. */ 15954 /* Line number to display. */
16135 || INTEGERP (w->base_line_pos) 15955 || w->base_line_pos > 0
16136 /* Column number is displayed and different from the one displayed. */ 15956 /* Column number is displayed and different from the one displayed. */
16137 || (!NILP (w->column_number_displayed) 15957 || (w->column_number_displayed != -1
16138 && (XFASTINT (w->column_number_displayed) != current_column ()))) 15958 && (w->column_number_displayed != current_column ())))
16139 /* This means that the window has a mode line. */ 15959 /* This means that the window has a mode line. */
16140 && (WINDOW_WANTS_MODELINE_P (w) 15960 && (WINDOW_WANTS_MODELINE_P (w)
16141 || WINDOW_WANTS_HEADER_LINE_P (w))) 15961 || WINDOW_WANTS_HEADER_LINE_P (w)))
@@ -16166,11 +15986,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
16166 goto need_larger_matrices; 15986 goto need_larger_matrices;
16167 } 15987 }
16168 15988
16169 if (!line_number_displayed 15989 if (!line_number_displayed && w->base_line_pos != -1)
16170 && !BUFFERP (w->base_line_pos))
16171 { 15990 {
16172 wset_base_line_pos (w, Qnil); 15991 w->base_line_pos = 0;
16173 wset_base_line_number (w, Qnil); 15992 w->base_line_number = 0;
16174 } 15993 }
16175 15994
16176 finish_menu_bars: 15995 finish_menu_bars:
@@ -16363,7 +16182,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
16363 } 16182 }
16364 16183
16365 /* But that is not valid info until redisplay finishes. */ 16184 /* But that is not valid info until redisplay finishes. */
16366 wset_window_end_valid (w, Qnil); 16185 w->window_end_valid = 0;
16367 return 1; 16186 return 1;
16368} 16187}
16369 16188
@@ -16407,7 +16226,7 @@ try_window_reusing_current_matrix (struct window *w)
16407 16226
16408 /* Can't do this if region may have changed. */ 16227 /* Can't do this if region may have changed. */
16409 if (0 <= markpos_of_region () 16228 if (0 <= markpos_of_region ()
16410 || !NILP (w->region_showing) 16229 || w->region_showing
16411 || !NILP (Vshow_trailing_whitespace)) 16230 || !NILP (Vshow_trailing_whitespace))
16412 return 0; 16231 return 0;
16413 16232
@@ -16610,7 +16429,7 @@ try_window_reusing_current_matrix (struct window *w)
16610 wset_window_end_pos (w, make_number (Z - ZV)); 16429 wset_window_end_pos (w, make_number (Z - ZV));
16611 wset_window_end_vpos (w, make_number (0)); 16430 wset_window_end_vpos (w, make_number (0));
16612 } 16431 }
16613 wset_window_end_valid (w, Qnil); 16432 w->window_end_valid = 0;
16614 16433
16615 /* Update hint: don't try scrolling again in update_window. */ 16434 /* Update hint: don't try scrolling again in update_window. */
16616 w->desired_matrix->no_scrolling_p = 1; 16435 w->desired_matrix->no_scrolling_p = 1;
@@ -16808,7 +16627,7 @@ try_window_reusing_current_matrix (struct window *w)
16808 (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled)); 16627 (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
16809 } 16628 }
16810 16629
16811 wset_window_end_valid (w, Qnil); 16630 w->window_end_valid = 0;
16812 w->desired_matrix->no_scrolling_p = 1; 16631 w->desired_matrix->no_scrolling_p = 1;
16813 16632
16814#ifdef GLYPH_DEBUG 16633#ifdef GLYPH_DEBUG
@@ -16941,7 +16760,7 @@ find_first_unchanged_at_end_row (struct window *w,
16941 16760
16942 /* Display must not have been paused, otherwise the current matrix 16761 /* Display must not have been paused, otherwise the current matrix
16943 is not up to date. */ 16762 is not up to date. */
16944 eassert (!NILP (w->window_end_valid)); 16763 eassert (w->window_end_valid);
16945 16764
16946 /* A value of window_end_pos >= END_UNCHANGED means that the window 16765 /* A value of window_end_pos >= END_UNCHANGED means that the window
16947 end is in the range of changed text. If so, there is no 16766 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,
17125 16944
17126/* Try to redisplay window W by reusing its existing display. W's 16945/* Try to redisplay window W by reusing its existing display. W's
17127 current matrix must be up to date when this function is called, 16946 current matrix must be up to date when this function is called,
17128 i.e. window_end_valid must not be nil. 16947 i.e. window_end_valid must be nonzero.
17129 16948
17130 Value is 16949 Value is
17131 16950
@@ -17233,7 +17052,7 @@ try_window_id (struct window *w)
17233 GIVE_UP (7); 17052 GIVE_UP (7);
17234 17053
17235 /* Verify that display wasn't paused. */ 17054 /* Verify that display wasn't paused. */
17236 if (NILP (w->window_end_valid)) 17055 if (!w->window_end_valid)
17237 GIVE_UP (8); 17056 GIVE_UP (8);
17238 17057
17239 /* Can't use this if highlighting a region because a cursor movement 17058 /* Can't use this if highlighting a region because a cursor movement
@@ -17246,7 +17065,7 @@ try_window_id (struct window *w)
17246 GIVE_UP (11); 17065 GIVE_UP (11);
17247 17066
17248 /* Likewise if showing a region. */ 17067 /* Likewise if showing a region. */
17249 if (!NILP (w->region_showing)) 17068 if (w->region_showing)
17250 GIVE_UP (10); 17069 GIVE_UP (10);
17251 17070
17252 /* Can't use this if overlay arrow position and/or string have 17071 /* Can't use this if overlay arrow position and/or string have
@@ -17884,7 +17703,7 @@ try_window_id (struct window *w)
17884 debug_end_vpos = XFASTINT (w->window_end_vpos)); 17703 debug_end_vpos = XFASTINT (w->window_end_vpos));
17885 17704
17886 /* Record that display has not been completed. */ 17705 /* Record that display has not been completed. */
17887 wset_window_end_valid (w, Qnil); 17706 w->window_end_valid = 0;
17888 w->desired_matrix->no_scrolling_p = 1; 17707 w->desired_matrix->no_scrolling_p = 1;
17889 return 3; 17708 return 3;
17890 17709
@@ -18248,7 +18067,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
18248 const unsigned char *arrow_end = arrow_string + arrow_len; 18067 const unsigned char *arrow_end = arrow_string + arrow_len;
18249 const unsigned char *p; 18068 const unsigned char *p;
18250 struct it it; 18069 struct it it;
18251 int multibyte_p; 18070 bool multibyte_p;
18252 int n_glyphs_before; 18071 int n_glyphs_before;
18253 18072
18254 set_buffer_temp (buffer); 18073 set_buffer_temp (buffer);
@@ -19333,7 +19152,7 @@ display_line (struct it *it)
19333 } 19152 }
19334 19153
19335 /* Is IT->w showing the region? */ 19154 /* Is IT->w showing the region? */
19336 wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil); 19155 it->w->region_showing = it->region_beg_charpos > 0 ? it->region_beg_charpos : 0;
19337 19156
19338 /* Clear the result glyph row and enable it. */ 19157 /* Clear the result glyph row and enable it. */
19339 prepare_desired_row (row); 19158 prepare_desired_row (row);
@@ -20096,10 +19915,7 @@ See also `bidi-paragraph-direction'. */)
20096 to make sure we are within that paragraph. To that end, find 19915 to make sure we are within that paragraph. To that end, find
20097 the previous non-empty line. */ 19916 the previous non-empty line. */
20098 if (pos >= ZV && pos > BEGV) 19917 if (pos >= ZV && pos > BEGV)
20099 { 19918 DEC_BOTH (pos, bytepos);
20100 pos--;
20101 bytepos = CHAR_TO_BYTE (pos);
20102 }
20103 if (fast_looking_at (build_string ("[\f\t ]*\n"), 19919 if (fast_looking_at (build_string ("[\f\t ]*\n"),
20104 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0) 19920 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
20105 { 19921 {
@@ -20337,7 +20153,7 @@ display_mode_lines (struct window *w)
20337 20153
20338 /* These will be set while the mode line specs are processed. */ 20154 /* These will be set while the mode line specs are processed. */
20339 line_number_displayed = 0; 20155 line_number_displayed = 0;
20340 wset_column_number_displayed (w, Qnil); 20156 w->column_number_displayed = -1;
20341 20157
20342 if (WINDOW_WANTS_MODELINE_P (w)) 20158 if (WINDOW_WANTS_MODELINE_P (w))
20343 { 20159 {
@@ -20679,7 +20495,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
20679 risky); 20495 risky);
20680 else if (c != 0) 20496 else if (c != 0)
20681 { 20497 {
20682 int multibyte; 20498 bool multibyte;
20683 ptrdiff_t bytepos, charpos; 20499 ptrdiff_t bytepos, charpos;
20684 const char *spec; 20500 const char *spec;
20685 Lisp_Object string; 20501 Lisp_Object string;
@@ -21284,7 +21100,7 @@ static char *
21284decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_flag) 21100decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_flag)
21285{ 21101{
21286 Lisp_Object val; 21102 Lisp_Object val;
21287 int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); 21103 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
21288 const unsigned char *eol_str; 21104 const unsigned char *eol_str;
21289 int eol_str_len; 21105 int eol_str_len;
21290 /* The EOL conversion we are using. */ 21106 /* The EOL conversion we are using. */
@@ -21360,8 +21176,7 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
21360 returned with spaces to that value. Return a Lisp string in 21176 returned with spaces to that value. Return a Lisp string in
21361 *STRING if the resulting string is taken from that Lisp string. 21177 *STRING if the resulting string is taken from that Lisp string.
21362 21178
21363 Note we operate on the current buffer for most purposes, 21179 Note we operate on the current buffer for most purposes. */
21364 the exception being w->base_line_pos. */
21365 21180
21366static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; 21181static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
21367 21182
@@ -21472,7 +21287,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
21472 else 21287 else
21473 { 21288 {
21474 ptrdiff_t col = current_column (); 21289 ptrdiff_t col = current_column ();
21475 wset_column_number_displayed (w, make_number (col)); 21290 w->column_number_displayed = col;
21476 pint2str (decode_mode_spec_buf, width, col); 21291 pint2str (decode_mode_spec_buf, width, col);
21477 return decode_mode_spec_buf; 21292 return decode_mode_spec_buf;
21478 } 21293 }
@@ -21531,27 +21346,24 @@ decode_mode_spec (struct window *w, register int c, int field_width,
21531 21346
21532 /* If we decided that this buffer isn't suitable for line numbers, 21347 /* If we decided that this buffer isn't suitable for line numbers,
21533 don't forget that too fast. */ 21348 don't forget that too fast. */
21534 if (EQ (w->base_line_pos, w->buffer)) 21349 if (w->base_line_pos == -1)
21535 goto no_value; 21350 goto no_value;
21536 /* But do forget it, if the window shows a different buffer now. */
21537 else if (BUFFERP (w->base_line_pos))
21538 wset_base_line_pos (w, Qnil);
21539 21351
21540 /* If the buffer is very big, don't waste time. */ 21352 /* If the buffer is very big, don't waste time. */
21541 if (INTEGERP (Vline_number_display_limit) 21353 if (INTEGERP (Vline_number_display_limit)
21542 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit)) 21354 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
21543 { 21355 {
21544 wset_base_line_pos (w, Qnil); 21356 w->base_line_pos = 0;
21545 wset_base_line_number (w, Qnil); 21357 w->base_line_number = 0;
21546 goto no_value; 21358 goto no_value;
21547 } 21359 }
21548 21360
21549 if (INTEGERP (w->base_line_number) 21361 if (w->base_line_number > 0
21550 && INTEGERP (w->base_line_pos) 21362 && w->base_line_pos > 0
21551 && XFASTINT (w->base_line_pos) <= startpos) 21363 && w->base_line_pos <= startpos)
21552 { 21364 {
21553 line = XFASTINT (w->base_line_number); 21365 line = w->base_line_number;
21554 linepos = XFASTINT (w->base_line_pos); 21366 linepos = w->base_line_pos;
21555 linepos_byte = buf_charpos_to_bytepos (b, linepos); 21367 linepos_byte = buf_charpos_to_bytepos (b, linepos);
21556 } 21368 }
21557 else 21369 else
@@ -21574,8 +21386,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
21574 go back past it. */ 21386 go back past it. */
21575 if (startpos == BUF_BEGV (b)) 21387 if (startpos == BUF_BEGV (b))
21576 { 21388 {
21577 wset_base_line_number (w, make_number (topline)); 21389 w->base_line_number = topline;
21578 wset_base_line_pos (w, make_number (BUF_BEGV (b))); 21390 w->base_line_pos = BUF_BEGV (b);
21579 } 21391 }
21580 else if (nlines < height + 25 || nlines > height * 3 + 50 21392 else if (nlines < height + 25 || nlines > height * 3 + 50
21581 || linepos == BUF_BEGV (b)) 21393 || linepos == BUF_BEGV (b))
@@ -21601,13 +21413,13 @@ decode_mode_spec (struct window *w, register int c, int field_width,
21601 give up on line numbers for this window. */ 21413 give up on line numbers for this window. */
21602 if (position == limit_byte && limit == startpos - distance) 21414 if (position == limit_byte && limit == startpos - distance)
21603 { 21415 {
21604 wset_base_line_pos (w, w->buffer); 21416 w->base_line_pos = -1;
21605 wset_base_line_number (w, Qnil); 21417 w->base_line_number = 0;
21606 goto no_value; 21418 goto no_value;
21607 } 21419 }
21608 21420
21609 wset_base_line_number (w, make_number (topline - nlines)); 21421 w->base_line_number = topline - nlines;
21610 wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position))); 21422 w->base_line_pos = BYTE_TO_CHAR (position);
21611 } 21423 }
21612 21424
21613 /* Now count lines from the start pos to point. */ 21425 /* 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,
21729 return "@"; 21541 return "@";
21730 } 21542 }
21731 21543
21732 case 't': /* indicate TEXT or BINARY */
21733 return "T";
21734
21735 case 'z': 21544 case 'z':
21736 /* coding-system (not including end-of-line format) */ 21545 /* coding-system (not including end-of-line format) */
21737 case 'Z': 21546 case 'Z':
@@ -21781,11 +21590,15 @@ decode_mode_spec (struct window *w, register int c, int field_width,
21781} 21590}
21782 21591
21783 21592
21784/* Count up to COUNT lines starting from START_BYTE. 21593/* Count up to COUNT lines starting from START_BYTE. COUNT negative
21785 But don't go beyond LIMIT_BYTE. 21594 means count lines back from START_BYTE. But don't go beyond
21786 Return the number of lines thus found (always nonnegative). 21595 LIMIT_BYTE. Return the number of lines thus found (always
21596 nonnegative).
21787 21597
21788 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */ 21598 Set *BYTE_POS_PTR to the byte position where we stopped. This is
21599 either the position COUNT lines after/before START_BYTE, if we
21600 found COUNT lines, or LIMIT_BYTE if we hit the limit before finding
21601 COUNT lines. */
21789 21602
21790static ptrdiff_t 21603static ptrdiff_t
21791display_count_lines (ptrdiff_t start_byte, 21604display_count_lines (ptrdiff_t start_byte,
@@ -21812,31 +21625,36 @@ display_count_lines (ptrdiff_t start_byte,
21812 ceiling = min (limit_byte - 1, ceiling); 21625 ceiling = min (limit_byte - 1, ceiling);
21813 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; 21626 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
21814 base = (cursor = BYTE_POS_ADDR (start_byte)); 21627 base = (cursor = BYTE_POS_ADDR (start_byte));
21815 while (1) 21628
21629 do
21816 { 21630 {
21817 if (selective_display) 21631 if (selective_display)
21818 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr) 21632 {
21819 ; 21633 while (*cursor != '\n' && *cursor != 015
21634 && ++cursor != ceiling_addr)
21635 continue;
21636 if (cursor == ceiling_addr)
21637 break;
21638 }
21820 else 21639 else
21821 while (*cursor != '\n' && ++cursor != ceiling_addr) 21640 {
21822 ; 21641 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
21642 if (! cursor)
21643 break;
21644 }
21823 21645
21824 if (cursor != ceiling_addr) 21646 cursor++;
21647
21648 if (--count == 0)
21825 { 21649 {
21826 if (--count == 0) 21650 start_byte += cursor - base;
21827 { 21651 *byte_pos_ptr = start_byte;
21828 start_byte += cursor - base + 1; 21652 return orig_count;
21829 *byte_pos_ptr = start_byte;
21830 return orig_count;
21831 }
21832 else
21833 if (++cursor == ceiling_addr)
21834 break;
21835 } 21653 }
21836 else
21837 break;
21838 } 21654 }
21839 start_byte += cursor - base; 21655 while (cursor < ceiling_addr);
21656
21657 start_byte += ceiling_addr - base;
21840 } 21658 }
21841 } 21659 }
21842 else 21660 else
@@ -21845,35 +21663,35 @@ display_count_lines (ptrdiff_t start_byte,
21845 { 21663 {
21846 ceiling = BUFFER_FLOOR_OF (start_byte - 1); 21664 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
21847 ceiling = max (limit_byte, ceiling); 21665 ceiling = max (limit_byte, ceiling);
21848 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; 21666 ceiling_addr = BYTE_POS_ADDR (ceiling);
21849 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); 21667 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
21850 while (1) 21668 while (1)
21851 { 21669 {
21852 if (selective_display) 21670 if (selective_display)
21853 while (--cursor != ceiling_addr 21671 {
21854 && *cursor != '\n' && *cursor != 015) 21672 while (--cursor >= ceiling_addr
21855 ; 21673 && *cursor != '\n' && *cursor != 015)
21674 continue;
21675 if (cursor < ceiling_addr)
21676 break;
21677 }
21856 else 21678 else
21857 while (--cursor != ceiling_addr && *cursor != '\n') 21679 {
21858 ; 21680 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
21681 if (! cursor)
21682 break;
21683 }
21859 21684
21860 if (cursor != ceiling_addr) 21685 if (++count == 0)
21861 { 21686 {
21862 if (++count == 0) 21687 start_byte += cursor - base + 1;
21863 { 21688 *byte_pos_ptr = start_byte;
21864 start_byte += cursor - base + 1; 21689 /* When scanning backwards, we should
21865 *byte_pos_ptr = start_byte; 21690 not count the newline posterior to which we stop. */
21866 /* When scanning backwards, we should 21691 return - orig_count - 1;
21867 not count the newline posterior to which we stop. */
21868 return - orig_count - 1;
21869 }
21870 } 21692 }
21871 else
21872 break;
21873 } 21693 }
21874 /* Here we add 1 to compensate for the last decrement 21694 start_byte += ceiling_addr - base;
21875 of CURSOR, which took it past the valid range. */
21876 start_byte += cursor - base + 1;
21877 } 21695 }
21878 } 21696 }
21879 21697
@@ -27793,7 +27611,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
27793 And verify the buffer's text has not changed. */ 27611 And verify the buffer's text has not changed. */
27794 b = XBUFFER (w->buffer); 27612 b = XBUFFER (w->buffer);
27795 if (part == ON_TEXT 27613 if (part == ON_TEXT
27796 && EQ (w->window_end_valid, w->buffer) 27614 && w->window_end_valid
27797 && w->last_modified == BUF_MODIFF (b) 27615 && w->last_modified == BUF_MODIFF (b)
27798 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b)) 27616 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b))
27799 { 27617 {
@@ -28426,6 +28244,9 @@ x_draw_vertical_border (struct window *w)
28426 if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame))) 28244 if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
28427 return; 28245 return;
28428 28246
28247 /* Note: It is necessary to redraw both the left and the right
28248 borders, for when only this single window W is being
28249 redisplayed. */
28429 if (!WINDOW_RIGHTMOST_P (w) 28250 if (!WINDOW_RIGHTMOST_P (w)
28430 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) 28251 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
28431 { 28252 {
@@ -28439,8 +28260,8 @@ x_draw_vertical_border (struct window *w)
28439 28260
28440 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1); 28261 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
28441 } 28262 }
28442 else if (!WINDOW_LEFTMOST_P (w) 28263 if (!WINDOW_LEFTMOST_P (w)
28443 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) 28264 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
28444 { 28265 {
28445 int x0, x1, y0, y1; 28266 int x0, x1, y0, y1;
28446 28267
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. */)
1585 for (i = nfonts - 1; i >= 0; --i) 1585 for (i = nfonts - 1; i >= 0; --i)
1586 { 1586 {
1587 Lisp_Object font = AREF (vec, i); 1587 Lisp_Object font = AREF (vec, i);
1588 Lisp_Object v = Fmake_vector (make_number (8), Qnil); 1588 Lisp_Object v = make_uninit_vector (8);
1589 int point; 1589 int point;
1590 Lisp_Object spacing; 1590 Lisp_Object spacing;
1591 1591
@@ -6152,7 +6152,7 @@ face_at_string_position (struct window *w, Lisp_Object string,
6152 struct frame *f = XFRAME (WINDOW_FRAME (w)); 6152 struct frame *f = XFRAME (WINDOW_FRAME (w));
6153 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 6153 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6154 struct face *base_face; 6154 struct face *base_face;
6155 int multibyte_p = STRING_MULTIBYTE (string); 6155 bool multibyte_p = STRING_MULTIBYTE (string);
6156 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface; 6156 Lisp_Object prop_name = mouse_p ? Qmouse_face : Qface;
6157 6157
6158 /* Get the value of the face property at the current position within 6158 /* 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,
3539 CHECK_STRING (color); 3539 CHECK_STRING (color);
3540 3540
3541 if (x_defined_color (f, SSDATA (color), &foo, 0)) 3541 if (x_defined_color (f, SSDATA (color), &foo, 0))
3542 return list3 (make_number (foo.red), 3542 return list3i (foo.red, foo.green, foo.blue);
3543 make_number (foo.green),
3544 make_number (foo.blue));
3545 else 3543 else
3546 return Qnil; 3544 return Qnil;
3547} 3545}
@@ -3703,9 +3701,8 @@ If omitted or nil, that stands for the selected frame's display. */)
3703 struct x_display_info *dpyinfo = check_x_display_info (terminal); 3701 struct x_display_info *dpyinfo = check_x_display_info (terminal);
3704 Display *dpy = dpyinfo->display; 3702 Display *dpy = dpyinfo->display;
3705 3703
3706 return Fcons (make_number (ProtocolVersion (dpy)), 3704 return list3i (ProtocolVersion (dpy), ProtocolRevision (dpy),
3707 Fcons (make_number (ProtocolRevision (dpy)), 3705 VendorRelease (dpy));
3708 Fcons (make_number (VendorRelease (dpy)), Qnil)));
3709} 3706}
3710 3707
3711DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, 3708DEFUN ("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. */)
5416 XmStringFree (default_xmstring); 5413 XmStringFree (default_xmstring);
5417 } 5414 }
5418 5415
5419 record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0)); 5416 record_unwind_protect (clean_up_file_dialog, make_save_pointer (dialog));
5420 5417
5421 /* Process events until the user presses Cancel or OK. */ 5418 /* Process events until the user presses Cancel or OK. */
5422 x_menu_set_in_use (1); 5419 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
15GNU General Public License for more details. 15GNU General Public License for more details.
16 16
17You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http§://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20#include <config.h> 20#include <config.h>
21 21
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,
1477 gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 1477 gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i,
1478 timestamp ? timestamp : gtk_get_current_event_time ()); 1478 timestamp ? timestamp : gtk_get_current_event_time ());
1479 1479
1480 record_unwind_protect (pop_down_menu, make_save_value (menu, 0)); 1480 record_unwind_protect (pop_down_menu, make_save_pointer (menu));
1481 1481
1482 if (gtk_widget_get_mapped (menu)) 1482 if (gtk_widget_get_mapped (menu))
1483 { 1483 {
@@ -1826,7 +1826,7 @@ xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
1826 /* Make sure to free the widget_value objects we used to specify the 1826 /* Make sure to free the widget_value objects we used to specify the
1827 contents even with longjmp. */ 1827 contents even with longjmp. */
1828 record_unwind_protect (cleanup_widget_value_tree, 1828 record_unwind_protect (cleanup_widget_value_tree,
1829 make_save_value (first_wv, 0)); 1829 make_save_pointer (first_wv));
1830 1830
1831 /* Actually create and show the menu until popped down. */ 1831 /* Actually create and show the menu until popped down. */
1832 create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp); 1832 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)
1925 if (menu) 1925 if (menu)
1926 { 1926 {
1927 ptrdiff_t specpdl_count = SPECPDL_INDEX (); 1927 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
1928 record_unwind_protect (pop_down_menu, make_save_value (menu, 0)); 1928 record_unwind_protect (pop_down_menu, make_save_pointer (menu));
1929 1929
1930 /* Display the menu. */ 1930 /* Display the menu. */
1931 gtk_widget_show_all (menu); 1931 gtk_widget_show_all (menu);
@@ -2136,7 +2136,7 @@ xdialog_show (FRAME_PTR f,
2136 /* Make sure to free the widget_value objects we used to specify the 2136 /* Make sure to free the widget_value objects we used to specify the
2137 contents even with longjmp. */ 2137 contents even with longjmp. */
2138 record_unwind_protect (cleanup_widget_value_tree, 2138 record_unwind_protect (cleanup_widget_value_tree,
2139 make_save_value (first_wv, 0)); 2139 make_save_pointer (first_wv));
2140 2140
2141 /* Actually create and show the dialog. */ 2141 /* Actually create and show the dialog. */
2142 create_and_show_dialog (f, first_wv); 2142 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,
2479#endif 2479#endif
2480 2480
2481 record_unwind_protect (pop_down_menu, 2481 record_unwind_protect (pop_down_menu,
2482 format_save_value ("pp", f, menu)); 2482 make_save_value ("pp", f, menu));
2483 2483
2484 /* Help display under X won't work because XMenuActivate contains 2484 /* Help display under X won't work because XMenuActivate contains
2485 a loop that doesn't give Emacs a chance to process it. */ 2485 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)
93 93
94 if (!(library = w32_delayed_load (Qlibxml2_dll))) 94 if (!(library = w32_delayed_load (Qlibxml2_dll)))
95 { 95 {
96 message ("%s", "libxml2 library not found"); 96 message1 ("libxml2 library not found");
97 return 0; 97 return 0;
98 } 98 }
99 99
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)
1141 1141
1142 /* Make sure to do unexpect_property_change if we quit or err. */ 1142 /* Make sure to do unexpect_property_change if we quit or err. */
1143 record_unwind_protect (wait_for_property_change_unwind, 1143 record_unwind_protect (wait_for_property_change_unwind,
1144 make_save_value (location, 0)); 1144 make_save_pointer (location));
1145 1145
1146 XSETCAR (property_change_reply, Qnil); 1146 XSETCAR (property_change_reply, Qnil);
1147 property_change_reply_object = location; 1147 property_change_reply_object = location;
@@ -1670,11 +1670,10 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1670 return x_atom_to_symbol (display, (Atom) idata[0]); 1670 return x_atom_to_symbol (display, (Atom) idata[0]);
1671 else 1671 else
1672 { 1672 {
1673 Lisp_Object v = Fmake_vector (make_number (size / sizeof (int)), 1673 Lisp_Object v = make_uninit_vector (size / sizeof (int));
1674 make_number (0)); 1674
1675 for (i = 0; i < size / sizeof (int); i++) 1675 for (i = 0; i < size / sizeof (int); i++)
1676 Faset (v, make_number (i), 1676 ASET (v, i, x_atom_to_symbol (display, (Atom) idata[i]));
1677 x_atom_to_symbol (display, (Atom) idata[i]));
1678 return v; 1677 return v;
1679 } 1678 }
1680 } 1679 }
@@ -1694,24 +1693,24 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1694 else if (format == 16) 1693 else if (format == 16)
1695 { 1694 {
1696 ptrdiff_t i; 1695 ptrdiff_t i;
1697 Lisp_Object v; 1696 Lisp_Object v = make_uninit_vector (size / 2);
1698 v = Fmake_vector (make_number (size / 2), make_number (0)); 1697
1699 for (i = 0; i < size / 2; i++) 1698 for (i = 0; i < size / 2; i++)
1700 { 1699 {
1701 short j = ((short *) data) [i]; 1700 short j = ((short *) data) [i];
1702 Faset (v, make_number (i), make_number (j)); 1701 ASET (v, i, make_number (j));
1703 } 1702 }
1704 return v; 1703 return v;
1705 } 1704 }
1706 else 1705 else
1707 { 1706 {
1708 ptrdiff_t i; 1707 ptrdiff_t i;
1709 Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE), 1708 Lisp_Object v = make_uninit_vector (size / X_LONG_SIZE);
1710 make_number (0)); 1709
1711 for (i = 0; i < size / X_LONG_SIZE; i++) 1710 for (i = 0; i < size / X_LONG_SIZE; i++)
1712 { 1711 {
1713 int j = ((int *) data) [i]; 1712 int j = ((int *) data) [i];
1714 Faset (v, make_number (i), INTEGER_TO_CONS (j)); 1713 ASET (v, i, INTEGER_TO_CONS (j));
1715 } 1714 }
1716 return v; 1715 return v;
1717 } 1716 }
@@ -1904,7 +1903,7 @@ clean_local_selection_data (Lisp_Object obj)
1904 Lisp_Object copy; 1903 Lisp_Object copy;
1905 if (size == 1) 1904 if (size == 1)
1906 return clean_local_selection_data (AREF (obj, 0)); 1905 return clean_local_selection_data (AREF (obj, 0));
1907 copy = Fmake_vector (make_number (size), Qnil); 1906 copy = make_uninit_vector (size);
1908 for (i = 0; i < size; i++) 1907 for (i = 0; i < size; i++)
1909 ASET (copy, i, clean_local_selection_data (AREF (obj, i))); 1908 ASET (copy, i, clean_local_selection_data (AREF (obj, i)));
1910 return copy; 1909 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,
6102 last_user_time = event.xproperty.time; 6102 last_user_time = event.xproperty.time;
6103 f = x_top_window_to_frame (dpyinfo, event.xproperty.window); 6103 f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
6104 if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state) 6104 if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
6105 if (x_handle_net_wm_state (f, &event.xproperty) && f->iconified 6105 if (x_handle_net_wm_state (f, &event.xproperty)
6106 && f->output_data.x->net_wm_state_hidden_seen) 6106 && FRAME_ICONIFIED_P (f)
6107 && f->output_data.x->net_wm_state_hidden_seen)
6107 { 6108 {
6108 /* Gnome shell does not iconify us when C-z is pressed. It hides 6109 /* Gnome shell does not iconify us when C-z is pressed.
6109 the frame. So if our state says we aren't hidden anymore, 6110 It hides the frame. So if our state says we aren't
6110 treat it as deiconified. */ 6111 hidden anymore, treat it as deiconified. */
6111 if (! f->async_iconified) 6112 SET_FRAME_VISIBLE (f, 1);
6112 SET_FRAME_GARBAGED (f); 6113 SET_FRAME_ICONIFIED (f, 0);
6113 f->async_visible = 1;
6114 f->async_iconified = 0;
6115 f->output_data.x->has_been_visible = 1; 6114 f->output_data.x->has_been_visible = 1;
6116 f->output_data.x->net_wm_state_hidden_seen = 0; 6115 f->output_data.x->net_wm_state_hidden_seen = 0;
6117 inev.ie.kind = DEICONIFY_EVENT; 6116 inev.ie.kind = DEICONIFY_EVENT;
@@ -6152,10 +6151,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
6152 event.xexpose.width, event.xexpose.height, 6151 event.xexpose.width, event.xexpose.height,
6153 FALSE); 6152 FALSE);
6154#endif 6153#endif
6155 if (f->async_visible == 0) 6154 if (!FRAME_VISIBLE_P (f))
6156 { 6155 {
6157 f->async_visible = 1; 6156 SET_FRAME_VISIBLE (f, 1);
6158 f->async_iconified = 0; 6157 SET_FRAME_ICONIFIED (f, 0);
6159 f->output_data.x->has_been_visible = 1; 6158 f->output_data.x->has_been_visible = 1;
6160 SET_FRAME_GARBAGED (f); 6159 SET_FRAME_GARBAGED (f);
6161 } 6160 }
@@ -6232,20 +6231,20 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
6232 if (f) /* F may no longer exist if 6231 if (f) /* F may no longer exist if
6233 the frame was deleted. */ 6232 the frame was deleted. */
6234 { 6233 {
6234 bool visible = FRAME_VISIBLE_P (f);
6235 /* While a frame is unmapped, display generation is 6235 /* While a frame is unmapped, display generation is
6236 disabled; you don't want to spend time updating a 6236 disabled; you don't want to spend time updating a
6237 display that won't ever be seen. */ 6237 display that won't ever be seen. */
6238 f->async_visible = 0; 6238 SET_FRAME_VISIBLE (f, 0);
6239 /* We can't distinguish, from the event, whether the window 6239 /* We can't distinguish, from the event, whether the window
6240 has become iconified or invisible. So assume, if it 6240 has become iconified or invisible. So assume, if it
6241 was previously visible, than now it is iconified. 6241 was previously visible, than now it is iconified.
6242 But x_make_frame_invisible clears both 6242 But x_make_frame_invisible clears both
6243 the visible flag and the iconified flag; 6243 the visible flag and the iconified flag;
6244 and that way, we know the window is not iconified now. */ 6244 and that way, we know the window is not iconified now. */
6245 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)) 6245 if (visible || FRAME_ICONIFIED_P (f))
6246 { 6246 {
6247 f->async_iconified = 1; 6247 SET_FRAME_ICONIFIED (f, 1);
6248
6249 inev.ie.kind = ICONIFY_EVENT; 6248 inev.ie.kind = ICONIFY_EVENT;
6250 XSETFRAME (inev.ie.frame_or_window, f); 6249 XSETFRAME (inev.ie.frame_or_window, f);
6251 } 6250 }
@@ -6264,13 +6263,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
6264 f = x_top_window_to_frame (dpyinfo, event.xmap.window); 6263 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
6265 if (f) 6264 if (f)
6266 { 6265 {
6266 bool iconified = FRAME_ICONIFIED_P (f);
6267 /* wait_reading_process_output will notice this and update 6267 /* wait_reading_process_output will notice this and update
6268 the frame's display structures. 6268 the frame's display structures.
6269 If we where iconified, we should not set garbaged, 6269 If we where iconified, we should not set garbaged,
6270 because that stops redrawing on Expose events. This looks 6270 because that stops redrawing on Expose events. This looks
6271 bad if we are called from a recursive event loop 6271 bad if we are called from a recursive event loop
6272 (x_dispatch_event), for example when a dialog is up. */ 6272 (x_dispatch_event), for example when a dialog is up. */
6273 if (! f->async_iconified) 6273 if (!iconified)
6274 SET_FRAME_GARBAGED (f); 6274 SET_FRAME_GARBAGED (f);
6275 6275
6276 /* Check if fullscreen was specified before we where mapped the 6276 /* Check if fullscreen was specified before we where mapped the
@@ -6278,20 +6278,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
6278 if (!f->output_data.x->has_been_visible) 6278 if (!f->output_data.x->has_been_visible)
6279 x_check_fullscreen (f); 6279 x_check_fullscreen (f);
6280 6280
6281 f->async_visible = 1; 6281 SET_FRAME_VISIBLE (f, 1);
6282 f->async_iconified = 0; 6282 SET_FRAME_ICONIFIED (f, 0);
6283 f->output_data.x->has_been_visible = 1; 6283 f->output_data.x->has_been_visible = 1;
6284 6284
6285 if (f->iconified) 6285 if (iconified)
6286 { 6286 {
6287 inev.ie.kind = DEICONIFY_EVENT; 6287 inev.ie.kind = DEICONIFY_EVENT;
6288 XSETFRAME (inev.ie.frame_or_window, f); 6288 XSETFRAME (inev.ie.frame_or_window, f);
6289 } 6289 }
6290 else if (! NILP (Vframe_list) 6290 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
6291 && ! NILP (XCDR (Vframe_list))) 6291 /* Force a redisplay sooner or later to update the
6292 /* Force a redisplay sooner or later 6292 frame titles in case this is the second frame. */
6293 to update the frame titles
6294 in case this is the second frame. */
6295 record_asynch_buffer_change (); 6293 record_asynch_buffer_change ();
6296 6294
6297#ifdef USE_GTK 6295#ifdef USE_GTK
@@ -8417,7 +8415,7 @@ get_current_wm_state (struct frame *f,
8417 if (tmp_data) XFree (tmp_data); 8415 if (tmp_data) XFree (tmp_data);
8418 x_uncatch_errors (); 8416 x_uncatch_errors ();
8419 unblock_input (); 8417 unblock_input ();
8420 return ! f->iconified; 8418 return !FRAME_ICONIFIED_P (f);
8421 } 8419 }
8422 8420
8423 x_uncatch_errors (); 8421 x_uncatch_errors ();
@@ -8529,7 +8527,7 @@ do_ewmh_fullscreen (struct frame *f)
8529static void 8527static void
8530XTfullscreen_hook (FRAME_PTR f) 8528XTfullscreen_hook (FRAME_PTR f)
8531{ 8529{
8532 if (f->async_visible) 8530 if (FRAME_VISIBLE_P (f))
8533 { 8531 {
8534 block_input (); 8532 block_input ();
8535 x_check_fullscreen (f); 8533 x_check_fullscreen (f);
@@ -8793,7 +8791,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
8793 /* But the ConfigureNotify may in fact never arrive, and then this is 8791 /* But the ConfigureNotify may in fact never arrive, and then this is
8794 not right if the frame is visible. Instead wait (with timeout) 8792 not right if the frame is visible. Instead wait (with timeout)
8795 for the ConfigureNotify. */ 8793 for the ConfigureNotify. */
8796 if (f->async_visible) 8794 if (FRAME_VISIBLE_P (f))
8797 x_wait_for_event (f, ConfigureNotify); 8795 x_wait_for_event (f, ConfigureNotify);
8798 else 8796 else
8799 { 8797 {
@@ -8905,9 +8903,8 @@ void
8905x_raise_frame (struct frame *f) 8903x_raise_frame (struct frame *f)
8906{ 8904{
8907 block_input (); 8905 block_input ();
8908 if (f->async_visible) 8906 if (FRAME_VISIBLE_P (f))
8909 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); 8907 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8910
8911 XFlush (FRAME_X_DISPLAY (f)); 8908 XFlush (FRAME_X_DISPLAY (f));
8912 unblock_input (); 8909 unblock_input ();
8913} 8910}
@@ -8917,7 +8914,7 @@ x_raise_frame (struct frame *f)
8917static void 8914static void
8918x_lower_frame (struct frame *f) 8915x_lower_frame (struct frame *f)
8919{ 8916{
8920 if (f->async_visible) 8917 if (FRAME_VISIBLE_P (f))
8921 { 8918 {
8922 block_input (); 8919 block_input ();
8923 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); 8920 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
@@ -8933,7 +8930,7 @@ xembed_request_focus (FRAME_PTR f)
8933{ 8930{
8934 /* See XEmbed Protocol Specification at 8931 /* See XEmbed Protocol Specification at
8935 http://freedesktop.org/wiki/Specifications/xembed-spec */ 8932 http://freedesktop.org/wiki/Specifications/xembed-spec */
8936 if (f->async_visible) 8933 if (FRAME_VISIBLE_P (f))
8937 xembed_send_message (f, CurrentTime, 8934 xembed_send_message (f, CurrentTime,
8938 XEMBED_REQUEST_FOCUS, 0, 0, 0); 8935 XEMBED_REQUEST_FOCUS, 0, 0, 0);
8939} 8936}
@@ -8947,16 +8944,14 @@ x_ewmh_activate_frame (FRAME_PTR f)
8947 http://freedesktop.org/wiki/Specifications/wm-spec */ 8944 http://freedesktop.org/wiki/Specifications/wm-spec */
8948 8945
8949 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 8946 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8950 if (f->async_visible && wm_supports (f, dpyinfo->Xatom_net_active_window)) 8947
8948 if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window))
8951 { 8949 {
8952 Lisp_Object frame; 8950 Lisp_Object frame;
8953 XSETFRAME (frame, f); 8951 XSETFRAME (frame, f);
8954 x_send_client_event (frame, make_number (0), frame, 8952 x_send_client_event (frame, make_number (0), frame,
8955 dpyinfo->Xatom_net_active_window, 8953 dpyinfo->Xatom_net_active_window,
8956 make_number (32), 8954 make_number (32), list2i (1, last_user_time));
8957 Fcons (make_number (1),
8958 Fcons (make_number (last_user_time),
8959 Qnil)));
8960 } 8955 }
8961} 8956}
8962 8957
@@ -9159,9 +9154,6 @@ x_make_frame_visible (struct frame *f)
9159 poll_for_input_1 (); 9154 poll_for_input_1 ();
9160 poll_suppress_count = old_poll_suppress_count; 9155 poll_suppress_count = old_poll_suppress_count;
9161 } 9156 }
9162
9163 /* See if a MapNotify event has been processed. */
9164 FRAME_SAMPLE_VISIBILITY (f);
9165 } 9157 }
9166 9158
9167 /* 2000-09-28: In 9159 /* 2000-09-28: In
@@ -9229,10 +9221,8 @@ x_make_frame_invisible (struct frame *f)
9229 So we can't win using the usual strategy of letting 9221 So we can't win using the usual strategy of letting
9230 FRAME_SAMPLE_VISIBILITY set this. So do it by hand, 9222 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9231 and synchronize with the server to make sure we agree. */ 9223 and synchronize with the server to make sure we agree. */
9232 f->visible = 0; 9224 SET_FRAME_VISIBLE (f, 0);
9233 FRAME_ICONIFIED_P (f) = 0; 9225 SET_FRAME_ICONIFIED (f, 0);
9234 f->async_visible = 0;
9235 f->async_iconified = 0;
9236 9226
9237 x_sync (f); 9227 x_sync (f);
9238 9228
@@ -9253,13 +9243,11 @@ x_iconify_frame (struct frame *f)
9253 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f) 9243 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9254 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0; 9244 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9255 9245
9256 if (f->async_iconified) 9246 if (FRAME_ICONIFIED_P (f))
9257 return; 9247 return;
9258 9248
9259 block_input (); 9249 block_input ();
9260 9250
9261 FRAME_SAMPLE_VISIBILITY (f);
9262
9263 type = x_icon_type (f); 9251 type = x_icon_type (f);
9264 if (!NILP (type)) 9252 if (!NILP (type))
9265 x_bitmap_icon (f, type); 9253 x_bitmap_icon (f, type);
@@ -9271,10 +9259,8 @@ x_iconify_frame (struct frame *f)
9271 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); 9259 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9272 9260
9273 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); 9261 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9274 f->iconified = 1; 9262 SET_FRAME_VISIBLE (f, 0);
9275 f->visible = 1; 9263 SET_FRAME_ICONIFIED (f, 1);
9276 f->async_iconified = 1;
9277 f->async_visible = 0;
9278 unblock_input (); 9264 unblock_input ();
9279 return; 9265 return;
9280 } 9266 }
@@ -9291,10 +9277,8 @@ x_iconify_frame (struct frame *f)
9291 /* The server won't give us any event to indicate 9277 /* The server won't give us any event to indicate
9292 that an invisible frame was changed to an icon, 9278 that an invisible frame was changed to an icon,
9293 so we have to record it here. */ 9279 so we have to record it here. */
9294 f->iconified = 1; 9280 SET_FRAME_VISIBLE (f, 0);
9295 f->visible = 1; 9281 SET_FRAME_ICONIFIED (f, 1);
9296 f->async_iconified = 1;
9297 f->async_visible = 0;
9298 unblock_input (); 9282 unblock_input ();
9299 return; 9283 return;
9300 } 9284 }
@@ -9307,9 +9291,8 @@ x_iconify_frame (struct frame *f)
9307 if (!result) 9291 if (!result)
9308 error ("Can't notify window manager of iconification"); 9292 error ("Can't notify window manager of iconification");
9309 9293
9310 f->async_iconified = 1; 9294 SET_FRAME_ICONIFIED (f, 1);
9311 f->async_visible = 0; 9295 SET_FRAME_VISIBLE (f, 0);
9312
9313 9296
9314 block_input (); 9297 block_input ();
9315 XFlush (FRAME_X_DISPLAY (f)); 9298 XFlush (FRAME_X_DISPLAY (f));
@@ -9358,8 +9341,8 @@ x_iconify_frame (struct frame *f)
9358 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 9341 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9359 } 9342 }
9360 9343
9361 f->async_iconified = 1; 9344 SET_FRAME_ICONIFIED (f, 1);
9362 f->async_visible = 0; 9345 SET_FRAME_VISIBLE (f, 0);
9363 9346
9364 XFlush (FRAME_X_DISPLAY (f)); 9347 XFlush (FRAME_X_DISPLAY (f));
9365 unblock_input (); 9348 unblock_input ();
@@ -10787,16 +10770,6 @@ With MS Windows or Nextstep, the value is t. */);
10787 Vx_toolkit_scroll_bars = Qnil; 10770 Vx_toolkit_scroll_bars = Qnil;
10788#endif 10771#endif
10789 10772
10790 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
10791 scroll_bar_adjust_thumb_portion_p,
10792 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
10793Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
10794even if the end of the buffer is shown (i.e. overscrolling).
10795Set to nil if you want the thumb to be at the bottom when the end of the buffer
10796is shown. Also, the thumb fills the whole scroll bar when the entire buffer
10797is visible. In this case you can not overscroll. */);
10798 scroll_bar_adjust_thumb_portion_p = 1;
10799
10800 staticpro (&last_mouse_motion_frame); 10773 staticpro (&last_mouse_motion_frame);
10801 last_mouse_motion_frame = Qnil; 10774 last_mouse_motion_frame = Qnil;
10802 10775