src/xterm.h (xw_popup_dialog): Add prototype.
src/xmenu.c (Fx_popup_dialog): Function moved to menu.c.
(xmenu_show): Block input here, instead in Fx_popup_menu.
(xw_popup_dialog): New function, with X-specific bits of popup
dialogs.
src/xdisp.c (deep_copy_glyph_row, display_tty_menu_item): New
functions.
src/window.c (Fset_window_configuration): Use run-time tests of the
frame type instead of compile-time conditionals, when menu-bar
lines are considered.
src/w32term.h (w32con_hide_cursor, w32con_show_cursor)
(w32_popup_dialog): New prototypes.
src/w32menu.c (Fx_popup_dialog): Function deleted.
(w32_popup_dialog): New function, with w32 specific bits of popup
dialogs. Block input here.
src/w32inevt.c (w32_console_read_socket): Minor change to add
debugging TTY events.
src/w32fns.c (show_hourglass): If returning early because the frame
is not a GUI frame, unblock input.
src/w32console.c (w32con_hide_cursor, w32con_show_cursor, cursorX)
(cursorY): New functions.
src/termhooks.h (cursorX, cursorY): Prototypes of functions on
WINDOWSNT, macros that call curX and curY elsewhere.
src/termchar.h (struct tty_display_info) <showing_menu>: New flag.
src/term.c (tty_hide_cursor, tty_show_cursor) [WINDOWSNT]: Call w32
specific function to hide and show cursor on a text-mode terminal.
(tty_menu_struct, struct tty_menu_state): New structures.
(tty_menu_create, tty_menu_make_room, tty_menu_search_pane)
(tty_menu_calc_size, mouse_get_xy, tty_menu_display)
(have_menus_p, tty_menu_add_pane, tty_menu_add_selection)
(tty_menu_locate, save_and_enable_current_matrix)
(restore_desired_matrix, screen_update, read_menu_input)
(tty_menu_activate, tty_menu_destroy, tty_menu_help_callback)
(tty_pop_down_menu, tty_menu_last_menubar_item)
(tty_menu_new_item_coords, tty_menu_show): New functions.
(syms_of_term): New DEFSYMs for tty-menu-* symbols.
src/nsterm.h (ns_popup_dialog): Adjust prototype.
src/nsmenu.m (ns_menu_show): Block and unblock input here, instead
of in x-popup-menu.
(ns_popup_dialog): Adapt order of arguments to the other
*_menu_show implementations.
(Fx_popup_dialog): Function deleted.
src/msdos.c (x_set_menu_bar_lines): Delete unused function.
src/menu.h (tty_menu_show, menu_item_width): provide prototypes.
src/menu.c (have_boxes): New function.
(single_keymap_panes): Use it instead of a compile-time
conditional.
(single_menu_item): Use run-time tests of the frame type instead
of compile-time conditionals.
(encode_menu_string): New function.
(list_of_items, list_of_panes): Use it instead of ENCODE_STRING
the macro, since different types of frame need different encoding
of menu items.
(digest_single_submenu): Use run-time tests of frame type instead
of, or in addition to, compile-time conditionals.
(menu_item_width, Fmenu_bar_menu_at_x_y): New functions.
(Fx_popup_menu): Detect when the function is called from keyboard
on a TTY. Don't barf when invoked on a text-mode frame. Check
frame type at run time, instead of compile-time conditionals for
invoking terminal-specific menu-show functions. Call
tty_menu_show on text-mode frames.
(Fx_popup_dialog): Moved here from xmenu.c. Test frame types at
run time to determine which alternative to invoke; support dialogs
on TTYs.
src/keyboard.h <Qmouse_movement>: Declare.
src/keyboard.c <Qmouse_movement>: Now extern.
<Qecho_keystrokes>: New static variable.
(read_key_sequence): Accept an additional argument, a flag to
prevent redisplay during reading of the key sequence. All callers
changed.
(read_menu_command): New function.
(read_char): When COMMANDFLAG is -2, do not redisplay and do not
autosave.
(toolkit_menubar_in_use): New function.
(make_lispy_event): Use it instead of a compile-time test.
src/fns.c (Fyes_or_no_p) [HAVE_MENUS]: Don't condition on
window-system being available.
src/editfns.c (Fmessage_box) [HAVE_MENUS]: Don't condition the call
to x-popup-dialog on the frame type, they all now support popup
dialogs.
src/dispnew.c (save_current_matrix): Save the margin areas.
(restore_current_matrix): Restore margin areas.
(update_frame_with_menu): New function.
src/dispextern.h (display_tty_menu_item, update_frame_with_menu):
Add prototypes.
src/alloc.c (make_save_ptr): Now compiled unconditionally.
lisp/tmm.el (tmm-menubar): Adapt doc string to TTY menus
functionality.
lisp/tooltip.el (tooltip-mode): Don't error out on TTYs.
lisp/menu-bar.el (popup-menu, popup-menu-normalize-position): Moved
here from mouse.el.
(popup-menu): Support menu-bar navigation on TTYs using C-f/C-b
and arrow keys.
(tty-menu-navigation-map): New map for TTY menu navigation.
lisp/loadup.el ("tooltip"): Load even if x-show-tip is not available.
lisp/frame.el (display-mouse-p): Report text-mode mouse as available
on w32.
(display-popup-menus-p): Report availability if mouse is
available; don't condition on window-system.
lisp/faces.el (tty-menu-enabled-face, tty-menu-disabled-face)
(tty-menu-selected-face): New faces.
configure.ac (HAVE_MENUS): Define unconditionally.
doc/emacs/screen.texi (Menu Bar): Adapt to TTY menus.
doc/emacs/frames.texi (Frames): Mention menu support on text terminals.
doc/emacs/files.texi (Visiting): Mention the "File" menu-bar menu.
doc/emacs/display.texi (Standard Faces): Mention TTY faces for menus.
doc/lispref/keymaps.texi (Defining Menus, Mouse Menus, Menu Bar): Modify
wording to the effect that menus are supported on TTYs.
doc/lisprefframes.texi (Pop-Up Menus, Dialog Boxes)
(Display Feature Testing): Update for menu support on TTYs.
etc/NEWS: Mention the new features.
++2013-10-08 Eli Zaretskii <eliz@gnu.org>
++
++ * configure.ac (HAVE_MENUS): Define unconditionally.
++
+2013-10-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ Improve support for popcount and counting trailing zeros (Bug#15550).
+ Do this by using the Gnulib modules for this.
+ This should generate faster code on non-GCC, non-MSC platforms,
+ and make the code a bit more portable, at least in theory.
+ * lib/count-one-bits.c, lib/count-one-bits.h:
+ * lib/count-trailing-zeros.c, lib/count-trailing-zeros.h:
+ * m4/count-one-bits.m4, m4/count-trailing-zeros.m4:
+ New files, copied from gnulib.
+ * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+
+2013-10-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use hardware support for byteswapping on glibc x86 etc.
+ * lib/byteswap.in.h, m4/byteswap.m4: New files, copied from Gnulib.
+ * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+
+2013-10-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Merge from gnulib, incorporating:
+ 2013-10-02 verify: new macro 'assume'
+ 2013-09-26 dup2, dup3: work around another cygwin crasher
+ 2013-09-26 getdtablesize: work around cygwin issue
+
2013-09-25 Paul Eggert <eggert@cs.ucla.edu>
Merge from gnulib, incorporating:
-2013-10-02 Eli Zaretskii <eliz@gnu.org>
++2013-10-08 Eli Zaretskii <eliz@gnu.org>
+
++ Support menus on text-mode terminals.
+ * screen.texi (Menu Bar): Adapt to TTY menus.
+
+ * frames.texi (Frames): Mention menu support on text terminals.
+
+ * files.texi (Visiting): Mention the "File" menu-bar menu.
+
+ * display.texi (Standard Faces): Mention TTY faces for menus.
+
+2013-10-06 Xue Fuqiao <xfq.free@gmail.com>
+
+ * cal-xtra.texi (Calendar Customizing, Diary Display): Remove @refill.
+
+2013-09-29 Xue Fuqiao <xfq.free@gmail.com>
+
+ * fortran-xtra.texi (Fortran Abbrev): Remove @refill.
+
2013-09-26 Xue Fuqiao <xfq.free@gmail.com>
* dired.texi (Flagging Many Files): Use @emph instead of @strong.
-2013-10-03 Eli Zaretskii <eliz@gnu.org>
++2013-10-08 Eli Zaretskii <eliz@gnu.org>
+
++ Support menus on text-mode terminals.
+ * keymaps.texi (Defining Menus, Mouse Menus, Menu Bar): Modify
+ wording to the effect that menus are supported on TTYs.
+
+ * frames.texi (Pop-Up Menus, Dialog Boxes)
+ (Display Feature Testing): Update for menu support on TTYs.
+
+2013-10-07 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * tips.texi (Comment Tips): Discourage use of triple semi-colons for
+ non-headings.
+
+2013-10-05 Xue Fuqiao <xfq.free@gmail.com>
+
+ * syntax.texi (Categories): Add an index for category sets.
+
+2013-10-03 Xue Fuqiao <xfq.free@gmail.com>
+
+ * syntax.texi (Syntax Flags):
+ (Syntax Table Functions): Add indexes.
+
+2013-10-02 Xue Fuqiao <xfq.free@gmail.com>
+
+ * syntax.texi (Syntax Class Table): Add an index for syntax class table.
+
+2013-09-29 Xue Fuqiao <xfq.free@gmail.com>
+
+ * searching.texi (Regexp Search): Refine.
+
2013-09-22 Xue Fuqiao <xfq.free@gmail.com>
* nonascii.texi (Default Coding Systems): Typo fix.
++2013-10-08 Eli Zaretskii <eliz@gnu.org>
++
++ Support menus on text-mode terminals.
++ * tmm.el (tmm-menubar): Adapt doc string to TTY menus
++ functionality.
++
++ * tooltip.el (tooltip-mode): Don't error out on TTYs.
++
++ * menu-bar.el (popup-menu, popup-menu-normalize-position): Moved
++ here from mouse.el.
++ (popup-menu): Support menu-bar navigation on TTYs using C-f/C-b
++ and arrow keys.
++ (tty-menu-navigation-map): New map for TTY menu navigation.
++
++ * loadup.el ("tooltip"): Load even if x-show-tip is not available.
++
++ * frame.el (display-mouse-p): Report text-mode mouse as available
++ on w32.
++ (display-popup-menus-p): Report availability if mouse is
++ available; don't condition on window-system.
++
++ * faces.el (tty-menu-enabled-face, tty-menu-disabled-face)
++ (tty-menu-selected-face): New faces.
++
+2013-10-08 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * emacs-lisp/lisp-mode.el: Font-lock cl-lib constructs.
+ (lisp-el-font-lock-keywords, lisp-el-font-lock-keywords-1)
+ (lisp-el-font-lock-keywords-2, lisp-cl-font-lock-keywords)
+ (lisp-cl-font-lock-keywords-1, lisp-cl-font-lock-keywords-2):
+ New constants.
+ (lisp-mode-variables): New `elisp' argument.
+ (emacs-lisp-mode): Use it.
+ * font-lock.el (lisp-font-lock-keywords, lisp-font-lock-keywords-1)
+ (lisp-font-lock-keywords-2): Move to lisp-mode.el.
+
+ * indent.el: Use lexical-binding.
+ (indent-region): Add progress reporter.
+ (tab-stop-list): Make it implicitly extend to infinity by repeating the
+ last step.
+ (indent--next-tab-stop): New function to implement this behavior.
+ (tab-to-tab-stop, move-to-tab-stop): Use it.
+
+2013-10-08 Teemu Likonen <tlikonen@iki.fi>
+
+ * indent.el (indent-rigidly--current-indentation): New function.
+ (indent-rigidly-map): New var.
+ (indent-rigidly): Use it to provide interactive mode (bug#8196).
+
+2013-10-08 Bastien Guerry <bzg@gnu.org>
+
+ * register.el (insert-register): Fix 2013-10-07T01:28:34Z!sdl.web@gmail.com.
+
+2013-10-08 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * progmodes/perl-mode.el: Use lexical-binding.
+ Remove redundant :group args.
+ (perl-nochange): Change default to be closer to other major modes's
+ standard behavior.
+ (perl-indent-line): Don't consider text on current line as a
+ valid beginning of function from which to indent.
+
+ * emacs-lisp/backquote.el (backquote-process): Catch uses of , and ,@
+ with more than one argument (bug#15538).
+
+ * mpc.el (mpc-songs-jump-to): Adjust to different playlist format.
+
+ * vc/pcvs.el: Use lexical-binding.
+ (cvs-temp-buffer, cvs-make-cvs-buffer): Pass some vars in the lexical
+ environment of `eval'.
+ (cvs-mode-run, cvs-mode-do): Change `postproc' to be a function rather
+ than a list of expressions. Adjust callers.
+ * vc/pcvs-defs.el (cvs-postprocess): Remove, unused.
+
+2013-10-07 Dmitry Gutov <dgutov@yandex.ru>
+
+ * progmodes/ruby-mode.el (ruby-smie--implicit-semi-p): Handle the
+ case of the dot in a chained method call being on the following line.
+
+2013-10-07 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * electric.el (electric-indent-inhibit): New var.
+ (electric-indent-post-self-insert-function): Use it.
+ * progmodes/python.el (python-mode): Set it.
+
+ * progmodes/ruby-mode.el (ruby-smie-rules): Tweak handling of
+ open braces.
+
+ * emacs-lisp/smie.el (smie-next-sexp): Refine last fix.
+
+ * textmodes/css-mode.el (css-smie-rules): Fix indentation (bug#15467).
+ (css-mode): Use electric-indent-chars.
+
+ * nxml/nxml-mode.el: Use lexical-binding and syntax-propertize.
+ (font-lock-beg, font-lock-end): Move before first use.
+ (nxml-mode): Use syntax-propertize-function.
+ (nxml-after-change, nxml-after-change1): Adjust accordingly.
+ (nxml-extend-after-change-region): Remove.
+ * nxml/xmltok.el: Use lexical-binding.
+ (xmltok-save): Use `declare'.
+ (xmltok-unclosed-reparse-p, xmltok-semi-closed-reparse-p): Remove.
+ * nxml/nxml-util.el: Use lexical-binding.
+ (nxml-with-degradation-on-error, nxml-with-invisible-motion):
+ Use `declare'.
+ * nxml/nxml-ns.el: Use lexical-binding.
+ (nxml-ns-save): Use `declare'.
+ (nxml-ns-prefixes-for): Avoid add-to-list.
+ * nxml/rng-match.el: Use lexical-binding.
+ (rng--ipattern): Use cl-defstruct.
+ (rng-compute-start-tag-open-deriv, rng-compute-start-attribute-deriv)
+ (rng-cons-group-after, rng-subst-group-after)
+ (rng-subst-interleave-after, rng-apply-after, rng-compute-data-deriv):
+ Use closures instead of `(lambda...).
+
+2013-10-07 Michael Albinus <michael.albinus@gmx.de>
+
+ * net/tramp.el (tramp-handle-insert-file-contents): Improve handling
+ of BEG and END.
+
+ * net/tramp-gvfs.el (tramp-gvfs-file-name-handler-alist):
+ Use `tramp-handle-insert-file-contents'.
+ (tramp-gvfs-handle-insert-file-contents): Remove function.
+
+ * net/tramp-sh.el (tramp-sh-handle-insert-directory):
+ Use `save-restriction' in order to keep markers.
+
+ * net/trampver.el: Update release number.
+
+2013-10-07 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * progmodes/compile.el (compilation-parse-errors):
+ Use compilation--put-prop.
+ (compilation--ensure-parse): Check compilation-multiline.
+
+ * emacs-lisp/easymenu.el (easy-menu-create-menu): Use closures.
+
+ * emacs-lisp/lisp-mode.el (eval-defun-2): Simplify, using
+ lexical-binding.
+
+ * emacs-lisp/tq.el (tq-create): Use a closure instead of `(lambda...).
+
+ * progmodes/ruby-mode.el: Fix recently added tests.
+ (ruby-smie-grammar): Add - and +.
+ (ruby-smie--redundant-do-p, ruby-smie--forward-id)
+ (ruby-smie--backward-id): New functions.
+ (ruby-smie--forward-token, ruby-smie--backward-token): Use them.
+ (ruby-smie-rules): Handle hanging do. Get rid of hack, not needed
+ any more.
+
+2013-10-07 Leo Liu <sdl.web@gmail.com>
+
+ * register.el (register-preview-delay)
+ (register-preview-functions): New variables.
+ (register-read-with-preview, register-preview)
+ (register-describe-oneline): New functions.
+ (point-to-register, window-configuration-to-register)
+ (frame-configuration-to-register, jump-to-register)
+ (number-to-register, view-register, insert-register)
+ (copy-to-register, append-to-register, prepend-to-register)
+ (copy-rectangle-to-register): Use register-read-with-preview to
+ read register. (Bug#15525)
+
+2013-10-06 Dato Simó <dato@net.com.org.es> (tiny change)
+
+ * net/network-stream.el (network-stream-open-starttls): Don't add
+ --insecure if it's already present, because that gnutls-cli
+ rejects getting that parameter twice.
+
+2013-10-06 Dmitry Gutov <dgutov@yandex.ru>
+
+ * progmodes/ruby-mode.el (ruby-smie-rules): Dedent `ensure'
+ keyword, too.
+
+2013-10-05 Dmitry Gutov <dgutov@yandex.ru>
+
+ * newcomment.el (comment-use-global-state): Change default value
+ to t, mark obsolete (Bug#15251).
+ (comment-beginning): In addition to `comment-to-syntax', check the
+ value of `comment-use-global-state'.
+
+2013-10-05 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * progmodes/ruby-mode.el (ruby-use-smie): Change default.
+ (ruby-comment-column): Follow the global default, by default.
+ (ruby-smie-grammar): Add assignment syntax.
+ (ruby-smie--implicit-semi-p): No implicit semi-colon after an
+ open-paren, a comma, or a \.
+ (ruby-smie--forward-token, ruby-smie--backward-token): Handle heredocs,
+ and line continuations.
+ (ruby-smie-rules): Adjust handling of open-paren, now that it's never
+ followed by implicit semi-colons. Add rule for string concatenation
+ and for indentation at BOB.
+ (ruby-forward-sexp, ruby-backward-sexp): Adjust for when smie is in use.
+
+ * emacs-lisp/smie.el (smie-next-sexp): Don't go back to pos before
+ calling next-sexp, since next-token may have skipped chars which
+ next-sexp doesn't know should be skipped!
+
+2013-10-05 Leo Liu <sdl.web@gmail.com>
+
+ * progmodes/octave.el (octave-send-region):
+ Call compilation-forget-errors.
+
+2013-10-04 Xue Fuqiao <xfq.free@gmail.com>
+
+ * vc/vc-svn.el (vc-svn-find-admin-dir):
+ * vc/vc-rcs.el (vc-rcs-find-admin-dir):
+ * vc/vc-mtn.el (vc-mtn-find-admin-dir):
+ * vc/vc-cvs.el (vc-cvs-find-admin-dir):
+ * vc/vc-arch.el (vc-arch-find-admin-dir): New functions.
+
+2013-10-04 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * textmodes/css-mode.el (css-smie-rules): Toplevel's a list (bug#15467).
+
+2013-10-04 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * subr.el (read-passwd): Hide chars even when called within a context
+ where after-change-functions is disabled (bug#15501).
+ (set-temporary-overlay-map): Don't remove oneself from pre-command-hook
+ until we removed ourself from overriding-terminal-local-map.
+
+2013-10-04 Leo Liu <sdl.web@gmail.com>
+
+ * progmodes/octave.el (inferior-octave-mode):
+ Call compilation-forget-errors.
+
+2013-10-04 Xue Fuqiao <xfq.free@gmail.com>
+
+ * emacs-lisp/syntax.el (syntax-ppss): Doc fix.
+
+2013-10-04 Michael Albinus <michael.albinus@gmx.de>
+
+ * net/secrets.el (secrets-create-collection): Add optional
+ argument ALIAS. Use proper Label keyword. Append ALIAS as
+ dbus-call-method argument. (Bug#15516)
+
+2013-10-04 Leo Liu <sdl.web@gmail.com>
+
+ * progmodes/octave.el (inferior-octave-error-regexp-alist)
+ (inferior-octave-compilation-font-lock-keywords): New variables.
+ (compilation-error-regexp-alist)
+ (compilation-mode-font-lock-keywords): Defvar to pacify compiler.
+ (inferior-octave-mode): Use compilation-shell-minor-mode.
+
+2013-10-04 Jorgen Schaefer <forcer@forcix.cx>
+
+ * minibuffer.el (completion--replace): Be careful that `end' might be
+ a marker.
+
+2013-10-03 Daiki Ueno <ueno@gnu.org>
+
+ Add support for package signature checking.
+ * emacs-lisp/package.el (url-http-file-exists-p)
+ (epg-make-context, epg-context-set-home-directory)
+ (epg-verify-string, epg-context-result-for)
+ (epg-signature-status, epg-signature-to-string)
+ (epg-check-configuration, epg-configuration)
+ (epg-import-keys-from-file): Declare.
+ (package-check-signature): New user option.
+ (package-unsigned-archives): New user option.
+ (package-desc): Add `signed' field.
+ (package-load-descriptor): Set `signed' field if .signed file exists.
+ (package--archive-file-exists-p): New function.
+ (package--check-signature): New function.
+ (package-install-from-archive): Check package signature.
+ (package--download-one-archive): Check archive signature.
+ (package-delete): Remove .signed file.
+ (package-import-keyring): New command.
+ (package-refresh-contents): Import default keyring.
+ (package-desc-status): Add "unsigned" status.
+ (describe-package-1, package-menu--print-info)
+ (package-menu-mark-delete, package-menu--find-upgrades)
+ (package-menu--status-predicate): Support "unsigned" status.
+
+2013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * emacs-lisp/cconv.el (cconv-convert, cconv-analyse-form): Adjust for
+ the new compilation scheme using the new byte-codes.
+
+ * emacs-lisp/bytecomp.el (byte-pushcatch, byte-pushconditioncase)
+ (byte-pophandler): New byte codes.
+ (byte-goto-ops): Adjust accordingly.
+ (byte-compile--use-old-handlers): New var.
+ (byte-compile-catch): Use new byte codes depending on
+ byte-compile--use-old-handlers.
+ (byte-compile-condition-case--old): Rename from
+ byte-compile-condition-case.
+ (byte-compile-condition-case--new): New function.
+ (byte-compile-condition-case): New function that dispatches depending
+ on byte-compile--use-old-handlers.
+ (byte-compile-unwind-protect): Pass a function to byte-unwind-protect
+ when we can.
+
+ * emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
+ Optimize under `condition-case' and `catch' if
+ byte-compile--use-old-handlers is nil.
+ (disassemble-offset): Handle new bytecodes.
+
+2013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * subr.el (error): Use `declare'.
+ (decode-char, encode-char): Use advertised-calling-convention instead
+ of the docstring to discourage use of the `restriction' arg.
+
+2013-10-03 Daiki Ueno <ueno@gnu.org>
+
+ * epg.el (epg-verify-file): Add a comment saying that it does not
+ notify verification error as a return value nor a signal.
+ (epg-verify-string): Ditto.
+
+2013-10-02 Kevin Rodgers <kevin.d.rodgers@gmail.com>
+
+ * progmodes/compile.el (compilation-start): Try globbing the arg to
+ `cd' (bug#15417).
+
+2013-10-02 Michael Albinus <michael.albinus@gmx.de>
+
+ Sync with Tramp 2.2.8.
+
+ * net/tramp-cmds.el (tramp-bug, tramp-append-tramp-buffers):
+ * net/tramp-cache.el (tramp-cache-print): Use `tramp-compat-funcall'.
+ * net/trampver.el: Update release number.
+
+2013-10-01 Jan Djärv <jan.h.d@swipnet.se>
+
+ * term/ns-win.el (ns-initialize-window-system): Set locale-coding-system
+ and default-process-coding-system for darwin only.
+
+2013-10-01 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * emacs-lisp/package.el (package-desc): Simplify (bug#15495).
+
+2013-10-01 Mitchel Humpherys <mitch.special@gmail.com> (tiny change)
+
+ * vc/vc-git.el (vc-git-grep): Disable pager.
+
+2013-10-01 Dmitry Gutov <dgutov@yandex.ru>
+
+ * emacs-lisp/package.el (package-buffer-info, describe-package-1):
+ Use :url instead of :homepage, as per
+ http://lists.gnu.org/archive/html/emacs-devel/2013-09/msg00622.html
+
+ * newcomment.el (comment-beginning): When `comment-use-syntax' is
+ non-nil, use `syntax-ppss' (Bug#15251).
+
+2013-09-30 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+
+ * progmodes/octave.el (inferior-octave-startup-file):
+ Prefer ~/.emacs.d/init_octave.m.
+
+2013-09-29 Dmitry Gutov <dgutov@yandex.ru>
+
+ * emacs-lisp/package.el (package-desc-from-define):
+ Accept additional arguments as plist, convert them to an alist and store
+ them in the `extras' slot.
+ (package-generate-description-file): Convert extras alist back to
+ plist and append to the `define-package' form arguments.
+ (package--alist-to-plist): New function.
+ (package--ac-desc): Add `extras' slot.
+ (package--add-to-archive-contents): Check if the archive-contents
+ vector is long enough, and if it is, pass its `extras' slot value
+ to `package-desc-create'.
+ (package-buffer-info): Call `lm-homepage', pass the returned value
+ to `package-desc-from-define'.
+ (describe-package-1): Render the homepage button (Bug#13291).
+
+ * emacs-lisp/package-x.el (package-upload-buffer-internal):
+ Pass `extras' slot from `package-desc' to `package-make-ac-desc'.
+
+2013-09-29 Jan Djärv <jan.h.d@swipnet.se>
+
+ * term/ns-win.el (ns-initialize-window-system): Set locale-coding-system
+ and default-process-coding-system to utf-8-unix (Bug#15402).
+
+2013-09-29 Xue Fuqiao <xfq.free@gmail.com>
+
+ * subr.el (looking-back): Do not recommend using looking-back.
+
+2013-09-28 Alan Mackenzie <acm@muc.de>
+
+ Fix indentation/fontification of Java enum with "implements".
+
+ * progmodes/cc-langs.el (c-postfix-decl-spec-key): New variable, a
+ regexp which matches "implements", etc., in Java.
+ * progmodes/cc-engine.el (c-inside-bracelist-p): Check for extra
+ specifier clauses coming after "enum".
+ * progmodes/cc-fonts.el (c-font-lock-declarations)
+ (c-font-lock-enum-tail): Check for extra specifier clauses coming
+ after "enum".
+
+2013-09-28 Jan Djärv <jan.h.d@swipnet.se>
+
+ * faces.el (region): Change ns_selection_color to
+ ns_selection_fg_color, add ns_selection_bg_color.
+
2013-09-28 Leo Liu <sdl.web@gmail.com>
* progmodes/octave.el (inferior-octave-completion-table)
++2013-10-08 Eli Zaretskii <eliz@gnu.org>
++
++ Support menus on text-mode terminals.
++ * xterm.h (xw_popup_dialog): Add prototype.
++
++ * xmenu.c (Fx_popup_dialog): Function moved to menu.c.
++ (xmenu_show): Block input here, instead in Fx_popup_menu.
++ (xw_popup_dialog): New function, with X-specific bits of popup
++ dialogs.
++
++ * xdisp.c (deep_copy_glyph_row, display_tty_menu_item): New
++ functions.
++
++ * window.c (Fset_window_configuration): Use run-time tests of the
++ frame type instead of compile-time conditionals, when menu-bar
++ lines are considered.
++
++ * w32term.h (w32con_hide_cursor, w32con_show_cursor)
++ (w32_popup_dialog): New prototypes.
++
++ * w32menu.c (Fx_popup_dialog): Function deleted.
++ (w32_popup_dialog): New function, with w32 specific bits of popup
++ dialogs. Block input here.
++
++ * w32inevt.c (w32_console_read_socket): Minor change to add
++ debugging TTY events.
++
++ * w32fns.c (show_hourglass): If returning early because the frame
++ is not a GUI frame, unblock input.
++
++ * w32console.c (w32con_hide_cursor, w32con_show_cursor, cursorX)
++ (cursorY): New functions.
++
++ * termhooks.h (cursorX, cursorY): Prototypes of functions on
++ WINDOWSNT, macros that call curX and curY elsewhere.
++
++ * termchar.h (struct tty_display_info) <showing_menu>: New flag.
++
++ * term.c (tty_hide_cursor, tty_show_cursor) [WINDOWSNT]: Call w32
++ specific function to hide and show cursor on a text-mode terminal.
++ (tty_menu_struct, struct tty_menu_state): New structures.
++ (tty_menu_create, tty_menu_make_room, tty_menu_search_pane)
++ (tty_menu_calc_size, mouse_get_xy, tty_menu_display)
++ (have_menus_p, tty_menu_add_pane, tty_menu_add_selection)
++ (tty_menu_locate, save_and_enable_current_matrix)
++ (restore_desired_matrix, screen_update, read_menu_input)
++ (tty_menu_activate, tty_menu_destroy, tty_menu_help_callback)
++ (tty_pop_down_menu, tty_menu_last_menubar_item)
++ (tty_menu_new_item_coords, tty_menu_show): New functions.
++ (syms_of_term): New DEFSYMs for tty-menu-* symbols.
++
++ * nsterm.h (ns_popup_dialog): Adjust prototype.
++
++ * nsmenu.m (ns_menu_show): Block and unblock input here, instead
++ of in x-popup-menu.
++ (ns_popup_dialog): Adapt order of arguments to the other
++ *_menu_show implementations.
++ (Fx_popup_dialog): Function deleted.
++
++ * msdos.c (x_set_menu_bar_lines): Delete unused function.
++
++ * menu.h (tty_menu_show, menu_item_width): provide prototypes.
++
++ * menu.c (have_boxes): New function.
++ (single_keymap_panes): Use it instead of a compile-time
++ conditional.
++ (single_menu_item): Use run-time tests of the frame type instead
++ of compile-time conditionals.
++ (encode_menu_string): New function.
++ (list_of_items, list_of_panes): Use it instead of ENCODE_STRING
++ the macro, since different types of frame need different encoding
++ of menu items.
++ (digest_single_submenu): Use run-time tests of frame type instead
++ of, or in addition to, compile-time conditionals.
++ (menu_item_width, Fmenu_bar_menu_at_x_y): New functions.
++ (Fx_popup_menu): Detect when the function is called from keyboard
++ on a TTY. Don't barf when invoked on a text-mode frame. Check
++ frame type at run time, instead of compile-time conditionals for
++ invoking terminal-specific menu-show functions. Call
++ tty_menu_show on text-mode frames.
++ (Fx_popup_dialog): Moved here from xmenu.c. Test frame types at
++ run time to determine which alternative to invoke; support dialogs
++ on TTYs.
++
++ * keyboard.h <Qmouse_movement>: Declare.
++
++ * keyboard.c <Qmouse_movement>: Now extern.
++ <Qecho_keystrokes>: New static variable.
++ (read_key_sequence): Accept an additional argument, a flag to
++ prevent redisplay during reading of the key sequence. All callers
++ changed.
++ (read_menu_command): New function.
++ (read_char): When COMMANDFLAG is -2, do not redisplay and do not
++ autosave.
++ (toolkit_menubar_in_use): New function.
++ (make_lispy_event): Use it instead of a compile-time test.
++
++ * fns.c (Fyes_or_no_p) [HAVE_MENUS]: Don't condition on
++ window-system being available.
++
++ * editfns.c (Fmessage_box) [HAVE_MENUS]: Don't condition the call
++ to x-popup-dialog on the frame type, they all now support popup
++ dialogs.
++
++ * dispnew.c (save_current_matrix): Save the margin areas.
++ (restore_current_matrix): Restore margin areas.
++ (update_frame_with_menu): New function.
++
++ * dispextern.h (display_tty_menu_item, update_frame_with_menu):
++ Add prototypes.
++
++ * alloc.c (make_save_ptr): Now compiled unconditionally.
++
+2013-10-08 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * dispnew.c (set_window_update_flags): Add buffer arg. Adjust comment.
+ (redraw_frame, update_frame): Adjust users.
+ * dispextern.h (set_window_update_flags): Adjust prototype.
+ * xdisp.c (redisplay_internal): When updating all frames with zero
+ windows_or_buffers_changed, assume that only the windows that shows
+ current buffer should be really updated.
+
+2013-10-08 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Do not allocate huge temporary memory areas and objects while encoding
+ for file I/O, thus reducing an enormous memory usage for large buffers.
+ See http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00180.html.
+ * coding.h (struct coding_system): New member raw_destination.
+ * coding.c (setup_coding_system): Initialize it to zero.
+ (encode_coding_object): If raw_destination is set, do not create
+ dst_object. Add comment.
+ * fileio.c (toplevel): New constant E_WRITE_MAX.
+ (e_write): Do not encode more than E_WRITE_MAX characters per one loop
+ iteration. Use raw_destination if E_WRITE_MAX characters is encoded.
+
+2013-10-08 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (windowDidExitFullScreen:):
+ (toggleFullScreen:): Change NS_IMPL_COCOA to HAVE_NATIVE_FS.
+
+2013-10-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix race where emacs aborts when sent SIGTERM (Bug#15534).
+ * keyboard.c (unblock_input_to): Don't process pending signals
+ if a fatal error is in progress.
+
+ * lisp.h (bits_word, BITS_WORD_MAX): New type and macro.
+ All uses of 'size_t' and 'SIZE_MAX' changed to use them, when
+ they're talking about words in Lisp bool vectors.
+ (BITS_PER_BITS_WORD): Rename from BITS_PER_SIZE_T. All uses changed.
+ * data.c (popcount_bits_word): Rename from popcount_size_t.
+ (bits_word_to_host_endian): Rename from size_t_to_host_endian.
+ All uses changed.
+
+2013-10-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ Improve support for popcount and counting trailing zeros (Bug#15550).
+ * data.c: Include <count-one-bits.h>, <count-trailing-zeros.h>.
+ (USE_MSC_POPCOUNT, POPCOUNT_STATIC_INLINE)
+ (NEED_GENERIC_POPCOUNT, popcount_size_t_generic)
+ (popcount_size_t_msc, popcount_size_t_gcc):
+ Remove; now done by Gnulib.
+ (popcount_size_t): Now a macro that defers to Gnulib.
+ (count_trailing_zero_bits): Return int, for consistency with
+ Gnulib and because Emacs prefers signed to unsigned int.
+ Don't assume that size_t is either unsigned int or unsigned long
+ or unsigned long long.
+ (size_t_to_host_endian): Do not assume that size_t is either
+ exactly 32 or exactly 64 bits wide.
+ * lisp.h (BITS_PER_SIZE_T): Define consistently with BITS_PER_LONG
+ etc., so that it's now an enum constant, not a macro.
+ No need to assume that it's either 32 or 64.
+
+2013-10-07 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (windowDidEnterFullScreen:): setPresentationOptions only
+ on >= 10.7.
+
+2013-10-07 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * insdel.c (insert_from_gap): Prefer ptrdiff_t to int where needed.
+ * xdisp.c (handle_fontified_prop): Likewise. Use bool for boolean.
+
+2013-10-07 Paul Eggert <eggert@cs.ucla.edu>
+
+ emacs_read and emacs_write now use void *, not char *.
+ * alloc.c (valid_pointer_p) [!WINDOWSNT]: Remove now-unnecessary cast.
+ * sysdep.c (emacs_read, emacs_write, emacs_write_sig):
+ Buffer arg is now void *, not char *. This matches plain
+ 'read' and 'write' better, and avoids a constraint violation
+ on Solaris 9 with Oracle Studio.
+
+2013-10-07 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * alloc.c (Fmake_string): For ASCII char initializer, prefer
+ memset to explicit loop. Otherwise copy largest possible chunk
+ from initialized to uninitialized part, thus allowing the longer
+ memcpy runs and reducing the number of loop iterations.
+
+2013-10-06 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_update_begin): If native fullscreen and no toolbar,
+ hide toolbar (Bug#15388).
+ (windowDidEnterFullScreen:): If presentation options are zero,
+ set them here (Bug#15388).
+ (ns_update_auto_hide_menu_bar): Remove runtime check.
+ Don't auto hide dock unless menubar is also auto hidden.
+
+2013-10-05 Xue Fuqiao <xfq.free@gmail.com>
+
+ * editfns.c (message): Mention batch mode in doc string.
+
+2013-10-05 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (check_native_fs): Remove erroneous comment.
+
+2013-10-04 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * xdisp.c (redisplay_internal): Simplify because scan_for_column now
+ uses find_newline instead of scan_newline and so doesn't move point.
+
+2013-10-04 Paul Eggert <eggert@cs.ucla.edu>
+
+ Use hardware support for byteswapping on glibc x86 etc.
+ On Fedora 19 x86-64, the new bswap_64 needs 1 instruction,
+ whereas the old swap64 needed 30.
+ * fringe.c (init_fringe_bitmap) [WORDS_BIGENDIAN]:
+ * sound.c (le2hl, le2hs, be2hl) [!WINDOWSNT]:
+ Use byteswap.h's macros to swap bytes.
+ * lisp.h (swap16, swap32, swap64): Remove.
+ All uses replaced by bswap_16, bswap_32, bswap_64.
+
+ * bytecode.c (exec_byte_code): Use some more volatile variables
+ to work around local variables getting clobbered by longjmp.
+ Port to pre-C99, which doesn't allow decls after stmts.
+
+2013-10-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ * lisp.h (eassert): Assume that COND is true when optimizing.
+ In other words, take on the behavior of eassert_and_assume.
+ This makes Emacs 0.2% smaller on my platform (Fedora 19, x86-64).
+ (eassert_and_assume): Remove. All uses replaced by eassert.
+
+ * xdisp.c (Qglyphless_char): Now static.
+
+ Adjust to merge from gnulib.
+ * conf_post.h (__has_builtin, assume): Remove; gnulib now does these.
+ * lisp.h: Include <verify.h>, for 'assume'.
+
+ * eval.c (clobbered_eassert): New macro.
+ (internal_catch, internal_condition_case)
+ (internal_condition_case_1, internal_condition_case_2)
+ (internal_condition_case_n): Use it instead of eassert
+ when the argument contains locals clobbered by longjmp.
+ Don't use clobbered locals outside of clobbered_eassert.
+ (internal_lisp_condition_case): Use a volatile variable
+ to work around a local variable's getting clobbered.
+
+2013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp.h (struct handler): Merge struct handler and struct catchtag.
+ (PUSH_HANDLER): New macro.
+ (catchlist): Remove.
+ (handlerlist): Always declare.
+
+ * eval.c (catchlist): Remove (merge with handlerlist).
+ (handlerlist, lisp_eval_depth): Not static any more.
+ (internal_catch, internal_condition_case, internal_condition_case_1)
+ (internal_condition_case_2, internal_condition_case_n):
+ Use PUSH_HANDLER.
+ (unwind_to_catch, Fthrow, Fsignal): Adjust to merged
+ handlerlist/catchlist.
+ (internal_lisp_condition_case): Use PUSH_HANDLER. Adjust to new
+ handlerlist which can only handle a single condition-case handler at
+ a time.
+ (find_handler_clause): Simplify since we only a single branch here
+ any more.
+
+ * bytecode.c (BYTE_CODES): Add Bpushcatch, Bpushconditioncase
+ and Bpophandler.
+ (bcall0): New function.
+ (exec_byte_code): Add corresponding cases. Improve error message when
+ encountering an invalid byte-code. Let Bunwind_protect accept
+ a function (rather than a list of expressions) as argument.
+
+ * alloc.c (Fgarbage_collect): Merge scans of handlerlist and catchlist,
+ and make them unconditional now that they're heap-allocated.
+
+2013-10-03 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * charset.c (Fdecode_char, Fencode_char): Remove description of
+ `restriction' arg. now that it's hidden by advertised-calling-convention.
+
+2013-10-02 Jan Djärv <jan.h.d@swipnet.se>
+
+ * macfont.m (mac_ctfont_create_preferred_family_for_attributes):
+ Remove unused variable (from mac-port).
+ (macfont_draw): Use s->ybase for correct y position.
+
+2013-10-02 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * frame.h (struct frame): Drop has_minibuffer member because...
+ (FRAME_HAS_MINIBUF_P): ...this macro can be implemented without it.
+ * frame.c (make_frame, make_minibuffer_frame): Adjust users.
+
+2013-10-02 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * window.h (struct window): Prefer enum text_cursor_kinds to int
+ for phys_cursor_type member. Move the latter, phys_cursor_width,
+ phys_cursor_ascent and phys_cursor_height under HAVE_WINDOW_SYSTEM.
+ * window.c (replace_window, make_window): Adjust users.
+
+2013-10-02 Dmitry Antipov <dmantipov@yandex.ru>
+
+ * fringe.c (toplevel): Do not use HAVE_WINDOW_SYSTEM because
+ this module is never compiled otherwise.
+
+2013-10-01 Alp Aker <alp.tekin.aker@gmail.com>
+
+ * macfont.m (macfont_draw): Use CGRectMake rather than NSMakeRect
+ (Bug#15500).
+
+2013-09-29 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (get_next_display_element): Don't call face_for_font in
+ a build configured --without-x. (Bug#15484)
+
+2013-09-29 Jan Djärv <jan.h.d@swipnet.se>
+
+ * window.c (calc_absolute_offset): #elif should be #elif defined.
+
+ * frame.c (delete_frame): Block/unblock input to overcome race
+ condition (Bug#15475).
+
+2013-09-29 Andreas Politz <politza@hochschule-trier.de> (tiny change)
+
+ * frame.c (delete_frame): Record selected frame only after
+ calling Qdelete_frame_functions (Bug#15477).
+
+2013-09-28 Jan Djärv <jan.h.d@swipnet.se>
+
+ * nsterm.m (ns_selection_color): Remove.
+ (ns_get_color): Check for ns_selection_(fg|bg)_color using
+ NSColor selectedText(Background)Color. Only for COCOA.
+ (ns_term_init): Remove assignment of ns_selection_color, logic
+ moved to ns_get_color.
+
+ * nsterm.h (NS_SELECTION_BG_COLOR_DEFAULT): Rename from
+ NS_SELECTION_COLOR_DEFAULT.
+ (NS_SELECTION_FG_COLOR_DEFAULT): New.
+
+2013-09-28 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (Fdump_tool_bar_row): Ifdef away the body if 'struct
+ frame' does not have the tool_bar_window member.
+
2013-09-26 Barry O'Reilly <gundaetiapo@gmail.com>
Signal error when reading an empty byte-code object (Bug#15405)
return paused_p;
}
- set_window_update_flags (root_window, 0);
+ /* Update a TTY frame F that has a menu dropped down over some of its
+ glyphs. This is like the second part of update_frame, but it
+ doesn't call build_frame_matrix, because we already have the
+ desired matrix prepared, and don't want it to be overwritten by the
+ text of the normal display. */
+ void
+ update_frame_with_menu (struct frame *f)
+ {
+ struct window *root_window = XWINDOW (f->root_window);
+ bool paused_p;
+
+ eassert (FRAME_TERMCAP_P (f));
+
+ /* We are working on frame matrix basis. Set the frame on whose
+ frame matrix we operate. */
+ set_frame_matrix_frame (f);
+
+ /* Update the display */
+ update_begin (f);
+ /* Force update_frame_1 not to stop due to pending input, and not
+ try scrolling. */
+ paused_p = update_frame_1 (f, 1, 1);
+ update_end (f);
+
+ if (FRAME_TTY (f)->termscript)
+ fflush (FRAME_TTY (f)->termscript);
+ fflush (FRAME_TTY (f)->output);
+ /* Check window matrices for lost pointers. */
+ #if GLYPH_DEBUG
+ #if 0
+ /* We cannot possibly survive the matrix pointers check, since
+ we have overwritten parts of the frame glyph matrix without
+ making any updates to the window matrices. */
+ check_window_matrix_pointers (root_window);
+ #endif
+ add_frame_display_history (f, paused_p);
+ #endif
+
+ /* Reset flags indicating that a window should be updated. */
++ set_window_update_flags (root_window, NULL, 0);
+ }
\f
/************************************************************************
}
#endif /* HAVE_GPM */
-struct glyph_matrix *
+ \f
+ /***********************************************************************
+ Menus
+ ***********************************************************************/
+
+ #if defined (HAVE_MENUS) && !defined (MSDOS)
+
+ /* TTY menu implementation and main ideas are borrowed from msdos.c.
+
+ However, unlike on MSDOS, where the menu text is drawn directly to
+ the display video memory, on a TTY we use display_string (see
+ display_tty_menu_item in xdisp.c) to put the glyphs produced from
+ the menu items directly into the frame's 'desired_matrix' glyph
+ matrix, and then call update_frame_with_menu to deliver the results
+ to the glass. The previous contents of the screen, in the form of
+ the current_matrix, is stashed away, and used to restore screen
+ contents when the menu selection changes or when the final
+ selection is made and the menu should be popped down.
+
+ The idea of this implementation was suggested by Gerd Moellmann. */
+
+ #define TTYM_FAILURE -1
+ #define TTYM_SUCCESS 1
+ #define TTYM_NO_SELECT 2
+ #define TTYM_IA_SELECT 3
+ #define TTYM_NEXT 4
+ #define TTYM_PREV 5
+
+ /* These hold text of the current and the previous menu help messages. */
+ static const char *menu_help_message, *prev_menu_help_message;
+ /* Pane number and item number of the menu item which generated the
+ last menu help message. */
+ static int menu_help_paneno, menu_help_itemno;
+
+ static Lisp_Object Qtty_menu_navigation_map, Qtty_menu_exit;
+ static Lisp_Object Qtty_menu_prev_item, Qtty_menu_next_item;
+ static Lisp_Object Qtty_menu_next_menu, Qtty_menu_prev_menu;
+ static Lisp_Object Qtty_menu_select, Qtty_menu_ignore;
+ static Lisp_Object Qtty_menu_mouse_movement;
+
+ typedef struct tty_menu_struct
+ {
+ int count;
+ char **text;
+ struct tty_menu_struct **submenu;
+ int *panenumber; /* Also used as enabled flag. */
+ int allocated;
+ int panecount;
+ int width;
+ const char **help_text;
+ } tty_menu;
+
+ /* Create a brand new menu structure. */
+
+ static tty_menu *
+ tty_menu_create (void)
+ {
+ tty_menu *menu;
+
+ menu = (tty_menu *) xmalloc (sizeof (tty_menu));
+ menu->allocated = menu->count = menu->panecount = menu->width = 0;
+ return menu;
+ }
+
+ /* Allocate some (more) memory for MENU ensuring that there is room for one
+ for item. */
+
+ static void
+ tty_menu_make_room (tty_menu *menu)
+ {
+ if (menu->allocated == 0)
+ {
+ int count = menu->allocated = 10;
+ menu->text = (char **) xmalloc (count * sizeof (char *));
+ menu->submenu = (tty_menu **) xmalloc (count * sizeof (tty_menu *));
+ menu->panenumber = (int *) xmalloc (count * sizeof (int));
+ menu->help_text = (const char **) xmalloc (count * sizeof (char *));
+ }
+ else if (menu->allocated == menu->count)
+ {
+ int count = menu->allocated = menu->allocated + 10;
+ menu->text
+ = (char **) xrealloc (menu->text, count * sizeof (char *));
+ menu->submenu
+ = (tty_menu **) xrealloc (menu->submenu, count * sizeof (tty_menu *));
+ menu->panenumber
+ = (int *) xrealloc (menu->panenumber, count * sizeof (int));
+ menu->help_text
+ = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
+ }
+ }
+
+ /* Search the given menu structure for a given pane number. */
+
+ static tty_menu *
+ tty_menu_search_pane (tty_menu *menu, int pane)
+ {
+ int i;
+ tty_menu *try;
+
+ for (i = 0; i < menu->count; i++)
+ if (menu->submenu[i])
+ {
+ if (pane == menu->panenumber[i])
+ return menu->submenu[i];
+ if ((try = tty_menu_search_pane (menu->submenu[i], pane)))
+ return try;
+ }
+ return (tty_menu *) 0;
+ }
+
+ /* Determine how much screen space a given menu needs. */
+
+ static void
+ tty_menu_calc_size (tty_menu *menu, int *width, int *height)
+ {
+ int i, h2, w2, maxsubwidth, maxheight;
+
+ maxsubwidth = menu->width;
+ maxheight = menu->count;
+ for (i = 0; i < menu->count; i++)
+ {
+ if (menu->submenu[i])
+ {
+ tty_menu_calc_size (menu->submenu[i], &w2, &h2);
+ if (w2 > maxsubwidth) maxsubwidth = w2;
+ if (i + h2 > maxheight) maxheight = i + h2;
+ }
+ }
+ *width = maxsubwidth;
+ *height = maxheight;
+ }
+
+ static void
+ mouse_get_xy (int *x, int *y)
+ {
+ struct frame *sf = SELECTED_FRAME ();
+ Lisp_Object lmx = Qnil, lmy = Qnil, lisp_dummy;
+ enum scroll_bar_part part_dummy;
+ Time time_dummy;
+
+ if (FRAME_TERMINAL (sf)->mouse_position_hook)
+ (*FRAME_TERMINAL (sf)->mouse_position_hook) (&sf, -1,
+ &lisp_dummy, &part_dummy,
+ &lmx, &lmy,
+ &time_dummy);
+ if (!NILP (lmx))
+ {
+ *x = XINT (lmx);
+ *y = XINT (lmy);
+ }
+ }
+
+ /* Display MENU at (X,Y) using FACES. */
+
+ static void
+ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
+ int mx, int my, int disp_help)
+ {
+ int i, face, width, enabled, mousehere, row, col;
+ struct frame *sf = SELECTED_FRAME ();
+ struct tty_display_info *tty = FRAME_TTY (sf);
+
+ menu_help_message = NULL;
+
+ width = menu->width;
+ col = cursorX (tty);
+ row = cursorY (tty);
+ for (i = 0; i < menu->count; i++)
+ {
+ int max_width = width + 2; /* +2 for padding blanks on each side */
+
+ cursor_to (sf, y + i, x);
+ if (menu->submenu[i])
+ max_width += 2; /* for displaying " >" after the item */
+ enabled
+ = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
+ mousehere = (y + i == my && x <= mx && mx < x + max_width);
+ face = faces[enabled + mousehere * 2];
+ /* Display the menu help string for the i-th menu item even if
+ the menu item is currently disabled. That's what the GUI
+ code does. */
+ if (disp_help && enabled + mousehere * 2 >= 2)
+ {
+ menu_help_message = menu->help_text[i];
+ menu_help_paneno = pn - 1;
+ menu_help_itemno = i;
+ }
+ display_tty_menu_item (menu->text[i], max_width, face, x, y + i,
+ menu->submenu[i] != NULL);
+ }
+ update_frame_with_menu (sf);
+ cursor_to (sf, row, col);
+ }
+
+ /* --------------------------- X Menu emulation ---------------------- */
+
+ /* Report availability of menus. */
+
+ int
+ have_menus_p (void) { return 1; }
+
+ /* Create a new pane and place it on the outer-most level. */
+
+ static int
+ tty_menu_add_pane (tty_menu *menu, const char *txt)
+ {
+ int len;
+ const char *p;
+
+ tty_menu_make_room (menu);
+ menu->submenu[menu->count] = tty_menu_create ();
+ menu->text[menu->count] = (char *)txt;
+ menu->panenumber[menu->count] = ++menu->panecount;
+ menu->help_text[menu->count] = NULL;
+ menu->count++;
+
+ /* Update the menu width, if necessary. */
+ for (len = 0, p = txt; *p; )
+ {
+ int ch_len;
+ int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
+
+ len += CHAR_WIDTH (ch);
+ p += ch_len;
+ }
+
+ if (len > menu->width)
+ menu->width = len;
+
+ return menu->panecount;
+ }
+
+ /* Create a new item in a menu pane. */
+
+ int
+ tty_menu_add_selection (tty_menu *menu, int pane,
+ char *txt, int enable, char const *help_text)
+ {
+ int len;
+ char *p;
+
+ if (pane)
+ if (!(menu = tty_menu_search_pane (menu, pane)))
+ return TTYM_FAILURE;
+ tty_menu_make_room (menu);
+ menu->submenu[menu->count] = (tty_menu *) 0;
+ menu->text[menu->count] = txt;
+ menu->panenumber[menu->count] = enable;
+ menu->help_text[menu->count] = help_text;
+ menu->count++;
+
+ /* Update the menu width, if necessary. */
+ for (len = 0, p = txt; *p; )
+ {
+ int ch_len;
+ int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
+
+ len += CHAR_WIDTH (ch);
+ p += ch_len;
+ }
+
+ if (len > menu->width)
+ menu->width = len;
+
+ return TTYM_SUCCESS;
+ }
+
+ /* Decide where the menu would be placed if requested at (X,Y). */
+
+ void
+ tty_menu_locate (tty_menu *menu, int x, int y,
+ int *ulx, int *uly, int *width, int *height)
+ {
+ tty_menu_calc_size (menu, width, height);
+ *ulx = x + 1;
+ *uly = y;
+ *width += 2;
+ }
+
+ struct tty_menu_state
+ {
+ struct glyph_matrix *screen_behind;
+ tty_menu *menu;
+ int pane;
+ int x, y;
+ };
+
+ /* Save away the contents of frame F's current frame matrix, and
+ enable all its rows. Value is a glyph matrix holding the contents
+ of F's current frame matrix with all its glyph rows enabled. */
+
++static struct glyph_matrix *
+ save_and_enable_current_matrix (struct frame *f)
+ {
+ int i;
+ struct glyph_matrix *saved = xzalloc (sizeof *saved);
+ saved->nrows = f->current_matrix->nrows;
+ saved->rows = xzalloc (saved->nrows * sizeof *saved->rows);
+
+ for (i = 0; i < saved->nrows; ++i)
+ {
+ struct glyph_row *from = f->current_matrix->rows + i;
+ struct glyph_row *to = saved->rows + i;
+ ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
+ to->glyphs[TEXT_AREA] = xmalloc (nbytes);
+ memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
+ to->used[TEXT_AREA] = from->used[TEXT_AREA];
+ /* Make sure every row is enabled, or else update_frame will not
+ redraw them. (Rows that are identical to what is already on
+ screen will not be redrawn anyway.) */
+ to->enabled_p = 1;
+ to->hash = from->hash;
+ if (from->used[LEFT_MARGIN_AREA])
+ {
+ nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
+ to->glyphs[LEFT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
+ memcpy (to->glyphs[LEFT_MARGIN_AREA],
+ from->glyphs[LEFT_MARGIN_AREA], nbytes);
+ to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
+ }
+ if (from->used[RIGHT_MARGIN_AREA])
+ {
+ nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
+ to->glyphs[RIGHT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
+ memcpy (to->glyphs[RIGHT_MARGIN_AREA],
+ from->glyphs[RIGHT_MARGIN_AREA], nbytes);
+ to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
+ }
+ }
+
+ return saved;
+ }
+
+ /* Restore the contents of frame F's desired frame matrix from SAVED,
+ and free memory associated with SAVED. */
+
+ static void
+ restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
+ {
+ int i;
+
+ for (i = 0; i < saved->nrows; ++i)
+ {
+ struct glyph_row *from = saved->rows + i;
+ struct glyph_row *to = f->desired_matrix->rows + i;
+ ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
+ eassert (to->glyphs[TEXT_AREA] != from->glyphs[TEXT_AREA]);
+ memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
+ to->used[TEXT_AREA] = from->used[TEXT_AREA];
+ to->enabled_p = from->enabled_p;
+ to->hash = from->hash;
+ nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
+ if (nbytes)
+ {
+ eassert (to->glyphs[LEFT_MARGIN_AREA] != from->glyphs[LEFT_MARGIN_AREA]);
+ memcpy (to->glyphs[LEFT_MARGIN_AREA],
+ from->glyphs[LEFT_MARGIN_AREA], nbytes);
+ to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
+ }
+ else
+ to->used[LEFT_MARGIN_AREA] = 0;
+ nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
+ if (nbytes)
+ {
+ eassert (to->glyphs[RIGHT_MARGIN_AREA] != from->glyphs[RIGHT_MARGIN_AREA]);
+ memcpy (to->glyphs[RIGHT_MARGIN_AREA],
+ from->glyphs[RIGHT_MARGIN_AREA], nbytes);
+ to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
+ }
+ else
+ to->used[RIGHT_MARGIN_AREA] = 0;
+ }
+ }
+
+ static void
+ free_saved_screen (struct glyph_matrix *saved)
+ {
+ int i;
+
+ if (!saved)
+ return; /* already freed */
+
+ for (i = 0; i < saved->nrows; ++i)
+ {
+ struct glyph_row *from = saved->rows + i;
+
+ xfree (from->glyphs[TEXT_AREA]);
+ if (from->used[LEFT_MARGIN_AREA])
+ xfree (from->glyphs[LEFT_MARGIN_AREA]);
+ if (from->used[RIGHT_MARGIN_AREA])
+ xfree (from->glyphs[RIGHT_MARGIN_AREA]);
+ }
+
+ xfree (saved->rows);
+ xfree (saved);
+ }
+
+ /* Update the display of frame F from its saved contents. */
+ static void
+ screen_update (struct frame *f, struct glyph_matrix *mtx)
+ {
+ restore_desired_matrix (f, mtx);
+ update_frame_with_menu (f);
+ }
+
+ /* Read user input and return X and Y coordinates where that input
+ puts us. We only consider mouse movement and click events and
+ keyboard movement commands; the rest are ignored.
+
+ Value is -1 if C-g was pressed, 1 if an item was selected, 2 or 3
+ if we need to move to the next or previous menu-bar menu, zero
+ otherwise. */
+ static int
+ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
+ bool *first_time)
+ {
+ if (*first_time)
+ {
+ *first_time = false;
+ sf->mouse_moved = 1;
+ }
+ else
+ {
+ extern Lisp_Object read_menu_command (void);
+ Lisp_Object cmd;
+ int usable_input = 1;
+ int st = 0;
+ struct tty_display_info *tty = FRAME_TTY (sf);
+ Lisp_Object saved_mouse_tracking = do_mouse_tracking;
+
+ /* Signal the keyboard reading routines we are displaying a menu
+ on this terminal. */
+ tty->showing_menu = 1;
+ /* We want mouse movements be reported by read_menu_command. */
+ do_mouse_tracking = Qt;
+ do {
+ cmd = read_menu_command ();
+ } while (NILP (cmd));
+ tty->showing_menu = 0;
+ do_mouse_tracking = saved_mouse_tracking;
+
+ if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
+ return -1;
+ if (EQ (cmd, Qtty_menu_mouse_movement))
+ {
+ int mx, my;
+
+ mouse_get_xy (&mx, &my);
+ *x = mx;
+ *y = my;
+ }
+ else if (EQ (cmd, Qtty_menu_next_menu))
+ {
+ usable_input = 0;
+ st = 2;
+ }
+ else if (EQ (cmd, Qtty_menu_prev_menu))
+ {
+ usable_input = 0;
+ st = 3;
+ }
+ else if (EQ (cmd, Qtty_menu_next_item))
+ {
+ if (*y < max_y)
+ *y += 1;
+ }
+ else if (EQ (cmd, Qtty_menu_prev_item))
+ {
+ if (*y > min_y)
+ *y -= 1;
+ }
+ else if (EQ (cmd, Qtty_menu_select))
+ st = 1;
+ else if (!EQ (cmd, Qtty_menu_ignore))
+ usable_input = 0;
+ if (usable_input)
+ sf->mouse_moved = 1;
+ return st;
+ }
+ return 0;
+ }
+
+ /* Display menu, wait for user's response, and return that response. */
+ static int
+ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
+ int x0, int y0, char **txt,
+ void (*help_callback)(char const *, int, int),
+ int kbd_navigation)
+ {
+ struct tty_menu_state *state;
+ int statecount, x, y, i, b, leave, result, onepane;
+ int title_faces[4]; /* face to display the menu title */
+ int faces[4], buffers_num_deleted = 0;
+ struct frame *sf = SELECTED_FRAME ();
+ struct tty_display_info *tty = FRAME_TTY (sf);
+ bool first_time;
+ Lisp_Object saved_echo_area_message, selectface;
+
+ /* Don't allow non-positive x0 and y0, lest the menu will wrap
+ around the display. */
+ if (x0 <= 0)
+ x0 = 1;
+ if (y0 <= 0)
+ y0 = 1;
+
+ state = alloca (menu->panecount * sizeof (struct tty_menu_state));
+ memset (state, 0, sizeof (*state));
+ faces[0]
+ = lookup_derived_face (sf, intern ("tty-menu-disabled-face"),
+ DEFAULT_FACE_ID, 1);
+ faces[1]
+ = lookup_derived_face (sf, intern ("tty-menu-enabled-face"),
+ DEFAULT_FACE_ID, 1);
+ selectface = intern ("tty-menu-selected-face");
+ faces[2] = lookup_derived_face (sf, selectface,
+ faces[0], 1);
+ faces[3] = lookup_derived_face (sf, selectface,
+ faces[1], 1);
+
+ /* Make sure the menu title is always displayed with
+ `tty-menu-selected-face', no matter where the mouse pointer is. */
+ for (i = 0; i < 4; i++)
+ title_faces[i] = faces[3];
+
+ statecount = 1;
+
+ /* Don't let the title for the "Buffers" popup menu include a
+ digit (which is ugly).
+
+ This is a terrible kludge, but I think the "Buffers" case is
+ the only one where the title includes a number, so it doesn't
+ seem to be necessary to make this more general. */
+ if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
+ {
+ menu->text[0][7] = '\0';
+ buffers_num_deleted = 1;
+ }
+
+ /* Force update of the current frame, so that the desired and the
+ current matrices are identical. */
+ update_frame_with_menu (sf);
+ state[0].menu = menu;
+ state[0].screen_behind = save_and_enable_current_matrix (sf);
+
+ /* Display the menu title. We subtract 1 from x0 and y0 because we
+ want to interpret them as zero-based column and row coordinates,
+ and also because we want the first item of the menu, not its
+ title, to appear at x0,y0. */
+ tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0);
+
+ /* Turn off the cursor. Otherwise it shows through the menu
+ panes, which is ugly. */
+ tty_hide_cursor (tty);
+ if (buffers_num_deleted)
+ menu->text[0][7] = ' ';
+ if ((onepane = menu->count == 1 && menu->submenu[0]))
+ {
+ menu->width = menu->submenu[0]->width;
+ state[0].menu = menu->submenu[0];
+ }
+ else
+ {
+ state[0].menu = menu;
+ }
+ state[0].x = x0 - 1;
+ state[0].y = y0;
+ state[0].pane = onepane;
+
+ x = state[0].x;
+ y = state[0].y;
+ first_time = true;
+
+ leave = 0;
+ while (!leave)
+ {
+ int input_status;
+ int min_y = state[0].y, max_y = min_y + state[0].menu->count - 1;
+
+ input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
+ if (input_status)
+ {
+ leave = 1;
+ if (input_status == -1)
+ {
+ /* Remove the last help-echo, so that it doesn't
+ re-appear after "Quit". */
+ show_help_echo (Qnil, Qnil, Qnil, Qnil);
+ result = TTYM_NO_SELECT;
+ }
+ else if (input_status == 2)
+ {
+ if (kbd_navigation)
+ result = TTYM_NEXT;
+ else
+ leave = 0;
+ }
+ else if (input_status == 3)
+ {
+ if (kbd_navigation)
+ result = TTYM_PREV;
+ else
+ leave = 0;
+ }
+ }
+ if (sf->mouse_moved && input_status != -1)
+ {
+ sf->mouse_moved = 0;
+ result = TTYM_IA_SELECT;
+ for (i = 0; i < statecount; i++)
+ if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
+ {
+ int dy = y - state[i].y;
+ if (0 <= dy && dy < state[i].menu->count)
+ {
+ if (!state[i].menu->submenu[dy])
+ {
+ if (state[i].menu->panenumber[dy])
+ result = TTYM_SUCCESS;
+ else
+ result = TTYM_IA_SELECT;
+ }
+ *pane = state[i].pane - 1;
+ *selidx = dy;
+ /* We hit some part of a menu, so drop extra menus that
+ have been opened. That does not include an open and
+ active submenu. */
+ if (i != statecount - 2
+ || state[i].menu->submenu[dy] != state[i+1].menu)
+ while (i != statecount - 1)
+ {
+ statecount--;
+ screen_update (sf, state[statecount].screen_behind);
+ state[statecount].screen_behind = NULL;
+ }
+ if (i == statecount - 1 && state[i].menu->submenu[dy])
+ {
+ tty_menu_display (state[i].menu,
+ state[i].x,
+ state[i].y,
+ state[i].pane,
+ faces, x, y, 1);
+ state[statecount].menu = state[i].menu->submenu[dy];
+ state[statecount].pane = state[i].menu->panenumber[dy];
+ state[statecount].screen_behind
+ = save_and_enable_current_matrix (sf);
+ state[statecount].x
+ = state[i].x + state[i].menu->width + 2;
+ state[statecount].y = y;
+ statecount++;
+ }
+ }
+ }
+ tty_menu_display (state[statecount - 1].menu,
+ state[statecount - 1].x,
+ state[statecount - 1].y,
+ state[statecount - 1].pane,
+ faces, x, y, 1);
+ tty_hide_cursor (tty);
+ fflush (tty->output);
+ }
+
+ /* Display the help-echo message for the currently-selected menu
+ item. */
+ if ((menu_help_message || prev_menu_help_message)
+ && menu_help_message != prev_menu_help_message)
+ {
+ help_callback (menu_help_message,
+ menu_help_paneno, menu_help_itemno);
+ tty_hide_cursor (tty);
+ fflush (tty->output);
+ prev_menu_help_message = menu_help_message;
+ }
+ }
+
+ sf->mouse_moved = 0;
+ screen_update (sf, state[0].screen_behind);
+ while (statecount--)
+ free_saved_screen (state[statecount].screen_behind);
+ tty_show_cursor (tty); /* turn cursor back on */
+
+ /* Clean up any mouse events that are waiting inside Emacs event queue.
+ These events are likely to be generated before the menu was even
+ displayed, probably because the user pressed and released the button
+ (which invoked the menu) too quickly. If we don't remove these events,
+ Emacs will process them after we return and surprise the user. */
+ discard_mouse_events ();
+ if (!kbd_buffer_events_waiting ())
+ clear_input_pending ();
+ SET_FRAME_GARBAGED (sf);
+ return result;
+ }
+
+ /* Dispose of a menu. */
+
+ void
+ tty_menu_destroy (tty_menu *menu)
+ {
+ int i;
+ if (menu->allocated)
+ {
+ for (i = 0; i < menu->count; i++)
+ if (menu->submenu[i])
+ tty_menu_destroy (menu->submenu[i]);
+ xfree (menu->text);
+ xfree (menu->submenu);
+ xfree (menu->panenumber);
+ xfree (menu->help_text);
+ }
+ xfree (menu);
+ menu_help_message = prev_menu_help_message = NULL;
+ }
+
+ /* Show help HELP_STRING, or clear help if HELP_STRING is null.
+
+ PANE is the pane number, and ITEM is the menu item number in
+ the menu (currently not used). */
+
+ static void
+ tty_menu_help_callback (char const *help_string, int pane, int item)
+ {
+ Lisp_Object *first_item;
+ Lisp_Object pane_name;
+ Lisp_Object menu_object;
+
+ first_item = XVECTOR (menu_items)->u.contents;
+ if (EQ (first_item[0], Qt))
+ pane_name = first_item[MENU_ITEMS_PANE_NAME];
+ else if (EQ (first_item[0], Qquote))
+ /* This shouldn't happen, see xmenu_show. */
+ pane_name = empty_unibyte_string;
+ else
+ pane_name = first_item[MENU_ITEMS_ITEM_NAME];
+
+ /* (menu-item MENU-NAME PANE-NUMBER) */
+ menu_object = list3 (Qmenu_item, pane_name, make_number (pane));
+ show_help_echo (help_string ? build_string (help_string) : Qnil,
+ Qnil, menu_object, make_number (item));
+ }
+
+ static void
+ tty_pop_down_menu (Lisp_Object arg)
+ {
+ tty_menu *menu = XSAVE_POINTER (arg, 0);
+
+ block_input ();
+ tty_menu_destroy (menu);
+ unblock_input ();
+ }
+
+ /* Return the zero-based index of the last menu-bar item on frame F. */
+ static int
+ tty_menu_last_menubar_item (struct frame *f)
+ {
+ int i = 0;
+
+ eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
+ if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
+ {
+ Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
+
+ while (i < ASIZE (items))
+ {
+ Lisp_Object str;
+
+ str = AREF (items, i + 1);
+ if (NILP (str))
+ break;
+ i += 4;
+ }
+ i -= 4; /* went one too far */
+ }
+ return i;
+ }
+
+ /* Find in frame F's menu bar the menu item that is next or previous
+ to the item at X/Y, and return that item's position in X/Y. WHICH
+ says which one--next or previous--item to look for. X and Y are
+ measured in character cells. This should only be called on TTY
+ frames. */
+ static void
+ tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y)
+ {
+ eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
+ if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
+ {
+ Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
+ int last_i = tty_menu_last_menubar_item (f);
+ int i, prev_x;
+
+ /* This loop assumes a single menu-bar line, and will fail to
+ find an item if it is not in the first line. Note that
+ make_lispy_event in keyboard.c makes the same assumption. */
+ for (i = 0, prev_x = -1; i < ASIZE (items); i += 4)
+ {
+ Lisp_Object pos, str;
+ int ix;
+
+ str = AREF (items, i + 1);
+ pos = AREF (items, i + 3);
+ if (NILP (str))
+ return;
+ ix = XINT (pos);
+ if (ix <= *x
+ /* We use <= so the blank between 2 items on a TTY is
+ considered part of the previous item. */
+ && *x <= ix + menu_item_width (SSDATA (str)))
+ {
+ /* Found current item. Now compute the X coordinate of
+ the previous or next item. */
+ if (which == TTYM_NEXT)
+ {
+ if (i < last_i)
+ *x = XINT (AREF (items, i + 4 + 3));
+ else
+ *x = 0; /* wrap around to the first item */
+ }
+ else if (prev_x < 0)
+ {
+ /* Wrap around to the last item. */
+ *x = XINT (AREF (items, last_i + 3));
+ }
+ else
+ *x = prev_x;
+ return;
+ }
+ prev_x = ix;
+ }
+ }
+ }
+
+ Lisp_Object
+ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
+ Lisp_Object title, int kbd_navigation, const char **error_name)
+ {
+ tty_menu *menu;
+ int pane, selidx, lpane, status;
+ Lisp_Object entry, pane_prefix;
+ char *datap;
+ int ulx, uly, width, height;
+ int item_x, item_y;
+ int dispwidth, dispheight;
+ int i, j, lines, maxlines;
+ int maxwidth;
+ int dummy_int;
+ unsigned int dummy_uint;
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+
+ if (! FRAME_TERMCAP_P (f))
+ emacs_abort ();
+
+ *error_name = 0;
+ if (menu_items_n_panes == 0)
+ return Qnil;
+
+ if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
+ {
+ *error_name = "Empty menu";
+ return Qnil;
+ }
+
+ /* Make the menu on that window. */
+ menu = tty_menu_create ();
+ if (menu == NULL)
+ {
+ *error_name = "Can't create menu";
+ return Qnil;
+ }
+
+ /* Don't GC while we prepare and show the menu, because we give the
+ menu functions pointers to the contents of strings. */
+ inhibit_garbage_collection ();
+
+ /* Adjust coordinates to be root-window-relative. */
+ item_x = x += f->left_pos;
+ item_y = y += f->top_pos;
+
+ /* Create all the necessary panes and their items. */
+ maxwidth = maxlines = lines = i = 0;
+ lpane = TTYM_FAILURE;
+ while (i < menu_items_used)
+ {
+ if (EQ (AREF (menu_items, i), Qt))
+ {
+ /* Create a new pane. */
+ Lisp_Object pane_name, prefix;
+ const char *pane_string;
+
+ maxlines = max (maxlines, lines);
+ lines = 0;
+ pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
+ prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
+ pane_string = (NILP (pane_name)
+ ? "" : SSDATA (pane_name));
+ if (keymaps && !NILP (prefix))
+ pane_string++;
+
+ lpane = tty_menu_add_pane (menu, pane_string);
+ if (lpane == TTYM_FAILURE)
+ {
+ tty_menu_destroy (menu);
+ *error_name = "Can't create pane";
+ return Qnil;
+ }
+ i += MENU_ITEMS_PANE_LENGTH;
+
+ /* Find the width of the widest item in this pane. */
+ j = i;
+ while (j < menu_items_used)
+ {
+ Lisp_Object item;
+ item = AREF (menu_items, j);
+ if (EQ (item, Qt))
+ break;
+ if (NILP (item))
+ {
+ j++;
+ continue;
+ }
+ width = SBYTES (item);
+ if (width > maxwidth)
+ maxwidth = width;
+
+ j += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ /* Ignore a nil in the item list.
+ It's meaningful only for dialog boxes. */
+ else if (EQ (AREF (menu_items, i), Qquote))
+ i += 1;
+ else
+ {
+ /* Create a new item within current pane. */
+ Lisp_Object item_name, enable, descrip, help;
+ char *item_data;
+ char const *help_string;
+
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
+ descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
+ help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
+ help_string = STRINGP (help) ? SSDATA (help) : NULL;
+
+ if (!NILP (descrip))
+ {
+ /* if alloca is fast, use that to make the space,
+ to reduce gc needs. */
+ item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
+ memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
+ for (j = SCHARS (item_name); j < maxwidth; j++)
+ item_data[j] = ' ';
+ memcpy (item_data + j, SSDATA (descrip), SBYTES (descrip));
+ item_data[j + SBYTES (descrip)] = 0;
+ }
+ else
+ item_data = SSDATA (item_name);
+
+ if (lpane == TTYM_FAILURE
+ || (tty_menu_add_selection (menu, lpane, item_data,
+ !NILP (enable), help_string)
+ == TTYM_FAILURE))
+ {
+ tty_menu_destroy (menu);
+ *error_name = "Can't add selection to menu";
+ return Qnil;
+ }
+ i += MENU_ITEMS_ITEM_LENGTH;
+ lines++;
+ }
+ }
+
+ maxlines = max (maxlines, lines);
+
+ /* All set and ready to fly. */
+ dispwidth = f->text_cols;
+ dispheight = f->text_lines;
+ x = min (x, dispwidth);
+ y = min (y, dispheight);
+ x = max (x, 1);
+ y = max (y, 1);
+ tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
+ if (ulx+width > dispwidth)
+ {
+ x -= (ulx + width) - dispwidth;
+ ulx = dispwidth - width;
+ }
+ if (uly+height > dispheight)
+ {
+ y -= (uly + height) - dispheight;
+ uly = dispheight - height;
+ }
+
+ if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 2)
+ {
+ /* Move the menu away of the echo area, to avoid overwriting the
+ menu with help echo messages or vice versa. */
+ if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
+ {
+ y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
+ uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
+ }
+ else
+ {
+ y -= 2;
+ uly -= 2;
+ }
+ }
+
+ if (ulx < 0) x -= ulx;
+ if (uly < 0) y -= uly;
+
+ #if 0
+ /* This code doesn't make sense on a TTY, since it can easily annul
+ the adjustments above that carefully avoid truncation of the menu
+ items. I think it was written to fix some problem that only
+ happens on X11. */
+ if (! for_click)
+ {
+ /* If position was not given by a mouse click, adjust so upper left
+ corner of the menu as a whole ends up at given coordinates. This
+ is what x-popup-menu says in its documentation. */
+ x += width/2;
+ y += 1.5*height/(maxlines+2);
+ }
+ #endif
+
+ pane = selidx = 0;
+
+ record_unwind_protect (tty_pop_down_menu, make_save_ptr (menu));
+
+ specbind (Qoverriding_terminal_local_map,
+ Fsymbol_value (Qtty_menu_navigation_map));
+ status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
+ tty_menu_help_callback, kbd_navigation);
+ entry = pane_prefix = Qnil;
+
+ switch (status)
+ {
+ case TTYM_SUCCESS:
+ /* Find the item number SELIDX in pane number PANE. */
+ i = 0;
+ while (i < menu_items_used)
+ {
+ if (EQ (AREF (menu_items, i), Qt))
+ {
+ if (pane == 0)
+ pane_prefix
+ = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
+ pane--;
+ i += MENU_ITEMS_PANE_LENGTH;
+ }
+ else
+ {
+ if (pane == -1)
+ {
+ if (selidx == 0)
+ {
+ entry
+ = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
+ if (keymaps != 0)
+ {
+ entry = Fcons (entry, Qnil);
+ if (!NILP (pane_prefix))
+ entry = Fcons (pane_prefix, entry);
+ }
+ break;
+ }
+ selidx--;
+ }
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ break;
+
+ case TTYM_NEXT:
+ case TTYM_PREV:
+ tty_menu_new_item_coords (f, status, &item_x, &item_y);
+ entry = Fcons (make_number (item_x), make_number (item_y));
+ break;
+
+ case TTYM_FAILURE:
+ *error_name = "Can't activate menu";
+ case TTYM_IA_SELECT:
+ break;
+ case TTYM_NO_SELECT:
+ /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
+ the menu was invoked with a mouse event as POSITION). */
+ if (! for_click)
+ Fsignal (Qquit, Qnil);
+ break;
+ }
+
+ unbind_to (specpdl_count, Qnil);
+
+ return entry;
+ }
+
+ #endif /* HAVE_MENUS && !MSDOS */
+
\f
#ifndef MSDOS
/***********************************************************************