diff options
author | Miles Bader <miles@gnu.org> | 2006-01-16 08:37:27 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 2006-01-16 08:37:27 +0000 |
commit | 41882805d6711e32ac0f066119226d84dbdedc13 (patch) | |
tree | 44f756cef3fbc4de2f229e93613a1a326da7f55d /src | |
parent | 6a2bd1a5019d2130c87ac5cf17f1322bf614b624 (diff) | |
parent | 28f74fdf77eaab2e9daf54e2d5b0b729c5201e4f (diff) | |
download | emacs-41882805d6711e32ac0f066119226d84dbdedc13.tar.gz |
Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-97
Merge from emacs--cvs-trunk--0
Patches applied:
* emacs--cvs-trunk--0 (patch 616-696)
- Add lisp/mh-e/.arch-inventory
- Update from CVS
- Merge from gnus--rel--5.10
- Update from CVS: lisp/smerge-mode.el: Add 'tools' to file keywords.
- lisp/gnus/ChangeLog: Remove duplicate entry
* gnus--rel--5.10 (patch 147-181)
- Update from CVS
- Merge from emacs--cvs-trunk--0
- Update from CVS: lisp/mml.el (mml-preview): Doc fix.
- Update from CVS: texi/message.texi: Fix default values.
- Update from CVS: texi/gnus.texi (RSS): Addition.
Diffstat (limited to 'src')
-rw-r--r-- | src/.gdbinit | 110 | ||||
-rw-r--r-- | src/ChangeLog | 1147 | ||||
-rw-r--r-- | src/Makefile.in | 35 | ||||
-rw-r--r-- | src/alloc.c | 291 | ||||
-rw-r--r-- | src/atimer.c | 2 | ||||
-rw-r--r-- | src/buffer.c | 6 | ||||
-rw-r--r-- | src/bytecode.c | 92 | ||||
-rw-r--r-- | src/callproc.c | 9 | ||||
-rw-r--r-- | src/casetab.c | 5 | ||||
-rw-r--r-- | src/category.c | 6 | ||||
-rw-r--r-- | src/category.h | 5 | ||||
-rw-r--r-- | src/ccl.c | 5 | ||||
-rw-r--r-- | src/ccl.h | 5 | ||||
-rw-r--r-- | src/charset.c | 5 | ||||
-rw-r--r-- | src/charset.h | 5 | ||||
-rw-r--r-- | src/coding.c | 5 | ||||
-rw-r--r-- | src/coding.h | 9 | ||||
-rw-r--r-- | src/commands.h | 12 | ||||
-rw-r--r-- | src/composite.c | 5 | ||||
-rw-r--r-- | src/composite.h | 7 | ||||
-rw-r--r-- | src/data.c | 20 | ||||
-rw-r--r-- | src/dispextern.h | 4 | ||||
-rw-r--r-- | src/doc.c | 11 | ||||
-rw-r--r-- | src/editfns.c | 16 | ||||
-rw-r--r-- | src/emacs.c | 17 | ||||
-rw-r--r-- | src/eval.c | 39 | ||||
-rw-r--r-- | src/fileio.c | 40 | ||||
-rw-r--r-- | src/floatfns.c | 2 | ||||
-rw-r--r-- | src/fns.c | 13 | ||||
-rw-r--r-- | src/fontset.c | 9 | ||||
-rw-r--r-- | src/fontset.h | 7 | ||||
-rw-r--r-- | src/fringe.c | 14 | ||||
-rw-r--r-- | src/gnu.h | 216 | ||||
-rw-r--r-- | src/gtkutil.c | 182 | ||||
-rw-r--r-- | src/gtkutil.h | 2 | ||||
-rw-r--r-- | src/image.c | 106 | ||||
-rw-r--r-- | src/indent.c | 12 | ||||
-rw-r--r-- | src/insdel.c | 30 | ||||
-rw-r--r-- | src/keyboard.c | 41 | ||||
-rw-r--r-- | src/keyboard.h | 1 | ||||
-rw-r--r-- | src/keymap.c | 175 | ||||
-rw-r--r-- | src/lisp.h | 38 | ||||
-rw-r--r-- | src/lread.c | 94 | ||||
-rw-r--r-- | src/m/amdx86-64.h | 27 | ||||
-rw-r--r-- | src/m/gould.h | 2 | ||||
-rw-r--r-- | src/mac.c | 737 | ||||
-rw-r--r-- | src/macfns.c | 121 | ||||
-rw-r--r-- | src/macgui.h | 31 | ||||
-rw-r--r-- | src/macmenu.c | 448 | ||||
-rw-r--r-- | src/macselect.c | 493 | ||||
-rw-r--r-- | src/macterm.c | 1707 | ||||
-rw-r--r-- | src/macterm.h | 17 | ||||
-rw-r--r-- | src/makefile.w32-in | 2 | ||||
-rw-r--r-- | src/minibuf.c | 135 | ||||
-rw-r--r-- | src/print.c | 25 | ||||
-rw-r--r-- | src/process.c | 236 | ||||
-rw-r--r-- | src/puresize.h | 2 | ||||
-rw-r--r-- | src/s/darwin.h | 8 | ||||
-rw-r--r-- | src/search.c | 4 | ||||
-rw-r--r-- | src/sheap.c | 8 | ||||
-rw-r--r-- | src/syntax.c | 4 | ||||
-rw-r--r-- | src/term.c | 16 | ||||
-rw-r--r-- | src/termhooks.h | 26 | ||||
-rw-r--r-- | src/textprop.c | 6 | ||||
-rw-r--r-- | src/undo.c | 22 | ||||
-rw-r--r-- | src/unexelf.c | 27 | ||||
-rw-r--r-- | src/unexmacosx.c | 68 | ||||
-rw-r--r-- | src/w32fns.c | 30 | ||||
-rw-r--r-- | src/w32menu.c | 3 | ||||
-rw-r--r-- | src/w32term.c | 4 | ||||
-rw-r--r-- | src/window.c | 359 | ||||
-rw-r--r-- | src/window.h | 3 | ||||
-rw-r--r-- | src/xdisp.c | 126 | ||||
-rw-r--r-- | src/xfaces.c | 84 | ||||
-rw-r--r-- | src/xfns.c | 94 | ||||
-rw-r--r-- | src/xmenu.c | 23 | ||||
-rw-r--r-- | src/xselect.c | 4 | ||||
-rw-r--r-- | src/xterm.c | 65 | ||||
-rw-r--r-- | src/xterm.h | 1 |
79 files changed, 5850 insertions, 1973 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 95ea18f7136..6573b86f5da 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -1,4 +1,4 @@ -# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998, 2000, 01, 2004 +# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998, 2000, 01, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is part of GNU Emacs. @@ -31,6 +31,9 @@ dir ../lwlib # However, C-z works just as well in that case. handle 2 noprint pass +# Make it work like SIGINT normally does. +handle SIGTSTP nopass + # Don't pass SIGALRM to Emacs. This makes problems when # debugging. handle SIGALRM ignore @@ -66,13 +69,53 @@ end # Print out s-expressions define pp set $tmp = $arg0 - set debug_print ($tmp) + set safe_debug_print ($tmp) end document pp Print the argument as an emacs s-expression Works only when an inferior emacs is executing. end +# Print out s-expressions from tool bar +define pp1 + set $tmp = $arg0 + echo $arg0 + printf " = " + set safe_debug_print ($tmp) +end +document pp1 +Print the argument as an emacs s-expression +Works only when an inferior emacs is executing. +For use on tool bar when debugging in Emacs +where the variable name would not otherwise +be recorded in the GUD buffer. +end + +# Print value of lisp variable +define pv + set $tmp = "$arg0" + set safe_debug_print ( find_symbol_value (intern ($tmp))) +end +document pv +Print the value of the lisp variable given as argument. +Works only when an inferior emacs is executing. +end + +# Print value of lisp variable +define pv1 + set $tmp = "$arg0" + echo $arg0 + printf " = " + set safe_debug_print (find_symbol_value (intern ($tmp))) +end +document pv1 +Print the value of the lisp variable given as argument. +Works only when an inferior emacs is executing. +For use on tool bar when debugging in Emacs +where the variable name would not otherwise +be recorded in the GUD buffer. +end + # Print out current buffer point and boundaries define ppt set $b = current_buffer @@ -122,7 +165,7 @@ define pitx printf " HL" end if ($it->n_overlay_strings > 0) - printf " nov=%d" + printf " nov=%d", $it->n_overlay_strings end if ($it->sp != 0) printf " sp=%d", $it->sp @@ -585,7 +628,7 @@ Print the contents of $, assuming it is an Emacs Lisp cons. end define nextcons - p $.cdr + p $.u.cdr xcons end document nextcons @@ -605,7 +648,7 @@ end define xcdr xgetptr $ xgettype $ - print/x ($type == Lisp_Cons ? ((struct Lisp_Cons *) $ptr)->cdr : 0) + print/x ($type == Lisp_Cons ? ((struct Lisp_Cons *) $ptr)->u.cdr : 0) end document xcdr Print the cdr of $, assuming it is an Emacs Lisp pair. @@ -613,7 +656,7 @@ end define xfloat xgetptr $ - print ((struct Lisp_Float *) $ptr)->data + print ((struct Lisp_Float *) $ptr)->u.data end document xfloat Print $ assuming it is a lisp floating-point number. @@ -695,6 +738,16 @@ document xbacktrace an error was signaled. end +# Show Lisp backtrace after normal backtrace. +define hookpost-backtrace + set $bt = backtrace_list + if $bt + echo \n + echo Lisp Backtrace:\n + xbacktrace + end +end + define xreload set $tagmask = (((long)1 << gdb_gctypebits) - 1) set $valmask = gdb_use_lsb ? ~($tagmask) : ((long)1 << gdb_valbits) - 1 @@ -734,13 +787,40 @@ show environment DISPLAY show environment TERM set args -geometry 80x40+0+0 -# Don't let abort actually run, as it will make -# stdio stop working and therefore the `pr' command above as well. -break abort - -# If we are running in synchronous mode, we want a chance to look around -# before Emacs exits. Perhaps we should put the break somewhere else -# instead... -break x_error_quitter - +# People get bothered when they see messages about non-existent functions... +xgetptr Vsystem_type +set $tem = (struct Lisp_Symbol *) $ptr +xgetptr $tem->xname +set $tem = (struct Lisp_String *) $ptr +set $tem = (char *) $tem->data + +# Don't let abort actually run, as it will make stdio stop working and +# therefore the `pr' command above as well. +if $tem[0] == 'w' && $tem[1] == 'i' && $tem[2] == 'n' && $tem[3] == 'd' + # The windows-nt build replaces abort with its own function. + break w32_abort +else + break abort +end + +# x_error_quitter is defined only on X. But window-system is set up +# only at run time, during Emacs startup, so we need to defer setting +# the breakpoint. init_sys_modes is the first function called on +# every platform after init_display, where window-system is set. +tbreak init_sys_modes +commands + silent + xgetptr Vwindow_system + set $tem = (struct Lisp_Symbol *) $ptr + xgetptr $tem->xname + set $tem = (struct Lisp_String *) $ptr + set $tem = (char *) $tem->data + # If we are running in synchronous mode, we want a chance to look + # around before Emacs exits. Perhaps we should put the break + # somewhere else instead... + if $tem[0] == 'x' && $tem[1] == '\0' + break x_error_quitter + end + continue +end # arch-tag: 12f34321-7bfa-4240-b77a-3cd3a1696dfe diff --git a/src/ChangeLog b/src/ChangeLog index 00b66dbd06f..40fbbc94192 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,1124 @@ +2006-01-15 Andreas Schwab <schwab@suse.de> + + * search.c (Freplace_match): Use UPPERCASEP instead of !NOCASEP. + +2006-01-13 Richard M. Stallman <rms@gnu.org> + + * Makefile.in: Define new macro WINDOW_SUPPORT. + (lisp): Use it. + (SOME_MACHINE_LISP): Add conditionally loaded files. + +2006-01-12 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c [USE_ATSUI] (atsu_get_text_layout_with_text_ptr) + [MAC_OS_X_VERSION_MAX_ALLOWED >= 1020]: Specify kATSLineUseQDRendering. + (XLoadQueryFont) [USE_ATSUI]: Display diacritical marks in + decomposed form. + + * process.c [HAVE_INTTYPES_H]: Include inttypes.h. + (ifflag_table): Fix typo (IFF_OACTIV -> IFF_OACTIVE). + (Fnetwork_interface_info): Use HAVE_STRUCT_IFREQ_IFR_NETMASK + macro. Also try member ifr_addr when getting netmask. + +2006-01-10 Stefan Monnier <monnier@iro.umontreal.ca> + + * fileio.c (Fexpand_file_name): Remove redundant tests. + Fix elimination of // so that it doesn't prevent elimination of an + immediately following /. or /.. + +2006-01-09 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * gtkutil.c (xg_toggle_notify_cb): New function. + (xg_toggle_visibility_cb): Move setting of x_gtk_show_hidden_files to + xg_toggle_notify_cb. + (xg_get_file_with_chooser): Add callback to xg_toggle_notify_cb when + parameter value changes so the toggle button gets updated. + +2006-01-06 Nick Roberts <nickrob@snap.net.nz> + + * .gdbinit: Fix typo. + +2006-01-05 Eli Zaretskii <eliz@gnu.org> + + * .gdbinit: Fix last change. + +2006-01-05 Kim F. Storm <storm@cua.dk> + + * process.c (Fmake_network_process): Use AF_INET instead of + AF_UNSPEC when AF_INET6 is not defined. + +2006-01-05 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * mac.c (mac_coerce_file_name_ptr, mac_coerce_file_name_desc): + Don't check that the other type is known file-related one. + + * macfns.c (Fx_server_version): Use gestaltSystemVersionMajor, + gestaltSystemVersionMinor, and gestaltSystemVersionBugFix on Mac + OS X 10.4 and later. + +2006-01-04 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * gtkutil.c (xg_get_image_for_pixmap): If the image is from a file, + let GTK do all image processing. Importing Emacs own pixmaps to GTK + looks bad for inactive tool bar items with some Gnome themes. + +2006-01-04 Eli Zaretskii <eliz@gnu.org> + + * .gdbinit: Avoid a warning message when x_error_quitter is not + compiled in. + + * process.c [WINDOWSNT]: Undef AF_INET6 to disable IPv6 support + for w32. + +2006-01-04 Kim F. Storm <storm@cua.dk> + + * process.c: Add IPv6 support. + (Qipv4, Qipv6): New vars. + (syms_of_process): Intern and staticpro them. + (Fformat_network_address): Handle 9 or 8 element vector as IPv6 address + with or without port number. Handle 4 element vector as IPv4 address + without port number. + (conv_sockaddr_to_lisp, get_lisp_to_sockaddr_size) + (conv_lisp_to_sockaddr): Handle IPv6 addresses. + (Fmake_network_process): Use :family 'ipv4 and 'ipv6 to explicitly + request that address family only. :family nil or omitted means to + determine address family from the specified :host and :service. + (ifflag_table): Add missing OpenBSD IFF_ flags. + (server_accept_connection): Handle IPv6 addresses. + (init_process): Add (:family ipv4) and (:family ipv6) sub-features. + + * .gdbinit: Undo last change. Instead, look at Vsystem_type to + determine which breakpoints to set. + +2006-01-03 Stefan Monnier <monnier@iro.umontreal.ca> + + * keymap.c (describe_map_compare): Yet another int/Lisp_Object mixup. + + * window.h (Fwindow_minibuffer_p): Declare (for use in minibuf.c). + +2006-01-03 Romain Francoise <romain@orebokech.com> + + * emacs.c (main): Update copyright year. + +2006-01-03 Ken Raeburn <raeburn@gnu.org> + + * callproc.c (delete_temp_file): Bind file-name-handler-alist to + nil for the call to internal_delete_file. + +2006-01-01 Ken Raeburn <raeburn@gnu.org> + + * callproc.c (Fcall_process_region): Bind file-name-handler-alist + to nil for the call to Fwrite_region. + +2005-12-31 Richard M. Stallman <rms@gnu.org> + + * minibuf.c (read_minibuf): Clear out all other minibuffer windows. + +2005-12-31 Eli Zaretskii <eliz@gnu.org> + + * emacs.c (gdb_pvec_type): A dummy variable for GDB's sake. + +2005-12-30 Luc Teirlinck <teirllm@auburn.edu> + + * textprop.c (set_text_properties): Reword description of return value. + Return Qnil if caller wants to remove all text properties from a + string and the string already has no intervals. + +2005-12-30 Stefan Monnier <monnier@iro.umontreal.ca> + + * term.c (visible_cursor): New boolean var. + (set_terminal_modes, tty_show_cursor): Use "vs" or "ve" depending on + visible_cursor. + (syms_of_term): Export the new var as "visible-cursor". + +2005-12-30 Eli Zaretskii <eliz@gnu.org> + + * .gdbinit: Tell users not to worry about GDB warnings that some + functions do not exist in the binary. + +2005-12-30 Andreas Schwab <schwab@suse.de> + + * process.c (Fnetwork_interface_info): Correctly terminate the + loop over ifflag_table. + +2005-12-29 Richard M. Stallman <rms@gnu.org> + + * lread.c (readevalloop): Test for reading a whole buffer + before actually reading anything. Handle all cases, including + START = END = nil and an already-narrowed buffer. + Convert END to a marker if it is a number. + + * keymap.c (describe_map): Put sparse map elements into an array, + sort them, then output a sequence of identical bindings on one line. + (struct describe_map_elt): New data type. + (describe_map_compare): New function. + +2005-12-28 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * gtkutil.c (xg_get_file_with_chooser): Change message shown + in file chooser. + +2005-12-27 Richard M. Stallman <rms@gnu.org> + + * lread.c (readevalloop): Set PT and ZV in the proper buffer, + not the current one. + + * minibuf.c (Fminibuffer_message): Doc fix. + (read_minibuf): Set current_buffer->enable_multibyte_characters sooner. + + * eval.c (do_autoload): Ignore elements of Vautoload_queue + where car is not symbol. + +2005-12-27 Kenichi Handa <handa@m17n.org> + + * charset.c (lisp_string_width): Check multibyteness of STRING. + +2005-12-27 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xfns.c: x_show_hidden_files, new variable. + (syms_of_xfns): Defvar it. + + * gtkutil.c (xg_toggle_visibility_cb): New function. + (xg_get_file_with_chooser): Add toggle hidden files and a message + to the new file chooser dialog. Show hidden files if + x_show_hidden_files is non-zero. + +2005-12-26 Richard M. Stallman <rms@gnu.org> + + * keyboard.h: Undo previous change. + + * Makefile.in (undo.o): Undo previous change. + + * undo.c: Undo previous change. + +2005-12-26 Luc Teirlinck <teirllm@auburn.edu> + + * keyboard.h: extern last_point_position_window. + + * undo.c: include keyboard.h. + + * Makefile.in (undo.o): Depend on keyboard.h. + +2005-12-26 Richard M. Stallman <rms@gnu.org> + + * commands.h (last_point_position_window): Declare. + + * undo.c: Depend on window.h. + (record_point): Save old point from the correct window. + + * keyboard.c (last_point_position_window): New variable. + (command_loop_1): Set last_point_position_window. + (syms_of_keyboard): Init it. + + * Makefile.in (undo.o): Depend on window.h. + +2005-12-25 Richard M. Stallman <rms@gnu.org> + + * eval.c (un_autoload): Expect (0 . OFEATURES) in Vautoload_queue + to undo a `provide'. + + * fns.c (Fprovide): Store (0 . OFEATURES) in Vautoload_queue. + +2005-12-25 Giorgos Keramidas <keramida@ceid.upatras.gr> + + * m/amdx86-64.h [__FreeBSD__] (START_FILES, LIB_STANDARD): + define for FreeBSD on this platform. + +2005-12-24 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.h (TYPE_FILE_NAME): New define. + (posix_pathname_to_fsspec, fsspec_to_posix_pathname): Remove externs. + + * mac.c (posix_pathname_to_fsspec, fsspec_to_posix_pathname): + Add prototypes. Make static. + (mac_aedesc_to_lisp): Initialize err to noErr. + (mac_coerce_file_name_ptr, mac_coerce_file_name_desc) + (init_coercion_handler): New functions. + (Fmac_coerce_ae_data): Use coercion of Apple event data for + translation from/to file names. + + * macterm.c: Don't include sys/param.h. + (init_coercion_handler): Add extern. + [MAC_OS8] (main): Call init_coercion_handler. + (mac_initialize) [MAC_OSX]: Likewise. + [TARGET_API_MAC_CARBON] (mac_do_receive_drag): Use coercion of + Apple event data for translation from/to file names. + + * macfns.c [TARGET_API_MAC_CARBON] (Fx_file_dialog): Likewise. + + * image.c [MAC_OS] (find_image_fsspec): Likewise. + +2005-12-23 Martin Rudalics <rudalics@gmx.at> (tiny change) + + * insdel.c (insert, insert_and_inherit, insert_before_markers) + (insert_before_markers_and_inherit): Make sure FROM is correct + when `after-change-functions' are called. + +2005-12-23 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xfns.c (Fx_uses_old_gtk_dialog): New function. + + * gtkutil.c (xg_uses_old_file_dialog): New function. + (xg_get_file_name): Use xg_uses_old_file_dialog. + + * gtkutil.h: Declare xg_uses_old_file_dialog. + +2005-12-22 Richard M. Stallman <rms@gnu.org> + + * xmenu.c (xmenu_show): Call inhibit_garbage_collection. + +2005-12-22 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * mac.c (Fmac_coerce_ae_data) [MAC_OSX]: Fix memory leak. + + * macgui.h (XCharStruct): Remove member `valid_p'. + (STORE_XCHARSTRUCT): Don't set member `valid_p'. + (XCharStructRow): New typedef. + (XCHARSTRUCTROW_CHAR_VALID_P, XCHARSTRUCTROW_SET_CHAR_VALID): + New macros. + (struct MacFontStruct): Add member `bounds'. Remove member + `per_char'. All uses for QuichDraw Text fonts are changed to + `bounds.per_char'. ATSUI font bounds are represented as an array + `bounds.rows' of XCharStructRow's, each of which consists of a + bitmap of valid entries and an array of char bounds. + + * macterm.c (mac_per_char_metric): Add prototype. + (x_per_char_metric) [USE_CG_TEXT_DRAWING]: Remove prototype. + (mac_query_char_extents): New function. + (x_per_char_metric): Use it. + (XLoadQueryFont): Likewise. Consolidate min/max_bounds calculations. + [USE_CG_TEXT_DRAWING] (mac_draw_string_cg): + Use mac_per_char_metric instead of x_per_char_metric. + (mac_text_extents_16): New function. + (mac_compute_glyph_string_overhangs): Use it. + (mac_unload_font): Free member `bounds' in struct MacFontStruct. + +2005-12-21 Stefan Monnier <monnier@iro.umontreal.ca> + + * minibuf.c (Fdisplay_completion_list): Use XCAR/XCDR. + (Fminibuffer_completion_help): Remove duplicates before display. + +2005-12-21 L$,1 q(Brentey K,Aa(Broly <lorentey@elte.hu> + + * print.c (print_preprocess): Don't lose print_depth levels while + iterating. + +2005-12-21 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macmenu.c (Qmac_apple_event): Add extern. + (set_frame_menubar, mac_menu_show keymp_panes) + (single_keymap_panes, list_of_panes, list_of_item) + (single_menu_item): Add argument types to prototypes. + (mac_dialog_show) [HAVE_DIALOGS]: Likewise. + (struct skp): New struct (from xmenu.c). + (single_keymap_panes, single_menu_item, list_of_panes) + (list_of_item): Sync with xmenu.c. + (Fx_popup_menu, Fx_popup_dialog): Likewise. Don't get window from + POSITION if it is mac-apple-event event. + (menubar_selection_callback): Don't use menu_command_in_progress. + (set_frame_menubar): First parse all submenus, then make + widget_value trees from them. Don't allocate any widget_value + objects until we are done with the parsing. + (parse_single_submenu, digest_single_submenu): New functions. + (single_submenu): Function deleted, replaced by those two. + (install_menu_quit_handler) [HAVE_CANCELMENUTRACKING]: Don't + create or dispose of EventHandlerUPP. Install hander to all submenus. + (mac_menu_show) [!HAVE_MULTILINGUAL_MENU]: Use ENCODE_MENU_STRING + instead of ENCODE_SYSTEM. + (free_frame_menubar, fill_submenu, fill_menu): Don't use NULL for + integer values. + [HAVE_DIALOGS] (mac_dialog_show): Sync with xdialog_show (in xmenu.c). + (add_menu_item) [TARGET_API_MAC_CARBON]: Use CFString functions to + format menu item string. Don't use NULL for integer value. + + * macterm.h (struct mac_output): Remove unused member + menu_command_in_progress. + +2005-12-20 Juri Linkov <juri@jurta.org> + + * xmenu.c (Fx_popup_menu): Set Vmenu_updating_frame to f if + position is non-nil, else set it to nil. + + * macmenu.c (Fx_popup_menu): Add `else' to set + Vmenu_updating_frame to nil only if position is nil. + + * w32menu.c (Fx_popup_menu): Add `else' to set + Vmenu_updating_frame to nil only if position is nil. + +2005-12-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * keyboard.c (make_lispy_event): Drag-and-drop items are now + stored in member `args' of struct input_event. + + * termhooks.h (struct input_event): Fix comment for DRAG_N_DROP_EVENT. + + * xselect.c (x_handle_dnd_message): Drag-and-drop items are now + stored in member `args' of struct input_event. + + * w32term.c (construct_drag_n_drop): Likewise. + + * macterm.c (mac_do_receive_drag): Likewise. + (x_use_underline_position_properties): Undo 2005-07-13 change. + (syms_of_macterm) <x-use-underline-position-properties>: Likewise. + (mac_use_core_graphics, mac_wheel_button_is_mouse_2) + (mac_pass_command_to_system, mac_pass_control_to_system): + New boolean variables renamed from Lisp_Object ones + Vmac_use_core_graphics, Vmac_wheel_button_is_mouse_2, + Vmac_pass_command_to_system, and Vmac_pass_control_to_system. + All uses changed. + (syms_of_macterm): DEFVAR_BOOL them. Remove previous DEFVAR_LISPs. + Make them user options. + (mac_handle_command_event, mac_store_services_event): + Call create_apple_event_from_event_ref without 5th argument. + (backtranslate_modified_keycode): Mask off modifier keys that are + mapped to some Emacs modifiers before passing it to KeyTranslate. + (syms_of_macterm): Make variables `mac-emulate-three-button-mouse', + `mac-wheel-button-is-mouse-2', and `mac-*-modifier' user options. + Fix docstrings of `mac-*-modifier'. + + * mac.c (create_apple_event_from_event_ref): Remove arg `types'. + (do_applescript): Change argument types to Lisp_Object. + All uses changed. + + * macterm.h (create_apple_event_from_event_ref): Remove 5th + argument from extern. + +2005-12-18 Dan Nicolaescu <dann@ics.uci.edu> + + * xfns.c (Fx_backspace_delete_keys_p): In case we cannot determine + the answer, return `lambda', not nil. + +2005-12-17 Eli Zaretskii <eliz@gnu.org> + + * makefile.w32-in (bootstrap-temacs): Warn that parts of commands + enclosed in $(ARGQUOTE)s should not be split between two lines, as + that will break with GNU Make >3.80, when sh.exe is used and + arg quoting is with '..'. + +2005-12-17 Chong Yidong <cyd@stupidchicken.com> + + * print.c (print_preprocess): Just signal an error if print_depth + is exceeded. + +2005-12-17 Eli Zaretskii <eliz@gnu.org> + + * .gdbinit: Set a breakpoint on w32_abort. + +2005-12-16 Juri Linkov <juri@jurta.org> + + * minibuf.c (Fminibuffer_completion_contents): New Lisp function + created from minibuffer_completion_contents. + (minibuffer_completion_contents): Remove. + (do_completion, Fminibuffer_complete_word) + (Fminibuffer_completion_help): Replace minibuffer_completion_contents + with Fminibuffer_completion_contents. + (syms_of_minibuf): Add Sminibuffer_completion_contents. + (Fdisplay_completion_list): Doc fix. + (display_completion_list_1): Use `nil' for second arg of + `Fdisplay_completion_list'. + +2005-12-14 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xfns.c (compute_tip_xy): Handle negative dx and dy. + + * w32fns.c (compute_tip_xy): Ditto. + + * macfns.c (compute_tip_xy): Ditto. + +2005-12-14 Chong Yidong <cyd@stupidchicken.com> + + * print.c (print_preprocess): Go to a deeper print_depth to avoid + print_object loop. + +2005-12-14 Kyotaro HORIGUCHI <horiguti@meadowy.org> (tiny change) + + * coding.c (code_convert_region_unwind): GCPRO arg. + +2005-12-12 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xfns.c (compute_tip_xy): Calculate root_y the same way as root_x, + i.e. dy is offset from top of frame instead of bottom. + + * macfns.c (compute_tip_xy): Ditto. + + * w32fns.c (compute_tip_xy): Ditto. + + * gtkutil.c (SSDATA): New macro to remove compiler warnings. + (xg_get_image_for_pixmap, xg_create_frame_widgets) + (xg_get_file_with_chooser): Use SSDATA instead of SDATA. + + * xmenu.c (menubar_selection_callback): Do nothing if the callback + is for an unselected radio menu item. + +2005-12-11 Richard M. Stallman <rms@gnu.org> + + * xdisp.c (syms_of_xdisp) <blink-cursor-alist>: Doc fix. + + * lisp.h [! NO_UNION_TYPE] (EQ): Use == so args are computed just once. + + * keymap.c (Fset_keymap_parent, store_in_keymap): Use CHECK_IMPURE. + (Flookup_key): Doc fix. + (syms_of_keymap) <function-key-map>: Doc fix. + + * fns.c (Frequire): Treat evaluating from a source file + like loading the file. + + * floatfns.c (Flog): Doc fix. + + * fileio.c (Finsert_file_contents): Set Vdeactivate_mark + when we change the buffer. + +2005-12-11 Juri Linkov <juri@jurta.org> + + * minibuf.c (display_completion_list_1): + Call `minibuffer_completion_contents' instead of using `nil' as + second arg of `Fdisplay_completion_list'. + (keys_of_minibuf): Unbind SPC in + Vminibuffer_local_filename_completion_map (see also related + change on 2005-12-06). + +2005-12-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * emacs.c (main) [MAC_OS8]: Undo previous change. + + * macselect.c (syms_of_macselect) <mac-apple-event-map>: + Initialize to nil. Keymap is now created in lisp/term/mac-win.el. + +2005-12-10 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * Makefile.in (macselect.o): Depend on keymap.h. + + * emacs.c (main) [MAC_OS8]: Call syms_of_keymap before + syms_of_macselect. + + * image.c (init_image) [MAC_OS]: Don't call EnterMovies. + [!HAVE_GIF && MAC_OS] (gif_load): Call EnterMovies. + + * keyboard.c (Qmac_apple_event) [MAC_OS]: New variable. + (syms_of_keyboard) [MAC_OS]: Initialize it. + (make_lispy_event) [MAC_OS]: Build lisp event for MAC_APPLE_EVENT. + + * mac.c (Qundecoded_file_name): New variable. + (syms_of_mac): Initialize it. + (mac_aelist_to_lisp, mac_aedesc_to_lisp): New functions. + [TARGET_API_MAC_CARBON] (create_apple_event_from_event_ref): New fun. + (Fmac_coerce_ae_data): New defun. + (syms_of_mac): Defsubr it. + + * macselect.c: Include keymap.h. + (mac_ready_for_apple_events): New variable. + (Vmac_apple_event_map, Qmac_apple_event_class) + (Qmac_apple_event_id): New variables. + (syms_of_macselect): Initialize them. + (Qundefined, mac_store_apple_event): Add externs. + (struct apple_event_binding): New struct. + (find_event_binding_fun, find_event_binding) + (mac_find_apple_event_spec, defer_apple_events) + (mac_handle_apple_event, init_apple_event_handler) + (copy_scrap_flavor_data): New functions. + (Fmac_process_deferred_apple_events): New defun. + (syms_of_macselect): Defsubr it. + (mac_store_services_event): Fix extern. + (mac_handle_service_event): Don't allocate Lisp objects during + asynchronous input processing. Use mac_store_services_event + instead of mac_store_application_menu_event. + + * macterm.c (Qmac_ready_for_drag_n_drop, Qapplication, Qabout) + (Qpreferences): Remove variables. + (syms_of_macterm) : Don't initialize them. + (Qhicommand) [USE_CARBON_EVENTS]: New variable. + (syms_of_macterm) [USE_CARBON_EVENTS]: Initialize it. + (init_required_apple_events, do_ae_open_application) + (do_ae_print_documents, do_ae_open_documents) + (do_ae_quit_application): Remove functions and prototypes. + (mac_ready_for_apple_events, Qundefined, init_apple_event_handler) + (mac_find_apple_event_spec): Add externs. + (mac_store_application_menu_event): Remove function. + (mac_store_apple_event, mac_make_lispy_event_code): New functions. + (mac_handle_command_event): Create Apple event from Carbon event. + Use mac_store_apple_event instead of mac_store_application_menu_event. + [MAC_OSX] (mac_store_services_event): Likewise. + (struct SelectionRange, SelectionRange): Remove struct and typedef. + [MAC_OS8] (main): Call init_apple_event_handler instead of + init_required_apple_events. + (mac_initialize) [MAC_OSX]: Likewise. + [!USE_CARBON_EVENTS] (mac_wait_next_event): + Use mac_ready_for_apple_events instead of Qmac_ready_for_drag_n_drop. + + * macterm.h (mac_make_lispy_event_code, mac_aedesc_to_lisp): + Add externs. + (create_apple_event_from_event_ref) [TARGET_API_MAC_CARBON]: Likewise. + (Fmac_get_preference): Add EXFUN. + + * termhooks.h (enum event_kind) [MAC_OS]: Add new MAC_APPLE_EVENT + event. + +2005-12-09 Richard M. Stallman <rms@gnu.org> + + * xfns.c (Fx_create_frame): Reinstate previous change. + +2005-12-09 Eli Zaretskii <eliz@gnu.org> + + * w32fns.c (w32_abort) [__GNUC__]: Add instructions for attaching + GDB to the abort dialog. + +2005-12-09 Kyotaro HORIGUCHI <horiguti@meadowy.org> (tiny change) + + * indent.c (Fvertical_motion): Force move if starting on + stretch glyph. + +2005-12-08 Richard M. Stallman <rms@gnu.org> + + * lread.c (read_escape) <\s>: Don't treat strings specially. + + * xfns.c (Fx_create_frame): Comment out previous change. + +2005-12-07 L$,1 q(Brentey K,Aa(Broly <lorentey@elte.hu> + + * xfns.c (Fx_create_frame): Initialize Vdefault_minibuffer_frame, + when needed. + +2005-12-06 Stefan Monnier <monnier@iro.umontreal.ca> + + * minibuf.c (keys_of_minibuf): Just unbind SPC in + Vminibuffer_local_filename_completion_map rather than forcing it + explicitly to the same binding as the global map. + +2005-12-06 Ken Raeburn <raeburn@gnu.org> + + * buffer.c (Fkill_buffer): Avoid dangerous side effects in NILP args. + * bytecode.c (Fbyte_code): Likewise. + * fileio.c (internal_delete_file, Fread_file_name_internal): Likewise. + * minibuf.c (Fminibuffer_complete_and_exit): Likewise. + * undo.c (truncate_undo_list): Likewise. + +2005-12-05 Richard M. Stallman <rms@gnu.org> + + * window.c (enlarge_window): Eliminate arg preserve_before. + Assume it is 0. All callers changed. + (Fenlarge_window, Fshrink_window): Likewise. + +2005-12-02 Eli Zaretskii <eliz@gnu.org> + + * w32fns.c (compute_tip_xy): Put tip above pointer if it doesn't + fit below. + +2005-12-02 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xterm.h: Add prototype for xg_set_icon_from_xpm_data. + + * xfns.c (x_real_positions): int ign => unsigned int. + (xg_set_icon_from_xpm_data): Remove unused variable err. + (x_set_name_internal, Fx_create_frame, xg_set_icon): Add cast + to remove compiler warning. + (compute_tip_xy): Put tip above pointer if it doesn't fit below. + +2005-12-02 David Reitter <david.reitter@gmail.com> + + * minibuf.c (Fcompleting_read): If Vminibuffer_completing_file_name is + non-nil, use the new keymaps Vminibuffer_local_filename_completion_map + and Vminibuffer_local_must_match_filename_map keymaps. + (keys_of_minibuf): Bind SPC in the new file-name completion keymaps. + + * keymap.c (Vminibuffer_local_filename_completion_map) + (Vminibuffer_local_must_match_filename_map): New variables. + (syms_of_keymap): DEFVAR_LISP them, initialize them, and set their + parent to be Vminibuffer_local_completion_map and + Vminibuffer_local_must_match_map, respectively. + + * commands.h (Vminibuffer_local_filename_completion_map) + (Vminibuffer_local_must_match_filename_map): Declare the new keymaps. + +2005-12-01 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Fset_window_configuration): Don't accidentally copy the + window-point of one window to another. + +2005-11-30 L$,1 q(Brentey K,Aa(Broly <lorentey@elte.hu> + + * buffer.c (Fpop_to_buffer): Remove superfluous call to record_buffer. + +2005-11-30 Kim F. Storm <storm@cua.dk> + + * alloc.c: Include fcntl.h. Define O_WRONLY if not defined. + (valid_lisp_object_p) [!GC_MARK_STACK]: Validate pointer by + passing it to `emacs_write'. + +2005-11-29 Ari Roponen <arjuropo@cc.jyu.fi> (tiny change) + + * atimer.c (stop_other_atimers): Fix loop to correctly compute `prev'. + +2005-11-27 Richard M. Stallman <rms@gnu.org> + + * window.c (adjust_window_trailing_edge): New function. + (Fadjust_window_trailing_edge): New function. + (syms_of_window): Defsubr it. + (window_deletion_count): New variable. + (delete_window): Update window_deletion_count. + +2005-11-26 Eli Zaretskii <eliz@gnu.org> + + * minibuf.c (syms_of_minibuf): Mention the extension of + `completion-auto-help's meaning by complete.el. + +2005-11-26 Henrik Enberg <henrik.enberg@telia.com> + + * xfaces.c (Finternal_set_lisp_face_attribute_from_resource): + Handle :inherit property as a lisp expression. + +2005-11-24 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c (Qcontrol): Rename from Qctrl. All uses changed. + (syms_of_macterm): Staticpro Qcontrol, Qmeta, Qalt, Qhyper, + Qsuper, and Qmodifier_value. + (Vmac_control_modifier, Vmac_option_modifier) + (Vmac_command_modifier, Vmac_function_modifier) + (Vmac_emulate_three_button_mouse, Vmac_wheel_button_is_mouse_2) + (Vmac_pass_command_to_system, Vmac_pass_control_to_system) + (Vmac_charset_info_alist): Doc fixes. + +2005-11-23 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * emacs.c (main) [MAC_OSX]: Change working directory to home + directory if `-psn_*' option is specified. + + * mac.c (DECODE_UTF_8): Remove macro. + [TARGET_API_MAC_CARBON] (cfstring_to_lisp_nodecode): New function + created from cfstring_to_lisp. + [TARGET_API_MAC_CARBON] (cfstring_to_lisp): Use it. + (xrm_get_preference_database) [TARGET_API_MAC_CARBON]: Likewise. + + * macterm.h (cfstring_to_lisp_nodecode) [TARGET_API_MAC_CARBON]: + Add prototype. + +2005-11-21 Ken Raeburn <raeburn@gnu.org> + + * keymap.c (shadow_lookup): Use make_number to pass a number to + Fsubstring. + +2005-11-21 Juri Linkov <juri@jurta.org> + + * puresize.h (BASE_PURESIZE): Increment to 1180000. + +2005-11-20 Chong Yidong <cyd@stupidchicken.com> + + * xfaces.c (Finternal_set_lisp_face_attribute): + Use :ignore-defface for new frame defaults when `unspecified' is + supplied. + (Finternal_get_lisp_face_attribute): Hide :ignore-defface. + (merge_face_vectors): Don't do :ignore-defface overwriting here. + (Finternal_merge_in_global_face): Do it here. + +2005-11-20 Juri Linkov <juri@jurta.org> + + * charset.c (invalid_character): Use Lisp-readable syntax + for octal and hex. Reorder decimal, octal and hex values. + +2005-11-20 Nick Roberts <nickrob@snap.net.nz> + + * lisp.h: Use typedef when Lisp_Object is EMACS_INT so that + this type is recognised when debugging. + +2005-11-19 Andreas Schwab <schwab@suse.de> + + * .gdbinit (nextcons, xcdr, xfloat): Update for changes in + Lisp_Cons and Lisp_Float. + +2005-11-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c [USE_CG_TEXT_DRAWING] (cg_text_anti_aliasing_threshold): + New variable. + [USE_CG_TEXT_DRAWING] (init_cg_text_anti_aliasing_threshold): New fun. + (init_font_name_table) [USE_ATSUI && USE_CG_TEXT_DRAWING]: Use it. + [USE_CG_TEXT_DRAWING] (mac_draw_string_cg): Don't do antialiasing if + font size is smaller than or equal to cg_text_anti_aliasing_threshold. + +2005-11-17 Chong Yidong <cyd@stupidchicken.com> + + * image.c (x_create_bitmap_from_xpm_data): Free attributes on fail. + + * xfaces.c (Qignore_defface): New variable. + (syms_of_xfaces): Provide `:ignore-defface'. + (IGNORE_DEFFACE_P): New macro. + (check_lface_attrs, lface_fully_specified_p) + (Finternal_set_lisp_face_attribute) + (Fface_attribute_relative_p, Fmerge_face_attribute): + Handle Qignore_defface as a possible value. + (merge_face_vectors): The merged face is `unspecified' if the + mergee specifies `:ignore-defface'. + +2005-11-16 Stefan Monnier <monnier@iro.umontreal.ca> + + * lread.c (readevalloop): Add missing GCPROs. + +2005-11-16 Chong Yidong <cyd@stupidchicken.com> + + * xfns.c (xg_set_icon_from_xpm_data): New function. + + * gnu.h (gnu_xpm_bits): Rename from gnu_bits. + (gnu_xbm_bits): Rename from gnu_bits (xbm version). + + * xterm.c (x_bitmap_icon): Use the xpm if available. + + * image.c (x_create_bitmap_from_xpm_data): New function. + (x_create_bitmap_from_xpm_data): Initialize XpmAttributes. + +2005-11-15 Luc Teirlinck <teirllm@auburn.edu> + + * Makefile.in (lisp, shortlisp): Add rfn-eshadow. + +2005-11-16 Nick Roberts <nickrob@snap.net.nz> + + * .gdbinit: Make SIGTSTP work like SIGINT normally does. + +2005-11-15 Andreas Schwab <schwab@suse.de> + + * lisp.h (struct Lisp_Cons): Make cdr a union. + (XCDR_AS_LVALUE): Adjust. + (struct Lisp_Float): Make data a union. + (XFLOAT_DATA): Adjust. + + * alloc.c (free_float): Make free list chaining aliasing-safe. + (make_float): Likewise. + (free_cons): Likewise. + (Fcons): Likewise. + (check_cons_list): Likewise. + (Fmake_symbol): Likewise. + (allocate_misc): Likewise. + (free_misc): Likewise. + (gc_sweep): Likewise. + +2005-11-15 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * mac.c (HASHKEY_QUERY_CACHE): New define. + (xrm_create_database, xrm_q_put_resource): Empty query cache. + (xrm_get_resource): Use query cache. + + * image.c (init_image) [MAC_OS]: Don't call EnterMovies if + inhibit_window_system is set. + +2005-11-13 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macgui.h (USE_CG_TEXT_DRAWING): New define. + (struct MacFontStruct) [USE_CG_TEXT_DRAWING]: New members cg_font + and cg_glyphs. + + * macterm.c [USE_CG_TEXT_DRAWING] (mac_draw_string_cg): New function. + (x_draw_glyph_string_foreground) [USE_CG_TEXT_DRAWING]: Use it. + (XLoadQueryFont) [USE_CG_TEXT_DRAWING]: Set members cg_font and + cg_glyphs in struct MacFontStruct if synthesized bold or italic is + not used and font substitution never occurs for ASCII and Latin-1 + characters. + (XLoadQueryFont): Maximum and minimum metrics are now those among + ASCII characters. + (XLoadQueryFont) [!MAC_OS8 || USE_ATSUI]: Apply WebKit-style + height adjustments for Courier, Helvetica, and Times. + + * s/darwin.h (LIBS_CARBON) [!HAVE_CARBON]: Remove `-framework Carbon'. + +2005-11-11 David Reitter <david.reitter@gmail.com> + + * macterm.c (syms_of_macterm): Remove macCtrlKey, macShiftKey, + macMetaKey, macAltKey. Introduce Qctrl, Qmeta, + Vmac_control_modifier / mac-control-modifier, + Vmac_option_modifier / mac-option-modifier, + Vmac_command_modifier / mac-command-modifier. + (mac_to_emacs_modifiers): Use the new style modifier + variables. Return UInt32 (modifiers are longs now.) + (backtranslate_modified_keycode): New function (refactoring). + (XTread_socket): Use new modifier variables and refactored function. + (mac_determine_quit_char_modifiers): Remove macMetaKey (there is + no dedicated meta key. Not in use anyway.) + (convert_fn_keycode): Map Fn-keys to their original keycode + using a table (english keyboard only). + +2005-11-11 Kim F. Storm <storm@cua.dk> + + * .gdbinit (pitx): Fix output format if n_overlay_strings > 0. + Add post hook to "backtrace" to always dump lisp call stack to + increase chance of people sending it to us when reporting bugs. + + * doc.c (Fsubstitute_command_keys): Doc fix. + + * dispextern.h (struct it): New member ignore_overlay_strings_at_pos_p. + + * xdisp.c (handle_stop): Skip overlay string handling if + ignore_overlay_strings_at_pos_p is set. + (set_iterator_to_next): At end of display vector, set + ignore_overlay_strings_at_pos_p if dpvec came from an overlay + string, so we skip those overlay strings at current pos. + +2005-11-10 Lars Hansen <larsh@soem.dk> + + * fileio.c (file-regular-p): Doc fix. + +2005-11-10 Kim F. Storm <storm@cua.dk> + + * alloc.c (valid_lisp_object_p): New function to validate that + an object is really a valid Lisp_Object. + + * lisp.h (valid_lisp_object_p): Add prototype. + + * print.c (safe_debug_print): New function to be called from gdb + to print Lisp objects; use valid_lisp_object_p to avoid crashing + if user tries to print something which is not a Lisp object. + + * .gdbinit (pp, pp1): Use safe_debug_print. + (pv, pv1): New commands to print value of a lisp variable. + +2005-11-10 Nick Roberts <nickrob@snap.net.nz> + + * .gdbinit (pp1): New user-defined function. + +2005-11-09 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * image.c [MAC_OSX] (image_load_quartz2d): Fix memory leak. + + * mac.c [MAC_OSX] (init_mac_osx_environment): Reinitialize locale + related variables for dumped executable. + + * unexmacosx.c (unexec_write_zero): New function. + (copy_data_segment): Clear uninitialized local variables in + statically linked libraries. + + * s/darwin.h (C_SWITCH_SYSTEM): Remove -fno-common. + +2005-11-09 Juri Linkov <juri@jurta.org> + + * keymap.c (shadow_lookup): If Flookup_key returns a number, + call it again with a sub-key-sequence, and if its return value + is non-nil (sub-key is bound), return nil. + +2005-11-08 Kim F. Storm <storm@cua.dk> + + * process.c (Fsignal_process): Recognize signal names with and + without SIG prefix, e.g. SIGHUP and HUP. + + * search.c (search_buffer): No need to initialize base_pat. + +2005-11-04 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Fget_lru_window, Fget_largest_window, window_loop): + Don't abuse the `mini' arg. Use the `obj' arg instead. + +2005-11-04 Kim F. Storm <storm@cua.dk> + + * xdisp.c (show_mouse_face): Clear mouse face to eol. + +2005-11-03 Dan Nicolaescu <dann@ics.uci.edu> + + * Makefile.in (lisp, shortlisp): Add emacs-lisp/syntax.elc, + font-lock.elc and jit-lock.elc. + +2005-11-03 Richard M. Stallman <rms@gnu.org> + + * window.c (Fenlarge_window): Rename SIDE to HORIZONTAL. + (enlarge_window): Rename WIDTHFLAG to HORIZ_FLAG. + (CURBEG, CURSIZE): Use HORIZ_FLAG instead of WIDTHFLAG. + + * sheap.c (STATIC_HEAP_SIZE): Increment both definitions. + + * alloc.c (refill_memory_reserve): Move decl out of conditionals. + +2005-11-03 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (Fdisplay_buffer): Fix last change to not use + a dedicated window. + +2005-11-01 Kim F. Storm <storm@cua.dk> + + * fringe.c (update_window_fringes): Undo 2005-10-27 change. + Instead, rotate the bottom angle bitmap 180 degrees to indicate + that the bottom row does not end in a newline. + +2005-11-01 Andreas Schwab <schwab@suse.de> + + * unexelf.c (unexec): Handle .plt section in BSS segment. + +2005-11-01 Stefan Monnier <monnier@iro.umontreal.ca> + + * lread.c (readevalloop): Yet another int/Lisp_Object mixup (YAILOM). + + * window.c (window_loop): For LRU and LARGEST, let the `mini' argument + determine whether to consider dedicated windows as well. + (Fget_lru_window, Fget_largest_window): Add `dedicated' argument. + (Fdisplay_buffer): Do consider dedicated windows in those cases where + we will split the window rather than reuse it. + Don't try to use windows on other displays. + +2005-10-31 Dan Nicolaescu <dann@ics.uci.edu> + + * puresize.h (BASE_PURESIZE): Increment to 1170000. + +2005-10-31 Romain Francoise <romain@orebokech.com> + + * macfns.c: Update copyright year. + * m/gould.h: Likewise. + +2005-10-30 Kim F. Storm <storm@cua.dk> + + * xdisp.c (display_line): Restore it->current_x and call + extend_face_to_end_of_line when last glyph doesn't fit on line. + (set_glyph_string_background_width): Remove specific tests here + to see if face background should extend to end of line. Simplify. + +2005-10-30 Richard M. Stallman <rms@gnu.org> + + * alloc.c (BYTES_USED): Use uordblks, not arena. + (bytes_used_when_reconsidered): New variable. + (emacs_blocked_free): Set that. + +2005-10-29 Chong Yidong <cyd@stupidchicken.com> + + * alloc.c (emacs_blocked_free): Fix typo. + +2005-10-29 Richard M. Stallman <rms@gnu.org> + + * data.c (Fmake_variable_frame_local): Doc fix. + + * xdisp.c (handle_fontified_prop): Do nothing if memory full. + (format_mode_line_unwind_data): New arg SAVE_PROPTRANS + controls whether to save and restore mode_line_proptrans_alist. + Callers changed. + (unwind_format_mode_line): Work with that feature. + (redisplay_internal): Don't call prepare_menu_bars if memory full. + (move_elt_to_front): New function. + (display_mode_element): Use move_elt_to_front. + Don't bother munging text props on a null string. + Delete obsolete elts from mode_line_proptrans_alist. + (decode_mode_spec): Test Vmemory_full, not spare_memory. + (Fformat_mode_line): Clear mode_line_proptrans_alist after saving. + + * lisp.h (memory_full_cons_threshold): Declare. + (internal_lisp_condition_case): Declare. + + * alloc.c (syms_of_alloc) <memory-full>: Doc fix. + (Fmemory_full_p): Function deleted. + (syms_of_alloc): Don't defsubr it. + (memory_full_cons_threshold): New variable. + (spare_memory): Now a vector of 7 elts. + (buffer_memory_full): Don't set Vmemory_full here. + (xfree): Don't try to refill here. + (emacs_blocked_free): Record BYTES_USED in local var. + (memory_full): Now free all the slots in spare_memory. + (refill_memory_reserve): Allocate each slot in spare_memory. + (init_alloc_once): Call refill_memory_reserve. + + * keyboard.c (command_loop_1): Don't set Vmemory_full here. + + * eval.c (internal_lisp_condition_case): New function. + (Fcondition_case): Use internal_lisp_condition_case. + (Feval): Test Vmemory_full and memory_full_cons_threshold. + (Ffuncall): Likewise. + + * bytecode.c (Fbyte_code): Use internal_lisp_condition_case. + +2005-10-29 Stefan Monnier <monnier@iro.umontreal.ca> + + * syntax.c (Fparse_partial_sexp): Fix docstring. + +2005-10-28 Romain Francoise <romain@orebokech.com> + + * puresize.h (BASE_PURESIZE): Increment to 1130000. + +2005-10-28 Richard M. Stallman <rms@gnu.org> + + * xfns.c (syms_of_xfns): Provide `x' as feature. + + * xdisp.c (decode_mode_spec): Define %e to indicate memory full. + + * editfns.c (Fformat): Don't include string padding + between info[n].start and info[n].end. + + * alloc.c (spare_memory): No longer static. + (xfree) [!SYSTEM_MALLOC]: Call refill_memory_reserve. + + * puresize.h (BASE_PURESIZE): Increment to 1120000. + +2005-10-27 Chong Yidong <cyd@stupidchicken.com> + + * data.c (Fmake_variable_frame_local): Add clarification to docstring. + + * fringe.c (update_window_fringes): Handle case where buffer ends + with a newline. + +2005-10-27 Kenichi Handa <handa@m17n.org> + + * coding.h (DECODE_SYSTEM): Fix argument name; name->str. + +2005-10-24 Kenichi Handa <handa@m17n.org> + + * charset.h (charset_mule_unicode_0100_24ff) + (charset_mule_unicode_2500_33ff, charset_mule_unicode_e000_ffff): + Extern them. + + * charset.c (charset_mule_unicode_0100_24ff) + (charset_mule_unicode_2500_33ff, charset_mule_unicode_e000_ffff): + New variables. + (Fsetup_special_charsets): Initialize them. + + * xterm.c (handle_one_xevent): Handle keysyms directly mapped to + supported Unicode characters. + +2005-10-25 Jason Rumney <jasonr@gnu.org> + + * w32fns.c (w32_to_x_font): Avoid forcing font widths. + +2005-10-25 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * image.c [MAC_OS] (image_load_qt_1): Check image size. + Use GraphicsImportGetImageDescription instead of + GraphicsImportGetNaturalBounds. + [MAC_OSX] (image_load_quartz2d): Check image size. + [MAC_OS] (xpm_load_image): Likewise. + + * macterm.c (last_mouse_glyph_frame): New var. + (note_mouse_movement): Say mouse moved if current frame differs + from last_mouse_glyph_frame, and update last_mouse_glyph_frame. + (XTmouse_position): Set last_mouse_glyph_frame. + (XTread_socket): Clear last_mouse_glyph_frame on mouse up/down event. + (mac_draw_string_common) [USE_ATSUI && WORDS_BIG_ENDIAN]: Fix typo. + Use EndianU16_BtoN. + (mac_draw_string_common) [MAC_OSX]: Don't use ATSUClearLayoutControls. + (x_per_char_metric, XLoadQueryFont) + [MAC_OS_X_VERSION_MAX_ALLOWED < 1020]: Use device origins to get + glyph bounds. + (mac_to_x_fontname, mac_do_list_fonts) + (mac_initialize_display_info): Change screen resolutions to 72dpi. + +2005-10-25 Masatake YAMATO <jet@gyve.org> + + * minibuf.c (Fdisplay_completion_list): Small doc fix. + +2005-10-24 Kim F. Storm <storm@cua.dk> + + * xterm.c: Undo 2005-10-23 change. + (last_mouse_glyph_frame): New var. + (note_mouse_movement): Say mouse moved if current frame differs + from last_mouse_glyph_frame, and update last_mouse_glyph_frame. + (XTmouse_position): Set last_mouse_glyph_frame. + (handle_one_xevent): Clear last_mouse_glyph_frame [instead of + last_mouse_glyph] on mouse up/down event. + + * editfns.c (Fcompare_buffer_substrings): Fix last change. + +2005-10-23 Stefan Monnier <monnier@iro.umontreal.ca> + + * editfns.c (Fcompare_buffer_substrings): Handle multibyte chars. + +2005-10-23 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xterm.c (note_mouse_movement): Always call note_mouse_highlight + so tool tips don't interfere with press on tool bar button. + +2005-10-23 Richard M. Stallman <rms@gnu.org> + + * casetab.c (Fset_case_table): Doc fix. + + * lread.c (build_load_history): Replace STREAM arg with ENTIRE. + (readevalloop): Compute ENTIRE properly. + (syms_of_lread) <load-history>: Doc fix. + 2005-10-21 Richard M. Stallman <rms@gnu.org> * lread.c (Fload): Simplify gcpro structure. @@ -8,8 +1129,7 @@ 2005-10-21 Kenichi Handa <handa@m17n.org> - * search.c (boyer_moore): Surround the '||' part of expression in - `if' condition by parentheses explicitly. + * search.c (boyer_moore): Add parens to fix and/or precedence bug. 2005-10-20 Kim F. Storm <storm@cua.dk> @@ -34,8 +1154,7 @@ 2005-10-20 Aubrey Jaffer <agj@alum.mit.edu> (tiny change) - * unexelf.c (unexec): Fix calls to `fatal' with less than 3 - arguments. + * unexelf.c (unexec): Fix calls to `fatal' with less than 3 arguments. 2005-10-20 Olli Savia <ops@iki.fi> (tiny change) @@ -81,7 +1200,7 @@ 2005-10-16 Masatake YAMATO <jet@gyve.org> * minibuf.c (Fdisplay_completion_list): Add new optional - argument COMMON_SUBSTRING. Bind `completion-common-substring' + argument COMMON_SUBSTRING. Bind `completion-common-substring' to the optional argument during running `completion-setup-hook'. 2005-10-16 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> @@ -165,8 +1284,8 @@ * xdisp.c (remember_mouse_glyph): Use MATRIX_BOTTOM_TEXT_ROW to get end of text rows. Obtain header-line/mode-line rows directly. - * xterm.c, w32term.c, macterm.c (note_mouse_movement): Restore - help_echo_string if mouse is moved inside last_mouse_glyph. + * xterm.c, w32term.c, macterm.c (note_mouse_movement): + Restore help_echo_string if mouse is moved inside last_mouse_glyph. 2005-10-12 Kim F. Storm <storm@cua.dk> @@ -231,8 +1350,8 @@ (init_font_name_table) [USE_ATSUI]: Use decode_mac_font_name. Don't use Fdowncase because family name is already lowered by decode_mac_font_name. - (init_font_name_table): Always call decode_mac_font_name. Add - pair of family name and its reference to fm_font_family_alist. + (init_font_name_table): Always call decode_mac_font_name. + Add pair of family name and its reference to fm_font_family_alist. (mac_clear_font_name_table): Clear fm_font_family_alist. (XLoadQueryFont): Move font size parsing part to parse_x_font_name. Lookup fm_font_family_alist to get font family reference. @@ -332,8 +1451,8 @@ (x_fix_overlapping_area): Add new OVERLAPS arg. (get_glyph_string_clip_rects): Add extern. - * dispnew.c (redraw_overlapping_rows): Call - rif->fix_overlapping_area with new OVERLAPS arg as redrawn part. + * dispnew.c (redraw_overlapping_rows): + Call rif->fix_overlapping_area with new OVERLAPS arg as redrawn part. * xdisp.c: Rename member for_overlaps_p in struct glyph_string to for_overlaps. @@ -678,8 +1797,8 @@ * xsmfns.c: (get_current_dir_name): Remove prototype. - * lisp.h: (get_current_dir_name) [!HAVE_GET_CURRENT_DIR_NAME]: Add - prototype. + * lisp.h: (get_current_dir_name) [!HAVE_GET_CURRENT_DIR_NAME]: + Add prototype. * sysdep.c [WINDOWSNT]: Add prototype for getwd. Don't #undef NULL after including blockinput.h. @@ -15801,7 +16920,7 @@ * xdisp.c (forward_to_next_line_start): Return 0 when reaching the end of the buffer. -2002-08-08 Ken Raeburn <raeburn@mit.edu> +2002-08-08 Ken Raeburn <raeburn@gnu.org> * coding.c (Ffind_operation_coding_system): Fix Lisp_Object/int mixup. diff --git a/src/Makefile.in b/src/Makefile.in index 6e8b8a0f0f1..fafd930a972 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -677,6 +677,20 @@ otherobj= $(termcapobj) lastfile.o $(mallocobj) $(allocaobj) $(widgetobj) $(LIBO #define MSDOS_SUPPORT #endif +#ifdef HAVE_WINDOW_SYSTEM +#ifdef HAVE_X_WINDOWS +#define WINDOW_SUPPORT ${lispsource}image.elc \ + ${lispsource}international/fontset.elc ${lispsource}dnd.elc \ + ${lispsource}tool-bar.elc ${lispsource}mwheel.elc ${lispsource}x-dnd.elc +#else +#define WINDOW_SUPPORT ${lispsource}image.elc \ + ${lispsource}international/fontset.elc ${lispsource}dnd.elc \ + ${lispsource}tool-bar.elc ${lispsource}mwheel.elc +#endif +#else +#define WINDOW_SUPPORT +#endif + #ifdef WINDOWSNT #define WINNT_SUPPORT ${lispsource}ls-lisp.elc ${lispsource}disp-table.elc \ ${lispsource}dos-w32.elc ${lispsource}w32-vars.elc \ @@ -726,6 +740,7 @@ lisp= \ ${lispsource}help.elc \ ${lispsource}indent.elc \ ${lispsource}isearch.elc \ + ${lispsource}rfn-eshadow.elc \ ${lispsource}loadup.el \ ${lispsource}loaddefs.el \ ${lispsource}bindings.elc \ @@ -769,6 +784,9 @@ lisp= \ ${lispsource}subr.elc \ ${lispsource}term/tty-colors.elc \ ${lispsource}font-core.elc \ + ${lispsource}emacs-lisp/syntax.elc \ + ${lispsource}font-lock.elc \ + ${lispsource}jit-lock.elc \ ${lispsource}textmodes/fill.elc \ ${lispsource}textmodes/page.elc \ ${lispsource}textmodes/paragraphs.elc \ @@ -781,6 +799,7 @@ lisp= \ VMS_SUPPORT \ MSDOS_SUPPORT \ WINNT_SUPPORT \ + WINDOW_SUPPORT \ ${lispsource}widget.elc \ ${lispsource}window.elc \ ${lispsource}version.el @@ -810,6 +829,7 @@ shortlisp= \ ../lisp/help.elc \ ../lisp/indent.elc \ ../lisp/isearch.elc \ + ../lisp/rfn-eshadow.elc \ ../lisp/loadup.el \ ../lisp/loaddefs.el \ ../lisp/bindings.elc \ @@ -853,6 +873,9 @@ shortlisp= \ ../lisp/subr.elc \ ../lisp/term/tty-colors.elc \ ../lisp/font-core.elc \ + ../lisp/emacs-lisp/syntax.elc \ + ../lisp/font-lock.elc \ + ../lisp/jit-lock.elc \ ../lisp/textmodes/fill.elc \ ../lisp/textmodes/page.elc \ ../lisp/textmodes/paragraphs.elc \ @@ -876,9 +899,13 @@ SOME_MACHINE_LISP = ${dotdot}/lisp/mouse.elc \ ${dotdot}/lisp/ls-lisp.elc ${dotdot}/lisp/dos-fns.elc \ ${dotdot}/lisp/w32-fns.elc ${dotdot}/lisp/dos-w32.elc \ ${dotdot}/lisp/disp-table.elc ${dotdot}/lisp/dos-vars.elc \ - ${dotdot}/lisp/tooltip.elc \ + ${dotdot}/lisp/tooltip.elc ${dotdot}/lisp/image.elc \ + ${dotdot}/lisp/dnd.elc ${dotdot}/lisp/mwheel.elc \ + ${dotdot}/lisp/tool-bar.elc \ + ${dotdot}/lisp/x-dnd.elc \ ${dotdot}/lisp/international/ccl.elc \ - ${dotdot}/lisp/international/codepage.elc + ${dotdot}/lisp/international/codepage.elc \ + ${dotdot}/lisp/international/fontset.elc /* Construct full set of libraries to be linked. Note that SunOS needs -lm to come before -lc; otherwise, you get @@ -1159,7 +1186,7 @@ term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \ termcap.o: termcap.c $(config_h) terminfo.o: terminfo.c $(config_h) tparam.o: tparam.c $(config_h) -undo.o: undo.c buffer.h commands.h $(config_h) +undo.o: undo.c buffer.h commands.h window.h $(config_h) /* This hack is to discard any space that cpp might put at the beginning of UNEXEC when substituting it in. */ UNEXEC_ALIAS=UNEXEC @@ -1251,7 +1278,7 @@ macterm.o: blockinput.h atimer.h systime.h syssignal.h macterm.h macgui.h \ frame.h charset.h ccl.h dispextern.h fontset.h termhooks.h termopts.h \ termchar.h gnu.h disptab.h buffer.h window.h keyboard.h $(INTERVAL_SRC) \ process.h coding.h $(config_h) -macselect.o: blockinput.h macterm.h macgui.h frame.h $(config_h) +macselect.o: blockinput.h macterm.h macgui.h frame.h keymap.h $(config_h) ${emacsapp}Contents/Resources/English.lproj: mkdir -p $@ diff --git a/src/alloc.c b/src/alloc.c index 5d8b1c1a359..1ef8f97b040 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -66,6 +66,14 @@ Boston, MA 02110-1301, USA. */ extern POINTER_TYPE *sbrk (); #endif +#ifdef HAVE_FCNTL_H +#define INCLUDED_FCNTL +#include <fcntl.h> +#endif +#ifndef O_WRONLY +#define O_WRONLY 1 +#endif + #ifdef DOUG_LEA_MALLOC #include <malloc.h> @@ -138,6 +146,8 @@ static pthread_mutex_t alloc_mutex; static __malloc_size_t bytes_used_when_full; +static __malloc_size_t bytes_used_when_reconsidered; + /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer to a struct Lisp_String. */ @@ -182,6 +192,11 @@ EMACS_INT gc_relative_threshold; static Lisp_Object Vgc_cons_percentage; +/* Minimum number of bytes of consing since GC before next GC, + when memory is full. */ + +EMACS_INT memory_full_cons_threshold; + /* Nonzero during GC. */ int gc_in_progress; @@ -213,11 +228,12 @@ static int total_free_conses, total_free_markers, total_free_symbols; static int total_free_floats, total_floats; /* Points to memory space allocated as "spare", to be freed if we run - out of memory. */ + out of memory. We keep one large block, four cons-blocks, and + two string blocks. */ -static char *spare_memory; +char *spare_memory[7]; -/* Amount of spare memory to keep in reserve. */ +/* Amount of spare memory to keep in large reserve block. */ #define SPARE_MEMORY (1 << 14) @@ -350,6 +366,11 @@ enum mem_type MEM_TYPE_WINDOW }; +static POINTER_TYPE *lisp_align_malloc P_ ((size_t, enum mem_type)); +static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); +void refill_memory_reserve (); + + #if GC_MARK_STACK || defined GC_MALLOC_CHECK #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES @@ -450,6 +471,7 @@ static void mem_delete P_ ((struct mem_node *)); static void mem_delete_fixup P_ ((struct mem_node *)); static INLINE struct mem_node *mem_find P_ ((void *)); + #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS static void check_gcpros P_ ((void)); #endif @@ -510,57 +532,10 @@ display_malloc_warning () #ifdef DOUG_LEA_MALLOC -# define BYTES_USED (mallinfo ().arena) +# define BYTES_USED (mallinfo ().uordblks) #else # define BYTES_USED _bytes_used #endif - - -/* Called if malloc returns zero. */ - -void -memory_full () -{ - Vmemory_full = Qt; - -#ifndef SYSTEM_MALLOC - bytes_used_when_full = BYTES_USED; -#endif - - /* The first time we get here, free the spare memory. */ - if (spare_memory) - { - free (spare_memory); - spare_memory = 0; - } - - /* This used to call error, but if we've run out of memory, we could - get infinite recursion trying to build the string. */ - while (1) - Fsignal (Qnil, Vmemory_signal_data); -} - -DEFUN ("memory-full-p", Fmemory_full_p, Smemory_full_p, 0, 0, 0, - doc: /* t if memory is nearly full, nil otherwise. */) - () -{ - return (spare_memory ? Qnil : Qt); -} - -/* If we released our reserve (due to running out of memory), - and we have a fair amount free once again, - try to set aside another reserve in case we run out once more. - - This is called when a relocatable block is freed in ralloc.c. */ - -void -refill_memory_reserve () -{ -#ifndef SYSTEM_MALLOC - if (spare_memory == 0) - spare_memory = (char *) malloc ((size_t) SPARE_MEMORY); -#endif -} /* Called if we can't allocate relocatable space for a buffer. */ @@ -578,8 +553,6 @@ buffer_memory_full () memory_full (); #endif - Vmemory_full = Qt; - /* This used to call error, but if we've run out of memory, we could get infinite recursion trying to build the string. */ while (1) @@ -805,6 +778,9 @@ xfree (block) BLOCK_INPUT; free (block); UNBLOCK_INPUT; + /* We don't call refill_memory_reserve here + because that duplicates doing so in emacs_blocked_free + and the criterion should go there. */ } @@ -1178,6 +1154,8 @@ emacs_blocked_free (ptr, ptr2) void *ptr; const void *ptr2; { + EMACS_INT bytes_used_now; + BLOCK_INPUT_ALLOC; #ifdef GC_MALLOC_CHECK @@ -1206,14 +1184,15 @@ emacs_blocked_free (ptr, ptr2) /* If we released our reserve (due to running out of memory), and we have a fair amount free once again, try to set aside another reserve in case we run out once more. */ - if (spare_memory == 0 + if (! NILP (Vmemory_full) /* Verify there is enough space that even with the malloc hysteresis this call won't run out again. The code here is correct as long as SPARE_MEMORY is substantially larger than the block size malloc uses. */ && (bytes_used_when_full - > BYTES_USED + max (malloc_hysteresis, 4) * SPARE_MEMORY)) - spare_memory = (char *) malloc ((size_t) SPARE_MEMORY); + > ((bytes_used_when_reconsidered = BYTES_USED) + + max (malloc_hysteresis, 4) * SPARE_MEMORY))) + refill_memory_reserve (); __free_hook = emacs_blocked_free; UNBLOCK_INPUT_ALLOC; @@ -2560,7 +2539,7 @@ void free_float (ptr) struct Lisp_Float *ptr; { - *(struct Lisp_Float **)&ptr->data = float_free_list; + ptr->u.chain = float_free_list; float_free_list = ptr; } @@ -2578,7 +2557,7 @@ make_float (float_value) /* We use the data field for chaining the free list so that we won't use the same field that has the mark bit. */ XSETFLOAT (val, float_free_list); - float_free_list = *(struct Lisp_Float **)&float_free_list->data; + float_free_list = float_free_list->u.chain; } else { @@ -2678,7 +2657,7 @@ void free_cons (ptr) struct Lisp_Cons *ptr; { - *(struct Lisp_Cons **)&ptr->cdr = cons_free_list; + ptr->u.chain = cons_free_list; #if GC_MARK_STACK ptr->car = Vdead; #endif @@ -2697,7 +2676,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, /* We use the cdr for chaining the free list so that we won't use the same field that has the mark bit. */ XSETCONS (val, cons_free_list); - cons_free_list = *(struct Lisp_Cons **)&cons_free_list->cdr; + cons_free_list = cons_free_list->u.chain; } else { @@ -2732,7 +2711,7 @@ check_cons_list () struct Lisp_Cons *tail = cons_free_list; while (tail) - tail = *(struct Lisp_Cons **)&tail->cdr; + tail = tail->u.chain; #endif } @@ -3126,7 +3105,7 @@ Its value and function definition are void, and its property list is nil. */) if (symbol_free_list) { XSETSYMBOL (val, symbol_free_list); - symbol_free_list = *(struct Lisp_Symbol **)&symbol_free_list->value; + symbol_free_list = symbol_free_list->next; } else { @@ -3337,6 +3316,83 @@ make_event_array (nargs, args) /************************************************************************ + Memory Full Handling + ************************************************************************/ + + +/* Called if malloc returns zero. */ + +void +memory_full () +{ + int i; + + Vmemory_full = Qt; + + 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++) + if (spare_memory[i]) + { + if (i == 0) + free (spare_memory[i]); + else if (i >= 1 && i <= 4) + lisp_align_free (spare_memory[i]); + else + lisp_free (spare_memory[i]); + spare_memory[i] = 0; + } + + /* Record the space now used. When it decreases substantially, + we can refill the memory reserve. */ +#ifndef SYSTEM_MALLOC + bytes_used_when_full = BYTES_USED; +#endif + + /* This used to call error, but if we've run out of memory, we could + get infinite recursion trying to build the string. */ + while (1) + Fsignal (Qnil, Vmemory_signal_data); +} + +/* If we released our reserve (due to running out of memory), + and we have a fair amount free once again, + try to set aside another reserve in case we run out once more. + + This is called when a relocatable block is freed in ralloc.c, + and also directly from this file, in case we're not using ralloc.c. */ + +void +refill_memory_reserve () +{ +#ifndef SYSTEM_MALLOC + if (spare_memory[0] == 0) + spare_memory[0] = (char *) malloc ((size_t) SPARE_MEMORY); + if (spare_memory[1] == 0) + spare_memory[1] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[2] == 0) + spare_memory[2] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[3] == 0) + spare_memory[3] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[4] == 0) + spare_memory[4] = (char *) lisp_align_malloc (sizeof (struct cons_block), + MEM_TYPE_CONS); + if (spare_memory[5] == 0) + spare_memory[5] = (char *) lisp_malloc (sizeof (struct string_block), + MEM_TYPE_STRING); + if (spare_memory[6] == 0) + spare_memory[6] = (char *) lisp_malloc (sizeof (struct string_block), + MEM_TYPE_STRING); + if (spare_memory[0] && spare_memory[1] && spare_memory[5]) + Vmemory_full = Qnil; +#endif +} + +/************************************************************************ C Stack Marking ************************************************************************/ @@ -4393,10 +4449,96 @@ mark_stack () #endif } - #endif /* GC_MARK_STACK != 0 */ + +/* Return 1 if OBJ is a valid lisp object. + Return 0 if OBJ is NOT a valid lisp object. + Return -1 if we cannot validate OBJ. + This function can be quite slow, + so it should only be used in code for manual debugging. */ + +int +valid_lisp_object_p (obj) + Lisp_Object obj; +{ + void *p; +#if !GC_MARK_STACK + int fd; +#else + struct mem_node *m; +#endif + + if (INTEGERP (obj)) + return 1; + + p = (void *) XPNTR (obj); + if (PURE_POINTER_P (p)) + return 1; + +#if !GC_MARK_STACK + /* We need to determine whether it is safe to access memory at + address P. Obviously, we cannot just access it (we would SEGV + trying), so we trick the o/s to tell us whether p is a valid + pointer. Unfortunately, we cannot use NULL_DEVICE here, as + emacs_write may not validate p in that case. */ + if ((fd = emacs_open ("__Valid__Lisp__Object__", O_CREAT | O_WRONLY | O_TRUNC, 0666)) >= 0) + { + int valid = (emacs_write (fd, (char *)p, 16) == 16); + emacs_close (fd); + unlink ("__Valid__Lisp__Object__"); + return valid; + } + + return -1; +#else + + m = mem_find (p); + + if (m == MEM_NIL) + return 0; + + switch (m->type) + { + case MEM_TYPE_NON_LISP: + return 0; + + case MEM_TYPE_BUFFER: + return live_buffer_p (m, p); + + case MEM_TYPE_CONS: + return live_cons_p (m, p); + + case MEM_TYPE_STRING: + return live_string_p (m, p); + + case MEM_TYPE_MISC: + return live_misc_p (m, p); + + case MEM_TYPE_SYMBOL: + return live_symbol_p (m, p); + + case MEM_TYPE_FLOAT: + return live_float_p (m, p); + + case MEM_TYPE_VECTOR: + case MEM_TYPE_PROCESS: + case MEM_TYPE_HASH_TABLE: + case MEM_TYPE_FRAME: + case MEM_TYPE_WINDOW: + return live_vector_p (m, p); + + default: + break; + } + + return 0; +#endif +} + + + /*********************************************************************** Pure Storage Management @@ -4876,7 +5018,7 @@ returns nil, because real GC can't be done. */) total += total_floats * sizeof (struct Lisp_Float); total += total_intervals * sizeof (struct interval); total += total_strings * sizeof (struct Lisp_String); - + gc_relative_threshold = total * XFLOAT_DATA (Vgc_cons_percentage); } else @@ -5403,14 +5545,14 @@ mark_object (arg) CHECK_ALLOCATED_AND_LIVE (live_cons_p); CONS_MARK (ptr); /* If the cdr is nil, avoid recursion for the car. */ - if (EQ (ptr->cdr, Qnil)) + if (EQ (ptr->u.cdr, Qnil)) { obj = ptr->car; cdr_count = 0; goto loop; } mark_object (ptr->car); - obj = ptr->cdr; + obj = ptr->u.cdr; cdr_count++; if (cdr_count == mark_object_loop_halt) abort (); @@ -5557,7 +5699,7 @@ gc_sweep () if (!CONS_MARKED_P (&cblk->conses[i])) { this_free++; - *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list; + cblk->conses[i].u.chain = cons_free_list; cons_free_list = &cblk->conses[i]; #if GC_MARK_STACK cons_free_list->car = Vdead; @@ -5576,7 +5718,7 @@ gc_sweep () { *cprev = cblk->next; /* Unhook from the free list. */ - cons_free_list = *(struct Lisp_Cons **) &cblk->conses[0].cdr; + cons_free_list = cblk->conses[0].u.chain; lisp_align_free (cblk); n_cons_blocks--; } @@ -5607,7 +5749,7 @@ gc_sweep () if (!FLOAT_MARKED_P (&fblk->floats[i])) { this_free++; - *(struct Lisp_Float **)&fblk->floats[i].data = float_free_list; + fblk->floats[i].u.chain = float_free_list; float_free_list = &fblk->floats[i]; } else @@ -5623,7 +5765,7 @@ gc_sweep () { *fprev = fblk->next; /* Unhook from the free list. */ - float_free_list = *(struct Lisp_Float **) &fblk->floats[0].data; + float_free_list = fblk->floats[0].u.chain; lisp_align_free (fblk); n_float_blocks--; } @@ -5711,7 +5853,7 @@ gc_sweep () if (!sym->gcmarkbit && !pure_p) { - *(struct Lisp_Symbol **) &sym->value = symbol_free_list; + sym->next = symbol_free_list; symbol_free_list = sym; #if GC_MARK_STACK symbol_free_list->function = Vdead; @@ -5735,7 +5877,7 @@ gc_sweep () { *sprev = sblk->next; /* Unhook from the free list. */ - symbol_free_list = *(struct Lisp_Symbol **)&sblk->symbols[0].value; + symbol_free_list = sblk->symbols[0].next; lisp_free (sblk); n_symbol_blocks--; } @@ -5963,7 +6105,7 @@ init_alloc_once () malloc_hysteresis = 0; #endif - spare_memory = (char *) malloc (SPARE_MEMORY); + refill_memory_reserve (); ignore_warnings = 0; gcprolist = 0; @@ -6064,7 +6206,7 @@ This means that certain objects should be allocated in shared (pure) space. */) build_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs")); DEFVAR_LISP ("memory-full", &Vmemory_full, - doc: /* Non-nil means we are handling a memory-full error. */); + doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); Vmemory_full = Qnil; staticpro (&Qgc_cons_threshold); @@ -6079,7 +6221,6 @@ The time is in seconds as a floating point value. */); DEFVAR_INT ("gcs-done", &gcs_done, doc: /* Accumulated number of garbage collections done. */); - defsubr (&Smemory_full_p); defsubr (&Scons); defsubr (&Slist); defsubr (&Svector); diff --git a/src/atimer.c b/src/atimer.c index f8ed1b265ec..d260f67d24d 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -231,7 +231,7 @@ stop_other_atimers (t) struct atimer *p, *prev; /* See if T is active. */ - for (p = atimers, prev = 0; p && p != t; p = p->next) + for (p = atimers, prev = NULL; p && p != t; prev = p, p = p->next) ; if (p == t) diff --git a/src/buffer.c b/src/buffer.c index 2c02ffacc1d..adcd03127da 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1360,7 +1360,8 @@ with SIGHUP. */) /* First run the query functions; if any query is answered no, don't kill the buffer. */ arglist[0] = Qkill_buffer_query_functions; - if (NILP (Frun_hook_with_args_until_failure (1, arglist))) + tem = Frun_hook_with_args_until_failure (1, arglist); + if (NILP (tem)) return unbind_to (count, Qnil); /* Then run the hooks. */ @@ -1723,9 +1724,6 @@ do not put this buffer at the front of the list of recently selected ones. */) } } Fset_buffer (buf); - if (NILP (norecord)) - /* Why bother ? Fselect_window will do it for us anyway. -stef */ - record_buffer (buf); Fselect_window (Fdisplay_buffer (buf, other_window, Qnil), norecord); return buf; } diff --git a/src/bytecode.c b/src/bytecode.c index 21e89d372c2..4a10d6091e7 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -524,15 +524,19 @@ If the third argument is incorrect, Emacs may crash. */) } case Bgotoifnil: - MAYBE_GC (); - op = FETCH2; - if (NILP (POP)) - { - BYTE_CODE_QUIT; - CHECK_RANGE (op); - stack.pc = stack.byte_string_start + op; - } - break; + { + Lisp_Object v1; + MAYBE_GC (); + op = FETCH2; + v1 = POP; + if (NILP (v1)) + { + BYTE_CODE_QUIT; + CHECK_RANGE (op); + stack.pc = stack.byte_string_start + op; + } + break; + } case Bcar: { @@ -730,15 +734,19 @@ If the third argument is incorrect, Emacs may crash. */) break; case Bgotoifnonnil: - MAYBE_GC (); - op = FETCH2; - if (!NILP (POP)) - { - BYTE_CODE_QUIT; - CHECK_RANGE (op); - stack.pc = stack.byte_string_start + op; - } - break; + { + Lisp_Object v1; + MAYBE_GC (); + op = FETCH2; + v1 = POP; + if (!NILP (v1)) + { + BYTE_CODE_QUIT; + CHECK_RANGE (op); + stack.pc = stack.byte_string_start + op; + } + break; + } case Bgotoifnilelsepop: MAYBE_GC (); @@ -771,24 +779,32 @@ If the third argument is incorrect, Emacs may crash. */) break; case BRgotoifnil: - MAYBE_GC (); - if (NILP (POP)) - { - BYTE_CODE_QUIT; - stack.pc += (int) *stack.pc - 128; - } - stack.pc++; - break; + { + Lisp_Object v1; + MAYBE_GC (); + v1 = POP; + if (NILP (v1)) + { + BYTE_CODE_QUIT; + stack.pc += (int) *stack.pc - 128; + } + stack.pc++; + break; + } case BRgotoifnonnil: - MAYBE_GC (); - if (!NILP (POP)) - { - BYTE_CODE_QUIT; - stack.pc += (int) *stack.pc - 128; - } - stack.pc++; - break; + { + Lisp_Object v1; + MAYBE_GC (); + v1 = POP; + if (!NILP (v1)) + { + BYTE_CODE_QUIT; + stack.pc += (int) *stack.pc - 128; + } + stack.pc++; + break; + } case BRgotoifnilelsepop: MAYBE_GC (); @@ -861,11 +877,11 @@ If the third argument is incorrect, Emacs may crash. */) case Bcondition_case: { - Lisp_Object v1; - v1 = POP; - v1 = Fcons (POP, v1); + Lisp_Object handlers, body; + handlers = POP; + body = POP; BEFORE_POTENTIAL_GC (); - TOP = Fcondition_case (Fcons (TOP, v1)); + TOP = internal_lisp_condition_case (TOP, body, handlers); AFTER_POTENTIAL_GC (); break; } diff --git a/src/callproc.c b/src/callproc.c index 4e81bb62c3a..128bf8825e6 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -896,9 +896,11 @@ static Lisp_Object delete_temp_file (name) Lisp_Object name; { - /* Use Fdelete_file (indirectly) because that runs a file name handler. - We did that when writing the file, so we should do so when deleting. */ + /* Suppress jka-compr handling, etc. */ + int count = SPECPDL_INDEX (); + specbind (intern ("file-name-handler-alist"), Qnil); internal_delete_file (name); + unbind_to (count, Qnil); return Qnil; } @@ -1009,6 +1011,9 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r int count1 = SPECPDL_INDEX (); specbind (intern ("coding-system-for-write"), val); + /* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we + happen to get a ".Z" suffix. */ + specbind (intern ("file-name-handler-alist"), Qnil); Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil); unbind_to (count1, Qnil); diff --git a/src/casetab.c b/src/casetab.c index d34ca473a93..cccc7d24084 100644 --- a/src/casetab.c +++ b/src/casetab.c @@ -97,8 +97,9 @@ A case table is a char-table which maps characters to their lower-case equivalents. It also has three \"extra\" slots which may be additional char-tables or nil. These slots are called UPCASE, CANONICALIZE and EQUIVALENCES. -UPCASE maps each character to its upper-case equivalent; - if lower and upper case characters are in 1-1 correspondence, +UPCASE maps each non-upper-case character to its upper-case equivalent. + (The value in UPCASE for an upper-case character is never used.) + If lower and upper case characters are in 1-1 correspondence, you may use nil and the upcase table will be deduced from DOWNCASE. CANONICALIZE maps each character to a canonical equivalent; any two characters that are related by case-conversion have the same diff --git a/src/category.c b/src/category.c index cd1be5a8da0..3f4a9dd83f4 100644 --- a/src/category.c +++ b/src/category.c @@ -1,6 +1,8 @@ /* GNU Emacs routines to deal with category tables. - Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 1998, 2001, 2004 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 1999 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/category.h b/src/category.h index c025d409549..fc755ed7d86 100644 --- a/src/category.h +++ b/src/category.h @@ -1,6 +1,7 @@ /* Declarations having to do with Emacs category tables. - Copyright (C) 1995 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 1995, 1998, 1999 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/ccl.c b/src/ccl.c index 7f6ec1a7aa3..301cf010ba1 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -1,7 +1,8 @@ /* CCL (Code Conversion Language) interpreter. - Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 2003, 2004, 2005 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/ccl.h b/src/ccl.h index b14c18b8f25..96417e79fa5 100644 --- a/src/ccl.h +++ b/src/ccl.h @@ -1,6 +1,7 @@ /* Header for CCL (Code Conversion Language) interpreter. - Copyright (C) 1995 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 1995, 1998, 2000 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/charset.c b/src/charset.c index d2d5686b899..15a5d75ecbd 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1,7 +1,8 @@ /* Basic character set support. - Copyright (C) 1995, 97, 98, 2000, 2001 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003, 2004 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/charset.h b/src/charset.h index a06c3a1b094..782e92799ff 100644 --- a/src/charset.h +++ b/src/charset.h @@ -1,7 +1,8 @@ /* Header for charset handler. - Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 2003 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/coding.c b/src/coding.c index 1a9b13fd10e..c283b5a4369 100644 --- a/src/coding.c +++ b/src/coding.c @@ -1,7 +1,8 @@ /* Coding system handler (conversion, detection, etc). - Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 2002, 2003, 2004, 2005 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/coding.h b/src/coding.h index c182f182e67..834724cf340 100644 --- a/src/coding.h +++ b/src/coding.h @@ -1,10 +1,11 @@ /* Header for coding system handler. - Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 2000 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -610,7 +611,7 @@ struct coding_system /* Decode the string STR using the specified coding system for system functions, if any. */ -#define DECODE_SYSTEM(name) \ +#define DECODE_SYSTEM(str) \ (! NILP (Vlocale_coding_system) \ && !EQ (Vlocale_coding_system, make_number (0)) \ ? code_convert_string_norecord (str, Vlocale_coding_system, 0) \ diff --git a/src/commands.h b/src/commands.h index 7ad593577ad..ed46141bf11 100644 --- a/src/commands.h +++ b/src/commands.h @@ -37,9 +37,16 @@ extern Lisp_Object Vminibuffer_local_ns_map; /* keymap used for minibuffers when doing completion */ extern Lisp_Object Vminibuffer_local_completion_map; +/* keymap used for minibuffers when doing completion in filenames*/ +extern Lisp_Object Vminibuffer_local_filename_completion_map; + /* keymap used for minibuffers when doing completion and require a match */ extern Lisp_Object Vminibuffer_local_must_match_map; +/* keymap used for minibuffers when doing completion in filenames + and require a match */ +extern Lisp_Object Vminibuffer_local_must_match_filename_map; + /* Last character of last key sequence. */ extern Lisp_Object last_command_char; @@ -68,12 +75,15 @@ extern Lisp_Object Vthis_command; events until a non-ASCII event is acceptable as input. */ extern Lisp_Object unread_switch_frame; -/* The value of point when the last command was executed. */ +/* The value of point when the last command was started. */ extern int last_point_position; /* The buffer that was current when the last command was started. */ extern Lisp_Object last_point_position_buffer; +/* The window that was selected when the last command was started. */ +extern Lisp_Object last_point_position_window; + /* Nonzero means ^G can quit instantly */ extern int immediate_quit; diff --git a/src/composite.c b/src/composite.c index 3d50886dc3c..3b3743b6b2e 100644 --- a/src/composite.c +++ b/src/composite.c @@ -1,7 +1,8 @@ /* Composite sequence support. - Copyright (C) 1999 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1999 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 diff --git a/src/composite.h b/src/composite.h index 37a75c8a80b..ecfa4db3a56 100644 --- a/src/composite.h +++ b/src/composite.h @@ -1,10 +1,11 @@ /* Header for composite sequence handler. - Copyright (C) 1999 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1997 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 - Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/data.c b/src/data.c index 5e83f018001..78e52d8d51c 100644 --- a/src/data.c +++ b/src/data.c @@ -1709,12 +1709,20 @@ From now on the default value will apply in this buffer. Return VARIABLE. */) DEFUN ("make-variable-frame-local", Fmake_variable_frame_local, Smake_variable_frame_local, 1, 1, "vMake Variable Frame Local: ", doc: /* Enable VARIABLE to have frame-local bindings. -When a frame-local binding exists in the current frame, -it is in effect whenever the current buffer has no buffer-local binding. -A frame-local binding is actually a frame parameter value; -thus, any given frame has a local binding for VARIABLE if it has -a value for the frame parameter named VARIABLE. Return VARIABLE. -See `modify-frame-parameters' for how to set frame parameters. */) +This does not create any frame-local bindings for VARIABLE, +it just makes them possible. + +A frame-local binding is actually a frame parameter value. +If a frame F has a value for the frame parameter named VARIABLE, +that also acts as a frame-local binding for VARIABLE in F-- +provided this function has been called to enable VARIABLE +to have frame-local bindings at all. + +The only way to create a frame-local binding for VARIABLE in a frame +is to set the VARIABLE frame parameter of that frame. See +`modify-frame-parameters' for how to set frame parameters. + +Buffer-local bindings take precedence over frame-local bindings. */) (variable) register Lisp_Object variable; { diff --git a/src/dispextern.h b/src/dispextern.h index b1f18e3ef25..52033a3e5f4 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1973,6 +1973,10 @@ struct it /* 1 means overlay strings at end_charpos have been processed. */ unsigned overlay_strings_at_end_processed_p : 1; + /* 1 means to ignore overlay strings at current pos, as they have + already been processed. */ + unsigned ignore_overlay_strings_at_pos_p : 1; + /* 1 means the actual glyph is not available in the current system. */ unsigned glyph_not_available_p : 1; diff --git a/src/doc.c b/src/doc.c index 82a2391c424..596bb0bfeec 100644 --- a/src/doc.c +++ b/src/doc.c @@ -735,15 +735,18 @@ the same file name is found in the `doc-directory'. */) DEFUN ("substitute-command-keys", Fsubstitute_command_keys, Ssubstitute_command_keys, 1, 1, 0, doc: /* Substitute key descriptions for command names in STRING. -Return a new string which is STRING with substrings of the form \\=\\[COMMAND] -replaced by either: a keystroke sequence that will invoke COMMAND, -or "M-x COMMAND" if COMMAND is not on any keys. +Substrings of the form \\=\\[COMMAND] replaced by either: a keystroke +sequence that will invoke COMMAND, or "M-x COMMAND" if COMMAND is not +on any keys. Substrings of the form \\=\\{MAPVAR} are replaced by summaries \(made by describe-bindings) of the value of MAPVAR, taken as a keymap. Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR as the keymap for future \\=\\[COMMAND] substrings. \\=\\= quotes the following character and is discarded; -thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output. */) +thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output. + +Returns original STRING if no substitutions were made. Othwerwise, +a new string, without any text properties, is returned. */) (string) Lisp_Object string; { diff --git a/src/editfns.c b/src/editfns.c index dad41b3d05d..c2f73bdea6a 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2493,9 +2493,9 @@ determines whether case is significant or ignored. */) { register int begp1, endp1, begp2, endp2, temp; register struct buffer *bp1, *bp2; - register Lisp_Object *trt + register Lisp_Object trt = (!NILP (current_buffer->case_fold_search) - ? XCHAR_TABLE (current_buffer->case_canon_table)->contents : 0); + ? current_buffer->case_canon_table : Qnil); int chars = 0; int i1, i2, i1_byte, i2_byte; @@ -2614,10 +2614,10 @@ determines whether case is significant or ignored. */) i2++; } - if (trt) + if (!NILP (trt)) { - c1 = XINT (trt[c1]); - c2 = XINT (trt[c2]); + c1 = CHAR_TABLE_TRANSLATE (trt, c1); + c2 = CHAR_TABLE_TRANSLATE (trt, c2); } if (c1 < c2) return make_number (- 1 - chars); @@ -3794,7 +3794,7 @@ usage: (format STRING &rest OBJECTS) */) ++nchars; } - start = nchars; + info[n].start = start = nchars; nchars += nchars_string; end = nchars; @@ -3809,6 +3809,8 @@ usage: (format STRING &rest OBJECTS) */) nbytes, STRING_MULTIBYTE (args[n]), multibyte); + info[n].end = nchars; + if (negative) while (padding-- > 0) { @@ -3845,9 +3847,9 @@ usage: (format STRING &rest OBJECTS) */) else p += this_nchars; nchars += this_nchars; + info[n].end = nchars; } - info[n].end = nchars; } else if (STRING_MULTIBYTE (args[0])) { diff --git a/src/emacs.c b/src/emacs.c index 0193043ed2d..41857b7ccb8 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1,6 +1,6 @@ /* Fully extensible Emacs, running on Unix, intended for GNU. Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1997, 1998, 1999, - 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -112,6 +112,9 @@ EMACS_INT gdb_data_seg_bits = 0; #endif EMACS_INT PVEC_FLAG = PSEUDOVECTOR_FLAG; EMACS_INT gdb_array_mark_flag = ARRAY_MARK_FLAG; +/* GDB might say "No enum type named pvec_type" if we don't have at + least one symbol with that type, and then xbacktrace could fail. */ +enum pvec_type gdb_pvec_type = PVEC_TYPE_MASK; /* Command line args from shell, as list of strings. */ Lisp_Object Vcommand_line_args; @@ -896,7 +899,7 @@ main (argc, argv else { printf ("GNU Emacs %s\n", SDATA (tem)); - printf ("Copyright (C) 2005 Free Software Foundation, Inc.\n"); + printf ("Copyright (C) 2006 Free Software Foundation, Inc.\n"); printf ("GNU Emacs comes with ABSOLUTELY NO WARRANTY.\n"); printf ("You may redistribute copies of Emacs\n"); printf ("under the terms of the GNU General Public License.\n"); @@ -962,9 +965,15 @@ main (argc, argv #ifdef MAC_OSX /* Skip process serial number passed in the form -psn_x_y as - command-line argument. */ + command-line argument. The WindowServer adds this option when + Emacs is invoked from the Finder or by the `open' command. In + these cases, the working directory becomes `/', so we change it + to the user's home directory. */ if (argc > skip_args + 1 && strncmp (argv[skip_args+1], "-psn_", 5) == 0) - skip_args++; + { + chdir (getenv ("HOME")); + skip_args++; + } #endif /* MAC_OSX */ #ifdef VMS diff --git a/src/eval.c b/src/eval.c index a867d00150e..a6c58bc2425 100644 --- a/src/eval.c +++ b/src/eval.c @@ -103,7 +103,7 @@ Lisp_Object Vrun_hooks; /* Non-nil means record all fset's and provide's, to be undone if the file being autoloaded is not fully loaded. They are recorded by being consed onto the front of Vautoload_queue: - (FUN . ODEF) for a defun, (OFEATURES . nil) for a provide. */ + (FUN . ODEF) for a defun, (0 . OFEATURES) for a provide. */ Lisp_Object Vautoload_queue; @@ -1343,15 +1343,28 @@ usage: (condition-case VAR BODYFORM &rest HANDLERS) */) (args) Lisp_Object args; { - Lisp_Object val; - struct catchtag c; - struct handler h; register Lisp_Object bodyform, handlers; volatile Lisp_Object var; var = Fcar (args); bodyform = Fcar (Fcdr (args)); handlers = Fcdr (Fcdr (args)); + + return internal_lisp_condition_case (var, bodyform, handlers); +} + +/* Like Fcondition_case, but the args are separate + rather than passed in a list. Used by Fbyte_code. */ + +Lisp_Object +internal_lisp_condition_case (var, bodyform, handlers) + volatile Lisp_Object var; + Lisp_Object bodyform, handlers; +{ + Lisp_Object val; + struct catchtag c; + struct handler h; + CHECK_SYMBOL (var); for (val = handlers; CONSP (val); val = XCDR (val)) @@ -2009,8 +2022,8 @@ un_autoload (oldqueue) first = XCAR (queue); second = Fcdr (first); first = Fcar (first); - if (EQ (second, Qnil)) - Vfeatures = first; + if (EQ (first, make_number (0))) + Vfeatures = second; else Ffset (first, second); queue = XCDR (queue); @@ -2056,7 +2069,7 @@ do_autoload (fundef, funname) second = Fcdr (first); first = Fcar (first); - if (CONSP (second) && EQ (XCAR (second), Qautoload)) + if (SYMBOLP (first) && CONSP (second) && EQ (XCAR (second), Qautoload)) Fput (first, Qautoload, (XCDR (second))); queue = XCDR (queue); @@ -2094,8 +2107,10 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, return form; QUIT; - if (consing_since_gc > gc_cons_threshold - && consing_since_gc > gc_relative_threshold) + if ((consing_since_gc > gc_cons_threshold + && consing_since_gc > gc_relative_threshold) + || + (!NILP (Vmemory_full) && consing_since_gc > memory_full_cons_threshold)) { GCPRO1 (form); Fgarbage_collect (); @@ -2795,8 +2810,10 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) register int i; QUIT; - if (consing_since_gc > gc_cons_threshold - && consing_since_gc > gc_relative_threshold) + if ((consing_since_gc > gc_cons_threshold + && consing_since_gc > gc_relative_threshold) + || + (!NILP (Vmemory_full) && consing_since_gc > memory_full_cons_threshold)) Fgarbage_collect (); if (++lisp_eval_depth > max_lisp_eval_depth) diff --git a/src/fileio.c b/src/fileio.c index 2e63a60fdb9..ad3d89aa983 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,7 +1,7 @@ /* File IO for GNU Emacs. Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005 Free Software Foundation, Inc. + 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -1648,8 +1648,7 @@ See also the function `substitute-in-file-name'. */) { *o++ = *p++; } - else if (IS_DIRECTORY_SEP (p[0]) - && p[1] == '.' + else if (p[1] == '.' && (IS_DIRECTORY_SEP (p[2]) || p[2] == 0)) { @@ -1659,7 +1658,7 @@ See also the function `substitute-in-file-name'. */) *o++ = *p; p += 2; } - else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.' + else if (p[1] == '.' && p[2] == '.' /* `/../' is the "superroot" on certain file systems. Turned off on DOS_NT systems because they have no "superroot" and because this causes us to produce @@ -1679,14 +1678,9 @@ See also the function `substitute-in-file-name'. */) ++o; p += 3; } - else if (p > target - && IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])) - { - /* Collapse multiple `/' in a row. */ - *o++ = *p++; - while (IS_DIRECTORY_SEP (*p)) - ++p; - } + else if (p > target && IS_DIRECTORY_SEP (p[1])) + /* Collapse multiple `/' in a row. */ + p++; else { *o++ = *p++; @@ -2735,8 +2729,10 @@ int internal_delete_file (filename) Lisp_Object filename; { - return NILP (internal_condition_case_1 (Fdelete_file, filename, - Qt, internal_delete_file_1)); + Lisp_Object tem; + tem = internal_condition_case_1 (Fdelete_file, filename, + Qt, internal_delete_file_1); + return NILP (tem); } DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, @@ -3397,8 +3393,10 @@ searchable directory. */) } DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0, - doc: /* Return t if file FILENAME is the name of a regular file. -This is the sort of file that holds an ordinary stream of data bytes. */) + doc: /* Return t if FILENAME names a regular file. +This is the sort of file that holds an ordinary stream of data bytes. +Symbolic links to regular files count as regular files. +See `file-symlink-p' to distinguish symlinks. */) (filename) Lisp_Object filename; { @@ -4531,6 +4529,8 @@ actually used. */) #endif Vdeactivate_mark = old_Vdeactivate_mark; } + else + Vdeactivate_mark = Qt; /* Make the text read part of the buffer. */ GAP_SIZE -= inserted; @@ -6148,13 +6148,17 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte #endif { /* Must do it the hard (and slow) way. */ + Lisp_Object tem; GCPRO3 (all, comp, specdir); count = SPECPDL_INDEX (); record_unwind_protect (read_file_name_cleanup, current_buffer->directory); current_buffer->directory = realdir; for (comp = Qnil; CONSP (all); all = XCDR (all)) - if (!NILP (call1 (Vread_file_name_predicate, XCAR (all)))) - comp = Fcons (XCAR (all), comp); + { + tem = call1 (Vread_file_name_predicate, XCAR (all)); + if (!NILP (tem)) + comp = Fcons (XCAR (all), comp); + } unbind_to (count, Qnil); UNGCPRO; } diff --git a/src/floatfns.c b/src/floatfns.c index 79574e0a69b..71f53542283 100644 --- a/src/floatfns.c +++ b/src/floatfns.c @@ -508,7 +508,7 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, DEFUN ("log", Flog, Slog, 1, 2, 0, doc: /* Return the natural logarithm of ARG. -If second optional argument BASE is given, return log ARG using that base. */) +If the optional argument BASE is given, return log ARG using that base. */) (arg, base) register Lisp_Object arg, base; { diff --git a/src/fns.c b/src/fns.c index b21af2b22f2..e260c46d4de 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2867,7 +2867,8 @@ particular subfeatures supported in this version of FEATURE. */) CHECK_SYMBOL (feature); CHECK_LIST (subfeatures); if (!NILP (Vautoload_queue)) - Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue); + Vautoload_queue = Fcons (Fcons (make_number (0), Vfeatures), + Vautoload_queue); tem = Fmemq (feature, Vfeatures); if (NILP (tem)) Vfeatures = Fcons (feature, Vfeatures); @@ -2912,14 +2913,20 @@ The normal messages at start and end of loading FILENAME are suppressed. */) { register Lisp_Object tem; struct gcpro gcpro1, gcpro2; + int from_file = load_in_progress; CHECK_SYMBOL (feature); /* Record the presence of `require' in this file even if the feature specified is already loaded. But not more than once in any file, - and not when we aren't loading a file. */ - if (load_in_progress) + and not when we aren't loading or reading from a file. */ + if (!from_file) + for (tem = Vcurrent_load_list; CONSP (tem); tem = XCDR (tem)) + if (NILP (XCDR (tem)) && STRINGP (XCAR (tem))) + from_file = 1; + + if (from_file) { tem = Fcons (Qrequire, feature); if (NILP (Fmember (tem, Vcurrent_load_list))) diff --git a/src/fontset.c b/src/fontset.c index c63bec61a15..e5d1f4c0b03 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -1,11 +1,12 @@ /* Fontset handler. - Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 2000, 2003, 2004, 2005 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. - + This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify diff --git a/src/fontset.h b/src/fontset.h index 33bbeda4f52..c3ef769d1ea 100644 --- a/src/fontset.h +++ b/src/fontset.h @@ -1,10 +1,11 @@ /* Header for fontset handler. - Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN. - Licensed to the Free Software Foundation. + Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 2000 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H14PRO021 Copyright (C) 2003 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/fringe.c b/src/fringe.c index 62de5e5cdb6..7a042ad200e 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -906,9 +906,12 @@ update_window_fringes (w, keep_current_p) left = LEFT_TRUNCATION_BITMAP; else if (row->indicate_bob_p && EQ (boundary_top, Qleft)) left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) - ? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP); + ? (row->ends_at_zv_p + ? TOP_RIGHT_ANGLE_BITMAP : LEFT_BRACKET_BITMAP) + : TOP_LEFT_ANGLE_BITMAP); else if (row->indicate_eob_p && EQ (boundary_bot, Qleft)) - left = BOTTOM_LEFT_ANGLE_BITMAP; + left = (row->ends_at_zv_p + ? TOP_RIGHT_ANGLE_BITMAP : BOTTOM_LEFT_ANGLE_BITMAP); else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) left = CONTINUATION_LINE_BITMAP; else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft)) @@ -932,9 +935,12 @@ update_window_fringes (w, keep_current_p) right = RIGHT_TRUNCATION_BITMAP; else if (row->indicate_bob_p && EQ (boundary_top, Qright)) right = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) - ? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP); + ? (row->ends_at_zv_p + ? TOP_LEFT_ANGLE_BITMAP : RIGHT_BRACKET_BITMAP) + : TOP_RIGHT_ANGLE_BITMAP); else if (row->indicate_eob_p && EQ (boundary_bot, Qright)) - right = BOTTOM_RIGHT_ANGLE_BITMAP; + right = (row->ends_at_zv_p + ? TOP_LEFT_ANGLE_BITMAP : BOTTOM_RIGHT_ANGLE_BITMAP); else if (row->continued_p) right = CONTINUED_LINE_BITMAP; else if (row->indicate_top_line_p && EQ (arrow_top, Qright)) diff --git a/src/gnu.h b/src/gnu.h index 1d623431af8..dbf47317493 100644 --- a/src/gnu.h +++ b/src/gnu.h @@ -1,6 +1,216 @@ -#define gnu_width 50 -#define gnu_height 50 -static unsigned char gnu_bits[] = { +#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) +static char * gnu_xpm_bits[] = { +"32 32 173 2", +" c None", +". c #67627D", +"+ c #5F5A76", +"@ c #78748C", +"# c #DCDBE1", +"$ c #CFCED7", +"% c #B8B5C7", +"& c #ADA9C1", +"* c #A6A3B9", +"= c #9995A9", +"- c #878398", +"; c #C2C0CD", +"> c #9591AE", +", c #9B97B3", +"' c #BDBACC", +") c #9C98B3", +"! c #A9A6B9", +"~ c #8D89A0", +"{ c #A9A5BC", +"] c #938FAB", +"^ c #B4B2C5", +"/ c #F8F8FA", +"( c #E4E3EA", +"_ c #BCB9CB", +": c #9390A5", +"< c #5E5A75", +"[ c #8B87A1", +"} c #918DA9", +"| c #BAB7C9", +"1 c #FFFFFF", +"2 c #F1F1F4", +"3 c #B4B1C4", +"4 c #9D99AF", +"5 c #5D5974", +"6 c #8E8AA5", +"7 c #A3A0B6", +"8 c #F8F8F9", +"9 c #9F9CB3", +"0 c #8C88A3", +"a c #938FA9", +"b c #C6C4D1", +"c c #B7B4C5", +"d c #9D99B1", +"e c #5C5873", +"f c #8985A0", +"g c #B5B3C4", +"h c #F0F0F3", +"i c #A6A3B7", +"j c #9B98AE", +"k c #5C5872", +"l c #88849D", +"m c #A6A3B6", +"n c #F8F7F9", +"o c #C3C1CE", +"p c #9996AB", +"q c #5B5772", +"r c #85819A", +"s c #9491A7", +"t c #E0DFE6", +"u c #C2C0CC", +"v c #8C88A0", +"w c #9894A9", +"x c #5A5671", +"y c #838097", +"z c #B2B0BE", +"A c #F7F7F8", +"B c #D8D7DE", +"C c #928FA4", +"D c #9491A5", +"E c #5A5670", +"F c #817D95", +"G c #A9A6B6", +"H c #A8A5B6", +"I c #928FA3", +"J c #59556F", +"K c #7E7B91", +"L c #BEBDC8", +"M c #AEACBA", +"N c #908DA0", +"O c #5B5771", +"P c #58546D", +"Q c #65617A", +"R c #E0DFE4", +"S c #8E8B9E", +"T c #7A778D", +"U c #5A566F", +"V c #57536C", +"W c #58546F", +"X c #A19EAE", +"Y c #EAEAED", +"Z c #F5F4F6", +"` c #A19FAE", +" . c #625F78", +".. c #77748A", +"+. c #59556E", +"@. c #56526B", +"#. c #807D90", +"$. c #D5D4DA", +"%. c #9693A3", +"&. c #767387", +"*. c #55516A", +"=. c #534F68", +"-. c #9491A1", +";. c #F4F4F6", +">. c #9E9CAA", +",. c #5D5971", +"'. c #737084", +"). c #545068", +"!. c #504D64", +"~. c #F4F4F5", +"{. c #DEDDE2", +"]. c #5A576D", +"^. c #716F81", +"/. c #56526A", +"(. c #524F67", +"_. c #4D4A61", +":. c #9A99A6", +"<. c #848292", +"[. c #6F6C7F", +"}. c #545169", +"|. c #514E65", +"1. c #4A475D", +"2. c #6B697B", +"3. c #D2D1D6", +"4. c #F4F3F5", +"5. c #9998A4", +"6. c #6C6A7B", +"7. c #535067", +"8. c #504C64", +"9. c #474459", +"0. c #747282", +"a. c #D1D0D5", +"b. c #E8E8EA", +"c. c #8C8A97", +"d. c #676576", +"e. c #4E4B62", +"f. c #444156", +"g. c #727080", +"h. c #E8E7EA", +"i. c #8A8996", +"j. c #656374", +"k. c #524F66", +"l. c #423F53", +"m. c #B8B7BE", +"n. c #D0CFD4", +"o. c #4E4B5E", +"p. c #636171", +"q. c #4C485E", +"r. c #434054", +"s. c #3F3C4F", +"t. c #575465", +"u. c #CFCED3", +"v. c #646272", +"w. c #504C62", +"x. c #4B475D", +"y. c #3D3A4C", +"z. c #494657", +"A. c #7A7884", +"B. c #B7B6BC", +"C. c #DADADD", +"D. c #4F4B61", +"E. c #49455B", +"F. c #3A3748", +"G. c #5E5C6A", +"H. c #908E98", +"I. c #C1C0C6", +"J. c #F3F2F4", +"K. c #777581", +"L. c #474458", +"M. c #434053", +"N. c #3C3A4A", +"O. c #373544", +"P. c #454256", +" ", +" ", +" . + + + + + + + + + + + + + + + + + + + + + + + ", +" @ # $ % & & & & & & & & & & & & & & & & & & * = @ + ", +" @ - ; > > > > > > > > > > , ' ' ) > > > > > > > > ! . + ", +" @ ~ { ] ] ] ] ] ] ] ] ] ] ] ] ^ / ( _ ] ] ] ] ] ] ] : < ", +" . [ } } } } } } } } } } } } } } | 1 1 2 3 } } } } } 4 < ", +" 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 8 1 1 1 8 6 6 6 6 6 9 5 ", +" 5 0 0 0 0 0 0 0 0 0 0 0 0 a b 8 1 1 1 1 c 0 0 0 0 0 d 5 ", +" e f f f f f f f f f f f g h 1 1 1 1 h i f f f f f f j e ", +" k l l l l l l l l l m h 1 1 1 1 n o l l l l l l l l p k ", +" q r r r r r r r s t 1 1 1 1 1 u v r r r r r r r r r w q ", +" x y y y y y y z A 1 1 1 1 B C y y y y y y y y y y y D e ", +" E F F F F F G 1 1 1 1 A H F F F F F F F F F F F F F I k ", +" J K K K K K L 1 1 1 1 M K K K K K K K K K K K K K K N O ", +" P q q q q q Q R 1 1 1 S q q q q q q q q q q q q q q T U ", +" V W W W W W W W X Y 1 Z ` .W W W W W W W W W W W W ..+. ", +" @.@.@.@.@.@.@.#.$.1 1 1 1 1 %.@.@.@.@.@.@.@.@.@.@.@.&.P ", +" *.=.=.=.=.=.-.1 1 1 1 ;.>.,.=.=.=.=.=.=.=.=.=.=.=.=.'.V ", +" ).!.!.!.!.!.~.1 1 1 {.].!.!.!.!.!.!.!.!.!.!.!.!.!.!.^./. ", +" (._._._._._.:.1 1 1 <._._._._._._._._._._._._._._._.[.}. ", +" |.1.1.1.1.1.1.2.3.1 4.5.1.1.1.1.1.1.1.1.1.1.1.1.1.1.6.7. ", +" 8.9.9.9.9.9.9.9.9.0.a.1 b.c.9.9.9.9.9.9.9.9.9.9.9.9.d.). ", +" e.f.f.f.f.f.f.f.f.f.f.g.h.1 h.i.f.f.f.f.f.f.f.f.f.f.j.k. ", +" _.l.l.l.l.l.l.l.l.l.l.l.l.m.1 1 n.o.l.l.l.l.l.l.l.l.p.|. ", +" q.r.s.s.s.s.s.s.s.s.s.s.s.t.1 1 1 u.s.s.s.s.s.s.s.s.v.w. ", +" x.9.y.y.y.y.y.y.y.y.z.A.B.1 1 1 1 C.y.y.y.y.y.y.y.y.d.D. ", +" E.E.r.F.F.F.F.F.F.F.F.G.H.I.J.I.K.F.F.F.F.F.F.F.F.r.E.E. ", +" L.L.M.N.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.N.M.L.L. ", +" P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P. ", +" ", +" "}; +#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */ + +#define gnu_xbm_width 50 +#define gnu_xbm_height 50 +static unsigned char gnu_xbm_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, diff --git a/src/gtkutil.c b/src/gtkutil.c index 84ce64beb56..065adeb4937 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -41,6 +41,9 @@ Boston, MA 02110-1301, USA. */ #define FRAME_TOTAL_PIXEL_HEIGHT(f) \ (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) +/* Avoid "differ in sign" warnings */ +#define SSDATA(x) ((char *) SDATA (x)) + /*********************************************************************** Display handling functions @@ -319,43 +322,43 @@ xg_get_image_for_pixmap (f, img, widget, old_widget) GdkPixmap *gmask; GdkDisplay *gdpy; - /* If we are on a one bit display, let GTK do all the image handling. + /* If we have a file, let GTK do all the image handling. This seems to be the only way to make insensitive and activated icons - look good. */ - if (x_screen_planes (f) == 1) - { - Lisp_Object specified_file = Qnil; - Lisp_Object tail; - extern Lisp_Object QCfile; + look good in all cases. */ + Lisp_Object specified_file = Qnil; + Lisp_Object tail; + extern Lisp_Object QCfile; - for (tail = XCDR (img->spec); - NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail)); - tail = XCDR (XCDR (tail))) - if (EQ (XCAR (tail), QCfile)) - specified_file = XCAR (XCDR (tail)); + for (tail = XCDR (img->spec); + NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail)); + tail = XCDR (XCDR (tail))) + if (EQ (XCAR (tail), QCfile)) + specified_file = XCAR (XCDR (tail)); - if (STRINGP (specified_file)) - { - - Lisp_Object file = Qnil; - struct gcpro gcpro1; - GCPRO1 (file); + if (STRINGP (specified_file)) + { + Lisp_Object file = Qnil; + struct gcpro gcpro1; + GCPRO1 (file); - file = x_find_image_file (specified_file); - /* We already loaded the image once before calling this - function, so this should not fail. */ - xassert (STRINGP (file) != 0); + file = x_find_image_file (specified_file); + /* We already loaded the image once before calling this + function, so this should not fail. */ + xassert (STRINGP (file) != 0); - if (! old_widget) - old_widget = GTK_IMAGE (gtk_image_new_from_file (SDATA (file))); - else - gtk_image_set_from_file (old_widget, SDATA (file)); + if (! old_widget) + old_widget = GTK_IMAGE (gtk_image_new_from_file (SSDATA (file))); + else + gtk_image_set_from_file (old_widget, SSDATA (file)); - UNGCPRO; - return GTK_WIDGET (old_widget); - } + UNGCPRO; + return GTK_WIDGET (old_widget); } + /* No file, do the image handling ourselves. This will look very bad + on a monochrome display, and sometimes bad on all displays with + certain themes. */ + gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap); gmask = img->mask ? gdk_pixmap_foreign_new_for_display (gdpy, img->mask) : 0; @@ -735,11 +738,11 @@ xg_create_frame_widgets (f) /* Use same names as the Xt port does. I.e. Emacs.pane.emacs by default */ gtk_widget_set_name (wtop, EMACS_CLASS); gtk_widget_set_name (wvbox, "pane"); - gtk_widget_set_name (wfixed, SDATA (Vx_resource_name)); + gtk_widget_set_name (wfixed, SSDATA (Vx_resource_name)); /* If this frame has a title or name, set it in the title bar. */ - if (! NILP (f->title)) title = SDATA (ENCODE_UTF_8 (f->title)); - else if (! NILP (f->name)) title = SDATA (ENCODE_UTF_8 (f->name)); + if (! NILP (f->title)) title = SSDATA (ENCODE_UTF_8 (f->title)); + else if (! NILP (f->name)) title = SSDATA (ENCODE_UTF_8 (f->name)); if (title) gtk_window_set_title (GTK_WINDOW (wtop), title); @@ -780,8 +783,8 @@ xg_create_frame_widgets (f) can't shrink the window from its starting size. */ gtk_window_set_policy (GTK_WINDOW (wtop), TRUE, TRUE, TRUE); gtk_window_set_wmclass (GTK_WINDOW (wtop), - SDATA (Vx_resource_name), - SDATA (Vx_resource_class)); + SSDATA (Vx_resource_name), + SSDATA (Vx_resource_class)); /* Add callback to do nothing on WM_DELETE_WINDOW. The default in GTK is to destroy the widget. We want Emacs to do that instead. */ @@ -1152,6 +1155,27 @@ create_dialog (wv, select_cb, deactivate_cb) /*********************************************************************** File dialog functions ***********************************************************************/ +/* Return non-zero if the old file selection dialog is being used. + Return zero if not. */ + +int +xg_uses_old_file_dialog () +{ +#ifdef HAVE_GTK_FILE_BOTH + extern int x_use_old_gtk_file_dialog; + return x_use_old_gtk_file_dialog; +#else /* ! HAVE_GTK_FILE_BOTH */ + +#ifdef HAVE_GTK_FILE_SELECTION_NEW + return 1; +#else + return 0; +#endif + +#endif /* ! HAVE_GTK_FILE_BOTH */ +} + + /* Function that is called when the file dialog pops down. W is the dialog widget, RESPONSE is the response code. USER_DATA is what we passed in to g_signal_connect (pointer to int). */ @@ -1196,6 +1220,59 @@ xg_get_file_name_from_chooser (w) return gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w)); } +/* Callback called when the "Show hidden files" toggle is pressed. + WIDGET is the toggle widget, DATA is the file chooser dialog. */ + +static void +xg_toggle_visibility_cb (widget, data) + GtkWidget *widget; + gpointer data; +{ + GtkFileChooser *dialog = GTK_FILE_CHOOSER (data); + gboolean visible; + g_object_get (G_OBJECT (dialog), "show-hidden", &visible, NULL); + g_object_set (G_OBJECT (dialog), "show-hidden", !visible, NULL); +} + + +/* Callback called when a property changes in a file chooser. + GOBJECT is the file chooser dialog, ARG1 describes the property. + USER_DATA is the toggle widget in the file chooser dialog. + We use this to update the "Show hidden files" toggle when the user + changes that property by right clicking in the file list. */ + +static void +xg_toggle_notify_cb (gobject, arg1, user_data) + GObject *gobject; + GParamSpec *arg1; + gpointer user_data; +{ + extern int x_gtk_show_hidden_files; + + if (strcmp (arg1->name, "show-hidden") == 0) + { + GtkFileChooser *dialog = GTK_FILE_CHOOSER (gobject); + GtkWidget *wtoggle = GTK_WIDGET (user_data); + gboolean visible, toggle_on; + + g_object_get (G_OBJECT (gobject), "show-hidden", &visible, NULL); + toggle_on = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wtoggle)); + + if (!!visible != !!toggle_on) + { + g_signal_handlers_block_by_func (G_OBJECT (wtoggle), + G_CALLBACK (xg_toggle_visibility_cb), + gobject); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle), visible); + g_signal_handlers_unblock_by_func + (G_OBJECT (wtoggle), + G_CALLBACK (xg_toggle_visibility_cb), + gobject); + } + x_gtk_show_hidden_files = visible; + } +} + /* Read a file name from the user using a file chooser dialog. F is the current frame. PROMPT is a prompt to show to the user. May not be NULL. @@ -1215,11 +1292,14 @@ xg_get_file_with_chooser (f, prompt, default_filename, int mustmatch_p, only_dir_p; xg_get_file_func *func; { - GtkWidget *filewin; + char message[1024]; + + GtkWidget *filewin, *wtoggle, *wbox, *wmessage; GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); GtkFileChooserAction action = (mustmatch_p ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE); + extern int x_gtk_show_hidden_files; if (only_dir_p) action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; @@ -1232,6 +1312,33 @@ xg_get_file_with_chooser (f, prompt, default_filename, NULL); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (filewin), TRUE); + wbox = gtk_vbox_new (FALSE, 0); + gtk_widget_show (wbox); + wtoggle = gtk_check_button_new_with_label ("Show hidden files."); + + if (x_gtk_show_hidden_files) + { + g_object_set (G_OBJECT (filewin), "show-hidden", TRUE, NULL); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle), TRUE); + } + gtk_widget_show (wtoggle); + g_signal_connect (G_OBJECT (wtoggle), "clicked", + G_CALLBACK (xg_toggle_visibility_cb), filewin); + g_signal_connect (G_OBJECT (filewin), "notify", + G_CALLBACK (xg_toggle_notify_cb), wtoggle); + + message[0] = '\0'; + if (action != GTK_FILE_CHOOSER_ACTION_SAVE) + strcat (message, "\nType C-l to display a file name text entry box.\n"); + strcat (message, "\nIf you don't like this file selector, customize " + "use-file-dialog\nto turn it off, or type C-x C-f to visit files."); + + wmessage = gtk_label_new (message); + gtk_widget_show (wmessage); + gtk_box_pack_start (GTK_BOX (wbox), wtoggle, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (wbox), wmessage, FALSE, FALSE, 0); + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (filewin), wbox); + if (default_filename) { Lisp_Object file; @@ -1245,7 +1352,7 @@ xg_get_file_with_chooser (f, prompt, default_filename, if (default_filename[0] != '/') file = Fexpand_file_name (file, Qnil); - default_filename = SDATA (file); + default_filename = SSDATA (file); if (Ffile_directory_p (file)) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filewin), default_filename); @@ -1340,7 +1447,6 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p) char *fn = 0; int filesel_done = 0; xg_get_file_func func; - extern int x_use_old_gtk_file_dialog; #if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN) /* I really don't know why this is needed, but without this the GLIBC add on @@ -1351,7 +1457,7 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p) #ifdef HAVE_GTK_FILE_BOTH - if (x_use_old_gtk_file_dialog) + if (xg_uses_old_file_dialog ()) w = xg_get_file_with_selection (f, prompt, default_filename, mustmatch_p, only_dir_p, &func); else diff --git a/src/gtkutil.h b/src/gtkutil.h index aea4ee9e7cf..6b9fd179ec5 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -132,6 +132,8 @@ extern int use_old_gtk_file_dialog; extern widget_value *malloc_widget_value P_ ((void)); extern void free_widget_value P_ ((widget_value *)); +extern int xg_uses_old_file_dialog P_ ((void)); + extern char *xg_get_file_name P_ ((FRAME_PTR f, char *prompt, char *default_filename, diff --git a/src/image.c b/src/image.c index 1996d8477e9..579c04e6f46 100644 --- a/src/image.c +++ b/src/image.c @@ -2259,23 +2259,25 @@ find_image_fsspec (specified_file, file, fss) Lisp_Object specified_file, *file; FSSpec *fss; { -#if MAC_OSX - FSRef fsr; -#endif OSErr err; + AEDesc desc; *file = x_find_image_file (specified_file); if (!STRINGP (*file)) return fnfErr; /* file or directory not found; incomplete pathname */ /* Try to open the image file. */ -#if MAC_OSX - err = FSPathMakeRef (SDATA (*file), &fsr, NULL); + err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file), + SBYTES (*file), typeFSS, &desc); if (err == noErr) - err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL); + { +#if TARGET_API_MAC_CARBON + err = AEGetDescData (&desc, fss, sizeof (FSSpec)); #else - err = posix_pathname_to_fsspec (SDATA (*file), fss); + *fss = *(FSSpec *)(*(desc.dataHandle)); #endif + AEDisposeDesc (&desc); + } return err; } @@ -2291,6 +2293,7 @@ image_load_qt_1 (f, img, type, fss, dh) GraphicsImportComponent gi; Rect rect; int width, height; + ImageDescriptionHandle desc_handle; short draw_all_pixels; Lisp_Object specified_bg; XColor color; @@ -2326,14 +2329,22 @@ image_load_qt_1 (f, img, type, fss, dh) goto error; } } - err = GraphicsImportGetNaturalBounds (gi, &rect); - if (err != noErr) + err = GraphicsImportGetImageDescription (gi, &desc_handle); + if (err != noErr || desc_handle == NULL) { image_error ("Error reading `%s'", img->spec, Qnil); goto error; } - width = img->width = rect.right - rect.left; - height = img->height = rect.bottom - rect.top; + width = img->width = (*desc_handle)->width; + height = img->height = (*desc_handle)->height; + DisposeHandle ((Handle)desc_handle); + + if (!check_image_size (f, width, height)) + { + image_error ("Invalid image size", Qnil, Qnil); + goto error; + } + err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels); #if 0 /* Don't check the error code here. It may have an undocumented @@ -2535,6 +2546,16 @@ image_load_quartz2d (f, img, png_p) image_error ("Error reading image `%s'", img->spec, Qnil); return 0; } + width = img->width = CGImageGetWidth (image); + height = img->height = CGImageGetHeight (image); + + if (!check_image_size (f, width, height)) + { + CGImageRelease (image); + UNGCPRO; + image_error ("Invalid image size", Qnil, Qnil); + return 0; + } if (png_p) { @@ -2548,8 +2569,7 @@ image_load_quartz2d (f, img, png_p) color.blue = BLUE16_FROM_ULONG (color.pixel); } } - width = img->width = CGImageGetWidth (image); - height = img->height = CGImageGetHeight (image); + if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) { CGImageRelease (image); @@ -3698,6 +3718,47 @@ xpm_image_p (object) #endif /* HAVE_XPM || MAC_OS */ +#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) +int +x_create_bitmap_from_xpm_data (f, bits) + struct frame *f; + char **bits; +{ + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + int id, rc; + XpmAttributes attrs; + Pixmap bitmap, mask; + + bzero (&attrs, sizeof attrs); + + attrs.visual = FRAME_X_VISUAL (f); + attrs.colormap = FRAME_X_COLORMAP (f); + attrs.valuemask |= XpmVisual; + attrs.valuemask |= XpmColormap; + + rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + bits, &bitmap, &mask, &attrs); + if (rc != XpmSuccess) + { + XpmFreeAttributes (&attrs); + return -1; + } + + id = x_allocate_bitmap_record (f); + dpyinfo->bitmaps[id - 1].pixmap = bitmap; + dpyinfo->bitmaps[id - 1].have_mask = 1; + dpyinfo->bitmaps[id - 1].mask = mask; + dpyinfo->bitmaps[id - 1].file = NULL; + dpyinfo->bitmaps[id - 1].height = attrs.height; + dpyinfo->bitmaps[id - 1].width = attrs.width; + dpyinfo->bitmaps[id - 1].depth = attrs.depth; + dpyinfo->bitmaps[id - 1].refcount = 1; + + XpmFreeAttributes (&attrs); + return id; +} +#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */ + /* Load image IMG which will be displayed on frame F. Value is non-zero if successful. */ @@ -3745,6 +3806,9 @@ xpm_load (f, img) attrs.valuemask |= XpmCloseness; #endif /* not XpmAllocCloseColors */ #endif /* ALLOC_XPM_COLORS */ +#ifdef ALLOC_XPM_COLORS + xpm_init_color_cache (f, &attrs); +#endif /* If image specification contains symbolic color definitions, add these to `attrs'. */ @@ -4190,6 +4254,13 @@ xpm_load_image (f, img, contents, end) || width <= 0 || height <= 0 || num_colors <= 0 || chars_per_pixel <= 0) goto failure; + + if (!check_image_size (f, width, height)) + { + image_error ("Invalid image size", Qnil, Qnil); + goto failure; + } + expect (','); XSETFRAME (frame, f); @@ -7709,6 +7780,9 @@ gif_load (f, img) specified_file = image_spec_value (img->spec, QCfile, NULL); specified_data = image_spec_value (img->spec, QCdata, NULL); + /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */ + EnterMovies (); + if (NILP (specified_data)) { /* Read from a file */ @@ -8431,13 +8505,9 @@ meaning don't clear the cache. */); void init_image () { -#ifdef MAC_OS - /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */ - EnterMovies (); -#ifdef MAC_OSX +#if defined (MAC_OSX) && TARGET_API_MAC_CARBON init_image_func_pointer (); #endif -#endif } /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9 diff --git a/src/indent.c b/src/indent.c index 8921361afd8..62ef3766682 100644 --- a/src/indent.c +++ b/src/indent.c @@ -2074,7 +2074,7 @@ whether or not it is currently displayed in some window. */) { int it_start; int oselective; - int start_on_image_p; + int start_on_image_or_stretch_p; SET_TEXT_POS (pt, PT, PT_BYTE); start_display (&it, w, pt); @@ -2086,7 +2086,8 @@ whether or not it is currently displayed in some window. */) while the end position is really at some X > 0, the same X that PT had. */ it_start = IT_CHARPOS (it); - start_on_image_p = (it.method == GET_FROM_IMAGE); + start_on_image_or_stretch_p = (it.method == GET_FROM_IMAGE + || it.method == GET_FROM_STRETCH); reseat_at_previous_visible_line_start (&it); it.current_x = it.hpos = 0; /* Temporarily disable selective display so we don't move too far */ @@ -2097,9 +2098,10 @@ whether or not it is currently displayed in some window. */) /* Move back if we got too far. This may happen if truncate-lines is on and PT is beyond right margin. - It may also happen if it_start is on an image -- - in that case, don't go back. */ - if (IT_CHARPOS (it) > it_start && XINT (lines) > 0 && !start_on_image_p) + It may also happen if it_start is on an image or a stretch + glyph -- in that case, don't go back. */ + if (IT_CHARPOS (it) > it_start && XINT (lines) > 0 + && !start_on_image_or_stretch_p) move_it_by_lines (&it, -1, 0); it.vpos = 0; diff --git a/src/insdel.c b/src/insdel.c index 2a11f5abe7f..174c0c6a153 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -738,9 +738,10 @@ insert (string, nbytes) { if (nbytes > 0) { - int opoint = PT; - insert_1 (string, nbytes, 0, 1, 0); - signal_after_change (opoint, 0, PT - opoint); + int len = chars_in_text (string, nbytes), opoint; + insert_1_both (string, len, nbytes, 0, 1, 0); + opoint = PT - len; + signal_after_change (opoint, 0, len); update_compositions (opoint, PT, CHECK_BORDER); } } @@ -754,9 +755,10 @@ insert_and_inherit (string, nbytes) { if (nbytes > 0) { - int opoint = PT; - insert_1 (string, nbytes, 1, 1, 0); - signal_after_change (opoint, 0, PT - opoint); + int len = chars_in_text (string, nbytes), opoint; + insert_1_both (string, len, nbytes, 1, 1, 0); + opoint = PT - len; + signal_after_change (opoint, 0, len); update_compositions (opoint, PT, CHECK_BORDER); } } @@ -802,10 +804,10 @@ insert_before_markers (string, nbytes) { if (nbytes > 0) { - int opoint = PT; - - insert_1 (string, nbytes, 0, 1, 1); - signal_after_change (opoint, 0, PT - opoint); + int len = chars_in_text (string, nbytes), opoint; + insert_1_both (string, len, nbytes, 0, 1, 1); + opoint = PT - len; + signal_after_change (opoint, 0, len); update_compositions (opoint, PT, CHECK_BORDER); } } @@ -819,10 +821,10 @@ insert_before_markers_and_inherit (string, nbytes) { if (nbytes > 0) { - int opoint = PT; - - insert_1 (string, nbytes, 1, 1, 1); - signal_after_change (opoint, 0, PT - opoint); + int len = chars_in_text (string, nbytes), opoint; + insert_1_both (string, len, nbytes, 1, 1, 1); + opoint = PT - len; + signal_after_change (opoint, 0, len); update_compositions (opoint, PT, CHECK_BORDER); } } diff --git a/src/keyboard.c b/src/keyboard.c index 5467d5ff903..07a0deaf828 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -381,12 +381,15 @@ Lisp_Object real_this_command; command is stored in this-original-command. It is nil otherwise. */ Lisp_Object Vthis_original_command; -/* The value of point when the last command was executed. */ +/* The value of point when the last command was started. */ int last_point_position; /* The buffer that was current when the last command was started. */ Lisp_Object last_point_position_buffer; +/* The window that was selected when the last command was started. */ +Lisp_Object last_point_position_window; + /* The frame in which the last input event occurred, or Qmacro if the last event came from a macro. We use this to determine when to generate switch-frame events. This may be cleared by functions @@ -527,6 +530,9 @@ Lisp_Object Qlanguage_change; #endif Lisp_Object Qdrag_n_drop; Lisp_Object Qsave_session; +#ifdef MAC_OS +Lisp_Object Qmac_apple_event; +#endif /* Lisp_Object Qmouse_movement; - also an event header */ @@ -1441,8 +1447,6 @@ command_loop_1 () safe_run_hooks (Qdeferred_action_function); } - Vmemory_full = Qnil; - /* Do this after running Vpost_command_hook, for consistency. */ current_kboard->Vlast_command = Vthis_command; current_kboard->Vreal_last_command = real_this_command; @@ -1580,6 +1584,7 @@ command_loop_1 () prev_buffer = current_buffer; prev_modiff = MODIFF; last_point_position = PT; + last_point_position_window = selected_window; XSETBUFFER (last_point_position_buffer, prev_buffer); /* By default, we adjust point to a boundary of a region that @@ -5803,14 +5808,8 @@ make_lispy_event (event) Lisp_Object head, position; Lisp_Object files; - /* The frame_or_window field should be a cons of the frame in - which the event occurred and a list of the filenames - dropped. */ - if (! CONSP (event->frame_or_window)) - abort (); - - f = XFRAME (XCAR (event->frame_or_window)); - files = XCDR (event->frame_or_window); + f = XFRAME (event->frame_or_window); + files = event->arg; /* Ignore mouse events that were made on frames that have been deleted. */ @@ -5865,6 +5864,20 @@ make_lispy_event (event) case SAVE_SESSION_EVENT: return Qsave_session; +#ifdef MAC_OS + case MAC_APPLE_EVENT: + { + Lisp_Object spec[2]; + + spec[0] = event->x; + spec[1] = event->y; + return Fcons (Qmac_apple_event, + Fcons (Fvector (2, spec), + Fcons (mac_make_lispy_event_code (event->code), + Qnil))); + } +#endif + /* The 'kind' field of the event is something we don't recognize. */ default: abort (); @@ -10879,6 +10892,11 @@ syms_of_keyboard () Qsave_session = intern ("save-session"); staticpro (&Qsave_session); +#ifdef MAC_OS + Qmac_apple_event = intern ("mac-apple-event"); + staticpro (&Qmac_apple_event); +#endif + Qusr1_signal = intern ("usr1-signal"); staticpro (&Qusr1_signal); Qusr2_signal = intern ("usr2-signal"); @@ -10969,6 +10987,7 @@ syms_of_keyboard () Fset (Qinput_method_use_echo_area, Qnil); last_point_position_buffer = Qnil; + last_point_position_window = Qnil; { struct event_head *p; diff --git a/src/keyboard.h b/src/keyboard.h index afda1c00a92..913f48ee64e 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -301,7 +301,6 @@ extern Lisp_Object read_char P_ ((int, int, Lisp_Object *, Lisp_Object, int *)); /* User-supplied string to translate input characters through. */ extern Lisp_Object Vkeyboard_translate_table; - extern int parse_menu_item P_ ((Lisp_Object, int, int)); extern void echo_now P_ ((void)); diff --git a/src/keymap.c b/src/keymap.c index 271b0672b1e..07bf957cdca 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -66,6 +66,13 @@ Lisp_Object Vminibuffer_local_ns_map; /* was MinibufLocalCompletionMap */ Lisp_Object Vminibuffer_local_completion_map; +/* keymap used for minibuffers when doing completion in filenames */ +Lisp_Object Vminibuffer_local_filename_completion_map; + +/* keymap used for minibuffers when doing completion in filenames + with require-match*/ +Lisp_Object Vminibuffer_local_must_match_filename_map; + /* keymap used for minibuffers when doing completion and require a match */ /* was MinibufLocalMustMatchMap */ Lisp_Object Vminibuffer_local_must_match_map; @@ -390,6 +397,7 @@ Return PARENT. PARENT should be nil or another keymap. */) if (EQ (XCDR (prev), parent)) RETURN_UNGCPRO (parent); + CHECK_IMPURE (prev); XSETCDR (prev, parent); break; } @@ -886,6 +894,7 @@ store_in_keymap (keymap, idx, def) { if (NATNUMP (idx) && XFASTINT (idx) < ASIZE (elt)) { + CHECK_IMPURE (elt); ASET (elt, XFASTINT (idx), def); return def; } @@ -929,6 +938,7 @@ store_in_keymap (keymap, idx, def) { if (EQ (idx, XCAR (elt))) { + CHECK_IMPURE (elt); XSETCDR (elt, def); return def; } @@ -972,6 +982,7 @@ store_in_keymap (keymap, idx, def) } else elt = Fcons (idx, def); + CHECK_IMPURE (insertion_point); XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point))); } } @@ -1243,7 +1254,7 @@ A number as value means KEY is "too long"; that is, characters or symbols in it except for the last one fail to be a valid sequence of prefix characters in KEYMAP. The number is how many characters at the front of KEY -it takes to reach a non-prefix command. +it takes to reach a non-prefix key. Normally, `lookup-key' ignores bindings for t, which act as default bindings, used when nothing else in the keymap applies; this makes it @@ -2368,7 +2379,14 @@ shadow_lookup (shadow, key, flag) for (tail = shadow; CONSP (tail); tail = XCDR (tail)) { value = Flookup_key (XCAR (tail), key, flag); - if (!NILP (value) && !NATNUMP (value)) + if (NATNUMP (value)) + { + value = Flookup_key (XCAR (tail), + Fsubstring (key, make_number (0), value), flag); + if (!NILP (value)) + return Qnil; + } + else if (!NILP (value)) return value; } return Qnil; @@ -3175,6 +3193,34 @@ describe_translation (definition, args) insert_string ("??\n"); } +/* describe_map puts all the usable elements of a sparse keymap + into an array of `struct describe_map_elt', + then sorts them by the events. */ + +struct describe_map_elt { Lisp_Object event; Lisp_Object definition; int shadowed; }; + +/* qsort comparison function for sorting `struct describe_map_elt' by + the event field. */ + +static int +describe_map_compare (aa, bb) + const void *aa, *bb; +{ + const struct describe_map_elt *a = aa, *b = bb; + if (INTEGERP (a->event) && INTEGERP (b->event)) + return ((XINT (a->event) > XINT (b->event)) + - (XINT (a->event) < XINT (b->event))); + if (!INTEGERP (a->event) && INTEGERP (b->event)) + return 1; + if (INTEGERP (a->event) && !INTEGERP (b->event)) + return -1; + if (SYMBOLP (a->event) && SYMBOLP (b->event)) + return (!NILP (Fstring_lessp (a->event, b->event)) ? -1 + : !NILP (Fstring_lessp (b->event, a->event)) ? 1 + : 0); + return 0; +} + /* Describe the contents of map MAP, assuming that this map itself is reached by the sequence of prefix keys PREFIX (a string or vector). PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */ @@ -3198,6 +3244,13 @@ describe_map (map, prefix, elt_describer, partial, shadow, int first = 1; struct gcpro gcpro1, gcpro2, gcpro3; + /* These accumulate the values from sparse keymap bindings, + so we can sort them and handle them in order. */ + int length_needed = 0; + struct describe_map_elt *vect; + int slots_used = 0; + int i; + suppress = Qnil; if (partial) @@ -3209,6 +3262,12 @@ describe_map (map, prefix, elt_describer, partial, shadow, kludge = Fmake_vector (make_number (1), Qnil); definition = Qnil; + for (tail = map; CONSP (tail); tail = XCDR (tail)) + length_needed++; + + vect = ((struct describe_map_elt *) + alloca (sizeof (struct describe_map_elt) * length_needed)); + GCPRO3 (prefix, definition, kludge); for (tail = map; CONSP (tail); tail = XCDR (tail)) @@ -3223,6 +3282,7 @@ describe_map (map, prefix, elt_describer, partial, shadow, else if (CONSP (XCAR (tail))) { int this_shadowed = 0; + event = XCAR (XCAR (tail)); /* Ignore bindings whose "prefix" are not really valid events. @@ -3263,27 +3323,10 @@ describe_map (map, prefix, elt_describer, partial, shadow, tem = Flookup_key (map, kludge, Qt); if (!EQ (tem, definition)) continue; - if (first) - { - previous_description_column = 0; - insert ("\n", 1); - first = 0; - } - - /* THIS gets the string to describe the character EVENT. */ - insert1 (Fkey_description (kludge, prefix)); - - /* Print a description of the definition of this character. - elt_describer will take care of spacing out far enough - for alignment purposes. */ - (*elt_describer) (definition, Qnil); - - if (this_shadowed) - { - SET_PT (PT - 1); - insert_string (" (binding currently shadowed)"); - SET_PT (PT + 1); - } + vect[slots_used].event = event; + vect[slots_used].definition = definition; + vect[slots_used].shadowed = this_shadowed; + slots_used++; } else if (EQ (XCAR (tail), Qkeymap)) { @@ -3297,6 +3340,68 @@ describe_map (map, prefix, elt_describer, partial, shadow, } } + /* If we found some sparse map events, sort them. */ + + qsort (vect, slots_used, sizeof (struct describe_map_elt), + describe_map_compare); + + /* Now output them in sorted order. */ + + for (i = 0; i < slots_used; i++) + { + Lisp_Object start, end; + + if (first) + { + previous_description_column = 0; + insert ("\n", 1); + first = 0; + } + + ASET (kludge, 0, vect[i].event); + start = vect[i].event; + end = start; + + definition = vect[i].definition; + + /* Find consecutive chars that are identically defined. */ + if (INTEGERP (vect[i].event)) + { + while (i + 1 < slots_used + && XINT (vect[i + 1].event) == XINT (vect[i].event) + 1 + && !NILP (Fequal (vect[i + 1].definition, definition)) + && vect[i].shadowed == vect[i + 1].shadowed) + i++; + end = vect[i].event; + } + + /* Now START .. END is the range to describe next. */ + + /* Insert the string to describe the event START. */ + insert1 (Fkey_description (kludge, prefix)); + + if (!EQ (start, end)) + { + insert (" .. ", 4); + + ASET (kludge, 0, end); + /* Insert the string to describe the character END. */ + insert1 (Fkey_description (kludge, prefix)); + } + + /* Print a description of the definition of this character. + elt_describer will take care of spacing out far enough + for alignment purposes. */ + (*elt_describer) (vect[i].definition, Qnil); + + if (vect[i].shadowed) + { + SET_PT (PT - 1); + insert_string (" (binding currently shadowed)"); + SET_PT (PT + 1); + } + } + UNGCPRO; } @@ -3646,12 +3751,27 @@ don't alter it yourself. */); Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil); Fset_keymap_parent (Vminibuffer_local_completion_map, Vminibuffer_local_map); + DEFVAR_LISP ("minibuffer-local-filename-completion-map", + &Vminibuffer_local_filename_completion_map, + doc: /* Local keymap for minibuffer input with completion for filenames. */); + Vminibuffer_local_filename_completion_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_filename_completion_map, + Vminibuffer_local_completion_map); + + DEFVAR_LISP ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map, doc: /* Local keymap for minibuffer input with completion, for exact match. */); Vminibuffer_local_must_match_map = Fmake_sparse_keymap (Qnil); Fset_keymap_parent (Vminibuffer_local_must_match_map, Vminibuffer_local_completion_map); + DEFVAR_LISP ("minibuffer-local-must-match-filename-map", + &Vminibuffer_local_must_match_filename_map, + doc: /* Local keymap for minibuffer input with completion for filenames with exact match. */); + Vminibuffer_local_must_match_filename_map = Fmake_sparse_keymap (Qnil); + Fset_keymap_parent (Vminibuffer_local_must_match_filename_map, + Vminibuffer_local_must_match_map); + DEFVAR_LISP ("minor-mode-map-alist", &Vminor_mode_map_alist, doc: /* Alist of keymaps to use for minor modes. Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read @@ -3678,9 +3798,9 @@ the same way. The "active" keymaps in each alist are used before DEFVAR_LISP ("function-key-map", &Vfunction_key_map, - doc: /* Keymap mapping ASCII function key sequences onto their preferred forms. -This allows Emacs to recognize function keys sent from ASCII -terminals at any point in a key sequence. + doc: /* Keymap that translates key sequences to key sequences during input. +This is used mainly for mapping ASCII function key sequences into +real Emacs function key events (symbols). The `read-key-sequence' function replaces any subsequence bound by `function-key-map' with its binding. More precisely, when the active @@ -3689,6 +3809,9 @@ keymaps have no binding for the current key sequence but `read-key-sequence' replaces the matching suffix with its binding, and continues with the new sequence. +If the binding is a function, it is called with one argument (the prompt) +and its return value (a key sequence) is used. + The events that come from bindings in `function-key-map' are not themselves looked up in `function-key-map'. diff --git a/src/lisp.h b/src/lisp.h index 1cefd7ba4b5..a80f76ddd8e 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -253,7 +253,7 @@ LISP_MAKE_RVALUE (Lisp_Object o) /* If union type is not wanted, define Lisp_Object as just a number. */ #ifdef NO_UNION_TYPE -#define Lisp_Object EMACS_INT +typedef EMACS_INT Lisp_Object; #define LISP_MAKE_RVALUE(o) (0+(o)) #endif /* NO_UNION_TYPE */ @@ -455,7 +455,7 @@ enum pvec_type extern Lisp_Object make_number P_ ((EMACS_INT)); #endif -#define EQ(x, y) ((x).s.val == (y).s.val && (x).s.type == (y).s.type) +#define EQ(x, y) ((x).i == (y).i) #endif /* NO_UNION_TYPE */ @@ -603,9 +603,19 @@ struct Lisp_Cons /* Please do not use the names of these elements in code other than the core lisp implementation. Use XCAR and XCDR below. */ #ifdef HIDE_LISP_IMPLEMENTATION - Lisp_Object car_, cdr_; + Lisp_Object car_; + union + { + Lisp_Object cdr_; + struct Lisp_Cons *chain; + } u; #else - Lisp_Object car, cdr; + Lisp_Object car; + union + { + Lisp_Object cdr; + struct Lisp_Cons *chain; + } u; #endif }; @@ -618,10 +628,10 @@ struct Lisp_Cons invalidated at arbitrary points.) */ #ifdef HIDE_LISP_IMPLEMENTATION #define XCAR_AS_LVALUE(c) (XCONS ((c))->car_) -#define XCDR_AS_LVALUE(c) (XCONS ((c))->cdr_) +#define XCDR_AS_LVALUE(c) (XCONS ((c))->u.cdr_) #else #define XCAR_AS_LVALUE(c) (XCONS ((c))->car) -#define XCDR_AS_LVALUE(c) (XCONS ((c))->cdr) +#define XCDR_AS_LVALUE(c) (XCONS ((c))->u.cdr) #endif /* Use these from normal code. */ @@ -1271,17 +1281,21 @@ union Lisp_Misc /* Lisp floating point type */ struct Lisp_Float { + union + { #ifdef HIDE_LISP_IMPLEMENTATION - double data_; + double data_; #else - double data; + double data; #endif + struct Lisp_Float *chain; + } u; }; #ifdef HIDE_LISP_IMPLEMENTATION -#define XFLOAT_DATA(f) (XFLOAT (f)->data_) +#define XFLOAT_DATA(f) (XFLOAT (f)->u.data_) #else -#define XFLOAT_DATA(f) (XFLOAT (f)->data) +#define XFLOAT_DATA(f) (XFLOAT (f)->u.data) #endif /* A character, declared with the following typedef, is a member @@ -1892,6 +1906,8 @@ extern EMACS_INT gc_cons_threshold; extern EMACS_INT gc_relative_threshold; +extern EMACS_INT memory_full_cons_threshold; + /* Structure for recording stack slots that need marking. */ /* This is a chain of structures, each of which points at a Lisp_Object variable @@ -2557,6 +2573,7 @@ extern void init_alloc_once P_ ((void)); extern void init_alloc P_ ((void)); extern void syms_of_alloc P_ ((void)); extern struct buffer * allocate_buffer P_ ((void)); +extern int valid_lisp_object_p P_ ((Lisp_Object)); /* Defined in chartab.c */ EXFUN (Fmake_char_table, 2); @@ -2699,6 +2716,7 @@ extern Lisp_Object call6 P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object EXFUN (Fdo_auto_save, 2); extern Lisp_Object apply_lambda P_ ((Lisp_Object, Lisp_Object, int)); extern Lisp_Object internal_catch P_ ((Lisp_Object, Lisp_Object (*) (Lisp_Object), Lisp_Object)); +extern Lisp_Object internal_lisp_condition_case P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); extern Lisp_Object internal_condition_case P_ ((Lisp_Object (*) (void), Lisp_Object, Lisp_Object (*) (Lisp_Object))); extern Lisp_Object internal_condition_case_1 P_ ((Lisp_Object (*) (Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object))); extern Lisp_Object internal_condition_case_2 P_ ((Lisp_Object (*) (int, Lisp_Object *), int, Lisp_Object *, Lisp_Object, Lisp_Object (*) (Lisp_Object))); diff --git a/src/lread.c b/src/lread.c index 5778a9d3a0c..7a4437350b1 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1392,33 +1392,34 @@ openp (path, str, suffixes, storeptr, predicate) /* Merge the list we've accumulated of globals from the current input source into the load_history variable. The details depend on whether - the source has an associated file name or not. */ + the source has an associated file name or not. + + FILENAME is the file name that we are loading from. + ENTIRE is 1 if loading that entire file, 0 if evaluating part of it. */ static void -build_load_history (stream, source) - FILE *stream; - Lisp_Object source; +build_load_history (filename, entire) + Lisp_Object filename; + int entire; { register Lisp_Object tail, prev, newelt; register Lisp_Object tem, tem2; - register int foundit, loading; - - loading = stream || !NARROWED; + register int foundit = 0; tail = Vload_history; prev = Qnil; - foundit = 0; + while (CONSP (tail)) { tem = XCAR (tail); /* Find the feature's previous assoc list... */ - if (!NILP (Fequal (source, Fcar (tem)))) + if (!NILP (Fequal (filename, Fcar (tem)))) { foundit = 1; - /* If we're loading, remove it. */ - if (loading) + /* If we're loading the entire file, remove old data. */ + if (entire) { if (NILP (prev)) Vload_history = XCDR (tail); @@ -1450,10 +1451,10 @@ build_load_history (stream, source) QUIT; } - /* If we're loading, cons the new assoc onto the front of load-history, - the most-recently-loaded position. Also do this if we didn't find - an existing member for the current source. */ - if (loading || !foundit) + /* If we're loading an entire file, cons the new assoc onto the + front of load-history, the most-recently-loaded position. Also + do this if we didn't find an existing member for the file. */ + if (entire || !foundit) Vload_history = Fcons (Fnreverse (Vcurrent_load_list), Vload_history); } @@ -1509,21 +1510,32 @@ readevalloop (readcharfun, stream, sourcename, evalfun, register int c; register Lisp_Object val; int count = SPECPDL_INDEX (); - struct gcpro gcpro1; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; struct buffer *b = 0; + int bpos; int continue_reading_p; + /* Nonzero if reading an entire buffer. */ + int whole_buffer = 0; + /* 1 on the first time around. */ + int first_sexp = 1; + + if (MARKERP (readcharfun)) + { + if (NILP (start)) + start = readcharfun; + } if (BUFFERP (readcharfun)) b = XBUFFER (readcharfun); else if (MARKERP (readcharfun)) b = XMARKER (readcharfun)->buffer; - specbind (Qstandard_input, readcharfun); + specbind (Qstandard_input, readcharfun); /* GCPROs readcharfun. */ specbind (Qcurrent_load_list, Qnil); record_unwind_protect (readevalloop_1, load_convert_to_unibyte ? Qt : Qnil); load_convert_to_unibyte = !NILP (unibyte); - GCPRO1 (sourcename); + GCPRO4 (sourcename, readfun, start, end); LOADHIST_ATTACH (sourcename); @@ -1537,12 +1549,32 @@ readevalloop (readcharfun, stream, sourcename, evalfun, if (!NILP (start)) { + /* Switch to the buffer we are reading from. */ record_unwind_protect (save_excursion_restore, save_excursion_save ()); + set_buffer_internal (b); + + /* Save point in it. */ + record_unwind_protect (save_excursion_restore, save_excursion_save ()); + /* Save ZV in it. */ record_unwind_protect (save_restriction_restore, save_restriction_save ()); + /* Those get unbound after we read one expression. */ + + /* Set point and ZV around stuff to be read. */ Fgoto_char (start); - Fnarrow_to_region (make_number (BEGV), end); + if (!NILP (end)) + Fnarrow_to_region (make_number (BEGV), end); + + /* Just for cleanliness, convert END to a marker + if it is an integer. */ + if (INTEGERP (end)) + end = Fpoint_max_marker (); } + /* On the first cycle, we can easily test here + whether we are reading the whole buffer. */ + if (b && first_sexp) + whole_buffer = (PT == BEG && ZV == Z); + instream = stream; read_next: c = READCHAR; @@ -1592,8 +1624,11 @@ readevalloop (readcharfun, stream, sourcename, evalfun, if (!NILP (start) && continue_reading_p) start = Fpoint_marker (); + + /* Restore saved point and BEGV. */ unbind_to (count1, Qnil); + /* Now eval what we just read. */ val = (*evalfun) (val); if (printflag) @@ -1604,9 +1639,13 @@ readevalloop (readcharfun, stream, sourcename, evalfun, else Fprint (val, Qnil); } + + first_sexp = 0; } - build_load_history (stream, sourcename); + build_load_history (sourcename, + stream || whole_buffer); + UNGCPRO; unbind_to (count, Qnil); @@ -1893,13 +1932,12 @@ read_escape (readcharfun, stringp) return c | alt_modifier; case 's': - if (stringp) - return ' '; c = READCHAR; - if (c != '-') { - UNREAD (c); - return ' '; - } + if (c != '-') + { + UNREAD (c); + return ' '; + } c = READCHAR; if (c == '\\') c = read_escape (readcharfun, 0); @@ -4035,8 +4073,8 @@ An element `(t . SYMBOL)' precedes an entry `(defun . FUNCTION)', and means that SYMBOL was an autoload before this file redefined it as a function. -For a preloaded file, the file name recorded is relative to the main Lisp -directory. These names are converted to absolute by `file-loadhist-lookup'. */); +During preloading, the file name recorded is relative to the main Lisp +directory. These file names are converted to absolute at startup. */); Vload_history = Qnil; DEFVAR_LISP ("load-file-name", &Vload_file_name, diff --git a/src/m/amdx86-64.h b/src/m/amdx86-64.h index 2d7d86ce7c3..14ddd16406e 100644 --- a/src/m/amdx86-64.h +++ b/src/m/amdx86-64.h @@ -100,11 +100,38 @@ Boston, MA 02110-1301, USA. */ /* Define XPNTR to avoid or'ing with DATA_SEG_BITS */ #undef DATA_SEG_BITS +#ifdef __FreeBSD__ + +/* The libraries for binaries native to the build host's architecture are + installed under /usr/lib in FreeBSD, and the ones that need special paths + are 32-bit compatibility libraries (installed under /usr/lib32). To build + a native binary of Emacs on FreeBSD/amd64 we can just point to /usr/lib. */ + +#undef START_FILES +#define START_FILES pre-crt0.o /usr/lib/crt1.o /usr/lib/crti.o + +/* The duplicate -lgcc is intentional in the definition of LIB_STANDARD. + The reason is that some functions in libgcc.a call functions from libc.a, + and some libc.a functions need functions from libgcc.a. Since most + versions of ld are one-pass linkers, we need to mention -lgcc twice, + or else we risk getting unresolved externals. */ +#undef LIB_STANDARD +#define LIB_STANDARD -lgcc -lc -lgcc /usr/lib/crtn.o + +#else /* !__FreeBSD__ */ + #undef START_FILES #define START_FILES pre-crt0.o /usr/lib64/crt1.o /usr/lib64/crti.o +/* The duplicate -lgcc is intentional in the definition of LIB_STANDARD. + The reason is that some functions in libgcc.a call functions from libc.a, + and some libc.a functions need functions from libgcc.a. Since most + versions of ld are one-pass linkers, we need to mention -lgcc twice, + or else we risk getting unresolved externals. */ #undef LIB_STANDARD #define LIB_STANDARD -lgcc -lc -lgcc /usr/lib64/crtn.o +#endif /* __FreeBSD__ */ + /* arch-tag: 8a5e001d-e12e-4692-a3a6-0b15ba271c6e (do not change this comment) */ diff --git a/src/m/gould.h b/src/m/gould.h index 3a382ca0c1b..a9168009d47 100644 --- a/src/m/gould.h +++ b/src/m/gould.h @@ -5,7 +5,7 @@ * RELEASE2_1 in config.h. This may also be necessary with un-updated * official releases of 2.1 - Copyright (C) 1986, 2002 Free Software Foundation, Inc. + Copyright (C) 1986, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/mac.c b/src/mac.c index 4c8e78ade25..5a56bd57817 100644 --- a/src/mac.c +++ b/src/mac.c @@ -79,6 +79,8 @@ static ComponentInstance as_scripting_component; /* The single script context used for all script executions. */ static OSAID as_script_context; +static OSErr posix_pathname_to_fsspec P_ ((const char *, FSSpec *)); +static OSErr fsspec_to_posix_pathname P_ ((const FSSpec *, char *, int)); /* When converting from Mac to Unix pathnames, /'s in folder names are converted to :'s. This function, used in copying folder names, @@ -259,13 +261,454 @@ posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen) /*********************************************************************** + Conversions on Apple event objects + ***********************************************************************/ + +static Lisp_Object Qundecoded_file_name; + +static Lisp_Object +mac_aelist_to_lisp (desc_list) + AEDescList *desc_list; +{ + OSErr err; + long count; + Lisp_Object result, elem; + DescType desc_type; + Size size; + AEKeyword keyword; + AEDesc desc; + + err = AECountItems (desc_list, &count); + if (err != noErr) + return Qnil; + result = Qnil; + while (count > 0) + { + err = AESizeOfNthItem (desc_list, count, &desc_type, &size); + if (err == noErr) + switch (desc_type) + { + case typeAEList: + case typeAERecord: + case typeAppleEvent: + err = AEGetNthDesc (desc_list, count, typeWildCard, + &keyword, &desc); + if (err != noErr) + break; + elem = mac_aelist_to_lisp (&desc); + AEDisposeDesc (&desc); + break; + + default: + if (desc_type == typeNull) + elem = Qnil; + else + { + elem = make_uninit_string (size); + err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword, + &desc_type, SDATA (elem), size, &size); + } + if (err != noErr) + break; + desc_type = EndianU32_NtoB (desc_type); + elem = Fcons (make_unibyte_string ((char *) &desc_type, 4), elem); + break; + } + + if (err != noErr) + elem = Qnil; + else if (desc_list->descriptorType != typeAEList) + { + keyword = EndianU32_NtoB (keyword); + elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem); + } + + result = Fcons (elem, result); + count--; + } + + desc_type = EndianU32_NtoB (desc_list->descriptorType); + return Fcons (make_unibyte_string ((char *) &desc_type, 4), result); +} + +Lisp_Object +mac_aedesc_to_lisp (desc) + AEDesc *desc; +{ + OSErr err = noErr; + DescType desc_type = desc->descriptorType; + Lisp_Object result; + + switch (desc_type) + { + case typeNull: + result = Qnil; + break; + + case typeAEList: + case typeAERecord: + case typeAppleEvent: + return mac_aelist_to_lisp (desc); +#if 0 + /* The following one is much simpler, but creates and disposes + of Apple event descriptors many times. */ + { + long count; + Lisp_Object elem; + AEKeyword keyword; + AEDesc desc1; + + err = AECountItems (desc, &count); + if (err != noErr) + break; + result = Qnil; + while (count > 0) + { + err = AEGetNthDesc (desc, count, typeWildCard, &keyword, &desc1); + if (err != noErr) + break; + elem = mac_aedesc_to_lisp (&desc1); + AEDisposeDesc (&desc1); + if (desc_type != typeAEList) + { + keyword = EndianU32_NtoB (keyword); + elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem); + } + result = Fcons (elem, result); + count--; + } + } +#endif + break; + + default: +#if TARGET_API_MAC_CARBON + result = make_uninit_string (AEGetDescDataSize (desc)); + err = AEGetDescData (desc, SDATA (result), SBYTES (result)); +#else + result = make_uninit_string (GetHandleSize (desc->dataHandle)); + memcpy (SDATA (result), *(desc->dataHandle), SBYTES (result)); +#endif + break; + } + + if (err != noErr) + return Qnil; + + desc_type = EndianU32_NtoB (desc_type); + return Fcons (make_unibyte_string ((char *) &desc_type, 4), result); +} + +static pascal OSErr +mac_coerce_file_name_ptr (type_code, data_ptr, data_size, + to_type, handler_refcon, result) + DescType type_code; + const void *data_ptr; + Size data_size; + DescType to_type; + long handler_refcon; + AEDesc *result; +{ + OSErr err; + + if (type_code == typeNull) + err = errAECoercionFail; + else if (type_code == to_type || to_type == typeWildCard) + err = AECreateDesc (TYPE_FILE_NAME, data_ptr, data_size, result); + else if (type_code == TYPE_FILE_NAME) + /* Coercion from undecoded file name. */ + { +#ifdef MAC_OSX + CFStringRef str; + CFURLRef url = NULL; + CFDataRef data = NULL; + + str = CFStringCreateWithBytes (NULL, data_ptr, data_size, + kCFStringEncodingUTF8, false); + if (str) + { + url = CFURLCreateWithFileSystemPath (NULL, str, + kCFURLPOSIXPathStyle, false); + CFRelease (str); + } + if (url) + { + data = CFURLCreateData (NULL, url, kCFStringEncodingUTF8, true); + CFRelease (url); + } + if (data) + { + err = AECoercePtr (typeFileURL, CFDataGetBytePtr (data), + CFDataGetLength (data), to_type, result); + CFRelease (data); + } + else + err = memFullErr; +#else + FSSpec fs; + char *buf; + + buf = xmalloc (data_size + 1); + if (buf) + { + memcpy (buf, data_ptr, data_size); + buf[data_size] = '\0'; + err = posix_pathname_to_fsspec (buf, &fs); + xfree (buf); + } + else + err = memFullErr; + if (err == noErr) + err = AECoercePtr (typeFSS, &fs, sizeof (FSSpec), to_type, result); +#endif + } + else if (to_type == TYPE_FILE_NAME) + /* Coercion to undecoded file name. */ + { +#ifdef MAC_OSX + CFURLRef url = NULL; + CFStringRef str = NULL; + CFDataRef data = NULL; + + if (type_code == typeFileURL) + url = CFURLCreateWithBytes (NULL, data_ptr, data_size, + kCFStringEncodingUTF8, NULL); + else + { + AEDesc desc; + Size size; + char *buf; + + err = AECoercePtr (type_code, data_ptr, data_size, + typeFileURL, &desc); + if (err == noErr) + { + size = AEGetDescDataSize (&desc); + buf = xmalloc (size); + if (buf) + { + err = AEGetDescData (&desc, buf, size); + if (err == noErr) + url = CFURLCreateWithBytes (NULL, buf, size, + kCFStringEncodingUTF8, NULL); + xfree (buf); + } + AEDisposeDesc (&desc); + } + } + if (url) + { + str = CFURLCopyFileSystemPath (url, kCFURLPOSIXPathStyle); + CFRelease (url); + } + if (str) + { + data = CFStringCreateExternalRepresentation (NULL, str, + kCFStringEncodingUTF8, + '\0'); + CFRelease (str); + } + if (data) + { + err = AECreateDesc (TYPE_FILE_NAME, CFDataGetBytePtr (data), + CFDataGetLength (data), result); + CFRelease (data); + } +#else + char file_name[MAXPATHLEN]; + + if (type_code == typeFSS && data_size == sizeof (FSSpec)) + err = fsspec_to_posix_pathname (data_ptr, file_name, + sizeof (file_name) - 1); + else + { + AEDesc desc; + FSSpec fs; + + err = AECoercePtr (type_code, data_ptr, data_size, typeFSS, &desc); + if (err == noErr) + { +#if TARGET_API_MAC_CARBON + err = AEGetDescData (&desc, &fs, sizeof (FSSpec)); +#else + fs = *(FSSpec *)(*(desc.dataHandle)); +#endif + if (err == noErr) + err = fsspec_to_posix_pathname (&fs, file_name, + sizeof (file_name) - 1); + AEDisposeDesc (&desc); + } + } + if (err == noErr) + err = AECreateDesc (TYPE_FILE_NAME, file_name, + strlen (file_name), result); +#endif + } + else + abort (); + + if (err != noErr) + return errAECoercionFail; + return noErr; +} + +static pascal OSErr +mac_coerce_file_name_desc (from_desc, to_type, handler_refcon, result) + const AEDesc *from_desc; + DescType to_type; + long handler_refcon; + AEDesc *result; +{ + OSErr err = noErr; + DescType from_type = from_desc->descriptorType; + + if (from_type == typeNull) + err = errAECoercionFail; + else if (from_type == to_type || to_type == typeWildCard) + err = AEDuplicateDesc (from_desc, result); + else + { + char *data_ptr; + Size data_size; + +#if TARGET_API_MAC_CARBON + data_size = AEGetDescDataSize (from_desc); +#else + data_size = GetHandleSize (from_desc->dataHandle); +#endif + data_ptr = xmalloc (data_size); + if (data_ptr) + { +#if TARGET_API_MAC_CARBON + err = AEGetDescData (from_desc, data_ptr, data_size); +#else + memcpy (data_ptr, *(from_desc->dataHandle), data_size); +#endif + if (err == noErr) + err = mac_coerce_file_name_ptr (from_type, data_ptr, + data_size, to_type, + handler_refcon, result); + xfree (data_ptr); + } + else + err = memFullErr; + } + + if (err != noErr) + return errAECoercionFail; + return noErr; +} + +OSErr +init_coercion_handler () +{ + OSErr err; + + static AECoercePtrUPP coerce_file_name_ptrUPP = NULL; + static AECoerceDescUPP coerce_file_name_descUPP = NULL; + + if (coerce_file_name_ptrUPP == NULL) + { + coerce_file_name_ptrUPP = NewAECoercePtrUPP (mac_coerce_file_name_ptr); + coerce_file_name_descUPP = NewAECoerceDescUPP (mac_coerce_file_name_desc); + } + + err = AEInstallCoercionHandler (TYPE_FILE_NAME, typeWildCard, + (AECoercionHandlerUPP) + coerce_file_name_ptrUPP, 0, false, false); + if (err == noErr) + err = AEInstallCoercionHandler (typeWildCard, TYPE_FILE_NAME, + (AECoercionHandlerUPP) + coerce_file_name_ptrUPP, 0, false, false); + if (err == noErr) + err = AEInstallCoercionHandler (TYPE_FILE_NAME, typeWildCard, + coerce_file_name_descUPP, 0, true, false); + if (err == noErr) + err = AEInstallCoercionHandler (typeWildCard, TYPE_FILE_NAME, + coerce_file_name_descUPP, 0, true, false); + return err; +} + +#if TARGET_API_MAC_CARBON +OSErr +create_apple_event_from_event_ref (event, num_params, names, types, result) + EventRef event; + UInt32 num_params; + EventParamName *names; + EventParamType *types; + AppleEvent *result; +{ + OSErr err; + static const ProcessSerialNumber psn = {0, kCurrentProcess}; + AEAddressDesc address_desc; + UInt32 i, size; + CFStringRef string; + CFDataRef data; + char *buf; + + err = AECreateDesc (typeProcessSerialNumber, &psn, + sizeof (ProcessSerialNumber), &address_desc); + if (err == noErr) + { + err = AECreateAppleEvent (0, 0, /* Dummy class and ID. */ + &address_desc, /* NULL is not allowed + on Mac OS Classic. */ + kAutoGenerateReturnID, + kAnyTransactionID, result); + AEDisposeDesc (&address_desc); + } + if (err != noErr) + return err; + + for (i = 0; i < num_params; i++) + switch (types[i]) + { +#ifdef MAC_OSX + case typeCFStringRef: + err = GetEventParameter (event, names[i], typeCFStringRef, NULL, + sizeof (CFStringRef), NULL, &string); + if (err != noErr) + break; + data = CFStringCreateExternalRepresentation (NULL, string, + kCFStringEncodingUTF8, + '?'); + if (data == NULL) + break; + /* typeUTF8Text is not available on Mac OS X 10.1. */ + AEPutParamPtr (result, names[i], 'utf8', + CFDataGetBytePtr (data), CFDataGetLength (data)); + CFRelease (data); + break; +#endif + + default: + err = GetEventParameter (event, names[i], types[i], NULL, + 0, &size, NULL); + if (err != noErr) + break; + buf = xmalloc (size); + if (buf == NULL) + break; + err = GetEventParameter (event, names[i], types[i], NULL, + size, NULL, buf); + if (err == noErr) + AEPutParamPtr (result, names[i], types[i], buf, size); + xfree (buf); + break; + } + + return noErr; +} +#endif + + +/*********************************************************************** Conversion between Lisp and Core Foundation objects ***********************************************************************/ #if TARGET_API_MAC_CARBON static Lisp_Object Qstring, Qnumber, Qboolean, Qdate, Qdata; static Lisp_Object Qarray, Qdictionary; -#define DECODE_UTF_8(str) code_convert_string_norecord (str, Qutf_8, 0) struct cfdict_context { @@ -336,12 +779,11 @@ cfdata_to_lisp (data) } -/* From CFString to a lisp string. Never returns a unibyte string - (even if it only contains ASCII characters). - This may cause GC during code conversion. */ +/* From CFString to a lisp string. Returns a unibyte string + containing a UTF-8 byte sequence. */ Lisp_Object -cfstring_to_lisp (string) +cfstring_to_lisp_nodecode (string) CFStringRef string; { Lisp_Object result = Qnil; @@ -362,9 +804,23 @@ cfstring_to_lisp (string) } } + return result; +} + + +/* From CFString to a lisp string. Never returns a unibyte string + (even if it only contains ASCII characters). + This may cause GC during code conversion. */ + +Lisp_Object +cfstring_to_lisp (string) + CFStringRef string; +{ + Lisp_Object result = cfstring_to_lisp_nodecode (string); + if (!NILP (result)) { - result = DECODE_UTF_8 (result); + result = code_convert_string_norecord (result, Qutf_8, 0); /* This may be superfluous. Just to make sure that the result is a multibyte string. */ result = string_to_multibyte (result); @@ -854,9 +1310,14 @@ parse_resource_line (p) implemented as a hash table that maps a pair (SRC-NODE-ID . EDGE-LABEL) to DEST-NODE-ID. It also holds a maximum node id used in the table as a value for HASHKEY_MAX_NID. A value associated to - a node is recorded as a value for the node id. */ + a node is recorded as a value for the node id. + + A database also has a cache for past queries as a value for + HASHKEY_QUERY_CACHE. It is another hash table that maps + "NAME-STRING\0CLASS-STRING" to the result of the query. */ #define HASHKEY_MAX_NID (make_number (0)) +#define HASHKEY_QUERY_CACHE (make_number (-1)) static XrmDatabase xrm_create_database () @@ -868,6 +1329,7 @@ xrm_create_database () make_float (DEFAULT_REHASH_THRESHOLD), Qnil, Qnil, Qnil); Fputhash (HASHKEY_MAX_NID, make_number (0), database); + Fputhash (HASHKEY_QUERY_CACHE, Qnil, database); return database; } @@ -901,6 +1363,7 @@ xrm_q_put_resource (database, quarks, value) Fputhash (node_id, value, database); Fputhash (HASHKEY_MAX_NID, make_number (max_nid), database); + Fputhash (HASHKEY_QUERY_CACHE, Qnil, database); } /* Merge multiple resource entries specified by DATA into a resource @@ -989,8 +1452,30 @@ xrm_get_resource (database, name, class) XrmDatabase database; char *name, *class; { - Lisp_Object quark_name, quark_class, tmp; - int nn, nc; + Lisp_Object key, query_cache, quark_name, quark_class, tmp; + int i, nn, nc; + struct Lisp_Hash_Table *h; + unsigned hash_code; + + nn = strlen (name); + nc = strlen (class); + key = make_uninit_string (nn + nc + 1); + strcpy (SDATA (key), name); + strncpy (SDATA (key) + nn + 1, class, nc); + + query_cache = Fgethash (HASHKEY_QUERY_CACHE, database, Qnil); + if (NILP (query_cache)) + { + query_cache = make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), + make_float (DEFAULT_REHASH_SIZE), + make_float (DEFAULT_REHASH_THRESHOLD), + Qnil, Qnil, Qnil); + Fputhash (HASHKEY_QUERY_CACHE, query_cache, database); + } + h = XHASH_TABLE (query_cache); + i = hash_lookup (h, key, &hash_code); + if (i >= 0) + return HASH_VALUE (h, i); quark_name = parse_resource_name (&name); if (*name != '\0') @@ -1009,7 +1494,11 @@ xrm_get_resource (database, name, class) if (nn != nc) return Qnil; else - return xrm_q_get_resource (database, quark_name, quark_class); + { + tmp = xrm_q_get_resource (database, quark_name, quark_class); + hash_put (h, key, tmp, hash_code); + return tmp; + } } #if TARGET_API_MAC_CARBON @@ -1108,7 +1597,7 @@ xrm_get_preference_database (application) CFSetGetValues (key_set, (const void **)keys); for (index = 0; index < count; index++) { - res_name = SDATA (cfstring_to_lisp (keys[index])); + res_name = SDATA (cfstring_to_lisp_nodecode (keys[index])); quarks = parse_resource_name (&res_name); if (!(NILP (quarks) || *res_name)) { @@ -2345,7 +2834,7 @@ path_from_vol_dir_name (char *path, int man_path_len, short vol_ref_num, } -OSErr +static OSErr posix_pathname_to_fsspec (ufn, fs) const char *ufn; FSSpec *fs; @@ -2361,7 +2850,7 @@ posix_pathname_to_fsspec (ufn, fs) } } -OSErr +static OSErr fsspec_to_posix_pathname (fs, ufn, ufnbuflen) const FSSpec *fs; char *ufn; @@ -2934,7 +3423,10 @@ mystrcpy (char *to, char *from) wildcard filename expansion. Since we don't really have a shell on the Mac, this case is detected and the starting of the shell is by-passed. We really need to add code here to do filename - expansion to support such functionality. */ + expansion to support such functionality. + + We can't use this strategy in Carbon because the High Level Event + APIs are not available. */ int run_mac_command (argv, workdir, infn, outfn, errfn) @@ -3678,84 +4170,53 @@ CODE must be a 4-character string. Return non-nil if successful. */) /* Compile and execute the AppleScript SCRIPT and return the error status as function value. A zero is returned if compilation and - execution is successful, in which case RESULT returns a pointer to - a string containing the resulting script value. Otherwise, the Mac - error code is returned and RESULT returns a pointer to an error - string. In both cases the caller should deallocate the storage - used by the string pointed to by RESULT if it is non-NULL. For - documentation on the MacOS scripting architecture, see Inside - Macintosh - Interapplication Communications: Scripting Components. */ + execution is successful, in which case *RESULT is set to a Lisp + string containing the resulting script value. Otherwise, the Mac + error code is returned and *RESULT is set to an error Lisp string. + For documentation on the MacOS scripting architecture, see Inside + Macintosh - Interapplication Communications: Scripting + Components. */ static long -do_applescript (char *script, char **result) +do_applescript (script, result) + Lisp_Object script, *result; { - AEDesc script_desc, result_desc, error_desc; + AEDesc script_desc, result_desc, error_desc, *desc = NULL; OSErr error; OSAError osaerror; - long length; - *result = 0; + *result = Qnil; if (!as_scripting_component) initialize_applescript(); - error = AECreateDesc (typeChar, script, strlen(script), &script_desc); + error = AECreateDesc (typeChar, SDATA (script), SBYTES (script), + &script_desc); if (error) return error; osaerror = OSADoScript (as_scripting_component, &script_desc, kOSANullScript, typeChar, kOSAModeNull, &result_desc); - if (osaerror == errOSAScriptError) - { - /* error executing AppleScript: retrieve error message */ - if (!OSAScriptError (as_scripting_component, kOSAErrorMessage, typeChar, - &error_desc)) - { -#if TARGET_API_MAC_CARBON - length = AEGetDescDataSize (&error_desc); - *result = (char *) xmalloc (length + 1); - if (*result) - { - AEGetDescData (&error_desc, *result, length); - *(*result + length) = '\0'; - } -#else /* not TARGET_API_MAC_CARBON */ - HLock (error_desc.dataHandle); - length = GetHandleSize(error_desc.dataHandle); - *result = (char *) xmalloc (length + 1); - if (*result) - { - memcpy (*result, *(error_desc.dataHandle), length); - *(*result + length) = '\0'; - } - HUnlock (error_desc.dataHandle); -#endif /* not TARGET_API_MAC_CARBON */ - AEDisposeDesc (&error_desc); - } - } - else if (osaerror == noErr) /* success: retrieve resulting script value */ + if (osaerror == noErr) + /* success: retrieve resulting script value */ + desc = &result_desc; + else if (osaerror == errOSAScriptError) + /* error executing AppleScript: retrieve error message */ + if (!OSAScriptError (as_scripting_component, kOSAErrorMessage, typeChar, + &error_desc)) + desc = &error_desc; + + if (desc) { #if TARGET_API_MAC_CARBON - length = AEGetDescDataSize (&result_desc); - *result = (char *) xmalloc (length + 1); - if (*result) - { - AEGetDescData (&result_desc, *result, length); - *(*result + length) = '\0'; - } + *result = make_uninit_string (AEGetDescDataSize (desc)); + AEGetDescData (desc, SDATA (*result), SBYTES (*result)); #else /* not TARGET_API_MAC_CARBON */ - HLock (result_desc.dataHandle); - length = GetHandleSize(result_desc.dataHandle); - *result = (char *) xmalloc (length + 1); - if (*result) - { - memcpy (*result, *(result_desc.dataHandle), length); - *(*result + length) = '\0'; - } - HUnlock (result_desc.dataHandle); + *result = make_uninit_string (GetHandleSize (desc->dataHandle)); + memcpy (SDATA (*result), *(desc->dataHandle), SBYTES (*result)); #endif /* not TARGET_API_MAC_CARBON */ - AEDisposeDesc (&result_desc); + AEDisposeDesc (desc); } AEDisposeDesc (&script_desc); @@ -3773,38 +4234,20 @@ component. */) (script) Lisp_Object script; { - char *result, *temp; - Lisp_Object lisp_result; + Lisp_Object result; long status; CHECK_STRING (script); BLOCK_INPUT; - status = do_applescript (SDATA (script), &result); + status = do_applescript (script, &result); UNBLOCK_INPUT; - if (status) - { - if (!result) - error ("AppleScript error %d", status); - else - { - /* Unfortunately only OSADoScript in do_applescript knows how - how large the resulting script value or error message is - going to be and therefore as caller memory must be - deallocated here. It is necessary to free the error - message before calling error to avoid a memory leak. */ - temp = (char *) alloca (strlen (result) + 1); - strcpy (temp, result); - xfree (result); - error (temp); - } - } + if (status == 0) + return result; + else if (!STRINGP (result)) + error ("AppleScript error %d", status); else - { - lisp_result = build_string (result); - xfree (result); - return lisp_result; - } + error ("%s", SDATA (result)); } @@ -3842,6 +4285,48 @@ DEFUN ("posix-file-name-to-mac", Fposix_file_name_to_mac, } +DEFUN ("mac-coerce-ae-data", Fmac_coerce_ae_data, Smac_coerce_ae_data, 3, 3, 0, + doc: /* Coerce Apple event data SRC-DATA of type SRC-TYPE to DST-TYPE. +Each type should be a string of length 4 or the symbol +`undecoded-file-name'. */) + (src_type, src_data, dst_type) + Lisp_Object src_type, src_data, dst_type; +{ + OSErr err; + Lisp_Object result = Qnil; + DescType src_desc_type, dst_desc_type; + AEDesc dst_desc; +#ifdef MAC_OSX + FSRef fref; +#else + FSSpec fs; +#endif + + CHECK_STRING (src_data); + if (EQ (src_type, Qundecoded_file_name)) + src_desc_type = TYPE_FILE_NAME; + else + src_desc_type = mac_get_code_from_arg (src_type, 0); + + if (EQ (dst_type, Qundecoded_file_name)) + dst_desc_type = TYPE_FILE_NAME; + else + dst_desc_type = mac_get_code_from_arg (dst_type, 0); + + BLOCK_INPUT; + err = AECoercePtr (src_desc_type, SDATA (src_data), SBYTES (src_data), + dst_desc_type, &dst_desc); + if (err == noErr) + { + result = Fcdr (mac_aedesc_to_lisp (&dst_desc)); + AEDisposeDesc (&dst_desc); + } + UNBLOCK_INPUT; + + return result; +} + + #if TARGET_API_MAC_CARBON static Lisp_Object Qxml, Qmime_charset; static Lisp_Object QNFD, QNFKD, QNFC, QNFKC, QHFS_plus_D, QHFS_plus_C; @@ -4119,7 +4604,7 @@ DEFUN ("mac-code-convert-string", Fmac_code_convert_string, Smac_code_convert_st The conversion is performed using the converter provided by the system. Each encoding is specified by either a coding system symbol, a mime charset string, or an integer as a CFStringEncoding value. Nil for -encoding means UTF-16 in native byte order, no byte order marker. +encoding means UTF-16 in native byte order, no byte order mark. On Mac OS X 10.2 and later, you can do Unicode Normalization by specifying the optional argument NORMALIZATION-FORM with a symbol NFD, NFKD, NFC, NFKC, HFS+D, or HFS+C. @@ -4192,6 +4677,29 @@ DEFUN ("mac-clear-font-name-table", Fmac_clear_font_name_table, Smac_clear_font_ return Qnil; } + +static Lisp_Object +mac_get_system_locale () +{ + OSErr err; + LangCode lang; + RegionCode region; + LocaleRef locale; + Str255 str; + + lang = GetScriptVariable (smSystemScript, smScriptLang); + region = GetScriptManagerVariable (smRegionCode); + err = LocaleRefFromLangOrRegionCode (lang, region, &locale); + if (err == noErr) + err = LocaleRefGetPartString (locale, kLocaleAllPartsMask, + sizeof (str), str); + if (err == noErr) + return build_string (str); + else + return Qnil; +} + + #ifdef MAC_OSX #undef select @@ -4213,7 +4721,7 @@ extern int noninteractive; involved, and timeout is not too short (greater than SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds). -> Create CFSocket for each socket and add it into the current - event RunLoop so that an `ready-to-read' event can be posted + event RunLoop so that a `ready-to-read' event can be posted to the event queue that is also used for window events. Then ReceiveNextEvent can wait for both kinds of inputs. 4. Otherwise. @@ -4481,6 +4989,11 @@ init_mac_osx_environment () char *p, *q; struct stat st; + /* Initialize locale related variables. */ + mac_system_script_code = + (ScriptCode) GetScriptManagerVariable (smSysScript); + Vmac_system_locale = mac_get_system_locale (); + /* Fetch the pathname of the application bundle as a C string into app_bundle_pathname. */ @@ -4600,31 +5113,12 @@ init_mac_osx_environment () #endif /* MAC_OSX */ -static Lisp_Object -mac_get_system_locale () -{ - OSErr err; - LangCode lang; - RegionCode region; - LocaleRef locale; - Str255 str; - - lang = GetScriptVariable (smSystemScript, smScriptLang); - region = GetScriptManagerVariable (smRegionCode); - err = LocaleRefFromLangOrRegionCode (lang, region, &locale); - if (err == noErr) - err = LocaleRefGetPartString (locale, kLocaleAllPartsMask, - sizeof (str), str); - if (err == noErr) - return build_string (str); - else - return Qnil; -} - - void syms_of_mac () { + Qundecoded_file_name = intern ("undecoded-file-name"); + staticpro (&Qundecoded_file_name); + #if TARGET_API_MAC_CARBON Qstring = intern ("string"); staticpro (&Qstring); Qnumber = intern ("number"); staticpro (&Qnumber); @@ -4648,6 +5142,7 @@ syms_of_mac () QHFS_plus_C = intern ("HFS+C"); staticpro (&QHFS_plus_C); #endif + defsubr (&Smac_coerce_ae_data); #if TARGET_API_MAC_CARBON defsubr (&Smac_get_preference); defsubr (&Smac_code_convert_string); diff --git a/src/macfns.c b/src/macfns.c index 8071974c6d4..a9119cc4ab9 100644 --- a/src/macfns.c +++ b/src/macfns.c @@ -1,5 +1,6 @@ /* Graphical user interface functions for Mac OS. - Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004, + 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -2879,24 +2880,37 @@ If omitted or nil, that stands for the selected frame's display. */) (display) Lisp_Object display; { - int mac_major_version; - SInt32 response; + UInt32 response, major, minor, bugfix; OSErr err; BLOCK_INPUT; err = Gestalt (gestaltSystemVersion, &response); + if (err == noErr) + if (response >= 0x00001040) + { + err = Gestalt ('sys1', &major); /* gestaltSystemVersionMajor */ + if (err == noErr) + err = Gestalt ('sys2', &minor); /* gestaltSystemVersionMinor */ + if (err == noErr) + err = Gestalt ('sys3', &bugfix); /* gestaltSystemVersionBugFix */ + } + else + { + bugfix = response & 0xf; + response >>= 4; + minor = response & 0xf; + response >>= 4; + /* convert BCD to int */ + major = response - (response >> 4) * 6; + } UNBLOCK_INPUT; if (err != noErr) error ("Cannot get Mac OS version"); - mac_major_version = (response >> 8) & 0xff; - /* convert BCD to int */ - mac_major_version -= (mac_major_version >> 4) * 6; - - return Fcons (make_number (mac_major_version), - Fcons (make_number ((response >> 4) & 0xf), - Fcons (make_number (response & 0xf), + return Fcons (make_number (major), + Fcons (make_number (minor), + Fcons (make_number (bugfix), Qnil))); } @@ -3839,16 +3853,22 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y) if (INTEGERP (top)) *root_y = XINT (top); - else if (*root_y + XINT (dy) - height < 0) - *root_y -= XINT (dy); + else if (*root_y + XINT (dy) <= 0) + *root_y = 0; /* Can happen for negative dy */ + else if (*root_y + XINT (dy) + height <= FRAME_MAC_DISPLAY_INFO (f)->height) + /* It fits below the pointer */ + *root_y += XINT (dy); + else if (height + XINT (dy) <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XINT (dy); else - { - *root_y -= height; - *root_y += XINT (dy); - } + /* Put it on the top. */ + *root_y = 0; if (INTEGERP (left)) *root_x = XINT (left); + else if (*root_x + XINT (dx) <= 0) + *root_x = 0; /* Can happen for negative dx */ else if (*root_x + XINT (dx) + width <= FRAME_MAC_DISPLAY_INFO (f)->width) /* It fits to the right of the pointer. */ *root_x += XINT (dx); @@ -4219,21 +4239,13 @@ If ONLY-DIR-P is non-nil, the user can only select directories. */) /* Set the default location and continue*/ if (status == noErr) { + Lisp_Object encoded_dir = ENCODE_FILE (dir); AEDesc defLocAed; -#ifdef MAC_OSX - FSRef defLoc; - status = FSPathMakeRef(SDATA(ENCODE_FILE(dir)), &defLoc, NULL); -#else - FSSpec defLoc; - status = posix_pathname_to_fsspec (SDATA (ENCODE_FILE (dir)), &defLoc); -#endif + + status = AECreateDesc (TYPE_FILE_NAME, SDATA (encoded_dir), + SBYTES (encoded_dir), &defLocAed); if (status == noErr) { -#ifdef MAC_OSX - AECreateDesc(typeFSRef, &defLoc, sizeof(FSRef), &defLocAed); -#else - AECreateDesc(typeFSS, &defLoc, sizeof(FSSpec), &defLocAed); -#endif NavCustomControl(dialogRef, kNavCtlSetLocation, (void*) &defLocAed); AEDisposeDesc(&defLocAed); } @@ -4255,41 +4267,36 @@ If ONLY-DIR-P is non-nil, the user can only select directories. */) case kNavUserActionSaveAs: { NavReplyRecord reply; - AEDesc aed; -#ifdef MAC_OSX - FSRef fsRef; -#else - FSSpec fs; -#endif - status = NavDialogGetReply(dialogRef, &reply); + Size len; -#ifdef MAC_OSX - AECoerceDesc(&reply.selection, typeFSRef, &aed); - AEGetDescData(&aed, (void *) &fsRef, sizeof (FSRef)); - FSRefMakePath(&fsRef, (UInt8 *) filename, sizeof (filename)); -#else - AECoerceDesc (&reply.selection, typeFSS, &aed); - AEGetDescData (&aed, (void *) &fs, sizeof (FSSpec)); - fsspec_to_posix_pathname (&fs, filename, sizeof (filename) - 1); -#endif - AEDisposeDesc(&aed); - if (reply.saveFileName) + status = NavDialogGetReply(dialogRef, &reply); + if (status != noErr) + break; + status = AEGetNthPtr (&reply.selection, 1, TYPE_FILE_NAME, + NULL, NULL, filename, + sizeof (filename) - 1, &len); + if (status == noErr) { - /* If it was a saved file, we need to add the file name */ - int len = strlen(filename); - if (len && filename[len-1] != '/') - filename[len++] = '/'; - CFStringGetCString(reply.saveFileName, filename+len, - sizeof (filename) - len, + len = min (len, sizeof (filename) - 1); + filename[len] = '\0'; + if (reply.saveFileName) + { + /* If it was a saved file, we need to add the file name */ + if (len && len < sizeof (filename) - 1 + && filename[len-1] != '/') + filename[len++] = '/'; + CFStringGetCString(reply.saveFileName, filename+len, + sizeof (filename) - len, #if MAC_OSX - kCFStringEncodingUTF8 + kCFStringEncodingUTF8 #else - CFStringGetSystemEncoding () + CFStringGetSystemEncoding () #endif - ); + ); + } + file = DECODE_FILE (make_unibyte_string (filename, + strlen (filename))); } - file = DECODE_FILE (make_unibyte_string (filename, - strlen (filename))); NavDisposeReply(&reply); } break; diff --git a/src/macgui.h b/src/macgui.h index 6e2adb092c6..74c64bfb41d 100644 --- a/src/macgui.h +++ b/src/macgui.h @@ -92,6 +92,12 @@ typedef GWorldPtr Pixmap; #endif +#ifndef USE_CG_TEXT_DRAWING +#if USE_ATSUI && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 +#define USE_CG_TEXT_DRAWING 1 +#endif +#endif + /* Emulate XCharStruct. */ typedef struct _XCharStruct { @@ -103,7 +109,6 @@ typedef struct _XCharStruct #if 0 unsigned short attributes; /* per char flags (not predefined) */ #endif - unsigned valid_p : 1; } XCharStruct; #define STORE_XCHARSTRUCT(xcs, w, bds) \ @@ -111,8 +116,19 @@ typedef struct _XCharStruct (xcs).lbearing = (bds).left, \ (xcs).rbearing = (bds).right, \ (xcs).ascent = -(bds).top, \ - (xcs).descent = (bds).bottom, \ - (xcs).valid_p = 1) + (xcs).descent = (bds).bottom) + +typedef struct +{ + char valid_bits[0x100 / 8]; + XCharStruct per_char[0x100]; +} XCharStructRow; + +#define XCHARSTRUCTROW_CHAR_VALID_P(row, byte2) \ + ((row)->valid_bits[(byte2) / 8] & (1 << (byte2) % 8)) + +#define XCHARSTRUCTROW_SET_CHAR_VALID(row, byte2) \ + ((row)->valid_bits[(byte2) / 8] |= (1 << (byte2) % 8)) struct MacFontStruct { char *full_name; @@ -127,6 +143,10 @@ struct MacFontStruct { #endif #if USE_ATSUI ATSUStyle mac_style; /* NULL if QuickDraw Text is used */ +#if USE_CG_TEXT_DRAWING + CGFontRef cg_font; /* NULL if ATSUI text drawing is used */ + CGGlyph *cg_glyphs; /* Likewise */ +#endif #endif /* from Xlib.h */ @@ -147,7 +167,10 @@ struct MacFontStruct { #endif /* 0 */ XCharStruct min_bounds; /* minimum bounds over all existing char */ XCharStruct max_bounds; /* maximum bounds over all existing char */ - XCharStruct *per_char; /* first_char to last_char information */ + union { + XCharStruct *per_char; /* first_char to last_char information */ + XCharStructRow **rows; /* first row to last row information */ + } bounds; int ascent; /* logical extent above baseline for spacing */ int descent; /* logical decent below baseline for spacing */ }; diff --git a/src/macmenu.c b/src/macmenu.c index a68ff04e405..1b132407df7 100644 --- a/src/macmenu.c +++ b/src/macmenu.c @@ -1,4 +1,4 @@ -/* Menu support for GNU Emacs on the for Mac OS. +/* Menu support for GNU Emacs on Mac OS. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. @@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA. */ #include <config.h> #include <stdio.h> + #include "lisp.h" #include "termhooks.h" #include "keyboard.h" @@ -154,7 +155,7 @@ Lisp_Object Vmenu_updating_frame; Lisp_Object Qdebug_on_next_call; -extern Lisp_Object Qmenu_bar; +extern Lisp_Object Qmenu_bar, Qmac_apple_event; extern Lisp_Object QCtoggle, QCradio; @@ -165,27 +166,28 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; extern Lisp_Object Qmenu_bar_update_hook; +void set_frame_menubar P_ ((FRAME_PTR, int, int)); + #if TARGET_API_MAC_CARBON #define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str) #else #define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str) #endif -void set_frame_menubar (); - static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)); #ifdef HAVE_DIALOGS -static Lisp_Object mac_dialog_show (); +static Lisp_Object mac_dialog_show P_ ((FRAME_PTR, int, Lisp_Object, + Lisp_Object, char **)); #endif -static Lisp_Object mac_menu_show (); - -static void keymap_panes (); -static void single_keymap_panes (); -static void single_menu_item (); -static void list_of_panes (); -static void list_of_items (); +static Lisp_Object mac_menu_show P_ ((struct frame *, int, int, int, int, + Lisp_Object, char **)); +static void keymap_panes P_ ((Lisp_Object *, int, int)); +static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, + int, int)); +static void list_of_panes P_ ((Lisp_Object)); +static void list_of_items P_ ((Lisp_Object)); static void fill_submenu (MenuHandle, widget_value *); static void fill_menubar (widget_value *); @@ -280,8 +282,7 @@ init_menu_items () menu_items_submenu_depth = 0; } -/* Call at the end of generating the data in menu_items. - This fills in the number of items in the last pane. */ +/* Call at the end of generating the data in menu_items. */ static void finish_menu_items () @@ -415,11 +416,21 @@ keymap_panes (keymaps, nmaps, notreal) P is the number of panes we have made so far. */ for (mapno = 0; mapno < nmaps; mapno++) single_keymap_panes (keymaps[mapno], - Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10); + Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10); finish_menu_items (); } +/* Args passed between single_keymap_panes and single_menu_item. */ +struct skp + { + Lisp_Object pending_maps; + int maxdepth, notreal; + }; + +static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, + void *)); + /* This is a recursive subroutine of keymap_panes. It handles one keymap, KEYMAP. The other arguments are passed along @@ -437,89 +448,71 @@ single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth) int notreal; int maxdepth; { - Lisp_Object pending_maps = Qnil; - Lisp_Object tail, item; - struct gcpro gcpro1, gcpro2; + struct skp skp; + struct gcpro gcpro1; + + skp.pending_maps = Qnil; + skp.maxdepth = maxdepth; + skp.notreal = notreal; if (maxdepth <= 0) return; push_menu_pane (pane_name, prefix); - for (tail = keymap; CONSP (tail); tail = XCDR (tail)) - { - GCPRO2 (keymap, pending_maps); - /* Look at each key binding, and if it is a menu item add it - to this menu. */ - item = XCAR (tail); - if (CONSP (item)) - single_menu_item (XCAR (item), XCDR (item), - &pending_maps, notreal, maxdepth); - else if (VECTORP (item)) - { - /* Loop over the char values represented in the vector. */ - int len = XVECTOR (item)->size; - int c; - for (c = 0; c < len; c++) - { - Lisp_Object character; - XSETFASTINT (character, c); - single_menu_item (character, XVECTOR (item)->contents[c], - &pending_maps, notreal, maxdepth); - } - } - UNGCPRO; - } + GCPRO1 (skp.pending_maps); + map_keymap (keymap, single_menu_item, Qnil, &skp, 1); + UNGCPRO; /* Process now any submenus which want to be panes at this level. */ - while (!NILP (pending_maps)) + while (CONSP (skp.pending_maps)) { Lisp_Object elt, eltcdr, string; - elt = Fcar (pending_maps); + elt = XCAR (skp.pending_maps); eltcdr = XCDR (elt); string = XCAR (eltcdr); /* We no longer discard the @ from the beginning of the string here. Instead, we do this in mac_menu_show. */ single_keymap_panes (Fcar (elt), string, XCDR (eltcdr), notreal, maxdepth - 1); - pending_maps = Fcdr (pending_maps); + skp.pending_maps = XCDR (skp.pending_maps); } } /* This is a subroutine of single_keymap_panes that handles one keymap entry. KEY is a key in a keymap and ITEM is its binding. - PENDING_MAPS_PTR points to a list of keymaps waiting to be made into + SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into separate panes. - If NOTREAL is nonzero, only check for equivalent key bindings, don't + If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't evaluate expressions in menu items and don't make any menu. - If we encounter submenus deeper than MAXDEPTH levels, ignore them. */ + If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. */ static void -single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth) - Lisp_Object key, item; - Lisp_Object *pending_maps_ptr; - int maxdepth, notreal; +single_menu_item (key, item, dummy, skp_v) + Lisp_Object key, item, dummy; + void *skp_v; { Lisp_Object map, item_string, enabled; struct gcpro gcpro1, gcpro2; int res; + struct skp *skp = skp_v; /* Parse the menu item and leave the result in item_properties. */ GCPRO2 (key, item); - res = parse_menu_item (item, notreal, 0); + res = parse_menu_item (item, skp->notreal, 0); UNGCPRO; if (!res) return; /* Not a menu item. */ map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; - if (notreal) + if (skp->notreal) { /* We don't want to make a menu, just traverse the keymaps to precompute equivalent key bindings. */ if (!NILP (map)) - single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); + single_keymap_panes (map, Qnil, key, 1, skp->maxdepth - 1); return; } @@ -530,8 +523,8 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth) { if (!NILP (enabled)) /* An enabled separate pane. Remember this to handle it later. */ - *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), - *pending_maps_ptr); + skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)), + skp->pending_maps); return; } @@ -539,14 +532,14 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth) XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ], XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE], - XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], - XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); + XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], + XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); /* Display a submenu using the toolkit. */ if (! (NILP (map) || NILP (enabled))) { push_submenu_start (); - single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); + single_keymap_panes (map, Qnil, key, 0, skp->maxdepth - 1); push_submenu_end (); } } @@ -563,13 +556,13 @@ list_of_panes (menu) init_menu_items (); - for (tail = menu; !NILP (tail); tail = Fcdr (tail)) + for (tail = menu; CONSP (tail); tail = XCDR (tail)) { Lisp_Object elt, pane_name, pane_data; - elt = Fcar (tail); + elt = XCAR (tail); pane_name = Fcar (elt); CHECK_STRING (pane_name); - push_menu_pane (pane_name, Qnil); + push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil); pane_data = Fcdr (elt); CHECK_CONS (pane_data); list_of_items (pane_data); @@ -586,20 +579,22 @@ list_of_items (pane) { Lisp_Object tail, item, item1; - for (tail = pane; !NILP (tail); tail = Fcdr (tail)) + for (tail = pane; CONSP (tail); tail = XCDR (tail)) { - item = Fcar (tail); + item = XCAR (tail); if (STRINGP (item)) - push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil); - else if (NILP (item)) - push_left_right_boundary (); - else + push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt, + Qnil, Qnil, Qnil, Qnil); + else if (CONSP (item)) { - CHECK_CONS (item); - item1 = Fcar (item); + item1 = XCAR (item); CHECK_STRING (item1); - push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil); + push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item), + Qt, Qnil, Qnil, Qnil, Qnil); } + else + push_left_right_boundary (); + } } @@ -659,15 +654,14 @@ no quit occurs and `x-popup-menu' returns nil. */) Lisp_Object keymap, tem; int xpos = 0, ypos = 0; Lisp_Object title; - char *error_name; + char *error_name = NULL; Lisp_Object selection; FRAME_PTR f = NULL; Lisp_Object x, y, window; int keymaps = 0; int for_click = 0; - struct gcpro gcpro1; int specpdl_count = SPECPDL_INDEX (); - + struct gcpro gcpro1; #ifdef HAVE_MENUS if (! NILP (position)) @@ -677,7 +671,8 @@ no quit occurs and `x-popup-menu' returns nil. */) /* Decode the first argument: find the window and the coordinates. */ if (EQ (position, Qt) || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) + || EQ (XCAR (position), Qtool_bar) + || EQ (XCAR (position), Qmac_apple_event)))) { /* Use the mouse's current position. */ FRAME_PTR new_f = SELECTED_FRAME (); @@ -703,8 +698,8 @@ no quit occurs and `x-popup-menu' returns nil. */) if (CONSP (tem)) { window = Fcar (Fcdr (position)); - x = Fcar (tem); - y = Fcar (Fcdr (tem)); + x = XCAR (tem); + y = Fcar (XCDR (tem)); } else { @@ -746,7 +741,8 @@ no quit occurs and `x-popup-menu' returns nil. */) XSETFRAME (Vmenu_updating_frame, f); } - Vmenu_updating_frame = Qnil; + else + Vmenu_updating_frame = Qnil; #endif /* HAVE_MENUS */ title = Qnil; @@ -787,11 +783,11 @@ no quit occurs and `x-popup-menu' returns nil. */) /* The first keymap that has a prompt string supplies the menu title. */ - for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem)) + for (tem = menu, i = 0; CONSP (tem); tem = XCDR (tem)) { Lisp_Object prompt; - maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0); + maps[i++] = keymap = get_keymap (XCAR (tem), 1, 0); prompt = Fkeymap_prompt (keymap); if (NILP (title) && !NILP (prompt)) @@ -878,7 +874,8 @@ for instance using the window manager, then this produces a quit and /* Decode the first argument: find the window or frame to use. */ if (EQ (position, Qt) || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) + || EQ (XCAR (position), Qtool_bar) + || EQ (XCAR (position), Qmac_apple_event)))) { #if 0 /* Using the frame the mouse is on may not be right. */ /* Use the mouse's current position. */ @@ -946,6 +943,7 @@ for instance using the window manager, then this produces a quit and Lisp_Object title; char *error_name; Lisp_Object selection; + int specpdl_count = SPECPDL_INDEX (); /* Decode the dialog items from what was specified. */ title = Fcar (contents); @@ -954,11 +952,11 @@ for instance using the window manager, then this produces a quit and list_of_panes (Fcons (contents, Qnil)); /* Display them in a dialog box. */ + record_unwind_protect (cleanup_popup_menu, Qnil); BLOCK_INPUT; selection = mac_dialog_show (f, 0, title, header, &error_name); UNBLOCK_INPUT; - - discard_menu_items (); + unbind_to (specpdl_count, Qnil); if (error_name) error (error_name); return selection; @@ -970,13 +968,14 @@ for instance using the window manager, then this produces a quit and This is called from keyboard.c when it gets the MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue. - To activate the menu bar, we signal to the input thread that it can - return from the WM_INITMENU message, allowing the normal Windows - processing of the menus. + To activate the menu bar, we use the button-press event location + that was saved in saved_menu_event_location. But first we recompute the menu bar contents (the whole tree). - This way we can safely execute Lisp code. */ + The reason for saving the button event until here, instead of + passing it to the toolkit right away, is that we can safely + execute Lisp code. */ void x_activate_menubar (f) @@ -1073,14 +1072,12 @@ menubar_selection_callback (FRAME_PTR f, int client_data) buf.arg = entry; kbd_buffer_store_event (&buf); - f->output_data.mac->menu_command_in_progress = 0; f->output_data.mac->menubar_active = 0; return; } i += MENU_ITEMS_ITEM_LENGTH; } } - f->output_data.mac->menu_command_in_progress = 0; f->output_data.mac->menubar_active = 0; } @@ -1126,22 +1123,18 @@ free_menubar_widget_value_tree (wv) UNBLOCK_INPUT; } -/* Return a tree of widget_value structures for a menu bar item +/* Set up data in menu_items for a menu bar item whose event type is ITEM_KEY (with string ITEM_NAME) and whose contents come from the list of keymaps MAPS. */ -static widget_value * -single_submenu (item_key, item_name, maps) +static int +parse_single_submenu (item_key, item_name, maps) Lisp_Object item_key, item_name, maps; { - widget_value *wv, *prev_wv, *save_wv, *first_wv; - int i; - int submenu_depth = 0; Lisp_Object length; int len; Lisp_Object *mapvec; - widget_value **submenu_stack; - int previous_items = menu_items_used; + int i; int top_level_items = 0; length = Flength (maps); @@ -1155,28 +1148,44 @@ single_submenu (item_key, item_name, maps) maps = Fcdr (maps); } - menu_items_n_panes = 0; - /* Loop over the given keymaps, making a pane for each map. But don't make a pane that is empty--ignore that map instead. */ for (i = 0; i < len; i++) { - if (SYMBOLP (mapvec[i]) - || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i]))) + if (!KEYMAPP (mapvec[i])) { /* Here we have a command at top level in the menu bar as opposed to a submenu. */ top_level_items = 1; push_menu_pane (Qnil, Qnil); push_menu_item (item_name, Qt, item_key, mapvec[i], - Qnil, Qnil, Qnil, Qnil); + Qnil, Qnil, Qnil, Qnil); } else - single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); + { + Lisp_Object prompt; + prompt = Fkeymap_prompt (mapvec[i]); + single_keymap_panes (mapvec[i], + !NILP (prompt) ? prompt : item_name, + item_key, 0, 10); + } } - /* Create a tree of widget_value objects - representing the panes and their items. */ + return top_level_items; +} + +/* Create a tree of widget_value objects + representing the panes and items + in menu_items starting at index START, up to index END. */ + +static widget_value * +digest_single_submenu (start, end, top_level_items) + int start, end, top_level_items; +{ + widget_value *wv, *prev_wv, *save_wv, *first_wv; + int i; + int submenu_depth = 0; + widget_value **submenu_stack; submenu_stack = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); @@ -1190,12 +1199,12 @@ single_submenu (item_key, item_name, maps) save_wv = 0; prev_wv = 0; - /* Loop over all panes and items made during this call - and construct a tree of widget_value objects. - Ignore the panes and items made by previous calls to - single_submenu, even though those are also in menu_items. */ - i = previous_items; - while (i < menu_items_used) + /* Loop over all panes and items made by the preceding call + to parse_single_submenu and construct a tree of widget_value objects. + Ignore the panes and items used by previous calls to + digest_single_submenu, even though those are also in menu_items. */ + i = start; + while (i < end) { if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) { @@ -1229,7 +1238,7 @@ single_submenu (item_key, item_name, maps) #ifndef HAVE_MULTILINGUAL_MENU if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) { - pane_name = ENCODE_SYSTEM (pane_name); + pane_name = ENCODE_MENU_STRING (pane_name); AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; } #endif @@ -1265,7 +1274,7 @@ single_submenu (item_key, item_name, maps) { /* Create a new item within current pane. */ Lisp_Object item_name, enable, descrip, def, type, selected; - Lisp_Object help; + Lisp_Object help; item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); @@ -1276,13 +1285,13 @@ single_submenu (item_key, item_name, maps) help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); #ifndef HAVE_MULTILINGUAL_MENU - if (STRING_MULTIBYTE (item_name)) + if (STRING_MULTIBYTE (item_name)) { item_name = ENCODE_MENU_STRING (item_name); AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; } - if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) + if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) { descrip = ENCODE_MENU_STRING (descrip); AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; @@ -1314,7 +1323,7 @@ single_submenu (item_key, item_name, maps) abort (); wv->selected = !NILP (selected); - if (!STRINGP (help)) + if (! STRINGP (help)) help = Qnil; wv->help = help; @@ -1336,6 +1345,7 @@ single_submenu (item_key, item_name, maps) return first_wv; } + /* Walk through the widget_value tree starting at FIRST_WV and update the char * pointers from the corresponding lisp values. We do this after building the whole tree, since GC may happen while the @@ -1417,20 +1427,28 @@ static void install_menu_quit_handler (MenuHandle menu_handle) { #ifdef HAVE_CANCELMENUTRACKING - EventHandlerUPP handler = NewEventHandlerUPP(menu_quit_handler); - UInt32 numTypes = 1; EventTypeSpec typesList[] = { { kEventClassKeyboard, kEventRawKeyDown } }; int i = MIN_MENU_ID; MenuHandle menu = menu_handle ? menu_handle : GetMenuHandle (i); while (menu != NULL) { - InstallMenuEventHandler (menu, handler, GetEventTypeCount (typesList), + InstallMenuEventHandler (menu, menu_quit_handler, + GetEventTypeCount (typesList), typesList, menu_handle, NULL); if (menu_handle) break; menu = GetMenuHandle (++i); } - DisposeEventHandlerUPP (handler); + + i = menu_handle ? MIN_POPUP_SUBMENU_ID : MIN_SUBMENU_ID; + menu = GetMenuHandle (i); + while (menu != NULL) + { + InstallMenuEventHandler (menu, menu_quit_handler, + GetEventTypeCount (typesList), + typesList, menu_handle, NULL); + menu = GetMenuHandle (++i); + } #endif /* HAVE_CANCELMENUTRACKING */ } @@ -1447,7 +1465,9 @@ set_frame_menubar (f, first_time, deep_p) int menubar_widget = f->output_data.mac->menubar_widget; Lisp_Object items; widget_value *wv, *first_wv, *prev_wv = 0; - int i; + int i, last_i = 0; + int *submenu_start, *submenu_end; + int *submenu_top_level_items, *submenu_n_panes; /* We must not change the menubar when actually in use. */ if (f->output_data.mac->menubar_active) @@ -1460,14 +1480,6 @@ set_frame_menubar (f, first_time, deep_p) else if (pending_menu_activation && !deep_p) deep_p = 1; - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; - wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; - first_wv = wv; - if (deep_p) { /* Make a widget-value tree representing the entire menu trees. */ @@ -1502,6 +1514,7 @@ set_frame_menubar (f, first_time, deep_p) /* Run the Lucid hook. */ safe_run_hooks (Qactivate_menubar_hook); + /* If it has changed current-menubar from previous value, really recompute the menubar from the value. */ if (! NILP (Vlucid_menu_bar_dirty_flag)) @@ -1516,21 +1529,56 @@ set_frame_menubar (f, first_time, deep_p) bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, previous_menu_items_used * sizeof (Lisp_Object)); - /* Fill in the current menu bar contents. */ + /* Fill in menu_items with the current menu bar contents. + This can evaluate Lisp code. */ menu_items = f->menu_bar_vector; menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; + submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int)); + submenu_top_level_items + = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); init_menu_items (); for (i = 0; i < XVECTOR (items)->size; i += 4) { Lisp_Object key, string, maps; + last_i = i; + key = XVECTOR (items)->contents[i]; string = XVECTOR (items)->contents[i + 1]; maps = XVECTOR (items)->contents[i + 2]; if (NILP (string)) break; - wv = single_submenu (key, string, maps); + submenu_start[i] = menu_items_used; + + menu_items_n_panes = 0; + submenu_top_level_items[i] + = parse_single_submenu (key, string, maps); + submenu_n_panes[i] = menu_items_n_panes; + + submenu_end[i] = menu_items_used; + } + + finish_menu_items (); + + /* 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->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + first_wv = wv; + + for (i = 0; i < last_i; i += 4) + { + menu_items_n_panes = submenu_n_panes[i]; + wv = digest_single_submenu (submenu_start[i], submenu_end[i], + submenu_top_level_items[i]); if (prev_wv) prev_wv->next = wv; else @@ -1541,8 +1589,6 @@ set_frame_menubar (f, first_time, deep_p) prev_wv = wv; } - finish_menu_items (); - set_buffer_internal_1 (prev); unbind_to (specpdl_count, Qnil); @@ -1551,22 +1597,18 @@ set_frame_menubar (f, first_time, deep_p) for (i = 0; i < previous_menu_items_used; i++) if (menu_items_used == i - || (NILP (Fequal (previous_items[i], - XVECTOR (menu_items)->contents[i])))) + || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i]))) break; if (i == menu_items_used && i == previous_menu_items_used && i != 0) { free_menubar_widget_value_tree (first_wv); - menu_items = Qnil; + discard_menu_items (); return; } /* Now GC cannot happen during the lifetime of the widget_value, - so it's safe to store data from a Lisp_String, as long as - local copies are made when the actual menu is created. - Windows takes care of this for normal string items, but - not for owner-drawn items or additional item-info. */ + so it's safe to store data from a Lisp_String. */ wv = first_wv->contents; for (i = 0; i < XVECTOR (items)->size; i += 4) { @@ -1581,13 +1623,21 @@ set_frame_menubar (f, first_time, deep_p) f->menu_bar_vector = menu_items; f->menu_bar_items_used = menu_items_used; - menu_items = Qnil; + discard_menu_items (); } else { /* 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->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + first_wv = wv; + items = FRAME_MENU_BAR_ITEMS (f); for (i = 0; i < XVECTOR (items)->size; i += 4) { @@ -1675,6 +1725,7 @@ initialize_frame_menubar (f) set_frame_menubar (f, 1, 1); } + /* Get rid of the menu bar of frame F, and free its storage. This is used when deleting a frame, and when turning off the menu bar. */ @@ -1682,7 +1733,7 @@ void free_frame_menubar (f) FRAME_PTR f; { - f->output_data.mac->menubar_widget = NULL; + f->output_data.mac->menubar_widget = 0; } @@ -1759,6 +1810,7 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) Lisp_Object *subprefix_stack = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); int submenu_depth = 0; + int first_pane; int specpdl_count = SPECPDL_INDEX (); @@ -1812,12 +1864,14 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) /* Create a new pane. */ Lisp_Object pane_name, prefix; char *pane_string; + pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); + #ifndef HAVE_MULTILINGUAL_MENU if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) { - pane_name = ENCODE_SYSTEM (pane_name); + pane_name = ENCODE_MENU_STRING (pane_name); AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; } #endif @@ -1860,14 +1914,13 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) { /* Create a new item within current pane. */ Lisp_Object item_name, enable, descrip, def, type, selected, help; - item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION); type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE); selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); - help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); + help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); #ifndef HAVE_MULTILINGUAL_MENU if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) @@ -1875,8 +1928,9 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) item_name = ENCODE_MENU_STRING (item_name); AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; } + if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) - { + { descrip = ENCODE_MENU_STRING (descrip); AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; } @@ -1906,7 +1960,8 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) abort (); wv->selected = !NILP (selected); - if (!STRINGP (help)) + + if (! STRINGP (help)) help = Qnil; wv->help = help; @@ -1933,6 +1988,7 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) if (STRING_MULTIBYTE (title)) title = ENCODE_MENU_STRING (title); #endif + wv_title->name = (char *) SDATA (title); wv_title->enabled = FALSE; wv_title->title = TRUE; @@ -1956,7 +2012,6 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) pos.v = y; SetPortWindowPort (FRAME_MAC_WINDOW (f)); - LocalToGlobal (&pos); /* No selection has been chosen yet. */ @@ -2166,11 +2221,11 @@ static char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -mac_dialog_show (f, keymaps, title, header, error) +mac_dialog_show (f, keymaps, title, header, error_name) FRAME_PTR f; int keymaps; Lisp_Object title, header; - char **error; + char **error_name; { int i, nb_buttons=0; char dialog_name[6]; @@ -2183,11 +2238,11 @@ mac_dialog_show (f, keymaps, title, header, error) /* 1 means we've seen the boundary between left-hand elts and right-hand. */ int boundary_seen = 0; - *error = NULL; + *error_name = NULL; if (menu_items_n_panes > 1) { - *error = "Multiple panes in dialog box"; + *error_name = "Multiple panes in dialog box"; return Qnil; } @@ -2215,18 +2270,16 @@ mac_dialog_show (f, keymaps, title, header, error) { /* Create a new item within current pane. */ - Lisp_Object item_name, enable, descrip, help; - + Lisp_Object item_name, enable, descrip; item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; descrip = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; - help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP]; if (NILP (item_name)) { free_menubar_widget_value_tree (first_wv); - *error = "Submenu in dialog items"; + *error_name = "Submenu in dialog items"; return Qnil; } if (EQ (item_name, Qquote)) @@ -2240,7 +2293,7 @@ mac_dialog_show (f, keymaps, title, header, error) if (nb_buttons >= 9) { free_menubar_widget_value_tree (first_wv); - *error = "Too many dialog items"; + *error_name = "Too many dialog items"; return Qnil; } @@ -2303,8 +2356,8 @@ mac_dialog_show (f, keymaps, title, header, error) /* Free the widget_value objects we used to specify the contents. */ free_menubar_widget_value_tree (first_wv); - /* Find the selected item, and its pane, to return the proper - value. */ + /* Find the selected item, and its pane, to return + the proper value. */ if (menu_item_selection != 0) { Lisp_Object prefix; @@ -2321,6 +2374,12 @@ mac_dialog_show (f, keymaps, title, header, error) = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; i += MENU_ITEMS_PANE_LENGTH; } + else if (EQ (XVECTOR (menu_items)->contents[i], Qquote)) + { + /* This is the boundary between left-side elts and + right-side elts. */ + ++i; + } else { entry @@ -2339,6 +2398,9 @@ mac_dialog_show (f, keymaps, title, header, error) } } } + else + /* Make "Cancel" equivalent to C-g. */ + Fsignal (Qquit, Qnil); return Qnil; } @@ -2364,7 +2426,11 @@ static void add_menu_item (MenuHandle menu, widget_value *wv, int submenu, int force_disable) { +#if TARGET_API_MAC_CARBON + CFStringRef item_name; +#else Str255 item_name; +#endif int pos; if (name_is_separator (wv->name)) @@ -2375,42 +2441,49 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu, #if TARGET_API_MAC_CARBON pos = CountMenuItems (menu); -#else - pos = CountMItems (menu); -#endif - strcpy (item_name, ""); - strncat (item_name, wv->name, 255); + item_name = cfstring_create_with_utf8_cstring (wv->name); + if (wv->key != NULL) { - strncat (item_name, " ", 255); - strncat (item_name, wv->key, 255); + CFStringRef name, key; + + name = item_name; + key = cfstring_create_with_utf8_cstring (wv->key); + item_name = CFStringCreateWithFormat (NULL, NULL, CFSTR ("%@ %@"), + name, key); + CFRelease (name); + CFRelease (key); } - item_name[255] = 0; -#if TARGET_API_MAC_CARBON - { - CFStringRef string = cfstring_create_with_utf8_cstring (item_name); - SetMenuItemTextWithCFString (menu, pos, string); - CFRelease (string); - } -#else + SetMenuItemTextWithCFString (menu, pos, item_name); + CFRelease (item_name); + + if (wv->enabled && !force_disable) + EnableMenuItem (menu, pos); + else + DisableMenuItem (menu, pos); +#else /* ! TARGET_API_MAC_CARBON */ + pos = CountMItems (menu); + + item_name[sizeof (item_name) - 1] = '\0'; + strncpy (item_name, wv->name, sizeof (item_name) - 1); + if (wv->key != NULL) + { + int len = strlen (item_name); + + strncpy (item_name + len, " ", sizeof (item_name) - 1 - len); + len = strlen (item_name); + strncpy (item_name + len, wv->key, sizeof (item_name) - 1 - len); + } c2pstr (item_name); SetMenuItemText (menu, pos, item_name); -#endif if (wv->enabled && !force_disable) -#if TARGET_API_MAC_CARBON - EnableMenuItem (menu, pos); -#else EnableItem (menu, pos); -#endif else -#if TARGET_API_MAC_CARBON - DisableMenuItem (menu, pos); -#else DisableItem (menu, pos); -#endif +#endif /* ! TARGET_API_MAC_CARBON */ /* Draw radio buttons and tickboxes. */ { @@ -2424,7 +2497,7 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu, SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data); } - if (submenu != NULL) + if (submenu != 0) SetMenuItemHierarchicalID (menu, pos, submenu); } @@ -2443,7 +2516,7 @@ fill_submenu (MenuHandle menu, widget_value *wv) add_menu_item (menu, wv, cur_submenu, 0); } else - add_menu_item (menu, wv, NULL, 0); + add_menu_item (menu, wv, 0, 0); } @@ -2462,7 +2535,7 @@ fill_menu (MenuHandle menu, widget_value *wv) add_menu_item (menu, wv, cur_submenu, 0); } else - add_menu_item (menu, wv, NULL, 0); + add_menu_item (menu, wv, 0, 0); } /* Construct native Mac OS menubar based on widget_value tree. */ @@ -2492,7 +2565,6 @@ fill_menubar (widget_value *wv) } #endif /* HAVE_MENUS */ - void syms_of_macmenu () diff --git a/src/macselect.c b/src/macselect.c index 63221ba3a90..066892adce0 100644 --- a/src/macselect.c +++ b/src/macselect.c @@ -23,6 +23,7 @@ Boston, MA 02110-1301, USA. */ #include "lisp.h" #include "macterm.h" #include "blockinput.h" +#include "keymap.h" #if !TARGET_API_MAC_CARBON #include <Endian.h> @@ -908,6 +909,253 @@ and t is the same as `SECONDARY'. */) } +int mac_ready_for_apple_events = 0; +static Lisp_Object Vmac_apple_event_map; +static Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id; +static struct +{ + AppleEvent *buf; + int size, count; +} deferred_apple_events; +extern Lisp_Object Qundefined; +extern OSErr mac_store_apple_event P_ ((Lisp_Object, Lisp_Object, + const AEDesc *)); + +struct apple_event_binding +{ + UInt32 code; /* Apple event class or ID. */ + Lisp_Object key, binding; +}; + +static void +find_event_binding_fun (key, binding, args, data) + Lisp_Object key, binding, args; + void *data; +{ + struct apple_event_binding *event_binding = + (struct apple_event_binding *)data; + Lisp_Object code_string; + + if (!SYMBOLP (key)) + return; + code_string = Fget (key, args); + if (STRINGP (code_string) && SBYTES (code_string) == 4 + && (EndianU32_BtoN (*((UInt32 *) SDATA (code_string))) + == event_binding->code)) + { + event_binding->key = key; + event_binding->binding = binding; + } +} + +static void +find_event_binding (keymap, event_binding, class_p) + Lisp_Object keymap; + struct apple_event_binding *event_binding; + int class_p; +{ + if (event_binding->code == 0) + event_binding->binding = + access_keymap (keymap, event_binding->key, 0, 1, 0); + else + { + event_binding->binding = Qnil; + map_keymap (keymap, find_event_binding_fun, + class_p ? Qmac_apple_event_class : Qmac_apple_event_id, + event_binding, 0); + } +} + +void +mac_find_apple_event_spec (class, id, class_key, id_key, binding) + AEEventClass class; + AEEventID id; + Lisp_Object *class_key, *id_key, *binding; +{ + struct apple_event_binding event_binding; + Lisp_Object keymap; + + *binding = Qnil; + + keymap = get_keymap (Vmac_apple_event_map, 0, 0); + if (NILP (keymap)) + return; + + event_binding.code = class; + event_binding.key = *class_key; + event_binding.binding = Qnil; + find_event_binding (keymap, &event_binding, 1); + *class_key = event_binding.key; + keymap = get_keymap (event_binding.binding, 0, 0); + if (NILP (keymap)) + return; + + event_binding.code = id; + event_binding.key = *id_key; + event_binding.binding = Qnil; + find_event_binding (keymap, &event_binding, 0); + *id_key = event_binding.key; + *binding = event_binding.binding; +} + +static OSErr +defer_apple_events (apple_event, reply) + const AppleEvent *apple_event, *reply; +{ + OSErr err; + + err = AESuspendTheCurrentEvent (apple_event); + + /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes + copies of the Apple event and the reply, but Mac OS 10.4 Xcode + manual says it doesn't. Anyway we create copies of them and save + it in `deferred_apple_events'. */ + if (err == noErr) + { + if (deferred_apple_events.buf == NULL) + { + deferred_apple_events.size = 16; + deferred_apple_events.count = 0; + deferred_apple_events.buf = + xmalloc (sizeof (AppleEvent) * deferred_apple_events.size); + if (deferred_apple_events.buf == NULL) + err = memFullErr; + } + else if (deferred_apple_events.count == deferred_apple_events.size) + { + AppleEvent *newbuf; + + deferred_apple_events.size *= 2; + newbuf = xrealloc (deferred_apple_events.buf, + sizeof (AppleEvent) * deferred_apple_events.size); + if (newbuf) + deferred_apple_events.buf = newbuf; + else + err = memFullErr; + } + } + + if (err == noErr) + { + int count = deferred_apple_events.count; + + AEDuplicateDesc (apple_event, deferred_apple_events.buf + count); + AEDuplicateDesc (reply, deferred_apple_events.buf + count + 1); + deferred_apple_events.count += 2; + } + + return err; +} + +static pascal OSErr +mac_handle_apple_event (apple_event, reply, refcon) + const AppleEvent *apple_event; + AppleEvent *reply; + SInt32 refcon; +{ + OSErr err; + AEEventClass event_class; + AEEventID event_id; + Lisp_Object class_key, id_key, binding; + + /* We can't handle an Apple event that requests a reply, but this + seems to be too restrictive. */ +#if 0 + if (reply->descriptorType != typeNull) + return errAEEventNotHandled; +#endif + + if (!mac_ready_for_apple_events) + { + err = defer_apple_events (apple_event, reply); + if (err != noErr) + return errAEEventNotHandled; + return noErr; + } + + err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL, + &event_class, sizeof (AEEventClass), NULL); + if (err == noErr) + err = AEGetAttributePtr (apple_event, keyEventIDAttr, typeType, NULL, + &event_id, sizeof (AEEventID), NULL); + if (err == noErr) + { + mac_find_apple_event_spec (event_class, event_id, + &class_key, &id_key, &binding); + if (!NILP (binding) && !EQ (binding, Qundefined)) + { + if (INTEGERP (binding)) + return XINT (binding); + err = mac_store_apple_event (class_key, id_key, apple_event); + if (err == noErr) + return noErr; + } + } + return errAEEventNotHandled; +} + +void +init_apple_event_handler () +{ + OSErr err; + long result; + + /* Make sure we have Apple events before starting. */ + err = Gestalt (gestaltAppleEventsAttr, &result); + if (err != noErr) + abort (); + + if (!(result & (1 << gestaltAppleEventsPresent))) + abort (); + + err = AEInstallEventHandler (typeWildCard, typeWildCard, +#if TARGET_API_MAC_CARBON + NewAEEventHandlerUPP (mac_handle_apple_event), +#else + NewAEEventHandlerProc (mac_handle_apple_event), +#endif + 0L, false); + if (err != noErr) + abort (); +} + +DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0, + doc: /* Process Apple events that are deferred at the startup time. */) + () +{ + OSErr err; + Lisp_Object result = Qnil; + long i, count; + AppleEvent apple_event, reply; + AEKeyword keyword; + + if (mac_ready_for_apple_events) + return Qnil; + + BLOCK_INPUT; + mac_ready_for_apple_events = 1; + if (deferred_apple_events.buf) + { + for (i = 0; i < deferred_apple_events.count; i += 2) + { + AEResumeTheCurrentEvent (deferred_apple_events.buf + i, + deferred_apple_events.buf + i + 1, + ((AEEventHandlerUPP) + kAEUseStandardDispatch), 0); + AEDisposeDesc (deferred_apple_events.buf + i); + AEDisposeDesc (deferred_apple_events.buf + i + 1); + } + xfree (deferred_apple_events.buf); + bzero (&deferred_apple_events, sizeof (deferred_apple_events)); + + result = Qt; + } + UNBLOCK_INPUT; + + return result; +} + + #ifdef MAC_OSX void init_service_handler () @@ -920,7 +1168,56 @@ init_service_handler () GetEventTypeCount (specs), specs, NULL, NULL); } -extern void mac_store_services_event P_ ((EventRef)); +extern OSErr mac_store_services_event P_ ((EventRef)); + +static OSStatus +copy_scrap_flavor_data (from_scrap, to_scrap, flavor_type) + ScrapRef from_scrap, to_scrap; + ScrapFlavorType flavor_type; +{ + OSStatus err; + Size size, size_allocated; + char *buf = NULL; + + err = GetScrapFlavorSize (from_scrap, flavor_type, &size); + if (err == noErr) + buf = xmalloc (size); + while (buf) + { + size_allocated = size; + err = GetScrapFlavorData (from_scrap, flavor_type, &size, buf); + if (err != noErr) + { + xfree (buf); + buf = NULL; + } + else if (size_allocated < size) + { + char *newbuf = xrealloc (buf, size); + + if (newbuf) + buf = newbuf; + else + { + xfree (buf); + buf = NULL; + } + } + else + break; + } + if (err == noErr) + if (buf == NULL) + err = memFullErr; + else + { + err = PutScrapFlavor (to_scrap, flavor_type, kScrapFlavorMaskNone, + size, buf); + xfree (buf); + } + + return err; +} static OSStatus mac_handle_service_event (call_ref, event, data) @@ -929,7 +1226,12 @@ mac_handle_service_event (call_ref, event, data) void *data; { OSStatus err = noErr; - ScrapRef cur_scrap; + ScrapRef cur_scrap, specific_scrap; + UInt32 event_kind = GetEventKind (event); + CFMutableArrayRef copy_types, paste_types; + CFStringRef type; + Lisp_Object rest; + ScrapFlavorType flavor_type; /* Check if Vmac_services_selection is a valid selection that has a corresponding scrap. */ @@ -940,86 +1242,103 @@ mac_handle_service_event (call_ref, event, data) if (!(err == noErr && cur_scrap)) return eventNotHandledErr; - switch (GetEventKind (event)) + switch (event_kind) { case kEventServiceGetTypes: - { - CFMutableArrayRef copy_types, paste_types; - CFStringRef type; - Lisp_Object rest; - ScrapFlavorType flavor_type; - - /* Set paste types. */ - err = GetEventParameter (event, kEventParamServicePasteTypes, - typeCFMutableArrayRef, NULL, - sizeof (CFMutableArrayRef), NULL, - &paste_types); - if (err == noErr) - for (rest = Vselection_converter_alist; CONSP (rest); - rest = XCDR (rest)) - if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))) - && (flavor_type = - get_flavor_type_from_symbol (XCAR (XCAR (rest))))) + /* Set paste types. */ + err = GetEventParameter (event, kEventParamServicePasteTypes, + typeCFMutableArrayRef, NULL, + sizeof (CFMutableArrayRef), NULL, + &paste_types); + if (err != noErr) + break; + + for (rest = Vselection_converter_alist; CONSP (rest); + rest = XCDR (rest)) + if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))) + && (flavor_type = + get_flavor_type_from_symbol (XCAR (XCAR (rest))))) + { + type = CreateTypeStringWithOSType (flavor_type); + if (type) { - type = CreateTypeStringWithOSType (flavor_type); - if (type) - { - CFArrayAppendValue (paste_types, type); - CFRelease (type); - } + CFArrayAppendValue (paste_types, type); + CFRelease (type); } + } - /* Set copy types. */ - err = GetEventParameter (event, kEventParamServiceCopyTypes, - typeCFMutableArrayRef, NULL, - sizeof (CFMutableArrayRef), NULL, - ©_types); - if (err == noErr - && !NILP (Fx_selection_owner_p (Vmac_services_selection))) - for (rest = get_scrap_target_type_list (cur_scrap); - CONSP (rest) && SYMBOLP (XCAR (rest)); rest = XCDR (rest)) - { - flavor_type = get_flavor_type_from_symbol (XCAR (rest)); - if (flavor_type) - { - type = CreateTypeStringWithOSType (flavor_type); - if (type) - { - CFArrayAppendValue (copy_types, type); - CFRelease (type); - } - } - } - } - break; + /* Set copy types. */ + err = GetEventParameter (event, kEventParamServiceCopyTypes, + typeCFMutableArrayRef, NULL, + sizeof (CFMutableArrayRef), NULL, + ©_types); + if (err != noErr) + break; + + if (NILP (Fx_selection_owner_p (Vmac_services_selection))) + break; + else + goto copy_all_flavors; case kEventServiceCopy: - { - ScrapRef specific_scrap; - Lisp_Object rest, data; - - err = GetEventParameter (event, kEventParamScrapRef, - typeScrapRef, NULL, - sizeof (ScrapRef), NULL, &specific_scrap); - if (err == noErr - && !NILP (Fx_selection_owner_p (Vmac_services_selection))) - for (rest = get_scrap_target_type_list (cur_scrap); - CONSP (rest) && SYMBOLP (XCAR (rest)); rest = XCDR (rest)) - { - data = get_scrap_string (cur_scrap, XCAR (rest)); - if (STRINGP (data)) - err = put_scrap_string (specific_scrap, XCAR (rest), data); - } - else + err = GetEventParameter (event, kEventParamScrapRef, + typeScrapRef, NULL, + sizeof (ScrapRef), NULL, &specific_scrap); + if (err != noErr + || NILP (Fx_selection_owner_p (Vmac_services_selection))) + { err = eventNotHandledErr; + break; + } + + copy_all_flavors: + { + UInt32 count, i; + ScrapFlavorInfo *flavor_info = NULL; + ScrapFlavorFlags flags; + + err = GetScrapFlavorCount (cur_scrap, &count); + if (err == noErr) + flavor_info = xmalloc (sizeof (ScrapFlavorInfo) * count); + if (flavor_info) + { + err = GetScrapFlavorInfoList (cur_scrap, &count, flavor_info); + if (err != noErr) + { + xfree (flavor_info); + flavor_info = NULL; + } + } + if (flavor_info == NULL) + break; + + for (i = 0; i < count; i++) + { + flavor_type = flavor_info[i].flavorType; + err = GetScrapFlavorFlags (cur_scrap, flavor_type, &flags); + if (err == noErr && !(flags & kScrapFlavorMaskSenderOnly)) + { + if (event_kind == kEventServiceCopy) + err = copy_scrap_flavor_data (cur_scrap, specific_scrap, + flavor_type); + else /* event_kind == kEventServiceGetTypes */ + { + type = CreateTypeStringWithOSType (flavor_type); + if (type) + { + CFArrayAppendValue (copy_types, type); + CFRelease (type); + } + } + } + } + xfree (flavor_info); } break; case kEventServicePaste: case kEventServicePerform: { - ScrapRef specific_scrap; - Lisp_Object rest, data; int data_exists_p = 0; err = GetEventParameter (event, kEventParamScrapRef, typeScrapRef, @@ -1033,25 +1352,24 @@ mac_handle_service_event (call_ref, event, data) { if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))))) continue; - data = get_scrap_string (specific_scrap, XCAR (XCAR (rest))); - if (STRINGP (data)) - { - err = put_scrap_string (cur_scrap, XCAR (XCAR (rest)), - data); - if (err != noErr) - break; - data_exists_p = 1; - } + flavor_type = get_flavor_type_from_symbol (XCAR (XCAR (rest))); + if (flavor_type == 0) + continue; + err = copy_scrap_flavor_data (specific_scrap, cur_scrap, + flavor_type); + if (err == noErr) + data_exists_p = 1; } - if (err == noErr) - if (data_exists_p) - mac_store_application_menu_event (event); - else - err = eventNotHandledErr; + if (!data_exists_p) + err = eventNotHandledErr; + else + err = mac_store_services_event (event); } break; } + if (err != noErr) + err = eventNotHandledErr; return err; } #endif @@ -1065,6 +1383,7 @@ syms_of_macselect () defsubr (&Sx_disown_selection_internal); defsubr (&Sx_selection_owner_p); defsubr (&Sx_selection_exists_p); + defsubr (&Smac_process_deferred_apple_events); Vselection_alist = Qnil; staticpro (&Vselection_alist); @@ -1106,6 +1425,10 @@ next communication only. After the communication, this variable is set to nil. */); Vnext_selection_coding_system = Qnil; + DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map, + doc: /* Keymap for Apple events handled by Emacs. */); + Vmac_apple_event_map = Qnil; + #ifdef MAC_OSX DEFVAR_LISP ("mac-services-selection", &Vmac_services_selection, doc: /* Selection name for communication via Services menu. */); @@ -1125,6 +1448,12 @@ set to nil. */); Qmac_ostype = intern ("mac-ostype"); staticpro (&Qmac_ostype); + + Qmac_apple_event_class = intern ("mac-apple-event-class"); + staticpro (&Qmac_apple_event_class); + + Qmac_apple_event_id = intern ("mac-apple-event-id"); + staticpro (&Qmac_apple_event_id); } /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732 diff --git a/src/macterm.c b/src/macterm.c index f0574c9078f..4e7b0fde4e2 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -68,7 +68,6 @@ Boston, MA 02110-1301, USA. */ #include <errno.h> #include <setjmp.h> #include <sys/stat.h> -#include <sys/param.h> #include "charset.h" #include "coding.h" @@ -89,22 +88,15 @@ Boston, MA 02110-1301, USA. */ #include "character.h" #include "ccl.h" -/* Set of macros that handle mapping of Mac modifier keys to emacs. */ -#define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \ - (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey)) -#define macShiftKey (shiftKey) -#define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \ - (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \ - : controlKey) -#define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey) /* Non-nil means Emacs uses toolkit scroll bars. */ Lisp_Object Vx_toolkit_scroll_bars; -/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */ -Lisp_Object Vmac_use_core_graphics; +/* If non-zero, the text will be rendered using Core Graphics text + rendering which may anti-alias the text. */ +int mac_use_core_graphics; /* Non-zero means that a HELP_EVENT has been generated since Emacs @@ -115,6 +107,10 @@ static int any_help_event_p; /* Last window where we saw the mouse. Used by mouse-autoselect-window. */ static Lisp_Object last_window; +/* Non-zero means make use of UNDERLINE_POSITION font properties. + (Not yet supported.) */ +int x_use_underline_position_properties; + /* This is a chain of structures for all the X displays currently in use. */ @@ -167,6 +163,7 @@ struct frame *pending_autoraise_frame; /* Where the mouse was last time we reported a mouse event. */ static Rect last_mouse_glyph; +static FRAME_PTR last_mouse_glyph_frame; /* The scroll bar in which the last X motion event occurred. @@ -208,7 +205,7 @@ extern EMACS_INT extra_keyboard_modifiers; /* The keysyms to use for the various modifiers. */ -static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value; +static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value; extern int inhibit_window_system; @@ -263,7 +260,7 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, unsigned long *)); static int is_emacs_window P_ ((WindowPtr)); - +static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int)); static void XSetFont P_ ((Display *, GC, XFontStruct *)); /* Defined in macmenu.h. */ @@ -630,7 +627,8 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout) ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)}; static ATSLineLayoutOptions line_layout = #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 - kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics + kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics + | kATSLineUseQDRendering #else kATSLineIsDisplayOnly | kATSLineFractDisable #endif @@ -695,7 +693,7 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 UInt32 textFlags, savedFlags; - if (!NILP(Vmac_use_core_graphics)) { + if (mac_use_core_graphics) { textFlags = kQDUseCGTextRendering; savedFlags = SwapQDTextFlags(textFlags); } @@ -718,10 +716,10 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) #ifndef WORDS_BIG_ENDIAN { int i; - Unichar *text = (Unichar *)buf; + UniChar *text = (UniChar *)buf; for (i = 0; i < nchars; i++) - text[i] = buf[2*i] << 8 | buf[2*i+1]; + text[i] = EndianU16_BtoN (text[i]); } #endif err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf, @@ -731,7 +729,7 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) if (err == noErr) { #ifdef MAC_OSX - if (NILP (Vmac_use_core_graphics)) + if (!mac_use_core_graphics) { #endif mac_begin_clip (GC_CLIP_REGION (gc)); @@ -775,11 +773,18 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) ATSUDrawText (text_layout, kATSUFromTextBeginning, kATSUToTextEnd, Long2Fix (x), Long2Fix (port_height - y)); + CGContextSynchronize (context); + QDEndCGContext (port, &context); +#if 0 + /* This doesn't work on Mac OS X 10.1. */ ATSUClearLayoutControls (text_layout, sizeof (tags) / sizeof (tags[0]), tags); - CGContextSynchronize (context); - QDEndCGContext (port, &context); +#else + ATSUSetLayoutControls (text_layout, + sizeof (tags) / sizeof (tags[0]), + tags, sizes, values); +#endif } #endif } @@ -803,7 +808,7 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char) if (mode != srcOr) RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 - if (!NILP(Vmac_use_core_graphics)) + if (mac_use_core_graphics) SwapQDTextFlags(savedFlags); #endif } @@ -865,6 +870,244 @@ mac_draw_image_string_16 (f, gc, x, y, buf, nchars) } +/* Mac replacement for XQueryTextExtents, but takes a character. If + STYLE is NULL, measurement is done by QuickDraw Text routines for + the font of the current graphics port. If CG_GLYPH is not NULL, + *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */ + +static OSErr +mac_query_char_extents (style, c, + font_ascent_return, font_descent_return, + overall_return, cg_glyph) +#if USE_ATSUI + ATSUStyle style; +#else + void *style; +#endif + int c; + int *font_ascent_return, *font_descent_return; + XCharStruct *overall_return; +#if USE_CG_TEXT_DRAWING + CGGlyph *cg_glyph; +#else + void *cg_glyph; +#endif +{ + OSErr err = noErr; + int width; + Rect char_bounds; + +#if USE_ATSUI + if (style) + { + ATSUTextLayout text_layout; + UniChar ch = c; + + err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout); + if (err == noErr) + { + ATSTrapezoid glyph_bounds; + + err = ATSUGetGlyphBounds (text_layout, 0, 0, + kATSUFromTextBeginning, kATSUToTextEnd, +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 + kATSUseFractionalOrigins, +#else + kATSUseDeviceOrigins, +#endif + 1, &glyph_bounds, NULL); + if (err == noErr) + { + xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x + == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); + + width = Fix2Long (glyph_bounds.upperRight.x + - glyph_bounds.upperLeft.x); + if (font_ascent_return) + *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y); + if (font_descent_return) + *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y); + } + } + if (err == noErr && overall_return) + { + err = ATSUMeasureTextImage (text_layout, + kATSUFromTextBeginning, kATSUToTextEnd, + 0, 0, &char_bounds); + if (err == noErr) + STORE_XCHARSTRUCT (*overall_return, width, char_bounds); +#if USE_CG_TEXT_DRAWING + if (err == noErr && cg_glyph) + { + OSErr err1; + ATSUGlyphInfoArray glyph_info_array; + ByteCount count = sizeof (ATSUGlyphInfoArray); + + err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning, + kATSUToTextEnd, NULL, NULL, NULL); + if (err1 == noErr) + err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning, + kATSUToTextEnd, &count, + &glyph_info_array); + if (err1 == noErr) + { + xassert (glyph_info_array.glyphs[0].glyphID); + *cg_glyph = glyph_info_array.glyphs[0].glyphID; + } + else + *cg_glyph = 0; + } +#endif + } + } + else +#endif + { + if (font_ascent_return || font_descent_return) + { + FontInfo font_info; + + GetFontInfo (&font_info); + if (font_ascent_return) + *font_ascent_return = font_info.ascent; + if (font_descent_return) + *font_descent_return = font_info.descent; + } + if (overall_return) + { + char ch = c; + + width = CharWidth (ch); + QDTextBounds (1, &ch, &char_bounds); + STORE_XCHARSTRUCT (*overall_return, width, char_bounds); + } + } + + return err; +} + + +/* Mac replacement for XTextExtents16. Only sets horizontal metrics. */ + +static int +mac_text_extents_16 (font_struct, string, nchars, overall_return) + XFontStruct *font_struct; + XChar2b *string; + int nchars; + XCharStruct *overall_return; +{ + int i; + short width = 0, lbearing = 0, rbearing = 0; + XCharStruct *pcm; + + for (i = 0; i < nchars; i++) + { + pcm = mac_per_char_metric (font_struct, string, 0); + if (pcm == NULL) + width += FONT_WIDTH (font_struct); + else + { + lbearing = min (lbearing, width + pcm->lbearing); + rbearing = max (rbearing, width + pcm->rbearing); + width += pcm->width; + } + string++; + } + + overall_return->lbearing = lbearing; + overall_return->rbearing = rbearing; + overall_return->width = width; + + /* What's the meaning of the return value of XTextExtents16? */ +} + + +#if USE_CG_TEXT_DRAWING +static int cg_text_anti_aliasing_threshold = 8; + +static void +init_cg_text_anti_aliasing_threshold () +{ + Lisp_Object val = + Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"), + Qnil, Qnil, Qnil); + + if (INTEGERP (val)) + cg_text_anti_aliasing_threshold = XINT (val); +} + +static int +mac_draw_string_cg (f, gc, x, y, buf, nchars) + struct frame *f; + GC gc; + int x, y; + XChar2b *buf; + int nchars; +{ + CGrafPtr port; + float port_height, gx, gy; + int i; + CGContextRef context; + CGGlyph *glyphs; + CGSize *advances; + + if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL) + return 0; + + port = GetWindowPort (FRAME_MAC_WINDOW (f)); + port_height = FRAME_PIXEL_HEIGHT (f); + gx = x; + gy = port_height - y; + glyphs = (CGGlyph *)buf; + advances = xmalloc (sizeof (CGSize) * nchars); + for (i = 0; i < nchars; i++) + { + XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0); + + advances[i].width = pcm->width; + advances[i].height = 0; + glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2]; + buf++; + } + + QDBeginCGContext (port, &context); + if (gc->n_clip_rects) + { + CGContextTranslateCTM (context, 0, port_height); + CGContextScaleCTM (context, 1, -1); + CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects); + CGContextScaleCTM (context, 1, -1); + CGContextTranslateCTM (context, 0, -port_height); + } + CGContextSetRGBFillColor (context, + RED_FROM_ULONG (gc->xgcv.foreground) / 255.0, + GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0, + BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0, + 1.0); + CGContextSetFont (context, GC_FONT (gc)->cg_font); + CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize); + if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold) + CGContextSetShouldAntialias (context, false); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + CGContextSetTextPosition (context, gx, gy); + CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars); +#else + for (i = 0; i < nchars; i++) + { + CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1); + gx += advances[i].width; + } +#endif + CGContextSynchronize (context); + QDEndCGContext (port, &context); + + xfree (advances); + + return 1; +} +#endif + + /* Mac replacement for XCopyArea: dest must be window. */ static void @@ -1636,59 +1879,32 @@ x_per_char_metric (font, char2b) #if USE_ATSUI if (font->mac_style) { - if (char2b->byte1 >= font->min_byte1 - && char2b->byte1 <= font->max_byte1 - && char2b->byte2 >= font->min_char_or_byte2 - && char2b->byte2 <= font->max_char_or_byte2) + XCharStructRow **row = font->bounds.rows + char2b->byte1; + + if (*row == NULL) { - pcm = (font->per_char - + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) - * (char2b->byte1 - font->min_byte1)) - + (char2b->byte2 - font->min_char_or_byte2)); + *row = xmalloc (sizeof (XCharStructRow)); + if (*row) + bzero (*row, sizeof (XCharStructRow)); } - - if (pcm && !pcm->valid_p) + if (*row) { - OSErr err; - ATSUTextLayout text_layout; - UniChar c; - int char_width; - ATSTrapezoid glyph_bounds; - Rect char_bounds; - - c = (char2b->byte1 << 8) + char2b->byte2; - BLOCK_INPUT; - err = atsu_get_text_layout_with_text_ptr (&c, 1, - font->mac_style, - &text_layout); - if (err == noErr) - err = ATSUMeasureTextImage (text_layout, - kATSUFromTextBeginning, kATSUToTextEnd, - 0, 0, &char_bounds); - - if (err == noErr) - err = ATSUGetGlyphBounds (text_layout, 0, 0, - kATSUFromTextBeginning, kATSUToTextEnd, - kATSUseFractionalOrigins, 1, - &glyph_bounds, NULL); - UNBLOCK_INPUT; - if (err != noErr) - pcm = NULL; - else + pcm = (*row)->per_char + char2b->byte2; + if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2)) { - xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x - == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); - - char_width = Fix2Long (glyph_bounds.upperRight.x - - glyph_bounds.upperLeft.x); - STORE_XCHARSTRUCT (*pcm, char_width, char_bounds); + BLOCK_INPUT; + mac_query_char_extents (font->mac_style, + (char2b->byte1 << 8) + char2b->byte2, + NULL, NULL, pcm, NULL); + UNBLOCK_INPUT; + XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2); } } } else { #endif - if (font->per_char != NULL) + if (font->bounds.per_char != NULL) { if (font->min_byte1 == 0 && font->max_byte1 == 0) { @@ -1701,7 +1917,8 @@ x_per_char_metric (font, char2b) if (char2b->byte1 == 0 && char2b->byte2 >= font->min_char_or_byte2 && char2b->byte2 <= font->max_char_or_byte2) - pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2; + pcm = font->bounds.per_char + + (char2b->byte2 - font->min_char_or_byte2); } else { @@ -1723,7 +1940,7 @@ x_per_char_metric (font, char2b) && char2b->byte2 >= font->min_char_or_byte2 && char2b->byte2 <= font->max_char_or_byte2) { - pcm = (font->per_char + pcm = (font->bounds.per_char + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) * (char2b->byte1 - font->min_byte1)) + (char2b->byte2 - font->min_char_or_byte2)); @@ -2064,67 +2281,32 @@ mac_compute_glyph_string_overhangs (s) { if (s->cmp == NULL && s->first_glyph->type == CHAR_GLYPH) - { - Rect r; - MacFontStruct *font = s->font; - + if (!s->two_byte_p #if USE_ATSUI - if (font->mac_style) - { - OSErr err; - ATSUTextLayout text_layout; - UniChar *buf; - int i; + || s->font->mac_style +#endif + ) + { + XCharStruct cs; - SetRect (&r, 0, 0, 0, 0); - buf = xmalloc (sizeof (UniChar) * s->nchars); - if (buf) - { - for (i = 0; i < s->nchars; i++) - buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2; + mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs); + s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; + s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; + } + else + { + Rect r; + MacFontStruct *font = s->font; - err = atsu_get_text_layout_with_text_ptr (buf, s->nchars, - font->mac_style, - &text_layout); - if (err == noErr) - err = ATSUMeasureTextImage (text_layout, - kATSUFromTextBeginning, - kATSUToTextEnd, - 0, 0, &r); - xfree (buf); - } - } - else - { -#endif - TextFont (font->mac_fontnum); - TextSize (font->mac_fontsize); - TextFace (font->mac_fontface); + TextFont (font->mac_fontnum); + TextSize (font->mac_fontsize); + TextFace (font->mac_fontface); - if (s->two_byte_p) QDTextBounds (s->nchars * 2, (char *)s->char2b, &r); - else - { - int i; - char *buf = xmalloc (s->nchars); - if (buf == NULL) - SetRect (&r, 0, 0, 0, 0); - else - { - for (i = 0; i < s->nchars; ++i) - buf[i] = s->char2b[i].byte2; - QDTextBounds (s->nchars, buf, &r); - xfree (buf); - } - } -#if USE_ATSUI - } -#endif - - s->right_overhang = r.right > s->width ? r.right - s->width : 0; - s->left_overhang = r.left < 0 ? -r.left : 0; - } + s->right_overhang = r.right > s->width ? r.right - s->width : 0; + s->left_overhang = r.left < 0 ? -r.left : 0; + } } @@ -2255,6 +2437,13 @@ x_draw_glyph_string_foreground (s) || GC_FONT (s->gc)->mac_style #endif ) +#if USE_CG_TEXT_DRAWING + if (!s->two_byte_p + && mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff, + s->char2b, s->nchars)) + ; + else +#endif mac_draw_string_16 (s->f, s->gc, x, s->ybase - boff, s->char2b, s->nchars); else @@ -3912,13 +4101,15 @@ note_mouse_movement (frame, pos) return 1; } /* Has the mouse moved off the glyph it was on at the last sighting? */ - if (!PtInRect (*pos, &last_mouse_glyph)) + if (frame != last_mouse_glyph_frame + || !PtInRect (*pos, &last_mouse_glyph)) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, pos->h, pos->v); /* Remember which glyph we're now on. */ remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph); + last_mouse_glyph_frame = frame; return 1; } @@ -4023,6 +4214,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) GetMouse (&mouse_pos); remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v, &last_mouse_glyph); + last_mouse_glyph_frame = f1; *bar_window = Qnil; *part = 0; @@ -6591,7 +6783,7 @@ mac_to_x_fontname (name, size, style, charset) sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s", style & bold ? "bold" : "medium", style & italic ? 'i' : 'r', - size, size * 10, size ? 75 : 0, size ? 75 : 0, size * 10, charset); + size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset); result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1); sprintf (result, "-%s-%s-%s", foundry, family, xf); @@ -6717,6 +6909,9 @@ init_font_name_table () text_encoding_info_alist = create_text_encoding_info_alist (); #if USE_ATSUI +#if USE_CG_TEXT_DRAWING + init_cg_text_anti_aliasing_threshold (); +#endif if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode), text_encoding_info_alist))) { @@ -7080,7 +7275,7 @@ mac_do_list_fonts (pattern, maxnames) continue; memcpy (scaled, font_name_table[i], former_len); sprintf (scaled + former_len, - "-%d-%d-75-75-m-%d-%s", + "-%d-%d-72-72-m-%d-%s", scl_val[XLFD_SCL_PIXEL_SIZE], scl_val[XLFD_SCL_POINT_SIZE], scl_val[XLFD_SCL_AVGWIDTH], @@ -7286,12 +7481,13 @@ is_fully_specified_xlfd (char *p) static MacFontStruct * XLoadQueryFont (Display *dpy, char *fontname) { - int i, size, char_width; + int size; char *name; Str255 family; Str31 charset; SInt16 fontnum; #if USE_ATSUI + static ATSUFontID font_id; ATSUStyle mac_style = NULL; #endif Style fontface; @@ -7302,6 +7498,7 @@ XLoadQueryFont (Display *dpy, char *fontname) short scriptcode; #endif MacFontStruct *font; + XCharStruct *space_bounds = NULL, *pcm; if (is_fully_specified_xlfd (fontname)) name = fontname; @@ -7326,13 +7523,14 @@ XLoadQueryFont (Display *dpy, char *fontname) kATSUQDBoldfaceTag, kATSUQDItalicTag}; ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed), sizeof (Boolean), sizeof (Boolean)}; - static ATSUFontID font_id; static Fixed size_fixed; static Boolean bold_p, italic_p; ATSUAttributeValuePtr values[] = {&font_id, &size_fixed, &bold_p, &italic_p}; - ATSUFontFeatureType types[] = {kAllTypographicFeaturesType}; - ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector}; + ATSUFontFeatureType types[] = {kAllTypographicFeaturesType, + kDiacriticsType}; + ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector, + kDecomposeDiacriticsSelector}; Lisp_Object font_id_cons; font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)), @@ -7380,6 +7578,10 @@ XLoadQueryFont (Display *dpy, char *fontname) font->mac_scriptcode = scriptcode; #if USE_ATSUI font->mac_style = mac_style; +#if USE_CG_TEXT_DRAWING + font->cg_font = NULL; + font->cg_glyphs = NULL; +#endif #endif /* Apple Japanese (SJIS) font is listed as both @@ -7395,83 +7597,103 @@ XLoadQueryFont (Display *dpy, char *fontname) if (font->mac_style) { OSErr err; - ATSUTextLayout text_layout; - UniChar c = 0x20; - Rect char_bounds, min_bounds, max_bounds; - int min_width, max_width; - ATSTrapezoid glyph_bounds; + UniChar c; - font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000); - if (font->per_char == NULL) + font->min_byte1 = 0; + font->max_byte1 = 0xff; + font->min_char_or_byte2 = 0; + font->max_char_or_byte2 = 0xff; + + font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100); + if (font->bounds.rows == NULL) { mac_unload_font (&one_mac_display_info, font); return NULL; } - bzero (font->per_char, sizeof (XCharStruct) * 0x10000); + bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100); + font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow)); + if (font->bounds.rows[0] == NULL) + { + mac_unload_font (&one_mac_display_info, font); + return NULL; + } + bzero (font->bounds.rows[0], sizeof (XCharStructRow)); - err = atsu_get_text_layout_with_text_ptr (&c, 1, - font->mac_style, - &text_layout); +#if USE_CG_TEXT_DRAWING + { + FMFontFamily font_family; + FMFontStyle style; + ATSFontRef ats_font; + + err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style); + if (err == noErr) + err = FMGetFontFromFontFamilyInstance (font_family, fontface, + &font_id, &style); + /* Use CG text drawing if italic/bold is not synthesized. */ + if (err == noErr && style == fontface) + { + ats_font = FMGetATSFontRefFromFont (font_id); + font->cg_font = CGFontCreateWithPlatformFont (&ats_font); + } + } + + if (font->cg_font) + font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100); + if (font->cg_glyphs) + bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100); +#endif + space_bounds = font->bounds.rows[0]->per_char + 0x20; + err = mac_query_char_extents (font->mac_style, 0x20, + &font->ascent, &font->descent, + space_bounds, +#if USE_CG_TEXT_DRAWING + (font->cg_glyphs ? font->cg_glyphs + 0x20 + : NULL) +#else + NULL +#endif + ); if (err != noErr) { mac_unload_font (&one_mac_display_info, font); return NULL; } + XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20); - for (c = 0x20; c <= 0x7e; c++) + pcm = font->bounds.rows[0]->per_char; + for (c = 0x21; c <= 0xff; c++) { - err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning); - if (err == noErr) - err = ATSUMeasureTextImage (text_layout, - kATSUFromTextBeginning, kATSUToTextEnd, - 0, 0, &char_bounds); - if (err == noErr) - err = ATSUGetGlyphBounds (text_layout, 0, 0, - kATSUFromTextBeginning, kATSUToTextEnd, - kATSUseFractionalOrigins, 1, - &glyph_bounds, NULL); - if (err == noErr) + if (c == 0xad) + /* Soft hyphen is not supported in ATSUI. */ + continue; + else if (c == 0x7f) { - xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x - == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); + c = 0x9f; + continue; + } - char_width = Fix2Long (glyph_bounds.upperRight.x - - glyph_bounds.upperLeft.x); - STORE_XCHARSTRUCT (font->per_char[c], - char_width, char_bounds); - if (c == 0x20) - { - min_width = max_width = char_width; - min_bounds = max_bounds = char_bounds; - font->ascent = -Fix2Long (glyph_bounds.upperLeft.y); - font->descent = Fix2Long (glyph_bounds.lowerLeft.y); - } - else - { - if (char_width > 0) - { - min_width = min (min_width, char_width); - max_width = max (max_width, char_width); - } - if (!EmptyRect (&char_bounds)) - { - SetRect (&min_bounds, - max (min_bounds.left, char_bounds.left), - max (min_bounds.top, char_bounds.top), - min (min_bounds.right, char_bounds.right), - min (min_bounds.bottom, char_bounds.bottom)); - UnionRect (&max_bounds, &char_bounds, &max_bounds); - } - } + mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c, +#if USE_CG_TEXT_DRAWING + (font->cg_glyphs ? font->cg_glyphs + c + : NULL) +#else + NULL +#endif + ); + XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c); + +#if USE_CG_TEXT_DRAWING + if (font->cg_glyphs && font->cg_glyphs[c] == 0) + { + /* Don't use CG text drawing if font substitution occurs in + ASCII or Latin-1 characters. */ + CGFontRelease (font->cg_font); + font->cg_font = NULL; + xfree (font->cg_glyphs); + font->cg_glyphs = NULL; } +#endif } - STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); - STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); - - font->min_byte1 = 0; - font->max_byte1 = 0xff; - font->min_char_or_byte2 = 0; - font->max_char_or_byte2 = 0xff; } else #endif @@ -7510,6 +7732,8 @@ XLoadQueryFont (Display *dpy, char *fontname) if (is_two_byte_font) { + int char_width; + font->min_byte1 = 0xa1; font->max_byte1 = 0xfe; font->min_char_or_byte2 = 0xa1; @@ -7538,21 +7762,8 @@ XLoadQueryFont (Display *dpy, char *fontname) char_width = StringWidth("\p\xa1\xa1"); break; } - } - else - { - font->min_byte1 = font->max_byte1 = 0; - font->min_char_or_byte2 = 0x20; - font->max_char_or_byte2 = 0xff; - - /* Do this instead of use the_fontinfo.widMax, which - incorrectly returns 15 for 12-point Monaco! */ - char_width = CharWidth ('m'); - } - if (is_two_byte_font) - { - font->per_char = NULL; + font->bounds.per_char = NULL; if (fontface & italic) font->max_bounds.rbearing = char_width + 1; @@ -7567,49 +7778,28 @@ XLoadQueryFont (Display *dpy, char *fontname) } else { - int c, min_width, max_width; - Rect char_bounds, min_bounds, max_bounds; - char ch; + int c; - font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); - bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1)); + font->min_byte1 = font->max_byte1 = 0; + font->min_char_or_byte2 = 0x20; + font->max_char_or_byte2 = 0xff; - min_width = max_width = char_width; - SetRect (&min_bounds, -32767, -32767, 32767, 32767); - SetRect (&max_bounds, 0, 0, 0, 0); - for (c = 0x20; c <= 0xff; c++) + font->bounds.per_char = + xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); + if (font->bounds.per_char == NULL) { - ch = c; - char_width = CharWidth (ch); - QDTextBounds (1, &ch, &char_bounds); - STORE_XCHARSTRUCT (font->per_char[c - 0x20], - char_width, char_bounds); - /* Some Japanese fonts (in SJIS encoding) return 0 as - the character width of 0x7f. */ - if (char_width > 0) - { - min_width = min (min_width, char_width); - max_width = max (max_width, char_width); - } - if (!EmptyRect (&char_bounds)) - { - SetRect (&min_bounds, - max (min_bounds.left, char_bounds.left), - max (min_bounds.top, char_bounds.top), - min (min_bounds.right, char_bounds.right), - min (min_bounds.bottom, char_bounds.bottom)); - UnionRect (&max_bounds, &char_bounds, &max_bounds); - } - } - STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); - STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); - if (min_width == max_width - && max_bounds.left >= 0 && max_bounds.right <= max_width) - { - /* Fixed width and no overhangs. */ - xfree (font->per_char); - font->per_char = NULL; + mac_unload_font (&one_mac_display_info, font); + return NULL; } + bzero (font->bounds.per_char, + sizeof (XCharStruct) * (0xff - 0x20 + 1)); + + space_bounds = font->bounds.per_char; + mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent, + space_bounds, NULL); + + for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++) + mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL); } /* Restore previous font number, size and face. */ @@ -7618,6 +7808,55 @@ XLoadQueryFont (Display *dpy, char *fontname) TextFace (old_fontface); } + if (space_bounds) + { + int c; + + font->min_bounds = font->max_bounds = *space_bounds; + for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++) + if (pcm->width > 0) + { + font->min_bounds.lbearing = min (font->min_bounds.lbearing, + pcm->lbearing); + font->min_bounds.rbearing = min (font->min_bounds.rbearing, + pcm->rbearing); + font->min_bounds.width = min (font->min_bounds.width, + pcm->width); + font->min_bounds.ascent = min (font->min_bounds.ascent, + pcm->ascent); + + font->max_bounds.lbearing = max (font->max_bounds.lbearing, + pcm->lbearing); + font->max_bounds.rbearing = max (font->max_bounds.rbearing, + pcm->rbearing); + font->max_bounds.width = max (font->max_bounds.width, + pcm->width); + font->max_bounds.ascent = max (font->max_bounds.ascent, + pcm->ascent); + } + if ( +#if USE_ATSUI + font->mac_style == NULL && +#endif + font->max_bounds.width == font->min_bounds.width + && font->min_bounds.lbearing >= 0 + && font->max_bounds.rbearing <= font->max_bounds.width) + { + /* Fixed width and no overhangs. */ + xfree (font->bounds.per_char); + font->bounds.per_char = NULL; + } + } + +#if !defined (MAC_OS8) || USE_ATSUI + /* AppKit and WebKit do some adjustment to the heights of Courier, + Helvetica, and Times. This only works on the environments where + the XDrawImageString counterpart is never used. */ + if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0 + || strcmp (family, "times") == 0) + font->ascent += (font->ascent + font->descent) * .15 + 0.5; +#endif + return font; } @@ -7628,11 +7867,26 @@ mac_unload_font (dpyinfo, font) XFontStruct *font; { xfree (font->full_name); - if (font->per_char) - xfree (font->per_char); #if USE_ATSUI if (font->mac_style) - ATSUDisposeStyle (font->mac_style); + { + int i; + + for (i = font->min_byte1; i <= font->max_byte1; i++) + if (font->bounds.rows[i]) + xfree (font->bounds.rows[i]); + xfree (font->bounds.rows); + ATSUDisposeStyle (font->mac_style); + } + else +#endif + if (font->bounds.per_char) + xfree (font->bounds.per_char); +#if USE_CG_TEXT_DRAWING + if (font->cg_font) + CGFontRelease (font->cg_font); + if (font->cg_glyphs) + xfree (font->cg_glyphs); #endif xfree (font); } @@ -7922,31 +8176,35 @@ x_find_ccl_program (fontp) /* Contains the string "reverse", which is a constant for mouse button emu.*/ Lisp_Object Qreverse; -/* True if using command key as meta key. */ -Lisp_Object Vmac_command_key_is_meta; -/* Modifier associated with the option key, or nil for normal behavior. */ +/* Modifier associated with the control key, or nil to ignore. */ +Lisp_Object Vmac_control_modifier; + +/* Modifier associated with the option key, or nil to ignore. */ Lisp_Object Vmac_option_modifier; -/* True if the ctrl and meta keys should be reversed. */ -Lisp_Object Vmac_reverse_ctrl_meta; +/* Modifier associated with the command key, or nil to ignore. */ +Lisp_Object Vmac_command_modifier; + +/* Modifier associated with the function key, or nil to ignore. */ +Lisp_Object Vmac_function_modifier; /* True if the option and command modifiers should be used to emulate a three button mouse */ Lisp_Object Vmac_emulate_three_button_mouse; #if USE_CARBON_EVENTS -/* True if the mouse wheel button (i.e. button 4) should map to +/* Non-zero if the mouse wheel button (i.e. button 4) should map to mouse-2, instead of mouse-3. */ -Lisp_Object Vmac_wheel_button_is_mouse_2; +int mac_wheel_button_is_mouse_2; -/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox +/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox for processing before Emacs sees it. */ -Lisp_Object Vmac_pass_command_to_system; +int mac_pass_command_to_system; -/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox +/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox for processing before Emacs sees it. */ -Lisp_Object Vmac_pass_control_to_system; +int mac_pass_control_to_system; #endif /* Points to the variable `inev' in the function XTread_socket. It is @@ -7954,20 +8212,19 @@ Lisp_Object Vmac_pass_control_to_system; Carbon/Apple event handlers. */ static struct input_event *read_socket_inev = NULL; -/* Set in term/mac-win.el to indicate that event loop can now generate - drag and drop events. */ -Lisp_Object Qmac_ready_for_drag_n_drop; - Point saved_menu_event_location; /* Apple Events */ -static void init_required_apple_events (void); -static pascal OSErr -do_ae_open_application (const AppleEvent *, AppleEvent *, long); -static pascal OSErr -do_ae_print_documents (const AppleEvent *, AppleEvent *, long); -static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long); -static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long); +#if USE_CARBON_EVENTS +static Lisp_Object Qhicommand; +#endif +extern int mac_ready_for_apple_events; +extern Lisp_Object Qundefined; +extern void init_apple_event_handler P_ ((void)); +extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID, + Lisp_Object *, Lisp_Object *, + Lisp_Object *)); +extern OSErr init_coercion_handler P_ ((void)); #if TARGET_API_MAC_CARBON /* Drag and Drop */ @@ -7977,11 +8234,10 @@ static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL; static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL; #endif -static Lisp_Object Qapplication, Qabout; #if USE_CARBON_EVENTS #ifdef MAC_OSX extern void init_service_handler (); -static Lisp_Object Qpreferences, Qservices, Qpaste, Qperform; +static Lisp_Object Qservices, Qpaste, Qperform; #endif /* Window Event Handler */ static pascal OSStatus mac_handle_window_event (EventHandlerCallRef, @@ -8003,20 +8259,42 @@ mac_to_emacs_modifiers (EventModifiers mods) #endif { unsigned int result = 0; - if (mods & macShiftKey) + if (mods & shiftKey) result |= shift_modifier; - if (mods & macCtrlKey) - result |= ctrl_modifier; - if (mods & macMetaKey) - result |= meta_modifier; - if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey)) - result |= alt_modifier; + + /* Deactivated to simplify configuration: + if Vmac_option_modifier is non-NIL, we fully process the Option + key. Otherwise, we only process it if an additional Ctrl or Command + is pressed. That way the system may convert the character to a + composed one. + if ((mods & optionKey) && + (( !NILP(Vmac_option_modifier) || + ((mods & cmdKey) || (mods & controlKey))))) */ + if (!NILP (Vmac_option_modifier) && (mods & optionKey)) { - Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value); - if (!NILP(val)) - result |= XUINT(val); + Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); + } + if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) { + Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); + } + if (!NILP (Vmac_control_modifier) && (mods & controlKey)) { + Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); } +#ifdef MAC_OSX + if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) { + Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); + } +#endif + return result; } @@ -8037,7 +8315,7 @@ mac_get_emulated_btn ( UInt32 modifiers ) #if USE_CARBON_EVENTS /* Obtains the event modifiers from the event ref and then calls mac_to_emacs_modifiers. */ -static int +static UInt32 mac_event_to_emacs_modifiers (EventRef eventRef) { UInt32 mods = 0; @@ -8071,10 +8349,10 @@ mac_get_mouse_btn (EventRef ref) return mac_get_emulated_btn(mods); } case kEventMouseButtonSecondary: - return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2; + return mac_wheel_button_is_mouse_2 ? 2 : 1; case kEventMouseButtonTertiary: case 4: /* 4 is the number for the mouse wheel button */ - return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1; + return mac_wheel_button_is_mouse_2 ? 1 : 2; default: return 0; } @@ -8502,179 +8780,49 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out) x_real_positions (f, &f->left_pos, &f->top_pos); } -/* Intialize AppleEvent dispatcher table for the required events. */ -void -init_required_apple_events () -{ - OSErr err; - long result; - - /* Make sure we have apple events before starting. */ - err = Gestalt (gestaltAppleEventsAttr, &result); - if (err != noErr) - abort (); - - if (!(result & (1 << gestaltAppleEventsPresent))) - abort (); - -#if TARGET_API_MAC_CARBON - err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, - NewAEEventHandlerUPP - ((AEEventHandlerProcPtr) do_ae_open_application), - 0L, false); -#else - err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, - NewAEEventHandlerProc - ((AEEventHandlerProcPtr) do_ae_open_application), - 0L, false); -#endif - if (err != noErr) - abort (); - -#if TARGET_API_MAC_CARBON - err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, - NewAEEventHandlerUPP - ((AEEventHandlerProcPtr) do_ae_open_documents), - 0L, false); -#else - err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, - NewAEEventHandlerProc - ((AEEventHandlerProcPtr) do_ae_open_documents), - 0L, false); -#endif - if (err != noErr) - abort (); - -#if TARGET_API_MAC_CARBON - err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, - NewAEEventHandlerUPP - ((AEEventHandlerProcPtr) do_ae_print_documents), - 0L, false); -#else - err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, - NewAEEventHandlerProc - ((AEEventHandlerProcPtr) do_ae_print_documents), - 0L, false); -#endif - if (err != noErr) - abort (); - -#if TARGET_API_MAC_CARBON - err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, - NewAEEventHandlerUPP - ((AEEventHandlerProcPtr) do_ae_quit_application), - 0L, false); -#else - err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, - NewAEEventHandlerProc - ((AEEventHandlerProcPtr) do_ae_quit_application), - 0L, false); -#endif - if (err != noErr) - abort (); -} - -void -mac_store_application_menu_event (event) -#if USE_CARBON_EVENTS - EventRef event; -#else - UInt32 event; -#endif +OSErr +mac_store_apple_event (class, id, desc) + Lisp_Object class, id; + const AEDesc *desc; { + OSErr err = noErr; struct input_event buf; - Lisp_Object frame, entry; - - EVENT_INIT (buf); - - XSETFRAME (frame, mac_focus_frame (&one_mac_display_info)); - buf.kind = MENU_BAR_EVENT; - buf.frame_or_window = frame; - buf.arg = frame; - kbd_buffer_store_event (&buf); + AEDesc *desc_copy; - buf.arg = Qapplication; - kbd_buffer_store_event (&buf); - -#if USE_CARBON_EVENTS - switch (GetEventClass (event)) + desc_copy = xmalloc (sizeof (AEDesc)); + if (desc_copy == NULL) + err = memFullErr; + else + err = AEDuplicateDesc (desc, desc_copy); + if (err == noErr) { -#ifdef MAC_OSX - case kEventClassService: - buf.arg = Qservices; - kbd_buffer_store_event (&buf); - switch (GetEventKind (event)) - { - case kEventServicePaste: - entry = Qpaste; - break; + EVENT_INIT (buf); - case kEventServicePerform: - { - OSErr err; - CFStringRef message; - - err = GetEventParameter (event, kEventParamServiceMessageName, - typeCFStringRef, NULL, - sizeof (CFStringRef), NULL, &message); - buf.arg = Qperform; - kbd_buffer_store_event (&buf); - if (err == noErr && message) - entry = intern (SDATA (cfstring_to_lisp (message))); - else - entry = Qnil; - } - break; + buf.kind = MAC_APPLE_EVENT; + buf.x = class; + buf.y = id; + buf.code = (int)desc_copy; + XSETFRAME (buf.frame_or_window, + mac_focus_frame (&one_mac_display_info)); + buf.arg = Qnil; + kbd_buffer_store_event (&buf); + } - default: - abort (); - } - break; -#endif /* MAC_OSX */ - case kEventClassCommand: - { - HICommand command; + return err; +} - GetEventParameter(event, kEventParamDirectObject, typeHICommand, - NULL, sizeof (HICommand), NULL, &command); - switch (command.commandID) - { - case kHICommandAbout: - entry = Qabout; - break; -#ifdef MAC_OSX - case kHICommandPreferences: - entry = Qpreferences; - break; -#endif /* MAC_OSX */ - case kHICommandQuit: - entry = Qquit; - break; - default: - abort (); - } - } - break; +Lisp_Object +mac_make_lispy_event_code (code) + int code; +{ + AEDesc *desc = (AEDesc *)code; + Lisp_Object obj; - default: - abort (); - } -#else /* USE_CARBON_EVENTS */ - switch (event) - { - case kHICommandAbout: - entry = Qabout; - break; - case kHICommandQuit: - entry = Qquit; - break; - default: - abort (); - } -#endif + obj = mac_aedesc_to_lisp (desc); + AEDisposeDesc (desc); + xfree (desc); - buf.arg = entry; - kbd_buffer_store_event (&buf); + return obj; } #if USE_CARBON_EVENTS @@ -8684,28 +8832,47 @@ mac_handle_command_event (next_handler, event, data) EventRef event; void *data; { + OSStatus result; + OSErr err; HICommand command; - OSErr result; + Lisp_Object class_key, id_key, binding; - GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, - sizeof (HICommand), NULL, &command); + result = CallNextEventHandler (next_handler, event); + if (result != eventNotHandledErr) + return result; - switch (command.commandID) - { - case kHICommandAbout: -#ifdef MAC_OSX - case kHICommandPreferences: -#endif /* MAC_OSX */ - result = CallNextEventHandler (next_handler, event); - if (result != eventNotHandledErr) - return result; + GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, + sizeof (HICommand), NULL, &command); - mac_store_application_menu_event (event); - return noErr; + if (command.commandID == 0) + return eventNotHandledErr; - default: - break; - } + /* A HICommand event is mapped to an Apple event whose event class + symbol is `hicommand' and event ID is its command ID. */ + class_key = Qhicommand; + mac_find_apple_event_spec (0, command.commandID, + &class_key, &id_key, &binding); + if (!NILP (binding) && !EQ (binding, Qundefined)) + if (INTEGERP (binding)) + return XINT (binding); + else + { + AppleEvent apple_event; + UInt32 modifiers; + static EventParamName names[] = {kEventParamDirectObject, + kEventParamKeyModifiers}; + static EventParamType types[] = {typeHICommand, + typeUInt32}; + err = create_apple_event_from_event_ref (event, 2, names, types, + &apple_event); + if (err == noErr) + { + err = mac_store_apple_event (class_key, id_key, &apple_event); + AEDisposeDesc (&apple_event); + } + if (err == noErr) + return noErr; + } return eventNotHandledErr; } @@ -8867,6 +9034,50 @@ mac_handle_mouse_event (next_handler, event, data) return eventNotHandledErr; } + +#ifdef MAC_OSX +OSErr +mac_store_services_event (event) + EventRef event; +{ + OSErr err; + AppleEvent apple_event; + Lisp_Object id_key; + + switch (GetEventKind (event)) + { + case kEventServicePaste: + id_key = Qpaste; + err = create_apple_event_from_event_ref (event, 0, NULL, NULL, + &apple_event); + break; + + case kEventServicePerform: + { + static EventParamName names[] = {kEventParamServiceMessageName, + kEventParamServiceUserData}; + static EventParamType types[] = {typeCFStringRef, + typeCFStringRef}; + + id_key = Qperform; + err = create_apple_event_from_event_ref (event, 2, names, types, + &apple_event); + } + break; + + default: + abort (); + } + + if (err == noErr) + { + err = mac_store_apple_event (Qservices, id_key, &apple_event); + AEDisposeDesc (&apple_event); + } + + return err; +} +#endif /* MAC_OSX */ #endif /* USE_CARBON_EVENTS */ @@ -8925,159 +9136,6 @@ remove_window_handler (window) #endif } -/* Open Application Apple Event */ -static pascal OSErr -do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon) -{ - return noErr; -} - - -/* Called when we receive an AppleEvent with an ID of - "kAEOpenDocuments". This routine gets the direct parameter, - extracts the FSSpecs in it, and puts their names on a list. */ -#pragma options align=mac68k -typedef struct SelectionRange { - short unused1; // 0 (not used) - short lineNum; // line to select (<0 to specify range) - long startRange; // start of selection range (if line < 0) - long endRange; // end of selection range (if line < 0) - long unused2; // 0 (not used) - long theDate; // modification date/time -} SelectionRange; -#pragma options align=reset - -static pascal OSErr -do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon) -{ - OSErr err, err2; - AEDesc the_desc; - AEKeyword keyword; - DescType actual_type; - Size actual_size; - SelectionRange position; - Lisp_Object file_list = Qnil; - - xassert (read_socket_inev); - - err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc); - if (err != noErr) - goto descriptor_error_exit; - - err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size); - if (err == noErr) - file_list = Fcons (list3 (make_number (position.lineNum + 1), - make_number (position.startRange + 1), - make_number (position.endRange + 1)), - file_list); - - /* Check to see that we got all of the required parameters from the - event descriptor. For an 'odoc' event this should just be the - file list. */ - err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard, - &actual_type, (Ptr) &keyword, - sizeof (keyword), &actual_size); - /* No error means that we found some unused parameters. - errAEDescNotFound means that there are no more parameters. If we - get an error code other than that, flag it. */ - if ((err == noErr) || (err != errAEDescNotFound)) - { - err = errAEEventNotHandled; - goto error_exit; - } - err = noErr; - - /* Got all the parameters we need. Now, go through the direct - object list and parse it up. */ - { - long num_files_to_open; - - err = AECountItems (&the_desc, &num_files_to_open); - if (err == noErr) - { - int i; - - /* AE file list is one based so just use that for indexing here. */ - for (i = 1; i <= num_files_to_open; i++) - { - char unix_path_name[MAXPATHLEN]; -#ifdef MAC_OSX - FSRef fref; - - err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword, - &actual_type, &fref, sizeof (FSRef), - &actual_size); - if (err != noErr || actual_type != typeFSRef) - continue; - - if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)) - == noErr) -#else - FSSpec fs; - - err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type, - (Ptr) &fs, sizeof (fs), &actual_size); - if (err != noErr) continue; - - if (fsspec_to_posix_pathname (&fs, unix_path_name, - sizeof (unix_path_name) - 1) == noErr) -#endif - /* x-dnd functions expect undecoded filenames. */ - file_list = Fcons (make_unibyte_string (unix_path_name, - strlen (unix_path_name)), - file_list); - } - } - - /* Build a DRAG_N_DROP_EVENT type event as is done in - constuct_drag_n_drop in w32term.c. */ - if (!NILP (file_list)) - { - struct frame *f = mac_focus_frame (&one_mac_display_info); - WindowPtr wp; - Lisp_Object frame; - - read_socket_inev->kind = DRAG_N_DROP_EVENT; - read_socket_inev->code = 0; - read_socket_inev->modifiers = 0; - - XSETINT (read_socket_inev->x, 0); - XSETINT (read_socket_inev->y, 0); - - XSETFRAME (frame, f); - read_socket_inev->frame_or_window = Fcons (frame, file_list); - -#if 0 - /* Regardless of whether Emacs was suspended or in the - foreground, ask it to redraw its entire screen. Otherwise - parts of the screen can be left in an inconsistent - state. */ - wp = FRAME_MAC_WINDOW (f); - if (wp) -#if TARGET_API_MAC_CARBON - { - Rect r; - - GetWindowPortBounds (wp, &r); - InvalWindowRect (wp, &r); - } -#else /* not TARGET_API_MAC_CARBON */ - InvalRect (&(wp->portRect)); -#endif /* not TARGET_API_MAC_CARBON */ -#endif - } - } - -error_exit: - /* Nuke the coerced file list in any case */ - err2 = AEDisposeDesc(&the_desc); - -descriptor_error_exit: - /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */ - return err; -} - - #if TARGET_API_MAC_CARBON static pascal OSErr mac_do_track_drag (DragTrackingMessage message, WindowPtr window, @@ -9173,25 +9231,25 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags); if (result == noErr) { -#ifdef MAC_OSX - FSRef fref; -#endif - char unix_path_name[MAXPATHLEN]; + OSErr err; + AEDesc desc; - GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L); -#ifdef MAC_OSX - /* Use Carbon routines, otherwise it converts the file name - to /Macintosh HD/..., which is not correct. */ - FSpMakeFSRef (&data.fileSpec, &fref); - if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))); -#else - if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name, - sizeof (unix_path_name) - 1) == noErr) -#endif - /* x-dnd functions expect undecoded filenames. */ - file_list = Fcons (make_unibyte_string (unix_path_name, - strlen (unix_path_name)), - file_list); + err = GetFlavorData (theDrag, theItem, flavorTypeHFS, + &data, &size, 0L); + if (err == noErr) + err = AECoercePtr (typeFSS, &data.fileSpec, sizeof (FSSpec), + TYPE_FILE_NAME, &desc); + if (err == noErr) + { + Lisp_Object file; + + /* x-dnd functions expect undecoded filenames. */ + file = make_uninit_string (AEGetDescDataSize (&desc)); + err = AEGetDescData (&desc, SDATA (file), SBYTES (file)); + if (err == noErr) + file_list = Fcons (file, file_list); + AEDisposeDesc (&desc); + } } } /* If there are items in the list, construct an event and post it to @@ -9213,8 +9271,8 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, XSETINT (event.x, mouse.h); XSETINT (event.y, mouse.v); XSETFRAME (frame, f); - event.frame_or_window = Fcons (frame, file_list); - event.arg = Qnil; + event.frame_or_window = frame; + event.arg = file_list; /* Post to the interrupt queue */ kbd_buffer_store_event (&event); /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */ @@ -9232,44 +9290,6 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, #endif -/* Print Document Apple Event */ -static pascal OSErr -do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon) -{ - return errAEEventNotHandled; -} - - -static pascal OSErr -do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon) -{ -#if USE_CARBON_EVENTS - OSErr err; - EventRef event = NULL; - static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit}; - - err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0, - kEventAttributeUserEvent, &event); - if (err == noErr) - err = SetEventParameter (event, kEventParamDirectObject, typeHICommand, - sizeof (HICommand), &quit_command); - if (err == noErr) - mac_store_application_menu_event (event); - if (event) - ReleaseEvent (event); - - if (err == noErr) - return noErr; - else - return errAEEventNotHandled; -#else - mac_store_application_menu_event (kHICommandQuit); - - return noErr; -#endif -} - - #if __profile__ void profiler_exit_proc () @@ -9321,9 +9341,11 @@ main (void) init_environ (); + init_coercion_handler (); + initialize_applescript (); - init_required_apple_events (); + init_apple_event_handler (); { char **argv; @@ -9387,6 +9409,7 @@ static unsigned char keycode_to_xkeysym_table[] = { /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0 }; + static int keycode_to_xkeysym (int keyCode, int *xKeySym) { @@ -9394,6 +9417,124 @@ keycode_to_xkeysym (int keyCode, int *xKeySym) return *xKeySym != 0; } +static unsigned char fn_keycode_to_xkeysym_table[] = { + /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + /*0x30*/ 0, 0, 0, 0, + /*0x34*/ 0, 0, 0, 0, + /*0x38*/ 0, 0, 0, 0, + /*0x3C*/ 0, 0, 0, 0, + + /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/, + /*0x44*/ 0, '/' /*kp-+*/, 0, 0, + /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/, + /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0, + + /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/, + /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/, + /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/, + /*0x5C*/ '9' /*kp-9*/, 0, 0, 0, + + /*0x60*/ 0, 0, 0, 0, + /*0x64*/ 0, 0, 0, 0, + /*0x68*/ 0, 0, 0, 0, + /*0x6C*/ 0, 0, 0, 0, + + /*0x70*/ 0, 0, 0, 0, + /*0x74*/ 0, 0, 0, 0, + /*0x78*/ 0, 0, 0, 0, + /*0x7C*/ 0, 0, 0, 0 +}; +static int +convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode) +{ +#ifdef MAC_OSX + /* Use the special map to translate keys when function modifier is + to be caught. KeyTranslate can't be used in that case. + We can't detect the function key using the input_event.modifiers, + because this uses the high word of an UInt32. Therefore, + we'll just read it out of the original eventRef. + */ + + + /* TODO / known issues + + - Fn-Shift-j is regonized as Fn-j and not Fn-J. + The above table always translates to lower characters. We need to use + the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*. + + - The table is meant for English language keyboards, and it will work + for many others with the exception of key combinations like Fn-ö on + a German keyboard, which is currently mapped to Fn-;. + How to solve this without keeping separate tables for all keyboards + around? KeyTranslate isn't of much help here, as it only takes a 16-bit + value for keycode with the modifiers in he high byte, i.e. no room for the + Fn modifier. That's why we need the table. + + */ + + UInt32 mods = 0; + if (!NILP(Vmac_function_modifier)) + { + GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL, + sizeof (UInt32), NULL, &mods); + if (mods & kEventKeyModifierFnMask) + { *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f]; + + return (*newCode != 0); + } + } +#endif + return false; +} + +static int +backtranslate_modified_keycode(int mods, int keycode, int def) +{ + EventModifiers mapped_modifiers = + (NILP (Vmac_control_modifier) ? 0 : controlKey) + | (NILP (Vmac_option_modifier) ? 0 : optionKey) + | (NILP (Vmac_command_modifier) ? 0 : cmdKey); + + if (mods & mapped_modifiers) + { + /* This code comes from Keyboard Resource, + Appendix C of IM - Text. This is necessary + since shift is ignored in KCHR table + translation when option or command is pressed. + It also does not translate correctly + control-shift chars like C-% so mask off shift + here also. + + Not done for combinations with the option key (alt) + unless it is to be caught by Emacs: this is + to preserve key combinations translated by the OS + such as Alt-3. + */ + /* Mask off modifier keys that are mapped to some Emacs + modifiers. */ + int new_modifiers = mods & ~mapped_modifiers; + /* set high byte of keycode to modifier high byte*/ + int new_keycode = keycode | new_modifiers; + Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); + unsigned long some_state = 0; + return (int) KeyTranslate (kchr_ptr, new_keycode, + &some_state) & 0xff; + /* TO DO: Recognize two separate resulting characters, "for + example, when the user presses Option-E followed by N, you + can map this through the KeyTranslate function using the + U.S. 'KCHR' resource to produce ´n, which KeyTranslate + returns as two characters in the bytes labeled Character code + 1 and Character code 2." (from Carbon API doc) */ + + } + else + return def; +} + + #if !USE_CARBON_EVENTS static RgnHandle mouse_region = NULL; @@ -9411,7 +9552,7 @@ mac_wait_next_event (er, sleep_time, dequeue) mouse_region = NewRgn (); event_mask = everyEvent; - if (NILP (Fboundp (Qmac_ready_for_drag_n_drop))) + if (!mac_ready_for_apple_events) event_mask -= highLevelEventMask; current_tick = TickCount (); @@ -9522,6 +9663,7 @@ XTread_socket (sd, expected, hold_quit) != eventNotHandledErr) break; #endif + last_mouse_glyph_frame = 0; if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -9933,12 +10075,11 @@ XTread_socket (sd, expected, hold_quit) will pass back noErr, otherwise it will pass back "eventNotHandledErr" and we can process it normally. */ - if ((!NILP (Vmac_pass_command_to_system) + if ((mac_pass_command_to_system || !(er.modifiers & cmdKey)) - && (!NILP (Vmac_pass_control_to_system) + && (mac_pass_control_to_system || !(er.modifiers & controlKey)) - && (!NILP (Vmac_command_key_is_meta) - && NILP (Vmac_option_modifier) + && (NILP (Vmac_option_modifier) || !(er.modifiers & optionKey))) if (SendEventToEventTarget (eventRef, toolbox_dispatcher) != eventNotHandledErr) @@ -9982,49 +10123,34 @@ XTread_socket (sd, expected, hold_quit) dpyinfo->mouse_face_hidden = 1; } - if (keycode_to_xkeysym (keycode, &xkeysym)) - { - inev.code = 0xff00 | xkeysym; - inev.kind = NON_ASCII_KEYSTROKE_EVENT; - } - else + /* translate the keycode back to determine the original key */ + /* Convert key code if function key is pressed. + Otherwise, if non-ASCII-event, take care of that + without re-translating the key code. */ +#if USE_CARBON_EVENTS + if (convert_fn_keycode (eventRef, keycode, &xkeysym)) { - if (er.modifiers & (controlKey | - (NILP (Vmac_command_key_is_meta) ? optionKey - : cmdKey))) - { - /* This code comes from Keyboard Resource, - Appendix C of IM - Text. This is necessary - since shift is ignored in KCHR table - translation when option or command is pressed. - It also does not translate correctly - control-shift chars like C-% so mask off shift - here also */ - int new_modifiers = er.modifiers & 0xe600; - /* mask off option and command */ - int new_keycode = keycode | new_modifiers; - Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); - unsigned long some_state = 0; - inev.code = KeyTranslate (kchr_ptr, new_keycode, - &some_state) & 0xff; - } - else if (!NILP (Vmac_option_modifier) - && (er.modifiers & optionKey)) - { - /* When using the option key as an emacs modifier, - convert the pressed key code back to one - without the Mac option modifier applied. */ - int new_modifiers = er.modifiers & ~optionKey; - int new_keycode = keycode | new_modifiers; - Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); - unsigned long some_state = 0; - inev.code = KeyTranslate (kchr_ptr, new_keycode, - &some_state) & 0xff; - } - else - inev.code = er.message & charCodeMask; + inev.code = xkeysym; + /* this doesn't work - tried to add shift modifiers */ + inev.code = + backtranslate_modified_keycode(er.modifiers & (~0x2200), + xkeysym | 0x80, xkeysym); inev.kind = ASCII_KEYSTROKE_EVENT; } + else +#endif + if (keycode_to_xkeysym (keycode, &xkeysym)) + { + inev.code = 0xff00 | xkeysym; + inev.kind = NON_ASCII_KEYSTROKE_EVENT; + } + else + { + inev.code = + backtranslate_modified_keycode(er.modifiers, keycode, + er.message & charCodeMask); + inev.kind = ASCII_KEYSTROKE_EVENT; + } } #if USE_CARBON_EVENTS @@ -10251,8 +10377,8 @@ mac_initialize_display_info () main_device_handle = LMGetMainDevice(); dpyinfo->reference_count = 0; - dpyinfo->resx = 75.0; - dpyinfo->resy = 75.0; + dpyinfo->resx = 72.0; + dpyinfo->resy = 72.0; dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType); #ifdef MAC_OSX /* HasDepth returns true if it is possible to have a 32 bit display, @@ -10464,10 +10590,9 @@ mac_determine_quit_char_modifiers() /* Map modifiers */ mac_quit_char_modifiers = 0; - if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey; - if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey; - if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey; - if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey; + if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= controlKey; + if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey; + if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= optionKey; } static void @@ -10592,7 +10717,6 @@ mac_initialize () BLOCK_INPUT; #if TARGET_API_MAC_CARBON - init_required_apple_events (); #if USE_CARBON_EVENTS #ifdef MAC_OSX @@ -10607,6 +10731,10 @@ mac_initialize () #endif /* USE_CARBON_EVENTS */ #ifdef MAC_OSX + init_coercion_handler (); + + init_apple_event_handler (); + if (!inhibit_window_system) MakeMeTheFrontProcess (); #endif @@ -10623,23 +10751,28 @@ syms_of_macterm () x_error_message_string = Qnil; #endif + Qcontrol = intern ("control"); staticpro (&Qcontrol); + Qmeta = intern ("meta"); staticpro (&Qmeta); + Qalt = intern ("alt"); staticpro (&Qalt); + Qhyper = intern ("hyper"); staticpro (&Qhyper); + Qsuper = intern ("super"); staticpro (&Qsuper); Qmodifier_value = intern ("modifier-value"); - Qalt = intern ("alt"); - Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); - Qhyper = intern ("hyper"); - Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); - Qsuper = intern ("super"); - Fput (Qsuper, Qmodifier_value, make_number (super_modifier)); + staticpro (&Qmodifier_value); - Qapplication = intern ("application"); staticpro (&Qapplication); - Qabout = intern ("about"); staticpro (&Qabout); + Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier)); + Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); + Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); + Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); + Fput (Qsuper, Qmodifier_value, make_number (super_modifier)); -#if USE_CARBON_EVENTS && defined (MAC_OSX) - Qpreferences = intern ("preferences"); staticpro (&Qpreferences); +#if USE_CARBON_EVENTS + Qhicommand = intern ("hicommand"); staticpro (&Qhicommand); +#ifdef MAC_OSX Qservices = intern ("services"); staticpro (&Qservices); Qpaste = intern ("paste"); staticpro (&Qpaste); Qperform = intern ("perform"); staticpro (&Qperform); #endif +#endif #ifdef MAC_OSX Fprovide (intern ("mac-carbon"), Qnil); @@ -10648,9 +10781,6 @@ syms_of_macterm () staticpro (&Qreverse); Qreverse = intern ("reverse"); - staticpro (&Qmac_ready_for_drag_n_drop); - Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); - staticpro (&x_display_name_list); x_display_name_list = Qnil; @@ -10665,6 +10795,18 @@ syms_of_macterm () atsu_font_id_hash = Qnil; #endif + /* We don't yet support this, but defining this here avoids whining + from cus-start.el and other places, like "M-x set-variable". */ + DEFVAR_BOOL ("x-use-underline-position-properties", + &x_use_underline_position_properties, + doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. +nil means ignore them. If you encounter fonts with bogus +UNDERLINE_POSITION font properties, for example 7x13 on XFree prior +to 4.1, set this to nil. + +NOTE: Not supported on Mac yet. */); + x_use_underline_position_properties = 0; + DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, doc: /* If not nil, Emacs uses toolkit scroll bars. */); #ifdef USE_TOOLKIT_SCROLL_BARS @@ -10676,70 +10818,83 @@ syms_of_macterm () staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; - DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta, - doc: /* Non-nil means that the command key is used as the Emacs meta key. -Otherwise the option key is used. */); - Vmac_command_key_is_meta = Qt; +/* Variables to configure modifier key assignment. */ + + DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier, + doc: /* *Modifier key assumed when the Mac control key is pressed. +The value can be `control', `meta', `alt', `hyper', or `super' for the +respective modifier. The default is `control'. */); + Vmac_control_modifier = Qcontrol; DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier, - doc: /* Modifier to use for the Mac alt/option key. The value can -be alt, hyper, or super for the respective modifier. If the value is -nil then the key will act as the normal Mac option modifier. */); + doc: /* *Modifier key assumed when the Mac alt/option key is pressed. +The value can be `control', `meta', `alt', `hyper', or `super' for the +respective modifier. If the value is nil then the key will act as the +normal Mac control modifier, and the option key can be used to compose +characters depending on the chosen Mac keyboard setting. */); Vmac_option_modifier = Qnil; - DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta, - doc: /* Non-nil means that the control and meta keys are reversed. This is -useful for non-standard keyboard layouts. */); - Vmac_reverse_ctrl_meta = Qnil; + DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier, + doc: /* *Modifier key assumed when the Mac command key is pressed. +The value can be `control', `meta', `alt', `hyper', or `super' for the +respective modifier. The default is `meta'. */); + Vmac_command_modifier = Qmeta; + + DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier, + doc: /* *Modifier key assumed when the Mac function key is pressed. +The value can be `control', `meta', `alt', `hyper', or `super' for the +respective modifier. Note that remapping the function key may lead to +unexpected results for some keys on non-US/GB keyboards. */); + Vmac_function_modifier = Qnil; DEFVAR_LISP ("mac-emulate-three-button-mouse", &Vmac_emulate_three_button_mouse, - doc: /* t means that when the option-key is held down while pressing the -mouse button, the click will register as mouse-2 and while the -command-key is held down, the click will register as mouse-3. -'reverse means that the option-key will register for mouse-3 -and the command-key will register for mouse-2. nil means that -no emulation should be done and the modifiers should be placed -on the mouse-1 event. */); + doc: /* *Specify a way of three button mouse emulation. +The value can be nil, t, or the symbol `reverse'. +nil means that no emulation should be done and the modifiers should be +placed on the mouse-1 event. +t means that when the option-key is held down while pressing the mouse +button, the click will register as mouse-2 and while the command-key +is held down, the click will register as mouse-3. +The symbol `reverse' means that the option-key will register for +mouse-3 and the command-key will register for mouse-2. */); Vmac_emulate_three_button_mouse = Qnil; #if USE_CARBON_EVENTS - DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2, - doc: /* Non-nil means that the wheel button will be treated as mouse-2 and -the right click will be mouse-3. -Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/); - Vmac_wheel_button_is_mouse_2 = Qt; + DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2, + doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3. +Otherwise, the right click will be treated as mouse-2 and the wheel +button will be mouse-3. */); + mac_wheel_button_is_mouse_2 = 1; - DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system, - doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac -Toolbox for processing before Emacs sees it. */); - Vmac_pass_command_to_system = Qt; + DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system, + doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */); + mac_pass_command_to_system = 1; - DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system, - doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac -Toolbox for processing before Emacs sees it. */); - Vmac_pass_control_to_system = Qt; + DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system, + doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */); + mac_pass_control_to_system = 1; #endif - DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics, - doc: /* If non-nil, allow anti-aliasing. + DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics, + doc: /* *If non-nil, allow anti-aliasing. The text will be rendered using Core Graphics text rendering which may anti-alias the text. */); - Vmac_use_core_graphics = Qnil; + mac_use_core_graphics = 0; /* Register an entry for `mac-roman' so that it can be used when creating the terminal frame on Mac OS 9 before loading term/mac-win.elc. */ DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist, - doc: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system. + doc: /* Alist of Emacs character sets vs text encodings and coding systems. Each entry should be of the form: (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM) where CHARSET-NAME is a string used in font names to identify the -charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM -is a coding system corresponding to TEXT-ENCODING. */); +charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and +CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */); Vmac_charset_info_alist = Fcons (list3 (build_string ("mac-roman"), make_number (smRoman), Qnil), Qnil); diff --git a/src/macterm.h b/src/macterm.h index 277fd2051c6..458fe63e5df 100644 --- a/src/macterm.h +++ b/src/macterm.h @@ -79,7 +79,7 @@ struct mac_display_info /* Number of planes on this screen. */ int n_planes; - /* Whether the screen supports color */ + /* Whether the screen supports color */ int color_p; /* Dimensions of this screen. */ @@ -322,9 +322,6 @@ struct mac_output { /* Nonzero means menubar is currently active. */ char menubar_active; - /* Nonzero means a menu command is being processed. */ - char menu_command_in_progress; - /* Relief GCs, colors etc. */ struct relief { @@ -567,23 +564,30 @@ extern void mac_clear_area P_ ((struct frame *, int, int, extern void mac_unload_font P_ ((struct mac_display_info *, XFontStruct *)); extern OSErr install_window_handler P_ ((WindowPtr)); extern void remove_window_handler P_ ((WindowPtr)); +extern Lisp_Object mac_make_lispy_event_code P_ ((int)); #define FONT_TYPE_FOR_UNIBYTE(font, ch) 0 #define FONT_TYPE_FOR_MULTIBYTE(font, ch) 0 +#define TYPE_FILE_NAME 'fNam' + /* Defined in macselect.c */ extern void x_clear_frame_selections P_ ((struct frame *)); /* Defined in mac.c. */ -extern OSErr posix_pathname_to_fsspec P_ ((const char *, FSSpec *)); -extern OSErr fsspec_to_posix_pathname P_ ((const FSSpec *, char *, int)); extern void mac_clear_font_name_table P_ ((void)); +extern Lisp_Object mac_aedesc_to_lisp P_ ((AEDesc *)); #if TARGET_API_MAC_CARBON +extern OSErr create_apple_event_from_event_ref P_ ((EventRef, UInt32, + EventParamName *, + EventParamType *, + AppleEvent *)); extern CFStringRef cfstring_create_with_utf8_cstring P_ ((const char *)); extern CFStringRef cfstring_create_with_string P_ ((Lisp_Object)); extern Lisp_Object cfdata_to_lisp P_ ((CFDataRef)); +extern Lisp_Object cfstring_to_lisp_nodecode P_ ((CFStringRef)); extern Lisp_Object cfstring_to_lisp P_ ((CFStringRef)); extern Lisp_Object cfnumber_to_lisp P_ ((CFNumberRef)); extern Lisp_Object cfdate_to_lisp P_ ((CFDateRef)); @@ -594,6 +598,7 @@ extern Lisp_Object cfproperty_list_to_lisp P_ ((CFPropertyListRef, int, int)); extern void xrm_merge_string_database P_ ((XrmDatabase, char *)); extern Lisp_Object xrm_get_resource P_ ((XrmDatabase, char *, char *)); extern XrmDatabase xrm_get_preference_database P_ ((char *)); +EXFUN (Fmac_get_preference, 4); /* arch-tag: 6b4ca125-5bef-476d-8ee8-31ed808b7e79 (do not change this comment) */ diff --git a/src/makefile.w32-in b/src/makefile.w32-in index 40c50f8e567..2bcc736e685 100644 --- a/src/makefile.w32-in +++ b/src/makefile.w32-in @@ -185,6 +185,8 @@ bootstrap: bootstrap-emacs # Build a temacs with a sufficiently large PURESIZE to load the # Lisp files from loadup.el in source form. # +# WARNING: Do NOT split the part inside $(ARGQUOTE)s into multiple lines as +# this can break with GNU Make 3.81 and later if sh.exe is used. bootstrap-temacs: $(MAKE) $(MFLAGS) temacs CFLAGS=$(ARGQUOTE)$(CFLAGS) -DPURESIZE=5000000$(ARGQUOTE) diff --git a/src/minibuf.c b/src/minibuf.c index 74d55a8abfd..9c7542ad090 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -388,6 +388,19 @@ The current buffer must be a minibuffer. */) return make_buffer_string (prompt_end, ZV, 0); } +DEFUN ("minibuffer-completion-contents", Fminibuffer_completion_contents, + Sminibuffer_completion_contents, 0, 0, 0, + doc: /* Return the user input in a minibuffer before point as a string. +That is what completion commands operate on. +The current buffer must be a minibuffer. */) + () +{ + int prompt_end = XINT (Fminibuffer_prompt_end ()); + if (PT < prompt_end) + error ("Cannot do completion in the prompt"); + return make_buffer_string (prompt_end, PT, 1); +} + DEFUN ("delete-minibuffer-contents", Fdelete_minibuffer_contents, Sdelete_minibuffer_contents, 0, 0, 0, doc: /* Delete all user input in a minibuffer. @@ -400,17 +413,6 @@ The current buffer must be a minibuffer. */) return Qnil; } -/* Get the text in the minibuffer before point. - That is what completion commands operate on. */ - -Lisp_Object -minibuffer_completion_contents () -{ - int prompt_end = XINT (Fminibuffer_prompt_end ()); - if (PT < prompt_end) - error ("Cannot do completion in the prompt"); - return make_buffer_string (prompt_end, PT, 1); -} /* Read from the minibuffer using keymap MAP and initial contents INITIAL, putting point minus BACKUP_N bytes from the end of INITIAL, @@ -461,6 +463,9 @@ read_minibuf (map, initial, prompt, backup_n, expflag, /* String to add to the history. */ Lisp_Object histstring; + Lisp_Object empty_minibuf; + Lisp_Object dummy, frame; + extern Lisp_Object Qfront_sticky; extern Lisp_Object Qrear_nonsticky; @@ -598,6 +603,10 @@ read_minibuf (map, initial, prompt, backup_n, expflag, minibuffer = get_minibuffer (minibuf_level); Fset_buffer (minibuffer); + /* If appropriate, copy enable-multibyte-characters into the minibuffer. */ + if (inherit_input_method) + current_buffer->enable_multibyte_characters = enable_multibyte; + /* The current buffer's default directory is usually the right thing for our minibuffer here. However, if you're typing a command at a minibuffer-only frame when minibuf_level is zero, then buf IS @@ -633,6 +642,22 @@ read_minibuf (map, initial, prompt, backup_n, expflag, Vminibuf_scroll_window = selected_window; if (minibuf_level == 1 || !EQ (minibuf_window, selected_window)) minibuf_selected_window = selected_window; + + /* Empty out the minibuffers of all frames other than the one + where we are going to display one now. + Set them to point to ` *Minibuf-0*', which is always empty. */ + empty_minibuf = Fget_buffer (build_string (" *Minibuf-0*")); + + FOR_EACH_FRAME (dummy, frame) + { + Lisp_Object root_window = Fframe_root_window (frame); + Lisp_Object mini_window = XWINDOW (root_window)->next; + + if (! NILP (mini_window) && !NILP (Fwindow_minibuffer_p (mini_window))) + Fset_window_buffer (mini_window, empty_minibuf, Qnil); + } + + /* Display this minibuffer in the proper window. */ Fset_window_buffer (minibuf_window, Fcurrent_buffer (), Qnil); Fselect_window (minibuf_window, Qnil); XSETFASTINT (XWINDOW (minibuf_window)->hscroll, 0); @@ -669,10 +694,6 @@ read_minibuf (map, initial, prompt, backup_n, expflag, minibuf_prompt_width = (int) current_column (); /* iftc */ - /* If appropriate, copy enable-multibyte-characters into the minibuffer. */ - if (inherit_input_method) - current_buffer->enable_multibyte_characters = enable_multibyte; - /* Put in the initial input. */ if (!NILP (initial)) { @@ -1236,11 +1257,11 @@ is used to further constrain the set of candidates. */) int bestmatchsize = 0; /* These are in bytes, too. */ int compare, matchsize; - int type = HASH_TABLE_P (alist) ? 3 - : VECTORP (alist) ? 2 - : NILP (alist) || (CONSP (alist) - && (!SYMBOLP (XCAR (alist)) - || NILP (XCAR (alist)))); + int type = (HASH_TABLE_P (alist) ? 3 + : VECTORP (alist) ? 2 + : NILP (alist) || (CONSP (alist) + && (!SYMBOLP (XCAR (alist)) + || NILP (XCAR (alist))))); int index = 0, obsize = 0; int matchcount = 0; int bindcount = -1; @@ -1747,8 +1768,12 @@ Completion ignores case if the ambient value of XSETFASTINT (histpos, 0); val = read_minibuf (NILP (require_match) - ? Vminibuffer_local_completion_map - : Vminibuffer_local_must_match_map, + ? (NILP (Vminibuffer_completing_file_name) + ? Vminibuffer_local_completion_map + : Vminibuffer_local_filename_completion_map) + : (NILP (Vminibuffer_completing_file_name) + ? Vminibuffer_local_must_match_map + : Vminibuffer_local_must_match_filename_map), init, prompt, make_number (pos), 0, histvar, histpos, def, 0, !NILP (inherit_input_method), 0); @@ -1895,7 +1920,7 @@ do_completion () Lisp_Object last; struct gcpro gcpro1, gcpro2; - completion = Ftry_completion (minibuffer_completion_contents (), + completion = Ftry_completion (Fminibuffer_completion_contents (), Vminibuffer_completion_table, Vminibuffer_completion_predicate); last = last_exact_completion; @@ -1917,7 +1942,7 @@ do_completion () return 1; } - string = minibuffer_completion_contents (); + string = Fminibuffer_completion_contents (); /* COMPLETEDP should be true if some completion was done, which doesn't include simply changing the case of the entered string. @@ -1984,7 +2009,7 @@ do_completion () last_exact_completion = completion; if (!NILP (last)) { - tem = minibuffer_completion_contents (); + tem = Fminibuffer_completion_contents (); if (!NILP (Fequal (tem, last))) Fminibuffer_completion_help (); } @@ -2112,16 +2137,17 @@ a repetition of this command will exit. */) () { register int i; - Lisp_Object val; + Lisp_Object val, tem; /* Allow user to specify null string */ if (XINT (Fminibuffer_prompt_end ()) == ZV) goto exit; val = Fminibuffer_contents (); - if (!NILP (Ftest_completion (val, - Vminibuffer_completion_table, - Vminibuffer_completion_predicate))) + tem = Ftest_completion (val, + Vminibuffer_completion_table, + Vminibuffer_completion_predicate); + if (!NILP (tem)) { if (completion_ignore_case) { /* Fixup case of the field, if necessary. */ @@ -2186,7 +2212,7 @@ Return nil if there is no valid completion, else t. */) /* We keep calling Fbuffer_string rather than arrange for GC to hold onto a pointer to one of the strings thus made. */ - completion = Ftry_completion (minibuffer_completion_contents (), + completion = Ftry_completion (Fminibuffer_completion_contents (), Vminibuffer_completion_table, Vminibuffer_completion_predicate); if (NILP (completion)) @@ -2218,7 +2244,7 @@ Return nil if there is no valid completion, else t. */) int buffer_nchars, completion_nchars; CHECK_STRING (completion); - tem = minibuffer_completion_contents (); + tem = Fminibuffer_completion_contents (); GCPRO2 (completion, tem); /* If reading a file name, expand any $ENVVAR refs in the buffer and in TEM. */ @@ -2282,7 +2308,7 @@ Return nil if there is no valid completion, else t. */) if (i == SCHARS (completion)) { GCPRO1 (completion); - tem = Ftry_completion (concat2 (minibuffer_completion_contents (), + tem = Ftry_completion (concat2 (Fminibuffer_completion_contents (), build_string (" ")), Vminibuffer_completion_table, Vminibuffer_completion_predicate); @@ -2294,7 +2320,7 @@ Return nil if there is no valid completion, else t. */) { GCPRO1 (completion); tem = - Ftry_completion (concat2 (minibuffer_completion_contents (), + Ftry_completion (concat2 (Fminibuffer_completion_contents (), build_string ("-")), Vminibuffer_completion_table, Vminibuffer_completion_predicate); @@ -2354,11 +2380,11 @@ properties of `highlight'. At the end, this runs the normal hook `completion-setup-hook'. It can find the completion buffer in `standard-output'. The optional second arg COMMON-SUBSTRING is a string. -It is used to put faces, `completions-first-difference` and +It is used to put faces, `completions-first-difference' and `completions-common-part' on the completion buffer. The `completions-common-part' face is put on the common substring -specified by COMMON-SUBSTRING. If COMMON-SUBSTRING is nil, -the faces are not put. +specified by COMMON-SUBSTRING. If COMMON-SUBSTRING is nil +and the current buffer is not the minibuffer, the faces are not put. Internally, COMMON-SUBSTRING is bound to `completion-common-substring' during running `completion-setup-hook'. */) (completions, common_substring) @@ -2388,7 +2414,7 @@ during running `completion-setup-hook'. */) else { write_string ("Possible completions are:", -1); - for (tail = completions, i = 0; !NILP (tail); tail = Fcdr (tail), i++) + for (tail = completions, i = 0; CONSP (tail); tail = XCDR (tail), i++) { Lisp_Object tem, string; int length; @@ -2396,7 +2422,7 @@ during running `completion-setup-hook'. */) startpos = Qnil; - elt = Fcar (tail); + elt = XCAR (tail); if (SYMBOLP (elt)) elt = SYMBOL_NAME (elt); /* Compute the length of this element. */ @@ -2560,7 +2586,7 @@ DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_co Lisp_Object completions; message ("Making completion list..."); - completions = Fall_completions (minibuffer_completion_contents (), + completions = Fall_completions (Fminibuffer_completion_contents (), Vminibuffer_completion_table, Vminibuffer_completion_predicate, Qt); @@ -2572,9 +2598,21 @@ DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_co temp_echo_area_glyphs (build_string (" [No completions]")); } else - internal_with_output_to_temp_buffer ("*Completions*", - display_completion_list_1, - Fsort (completions, Qstring_lessp)); + { + /* Sort and remove duplicates. */ + Lisp_Object tmp = completions = Fsort (completions, Qstring_lessp); + while (CONSP (tmp)) + { + if (CONSP (XCDR (tmp)) + && !NILP (Fequal (XCAR (tmp), XCAR (XCDR (tmp))))) + XSETCDR (tmp, XCDR (XCDR (tmp))); + else + tmp = XCDR (tmp); + } + internal_with_output_to_temp_buffer ("*Completions*", + display_completion_list_1, + completions); + } return Qnil; } @@ -2658,7 +2696,7 @@ temp_echo_area_glyphs (string) DEFUN ("minibuffer-message", Fminibuffer_message, Sminibuffer_message, 1, 1, 0, doc: /* Temporarily display STRING at the end of the minibuffer. -The text is displayed for two seconds, +The text is displayed for a period controlled by `minibuffer-message-timeout', or until the next input event arrives, whichever comes first. */) (string) Lisp_Object string; @@ -2761,7 +2799,9 @@ elements are deleted. */); history_delete_duplicates = 0; DEFVAR_LISP ("completion-auto-help", &Vcompletion_auto_help, - doc: /* *Non-nil means automatically provide help for invalid completion input. */); + doc: /* *Non-nil means automatically provide help for invalid completion input. +Under Partial Completion mode, a non-nil, non-t value has a special meaning; +see the doc string of `partial-completion-mode' for more details. */); Vcompletion_auto_help = Qt; DEFVAR_BOOL ("completion-ignore-case", &completion_ignore_case, @@ -2867,6 +2907,7 @@ properties. */); defsubr (&Sminibuffer_prompt_end); defsubr (&Sminibuffer_contents); defsubr (&Sminibuffer_contents_no_properties); + defsubr (&Sminibuffer_completion_contents); defsubr (&Sdelete_minibuffer_contents); defsubr (&Stry_completion); @@ -2910,10 +2951,16 @@ keys_of_minibuf () initial_define_key (Vminibuffer_local_completion_map, '?', "minibuffer-completion-help"); + Fdefine_key (Vminibuffer_local_filename_completion_map, + build_string (" "), Qnil); + initial_define_key (Vminibuffer_local_must_match_map, Ctl ('m'), "minibuffer-complete-and-exit"); initial_define_key (Vminibuffer_local_must_match_map, Ctl ('j'), "minibuffer-complete-and-exit"); + + Fdefine_key (Vminibuffer_local_must_match_filename_map, + build_string (" "), Qnil); } /* arch-tag: 8f69b601-fba3-484c-a6dd-ceaee54a7a73 diff --git a/src/print.c b/src/print.c index 7818565ce62..cc2902acb2b 100644 --- a/src/print.c +++ b/src/print.c @@ -970,6 +970,26 @@ debug_print (arg) Fprin1 (arg, Qexternal_debugging_output); fprintf (stderr, "\r\n"); } + +void +safe_debug_print (arg) + Lisp_Object arg; +{ + int valid = valid_lisp_object_p (arg); + + if (valid > 0) + debug_print (arg); + else + fprintf (stderr, "#<%s_LISP_OBJECT 0x%08lx>\r\n", + !valid ? "INVALID" : "SOME", +#ifdef NO_UNION_TYPE + (unsigned long) arg +#else + (unsigned long) arg.i +#endif + ); +} + DEFUN ("error-message-string", Ferror_message_string, Serror_message_string, 1, 1, 0, @@ -1294,7 +1314,7 @@ print_preprocess (obj) /* Give up if we go so deep that print_object will get an error. */ /* See similar code in print_object. */ if (print_depth >= PRINT_CIRCLE) - return; + error ("Apparently circular structure being printed"); /* Avoid infinite recursion for circular nested structure in the case where Vprint_circle is nil. */ @@ -1325,7 +1345,8 @@ print_preprocess (obj) { /* OBJ appears more than once. Let's remember that. */ PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt; - return; + print_depth--; + return; } /* OBJ is not yet recorded. Let's add to the table. */ diff --git a/src/process.c b/src/process.c index b66c768c256..cde2c606d93 100644 --- a/src/process.c +++ b/src/process.c @@ -40,6 +40,9 @@ Boston, MA 02110-1301, USA. */ #include <sys/types.h> /* some typedefs are used in sys/file.h */ #include <sys/file.h> #include <sys/stat.h> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -118,6 +121,14 @@ Boston, MA 02110-1301, USA. */ #include <sys/wait.h> #endif +/* Disable IPv6 support for w32 until someone figures out how to do it + properly. */ +#ifdef WINDOWSNT +# ifdef AF_INET6 +# undef AF_INET6 +# endif +#endif + #include "lisp.h" #include "systime.h" #include "systty.h" @@ -140,7 +151,10 @@ Boston, MA 02110-1301, USA. */ Lisp_Object Qprocessp; Lisp_Object Qrun, Qstop, Qsignal; Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten; -Lisp_Object Qlocal, Qdatagram; +Lisp_Object Qlocal, Qipv4, Qdatagram; +#ifdef AF_INET6 +Lisp_Object Qipv6; +#endif Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype; Lisp_Object QClocal, QCremote, QCcoding; Lisp_Object QCserver, QCnowait, QCnoquery, QCstop; @@ -1196,9 +1210,11 @@ a socket connection. */) DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address, 1, 2, 0, doc: /* Convert network ADDRESS from internal format to a string. +A 4 or 5 element vector represents an IPv4 address (with port number). +An 8 or 9 element vector represents an IPv6 address (with port number). If optional second argument OMIT-PORT is non-nil, don't include a port -number in the string; in this case, interpret a 4 element vector as an -IP address. Returns nil if format of ADDRESS is invalid. */) +number in the string, even when present in ADDRESS. +Returns nil if format of ADDRESS is invalid. */) (address, omit_port) Lisp_Object address, omit_port; { @@ -1208,13 +1224,13 @@ IP address. Returns nil if format of ADDRESS is invalid. */) if (STRINGP (address)) /* AF_LOCAL */ return address; - if (VECTORP (address)) /* AF_INET */ + if (VECTORP (address)) /* AF_INET or AF_INET6 */ { register struct Lisp_Vector *p = XVECTOR (address); Lisp_Object args[6]; int nargs, i; - if (!NILP (omit_port) && (p->size == 4 || p->size == 5)) + if (p->size == 4 || (p->size == 5 && !NILP (omit_port))) { args[0] = build_string ("%d.%d.%d.%d"); nargs = 4; @@ -1224,6 +1240,16 @@ IP address. Returns nil if format of ADDRESS is invalid. */) args[0] = build_string ("%d.%d.%d.%d:%d"); nargs = 5; } + else if (p->size == 8 || (p->size == 9 && !NILP (omit_port))) + { + args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); + nargs = 8; + } + else if (p->size == 9) + { + args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d"); + nargs = 9; + } else return Qnil; @@ -2213,6 +2239,20 @@ conv_sockaddr_to_lisp (sa, len) cp = (unsigned char *)&sin->sin_addr; break; } +#ifdef AF_INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; + len = sizeof (sin6->sin6_addr)/2 + 1; + address = Fmake_vector (make_number (len), Qnil); + p = XVECTOR (address); + p->contents[--len] = make_number (ntohs (sin6->sin6_port)); + for (i = 0; i < len; i++) + p->contents[i] = make_number (ntohs (ip6[i])); + return address; + } +#endif #ifdef HAVE_LOCAL_SOCKETS case AF_LOCAL: { @@ -2257,6 +2297,13 @@ get_lisp_to_sockaddr_size (address, familyp) *familyp = AF_INET; return sizeof (struct sockaddr_in); } +#ifdef AF_INET6 + else if (p->size == 9) + { + *familyp = AF_INET6; + return sizeof (struct sockaddr_in6); + } +#endif } #ifdef HAVE_LOCAL_SOCKETS else if (STRINGP (address)) @@ -2303,6 +2350,23 @@ conv_lisp_to_sockaddr (family, address, sa, len) sin->sin_port = htons (i); cp = (unsigned char *)&sin->sin_addr; } +#ifdef AF_INET6 + else if (family == AF_INET6) + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; + len = sizeof (sin6->sin6_addr) + 1; + i = XINT (p->contents[--len]); + sin6->sin6_port = htons (i); + for (i = 0; i < len; i++) + if (INTEGERP (p->contents[i])) + { + int j = XFASTINT (p->contents[i]) & 0xffff; + ip6[i] = ntohs (j); + } + return; + } +#endif } else if (STRINGP (address)) { @@ -2596,10 +2660,13 @@ a random port number is selected for the server. stream type connection, `datagram' creates a datagram type connection. :family FAMILY -- FAMILY is the address (and protocol) family for the -service specified by HOST and SERVICE. The default address family is -Inet (or IPv4) for the host and port number specified by HOST and -SERVICE. Other address families supported are: +service specified by HOST and SERVICE. The default (nil) is to use +whatever address family (IPv4 or IPv6) that is defined for the host +and port number specified by HOST and SERVICE. Other address families +supported are: local -- for a local (i.e. UNIX) address specified by SERVICE. + ipv4 -- use IPv4 address family only. + ipv6 -- use IPv6 address family only. :local ADDRESS -- ADDRESS is the local address used for the connection. This parameter is ignored when opening a client process. When specified @@ -2716,8 +2783,8 @@ usage: (make-network-process &rest ARGS) */) struct Lisp_Process *p; #ifdef HAVE_GETADDRINFO struct addrinfo ai, *res, *lres; - struct addrinfo hints; - char *portstring, portbuf[128]; + struct addrinfo hints; + char *portstring, portbuf[128]; #else /* HAVE_GETADDRINFO */ struct _emacs_addrinfo { @@ -2856,19 +2923,29 @@ usage: (make-network-process &rest ARGS) */) /* :family FAMILY -- nil (for Inet), local, or integer. */ tem = Fplist_get (contact, QCfamily); - if (INTEGERP (tem)) - family = XINT (tem); - else + if (NILP (tem)) { - if (NILP (tem)) - family = AF_INET; -#ifdef HAVE_LOCAL_SOCKETS - else if (EQ (tem, Qlocal)) - family = AF_LOCAL; +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + family = AF_UNSPEC; +#else + family = AF_INET; #endif } - if (family < 0) +#ifdef HAVE_LOCAL_SOCKETS + else if (EQ (tem, Qlocal)) + family = AF_LOCAL; +#endif +#ifdef AF_INET6 + else if (EQ (tem, Qipv6)) + family = AF_INET6; +#endif + else if (EQ (tem, Qipv4)) + family = AF_INET; + else if (INTEGERP (tem)) + family = XINT (tem); + else error ("Unknown address family"); + ai.ai_family = family; /* :service SERVICE -- string, integer (port number), or t (random port). */ @@ -2934,7 +3011,7 @@ usage: (make-network-process &rest ARGS) */) QUIT; memset (&hints, 0, sizeof (hints)); hints.ai_flags = 0; - hints.ai_family = NILP (Fplist_member (contact, QCfamily)) ? AF_UNSPEC : family; + hints.ai_family = family; hints.ai_socktype = socktype; hints.ai_protocol = 0; ret = getaddrinfo (SDATA (host), portstring, &hints, &res); @@ -3523,6 +3600,21 @@ static struct ifflag_def ifflag_table[] = { #ifdef IFF_DYNAMIC { IFF_DYNAMIC, "dynamic" }, #endif +#ifdef IFF_OACTIVE + { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress */ +#endif +#ifdef IFF_SIMPLEX + { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */ +#endif +#ifdef IFF_LINK0 + { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit */ +#endif +#ifdef IFF_LINK1 + { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit */ +#endif +#ifdef IFF_LINK2 + { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit */ +#endif { 0, 0 } }; @@ -3559,7 +3651,7 @@ FLAGS is the current flags of the interface. */) int fnum; any++; - for (fp = ifflag_table; flags != 0 && fp; fp++) + for (fp = ifflag_table; flags != 0 && fp->flag_sym; fp++) { if (flags & fp->flag_bit) { @@ -3595,11 +3687,15 @@ FLAGS is the current flags of the interface. */) res = Fcons (elt, res); elt = Qnil; -#if defined(SIOCGIFNETMASK) && defined(ifr_netmask) +#if defined(SIOCGIFNETMASK) && (defined(HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined(HAVE_STRUCT_IFREQ_IFR_ADDR)) if (ioctl (s, SIOCGIFNETMASK, &rq) == 0) { any++; +#ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask)); +#else + elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr)); +#endif } #endif res = Fcons (elt, res); @@ -3817,6 +3913,9 @@ server_accept_connection (server, channel) union u_sockaddr { struct sockaddr sa; struct sockaddr_in in; +#ifdef AF_INET6 + struct sockaddr_in6 in6; +#endif #ifdef HAVE_LOCAL_SOCKETS struct sockaddr_un un; #endif @@ -3873,6 +3972,26 @@ server_accept_connection (server, channel) } break; +#ifdef AF_INET6 + case AF_INET6: + { + Lisp_Object args[9]; + uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr; + int i; + args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); + for (i = 0; i < 8; i++) + args[i+1] = make_number (ntohs(ip6[i])); + host = Fformat (9, args); + service = make_number (ntohs (saddr.in.sin_port)); + + args[0] = build_string (" <[%s]:%d>"); + args[1] = host; + args[2] = service; + caller = Fformat (3, args); + } + break; +#endif + #ifdef HAVE_LOCAL_SOCKETS case AF_LOCAL: #endif @@ -5942,97 +6061,100 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) CHECK_SYMBOL (sigcode); name = SDATA (SYMBOL_NAME (sigcode)); + if (!strncmp(name, "SIG", 3)) + name += 3; + if (0) ; #ifdef SIGHUP - handle_signal ("SIGHUP", SIGHUP); + handle_signal ("HUP", SIGHUP); #endif #ifdef SIGINT - handle_signal ("SIGINT", SIGINT); + handle_signal ("INT", SIGINT); #endif #ifdef SIGQUIT - handle_signal ("SIGQUIT", SIGQUIT); + handle_signal ("QUIT", SIGQUIT); #endif #ifdef SIGILL - handle_signal ("SIGILL", SIGILL); + handle_signal ("ILL", SIGILL); #endif #ifdef SIGABRT - handle_signal ("SIGABRT", SIGABRT); + handle_signal ("ABRT", SIGABRT); #endif #ifdef SIGEMT - handle_signal ("SIGEMT", SIGEMT); + handle_signal ("EMT", SIGEMT); #endif #ifdef SIGKILL - handle_signal ("SIGKILL", SIGKILL); + handle_signal ("KILL", SIGKILL); #endif #ifdef SIGFPE - handle_signal ("SIGFPE", SIGFPE); + handle_signal ("FPE", SIGFPE); #endif #ifdef SIGBUS - handle_signal ("SIGBUS", SIGBUS); + handle_signal ("BUS", SIGBUS); #endif #ifdef SIGSEGV - handle_signal ("SIGSEGV", SIGSEGV); + handle_signal ("SEGV", SIGSEGV); #endif #ifdef SIGSYS - handle_signal ("SIGSYS", SIGSYS); + handle_signal ("SYS", SIGSYS); #endif #ifdef SIGPIPE - handle_signal ("SIGPIPE", SIGPIPE); + handle_signal ("PIPE", SIGPIPE); #endif #ifdef SIGALRM - handle_signal ("SIGALRM", SIGALRM); + handle_signal ("ALRM", SIGALRM); #endif #ifdef SIGTERM - handle_signal ("SIGTERM", SIGTERM); + handle_signal ("TERM", SIGTERM); #endif #ifdef SIGURG - handle_signal ("SIGURG", SIGURG); + handle_signal ("URG", SIGURG); #endif #ifdef SIGSTOP - handle_signal ("SIGSTOP", SIGSTOP); + handle_signal ("STOP", SIGSTOP); #endif #ifdef SIGTSTP - handle_signal ("SIGTSTP", SIGTSTP); + handle_signal ("TSTP", SIGTSTP); #endif #ifdef SIGCONT - handle_signal ("SIGCONT", SIGCONT); + handle_signal ("CONT", SIGCONT); #endif #ifdef SIGCHLD - handle_signal ("SIGCHLD", SIGCHLD); + handle_signal ("CHLD", SIGCHLD); #endif #ifdef SIGTTIN - handle_signal ("SIGTTIN", SIGTTIN); + handle_signal ("TTIN", SIGTTIN); #endif #ifdef SIGTTOU - handle_signal ("SIGTTOU", SIGTTOU); + handle_signal ("TTOU", SIGTTOU); #endif #ifdef SIGIO - handle_signal ("SIGIO", SIGIO); + handle_signal ("IO", SIGIO); #endif #ifdef SIGXCPU - handle_signal ("SIGXCPU", SIGXCPU); + handle_signal ("XCPU", SIGXCPU); #endif #ifdef SIGXFSZ - handle_signal ("SIGXFSZ", SIGXFSZ); + handle_signal ("XFSZ", SIGXFSZ); #endif #ifdef SIGVTALRM - handle_signal ("SIGVTALRM", SIGVTALRM); + handle_signal ("VTALRM", SIGVTALRM); #endif #ifdef SIGPROF - handle_signal ("SIGPROF", SIGPROF); + handle_signal ("PROF", SIGPROF); #endif #ifdef SIGWINCH - handle_signal ("SIGWINCH", SIGWINCH); + handle_signal ("WINCH", SIGWINCH); #endif #ifdef SIGINFO - handle_signal ("SIGINFO", SIGINFO); + handle_signal ("INFO", SIGINFO); #endif #ifdef SIGUSR1 - handle_signal ("SIGUSR1", SIGUSR1); + handle_signal ("USR1", SIGUSR1); #endif #ifdef SIGUSR2 - handle_signal ("SIGUSR2", SIGUSR2); + handle_signal ("USR2", SIGUSR2); #endif else error ("Undefined signal name %s", name); @@ -6719,6 +6841,10 @@ init_process () #ifdef HAVE_LOCAL_SOCKETS ADD_SUBFEATURE (QCfamily, Qlocal); #endif + ADD_SUBFEATURE (QCfamily, Qipv4); +#ifdef AF_INET6 + ADD_SUBFEATURE (QCfamily, Qipv6); +#endif #ifdef HAVE_GETSOCKNAME ADD_SUBFEATURE (QCservice, Qt); #endif @@ -6777,6 +6903,12 @@ syms_of_process () staticpro (&Qlisten); Qlocal = intern ("local"); staticpro (&Qlocal); + Qipv4 = intern ("ipv4"); + staticpro (&Qipv4); +#ifdef AF_INET6 + Qipv6 = intern ("ipv6"); + staticpro (&Qipv6); +#endif Qdatagram = intern ("datagram"); staticpro (&Qdatagram); diff --git a/src/puresize.h b/src/puresize.h index 767c88bb807..f82c705265b 100644 --- a/src/puresize.h +++ b/src/puresize.h @@ -42,7 +42,7 @@ Boston, MA 02110-1301, USA. */ #endif #ifndef BASE_PURESIZE -#define BASE_PURESIZE (1100000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) +#define BASE_PURESIZE (1180000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) #endif /* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ diff --git a/src/s/darwin.h b/src/s/darwin.h index fad445d7557..6227010e3ed 100644 --- a/src/s/darwin.h +++ b/src/s/darwin.h @@ -263,13 +263,13 @@ Boston, MA 02110-1301, USA. */ /* Indicate that we are compiling for Mac OS X and where to find Mac specific headers. */ -#define C_SWITCH_SYSTEM -fpascal-strings -fno-common -DMAC_OSX -I../mac/src +#define C_SWITCH_SYSTEM -fpascal-strings -DMAC_OSX -I../mac/src /* Link in the Carbon lib. */ #ifdef HAVE_CARBON #define LIBS_CARBON -framework Carbon -framework QuickTime #else -#define LIBS_CARBON -framework Carbon +#define LIBS_CARBON #endif /* The -headerpad option tells ld (see man page) to leave room at the @@ -328,6 +328,10 @@ struct kboard; does not exist. */ #undef HAVE_WORKING_VFORK #define vfork fork + +/* Don't close pty in process.c to make it as controlling terminal. + It is already a controlling terminal of subprocess, because we did + ioctl TIOCSCTTY. */ #define DONT_REOPEN_PTY #ifdef temacs diff --git a/src/search.c b/src/search.c index 346c0e589fa..e35545f0e19 100644 --- a/src/search.c +++ b/src/search.c @@ -1140,7 +1140,7 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n, int raw_pattern_size_byte; unsigned char *patbuf; int multibyte = !NILP (current_buffer->enable_multibyte_characters); - unsigned char *base_pat = SDATA (string); + unsigned char *base_pat; /* Set to positive if we find a non-ASCII char that need translation. Otherwise set to zero later. */ int char_base = -1; @@ -2354,7 +2354,7 @@ since only regular expressions have distinguished subexpressions. */) else some_multiletter_word = 1; } - else if (!NOCASEP (c)) + else if (UPPERCASEP (c)) { some_uppercase = 1; if (SYNTAX (prevc) != Sword) diff --git a/src/sheap.c b/src/sheap.c index 635c3dc0144..cc740173a24 100644 --- a/src/sheap.c +++ b/src/sheap.c @@ -1,5 +1,5 @@ -/* simulate sbrk() with an array in .bss, for unexec() support for Cygwin; - complete rewrite of xemacs Cygwin unexec() code +/* simulate `sbrk' with an array in .bss, for `unexec' support for Cygwin; + complete rewrite of xemacs Cygwin `unexec' code Copyright (C) 2004, 2005 Free Software Foundation, Inc. @@ -27,9 +27,9 @@ Boston, MA 02110-1301, USA. */ #include <unistd.h> #ifdef HAVE_X_WINDOWS -#define STATIC_HEAP_SIZE (7 * 1024 * 1024) +#define STATIC_HEAP_SIZE (8 * 1024 * 1024) #else -#define STATIC_HEAP_SIZE (7 * 1024 * 1024) +#define STATIC_HEAP_SIZE (8 * 1024 * 1024) #endif int debug_sheap = 0; diff --git a/src/syntax.c b/src/syntax.c index e3e1f27b9d8..32ef35d2d55 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -3244,7 +3244,7 @@ Parsing stops at TO or when certain criteria are met; point is set to where parsing stops. If fifth arg OLDSTATE is omitted or nil, parsing assumes that FROM is the beginning of a function. -Value is a list of ten elements describing final state of parsing: +Value is a list of elements describing final state of parsing: 0. depth in parens. 1. character address of start of innermost containing list; nil if none. 2. character address of start of last complete sexp terminated. @@ -3263,7 +3263,7 @@ If third arg TARGETDEPTH is non-nil, parsing stops if the depth in parentheses becomes equal to TARGETDEPTH. Fourth arg STOPBEFORE non-nil means stop when come to any character that starts a sexp. -Fifth arg OLDSTATE is a nine-element list like what this function returns. +Fifth arg OLDSTATE is a list like what this function returns. It is used to initialize the state of the parse. Elements number 1, 2, 6 and 8 are ignored; you can leave off element 8 (the last) entirely. Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. diff --git a/src/term.c b/src/term.c index 0a409931fc1..aae4f7dffdc 100644 --- a/src/term.c +++ b/src/term.c @@ -89,6 +89,10 @@ extern Lisp_Object Qspace, QCalign_to, QCwidth; Lisp_Object Vring_bell_function; +/* If true, use "vs", otherwise use "ve" to make the cursor visible. */ + +static int visible_cursor; + /* Terminal characteristics that higher levels want to look at. These are all extern'd in termchar.h */ @@ -462,7 +466,7 @@ set_terminal_modes () putchar ('\n'); } - OUTPUT_IF (TS_cursor_visible); + OUTPUT_IF (visible_cursor ? TS_cursor_visible : TS_cursor_normal); OUTPUT_IF (TS_keypad_mode); losecursor (); } @@ -617,7 +621,8 @@ tty_show_cursor () { tty_cursor_hidden = 0; OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_cursor_visible); + if (visible_cursor) + OUTPUT_IF (TS_cursor_visible); } } @@ -2745,6 +2750,13 @@ This variable can be used by terminal emulator packages. */); The function should accept no arguments. */); Vring_bell_function = Qnil; + DEFVAR_BOOL ("visible-cursor", &visible_cursor, + doc: /* Non-nil means to make the cursor very visible. +This only has an effect when running in a text terminal. +What means \"very visible\" is up to your terminal. It may make the cursor +bigger, or it may make it blink, or it may do nothing at all. */); + visible_cursor = 1; + defsubr (&Stty_display_color_p); defsubr (&Stty_display_color_cells); defsubr (&Stty_no_underline); diff --git a/src/termhooks.h b/src/termhooks.h index 641d21bdc06..2f0e1089227 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -278,7 +278,7 @@ enum event_kind by MS-Windows scroll bar controls. */ #endif SELECTION_REQUEST_EVENT, /* Another X client wants a selection from us. - See `struct selection_event'. */ + See `struct selection_input_event'. */ SELECTION_CLEAR_EVENT, /* Another X client cleared our selection. */ BUFFER_SWITCH_EVENT, /* A process filter has switched buffers. */ DELETE_WINDOW_EVENT, /* An X client said "delete this window". */ @@ -293,14 +293,14 @@ enum event_kind DRAG_N_DROP_EVENT, /* A drag-n-drop event is generated when files selected outside of Emacs are dropped onto an Emacs window. - Currently used only on Windows NT. .modifiers holds the state of the modifier keys. .x and .y give the mouse position, in characters, within the window. - .frame_or_window is a cons of the frame - in which the drop was made and a list of - the filenames of the dropped files. + .frame_or_window is the frame in + which the drop was made. + .arg is a platform-dependent + representation of the dropped items. .timestamp gives a timestamp (in milliseconds) for the click. */ USER_SIGNAL_EVENT, /* A user signal. @@ -326,12 +326,22 @@ enum event_kind /* Queued from XTread_socket when session manager sends save yourself before shutdown. */ - SAVE_SESSION_EVENT + SAVE_SESSION_EVENT, + +#ifdef MAC_OS + /* Generated when an Apple event, a HICommand event, or a Services + menu event is received and the corresponding handler is + registered. Members `x' and `y' are for the event class and ID + symbols, respectively. Member `code' points to the Apple event + descriptor. Parameters for Non-Apple events are converted to + those in Apple events. */ + MAC_APPLE_EVENT +#endif }; /* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT or SELECTION_CLEAR_EVENT, then its contents are really described - by `struct selection_event'; see xterm.h. */ + by `struct selection_input_event'; see xterm.h. */ /* The keyboard input buffer is an array of these structures. Each one represents some sort of input event - a keystroke, a mouse click, or @@ -357,7 +367,7 @@ struct input_event unsigned long timestamp; /* This is padding just to put the frame_or_window field - past the size of struct selection_event. */ + past the size of struct selection_input_event. */ int *padding[2]; /* This field is copied into a vector while the event is in the queue, diff --git a/src/textprop.c b/src/textprop.c index fa9b0e498c5..029f2f41031 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -1316,8 +1316,8 @@ the designated part of OBJECT. */) properties PROPERTIES. OBJECT is the buffer or string containing the text. OBJECT nil means use the current buffer. SIGNAL_AFTER_CHANGE_P nil means don't signal after changes. Value - is non-nil if properties were replaced; it is nil if there weren't - any properties to replace. */ + is nil if the function _detected_ that it did not replace any + properties, non-nil otherwise. */ Lisp_Object set_text_properties (start, end, properties, object, signal_after_change_p) @@ -1341,7 +1341,7 @@ set_text_properties (start, end, properties, object, signal_after_change_p) && XFASTINT (end) == SCHARS (object)) { if (! STRING_INTERVALS (object)) - return Qt; + return Qnil; STRING_SET_INTERVALS (object, NULL_INTERVAL); return Qt; diff --git a/src/undo.c b/src/undo.c index 9839906ca7e..bf774affac5 100644 --- a/src/undo.c +++ b/src/undo.c @@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA. */ #include "lisp.h" #include "buffer.h" #include "commands.h" +#include "window.h" /* Limits controlling how much undo information to keep. */ @@ -100,12 +101,19 @@ record_point (pt) /* If we are just after an undo boundary, and point wasn't at start of deleted range, record where it was. */ if (at_boundary - && last_point_position != pt - /* If we're called from batch mode, this could be nil. */ && BUFFERP (last_point_position_buffer) + /* If we're called from batch mode, this could be nil. */ && current_buffer == XBUFFER (last_point_position_buffer)) - current_buffer->undo_list - = Fcons (make_number (last_point_position), current_buffer->undo_list); + { + /* If we have switched windows, use the point value + from the window we are in. */ + if (! EQ (last_point_position_window, selected_window)) + last_point_position = marker_position (XWINDOW (selected_window)->pointm); + + if (last_point_position != pt) + current_buffer->undo_list + = Fcons (make_number (last_point_position), current_buffer->undo_list); + } } /* Record an insertion that just happened or is about to happen, @@ -378,11 +386,11 @@ truncate_undo_list (b) && size_so_far > XINT (Vundo_outer_limit) && !NILP (Vundo_outer_limit_function)) { - Lisp_Object temp = last_undo_buffer; + Lisp_Object temp = last_undo_buffer, tem; /* Normally the function this calls is undo-outer-limit-truncate. */ - if (! NILP (call1 (Vundo_outer_limit_function, - make_number (size_so_far)))) + tem = call1 (Vundo_outer_limit_function, make_number (size_so_far)); + if (! NILP (tem)) { /* The function is responsible for making any desired changes in buffer-undo-list. */ diff --git a/src/unexelf.c b/src/unexelf.c index f50e849fdcf..c53974be9f2 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -682,7 +682,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) ElfW(Addr) new_data2_addr; int n, nn; - int old_bss_index, old_sbss_index; + int old_bss_index, old_sbss_index, old_plt_index; int old_data_index, new_data2_index; int old_mdebug_index; struct stat stat_buf; @@ -740,15 +740,34 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) old_sbss_index = find_section (".sbss", old_section_names, old_name, old_file_h, old_section_h, 1); if (old_sbss_index != -1) - if (OLD_SECTION_H (old_sbss_index).sh_type == SHT_PROGBITS) + if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS) old_sbss_index = -1; - if (old_sbss_index == -1) + /* PowerPC64 has .plt in the BSS section. */ + old_plt_index = find_section (".plt", old_section_names, + old_name, old_file_h, old_section_h, 1); + if (old_plt_index != -1) + if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS) + old_plt_index = -1; + + if (old_sbss_index == -1 && old_plt_index == -1) { old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; new_data2_index = old_bss_index; } + else if (old_plt_index != -1 + && (old_sbss_index == -1 + || (OLD_SECTION_H (old_sbss_index).sh_addr + > OLD_SECTION_H (old_plt_index).sh_addr))) + { + old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr; + old_bss_size = OLD_SECTION_H (old_bss_index).sh_size + + OLD_SECTION_H (old_plt_index).sh_size; + if (old_sbss_index != -1) + old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size; + new_data2_index = old_plt_index; + } else { old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr; @@ -934,7 +953,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) if (n == old_bss_index /* The new bss and sbss section's size is zero, and its file offset and virtual address should be off by NEW_DATA2_SIZE. */ - || n == old_sbss_index + || n == old_sbss_index || n == old_plt_index ) { /* NN should be `old_s?bss_index + 1' at this point. */ diff --git a/src/unexmacosx.c b/src/unexmacosx.c index 9db9622f6f5..43e1f5e805c 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c @@ -174,7 +174,7 @@ off_t data_segment_old_fileoff; struct segment_command *data_segment_scp; -/* Read n bytes from infd into memory starting at address dest. +/* Read N bytes from infd into memory starting at address DEST. Return true if successful, false otherwise. */ static int unexec_read (void *dest, size_t n) @@ -182,8 +182,9 @@ unexec_read (void *dest, size_t n) return n == read (infd, dest, n); } -/* Write n bytes from memory starting at address src to outfd starting - at offset dest. Return true if successful, false otherwise. */ +/* Write COUNT bytes from memory starting at address SRC to outfd + starting at offset DEST. Return true if successful, false + otherwise. */ static int unexec_write (off_t dest, const void *src, size_t count) { @@ -193,8 +194,32 @@ unexec_write (off_t dest, const void *src, size_t count) return write (outfd, src, count) == count; } -/* Copy n bytes from starting offset src in infd to starting offset - dest in outfd. Return true if successful, false otherwise. */ +/* Write COUNT bytes of zeros to outfd starting at offset DEST. + Return true if successful, false otherwise. */ +static int +unexec_write_zero (off_t dest, size_t count) +{ + char buf[UNEXEC_COPY_BUFSZ]; + ssize_t bytes; + + bzero (buf, UNEXEC_COPY_BUFSZ); + if (lseek (outfd, dest, SEEK_SET) != dest) + return 0; + + while (count > 0) + { + bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count; + if (write (outfd, buf, bytes) != bytes) + return 0; + count -= bytes; + } + + return 1; +} + +/* Copy COUNT bytes from starting offset SRC in infd to starting + offset DEST in outfd. Return true if successful, false + otherwise. */ static int unexec_copy (off_t dest, off_t src, ssize_t count) { @@ -684,14 +709,39 @@ copy_data_segment (struct load_command *lc) if (!unexec_write (header_offset, sectp, sizeof (struct section))) unexec_error ("cannot write section %s's header", SECT_DATA); } - else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0 - || strncmp (sectp->sectname, SECT_COMMON, 16) == 0) + else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0) { sectp->flags = S_REGULAR; if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) - unexec_error ("cannot write section %s", SECT_DATA); + unexec_error ("cannot write section %s", sectp->sectname); if (!unexec_write (header_offset, sectp, sizeof (struct section))) - unexec_error ("cannot write section %s's header", SECT_DATA); + unexec_error ("cannot write section %s's header", sectp->sectname); + } + else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0) + { + extern char *my_endbss_static; + unsigned long my_size; + + sectp->flags = S_REGULAR; + + /* Clear uninitialized local variables in statically linked + libraries. In particular, function pointers stored by + libSystemStub.a, which is introduced in Mac OS X 10.4 for + binary compatibility with respect to long double, are + cleared so that they will be reinitialized when the + dumped binary is executed on other versions of OS. */ + my_size = (unsigned long)my_endbss_static - sectp->addr; + if (!(sectp->addr <= (unsigned long)my_endbss_static + && my_size <= sectp->size)) + unexec_error ("my_endbss_static is not in section %s", + sectp->sectname); + if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size)) + unexec_error ("cannot write section %s", sectp->sectname); + if (!unexec_write_zero (sectp->offset + my_size, + sectp->size - my_size)) + unexec_error ("cannot write section %s", sectp->sectname); + if (!unexec_write (header_offset, sectp, sizeof (struct section))) + unexec_error ("cannot write section %s's header", sectp->sectname); } else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0 || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0 diff --git a/src/w32fns.c b/src/w32fns.c index 0fc27ac7d89..a9fded5525e 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -5348,9 +5348,13 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset) strcpy (height_pixels, "*"); strcpy (height_dpi, "*"); } + +#if 0 /* Never put the width in the xfld. It fails on fonts with + double-width characters. */ if (lplogfont->lfWidth) sprintf (width_pixels, "%u", lplogfont->lfWidth * 10); else +#endif strcpy (width_pixels, "*"); _snprintf (lpxstr, len - 1, @@ -7469,16 +7473,22 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y) if (INTEGERP (top)) *root_y = XINT (top); - else if (*root_y + XINT (dy) - height < 0) - *root_y -= XINT (dy); - else - { - *root_y -= height; + else if (*root_y + XINT (dy) <= 0) + *root_y = 0; /* Can happen for negative dy */ + else if (*root_y + XINT (dy) + height <= FRAME_W32_DISPLAY_INFO (f)->height) + /* It fits below the pointer */ *root_y += XINT (dy); - } + else if (height + XINT (dy) <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XINT (dy); + else + /* Put it on the top. */ + *root_y = 0; if (INTEGERP (left)) *root_x = XINT (left); + else if (*root_x + XINT (dx) <= 0) + *root_x = 0; /* Can happen for negative dx */ else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width) /* It fits to the right of the pointer. */ *root_x += XINT (dx); @@ -8995,8 +9005,12 @@ w32_abort() button = MessageBox (NULL, "A fatal error has occurred!\n\n" "Would you like to attach a debugger?\n\n" - "Select YES to debug, NO to abort Emacs", - "Emacs Abort Dialog", + "Select YES to debug, NO to abort Emacs" +#if __GNUC__ + "\n\n(type \"gdb -p <emacs-PID>\" and\n" + "\"continue\" inside GDB before clicking YES.)" +#endif + , "Emacs Abort Dialog", MB_ICONEXCLAMATION | MB_TASKMODAL | MB_SETFOREGROUND | MB_YESNO); switch (button) diff --git a/src/w32menu.c b/src/w32menu.c index d441d14b259..dfd885eee08 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -738,7 +738,8 @@ cached information about equivalent key sequences. */) XSETFRAME (Vmenu_updating_frame, f); } - Vmenu_updating_frame = Qnil; + else + Vmenu_updating_frame = Qnil; #endif /* HAVE_MENUS */ title = Qnil; diff --git a/src/w32term.c b/src/w32term.c index 75a4151e8f2..8084685cf48 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -3338,8 +3338,8 @@ construct_drag_n_drop (result, msg, f) DragFinish (hdrop); XSETFRAME (frame, f); - result->frame_or_window = Fcons (frame, files); - result->arg = Qnil; + result->frame_or_window = frame; + result->arg = files; return Qnil; } diff --git a/src/window.c b/src/window.c index be3ecaa2b0b..e2678a3f3b8 100644 --- a/src/window.c +++ b/src/window.c @@ -65,7 +65,7 @@ static int window_min_size P_ ((struct window *, int, int, int *)); static void size_window P_ ((Lisp_Object, int, int, int)); static int freeze_window_start P_ ((struct window *, void *)); static int window_fixed_size_p P_ ((struct window *, int, int)); -static void enlarge_window P_ ((Lisp_Object, int, int, int)); +static void enlarge_window P_ ((Lisp_Object, int, int)); static Lisp_Object window_list P_ ((void)); static int add_window_to_list P_ ((struct window *, void *)); static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object, @@ -210,6 +210,10 @@ Lisp_Object Vwindow_configuration_change_hook; Lisp_Object Vscroll_preserve_screen_position; +/* Incremented by 1 whenever a window is deleted. */ + +int window_deletion_count; + #if 0 /* This isn't used anywhere. */ /* Nonzero means we can split a frame even if it is "unsplittable". */ static int inhibit_frame_unsplittable; @@ -1333,7 +1337,7 @@ delete_window (window) CHECK_WINDOW (window); p = XWINDOW (window); - /* It's okay to delete an already-deleted window. */ + /* It's a no-op to delete an already-deleted window. */ if (NILP (p->buffer) && NILP (p->hchild) && NILP (p->vchild)) @@ -1397,6 +1401,9 @@ delete_window (window) } } + /* Now we know we can delete this one. */ + window_deletion_count++; + tem = p->buffer; /* tem is null for dummy parent windows (which have inferiors but not any contents themselves) */ @@ -1962,7 +1969,7 @@ window_loop (type, obj, mini, frames) GCPRO1 (windows); best_window = Qnil; - for (; CONSP (windows); windows = CDR (windows)) + for (; CONSP (windows); windows = XCDR (windows)) { struct window *w; @@ -1996,11 +2003,13 @@ window_loop (type, obj, mini, frames) break; case GET_LRU_WINDOW: - /* t as arg means consider only full-width windows */ - if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w)) - break; - /* Ignore dedicated windows and minibuffers. */ - if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt)) + /* `obj' is an integer encoding a bitvector. + `obj & 1' means consider only full-width windows. + `obj & 2' means consider also dedicated windows. */ + if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w)) + || (!(XINT (obj) & 2) && EQ (w->dedicated, Qt)) + /* Minibuffer windows are always ignored. */ + || MINI_WINDOW_P (w)) break; if (NILP (best_window) || (XFASTINT (XWINDOW (best_window)->use_time) @@ -2051,9 +2060,9 @@ window_loop (type, obj, mini, frames) break; case GET_LARGEST_WINDOW: - { + { /* nil `obj' means to ignore dedicated windows. */ /* Ignore dedicated windows and minibuffers. */ - if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt)) + if (MINI_WINDOW_P (w) || (NILP (obj) && EQ (w->dedicated, Qt))) break; if (NILP (best_window)) @@ -2147,43 +2156,47 @@ check_all_windows () window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt); } -DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0, +DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0, doc: /* Return the window least recently selected or used for display. Return a full-width window if possible. A minibuffer window is never a candidate. -A dedicated window is never a candidate, so if all windows are dedicated, -the value is nil. +A dedicated window is never a candidate, unless DEDICATED is non-nil, + so if all windows are dedicated, the value is nil. If optional argument FRAME is `visible', search all visible frames. If FRAME is 0, search all visible and iconified frames. If FRAME is t, search all frames. If FRAME is nil, search only the selected frame. If FRAME is a frame, search only that frame. */) - (frame) - Lisp_Object frame; + (frame, dedicated) + Lisp_Object frame, dedicated; { register Lisp_Object w; /* First try for a window that is full-width */ - w = window_loop (GET_LRU_WINDOW, Qt, 0, frame); + w = window_loop (GET_LRU_WINDOW, + NILP (dedicated) ? make_number (1) : make_number (3), + 0, frame); if (!NILP (w) && !EQ (w, selected_window)) return w; /* If none of them, try the rest */ - return window_loop (GET_LRU_WINDOW, Qnil, 0, frame); + return window_loop (GET_LRU_WINDOW, + NILP (dedicated) ? make_number (0) : make_number (2), + 0, frame); } -DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0, +DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0, doc: /* Return the largest window in area. A minibuffer window is never a candidate. -A dedicated window is never a candidate, so if all windows are dedicated, -the value is nil. +A dedicated window is never a candidate unless DEDICATED is non-nil, + so if all windows are dedicated, the value is nil. If optional argument FRAME is `visible', search all visible frames. If FRAME is 0, search all visible and iconified frames. If FRAME is t, search all frames. If FRAME is nil, search only the selected frame. If FRAME is a frame, search only that frame. */) - (frame) - Lisp_Object frame; + (frame, dedicated) + Lisp_Object frame, dedicated; { - return window_loop (GET_LARGEST_WINDOW, Qnil, 0, + return window_loop (GET_LARGEST_WINDOW, dedicated, 0, frame); } @@ -3503,15 +3516,17 @@ displayed. */) if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame)) { /* Try visible frames first. */ - window = Fget_largest_window (Qvisible); + window = Fget_largest_window (Qvisible, Qt); /* If that didn't work, try iconified frames. */ if (NILP (window)) - window = Fget_largest_window (make_number (0)); + window = Fget_largest_window (make_number (0), Qt); +#if 0 /* Don't try windows on other displays. */ if (NILP (window)) - window = Fget_largest_window (Qt); + window = Fget_largest_window (Qt, Qt); +#endif } else - window = Fget_largest_window (frames); + window = Fget_largest_window (frames, Qt); /* If we got a tall enough full-width window that can be split, split it. */ @@ -3524,7 +3539,7 @@ displayed. */) { Lisp_Object upper, other; - window = Fget_lru_window (frames); + window = Fget_lru_window (frames, Qt); /* If the LRU window is selected, and big enough, and can be split, split it. */ if (!NILP (window) @@ -3533,23 +3548,27 @@ displayed. */) || EQ (XWINDOW (window)->parent, Qnil)) && window_height (window) >= window_min_height << 1) window = Fsplit_window (window, Qnil, Qnil); + else + window = Fget_lru_window (frames, Qnil); /* If Fget_lru_window returned nil, try other approaches. */ /* Try visible frames first. */ if (NILP (window)) window = Fget_buffer_window (buffer, Qvisible); if (NILP (window)) - window = Fget_largest_window (Qvisible); + window = Fget_largest_window (Qvisible, Qnil); /* If that didn't work, try iconified frames. */ if (NILP (window)) window = Fget_buffer_window (buffer, make_number (0)); if (NILP (window)) - window = Fget_largest_window (make_number (0)); - /* Try invisible frames. */ + window = Fget_largest_window (make_number (0), Qnil); + +#if 0 /* Don't try frames on other displays. */ if (NILP (window)) window = Fget_buffer_window (buffer, Qt); if (NILP (window)) - window = Fget_largest_window (Qt); + window = Fget_largest_window (Qt, Qnil); +#endif /* As a last resort, make a new frame. */ if (NILP (window)) window = Fframe_selected_window (call0 (Vpop_up_frame_function)); @@ -3571,12 +3590,12 @@ displayed. */) + XFASTINT (XWINDOW (window)->total_lines)); enlarge_window (upper, total / 2 - XFASTINT (XWINDOW (upper)->total_lines), - 0, 0); + 0); } } } else - window = Fget_lru_window (Qnil); + window = Fget_lru_window (Qnil, Qnil); Fset_window_buffer (window, buffer, Qnil); return display_buffer_1 (window); @@ -3648,7 +3667,7 @@ temp_output_buffer_show (buf) #endif set_buffer_internal (old); - if (!EQ (Vtemp_buffer_show_function, Qnil)) + if (!NILP (Vtemp_buffer_show_function)) call1 (Vtemp_buffer_show_function, buf); else { @@ -3862,20 +3881,18 @@ See Info node `(elisp)Splitting Windows' for more details and examples.*/) return new; } -DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p", +DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p", doc: /* Make current window ARG lines bigger. From program, optional second arg non-nil means grow sideways ARG columns. Interactively, if an argument is not given, make the window one line bigger. - -Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size -of the siblings above or to the left of the selected window. Only -siblings to the right or below are changed. */) - (arg, side, preserve_before) - register Lisp_Object arg, side, preserve_before; +If HORIZONTAL is non-nil, enlarge horizontally instead of vertically. +This function can delete windows, even the second window, if they get +too small. */) + (arg, horizontal) + Lisp_Object arg, horizontal; { CHECK_NUMBER (arg); - enlarge_window (selected_window, XINT (arg), !NILP (side), - !NILP (preserve_before)); + enlarge_window (selected_window, XINT (arg), !NILP (horizontal)); if (! NILP (Vwindow_configuration_change_hook)) call1 (Vrun_hooks, Qwindow_configuration_change_hook); @@ -3883,20 +3900,16 @@ siblings to the right or below are changed. */) return Qnil; } -DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p", +DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p", doc: /* Make current window ARG lines smaller. From program, optional second arg non-nil means shrink sideways arg columns. -Interactively, if an argument is not given, make the window one line smaller. - -Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size -of the siblings above or to the left of the selected window. Only +Interactively, if an argument is not given, make the window one line smaller. Only siblings to the right or below are changed. */) - (arg, side, preserve_before) - register Lisp_Object arg, side, preserve_before; + (arg, side) + Lisp_Object arg, side; { CHECK_NUMBER (arg); - enlarge_window (selected_window, -XINT (arg), !NILP (side), - !NILP (preserve_before)); + enlarge_window (selected_window, -XINT (arg), !NILP (side)); if (! NILP (Vwindow_configuration_change_hook)) call1 (Vrun_hooks, Qwindow_configuration_change_hook); @@ -3922,40 +3935,40 @@ window_width (window) #define CURBEG(w) \ - *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line)) + *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line)) #define CURSIZE(w) \ - *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines)) + *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines)) -/* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means - increase its width. Siblings of the selected window are resized to - fulfill the size request. If they become too small in the process, - they will be deleted. +/* Enlarge WINDOW by DELTA. + HORIZ_FLAG nonzero means enlarge it horizontally; + zero means do it vertically. - If PRESERVE_BEFORE is nonzero, that means don't alter - the siblings to the left or above WINDOW. */ + Siblings of the selected window are resized to fulfill the size + request. If they become too small in the process, they will be + deleted. */ static void -enlarge_window (window, delta, widthflag, preserve_before) +enlarge_window (window, delta, horiz_flag) Lisp_Object window; - int delta, widthflag, preserve_before; + int delta, horiz_flag; { Lisp_Object parent, next, prev; struct window *p; Lisp_Object *sizep; int maximum; int (*sizefun) P_ ((Lisp_Object)) - = widthflag ? window_width : window_height; + = horiz_flag ? window_width : window_height; void (*setsizefun) P_ ((Lisp_Object, int, int)) - = (widthflag ? set_window_width : set_window_height); + = (horiz_flag ? set_window_width : set_window_height); /* Check values of window_min_width and window_min_height for validity. */ check_min_window_sizes (); /* Give up if this window cannot be resized. */ - if (window_fixed_size_p (XWINDOW (window), widthflag, 1)) + if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) error ("Window is not resizable"); /* Find the parent of the selected window. */ @@ -3966,12 +3979,12 @@ enlarge_window (window, delta, widthflag, preserve_before) if (NILP (parent)) { - if (widthflag) + if (horiz_flag) error ("No other window to side of this one"); break; } - if (widthflag + if (horiz_flag ? !NILP (XWINDOW (parent)->hchild) : !NILP (XWINDOW (parent)->vchild)) break; @@ -3986,33 +3999,18 @@ enlarge_window (window, delta, widthflag, preserve_before) /* Compute the maximum size increment this window can have. */ - if (preserve_before) - { - if (!NILP (parent)) - { - maxdelta = (*sizefun) (parent) - XINT (*sizep); - /* Subtract size of siblings before, since we can't take that. */ - maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent)); - } - else - maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next) - - window_min_size (XWINDOW (p->next), - widthflag, 0, 0)) - : (delta = 0)); - } - else - maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep) - /* This is a main window followed by a minibuffer. */ - : !NILP (p->next) ? ((*sizefun) (p->next) - - window_min_size (XWINDOW (p->next), - widthflag, 0, 0)) - /* This is a minibuffer following a main window. */ - : !NILP (p->prev) ? ((*sizefun) (p->prev) - - window_min_size (XWINDOW (p->prev), - widthflag, 0, 0)) - /* This is a frame with only one window, a minibuffer-only - or a minibufferless frame. */ - : (delta = 0)); + maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep) + /* This is a main window followed by a minibuffer. */ + : !NILP (p->next) ? ((*sizefun) (p->next) + - window_min_size (XWINDOW (p->next), + horiz_flag, 0, 0)) + /* This is a minibuffer following a main window. */ + : !NILP (p->prev) ? ((*sizefun) (p->prev) + - window_min_size (XWINDOW (p->prev), + horiz_flag, 0, 0)) + /* This is a frame with only one window, a minibuffer-only + or a minibufferless frame. */ + : (delta = 0)); if (delta > maxdelta) /* This case traps trying to make the minibuffer @@ -4021,7 +4019,7 @@ enlarge_window (window, delta, widthflag, preserve_before) delta = maxdelta; } - if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0)) + if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0)) { delete_window (window); return; @@ -4034,11 +4032,10 @@ enlarge_window (window, delta, widthflag, preserve_before) maximum = 0; for (next = p->next; ! NILP (next); next = XWINDOW (next)->next) maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), - widthflag, 0, 0); - if (! preserve_before) - for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) - maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), - widthflag, 0, 0); + horiz_flag, 0, 0); + for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) + maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), + horiz_flag, 0, 0); /* If we can get it all from them without deleting them, do so. */ if (delta <= maximum) @@ -4054,13 +4051,13 @@ enlarge_window (window, delta, widthflag, preserve_before) moving away from this window in both directions alternately, and take as much as we can get without deleting that sibling. */ while (delta != 0 - && (!NILP (next) || (!preserve_before && !NILP (prev)))) + && (!NILP (next) || !NILP (prev))) { if (! NILP (next)) { int this_one = ((*sizefun) (next) - window_min_size (XWINDOW (next), - widthflag, 0, &fixed_p)); + horiz_flag, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) @@ -4078,11 +4075,11 @@ enlarge_window (window, delta, widthflag, preserve_before) if (delta == 0) break; - if (!preserve_before && ! NILP (prev)) + if (! NILP (prev)) { int this_one = ((*sizefun) (prev) - window_min_size (XWINDOW (prev), - widthflag, 0, &fixed_p)); + horiz_flag, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) @@ -4185,10 +4182,10 @@ enlarge_window (window, delta, widthflag, preserve_before) int n = 1; for (s = w->next; !NILP (s); s = XWINDOW (s)->next) - if (!window_fixed_size_p (XWINDOW (s), widthflag, 0)) + if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0)) ++n; for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev) - if (!window_fixed_size_p (XWINDOW (s), widthflag, 0)) + if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0)) ++n; delta1 = n * delta; @@ -4215,9 +4212,136 @@ enlarge_window (window, delta, widthflag, preserve_before) adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window)))); } + +/* Adjust the size of WINDOW by DELTA, moving only its trailing edge. + HORIZ_FLAG nonzero means adjust the width, moving the right edge. + zero means adjust the height, moving the bottom edge. + + Following siblings of the selected window are resized to fulfill + the size request. If they become too small in the process, they + are not deleted; instead, we signal an error. */ + +static void +adjust_window_trailing_edge (window, delta, horiz_flag) + Lisp_Object window; + int delta, horiz_flag; +{ + Lisp_Object parent, child; + struct window *p; + Lisp_Object old_config = Fcurrent_window_configuration (Qnil); + int delcount = window_deletion_count; + + /* Check values of window_min_width and window_min_height for + validity. */ + check_min_window_sizes (); + + if (NILP (window)) + window = Fselected_window (); + + CHECK_WINDOW (window); + + /* Give up if this window cannot be resized. */ + if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) + error ("Window is not resizable"); + + while (1) + { + p = XWINDOW (window); + parent = p->parent; + + /* Make sure there is a following window. */ + if (NILP (parent) + && (horiz_flag ? 1 + : NILP (XWINDOW (window)->next))) + { + Fset_window_configuration (old_config); + error ("No other window following this one"); + } + + /* Don't make this window too small. */ + if (XINT (CURSIZE (window)) + delta + < (horiz_flag ? window_min_width : window_min_height)) + { + Fset_window_configuration (old_config); + error ("Cannot adjust window size as specified"); + } + + /* Clear out some redisplay caches. */ + XSETFASTINT (p->last_modified, 0); + XSETFASTINT (p->last_overlay_modified, 0); + + /* Adjust this window's edge. */ + XSETINT (CURSIZE (window), + XINT (CURSIZE (window)) + delta); + + /* If this window has following siblings in the desired dimension, + make them smaller. + (If we reach the top of the tree and can never do this, + we will fail and report an error, above.) */ + if (horiz_flag + ? !NILP (XWINDOW (parent)->hchild) + : !NILP (XWINDOW (parent)->vchild)) + { + if (!NILP (XWINDOW (window)->next)) + { + XSETINT (CURBEG (p->next), + XINT (CURBEG (p->next)) + delta); + size_window (p->next, XINT (CURSIZE (p->next)) - delta, + horiz_flag, 0); + break; + } + } + else + /* Here we have a chain of parallel siblings, in the other dimension. + Change the size of the other siblings. */ + for (child = (horiz_flag + ? XWINDOW (parent)->vchild + : XWINDOW (parent)->hchild); + ! NILP (child); + child = XWINDOW (child)->next) + if (! EQ (child, window)) + size_window (child, XINT (CURSIZE (child)) + delta, + horiz_flag, 0); + + window = parent; + } + + /* If we made a window so small it got deleted, + we failed. Report failure. */ + if (delcount != window_deletion_count) + { + Fset_window_configuration (old_config); + error ("Cannot adjust window size as specified"); + } + + /* Adjust glyph matrices. */ + adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window)))); +} + #undef CURBEG #undef CURSIZE +DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge, + Sadjust_window_trailing_edge, 3, 3, 0, + doc: /* Adjust the bottom or right edge of WINDOW by DELTA. +If HORIZONTAL is non-nil, that means adjust the width, moving the right edge. +Otherwise, adjust the height, moving the bottom edge. + +Following siblings of the selected window are resized to fulfill +the size request. If they become too small in the process, they +are not deleted; instead, we signal an error. */) + (window, delta, horizontal) + Lisp_Object window, delta, horizontal; +{ + CHECK_NUMBER (delta); + adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal)); + + if (! NILP (Vwindow_configuration_change_hook)) + call1 (Vrun_hooks, Qwindow_configuration_change_hook); + + return Qnil; +} + /*********************************************************************** @@ -4452,7 +4576,7 @@ shrink_mini_window (w) among the other windows. */ Lisp_Object window; XSETWINDOW (window, w); - enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0); + enlarge_window (window, 1 - XFASTINT (w->total_lines), 0); } } @@ -5681,7 +5805,23 @@ the return value is nil. Otherwise the value is t. */) else { if (XBUFFER (new_current_buffer) == current_buffer) - old_point = PT; + /* The code further down "preserves point" by saving here PT in + old_point and then setting it later back into PT. When the + current-selected-window and the final-selected-window both show + the current buffer, this suffers from the problem that the + current PT is the window-point of the current-selected-window, + while the final PT is the point of the final-selected-window, so + this copy from one PT to the other would end up moving the + window-point of the final-selected-window to the window-point of + the current-selected-window. So we have to be careful which + point of the current-buffer we copy into old_point. */ + if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer) + && WINDOWP (selected_window) + && EQ (XWINDOW (selected_window)->buffer, new_current_buffer) + && !EQ (selected_window, data->current_window)) + old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos; + else + old_point = PT; else /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of point in new_current_buffer as of the last time this buffer was @@ -7098,6 +7238,7 @@ The selected frame is the one whose configuration has changed. */); defsubr (&Ssplit_window); defsubr (&Senlarge_window); defsubr (&Sshrink_window); + defsubr (&Sadjust_window_trailing_edge); defsubr (&Sscroll_up); defsubr (&Sscroll_down); defsubr (&Sscroll_left); diff --git a/src/window.h b/src/window.h index 46d75de384f..ed4c8728117 100644 --- a/src/window.h +++ b/src/window.h @@ -1,6 +1,6 @@ /* Window definitions for GNU Emacs. Copyright (C) 1985, 1986, 1993, 1995, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -865,6 +865,7 @@ extern Lisp_Object Vwindow_list; EXFUN (Fwindow_end, 2); EXFUN (Fselected_window, 0); +EXFUN (Fwindow_minibuffer_p, 1); EXFUN (Fdelete_window, 1); EXFUN (Fwindow_buffer, 1); EXFUN (Fget_buffer_window, 2); diff --git a/src/xdisp.c b/src/xdisp.c index fd730075646..3af661108d8 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2981,11 +2981,13 @@ handle_stop (it) struct it *it; { enum prop_handled handled; - int handle_overlay_change_p = 1; + int handle_overlay_change_p; struct props *p; it->dpvec = NULL; it->current.dpvec_index = -1; + handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p; + it->ignore_overlay_strings_at_pos_p = 0; /* Use face of preceding text for ellipsis (if invisible) */ if (it->selective_display_ellipsis_p) @@ -3179,6 +3181,9 @@ handle_fontified_prop (it) Lisp_Object prop, pos; enum prop_handled handled = HANDLED_NORMALLY; + if (!NILP (Vmemory_full)) + return handled; + /* Get the value of the `fontified' property at IT's current buffer position. (The `fontified' property doesn't have a special meaning in strings.) If the value is nil, call functions from @@ -5777,6 +5782,9 @@ set_iterator_to_next (it, reseat_p) reseat_at_next_visible_line_start (it, 1); else if (it->dpvec_char_len > 0) { + if (it->method == GET_FROM_STRING + && it->n_overlay_strings > 0) + it->ignore_overlay_strings_at_pos_p = 1; it->len = it->dpvec_char_len; set_iterator_to_next (it, reseat_p); } @@ -8722,7 +8730,7 @@ static Lisp_Object mode_line_string_face_prop; static Lisp_Object Vmode_line_unwind_vector; static Lisp_Object -format_mode_line_unwind_data (obuf) +format_mode_line_unwind_data (obuf, save_proptrans) struct buffer *obuf; { Lisp_Object vector; @@ -8738,7 +8746,7 @@ format_mode_line_unwind_data (obuf) AREF (vector, 0) = make_number (mode_line_target); AREF (vector, 1) = make_number (MODE_LINE_NOPROP_LEN (0)); AREF (vector, 2) = mode_line_string_list; - AREF (vector, 3) = mode_line_proptrans_alist; + AREF (vector, 3) = (save_proptrans ? mode_line_proptrans_alist : Qt); AREF (vector, 4) = mode_line_string_face; AREF (vector, 5) = mode_line_string_face_prop; @@ -8757,7 +8765,8 @@ unwind_format_mode_line (vector) mode_line_target = XINT (AREF (vector, 0)); mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1)); mode_line_string_list = AREF (vector, 2); - mode_line_proptrans_alist = AREF (vector, 3); + if (! EQ (AREF (vector, 3), Qt)) + mode_line_proptrans_alist = AREF (vector, 3); mode_line_string_face = AREF (vector, 4); mode_line_string_face_prop = AREF (vector, 5); @@ -8880,7 +8889,7 @@ x_consider_frame_title (frame) mode_line_target so that display_mode_element will output into mode_line_noprop_buf; then display the title. */ record_unwind_protect (unwind_format_mode_line, - format_mode_line_unwind_data (current_buffer)); + format_mode_line_unwind_data (current_buffer, 0)); set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer)); fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; @@ -10677,7 +10686,8 @@ redisplay_internal (preserve_echo_area) clear_garbaged_frames (); /* Build menubar and tool-bar items. */ - prepare_menu_bars (); + if (NILP (Vmemory_full)) + prepare_menu_bars (); if (windows_or_buffers_changed) update_mode_lines++; @@ -15769,7 +15779,9 @@ display_line (it) produce_special_glyphs (it, IT_CONTINUATION); row->continued_p = 1; + it->current_x = x_before; it->continuation_lines_width += x; + extend_face_to_end_of_line (it); if (nglyphs > 1 && i > 0) { @@ -16254,7 +16266,7 @@ display_mode_line (w, face_id, format) it.base_face_id = it.face_id = DEFAULT_FACE_ID; record_unwind_protect (unwind_format_mode_line, - format_mode_line_unwind_data (NULL)); + format_mode_line_unwind_data (NULL, 0)); mode_line_target = MODE_LINE_DISPLAY; @@ -16289,6 +16301,44 @@ display_mode_line (w, face_id, format) return it.glyph_row->height; } +/* Move element ELT in LIST to the front of LIST. + Return the updated list. */ + +static Lisp_Object +move_elt_to_front (elt, list) + Lisp_Object elt, list; +{ + register Lisp_Object tail, prev; + register Lisp_Object tem; + + tail = list; + prev = Qnil; + while (CONSP (tail)) + { + tem = XCAR (tail); + + if (EQ (elt, tem)) + { + /* Splice out the link TAIL. */ + if (NILP (prev)) + list = XCDR (tail); + else + Fsetcdr (prev, XCDR (tail)); + + /* Now make it the first. */ + Fsetcdr (tail, list); + return tail; + } + else + prev = tail; + tail = XCDR (tail); + QUIT; + } + + /* Not found--return unchanged LIST. */ + return list; +} + /* Contribute ELT to the mode line for window IT->w. How it translates into text depends on its data type. @@ -16338,7 +16388,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) unsigned char c; int offset = 0; - if (!NILP (props) || risky) + if (SCHARS (elt) > 0 + && (!NILP (props) || risky)) { Lisp_Object oprops, aelt; oprops = Ftext_properties_at (make_number (0), elt); @@ -16369,14 +16420,22 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) aelt = Fassoc (elt, mode_line_proptrans_alist); if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt)))) { - mode_line_proptrans_alist - = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist)); + /* AELT is what we want. Move it to the front + without consing. */ elt = XCAR (aelt); + mode_line_proptrans_alist + = move_elt_to_front (aelt, mode_line_proptrans_alist); } else { Lisp_Object tem; + /* If AELT has the wrong props, it is useless. + so get rid of it. */ + if (! NILP (aelt)) + mode_line_proptrans_alist + = Fdelq (aelt, mode_line_proptrans_alist); + elt = Fcopy_sequence (elt); Fset_text_properties (make_number (0), Flength (elt), props, elt); @@ -16901,8 +16960,11 @@ are the selected window and the window's buffer). */) if (XBUFFER (buffer) != current_buffer) old_buffer = current_buffer; + /* Save things including mode_line_proptrans_alist, + and set that to nil so that we don't alter the outer value. */ record_unwind_protect (unwind_format_mode_line, - format_mode_line_unwind_data (old_buffer)); + format_mode_line_unwind_data (old_buffer, 1)); + mode_line_proptrans_alist = Qnil; if (old_buffer) set_buffer_internal_1 (XBUFFER (buffer)); @@ -17288,6 +17350,18 @@ decode_mode_spec (w, c, field_width, precision, multibyte) return decode_mode_spec_buf; } + case 'e': +#ifndef SYSTEM_MALLOC + { + if (NILP (Vmemory_full)) + return ""; + else + return "!MEM FULL! "; + } +#else + return ""; +#endif + case 'F': /* %F displays the frame name. */ if (!NILP (f->title)) @@ -18810,19 +18884,15 @@ set_glyph_string_background_width (s, start, last_x) { /* If the face of this glyph string has to be drawn to the end of the drawing area, set S->extends_to_end_of_line_p. */ - struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID); if (start == s->row->used[s->area] && s->area == TEXT_AREA - && ((s->hl == DRAW_NORMAL_TEXT - && (s->row->fill_line_p - || s->face->background != default_face->background - || s->face->stipple != default_face->stipple - || s->row->mouse_face_p)) - || s->hl == DRAW_MOUSE_FACE - || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) - && s->row->fill_line_p))) - s->extends_to_end_of_line_p = 1; + && ((s->row->fill_line_p + && (s->hl == DRAW_NORMAL_TEXT + || s->hl == DRAW_IMAGE_RAISED + || s->hl == DRAW_IMAGE_SUNKEN)) + || s->hl == DRAW_MOUSE_FACE)) + s->extends_to_end_of_line_p = 1; /* If S extends its face to the end of the line, set its background_width to the distance to the right edge of the drawing @@ -20873,7 +20943,7 @@ get_window_cursor_type (w, glyph, width, active_cursor) /* Use cursor-in-non-selected-windows for non-selected window or frame. */ if (non_selected) { - alt_cursor = XBUFFER (w->buffer)->cursor_in_non_selected_windows; + alt_cursor = b->cursor_in_non_selected_windows; return get_specified_cursor_type (alt_cursor, width); } @@ -21408,7 +21478,11 @@ show_mouse_face (dpyinfo, draw) if (row == last) end_hpos = dpyinfo->mouse_face_end_col; else - end_hpos = row->used[TEXT_AREA]; + { + end_hpos = row->used[TEXT_AREA]; + if (draw == DRAW_NORMAL_TEXT) + row->fill_line_p = 1; /* Clear to end of line */ + } if (end_hpos > start_hpos) { @@ -23699,7 +23773,11 @@ go back to their normal size. */); Each element has the form (ON-STATE . OFF-STATE). Whenever the `cursor-type' frame-parameter or variable equals ON-STATE, comparing using `equal', Emacs uses OFF-STATE to specify -how to blink it off. */); +how to blink it off. ON-STATE and OFF-STATE are values for +the `cursor-type' frame parameter. + +If a frame's ON-STATE has no entry in this list, +the frame's other specifications determine how to blink the cursor off. */); Vblink_cursor_alist = Qnil; DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p, diff --git a/src/xfaces.c b/src/xfaces.c index 2c5f729f6c5..ba1bbe7f1f6 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -277,6 +277,10 @@ Boston, MA 02110-1301, USA. */ #define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified) +/* Non-zero if face attribute ATTR is `ignore-defface'. */ + +#define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), Qignore_defface) + /* Value is the number of elements of VECTOR. */ #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR)) @@ -316,6 +320,7 @@ Lisp_Object Qultra_expanded; Lisp_Object Qreleased_button, Qpressed_button; Lisp_Object QCstyle, QCcolor, QCline_width; Lisp_Object Qunspecified; +Lisp_Object Qignore_defface; char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg"; @@ -3165,48 +3170,64 @@ check_lface_attrs (attrs) Lisp_Object *attrs; { xassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX]) || STRINGP (attrs[LFACE_FAMILY_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX]) || SYMBOLP (attrs[LFACE_SWIDTH_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_AVGWIDTH_INDEX]) || INTEGERP (attrs[LFACE_AVGWIDTH_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX]) || INTEGERP (attrs[LFACE_HEIGHT_INDEX]) || FLOATP (attrs[LFACE_HEIGHT_INDEX]) || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX]) || SYMBOLP (attrs[LFACE_WEIGHT_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX]) || SYMBOLP (attrs[LFACE_SLANT_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX]) || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX]) || STRINGP (attrs[LFACE_UNDERLINE_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX]) || SYMBOLP (attrs[LFACE_OVERLINE_INDEX]) || STRINGP (attrs[LFACE_OVERLINE_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX]) || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX]) || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX]) || SYMBOLP (attrs[LFACE_BOX_INDEX]) || STRINGP (attrs[LFACE_BOX_INDEX]) || INTEGERP (attrs[LFACE_BOX_INDEX]) || CONSP (attrs[LFACE_BOX_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX]) || SYMBOLP (attrs[LFACE_INVERSE_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX]) || STRINGP (attrs[LFACE_FOREGROUND_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX]) || STRINGP (attrs[LFACE_BACKGROUND_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX]) || NILP (attrs[LFACE_INHERIT_INDEX]) || SYMBOLP (attrs[LFACE_INHERIT_INDEX]) || CONSP (attrs[LFACE_INHERIT_INDEX])); #ifdef HAVE_WINDOW_SYSTEM xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX]) || SYMBOLP (attrs[LFACE_STIPPLE_INDEX]) || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX]))); xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX]) || NILP (attrs[LFACE_FONT_INDEX]) || STRINGP (attrs[LFACE_FONT_INDEX])); xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX]) @@ -3403,7 +3424,7 @@ lface_fully_specified_p (attrs) for (i = 1; i < LFACE_VECTOR_SIZE; ++i) if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX && i != LFACE_AVGWIDTH_INDEX && i != LFACE_FONTSET_INDEX) - if (UNSPECIFIEDP (attrs[i]) + if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i])) #ifdef MAC_OS /* MAC_TODO: No stipple support on Mac OS yet, this index is always unspecified. */ @@ -4110,7 +4131,18 @@ FRAME 0 means change the face on all frames, and change the default /* Set lface to the Lisp attribute vector of FACE. */ if (EQ (frame, Qt)) - lface = lface_from_face_name (NULL, face, 1); + { + lface = lface_from_face_name (NULL, face, 1); + + /* When updating face-new-frame-defaults, we put :ignore-defface + where the caller wants `unspecified'. This forces the frame + defaults to ignore the defface value. Otherwise, the defface + will take effect, which is generally not what is intended. + The value of that attribute will be inherited from some other + face during face merging. See internal_merge_in_global_face. */ + if (UNSPECIFIEDP (value)) + value = Qignore_defface; + } else { if (NILP (frame)) @@ -4126,7 +4158,7 @@ FRAME 0 means change the face on all frames, and change the default if (EQ (attr, QCfamily)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { CHECK_STRING (value); if (SCHARS (value) == 0) @@ -4138,7 +4170,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCheight)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { Lisp_Object test; @@ -4159,7 +4191,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCweight)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { CHECK_SYMBOL (value); if (face_numeric_weight (value) < 0) @@ -4171,7 +4203,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCslant)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { CHECK_SYMBOL (value); if (face_numeric_slant (value) < 0) @@ -4183,7 +4215,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCunderline)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !EQ (value, Qnil)) @@ -4197,7 +4229,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCoverline)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !EQ (value, Qnil)) @@ -4211,7 +4243,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCstrike_through)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !EQ (value, Qnil)) @@ -4232,7 +4264,7 @@ FRAME 0 means change the face on all frames, and change the default if (EQ (value, Qt)) value = make_number (1); - if (UNSPECIFIEDP (value)) + if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value)) valid_p = 1; else if (NILP (value)) valid_p = 1; @@ -4289,7 +4321,7 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { CHECK_SYMBOL (value); if (!EQ (value, Qt) && !NILP (value)) @@ -4300,7 +4332,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCforeground)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -4314,7 +4346,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCbackground)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -4329,7 +4361,7 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCstipple)) { #ifdef HAVE_X_WINDOWS - if (!UNSPECIFIEDP (value) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value) && !NILP (value) && NILP (Fbitmap_spec_p (value))) signal_error ("Invalid stipple attribute", value); @@ -4339,7 +4371,7 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCwidth)) { - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { CHECK_SYMBOL (value); if (face_numeric_swidth (value) < 0) @@ -4364,7 +4396,7 @@ FRAME 0 means change the face on all frames, and change the default else f = check_x_frame (frame); - if (!UNSPECIFIEDP (value)) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { CHECK_STRING (value); @@ -4419,7 +4451,7 @@ FRAME 0 means change the face on all frames, and change the default signal_error ("Invalid face attribute name", attr); if (font_related_attr_p - && !UNSPECIFIEDP (value)) + && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) /* If a font-related attribute other than QCfont is specified, the original `font' attribute nor that of default face is useless to determine a new font. Thus, we set it to nil so that font @@ -4441,7 +4473,7 @@ FRAME 0 means change the face on all frames, and change the default ++windows_or_buffers_changed; } - if (!UNSPECIFIEDP (value) + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value) && NILP (Fequal (old_value, value))) { Lisp_Object param; @@ -4742,7 +4774,7 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource", if (SYMBOLP (boolean_value)) value = boolean_value; } - else if (EQ (attr, QCbox)) + else if (EQ (attr, QCbox) || EQ (attr, QCinherit)) value = Fcar (Fread_from_string (value, Qnil, Qnil)); return Finternal_set_lisp_face_attribute (face, attr, value, frame); @@ -4858,7 +4890,7 @@ DEFUN ("face-attribute-relative-p", Fface_attribute_relative_p, (attribute, value) Lisp_Object attribute, value; { - if (EQ (value, Qunspecified)) + if (EQ (value, Qunspecified) || (EQ (value, Qignore_defface))) return Qt; else if (EQ (attribute, QCheight)) return INTEGERP (value) ? Qnil : Qt; @@ -4874,7 +4906,7 @@ the result will be absolute, otherwise it will be relative. */) (attribute, value1, value2) Lisp_Object attribute, value1, value2; { - if (EQ (value1, Qunspecified)) + if (EQ (value1, Qunspecified) || EQ (value1, Qignore_defface)) return value2; else if (EQ (attribute, QCheight)) return merge_face_heights (value1, value2, value1); @@ -4946,6 +4978,9 @@ frames). If FRAME is omitted or nil, use the selected frame. */) else signal_error ("Invalid face attribute name", keyword); + if (IGNORE_DEFFACE_P (value)) + return Qunspecified; + return value; } @@ -5028,7 +5063,10 @@ Default face attributes override any local face attributes. */) gvec = XVECTOR (global_lface)->contents; for (i = 1; i < LFACE_VECTOR_SIZE; ++i) if (! UNSPECIFIEDP (gvec[i])) - lvec[i] = gvec[i]; + if (IGNORE_DEFFACE_P (gvec[i])) + lvec[i] = Qunspecified; + else + lvec[i] = gvec[i]; return Qnil; } @@ -8210,6 +8248,8 @@ syms_of_xfaces () staticpro (&Qforeground_color); Qunspecified = intern ("unspecified"); staticpro (&Qunspecified); + Qignore_defface = intern (":ignore-defface"); + staticpro (&Qignore_defface); Qface_alias = intern ("face-alias"); staticpro (&Qface_alias); diff --git a/src/xfns.c b/src/xfns.c index a8640d72986..69573dbac65 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -155,6 +155,10 @@ int display_hourglass_p; int x_use_old_gtk_file_dialog; +/* If non-zero, by default show hidden files in the GTK file chooser. */ + +int x_gtk_show_hidden_files; + /* The background and shape of the mouse pointer, and shape when not over text or in the modeline. */ @@ -609,7 +613,7 @@ x_real_positions (f, xptr, yptr) if (! had_errors) { - int ign; + unsigned int ign; Window child, rootw; /* Get the real coordinates for the WM window upper left corner */ @@ -795,9 +799,7 @@ xg_set_icon (f, file) { GdkPixbuf *pixbuf; GError *err = NULL; - char *filename; - - filename = SDATA (found); + char *filename = (char *) SDATA (found); BLOCK_INPUT; pixbuf = gdk_pixbuf_new_from_file (filename, &err); @@ -819,6 +821,22 @@ xg_set_icon (f, file) UNGCPRO; return result; } + +int +xg_set_icon_from_xpm_data (f, data) + FRAME_PTR f; + char **data; +{ + int result = 0; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) data); + + if (!pixbuf) + return 0; + + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); + g_object_unref (pixbuf); + return 1; +} #endif /* USE_GTK */ @@ -1608,7 +1626,7 @@ x_set_name_internal (f, name) #ifdef USE_GTK gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - SDATA (ENCODE_UTF_8 (name))); + (char *) SDATA (ENCODE_UTF_8 (name))); #else /* not USE_GTK */ XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text); #endif /* not USE_GTK */ @@ -3339,10 +3357,17 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_OUTER_WINDOW (f), dpyinfo->Xatom_wm_client_leader, XA_WINDOW, 32, PropModeReplace, - (char *) &dpyinfo->client_leader_window, 1); + (unsigned char *) &dpyinfo->client_leader_window, 1); UNBLOCK_INPUT; } + /* Initialize `default-minibuffer-frame' in case this is the first + frame on this display device. */ + if (FRAME_HAS_MINIBUF_P (f) + && (!FRAMEP (kb->Vdefault_minibuffer_frame) + || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))) + kb->Vdefault_minibuffer_frame = frame; + UNGCPRO; /* Make sure windows on this frame appear in calls to next-window @@ -4903,16 +4928,22 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y) if (INTEGERP (top)) *root_y = XINT (top); - else if (*root_y + XINT (dy) - height < 0) - *root_y -= XINT (dy); - else - { - *root_y -= height; + else if (*root_y + XINT (dy) <= 0) + *root_y = 0; /* Can happen for negative dy */ + else if (*root_y + XINT (dy) + height <= FRAME_X_DISPLAY_INFO (f)->height) + /* It fits below the pointer */ *root_y += XINT (dy); - } + else if (height + XINT (dy) <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XINT (dy); + else + /* Put it on the top. */ + *root_y = 0; if (INTEGERP (left)) *root_x = XINT (left); + else if (*root_x + XINT (dx) <= 0) + *root_x = 0; /* Can happen for negative dx */ else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width) /* It fits to the right of the pointer. */ *root_x += XINT (dx); @@ -5193,8 +5224,27 @@ Value is t if tooltip was open, nil otherwise. */) File selection dialog ***********************************************************************/ -#ifdef USE_MOTIF +DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog, + Sx_uses_old_gtk_dialog, + 0, 0, 0, + doc: /* Return t if the old Gtk+ file selection dialog is used. */) + () +{ +#ifdef USE_GTK + extern int use_dialog_box; + extern int use_file_dialog; + + if (use_dialog_box + && use_file_dialog + && have_menus_p () + && xg_uses_old_file_dialog ()) + return Qt; +#endif + return Qnil; +} + +#ifdef USE_MOTIF /* Callback for "OK" and "Cancel" on file selection dialog. */ static void @@ -5479,7 +5529,8 @@ DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p, doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME. FRAME nil means use the selected frame. Value is t if we know that both keys are present, and are mapped to the -usual X keysyms. */) +usual X keysyms. Value is `lambda' if we cannot determine if both keys are +present and mapped to the usual X keysyms. */) (frame) Lisp_Object frame; { @@ -5498,7 +5549,7 @@ usual X keysyms. */) if (!XkbLibraryVersion (&major, &minor)) { UNBLOCK_INPUT; - return Qnil; + return Qlambda; } /* Check that the server supports XKB. */ @@ -5507,7 +5558,7 @@ usual X keysyms. */) if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor)) { UNBLOCK_INPUT; - return Qnil; + return Qlambda; } /* In this code we check that the keyboard has physical keys with names @@ -5562,7 +5613,7 @@ usual X keysyms. */) UNBLOCK_INPUT; return have_keys; #else /* not HAVE_XKBGETKEYBOARD */ - return Qnil; + return Qlambda; #endif /* not HAVE_XKBGETKEYBOARD */ } @@ -5725,6 +5776,14 @@ chooser is used instead. To turn off all file dialogs set the variable `use-file-dialog'. */); x_use_old_gtk_file_dialog = 0; + DEFVAR_BOOL ("x-gtk-show-hidden-files", &x_gtk_show_hidden_files, + doc: /* *If non-nil, the GTK file chooser will by default show hidden files. +Note that this is just the default, there is a toggle button on the file +chooser to show or not show hidden files on a case by case basis. */); + x_gtk_show_hidden_files = 0; + + Fprovide (intern ("x"), Qnil); + #ifdef USE_X_TOOLKIT Fprovide (intern ("x-toolkit"), Qnil); #ifdef USE_MOTIF @@ -5812,6 +5871,7 @@ variable `use-file-dialog'. */); last_show_tip_args = Qnil; staticpro (&last_show_tip_args); + defsubr (&Sx_uses_old_gtk_dialog); #if defined (USE_MOTIF) || defined (USE_GTK) defsubr (&Sx_file_dialog); #endif diff --git a/src/xmenu.c b/src/xmenu.c index 2de8c0917d4..816f8307850 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -899,8 +899,11 @@ no quit occurs and `x-popup-menu' returns nil. */) xpos += XINT (x); ypos += XINT (y); + + XSETFRAME (Vmenu_updating_frame, f); } - Vmenu_updating_frame = Qnil; + else + Vmenu_updating_frame = Qnil; #endif /* HAVE_MENUS */ record_unwind_protect (unuse_menu_items, Qnil); @@ -1572,6 +1575,15 @@ menubar_selection_callback (widget, client_data) if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f) return; + /* For a group of radio buttons, GTK calls the selection callback first + for the item that was active before the selection and then for the one that + is active after the selection. For C-h k this means we get the help on + the deselected item and then the selected item is executed. Prevent that + by ignoring the non-active item. */ + if (GTK_IS_RADIO_MENU_ITEM (widget) + && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) + return; + /* When a menu is popped down, X generates a focus event (i.e. focus goes back to the frame below the menu). Since GTK buffers events, we force it out here before the menu selection event. Otherwise @@ -1891,7 +1903,7 @@ update_submenu_strings (first_wv) { if (STRINGP (wv->lname)) { - wv->name = SDATA (wv->lname); + wv->name = (char *) SDATA (wv->lname); /* Ignore the @ that means "separate pane". This is a kludge, but this isn't worth more time. */ @@ -1904,7 +1916,7 @@ update_submenu_strings (first_wv) } if (STRINGP (wv->lkey)) - wv->key = SDATA (wv->lkey); + wv->key = (char *) SDATA (wv->lkey); if (wv->contents) update_submenu_strings (wv->contents); @@ -3331,6 +3343,11 @@ xmenu_show (f, x, y, for_click, keymaps, title, error) return Qnil; } + /* Don't GC while we prepare and show the menu, + because we give the oldxmenu library pointers to the + contents of strings. */ + inhibit_garbage_collection (); + #ifdef HAVE_X_WINDOWS /* Adjust coordinates to relative to the outer (window manager) window. */ x += FRAME_OUTER_TO_INNER_DIFF_X (f); diff --git a/src/xselect.c b/src/xselect.c index 4db86c1cc5a..b41a05825ae 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -2727,11 +2727,11 @@ x_handle_dnd_message (f, event, dpyinfo, bufp) mouse_position_for_drop (f, &x, &y); bufp->kind = DRAG_N_DROP_EVENT; - bufp->frame_or_window = Fcons (frame, vec); + bufp->frame_or_window = frame; bufp->timestamp = CurrentTime; bufp->x = make_number (x); bufp->y = make_number (y); - bufp->arg = Qnil; + bufp->arg = vec; bufp->modifiers = 0; return 1; diff --git a/src/xterm.c b/src/xterm.c index e20935f0be4..d34a25ab6f6 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -250,6 +250,7 @@ static unsigned long ignore_next_mouse_click_timeout; /* Where the mouse was last time we reported a mouse event. */ static XRectangle last_mouse_glyph; +static FRAME_PTR last_mouse_glyph_frame; static Lisp_Object last_mouse_press_frame; /* The scroll bar in which the last X motion event occurred. @@ -3602,20 +3603,24 @@ note_mouse_movement (frame, event) frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, -1, -1); + last_mouse_glyph_frame = 0; return 1; } + /* Has the mouse moved off the glyph it was on at the last sighting? */ - if (event->x < last_mouse_glyph.x - || event->x >= last_mouse_glyph.x + last_mouse_glyph.width - || event->y < last_mouse_glyph.y - || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) + if (frame != last_mouse_glyph_frame + || event->x < last_mouse_glyph.x + || event->x >= last_mouse_glyph.x + last_mouse_glyph.width + || event->y < last_mouse_glyph.y + || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, event->x, event->y); /* Remember which glyph we're now on. */ remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph); + last_mouse_glyph_frame = frame; return 1; } @@ -3826,6 +3831,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) the frame are divided into. */ remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph); + last_mouse_glyph_frame = f1; *bar_window = Qnil; *part = 0; @@ -6249,6 +6255,27 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) goto done_keysym; } + /* Keysyms directly mapped to supported Unicode characters. */ + if ((keysym >= 0x01000100 && keysym <= 0x010033ff) + || (keysym >= 0x0100e000 && keysym <= 0x0100ffff)) + { + int code, charset_id, c1, c2; + + if (keysym < 0x01002500) + charset_id = charset_mule_unicode_0100_24ff, + code = (keysym & 0xFFFF) - 0x100; + else if (keysym < 0x0100e000) + charset_id = charset_mule_unicode_2500_33ff, + code = (keysym & 0xFFFF) - 0x2500; + else + charset_id = charset_mule_unicode_e000_ffff, + code = (keysym & 0xFFFF) - 0xe000; + c1 = (code / 96) + 32, c2 = (code % 96) + 32; + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = MAKE_CHAR (charset_id, c1, c2); + goto done_keysym; + } + /* Now non-ASCII. */ if (HASH_TABLE_P (Vx_keysym_table) && (NATNUMP (c = Fgethash (make_number (keysym), @@ -6651,7 +6678,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) int tool_bar_p = 0; bzero (&compose_status, sizeof (compose_status)); - bzero (&last_mouse_glyph, sizeof (last_mouse_glyph)); + last_mouse_glyph_frame = 0; if (dpyinfo->grabbed && last_mouse_frame @@ -7350,10 +7377,30 @@ x_bitmap_icon (f, file) /* Create the GNU bitmap and mask if necessary. */ if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) { - FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id - = x_create_bitmap_from_data (f, gnu_bits, - gnu_width, gnu_height); - x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + int rc = -1; + +#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) +#ifdef USE_GTK + if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + return 0; +#else + rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits); + if (rc != -1) + FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; +#endif /* USE_GTK */ +#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */ + + /* If all else fails, use the (black and white) xbm image. */ + if (rc == -1) + { + rc = x_create_bitmap_from_data (f, gnu_xbm_bits, + gnu_xbm_width, gnu_xbm_height); + if (rc == -1) + return 1; + + FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; + x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + } } /* The first time we create the GNU bitmap and mask, diff --git a/src/xterm.h b/src/xterm.h index 8f15184e09a..d3e896e27b3 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1039,6 +1039,7 @@ extern int have_menus_p P_ ((void)); #ifdef USE_GTK extern int xg_set_icon P_ ((struct frame *, Lisp_Object)); +extern int xg_set_icon_from_xpm_data P_ ((struct frame *, char**)); #endif /* USE_GTK */ extern void x_real_positions P_ ((struct frame *, int *, int *)); |