1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-26 07:33:47 +00:00
This commit is contained in:
Paul Eggert 2016-01-30 11:27:34 -08:00
commit 82b089783e
36 changed files with 2874 additions and 172 deletions

View File

@ -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

View File

@ -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

View File

@ -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!

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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
View 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

View File

@ -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) \

View File

@ -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))

View File

@ -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;

View File

@ -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;

View File

@ -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 ();

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -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,

View File

@ -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",

View File

@ -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

View File

@ -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). */

View File

@ -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)

View File

@ -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

File diff suppressed because it is too large Load Diff

132
src/xwidget.h Normal file
View 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 */

View File

@ -4,6 +4,10 @@
end
eowarn
foo
foo(<<~squiggly)
end
squiggly
end
def foo