From 3f246b657225c786c460b22d774ab0b2e7488b55 Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Tue, 20 Aug 2013 17:56:03 +0300 Subject: src/character.c (string_char): Improve commentary. --- src/ChangeLog | 4 ++++ src/character.c | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index e21d82bdc09..997459f01c2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2013-08-20 Kenichi Handa + + * character.c (string_char): Improve commentary. + 2013-08-20 Paul Eggert * image.c (SIGNATURE_DIGESTSIZE): Remove. 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) if (*p < 0x80 || ! (*p & 0x20) || ! (*p & 0x10)) { + /* 1-, 2-, and 3-byte sequences can be handled by the macro. */ c = STRING_CHAR_ADVANCE (p); } else if (! (*p & 0x08)) { - c = ((((p)[0] & 0xF) << 18) + /* A 4-byte sequence of this form: + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + c = ((((p)[0] & 0x7) << 18) | (((p)[1] & 0x3F) << 12) | (((p)[2] & 0x3F) << 6) | ((p)[3] & 0x3F)); @@ -186,7 +189,14 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len) } else { - c = ((((p)[1] & 0x3F) << 18) + /* A 5-byte sequence of this form: + + 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + + Note that the top 4 `x's are always 0, so shifting p[1] can + never exceed the maximum valid character codepoint. */ + c = (/* (((p)[0] & 0x3) << 24) ... always 0, so no need to shift. */ + (((p)[1] & 0x3F) << 18) | (((p)[2] & 0x3F) << 12) | (((p)[3] & 0x3F) << 6) | ((p)[4] & 0x3F)); -- cgit v1.2.1 From 0d7c1e66ffad14f76fbd226d50113a61c738806c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 20 Aug 2013 22:39:51 -0700 Subject: * process.c (allocate_pty) [PTY_OPEN]: Set fd's FD_CLOEXEC flag. We can't portably rely on PTY_OPEN doing that, even if it calls posix_openpt with O_CLOEXEC. --- src/ChangeLog | 6 ++++++ src/process.c | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 997459f01c2..c7cceb27a4f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2013-08-21 Paul Eggert + + * process.c (allocate_pty) [PTY_OPEN]: Set fd's FD_CLOEXEC flag. + We can't portably rely on PTY_OPEN doing that, even if + it calls posix_openpt with O_CLOEXEC. + 2013-08-20 Kenichi Handa * character.c (string_char): Improve commentary. diff --git a/src/process.c b/src/process.c index c4dd87a6b48..349ec26534b 100644 --- a/src/process.c +++ b/src/process.c @@ -687,6 +687,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) if (fd >= 0) { +#ifdef PTY_OPEN + /* Set FD's close-on-exec flag. This is needed even if + PT_OPEN calls posix_openpt with O_CLOEXEC, since POSIX + doesn't require support for that combination. + Multithreaded platforms where posix_openpt ignores + O_CLOEXEC (or where PTY_OPEN doesn't call posix_openpt) + have a race condition between the PTY_OPEN and here. */ + fcntl (fd, F_SETFD, FD_CLOEXEC); +#endif /* check to make certain that both sides are available this avoids a nasty yet stupid bug in rlogins */ #ifdef PTY_TTY_NAME_SPRINTF -- cgit v1.2.1 From 0c5307b05f8a31204b409756248f30add802377c Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 21 Aug 2013 11:02:45 +0400 Subject: Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE and GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES. * alloc.c (toplevel): Remove unnecessary nested #if...#endif. (mark_maybe_object) [!GC_MARK_STACK]: Define to emacs_abort to shut up compiler in mark_object. (dump_zombies): Convert to global and add EXTERNALLY_VISIBLE. --- src/ChangeLog | 9 +++++++++ src/alloc.c | 12 +++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index c7cceb27a4f..cb552c9d9d5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2013-08-21 Dmitry Antipov + + Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE + and GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES. + * alloc.c (toplevel): Remove unnecessary nested #if...#endif. + (mark_maybe_object) [!GC_MARK_STACK]: Define to emacs_abort + to shut up compiler in mark_object. + (dump_zombies): Convert to global and add EXTERNALLY_VISIBLE. + 2013-08-21 Paul Eggert * process.c (allocate_pty) [PTY_OPEN]: Set fd's FD_CLOEXEC flag. diff --git a/src/alloc.c b/src/alloc.c index c0d8c32b440..81742e1ffc1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -318,7 +318,6 @@ static void *min_heap_address, *max_heap_address; static struct mem_node mem_z; #define MEM_NIL &mem_z -#if GC_MARK_STACK || defined GC_MALLOC_CHECK static struct mem_node *mem_insert (void *, void *, enum mem_type); static void mem_insert_fixup (struct mem_node *); static void mem_rotate_left (struct mem_node *); @@ -326,7 +325,6 @@ static void mem_rotate_right (struct mem_node *); static void mem_delete (struct mem_node *); static void mem_delete_fixup (struct mem_node *); static struct mem_node *mem_find (void *); -#endif #endif /* GC_MARK_STACK || GC_MALLOC_CHECK */ @@ -4238,6 +4236,10 @@ live_buffer_p (struct mem_node *m, void *p) #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES +/* Currently not used, but may be called from gdb. */ + +void dump_zombies (void) EXTERNALLY_VISIBLE; + /* Array of objects that are kept alive because the C stack contains a pattern that looks like a reference to them . */ @@ -4620,7 +4622,7 @@ check_gcpros (void) #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES -static void +void dump_zombies (void) { int i; @@ -4757,6 +4759,10 @@ mark_stack (void) #endif } +#else /* GC_MARK_STACK == 0 */ + +#define mark_maybe_object(obj) emacs_abort () + #endif /* GC_MARK_STACK != 0 */ -- cgit v1.2.1 From 4a88129ae4332cbf3833c00f79100610ca2e576d Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 21 Aug 2013 14:27:30 -0700 Subject: * callproc.c: Fix race that killed background processes. (call_process): New arg TEMPFILE_INDEX. Callers changed. Record deleted process-id in critical section, not afterwards. Don't mistakenly kill process created by a call-process invocation that discards output and does not wait. Fixes: debbugs:15144 --- src/ChangeLog | 8 ++++++++ src/callproc.c | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index cb552c9d9d5..8983b6abd64 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2013-08-21 Paul Eggert + + * callproc.c: Fix race that killed background processes (Bug#15144). + (call_process): New arg TEMPFILE_INDEX. Callers changed. + Record deleted process-id in critical section, not afterwards. + Don't mistakenly kill process created by a call-process invocation + that discards output and does not wait. + 2013-08-21 Dmitry Antipov Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE diff --git a/src/callproc.c b/src/callproc.c index 2a9162cb5cc..fca4216b5f7 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -102,7 +102,7 @@ enum CALLPROC_FDS }; -static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); +static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t); /* Block SIGCHLD. */ @@ -248,14 +248,20 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * report_file_error ("Opening process input file", infile); record_unwind_protect_int (close_file_unwind, filefd); UNGCPRO; - return unbind_to (count, call_process (nargs, args, filefd)); + return unbind_to (count, call_process (nargs, args, filefd, -1)); } /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. + + If TEMPFILE_INDEX is nonnegative, it is the specpdl index of an + unwinder that is intended to remove the input temporary file; in + this case NARGS must be at least 2 and ARGS[1] is the file's name. + At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ static Lisp_Object -call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) +call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, + ptrdiff_t tempfile_index) { Lisp_Object buffer, current_dir, path; bool display_p; @@ -661,7 +667,22 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) child_errno = errno; if (pid > 0) - synch_process_pid = pid; + { + synch_process_pid = pid; + + if (INTEGERP (buffer)) + { + if (tempfile_index < 0) + record_deleted_pid (pid, Qnil); + else + { + eassert (1 < nargs); + record_deleted_pid (pid, args[1]); + clear_unwind_protect (tempfile_index); + } + synch_process_pid = 0; + } + } unblock_child_signal (); unblock_input (); @@ -1030,7 +1051,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - struct gcpro gcpro1, gcpro2; + struct gcpro gcpro1; Lisp_Object infile, val; ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object start = args[0]; @@ -1061,8 +1082,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r record_unwind_protect_int (close_file_unwind, fd); } - val = infile; - GCPRO2 (infile, val); + GCPRO1 (infile); if (nargs > 3 && !NILP (args[3])) Fdelete_region (start, end); @@ -1079,16 +1099,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r } args[1] = infile; - val = call_process (nargs, args, fd); - - if (!empty_input && 4 < nargs - && (INTEGERP (CONSP (args[4]) ? XCAR (args[4]) : args[4]))) - { - record_deleted_pid (synch_process_pid, infile); - synch_process_pid = 0; - clear_unwind_protect (count); - } - + val = call_process (nargs, args, fd, empty_input ? -1 : count); RETURN_UNGCPRO (unbind_to (count, val)); } -- cgit v1.2.1 From 2649579468273544ead2ed1c16b224a75ec3a895 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 22 Aug 2013 11:29:51 -0700 Subject: * process.c (flush_pending_output): Remove stub. All uses removed. --- src/ChangeLog | 5 +++++ src/lisp.h | 1 - src/process.c | 18 ++++-------------- src/sysdep.c | 10 ---------- 4 files changed, 9 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 8983b6abd64..ebd41a61203 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2013-08-22 Paul Eggert + + * process.c (flush_pending_output): Remove stub. + All uses removed. + 2013-08-21 Paul Eggert * callproc.c: Fix race that killed background processes (Bug#15144). diff --git a/src/lisp.h b/src/lisp.h index e6e90e1e968..ea8b7e3474e 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4100,7 +4100,6 @@ extern void init_sys_modes (struct tty_display_info *); extern void reset_sys_modes (struct tty_display_info *); extern void init_all_sys_modes (void); extern void reset_all_sys_modes (void); -extern void flush_pending_output (int) ATTRIBUTE_CONST; extern void child_setup_tty (int); extern void setup_pty (int); extern int set_window_size (int, int, int); diff --git a/src/process.c b/src/process.c index 349ec26534b..75cb590fc57 100644 --- a/src/process.c +++ b/src/process.c @@ -3846,15 +3846,12 @@ deactivate_process (Lisp_Object proc) } #endif - inchannel = p->infd; - /* Beware SIGCHLD hereabouts. */ - if (inchannel >= 0) - flush_pending_output (inchannel); for (i = 0; i < PROCESS_OPEN_FDS; i++) close_process_fd (&p->open_fd[i]); + inchannel = p->infd; if (inchannel >= 0) { p->infd = -1; @@ -5785,10 +5782,9 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, return; } - switch (signo) - { #ifdef SIGCONT - case SIGCONT: + if (signo == SIGCONT) + { p->raw_status_new = 0; pset_status (p, Qrun); p->tick = ++process_tick; @@ -5797,14 +5793,8 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, status_notify (NULL); redisplay_preserve_echo_area (13); } - break; -#endif /* ! defined (SIGCONT) */ - case SIGINT: - case SIGQUIT: - case SIGKILL: - flush_pending_output (p->infd); - break; } +#endif /* If we don't have process groups, send the signal to the immediate subprocess. That isn't really right, but it's better than any diff --git a/src/sysdep.c b/src/sysdep.c index 201ba9d104d..78e3d908cfe 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -337,16 +337,6 @@ child_status_changed (pid_t child, int *status, int options) return get_child_status (child, status, WNOHANG | options, 0); } -/* - * flush any pending output - * (may flush input as well; it does not matter the way we use it) - */ - -void -flush_pending_output (int channel) -{ - /* FIXME: maybe this function should be removed */ -} /* Set up the terminal at the other end of a pseudo-terminal that we will be controlling an inferior through. -- cgit v1.2.1 From 7f780da621d462afa3c6e0374590a86de513f863 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 23 Aug 2013 07:03:37 +0400 Subject: Redesign redisplay interface to drop updated_row and updated_area. * dispextern.h (updated_row, updated_area): Remove declaration. (struct redisplay_interface): Pass glyph row and row area parameters to write_glyphs, insert_glyphs and clear_end_of_line functions. (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line): Adjust prototypes. * dispnew.c (updated_row, updated_area): Remove. (redraw_overlapped_rows, update_window_line): Adjust user. (update_marginal_area, update_text_area): Likewise. Pass updated row as a parameter. Prefer enum glyph_row_area to int where appropriate. * xdisp.c (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line): Adjust users. --- src/ChangeLog | 15 +++++++++++++++ src/dispextern.h | 25 +++++++++++++----------- src/dispnew.c | 58 ++++++++++++++++++++------------------------------------ src/xdisp.c | 16 +++++++++------- 4 files changed, 59 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index ebd41a61203..aadaae24e98 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2013-08-23 Dmitry Antipov + + Redesign redisplay interface to drop updated_row and updated_area. + * dispextern.h (updated_row, updated_area): Remove declaration. + (struct redisplay_interface): Pass glyph row and row area parameters + to write_glyphs, insert_glyphs and clear_end_of_line functions. + (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line): + Adjust prototypes. + * dispnew.c (updated_row, updated_area): Remove. + (redraw_overlapped_rows, update_window_line): Adjust user. + (update_marginal_area, update_text_area): Likewise. Pass updated row + as a parameter. Prefer enum glyph_row_area to int where appropriate. + * xdisp.c (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line): + Adjust users. + 2013-08-22 Paul Eggert * process.c (flush_pending_output): Remove stub. diff --git a/src/dispextern.h b/src/dispextern.h index 7a4fa2ea774..eb5b4bd195c 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1197,11 +1197,6 @@ extern bool fonts_changed_p; extern struct glyph space_glyph; -/* Glyph row and area updated by update_window_line. */ - -extern struct glyph_row *updated_row; -extern int updated_area; - /* Non-zero means last display completed. Zero means it was preempted. */ @@ -2713,12 +2708,17 @@ struct redisplay_interface /* Write or insert LEN glyphs from STRING at the nominal output position. */ - void (*write_glyphs) (struct window *w, struct glyph *string, int len); - void (*insert_glyphs) (struct window *w, struct glyph *start, int len); + void (*write_glyphs) (struct window *w, struct glyph_row *row, + struct glyph *string, enum glyph_row_area area, + int len); + void (*insert_glyphs) (struct window *w, struct glyph_row *row, + struct glyph *start, enum glyph_row_area area, + int len); /* Clear from nominal output position to X. X < 0 means clear to right end of display. */ - void (*clear_end_of_line) (struct window *w, int x); + void (*clear_end_of_line) (struct window *w, struct glyph_row *row, + enum glyph_row_area area, int x); /* Function to call to scroll the display as described by RUN on window W. */ @@ -3178,9 +3178,12 @@ extern void x_get_glyph_overhangs (struct glyph *, struct frame *, int *, int *); extern void x_produce_glyphs (struct it *); -extern void x_write_glyphs (struct window *, struct glyph *, int); -extern void x_insert_glyphs (struct window *, struct glyph *, int len); -extern void x_clear_end_of_line (struct window *, int); +extern void x_write_glyphs (struct window *, struct glyph_row *, + struct glyph *, enum glyph_row_area, int); +extern void x_insert_glyphs (struct window *, struct glyph_row *, + struct glyph *, enum glyph_row_area, int); +extern void x_clear_end_of_line (struct window *, struct glyph_row *, + enum glyph_row_area, int); extern struct cursor_pos output_cursor; 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; static bool delayed_size_change; -/* Glyph row updated in update_window_line, and area that is updated. */ - -struct glyph_row *updated_row; -int updated_area; - /* A glyph for a space. */ struct glyph space_glyph; @@ -3230,14 +3225,12 @@ redraw_overlapped_rows (struct window *w, int yb) for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) { - updated_row = row; - updated_area = area; FRAME_RIF (f)->cursor_to (w, i, 0, row->y, area == TEXT_AREA ? row->x : 0); if (row->used[area]) - FRAME_RIF (f)->write_glyphs (w, row->glyphs[area], - row->used[area]); - FRAME_RIF (f)->clear_end_of_line (w, -1); + FRAME_RIF (f)->write_glyphs (w, row, row->glyphs[area], + area, row->used[area]); + FRAME_RIF (f)->clear_end_of_line (w, row, area, -1); } row->overlapped_p = 0; @@ -3511,22 +3504,20 @@ update_window (struct window *w, bool force_p) AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */ static void -update_marginal_area (struct window *w, int area, int vpos) +update_marginal_area (struct window *w, struct glyph_row *updated_row, + enum glyph_row_area area, int vpos) { struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); - /* Let functions in xterm.c know what area subsequent X positions - will be relative to. */ - updated_area = area; - /* Set cursor to start of glyphs, write them, and clear to the end of the area. I don't think that something more sophisticated is necessary here, since marginal areas will not be the default. */ rif->cursor_to (w, vpos, 0, desired_row->y, 0); if (desired_row->used[area]) - rif->write_glyphs (w, desired_row->glyphs[area], desired_row->used[area]); - rif->clear_end_of_line (w, -1); + rif->write_glyphs (w, updated_row, desired_row->glyphs[area], + area, desired_row->used[area]); + rif->clear_end_of_line (w, updated_row, area, -1); } @@ -3534,17 +3525,13 @@ update_marginal_area (struct window *w, int area, int vpos) Value is true if display has changed. */ static bool -update_text_area (struct window *w, int vpos) +update_text_area (struct window *w, struct glyph_row *updated_row, int vpos) { struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); bool changed_p = 0; - /* Let functions in xterm.c know what area subsequent X positions - will be relative to. */ - updated_area = TEXT_AREA; - /* If rows are at different X or Y, or rows have different height, or the current row is marked invalid, write the entire line. */ if (!current_row->enabled_p @@ -3567,11 +3554,11 @@ update_text_area (struct window *w, int vpos) rif->cursor_to (w, vpos, 0, desired_row->y, desired_row->x); if (desired_row->used[TEXT_AREA]) - rif->write_glyphs (w, desired_row->glyphs[TEXT_AREA], - desired_row->used[TEXT_AREA]); + rif->write_glyphs (w, updated_row, desired_row->glyphs[TEXT_AREA], + TEXT_AREA, desired_row->used[TEXT_AREA]); /* Clear to end of window. */ - rif->clear_end_of_line (w, -1); + rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1); changed_p = 1; /* This erases the cursor. We do this here because @@ -3708,7 +3695,8 @@ update_text_area (struct window *w, int vpos) } rif->cursor_to (w, vpos, start_hpos, desired_row->y, start_x); - rif->write_glyphs (w, start, i - start_hpos); + rif->write_glyphs (w, updated_row, start, + TEXT_AREA, i - start_hpos); changed_p = 1; } } @@ -3717,7 +3705,8 @@ update_text_area (struct window *w, int vpos) if (i < desired_row->used[TEXT_AREA]) { rif->cursor_to (w, vpos, i, desired_row->y, x); - rif->write_glyphs (w, desired_glyph, desired_row->used[TEXT_AREA] - i); + rif->write_glyphs (w, updated_row, desired_glyph, + TEXT_AREA, desired_row->used[TEXT_AREA] - i); changed_p = 1; } @@ -3739,7 +3728,7 @@ update_text_area (struct window *w, int vpos) if (i >= desired_row->used[TEXT_AREA]) rif->cursor_to (w, vpos, i, desired_row->y, desired_row->pixel_width); - rif->clear_end_of_line (w, -1); + rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1); changed_p = 1; } else if (desired_row->pixel_width < current_row->pixel_width) @@ -3767,7 +3756,7 @@ update_text_area (struct window *w, int vpos) } else xlim = current_row->pixel_width; - rif->clear_end_of_line (w, xlim); + rif->clear_end_of_line (w, updated_row, TEXT_AREA, xlim); changed_p = 1; } } @@ -3786,10 +3775,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); bool changed_p = 0; - /* Set the row being updated. This is important to let xterm.c - know what line height values are in effect. */ - updated_row = desired_row; - /* A row can be completely invisible in case a desired matrix was built with a vscroll and then make_cursor_line_fully_visible shifts 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) if (!desired_row->full_width_p && w->left_margin_cols > 0) { changed_p = 1; - update_marginal_area (w, LEFT_MARGIN_AREA, vpos); + update_marginal_area (w, desired_row, LEFT_MARGIN_AREA, vpos); /* Setting this flag will ensure the vertical border, if any, between this window and the one on its left will be redrawn. This is necessary because updating the left @@ -3812,7 +3797,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) } /* Update the display of the text area. */ - if (update_text_area (w, vpos)) + if (update_text_area (w, desired_row, vpos)) { changed_p = 1; if (current_row->mouse_face_p) @@ -3823,7 +3808,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) if (!desired_row->full_width_p && w->right_margin_cols > 0) { changed_p = 1; - update_marginal_area (w, RIGHT_MARGIN_AREA, vpos); + update_marginal_area (w, desired_row, RIGHT_MARGIN_AREA, vpos); } /* Draw truncation marks etc. */ @@ -3842,7 +3827,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p) /* Update current_row from desired_row. */ make_current (w->desired_matrix, w->current_matrix, vpos); - updated_row = NULL; return changed_p; } diff --git a/src/xdisp.c b/src/xdisp.c index ea1cd7dd2bc..a029f53305c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25763,12 +25763,12 @@ x_produce_glyphs (struct it *it) /* EXPORT for RIF: Output LEN glyphs starting at START at the nominal cursor position. - Advance the nominal cursor over the text. The global variable - updated_row is the glyph row being updated, and updated_area is the - area of that row being updated. */ + Advance the nominal cursor over the text. UPDATED_ROW is the glyph row + being updated, and UPDATED_AREA is the area of that row being updated. */ void -x_write_glyphs (struct window *w, struct glyph *start, int len) +x_write_glyphs (struct window *w, struct glyph_row *updated_row, + struct glyph *start, enum glyph_row_area updated_area, int len) { int x, hpos, chpos = w->phys_cursor.hpos; @@ -25811,7 +25811,8 @@ x_write_glyphs (struct window *w, struct glyph *start, int len) Insert LEN glyphs from START at the nominal cursor position. */ void -x_insert_glyphs (struct window *w, struct glyph *start, int len) +x_insert_glyphs (struct window *w, struct glyph_row *updated_row, + struct glyph *start, enum glyph_row_area updated_area, int len) { struct frame *f; int line_height, shift_by_width, shifted_region_width; @@ -25863,11 +25864,12 @@ x_insert_glyphs (struct window *w, struct glyph *start, int len) (inclusive) to pixel column TO_X (exclusive). The idea is that everything from TO_X onward is already erased. - TO_X is a pixel position relative to updated_area of currently + TO_X is a pixel position relative to UPDATED_AREA of currently updated window W. TO_X == -1 means clear to the end of this area. */ void -x_clear_end_of_line (struct window *w, int to_x) +x_clear_end_of_line (struct window *w, struct glyph_row *updated_row, + enum glyph_row_area updated_area, int to_x) { struct frame *f; int max_x, min_y, max_y; -- cgit v1.2.1 From 9997ec56be8bf3fb32ac246e5b654ed735ee2c52 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 23 Aug 2013 08:03:25 +0400 Subject: Minor cleanup for redisplay interface and few related functions. * frame.h (enum text_cursor_kinds): Move from here... * dispextern.h (enum text_cursor_kinds): ...to here. (toplevel): Drop unnecessary declarations. (struct redisplay_interface): Use bool and enum text_cursor_kinds in update_window_end_hook and draw_window_cursor functions. (display_and_set_cursor, x_update_cursor): Adjust prototypes. * nsterm.m (ns_update_window_end, ns_draw_window_cursor): * w32term.c (x_update_window_end,w32_draw_window_cursor): * xterm.c (x_update_window_end, x_draw_window_cursor): * xdisp.c (display_and_set_cursor, update_window_cursor) (update_cursor_in_window_tree, x_update_cursor): Use bool and enum text_cursor_kinds where appropriate. --- src/ChangeLog | 16 ++++++++++++++++ src/dispextern.h | 38 ++++++++++++++++++-------------------- src/frame.h | 10 ---------- src/nsterm.m | 8 ++++---- src/w32term.c | 9 ++++----- src/xdisp.c | 8 ++++---- src/xterm.c | 9 +++++---- 7 files changed, 51 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index aadaae24e98..e252e4a2f4f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2013-08-23 Dmitry Antipov + + Minor cleanup for redisplay interface and few related functions. + * frame.h (enum text_cursor_kinds): Move from here... + * dispextern.h (enum text_cursor_kinds): ...to here. + (toplevel): Drop unnecessary declarations. + (struct redisplay_interface): Use bool and enum text_cursor_kinds + in update_window_end_hook and draw_window_cursor functions. + (display_and_set_cursor, x_update_cursor): Adjust prototypes. + * nsterm.m (ns_update_window_end, ns_draw_window_cursor): + * w32term.c (x_update_window_end,w32_draw_window_cursor): + * xterm.c (x_update_window_end, x_draw_window_cursor): + * xdisp.c (display_and_set_cursor, update_window_cursor) + (update_cursor_in_window_tree, x_update_cursor): Use bool and + enum text_cursor_kinds where appropriate. + 2013-08-23 Dmitry Antipov Redesign redisplay interface to drop updated_row and updated_area. diff --git a/src/dispextern.h b/src/dispextern.h index eb5b4bd195c..6e1d85de924 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -95,18 +95,17 @@ typedef int Cursor; #define NativeRectangle int #endif -/* Structure forward declarations. Some are here because function - prototypes below reference structure types before their definition - in this file. Some are here because not every file including - dispextern.h also includes frame.h and windows.h. */ - -struct glyph; -struct glyph_row; -struct glyph_matrix; -struct glyph_pool; -struct frame; -struct window; +/* Text cursor types. */ +enum text_cursor_kinds +{ + DEFAULT_CURSOR = -2, + NO_CURSOR = -1, + FILLED_BOX_CURSOR, + HOLLOW_BOX_CURSOR, + BAR_CURSOR, + HBAR_CURSOR +}; /* Values returned from coordinates_in_window. */ @@ -2739,8 +2738,8 @@ struct redisplay_interface MOUSE_FACE_OVERWRITTEN_P non-zero means that some lines in W that contained glyphs in mouse-face were overwritten, so we have to update the mouse highlight. */ - void (*update_window_end_hook) (struct window *w, int cursor_on_p, - int mouse_face_overwritten_p); + void (*update_window_end_hook) (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p); /* Move cursor to row/column position VPOS/HPOS, pixel coordinates Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y @@ -2799,10 +2798,10 @@ struct redisplay_interface 0, don't draw cursor. If ACTIVE_P is 1, system caret should track this cursor (when applicable). */ void (*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); + struct glyph_row *glyph_row, + int x, int y, + enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p); /* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */ void (*draw_vertical_window_border) (struct window *w, @@ -3195,13 +3194,12 @@ extern void draw_phys_cursor_glyph (struct window *, extern void get_phys_cursor_geometry (struct window *, struct glyph_row *, struct glyph *, int *, int *, int *); extern void erase_phys_cursor (struct window *); -extern void display_and_set_cursor (struct window *, - int, int, int, int, int); +extern void display_and_set_cursor (struct window *, bool, int, int, int, int); extern void set_output_cursor (struct cursor_pos *); extern void x_cursor_to (struct window *, int, int, int, int); -extern void x_update_cursor (struct frame *, int); +extern void x_update_cursor (struct frame *, bool); extern void x_clear_cursor (struct window *); extern void x_draw_vertical_border (struct window *w); 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 vertical_scroll_bar_right }; -enum text_cursor_kinds -{ - DEFAULT_CURSOR = -2, - NO_CURSOR = -1, - FILLED_BOX_CURSOR, - HOLLOW_BOX_CURSOR, - BAR_CURSOR, - HBAR_CURSOR -}; - enum fullscreen_type { FULLSCREEN_NONE, 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) static void -ns_update_window_end (struct window *w, int cursor_on_p, - int mouse_face_overwritten_p) +ns_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) /* -------------------------------------------------------------------------- Finished a grouped sequence of drawing calls 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, static void ns_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) + int x, int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) /* -------------------------------------------------------------------------- External call (RIF): draw cursor. Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. 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; int w32_message_fd = -1; #endif /* CYGWIN */ -static void x_update_window_end (struct window *, int, int); static void w32_handle_tool_bar_click (struct frame *, struct input_event *); static void w32_define_cursor (Window, Cursor); @@ -676,8 +675,8 @@ w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1) here. */ static void -x_update_window_end (struct window *w, int cursor_on_p, - int mouse_face_overwritten_p) +x_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) { Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); @@ -5300,8 +5299,8 @@ w32_clear_frame_area (struct frame *f, int x, int y, int width, int height) static void w32_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) + int x, int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) { if (on_p) { diff --git a/src/xdisp.c b/src/xdisp.c index a029f53305c..53fc6d85647 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -26465,7 +26465,7 @@ erase_phys_cursor (struct window *w) where to put the cursor is specified by HPOS, VPOS, X and Y. */ void -display_and_set_cursor (struct window *w, int on, +display_and_set_cursor (struct window *w, bool on, int hpos, int vpos, int x, int y) { struct frame *f = XFRAME (w->frame); @@ -26549,7 +26549,7 @@ display_and_set_cursor (struct window *w, int on, of ON. */ static void -update_window_cursor (struct window *w, int on) +update_window_cursor (struct window *w, bool on) { /* Don't update cursor in windows whose frame is in the process of being deleted. */ @@ -26585,7 +26585,7 @@ update_window_cursor (struct window *w, int on) in the window tree rooted at W. */ static void -update_cursor_in_window_tree (struct window *w, int on_p) +update_cursor_in_window_tree (struct window *w, bool on_p) { while (w) { @@ -26604,7 +26604,7 @@ update_cursor_in_window_tree (struct window *w, int on_p) Don't change the cursor's position. */ void -x_update_cursor (struct frame *f, int on_p) +x_update_cursor (struct frame *f, bool on_p) { update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); } 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); static void x_raise_frame (struct frame *); static void x_lower_frame (struct frame *); static const XColor *x_color_cells (Display *, int *); -static void x_update_window_end (struct window *, int, int); - static int x_io_error_quitter (Display *); static struct terminal *x_create_terminal (struct x_display_info *); void x_delete_terminal (struct terminal *); @@ -612,7 +610,8 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1) here. */ static void -x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p) +x_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) { Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); @@ -7372,7 +7371,9 @@ x_clear_frame_area (struct frame *f, int x, int y, int width, int height) /* RIF: Draw cursor on window W. */ static void -x_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) +x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, + int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) { struct frame *f = XFRAME (WINDOW_FRAME (w)); -- cgit v1.2.1 From 6b729d1685255d309d6de0ac1c973527ec691f8b Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 23 Aug 2013 08:17:04 +0400 Subject: * window.c (struct save_window_data): Fix typo. --- src/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/window.c b/src/window.c index b295f748bfd..023dc485d7f 100644 --- a/src/window.c +++ b/src/window.c @@ -5408,7 +5408,7 @@ struct save_window_data Lisp_Object saved_windows; /* All fields above are traced by the GC. - From `fame-cols' down, the fields are ignored by the GC. */ + From `frame-cols' down, the fields are ignored by the GC. */ int frame_cols, frame_lines, frame_menu_bar_lines; int frame_tool_bar_lines; -- cgit v1.2.1 From 6c6014d4cc93c33a964acd246e792e1bd73f910d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 23 Aug 2013 17:25:39 +0300 Subject: Fix bug #15155 with ignoring face remapping for strings from prefix properties. src/xdisp.c (handle_face_prop): If the default face was remapped use the remapped face for strings from prefix properties. --- src/ChangeLog | 5 +++++ src/xdisp.c | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index e252e4a2f4f..bee477c745a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2013-08-23 Eli Zaretskii + + * xdisp.c (handle_face_prop): If the default face was remapped use + the remapped face for strings from prefix properties. (Bug#15155) + 2013-08-23 Dmitry Antipov Minor cleanup for redisplay interface and few related functions. diff --git a/src/xdisp.c b/src/xdisp.c index 53fc6d85647..ca130473c0f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3912,10 +3912,14 @@ handle_face_prop (struct it *it) /* For strings from a `display' property, use the face at IT's current buffer position as the base face to merge with, so that overlay strings appear in the same face as - surrounding text, unless they specify their own - faces. */ + surrounding text, unless they specify their own faces. + For strings from wrap-prefix and line-prefix properties, + use the default face, possibly remapped via + Vface_remapping_alist. */ base_face_id = it->string_from_prefix_prop_p - ? DEFAULT_FACE_ID + ? (!NILP (Vface_remapping_alist) + ? lookup_basic_face (it->f, DEFAULT_FACE_ID) + : DEFAULT_FACE_ID) : underlying_face_id (it); } -- cgit v1.2.1 From c365c3558065fca4c11c3f46605d1045763485ab Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 23 Aug 2013 10:57:07 -0700 Subject: Don't let very long directory names overrun the stack. Fix some related minor problems involving "//", vfork. * callproc.c (encode_current_directory): New function. (call_process): Don't append "/"; not needed. * fileio.c (file_name_as_directory_slop): New constant. (file_name_as_directory): Allow SRC to be longer than SRCLEN; this can save the caller having to alloca. (Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name): Use SAFE_ALLOCA, not alloca. (directory_file_name, Fexpand_file_name): Leave leading "//" alone, since it can be special even on POSIX platforms. * callproc.c (call_process): * process.c (Fformat_network_address): * sysdep.c (sys_subshell): Use encode_current_directory rather than rolling our own. (create_process): No need to encode directory; caller does that now. * process.h (encode_current_directory): New decl. * sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers. Rework to avoid 'goto xyzzy;'. --- src/ChangeLog | 22 +++++++++++ src/callproc.c | 59 ++++++++++++++++++----------- src/fileio.c | 118 ++++++++++++++++++++++++++++----------------------------- src/process.c | 32 ++++------------ src/process.h | 1 + src/sysdep.c | 48 ++++++++--------------- 6 files changed, 142 insertions(+), 138 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index bee477c745a..73fdb0221ce 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,25 @@ +2013-08-23 Paul Eggert + + Don't let very long directory names overrun the stack. + Fix some related minor problems involving "//", vfork. + * callproc.c (encode_current_directory): New function. + (call_process): Don't append "/"; not needed. + * fileio.c (file_name_as_directory_slop): New constant. + (file_name_as_directory): Allow SRC to be longer than SRCLEN; + this can save the caller having to alloca. + (Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name): + Use SAFE_ALLOCA, not alloca. + (directory_file_name, Fexpand_file_name): Leave leading "//" + alone, since it can be special even on POSIX platforms. + * callproc.c (call_process): + * process.c (Fformat_network_address): + * sysdep.c (sys_subshell): + Use encode_current_directory rather than rolling our own. + (create_process): No need to encode directory; caller does that now. + * process.h (encode_current_directory): New decl. + * sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers. + Rework to avoid 'goto xyzzy;'. + 2013-08-23 Eli Zaretskii * xdisp.c (handle_face_prop): If the default face was remapped use diff --git a/src/callproc.c b/src/callproc.c index fca4216b5f7..d4b4a26ec3a 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -123,6 +123,37 @@ unblock_child_signal (void) pthread_sigmask (SIG_SETMASK, &empty_mask, 0); } +/* Return the current buffer's working directory, or the home + directory if it's unreachable, as a string suitable for a system call. + Signal an error if the result would not be an accessible directory. */ + +Lisp_Object +encode_current_directory (void) +{ + Lisp_Object dir; + struct gcpro gcpro1; + + dir = BVAR (current_buffer, directory); + GCPRO1 (dir); + + dir = Funhandled_file_name_directory (dir); + + /* If the file name handler says that dir is unreachable, use + a sensible default. */ + if (NILP (dir)) + dir = build_string ("~"); + + dir = expand_and_dir_to_file (dir, Qnil); + + if (STRING_MULTIBYTE (dir)) + dir = ENCODE_FILE (dir); + if (! file_accessible_directory_p (SSDATA (dir))) + report_file_error ("Setting current directory", + BVAR (current_buffer, directory)); + + RETURN_UNGCPRO (dir); +} + /* If P is reapable, record it as a deleted process and kill it. Do this in a critical section. Unless PID is wedged it will be reaped on receipt of the first SIGCHLD after the critical section. */ @@ -408,24 +439,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, { struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; - current_dir = BVAR (current_buffer, directory); + current_dir = encode_current_directory (); GCPRO4 (buffer, current_dir, error_file, output_file); - current_dir = Funhandled_file_name_directory (current_dir); - if (NILP (current_dir)) - /* If the file name handler says that current_dir is unreachable, use - a sensible default. */ - current_dir = build_string ("~/"); - current_dir = expand_and_dir_to_file (current_dir, Qnil); - current_dir = Ffile_name_as_directory (current_dir); - - if (NILP (Ffile_accessible_directory_p (current_dir))) - report_file_error ("Setting current directory", - BVAR (current_buffer, directory)); - - if (STRING_MULTIBYTE (current_dir)) - current_dir = ENCODE_FILE (current_dir); if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) error_file = ENCODE_FILE (error_file); if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) @@ -1176,23 +1193,21 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, static variables as if the superior had done alloca and will be cleaned up in the usual way. */ { - register char *temp; - size_t i; /* size_t, because ptrdiff_t might overflow here! */ + char *temp; + ptrdiff_t i; i = SBYTES (current_dir); #ifdef MSDOS /* MSDOS must have all environment variables malloc'ed, because low-level libc functions that launch subsidiary processes rely on that. */ - pwd_var = xmalloc (i + 6); + pwd_var = xmalloc (i + 5); #else - pwd_var = alloca (i + 6); + pwd_var = alloca (i + 5); #endif temp = pwd_var + 4; memcpy (pwd_var, "PWD=", 4); - memcpy (temp, SDATA (current_dir), i); - if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP; - temp[i] = 0; + strcpy (temp, SSDATA (current_dir)); #ifndef DOS_NT /* We can't signal an Elisp error here; we're in a vfork. Since 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. */) return Ffile_name_directory (filename); } +/* Maximum number of bytes that DST will be longer than SRC + in file_name_as_directory. This occurs when SRCLEN == 0. */ +enum { file_name_as_directory_slop = 2 }; + /* Convert from file name SRC of length SRCLEN to directory name in DST. MULTIBYTE non-zero means the file name in SRC is a multibyte 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, return 2; } - strcpy (dst, src); - + memcpy (dst, src, srclen); if (!IS_DIRECTORY_SEP (dst[srclen - 1])) - { - dst[srclen] = DIRECTORY_SEP; - dst[srclen + 1] = '\0'; - srclen++; - } + dst[srclen++] = DIRECTORY_SEP; + dst[srclen] = 0; #ifdef DOS_NT dostounix_filename (dst, multibyte); #endif @@ -547,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */) { char *buf; ptrdiff_t length; - Lisp_Object handler; + Lisp_Object handler, val; + USE_SAFE_ALLOCA; CHECK_STRING (file); if (NILP (file)) @@ -569,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */) if (!NILP (Vw32_downcase_file_names)) file = Fdowncase (file); #endif - buf = alloca (SBYTES (file) + 10); + buf = SAFE_ALLOCA (SBYTES (file) + file_name_as_directory_slop + 1); length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), STRING_MULTIBYTE (file)); - return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); + val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); + SAFE_FREE (); + return val; } /* Convert from directory name SRC of length SRCLEN to file name in @@ -584,18 +587,17 @@ static ptrdiff_t directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) { /* Process as Unix format: just remove any final slash. - But leave "/" unchanged; do not change it to "". */ - strcpy (dst, src); - if (srclen > 1 - && IS_DIRECTORY_SEP (dst[srclen - 1]) + But leave "/" and "//" unchanged. */ + while (srclen > 1 #ifdef DOS_NT - && !IS_ANY_SEP (dst[srclen - 2]) + && !IS_ANY_SEP (src[srclen - 2]) #endif - ) - { - dst[srclen - 1] = 0; - srclen--; - } + && IS_DIRECTORY_SEP (src[srclen - 1]) + && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0]))) + srclen--; + + memcpy (dst, src, srclen); + dst[srclen] = 0; #ifdef DOS_NT dostounix_filename (dst, multibyte); #endif @@ -613,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */) { char *buf; ptrdiff_t length; - Lisp_Object handler; + Lisp_Object handler, val; + USE_SAFE_ALLOCA; CHECK_STRING (directory); @@ -636,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */) if (!NILP (Vw32_downcase_file_names)) directory = Fdowncase (directory); #endif - buf = alloca (SBYTES (directory) + 20); + buf = SAFE_ALLOCA (SBYTES (directory) + 1); length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), STRING_MULTIBYTE (directory)); - return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); + val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); + SAFE_FREE (); + return val; } static const char make_temp_name_tbl[64] = @@ -837,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) Lisp_Object handler, result, handled_name; bool multibyte; Lisp_Object hdir; + USE_SAFE_ALLOCA; CHECK_STRING (name); @@ -1011,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)))) lose = 1; - /* We want to replace multiple `/' in a row with a single - slash. */ - else if (p > nm - && IS_DIRECTORY_SEP (p[0]) - && IS_DIRECTORY_SEP (p[1])) + /* Replace multiple slashes with a single one, except + leave leading "//" alone. */ + else if (IS_DIRECTORY_SEP (p[0]) + && IS_DIRECTORY_SEP (p[1]) + && (p != nm || IS_DIRECTORY_SEP (p[2]))) lose = 1; p++; } @@ -1098,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) else /* ~user/filename */ { char *o, *p; - for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); - o = alloca (p - nm + 1); + for (p = nm; *p && !IS_DIRECTORY_SEP (*p); p++) + continue; + o = SAFE_ALLOCA (p - nm + 1); memcpy (o, nm, p - nm); - o [p - nm] = 0; + o[p - nm] = 0; block_input (); pw = getpwnam (o + 1); @@ -1217,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (!IS_DIRECTORY_SEP (nm[0])) { ptrdiff_t newlen = strlen (newdir); - char *tmp = alloca (newlen + strlen (nm) + 2); + char *tmp = alloca (newlen + file_name_as_directory_slop + + strlen (nm) + 1); file_name_as_directory (tmp, newdir, newlen, multibyte); strcat (tmp, nm); nm = tmp; @@ -1271,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (newdir) { - /* Get rid of any slash at the end of newdir, unless newdir is - just / or // (an incomplete UNC name). */ + /* Ignore any slash at the end of newdir, unless newdir is + just "/" or "//". */ length = strlen (newdir); - tlen = length + 1; - if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) -#ifdef WINDOWSNT - && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) -#endif - ) - { - char *temp = alloca (length); - memcpy (temp, newdir, length - 1); - temp[length - 1] = 0; - length--; - newdir = temp; - } + while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) + && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0]))) + length--; } else - { - length = 0; - tlen = 0; - } + length = 0; /* Now concatenate the directory and name to new space in the stack frame. */ - tlen += strlen (nm) + 1; + tlen = length + file_name_as_directory_slop + strlen (nm) + 1; #ifdef DOS_NT /* Reserve space for drive specifier and escape prefix, since either or both may need to be inserted. (The Microsoft x86 compiler @@ -1303,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) target = alloca (tlen + 4); target += 4; #else /* not DOS_NT */ - target = alloca (tlen); + target = SAFE_ALLOCA (tlen); #endif /* not DOS_NT */ *target = 0; @@ -1320,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */) if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) && newdir[1] == '\0')) #endif - strcpy (target, newdir); + { + memcpy (target, newdir, length); + target[length] = 0; + } } else file_name_as_directory (target, newdir, length, multibyte); @@ -1380,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */) ++o; p += 3; } - else if (p > target && IS_DIRECTORY_SEP (p[1])) - /* Collapse multiple `/' in a row. */ + else if (IS_DIRECTORY_SEP (p[1]) + && (p != target || IS_DIRECTORY_SEP (p[2]))) + /* Collapse multiple "/", except leave leading "//" alone. */ p++; else { @@ -1429,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */) { handled_name = call3 (handler, Qexpand_file_name, result, default_directory); - if (STRINGP (handled_name)) - return handled_name; - error ("Invalid handler in `file-name-handler-alist'"); + if (! STRINGP (handled_name)) + error ("Invalid handler in `file-name-handler-alist'"); + result = handled_name; } + SAFE_FREE (); return result; } diff --git a/src/process.c b/src/process.c index 75cb590fc57..ea1129ffbb8 100644 --- a/src/process.c +++ b/src/process.c @@ -1408,22 +1408,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) function. The argument list is protected by the caller, so all we really have to worry about is buffer. */ { - struct gcpro gcpro1, gcpro2; - - current_dir = BVAR (current_buffer, directory); - - GCPRO2 (buffer, current_dir); - - current_dir = Funhandled_file_name_directory (current_dir); - if (NILP (current_dir)) - /* If the file name handler says that current_dir is unreachable, use - a sensible default. */ - current_dir = build_string ("~/"); - current_dir = expand_and_dir_to_file (current_dir, Qnil); - if (NILP (Ffile_accessible_directory_p (current_dir))) - report_file_error ("Setting current directory", - BVAR (current_buffer, directory)); - + struct gcpro gcpro1; + GCPRO1 (buffer); + current_dir = encode_current_directory (); UNGCPRO; } @@ -1670,7 +1657,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; Lisp_Object lisp_pty_name = Qnil; - Lisp_Object encoded_current_dir; inchannel = outchannel = -1; @@ -1735,15 +1721,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* This may signal an error. */ setup_process_coding_systems (process); - encoded_current_dir = ENCODE_FILE (current_dir); - block_input (); block_child_signal (); #ifndef WINDOWSNT /* vfork, and prevent local vars from being clobbered by the vfork. */ { - Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; + Lisp_Object volatile current_dir_volatile = current_dir; Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; char **volatile new_argv_volatile = new_argv; int volatile forkin_volatile = forkin; @@ -1752,7 +1736,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) pid = vfork (); - encoded_current_dir = encoded_current_dir_volatile; + current_dir = current_dir_volatile; lisp_pty_name = lisp_pty_name_volatile; new_argv = new_argv_volatile; forkin = forkin_volatile; @@ -1864,11 +1848,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (pty_flag) child_setup_tty (xforkout); #ifdef WINDOWSNT - pid = child_setup (xforkin, xforkout, xforkout, - new_argv, 1, encoded_current_dir); + pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); #else /* not WINDOWSNT */ - child_setup (xforkin, xforkout, xforkout, - new_argv, 1, encoded_current_dir); + child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); #endif /* not WINDOWSNT */ } diff --git a/src/process.h b/src/process.h index b312f7f2425..6aff95686a2 100644 --- a/src/process.h +++ b/src/process.h @@ -218,6 +218,7 @@ enum extern void block_child_signal (void); extern void unblock_child_signal (void); +extern Lisp_Object encode_current_directory (void); extern void record_kill_process (struct Lisp_Process *, Lisp_Object); /* Defined in sysdep.c. */ diff --git a/src/sysdep.c b/src/sysdep.c index 78e3d908cfe..c6d5f9942ab 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -471,10 +471,20 @@ sys_subshell (void) pid_t pid; int status; struct save_signal saved_handlers[5]; - Lisp_Object dir; - unsigned char *volatile str_volatile = 0; - unsigned char *str; - int len; + char *str = SSDATA (encode_current_directory ()); + +#ifdef DOS_NT + pid = 0; +#else + { + char *volatile str_volatile = str; + pid = vfork (); + str = str_volatile; + } +#endif + + if (pid < 0) + error ("Can't spawn subshell"); saved_handlers[0].code = SIGINT; saved_handlers[1].code = SIGQUIT; @@ -486,31 +496,8 @@ sys_subshell (void) saved_handlers[3].code = 0; #endif - /* Mentioning current_buffer->buffer would mean including buffer.h, - which somehow wedges the hp compiler. So instead... */ - - dir = intern ("default-directory"); - if (NILP (Fboundp (dir))) - goto xyzzy; - dir = Fsymbol_value (dir); - if (!STRINGP (dir)) - goto xyzzy; - - dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil); - str_volatile = str = alloca (SCHARS (dir) + 2); - len = SCHARS (dir); - memcpy (str, SDATA (dir), len); - if (str[len - 1] != '/') str[len++] = '/'; - str[len] = 0; - xyzzy: - #ifdef DOS_NT - pid = 0; save_signal_handlers (saved_handlers); -#else - pid = vfork (); - if (pid == -1) - error ("Can't spawn subshell"); #endif if (pid == 0) @@ -528,11 +515,10 @@ sys_subshell (void) sh = "sh"; /* Use our buffer's default directory for the subshell. */ - str = str_volatile; - if (str && chdir ((char *) str) != 0) + if (chdir (str) != 0) { #ifndef DOS_NT - emacs_perror ((char *) str); + emacs_perror (str); _exit (EXIT_CANCELED); #endif } @@ -546,8 +532,6 @@ sys_subshell (void) if (epwd) { strcpy (old_pwd, epwd); - if (str[len - 1] == '/') - str[len - 1] = '\0'; setenv ("PWD", str, 1); } st = system (sh); -- cgit v1.2.1 From 9c05bccfb9cd29ab66b5c46643467671315a0f29 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 23 Aug 2013 19:23:34 -0700 Subject: System-dependent integer overflow fixes. * process.c (Fset_process_window_size): Signal an error if the window size is outside the range supported by the lower level. * sysdep.c (set_window_size): Return negative on error, nonnegative on success, rather than -1, 0, 1 on not in system, failure, success. This is simpler. Caller changed. (serial_configure): Remove unnecessary initialization of local. (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory size fits in unsigned long; this isn't true on some 32-bit hosts. Avoid buffer overrun if some future version of /proc/meminfo has a variable name longer than 20 bytes. (system_process_attributes) [__FreeBSD__]: Don't assume hw.availpages fits in 'int'. --- src/ChangeLog | 16 ++++++++++++++++ src/process.c | 13 ++++++++----- src/sysdep.c | 55 +++++++++++++++++++++++++++++++------------------------ 3 files changed, 55 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 73fdb0221ce..3eccf6ff557 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2013-08-24 Paul Eggert + + System-dependent integer overflow fixes. + * process.c (Fset_process_window_size): Signal an error if + the window size is outside the range supported by the lower level. + * sysdep.c (set_window_size): Return negative on error, + nonnegative on success, rather than -1, 0, 1 on not in system, + failure, success. This is simpler. Caller changed. + (serial_configure): Remove unnecessary initialization of local. + (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory + size fits in unsigned long; this isn't true on some 32-bit hosts. + Avoid buffer overrun if some future version of /proc/meminfo has a + variable name longer than 20 bytes. + (system_process_attributes) [__FreeBSD__]: + Don't assume hw.availpages fits in 'int'. + 2013-08-23 Paul Eggert Don't let very long directory names overrun the stack. diff --git a/src/process.c b/src/process.c index ea1129ffbb8..c5e691bf602 100644 --- a/src/process.c +++ b/src/process.c @@ -1140,15 +1140,18 @@ See `set-process-sentinel' for more info on sentinels. */) DEFUN ("set-process-window-size", Fset_process_window_size, Sset_process_window_size, 3, 3, 0, doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) - (register Lisp_Object process, Lisp_Object height, Lisp_Object width) + (Lisp_Object process, Lisp_Object height, Lisp_Object width) { CHECK_PROCESS (process); - CHECK_RANGED_INTEGER (height, 0, INT_MAX); - CHECK_RANGED_INTEGER (width, 0, INT_MAX); + + /* All known platforms store window sizes as 'unsigned short'. */ + CHECK_RANGED_INTEGER (height, 0, USHRT_MAX); + CHECK_RANGED_INTEGER (width, 0, USHRT_MAX); if (XPROCESS (process)->infd < 0 - || set_window_size (XPROCESS (process)->infd, - XINT (height), XINT (width)) <= 0) + || (set_window_size (XPROCESS (process)->infd, + XINT (height), XINT (width)) + < 0)) return Qnil; else return Qt; diff --git a/src/sysdep.c b/src/sysdep.c index c6d5f9942ab..0d732526528 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1170,7 +1170,8 @@ get_tty_size (int fd, int *widthp, int *heightp) } /* Set the logical window size associated with descriptor FD - to HEIGHT and WIDTH. This is used mainly with ptys. */ + to HEIGHT and WIDTH. This is used mainly with ptys. + Return a negative value on failure. */ int set_window_size (int fd, int height, int width) @@ -1182,10 +1183,7 @@ set_window_size (int fd, int height, int width) size.ws_row = height; size.ws_col = width; - if (ioctl (fd, TIOCSWINSZ, &size) == -1) - return 0; /* error */ - else - return 1; + return ioctl (fd, TIOCSWINSZ, &size); #else #ifdef TIOCSSIZE @@ -1195,10 +1193,7 @@ set_window_size (int fd, int height, int width) size.ts_lines = height; size.ts_cols = width; - if (ioctl (fd, TIOCGSIZE, &size) == -1) - return 0; - else - return 1; + return ioctl (fd, TIOCGSIZE, &size); #else return -1; #endif /* not SunOS-style */ @@ -2459,7 +2454,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object childp2 = Qnil; Lisp_Object tem = Qnil; struct termios attr; - int err = -1; + int err; char summary[4] = "???"; /* This usually becomes "8N1". */ childp2 = Fcopy_sequence (p->childp); @@ -2826,29 +2821,41 @@ procfs_ttyname (int rdev) return build_string (name); } -static unsigned long +static uintmax_t procfs_get_total_memory (void) { FILE *fmem; - unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ + uintmax_t retval = 2 * 1024 * 1024; /* default: 2 GiB */ + int c; block_input (); fmem = emacs_fopen ("/proc/meminfo", "r"); if (fmem) { - unsigned long entry_value; - char entry_name[20]; /* the longest I saw is 13+1 */ + uintmax_t entry_value; + bool done; + + do + switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value)) + { + case 1: + retval = entry_value; + done = 1; + break; + + case 0: + while ((c = getc (fmem)) != EOF && c != '\n') + continue; + done = c == EOF; + break; + + default: + done = 1; + break; + } + while (!done); - while (!feof (fmem) && !ferror (fmem)) - { - if (fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) >= 2 - && strcmp (entry_name, "MemTotal:") == 0) - { - retval = entry_value; - break; - } - } fclose (fmem); } unblock_input (); @@ -3249,7 +3256,7 @@ system_process_attributes (Lisp_Object pid) { int proc_id; int pagesize = getpagesize (); - int npages; + unsigned long npages; int fscale; struct passwd *pw; struct group *gr; -- cgit v1.2.1 From 6e1b469ee2c44797e9f7922366d069e0f924cc63 Mon Sep 17 00:00:00 2001 From: Jan Djärv Date: Sat, 24 Aug 2013 10:43:36 +0200 Subject: * gtkutil.c (x_wm_set_size_hint): Don't set hints when maximized or fullscreen. Fixes: debbugs:14627 --- src/ChangeLog | 5 +++++ src/gtkutil.c | 11 +++++++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 3eccf6ff557..8e5eedd445c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2013-08-24 Jan Djärv + + * gtkutil.c (x_wm_set_size_hint): Don't set hints when maximized + or fullscreen (Bug#14627). + 2013-08-24 Paul Eggert System-dependent integer overflow fixes. 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) int base_width, base_height; int min_rows = 0, min_cols = 0; int win_gravity = f->win_gravity; + Lisp_Object fs_state, frame; /* Don't set size hints during initialization; that apparently leads 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) if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f)) return; + XSETFRAME (frame, f); + fs_state = Fframe_parameter (frame, Qfullscreen); + if (EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth)) + { + /* Don't set hints when maximized or fullscreen. Apparently KWin and + Gtk3 don't get along and the frame shrinks (!). + */ + return; + } + if (flags) { memset (&size_hints, 0, sizeof (size_hints)); -- cgit v1.2.1 From b34454d067efe26983f32ee6dc725d5122de58f4 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 24 Aug 2013 13:15:01 +0300 Subject: Fix bug #15176 with setting directory times on MS-Windows. src/w32.c (fdutimens): Call 'utime', which is implemented on w32.c to handle directories, rather than '_utime' which doesn't. --- src/ChangeLog | 6 ++++++ src/w32.c | 29 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 8e5eedd445c..2bb41071fd6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2013-08-24 Eli Zaretskii + + * w32.c (fdutimens): Call 'utime', which is implemented on w32.c + to handle directories, rather than '_utime' which doesn't. + (Bug#15176) + 2013-08-24 Jan Djärv * gtkutil.c (x_wm_set_size_hint): Don't set hints when maximized 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) int fdutimens (int fd, char const *file, struct timespec const timespec[2]) { - struct _utimbuf ut; - if (!timespec) { errno = ENOSYS; @@ -2515,12 +2513,28 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2]) errno = EBADF; return -1; } - ut.actime = timespec[0].tv_sec; - ut.modtime = timespec[1].tv_sec; + /* _futime's prototype defines 2nd arg as having the type 'struct + _utimbuf', while utime needs to accept 'struct utimbuf' for + compatibility with Posix. So we need to use 2 different (but + equivalent) types to avoid compiler warnings, sigh. */ if (fd >= 0) - return _futime (fd, &ut); + { + struct _utimbuf _ut; + + _ut.actime = timespec[0].tv_sec; + _ut.modtime = timespec[1].tv_sec; + return _futime (fd, &_ut); + } else - return _utime (file, &ut); + { + struct utimbuf ut; + + ut.actime = timespec[0].tv_sec; + ut.modtime = timespec[1].tv_sec; + /* Call 'utime', which is implemented below, not the MS library + function, which fails on directories. */ + return utime (file, &ut); + } } @@ -4501,6 +4515,9 @@ fstat (int desc, struct stat * buf) return 0; } +/* A version of 'utime' which handles directories as well as + files. */ + int utime (const char *name, struct utimbuf *times) { -- cgit v1.2.1 From 11f20add707674b98227ca6f26d0e7f10dbbfac9 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 24 Aug 2013 15:59:13 +0300 Subject: Fix bug #15175 with cursor on boxed characters from display tables. src/xdisp.c (get_next_display_element): Don't apply to characters from a display vector the logic of setting it->end_of_box_run_p suitable for characters from a buffer. --- src/ChangeLog | 4 ++++ src/xdisp.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 2bb41071fd6..70d722a02a4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,9 @@ 2013-08-24 Eli Zaretskii + * xdisp.c (get_next_display_element): Don't apply to characters + from a display vector the logic of setting it->end_of_box_run_p + suitable for characters from a buffer. (Bug#15175) + * w32.c (fdutimens): Call 'utime', which is implemented on w32.c to handle directories, rather than '_utime' which doesn't. (Bug#15176) diff --git a/src/xdisp.c b/src/xdisp.c index ca130473c0f..fecf22af1e9 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -7050,7 +7050,7 @@ get_next_display_element (struct it *it) } } } - else + else if (it->method != GET_FROM_DISPLAY_VECTOR) { int face_id = face_after_it_pos (it); it->end_of_box_run_p -- cgit v1.2.1 From 6dc695d1e31fe51e6f15993d998540875b3ae881 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 24 Aug 2013 18:21:05 +0300 Subject: Add commentary for the last commit. --- src/xdisp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/xdisp.c b/src/xdisp.c index fecf22af1e9..3ff4603b727 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -7050,6 +7050,8 @@ get_next_display_element (struct it *it) } } } + /* next_element_from_display_vector sets this flag according to + faces of the display vector glyphs, see there. */ else if (it->method != GET_FROM_DISPLAY_VECTOR) { int face_id = face_after_it_pos (it); -- cgit v1.2.1