diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.gdbinit | 10 | ||||
-rw-r--r-- | src/ChangeLog | 1202 | ||||
-rw-r--r-- | src/Makefile.in | 49 | ||||
-rw-r--r-- | src/alloc.c | 1154 | ||||
-rw-r--r-- | src/atimer.c | 44 | ||||
-rw-r--r-- | src/buffer.c | 143 | ||||
-rw-r--r-- | src/buffer.h | 2 | ||||
-rw-r--r-- | src/bytecode.c | 6 | ||||
-rw-r--r-- | src/callint.c | 67 | ||||
-rw-r--r-- | src/callproc.c | 39 | ||||
-rw-r--r-- | src/charset.c | 2 | ||||
-rw-r--r-- | src/chartab.c | 8 | ||||
-rw-r--r-- | src/cmds.c | 2 | ||||
-rw-r--r-- | src/coding.c | 4 | ||||
-rw-r--r-- | src/coding.h | 2 | ||||
-rw-r--r-- | src/conf_post.h | 47 | ||||
-rw-r--r-- | src/data.c | 28 | ||||
-rw-r--r-- | src/dbusbind.c | 6 | ||||
-rw-r--r-- | src/dired.c | 2 | ||||
-rw-r--r-- | src/dispextern.h | 21 | ||||
-rw-r--r-- | src/doc.c | 2 | ||||
-rw-r--r-- | src/dosfns.c | 4 | ||||
-rw-r--r-- | src/emacs.c | 53 | ||||
-rw-r--r-- | src/fileio.c | 16 | ||||
-rw-r--r-- | src/filelock.c | 10 | ||||
-rw-r--r-- | src/fns.c | 274 | ||||
-rw-r--r-- | src/font.c | 45 | ||||
-rw-r--r-- | src/font.h | 11 | ||||
-rw-r--r-- | src/frame.c | 89 | ||||
-rw-r--r-- | src/frame.h | 17 | ||||
-rw-r--r-- | src/fringe.c | 7 | ||||
-rw-r--r-- | src/ftxfont.c | 3 | ||||
-rw-r--r-- | src/gmalloc.c | 6 | ||||
-rw-r--r-- | src/gnutls.c | 12 | ||||
-rw-r--r-- | src/gtkutil.c | 51 | ||||
-rw-r--r-- | src/gtkutil.h | 4 | ||||
-rw-r--r-- | src/image.c | 128 | ||||
-rw-r--r-- | src/insdel.c | 23 | ||||
-rw-r--r-- | src/keyboard.c | 150 | ||||
-rw-r--r-- | src/keyboard.h | 57 | ||||
-rw-r--r-- | src/keymap.c | 6 | ||||
-rw-r--r-- | src/keymap.h | 2 | ||||
-rw-r--r-- | src/lisp.h | 152 | ||||
-rw-r--r-- | src/lread.c | 28 | ||||
-rw-r--r-- | src/macfont.m | 174 | ||||
-rw-r--r-- | src/menu.c | 207 | ||||
-rw-r--r-- | src/menu.h | 30 | ||||
-rw-r--r-- | src/minibuf.c | 2 | ||||
-rw-r--r-- | src/msdos.c | 5 | ||||
-rw-r--r-- | src/nsfns.m | 14 | ||||
-rw-r--r-- | src/nsfont.m | 14 | ||||
-rw-r--r-- | src/nsgui.h | 5 | ||||
-rw-r--r-- | src/nsmenu.m | 93 | ||||
-rw-r--r-- | src/nsterm.h | 7 | ||||
-rw-r--r-- | src/nsterm.m | 137 | ||||
-rw-r--r-- | src/process.c | 215 | ||||
-rw-r--r-- | src/process.h | 6 | ||||
-rw-r--r-- | src/profiler.c | 2 | ||||
-rw-r--r-- | src/puresize.h | 2 | ||||
-rw-r--r-- | src/regex.c | 10 | ||||
-rw-r--r-- | src/search.c | 14 | ||||
-rw-r--r-- | src/sound.c | 12 | ||||
-rw-r--r-- | src/sysdep.c | 48 | ||||
-rw-r--r-- | src/sysselect.h | 42 | ||||
-rw-r--r-- | src/syssignal.h | 4 | ||||
-rw-r--r-- | src/term.c | 96 | ||||
-rw-r--r-- | src/termhooks.h | 14 | ||||
-rw-r--r-- | src/terminal.c | 15 | ||||
-rw-r--r-- | src/unexcoff.c | 2 | ||||
-rw-r--r-- | src/unexcw.c | 10 | ||||
-rw-r--r-- | src/unexw32.c | 52 | ||||
-rw-r--r-- | src/vm-limit.c | 12 | ||||
-rw-r--r-- | src/w32.c | 24 | ||||
-rw-r--r-- | src/w32console.c | 4 | ||||
-rw-r--r-- | src/w32fns.c | 158 | ||||
-rw-r--r-- | src/w32gui.h | 5 | ||||
-rw-r--r-- | src/w32heap.c | 813 | ||||
-rw-r--r-- | src/w32heap.h | 21 | ||||
-rw-r--r-- | src/w32menu.c | 120 | ||||
-rw-r--r-- | src/w32notify.c | 4 | ||||
-rw-r--r-- | src/w32proc.c | 11 | ||||
-rw-r--r-- | src/w32term.c | 67 | ||||
-rw-r--r-- | src/w32term.h | 2 | ||||
-rw-r--r-- | src/window.c | 74 | ||||
-rw-r--r-- | src/xdisp.c | 68 | ||||
-rw-r--r-- | src/xfaces.c | 32 | ||||
-rw-r--r-- | src/xfns.c | 320 | ||||
-rw-r--r-- | src/xfont.c | 6 | ||||
-rw-r--r-- | src/xftfont.c | 11 | ||||
-rw-r--r-- | src/xgselect.c | 2 | ||||
-rw-r--r-- | src/xmenu.c | 155 | ||||
-rw-r--r-- | src/xsmfns.c | 2 | ||||
-rw-r--r-- | src/xterm.c | 191 | ||||
-rw-r--r-- | src/xterm.h | 13 |
94 files changed, 4363 insertions, 2972 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 715744bc18e..fd2e871ff3d 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -49,7 +49,7 @@ define xgetptr else set $bugfix = $arg0 end - set $ptr = ($bugfix & VALMASK) | DATA_SEG_BITS + set $ptr = $bugfix & VALMASK end define xgetint @@ -1093,8 +1093,8 @@ document xprintsym end define xcoding - set $tmp = (struct Lisp_Hash_Table *) ((Vcoding_system_hash_table & VALMASK) | DATA_SEG_BITS) - set $tmp = (struct Lisp_Vector *) (($tmp->key_and_value & VALMASK) | DATA_SEG_BITS) + set $tmp = (struct Lisp_Hash_Table *) (Vcoding_system_hash_table & VALMASK) + set $tmp = (struct Lisp_Vector *) ($tmp->key_and_value & VALMASK) set $name = $tmp->contents[$arg0 * 2] print $name pr @@ -1106,8 +1106,8 @@ document xcoding end define xcharset - set $tmp = (struct Lisp_Hash_Table *) ((Vcharset_hash_table & VALMASK) | DATA_SEG_BITS) - set $tmp = (struct Lisp_Vector *) (($tmp->key_and_value & VALMASK) | DATA_SEG_BITS) + set $tmp = (struct Lisp_Hash_Table *) (Vcharset_hash_table & VALMASK) + set $tmp = (struct Lisp_Vector *) ($tmp->key_and_value & VALMASK) p $tmp->contents[charset_table[$arg0].hash_index * 2] pr end diff --git a/src/ChangeLog b/src/ChangeLog index 6e312e79d7d..1bb96989b60 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,36 +1,165 @@ -2014-06-14 Eli Zaretskii <eliz@gnu.org> +2014-06-15 Eli Zaretskii <eliz@gnu.org> * xdisp.c (Fmove_point_visually): Don't use the glyph matrix information if we are in the middle of executing a keyboard macro, since redisplay doesn't update the screen until the macro is finished. (Bug#17777) -2014-06-13 Eli Zaretskii <eliz@gnu.org> - * alloc.c (cleanup_vector): Don't dereference a font driver pointer if it is NULL. (Bug#17771) +2014-06-13 Glenn Morris <rgm@gnu.org> + + * Makefile.in ($(leimdir)/leim-list.el, $(srcdir)/macuvs.h) + ($(lispsource)/international/charprop.el) + ($(libsrc)/make-docfile$(EXEEXT), $(lwlibdir)/liblw.a) + ($(oldXMenudir)/libXMenu11.a, ns-app, .el.elc) + ($(lispsource)/loaddefs.el, bootstrap-emacs$(EXEEXT)): + GNU make automatically passes command-line arguments to sub-makes. + +2014-06-13 Paul Eggert <eggert@cs.ucla.edu> + + Avoid hangs in accept-process-output (Bug#17647). + * lisp.h, process.c (wait_reading_process_input): + Return int, not bool. All uses changed. + * process.c (SELECT_CANT_DO_WRITE_MASK): + Remove macro, replacing with ... + (SELECT_CAN_DO_WRITE_MASK): ... new constant, with inverted sense. + All uses changed. + (status_notify): New arg WAIT_PROC. Return int, not void. + All uses changed. + +2014-06-13 Eli Zaretskii <eliz@gnu.org> + + * menu.c (Fx_popup_menu): Don't call the frame's menu_show_hook if + the frame is the initial frame, because the hook is not set up + then, and Emacs crashes. + Reported by Fabrice Popineau <fabrice.popineau@gmail.com>. + +2014-06-12 Stefan Monnier <monnier@iro.umontreal.ca> + + * keymap.c (silly_event_symbol_error): Don't recommend the use + of strings. + 2014-06-11 Eli Zaretskii <eliz@gnu.org> * xdisp.c (set_cursor_from_row): Fix an off-by-one error when matching overlay strings with 'cursor' property against buffer positions traversed in the glyph row. (Bug#17744) +2014-06-11 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.h (EmacsApp): Always compile in shouldKeepRunning, isFirst + on Cocoa. + + * nsterm.m (run): Always compile for Cocoa. Use runtime check to + determine 10.9 (Bug#17751). + + * macfont.m (macfont_draw): Positions were not freed. + +2014-06-10 Dmitry Antipov <dmantipov@yandex.ru> + + * dispextern.h (PREPARE_FACE_FOR_DISPLAY): Remove as a duplicate of ... + * xfaces.c (prepare_face_for_display) [HAVE_WINDOW_SYSTEM]: ... this + function. Also adjust comment. + * fringe.c, w32term.c, xdisp.c, xterm.c: All users changed. + + * dispextern.h (struct face) [HAVE_XFT]: Ifdef 'extra' member. + * font.c (font_done_for_face): + * xface.c (realize_non_ascii_face): Adjust user. + * font.h (struct font_driver): Convert 'prepare_face' to return + void because its return value is never used anyway. + * xfont.c (xfont_prepare_face): Return void. + * xftfont.c (xftfont_prepare_face): Likewise. Use xmalloc. + (xftfont_done_face): Use xfree. + + * dispextern.h (last_tool_bar_item): Remove declaration. + * frame.h (struct frame): New member last_tool_bar_item. + * frame.c (make_frame): Initialize it. + * xdisp.c (toplevel): Remove last_tool_bar_item. + (handle_tool_bar_click, note_tool_bar_highlight): + * w32term.c (w32_read_socket, w32_initialize): + * xterm.c (handle_one_xevent, x_initialize): Adjust users. + + * frame.h (window_system_available) [!HAVE_WINDOW_SYSTEM]: Always false. + * frame.c (window_system_available) [HAVE_WINDOW_SYSTEM]: Now here. + +2014-06-09 Paul Eggert <eggert@cs.ucla.edu> + + Say (accept-process-output P)'s result pertains to P if P is non-nil. + * process.c (Faccept_process_output) + (wait_reading_process_output): Mention that if PROCESS is non-nil, + the return value is about PROCESS, not about other processes. + +2014-06-09 Dmitry Antipov <dmantipov@yandex.ru> + + Further adjustments to mark_object and friends. + Now the mark_object's stack is just 32 bytes on a 64-bit + system, which means extra 20% off the stack usage. + * alloc.c (mark_save_value): As before, refactored out from ... + (mark_object): ... adjusted user. Also add comment. + +2014-06-09 Paul Eggert <eggert@cs.ucla.edu> + + Fix core dump after a dropped X connection (Bug#17704). + * sysdep.c (stuff_char): Don't abort merely because the selected frame + is dead, as we may be shutting down. + 2014-06-08 Glenn Morris <rgm@gnu.org> * fileio.c (write-region-inhibit-fsync): Doc tweak. * data.c (Flss, Fgtr, Fleq, Fgeq): Doc tweaks. -2014-06-04 Eli Zaretskii <eliz@gnu.org> +2014-06-08 Paul Eggert <eggert@cs.ucla.edu> + + If a C name must be extern on some platforms, make it extern on all. + * dispextern.h (set_vertical_scroll_bar, erase_phys_cursor) + (load_color): + * font.h (ftxfont_driver) [HAVE_XFT]: + * keyboard.h (menu_items_inuse, ignore_mouse_drag_p, make_ctrl_char): + * lisp.h (get_frame_param): + * menu.h (tty_menu_show): + * process.h (conv_sockaddr_to_lisp, catch_child_signal): + * termhooks.h (encode_terminal_code): + * xterm.h (x_menu_wait_for_event): + Always declare. + * frame.c (get_frame_param): + * fringe.c (max_used_fringe_bitmap): + * ftxfont.c (ftxfont_driver): + * keyboard.c (ignore_mouse_drag_p, make_ctrl_char): + * menu.c (menu_items_inuse): + * process.c (conv_sockaddr_to_lisp, catch_child_signal): + * term.c (encode_terminal_code, tty_menu_show): + * xdisp.c (set_vertical_scroll_bar, erase_phys_cursor): + * xfaces.c (load_color): + * xmenu.c (x_menu_wait_for_event): + Now always extern. + +2014-06-08 Dmitry Antipov <dmantipov@yandex.ru> + + Change object marking routines to minimize stack usage. + This change moves a few cold paths from mark_object to NO_INLINE + functions and adjusts symbol marking loop. According to GCC 4.8.2 + -Wstack-usage, this reduces mark_object's stack usage from 80 to + 48 bytes on a 64-bit system. For a long byte-force-recompile runs, + stack usage at the mark phase is reduced up to 28%. Surprisingly, + it also gains up to 3% in speed (with default '-O2 -g3' flags). + * alloc.c (mark_compiled, mark_localized_symbol): New functions, + refactored out from ... + (mark_object): ... adjusted user. Also mark symbols in a tight + inner loop. + (mark_face_cache): Add NO_INLINE. + +2014-06-08 Eli Zaretskii <eliz@gnu.org> * sysdep.c (reset_sys_modes): Use cursorX, not curX, as the latter contains garbage on WINDOWSNT (which could potentially infloop at exit). Minimize cursor motion during TTY menu updates. - * term.c (tty_menu_display): Don't position cursor here. Instead, - pass the cursor coordinates to update_frame_with_menu. + * term.c (tty_menu_display): Don't position cursor here. + Instead, pass the cursor coordinates to update_frame_with_menu. (tty_menu_activate): Send the hide cursor command only once in an iteration through the outer 'while' loop. @@ -41,30 +170,193 @@ update_frame_with_menu. (update_frame_with_menu): Accept 2 additional arguments ROW and COL; if they are non-negative, instruct update_frame_1 not to - position the cursor, and instead position it according to ROW and - COL. + position the cursor, and instead position it according to ROW and COL. * dispextern.h (update_frame_with_menu): Update prototype. -2014-06-02 Stefan Monnier <monnier@iro.umontreal.ca> +2014-06-08 Stefan Monnier <monnier@iro.umontreal.ca> * callproc.c (call_process): Don't check read-only if we don't insert anything (bug#17666). -2014-06-02 Eli Zaretskii <eliz@gnu.org> +2014-06-08 Eli Zaretskii <eliz@gnu.org> * dispnew.c (update_frame_with_menu): Set display_completed. -2014-06-01 Paul Eggert <eggert@cs.ucla.edu> +2014-06-07 Eli Zaretskii <eliz@gnu.org> + + * term.c (tty_menu_show) [WINDOWSNT]: Make tty_menu_show extern + only for WINDOWSNT. + * menu.h (tty_menu_show) [WINDOWSNT]: Declare extern only for WINDOWSNT. + +2014-06-06 Paul Eggert <eggert@cs.ucla.edu> + + * term.c (tty_menu_show) [!HAVE_NTGUI]: Now static. + * menu.h (tty_menu_show) [!HAVE_NTGUI]: Omit extern decl. + +2014-06-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Frecenter): Signal an error if window-buffer is not + current-buffer. + + * keyboard.c (make_lispy_position): Don't include a buffer position in + mode/header-line mouse events. + + * keyboard.c (read_char): Handle (t . <event>) in the second use of + Vunread_command_events (bug#17650). + +2014-06-06 Dmitry Antipov <dmantipov@yandex.ru> + + * xterm.c (x_setup_pointer_blanking): + Conditionally probe Xfixes until this stuff is stabilized (Bug#17609). + +2014-06-05 Dmitry Antipov <dmantipov@yandex.ru> + + * keyboard.c, process.c: Do not define POLL_FOR_INPUT here + because it will be defined in generated config.h if needed. + +2014-06-04 Dmitry Antipov <dmantipov@yandex.ru> + + Use terminal-specific hooks to display popup dialogs. + * termhooks.h (struct terminal): New field popup_dialog_hook. + * menu.c (emulate_dialog_with_menu): New function, refactored from ... + (Fx_popup_dialog): ... adjusted user. Also remove old #if 0 + code and use popup_dialog_hook. + * nsmenu.m (ns_popup_dialog): Make hook-compatible. + * nsterm.h (ns_popup_dialog): Adjust prototype. + * nsterm.m (ns_create_terminal): + * w32term.c (w32_create_terminal): + * xterm.c (x_create_terminal) [USE_X_TOOLKIT || USE_GTK]: + Setup popup_dialog_hook. + +2014-06-04 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (report_temacs_memory_usage): Improve the report by + reporting the large blocks that are actually occupied at dump time. + + * w32console.c (initialize_w32_display): Set the console + menu_show_hook, otherwise TTY menus are broken on w32. + +2014-06-04 Dmitry Antipov <dmantipov@yandex.ru> + + Use terminal-specific hooks to display menus. + * termhooks.h (struct terminal): New field menu_show_hook. + * menu.h (<anonymous enum>): Bit flags for menu hooks. + (x_menu_show, w32_menu_show, ns_menu_show, tty_menu_show): + Adjust prototypes. + * menu.c (Fx_popup_menu): Use bit flags and menu_show_hook. + * nsmenu.m (ns_menu_show): + * w32menu.c (w32_menu_show): + * xmenu.c (x_menu_show): + * term.c (tty_menu_show): Adjust to use bit flags. + (set_tty_hooks): Set menu_show_hook. + * xterm.c (x_create_terminal): + * nsterm.m (ns_create_terminal): + * msdos.c (initialize_msdos_display): + * w32term.c (w32_create_terminal): Likewise. + +2014-06-03 Juanma Barranquero <lekktu@gmail.com> + + * w32heap.c (DUMPED_HEAP_SIZE) [!_WIN64]: Reduce to 11 MB. + +2014-06-03 Eli Zaretskii <eliz@gnu.org> + + * sysselect.h (fd_CLR, fd_ISSET, fd_SET, FD_CLR, FD_ISSET) + (FD_SET): Don't define on WINDOWSNT. + +2014-06-03 Paul Eggert <eggert@cs.ucla.edu> + + * emacs.c: Include "sysselect.h", to define its inline functions. + Problem reported by Glenn Morris in: + http://lists.gnu.org/archive/html/emacs-devel/2014-06/msg00077.html + + Do not require libXt-devel when building with gtk. + * gtkutil.h, menu.h: Include lwlib-widget.h, not lwlib-h, to avoid + dependency on libXt-devel. + * menu.h [HAVE_NTGUI]: Include lwlib-widget.h in this case too. + (enum button_type, widget_value) [HAVE_NTGUI]: Remove, as + lwlib-widget.h now does this. + * nsmenu.m (ns_menu_show): "enabled" -> "enable" to fix typo. + +2014-06-03 Paul Eggert <eggert@penguin.cs.ucla.edu> + + If ENABLE_CHECKING, range-check args of FD_CLR, FD_ISSET, FD_SET. + * process.c (add_read_fd, delete_read_fd, add_write_fd) + (delete_write_fd, wait_reading_process_output): + Remove now-redundant easserts. + * sysselect.h (SYSSELECT_H): New macro, to avoid double-inclusion woes. + Use INLINE_HEADER_BEGIN, INLINE_HEADER_END. + (fd_CLR, fd_ISSET, fd_SET): New inline functions. + (FD_CLR, FD_ISSET, FD_SET): Redefine in terms of these functions. + +2014-06-03 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (DUMPED_HEAP_SIZE): Move from w32heap.h. Don't use + HEAPSIZE; instead, define separate values for the 32- and 64-bit builds. + (calloc): Don't undef, it is never defined. + (HEAP_ENTRY_SHIFT): Remove unused macro. + + * Makefile.in (C_HEAP_SWITCH): Remove. + (ALL_CFLAGS): Don't use $(C_HEAP_SWITCH). + + Fix MS-Windows build broken by menu changes on 2014-06-02. + * w32menu.c (w32_menu_show): Fix a typo that broke compilation. + + * menu.h (enum button_type, struct _widget_value) [HAVE_NTGUI]: + Define instead of including ../lwlib/lwlib.h, which causes + compilation errors due to missing X11 headers. + +2014-06-03 Paul Eggert <eggert@cs.ucla.edu> + + * process.c (wait_reading_process_output): Omit incorrect test of + p->infd against zero. Add easserts for infd having a plausible value. + +2014-06-02 Dmitry Antipov <dmantipov@yandex.ru> + + Adjust to match recent lwlib changes. + * menu.h (xmalloc_widget_value): Replace by ... + (make_widget_value): ... new prototype. + * menu.c (xmalloc_widget_value): Replace by ... + (make_widget_value): ... new function. + (free_menubar_widget_value_tree, digest_single_submenu): Adjust users. + * gtkutil.c (malloc_widget_value, free_widget_value): + (widget_value_free_list, malloc_cpt): Remove old lwlib-compatible code. + * keyboard.h (enum button_type, struct _widget_value): + * gtkutil.h, nsgui.h, w32gui.h (malloc_widget_value, free_widget_value): + Likewise. + * nsmenu.m (ns_update_menubar, ns_menu_show): + * w32menu.c (set_frame_menubar, w32_menu_show, w32_dialog_show): + * xmenu.c (set_frame_menubar, xmenu_show, x_dialog_show): Adjust users. + * xterm.h (XtParent) [USE_GTK]: Remove unused macro. + +2014-06-02 Dmitry Antipov <dmantipov@yandex.ru> + + * image.c (x_query_frame_background_color) + [HAVE_PNG || HAVE_NS || HAVE_IMAGEMAGICK || HAVE_RSVG]: + Fix --enable-gcc-warnings compilation without image libraries. + +2014-06-02 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (malloc_after_dump, realloc_after_dump): Update the + emulated break value only if it goes up. + (sbrk): Add assertion that the INCREMENT argument is strictly + zero. Improve and correct the commentary. + +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> + + Improve AIX-related merge from emacs-24. + * conf_post.h (FLEXIBLE_ARRAY_MEMBER): Fix comment. + * lisp.h (ENUMABLE) [!_AIX]: Don't define to 0 merely because we're + not on AIX; since we're on the trunk we can use enums more broadly. * frame.c (x_set_frame_parameters): Don't read uninitialized storage. -2014-06-01 Jan Djärv <jan.h.d@swipnet.se> +2014-06-02 Jan Djärv <jan.h.d@swipnet.se> * xterm.c (xg_scroll_callback): Remove position, for jump set portion to min(value, whole). -2014-06-01 Paul Eggert <eggert@cs.ucla.edu> +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> Bring back the changes to GDB-visible symbols, but only on AIX. And only if it's not pre-4.2 GCC. @@ -73,7 +365,7 @@ (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): New macros. -2014-05-31 Eli Zaretskii <eliz@gnu.org> +2014-06-02 Eli Zaretskii <eliz@gnu.org> * fileio.c (Finsert_file_contents): Call prepare_to_modify_buffer with PT, not GPT. (Bug#16433) @@ -84,11 +376,11 @@ (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): Delete macros. -2014-05-31 Glenn Morris <rgm@gnu.org> +2014-06-02 Glenn Morris <rgm@gnu.org> * cmds.c (Fself_insert_command): Allow zero repeat count. (Bug#17649) -2014-05-30 Paul Eggert <eggert@cs.ucla.edu> +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> Fix port to 32-bit AIX with xlc (Bug#17598). * alloc.c (gdb_make_enums_visible): Remove FLOAT_TO_STRING_BUFSIZE. @@ -96,13 +388,13 @@ * lisp.h (FLOAT_TO_STRING_BUFSIZE): Make it a macro, instead of an enum, to work around a compiler bug in IBM xlc 12.1. -2014-05-29 Eli Zaretskii <eliz@gnu.org> +2014-06-02 Eli Zaretskii <eliz@gnu.org> * xterm.c (x_update_window_end): Don't invalidate the entire mouse-highlight info, just signal frame_up_to_date_hook that mouse highlight needs to be redisplayed. (Bug#17588) -2014-05-29 Paul Eggert <eggert@cs.ucla.edu> +2014-06-02 Paul Eggert <eggert@cs.ucla.edu> Port the GDB-visible symbols to AIX. Without them, GDB doesn't work to debug Emacs, since the AIX linker @@ -113,35 +405,248 @@ (ARRAY_MARK_FLAG_val, PSEUDOVECTOR_FLAG_val, VALMASK_val): New macros. -2014-05-26 Paul Eggert <eggert@cs.ucla.edu> - Include sources used to create macuvs.h. * Makefile.in ($(srcdir)/macuvs.h): New rule. * macuvs.h: Use automatically-generated header. -2014-05-25 Eli Zaretskii <eliz@gnu.org> +2014-06-01 Paul Eggert <eggert@cs.ucla.edu> + + Port signal-handling to DragonFly BSD (Bug#17646). + * callproc.c, sysdep.c (block_child_signal, unblock_child_signal): + Move implementations from callproc.c to sysdep.c. + * process.h, syssignal.h (block_child_signal, unblock_child_signal): + Move declarations from process.h to syssignal.h. + +2014-06-01 Juanma Barranquero <lekktu@gmail.com> + + * callint.c (Ffuncall_interactively): Add usage. + +2014-06-01 Jan Djärv <jan.h.d@swipnet.se> + + * nsfns.m (ns_appkit_version_str): Add os version for Cocoa. + +2014-05-30 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (malloc_before_dump, malloc_after_dump) + (malloc_before_dump, realloc_after_dump, realloc_before_dump) + (mmap_alloc, mmap_realloc): Check for errors more thoroughly and + set errno where appropriate to emulate CRT functions. + +2014-05-30 Dmitry Antipov <dmantipov@yandex.ru> + + Debugging facility to check whether 'const char *' points to + relocatable data of non-pure Lisp string. + * alloc.c (maybe_lisp_pointer): New function, refactored out of ... + (mark_maybe_pointer): ... adjusted user. + (relocatable_string_data_p): New function. + * lisp.h (relocatable_string_data_p): Add prototype. + * xdisp.c (message_with_string): If ENABLE_CHECKING, make sure + the pointer to relocatable Lisp data is not used. + +2014-05-30 Paul Eggert <eggert@cs.ucla.edu> + + Don't let SIGINT handling block SIGCHLD indefinitely (Bug#17561). + * atimer.c (block_atimers): + * callproc.c (block_child_signal): Block SIGINT too; + otherwise, its handler might now unblock signals that it shouldn't. + * keyboard.c (read_char): Clear signal mask, since we may + be in a SIGINT handler, and many signals may be masked. + * keyboard.c (handle_interrupt): + * sysdep.c (handle_arith_signal): + Clear signal mask instead of just unblocking the signal that + was received, since several signals may be blocked at this point. + +2014-05-29 Eli Zaretskii <eliz@gnu.org> + + * Makefile.in (TEMACS_POST_LINK): Remove target. + (emacs$(EXEEXT)): Remove $(ADDSECTION) from prerequisites. + (temacs$(EXEEXT)): Remove $(TEMACS_POST_LINK) from the recipe. + +2014-05-29 Dmitry Antipov <dmantipov@yandex.ru> + + * xmenu.c (xdialog_show): Remove prototype, rename to + x_dialog_show, remove 2nd arg because it's always zero + and simplify accordingly. + (xw_popup_dialog): Adjust user. + * w32menu.c (w32_dialog_show): Adjust prototype, remove + 2nd arg because it's always zero and simplify accordingly. + (w32_popup_dialog): Adjust user. + +2014-05-29 Eli Zaretskii <eliz@gnu.org> + + * w32heap.c (report_temacs_memory_usage): New function. + + * unexw32.c (unexec) [ENABLE_CHECKING]: + Call report_temacs_memory_usage. + + * w32heap.h (report_temacs_memory_usage): Add prototype. + +2014-05-29 Paul Eggert <eggert@cs.ucla.edu> + + Don't substitute sigprocmask for pthread_sigmask (Bug#17561). + * Makefile.in (LIB_PTHREAD_SIGMASK): Remove; all uses removed. + +2014-05-29 Eli Zaretskii <eliz@gnu.org> + + * buffer.c (init_buffer): Accept an argument 'initialized'. + [USE_MMAP_FOR_BUFFERS]: If 'initialized' is non-zero, reset + mmap_regions and mmap_fd, to avoid referencing stale data from the + dump phase. Add an assertion for buffer text of buffers created + in temacs before this function is called. (Bug#17622) + (mmap_regions_1, mmap_fd_1): Remove unused variables. + + * lisp.h (init_buffer): Update prototype. + + * emacs.c (main): Pass 'initialized' as the argument to init_buffer. + +2014-05-29 Dmitry Antipov <dmantipov@yandex.ru> + + * alloc.c (Fgarbage_collect): Fix compilation with + GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE. + +2014-05-29 Paul Eggert <eggert@cs.ucla.edu> + + * frame.c, frame.h (frame_char_to_pixel_position) + (frame_set_mouse_position): Now static, and made private in + frame.c rather than public in frame.h. + +2014-05-28 Dmitry Antipov <dmantipov@yandex.ru> + + Refactor mouse positioning stuff to avoid code duplication. + * frame.h (frame_char_to_pixel_position): New function. + (x_set_mouse_position): Rename to... + (frame_set_mouse_position): ...new function. + (frame_set_mouse_pixel_position): Add prototype. + * nsterm.m, w32term.c, xterm.c (x_set_mouse_pixel_position): + Rename to frame_set_mouse_pixel_position. + * frame.c (Fset_mouse_pixel_position, Fset_mouse_position): + Adjust users. + * xterm.h, w32term.h ( x_set_mouse_position) + (x_set_mouse_pixel_position): Remove prototypes. + +2014-05-28 Dmitry Antipov <dmantipov@yandex.ru> + + On X, always make pointer visible when deleting frame (Bug#17609). + * frame.c (frame_make_pointer_visible, frame_make_pointer_invisible): + Pass frame as arg. + * frame.h (frame_make_pointer_visible, frame_make_pointer_invisible): + Adjust prototypes. + * cmds.c (Fself_insert_command): Use SELECTED_FRAME. + * keyboard.c (gobble_input): If there is no terminal input error, + make sure the pointer is visible for all frames on this terminal. + * xterm.c (x_free_frame_resources): Enable pointer visibility if + it was previously disabled. + +2014-05-28 Stefan Monnier <monnier@iro.umontreal.ca> + + * data.c (Fzerop): Move to Elisp. + (syms_of_data): Don't defsubr it. + * keyboard.c (echo_keystrokes_p): New function. + (read_char, record_menu_key, read_key_sequence): Use it. + + * callint.c (Qfuncall_interactively): New var. + (Qcall_interactively): Remove. + (Ffuncall_interactively): New function. + (Fcall_interactively): Use it. + (syms_of_callint): Defsubr it. + +2014-05-27 Stefan Monnier <monnier@iro.umontreal.ca> + + * bytecode.c (FETCH) [BYTE_CODE_SAFE]: Check the bytecode wasn't + relocated from under us. + +2014-05-27 Fabrice Popineau <fabrice.popineau@gmail.com> + + Use mmap(2) emulation for allocating buffer text on MS-Windows. + * Makefile.in (C_HEAP_SWITCH): Get the predefined heap size from + configure. + (ADDSECTION, MINGW_TEMACS_POST_LINK): Remove, no longer used. + + * lisp.h (NONPOINTER_BITS): Modify the condition to define to zero + for MinGW, since it no longer uses gmalloc. + + * buffer.c: Do not define mmap allocations functions for Windows. + Remove mmap_find which is unused. Remove mmap_set_vars which does + nothing useful. + [WINDOWSNT]: Include w32heap.h. + (init_buffer): Always allocate new memory for buffers. + + * emacs.c: Remove mmap_set_vars calls. + + * image.c (free_image): Undef free for Windows because it is + redirected to our private version. + + * unexw32.c (COPY_PROC_CHUNK): Use %p format for 64bits compatibility. + (copy_executable_and_dump_data): Remove dumping the heap section. + (unexec): Restore using_dynamic_heap after dumping. + + * w32heap.c (dumped_data_commit, malloc_after_dump) + (malloc_before_dump, realloc_after_dump, realloc_before_dump) + (free_after_dump, free_before_dump, mmap_alloc, mmap_realloc) + (mmap_free): New functions. + + * w32heap.h: Declare dumped_data and mmap_* function prototypes. + +2014-05-27 Paul Eggert <eggert@cs.ucla.edu> + + * image.c (imagemagick_load_image): Use MagickRealType for local + 'color_scale', instead of double, to avoid a GCC warning about + double promotion. + + * xfns.c (Fx_window_property): Remove unused local. + + Don't kill already-reaped process (Bug#17561). + * process.c (process_send_signal): Fix race condition where a + subprocess was reaped by a signal handler between the check for + liveness and calling 'kill', which meant that Emacs could in + theory kill an innocent bystander process. Do the fix by blocking + SIGCHLD in a critical section that checks liveness before killing. + +2014-05-26 Eli Zaretskii <eliz@gnu.org> + + * w32.c (_ANONYMOUS_UNION, _ANONYMOUS_STRUCT): Define only if undefined. + +2014-05-26 Ken Brown <kbrown@cornell.edu> + + * w32term.c (x_delete_display): Don't free dpyinfo->w32_id_name, + even if !CYGWIN (see bug#17510). + +2014-05-26 Jan Djärv <jan.h.d@swipnet.se> + + * nsfns.m (Fns_do_applescript): Surround NSApp run + with calls to ns_init_events, ns_finish_events (Bug#17424). + + * nsterm.h (ns_init_events, ns_finish_events): Declare. + + * nsterm.m (ns_init_events, ns_finish_events): New functions. + (ns_read_socket, ns_select): Call ns_init_events, ns_finish_events. + + * nsfns.m (ns_do_applescript): Surround executeAndReturnError + with calls to ns_init_events, ns_finish_events (Bug#17424). + +2014-05-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_in_display_line_to): Don't record wrap position if we are iterating over an object that generates glyphs for marginal areas. (Bug#17585) -2014-05-24 Paul Eggert <eggert@cs.ucla.edu> +2014-05-26 Paul Eggert <eggert@cs.ucla.edu> * xdisp.c (safe__call1, safe__eval): Now static. -2014-05-24 Eli Zaretskii <eliz@gnu.org> +2014-05-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (safe__call): Accept va_list argument instead of '...'. (safe_call, safe__call1): Construct a va_list argument for safe_call. (safe_call1): Call safe_call instead of safe__call directly. -2014-05-24 Ken Brown <kbrown@cornell.edu> +2014-05-26 Ken Brown <kbrown@cornell.edu> * w32term.c (x_delete_display) [CYGWIN]: Don't free dpyinfo->w32_id_name, to make sure it doesn't get freed more than once. (Bug#17510) -2014-05-24 Stefan Monnier <monnier@iro.umontreal.ca> +2014-05-26 Stefan Monnier <monnier@iro.umontreal.ca> * xdisp.c: Bind inhibit-quit during pre-redisplay-function. (safe__call, safe__call1, safe__eval): New functions. @@ -149,67 +654,215 @@ (prepare_menu_bars): Use it for pre-redisplay-function (bug#17577). (display_mode_element): Same for `:eval'. -2014-05-22 Paul Eggert <eggert@cs.ucla.edu> +2014-05-26 Paul Eggert <eggert@cs.ucla.edu> Fix port to 32-bit AIX (Bug#17540). * unexaix.c (copy_text_and_data): Don't add text_scnptr to ptr twice. _text already includes this offset. (unrelocate_symbols): Don't cast 64-bit integer to pointer. -2014-05-21 Eli Zaretskii <eliz@gnu.org> +2014-05-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_in_display_line_to): Avoid infinite recursion: when closest_pos is identical to to_charpos, don't recurse, since we already tried that, and failed. (Bug#17539) -2014-05-20 Eli Zaretskii <eliz@gnu.org> - * w32fns.c (unwind_create_frame) [GLYPH_DEBUG]: If we are unwinding when frame's faces were not initialized yet, increment the frame's image-cache reference count before calling x_free_frame_resources. Don't dereference dpyinfo->terminal->image_cache if it is NULL. (Bug#17524) -2014-05-11 Glenn Morris <rgm@gnu.org> +2014-05-25 Jan Djärv <jan.h.d@swipnet.se> + + * nsfont.m (nsfont_draw): Simplify as arguments are adjusted in + nsterm.m now. + + * nsterm.m (ns_draw_glyph_string): Move isComposite and end from + macfont.m, call draw with adjusted arguments so font drivers + don't need to do that. + + * macfont.m (macfont_draw): Merge changes from Macport. + +2014-05-24 Eli Zaretskii <eliz@gnu.org> + + * alloc.c (garbage_collect_1): New function, with all of the guts + of Fgarbage_collect. + (mark_stack): Accept an argument END and don't mark Lisp objects + on the stack beyond the address given by END. Calculation of END + was moved to Fgarbage_collect. + (Fgarbage_collect): Calculate the end address of the stack portion + that needs to be examined by mark_stack, and pass that address to + garbage_collect_1, which will pass it to mark_stack. + See http://lists.gnu.org/archive/html/emacs-devel/2014-05/msg00270.html + for more details about the underlying problems. In particular, + this avoids dumping Emacs with the large hash-table whose value is + held in purify-flag for most of the time loadup.el runs. + +2014-05-24 Jan Djärv <jan.h.d@swipnet.se> + + * xfns.c (x_window_property_intern): New function (code from + x_window_property). + (Fx_window_property): Call x_window_property_intern. If property + not found and NILP (source) and outer window != inner window, + check outer window for property (Bug#17537). + +2014-05-22 Paul Eggert <eggert@cs.ucla.edu> + + Supply malloc and alloc_size attributes for extern allocators. + This documents the C API, and helps GCC generate a bit better code. + * conf_post.h (ATTRIBUTE_MALLOC, ATTRIBUTE_ALLOC_SIZE) + (ATTRIBUTE_MALLOC_SIZE): New macros. + * gmalloc.c (malloc, realloc, calloc): + * gtkutil.h (malloc_widget_value): + * lisp.h (ralloc, r_re_alloc, xmalloc, xzalloc, xrealloc, xnmalloc) + (xnrealloc, xstrdup, xlispstrdup, record_xmalloc): + Use them. + +2014-05-21 Paul Eggert <eggert@cs.ucla.edu> + + Don't assume that ImageMagick uses a 16-bit quantum (Bug#17519). + * image.c (imagemagick_load_image): Port to hosts that do not use + a 16-bit quantum, i.e., QuantumRange does not equal 65535. + +2014-05-21 Leo Liu <sdl.web@gmail.com> + + * fns.c (Fnreverse): Accept strings for SEQ and update doc-string. + +2014-05-20 Michael Albinus <michael.albinus@gmx.de> + + * dbusbind.c (xd_signature): Revert last 2 patches. + +2014-05-19 Paul Eggert <eggert@cs.ucla.edu> + + Allow any non-nil value to count as true in bool-vector. + Likewise for xd_signature in dbusbind.c. + This is more consistent with the usual practice in Emacs, which is + that any non-nil value counts as true. + * alloc.c (Fbool_vector): Don't require args to be t or nil. + * dbusbind.c (xd_signature): Likewise, for booleans. + * data.c, lisp.h (Qbooleanp): + * lisp.h (CHECK_BOOLEAN): Remove. All uses removed. + +2014-05-19 Dmitry Antipov <dmantipov@yandex.ru> + + * lisp.h (CHECK_BOOLEAN): New function. + * alloc.c (Fbool_vector): New function. + (syms_of_alloc): Defsubr it. + * data.c (Qbooleanp): New symbol. + (syms_of_data): DEFSYM it. + * dbusbind.c (xd_signature): Use CHECK_BOOLEAN. + + * font.c (font_matching_entity): Extract font-entity object + from the vector of matching entities (Bug#17486). + +2014-05-17 Paul Eggert <eggert@cs.ucla.edu> + + Assume C99 or later (Bug#17487). + * bytecode.c (B__dummy__): Remove. + * conf_post.h (bool_bf) [!NS_IMPL_GNUSTEP]: Use bool. + (FLEXIBLE_ARRAY_MEMBER): Now always empty. + * dbusbind.c (XD_DEBUG_MESSAGE) [!DBUS_DEBUG]: + * regex.c (DEBUG_PRINT): Assume varargs macros. + * lisp.h (DEFUN_FUNCTION_INIT): Remove. All uses now assume C99. + +2014-05-17 Fabrice Popineau <fabrice.popineau@gmail.com> + + * buffer.c (init_buffer) [USE_MMAP_FOR_BUFFERS]: Always map new + memory for every buffer that was dumped. + +2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> + + * fns.c (Freverse): Allow vectors, bool vectors and strings. + (Fnreverse): Allow vectors and bool vectors. + +2014-05-14 Dmitry Antipov <dmantipov@yandex.ru> + + Minor cleanup for terminal setup. + * termhooks.h (create_terminal): Adjust prototype. + * terminal.c (create_terminal): Pass output method and RIF as args. + (init_initial_terminal): + * nsterm.m (ns_create_terminal): + * term.c (init_tty): + * w32term.c (w32_create_terminal): + * xterm.c (x_create_terminal): Adjust users. + Avoid redundant NULL initializers and add comments. + +2014-05-13 Paul Eggert <eggert@cs.ucla.edu> + + * keyboard.c (Qdeactivate_mark): Now static. + +2014-05-13 Dmitry Antipov <dmantipov@yandex.ru> + + If available, use Xfixes extension to do pointer blanking. + * Makefile.in (XFIXES_CFLAGS, XFIXES_LIBS): New var. + * xfns.c (x_set_mouse_color): Do not call make_invisible_cursor here. + (make_invisible_cursor): Move to... + * xterm.c (make_invisible_cursor): ...here. + (x_probe_xfixes_extension, xfixes_toggle_visible_pointer) + (x_toggle_visible_pointer, x_setup_pointer_blanking): New functions. + (x_term_init): Call to x_setup_pointer_blanking. + (XTtoggle_invisible_pointer): Use blanking specific to this display. + * xterm.h (struct x_display_info): New member toggle_visible_pointer. + +2014-05-12 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * xdisp.c (draw_glyphs): Set clipping to highlight boundaries. + +2014-05-12 Glenn Morris <rgm@gnu.org> * fileio.c (Ffile_executable_p): Doc tweak. -2014-05-10 Jan Djärv <jan.h.d@swipnet.se> +2014-05-12 Jan Djärv <jan.h.d@swipnet.se> * xsettings.c (init_gsettings): Use g_settings_schema_source_lookup instead of deprecated g_settings_list_schemas if possible (Bug#17434). -2014-05-07 Paul Eggert <eggert@cs.ucla.edu> +2014-05-08 Paul Eggert <eggert@cs.ucla.edu> * minibuf.c (read_minibuf): Avoid C99ism in previous patch (Bug#17430). -2014-05-07 Jarek Czekalski <jarekczek@poczta.onet.pl> +2014-05-08 Jarek Czekalski <jarekczek@poczta.onet.pl> Fix initialization of minibuffer history variable (Bug#17430). * minibuf.c (read_minibuf): Initialize histval to Qnil if unbound. Move the initialization up to prevent any "value void" message. -2014-05-06 Samuel Bronson <naesten@gmail.com> +2014-05-08 Samuel Bronson <naesten@gmail.com> * keyboard.c (Frecursive_edit): Ensure inc&dec of command_loop_level are matched (bug#17413). -2014-05-06 Jarek Czekalski <jarekczek@poczta.onet.pl> +2014-05-08 Jarek Czekalski <jarekczek@poczta.onet.pl> Stop tooltips pulling Emacs window to front (Bug#17408). * w32fns.c (Fx_show_tip): Add SWP_NOOWNERZORDER flag to SetWindowPos invocations. -2014-05-05 Jan Djärv <jan.h.d@swipnet.se> +2014-05-08 Jan Djärv <jan.h.d@swipnet.se> * nsselect.m (Fx_selection_exists_p): Just return Qnil if window system not initialized (Bug#17398). +2014-05-07 Paul Eggert <eggert@cs.ucla.edu> + + * image.c: Include <png.h> before <setjmp.h> (Bug#17429). + +2014-05-06 Paul Eggert <eggert@cs.ucla.edu> + + * image.c: Do not use libpng if HAVE_NS, as NS does its own thing. + [HAVE_NS]: Do not include png.h. + (x_query_frame_background_color): New function. + (png_load_body, imagemagick_load_image, svg_load_image): Use it. + (png_load_body): Coalesce duplicate code. + 2014-05-04 Paul Eggert <eggert@cs.ucla.edu> - Revert recent libpng changes (Bug#17339). - * Makefile.in (PNG_CFLAGS): Remove; all uses removed. - * image.c [HAVE_LIBPNG_PNG_H]: Include <libpng/png.h>, not <png.h>. + Consult libpng-config more consistently (Bug#17339). + * Makefile.in (PNG_CFLAGS): New var. + (ALL_CFLAGS): Use it. + * image.c [HAVE_PNG]: Don't worry about <libpng/png.h>, as + CFLAGS now handles this. 2014-05-03 Paul Eggert <eggert@cs.ucla.edu> @@ -222,14 +875,6 @@ * buffer.c (overlay_strings): Fix the wording of the commentary. -2014-05-02 Paul Eggert <eggert@cs.ucla.edu> - - Consult libpng-config more consistently (Bug#17339). - * Makefile.in (PNG_CFLAGS): New var. - (ALL_CFLAGS): Use it. - * image.c [HAVE_PNG]: Don't worry about <libpng/png.h>, as - CFLAGS now handles this. - 2014-05-01 Glenn Morris <rgm@gnu.org> * floatfns.c (Fisnan): @@ -262,26 +907,66 @@ GCC 4.9.0 warned about this, and I couldn't easily prove to my own satisfaction that they would always be initialized. -2014-04-29 Eli Zaretskii <eliz@gnu.org> +2014-04-30 Eli Zaretskii <eliz@gnu.org> - * term.c (tty_menu_display): Move the cursor to the active menu - item. + * term.c (tty_menu_display): Move the cursor to the active menu item. (tty_menu_activate): Return the cursor to the active menu item - after displaying the menu and after displaying help-echo. See - http://lists.gnu.org/archive/html/emacs-devel/2014-04/msg00402.html + after displaying the menu and after displaying help-echo. + See http://lists.gnu.org/archive/html/emacs-devel/2014-04/msg00402.html for the details of why this is needed by screen readers and Braille displays. -2014-04-29 Glenn Morris <rgm@gnu.org> +2014-04-30 Glenn Morris <rgm@gnu.org> * process.c (handle_child_signal): Handle systems without WCONTINUED. (Bug#15110, 17339) -2014-04-23 Eli Zaretskii <eliz@gnu.org> +2014-04-29 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (struct saved_window): Remove mark. + (Fset_window_configuration, save_window_save) + (compare_window_configurations): Don't touch marks any more. + +2014-04-28 Paul Eggert <eggert@cs.ucla.edu> + + Use bits_word for gcmarkbits. + * alloc.c (struct cons_block, struct float_block): On 64-bit hosts, + bits_word is typically a tad more efficient for mark bits than + unsigned is, so use bits_word. All uses changed. + * lisp.h (BITS_PER_INT): Remove; no longer used. + + Avoid undefined behavior in signed left shift. + This ports to GCC 4.9.0 with -fsanitize=undefined. + * alloc.c (bool_vector_fill, SETMARKBIT, UNSETMARKBIT): + * data.c (Fash): + * regex.c (extract_number): + * lisp.h (make_number, XINT): + Do not shift a 1 bit left into a sign bit. + * alloc.c (struct cons_block, struct float_block): Use unsigned, + not int, for gcmarkbits. All uses changed. + +2014-04-25 Eli Zaretskii <eliz@gnu.org> * search.c (Fnewline_cache_check): Don't try to count newlines outside the buffer's restriction, as find_newline doesn't support that. +2014-04-24 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Fset_window_configuration): Deactivate the mark before + unsetting the mark. + (set_window_buffer): Ignore window_initialized. + (window_initialized): Remove. + * keyboard.c (Qdeactivate_mark): Not static any more. + * buffer.c (buffer_local_value): Rename from buffer_local_value_1. + Update all callers. + +2014-04-23 Paul Eggert <eggert@cs.ucla.edu> + + * conf_post.h (ADDRESS_SANITIZER_WORKAROUND): Port to GCC 4.9.0 + and to clang 3.4, which have fixed the bug. This should let us + run a bit faster on these platforms when address sanitization is + in effect. + 2014-04-22 Paul Eggert <eggert@cs.ucla.edu> Port to GCC 4.9.0 with --enable-gcc-warnings. @@ -298,42 +983,61 @@ (Fnewline_cache_check): New function. (syms_of_search): Defsubr it. -2014-04-21 Jarek Czekalski <jarekczek@poczta.onet.pl> +2014-04-22 Jarek Czekalski <jarekczek@poczta.onet.pl> Fix freezing with scroll bars of GTK3 Toolkit (bug#15801). * keyboard.c (unblock_input): Add comment. * xgselect.c (xg_select): Prevent Glib main loop recursion. +2014-04-22 Daniel Colascione <dancol@dancol.org> + + * lread.c (readevalloop_eager_expand_eval): New function + that can recurse into toplevel forms. + (readevalloop): Call it. + * lisp.h: Declare Qprogn. + * callint.c (Qprogn): No longer static. + 2014-04-19 Stefan Monnier <monnier@iro.umontreal.ca> * intervals.c (rotate_right, rotate_left): Fix up length computation. Also change identifiers to match the comments, and add more assertions (bug#16234). -2014-04-18 Eli Zaretskii <eliz@gnu.org> - - * xdisp.c (insert_left_trunc_glyphs): Ensure the left truncation - glyph is written to TEXT_AREA of the temporary glyph_row. - (Bug#17288) - 2014-04-18 Paul Eggert <eggert@cs.ucla.edu> * emacs.c (close_output_streams): Don't clear and restore errno. -2014-04-17 Jan Djärv <jan.h.d@swipnet.se> +2014-04-18 Jan Djärv <jan.h.d@swipnet.se> * xterm.c (x_make_frame_visible): Prevent endless loop when frame never becomes visible, i.e. using XMonad (Bug#17237). -2014-04-17 Eli Zaretskii <eliz@gnu.org> +2014-04-18 Eli Zaretskii <eliz@gnu.org> - * xdisp.c (Fline_pixel_height): Don't assume that the current - buffer and the selected window's buffer are one and the same. - (Bug#17281) + * xdisp.c (insert_left_trunc_glyphs): Ensure the left truncation + glyph is written to TEXT_AREA of the temporary glyph_row. (Bug#17288) + (Fline_pixel_height): Don't assume that the current buffer and the + selected window's buffer are one and the same. (Bug#17281) * insdel.c (invalidate_buffer_caches): Invalidate the bidi paragraph-start cache before the newline cache. (Bug#17269) +2014-04-17 Paul Eggert <eggert@cs.ucla.edu> + + * term.c (tty_send_additional_strings): No need to fflush here, + as callers fflush. + (tty_set_terminal_modes): fflush after sending additional strings, + not before. + +2014-04-17 Daniel Colascione <dancol@dancol.org> + + * term.c (Qtty_mode_set_strings, Qtty_mode_reset_strings): + New symbols. + (tty_send_additional_strings): New function. + (tty_set_terminal_modes, tty_reset_terminal_modes): Use it. + (syms_of_term): Intern tty-mode-set-strings and + tty-mode-reset-strings. + 2014-04-16 Stefan Monnier <monnier@iro.umontreal.ca> * window.c (save_window_save): Lookup window_point_insertion_type in @@ -401,44 +1105,57 @@ Move vfork-related portions under #ifndef MSDOS. (syms_of_callproc): Unify templates of MSDOS and WINDOWSNT. -2014-04-15 Stefan Monnier <monnier@iro.umontreal.ca> +2014-04-16 Stefan Monnier <monnier@iro.umontreal.ca> * buffer.c (Foverlays_at): Add argument `sorted'. -2014-04-14 Eli Zaretskii <eliz@gnu.org> +2014-04-16 Eli Zaretskii <eliz@gnu.org> * insdel.c (invalidate_buffer_caches): When deleting or replacing text, invalidate the bidi_paragraph_cache upto and including the preceding newline. -2014-04-13 Paul Eggert <eggert@cs.ucla.edu> +2014-04-16 Paul Eggert <eggert@cs.ucla.edu> Port to IRIX 6.5 (Bug#9684). - * alloc.c (TAGGABLE_NULL): New constant, - for porting to hosts with nontrivial DATA_SEG_BITS settings. - (next_vector, set_next_vector): Use it. * conf_post.h (INET6) [IRIX6_5]: Define. (HAVE_GETADDRINFO) [IRIX6_5]: Undef. * data.c (BITS_PER_ULL): Don't assume ULLONG_MAX is defined. - * lisp.h (lisp_h_XPNTR): Don't OR in bits that aren't masked out, - for consistency with how TAGGABLE_NULL is computed. -2014-04-13 Eli Zaretskii <eliz@gnu.org> +2014-04-16 Eli Zaretskii <eliz@gnu.org> * keyboard.c (Fopen_dribble_file): Encode the dribble file-name before passing it to system APIs. - * puresize.h (BASE_PURESIZE): Bump by 1K. (Bug#17255) - -2014-04-13 Stefan Monnier <monnier@iro.umontreal.ca> +2014-04-16 Stefan Monnier <monnier@iro.umontreal.ca> * bytecode.c (exec_byte_code): Rework the volatiles. Most importantly, make sure stack.byte_string_start is not de-adjusted by pushhandler. -2014-04-12 Paul Eggert <eggert@cs.ucla.edu> +2014-04-16 Paul Eggert <eggert@cs.ucla.edu> * keyboard.c (Fopen_dribble_file): Avoid some races. (Bug#17187) +2014-04-15 Paul Eggert <eggert@cs.ucla.edu> + + Remove DATA_SEG_BITS. + The DATA_SEG_BITS hack was needed for older 32 bit platforms. + As a result of this change, Emacs won't work on IRIX 6.5 with IRIX + cc, but that platform is so old that SGI itself stopped supporting + it in December 2013. If you still need Emacs on IRIX, please + either compile with GCC and port the undumping code, or run + './configure --with-wide-int'. + * alloc.c (gdb_make_enums_visible): Update to match lisp.h. + * lisp.h (GCTYPEBITS): Move definition up, and switch to the + DEFINE_GDB_SYMBOL_START way to define it. + (NONPOINTER_BITS): New macro. + (EMACS_INT): Use it. + [!USE_LSB_TAG && !WIDE_EMACS_INT]: Fail, and suggest reporting + the problem and/or configuring --with-wide-int. + (USE_LSB_TAG): Simplify, based on above changes. + (gdb_DATA_SEG_BITS): Remove. All uses removed. + * vm-limit.c (exceeds_lisp_ptr): Remove. All uses removed. + 2014-04-12 Eli Zaretskii <eliz@gnu.org> * xdisp.c (move_it_by_lines): If a large portion of buffer text is @@ -449,8 +1166,6 @@ * indent.c (Fvertical_motion): Handle correctly the case when the display string is preceded by an empty line. -2014-04-11 Eli Zaretskii <eliz@gnu.org> - * w32.c (sys_umask) <WRITE_USER>: Remove redundant constant, and use S_IWRITE instead. @@ -458,10 +1173,33 @@ * keyboard.c (Fopen_dribble_file): Make file private. (Bug#17187) -2014-04-09 Ken Brown <kbrown@cornell.edu> +2014-04-11 Ken Brown <kbrown@cornell.edu> * Makefile.in (EMACS_MANIFEST): Revert last change. +2014-04-10 Daniel Colascione <dancol@dancol.org> + + * puresize.h (BASE_PURESIZE): Increase. + +2014-04-09 Stefan Monnier <monnier@iro.umontreal.ca> + + * keyboard.c (syms_of_keyboard): Make deactivate-mark buffer-local. + + * insdel.c (prepare_to_modify_buffer_1): Cancel lock-file checks and + region handling (and don't call signal_before_change) if + inhibit_modification_hooks is set. + (signal_before_change): Don't check inhibit_modification_hooks any more. + +2014-04-08 Daniel Colascione <dancol@dancol.org> + + * alloc.c (sweep_symbols, mark_object): Assert that symbol + function cells contain valid lisp objects. (Modified version of + patch from Dmitry). + + * alloc.c (detect_suspicious_free): Split actual stack capturing + out into new function for easier breakpoint setting. + (note_suspicious_free): New function. + 2014-04-07 Stefan Monnier <monnier@iro.umontreal.ca> * lisp.h (struct Lisp_Symbol): New bitfield `pinned'. @@ -477,58 +1215,183 @@ (Fgarbage_collect): Use it. (gc_sweep): Remove hack made unnecessary. -2014-04-05 Glenn Morris <rgm@gnu.org> +2014-04-07 Glenn Morris <rgm@gnu.org> * keyboard.c (Fopen_dribble_file): Doc tweak. -2014-04-04 Jan Djärv <jan.h.d@swipnet.se> +2014-04-07 Ken Brown <kbrown@cornell.edu> - Backport from trunk. - * nsterm.m (updateFrameSize:): If waiting for the tool bar and tool - bar is zero height, just return (Bug#16976). - (initFrameFromEmacs:): Initialize wait_for_tool_bar. - * nsterm.h (EmacsView): Add wait_for_tool_bar. - * nsmenu.m (update_frame_tool_bar): Return early if view or toolbar - is nil. If waiting for toolbar to complete, force a redraw. - (free_frame_tool_bar): Set wait_for_tool_bar = NO (Bug#16976). + * Makefile.in (EMACS_MANIFEST): Update comment. (Bug#17176) -2014-04-03 Ken Brown <kbrown@cornell.edu> +2014-04-07 Paul Eggert <eggert@cs.ucla.edu> - * Makefile.in (EMACS_MANIFEST): Update comment. (Bug#17176) + * alloc.c: Simplify by removing use of HAVE_EXECINFO_H. + We have a substitute execinfo.h on hosts that lack it. + (suspicious_free_history): Make it EXTERNALLY_VISIBLE so it + isn't optimized away. + +2014-04-05 Paul Eggert <eggert@cs.ucla.edu> + + Prefer 'ARRAYELTS (x)' to 'sizeof x / sizeof *x'. + * alloc.c (memory_full): + * charset.c (syms_of_charset): + * doc.c (Fsnarf_documentation): + * emacs.c (main): + * font.c (BUILD_STYLE_TABLE): + * keyboard.c (make_lispy_event): + * profiler.c (setup_cpu_timer): + * xgselect.c (xg_select): + * xterm.c (record_event, STORE_KEYSYM_FOR_DEBUG): + Use ARRAYELTS. + * font.c (FONT_PROPERTY_TABLE_SIZE): Remove. + Replace the only use with ARRAYELTS (font_property_table). + * xfaces.c (DIM): Remove. All uses replaced by ARRAYELTS. + +2014-04-03 Daniel Colascione <dancol@dancol.org> + + * xterm.c (x_term_init): + * xfns.c (best_xim_style): + * xfaces.c (Fdump_colors): + * w32fns.c (w32_default_color_map): + * w32.c (init_environment, N_ENV_VARS): + * unexcw.c (read_exe_header): + * term.c (term_get_fkeys_1): + * sysdep.c (init_baud_rate): + * nsterm.m (ns_convert_key): + * nsfns.m (get_geometry_from_preferences): + * msdos.c (dos_set_window_size, init_environment): + * macfont.m (mac_font_get_glyph_for_cid) + (macfont_store_descriptor_attributes) + (macfont_create_attributes_with_spec, mac_ctfont_get_glyph_for_cid): + * keyboard.c (command_loop_1, read_menu_command, make_lispy_event) + (NUM_MOD_NAMES, read_key_sequence_vs, Fcurrent_input_mode) + (syms_of_keyboard): + * image.c (xpm_str_to_color_key): + * fringe.c (MAX_STANDARD_FRINGE_BITMAPS): + * frame.c (x_set_frame_parameters): + * fileio.c (Ffile_selinux_context): + * emacs.c (sort_args): + * dosfns.c (msdos_stdcolor_name): + * dired.c (file_attributes): + * chartab.c (uniprop_decoder_count, uniprop_encode_count): + Change expressions of the form sizeof(arr) / sizeof(arr[0]) + to ARRAYELTS (arr). + +2014-04-02 Daniel Colascione <dancol@dancol.org> + + * data.c (Ffset): Abort if we're trying to set a function call to + a dead lisp object. + + * lisp.h (ARRAYELTS): New macro. + + * alloc.c: Include execinfo.h if available. + (SUSPICIOUS_OBJECT_CHECKING): New macro; define unconditionally. + (suspicious_free_record): New structure. + (suspicious_objects, suspicious_object_index) + (suspicious_free_history, suspicious_free_history_index): + New variables. + (find_suspicious_object_in_range, detect_suspicious_free) + (Fsuspicious_object): New functions. + (cleanup_vector): Call find_suspicious_object_in_range. 2014-04-02 Martin Rudalics <rudalics@gmx.at> * xterm.c (x_new_font): Don't calculate non-toolkit scrollbar width from font width (Bug#17163). -2014-03-30 Martin Rudalics <rudalics@gmx.at> - * frame.c (x_set_frame_parameters): Calculate default values of new frame sizes only after all other frame parameters have been processed (Bug#17142). -2014-03-28 Ken Brown <kbrown@cornell.edu> +2014-04-02 Ken Brown <kbrown@cornell.edu> * conf_post.h (SYSTEM_PURESIZE_EXTRA) [CYGWIN]: Set to 10000. (Bug#17112) -2014-03-28 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> +2014-04-02 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> * xterm.c (x_draw_image_glyph_string): Adjust image background width accordingly when its x position is adjusted. (Bug#17115) +2014-04-02 Dmitry Antipov <dmantipov@yandex.ru> + + * font.c (font_list_entities): Do not add empty vector to font cache. + (font_matching_entity): Likewise. If matching entity is found, insert + 1-item vector with this entity instead of entity itself (Bug#17125). + + * xterm.c (x_term_init) [USE_LUCID]: Fix minor memory leak. + +2014-04-01 Paul Eggert <eggert@cs.ucla.edu> + + * fns.c (validate_subarray): Rename from validate_substring, + since it works for vectors too. New arg ARRAY. Optimize for the + non-nil case. Instead of returning bool, throw an error if out of + range, so that the caller needn't do that. All uses changed. + Report original values if out of range. + (Fsubstring, Fsubstring_no_properties, secure_hash): + Also optimize the case where FROM is 0 or TO is the size. + +2014-03-31 Dmitry Antipov <dmantipov@yandex.ru> + + * search.c (Freplace_match): Use make_specified_string. + * xterm.c, w32term.c (x_set_glyph_string_gc): Use emacs_abort + to catch bogus override face of glyph strings. + * fns.c (Fsubstring, Fsubstring_no_properties, secure_hash): + Move common substring range checking code to... + (validate_substring): ...this function. + +2014-03-31 Jan Djärv <jan.h.d@swipnet.se> + + * nsmenu.m (free_frame_tool_bar): Set wait_for_tool_bar = NO (Bug#16976) + +2014-03-30 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (updateFrameSize:): If waiting for the tool bar and tool + bar is zero height, just return (Bug#16976). + (initFrameFromEmacs:): Initialize wait_for_tool_bar. + + * nsterm.h (EmacsView): Add wait_for_tool_bar. + + * nsmenu.m (update_frame_tool_bar): Return early if view or toolbar + is nil. If waiting for toolbar to complete, force a redraw. + +2014-03-28 Glenn Morris <rgm@gnu.org> + + * emacs.c (emacs_version): Use PACKAGE_VERSION rather than VERSION. + (emacs_bugreport): New variable. + (usage_message): Use PACKAGE_BUGREPORT. + (syms_of_emacs) <report-emacs-bug-address>: New variable. + + * emacs.c (syms_of_emacs) <system-configuration-features>: New var. + +2014-03-27 Paul Eggert <eggert@cs.ucla.edu> + + Port recent signal-related changes to FreeBSD. + Problem reported by Herbert J. Skuhra. + * lisp.h (block_tty_out_signal, unblock_tty_out_signal): + Move decls from here ... + * syssignal.h: ... to here, so that lisp.h doesn't depend on signal.h. + 2014-03-27 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> * w32term.c (x_draw_image_glyph_string): Fix computation of height and width of image background when it is displayed with a 'box' face. (Bug#17115) -2014-03-26 Paul Eggert <eggert@penguin.cs.ucla.edu> +2014-03-27 Paul Eggert <eggert@penguin.cs.ucla.edu> More backward-compatible fix to char-equal core dump (Bug#17011). * editfns.c (Fchar_equal): In unibyte buffers, assume values in range 128-255 are raw bytes. Suggested by Eli Zaretskii. +2014-03-27 Juanma Barranquero <lekktu@gmail.com> + + * image.c (init_svg_functions): When loading SVG-related libraries, + free already loaded libraries if the initialization fails. + (rsvg_handle_set_size_callback): Remove declaration, unused. + +2014-03-26 Paul Eggert <eggert@cs.ucla.edu> + Fix core dump in char-equal (Bug#17011). * editfns.c (Fchar_equal): Do not use MAKE_CHAR_MULTIBYTE in unibyte buffers, as we can't tell whether the characters are @@ -536,7 +1399,7 @@ * insdel.c (adjust_markers_for_delete): Remove unused local. -2014-03-24 Barry O'Reilly <gundaetiapo@gmail.com> +2014-03-26 Barry O'Reilly <gundaetiapo@gmail.com> Have (MARKER . ADJUSTMENT) undo records always be immediately after their corresponding (TEXT . POS) record in undo list. @@ -564,38 +1427,134 @@ (record_point): at_boundary calculation no longer needs to account for marker adjustments. -2014-03-24 Martin Rudalics <rudalics@gmx.at> +2014-03-26 Martin Rudalics <rudalics@gmx.at> * w32term.c (x_set_window_size): Refine fix from 2014-03-14 (Bug#17077). -2014-03-23 Glenn Morris <rgm@gnu.org> +2014-03-26 Glenn Morris <rgm@gnu.org> * fileio.c (Ffile_symlink_p): Doc fix. (Bug#17073) -2014-03-23 Stefan Monnier <monnier@iro.umontreal.ca> +2014-03-26 Stefan Monnier <monnier@iro.umontreal.ca> * buffer.c (struct sortvec): Add field `spriority'. (compare_overlays): Use it. (sort_overlays): Set it. -2014-03-23 Eli Zaretskii <eliz@gnu.org> +2014-03-26 Eli Zaretskii <eliz@gnu.org> * xdisp.c (redisplay_window): If all previous attempts to find the cursor row failed, try a few alternatives before falling back to the top-most row of the window. Use row_containing_pos. (Bug#17047) -2014-03-22 Daniel Colascione <dancol@dancol.org> +2014-03-26 Juanma Barranquero <lekktu@gmail.com> - * process.c (conv_sockaddr_to_lisp): When extracting the string - names of AF_LOCAL sockets, stop before reading uninitialized - memory. + * image.c (x_bitmap_height, x_bitmap_width) [HAVE_X_WINDOWS]: + * sysdep.c (reset_sigio) [!DOS_NT]: Declare conditionally. + + * keyboard.c (read_decoded_event_from_main_queue): #ifdef out + variables on Windows. + + * w32fns.c (Ffile_system_info): Use parenthesis in and/or expression. + + * w32.c (unsetenv): Remove unused var `retval'. + (emacs_gnutls_pull): Remove unused vars `fdset' and `timeout'. + + * w32notify.c (watch_worker): Remove unnecesary var sleep_result. + (start_watching): Remove unused var `thr'. + + * w32proc.c (sys_spawnve): Comment out unused vars `first', `last'. + (find_child_console): Remove unnecesary var `thread_id'. + + * w32term.c (w32_read_socket): Comment out unused vars `row', `columns'. + (x_focus_frame): #ifdef 0 unused variable `dpyinfo'. + +2014-03-26 Glenn Morris <rgm@gnu.org> + + * filelock.c (Flock_buffer): Doc tweak. + + * buffer.c (Frestore_buffer_modified_p, Fkill_buffer): + * emacs.c (shut_down_emacs): + * fileio.c (Finsert_file_contents, write_region): + * filelock.c (top-level, syms_of_filelock): + * insdel.c (prepare_to_modify_buffer_1): + CLASH_DETECTION is always defined now. + +2014-03-25 Eli Zaretskii <eliz@gnu.org> + + * w32.c (w32_delayed_load): Call DisableThreadLibraryCalls on the + DLL handle, to speed up thread startup. + +2014-03-25 Paul Eggert <eggert@cs.ucla.edu> + + Handle sigmask better with nested signal handlers (Bug#15561). + * atimer.c (sigmask_atimers): Remove. + Remaining use rewritten to use body of this function. + * atimer.c (block_atimers, unblock_atimers): + * callproc.c (block_child_signal, unblock_child_signal): + * sysdep.c (block_tty_out_signal, unblock_tty_out_signal): + New arg OLDSET. All callers changed. + * atimer.c (block_atimers, unblock_atimers): + * callproc.c (block_child_signal, unblock_child_signal): + * keyboard.c (handle_interrupt): + * sound.c (vox_configure, vox_close): + Restore the old signal mask rather than unilaterally clearing bits + from the mask, in case a handler is running within another + handler. All callers changed. + * lisp.h, process.c, process.h, term.c: + Adjust decls and callers to match new API. + * sysdep.c (emacs_sigaction_init): Don't worry about masking SIGFPE; + signal handlers aren't supposed to use floating point anyway. + (handle_arith_signal): Unblock just SIGFPE rather than clearing mask. + +2014-03-23 Daniel Colascione <dancol@dancol.org> + + Split gc_sweep into discrete functions for legibility and better + stack traces. + + * alloc.c (sweep_strings, sweep_vectors): Add NO_INLINE + (sweep_vectors): Fix typo in comment. + (sweep_conses, sweep_floats, sweep_intervals) + (sweep_symbols, sweep_misc, sweep_buffers): New functions. + (gc_sweep): Call new functions, to which existing functionality is + moved. + * fns.c (sweep_weak_hash_tables): Add NO_INLINE. + +2014-03-23 Juanma Barranquero <lekktu@gmail.com> + + * w32fns.c (Fw32_shell_execute): Declare `result' only on Cygwin. + +2014-03-23 Daniel Colascione <dancol@dancol.org> + + * xfns.c (create_frame_xic): Pass XNStatusAttributes to XCreateIC + only if xic_style calls for it. This change allows Emacs to work + with ibus. Also, don't leak resources if create_frame_xic fails, + and stop caching xic_style across different displays. + (supported_xim_styles): Make const. + (best_xim_style): Remove first parameter: it's always just + supported_xim_styles. Change to look at supported_xim_styles + directly. + +2014-03-23 Daniel Colascione <dancol@dancol.org> + + * term.c (init_tty): Rearrange condition for clarity; print + appropriate diagnostic. 2014-03-23 Daniel Colascione <dancol@dancol.org> * process.c (DATAGRAM_CONN_P): Don't underflow datagram_address array. (ASAN caught.) +2014-03-22 Glenn Morris <rgm@gnu.org> + + * callproc.c (init_callproc): In etc, look for NEWS rather than GNU. + +2014-03-22 Daniel Colascione <dancol@dancol.org> + + * process.c (conv_sockaddr_to_lisp): When extracting the string + names of AF_LOCAL sockets, stop before reading uninitialized memory. + 2014-03-21 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> Fix regression introduced by patch for Bug#10500. @@ -608,6 +1567,33 @@ constrain frame size in SW_SHOWMAXIMIZED case so we can truly maximize a frame for odd default fonts. +2014-03-21 Glenn Morris <rgm@gnu.org> + + * minibuf.c (history-length): Increase default from 30 to 100. + +2014-03-21 Daniel Colascione <dancol@dancol.org> + + * xterm.c (x_bitmap_icon): Stop reading the icon bitmap from disk + every time we switch to minibuffer. + + * alloc.c (lisp_align_malloc, allocate_string_data) + (allocate_vectorlike): Allow mmap allocation of lisp objects. + (pointers_fit_in_lispobj_p, mmap_lisp_allowed_p): New functions. + +2014-03-21 Eli Zaretskii <eliz@gnu.org> + + * w32fns.c (Fw32_shell_execute) [!CYGWIN]: Use ShellExecuteEx, to + support more "verbs". + +2014-03-21 Daniel Colascione <dancol@dancol.org> + + Always prohibit dumping a dumped Emacs. + + * emacs.c (might_dump): New variable. + (Fdump_emacs): Always prohibit dumping of dumped Emacs. + * lisp.h (might_dump): Declare. + * unexcw.c (unexec): Remove now-redundant multiple-dump detection code. + 2014-03-20 Paul Eggert <eggert@cs.ucla.edu> * doc.c (store_function_docstring): Fix pointer signedness mismatch. diff --git a/src/Makefile.in b/src/Makefile.in index 70e31b50946..c858220c432 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -77,6 +77,7 @@ C_SWITCH_MACHINE=@C_SWITCH_MACHINE@ C_SWITCH_SYSTEM=@C_SWITCH_SYSTEM@ GNUSTEP_CFLAGS=@GNUSTEP_CFLAGS@ +PNG_CFLAGS=@PNG_CFLAGS@ ## Define C_SWITCH_X_SITE to contain any special flags your compiler ## may need to deal with X Windows. For instance, if you've defined @@ -121,7 +122,7 @@ LIBS_SYSTEM=@LIBS_SYSTEM@ ## -lm, or empty. LIB_MATH=@LIB_MATH@ -## -lpthreads, or empty. +## -lpthread, or empty. LIB_PTHREAD=@LIB_PTHREAD@ LIBIMAGE=@LIBTIFF@ @LIBJPEG@ @LIBPNG@ @LIBGIF@ @LIBXPM@ @@ -230,6 +231,9 @@ XRANDR_CFLAGS = @XRANDR_CFLAGS@ XINERAMA_LIBS = @XINERAMA_LIBS@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ + ## widget.o if USE_X_TOOLKIT, otherwise empty. WIDGET_OBJ=@WIDGET_OBJ@ @@ -286,21 +290,14 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@ LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ -LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ - INTERVALS_H = dispextern.h intervals.h composite.h GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ RUN_TEMACS = ./temacs -## Invoke ../nt/addsection for MinGW, ":" elsewhere. -TEMACS_POST_LINK = @TEMACS_POST_LINK@ -ADDSECTION = @ADDSECTION@ +## Static heap size for temacs on MinGW. EMACS_HEAPSIZE = @EMACS_HEAPSIZE@ -MINGW_TEMACS_POST_LINK = \ - mv temacs$(EXEEXT) temacs.tmp; \ - ../nt/addsection temacs.tmp temacs$(EXEEXT) EMHEAP $(EMACS_HEAPSIZE) UNEXEC_OBJ = @UNEXEC_OBJ@ @@ -325,7 +322,8 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ -I$(lib) -I$(srcdir)/../lib \ $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ - $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) \ + $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ + $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) \ @@ -405,29 +403,29 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ - $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) \ + $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ - $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \ + $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \ $(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) all: emacs$(EXEEXT) $(OTHER_FILES) .PHONY: all $(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT) - cd ../leim && $(MAKE) $(MFLAGS) leim-list.el EMACS="$(bootstrap_exe)" + cd ../leim && $(MAKE) leim-list.el EMACS="$(bootstrap_exe)" $(srcdir)/macuvs.h $(lispsource)/international/charprop.el: \ bootstrap-emacs$(EXEEXT) - cd ../admin/unidata && $(MAKE) $(MFLAGS) all EMACS="../$(bootstrap_exe)" + cd ../admin/unidata && $(MAKE) all EMACS="../$(bootstrap_exe)" ## The dumped Emacs is as functional and more efficient than ## bootstrap-emacs, so we replace the latter with the former. ## Strictly speaking, emacs does not depend directly on all of $lisp, ## since not all pieces are used on all platforms. But DOC depends ## on all of $lisp, and emacs depends on DOC, so it is ok to use $lisp here. -emacs$(EXEEXT): temacs$(EXEEXT) $(ADDSECTION) \ +emacs$(EXEEXT): temacs$(EXEEXT) \ $(etc)/DOC $(lisp) $(leimdir)/leim-list.el \ $(lispsource)/international/charprop.el if test "$(CANNOT_DUMP)" = "yes"; then \ @@ -461,7 +459,7 @@ $(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(obj) $(lisp) $(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) `sed -n -e 's| \\\\||' -e 's|^[ ]*$$(lispsource)/||p' $(srcdir)/lisp.mk` $(libsrc)/make-docfile$(EXEEXT): - cd $(libsrc); $(MAKE) $(MFLAGS) make-docfile$(EXEEXT) + cd $(libsrc); $(MAKE) make-docfile$(EXEEXT) buildobj.h: Makefile for i in $(ALLOBJS); do \ @@ -493,7 +491,6 @@ temacs$(EXEEXT): $(LIBXMENU) $(ALLOBJS) \ $(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \ -o temacs $(ALLOBJS) $(lib)/libgnu.a $(W32_RES_LINK) $(LIBES) $(MKDIR_P) $(etc) - $(TEMACS_POST_LINK) test "$(CANNOT_DUMP)" = "yes" || \ test "X$(PAXCTL)" = X || $(PAXCTL) -r temacs$(EXEEXT) test "$(CANNOT_DUMP)" = "yes" || test -z "$(SETFATTR)" || \ @@ -502,13 +499,9 @@ temacs$(EXEEXT): $(LIBXMENU) $(ALLOBJS) \ ## The following oldxmenu-related rules are only (possibly) used if ## HAVE_X11 && !USE_GTK, but there is no harm in always defining them. $(lwlibdir)/liblw.a: $(config_h) globals.h lisp.h FORCE - cd $(lwlibdir) && \ - $(MAKE) $(MFLAGS) CC='$(CC)' CFLAGS='$(CFLAGS)' MAKE='$(MAKE)' \ - liblw.a + cd $(lwlibdir) && $(MAKE) liblw.a $(oldXMenudir)/libXMenu11.a: FORCE - cd $(oldXMenudir) && \ - $(MAKE) $(MFLAGS) CC='$(CC)' CFLAGS='$(CFLAGS)' MAKE='$(MAKE)' \ - libXMenu11.a + cd $(oldXMenudir) && $(MAKE) libXMenu11.a FORCE: .PHONY: FORCE @@ -526,7 +519,7 @@ emacs.res: $(ntsource)/emacs.rc \ -o $@ $(ntsource)/emacs.rc ns-app: emacs$(EXEEXT) - cd ../nextstep && $(MAKE) $(MFLAGS) all + cd ../nextstep && $(MAKE) all .PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean .PHONY: versionclean extraclean @@ -624,7 +617,7 @@ tags: TAGS ../lisp/TAGS $(lwlibdir)/TAGS ## separately below. ## With GNU Make, we would just say "%.el : %.elc $(BOOTSTRAPEMACS)" .el.elc: - @cd ../lisp; $(MAKE) $(MFLAGS) compile-onefile \ + @cd ../lisp && $(MAKE) compile-onefile \ THEFILE=$< EMACS="$(bootstrap_exe)" ## Since the .el.elc rule cannot specify an extra dependency, we do it here. @@ -636,12 +629,12 @@ $(lisp): $(BOOTSTRAPEMACS) VCSWITNESS = $(lispsource)/loaddefs.el: $(BOOTSTRAPEMACS) $(VCSWITNESS) - cd ../lisp; $(MAKE) $(MFLAGS) autoloads EMACS="$(bootstrap_exe)" + cd ../lisp && $(MAKE) autoloads EMACS="$(bootstrap_exe)" ## Dump an Emacs executable named bootstrap-emacs containing the ## files from loadup.el in source form. bootstrap-emacs$(EXEEXT): temacs$(EXEEXT) - cd ../lisp; $(MAKE) $(MFLAGS) update-subdirs + cd ../lisp && $(MAKE) update-subdirs if test "$(CANNOT_DUMP)" = "yes"; then \ rm -f bootstrap-emacs$(EXEEXT); \ ln temacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \ @@ -651,7 +644,7 @@ bootstrap-emacs$(EXEEXT): temacs$(EXEEXT) mv -f emacs$(EXEEXT) bootstrap-emacs$(EXEEXT); \ fi @: Compile some files earlier to speed up further compilation. - cd ../lisp; $(MAKE) $(MFLAGS) compile-first EMACS="$(bootstrap_exe)" + cd ../lisp && $(MAKE) compile-first EMACS="$(bootstrap_exe)" ## Insert either autodeps.mk (if AUTO_DEPEND), else deps.mk. @deps_frag@ diff --git a/src/alloc.c b/src/alloc.c index a3f3f5478cb..e2213db853d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -47,6 +47,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif /* HAVE_WINDOW_SYSTEM */ #include <verify.h> +#include <execinfo.h> /* For backtrace. */ #if (defined ENABLE_CHECKING \ && defined HAVE_VALGRIND_VALGRIND_H \ @@ -192,6 +193,35 @@ static ptrdiff_t pure_bytes_used_non_lisp; const char *pending_malloc_warning; +#if 0 /* Normally, pointer sanity only on request... */ +#ifdef ENABLE_CHECKING +#define SUSPICIOUS_OBJECT_CHECKING 1 +#endif +#endif + +/* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC + bug is unresolved. */ +#define SUSPICIOUS_OBJECT_CHECKING 1 + +#ifdef SUSPICIOUS_OBJECT_CHECKING +struct suspicious_free_record +{ + void *suspicious_object; + void *backtrace[128]; +}; +static void *suspicious_objects[32]; +static int suspicious_object_index; +struct suspicious_free_record suspicious_free_history[64] EXTERNALLY_VISIBLE; +static int suspicious_free_history_index; +/* Find the first currently-monitored suspicious pointer in range + [begin,end) or NULL if no such pointer exists. */ +static void *find_suspicious_object_in_range (void *begin, void *end); +static void detect_suspicious_free (void *ptr); +#else +# define find_suspicious_object_in_range(begin, end) NULL +# define detect_suspicious_free(ptr) (void) +#endif + /* Maximum amount of C stack to save when a GC happens. */ #ifndef MAX_SAVE_STACK @@ -403,6 +433,23 @@ XFLOAT_INIT (Lisp_Object f, double n) XFLOAT (f)->u.data = n; } +static bool +pointers_fit_in_lispobj_p (void) +{ + return (UINTPTR_MAX <= VAL_MAX) || USE_LSB_TAG; +} + +static bool +mmap_lisp_allowed_p (void) +{ + /* If we can't store all memory addresses in our lisp objects, it's + risky to let the heap use mmap and give us addresses from all + over our address space. We also can't use mmap for lisp objects + if we might dump: unexec doesn't preserve the contents of mmaped + regions. */ + return pointers_fit_in_lispobj_p () && !might_dump; +} + /************************************************************************ Malloc @@ -1073,10 +1120,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) intptr_t aligned; /* int gets warning casting to 64-bit pointer. */ #ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. */ - mallopt (M_MMAP_MAX, 0); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, 0); #endif #ifdef USE_ALIGNED_ALLOC @@ -1097,8 +1142,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) ((void **) abase)[-1] = base; #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif #if ! USE_LSB_TAG @@ -1733,23 +1778,15 @@ allocate_string_data (struct Lisp_String *s, size_t size = offsetof (struct sblock, data) + needed; #ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. - - In case you think of allowing it in a dumped Emacs at the - cost of not being able to re-dump, there's another reason: - mmap'ed data typically have an address towards the top of the - address space, which won't fit into an EMACS_INT (at least on - 32-bit systems with the current tagging scheme). --fx */ - mallopt (M_MMAP_MAX, 0); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, 0); #endif b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif b->next_free = b->data; @@ -1810,6 +1847,7 @@ allocate_string_data (struct Lisp_String *s, /* Sweep and compact strings. */ +NO_INLINE /* For better stack traces */ static void sweep_strings (void) { @@ -2093,7 +2131,7 @@ bool_vector_fill (Lisp_Object a, Lisp_Object init) unsigned char *data = bool_vector_uchar_data (a); int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; ptrdiff_t nbytes = bool_vector_bytes (nbits); - int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); + int last_mask = ~ (~0u << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); memset (data, pattern, nbytes - 1); data[nbytes - 1] = pattern & last_mask; } @@ -2136,6 +2174,21 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) return bool_vector_fill (val, init); } +DEFUN ("bool-vector", Fbool_vector, Sbool_vector, 0, MANY, 0, + doc: /* Return a new bool-vector with specified arguments as elements. +Any number of arguments, even zero arguments, are allowed. +usage: (bool-vector &rest OBJECTS) */) + (ptrdiff_t nargs, Lisp_Object *args) +{ + ptrdiff_t i; + Lisp_Object vector; + + vector = make_uninit_bool_vector (nargs); + for (i = 0; i < nargs; i++) + bool_vector_set (vector, i, !NILP (args[i])); + + return vector; +} /* Make a string from NBYTES bytes at CONTENTS, and compute the number of characters from the contents. This string may be unibyte or @@ -2294,21 +2347,21 @@ make_formatted_string (char *buf, const char *format, ...) #define FLOAT_BLOCK_SIZE \ (((BLOCK_BYTES - sizeof (struct float_block *) \ /* The compiler might add padding at the end. */ \ - - (sizeof (struct Lisp_Float) - sizeof (int))) * CHAR_BIT) \ + - (sizeof (struct Lisp_Float) - sizeof (bits_word))) * CHAR_BIT) \ / (sizeof (struct Lisp_Float) * CHAR_BIT + 1)) #define GETMARKBIT(block,n) \ - (((block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ - >> ((n) % (sizeof (int) * CHAR_BIT))) \ + (((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \ + >> ((n) % BITS_PER_BITS_WORD)) \ & 1) #define SETMARKBIT(block,n) \ - (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ - |= 1 << ((n) % (sizeof (int) * CHAR_BIT)) + ((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \ + |= (bits_word) 1 << ((n) % BITS_PER_BITS_WORD)) #define UNSETMARKBIT(block,n) \ - (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ - &= ~(1 << ((n) % (sizeof (int) * CHAR_BIT))) + ((block)->gcmarkbits[(n) / BITS_PER_BITS_WORD] \ + &= ~((bits_word) 1 << ((n) % BITS_PER_BITS_WORD))) #define FLOAT_BLOCK(fptr) \ ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))) @@ -2320,7 +2373,7 @@ struct float_block { /* Place `floats' at the beginning, to ease up FLOAT_INDEX's job. */ struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; - int gcmarkbits[1 + FLOAT_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)]; + bits_word gcmarkbits[1 + FLOAT_BLOCK_SIZE / BITS_PER_BITS_WORD]; struct float_block *next; }; @@ -2401,7 +2454,7 @@ make_float (double float_value) #define CONS_BLOCK_SIZE \ (((BLOCK_BYTES - sizeof (struct cons_block *) \ /* The compiler might add padding at the end. */ \ - - (sizeof (struct Lisp_Cons) - sizeof (int))) * CHAR_BIT) \ + - (sizeof (struct Lisp_Cons) - sizeof (bits_word))) * CHAR_BIT) \ / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1)) #define CONS_BLOCK(fptr) \ @@ -2414,7 +2467,7 @@ struct cons_block { /* Place `conses' at the beginning, to ease up CONS_INDEX's job. */ struct Lisp_Cons conses[CONS_BLOCK_SIZE]; - int gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)]; + bits_word gcmarkbits[1 + CONS_BLOCK_SIZE / BITS_PER_BITS_WORD]; struct cons_block *next; }; @@ -2651,20 +2704,16 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, pointer cannot be tagged, represent it with a Lisp 0. Usually you don't want to touch this. */ -enum { TAGGABLE_NULL = (DATA_SEG_BITS & ~VALMASK) == 0 }; - static struct Lisp_Vector * next_vector (struct Lisp_Vector *v) { - if (! TAGGABLE_NULL && EQ (v->contents[0], make_number (0))) - return 0; return XUNTAG (v->contents[0], 0); } static void set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p) { - v->contents[0] = TAGGABLE_NULL || p ? make_lisp_ptr (p, 0) : make_number (0); + v->contents[0] = make_lisp_ptr (p, 0); } /* This value is balanced well enough to avoid too much internal overhead @@ -2920,6 +2969,7 @@ vector_nbytes (struct Lisp_Vector *v) static void cleanup_vector (struct Lisp_Vector *vector) { + detect_suspicious_free (vector); if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT) && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX)) @@ -2939,6 +2989,7 @@ cleanup_vector (struct Lisp_Vector *vector) /* Reclaim space used by unmarked vectors. */ +NO_INLINE /* For better stack traces */ static void sweep_vectors (void) { @@ -2993,7 +3044,7 @@ sweep_vectors (void) if (vector == (struct Lisp_Vector *) block->data && !VECTOR_IN_BLOCK (next, block)) - /* This block should be freed because all of it's + /* This block should be freed because all of its space was coalesced into the only free vector. */ free_this_block = 1; else @@ -3063,10 +3114,8 @@ allocate_vectorlike (ptrdiff_t len) size_t nbytes = header_size + len * word_size; #ifdef DOUG_LEA_MALLOC - /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed - because mapped region contents are not preserved in - a dumped Emacs. */ - mallopt (M_MMAP_MAX, 0); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, 0); #endif if (nbytes <= VBLOCK_BYTES_MAX) @@ -3083,10 +3132,13 @@ allocate_vectorlike (ptrdiff_t len) } #ifdef DOUG_LEA_MALLOC - /* Back to a reasonable maximum of mmap'ed areas. */ - mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); + if (!mmap_lisp_allowed_p ()) + mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif + if (find_suspicious_object_in_range (p, (char *) p + nbytes)) + emacs_abort (); + consing_since_gc += nbytes; vector_cells_consed += len; } @@ -3741,7 +3793,7 @@ memory_full (size_t nbytes) memory_full_cons_threshold = sizeof (struct cons_block); /* The first time we get here, free the spare memory. */ - for (i = 0; i < sizeof (spare_memory) / sizeof (char *); i++) + for (i = 0; i < ARRAYELTS (spare_memory); i++) if (spare_memory[i]) { if (i == 0) @@ -4502,6 +4554,15 @@ mark_maybe_object (Lisp_Object obj) } } +/* Return true if P can point to Lisp data, and false otherwise. + USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. + Otherwise, assume that Lisp data is aligned on even addresses. */ + +static bool +maybe_lisp_pointer (void *p) +{ + return !((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2)); +} /* If P points to Lisp data, mark that as live if it isn't already marked. */ @@ -4516,10 +4577,7 @@ mark_maybe_pointer (void *p) VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p)); #endif - /* Quickly rule out some values which can't point to Lisp data. - USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. - Otherwise, assume that Lisp data is aligned on even addresses. */ - if ((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2)) + if (!maybe_lisp_pointer (p)) return; m = mem_find (p); @@ -4831,61 +4889,8 @@ dump_zombies (void) from the stack start. */ static void -mark_stack (void) +mark_stack (void *end) { - void *end; - -#ifdef HAVE___BUILTIN_UNWIND_INIT - /* Force callee-saved registers and register windows onto the stack. - This is the preferred method if available, obviating the need for - machine dependent methods. */ - __builtin_unwind_init (); - end = &end; -#else /* not HAVE___BUILTIN_UNWIND_INIT */ -#ifndef GC_SAVE_REGISTERS_ON_STACK - /* jmp_buf may not be aligned enough on darwin-ppc64 */ - union aligned_jmpbuf { - Lisp_Object o; - sys_jmp_buf j; - } j; - volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; -#endif - /* This trick flushes the register windows so that all the state of - the process is contained in the stack. */ - /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is - needed on ia64 too. See mach_dep.c, where it also says inline - assembler doesn't work with relevant proprietary compilers. */ -#ifdef __sparc__ -#if defined (__sparc64__) && defined (__FreeBSD__) - /* FreeBSD does not have a ta 3 handler. */ - asm ("flushw"); -#else - asm ("ta 3"); -#endif -#endif - - /* Save registers that we need to see on the stack. We need to see - registers used to hold register variables and registers used to - pass parameters. */ -#ifdef GC_SAVE_REGISTERS_ON_STACK - GC_SAVE_REGISTERS_ON_STACK (end); -#else /* not GC_SAVE_REGISTERS_ON_STACK */ - -#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that - setjmp will definitely work, test it - and print a message with the result - of the test. */ - if (!setjmp_tested_p) - { - setjmp_tested_p = 1; - test_setjmp (); - } -#endif /* GC_SETJMP_WORKS */ - - sys_setjmp (j.j); - end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; -#endif /* not GC_SAVE_REGISTERS_ON_STACK */ -#endif /* not HAVE___BUILTIN_UNWIND_INIT */ /* This assumes that the stack is a contiguous region in memory. If that's not the case, something has to be done here to iterate @@ -5015,9 +5020,34 @@ valid_lisp_object_p (Lisp_Object obj) #endif } +/* If GC_MARK_STACK, return 1 if STR is a relocatable data of Lisp_String + (i.e. there is a non-pure Lisp_Object X so that SDATA (X) == STR) and 0 + if not. Otherwise we can't rely on valid_lisp_object_p and return -1. + This function is slow and should be used for debugging purposes. */ +int +relocatable_string_data_p (const char *str) +{ + if (PURE_POINTER_P (str)) + return 0; +#if GC_MARK_STACK + if (str) + { + struct sdata *sdata + = (struct sdata *) (str - offsetof (struct sdata, data)); + + if (valid_pointer_p (sdata) + && valid_pointer_p (sdata->string) + && maybe_lisp_pointer (sdata->string)) + return (valid_lisp_object_p + (make_lisp_ptr (sdata->string, Lisp_String)) + && (const char *) sdata->string->data == str); + } + return 0; +#endif /* GC_MARK_STACK */ + return -1; +} - /*********************************************************************** Pure Storage Management ***********************************************************************/ @@ -5493,22 +5523,15 @@ mark_pinned_symbols (void) } } -DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", - doc: /* Reclaim storage for Lisp objects no longer needed. -Garbage collection happens automatically if you cons more than -`gc-cons-threshold' bytes of Lisp data since previous garbage collection. -`garbage-collect' normally returns a list with info on amount of space in use, -where each entry has the form (NAME SIZE USED FREE), where: -- NAME is a symbol describing the kind of objects this entry represents, -- SIZE is the number of bytes used by each one, -- USED is the number of those objects that were found live in the heap, -- FREE is the number of those objects that are not live but that Emacs - keeps around for future allocations (maybe because it does not know how - to return them to the OS). -However, if there was overflow in pure space, `garbage-collect' -returns nil, because real GC can't be done. -See Info node `(elisp)Garbage Collection'. */) - (void) +/* Subroutine of Fgarbage_collect that does most of the work. It is a + separate function so that we could limit mark_stack in searching + the stack frames below this function, thus avoiding the rare cases + where mark_stack finds values that look like live Lisp objects on + portions of stack that couldn't possibly contain such live objects. + For more details of this, see the discussion at + http://lists.gnu.org/archive/html/emacs-devel/2014-05/msg00270.html. */ +static Lisp_Object +garbage_collect_1 (void *end) { struct buffer *nextb; char stack_top_variable; @@ -5606,7 +5629,7 @@ See Info node `(elisp)Garbage Collection'. */) #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS) - mark_stack (); + mark_stack (end); #else { register struct gcpro *tail; @@ -5629,7 +5652,7 @@ See Info node `(elisp)Garbage Collection'. */) #endif #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES - mark_stack (); + mark_stack (end); #endif /* Everything is now marked, except for the data in font caches @@ -5789,6 +5812,87 @@ See Info node `(elisp)Garbage Collection'. */) return retval; } +DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", + doc: /* Reclaim storage for Lisp objects no longer needed. +Garbage collection happens automatically if you cons more than +`gc-cons-threshold' bytes of Lisp data since previous garbage collection. +`garbage-collect' normally returns a list with info on amount of space in use, +where each entry has the form (NAME SIZE USED FREE), where: +- NAME is a symbol describing the kind of objects this entry represents, +- SIZE is the number of bytes used by each one, +- USED is the number of those objects that were found live in the heap, +- FREE is the number of those objects that are not live but that Emacs + keeps around for future allocations (maybe because it does not know how + to return them to the OS). +However, if there was overflow in pure space, `garbage-collect' +returns nil, because real GC can't be done. +See Info node `(elisp)Garbage Collection'. */) + (void) +{ +#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ + || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS \ + || GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES) + void *end; + +#ifdef HAVE___BUILTIN_UNWIND_INIT + /* Force callee-saved registers and register windows onto the stack. + This is the preferred method if available, obviating the need for + machine dependent methods. */ + __builtin_unwind_init (); + end = &end; +#else /* not HAVE___BUILTIN_UNWIND_INIT */ +#ifndef GC_SAVE_REGISTERS_ON_STACK + /* jmp_buf may not be aligned enough on darwin-ppc64 */ + union aligned_jmpbuf { + Lisp_Object o; + sys_jmp_buf j; + } j; + volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; +#endif + /* This trick flushes the register windows so that all the state of + the process is contained in the stack. */ + /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is + needed on ia64 too. See mach_dep.c, where it also says inline + assembler doesn't work with relevant proprietary compilers. */ +#ifdef __sparc__ +#if defined (__sparc64__) && defined (__FreeBSD__) + /* FreeBSD does not have a ta 3 handler. */ + asm ("flushw"); +#else + asm ("ta 3"); +#endif +#endif + + /* Save registers that we need to see on the stack. We need to see + registers used to hold register variables and registers used to + pass parameters. */ +#ifdef GC_SAVE_REGISTERS_ON_STACK + GC_SAVE_REGISTERS_ON_STACK (end); +#else /* not GC_SAVE_REGISTERS_ON_STACK */ + +#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that + setjmp will definitely work, test it + and print a message with the result + of the test. */ + if (!setjmp_tested_p) + { + setjmp_tested_p = 1; + test_setjmp (); + } +#endif /* GC_SETJMP_WORKS */ + + sys_setjmp (j.j); + end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; +#endif /* not GC_SAVE_REGISTERS_ON_STACK */ +#endif /* not HAVE___BUILTIN_UNWIND_INIT */ + return garbage_collect_1 (end); +#elif (GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE) + /* Old GCPROs-based method without stack marking. */ + return garbage_collect_1 (NULL); +#else + emacs_abort (); +#endif /* GC_MARK_STACK */ +} /* Mark Lisp objects in glyph matrix MATRIX. Currently the only interesting objects referenced from glyphs are strings. */ @@ -5877,6 +5981,19 @@ mark_char_table (struct Lisp_Vector *ptr) } } +NO_INLINE /* To reduce stack depth in mark_object. */ +static Lisp_Object +mark_compiled (struct Lisp_Vector *ptr) +{ + int i, size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; + + VECTOR_MARK (ptr); + for (i = 0; i < size; i++) + if (i != COMPILED_CONSTANTS) + mark_object (ptr->contents[i]); + return size > COMPILED_CONSTANTS ? ptr->contents[COMPILED_CONSTANTS] : Qnil; +} + /* Mark the chain of overlays starting at PTR. */ static void @@ -5917,6 +6034,7 @@ mark_buffer (struct buffer *buffer) /* Mark Lisp faces in the face cache C. */ +NO_INLINE /* To reduce stack depth in mark_object. */ static void mark_face_cache (struct face_cache *c) { @@ -5939,6 +6057,48 @@ mark_face_cache (struct face_cache *c) } } +NO_INLINE /* To reduce stack depth in mark_object. */ +static void +mark_localized_symbol (struct Lisp_Symbol *ptr) +{ + struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); + Lisp_Object where = blv->where; + /* If the value is set up for a killed buffer or deleted + frame, restore its global binding. If the value is + forwarded to a C variable, either it's not a Lisp_Object + var, or it's staticpro'd already. */ + if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) + || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) + swap_in_global_binding (ptr); + mark_object (blv->where); + mark_object (blv->valcell); + mark_object (blv->defcell); +} + +NO_INLINE /* To reduce stack depth in mark_object. */ +static void +mark_save_value (struct Lisp_Save_Value *ptr) +{ + /* If `save_type' is zero, `data[0].pointer' is the address + of a memory area containing `data[1].integer' potential + Lisp_Objects. */ + if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY) + { + Lisp_Object *p = ptr->data[0].pointer; + ptrdiff_t nelt; + for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++) + mark_maybe_object (*p); + } + else + { + /* Find Lisp_Objects in `data[N]' slots and mark them. */ + int i; + for (i = 0; i < SAVE_VALUE_SLOTS; i++) + if (save_type (ptr, i) == SAVE_OBJECT) + mark_object (ptr->data[i].object); + } +} + /* Remove killed buffers or items whose car is a killed buffer from LIST, and mark other items. Return changed LIST, which is marked. */ @@ -5966,7 +6126,13 @@ mark_discard_killed_buffers (Lisp_Object list) return list; } -/* Determine type of generic Lisp_Object and mark it accordingly. */ +/* Determine type of generic Lisp_Object and mark it accordingly. + + This function implements a straightforward depth-first marking + algorithm and so the recursion depth may be very high (a few + tens of thousands is not uncommon). To minimize stack usage, + a few cold paths are moved out to NO_INLINE functions above. + In general, inlining them doesn't help you to gain more speed. */ void mark_object (Lisp_Object arg) @@ -6083,22 +6249,13 @@ mark_object (Lisp_Object arg) break; case PVEC_COMPILED: - { /* We could treat this just like a vector, but it is better - to save the COMPILED_CONSTANTS element for last and avoid - recursion there. */ - int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; - - VECTOR_MARK (ptr); - for (i = 0; i < size; i++) - if (i != COMPILED_CONSTANTS) - mark_object (ptr->contents[i]); - if (size > COMPILED_CONSTANTS) - { - obj = ptr->contents[COMPILED_CONSTANTS]; - goto loop; - } - } + /* Although we could treat this just like a vector, mark_compiled + returns the COMPILED_CONSTANTS element, which is marked at the + next iteration of goto-loop here. This is done to avoid a few + recursive calls to mark_object. */ + obj = mark_compiled (ptr); + if (!NILP (obj)) + goto loop; break; case PVEC_FRAME: @@ -6186,12 +6343,13 @@ mark_object (Lisp_Object arg) case Lisp_Symbol: { register struct Lisp_Symbol *ptr = XSYMBOL (obj); - struct Lisp_Symbol *ptrx; - + nextsym: if (ptr->gcmarkbit) break; CHECK_ALLOCATED_AND_LIVE (live_symbol_p); ptr->gcmarkbit = 1; + /* Attempt to catch bogus objects. */ + eassert (valid_lisp_object_p (ptr->function) >= 1); mark_object (ptr->function); mark_object (ptr->plist); switch (ptr->redirect) @@ -6205,21 +6363,8 @@ mark_object (Lisp_Object arg) break; } case SYMBOL_LOCALIZED: - { - struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); - Lisp_Object where = blv->where; - /* If the value is set up for a killed buffer or deleted - frame, restore it's global binding. If the value is - forwarded to a C variable, either it's not a Lisp_Object - var, or it's staticpro'd already. */ - if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) - || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) - swap_in_global_binding (ptr); - mark_object (blv->where); - mark_object (blv->valcell); - mark_object (blv->defcell); - break; - } + mark_localized_symbol (ptr); + break; case SYMBOL_FORWARDED: /* If the value is forwarded to a buffer or keyboard field, these are marked when we see the corresponding object. @@ -6231,14 +6376,10 @@ mark_object (Lisp_Object arg) if (!PURE_POINTER_P (XSTRING (ptr->name))) MARK_STRING (XSTRING (ptr->name)); MARK_INTERVAL_TREE (string_intervals (ptr->name)); - + /* Inner loop to mark next symbol in this bucket, if any. */ ptr = ptr->next; if (ptr) - { - ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun. */ - XSETSYMBOL (obj, ptrx); - goto loop; - } + goto nextsym; } break; @@ -6259,27 +6400,7 @@ mark_object (Lisp_Object arg) case Lisp_Misc_Save_Value: XMISCANY (obj)->gcmarkbit = 1; - { - struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); - /* If `save_type' is zero, `data[0].pointer' is the address - of a memory area containing `data[1].integer' potential - Lisp_Objects. */ - if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY) - { - Lisp_Object *p = ptr->data[0].pointer; - ptrdiff_t nelt; - for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++) - mark_maybe_object (*p); - } - else - { - /* Find Lisp_Objects in `data[N]' slots and mark them. */ - int i; - for (i = 0; i < SAVE_VALUE_SLOTS; i++) - if (save_type (ptr, i) == SAVE_OBJECT) - mark_object (ptr->data[i].object); - } - } + mark_save_value (XSAVE_VALUE (obj)); break; case Lisp_Misc_Overlay: @@ -6399,330 +6520,348 @@ survives_gc_p (Lisp_Object obj) -/* Sweep: find all structures not marked, and free them. */ +NO_INLINE /* For better stack traces */ static void -gc_sweep (void) +sweep_conses (void) { - /* Remove or mark entries in weak hash tables. - This must be done before any object is unmarked. */ - sweep_weak_hash_tables (); + struct cons_block *cblk; + struct cons_block **cprev = &cons_block; + int lim = cons_block_index; + EMACS_INT num_free = 0, num_used = 0; - sweep_strings (); - check_string_bytes (!noninteractive); - - /* Put all unmarked conses on free list. */ - { - register struct cons_block *cblk; - struct cons_block **cprev = &cons_block; - register int lim = cons_block_index; - EMACS_INT num_free = 0, num_used = 0; + cons_free_list = 0; - cons_free_list = 0; - - for (cblk = cons_block; cblk; cblk = *cprev) - { - register int i = 0; - int this_free = 0; - int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT; + for (cblk = cons_block; cblk; cblk = *cprev) + { + int i = 0; + int this_free = 0; + int ilim = (lim + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD; - /* Scan the mark bits an int at a time. */ - for (i = 0; i < ilim; i++) - { - if (cblk->gcmarkbits[i] == -1) - { - /* Fast path - all cons cells for this int are marked. */ - cblk->gcmarkbits[i] = 0; - num_used += BITS_PER_INT; - } - else - { - /* Some cons cells for this int are not marked. - Find which ones, and free them. */ - int start, pos, stop; - - start = i * BITS_PER_INT; - stop = lim - start; - if (stop > BITS_PER_INT) - stop = BITS_PER_INT; - stop += start; - - for (pos = start; pos < stop; pos++) - { - if (!CONS_MARKED_P (&cblk->conses[pos])) - { - this_free++; - cblk->conses[pos].u.chain = cons_free_list; - cons_free_list = &cblk->conses[pos]; + /* Scan the mark bits an int at a time. */ + for (i = 0; i < ilim; i++) + { + if (cblk->gcmarkbits[i] == BITS_WORD_MAX) + { + /* Fast path - all cons cells for this int are marked. */ + cblk->gcmarkbits[i] = 0; + num_used += BITS_PER_BITS_WORD; + } + else + { + /* Some cons cells for this int are not marked. + Find which ones, and free them. */ + int start, pos, stop; + + start = i * BITS_PER_BITS_WORD; + stop = lim - start; + if (stop > BITS_PER_BITS_WORD) + stop = BITS_PER_BITS_WORD; + stop += start; + + for (pos = start; pos < stop; pos++) + { + if (!CONS_MARKED_P (&cblk->conses[pos])) + { + this_free++; + cblk->conses[pos].u.chain = cons_free_list; + cons_free_list = &cblk->conses[pos]; #if GC_MARK_STACK - cons_free_list->car = Vdead; + cons_free_list->car = Vdead; #endif - } - else - { - num_used++; - CONS_UNMARK (&cblk->conses[pos]); - } - } - } - } + } + else + { + num_used++; + CONS_UNMARK (&cblk->conses[pos]); + } + } + } + } - lim = CONS_BLOCK_SIZE; - /* If this block contains only free conses and we have already - seen more than two blocks worth of free conses then deallocate - this block. */ - if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE) - { - *cprev = cblk->next; - /* Unhook from the free list. */ - cons_free_list = cblk->conses[0].u.chain; - lisp_align_free (cblk); - } - else - { - num_free += this_free; - cprev = &cblk->next; - } - } - total_conses = num_used; - total_free_conses = num_free; - } + lim = CONS_BLOCK_SIZE; + /* If this block contains only free conses and we have already + seen more than two blocks worth of free conses then deallocate + this block. */ + if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE) + { + *cprev = cblk->next; + /* Unhook from the free list. */ + cons_free_list = cblk->conses[0].u.chain; + lisp_align_free (cblk); + } + else + { + num_free += this_free; + cprev = &cblk->next; + } + } + total_conses = num_used; + total_free_conses = num_free; +} - /* Put all unmarked floats on free list. */ - { - register struct float_block *fblk; - struct float_block **fprev = &float_block; - register int lim = float_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_floats (void) +{ + register struct float_block *fblk; + struct float_block **fprev = &float_block; + register int lim = float_block_index; + EMACS_INT num_free = 0, num_used = 0; - float_free_list = 0; + float_free_list = 0; - for (fblk = float_block; fblk; fblk = *fprev) - { - register int i; - int this_free = 0; - for (i = 0; i < lim; i++) - if (!FLOAT_MARKED_P (&fblk->floats[i])) - { - this_free++; - fblk->floats[i].u.chain = float_free_list; - float_free_list = &fblk->floats[i]; - } - else - { - num_used++; - FLOAT_UNMARK (&fblk->floats[i]); - } - lim = FLOAT_BLOCK_SIZE; - /* If this block contains only free floats and we have already - seen more than two blocks worth of free floats then deallocate - this block. */ - if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE) - { - *fprev = fblk->next; - /* Unhook from the free list. */ - float_free_list = fblk->floats[0].u.chain; - lisp_align_free (fblk); - } - else - { - num_free += this_free; - fprev = &fblk->next; - } - } - total_floats = num_used; - total_free_floats = num_free; - } + for (fblk = float_block; fblk; fblk = *fprev) + { + register int i; + int this_free = 0; + for (i = 0; i < lim; i++) + if (!FLOAT_MARKED_P (&fblk->floats[i])) + { + this_free++; + fblk->floats[i].u.chain = float_free_list; + float_free_list = &fblk->floats[i]; + } + else + { + num_used++; + FLOAT_UNMARK (&fblk->floats[i]); + } + lim = FLOAT_BLOCK_SIZE; + /* If this block contains only free floats and we have already + seen more than two blocks worth of free floats then deallocate + this block. */ + if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE) + { + *fprev = fblk->next; + /* Unhook from the free list. */ + float_free_list = fblk->floats[0].u.chain; + lisp_align_free (fblk); + } + else + { + num_free += this_free; + fprev = &fblk->next; + } + } + total_floats = num_used; + total_free_floats = num_free; +} - /* Put all unmarked intervals on free list. */ - { - register struct interval_block *iblk; - struct interval_block **iprev = &interval_block; - register int lim = interval_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_intervals (void) +{ + register struct interval_block *iblk; + struct interval_block **iprev = &interval_block; + register int lim = interval_block_index; + EMACS_INT num_free = 0, num_used = 0; - interval_free_list = 0; + interval_free_list = 0; - for (iblk = interval_block; iblk; iblk = *iprev) - { - register int i; - int this_free = 0; + for (iblk = interval_block; iblk; iblk = *iprev) + { + register int i; + int this_free = 0; - for (i = 0; i < lim; i++) - { - if (!iblk->intervals[i].gcmarkbit) - { - set_interval_parent (&iblk->intervals[i], interval_free_list); - interval_free_list = &iblk->intervals[i]; - this_free++; - } - else - { - num_used++; - iblk->intervals[i].gcmarkbit = 0; - } - } - lim = INTERVAL_BLOCK_SIZE; - /* If this block contains only free intervals and we have already - seen more than two blocks worth of free intervals then - deallocate this block. */ - if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE) - { - *iprev = iblk->next; - /* Unhook from the free list. */ - interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); - lisp_free (iblk); - } - else - { - num_free += this_free; - iprev = &iblk->next; - } - } - total_intervals = num_used; - total_free_intervals = num_free; - } + for (i = 0; i < lim; i++) + { + if (!iblk->intervals[i].gcmarkbit) + { + set_interval_parent (&iblk->intervals[i], interval_free_list); + interval_free_list = &iblk->intervals[i]; + this_free++; + } + else + { + num_used++; + iblk->intervals[i].gcmarkbit = 0; + } + } + lim = INTERVAL_BLOCK_SIZE; + /* If this block contains only free intervals and we have already + seen more than two blocks worth of free intervals then + deallocate this block. */ + if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE) + { + *iprev = iblk->next; + /* Unhook from the free list. */ + interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); + lisp_free (iblk); + } + else + { + num_free += this_free; + iprev = &iblk->next; + } + } + total_intervals = num_used; + total_free_intervals = num_free; +} - /* Put all unmarked symbols on free list. */ - { - register struct symbol_block *sblk; - struct symbol_block **sprev = &symbol_block; - register int lim = symbol_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_symbols (void) +{ + register struct symbol_block *sblk; + struct symbol_block **sprev = &symbol_block; + register int lim = symbol_block_index; + EMACS_INT num_free = 0, num_used = 0; - symbol_free_list = NULL; + symbol_free_list = NULL; - for (sblk = symbol_block; sblk; sblk = *sprev) - { - int this_free = 0; - union aligned_Lisp_Symbol *sym = sblk->symbols; - union aligned_Lisp_Symbol *end = sym + lim; + for (sblk = symbol_block; sblk; sblk = *sprev) + { + int this_free = 0; + union aligned_Lisp_Symbol *sym = sblk->symbols; + union aligned_Lisp_Symbol *end = sym + lim; - for (; sym < end; ++sym) - { - if (!sym->s.gcmarkbit) - { - if (sym->s.redirect == SYMBOL_LOCALIZED) - xfree (SYMBOL_BLV (&sym->s)); - sym->s.next = symbol_free_list; - symbol_free_list = &sym->s; + for (; sym < end; ++sym) + { + if (!sym->s.gcmarkbit) + { + if (sym->s.redirect == SYMBOL_LOCALIZED) + xfree (SYMBOL_BLV (&sym->s)); + sym->s.next = symbol_free_list; + symbol_free_list = &sym->s; #if GC_MARK_STACK - symbol_free_list->function = Vdead; + symbol_free_list->function = Vdead; #endif - ++this_free; - } - else - { - ++num_used; - eassert (!STRING_MARKED_P (XSTRING (sym->s.name))); - sym->s.gcmarkbit = 0; - } - } + ++this_free; + } + else + { + ++num_used; + sym->s.gcmarkbit = 0; + /* Attempt to catch bogus objects. */ + eassert (valid_lisp_object_p (sym->s.function) >= 1); + } + } - lim = SYMBOL_BLOCK_SIZE; - /* If this block contains only free symbols and we have already - seen more than two blocks worth of free symbols then deallocate - this block. */ - if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE) - { - *sprev = sblk->next; - /* Unhook from the free list. */ - symbol_free_list = sblk->symbols[0].s.next; - lisp_free (sblk); - } - else - { - num_free += this_free; - sprev = &sblk->next; - } - } - total_symbols = num_used; - total_free_symbols = num_free; - } + lim = SYMBOL_BLOCK_SIZE; + /* If this block contains only free symbols and we have already + seen more than two blocks worth of free symbols then deallocate + this block. */ + if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE) + { + *sprev = sblk->next; + /* Unhook from the free list. */ + symbol_free_list = sblk->symbols[0].s.next; + lisp_free (sblk); + } + else + { + num_free += this_free; + sprev = &sblk->next; + } + } + total_symbols = num_used; + total_free_symbols = num_free; +} - /* Put all unmarked misc's on free list. - For a marker, first unchain it from the buffer it points into. */ - { - register struct marker_block *mblk; - struct marker_block **mprev = &marker_block; - register int lim = marker_block_index; - EMACS_INT num_free = 0, num_used = 0; +NO_INLINE /* For better stack traces */ +static void +sweep_misc (void) +{ + register struct marker_block *mblk; + struct marker_block **mprev = &marker_block; + register int lim = marker_block_index; + EMACS_INT num_free = 0, num_used = 0; - marker_free_list = 0; + /* Put all unmarked misc's on free list. For a marker, first + unchain it from the buffer it points into. */ - for (mblk = marker_block; mblk; mblk = *mprev) - { - register int i; - int this_free = 0; + marker_free_list = 0; - for (i = 0; i < lim; i++) - { - if (!mblk->markers[i].m.u_any.gcmarkbit) - { - if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) - unchain_marker (&mblk->markers[i].m.u_marker); - /* Set the type of the freed object to Lisp_Misc_Free. - We could leave the type alone, since nobody checks it, - but this might catch bugs faster. */ - mblk->markers[i].m.u_marker.type = Lisp_Misc_Free; - mblk->markers[i].m.u_free.chain = marker_free_list; - marker_free_list = &mblk->markers[i].m; - this_free++; - } - else - { - num_used++; - mblk->markers[i].m.u_any.gcmarkbit = 0; - } - } - lim = MARKER_BLOCK_SIZE; - /* If this block contains only free markers and we have already - seen more than two blocks worth of free markers then deallocate - this block. */ - if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) - { - *mprev = mblk->next; - /* Unhook from the free list. */ - marker_free_list = mblk->markers[0].m.u_free.chain; - lisp_free (mblk); - } - else - { - num_free += this_free; - mprev = &mblk->next; - } - } + for (mblk = marker_block; mblk; mblk = *mprev) + { + register int i; + int this_free = 0; - total_markers = num_used; - total_free_markers = num_free; - } + for (i = 0; i < lim; i++) + { + if (!mblk->markers[i].m.u_any.gcmarkbit) + { + if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) + unchain_marker (&mblk->markers[i].m.u_marker); + /* Set the type of the freed object to Lisp_Misc_Free. + We could leave the type alone, since nobody checks it, + but this might catch bugs faster. */ + mblk->markers[i].m.u_marker.type = Lisp_Misc_Free; + mblk->markers[i].m.u_free.chain = marker_free_list; + marker_free_list = &mblk->markers[i].m; + this_free++; + } + else + { + num_used++; + mblk->markers[i].m.u_any.gcmarkbit = 0; + } + } + lim = MARKER_BLOCK_SIZE; + /* If this block contains only free markers and we have already + seen more than two blocks worth of free markers then deallocate + this block. */ + if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) + { + *mprev = mblk->next; + /* Unhook from the free list. */ + marker_free_list = mblk->markers[0].m.u_free.chain; + lisp_free (mblk); + } + else + { + num_free += this_free; + mprev = &mblk->next; + } + } - /* Free all unmarked buffers */ - { - register struct buffer *buffer, **bprev = &all_buffers; + total_markers = num_used; + total_free_markers = num_free; +} - total_buffers = 0; - for (buffer = all_buffers; buffer; buffer = *bprev) - if (!VECTOR_MARKED_P (buffer)) - { - *bprev = buffer->next; - lisp_free (buffer); - } - else - { - VECTOR_UNMARK (buffer); - /* Do not use buffer_(set|get)_intervals here. */ - buffer->text->intervals = balance_intervals (buffer->text->intervals); - total_buffers++; - bprev = &buffer->next; - } - } +NO_INLINE /* For better stack traces */ +static void +sweep_buffers (void) +{ + register struct buffer *buffer, **bprev = &all_buffers; - sweep_vectors (); - check_string_bytes (!noninteractive); + total_buffers = 0; + for (buffer = all_buffers; buffer; buffer = *bprev) + if (!VECTOR_MARKED_P (buffer)) + { + *bprev = buffer->next; + lisp_free (buffer); + } + else + { + VECTOR_UNMARK (buffer); + /* Do not use buffer_(set|get)_intervals here. */ + buffer->text->intervals = balance_intervals (buffer->text->intervals); + total_buffers++; + bprev = &buffer->next; + } } +/* Sweep: find all structures not marked, and free them. */ +static void +gc_sweep (void) +{ + /* Remove or mark entries in weak hash tables. + This must be done before any object is unmarked. */ + sweep_weak_hash_tables (); + sweep_strings (); + check_string_bytes (!noninteractive); + sweep_conses (); + sweep_floats (); + sweep_intervals (); + sweep_symbols (); + sweep_misc (); + sweep_buffers (); + sweep_vectors (); + check_string_bytes (!noninteractive); +} /* Debugging aids. */ @@ -6821,6 +6960,78 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) return found; } +#ifdef SUSPICIOUS_OBJECT_CHECKING + +static void * +find_suspicious_object_in_range (void *begin, void *end) +{ + char *begin_a = begin; + char *end_a = end; + int i; + + for (i = 0; i < ARRAYELTS (suspicious_objects); ++i) + { + char *suspicious_object = suspicious_objects[i]; + if (begin_a <= suspicious_object && suspicious_object < end_a) + return suspicious_object; + } + + return NULL; +} + +static void +note_suspicious_free (void* ptr) +{ + struct suspicious_free_record* rec; + + rec = &suspicious_free_history[suspicious_free_history_index++]; + if (suspicious_free_history_index == + ARRAYELTS (suspicious_free_history)) + { + suspicious_free_history_index = 0; + } + + memset (rec, 0, sizeof (*rec)); + rec->suspicious_object = ptr; + backtrace (&rec->backtrace[0], ARRAYELTS (rec->backtrace)); +} + +static void +detect_suspicious_free (void* ptr) +{ + int i; + + eassert (ptr != NULL); + + for (i = 0; i < ARRAYELTS (suspicious_objects); ++i) + if (suspicious_objects[i] == ptr) + { + note_suspicious_free (ptr); + suspicious_objects[i] = NULL; + } +} + +#endif /* SUSPICIOUS_OBJECT_CHECKING */ + +DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0, + doc: /* Return OBJ, maybe marking it for extra scrutiny. +If Emacs is compiled with suspicous object checking, capture +a stack trace when OBJ is freed in order to help track down +garbage collection bugs. Otherwise, do nothing and return OBJ. */) + (Lisp_Object obj) +{ +#ifdef SUSPICIOUS_OBJECT_CHECKING + /* Right now, we care only about vectors. */ + if (VECTORLIKEP (obj)) + { + suspicious_objects[suspicious_object_index++] = XVECTOR (obj); + if (suspicious_object_index == ARRAYELTS (suspicious_objects)) + suspicious_object_index = 0; + } +#endif + return obj; +} + #ifdef ENABLE_CHECKING bool suppress_checking; @@ -6980,6 +7191,7 @@ The time is in seconds as a floating point value. */); defsubr (&Scons); defsubr (&Slist); defsubr (&Svector); + defsubr (&Sbool_vector); defsubr (&Smake_byte_code); defsubr (&Smake_list); defsubr (&Smake_vector); @@ -6991,6 +7203,7 @@ The time is in seconds as a floating point value. */); defsubr (&Sgarbage_collect); defsubr (&Smemory_limit); defsubr (&Smemory_use_counts); + defsubr (&Ssuspicious_object); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES defsubr (&Sgc_status); @@ -7009,7 +7222,6 @@ union enum char_bits char_bits; enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE; enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE; - enum enum_USE_LSB_TAG enum_USE_LSB_TAG; enum Lisp_Bits Lisp_Bits; enum Lisp_Compiled Lisp_Compiled; enum maxargs maxargs; diff --git a/src/atimer.c b/src/atimer.c index d98ddac0171..e457a7fcf1c 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -50,22 +50,18 @@ static bool alarm_timer_ok; /* Block/unblock SIGALRM. */ static void -sigmask_atimers (int how) +block_atimers (sigset_t *oldset) { sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGALRM); - pthread_sigmask (how, &blocked, 0); + sigaddset (&blocked, SIGINT); + pthread_sigmask (SIG_BLOCK, &blocked, oldset); } static void -block_atimers (void) +unblock_atimers (sigset_t const *oldset) { - sigmask_atimers (SIG_BLOCK); -} -static void -unblock_atimers (void) -{ - sigmask_atimers (SIG_UNBLOCK); + pthread_sigmask (SIG_SETMASK, oldset, 0); } /* Function prototypes. */ @@ -98,6 +94,7 @@ start_atimer (enum atimer_type type, struct timespec timestamp, atimer_callback fn, void *client_data) { struct atimer *t; + sigset_t oldset; /* Round TIME up to the next full second if we don't have itimers. */ @@ -122,7 +119,7 @@ start_atimer (enum atimer_type type, struct timespec timestamp, t->fn = fn; t->client_data = client_data; - block_atimers (); + block_atimers (&oldset); /* Compute the timer's expiration time. */ switch (type) @@ -143,7 +140,7 @@ start_atimer (enum atimer_type type, struct timespec timestamp, /* Insert the timer in the list of active atimers. */ schedule_atimer (t); - unblock_atimers (); + unblock_atimers (&oldset); /* Arrange for a SIGALRM at the time the next atimer is ripe. */ set_alarm (); @@ -158,8 +155,9 @@ void cancel_atimer (struct atimer *timer) { int i; + sigset_t oldset; - block_atimers (); + block_atimers (&oldset); for (i = 0; i < 2; ++i) { @@ -186,7 +184,7 @@ cancel_atimer (struct atimer *timer) } } - unblock_atimers (); + unblock_atimers (&oldset); } @@ -217,7 +215,8 @@ append_atimer_lists (struct atimer *list_1, struct atimer *list_2) void stop_other_atimers (struct atimer *t) { - block_atimers (); + sigset_t oldset; + block_atimers (&oldset); if (t) { @@ -242,7 +241,7 @@ stop_other_atimers (struct atimer *t) stopped_atimers = append_atimer_lists (atimers, stopped_atimers); atimers = t; - unblock_atimers (); + unblock_atimers (&oldset); } @@ -256,8 +255,9 @@ run_all_atimers (void) { struct atimer *t = atimers; struct atimer *next; + sigset_t oldset; - block_atimers (); + block_atimers (&oldset); atimers = stopped_atimers; stopped_atimers = NULL; @@ -268,7 +268,7 @@ run_all_atimers (void) t = next; } - unblock_atimers (); + unblock_atimers (&oldset); } } @@ -381,9 +381,10 @@ do_pending_atimers (void) { if (atimers) { - block_atimers (); + sigset_t oldset; + block_atimers (&oldset); run_timers (); - unblock_atimers (); + unblock_atimers (&oldset); } } @@ -404,7 +405,6 @@ turn_on_atimers (bool on) void init_atimer (void) { - struct sigaction action; #ifdef HAVE_ITIMERSPEC struct sigevent sigev; sigev.sigev_notify = SIGEV_SIGNAL; @@ -413,7 +413,9 @@ init_atimer (void) alarm_timer_ok = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; #endif free_atimers = stopped_atimers = atimers = NULL; - /* pending_signals is initialized in init_keyboard.*/ + + /* pending_signals is initialized in init_keyboard. */ + struct sigaction action; emacs_sigaction_init (&action, handle_alarm_signal); sigaction (SIGALRM, &action, 0); } diff --git a/src/buffer.c b/src/buffer.c index 8077e47fa0b..909b3779b06 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,7 +1,6 @@ /* Buffer manipulation primitives for GNU Emacs. -Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, -Inc. +Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -42,6 +41,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "keymap.h" #include "frame.h" +#ifdef WINDOWSNT +#include "w32heap.h" /* for mmap_* */ +#endif + struct buffer *current_buffer; /* The current buffer. */ /* First buffer in chain of all buffers (in reverse order of creation). @@ -1159,10 +1162,10 @@ DEFUN ("buffer-local-value", Fbuffer_local_value, Sbuffer_local_value, 2, 2, 0, doc: /* Return the value of VARIABLE in BUFFER. If VARIABLE does not have a buffer-local binding in BUFFER, the value -is the default binding of the variable. */) +is the default binding of the variable. */) (register Lisp_Object variable, register Lisp_Object buffer) { - register Lisp_Object result = buffer_local_value_1 (variable, buffer); + register Lisp_Object result = buffer_local_value (variable, buffer); if (EQ (result, Qunbound)) xsignal1 (Qvoid_variable, variable); @@ -1175,7 +1178,7 @@ is the default binding of the variable. */) locally unbound. */ Lisp_Object -buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer) +buffer_local_value (Lisp_Object variable, Lisp_Object buffer) { register struct buffer *buf; register Lisp_Object result; @@ -1380,7 +1383,6 @@ It is not ensured that mode lines will be updated to show the modified state of the current buffer. Use with care. */) (Lisp_Object flag) { -#ifdef CLASH_DETECTION Lisp_Object fn; /* If buffer becoming modified, lock the file. @@ -1400,7 +1402,6 @@ state of the current buffer. Use with care. */) else if (already && NILP (flag)) unlock_file (fn); } -#endif /* CLASH_DETECTION */ /* Here we have a problem. SAVE_MODIFF is used here to encode buffer-modified-p (as SAVE_MODIFF<MODIFF) as well as @@ -1820,10 +1821,8 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* Now there is no question: we can kill the buffer. */ -#ifdef CLASH_DETECTION /* Unlock this buffer's file, if it is locked. */ unlock_buffer (b); -#endif /* CLASH_DETECTION */ GCPRO1 (buffer); kill_buffer_processes (buffer); @@ -4637,7 +4636,8 @@ evaporate_overlays (ptrdiff_t pos) Allocation with mmap ***********************************************************************/ -#ifdef USE_MMAP_FOR_BUFFERS +/* Note: WINDOWSNT implements this stuff on w32heap.c. */ +#if defined USE_MMAP_FOR_BUFFERS && !defined WINDOWSNT #include <sys/mman.h> @@ -4703,11 +4703,6 @@ static struct mmap_region *mmap_regions; static int mmap_fd; -/* Temporary storage for mmap_set_vars, see there. */ - -static struct mmap_region *mmap_regions_1; -static int mmap_fd_1; - /* Page size on this system. */ static int mmap_page_size; @@ -4779,36 +4774,6 @@ mmap_init (void) mmap_page_size = getpagesize (); } -/* Return a region overlapping address range START...END, or null if - none. END is not including, i.e. the last byte in the range - is at END - 1. */ - -static struct mmap_region * -mmap_find (void *start, void *end) -{ - struct mmap_region *r; - char *s = start, *e = end; - - for (r = mmap_regions; r; r = r->next) - { - char *rstart = (char *) r; - char *rend = rstart + r->nbytes_mapped; - - if (/* First byte of range, i.e. START, in this region? */ - (s >= rstart && s < rend) - /* Last byte of range, i.e. END - 1, in this region? */ - || (e > rstart && e <= rend) - /* First byte of this region in the range? */ - || (rstart >= s && rstart < e) - /* Last byte of this region in the range? */ - || (rend > s && rend <= e)) - break; - } - - return r; -} - - /* Unmap a region. P is a pointer to the start of the user-araa of the region. */ @@ -4885,38 +4850,6 @@ mmap_enlarge (struct mmap_region *r, int npages) } -/* Set or reset variables holding references to mapped regions. - If not RESTORE_P, set all variables to null. If RESTORE_P, set all - variables to the start of the user-areas of mapped regions. - - This function is called from Fdump_emacs to ensure that the dumped - Emacs doesn't contain references to memory that won't be mapped - when Emacs starts. */ - -void -mmap_set_vars (bool restore_p) -{ - struct mmap_region *r; - - if (restore_p) - { - mmap_regions = mmap_regions_1; - mmap_fd = mmap_fd_1; - for (r = mmap_regions; r; r = r->next) - *r->var = MMAP_USER_AREA (r); - } - else - { - for (r = mmap_regions; r; r = r->next) - *r->var = NULL; - mmap_regions_1 = mmap_regions; - mmap_regions = NULL; - mmap_fd_1 = mmap_fd; - mmap_fd = -1; - } -} - - /* Allocate a block of storage large enough to hold NBYTES bytes of data. A pointer to the data is returned in *VAR. VAR is thus the address of some variable which will use the data area. @@ -5334,23 +5267,57 @@ init_buffer_once (void) } void -init_buffer (void) +init_buffer (int initialized) { char *pwd; Lisp_Object temp; ptrdiff_t len; #ifdef USE_MMAP_FOR_BUFFERS - { - /* When using the ralloc implementation based on mmap(2), buffer - text pointers will have been set to null in the dumped Emacs. - Map new memory. */ - struct buffer *b; - - FOR_EACH_BUFFER (b) - if (b->text->beg == NULL) - enlarge_buffer_text (b, 0); - } + if (initialized) + { + struct buffer *b; + +#ifndef WINDOWSNT + /* These must be reset in the dumped Emacs, to avoid stale + references to mmap'ed memory from before the dump. + + WINDOWSNT doesn't need this because it doesn't track mmap'ed + regions by hand (see w32heap.c, which uses system APIs for + that purpose), and thus doesn't use mmap_regions. */ + mmap_regions = NULL; + mmap_fd = -1; +#endif + + /* The dumped buffers reference addresses of buffer text + recorded by temacs, that cannot be used by the dumped Emacs. + We map new memory for their text here. + + Implementation note: the buffers we carry from temacs are: + " prin1", "*scratch*", " *Minibuf-0*", "*Messages*", and + " *code-conversion-work*". They are created by + init_buffer_once and init_window_once (which are not called + in the dumped Emacs), and by the first call to coding.c routines. */ + FOR_EACH_BUFFER (b) + { + b->text->beg = NULL; + enlarge_buffer_text (b, 0); + } + } + else + { + struct buffer *b; + + /* Only buffers with allocated buffer text should be present at + this point in temacs. */ + FOR_EACH_BUFFER (b) + { + eassert (b->text->beg != NULL); + } + } +#else /* not USE_MMAP_FOR_BUFFERS */ + /* Avoid compiler warnings. */ + initialized = initialized; #endif /* USE_MMAP_FOR_BUFFERS */ Fset_buffer (Fget_buffer_create (build_string ("*scratch*"))); diff --git a/src/buffer.h b/src/buffer.h index de117eb9c61..5c1e1bb278c 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1079,7 +1079,7 @@ extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); extern void validate_region (Lisp_Object *, Lisp_Object *); extern void set_buffer_internal_1 (struct buffer *); extern void set_buffer_temp (struct buffer *); -extern Lisp_Object buffer_local_value_1 (Lisp_Object, Lisp_Object); +extern Lisp_Object buffer_local_value (Lisp_Object, Lisp_Object); extern void record_buffer (Lisp_Object); extern void fix_overlays_before (struct buffer *, ptrdiff_t, ptrdiff_t); extern void mmap_set_vars (bool); diff --git a/src/bytecode.c b/src/bytecode.c index f1bdfd9d9c5..ca6681f21e9 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -292,8 +292,6 @@ enum byte_code_op Bscan_buffer = 0153, /* No longer generated as of v18. */ Bset_mark = 0163, /* this loser is no longer generated as of v18 */ #endif - - B__dummy__ = 0 /* Pacify C89. */ }; /* Whether to maintain a `top' and `bottom' field in the stack frame. */ @@ -390,7 +388,11 @@ unmark_byte_stack (void) /* Fetch the next byte from the bytecode stream. */ +#ifdef BYTE_CODE_SAFE +#define FETCH (eassert (stack.byte_string_start == SDATA (stack.byte_string)), *stack.pc++) +#else #define FETCH *stack.pc++ +#endif /* Fetch two bytes from the bytecode stream and make a 16-bit number out of them. */ diff --git a/src/callint.c b/src/callint.c index 35411bf9b5c..9e40cc01a62 100644 --- a/src/callint.c +++ b/src/callint.c @@ -29,7 +29,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "keymap.h" Lisp_Object Qminus, Qplus; -static Lisp_Object Qcall_interactively; +static Lisp_Object Qfuncall_interactively; static Lisp_Object Qcommand_debug_status; static Lisp_Object Qenable_recursive_minibuffers; @@ -38,8 +38,8 @@ static Lisp_Object Qread_number; Lisp_Object Qmouse_leave_buffer_hook; -static Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion, Qprogn, Qif; -Lisp_Object Qwhen; +static Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion, Qif; +Lisp_Object Qwhen, Qprogn; static Lisp_Object preserved_fns; /* Marker used within call-interactively to refer to point. */ @@ -233,6 +233,23 @@ fix_command (Lisp_Object input, Lisp_Object values) } } +/* BEWARE: Calling this directly from C would defeat the purpose! */ +DEFUN ("funcall-interactively", Ffuncall_interactively, Sfuncall_interactively, + 1, MANY, 0, doc: /* Like `funcall' but marks the call as interactive. +I.e. arrange that within the called function `called-interactively-p' will +return non-nil. +usage: (funcall-interactively FUNCTION &rest ARGUMENTS) */) + (ptrdiff_t nargs, Lisp_Object *args) +{ + ptrdiff_t speccount = SPECPDL_INDEX (); + temporarily_switch_to_single_kboard (NULL); + + /* Nothing special to do here, all the work is inside + `called-interactively-p'. Which will look for us as a marker in the + backtrace. */ + return unbind_to (speccount, Ffuncall (nargs, args)); +} + DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0, doc: /* Call FUNCTION, providing args according to its interactive calling specs. Return the value FUNCTION returns. @@ -374,8 +391,13 @@ invoke it. If KEYS is omitted or nil, the return value of Vreal_this_command = save_real_this_command; kset_last_command (current_kboard, save_last_command); - temporarily_switch_to_single_kboard (NULL); - return unbind_to (speccount, apply1 (function, specs)); + { + Lisp_Object args[3]; + args[0] = Qfuncall_interactively; + args[1] = function; + args[2] = specs; + return unbind_to (speccount, Fapply (3, args)); + } } /* Here if function specifies a string to control parsing the defaults. */ @@ -446,10 +468,11 @@ invoke it. If KEYS is omitted or nil, the return value of else break; } - /* Count the number of arguments, which is one plus the number of arguments - the interactive spec would have us give to the function. */ + /* Count the number of arguments, which is two (the function itself and + `funcall-interactively') plus the number of arguments the interactive spec + would have us give to the function. */ tem = string; - for (nargs = 1; *tem; ) + for (nargs = 2; *tem; ) { /* 'r' specifications ("point and mark as 2 numeric args") produce *two* arguments. */ @@ -488,13 +511,13 @@ invoke it. If KEYS is omitted or nil, the return value of specbind (Qenable_recursive_minibuffers, Qt); tem = string; - for (i = 1; *tem; i++) + for (i = 2; *tem; i++) { - visargs[0] = make_string (tem + 1, strcspn (tem + 1, "\n")); - if (strchr (SSDATA (visargs[0]), '%')) + visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n")); + if (strchr (SSDATA (visargs[1]), '%')) callint_message = Fformat (i, visargs); else - callint_message = visargs[0]; + callint_message = visargs[1]; switch (*tem) { @@ -789,21 +812,22 @@ invoke it. If KEYS is omitted or nil, the return value of QUIT; - args[0] = function; + args[0] = Qfuncall_interactively; + args[1] = function; if (arg_from_tty || !NILP (record_flag)) { /* We don't need `visargs' any more, so let's recycle it since we need an array of just the same size. */ - visargs[0] = function; - for (i = 1; i < nargs; i++) + visargs[1] = function; + for (i = 2; i < nargs; i++) { if (varies[i] > 0) visargs[i] = list1 (intern (callint_argfuns[varies[i]])); else visargs[i] = quotify_arg (args[i]); } - Vcommand_history = Fcons (Flist (nargs, visargs), + Vcommand_history = Fcons (Flist (nargs - 1, visargs + 1), Vcommand_history); /* Don't keep command history around forever. */ if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0) @@ -816,7 +840,7 @@ invoke it. If KEYS is omitted or nil, the return value of /* If we used a marker to hold point, mark, or an end of the region, temporarily, convert it to an integer now. */ - for (i = 1; i < nargs; i++) + for (i = 2; i < nargs; i++) if (varies[i] >= 1 && varies[i] <= 4) XSETINT (args[i], marker_position (args[i])); @@ -829,11 +853,7 @@ invoke it. If KEYS is omitted or nil, the return value of kset_last_command (current_kboard, save_last_command); { - Lisp_Object val; - specbind (Qcommand_debug_status, Qnil); - - temporarily_switch_to_single_kboard (NULL); - val = Ffuncall (nargs, args); + Lisp_Object val = Ffuncall (nargs, args); UNGCPRO; return unbind_to (speccount, val); } @@ -888,7 +908,7 @@ syms_of_callint (void) DEFSYM (Qplus, "+"); DEFSYM (Qhandle_shift_selection, "handle-shift-selection"); DEFSYM (Qread_number, "read-number"); - DEFSYM (Qcall_interactively, "call-interactively"); + DEFSYM (Qfuncall_interactively, "funcall-interactively"); DEFSYM (Qcommand_debug_status, "command-debug-status"); DEFSYM (Qenable_recursive_minibuffers, "enable-recursive-minibuffers"); DEFSYM (Qmouse_leave_buffer_hook, "mouse-leave-buffer-hook"); @@ -946,5 +966,6 @@ a way to turn themselves off when a mouse command switches windows. */); defsubr (&Sinteractive); defsubr (&Scall_interactively); + defsubr (&Sfuncall_interactively); defsubr (&Sprefix_numeric_value); } diff --git a/src/callproc.c b/src/callproc.c index 7ba3e398b41..9fbc7e5b713 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -105,29 +105,6 @@ enum static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t); - -#ifndef MSDOS -/* Block SIGCHLD. */ - -void -block_child_signal (void) -{ - sigset_t blocked; - sigemptyset (&blocked); - sigaddset (&blocked, SIGCHLD); - pthread_sigmask (SIG_BLOCK, &blocked, 0); -} - -/* Unblock SIGCHLD. */ - -void -unblock_child_signal (void) -{ - pthread_sigmask (SIG_SETMASK, &empty_mask, 0); -} - -#endif /* !MSDOS */ - /* 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. */ @@ -167,7 +144,8 @@ void record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) { #ifndef MSDOS - block_child_signal (); + sigset_t oldset; + block_child_signal (&oldset); if (p->alive) { @@ -176,7 +154,7 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) kill (- p->pid, SIGKILL); } - unblock_child_signal (); + unblock_child_signal (&oldset); #endif /* !MSDOS */ } @@ -321,6 +299,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, char *tempfile = NULL; int pid; #else + sigset_t oldset; pid_t pid; #endif int child_errno; @@ -637,7 +616,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, #ifndef MSDOS block_input (); - block_child_signal (); + block_child_signal (&oldset); #ifdef WINDOWSNT pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); @@ -679,7 +658,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, if (pid == 0) { - unblock_child_signal (); + unblock_child_signal (&oldset); setsid (); @@ -715,7 +694,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, } } - unblock_child_signal (); + unblock_child_signal (&oldset); unblock_input (); if (pid < 0) @@ -1628,13 +1607,13 @@ init_callproc (void) srcdir = Fexpand_file_name (build_string ("../src/"), lispdir); - tem = Fexpand_file_name (build_string ("GNU"), Vdata_directory); + tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory); tem1 = Ffile_exists_p (tem); if (!NILP (Fequal (srcdir, Vinvocation_directory)) || NILP (tem1)) { Lisp_Object newdir; newdir = Fexpand_file_name (build_string ("../etc/"), lispdir); - tem = Fexpand_file_name (build_string ("GNU"), newdir); + tem = Fexpand_file_name (build_string ("NEWS"), newdir); tem1 = Ffile_exists_p (tem); if (!NILP (tem1)) Vdata_directory = newdir; diff --git a/src/charset.c b/src/charset.c index 3566b156736..baa692232c7 100644 --- a/src/charset.c +++ b/src/charset.c @@ -2386,7 +2386,7 @@ syms_of_charset (void) } charset_table = charset_table_init; - charset_table_size = sizeof charset_table_init / sizeof *charset_table_init; + charset_table_size = ARRAYELTS (charset_table_init); charset_table_used = 0; defsubr (&Scharsetp); diff --git a/src/chartab.c b/src/chartab.c index 2a8bbc6983a..4d4e6381b19 100644 --- a/src/chartab.c +++ b/src/chartab.c @@ -1221,9 +1221,7 @@ uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value) static uniprop_decoder_t uniprop_decoder [] = { uniprop_decode_value_run_length }; -static int uniprop_decoder_count - = (sizeof uniprop_decoder) / sizeof (uniprop_decoder[0]); - +static const int uniprop_decoder_count = ARRAYELTS (uniprop_decoder); /* Return the decoder of char-table TABLE or nil if none. */ @@ -1301,9 +1299,7 @@ static uniprop_encoder_t uniprop_encoder[] = uniprop_encode_value_run_length, uniprop_encode_value_numeric }; -static int uniprop_encoder_count - = (sizeof uniprop_encoder) / sizeof (uniprop_encoder[0]); - +static const int uniprop_encoder_count = ARRAYELTS (uniprop_encoder); /* Return the encoder of char-table TABLE or nil if none. */ diff --git a/src/cmds.c b/src/cmds.c index 1a510afa271..828fea3d753 100644 --- a/src/cmds.c +++ b/src/cmds.c @@ -315,7 +315,7 @@ At the end, it runs `post-self-insert-hook'. */) int val = internal_self_insert (character, XFASTINT (n)); if (val == 2) nonundocount = 0; - frame_make_pointer_invisible (); + frame_make_pointer_invisible (SELECTED_FRAME ()); } return Qnil; diff --git a/src/coding.c b/src/coding.c index 654e39c0e3d..fbe14f1695f 100644 --- a/src/coding.c +++ b/src/coding.c @@ -8443,11 +8443,11 @@ from_unicode (Lisp_Object str) } Lisp_Object -from_unicode_buffer (const wchar_t* wstr) +from_unicode_buffer (const wchar_t *wstr) { return from_unicode ( make_unibyte_string ( - (char*) wstr, + (char *) wstr, /* we get one of the two final 0 bytes for free. */ 1 + sizeof (wchar_t) * wcslen (wstr))); } diff --git a/src/coding.h b/src/coding.h index 4e8b1056e43..f3efcca031d 100644 --- a/src/coding.h +++ b/src/coding.h @@ -743,7 +743,7 @@ extern wchar_t *to_unicode (Lisp_Object str, Lisp_Object *buf); extern Lisp_Object from_unicode (Lisp_Object str); /* Convert WSTR to an Emacs string. */ -extern Lisp_Object from_unicode_buffer (const wchar_t* wstr); +extern Lisp_Object from_unicode_buffer (const wchar_t *wstr); #endif /* WINDOWSNT || CYGWIN */ diff --git a/src/conf_post.h b/src/conf_post.h index 446c8275613..a995acfd915 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -34,9 +34,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <stdbool.h> -/* The pre-C99 <stdbool.h> emulation doesn't work for bool bitfields. - Nor does compiling Objective-C with standard GCC. */ -#if __STDC_VERSION__ < 199901 || NS_IMPL_GNUSTEP +/* The type of bool bitfields. Needed to compile Objective-C with + standard GCC. It was also needed to port to pre-C99 compilers, + although we don't care about that any more. */ +#if NS_IMPL_GNUSTEP typedef unsigned int bool_bf; #else typedef bool bool_bf; @@ -87,10 +88,6 @@ typedef bool bool_bf; #ifdef HPUX #undef srandom #undef random -/* We try to avoid checking for random and rint on hpux in - configure.ac, but some other configure test might check for them as - a dependency, so to be safe we also undefine them here. - */ #undef HAVE_RANDOM #undef HAVE_RINT #endif /* HPUX */ @@ -228,16 +225,30 @@ extern void _DebPrint (const char *fmt, ...); #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST +#if 3 <= __GNUC__ +# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +#else +# define ATTRIBUTE_MALLOC +#endif + +#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__) +# define ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args)) +#else +# define ATTRIBUTE_ALLOC_SIZE(args) +#endif + +#define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args) + /* Work around GCC bug 59600: when a function is inlined, the inlined code may have its addresses sanitized even if the function has the - no_sanitize_address attribute. This bug is present in GCC 4.8.2 - and clang 3.3, the latest releases as of December 2013, and the - only platforms known to support address sanitization. When the bug - is fixed the #if can be updated accordingly. */ -#if ADDRESS_SANITIZER -# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE + no_sanitize_address attribute. This bug is fixed in GCC 4.9.0 and + clang 3.4. */ +#if (! ADDRESS_SANITIZER \ + || ((4 < __GNUC__ + (9 <= __GNUC_MINOR__)) \ + || 3 < __clang_major__ + (4 <= __clang_minor__))) +# define ADDRESS_SANITIZER_WORKAROUND /* No workaround needed. */ #else -# define ADDRESS_SANITIZER_WORKAROUND +# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE #endif /* Attribute of functions whose code should not have addresses @@ -299,12 +310,10 @@ extern void _DebPrint (const char *fmt, ...); struct s { ...; t name[FLEXIBLE_ARRAY_MEMBER]; }; and allocate (offsetof (struct s, name) + N * sizeof (t)) bytes. IBM xlc 12.1 claims to do C99 but mishandles flexible array members. */ -#if 199901 <= __STDC_VERSION__ && !defined __IBMC__ -# define FLEXIBLE_ARRAY_MEMBER -#elif __GNUC__ && !defined __STRICT_ANSI__ -# define FLEXIBLE_ARRAY_MEMBER 0 -#else +#ifdef __IBMC__ # define FLEXIBLE_ARRAY_MEMBER 1 +#else +# define FLEXIBLE_ARRAY_MEMBER #endif /* Use this to suppress gcc's `...may be used before initialized' warnings. */ diff --git a/src/data.c b/src/data.c index 4cb569bd943..2de1c19452c 100644 --- a/src/data.c +++ b/src/data.c @@ -727,6 +727,11 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, if (AUTOLOADP (function)) Fput (symbol, Qautoload, XCDR (function)); + /* Convert to eassert or remove after GC bug is found. In the + meantime, check unconditionally, at a slight perf hit. */ + if (valid_lisp_object_p (definition) < 1) + emacs_abort (); + set_symbol_function (symbol, definition); return definition; @@ -2327,7 +2332,7 @@ arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args, ptrdiff_t argnum; for (argnum = 1; argnum < nargs; ++argnum) { - if (EQ (Qnil, arithcompare (args[argnum-1], args[argnum], comparison))) + if (EQ (Qnil, arithcompare (args[argnum - 1], args[argnum], comparison))) return Qnil; } return Qt; @@ -2379,24 +2384,6 @@ DEFUN ("/=", Fneq, Sneq, 2, 2, 0, { return arithcompare (num1, num2, ARITH_NOTEQUAL); } - -DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, - doc: /* Return t if NUMBER is zero. */) - (register Lisp_Object number) -{ - CHECK_NUMBER_OR_FLOAT (number); - - if (FLOATP (number)) - { - if (XFLOAT_DATA (number) == 0.0) - return Qt; - return Qnil; - } - - if (!XINT (number)) - return Qt; - return Qnil; -} /* Convert the cons-of-integers, integer, or float value C to an unsigned value with maximum value MAX. Signal an error if C does not @@ -2888,7 +2875,7 @@ In this case, the sign bit is duplicated. */) if (XINT (count) >= BITS_PER_EMACS_INT) XSETINT (val, 0); else if (XINT (count) > 0) - XSETINT (val, XINT (value) << XFASTINT (count)); + XSETINT (val, XUINT (value) << XFASTINT (count)); else if (XINT (count) <= -BITS_PER_EMACS_INT) XSETINT (val, XINT (value) < 0 ? -1 : 0); else @@ -3643,7 +3630,6 @@ syms_of_data (void) defsubr (&Sleq); defsubr (&Sgeq); defsubr (&Sneq); - defsubr (&Szerop); defsubr (&Splus); defsubr (&Sminus); defsubr (&Stimes); diff --git a/src/dbusbind.c b/src/dbusbind.c index 8ebc56c72c4..8997e01b068 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -142,10 +142,7 @@ static bool xd_in_read_queued_messages = 0; } while (0) #else /* !DBUS_DEBUG */ -# if __STDC_VERSION__ < 199901 -# define XD_DEBUG_MESSAGE (void) /* Pre-C99 compilers cannot debug. */ -# else -# define XD_DEBUG_MESSAGE(...) \ +# define XD_DEBUG_MESSAGE(...) \ do { \ if (!NILP (Vdbus_debug)) \ { \ @@ -154,7 +151,6 @@ static bool xd_in_read_queued_messages = 0; message ("%s: %s", __func__, s); \ } \ } while (0) -# endif # define XD_DEBUG_VALID_LISP_OBJECT_P(object) #endif diff --git a/src/dired.c b/src/dired.c index 55b2f6658c7..d3fe5b4943d 100644 --- a/src/dired.c +++ b/src/dired.c @@ -988,7 +988,7 @@ file_attributes (int fd, char const *name, Lisp_Object id_format) values[10] = INTEGER_TO_CONS (s.st_ino); values[11] = INTEGER_TO_CONS (s.st_dev); - return Flist (sizeof (values) / sizeof (values[0]), values); + return Flist (ARRAYELTS (values), values); } DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0, diff --git a/src/dispextern.h b/src/dispextern.h index 8ccc3d35d8c..e710f8e35d7 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1716,8 +1716,10 @@ struct face attributes except the font. */ struct face *ascii_face; +#ifdef HAVE_XFT /* Extra member that a font-driver uses privately. */ void *extra; +#endif }; @@ -1795,16 +1797,6 @@ struct face_cache bool_bf menu_face_changed_p : 1; }; - -/* Prepare face FACE for use on frame F. This must be called before - using X resources of FACE. */ - -#define PREPARE_FACE_FOR_DISPLAY(F, FACE) \ - do { \ - if ((FACE)->gc == 0) \ - prepare_face_for_display ((F), (FACE)); \ - } while (false) - /* Return a pointer to the face with ID on frame F, or null if such a face doesn't exist. */ @@ -3163,9 +3155,7 @@ int default_line_pixel_height (struct window *); int display_prop_intangible_p (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t); void resize_echo_area_exactly (void); int resize_mini_window (struct window *, int); -#if defined USE_TOOLKIT_SCROLL_BARS && !defined USE_GTK void set_vertical_scroll_bar (struct window *); -#endif int try_window (Lisp_Object, struct text_pos, int); void window_box (struct window *, enum glyph_row_area, int *, int *, int *, int *); @@ -3204,7 +3194,6 @@ extern bool help_echo_showing_p; extern Lisp_Object help_echo_string, help_echo_window; extern Lisp_Object help_echo_object, previous_help_echo_string; extern ptrdiff_t help_echo_pos; -extern int last_tool_bar_item; extern void reseat_at_previous_visible_line_start (struct it *); extern Lisp_Object lookup_glyphless_char_display (int, struct it *); extern ptrdiff_t compute_display_string_pos (struct text_pos *, @@ -3238,9 +3227,7 @@ extern void draw_phys_cursor_glyph (struct window *, enum draw_glyphs_face); extern void get_phys_cursor_geometry (struct window *, struct glyph_row *, struct glyph *, int *, int *, int *); -#if HAVE_NTGUI extern void erase_phys_cursor (struct window *); -#endif extern void display_and_set_cursor (struct window *, bool, int, int, int, int); extern void x_update_cursor (struct frame *, bool); extern void x_clear_cursor (struct window *); @@ -3354,13 +3341,13 @@ void update_face_from_frame_parameter (struct frame *, Lisp_Object, Lisp_Object); Lisp_Object tty_color_name (struct frame *, int); void clear_face_cache (int); -#ifdef MSDOS unsigned long load_color (struct frame *, struct face *, Lisp_Object, enum lface_attribute_index); -#endif char *choose_face_font (struct frame *, Lisp_Object *, Lisp_Object, int *); +#ifdef HAVE_WINDOW_SYSTEM void prepare_face_for_display (struct frame *, struct face *); +#endif int lookup_named_face (struct frame *, Lisp_Object, int); int lookup_basic_face (struct frame *, int); int smaller_face (struct frame *, int, int); diff --git a/src/doc.c b/src/doc.c index b6a4cd0a27b..df8cfba3f2a 100644 --- a/src/doc.c +++ b/src/doc.c @@ -595,7 +595,7 @@ the same file name is found in the `doc-directory'. */) { #include "buildobj.h" }; - int i = sizeof buildobj / sizeof *buildobj; + int i = ARRAYELTS (buildobj); while (0 <= --i) Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files); Vbuild_files = Fpurecopy (Vbuild_files); diff --git a/src/dosfns.c b/src/dosfns.c index 071d73ea16e..baa0358d725 100644 --- a/src/dosfns.c +++ b/src/dosfns.c @@ -402,7 +402,7 @@ msdos_stdcolor_idx (const char *name) { int i; - for (i = 0; i < sizeof (vga_colors) / sizeof (vga_colors[0]); i++) + for (i = 0; i < ARRAYELTS (vga_colors); i++) if (xstrcasecmp (name, vga_colors[i]) == 0) return i; @@ -422,7 +422,7 @@ msdos_stdcolor_name (int idx) return build_string (unspecified_fg); else if (idx == FACE_TTY_DEFAULT_BG_COLOR) return build_string (unspecified_bg); - else if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0])) + else if (idx >= 0 && idx < ARRAYELTS (vga_colors)) return build_string (vga_colors[idx]); else return Qunspecified; /* meaning the default */ diff --git a/src/emacs.c b/src/emacs.c index fd93324de97..117ce4decdb 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1,7 +1,7 @@ /* Fully extensible Emacs, running on Unix, intended for GNU. -Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2014 Free Software -Foundation, Inc. +Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2014 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -80,6 +80,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "composite.h" #include "dispextern.h" #include "syntax.h" +#include "sysselect.h" #include "systime.h" #ifdef HAVE_GNUTLS @@ -105,8 +106,9 @@ extern void moncontrol (int mode); #include <sys/personality.h> #endif -static const char emacs_version[] = VERSION; +static const char emacs_version[] = PACKAGE_VERSION; static const char emacs_copyright[] = COPYRIGHT; +static const char emacs_bugreport[] = PACKAGE_BUGREPORT; /* Empty lisp strings. To avoid having to build any others. */ Lisp_Object empty_unibyte_string, empty_multibyte_string; @@ -121,6 +123,9 @@ Lisp_Object Vlibrary_cache; on subsequent starts. */ bool initialized; +/* Set to true if this instance of Emacs might dump. */ +bool might_dump; + #ifdef DARWIN_OS extern void unexec_init_emacs_zone (void); #endif @@ -132,7 +137,7 @@ static void *malloc_state_ptr; /* From glibc, a routine that returns a copy of the malloc internal state. */ extern void *malloc_get_state (void); /* From glibc, a routine that overwrites the malloc internal state. */ -extern int malloc_set_state (void*); +extern int malloc_set_state (void *); /* True if the MALLOC_CHECK_ environment variable was set while dumping. Used to work around a bug in glibc's malloc. */ static bool malloc_using_checking; @@ -210,7 +215,7 @@ int initial_argc; static void sort_args (int argc, char **argv); static void syms_of_emacs (void); -/* C89 needs each string be at most 509 characters, so the usage +/* C99 needs each string to be at most 4095 characters, and the usage strings below are split to not overflow this limit. */ static char const *const usage_message[] = { "\ @@ -321,7 +326,7 @@ abbreviation for a --option.\n\ Various environment variables and window system resources also affect\n\ the operation of Emacs. See the main documentation.\n\ \n\ -Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\ +Report bugs to " PACKAGE_BUGREPORT ". First, please see the Bugs\n\ section of the Emacs manual or the file BUGS.\n" }; @@ -731,6 +736,10 @@ main (int argc, char **argv) xputenv ("G_SLICE=always-malloc"); #endif +#ifndef CANNOT_DUMP + might_dump = !initialized; +#endif + #ifdef GNU_LINUX if (!initialized) { @@ -1000,7 +1009,7 @@ main (int argc, char **argv) { int i; printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); - for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++) + for (i = 0; i < ARRAYELTS (usage_message); i++) fputs (usage_message[i], stdout); exit (0); } @@ -1368,7 +1377,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem xputenv ("LANG=C"); #endif - init_buffer (); /* Init default directory of main buffer. */ + /* Init buffer storage and default directory of main buffer. */ + init_buffer (initialized); init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */ @@ -1809,7 +1819,7 @@ sort_args (int argc, char **argv) } /* Look for a match with a known old-fashioned option. */ - for (i = 0; i < sizeof (standard_args) / sizeof (standard_args[0]); i++) + for (i = 0; i < ARRAYELTS (standard_args); i++) if (!strcmp (argv[from], standard_args[i].name)) { options[from] = standard_args[i].nargs; @@ -1831,8 +1841,7 @@ sort_args (int argc, char **argv) match = -1; - for (i = 0; - i < sizeof (standard_args) / sizeof (standard_args[0]); i++) + for (i = 0; i < ARRAYELTS (standard_args); i++) if (standard_args[i].longname && !strncmp (argv[from], standard_args[i].longname, thislen)) @@ -2025,9 +2034,7 @@ shut_down_emacs (int sig, Lisp_Object stuff) kill_buffer_processes (Qnil); Fdo_auto_save (Qt, Qnil); -#ifdef CLASH_DETECTION unlock_all_files (); -#endif /* There is a tendency for a SIGIO signal to arrive within exit, and cause a SIGHUP because the input descriptor is already closed. */ @@ -2082,6 +2089,9 @@ You must run Emacs in batch mode in order to dump it. */) if (! noninteractive) error ("Dumping Emacs works only in batch mode"); + if (!might_dump) + error ("Emacs can be dumped only once"); + #ifdef GNU_LINUX /* Warn if the gap between BSS end and heap start is larger than this. */ @@ -2147,13 +2157,8 @@ You must run Emacs in batch mode in order to dump it. */) malloc_state_ptr = malloc_get_state (); #endif -#ifdef USE_MMAP_FOR_BUFFERS - mmap_set_vars (0); -#endif unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0); -#ifdef USE_MMAP_FOR_BUFFERS - mmap_set_vars (1); -#endif + #ifdef DOUG_LEA_MALLOC free (malloc_state_ptr); #endif @@ -2452,6 +2457,12 @@ Emacs is running. */); doc: /* String containing the configuration options Emacs was built with. */); Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS); + DEFVAR_LISP ("system-configuration-features", Vsystem_configuration_features, + doc: /* String listing some of the main features this Emacs was compiled with. +An element of the form \"FOO\" generally means that HAVE_FOO was +defined during the build. */); + Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES); + DEFVAR_BOOL ("noninteractive", noninteractive1, doc: /* Non-nil means Emacs is running without interactive terminal. */); @@ -2529,6 +2540,10 @@ This is nil during initialization. */); doc: /* Version numbers of this version of Emacs. */); Vemacs_version = build_string (emacs_version); + DEFVAR_LISP ("report-emacs-bug-address", Vreport_emacs_bug_address, + doc: /* Address of mailing list for GNU Emacs bugs. */); + Vreport_emacs_bug_address = build_string (emacs_bugreport); + DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist, doc: /* Alist of dynamic libraries vs external files implementing them. Each element is a list (LIBRARY FILE...), where the car is a symbol diff --git a/src/fileio.c b/src/fileio.c index cd32821ed0c..dc3ed431d40 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2911,7 +2911,7 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */) } #endif - return Flist (sizeof (values) / sizeof (values[0]), values); + return Flist (ARRAYELTS (values), values); } DEFUN ("set-file-selinux-context", Fset_file_selinux_context, @@ -4080,13 +4080,11 @@ by calling `format-decode', which see. */) if (NILP (visit) && total > 0) { -#ifdef CLASH_DETECTION if (!NILP (BVAR (current_buffer, file_truename)) /* Make binding buffer-file-name to nil effective. */ && !NILP (BVAR (current_buffer, filename)) && SAVE_MODIFF >= MODIFF) we_locked_file = 1; -#endif /* CLASH_DETECTION */ prepare_to_modify_buffer (PT, PT, NULL); } @@ -4186,10 +4184,8 @@ by calling `format-decode', which see. */) if (inserted == 0) { -#ifdef CLASH_DETECTION if (we_locked_file) unlock_file (BVAR (current_buffer, file_truename)); -#endif Vdeactivate_mark = old_Vdeactivate_mark; } else @@ -4338,14 +4334,12 @@ by calling `format-decode', which see. */) SAVE_MODIFF = MODIFF; BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF; XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG); -#ifdef CLASH_DETECTION if (NILP (handler)) { if (!NILP (BVAR (current_buffer, file_truename))) unlock_file (BVAR (current_buffer, file_truename)); unlock_file (filename); } -#endif /* CLASH_DETECTION */ if (not_regular) xsignal2 (Qfile_error, build_string ("not a regular file"), orig_filename); @@ -4815,13 +4809,11 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, if (!STRINGP (start) && !NILP (BVAR (current_buffer, selective_display))) coding.mode |= CODING_MODE_SELECTIVE_DISPLAY; -#ifdef CLASH_DETECTION if (open_and_close_file && !auto_saving) { lock_file (lockname); file_locked = 1; } -#endif /* CLASH_DETECTION */ encoded_filename = ENCODE_FILE (filename); fn = SSDATA (encoded_filename); @@ -4843,10 +4835,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, if (desc < 0) { int open_errno = errno; -#ifdef CLASH_DETECTION if (file_locked) unlock_file (lockname); -#endif /* CLASH_DETECTION */ UNGCPRO; report_file_errno ("Opening output file", filename, open_errno); } @@ -4861,10 +4851,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, if (ret < 0) { int lseek_errno = errno; -#ifdef CLASH_DETECTION if (file_locked) unlock_file (lockname); -#endif /* CLASH_DETECTION */ UNGCPRO; report_file_errno ("Lseek error", filename, lseek_errno); } @@ -5007,10 +4995,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, unbind_to (count, Qnil); -#ifdef CLASH_DETECTION if (file_locked) unlock_file (lockname); -#endif /* CLASH_DETECTION */ /* Do this before reporting IO error to avoid a "file has changed on disk" warning on diff --git a/src/filelock.c b/src/filelock.c index 5252db09104..f857c488143 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -55,8 +55,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "w32.h" /* for dostounix_filename */ #endif -#ifdef CLASH_DETECTION - #ifdef HAVE_UTMP_H #include <utmp.h> #endif @@ -773,7 +771,9 @@ DEFUN ("lock-buffer", Flock_buffer, Slock_buffer, 0, 1, 0, doc: /* Lock FILE, if current buffer is modified. FILE defaults to current buffer's visited file, -or else nothing is done if current buffer isn't visiting a file. */) +or else nothing is done if current buffer isn't visiting a file. + +If the option `create-lockfiles' is nil, this does nothing. */) (Lisp_Object file) { if (NILP (file)) @@ -837,8 +837,6 @@ t if it is locked by you, else a string saying which user has locked it. */) return ret; } -#endif /* CLASH_DETECTION */ - void syms_of_filelock (void) { @@ -850,9 +848,7 @@ syms_of_filelock (void) doc: /* Non-nil means use lockfiles to avoid editing collisions. */); create_lockfiles = 1; -#ifdef CLASH_DETECTION defsubr (&Sunlock_buffer); defsubr (&Slock_buffer); defsubr (&Sfile_locked_p); -#endif } diff --git a/src/fns.c b/src/fns.c index 499e4b490a6..5074ae3b41b 100644 --- a/src/fns.c +++ b/src/fns.c @@ -1127,7 +1127,48 @@ Elements of ALIST that are not conses are also shared. */) return alist; } -DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0, +/* Check that ARRAY can have a valid subarray [FROM..TO), + given that its size is SIZE. + If FROM is nil, use 0; if TO is nil, use SIZE. + Count negative values backwards from the end. + Set *IFROM and *ITO to the two indexes used. */ + +static void +validate_subarray (Lisp_Object array, Lisp_Object from, Lisp_Object to, + ptrdiff_t size, EMACS_INT *ifrom, EMACS_INT *ito) +{ + EMACS_INT f, t; + + if (INTEGERP (from)) + { + f = XINT (from); + if (f < 0) + f += size; + } + else if (NILP (from)) + f = 0; + else + wrong_type_argument (Qintegerp, from); + + if (INTEGERP (to)) + { + t = XINT (to); + if (t < 0) + t += size; + } + else if (NILP (to)) + t = size; + else + wrong_type_argument (Qintegerp, to); + + if (! (0 <= f && f <= t && t <= size)) + args_out_of_range_3 (array, from, to); + + *ifrom = f; + *ito = t; +} + +DEFUN ("substring", Fsubstring, Ssubstring, 1, 3, 0, doc: /* Return a new string whose contents are a substring of STRING. The returned string consists of the characters between index FROM \(inclusive) and index TO (exclusive) of STRING. FROM and TO are @@ -1137,52 +1178,38 @@ to the end of STRING. The STRING argument may also be a vector. In that case, the return value is a new vector that contains the elements between index FROM -\(inclusive) and index TO (exclusive) of that vector argument. */) - (Lisp_Object string, register Lisp_Object from, Lisp_Object to) +\(inclusive) and index TO (exclusive) of that vector argument. + +With one argument, just copy STRING (with properties, if any). */) + (Lisp_Object string, Lisp_Object from, Lisp_Object to) { Lisp_Object res; ptrdiff_t size; - EMACS_INT from_char, to_char; - - CHECK_VECTOR_OR_STRING (string); - CHECK_NUMBER (from); + EMACS_INT ifrom, ito; if (STRINGP (string)) size = SCHARS (string); - else + else if (VECTORP (string)) size = ASIZE (string); - - if (NILP (to)) - to_char = size; else - { - CHECK_NUMBER (to); - - to_char = XINT (to); - if (to_char < 0) - to_char += size; - } + wrong_type_argument (Qarrayp, string); - from_char = XINT (from); - if (from_char < 0) - from_char += size; - if (!(0 <= from_char && from_char <= to_char && to_char <= size)) - args_out_of_range_3 (string, make_number (from_char), - make_number (to_char)); + validate_subarray (string, from, to, size, &ifrom, &ito); if (STRINGP (string)) { - ptrdiff_t to_byte = - (NILP (to) ? SBYTES (string) : string_char_to_byte (string, to_char)); - ptrdiff_t from_byte = string_char_to_byte (string, from_char); + ptrdiff_t from_byte + = !ifrom ? 0 : string_char_to_byte (string, ifrom); + ptrdiff_t to_byte + = ito == size ? SBYTES (string) : string_char_to_byte (string, ito); res = make_specified_string (SSDATA (string) + from_byte, - to_char - from_char, to_byte - from_byte, + ito - ifrom, to_byte - from_byte, STRING_MULTIBYTE (string)); - copy_text_properties (make_number (from_char), make_number (to_char), + copy_text_properties (make_number (ifrom), make_number (ito), string, make_number (0), res, Qnil); } else - res = Fvector (to_char - from_char, aref_addr (string, from_char)); + res = Fvector (ito - ifrom, aref_addr (string, ifrom)); return res; } @@ -1205,34 +1232,11 @@ With one argument, just copy STRING without its properties. */) CHECK_STRING (string); size = SCHARS (string); + validate_subarray (string, from, to, size, &from_char, &to_char); - if (NILP (from)) - from_char = 0; - else - { - CHECK_NUMBER (from); - from_char = XINT (from); - if (from_char < 0) - from_char += size; - } - - if (NILP (to)) - to_char = size; - else - { - CHECK_NUMBER (to); - to_char = XINT (to); - if (to_char < 0) - to_char += size; - } - - if (!(0 <= from_char && from_char <= to_char && to_char <= size)) - args_out_of_range_3 (string, make_number (from_char), - make_number (to_char)); - - from_byte = NILP (from) ? 0 : string_char_to_byte (string, from_char); + from_byte = !from_char ? 0 : string_char_to_byte (string, from_char); to_byte = - NILP (to) ? SBYTES (string) : string_char_to_byte (string, to_char); + to_char == size ? SBYTES (string) : string_char_to_byte (string, to_char); return make_specified_string (SSDATA (string) + from_byte, to_char - from_char, to_byte - from_byte, STRING_MULTIBYTE (string)); @@ -1693,40 +1697,121 @@ changing the value of a sequence `foo'. */) } DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0, - doc: /* Reverse LIST by modifying cdr pointers. -Return the reversed list. Expects a properly nil-terminated list. */) - (Lisp_Object list) + doc: /* Reverse order of items in a list, vector or string SEQ. +If SEQ is a list, it should be nil-terminated. +This function may destructively modify SEQ to produce the value. */) + (Lisp_Object seq) { - register Lisp_Object prev, tail, next; + if (NILP (seq)) + return seq; + else if (STRINGP (seq)) + return Freverse (seq); + else if (CONSP (seq)) + { + Lisp_Object prev, tail, next; - if (NILP (list)) return list; - prev = Qnil; - tail = list; - while (!NILP (tail)) + for (prev = Qnil, tail = seq; !NILP (tail); tail = next) + { + QUIT; + CHECK_LIST_CONS (tail, tail); + next = XCDR (tail); + Fsetcdr (tail, prev); + prev = tail; + } + seq = prev; + } + else if (VECTORP (seq)) { - QUIT; - CHECK_LIST_CONS (tail, tail); - next = XCDR (tail); - Fsetcdr (tail, prev); - prev = tail; - tail = next; + ptrdiff_t i, size = ASIZE (seq); + + for (i = 0; i < size / 2; i++) + { + Lisp_Object tem = AREF (seq, i); + ASET (seq, i, AREF (seq, size - i - 1)); + ASET (seq, size - i - 1, tem); + } } - return prev; + else if (BOOL_VECTOR_P (seq)) + { + ptrdiff_t i, size = bool_vector_size (seq); + + for (i = 0; i < size / 2; i++) + { + bool tem = bool_vector_bitref (seq, i); + bool_vector_set (seq, i, bool_vector_bitref (seq, size - i - 1)); + bool_vector_set (seq, size - i - 1, tem); + } + } + else + wrong_type_argument (Qarrayp, seq); + return seq; } DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0, - doc: /* Reverse LIST, copying. Return the reversed list. + doc: /* Return the reversed copy of list, vector, or string SEQ. See also the function `nreverse', which is used more often. */) - (Lisp_Object list) + (Lisp_Object seq) { Lisp_Object new; - for (new = Qnil; CONSP (list); list = XCDR (list)) + if (NILP (seq)) + return Qnil; + else if (CONSP (seq)) { - QUIT; - new = Fcons (XCAR (list), new); + for (new = Qnil; CONSP (seq); seq = XCDR (seq)) + { + QUIT; + new = Fcons (XCAR (seq), new); + } + CHECK_LIST_END (seq, seq); + } + else if (VECTORP (seq)) + { + ptrdiff_t i, size = ASIZE (seq); + + new = make_uninit_vector (size); + for (i = 0; i < size; i++) + ASET (new, i, AREF (seq, size - i - 1)); + } + else if (BOOL_VECTOR_P (seq)) + { + ptrdiff_t i; + EMACS_INT nbits = bool_vector_size (seq); + + new = make_uninit_bool_vector (nbits); + for (i = 0; i < nbits; i++) + bool_vector_set (new, i, bool_vector_bitref (seq, nbits - i - 1)); } - CHECK_LIST_END (list, list); + else if (STRINGP (seq)) + { + ptrdiff_t size = SCHARS (seq), bytes = SBYTES (seq); + + if (size == bytes) + { + ptrdiff_t i; + + new = make_uninit_string (size); + for (i = 0; i < size; i++) + SSET (new, i, SREF (seq, size - i - 1)); + } + else + { + unsigned char *p, *q; + + new = make_uninit_multibyte_string (size, bytes); + p = SDATA (seq), q = SDATA (new) + bytes; + while (q > SDATA (new)) + { + int ch, len; + + ch = STRING_CHAR_AND_LENGTH (p, len); + p += len, q -= len; + CHAR_STRING (ch, q); + } + } + } + else + wrong_type_argument (Qsequencep, seq); return new; } @@ -4032,6 +4117,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) current garbage collection. Remove weak tables that don't survive from Vweak_hash_tables. Called from gc_sweep. */ +NO_INLINE /* For better stack traces */ void sweep_weak_hash_tables (void) { @@ -4612,36 +4698,12 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_ object = code_convert_string (object, coding_system, Qnil, 1, 0, 1); size = SCHARS (object); + validate_subarray (object, start, end, size, &start_char, &end_char); - if (!NILP (start)) - { - CHECK_NUMBER (start); - - start_char = XINT (start); - - if (start_char < 0) - start_char += size; - } - - if (NILP (end)) - end_char = size; - else - { - CHECK_NUMBER (end); - - end_char = XINT (end); - - if (end_char < 0) - end_char += size; - } - - if (!(0 <= start_char && start_char <= end_char && end_char <= size)) - args_out_of_range_3 (object, make_number (start_char), - make_number (end_char)); - - start_byte = NILP (start) ? 0 : string_char_to_byte (object, start_char); - end_byte = - NILP (end) ? SBYTES (object) : string_char_to_byte (object, end_char); + start_byte = !start_char ? 0 : string_char_to_byte (object, start_char); + end_byte = (end_char == size + ? SBYTES (object) + : string_char_to_byte (object, end_char)); } else { diff --git a/src/font.c b/src/font.c index b49664b5f31..6113e1c3e71 100644 --- a/src/font.c +++ b/src/font.c @@ -662,10 +662,6 @@ static const struct { &QCotf, font_prop_validate_otf } }; -/* Size (number of elements) of the above table. */ -#define FONT_PROPERTY_TABLE_SIZE \ - ((sizeof font_property_table) / (sizeof *font_property_table)) - /* Return an index number of font property KEY or -1 if KEY is not an already known property. */ @@ -674,7 +670,7 @@ get_font_prop_index (Lisp_Object key) { int i; - for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++) + for (i = 0; i < ARRAYELTS (font_property_table); i++) if (EQ (key, *font_property_table[i].key)) return i; return -1; @@ -2753,22 +2749,21 @@ font_list_entities (struct frame *f, Lisp_Object spec) val = XCDR (val); else { - Lisp_Object copy; - val = driver_list->driver->list (f, scratch_font_spec); - if (NILP (val)) - val = zero_vector; - else - val = Fvconcat (1, &val); - copy = copy_font_spec (scratch_font_spec); - ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); - XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); + if (!NILP (val)) + { + Lisp_Object copy = copy_font_spec (scratch_font_spec); + + val = Fvconcat (1, &val); + ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); + XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); + } } - if (ASIZE (val) > 0 + if (VECTORP (val) && ASIZE (val) > 0 && (need_filtering || ! NILP (Vface_ignored_fonts))) val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size); - if (ASIZE (val) > 0) + if (VECTORP (val) && ASIZE (val) > 0) list = Fcons (val, list); } @@ -2804,18 +2799,22 @@ font_matching_entity (struct frame *f, Lisp_Object *attrs, Lisp_Object spec) && (NILP (ftype) || EQ (driver_list->driver->type, ftype))) { Lisp_Object cache = font_get_cache (f, driver_list->driver); - Lisp_Object copy; ASET (work, FONT_TYPE_INDEX, driver_list->driver->type); entity = assoc_no_quit (work, XCDR (cache)); if (CONSP (entity)) - entity = XCDR (entity); + entity = AREF (XCDR (entity), 0); else { entity = driver_list->driver->match (f, work); - copy = copy_font_spec (work); - ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); - XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache))); + if (!NILP (entity)) + { + Lisp_Object copy = copy_font_spec (work); + Lisp_Object match = Fvector (1, &entity); + + ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); + XSETCDR (cache, Fcons (Fcons (copy, match), XCDR (cache))); + } } if (! NILP (entity)) break; @@ -3338,7 +3337,6 @@ font_done_for_face (struct frame *f, struct face *face) { if (face->font->driver->done_face) face->font->driver->done_face (f, face); - face->extra = NULL; } @@ -4932,8 +4930,7 @@ If the named font is not yet loaded, return nil. */) #endif -#define BUILD_STYLE_TABLE(TBL) \ - build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry)) +#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL)) static Lisp_Object build_style_table (const struct table_entry *entry, int nelement) diff --git a/src/font.h b/src/font.h index e2e36460583..42137deeaa4 100644 --- a/src/font.h +++ b/src/font.h @@ -564,11 +564,9 @@ struct font_driver /* Close FONT. NOTE: this can be called by GC. */ void (*close) (struct font *font); - /* Optional (if FACE->extra is not used). - Prepare FACE for displaying characters by FONT on frame F by - storing some data in FACE->extra. If successful, return 0. - Otherwise, return -1. */ - int (*prepare_face) (struct frame *f, struct face *face); + /* Prepare FACE for displaying characters by FONT on frame F by + storing some data in FACE->extra. */ + void (*prepare_face) (struct frame *f, struct face *face); /* Optional. Done FACE for displaying characters by FACE->font on frame F. */ @@ -834,7 +832,8 @@ extern void syms_of_ftxfont (void); extern Lisp_Object Qxft; extern struct font_driver xftfont_driver; extern void syms_of_xftfont (void); -#elif defined HAVE_FREETYPE +#endif +#if defined HAVE_FREETYPE || defined HAVE_XFT extern struct font_driver ftxfont_driver; #endif #ifdef HAVE_BDFFONT diff --git a/src/frame.c b/src/frame.c index 35c926ce7ef..af2d3c39164 100644 --- a/src/frame.c +++ b/src/frame.c @@ -162,19 +162,16 @@ decode_any_frame (register Lisp_Object frame) return XFRAME (frame); } +#ifdef HAVE_WINDOW_SYSTEM + bool window_system_available (struct frame *f) { - if (f) - return FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f); - else -#ifdef HAVE_WINDOW_SYSTEM - return x_display_list != NULL; -#else - return 0; -#endif + return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL; } +#endif /* HAVE_WINDOW_SYSTEM */ + struct frame * decode_window_system_frame (Lisp_Object frame) { @@ -352,6 +349,9 @@ make_frame (bool mini_p) f->line_height = 1; /* !FRAME_WINDOW_P value. */ #ifdef HAVE_WINDOW_SYSTEM f->want_fullscreen = FULLSCREEN_NONE; +#if ! defined (USE_GTK) && ! defined (HAVE_NS) + f->last_tool_bar_item = -1; +#endif #endif root_window = make_window (); @@ -1593,6 +1593,42 @@ and nil for X and Y. */) return Fcons (lispy_dummy, Fcons (x, y)); } +#ifdef HAVE_WINDOW_SYSTEM + +/* On frame F, convert character coordinates X and Y to pixel + coordinates *PIX_X and *PIX_Y. */ + +static void +frame_char_to_pixel_position (struct frame *f, int x, int y, + int *pix_x, int *pix_y) +{ + *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; + *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; + + if (*pix_x < 0) + *pix_x = 0; + if (*pix_x > FRAME_PIXEL_WIDTH (f)) + *pix_x = FRAME_PIXEL_WIDTH (f); + + if (*pix_y < 0) + *pix_y = 0; + if (*pix_y > FRAME_PIXEL_HEIGHT (f)) + *pix_y = FRAME_PIXEL_HEIGHT (f); +} + +/* On frame F, reposition mouse pointer to character coordinates X and Y. */ + +static void +frame_set_mouse_position (struct frame *f, int x, int y) +{ + int pix_x, pix_y; + + frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y); + frame_set_mouse_pixel_position (f, pix_x, pix_y); +} + +#endif /* HAVE_WINDOW_SYSTEM */ + DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0, doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME. Coordinates are relative to the frame, not a window, @@ -1617,7 +1653,7 @@ before calling this function on it, like this. #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (frame))) /* Warping the mouse will cause enternotify and focus events. */ - x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y)); + frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y)); #else #if defined (MSDOS) if (FRAME_MSDOS_P (XFRAME (frame))) @@ -1658,7 +1694,7 @@ before calling this function on it, like this. #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (frame))) /* Warping the mouse will cause enternotify and focus events. */ - x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y)); + frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y)); #else #if defined (MSDOS) if (FRAME_MSDOS_P (XFRAME (frame))) @@ -1929,9 +1965,6 @@ If there is no window system support, this function does nothing. */) /* Return the value of frame parameter PROP in frame FRAME. */ #ifdef HAVE_WINDOW_SYSTEM -#if !HAVE_NS && !HAVE_NTGUI -static -#endif Lisp_Object get_frame_param (register struct frame *frame, Lisp_Object prop) { @@ -2867,8 +2900,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) param_index = Fget (prop, Qx_frame_parameter); if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (param_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } @@ -2916,8 +2948,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) param_index = Fget (prop, Qx_frame_parameter); if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (param_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } @@ -3228,8 +3259,7 @@ x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu { Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter); if (NATNUMP (parm_index) - && (XFASTINT (parm_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (parm_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)]) (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)]) (f, bgcolor, Qnil); @@ -4376,16 +4406,11 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) #endif /* HAVE_WINDOW_SYSTEM */ void -frame_make_pointer_invisible (void) +frame_make_pointer_invisible (struct frame *f) { if (! NILP (Vmake_pointer_invisible)) { - struct frame *f; - if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))) - return; - - f = SELECTED_FRAME (); - if (f && !f->pointer_invisible + if (f && FRAME_LIVE_P (f) && !f->pointer_invisible && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook) { f->mouse_moved = 0; @@ -4396,17 +4421,11 @@ frame_make_pointer_invisible (void) } void -frame_make_pointer_visible (void) +frame_make_pointer_visible (struct frame *f) { /* We don't check Vmake_pointer_invisible here in case the pointer was invisible when Vmake_pointer_invisible was set to nil. */ - struct frame *f; - - if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))) - return; - - f = SELECTED_FRAME (); - if (f && f->pointer_invisible && f->mouse_moved + if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook) { FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0); @@ -4563,7 +4582,7 @@ syms_of_frame (void) { int i; - for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++) + for (i = 0; i < ARRAYELTS (frame_parms); i++) { Lisp_Object v = intern_c_string (frame_parms[i].name); if (frame_parms[i].variable) diff --git a/src/frame.h b/src/frame.h index ff696df9eff..44b113e3416 100644 --- a/src/frame.h +++ b/src/frame.h @@ -164,6 +164,11 @@ struct frame /* Cache of realized faces. */ struct face_cache *face_cache; +#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) + /* Tool-bar item index of the item on which a mouse button was pressed. */ + int last_tool_bar_item; +#endif + /* Number of elements in `menu_bar_vector' that have meaningful data. */ int menu_bar_items_used; @@ -992,11 +997,13 @@ extern struct frame *make_minibuffer_frame (void); extern struct frame *make_frame_without_minibuffer (Lisp_Object, struct kboard *, Lisp_Object); -#endif /* HAVE_WINDOW_SYSTEM */ extern bool window_system_available (struct frame *); +#else /* not HAVE_WINDOW_SYSTEM */ +#define window_system_available(f) ((void) (f), false) +#endif /* HAVE_WINDOW_SYSTEM */ extern void check_window_system (struct frame *); -extern void frame_make_pointer_invisible (void); -extern void frame_make_pointer_visible (void); +extern void frame_make_pointer_invisible (struct frame *); +extern void frame_make_pointer_visible (struct frame *); extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); extern Lisp_Object Vframe_list; @@ -1313,8 +1320,7 @@ extern void set_frame_menubar (struct frame *f, bool first_time, bool deep_p); extern void x_set_window_size (struct frame *f, int change_grav, int width, int height, bool pixelwise); extern Lisp_Object x_get_focus_frame (struct frame *); -extern void x_set_mouse_position (struct frame *f, int h, int v); -extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); +extern void frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); extern void x_make_frame_visible (struct frame *f); extern void x_make_frame_invisible (struct frame *f); extern void x_iconify_frame (struct frame *f); @@ -1354,7 +1360,6 @@ x_set_bitmap_icon (struct frame *f) } #endif /* !HAVE_NS */ - #endif /* HAVE_WINDOW_SYSTEM */ INLINE void diff --git a/src/fringe.c b/src/fringe.c index 6325de4128e..d00aee0e0b6 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -474,15 +474,12 @@ static struct fringe_bitmap standard_bitmaps[] = #define NO_FRINGE_BITMAP 0 #define UNDEF_FRINGE_BITMAP 1 -#define MAX_STANDARD_FRINGE_BITMAPS (sizeof (standard_bitmaps)/sizeof (standard_bitmaps[0])) +#define MAX_STANDARD_FRINGE_BITMAPS ARRAYELTS (standard_bitmaps) static struct fringe_bitmap **fringe_bitmaps; static Lisp_Object *fringe_faces; static int max_fringe_bitmaps; -#ifndef HAVE_NS -static -#endif int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; @@ -637,7 +634,7 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o return; } - PREPARE_FACE_FOR_DISPLAY (f, p.face); + prepare_face_for_display (f, p.face); /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill the fringe. */ diff --git a/src/ftxfont.c b/src/ftxfont.c index 9db7cbceb66..53f2616bb62 100644 --- a/src/ftxfont.c +++ b/src/ftxfont.c @@ -37,9 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ static Lisp_Object Qftx; -#if defined HAVE_XFT || !defined HAVE_FREETYPE -static -#endif struct font_driver ftxfont_driver; struct ftxfont_frame_data diff --git a/src/gmalloc.c b/src/gmalloc.c index 977abbdbbbd..ab1dfd07db2 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -51,12 +51,12 @@ extern "C" /* Allocate SIZE bytes of memory. */ -extern void *malloc (size_t size); +extern void *malloc (size_t size) ATTRIBUTE_MALLOC_SIZE ((1)); /* Re-allocate the previously allocated block in ptr, making the new block SIZE bytes long. */ -extern void *realloc (void *ptr, size_t size); +extern void *realloc (void *ptr, size_t size) ATTRIBUTE_ALLOC_SIZE ((2)); /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ -extern void *calloc (size_t nmemb, size_t size); +extern void *calloc (size_t nmemb, size_t size) ATTRIBUTE_MALLOC_SIZE ((1,2)); /* Free a block allocated by `malloc', `realloc' or `calloc'. */ extern void free (void *ptr); diff --git a/src/gnutls.c b/src/gnutls.c index 03c29d03014..d9b417b46ed 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -56,7 +56,7 @@ static Lisp_Object QCgnutls_bootprop_verify_error; static Lisp_Object QCgnutls_bootprop_callbacks_verify; static void gnutls_log_function (int, const char *); -static void gnutls_log_function2 (int, const char*, const char*); +static void gnutls_log_function2 (int, const char *, const char *); #ifdef HAVE_GNUTLS3 static void gnutls_audit_log_function (gnutls_session_t, const char *); #endif @@ -267,7 +267,7 @@ init_gnutls_functions (void) #ifdef HAVE_GNUTLS3 /* Function to log a simple audit message. */ static void -gnutls_audit_log_function (gnutls_session_t session, const char* string) +gnutls_audit_log_function (gnutls_session_t session, const char *string) { if (global_gnutls_log_level >= 1) { @@ -278,21 +278,21 @@ gnutls_audit_log_function (gnutls_session_t session, const char* string) /* Function to log a simple message. */ static void -gnutls_log_function (int level, const char* string) +gnutls_log_function (int level, const char *string) { message ("gnutls.c: [%d] %s", level, string); } /* Function to log a message and a string. */ static void -gnutls_log_function2 (int level, const char* string, const char* extra) +gnutls_log_function2 (int level, const char *string, const char *extra) { message ("gnutls.c: [%d] %s %s", level, string, extra); } /* Function to log a message and an integer. */ static void -gnutls_log_function2i (int level, const char* string, int extra) +gnutls_log_function2i (int level, const char *string, int extra) { message ("gnutls.c: [%d] %s %d", level, string, extra); } @@ -794,7 +794,7 @@ one trustfile (usually a CA bundle). */) Lisp_Object global_init; char const *priority_string_ptr = "NORMAL"; /* default priority string. */ unsigned int peer_verification; - char* c_hostname; + char *c_hostname; /* Placeholders for the property list elements. */ Lisp_Object priority_string; diff --git a/src/gtkutil.c b/src/gtkutil.c index cebff68614f..8614fe57cb2 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -221,57 +221,6 @@ xg_display_close (Display *dpy) /*********************************************************************** Utility functions ***********************************************************************/ -/* The next two variables and functions are taken from lwlib. */ -static widget_value *widget_value_free_list; -static int malloc_cpt; - -/* Allocate a widget_value structure, either by taking one from the - widget_value_free_list or by malloc:ing a new one. - - Return a pointer to the allocated structure. */ - -widget_value * -malloc_widget_value (void) -{ - widget_value *wv; - if (widget_value_free_list) - { - wv = widget_value_free_list; - widget_value_free_list = wv->free_list; - wv->free_list = 0; - } - else - { - wv = xmalloc (sizeof *wv); - malloc_cpt++; - } - memset (wv, 0, sizeof (widget_value)); - return wv; -} - -/* This is analogous to free. It frees only what was allocated - by malloc_widget_value, and no substructures. */ - -void -free_widget_value (widget_value *wv) -{ - if (wv->free_list) - emacs_abort (); - - if (malloc_cpt > 25) - { - /* When the number of already allocated cells is too big, - We free it. */ - xfree (wv); - malloc_cpt--; - } - else - { - wv->free_list = widget_value_free_list; - widget_value_free_list = wv; - } -} - /* Create and return the cursor to be used for popup menus and scroll bars on display DPY. */ diff --git a/src/gtkutil.h b/src/gtkutil.h index 12bf461fd69..a69932cc25c 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #ifdef USE_GTK #include <gtk/gtk.h> +#include "../lwlib/lwlib-widget.h" #include "frame.h" #include "xterm.h" @@ -74,9 +75,6 @@ typedef struct xg_menu_item_cb_data_ } xg_menu_item_cb_data; -extern struct _widget_value *malloc_widget_value (void); -extern void free_widget_value (struct _widget_value *); - extern bool xg_uses_old_file_dialog (void) ATTRIBUTE_CONST; extern char *xg_get_file_name (struct frame *f, diff --git a/src/image.c b/src/image.c index 4133aaa7621..3220a45a282 100644 --- a/src/image.c +++ b/src/image.c @@ -21,13 +21,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "sysstdio.h" #include <unistd.h> -#ifdef HAVE_PNG -#if defined HAVE_LIBPNG_PNG_H -# include <libpng/png.h> -#else +/* Include this before including <setjmp.h> to work around bugs with + older libpng; see Bug#17429. */ +#if defined HAVE_PNG && !defined HAVE_NS # include <png.h> #endif -#endif #include <setjmp.h> #include <c-ctype.h> @@ -160,6 +158,7 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) /* Functions to access the contents of a bitmap, given an id. */ +#ifdef HAVE_X_WINDOWS static int x_bitmap_height (struct frame *f, ptrdiff_t id) { @@ -171,6 +170,7 @@ x_bitmap_width (struct frame *f, ptrdiff_t id) { return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].width; } +#endif #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) ptrdiff_t @@ -998,6 +998,11 @@ free_image (struct frame *f, struct image *img) c->images[img->id] = NULL; + /* Windows NT redefines 'free', but in this file, we need to + avoid the redefinition. */ +#ifdef WINDOWSNT +#undef free +#endif /* Free resources, then free IMG. */ img->type->free (f, img); xfree (img); @@ -1231,7 +1236,23 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D return img->background_transparent; } - +#if defined (HAVE_PNG) || defined (HAVE_NS) \ + || defined (HAVE_IMAGEMAGICK) || defined (HAVE_RSVG) + +/* Store F's background color into *BGCOLOR. */ +static void +x_query_frame_background_color (struct frame *f, XColor *bgcolor) +{ +#ifndef HAVE_NS + bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f); + x_query_color (f, bgcolor); +#else + ns_query_color (FRAME_BACKGROUND_COLOR (f), bgcolor, 1); +#endif +} + +#endif /* HAVE_PNG || HAVE_NS || HAVE_IMAGEMAGICK || HAVE_RSVG */ + /*********************************************************************** Helper functions for X image types ***********************************************************************/ @@ -3953,9 +3974,7 @@ xpm_str_to_color_key (const char *s) { int i; - for (i = 0; - i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0]; - i++) + for (i = 0; i < ARRAYELTS (xpm_color_key_strings); i++) if (strcmp (xpm_color_key_strings[i], s) == 0) return i; return -1; @@ -5506,7 +5525,7 @@ png_image_p (Lisp_Object object) #endif /* HAVE_PNG || HAVE_NS */ -#ifdef HAVE_PNG +#if defined HAVE_PNG && !defined HAVE_NS #ifdef WINDOWSNT /* PNG library details. */ @@ -5884,43 +5903,23 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) /* png_color_16 *image_bg; */ Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); - int shift = (bit_depth == 16) ? 0 : 8; + XColor color; - if (STRINGP (specified_bg)) + /* If the user specified a color, try to use it; if not, use the + current frame background, ignoring any default background + color set by the image. */ + if (STRINGP (specified_bg) + ? x_defined_color (f, SSDATA (specified_bg), &color, false) + : (x_query_frame_background_color (f, &color), true)) /* The user specified `:background', use that. */ { - XColor color; - if (x_defined_color (f, SSDATA (specified_bg), &color, 0)) - { - png_color_16 user_bg; + int shift = bit_depth == 16 ? 0 : 8; + png_color_16 bg = { 0 }; + bg.red = color.red >> shift; + bg.green = color.green >> shift; + bg.blue = color.blue >> shift; - memset (&user_bg, 0, sizeof user_bg); - user_bg.red = color.red >> shift; - user_bg.green = color.green >> shift; - user_bg.blue = color.blue >> shift; - - fn_png_set_background (png_ptr, &user_bg, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - } - } - else - { - /* We use the current frame background, ignoring any default - background color set by the image. */ -#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) - XColor color; - png_color_16 frame_background; - - color.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &color); - - memset (&frame_background, 0, sizeof frame_background); - frame_background.red = color.red >> shift; - frame_background.green = color.green >> shift; - frame_background.blue = color.blue >> shift; -#endif /* HAVE_X_WINDOWS */ - - fn_png_set_background (png_ptr, &frame_background, + fn_png_set_background (png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } @@ -6062,9 +6061,8 @@ png_load (struct frame *f, struct image *img) return png_load_body (f, img, &c); } -#else /* HAVE_PNG */ +#elif defined HAVE_NS -#ifdef HAVE_NS static bool png_load (struct frame *f, struct image *img) { @@ -6072,10 +6070,8 @@ png_load (struct frame *f, struct image *img) image_spec_value (img->spec, QCfile, NULL), image_spec_value (img->spec, QCdata, NULL)); } -#endif /* HAVE_NS */ - -#endif /* !HAVE_PNG */ +#endif /* HAVE_NS */ @@ -6466,7 +6462,6 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp) src->mgr.next_input_byte = NULL; } - /* Load image IMG for use on frame F. Patterned after example.c from the JPEG lib. */ @@ -8229,14 +8224,7 @@ imagemagick_load_image (struct frame *f, struct image *img, specified_bg = image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg) || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0)) - { -#ifndef HAVE_NS - bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &bgcolor); -#else - ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1); -#endif - } + x_query_frame_background_color (f, &bgcolor); bg_wand = NewPixelWand (); PixelSetRed (bg_wand, (double) bgcolor.red / 65535); @@ -8388,6 +8376,7 @@ imagemagick_load_image (struct frame *f, struct image *img, #endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */ { size_t image_height; + MagickRealType color_scale = 65535.0 / QuantumRange; /* Try to create a x pixmap to hold the imagemagick pixmap. */ if (!image_create_x_image_and_pixmap (f, img, width, height, 0, @@ -8428,9 +8417,9 @@ imagemagick_load_image (struct frame *f, struct image *img, PixelGetMagickColor (pixels[x], &pixel); XPutPixel (ximg, x, y, lookup_rgb_color (f, - pixel.red, - pixel.green, - pixel.blue)); + color_scale * pixel.red, + color_scale * pixel.green, + color_scale * pixel.blue)); } } DestroyPixelIterator (iterator); @@ -8652,7 +8641,6 @@ DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions, (RsvgHandle *, RsvgDimensionDat DEF_IMGLIB_FN (gboolean, rsvg_handle_write, (RsvgHandle *, const guchar *, gsize, GError **)); DEF_IMGLIB_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **)); DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *)); -DEF_IMGLIB_FN (void *, rsvg_handle_set_size_callback, (RsvgHandle *, RsvgSizeFunc, gpointer, GDestroyNotify)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *)); DEF_IMGLIB_FN (int, gdk_pixbuf_get_height, (const GdkPixbuf *)); @@ -8674,13 +8662,18 @@ Lisp_Object Qgdk_pixbuf, Qglib, Qgobject; static bool init_svg_functions (void) { - HMODULE library, gdklib, glib, gobject; + HMODULE library, gdklib = NULL, glib = NULL, gobject = NULL; if (!(glib = w32_delayed_load (Qglib)) || !(gobject = w32_delayed_load (Qgobject)) || !(gdklib = w32_delayed_load (Qgdk_pixbuf)) || !(library = w32_delayed_load (Qsvg))) - return 0; + { + if (gdklib) FreeLibrary (gdklib); + if (gobject) FreeLibrary (gobject); + if (glib) FreeLibrary (glib); + return 0; + } LOAD_IMGLIB_FN (library, rsvg_handle_new); LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions); @@ -8868,14 +8861,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * specified_bg = image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg) || !x_defined_color (f, SSDATA (specified_bg), &background, 0)) - { -#ifndef HAVE_NS - background.pixel = FRAME_BACKGROUND_PIXEL (f); - x_query_color (f, &background); -#else - ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1); -#endif - } + x_query_frame_background_color (f, &background); /* SVG pixmaps specify transparency in the last byte, so right shift 8 bits to get rid of it, since emacs doesn't support diff --git a/src/insdel.c b/src/insdel.c index 85526d46db1..2894af75348 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1,6 +1,6 @@ /* Buffer insertion/deletion and gap motion for GNU Emacs. - Copyright (C) 1985-1986, 1993-1995, 1997-2014 Free Software - Foundation, Inc. + +Copyright (C) 1985-1986, 1993-1995, 1997-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -1804,26 +1804,18 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end, else base_buffer = current_buffer; -#ifdef CLASH_DETECTION + if (inhibit_modification_hooks) + return; + if (!NILP (BVAR (base_buffer, file_truename)) /* Make binding buffer-file-name to nil effective. */ && !NILP (BVAR (base_buffer, filename)) && SAVE_MODIFF >= MODIFF) lock_file (BVAR (base_buffer, file_truename)); -#else - /* At least warn if this file has changed on disk since it was visited. */ - if (!NILP (BVAR (base_buffer, filename)) - && SAVE_MODIFF >= MODIFF - && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ())) - && !NILP (Ffile_exists_p (BVAR (base_buffer, filename)))) - call1 (intern ("ask-user-about-supersession-threat"), - BVAR (base_buffer,filename)); -#endif /* not CLASH_DETECTION */ /* If `select-active-regions' is non-nil, save the region text. */ /* FIXME: Move this to Elisp (via before-change-functions). */ if (!NILP (BVAR (current_buffer, mark_active)) - && !inhibit_modification_hooks && XMARKER (BVAR (current_buffer, mark))->buffer && NILP (Vsaved_region_selection) && (EQ (Vselect_active_regions, Qonly) @@ -1962,9 +1954,6 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, ptrdiff_t count = SPECPDL_INDEX (); struct rvoe_arg rvoe_arg; - if (inhibit_modification_hooks) - return; - start = make_number (start_int); end = make_number (end_int); preserve_marker = Qnil; @@ -1975,7 +1964,7 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int, specbind (Qinhibit_modification_hooks, Qt); /* If buffer is unmodified, run a special hook for that case. The - check for Vfirst_change_hook is just a minor optimization. */ + check for Vfirst_change_hook is just a minor optimization. */ if (SAVE_MODIFF >= MODIFF && !NILP (Vfirst_change_hook)) { diff --git a/src/keyboard.c b/src/keyboard.c index 8bc0c108739..dcf89137a5c 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -228,7 +228,7 @@ static Lisp_Object Qbackward_char; Lisp_Object Qundefined; static Lisp_Object Qtimer_event_handler; -/* read_key_sequence stores here the command definition of the +/* `read_key_sequence' stores here the command definition of the key sequence that it reads. */ static Lisp_Object read_key_sequence_cmd; static Lisp_Object read_key_sequence_remapped; @@ -377,12 +377,6 @@ bool interrupt_input; /* Nonzero while interrupts are temporarily deferred during redisplay. */ bool interrupts_deferred; -/* If we support a window system, turn on the code to poll periodically - to detect C-g. It isn't actually used when doing interrupt input. */ -#ifdef HAVE_WINDOW_SYSTEM -#define POLL_FOR_INPUT -#endif - /* The time when Emacs started being idle. */ static struct timespec timer_idleness_start_time; @@ -1292,9 +1286,6 @@ usage: (track-mouse BODY...) */) If ignore_mouse_drag_p is non-zero, ignore (implicit) mouse movement after resizing the tool-bar window. */ -#if !defined HAVE_WINDOW_SYSTEM || defined USE_GTK || defined HAVE_NS -static -#endif bool ignore_mouse_drag_p; static struct frame * @@ -1449,7 +1440,7 @@ command_loop_1 (void) Vthis_command_keys_shift_translated = Qnil; /* Read next key sequence; i gets its length. */ - i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0], + i = read_key_sequence (keybuf, ARRAYELTS (keybuf), Qnil, 0, 1, 1, 0); /* A filter may have run while we were reading the input. */ @@ -1697,7 +1688,7 @@ read_menu_command (void) menus. */ specbind (Qecho_keystrokes, make_number (0)); - i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0], + i = read_key_sequence (keybuf, ARRAYELTS (keybuf), Qnil, 0, 1, 1, 1); unbind_to (count, Qnil); @@ -2091,9 +2082,6 @@ bind_polling_period (int n) /* Apply the control modifier to CHARACTER. */ -#ifndef HAVE_NTGUI -static -#endif int make_ctrl_char (int c) { @@ -2302,8 +2290,10 @@ read_decoded_event_from_main_queue (struct timespec *end_time, bool *used_mouse_menu) { #define MAX_ENCODED_BYTES 16 +#ifndef WINDOWSNT Lisp_Object events[MAX_ENCODED_BYTES]; int n = 0; +#endif while (true) { Lisp_Object nextevt @@ -2374,6 +2364,13 @@ read_decoded_event_from_main_queue (struct timespec *end_time, } } +static bool +echo_keystrokes_p (void) +{ + return (FLOATP (Vecho_keystrokes) ? XFLOAT_DATA (Vecho_keystrokes) > 0.0 + : INTEGERP (Vecho_keystrokes) ? XINT (Vecho_keystrokes) > 0 : false); +} + /* Read a character from the keyboard; call the redisplay if needed. */ /* commandflag 0 means do not autosave, but do redisplay. -1 means do not redisplay, but do autosave. @@ -2431,7 +2428,6 @@ read_char (int commandflag, Lisp_Object map, retry: - reread = 0; if (CONSP (Vunread_post_input_method_events)) { c = XCAR (Vunread_post_input_method_events); @@ -2445,9 +2441,12 @@ read_char (int commandflag, Lisp_Object map, && NILP (XCDR (c))) c = XCAR (c); - reread = 1; + reread = true; goto reread_first; } + else + reread = false; + if (CONSP (Vunread_command_events)) { @@ -2456,17 +2455,13 @@ read_char (int commandflag, Lisp_Object map, c = XCAR (Vunread_command_events); Vunread_command_events = XCDR (Vunread_command_events); - reread = 1; - /* Undo what sit-for did when it unread additional keys inside universal-argument. */ - if (CONSP (c) - && EQ (XCAR (c), Qt)) - { - reread = 0; - c = XCDR (c); - } + if (CONSP (c) && EQ (XCAR (c), Qt)) + c = XCDR (c); + else + reread = true; /* Undo what read_char_x_menu_prompt did when it unread additional keys returned by Fx_popup_menu. */ @@ -2500,7 +2495,7 @@ read_char (int commandflag, Lisp_Object map, && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c))) && NILP (XCDR (c))) c = XCAR (c); - reread = 1; + reread = true; goto reread_for_input_method; } @@ -2655,6 +2650,7 @@ read_char (int commandflag, Lisp_Object map, /* We must have saved the outer value of getcjmp here, so restore it now. */ restore_getcjmp (save_jump); + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); unbind_to (jmpcount, Qnil); XSETINT (c, quit_char); internal_last_event_frame = selected_frame; @@ -2709,8 +2705,7 @@ read_char (int commandflag, Lisp_Object map, && !current_kboard->immediate_echo && this_command_key_count > 0 && ! noninteractive - && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes)) + && echo_keystrokes_p () && (/* No message. */ NILP (echo_area_buffer[0]) /* Or empty message. */ @@ -2841,6 +2836,11 @@ read_char (int commandflag, Lisp_Object map, { c = XCAR (Vunread_command_events); Vunread_command_events = XCDR (Vunread_command_events); + + if (CONSP (c) && EQ (XCAR (c), Qt)) + c = XCDR (c); + else + reread = true; } /* Read something from current KBOARD's side queue, if possible. */ @@ -2894,8 +2894,8 @@ read_char (int commandflag, Lisp_Object map, { c = read_decoded_event_from_main_queue (end_time, local_getcjmp, prev_event, used_mouse_menu); - if (NILP(c) && end_time && - timespec_cmp (*end_time, current_timespec ()) <= 0) + if (NILP (c) && end_time + && timespec_cmp (*end_time, current_timespec ()) <= 0) { goto exit; } @@ -3171,8 +3171,7 @@ read_char (int commandflag, Lisp_Object map, { /* Don't echo mouse motion events. */ - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes)) + if (echo_keystrokes_p () && ! (EVENT_HAS_PARAMETERS (c) && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement))) { @@ -3248,8 +3247,7 @@ record_menu_key (Lisp_Object c) #endif /* Don't echo mouse motion events. */ - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes))) + if (echo_keystrokes_p ()) { echo_char (c); @@ -5224,7 +5222,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, /* It's a click in window WINDOW at frame coordinates (X,Y) */ struct window *w = XWINDOW (window); Lisp_Object string_info = Qnil; - ptrdiff_t textpos = -1; + ptrdiff_t textpos = 0; int col = -1, row = -1; int dx = -1, dy = -1; int width = -1, height = -1; @@ -5259,9 +5257,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, &object, &dx, &dy, &width, &height); if (STRINGP (string)) string_info = Fcons (string, make_number (charpos)); - textpos = (w == XWINDOW (selected_window) - && current_buffer == XBUFFER (w->contents)) - ? PT : marker_position (w->pointm); + textpos = -1; xret = wx; yret = wy; @@ -5329,7 +5325,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, /* For clicks in the text area, fringes, or margins, call buffer_posn_from_coords to extract TEXTPOS, the buffer position nearest to the click. */ - if (textpos < 0) + if (!textpos) { Lisp_Object string2, object2 = Qnil; struct display_pos p; @@ -5380,15 +5376,15 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, } #endif - /* Object info */ + /* Object info. */ extra_info = list3 (object, Fcons (make_number (dx), make_number (dy)), Fcons (make_number (width), make_number (height))); - /* String info */ + /* String info. */ extra_info = Fcons (string_info, - Fcons (make_number (textpos), + Fcons (textpos < 0 ? Qnil : make_number (textpos), Fcons (Fcons (make_number (col), make_number (row)), extra_info))); @@ -5479,14 +5475,13 @@ make_lispy_event (struct input_event *event) case NON_ASCII_KEYSTROKE_EVENT: button_down_time = 0; - for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++) + for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++) if (event->code == lispy_accent_codes[i]) return modify_event_symbol (i, event->modifiers, Qfunction_key, Qnil, lispy_accent_keys, &accent_key_syms, - (sizeof (lispy_accent_keys) - / sizeof (lispy_accent_keys[0]))); + ARRAYELTS (lispy_accent_keys)); #if 0 #ifdef XK_kana_A @@ -5495,8 +5490,7 @@ make_lispy_event (struct input_event *event) event->modifiers & ~shift_modifier, Qfunction_key, Qnil, lispy_kana_keys, &func_key_syms, - (sizeof (lispy_kana_keys) - / sizeof (lispy_kana_keys[0]))); + ARRAYELTS (lispy_kana_keys)); #endif /* XK_kana_A */ #endif /* 0 */ @@ -5507,15 +5501,14 @@ make_lispy_event (struct input_event *event) event->modifiers, Qfunction_key, Qnil, iso_lispy_function_keys, &func_key_syms, - (sizeof (iso_lispy_function_keys) - / sizeof (iso_lispy_function_keys[0]))); + ARRAYELTS (iso_lispy_function_keys)); #endif /* Handle system-specific or unknown keysyms. */ if (event->code & (1 << 28) || event->code - FUNCTION_KEY_OFFSET < 0 || (event->code - FUNCTION_KEY_OFFSET - >= sizeof lispy_function_keys / sizeof *lispy_function_keys) + >= ARRAYELTS (lispy_function_keys)) || !lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) { /* We need to use an alist rather than a vector as the cache @@ -5534,20 +5527,17 @@ make_lispy_event (struct input_event *event) event->modifiers, Qfunction_key, Qnil, lispy_function_keys, &func_key_syms, - (sizeof (lispy_function_keys) - / sizeof (lispy_function_keys[0]))); + ARRAYELTS (lispy_function_keys)); #ifdef HAVE_NTGUI case MULTIMEDIA_KEY_EVENT: - if (event->code < (sizeof (lispy_multimedia_keys) - / sizeof (lispy_multimedia_keys[0])) + if (event->code < ARRAYELTS (lispy_multimedia_keys) && event->code > 0 && lispy_multimedia_keys[event->code]) { return modify_event_symbol (event->code, event->modifiers, Qfunction_key, Qnil, lispy_multimedia_keys, &func_key_syms, - (sizeof (lispy_multimedia_keys) - / sizeof (lispy_multimedia_keys[0]))); + ARRAYELTS (lispy_multimedia_keys)); } return Qnil; #endif @@ -6269,7 +6259,7 @@ static const char *const modifier_names[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "alt", "super", "hyper", "shift", "control", "meta" }; -#define NUM_MOD_NAMES (sizeof (modifier_names) / sizeof (modifier_names[0])) +#define NUM_MOD_NAMES ARRAYELTS (modifier_names) static Lisp_Object modifier_symbols; @@ -6877,6 +6867,20 @@ gobble_input (void) } } + /* If there was no error, make sure the pointer + is visible for all frames on this terminal. */ + if (nr >= 0) + { + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_TERMINAL (f) == t) + frame_make_pointer_visible (f); + } + } + if (hold_quit.kind != NO_EVENT) kbd_buffer_store_event (&hold_quit); } @@ -6887,8 +6891,6 @@ gobble_input (void) if (err && !nread) nread = -1; - frame_make_pointer_visible (); - return nread; } @@ -7294,7 +7296,7 @@ store_user_signal_events (void) } -static void menu_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*); +static void menu_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void *); static Lisp_Object menu_bar_one_keymap_changed_items; /* These variables hold the vector under construction within @@ -7304,7 +7306,7 @@ static Lisp_Object menu_bar_items_vector; static int menu_bar_items_index; -static const char* separator_names[] = { +static const char *separator_names[] = { "space", "no-line", "single-line", @@ -7912,7 +7914,8 @@ static Lisp_Object QCrtl; /* Function prototypes. */ static void init_tool_bar_items (Lisp_Object); -static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*); +static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, + void *); static bool parse_tool_bar_item (Lisp_Object, Lisp_Object); static void append_tool_bar_item (void); @@ -8934,8 +8937,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, echo_now (); } else if (cursor_in_echo_area - && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes))) + && echo_keystrokes_p ()) /* This doesn't put in a dash if the echo buffer is empty, so you don't always see a dash hanging out in the minibuffer. */ echo_dash (); @@ -9067,8 +9069,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, { key = keybuf[t]; add_command_key (key); - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes)) + if (echo_keystrokes_p () && current_kboard->immediate_echo) { echo_add_key (key); @@ -9732,8 +9733,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, Better ideas? */ for (; t < mock_input; t++) { - if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) - && NILP (Fzerop (Vecho_keystrokes))) + if (echo_keystrokes_p ()) echo_char (keybuf[t]); add_command_key (keybuf[t]); } @@ -9764,7 +9764,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo, memset (keybuf, 0, sizeof keybuf); GCPRO1 (keybuf[0]); - gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0])); + gcpro1.nvars = ARRAYELTS (keybuf); if (NILP (continue_echo)) { @@ -9778,7 +9778,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo, cancel_hourglass (); #endif - i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), + i = read_key_sequence (keybuf, ARRAYELTS (keybuf), prompt, ! NILP (dont_downcase_last), ! NILP (can_return_switch_frame), 0, 0); @@ -10691,7 +10691,7 @@ The elements of this list correspond to the arguments of } XSETFASTINT (val[3], quit_char); - return Flist (sizeof (val) / sizeof (val[0]), val); + return Flist (ARRAYELTS (val), val); } DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 4, 0, @@ -11059,7 +11059,7 @@ syms_of_keyboard (void) { int i; - int len = sizeof (head_table) / sizeof (head_table[0]); + int len = ARRAYELTS (head_table); for (i = 0; i < len; i++) { @@ -11075,14 +11075,13 @@ syms_of_keyboard (void) staticpro (&button_down_location); mouse_syms = Fmake_vector (make_number (5), Qnil); staticpro (&mouse_syms); - wheel_syms = Fmake_vector (make_number (sizeof (lispy_wheel_names) - / sizeof (lispy_wheel_names[0])), + wheel_syms = Fmake_vector (make_number (ARRAYELTS (lispy_wheel_names)), Qnil); staticpro (&wheel_syms); { int i; - int len = sizeof (modifier_names) / sizeof (modifier_names[0]); + int len = ARRAYELTS (modifier_names); modifier_symbols = Fmake_vector (make_number (len), Qnil); for (i = 0; i < len; i++) @@ -11401,6 +11400,7 @@ and tests the value when the command returns. Buffer modification stores t in this variable. */); Vdeactivate_mark = Qnil; DEFSYM (Qdeactivate_mark, "deactivate-mark"); + Fmake_variable_buffer_local (Qdeactivate_mark); DEFVAR_LISP ("pre-command-hook", Vpre_command_hook, doc: /* Normal hook run before each command is executed. diff --git a/src/keyboard.h b/src/keyboard.h index 8bb54dd86e0..da83b9b01ed 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -305,9 +305,7 @@ extern Lisp_Object menu_items; /* If non-nil, means that the global vars defined here are already in use. Used to detect cases where we try to re-enter this non-reentrant code. */ -#if defined USE_GTK || defined USE_MOTIF extern Lisp_Object menu_items_inuse; -#endif /* Number of slots currently allocated in menu_items. */ extern int menu_items_allocated; @@ -354,57 +352,6 @@ extern void unuse_menu_items (void); #define ENCODE_MENU_STRING(str) (str) #endif -#if defined (HAVE_NS) || defined (HAVE_NTGUI) || defined (USE_GTK) - -/* Definitions copied from lwlib.h */ - -enum button_type -{ - BUTTON_TYPE_NONE, - BUTTON_TYPE_TOGGLE, - BUTTON_TYPE_RADIO -}; - -/* This structure is based on the one in ../lwlib/lwlib.h, with unused portions - removed. No term uses these. */ -typedef struct _widget_value -{ - /* name of widget */ - Lisp_Object lname; - const char* name; - /* value (meaning depend on widget type) */ - const char* value; - /* keyboard equivalent. no implications for XtTranslations */ - Lisp_Object lkey; - const char* key; - /* Help string or nil if none. - GC finds this string through the frame's menu_bar_vector - or through menu_items. */ - Lisp_Object help; - /* true if enabled */ - unsigned char enabled; - /* true if selected */ - unsigned char selected; - /* The type of a button. */ - enum button_type button_type; -#if defined (HAVE_NTGUI) - /* true if menu title */ - unsigned char title; -#endif - /* Contents of the sub-widgets, also selected slot for checkbox */ - struct _widget_value* contents; - /* data passed to callback */ - void *call_data; - /* next one in the list */ - struct _widget_value* next; -#ifdef USE_GTK - struct _widget_value *free_list; -#endif -} widget_value; - -#endif /* HAVE_NS || HAVE_NTGUI */ - - /* Macros for dealing with lispy events. */ /* True if EVENT has data fields describing it (i.e. a mouse click). */ @@ -466,9 +413,7 @@ extern bool waiting_for_input; happens. */ extern struct timespec *input_available_clear_time; -#if defined HAVE_WINDOW_SYSTEM && !defined USE_GTK && !defined HAVE_NS extern bool ignore_mouse_drag_p; -#endif /* The primary selection. */ extern Lisp_Object QPRIMARY; @@ -518,9 +463,7 @@ extern bool input_polling_used (void); extern void clear_input_pending (void); extern bool requeued_events_pending_p (void); extern void bind_polling_period (int); -#if HAVE_NTGUI extern int make_ctrl_char (int) ATTRIBUTE_CONST; -#endif extern void stuff_buffered_input (Lisp_Object); extern void clear_waiting_for_input (void); extern void swallow_events (bool); diff --git a/src/keymap.c b/src/keymap.c index c1416f8a780..0b2b61dcc05 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1383,9 +1383,7 @@ silly_event_symbol_error (Lisp_Object c) c = reorder_modifiers (c); keystring = concat2 (build_string (new_mods), XCDR (assoc)); - error ((modifiers & ~meta_modifier - ? "To bind the key %s, use [?%s], not [%s]" - : "To bind the key %s, use \"%s\", not [%s]"), + error ("To bind the key %s, use [?%s], not [%s]", SDATA (SYMBOL_NAME (c)), SDATA (keystring), SDATA (SYMBOL_NAME (c))); } @@ -1894,7 +1892,7 @@ struct accessible_keymaps_data { static void accessible_keymaps_1 (Lisp_Object key, Lisp_Object cmd, Lisp_Object args, void *data) -/* Use void* data to be compatible with map_keymap_function_t. */ +/* Use void * data to be compatible with map_keymap_function_t. */ { struct accessible_keymaps_data *d = data; /* Cast! */ Lisp_Object maps = d->maps; diff --git a/src/keymap.h b/src/keymap.h index 4a408c6a2a0..b01886dfa61 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -46,7 +46,7 @@ extern void syms_of_keymap (void); extern void keys_of_keymap (void); typedef void (*map_keymap_function_t) - (Lisp_Object key, Lisp_Object val, Lisp_Object args, void* data); + (Lisp_Object key, Lisp_Object val, Lisp_Object args, void *data); extern void map_keymap (Lisp_Object, map_keymap_function_t, Lisp_Object, void *, bool); extern void map_keymap_canonical (Lisp_Object map, diff --git a/src/lisp.h b/src/lisp.h index 2b632ad19f1..280886d063a 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -59,16 +59,6 @@ INLINE_HEADER_BEGIN # define ENUMABLE(val) 0 #endif -/* On AIX 7.1 ENUMABLE should return true when possible, otherwise the - linker can optimize the symbols away, making it harder to debug. - This was discovered only late in the release process, so to play it - safe for now, non-AIX platforms do not use enums for debugging symbols. - FIXME: remove this comment and the following four lines of code. */ -#ifndef _AIX -# undef ENUMABLE -# define ENUMABLE(val) 0 -#endif - #define DEFINE_GDB_SYMBOL_ENUM(id) enum { id = id##_val }; #if defined MAIN_PROGRAM # define DEFINE_GDB_SYMBOL_BEGIN(type, id) type const id EXTERNALLY_VISIBLE @@ -84,6 +74,26 @@ INLINE_HEADER_BEGIN #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) +/* Number of elements in an array. */ +#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) + +/* Number of bits in a Lisp_Object tag. */ +DEFINE_GDB_SYMBOL_BEGIN (int, GCTYPEBITS) +#define GCTYPEBITS 3 +DEFINE_GDB_SYMBOL_END (GCTYPEBITS) + +/* The number of bits needed in an EMACS_INT over and above the number + of bits in a pointer. This is 0 on systems where: + 1. We can specify multiple-of-8 alignment on static variables. + 2. We know malloc returns a multiple of 8. */ +#if (defined alignas \ + && (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \ + || defined DARWIN_OS || defined __sun || defined __MINGW32__)) +# define NONPOINTER_BITS 0 +#else +# define NONPOINTER_BITS GCTYPEBITS +#endif + /* EMACS_INT - signed integer wide enough to hold an Emacs value EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if pI - printf length modifier for EMACS_INT @@ -91,16 +101,18 @@ INLINE_HEADER_BEGIN #ifndef EMACS_INT_MAX # if INTPTR_MAX <= 0 # error "INTPTR_MAX misconfigured" -# elif INTPTR_MAX <= INT_MAX && !defined WIDE_EMACS_INT +# elif INTPTR_MAX <= INT_MAX >> NONPOINTER_BITS && !defined WIDE_EMACS_INT typedef int EMACS_INT; typedef unsigned int EMACS_UINT; # define EMACS_INT_MAX INT_MAX # define pI "" -# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT +# elif INTPTR_MAX <= LONG_MAX >> NONPOINTER_BITS && !defined WIDE_EMACS_INT typedef long int EMACS_INT; typedef unsigned long EMACS_UINT; # define EMACS_INT_MAX LONG_MAX # define pI "l" +/* Check versus LLONG_MAX, not LLONG_MAX >> NONPOINTER_BITS. + In theory this is not safe, but in practice it seems to be OK. */ # elif INTPTR_MAX <= LLONG_MAX typedef long long int EMACS_INT; typedef unsigned long long int EMACS_UINT; @@ -119,7 +131,7 @@ enum { BOOL_VECTOR_BITS_PER_CHAR = }; /* An unsigned integer type representing a fixed-length bit sequence, - suitable for words in a Lisp bool vector. Normally it is size_t + suitable for bool vector words, GC mark bits, etc. Normally it is size_t for speed, but it is unsigned char on weird platforms. */ #if BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT typedef size_t bits_word; @@ -137,7 +149,6 @@ enum { BITS_PER_CHAR = CHAR_BIT, BITS_PER_SHORT = CHAR_BIT * sizeof (short), - BITS_PER_INT = CHAR_BIT * sizeof (int), BITS_PER_LONG = CHAR_BIT * sizeof (long int), BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) }; @@ -241,12 +252,6 @@ extern bool suppress_checking EXTERNALLY_VISIBLE; enum Lisp_Bits { - /* Number of bits in a Lisp_Object tag. This can be used in #if, - and for GDB's sake also as a regular symbol. */ - GCTYPEBITS = -#define GCTYPEBITS 3 - GCTYPEBITS, - /* 2**GCTYPEBITS. This must be a macro that expands to a literal integer constant, for MSVC. */ #define GCALIGNMENT 8 @@ -270,31 +275,19 @@ enum Lisp_Bits This can be used in #if, e.g., '#if VAL_MAX < UINTPTR_MAX' below. */ #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1)) -/* Unless otherwise specified, use USE_LSB_TAG on systems where: */ -#ifndef USE_LSB_TAG -/* 1. We know malloc returns a multiple of 8. */ -# if (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \ - || defined DARWIN_OS || defined __sun) -/* 2. We can specify multiple-of-8 alignment on static variables. */ -# ifdef alignas -/* 3. Pointers-as-ints exceed VAL_MAX. +/* Whether the least-significant bits of an EMACS_INT contain the tag. On hosts where pointers-as-ints do not exceed VAL_MAX, USE_LSB_TAG is: a. unnecessary, because the top bits of an EMACS_INT are unused, and b. slower, because it typically requires extra masking. - So, default USE_LSB_TAG to true only on hosts where it might be useful. */ -# if VAL_MAX < UINTPTR_MAX -# define USE_LSB_TAG true -# endif -# endif -# endif -#endif -#ifdef USE_LSB_TAG -# undef USE_LSB_TAG -enum enum_USE_LSB_TAG { USE_LSB_TAG = true }; -# define USE_LSB_TAG true -#else -enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; -# define USE_LSB_TAG false + So, USE_LSB_TAG is true only on hosts where it might be useful. */ +DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG) +#define USE_LSB_TAG (EMACS_INT_MAX >> GCTYPEBITS < INTPTR_MAX) +DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) + +#if !USE_LSB_TAG && !defined WIDE_EMACS_INT +# error "USE_LSB_TAG not supported on this platform; please report this." \ + "Try 'configure --with-wide-int' to work around the problem." +error !; #endif #ifndef alignas @@ -369,15 +362,15 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = false }; #define lisp_h_XCONS(a) \ (eassert (CONSP (a)), (struct Lisp_Cons *) XUNTAG (a, Lisp_Cons)) #define lisp_h_XHASH(a) XUINT (a) -#define lisp_h_XPNTR(a) \ - ((void *) (intptr_t) ((XLI (a) & VALMASK) | (DATA_SEG_BITS & ~VALMASK))) +#define lisp_h_XPNTR(a) ((void *) (intptr_t) (XLI (a) & VALMASK)) #define lisp_h_XSYMBOL(a) \ (eassert (SYMBOLP (a)), (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol)) #ifndef GC_CHECK_CONS_LIST # define lisp_h_check_cons_list() ((void) 0) #endif #if USE_LSB_TAG -# define lisp_h_make_number(n) XIL ((EMACS_INT) (n) << INTTYPEBITS) +# define lisp_h_make_number(n) \ + XIL ((EMACS_INT) ((EMACS_UINT) (n) << INTTYPEBITS)) # define lisp_h_XFASTINT(a) XINT (a) # define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS) # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) @@ -641,18 +634,8 @@ enum pvec_type PVEC_FONT /* Should be last because it's used for range checking. */ }; -/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers - which were stored in a Lisp_Object. */ -#ifndef DATA_SEG_BITS -# define DATA_SEG_BITS 0 -#endif -enum { gdb_DATA_SEG_BITS = DATA_SEG_BITS }; -#undef DATA_SEG_BITS - enum More_Lisp_Bits { - DATA_SEG_BITS = gdb_DATA_SEG_BITS, - /* For convenience, we also store the number of elements in these bits. Note that this size is not necessarily the memory-footprint size, but only the number of Lisp_Object fields (that need to be traced by GC). @@ -714,7 +697,14 @@ LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type)) INLINE Lisp_Object make_number (EMACS_INT n) { - return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK); + if (USE_LSB_TAG) + { + EMACS_UINT u = n; + n = u << INTTYPEBITS; + } + else + n &= INTMASK; + return XIL (n); } /* Extract A's value as a signed integer. */ @@ -722,7 +712,12 @@ INLINE EMACS_INT XINT (Lisp_Object a) { EMACS_INT i = XLI (a); - return (USE_LSB_TAG ? i : i << INTTYPEBITS) >> INTTYPEBITS; + if (! USE_LSB_TAG) + { + EMACS_UINT u = i; + i = u << INTTYPEBITS; + } + return i >> INTTYPEBITS; } /* Like XINT (A), but may be faster. A must be nonnegative. @@ -842,6 +837,7 @@ extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object); /* Defined in emacs.c. */ extern bool initialized; +extern bool might_dump; /* Defined in eval.c. */ extern Lisp_Object Qautoload; @@ -2690,16 +2686,11 @@ CHECK_NUMBER_CDR (Lisp_Object x) minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #else /* not _MSC_VER */ -# if __STDC_VERSION__ < 199901 -# define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname -# else -# define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname -# endif #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ - { DEFUN_FUNCTION_INIT (fnname, maxargs) }, \ + { .a ## maxargs = fnname }, \ minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #endif @@ -3788,6 +3779,7 @@ extern void init_alloc (void); extern void syms_of_alloc (void); extern struct buffer * allocate_buffer (void); extern int valid_lisp_object_p (Lisp_Object); +extern int relocatable_string_data_p (const char *); #ifdef GC_CHECK_CONS_LIST extern void check_cons_list (void); #else @@ -3796,9 +3788,9 @@ INLINE void (check_cons_list) (void) { lisp_h_check_cons_list (); } #ifdef REL_ALLOC /* Defined in ralloc.c. */ -extern void *r_alloc (void **, size_t); +extern void *r_alloc (void **, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void r_alloc_free (void **); -extern void *r_re_alloc (void **, size_t); +extern void *r_re_alloc (void **, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void r_alloc_reset_variable (void **, void **); extern void r_alloc_inhibit_buffer_relocation (int); #endif @@ -3992,7 +3984,7 @@ extern bool overlay_touches_p (ptrdiff_t); extern Lisp_Object other_buffer_safely (Lisp_Object); extern Lisp_Object get_truename_buffer (Lisp_Object); extern void init_buffer_once (void); -extern void init_buffer (void); +extern void init_buffer (int); extern void syms_of_buffer (void); extern void keys_of_buffer (void); @@ -4075,6 +4067,7 @@ extern void syms_of_minibuf (void); /* Defined in callint.c. */ extern Lisp_Object Qminus, Qplus; +extern Lisp_Object Qprogn; extern Lisp_Object Qwhen; extern Lisp_Object Qmouse_leave_buffer_hook; extern void syms_of_callint (void); @@ -4134,9 +4127,7 @@ extern void set_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object); extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object); -#if HAVE_NS || HAVE_NTGUI extern Lisp_Object get_frame_param (struct frame *, Lisp_Object); -#endif extern void frames_discard_buffer (Lisp_Object); extern void syms_of_frame (void); @@ -4187,10 +4178,8 @@ extern bool running_asynch_code; /* Defined in process.c. */ extern Lisp_Object QCtype, Qlocal; extern void kill_buffer_processes (Lisp_Object); -extern bool wait_reading_process_output (intmax_t, int, int, bool, - Lisp_Object, - struct Lisp_Process *, - int); +extern int wait_reading_process_output (intmax_t, int, int, bool, Lisp_Object, + struct Lisp_Process *, int); /* Max value for the first argument of wait_reading_process_output. */ #if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) /* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3. @@ -4282,8 +4271,6 @@ extern void init_sigio (int); extern void sys_subshell (void); extern void sys_suspend (void); extern void discard_tty_input (void); -extern void block_tty_out_signal (void); -extern void unblock_tty_out_signal (void); 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); @@ -4433,16 +4420,17 @@ extern bool initialized; /* True means ^G can quit instantly. */ extern bool immediate_quit; -extern void *xmalloc (size_t); -extern void *xzalloc (size_t); -extern void *xrealloc (void *, size_t); +extern void *xmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); +extern void *xzalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); +extern void *xrealloc (void *, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void xfree (void *); -extern void *xnmalloc (ptrdiff_t, ptrdiff_t); -extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t); +extern void *xnmalloc (ptrdiff_t, ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1,2)); +extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t) + ATTRIBUTE_ALLOC_SIZE ((2,3)); extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t); -extern char *xstrdup (const char *); -extern char *xlispstrdup (Lisp_Object); +extern char *xstrdup (const char *) ATTRIBUTE_MALLOC; +extern char *xlispstrdup (Lisp_Object) ATTRIBUTE_MALLOC; extern void dupstring (char **, char const *); extern void xputenv (const char *); @@ -4474,7 +4462,7 @@ extern void init_system_name (void); enum MAX_ALLOCA { MAX_ALLOCA = 16 * 1024 }; -extern void *record_xmalloc (size_t); +extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1)); #define USE_SAFE_ALLOCA \ ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = false diff --git a/src/lread.c b/src/lread.c index 4990d25eda1..4edd1177fb4 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1763,6 +1763,29 @@ end_of_file_error (void) xsignal0 (Qend_of_file); } +static Lisp_Object +readevalloop_eager_expand_eval (Lisp_Object val, Lisp_Object macroexpand) +{ + /* If we macroexpand the toplevel form non-recursively and it ends + up being a `progn' (or if it was a progn to start), treat each + form in the progn as a top-level form. This way, if one form in + the progn defines a macro, that macro is in effect when we expand + the remaining forms. See similar code in bytecomp.el. */ + val = call2 (macroexpand, val, Qnil); + if (EQ (CAR_SAFE (val), Qprogn)) + { + Lisp_Object subforms = XCDR (val); + val = Qnil; + for (; CONSP (subforms); subforms = XCDR (subforms)) + val = readevalloop_eager_expand_eval (XCAR (subforms), + macroexpand); + } + else + val = eval_sub (call2 (macroexpand, val, Qt)); + + return val; +} + /* UNIBYTE specifies how to set load_convert_to_unibyte for this invocation. READFUN, if non-nil, is used instead of `read'. @@ -1930,8 +1953,9 @@ readevalloop (Lisp_Object readcharfun, /* Now eval what we just read. */ if (!NILP (macroexpand)) - val = call1 (macroexpand, val); - val = eval_sub (val); + val = readevalloop_eager_expand_eval (val, macroexpand); + else + val = eval_sub (val); if (printflag) { diff --git a/src/macfont.m b/src/macfont.m index 075b512e686..9b3cb2c29f6 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -237,8 +237,7 @@ mac_font_get_glyph_for_cid (FontRef font, CharacterCollection collection, unichar characters[] = {0xfffd}; NSString *string = [NSString stringWithCharacters:characters - length:(sizeof (characters) - / sizeof (characters[0]))]; + length:ARRAYELTS (characters)]; NSGlyphInfo *glyphInfo = [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid collection:collection @@ -777,7 +776,7 @@ cfnumber_get_font_symbolic_traits_value (CFNumberRef number, SInt64 sint64_value; /* Getting symbolic traits with kCFNumberSInt32Type is lossy on Mac - OS 10.6 when the value is greater than or equal to 1 << 31. */ + OS X 10.6 when the value is greater than or equal to 1 << 31. */ if (CFNumberGetValue (number, kCFNumberSInt64Type, &sint64_value)) { *sym_traits = (FontSymbolicTraits) sint64_value; @@ -826,7 +825,7 @@ macfont_store_descriptor_attributes (FontDescriptorRef desc, {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}}; int i; - for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++) + for (i = 0; i < ARRAYELTS (numeric_traits); i++) { num = CFDictionaryGetValue (dict, numeric_traits[i].trait); if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval)) @@ -1252,8 +1251,7 @@ macfont_lookup_cache (CFStringRef key) CTFontCopyCharacterSet nor -[NSFont coveredCharacterSet] for this font is correct for non-BMP characters on Mac OS X 10.5, anyway. */ - if (CFStringCompare (key, CFSTR ("LastResort"), 0) - == kCFCompareEqualTo) + if (CFEqual (key, CFSTR ("LastResort"))) { CFRange range = CFRangeMake (0, MAX_UNICODE_CHAR + 1); @@ -1908,7 +1906,7 @@ macfont_create_attributes_with_spec (Lisp_Object spec) if (! traits) goto err; - for (i = 0; i < sizeof (numeric_traits) / sizeof (numeric_traits[0]); i++) + for (i = 0; i < ARRAYELTS (numeric_traits); i++) { tmp = AREF (spec, numeric_traits[i].index); if (INTEGERP (tmp)) @@ -2211,27 +2209,26 @@ macfont_list (struct frame *f, Lisp_Object spec) 10.7 returns NULL if pat_desc represents the LastResort font. So we use CTFontDescriptorCreateMatchingFontDescriptor (no trailing "s") for such a font. */ - if (CFStringCompare (family_name, CFSTR ("LastResort"), 0) - != kCFCompareEqualTo) - descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc, - NULL); + if (!CFEqual (family_name, CFSTR ("LastResort"))) + descs = mac_font_descriptor_create_matching_font_descriptors (pat_desc, + NULL); else - { - FontDescriptorRef lr_desc = - mac_font_descriptor_create_matching_font_descriptor (pat_desc, - NULL); - if (lr_desc) - { - descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1, - &kCFTypeArrayCallBacks); - CFRelease (lr_desc); - } - else - descs = NULL; - } + { + FontDescriptorRef lr_desc = + mac_font_descriptor_create_matching_font_descriptor (pat_desc, + NULL); + if (lr_desc) + { + descs = CFArrayCreate (NULL, (const void **) &lr_desc, 1, + &kCFTypeArrayCallBacks); + CFRelease (lr_desc); + } + else + descs = NULL; + } CFRelease (pat_desc); if (! descs) - goto err; + goto err; descs_count = CFArrayGetCount (descs); if (descs_count == 0 @@ -2572,12 +2569,9 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size) family_name = mac_font_copy_family_name (macfont); if (family_name) { - if ((CFStringCompare (family_name, CFSTR ("Courier"), 0) - == kCFCompareEqualTo) - || (CFStringCompare (family_name, CFSTR ("Helvetica"), 0) - == kCFCompareEqualTo) - || (CFStringCompare (family_name, CFSTR ("Times"), 0) - == kCFCompareEqualTo)) + if (CFEqual (family_name, CFSTR ("Courier")) + || CFEqual (family_name, CFSTR ("Helvetica")) + || CFEqual (family_name, CFSTR ("Times"))) ascent += (ascent + descent) * .15f; else if (CFStringHasPrefix (family_name, CFSTR ("Hiragino"))) { @@ -2712,33 +2706,54 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, { struct frame * f = s->f; struct macfont_info *macfont_info = (struct macfont_info *) s->font; - FontRef macfont = macfont_info->macfont; - CGContextRef context; - BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; - int end = isComposite ? s->cmp_to : s->nchars; - int len = end - s->cmp_from; + CGRect background_rect; + CGPoint text_position; + CGGlyph *glyphs; + CGPoint *positions; + CGFloat font_size = mac_font_get_size (macfont_info->macfont); + bool no_antialias_p = + (macfont_info->antialias == MACFONT_ANTIALIAS_OFF + || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT + && font_size <= macfont_antialias_threshold)); + int len = to - from; struct face *face = s->face; - int i; + CGContextRef context; block_input (); - context = [[NSGraphicsContext currentContext] graphicsPort]; - CGContextSaveGState (context); + if (with_background) + background_rect = CGRectMake (x, y - FONT_BASE (s->font), + s->width, FONT_HEIGHT (s->font)); + else + background_rect = CGRectNull; + + text_position = CGPointMake (x, -y); + glyphs = xmalloc (sizeof (CGGlyph) * len); + { + CGFloat advance_delta; + int i; + CGFloat total_width = 0; -#if 0 - if (s->num_clips > 0) - { - CGRect clips[2]; + positions = xmalloc (sizeof (CGPoint) * len); + for (i = 0; i < len; i++) + { + int width; + + glyphs[i] = s->char2b[from + i]; + width = (s->padding_p ? 1 + : macfont_glyph_extents (s->font, glyphs[i], + NULL, &advance_delta, + no_antialias_p)); + positions[i].x = total_width + advance_delta; + positions[i].y = 0; + total_width += width; + } + } - for (i = 0; i < s->num_clips; i++) - clips[i] = mac_rect_make (f, s->clip[i].left, s->clip[i].top, - s->clip[i].right - s->clip[i].left, - s->clip[i].bottom - s->clip[i].top); - CGContextClipToRects (context, clips, s->num_clips); - } -#endif + context = [[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState (context); - if (with_background) + if (!CGRectIsNull (background_rect)) { if (s->hl == DRAW_MOUSE_FACE) { @@ -2746,41 +2761,13 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, if (!face) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); } - CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face, f); - CGContextFillRect (context, - CGRectMake (x, y, - s->width, FONT_HEIGHT (s->font))); + CGContextFillRects (context, &background_rect, 1); } if (macfont_info->cgfont) { - CGGlyph *glyphs = alloca (sizeof (CGGlyph) * len); - CGPoint *positions = alloca (sizeof (CGPoint) * len); - CGFloat total_width = 0; - CGFloat font_size = mac_font_get_size (macfont); CGAffineTransform atfm; - CGFloat advance_delta = 0; - int y_draw = -s->ybase; - int no_antialias_p = - (macfont_info->antialias == MACFONT_ANTIALIAS_OFF - || (macfont_info->antialias == MACFONT_ANTIALIAS_DEFAULT - && font_size <= macfont_antialias_threshold)); - - for (i = 0; i < len; i++) - { - int width; - - glyphs[i] = *(s->char2b + s->cmp_from + i); - width = (s->padding_p ? 1 - : macfont_glyph_extents (s->font, glyphs[i], - NULL, &advance_delta, - no_antialias_p)); - positions[i].x = total_width + advance_delta; - positions[i].y = 0; - total_width += width; - } - CGContextScaleCTM (context, 1, -1); CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face, s->f); if (macfont_info->synthetic_italic_p) @@ -2797,7 +2784,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, CGContextSetShouldAntialias (context, false); CGContextSetTextMatrix (context, atfm); - CGContextSetTextPosition (context, x, y_draw); + CGContextSetTextPosition (context, text_position.x, text_position.y); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (macfont_info->color_bitmap_p @@ -2808,7 +2795,8 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, { if (len > 0) { - CTFontDrawGlyphs (macfont, glyphs, positions, len, context); + CTFontDrawGlyphs (macfont_info->macfont, glyphs, positions, len, + context); } } else @@ -2820,6 +2808,9 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, } } + + xfree (glyphs); + xfree (positions); CGContextRestoreGState (context); unblock_input (); @@ -3558,7 +3549,7 @@ mac_ctfont_equal_in_postscript_name (CTFontRef font1, CTFontRef font2) name2 = CTFontCopyPostScriptName (font2); if (name2) { - result = (CFStringCompare (name1, name2, 0) == kCFCompareEqualTo); + result = CFEqual (name1, name2); CFRelease (name2); } CFRelease (name1); @@ -3584,7 +3575,7 @@ mac_ctfont_create_line_with_string_and_font (CFStringRef string, { attributes = CFDictionaryCreate (NULL, (const void **) keys, (const void **) values, - sizeof (keys) / sizeof (keys[0]), + ARRAYELTS (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease (values[1]); @@ -3795,8 +3786,8 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, CTLineRef ctline = NULL; string = CFStringCreateWithCharacters (NULL, characters, - sizeof (characters) - / sizeof (characters[0])); + ARRAYELTS (characters)); + if (string) { CTGlyphInfoRef glyph_info = @@ -3811,7 +3802,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, attributes = CFDictionaryCreate (NULL, (const void **) keys, (const void **) values, - sizeof (keys) / sizeof (keys[0]), + ARRAYELTS (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease (glyph_info); @@ -3931,8 +3922,8 @@ mac_font_copy_default_descriptors_for_language (CFStringRef language) for (i = 0; macfont_language_default_font_names[i].language; i++) { - if (CFStringCompare (macfont_language_default_font_names[i].language, - language, 0) == kCFCompareEqualTo) + if (CFEqual (macfont_language_default_font_names[i].language, + language)) { CFMutableArrayRef descriptors = CFArrayCreateMutable (NULL, 0, &kCFTypeArrayCallBacks); @@ -4012,9 +4003,8 @@ mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset, if (family) { if (!CFStringHasPrefix (family, CFSTR (".")) - && (CFStringCompare (family, CFSTR ("LastResort"), 0) - != kCFCompareEqualTo)) - { + && !CFEqual (family, CFSTR ("LastResort"))) + { result = family; break; } diff --git a/src/menu.c b/src/menu.c index 468f2814eb4..460dc7967b5 100644 --- a/src/menu.c +++ b/src/menu.c @@ -66,9 +66,6 @@ Lisp_Object menu_items; /* If non-nil, means that the global vars defined here are already in use. Used to detect cases where we try to re-enter this non-reentrant code. */ -#if ! (defined USE_GTK || defined USE_MOTIF) -static -#endif Lisp_Object menu_items_inuse; /* Number of slots currently allocated in menu_items. */ @@ -576,21 +573,26 @@ parse_single_submenu (Lisp_Object item_key, Lisp_Object item_name, #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI) -/* Allocate a widget_value, blocking input. */ +/* Allocate and basically initialize widget_value, blocking input. */ widget_value * -xmalloc_widget_value (void) +make_widget_value (const char *name, char *value, + bool enabled, Lisp_Object help) { - widget_value *value; + widget_value *wv; block_input (); - value = malloc_widget_value (); + wv = xzalloc (sizeof (widget_value)); unblock_input (); - return value; + wv->name = (char *) name; + wv->value = value; + wv->enabled = enabled; + wv->help = help; + return wv; } -/* This recursively calls free_widget_value on the tree of widgets. +/* This recursively calls xfree on the tree of widgets. It must free all data that was malloc'ed for these widget_values. In Emacs, many slots are pointers into the data of Lisp_Strings, and must be left alone. */ @@ -613,7 +615,7 @@ free_menubar_widget_value_tree (widget_value *wv) wv->next = (widget_value *) 0xDEADBEEF; } block_input (); - free_widget_value (wv); + xfree (wv); unblock_input (); } @@ -632,12 +634,8 @@ digest_single_submenu (int start, int end, bool top_level_items) struct frame *f = XFRAME (Vmenu_updating_frame); submenu_stack = alloca (menu_items_used * sizeof *submenu_stack); - wv = xmalloc_widget_value (); - wv->name = "menu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; save_wv = 0; prev_wv = 0; @@ -721,17 +719,14 @@ digest_single_submenu (int start, int end, bool top_level_items) with its items as a submenu beneath it. */ if (strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + /* Set value to 1 so update_submenu_strings can handle '@'. */ + wv = make_widget_value (NULL, (char *) 1, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; wv->lname = pane_name; - /* Set value to 1 so update_submenu_strings can handle '@' */ - wv->value = (char *)1; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; } else @@ -805,7 +800,8 @@ digest_single_submenu (int start, int end, bool top_level_items) #endif } - wv = xmalloc_widget_value (); + wv = make_widget_value (NULL, NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else @@ -814,11 +810,9 @@ digest_single_submenu (int start, int end, bool top_level_items) wv->lname = item_name; if (!NILP (descrip)) wv->lkey = descrip; - wv->value = 0; /* The intptr_t cast avoids a warning. There's no problem as long as pointers have enough bits to hold small integers. */ wv->call_data = (!NILP (def) ? (void *) (intptr_t) i : 0); - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -830,10 +824,6 @@ digest_single_submenu (int start, int end, bool top_level_items) emacs_abort (); wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; prev_wv = wv; @@ -846,7 +836,7 @@ digest_single_submenu (int start, int end, bool top_level_items) if (top_level_items && first_wv->contents && first_wv->contents->next == 0) { wv = first_wv->contents; - free_widget_value (first_wv); + xfree (first_wv); return wv; } @@ -1168,9 +1158,7 @@ no quit occurs and `x-popup-menu' returns nil. */) Lisp_Object selection = Qnil; struct frame *f = NULL; Lisp_Object x, y, window; - bool keymaps = 0; - bool for_click = 0; - bool kbd_menu_navigation = 0; + int menuflags = 0; ptrdiff_t specpdl_count = SPECPDL_INDEX (); struct gcpro gcpro1; @@ -1200,12 +1188,12 @@ no quit occurs and `x-popup-menu' returns nil. */) } else { - for_click = 1; + menuflags |= MENU_FOR_CLICK; tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ window = Fcar (tem); /* POSN_WINDOW (tem) */ tem2 = Fcar (Fcdr (tem)); /* POSN_POSN (tem) */ - /* The kbd_menu_navigation flag is set when the menu was - invoked by F10, which probably means they have no + /* The MENU_KBD_NAVIGATION field is set when the menu + was invoked by F10, which probably means they have no mouse. In that case, we let them switch between top-level menu-bar menus by using C-f/C-b and horizontal arrow keys, since they cannot click the @@ -1218,7 +1206,7 @@ no quit occurs and `x-popup-menu' returns nil. */) if (!EQ (POSN_POSN (last_nonmenu_event), POSN_POSN (position)) && CONSP (tem2) && EQ (Fcar (tem2), Qmenu_bar)) - kbd_menu_navigation = 1; + menuflags |= MENU_KBD_NAVIGATION; tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */ x = Fcar (tem); y = Fcdr (tem); @@ -1347,7 +1335,7 @@ no quit occurs and `x-popup-menu' returns nil. */) if (!NILP (prompt) && menu_items_n_panes >= 0) ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt); - keymaps = 1; + menuflags |= MENU_KEYMAPS; } else if (CONSP (menu) && KEYMAPP (XCAR (menu))) { @@ -1380,7 +1368,7 @@ no quit occurs and `x-popup-menu' returns nil. */) if (!NILP (title) && menu_items_n_panes >= 0) ASET (menu_items, MENU_ITEMS_PANE_NAME, title); - keymaps = 1; + menuflags |= MENU_KEYMAPS; SAFE_FREE (); } @@ -1392,7 +1380,7 @@ no quit occurs and `x-popup-menu' returns nil. */) list_of_panes (Fcdr (menu)); - keymaps = 0; + menuflags &= ~MENU_KEYMAPS; } unbind_to (specpdl_count, Qnil); @@ -1422,40 +1410,12 @@ no quit occurs and `x-popup-menu' returns nil. */) record_unwind_protect_void (discard_menu_items); #endif - /* Display them in a menu. */ - - /* FIXME: Use a terminal hook! */ -#if defined HAVE_NTGUI - if (FRAME_W32_P (f)) - selection = w32_menu_show (f, xpos, ypos, for_click, - keymaps, title, &error_name); - else -#endif -#if defined HAVE_NS - if (FRAME_NS_P (f)) - selection = ns_menu_show (f, xpos, ypos, for_click, - keymaps, title, &error_name); - else -#endif -#if (defined (HAVE_X_WINDOWS) || defined (MSDOS)) - if (FRAME_X_P (f) || FRAME_MSDOS_P (f)) - selection = xmenu_show (f, xpos, ypos, for_click, - keymaps, title, &error_name); - else -#endif -#ifndef MSDOS - if (FRAME_TERMCAP_P (f)) - { - ptrdiff_t count1 = SPECPDL_INDEX (); - - /* Avoid crashes if, e.g., another client will connect while we - are in a menu. */ - temporarily_switch_to_single_kboard (f); - selection = tty_menu_show (f, xpos, ypos, for_click, keymaps, title, - kbd_menu_navigation, &error_name); - unbind_to (count1, Qnil); - } -#endif + /* Display them in a menu, but not if F is the initial frame that + doesn't have its hooks set (e.g., in a batch session), because + such a frame cannot display menus. */ + if (!FRAME_INITIAL_P (f)) + selection = FRAME_TERMINAL (f)->menu_show_hook (f, xpos, ypos, menuflags, + title, &error_name); #ifdef HAVE_NS unbind_to (specpdl_count, Qnil); @@ -1474,6 +1434,38 @@ no quit occurs and `x-popup-menu' returns nil. */) return selection; } +/* If F's terminal is not capable of displaying a popup dialog, + emulate it with a menu. */ + +static Lisp_Object +emulate_dialog_with_menu (struct frame *f, Lisp_Object contents) +{ + Lisp_Object x, y, frame, newpos, prompt = Fcar (contents); + int x_coord, y_coord; + + if (FRAME_WINDOW_P (f)) + { + x_coord = FRAME_PIXEL_WIDTH (f); + y_coord = FRAME_PIXEL_HEIGHT (f); + } + else + { + x_coord = FRAME_COLS (f); + /* Center the title at frame middle. (TTY menus have + their upper-left corner at the given position.) */ + if (STRINGP (prompt)) + x_coord -= SCHARS (prompt); + y_coord = FRAME_LINES (f); + } + + XSETFRAME (frame, f); + XSETINT (x, x_coord / 2); + XSETINT (y, y_coord / 2); + newpos = list2 (list2 (x, y), frame); + + return Fx_popup_menu (newpos, list2 (prompt, contents)); +} + DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, doc: /* Pop up a dialog box and return user's selection. POSITION specifies which frame to use. @@ -1506,24 +1498,7 @@ for instance using the window manager, then this produces a quit and if (EQ (position, Qt) || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) || EQ (XCAR (position), Qtool_bar)))) - { -#if 0 /* Using the frame the mouse is on may not be right. */ - /* Use the mouse's current position. */ - struct frame *new_f = SELECTED_FRAME (); - Lisp_Object bar_window; - enum scroll_bar_part part; - Time time; - Lisp_Object x, y; - - (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time); - - if (new_f != 0) - XSETFRAME (window, new_f); - else - window = selected_window; -#endif - window = selected_window; - } + window = selected_window; else if (CONSP (position)) { Lisp_Object tem = XCAR (position); @@ -1565,51 +1540,21 @@ for instance using the window manager, then this produces a quit and string contents, because Fredisplay may GC and relocate them. */ Fredisplay (Qt); -#if defined USE_X_TOOLKIT || defined USE_GTK - if (FRAME_WINDOW_P (f)) - return xw_popup_dialog (f, header, contents); -#endif -#ifdef HAVE_NTGUI - if (FRAME_W32_P (f)) + /* Display the popup dialog by a terminal-specific hook ... */ + if (FRAME_TERMINAL (f)->popup_dialog_hook) { - Lisp_Object selection = w32_popup_dialog (f, header, contents); - + Lisp_Object selection + = FRAME_TERMINAL (f)->popup_dialog_hook (f, header, contents); +#ifdef HAVE_NTGUI + /* NTGUI supports only simple dialogs with Yes/No choices. For + other dialogs, it returns the symbol 'unsupported--w32-dialog', + as a signal for the caller to fall back to the emulation code. */ if (!EQ (selection, Qunsupported__w32_dialog)) +#endif return selection; } -#endif -#ifdef HAVE_NS - if (FRAME_NS_P (f)) - return ns_popup_dialog (position, header, contents); -#endif - /* Display a menu with these alternatives - in the middle of frame F. */ - { - Lisp_Object x, y, frame, newpos, prompt; - int x_coord, y_coord; - - prompt = Fcar (contents); - if (FRAME_WINDOW_P (f)) - { - x_coord = FRAME_PIXEL_WIDTH (f); - y_coord = FRAME_PIXEL_HEIGHT (f); - } - else - { - x_coord = FRAME_COLS (f); - /* Center the title at frame middle. (TTY menus have their - upper-left corner at the given position.) */ - if (STRINGP (prompt)) - x_coord -= SCHARS (prompt); - y_coord = FRAME_LINES (f); - } - XSETFRAME (frame, f); - XSETINT (x, x_coord / 2); - XSETINT (y, y_coord / 2); - newpos = list2 (list2 (x, y), frame); - - return Fx_popup_menu (newpos, list2 (prompt, contents)); - } + /* ... or emulate it with a menu. */ + return emulate_dialog_with_menu (f, contents); } void diff --git a/src/menu.h b/src/menu.h index 429dcfa6221..643ff40fef8 100644 --- a/src/menu.h +++ b/src/menu.h @@ -20,11 +20,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define MENU_H #include "systime.h" /* for Time */ +#include "../lwlib/lwlib-widget.h" #ifdef HAVE_NTGUI extern Lisp_Object Qunsupported__w32_dialog; #endif +/* Bit fields used by terminal-specific menu_show_hook. */ + +enum { + MENU_KEYMAPS = 0x1, + MENU_FOR_CLICK = 0x2, + MENU_KBD_NAVIGATION = 0x4 +}; + extern void x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval); @@ -41,21 +50,26 @@ extern void free_menubar_widget_value_tree (widget_value *); extern void update_submenu_strings (widget_value *); extern void find_and_call_menu_selection (struct frame *, int, Lisp_Object, void *); -extern widget_value *xmalloc_widget_value (void); +extern widget_value *make_widget_value (const char *, char *, bool, Lisp_Object); extern widget_value *digest_single_submenu (int, int, bool); #endif #ifdef HAVE_X_WINDOWS extern void mouse_position_for_popup (struct frame *f, int *x, int *y); #endif - -extern Lisp_Object w32_menu_show (struct frame *, int, int, int, int, +#if defined (HAVE_X_WINDOWS) || defined (MSDOS) +extern Lisp_Object x_menu_show (struct frame *, int, int, int, + Lisp_Object, const char **); +#endif +#ifdef HAVE_NTGUI +extern Lisp_Object w32_menu_show (struct frame *, int, int, int, Lisp_Object, const char **); -extern Lisp_Object ns_menu_show (struct frame *, int, int, bool, bool, +#endif +#ifdef HAVE_NS +extern Lisp_Object ns_menu_show (struct frame *, int, int, int, Lisp_Object, const char **); -extern Lisp_Object xmenu_show (struct frame *, int, int, bool, bool, - Lisp_Object, const char **); -extern Lisp_Object tty_menu_show (struct frame *, int, int, bool, bool, - Lisp_Object, bool, const char **); +#endif +extern Lisp_Object tty_menu_show (struct frame *, int, int, int, + Lisp_Object, const char **); extern ptrdiff_t menu_item_width (const unsigned char *); #endif /* MENU_H */ diff --git a/src/minibuf.c b/src/minibuf.c index c3fcbeb59c7..3042b13b7d6 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -1970,7 +1970,7 @@ A value of t means no truncation. This variable only affects history lists that don't specify their own maximum lengths. Setting the `history-length' property of a history variable overrides this default. */); - XSETFASTINT (Vhistory_length, 30); + XSETFASTINT (Vhistory_length, 100); DEFVAR_BOOL ("history-delete-duplicates", history_delete_duplicates, doc: /* Non-nil means to delete duplicates in history. diff --git a/src/msdos.c b/src/msdos.c index 010a0a3746c..ccca371583f 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -566,7 +566,7 @@ dos_set_window_size (int *rows, int *cols) }; int i = 0; - while (i < sizeof (std_dimension) / sizeof (std_dimension[0])) + while (i < ARRAYELTS (std_dimension)) { if (std_dimension[i].need_vga <= have_vga && std_dimension[i].rows >= *rows) @@ -1863,6 +1863,7 @@ initialize_msdos_display (struct terminal *term) term->update_end_hook = IT_update_end; term->frame_up_to_date_hook = IT_frame_up_to_date; term->mouse_position_hook = 0; /* set later by dos_ttraw */ + term->menu_show_hook = x_menu_show; term->frame_rehighlight_hook = 0; term->frame_raise_lower_hook = 0; term->set_vertical_scroll_bar_hook = 0; @@ -3455,7 +3456,7 @@ init_environment (int argc, char **argv, int skip_args) static const char * const tempdirs[] = { "$TMPDIR", "$TEMP", "$TMP", "c:/" }; - const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]); + const int imax = ARRAYELTS (tempdirs); /* Make sure they have a usable $TMPDIR. Many Emacs functions use temporary files and assume "/tmp" if $TMPDIR is unset, which diff --git a/src/nsfns.m b/src/nsfns.m index 58746aed9fa..5f9588aea64 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -873,12 +873,16 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) static Lisp_Object ns_appkit_version_str (void) { - char tmp[80]; + char tmp[256]; #ifdef NS_IMPL_GNUSTEP sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION)); #elif defined (NS_IMPL_COCOA) - sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber); + NSString *osversion + = [[NSProcessInfo processInfo] operatingSystemVersionString]; + sprintf(tmp, "appkit-%.2f %s", + NSAppKitVersionNumber, + [osversion UTF8String]); #else tmp = "ns-unknown"; #endif @@ -1024,7 +1028,7 @@ get_geometry_from_preferences (struct ns_display_info *dpyinfo, }; int i; - for (i = 0; i < sizeof (r)/sizeof (r[0]); ++i) + for (i = 0; i < ARRAYELTS (r); ++i) { if (NILP (Fassq (r[i].tem, parms))) { @@ -2096,7 +2100,6 @@ ns_do_applescript (Lisp_Object script, Lisp_Object *result) returnDescriptor = [scriptObject executeAndReturnError: &errorDict]; [scriptObject release]; - *result = Qnil; if (returnDescriptor != NULL) @@ -2157,6 +2160,7 @@ In case the execution fails, an error is signaled. */) Lisp_Object result; int status; NSEvent *nxev; + struct input_event ev; CHECK_STRING (script); check_window_system (NULL); @@ -2184,8 +2188,10 @@ In case the execution fails, an error is signaled. */) // If there are other events, the event loop may exit. Keep running // until the script has been handled. */ + ns_init_events (&ev); while (! NILP (as_script)) [NSApp run]; + ns_finish_events (); status = as_status; as_status = 0; diff --git a/src/nsfont.m b/src/nsfont.m index 14e24c270e8..2c5e25b993c 100644 --- a/src/nsfont.m +++ b/src/nsfont.m @@ -1037,8 +1037,7 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, static int nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background) -/* NOTE: focus and clip must be set - also, currently assumed (true in nsterm.m call) from ==0, to ==nchars */ +/* NOTE: focus and clip must be set */ { static unsigned char cbuf[1024]; unsigned char *c = cbuf; @@ -1056,7 +1055,6 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, unsigned short *t = s->char2b; int i, len, flags; char isComposite = s->first_glyph->type == COMPOSITE_GLYPH; - int end = isComposite ? s->cmp_to : s->nchars; block_input (); @@ -1098,8 +1096,8 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, int cwidth, twidth = 0; int hi, lo; /* FIXME: composition: no vertical displacement is considered. */ - t += s->cmp_from; /* advance into composition */ - for (i = s->cmp_from; i < end; i++, t++) + t += from; /* advance into composition */ + for (i = from; i < to; i++, t++) { hi = (*t & 0xFF00) >> 8; lo = *t & 0x00FF; @@ -1193,7 +1191,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, /* set up for character rendering */ - r.origin.y = s->ybase; + r.origin.y = y; col = (NS_FACE_FOREGROUND (face) != 0 ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f) @@ -1275,13 +1273,13 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, [col set]; CGContextSetTextPosition (gcontext, r.origin.x, r.origin.y); - CGContextShowGlyphsWithAdvances (gcontext, s->char2b + s->cmp_from, + CGContextShowGlyphsWithAdvances (gcontext, s->char2b + from, advances, len); if (face->overstrike) { CGContextSetTextPosition (gcontext, r.origin.x+0.5, r.origin.y); - CGContextShowGlyphsWithAdvances (gcontext, s->char2b + s->cmp_from, + CGContextShowGlyphsWithAdvances (gcontext, s->char2b + from, advances, len); } diff --git a/src/nsgui.h b/src/nsgui.h index 5935531fa48..0e1e9bb73e9 100644 --- a/src/nsgui.h +++ b/src/nsgui.h @@ -48,11 +48,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #undef _GL_VERIFY_H #include <verify.h> -/* menu-related */ -#define free_widget_value(wv) xfree (wv) -#define malloc_widget_value() ((widget_value *) memset (xmalloc \ - (sizeof (widget_value)), 0, sizeof (widget_value))) - /* Emulate XCharStruct. */ typedef struct _XCharStruct { diff --git a/src/nsmenu.m b/src/nsmenu.m index 24842241f37..24c1189584b 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -266,12 +266,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) /* parse stage 2: insert into lucid 'widget_value' structures [comments in other terms say not to evaluate lisp code here] */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; i < 4*n; i += 4) @@ -378,12 +374,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) int n; Lisp_Object string; - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; /* Make widget-value tree w/ just the top level menu bar strings */ @@ -439,12 +431,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) memcpy (previous_strings[i/4], SDATA (string), min (10, SBYTES (string) + 1)); - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; wv->call_data = (void *) (intptr_t) (-1); #ifdef NS_IMPL_COCOA @@ -824,7 +812,7 @@ extern NSString *NSMenuDidBeginTrackingNotification; ========================================================================== */ Lisp_Object -ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, +ns_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error) { EmacsMenu *pmenu; @@ -832,18 +820,15 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, Lisp_Object tem; ptrdiff_t specpdl_count = SPECPDL_INDEX (); widget_value *wv, *first_wv = 0; + bool keymaps = (menuflags & MENU_KEYMAPS); block_input (); p.x = x; p.y = y; /* now parse stage 2 as in ns_update_menubar */ - wv = xmalloc_widget_value (); - wv->name = "contextmenu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("contextmenu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; #if 0 @@ -914,18 +899,14 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, with its items as a submenu beneath it. */ if (!keymaps && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = pane_string; if (keymaps && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -963,20 +944,18 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, } #endif /* not HAVE_MULTILINGUAL_MENU */ - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* If this item has a null value, make the call_data null so that it won't display a box when the mouse is on it. */ wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -989,11 +968,6 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -1004,24 +978,19 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil); /* Maybe replace this separator with a bitmap or owner-draw item so that it looks better. Having two separators looks odd. */ - wv_sep->name = "--"; wv_sep->next = first_wv->contents; - wv_sep->help = Qnil; #ifndef HAVE_MULTILINGUAL_MENU if (STRING_MULTIBYTE (title)) title = ENCODE_MENU_STRING (title); #endif - - wv_title->name = SSDATA (title); - wv_title->enabled = NO; + wv_title = make_widget_value (SSDATA (title), NULL, false, Qnil); wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep; first_wv->contents = wv_title; } @@ -1459,11 +1428,10 @@ pop_down_menu (void *arg) Lisp_Object -ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents) +ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) { id dialog; Lisp_Object window, tem, title; - struct frame *f; NSPoint p; BOOL isQ; NSAutoreleasePool *pool; @@ -1472,41 +1440,6 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents) isQ = NILP (header); - if (EQ (position, Qt) - || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) - { - window = selected_window; - } - else if (CONSP (position)) - { - Lisp_Object tem; - tem = Fcar (position); - if (XTYPE (tem) == Lisp_Cons) - window = Fcar (Fcdr (position)); - else - { - tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ - window = Fcar (tem); /* POSN_WINDOW (tem) */ - } - } - else if (WINDOWP (position) || FRAMEP (position)) - { - window = position; - } - else - window = Qnil; - - if (FRAMEP (window)) - f = XFRAME (window); - else if (WINDOWP (window)) - { - CHECK_LIVE_WINDOW (window); - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - } - else - CHECK_WINDOW (window); - check_window_system (f); p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2; diff --git a/src/nsterm.h b/src/nsterm.h index 74789634a90..e77aca3d50d 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -100,7 +100,7 @@ typedef float EmacsCGFloat; /* We override sendEvent: as a means to stop/start the event loop */ @interface EmacsApp : NSApplication { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#ifdef NS_IMPL_COCOA BOOL shouldKeepRunning; BOOL isFirst; #endif @@ -855,7 +855,7 @@ extern void find_and_call_menu_selection (struct frame *f, extern Lisp_Object find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data); -extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object header, +extern Lisp_Object ns_popup_dialog (struct frame *, Lisp_Object header, Lisp_Object contents); #define NSAPP_DATA2_RUNASSCRIPT 10 @@ -896,6 +896,9 @@ extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, extern unsigned long ns_get_rgb_color (struct frame *f, float r, float g, float b, float a); +extern void ns_init_events (); +extern void ns_finish_events (); + /* From nsterm.m, needed in nsfont.m. */ #ifdef __OBJC__ extern void diff --git a/src/nsterm.m b/src/nsterm.m index c7cb4faa3b7..c6450804f57 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -54,7 +54,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include "termhooks.h" #include "termchar.h" - +#include "menu.h" #include "window.h" #include "keyboard.h" #include "buffer.h" @@ -396,6 +396,19 @@ void x_set_frame_alpha (struct frame *f); ========================================================================== */ +void +ns_init_events (struct input_event* ev) +{ + EVENT_INIT (*ev); + emacs_event = ev; +} + +void +ns_finish_events () +{ + emacs_event = NULL; +} + static void hold_event (struct input_event *event) { @@ -1799,12 +1812,12 @@ x_set_frame_alpha (struct frame *f) void -x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) /* -------------------------------------------------------------------------- Programmatically reposition mouse pointer in pixel coordinates -------------------------------------------------------------------------- */ { - NSTRACE (x_set_mouse_pixel_position); + NSTRACE (frame_set_mouse_pixel_position); ns_raise_frame (f); #if 0 /* FIXME: this does not work, and what about GNUstep? */ @@ -1816,28 +1829,6 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) #endif } - -void -x_set_mouse_position (struct frame *f, int h, int v) -/* -------------------------------------------------------------------------- - Programmatically reposition mouse pointer in character coordinates - -------------------------------------------------------------------------- */ -{ - int pix_x, pix_y; - - pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2; - pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2; - - if (pix_x < 0) pix_x = 0; - if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); - - if (pix_y < 0) pix_y = 0; - if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); - - x_set_mouse_pixel_position (f, pix_x, pix_y); -} - - static int note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y) /* ------------------------------------------------------------------------ @@ -2012,8 +2003,7 @@ ns_convert_key (unsigned code) Internal call used by NSView-keyDown. -------------------------------------------------------------------------- */ { - const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) - / sizeof (convert_ns_to_X_keysym[0])); + const unsigned last_keysym = ARRAYELTS (convert_ns_to_X_keysym); unsigned keysym; /* An array would be faster, but less easy to read. */ for (keysym = 0; keysym < last_keysym; keysym += 2) @@ -3356,10 +3346,16 @@ ns_draw_glyph_string (struct glyph_string *s) NS_FACE_FOREGROUND (s->face) = tmp; } - font->driver->draw - (s, 0, s->nchars, s->x, s->y, - (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) - || flags == NS_DUMPGLYPH_MOUSEFACE); + { + BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH; + int end = isComposite ? s->cmp_to : s->nchars; + + font->driver->draw + (s, s->cmp_from, end, s->x, s->ybase, + (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) + || flags == NS_DUMPGLYPH_MOUSEFACE); + + } { NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0 @@ -3601,8 +3597,7 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) block_input (); n_emacs_events_pending = 0; - EVENT_INIT (ev); - emacs_event = &ev; + ns_init_events (&ev); q_event_ptr = hold_quit; /* we manage autorelease pools by allocate/reallocate each time around @@ -3643,7 +3638,8 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) nevents = n_emacs_events_pending; n_emacs_events_pending = 0; - emacs_event = q_event_ptr = NULL; + ns_finish_events (); + q_event_ptr = NULL; unblock_input (); return nevents; @@ -3738,16 +3734,15 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, ns_send_appdefined (-1); } - EVENT_INIT (event); block_input (); - emacs_event = &event; + ns_init_events (&event); if (++apploopnr != 1) { emacs_abort (); } [NSApp run]; --apploopnr; - emacs_event = NULL; + ns_finish_events (); if (nr > 0 && readfds) { c = 's'; @@ -4154,38 +4149,30 @@ ns_create_terminal (struct ns_display_info *dpyinfo) NSTRACE (ns_create_terminal); - terminal = create_terminal (); + terminal = create_terminal (output_ns, &ns_redisplay_interface); - terminal->type = output_ns; terminal->display_info.ns = dpyinfo; dpyinfo->terminal = terminal; - terminal->rif = &ns_redisplay_interface; - terminal->clear_frame_hook = ns_clear_frame; - terminal->ins_del_lines_hook = 0; /* XXX vestigial? */ - terminal->delete_glyphs_hook = 0; /* XXX vestigial? */ terminal->ring_bell_hook = ns_ring_bell; - terminal->reset_terminal_modes_hook = NULL; - terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = ns_update_begin; terminal->update_end_hook = ns_update_end; - terminal->set_terminal_window_hook = NULL; /* XXX vestigial? */ terminal->read_socket_hook = ns_read_socket; terminal->frame_up_to_date_hook = ns_frame_up_to_date; terminal->mouse_position_hook = ns_mouse_position; terminal->frame_rehighlight_hook = ns_frame_rehighlight; terminal->frame_raise_lower_hook = ns_frame_raise_lower; - terminal->fullscreen_hook = ns_fullscreen_hook; - + terminal->menu_show_hook = ns_menu_show; + terminal->popup_dialog_hook = ns_popup_dialog; terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar; terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars; terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar; terminal->judge_scroll_bars_hook = ns_judge_scroll_bars; - terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = ns_delete_terminal; + /* Other hooks are NULL by default. */ return terminal; } @@ -4466,7 +4453,7 @@ ns_term_shutdown (int sig) { if (self = [super init]) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#ifdef NS_IMPL_COCOA self->isFirst = YES; #endif #ifdef NS_IMPL_GNUSTEP @@ -4477,30 +4464,40 @@ ns_term_shutdown (int sig) return self; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#ifdef NS_IMPL_COCOA - (void)run { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +#ifndef NSAppKitVersionNumber10_8 +#define NSAppKitVersionNumber10_8 1187 +#endif - if (isFirst) [self finishLaunching]; - isFirst = NO; + if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_8) + { + [super run]; + return; + } - shouldKeepRunning = YES; - do - { - [pool release]; - pool = [[NSAutoreleasePool alloc] init]; - - NSEvent *event = - [self nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - [self sendEvent:event]; - [self updateWindows]; - } while (shouldKeepRunning); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if (isFirst) [self finishLaunching]; + isFirst = NO; + + shouldKeepRunning = YES; + do + { + [pool release]; + pool = [[NSAutoreleasePool alloc] init]; - [pool release]; + NSEvent *event = + [self nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantFuture] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + [self sendEvent:event]; + [self updateWindows]; + } while (shouldKeepRunning); + + [pool release]; } - (void)stop: (id)sender @@ -4510,7 +4507,7 @@ ns_term_shutdown (int sig) // The file dialog still leaks 7k - 10k on 10.9 though. [super stop:sender]; } -#endif +#endif /* NS_IMPL_COCOA */ - (void)logNotification: (NSNotification *)notification { diff --git a/src/process.c b/src/process.c index 2c66b9e976e..592c43acc2d 100644 --- a/src/process.c +++ b/src/process.c @@ -224,8 +224,9 @@ static EMACS_INT update_tick; /* Only W32 has this, it really means that select can't take write mask. */ #ifdef BROKEN_NON_BLOCKING_CONNECT #undef NON_BLOCKING_CONNECT -#define SELECT_CANT_DO_WRITE_MASK +enum { SELECT_CAN_DO_WRITE_MASK = false }; #else +enum { SELECT_CAN_DO_WRITE_MASK = true }; #ifndef NON_BLOCKING_CONNECT #ifdef HAVE_SELECT #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX) @@ -281,17 +282,11 @@ static void create_process (Lisp_Object, char **, Lisp_Object); static bool keyboard_bit_set (fd_set *); #endif static void deactivate_process (Lisp_Object); -static void status_notify (struct Lisp_Process *); +static int status_notify (struct Lisp_Process *, struct Lisp_Process *); static int read_process_output (Lisp_Object, int); static void handle_child_signal (int); static void create_pty (Lisp_Object); -/* If we support a window system, turn on the code to poll periodically - to detect C-g. It isn't actually used when doing interrupt input. */ -#ifdef HAVE_WINDOW_SYSTEM -#define POLL_FOR_INPUT -#endif - static Lisp_Object get_process (register Lisp_Object name); static void exec_sentinel (Lisp_Object proc, Lisp_Object reason); @@ -468,7 +463,6 @@ static struct fd_callback_data void add_read_fd (int fd, fd_callback func, void *data) { - eassert (fd < FD_SETSIZE); add_keyboard_wait_descriptor (fd); fd_callback_info[fd].func = func; @@ -481,7 +475,6 @@ add_read_fd (int fd, fd_callback func, void *data) void delete_read_fd (int fd) { - eassert (fd < FD_SETSIZE); delete_keyboard_wait_descriptor (fd); fd_callback_info[fd].condition &= ~FOR_READ; @@ -498,7 +491,6 @@ delete_read_fd (int fd) void add_write_fd (int fd, fd_callback func, void *data) { - eassert (fd < FD_SETSIZE); FD_SET (fd, &write_mask); if (fd > max_input_desc) max_input_desc = fd; @@ -529,7 +521,6 @@ delete_input_desc (int fd) void delete_write_fd (int fd) { - eassert (fd < FD_SETSIZE); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; if (fd_callback_info[fd].condition == 0) @@ -870,7 +861,7 @@ nil, indicating the current buffer's process. */) { pset_status (p, list2 (Qexit, make_number (0))); p->tick = ++process_tick; - status_notify (p); + status_notify (p, NULL); redisplay_preserve_echo_area (13); } else @@ -890,7 +881,7 @@ nil, indicating the current buffer's process. */) pset_status (p, list2 (Qsignal, make_number (SIGKILL))); p->tick = ++process_tick; - status_notify (p); + status_notify (p, NULL); redisplay_preserve_echo_area (13); } } @@ -1663,6 +1654,7 @@ 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; + sigset_t oldset; inchannel = outchannel = -1; @@ -1728,7 +1720,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) setup_process_coding_systems (process); block_input (); - block_child_signal (); + block_child_signal (&oldset); #ifndef WINDOWSNT /* vfork, and prevent local vars from being clobbered by the vfork. */ @@ -1852,7 +1844,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) signal (SIGPIPE, SIG_DFL); /* Stop blocking SIGCHLD in the child. */ - unblock_child_signal (); + unblock_child_signal (&oldset); if (pty_flag) child_setup_tty (xforkout); @@ -1871,7 +1863,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) p->alive = 1; /* Stop blocking in the parent. */ - unblock_child_signal (); + unblock_child_signal (&oldset); unblock_input (); if (pid < 0) @@ -1966,9 +1958,6 @@ create_pty (Lisp_Object process) /* Convert an internal struct sockaddr to a lisp object (vector or string). The address family of sa is not included in the result. */ -#ifndef WINDOWSNT -static -#endif Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *sa, int len) { @@ -2021,11 +2010,11 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len) terminator, however. */ if (name_length > 0 && sockun->sun_path[0] != '\0') { - const char* terminator = - memchr (sockun->sun_path, '\0', name_length); + const char *terminator + = memchr (sockun->sun_path, '\0', name_length); if (terminator) - name_length = terminator - (const char*) sockun->sun_path; + name_length = terminator - (const char *) sockun->sun_path; } return make_unibyte_string (sockun->sun_path, name_length); @@ -3933,19 +3922,20 @@ DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output, 0, 4, 0, doc: /* Allow any pending output from subprocesses to be read by Emacs. It is given to their filter functions. -Non-nil arg PROCESS means do not return until some output has been received -from PROCESS. +Optional argument PROCESS means do not return until output has been +received from PROCESS. -Non-nil second arg SECONDS and third arg MILLISEC are number of seconds -and milliseconds to wait; return after that much time whether or not -there is any subprocess output. If SECONDS is a floating point number, +Optional second argument SECONDS and third argument MILLISEC +specify a timeout; return after that much time even if there is +no subprocess output. If SECONDS is a floating point number, it specifies a fractional number of seconds to wait. The MILLISEC argument is obsolete and should be avoided. -If optional fourth arg JUST-THIS-ONE is non-nil, only accept output -from PROCESS, suspending reading output from other processes. +If optional fourth argument JUST-THIS-ONE is non-nil, accept output +from PROCESS only, suspending reading output from other processes. If JUST-THIS-ONE is an integer, don't run any timers either. -Return non-nil if we received any output before the timeout expired. */) +Return non-nil if we received any output from PROCESS (or, if PROCESS +is nil, from any process) before the timeout expired. */) (register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one) { intmax_t secs; @@ -3997,12 +3987,13 @@ Return non-nil if we received any output before the timeout expired. */) nsecs = 0; return - (wait_reading_process_output (secs, nsecs, 0, 0, + ((wait_reading_process_output (secs, nsecs, 0, 0, Qnil, !NILP (process) ? XPROCESS (process) : NULL, NILP (just_this_one) ? 0 : !INTEGERP (just_this_one) ? 1 : -1) - ? Qt : Qnil); + <= 0) + ? Qnil : Qt); } /* Accept a connection for server process SERVER on CHANNEL. */ @@ -4267,18 +4258,17 @@ wait_reading_process_output_1 (void) (and gobble terminal input into the buffer if any arrives). If WAIT_PROC is specified, wait until something arrives from that - process. The return value is true if we read some input from - that process. + process. If JUST_WAIT_PROC is nonzero, handle only output from WAIT_PROC (suspending output from other processes). A negative value means don't run any timers either. - If WAIT_PROC is specified, then the function returns true if we - received input from that process before the timeout elapsed. - Otherwise, return true if we received input from any process. */ + Return positive if we received input from WAIT_PROC (or from any + process if WAIT_PROC is null), zero if we attempted to receive + input but got none, and negative if we didn't even try. */ -bool +int wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -4293,8 +4283,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, int xerrno; Lisp_Object proc; struct timespec timeout, end_time; - int wait_channel = -1; - bool got_some_input = 0; + int got_some_input = -1; ptrdiff_t count = SPECPDL_INDEX (); FD_ZERO (&Available); @@ -4305,10 +4294,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && EQ (XCAR (wait_proc->status), Qexit))) message1 ("Blocking call to accept-process-output with quit inhibited!!"); - /* If wait_proc is a process to watch, set wait_channel accordingly. */ - if (wait_proc != NULL) - wait_channel = wait_proc->infd; - record_unwind_protect_int (wait_reading_process_output_unwind, waiting_for_user_input_p); waiting_for_user_input_p = read_kbd; @@ -4345,6 +4330,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) break; + /* After reading input, vacuum up any leftovers without waiting. */ + if (0 <= got_some_input) + nsecs = -1; + /* Compute time from now till when time limit is up. */ /* Exit if already run out. */ if (nsecs < 0) @@ -4463,7 +4452,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* It's okay for us to do this and then continue with the loop, since timeout has already been zeroed out. */ clear_waiting_for_input (); - status_notify (NULL); + got_some_input = status_notify (NULL, wait_proc); if (do_display) redisplay_preserve_echo_area (13); } } @@ -4485,18 +4474,23 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (wait_proc->infd >= 0) { int nread = read_process_output (proc, wait_proc->infd); - - if (nread == 0) - break; - - if (nread > 0) - got_some_input = read_some_bytes = 1; - else if (nread == -1 && (errno == EIO || errno == EAGAIN)) - break; + if (nread < 0) + { + if (errno == EIO || errno == EAGAIN) + break; #ifdef EWOULDBLOCK - else if (nread == -1 && EWOULDBLOCK == errno) - break; + if (errno == EWOULDBLOCK) + break; #endif + } + else + { + if (got_some_input < nread) + got_some_input = nread; + if (nread == 0) + break; + read_some_bytes = true; + } } if (read_some_bytes && do_display) redisplay_preserve_echo_area (10); @@ -4527,12 +4521,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, else Available = input_wait_mask; Writeok = write_mask; -#ifdef SELECT_CANT_DO_WRITE_MASK - check_write = 0; -#else - check_write = 1; -#endif - check_delay = wait_channel >= 0 ? 0 : process_output_delay_count; + check_delay = wait_proc ? 0 : process_output_delay_count; + check_write = SELECT_CAN_DO_WRITE_MASK; } /* If frame size has changed or the window is newly mapped, @@ -4558,6 +4548,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { nfds = read_kbd ? 0 : 1; no_avail = 1; + FD_ZERO (&Available); } if (!no_avail) @@ -4567,7 +4558,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* Set the timeout for adaptive read buffering if any process has non-zero read_output_skip and non-zero read_output_delay, and we are not reading output for a - specific wait_channel. It is not executed if + specific process. It is not executed if Vprocess_adaptive_read_buffering is nil. */ if (process_output_skip && check_delay > 0) { @@ -4629,12 +4620,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { struct Lisp_Process *p = XPROCESS (chan_process[channel]); - if (p && p->gnutls_p && p->gnutls_state && p->infd + if (p && p->gnutls_p && p->gnutls_state && ((emacs_gnutls_record_check_pending (p->gnutls_state)) > 0)) { nfds++; + eassert (p->infd == channel); FD_SET (p->infd, &Available); } } @@ -4679,12 +4671,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, report_file_errno ("Failed select", Qnil, xerrno); } - if (no_avail) - { - FD_ZERO (&Available); - check_write = 0; - } - /* Check for keyboard input */ /* If there is any, return immediately to give it higher priority than subprocesses */ @@ -4751,9 +4737,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, handle_input_available_signal (SIGIO); #endif - if (! wait_proc) - got_some_input |= nfds > 0; - /* If checking input just got us a size-change event from X, obey it now if we should. */ if (read_kbd || ! NILP (wait_for_cell)) @@ -4785,12 +4768,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* If waiting for this channel, arrange to return as soon as no more input to be processed. No more waiting. */ - if (wait_channel == channel) - { - wait_channel = -1; - nsecs = -1; - got_some_input = 1; - } proc = chan_process[channel]; if (NILP (proc)) continue; @@ -4806,6 +4783,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, buffered-ahead character if we have one. */ nread = read_process_output (proc, channel); + if ((!wait_proc || wait_proc == XPROCESS (proc)) && got_some_input < nread) + got_some_input = nread; if (nread > 0) { /* Since read_process_output can run a filter, @@ -5826,36 +5805,31 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, p->tick = ++process_tick; if (!nomsg) { - status_notify (NULL); + status_notify (NULL, NULL); redisplay_preserve_echo_area (13); } } #endif +#ifdef TIOCSIGSEND + /* Work around a HP-UX 7.0 bug that mishandles signals to subjobs. + We don't know whether the bug is fixed in later HP-UX versions. */ + if (! NILP (current_group) && ioctl (p->infd, TIOCSIGSEND, signo) != -1) + return; +#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 obvious alternative. */ - if (no_pgrp) - { - kill (p->pid, signo); - return; - } + pid_t pid = no_pgrp ? gid : - gid; - /* gid may be a pid, or minus a pgrp's number */ -#ifdef TIOCSIGSEND - if (!NILP (current_group)) - { - if (ioctl (p->infd, TIOCSIGSEND, signo) == -1) - kill (-gid, signo); - } - else - { - gid = - p->pid; - kill (gid, signo); - } -#else /* ! defined (TIOCSIGSEND) */ - kill (-gid, signo); -#endif /* ! defined (TIOCSIGSEND) */ + /* Do not kill an already-reaped process, as that could kill an + innocent bystander that happens to have the same process ID. */ + sigset_t oldset; + block_child_signal (&oldset); + if (p->alive) + kill (pid, signo); + unblock_child_signal (&oldset); } DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0, @@ -6354,14 +6328,20 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason) /* Report all recent events of a change in process status (either run the sentinel or output a message). This is usually done while Emacs is waiting for keyboard input - but can be done at other times. */ + but can be done at other times. -static void -status_notify (struct Lisp_Process *deleting_process) + Return positive if any input was received from WAIT_PROC (or from + any process if WAIT_PROC is null), zero if input was attempted but + none received, and negative if we didn't even try. */ + +static int +status_notify (struct Lisp_Process *deleting_process, + struct Lisp_Process *wait_proc) { - register Lisp_Object proc; + Lisp_Object proc; Lisp_Object tail, msg; struct gcpro gcpro1, gcpro2; + int got_some_input = -1; tail = Qnil; msg = Qnil; @@ -6391,8 +6371,14 @@ status_notify (struct Lisp_Process *deleting_process) /* Network or serial process not stopped: */ && ! EQ (p->command, Qt) && p->infd >= 0 - && p != deleting_process - && read_process_output (proc, p->infd) > 0); + && p != deleting_process) + { + int nread = read_process_output (proc, p->infd); + if (got_some_input < nread) + got_some_input = nread; + if (nread <= 0) + break; + } /* Get the text to use for the message. */ if (p->raw_status_new) @@ -6424,6 +6410,7 @@ status_notify (struct Lisp_Process *deleting_process) update_mode_lines = 24; /* In case buffers use %s in mode-line-format. */ UNGCPRO; + return got_some_input; } DEFUN ("internal-default-process-sentinel", Finternal_default_process_sentinel, @@ -6635,9 +6622,11 @@ extern int sys_select (int, fd_set *, fd_set *, fd_set *, DO_DISPLAY means redisplay should be done to show subprocess output that arrives. - Return true if we received input from any process. */ + Return positive if we received input from WAIT_PROC (or from any + process if WAIT_PROC is null), zero if we attempted to receive + input but got none, and negative if we didn't even try. */ -bool +int wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -6825,7 +6814,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, start_polling (); - return 0; + return -1; } #endif /* not subprocesses */ @@ -7064,15 +7053,13 @@ integer or floating point values. futz with the SIGCHLD handler, but before Emacs forks any children. This function's caller should block SIGCHLD. */ -#ifndef NS_IMPL_GNUSTEP -static -#endif void catch_child_signal (void) { struct sigaction action, old_action; + sigset_t oldset; emacs_sigaction_init (&action, deliver_child_signal); - block_child_signal (); + block_child_signal (&oldset); sigaction (SIGCHLD, &action, &old_action); eassert (! (old_action.sa_flags & SA_SIGINFO)); @@ -7081,7 +7068,7 @@ catch_child_signal (void) = (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN ? dummy_handler : old_action.sa_handler); - unblock_child_signal (); + unblock_child_signal (&oldset); } #endif /* subprocesses */ diff --git a/src/process.h b/src/process.h index c3481f295f5..273ad9267d6 100644 --- a/src/process.h +++ b/src/process.h @@ -213,8 +213,6 @@ enum /* Defined in callproc.c. */ -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); @@ -227,9 +225,7 @@ extern Lisp_Object system_process_attributes (Lisp_Object); extern void record_deleted_pid (pid_t, Lisp_Object); struct sockaddr; -#ifdef WINDOWSNT extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, int); -#endif extern void hold_keyboard_input (void); extern void unhold_keyboard_input (void); extern bool kbd_on_hold_p (void); @@ -240,9 +236,7 @@ extern void add_read_fd (int fd, fd_callback func, void *data); extern void delete_read_fd (int fd); extern void add_write_fd (int fd, fd_callback func, void *data); extern void delete_write_fd (int fd); -#ifdef NS_IMPL_GNUSTEP extern void catch_child_signal (void); -#endif #ifdef WINDOWSNT extern Lisp_Object network_interface_list (void); diff --git a/src/profiler.c b/src/profiler.c index fff7c6b0ff6..919aabc92af 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -294,7 +294,7 @@ setup_cpu_timer (Lisp_Object sampling_interval) sigev.sigev_signo = SIGPROF; sigev.sigev_notify = SIGEV_SIGNAL; - for (i = 0; i < sizeof system_clock / sizeof *system_clock; i++) + for (i = 0; i < ARRAYELTS (system_clock); i++) if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) { profiler_timer_ok = 1; diff --git a/src/puresize.h b/src/puresize.h index 1371fb3cea2..376b11cf75b 100644 --- a/src/puresize.h +++ b/src/puresize.h @@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #endif #ifndef BASE_PURESIZE -#define BASE_PURESIZE (1701000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) +#define BASE_PURESIZE (1800000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) #endif /* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ diff --git a/src/regex.c b/src/regex.c index 244924058a0..ac71b797fbd 100644 --- a/src/regex.c +++ b/src/regex.c @@ -713,7 +713,8 @@ typedef enum static int extract_number (re_char *source) { - return (SIGN_EXTEND_CHAR (source[1]) << 8) + source[0]; + unsigned leading_byte = SIGN_EXTEND_CHAR (source[1]); + return (leading_byte << 8) + source[0]; } /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. @@ -1189,12 +1190,7 @@ print_double_string (re_char *where, re_char *string1, ssize_t size1, # define assert(e) # define DEBUG_STATEMENT(e) -# if __STDC_VERSION__ < 199901L -# define DEBUG_COMPILES_ARGUMENTS -# define DEBUG_PRINT /* 'DEBUG_PRINT (x, y)' discards X and Y. */ (void) -# else -# define DEBUG_PRINT(...) -# endif +# define DEBUG_PRINT(...) # define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) # define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) diff --git a/src/search.c b/src/search.c index 0a693daa15e..dc4820d8588 100644 --- a/src/search.c +++ b/src/search.c @@ -2679,18 +2679,8 @@ since only regular expressions have distinguished subexpressions. */) } if (really_changed) - { - if (buf_multibyte) - { - ptrdiff_t nchars = - multibyte_chars_in_text (substed, substed_len); - - newtext = make_multibyte_string ((char *) substed, nchars, - substed_len); - } - else - newtext = make_unibyte_string ((char *) substed, substed_len); - } + newtext = make_specified_string ((const char *) substed, -1, + substed_len, buf_multibyte); xfree (substed); } diff --git a/src/sound.c b/src/sound.c index a95678812e1..7046f4e8e32 100644 --- a/src/sound.c +++ b/src/sound.c @@ -702,7 +702,7 @@ vox_configure (struct sound_device *sd) { int val; #ifdef USABLE_SIGIO - sigset_t blocked; + sigset_t oldset, blocked; #endif eassert (sd->fd >= 0); @@ -714,7 +714,7 @@ vox_configure (struct sound_device *sd) #ifdef USABLE_SIGIO sigemptyset (&blocked); sigaddset (&blocked, SIGIO); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + pthread_sigmask (SIG_BLOCK, &blocked, &oldset); #endif val = sd->format; @@ -748,7 +748,7 @@ vox_configure (struct sound_device *sd) turn_on_atimers (1); #ifdef USABLE_SIGIO - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &oldset, 0); #endif } @@ -764,10 +764,10 @@ vox_close (struct sound_device *sd) be interrupted by a signal. Block the ones we know to cause troubles. */ #ifdef USABLE_SIGIO - sigset_t blocked; + sigset_t blocked, oldset; sigemptyset (&blocked); sigaddset (&blocked, SIGIO); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + pthread_sigmask (SIG_BLOCK, &blocked, &oldset); #endif turn_on_atimers (0); @@ -776,7 +776,7 @@ vox_close (struct sound_device *sd) turn_on_atimers (1); #ifdef USABLE_SIGIO - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &oldset, 0); #endif /* Close the device. */ diff --git a/src/sysdep.c b/src/sysdep.c index e1fd86f5f3b..211a3bb706f 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -128,7 +128,7 @@ static const int baud_convert[] = /* Return the current working directory. Returns NULL on errors. Any other returned value must be freed with free. This is used only when get_current_dir_name is not defined on the system. */ -char* +char * get_current_dir_name (void) { char *buf; @@ -222,7 +222,9 @@ discard_tty_input (void) void stuff_char (char c) { - if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) + if (! (FRAMEP (selected_frame) + && FRAME_LIVE_P (XFRAME (selected_frame)) + && FRAME_TERMCAP_P (XFRAME (selected_frame)))) return; /* Should perhaps error if in batch mode */ @@ -255,7 +257,7 @@ init_baud_rate (int fd) #endif /* not DOS_NT */ } - baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0] + baud_rate = (emacs_ospeed < ARRAYELTS (baud_convert) ? baud_convert[emacs_ospeed] : 9600); if (baud_rate == 0) baud_rate = 1200; @@ -603,6 +605,7 @@ init_sigio (int fd) #endif } +#ifndef DOS_NT static void reset_sigio (int fd) { @@ -610,6 +613,7 @@ reset_sigio (int fd) fcntl (fd, F_SETFL, old_fcntl_flags[fd]); #endif } +#endif void request_sigio (void) @@ -657,7 +661,29 @@ ignore_sigio (void) signal (SIGIO, SIG_IGN); #endif } + +#ifndef MSDOS +/* Block SIGCHLD. */ + +void +block_child_signal (sigset_t *oldset) +{ + sigset_t blocked; + sigemptyset (&blocked); + sigaddset (&blocked, SIGCHLD); + sigaddset (&blocked, SIGINT); + pthread_sigmask (SIG_BLOCK, &blocked, oldset); +} +/* Unblock SIGCHLD. */ + +void +unblock_child_signal (sigset_t const *oldset) +{ + pthread_sigmask (SIG_SETMASK, oldset, 0); +} + +#endif /* !MSDOS */ /* Saving and restoring the process group of Emacs's terminal. */ @@ -692,21 +718,21 @@ init_foreground_group (void) /* Block and unblock SIGTTOU. */ void -block_tty_out_signal (void) +block_tty_out_signal (sigset_t *oldset) { #ifdef SIGTTOU sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGTTOU); - pthread_sigmask (SIG_BLOCK, &blocked, 0); + pthread_sigmask (SIG_BLOCK, &blocked, oldset); #endif } void -unblock_tty_out_signal (void) +unblock_tty_out_signal (sigset_t const *oldset) { #ifdef SIGTTOU - pthread_sigmask (SIG_SETMASK, &empty_mask, 0); + pthread_sigmask (SIG_SETMASK, oldset, 0); #endif } @@ -721,10 +747,11 @@ static void tcsetpgrp_without_stopping (int fd, pid_t pgid) { #ifdef SIGTTOU + sigset_t oldset; block_input (); - block_tty_out_signal (); + block_tty_out_signal (&oldset); tcsetpgrp (fd, pgid); - unblock_tty_out_signal (); + unblock_tty_out_signal (&oldset); unblock_input (); #endif } @@ -1527,9 +1554,6 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler) #endif } - if (! IEEE_FLOATING_POINT) - sigaddset (&action->sa_mask, SIGFPE); - action->sa_handler = handler; action->sa_flags = emacs_sigaction_flags (); } diff --git a/src/sysselect.h b/src/sysselect.h index b76e71a3a75..db6438ed1f8 100644 --- a/src/sysselect.h +++ b/src/sysselect.h @@ -16,6 +16,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef SYSSELECT_H +#define SYSSELECT_H 1 + #ifndef DOS_NT #include <sys/select.h> #endif @@ -47,3 +50,42 @@ typedef int fd_set; #ifdef MSDOS #define pselect sys_select #endif + +#ifndef WINDOWSNT +INLINE_HEADER_BEGIN + +/* Check for out-of-range errors if ENABLE_CHECKING is defined. */ + +INLINE void +fd_CLR (int fd, fd_set *set) +{ + eassume (0 <= fd && fd < FD_SETSIZE); + FD_CLR (fd, set); +} + +INLINE bool +fd_ISSET (int fd, fd_set *set) +{ + eassume (0 <= fd && fd < FD_SETSIZE); + return FD_ISSET (fd, set) != 0; +} + +INLINE void +fd_SET (int fd, fd_set *set) +{ + eassume (0 <= fd && fd < FD_SETSIZE); + FD_SET (fd, set); +} + +#undef FD_CLR +#undef FD_ISSET +#undef FD_SET +#define FD_CLR(fd, set) fd_CLR (fd, set) +#define FD_ISSET(fd, set) fd_ISSET (fd, set) +#define FD_SET(fd, set) fd_SET (fd, set) + +INLINE_HEADER_END + +#endif /* !WINDOWSNT */ + +#endif diff --git a/src/syssignal.h b/src/syssignal.h index 477ddfc2086..3fd9730e665 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -20,6 +20,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <signal.h> extern void init_signals (bool); +extern void block_child_signal (sigset_t *); +extern void unblock_child_signal (sigset_t const *); +extern void block_tty_out_signal (sigset_t *); +extern void unblock_tty_out_signal (sigset_t const *); #ifdef HAVE_PTHREAD #include <pthread.h> diff --git a/src/term.c b/src/term.c index 8661cba1160..642907979aa 100644 --- a/src/term.c +++ b/src/term.c @@ -131,6 +131,9 @@ enum no_color_bit static int max_frame_cols; +static Lisp_Object Qtty_mode_set_strings; +static Lisp_Object Qtty_mode_reset_strings; + #ifdef HAVE_GPM @@ -162,6 +165,28 @@ tty_ring_bell (struct frame *f) /* Set up termcap modes for Emacs. */ static void +tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym) +{ + Lisp_Object lisp_terminal; + Lisp_Object extra_codes; + struct tty_display_info *tty = terminal->display_info.tty; + + XSETTERMINAL (lisp_terminal, terminal); + for (extra_codes = Fterminal_parameter (lisp_terminal, sym); + CONSP (extra_codes); + extra_codes = XCDR (extra_codes)) + { + Lisp_Object string = XCAR (extra_codes); + if (STRINGP (string)) + { + fwrite (SDATA (string), 1, SBYTES (string), tty->output); + if (tty->termscript) + fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); + } + } +} + +static void tty_set_terminal_modes (struct terminal *terminal) { struct tty_display_info *tty = terminal->display_info.tty; @@ -183,6 +208,7 @@ tty_set_terminal_modes (struct terminal *terminal) OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal); OUTPUT_IF (tty, tty->TS_keypad_mode); losecursor (tty); + tty_send_additional_strings (terminal, Qtty_mode_set_strings); fflush (tty->output); } } @@ -196,6 +222,7 @@ tty_reset_terminal_modes (struct terminal *terminal) if (tty->output) { + tty_send_additional_strings (terminal, Qtty_mode_reset_strings); tty_turn_off_highlight (tty); tty_turn_off_insert (tty); OUTPUT_IF (tty, tty->TS_end_keypad_mode); @@ -500,9 +527,6 @@ static ptrdiff_t encode_terminal_dst_size; Set CODING->produced to the byte-length of the resulting byte sequence, and return a pointer to that byte sequence. */ -#ifndef DOS_NT -static -#endif unsigned char * encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding) @@ -1339,7 +1363,7 @@ term_get_fkeys_1 (void) if (!KEYMAPP (KVAR (kboard, Vinput_decode_map))) kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil)); - for (i = 0; i < (sizeof (keys) / sizeof (keys[0])); i++) + for (i = 0; i < ARRAYELTS (keys); i++) { char *sequence = tgetstr (keys[i].cap, address); if (sequence) @@ -3555,9 +3579,10 @@ tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y) } } +/* WINDOWSNT uses this as menu_show_hook, see w32console.c. */ Lisp_Object -tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, - Lisp_Object title, bool kbd_navigation, const char **error_name) +tty_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) { tty_menu *menu; int pane, selidx, lpane, status; @@ -3594,6 +3619,10 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, menu functions pointers to the contents of strings. */ specpdl_count = inhibit_garbage_collection (); + /* Avoid crashes if, e.g., another client will connect while we + are in a menu. */ + temporarily_switch_to_single_kboard (f); + /* Adjust coordinates to be root-window-relative. */ item_x = x += f->left_pos; item_y = y += f->top_pos; @@ -3615,7 +3644,7 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) pane_string++; lpane = tty_menu_add_pane (menu, pane_string); @@ -3755,7 +3784,8 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, specbind (Qoverriding_terminal_local_map, Fsymbol_value (Qtty_menu_navigation_map)); status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap, - tty_menu_help_callback, kbd_navigation); + tty_menu_help_callback, + menuflags & MENU_KBD_NAVIGATION); entry = pane_prefix = Qnil; switch (status) @@ -3781,7 +3811,7 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, { entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); - if (keymaps != 0) + if (menuflags & MENU_KEYMAPS) { entry = Fcons (entry, Qnil); if (!NILP (pane_prefix)) @@ -3814,7 +3844,7 @@ tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, Ftop_level (); /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means the menu was invoked with a mouse event as POSITION). */ - if (! for_click) + if (!(menuflags & MENU_FOR_CLICK)) Fsignal (Qquit, Qnil); break; } @@ -3895,6 +3925,7 @@ clear_tty_hooks (struct terminal *terminal) terminal->frame_rehighlight_hook = 0; terminal->frame_raise_lower_hook = 0; terminal->fullscreen_hook = 0; + terminal->menu_show_hook = 0; terminal->set_vertical_scroll_bar_hook = 0; terminal->condemn_scroll_bars_hook = 0; terminal->redeem_scroll_bar_hook = 0; @@ -3913,43 +3944,25 @@ clear_tty_hooks (struct terminal *terminal) static void set_tty_hooks (struct terminal *terminal) { - terminal->rif = 0; /* ttys don't support window-based redisplay. */ - terminal->cursor_to_hook = &tty_cursor_to; terminal->raw_cursor_to_hook = &tty_raw_cursor_to; - terminal->clear_to_end_hook = &tty_clear_to_end; terminal->clear_frame_hook = &tty_clear_frame; terminal->clear_end_of_line_hook = &tty_clear_end_of_line; - terminal->ins_del_lines_hook = &tty_ins_del_lines; - terminal->insert_glyphs_hook = &tty_insert_glyphs; terminal->write_glyphs_hook = &tty_write_glyphs; terminal->delete_glyphs_hook = &tty_delete_glyphs; - terminal->ring_bell_hook = &tty_ring_bell; - terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes; terminal->set_terminal_modes_hook = &tty_set_terminal_modes; - terminal->update_begin_hook = 0; /* Not needed. */ terminal->update_end_hook = &tty_update_end; + terminal->menu_show_hook = &tty_menu_show; terminal->set_terminal_window_hook = &tty_set_terminal_window; - - terminal->mouse_position_hook = 0; /* Not needed. */ - terminal->frame_rehighlight_hook = 0; /* Not needed. */ - terminal->frame_raise_lower_hook = 0; /* Not needed. */ - - terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */ - terminal->condemn_scroll_bars_hook = 0; /* Not needed. */ - terminal->redeem_scroll_bar_hook = 0; /* Not needed. */ - terminal->judge_scroll_bars_hook = 0; /* Not needed. */ - terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ - terminal->frame_up_to_date_hook = 0; /* Not needed. */ - terminal->delete_frame_hook = &tty_free_frame_resources; terminal->delete_terminal_hook = &delete_tty; + /* Other hooks are NULL by default. */ } /* If FD is the controlling terminal, drop it. */ @@ -3964,9 +3977,10 @@ dissociate_if_controlling_tty (int fd) /* setsid failed, presumably because Emacs is already a process group leader. Fall back on the obsolescent way to dissociate a controlling tty. */ - block_tty_out_signal (); + sigset_t oldset; + block_tty_out_signal (&oldset); ioctl (fd, TIOCNOTTY, 0); - unblock_tty_out_signal (); + unblock_tty_out_signal (&oldset); #endif } } @@ -3990,6 +4004,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) int status; struct tty_display_info *tty = NULL; struct terminal *terminal = NULL; + sigset_t oldset; bool ctty = false; /* True if asked to open controlling tty. */ if (!terminal_type) @@ -4011,7 +4026,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) if (terminal) return terminal; - terminal = create_terminal (); + terminal = create_terminal (output_termcap, NULL); #ifdef MSDOS if (been_here > 0) maybe_fatal (0, 0, "Attempt to create another terminal %s", "", @@ -4025,7 +4040,6 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) tty->next = tty_list; tty_list = tty; - terminal->type = output_termcap; terminal->display_info.tty = tty; tty->terminal = terminal; @@ -4051,12 +4065,15 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) open a frame on the same terminal. */ int flags = O_RDWR | O_NOCTTY | (ctty ? 0 : O_IGNORE_CTTY); int fd = emacs_open (name, flags, 0); - tty->input = tty->output = fd < 0 || ! isatty (fd) ? 0 : fdopen (fd, "w+"); + tty->input = tty->output = + ((fd < 0 || ! isatty (fd)) + ? NULL + : fdopen (fd, "w+")); if (! tty->input) { char const *diagnostic - = tty->input ? "Not a tty device: %s" : "Could not open file: %s"; + = (fd < 0) ? "Could not open file: %s" : "Not a tty device: %s"; emacs_close (fd); maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name); } @@ -4076,11 +4093,11 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) /* On some systems, tgetent tries to access the controlling terminal. */ - block_tty_out_signal (); + block_tty_out_signal (&oldset); status = tgetent (tty->termcap_term_buffer, terminal_type); if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1]) emacs_abort (); - unblock_tty_out_signal (); + unblock_tty_out_signal (&oldset); if (status < 0) { @@ -4577,6 +4594,9 @@ bigger, or it may make it blink, or it may do nothing at all. */); encode_terminal_src = NULL; encode_terminal_dst = NULL; + DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings"); + DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings"); + #ifndef MSDOS DEFSYM (Qtty_menu_next_item, "tty-menu-next-item"); DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item"); diff --git a/src/termhooks.h b/src/termhooks.h index 708351da83d..f9bf9d785b6 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -478,7 +478,14 @@ struct terminal may do something OS dependent, like extended window manager hints on X11. */ void (*fullscreen_hook) (struct frame *f); - + /* This hook is called to display menus. */ + Lisp_Object (*menu_show_hook) (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name); + + /* This hook is called to display popup dialog. */ + Lisp_Object (*popup_dialog_hook) (struct frame *f, Lisp_Object header, + Lisp_Object contents); + /* Scroll bar hooks. */ /* The representation of scroll bars is determined by the code which @@ -637,16 +644,15 @@ extern struct terminal *terminal_list; #endif extern struct terminal *get_terminal (Lisp_Object terminal, bool); -extern struct terminal *create_terminal (void); +extern struct terminal *create_terminal (enum output_method, + struct redisplay_interface *); extern void delete_terminal (struct terminal *); /* The initial terminal device, created by initial_term_init. */ extern struct terminal *initial_terminal; -#ifdef DOS_NT extern unsigned char *encode_terminal_code (struct glyph *, int, struct coding_system *); -#endif #ifdef HAVE_GPM extern void close_gpm (int gpm_fd); diff --git a/src/terminal.c b/src/terminal.c index d0a38b97bb4..23455262cb3 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -224,19 +224,19 @@ get_terminal (Lisp_Object terminal, bool throw) return result; } - - -/* Create a new terminal object and add it to the terminal list. */ +/* Create a new terminal object of TYPE and add it to the terminal list. RIF + may be NULL if this terminal type doesn't support window-based redisplay. */ struct terminal * -create_terminal (void) +create_terminal (enum output_method type, struct redisplay_interface *rif) { struct terminal *terminal = allocate_terminal (); Lisp_Object terminal_coding, keyboard_coding; terminal->next_terminal = terminal_list; terminal_list = terminal; - + terminal->type = type; + terminal->rif = rif; terminal->id = next_terminal_id++; terminal->keyboard_coding = xmalloc (sizeof (struct coding_system)); @@ -519,13 +519,12 @@ init_initial_terminal (void) if (initialized || terminal_list || tty_list) emacs_abort (); - initial_terminal = create_terminal (); - initial_terminal->type = output_initial; + initial_terminal = create_terminal (output_initial, NULL); initial_terminal->name = xstrdup ("initial_terminal"); initial_terminal->kboard = initial_kboard; initial_terminal->delete_terminal_hook = &delete_initial_terminal; initial_terminal->delete_frame_hook = &initial_free_frame_resources; - /* All other hooks are NULL. */ + /* Other hooks are NULL by default. */ return initial_terminal; } diff --git a/src/unexcoff.c b/src/unexcoff.c index 043f3348d16..0e47bdd8656 100644 --- a/src/unexcoff.c +++ b/src/unexcoff.c @@ -122,7 +122,7 @@ static int pagemask; into an int which is the number of a byte. This is a no-op on ordinary machines, but not on all. */ -#define ADDR_CORRECT(x) ((char *)(x) - (char*)0) +#define ADDR_CORRECT(x) ((char *) (x) - (char *) 0) #include "lisp.h" diff --git a/src/unexcw.c b/src/unexcw.c index fcca5e5cbf2..7636b05a12e 100644 --- a/src/unexcw.c +++ b/src/unexcw.c @@ -81,8 +81,7 @@ read_exe_header (int fd, exe_header_t * exe_header_buffer) #endif assert (exe_header_buffer->file_header.f_nscns > 0); assert (exe_header_buffer->file_header.f_nscns <= - sizeof (exe_header_buffer->section_header) / - sizeof (exe_header_buffer->section_header[0])); + ARRAYELTS (exe_header_buffer->section_header)); assert (exe_header_buffer->file_header.f_opthdr > 0); ret = @@ -286,13 +285,6 @@ unexec (const char *outfile, const char *infile) int ret; int ret2; - if (bss_sbrk_did_unexec) - { - /* can only dump once */ - printf ("You can only dump Emacs once on this platform.\n"); - return; - } - report_sheap_usage (1); infile = add_exe_suffix_if_necessary (infile, infile_buffer); diff --git a/src/unexw32.c b/src/unexw32.c index f70cdd79478..7cbd95a46fe 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -83,8 +83,6 @@ PCHAR bss_start_static = 0; DWORD_PTR bss_size_static = 0; DWORD_PTR extra_bss_size_static = 0; -PIMAGE_SECTION_HEADER heap_section; - /* MinGW64 doesn't add a leading underscore to external symbols, whereas configure.ac sets up LD_SWITCH_SYSTEM_TEMACS to force the entry point at __start, with two underscores. */ @@ -475,8 +473,6 @@ get_section_info (file_data *p_infile) bss_section_static = 0; extra_bss_size_static = 0; } - - heap_section = rva_to_section (PTR_TO_RVA (get_heap_start ()), nt_header); } @@ -518,9 +514,11 @@ copy_executable_and_dump_data (file_data *p_infile, if (verbose) \ { \ printf ("%s\n", (message)); \ - printf ("\t0x%08x Address in process.\n", s); \ - printf ("\t0x%08x Offset in output file.\n", dst - p_outfile->file_base); \ - printf ("\t0x%08x Size in bytes.\n", count); \ + printf ("\t0x%p Address in process.\n", s); \ + printf ("\t0x%p Base output file.\n", p_outfile->file_base); \ + printf ("\t0x%p Offset in output file.\n", dst - p_outfile->file_base); \ + printf ("\t0x%p Address in output file.\n", dst); \ + printf ("\t0x%p Size in bytes.\n", count); \ } \ memcpy (dst, s, count); \ dst += count; \ @@ -629,34 +627,6 @@ copy_executable_and_dump_data (file_data *p_infile, dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA; dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; } - if (section == heap_section) - { - DWORD_PTR heap_start = (DWORD_PTR) get_heap_start (); - DWORD_PTR heap_size = get_committed_heap_size (); - - /* Dump the used portion of the predump heap, adjusting the - section's size to the appropriate size. */ - dst = dst_save - + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (heap_start), dst_section); - COPY_PROC_CHUNK ("Dumping heap...", heap_start, heap_size, - be_verbose); - ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); - dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile); - /* Determine new size of raw data area. */ - dst = max (dst, dst_save + dst_section->SizeOfRawData); - dst_section->SizeOfRawData = dst - dst_save; - /* Reduce the size of the heap section to fit (must be last - section). */ - dst_nt_header->OptionalHeader.SizeOfImage -= - dst_section->Misc.VirtualSize - - ROUND_UP (dst_section->SizeOfRawData, - dst_nt_header->OptionalHeader.SectionAlignment); - dst_section->Misc.VirtualSize = - ROUND_UP (dst_section->SizeOfRawData, - dst_nt_header->OptionalHeader.SectionAlignment); - dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA; - dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; - } /* Align the section's raw data area. */ ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); @@ -758,6 +728,10 @@ unexec (const char *new_name, const char *old_name) abort (); strcpy (p, q); +#ifdef ENABLE_CHECKING + report_temacs_memory_usage (); +#endif + /* Make sure that the output filename has the ".exe" extension...patch it up if not. */ p = out_filename + strlen (out_filename) - 4; @@ -767,9 +741,6 @@ unexec (const char *new_name, const char *old_name) printf ("Dumping from %s\n", in_filename); printf (" to %s\n", out_filename); - /* We need to round off our heap to NT's page size. */ - round_heap (get_page_size ()); - /* Open the undumped executable file. */ if (!open_input_file (&in_file, in_filename)) { @@ -784,7 +755,6 @@ unexec (const char *new_name, const char *old_name) /* The size of the dumped executable is the size of the original executable plus the size of the heap and the size of the .bss section. */ size = in_file.size + - get_committed_heap_size () + extra_bss_size + extra_bss_size_static; if (!open_output_file (&out_file, out_filename, size)) @@ -799,6 +769,10 @@ unexec (const char *new_name, const char *old_name) copy_executable_and_dump_data (&in_file, &out_file); + /* Unset it because it is plain wrong to keep it after dumping. + Malloc can still occur! */ + using_dynamic_heap = FALSE; + /* Patch up header fields; profiler is picky about this. */ { PIMAGE_DOS_HEADER dos_header; diff --git a/src/vm-limit.c b/src/vm-limit.c index bad1d61e611..f138dc28b2e 100644 --- a/src/vm-limit.c +++ b/src/vm-limit.c @@ -71,15 +71,6 @@ static char *data_space_start; /* Number of bytes of writable memory we can expect to be able to get. */ static size_t lim_data; -/* Return true if PTR cannot be represented as an Emacs Lisp object. */ -static bool -exceeds_lisp_ptr (void *ptr) -{ - return (! USE_LSB_TAG - && VAL_MAX < UINTPTR_MAX - && ((uintptr_t) ptr & ~DATA_SEG_BITS) >> VALBITS != 0); -} - #ifdef HAVE_GETRLIMIT # ifndef RLIMIT_AS @@ -222,9 +213,6 @@ check_memory_limits (void) else if (warnlevel > warned_85 && data_size < five_percent * 18) warnlevel = warned_85; } - - if (exceeds_lisp_ptr (cp)) - (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); } /* Enable memory usage warnings. diff --git a/src/w32.c b/src/w32.c index 0892f932bc2..4643fc7fbec 100644 --- a/src/w32.c +++ b/src/w32.c @@ -73,9 +73,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <grp.h> /* MinGW64 (_W64) defines these in its _mingw.h. */ -#if defined(__GNUC__) && !defined(_W64) -#define _ANONYMOUS_UNION -#define _ANONYMOUS_STRUCT +#ifndef _ANONYMOUS_UNION +# define _ANONYMOUS_UNION +#endif +#ifndef _ANONYMOUS_STRUCT +# define _ANONYMOUS_STRUCT #endif #include <windows.h> /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we @@ -1707,7 +1709,7 @@ static unsigned num_of_processors; /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */ static struct load_sample samples[16*60]; static int first_idx = -1, last_idx = -1; -static int max_idx = sizeof (samples) / sizeof (samples[0]); +static int max_idx = ARRAYELTS (samples); static int buf_next (int from) @@ -2413,7 +2415,6 @@ unsetenv (const char *name) { char *var; size_t name_len; - int retval; if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { @@ -2512,7 +2513,7 @@ init_environment (char ** argv) int i; - const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]); + const int imax = ARRAYELTS (tempdirs); /* Implementation note: This function explicitly works with ANSI file names, not with UTF-8 encoded file names. This is because @@ -2585,7 +2586,7 @@ init_environment (char ** argv) {"LANG", NULL}, }; -#define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0]) +#define N_ENV_VARS ARRAYELTS (dflt_envvars) /* We need to copy dflt_envvars[] and work on the copy because we don't want the dumped Emacs to inherit the values of @@ -8697,6 +8698,13 @@ w32_delayed_load (Lisp_Object library_id) /* Possibly truncated */ ? make_specified_string (name, -1, len, 1) : Qnil); + /* This prevents thread start and end notifications + from being sent to the DLL, for every thread we + start. We don't need those notifications because + threads we create never use any of these DLLs, only + the main thread uses them. This is supposed to + speed up thread creation. */ + DisableThreadLibraryCalls (dll_handle); break; } } @@ -9249,8 +9257,6 @@ ssize_t emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz) { int n, err; - SELECT_TYPE fdset; - struct timespec timeout; struct Lisp_Process *process = (struct Lisp_Process *)p; int fd = process->infd; diff --git a/src/w32console.c b/src/w32console.c index e3ca2f86b8d..2fbc190ee2d 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -36,8 +36,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "termhooks.h" #include "termchar.h" #include "dispextern.h" +#include "menu.h" /* for tty_menu_show */ #include "w32term.h" -#include "w32common.h" /* for os_subtype */ +#include "w32common.h" /* for os_subtype */ #include "w32inevt.h" /* from window.c */ @@ -650,6 +651,7 @@ initialize_w32_display (struct terminal *term, int *width, int *height) term->read_socket_hook = w32_console_read_socket; term->mouse_position_hook = w32_console_mouse_position; + term->menu_show_hook = tty_menu_show; /* The following are not used on the console. */ term->frame_rehighlight_hook = 0; diff --git a/src/w32fns.c b/src/w32fns.c index 638c617df99..c9a83c98234 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -723,8 +723,7 @@ w32_default_color_map (void) cmap = Qnil; - for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]); - pc++, i++) + for (i = 0; i < ARRAYELTS (w32_color_map); pc++, i++) cmap = Fcons (Fcons (build_string (pc->name), make_number (pc->colorref)), cmap); @@ -6883,24 +6882,33 @@ operations: specified DOCUMENT. \"find\" - initiate search starting from DOCUMENT, which must specify a directory. + \"delete\" - move DOCUMENT, a file or a directory, to Recycle Bin. + \"copy\" - copy DOCUMENT, which must be a file or a directory, into + the clipboard. + \"cut\" - move DOCUMENT, a file or a directory, into the clipboard. + \"paste\" - paste the file whose name is in the clipboard into DOCUMENT, + which must be a directory. + \"pastelink\" + - create a shortcut in DOCUMENT (which must be a directory) + the file or directory whose name is in the clipboard. \"runas\" - run DOCUMENT, which must be an excutable file, with elevated privileges (a.k.a. \"as Administrator\"). \"properties\" - - open the the property sheet dialog for DOCUMENT; works - for *.lnk desktop shortcuts, and little or nothing else. + - open the the property sheet dialog for DOCUMENT. nil - invoke the default OPERATION, or \"open\" if default is not defined or unavailable. DOCUMENT is typically the name of a document file or a URL, but can also be an executable program to run, or a directory to open in the -Windows Explorer. If it is a file, it must be a local one; this -function does not support remote file names. +Windows Explorer. If it is a file or a directory, it must be a local +one; this function does not support remote file names. If DOCUMENT is an executable program, the optional third arg PARAMETERS -can be a string containing command line parameters that will be passed -to the program. Some values of OPERATION also require parameters (e.g., -\"printto\" requires the printer address). Otherwise, PARAMETERS should -be nil or unspecified. +can be a string containing command line parameters, separated by blanks, +that will be passed to the program. Some values of OPERATION also require +parameters (e.g., \"printto\" requires the printer address). Otherwise, +PARAMETERS should be nil or unspecified. Note that double quote characters +in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\". Optional fourth argument SHOW-FLAG can be used to control how the application will be displayed when it is invoked. If SHOW-FLAG is nil @@ -6918,11 +6926,13 @@ a ShowWindow flag: char *errstr; Lisp_Object current_dir = BVAR (current_buffer, directory);; wchar_t *doc_w = NULL, *params_w = NULL, *ops_w = NULL; +#ifdef CYGWIN intptr_t result; -#ifndef CYGWIN +#else int use_unicode = w32_unicode_filenames; char *doc_a = NULL, *params_a = NULL, *ops_a = NULL; Lisp_Object absdoc, handler; + BOOL success; struct gcpro gcpro1; #endif @@ -6950,7 +6960,48 @@ a ShowWindow flag: GUI_SDATA (current_dir), (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT)); + + if (result > 32) + return Qt; + + switch (result) + { + case SE_ERR_ACCESSDENIED: + errstr = w32_strerror (ERROR_ACCESS_DENIED); + break; + case SE_ERR_ASSOCINCOMPLETE: + case SE_ERR_NOASSOC: + errstr = w32_strerror (ERROR_NO_ASSOCIATION); + break; + case SE_ERR_DDEBUSY: + case SE_ERR_DDEFAIL: + errstr = w32_strerror (ERROR_DDE_FAIL); + break; + case SE_ERR_DDETIMEOUT: + errstr = w32_strerror (ERROR_TIMEOUT); + break; + case SE_ERR_DLLNOTFOUND: + errstr = w32_strerror (ERROR_DLL_NOT_FOUND); + break; + case SE_ERR_FNF: + errstr = w32_strerror (ERROR_FILE_NOT_FOUND); + break; + case SE_ERR_OOM: + errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY); + break; + case SE_ERR_PNF: + errstr = w32_strerror (ERROR_PATH_NOT_FOUND); + break; + case SE_ERR_SHARE: + errstr = w32_strerror (ERROR_SHARING_VIOLATION); + break; + default: + errstr = w32_strerror (0); + break; + } + #else /* !CYGWIN */ + current_dir = ENCODE_FILE (current_dir); /* We have a situation here. If DOCUMENT is a relative file name, but its name includes leading directories, i.e. it lives not in @@ -6980,6 +7031,7 @@ a ShowWindow flag: if (use_unicode) { wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH]; + SHELLEXECUTEINFOW shexinfo_w; /* Encode filename, current directory and parameters, and convert operation to UTF-16. */ @@ -7013,14 +7065,28 @@ a ShowWindow flag: *d++ = *s++; *d = 0; } - result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w, - current_dir_w, - (INTEGERP (show_flag) - ? XINT (show_flag) : SW_SHOWDEFAULT)); + + /* Using ShellExecuteEx and setting the SEE_MASK_INVOKEIDLIST + flag succeeds with more OPERATIONs (a.k.a. "verbs"), as it is + able to invoke verbs from shortcut menu extensions, not just + static verbs listed in the Registry. */ + memset (&shexinfo_w, 0, sizeof (shexinfo_w)); + shexinfo_w.cbSize = sizeof (shexinfo_w); + shexinfo_w.fMask = + SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; + shexinfo_w.hwnd = NULL; + shexinfo_w.lpVerb = ops_w; + shexinfo_w.lpFile = doc_w; + shexinfo_w.lpParameters = params_w; + shexinfo_w.lpDirectory = current_dir_w; + shexinfo_w.nShow = + (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT); + success = ShellExecuteExW (&shexinfo_w); } else { char document_a[MAX_PATH], current_dir_a[MAX_PATH]; + SHELLEXECUTEINFOA shexinfo_a; filename_to_ansi (SSDATA (current_dir), current_dir_a); filename_to_ansi (SSDATA (document), document_a); @@ -7035,51 +7101,27 @@ a ShowWindow flag: /* Assume OPERATION is pure ASCII. */ ops_a = SSDATA (operation); } - result = (intptr_t) ShellExecuteA (NULL, ops_a, doc_a, params_a, - current_dir_a, - (INTEGERP (show_flag) - ? XINT (show_flag) : SW_SHOWDEFAULT)); + memset (&shexinfo_a, 0, sizeof (shexinfo_a)); + shexinfo_a.cbSize = sizeof (shexinfo_a); + shexinfo_a.fMask = + SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; + shexinfo_a.hwnd = NULL; + shexinfo_a.lpVerb = ops_a; + shexinfo_a.lpFile = doc_a; + shexinfo_a.lpParameters = params_a; + shexinfo_a.lpDirectory = current_dir_a; + shexinfo_a.nShow = + (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT); + success = ShellExecuteExA (&shexinfo_a); } -#endif /* !CYGWIN */ - if (result > 32) + if (success) return Qt; - switch (result) - { - case SE_ERR_ACCESSDENIED: - errstr = w32_strerror (ERROR_ACCESS_DENIED); - break; - case SE_ERR_ASSOCINCOMPLETE: - case SE_ERR_NOASSOC: - errstr = w32_strerror (ERROR_NO_ASSOCIATION); - break; - case SE_ERR_DDEBUSY: - case SE_ERR_DDEFAIL: - errstr = w32_strerror (ERROR_DDE_FAIL); - break; - case SE_ERR_DDETIMEOUT: - errstr = w32_strerror (ERROR_TIMEOUT); - break; - case SE_ERR_DLLNOTFOUND: - errstr = w32_strerror (ERROR_DLL_NOT_FOUND); - break; - case SE_ERR_FNF: - errstr = w32_strerror (ERROR_FILE_NOT_FOUND); - break; - case SE_ERR_OOM: - errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY); - break; - case SE_ERR_PNF: - errstr = w32_strerror (ERROR_PATH_NOT_FOUND); - break; - case SE_ERR_SHARE: - errstr = w32_strerror (ERROR_SHARING_VIOLATION); - break; - default: - errstr = w32_strerror (0); - break; - } + errstr = w32_strerror (0); + +#endif /* !CYGWIN */ + /* The error string might be encoded in the locale's encoding. */ if (!NILP (Vlocale_coding_system)) { @@ -7499,8 +7541,8 @@ If the underlying system call fails, value is nil. */) (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = GetProcAddress (hKernel, "GetDiskFreeSpaceExA"); bool have_pfn_GetDiskFreeSpaceEx = - (w32_unicode_filenames && pfn_GetDiskFreeSpaceExW - || !w32_unicode_filenames && pfn_GetDiskFreeSpaceExA); + ((w32_unicode_filenames && pfn_GetDiskFreeSpaceExW) + || (!w32_unicode_filenames && pfn_GetDiskFreeSpaceExA)); /* On Windows, we may need to specify the root directory of the volume holding FILENAME. */ diff --git a/src/w32gui.h b/src/w32gui.h index b8c8557357a..d04ce625d1d 100644 --- a/src/w32gui.h +++ b/src/w32gui.h @@ -22,14 +22,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "systime.h" /* for Time */ -/* Local memory management for menus. */ +/* FIXME: old local memory management for menus. */ #define local_heap (GetProcessHeap ()) #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n))) #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p)))) -#define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value))) -#define free_widget_value(wv) (local_free ((wv))) - /* Emulate X GC's by keeping color and font info in a structure. */ typedef struct _XGCValues { diff --git a/src/w32heap.c b/src/w32heap.c index 8ab2f58c6e7..94ba3428794 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -1,256 +1,695 @@ -/* Heap management routines for GNU Emacs on the Microsoft Windows API. - Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc. +/* Heap management routines for GNU Emacs on the Microsoft Windows + API. Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc. -This file is part of GNU Emacs. + This file is part of GNU Emacs. -GNU Emacs is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + GNU Emacs is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GNU Emacs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public License + along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ /* - Geoff Voelker (voelker@cs.washington.edu) 7-29-94 + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ +/* + Heavily modified by Fabrice Popineau (fabrice.popineau@gmail.com) 28-02-2014 +*/ + +/* + Memory allocation scheme for w32/w64: + + - Buffers are mmap'ed using a very simple emulation of mmap/munmap + - During the temacs phase: + * we use a private heap declared to be stored into the `dumped_data' + * unfortunately, this heap cannot be made growable, so the size of + blocks it can allocate is limited to (0x80000 - pagesize) + * the blocks that are larger than this are allocated from the end + of the `dumped_data' array; there are not so many of them. + We use a very simple first-fit scheme to reuse those blocks. + * we check that the private heap does not cross the area used + by the bigger chunks. + - During the emacs phase: + * we create a private heap for new memory blocks + * we make sure that we never free a block that has been dumped. + Freeing a dumped block could work in principle, but may prove + unreliable if we distribute binaries of emacs.exe: MS does not + guarantee that the heap data structures are the same across all + versions of their OS, even though the API is available since XP. */ + #include <config.h> #include <stdio.h> +#include <errno.h> +#include <sys/mman.h> #include "w32common.h" #include "w32heap.h" #include "lisp.h" /* for VALMASK */ -#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD_PTR)(rva) + (DWORD_PTR)GetModuleHandle (NULL))) - -/* Emulate getpagesize. */ -int -getpagesize (void) -{ - return sysinfo_cache.dwPageSize; -} +/* We chose to leave those declarations here. They are used only in + this file. The RtlCreateHeap is available since XP. It is located + in ntdll.dll and is available with the DDK. People often + complained that HeapCreate doesn't offer the ability to create a + heap at a given place, which we need here, and which RtlCreateHeap + provides. We reproduce here the definitions available with the + DDK. */ + +typedef PVOID (WINAPI * RtlCreateHeap_Proc) ( + /* _In_ */ ULONG Flags, + /* _In_opt_ */ PVOID HeapBase, + /* _In_opt_ */ SIZE_T ReserveSize, + /* _In_opt_ */ SIZE_T CommitSize, + /* _In_opt_ */ PVOID Lock, + /* _In_opt_ */ PVOID Parameters + ); + +typedef LONG NTSTATUS; + +typedef NTSTATUS +(NTAPI * PRTL_HEAP_COMMIT_ROUTINE)( + IN PVOID Base, + IN OUT PVOID *CommitAddress, + IN OUT PSIZE_T CommitSize + ); + +typedef struct _RTL_HEAP_PARAMETERS { + ULONG Length; + SIZE_T SegmentReserve; + SIZE_T SegmentCommit; + SIZE_T DeCommitFreeBlockThreshold; + SIZE_T DeCommitTotalFreeThreshold; + SIZE_T MaximumAllocationSize; + SIZE_T VirtualMemoryThreshold; + SIZE_T InitialCommit; + SIZE_T InitialReserve; + PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; + SIZE_T Reserved[ 2 ]; +} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; + +/* We reserve space for dumping emacs lisp byte-code inside a static + array. By storing it in an array, the generic mechanism in + unexecw32.c will be able to dump it without the need to add a + special segment to the executable. In order to be able to do this + without losing too much space, we need to create a Windows heap at + the specific address of the static array. The RtlCreateHeap + available inside the NT kernel since XP will do this. It allows to + create a non-growable heap at a specific address. So before + dumping, we create a non-growable heap at the address of the + dumped_data[] array. After dumping, we reuse memory allocated + there without being able to free it (but most of it is not meant to + be freed anyway), and we use a new private heap for all new + allocations. */ + +/* FIXME: Most of the space reserved for dumped_data[] is only used by + the 1st bootstrap-emacs.exe built while bootstrapping. Once the + preloaded Lisp files are byte-compiled, the next loadup uses less + than half of the size stated below. It would be nice to find a way + to build only the first bootstrap-emacs.exe with the large size, + and reset that to a lower value afterwards. */ +#ifdef _WIN64 +# define DUMPED_HEAP_SIZE (18*1024*1024) +#else +# define DUMPED_HEAP_SIZE (11*1024*1024) +#endif -/* Info for managing our preload heap, which is essentially a fixed size - data area in the executable. */ -PIMAGE_SECTION_HEADER preload_heap_section; +static unsigned char dumped_data[DUMPED_HEAP_SIZE]; -/* Info for keeping track of our heap. */ +/* Info for keeping track of our dynamic heap used after dumping. */ unsigned char *data_region_base = NULL; unsigned char *data_region_end = NULL; -unsigned char *real_data_region_end = NULL; -size_t reserved_heap_size = 0; +static DWORD_PTR committed = 0; -/* The start of the data segment. */ -unsigned char * -get_data_start (void) -{ - return data_region_base; -} +/* The maximum block size that can be handled by a non-growable w32 + heap is limited by the MaxBlockSize value below. + + This point deserves and explanation. + + The W32 heap allocator can be used for a growable + heap or a non-growable one. + + A growable heap is not compatible with a fixed base address for the + heap. Only a non-growable one is. One drawback of non-growable + heaps is that they can hold only objects smaller than a certain + size (the one defined below). Most of the largest blocks are GC'ed + before dumping. In any case and to be safe, we implement a simple + first-fit allocation algorithm starting at the end of the + dumped_data[] array like depicted below: -/* The end of the data segment. */ -unsigned char * -get_data_end (void) + ---------------------------------------------- + | | | | + | Private heap |-> <-| Big chunks | + | | | | + ---------------------------------------------- + ^ ^ ^ + dumped_data dumped_data bc_limit + + committed + +*/ + +/* Info for managing our preload heap, which is essentially a fixed size + data area in the executable. */ +#define PAGE_SIZE 0x1000 +#define MaxBlockSize (0x80000 - PAGE_SIZE) + +#define MAX_BLOCKS 0x40 + +static struct { - return data_region_end; -} + unsigned char *address; + size_t size; + DWORD occupied; +} blocks[MAX_BLOCKS]; + +static DWORD blocks_number = 0; +static unsigned char *bc_limit; + +/* Handle for the private heap: + - inside the dumped_data[] array before dump, + - outside of it after dump. +*/ +HANDLE heap = NULL; + +/* We redirect the standard allocation functions. */ +malloc_fn the_malloc_fn; +realloc_fn the_realloc_fn; +free_fn the_free_fn; + +/* It doesn't seem to be useful to allocate from a file mapping. + It would be if the memory was shared. + http://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */ -#if !USE_LSB_TAG -static char * -allocate_heap (void) +/* This is the function to commit memory when the heap allocator + claims for new memory. Before dumping, we allocate space + from the fixed size dumped_data[] array. +*/ +NTSTATUS NTAPI +dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize) { - /* Try to get as much as possible of the address range from the end of - the preload heap section up to the usable address limit. Since GNU - malloc can handle gaps in the memory it gets from sbrk, we can - simply set the sbrk pointer to the base of the new heap region. */ - DWORD_PTR base = - ROUND_UP ((RVA_TO_PTR (preload_heap_section->VirtualAddress) - + preload_heap_section->Misc.VirtualSize), - get_allocation_unit ()); - DWORD_PTR end = ((unsigned __int64)1) << VALBITS; /* 256MB */ - void *ptr = NULL; - - while (!ptr && (base < end)) + /* This is used before dumping. + + The private heap is stored at dumped_data[] address. + We commit contiguous areas of the dumped_data array + as requests arrive. */ + *CommitAddress = data_region_base + committed; + committed += *CommitSize; + if (((unsigned char *)(*CommitAddress)) + *CommitSize >= bc_limit) { -#ifdef _WIN64 - reserved_heap_size = min(end - base, 0x4000000000ull); /* Limit to 256Gb */ -#else - reserved_heap_size = end - base; -#endif - ptr = VirtualAlloc ((void *) base, - get_reserved_heap_size (), - MEM_RESERVE, - PAGE_NOACCESS); - base += 0x00100000; /* 1MB increment */ + /* Check that the private heap area does not overlap the big + chunks area. */ + fprintf(stderr, + "dumped_data_commit: memory exhausted.\nEnlarge dumped_data[]!\n"); + exit (-1); } - - return ptr; + return 0; } -#else /* USE_LSB_TAG */ -static char * -allocate_heap (void) + +/* Heap creation. */ + +/* We want to turn on Low Fragmentation Heap for XP and older systems. + MinGW32 lacks those definitions. */ +#ifndef _W64 +typedef enum _HEAP_INFORMATION_CLASS { + HeapCompatibilityInformation +} HEAP_INFORMATION_CLASS; + +typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T); +#endif + +void +init_heap (void) { -#ifdef _WIN64 - size_t size = 0x4000000000ull; /* start by asking for 32GB */ -#else - /* We used to start with 2GB here, but on Windows 7 that would leave - too little room in the address space for threads started by - Windows on our behalf, e.g. when we pop up the file selection - dialog. */ - size_t size = 0x68000000; /* start by asking for 1.7GB */ + if (using_dynamic_heap) + { + unsigned long enable_lfh = 2; + + /* After dumping, use a new private heap. We explicitly enable + the low fragmentation heap (LFH) here, for the sake of pre + Vista versions. Note: this will harmlessly fail on Vista and + later, where the low-fragmentation heap is enabled by + default. It will also fail on pre-Vista versions when Emacs + is run under a debugger; set _NO_DEBUG_HEAP=1 in the + environment before starting GDB to get low fragmentation heap + on XP and older systems, for the price of losing "certain + heap debug options"; for the details see + http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */ + data_region_end = data_region_base; + + /* Create the private heap. */ + heap = HeapCreate(0, 0, 0); + +#ifndef _W64 + /* Set the low-fragmentation heap for OS before Vista. */ + HMODULE hm_kernel32dll = LoadLibrary("kernel32.dll"); + HeapSetInformation_Proc s_pfn_Heap_Set_Information = (HeapSetInformation_Proc) GetProcAddress(hm_kernel32dll, "HeapSetInformation"); + if (s_pfn_Heap_Set_Information != NULL) + if (s_pfn_Heap_Set_Information ((PVOID) heap, + HeapCompatibilityInformation, + &enable_lfh, sizeof(enable_lfh)) == 0) + DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n", + GetLastError ())); #endif - void *ptr = NULL; - while (!ptr && size > 0x00100000) + the_malloc_fn = malloc_after_dump; + the_realloc_fn = realloc_after_dump; + the_free_fn = free_after_dump; + } + else { - reserved_heap_size = size; - ptr = VirtualAlloc (NULL, - get_reserved_heap_size (), - MEM_RESERVE, - PAGE_NOACCESS); - size -= 0x00800000; /* if failed, decrease request by 8MB */ + /* Find the RtlCreateHeap function. Headers for this function + are provided with the w32 ddk, but the function is available + in ntdll.dll since XP. */ + HMODULE hm_ntdll = LoadLibrary ("ntdll.dll"); + RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap + = (RtlCreateHeap_Proc) GetProcAddress (hm_ntdll, "RtlCreateHeap"); + /* Specific parameters for the private heap. */ + RTL_HEAP_PARAMETERS params; + ZeroMemory(¶ms, sizeof(params)); + params.Length = sizeof(RTL_HEAP_PARAMETERS); + + data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000); + data_region_end = bc_limit = dumped_data + DUMPED_HEAP_SIZE; + + params.InitialCommit = committed = 0x1000; + params.InitialReserve = sizeof(dumped_data); + /* Use our own routine to commit memory from the dumped_data + array. */ + params.CommitRoutine = &dumped_data_commit; + + /* Create the private heap. */ + heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, ¶ms); + the_malloc_fn = malloc_before_dump; + the_realloc_fn = realloc_before_dump; + the_free_fn = free_before_dump; } - return ptr; + /* Update system version information to match current system. */ + cache_system_info (); } -#endif /* USE_LSB_TAG */ +#undef malloc +#undef realloc +#undef free + +/* FREEABLE_P checks if the block can be safely freed. */ +#define FREEABLE_P(addr) \ + ((unsigned char *)(addr) < dumped_data \ + || (unsigned char *)(addr) >= dumped_data + DUMPED_HEAP_SIZE) -/* Emulate Unix sbrk. Note that ralloc.c expects the return value to - be the address of the _start_ (not end) of the new block in case of - success, and zero (not -1) in case of failure. */ void * -sbrk (ptrdiff_t increment) +malloc_after_dump (size_t size) { - void *result; - ptrdiff_t size = increment; + /* Use the new private heap. */ + void *p = HeapAlloc (heap, 0, size); - result = data_region_end; + /* After dump, keep track of the "brk value" for sbrk(0). */ + if (p) + { + unsigned char *new_brk = (unsigned char *)p + size; - /* If size is negative, shrink the heap by decommitting pages. */ - if (size < 0) + if (new_brk > data_region_end) + data_region_end = new_brk; + } + else + errno = ENOMEM; + return p; +} + +void * +malloc_before_dump (size_t size) +{ + void *p; + + /* Before dumping. The private heap can handle only requests for + less than MaxBlockSize. */ + if (size < MaxBlockSize) { - ptrdiff_t new_size; - unsigned char *new_data_region_end; - - size = -size; - - /* Sanity checks. */ - if ((data_region_end - size) < data_region_base) - return NULL; - - /* We can only decommit full pages, so allow for - partial deallocation [cga]. */ - new_data_region_end = (data_region_end - size); - new_data_region_end = (unsigned char *) - ((DWORD_PTR) (new_data_region_end + syspage_mask) & ~syspage_mask); - new_size = real_data_region_end - new_data_region_end; - real_data_region_end = new_data_region_end; - if (new_size > 0) + /* Use the private heap if possible. */ + p = HeapAlloc (heap, 0, size); + if (!p) + errno = ENOMEM; + } + else + { + /* Find the first big chunk that can hold the requested size. */ + int i = 0; + + for (i = 0; i < blocks_number; i++) { - /* Decommit size bytes from the end of the heap. */ - if (using_dynamic_heap - && !VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT)) - return NULL; - } + if (blocks[i].occupied == 0 && blocks[i].size >= size) + break; + } + if (i < blocks_number) + { + /* If found, use it. */ + p = blocks[i].address; + blocks[i].occupied = TRUE; + } + else + { + /* Allocate a new big chunk from the end of the dumped_data + array. */ + if (blocks_number >= MAX_BLOCKS) + { + fprintf(stderr, + "malloc_before_dump: no more big chunks available.\nEnlarge MAX_BLOCKS!\n"); + exit (-1); + } + bc_limit -= size; + bc_limit = (unsigned char *)ROUND_DOWN (bc_limit, 0x10); + p = bc_limit; + blocks[blocks_number].address = p; + blocks[blocks_number].size = size; + blocks[blocks_number].occupied = TRUE; + blocks_number++; + if (bc_limit < dumped_data + committed) + { + /* Check that areas do not overlap. */ + fprintf(stderr, + "malloc_before_dump: memory exhausted.\nEnlarge dumped_data[]!\n"); + exit (-1); + } + } + } + return p; +} + +/* Re-allocate the previously allocated block in ptr, making the new + block SIZE bytes long. */ +void * +realloc_after_dump (void *ptr, size_t size) +{ + void *p; - data_region_end -= size; + /* After dumping. */ + if (FREEABLE_P (ptr)) + { + /* Reallocate the block since it lies in the new heap. */ + p = HeapReAlloc (heap, 0, ptr, size); + if (!p) + errno = ENOMEM; } - /* If size is positive, grow the heap by committing reserved pages. */ - else if (size > 0) + else { - /* Sanity checks. */ - if ((data_region_end + size) > - (data_region_base + get_reserved_heap_size ())) - return NULL; - - /* Commit more of our heap. */ - if (using_dynamic_heap - && VirtualAlloc (data_region_end, size, MEM_COMMIT, - PAGE_READWRITE) == NULL) - return NULL; - data_region_end += size; - - /* We really only commit full pages, so record where - the real end of committed memory is [cga]. */ - real_data_region_end = (unsigned char *) - ((DWORD_PTR) (data_region_end + syspage_mask) & ~syspage_mask); + /* If the block lies in the dumped data, do not free it. Only + allocate a new one. */ + p = HeapAlloc (heap, 0, size); + if (p) + CopyMemory (p, ptr, size); + else + errno = ENOMEM; } + /* After dump, keep track of the "brk value" for sbrk(0). */ + if (p) + { + unsigned char *new_brk = (unsigned char *)p + size; - return result; + if (new_brk > data_region_end) + data_region_end = new_brk; + } + return p; } -/* Initialize the internal heap variables used by sbrk. When running in - preload phase (ie. in the undumped executable), we rely entirely on a - fixed size heap section included in the .exe itself; this is - preserved during dumping, and truncated to the size actually used. - - When running in the dumped executable, we reserve as much as possible - of the address range that is addressable by Lisp object pointers, to - supplement what is left of the preload heap. Although we cannot rely - on the dynamically allocated arena being contiguous with the static - heap area, it is not a problem because sbrk can pretend that the gap - was allocated by something else; GNU malloc detects when there is a - jump in the sbrk values, and starts a new heap block. */ -void -init_heap (void) +void * +realloc_before_dump (void *ptr, size_t size) { - PIMAGE_DOS_HEADER dos_header; - PIMAGE_NT_HEADERS nt_header; - - dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0); - nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) + - dos_header->e_lfanew); - preload_heap_section = find_section ("EMHEAP", nt_header); + void *p; - if (using_dynamic_heap) + /* Before dumping. */ + if (dumped_data < (unsigned char *)ptr + && (unsigned char *)ptr < bc_limit && size <= MaxBlockSize) + { + p = HeapReAlloc (heap, 0, ptr, size); + if (!p) + errno = ENOMEM; + } + else { - data_region_base = allocate_heap (); - if (!data_region_base) + /* In this case, either the new block is too large for the heap, + or the old block was already too large. In both cases, + malloc_before_dump() and free_before_dump() will take care of + reallocation. */ + p = malloc_before_dump (size); + /* If SIZE is below MaxBlockSize, malloc_before_dump will try to + allocate it in the fixed heap. If that fails, we could have + kept the block in its original place, above bc_limit, instead + of failing the call as below. But this doesn't seem to be + worth the added complexity, as loadup allocates only a very + small number of large blocks, and never reallocates them. */ + if (p) { - printf ("Error: Could not reserve dynamic heap area.\n"); - exit (1); + CopyMemory (p, ptr, size); + free_before_dump (ptr); } + } + return p; +} + +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +void +free_after_dump (void *ptr) +{ + /* After dumping. */ + if (FREEABLE_P (ptr)) + { + /* Free the block if it is in the new private heap. */ + HeapFree (heap, 0, ptr); + } +} -#if !USE_LSB_TAG - /* Ensure that the addresses don't use the upper tag bits since - the Lisp type goes there. */ - if (((DWORD_PTR) data_region_base & ~VALMASK) != 0) +void +free_before_dump (void *ptr) +{ + /* Before dumping. */ + if (dumped_data < (unsigned char *)ptr + && (unsigned char *)ptr < bc_limit) + { + /* Free the block if it is allocated in the private heap. */ + HeapFree (heap, 0, ptr); + } + else + { + /* Look for the big chunk. */ + int i; + + for (i = 0; i < blocks_number; i++) { - printf ("Error: The heap was allocated in upper memory.\n"); - exit (1); + if (blocks[i].address == ptr) + { + /* Reset block occupation if found. */ + blocks[i].occupied = 0; + break; + } + /* What if the block is not found? We should trigger an + error here. */ + eassert (i < blocks_number); } + } +} + +#ifdef ENABLE_CHECKING +void +report_temacs_memory_usage (void) +{ + DWORD blocks_used = 0; + size_t large_mem_used = 0; + int i; + + for (i = 0; i < blocks_number; i++) + if (blocks[i].occupied) + { + blocks_used++; + large_mem_used += blocks[i].size; + } + + /* Emulate 'message', which writes to stderr in non-interactive + sessions. */ + fprintf (stderr, + "Dump memory usage: Heap: %" PRIu64 " Large blocks(%lu/%lu): %" PRIu64 "/%" PRIu64 "\n", + (unsigned long long)committed, blocks_used, blocks_number, + (unsigned long long)large_mem_used, + (unsigned long long)(dumped_data + DUMPED_HEAP_SIZE - bc_limit)); +} #endif - data_region_end = data_region_base; - real_data_region_end = data_region_end; + +/* Emulate getpagesize. */ +int +getpagesize (void) +{ + return sysinfo_cache.dwPageSize; +} + +void * +sbrk (ptrdiff_t increment) +{ + /* data_region_end is the address beyond the last allocated byte. + The sbrk() function is not emulated at all, except for a 0 value + of its parameter. This is needed by the Emacs Lisp function + `memory-limit'. */ + eassert (increment == 0); + return data_region_end; +} + +#define MAX_BUFFER_SIZE (512 * 1024 * 1024) + +/* MMAP allocation for buffers. */ +void * +mmap_alloc (void **var, size_t nbytes) +{ + void *p = NULL; + + /* We implement amortized allocation. We start by reserving twice + the size requested and commit only the size requested. Then + realloc could proceed and use the reserved pages, reallocating + only if needed. Buffer shrink would happen only so that we stay + in the 2x range. This is a big win when visiting compressed + files, where the final size of the buffer is not known in + advance, and the buffer is enlarged several times as the data is + decompressed on the fly. */ + if (nbytes < MAX_BUFFER_SIZE) + p = VirtualAlloc (NULL, (nbytes * 2), MEM_RESERVE, PAGE_READWRITE); + + /* If it fails, or if the request is above 512MB, try with the + requested size. */ + if (p == NULL) + p = VirtualAlloc (NULL, nbytes, MEM_RESERVE, PAGE_READWRITE); + + if (p != NULL) + { + /* Now, commit pages for NBYTES. */ + *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); } - else + + if (!p) { - data_region_base = RVA_TO_PTR (preload_heap_section->VirtualAddress); - data_region_end = data_region_base; - real_data_region_end = data_region_end; - reserved_heap_size = preload_heap_section->Misc.VirtualSize; + if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY) + errno = ENOMEM; + else + { + DebPrint (("mmap_alloc: error %ld\n", GetLastError ())); + errno = EINVAL; + } } - /* Update system version information to match current system. */ - cache_system_info (); + return *var = p; } -/* Round the heap up to the given alignment. */ void -round_heap (size_t align) +mmap_free (void **var) { - DWORD_PTR needs_to_be; - DWORD_PTR need_to_alloc; + if (*var) + { + if (VirtualFree (*var, 0, MEM_RELEASE) == 0) + DebPrint (("mmap_free: error %ld\n", GetLastError ())); + *var = NULL; + } +} + +void * +mmap_realloc (void **var, size_t nbytes) +{ + MEMORY_BASIC_INFORMATION memInfo, m2; + + if (*var == NULL) + return mmap_alloc (var, nbytes); + + /* This case happens in init_buffer(). */ + if (nbytes == 0) + { + mmap_free (var); + return mmap_alloc (var, nbytes); + } + + if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) + DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ())); - needs_to_be = (DWORD_PTR) ROUND_UP (get_heap_end (), align); - need_to_alloc = needs_to_be - (DWORD_PTR) get_heap_end (); + /* We need to enlarge the block. */ + if (memInfo.RegionSize < nbytes) + { + if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) + DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", + GetLastError ())); + /* If there is enough room in the current reserved area, then + commit more pages as needed. */ + if (m2.State == MEM_RESERVE + && nbytes <= memInfo.RegionSize + m2.RegionSize) + { + void *p; + + p = VirtualAlloc (*var + memInfo.RegionSize, + nbytes - memInfo.RegionSize, + MEM_COMMIT, PAGE_READWRITE); + if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) + { + DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", + GetLastError ())); + errno = ENOMEM; + } + return *var; + } + else + { + /* Else we must actually enlarge the block by allocating a + new one and copying previous contents from the old to the + new one. */ + void *old_ptr = *var; + + if (mmap_alloc (var, nbytes)) + { + CopyMemory (*var, old_ptr, memInfo.RegionSize); + mmap_free (&old_ptr); + return *var; + } + else + { + /* We failed to enlarge the buffer. */ + *var = old_ptr; + return NULL; + } + } + } + + /* If we are shrinking by more than one page... */ + if (memInfo.RegionSize > nbytes + getpagesize()) + { + /* If we are shrinking a lot... */ + if ((memInfo.RegionSize / 2) > nbytes) + { + /* Let's give some memory back to the system and release + some pages. */ + void *old_ptr = *var; + + if (mmap_alloc (var, nbytes)) + { + CopyMemory (*var, old_ptr, nbytes); + mmap_free (&old_ptr); + return *var; + } + else + { + /* In case we fail to shrink, try to go on with the old block. + But that means there is a lot of memory pressure. + We could also decommit pages. */ + *var = old_ptr; + return *var; + } + } + + /* We still can decommit pages. */ + if (VirtualFree (*var + nbytes + get_page_size(), + memInfo.RegionSize - nbytes - get_page_size(), + MEM_DECOMMIT) == 0) + DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError ())); + return *var; + } - if (need_to_alloc) - sbrk (need_to_alloc); + /* Not enlarging, not shrinking by more than one page. */ + return *var; } diff --git a/src/w32heap.h b/src/w32heap.h index d5791a3a23c..787fe9ade5f 100644 --- a/src/w32heap.h +++ b/src/w32heap.h @@ -27,15 +27,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. /* * Heap related stuff. */ -#define get_reserved_heap_size() reserved_heap_size -#define get_committed_heap_size() (get_data_end () - get_data_start ()) -#define get_heap_start() get_data_start () -#define get_heap_end() get_data_end () extern unsigned char *get_data_start (void); extern unsigned char *get_data_end (void); extern size_t reserved_heap_size; -extern BOOL using_dynamic_heap; +extern BOOL using_dynamic_heap; + +extern void *mmap_realloc (void **, size_t); +extern void mmap_free (void **); +extern void *mmap_alloc (void **, size_t); + +extern void report_temacs_memory_usage (void); /* Emulation of Unix sbrk(). */ extern void *sbrk (ptrdiff_t size); @@ -43,11 +45,8 @@ extern void *sbrk (ptrdiff_t size); /* Initialize heap structures for sbrk on startup. */ extern void init_heap (void); -/* Round the heap to this size. */ -extern void round_heap (size_t size); - /* ----------------------------------------------------------------- */ -/* Useful routines for manipulating memory-mapped files. */ +/* Useful routines for manipulating memory-mapped files. */ typedef struct file_data { char *name; @@ -61,11 +60,11 @@ int open_input_file (file_data *p_file, char *name); int open_output_file (file_data *p_file, char *name, unsigned long size); void close_file_data (file_data *p_file); -/* Return pointer to section header for named section. */ +/* Return pointer to section header for named section. */ IMAGE_SECTION_HEADER * find_section (char * name, IMAGE_NT_HEADERS * nt_header); /* Return pointer to section header for section containing the given - relative virtual address. */ + relative virtual address. */ IMAGE_SECTION_HEADER * rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header); #endif /* NTHEAP_H_ */ diff --git a/src/w32menu.c b/src/w32menu.c index a4acdfd9e91..6276c840fc6 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -103,7 +103,7 @@ Lisp_Object Qdebug_on_next_call, Qunsupported__w32_dialog; void set_frame_menubar (struct frame *, bool, bool); #ifdef HAVE_DIALOGS -static Lisp_Object w32_dialog_show (struct frame *, int, Lisp_Object, char**); +static Lisp_Object w32_dialog_show (struct frame *, Lisp_Object, Lisp_Object, char **); #else static int is_simple_dialog (Lisp_Object); static Lisp_Object simple_dialog_show (struct frame *, Lisp_Object, Lisp_Object); @@ -141,7 +141,7 @@ w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) /* Display them in a dialog box. */ block_input (); - selection = w32_dialog_show (f, 0, title, header, &error_name); + selection = w32_dialog_show (f, title, header, &error_name); unblock_input (); discard_menu_items (); @@ -376,12 +376,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Convert menu_items into widget_value trees to display the menu. This cannot evaluate Lisp code. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; i < last_i; i += 4) @@ -444,12 +440,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Make a widget-value tree containing just the top level menu bar strings. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; items = FRAME_MENU_BAR_ITEMS (f); @@ -461,12 +453,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) if (NILP (string)) break; - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; /* This prevents lwlib from assuming this menu item is really supposed to be empty. */ /* The EMACS_INT cast avoids a warning. @@ -561,8 +549,9 @@ free_frame_menubar (struct frame *f) /* F is the frame the menu is for. X and Y are the frame-relative specified position, relative to the inside upper left corner of the frame F. - FOR_CLICK is nonzero if this menu was invoked for a mouse click. - KEYMAPS is 1 if this menu was specified with keymaps; + Bitfield MENUFLAGS bits are: + MENU_FOR_CLICK is set if this menu was invoked for a mouse click. + MENU_KEYMAPS is set if this menu was specified with keymaps; in that case, we return a list containing the chosen item's value and perhaps also the pane's prefix. TITLE is the specified menu title. @@ -570,7 +559,7 @@ free_frame_menubar (struct frame *f) (We return nil on failure, but the value doesn't actually matter.) */ Lisp_Object -w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, +w32_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error) { int i; @@ -600,12 +589,8 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, /* Create a tree of widget_value objects representing the panes and their items. */ - wv = xmalloc_widget_value (); - wv->name = "menu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; first_pane = 1; @@ -663,20 +648,16 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, /* If the pane has a meaningful name, make the pane a top-level menu item with its items as a submenu beneath it. */ - if (!keymaps && strcmp (pane_string, "")) + if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = pane_string; - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -717,19 +698,17 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); } - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* Use the contents index as call_data, since we are restricted to 16-bits. */ wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -742,11 +721,6 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, wv->selected = !NILP (selected); - if (!STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -756,25 +730,21 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, /* Deal with the title, if it is non-nil. */ if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil); /* Maybe replace this separator with a bitmap or owner-draw item so that it looks better. Having two separators looks odd. */ - wv_sep->name = "--"; wv_sep->next = first_wv->contents; - wv_sep->help = Qnil; if (unicode_append_menu) title = ENCODE_UTF_8 (title); else if (STRING_MULTIBYTE (title)) title = ENCODE_SYSTEM (title); - wv_title->name = SSDATA (title); - wv_title->enabled = TRUE; + wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil); wv_title->title = TRUE; wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep; first_wv->contents = wv_title; } @@ -842,10 +812,10 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, i += 1; else { - entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == i) { - if (keymaps != 0) + if (menuflags & MENU_KEYMAPS) { int j; @@ -863,7 +833,7 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps, } } } - else if (!for_click) + else if (!(menuflags & MENU_FOR_CLICK)) { unblock_input (); /* Make "Cancel" equivalent to C-g. */ @@ -904,9 +874,8 @@ static char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -w32_dialog_show (struct frame *f, int keymaps, - Lisp_Object title, Lisp_Object header, - char **error) +w32_dialog_show (struct frame *f, Lisp_Object title, + Lisp_Object header, char **error) { int i, nb_buttons = 0; char dialog_name[6]; @@ -930,19 +899,12 @@ w32_dialog_show (struct frame *f, int keymaps, /* Create a tree of widget_value objects representing the text label and buttons. */ { - Lisp_Object pane_name, prefix; + Lisp_Object pane_name; char *pane_string; pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); - prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - prev_wv = xmalloc_widget_value (); - prev_wv->value = pane_string; - if (keymaps && !NILP (prefix)) - prev_wv->name++; - prev_wv->enabled = 1; - prev_wv->name = "message"; - prev_wv->help = Qnil; + prev_wv = make_widget_value ("message", pane_string, true, Qnil); first_wv = prev_wv; /* Loop over all panes and items, filling in the tree. */ @@ -979,15 +941,13 @@ w32_dialog_show (struct frame *f, int keymaps, return Qnil; } - wv = xmalloc_widget_value (); + wv = make_widget_value (button_names[nb_buttons], + SSDATA (item_name), + !NILP (enable), Qnil); prev_wv->next = wv; - wv->name = (char *) button_names[nb_buttons]; if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = SSDATA (item_name); wv->call_data = aref_addr (menu_items, i); - wv->enabled = !NILP (enable); - wv->help = Qnil; prev_wv = wv; if (! boundary_seen) @@ -1002,9 +962,7 @@ w32_dialog_show (struct frame *f, int keymaps, if (! boundary_seen) left_count = nb_buttons - nb_buttons / 2; - wv = xmalloc_widget_value (); - wv->name = dialog_name; - wv->help = Qnil; + wv = make_widget_value (dialog_name, NULL, false, Qnil); /* Frame title: 'Q' = Question, 'I' = Information. Can also have 'E' = Error if, one day, we want @@ -1052,32 +1010,18 @@ w32_dialog_show (struct frame *f, int keymaps, the proper value. */ if (menu_item_selection != 0) { - Lisp_Object prefix; - - prefix = Qnil; i = 0; while (i < menu_items_used) { Lisp_Object entry; if (EQ (AREF (menu_items, i), Qt)) - { - prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); - i += MENU_ITEMS_PANE_LENGTH; - } + i += MENU_ITEMS_PANE_LENGTH; else { - entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == i) - { - if (keymaps != 0) - { - entry = Fcons (entry, Qnil); - if (!NILP (prefix)) - entry = Fcons (prefix, entry); - } - return entry; - } + return entry; i += MENU_ITEMS_ITEM_LENGTH; } } diff --git a/src/w32notify.c b/src/w32notify.c index 7155f16f3b0..86412b8a974 100644 --- a/src/w32notify.c +++ b/src/w32notify.c @@ -247,7 +247,6 @@ watch_worker (LPVOID arg) do { BOOL status; - DWORD sleep_result; DWORD bytes_ret = 0; if (dirwatch->dir) @@ -275,7 +274,7 @@ watch_worker (LPVOID arg) /* Sleep indefinitely until awoken by the I/O completion, which could be either a change notification or a cancellation of the watch. */ - sleep_result = SleepEx (INFINITE, TRUE); + SleepEx (INFINITE, TRUE); } while (!dirwatch->terminate); return 0; @@ -287,7 +286,6 @@ static struct notification * start_watching (const char *file, HANDLE hdir, BOOL subdirs, DWORD flags) { struct notification *dirwatch = xzalloc (sizeof (struct notification)); - HANDLE thr; dirwatch->signature = DIRWATCH_SIGNATURE; dirwatch->buf = xmalloc (16384); diff --git a/src/w32proc.c b/src/w32proc.c index 96f11657892..426a656f566 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -1772,12 +1772,12 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) if (need_quotes) { int escape_char_run = 0; - char * first; - char * last; + /* char * first; */ + /* char * last; */ p = *targ; - first = p; - last = p + strlen (p) - 1; + /* first = p; */ + /* last = p + strlen (p) - 1; */ *parg++ = '"'; #if 0 /* This version does not escape quotes if they occur at the @@ -2249,10 +2249,9 @@ static BOOL CALLBACK find_child_console (HWND hwnd, LPARAM arg) { child_process * cp = (child_process *) arg; - DWORD thread_id; DWORD process_id; - thread_id = GetWindowThreadProcessId (hwnd, &process_id); + GetWindowThreadProcessId (hwnd, &process_id); if (process_id == cp->procinfo.dwProcessId) { char window_class[32]; diff --git a/src/w32term.c b/src/w32term.c index 2781fb63d62..553764a8de5 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -50,6 +50,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "process.h" #include "atimer.h" #include "keymap.h" +#include "menu.h" #ifdef WINDOWSNT #include "w32.h" /* for filename_from_utf16, filename_from_ansi */ @@ -999,7 +1000,7 @@ x_set_mouse_face_gc (struct glyph_string *s) else face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); s->face = FACE_FROM_ID (s->f, face_id); - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); /* If font in this face is same as S->font, use it. */ if (s->font == s->face->font) @@ -1049,7 +1050,7 @@ x_set_mode_line_face_gc (struct glyph_string *s) static inline void x_set_glyph_string_gc (struct glyph_string *s) { - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); if (s->hl == DRAW_NORMAL_TEXT) { @@ -1078,10 +1079,7 @@ x_set_glyph_string_gc (struct glyph_string *s) s->stippled_p = s->face->stipple != 0; } else - { - s->gc = s->face->gc; - s->stippled_p = s->face->stipple != 0; - } + emacs_abort (); /* GC must have been set. */ eassert (s->gc != 0); @@ -4538,10 +4536,11 @@ w32_read_socket (struct terminal *terminal, Emacs events should reflect only motion after the ButtonPress. */ if (f != 0) - f->mouse_moved = 0; - - if (!tool_bar_p) - last_tool_bar_item = -1; + { + f->mouse_moved = 0; + if (!tool_bar_p) + f->last_tool_bar_item = -1; + } } break; } @@ -4566,9 +4565,9 @@ w32_read_socket (struct terminal *terminal, should reflect only motion after the ButtonPress. */ f->mouse_moved = 0; + f->last_tool_bar_item = -1; } dpyinfo->last_mouse_frame = f; - last_tool_bar_item = -1; } break; @@ -4760,8 +4759,8 @@ w32_read_socket (struct terminal *terminal, width = rect.right - rect.left; text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width); text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height); - rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); - columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); + /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */ + /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */ /* TODO: Clip size to the screen dimensions. */ @@ -5770,27 +5769,8 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b /* Mouse warping. */ -void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); - void -x_set_mouse_position (struct frame *f, int x, int y) -{ - int pix_x, pix_y; - - pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; - pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; - - if (pix_x < 0) pix_x = 0; - if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); - - if (pix_y < 0) pix_y = 0; - if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); - - x_set_mouse_pixel_position (f, pix_x, pix_y); -} - -void -x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) { RECT rect; POINT pt; @@ -5813,7 +5793,9 @@ x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) void x_focus_frame (struct frame *f) { +#if 0 struct w32_display_info *dpyinfo = &one_w32_display_info; +#endif /* Give input focus to frame. */ block_input (); @@ -6273,9 +6255,8 @@ w32_create_terminal (struct w32_display_info *dpyinfo) { struct terminal *terminal; - terminal = create_terminal (); + terminal = create_terminal (output_w32, &w32_redisplay_interface); - terminal->type = output_w32; terminal->display_info.w32 = dpyinfo; dpyinfo->terminal = terminal; @@ -6285,26 +6266,23 @@ w32_create_terminal (struct w32_display_info *dpyinfo) terminal->ins_del_lines_hook = x_ins_del_lines; terminal->delete_glyphs_hook = x_delete_glyphs; terminal->ring_bell_hook = w32_ring_bell; - terminal->reset_terminal_modes_hook = NULL; - terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = x_update_begin; terminal->update_end_hook = x_update_end; - terminal->set_terminal_window_hook = NULL; terminal->read_socket_hook = w32_read_socket; terminal->frame_up_to_date_hook = w32_frame_up_to_date; terminal->mouse_position_hook = w32_mouse_position; terminal->frame_rehighlight_hook = w32_frame_rehighlight; terminal->frame_raise_lower_hook = w32_frame_raise_lower; terminal->fullscreen_hook = w32fullscreen_hook; + terminal->menu_show_hook = w32_menu_show; + terminal->popup_dialog_hook = w32_popup_dialog; terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar; terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars; terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar; terminal->judge_scroll_bars_hook = w32_judge_scroll_bars; - terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = x_delete_terminal; - - terminal->rif = &w32_redisplay_interface; + /* Other hooks are NULL by default. */ /* We don't yet support separate terminals on W32, so don't try to share keyboards between virtual terminals that are on the same physical @@ -6426,12 +6404,6 @@ x_delete_display (struct w32_display_info *dpyinfo) if (dpyinfo->palette) DeleteObject (dpyinfo->palette); } - /* Avoid freeing dpyinfo->w32_id_name more than once if emacs is - running as a daemon; see bug#17510. */ -#ifndef CYGWIN - xfree (dpyinfo->w32_id_name); -#endif - w32_reset_fringes (); } @@ -6483,7 +6455,6 @@ w32_initialize (void) &w32_use_visible_system_caret, 0)) w32_use_visible_system_caret = 0; - last_tool_bar_item = -1; any_help_event_p = 0; /* Initialize input mode: interrupt_input off, no flow control, allow diff --git a/src/w32term.h b/src/w32term.h index e3b65f0ffaf..561a280b65f 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -219,8 +219,6 @@ extern void x_set_window_size (struct frame *f, int change_grav, extern int x_display_pixel_height (struct w32_display_info *); extern int x_display_pixel_width (struct w32_display_info *); extern Lisp_Object x_get_focus_frame (struct frame *); -extern void x_set_mouse_position (struct frame *f, int h, int v); -extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); extern void x_make_frame_visible (struct frame *f); extern void x_make_frame_invisible (struct frame *f); extern void x_iconify_frame (struct frame *f); diff --git a/src/window.c b/src/window.c index 8e8252d3b76..46024614179 100644 --- a/src/window.c +++ b/src/window.c @@ -119,9 +119,6 @@ static Lisp_Object Qtemp_buffer_show_hook; /* Incremented for each window created. */ static int sequence_number; -/* Nonzero after init_window_once has finished. */ -static int window_initialized; - /* Hook to run when window config changes. */ static Lisp_Object Qwindow_configuration_change_hook; @@ -3439,14 +3436,10 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, wset_redisplay (w); w->update_mode_line = true; - /* We must select BUFFER for running the window-scroll-functions. */ - /* We can't check ! NILP (Vwindow_scroll_functions) here - because that might itself be a local variable. */ - if (window_initialized) - { - record_unwind_current_buffer (); - Fset_buffer (buffer); - } + /* We must select BUFFER to run the window-scroll-functions and to look up + the buffer-local value of Vwindow_point_insertion_type. */ + record_unwind_current_buffer (); + Fset_buffer (buffer); XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type); @@ -4874,7 +4867,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) /* If PT is not visible in WINDOW, move back one half of the screen. Allow PT to be partially visible, otherwise something like (scroll-down 1) with PT in the line before - the partially visible one would recenter. */ + the partially visible one would recenter. */ if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos)) { @@ -4903,7 +4896,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) } else if (auto_window_vscroll_p) { - if (rtop || rbot) /* partially visible */ + if (rtop || rbot) /* Partially visible. */ { int px; int dy = frame_line_height; @@ -5650,14 +5643,16 @@ and redisplay normally--don't erase and redraw the frame. */) { struct window *w = XWINDOW (selected_window); struct buffer *buf = XBUFFER (w->contents); - struct buffer *obuf = current_buffer; bool center_p = 0; ptrdiff_t charpos, bytepos; EMACS_INT iarg IF_LINT (= 0); int this_scroll_margin; + if (buf != current_buffer) + error ("`recenter'ing a window that does not display current-buffer."); + /* If redisplay is suppressed due to an error, try again. */ - obuf->display_error_modiff = 0; + buf->display_error_modiff = 0; if (NILP (arg)) { @@ -5679,7 +5674,7 @@ and redisplay normally--don't erase and redraw the frame. */) center_p = 1; } - else if (CONSP (arg)) /* Just C-u. */ + else if (CONSP (arg)) /* Just C-u. */ center_p = 1; else { @@ -5688,12 +5683,10 @@ and redisplay normally--don't erase and redraw the frame. */) iarg = XINT (arg); } - set_buffer_internal (buf); - /* Do this after making BUF current in case scroll_margin is buffer-local. */ - this_scroll_margin = - max (0, min (scroll_margin, w->total_lines / 4)); + this_scroll_margin + = max (0, min (scroll_margin, w->total_lines / 4)); /* Handle centering on a graphical frame specially. Such frames can have variable-height lines and centering point on the basis of @@ -5741,7 +5734,7 @@ and redisplay normally--don't erase and redraw the frame. */) h -= it.current_y; else { - /* Last line has no newline */ + /* Last line has no newline. */ h -= line_bottom_y (&it); it.vpos++; } @@ -5820,10 +5813,9 @@ and redisplay normally--don't erase and redraw the frame. */) w->optional_new_start = 1; - w->start_at_line_beg = (bytepos == BEGV_BYTE || - FETCH_BYTE (bytepos - 1) == '\n'); + w->start_at_line_beg = (bytepos == BEGV_BYTE + || FETCH_BYTE (bytepos - 1) == '\n'); - set_buffer_internal (obuf); return Qnil; } @@ -5960,12 +5952,12 @@ struct save_window_data int frame_menu_bar_height, frame_tool_bar_height; }; -/* This is saved as a Lisp_Vector */ +/* This is saved as a Lisp_Vector. */ struct saved_window { struct vectorlike_header header; - Lisp_Object window, buffer, start, pointm, mark; + Lisp_Object window, buffer, start, pointm; Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; @@ -6267,8 +6259,6 @@ the return value is nil. Otherwise the value is t. */) set_marker_restricted (w->start, p->start, w->contents); set_marker_restricted (w->pointm, p->pointm, w->contents); - Fset_marker (BVAR (XBUFFER (w->contents), mark), - p->mark, w->contents); /* As documented in Fcurrent_window_configuration, don't restore the location of point in the buffer which was @@ -6619,32 +6609,21 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) else p->pointm = Fcopy_marker (w->pointm, Qnil); XMARKER (p->pointm)->insertion_type - = !NILP (buffer_local_value_1 /* Don't signal error if void. */ + = !NILP (buffer_local_value /* Don't signal error if void. */ (Qwindow_point_insertion_type, w->contents)); p->start = Fcopy_marker (w->start, Qnil); p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil; - - tem = BVAR (XBUFFER (w->contents), mark); - p->mark = Fcopy_marker (tem, Qnil); } else { p->pointm = Qnil; p->start = Qnil; - p->mark = Qnil; p->start_at_line_beg = Qnil; } - if (NILP (w->parent)) - p->parent = Qnil; - else - p->parent = XWINDOW (w->parent)->temslot; - - if (NILP (w->prev)) - p->prev = Qnil; - else - p->prev = XWINDOW (w->prev)->temslot; + p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot; + p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot; if (WINDOWP (w->contents)) i = save_window_save (w->contents, vector, i); @@ -6658,8 +6637,8 @@ DEFUN ("current-window-configuration", Fcurrent_window_configuration, doc: /* Return an object representing the current window configuration of FRAME. If FRAME is nil or omitted, use the selected frame. This describes the number of windows, their sizes and current buffers, -and for each displayed buffer, where display starts, and the positions of -point and mark. An exception is made for point in the current buffer: +and for each displayed buffer, where display starts, and the position of +point. An exception is made for point in the current buffer: its value is -not- saved. This also records the currently selected frame, and FRAME's focus redirection (see `redirect-frame-focus'). The variable @@ -7103,8 +7082,7 @@ compare_window_configurations (Lisp_Object configuration1, || !EQ (sw1->min_hscroll, sw2->min_hscroll) || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg) || NILP (Fequal (sw1->start, sw2->start)) - || NILP (Fequal (sw1->pointm, sw2->pointm)) - || NILP (Fequal (sw1->mark, sw2->mark)))) + || NILP (Fequal (sw1->pointm, sw2->pointm)))) || !EQ (sw1->left_margin_cols, sw2->left_margin_cols) || !EQ (sw1->right_margin_cols, sw2->right_margin_cols) || !EQ (sw1->left_fringe_width, sw2->left_fringe_width) @@ -7121,7 +7099,7 @@ compare_window_configurations (Lisp_Object configuration1, DEFUN ("compare-window-configurations", Fcompare_window_configurations, Scompare_window_configurations, 2, 2, 0, doc: /* Compare two window configurations as regards the structure of windows. -This function ignores details such as the values of point and mark +This function ignores details such as the values of point and scrolling positions. */) (Lisp_Object x, Lisp_Object y) { @@ -7138,8 +7116,6 @@ init_window_once (void) Vterminal_frame = selected_frame; minibuf_window = f->minibuffer_window; selected_window = f->selected_window; - - window_initialized = 1; } void diff --git a/src/xdisp.c b/src/xdisp.c index cb92ab7c952..d7368c7c0c4 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10216,19 +10216,17 @@ message_with_string (const char *m, Lisp_Object string, int log) { if (m) { - /* ENCODE_SYSTEM below can GC and/or relocate the Lisp - String whose data pointer might be passed to us in M. So - we use a local copy. */ - char *fmt = xstrdup (m); + /* ENCODE_SYSTEM below can GC and/or relocate the + Lisp data, so make sure we don't use it here. */ + eassert (relocatable_string_data_p (m) != 1); if (noninteractive_need_newline) putc ('\n', stderr); noninteractive_need_newline = 0; - fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string))); + fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string))); if (!cursor_in_echo_area) fprintf (stderr, "\n"); fflush (stderr); - xfree (fmt); } } else if (INTERACTIVE) @@ -11823,11 +11821,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) #ifdef HAVE_WINDOW_SYSTEM -/* Tool-bar item index of the item on which a mouse button was pressed - or -1. */ - -int last_tool_bar_item; - /* Select `frame' temporarily without running all the code in do_switch_frame. FIXME: Maybe do_switch_frame should be trimmed down similarly @@ -12629,7 +12622,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, where the button was pressed, disregarding where it was released. */ if (NILP (Vmouse_highlight) && !down_p) - prop_idx = last_tool_bar_item; + prop_idx = f->last_tool_bar_item; /* If item is disabled, do nothing. */ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); @@ -12641,7 +12634,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, /* Show item in pressed state. */ if (!NILP (Vmouse_highlight)) show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); - last_tool_bar_item = prop_idx; + f->last_tool_bar_item = prop_idx; } else { @@ -12666,7 +12659,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, event.arg = key; event.modifiers = modifiers; kbd_buffer_store_event (&event); - last_tool_bar_item = -1; + f->last_tool_bar_item = -1; } } @@ -12716,8 +12709,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) mouse_down_p = (x_mouse_grabbed (dpyinfo) && f == dpyinfo->last_mouse_frame); - if (mouse_down_p - && last_tool_bar_item != prop_idx) + if (mouse_down_p && f->last_tool_bar_item != prop_idx) return; draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; @@ -15727,9 +15719,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste return rc; } -#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK -static -#endif void set_vertical_scroll_bar (struct window *w) { @@ -22770,7 +22759,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, return decode_mode_spec_buf; no_value: { - char* p = decode_mode_spec_buf; + char *p = decode_mode_spec_buf; int pad = width - 2; while (pad-- > 0) *p++ = ' '; @@ -23518,7 +23507,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)); } - prop = buffer_local_value_1 (prop, it->w->contents); + prop = buffer_local_value (prop, it->w->contents); if (EQ (prop, Qunbound)) prop = Qnil; } @@ -23570,7 +23559,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (pixels); } - car = buffer_local_value_1 (car, it->w->contents); + car = buffer_local_value (car, it->w->contents); if (EQ (car, Qunbound)) car = Qnil; } @@ -23747,7 +23736,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id, #endif { eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); } return face; @@ -23770,7 +23759,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, /* Make sure X resources of the face are allocated. */ eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); if (two_byte_p) *two_byte_p = 0; @@ -24087,7 +24076,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end) s->ybase += voffset; /* The case that face->gc == 0 is handled when drawing the glyph - string by calling PREPARE_FACE_FOR_DISPLAY. */ + string by calling prepare_face_for_display. */ eassert (s->face); return glyph - s->row->glyphs[s->area]; } @@ -24685,13 +24674,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_head = head; j = i; BUILD_GLYPH_STRINGS (j, start, h, t, overlap_hl, dummy_x, last_x); start = i; compute_overhangs_and_x (t, head->x, 1); prepend_glyph_string_lists (&head, &tail, h, t); - clip_head = head; + if (clip_head == NULL) + clip_head = head; } /* Prepend glyph strings for glyphs in front of the first glyph @@ -24712,7 +24704,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_head = head; + if (hl == overlap_hl || clip_head == NULL) + clip_head = head; BUILD_GLYPH_STRINGS (i, start, h, t, overlap_hl, dummy_x, last_x); for (s = h; s; s = s->next) @@ -24736,13 +24729,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_tail = tail; BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); /* Because BUILD_GLYPH_STRINGS updates the first argument, we don't have `end = i;' here. */ compute_overhangs_and_x (h, tail->x + tail->width, 0); append_glyph_string_lists (&head, &tail, h, t); - clip_tail = tail; + if (clip_tail == NULL) + clip_tail = tail; } /* Append glyph strings for glyphs following the last glyph @@ -24760,7 +24756,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_tail = tail; + if (hl == overlap_hl || clip_tail == NULL) + clip_tail = tail; i++; /* We must include the Ith glyph. */ BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); @@ -25028,7 +25025,7 @@ produce_image_glyph (struct it *it) face = FACE_FROM_ID (it->f, it->face_id); eassert (face); /* Make sure X resources of the face is loaded. */ - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->image_id < 0) { @@ -25306,7 +25303,7 @@ produce_stretch_glyph (struct it *it) { struct face *face = FACE_FROM_ID (it->f, it->face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); } #endif @@ -25770,7 +25767,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) face = FACE_FROM_ID (it->f, face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) { @@ -27111,9 +27108,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row, /* Erase the image of a cursor of window W from the screen. */ -#ifndef HAVE_NTGUI -static -#endif void erase_phys_cursor (struct window *w) { @@ -28639,8 +28633,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, else if (area == ON_MODE_LINE) { Lisp_Object default_help - = buffer_local_value_1 (Qmode_line_default_help_echo, - w->contents); + = buffer_local_value (Qmode_line_default_help_echo, + w->contents); if (STRINGP (default_help)) { diff --git a/src/xfaces.c b/src/xfaces.c index 4271e47c36f..4571137a249 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -273,10 +273,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface) -/* Value is the number of elements of VECTOR. */ - -#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR)) - /* Size of hash table of realized faces in face caches (should be a prime number). */ @@ -515,7 +511,7 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0, fputc ('\n', stderr); - for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i) + for (i = n = 0; i < ARRAYELTS (color_count); ++i) if (color_count[i]) { fprintf (stderr, "%3d: %5d", i, color_count[i]); @@ -1252,9 +1248,6 @@ load_color2 (struct frame *f, struct face *face, Lisp_Object name, record that fact in flags of the face so that we don't try to free these colors. */ -#ifndef MSDOS -static -#endif unsigned long load_color (struct frame *f, struct face *face, Lisp_Object name, enum lface_attribute_index target_index) @@ -4105,15 +4098,15 @@ free_realized_face (struct frame *f, struct face *face) } } +#ifdef HAVE_WINDOW_SYSTEM -/* Prepare face FACE for subsequent display on frame F. This - allocated GCs if they haven't been allocated yet or have been freed - by clearing the face cache. */ +/* Prepare face FACE for subsequent display on frame F. This must be called + before using X resources of FACE to allocate GCs if they haven't been + allocated yet or have been freed by clearing the face cache. */ void prepare_face_for_display (struct frame *f, struct face *face) { -#ifdef HAVE_WINDOW_SYSTEM eassert (FRAME_WINDOW_P (f)); if (face->gc == 0) @@ -4141,10 +4134,10 @@ prepare_face_for_display (struct frame *f, struct face *face) font_prepare_for_face (f, face); unblock_input (); } -#endif /* HAVE_WINDOW_SYSTEM */ } - +#endif /* HAVE_WINDOW_SYSTEM */ + /* Returns the `distance' between the colors X and Y. */ static int @@ -5093,14 +5086,14 @@ Value is ORDER. */) { Lisp_Object list; int i; - int indices[DIM (font_sort_order)]; + int indices[ARRAYELTS (font_sort_order)]; CHECK_LIST (order); memset (indices, 0, sizeof indices); i = 0; for (list = order; - CONSP (list) && i < DIM (indices); + CONSP (list) && i < ARRAYELTS (indices); list = XCDR (list), ++i) { Lisp_Object attr = XCAR (list); @@ -5122,9 +5115,9 @@ Value is ORDER. */) indices[i] = xlfd; } - if (!NILP (list) || i != DIM (indices)) + if (!NILP (list) || i != ARRAYELTS (indices)) signal_error ("Invalid font sort order", order); - for (i = 0; i < DIM (font_sort_order); ++i) + for (i = 0; i < ARRAYELTS (font_sort_order); ++i) if (indices[i] == 0) signal_error ("Invalid font sort order", order); @@ -5490,7 +5483,6 @@ realize_non_ascii_face (struct frame *f, Lisp_Object font_object, face = xmalloc (sizeof *face); *face = *base_face; face->gc = 0; - face->extra = NULL; face->overstrike = (! NILP (font_object) && FONT_WEIGHT_NAME_NUMERIC (face->lface[LFACE_WEIGHT_INDEX]) > 100 @@ -6348,7 +6340,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */) int i; fprintf (stderr, "font selection order: "); - for (i = 0; i < DIM (font_sort_order); ++i) + for (i = 0; i < ARRAYELTS (font_sort_order); ++i) fprintf (stderr, "%d ", font_sort_order[i]); fprintf (stderr, "\n"); diff --git a/src/xfns.c b/src/xfns.c index 5dbc7053fd9..dc3211e4d6b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -577,35 +577,6 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) } } -static Cursor -make_invisible_cursor (struct frame *f) -{ - Display *dpy = FRAME_X_DISPLAY (f); - static char const no_data[] = { 0 }; - Pixmap pix; - XColor col; - Cursor c = 0; - - x_catch_errors (dpy); - pix = XCreateBitmapFromData (dpy, FRAME_DISPLAY_INFO (f)->root_window, - no_data, 1, 1); - if (! x_had_errors_p (dpy) && pix != None) - { - Cursor pixc; - col.pixel = 0; - col.red = col.green = col.blue = 0; - col.flags = DoRed | DoGreen | DoBlue; - pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0); - if (! x_had_errors_p (dpy) && pixc != None) - c = pixc; - XFreePixmap (dpy, pix); - } - - x_uncatch_errors (); - - return c; -} - static void x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -723,9 +694,6 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) XDefineCursor (dpy, FRAME_X_WINDOW (f), f->output_data.x->current_cursor = cursor); - if (FRAME_DISPLAY_INFO (f)->invisible_cursor == 0) - FRAME_DISPLAY_INFO (f)->invisible_cursor = make_invisible_cursor (f); - if (cursor != x->text_cursor && x->text_cursor != 0) XFreeCursor (dpy, x->text_cursor); @@ -1641,12 +1609,12 @@ hack_wm_protocols (struct frame *f, Widget widget) #ifdef HAVE_X_I18N static XFontSet xic_create_xfontset (struct frame *); -static XIMStyle best_xim_style (XIMStyles *, XIMStyles *); +static XIMStyle best_xim_style (XIMStyles *); /* Supported XIM styles, ordered by preference. */ -static XIMStyle supported_xim_styles[] = +static const XIMStyle supported_xim_styles[] = { XIMPreeditPosition | XIMStatusArea, XIMPreeditPosition | XIMStatusNothing, @@ -1941,14 +1909,15 @@ xic_free_xfontset (struct frame *f) input method XIM. */ static XIMStyle -best_xim_style (XIMStyles *user, XIMStyles *xim) +best_xim_style (XIMStyles *xim) { int i, j; + int nr_supported = ARRAYELTS (supported_xim_styles); - for (i = 0; i < user->count_styles; ++i) + for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) - if (user->supported_styles[i] == xim->supported_styles[j]) - return user->supported_styles[i]; + if (supported_xim_styles[i] == xim->supported_styles[j]) + return supported_xim_styles[i]; /* Return the default style. */ return XIMPreeditNothing | XIMStatusNothing; @@ -1956,42 +1925,41 @@ best_xim_style (XIMStyles *user, XIMStyles *xim) /* Create XIC for frame F. */ -static XIMStyle xic_style; - void create_frame_xic (struct frame *f) { XIM xim; XIC xic = NULL; XFontSet xfs = NULL; + XVaNestedList status_attr = NULL; + XVaNestedList preedit_attr = NULL; + XRectangle s_area; + XPoint spot; + XIMStyle xic_style; if (FRAME_XIC (f)) - return; + goto out; - /* Create X fontset. */ - xfs = xic_create_xfontset (f); xim = FRAME_X_XIM (f); - if (xim) - { - XRectangle s_area; - XPoint spot; - XVaNestedList preedit_attr; - XVaNestedList status_attr; + if (!xim) + goto out; - s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1; - spot.x = 0; spot.y = 1; + /* Determine XIC style. */ + xic_style = best_xim_style (FRAME_X_XIM_STYLES (f)); - /* Determine XIC style. */ - if (xic_style == 0) - { - XIMStyles supported_list; - supported_list.count_styles = (sizeof supported_xim_styles - / sizeof supported_xim_styles[0]); - supported_list.supported_styles = supported_xim_styles; - xic_style = best_xim_style (&supported_list, - FRAME_X_XIM_STYLES (f)); - } + /* Create X fontset. */ + if (xic_style & (XIMPreeditPosition | XIMStatusArea)) + { + xfs = xic_create_xfontset (f); + if (!xfs) + goto out; + FRAME_XIC_FONTSET (f) = xfs; + } + + if (xic_style & XIMPreeditPosition) + { + spot.x = 0; spot.y = 1; preedit_attr = XVaCreateNestedList (0, XNFontSet, xfs, XNForeground, @@ -2003,31 +1971,75 @@ create_frame_xic (struct frame *f) : NULL), &spot, NULL); + + if (!preedit_attr) + goto out; + } + + if (xic_style & XIMStatusArea) + { + s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1; status_attr = XVaCreateNestedList (0, - XNArea, - &s_area, - XNFontSet, - xfs, - XNForeground, - FRAME_FOREGROUND_PIXEL (f), - XNBackground, - FRAME_BACKGROUND_PIXEL (f), - NULL); - - xic = XCreateIC (xim, - XNInputStyle, xic_style, - XNClientWindow, FRAME_X_WINDOW (f), - XNFocusWindow, FRAME_X_WINDOW (f), - XNStatusAttributes, status_attr, - XNPreeditAttributes, preedit_attr, - NULL); - XFree (preedit_attr); - XFree (status_attr); + XNArea, + &s_area, + XNFontSet, + xfs, + XNForeground, + FRAME_FOREGROUND_PIXEL (f), + XNBackground, + FRAME_BACKGROUND_PIXEL (f), + NULL); + + if (!status_attr) + goto out; } + if (preedit_attr && status_attr) + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + XNStatusAttributes, status_attr, + XNPreeditAttributes, preedit_attr, + NULL); + else if (preedit_attr) + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + XNPreeditAttributes, preedit_attr, + NULL); + else if (status_attr) + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + XNStatusAttributes, status_attr, + NULL); + else + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + NULL); + + if (!xic) + goto out; + FRAME_XIC (f) = xic; FRAME_XIC_STYLE (f) = xic_style; - FRAME_XIC_FONTSET (f) = xfs; + xfs = NULL; /* Don't free below. */ + + out: + + if (xfs) + free_frame_xic (f); + + if (preedit_attr) + XFree (preedit_attr); + + if (status_attr) + XFree (status_attr); } @@ -4538,75 +4550,43 @@ FRAME nil or omitted means use the selected frame. Value is PROP. */) } -DEFUN ("x-window-property", Fx_window_property, Sx_window_property, - 1, 6, 0, - doc: /* Value is the value of window property PROP on FRAME. -If FRAME is nil or omitted, use the selected frame. - -On X Windows, the following optional arguments are also accepted: -If TYPE is nil or omitted, get the property as a string. -Otherwise TYPE is the name of the atom that denotes the type expected. -If SOURCE is non-nil, get the property on that window instead of from -FRAME. The number 0 denotes the root window. -If DELETE-P is non-nil, delete the property after retrieving it. -If VECTOR-RET-P is non-nil, don't return a string but a vector of values. - -On MS Windows, this function accepts but ignores those optional arguments. - -Value is nil if FRAME hasn't a property with name PROP or if PROP has -no value of TYPE (always string in the MS Windows case). */) - (Lisp_Object prop, Lisp_Object frame, Lisp_Object type, - Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p) +static Lisp_Object +x_window_property_intern (struct frame *f, + Window target_window, + Atom prop_atom, + Atom target_type, + Lisp_Object delete_p, + Lisp_Object vector_ret_p, + bool *found) { - struct frame *f = decode_window_system_frame (frame); - Atom prop_atom; - int rc; - Lisp_Object prop_value = Qnil; unsigned char *tmp_data = NULL; + Lisp_Object prop_value = Qnil; Atom actual_type; - Atom target_type = XA_STRING; int actual_format; unsigned long actual_size, bytes_remaining; - Window target_window = FRAME_X_WINDOW (f); + int rc; struct gcpro gcpro1; GCPRO1 (prop_value); - CHECK_STRING (prop); - - if (! NILP (source)) - { - CONS_TO_INTEGER (source, Window, target_window); - if (! target_window) - target_window = FRAME_DISPLAY_INFO (f)->root_window; - } - block_input (); - if (STRINGP (type)) - { - if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) - target_type = AnyPropertyType; - else - target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); - } - - prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, prop_atom, 0, 0, False, target_type, &actual_type, &actual_format, &actual_size, &bytes_remaining, &tmp_data); - if (rc == Success) - { - int size = bytes_remaining; + *found = actual_format != 0; + + if (rc == Success && *found) + { XFree (tmp_data); tmp_data = NULL; rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, - prop_atom, 0, bytes_remaining, - ! NILP (delete_p), target_type, - &actual_type, &actual_format, - &actual_size, &bytes_remaining, - &tmp_data); + prop_atom, 0, bytes_remaining, + ! NILP (delete_p), target_type, + &actual_type, &actual_format, + &actual_size, &bytes_remaining, + &tmp_data); if (rc == Success && tmp_data) { /* The man page for XGetWindowProperty says: @@ -4634,7 +4614,7 @@ no value of TYPE (always string in the MS Windows case). */) } if (NILP (vector_ret_p)) - prop_value = make_string ((char *) tmp_data, size); + prop_value = make_string ((char *) tmp_data, actual_size); else prop_value = x_property_data_to_lisp (f, tmp_data, @@ -4646,6 +4626,80 @@ no value of TYPE (always string in the MS Windows case). */) if (tmp_data) XFree (tmp_data); } + UNGCPRO; + return prop_value; +} + +DEFUN ("x-window-property", Fx_window_property, Sx_window_property, + 1, 6, 0, + doc: /* Value is the value of window property PROP on FRAME. +If FRAME is nil or omitted, use the selected frame. + +On X Windows, the following optional arguments are also accepted: +If TYPE is nil or omitted, get the property as a string. +Otherwise TYPE is the name of the atom that denotes the type expected. +If SOURCE is non-nil, get the property on that window instead of from +FRAME. The number 0 denotes the root window. +If DELETE-P is non-nil, delete the property after retrieving it. +If VECTOR-RET-P is non-nil, don't return a string but a vector of values. + +On MS Windows, this function accepts but ignores those optional arguments. + +Value is nil if FRAME hasn't a property with name PROP or if PROP has +no value of TYPE (always string in the MS Windows case). */) + (Lisp_Object prop, Lisp_Object frame, Lisp_Object type, + Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p) +{ + struct frame *f = decode_window_system_frame (frame); + Atom prop_atom; + Lisp_Object prop_value = Qnil; + Atom target_type = XA_STRING; + Window target_window = FRAME_X_WINDOW (f); + struct gcpro gcpro1; + bool found; + + GCPRO1 (prop_value); + CHECK_STRING (prop); + + if (! NILP (source)) + { + CONS_TO_INTEGER (source, Window, target_window); + if (! target_window) + target_window = FRAME_DISPLAY_INFO (f)->root_window; + } + + block_input (); + if (STRINGP (type)) + { + if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) + target_type = AnyPropertyType; + else + target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); + } + + prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); + prop_value = x_window_property_intern (f, + target_window, + prop_atom, + target_type, + delete_p, + vector_ret_p, + &found); + if (NILP (prop_value) + && ! found + && NILP (source) + && target_window != FRAME_OUTER_WINDOW (f)) + { + prop_value = x_window_property_intern (f, + FRAME_OUTER_WINDOW (f), + prop_atom, + target_type, + delete_p, + vector_ret_p, + &found); + } + + unblock_input (); UNGCPRO; return prop_value; diff --git a/src/xfont.c b/src/xfont.c index 525f00031c5..f90904a018e 100644 --- a/src/xfont.c +++ b/src/xfont.c @@ -121,7 +121,7 @@ static Lisp_Object xfont_match (struct frame *, Lisp_Object); static Lisp_Object xfont_list_family (struct frame *); static Lisp_Object xfont_open (struct frame *, Lisp_Object, int); static void xfont_close (struct font *); -static int xfont_prepare_face (struct frame *, struct face *); +static void xfont_prepare_face (struct frame *, struct face *); static int xfont_has_char (Lisp_Object, int); static unsigned xfont_encode_char (struct font *, int); static int xfont_text_extents (struct font *, unsigned *, int, @@ -916,15 +916,13 @@ xfont_close (struct font *font) } } -static int +static void xfont_prepare_face (struct frame *f, struct face *face) { block_input (); XSetFont (FRAME_X_DISPLAY (f), face->gc, ((struct xfont_info *) face->font)->xfont->fid); unblock_input (); - - return 0; } static int diff --git a/src/xftfont.c b/src/xftfont.c index 18c180f906a..421eb713a15 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -507,7 +507,7 @@ xftfont_close (struct font *font) } } -static int +static void xftfont_prepare_face (struct frame *f, struct face *face) { struct xftface_info *xftface_info; @@ -517,17 +517,14 @@ xftfont_prepare_face (struct frame *f, struct face *face) if (face != face->ascii_face) { face->extra = face->ascii_face->extra; - return 0; + return; } #endif - xftface_info = malloc (sizeof *xftface_info); - if (! xftface_info) - return -1; + xftface_info = xmalloc (sizeof *xftface_info); xftfont_get_colors (f, face, face->gc, NULL, &xftface_info->xft_fg, &xftface_info->xft_bg); face->extra = xftface_info; - return 0; } static void @@ -545,7 +542,7 @@ xftfont_done_face (struct frame *f, struct face *face) xftface_info = (struct xftface_info *) face->extra; if (xftface_info) { - free (xftface_info); + xfree (xftface_info); face->extra = NULL; } } diff --git a/src/xgselect.c b/src/xgselect.c index 42fdfed0d34..bf889a90e97 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -53,7 +53,7 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, int have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; - int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; + int gfds_size = ARRAYELTS (gfds_buf); int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; int i, nfds, tmo_in_millisec; bool need_to_dispatch; diff --git a/src/xmenu.c b/src/xmenu.c index 9b1ac540c21..2d41350e737 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -110,11 +110,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ static Lisp_Object Qdebug_on_next_call; -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) -static Lisp_Object xdialog_show (struct frame *, bool, Lisp_Object, Lisp_Object, - const char **); -#endif - /* Flag which when set indicates a dialog or menu has been posted by Xt on behalf of one of the widget sets. */ static int popup_activated_flag; @@ -184,7 +179,7 @@ mouse_position_for_popup (struct frame *f, int *x, int *y) unblock_input (); - /* xmenu_show expects window coordinates, not root window + /* x_menu_show expects window coordinates, not root window coordinates. Translate. */ *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); @@ -213,9 +208,6 @@ x_menu_set_in_use (int in_use) /* Wait for an X event to arrive or for a timer to expire. */ -#ifndef USE_MOTIF -static -#endif void x_menu_wait_for_event (void *data) { @@ -887,12 +879,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Convert menu_items into widget_value trees to display the menu. This cannot evaluate Lisp code. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; submenu_start[i] >= 0; i++) @@ -957,12 +945,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Make a widget-value tree containing just the top level menu bar strings. */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; items = FRAME_MENU_BAR_ITEMS (f); @@ -974,12 +958,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) if (NILP (string)) break; - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; /* This prevents lwlib from assuming this menu item is really supposed to be empty. */ /* The intptr_t cast avoids a warning. @@ -1175,16 +1155,17 @@ free_frame_menubar (struct frame *f) #endif /* USE_X_TOOLKIT || USE_GTK */ -/* xmenu_show actually displays a menu using the panes and items in menu_items +/* x_menu_show actually displays a menu using the panes and items in menu_items and returns the value selected from it. - There are two versions of xmenu_show, one for Xt and one for Xlib. + There are two versions of x_menu_show, one for Xt and one for Xlib. Both assume input is blocked by the caller. */ /* F is the frame the menu is for. X and Y are the frame-relative specified position, relative to the inside upper left corner of the frame F. - FOR_CLICK is true if this menu was invoked for a mouse click. - KEYMAPS is true if this menu was specified with keymaps; + Bitfield MENUFLAGS bits are: + MENU_FOR_CLICK is set if this menu was invoked for a mouse click. + MENU_KEYMAPS is set if this menu was specified with keymaps; in that case, we return a list containing the chosen item's value and perhaps also the pane's prefix. TITLE is the specified menu title. @@ -1450,8 +1431,8 @@ cleanup_widget_value_tree (void *arg) } Lisp_Object -xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, - Lisp_Object title, const char **error_name) +x_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) { int i; widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; @@ -1479,12 +1460,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* Create a tree of widget_value objects representing the panes and their items. */ - wv = xmalloc_widget_value (); - wv->name = "menu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help =Qnil; first_wv = wv; first_pane = 1; @@ -1540,20 +1517,16 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* If the pane has a meaningful name, make the pane a top-level menu item with its items as a submenu beneath it. */ - if (!keymaps && strcmp (pane_string, "")) + if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = (char *) pane_string; - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -1591,20 +1564,18 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, } #endif /* not HAVE_MULTILINGUAL_MENU */ - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* If this item has a null value, make the call_data null so that it won't display a box when the mouse is on it. */ wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -1617,11 +1588,6 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -1631,27 +1597,20 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, /* Deal with the title, if it is non-nil. */ if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep1 = xmalloc_widget_value (); - widget_value *wv_sep2 = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep1 = make_widget_value ("--", NULL, false, Qnil); + widget_value *wv_sep2 = make_widget_value ("--", NULL, false, Qnil); - wv_sep2->name = "--"; wv_sep2->next = first_wv->contents; - wv_sep2->help = Qnil; - - wv_sep1->name = "--"; wv_sep1->next = wv_sep2; - wv_sep1->help = Qnil; #ifndef HAVE_MULTILINGUAL_MENU if (STRING_MULTIBYTE (title)) title = ENCODE_MENU_STRING (title); #endif - wv_title->name = SSDATA (title); - wv_title->enabled = true; + wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil); wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep1; first_wv->contents = wv_title; } @@ -1664,7 +1623,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv); /* Actually create and show the menu until popped down. */ - create_and_show_popup_menu (f, first_wv, x, y, for_click); + create_and_show_popup_menu (f, first_wv, x, y, + menuflags & MENU_FOR_CLICK); unbind_to (specpdl_count, Qnil); @@ -1705,7 +1665,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == aref_addr (menu_items, i)) { - if (keymaps) + if (menuflags & MENU_KEYMAPS) { int j; @@ -1723,7 +1683,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, } } } - else if (!for_click) + else if (!(menuflags & MENU_FOR_CLICK)) { unblock_input (); /* Make "Cancel" equivalent to C-g. */ @@ -1839,11 +1799,8 @@ static const char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -xdialog_show (struct frame *f, - bool keymaps, - Lisp_Object title, - Lisp_Object header, - const char **error_name) +x_dialog_show (struct frame *f, Lisp_Object title, + Lisp_Object header, const char **error_name) { int i, nb_buttons=0; char dialog_name[6]; @@ -1870,19 +1827,12 @@ xdialog_show (struct frame *f, /* Create a tree of widget_value objects representing the text label and buttons. */ { - Lisp_Object pane_name, prefix; + Lisp_Object pane_name; const char *pane_string; pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); - prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - prev_wv = xmalloc_widget_value (); - prev_wv->value = (char *) pane_string; - if (keymaps && !NILP (prefix)) - prev_wv->name++; - prev_wv->enabled = 1; - prev_wv->name = "message"; - prev_wv->help = Qnil; + prev_wv = make_widget_value ("message", (char *) pane_string, true, Qnil); first_wv = prev_wv; /* Loop over all panes and items, filling in the tree. */ @@ -1918,15 +1868,13 @@ xdialog_show (struct frame *f, return Qnil; } - wv = xmalloc_widget_value (); + wv = make_widget_value (button_names[nb_buttons], + SSDATA (item_name), + !NILP (enable), Qnil); prev_wv->next = wv; - wv->name = (char *) button_names[nb_buttons]; if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = SSDATA (item_name); wv->call_data = aref_addr (menu_items, i); - wv->enabled = !NILP (enable); - wv->help = Qnil; prev_wv = wv; if (! boundary_seen) @@ -1941,9 +1889,7 @@ xdialog_show (struct frame *f, if (! boundary_seen) left_count = nb_buttons - nb_buttons / 2; - wv = xmalloc_widget_value (); - wv->name = dialog_name; - wv->help = Qnil; + wv = make_widget_value (dialog_name, NULL, false, Qnil); /* Frame title: 'Q' = Question, 'I' = Information. Can also have 'E' = Error if, one day, we want @@ -1982,20 +1928,13 @@ xdialog_show (struct frame *f, the proper value. */ if (menu_item_selection != 0) { - Lisp_Object prefix; - - prefix = Qnil; i = 0; while (i < menu_items_used) { Lisp_Object entry; if (EQ (AREF (menu_items, i), Qt)) - { - prefix - = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); - i += MENU_ITEMS_PANE_LENGTH; - } + i += MENU_ITEMS_PANE_LENGTH; else if (EQ (AREF (menu_items, i), Qquote)) { /* This is the boundary between left-side elts and @@ -2007,15 +1946,7 @@ xdialog_show (struct frame *f, entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == aref_addr (menu_items, i)) - { - if (keymaps != 0) - { - entry = list1 (entry); - if (!NILP (prefix)) - entry = Fcons (prefix, entry); - } - return entry; - } + return entry; i += MENU_ITEMS_ITEM_LENGTH; } } @@ -2052,7 +1983,7 @@ xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) /* Display them in a dialog box. */ block_input (); - selection = xdialog_show (f, 0, title, header, &error_name); + selection = x_dialog_show (f, title, header, &error_name); unblock_input (); unbind_to (specpdl_count, Qnil); @@ -2090,7 +2021,7 @@ menu_help_callback (char const *help_string, int pane, int item) if (EQ (first_item[0], Qt)) pane_name = first_item[MENU_ITEMS_PANE_NAME]; else if (EQ (first_item[0], Qquote)) - /* This shouldn't happen, see xmenu_show. */ + /* This shouldn't happen, see x_menu_show. */ pane_name = empty_unibyte_string; else pane_name = first_item[MENU_ITEMS_ITEM_NAME]; @@ -2132,8 +2063,8 @@ pop_down_menu (Lisp_Object arg) Lisp_Object -xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, - Lisp_Object title, const char **error_name) +x_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) { Window root; XMenu *menu; @@ -2208,7 +2139,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); - if (keymaps && !NILP (prefix)) + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) pane_string++; lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, TRUE); @@ -2331,7 +2262,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, if (ulx < 0) x -= ulx; if (uly < 0) y -= uly; - if (! for_click) + if (!(menuflags & MENU_FOR_CLICK)) { /* If position was not given by a mouse click, adjust so upper left corner of the menu as a whole ends up at given coordinates. This @@ -2385,7 +2316,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, { entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); - if (keymaps) + if (menuflags & MENU_KEYMAPS) { entry = list1 (entry); if (!NILP (pane_prefix)) @@ -2407,7 +2338,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, case XM_NO_SELECT: /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means the menu was invoked with a mouse event as POSITION). */ - if (! for_click) + if (!(menuflags & MENU_FOR_CLICK)) { unblock_input (); Fsignal (Qquit, Qnil); diff --git a/src/xsmfns.c b/src/xsmfns.c index 9a31f518f30..81b012690f9 100644 --- a/src/xsmfns.c +++ b/src/xsmfns.c @@ -395,7 +395,7 @@ x_session_initialize (struct x_display_info *dpyinfo) { #define SM_ERRORSTRING_LEN 512 char errorstring[SM_ERRORSTRING_LEN]; - char* previous_id = NULL; + char *previous_id = NULL; SmcCallbacks callbacks; ptrdiff_t name_len = 0; diff --git a/src/xterm.c b/src/xterm.c index ed98fb10b89..b6728880f5d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -32,6 +32,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "xterm.h" #include <X11/cursorfont.h> +/* If we have Xfixes extension, use it for pointer blanking. */ +#ifdef HAVE_XFIXES +#include <X11/extensions/Xfixes.h> +#endif + /* Load sys/types.h if not already loaded. In some systems loading it twice is suicidal. */ #ifndef makedev @@ -70,6 +75,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "xsettings.h" #include "xgselect.h" #include "sysselect.h" +#include "menu.h" #ifdef USE_X_TOOLKIT #include <X11/Shell.h> @@ -308,7 +314,7 @@ int event_record_index; void record_event (char *locus, int type) { - if (event_record_index == sizeof (event_record) / sizeof (struct record)) + if (event_record_index == ARRAYELTS (event_record)) event_record_index = 0; event_record[event_record_index].locus = locus; @@ -897,7 +903,7 @@ x_set_mouse_face_gc (struct glyph_string *s) else face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); s->face = FACE_FROM_ID (s->f, face_id); - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); if (s->font == s->face->font) s->gc = s->face->gc; @@ -945,7 +951,7 @@ x_set_mode_line_face_gc (struct glyph_string *s) static void x_set_glyph_string_gc (struct glyph_string *s) { - PREPARE_FACE_FOR_DISPLAY (s->f, s->face); + prepare_face_for_display (s->f, s->face); if (s->hl == DRAW_NORMAL_TEXT) { @@ -974,10 +980,7 @@ x_set_glyph_string_gc (struct glyph_string *s) s->stippled_p = s->face->stipple != 0; } else - { - s->gc = s->face->gc; - s->stippled_p = s->face->stipple != 0; - } + emacs_abort (); /* GC must have been set. */ eassert (s->gc != 0); @@ -3105,16 +3108,7 @@ static void XTtoggle_invisible_pointer (struct frame *f, int invisible) { block_input (); - if (invisible) - { - if (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0) - XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->invisible_cursor); - } - else - XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - f->output_data.x->current_cursor); - f->pointer_invisible = invisible; + FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible); unblock_input (); } @@ -5630,7 +5624,7 @@ static int temp_index; static short temp_buffer[100]; #define STORE_KEYSYM_FOR_DEBUG(keysym) \ - if (temp_index == sizeof temp_buffer / sizeof (short)) \ + if (temp_index == ARRAYELTS (temp_buffer)) \ temp_index = 0; \ temp_buffer[temp_index++] = (keysym) @@ -6815,9 +6809,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, { dpyinfo->grabbed |= (1 << event->xbutton.button); dpyinfo->last_mouse_frame = f; - - if (!tool_bar_p) - last_tool_bar_item = -1; +#if ! defined (USE_GTK) + if (f && !tool_bar_p) + f->last_tool_bar_item = -1; +#endif /* not USE_GTK */ } else dpyinfo->grabbed &= ~(1 << event->xbutton.button); @@ -7360,9 +7355,13 @@ x_bitmap_icon (struct frame *f, Lisp_Object file) #ifdef USE_GTK - if (xg_set_icon (f, xg_default_icon_file) - || xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) - return 0; + if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id == -2 + || xg_set_icon (f, xg_default_icon_file) + || xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + { + FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2; + return 0; + } #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) @@ -8741,34 +8740,11 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b unblock_input (); } - -/* Mouse warping. */ - -void -x_set_mouse_position (struct frame *f, int x, int y) -{ - int pix_x, pix_y; - - pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; - pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; - - if (pix_x < 0) pix_x = 0; - if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); - - if (pix_y < 0) pix_y = 0; - if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); - - block_input (); - - XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f), - 0, 0, 0, 0, pix_x, pix_y); - unblock_input (); -} /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */ void -x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) { block_input (); @@ -9239,6 +9215,11 @@ x_free_frame_resources (struct frame *f) commands to the X server. */ if (dpyinfo->display) { + /* Always exit with visible pointer to avoid weird issue + with Xfixes (Bug#17609). */ + if (f->pointer_invisible) + FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, 0); + /* We must free faces before destroying windows because some font-driver (e.g. xft) access a window while finishing a face. */ @@ -9722,6 +9703,96 @@ my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, } #endif +/* Create invisible cursor on X display referred by DPYINFO. */ + +static Cursor +make_invisible_cursor (struct x_display_info *dpyinfo) +{ + Display *dpy = dpyinfo->display; + static char const no_data[] = { 0 }; + Pixmap pix; + XColor col; + Cursor c = 0; + + x_catch_errors (dpy); + pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1); + if (! x_had_errors_p (dpy) && pix != None) + { + Cursor pixc; + col.pixel = 0; + col.red = col.green = col.blue = 0; + col.flags = DoRed | DoGreen | DoBlue; + pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0); + if (! x_had_errors_p (dpy) && pixc != None) + c = pixc; + XFreePixmap (dpy, pix); + } + + x_uncatch_errors (); + + return c; +} + +/* True if DPY supports Xfixes extension >= 4. */ + +static bool +x_probe_xfixes_extension (Display *dpy) +{ +#ifdef HAVE_XFIXES + int major, minor; + return XFixesQueryVersion (dpy, &major, &minor) && major >= 4; +#else + return false; +#endif /* HAVE_XFIXES */ +} + +/* Toggle mouse pointer visibility on frame F by using Xfixes functions. */ + +static void +xfixes_toggle_visible_pointer (struct frame *f, bool invisible) +{ +#ifdef HAVE_XFIXES + if (invisible) + XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + else + XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + f->pointer_invisible = invisible; +#else + emacs_abort (); +#endif /* HAVE_XFIXES */ +} + +/* Toggle mouse pointer visibility on frame F by using invisible cursor. */ + +static void +x_toggle_visible_pointer (struct frame *f, bool invisible) +{ + eassert (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0); + if (invisible) + XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->invisible_cursor); + else + XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + f->output_data.x->current_cursor); + f->pointer_invisible = invisible; +} + +/* Setup pointer blanking, prefer Xfixes if available. */ + +static void +x_setup_pointer_blanking (struct x_display_info *dpyinfo) +{ + /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting + X server bug, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */ + if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo->display)) + dpyinfo->toggle_visible_pointer = xfixes_toggle_visible_pointer; + else + { + dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer; + dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); + } +} + /* Current X display connection identifier. Incremented for each next connection established. */ static unsigned x_display_id; @@ -10112,7 +10183,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) }; int i; - const int atom_count = sizeof (atom_refs) / sizeof (atom_refs[0]); + const int atom_count = ARRAYELTS (atom_refs); /* 1 for _XSETTINGS_SN */ const int total_atom_count = 1 + atom_count; Atom *atoms_return = xmalloc (total_atom_count * sizeof *atoms_return); @@ -10150,6 +10221,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) gray_bits, gray_width, gray_height, 1, 0, 1); + x_setup_pointer_blanking (dpyinfo); + #ifdef HAVE_X_I18N xim_initialize (dpyinfo, resource_name); #endif @@ -10171,6 +10244,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #ifdef USE_LUCID { + XFontStruct *xfont = NULL; XrmValue d, fr, to; Font font; @@ -10184,8 +10258,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) x_catch_errors (dpy); if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL)) emacs_abort (); - if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) + if (x_had_errors_p (dpy) || !((xfont = XQueryFont (dpy, font)))) XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); + if (xfont) + XFreeFont (dpy, xfont); x_uncatch_errors (); } #endif @@ -10439,9 +10515,8 @@ x_create_terminal (struct x_display_info *dpyinfo) { struct terminal *terminal; - terminal = create_terminal (); + terminal = create_terminal (output_x_window, &x_redisplay_interface); - terminal->type = output_x_window; terminal->display_info.x = dpyinfo; dpyinfo->terminal = terminal; @@ -10452,26 +10527,25 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->delete_glyphs_hook = x_delete_glyphs; terminal->ring_bell_hook = XTring_bell; terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer; - terminal->reset_terminal_modes_hook = NULL; - terminal->set_terminal_modes_hook = NULL; terminal->update_begin_hook = x_update_begin; terminal->update_end_hook = x_update_end; - terminal->set_terminal_window_hook = NULL; terminal->read_socket_hook = XTread_socket; terminal->frame_up_to_date_hook = XTframe_up_to_date; terminal->mouse_position_hook = XTmouse_position; terminal->frame_rehighlight_hook = XTframe_rehighlight; terminal->frame_raise_lower_hook = XTframe_raise_lower; terminal->fullscreen_hook = XTfullscreen_hook; + terminal->menu_show_hook = x_menu_show; +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) + terminal->popup_dialog_hook = xw_popup_dialog; +#endif terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars; terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar; terminal->judge_scroll_bars_hook = XTjudge_scroll_bars; - terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = x_delete_terminal; - - terminal->rif = &x_redisplay_interface; + /* Other hooks are NULL by default. */ return terminal; } @@ -10482,7 +10556,6 @@ x_initialize (void) baud_rate = 19200; x_noop_count = 0; - last_tool_bar_item = -1; any_help_event_p = 0; ignore_next_mouse_click_timeout = 0; diff --git a/src/xterm.h b/src/xterm.h index 50df88cb592..9daa478c964 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -47,7 +47,6 @@ typedef Widget xt_or_gtk_widget; /* Some definitions to reduce conditionals. */ typedef GtkWidget *xt_or_gtk_widget; -#define XtParent(x) (gtk_widget_get_parent (x)) #undef XSync #define XSync(d, b) do { gdk_window_process_all_updates (); \ XSync (d, b); } while (false) @@ -174,9 +173,13 @@ struct x_display_info /* The cursor to use for vertical scroll bars. */ Cursor vertical_scroll_bar_cursor; - /* The invisible cursor used for pointer blanking. */ + /* The invisible cursor used for pointer blanking. + Unused if this display supports Xfixes extension. */ Cursor invisible_cursor; + /* Function used to toggle pointer visibility on this display. */ + void (*toggle_visible_pointer) (struct frame *, bool); + #ifdef USE_GTK /* The GDK cursor for scroll bars and popup menus. */ GdkCursor *xg_cursor; @@ -927,8 +930,6 @@ extern bool x_had_errors_p (Display *); extern void x_uncatch_errors (void); extern void x_clear_errors (Display *); extern void x_set_window_size (struct frame *, int, int, int, bool); -extern void x_set_mouse_position (struct frame *, int, int); -extern void x_set_mouse_pixel_position (struct frame *, int, int); extern void xembed_request_focus (struct frame *); extern void x_ewmh_activate_frame (struct frame *); extern void x_delete_terminal (struct terminal *terminal); @@ -996,7 +997,7 @@ extern Lisp_Object x_get_focus_frame (struct frame *); #ifdef USE_GTK extern int xg_set_icon (struct frame *, Lisp_Object); -extern int xg_set_icon_from_xpm_data (struct frame *, const char**); +extern int xg_set_icon_from_xpm_data (struct frame *, const char **); #endif /* USE_GTK */ extern void x_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); @@ -1030,9 +1031,7 @@ extern Lisp_Object xw_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); #if defined USE_GTK || defined USE_MOTIF extern void x_menu_set_in_use (int); #endif -#ifdef USE_MOTIF extern void x_menu_wait_for_event (void *data); -#endif extern int popup_activated (void); extern void initialize_frame_menubar (struct frame *); |