## This is an option because I do not know if all info/man support
## compressed files, nor how to test if they do so.
- OPTION_DEFAULT_ON([compress-info],[don't compress the installed Info pages])
- if test $with_compress_info = yes; then
- GZIP_INFO=yes
- else
- GZIP_INFO=
- fi
- AC_SUBST(GZIP_INFO)
+ OPTION_DEFAULT_ON([compress-install],
+ [don't compress some files (.el, .info, etc.) when installing. Equivalent to:
+ make GZIP_PROG= install])
AC_ARG_WITH([pkg-config-prog],dnl
[AS_HELP_STRING([--with-pkg-config-prog=FILENAME],
* ) srcdir=`(cd "$srcdir"; pwd)` ;;
esac
+ #### When building with MinGW inside the MSYS tree, 'pwd' produces
+ #### directories relative to the root of the MSYS tree,
+ #### e.g. '/home/user/foo' instead of '/d/MSYS/home/user/foo'. When
+ #### such a value of srcdir is written to the top-level Makefile, it
+ #### gets propagated to src/epaths.h, and that causes temacs to fail,
+ #### because, being a MinGW program that knows nothing of MSYS root
+ #### substitution, it cannot find the data directory. "pwd -W"
+ #### produces Windows-style 'd:/foo/bar' absolute directory names, so
+ #### we use it here to countermand that lossage.
+ test "$MSYSTEM" = "MINGW32" && srcdir=`(cd "$srcdir"; pwd -W | sed -e 's,^\([[A-Za-z]]\):,/\1,')`
+
### Canonicalize the configuration name.
AC_CANONICAL_HOST
]
)
+ # clang is unduly picky about some things.
+ AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+ #ifndef __clang__
+ #error "not clang"
+ #endif
+ ]])],
+ [emacs_cv_clang=yes],
+ [emacs_cv_clang=no])])
+
# When compiling with GCC, prefer -isystem to -I when including system
# include files, to avoid generating useless diagnostics for the files.
if test "$gl_gcc_warnings" != yes; then
isystem='-I'
+ if test "$emacs_cv_clang" = yes
+ then
+ # Turn off some warnings if supported.
+ gl_WARN_ADD([-Wno-switch])
+ gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare])
+ gl_WARN_ADD([-Wno-pointer-sign])
+ fi
else
isystem='-isystem '
# The following line should be removable at some point.
nw="$nw -Wsuggest-attribute=pure"
- # clang is unduly picky about some things.
- AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
- [AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([[
- #ifndef __clang__
- #error "not clang"
- #endif
- ]])],
- [emacs_cv_clang=yes],
- [emacs_cv_clang=no])])
+ # This part is merely for shortening the command line,
+ # since -Wno-FOO needs to be added below regardless.
+ nw="$nw -Wmissing-field-initializers"
+ nw="$nw -Wswitch"
+ nw="$nw -Wtype-limits"
+ nw="$nw -Wunused-parameter"
+
if test $emacs_cv_clang = yes; then
nw="$nw -Wcast-align"
fi
gl_WARN_ADD([-Wno-unused-value])
fi
- gl_WARN_ADD([-fdiagnostics-show-option])
- gl_WARN_ADD([-funit-at-a-time])
-
AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
AH_VERBATIM([FORTIFY_SOURCE],
[/* Enable compile-time and run-time bounds-checking, and some warnings,
dnl Don't use GZIP, which is used by gzip for additional parameters.
AC_PATH_PROG(GZIP_PROG, gzip)
+ test $with_compress_install != yes && test -n "$GZIP_PROG" && \
+ GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)"
+
if test $opsys = gnu-linux; then
AC_PATH_PROG(PAXCTL, paxctl,,
[$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin])
dnl Treat GCC specially since it just gives a non-fatal `unrecognized option'
dnl if not built to support GNU ld.
- late_LDFLAGS=$LDFLAGS
+ dnl For a long time, -znocombreloc was added to LDFLAGS rather than
+ dnl LD_SWITCH_SYSTEM_TEMACS. That is:
+ dnl * inappropriate, as LDFLAGS is a user option but this is essential.
+ dnl Eg "make LDFLAGS=... all" could run into problems,
+ dnl http://bugs.debian.org/684788
+ dnl * unnecessary, since temacs is the only thing that actually needs it.
+ dnl Indeed this is where it was originally, prior to:
+ dnl http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-03/msg00170.html
+ late_LDFLAGS="$LDFLAGS"
if test x$GCC = xyes; then
- LDFLAGS="$LDFLAGS -Wl,-znocombreloc"
+ LDFLAGS_NOCOMBRELOC="-Wl,-znocombreloc"
else
- LDFLAGS="$LDFLAGS -znocombreloc"
+ LDFLAGS_NOCOMBRELOC="-znocombreloc"
fi
+ LDFLAGS="$LDFLAGS $LDFLAGS_NOCOMBRELOC"
+
AC_MSG_CHECKING([for -znocombreloc])
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
[AC_MSG_RESULT(yes)],
- LDFLAGS=$late_LDFLAGS
+ LDFLAGS_NOCOMBRELOC=
[AC_MSG_RESULT(no)])
+ LDFLAGS="$late_LDFLAGS"
dnl The function dump-emacs will not be defined and temacs will do
dnl (load "loadup") automatically unless told otherwise.
[AC_MSG_ERROR([`--with-ns' was specified, but the include
files are missing or cannot be compiled.])])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <AppKit/AppKit.h>],
+ macfont_file=""
+ if test "${NS_IMPL_COCOA}" = "yes"; then
+ AC_MSG_CHECKING([for OSX 10.4 or newer])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <AppKit/AppKit.h>],
[
#ifdef MAC_OS_X_VERSION_MAX_ALLOWED
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
])],
ns_osx_have_104=yes,
ns_osx_have_104=no)
+ AC_MSG_RESULT([$ns_osx_have_104])
+
+ if test $ns_osx_have_104 = no; then
+ AC_MSG_ERROR([`OSX 10.4 or newer is required']);
+ fi
+ AC_MSG_CHECKING([for OSX 10.5 or newer])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <AppKit/AppKit.h>],
+ [
+ #ifdef MAC_OS_X_VERSION_MAX_ALLOWED
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+ ; /* OK */
+ #else
+ #error "OSX 10.5 not found"
+ #endif
+ #endif
+ ])],
+ ns_osx_have_105=yes,
+ ns_osx_have_105=no)
+ AC_MSG_RESULT([$ns_osx_have_105])
+ if test $ns_osx_have_105 = yes; then
+ macfont_file="macfont.o"
+ fi
+ fi
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <Foundation/NSObjCRuntime.h>],
[NSInteger i;])],
ns_have_nsinteger=yes,
ns_have_nsinteger=no)
- if test $ns_osx_have_104 = no; then
- AC_MSG_ERROR([`OSX 10.4 or newer is required']);
- fi
if test $ns_have_nsinteger = yes; then
AC_DEFINE(NS_HAVE_NSINTEGER, 1, [Define to 1 if `NSInteger' is defined.])
fi
leimdir="\${ns_appresdir}/leim"
INSTALL_ARCH_INDEP_EXTRA=
fi
- NS_OBJC_OBJ="nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o"
+
+ NS_OBJC_OBJ="nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o $macfont_file"
fi
CFLAGS="$tmp_CFLAGS"
CPPFLAGS="$tmp_CPPFLAGS"
if test "$window_system" = none && test "$gl_gcc_warnings" = yes; then
# Too many warnings for now.
+ nw=
+ nw="$nw -Wsuggest-attribute=const"
+ nw="$nw -Wsuggest-attribute=noreturn"
+ gl_MANYWARN_COMPLEMENT([WARN_CFLAGS], [$WARN_CFLAGS], [$nw])
+
gl_WARN_ADD([-Wno-unused-variable])
gl_WARN_ADD([-Wno-unused-but-set-variable])
gl_WARN_ADD([-Wno-unused-but-set-parameter])
fi
fi
-### If we're using X11, we should use the X menu package.
-HAVE_MENUS=no
-case ${HAVE_X11} in
- yes ) HAVE_MENUS=yes ;;
-esac
+### We always support menus.
+HAVE_MENUS=yes
# Does the opsystem file prohibit the use of the GNU malloc?
# Assume not, until told otherwise.
SAVE_LIBS="$LIBS"
CFLAGS="$SETTINGS_CFLAGS $CFLAGS"
LIBS="$SETTINGS_LIBS $LIBS"
- AC_CHECK_FUNCS([g_type_init])
CFLAGS="$SAVE_CFLAGS"
LIBS="$SAVE_LIBS"
fi
## Extra CFLAGS applied to src/*.m files.
GNU_OBJC_CFLAGS="$GNU_OBJC_CFLAGS -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGSWARN -DGSDIAGNOSE"
fi
- # We also have mouse menus.
- HAVE_MENUS=yes
OTHER_FILES=ns-app
fi
-if test "${HAVE_W32}" = "yes"; then
- HAVE_MENUS=yes
-fi
-
### Use session management (-lSM -lICE) if available
HAVE_X_SM=no
LIBXSM=
AC_SUBST(DESLIB)
AC_SUBST(KRB4LIB)
+ AC_CHECK_HEADERS(valgrind/valgrind.h)
+
AC_CHECK_FUNCS_ONCE(tzset)
AC_MSG_CHECKING(whether localtime caches TZ)
AC_CACHE_VAL(emacs_cv_localtime_cache,
if test "${HAVE_MENUS}" = "yes" ; then
AC_DEFINE(HAVE_MENUS, 1,
- [Define to 1 if you have mouse menus.
- (This is automatic if you use X, but the option to specify it remains.)
- It is also defined with other window systems that support xmenu.c.])
+ [Define to 1 if you have mouse menus. (This is supported in all configurations, but the option to specify it remains.)])
fi
if test "${GNU_MALLOC}" = "yes" ; then
AC_SUBST(PRE_ALLOC_OBJ)
AC_SUBST(POST_ALLOC_OBJ)
+ dnl Call this 'FORTIFY_SOUR' so that it sorts before the 'FORTIFY_SOURCE'
+ dnl verbatim defined above. The tricky name is apropos, as this hack
+ dnl makes Fortify go sour!
+ AH_VERBATIM([FORTIFY_SOUR],
+ [/* Without the following workaround, Emacs runs slowly on OS X 10.8.
+ The workaround disables some useful run-time checking, so it
+ should be conditional to the platforms with the performance bug.
+ Perhaps Apple will fix this some day; also see m4/extern-inline.m4. */
+ #if defined __APPLE__ && defined __GNUC__
+ # ifndef _DONT_USE_CTYPE_INLINE_
+ # define _DONT_USE_CTYPE_INLINE_
+ # endif
+ # ifndef _FORTIFY_SOURCE
+ # define _FORTIFY_SOURCE 0
+ # endif
+ #endif
+ ])
+
# Configure gnulib. Although this does not affect CFLAGS or LIBS permanently.
# it temporarily reverts them to their pre-pkg-config values,
# because gnulib needs to work with both src (which uses the
esac
fi
+ LD_SWITCH_SYSTEM_TEMACS="$LDFLAGS_NOCOMBRELOC $LD_SWITCH_SYSTEM_TEMACS"
+
AC_SUBST(LD_SWITCH_SYSTEM_TEMACS)
## MinGW-specific post-link processing of temacs.
;;; Frame creation.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ (declare-function x-display-list "xfns.c" ())
+ (declare-function x-open-connection "xfns.c"
+ (display &optional xrm-string must-succeed))
+ (declare-function x-get-resource "frame.c"
+ (attribute class &optional component subclass))
(declare-function x-parse-geometry "frame.c" (string))
(defvar x-display-name)
(defun tty-set-up-initial-frame-faces ()
(let ((frame (selected-frame)))
(frame-set-background-mode frame t)
- (face-set-after-frame-default frame)))
-
+ (face-set-after-frame-default frame)
+ (make-face 'tty-menu-enabled-face)
+ (make-face 'tty-menu-disabled-face)
+ (make-face 'tty-menu-selected-face)
+ (set-face-foreground 'tty-menu-enabled-face "yellow")
+ (set-face-foreground 'tty-menu-disabled-face "white")
+ (set-face-background 'tty-menu-enabled-face "blue")
+ (set-face-background 'tty-menu-disabled-face "blue")
+ (set-face-background 'tty-menu-selected-face "red")))
\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\f
;; Provide a mode-specific menu on a mouse button.
-(defun popup-menu (menu &optional position prefix)
- "Popup the given menu and call the selected option.
-MENU can be a keymap, an easymenu-style menu or a list of keymaps as for
-`x-popup-menu'.
-The menu is shown at the place where POSITION specifies. About
-the form of POSITION, see `popup-menu-normalize-position'.
-PREFIX is the prefix argument (if any) to pass to the command."
- (let* ((map (cond
- ((keymapp menu) menu)
- ((and (listp menu) (keymapp (car menu))) menu)
- (t (let* ((map (easy-menu-create-menu (car menu) (cdr menu)))
- (filter (when (symbolp map)
- (plist-get (get map 'menu-prop) :filter))))
- (if filter (funcall filter (symbol-function map)) map)))))
- event cmd
- (position (popup-menu-normalize-position position)))
- ;; The looping behavior was taken from lmenu's popup-menu-popup
- (while (and map (setq event
- ;; map could be a prefix key, in which case
- ;; we need to get its function cell
- ;; definition.
- (x-popup-menu position (indirect-function map))))
- ;; Strangely x-popup-menu returns a list.
- ;; mouse-major-mode-menu was using a weird:
- ;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
- (setq cmd
- (if (and (not (keymapp map)) (listp map))
- ;; We were given a list of keymaps. Search them all
- ;; in sequence until a first binding is found.
- (let ((mouse-click (apply 'vector event))
- binding)
- (while (and map (null binding))
- (setq binding (lookup-key (car map) mouse-click))
- (if (numberp binding) ; `too long'
- (setq binding nil))
- (setq map (cdr map)))
- binding)
- ;; We were given a single keymap.
- (lookup-key map (apply 'vector event))))
- ;; Clear out echoing, which perhaps shows a prefix arg.
- (message "")
- ;; Maybe try again but with the submap.
- (setq map (if (keymapp cmd) cmd)))
- ;; If the user did not cancel by refusing to select,
- ;; and if the result is a command, run it.
- (when (and (null map) (commandp cmd))
- (setq prefix-arg prefix)
- ;; `setup-specified-language-environment', for instance,
- ;; expects this to be set from a menu keymap.
- (setq last-command-event (car (last event)))
- ;; mouse-major-mode-menu was using `command-execute' instead.
- (call-interactively cmd))))
-
-(defun popup-menu-normalize-position (position)
- "Convert the POSITION to the form which `popup-menu' expects internally.
-POSITION can an event, a posn- value, a value having
-form ((XOFFSET YOFFSET) WINDOW), or nil.
-If nil, the current mouse position is used."
- (pcase position
- ;; nil -> mouse cursor position
- (`nil
- (let ((mp (mouse-pixel-position)))
- (list (list (cadr mp) (cddr mp)) (car mp))))
- ;; Value returned from `event-end' or `posn-at-point'.
- ((pred posnp)
- (let ((xy (posn-x-y position)))
- (list (list (car xy) (cdr xy))
- (posn-window position))))
- ;; Event.
- ((pred eventp)
- (popup-menu-normalize-position (event-end position)))
- (t position)))
-
(defun minor-mode-menu-from-indicator (indicator)
"Show menu for minor mode specified by INDICATOR.
Interactively, INDICATOR is read using completion.
(deactivate-mark)))
(or mouse-yank-at-point (mouse-set-point click))
(let ((primary
- (cond
- ((eq (framep (selected-frame)) 'w32)
- ;; MS-Windows emulates PRIMARY in x-get-selection, but not
- ;; in x-get-selection-value (the latter only accesses the
- ;; clipboard). So try PRIMARY first, in case they selected
- ;; something with the mouse in the current Emacs session.
- (or (x-get-selection 'PRIMARY)
- (x-get-selection-value)))
- ((fboundp 'x-get-selection-value) ; MS-DOS and X.
- ;; On X, x-get-selection-value supports more formats and
- ;; encodings, so use it in preference to x-get-selection.
- (or (x-get-selection-value)
- (x-get-selection 'PRIMARY)))
- ;; FIXME: What about xterm-mouse-mode etc.?
- (t
- (x-get-selection 'PRIMARY)))))
+ (if (fboundp 'x-get-selection-value)
+ (if (eq (framep (selected-frame)) 'w32)
+ ;; MS-Windows emulates PRIMARY in x-get-selection, but not
+ ;; in x-get-selection-value (the latter only accesses the
+ ;; clipboard). So try PRIMARY first, in case they selected
+ ;; something with the mouse in the current Emacs session.
+ (or (x-get-selection 'PRIMARY)
+ (x-get-selection-value))
+ ;; Else MS-DOS or X.
+ ;; On X, x-get-selection-value supports more formats and
+ ;; encodings, so use it in preference to x-get-selection.
+ (or (x-get-selection-value)
+ (x-get-selection 'PRIMARY)))
+ ;; FIXME: What about xterm-mouse-mode etc.?
+ (x-get-selection 'PRIMARY))))
(unless primary
(error "No selection is available"))
(push-mark (point))
#include <config.h>
- #define LISP_INLINE EXTERN_INLINE
-
#include <stdio.h>
#include <limits.h> /* For CHAR_BIT. */
#include <verify.h>
+ #if (defined ENABLE_CHECKING \
+ && defined HAVE_VALGRIND_VALGRIND_H \
+ && !defined USE_VALGRIND)
+ # define USE_VALGRIND 1
+ #endif
+
+ #if USE_VALGRIND
+ #include <valgrind/valgrind.h>
+ #include <valgrind/memcheck.h>
+ static bool valgrind_p;
+ #endif
+
/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
Doable only if GC_MARK_STACK. */
#if ! GC_MARK_STACK
#define ABLOCKS_BASE(abase) (abase)
#else
#define ABLOCKS_BASE(abase) \
- (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void**)abase)[-1])
+ (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **)abase)[-1])
#endif
/* The list of free ablock. */
aligned = (base == abase);
if (!aligned)
- ((void**)abase)[-1] = base;
+ ((void **) abase)[-1] = base;
#ifdef DOUG_LEA_MALLOC
/* Back to a reasonable maximum of mmap'ed areas. */
return val;
}
+ verify (sizeof (size_t) * CHAR_BIT == BITS_PER_SIZE_T);
+ verify ((BITS_PER_SIZE_T & (BITS_PER_SIZE_T - 1)) == 0);
+
+ static ptrdiff_t
+ bool_vector_payload_bytes (ptrdiff_t nr_bits,
+ ptrdiff_t *exact_needed_bytes_out)
+ {
+ ptrdiff_t exact_needed_bytes;
+ ptrdiff_t needed_bytes;
+
+ eassert_and_assume (nr_bits >= 0);
+
+ exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT;
+ needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_SIZE_T) / CHAR_BIT;
+
+ if (needed_bytes == 0)
+ {
+ /* Always allocate at least one machine word of payload so that
+ bool-vector operations in data.c don't need a special case
+ for empty vectors. */
+ needed_bytes = sizeof (size_t);
+ }
+
+ if (exact_needed_bytes_out != NULL)
+ *exact_needed_bytes_out = exact_needed_bytes;
+
+ return needed_bytes;
+ }
DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
{
register Lisp_Object val;
struct Lisp_Bool_Vector *p;
- ptrdiff_t length_in_chars;
- EMACS_INT length_in_elts;
- int bits_per_value;
- int extra_bool_elts = ((bool_header_size - header_size + word_size - 1)
- / word_size);
+ ptrdiff_t exact_payload_bytes;
+ ptrdiff_t total_payload_bytes;
+ ptrdiff_t needed_elements;
CHECK_NATNUM (length);
+ if (PTRDIFF_MAX < XFASTINT (length))
+ memory_full (SIZE_MAX);
- bits_per_value = sizeof (EMACS_INT) * BOOL_VECTOR_BITS_PER_CHAR;
+ total_payload_bytes = bool_vector_payload_bytes
+ (XFASTINT (length), &exact_payload_bytes);
- length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value;
+ eassert_and_assume (exact_payload_bytes <= total_payload_bytes);
+ eassert_and_assume (0 <= exact_payload_bytes);
- val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil);
+ needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size)
+ + total_payload_bytes),
+ word_size) / word_size;
- /* No Lisp_Object to trace in there. */
+ p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
+ XSETVECTOR (val, p);
XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
- p = XBOOL_VECTOR (val);
p->size = XFASTINT (length);
-
- length_in_chars = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
- / BOOL_VECTOR_BITS_PER_CHAR);
- if (length_in_chars)
+ if (exact_payload_bytes)
{
- memset (p->data, ! NILP (init) ? -1 : 0, length_in_chars);
+ memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes);
/* Clear any extraneous bits in the last byte. */
- p->data[length_in_chars - 1]
+ p->data[exact_payload_bytes - 1]
&= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1;
}
+ /* Clear padding at the end. */
+ memset (p->data + exact_payload_bytes,
+ 0,
+ total_payload_bytes - exact_payload_bytes);
+
return val;
}
roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1)
};
- /* ROUNDUP_SIZE must be a power of 2. */
- verify ((roundup_size & (roundup_size - 1)) == 0);
-
/* Verify assumptions described above. */
verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
- /* Round up X to nearest mult-of-ROUNDUP_SIZE. */
-
- #define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1))
+ /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */
+ #define vroundup_ct(x) ROUNDUP ((size_t) (x), roundup_size)
+ /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */
+ #define vroundup(x) (assume ((x) >= 0), vroundup_ct (x))
/* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */
- #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *)))
+ #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *)))
/* Size of the minimal vector allocated from block. */
- #define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object))
+ #define VBLOCK_BYTES_MIN vroundup_ct (header_size + sizeof (Lisp_Object))
/* Size of the largest vector allocated from block. */
#define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
- /* Get and set the next field in block-allocated vectorlike objects on
- the free list. Doing it this way respects C's aliasing rules.
- We could instead make 'contents' a union, but that would mean
- changes everywhere that the code uses 'contents'. */
- static struct Lisp_Vector *
- next_in_free_list (struct Lisp_Vector *v)
- {
- intptr_t i = XLI (v->contents[0]);
- return (struct Lisp_Vector *) i;
- }
- static void
- set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next)
- {
- v->contents[0] = XIL ((intptr_t) next);
- }
-
/* Common shortcut to setup vector on a free list. */
#define SETUP_ON_FREE_LIST(v, nbytes, tmp) \
eassert ((nbytes) % roundup_size == 0); \
(tmp) = VINDEX (nbytes); \
eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \
- set_next_in_free_list (v, vector_free_lists[tmp]); \
+ v->u.next = vector_free_lists[tmp]; \
vector_free_lists[tmp] = (v); \
total_free_vector_slots += (nbytes) / word_size; \
} while (0)
struct large_vector *vector;
#if USE_LSB_TAG
/* We need to maintain ROUNDUP_SIZE alignment for the vector member. */
- unsigned char c[vroundup (sizeof (struct large_vector *))];
+ unsigned char c[vroundup_ct (sizeof (struct large_vector *))];
#endif
} next;
struct Lisp_Vector v;
if (vector_free_lists[index])
{
vector = vector_free_lists[index];
- vector_free_lists[index] = next_in_free_list (vector);
+ vector_free_lists[index] = vector->u.next;
total_free_vector_slots -= nbytes / word_size;
return vector;
}
{
/* This vector is larger than requested. */
vector = vector_free_lists[index];
- vector_free_lists[index] = next_in_free_list (vector);
+ vector_free_lists[index] = vector->u.next;
total_free_vector_slots -= nbytes / word_size;
/* Excess bytes are used for the smaller vector,
if (size & PSEUDOVECTOR_FLAG)
{
if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
- size = (bool_header_size
- + (((struct Lisp_Bool_Vector *) v)->size
- + BOOL_VECTOR_BITS_PER_CHAR - 1)
- / BOOL_VECTOR_BITS_PER_CHAR);
+ {
+ struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
+ ptrdiff_t payload_bytes =
+ bool_vector_payload_bytes (bv->size, NULL);
+
+ eassert_and_assume (payload_bytes >= 0);
+ size = bool_header_size + ROUNDUP (payload_bytes, word_size);
+ }
else
size = (header_size
+ ((size & PSEUDOVECTOR_SIZE_MASK)
free_this_block = 1;
else
{
- int tmp;
+ size_t tmp;
SETUP_ON_FREE_LIST (vector, total_bytes, tmp);
}
}
total_vectors++;
if (vector->header.size & PSEUDOVECTOR_FLAG)
{
- struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector;
-
/* All non-bool pseudovectors are small enough to be allocated
from vector blocks. This code should be redesigned if some
pseudovector type grows beyond VBLOCK_BYTES_MAX. */
eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
-
- total_vector_slots
- += (bool_header_size
- + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
- / BOOL_VECTOR_BITS_PER_CHAR)) / word_size;
+ total_vector_slots += vector_nbytes (vector) / word_size;
}
else
total_vector_slots
else
{
struct large_vector *lv
- = lisp_malloc ((offsetof (struct large_vector, v.contents)
+ = lisp_malloc ((offsetof (struct large_vector, v.u.contents)
+ len * word_size),
MEM_TYPE_VECTORLIKE);
lv->next.vector = large_vectors;
/* Only the first lisplen slots will be traced normally by the GC. */
for (i = 0; i < lisplen; ++i)
- v->contents[i] = Qnil;
+ v->u.contents[i] = Qnil;
XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
return v;
p = allocate_vector (XFASTINT (length));
sizei = XFASTINT (length);
for (i = 0; i < sizei; i++)
- p->contents[i] = init;
+ p->u.contents[i] = init;
XSETVECTOR (vector, p);
return vector;
register struct Lisp_Vector *p = XVECTOR (val);
for (i = 0; i < nargs; i++)
- p->contents[i] = args[i];
+ p->u.contents[i] = args[i];
return val;
}
void
make_byte_code (struct Lisp_Vector *v)
{
- if (v->header.size > 1 && STRINGP (v->contents[1])
- && STRING_MULTIBYTE (v->contents[1]))
+ /* Don't allow the global zero_vector to become a byte code object. */
+ eassert(0 < v->header.size);
+ if (v->header.size > 1 && STRINGP (v->u.contents[1])
+ && STRING_MULTIBYTE (v->u.contents[1]))
/* BYTECODE-STRING must have been produced by Emacs 20.2 or the
earlier because they produced a raw 8-bit string for byte-code
and now such a byte-code string is loaded as multibyte while
raw 8-bit characters converted to multibyte form. Thus, now we
must convert them back to the original unibyte form. */
- v->contents[1] = Fstring_as_unibyte (v->contents[1]);
+ v->u.contents[1] = Fstring_as_unibyte (v->u.contents[1]);
XSETPVECTYPE (v, PVEC_COMPILED);
}
to be setcar'd). */
for (i = 0; i < nargs; i++)
- p->contents[i] = args[i];
+ p->u.contents[i] = args[i];
make_byte_code (p);
XSETCOMPILED (val, p);
return val;
return val;
}
-#if defined HAVE_NS || defined HAVE_NTGUI
Lisp_Object
make_save_ptr (void *a)
{
p->data[0].pointer = a;
return val;
}
-#endif
Lisp_Object
make_save_ptr_int (void *a, ptrdiff_t b)
void *po;
struct mem_node *m;
+ #if USE_VALGRIND
+ if (valgrind_p)
+ VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
+ #endif
+
if (INTEGERP (obj))
return;
{
struct mem_node *m;
+ #if USE_VALGRIND
+ if (valgrind_p)
+ VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
+ #endif
+
/* Quickly rule out some values which can't point to Lisp data.
USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT.
Otherwise, assume that Lisp data is aligned on even addresses. */
size &= PSEUDOVECTOR_SIZE_MASK;
vec = XVECTOR (make_pure_vector (size));
for (i = 0; i < size; i++)
- vec->contents[i] = Fpurecopy (AREF (obj, i));
+ vec->u.contents[i] = Fpurecopy (AREF (obj, i));
if (COMPILEDP (obj))
{
XSETPVECTYPE (vec, PVEC_COMPILED);
The distinction is used e.g. by Lisp_Process which places extra
non-Lisp_Object fields at the end of the structure... */
for (i = 0; i < size; i++) /* ...and then mark its elements. */
- mark_object (ptr->contents[i]);
+ mark_object (ptr->u.contents[i]);
}
/* Like mark_vectorlike but optimized for char-tables (and
VECTOR_MARK (ptr);
for (i = 0; i < size; i++)
{
- Lisp_Object val = ptr->contents[i];
+ Lisp_Object val = ptr->u.contents[i];
if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit))
continue;
VECTOR_MARK (ptr);
for (i = 0; i < size; i++)
if (i != COMPILED_CONSTANTS)
- mark_object (ptr->contents[i]);
+ mark_object (ptr->u.contents[i]);
if (size > COMPILED_CONSTANTS)
{
- obj = ptr->contents[COMPILED_CONSTANTS];
+ obj = ptr->u.contents[COMPILED_CONSTANTS];
goto loop;
}
}
#endif
Vgc_elapsed = make_float (0.0);
gcs_done = 0;
+
+ #if USE_VALGRIND
+ valgrind_p = RUNNING_ON_VALGRIND != 0;
+ #endif
}
void
#endif
INLINE_HEADER_BEGIN
- #ifndef DISPEXTERN_INLINE
- # define DISPEXTERN_INLINE INLINE
- #endif
#include <c-strcase.h>
- DISPEXTERN_INLINE int
+ INLINE int
xstrcasecmp (char const *a, char const *b)
{
return c_strcasecmp (a, b);
}
#ifdef HAVE_X_WINDOWS
+ #include <X11/Xresource.h> /* for XrmDatabase */
typedef struct x_display_info Display_Info;
typedef XImage * XImagePtr;
typedef XImagePtr XImagePtr_or_DC;
} GLYPH;
/* Return a glyph's character code. */
- DISPEXTERN_INLINE int GLYPH_CHAR (GLYPH glyph) { return glyph.ch; }
+ INLINE int GLYPH_CHAR (GLYPH glyph) { return glyph.ch; }
/* Return a glyph's face ID. */
- DISPEXTERN_INLINE int GLYPH_FACE (GLYPH glyph) { return glyph.face_id; }
+ INLINE int GLYPH_FACE (GLYPH glyph) { return glyph.face_id; }
#define SET_GLYPH_CHAR(glyph, char) ((glyph).ch = (char))
#define SET_GLYPH_FACE(glyph, face) ((glyph).face_id = (face))
/* The following are valid only if GLYPH_CODE_P (gc). */
- DISPEXTERN_INLINE int
+ INLINE int
GLYPH_CODE_CHAR (Lisp_Object gc)
{
return (CONSP (gc)
: XINT (gc) & MAX_CHAR);
}
- DISPEXTERN_INLINE int
+ INLINE int
GLYPH_CODE_FACE (Lisp_Object gc)
{
return CONSP (gc) ? XINT (XCDR (gc)) : XINT (gc) >> CHARACTERBITS;
Rows in window matrices on frames having no frame matrices point to
glyphs allocated from the heap via xmalloc;
glyphs[LEFT_MARGIN_AREA] is the start address of the allocated
- glyph structure array. */
+ glyph structure array.
+
+ NOTE: layout of first four members of this structure is important,
+ see clear_glyph_row and copy_row_except_pointers to check why. */
struct glyph_row
{
removed some day, so don't use it in new code. */
struct glyph *glyphs[1 + LAST_AREA];
- /* Number of glyphs actually filled in areas. */
- short used[LAST_AREA];
+ /* Number of glyphs actually filled in areas. This could have size
+ LAST_AREA, but it's 1 + LAST_AREA to simplify offset calculations. */
+ short used[1 + LAST_AREA];
+
+ /* Hash code. This hash code is available as soon as the row
+ is constructed, i.e. after a call to display_line. */
+ unsigned hash;
/* Window-relative x and y-position of the top-left corner of this
row. If y < 0, this means that eabs (y) pixels of the row are
in last row when checking if row is fully visible. */
int extra_line_spacing;
- /* Hash code. This hash code is available as soon as the row
- is constructed, i.e. after a call to display_line. */
- unsigned hash;
-
/* First position in this row. This is the text position, including
overlay position information etc, where the display of this row
started, and can thus be less than the position of the first
((ROW)->phys_height - (ROW)->phys_ascent \
> (ROW)->height - (ROW)->ascent)
- /* True means that fonts have been loaded since the last glyph
- matrix adjustments. The function redisplay_internal adjusts glyph
- matrices when this flag is true. */
-
- extern bool fonts_changed_p;
-
/* A glyph for a space. */
extern struct glyph space_glyph;
#define CURRENT_MODE_LINE_FACE_ID(W) \
(CURRENT_MODE_LINE_FACE_ID_3((W), XWINDOW (selected_window), (W)))
- /* Return the current height of the mode line of window W. If not
- known from current_mode_line_height, look at W's current glyph
- matrix, or return a default based on the height of the font of the
- face `mode-line'. */
+ /* Return the current height of the mode line of window W. If not known
+ from W->mode_line_height, look at W's current glyph matrix, or return
+ a default based on the height of the font of the face `mode-line'. */
- #define CURRENT_MODE_LINE_HEIGHT(W) \
- (current_mode_line_height >= 0 \
- ? current_mode_line_height \
- : (MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix) \
- ? MATRIX_MODE_LINE_HEIGHT ((W)->current_matrix) \
- : estimate_mode_line_height (XFRAME ((W)->frame), \
- CURRENT_MODE_LINE_FACE_ID (W))))
+ #define CURRENT_MODE_LINE_HEIGHT(W) \
+ (W->mode_line_height >= 0 \
+ ? W->mode_line_height \
+ : (W->mode_line_height \
+ = (MATRIX_MODE_LINE_HEIGHT (W->current_matrix) \
+ ? MATRIX_MODE_LINE_HEIGHT (W->current_matrix) \
+ : estimate_mode_line_height \
+ (XFRAME (W->frame), CURRENT_MODE_LINE_FACE_ID (W)))))
- /* Return the current height of the header line of window W. If not
- known from current_header_line_height, look at W's current glyph
- matrix, or return an estimation based on the height of the font of
- the face `header-line'. */
+ /* Return the current height of the header line of window W. If not known
+ from W->header_line_height, look at W's current glyph matrix, or return
+ an estimation based on the height of the font of the face `header-line'. */
#define CURRENT_HEADER_LINE_HEIGHT(W) \
- (current_header_line_height >= 0 \
- ? current_header_line_height \
- : (MATRIX_HEADER_LINE_HEIGHT ((W)->current_matrix) \
- ? MATRIX_HEADER_LINE_HEIGHT ((W)->current_matrix) \
- : estimate_mode_line_height (XFRAME ((W)->frame), \
- HEADER_LINE_FACE_ID)))
+ (W->header_line_height >= 0 \
+ ? W->header_line_height \
+ : (W->header_line_height \
+ = (MATRIX_HEADER_LINE_HEIGHT (W->current_matrix) \
+ ? MATRIX_HEADER_LINE_HEIGHT (W->current_matrix) \
+ : estimate_mode_line_height \
+ (XFRAME (W->frame), HEADER_LINE_FACE_ID))))
/* Return the height of the desired mode line of window W. */
#endif /* not HAVE_WINDOW_SYSTEM */
/* Return true if G contains a valid character code. */
- DISPEXTERN_INLINE bool
+ INLINE bool
GLYPH_CHAR_VALID_P (GLYPH g)
{
return CHAR_VALID_P (GLYPH_CHAR (g));
encodes a char code in the lower CHARACTERBITS bits and a (very small)
face-id in the upper bits, or it may be a cons (CHAR . FACE-ID). */
- DISPEXTERN_INLINE bool
+ INLINE bool
GLYPH_CODE_P (Lisp_Object gc)
{
return (CONSP (gc)
unsigned mouse_face_hidden : 1;
} Mouse_HLInfo;
- DISPEXTERN_INLINE void
+ INLINE void
reset_mouse_highlight (Mouse_HLInfo *hlinfo)
{
/* Flush the display of frame F. For X, this is XFlush. */
void (*flush_display) (struct frame *f);
- /* Flush the display of frame F if non-NULL. This is called
- during redisplay, and should be NULL on systems which flush
- automatically before reading input. */
- void (*flush_display_optional) (struct frame *f);
-
/* Clear the mouse highlight in window W, if there is any. */
void (*clear_window_mouse_face) (struct window *w);
int frame_mode_line_height (struct frame *);
extern Lisp_Object Qtool_bar;
extern bool redisplaying_p;
- extern int help_echo_showing_p;
- extern int current_mode_line_height, current_header_line_height;
+ extern bool help_echo_showing_p;
extern Lisp_Object help_echo_string, help_echo_window;
extern Lisp_Object help_echo_object, previous_help_echo_string;
extern ptrdiff_t help_echo_pos;
- extern struct frame *last_mouse_frame;
extern int last_tool_bar_item;
extern void reseat_at_previous_visible_line_start (struct it *);
extern Lisp_Object lookup_glyphless_char_display (int, struct it *);
extern ptrdiff_t compute_display_string_end (ptrdiff_t,
struct bidi_string_data *);
extern void produce_stretch_glyph (struct it *);
+ extern int merge_glyphless_glyph_face (struct it *);
#ifdef HAVE_WINDOW_SYSTEM
extern int cursor_in_mouse_face_p (struct window *w);
extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *,
int, int, enum draw_glyphs_face);
+extern void display_tty_menu_item (const char *, int, int, int, int, int);
/* Flags passed to try_window. */
#define TRY_WINDOW_CHECK_MARGINS (1 << 0)
extern void start_hourglass (void);
extern void cancel_hourglass (void);
- extern int hourglass_shown_p;
+ extern bool hourglass_shown_p;
/* If non-null, an asynchronous timer that, when it expires, displays
an hourglass cursor on all frames. */
extern struct atimer *hourglass_atimer;
int popup_activated (void);
+/* Defined in dispnew.c */
+
extern Lisp_Object buffer_posn_from_coords (struct window *,
int *, int *,
struct display_pos *,
Lisp_Object *,
int *, int *, int *, int *);
extern void redraw_frame (struct frame *);
- extern void cancel_line (int, struct frame *);
- extern void init_desired_glyphs (struct frame *);
extern bool update_frame (struct frame *, bool, bool);
+extern void update_frame_with_menu (struct frame *);
extern void bitch_at_user (void);
- void adjust_glyphs (struct frame *);
- struct glyph_matrix *save_current_matrix (struct frame *);
+ extern void adjust_frame_glyphs (struct frame *);
void free_glyphs (struct frame *);
void free_window_matrices (struct window *);
void check_glyph_memory (void);
void init_display (void);
void syms_of_display (void);
extern Lisp_Object Qredisplay_dont_pause;
-void spec_glyph_lookup_face (struct window *, GLYPH *);
+extern void spec_glyph_lookup_face (struct window *, GLYPH *);
/* Defined in terminal.c */
RES_TYPE_BOOLEAN_NUMBER
};
+ extern Display_Info *check_x_display_info (Lisp_Object);
extern Lisp_Object x_get_arg (Display_Info *, Lisp_Object,
Lisp_Object, const char *, const char *class,
enum resource_types);
Lisp_Object, Lisp_Object,
const char *, const char *,
enum resource_types);
+ extern char *x_get_string_resource (XrmDatabase, const char *,
+ const char *);
+
+ #ifndef HAVE_NS /* These both used on W32 and X only. */
+ extern bool x_mouse_grabbed (Display_Info *);
+ extern void x_redo_mouse_highlight (Display_Info *);
+ #endif /* HAVE_NS */
#endif /* HAVE_WINDOW_SYSTEM */
#include <config.h>
- #define DISPEXTERN_INLINE EXTERN_INLINE
-
#include "sysstdio.h"
#include <unistd.h>
static void update_frame_line (struct frame *, int);
static int required_matrix_height (struct window *);
static int required_matrix_width (struct window *);
- static void adjust_frame_glyphs (struct frame *);
static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool);
static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
static void fill_up_frame_row_with_spaces (struct glyph_row *, int);
static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
static void adjust_frame_glyphs_for_frame_redisplay (struct frame *);
- /* True upon entry to redisplay means do not assume anything about
- current contents of actual terminal frame; clear and redraw it. */
-
- bool frame_garbaged;
-
/* True means last display completed. False means it was preempted. */
bool display_completed;
Lisp_Object Qdisplay_table, Qredisplay_dont_pause;
- \f
- /* The currently selected frame. In a single-frame version, this
- variable always equals the_only_frame. */
-
- Lisp_Object selected_frame;
-
- /* A frame which is not just a mini-buffer, or 0 if there are no such
- frames. This is usually the most recent such frame that was
- selected. In a single-frame version, this variable always holds
- the address of the_only_frame. */
-
- struct frame *last_nonminibuf_frame;
-
/* True means SIGWINCH happened when not safe. */
static bool delayed_size_change;
static struct frame *frame_matrix_frame;
- /* True means that fonts have been loaded since the last glyph
- matrix adjustments. Redisplay must stop, and glyph matrices must
- be adjusted when this flag becomes true during display. The
- reason fonts can be loaded so late is that fonts of fontsets are
- loaded on demand. Another reason is that a line contains many
- characters displayed by zero width or very narrow glyphs of
- variable-width fonts. */
-
- bool fonts_changed_p;
-
/* Convert vpos and hpos from frame to window and vice versa.
This may only be used for terminal frames. */
|| right != matrix->right_margin_glyphs);
if (!marginal_areas_changed_p
- && !fonts_changed_p
+ && !XFRAME (w->frame)->fonts_changed
&& !header_line_changed_p
&& matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
&& matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
#endif
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* Clear the matrix of the tool-bar window, if any. */
if (WINDOWP (f->tool_bar_window))
clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+ #endif
/* Clear current window matrices. */
eassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
#endif
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
if (WINDOWP (f->tool_bar_window))
clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
+ #endif
/* Do it for window matrices. */
eassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
See dispextern.h for an overall explanation of glyph rows.
***********************************************************************/
- /* Clear glyph row ROW. Do it in a way that makes it robust against
- changes in the glyph_row structure, i.e. addition or removal of
- structure members. */
-
- static struct glyph_row null_row;
+ /* Clear glyph row ROW. NOTE: this code relies on the current
+ layout of `glyphs' and `used' fields of `struct glyph_row'. */
void
clear_glyph_row (struct glyph_row *row)
{
- struct glyph *p[1 + LAST_AREA];
-
- /* Save pointers. */
- p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
- p[TEXT_AREA] = row->glyphs[TEXT_AREA];
- p[RIGHT_MARGIN_AREA] = row->glyphs[RIGHT_MARGIN_AREA];
- p[LAST_AREA] = row->glyphs[LAST_AREA];
-
- /* Clear. */
- *row = null_row;
-
- /* Restore pointers. */
- row->glyphs[LEFT_MARGIN_AREA] = p[LEFT_MARGIN_AREA];
- row->glyphs[TEXT_AREA] = p[TEXT_AREA];
- row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA];
- row->glyphs[LAST_AREA] = p[LAST_AREA];
-
- #if 0 /* At some point, some bit-fields of struct glyph were not set,
- which made glyphs unequal when compared with GLYPH_EQUAL_P.
- Redisplay outputs such glyphs, and flickering effects were
- the result. This also depended on the contents of memory
- returned by xmalloc. If flickering happens again, activate
- the code below. If the flickering is gone with that, chances
- are that the flickering has the same reason as here. */
- memset (p[0], 0, (char *) p[LAST_AREA] - (char *) p[0]);
- #endif
+ enum { off = offsetof (struct glyph_row, used) };
+
+ /* Zero everything except pointers in `glyphs'. */
+ memset (row->used, 0, sizeof *row - off);
}
}
- /* Copy glyph row structure FROM to glyph row structure TO, except
- that glyph pointers, the `used' counts, and the hash values in the
- structures are left unchanged. */
+ /* Copy glyph row structure FROM to glyph row structure TO, except that
+ glyph pointers, the `used' counts, and the hash values in the structures
+ are left unchanged. NOTE: this code relies on the current layout of
+ `glyphs', `used', `hash' and `x' fields of `struct glyph_row'. */
static void
copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
{
- struct glyph *pointers[1 + LAST_AREA];
- short used[LAST_AREA];
- unsigned hashval;
-
- /* Save glyph pointers of TO. */
- memcpy (pointers, to->glyphs, sizeof to->glyphs);
- memcpy (used, to->used, sizeof to->used);
- hashval = to->hash;
-
- /* Do a structure assignment. */
- *to = *from;
-
- /* Restore original pointers of TO. */
- memcpy (to->glyphs, pointers, sizeof to->glyphs);
- memcpy (to->used, used, sizeof to->used);
- to->hash = hashval;
+ enum { off = offsetof (struct glyph_row, x) };
+
+ memcpy (&to->x, &from->x, sizeof *to - off);
}
}
}
-
- /* Re-allocate/ re-compute glyph matrices on frame F. If F is null,
- do it for all frames; otherwise do it just for the given frame.
- This function must be called when a new frame is created, its size
- changes, or its window configuration changes. */
+ /* Allocate/reallocate glyph matrices of a single frame F.
+ This function must be called when a new frame is created,
+ its size changes, or its window configuration changes. */
void
- adjust_glyphs (struct frame *f)
+ adjust_frame_glyphs (struct frame *f)
{
/* Block input so that expose events and other events that access
glyph matrices are not processed while we are changing them. */
block_input ();
- if (f)
- adjust_frame_glyphs (f);
- else
- {
- Lisp_Object tail, lisp_frame;
-
- FOR_EACH_FRAME (tail, lisp_frame)
- adjust_frame_glyphs (XFRAME (lisp_frame));
- }
-
- unblock_input ();
- }
-
- /* Allocate/reallocate glyph matrices of a single frame F. */
-
- static void
- adjust_frame_glyphs (struct frame *f)
- {
if (FRAME_WINDOW_P (f))
adjust_frame_glyphs_for_window_redisplay (f);
else
adjust_decode_mode_spec_buffer (f);
f->glyphs_initialized_p = 1;
+
+ unblock_input ();
}
/* Return true if any window in the tree has nonzero window margins. See
/* Save away the contents of frame F's current frame matrix. Value is
a glyph matrix holding the contents of F's current frame matrix. */
- struct glyph_matrix *
+ static struct glyph_matrix *
save_current_matrix (struct frame *f)
{
int 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];
+ to->enabled_p = from->enabled_p;
+ 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;
struct glyph_row *from = saved->rows + i;
struct glyph_row *to = f->current_matrix->rows + i;
ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
to->used[TEXT_AREA] = from->used[TEXT_AREA];
xfree (from->glyphs[TEXT_AREA]);
+ nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
+ if (nbytes)
+ {
+ memcpy (to->glyphs[LEFT_MARGIN_AREA],
+ from->glyphs[LEFT_MARGIN_AREA], nbytes);
+ to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
+ xfree (from->glyphs[LEFT_MARGIN_AREA]);
+ }
+ else
+ to->used[LEFT_MARGIN_AREA] = 0;
+ nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
+ if (nbytes)
+ {
+ memcpy (to->glyphs[RIGHT_MARGIN_AREA],
+ from->glyphs[RIGHT_MARGIN_AREA], nbytes);
+ to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
+ xfree (from->glyphs[RIGHT_MARGIN_AREA]);
+ }
+ else
+ to->used[RIGHT_MARGIN_AREA] = 0;
}
xfree (saved->rows);
/* Allocate/reallocate window matrices. */
allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)));
- #ifdef HAVE_X_WINDOWS
+ #if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
/* Allocate/ reallocate matrices of the dummy window used to display
the menu bar under X when no X toolkit support is available. */
- #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
{
/* Allocate a dummy window if not already done. */
struct window *w;
w->total_cols = FRAME_TOTAL_COLS (f);
allocate_matrices_for_window_redisplay (w);
}
- #endif /* not USE_X_TOOLKIT && not USE_GTK */
- #endif /* HAVE_X_WINDOWS */
+ #endif
- #ifndef USE_GTK
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
{
/* Allocate/ reallocate matrices of the tool bar window. If we
don't have a tool bar window yet, make one. */
}
#endif
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* Free the tool bar window and its glyph matrices. */
if (!NILP (f->tool_bar_window))
{
w->desired_matrix = w->current_matrix = NULL;
fset_tool_bar_window (f, Qnil);
}
+ #endif
/* Release frame glyph matrices. Reset fields to zero in
case we are called a second time. */
update_window (XWINDOW (f->menu_bar_window), 1);
#endif
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* Update the tool-bar window, if present. */
if (WINDOWP (f->tool_bar_window))
{
fset_desired_tool_bar_string (f, tem);
}
}
-
+ #endif
/* Update windows. */
paused_p = update_window_tree (root_window, force_p);
update_end (f);
-
- /* This flush is a performance bottleneck under X,
- and it doesn't seem to be necessary anyway (in general).
- It is necessary when resizing the window with the mouse, or
- at least the fringes are not redrawn in a timely manner. ++kfs */
- if (f->force_flush_display_p)
- {
- FRAME_RIF (f)->flush_display (f);
- f->force_flush_display_p = 0;
- }
}
else
{
return paused_p;
}
+/* 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, 0);
+}
\f
/************************************************************************
}
}
- lint_assume (0 <= FRAME_LINES (f));
+ assume (0 <= FRAME_LINES (f));
pause_p = 0 < i && i < FRAME_LINES (f) - 1;
/* Now just clean up termcap drivers and set cursor, etc. */
if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
FrameCols (FRAME_TTY (f)) = newwidth;
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
if (WINDOWP (f->tool_bar_window))
XWINDOW (f->tool_bar_window)->total_cols = newwidth;
+ #endif
}
FRAME_LINES (f) = newheight;
w->cursor.vpos = w->cursor.y = 0;
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
calculate_costs (f);
SET_FRAME_GARBAGED (f);
f->resized_p = 1;
#include <config.h>
- #define BLOCKINPUT_INLINE EXTERN_INLINE
- #define KEYBOARD_INLINE EXTERN_INLINE
-
#include "sysstdio.h"
#include "lisp.h"
at inopportune times. */
/* Symbols to head events. */
-static Lisp_Object Qmouse_movement;
+Lisp_Object Qmouse_movement;
static Lisp_Object Qscroll_bar_movement;
Lisp_Object Qswitch_frame;
static Lisp_Object Qfocus_in, Qfocus_out;
static Lisp_Object Qvertical_scroll_bar;
Lisp_Object Qmenu_bar;
+static Lisp_Object Qecho_keystrokes;
+
static void recursive_edit_unwind (Lisp_Object buffer);
static Lisp_Object command_loop (void);
static Lisp_Object Qcommand_execute;
sans error-handling encapsulation. */
static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
- bool, bool, bool);
+ bool, bool, bool, bool);
void safe_run_hooks (Lisp_Object);
static void adjust_point_for_property (ptrdiff_t, bool);
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
- Qnil, 0, 1, 1);
+ Qnil, 0, 1, 1, 0);
/* A filter may have run while we were reading the input. */
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
}
}
+Lisp_Object
+read_menu_command (void)
+{
+ Lisp_Object cmd;
+ Lisp_Object keybuf[30];
+ ptrdiff_t count = SPECPDL_INDEX ();
+ int i;
+
+ /* We don't want to echo the keystrokes while navigating the
+ menus. */
+ specbind (Qecho_keystrokes, make_number (0));
+
+ i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
+ Qnil, 0, 1, 1, 1);
+
+ unbind_to (count, Qnil);
+
+ if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+ Fkill_emacs (Qnil);
+ if (i == 0 || i == -1)
+ return Qt;
+
+ return read_key_sequence_cmd;
+}
+
/* Adjust point to a boundary of a region that has such a property
that should be treated intangible. For the moment, we check
`composition', `display' and `invisible' properties.
/* Read a character from the keyboard; call the redisplay if needed. */
/* commandflag 0 means do not autosave, but do redisplay.
-1 means do not redisplay, but do autosave.
+ -2 means do neither.
1 means do both. */
/* The arguments MAP is for menu prompting. MAP is a keymap.
if (/* There currently is something in the echo area. */
!NILP (echo_area_buffer[0])
- && (/* And it's either not from echoing. */
- !EQ (echo_area_buffer[0], echo_message_buffer)
- /* Or it's an echo from a different kboard. */
- || echo_kboard != current_kboard
+ && (/* It's an echo from a different kboard. */
+ echo_kboard != current_kboard
/* Or we explicitly allow overwriting whatever there is. */
|| ok_to_echo_at_next_pause == NULL))
cancel_echoing ();
/* Maybe auto save due to number of keystrokes. */
- if (commandflag != 0
+ if (commandflag != 0 && commandflag != -2
&& auto_save_interval > 0
&& num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
&& !detect_input_pending_run_timers (0))
9 at 200k, 11 at 300k, and 12 at 500k. It is 15 at 1 meg. */
/* Auto save if enough time goes by without input. */
- if (commandflag != 0
+ if (commandflag != 0 && commandflag != -2
&& num_nonmacro_input_events > last_auto_save
&& INTEGERP (Vauto_save_timeout)
&& XINT (Vauto_save_timeout) > 0)
}
}
else
- wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
+ {
+ bool do_display = true;
+
+ if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
+ {
+ struct tty_display_info *tty = CURTTY ();
+
+ /* When this TTY is displaying a menu, we must prevent
+ any redisplay, because we modify the frame's glyph
+ matrix behind the back of the display engine. */
+ if (tty->showing_menu)
+ do_display = false;
+ }
+
+ wait_reading_process_output (0, 0, -1, do_display, Qnil, NULL, 0);
+ }
if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
gobble_input ();
if (! (VECTORP (timer) && ASIZE (timer) == 9))
return 0;
- vector = XVECTOR (timer)->contents;
+ vector = XVECTOR (timer)->u.contents;
if (! NILP (vector[0]))
return 0;
discard any previously made item. */
for (i = 0; i < ntool_bar_items; i += TOOL_BAR_ITEM_NSLOTS)
{
- Lisp_Object *v = XVECTOR (tool_bar_items_vector)->contents + i;
+ Lisp_Object *v = XVECTOR (tool_bar_items_vector)->u.contents + i;
if (EQ (key, v[TOOL_BAR_ITEM_KEY]))
{
/* Append entries from tool_bar_item_properties to the end of
tool_bar_items_vector. */
vcopy (tool_bar_items_vector, ntool_bar_items,
- XVECTOR (tool_bar_item_properties)->contents, TOOL_BAR_ITEM_NSLOTS);
+ XVECTOR (tool_bar_item_properties)->u.contents, TOOL_BAR_ITEM_NSLOTS);
ntool_bar_items += TOOL_BAR_ITEM_NSLOTS;
}
Echo starting immediately unless `prompt' is 0.
+ If PREVENT_REDISPLAY is non-zero, avoid redisplay by calling
+ read_char with a suitable COMMANDFLAG argument.
+
Where a key sequence ends depends on the currently active keymaps.
These include any minor mode keymaps active in the current buffer,
the current buffer's local map, and the global map.
static int
read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
bool dont_downcase_last, bool can_return_switch_frame,
- bool fix_current_buffer)
+ bool fix_current_buffer, bool prevent_redisplay)
{
ptrdiff_t count = SPECPDL_INDEX ();
{
if (!NILP (prompt))
{
- /* Install the string STR as the beginning of the string of
- echoing, so that it serves as a prompt for the next
+ /* Install the string PROMPT as the beginning of the string
+ of echoing, so that it serves as a prompt for the next
character. */
kset_echo_string (current_kboard, prompt);
current_kboard->echo_after_prompt = SCHARS (prompt);
{
KBOARD *interrupted_kboard = current_kboard;
struct frame *interrupted_frame = SELECTED_FRAME ();
- key = read_char (NILP (prompt),
+ /* Calling read_char with COMMANDFLAG = -2 avoids
+ redisplay in read_char and its subroutines. */
+ key = read_char (prevent_redisplay ? -2 : NILP (prompt),
current_binding, last_nonmenu_event,
&used_mouse_menu, NULL);
if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
- ! NILP (can_return_switch_frame), 0);
+ ! NILP (can_return_switch_frame), 0, 0);
#if 0 /* The following is fine for code reading a key sequence and
then proceeding with a lengthy computation, but it's not good
get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
if (old_timers_run != timers_run && do_display)
- {
- redisplay_preserve_echo_area (8);
- /* The following fixes a bug when using lazy-lock with
- lazy-lock-defer-on-the-fly set to t, i.e. when fontifying
- from an idle timer function. The symptom of the bug is that
- the cursor sometimes doesn't become visible until the next X
- event is processed. --gerd. */
- {
- Lisp_Object tail, frame;
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_RIF (XFRAME (frame)))
- FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
- }
- }
+ redisplay_preserve_echo_area (8);
return input_pending;
}
doc: /* Return vector of last 300 events, not counting those from keyboard macros. */)
(void)
{
- Lisp_Object *keys = XVECTOR (recent_keys)->contents;
+ Lisp_Object *keys = XVECTOR (recent_keys)->u.contents;
Lisp_Object val;
if (total_keys < NUM_RECENT_KEYS)
(void)
{
return make_event_array (this_command_key_count,
- XVECTOR (this_command_keys)->contents);
+ XVECTOR (this_command_keys)->u.contents);
}
DEFUN ("this-command-keys-vector", Fthis_command_keys_vector, Sthis_command_keys_vector, 0, 0, 0,
(void)
{
return Fvector (this_command_key_count,
- XVECTOR (this_command_keys)->contents);
+ XVECTOR (this_command_keys)->u.contents);
}
DEFUN ("this-single-command-keys", Fthis_single_command_keys,
{
return Fvector (this_command_key_count
- this_single_command_key_start,
- (XVECTOR (this_command_keys)->contents
+ (XVECTOR (this_command_keys)->u.contents
+ this_single_command_key_start));
}
The value is always a vector. */)
(void)
{
- return Fvector (raw_keybuf_count,
- (XVECTOR (raw_keybuf)->contents));
+ return Fvector (raw_keybuf_count, XVECTOR (raw_keybuf)->u.contents);
}
DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
DEFSYM (Qhelp_form_show, "help-form-show");
+ DEFSYM (Qecho_keystrokes, "echo-keystrokes");
+
Fset (Qinput_method_exit_on_first_char, Qnil);
Fset (Qinput_method_use_echo_area, Qnil);
#include "termhooks.h"
INLINE_HEADER_BEGIN
- #ifndef KEYBOARD_INLINE
- # define KEYBOARD_INLINE INLINE
- #endif
/* Most code should use this macro to access Lisp fields in struct kboard. */
ptrdiff_t echo_after_prompt;
};
- KEYBOARD_INLINE void
+ INLINE void
kset_default_minibuffer_frame (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vdefault_minibuffer_frame) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_defining_kbd_macro (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (defining_kbd_macro) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_input_decode_map (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vinput_decode_map) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_last_command (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vlast_command) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_last_kbd_macro (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vlast_kbd_macro) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_prefix_arg (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vprefix_arg) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_system_key_alist (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vsystem_key_alist) = val;
}
- KEYBOARD_INLINE void
+ INLINE void
kset_window_system (struct kboard *kb, Lisp_Object val)
{
kb->INTERNAL_FIELD (Vwindow_system) = val;
extern Lisp_Object Qevent_kind;
/* The values of Qevent_kind properties. */
-extern Lisp_Object Qmouse_click;
+extern Lisp_Object Qmouse_click, Qmouse_movement;
extern Lisp_Object Qhelp_echo;
#include "menu.h"
-/* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
+/* Return non-zero if menus can handle radio and toggle buttons. */
+static bool
+have_boxes (void)
+{
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
-#define HAVE_BOXES 1
+ if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame)))
+ return 1;
#endif
+ return 0;
+}
Lisp_Object menu_items;
push_menu_pane (pane_name, prefix);
-#ifndef HAVE_BOXES
- /* Remember index for first item in this pane so we can go back and
- add a prefix when (if) we see the first button. After that, notbuttons
- is set to 0, to mark that we have seen a button and all non button
- items need a prefix. */
- skp.notbuttons = menu_items_used;
-#endif
+ if (!have_boxes ())
+ {
+ /* Remember index for first item in this pane so we can go back
+ and add a prefix when (if) we see the first button. After
+ that, notbuttons is set to 0, to mark that we have seen a
+ button and all non button items need a prefix. */
+ skp.notbuttons = menu_items_used;
+ }
GCPRO1 (skp.pending_maps);
map_keymap_canonical (keymap, single_menu_item, Qnil, &skp);
return;
}
-#if defined (HAVE_X_WINDOWS) || defined (MSDOS)
-#ifndef HAVE_BOXES
/* Simulate radio buttons and toggle boxes by putting a prefix in
front of them. */
- {
- Lisp_Object prefix = Qnil;
- Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
- if (!NILP (type))
- {
- Lisp_Object selected
- = AREF (item_properties, ITEM_PROPERTY_SELECTED);
+ if (!have_boxes ())
+ {
+ Lisp_Object prefix = Qnil;
+ Lisp_Object type = AREF (item_properties, ITEM_PROPERTY_TYPE);
+ if (!NILP (type))
+ {
+ Lisp_Object selected
+ = AREF (item_properties, ITEM_PROPERTY_SELECTED);
- if (skp->notbuttons)
- /* The first button. Line up previous items in this menu. */
- {
- int idx = skp->notbuttons; /* Index for first item this menu. */
- int submenu = 0;
- Lisp_Object tem;
- while (idx < menu_items_used)
- {
- tem
- = AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
- if (NILP (tem))
- {
- idx++;
- submenu++; /* Skip sub menu. */
- }
- else if (EQ (tem, Qlambda))
- {
- idx++;
- submenu--; /* End sub menu. */
- }
- else if (EQ (tem, Qt))
- idx += 3; /* Skip new pane marker. */
- else if (EQ (tem, Qquote))
- idx++; /* Skip a left, right divider. */
- else
- {
- if (!submenu && SREF (tem, 0) != '\0'
- && SREF (tem, 0) != '-')
- ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
- concat2 (build_string (" "), tem));
- idx += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- skp->notbuttons = 0;
- }
+ if (skp->notbuttons)
+ /* The first button. Line up previous items in this menu. */
+ {
+ int idx = skp->notbuttons; /* Index for first item this menu. */
+ int submenu = 0;
+ Lisp_Object tem;
+ while (idx < menu_items_used)
+ {
+ tem
+ = AREF (menu_items, idx + MENU_ITEMS_ITEM_NAME);
+ if (NILP (tem))
+ {
+ idx++;
+ submenu++; /* Skip sub menu. */
+ }
+ else if (EQ (tem, Qlambda))
+ {
+ idx++;
+ submenu--; /* End sub menu. */
+ }
+ else if (EQ (tem, Qt))
+ idx += 3; /* Skip new pane marker. */
+ else if (EQ (tem, Qquote))
+ idx++; /* Skip a left, right divider. */
+ else
+ {
+ if (!submenu && SREF (tem, 0) != '\0'
+ && SREF (tem, 0) != '-')
+ ASET (menu_items, idx + MENU_ITEMS_ITEM_NAME,
+ concat2 (build_string (" "), tem));
+ idx += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ skp->notbuttons = 0;
+ }
- /* Calculate prefix, if any, for this item. */
- if (EQ (type, QCtoggle))
- prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
- else if (EQ (type, QCradio))
- prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
- }
- /* Not a button. If we have earlier buttons, then we need a prefix. */
- else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
- && SREF (item_string, 0) != '-')
- prefix = build_string (" ");
+ /* Calculate prefix, if any, for this item. */
+ if (EQ (type, QCtoggle))
+ prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
+ else if (EQ (type, QCradio))
+ prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
+ }
+ /* Not a button. If we have earlier buttons, then we need a prefix. */
+ else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
+ && SREF (item_string, 0) != '-')
+ prefix = build_string (" ");
- if (!NILP (prefix))
- item_string = concat2 (prefix, item_string);
+ if (!NILP (prefix))
+ item_string = concat2 (prefix, item_string);
}
-#endif /* not HAVE_BOXES */
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
- if (!NILP (map))
+ if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame))
+ && !NILP (map))
/* Indicate visually that this is a submenu. */
item_string = concat2 (item_string, build_string (" >"));
-#endif
-
-#endif /* HAVE_X_WINDOWS || MSDOS */
push_menu_item (item_string, enabled, key,
AREF (item_properties, ITEM_PROPERTY_DEF),
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
/* Display a submenu using the toolkit. */
- if (! (NILP (map) || NILP (enabled)))
+ if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame))
+ && ! (NILP (map) || NILP (enabled)))
{
push_submenu_start ();
single_keymap_panes (map, Qnil, key, skp->maxdepth - 1);
finish_menu_items ();
}
+/* Encode a menu string as appropriate for menu-updating-frame's type. */
+static Lisp_Object
+encode_menu_string (Lisp_Object str)
+{
+ /* TTY menu strings are encoded by write_glyphs, when they are
+ delivered to the glass, so no need to encode them here. */
+ if (FRAME_TERMCAP_P (XFRAME (Vmenu_updating_frame)))
+ return str;
+ return ENCODE_MENU_STRING (str);
+}
/* Push the items in a single pane defined by the alist PANE. */
static void
{
item = XCAR (tail);
if (STRINGP (item))
- push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt,
+ push_menu_item (encode_menu_string (item), Qnil, Qnil, Qt,
Qnil, Qnil, Qnil, Qnil);
else if (CONSP (item))
{
item1 = XCAR (item);
CHECK_STRING (item1);
- push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item),
+ push_menu_item (encode_menu_string (item1), Qt, XCDR (item),
Qt, Qnil, Qnil, Qnil, Qnil);
}
else
elt = XCAR (tail);
pane_name = Fcar (elt);
CHECK_STRING (pane_name);
- push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil);
+ push_menu_pane (encode_menu_string (pane_name), Qnil);
pane_data = Fcdr (elt);
CHECK_CONS (pane_data);
list_of_items (pane_data);
int submenu_depth = 0;
widget_value **submenu_stack;
bool panes_seen = 0;
+ struct frame *f = XFRAME (Vmenu_updating_frame);
submenu_stack = alloca (menu_items_used * sizeof *submenu_stack);
wv = xmalloc_widget_value ();
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
-#ifdef HAVE_NTGUI
- if (STRINGP (pane_name))
+ /* TTY menus display menu items via tty_write_glyphs, which
+ will encode the strings as appropriate. */
+ if (!FRAME_TERMCAP_P (f))
{
- if (unicode_append_menu)
- /* Encode as UTF-8 for now. */
- pane_name = ENCODE_UTF_8 (pane_name);
- else if (STRING_MULTIBYTE (pane_name))
- pane_name = ENCODE_SYSTEM (pane_name);
+#ifdef HAVE_NTGUI
+ if (STRINGP (pane_name))
+ {
+ if (unicode_append_menu)
+ /* Encode as UTF-8 for now. */
+ pane_name = ENCODE_UTF_8 (pane_name);
+ else if (STRING_MULTIBYTE (pane_name))
+ pane_name = ENCODE_SYSTEM (pane_name);
- ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
- }
+ ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
+ }
#elif defined (USE_LUCID) && defined (HAVE_XFT)
- if (STRINGP (pane_name))
- {
- pane_name = ENCODE_UTF_8 (pane_name);
- ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
- }
+ if (STRINGP (pane_name))
+ {
+ pane_name = ENCODE_UTF_8 (pane_name);
+ ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
+ }
#elif !defined (HAVE_MULTILINGUAL_MENU)
- if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
- {
- pane_name = ENCODE_MENU_STRING (pane_name);
- ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
- }
+ if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
+ {
+ pane_name = ENCODE_MENU_STRING (pane_name);
+ ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
+ }
#endif
+ }
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
-#ifdef HAVE_NTGUI
- if (STRINGP (item_name))
+ /* TTY menu items and their descriptions will be encoded by
+ tty_write_glyphs. */
+ if (!FRAME_TERMCAP_P (f))
{
- if (unicode_append_menu)
- item_name = ENCODE_UTF_8 (item_name);
- else if (STRING_MULTIBYTE (item_name))
- item_name = ENCODE_SYSTEM (item_name);
+#ifdef HAVE_NTGUI
+ if (STRINGP (item_name))
+ {
+ if (unicode_append_menu)
+ item_name = ENCODE_UTF_8 (item_name);
+ else if (STRING_MULTIBYTE (item_name))
+ item_name = ENCODE_SYSTEM (item_name);
- ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
- }
+ ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
+ }
- if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- {
- descrip = ENCODE_SYSTEM (descrip);
- ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
- }
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+ {
+ descrip = ENCODE_SYSTEM (descrip);
+ ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
+ }
#elif USE_LUCID
- if (STRINGP (item_name))
- {
- item_name = ENCODE_UTF_8 (item_name);
- ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
- }
+ if (STRINGP (item_name))
+ {
+ item_name = ENCODE_UTF_8 (item_name);
+ ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
+ }
- if (STRINGP (descrip))
- {
- descrip = ENCODE_UTF_8 (descrip);
- ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
- }
+ if (STRINGP (descrip))
+ {
+ descrip = ENCODE_UTF_8 (descrip);
+ ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
+ }
#elif !defined (HAVE_MULTILINGUAL_MENU)
- if (STRING_MULTIBYTE (item_name))
- {
- item_name = ENCODE_MENU_STRING (item_name);
- ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
- }
+ if (STRING_MULTIBYTE (item_name))
+ {
+ item_name = ENCODE_MENU_STRING (item_name);
+ ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
+ }
- if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- {
- descrip = ENCODE_MENU_STRING (descrip);
- ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
- }
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+ {
+ descrip = ENCODE_MENU_STRING (descrip);
+ ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
+ }
#endif
+ }
wv = xmalloc_widget_value ();
if (prev_wv)
{
bool get_current_pos_p = 0;
- check_window_system (SELECTED_FRAME ());
-
/* Decode the first argument: find the window and the coordinates. */
if (EQ (position, Qt)
|| (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
xpos += XINT (x);
ypos += XINT (y);
- /* FIXME: Find a more general check! */
- if (!(FRAME_X_P (f) || FRAME_MSDOS_P (f)
- || FRAME_W32_P (f) || FRAME_NS_P (f)))
- error ("Can not put GUI menu on this terminal");
-
XSETFRAME (Vmenu_updating_frame, f);
}
#endif /* HAVE_MENUS */
#ifdef HAVE_MENUS
#ifdef HAVE_WINDOW_SYSTEM
/* Hide a previous tip, if any. */
- Fx_hide_tip ();
+ if (!FRAME_TERMCAP_P (f))
+ Fx_hide_tip ();
#endif
#ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */
can occur if you press ESC or click outside a menu without selecting
a menu item.
*/
- if (current_popup_menu)
+ if (current_popup_menu && FRAME_W32_P (f))
{
discard_menu_items ();
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
UNGCPRO;
return Qnil;
}
#endif
/* Display them in a menu. */
- block_input ();
/* FIXME: Use a terminal hook! */
#if defined HAVE_NTGUI
- selection = w32_menu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name);
-#elif defined HAVE_NS
- selection = ns_menu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name);
-#else /* MSDOS and X11 */
+ if (FRAME_W32_P (f))
+ selection = w32_menu_show (f, xpos, ypos, for_click,
+ keymaps, title, &error_name);
+ else
+#endif
+#if defined HAVE_NS
+ if (FRAME_NS_P (f))
+ selection = ns_menu_show (f, xpos, ypos, for_click,
+ keymaps, title, &error_name);
+ else
+#endif
+#if (defined (HAVE_X_WINDOWS) || defined (MSDOS))
/* Assume last_event_timestamp is the timestamp of the button event.
Is this assumption ever violated? We can't use the timestamp
stored within POSITION because there the top bits from the actual
timestamp may be truncated away (Bug#4930). */
- selection = xmenu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name,
- last_event_timestamp);
+ if (FRAME_X_P (f) || FRAME_MSDOS_P (f))
+ selection = xmenu_show (f, xpos, ypos, for_click,
+ keymaps, title, &error_name,
+ last_event_timestamp);
+ else
#endif
-
- unblock_input ();
+ if (FRAME_TERMCAP_P (f))
+ selection = tty_menu_show (f, xpos, ypos, for_click,
+ keymaps, title, &error_name);
#ifdef HAVE_NS
unbind_to (specpdl_count, Qnil);
#endif
#ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */
- FRAME_DISPLAY_INFO (f)->grabbed = 0;
+ if (FRAME_W32_P (f))
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
++ FRAME_DISPLAY_INFO (f)->grabbed = 0;
#endif
#endif /* HAVE_MENUS */
static unsigned short outside_cursor;
- /* Similar to the_only_frame. */
+ /* The only display since MS-DOS does not support multiple ones. */
struct tty_display_info the_only_display_info;
/* Support for DOS/V (allows Japanese characters to be displayed on
static void
IT_update_begin (struct frame *f)
{
- struct tty_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
+ struct tty_display_info *display_info = FRAME_DISPLAY_INFO (f);
Mouse_HLInfo *hlinfo = &display_info->mouse_highlight;
struct frame *mouse_face_frame = hlinfo->mouse_face_mouse_frame;
static void
IT_update_end (struct frame *f)
{
- struct tty_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ struct tty_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
if (dpyinfo->termscript)
fprintf (dpyinfo->termscript, "\n<UPDATE_END\n");
emacs_abort ();
}
-/* set-window-configuration on window.c needs this. */
-void
-x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
-{
- set_menu_bar_lines (f, value, oldval);
-}
-
/* This was copied from xfaces.c */
extern Lisp_Object Qbackground_color;
and then the scan code. */)
(void)
{
- Lisp_Object val, *keys = XVECTOR (recent_doskeys)->contents;
+ Lisp_Object val, *keys = XVECTOR (recent_doskeys)->u.contents;
if (total_doskeys < NUM_RECENT_DOSKEYS)
return Fvector (total_doskeys, keys);
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
widget_value *wv, *first_wv = 0;
+ block_input ();
+
p.x = x; p.y = y;
/* now parse stage 2 as in ns_update_menubar */
popup_activated_flag = 0;
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
+ unblock_input ();
return tem;
}
{
/* 1) come up w/identifier */
NSString *identifier
- = [NSString stringWithFormat: @"%u", [img hash]];
+ = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]];
[activeIdentifiers addObject: identifier];
/* 2) create / reuse item */
#include "xterm.h"
#endif
+#include "menu.h"
+
/* The name of the default console device. */
#ifdef WINDOWSNT
#define DEV_TTY "CONOUT$"
if (tty->cursor_hidden == 0)
{
tty->cursor_hidden = 1;
+#ifdef WINDOWSNT
+ w32con_hide_cursor ();
+#else
OUTPUT_IF (tty, tty->TS_cursor_invisible);
+#endif
}
}
if (tty->cursor_hidden)
{
tty->cursor_hidden = 0;
+#ifdef WINDOWSNT
+ w32con_show_cursor ();
+#else
OUTPUT_IF (tty, tty->TS_cursor_normal);
if (visible_cursor)
OUTPUT_IF (tty, tty->TS_cursor_visible);
+#endif
}
}
static void
produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
{
- int face_id;
- int len;
+ int len, face_id = merge_glyphless_glyph_face (it);
char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)];
char const *str = " ";
- /* Get a face ID for the glyph by utilizing a cache (the same way as
- done for `escape-glyph' in get_next_display_element). */
- if (it->f == last_glyphless_glyph_frame
- && it->face_id == last_glyphless_glyph_face_id)
- {
- face_id = last_glyphless_glyph_merged_face_id;
- }
- else
- {
- /* Merge the `glyphless-char' face into the current face. */
- face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
- last_glyphless_glyph_frame = it->f;
- last_glyphless_glyph_face_id = it->face_id;
- last_glyphless_glyph_merged_face_id = face_id;
- }
-
if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
{
/* As there's no way to produce a thin space, we produce a space
#endif /* HAVE_GPM */
\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
+
+/* 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 int menu_x, menu_y;
+
+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 enable. */
+ 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, lmy, 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);
+#if 0
+ IT_update_begin (sf); /* FIXME: do we need an update_begin_hook? */
+#endif
+ 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. */
+
+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, 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;
+ /* FIXME: Following 2 or 3 lines are temporary! */
+ menu_x = *x;
+ menu_y = *y;
+ sf->mouse_moved = 1;
+ return 0;
+ }
+
+ while (1)
+ {
+#if 1
+ 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))
+ *x += 1;
+ else if (EQ (cmd, Qtty_menu_prev_menu))
+ *x -= 1;
+ 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;
+#else
+ int volatile dx = 0;
+ int volatile dy = 0;
+ int volatile st = 0;
+
+ *x += dx;
+ *y += dy;
+ if (dx != 0 || dy != 0)
+ sf->mouse_moved = 1;
+ Sleep (300);
+#endif
+ menu_x = *x;
+ menu_y = *y;
+ return st;
+ }
+ return 0;
+}
+
+/* FIXME */
+static bool mouse_visible;
+static void
+mouse_off (void)
+{
+ mouse_visible = false;
+}
+
+static void
+mouse_on (void)
+{
+ mouse_visible = true;
+}
+
+static bool
+mouse_pressed (int b, int *x, int *y)
+{
+ return false;
+}
+
+static bool
+mouse_button_depressed (int b, int *x, int *y)
+{
+ return false;
+}
+
+static bool
+mouse_released (int b, int *x, int *y)
+{
+ return true;
+}
+
+/* Display menu, wait for user's response, and return that response. */
+int
+tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
+ int x0, int y0, char **txt,
+ void (*help_callback)(char const *, int, int))
+{
+ 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;
+
+#if 0
+ /* We will process all the mouse events directly. */
+ mouse_preempted++;
+#endif
+
+ 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;
+ }
+
+#if 0
+ /* We need to save the current echo area message, so that we could
+ restore it below, before we exit. See the commentary below,
+ before the call to message_with_string. */
+ saved_echo_area_message = Fcurrent_message ();
+#endif
+ /* 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;
+ mouse_off (); /* FIXME */
+ state[0].screen_behind = save_and_enable_current_matrix (sf);
+
+ /* Turn off the cursor. Otherwise it shows through the menu
+ panes, which is ugly. */
+ tty_hide_cursor (tty);
+
+ /* 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);
+ 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 mouse_button_count = 3; /* FIXME */
+ int input_status;
+ int min_y = state[0].y, max_y = min_y + state[0].menu->count - 1;
+
+ if (!mouse_visible) mouse_on ();
+ input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
+ if (input_status)
+ {
+ 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;
+ }
+ leave = 1;
+ }
+ 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--;
+ mouse_off (); /* FIXME */
+ 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];
+ mouse_off (); /* FIXME */
+ 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);
+ }
+
+ /* 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);
+ prev_menu_help_message = menu_help_message;
+ }
+#if 0
+ /* We are busy-waiting for the mouse to move, so let's be nice
+ to other Windows applications by releasing our time slice. */
+ Sleep (20); /* FIXME */
+
+ for (b = 0; b < mouse_button_count && !leave; b++)
+ {
+ /* Only leave if user both pressed and released the mouse, and in
+ that order. This avoids popping down the menu pane unless
+ the user is really done with it. */
+ if (mouse_pressed (b, &x, &y))
+ {
+ while (mouse_button_depressed (b, &x, &y))
+ Sleep (20); /* FIXME */
+ leave = 1;
+ }
+ (void) mouse_released (b, &x, &y);
+ }
+#endif
+ }
+
+ mouse_off (); /* FIXME */
+ sf->mouse_moved = 0;
+ /* FIXME: Since we set the fram's garbaged flag, do we need this
+ call to screen_update? */
+ screen_update (sf, state[0].screen_behind);
+#if 0
+ /* We have a situation here. ScreenUpdate has just restored the
+ screen contents as it was before we started drawing this menu.
+ That includes any echo area message that could have been
+ displayed back then. (In reality, that echo area message will
+ almost always be the ``keystroke echo'' that echoes the sequence
+ of menu items chosen by the user.) However, if the menu had some
+ help messages, then displaying those messages caused Emacs to
+ forget about the original echo area message. So when
+ ScreenUpdate restored it, it created a discrepancy between the
+ actual screen contents and what Emacs internal data structures
+ know about it.
+
+ To avoid this conflict, we force Emacs to restore the original
+ echo area message as we found it when we entered this function.
+ The irony of this is that we then erase the restored message
+ right away, so the only purpose of restoring it is so that
+ erasing it works correctly... */
+ if (! NILP (saved_echo_area_message))
+ message_with_string ("%s", saved_echo_area_message, 0);
+ message (0);
+#endif
+ 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 0
+ mouse_clear_clicks ();
+#endif
+ if (!kbd_buffer_events_waiting ())
+ clear_input_pending ();
+#if 0
+ /* Allow mouse events generation by dos_rawgetc. */
+ mouse_preempted--;
+#endif
+ 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;
+}
+
+static struct frame *tty_menu_help_frame;
+
+/* 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).
+
+ This cannot be done with generating a HELP_EVENT because
+ XMenuActivate contains a loop that doesn't let Emacs process
+ keyboard events.
+
+ FIXME: Do we need this in TTY menus? */
+
+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)->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 ();
+}
+
+Lisp_Object
+tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
+ Lisp_Object title, 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 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. */
+ x += f->left_pos;
+ 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. */
+ 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));
+
+ tty_menu_help_frame = f; /* FIXME: This seems unused. */
+ 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);
+ 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_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
/***********************************************************************
Initialization
struct terminal *
init_tty (const char *name, const char *terminal_type, bool must_succeed)
{
- #ifdef TERMINFO
- char **address = 0;
- #else
char *area;
char **address = &area;
- #endif
int status;
struct tty_display_info *tty = NULL;
struct terminal *terminal = NULL;
/* On some systems, tgetent tries to access the controlling
terminal. */
block_tty_out_signal ();
- #ifdef TERMINFO
- status = tgetent (0, terminal_type);
- #else
status = tgetent (tty->termcap_term_buffer, terminal_type);
if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
emacs_abort ();
- #endif
unblock_tty_out_signal ();
if (status < 0)
terminal_type);
}
- #ifndef TERMINFO
area = tty->termcap_strings_buffer;
- #endif
tty->TS_ins_line = tgetstr ("al", address);
tty->TS_ins_multi_lines = tgetstr ("AL", address);
tty->TS_bell = tgetstr ("bl", address);
encode_terminal_src = NULL;
encode_terminal_dst = NULL;
+
+ DEFSYM (Qtty_menu_next_item, "tty-menu-next-item");
+ DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item");
+ DEFSYM (Qtty_menu_next_menu, "tty-menu-next-menu");
+ DEFSYM (Qtty_menu_prev_menu, "tty-menu-prev-menu");
+ DEFSYM (Qtty_menu_select, "tty-menu-select");
+ DEFSYM (Qtty_menu_ignore, "tty-menu-ignore");
+ DEFSYM (Qtty_menu_exit, "tty-menu-exit");
+ DEFSYM (Qtty_menu_mouse_movement, "tty-menu-mouse-movement");
+ DEFSYM (Qtty_menu_navigation_map, "tty-menu-navigation-map");
}
/* There is nothing else here at the moment... */
};
- #ifndef TERMINFO
enum { TERMCAP_BUFFER_SIZE = 4096 };
- #endif
/* Parameters that are shared between frames on the same tty device. */
mouse-face. */
Mouse_HLInfo mouse_highlight;
- #ifndef TERMINFO
/* Buffer used internally by termcap (see tgetent in the Termcap
manual). Only init_tty should use this. */
char termcap_term_buffer[TERMCAP_BUFFER_SIZE];
/* Buffer storing terminal description strings (see tgetstr in the
Termcap manual). Only init_tty should use this. */
char termcap_strings_buffer[TERMCAP_BUFFER_SIZE];
- #endif
/* Strings, numbers and flags taken from the termcap entry. */
/* Nonzero means use ^S/^Q for flow control. */
unsigned flow_control : 1;
+
+ /* Non-zero means we are displaying a TTY menu on this tty. */
+ unsigned showing_menu : 1;
};
/* A chain of structures for all tty devices currently in use. */
#include "systime.h" /* for Time */
INLINE_HEADER_BEGIN
- #ifndef TERMHOOKS_INLINE
- # define TERMHOOKS_INLINE INLINE
- #endif
enum scroll_bar_part {
+ scroll_bar_nowhere = -1,
scroll_bar_above_handle,
scroll_bar_handle,
scroll_bar_below_handle,
scroll_bar_move_ratio
};
- /* If the value of the frame parameter changed, whis hook is called.
- For example, if going from fullscreen to not fullscreen this hook
- may do something OS dependent, like extended window manager hints on X11. */
- extern void (*fullscreen_hook) (struct frame *f);
-
/* Output method of a terminal (and frames on this terminal, respectively). */
enum output_method
windows. */
void (*frame_raise_lower_hook) (struct frame *f, int raise_flag);
- /* If the value of the frame parameter changed, whis hook is called.
+ /* If the value of the frame parameter changed, this hook is called.
For example, if going from fullscreen to not fullscreen this hook
may do something OS dependent, like extended window manager hints on X11. */
void (*fullscreen_hook) (struct frame *f);
/* Most code should use these functions to set Lisp fields in struct
terminal. */
- TERMHOOKS_INLINE void
+ INLINE void
tset_charset_list (struct terminal *t, Lisp_Object val)
{
t->charset_list = val;
}
- TERMHOOKS_INLINE void
+ INLINE void
tset_selection_alist (struct terminal *t, Lisp_Object val)
{
t->Vselection_alist = val;
extern void close_gpm (int gpm_fd);
#endif
+#ifdef WINDOWSNT
+extern int cursorX (struct tty_display_info *);
+extern int cursorY (struct tty_display_info *);
+#else
+#define cursorX(t) curX(t)
+#define cursorY(t) curY(t)
+#endif
+
INLINE_HEADER_END
#endif /* EMACS_TERMHOOKS_H */
static WORD char_attr_normal;
static DWORD prev_console_mode;
+static CONSOLE_CURSOR_INFO console_cursor_info;
#ifndef USE_SEPARATE_SCREEN
static CONSOLE_CURSOR_INFO prev_console_cursor;
#endif
SetConsoleCursorPosition (cur_screen, cursor_coords);
}
+void
+w32con_hide_cursor (void)
+{
+ GetConsoleCursorInfo (cur_screen, &console_cursor_info);
+ console_cursor_info.bVisible = FALSE;
+ SetConsoleCursorInfo (cur_screen, &console_cursor_info);
+}
+
+void
+w32con_show_cursor (void)
+{
+ GetConsoleCursorInfo (cur_screen, &console_cursor_info);
+ console_cursor_info.bVisible = TRUE;
+ SetConsoleCursorInfo (cur_screen, &console_cursor_info);
+}
+
/* Clear from cursor to end of screen. */
static void
w32con_clear_to_end (struct frame *f)
}
+/* Report the current cursor position. The following two functions
+ are used in term.c's tty menu code, so they are not really
+ "stubs". */
+int
+cursorX (struct tty_display_info *tty)
+{
+ return cursor_coords.X;
+}
+
+int
+cursorY (struct tty_display_info *tty)
+{
+ return cursor_coords.Y;
+}
+
/***********************************************************************
Faces
***********************************************************************/
initialize_w32_display (struct terminal *term, int *width, int *height)
{
CONSOLE_SCREEN_BUFFER_INFO info;
- Mouse_HLInfo *hlinfo;
term->rif = 0; /* No window based redisplay on the console. */
term->cursor_to_hook = w32con_move_cursor;
struct frame *sf = XFRAME (selected_frame);
if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
- return FRAME_W32_DISPLAY_INFO (sf);
+ return FRAME_DISPLAY_INFO (sf);
else
return &one_w32_display_info;
}
f = XFRAME (frame);
if (! FRAME_W32_P (f))
error ("Non-W32 frame used");
- return FRAME_W32_DISPLAY_INFO (f);
+ return FRAME_DISPLAY_INFO (f);
}
}
\f
FOR_EACH_FRAME (tail, frame)
{
f = XFRAME (frame);
- if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
+ if (!FRAME_W32_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
continue;
if (FRAME_W32_WINDOW (f) == wdesc)
int i;
/* don't bother trying to create palette if not supported */
- if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
+ if (! FRAME_DISPLAY_INFO (f)->has_palette)
return;
log_palette = (LOGPALETTE *)
alloca (sizeof (LOGPALETTE) +
- FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
+ FRAME_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
log_palette->palVersion = 0x300;
- log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
+ log_palette->palNumEntries = FRAME_DISPLAY_INFO (f)->num_colors;
- list = FRAME_W32_DISPLAY_INFO (f)->color_list;
+ list = FRAME_DISPLAY_INFO (f)->color_list;
for (i = 0;
- i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
+ i < FRAME_DISPLAY_INFO (f)->num_colors;
i++, list = list->next)
log_palette->palPalEntry[i] = list->entry;
enter_crit ();
- if (FRAME_W32_DISPLAY_INFO (f)->palette)
- DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
- FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
+ if (FRAME_DISPLAY_INFO (f)->palette)
+ DeleteObject (FRAME_DISPLAY_INFO (f)->palette);
+ FRAME_DISPLAY_INFO (f)->palette = new_palette;
/* Realize display palette and garbage all frames. */
release_frame_dc (f, get_frame_dc (f));
void
w32_map_color (struct frame *f, COLORREF color)
{
- struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
+ struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list;
if (NILP (Vw32_enable_palette))
return;
list = xmalloc (sizeof (struct w32_palette_entry));
SET_W32_COLOR (list->entry, color);
list->refcount = 1;
- list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
- FRAME_W32_DISPLAY_INFO (f)->color_list = list;
- FRAME_W32_DISPLAY_INFO (f)->num_colors++;
+ list->next = FRAME_DISPLAY_INFO (f)->color_list;
+ FRAME_DISPLAY_INFO (f)->color_list = list;
+ FRAME_DISPLAY_INFO (f)->num_colors++;
/* set flag that palette must be regenerated */
- FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
+ FRAME_DISPLAY_INFO (f)->regen_palette = TRUE;
}
void
w32_unmap_color (struct frame *f, COLORREF color)
{
- struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
- struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
+ struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list;
+ struct w32_palette_entry **prev = &FRAME_DISPLAY_INFO (f)->color_list;
if (NILP (Vw32_enable_palette))
return;
{
*prev = list->next;
xfree (list);
- FRAME_W32_DISPLAY_INFO (f)->num_colors--;
+ FRAME_DISPLAY_INFO (f)->num_colors--;
break;
}
else
}
/* set flag that palette must be regenerated */
- FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
+ FRAME_DISPLAY_INFO (f)->regen_palette = TRUE;
}
#endif
else if (strcmp (SDATA (arg), "white") == 0)
return WHITE_PIX_DEFAULT (f);
- if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
+ if ((FRAME_DISPLAY_INFO (f)->n_planes * FRAME_DISPLAY_INFO (f)->n_cbits) == 1)
return def;
/* w32_defined_color is responsible for coping with failures
x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
do_pending_window_change (0);
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
}
FRAME_TOOL_BAR_LINES (f) = nlines;
resize_frame_windows (f, FRAME_LINES (f), 0);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* We also have to make sure that the internal border at the top of
the frame, below the menu bar or tool bar, is redrawn when the
{
/* Check for no change needed in this very common case
before we do any consing. */
- if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
+ if (!strcmp (FRAME_DISPLAY_INFO (f)->w32_id_name,
SDATA (f->name)))
return;
- name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
+ name = build_string (FRAME_DISPLAY_INFO (f)->w32_id_name);
}
else
CHECK_STRING (name);
static HWND
w32_createscrollbar (struct frame *f, struct scroll_bar * bar)
{
- return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
- /* Position and size of scroll bar. */
- XINT (bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- XINT (bar->top),
- XINT (bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- XINT (bar->height),
- FRAME_W32_WINDOW (f),
- NULL,
- hinst,
- NULL));
+ return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
+ /* Position and size of scroll bar. */
+ XINT (bar->left), XINT (bar->top),
+ XINT (bar->width), XINT (bar->height),
+ FRAME_W32_WINDOW (f), NULL, hinst, NULL);
}
static void
if (NILP (Fmemq (frame, Vframe_list)))
{
#ifdef GLYPH_DEBUG
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+ struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
#endif
x_free_frame_resources (f);
static void
x_default_font_parameter (struct frame *f, Lisp_Object parms)
{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+ struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
RES_TYPE_STRING);
Lisp_Object font;
if (! STRINGP (f->icon_name))
fset_icon_name (f, Qnil);
- /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
+ /* FRAME_DISPLAY_INFO (f) = dpyinfo; */
- /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
+ /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
record_unwind_protect (do_unwind_create_frame, frame);
#ifdef GLYPH_DEBUG
image_cache_refcount =
}
else
{
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
f->output_data.w32->explicit_parent = 0;
}
"fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
/* Now consider the frame official. */
f->terminal->reference_count++;
- FRAME_W32_DISPLAY_INFO (f)->reference_count++;
+ FRAME_DISPLAY_INFO (f)->reference_count++;
Vframe_list = Fcons (frame, Vframe_list);
/* We need to do this after creating the window, so that the
Lisp_Object
x_get_focus_frame (struct frame *frame)
{
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
+ struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
Lisp_Object xfocus;
if (! dpyinfo->w32_focus_frame)
return Qnil;
return xfocus;
}
- DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
- doc: /* Give FRAME input focus, raising to foreground if necessary. */)
- (Lisp_Object frame)
- {
- x_focus_on_frame (decode_window_system_frame (frame));
- return Qnil;
- }
-
- \f
DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
doc: /* Internal function called by `color-defined-p', which see.
\(Note that the Nextstep version of this function ignores FRAME.) */)
int
x_screen_planes (register struct frame *f)
{
- return FRAME_W32_DISPLAY_INFO (f)->n_planes;
+ return FRAME_DISPLAY_INFO (f)->n_planes;
}
\f
/* Return the display structure for the display named NAME.
if (! NILP (xrm_string))
CHECK_STRING (xrm_string);
- #if 0
- if (! EQ (Vwindow_system, intern ("w32")))
- error ("Not using Microsoft Windows");
- #endif
-
/* Allow color mapping to be defined externally; first look in user's
HOME directory, then in Emacs etc dir for a file called rgb.txt. */
{
f = SELECTED_FRAME ();
if (!FRAME_W32_P (f))
- return;
+ {
+ unblock_input ();
+ return;
+ }
w32_show_hourglass (f);
unblock_input ();
dpyinfo_refcount = dpyinfo->reference_count;
#endif /* GLYPH_DEBUG */
FRAME_KBOARD (f) = kb;
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
f->output_data.w32->explicit_parent = 0;
/* Set the name; the functions to which we pass f expect the name to
init_frame_faces (f);
f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
window_prompting = x_figure_window_size (f, parms, 0);
/* Now that the frame is official, it counts as a reference to
its display. */
- FRAME_W32_DISPLAY_INFO (f)->reference_count++;
+ FRAME_DISPLAY_INFO (f)->reference_count++;
f->terminal->reference_count++;
/* It is now ok to make the frame official even if we get an error
/* Default min and max values. */
min_x = 0;
min_y = 0;
- max_x = x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f));
- max_y = x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f));
+ max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
+ max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
block_input ();
GetCursorPos (&pt);
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
- frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
+ frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string);
f = XFRAME (frame);
/* Set up the frame's root window. */
}
FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
w->pseudo_window_p = 1;
/* Display the tooltip text in a temporary buffer. */
width /= WINDOW_FRAME_COLUMN_WIDTH (w);
w->total_cols = width;
FRAME_TOTAL_COLS (f) = width;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
w->pseudo_window_p = 1;
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
defsubr (&Sx_close_connection);
defsubr (&Sx_display_list);
defsubr (&Sx_synchronize);
- defsubr (&Sx_focus_frame);
/* W32 specific functions */
unblock_input ();
discard_menu_items ();
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
if (error_name) error (error_name);
return selection;
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
- memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+ memcpy (previous_items, XVECTOR (f->menu_bar_vector)->u.contents,
previous_menu_items_used * word_size);
/* Fill in menu_items with the current menu bar contents.
return Qnil;
}
+ block_input ();
+
/* Create a tree of widget_value objects
representing the panes and their items. */
wv = xmalloc_widget_value ();
/* Clean up extraneous mouse events which might have been generated
during the call. */
discard_mouse_events ();
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
/* Free the widget_value objects we used to specify the contents. */
free_menubar_widget_value_tree (first_wv);
if (!NILP (subprefix_stack[j]))
entry = Fcons (subprefix_stack[j], entry);
}
+ unblock_input ();
return entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
}
}
else if (!for_click)
- /* Make "Cancel" equivalent to C-g. */
- Fsignal (Qquit, Qnil);
+ {
+ unblock_input ();
+ /* Make "Cancel" equivalent to C-g. */
+ Fsignal (Qquit, Qnil);
+ }
+ unblock_input ();
return Qnil;
}
\f
lw_pop_up_all_widgets (dialog_id);
/* Process events that apply to the menu. */
- popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
+ popup_get_selection ((XEvent *) 0, FRAME_DISPLAY_INFO (f), dialog_id);
lw_destroy_all_widgets (dialog_id);
frame. It differs from w32_focus_frame when we're using a global
minibuffer. */
struct frame *x_highlight_frame;
+
+ /* The frame waiting to be auto-raised in w32_read_socket. */
+ struct frame *w32_pending_autoraise_frame;
+
+ /* The frame where the mouse was last time we reported a mouse event. */
+ struct frame *last_mouse_frame;
+
+ /* The frame where the mouse was last time we reported a mouse motion. */
+ struct frame *last_mouse_motion_frame;
+
+ /* The frame where the mouse was last time we reported a mouse position. */
+ struct frame *last_mouse_glyph_frame;
+
+ /* Position where the mouse was last time we reported a motion.
+ This is a position on last_mouse_motion_frame. */
+ int last_mouse_motion_x;
+ int last_mouse_motion_y;
+
+ /* Where the mouse was last time we reported a mouse position.
+ This is a rectangle on last_mouse_glyph_frame. */
+ RECT last_mouse_glyph;
+
+ /* The scroll bar in which the last motion event occurred. */
+ struct scroll_bar *last_mouse_scroll_bar;
+
+ /* Mouse position on the scroll bar above.
+ FIXME: shouldn't it be a member of struct scroll_bar? */
+ int last_mouse_scroll_bar_pos;
+
+ /* Time of last mouse movement. */
+ Time last_mouse_movement_time;
};
/* This is a chain of structures for all the displays currently in use. */
Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
- extern void x_focus_on_frame (struct frame *f);
-
/* also defined in xterm.h XXX: factor out to common header */
extern struct w32_display_info *w32_term_init (Lisp_Object,
int cols, int rows);
extern int x_display_pixel_height (struct w32_display_info *);
extern int x_display_pixel_width (struct w32_display_info *);
- extern void x_sync (struct frame *);
extern Lisp_Object x_get_focus_frame (struct frame *);
extern void x_set_mouse_position (struct frame *f, int h, int v);
extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
extern Lisp_Object x_get_focus_frame (struct frame *);
+/* w32console.c */
+extern void w32con_hide_cursor (void);
+extern void w32con_show_cursor (void);
+
\f
#define PIX_TYPE COLORREF
#define FRAME_BASELINE_OFFSET(f) ((f)->output_data.w32->baseline_offset)
/* This gives the w32_display_info structure for the display F is on. */
- #define FRAME_W32_DISPLAY_INFO(f) (&one_w32_display_info)
- #define FRAME_X_DISPLAY_INFO(f) (&one_w32_display_info)
+ #define FRAME_DISPLAY_INFO(f) (&one_w32_display_info)
/* This is the `Display *' which frame F is on. */
#define FRAME_X_DISPLAY(f) (0)
- /* Value is the smallest width of any character in any font on frame F. */
-
- #define FRAME_SMALLEST_CHAR_WIDTH(F) \
- FRAME_W32_DISPLAY_INFO(F)->smallest_char_width
-
- /* Value is the smallest height of any font on frame F. */
-
- #define FRAME_SMALLEST_FONT_HEIGHT(F) \
- FRAME_W32_DISPLAY_INFO(F)->smallest_font_height
-
#define FRAME_NORMAL_PLACEMENT(F) ((F)->output_data.w32->normal_placement)
#define FRAME_PREV_FSMODE(F) ((F)->output_data.w32->prev_fsmode)
#define SET_SCROLL_BAR_W32_WINDOW(ptr, id) \
(SCROLL_BAR_UNPACK ((ptr)->w32_window_low, (ptr)->w32_window_high, (intptr_t) id))
- /* Extract the X widget of the scroll bar from a struct scroll_bar. */
- #define SCROLL_BAR_X_WIDGET(ptr) \
- ((Widget) SCROLL_BAR_PACK ((ptr)->x_widget_low, (ptr)->x_widget_high))
-
- /* Store a widget id in a struct scroll_bar. */
- #define SET_SCROLL_BAR_X_WIDGET(ptr, w) \
- (SCROLL_BAR_UNPACK ((ptr)->x_widget_low, (ptr)->x_widget_high, (int) w))
-
/* Return the inside width of a vertical scroll bar, given the outside
width. */
#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
((width) \
- VERTICAL_SCROLL_BAR_LEFT_BORDER \
- - VERTICAL_SCROLL_BAR_RIGHT_BORDER \
- - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2)
+ - VERTICAL_SCROLL_BAR_RIGHT_BORDER)
/* Return the length of the rectangle within which the top of the
handle must stay. This isn't equivalent to the inside height,
/* Minimum lengths for scroll bar handles, in pixels. */
#define VERTICAL_SCROLL_BAR_MIN_HANDLE (vertical_scroll_bar_min_handle)
- /* Trimming off a few pixels from each side prevents
- text from glomming up against the scroll bar */
- #define VERTICAL_SCROLL_BAR_WIDTH_TRIM (0)
-
- \f
struct frame; /* from frame.h */
extern void w32_fill_rect (struct frame *, HDC, COLORREF, RECT *);
#include <config.h>
- #define WINDOW_INLINE EXTERN_INLINE
-
#include <stdio.h>
#include "lisp.h"
#include "blockinput.h"
#include "intervals.h"
#include "termhooks.h" /* For FRAME_TERMINAL. */
-
- #ifdef HAVE_X_WINDOWS
- #include "xterm.h"
- #endif /* HAVE_X_WINDOWS */
- #ifdef HAVE_NTGUI
- #include "w32term.h"
- #endif
+ #ifdef HAVE_WINDOW_SYSTEM
+ #include TERM_HEADER
+ #endif /* HAVE_WINDOW_SYSTEM */
#ifdef MSDOS
#include "msdos.h"
#endif
- #ifdef HAVE_NS
- #include "nsterm.h"
- #endif
Lisp_Object Qwindowp, Qwindow_live_p;
static Lisp_Object Qwindow_valid_p;
cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
foreach_window (f, check_window_containing, &cw);
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* If not found above, see if it's in the tool bar window, if a tool
bar exists. */
if (NILP (window)
*part = ON_TEXT;
window = f->tool_bar_window;
}
+ #endif
return window;
}
}
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
run_window_configuration_change_hook (f);
non-Lisp data, so do it only for slots which should not be zero. */
w->nrows_scale_factor = w->ncols_scale_factor = 1;
w->left_fringe_width = w->right_fringe_width = -1;
+ w->mode_line_height = w->header_line_height = -1;
w->phys_cursor_type = -1;
w->phys_cursor_width = -1;
w->scroll_bar_width = -1;
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
run_window_configuration_change_hook (f);
block_input ();
window_resize_apply (p, horflag);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* Set buffer of NEW to buffer of reference window. Don't run
any hooks. */
set_window_buffer (new, r->contents, 0, 1);
recombine_windows (sibling);
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
/* We deleted the frame's selected window. */
w->total_lines -= XINT (value);
/* Enforce full redisplay. FIXME: make it more selective. */
windows_or_buffers_changed++;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
}
}
w->total_lines = 1;
/* Enforce full redisplay. FIXME: make it more selective. */
windows_or_buffers_changed++;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
}
/* If the above failed for whatever strange reason we must make a
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
run_window_configuration_change_hook (f);
visible. */
w->vscroll = (it.last_visible_y
- it.current_y + it.max_ascent + it.max_descent);
- adjust_glyphs (it.f);
+ adjust_frame_glyphs (it.f);
}
else
{
/* Invalidate pixel data calculated for all compositions. */
for (i = 0; i < n_compositions; i++)
composition_table[i]->font = NULL;
-
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
-
+ #endif
Fredraw_frame (WINDOW_FRAME (w));
SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
}
};
#define SAVED_WINDOW_N(swv,n) \
- ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
+ ((struct saved_window *) (XVECTOR ((swv)->u.contents[(n)])))
DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
doc: /* Return t if OBJECT is a window-configuration object. */)
|| data->frame_cols != previous_frame_cols)
change_frame_size (f, data->frame_lines,
data->frame_cols, 0, 0, 0);
-#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
+#ifdef HAVE_MENUS
if (data->frame_menu_bar_lines
!= previous_frame_menu_bar_lines)
- x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
- make_number (0));
+ {
+ if (FRAME_WINDOW_P (f))
+ x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
+ make_number (0));
+ else /* TTY or MSDOS */
+ set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
+ make_number (0));
+ }
+#endif
#ifdef HAVE_WINDOW_SYSTEM
if (data->frame_tool_bar_lines
!= previous_frame_tool_bar_lines)
x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
make_number (0));
-#endif
#endif
/* "Swap out" point from the selected window's buffer
|| previous_frame_cols != FRAME_COLS (f))
change_frame_size (f, previous_frame_lines, previous_frame_cols,
0, 0, 0);
-#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
+#ifdef HAVE_MENUS
if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
- x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
- make_number (0));
+ {
+ if (FRAME_WINDOW_P (f))
+ x_set_menu_bar_lines (f,
+ make_number (previous_frame_menu_bar_lines),
+ make_number (0));
+ else /* TTY or MSDOS */
+ set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
+ make_number (0));
+ }
+#endif
#ifdef HAVE_WINDOW_SYSTEM
if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
make_number (0));
-#endif
#endif
/* Now, free glyph matrices in windows that were not reused. */
++n;
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
/* Scan dead buffer windows. */
clear_glyph_matrix (w->current_matrix);
w->window_end_valid = 0;
windows_or_buffers_changed++;
- adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
+ adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
}
\f
/* Adjust glyph matrix of the frame if the virtual display
area becomes larger than before. */
if (w->vscroll < 0 && w->vscroll < old_dy)
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* Prevent redisplay shortcuts. */
XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
Vterminal_frame = selected_frame;
minibuf_window = f->minibuffer_window;
selected_window = f->selected_window;
- last_nonminibuf_frame = f;
window_initialized = 1;
}
/* Display generation from window structure and buffer text.
- Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
- Inc.
+ Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "font.h"
#include "fontset.h"
#include "blockinput.h"
-
- #ifdef HAVE_X_WINDOWS
- #include "xterm.h"
- #endif
- #ifdef HAVE_NTGUI
- #include "w32term.h"
- #endif
- #ifdef HAVE_NS
- #include "nsterm.h"
- #endif
- #ifdef USE_GTK
- #include "gtkutil.h"
- #endif
+ #ifdef HAVE_WINDOW_SYSTEM
+ #include TERM_HEADER
+ #endif /* HAVE_WINDOW_SYSTEM */
#ifndef FRAME_X_OUTPUT
#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
/* Non-zero means print newline to stdout before next mini-buffer
message. */
- int noninteractive_need_newline;
+ bool noninteractive_need_newline;
/* Non-zero means print newline to message log before next message. */
- static int message_log_need_newline;
+ static bool message_log_need_newline;
/* Three markers that message_dolog uses.
It could allocate them itself, but that causes trouble
/* Nonzero if an overlay arrow has been displayed in this window. */
- static int overlay_arrow_seen;
+ static bool overlay_arrow_seen;
/* Vector containing glyphs for an ellipsis `...'. */
/* Nonzero means multibyte characters were enabled when the echo area
message was specified. */
- static int message_enable_multibyte;
+ static bool message_enable_multibyte;
/* Nonzero if we should redraw the mode lines on the next redisplay. */
int windows_or_buffers_changed;
- /* Nonzero means a frame's cursor type has been changed. */
-
- static int cursor_type_changed;
-
/* Nonzero after display_mode_line if %l was used and it displayed a
line number. */
- static int line_number_displayed;
+ static bool line_number_displayed;
/* The name of the *Messages* buffer, a string. */
/* Non-zero means display_echo_area should display the last echo area
message again. Set by redisplay_preserve_echo_area. */
- static int display_last_displayed_message_p;
+ static bool display_last_displayed_message_p;
/* Nonzero if echo area is being used by print; zero if being used by
message. */
- static int message_buf_print;
+ static bool message_buf_print;
/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
/* Set to 1 in clear_message to make redisplay_internal aware
of an emptied echo area. */
- static int message_cleared_p;
+ static bool message_cleared_p;
/* A scratch glyph row with contents used for generating truncation
glyphs. Also used in direct_output_for_insert. */
/* Non-zero if there's a help-echo in the echo area. */
- int help_echo_showing_p;
-
- /* If >= 0, computed, exact values of mode-line and header-line height
- to use in the macros CURRENT_MODE_LINE_HEIGHT and
- CURRENT_HEADER_LINE_HEIGHT. */
-
- int current_mode_line_height, current_header_line_height;
+ bool help_echo_showing_p;
/* The maximum distance to look ahead for text properties. Values
that are too small let us call compute_char_face and similar
#ifdef HAVE_WINDOW_SYSTEM
/* Non-zero means an hourglass cursor is currently shown. */
- int hourglass_shown_p;
+ bool hourglass_shown_p;
/* If non-null, an asynchronous timer that, when it expires, displays
an hourglass cursor on all frames. */
#ifdef HAVE_WINDOW_SYSTEM
static void x_consider_frame_title (Lisp_Object);
- static int tool_bar_lines_needed (struct frame *, int *);
static void update_tool_bar (struct frame *, int);
- static void build_desired_tool_bar_string (struct frame *f);
static int redisplay_tool_bar (struct frame *);
- static void display_tool_bar_line (struct it *, int);
static void notice_overwritten_cursor (struct window *,
enum glyph_row_area,
int, int, int, int);
/* Compute exact mode line heights. */
if (WINDOW_WANTS_MODELINE_P (w))
- current_mode_line_height
+ w->mode_line_height
= display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
BVAR (current_buffer, mode_line_format));
if (WINDOW_WANTS_HEADER_LINE_P (w))
- current_header_line_height
+ w->header_line_height
= display_mode_line (w, HEADER_LINE_FACE_ID,
BVAR (current_buffer, header_line_format));
if (old_buffer)
set_buffer_internal_1 (old_buffer);
- current_header_line_height = current_mode_line_height = -1;
-
if (visible_p && w->hscroll > 0)
*x -=
window_hscroll_limited (w, WINDOW_XFRAME (w))
text, or we can't tell because W's current matrix is not up to
date. */
- static
- struct glyph *
+ static struct glyph *
x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
int *dx, int *dy, int *area)
{
if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
{
struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
- it->dpvec = v->contents;
- it->dpend = v->contents + v->header.size;
+ it->dpvec = v->u.contents;
+ it->dpend = v->u.contents + v->header.size;
}
else
{
return glyphless_method;
}
- /* Load IT's display element fields with information about the next
- display element from the current position of IT. Value is zero if
- end of buffer (or C string) is reached. */
+ /* Merge escape glyph face and cache the result. */
static struct frame *last_escape_glyph_frame = NULL;
static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
static int last_escape_glyph_merged_face_id = 0;
- struct frame *last_glyphless_glyph_frame = NULL;
- int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
- int last_glyphless_glyph_merged_face_id = 0;
+ static int
+ merge_escape_glyph_face (struct it *it)
+ {
+ int face_id;
+
+ if (it->f == last_escape_glyph_frame
+ && it->face_id == last_escape_glyph_face_id)
+ face_id = last_escape_glyph_merged_face_id;
+ else
+ {
+ /* Merge the `escape-glyph' face into the current face. */
+ face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id);
+ last_escape_glyph_frame = it->f;
+ last_escape_glyph_face_id = it->face_id;
+ last_escape_glyph_merged_face_id = face_id;
+ }
+ return face_id;
+ }
+
+ /* Likewise for glyphless glyph face. */
+
+ static struct frame *last_glyphless_glyph_frame = NULL;
+ static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+ static int last_glyphless_glyph_merged_face_id = 0;
+
+ int
+ merge_glyphless_glyph_face (struct it *it)
+ {
+ int face_id;
+
+ if (it->f == last_glyphless_glyph_frame
+ && it->face_id == last_glyphless_glyph_face_id)
+ face_id = last_glyphless_glyph_merged_face_id;
+ else
+ {
+ /* Merge the `glyphless-char' face into the current face. */
+ face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
+ last_glyphless_glyph_frame = it->f;
+ last_glyphless_glyph_face_id = it->face_id;
+ last_glyphless_glyph_merged_face_id = face_id;
+ }
+ return face_id;
+ }
+
+ /* Load IT's display element fields with information about the next
+ display element from the current position of IT. Value is zero if
+ end of buffer (or C string) is reached. */
static int
get_next_display_element (struct it *it)
if (v->header.size)
{
it->dpvec_char_len = it->len;
- it->dpvec = v->contents;
- it->dpend = v->contents + v->header.size;
+ it->dpvec = v->u.contents;
+ it->dpend = v->u.contents + v->header.size;
it->current.dpvec_index = 0;
it->dpvec_face_id = -1;
it->saved_face_id = it->face_id;
g = GLYPH_CODE_CHAR (gc);
lface_id = GLYPH_CODE_FACE (gc);
}
- if (lface_id)
- {
- face_id = merge_faces (it->f, Qt, lface_id, it->face_id);
- }
- else if (it->f == last_escape_glyph_frame
- && it->face_id == last_escape_glyph_face_id)
- {
- face_id = last_escape_glyph_merged_face_id;
- }
- else
- {
- /* Merge the escape-glyph face into the current face. */
- face_id = merge_faces (it->f, Qescape_glyph, 0,
- it->face_id);
- last_escape_glyph_frame = it->f;
- last_escape_glyph_face_id = it->face_id;
- last_escape_glyph_merged_face_id = face_id;
- }
+
+ face_id = (lface_id
+ ? merge_faces (it->f, Qt, lface_id, it->face_id)
+ : merge_escape_glyph_face (it));
XSETINT (it->ctl_chars[0], g);
XSETINT (it->ctl_chars[1], c ^ 0100);
escape_glyph = GLYPH_CODE_CHAR (gc);
lface_id = GLYPH_CODE_FACE (gc);
}
- if (lface_id)
- {
- /* The display table specified a face.
- Merge it into face_id and also into escape_glyph. */
- face_id = merge_faces (it->f, Qt, lface_id,
- it->face_id);
- }
- else if (it->f == last_escape_glyph_frame
- && it->face_id == last_escape_glyph_face_id)
- {
- face_id = last_escape_glyph_merged_face_id;
- }
- else
- {
- /* Merge the escape-glyph face into the current face. */
- face_id = merge_faces (it->f, Qescape_glyph, 0,
- it->face_id);
- last_escape_glyph_frame = it->f;
- last_escape_glyph_face_id = it->face_id;
- last_escape_glyph_merged_face_id = face_id;
- }
+
+ face_id = (lface_id
+ ? merge_faces (it->f, Qt, lface_id, it->face_id)
+ : merge_escape_glyph_face (it));
/* Draw non-ASCII hyphen with just highlighting: */
old_deactivate_mark = Vdeactivate_mark;
oldbuf = current_buffer;
- Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
+
+ /* Ensure the Messages buffer exists, and switch to it.
+ If we created it, set the major-mode. */
+ {
+ int newbuffer = 0;
+ if (NILP (Fget_buffer (Vmessages_buffer_name))) newbuffer = 1;
+
+ Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
+
+ if (newbuffer &&
+ !NILP (Ffboundp (intern ("messages-buffer-mode"))))
+ call0 (intern ("messages-buffer-mode"));
+ }
+
bset_undo_list (current_buffer, Qt);
oldpoint = message_dolog_marker1;
if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
{
if (f->resized_p)
- {
- redraw_frame (f);
- f->force_flush_display_p = 1;
- }
- clear_current_matrices (f);
+ redraw_frame (f);
+ else
+ clear_current_matrices (f);
changed_count++;
f->garbaged = 0;
f->resized_p = 0;
Can do with a display update of the echo area,
unless we displayed some mode lines. */
update_single_window (w, 1);
- FRAME_RIF (f)->flush_display (f);
+ flush_frame (f);
}
else
update_frame (f, 1, 1);
#ifdef HAVE_WINDOW_SYSTEM
- /* Where the mouse was last time we reported a mouse event. */
-
- struct frame *last_mouse_frame;
-
/* Tool-bar item index of the item on which a mouse button was pressed
or -1. */
}
}
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
/* Set F->desired_tool_bar_string to a Lisp string representing frame
F's desired tool-bar contents. F->tool_bar_items must have
return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
}
+ #endif /* !USE_GTK && !HAVE_NS */
+
+ #if defined USE_GTK || defined HAVE_NS
+ EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
+ #endif
DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
0, 1, 0,
If FRAME is nil or omitted, use the selected frame. */)
(Lisp_Object frame)
{
+ int nlines = 0;
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
struct frame *f = decode_any_frame (frame);
struct window *w;
- int nlines = 0;
if (WINDOWP (f->tool_bar_window)
&& (w = XWINDOW (f->tool_bar_window),
nlines = tool_bar_lines_needed (f, NULL);
}
}
-
+ #endif
return make_number (nlines);
}
static int
redisplay_tool_bar (struct frame *f)
{
- struct window *w;
- struct it it;
- struct glyph_row *row;
-
#if defined (USE_GTK) || defined (HAVE_NS)
+
if (FRAME_EXTERNAL_TOOL_BAR (f))
update_frame_tool_bar (f);
return 0;
- #endif
+
+ #else /* !USE_GTK && !HAVE_NS */
+
+ struct window *w;
+ struct it it;
+ struct glyph_row *row;
/* If frame hasn't a tool-bar window or if it is zero-height, don't
do anything. This means you must start with tool-bar-lines
if (WINDOW_TOTAL_LINES (w) != old_height)
{
clear_glyph_matrix (w->desired_matrix);
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
return 1;
}
}
{
clear_glyph_matrix (w->desired_matrix);
f->n_tool_bar_rows = nrows;
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
return 1;
}
}
f->minimize_tool_bar_window_p = 0;
return 0;
+
+ #endif /* USE_GTK || HAVE_NS */
}
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
/* Get information about the tool-bar item which is displayed in GLYPH
on frame F. Return in *PROP_IDX the index where tool-bar item
{
Lisp_Object window = f->tool_bar_window;
struct window *w = XWINDOW (window);
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
int hpos, vpos;
struct glyph *glyph;
clear_mouse_face (hlinfo);
/* Mouse is down, but on different tool-bar item? */
- mouse_down_p = (dpyinfo->grabbed
- && f == last_mouse_frame
- && FRAME_LIVE_P (f));
+ mouse_down_p = (x_mouse_grabbed (dpyinfo)
+ && f == dpyinfo->last_mouse_frame);
+
if (mouse_down_p
&& last_tool_bar_item != prop_idx)
return;
help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
}
+ #endif /* !USE_GTK && !HAVE_NS */
+
#endif /* HAVE_WINDOW_SYSTEM */
last_glyphless_glyph_frame = NULL;
last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
- /* If new fonts have been loaded that make a glyph matrix adjustment
- necessary, do it. */
- if (fonts_changed_p)
- {
- adjust_glyphs (NULL);
- ++windows_or_buffers_changed;
- fonts_changed_p = 0;
- }
-
/* If face_change_count is non-zero, init_iterator will free all
realized faces, which includes the faces referenced from current
matrices. So, we can't reuse current matrices in this case. */
struct frame *f = XFRAME (frame);
if (FRAME_VISIBLE_P (f))
- ++number_of_visible_frames;
+ {
+ ++number_of_visible_frames;
+ /* Adjust matrices for visible frames only. */
+ if (f->fonts_changed)
+ {
+ adjust_frame_glyphs (f);
+ f->fonts_changed = 0;
+ }
+ /* If cursor type has been changed on the frame
+ other than selected, consider all frames. */
+ if (f != sf && f->cursor_type_changed)
+ update_mode_lines++;
+ }
clear_desired_matrices (f);
}
}
consider_all_windows_p = (update_mode_lines
- || buffer_shared_and_changed ()
- || cursor_type_changed);
+ || buffer_shared_and_changed ());
/* If specs for an arrow have changed, do thorough redisplay
to ensure we remove any arrow that should no longer exist. */
if (!display_last_displayed_message_p)
message_cleared_p = 0;
- if (fonts_changed_p)
- goto retry;
- else if (window_height_changed_p)
+ if (window_height_changed_p)
{
consider_all_windows_p = 1;
++update_mode_lines;
&& !current_buffer->prevent_redisplay_optimizations_p
&& FRAME_VISIBLE_P (XFRAME (w->frame))
&& !FRAME_OBSCURED_P (XFRAME (w->frame))
+ && !XFRAME (w->frame)->cursor_type_changed
/* Make sure recorded data applies to current buffer, etc. */
&& this_line_buffer == current_buffer
&& match_p
&& !EQ (FRAME_TTY (f)->top_frame, frame))
continue;
+ retry_frame:
+
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
/* Mark all the scroll bars to be removed; we'll redeem
if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
- /* If fonts changed, display again. */
- /* ??? rms: I suspect it is a mistake to jump all the way
- back to retry here. It should just retry this frame. */
- if (fonts_changed_p)
- goto retry;
-
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
{
+ /* If fonts changed on visible frame, display again. */
+ if (f->fonts_changed)
+ {
+ adjust_frame_glyphs (f);
+ f->fonts_changed = 0;
+ goto retry_frame;
+ }
+
/* See if we have to hscroll. */
if (!f->already_hscrolled_p)
{
f->already_hscrolled_p = 1;
if (hscroll_windows (f->root_window))
- goto retry;
+ goto retry_frame;
}
/* Prevent various kinds of signals during display
/* Update the display. */
set_window_update_flags (XWINDOW (f->root_window), 1);
pending |= update_frame (f, 0, 0);
+ f->cursor_type_changed = 0;
f->updated_p = 1;
}
}
update:
/* If fonts changed, display again. */
- if (fonts_changed_p)
+ if (sf->fonts_changed)
goto retry;
/* Prevent various kinds of signals during display update.
XWINDOW (selected_window)->must_be_updated_p = 1;
pending = update_frame (sf, 0, 0);
+ sf->cursor_type_changed = 0;
}
/* We may have called echo_area_display at the top of this
{
XWINDOW (mini_window)->must_be_updated_p = 1;
pending |= update_frame (mini_frame, 0, 0);
+ mini_frame->cursor_type_changed = 0;
if (!pending && hscroll_windows (mini_window))
goto retry;
}
update_mode_lines = 0;
windows_or_buffers_changed = 0;
- cursor_type_changed = 0;
}
/* Start SIGIO interrupts coming again. Having them off during the
else
redisplay_internal ();
- if (FRAME_RIF (SELECTED_FRAME ()) != NULL
- && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
- FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (NULL);
+ flush_frame (SELECTED_FRAME ());
}
cases. */
&& !update_mode_lines
&& !windows_or_buffers_changed
- && !cursor_type_changed
+ && !f->cursor_type_changed
/* Can't use this case if highlighting a region. When a
region exists, cursor movement has to do more than just
set the cursor. */
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
selected_window is redisplayed.
- We can return without actually redisplaying the window if
- fonts_changed_p. In that case, redisplay_internal will
- retry. */
+ We can return without actually redisplaying the window if fonts has been
+ changed on window's frame. In that case, redisplay_internal will retry. */
static void
redisplay_window (Lisp_Object window, int just_this_one_p)
debug_method_add (w, "try_window_id %d", tem);
#endif
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
if (tem > 0)
goto done;
IF_DEBUG (debug_method_add (w, "1"));
if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
/* -1 means we need to scroll.
- 0 means we need new matrices, but fonts_changed_p
+ 0 means we need new matrices, but fonts_changed
is set in that case, so we will detect it below. */
goto try_to_scroll;
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
if (w->cursor.vpos >= 0)
/* Redisplay the window. */
if (!current_matrix_up_to_date_p
|| windows_or_buffers_changed
- || cursor_type_changed
+ || f->cursor_type_changed
/* Don't use try_window_reusing_current_matrix in this case
because it can have changed the buffer. */
|| !NILP (Vwindow_scroll_functions)
/* If new fonts have been loaded (due to fontsets), give up. We
have to start a new redisplay since we need to re-adjust glyph
matrices. */
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
/* If cursor did not appear assume that the middle of the window is
if (WINDOW_WANTS_MODELINE_P (w)
&& CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
{
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
+ w->mode_line_height = -1;
MATRIX_MODE_LINE_ROW (w->current_matrix)->height
= DESIRED_MODE_LINE_HEIGHT (w);
}
if (WINDOW_WANTS_HEADER_LINE_P (w)
&& CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
{
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
+ w->header_line_height = -1;
MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
= DESIRED_HEADER_LINE_HEIGHT (w);
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
}
}
#endif /* HAVE_WINDOW_SYSTEM */
- /* We go to this label, with fonts_changed_p set,
- if it is necessary to try again using larger glyph matrices.
+ /* We go to this label, with fonts_changed set, if it is
+ necessary to try again using larger glyph matrices.
We have to redeem the scroll bar even in this case,
because the loop in redisplay_internal expects that. */
need_larger_matrices:
{
if (display_line (&it))
last_text_row = it.glyph_row - 1;
- if (fonts_changed_p && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
+ if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
return 0;
}
/* Don't try to reuse the display if windows have been split
or such. */
|| windows_or_buffers_changed
- || cursor_type_changed)
+ || f->cursor_type_changed)
return 0;
/* Can't do this if region may have changed. */
w->cursor.vpos = -1;
last_text_row = last_reused_text_row = NULL;
- while (it.current_y < it.last_visible_y
- && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
{
/* If we have reached into the characters in the START row,
that means the line boundaries have changed. So we
if (pt_row == NULL)
w->cursor.vpos = -1;
last_text_row = NULL;
- while (it.current_y < it.last_visible_y && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
if (display_line (&it))
last_text_row = it.glyph_row - 1;
GIVE_UP (1);
/* This flag is used to prevent redisplay optimizations. */
- if (windows_or_buffers_changed || cursor_type_changed)
+ if (windows_or_buffers_changed || f->cursor_type_changed)
GIVE_UP (2);
/* Verify that narrowing has not changed.
row = row_containing_pos (w, PT, r0, NULL, 0);
if (row)
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
- else
- emacs_abort ();
return 1;
}
}
row = row_containing_pos (w, PT, r0, NULL, 0);
if (row)
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
- else
- emacs_abort ();
return 2;
}
}
last_text_row = NULL;
overlay_arrow_seen = 0;
while (it.current_y < it.last_visible_y
- && !fonts_changed_p
+ && !f->fonts_changed
&& (first_unchanged_at_end_row == NULL
|| IT_CHARPOS (it) < stop_pos))
{
last_text_row = it.glyph_row - 1;
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
return -1;
/* Display the rest of the lines at the window end. */
it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
- while (it.current_y < it.last_visible_y
- && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
{
/* Is it always sure that the display agrees with lines in
the current matrix? I don't think so, so we mark rows
>= it->w->desired_matrix->nrows)
{
it->w->nrows_scale_factor++;
- fonts_changed_p = 1;
+ it->f->fonts_changed = 1;
return 0;
}
compute_line_metrics (&it);
}
+#ifdef HAVE_MENUS
+/* Deep copy of a glyph row, including the glyphs. */
+static void
+deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
+{
+ int area, i, sum_used = 0;
+ struct glyph *pointers[1 + LAST_AREA];
+
+ /* Save glyph pointers of TO. */
+ memcpy (pointers, to->glyphs, sizeof to->glyphs);
+
+ /* Do a structure assignment. */
+ *to = *from;
+
+ /* Restore original pointers of TO. */
+ memcpy (to->glyphs, pointers, sizeof to->glyphs);
+ /* Count how many glyphs to copy and update glyph pointers. */
+ for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+ {
+ if (area > LEFT_MARGIN_AREA)
+ {
+ eassert (from->glyphs[area] - from->glyphs[area - 1]
+ == from->used[area - 1]);
+ to->glyphs[area] = to->glyphs[area - 1] + to->used[area - 1];
+ }
+ sum_used += from->used[area];
+ }
+
+ /* Copy the glyphs. */
+ eassert (sum_used <= to->glyphs[LAST_AREA] - to->glyphs[LEFT_MARGIN_AREA]);
+ for (i = 0; i < sum_used; i++)
+ to->glyphs[LEFT_MARGIN_AREA][i] = from->glyphs[LEFT_MARGIN_AREA][i];
+}
+
+/* Display one menu item on a TTY, by overwriting the glyphs in the
+ desired glyph matrix with glyphs produced from the menu item text.
+ Called from term.c to display TTY drop-down menus one item at a
+ time.
+
+ ITEM_TEXT is the menu item text as a C string.
+
+ FACE_ID is the face ID to be used for this menu item. FACE_ID
+ could specify one of 3 faces: a face for an enabled item, a face
+ for a disabled item, or a face for a selected item.
+
+ X and Y are coordinates of the first glyph in the desired matrix to
+ be overwritten by the menu item. Since this is a TTY, Y is the
+ zero-based number of the glyph row and X is the zero-based glyph
+ number in the row, starting from left, where to start displaying
+ the item.
+
+ SUBMENU non-zero means this menu item drops down a submenu, which
+ should be indicated by displaying a proper visual cue after the
+ item text. */
+
+void
+display_tty_menu_item (const char *item_text, int width, int face_id,
+ int x, int y, int submenu)
+{
+ struct it it;
+ struct frame *f = SELECTED_FRAME ();
+ struct window *w = XWINDOW (f->selected_window);
+ int saved_used, saved_truncated, saved_width, saved_reversed;
+ struct glyph_row *row;
+ size_t item_len = strlen (item_text);
+
+ eassert (FRAME_TERMCAP_P (f));
+
+ init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
+ it.first_visible_x = 0;
+ it.last_visible_x = FRAME_COLS (f) - 1;
+ row = it.glyph_row;
+ /* Start with the row contents from the current matrix. */
+ deep_copy_glyph_row (row, f->current_matrix->rows + y);
+ saved_width = row->full_width_p;
+ row->full_width_p = 1;
+ saved_reversed = row->reversed_p;
+ row->reversed_p = 0;
+ row->enabled_p = 1;
+
+ /* Arrange for the menu item glyphs to start at (X,Y) and have the
+ desired face. */
+ it.current_x = it.hpos = x;
+ it.current_y = it.vpos = y;
+ saved_used = row->used[TEXT_AREA];
+ saved_truncated = row->truncated_on_right_p;
+ row->used[TEXT_AREA] = x;
+ it.face_id = face_id;
+ it.line_wrap = TRUNCATE;
+
+ /* FIXME: This should be controlled by a user option. See the
+ comments in redisplay_tool_bar and display_mode_line about this.
+ Also, if paragraph_embedding could ever be R2L, changes will be
+ needed to avoid shifting to the right the row characters in
+ term.c:append_glyph. */
+ it.paragraph_embedding = L2R;
+
+ /* Pad with a space on the left. */
+ display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
+ width--;
+ /* Display the menu item, pad with spaces to WIDTH. */
+ if (submenu)
+ {
+ display_string (item_text, Qnil, Qnil, 0, 0, &it,
+ item_len, 0, FRAME_COLS (f) - 1, -1);
+ width -= item_len;
+ /* Indicate with " >" that there's a submenu. */
+ display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
+ FRAME_COLS (f) - 1, -1);
+ }
+ else
+ display_string (item_text, Qnil, Qnil, 0, 0, &it,
+ width, 0, FRAME_COLS (f) - 1, -1);
+
+ row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
+ row->truncated_on_right_p = saved_truncated;
+ row->hash = row_hash (row);
+ row->full_width_p = saved_width;
+ row->reversed_p = saved_reversed;
+}
+#endif /* HAVE_MENUS */
\f
/***********************************************************************
Mode Line
#define IT_EXPAND_MATRIX_WIDTH(it, area) \
{ \
- if (!fonts_changed_p \
+ if (!it->f->fonts_changed \
&& (it->glyph_row->glyphs[area] \
< it->glyph_row->glyphs[area + 1])) \
{ \
it->w->ncols_scale_factor++; \
- fonts_changed_p = 1; \
+ it->f->fonts_changed = 1; \
} \
}
base_height = it->ascent + it->descent;
base_width = font->average_width;
- /* Get a face ID for the glyph by utilizing a cache (the same way as
- done for `escape-glyph' in get_next_display_element). */
- if (it->f == last_glyphless_glyph_frame
- && it->face_id == last_glyphless_glyph_face_id)
- {
- face_id = last_glyphless_glyph_merged_face_id;
- }
- else
- {
- /* Merge the `glyphless-char' face into the current face. */
- face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
- last_glyphless_glyph_frame = it->f;
- last_glyphless_glyph_face_id = it->face_id;
- last_glyphless_glyph_merged_face_id = face_id;
- }
+ face_id = merge_glyphless_glyph_face (it);
if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
{
FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
/* Make sure the cursor gets redrawn. */
- cursor_type_changed = 1;
+ f->cursor_type_changed = 1;
}
/* Detect a nonselected window or nonselected frame. */
else if (w != XWINDOW (f->selected_window)
- || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
+ || f != FRAME_DISPLAY_INFO (f)->x_highlight_frame)
{
*active_cursor = 0;
/* Change the mouse cursor. */
if (FRAME_WINDOW_P (f))
{
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
if (draw == DRAW_NORMAL_TEXT
&& !EQ (hlinfo->mouse_face_window, f->tool_bar_window))
FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
- else if (draw == DRAW_MOUSE_FACE)
+ else
+ #endif
+ if (draw == DRAW_MOUSE_FACE)
FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
else
FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
#endif /* not used */
/* Find the positions of the first and the last glyphs in window W's
- current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT
+ current matrix that occlude positions [STARTPOS..ENDPOS) in OBJECT
(assumed to be a string), and return in HLINFO's mouse_face_*
members the pixel and column/row coordinates of those glyphs. */
int found = 0;
/* Find the glyph row with at least one position in the range
- [STARTPOS..ENDPOS], and the first glyph in that row whose
+ [STARTPOS..ENDPOS), and the first glyph in that row whose
position belongs to that range. */
for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
r->enabled_p && r->y < yb;
e = g + r->used[TEXT_AREA];
for (gx = r->x; g < e; gx += g->pixel_width, ++g)
if (EQ (g->object, object)
- && startpos <= g->charpos && g->charpos <= endpos)
+ && startpos <= g->charpos && g->charpos < endpos)
{
hlinfo->mouse_face_beg_row
= MATRIX_ROW_VPOS (r, w->current_matrix);
g = e + r->used[TEXT_AREA];
for ( ; g > e; --g)
if (EQ ((g-1)->object, object)
- && startpos <= (g-1)->charpos && (g-1)->charpos <= endpos)
+ && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
{
hlinfo->mouse_face_beg_row
= MATRIX_ROW_VPOS (r, w->current_matrix);
found = 0;
for ( ; g < e; ++g)
if (EQ (g->object, object)
- && startpos <= g->charpos && g->charpos <= endpos)
+ && startpos <= g->charpos && g->charpos < endpos)
{
found = 1;
break;
e = g + r->used[TEXT_AREA];
for ( ; e > g; --e)
if (EQ ((e-1)->object, object)
- && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos)
+ && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
break;
hlinfo->mouse_face_end_col = e - g;
for (gx = r->x ; e < g; ++e)
{
if (EQ (e->object, object)
- && startpos <= e->charpos && e->charpos <= endpos)
+ && startpos <= e->charpos && e->charpos < endpos)
break;
gx += e->pixel_width;
}
if (VECTORP (XCDR (hot_spot)))
{
struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
- Lisp_Object *poly = v->contents;
+ Lisp_Object *poly = v->u.contents;
ptrdiff_t n = v->header.size;
ptrdiff_t i;
int inside = 0;
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
#ifdef HAVE_X_WINDOWS
else if (EQ (pointer, intern ("vdrag")))
- cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+ cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
#endif
else if (EQ (pointer, intern ("hourglass")))
cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
/* Change the mouse pointer according to what is under it. */
if (FRAME_WINDOW_P (f))
{
- dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
if (STRINGP (string))
{
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
}
else
/* Default mode-line pointer. */
- cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+ cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
}
#endif
}
w = XWINDOW (window);
frame_to_window_pixel_xy (w, &x, &y);
- #ifdef HAVE_WINDOW_SYSTEM
+ #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* Handle tool-bar window differently since it doesn't display a
buffer. */
if (EQ (window, f->tool_bar_window))
if (NILP (s))
s = make_number (0);
if (NILP (e))
- e = make_number (SCHARS (object) - 1);
+ e = make_number (SCHARS (object));
mouse_face_from_string_pos (w, hlinfo, object,
XINT (s), XINT (e));
hlinfo->mouse_face_past_end = 0;
TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
+ #if ! defined (USE_GTK) && ! defined (HAVE_NS)
if (WINDOWP (f->tool_bar_window))
mouse_face_overwritten_p
|= expose_window (XWINDOW (f->tool_bar_window), &r);
+ #endif
#ifdef HAVE_X_WINDOWS
#ifndef MSDOS
void
init_xdisp (void)
{
- current_header_line_height = current_mode_line_height = -1;
-
CHARPOS (this_line_start_pos) = 0;
if (!noninteractive)
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.root = FRAME_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;
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
- memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+ memcpy (previous_items, XVECTOR (f->menu_bar_vector)->u.contents,
previous_menu_items_used * word_size);
/* Fill in menu_items with the current menu bar contents.
{
struct next_popup_x_y *data = user_data;
GtkRequisition req;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (data->f);
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (data->f);
int disp_width = x_display_pixel_width (dpyinfo);
int disp_height = x_display_pixel_height (dpyinfo);
if (for_click)
{
for (i = 0; i < 5; i++)
- if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+ if (FRAME_DISPLAY_INFO (f)->grabbed & (1 << i))
break;
}
/* Must reset this manually because the button release event is not passed
to Emacs event loop. */
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
}
#else /* not USE_GTK */
event->send_event = 0;
event->display = FRAME_X_DISPLAY (f);
event->time = CurrentTime;
- event->root = FRAME_X_DISPLAY_INFO (f)->root_window;
+ event->root = FRAME_DISPLAY_INFO (f)->root_window;
event->window = event->subwindow = event->root;
event->x = x;
event->y = y;
event->state = 0;
event->button = 0;
for (i = 0; i < 5; i++)
- if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+ if (FRAME_DISPLAY_INFO (f)->grabbed & (1 << i))
event->button = i;
/* Don't allow any geometry request from the user. */
make_number (menu_id & ~(-1 << (fact)))));
/* Process events that apply to the menu. */
- popup_get_selection (0, FRAME_X_DISPLAY_INFO (f), menu_id, 1);
+ popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
unbind_to (specpdl_count, Qnil);
}
return Qnil;
}
+ block_input ();
+
/* Create a tree of widget_value objects
representing the panes and their items. */
wv = xmalloc_widget_value ();
if (!NILP (subprefix_stack[j]))
entry = Fcons (subprefix_stack[j], entry);
}
+ unblock_input ();
return entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
}
}
else if (!for_click)
- /* Make "Cancel" equivalent to C-g. */
- Fsignal (Qquit, Qnil);
+ {
+ unblock_input ();
+ /* Make "Cancel" equivalent to C-g. */
+ Fsignal (Qquit, Qnil);
+ }
+ unblock_input ();
return Qnil;
}
\f
Fcons (make_number (dialog_id >> (fact)),
make_number (dialog_id & ~(-1 << (fact)))));
- popup_get_selection (0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
+ popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
unbind_to (count, Qnil);
}
Lisp_Object pane_name;
Lisp_Object menu_object;
- first_item = XVECTOR (menu_items)->contents;
+ 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))
#ifdef HAVE_X_WINDOWS
/* Assume the mouse has moved out of the X window.
If it has actually moved in, we will get an EnterNotify. */
- x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
+ x_mouse_leave (FRAME_DISPLAY_INFO (f));
/* State that no mouse buttons are now held.
(The oldXMenu code doesn't track this info for us.)
That is not necessarily true, but the fiction leads to reasonable
results, and it is a pain to ask which are actually held now. */
- FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
#endif /* HAVE_X_WINDOWS */
return Qnil;
}
+ block_input ();
+
/* Figure out which root window F is on. */
XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
&dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
if (menu == NULL)
{
*error_name = "Can't create menu";
+ unblock_input ();
return Qnil;
}
{
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't create pane";
+ unblock_input ();
return Qnil;
}
i += MENU_ITEMS_PANE_LENGTH;
{
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't add selection to menu";
+ unblock_input ();
return Qnil;
}
i += MENU_ITEMS_ITEM_LENGTH;
/* 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);
+ {
+ unblock_input ();
+ Fsignal (Qquit, Qnil);
+ }
break;
}
+ unblock_input ();
unbind_to (specpdl_count, Qnil);
return entry;