diff options
| author | Miles Bader <miles@gnu.org> | 2006-06-07 18:05:10 +0000 |
|---|---|---|
| committer | Miles Bader <miles@gnu.org> | 2006-06-07 18:05:10 +0000 |
| commit | b883cdb2fefa8ea9c3b0d82eba7a9ee792f871bb (patch) | |
| tree | de3804210a8cd955e0d3b9abc15679480930bc82 /src | |
| parent | 885b7d0991bd4b4b8f4bd1d3cd21c18a697bbce2 (diff) | |
| parent | 26c9afc3239e18b03537faaea33e3e82e28099e6 (diff) | |
Merge from emacs--devo--0
Patches applied:
* emacs--devo--0 (patch 285-296)
- Update from CVS
- Merge from gnus--rel--5.10
- Update from CVS: admin/FOR-RELEASE: Update refcard section.
* gnus--rel--5.10 (patch 102-104)
- Update from CVS
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-64
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 455 | ||||
| -rw-r--r-- | src/Makefile.in | 3 | ||||
| -rw-r--r-- | src/buffer.c | 21 | ||||
| -rw-r--r-- | src/callint.c | 2 | ||||
| -rw-r--r-- | src/coding.c | 11 | ||||
| -rw-r--r-- | src/config.in | 6 | ||||
| -rw-r--r-- | src/dispextern.h | 8 | ||||
| -rw-r--r-- | src/dispnew.c | 10 | ||||
| -rw-r--r-- | src/emacs.c | 19 | ||||
| -rw-r--r-- | src/fileio.c | 38 | ||||
| -rw-r--r-- | src/fns.c | 2 | ||||
| -rw-r--r-- | src/frame.c | 2 | ||||
| -rw-r--r-- | src/gtkutil.c | 34 | ||||
| -rw-r--r-- | src/image.c | 13 | ||||
| -rw-r--r-- | src/intervals.c | 4 | ||||
| -rw-r--r-- | src/lisp.h | 6 | ||||
| -rw-r--r-- | src/lread.c | 71 | ||||
| -rw-r--r-- | src/mac.c | 180 | ||||
| -rw-r--r-- | src/macfns.c | 46 | ||||
| -rw-r--r-- | src/macgui.h | 7 | ||||
| -rw-r--r-- | src/macselect.c | 369 | ||||
| -rw-r--r-- | src/macterm.c | 735 | ||||
| -rw-r--r-- | src/macterm.h | 53 | ||||
| -rw-r--r-- | src/minibuf.c | 46 | ||||
| -rw-r--r-- | src/process.c | 84 | ||||
| -rw-r--r-- | src/puresize.h | 2 | ||||
| -rw-r--r-- | src/search.c | 1 | ||||
| -rw-r--r-- | src/sound.c | 413 | ||||
| -rw-r--r-- | src/sysdep.c | 2 | ||||
| -rw-r--r-- | src/w32.c | 38 | ||||
| -rw-r--r-- | src/w32fns.c | 2 | ||||
| -rw-r--r-- | src/w32heap.c | 4 | ||||
| -rw-r--r-- | src/w32term.c | 222 | ||||
| -rw-r--r-- | src/window.c | 15 | ||||
| -rw-r--r-- | src/xdisp.c | 100 | ||||
| -rw-r--r-- | src/xfaces.c | 75 | ||||
| -rw-r--r-- | src/xfns.c | 4 | ||||
| -rw-r--r-- | src/xmenu.c | 117 | ||||
| -rw-r--r-- | src/xterm.c | 51 | ||||
| -rw-r--r-- | src/xterm.h | 10 |
40 files changed, 2634 insertions, 647 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 61fca56c357..d0ad63de10d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,441 @@ +2006-06-06 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c [USE_MAC_TSM] (mac_handle_text_input_event): Exclude + 0x7f from ASCII range. + +2006-06-05 Jason Rumney <jasonr@gnu.org> + + * w32term.c (w32_set_scroll_bar_thumb, x_scroll_bar_create) + (w32_set_vertical_scroll_bar, w32_scroll_bar_handle_click) + (x_scroll_bar_report_motion): Remove workarounds for + versions of Windows NT < 3.51. + [!SIF_ALL]: Remove. + (pfnSetScrollInfo, pfnGetScrollInfo): Remove. + (w32_initialize): Don't dynamically load Get/SetScrollInfo. + +2006-06-04 David Kastrup <dak@gnu.org> + + * dispnew.c: Mention `redisplay-dont-pause' in doc string of + `sit-for'. + +2006-06-03 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macfns.c (x_set_icon_name): Apply 2006-06-02 change for xfns.c. + + * macgui.h (USE_MAC_TSM): Set default to 1 on Mac OS X. + + * macterm.c (tsm_document_id) [USE_MAC_TSM]: New variable. + (Qtext_input, Qupdate_active_input_area, Qunicode_for_key_event) + [USE_MAC_TSM]: Likewise. + (syms_of_macterm) [USE_MAC_TSM]: Intern and staticpro them. + (Qbefore_string) [USE_MAC_TSM]: Add extern. + (do_app_resume, do_app_suspend) [USE_MAC_TSM]: Call + ActivateTSMDocument/DeactivateTSMDocument. + (mac_store_event_ref_as_apple_event): Call mac_post_mouse_moved_event. + (mac_handle_window_event) [USE_MAC_TSM]: Handle + kEventWindowFocusAcquired/kEventWindowFocusRelinquish. + (mac_handle_text_input_event) [USE_MAC_TSM]: New function. + (install_window_handler) [USE_MAC_TSM]: Install it. Register + kEventWindowFocusAcquired/kEventWindowFocusRelinquish. + (keycode_to_xkeysym_table): Add entry for f16. + (XTread_socket) [USE_MAC_TSM]: Set/reset read_socket_inev + before/after passing keystroke event to toolbox dispatcher. + (init_tsm) [USE_MAC_TSM]: New function. + (mac_initialize) [USE_MAC_TSM]: Call it. + (Vmac_ts_active_input_overlay) [USE_MAC_TSM]: New defvar. + + * macterm.h (EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER): New enumerator. + +2006-06-02 John Paul Wallington <jpw@gnu.org> + + * xfns.c (x_set_name_internal): Set icon to `text', derived from + name, when frame's icon_name isn't a string rather than only when + it is nil. + +2006-06-03 Eli Zaretskii <eliz@gnu.org> + + * w32fns.c (x_set_icon_name): Don't use arg if it's not a string + and not nil. + +2006-06-02 Chong Yidong <cyd@stupidchicken.com> + + * xfns.c (x_set_icon_name): No-op if arg is non-nil and not a + string. + +2006-06-02 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * xdisp.c (next_element_from_composition): Set it->object to + it->string if composition is coming from string. + (set_cursor_from_row): Don't return 0 unless row displays a + continued line. + (dump_glyph): Dump composite glyph. + +2006-06-02 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * gtkutil.c (menu_nav_ended): Check that menubar_widget is not NULL. + +2006-06-01 Richard Stallman <rms@gnu.org> + + * window.c (Fsplit_window): Doc fix. + +2006-06-01 Micha,Ak(Bl Cadilhac <michael.cadilhac@lrde.org> + + * process.c (deleted_pid_list): New variable to store the pids + of deleted processes. Declare it only if SIGCHLD is defined. + (init_process): Initialize it. + (syms_of_process): Staticpro it. + (Fdelete_process): Add pid of the deleted process to it. Check after + the addition and before the kill if the process is already stopped, + in which case it is deleted from the list and not killed. + (sigchld_handler): Define it only if SIGCHLD is. Search the process + that signaled Emacs in `deleted_pid_list' before `Vprocess_alist'. + Original idea by Stefan Monnier. + +2006-06-01 Kim F. Storm <storm@cua.dk> + + * dispnew.c (sit_for): Perform redisplay even if input is pending + when redisplay-dont-pause is non-nil. + +2006-06-01 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c (mac_handle_visibility_change): Set buf.arg to Qnil. + (XTread_socket): Remove obsolete comment. + +2006-06-01 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xmenu.c (syms_of_xmenu): Make accelerate-menu an alias for + menu-bar-open. + +2006-06-01 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xmenu.c (Fmenu_bar_open, syms_of_xmenu): Change menu-bar-start to + menu-bar-open. + + * gtkutil.c (menu_nav_ended): Change x-menu-bar-start to menu-bar-open. + +2006-05-31 Juri Linkov <juri@jurta.org> + + * minibuf.c (Vhistory_add_new_input): New variable. + (read_minibuf): Use it. + (syms_of_minibuf) <history-add-new-input>: New Lisp variable. + (syms_of_minibuf) <history-delete-duplicates>: Doc fix. + +2006-05-31 Kim F. Storm <storm@cua.dk> + + * process.c (select_wrapper): Add wrapper around select to work around + "incomplete backtrace" bug in gdb 5.3, when emacs is stopped inside + select called from wait_reading_process_output. + +2006-05-30 Andreas Schwab <schwab@suse.de> + + * xmenu.c (Fmenu_bar_start): Return a value. + +2006-05-30 Richard Stallman <rms@gnu.org> + + * coding.c (Ffind_operation_coding_system): Doc fix. + +2006-05-30 Eli Zaretskii <eliz@gnu.org> + + * w32term.c (x_draw_hollow_cursor): Fix last change. + +2006-05-29 Kim F. Storm <storm@cua.dk> + + * w32term.c (x_draw_stretch_glyph_string): Fix last change. + +2006-05-29 Eli Zaretskii <eliz@gnu.org> + + * coding.c (Ffind_operation_coding_system): Doc fix. + +2006-05-29 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macfns.c [USE_MAC_FONT_PANEL] (Fmac_set_font_panel_visibility): + Call mac_set_font_info_for_selection if font panel is made visible. + + * macterm.c (font_panel_shown_p) [USE_MAC_FONT_PANEL]: New variable. + (mac_font_panel_visible_p, mac_show_hide_font_panel) + [USE_MAC_FONT_PANEL]: New functions. + [USE_MAC_FONT_PANEL] (mac_set_font_info_for_selection): Return + immediately if font panel is not visible. + + * macterm.h (mac_font_panel_visible_p, mac_show_hide_font_panel): + Add externs. + +2006-05-29 Dan Nicolaescu <dann@ics.uci.edu> + + * search.c (matcher_overflow): Mark as NO_RETURN. + + * xterm.c (x_connection_closed): Likewise. + + * sysdep.c (croak): Likewise. + + * sound.c (sound_perror, alsa_sound_perror): Likewise. + + * lisp.h (die, nsberror): Likewise. + +2006-05-29 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * sound.c (alsa_open, alsa_configure, alsa_write): Move + assignment to err out of if-statement. + + * gtkutil.c (menu_nav_ended): New function. + (create_menus): Connect menu_nav_ended to "selection-done" to fix + grabs. + + * xmenu.c (Fmenu_bar_start): New function for USE_GTK and USE_X_TOOLKIT. + +2006-05-28 Dan Nicolaescu <dann@ics.uci.edu> + + * charset.h (invalid_character): Mark as NO_RETURN. + +2006-05-29 Kenichi Handa <handa@m17n.org> + + * coding.c (Ffind_operation_coding_system): Call a function by + safe_call1 instead of call1. + +2006-05-28 Stefan Monnier <monnier@iro.umontreal.ca> + + * window.c (struct saved_window): Add `dedicated'. + (Fset_window_configuration, save_window_save): Save/restore the + `dedicated' flag. + +2006-05-28 Kim F. Storm <storm@cua.dk> + + * xdisp.c (set_cursor_from_row): If cursor cannot be set in row, + don't update w->cursor and return 0. Return 1 on success. + (try_cursor_movement): Repeat set_cursor_from_row on successive rows + until it succeeds. + + * dispextern.h (set_cursor_from_row): Update prototype. + +2006-05-28 Kim F. Storm <storm@cua.dk> + + * xdisp.c (get_phys_cursor_geometry): Return computed x and y through + parameters. Adjust x and width in case cursor in on a partially + visible stretch glyph on the left edge. + (erase_phys_cursor): Don't erase into left fringe/margin in case + previous cursor glyph is a partially visible stretch glyph on left. + + * dispextern.h (get_phys_cursor_geometry): Update prototype. + + * xterm.c (x_draw_stretch_glyph_string): Fix problems with invisible + cursor and erasing cursor on partially visible stretch glyph on left. + (x_draw_hollow_cursor): Compute x via get_phys_cursor_geometry. + + * macterm.c: Likewise. + + * w32term.c: Likewise. + +2006-05-27 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macselect.c (mac_handle_apple_event): + Return errAEEventNotHandled if key binding is not found. + +2006-05-26 Eli Zaretskii <eliz@gnu.org> + + * emacs.c (main) [PROFILING]: Enable also for __MINGW32__. + [__MINGW32__]: MinGW-specific declaration of `etext'. + + * w32heap.c (etext, edata): Remove unused definitions. + +2006-05-26 Chong Yidong <cyd@stupidchicken.com> + + * fileio.c (Fcopy_file): Delete argument MUSTBENEW. + Incorporate the exclusive file-opening functionality into the behavior + when OK-IF-ALREADY-EXISTS is nil. + (Frename_file): Call Fcopy_file without MUSTBENEW argument. + +2006-05-26 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * sound.c (alsa_configure): Move get period/buffer_size after + setting hwparams. + +2006-05-26 Kenichi Handa <handa@m17n.org> + + * coding.c (Ffind_operation_coding_system): Allow (FILENAME + . BUFFER) in TARGET. + +2006-05-25 Chong Yidong <cyd@stupidchicken.com> + + * image.c (png_load): Don't call fclose on NULL. + +2006-05-25 Luc Teirlinck <teirllm@auburn.edu> + + * fns.c (Fyes_or_no_p): + * callint.c (Fcall_interactively): Fread_from_minibuffer now takes + only seven args. + +2006-05-25 Juri Linkov <juri@jurta.org> + + * lisp.h (Fread_from_minibuffer): Decrement number of args. + + * minibuf.c (read_minibuf): Remove arg KEEP_ALL. Callers changed. + (Fread_from_minibuffer): Remove arg KEEP_ALL. Callers changed. + + * buffer.c (mode-line-format): Fix docstring. + +2006-05-25 Richard Stallman <rms@gnu.org> + + * emacs.c (main, Fdump_emacs): Don't test __linux or __linux__. + +2006-05-24 Luc Teirlinck <teirllm@auburn.edu> + + * puresize.h (BASE_PURESIZE): Increase to 1210000. + +2006-05-24 Alan Mackenzie <acm@muc.de> + + * lread.c (Vload_history): Enhance doc-string to say that the file + is the absolute truename of the loaded file. + + * lread.c (Vafter_load_alist): doc-string: state that an element + now has a regexp to match file names, not a file name as such. + + * lread.c (readevalloop): Call file-truename on the name for + load-history, except at preloading time. + + * lread.c (Fload): At preloading time, preserve the extension of + the filename which goes into load-history. New var hist_file_name. + + * lread.c (Fload): Do eval-after-load stuff by calling the lisp + function do-after-load-evaluation. + +2006-05-24 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * mac.c (ae_attr_table): New variable. + (syms_of_mac): Intern and staticpro its elements. + (mac_aelist_to_lisp): Also convert Apple event attributes. + (mac_ae_put_lisp): New function. + (create_apple_event_from_event_ref) [MAC_OSX]: Use typeUTF8Text. + + * macfns.c (Fx_server_version): Use gestaltSystemVersionMajor etc. + + * macselect.c (Qemacs_suspension_id): New variable. + (syms_of_macselect): Intern and staticpro it. + (struct suspended_ae_info): New struct. + (deferred_apple_events, defer_apple_events) + (Fmac_process_deferred_apple_events): Use it. + (suspended_apple_events): New variable. + (mac_handle_apple_event_1): New function. + (mac_handle_apple_event): Use it. Don't process previously + suspended events. + (cleanup_suspended_apple_events, get_suspension_id) + (cleanup_all_suspended_apple_events): New functions. + (init_apple_event_handler): Call cleanup_all_suspended_apple_events + at exit. + (Fmac_cleanup_expired_apple_events, Fmac_ae_set_reply_parameter) + (Fmac_resume_apple_event): New defuns. + (syms_of_macselect): Defsubr them. + + * macterm.c (fn_keycode_to_keycode_table, XTread_socket) [MAC_OSX]: + Fix last change. Don't map `fn' modifier if pressed with F1 ... F12. + + * macterm.h (TYPE_FILE_NAME): Change from macro to enumerator. + (KEY_EMACS_SUSPENSION_ID_ATTR): New enumerator. + (keyReplyRequestedAttr) [MAC_OS_X_VERSION_MAX_ALLOWED < 1030]: Likewise. + (gestaltSystemVersionMajor, gestaltSystemVersionMinor) + (gestaltSystemVersionBugFix) [MAC_OS_X_VERSION_MAX_ALLOWED < 1040]: + Likewise. + (typeUTF8Text, kEventParamWindowMouseLocation) + [MAC_OSX && MAC_OS_X_VERSION_MAX_ALLOWED < 1020]: Likewise. + (x_get_focus_frame, mac_ae_put_lisp): Add externs. + +2006-05-23 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c (fn_keycode_to_xkeysym_table, convert_fn_keycode): Remove. + (fn_keycode_to_keycode_table) [MAC_OSX]: New variable. + (mac_set_unicode_keystroke_event) [TARGET_API_MAC_CARBON]: New function. + (XTread_socket) [TARGET_API_MAC_CARBON]: Use it. + (XTread_socket) [MAC_OSX]: Try 'uchr' Unicode keyboard-layout + resource to backtranslate key with modifiers. + (XTread_socket): Don't set read_socket_inev around AEProcessAppleEvent. + +2006-05-23 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * xterm.c: Remove declarations already in xterm.h + + * xterm.h: Add extern declarations for x_clear_errors, + x_fully_uncatch_errors, x_catching_errors and + x_alloc_lighter_color_for_widget. Remove duplicated declarations. + +2006-05-21 Richard Stallman <rms@gnu.org> + + * xfaces.c (best_matching_font): Abort for best == NULL + before we start to use it. + + * buffer.c (syms_of_buffer, Fmake_overlay): Doc fixes. + +2006-05-20 Kim F. Storm <storm@cua.dk> + + * xfaces.c (best_matching_font): Fix crash in 2006-05-17 change. + +2006-05-20 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * macterm.c (convert_fn_keycode): Fix last change. + +2006-05-19 Eli Zaretskii <eliz@gnu.org> + + * w32.c (init_environment): Perform the processing of environment + variables on a copy of default variables and their values, not on + the original. Simplify code that calls ExpandEnvironmentStrings + and make buf1[] and buf2[] more visible for easier debugging. + +2006-05-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> + + * frame.c (x_set_border_width): Remove #ifndef MAC_OS. + + * image.c [MAC_OS] (gif_load): Allocate Lisp string first. + + * macfns.c (Fx_focus_frame): Don't check dpyinfo->x_focus_frame. + + * macterm.c (XTread_socket) [TARGET_API_MAC_CARBON && MAC_OSX]: + Forward keyUp events to toolbox_dispatcher. + + * window.c (foreach_window): Check WINDOWP (FRAME_ROOT_WINDOW (f)). + +2006-05-18 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> + + * config.in: Regenerated (HAVE_ALSA). + + * sound.c (alsa_sound_perror, alsa_open, alsa_period_size) + (alsa_configure, alsa_close, alsa_choose_format, alsa_write) + (snd_error_quiet, alsa_init): New functions. + (vox_init): Return 0 if unable to open device. + (Fplay_sound_internal): Test for alsa first and use vox (oss) as + a fallback. + (struct sound_device): Add period_size. + (wav_play, au_play): Use period_size if set. + + * Makefile.in (CFLAGS_SOUND): New flags for ALSA + (ALL_CFLAGS): Add CFLAGS_SOUND + +2006-05-18 Kenichi Handa <handa@m17n.org> + + * callproc.c (Fcall_process): Reject encoding arguments by + ascii-incompatible coding systems (e.g. utf-16). + + * coding.c (Qascii_incompatible): New variable. + (syms_of_coding): Setup Qascii_incompatible. + (setup_coding_system): Be sure to initialize coding->common_flags. + Check `ascii-incompatible' property of the coding system. + + * coding.h (CODING_ASCII_INCOMPATIBLE_MASK): New macro. + +2006-05-18 Kim F. Storm <storm@cua.dk> + + * xdisp.c (display_tool_bar_line): Restore entire tool-bar geometry when + backtracking in case last image doesn't fit on line. + +2006-05-18 MIYOSHI Masanori <miyoshi@meadowy.org> (tiny change) + + * xdisp.c (display_tool_bar_line): Don't adjust tool-bar height by more than + height of one frame default line. + +2006-05-17 Richard Stallman <rms@gnu.org> + + * xfaces.c (better_font_p): Any font beats no font. + (best_matching_font): Simplify based on above change. + + * buffer.c (Fprevious_overlay_change, Fnext_overlay_change): Doc fixes. + 2006-05-16 Kim F. Storm <storm@cua.dk> * xterm.c (handle_one_xevent): Check that f is not NULL before @@ -62,7 +500,7 @@ [MAC_OS] (gif_load): Emulate Graphic Control Extension block. * macfns.c (x_to_mac_color): Fix shift amount change. - [USE_MAC_FONT_PANEL] (mac_set_font): Use x_get_focus_frame. + (mac_set_font) [USE_MAC_FONT_PANEL]: Use x_get_focus_frame. [USE_MAC_FONT_PANEL] (Fmac_set_font_panel_visibility): Doc fix. * macselect.c (Vmac_service_selection) [MAC_OSX]: Rename from @@ -490,7 +928,7 @@ * puresize.h (BASE_PURESIZE): Increment to 1210000. -2006-04-13 Micha,Ak(Bl Cadilhac <michael.cadilhac@lrde.org> (tiny change) +2006-04-13 Micha,Ak(Bl Cadilhac <michael.cadilhac@lrde.org> * print.c (Fprin1_to_string): Mention in the `doc' that the behavior is modified by `print-level' and `print-length'. @@ -611,7 +1049,7 @@ * xfaces.c (Finternal_merge_in_global_face, try_font_list): Add explicit braces to avoid ambiguous `else'. -2006-04-11 Micha,Ak(Bl Cadilhac <michael.cadilhac@lrde.org> (tiny change) +2006-04-11 Micha,Ak(Bl Cadilhac <michael.cadilhac@lrde.org> * dispnew.c (init_display): Don't init X display if the user asked for a non-X display. @@ -8477,7 +8915,7 @@ * xfns.c (xic_create_xfontset): Initialize missing_list to NULL. -2004-10-21 K,Ba(Broly L,Bu(Brentey <lorentey@elte.hu> +2004-10-21 K,Aa(Broly L$,1 q(Brentey <lorentey@elte.hu> * xterm.h (x_output): New member `xic_base_fontname'. (FRAME_XIC_BASE_FONTNAME): New macro. @@ -9421,7 +9859,7 @@ * fileio.c (Fvisited_file_modtime): Return a list of two integers, instead of a cons. -2004-07-14 K,Ba(Broly L,Bu(Brentey <lorentey@elte.hu> +2004-07-14 K,Aa(Broly L$,1 q(Brentey <lorentey@elte.hu> * keyboard.c (echo_dash): Do nothing if there already is a dash at the end of the echo string. @@ -9758,7 +10196,7 @@ * keyboard.c (cmd_error): Don't call any_kboard_state if inside a recursive edit level. -2004-06-13 K,Ba(Broly L,Bu(Brentey <lorentey@elte.hu> +2004-06-13 K,Aa(Broly L$,1 q(Brentey <lorentey@elte.hu> * keyboard.c (command_loop): Call any_kboard_state before command_loop_2 when at top level. @@ -10071,7 +10509,7 @@ before actually accepting connection in case it has already been accepted due to recursion. -2004-05-23 K,Ba(Broly L,Bu(Brentey <lorentey@elte.hu> +2004-05-23 K,Aa(Broly L$,1 q(Brentey <lorentey@elte.hu> * coding.c (Fset_safe_terminal_coding_system_internal): Set suppress_error in safe_terminal_coding, not terminal_coding. @@ -17007,8 +17445,7 @@ (Fapropos_internal): Initialize them and clear them out. Don't GCPRO them. - * buffer.c (syms_of_buffer) <scroll-up-aggressively, scroll-down-aggressively>: - Doc fixes. + * buffer.c (syms_of_buffer) <scroll-up|down-aggressively>: Doc fixes. * lisp.h: New misc type Lisp_Save_Value. (enum Lisp_Misc_Type): Add Lisp_Misc_Save_Value. diff --git a/src/Makefile.in b/src/Makefile.in index 049a4c5bc17..342540df7be 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -281,7 +281,7 @@ TOOLKIT_DEFINES = /* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM since it may have -I options that should override those two. */ -ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ +ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ .c.o: $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< @@ -459,6 +459,7 @@ LIBX= $(LIBXMENU) LD_SWITCH_X_SITE -lX10 LIBX10_MACHINE LIBX10_SYSTEM #endif /* not HAVE_X_WINDOWS */ LIBSOUND= @LIBSOUND@ +CFLAGS_SOUND= @CFLAGS_SOUND@ #ifndef ORDINARY_LINK /* Fix linking if compiled with GCC. */ diff --git a/src/buffer.c b/src/buffer.c index e4d846c8093..5bdfe737767 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2481,10 +2481,10 @@ swap_out_buffer_local_variables (b) Return the number found, and store them in a vector in *VEC_PTR. Store in *LEN_PTR the size allocated for the vector. Store in *NEXT_PTR the next position after POS where an overlay starts, - or ZV if there are no more overlays. + or ZV if there are no more overlays between POS and ZV. Store in *PREV_PTR the previous position before POS where an overlay ends, or where an overlay starts which ends at or after POS; - or BEGV if there are no such overlays. + or BEGV if there are no such overlays from BEGV to POS. NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info. *VEC_PTR and *LEN_PTR should contain a valid vector and size @@ -3570,10 +3570,10 @@ If omitted, BUFFER defaults to the current buffer. BEG and END may be integers or markers. The fourth arg FRONT-ADVANCE, if non-nil, makes the marker for the front of the overlay advance when text is inserted there -(which means the text *is not* included in the overlay). +\(which means the text *is not* included in the overlay). The fifth arg REAR-ADVANCE, if non-nil, makes the marker for the rear of the overlay advance when text is inserted there -(which means the text *is* included in the overlay). */) +\(which means the text *is* included in the overlay). */) (beg, end, buffer, front_advance, rear_advance) Lisp_Object beg, end, buffer; Lisp_Object front_advance, rear_advance; @@ -3955,7 +3955,8 @@ or between BEG and END. */) DEFUN ("next-overlay-change", Fnext_overlay_change, Snext_overlay_change, 1, 1, 0, doc: /* Return the next position after POS where an overlay starts or ends. -If there are no more overlay boundaries after POS, return (point-max). */) +If there are no overlay boundaries from POS to (point-max), +the value is (point-max). */) (pos) Lisp_Object pos; { @@ -3996,7 +3997,8 @@ If there are no more overlay boundaries after POS, return (point-max). */) DEFUN ("previous-overlay-change", Fprevious_overlay_change, Sprevious_overlay_change, 1, 1, 0, doc: /* Return the previous position before POS where an overlay starts or ends. -If there are no more overlay boundaries before POS, return (point-min). */) +If there are no overlay boundaries from (point-min) to POS, +the value is (point-min). */) (pos) Lisp_Object pos; { @@ -5454,10 +5456,11 @@ A string is printed verbatim in the mode line except for %-constructs: %p -- print percent of buffer above top of window, or Top, Bot or All. %P -- print percent of buffer above bottom of window, perhaps plus Top, or print Bottom or All. - %m -- print the mode name. %n -- print Narrow if appropriate. + %t -- visited file is text or binary (if OS supports this distinction). %z -- print mnemonics of buffer, terminal, and keyboard coding systems. %Z -- like %z, but including the end-of-line format. + %e -- print error message about full memory. %[ -- print one [ for each recursive editing level. %] similar. %% -- print %. %- -- print infinitely many dashes. Decimal digits after the % specify field width to which to pad. */); @@ -5753,7 +5756,7 @@ the actual bitmap shown in the left or right fringe for the logical indicator. LEFT and RIGHT are the bitmaps shown in the left and/or right fringe for the specific indicator. The LEFT1 or RIGHT1 bitmaps are used only for the `bottom' and `one-line' indicators when the last -(only) line in has no final newline. BITMAPS may also be a single +\(only) line in has no final newline. BITMAPS may also be a single symbol which is used in both left and right fringes. */); DEFVAR_PER_BUFFER ("fringe-cursor-alist", @@ -6000,7 +6003,7 @@ this variable has no effect; the cursor appears as a hollow box. */); doc: /* Additional space to put between lines when displaying a buffer. The space is measured in pixels, and put below lines on window systems. If value is a floating point number, it specifies the spacing relative -to the default frame line height. */); +to the default frame line height. nil means add no extra space. */); DEFVAR_PER_BUFFER ("cursor-in-non-selected-windows", ¤t_buffer->cursor_in_non_selected_windows, Qnil, diff --git a/src/callint.c b/src/callint.c index 4789fb5582d..ae10e64e1de 100644 --- a/src/callint.c +++ b/src/callint.c @@ -730,7 +730,7 @@ If KEYS is omitted or nil, the return value of `this-command-keys' is used. */) tem = Fread_from_minibuffer (build_string (callint_message), Qnil, Qnil, Qnil, Qnil, Qnil, - Qnil, Qnil); + Qnil); if (! STRINGP (tem) || SCHARS (tem) == 0) args[i] = Qnil; else diff --git a/src/coding.c b/src/coding.c index debb2f27ffc..9f95c2c6777 100644 --- a/src/coding.c +++ b/src/coding.c @@ -8315,7 +8315,7 @@ is selected as the TARGET. For example, if OPERATION does file I/O, whichever argument specifies the file name is TARGET. TARGET has a meaning which depends on OPERATION: - For file I/O, TARGET is a file name. + For file I/O, TARGET is a file name (except for the special case below). For process I/O, TARGET is a process name. For network I/O, TARGET is a service name or a port number @@ -8327,6 +8327,13 @@ or a function symbol to call. In the last case, we call the function with one argument, which is a list of all the arguments given to this function. +If OPERATION is `insert-file-contents', the argument corresponding to +TARGET may be a cons (FILENAME . BUFFER). In that case, FILENAME is a +file name to look up, and BUFFER is a buffer that contains the file's +contents (not yet decoded). If `file-coding-system-alist' specifies a +function to call for FILENAME, that function should examine the +contents of BUFFER instead of reading the file. + usage: (find-operation-coding-system OPERATION ARGUMENTS ...) */) (nargs, args) int nargs; @@ -8380,7 +8387,7 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS ...) */) return Fcons (val, val); if (! NILP (Ffboundp (val))) { - val = call1 (val, Flist (nargs, args)); + val = safe_call1 (val, Flist (nargs, args)); if (CONSP (val)) return val; if (SYMBOLP (val) && ! NILP (Fcoding_system_p (val))) diff --git a/src/config.in b/src/config.in index 9c1abadd283..106aeea920c 100644 --- a/src/config.in +++ b/src/config.in @@ -87,6 +87,9 @@ Boston, MA 02110-1301, USA. */ */ #undef HAVE_ALLOCA_H +/* Define to 1 if ALSA is available. */ +#undef HAVE_ALSA + /* Define to 1 if you have the `bcmp' function. */ #undef HAVE_BCMP @@ -955,6 +958,9 @@ Boston, MA 02110-1301, USA. */ #ifdef HAVE_SOUNDCARD_H #define HAVE_SOUND 1 #endif +#ifdef HAVE_ALSA +#define HAVE_SOUND 1 +#endif #endif /* __FreeBSD__ || __NetBSD__ || __linux__ */ /* If using GNU, then support inline function declarations. */ diff --git a/src/dispextern.h b/src/dispextern.h index 0aac78f9557..92005e6b149 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2642,8 +2642,8 @@ void remember_mouse_glyph P_ ((struct frame *, int, int, NativeRectangle *)); void mark_window_display_accurate P_ ((Lisp_Object, int)); void redisplay_preserve_echo_area P_ ((int)); -void set_cursor_from_row P_ ((struct window *, struct glyph_row *, - struct glyph_matrix *, int, int, int, int)); +int set_cursor_from_row P_ ((struct window *, struct glyph_row *, + struct glyph_matrix *, int, int, int, int)); void init_iterator P_ ((struct it *, struct window *, int, int, struct glyph_row *, enum face_id)); void init_iterator_to_row_start P_ ((struct it *, struct window *, @@ -2703,8 +2703,8 @@ extern void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *, extern void draw_phys_cursor_glyph P_ ((struct window *, struct glyph_row *, enum draw_glyphs_face)); -extern int get_phys_cursor_geometry P_ ((struct window *, struct glyph_row *, - struct glyph *, int *)); +extern void get_phys_cursor_geometry P_ ((struct window *, struct glyph_row *, + struct glyph *, int *, int *, int *)); extern void erase_phys_cursor P_ ((struct window *)); extern void display_and_set_cursor P_ ((struct window *, int, int, int, int, int)); diff --git a/src/dispnew.c b/src/dispnew.c index e8833376701..f239d6969f4 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -355,8 +355,7 @@ static unsigned history_tick; static void add_frame_display_history P_ ((struct frame *, int)); static void add_window_display_history P_ ((struct window *, char *, int)); - - + /* Add to the redisplay history how window W has been displayed. MSG is a trace containing the information how W's glyph matrix has been constructed. PAUSED_P non-zero means that the update @@ -6391,7 +6390,9 @@ sit_for (sec, usec, reading, display, initial_display) { swallow_events (display); - if (detect_input_pending_run_timers (display) || !NILP (Vexecuting_kbd_macro)) + if ((detect_input_pending_run_timers (display) + && !redisplay_dont_pause) + || !NILP (Vexecuting_kbd_macro)) return Qnil; if (initial_display) @@ -6421,6 +6422,9 @@ Redisplay is preempted as always if input arrives, and does not happen if input is available before it starts. Value is t if waited the full time with no input arriving. +Redisplay will occur even when input is available if you bind +`redisplay-dont-pause' to a non-nil value. + An obsolete but still supported form is \(sit-for SECONDS &optional MILLISECONDS NODISP) Where the optional arg MILLISECONDS specifies an additional wait period, diff --git a/src/emacs.c b/src/emacs.c index 27e349c637f..4bbbf84ebab 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1770,16 +1770,21 @@ main (argc, argv #endif } - /* Set up for profiling. This is known to work on FreeBSD and - GNU/Linux. It might work on some other systems too. Give it a - try and tell us if it works on your system. To compile for - profiling use something like `make CFLAGS="-pg -g -O -DPROFILING=1'. */ -#if defined (__FreeBSD__) || defined (__linux) + /* Set up for profiling. This is known to work on FreeBSD, + GNU/Linux and MinGW. It might work on some other systems too. + Give it a try and tell us if it works on your system. To compile + for profiling use something like: + `make CFLAGS="-pg -g -O -DPROFILING=1'. */ +#if defined (__FreeBSD__) || defined (GNU_LINUX) || defined(__MINGW32__) #ifdef PROFILING if (initialized) { extern void _mcleanup (); +#ifdef __MINGW32__ + extern unsigned char etext asm ("etext"); +#else extern char etext; +#endif extern void safe_bcopy (); extern void dump_opcode_frequencies (); @@ -2253,7 +2258,7 @@ You must run Emacs in batch mode in order to dump it. */) if (! noninteractive) error ("Dumping Emacs works only in batch mode"); -#ifdef __linux__ +#ifdef GNU_LINUX if (heap_bss_diff > MAX_HEAP_BSS_DIFF) { fprintf (stderr, "**************************************************\n"); @@ -2265,7 +2270,7 @@ You must run Emacs in batch mode in order to dump it. */) fprintf (stderr, "exec-shield in etc/PROBLEMS for more information.\n"); fprintf (stderr, "**************************************************\n"); } -#endif /* __linux__ */ +#endif /* GNU_LINUX */ /* Bind `command-line-processed' to nil before dumping, so that the dumped Emacs will process its command line diff --git a/src/fileio.c b/src/fileio.c index 84b32f8dda9..8ce89ba23f3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2409,32 +2409,31 @@ barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick) return; } -DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, +DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 5, "fCopy file: \nGCopy %s to file: \np\nP", doc: /* Copy FILE to NEWNAME. Both args must be strings. If NEWNAME names a directory, copy FILE there. -Signals a `file-already-exists' error if file NEWNAME already exists, -unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil. -A number as third arg means request confirmation if NEWNAME already exists. -This is what happens in interactive use with M-x. -Always sets the file modes of the output file to match the input file. + +This function always sets the file modes of the output file to match +the input file. + +The optional third argument OK-IF-ALREADY-EXISTS specifies what to do +if file NEWNAME already exists. If OK-IF-ALREADY-EXISTS is nil, we +signal a `file-already-exists' error without overwriting. If +OK-IF-ALREADY-EXISTS is a number, we request confirmation from the user +about overwriting; this is what happens in interactive use with M-x. +Any other value for OK-IF-ALREADY-EXISTS means to overwrite the +existing file. Fourth arg KEEP-TIME non-nil means give the output file the same last-modified time as the old one. (This works on only some systems.) A prefix arg makes KEEP-TIME non-nil. -The optional fifth arg MUSTBENEW, if non-nil, insists on a check -for an existing file with the same name. If MUSTBENEW is `excl', -that means to get an error if the file already exists; never overwrite. -If MUSTBENEW is neither nil nor `excl', that means ask for -confirmation before overwriting, but do go ahead and overwrite the file -if the user confirms. - If PRESERVE-UID-GID is non-nil, we try to transfer the uid and gid of FILE to NEWNAME. */) - (file, newname, ok_if_already_exists, keep_time, mustbenew, preserve_uid_gid) - Lisp_Object file, newname, ok_if_already_exists, keep_time, mustbenew; + (file, newname, ok_if_already_exists, keep_time, preserve_uid_gid) + Lisp_Object file, newname, ok_if_already_exists, keep_time; Lisp_Object preserve_uid_gid; { int ifd, ofd, n; @@ -2451,9 +2450,6 @@ uid and gid of FILE to NEWNAME. */) CHECK_STRING (file); CHECK_STRING (newname); - if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl)) - barf_or_query_if_file_exists (newname, "overwrite", 1, 0, 1); - if (!NILP (Ffile_directory_p (newname))) newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname); else @@ -2556,12 +2552,12 @@ uid and gid of FILE to NEWNAME. */) /* System's default file type was set to binary by _fmode in emacs.c. */ ofd = emacs_open (SDATA (encoded_newname), O_WRONLY | O_TRUNC | O_CREAT - | (EQ (mustbenew, Qexcl) ? O_EXCL : 0), + | (NILP (ok_if_already_exists) ? O_EXCL : 0), S_IREAD | S_IWRITE); #else /* not MSDOS */ ofd = emacs_open (SDATA (encoded_newname), O_WRONLY | O_TRUNC | O_CREAT - | (EQ (mustbenew, Qexcl) ? O_EXCL : 0), + | (NILP (ok_if_already_exists) ? O_EXCL : 0), 0666); #endif /* not MSDOS */ #endif /* VMS */ @@ -2806,7 +2802,7 @@ This is what happens in interactive use with M-x. */) /* We have already prompted if it was an integer, so don't have copy-file prompt again. */ NILP (ok_if_already_exists) ? Qnil : Qt, - Qt, Qnil, Qt); + Qt, Qt); Fdelete_file (file); } diff --git a/src/fns.c b/src/fns.c index 545b4d7b0ea..3b4b3e5149b 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2798,7 +2798,7 @@ is nil, and `use-dialog-box' is non-nil. */) { ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil, Qyes_or_no_p_history, Qnil, - Qnil, Qnil)); + Qnil)); if (SCHARS (ans) == 3 && !strcmp (SDATA (ans), "yes")) { UNGCPRO; diff --git a/src/frame.c b/src/frame.c index 1606f195f90..cafa9b655d4 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3156,10 +3156,8 @@ x_set_border_width (f, arg, oldval) if (XINT (arg) == f->border_width) return; -#ifndef MAC_OS if (FRAME_X_WINDOW (f) != 0) error ("Cannot change the border width of a frame"); -#endif /* MAC_TODO */ f->border_width = XINT (arg); } diff --git a/src/gtkutil.c b/src/gtkutil.c index b8d37df2214..2a6ed9d1524 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1970,6 +1970,34 @@ xg_create_one_menuitem (item, f, select_cb, highlight_cb, cl_data, group) return w; } +/* Callback called when keyboard traversal (started by menu-bar-open) ends. + WMENU is the menu for which traversal has been done. DATA points to the + frame for WMENU. We must release grabs, some bad interaction between GTK + and Emacs makes the menus keep the grabs. */ + +static void +menu_nav_ended (wmenu, data) + GtkMenuShell *wmenu; + gpointer data; +{ + FRAME_PTR f = (FRAME_PTR) data; + + if (FRAME_X_OUTPUT (f)->menubar_widget) + { + GtkMenuShell *w = GTK_MENU_SHELL (FRAME_X_OUTPUT (f)->menubar_widget); + Display *dpy = FRAME_X_DISPLAY (f); + + BLOCK_INPUT; + gtk_menu_shell_deactivate (w); + gtk_menu_shell_deselect (w); + + XUngrabKeyboard (dpy, CurrentTime); + XUngrabPointer (dpy, CurrentTime); + UNBLOCK_INPUT; + } +} + + static GtkWidget *create_menus P_ ((widget_value *, FRAME_PTR, GCallback, GCallback, GCallback, int, int, int, GtkWidget *, xg_menu_cb_data *, char *)); @@ -2024,6 +2052,12 @@ create_menus (data, f, select_cb, deactivate_cb, highlight_cb, } else wmenu = gtk_menu_bar_new (); + /* Fix up grabs after keyboard traversal ends. */ + g_signal_connect (G_OBJECT (wmenu), + "selection-done", + G_CALLBACK (menu_nav_ended), + f); + /* Put cl_data on the top menu for easier access. */ cl_data = make_cl_data (cl_data, f, highlight_cb); g_object_set_data (G_OBJECT (wmenu), XG_FRAME_DATA, (gpointer)cl_data); diff --git a/src/image.c b/src/image.c index f309a401139..70ffabc1937 100644 --- a/src/image.c +++ b/src/image.c @@ -6104,7 +6104,6 @@ png_load (f, img) { image_error ("Cannot open image file `%s'", file, Qnil); UNGCPRO; - fclose (fp); return 0; } @@ -8067,18 +8066,18 @@ gif_load (f, img) /* Save GIF image extension data for `image-extension-data'. Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */ { - unsigned char gce[4]; + Lisp_Object gce = make_uninit_string (4); int centisec = ((float)duration / time_scale) * 100.0f + 0.5f; /* Fill the delay time field. */ - gce[1] = centisec & 0xff; - gce[2] = (centisec >> 8) & 0xff; + SSET (gce, 1, centisec & 0xff); + SSET (gce, 2, (centisec >> 8) & 0xff); /* We don't know about other fields. */ - gce[0] = gce[3] = 0; + SSET (gce, 0, 0); + SSET (gce, 3, 0); img->data.lisp_val = list4 (Qcount, make_number (nsamples), - make_number (0xf9), - make_unibyte_string (gce, 4)); + make_number (0xf9), gce); } /* Maybe fill in the background field while we have ximg handy. */ diff --git a/src/intervals.c b/src/intervals.c index 21e60c96d3f..fecd1d181dc 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -2016,6 +2016,10 @@ set_point_both (buffer, charpos, bytepos) register INTERVAL to, from, toprev, fromprev; int buffer_point; int old_position = BUF_PT (buffer); + /* This ensures that we move forward past intangible text when the + initial position is the same as the destination, in the rare + instances where this is important, e.g. in line-move-finish + (simple.el). */ int backwards = (charpos < old_position ? 1 : 0); int have_overlays; int original_position; diff --git a/src/lisp.h b/src/lisp.h index bf2426e25a7..af7fae52eaf 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -80,7 +80,7 @@ Boston, MA 02110-1301, USA. */ /* Extra internal type checking? */ extern int suppress_checking; -extern void die P_((const char *, const char *, int)); +extern void die P_((const char *, const char *, int)) NO_RETURN; #ifdef ENABLE_CHECKING @@ -2816,7 +2816,7 @@ extern void set_time_zone_rule P_ ((char *)); /* defined in buffer.c */ extern int mouse_face_overlay_overlaps P_ ((Lisp_Object)); -extern void nsberror P_ ((Lisp_Object)); +extern void nsberror P_ ((Lisp_Object)) NO_RETURN; extern char *no_switch_window P_ ((Lisp_Object window)); EXFUN (Fset_buffer_multibyte, 1); EXFUN (Foverlay_start, 1); @@ -2936,7 +2936,7 @@ extern void syms_of_search P_ ((void)); extern Lisp_Object last_minibuf_string; extern void choose_minibuf_frame P_ ((void)); EXFUN (Fcompleting_read, 8); -EXFUN (Fread_from_minibuffer, 8); +EXFUN (Fread_from_minibuffer, 7); EXFUN (Fread_variable, 2); EXFUN (Fread_buffer, 3); EXFUN (Fread_minibuffer, 2); diff --git a/src/lread.c b/src/lread.c index b6161ebedaa..d8abde1c458 100644 --- a/src/lread.c +++ b/src/lread.c @@ -89,6 +89,7 @@ Lisp_Object Qascii_character, Qload, Qload_file_name; Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction; Lisp_Object Qinhibit_file_name_operation; Lisp_Object Qeval_buffer_list, Veval_buffer_list; +Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */ /* Used instead of Qget_file_char while loading *.elc files compiled by Emacs 21 or older. */ @@ -897,8 +898,8 @@ Return t if the file exists and loads successfully. */) register int fd = -1; int count = SPECPDL_INDEX (); Lisp_Object temp; - struct gcpro gcpro1, gcpro2; - Lisp_Object found, efound; + struct gcpro gcpro1, gcpro2, gcpro3; + Lisp_Object found, efound, hist_file_name; /* 1 means we printed the ".el is newer" message. */ int newer = 0; /* 1 means we are loading a compiled file. */ @@ -906,6 +907,7 @@ Return t if the file exists and loads successfully. */) Lisp_Object handler; int safe_p = 1; char *fmode = "r"; + Lisp_Object tmp[2]; int version; #ifdef DOS_NT @@ -924,7 +926,7 @@ Return t if the file exists and loads successfully. */) the need to gcpro noerror, nomessage and nosuffix. (Below here, we care only whether they are nil or not.) The presence of this call is the result of a historical accident: - it used to be in every file-operations and when it got removed + it used to be in every file-operation and when it got removed everywhere, it accidentally stayed here. Since then, enough people supposedly have things like (load "$PROJECT/foo.el") in their .emacs that it seemed risky to remove. */ @@ -944,7 +946,6 @@ Return t if the file exists and loads successfully. */) if (SCHARS (file) > 0) { int size = SBYTES (file); - Lisp_Object tmp[2]; found = Qnil; GCPRO2 (file, found); @@ -1028,6 +1029,13 @@ Return t if the file exists and loads successfully. */) Vloads_in_progress = Fcons (found, Vloads_in_progress); } + /* Get the name for load-history. */ + hist_file_name = (! NILP (Vpurify_flag) + ? Fconcat (2, (tmp[0] = Ffile_name_directory (file), + tmp[1] = Ffile_name_nondirectory (found), + tmp)) + : found) ; + version = -1; if (!bcmp (SDATA (found) + SBYTES (found) - 4, ".elc", 4) @@ -1040,7 +1048,7 @@ Return t if the file exists and loads successfully. */) struct stat s1, s2; int result; - GCPRO2 (file, found); + GCPRO3 (file, found, hist_file_name); if (version < 0 && ! (version = safe_to_load_p (fd))) @@ -1095,14 +1103,14 @@ Return t if the file exists and loads successfully. */) if (fd >= 0) emacs_close (fd); - val = call4 (Vload_source_file_function, found, file, + val = call4 (Vload_source_file_function, found, hist_file_name, NILP (noerror) ? Qnil : Qt, NILP (nomessage) ? Qnil : Qt); return unbind_to (count, val); } } - GCPRO2 (file, found); + GCPRO3 (file, found, hist_file_name); #ifdef WINDOWSNT emacs_close (fd); @@ -1142,23 +1150,23 @@ Return t if the file exists and loads successfully. */) = Fcons (make_number (fileno (stream)), load_descriptor_list); load_in_progress++; if (! version || version >= 22) - readevalloop (Qget_file_char, stream, - (! NILP (Vpurify_flag) ? file : found), + readevalloop (Qget_file_char, stream, hist_file_name, Feval, 0, Qnil, Qnil, Qnil, Qnil); else { /* We can't handle a file which was compiled with byte-compile-dynamic by older version of Emacs. */ specbind (Qload_force_doc_strings, Qt); - readevalloop (Qget_emacs_mule_file_char, stream, file, Feval, + readevalloop (Qget_emacs_mule_file_char, stream, hist_file_name, Feval, 0, Qnil, Qnil, Qnil, Qnil); } unbind_to (count, Qnil); - /* Run any load-hooks for this file. */ - temp = Fassoc (file, Vafter_load_alist); - if (!NILP (temp)) - Fprogn (Fcdr (temp)); + /* Run any eval-after-load forms for this file */ + if (NILP (Vpurify_flag) + && (!NILP (Ffboundp (Qdo_after_load_evaluation)))) + call1 (Qdo_after_load_evaluation, hist_file_name) ; + UNGCPRO; if (saved_doc_string) @@ -1583,6 +1591,12 @@ readevalloop (readcharfun, stream, sourcename, evalfun, GCPRO4 (sourcename, readfun, start, end); + /* Try to ensure sourcename is a truename, except whilst preloading. */ + if (NILP (Vpurify_flag) + && !NILP (sourcename) && Ffile_name_absolute_p (sourcename) + && (!NILP (Ffboundp (Qfile_truename)))) + sourcename = call1 (Qfile_truename, sourcename) ; + LOADHIST_ATTACH (sourcename); continue_reading_p = 1; @@ -4110,16 +4124,17 @@ customize `jka-compr-load-suffixes' rather than the present variable. */); DEFVAR_LISP ("after-load-alist", &Vafter_load_alist, doc: /* An alist of expressions to be evalled when particular files are loaded. -Each element looks like (FILENAME FORMS...). -When `load' is run and the file-name argument is FILENAME, -the FORMS in the corresponding element are executed at the end of loading. +Each element looks like (REGEXP-OR-FEATURE FORMS...). -FILENAME must match exactly! Normally FILENAME is the name of a library, -with no directory specified, since that is how `load' is normally called. -An error in FORMS does not undo the load, -but does prevent execution of the rest of the FORMS. -FILENAME can also be a symbol (a feature) and FORMS are then executed -when the corresponding call to `provide' is made. */); +REGEXP-OR-FEATURE is either a regular expression to match file names, or +a symbol \(a feature name). + +When `load' is run and the file-name argument matches an element's +REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol +REGEXP-OR-FEATURE, the FORMS in the element are executed. + +An error in FORMS does not undo the load, but does prevent execution of +the rest of the FORMS. */); Vafter_load_alist = Qnil; DEFVAR_LISP ("load-history", &Vload_history, @@ -4127,6 +4142,10 @@ when the corresponding call to `provide' is made. */); Each alist element is a list that starts with a file name, except for one element (optional) that starts with nil and describes definitions evaluated from buffers not visiting files. + +The file name is absolute and is the true file name (i.e. it doesn't +contain symbolic links) of the loaded file. + The remaining elements of each list are symbols defined as variables and cons cells of the form `(provide . FEATURE)', `(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)', and `(t . SYMBOL)'. @@ -4263,6 +4282,12 @@ to load. See also `load-dangerous-libraries'. */); Qeval_buffer_list = intern ("eval-buffer-list"); staticpro (&Qeval_buffer_list); + Qfile_truename = intern ("file-truename"); + staticpro (&Qfile_truename) ; + + Qdo_after_load_evaluation = intern ("do-after-load-evaluation"); + staticpro (&Qdo_after_load_evaluation) ; + staticpro (&dump_path); staticpro (&read_objects); diff --git a/src/mac.c b/src/mac.c index f7fcbe9ac88..5fc9ea4ee28 100644 --- a/src/mac.c +++ b/src/mac.c @@ -270,6 +270,26 @@ posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen) static Lisp_Object Qundecoded_file_name; +static struct { + AEKeyword keyword; + char *name; + Lisp_Object symbol; +} ae_attr_table [] = + {{keyTransactionIDAttr, "transaction-id"}, + {keyReturnIDAttr, "return-id"}, + {keyEventClassAttr, "event-class"}, + {keyEventIDAttr, "event-id"}, + {keyAddressAttr, "address"}, + {keyOptionalKeywordAttr, "optional-keyword"}, + {keyTimeoutAttr, "timeout"}, + {keyInteractLevelAttr, "interact-level"}, + {keyEventSourceAttr, "event-source"}, + /* {keyMissedKeywordAttr, "missed-keyword"}, */ + {keyOriginalAddressAttr, "original-address"}, + {keyReplyRequestedAttr, "reply-requested"}, + {KEY_EMACS_SUSPENSION_ID_ATTR, "emacs-suspension-id"} + }; + static Lisp_Object mac_aelist_to_lisp (desc_list) const AEDescList *desc_list; @@ -281,22 +301,36 @@ mac_aelist_to_lisp (desc_list) Size size; AEKeyword keyword; AEDesc desc; + int attribute_p = 0; err = AECountItems (desc_list, &count); if (err != noErr) return Qnil; result = Qnil; + + again: while (count > 0) { - err = AESizeOfNthItem (desc_list, count, &desc_type, &size); + if (attribute_p) + { + keyword = ae_attr_table[count - 1].keyword; + err = AESizeOfAttribute (desc_list, keyword, &desc_type, &size); + } + else + 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 (attribute_p) + err = AEGetAttributeDesc (desc_list, keyword, typeWildCard, + &desc); + else + err = AEGetNthDesc (desc_list, count, typeWildCard, + &keyword, &desc); if (err != noErr) break; elem = mac_aelist_to_lisp (&desc); @@ -309,8 +343,13 @@ mac_aelist_to_lisp (desc_list) else { elem = make_uninit_string (size); - err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword, - &desc_type, SDATA (elem), size, &size); + if (attribute_p) + err = AEGetAttributePtr (desc_list, keyword, typeWildCard, + &desc_type, SDATA (elem), + size, &size); + else + err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword, + &desc_type, SDATA (elem), size, &size); } if (err != noErr) break; @@ -319,18 +358,35 @@ mac_aelist_to_lisp (desc_list) break; } - if (err != noErr) - elem = Qnil; - else if (desc_list->descriptorType != typeAEList) + if (err == noErr || desc_list->descriptorType == typeAEList) { - keyword = EndianU32_NtoB (keyword); - elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem); + if (err != noErr) + elem = Qnil; /* Don't skip elements in AEList. */ + else if (desc_list->descriptorType != typeAEList) + { + if (attribute_p) + elem = Fcons (ae_attr_table[count-1].symbol, elem); + else + { + keyword = EndianU32_NtoB (keyword); + elem = Fcons (make_unibyte_string ((char *) &keyword, 4), + elem); + } + } + + result = Fcons (elem, result); } - result = Fcons (elem, result); count--; } + if (desc_list->descriptorType == typeAppleEvent && !attribute_p) + { + attribute_p = 1; + count = sizeof (ae_attr_table) / sizeof (ae_attr_table[0]); + goto again; + } + desc_type = EndianU32_NtoB (desc_list->descriptorType); return Fcons (make_unibyte_string ((char *) &desc_type, 4), result); } @@ -403,6 +459,93 @@ mac_aedesc_to_lisp (desc) return Fcons (make_unibyte_string ((char *) &desc_type, 4), result); } +OSErr +mac_ae_put_lisp (desc, keyword_or_index, obj) + AEDescList *desc; + UInt32 keyword_or_index; + Lisp_Object obj; +{ + OSErr err; + + if (!(desc->descriptorType == typeAppleEvent + || desc->descriptorType == typeAERecord + || desc->descriptorType == typeAEList)) + return errAEWrongDataType; + + if (CONSP (obj) && STRINGP (XCAR (obj)) && SBYTES (XCAR (obj)) == 4) + { + DescType desc_type1 = EndianU32_BtoN (*((UInt32 *) SDATA (XCAR (obj)))); + Lisp_Object data = XCDR (obj), rest; + AEDesc desc1; + + switch (desc_type1) + { + case typeNull: + case typeAppleEvent: + break; + + case typeAEList: + case typeAERecord: + err = AECreateList (NULL, 0, desc_type1 == typeAERecord, &desc1); + if (err == noErr) + { + for (rest = data; CONSP (rest); rest = XCDR (rest)) + { + UInt32 keyword_or_index1 = 0; + Lisp_Object elem = XCAR (rest); + + if (desc_type1 == typeAERecord) + { + if (CONSP (elem) && STRINGP (XCAR (elem)) + && SBYTES (XCAR (elem)) == 4) + { + keyword_or_index1 = + EndianU32_BtoN (*((UInt32 *) + SDATA (XCAR (elem)))); + elem = XCDR (elem); + } + else + continue; + } + + err = mac_ae_put_lisp (&desc1, keyword_or_index1, elem); + if (err != noErr) + break; + } + + if (err == noErr) + { + if (desc->descriptorType == typeAEList) + err = AEPutDesc (desc, keyword_or_index, &desc1); + else + err = AEPutParamDesc (desc, keyword_or_index, &desc1); + } + + AEDisposeDesc (&desc1); + } + return err; + + default: + if (!STRINGP (data)) + break; + if (desc->descriptorType == typeAEList) + err = AEPutPtr (desc, keyword_or_index, desc_type1, + SDATA (data), SBYTES (data)); + else + err = AEPutParamPtr (desc, keyword_or_index, desc_type1, + SDATA (data), SBYTES (data)); + return err; + } + } + + if (desc->descriptorType == typeAEList) + err = AEPutPtr (desc, keyword_or_index, typeNull, NULL, 0); + else + err = AEPutParamPtr (desc, keyword_or_index, typeNull, NULL, 0); + + return err; +} + static pascal OSErr mac_coerce_file_name_ptr (type_code, data_ptr, data_size, to_type, handler_refcon, result) @@ -722,8 +865,7 @@ create_apple_event_from_event_ref (event, num_params, names, types, result) '?'); if (data == NULL) break; - /* typeUTF8Text is not available on Mac OS X 10.1. */ - AEPutParamPtr (result, names[i], 'utf8', + AEPutParamPtr (result, names[i], typeUTF8Text, CFDataGetBytePtr (data), CFDataGetLength (data)); CFRelease (data); break; @@ -4661,7 +4803,7 @@ cfstring_create_normalized (str, symbol) } if (in_text) - err = CreateUnicodeToTextInfo(&map, &uni); + err = CreateUnicodeToTextInfo (&map, &uni); while (err == noErr) { out_buf = xmalloc (out_size); @@ -5234,6 +5376,16 @@ syms_of_mac () QHFS_plus_C = intern ("HFS+C"); staticpro (&QHFS_plus_C); #endif + { + int i; + + for (i = 0; i < sizeof (ae_attr_table) / sizeof (ae_attr_table[0]); i++) + { + ae_attr_table[i].symbol = intern (ae_attr_table[i].name); + staticpro (&ae_attr_table[i].symbol); + } + } + defsubr (&Smac_coerce_ae_data); #if TARGET_API_MAC_CARBON defsubr (&Smac_get_preference); diff --git a/src/macfns.c b/src/macfns.c index 8e0d5153034..1c774f8ade2 100644 --- a/src/macfns.c +++ b/src/macfns.c @@ -1592,7 +1592,7 @@ x_set_icon_name (f, arg, oldval) if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) return; } - else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) + else if (!NILP (arg) || NILP (oldval)) return; f->icon_name = arg; @@ -2829,26 +2829,22 @@ FRAME nil means use the selected frame. */) Lisp_Object frame; { struct frame *f = check_x_frame (frame); - struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); - if (dpyinfo->x_focus_frame != f) - { - BLOCK_INPUT; + BLOCK_INPUT; #ifdef MAC_OSX - ActivateWindow (ActiveNonFloatingWindow (), false); - ActivateWindow (FRAME_MAC_WINDOW (f), true); + ActivateWindow (ActiveNonFloatingWindow (), false); + ActivateWindow (FRAME_MAC_WINDOW (f), true); #else #if !TARGET_API_MAC_CARBON - /* SelectWindow (Non-Carbon) does not issue deactivate events if - the possibly inactive window that is to be selected is - already the frontmost one. */ - SendBehind (FRAME_MAC_WINDOW (f), NULL); + /* SelectWindow (Non-Carbon) does not issue deactivate events if the + possibly inactive window that is to be selected is already the + frontmost one. */ + SendBehind (FRAME_MAC_WINDOW (f), NULL); #endif - /* This brings the window to the front. */ - SelectWindow (FRAME_MAC_WINDOW (f)); + /* This brings the window to the front. */ + SelectWindow (FRAME_MAC_WINDOW (f)); #endif - UNBLOCK_INPUT; - } + UNBLOCK_INPUT; return Qnil; } @@ -3028,11 +3024,11 @@ If omitted or nil, that stands for the selected frame's display. */) { if (response >= 0x00001040) { - err = Gestalt ('sys1', &major); /* gestaltSystemVersionMajor */ + err = Gestalt (gestaltSystemVersionMajor, &major); if (err == noErr) - err = Gestalt ('sys2', &minor); /* gestaltSystemVersionMinor */ + err = Gestalt (gestaltSystemVersionMinor, &minor); if (err == noErr) - err = Gestalt ('sys3', &bugfix); /* gestaltSystemVersionBugFix */ + err = Gestalt (gestaltSystemVersionBugFix, &bugfix); } else { @@ -4518,8 +4514,18 @@ This is for internal use only. Use `mac-font-panel-mode' instead. */) check_mac (); BLOCK_INPUT; - if (NILP (visible) == (FPIsFontPanelVisible () == true)) - err = FPShowHideFontPanel (); + if (NILP (visible) != !mac_font_panel_visible_p ()) + { + err = mac_show_hide_font_panel (); + if (err == noErr && !NILP (visible)) + { + Lisp_Object focus_frame = x_get_focus_frame (SELECTED_FRAME ()); + struct frame *f = (NILP (focus_frame) ? SELECTED_FRAME () + : XFRAME (focus_frame)); + + mac_set_font_info_for_selection (f, DEFAULT_FACE_ID, 0); + } + } UNBLOCK_INPUT; if (err != noErr) diff --git a/src/macgui.h b/src/macgui.h index 690840c6c33..90688e5703e 100644 --- a/src/macgui.h +++ b/src/macgui.h @@ -112,6 +112,13 @@ typedef unsigned long Time; #endif #endif +/* Whether to use Text Services Manager. */ +#ifndef USE_MAC_TSM +#ifdef MAC_OSX +#define USE_MAC_TSM 1 +#endif +#endif + typedef WindowPtr Window; typedef GWorldPtr Pixmap; diff --git a/src/macselect.c b/src/macselect.c index 1b6a1a46cc3..3afea1e9813 100644 --- a/src/macselect.c +++ b/src/macselect.c @@ -909,14 +909,13 @@ and t is the same as `SECONDARY'. */) } +/*********************************************************************** + Apple event support +***********************************************************************/ 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; +static Lisp_Object Qemacs_suspension_id; extern Lisp_Object Qundefined; extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object, const AEDesc *)); @@ -927,6 +926,19 @@ struct apple_event_binding Lisp_Object key, binding; }; +struct suspended_ae_info +{ + UInt32 expiration_tick, suspension_id; + AppleEvent apple_event, reply; + struct suspended_ae_info *next; +}; + +/* List of deferred apple events at the startup time. */ +static struct suspended_ae_info *deferred_apple_events = NULL; + +/* List of suspended apple events, in order of expiration_tick. */ +static struct suspended_ae_info *suspended_apple_events = NULL; + static void find_event_binding_fun (key, binding, args, data) Lisp_Object key, binding, args; @@ -1003,6 +1015,12 @@ defer_apple_events (apple_event, reply) const AppleEvent *apple_event, *reply; { OSErr err; + struct suspended_ae_info *new; + + new = xmalloc (sizeof (struct suspended_ae_info)); + bzero (new, sizeof (struct suspended_ae_info)); + new->apple_event.descriptorType = typeNull; + new->reply.descriptorType = typeNull; err = AESuspendTheCurrentEvent (apple_event); @@ -1011,30 +1029,88 @@ defer_apple_events (apple_event, reply) manual says it doesn't. Anyway we create copies of them and save them in `deferred_apple_events'. */ if (err == noErr) + err = AEDuplicateDesc (apple_event, &new->apple_event); + if (err == noErr) + err = AEDuplicateDesc (reply, &new->reply); + 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); - } - else if (deferred_apple_events.count == deferred_apple_events.size) + new->next = deferred_apple_events; + deferred_apple_events = new; + } + else + { + AEDisposeDesc (&new->apple_event); + AEDisposeDesc (&new->reply); + xfree (new); + } + + return err; +} + +static OSErr +mac_handle_apple_event_1 (class, id, apple_event, reply) + Lisp_Object class, id; + const AppleEvent *apple_event; + AppleEvent *reply; +{ + OSErr err; + static UInt32 suspension_id = 0; + struct suspended_ae_info *new; + + new = xmalloc (sizeof (struct suspended_ae_info)); + bzero (new, sizeof (struct suspended_ae_info)); + new->apple_event.descriptorType = typeNull; + new->reply.descriptorType = typeNull; + + err = AESuspendTheCurrentEvent (apple_event); + if (err == noErr) + err = AEDuplicateDesc (apple_event, &new->apple_event); + if (err == noErr) + err = AEDuplicateDesc (reply, &new->reply); + if (err == noErr) + err = AEPutAttributePtr (&new->apple_event, KEY_EMACS_SUSPENSION_ID_ATTR, + typeUInt32, &suspension_id, sizeof (UInt32)); + if (err == noErr) + { + OSErr err1; + SInt32 reply_requested; + + err1 = AEGetAttributePtr (&new->apple_event, keyReplyRequestedAttr, + typeSInt32, NULL, &reply_requested, + sizeof (SInt32), NULL); + if (err1 != noErr) { - deferred_apple_events.size *= 2; - deferred_apple_events.buf - = xrealloc (deferred_apple_events.buf, - sizeof (AppleEvent) * deferred_apple_events.size); + /* Emulate keyReplyRequestedAttr in older versions. */ + reply_requested = reply->descriptorType != typeNull; + err = AEPutAttributePtr (&new->apple_event, keyReplyRequestedAttr, + typeSInt32, &reply_requested, + sizeof (SInt32)); } } - if (err == noErr) { - int count = deferred_apple_events.count; + SInt32 timeout = 0; + struct suspended_ae_info **p; + + new->suspension_id = suspension_id; + suspension_id++; + err = AEGetAttributePtr (apple_event, keyTimeoutAttr, typeSInt32, + NULL, &timeout, sizeof (SInt32), NULL); + new->expiration_tick = TickCount () + timeout; + + for (p = &suspended_apple_events; *p; p = &(*p)->next) + if ((*p)->expiration_tick >= new->expiration_tick) + break; + new->next = *p; + *p = new; - AEDuplicateDesc (apple_event, deferred_apple_events.buf + count); - AEDuplicateDesc (reply, deferred_apple_events.buf + count + 1); - deferred_apple_events.count += 2; + mac_store_apple_event (class, id, &new->apple_event); + } + else + { + AEDisposeDesc (&new->reply); + AEDisposeDesc (&new->apple_event); + xfree (new); } return err; @@ -1047,17 +1123,11 @@ mac_handle_apple_event (apple_event, reply, refcon) SInt32 refcon; { OSErr err; + UInt32 suspension_id; 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); @@ -1066,6 +1136,13 @@ mac_handle_apple_event (apple_event, reply, refcon) return noErr; } + err = AEGetAttributePtr (apple_event, KEY_EMACS_SUSPENSION_ID_ATTR, + typeUInt32, NULL, + &suspension_id, sizeof (UInt32), NULL); + if (err == noErr) + /* Previously suspended event. Pass it to the next handler. */ + return errAEEventNotHandled; + err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL, &event_class, sizeof (AEEventClass), NULL); if (err == noErr) @@ -1079,11 +1156,49 @@ mac_handle_apple_event (apple_event, reply, refcon) { if (INTEGERP (binding)) return XINT (binding); - mac_store_apple_event (class_key, id_key, apple_event); - return noErr; + err = mac_handle_apple_event_1 (class_key, id_key, + apple_event, reply); } + else + err = errAEEventNotHandled; } - return errAEEventNotHandled; + if (err == noErr) + return noErr; + else + return errAEEventNotHandled; +} + +static int +cleanup_suspended_apple_events (head, all_p) + struct suspended_ae_info **head; + int all_p; +{ + UInt32 current_tick = TickCount (), nresumed = 0; + struct suspended_ae_info *p, *next; + + for (p = *head; p; p = next) + { + if (!all_p && p->expiration_tick > current_tick) + break; + AESetTheCurrentEvent (&p->apple_event); + AEResumeTheCurrentEvent (&p->apple_event, &p->reply, + (AEEventHandlerUPP) kAENoDispatch, 0); + AEDisposeDesc (&p->reply); + AEDisposeDesc (&p->apple_event); + nresumed++; + next = p->next; + xfree (p); + } + *head = p; + + return nresumed; +} + +static void +cleanup_all_suspended_apple_events () +{ + cleanup_suspended_apple_events (&deferred_apple_events, 1); + cleanup_suspended_apple_events (&suspended_apple_events, 1); } void @@ -1109,34 +1224,190 @@ init_apple_event_handler () 0L, false); if (err != noErr) abort (); + + atexit (cleanup_all_suspended_apple_events); +} + +static UInt32 +get_suspension_id (apple_event) + Lisp_Object apple_event; +{ + Lisp_Object tem; + + CHECK_CONS (apple_event); + CHECK_STRING_CAR (apple_event); + if (SBYTES (XCAR (apple_event)) != 4 + || strcmp (SDATA (XCAR (apple_event)), "aevt") != 0) + error ("Not an apple event"); + + tem = assq_no_quit (Qemacs_suspension_id, XCDR (apple_event)); + if (NILP (tem)) + error ("Suspension ID not available"); + + tem = XCDR (tem); + if (!(CONSP (tem) + && STRINGP (XCAR (tem)) && SBYTES (XCAR (tem)) == 4 + && strcmp (SDATA (XCAR (tem)), "magn") == 0 + && STRINGP (XCDR (tem)) && SBYTES (XCDR (tem)) == 4)) + error ("Bad suspension ID format"); + + return *((UInt32 *) SDATA (XCDR (tem))); } + 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. */) () { - Lisp_Object result = Qnil; - long i; - if (mac_ready_for_apple_events) return Qnil; BLOCK_INPUT; mac_ready_for_apple_events = 1; - if (deferred_apple_events.buf) + if (deferred_apple_events) { - for (i = 0; i < deferred_apple_events.count; i += 2) + struct suspended_ae_info *prev, *tail, *next; + + /* `nreverse' deferred_apple_events. */ + prev = NULL; + for (tail = deferred_apple_events; tail; tail = next) + { + next = tail->next; + tail->next = prev; + prev = tail; + } + + /* Now `prev' points to the first cell. */ + for (tail = prev; tail; tail = next) { - AEResumeTheCurrentEvent (deferred_apple_events.buf + i, - deferred_apple_events.buf + i + 1, + next = tail->next; + AEResumeTheCurrentEvent (&tail->apple_event, &tail->reply, ((AEEventHandlerUPP) kAEUseStandardDispatch), 0); - AEDisposeDesc (deferred_apple_events.buf + i); - AEDisposeDesc (deferred_apple_events.buf + i + 1); + AEDisposeDesc (&tail->reply); + AEDisposeDesc (&tail->apple_event); + xfree (tail); } - xfree (deferred_apple_events.buf); - bzero (&deferred_apple_events, sizeof (deferred_apple_events)); + deferred_apple_events = NULL; + } + UNBLOCK_INPUT; + + return Qt; +} + +DEFUN ("mac-cleanup-expired-apple-events", Fmac_cleanup_expired_apple_events, Smac_cleanup_expired_apple_events, 0, 0, 0, + doc: /* Clean up expired Apple events. +Return the number of expired events. */) + () +{ + int nexpired; + + BLOCK_INPUT; + nexpired = cleanup_suspended_apple_events (&suspended_apple_events, 0); + UNBLOCK_INPUT; + + return make_number (nexpired); +} + +DEFUN ("mac-ae-set-reply-parameter", Fmac_ae_set_reply_parameter, Smac_ae_set_reply_parameter, 3, 3, 0, + doc: /* Set parameter KEYWORD to DESCRIPTOR on reply of APPLE-EVENT. +KEYWORD is a 4-byte string. DESCRIPTOR is a Lisp representation of an +Apple event descriptor. It has the form of (TYPE . DATA), where TYPE +is a 4-byte string. Valid format of DATA is as follows: + + * If TYPE is "null", then DATA is nil. + * If TYPE is "list", then DATA is a list (DESCRIPTOR1 ... DESCRIPTORn). + * If TYPE is "reco", then DATA is a list ((KEYWORD1 . DESCRIPTOR1) + ... (KEYWORDn . DESCRIPTORn)). + * If TYPE is "aevt", then DATA is ignored and the descriptor is + treated as null. + * Otherwise, DATA is a string. + +If a (sub-)descriptor is in an invalid format, it is silently treated +as null. + +Return t if the parameter is successfully set. Otherwise return nil. */) + (apple_event, keyword, descriptor) + Lisp_Object apple_event, keyword, descriptor; +{ + Lisp_Object result = Qnil; + UInt32 suspension_id; + struct suspended_ae_info *p; + + suspension_id = get_suspension_id (apple_event); + + CHECK_STRING (keyword); + if (SBYTES (keyword) != 4) + error ("Apple event keyword must be a 4-byte string: %s", + SDATA (keyword)); + + BLOCK_INPUT; + for (p = suspended_apple_events; p; p = p->next) + if (p->suspension_id == suspension_id) + break; + if (p && p->reply.descriptorType != typeNull) + { + OSErr err; + + err = mac_ae_put_lisp (&p->reply, + EndianU32_BtoN (*((UInt32 *) SDATA (keyword))), + descriptor); + if (err == noErr) + result = Qt; + } + UNBLOCK_INPUT; + + return result; +} + +DEFUN ("mac-resume-apple-event", Fmac_resume_apple_event, Smac_resume_apple_event, 1, 2, 0, + doc: /* Resume handling of APPLE-EVENT. +Every Apple event handled by the Lisp interpreter is suspended first. +This function resumes such a suspended event either to complete Apple +event handling to give a reply, or to redispatch it to other handlers. + +If optional ERROR-CODE is an integer, it specifies the error number +that is set in the reply. If ERROR-CODE is t, the resumed event is +handled with the standard dispatching mechanism, but it is not handled +by Emacs again, thus it is redispatched to other handlers. + +Return t if APPLE-EVENT is successfully resumed. Otherwise return +nil, which means the event is already resumed or expired. */) + (apple_event, error_code) + Lisp_Object apple_event, error_code; +{ + Lisp_Object result = Qnil; + UInt32 suspension_id; + struct suspended_ae_info **p, *ae; + + suspension_id = get_suspension_id (apple_event); + + BLOCK_INPUT; + for (p = &suspended_apple_events; *p; p = &(*p)->next) + if ((*p)->suspension_id == suspension_id) + break; + if (*p) + { + ae = *p; + *p = (*p)->next; + if (INTEGERP (error_code) + && ae->apple_event.descriptorType != typeNull) + { + SInt32 errn = XINT (error_code); + + AEPutParamPtr (&ae->reply, keyErrorNumber, typeSInt32, + &errn, sizeof (SInt32)); + } + AESetTheCurrentEvent (&ae->apple_event); + AEResumeTheCurrentEvent (&ae->apple_event, &ae->reply, + ((AEEventHandlerUPP) + (EQ (error_code, Qt) ? + kAEUseStandardDispatch : kAENoDispatch)), + 0); + AEDisposeDesc (&ae->reply); + AEDisposeDesc (&ae->apple_event); + xfree (ae); result = Qt; } UNBLOCK_INPUT; @@ -1145,6 +1416,9 @@ DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, } +/*********************************************************************** + Drag and drop support +***********************************************************************/ #if TARGET_API_MAC_CARBON static Lisp_Object Vmac_dnd_known_types; static pascal OSErr mac_do_track_drag P_ ((DragTrackingMessage, WindowRef, @@ -1337,6 +1611,9 @@ remove_drag_handler (window) } +/*********************************************************************** + Services menu support +***********************************************************************/ #ifdef MAC_OSX void init_service_handler () @@ -1554,6 +1831,9 @@ syms_of_macselect () defsubr (&Sx_selection_owner_p); defsubr (&Sx_selection_exists_p); defsubr (&Smac_process_deferred_apple_events); + defsubr (&Smac_cleanup_expired_apple_events); + defsubr (&Smac_resume_apple_event); + defsubr (&Smac_ae_set_reply_parameter); Vselection_alist = Qnil; staticpro (&Vselection_alist); @@ -1635,6 +1915,9 @@ The types are chosen in the order they appear in the list. */); Qmac_apple_event_id = intern ("mac-apple-event-id"); staticpro (&Qmac_apple_event_id); + + Qemacs_suspension_id = intern ("emacs-suspension-id"); + staticpro (&Qemacs_suspension_id); } /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732 diff --git a/src/macterm.c b/src/macterm.c index e3b8b3b5881..549e1e7977b 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -3531,19 +3531,28 @@ x_draw_stretch_glyph_string (s) { /* If `x-stretch-block-cursor' is nil, don't draw a block cursor as wide as the stretch glyph. */ - int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width); + int width, background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + width = min (FRAME_COLUMN_WIDTH (s->f), background_width); /* Draw cursor. */ - x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height); + x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height); /* Clear rest using the GC of the original non-cursor face. */ - if (width < s->background_width) + if (width < background_width) { - int x = s->x + width, y = s->y; - int w = s->background_width - width, h = s->height; + int y = s->y; + int w = background_width - width, h = s->height; Rect r; GC gc; + x += width; if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) { @@ -3570,8 +3579,18 @@ x_draw_stretch_glyph_string (s) } } else if (!s->background_filled_p) - x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width, - s->height); + { + int background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + if (background_width > 0) + x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); + } s->background_filled_p = 1; } @@ -5398,8 +5417,7 @@ x_draw_hollow_cursor (w, row) return; /* Compute frame-relative coordinates for phys cursor. */ - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - y = get_phys_cursor_geometry (w, row, cursor_glyph, &h); + get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); wd = w->phys_cursor_width; /* The foreground of cursor_gc is typically the same as the normal @@ -6135,6 +6153,7 @@ mac_handle_visibility_change (f) EVENT_INIT (buf); buf.kind = DEICONIFY_EVENT; XSETFRAME (buf.frame_or_window, f); + buf.arg = Qnil; kbd_buffer_store_event (&buf); } else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) @@ -6148,6 +6167,7 @@ mac_handle_visibility_change (f) EVENT_INIT (buf); buf.kind = ICONIFY_EVENT; XSETFRAME (buf.frame_or_window, f); + buf.arg = Qnil; kbd_buffer_store_event (&buf); } @@ -8341,6 +8361,26 @@ x_find_ccl_program (fontp) } #if USE_MAC_FONT_PANEL +/* Whether Font Panel has been shown before. The first call to font + panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is + slow. This variable is used for deferring such a call as much as + possible. */ +static int font_panel_shown_p = 0; + +int +mac_font_panel_visible_p () +{ + return font_panel_shown_p && FPIsFontPanelVisible (); +} + +OSStatus +mac_show_hide_font_panel () +{ + font_panel_shown_p = 1; + + return FPShowHideFontPanel (); +} + OSStatus mac_set_font_info_for_selection (f, face_id, c) struct frame *f; @@ -8350,6 +8390,9 @@ mac_set_font_info_for_selection (f, face_id, c) EventTargetRef target = NULL; XFontStruct *font = NULL; + if (!mac_font_panel_visible_p ()) + return noErr; + if (f) { target = GetWindowEventTarget (FRAME_MAC_WINDOW (f)); @@ -8484,6 +8527,13 @@ static Lisp_Object Qtoolbar_switch_mode; extern Lisp_Object Qfont; static Lisp_Object Qpanel_closed, Qselection; #endif +#if USE_MAC_TSM +static TSMDocumentID tsm_document_id; +static Lisp_Object Qtext_input; +static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event; +static Lisp_Object Vmac_ts_active_input_overlay; +extern Lisp_Object Qbefore_string; +#endif #endif extern int mac_ready_for_apple_events; extern Lisp_Object Qundefined; @@ -8835,13 +8885,17 @@ is_emacs_window (WindowPtr win) static void do_app_resume () { - /* Window-activate events will do the job. */ +#if USE_MAC_TSM + ActivateTSMDocument (tsm_document_id); +#endif } static void do_app_suspend () { - /* Window-deactivate events will do the job. */ +#if USE_MAC_TSM + DeactivateTSMDocument (tsm_document_id); +#endif } @@ -9101,6 +9155,9 @@ mac_store_event_ref_as_apple_event (class, id, class_key, id_key, { mac_store_apple_event (class_key, id_key, &apple_event); AEDisposeDesc (&apple_event); + /* Post a harmless event so as to wake up from + ReceiveNextEvent. */ + mac_post_mouse_moved_event (); } } } @@ -9290,6 +9347,18 @@ mac_handle_window_event (next_handler, event, data) } return err == noErr ? noErr : result; #endif + +#if USE_MAC_TSM + case kEventWindowFocusAcquired: + result = CallNextEventHandler (next_handler, event); + err = ActivateTSMDocument (tsm_document_id); + return err == noErr ? noErr : result; + + case kEventWindowFocusRelinquish: + result = CallNextEventHandler (next_handler, event); + err = DeactivateTSMDocument (tsm_document_id); + return err == noErr ? noErr : result; +#endif } return eventNotHandledErr; @@ -9416,6 +9485,183 @@ mac_handle_font_event (next_handler, event, data) } #endif +#if USE_MAC_TSM +static pascal OSStatus +mac_handle_text_input_event (next_handler, event, data) + EventHandlerCallRef next_handler; + EventRef event; + void *data; +{ + OSStatus result, err = noErr; + Lisp_Object id_key = Qnil; + int num_params; + EventParamName *names; + EventParamType *types; + static UInt32 seqno_uaia = 0; + static EventParamName names_uaia[] = + {kEventParamTextInputSendComponentInstance, + kEventParamTextInputSendRefCon, + kEventParamTextInputSendSLRec, + kEventParamTextInputSendFixLen, + kEventParamTextInputSendText, + kEventParamTextInputSendUpdateRng, + kEventParamTextInputSendHiliteRng, + kEventParamTextInputSendClauseRng, + kEventParamTextInputSendPinRng, + kEventParamTextInputSendTextServiceEncoding, + kEventParamTextInputSendTextServiceMacEncoding, + EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER}; + static EventParamType types_uaia[] = + {typeComponentInstance, + typeLongInteger, + typeIntlWritingCode, + typeLongInteger, + typeUnicodeText, + typeTextRangeArray, + typeTextRangeArray, + typeOffsetArray, + typeTextRange, + typeUInt32, + typeUInt32, + typeUInt32}; + static EventParamName names_ufke[] = + {kEventParamTextInputSendComponentInstance, + kEventParamTextInputSendRefCon, + kEventParamTextInputSendSLRec, + kEventParamTextInputSendText}; + static EventParamType types_ufke[] = + {typeComponentInstance, + typeLongInteger, + typeIntlWritingCode, + typeUnicodeText}; + + result = CallNextEventHandler (next_handler, event); + + switch (GetEventKind (event)) + { + case kEventTextInputUpdateActiveInputArea: + id_key = Qupdate_active_input_area; + num_params = sizeof (names_uaia) / sizeof (names_uaia[0]); + names = names_uaia; + types = types_uaia; + SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER, + typeUInt32, sizeof (UInt32), &seqno_uaia); + seqno_uaia++; + break; + + case kEventTextInputUnicodeForKeyEvent: + { + EventRef kbd_event; + UInt32 actual_size, modifiers, mapped_modifiers; + UniChar code; + + err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent, + typeEventRef, NULL, sizeof (EventRef), NULL, + &kbd_event); + if (err == noErr) + err = GetEventParameter (kbd_event, kEventParamKeyModifiers, + typeUInt32, NULL, + sizeof (UInt32), NULL, &modifiers); + if (err == noErr) + { + mapped_modifiers = + (NILP (Vmac_control_modifier) ? 0 : controlKey) + | (NILP (Vmac_option_modifier) ? 0 : optionKey) + | (NILP (Vmac_command_modifier) ? 0 : cmdKey); +#ifdef MAC_OSX + mapped_modifiers |= + (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask); +#endif + if (modifiers & mapped_modifiers) + /* There're mapped modifier keys. Process it in + XTread_socket. */ + return eventNotHandledErr; + } + if (err == noErr) + err = GetEventParameter (kbd_event, kEventParamKeyUnicodes, + typeUnicodeText, NULL, 0, &actual_size, + NULL); + if (err == noErr) + { + if (actual_size == sizeof (UniChar)) + err = GetEventParameter (kbd_event, kEventParamKeyUnicodes, + typeUnicodeText, NULL, + sizeof (UniChar), NULL, &code); + if (err == noErr && code < 0x80) + { + /* ASCII character. Process it in XTread_socket. */ + if (read_socket_inev && code >= 0x20 && code <= 0x7e) + { + struct frame *f = mac_focus_frame (&one_mac_display_info); + + read_socket_inev->kind = ASCII_KEYSTROKE_EVENT; + read_socket_inev->code = code; + read_socket_inev->modifiers = + (extra_keyboard_modifiers + & (meta_modifier | alt_modifier + | hyper_modifier | super_modifier)); + XSETFRAME (read_socket_inev->frame_or_window, f); + } + return eventNotHandledErr; + } + } + } + /* Non-ASCII keystrokes without mapped modifiers are processed + at the Lisp level. */ + id_key = Qunicode_for_key_event; + num_params = sizeof (names_ufke) / sizeof (names_ufke[0]); + names = names_ufke; + types = types_ufke; + break; + + case kEventTextInputOffsetToPos: + { + struct frame *f; + struct window *w; + Point p; + + if (!OVERLAYP (Vmac_ts_active_input_overlay)) + return eventNotHandledErr; + + /* Strictly speaking, this is not always correct because + previous events may change some states about display. */ + if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string))) + { + /* Active input area is displayed in the echo area. */ + w = XWINDOW (echo_area_window); + f = WINDOW_XFRAME (w); + } + else + { + /* Active input area is displayed around the current point. */ + f = SELECTED_FRAME (); + w = XWINDOW (f->selected_window); + } + + p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x) + + WINDOW_LEFT_FRINGE_WIDTH (w)); + p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y) + + FONT_BASE (FRAME_FONT (f))); + SetPortWindowPort (FRAME_MAC_WINDOW (f)); + LocalToGlobal (&p); + err = SetEventParameter (event, kEventParamTextInputReplyPoint, + typeQDPoint, sizeof (typeQDPoint), &p); + } + break; + + default: + abort (); + } + + if (!NILP (id_key)) + err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key, + event, num_params, + names, types); + + return err == noErr ? noErr : result; +} +#endif + #ifdef MAC_OSX OSStatus mac_store_service_event (event) @@ -9477,6 +9723,10 @@ install_window_handler (window) #ifdef MAC_OSX {kEventClassWindow, kEventWindowToolbarSwitchMode}, #endif +#if USE_MAC_TSM + {kEventClassWindow, kEventWindowFocusAcquired}, + {kEventClassWindow, kEventWindowFocusRelinquish}, +#endif }; EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}}; static EventHandlerUPP handle_window_eventUPP = NULL; @@ -9486,6 +9736,13 @@ install_window_handler (window) {kEventClassFont, kEventFontSelection}}; static EventHandlerUPP handle_font_eventUPP = NULL; #endif +#if USE_MAC_TSM + EventTypeSpec specs_text_input[] = + {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea}, + {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent}, + {kEventClassTextInput, kEventTextInputOffsetToPos}}; + static EventHandlerUPP handle_text_input_eventUPP = NULL; +#endif if (handle_window_eventUPP == NULL) handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event); @@ -9495,6 +9752,11 @@ install_window_handler (window) if (handle_font_eventUPP == NULL) handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event); #endif +#if USE_MAC_TSM + if (handle_text_input_eventUPP == NULL) + handle_text_input_eventUPP = + NewEventHandlerUPP (mac_handle_text_input_event); +#endif err = InstallWindowEventHandler (window, handle_window_eventUPP, GetEventTypeCount (specs_window), specs_window, NULL, NULL); @@ -9508,6 +9770,12 @@ install_window_handler (window) GetEventTypeCount (specs_font), specs_font, NULL, NULL); #endif +#if USE_MAC_TSM + if (err == noErr) + err = InstallWindowEventHandler (window, handle_text_input_eventUPP, + GetEventTypeCount (specs_text_input), + specs_text_input, window, NULL); +#endif #endif if (err == noErr) err = install_drag_handler (window); @@ -9633,7 +9901,7 @@ static unsigned char keycode_to_xkeysym_table[] = { /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/, /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/, - /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/, + /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/, /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/, /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/, @@ -9650,7 +9918,13 @@ keycode_to_xkeysym (int keyCode, int *xKeySym) return *xKeySym != 0; } -static unsigned char fn_keycode_to_xkeysym_table[] = { +#ifdef MAC_OSX +/* Table for translating Mac keycode with the laptop `fn' key to that + without it. Destination symbols in comments are keys on US + keyboard, and they may not be the same on other types of keyboards. + If the destination is identical to the source (f1 ... f12), it + doesn't map `fn' key to a modifier. */ +static unsigned char fn_keycode_to_keycode_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, @@ -9660,113 +9934,27 @@ static unsigned char fn_keycode_to_xkeysym_table[] = { /*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, + /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/, + /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/, + /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/, + /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*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, + /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/, + /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/, + /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/, + /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0, - /*0x60*/ 0, 0, 0, 0, - /*0x64*/ 0, 0, 0, 0, + /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/, + /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/, /*0x68*/ 0, 0, 0, 0, - /*0x6C*/ 0, 0, 0, 0, + /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/, - /*0x70*/ 0, 0, 0, 0, - /*0x74*/ 0, 0, 0, 0, - /*0x78*/ 0, 0, 0, 0, + /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/, + /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/, + /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 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. - - */ - OSStatus err; - UInt32 mods = 0; - if (!NILP(Vmac_function_modifier)) - { - err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, - NULL, sizeof (UInt32), NULL, &mods); - if (err != noErr && 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; -} - +#endif /* MAC_OSX */ #if !USE_CARBON_EVENTS static RgnHandle mouse_region = NULL; @@ -9840,6 +10028,44 @@ mac_post_mouse_moved_event () return err; } + +static void +mac_set_unicode_keystroke_event (code, buf) + UniChar code; + struct input_event *buf; +{ + int charset_id, c1, c2; + + if (code < 0x80) + { + buf->kind = ASCII_KEYSTROKE_EVENT; + buf->code = code; + } + else if (code < 0x100) + { + if (code < 0xA0) + charset_id = CHARSET_8_BIT_CONTROL; + else + charset_id = charset_latin_iso8859_1; + buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + buf->code = MAKE_CHAR (charset_id, code, 0); + } + else + { + if (code < 0x2500) + charset_id = charset_mule_unicode_0100_24ff, + code -= 0x100; + else if (code < 0x33FF) + charset_id = charset_mule_unicode_2500_33ff, + code -= 0x2500; + else if (code >= 0xE000) + charset_id = charset_mule_unicode_e000_ffff, + code -= 0xE000; + c1 = (code / 96) + 32, c2 = (code % 96) + 32; + buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + buf->code = MAKE_CHAR (charset_id, c1, c2); + } +} #endif /* Emacs calls this whenever it wants to read an input event from the @@ -9889,10 +10115,6 @@ XTread_socket (sd, expected, hold_quit) struct frame *f; unsigned long timestamp; - /* It is necessary to set this (additional) argument slot of an - event to nil because keyboard.c protects incompletely - processed event from being garbage collected by placing them - in the kbd_buffer_gcpro vector. */ EVENT_INIT (inev); inev.kind = NO_EVENT; inev.arg = Qnil; @@ -10354,10 +10576,29 @@ XTread_socket (sd, expected, hold_quit) break; case keyDown: + case keyUp: case autoKey: { int keycode = (er.message & keyCodeMask) >> 8; int xkeysym; + static SInt16 last_key_script = -1; + SInt16 current_key_script; + UInt32 modifiers = er.modifiers, mapped_modifiers; + + mapped_modifiers = + (NILP (Vmac_control_modifier) ? 0 : controlKey) + | (NILP (Vmac_option_modifier) ? 0 : optionKey) + | (NILP (Vmac_command_modifier) ? 0 : cmdKey); + +#if USE_CARBON_EVENTS && defined (MAC_OSX) + mapped_modifiers |= + (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask); + + GetEventParameter (eventRef, kEventParamKeyModifiers, + typeUInt32, NULL, + sizeof (UInt32), NULL, &modifiers); +#endif + mapped_modifiers &= modifiers; #if USE_CARBON_EVENTS && defined (MAC_OSX) /* When using Carbon Events, we need to pass raw keyboard @@ -10365,45 +10606,21 @@ XTread_socket (sd, expected, hold_quit) will pass back noErr, otherwise it will pass back "eventNotHandledErr" and we can process it normally. */ - if ((mac_pass_command_to_system - || !(er.modifiers & cmdKey)) - && (mac_pass_control_to_system - || !(er.modifiers & controlKey)) - && (NILP (Vmac_option_modifier) - || !(er.modifiers & optionKey))) - if (SendEventToEventTarget (eventRef, toolbox_dispatcher) - != eventNotHandledErr) - break; -#endif - -#if 0 - if (dpyinfo->x_focus_frame == NULL) + if (!(mapped_modifiers + & ~(mac_pass_command_to_system ? cmdKey : 0) + & ~(mac_pass_control_to_system ? controlKey : 0))) { - /* Beep if keyboard input occurs when all the frames - are invisible. */ - SysBeep (1); - break; + OSStatus err; + + read_socket_inev = &inev; + err = SendEventToEventTarget (eventRef, toolbox_dispatcher); + read_socket_inev = NULL; + if (err != eventNotHandledErr) + break; } #endif - - { - static SInt16 last_key_script = -1; - SInt16 current_key_script = GetScriptManagerVariable (smKeyScript); - - if (last_key_script != current_key_script) - { - struct input_event event; - - EVENT_INIT (event); - event.kind = LANGUAGE_CHANGE_EVENT; - event.arg = Qnil; - event.code = current_key_script; - event.timestamp = timestamp; - kbd_buffer_store_event (&event); - count++; - } - last_key_script = current_key_script; - } + if (er.what == keyUp) + break; ObscureCursor (); @@ -10416,51 +10633,163 @@ XTread_socket (sd, expected, hold_quit) dpyinfo->mouse_face_hidden = 1; } - /* 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)) + current_key_script = GetScriptManagerVariable (smKeyScript); + if (last_key_script != current_key_script) { - 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; + struct input_event event; + + EVENT_INIT (event); + event.kind = LANGUAGE_CHANGE_EVENT; + event.arg = Qnil; + event.code = current_key_script; + event.timestamp = timestamp; + kbd_buffer_store_event (&event); + count++; + last_key_script = current_key_script; } - else + +#if USE_MAC_TSM + if (inev.kind != NO_EVENT) + break; #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 - inev.modifiers = mac_event_to_emacs_modifiers (eventRef); -#else - inev.modifiers = mac_to_emacs_modifiers (er.modifiers); +#ifdef MAC_OSX + if (mapped_modifiers & kEventKeyModifierFnMask + && keycode <= 0x7f + && fn_keycode_to_keycode_table[keycode]) + keycode = fn_keycode_to_keycode_table[keycode]; +#endif + if (keycode_to_xkeysym (keycode, &xkeysym)) + { + inev.kind = NON_ASCII_KEYSTROKE_EVENT; + inev.code = 0xff00 | xkeysym; +#ifdef MAC_OSX + if (modifiers & kEventKeyModifierFnMask + && keycode <= 0x7f + && fn_keycode_to_keycode_table[keycode] == keycode) + modifiers &= ~kEventKeyModifierFnMask; +#endif + } + else if (mapped_modifiers) + { + /* translate the keycode back to determine the + original key */ +#ifdef MAC_OSX + static SInt16 last_key_layout_id = 0; + static Handle uchr_handle = (Handle)-1; + SInt16 current_key_layout_id = + GetScriptVariable (current_key_script, smScriptKeys); + + if (uchr_handle == (Handle)-1 + || last_key_layout_id != current_key_layout_id) + { + uchr_handle = GetResource ('uchr', current_key_layout_id); + last_key_layout_id = current_key_layout_id; + } + + if (uchr_handle) + { + OSStatus status; + UInt16 key_action = er.what - keyDown; + UInt32 modifier_key_state = + (modifiers & ~mapped_modifiers) >> 8; + UInt32 keyboard_type = LMGetKbdType (); + SInt32 dead_key_state = 0; + UniChar code; + UniCharCount actual_length; + + status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle, + keycode, key_action, + modifier_key_state, + keyboard_type, + kUCKeyTranslateNoDeadKeysMask, + &dead_key_state, + 1, &actual_length, &code); + if (status == noErr && actual_length == 1) + mac_set_unicode_keystroke_event (code, &inev); + } +#endif /* MAC_OSX */ + + if (inev.kind == NO_EVENT) + { + /* 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. */ + /* Mask off modifier keys that are mapped to some + Emacs modifiers. */ + int new_modifiers = er.modifiers & ~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; + UInt32 new_char_code; + + new_char_code = KeyTranslate (kchr_ptr, new_keycode, + &some_state); + if (new_char_code == 0) + /* Seems like a dead key. Append up-stroke. */ + new_char_code = KeyTranslate (kchr_ptr, + new_keycode | 0x80, + &some_state); + if (new_char_code) + { + inev.kind = ASCII_KEYSTROKE_EVENT; + inev.code = new_char_code & 0xff; + } + } + } + + if (inev.kind == NO_EVENT) + { + inev.kind = ASCII_KEYSTROKE_EVENT; + inev.code = er.message & charCodeMask; + } + + inev.modifiers = mac_to_emacs_modifiers (modifiers); + inev.modifiers |= (extra_keyboard_modifiers + & (meta_modifier | alt_modifier + | hyper_modifier | super_modifier)); + XSETFRAME (inev.frame_or_window, f); + +#if TARGET_API_MAC_CARBON + if (inev.kind == ASCII_KEYSTROKE_EVENT + && inev.code >= 0x80 && inev.modifiers) + { + OSStatus err; + TextEncoding encoding = kTextEncodingMacRoman; + TextToUnicodeInfo ttu_info; + + UpgradeScriptInfoToTextEncoding (current_key_script, + kTextLanguageDontCare, + kTextRegionDontCare, + NULL, &encoding); + err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info); + if (err == noErr) + { + UniChar code; + Str255 pstr; + ByteCount unicode_len; + + pstr[0] = 1; + pstr[1] = inev.code; + err = ConvertFromPStringToUnicode (ttu_info, pstr, + sizeof (UniChar), + &unicode_len, &code); + if (err == noErr && unicode_len == sizeof (UniChar)) + mac_set_unicode_keystroke_event (code, &inev); + DisposeTextToUnicodeInfo (&ttu_info); + } + } #endif - inev.modifiers |= (extra_keyboard_modifiers - & (meta_modifier | alt_modifier - | hyper_modifier | super_modifier)); - XSETFRAME (inev.frame_or_window, f); + } break; case kHighLevelEvent: - read_socket_inev = &inev; AEProcessAppleEvent (&er); - read_socket_inev = NULL; break; default: @@ -10932,6 +11261,16 @@ init_menu_bar () #endif } +#if USE_MAC_TSM +static void +init_tsm () +{ + static InterfaceTypeList types = {kUnicodeDocument}; + + NewTSMDocument (sizeof (types) / sizeof (types[0]), types, + &tsm_document_id, 0); +} +#endif /* Set up use of X before we make the first connection. */ @@ -11026,6 +11365,10 @@ mac_initialize () init_command_handler (); init_menu_bar (); + +#if USE_MAC_TSM + init_tsm (); +#endif #endif /* USE_CARBON_EVENTS */ #ifdef MAC_OSX @@ -11082,6 +11425,13 @@ syms_of_macterm () Qpaste = intern ("paste"); staticpro (&Qpaste); Qperform = intern ("perform"); staticpro (&Qperform); #endif +#if USE_MAC_TSM + Qtext_input = intern ("text-input"); staticpro (&Qtext_input); + Qupdate_active_input_area = intern ("update-active-input-area"); + staticpro (&Qupdate_active_input_area); + Qunicode_for_key_event = intern ("unicode-for-key-event"); + staticpro (&Qunicode_for_key_event); +#endif #endif #ifdef MAC_OSX @@ -11224,6 +11574,11 @@ order. */); make_float (DEFAULT_REHASH_THRESHOLD), Qnil, Qnil, Qnil); #endif +#if USE_MAC_TSM + DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay, + doc: /* Overlay used to display Mac TSM active input area. */); + Vmac_ts_active_input_overlay = Qnil; +#endif } /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b diff --git a/src/macterm.h b/src/macterm.h index 8b45777e546..55bf583c214 100644 --- a/src/macterm.h +++ b/src/macterm.h @@ -539,6 +539,53 @@ struct scroll_bar { #define HOURGLASS_WIDTH 16 #define HOURGLASS_HEIGHT 16 +/* Some constants that are used locally. */ +/* Apple event descriptor types */ +enum { + TYPE_FILE_NAME = 'fNam' +}; + +/* Keywords for Apple event attributes */ +enum { + KEY_EMACS_SUSPENSION_ID_ATTR = 'esId' /* typeUInt32 */ +}; + +/* Carbon event parameter names. */ +enum { + EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER = 'tsSn' /* typeUInt32 */ +}; + +/* Some constants that are not defined in older versions. */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 +/* Keywords for Apple event attributes */ +enum { + keyReplyRequestedAttr = 'repq' +}; +#endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1040 +/* Gestalt selectors */ +enum { + gestaltSystemVersionMajor = 'sys1', + gestaltSystemVersionMinor = 'sys2', + gestaltSystemVersionBugFix = 'sys3' +}; +#endif + +#ifdef MAC_OSX +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1020 +/* Apple event descriptor types */ +enum { + typeUTF8Text = 'utf8' +}; + +/* Carbon event parameter names */ +enum { + kEventParamWindowMouseLocation = 'wmou' +}; +#endif +#endif + struct frame; struct face; struct image; @@ -584,6 +631,8 @@ extern void mac_draw_line_to_pixmap P_ ((Display *, Pixmap, GC, int, int, extern void mac_clear_area P_ ((struct frame *, int, int, unsigned int, unsigned int)); extern void mac_unload_font P_ ((struct mac_display_info *, XFontStruct *)); +extern int mac_font_panel_visible_p P_ ((void)); +extern OSStatus mac_show_hide_font_panel P_ ((void)); extern OSStatus mac_set_font_info_for_selection P_ ((struct frame *, int, int)); extern OSErr install_window_handler P_ ((WindowPtr)); extern void remove_window_handler P_ ((WindowPtr)); @@ -596,8 +645,6 @@ extern void mac_prepare_for_quickdraw P_ ((struct frame *)); #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 *)); @@ -615,6 +662,7 @@ extern int x_char_height P_ ((struct frame *)); extern void x_sync P_ ((struct frame *)); extern void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); extern void mac_update_title_bar P_ ((struct frame *, int)); +extern Lisp_Object x_get_focus_frame P_ ((struct frame *)); /* Defined in macmenu.c */ @@ -625,6 +673,7 @@ extern void free_frame_menubar P_ ((struct frame *)); extern void mac_clear_font_name_table P_ ((void)); extern Lisp_Object mac_aedesc_to_lisp P_ ((const AEDesc *)); +extern OSErr mac_ae_put_lisp P_ ((AEDescList *, UInt32, Lisp_Object)); #if TARGET_API_MAC_CARBON extern OSErr create_apple_event_from_event_ref P_ ((EventRef, UInt32, EventParamName *, diff --git a/src/minibuf.c b/src/minibuf.c index d37f82c9dcd..c5910b1771f 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -66,6 +66,10 @@ Lisp_Object Qhistory_length, Vhistory_length; int history_delete_duplicates; +/* Non-nil means add new input to history. */ + +Lisp_Object Vhistory_add_new_input; + /* Fread_minibuffer leaves the input here as a string. */ Lisp_Object last_minibuf_string; @@ -219,7 +223,7 @@ static Lisp_Object read_minibuf P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int, Lisp_Object, Lisp_Object, Lisp_Object, - int, int, int)); + int, int)); static Lisp_Object read_minibuf_noninteractive P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int, Lisp_Object, @@ -440,8 +444,7 @@ The current buffer must be a minibuffer. */) static Lisp_Object read_minibuf (map, initial, prompt, backup_n, expflag, - histvar, histpos, defalt, allow_props, inherit_input_method, - keep_all) + histvar, histpos, defalt, allow_props, inherit_input_method) Lisp_Object map; Lisp_Object initial; Lisp_Object prompt; @@ -452,7 +455,6 @@ read_minibuf (map, initial, prompt, backup_n, expflag, Lisp_Object defalt; int allow_props; int inherit_input_method; - int keep_all; { Lisp_Object val; int count = SPECPDL_INDEX (); @@ -747,7 +749,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag, last_minibuf_string = val; /* Choose the string to add to the history. */ - if (SCHARS (val) != 0 || keep_all) + if (SCHARS (val) != 0) histstring = val; else if (STRINGP (defalt)) histstring = defalt; @@ -755,7 +757,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histstring = Qnil; /* Add the value to the appropriate history list, if any. */ - if (SYMBOLP (Vminibuffer_history_variable) + if (!NILP (Vhistory_add_new_input) + && SYMBOLP (Vminibuffer_history_variable) && !NILP (histstring)) { /* If the caller wanted to save the value read on a history list, @@ -774,8 +777,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag, if (NILP (histval) || (CONSP (histval) /* Don't duplicate the most recent entry in the history. */ - && (keep_all - || NILP (Fequal (histstring, Fcar (histval)))))) + && (NILP (Fequal (histstring, Fcar (histval)))))) { Lisp_Object length; @@ -937,7 +939,7 @@ read_minibuf_unwind (data) } -DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 8, 0, +DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 7, 0, doc: /* Read a string from the minibuffer, prompting with string PROMPT. The optional second arg INITIAL-CONTENTS is an obsolete alternative to DEFAULT-VALUE. It normally should be nil in new code, except when @@ -961,8 +963,6 @@ Sixth arg DEFAULT-VALUE is the default value. If non-nil, it is available the empty string. Seventh arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits the current input method and the setting of `enable-multibyte-characters'. -Eight arg KEEP-ALL, if non-nil, says to put all inputs in the history list, - even empty or duplicate inputs. If the variable `minibuffer-allow-text-properties' is non-nil, then the string which is returned includes whatever text properties were present in the minibuffer. Otherwise the value has no text properties. @@ -978,9 +978,9 @@ POSITION in the minibuffer. Any integer value less than or equal to one puts point at the beginning of the string. *Note* that this behavior differs from the way such arguments are used in `completing-read' and some related functions, which use zero-indexing for POSITION. */) - (prompt, initial_contents, keymap, read, hist, default_value, inherit_input_method, keep_all) +(prompt, initial_contents, keymap, read, hist, default_value, inherit_input_method) Lisp_Object prompt, initial_contents, keymap, read, hist, default_value; - Lisp_Object inherit_input_method, keep_all; + Lisp_Object inherit_input_method; { Lisp_Object histvar, histpos, val; struct gcpro gcpro1; @@ -1011,8 +1011,7 @@ and some related functions, which use zero-indexing for POSITION. */) Qnil, !NILP (read), histvar, histpos, default_value, minibuffer_allow_text_properties, - !NILP (inherit_input_method), - !NILP (keep_all)); + !NILP (inherit_input_method)); UNGCPRO; return val; } @@ -1029,7 +1028,7 @@ arguments are used as in `read-from-minibuffer') */) CHECK_STRING (prompt); return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, Qnil, 1, Qminibuffer_history, - make_number (0), Qnil, 0, 0, 0); + make_number (0), Qnil, 0, 0); } DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0, @@ -1067,7 +1066,7 @@ Fifth arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits Lisp_Object val; val = Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil, history, default_value, - inherit_input_method, Qnil); + inherit_input_method); if (STRINGP (val) && SCHARS (val) == 0 && ! NILP (default_value)) val = default_value; return val; @@ -1089,7 +1088,7 @@ the current input method and the setting of`enable-multibyte-characters'. */) CHECK_STRING (prompt); return read_minibuf (Vminibuffer_local_ns_map, initial, prompt, Qnil, 0, Qminibuffer_history, make_number (0), Qnil, 0, - !NILP (inherit_input_method), 0); + !NILP (inherit_input_method)); } DEFUN ("read-command", Fread_command, Sread_command, 1, 2, 0, @@ -1778,7 +1777,7 @@ Completion ignores case if the ambient value of : Vminibuffer_local_must_match_filename_map), init, prompt, make_number (pos), 0, histvar, histpos, def, 0, - !NILP (inherit_input_method), 0); + !NILP (inherit_input_method)); if (STRINGP (val) && SCHARS (val) == 0 && ! NILP (def)) val = def; @@ -2797,9 +2796,16 @@ property of a history variable overrides this default. */); DEFVAR_BOOL ("history-delete-duplicates", &history_delete_duplicates, doc: /* *Non-nil means to delete duplicates in history. If set to t when adding a new history element, all previous identical -elements are deleted. */); +elements are deleted from the history list. */); history_delete_duplicates = 0; + DEFVAR_LISP ("history-add-new-input", &Vhistory_add_new_input, + doc: /* *Non-nil means to add new elements in history. +If set to nil, minibuffer reading functions don't add new elements to the +history list, so it is possible to do this afterwards by calling +`add-to-history' explicitly. */); + Vhistory_add_new_input = Qt; + DEFVAR_LISP ("completion-auto-help", &Vcompletion_auto_help, 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; diff --git a/src/process.c b/src/process.c index 1960e6a914c..2281f1ce3f6 100644 --- a/src/process.c +++ b/src/process.c @@ -777,6 +777,16 @@ get_process (name) return proc; } + +#ifdef SIGCHLD +/* Fdelete_process promises to immediately forget about the process, but in + reality, Emacs needs to remember those processes until they have been + treated by sigchld_handler; otherwise this handler would consider the + process as being synchronous and say that the synchronous process is + dead. */ +static Lisp_Object deleted_pid_list; +#endif + DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0, doc: /* Delete PROCESS: kill it and forget about it immediately. PROCESS may be a process, a buffer, the name of a process or buffer, or @@ -798,12 +808,31 @@ nil, indicating the current buffer's process. */) } else if (XINT (p->infd) >= 0) { - Fkill_process (process, Qnil); - /* Do this now, since remove_process will make sigchld_handler do nothing. */ - p->status - = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)); - XSETINT (p->tick, ++process_tick); - status_notify (p); +#ifdef SIGCHLD + Lisp_Object symbol; + + /* No problem storing the pid here, as it is still in Vprocess_alist. */ + deleted_pid_list = Fcons (make_fixnum_or_float (p->pid), + /* GC treated elements set to nil. */ + Fdelq (Qnil, deleted_pid_list)); + /* If the process has already signaled, remove it from the list. */ + if (p->raw_status_new) + update_status (p); + symbol = p->status; + if (CONSP (p->status)) + symbol = XCAR (p->status); + if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)) + Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list); + else +#endif + { + Fkill_process (process, Qnil); + /* Do this now, since remove_process will make sigchld_handler do nothing. */ + p->status + = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)); + XSETINT (p->tick, ++process_tick); + status_notify (p); + } } remove_process (process); return Qnil; @@ -4134,6 +4163,25 @@ wait_reading_process_output_1 () { } +/* Use a wrapper around select to work around a bug in gdb 5.3. + Normally, the wrapper is optimzed away by inlining. + + If emacs is stopped inside select, the gdb backtrace doesn't + show the function which called select, so it is practically + impossible to step through wait_reading_process_output. */ + +#ifndef select +static INLINE int +select_wrapper (n, rfd, wfd, xfd, tmo) + int n; + SELECT_TYPE *rfd, *wfd, *xfd; + EMACS_TIME *tmo; +{ + return select (n, rfd, wfd, xfd, tmo); +} +#define select select_wrapper +#endif + /* Read and dispose of subprocess output while waiting for timeout to elapse and/or keyboard input to be available. @@ -6304,6 +6352,7 @@ kill_buffer_processes (buffer) ** Malloc WARNING: This should never call malloc either directly or indirectly; if it does, that is a bug */ +#ifdef SIGCHLD SIGTYPE sigchld_handler (signo) int signo; @@ -6361,6 +6410,15 @@ sigchld_handler (signo) /* Find the process that signaled us, and record its status. */ + /* The process can have been deleted by Fdelete_process. */ + tail = Fmember (make_fixnum_or_float (pid), deleted_pid_list); + if (!NILP (tail)) + { + Fsetcar (tail, Qnil); + goto sigchld_end_of_loop; + } + + /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ p = 0; for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail)) { @@ -6412,8 +6470,8 @@ sigchld_handler (signo) EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0); } - /* There was no asynchronous process found for that id. Check - if we have a synchronous process. */ + /* There was no asynchronous process found for that pid: we have + a synchronous process. */ else { synch_process_alive = 0; @@ -6430,6 +6488,9 @@ sigchld_handler (signo) EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0); } + sigchld_end_of_loop: + ; + /* On some systems, we must return right away. If any more processes want to signal us, we will get another signal. @@ -6446,6 +6507,7 @@ sigchld_handler (signo) #endif /* USG, but not HPUX with WNOHANG */ } } +#endif /* SIGCHLD */ static Lisp_Object @@ -6831,6 +6893,9 @@ init_process () FD_SET (0, &input_wait_mask); Vprocess_alist = Qnil; +#ifdef SIGCHLD + deleted_pid_list = Qnil; +#endif for (i = 0; i < MAXDESC; i++) { chan_process[i] = Qnil; @@ -6969,6 +7034,9 @@ syms_of_process () staticpro (&Qlast_nonmenu_event); staticpro (&Vprocess_alist); +#ifdef SIGCHLD + staticpro (&deleted_pid_list); +#endif DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes, doc: /* *Non-nil means delete processes immediately when they exit. diff --git a/src/puresize.h b/src/puresize.h index 1288feff151..67e758ae799 100644 --- a/src/puresize.h +++ b/src/puresize.h @@ -43,7 +43,7 @@ Boston, MA 02110-1301, USA. */ #endif #ifndef BASE_PURESIZE -#define BASE_PURESIZE (1205000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) +#define BASE_PURESIZE (1210000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) #endif /* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ diff --git a/src/search.c b/src/search.c index f613630eaf9..15cc51cb511 100644 --- a/src/search.c +++ b/src/search.c @@ -90,6 +90,7 @@ static void save_search_regs (); static int simple_search (); static int boyer_moore (); static int search_buffer (); +static void matcher_overflow () NO_RETURN; static void matcher_overflow () diff --git a/src/sound.c b/src/sound.c index 0fbeceb4b9e..af2369040cc 100644 --- a/src/sound.c +++ b/src/sound.c @@ -73,6 +73,10 @@ Boston, MA 02110-1301, USA. */ #ifdef HAVE_SOUNDCARD_H #include <soundcard.h> #endif +#ifdef HAVE_ALSA +#include <asoundlib.h> +#endif + /* END: Non Windows Includes */ #else /* WINDOWSNT */ @@ -109,7 +113,8 @@ enum sound_attr SOUND_ATTR_SENTINEL }; -static void sound_perror P_ ((char *)); +static void alsa_sound_perror P_ ((char *, int)) NO_RETURN; +static void sound_perror P_ ((char *)) NO_RETURN; static void sound_warning P_ ((char *)); static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); @@ -121,6 +126,9 @@ static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); #ifndef DEFAULT_SOUND_DEVICE #define DEFAULT_SOUND_DEVICE "/dev/dsp" #endif +#ifndef DEFAULT_ALSA_SOUND_DEVICE +#define DEFAULT_ALSA_SOUND_DEVICE "default" +#endif /* Structure forward declarations. */ @@ -227,6 +235,10 @@ struct sound_device void (* choose_format) P_ ((struct sound_device *sd, struct sound *s)); + /* Return a preferred data size in bytes to be sent to write (below) + each time. 2048 is used if this is NULL. */ + int (* period_size) P_ ((struct sound_device *sd)); + /* Write NYBTES bytes from BUFFER to device SD. */ void (* write) P_ ((struct sound_device *sd, const char *buffer, int nbytes)); @@ -280,7 +292,7 @@ static void vox_open P_ ((struct sound_device *)); static void vox_configure P_ ((struct sound_device *)); static void vox_close P_ ((struct sound_device *sd)); static void vox_choose_format P_ ((struct sound_device *, struct sound *)); -static void vox_init P_ ((struct sound_device *)); +static int vox_init P_ ((struct sound_device *)); static void vox_write P_ ((struct sound_device *, const char *, int)); static void find_sound_type P_ ((struct sound *)); static u_int32_t le2hl P_ ((u_int32_t)); @@ -604,7 +616,7 @@ wav_play (s, sd) { char *buffer; int nbytes; - int blksize = 2048; + int blksize = sd->period_size ? sd->period_size (sd) : 2048; buffer = (char *) alloca (blksize); lseek (s->fd, sizeof *header, SEEK_SET); @@ -633,7 +645,8 @@ enum au_encoding AU_ENCODING_32, AU_ENCODING_IEEE32, AU_ENCODING_IEEE64, - AU_COMPRESSED = 23 + AU_COMPRESSED = 23, + AU_ENCODING_ALAW_8 = 27 }; @@ -689,7 +702,7 @@ au_play (s, sd) SBYTES (s->data) - header->data_offset); else { - int blksize = 2048; + int blksize = sd->period_size ? sd->period_size (sd) : 2048; char *buffer; int nbytes; @@ -868,16 +881,33 @@ vox_choose_format (sd, s) /* Initialize device SD. Set up the interface functions in the device structure. */ -static void +static int vox_init (sd) struct sound_device *sd; { + char *file; + int fd; + + /* Open the sound device. Default is /dev/dsp. */ + if (sd->file) + file = sd->file; + else + file = DEFAULT_SOUND_DEVICE; + fd = emacs_open (file, O_WRONLY, 0); + if (fd >= 0) + emacs_close (fd); + else + return 0; + sd->fd = -1; sd->open = vox_open; sd->close = vox_close; sd->configure = vox_configure; sd->choose_format = vox_choose_format; sd->write = vox_write; + sd->period_size = NULL; + + return 1; } /* Write NBYTES bytes from BUFFER to device SD. */ @@ -893,6 +923,368 @@ vox_write (sd, buffer, nbytes) sound_perror ("Error writing to sound device"); } +#ifdef HAVE_ALSA +/*********************************************************************** + ALSA Driver Interface + ***********************************************************************/ + +/* This driver is available on GNU/Linux. */ + +static void +alsa_sound_perror (msg, err) + char *msg; + int err; +{ + error ("%s: %s", msg, snd_strerror (err)); +} + +struct alsa_params +{ + snd_pcm_t *handle; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + snd_pcm_uframes_t period_size; +}; + +/* Open device SD. If SD->file is non-null, open that device, + otherwise use a default device name. */ + +static void +alsa_open (sd) + struct sound_device *sd; +{ + char *file; + struct alsa_params *p; + int err; + + /* Open the sound device. Default is "default". */ + if (sd->file) + file = sd->file; + else + file = DEFAULT_ALSA_SOUND_DEVICE; + + p = xmalloc (sizeof (*p)); + p->handle = NULL; + p->hwparams = NULL; + p->swparams = NULL; + + sd->fd = -1; + sd->data = p; + + + err = snd_pcm_open (&p->handle, file, SND_PCM_STREAM_PLAYBACK, 0); + if (err < 0) + alsa_sound_perror (file, err); +} + +static int +alsa_period_size (sd) + struct sound_device *sd; +{ + struct alsa_params *p = (struct alsa_params *) sd->data; + return p->period_size; +} + +static void +alsa_configure (sd) + struct sound_device *sd; +{ + int val, err, dir; + struct alsa_params *p = (struct alsa_params *) sd->data; + snd_pcm_uframes_t buffer_size; + + xassert (p->handle != 0); + + err = snd_pcm_hw_params_malloc (&p->hwparams); + if (err < 0) + alsa_sound_perror ("Could not allocate hardware parameter structure", err); + + err = snd_pcm_sw_params_malloc (&p->swparams); + if (err < 0) + alsa_sound_perror ("Could not allocate software parameter structure", err); + + err = snd_pcm_hw_params_any (p->handle, p->hwparams); + if (err < 0) + alsa_sound_perror ("Could not initialize hardware parameter structure", err); + + err = snd_pcm_hw_params_set_access (p->handle, p->hwparams, + SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) + alsa_sound_perror ("Could not set access type", err); + + val = sd->format; + err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val); + if (err < 0) + alsa_sound_perror ("Could not set sound format", err); + + val = sd->sample_rate; + err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &val, 0); + if (err < 0) + alsa_sound_perror ("Could not set sample rate", err); + + val = sd->channels; + err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val); + if (err < 0) + alsa_sound_perror ("Could not set channel count", err); + + err = snd_pcm_hw_params (p->handle, p->hwparams); + if (err < 0) + alsa_sound_perror ("Could not set parameters", err); + + + err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir); + if (err < 0) + alsa_sound_perror ("Unable to get period size for playback", err); + + err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size); + if (err < 0) + alsa_sound_perror("Unable to get buffer size for playback", err); + + err = snd_pcm_sw_params_current (p->handle, p->swparams); + if (err < 0) + alsa_sound_perror ("Unable to determine current swparams for playback", + err); + + /* Start the transfer when the buffer is almost full */ + err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams, + (buffer_size / p->period_size) + * p->period_size); + if (err < 0) + alsa_sound_perror ("Unable to set start threshold mode for playback", err); + + /* Allow the transfer when at least period_size samples can be processed */ + err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size); + if (err < 0) + alsa_sound_perror ("Unable to set avail min for playback", err); + + /* Align all transfers to 1 period */ + err = snd_pcm_sw_params_set_xfer_align (p->handle, p->swparams, + p->period_size); + if (err < 0) + alsa_sound_perror ("Unable to set transfer align for playback", err); + + err = snd_pcm_sw_params (p->handle, p->swparams); + if (err < 0) + alsa_sound_perror ("Unable to set sw params for playback\n", err); + + snd_pcm_hw_params_free (p->hwparams); + p->hwparams = NULL; + snd_pcm_sw_params_free (p->swparams); + p->swparams = NULL; + + err = snd_pcm_prepare (p->handle); + if (err < 0) + alsa_sound_perror ("Could not prepare audio interface for use", err); + + if (sd->volume > 0) + { + int chn; + snd_mixer_t *handle; + snd_mixer_elem_t *e; + char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE; + + if (snd_mixer_open (&handle, 0) >= 0) + { + if (snd_mixer_attach (handle, file) >= 0 + && snd_mixer_load (handle) >= 0 + && snd_mixer_selem_register (handle, NULL, NULL) >= 0) + for (e = snd_mixer_first_elem (handle); + e; + e = snd_mixer_elem_next (e)) + { + if (snd_mixer_selem_has_playback_volume (e)) + { + long pmin, pmax; + snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax); + long vol = pmin + (sd->volume * (pmax - pmin)) / 100; + + for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) + snd_mixer_selem_set_playback_volume (e, chn, vol); + } + } + snd_mixer_close(handle); + } + } +} + + +/* Close device SD if it is open. */ + +static void +alsa_close (sd) + struct sound_device *sd; +{ + struct alsa_params *p = (struct alsa_params *) sd->data; + if (p) + { + if (p->hwparams) + snd_pcm_hw_params_free (p->hwparams); + if (p->swparams) + snd_pcm_sw_params_free (p->swparams); + if (p->handle) + { + snd_pcm_drain(p->handle); + snd_pcm_close (p->handle); + } + free (p); + } +} + +/* Choose device-dependent format for device SD from sound file S. */ + +static void +alsa_choose_format (sd, s) + struct sound_device *sd; + struct sound *s; +{ + struct alsa_params *p = (struct alsa_params *) sd->data; + if (s->type == RIFF) + { + struct wav_header *h = (struct wav_header *) s->header; + if (h->precision == 8) + sd->format = SND_PCM_FORMAT_U8; + else if (h->precision == 16) + sd->format = SND_PCM_FORMAT_S16_LE; + else + error ("Unsupported WAV file format"); + } + else if (s->type == SUN_AUDIO) + { + struct au_header *header = (struct au_header *) s->header; + switch (header->encoding) + { + case AU_ENCODING_ULAW_8: + sd->format = SND_PCM_FORMAT_MU_LAW; + break; + case AU_ENCODING_ALAW_8: + sd->format = SND_PCM_FORMAT_A_LAW; + break; + case AU_ENCODING_IEEE32: + sd->format = SND_PCM_FORMAT_FLOAT_BE; + break; + case AU_ENCODING_IEEE64: + sd->format = SND_PCM_FORMAT_FLOAT64_BE; + break; + case AU_ENCODING_8: + sd->format = SND_PCM_FORMAT_S8; + break; + case AU_ENCODING_16: + sd->format = SND_PCM_FORMAT_S16_BE; + break; + case AU_ENCODING_24: + sd->format = SND_PCM_FORMAT_S24_BE; + break; + case AU_ENCODING_32: + sd->format = SND_PCM_FORMAT_S32_BE; + break; + + default: + error ("Unsupported AU file format"); + } + } + else + abort (); +} + + +/* Write NBYTES bytes from BUFFER to device SD. */ + +static void +alsa_write (sd, buffer, nbytes) + struct sound_device *sd; + const char *buffer; + int nbytes; +{ + struct alsa_params *p = (struct alsa_params *) sd->data; + + /* The the third parameter to snd_pcm_writei is frames, not bytes. */ + int fact = snd_pcm_format_size (sd->format, 1) * sd->channels; + int nwritten = 0; + int err; + + while (nwritten < nbytes) + { + err = snd_pcm_writei (p->handle, + buffer + nwritten, + (nbytes - nwritten)/fact); + if (err < 0) + { + if (err == -EPIPE) + { /* under-run */ + err = snd_pcm_prepare (p->handle); + if (err < 0) + alsa_sound_perror ("Can't recover from underrun, prepare failed", + err); + } + else if (err == -ESTRPIPE) + { + while ((err = snd_pcm_resume (p->handle)) == -EAGAIN) + sleep(1); /* wait until the suspend flag is released */ + if (err < 0) + { + err = snd_pcm_prepare (p->handle); + if (err < 0) + alsa_sound_perror ("Can't recover from suspend, " + "prepare failed", + err); + } + } + else + alsa_sound_perror ("Error writing to sound device", err); + + } + else + nwritten += err * fact; + } +} + +static void +snd_error_quiet (file, line, function, err, fmt) + const char *file; + int line; + const char *function; + int err; + const char *fmt; +{ +} + +/* Initialize device SD. Set up the interface functions in the device + structure. */ + +static int +alsa_init (sd) + struct sound_device *sd; +{ + char *file; + snd_pcm_t *handle; + int err; + + /* Open the sound device. Default is "default". */ + if (sd->file) + file = sd->file; + else + file = DEFAULT_ALSA_SOUND_DEVICE; + + snd_lib_error_set_handler ((snd_lib_error_handler_t) snd_error_quiet); + err = snd_pcm_open (&handle, file, SND_PCM_STREAM_PLAYBACK, 0); + snd_lib_error_set_handler (NULL); + if (err < 0) + return 0; + + sd->fd = -1; + sd->open = alsa_open; + sd->close = alsa_close; + sd->configure = alsa_configure; + sd->choose_format = alsa_choose_format; + sd->write = alsa_write; + sd->period_size = alsa_period_size; + + return 1; +} + +#endif /* HAVE_ALSA */ + + /* END: Non Windows functions */ #else /* WINDOWSNT */ @@ -1056,10 +1448,11 @@ Internal use only, use `play-sound' instead.\n */) args[1] = sound; Frun_hook_with_args (2, args); - /* There is only one type of device we currently support, the VOX - sound driver. Set up the device interface functions for that - device. */ - vox_init (current_sound_device); +#ifdef HAVE_ALSA + if (!alsa_init (current_sound_device)) +#endif + if (!vox_init (current_sound_device)) + error ("No usable sound device driver found"); /* Open the device. */ current_sound_device->open (current_sound_device); diff --git a/src/sysdep.c b/src/sysdep.c index 3e06170e721..307f69290d6 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -244,7 +244,7 @@ int emacs_ospeed; under VMS, we place the input channel number here. */ int input_fd; -void croak P_ ((char *)); +void croak P_ ((char *)) NO_RETURN; #ifdef AIXHFT void hft_init (); diff --git a/src/w32.c b/src/w32.c index 71799befdbb..f11ffb7a785 100644 --- a/src/w32.c +++ b/src/w32.c @@ -950,11 +950,11 @@ init_environment (char ** argv) struct stat ignored; char default_home[MAX_PATH]; - static struct env_entry + static const struct env_entry { char * name; char * def_value; - } env_vars[] = + } dflt_envvars[] = { {"HOME", "C:/"}, {"PRELOAD_WINSOCK", NULL}, @@ -971,6 +971,17 @@ init_environment (char ** argv) {"LANG", NULL}, }; +#define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0]) + + /* We need to copy dflt_envvars[] and work on the copy because we + don't want the dumped Emacs to inherit the values of + environment variables we saw during dumping (which could be on + a different system). The defaults above must be left intact. */ + struct env_entry env_vars[N_ENV_VARS]; + + for (i = 0; i < N_ENV_VARS; i++) + env_vars[i] = dflt_envvars[i]; + /* For backwards compatibility, check if a .emacs file exists in C:/ If not, then we can try to default to the appdata directory under the user's profile, which is more likely to be writable. */ @@ -1005,7 +1016,7 @@ init_environment (char ** argv) LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP, locale_name, sizeof (locale_name))) { - for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) + for (i = 0; i < N_ENV_VARS; i++) { if (strcmp (env_vars[i].name, "LANG") == 0) { @@ -1069,7 +1080,7 @@ init_environment (char ** argv) } } - for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) + for (i = 0; i < N_ENV_VARS; i++) { if (!getenv (env_vars[i].name)) { @@ -1084,20 +1095,17 @@ init_environment (char ** argv) if (lpval) { - if (dwType == REG_EXPAND_SZ) - { - char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE]; + char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE]; - ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1)); - _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name, buf1); - _putenv (strdup (buf2)); - } + if (dwType == REG_EXPAND_SZ) + ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1)); else if (dwType == REG_SZ) + strcpy (buf1, lpval); + if (dwType == REG_EXPAND_SZ || dwType == REG_SZ) { - char buf[SET_ENV_BUF_SIZE]; - - _snprintf (buf, sizeof(buf)-1, "%s=%s", env_vars[i].name, lpval); - _putenv (strdup (buf)); + _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name, + buf1); + _putenv (strdup (buf2)); } if (!dont_free) diff --git a/src/w32fns.c b/src/w32fns.c index 4da5271c870..aa83e006194 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -1684,7 +1684,7 @@ x_set_icon_name (f, arg, oldval) if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) return; } - else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) + else if (!NILP (arg) || NILP (oldval)) return; f->icon_name = arg; diff --git a/src/w32heap.c b/src/w32heap.c index f1fa196abe7..e1bdd867721 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -42,10 +42,6 @@ OSVERSIONINFO osinfo_cache; unsigned long syspage_mask = 0; -/* These are defined to get Emacs to compile, but are not used. */ -int edata; -int etext; - /* The major and minor versions of NT. */ int w32_major_version; int w32_minor_version; diff --git a/src/w32term.c b/src/w32term.c index 305527946fb..0a7007cc8f4 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -173,32 +173,6 @@ HANDLE hWindowsThread = NULL; DWORD dwMainThreadId = 0; HANDLE hMainThread = NULL; -#ifndef SIF_ALL -/* These definitions are new with Windows 95. */ -#define SIF_RANGE 0x0001 -#define SIF_PAGE 0x0002 -#define SIF_POS 0x0004 -#define SIF_DISABLENOSCROLL 0x0008 -#define SIF_TRACKPOS 0x0010 -#define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS) - -typedef struct tagSCROLLINFO -{ - UINT cbSize; - UINT fMask; - int nMin; - int nMax; - UINT nPage; - int nPos; - int nTrackPos; -} SCROLLINFO, FAR *LPSCROLLINFO; -typedef SCROLLINFO CONST FAR *LPCSCROLLINFO; -#endif /* SIF_ALL */ - -/* Dynamic linking to new proportional scroll bar functions. */ -int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw); -BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi); - int vertical_scroll_bar_min_handle; int vertical_scroll_bar_top_border; int vertical_scroll_bar_bottom_border; @@ -2540,20 +2514,29 @@ x_draw_stretch_glyph_string (s) { /* If `x-stretch-block-cursor' is nil, don't draw a block cursor as wide as the stretch glyph. */ - int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width); + int width, background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + width = min (FRAME_COLUMN_WIDTH (s->f), background_width); /* Draw cursor. */ - x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height); + x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height); /* Clear rest using the GC of the original non-cursor face. */ - if (width < s->background_width) + if (width < background_width) { XGCValues *gc = s->face->gc; - int x = s->x + width, y = s->y; - int w = s->background_width - width, h = s->height; + int y = s->y; + int w = background_width - width, h = s->height; RECT r; HDC hdc = s->hdc; + x += width; if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) { @@ -2582,8 +2565,18 @@ x_draw_stretch_glyph_string (s) } } else if (!s->background_filled_p) - x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width, - s->height); + { + int background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + if (background_width > 0) + x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); + } s->background_filled_p = 1; } @@ -3619,6 +3612,7 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole) double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); int sb_page, sb_pos; BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE; + SCROLLINFO si; if (whole) { @@ -3643,24 +3637,17 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole) BLOCK_INPUT; - if (pfnSetScrollInfo) - { - SCROLLINFO si; - - si.cbSize = sizeof (si); - /* Only update page size if currently dragging, to reduce - flicker effects. */ - if (draggingp) - si.fMask = SIF_PAGE; - else - si.fMask = SIF_PAGE | SIF_POS; - si.nPage = sb_page; - si.nPos = sb_pos; - - pfnSetScrollInfo (w, SB_CTL, &si, !draggingp); - } + si.cbSize = sizeof (si); + /* Only update page size if currently dragging, to reduce + flicker effects. */ + if (draggingp) + si.fMask = SIF_PAGE; else - SetScrollPos (w, SB_CTL, sb_pos, !draggingp); + si.fMask = SIF_PAGE | SIF_POS; + si.nPage = sb_page; + si.nPos = sb_pos; + + SetScrollInfo (w, SB_CTL, &si, !draggingp); UNBLOCK_INPUT; } @@ -3749,6 +3736,7 @@ x_scroll_bar_create (w, top, left, width, height) { struct frame *f = XFRAME (WINDOW_FRAME (w)); HWND hwnd; + SCROLLINFO si; struct scroll_bar *bar = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil)); @@ -3767,26 +3755,15 @@ x_scroll_bar_create (w, top, left, width, height) hwnd = my_create_scrollbar (f, bar); - if (pfnSetScrollInfo) - { - SCROLLINFO si; - - si.cbSize = sizeof (si); - si.fMask = SIF_ALL; - si.nMin = 0; - si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) - + VERTICAL_SCROLL_BAR_MIN_HANDLE; - si.nPage = si.nMax; - si.nPos = 0; + si.cbSize = sizeof (si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) + + VERTICAL_SCROLL_BAR_MIN_HANDLE; + si.nPage = si.nMax; + si.nPos = 0; - pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE); - } - else - { - SetScrollRange (hwnd, SB_CTL, 0, - VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE); - SetScrollPos (hwnd, SB_CTL, 0, FALSE); - } + SetScrollInfo (hwnd, SB_CTL, &si, FALSE); SET_SCROLL_BAR_W32_WINDOW (bar, hwnd); @@ -3895,6 +3872,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) else { HDC hdc; + SCROLLINFO si; + BLOCK_INPUT; if (width && height) { @@ -3914,21 +3893,15 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, max (height, 1), TRUE); - if (pfnSetScrollInfo) - { - SCROLLINFO si; - si.cbSize = sizeof (si); - si.fMask = SIF_RANGE; - si.nMin = 0; - si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) - + VERTICAL_SCROLL_BAR_MIN_HANDLE; + si.cbSize = sizeof (si); + si.fMask = SIF_RANGE; + si.nMin = 0; + si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) + + VERTICAL_SCROLL_BAR_MIN_HANDLE; + + SetScrollInfo (hwnd, SB_CTL, &si, FALSE); - pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE); - } - else - SetScrollRange (hwnd, SB_CTL, 0, - VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE); my_show_window (f, hwnd, SW_NORMAL); /* InvalidateRect (w, NULL, FALSE); */ @@ -4080,19 +4053,13 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event) int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); int y; int dragging = !NILP (bar->dragging); + SCROLLINFO si; - if (pfnGetScrollInfo) - { - SCROLLINFO si; - - si.cbSize = sizeof (si); - si.fMask = SIF_POS; + si.cbSize = sizeof (si); + si.fMask = SIF_POS; - pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si); - y = si.nPos; - } - else - y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL); + GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si); + y = si.nPos; bar->dragging = Qnil; @@ -4129,21 +4096,18 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event) emacs_event->part = scroll_bar_handle; /* "Silently" update current position. */ - if (pfnSetScrollInfo) - { - SCROLLINFO si; + { + SCROLLINFO si; - si.cbSize = sizeof (si); - si.fMask = SIF_POS; - si.nPos = y; - /* Remember apparent position (we actually lag behind the real - position, so don't set that directly. */ - last_scroll_bar_drag_pos = y; + si.cbSize = sizeof (si); + si.fMask = SIF_POS; + si.nPos = y; + /* Remember apparent position (we actually lag behind the real + position, so don't set that directly. */ + last_scroll_bar_drag_pos = y; - pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE); - } - else - SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE); + SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE); + } break; case SB_ENDSCROLL: /* If this is the end of a drag sequence, then reset the scroll @@ -4151,20 +4115,15 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event) nothing. */ if (dragging) { - if (pfnSetScrollInfo) - { - SCROLLINFO si; - int start = XINT (bar->start); - int end = XINT (bar->end); + SCROLLINFO si; + int start = XINT (bar->start); + int end = XINT (bar->end); - si.cbSize = sizeof (si); - si.fMask = SIF_PAGE | SIF_POS; - si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE; - si.nPos = last_scroll_bar_drag_pos; - pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE); - } - else - SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE); + si.cbSize = sizeof (si); + si.fMask = SIF_PAGE | SIF_POS; + si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE; + si.nPos = last_scroll_bar_drag_pos; + SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE); } /* fall through */ default: @@ -4195,25 +4154,19 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); int pos; int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); + SCROLLINFO si; BLOCK_INPUT; *fp = f; *bar_window = bar->window; - if (pfnGetScrollInfo) - { - SCROLLINFO si; - - si.cbSize = sizeof (si); - si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; + si.cbSize = sizeof (si); + si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; - pfnGetScrollInfo (w, SB_CTL, &si); - pos = si.nPos; - top_range = si.nMax - si.nPage + 1; - } - else - pos = GetScrollPos (w, SB_CTL); + GetScrollInfo (w, SB_CTL, &si); + pos = si.nPos; + top_range = si.nMax - si.nPage + 1; switch (LOWORD (last_mouse_scroll_bar_pos)) { @@ -5082,7 +5035,7 @@ x_draw_hollow_cursor (w, row) struct frame *f = XFRAME (WINDOW_FRAME (w)); HDC hdc; RECT rect; - int h; + int left, top, h; struct glyph *cursor_glyph; HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel); @@ -5093,8 +5046,9 @@ x_draw_hollow_cursor (w, row) return; /* Compute frame-relative coordinates for phys cursor. */ - rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h); + get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h); + rect.left = left; + rect.top = top; rect.bottom = rect.top + h; rect.right = rect.left + w->phys_cursor_width; diff --git a/src/window.c b/src/window.c index 1abeec92367..59c223b4a8f 100644 --- a/src/window.c +++ b/src/window.c @@ -3778,7 +3778,9 @@ SIZE includes that window's scroll bar, or the divider column to its right. Interactively, all arguments are nil. Returns the newly created window (which is the lower or rightmost one). -The upper or leftmost window is the original one and remains selected. +The upper or leftmost window is the original one, and remains selected +if it was selected before. + See Info node `(elisp)Splitting Windows' for more details and examples.*/) (window, size, horflag) Lisp_Object window, size, horflag; @@ -5794,6 +5796,7 @@ struct saved_window Lisp_Object left_margin_cols, right_margin_cols; Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins; Lisp_Object scroll_bar_width, vertical_scroll_bar_type; + Lisp_Object dedicated; }; #define SAVED_WINDOW_N(swv,n) \ @@ -5804,9 +5807,7 @@ DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_ (object) Lisp_Object object; { - if (WINDOW_CONFIGURATIONP (object)) - return Qt; - return Qnil; + return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil; } DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0, @@ -6028,6 +6029,7 @@ the return value is nil. Otherwise the value is t. */) w->fringes_outside_margins = p->fringes_outside_margins; w->scroll_bar_width = p->scroll_bar_width; w->vertical_scroll_bar_type = p->vertical_scroll_bar_type; + w->dedicated = p->dedicated; XSETFASTINT (w->last_modified, 0); XSETFASTINT (w->last_overlay_modified, 0); @@ -6297,6 +6299,7 @@ save_window_save (window, vector, i) p->fringes_outside_margins = w->fringes_outside_margins; p->scroll_bar_width = w->scroll_bar_width; p->vertical_scroll_bar_type = w->vertical_scroll_bar_type; + p->dedicated = w->dedicated; if (!NILP (w->buffer)) { /* Save w's value of point in the window configuration. @@ -6796,7 +6799,9 @@ foreach_window (f, fn, user_data) int (* fn) P_ ((struct window *, void *)); void *user_data; { - foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data); + /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */ + if (WINDOWP (FRAME_ROOT_WINDOW (f))) + foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data); } diff --git a/src/xdisp.c b/src/xdisp.c index 9b5b913938b..0cb34a2fef8 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1995,15 +1995,15 @@ get_glyph_string_clip_rect (s, nr) Set w->phys_cursor_width to width of phys cursor. */ -int -get_phys_cursor_geometry (w, row, glyph, heightp) +void +get_phys_cursor_geometry (w, row, glyph, xp, yp, heightp) struct window *w; struct glyph_row *row; struct glyph *glyph; - int *heightp; + int *xp, *yp, *heightp; { struct frame *f = XFRAME (WINDOW_FRAME (w)); - int y, wd, h, h0, y0; + int x, y, wd, h, h0, y0; /* Compute the width of the rectangle to draw. If on a stretch glyph, and `x-stretch-block-cursor' is nil, don't draw a @@ -2013,6 +2013,14 @@ get_phys_cursor_geometry (w, row, glyph, heightp) #ifdef HAVE_NTGUI wd++; /* Why? */ #endif + + x = w->phys_cursor.x; + if (x < 0) + { + wd += x; + x = 0; + } + if (glyph->type == STRETCH_GLYPH && !x_stretch_cursor_p) wd = min (FRAME_COLUMN_WIDTH (f), wd); @@ -2042,8 +2050,9 @@ get_phys_cursor_geometry (w, row, glyph, heightp) } } + *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x); + *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y); *heightp = h; - return WINDOW_TO_FRAME_PIXEL_Y (w, y); } /* @@ -6334,6 +6343,8 @@ next_element_from_composition (it) it->position = (STRINGP (it->string) ? it->current.string_pos : it->current.pos); + if (STRINGP (it->string)) + it->object = it->string; return 1; } @@ -9608,7 +9619,8 @@ display_tool_bar_line (it, height) while (it->current_x < max_x) { - int x_before, x, n_glyphs_before, i, nglyphs; + int x, n_glyphs_before, i, nglyphs; + struct it it_before; /* Get the next display element. */ if (!get_next_display_element (it)) @@ -9620,22 +9632,23 @@ display_tool_bar_line (it, height) } /* Produce glyphs. */ - x_before = it->current_x; - n_glyphs_before = it->glyph_row->used[TEXT_AREA]; + n_glyphs_before = row->used[TEXT_AREA]; + it_before = *it; + PRODUCE_GLYPHS (it); - nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before; + nglyphs = row->used[TEXT_AREA] - n_glyphs_before; i = 0; - x = x_before; + x = it_before.current_x; while (i < nglyphs) { struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i; if (x + glyph->pixel_width > max_x) { - /* Glyph doesn't fit on line. */ - it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i; - it->current_x = x; + /* Glyph doesn't fit on line. Backtrack. */ + row->used[TEXT_AREA] = n_glyphs_before; + *it = it_before; goto out; } @@ -9666,6 +9679,8 @@ display_tool_bar_line (it, height) /* Make line the desired height and center it vertically. */ if ((height -= it->max_ascent + it->max_descent) > 0) { + /* Don't add more than one line height. */ + height %= FRAME_LINE_HEIGHT (it->f); it->max_ascent += height / 2; it->max_descent += (height + 1) / 2; } @@ -11713,9 +11728,11 @@ redisplay_window_1 (window) /* Set cursor position of W. PT is assumed to be displayed in ROW. DELTA is the number of bytes by which positions recorded in ROW - differ from current buffer positions. */ + differ from current buffer positions. -void + Return 0 if cursor is not on this row. 1 otherwise. */ + +int set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) struct window *w; struct glyph_row *row; @@ -11865,6 +11882,11 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string)); } } + + /* If we reached the end of the line, and end was from a string, + cursor is not on this line. */ + if (glyph == end && row->continued_p) + return 0; } w->cursor.hpos = glyph - row->glyphs[TEXT_AREA]; @@ -11898,6 +11920,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) else CHARPOS (this_line_start_pos) = 0; } + + return 1; } @@ -12581,8 +12605,18 @@ try_cursor_movement (window, startp, scroll_step) rc = CURSOR_MOVEMENT_MUST_SCROLL; else { - set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); - rc = CURSOR_MOVEMENT_SUCCESS; + do + { + if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0)) + { + rc = CURSOR_MOVEMENT_SUCCESS; + break; + } + ++row; + } + while (MATRIX_ROW_BOTTOM_Y (row) < last_y + && MATRIX_ROW_START_CHARPOS (row) == PT + && cursor_row_p (w, row)); } } } @@ -15035,6 +15069,25 @@ dump_glyph (row, glyph, area) glyph->left_box_line_p, glyph->right_box_line_p); } + else if (glyph->type == COMPOSITE_GLYPH) + { + fprintf (stderr, + " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + glyph - row->glyphs[TEXT_AREA], + '+', + glyph->charpos, + (BUFFERP (glyph->object) + ? 'B' + : (STRINGP (glyph->object) + ? 'S' + : '-')), + glyph->pixel_width, + glyph->u.cmp_id, + '.', + glyph->face_id, + glyph->left_box_line_p, + glyph->right_box_line_p); + } } @@ -21603,7 +21656,7 @@ erase_phys_cursor (w) /* Maybe clear the display under the cursor. */ if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) { - int x, y; + int x, y, left_x; int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); int width; @@ -21611,11 +21664,16 @@ erase_phys_cursor (w) if (cursor_glyph == NULL) goto mark_cursor_off; - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + width = cursor_glyph->pixel_width; + left_x = window_box_left_offset (w, TEXT_AREA); + x = w->phys_cursor.x; + if (x < left_x) + width -= left_x - x; + width = min (width, window_box_width (w, TEXT_AREA) - x); y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y)); - width = min (cursor_glyph->pixel_width, - window_box_width (w, TEXT_AREA) - w->phys_cursor.x); + x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x)); + if (width > 0) rif->clear_frame_area (f, x, y, width, cursor_row->visible_height); } diff --git a/src/xfaces.c b/src/xfaces.c index 2b2f1620133..9adc9218f6d 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -6762,6 +6762,12 @@ better_font_p (values, font1, font2, compare_pt_p, avgwidth) { int i; + /* Any font is better than no font. */ + if (! font1) + return 0; + if (! font2) + return 1; + for (i = 0; i < DIM (font_sort_order); ++i) { int xlfd_idx = font_sort_order[i]; @@ -7012,29 +7018,19 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike) if (needs_overstrike) *needs_overstrike = 0; - /* Start with the first non-scalable font in the list. */ - for (i = 0; i < nfonts; ++i) - if (!font_scalable_p (fonts + i)) - break; + best = NULL; /* Find the best match among the non-scalable fonts. */ - if (i < nfonts) - { - best = fonts + i; - - for (i = 1; i < nfonts; ++i) - if (!font_scalable_p (fonts + i) - && better_font_p (specified, fonts + i, best, 1, avgwidth)) - { - best = fonts + i; + for (i = 0; i < nfonts; ++i) + if (!font_scalable_p (fonts + i) + && better_font_p (specified, fonts + i, best, 1, avgwidth)) + { + best = fonts + i; - exact_p = exact_face_match_p (specified, best, avgwidth); - if (exact_p) - break; - } - } - else - best = NULL; + exact_p = exact_face_match_p (specified, best, avgwidth); + if (exact_p) + break; + } /* Unless we found an exact match among non-scalable fonts, see if we can find a better match among scalable fonts. */ @@ -7058,8 +7054,7 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike) for (i = 0; i < nfonts; ++i) if (font_scalable_p (fonts + i)) { - if (best == NULL - || better_font_p (specified, fonts + i, best, 0, 0) + if (better_font_p (specified, fonts + i, best, 0, 0) || (!non_scalable_has_exact_height_p && !better_font_p (specified, best, fonts + i, 0, 0))) { @@ -7067,23 +7062,27 @@ best_matching_font (f, attrs, fonts, nfonts, width_ratio, needs_overstrike) best = fonts + i; } } + } - if (needs_overstrike) - { - enum xlfd_weight want_weight = specified[XLFD_WEIGHT]; - enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT]; + /* We should have found SOME font. */ + if (best == NULL) + abort (); - if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight) - { - /* We want a bold font, but didn't get one; try to use - overstriking instead to simulate bold-face. However, - don't overstrike an already-bold fontn unless the - desired weight grossly exceeds the available weight. */ - if (got_weight > XLFD_WEIGHT_MEDIUM) - *needs_overstrike = (got_weight - want_weight) > 2; - else - *needs_overstrike = 1; - } + if (! exact_p && needs_overstrike) + { + enum xlfd_weight want_weight = specified[XLFD_WEIGHT]; + enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT]; + + if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight) + { + /* We want a bold font, but didn't get one; try to use + overstriking instead to simulate bold-face. However, + don't overstrike an already-bold fontn unless the + desired weight grossly exceeds the available weight. */ + if (got_weight > XLFD_WEIGHT_MEDIUM) + *needs_overstrike = (got_weight - want_weight) > 2; + else + *needs_overstrike = 1; } } @@ -7488,7 +7487,7 @@ realize_default_face (f) face = realize_face (c, attrs, DEFAULT_FACE_ID); #ifdef HAVE_WINDOW_SYSTEM -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_X_WINDOWS if (face->font != FRAME_FONT (f)) /* As the font specified for the frame was not acceptable as a font for the default face (perhaps because auto-scaled fonts diff --git a/src/xfns.c b/src/xfns.c index ed6d00d0325..b4d16615fb0 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1256,7 +1256,7 @@ x_set_icon_name (f, arg, oldval) if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) return; } - else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) + else if (!NILP (arg) || NILP (oldval)) return; f->icon_name = arg; @@ -1612,7 +1612,7 @@ x_set_name_internal (f, name) text.format = 8; text.nitems = bytes; - if (NILP (f->icon_name)) + if (!STRINGP (f->icon_name)) { icon = text; } diff --git a/src/xmenu.c b/src/xmenu.c index 2abf0a48319..8e994ac5efb 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1301,9 +1301,119 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers) } } +DEFUN ("menu-bar-open", Fmenu_bar_open, Smenu_bar_open, 0, 1, "i", + doc: /* Start key navigation of the menu bar in FRAME. +This initially opens the first menu bar item and you can then navigate with the +arrow keys, select a menu entry with the return key or cancel with the +escape key. If FRAME has no menu bar this function does nothing. + +If FRAME is nil or not given, use the selected frame. */) + (frame) + Lisp_Object frame; +{ + XEvent ev; + FRAME_PTR f = check_x_frame (frame); + Widget menubar; + BLOCK_INPUT; + + if (FRAME_EXTERNAL_MENU_BAR (f)) + set_frame_menubar (f, 0, 1); + + menubar = FRAME_X_OUTPUT (f)->menubar_widget; + if (menubar) + { + Window child; + int error_p = 0; + + x_catch_errors (FRAME_X_DISPLAY (f)); + memset (&ev, 0, sizeof ev); + ev.xbutton.display = FRAME_X_DISPLAY (f); + ev.xbutton.window = XtWindow (menubar); + ev.xbutton.root = FRAME_X_DISPLAY_INFO (f)->root_window; + ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f)); + ev.xbutton.button = Button1; + ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2; + ev.xbutton.same_screen = True; + +#ifdef USE_MOTIF + { + Arg al[2]; + WidgetList list; + Cardinal nr; + XtSetArg (al[0], XtNchildren, &list); + XtSetArg (al[1], XtNnumChildren, &nr); + XtGetValues (menubar, al, 2); + ev.xbutton.window = XtWindow (list[0]); + } +#endif + + XTranslateCoordinates (FRAME_X_DISPLAY (f), + /* From-window, to-window. */ + ev.xbutton.window, ev.xbutton.root, + + /* From-position, to-position. */ + ev.xbutton.x, ev.xbutton.y, + &ev.xbutton.x_root, &ev.xbutton.y_root, + + /* Child of win. */ + &child); + error_p = x_had_errors_p (FRAME_X_DISPLAY (f)); + x_uncatch_errors (); + + if (! error_p) + { + ev.type = ButtonPress; + ev.xbutton.state = 0; + + XtDispatchEvent (&ev); + ev.xbutton.type = ButtonRelease; + ev.xbutton.state = Button1Mask; + XtDispatchEvent (&ev); + } + } + + UNBLOCK_INPUT; + + return Qnil; +} #endif /* USE_X_TOOLKIT */ + #ifdef USE_GTK +DEFUN ("menu-bar-open", Fmenu_bar_open, Smenu_bar_open, 0, 1, "i", + doc: /* Start key navigation of the menu bar in FRAME. +This initially opens the first menu bar item and you can then navigate with the +arrow keys, select a menu entry with the return key or cancel with the +escape key. If FRAME has no menu bar this function does nothing. + +If FRAME is nil or not given, use the selected frame. */) + (frame) + Lisp_Object frame; +{ + GtkWidget *menubar; + BLOCK_INPUT; + FRAME_PTR f = check_x_frame (frame); + + if (FRAME_EXTERNAL_MENU_BAR (f)) + set_frame_menubar (f, 0, 1); + + menubar = FRAME_X_OUTPUT (f)->menubar_widget; + if (menubar) + { + /* Activate the first menu. */ + GList *children = gtk_container_get_children (GTK_CONTAINER (menubar)); + + gtk_menu_shell_select_item (GTK_MENU_SHELL (menubar), + GTK_WIDGET (children->data)); + + popup_activated_flag = 1; + g_list_free (children); + } + UNBLOCK_INPUT; + + return Qnil; +} + /* Loop util popup_activated_flag is set to zero in a callback. Used for popup menus and dialogs. */ @@ -3659,6 +3769,13 @@ The enable predicate for a menu command should check this variable. */); #endif defsubr (&Sx_popup_menu); + +#if defined (USE_GTK) || defined (USE_X_TOOLKIT) + defsubr (&Smenu_bar_open); + Fdefalias (intern ("accelerate-menu"), intern (Smenu_bar_open.symbol_name), + Qnil); +#endif + #ifdef HAVE_MENUS defsubr (&Sx_popup_dialog); #endif diff --git a/src/xterm.c b/src/xterm.c index c25f23cc573..7407585ebf0 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -326,20 +326,8 @@ static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *)); static void x_set_window_size_1 P_ ((struct frame *, int, int, int)); static const XColor *x_color_cells P_ ((Display *, int *)); static void x_update_window_end P_ ((struct window *, int, int)); -void x_delete_display P_ ((struct x_display_info *)); static int x_io_error_quitter P_ ((Display *)); -void x_catch_errors P_ ((Display *)); -void x_uncatch_errors P_ ((void)); -void x_lower_frame P_ ((struct frame *)); -void x_scroll_bar_clear P_ ((struct frame *)); -int x_had_errors_p P_ ((Display *)); -void x_wm_set_size_hint P_ ((struct frame *, long, int)); -void x_raise_frame P_ ((struct frame *)); -void x_set_window_size P_ ((struct frame *, int, int, int)); -void x_wm_set_window_state P_ ((struct frame *, int)); -void x_wm_set_icon_pixmap P_ ((struct frame *, int)); -void x_initialize P_ ((void)); static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); static int x_compute_min_glyph_bounds P_ ((struct frame *)); static void x_update_end P_ ((struct frame *)); @@ -374,6 +362,7 @@ static void x_check_fullscreen P_ ((struct frame *)); static void x_check_expected_move P_ ((struct frame *)); static int handle_one_xevent P_ ((struct x_display_info *, XEvent *, int *, struct input_event *)); +static SIGTYPE x_connection_closed P_ ((Display *, char *)); /* Flush display of frame F, or of all frames if F is null. */ @@ -2694,19 +2683,28 @@ x_draw_stretch_glyph_string (s) { /* If `x-stretch-block-cursor' is nil, don't draw a block cursor as wide as the stretch glyph. */ - int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width); + int width, background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + width = min (FRAME_COLUMN_WIDTH (s->f), background_width); /* Draw cursor. */ - x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height); + x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height); /* Clear rest using the GC of the original non-cursor face. */ - if (width < s->background_width) + if (width < background_width) { - int x = s->x + width, y = s->y; - int w = s->background_width - width, h = s->height; + int y = s->y; + int w = background_width - width, h = s->height; XRectangle r; GC gc; + x += width; if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) { @@ -2737,8 +2735,18 @@ x_draw_stretch_glyph_string (s) } } else if (!s->background_filled_p) - x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width, - s->height); + { + int background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + if (background_width > 0) + x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); + } s->background_filled_p = 1; } @@ -6320,6 +6328,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) f = x_any_window_to_frame (dpyinfo, event.xkey.window); + /* If mouse-highlight is an integer, input clears out + mouse highlighting. */ if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) && (f == 0 || !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))) @@ -7375,8 +7385,7 @@ x_draw_hollow_cursor (w, row) return; /* Compute frame-relative coordinates for phys cursor. */ - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - y = get_phys_cursor_geometry (w, row, cursor_glyph, &h); + get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); wd = w->phys_cursor_width; /* The foreground of cursor_gc is typically the same as the normal diff --git a/src/xterm.h b/src/xterm.h index 8e1e06097a8..1d1319fca31 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -962,10 +962,6 @@ void x_delete_display P_ ((struct x_display_info *)); void x_make_frame_visible P_ ((struct frame *)); void x_iconify_frame P_ ((struct frame *)); void x_wm_set_size_hint P_ ((struct frame *, long, int)); -void x_catch_errors P_ ((Display *)); -int x_had_errors_p P_ ((Display *)); -void x_uncatch_errors P_ ((void)); -void x_check_errors P_ ((Display *, char *)); int x_text_icon P_ ((struct frame *, char *)); int x_bitmap_icon P_ ((struct frame *, Lisp_Object)); void x_set_window_size P_ ((struct frame *, int, int, int)); @@ -981,7 +977,10 @@ extern int x_bitmap_icon P_ ((struct frame *, Lisp_Object)); extern void x_catch_errors P_ ((Display *)); extern void x_check_errors P_ ((Display *, char *)); extern int x_had_errors_p P_ ((Display *)); +extern int x_catching_errors P_ ((void)); extern void x_uncatch_errors P_ ((void)); +extern void x_clear_errors P_ ((Display *)); +extern void x_fully_uncatch_errors P_ ((void)); extern void x_set_window_size P_ ((struct frame *, int, int, int)); extern void x_set_mouse_position P_ ((struct frame *, int, int)); extern void x_set_mouse_pixel_position P_ ((struct frame *, int, int)); @@ -1000,6 +999,9 @@ extern void x_initialize P_ ((void)); extern unsigned long x_copy_color P_ ((struct frame *, unsigned long)); #ifdef USE_X_TOOLKIT extern XtAppContext Xt_app_con; +extern int x_alloc_lighter_color_for_widget __P ((Widget, Display*, Colormap, + unsigned long *, + double, int)); #endif extern void x_query_colors P_ ((struct frame *f, XColor *, int)); extern void x_query_color P_ ((struct frame *f, XColor *)); |
