mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-26 07:33:47 +00:00
-
This commit is contained in:
commit
82b089783e
32
configure.ac
32
configure.ac
@ -374,6 +374,9 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' that is usable.])
|
||||
],
|
||||
[with_file_notification=$with_features])
|
||||
|
||||
OPTION_DEFAULT_OFF([xwidgets],
|
||||
[enable use of some gtk widgets in Emacs buffers (requires gtk3)])
|
||||
|
||||
## For the times when you want to build Emacs but don't have
|
||||
## a suitable makeinfo, and can live without the manuals.
|
||||
dnl http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg01844.html
|
||||
@ -2563,6 +2566,26 @@ if test "${HAVE_GTK}" = "yes"; then
|
||||
term_header=gtkutil.h
|
||||
fi
|
||||
|
||||
|
||||
dnl Enable xwidgets if GTK3 and WebKitGTK+ are available.
|
||||
HAVE_XWIDGETS=no
|
||||
XWIDGETS_OBJ=
|
||||
if test "$with_xwidgets" != "no"; then
|
||||
test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none" ||
|
||||
AC_MSG_ERROR([xwidgets requested but gtk3 not used.])
|
||||
|
||||
WEBKIT_REQUIRED=1.4.0
|
||||
WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED"
|
||||
EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
|
||||
HAVE_XWIDGETS=$HAVE_WEBKIT
|
||||
test $HAVE_XWIDGETS = yes ||
|
||||
AC_MSG_ERROR([xwidgets requested but WebKitGTK+ not found.])
|
||||
|
||||
XWIDGETS_OBJ=xwidget.o
|
||||
AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.])
|
||||
fi
|
||||
AC_SUBST(XWIDGETS_OBJ)
|
||||
|
||||
CFLAGS=$OLD_CFLAGS
|
||||
LIBS=$OLD_LIBS
|
||||
|
||||
@ -3123,7 +3146,7 @@ if test "${HAVE_X11}" = "yes"; then
|
||||
if test "${with_cairo}" != "no"; then
|
||||
CAIRO_REQUIRED=1.12.0
|
||||
CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
|
||||
PKG_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
|
||||
EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
|
||||
if test $USE_CAIRO = yes; then
|
||||
AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
|
||||
else
|
||||
@ -4948,6 +4971,9 @@ case "$USE_X_TOOLKIT" in
|
||||
LUCID) TOOLKIT_LIBW="$LUCID_LIBW" ;;
|
||||
none) test "x$HAVE_GTK" = "xyes" && TOOLKIT_LIBW="$GTK_LIBS" ;;
|
||||
esac
|
||||
if test "$HAVE_XWIDGETS" = "yes"; then
|
||||
TOOLKIT_LIBW="$TOOLKIT_LIBW -lXcomposite"
|
||||
fi
|
||||
AC_SUBST(TOOLKIT_LIBW)
|
||||
|
||||
if test "${opsys}" != "mingw32"; then
|
||||
@ -5237,7 +5263,8 @@ optsep=
|
||||
emacs_config_features=
|
||||
for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \
|
||||
GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \
|
||||
LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES; do
|
||||
LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \
|
||||
XWIDGETS; do
|
||||
|
||||
case $opt in
|
||||
NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;;
|
||||
@ -5287,6 +5314,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
|
||||
Does Emacs directly use zlib? ${HAVE_ZLIB}
|
||||
Does Emacs have dynamic modules support? ${HAVE_MODULES}
|
||||
Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}
|
||||
Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS}
|
||||
"])
|
||||
|
||||
if test -n "${EMACSDATA}"; then
|
||||
|
@ -1,113 +1,218 @@
|
||||
@c -*- coding: utf-8 -*-
|
||||
@c This is part of the Emacs manual.
|
||||
@c Copyright (C) 2005-2016 Free Software Foundation, Inc.
|
||||
@c See file emacs.texi for copying conditions.
|
||||
|
||||
@node Antinews
|
||||
@appendix Emacs 23 Antinews
|
||||
@appendix Emacs 24 Antinews
|
||||
@c Update the emacs.texi Antinews menu entry with the above version number.
|
||||
|
||||
For those users who live backwards in time, here is information
|
||||
about downgrading to Emacs version 23.4. We hope you will enjoy the
|
||||
about downgrading to Emacs version 24.5. We hope you will enjoy the
|
||||
greater simplicity that results from the absence of many Emacs
|
||||
@value{EMACSVER} features.
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Support for displaying and editing ``bidirectional'' text has been
|
||||
removed. Text is now always displayed on the screen in a single
|
||||
consistent direction---left to right---regardless of the underlying
|
||||
script. Similarly, @kbd{C-f} and @kbd{C-b} always move the text
|
||||
cursor to the right and left respectively. Also, @key{RIGHT} and
|
||||
@key{LEFT} are now equivalent to @kbd{C-f} and @kbd{C-b}, as you might
|
||||
expect, rather than moving forward or backward based on the underlying
|
||||
``paragraph direction''.
|
||||
|
||||
Users of right-to-left languages, like Arabic and Hebrew, may
|
||||
adapt by reading and/or editing text in left-to-right order.
|
||||
Support for Cairo drawing has been removed. On GNU and Unix systems,
|
||||
you now have only one drawing engine---the venerable X Window system.
|
||||
No need to procrastinate on the dilemma whether you do or don't want
|
||||
the new shiny Cairo thing. Hail, simplicity!
|
||||
|
||||
@item
|
||||
The Emacs Lisp package manager has been removed. Instead of using a
|
||||
user interface (@kbd{M-x list-packages}), additional Lisp packages
|
||||
must now be installed by hand, which is the most flexible and
|
||||
``Lispy'' method anyway. Typically, this just involves editing your
|
||||
init file to add the package installation directory to the load path
|
||||
and defining some autoloads; see each package's commentary section
|
||||
and/or README file for details.
|
||||
Emacs still works on SGI IRIX systems. if you live backwards in time,
|
||||
this is actually a bonus, as IRIX systems will become more and more
|
||||
popular as you move farther back in time.
|
||||
|
||||
@item
|
||||
The option @code{delete-active-region} has been deleted. When the
|
||||
region is active, typing @key{DEL} or @key{Delete} no longer deletes
|
||||
the text in the region; it deletes a single character instead.
|
||||
Support for dynamically loaded modules has been removed. You get to
|
||||
use only the trusted Emacs codebase, with no additions. Those
|
||||
external modules written by some J.R. Hacker cannot be trusted anyway.
|
||||
Good riddance!
|
||||
|
||||
@item
|
||||
We have reworked how Emacs handles the clipboard and the X primary
|
||||
selection. Commands for killing and yanking, like @kbd{C-w} and
|
||||
@kbd{C-y}, use the primary selection and not the clipboard, so you can
|
||||
use these commands without interfering with ``cutting'' or ``pasting''
|
||||
in other programs. The @samp{Cut}/@samp{Copy}/@samp{Paste} menu items
|
||||
are bound to separate clipboard commands, not to the same commands as
|
||||
@kbd{C-w}/@kbd{M-w}/@kbd{C-y}.
|
||||
|
||||
Selecting text by dragging with the mouse now puts the text in the
|
||||
kill ring, in addition to the primary selection. But note that
|
||||
selecting an active region with @kbd{C-@key{SPC}} does @emph{not}
|
||||
alter the kill ring nor the primary selection, even though the text
|
||||
highlighting is visually identical.
|
||||
We have greatly simplified the Emacs features which access the network
|
||||
by removing the Network Security Manager. No more annoying prompts
|
||||
about trusting this or that site or page---you asked for it, you get
|
||||
it, no questions asked! You, the user, are now in charge of any
|
||||
security issues related to sites whose certificates expired or didn't
|
||||
exist in the first place. Giving the user the utmost freedom was and
|
||||
always will be the most important goal of Emacs development. We keep
|
||||
that goal even as we develop Emacs back in time.
|
||||
|
||||
@item
|
||||
In Isearch, @kbd{C-y} and @kbd{M-y} are no longer bound to
|
||||
@code{isearch-yank-kill} and @code{isearch-yank-pop} respectively.
|
||||
Instead, @kbd{C-y} yanks the rest of the current line into the search
|
||||
string (@code{isearch-yank-line}), whereas @kbd{M-y} does
|
||||
@code{isearch-yank-kill}. The mismatch with the usual meanings of
|
||||
@kbd{C-y} and @kbd{M-y} is unintended.
|
||||
We made the output of @kbd{C-h l} much simpler and easier to grasp by
|
||||
removing the names of commands run by the recorded keystrokes. True
|
||||
Emacs lovers know their bindings by heart anyway, so why waste
|
||||
precious screen estate on that which is well known?
|
||||
|
||||
@item
|
||||
Various completion features have been simplified. The option
|
||||
@code{completion-category-overrides} has been removed, so Emacs uses a
|
||||
single consistent scheme to generate completions, instead of using a
|
||||
separate scheme for (say) buffer name completion. Several major
|
||||
modes, such as Shell mode, now implement their own inline completion
|
||||
commands instead of using @code{completion-at-point}.
|
||||
Selection- and clipboard-related commands and variables got their
|
||||
historical names back. It's now the definitive
|
||||
@code{x-select-enable-clipboard} again instead of the vague
|
||||
@code{select-enable-clipboard}, and all those @code{gui-select-text},
|
||||
@code{gui-get-primary-selection}, etc.@: got their @code{x-*} names
|
||||
back. (What's a ``GUI'', anyway?) The only true window system with
|
||||
selections is the X Window system, so we stopped pretending that other
|
||||
platforms have anything similar to that. You now know when you invoke
|
||||
a command that accesses X.
|
||||
|
||||
@item
|
||||
We have removed several options for controlling how windows are used,
|
||||
such as @code{display-buffer-base-action},
|
||||
@code{display-buffer-alist}, @code{window-combination-limit}, and
|
||||
@code{window-combination-resize}.
|
||||
Passwords are no longer hidden when typed in @code{-batch} mode. It
|
||||
was a misfeature to have it not shown in the first place: who can type
|
||||
without seeing what they type? We couldn't convince the users of GUI
|
||||
sessions to give up hiding the password, so we at least made it
|
||||
visible in batch mode, which is something every veteran Emacs user
|
||||
uses all the time. Stay tuned for un-hiding the password in GUI
|
||||
sessions as well as we downgrade progressively to previous Emacs
|
||||
versions.
|
||||
|
||||
@item
|
||||
The command @kbd{M-x customize-themes} has been removed. Emacs no
|
||||
longer comes with pre-defined themes (you can write your own).
|
||||
The nuisance with Unicode characters popping up all over the place has
|
||||
been amply dealt with. We've removed @kbd{C-x 8} shorthands for
|
||||
characters such as ‘, ’, “, ”, €, ≤, and many others; as a nice
|
||||
benefit, this removes many useless entries at the beginning of the
|
||||
@kbd{C-h b} output. The @code{electric-quote-mode} has been deleted,
|
||||
so there's only the one true quoting method now---using the
|
||||
plain-@acronym{ASCII} quote characters. And if that's not enough, the
|
||||
doc strings and other messages show text quoted `like this' and "like
|
||||
this" as they were written, instead of arbitrarily replacing them
|
||||
with Unicode ``curved quote'' characters. The
|
||||
@code{text-quoting-style} variable becomes therefore unneeded and was
|
||||
removed. As result, text produced by Emacs can be sent to those
|
||||
venerable teletypes again, yeah!
|
||||
|
||||
For the same reasons, the character classes @code{[:alpha:]} and
|
||||
@code{[:alnum:]} again match any word-constituent character, and
|
||||
@code{[:graph:]} and @code{[:print:]} match every multibyte character.
|
||||
Confusing use of Unicode character properties is gone.
|
||||
|
||||
@item
|
||||
Emacs no longer adapts various aspects of its display to GTK+
|
||||
settings, opting instead for a uniform toolkit-independent look. GTK+
|
||||
scroll bars are placed on the left, the same position as non-GTK+ X
|
||||
scroll bars. Emacs no longer refers to GTK+ to set the default
|
||||
@code{region} face, nor for drawing tooltips.
|
||||
I-search and query-replace no longer try to confuse you by using the
|
||||
``character-folding'' magic. They will no longer find any characters
|
||||
you didn't actually type, like find @kbd{ⓐ} when you actually typed
|
||||
@kbd{a}. Users who want to find some fancy character will have to
|
||||
type it explicitly.
|
||||
|
||||
@item
|
||||
Setting the option @code{delete-by-moving-to-trash} to a
|
||||
non-@code{nil} value now causes all file deletions to use the system trash,
|
||||
even temporary files created by Lisp programs; furthermore, the
|
||||
@kbd{M-x delete-file} and @kbd{M-x delete-directory} commands no
|
||||
longer accept prefix arguments to force true deletion.
|
||||
The @file{desktop.el} package no longer records window and frame
|
||||
configuration, and doesn't attempt to restore them. You now have back
|
||||
your freedom of re-arranging your windows and frames anew each time
|
||||
you restore a session. This made the new backward-incompatible format
|
||||
of the @file{.emacs.desktop} file unnecessary, so the format was
|
||||
reverted back to what it was before Emacs 25. You can now again use
|
||||
the desktop file with all the previous versions of Emacs.
|
||||
|
||||
@item
|
||||
On GNU/Linux and Unix, the default method for sending mail (as
|
||||
specified by @code{send-mail-function}) is to use the
|
||||
@command{sendmail} program. Emacs no longer asks for a delivery
|
||||
method the first time you try to send mail, trusting instead that the
|
||||
system is configured for mail delivery, as it ought to be.
|
||||
We have reworked the Prettify Symbols mode to support only the default
|
||||
@code{prettify-symbols-compose-predicate}. No need to consider
|
||||
whether your major or minor mode needs its own prettifications; just
|
||||
use what came with Emacs. We also removed the
|
||||
@code{prettify-symbols-unprettify-at-point} option: once prettified,
|
||||
always prettified! These changes make the Prettify Symbols mode quite
|
||||
a lot simpler and easier to use.
|
||||
|
||||
@item
|
||||
Several VC features have been removed, including the @kbd{C-x v +} and
|
||||
@kbd{C-x v m} commands for pulling and merging on distributed version
|
||||
control systems, and the ability to view inline log entries in the log
|
||||
buffers made by @kbd{C-x v L}.
|
||||
Support for nifty new features of xterm, such as access to the X
|
||||
selection and the clipboard, the ``bracketed paste mode'', and other
|
||||
advanced capabilities has been removed. When you kill text in an
|
||||
xterm Emacs session, that text is only saved in the Emacs kill ring,
|
||||
without letting other applications have any way of accessing it. An
|
||||
xterm is just a text terminal, nothing more, nothing less. There
|
||||
should be no feature we support on xterm that isn't supported on bare
|
||||
console terminals. For the same reasons, support for mouse-tracking
|
||||
on xterm was removed. We will continue this line of simplifications
|
||||
as we downgrade to previous versions of Emacs; stay tuned.
|
||||
|
||||
@item
|
||||
Various features in @file{package.el} have been simplified. The
|
||||
``external'' package status is no longer available. A package present
|
||||
on multiple archives will now be listed as many times as it is found:
|
||||
we don't believe in concealing any information from the users. This
|
||||
and other similar simplifications made
|
||||
@code{package-menu-toggle-hiding} unnecessary, since there's nothing
|
||||
to unhide now.
|
||||
|
||||
@item
|
||||
The @kbd{@key{UP}} and @kbd{@key{DOWN}} keys in the minibuffer have
|
||||
been simplified to move by history items. No need to wonder whether
|
||||
you have moved to the next/previous item or to another line within the
|
||||
same item. Well-written commands shouldn't allow too long history
|
||||
entries anyway; be sure to report any that do as bugs, so that we
|
||||
could fix them in past versions of Emacs.
|
||||
|
||||
@item
|
||||
The VC mode was simplified by removing the support for ``push''
|
||||
commands. Moving back in time means you will have less and less need
|
||||
to use modern version control systems such as Git, Bazaar, and
|
||||
Mercurial, so the necessity of using ``push'' commands will gradually
|
||||
disappear. We removed it from Emacs in advance, so that you won't
|
||||
need to un-learn it when this command disappears, as it should.
|
||||
|
||||
@item
|
||||
The support for full C/C++ expressions in macros has been removed from
|
||||
Hide-Ifdef mode. It now supports only the basic literal macros. As
|
||||
result, the user interface was simplified, and a number of useless
|
||||
commands have been removed from Hide-Ifdef mode. Further
|
||||
simplifications were made possible by removing support for some fancy
|
||||
new preprocessor directives, such as @code{#if defined}, @code{#elif},
|
||||
etc.
|
||||
|
||||
@item
|
||||
We have reverted to Etags for looking up definitions of functions,
|
||||
variables, etc. Commands such as @kbd{M-.} use tags tables, as they
|
||||
always have. This allowed the removal of the entire @file{xref.el}
|
||||
package and its many metastases in the other Emacs packages and
|
||||
commands, significantly simplifying those. No more complexities with
|
||||
the various ``backends'' that provide incoherent behavior that is hard
|
||||
to explain and remember; either the symbol is in TAGS or it isn't. No
|
||||
more new user interfaces we never before saw in Emacs, either; if you
|
||||
want the next definition for the symbol you typed, just invoke
|
||||
@kbd{C-u M-.}---what could be simpler? As a nice side effect, you get
|
||||
to use your beloved @code{tags-loop-continue} and @code{pop-tag-mark}
|
||||
commands and their memorable bindings. The @file{package.el} package
|
||||
has been removed for similar reasons.
|
||||
|
||||
@item
|
||||
@code{(/ @var{n})} once again yields just @var{n}. Emacs Lisp is not
|
||||
Common Lisp, so compatibility with CL just complicates Emacs here.
|
||||
|
||||
@item
|
||||
The functions @code{filepos-to-bufferpos} and
|
||||
@code{bufferpos-to-filepos} have been removed. Code that needs to
|
||||
find a file position by a buffer position or vice versa should adapt
|
||||
by reading the file with no conversions and counting bytes while
|
||||
comparing text. How hard can that be?
|
||||
|
||||
@item
|
||||
We saw no need for the @code{make-process} primitive, so we removed
|
||||
it. The @code{start-process} primitive provides all the functionality
|
||||
one needs, so adding more APIs just confuses users.
|
||||
|
||||
@item
|
||||
The functions @code{bidi-find-overridden-directionality} and
|
||||
@code{buffer-substring-with-bidi-context} were removed, in preparation
|
||||
for removing the whole bidi support when downgrading to Emacs 23.
|
||||
|
||||
@item
|
||||
Horizontal scroll bars are no longer supported. Enlarge your windows
|
||||
and frames instead, or use @code{truncate-lines} and the automatic
|
||||
horizontal scrolling of text that Emacs had since time immemoriam.
|
||||
|
||||
@item
|
||||
Emacs is again counting the height of a frame's menu and its tool bar
|
||||
in the frame's text height calculations. This makes Emacs invocation
|
||||
on different platforms and with different toolkits less predictable
|
||||
when frame geometry parameters are given on the Emacs command line,
|
||||
thus making Emacs more adventurous and less boring to use.
|
||||
|
||||
@item
|
||||
The @command{etags} program no longer supports Ruby and Go languages.
|
||||
You won't need that as you progressively travel back in time towards
|
||||
the time before these languages were invented. We removed support for
|
||||
them in anticipation for that time.
|
||||
|
||||
@item
|
||||
To keep up with decreasing computer memory capacity and disk space, many
|
||||
other functions and files have been eliminated in Emacs 23.4.
|
||||
other functions and files have been eliminated in Emacs 24.5.
|
||||
@end itemize
|
||||
|
@ -221,7 +221,7 @@ Appendices
|
||||
* GNU Free Documentation License:: The license for this documentation.
|
||||
* Emacs Invocation:: Hairy startup options.
|
||||
* X Resources:: X resources for customizing Emacs.
|
||||
* Antinews:: Information about Emacs version 23.
|
||||
* Antinews:: Information about Emacs version 24.
|
||||
* Mac OS / GNUstep:: Using Emacs under Mac OS and GNUstep.
|
||||
* Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS.
|
||||
* Manifesto:: What's GNU? Gnu's Not Unix!
|
||||
|
@ -1990,8 +1990,8 @@ Searching}.
|
||||
@table @kbd
|
||||
@item C-M-i
|
||||
@itemx M-@key{TAB}
|
||||
Perform completion on the text around point, using the selected tags
|
||||
table if one is loaded (@code{completion-at-point}).
|
||||
Perform completion on the text around point, possibly using the
|
||||
selected tags table if one is loaded (@code{completion-at-point}).
|
||||
@item M-x xref-find-apropos @key{RET} @var{regexp} @key{RET}
|
||||
Display a list of all known identifiers matching @var{regexp}.
|
||||
@item M-x list-tags @key{RET} @var{file} @key{RET}
|
||||
@ -2004,9 +2004,10 @@ Visit files recorded in the selected tags table.
|
||||
@cindex completion (symbol names)
|
||||
In most programming language modes, you can type @kbd{C-M-i} or
|
||||
@kbd{M-@key{TAB}} (@code{completion-at-point}) to complete the symbol
|
||||
at point. If there is a tags table loaded, this command can use it to
|
||||
generate completion candidates more intelligently. @xref{Symbol
|
||||
Completion}.
|
||||
at point. Some modes provide specialized completion for this command
|
||||
tailored to the mode; for those that don't, if there is a tags table
|
||||
loaded, this command can use it to generate completion candidates.
|
||||
@xref{Symbol Completion}.
|
||||
|
||||
@findex list-tags
|
||||
@kbd{M-x list-tags} reads the name of one of the files covered by
|
||||
@ -2047,17 +2048,17 @@ file. This command requires a tags table to be selected.
|
||||
@subsection Tags Tables
|
||||
@cindex tags and tag tables
|
||||
|
||||
@cindex tag
|
||||
A @dfn{tag} is a synonym for identifier reference. @xref{Xref}.
|
||||
|
||||
A @dfn{tags table} records the tags extracted by scanning the source
|
||||
code of a certain program or a certain document. Tags extracted from
|
||||
generated files reference the original files, rather than the
|
||||
generated files that were scanned during tag extraction. Examples of
|
||||
generated files include C files generated from Cweb source files, from
|
||||
a Yacc parser, or from Lex scanner definitions; @file{.i} preprocessed
|
||||
C files; and Fortran files produced by preprocessing @file{.fpp}
|
||||
source files.
|
||||
A @dfn{tags table} records the tags@footnote{
|
||||
A @dfn{tag} is a synonym for identifier reference. Commands and
|
||||
features based on the @code{etags} package traditionally use ``tag''
|
||||
with this meaning, and this subsection follows that tradition.
|
||||
} extracted by scanning the source code of a certain program or a
|
||||
certain document. Tags extracted from generated files reference the
|
||||
original files, rather than the generated files that were scanned
|
||||
during tag extraction. Examples of generated files include C files
|
||||
generated from Cweb source files, from a Yacc parser, or from Lex
|
||||
scanner definitions; @file{.i} preprocessed C files; and Fortran files
|
||||
produced by preprocessing @file{.fpp} source files.
|
||||
|
||||
@cindex etags
|
||||
To produce a tags table, you run the @command{etags} shell command
|
||||
|
@ -2068,7 +2068,7 @@ cdar nthcdr
|
||||
A call to any of the following Emacs-specific functions:
|
||||
|
||||
@smallexample
|
||||
default-value process-get
|
||||
alist-get process-get
|
||||
frame-parameter process-sentinel
|
||||
terminal-parameter window-buffer
|
||||
keymap-parent window-display-table
|
||||
@ -2077,7 +2077,7 @@ overlay-get window-hscroll
|
||||
overlay-start window-parameter
|
||||
overlay-end window-point
|
||||
process-buffer window-start
|
||||
process-filter
|
||||
process-filter default-value
|
||||
@end smallexample
|
||||
@end itemize
|
||||
|
||||
|
15
etc/NEWS
15
etc/NEWS
@ -179,6 +179,20 @@ and can contain escape sequences for command keys, quotes, and the like.
|
||||
|
||||
* Changes in Emacs 25.1
|
||||
|
||||
** Xwidgets: a new feature for embedding native widgets inside Emacs buffers.
|
||||
If you have gtk3 and webkitgtk3 installed, you can access the
|
||||
embedded webkit browser with `M-x xwidget-webkit-browse-url'. This
|
||||
opens a new buffer with the embedded browser. The buffer will
|
||||
have a new mode, `xwidget-webkit-mode' (similar to `image-mode'),
|
||||
which supports the webkit widget.
|
||||
|
||||
*** New functions for xwidget-webkit mode `xwidget-webkit-insert-string',
|
||||
`xwidget-webkit-adjust-size-dispatch', `xwidget-webkit-back',
|
||||
`xwidget-webkit-browse-url', `xwidget-webkit-reload',
|
||||
`xwidget-webkit-current-url', `xwidget-webkit-scroll-backward',
|
||||
`xwidget-webkit-scroll-forward', `xwidget-webkit-scroll-down',
|
||||
`xwidget-webkit-scroll-up'.
|
||||
|
||||
+++
|
||||
** Emacs can now load shared/dynamic libraries (modules).
|
||||
A dynamic Emacs module is a shared library that provides additional
|
||||
@ -1596,6 +1610,7 @@ permissions set to temporary values (e.g., for creating private files).
|
||||
+++
|
||||
** Function `sort' can deal with vectors.
|
||||
|
||||
---
|
||||
** Function `system-name' now returns an updated value if the current
|
||||
system's name has changed or if the Emacs process has changed systems,
|
||||
and to avoid long waits it no longer consults DNS to canonicalize the
|
||||
|
@ -4654,13 +4654,15 @@ name in `todo-directory'. See also the documentation string of
|
||||
(goto-char (match-beginning 0))
|
||||
(goto-char (point-max)))
|
||||
(backward-char)
|
||||
(when (looking-back "\\[\\([^][]+\\)\\]")
|
||||
(when (looking-back "\\[\\([^][]+\\)\\]"
|
||||
(line-beginning-position))
|
||||
(setq cat (match-string 1))
|
||||
(goto-char (match-beginning 0))
|
||||
(replace-match ""))
|
||||
;; If the item ends with a non-comment parenthesis not
|
||||
;; followed by a period, we lose (but we inherit that
|
||||
;; problem from the legacy code).
|
||||
;; FIXME: fails on multiline comment
|
||||
(when (looking-back "(\\(.*\\)) " (line-beginning-position))
|
||||
(setq comment (match-string 1))
|
||||
(replace-match "")
|
||||
@ -5230,7 +5232,8 @@ Also preserve category display, if applicable."
|
||||
(with-current-buffer buffer
|
||||
(widen)
|
||||
(let ((todo-category-number (cdr (assq 'catnum misc))))
|
||||
(todo-category-select))))
|
||||
(todo-category-select)
|
||||
(current-buffer))))
|
||||
|
||||
(add-to-list 'desktop-buffer-mode-handlers
|
||||
'(todo-mode . todo-restore-desktop-buffer))
|
||||
@ -6579,8 +6582,7 @@ Added to `window-configuration-change-hook' in Todo mode."
|
||||
"Make some settings that apply to multiple Todo modes."
|
||||
(add-to-invisibility-spec 'todo)
|
||||
(setq buffer-read-only t)
|
||||
(when (and (boundp 'desktop-save-mode) desktop-save-mode)
|
||||
(setq-local desktop-save-buffer 'todo-desktop-save-buffer))
|
||||
(setq-local desktop-save-buffer 'todo-desktop-save-buffer)
|
||||
(when (boundp 'hl-line-range-function)
|
||||
(setq-local hl-line-range-function
|
||||
(lambda() (save-excursion
|
||||
|
@ -1714,7 +1714,8 @@ If BACKWARD is non-nil, jump to the previous match."
|
||||
;; window-parameters in the window-state(s) and then restoring this
|
||||
;; window-state should call us back (to interpret/use those parameters).
|
||||
(doc-view-goto-page page)
|
||||
(when slice (apply 'doc-view-set-slice slice)))))
|
||||
(when slice (apply 'doc-view-set-slice slice))
|
||||
(current-buffer))))
|
||||
|
||||
(add-to-list 'desktop-buffer-mode-handlers
|
||||
'(doc-view-mode . doc-view-restore-desktop-buffer))
|
||||
@ -1788,9 +1789,7 @@ toggle between displaying the document or editing it as text.
|
||||
nil t)
|
||||
(add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t)
|
||||
(add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t)
|
||||
(when (and (boundp 'desktop-save-mode)
|
||||
desktop-save-mode)
|
||||
(setq-local desktop-save-buffer 'doc-view-desktop-save-buffer))
|
||||
(setq-local desktop-save-buffer 'doc-view-desktop-save-buffer)
|
||||
|
||||
(remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case.
|
||||
;; Keep track of display info ([vh]scroll, page number, overlay,
|
||||
|
@ -107,12 +107,36 @@
|
||||
|
||||
;;;###autoload
|
||||
(defmacro pcase (exp &rest cases)
|
||||
"Eval EXP and perform ML-style pattern matching on that value.
|
||||
"Evaluate EXP and attempt to match it against structural patterns.
|
||||
CASES is a list of elements of the form (PATTERN CODE...).
|
||||
|
||||
Patterns can take the following forms:
|
||||
A structural PATTERN describes a template that identifies a class
|
||||
of values. For example, the pattern `(,foo ,bar) matches any
|
||||
two element list, binding its elements to symbols named `foo' and
|
||||
`bar' -- in much the same way that `cl-destructuring-bind' would.
|
||||
|
||||
A significant difference from `cl-destructuring-bind' is that, if
|
||||
a pattern match fails, the next case is tried until either a
|
||||
succesful match is found or there are no more cases.
|
||||
|
||||
Another difference is that pattern elements may be backquoted,
|
||||
meaning they must match exactly: The pattern \\='(foo bar)
|
||||
matches only against two element lists containing the symbols
|
||||
`foo' and `bar' in that order. (As a short-hand, atoms always
|
||||
match themselves, such as numbers or strings, and need not be
|
||||
quoted).
|
||||
|
||||
Lastly, a pattern can be logical, such as (pred numberp), that
|
||||
matches any number-like element; or the symbol `_', that matches
|
||||
anything. Also, when patterns are backquoted, a comma may be
|
||||
used to introduce logical patterns inside backquoted patterns.
|
||||
|
||||
The complete list of standard patterns is as follows:
|
||||
|
||||
_ matches anything.
|
||||
SYMBOL matches anything and binds it to SYMBOL.
|
||||
If a SYMBOL is used twice in the same pattern
|
||||
the second occurrence becomes an `eq'uality test.
|
||||
(or PAT...) matches if any of the patterns matches.
|
||||
(and PAT...) matches if all the patterns match.
|
||||
\\='VAL matches if the object is `equal' to VAL.
|
||||
@ -122,23 +146,18 @@ Patterns can take the following forms:
|
||||
(guard BOOLEXP) matches if BOOLEXP evaluates to non-nil.
|
||||
(let PAT EXP) matches if EXP matches PAT.
|
||||
(app FUN PAT) matches if FUN applied to the object matches PAT.
|
||||
If a SYMBOL is used twice in the same pattern (i.e. the pattern is
|
||||
\"non-linear\"), then the second occurrence is turned into an `eq'uality test.
|
||||
|
||||
FUN can take the form
|
||||
Additional patterns can be defined using `pcase-defmacro'.
|
||||
|
||||
The FUN argument in the `app' pattern may have the following forms:
|
||||
SYMBOL or (lambda ARGS BODY) in which case it's called with one argument.
|
||||
(F ARG1 .. ARGn) in which case F gets called with an n+1'th argument
|
||||
which is the value being matched.
|
||||
So a FUN of the form SYMBOL is equivalent to one of the form (FUN).
|
||||
So a FUN of the form SYMBOL is equivalent to (FUN).
|
||||
FUN can refer to variables bound earlier in the pattern.
|
||||
E.g. you can match pairs where the cdr is larger than the car with a pattern
|
||||
like \\=`(,a . ,(pred (< a))) or, with more checks:
|
||||
\\=`(,(and a (pred numberp)) . ,(and (pred numberp) (pred (< a))))
|
||||
FUN is assumed to be pure, i.e. it can be dropped if its result is not used,
|
||||
and two identical calls can be merged into one.
|
||||
|
||||
Additional patterns can be defined via `pcase-defmacro'.
|
||||
Currently, the following patterns are provided this way:"
|
||||
See Info node `(elisp) Pattern matching case statement' in the
|
||||
Emacs Lisp manual for more information and examples."
|
||||
(declare (indent 1) (debug (form &rest (pcase-PAT body))))
|
||||
;; We want to use a weak hash table as a cache, but the key will unavoidably
|
||||
;; be based on `exp' and `cases', yet `cases' is a fresh new list each time
|
||||
|
@ -822,8 +822,10 @@ skips all prompting."
|
||||
(deffoo nnir-request-update-mark (group article mark)
|
||||
(let ((artgroup (nnir-article-group article))
|
||||
(artnumber (nnir-article-number article)))
|
||||
(when (and artgroup artnumber)
|
||||
(gnus-request-update-mark artgroup artnumber mark))))
|
||||
(or (and artgroup
|
||||
artnumber
|
||||
(gnus-request-update-mark artgroup artnumber mark))
|
||||
mark)))
|
||||
|
||||
(deffoo nnir-request-set-mark (group actions &optional server)
|
||||
(nnir-possibly-change-group group server)
|
||||
|
@ -1001,7 +1001,7 @@ merged by the user - `hfy-flatten-style' should do this."
|
||||
(append
|
||||
parent
|
||||
(hfy-face-to-style-i
|
||||
(hfy-face-attr-for-class v hfy-display-class)) ))))
|
||||
(hfy-face-attr-for-class v hfy-display-class))))))
|
||||
(setq this
|
||||
(if val (case key
|
||||
(:family (hfy-family val))
|
||||
@ -1020,7 +1020,7 @@ merged by the user - `hfy-flatten-style' should do this."
|
||||
(:italic (hfy-slant 'italic))))))
|
||||
(setq that (hfy-face-to-style-i next))
|
||||
;;(lwarn t :warning "%S => %S" fn (nconc this that parent))
|
||||
(nconc this that parent))) )
|
||||
(nconc this parent that))) )
|
||||
|
||||
(defun hfy-size-to-int (spec)
|
||||
"Convert SPEC, a CSS font-size specifier, to an Emacs :height attribute value.
|
||||
@ -1058,13 +1058,19 @@ haven't encountered them yet. Returns a `hfy-style-assoc'."
|
||||
(nconc r (hfy-size (if x (round n) (* n 1.0)))) ))
|
||||
|
||||
(defun hfy-face-resolve-face (fn)
|
||||
"For FN return a face specification.
|
||||
FN may be either a face or a face specification. If the latter,
|
||||
then the specification is returned unchanged."
|
||||
(cond
|
||||
((facep fn)
|
||||
(hfy-face-attr-for-class fn hfy-display-class))
|
||||
;; FIXME: is this necessary? Faces can be symbols, but
|
||||
;; not symbols refering to other symbols?
|
||||
((and (symbolp fn)
|
||||
(facep (symbol-value fn)))
|
||||
(hfy-face-attr-for-class (symbol-value fn) hfy-display-class))
|
||||
(t nil)))
|
||||
(hfy-face-attr-for-class
|
||||
(symbol-value fn) hfy-display-class))
|
||||
(t fn)))
|
||||
|
||||
|
||||
(defun hfy-face-to-style (fn)
|
||||
|
@ -153,6 +153,8 @@ otherwise it defaults to t, used for times when the buffer is not displayed."
|
||||
(selected-window))))
|
||||
|
||||
(declare-function image-size "image.c" (spec &optional pixels frame))
|
||||
(declare-function xwidget-info "xwidget.c" (xwidget))
|
||||
(declare-function xwidget-at "xwidget.el" (pos))
|
||||
|
||||
(defun image-display-size (spec &optional pixels frame)
|
||||
"Wrapper around `image-size', handling slice display properties.
|
||||
@ -160,24 +162,29 @@ Like `image-size', the return value is (WIDTH . HEIGHT).
|
||||
WIDTH and HEIGHT are in canonical character units if PIXELS is
|
||||
nil, and in pixel units if PIXELS is non-nil.
|
||||
|
||||
If SPEC is an image display property, this function is equivalent
|
||||
to `image-size'. If SPEC is a list of properties containing
|
||||
`image' and `slice' properties, return the display size taking
|
||||
the slice property into account. If the list contains `image'
|
||||
but not `slice', return the `image-size' of the specified image."
|
||||
(if (eq (car spec) 'image)
|
||||
(image-size spec pixels frame)
|
||||
(let ((image (assoc 'image spec))
|
||||
(slice (assoc 'slice spec)))
|
||||
(cond ((and image slice)
|
||||
(if pixels
|
||||
(cons (nth 3 slice) (nth 4 slice))
|
||||
(cons (/ (float (nth 3 slice)) (frame-char-width frame))
|
||||
(/ (float (nth 4 slice)) (frame-char-height frame)))))
|
||||
(image
|
||||
(image-size image pixels frame))
|
||||
(t
|
||||
(error "Invalid image specification: %s" spec))))))
|
||||
If SPEC is an image display property, this function is equivalent to
|
||||
`image-size'. If SPEC represents an xwidget object, defer to `xwidget-info'.
|
||||
If SPEC is a list of properties containing `image' and `slice' properties,
|
||||
return the display size taking the slice property into account. If the list
|
||||
contains `image' but not `slice', return the `image-size' of the specified
|
||||
image."
|
||||
(cond ((eq (car spec) 'xwidget)
|
||||
(let ((xwi (xwidget-info (xwidget-at (point-min)))))
|
||||
(cons (aref xwi 2) (aref xwi 3))))
|
||||
((eq (car spec) 'image)
|
||||
(image-size spec pixels frame))
|
||||
(t (let ((image (assoc 'image spec))
|
||||
(slice (assoc 'slice spec)))
|
||||
(cond ((and image slice)
|
||||
(if pixels
|
||||
(cons (nth 3 slice) (nth 4 slice))
|
||||
(cons (/ (float (nth 3 slice)) (frame-char-width frame))
|
||||
(/ (float (nth 4 slice))
|
||||
(frame-char-height frame)))))
|
||||
(image
|
||||
(image-size image pixels frame))
|
||||
(t
|
||||
(error "Invalid image specification: %s" spec)))))))
|
||||
|
||||
(defun image-forward-hscroll (&optional n)
|
||||
"Scroll image in current window to the left by N character widths.
|
||||
|
@ -2119,7 +2119,7 @@ See `set-language-info-alist' for use in programs."
|
||||
(with-current-buffer standard-output
|
||||
(insert language-name " language environment\n\n")
|
||||
(if (stringp doc)
|
||||
(insert doc "\n\n"))
|
||||
(insert (substitute-command-keys doc) "\n\n"))
|
||||
(condition-case nil
|
||||
(let ((str (eval (get-language-info language-name 'sample-text))))
|
||||
(if (stringp str)
|
||||
|
@ -2516,7 +2516,7 @@ package to describe."
|
||||
")\n\n")
|
||||
(save-restriction
|
||||
(narrow-to-region (point) (point))
|
||||
(insert (quail-docstring))
|
||||
(insert (substitute-command-keys (quail-docstring)))
|
||||
(goto-char (point-min))
|
||||
(with-syntax-table emacs-lisp-mode-syntax-table
|
||||
(while (re-search-forward "\\\\<\\sw\\(\\sw\\|\\s_\\)+>" nil t)
|
||||
|
@ -2647,10 +2647,11 @@ the word mode."
|
||||
"Non-default value overrides the behavior of `isearch-search-fun-default'.
|
||||
This variable's value should be a function, which will be called
|
||||
with no arguments, and should return a function that takes three
|
||||
arguments: STRING, BOUND, and NOERROR.
|
||||
arguments: STRING, BOUND, and NOERROR. See `re-search-forward'
|
||||
for the meaning of BOUND and NOERROR arguments.
|
||||
|
||||
This returned function will be used by `isearch-search-string' to
|
||||
search for the first occurrence of STRING or its translation.")
|
||||
search for the first occurrence of STRING.")
|
||||
|
||||
(defun isearch-search-fun ()
|
||||
"Return the function to use for the search.
|
||||
@ -2695,8 +2696,14 @@ Can be changed via `isearch-search-fun-function' for special needs."
|
||||
|
||||
(defun isearch-search-string (string bound noerror)
|
||||
"Search for the first occurrence of STRING or its translation.
|
||||
STRING's characters are translated using `translation-table-for-input'
|
||||
if that is non-nil.
|
||||
If found, move point to the end of the occurrence,
|
||||
update the match data, and return point."
|
||||
update the match data, and return point.
|
||||
An optional second argument bounds the search; it is a buffer position.
|
||||
The match found must not extend after that position.
|
||||
Optional third argument, if t, means if fail just return nil (no error).
|
||||
If not nil and not t, move to limit of search and return nil."
|
||||
(let* ((func (isearch-search-fun))
|
||||
(pos1 (save-excursion (funcall func string bound noerror)))
|
||||
pos2)
|
||||
|
@ -1619,7 +1619,7 @@ The preference is a float determined from `shr-prefer-media-type'."
|
||||
(defun shr-table-body (dom)
|
||||
(let ((tbodies (seq-filter (lambda (child)
|
||||
(eq (dom-tag child) 'tbody))
|
||||
(dom-children dom))))
|
||||
(dom-non-text-children dom))))
|
||||
(cond
|
||||
((null tbodies)
|
||||
dom)
|
||||
|
@ -102,7 +102,7 @@
|
||||
|
||||
(eval-and-compile
|
||||
(defconst ruby-here-doc-beg-re
|
||||
"\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
|
||||
"\\(<\\)<\\([~-]\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
|
||||
"Regexp to match the beginning of a heredoc.")
|
||||
|
||||
(defconst ruby-expression-expansion-re
|
||||
|
@ -861,7 +861,13 @@ tools are used, and when."
|
||||
(cl-assert (directory-name-p dir))
|
||||
(require 'semantic/symref)
|
||||
(defvar semantic-symref-tool)
|
||||
(let* ((default-directory dir)
|
||||
|
||||
;; Some symref backends use `ede-project-root-directory' as the root
|
||||
;; directory for the search, rather than `default-directory'. Since
|
||||
;; the caller has specified `dir', we bind `ede-minor-mode' to nil
|
||||
;; to force the backend to use `default-directory'.
|
||||
(let* ((ede-minor-mode nil)
|
||||
(default-directory dir)
|
||||
(semantic-symref-tool 'detect)
|
||||
(res (semantic-symref-find-references-by-name symbol 'subdirs))
|
||||
(hits (and res (oref res hit-lines)))
|
||||
|
580
lisp/xwidget.el
Normal file
580
lisp/xwidget.el
Normal file
@ -0,0 +1,580 @@
|
||||
;;; xwidget.el --- api functions for xwidgets -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; Copyright (C) 2011-2016 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; Author: Joakim Verona (joakim@verona.se)
|
||||
;;
|
||||
;; This file is part of GNU Emacs.
|
||||
;;
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
;;
|
||||
;; --------------------------------------------------------------------
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; See xwidget.c for more api functions.
|
||||
|
||||
;; TODO this breaks compilation when we don't have xwidgets.
|
||||
;;(require 'xwidget-internal)
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'bookmark)
|
||||
|
||||
(defcustom xwidget-webkit-scroll-behaviour 'native
|
||||
"Scroll behaviour of the webkit instance.
|
||||
'native or 'image."
|
||||
:version "25.1"
|
||||
:group 'frames ; TODO add xwidgets group if more options are added
|
||||
:type '(choice (const native) (const image)))
|
||||
|
||||
(declare-function make-xwidget "xwidget.c"
|
||||
(beg end type title width height arguments &optional buffer))
|
||||
(declare-function xwidget-set-adjustment "xwidget.c"
|
||||
(xwidget axis relative value))
|
||||
(declare-function xwidget-buffer "xwidget.c" (xwidget))
|
||||
(declare-function xwidget-webkit-get-title "xwidget.c" (xwidget))
|
||||
(declare-function xwidget-size-request "xwidget.c" (xwidget))
|
||||
(declare-function xwidget-resize "xwidget.c" (xwidget new-width new-height))
|
||||
(declare-function xwidget-webkit-execute-script "xwidget.c" (xwidget script))
|
||||
(declare-function xwidget-webkit-goto-uri "xwidget.c" (xwidget uri))
|
||||
(declare-function xwidget-plist "xwidget.c" (xwidget))
|
||||
(declare-function set-xwidget-plist "xwidget.c" (xwidget plist))
|
||||
(declare-function xwidget-view-window "xwidget.c" (xwidget-view))
|
||||
(declare-function xwidget-view-model "xwidget.c" (xwidget-view))
|
||||
(declare-function delete-xwidget-view "xwidget.c" (xwidget-view))
|
||||
(declare-function get-buffer-xwidgets "xwidget.c" (buffer))
|
||||
|
||||
(defun xwidget-insert (pos type title width height &optional args)
|
||||
"Insert an xwidget at POS.
|
||||
given ID, TYPE, TITLE WIDTH and
|
||||
HEIGHT in the current buffer.
|
||||
|
||||
Return ID
|
||||
|
||||
see `make-xwidget' for types suitable for TYPE.
|
||||
Optional argument ARGS usage depends on the xwidget."
|
||||
(goto-char pos)
|
||||
(let ((id (make-xwidget (point) (point)
|
||||
type title width height args)))
|
||||
(put-text-property (point) (+ 1 (point))
|
||||
'display (list 'xwidget ':xwidget id))
|
||||
id))
|
||||
|
||||
(defun xwidget-at (pos)
|
||||
"Return xwidget at POS."
|
||||
;; TODO this function is a bit tedious because the C layer isn't well
|
||||
;; protected yet and xwidgetp apparently doesn't work yet.
|
||||
(let* ((disp (get-text-property pos 'display))
|
||||
(xw (car (cdr (cdr disp)))))
|
||||
;;(if (xwidgetp xw) xw nil)
|
||||
(if (equal 'xwidget (car disp)) xw)))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; webkit support
|
||||
(require 'browse-url)
|
||||
(require 'image-mode);;for some image-mode alike functionality
|
||||
|
||||
;;;###autoload
|
||||
(defun xwidget-webkit-browse-url (url &optional new-session)
|
||||
"Ask xwidget-webkit to browse URL.
|
||||
NEW-SESSION specifies whether to create a new xwidget-webkit session. URL
|
||||
defaults to the string looking like a url around the cursor position."
|
||||
(interactive (progn
|
||||
(require 'browse-url)
|
||||
(browse-url-interactive-arg "xwidget-webkit URL: "
|
||||
;;(xwidget-webkit-current-url)
|
||||
)))
|
||||
(when (stringp url)
|
||||
(if new-session
|
||||
(xwidget-webkit-new-session url)
|
||||
(xwidget-webkit-goto-url url))))
|
||||
|
||||
;;todo.
|
||||
;; - check that the webkit support is compiled in
|
||||
(defvar xwidget-webkit-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map "g" 'xwidget-webkit-browse-url)
|
||||
(define-key map "a" 'xwidget-webkit-adjust-size-dispatch)
|
||||
(define-key map "b" 'xwidget-webkit-back)
|
||||
(define-key map "r" 'xwidget-webkit-reload)
|
||||
(define-key map "t" (lambda () (interactive) (message "o"))) ;FIXME: ?!?
|
||||
(define-key map "\C-m" 'xwidget-webkit-insert-string)
|
||||
(define-key map "w" 'xwidget-webkit-current-url)
|
||||
|
||||
;;similar to image mode bindings
|
||||
(define-key map (kbd "SPC") 'xwidget-webkit-scroll-up)
|
||||
(define-key map (kbd "DEL") 'xwidget-webkit-scroll-down)
|
||||
|
||||
(define-key map [remap scroll-up] 'xwidget-webkit-scroll-up)
|
||||
(define-key map [remap scroll-up-command] 'xwidget-webkit-scroll-up)
|
||||
|
||||
(define-key map [remap scroll-down] 'xwidget-webkit-scroll-down)
|
||||
(define-key map [remap scroll-down-command] 'xwidget-webkit-scroll-down)
|
||||
|
||||
(define-key map [remap forward-char] 'xwidget-webkit-scroll-forward)
|
||||
(define-key map [remap backward-char] 'xwidget-webkit-scroll-backward)
|
||||
(define-key map [remap right-char] 'xwidget-webkit-scroll-forward)
|
||||
(define-key map [remap left-char] 'xwidget-webkit-scroll-backward)
|
||||
;; (define-key map [remap previous-line] 'image-previous-line)
|
||||
;; (define-key map [remap next-line] 'image-next-line)
|
||||
|
||||
;; (define-key map [remap move-beginning-of-line] 'image-bol)
|
||||
;; (define-key map [remap move-end-of-line] 'image-eol)
|
||||
;; (define-key map [remap beginning-of-buffer] 'image-bob)
|
||||
;; (define-key map [remap end-of-buffer] 'image-eob)
|
||||
map)
|
||||
"Keymap for `xwidget-webkit-mode'.")
|
||||
|
||||
(defun xwidget-webkit-scroll-up ()
|
||||
"Scroll webkit up,either native or like image mode."
|
||||
(interactive)
|
||||
(if (eq xwidget-webkit-scroll-behaviour 'native)
|
||||
(xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t 50)
|
||||
(image-scroll-up)))
|
||||
|
||||
(defun xwidget-webkit-scroll-down ()
|
||||
"Scroll webkit down,either native or like image mode."
|
||||
(interactive)
|
||||
(if (eq xwidget-webkit-scroll-behaviour 'native)
|
||||
(xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t -50)
|
||||
(image-scroll-down)))
|
||||
|
||||
(defun xwidget-webkit-scroll-forward ()
|
||||
"Scroll webkit forward,either native or like image mode."
|
||||
(interactive)
|
||||
(if (eq xwidget-webkit-scroll-behaviour 'native)
|
||||
(xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t 50)
|
||||
(xwidget-webkit-scroll-forward)))
|
||||
|
||||
(defun xwidget-webkit-scroll-backward ()
|
||||
"Scroll webkit backward,either native or like image mode."
|
||||
(interactive)
|
||||
(if (eq xwidget-webkit-scroll-behaviour 'native)
|
||||
(xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t -50)
|
||||
(xwidget-webkit-scroll-backward)))
|
||||
|
||||
|
||||
;; The xwidget event needs to go into a higher level handler
|
||||
;; since the xwidget can generate an event even if it's offscreen.
|
||||
;; TODO this needs to use callbacks and consider different xwidget event types.
|
||||
(define-key (current-global-map) [xwidget-event] #'xwidget-event-handler)
|
||||
(defun xwidget-log (&rest msg)
|
||||
"Log MSG to a buffer."
|
||||
(let ((buf (get-buffer-create " *xwidget-log*")))
|
||||
(with-current-buffer buf
|
||||
(insert (apply #'format msg))
|
||||
(insert "\n"))))
|
||||
|
||||
(defun xwidget-event-handler ()
|
||||
"Receive xwidget event."
|
||||
(interactive)
|
||||
(xwidget-log "stuff happened to xwidget %S" last-input-event)
|
||||
(let*
|
||||
((xwidget-event-type (nth 1 last-input-event))
|
||||
(xwidget (nth 2 last-input-event))
|
||||
;;(xwidget-callback (xwidget-get xwidget 'callback))
|
||||
;;TODO stopped working for some reason
|
||||
)
|
||||
;;(funcall xwidget-callback xwidget xwidget-event-type)
|
||||
(message "xw callback %s" xwidget)
|
||||
(funcall 'xwidget-webkit-callback xwidget xwidget-event-type)))
|
||||
|
||||
(defun xwidget-webkit-callback (xwidget xwidget-event-type)
|
||||
"Callback for xwidgets.
|
||||
XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget."
|
||||
(if (not (buffer-live-p (xwidget-buffer xwidget)))
|
||||
(xwidget-log
|
||||
"error: callback called for xwidget with dead buffer")
|
||||
(with-current-buffer (xwidget-buffer xwidget)
|
||||
(let* ((strarg (nth 3 last-input-event)))
|
||||
(cond ((eq xwidget-event-type 'document-load-finished)
|
||||
(xwidget-log "webkit finished loading: '%s'"
|
||||
(xwidget-webkit-get-title xwidget))
|
||||
;;TODO - check the native/internal scroll
|
||||
;;(xwidget-adjust-size-to-content xwidget)
|
||||
(xwidget-webkit-adjust-size-dispatch) ;;TODO xwidget arg
|
||||
(rename-buffer (format "*xwidget webkit: %s *"
|
||||
(xwidget-webkit-get-title xwidget)))
|
||||
(pop-to-buffer (current-buffer)))
|
||||
((eq xwidget-event-type
|
||||
'navigation-policy-decision-requested)
|
||||
(if (string-match ".*#\\(.*\\)" strarg)
|
||||
(xwidget-webkit-show-id-or-named-element
|
||||
xwidget
|
||||
(match-string 1 strarg))))
|
||||
(t (xwidget-log "unhandled event:%s" xwidget-event-type)))))))
|
||||
|
||||
(defvar bookmark-make-record-function)
|
||||
(define-derived-mode xwidget-webkit-mode
|
||||
special-mode "xwidget-webkit" "Xwidget webkit view mode."
|
||||
(setq buffer-read-only t)
|
||||
(setq-local bookmark-make-record-function
|
||||
#'xwidget-webkit-bookmark-make-record)
|
||||
;; Keep track of [vh]scroll when switching buffers
|
||||
(image-mode-setup-winprops))
|
||||
|
||||
(defun xwidget-webkit-bookmark-make-record ()
|
||||
"Integrate Emacs bookmarks with the webkit xwidget."
|
||||
(nconc (bookmark-make-record-default t t)
|
||||
`((page . ,(xwidget-webkit-current-url))
|
||||
(handler . (lambda (bmk) (browse-url
|
||||
(bookmark-prop-get bmk 'page)))))))
|
||||
|
||||
|
||||
(defvar xwidget-webkit-last-session-buffer nil)
|
||||
|
||||
(defun xwidget-webkit-last-session ()
|
||||
"Last active webkit, or nil."
|
||||
(if (buffer-live-p xwidget-webkit-last-session-buffer)
|
||||
(with-current-buffer xwidget-webkit-last-session-buffer
|
||||
(xwidget-at (point-min)))
|
||||
nil))
|
||||
|
||||
(defun xwidget-webkit-current-session ()
|
||||
"Either the webkit in the current buffer, or the last one used.
|
||||
The latter might be nil."
|
||||
(or (xwidget-at (point-min)) (xwidget-webkit-last-session)))
|
||||
|
||||
(defun xwidget-adjust-size-to-content (xw)
|
||||
"Resize XW to content."
|
||||
;; xwidgets doesn't support widgets that have their own opinions about
|
||||
;; size well, yet this reads the desired size and resizes the Emacs
|
||||
;; allocated area accordingly.
|
||||
(let ((size (xwidget-size-request xw)))
|
||||
(xwidget-resize xw (car size) (cadr size))))
|
||||
|
||||
|
||||
(defvar xwidget-webkit-activeelement-js"
|
||||
function findactiveelement(doc){
|
||||
//alert(doc.activeElement.value);
|
||||
if(doc.activeElement.value != undefined){
|
||||
return doc.activeElement;
|
||||
}else{
|
||||
// recurse over the child documents:
|
||||
var frames = doc.getElementsByTagName('frame');
|
||||
for (var i = 0; i < frames.length; i++)
|
||||
{
|
||||
var d = frames[i].contentDocument;
|
||||
var rv = findactiveelement(d);
|
||||
if(rv != undefined){
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
"
|
||||
|
||||
"javascript that finds the active element."
|
||||
;; Yes it's ugly, because:
|
||||
;; - there is apparently no way to find the active frame other than recursion
|
||||
;; - the js "for each" construct misbehaved on the "frames" collection
|
||||
;; - a window with no frameset still has frames.length == 1, but
|
||||
;; frames[0].document.activeElement != document.activeElement
|
||||
;;TODO the activeelement type needs to be examined, for iframe, etc.
|
||||
)
|
||||
|
||||
(defun xwidget-webkit-insert-string (xw str)
|
||||
"Insert string in the active field in the webkit.
|
||||
Argument XW webkit.
|
||||
Argument STR string."
|
||||
;; Read out the string in the field first and provide for edit.
|
||||
(interactive
|
||||
(let* ((xww (xwidget-webkit-current-session))
|
||||
|
||||
(field-value
|
||||
(progn
|
||||
(xwidget-webkit-execute-script xww xwidget-webkit-activeelement-js)
|
||||
(xwidget-webkit-execute-script-rv
|
||||
xww
|
||||
"findactiveelement(document).value;")))
|
||||
(field-type (xwidget-webkit-execute-script-rv
|
||||
xww
|
||||
"findactiveelement(document).type;")))
|
||||
(list xww
|
||||
(cond ((equal "text" field-type)
|
||||
(read-string "text:" field-value))
|
||||
((equal "password" field-type)
|
||||
(read-passwd "password:" nil field-value))
|
||||
((equal "textarea" field-type)
|
||||
(xwidget-webkit-begin-edit-textarea xww field-value))))))
|
||||
(xwidget-webkit-execute-script
|
||||
xw
|
||||
(format "findactiveelement(document).value='%s'" str)))
|
||||
|
||||
(defvar xwidget-xwbl)
|
||||
(defun xwidget-webkit-begin-edit-textarea (xw text)
|
||||
"Start editing of a webkit text area.
|
||||
XW is the xwidget identifier, TEXT is retrieved from the webkit."
|
||||
(switch-to-buffer
|
||||
(generate-new-buffer "textarea"))
|
||||
|
||||
(set (make-local-variable 'xwidget-xwbl) xw)
|
||||
(insert text))
|
||||
|
||||
(defun xwidget-webkit-end-edit-textarea ()
|
||||
"End editing of a webkit text area."
|
||||
(interactive)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward "\n" nil t)
|
||||
(replace-match "\\n" nil t))
|
||||
(xwidget-webkit-execute-script
|
||||
xwidget-xwbl
|
||||
(format "findactiveelement(document).value='%s'"
|
||||
(buffer-substring (point-min) (point-max))))
|
||||
;;TODO convert linefeed to \n
|
||||
)
|
||||
|
||||
(defun xwidget-webkit-show-named-element (xw element-name)
|
||||
"Make named-element show. for instance an anchor.
|
||||
Argument XW is the xwidget.
|
||||
Argument ELEMENT-NAME is the element name to display in the webkit xwidget."
|
||||
(interactive (list (xwidget-webkit-current-session)
|
||||
(read-string "element name:")))
|
||||
;;TODO since an xwidget is an Emacs object, it is not trivial to do
|
||||
;; some things that are taken for granted in a normal browser.
|
||||
;; scrolling an anchor/named-element into view is one such thing.
|
||||
;; This function implements a proof-of-concept for this. Problems
|
||||
;; remaining: - The selected window is scrolled but this is not
|
||||
;; always correct - This needs to be interfaced into browse-url
|
||||
;; somehow. The tricky part is that we need to do this in two steps:
|
||||
;; A: load the base url, wait for load signal to arrive B: navigate
|
||||
;; to the anchor when the base url is finished rendering
|
||||
|
||||
;; This part figures out the Y coordinate of the element
|
||||
(let ((y (string-to-number
|
||||
(xwidget-webkit-execute-script-rv
|
||||
xw
|
||||
(format
|
||||
"document.getElementsByName('%s')[0].getBoundingClientRect().top"
|
||||
element-name)
|
||||
0))))
|
||||
;; Now we need to tell Emacs to scroll the element into view.
|
||||
(xwidget-log "scroll: %d" y)
|
||||
(set-window-vscroll (selected-window) y t)))
|
||||
|
||||
(defun xwidget-webkit-show-id-element (xw element-id)
|
||||
"Make id-element show. for instance an anchor.
|
||||
Argument XW is the webkit xwidget.
|
||||
Argument ELEMENT-ID is the id of the element to show."
|
||||
(interactive (list (xwidget-webkit-current-session)
|
||||
(read-string "element id:")))
|
||||
(let ((y (string-to-number
|
||||
(xwidget-webkit-execute-script-rv
|
||||
xw
|
||||
(format "document.getElementById('%s').getBoundingClientRect().top"
|
||||
element-id)
|
||||
0))))
|
||||
;; Now we need to tell Emacs to scroll the element into view.
|
||||
(xwidget-log "scroll: %d" y)
|
||||
(set-window-vscroll (selected-window) y t)))
|
||||
|
||||
(defun xwidget-webkit-show-id-or-named-element (xw element-id)
|
||||
"Make id-element show. for instance an anchor.
|
||||
Argument XW is the webkit xwidget.
|
||||
Argument ELEMENT-ID is either a name or an element id."
|
||||
(interactive (list (xwidget-webkit-current-session)
|
||||
(read-string "element id:")))
|
||||
(let* ((y1 (string-to-number
|
||||
(xwidget-webkit-execute-script-rv
|
||||
xw
|
||||
(format "document.getElementsByName('%s')[0].getBoundingClientRect().top" element-id)
|
||||
"0")))
|
||||
(y2 (string-to-number
|
||||
(xwidget-webkit-execute-script-rv
|
||||
xw
|
||||
(format "document.getElementById('%s').getBoundingClientRect().top" element-id)
|
||||
"0")))
|
||||
(y3 (max y1 y2)))
|
||||
;; Now we need to tell Emacs to scroll the element into view.
|
||||
(xwidget-log "scroll: %d" y3)
|
||||
(set-window-vscroll (selected-window) y3 t)))
|
||||
|
||||
(defun xwidget-webkit-adjust-size-to-content ()
|
||||
"Adjust webkit to content size."
|
||||
(interactive)
|
||||
(xwidget-adjust-size-to-content (xwidget-webkit-current-session)))
|
||||
|
||||
(defun xwidget-webkit-adjust-size-dispatch ()
|
||||
"Adjust size according to mode."
|
||||
(interactive)
|
||||
(if (eq xwidget-webkit-scroll-behaviour 'native)
|
||||
(xwidget-webkit-adjust-size-to-window)
|
||||
(xwidget-webkit-adjust-size-to-content))
|
||||
;; The recenter is intended to correct a visual glitch.
|
||||
;; It errors out if the buffer isn't visible, but then we don't get
|
||||
;; the glitch, so silence errors.
|
||||
(ignore-errors
|
||||
(recenter-top-bottom))
|
||||
)
|
||||
|
||||
(defun xwidget-webkit-adjust-size-to-window ()
|
||||
"Adjust webkit to window."
|
||||
(interactive)
|
||||
(xwidget-resize (xwidget-webkit-current-session) (window-pixel-width)
|
||||
(window-pixel-height)))
|
||||
|
||||
(defun xwidget-webkit-adjust-size (w h)
|
||||
"Manually set webkit size.
|
||||
Argument W width.
|
||||
Argument H height."
|
||||
;; TODO shouldn't be tied to the webkit xwidget
|
||||
(interactive "nWidth:\nnHeight:\n")
|
||||
(xwidget-resize (xwidget-webkit-current-session) w h))
|
||||
|
||||
(defun xwidget-webkit-fit-width ()
|
||||
"Adjust width of webkit to window width."
|
||||
(interactive)
|
||||
(xwidget-webkit-adjust-size (- (nth 2 (window-inside-pixel-edges))
|
||||
(car (window-inside-pixel-edges)))
|
||||
1000))
|
||||
|
||||
(defun xwidget-webkit-new-session (url)
|
||||
"Create a new webkit session buffer with URL."
|
||||
(let*
|
||||
((bufname (generate-new-buffer-name "*xwidget-webkit*"))
|
||||
xw)
|
||||
(setq xwidget-webkit-last-session-buffer (switch-to-buffer
|
||||
(get-buffer-create bufname)))
|
||||
(insert " 'a' adjusts the xwidget size.")
|
||||
(setq xw (xwidget-insert 1 'webkit-osr bufname 1000 1000))
|
||||
(xwidget-put xw 'callback 'xwidget-webkit-callback)
|
||||
(xwidget-webkit-mode)
|
||||
(xwidget-webkit-goto-uri (xwidget-webkit-last-session) url)))
|
||||
|
||||
|
||||
(defun xwidget-webkit-goto-url (url)
|
||||
"Goto URL."
|
||||
(if (xwidget-webkit-current-session)
|
||||
(progn
|
||||
(xwidget-webkit-goto-uri (xwidget-webkit-current-session) url))
|
||||
(xwidget-webkit-new-session url)))
|
||||
|
||||
(defun xwidget-webkit-back ()
|
||||
"Back in history."
|
||||
(interactive)
|
||||
(xwidget-webkit-execute-script (xwidget-webkit-current-session)
|
||||
"history.go(-1);"))
|
||||
|
||||
(defun xwidget-webkit-reload ()
|
||||
"Reload current url."
|
||||
(interactive)
|
||||
(xwidget-webkit-execute-script (xwidget-webkit-current-session)
|
||||
"history.go(0);"))
|
||||
|
||||
(defun xwidget-webkit-current-url ()
|
||||
"Get the webkit url. place it on kill ring."
|
||||
(interactive)
|
||||
(let* ((rv (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
|
||||
"document.URL"))
|
||||
(url (kill-new (or rv ""))))
|
||||
(message "url: %s" url)
|
||||
url))
|
||||
|
||||
(defun xwidget-webkit-execute-script-rv (xw script &optional default)
|
||||
"Same as 'xwidget-webkit-execute-script' but but with return value.
|
||||
XW is the webkit instance. SCRIPT is the script to execute.
|
||||
DEFAULT is the defaultreturn value."
|
||||
;; Notice the ugly "title" hack. It is needed because the Webkit
|
||||
;; API at the time of writing didn't support returning values. This
|
||||
;; is a wrapper for the title hack so it's easy to remove should
|
||||
;; Webkit someday support JS return values or we find some other way
|
||||
;; to access the DOM.
|
||||
|
||||
;; Reset webkit title. Not very nice.
|
||||
(let* ((emptytag "titlecantbewhitespaceohthehorror")
|
||||
title)
|
||||
(xwidget-webkit-execute-script xw (format "document.title=\"%s\";"
|
||||
(or default emptytag)))
|
||||
(xwidget-webkit-execute-script xw (format "document.title=%s;" script))
|
||||
(setq title (xwidget-webkit-get-title xw))
|
||||
(if (equal emptytag title)
|
||||
(setq title ""))
|
||||
(unless title
|
||||
(setq title default))
|
||||
title))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defun xwidget-webkit-get-selection ()
|
||||
"Get the webkit selection."
|
||||
(xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
|
||||
"window.getSelection().toString();"))
|
||||
|
||||
(defun xwidget-webkit-copy-selection-as-kill ()
|
||||
"Get the webkit selection and put it on the kill ring."
|
||||
(interactive)
|
||||
(kill-new (xwidget-webkit-get-selection)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Xwidget plist management (similar to the process plist functions)
|
||||
|
||||
(defun xwidget-get (xwidget propname)
|
||||
"Return the value of XWIDGET' PROPNAME property.
|
||||
This is the last value stored with `(xwidget-put XWIDGET PROPNAME VALUE)'."
|
||||
(plist-get (xwidget-plist xwidget) propname))
|
||||
|
||||
(defun xwidget-put (xwidget propname value)
|
||||
"Change XWIDGET' PROPNAME property to VALUE.
|
||||
It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'."
|
||||
(set-xwidget-plist xwidget
|
||||
(plist-put (xwidget-plist xwidget) propname value)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defvar xwidget-view-list) ; xwidget.c
|
||||
(defvar xwidget-list) ; xwidget.c
|
||||
|
||||
(defun xwidget-delete-zombies ()
|
||||
"Helper for `xwidget-cleanup'."
|
||||
(dolist (xwidget-view xwidget-view-list)
|
||||
(when (or (not (window-live-p (xwidget-view-window xwidget-view)))
|
||||
(not (memq (xwidget-view-model xwidget-view)
|
||||
xwidget-list)))
|
||||
(delete-xwidget-view xwidget-view))))
|
||||
|
||||
(defun xwidget-cleanup ()
|
||||
"Delete zombie xwidgets."
|
||||
;; During development it was sometimes easy to wind up with zombie
|
||||
;; xwidget instances.
|
||||
;; This function tries to implement a workaround should it occur again.
|
||||
(interactive)
|
||||
;; Kill xviews that should have been deleted but still linger.
|
||||
(xwidget-delete-zombies)
|
||||
;; Redraw display otherwise ghost of zombies will remain to haunt the screen
|
||||
(redraw-display))
|
||||
|
||||
(defun xwidget-kill-buffer-query-function ()
|
||||
"Ask before killing a buffer that has xwidgets."
|
||||
(let ((xwidgets (get-buffer-xwidgets (current-buffer))))
|
||||
(or (not xwidgets)
|
||||
(not (memq t (mapcar #'xwidget-query-on-exit-flag xwidgets)))
|
||||
(yes-or-no-p
|
||||
(format "Buffer %S has xwidgets; kill it? " (buffer-name))))))
|
||||
|
||||
(when (featurep 'xwidget-internal)
|
||||
(add-hook 'kill-buffer-query-functions #'xwidget-kill-buffer-query-function)
|
||||
;; This would have felt better in C, but this seems to work well in
|
||||
;; practice though.
|
||||
(add-hook 'window-configuration-change-hook #'xwidget-delete-zombies))
|
||||
|
||||
(provide 'xwidget)
|
||||
;;; xwidget.el ends here
|
@ -152,6 +152,9 @@ DBUS_LIBS = @DBUS_LIBS@
|
||||
## dbusbind.o if HAVE_DBUS, else empty.
|
||||
DBUS_OBJ = @DBUS_OBJ@
|
||||
|
||||
## xwidgets.o if HAVE_XWIDGETS, else empty.
|
||||
XWIDGETS_OBJ = @XWIDGETS_OBJ@
|
||||
|
||||
LIB_EXECINFO=@LIB_EXECINFO@
|
||||
|
||||
SETTINGS_CFLAGS = @SETTINGS_CFLAGS@
|
||||
@ -220,6 +223,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
|
||||
RSVG_LIBS= @RSVG_LIBS@
|
||||
RSVG_CFLAGS= @RSVG_CFLAGS@
|
||||
|
||||
WEBKIT_LIBS= @WEBKIT_LIBS@
|
||||
WEBKIT_CFLAGS= @WEBKIT_CFLAGS@
|
||||
|
||||
CAIRO_LIBS= @CAIRO_LIBS@
|
||||
CAIRO_CFLAGS= @CAIRO_CFLAGS@
|
||||
|
||||
@ -359,6 +365,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
|
||||
$(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
|
||||
$(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
|
||||
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
|
||||
$(WEBKIT_CFLAGS) \
|
||||
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
||||
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
||||
$(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
|
||||
@ -388,6 +395,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
|
||||
process.o gnutls.o callproc.o \
|
||||
region-cache.o sound.o atimer.o \
|
||||
doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
|
||||
$(XWIDGETS_OBJ) \
|
||||
profiler.o decompress.o \
|
||||
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
|
||||
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
|
||||
@ -468,6 +476,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp})
|
||||
LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
|
||||
$(LIBX_OTHER) $(LIBSOUND) \
|
||||
$(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
|
||||
$(WEBKIT_LIBS) \
|
||||
$(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
|
||||
$(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
|
||||
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
|
||||
|
@ -43,6 +43,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "keymap.h"
|
||||
#include "frame.h"
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
#ifdef WINDOWSNT
|
||||
#include "w32heap.h" /* for mmap_* */
|
||||
#endif
|
||||
@ -1747,6 +1750,9 @@ cleaning up all windows currently displaying the buffer to be killed. */)
|
||||
|
||||
kill_buffer_processes (buffer);
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
kill_buffer_xwidgets (buffer);
|
||||
#endif
|
||||
/* Killing buffer processes may run sentinels which may have killed
|
||||
our buffer. */
|
||||
if (!BUFFER_LIVE_P (b))
|
||||
|
@ -348,6 +348,10 @@ enum glyph_type
|
||||
|
||||
/* Glyph is a space of fractional width and/or height. */
|
||||
STRETCH_GLYPH
|
||||
#ifdef HAVE_XWIDGETS
|
||||
/* Glyph is an external widget drawn by the GUI toolkit. */
|
||||
,XWIDGET_GLYPH
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -499,6 +503,9 @@ struct glyph
|
||||
/* Image ID for image glyphs (type == IMAGE_GLYPH). */
|
||||
int img_id;
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
struct xwidget *xwidget;
|
||||
#endif
|
||||
/* Sub-structure for type == STRETCH_GLYPH. */
|
||||
struct
|
||||
{
|
||||
@ -1350,6 +1357,9 @@ struct glyph_string
|
||||
/* Image, if any. */
|
||||
struct image *img;
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
struct xwidget *xwidget;
|
||||
#endif
|
||||
/* Slice */
|
||||
struct glyph_slice slice;
|
||||
|
||||
@ -2102,6 +2112,10 @@ enum display_element_type
|
||||
|
||||
/* Continuation glyphs. See the comment for IT_TRUNCATION. */
|
||||
IT_CONTINUATION
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
,IT_XWIDGET
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -2165,6 +2179,9 @@ enum it_method {
|
||||
GET_FROM_C_STRING,
|
||||
GET_FROM_IMAGE,
|
||||
GET_FROM_STRETCH,
|
||||
#ifdef HAVE_XWIDGETS
|
||||
GET_FROM_XWIDGET,
|
||||
#endif
|
||||
NUM_IT_METHODS
|
||||
};
|
||||
|
||||
@ -2382,6 +2399,12 @@ struct it
|
||||
struct {
|
||||
Lisp_Object object;
|
||||
} stretch;
|
||||
#ifdef HAVE_XWIDGETS
|
||||
/* method == GET_FROM_XWIDGET */
|
||||
struct {
|
||||
Lisp_Object object;
|
||||
} xwidget;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
/* Current text and display positions. */
|
||||
@ -2506,6 +2529,11 @@ struct it
|
||||
/* If what == IT_IMAGE, the id of the image to display. */
|
||||
ptrdiff_t image_id;
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
/* If what == IT_XWIDGET. */
|
||||
struct xwidget *xwidget;
|
||||
#endif
|
||||
|
||||
/* Values from `slice' property. */
|
||||
struct it_slice slice;
|
||||
|
||||
|
@ -44,6 +44,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include TERM_HEADER
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <fpending.h>
|
||||
@ -3543,6 +3547,9 @@ update_window (struct window *w, bool force_p)
|
||||
add_window_display_history (w, w->current_matrix->method, paused_p);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
xwidget_end_redisplay (w, w->current_matrix);
|
||||
#endif
|
||||
clear_glyph_matrix (desired_matrix);
|
||||
|
||||
return paused_p;
|
||||
@ -4116,6 +4123,11 @@ scrolling_window (struct window *w, bool header_line_p)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
/* Currently this seems needed to detect xwidget movement reliably. */
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* Give up if some rows in the desired matrix are not enabled. */
|
||||
if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
|
||||
return -1;
|
||||
|
@ -66,6 +66,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "buffer.h"
|
||||
#include "window.h"
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
#include "atimer.h"
|
||||
#include "blockinput.h"
|
||||
#include "syssignal.h"
|
||||
@ -1492,6 +1495,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
||||
syms_of_xfns ();
|
||||
syms_of_xmenu ();
|
||||
syms_of_fontset ();
|
||||
#ifdef HAVE_XWIDGETS
|
||||
syms_of_xwidget ();
|
||||
#endif
|
||||
syms_of_xsettings ();
|
||||
#ifdef HAVE_X_SM
|
||||
syms_of_xsmfns ();
|
||||
|
@ -23,6 +23,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "lisp.h"
|
||||
#include "frame.h"
|
||||
#include "xterm.h"
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
#include "emacsgtkfixed.h"
|
||||
|
||||
/* Silence a bogus diagnostic; see GNOME bug 683906. */
|
||||
@ -31,27 +34,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
# pragma GCC diagnostic ignored "-Wunused-local-typedefs"
|
||||
#endif
|
||||
|
||||
#define EMACS_TYPE_FIXED emacs_fixed_get_type ()
|
||||
#define EMACS_FIXED(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed)
|
||||
|
||||
typedef struct _EmacsFixed EmacsFixed;
|
||||
typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
|
||||
typedef struct _EmacsFixedClass EmacsFixedClass;
|
||||
|
||||
struct _EmacsFixed
|
||||
{
|
||||
GtkFixed container;
|
||||
|
||||
/*< private >*/
|
||||
EmacsFixedPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EmacsFixedClass
|
||||
{
|
||||
GtkFixedClass parent_class;
|
||||
};
|
||||
|
||||
struct _EmacsFixedPrivate
|
||||
{
|
||||
struct frame *f;
|
||||
@ -64,9 +50,103 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget,
|
||||
static void emacs_fixed_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum,
|
||||
gint *natural);
|
||||
|
||||
static GType emacs_fixed_get_type (void);
|
||||
G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
|
||||
|
||||
static EmacsFixed *
|
||||
EMACS_FIXED (GtkWidget *widget)
|
||||
{
|
||||
return G_TYPE_CHECK_INSTANCE_CAST (widget, emacs_fixed_get_type (),
|
||||
EmacsFixed);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
|
||||
static EmacsFixedClass *
|
||||
EMACS_FIXED_GET_CLASS (GtkWidget *widget)
|
||||
{
|
||||
return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (),
|
||||
EmacsFixedClass);
|
||||
}
|
||||
|
||||
struct GtkFixedPrivateL
|
||||
{
|
||||
GList *children;
|
||||
};
|
||||
|
||||
static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
// For xwidgets.
|
||||
|
||||
// This basically re-implements the base class method and adds an
|
||||
// additional case for an xwidget view.
|
||||
|
||||
// It would be nicer if the bse class method could be called first,
|
||||
// and the the xview modification only would remain here. It wasn't
|
||||
// possible to solve it that way yet.
|
||||
EmacsFixedClass *klass;
|
||||
GtkWidgetClass *parent_class;
|
||||
struct GtkFixedPrivateL* priv;
|
||||
|
||||
klass = EMACS_FIXED_GET_CLASS (widget);
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
parent_class->size_allocate (widget, allocation);
|
||||
|
||||
priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
|
||||
GTK_TYPE_FIXED,
|
||||
struct GtkFixedPrivateL);
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
if (gtk_widget_get_has_window (widget))
|
||||
{
|
||||
if (gtk_widget_get_realized (widget))
|
||||
gdk_window_move_resize (gtk_widget_get_window (widget),
|
||||
allocation->x,
|
||||
allocation->y,
|
||||
allocation->width,
|
||||
allocation->height);
|
||||
}
|
||||
|
||||
for (GList *children = priv->children; children; children = children->next)
|
||||
{
|
||||
GtkFixedChild *child = children->data;
|
||||
|
||||
if (!gtk_widget_get_visible (child->widget))
|
||||
continue;
|
||||
|
||||
GtkRequisition child_requisition;
|
||||
gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
|
||||
|
||||
GtkAllocation child_allocation;
|
||||
child_allocation.x = child->x;
|
||||
child_allocation.y = child->y;
|
||||
|
||||
if (!gtk_widget_get_has_window (widget))
|
||||
{
|
||||
child_allocation.x += allocation->x;
|
||||
child_allocation.y += allocation->y;
|
||||
}
|
||||
|
||||
child_allocation.width = child_requisition.width;
|
||||
child_allocation.height = child_requisition.height;
|
||||
|
||||
struct xwidget_view *xv
|
||||
= g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
|
||||
if (xv)
|
||||
{
|
||||
child_allocation.width = xv->clip_right;
|
||||
child_allocation.height = xv->clip_bottom - xv->clip_top;
|
||||
}
|
||||
|
||||
gtk_widget_size_allocate (child->widget, &child_allocation);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_XWIDGETS */
|
||||
|
||||
static void
|
||||
emacs_fixed_class_init (EmacsFixedClass *klass)
|
||||
{
|
||||
@ -74,15 +154,20 @@ emacs_fixed_class_init (EmacsFixedClass *klass)
|
||||
|
||||
widget_class = (GtkWidgetClass*) klass;
|
||||
|
||||
|
||||
widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
|
||||
widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
|
||||
#ifdef HAVE_XWIDGETS
|
||||
widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
|
||||
#endif
|
||||
g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
emacs_fixed_init (EmacsFixed *fixed)
|
||||
{
|
||||
fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, EMACS_TYPE_FIXED,
|
||||
fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, emacs_fixed_get_type (),
|
||||
EmacsFixedPrivate);
|
||||
fixed->priv->f = 0;
|
||||
}
|
||||
@ -97,7 +182,7 @@ emacs_fixed_init (EmacsFixed *fixed)
|
||||
GtkWidget*
|
||||
emacs_fixed_new (struct frame *f)
|
||||
{
|
||||
EmacsFixed *fixed = g_object_new (EMACS_TYPE_FIXED, NULL);
|
||||
EmacsFixed *fixed = g_object_new (emacs_fixed_get_type (), NULL);
|
||||
EmacsFixedPrivate *priv = fixed->priv;
|
||||
priv->f = f;
|
||||
return GTK_WIDGET (fixed);
|
||||
|
@ -27,6 +27,26 @@ struct frame;
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct frame;
|
||||
|
||||
//typedef struct _EmacsFixed EmacsFixed;
|
||||
typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
|
||||
typedef struct _EmacsFixedClass EmacsFixedClass;
|
||||
|
||||
struct _EmacsFixed
|
||||
{
|
||||
GtkFixed container;
|
||||
|
||||
/*< private >*/
|
||||
EmacsFixedPrivate *priv;
|
||||
};
|
||||
|
||||
|
||||
struct _EmacsFixedClass
|
||||
{
|
||||
GtkFixedClass parent_class;
|
||||
};
|
||||
|
||||
extern GtkWidget *emacs_fixed_new (struct frame *f);
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -4013,6 +4013,13 @@ kbd_buffer_get_event (KBOARD **kbp,
|
||||
obj = make_lispy_event (&event->ie);
|
||||
kbd_fetch_ptr = event + 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_XWIDGETS
|
||||
else if (event->kind == XWIDGET_EVENT)
|
||||
{
|
||||
obj = make_lispy_event (&event->ie);
|
||||
kbd_fetch_ptr = event + 1;
|
||||
}
|
||||
#endif
|
||||
else if (event->kind == CONFIG_CHANGED_EVENT)
|
||||
{
|
||||
@ -5950,6 +5957,13 @@ make_lispy_event (struct input_event *event)
|
||||
}
|
||||
#endif /* HAVE_DBUS */
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
case XWIDGET_EVENT:
|
||||
{
|
||||
return Fcons (Qxwidget_event,event->arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY
|
||||
case FILE_NOTIFY_EVENT:
|
||||
{
|
||||
@ -10956,6 +10970,10 @@ syms_of_keyboard (void)
|
||||
DEFSYM (Qdbus_event, "dbus-event");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
DEFSYM (Qxwidget_event,"xwidget-event");
|
||||
#endif
|
||||
|
||||
#ifdef USE_FILE_NOTIFY
|
||||
DEFSYM (Qfile_notify, "file-notify");
|
||||
#endif /* USE_FILE_NOTIFY */
|
||||
|
@ -799,6 +799,12 @@ enum pvec_type
|
||||
PVEC_WINDOW_CONFIGURATION,
|
||||
PVEC_SUBR,
|
||||
PVEC_OTHER,
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
PVEC_XWIDGET,
|
||||
PVEC_XWIDGET_VIEW,
|
||||
#endif
|
||||
|
||||
/* These should be last, check internal_equal to see why. */
|
||||
PVEC_COMPILED,
|
||||
PVEC_CHAR_TABLE,
|
||||
|
16
src/print.c
16
src/print.c
@ -33,6 +33,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "intervals.h"
|
||||
#include "blockinput.h"
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
|
||||
#include <c-ctype.h>
|
||||
#include <float.h>
|
||||
#include <ftoastr.h>
|
||||
@ -1736,6 +1740,18 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
|
||||
print_c_string (XSUBR (obj)->symbol_name, printcharfun);
|
||||
printchar ('>', printcharfun);
|
||||
}
|
||||
#ifdef HAVE_XWIDGETS
|
||||
else if (XWIDGETP (obj))
|
||||
{
|
||||
print_c_string ("#<xwidget ", printcharfun);
|
||||
printchar ('>', printcharfun);
|
||||
}
|
||||
else if (XWIDGET_VIEW_P (obj))
|
||||
{
|
||||
print_c_string ("#<xwidget ", printcharfun);
|
||||
printchar ('>', printcharfun);
|
||||
}
|
||||
#endif
|
||||
else if (WINDOWP (obj))
|
||||
{
|
||||
int len = sprintf (buf, "#<window %"pI"d",
|
||||
|
@ -239,6 +239,11 @@ enum event_kind
|
||||
, NS_NONKEY_EVENT
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
/* events generated by xwidgets*/
|
||||
, XWIDGET_EVENT
|
||||
#endif
|
||||
|
||||
#ifdef USE_FILE_NOTIFY
|
||||
/* File or directory was changed. */
|
||||
, FILE_NOTIFY_EVENT
|
||||
|
@ -41,6 +41,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#ifdef MSDOS
|
||||
#include "msdos.h"
|
||||
#endif
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
|
||||
static ptrdiff_t count_windows (struct window *);
|
||||
static ptrdiff_t get_leaf_windows (struct window *, struct window **,
|
||||
@ -4368,6 +4371,9 @@ Signal an error when WINDOW is the only window on its frame. */)
|
||||
|
||||
/* Block input. */
|
||||
block_input ();
|
||||
#ifdef HAVE_XWIDGETS
|
||||
xwidget_view_delete_all_in_window (w);
|
||||
#endif
|
||||
window_resize_apply (p, horflag);
|
||||
/* If this window is referred to by the dpyinfo's mouse
|
||||
highlight, invalidate that slot to be safe (Bug#9904). */
|
||||
|
248
src/xdisp.c
248
src/xdisp.c
@ -318,6 +318,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include TERM_HEADER
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
#ifndef FRAME_X_OUTPUT
|
||||
#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
|
||||
#endif
|
||||
@ -854,6 +857,9 @@ static bool next_element_from_buffer (struct it *);
|
||||
static bool next_element_from_composition (struct it *);
|
||||
static bool next_element_from_image (struct it *);
|
||||
static bool next_element_from_stretch (struct it *);
|
||||
#ifdef HAVE_XWIDGETS
|
||||
static bool next_element_from_xwidget (struct it *);
|
||||
#endif
|
||||
static void load_overlay_strings (struct it *, ptrdiff_t);
|
||||
static bool get_next_display_element (struct it *);
|
||||
static enum move_it_result
|
||||
@ -4690,6 +4696,9 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
|
||||
if (CONSP (spec)
|
||||
/* Simple specifications. */
|
||||
&& !EQ (XCAR (spec), Qimage)
|
||||
#ifdef HAVE_XWIDGETS
|
||||
&& !EQ (XCAR (spec), Qxwidget)
|
||||
#endif
|
||||
&& !EQ (XCAR (spec), Qspace)
|
||||
&& !EQ (XCAR (spec), Qwhen)
|
||||
&& !EQ (XCAR (spec), Qslice)
|
||||
@ -5137,7 +5146,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
|
||||
|| ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
|
||||
&& valid_image_p (value))
|
||||
#endif /* not HAVE_WINDOW_SYSTEM */
|
||||
|| (CONSP (value) && EQ (XCAR (value), Qspace)));
|
||||
|| (CONSP (value) && EQ (XCAR (value), Qspace))
|
||||
#ifdef HAVE_XWIDGETS
|
||||
|| ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
|
||||
&& valid_xwidget_spec_p (value))
|
||||
#endif
|
||||
);
|
||||
|
||||
if (valid_p && display_replaced == 0)
|
||||
{
|
||||
@ -5212,6 +5226,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
|
||||
*position = it->position = start_pos;
|
||||
retval = 1 + (it->area == TEXT_AREA);
|
||||
}
|
||||
#ifdef HAVE_XWIDGETS
|
||||
else if (valid_xwidget_spec_p(value))
|
||||
{
|
||||
it->what = IT_XWIDGET;
|
||||
it->method = GET_FROM_XWIDGET;
|
||||
it->position = start_pos;
|
||||
it->object = NILP (object) ? it->w->contents : object;
|
||||
*position = start_pos;
|
||||
it->xwidget = lookup_xwidget(value);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
else
|
||||
{
|
||||
@ -5964,6 +5989,11 @@ push_it (struct it *it, struct text_pos *position)
|
||||
case GET_FROM_STRETCH:
|
||||
p->u.stretch.object = it->object;
|
||||
break;
|
||||
#ifdef HAVE_XWIDGETS
|
||||
case GET_FROM_XWIDGET:
|
||||
p->u.xwidget.object = it->object;
|
||||
break;
|
||||
#endif
|
||||
case GET_FROM_BUFFER:
|
||||
case GET_FROM_DISPLAY_VECTOR:
|
||||
case GET_FROM_STRING:
|
||||
@ -6065,6 +6095,11 @@ pop_it (struct it *it)
|
||||
it->object = p->u.image.object;
|
||||
it->slice = p->u.image.slice;
|
||||
break;
|
||||
#ifdef HAVE_XWIDGETS
|
||||
case GET_FROM_XWIDGET:
|
||||
it->object = p->u.xwidget.object;
|
||||
break;
|
||||
#endif
|
||||
case GET_FROM_STRETCH:
|
||||
it->object = p->u.stretch.object;
|
||||
break;
|
||||
@ -6739,7 +6774,10 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
|
||||
next_element_from_string,
|
||||
next_element_from_c_string,
|
||||
next_element_from_image,
|
||||
next_element_from_stretch
|
||||
next_element_from_stretch,
|
||||
#ifdef HAVE_XWIDGETS
|
||||
next_element_from_xwidget,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
|
||||
@ -7600,6 +7638,10 @@ set_iterator_to_next (struct it *it, bool reseat_p)
|
||||
|
||||
case GET_FROM_IMAGE:
|
||||
case GET_FROM_STRETCH:
|
||||
#ifdef HAVE_XWIDGETS
|
||||
case GET_FROM_XWIDGET:
|
||||
#endif
|
||||
|
||||
/* The position etc with which we have to proceed are on
|
||||
the stack. The position may be at the end of a string,
|
||||
if the `display' property takes up the whole string. */
|
||||
@ -8061,6 +8103,15 @@ next_element_from_image (struct it *it)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
static bool
|
||||
next_element_from_xwidget (struct it *it)
|
||||
{
|
||||
it->what = IT_XWIDGET;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Fill iterator IT with next display element from a stretch glyph
|
||||
property. IT->object is the value of the text property. Value is
|
||||
@ -18793,6 +18844,28 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
|
||||
glyph->left_box_line_p,
|
||||
glyph->right_box_line_p);
|
||||
}
|
||||
#ifdef HAVE_XWIDGETS
|
||||
else if (glyph->type == XWIDGET_GLYPH)
|
||||
{
|
||||
fprintf (stderr,
|
||||
" %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
|
||||
glyph - row->glyphs[TEXT_AREA],
|
||||
'X',
|
||||
glyph->charpos,
|
||||
(BUFFERP (glyph->object)
|
||||
? 'B'
|
||||
: (STRINGP (glyph->object)
|
||||
? 'S'
|
||||
: '-')),
|
||||
glyph->pixel_width,
|
||||
glyph->u.xwidget,
|
||||
'.',
|
||||
glyph->face_id,
|
||||
glyph->left_box_line_p,
|
||||
glyph->right_box_line_p);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -24291,6 +24364,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
|
||||
|
||||
return OK_PIXELS (width_p ? img->width : img->height);
|
||||
}
|
||||
# ifdef HAVE_XWIDGETS
|
||||
if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
|
||||
{
|
||||
// TODO: Don't return dummy size.
|
||||
return OK_PIXELS (100);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
if (EQ (car, Qplus) || EQ (car, Qminus))
|
||||
{
|
||||
@ -24796,6 +24876,18 @@ fill_image_glyph_string (struct glyph_string *s)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
static void
|
||||
fill_xwidget_glyph_string (struct glyph_string *s)
|
||||
{
|
||||
eassert (s->first_glyph->type == XWIDGET_GLYPH);
|
||||
s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
|
||||
s->font = s->face->font;
|
||||
s->width = s->first_glyph->pixel_width;
|
||||
s->ybase += s->first_glyph->voffset;
|
||||
s->xwidget = s->first_glyph->u.xwidget;
|
||||
}
|
||||
#endif
|
||||
/* Fill glyph string S from a sequence of stretch glyphs.
|
||||
|
||||
START is the index of the first glyph to consider,
|
||||
@ -25181,6 +25273,20 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
|
||||
} \
|
||||
while (false)
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
do \
|
||||
{ \
|
||||
s = alloca (sizeof *s); \
|
||||
INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
|
||||
fill_xwidget_glyph_string (s); \
|
||||
append_glyph_string (&(HEAD), &(TAIL), s); \
|
||||
++(START); \
|
||||
s->x = (X); \
|
||||
} \
|
||||
while (false)
|
||||
#endif
|
||||
|
||||
|
||||
/* Add a glyph string for a sequence of character glyphs to the list
|
||||
of strings between HEAD and TAIL. START is the index of the first
|
||||
@ -25302,7 +25408,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
|
||||
to allocate glyph strings (because draw_glyphs can be called
|
||||
asynchronously). */
|
||||
|
||||
#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
#define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
do \
|
||||
{ \
|
||||
HEAD = TAIL = NULL; \
|
||||
@ -25333,8 +25439,17 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
|
||||
case IMAGE_GLYPH: \
|
||||
BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
|
||||
HL, X, LAST_X); \
|
||||
break; \
|
||||
\
|
||||
break;
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
case XWIDGET_GLYPH: \
|
||||
BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
|
||||
HL, X, LAST_X); \
|
||||
break;
|
||||
#endif
|
||||
|
||||
#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
case GLYPHLESS_GLYPH: \
|
||||
BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
|
||||
HL, X, LAST_X); \
|
||||
@ -25353,6 +25468,18 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
|
||||
} while (false)
|
||||
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
|
||||
#else
|
||||
# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
|
||||
BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
|
||||
#endif
|
||||
|
||||
|
||||
/* Draw glyphs between START and END in AREA of ROW on window W,
|
||||
starting at x-position X. X is relative to AREA in W. HL is a
|
||||
face-override with the following meaning:
|
||||
@ -25991,6 +26118,109 @@ produce_image_glyph (struct it *it)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
static void
|
||||
produce_xwidget_glyph (struct it *it)
|
||||
{
|
||||
struct xwidget *xw;
|
||||
int glyph_ascent, crop;
|
||||
eassert (it->what == IT_XWIDGET);
|
||||
|
||||
struct face *face = FACE_FROM_ID (it->f, it->face_id);
|
||||
eassert (face);
|
||||
/* Make sure X resources of the face is loaded. */
|
||||
prepare_face_for_display (it->f, face);
|
||||
|
||||
xw = it->xwidget;
|
||||
it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
|
||||
it->descent = xw->height/2;
|
||||
it->phys_descent = it->descent;
|
||||
it->pixel_width = xw->width;
|
||||
/* It's quite possible for images to have an ascent greater than
|
||||
their height, so don't get confused in that case. */
|
||||
if (it->descent < 0)
|
||||
it->descent = 0;
|
||||
|
||||
it->nglyphs = 1;
|
||||
|
||||
if (face->box != FACE_NO_BOX)
|
||||
{
|
||||
if (face->box_line_width > 0)
|
||||
{
|
||||
it->ascent += face->box_line_width;
|
||||
it->descent += face->box_line_width;
|
||||
}
|
||||
|
||||
if (it->start_of_box_run_p)
|
||||
it->pixel_width += eabs (face->box_line_width);
|
||||
it->pixel_width += eabs (face->box_line_width);
|
||||
}
|
||||
|
||||
take_vertical_position_into_account (it);
|
||||
|
||||
/* Automatically crop wide image glyphs at right edge so we can
|
||||
draw the cursor on same display row. */
|
||||
crop = it->pixel_width - (it->last_visible_x - it->current_x);
|
||||
if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
|
||||
it->pixel_width -= crop;
|
||||
|
||||
if (it->glyph_row)
|
||||
{
|
||||
enum glyph_row_area area = it->area;
|
||||
struct glyph *glyph
|
||||
= it->glyph_row->glyphs[area] + it->glyph_row->used[area];
|
||||
|
||||
if (it->glyph_row->reversed_p)
|
||||
{
|
||||
struct glyph *g;
|
||||
|
||||
/* Make room for the new glyph. */
|
||||
for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
|
||||
g[1] = *g;
|
||||
glyph = it->glyph_row->glyphs[it->area];
|
||||
}
|
||||
if (glyph < it->glyph_row->glyphs[area + 1])
|
||||
{
|
||||
glyph->charpos = CHARPOS (it->position);
|
||||
glyph->object = it->object;
|
||||
glyph->pixel_width = it->pixel_width;
|
||||
glyph->ascent = glyph_ascent;
|
||||
glyph->descent = it->descent;
|
||||
glyph->voffset = it->voffset;
|
||||
glyph->type = XWIDGET_GLYPH;
|
||||
glyph->avoid_cursor_p = it->avoid_cursor_p;
|
||||
glyph->multibyte_p = it->multibyte_p;
|
||||
if (it->glyph_row->reversed_p && area == TEXT_AREA)
|
||||
{
|
||||
/* In R2L rows, the left and the right box edges need to be
|
||||
drawn in reverse direction. */
|
||||
glyph->right_box_line_p = it->start_of_box_run_p;
|
||||
glyph->left_box_line_p = it->end_of_box_run_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph->left_box_line_p = it->start_of_box_run_p;
|
||||
glyph->right_box_line_p = it->end_of_box_run_p;
|
||||
}
|
||||
glyph->overlaps_vertically_p = 0;
|
||||
glyph->padding_p = 0;
|
||||
glyph->glyph_not_available_p = 0;
|
||||
glyph->face_id = it->face_id;
|
||||
glyph->u.xwidget = it->xwidget;
|
||||
glyph->font_type = FONT_TYPE_UNKNOWN;
|
||||
if (it->bidi_p)
|
||||
{
|
||||
glyph->resolved_level = it->bidi_it.resolved_level;
|
||||
eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
|
||||
glyph->bidi_type = it->bidi_it.type;
|
||||
}
|
||||
++it->glyph_row->used[area];
|
||||
}
|
||||
else
|
||||
IT_EXPAND_MATRIX_WIDTH (it, area);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
|
||||
of the glyph, WIDTH and HEIGHT are the width and height of the
|
||||
@ -27401,6 +27631,10 @@ x_produce_glyphs (struct it *it)
|
||||
produce_image_glyph (it);
|
||||
else if (it->what == IT_STRETCH)
|
||||
produce_stretch_glyph (it);
|
||||
#ifdef HAVE_XWIDGETS
|
||||
else if (it->what == IT_XWIDGET)
|
||||
produce_xwidget_glyph (it);
|
||||
#endif
|
||||
|
||||
done:
|
||||
/* Accumulate dimensions. Note: can't assume that it->descent > 0
|
||||
@ -27770,6 +28004,10 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
|
||||
/* Use normal cursor if not blinked off. */
|
||||
if (!w->cursor_off_p)
|
||||
{
|
||||
#ifdef HAVE_XWIDGETS
|
||||
if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
|
||||
return NO_CURSOR;
|
||||
#endif
|
||||
if (glyph != NULL && glyph->type == IMAGE_GLYPH)
|
||||
{
|
||||
if (cursor_type == FILLED_BOX_CURSOR)
|
||||
|
14
src/xterm.c
14
src/xterm.c
@ -62,6 +62,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "composite.h"
|
||||
#include "frame.h"
|
||||
#include "dispextern.h"
|
||||
#ifdef HAVE_XWIDGETS
|
||||
# include "xwidget.h"
|
||||
#endif
|
||||
#include "fontset.h"
|
||||
#include "termhooks.h"
|
||||
#include "termopts.h"
|
||||
@ -3511,6 +3514,12 @@ x_draw_glyph_string (struct glyph_string *s)
|
||||
x_draw_image_glyph_string (s);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
case XWIDGET_GLYPH:
|
||||
x_draw_xwidget_glyph_string (s);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case STRETCH_GLYPH:
|
||||
x_draw_stretch_glyph_string (s);
|
||||
break;
|
||||
@ -8920,6 +8929,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
|
||||
if (cursor_glyph == NULL)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_XWIDGETS
|
||||
if (cursor_glyph->type == XWIDGET_GLYPH)
|
||||
return; // Experimental avoidance of cursor on xwidget.
|
||||
#endif
|
||||
|
||||
/* If on an image, draw like a normal cursor. That's usually better
|
||||
visible than drawing a bar, esp. if the image is large so that
|
||||
the bar might not be in the window. */
|
||||
|
1320
src/xwidget.c
Normal file
1320
src/xwidget.c
Normal file
File diff suppressed because it is too large
Load Diff
132
src/xwidget.h
Normal file
132
src/xwidget.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* Support for embedding graphical components in a buffer.
|
||||
|
||||
Copyright (C) 2011-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef XWIDGET_H_INCLUDED
|
||||
#define XWIDGET_H_INCLUDED
|
||||
|
||||
void x_draw_xwidget_glyph_string (struct glyph_string *s);
|
||||
void syms_of_xwidget (void);
|
||||
|
||||
//extern Lisp_Object Qxwidget;
|
||||
|
||||
|
||||
bool valid_xwidget_spec_p (Lisp_Object object);
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
/*
|
||||
each xwidget instance/model is described by this struct.
|
||||
|
||||
lisp pseudovector.
|
||||
|
||||
|
||||
*/
|
||||
struct xwidget
|
||||
{
|
||||
struct vectorlike_header header;
|
||||
Lisp_Object plist; //auxilliary data
|
||||
Lisp_Object type; //the widget type
|
||||
Lisp_Object buffer; //buffer where xwidget lives
|
||||
Lisp_Object title; //a title that is used for button labels for instance
|
||||
|
||||
//here ends the lisp part.
|
||||
//"height" is the marker field
|
||||
int height;
|
||||
int width;
|
||||
|
||||
//for offscreen widgets, unused if not osr
|
||||
GtkWidget *widget_osr;
|
||||
GtkWidget *widgetwindow_osr;
|
||||
//this is used if the widget (webkit) is to be wrapped in a scrolled window,
|
||||
GtkWidget *widgetscrolledwindow_osr;
|
||||
/* Non-nil means kill silently if Emacs is exited. */
|
||||
unsigned int kill_without_query:1;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//struct for each xwidget view
|
||||
struct xwidget_view
|
||||
{
|
||||
struct vectorlike_header header;
|
||||
Lisp_Object model;
|
||||
Lisp_Object w;
|
||||
|
||||
//here ends the lisp part.
|
||||
//"redisplayed" is the marker field
|
||||
int redisplayed; //if touched by redisplay
|
||||
|
||||
int hidden; //if the "live" instance isnt drawn
|
||||
|
||||
GtkWidget *widget;
|
||||
GtkWidget *widgetwindow;
|
||||
GtkWidget *emacswindow;
|
||||
int x;
|
||||
int y;
|
||||
int clip_right;
|
||||
int clip_bottom;
|
||||
int clip_top;
|
||||
int clip_left;
|
||||
|
||||
|
||||
long handler_id;
|
||||
};
|
||||
|
||||
/* Test for xwidget pseudovector*/
|
||||
#define XWIDGETP(x) PSEUDOVECTORP (x, PVEC_XWIDGET)
|
||||
#define XXWIDGET(a) (eassert (XWIDGETP(a)), \
|
||||
(struct xwidget *) XUNTAG(a, Lisp_Vectorlike))
|
||||
|
||||
#define CHECK_XWIDGET(x) \
|
||||
CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x)
|
||||
|
||||
/* Test for xwidget_view pseudovector */
|
||||
#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW)
|
||||
#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P(a)), \
|
||||
(struct xwidget_view *) XUNTAG(a, Lisp_Vectorlike))
|
||||
|
||||
#define CHECK_XWIDGET_VIEW(x) \
|
||||
CHECK_TYPE (XWIDGET_VIEW_P (x), Qxwidget_view_p, x)
|
||||
|
||||
struct xwidget_type
|
||||
{
|
||||
/* A symbol uniquely identifying the xwidget type, */
|
||||
Lisp_Object *type;
|
||||
|
||||
/* Check that SPEC is a valid image specification for the given
|
||||
image type. Value is non-zero if SPEC is valid. */
|
||||
int (*valid_p) (Lisp_Object spec);
|
||||
|
||||
/* Next in list of all supported image types. */
|
||||
struct xwidget_type *next;
|
||||
};
|
||||
|
||||
|
||||
struct xwidget *xwidget_from_id (int id);
|
||||
|
||||
void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix);
|
||||
|
||||
struct xwidget *lookup_xwidget (Lisp_Object spec);
|
||||
#define XG_XWIDGET "emacs_xwidget"
|
||||
#define XG_XWIDGET_VIEW "emacs_xwidget_view"
|
||||
void xwidget_view_delete_all_in_window (struct window *w);
|
||||
|
||||
void kill_buffer_xwidgets (Lisp_Object buffer);
|
||||
#endif /* XWIDGET_H_INCLUDED */
|
@ -4,6 +4,10 @@
|
||||
end
|
||||
eowarn
|
||||
foo
|
||||
|
||||
foo(<<~squiggly)
|
||||
end
|
||||
squiggly
|
||||
end
|
||||
|
||||
def foo
|
||||
|
Loading…
Reference in New Issue
Block a user