aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog121
-rw-r--r--src/alloc.c12
-rw-r--r--src/callproc.c104
-rw-r--r--src/character.c14
-rw-r--r--src/dispextern.h63
-rw-r--r--src/dispnew.c58
-rw-r--r--src/fileio.c118
-rw-r--r--src/frame.h10
-rw-r--r--src/gtkutil.c11
-rw-r--r--src/lisp.h1
-rw-r--r--src/nsterm.m8
-rw-r--r--src/process.c72
-rw-r--r--src/process.h1
-rw-r--r--src/sysdep.c113
-rw-r--r--src/w32.c29
-rw-r--r--src/w32term.c9
-rw-r--r--src/window.c2
-rw-r--r--src/xdisp.c38
-rw-r--r--src/xterm.c9
19 files changed, 466 insertions, 327 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e21d82bdc09..70d722a02a4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,124 @@
12013-08-24 Eli Zaretskii <eliz@gnu.org>
2
3 * xdisp.c (get_next_display_element): Don't apply to characters
4 from a display vector the logic of setting it->end_of_box_run_p
5 suitable for characters from a buffer. (Bug#15175)
6
7 * w32.c (fdutimens): Call 'utime', which is implemented on w32.c
8 to handle directories, rather than '_utime' which doesn't.
9 (Bug#15176)
10
112013-08-24 Jan Djärv <jan.h.d@swipnet.se>
12
13 * gtkutil.c (x_wm_set_size_hint): Don't set hints when maximized
14 or fullscreen (Bug#14627).
15
162013-08-24 Paul Eggert <eggert@cs.ucla.edu>
17
18 System-dependent integer overflow fixes.
19 * process.c (Fset_process_window_size): Signal an error if
20 the window size is outside the range supported by the lower level.
21 * sysdep.c (set_window_size): Return negative on error,
22 nonnegative on success, rather than -1, 0, 1 on not in system,
23 failure, success. This is simpler. Caller changed.
24 (serial_configure): Remove unnecessary initialization of local.
25 (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory
26 size fits in unsigned long; this isn't true on some 32-bit hosts.
27 Avoid buffer overrun if some future version of /proc/meminfo has a
28 variable name longer than 20 bytes.
29 (system_process_attributes) [__FreeBSD__]:
30 Don't assume hw.availpages fits in 'int'.
31
322013-08-23 Paul Eggert <eggert@cs.ucla.edu>
33
34 Don't let very long directory names overrun the stack.
35 Fix some related minor problems involving "//", vfork.
36 * callproc.c (encode_current_directory): New function.
37 (call_process): Don't append "/"; not needed.
38 * fileio.c (file_name_as_directory_slop): New constant.
39 (file_name_as_directory): Allow SRC to be longer than SRCLEN;
40 this can save the caller having to alloca.
41 (Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name):
42 Use SAFE_ALLOCA, not alloca.
43 (directory_file_name, Fexpand_file_name): Leave leading "//"
44 alone, since it can be special even on POSIX platforms.
45 * callproc.c (call_process):
46 * process.c (Fformat_network_address):
47 * sysdep.c (sys_subshell):
48 Use encode_current_directory rather than rolling our own.
49 (create_process): No need to encode directory; caller does that now.
50 * process.h (encode_current_directory): New decl.
51 * sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers.
52 Rework to avoid 'goto xyzzy;'.
53
542013-08-23 Eli Zaretskii <eliz@gnu.org>
55
56 * xdisp.c (handle_face_prop): If the default face was remapped use
57 the remapped face for strings from prefix properties. (Bug#15155)
58
592013-08-23 Dmitry Antipov <dmantipov@yandex.ru>
60
61 Minor cleanup for redisplay interface and few related functions.
62 * frame.h (enum text_cursor_kinds): Move from here...
63 * dispextern.h (enum text_cursor_kinds): ...to here.
64 (toplevel): Drop unnecessary declarations.
65 (struct redisplay_interface): Use bool and enum text_cursor_kinds
66 in update_window_end_hook and draw_window_cursor functions.
67 (display_and_set_cursor, x_update_cursor): Adjust prototypes.
68 * nsterm.m (ns_update_window_end, ns_draw_window_cursor):
69 * w32term.c (x_update_window_end,w32_draw_window_cursor):
70 * xterm.c (x_update_window_end, x_draw_window_cursor):
71 * xdisp.c (display_and_set_cursor, update_window_cursor)
72 (update_cursor_in_window_tree, x_update_cursor): Use bool and
73 enum text_cursor_kinds where appropriate.
74
752013-08-23 Dmitry Antipov <dmantipov@yandex.ru>
76
77 Redesign redisplay interface to drop updated_row and updated_area.
78 * dispextern.h (updated_row, updated_area): Remove declaration.
79 (struct redisplay_interface): Pass glyph row and row area parameters
80 to write_glyphs, insert_glyphs and clear_end_of_line functions.
81 (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line):
82 Adjust prototypes.
83 * dispnew.c (updated_row, updated_area): Remove.
84 (redraw_overlapped_rows, update_window_line): Adjust user.
85 (update_marginal_area, update_text_area): Likewise. Pass updated row
86 as a parameter. Prefer enum glyph_row_area to int where appropriate.
87 * xdisp.c (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line):
88 Adjust users.
89
902013-08-22 Paul Eggert <eggert@cs.ucla.edu>
91
92 * process.c (flush_pending_output): Remove stub.
93 All uses removed.
94
952013-08-21 Paul Eggert <eggert@cs.ucla.edu>
96
97 * callproc.c: Fix race that killed background processes (Bug#15144).
98 (call_process): New arg TEMPFILE_INDEX. Callers changed.
99 Record deleted process-id in critical section, not afterwards.
100 Don't mistakenly kill process created by a call-process invocation
101 that discards output and does not wait.
102
1032013-08-21 Dmitry Antipov <dmantipov@yandex.ru>
104
105 Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE
106 and GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES.
107 * alloc.c (toplevel): Remove unnecessary nested #if...#endif.
108 (mark_maybe_object) [!GC_MARK_STACK]: Define to emacs_abort
109 to shut up compiler in mark_object.
110 (dump_zombies): Convert to global and add EXTERNALLY_VISIBLE.
111
1122013-08-21 Paul Eggert <eggert@cs.ucla.edu>
113
114 * process.c (allocate_pty) [PTY_OPEN]: Set fd's FD_CLOEXEC flag.
115 We can't portably rely on PTY_OPEN doing that, even if
116 it calls posix_openpt with O_CLOEXEC.
117
1182013-08-20 Kenichi Handa <handa@gnu.org>
119
120 * character.c (string_char): Improve commentary.
121
12013-08-20 Paul Eggert <eggert@cs.ucla.edu> 1222013-08-20 Paul Eggert <eggert@cs.ucla.edu>
2 123
3 * image.c (SIGNATURE_DIGESTSIZE): Remove. 124 * image.c (SIGNATURE_DIGESTSIZE): Remove.
diff --git a/src/alloc.c b/src/alloc.c
index 4cc9b3e1a13..9b5f2955aa5 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -314,7 +314,6 @@ static void *min_heap_address, *max_heap_address;
314static struct mem_node mem_z; 314static struct mem_node mem_z;
315#define MEM_NIL &mem_z 315#define MEM_NIL &mem_z
316 316
317#if GC_MARK_STACK || defined GC_MALLOC_CHECK
318static struct mem_node *mem_insert (void *, void *, enum mem_type); 317static struct mem_node *mem_insert (void *, void *, enum mem_type);
319static void mem_insert_fixup (struct mem_node *); 318static void mem_insert_fixup (struct mem_node *);
320static void mem_rotate_left (struct mem_node *); 319static void mem_rotate_left (struct mem_node *);
@@ -322,7 +321,6 @@ static void mem_rotate_right (struct mem_node *);
322static void mem_delete (struct mem_node *); 321static void mem_delete (struct mem_node *);
323static void mem_delete_fixup (struct mem_node *); 322static void mem_delete_fixup (struct mem_node *);
324static struct mem_node *mem_find (void *); 323static struct mem_node *mem_find (void *);
325#endif
326 324
327#endif /* GC_MARK_STACK || GC_MALLOC_CHECK */ 325#endif /* GC_MARK_STACK || GC_MALLOC_CHECK */
328 326
@@ -4237,6 +4235,10 @@ live_buffer_p (struct mem_node *m, void *p)
4237 4235
4238#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 4236#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
4239 4237
4238/* Currently not used, but may be called from gdb. */
4239
4240void dump_zombies (void) EXTERNALLY_VISIBLE;
4241
4240/* Array of objects that are kept alive because the C stack contains 4242/* Array of objects that are kept alive because the C stack contains
4241 a pattern that looks like a reference to them . */ 4243 a pattern that looks like a reference to them . */
4242 4244
@@ -4619,7 +4621,7 @@ check_gcpros (void)
4619 4621
4620#elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 4622#elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
4621 4623
4622static void 4624void
4623dump_zombies (void) 4625dump_zombies (void)
4624{ 4626{
4625 int i; 4627 int i;
@@ -4766,6 +4768,10 @@ flush_stack_call_func (void (*func) (void *arg), void *arg)
4766 eassert (current_thread == self); 4768 eassert (current_thread == self);
4767} 4769}
4768 4770
4771#else /* GC_MARK_STACK == 0 */
4772
4773#define mark_maybe_object(obj) emacs_abort ()
4774
4769#endif /* GC_MARK_STACK != 0 */ 4775#endif /* GC_MARK_STACK != 0 */
4770 4776
4771 4777
diff --git a/src/callproc.c b/src/callproc.c
index 2a9162cb5cc..d4b4a26ec3a 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -102,7 +102,7 @@ enum
102 CALLPROC_FDS 102 CALLPROC_FDS
103 }; 103 };
104 104
105static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); 105static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
106 106
107/* Block SIGCHLD. */ 107/* Block SIGCHLD. */
108 108
@@ -123,6 +123,37 @@ unblock_child_signal (void)
123 pthread_sigmask (SIG_SETMASK, &empty_mask, 0); 123 pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
124} 124}
125 125
126/* Return the current buffer's working directory, or the home
127 directory if it's unreachable, as a string suitable for a system call.
128 Signal an error if the result would not be an accessible directory. */
129
130Lisp_Object
131encode_current_directory (void)
132{
133 Lisp_Object dir;
134 struct gcpro gcpro1;
135
136 dir = BVAR (current_buffer, directory);
137 GCPRO1 (dir);
138
139 dir = Funhandled_file_name_directory (dir);
140
141 /* If the file name handler says that dir is unreachable, use
142 a sensible default. */
143 if (NILP (dir))
144 dir = build_string ("~");
145
146 dir = expand_and_dir_to_file (dir, Qnil);
147
148 if (STRING_MULTIBYTE (dir))
149 dir = ENCODE_FILE (dir);
150 if (! file_accessible_directory_p (SSDATA (dir)))
151 report_file_error ("Setting current directory",
152 BVAR (current_buffer, directory));
153
154 RETURN_UNGCPRO (dir);
155}
156
126/* If P is reapable, record it as a deleted process and kill it. 157/* If P is reapable, record it as a deleted process and kill it.
127 Do this in a critical section. Unless PID is wedged it will be 158 Do this in a critical section. Unless PID is wedged it will be
128 reaped on receipt of the first SIGCHLD after the critical section. */ 159 reaped on receipt of the first SIGCHLD after the critical section. */
@@ -248,14 +279,20 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
248 report_file_error ("Opening process input file", infile); 279 report_file_error ("Opening process input file", infile);
249 record_unwind_protect_int (close_file_unwind, filefd); 280 record_unwind_protect_int (close_file_unwind, filefd);
250 UNGCPRO; 281 UNGCPRO;
251 return unbind_to (count, call_process (nargs, args, filefd)); 282 return unbind_to (count, call_process (nargs, args, filefd, -1));
252} 283}
253 284
254/* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. 285/* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file.
286
287 If TEMPFILE_INDEX is nonnegative, it is the specpdl index of an
288 unwinder that is intended to remove the input temporary file; in
289 this case NARGS must be at least 2 and ARGS[1] is the file's name.
290
255 At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ 291 At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */
256 292
257static Lisp_Object 293static Lisp_Object
258call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) 294call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
295 ptrdiff_t tempfile_index)
259{ 296{
260 Lisp_Object buffer, current_dir, path; 297 Lisp_Object buffer, current_dir, path;
261 bool display_p; 298 bool display_p;
@@ -402,24 +439,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd)
402 { 439 {
403 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 440 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
404 441
405 current_dir = BVAR (current_buffer, directory); 442 current_dir = encode_current_directory ();
406 443
407 GCPRO4 (buffer, current_dir, error_file, output_file); 444 GCPRO4 (buffer, current_dir, error_file, output_file);
408 445
409 current_dir = Funhandled_file_name_directory (current_dir);
410 if (NILP (current_dir))
411 /* If the file name handler says that current_dir is unreachable, use
412 a sensible default. */
413 current_dir = build_string ("~/");
414 current_dir = expand_and_dir_to_file (current_dir, Qnil);
415 current_dir = Ffile_name_as_directory (current_dir);
416
417 if (NILP (Ffile_accessible_directory_p (current_dir)))
418 report_file_error ("Setting current directory",
419 BVAR (current_buffer, directory));
420
421 if (STRING_MULTIBYTE (current_dir))
422 current_dir = ENCODE_FILE (current_dir);
423 if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) 446 if (STRINGP (error_file) && STRING_MULTIBYTE (error_file))
424 error_file = ENCODE_FILE (error_file); 447 error_file = ENCODE_FILE (error_file);
425 if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) 448 if (STRINGP (output_file) && STRING_MULTIBYTE (output_file))
@@ -661,7 +684,22 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd)
661 child_errno = errno; 684 child_errno = errno;
662 685
663 if (pid > 0) 686 if (pid > 0)
664 synch_process_pid = pid; 687 {
688 synch_process_pid = pid;
689
690 if (INTEGERP (buffer))
691 {
692 if (tempfile_index < 0)
693 record_deleted_pid (pid, Qnil);
694 else
695 {
696 eassert (1 < nargs);
697 record_deleted_pid (pid, args[1]);
698 clear_unwind_protect (tempfile_index);
699 }
700 synch_process_pid = 0;
701 }
702 }
665 703
666 unblock_child_signal (); 704 unblock_child_signal ();
667 unblock_input (); 705 unblock_input ();
@@ -1030,7 +1068,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
1030usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) 1068usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */)
1031 (ptrdiff_t nargs, Lisp_Object *args) 1069 (ptrdiff_t nargs, Lisp_Object *args)
1032{ 1070{
1033 struct gcpro gcpro1, gcpro2; 1071 struct gcpro gcpro1;
1034 Lisp_Object infile, val; 1072 Lisp_Object infile, val;
1035 ptrdiff_t count = SPECPDL_INDEX (); 1073 ptrdiff_t count = SPECPDL_INDEX ();
1036 Lisp_Object start = args[0]; 1074 Lisp_Object start = args[0];
@@ -1061,8 +1099,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1061 record_unwind_protect_int (close_file_unwind, fd); 1099 record_unwind_protect_int (close_file_unwind, fd);
1062 } 1100 }
1063 1101
1064 val = infile; 1102 GCPRO1 (infile);
1065 GCPRO2 (infile, val);
1066 1103
1067 if (nargs > 3 && !NILP (args[3])) 1104 if (nargs > 3 && !NILP (args[3]))
1068 Fdelete_region (start, end); 1105 Fdelete_region (start, end);
@@ -1079,16 +1116,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1079 } 1116 }
1080 args[1] = infile; 1117 args[1] = infile;
1081 1118
1082 val = call_process (nargs, args, fd); 1119 val = call_process (nargs, args, fd, empty_input ? -1 : count);
1083
1084 if (!empty_input && 4 < nargs
1085 && (INTEGERP (CONSP (args[4]) ? XCAR (args[4]) : args[4])))
1086 {
1087 record_deleted_pid (synch_process_pid, infile);
1088 synch_process_pid = 0;
1089 clear_unwind_protect (count);
1090 }
1091
1092 RETURN_UNGCPRO (unbind_to (count, val)); 1120 RETURN_UNGCPRO (unbind_to (count, val));
1093} 1121}
1094 1122
@@ -1165,23 +1193,21 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1165 static variables as if the superior had done alloca and will be 1193 static variables as if the superior had done alloca and will be
1166 cleaned up in the usual way. */ 1194 cleaned up in the usual way. */
1167 { 1195 {
1168 register char *temp; 1196 char *temp;
1169 size_t i; /* size_t, because ptrdiff_t might overflow here! */ 1197 ptrdiff_t i;
1170 1198
1171 i = SBYTES (current_dir); 1199 i = SBYTES (current_dir);
1172#ifdef MSDOS 1200#ifdef MSDOS
1173 /* MSDOS must have all environment variables malloc'ed, because 1201 /* MSDOS must have all environment variables malloc'ed, because
1174 low-level libc functions that launch subsidiary processes rely 1202 low-level libc functions that launch subsidiary processes rely
1175 on that. */ 1203 on that. */
1176 pwd_var = xmalloc (i + 6); 1204 pwd_var = xmalloc (i + 5);
1177#else 1205#else
1178 pwd_var = alloca (i + 6); 1206 pwd_var = alloca (i + 5);
1179#endif 1207#endif
1180 temp = pwd_var + 4; 1208 temp = pwd_var + 4;
1181 memcpy (pwd_var, "PWD=", 4); 1209 memcpy (pwd_var, "PWD=", 4);
1182 memcpy (temp, SDATA (current_dir), i); 1210 strcpy (temp, SSDATA (current_dir));
1183 if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP;
1184 temp[i] = 0;
1185 1211
1186#ifndef DOS_NT 1212#ifndef DOS_NT
1187 /* We can't signal an Elisp error here; we're in a vfork. Since 1213 /* We can't signal an Elisp error here; we're in a vfork. Since
diff --git a/src/character.c b/src/character.c
index b2caaa290af..1bde2364e37 100644
--- a/src/character.c
+++ b/src/character.c
@@ -174,11 +174,14 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len)
174 174
175 if (*p < 0x80 || ! (*p & 0x20) || ! (*p & 0x10)) 175 if (*p < 0x80 || ! (*p & 0x20) || ! (*p & 0x10))
176 { 176 {
177 /* 1-, 2-, and 3-byte sequences can be handled by the macro. */
177 c = STRING_CHAR_ADVANCE (p); 178 c = STRING_CHAR_ADVANCE (p);
178 } 179 }
179 else if (! (*p & 0x08)) 180 else if (! (*p & 0x08))
180 { 181 {
181 c = ((((p)[0] & 0xF) << 18) 182 /* A 4-byte sequence of this form:
183 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
184 c = ((((p)[0] & 0x7) << 18)
182 | (((p)[1] & 0x3F) << 12) 185 | (((p)[1] & 0x3F) << 12)
183 | (((p)[2] & 0x3F) << 6) 186 | (((p)[2] & 0x3F) << 6)
184 | ((p)[3] & 0x3F)); 187 | ((p)[3] & 0x3F));
@@ -186,7 +189,14 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len)
186 } 189 }
187 else 190 else
188 { 191 {
189 c = ((((p)[1] & 0x3F) << 18) 192 /* A 5-byte sequence of this form:
193
194 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
195
196 Note that the top 4 `x's are always 0, so shifting p[1] can
197 never exceed the maximum valid character codepoint. */
198 c = (/* (((p)[0] & 0x3) << 24) ... always 0, so no need to shift. */
199 (((p)[1] & 0x3F) << 18)
190 | (((p)[2] & 0x3F) << 12) 200 | (((p)[2] & 0x3F) << 12)
191 | (((p)[3] & 0x3F) << 6) 201 | (((p)[3] & 0x3F) << 6)
192 | ((p)[4] & 0x3F)); 202 | ((p)[4] & 0x3F));
diff --git a/src/dispextern.h b/src/dispextern.h
index 7a4fa2ea774..6e1d85de924 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -95,18 +95,17 @@ typedef int Cursor;
95#define NativeRectangle int 95#define NativeRectangle int
96#endif 96#endif
97 97
98/* Structure forward declarations. Some are here because function 98/* Text cursor types. */
99 prototypes below reference structure types before their definition
100 in this file. Some are here because not every file including
101 dispextern.h also includes frame.h and windows.h. */
102
103struct glyph;
104struct glyph_row;
105struct glyph_matrix;
106struct glyph_pool;
107struct frame;
108struct window;
109 99
100enum text_cursor_kinds
101{
102 DEFAULT_CURSOR = -2,
103 NO_CURSOR = -1,
104 FILLED_BOX_CURSOR,
105 HOLLOW_BOX_CURSOR,
106 BAR_CURSOR,
107 HBAR_CURSOR
108};
110 109
111/* Values returned from coordinates_in_window. */ 110/* Values returned from coordinates_in_window. */
112 111
@@ -1197,11 +1196,6 @@ extern bool fonts_changed_p;
1197 1196
1198extern struct glyph space_glyph; 1197extern struct glyph space_glyph;
1199 1198
1200/* Glyph row and area updated by update_window_line. */
1201
1202extern struct glyph_row *updated_row;
1203extern int updated_area;
1204
1205/* Non-zero means last display completed. Zero means it was 1199/* Non-zero means last display completed. Zero means it was
1206 preempted. */ 1200 preempted. */
1207 1201
@@ -2713,12 +2707,17 @@ struct redisplay_interface
2713 2707
2714 /* Write or insert LEN glyphs from STRING at the nominal output 2708 /* Write or insert LEN glyphs from STRING at the nominal output
2715 position. */ 2709 position. */
2716 void (*write_glyphs) (struct window *w, struct glyph *string, int len); 2710 void (*write_glyphs) (struct window *w, struct glyph_row *row,
2717 void (*insert_glyphs) (struct window *w, struct glyph *start, int len); 2711 struct glyph *string, enum glyph_row_area area,
2712 int len);
2713 void (*insert_glyphs) (struct window *w, struct glyph_row *row,
2714 struct glyph *start, enum glyph_row_area area,
2715 int len);
2718 2716
2719 /* Clear from nominal output position to X. X < 0 means clear 2717 /* Clear from nominal output position to X. X < 0 means clear
2720 to right end of display. */ 2718 to right end of display. */
2721 void (*clear_end_of_line) (struct window *w, int x); 2719 void (*clear_end_of_line) (struct window *w, struct glyph_row *row,
2720 enum glyph_row_area area, int x);
2722 2721
2723 /* Function to call to scroll the display as described by RUN on 2722 /* Function to call to scroll the display as described by RUN on
2724 window W. */ 2723 window W. */
@@ -2739,8 +2738,8 @@ struct redisplay_interface
2739 MOUSE_FACE_OVERWRITTEN_P non-zero means that some lines in W 2738 MOUSE_FACE_OVERWRITTEN_P non-zero means that some lines in W
2740 that contained glyphs in mouse-face were overwritten, so we 2739 that contained glyphs in mouse-face were overwritten, so we
2741 have to update the mouse highlight. */ 2740 have to update the mouse highlight. */
2742 void (*update_window_end_hook) (struct window *w, int cursor_on_p, 2741 void (*update_window_end_hook) (struct window *w, bool cursor_on_p,
2743 int mouse_face_overwritten_p); 2742 bool mouse_face_overwritten_p);
2744 2743
2745 /* Move cursor to row/column position VPOS/HPOS, pixel coordinates 2744 /* Move cursor to row/column position VPOS/HPOS, pixel coordinates
2746 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y 2745 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y
@@ -2799,10 +2798,10 @@ struct redisplay_interface
2799 0, don't draw cursor. If ACTIVE_P is 1, system caret 2798 0, don't draw cursor. If ACTIVE_P is 1, system caret
2800 should track this cursor (when applicable). */ 2799 should track this cursor (when applicable). */
2801 void (*draw_window_cursor) (struct window *w, 2800 void (*draw_window_cursor) (struct window *w,
2802 struct glyph_row *glyph_row, 2801 struct glyph_row *glyph_row,
2803 int x, int y, 2802 int x, int y,
2804 int cursor_type, int cursor_width, 2803 enum text_cursor_kinds cursor_type,
2805 int on_p, int active_p); 2804 int cursor_width, bool on_p, bool active_p);
2806 2805
2807/* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */ 2806/* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */
2808 void (*draw_vertical_window_border) (struct window *w, 2807 void (*draw_vertical_window_border) (struct window *w,
@@ -3178,9 +3177,12 @@ extern void x_get_glyph_overhangs (struct glyph *, struct frame *,
3178 int *, int *); 3177 int *, int *);
3179extern void x_produce_glyphs (struct it *); 3178extern void x_produce_glyphs (struct it *);
3180 3179
3181extern void x_write_glyphs (struct window *, struct glyph *, int); 3180extern void x_write_glyphs (struct window *, struct glyph_row *,
3182extern void x_insert_glyphs (struct window *, struct glyph *, int len); 3181 struct glyph *, enum glyph_row_area, int);
3183extern void x_clear_end_of_line (struct window *, int); 3182extern void x_insert_glyphs (struct window *, struct glyph_row *,
3183 struct glyph *, enum glyph_row_area, int);
3184extern void x_clear_end_of_line (struct window *, struct glyph_row *,
3185 enum glyph_row_area, int);
3184 3186
3185extern struct cursor_pos output_cursor; 3187extern struct cursor_pos output_cursor;
3186 3188
@@ -3192,13 +3194,12 @@ extern void draw_phys_cursor_glyph (struct window *,
3192extern void get_phys_cursor_geometry (struct window *, struct glyph_row *, 3194extern void get_phys_cursor_geometry (struct window *, struct glyph_row *,
3193 struct glyph *, int *, int *, int *); 3195 struct glyph *, int *, int *, int *);
3194extern void erase_phys_cursor (struct window *); 3196extern void erase_phys_cursor (struct window *);
3195extern void display_and_set_cursor (struct window *, 3197extern void display_and_set_cursor (struct window *, bool, int, int, int, int);
3196 int, int, int, int, int);
3197 3198
3198extern void set_output_cursor (struct cursor_pos *); 3199extern void set_output_cursor (struct cursor_pos *);
3199extern void x_cursor_to (struct window *, int, int, int, int); 3200extern void x_cursor_to (struct window *, int, int, int, int);
3200 3201
3201extern void x_update_cursor (struct frame *, int); 3202extern void x_update_cursor (struct frame *, bool);
3202extern void x_clear_cursor (struct window *); 3203extern void x_clear_cursor (struct window *);
3203extern void x_draw_vertical_border (struct window *w); 3204extern void x_draw_vertical_border (struct window *w);
3204 3205
diff --git a/src/dispnew.c b/src/dispnew.c
index b7e44e425bf..3c6b89bde68 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -135,11 +135,6 @@ struct frame *last_nonminibuf_frame;
135 135
136static bool delayed_size_change; 136static bool delayed_size_change;
137 137
138/* Glyph row updated in update_window_line, and area that is updated. */
139
140struct glyph_row *updated_row;
141int updated_area;
142
143/* A glyph for a space. */ 138/* A glyph for a space. */
144 139
145struct glyph space_glyph; 140struct glyph space_glyph;
@@ -3230,14 +3225,12 @@ redraw_overlapped_rows (struct window *w, int yb)
3230 3225
3231 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) 3226 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
3232 { 3227 {
3233 updated_row = row;
3234 updated_area = area;
3235 FRAME_RIF (f)->cursor_to (w, i, 0, row->y, 3228 FRAME_RIF (f)->cursor_to (w, i, 0, row->y,
3236 area == TEXT_AREA ? row->x : 0); 3229 area == TEXT_AREA ? row->x : 0);
3237 if (row->used[area]) 3230 if (row->used[area])
3238 FRAME_RIF (f)->write_glyphs (w, row->glyphs[area], 3231 FRAME_RIF (f)->write_glyphs (w, row, row->glyphs[area],
3239 row->used[area]); 3232 area, row->used[area]);
3240 FRAME_RIF (f)->clear_end_of_line (w, -1); 3233 FRAME_RIF (f)->clear_end_of_line (w, row, area, -1);
3241 } 3234 }
3242 3235
3243 row->overlapped_p = 0; 3236 row->overlapped_p = 0;
@@ -3511,22 +3504,20 @@ update_window (struct window *w, bool force_p)
3511 AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */ 3504 AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */
3512 3505
3513static void 3506static void
3514update_marginal_area (struct window *w, int area, int vpos) 3507update_marginal_area (struct window *w, struct glyph_row *updated_row,
3508 enum glyph_row_area area, int vpos)
3515{ 3509{
3516 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); 3510 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
3517 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3511 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3518 3512
3519 /* Let functions in xterm.c know what area subsequent X positions
3520 will be relative to. */
3521 updated_area = area;
3522
3523 /* Set cursor to start of glyphs, write them, and clear to the end 3513 /* Set cursor to start of glyphs, write them, and clear to the end
3524 of the area. I don't think that something more sophisticated is 3514 of the area. I don't think that something more sophisticated is
3525 necessary here, since marginal areas will not be the default. */ 3515 necessary here, since marginal areas will not be the default. */
3526 rif->cursor_to (w, vpos, 0, desired_row->y, 0); 3516 rif->cursor_to (w, vpos, 0, desired_row->y, 0);
3527 if (desired_row->used[area]) 3517 if (desired_row->used[area])
3528 rif->write_glyphs (w, desired_row->glyphs[area], desired_row->used[area]); 3518 rif->write_glyphs (w, updated_row, desired_row->glyphs[area],
3529 rif->clear_end_of_line (w, -1); 3519 area, desired_row->used[area]);
3520 rif->clear_end_of_line (w, updated_row, area, -1);
3530} 3521}
3531 3522
3532 3523
@@ -3534,17 +3525,13 @@ update_marginal_area (struct window *w, int area, int vpos)
3534 Value is true if display has changed. */ 3525 Value is true if display has changed. */
3535 3526
3536static bool 3527static bool
3537update_text_area (struct window *w, int vpos) 3528update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
3538{ 3529{
3539 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); 3530 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
3540 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); 3531 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
3541 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3532 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3542 bool changed_p = 0; 3533 bool changed_p = 0;
3543 3534
3544 /* Let functions in xterm.c know what area subsequent X positions
3545 will be relative to. */
3546 updated_area = TEXT_AREA;
3547
3548 /* If rows are at different X or Y, or rows have different height, 3535 /* If rows are at different X or Y, or rows have different height,
3549 or the current row is marked invalid, write the entire line. */ 3536 or the current row is marked invalid, write the entire line. */
3550 if (!current_row->enabled_p 3537 if (!current_row->enabled_p
@@ -3567,11 +3554,11 @@ update_text_area (struct window *w, int vpos)
3567 rif->cursor_to (w, vpos, 0, desired_row->y, desired_row->x); 3554 rif->cursor_to (w, vpos, 0, desired_row->y, desired_row->x);
3568 3555
3569 if (desired_row->used[TEXT_AREA]) 3556 if (desired_row->used[TEXT_AREA])
3570 rif->write_glyphs (w, desired_row->glyphs[TEXT_AREA], 3557 rif->write_glyphs (w, updated_row, desired_row->glyphs[TEXT_AREA],
3571 desired_row->used[TEXT_AREA]); 3558 TEXT_AREA, desired_row->used[TEXT_AREA]);
3572 3559
3573 /* Clear to end of window. */ 3560 /* Clear to end of window. */
3574 rif->clear_end_of_line (w, -1); 3561 rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
3575 changed_p = 1; 3562 changed_p = 1;
3576 3563
3577 /* This erases the cursor. We do this here because 3564 /* This erases the cursor. We do this here because
@@ -3708,7 +3695,8 @@ update_text_area (struct window *w, int vpos)
3708 } 3695 }
3709 3696
3710 rif->cursor_to (w, vpos, start_hpos, desired_row->y, start_x); 3697 rif->cursor_to (w, vpos, start_hpos, desired_row->y, start_x);
3711 rif->write_glyphs (w, start, i - start_hpos); 3698 rif->write_glyphs (w, updated_row, start,
3699 TEXT_AREA, i - start_hpos);
3712 changed_p = 1; 3700 changed_p = 1;
3713 } 3701 }
3714 } 3702 }
@@ -3717,7 +3705,8 @@ update_text_area (struct window *w, int vpos)
3717 if (i < desired_row->used[TEXT_AREA]) 3705 if (i < desired_row->used[TEXT_AREA])
3718 { 3706 {
3719 rif->cursor_to (w, vpos, i, desired_row->y, x); 3707 rif->cursor_to (w, vpos, i, desired_row->y, x);
3720 rif->write_glyphs (w, desired_glyph, desired_row->used[TEXT_AREA] - i); 3708 rif->write_glyphs (w, updated_row, desired_glyph,
3709 TEXT_AREA, desired_row->used[TEXT_AREA] - i);
3721 changed_p = 1; 3710 changed_p = 1;
3722 } 3711 }
3723 3712
@@ -3739,7 +3728,7 @@ update_text_area (struct window *w, int vpos)
3739 if (i >= desired_row->used[TEXT_AREA]) 3728 if (i >= desired_row->used[TEXT_AREA])
3740 rif->cursor_to (w, vpos, i, desired_row->y, 3729 rif->cursor_to (w, vpos, i, desired_row->y,
3741 desired_row->pixel_width); 3730 desired_row->pixel_width);
3742 rif->clear_end_of_line (w, -1); 3731 rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
3743 changed_p = 1; 3732 changed_p = 1;
3744 } 3733 }
3745 else if (desired_row->pixel_width < current_row->pixel_width) 3734 else if (desired_row->pixel_width < current_row->pixel_width)
@@ -3767,7 +3756,7 @@ update_text_area (struct window *w, int vpos)
3767 } 3756 }
3768 else 3757 else
3769 xlim = current_row->pixel_width; 3758 xlim = current_row->pixel_width;
3770 rif->clear_end_of_line (w, xlim); 3759 rif->clear_end_of_line (w, updated_row, TEXT_AREA, xlim);
3771 changed_p = 1; 3760 changed_p = 1;
3772 } 3761 }
3773 } 3762 }
@@ -3786,10 +3775,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3786 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3775 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3787 bool changed_p = 0; 3776 bool changed_p = 0;
3788 3777
3789 /* Set the row being updated. This is important to let xterm.c
3790 know what line height values are in effect. */
3791 updated_row = desired_row;
3792
3793 /* A row can be completely invisible in case a desired matrix was 3778 /* A row can be completely invisible in case a desired matrix was
3794 built with a vscroll and then make_cursor_line_fully_visible shifts 3779 built with a vscroll and then make_cursor_line_fully_visible shifts
3795 the matrix. Make sure to make such rows current anyway, since 3780 the matrix. Make sure to make such rows current anyway, since
@@ -3803,7 +3788,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3803 if (!desired_row->full_width_p && w->left_margin_cols > 0) 3788 if (!desired_row->full_width_p && w->left_margin_cols > 0)
3804 { 3789 {
3805 changed_p = 1; 3790 changed_p = 1;
3806 update_marginal_area (w, LEFT_MARGIN_AREA, vpos); 3791 update_marginal_area (w, desired_row, LEFT_MARGIN_AREA, vpos);
3807 /* Setting this flag will ensure the vertical border, if 3792 /* Setting this flag will ensure the vertical border, if
3808 any, between this window and the one on its left will be 3793 any, between this window and the one on its left will be
3809 redrawn. This is necessary because updating the left 3794 redrawn. This is necessary because updating the left
@@ -3812,7 +3797,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3812 } 3797 }
3813 3798
3814 /* Update the display of the text area. */ 3799 /* Update the display of the text area. */
3815 if (update_text_area (w, vpos)) 3800 if (update_text_area (w, desired_row, vpos))
3816 { 3801 {
3817 changed_p = 1; 3802 changed_p = 1;
3818 if (current_row->mouse_face_p) 3803 if (current_row->mouse_face_p)
@@ -3823,7 +3808,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3823 if (!desired_row->full_width_p && w->right_margin_cols > 0) 3808 if (!desired_row->full_width_p && w->right_margin_cols > 0)
3824 { 3809 {
3825 changed_p = 1; 3810 changed_p = 1;
3826 update_marginal_area (w, RIGHT_MARGIN_AREA, vpos); 3811 update_marginal_area (w, desired_row, RIGHT_MARGIN_AREA, vpos);
3827 } 3812 }
3828 3813
3829 /* Draw truncation marks etc. */ 3814 /* Draw truncation marks etc. */
@@ -3842,7 +3827,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3842 3827
3843 /* Update current_row from desired_row. */ 3828 /* Update current_row from desired_row. */
3844 make_current (w->desired_matrix, w->current_matrix, vpos); 3829 make_current (w->desired_matrix, w->current_matrix, vpos);
3845 updated_row = NULL;
3846 return changed_p; 3830 return changed_p;
3847} 3831}
3848 3832
diff --git a/src/fileio.c b/src/fileio.c
index 08caf102266..7cad8d29da2 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -504,6 +504,10 @@ get a current directory to run processes in. */)
504 return Ffile_name_directory (filename); 504 return Ffile_name_directory (filename);
505} 505}
506 506
507/* Maximum number of bytes that DST will be longer than SRC
508 in file_name_as_directory. This occurs when SRCLEN == 0. */
509enum { file_name_as_directory_slop = 2 };
510
507/* Convert from file name SRC of length SRCLEN to directory name in 511/* Convert from file name SRC of length SRCLEN to directory name in
508 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte 512 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte
509 string. On UNIX, just make sure there is a terminating /. Return 513 string. On UNIX, just make sure there is a terminating /. Return
@@ -521,14 +525,10 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
521 return 2; 525 return 2;
522 } 526 }
523 527
524 strcpy (dst, src); 528 memcpy (dst, src, srclen);
525
526 if (!IS_DIRECTORY_SEP (dst[srclen - 1])) 529 if (!IS_DIRECTORY_SEP (dst[srclen - 1]))
527 { 530 dst[srclen++] = DIRECTORY_SEP;
528 dst[srclen] = DIRECTORY_SEP; 531 dst[srclen] = 0;
529 dst[srclen + 1] = '\0';
530 srclen++;
531 }
532#ifdef DOS_NT 532#ifdef DOS_NT
533 dostounix_filename (dst, multibyte); 533 dostounix_filename (dst, multibyte);
534#endif 534#endif
@@ -547,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */)
547{ 547{
548 char *buf; 548 char *buf;
549 ptrdiff_t length; 549 ptrdiff_t length;
550 Lisp_Object handler; 550 Lisp_Object handler, val;
551 USE_SAFE_ALLOCA;
551 552
552 CHECK_STRING (file); 553 CHECK_STRING (file);
553 if (NILP (file)) 554 if (NILP (file))
@@ -569,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */)
569 if (!NILP (Vw32_downcase_file_names)) 570 if (!NILP (Vw32_downcase_file_names))
570 file = Fdowncase (file); 571 file = Fdowncase (file);
571#endif 572#endif
572 buf = alloca (SBYTES (file) + 10); 573 buf = SAFE_ALLOCA (SBYTES (file) + file_name_as_directory_slop + 1);
573 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), 574 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
574 STRING_MULTIBYTE (file)); 575 STRING_MULTIBYTE (file));
575 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); 576 val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
577 SAFE_FREE ();
578 return val;
576} 579}
577 580
578/* Convert from directory name SRC of length SRCLEN to file name in 581/* Convert from directory name SRC of length SRCLEN to file name in
@@ -584,18 +587,17 @@ static ptrdiff_t
584directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) 587directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
585{ 588{
586 /* Process as Unix format: just remove any final slash. 589 /* Process as Unix format: just remove any final slash.
587 But leave "/" unchanged; do not change it to "". */ 590 But leave "/" and "//" unchanged. */
588 strcpy (dst, src); 591 while (srclen > 1
589 if (srclen > 1
590 && IS_DIRECTORY_SEP (dst[srclen - 1])
591#ifdef DOS_NT 592#ifdef DOS_NT
592 && !IS_ANY_SEP (dst[srclen - 2]) 593 && !IS_ANY_SEP (src[srclen - 2])
593#endif 594#endif
594 ) 595 && IS_DIRECTORY_SEP (src[srclen - 1])
595 { 596 && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0])))
596 dst[srclen - 1] = 0; 597 srclen--;
597 srclen--; 598
598 } 599 memcpy (dst, src, srclen);
600 dst[srclen] = 0;
599#ifdef DOS_NT 601#ifdef DOS_NT
600 dostounix_filename (dst, multibyte); 602 dostounix_filename (dst, multibyte);
601#endif 603#endif
@@ -613,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */)
613{ 615{
614 char *buf; 616 char *buf;
615 ptrdiff_t length; 617 ptrdiff_t length;
616 Lisp_Object handler; 618 Lisp_Object handler, val;
619 USE_SAFE_ALLOCA;
617 620
618 CHECK_STRING (directory); 621 CHECK_STRING (directory);
619 622
@@ -636,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */)
636 if (!NILP (Vw32_downcase_file_names)) 639 if (!NILP (Vw32_downcase_file_names))
637 directory = Fdowncase (directory); 640 directory = Fdowncase (directory);
638#endif 641#endif
639 buf = alloca (SBYTES (directory) + 20); 642 buf = SAFE_ALLOCA (SBYTES (directory) + 1);
640 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), 643 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
641 STRING_MULTIBYTE (directory)); 644 STRING_MULTIBYTE (directory));
642 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); 645 val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
646 SAFE_FREE ();
647 return val;
643} 648}
644 649
645static const char make_temp_name_tbl[64] = 650static const char make_temp_name_tbl[64] =
@@ -837,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
837 Lisp_Object handler, result, handled_name; 842 Lisp_Object handler, result, handled_name;
838 bool multibyte; 843 bool multibyte;
839 Lisp_Object hdir; 844 Lisp_Object hdir;
845 USE_SAFE_ALLOCA;
840 846
841 CHECK_STRING (name); 847 CHECK_STRING (name);
842 848
@@ -1011,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1011 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) 1017 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
1012 || p[3] == 0)))) 1018 || p[3] == 0))))
1013 lose = 1; 1019 lose = 1;
1014 /* We want to replace multiple `/' in a row with a single 1020 /* Replace multiple slashes with a single one, except
1015 slash. */ 1021 leave leading "//" alone. */
1016 else if (p > nm 1022 else if (IS_DIRECTORY_SEP (p[0])
1017 && IS_DIRECTORY_SEP (p[0]) 1023 && IS_DIRECTORY_SEP (p[1])
1018 && IS_DIRECTORY_SEP (p[1])) 1024 && (p != nm || IS_DIRECTORY_SEP (p[2])))
1019 lose = 1; 1025 lose = 1;
1020 p++; 1026 p++;
1021 } 1027 }
@@ -1098,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1098 else /* ~user/filename */ 1104 else /* ~user/filename */
1099 { 1105 {
1100 char *o, *p; 1106 char *o, *p;
1101 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); 1107 for (p = nm; *p && !IS_DIRECTORY_SEP (*p); p++)
1102 o = alloca (p - nm + 1); 1108 continue;
1109 o = SAFE_ALLOCA (p - nm + 1);
1103 memcpy (o, nm, p - nm); 1110 memcpy (o, nm, p - nm);
1104 o [p - nm] = 0; 1111 o[p - nm] = 0;
1105 1112
1106 block_input (); 1113 block_input ();
1107 pw = getpwnam (o + 1); 1114 pw = getpwnam (o + 1);
@@ -1217,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1217 if (!IS_DIRECTORY_SEP (nm[0])) 1224 if (!IS_DIRECTORY_SEP (nm[0]))
1218 { 1225 {
1219 ptrdiff_t newlen = strlen (newdir); 1226 ptrdiff_t newlen = strlen (newdir);
1220 char *tmp = alloca (newlen + strlen (nm) + 2); 1227 char *tmp = alloca (newlen + file_name_as_directory_slop
1228 + strlen (nm) + 1);
1221 file_name_as_directory (tmp, newdir, newlen, multibyte); 1229 file_name_as_directory (tmp, newdir, newlen, multibyte);
1222 strcat (tmp, nm); 1230 strcat (tmp, nm);
1223 nm = tmp; 1231 nm = tmp;
@@ -1271,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1271 1279
1272 if (newdir) 1280 if (newdir)
1273 { 1281 {
1274 /* Get rid of any slash at the end of newdir, unless newdir is 1282 /* Ignore any slash at the end of newdir, unless newdir is
1275 just / or // (an incomplete UNC name). */ 1283 just "/" or "//". */
1276 length = strlen (newdir); 1284 length = strlen (newdir);
1277 tlen = length + 1; 1285 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1278 if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) 1286 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1279#ifdef WINDOWSNT 1287 length--;
1280 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1281#endif
1282 )
1283 {
1284 char *temp = alloca (length);
1285 memcpy (temp, newdir, length - 1);
1286 temp[length - 1] = 0;
1287 length--;
1288 newdir = temp;
1289 }
1290 } 1288 }
1291 else 1289 else
1292 { 1290 length = 0;
1293 length = 0;
1294 tlen = 0;
1295 }
1296 1291
1297 /* Now concatenate the directory and name to new space in the stack frame. */ 1292 /* Now concatenate the directory and name to new space in the stack frame. */
1298 tlen += strlen (nm) + 1; 1293 tlen = length + file_name_as_directory_slop + strlen (nm) + 1;
1299#ifdef DOS_NT 1294#ifdef DOS_NT
1300 /* Reserve space for drive specifier and escape prefix, since either 1295 /* Reserve space for drive specifier and escape prefix, since either
1301 or both may need to be inserted. (The Microsoft x86 compiler 1296 or both may need to be inserted. (The Microsoft x86 compiler
@@ -1303,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1303 target = alloca (tlen + 4); 1298 target = alloca (tlen + 4);
1304 target += 4; 1299 target += 4;
1305#else /* not DOS_NT */ 1300#else /* not DOS_NT */
1306 target = alloca (tlen); 1301 target = SAFE_ALLOCA (tlen);
1307#endif /* not DOS_NT */ 1302#endif /* not DOS_NT */
1308 *target = 0; 1303 *target = 0;
1309 1304
@@ -1320,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1320 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) 1315 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
1321 && newdir[1] == '\0')) 1316 && newdir[1] == '\0'))
1322#endif 1317#endif
1323 strcpy (target, newdir); 1318 {
1319 memcpy (target, newdir, length);
1320 target[length] = 0;
1321 }
1324 } 1322 }
1325 else 1323 else
1326 file_name_as_directory (target, newdir, length, multibyte); 1324 file_name_as_directory (target, newdir, length, multibyte);
@@ -1380,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1380 ++o; 1378 ++o;
1381 p += 3; 1379 p += 3;
1382 } 1380 }
1383 else if (p > target && IS_DIRECTORY_SEP (p[1])) 1381 else if (IS_DIRECTORY_SEP (p[1])
1384 /* Collapse multiple `/' in a row. */ 1382 && (p != target || IS_DIRECTORY_SEP (p[2])))
1383 /* Collapse multiple "/", except leave leading "//" alone. */
1385 p++; 1384 p++;
1386 else 1385 else
1387 { 1386 {
@@ -1429,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1429 { 1428 {
1430 handled_name = call3 (handler, Qexpand_file_name, 1429 handled_name = call3 (handler, Qexpand_file_name,
1431 result, default_directory); 1430 result, default_directory);
1432 if (STRINGP (handled_name)) 1431 if (! STRINGP (handled_name))
1433 return handled_name; 1432 error ("Invalid handler in `file-name-handler-alist'");
1434 error ("Invalid handler in `file-name-handler-alist'"); 1433 result = handled_name;
1435 } 1434 }
1436 1435
1436 SAFE_FREE ();
1437 return result; 1437 return result;
1438} 1438}
1439 1439
diff --git a/src/frame.h b/src/frame.h
index e44003b15ca..2dcb7562524 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -56,16 +56,6 @@ enum vertical_scroll_bar_type
56 vertical_scroll_bar_right 56 vertical_scroll_bar_right
57}; 57};
58 58
59enum text_cursor_kinds
60{
61 DEFAULT_CURSOR = -2,
62 NO_CURSOR = -1,
63 FILLED_BOX_CURSOR,
64 HOLLOW_BOX_CURSOR,
65 BAR_CURSOR,
66 HBAR_CURSOR
67};
68
69enum fullscreen_type 59enum fullscreen_type
70{ 60{
71 FULLSCREEN_NONE, 61 FULLSCREEN_NONE,
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 7e304d417d8..8e255ac4bfb 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1341,6 +1341,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
1341 int base_width, base_height; 1341 int base_width, base_height;
1342 int min_rows = 0, min_cols = 0; 1342 int min_rows = 0, min_cols = 0;
1343 int win_gravity = f->win_gravity; 1343 int win_gravity = f->win_gravity;
1344 Lisp_Object fs_state, frame;
1344 1345
1345 /* Don't set size hints during initialization; that apparently leads 1346 /* Don't set size hints during initialization; that apparently leads
1346 to a race condition. See the thread at 1347 to a race condition. See the thread at
@@ -1348,6 +1349,16 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
1348 if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f)) 1349 if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f))
1349 return; 1350 return;
1350 1351
1352 XSETFRAME (frame, f);
1353 fs_state = Fframe_parameter (frame, Qfullscreen);
1354 if (EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth))
1355 {
1356 /* Don't set hints when maximized or fullscreen. Apparently KWin and
1357 Gtk3 don't get along and the frame shrinks (!).
1358 */
1359 return;
1360 }
1361
1351 if (flags) 1362 if (flags)
1352 { 1363 {
1353 memset (&size_hints, 0, sizeof (size_hints)); 1364 memset (&size_hints, 0, sizeof (size_hints));
diff --git a/src/lisp.h b/src/lisp.h
index 60a553cc7d1..51c09e0abb3 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4177,7 +4177,6 @@ extern void init_sys_modes (struct tty_display_info *);
4177extern void reset_sys_modes (struct tty_display_info *); 4177extern void reset_sys_modes (struct tty_display_info *);
4178extern void init_all_sys_modes (void); 4178extern void init_all_sys_modes (void);
4179extern void reset_all_sys_modes (void); 4179extern void reset_all_sys_modes (void);
4180extern void flush_pending_output (int) ATTRIBUTE_CONST;
4181extern void child_setup_tty (int); 4180extern void child_setup_tty (int);
4182extern void setup_pty (int); 4181extern void setup_pty (int);
4183extern int set_window_size (int, int, int); 4182extern int set_window_size (int, int, int);
diff --git a/src/nsterm.m b/src/nsterm.m
index f374bfd90c6..287c119ba73 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -742,8 +742,8 @@ ns_update_window_begin (struct window *w)
742 742
743 743
744static void 744static void
745ns_update_window_end (struct window *w, int cursor_on_p, 745ns_update_window_end (struct window *w, bool cursor_on_p,
746 int mouse_face_overwritten_p) 746 bool mouse_face_overwritten_p)
747/* -------------------------------------------------------------------------- 747/* --------------------------------------------------------------------------
748 Finished a grouped sequence of drawing calls 748 Finished a grouped sequence of drawing calls
749 external (RIF) call; for one window called before update_end 749 external (RIF) call; for one window called before update_end
@@ -2341,8 +2341,8 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2341 2341
2342static void 2342static void
2343ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, 2343ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2344 int x, int y, int cursor_type, int cursor_width, 2344 int x, int y, enum text_cursor_kinds cursor_type,
2345 int on_p, int active_p) 2345 int cursor_width, bool on_p, bool active_p)
2346/* -------------------------------------------------------------------------- 2346/* --------------------------------------------------------------------------
2347 External call (RIF): draw cursor. 2347 External call (RIF): draw cursor.
2348 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. 2348 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
diff --git a/src/process.c b/src/process.c
index 1d1741d8b7e..3edc3b4f061 100644
--- a/src/process.c
+++ b/src/process.c
@@ -826,6 +826,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
826 826
827 if (fd >= 0) 827 if (fd >= 0)
828 { 828 {
829#ifdef PTY_OPEN
830 /* Set FD's close-on-exec flag. This is needed even if
831 PT_OPEN calls posix_openpt with O_CLOEXEC, since POSIX
832 doesn't require support for that combination.
833 Multithreaded platforms where posix_openpt ignores
834 O_CLOEXEC (or where PTY_OPEN doesn't call posix_openpt)
835 have a race condition between the PTY_OPEN and here. */
836 fcntl (fd, F_SETFD, FD_CLOEXEC);
837#endif
829 /* check to make certain that both sides are available 838 /* check to make certain that both sides are available
830 this avoids a nasty yet stupid bug in rlogins */ 839 this avoids a nasty yet stupid bug in rlogins */
831#ifdef PTY_TTY_NAME_SPRINTF 840#ifdef PTY_TTY_NAME_SPRINTF
@@ -1322,15 +1331,18 @@ DEFUN ("process-thread", Fprocess_thread, Sprocess_thread,
1322DEFUN ("set-process-window-size", Fset_process_window_size, 1331DEFUN ("set-process-window-size", Fset_process_window_size,
1323 Sset_process_window_size, 3, 3, 0, 1332 Sset_process_window_size, 3, 3, 0,
1324 doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) 1333 doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */)
1325 (register Lisp_Object process, Lisp_Object height, Lisp_Object width) 1334 (Lisp_Object process, Lisp_Object height, Lisp_Object width)
1326{ 1335{
1327 CHECK_PROCESS (process); 1336 CHECK_PROCESS (process);
1328 CHECK_RANGED_INTEGER (height, 0, INT_MAX); 1337
1329 CHECK_RANGED_INTEGER (width, 0, INT_MAX); 1338 /* All known platforms store window sizes as 'unsigned short'. */
1339 CHECK_RANGED_INTEGER (height, 0, USHRT_MAX);
1340 CHECK_RANGED_INTEGER (width, 0, USHRT_MAX);
1330 1341
1331 if (XPROCESS (process)->infd < 0 1342 if (XPROCESS (process)->infd < 0
1332 || set_window_size (XPROCESS (process)->infd, 1343 || (set_window_size (XPROCESS (process)->infd,
1333 XINT (height), XINT (width)) <= 0) 1344 XINT (height), XINT (width))
1345 < 0))
1334 return Qnil; 1346 return Qnil;
1335 else 1347 else
1336 return Qt; 1348 return Qt;
@@ -1590,22 +1602,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
1590 function. The argument list is protected by the caller, so all 1602 function. The argument list is protected by the caller, so all
1591 we really have to worry about is buffer. */ 1603 we really have to worry about is buffer. */
1592 { 1604 {
1593 struct gcpro gcpro1, gcpro2; 1605 struct gcpro gcpro1;
1594 1606 GCPRO1 (buffer);
1595 current_dir = BVAR (current_buffer, directory); 1607 current_dir = encode_current_directory ();
1596
1597 GCPRO2 (buffer, current_dir);
1598
1599 current_dir = Funhandled_file_name_directory (current_dir);
1600 if (NILP (current_dir))
1601 /* If the file name handler says that current_dir is unreachable, use
1602 a sensible default. */
1603 current_dir = build_string ("~/");
1604 current_dir = expand_and_dir_to_file (current_dir, Qnil);
1605 if (NILP (Ffile_accessible_directory_p (current_dir)))
1606 report_file_error ("Setting current directory",
1607 BVAR (current_buffer, directory));
1608
1609 UNGCPRO; 1608 UNGCPRO;
1610 } 1609 }
1611 1610
@@ -1852,7 +1851,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1852 bool pty_flag = 0; 1851 bool pty_flag = 0;
1853 char pty_name[PTY_NAME_SIZE]; 1852 char pty_name[PTY_NAME_SIZE];
1854 Lisp_Object lisp_pty_name = Qnil; 1853 Lisp_Object lisp_pty_name = Qnil;
1855 Lisp_Object encoded_current_dir;
1856 1854
1857 inchannel = outchannel = -1; 1855 inchannel = outchannel = -1;
1858 1856
@@ -1914,15 +1912,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1914 /* This may signal an error. */ 1912 /* This may signal an error. */
1915 setup_process_coding_systems (process); 1913 setup_process_coding_systems (process);
1916 1914
1917 encoded_current_dir = ENCODE_FILE (current_dir);
1918
1919 block_input (); 1915 block_input ();
1920 block_child_signal (); 1916 block_child_signal ();
1921 1917
1922#ifndef WINDOWSNT 1918#ifndef WINDOWSNT
1923 /* vfork, and prevent local vars from being clobbered by the vfork. */ 1919 /* vfork, and prevent local vars from being clobbered by the vfork. */
1924 { 1920 {
1925 Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; 1921 Lisp_Object volatile current_dir_volatile = current_dir;
1926 Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; 1922 Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name;
1927 char **volatile new_argv_volatile = new_argv; 1923 char **volatile new_argv_volatile = new_argv;
1928 int volatile forkin_volatile = forkin; 1924 int volatile forkin_volatile = forkin;
@@ -1931,7 +1927,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1931 1927
1932 pid = vfork (); 1928 pid = vfork ();
1933 1929
1934 encoded_current_dir = encoded_current_dir_volatile; 1930 current_dir = current_dir_volatile;
1935 lisp_pty_name = lisp_pty_name_volatile; 1931 lisp_pty_name = lisp_pty_name_volatile;
1936 new_argv = new_argv_volatile; 1932 new_argv = new_argv_volatile;
1937 forkin = forkin_volatile; 1933 forkin = forkin_volatile;
@@ -2043,11 +2039,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2043 if (pty_flag) 2039 if (pty_flag)
2044 child_setup_tty (xforkout); 2040 child_setup_tty (xforkout);
2045#ifdef WINDOWSNT 2041#ifdef WINDOWSNT
2046 pid = child_setup (xforkin, xforkout, xforkout, 2042 pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
2047 new_argv, 1, encoded_current_dir);
2048#else /* not WINDOWSNT */ 2043#else /* not WINDOWSNT */
2049 child_setup (xforkin, xforkout, xforkout, 2044 child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
2050 new_argv, 1, encoded_current_dir);
2051#endif /* not WINDOWSNT */ 2045#endif /* not WINDOWSNT */
2052 } 2046 }
2053 2047
@@ -4012,15 +4006,12 @@ deactivate_process (Lisp_Object proc)
4012 } 4006 }
4013#endif 4007#endif
4014 4008
4015 inchannel = p->infd;
4016
4017 /* Beware SIGCHLD hereabouts. */ 4009 /* Beware SIGCHLD hereabouts. */
4018 if (inchannel >= 0)
4019 flush_pending_output (inchannel);
4020 4010
4021 for (i = 0; i < PROCESS_OPEN_FDS; i++) 4011 for (i = 0; i < PROCESS_OPEN_FDS; i++)
4022 close_process_fd (&p->open_fd[i]); 4012 close_process_fd (&p->open_fd[i]);
4023 4013
4014 inchannel = p->infd;
4024 if (inchannel >= 0) 4015 if (inchannel >= 0)
4025 { 4016 {
4026 p->infd = -1; 4017 p->infd = -1;
@@ -5928,10 +5919,9 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
5928 return; 5919 return;
5929 } 5920 }
5930 5921
5931 switch (signo)
5932 {
5933#ifdef SIGCONT 5922#ifdef SIGCONT
5934 case SIGCONT: 5923 if (signo == SIGCONT)
5924 {
5935 p->raw_status_new = 0; 5925 p->raw_status_new = 0;
5936 pset_status (p, Qrun); 5926 pset_status (p, Qrun);
5937 p->tick = ++process_tick; 5927 p->tick = ++process_tick;
@@ -5940,14 +5930,8 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
5940 status_notify (NULL); 5930 status_notify (NULL);
5941 redisplay_preserve_echo_area (13); 5931 redisplay_preserve_echo_area (13);
5942 } 5932 }
5943 break;
5944#endif /* ! defined (SIGCONT) */
5945 case SIGINT:
5946 case SIGQUIT:
5947 case SIGKILL:
5948 flush_pending_output (p->infd);
5949 break;
5950 } 5933 }
5934#endif
5951 5935
5952 /* If we don't have process groups, send the signal to the immediate 5936 /* If we don't have process groups, send the signal to the immediate
5953 subprocess. That isn't really right, but it's better than any 5937 subprocess. That isn't really right, but it's better than any
diff --git a/src/process.h b/src/process.h
index 95881d10f58..e8bafe689b1 100644
--- a/src/process.h
+++ b/src/process.h
@@ -221,6 +221,7 @@ enum
221 221
222extern void block_child_signal (void); 222extern void block_child_signal (void);
223extern void unblock_child_signal (void); 223extern void unblock_child_signal (void);
224extern Lisp_Object encode_current_directory (void);
224extern void record_kill_process (struct Lisp_Process *, Lisp_Object); 225extern void record_kill_process (struct Lisp_Process *, Lisp_Object);
225 226
226/* Defined in sysdep.c. */ 227/* Defined in sysdep.c. */
diff --git a/src/sysdep.c b/src/sysdep.c
index 201ba9d104d..0d732526528 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -337,16 +337,6 @@ child_status_changed (pid_t child, int *status, int options)
337 return get_child_status (child, status, WNOHANG | options, 0); 337 return get_child_status (child, status, WNOHANG | options, 0);
338} 338}
339 339
340/*
341 * flush any pending output
342 * (may flush input as well; it does not matter the way we use it)
343 */
344
345void
346flush_pending_output (int channel)
347{
348 /* FIXME: maybe this function should be removed */
349}
350 340
351/* Set up the terminal at the other end of a pseudo-terminal that 341/* Set up the terminal at the other end of a pseudo-terminal that
352 we will be controlling an inferior through. 342 we will be controlling an inferior through.
@@ -481,10 +471,20 @@ sys_subshell (void)
481 pid_t pid; 471 pid_t pid;
482 int status; 472 int status;
483 struct save_signal saved_handlers[5]; 473 struct save_signal saved_handlers[5];
484 Lisp_Object dir; 474 char *str = SSDATA (encode_current_directory ());
485 unsigned char *volatile str_volatile = 0; 475
486 unsigned char *str; 476#ifdef DOS_NT
487 int len; 477 pid = 0;
478#else
479 {
480 char *volatile str_volatile = str;
481 pid = vfork ();
482 str = str_volatile;
483 }
484#endif
485
486 if (pid < 0)
487 error ("Can't spawn subshell");
488 488
489 saved_handlers[0].code = SIGINT; 489 saved_handlers[0].code = SIGINT;
490 saved_handlers[1].code = SIGQUIT; 490 saved_handlers[1].code = SIGQUIT;
@@ -496,31 +496,8 @@ sys_subshell (void)
496 saved_handlers[3].code = 0; 496 saved_handlers[3].code = 0;
497#endif 497#endif
498 498
499 /* Mentioning current_buffer->buffer would mean including buffer.h,
500 which somehow wedges the hp compiler. So instead... */
501
502 dir = intern ("default-directory");
503 if (NILP (Fboundp (dir)))
504 goto xyzzy;
505 dir = Fsymbol_value (dir);
506 if (!STRINGP (dir))
507 goto xyzzy;
508
509 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
510 str_volatile = str = alloca (SCHARS (dir) + 2);
511 len = SCHARS (dir);
512 memcpy (str, SDATA (dir), len);
513 if (str[len - 1] != '/') str[len++] = '/';
514 str[len] = 0;
515 xyzzy:
516
517#ifdef DOS_NT 499#ifdef DOS_NT
518 pid = 0;
519 save_signal_handlers (saved_handlers); 500 save_signal_handlers (saved_handlers);
520#else
521 pid = vfork ();
522 if (pid == -1)
523 error ("Can't spawn subshell");
524#endif 501#endif
525 502
526 if (pid == 0) 503 if (pid == 0)
@@ -538,11 +515,10 @@ sys_subshell (void)
538 sh = "sh"; 515 sh = "sh";
539 516
540 /* Use our buffer's default directory for the subshell. */ 517 /* Use our buffer's default directory for the subshell. */
541 str = str_volatile; 518 if (chdir (str) != 0)
542 if (str && chdir ((char *) str) != 0)
543 { 519 {
544#ifndef DOS_NT 520#ifndef DOS_NT
545 emacs_perror ((char *) str); 521 emacs_perror (str);
546 _exit (EXIT_CANCELED); 522 _exit (EXIT_CANCELED);
547#endif 523#endif
548 } 524 }
@@ -556,8 +532,6 @@ sys_subshell (void)
556 if (epwd) 532 if (epwd)
557 { 533 {
558 strcpy (old_pwd, epwd); 534 strcpy (old_pwd, epwd);
559 if (str[len - 1] == '/')
560 str[len - 1] = '\0';
561 setenv ("PWD", str, 1); 535 setenv ("PWD", str, 1);
562 } 536 }
563 st = system (sh); 537 st = system (sh);
@@ -1196,7 +1170,8 @@ get_tty_size (int fd, int *widthp, int *heightp)
1196} 1170}
1197 1171
1198/* Set the logical window size associated with descriptor FD 1172/* Set the logical window size associated with descriptor FD
1199 to HEIGHT and WIDTH. This is used mainly with ptys. */ 1173 to HEIGHT and WIDTH. This is used mainly with ptys.
1174 Return a negative value on failure. */
1200 1175
1201int 1176int
1202set_window_size (int fd, int height, int width) 1177set_window_size (int fd, int height, int width)
@@ -1208,10 +1183,7 @@ set_window_size (int fd, int height, int width)
1208 size.ws_row = height; 1183 size.ws_row = height;
1209 size.ws_col = width; 1184 size.ws_col = width;
1210 1185
1211 if (ioctl (fd, TIOCSWINSZ, &size) == -1) 1186 return ioctl (fd, TIOCSWINSZ, &size);
1212 return 0; /* error */
1213 else
1214 return 1;
1215 1187
1216#else 1188#else
1217#ifdef TIOCSSIZE 1189#ifdef TIOCSSIZE
@@ -1221,10 +1193,7 @@ set_window_size (int fd, int height, int width)
1221 size.ts_lines = height; 1193 size.ts_lines = height;
1222 size.ts_cols = width; 1194 size.ts_cols = width;
1223 1195
1224 if (ioctl (fd, TIOCGSIZE, &size) == -1) 1196 return ioctl (fd, TIOCGSIZE, &size);
1225 return 0;
1226 else
1227 return 1;
1228#else 1197#else
1229 return -1; 1198 return -1;
1230#endif /* not SunOS-style */ 1199#endif /* not SunOS-style */
@@ -2485,7 +2454,7 @@ serial_configure (struct Lisp_Process *p,
2485 Lisp_Object childp2 = Qnil; 2454 Lisp_Object childp2 = Qnil;
2486 Lisp_Object tem = Qnil; 2455 Lisp_Object tem = Qnil;
2487 struct termios attr; 2456 struct termios attr;
2488 int err = -1; 2457 int err;
2489 char summary[4] = "???"; /* This usually becomes "8N1". */ 2458 char summary[4] = "???"; /* This usually becomes "8N1". */
2490 2459
2491 childp2 = Fcopy_sequence (p->childp); 2460 childp2 = Fcopy_sequence (p->childp);
@@ -2852,29 +2821,41 @@ procfs_ttyname (int rdev)
2852 return build_string (name); 2821 return build_string (name);
2853} 2822}
2854 2823
2855static unsigned long 2824static uintmax_t
2856procfs_get_total_memory (void) 2825procfs_get_total_memory (void)
2857{ 2826{
2858 FILE *fmem; 2827 FILE *fmem;
2859 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ 2828 uintmax_t retval = 2 * 1024 * 1024; /* default: 2 GiB */
2829 int c;
2860 2830
2861 block_input (); 2831 block_input ();
2862 fmem = emacs_fopen ("/proc/meminfo", "r"); 2832 fmem = emacs_fopen ("/proc/meminfo", "r");
2863 2833
2864 if (fmem) 2834 if (fmem)
2865 { 2835 {
2866 unsigned long entry_value; 2836 uintmax_t entry_value;
2867 char entry_name[20]; /* the longest I saw is 13+1 */ 2837 bool done;
2838
2839 do
2840 switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value))
2841 {
2842 case 1:
2843 retval = entry_value;
2844 done = 1;
2845 break;
2846
2847 case 0:
2848 while ((c = getc (fmem)) != EOF && c != '\n')
2849 continue;
2850 done = c == EOF;
2851 break;
2852
2853 default:
2854 done = 1;
2855 break;
2856 }
2857 while (!done);
2868 2858
2869 while (!feof (fmem) && !ferror (fmem))
2870 {
2871 if (fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) >= 2
2872 && strcmp (entry_name, "MemTotal:") == 0)
2873 {
2874 retval = entry_value;
2875 break;
2876 }
2877 }
2878 fclose (fmem); 2859 fclose (fmem);
2879 } 2860 }
2880 unblock_input (); 2861 unblock_input ();
@@ -3275,7 +3256,7 @@ system_process_attributes (Lisp_Object pid)
3275{ 3256{
3276 int proc_id; 3257 int proc_id;
3277 int pagesize = getpagesize (); 3258 int pagesize = getpagesize ();
3278 int npages; 3259 unsigned long npages;
3279 int fscale; 3260 int fscale;
3280 struct passwd *pw; 3261 struct passwd *pw;
3281 struct group *gr; 3262 struct group *gr;
diff --git a/src/w32.c b/src/w32.c
index 21dbf49ed7c..7f9b96a77a5 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -2503,8 +2503,6 @@ gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
2503int 2503int
2504fdutimens (int fd, char const *file, struct timespec const timespec[2]) 2504fdutimens (int fd, char const *file, struct timespec const timespec[2])
2505{ 2505{
2506 struct _utimbuf ut;
2507
2508 if (!timespec) 2506 if (!timespec)
2509 { 2507 {
2510 errno = ENOSYS; 2508 errno = ENOSYS;
@@ -2515,12 +2513,28 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
2515 errno = EBADF; 2513 errno = EBADF;
2516 return -1; 2514 return -1;
2517 } 2515 }
2518 ut.actime = timespec[0].tv_sec; 2516 /* _futime's prototype defines 2nd arg as having the type 'struct
2519 ut.modtime = timespec[1].tv_sec; 2517 _utimbuf', while utime needs to accept 'struct utimbuf' for
2518 compatibility with Posix. So we need to use 2 different (but
2519 equivalent) types to avoid compiler warnings, sigh. */
2520 if (fd >= 0) 2520 if (fd >= 0)
2521 return _futime (fd, &ut); 2521 {
2522 struct _utimbuf _ut;
2523
2524 _ut.actime = timespec[0].tv_sec;
2525 _ut.modtime = timespec[1].tv_sec;
2526 return _futime (fd, &_ut);
2527 }
2522 else 2528 else
2523 return _utime (file, &ut); 2529 {
2530 struct utimbuf ut;
2531
2532 ut.actime = timespec[0].tv_sec;
2533 ut.modtime = timespec[1].tv_sec;
2534 /* Call 'utime', which is implemented below, not the MS library
2535 function, which fails on directories. */
2536 return utime (file, &ut);
2537 }
2524} 2538}
2525 2539
2526 2540
@@ -4501,6 +4515,9 @@ fstat (int desc, struct stat * buf)
4501 return 0; 4515 return 0;
4502} 4516}
4503 4517
4518/* A version of 'utime' which handles directories as well as
4519 files. */
4520
4504int 4521int
4505utime (const char *name, struct utimbuf *times) 4522utime (const char *name, struct utimbuf *times)
4506{ 4523{
diff --git a/src/w32term.c b/src/w32term.c
index 7d51850559b..7a15323551b 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -210,7 +210,6 @@ static int volatile input_signal_count;
210int w32_message_fd = -1; 210int w32_message_fd = -1;
211#endif /* CYGWIN */ 211#endif /* CYGWIN */
212 212
213static void x_update_window_end (struct window *, int, int);
214static void w32_handle_tool_bar_click (struct frame *, 213static void w32_handle_tool_bar_click (struct frame *,
215 struct input_event *); 214 struct input_event *);
216static void w32_define_cursor (Window, Cursor); 215static void w32_define_cursor (Window, Cursor);
@@ -676,8 +675,8 @@ w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
676 here. */ 675 here. */
677 676
678static void 677static void
679x_update_window_end (struct window *w, int cursor_on_p, 678x_update_window_end (struct window *w, bool cursor_on_p,
680 int mouse_face_overwritten_p) 679 bool mouse_face_overwritten_p)
681{ 680{
682 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); 681 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
683 682
@@ -5300,8 +5299,8 @@ w32_clear_frame_area (struct frame *f, int x, int y, int width, int height)
5300 5299
5301static void 5300static void
5302w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, 5301w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
5303 int x, int y, int cursor_type, int cursor_width, 5302 int x, int y, enum text_cursor_kinds cursor_type,
5304 int on_p, int active_p) 5303 int cursor_width, bool on_p, bool active_p)
5305{ 5304{
5306 if (on_p) 5305 if (on_p)
5307 { 5306 {
diff --git a/src/window.c b/src/window.c
index a1a069e0e7d..b02b30cd0b2 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5408,7 +5408,7 @@ struct save_window_data
5408 Lisp_Object saved_windows; 5408 Lisp_Object saved_windows;
5409 5409
5410 /* All fields above are traced by the GC. 5410 /* All fields above are traced by the GC.
5411 From `fame-cols' down, the fields are ignored by the GC. */ 5411 From `frame-cols' down, the fields are ignored by the GC. */
5412 5412
5413 int frame_cols, frame_lines, frame_menu_bar_lines; 5413 int frame_cols, frame_lines, frame_menu_bar_lines;
5414 int frame_tool_bar_lines; 5414 int frame_tool_bar_lines;
diff --git a/src/xdisp.c b/src/xdisp.c
index ea1cd7dd2bc..3ff4603b727 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3912,10 +3912,14 @@ handle_face_prop (struct it *it)
3912 /* For strings from a `display' property, use the face at 3912 /* For strings from a `display' property, use the face at
3913 IT's current buffer position as the base face to merge 3913 IT's current buffer position as the base face to merge
3914 with, so that overlay strings appear in the same face as 3914 with, so that overlay strings appear in the same face as
3915 surrounding text, unless they specify their own 3915 surrounding text, unless they specify their own faces.
3916 faces. */ 3916 For strings from wrap-prefix and line-prefix properties,
3917 use the default face, possibly remapped via
3918 Vface_remapping_alist. */
3917 base_face_id = it->string_from_prefix_prop_p 3919 base_face_id = it->string_from_prefix_prop_p
3918 ? DEFAULT_FACE_ID 3920 ? (!NILP (Vface_remapping_alist)
3921 ? lookup_basic_face (it->f, DEFAULT_FACE_ID)
3922 : DEFAULT_FACE_ID)
3919 : underlying_face_id (it); 3923 : underlying_face_id (it);
3920 } 3924 }
3921 3925
@@ -7046,7 +7050,9 @@ get_next_display_element (struct it *it)
7046 } 7050 }
7047 } 7051 }
7048 } 7052 }
7049 else 7053 /* next_element_from_display_vector sets this flag according to
7054 faces of the display vector glyphs, see there. */
7055 else if (it->method != GET_FROM_DISPLAY_VECTOR)
7050 { 7056 {
7051 int face_id = face_after_it_pos (it); 7057 int face_id = face_after_it_pos (it);
7052 it->end_of_box_run_p 7058 it->end_of_box_run_p
@@ -25763,12 +25769,12 @@ x_produce_glyphs (struct it *it)
25763 25769
25764/* EXPORT for RIF: 25770/* EXPORT for RIF:
25765 Output LEN glyphs starting at START at the nominal cursor position. 25771 Output LEN glyphs starting at START at the nominal cursor position.
25766 Advance the nominal cursor over the text. The global variable 25772 Advance the nominal cursor over the text. UPDATED_ROW is the glyph row
25767 updated_row is the glyph row being updated, and updated_area is the 25773 being updated, and UPDATED_AREA is the area of that row being updated. */
25768 area of that row being updated. */
25769 25774
25770void 25775void
25771x_write_glyphs (struct window *w, struct glyph *start, int len) 25776x_write_glyphs (struct window *w, struct glyph_row *updated_row,
25777 struct glyph *start, enum glyph_row_area updated_area, int len)
25772{ 25778{
25773 int x, hpos, chpos = w->phys_cursor.hpos; 25779 int x, hpos, chpos = w->phys_cursor.hpos;
25774 25780
@@ -25811,7 +25817,8 @@ x_write_glyphs (struct window *w, struct glyph *start, int len)
25811 Insert LEN glyphs from START at the nominal cursor position. */ 25817 Insert LEN glyphs from START at the nominal cursor position. */
25812 25818
25813void 25819void
25814x_insert_glyphs (struct window *w, struct glyph *start, int len) 25820x_insert_glyphs (struct window *w, struct glyph_row *updated_row,
25821 struct glyph *start, enum glyph_row_area updated_area, int len)
25815{ 25822{
25816 struct frame *f; 25823 struct frame *f;
25817 int line_height, shift_by_width, shifted_region_width; 25824 int line_height, shift_by_width, shifted_region_width;
@@ -25863,11 +25870,12 @@ x_insert_glyphs (struct window *w, struct glyph *start, int len)
25863 (inclusive) to pixel column TO_X (exclusive). The idea is that 25870 (inclusive) to pixel column TO_X (exclusive). The idea is that
25864 everything from TO_X onward is already erased. 25871 everything from TO_X onward is already erased.
25865 25872
25866 TO_X is a pixel position relative to updated_area of currently 25873 TO_X is a pixel position relative to UPDATED_AREA of currently
25867 updated window W. TO_X == -1 means clear to the end of this area. */ 25874 updated window W. TO_X == -1 means clear to the end of this area. */
25868 25875
25869void 25876void
25870x_clear_end_of_line (struct window *w, int to_x) 25877x_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
25878 enum glyph_row_area updated_area, int to_x)
25871{ 25879{
25872 struct frame *f; 25880 struct frame *f;
25873 int max_x, min_y, max_y; 25881 int max_x, min_y, max_y;
@@ -26463,7 +26471,7 @@ erase_phys_cursor (struct window *w)
26463 where to put the cursor is specified by HPOS, VPOS, X and Y. */ 26471 where to put the cursor is specified by HPOS, VPOS, X and Y. */
26464 26472
26465void 26473void
26466display_and_set_cursor (struct window *w, int on, 26474display_and_set_cursor (struct window *w, bool on,
26467 int hpos, int vpos, int x, int y) 26475 int hpos, int vpos, int x, int y)
26468{ 26476{
26469 struct frame *f = XFRAME (w->frame); 26477 struct frame *f = XFRAME (w->frame);
@@ -26547,7 +26555,7 @@ display_and_set_cursor (struct window *w, int on,
26547 of ON. */ 26555 of ON. */
26548 26556
26549static void 26557static void
26550update_window_cursor (struct window *w, int on) 26558update_window_cursor (struct window *w, bool on)
26551{ 26559{
26552 /* Don't update cursor in windows whose frame is in the process 26560 /* Don't update cursor in windows whose frame is in the process
26553 of being deleted. */ 26561 of being deleted. */
@@ -26583,7 +26591,7 @@ update_window_cursor (struct window *w, int on)
26583 in the window tree rooted at W. */ 26591 in the window tree rooted at W. */
26584 26592
26585static void 26593static void
26586update_cursor_in_window_tree (struct window *w, int on_p) 26594update_cursor_in_window_tree (struct window *w, bool on_p)
26587{ 26595{
26588 while (w) 26596 while (w)
26589 { 26597 {
@@ -26602,7 +26610,7 @@ update_cursor_in_window_tree (struct window *w, int on_p)
26602 Don't change the cursor's position. */ 26610 Don't change the cursor's position. */
26603 26611
26604void 26612void
26605x_update_cursor (struct frame *f, int on_p) 26613x_update_cursor (struct frame *f, bool on_p)
26606{ 26614{
26607 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); 26615 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
26608} 26616}
diff --git a/src/xterm.c b/src/xterm.c
index b5c5a5cb584..cea952f44d2 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -292,8 +292,6 @@ static void x_set_window_size_1 (struct frame *, int, int, int);
292static void x_raise_frame (struct frame *); 292static void x_raise_frame (struct frame *);
293static void x_lower_frame (struct frame *); 293static void x_lower_frame (struct frame *);
294static const XColor *x_color_cells (Display *, int *); 294static const XColor *x_color_cells (Display *, int *);
295static void x_update_window_end (struct window *, int, int);
296
297static int x_io_error_quitter (Display *); 295static int x_io_error_quitter (Display *);
298static struct terminal *x_create_terminal (struct x_display_info *); 296static struct terminal *x_create_terminal (struct x_display_info *);
299void x_delete_terminal (struct terminal *); 297void x_delete_terminal (struct terminal *);
@@ -612,7 +610,8 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
612 here. */ 610 here. */
613 611
614static void 612static void
615x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p) 613x_update_window_end (struct window *w, bool cursor_on_p,
614 bool mouse_face_overwritten_p)
616{ 615{
617 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); 616 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
618 617
@@ -7372,7 +7371,9 @@ x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
7372/* RIF: Draw cursor on window W. */ 7371/* RIF: Draw cursor on window W. */
7373 7372
7374static void 7373static void
7375x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, int cursor_type, int cursor_width, int on_p, int active_p) 7374x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
7375 int y, enum text_cursor_kinds cursor_type,
7376 int cursor_width, bool on_p, bool active_p)
7376{ 7377{
7377 struct frame *f = XFRAME (WINDOW_FRAME (w)); 7378 struct frame *f = XFRAME (WINDOW_FRAME (w));
7378 7379