Merge from mainline.

This commit is contained in:
Xue Fuqiao 2013-08-04 10:59:08 +08:00
commit 99191b89ff
138 changed files with 4270 additions and 2495 deletions

View file

@ -1,3 +1,30 @@
2013-07-31 Eli Zaretskii <eliz@gnu.org>
* emacs.texi (Top): Remove menu item for the removed "Disabling
Multibyte" node.
2013-07-31 Xue Fuqiao <xfq.free@gmail.com>
* rmail.texi (Rmail Coding): Move here from mule.texi.
* custom.texi (Specifying File Variables): Fix cross-references.
* mule.texi (Unibyte Mode): Fix cross-references.
(Disabling Multibyte): Remove.
* macos.texi (Mac / GNUstep Basics): Mention `ns-alternate-modifier'.
* cal-xtra.texi (Advanced Calendar/Diary Usage): Update menu.
(Mayan Calendar): Move here from calendar.texi.
* emacs.texi (Top): Update menu.
2013-07-30 Xue Fuqiao <xfq.free@gmail.com>
* emacs.texi (Top): Add menu entry.
* maintaining.texi (VC Ignore): New node. Document vc-ignore.
(VC Directory Commands): Add vc-dir-ignore.
2013-07-28 Xue Fuqiao <xfq.free@gmail.com>
* glossary.texi (Glossary): Add some entries.

View file

@ -17,6 +17,7 @@ your personal tastes.
@menu
* Calendar Customizing:: Calendar layout and hooks.
* Holiday Customizing:: Defining your own holidays.
* Mayan Calendar:: Moving to a date specified in a Mayan calendar.
* Date Display Format:: Changing the format.
* Time Display Format:: Changing the format.
* Diary Customizing:: Defaults you can set.
@ -260,6 +261,99 @@ visible in the calendar window, with descriptive strings, like this:
(((6 4 2012) "Lunar Eclipse") ((11 13 2012) "Solar Eclipse") ... )
@end smallexample
@node Mayan Calendar
@subsection Converting from the Mayan Calendar
@cindex Mayan calendar
Here are the commands to select dates based on the Mayan calendar:
@table @kbd
@item g m l
Move to a date specified by the long count calendar
(@code{calendar-mayan-goto-long-count-date}).
@item g m n t
Move to the next occurrence of a place in the
tzolkin calendar (@code{calendar-mayan-next-tzolkin-date}).
@item g m p t
Move to the previous occurrence of a place in the
tzolkin calendar (@code{calendar-mayan-previous-tzolkin-date}).
@item g m n h
Move to the next occurrence of a place in the
haab calendar (@code{calendar-mayan-next-haab-date}).
@item g m p h
Move to the previous occurrence of a place in the
haab calendar (@code{calendar-mayan-previous-haab-date}).
@item g m n c
Move to the next occurrence of a place in the
calendar round (@code{calendar-mayan-next-calendar-round-date}).
@item g m p c
Move to the previous occurrence of a place in the
calendar round (@code{calendar-mayan-previous-calendar-round-date}).
@end table
@cindex Mayan long count
To understand these commands, you need to understand the Mayan calendars.
The @dfn{long count} is a counting of days with these units:
@display
1 kin = 1 day@ @ @ 1 uinal = 20 kin@ @ @ 1 tun = 18 uinal
1 katun = 20 tun@ @ @ 1 baktun = 20 katun
@end display
@kindex g m @r{(Calendar mode)}
@findex calendar-mayan-goto-long-count-date
@noindent
Thus, the long count date 12.16.11.16.6 means 12 baktun, 16 katun, 11
tun, 16 uinal, and 6 kin. The Emacs calendar can handle Mayan long
count dates as early as 7.17.18.13.3, but no earlier. When you use the
@kbd{g m l} command, type the Mayan long count date with the baktun,
katun, tun, uinal, and kin separated by periods.
@findex calendar-mayan-previous-tzolkin-date
@findex calendar-mayan-next-tzolkin-date
@cindex Mayan tzolkin calendar
The Mayan tzolkin calendar is a cycle of 260 days formed by a pair of
independent cycles of 13 and 20 days. Since this cycle repeats
endlessly, Emacs provides commands to move backward and forward to the
previous or next point in the cycle. Type @kbd{g m p t} to go to the
previous tzolkin date; Emacs asks you for a tzolkin date and moves point
to the previous occurrence of that date. Similarly, type @kbd{g m n t}
to go to the next occurrence of a tzolkin date.
@findex calendar-mayan-previous-haab-date
@findex calendar-mayan-next-haab-date
@cindex Mayan haab calendar
The Mayan haab calendar is a cycle of 365 days arranged as 18 months
of 20 days each, followed by a 5-day monthless period. Like the tzolkin
cycle, this cycle repeats endlessly, and there are commands to move
backward and forward to the previous or next point in the cycle. Type
@kbd{g m p h} to go to the previous haab date; Emacs asks you for a haab
date and moves point to the previous occurrence of that date.
Similarly, type @kbd{g m n h} to go to the next occurrence of a haab
date.
@c This is omitted because it is too long for smallbook format.
@c @findex calendar-mayan-previous-calendar-round-date
@findex calendar-mayan-next-calendar-round-date
@cindex Mayan calendar round
The Maya also used the combination of the tzolkin date and the haab
date. This combination is a cycle of about 52 years called a
@emph{calendar round}. If you type @kbd{g m p c}, Emacs asks you for
both a haab and a tzolkin date and then moves point to the previous
occurrence of that combination. Use @kbd{g m n c} to move point to the
next occurrence of a combination. These commands signal an error if the
haab/tzolkin date combination you have typed is impossible.
Emacs uses strict completion
@iftex
(@pxref{Completion Exit,,, emacs, the Emacs Manual})
@end iftex
@ifnottex
(@pxref{Completion Exit})
@end ifnottex
whenever it asks you to type a Mayan name, so you don't have to worry
about spelling.
@node Date Display Format
@subsection Date Display Format
@vindex calendar-date-display-form

View file

@ -678,7 +678,6 @@ and from several other calendars.
(aside from Gregorian).
* To Other Calendar:: Converting the selected date to various calendars.
* From Other Calendar:: Moving to a date specified in another calendar.
* Mayan Calendar:: Moving to a date specified in a Mayan calendar.
@end menu
@c FIXME perhaps most of the details should be moved to cal-xtra.
@ -913,93 +912,6 @@ years for the date given by point. If you are not in the calendar,
this command first asks you for the date of death and the range of
years, and then displays the list of yahrzeit dates.
@c FIXME move to emacs-xtra.
@node Mayan Calendar
@subsection Converting from the Mayan Calendar
Here are the commands to select dates based on the Mayan calendar:
@table @kbd
@item g m l
Move to a date specified by the long count calendar
(@code{calendar-mayan-goto-long-count-date}).
@item g m n t
Move to the next occurrence of a place in the
tzolkin calendar (@code{calendar-mayan-next-tzolkin-date}).
@item g m p t
Move to the previous occurrence of a place in the
tzolkin calendar (@code{calendar-mayan-previous-tzolkin-date}).
@item g m n h
Move to the next occurrence of a place in the
haab calendar (@code{calendar-mayan-next-haab-date}).
@item g m p h
Move to the previous occurrence of a place in the
haab calendar (@code{calendar-mayan-previous-haab-date}).
@item g m n c
Move to the next occurrence of a place in the
calendar round (@code{calendar-mayan-next-calendar-round-date}).
@item g m p c
Move to the previous occurrence of a place in the
calendar round (@code{calendar-mayan-previous-calendar-round-date}).
@end table
@cindex Mayan long count
To understand these commands, you need to understand the Mayan calendars.
The @dfn{long count} is a counting of days with these units:
@display
1 kin = 1 day@ @ @ 1 uinal = 20 kin@ @ @ 1 tun = 18 uinal
1 katun = 20 tun@ @ @ 1 baktun = 20 katun
@end display
@kindex g m @r{(Calendar mode)}
@findex calendar-mayan-goto-long-count-date
@noindent
Thus, the long count date 12.16.11.16.6 means 12 baktun, 16 katun, 11
tun, 16 uinal, and 6 kin. The Emacs calendar can handle Mayan long
count dates as early as 7.17.18.13.3, but no earlier. When you use the
@kbd{g m l} command, type the Mayan long count date with the baktun,
katun, tun, uinal, and kin separated by periods.
@findex calendar-mayan-previous-tzolkin-date
@findex calendar-mayan-next-tzolkin-date
@cindex Mayan tzolkin calendar
The Mayan tzolkin calendar is a cycle of 260 days formed by a pair of
independent cycles of 13 and 20 days. Since this cycle repeats
endlessly, Emacs provides commands to move backward and forward to the
previous or next point in the cycle. Type @kbd{g m p t} to go to the
previous tzolkin date; Emacs asks you for a tzolkin date and moves point
to the previous occurrence of that date. Similarly, type @kbd{g m n t}
to go to the next occurrence of a tzolkin date.
@findex calendar-mayan-previous-haab-date
@findex calendar-mayan-next-haab-date
@cindex Mayan haab calendar
The Mayan haab calendar is a cycle of 365 days arranged as 18 months
of 20 days each, followed by a 5-day monthless period. Like the tzolkin
cycle, this cycle repeats endlessly, and there are commands to move
backward and forward to the previous or next point in the cycle. Type
@kbd{g m p h} to go to the previous haab date; Emacs asks you for a haab
date and moves point to the previous occurrence of that date.
Similarly, type @kbd{g m n h} to go to the next occurrence of a haab
date.
@c This is omitted because it is too long for smallbook format.
@c @findex calendar-mayan-previous-calendar-round-date
@findex calendar-mayan-next-calendar-round-date
@cindex Mayan calendar round
The Maya also used the combination of the tzolkin date and the haab
date. This combination is a cycle of about 52 years called a
@emph{calendar round}. If you type @kbd{g m p c}, Emacs asks you for
both a haab and a tzolkin date and then moves point to the previous
occurrence of that combination. Use @kbd{g m n c} to move point to the
next occurrence of a combination. These commands signal an error if the
haab/tzolkin date combination you have typed is impossible.
Emacs uses strict completion (@pxref{Completion Exit}) whenever it
asks you to type a Mayan name, so you don't have to worry about
spelling.
@node Diary
@section The Diary
@cindex diary

View file

@ -1166,7 +1166,10 @@ conversion of this file. @xref{Coding Systems}.
@item
@code{unibyte} says to load or compile a file of Emacs Lisp in unibyte
mode, if the value is @code{t}. @xref{Disabling Multibyte}.
mode, if the value is @code{t}. @xref{Disabling Multibyte, ,
Disabling Multibyte Characters, elisp, GNU Emacs Lisp Reference
Manual}.
@end itemize
@noindent

View file

@ -544,7 +544,6 @@ Frames and Graphical Displays
International Character Set Support
* International Chars:: Basic concepts of multibyte characters.
* Disabling Multibyte:: Controlling whether to use multibyte characters.
* Language Environments:: Setting things up for the language you use.
* Input Methods:: Entering text characters not on your keyboard.
* Select Input Method:: Specifying your choice of input methods.
@ -798,6 +797,7 @@ Version Control
* Old Revisions:: Examining and comparing old versions.
* VC Change Log:: Viewing the VC Change Log.
* VC Undo:: Canceling changes before or after committing.
* VC Ignore:: Ignore files under version control system.
* VC Directory Mode:: Listing files managed by version control.
* Branches:: Multiple lines of development.
@ifnottex
@ -956,7 +956,6 @@ Conversion To and From Other Calendars
(aside from Gregorian).
* To Other Calendar:: Converting the selected date to various calendars.
* From Other Calendar:: Moving to a date specified in another calendar.
* Mayan Calendar:: Moving to a date specified in a Mayan calendar.
The Diary
@ -971,6 +970,7 @@ More advanced features of the Calendar and Diary
* Calendar Customizing:: Calendar layout and hooks.
* Holiday Customizing:: Defining your own holidays.
* Mayan Calendar:: Moving to a date specified in a Mayan calendar.
* Date Display Format:: Changing the format.
* Time Display Format:: Changing the format.
* Diary Customizing:: Defaults you can set.

View file

@ -40,13 +40,16 @@ Emacs provides a set of key bindings using this modifier key that mimic
other Mac / GNUstep applications (@pxref{Mac / GNUstep Events}). You
can change these bindings in the usual way (@pxref{Key Bindings}).
@c FIXME mention ns-alternate-modifier?
@vindex ns-alternate-modifier
@vindex ns-right-alternate-modifier
The variable @code{ns-right-alternate-modifier} controls the
behavior of the right @key{alt} and @key{option} keys. These keys
behave like the left-hand keys if the value is @code{left} (the
default). A value of @code{control}, @code{meta}, @code{alt},
@code{super}, or @code{hyper} makes them behave like the corresponding
modifier keys; a value of @code{none} tells Emacs to ignore them.
modifier keys; a value to @code{left} means be the same key as
@code{ns-alternate-modifier}; a value of @code{none} tells Emacs to
ignore them.
@kbd{S-Mouse-1} adjusts the region to the click position,
just like @kbd{Mouse-3} (@code{mouse-save-then-kill}); it does not pop

View file

@ -1,4 +1,4 @@
@c This is part of the Emacs manual.
@c This is part of the Emacs manual., Abbrevs, This is part of the Emacs manual., Top
@c Copyright (C) 1985-1987, 1993-1995, 1997, 1999-2013 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@ -56,6 +56,7 @@ variable @code{vc-handled-backends} to @code{nil}
* Old Revisions:: Examining and comparing old versions.
* VC Change Log:: Viewing the VC Change Log.
* VC Undo:: Canceling changes before or after committing.
* VC Ignore:: Ignore files under version control system.
* VC Directory Mode:: Listing files managed by version control.
* Branches:: Multiple lines of development.
@ifnottex
@ -1032,6 +1033,23 @@ unlocked; you must lock again to resume editing. You can also use
@kbd{C-x v u} to unlock a file if you lock it and then decide not to
change it.
@node VC Ignore
@subsection Ignore Version Control Files
@table @kbd
@item C-x v G
Ignore a file under current version control system. (@code{vc-ignore}).
@end table
@kindex C-x v G
@findex vc-ignore
Many source trees contain some files that do not need to be versioned,
such as editor backups, object or bytecode files, and built programs.
You can simply not add them, but then theyll always crop up as
unknown files. You can also tell the version control system to ignore
these files by adding them to the ignore file at the top of the tree.
@kbd{C-x v G} (@code{vc-ignore}) can help you do this.
@node VC Directory Mode
@subsection VC Directory Mode
@ -1222,7 +1240,7 @@ Revisions}), and @w{@kbd{C-x v u}} (@pxref{VC Undo}).
The VC Directory buffer also defines some single-key shortcuts for
VC commands with the @kbd{C-x v} prefix: @kbd{=}, @kbd{+}, @kbd{l},
@kbd{i}, @kbd{D}, @kbd{L} and @kbd{v}.
@kbd{i}, @kbd{D}, @kbd{L}, @kbd{G} and @kbd{v}.
For example, you can commit a set of edited files by opening a VC
Directory buffer, where the files are listed with the @samp{edited}

View file

@ -90,7 +90,6 @@ value to make sure Emacs interprets keyboard input correctly; see
@menu
* International Chars:: Basic concepts of multibyte characters.
* Disabling Multibyte:: Controlling whether to use multibyte characters.
* Language Environments:: Setting things up for the language you use.
* Input Methods:: Entering text characters not on your keyboard.
* Select Input Method:: Specifying your choice of input methods.
@ -244,79 +243,6 @@ Character code properties: customize what to show
decomposition: (65 768) ('A' '`')
@end smallexample
@c FIXME? Does this section even belong in the user manual?
@c Seems more appropriate to the lispref?
@node Disabling Multibyte
@section Disabling Multibyte Characters
By default, Emacs starts in multibyte mode: it stores the contents
of buffers and strings using an internal encoding that represents
non-@acronym{ASCII} characters using multi-byte sequences. Multibyte
mode allows you to use all the supported languages and scripts without
limitations.
@cindex turn multibyte support on or off
Under very special circumstances, you may want to disable multibyte
character support, for a specific buffer.
When multibyte characters are disabled in a buffer, we call
that @dfn{unibyte mode}. In unibyte mode, each character in the
buffer has a character code ranging from 0 through 255 (0377 octal); 0
through 127 (0177 octal) represent @acronym{ASCII} characters, and 128
(0200 octal) through 255 (0377 octal) represent non-@acronym{ASCII}
characters.
To edit a particular file in unibyte representation, visit it using
@code{find-file-literally}. @xref{Visiting}. You can convert a
multibyte buffer to unibyte by saving it to a file, killing the
buffer, and visiting the file again with @code{find-file-literally}.
Alternatively, you can use @kbd{C-x @key{RET} c}
(@code{universal-coding-system-argument}) and specify @samp{raw-text}
as the coding system with which to visit or save a file. @xref{Text
Coding}. Unlike @code{find-file-literally}, finding a file as
@samp{raw-text} doesn't disable format conversion, uncompression, or
auto mode selection.
@c Not a single file in Emacs uses this feature. Is it really worth
@c mentioning in the _user_ manual? Also, this duplicates somewhat
@c "Loading Non-ASCII" from the lispref.
@cindex Lisp files, and multibyte operation
@cindex multibyte operation, and Lisp files
@cindex unibyte operation, and Lisp files
@cindex init file, and non-@acronym{ASCII} characters
Emacs normally loads Lisp files as multibyte.
This includes the Emacs initialization
file, @file{.emacs}, and the initialization files of packages
such as Gnus. However, you can specify unibyte loading for a
particular Lisp file, by adding an entry @samp{coding: raw-text} in a file
local variables section. @xref{Specify Coding}.
Then that file is always loaded as unibyte text.
@ignore
@c I don't see the point of this statement:
The motivation for these conventions is that it is more reliable to
always load any particular Lisp file in the same way.
@end ignore
You can also load a Lisp file as unibyte, on any one occasion, by
typing @kbd{C-x @key{RET} c raw-text @key{RET}} immediately before
loading it.
@c See http://debbugs.gnu.org/11226 for lack of unibyte tooltip.
@vindex enable-multibyte-characters
The buffer-local variable @code{enable-multibyte-characters} is
non-@code{nil} in multibyte buffers, and @code{nil} in unibyte ones.
The mode line also indicates whether a buffer is multibyte or not.
@xref{Mode Line}. With a graphical display, in a multibyte buffer,
the portion of the mode line that indicates the character set has a
tooltip that (amongst other things) says that the buffer is multibyte.
In a unibyte buffer, the character set indicator is absent. Thus, in
a unibyte buffer (when using a graphical display) there is normally
nothing before the indication of the visited file's end-of-line
convention (colon, backslash, etc.), unless you are using an input
method.
@findex toggle-enable-multibyte-characters
You can turn off multibyte support in a specific buffer by invoking the
command @code{toggle-enable-multibyte-characters} in that buffer.
@node Language Environments
@section Language Environments
@cindex language environments
@ -919,18 +845,6 @@ pattern, are decoded correctly.
Unlike the previous two, this variable does not override any
@samp{-*-coding:-*-} tag.
@c FIXME? This seems somewhat out of place. Move to the Rmail section?
@vindex rmail-file-coding-system
When you get new mail in Rmail, each message is translated
automatically from the coding system it is written in, as if it were a
separate file. This uses the priority list of coding systems that you
have specified. If a MIME message specifies a character set, Rmail
obeys that specification. For reading and saving Rmail files
themselves, Emacs uses the coding system specified by the variable
@code{rmail-file-coding-system}. The default value is @code{nil},
which means that Rmail files are not translated (they are read and
written in the Emacs internal character code).
@node Specify Coding
@section Specifying a File's Coding System
@ -1591,15 +1505,13 @@ the range 0240 to 0377 octal (160 to 255 decimal) to handle the
accented letters and punctuation needed by various European languages
(and some non-European ones). Note that Emacs considers bytes with
codes in this range as raw bytes, not as characters, even in a unibyte
buffer, i.e., if you disable multibyte characters. However, Emacs
can still handle these character codes as if they belonged to
@emph{one} of the single-byte character sets at a time. To specify
@emph{which} of these codes to use, invoke @kbd{M-x
set-language-environment} and specify a suitable language environment
such as @samp{Latin-@var{n}}.
For more information about unibyte operation, see
@ref{Disabling Multibyte}.
buffer, i.e., if you disable multibyte characters. However, Emacs can
still handle these character codes as if they belonged to @emph{one}
of the single-byte character sets at a time. To specify @emph{which}
of these codes to use, invoke @kbd{M-x set-language-environment} and
specify a suitable language environment such as @samp{Latin-@var{n}}.
@xref{Disabling Multibyte, , Disabling Multibyte Characters, elisp,
GNU Emacs Lisp Reference Manual}.
@vindex unibyte-display-via-language-environment
Emacs can also display bytes in the range 160 to 255 as readable

View file

@ -1274,6 +1274,17 @@ It reads the name of a coding system, and then redecodes the message
using the coding system you specified. If you specified the right
coding system, the result should be readable.
@vindex rmail-file-coding-system
When you get new mail in Rmail, each message is translated
automatically from the coding system it is written in, as if it were a
separate file. This uses the priority list of coding systems that you
have specified. If a MIME message specifies a character set, Rmail
obeys that specification. For reading and saving Rmail files
themselves, Emacs uses the coding system specified by the variable
@code{rmail-file-coding-system}. The default value is @code{nil},
which means that Rmail files are not translated (they are read and
written in the Emacs internal character code).
@node Rmail Editing
@section Editing Within a Message

View file

@ -1,3 +1,7 @@
2013-08-02 Xue Fuqiao <xfq.free@gmail.com>
* emacs-lisp-intro.texi (zap-to-char): Remove obsolete stuff.
2013-07-06 Glenn Morris <rgm@gnu.org>
* emacs-lisp-intro.texi (Top):

View file

@ -7537,20 +7537,7 @@ retrieved. @xref{Yanking, , Yanking Text Back}.
@section @code{zap-to-char}
@findex zap-to-char
@c FIXME remove obsolete stuff
The @code{zap-to-char} function changed little between GNU Emacs
version 19 and GNU Emacs version 22. However, @code{zap-to-char}
calls another function, @code{kill-region}, which enjoyed a major
rewrite.
The @code{kill-region} function in Emacs 19 is complex, but does not
use code that is important at this time. We will skip it.
The @code{kill-region} function in Emacs 22 is easier to read than the
same function in Emacs 19 and introduces a very important concept,
that of error handling. We will walk through the function.
But first, let us look at the interactive @code{zap-to-char} function.
Let us look at the interactive @code{zap-to-char} function.
@menu
* Complete zap-to-char:: The complete implementation.

View file

@ -1,3 +1,20 @@
2013-08-02 Xue Fuqiao <xfq.free@gmail.com>
* display.texi (Face Functions): Add an index.
* variables.texi (Variable Aliases): Add an index.
* functions.texi (Defining Functions): Add an index.
* nonascii.texi (Coding System Basics): Add an index.
2013-07-31 Xue Fuqiao <xfq.free@gmail.com>
* nonascii.texi (Non-ASCII Characters): Update menu.
(Disabling Multibyte): Move here from doc/emacs/mule.texi. Fix cross-references.
* elisp.texi (Top): Update menu.
2013-07-30 Xue Fuqiao <xfq.free@gmail.com>
* windows.texi (Window History): Mention the default value of

View file

@ -2738,6 +2738,7 @@ differently from the default face.
@end defun
@cindex face alias
@cindex alias, for faces
A @dfn{face alias} provides an equivalent name for a face. You can
define a face alias by giving the alias symbol the @code{face-alias}
property, with a value of the target face name. The following example

View file

@ -1194,6 +1194,7 @@ Text Properties
Non-@acronym{ASCII} Characters
* Text Representations:: How Emacs represents text.
* Disabling Multibyte:: Controlling whether to use multibyte characters.
* Converting Representations:: Converting unibyte to multibyte and vice versa.
* Selecting a Representation:: Treating a byte sequence as unibyte or multi.
* Character Codes:: How unibyte and multibyte relate to

View file

@ -580,6 +580,7 @@ redefinition from unintentional redefinition.
@end defmac
@cindex function aliases
@cindex alias, for functions
@defun defalias name definition &optional doc
@anchor{Definition of defalias}
This function defines the symbol @var{name} as a function, with

View file

@ -13,6 +13,7 @@ how they are stored in strings and buffers.
@menu
* Text Representations:: How Emacs represents text.
* Disabling Multibyte:: Controlling whether to use multibyte characters.
* Converting Representations:: Converting unibyte to multibyte and vice versa.
* Selecting a Representation:: Treating a byte sequence as unibyte or multi.
* Character Codes:: How unibyte and multibyte relate to
@ -140,6 +141,55 @@ This function concatenates all its argument @var{bytes} and makes the
result a unibyte string.
@end defun
@node Disabling Multibyte
@section Disabling Multibyte Characters
@cindex disabling multibyte
By default, Emacs starts in multibyte mode: it stores the contents
of buffers and strings using an internal encoding that represents
non-@acronym{ASCII} characters using multi-byte sequences. Multibyte
mode allows you to use all the supported languages and scripts without
limitations.
@cindex turn multibyte support on or off
Under very special circumstances, you may want to disable multibyte
character support, for a specific buffer.
When multibyte characters are disabled in a buffer, we call
that @dfn{unibyte mode}. In unibyte mode, each character in the
buffer has a character code ranging from 0 through 255 (0377 octal); 0
through 127 (0177 octal) represent @acronym{ASCII} characters, and 128
(0200 octal) through 255 (0377 octal) represent non-@acronym{ASCII}
characters.
To edit a particular file in unibyte representation, visit it using
@code{find-file-literally}. @xref{Visiting Functions}. You can
convert a multibyte buffer to unibyte by saving it to a file, killing
the buffer, and visiting the file again with
@code{find-file-literally}. Alternatively, you can use @kbd{C-x
@key{RET} c} (@code{universal-coding-system-argument}) and specify
@samp{raw-text} as the coding system with which to visit or save a
file. @xref{Text Coding, , Specifying a Coding System for File Text,
emacs, GNU Emacs Manual}. Unlike @code{find-file-literally}, finding
a file as @samp{raw-text} doesn't disable format conversion,
uncompression, or auto mode selection.
@c See http://debbugs.gnu.org/11226 for lack of unibyte tooltip.
@vindex enable-multibyte-characters
The buffer-local variable @code{enable-multibyte-characters} is
non-@code{nil} in multibyte buffers, and @code{nil} in unibyte ones.
The mode line also indicates whether a buffer is multibyte or not.
With a graphical display, in a multibyte buffer, the portion of the
mode line that indicates the character set has a tooltip that (amongst
other things) says that the buffer is multibyte. In a unibyte buffer,
the character set indicator is absent. Thus, in a unibyte buffer
(when using a graphical display) there is normally nothing before the
indication of the visited file's end-of-line convention (colon,
backslash, etc.), unless you are using an input method.
@findex toggle-enable-multibyte-characters
You can turn off multibyte support in a specific buffer by invoking the
command @code{toggle-enable-multibyte-characters} in that buffer.
@node Converting Representations
@section Converting Text Representations
@ -962,6 +1012,7 @@ The value of the @code{:mime-charset} property is also defined
as an alias for the coding system.
@end defun
@cindex alias, for coding systems
@defun coding-system-aliases coding-system
This function returns the list of aliases of @var{coding-system}.
@end defun

View file

@ -1838,6 +1838,7 @@ updates this list.
@node Variable Aliases
@section Variable Aliases
@cindex variable aliases
@cindex alias, for variables
It is sometimes useful to make two variables synonyms, so that both
variables always have the same value, and changing either one also

View file

@ -1,3 +1,8 @@
2013-08-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus.texi (Basic Usage): Mention that warp means jump here.
(The notmuch Engine): Mention notmuch.
2013-07-30 Tassilo Horn <tsdh@gnu.org>
* gnus.texi (Sorting the Summary Buffer): Document new defcustom

View file

@ -21109,17 +21109,17 @@ the articles that match this query, and takes you to a summary buffer
showing these articles. Articles may then be read, moved and deleted
using the usual commands.
The @code{nnir} group made in this way is an @code{ephemeral} group, and
some changes are not permanent: aside from reading, moving, and
The @code{nnir} group made in this way is an @code{ephemeral} group,
and some changes are not permanent: aside from reading, moving, and
deleting, you can't act on the original article. But there is an
alternative: you can @emph{warp} to the original group for the article
on the current line with @kbd{A W}, aka
alternative: you can @emph{warp} (i.e., jump) to the original group
for the article on the current line with @kbd{A W}, aka
@code{gnus-warp-to-article}. Even better, the function
@code{gnus-summary-refer-thread}, bound by default in summary buffers to
@kbd{A T}, will first warp to the original group before it works its
magic and includes all the articles in the thread. From here you can
read, move and delete articles, but also copy them, alter article marks,
whatever. Go nuts.
@code{gnus-summary-refer-thread}, bound by default in summary buffers
to @kbd{A T}, will first warp to the original group before it works
its magic and includes all the articles in the thread. From here you
can read, move and delete articles, but also copy them, alter article
marks, whatever. Go nuts.
You say you want to search more than just the group on the current line?
No problem: just process-mark the groups you want to search. You want
@ -21161,6 +21161,7 @@ query language anyway.
* The swish++ Engine:: Swish++ configuration and usage.
* The swish-e Engine:: Swish-e configuration and usage.
* The namazu Engine:: Namazu configuration and usage.
* The notmuch Engine:: Notmuch configuration and usage.
* The hyrex Engine:: Hyrex configuration and usage.
* Customizations:: User customizable settings.
@end menu
@ -21390,6 +21391,26 @@ mknmz --mailnews ~/Mail/archive/ ~/Mail/mail/ ~/Mail/lists/
For maximum searching efficiency you might want to have a cron job run
this command periodically, say every four hours.
@node The notmuch Engine
@subsubsection The notmuch Engine
@table @code
@item nnir-notmuch-program
The name of the notmuch search executable. Defaults to
@samp{notmuch}.
@item nnir-notmuch-additional-switches
A list of strings, to be given as additional arguments to notmuch.
@item nnir-notmuch-remove-prefix
The prefix to remove from each file name returned by notmuch in order
to get a group name (albeit with @samp{/} instead of @samp{.}). This
is a regular expression.
@end table
@node The hyrex Engine
@subsubsection The hyrex Engine
This engine is obsolete.

View file

@ -1,3 +1,27 @@
2013-08-03 Juanma Barranquero <lekktu@gmail.com>
* NEWS: Document new package frameset.el.
2013-08-03 Xue Fuqiao <xfq.free@gmail.com>
* TODO: Adjust entry about bug reporting.
2013-08-02 Bastien Guerry <bzg@gnu.org>
* DEVEL.HUMOR: New entry.
2013-08-02 Xue Fuqiao <xfq.free@gmail.com>
* tutorials/TUTORIAL: Remove a redundant sentence about yanking.
* tutorials/TUTORIAL.cn: Update; synchronize with TUTORIAL.
* tutorials/TUTORIAL.translators (Maintainer): Update the maintainer.
2013-08-02 Juanma Barranquero <lekktu@gmail.com>
* tutorials/TUTORIAL.es: Fix typos (bug#15000).
2013-07-26 Micah Anderson <micah@riseup.net> (tiny change)
* spook.lines: Additions. (Bug#14658)

View file

@ -194,3 +194,11 @@ drivers?"
depression or loneliness when it is left out of the picture, so I
wouldn't worry about it too much."
-- Lennart Borgman and Jason Rumney
----------------------------------------------------------------------
"... a non-CS-educated guy like me ..."
"Kind of late, but thanks for letting us know. I've just revoked your
write access to the repository for the obvious safety reasons,"
-- Bastien Guerry and Stefan Monnier

View file

@ -233,11 +233,16 @@ The default separator is changed to allow surrounding spaces around the comma.
*** New variable `diary-from-outlook-function', used by the command
`diary-from-outlook'.
** VC Directory Mode
** VC and related modes
*** `D' displays diffs between VC-controlled whole tree revisions.
*** `L' lists the change log for the current VC controlled tree in a window.
*** `I' ignores the file under current version control system.
*** In VC directory mode, `D' displays diffs between VC-controlled
whole tree revisions.
*** In VC directory mode, `L' lists the change log for the current VC
controlled tree in a window.
*** `C-x v G' (globally) and `G' (in VC directory mode) ignores a
file under current version control system.
** cl-lib
@ -269,8 +274,8 @@ auto-saves of the desktop.
*** `desktop-restore-frames', enabled by default, allows saving and
restoring the window/frame configuration. Additional options
`desktop-restore-in-current-display' and
`desktop-restoring-reuses-frames' allow further customization.
`desktop-restore-in-current-display', `desktop-restore-reuses-frames'
and `desktop-restore-forces-onscreen' allow further customization.
** Dired
@ -511,6 +516,12 @@ It is layered as:
- advice-add/advice-remove to add/remove a piece of advice on a named function,
much like `defadvice' does.
** New frameset.el package.
It provides a set of operations to save a frameset (the state of all
or a subset of the existing frames and windows, somewhat similar to a
frame configuration), both in-session and persistently, and restore it
at some point in the future.
+++
** The package filenotify.el provides an interface for file system
notifications. It requires, that Emacs is compiled with one of the
@ -519,6 +530,8 @@ low-level libraries gfilenotify.c, inotify.c or w32notify.c.
* Incompatible Lisp Changes in Emacs 24.4
** `defvar' and `defcustom' in a let-binding affect the "external" default.
** The syntax of ?» and ?« is now punctuation instead of matched parens.
Some languages match those as »...« and others as «...» so better stay neutral.

View file

@ -176,6 +176,15 @@ where <device> is the network device found under the first key.
** Check for any included packages that define obsolete bug-reporting commands.
Change them to use report-emacs-bug.
*** Related functions:
**** gnus-bug
**** report-calc-bug
**** org-submit-bug-report
**** lm-report-bug
**** tramp-bug
**** c-submit-bug-report
**** ffap-bug and ffap-submit-bug (obsoleted)
[Do all of them need changing?]
** Allow fringe indicators to display a tooltip (provide a help-echo property?)

View file

@ -372,13 +372,15 @@ the text between the two positions.
The difference between "killing" and "deleting" is that "killed" text
can be reinserted (at any position), whereas "deleted" things cannot
be reinserted in this way (you can, however, undo a deletion--see below).
Reinsertion of killed text is called "yanking". Generally, the
commands that can remove a lot of text kill the text (they are set up so
that you can yank the text), while the commands that remove just one
character, or only remove blank lines and spaces, do deletion (so you
cannot yank that text). <DEL> and C-d do deletion in the simplest
case, with no argument. When given an argument, they kill instead.
be reinserted in this way (you can, however, undo a deletion--see
below). Reinsertion of killed text is called "yanking". (Think of it
as yanking back, or pulling back, some text that was taken away.)
Generally, the commands that can remove a lot of text kill the text
(they are set up so that you can yank the text), while the commands
that remove just one character, or only remove blank lines and spaces,
do deletion (so you cannot yank that text). <DEL> and C-d do deletion
in the simplest case, with no argument. When given an argument, they
kill instead.
>> Move the cursor to the beginning of a line which is not empty.
Then type C-k to kill the text on that line.
@ -391,13 +393,12 @@ treats a numeric argument specially: it kills that many lines AND
their contents. This is not mere repetition. C-u 2 C-k kills two
lines and their newlines; typing C-k twice would not do that.
Reinserting killed text is called "yanking". (Think of it as yanking
back, or pulling back, some text that was taken away.) You can yank
the killed text either at the same place where it was killed, or at
some other place in the text you are editing, or even in a different
file. You can yank the same text several times; that makes multiple
copies of it. Some other editors call killing and yanking "cutting"
and "pasting" (see the Glossary in the Emacs manual).
You can yank the killed text either at the same place where it was
killed, or at some other place in the text you are editing, or even in
a different file. You can yank the same text several times; that
makes multiple copies of it. Some other editors call killing and
yanking "cutting" and "pasting" (see the Glossary in the Emacs
manual).
The command for yanking is C-y. It reinserts the last killed text,
at the current cursor position.

View file

@ -14,8 +14,9 @@ META 键(有时候用 EDIT 或 ALT 来标示)。为了避免每次都要写
先按一下 ESC 键然后放开,再输入 <chr>。我们用 <ESC> 来表示
ESC 键。
重要提示:要退出 Emacs请用 C-x C-c两个连续的组合键。下文中左边顶
行的“>>”字样用来提示你尝试键盘命令。比如:
重要提示:要退出 Emacs请用 C-x C-c两个连续的组合键
要退出一个正在运行中的命令,请用 C-g。
下文中左边顶行的“>>”字样用来提示你尝试键盘命令。比如:
<<Blank lines inserted around following line by help-with-tutorial>>
[本页当中特意留出一些空白是出于教学目的,请继续往后阅读]
>> 现在输入 C-v (查看下一屏文字)移动到下一屏。
@ -43,7 +44,9 @@ META、EDIT 或 ALT 键那么就先按 <ESC> 再按 v
(注意是 CONTROL-L不是 CONTROL-1
>> 找到光标,留意其附近的文字,然后输入 C-l。
找找光标在哪里,你会发现其附近的文字并没有变化。
找找光标在哪里,你会发现其附近的文字与之前相同,位置却变为屏幕的中心。
如果你再次输入 C-l ,附近的文字将移动到屏幕的顶端。再次输入 C-l
文字将移动到底端。
如果你的键盘上有 PageUp 和 PageDn也可以用这两个键来滚屏。不过使用
C-v 和 M-v 的效率要更高一些。
@ -78,8 +81,8 @@ P 代表 previous上一行N 代表 next下一行B 代表 backw
>> 用 C-f 把光标移动到这一行,然后再用 C-p 往上挪。
注意观察当光标在一行的中央时 C-p 命令的行为。
每行文字都以一个“换行符”结束,“换行符”把行与行区分开来。文件的最后
行也应该也有一个换行符(不过 Emacs 并不强制要求这一点)。
每行文字都以一个“换行符”结束,“换行符”把行与行区分开来。(通常情况下,
个文件的最后一行会有一个换行符,但是 Emacs 不强制要求这一点。)
>> 在一行的行头输入 C-b。
光标应该会移动到前一行的行尾,因为光标在回退过程中越过了换行符。
@ -179,27 +182,20 @@ EDIT 或 ALT那么还有另一种办法按住 META 键不放,然
标志――只要给出有一个前缀参数,不管其值为何,它都会改变命令的功能。
而 C-v 和 M-v 则属于另一种类型的例外。当给定一个参数时,它们将滚动你指
定的“行数”而不是“屏数”。举例来说C-u 8 C-v 将屏幕向下滚动 8 行,
而不是 8 屏。
定的“行数”而不是“屏数”。举例来说C-u 8 C-v 将文本向下滚动 8 行。
>> 现在试试看,输入 C-u 8 C-v。
这个命令应该已经将文字向上滚动了 8 行。如果你想将它再次地向下滚动,你可
以给定一个参数然后执行 M-v。
如果你正在使用一个窗口系统,比如 X11 或者微软的 Windows那么在 Emacs
口的边应该有一个长方形的区域叫“滚动条”,你可以用鼠标操纵滚动条来
滚动文字。
如果你正在使用图形界面,比如 X 或者微软的 Windows那么在 Emacs窗
口的边应该有一个长方形的区域叫“滚动条”。你可以用鼠标操纵滚动条来滚动
文字。
>> 试着在“滚动条内的反白区域”上按一下鼠标中键。
文字应该会滚动到鼠标所指示的位置。
如果你的鼠标有滚轮的话,你也可以使用滚轮来滚动。
>> 当按住中键时,试着将鼠标上下移动。
你会看到文字随着鼠标的移动而上下滚动。
【Windows 版本符合 Windows 程序的传统操作习惯,上述操作不适用。】
* 在 EMACS 失去响应的时候WHEN EMACS IS HUNG
* 如果 EMACS 失去响应IF EMACS STOPS RESPONDING
-----------------------------------------------
如果 Emacs 对你的命令失去响应,你可以用 C-g 来安全地终止这条命令。C-g
@ -234,7 +230,7 @@ C-g 还可以取消数字参数和只输入到一半的命令。
* 窗格WINDOWS
-----------------
Emacs 可以有多个窗格,每个窗格显示不同的文字。后面会介绍怎么对付多个窗
Emacs 可以有多个窗格,每个窗格显示不同的文字。后面会介绍怎么对付多个窗
格,现在我们先学会如何关掉多余的窗格。其实也很简单:
C-x 1 只保留一个窗格(也就是关掉其它所有窗格)。
@ -244,49 +240,46 @@ Emacs 可以有多个窗格,每个窗格显示不同的文字。后面会介
>> 把光标移到本行然后输入 C-u 0 C-l。
>> 输入 CONTROL-h k CONTROL-f。观察当一个新窗格出现时当前窗格用来显示
CONTROL-f 命令的文档)是如何缩小的。
>> 输入 C-h k C-f。观察当一个新窗格出现时当前窗格用来显示
C-f 命令的文档)是如何缩小的。
>> 输入 C-x 1 关掉文档窗格。
这个命令跟先前学过的命令不太一样,因为它包含了两个字符,以 CONTROL-x 开
始。有一系列命令都是以 CONTROL-x 开始的,这些命令许多都跟“窗格、文件、
缓冲区【缓冲区buffer会在后文详细介绍】”等等诸如此类的东西有关
中有些命令可能包含了 2 个、3 个或者 4 个字符。
有一系列命令是以 CONTROL-x 开始的,这些命令许多都跟“窗格、文件、缓冲区
【缓冲区buffer会在后文详细介绍】”等等诸如此类的东西有关其中有些
命令可能包含了 2 个、3 个或者 4 个字符。
* 插入与删除INSERTING AND DELETING
--------------------------------------
插入文字很简单,直接敲键盘就可以了。你能看到的字符,比如 A、7、* 等等,
都被 Emacs 视为文字并且可以直接插入。敲 <Return>(回车键)会插入一个换
行符
插入文字很简单,直接敲键盘就可以了。普通的字符,比如 A、7、* 等等,会
随着你的输入而插入。要插入一个换行符,输入 <Return>(这个键在键盘上有
时会被标注成“Enter”
你可以用 <Delback> 来删除最后输入的一个字符,这个跟你在 Emacs 之外的用
法应该一样。一般来说 <Delback> 就是位于 <Return> 键上方某处的一个大块头
的键通常被标示为“Delete”、“Del”或者“Backspace”。
你可以用 <DEL> 来删除光标左边的字符这个键通常被标注为“Backspace”――跟
你在 Emacs 之外的用法应该一样,删除最后一个输入的字符。
如果你找到了“Backspace”键那么它应该就是 <Delback>;这时哪怕你又在别
的地方找到了一个“Del”键那么它也应该不是 <Delback>。
你的键盘上可能有另外一个键,标注着 <Delete>,但那个不是我们所说的 <DEL>。
一种更通用的说法是,<Delback> 将删除位于光标前的一个字符。
>> 现在就来试试――敲点字,然后按几下 <Delback> 删除它们。
>> 现在就来试试――敲点字,然后按几下 <DEL> 删除它们。
不用担心文件被修改,你做什么都没关系,这里就是专给你练习用的。
如果一行文字很长、超出了窗格的宽度,显示不下的部分会在紧邻的下一行继续
显示。这时会有一个反斜线(在控制台下是反斜线,如果你用图形窗口系统,则
应该是一个小小的转弯箭头)显示在右边沿,表明这是某一行的接续显示。
显示。如果你使用的是图形界面,文本区域两边的狭窄区域(左右“边缘”)会出
现小小的转弯箭头,表明这是某一行的接续显示。如果你使用的是文本终端,接
续显示由屏幕最右边一列的一个反斜线来表示。
>> 输入文字,一直到屏幕的右边界,然后继续,你会看到一个接续行出现。
>> 输入文字,一直到屏幕的右边界,然后继续。
你会看到一个接续行出现。
>> 用 <Delback> 删掉一些文字,直到此行长度小于窗格宽度,接续行就消失了。
>> 用 <DEL> 删掉一些文字,直到此行长度小于窗格宽度,接续行就消失了。
换行符跟其它字符一样可以被删除。两行中间的换行符被删除后,这两行将会合
并成一行。如果合并后的这一行太长,超出了窗格宽度,它就会以一个接续行来
显示。
>> 移动光标到某行的开头并输入 <Delback>。
>> 移动光标到某行的开头并输入 <DEL>。
这时该行将与其前一行一起被合并为一行。
>> 输入 <Return> 重新插入你刚才删除的换行符。
@ -299,10 +292,10 @@ Emacs 可以有多个窗格,每个窗格显示不同的文字。后面会介
好,现在你应该已经掌握了最基本的的文本插入和修改功能,其实删除还可以
“以词为单位”进行,下面是一个关于“删除”操作的小结:
<Delback> 删除光标前的一个字符
<DEL> 删除光标前的一个字符
C-d 删除光标后的一个字符
M-<Delback> 移除光标前的一个词
M-<DEL> 移除光标前的一个词
M-d 移除光标后的一个词
C-k 移除从光标到“行尾”间的字符
@ -311,29 +304,31 @@ Emacs 可以有多个窗格,每个窗格显示不同的文字。后面会介
【可能你已经注意到了“删除delete”和“移除kill”的用词区别
文会有详细说明。】
注意“<Delback> 和 C-d”还有“M-<Delback> 和 M-d”是根据前述惯例从 C-f
和 M-f 衍生出来的(其实<Delback>不是控制字符我们先忽略这一点。C-k
和 M-k 的关系在某种程度上与 C-e 和 M-e 一样――如果把“一行”和“一句”
作一个类比的话。
注意“<DEL> 和 C-d”还有“M-<DEL> 和 M-d”是根据前述惯例从 C-f和 M-f 衍生
出来的(其实<DEL>不是控制字符我们先忽略这一点。C-k和 M-k 的关系在
某种程度上与 C-e 和 M-e 一样――如果把“一行”和“一句”作一个类比的话。
你也可以用一种通用的办法来移除缓冲区里的任何一部分:首先把光标移动到你
想要移除的区域的一端,然后按 C-@ 或 C-SPC任一即可SPC指空格【注意
C-SPC 往往被中文用户设定成输入法热键如果这样C-SPC 就被系统拦截而无
法传递给 Emacs 了因此这里还是推荐使用C-@。】,然后将光标移动到另一端,
再按 C-w 就可以把位于这两点之间的所有文字移除了。
想要移除的区域的一端,然后按 C-<SPC><SPC>指空格【注意C-<SPC> 往
往被中文用户设定成输入法热键如果这样C-<SPC> 就被系统拦截而无法传递
给 Emacs 了在这种情况下可以使用C-@。】,然后将光标移动到你准备移除的
文字的另一端。这个时候, Emacs 会高亮光标和你按下 C-<SPC> 之间的文本。
最后,按下 C-w 。这样就可以把位于这两点之间的所有文字移除了。
>> 移动光标到上一段开头的“你”字。
>> 输入 C-@ 。Emacs 应该会在屏幕的下方显示一个“Mark set”的消息。
>> 输入 C-<SPC> 。Emacs 应该会在屏幕的下方显示一个“Mark set”的消息。
>> 移动光标到第二行中的“端”字。
>> 输入 C-w从“你”开始到“端”之前的文字被全部移除。
注意,“移除kill”和“删除delete”的不同在于被移除的东西可以找回
来,而被删除的就不行了。【实际上,移除掉的东西虽然看起来“消失”了,但
实际上被 Emacs 记录了下来,因此还可以找回来;而删除掉的东西虽然也可能还
在内存里,但是已经被 Emacs“抛弃”了所以就找不回来了。】重新插入被移
除的文字称为“召回yank”。一般而言那些可能消除很多文字的命令会把
消除掉的文字记录下来(它们被设定成了“可召回”),而那些只消除一个字符
或者只消除空白的命令就不会记录被消除的内容(自然你也就无法召回了)。
注意,“移除kill”和“删除delete”的不同在于被移除的东西可以被重新
插入(在任何位置),而被删除的就不能使用相同的方法重新插入了(不过可以
通过撤销一个删除命令来做到,后文会提到)。【实际上,移除掉的东西虽然看
起来“消失”了,但实际上被 Emacs 记录了下来,因此还可以找回来;而删除掉
的东西虽然也可能还在内存里,但是已经被 Emacs“抛弃”了所以就找不回来
了。】重新插入被移除的文字称为“召回yank”。一般而言那些可能消除很
多文字的命令会把消除掉的文字记录下来(它们被设定成了“可召回”),而那些
只消除一个字符或者只消除空白的命令就不会记录被消除的内容(自然你也就无
法召回了)。
>> 移动光标到一非空白行的行头,然后输入 C-k 移除那一行上的文字。
@ -345,9 +340,10 @@ C-SPC 往往被中文用户设定成输入法热键如果这样C-SPC 就
C-k 会把两行以及它们的换行符移除;而如果只是输入 C-k 两次显然不是这个结
果。
被移除的文字恢复的动作称为“召回yanking”。就好像把别人从你身边
重新插入被移除的文字恢复的动作称为“召回yanking”。就好像把别人从你身边
移走的东西又猛力地拉回来。)你可以在你删除文字的地方召回,也可以在别的
地方召回,还可以多次召回同样的文字以得到它的多个拷贝。
地方召回,还可以多次召回同样的文字以得到它的多个拷贝。很多其它的编辑器
把移除和召回叫做“剪切”和“粘贴” (详情可见 Emacs 使用手册里的术语表)。
召回的命令是 C-y。它会在光标所在处插入你最后移除的文字。
@ -383,24 +379,23 @@ C-y 可以召回最近一次移除的内容,那如何召回前几次移除的
* 撤销UNDO
--------------
如果你修改了一段文字,又觉得改得不好,可以用 undo 命令进行撤销:
C-x u。
如果你修改了一段文字,又觉得改得不好,可以用 undo 命令进行撤销C-/。
通常 C-x u 会消除一个命令所造成的所有改变;如果你在一行中连续多次地使用
C-x u,你会把以前的命令也依次撤销。
通常 C-/ 会消除一个命令所造成的所有改变;如果你在一行中连续多次地使用
C-/,你会把以前的命令也依次撤销。
但是有两个例外:
1 没有改变文字的命令不算(包括光标移动命令和滚动命令)
2 从键盘输入的字符以组为单位――每组 20 个字符――来进行处理。
(这是为了减少你在撤销“插入文字”动作时需要输入 C-x u 的次数)
2 从键盘输入的字符以组为单位――每组最多 20 个字符――来进行处理。
(这是为了减少你在撤销“插入文字”动作时需要输入 C-/ 的次数)
>> 用 C-k 将这一行移除,然后输入 C-x u ,它会再次出现。
>> 用 C-k 将这一行移除,然后输入 C-/ ,它会再次出现。
C-_ 也是撤销命令;它的作用跟 C-x u 一样但是它比较容易多次输入。C-_ 的
缺点是在某些键盘上可能不太容易按,这也正是我们同时提供 C-x u 的原因。在
某些终端上,你可以按住 CONTROL 再按“/”来输入 C-_
C-_ 也是撤销命令;它的作用跟 C-/ 一样,但是它比较容易多次输入。在
某些终端上,输入 C-/ 实际上向 Emacs 发送的是 C-_ 。
另外, C-x u 和 C-/ 完全一样,但是按起来有些麻烦
数字参数对于 C-_ 和 C-x u 的意义是执行撤销的重复次数。
数字参数对于 C-/ 、 C-_ 和 C-x u 的意义是执行撤销的重复次数。
* 文件FILE
@ -416,14 +411,13 @@ C-_ 也是撤销命令;它的作用跟 C-x u 一样,但是它比较容易多
文件也保存到计算机上。在存盘的时候Emacs 会把存盘前的文件重命名保存,
以防你改完之后又想反悔。
在屏幕的下方,你应该能够看到头尾都是短线“-”的一行,行首通常是一些诸如
“--:-- TUTORIAL.cn”的文字这些文字代表了你当前正在访问的文件。比如你
现在正在访问的文件叫“TUTORIAL.cn”它只是一个给你临时使用的拷贝。每当
Emacs 寻找到一个文件,文件名就会出现在这个位置。
在屏幕的下方,你应该能够看到头部有短线“-”的一行,行首通常是一些诸如
-:--- TUTORIAL.cn”的文字这些文字代表了你当前正在访问的文件。比如你
在正在访问的文件是对 Emacs 快速指南的一份临时拷贝叫做“TUTORIAL.cn”。
每当Emacs 寻找到一个文件,文件名就会出现在这个位置。
寻找文件的命令有一个特点,那就是你必须给出文件名。我们称这个命令“从终
端读入了一个参数”(在这里,这个参数显然就是文件名)。在你输入这条命令
之后:
寻找文件的命令有一个特点,那就是你必须给出文件名。我们称这个命令“读入
了一个参数”(在这里,这个参数显然就是文件名)。在你输入这条命令之后:
C-x C-f 寻找一个文件
@ -437,10 +431,10 @@ Emacs 会提示你输入文件名。你输入的文件名会出现在屏幕最
这会关掉小缓冲,同时也会取消使用小缓冲的 C-x C-f 命令。
当然了,你也没有找任何文件。
用 <Return> 结束文件名的输入。这之后 C-x C-f 命令开始工作并找到你指定的
文件。小缓冲在 C-x C-f 命令结束之后也会消失。
用 <Return> 结束文件名的输入。之后小缓冲会消失C-x C-f 将会去寻找你
指定的文件。小缓冲在 C-x C-f 命令结束之后也会消失。
眨眼间文件被显示在屏幕上,你可以开始编辑了。存盘用这条命令:
文件被显示在屏幕上,你可以开始编辑了。存盘用这条命令:
C-x C-s 储存这个文件
@ -450,15 +444,16 @@ Emacs 会提示你输入文件名。你输入的文件名会出现在屏幕最
M-x customize-variable <Return> make-backup-files <Return>】
存盘结束后Emacs 会显示写入文件的文件名。你最好养成经常存盘的习惯,这
可以减少系统崩溃和死机给你带来的损失。
可以减少系统崩溃和死机给你带来的损失(也可参见下面的“自动保存”一节)
>> 输入 C-x C-s 把本快速指南存下来。
你会在屏幕的下方看到一条消息“Wrote ...TUTORIAL.cn”。
>> 输入 C-x C-s TUTORIAL.cn <Return> 。
这将会把该指南保存为一个名为 TUTORIAL.cn 的文件,并且在屏幕的下方显
示一条消息“Wrote ...TUTORIAL.cn”。
你不但可以寻找一个已有的文件来查看或编辑,还可以寻找一个不存在的文件。
实际上这正是 Emacs 创建新文件的方法:找到不存在的新文件。只有在存盘的时
Emacs 才会真正创建这个文件。而在这之后的一切就跟编辑一个已有文件没
有区别了。
实际上这正是 Emacs 创建新文件的方法:找到不存在的新文件。事实上,只有
在存盘的时Emacs 才会真正创建这个文件。而在这之后的一切就跟编辑一个
已有文件没有区别了。
* 缓冲区BUFFER
@ -468,10 +463,6 @@ Emacs 会提示你输入文件名。你输入的文件名会出现在屏幕最
切回第一个文件,一种办法是再用一次 C-x C-f。这样你就可以在 Emacs 中同
时打开多个文件。
>> 用 C-x C-f foo <Return> 的方式建立一个名为“foo”的文件。
输入一些文字,再用 C-x C-s 保存文件“foo”。
最后,输入 C-x C-f TUTORIAL.cn <Return> 回到这里。
Emacs 把每个编辑中的文件都放在一个称为“缓冲区buffer”的地方。每寻
找到一个文件Emacs 就在其内部开辟一个缓冲区。用下面的命令可以列出当前
所有的缓冲区:
@ -490,24 +481,28 @@ Emacs 把每个编辑中的文件都放在一个称为“缓冲区buffer
C-x C-f 是一种办法。不过还有一个更简单的办法,那就是用 C-x b。用这条命
令,你必须输入缓冲区的名称。
>> 输入 C-x b foo <Return> 以回到文件“foo”的缓冲区
>> 通过输入 C-x C-f foo <Return> 创建一个名为“foo”的文件
然后输入 C-x b TUTORIAL.cn <Return> 回到这里。
大多数情况下,缓冲区与跟其对应的文件是同名的(不包括目录名),不过这也
不是绝对的。用 C-x C-b 得到的缓冲区列表总是显示缓冲区名。
你在 Emacs 窗格里看到的“任何”文字都一定属于某个缓冲区。然而,缓冲区未
必有对应文件:比如显示缓冲区列表的缓冲区就是这样。再比如“*Messages*”
缓冲区也没有对应文件,这个缓冲区里存放的都是在 Emacs 底部出现的消息。
缓冲区未必有对应文件。显示缓冲区列表的缓冲区(叫做“*Buffer List*”)就
是这样。这个 TUTORIAL.cn 缓冲区起初没有对应的文件,但是现在有了,因为
在前一节你输入了 C-x C-s 将它保存成了一个文件。
“*Messages*”缓冲区也没有对应文件,这个缓冲区里存放的都是在 Emacs 底部
出现的消息。
>> 输入 C-x b *Messages* <Return> 瞅瞅消息缓冲区里都有什么东西。
然后再输入 C-x b TUTORIAL.cn <Return> 回到这里。
如果你对某个文件做了些修改,然后切换到另一个文件,这个动作并不会帮你把
前一个文件存盘。对第一个文件的修改仍然仅存在于 Emacs 中,也就是在它对应
的缓冲区里。并且,对第二个文件的修改也不会影响到第一个文件。这很有用,
但是也挺麻烦:因为如果你想要存储第一个文件,还需要先 C-x C-f 切换回去再
用 C-x C-s 存盘。你需要一个更简便的方法,而 Emacs 已经为你准备好了:
前一个文件存盘。对第一个文件的修改仍然仅存在于 Emacs 中,也就是在它对
应的缓冲区里。并且,对第二个文件的修改也不会影响到第一个文件。这很有用,
但也意味着你需要一个简便的办法来保存第一个文件的缓冲区。先切换回那个缓
冲区,再用 C-x C-s 存盘,太麻烦了。你需要一个更简便的方法,而 Emacs 已
经为你准备好了:
C-x s 保存多个缓冲区
@ -532,21 +527,18 @@ Emacs 的命令就像天上的星星,数也数不清。把它们都对应到 C
很多扩展命令都相当有用,虽然与你已经学过的命令比起来,他们可能不那么常
用。我们早已经见过一些扩展命令了,比如用 C-x C-f 寻找文件和用 C-x C-s
保存文件;退出 Emacs 用的 C-x C-c 也是扩展命令。(不用担心退出 Emacs 会
给你带来什么损失Emacs 会在退出之前提醒你存盘的)
给你带来什么损失Emacs 会在退出之前提醒你存盘的
在控制台下C-z 可以暂时离开 Emacs――当然你还可以再回来。
如果你使用图形界面,你不需要任何特殊的命令来切换 Emacs 和其他应用程序。
你可以使用鼠标或者窗口管理器的命令。然而,如果你使用只能同时显示一个应
用程序的文本终端,你需要“挂起” Emacs ,以切换到其他的应用程序。
在允许 C-z 的系统中C-z 会把 Emacs“挂起”也就是说它会回到 shell
但不退出 Emacs。在常用的 shell 中通常可以用“fg”或者“%emacs”命令再
次回到 Emacs 中。
C-z 可以暂时离开 Emacs――当然你还可以再回来。在允许 C-z 的系统中C-z
会把 Emacs“挂起”也就是说它会回到 shell但不杀死 Emacs 的进程。在常
用的 shell 中通常可以用“fg”或者“%emacs”命令再次回到 Emacs 中。
在没有提供挂起功能的系统中C-z 会在 Emacs 之下创建一个子 shell 来让你
运行其它程序并且再次“回到”Emacs 中――虽然我们并没有真正离开过。这
种情况下,通常用 shell 命令“exit”从子 shell 回到 Emacs。
你最好在打算退出登陆的时候再用 C-x C-c。在 Emacs 被诸如邮件处理程序之类
的外部程序调用之后,也可以用 C-x C-c 退出。不过一般来讲,如果你不想退出
登录,最好还是把 Emacs 挂起而不是退出。
你最好在打算退出登陆的时候再用 C-x C-c。在把 Emacs 当做一个临时的编辑
器的时候(比如被一个邮件处理程序调用),也可以用 C-x C-c 退出。
C-x 的扩展命令有很多,下面列出的是你已经学过的:
@ -557,11 +549,11 @@ C-x 的扩展命令有很多,下面列出的是你已经学过的:
C-x 1 关掉其它所有窗格,只保留一个。
C-x u 撤销。
用命令名扩展的命令通常并不常用,或只用在部分模式下。比如 replace-string
(字符串替换)这个命令,它会在全文范围内把一个字符串替换成另一个。在
入 M-x 之后Emacs 会在屏幕底端向你询问并等待你输入命令名。如果你想输入
“replace-string”其实只需要敲“repl s<TAB>”就行了Emacs 会帮你自
补齐。输入完之后按 <Return> 。
用命令名扩展的命令通常并不常用,或只用在部分模式下。比如
replace-string(字符串替换)这个命令,它会把一个字符串替换成另一个。在
入 M-x 之后Emacs 会在屏幕底端向你询问并等待你输入命令名。如果你想
输入“replace-string”其实只需要敲“repl s<TAB>”就行了Emacs 会帮你自
补齐。输入完之后按 <Return> 提交
字符串替换命令需要两个参数――被替换的字符串和用来替换它的字符串。每个
参数的输入都以换行符来结束。
@ -586,8 +578,8 @@ C-x 的扩展命令有很多,下面列出的是你已经学过的:
“#hello.c#”。这个文件会在正常存盘之后被 Emacs 删除。
所以,假如不幸真的发生了,你大可以从容地打开原来的文件(注意不是自动保
存文件)然后输入 M-x recover file<Return> 来恢复你的自动保存文件。在
示确认的时候,输入 yes<Return>。
存文件)然后输入 M-x recover file <Return> 来恢复你的自动保存文件。在
示确认的时候,输入 yes<Return>。
* 回显区ECHO AREA
@ -602,7 +594,7 @@ C-x 的扩展命令有很多,下面列出的是你已经学过的:
位于回显区正上方的一行被称为“状态栏”。状态栏上会显示一些信息,比如:
--:** TUTORIAL.cn (Fundamental)--L670--54%----------------
-:**- TUTORIAL.cn 63% L749 (Fundamental)
状态栏显示了 Emacs 的状态和你正在编辑的文字的一些信息。
@ -631,7 +623,7 @@ Emacs 的主模式林林总总。有用来编辑程序代码的――比如 Lisp
编辑自然语言文本――比如现在――应该用 Text 模式。
>> 输入 M-x text mode<Return>。
>> 输入 M-x text-mode <Return>。
别担心什么都没变。不过细心一些可以发现M-f 和 M-b 现在把单引号('
视为词的一部分了。而在先前的 Fundamental 模式中M-f 和 M-b 都将单引号
@ -643,7 +635,8 @@ Emacs 里得到了很好的体现】
用 C-h m 可以查看当前主模式的文档。
>> 用 C-u C-v 将本行带到屏幕的最上方。
>> 把光标移动到下一行。
>> 用 C-l C-l 将本行带到屏幕的最上方。
>> 输入 C-h m看看 Text 模式与 Fundamental 模式有哪些不同。
>> 输入 C-x 1 关掉文档窗格。
@ -655,12 +648,12 @@ mode存在。辅模式并不能替代主模式而是提供一些辅助的
有一个叫做自动折行Auto Fill的辅模式很有用特别是在编辑自然语言文本
的时候。启用自动折行后Emacs 会在你打字超出一行边界时自动替你换行。
用 M-x auto fill mode<Return> 启动自动折行模式。再用一次这条命令,自
折行模式会被关闭。也就是说,如果自动折行模式没有被开启,这个命令会开
它;如果已经开启了,这个命令会关闭它。所以我们说,这个命令可以用来“开
toggle”模式。
用 M-x auto-fill-mode <Return> 启动自动折行模式。再用一次这条命令,自
折行模式会被关闭。也就是说,如果自动折行模式没有被开启,这个命令会开
它;如果已经开启了,这个命令会关闭它。所以我们说,这个命令可以用来
“开toggle”模式。
>> 现在输入 M-x auto fill mode<Return>。然后随便敲点什么,直到你看到它
>> 现在输入 M-x auto-fill-mode <Return>。然后随便敲点什么,直到你看到它
分成两行。你必须敲一些空格,因为 Auto Fill 只在空白处进行断行。
【输入空格对英文来说是必须的,而对中文则不必。】
@ -680,12 +673,11 @@ mode存在。辅模式并不能替代主模式而是提供一些辅助的
* 搜索SEARCHING
-------------------
Emacs 可以向前或向后搜索字符串。搜索命令是一个移动光标的命令:搜索成功
后,光标会停留在搜索目标出现的地方。
Emacs 可以向前或向后搜索字符串(“字符串”指的是一组连续的字符)。搜索命
令是一个移动光标的命令:搜索成功后,光标会停留在搜索目标出现的地方。
Emacs 的搜索命令的独特之处在于它是“渐进的incremental”。意思是搜
索与输入同时进行你在键盘上一字一句地输入搜索词的过程中Emacs 就已经
开始替你搜索了。
Emacs 的搜索命令是“渐进的incremental”。意思是搜索与输入同时进行
你在键盘上一字一句地输入搜索词的过程中Emacs 就已经开始替你搜索了。
C-s 是向前搜索C-r 是向后搜索。不过手别这么快!别着急试。
@ -696,7 +688,7 @@ C-s 是向前搜索C-r 是向后搜索。不过手别这么快!别着急试
慢慢输入“cursor”这个词每敲一个字都停顿一下并观察光标。
现在你应该已曾经找到“cursor”这个词了。
>> 再按一次 C-s搜索下一个“cursor”出现的位置。
>> 现在按四次退格键,看看光标是如何移动的。
>> 现在按四次 <DEL> ,看看光标是如何移动的。
>> 敲 <Return> 结束搜索。
看仔细了么在一次渐进式搜索中Emacs 会尝试跳到搜索目标出现的位置。要
@ -705,19 +697,14 @@ C-s 是向前搜索C-r 是向后搜索。不过手别这么快!别着急试
现 C-g 会让光标回到搜索开始的位置,而 <Return> 则让光标留在搜索结果上,
这是很有用的功能。】
注意:在某些终端下,输入 C-x C-s 会冻结屏幕【屏幕没有任何输出】,使你看
不到 Emacs 的任何变化。其原因是操作系统的“流量控制”功能拦截了 C-s 并
冻结了屏幕。用 C-q 可以解除屏幕冻结。要解决这个问题,请参考 Emacs 手册
里的“Spontaneous Entry to Incremental Search”一节【Emacs 手册可能还没
有中文翻译】,那里提供了一些有用的建议
在渐进式搜索中,按 <DEL> 会“撤回”到最近一次搜索的命中位置。如果之前没
有一个命中, <DEL> 会抹去搜索字符串中的最后一个字符。比如你已经输入了
“c”光标就停在“c”第一次出现的位置再输入“u”光标停在“cu”第一次出现
的位置,这时再按 <DEL> “u”就从搜索字串中消失了然后光标会回到“c”第
一次出现的位置
在渐进式搜索中,按退格键会删除目标字符串的最后一个字符,并且光标会回到
最近一次搜索的命中位置。比如你已经输入了“c”光标就停在“c”第一次出
现的位置再输入“u”光标停在“cu”第一次出现的位置这时再按退格键
“u”就从搜索字串中消失了然后光标会回到“c”第一次出现的位置。
另外,如果你在搜索的时候输入了 CONTROL 或者 META 组合键的话,搜索可能会
结束。(也有例外,比如 C-s 和 M-r 这些用于搜索的命令。)
另外,如果你在搜索的时候输入了 control 或者 meta 组合键的话,搜索可能会
结束。(也有例外,比如 C-s 和 C-r 这些用于搜索的命令。)
前面说的都是“向下”搜索,如果想“向上”搜索,可以用 C-r。C-r 与 C-s
相比除了搜索方向相反之外,其余的操作都一样。
@ -728,7 +715,7 @@ C-s 是向前搜索C-r 是向后搜索。不过手别这么快!别着急试
Emacs 的迷人之处很多,能够在屏幕上同时显示多个窗格就是其中之一。
>> 移动光标到这一行,然后输入 C-u 0 C-l。
>> 移动光标到这一行,然后输入 C-l C-l。
>> 现在输入 C-x 2它会将屏幕划分成两个窗格。
这两个窗格里显示的都是本篇快速指南,而光标则停留在上方的窗格里。
@ -746,18 +733,17 @@ Emacs 的迷人之处很多,能够在屏幕上同时显示多个窗格就是
>> 再输入 C-x o 将光标移回到上方的窗格里。
光标会回到它在上方窗格中原本所在的位置。
连续使用 C-x o 可以遍历所有窗格。每一个窗格都有它自己的光标位置,但是只
有一个窗格会真正显示这个光标。【其它窗格在控制台下不会显示光标,在图形
窗口下缺省显示为镂空光标。】一般所有的编辑命令都作用于这个光标所在的窗
格,我们称这个窗格为“被选中的窗格”。
连续使用 C-x o 可以遍历所有窗格。“被选中的窗格”,也就是绝大多数的编辑
操作所发生的地方,是在你不打字时闪烁光标的那个窗格。其他的窗格有它们自
己的光标位置; 如果你在图形界面下运行 Emacs ,这些光标是镂空的长方形。
当你在一个窗格中编辑但用另一个窗格作为参考的时候C-M-v 是很有用的命
令。你可以始终处于编辑窗格中,然后用 C-M-v 命令滚动另外一个窗格。【比如
翻译和校对就很适合用这种方式进行。】
令。无需离开被选中的窗格,你就可以用 C-M-v 命令滚动另外一个窗格中的文
字。【比如翻译和校对就很适合用这种方式进行。】
C-M-v 是一个 CONTROL-META 组合键。如果你有 META 键的话,可以同时按住
CONTROL 和 META 键并输入 v。CONTROL 和 META 键先按哪个都可以,因为它们
只是用来“修饰modify”你输入的字符的。
C-M-v 是一个 CONTROL-META 组合键。如果你有 META (或 Alt键的话,可以
同时按住CONTROL 和 META 键并输入 v。CONTROL 和 META 键先按哪个都可以,
因为它们只是用来“修饰modify”你输入的字符的。
如果你并没有 META 键,你也可以用 ESC 来代替,不过这样的话就要注意按键顺
序了:你必须先输入 ESC ,然后再输入 CONTROL-v。CONTROL-ESC v 是没用的,
@ -779,6 +765,26 @@ CONTROL 和 META 键并输入 v。CONTROL 和 META 键先按哪个都可以,
>> 输入 C-x o 回到上方的窗格,然后再用 C-x 1 关掉下方窗格。
* 多窗口MULTIPLE FRAMES
------------------
Emacs 可以创建多个窗口。窗口由许多窗格以及菜单、滚动条、回显区等组成。
在图形界面下,多个窗口可以同时显示出来。在文本终端中,只能同时显示一个
窗口。
>> 输入 M-x make-frame <Return>。
可以看到一个新的窗口出现在了你的屏幕上。
你可以在新的窗口里做最初的窗口里可以做的任何事情。第一个窗口没有什么特
别的。
>> 输入 M-x delete-frame <Return>.
这个命令将会关闭选中的窗口。
你也可以通过图形系统来关闭某个窗口(通常是在窗口上面的某个角落里的一个
“X”按钮。如果你关闭的是 Emacs 进程的最后一个窗口, Emacs 将会退出。
* 递归编辑RECURSIVE EDITING LEVELS
--------------------------------------
@ -810,9 +816,7 @@ CONTROL 和 META 键并输入 v。CONTROL 和 META 键先按哪个都可以,
么帮助。如果你连自己到底需要什么帮助都不知道,那么就输入 C-h ?Emacs
会告诉你它能提供了哪些帮助。如果你按了 C-h 又想反悔,可以用 C-g 取消。
(有些主机改变了 C-h 的意义,这种以己度人外加一刀切的做法确实不太好,不
过倒是让你可以义正辞严地抱怨他们的系统管理员。话说回来,如果你按 C-h 之
后没有任何帮助信息显示出来,那么试试 F1 键或者 M-x help <Return> 。)
(如果你按 C-h 之后没有任何帮助信息显示出来,那么试试 F1 键或者 M-x help <Return> 。)
最基本的帮助功能是 C-h c。输入 C-h c 之后再输入一个组合键Emacs 会给出
这个命令的简要说明。
@ -823,9 +827,9 @@ CONTROL 和 META 键并输入 v。CONTROL 和 META 键先按哪个都可以,
C-p runs the command previous-line
这条消息显示了 C-p 命令对应的函数名,函数名主要用来定制和扩展 Emacs。命
令的功能由函数完成,所以函数名本身也可以被看成是最简单的文档――至少对
于你已经学过的命令来说,它们的函数名足以解释它们的功能了。
这条消息显示了 C-p 命令对应的函数名。命令的功能由函数完成,所以函数名
本身也可以被看成是最简单的文档――至少对于你已经学过的命令来说,它们的函
数名足以解释它们的功能了。
多字符命令一样可以用 C-h c 来查看。
@ -841,7 +845,7 @@ CONTROL 和 META 键并输入 v。CONTROL 和 META 键先按哪个都可以,
C-h f 解释一个函数。需要输入函数名。
>> 试试看,输入 C-h f previous-line<Return>。
>> 试试看,输入 C-h f previous-line <Return>。
Emacs 会给出它所知道的所有有关“实现 C-p 命令功能的函数”的信息。
C-h v 用来显示 Emacs 变量的文档。Emacs 变量可以被用来“定制 Emacs 的行
@ -852,7 +856,7 @@ C-h v 用来显示 Emacs 变量的文档。Emacs 变量可以被用来“定制
的命令。这些命令全都可以用 M-x 来启动。对于某些命令来说,
相关命令搜索还会列出一两个组合键。
>> 输入 C-h a file<Return>。
>> 输入 C-h a file <Return>。
Emacs 会在另一个窗格里显示一个 M-x 命令列表,这个列表包含了所有名称中含
有“file”的命令。你可以看到像“C-x C-f”这样的组合键显示在“find-file”
@ -862,7 +866,7 @@ Emacs 会在另一个窗格里显示一个 M-x 命令列表,这个列表包含
>> 输入 C-x 1 来删除 help 窗格。
C-h i 阅读联机手册(也就是通常讲的 Info
C-h i 阅读手册(也就是通常讲的 Info
这个命令会打开一个称为“*info*”的特殊缓冲区,在那里,
你可以阅读安装在系统里的软件包使用手册。要读 Emacs 的使
用手册,按 m emacs <Return> 就可以了。如果你之前从没用
@ -875,18 +879,19 @@ Emacs 会在另一个窗格里显示一个 M-x 命令列表,这个列表包含
---------------------------
想学习更多的使用技巧Emacs 使用手册manual值得一读。你可以读纸版的
书,也可以看电子版的联机手册(可以从 Help 菜单进入或者按 F10 h r。提
两个你可能会很感兴趣的功能吧,一个是可以帮你少敲键盘的 completion自动
补全),另一个是方便文件处理的 dired目录编辑
书,也可以在 Emacs 中读(可以从 Help 菜单进入或者按 C-h r。提两个你
可能会很感兴趣的功能吧,一个是可以帮你少敲键盘的 completion自动补全),
另一个是方便文件处理的 dired目录编辑
Completion 可以替你节省不必要的键盘输入。比如说你想切换到 *Message* 缓
冲区,你就可以用 C-x b *M<Tab> 来完成。只要 Emacs 能够根据你已经输入的
文字确定你想要输入的内容,它就会自动帮你补齐。有关 Completion 的详细说
明可以在 Emacs Info 中的“Completion”一节里找到。
文字确定你想要输入的内容它就会自动帮你补齐。Completion 也可用于命令
名和文件名。有关 Completion 的详细说明可以在 Emacs Info 中的
“Completion”一节里找到。
Dired 能够在一个缓冲区里列出一个目录下的所有文件(可以选择是否也列出子
目录),然后你可以在这个文件列表上完成对文件的移动、访问、重命名或删除
等等操作。Dired 也在 Emacs Info 中有详细介绍参见“Dired”一节。
等等操作。Dired 也在 Emacs 使用手册中有详细介绍参见“Dired”一节。
Emacs 使用手册里还有许许多多的精彩功能等着你来了解。
@ -894,8 +899,7 @@ Emacs 使用手册里还有许许多多的精彩功能等着你来了解。
* 总结CONCLUSION
--------------------
记住,要退出 Emacs 请用 C-x C-c。要暂时切换到 shell 并且稍后再回到
Emacs 里来,请用 C-z。【切换到 shell 仅对控制台下的 Emacs 有效】
要退出 Emacs 请用 C-x C-c。
本文完全是为零起点新手所写的起步教程。如果你觉得哪里还看不明白,千万不
要怀疑自己,那一定是我们没有写好。我们永远欢迎你的不满和抱怨。
@ -905,6 +909,7 @@ Emacs 里来,请用 C-z。【切换到 shell 仅对控制台下的 Emacs 有
---------------------
翻译:孙一江 <sunyijiang@gmail.com>
维护:薛富侨 <xfq.free@gmail.com>
校对水木社区www.newsmth.netEmacs 板众多网友及众多 Emacs 中文用户
Emacs 快速指南Tutorial早有两个刘昭宏的中文译本繁简各一。其简体版本
@ -915,11 +920,11 @@ Emacs 快速指南Tutorial早有两个刘昭宏的中文译本繁简各
的译文质量很高,在翻译过程中给予过我们许多借鉴和参考,在此对刘昭宏的工作
表示感谢。
翻译过程中最大的挑战莫过于术语译词的选择了。经过水木社区 Emacs 板热心
友小范围内的讨论,我们选择了现在的译法。用户的广泛参与是自由软件生命
的源泉,所以如果你有任何建议、勘误或想法,请用你喜欢的方式向我们提出。
你可以通过电子邮件直接联系者,也可以放到 GNU Emacs 的开发邮件列表或者
水木社区的 Emacs 板上进行讨论。
翻译过程中最大的挑战莫过于术语译词的选择了。经过水木社区 Emacs 板热心
友小范围内的讨论,我们选择了现在的译法。用户的广泛参与是自由软件生命
的源泉,所以如果你有任何建议、勘误或想法,请用你喜欢的方式向我们提出。
你可以通过电子邮件直接联系维护者,也可以放到 GNU Emacs 的开发邮件列表
或者水木社区的 Emacs 板上进行讨论。
下面列出主要术语的译词对照,并给出注释说明:
@ -941,6 +946,8 @@ Emacs 快速指南Tutorial早有两个刘昭宏的中文译本繁简各
search 搜索
incremental search 渐进式搜索 [3]
对于其他没有提到的术语,读者可以参考 Emacs 使用手册里的术语表。
[1] “window”一词在计算机相关的领域一般都被译为“窗口”。但是在 Emacs
还有一个“frame”的概念。在被广泛使用的 X 窗口系统和微软的视窗
Windows系列操作系统中Emacs 的一个“frame”就是一个“窗口”
@ -977,46 +984,56 @@ Emacs 快速指南Tutorial早有两个刘昭宏的中文译本繁简各
This tutorial descends from a long line of Emacs tutorials
starting with the one written by Stuart Cracraft for the original Emacs.
This version of the tutorial, like GNU Emacs, is copyrighted, and
comes with permission to distribute copies on certain conditions:
This version of the tutorial is a part of GNU Emacs. It is copyrighted
and comes with permission to distribute copies on certain conditions:
Copyright (C) 1985, 1996, 1998, 2001-2013 Free Software Foundation, Inc.
Copyright (C) 1985, 1996, 1998, 2001-2013 Free Software Foundation,
Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
copyright notice and permission notice are preserved,
and that the distributor grants the recipient permission
for further redistribution as permitted by this notice.
This file is part of GNU Emacs.
Permission is granted to distribute modified versions
of this document, or of portions of it,
under the above conditions, provided also that they
carry prominent notices stating who last altered them.
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.
The conditions for copying Emacs itself are more complex, but in the
same spirit. Please read the file COPYING and then do give copies of
GNU Emacs to your friends. Help stamp out software obstructionism
("ownership") by using, writing, and sharing free software!
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/>.
Please read the file COPYING and then do give copies of GNU Emacs to
your friends. Help stamp out software obstructionism ("ownership") by
using, writing, and sharing free software!
【下面为版权声明的译文,仅供参考。实际法律效力以英文原文为准。】
本快速指南沿袭自历史悠久的 Emacs 快速指南,可上溯至 Stuart Cracraft 为最
初的 Emacs 所作的版本。
本篇文档与 GNU Emacs 一样拥有版权,并允许在下列条件的约束下发行其拷贝:
本篇指南是 GNU Emacs 的一部分,并允许在下列条件的约束下发行其拷贝:
Copyright (C) 1985, 1996, 1998, 2001-2013 Free Software Foundation, Inc.
Copyright (C) 1985, 1996, 1998, 2001-2013 Free Software Foundation,
Inc.
本文档允许在不变更文档内容的情况下由任何人发布在任何媒体上,同时必须
完整保留版权和许可声明,且需给予受众与发行者完全相同的、如本声明所允
许的再次发行本文档的权利。
本文件为 GNU Emacs 的一部分。
本声明允许在与上述条件相同的情况下发布经过修改的全部或部分文档,同时
必须附带显要的文字以申明文档的最后修改者。
GNU Emacs 为自由软件您可依据自由软件基金会所发表的GNU通用公共授权
条款,对本程序再次发布和/或修改;无论您依据的是本授权的第三版,或
(您可选的)任一日后发行的版本。
Emacs 自身的版权问题虽比本文档要复杂一些,但也基于相同的精神。敬请阅读文
件“COPYING”然后向你的朋友们分发 GNU Emacs 拷贝。让我们以使用、编写和
分享自由软件的实际行动来共同祛除软件障碍主义(所谓的“所有权”)!
GNU Emacs 是基于使用目的而加以发布,然而不负任何担保责任;亦无对适
售性或特定目的适用性所为的默示性担保。详情请参照GNU通用公共授权。
您应已收到附随于 GNU Emacs 的GNU通用公共授权的副本如果没有请参照
<http://www.gnu.org/licenses/>.
敬请阅读文件“COPYING”然后向你的朋友们分发 GNU Emacs 拷贝。让我们以使
用、编写和分享自由软件的实际行动来共同祛除软件障碍主义(所谓的“所有
权”)!
;;; Local Variables:
;;; coding: utf-8

View file

@ -285,7 +285,7 @@ Explicaremos después como usar múltiples ventanas. Ahora mismo
queremos explicar cómo deshacerse de ventanas adicionales y volver a
la edición básica en una ventana. Es sencillo:
C-x 1 Una ventana (p.ej., elimina todas las otras ventanas).
C-x 1 Una ventana (es decir, elimina todas las demás ventanas).
Esto es CONTROL-x seguido por el dígito 1. C-x 1 expande la ventana que
contiene el cursor, para ocupar toda la pantalla. Esto borra todas las
@ -374,7 +374,7 @@ resumen de las operaciones de borrado:
Note que <DEL> y C-d, comparados con M-<DEL> y M-d, extienden el
paralelismo iniciado por C-f y M-f (bien, <DEL> no es realmente una
tecla de control, pero no nos preocuparemos de eso ahora). C-k y M-k,
en ciertas forma, son como C-e y M-e, en que las líneas de unos
en cierta forma, son como C-e y M-e, en que las líneas de unos
corresponden a sentencias en los otros.
También puede eliminar un segmento contiguo de texto con un método

View file

@ -7,7 +7,7 @@ Maintainer: Ognyan Kulev <ogi@tower.3.bg>
* TUTORIAL.cn:
Author: Sun Yijiang <sunyijiang@gmail.com>
Maintainer: Sun Yijiang <sunyijiang@gmail.com>
Maintainer: Xue Fuqiao <xfq.free@gmail.com>
* TUTORIAL.cs:
Author: Milan Zamazal <pdm@zamazal.org>

View file

@ -22,15 +22,208 @@
(vc-bzr-ignore-completion-table):
(vc-bzr-find-ignore-file): New functions.
2013-08-04 Juanma Barranquero <lekktu@gmail.com>
* frameset.el (frameset-p, frameset-save): Fix autoload cookies.
(frameset-filter-minibuffer): Doc fix.
(frameset-restore): Fix autoload cookie. Fix typo in docstring.
* desktop.el (desktop-clear): Only delete frames when called
interactively and desktop-restore-frames is non-nil. Doc fix.
(desktop-read): Set desktop-saved-frameset to nil.
2013-08-03 Juanma Barranquero <lekktu@gmail.com>
* frameset.el (frameset-prop): New function and setter.
(frameset-save): Do not modify frame list passed by the caller.
2013-08-03 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/package.el (package-desc-from-define): Ignore unknown keys.
2013-08-02 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/easy-mmode.el (define-globalized-minor-mode)
(easy-mmode-define-navigation): Avoid ((lambda (..) ..) ...).
* custom.el (custom-initialize-default, custom-initialize-set)
(custom-initialize-reset, custom-initialize-changed): Affect the
toplevel-default-value (bug#6275, bug#14586).
* emacs-lisp/advice.el (ad-compile-function): Undo previous workaround
for bug#6275.
2013-08-02 Juanma Barranquero <lekktu@gmail.com>
* emacs-lisp/lisp-mode.el (lisp-imenu-generic-expression):
Add cl-def* expressions.
* frameset.el (frameset-filter-params): Fix order of arguments.
2013-08-02 Juanma Barranquero <lekktu@gmail.com>
Move code related to saving frames to frameset.el.
* desktop.el: Require frameset.
(desktop-restore-frames): Doc fix.
(desktop-restore-reuses-frames): Rename from
desktop-restoring-reuses-frames.
(desktop-saved-frameset): Rename from desktop-saved-frame-states.
(desktop-clear): Clear frames too.
(desktop-filter-parameters-alist): Set from frameset-filter-alist.
(desktop--filter-tty*, desktop-save, desktop-read):
Use frameset functions.
(desktop-before-saving-frames-functions, desktop--filter-*-color)
(desktop--filter-minibuffer, desktop--filter-restore-desktop-parm)
(desktop--filter-save-desktop-parm, desktop--filter-iconified-position)
(desktop-restore-in-original-display-p, desktop--filter-frame-parms)
(desktop--process-minibuffer-frames, desktop-save-frames)
(desktop--reuse-list, desktop--compute-pos, desktop--move-onscreen)
(desktop--find-frame, desktop--select-frame, desktop--make-frame)
(desktop--sort-states, desktop-restoring-frames-p)
(desktop-restore-frames): Remove. Most code moved to frameset.el.
(desktop-restoring-frameset-p, desktop-restore-frameset)
(desktop--check-dont-save, desktop-save-frameset): New functions.
(desktop--app-id): New constant.
(desktop-first-buffer, desktop-buffer-ok-count)
(desktop-buffer-fail-count): Move before first use.
* frameset.el: New file.
2013-08-01 Stefan Monnier <monnier@iro.umontreal.ca>
* files.el: Use lexical-binding.
(dir-locals-read-from-file): Remove unused `err' variable.
(hack-dir-local-variables--warned-coding): New var.
(hack-dir-local-variables): Use it to avoid repeated warnings.
(make-backup-file-name--default-function): New function.
(make-backup-file-name-function): Use it as default.
(buffer-stale--default-function): New function.
(buffer-stale-function): Use it as default.
(revert-buffer-insert-file-contents--default-function): New function.
(revert-buffer-insert-file-contents-function): Use it as default.
(insert-directory): Avoid add-to-list.
* autorevert.el (auto-revert-handler): Simplify.
Use buffer-stale--default-function.
2013-08-01 Tassilo Horn <tsdh@gnu.org>
* speedbar.el (speedbar-query-confirmation-method): Doc fix.
* whitespace.el (whitespace-ensure-local-variables): New function.
(whitespace-cleanup-region): Call it.
(whitespace-turn-on): Call it.
2013-08-01 Michael Albinus <michael.albinus@gmx.de>
Complete file name handlers.
* net/tramp.el (tramp-handle-set-visited-file-modtime)
(tramp-handle-verify-visited-file-modtime)
(tramp-handle-file-notify-rm-watch): New functions.
(tramp-call-process): Do not bind `default-directory'.
* net/tramp-adb.el (tramp-adb-file-name-handler-alist):
Order alphabetically.
[access-file, add-name-to-file, dired-call-process]:
[dired-compress-file, file-acl, file-notify-rm-watch]:
[file-ownership-preserved-p, file-selinux-context]:
[make-directory-internal, make-symbolic-link, set-file-acl]:
[set-file-selinux-context, set-visited-file-modtime]:
[verify-visited-file-modtime]: Add handler.
(tramp-adb-handle-write-region): Apply `set-visited-file-modtime'.
* net/tramp-gvfs.el (tramp-gvfs-file-name-handler-alist)
[file-notify-add-watch, file-notify-rm-watch]:
[set-file-times, set-visited-file-modtime]:
[verify-visited-file-modtime]: Add handler.
(with-tramp-gvfs-error-message)
(tramp-gvfs-handle-set-visited-file-modtime)
(tramp-gvfs-fuse-file-name): Remove.
(tramp-gvfs-handle-file-notify-add-watch)
(tramp-gvfs-file-gvfs-monitor-file-process-filter): New defuns.
(tramp-gvfs-handle-write-region): Fix error in moving tmpfile.
* net/tramp-sh.el (tramp-sh-file-name-handler-alist):
Order alphabetically.
[file-notify-rm-watch ]: Use default Tramp handler.
[executable-find]: Remove private handler.
(tramp-do-copy-or-rename-file-out-of-band): Do not bind
`default-directory'.
(tramp-sh-handle-executable-find)
(tramp-sh-handle-file-notify-rm-watch): Remove functions.
(tramp-sh-file-gvfs-monitor-dir-process-filter)
(tramp-sh-file-inotifywait-process-filter, tramp-set-remote-path):
Do not use `format' in `tramp-message'.
* net/tramp-smb.el (tramp-smb-file-name-handler-alist)
[file-notify-rm-watch, set-visited-file-modtime]:
[verify-visited-file-modtime]: Add handler.
(tramp-smb-call-winexe): Do not bind `default-directory'.
2013-08-01 Xue Fuqiao <xfq.free@gmail.com>
* vc/vc-hooks.el (vc-menu-map): Fix menu entry for vc-ignore.
2013-07-31 Dmitry Gutov <dgutov@yandex.ru>
* vc/log-view.el (log-view-diff): Extract `log-view-diff-common',
use it.
(log-view-diff-changeset): Same.
(log-view-diff-common): Call backend command `previous-revision'
to find out the previous revision, in both cases. Swap the
variables `to' and `fr', so that `fr' usually refers to the
earlier revision (Bug#14989).
2013-07-31 Kan-Ru Chen <kanru@kanru.info>
* ibuf-ext.el (ibuffer-filter-by-filename):
Make it work with dired buffers too.
2013-07-31 Dmitry Antipov <dmantipov@yandex.ru>
* emacs-lisp/re-builder.el (reb-color-display-p):
* files.el (save-buffers-kill-terminal):
* net/browse-url.el (browse-url):
* server.el (server-save-buffers-kill-terminal):
* textmodes/reftex-toc.el (reftex-toc, reftex-toc-revert):
Prefer nil to selected-frame for the first arg of frame-parameter.
2013-07-31 Xue Fuqiao <xfq.free@gmail.com>
* vc/vc-hooks.el (vc-menu-map): Add menu entry for vc-ignore.
2013-07-30 Stephen Berman <stephen.berman@gmx.net>
* minibuffer.el (completion--twq-all): Try and preserve each
completion's case choice (bug#14907).
2013-07-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
* net/network-stream.el (open-network-stream): Mention the new
:nogreeting parameter.
(network-stream-open-starttls): Use the :nogreeting parameter
(bug#14938).
* net/shr.el (shr-mouse-browse-url): Remove and use `shr-browse-url'.
* net/eww.el (eww-setup-buffer): Switching to the buffer seems
more natural than popping.
* net/shr.el (shr-urlify): Put `follow-link' on URLs (bug#14815).
(shr-urlify): Highlight under mouse.
2013-07-30 Xue Fuqiao <xfq.free@gmail.com>
* vc/vc-hooks.el (vc-prefix-map): Add key binding for vc-ignore.
* vc/vc-dir.el (vc-dir-mode-map): Change key binding for vc-dir-ignore.
* vc/vc-svn.el (vc-svn-ignore): Remove `interactive'. Use `*vc*'
buffer for output.
* vc/vc-hg.el (vc-hg-ignore): Remove `interactive'. Do not assume
point-min==1. Fix search string. Fix parentheses missing.
* vc/vc-git.el (vc-git-ignore): Remove `interactive'. Do not
* vc/vc-git.el (vc-git-ignore): Remove `interactive'. Do not
assume point-min==1. Fix search string. Fix parentheses missing.
* vc/vc-cvs.el (vc-cvs-ignore): Remove `interactive'.
@ -94,7 +287,7 @@
* progmodes/cc-engine.el (c-beginning-of-statement-1)
(c-after-conditional): Adapt to deal with c-block-stmt-1-2-key.
* progmodes/cc-fonts.el (c-font-lock-declarations): Adapt to deal
with c-block-stmet-1-2-key.
with c-block-stmt-1-2-key.
2013-07-27 Juanma Barranquero <lekktu@gmail.com>

View file

@ -595,14 +595,14 @@ This is an internal function used by Auto-Revert Mode."
(setq size
(nth 7 (file-attributes
buffer-file-name)))))
(and (file-readable-p buffer-file-name)
(not (verify-visited-file-modtime buffer)))))
(funcall (or buffer-stale-function
#'buffer-stale--default-function)
t)))
(and (or auto-revert-mode
global-auto-revert-non-file-buffers)
revert-buffer-function
(boundp 'buffer-stale-function)
(functionp buffer-stale-function)
(funcall buffer-stale-function t))))
(funcall (or buffer-stale-function
#'buffer-stale--default-function)
t))))
eob eoblist)
(setq auto-revert-notify-modified-p nil)
(when revert

View file

@ -49,63 +49,66 @@ Users should not set it.")
;;; The `defcustom' Macro.
(defun custom-initialize-default (symbol value)
"Initialize SYMBOL with VALUE.
(defun custom-initialize-default (symbol exp)
"Initialize SYMBOL with EXP.
This will do nothing if symbol already has a default binding.
Otherwise, if symbol has a `saved-value' property, it will evaluate
the car of that and use it as the default binding for symbol.
Otherwise, VALUE will be evaluated and used as the default binding for
Otherwise, EXP will be evaluated and used as the default binding for
symbol."
(eval `(defvar ,symbol ,(if (get symbol 'saved-value)
(car (get symbol 'saved-value))
value))))
(eval `(defvar ,symbol ,(let ((sv (get symbol 'saved-value)))
(if sv (car sv) exp)))))
(defun custom-initialize-set (symbol value)
"Initialize SYMBOL based on VALUE.
(defun custom-initialize-set (symbol exp)
"Initialize SYMBOL based on EXP.
If the symbol doesn't have a default binding already,
then set it using its `:set' function (or `set-default' if it has none).
The value is either the value in the symbol's `saved-value' property,
if any, or VALUE."
(unless (default-boundp symbol)
(funcall (or (get symbol 'custom-set) 'set-default)
symbol
(eval (if (get symbol 'saved-value)
(car (get symbol 'saved-value))
value)))))
if any, or the value of EXP."
(condition-case nil
(default-toplevel-value symbol)
(error
(funcall (or (get symbol 'custom-set) #'set-default-toplevel-value)
symbol
(eval (let ((sv (get symbol 'saved-value)))
(if sv (car sv) exp)))))))
(defun custom-initialize-reset (symbol value)
"Initialize SYMBOL based on VALUE.
(defun custom-initialize-reset (symbol exp)
"Initialize SYMBOL based on EXP.
Set the symbol, using its `:set' function (or `set-default' if it has none).
The value is either the symbol's current value
(as obtained using the `:get' function), if any,
or the value in the symbol's `saved-value' property if any,
or (last of all) VALUE."
(funcall (or (get symbol 'custom-set) 'set-default)
or (last of all) the value of EXP."
(funcall (or (get symbol 'custom-set) #'set-default-toplevel-value)
symbol
(cond ((default-boundp symbol)
(funcall (or (get symbol 'custom-get) 'default-value)
symbol))
((get symbol 'saved-value)
(eval (car (get symbol 'saved-value))))
(t
(eval value)))))
(condition-case nil
(let ((def (default-toplevel-value symbol))
(getter (get symbol 'custom-get)))
(if getter (funcall getter symbol) def))
(error
(eval (let ((sv (get symbol 'saved-value)))
(if sv (car sv) exp)))))))
(defun custom-initialize-changed (symbol value)
"Initialize SYMBOL with VALUE.
(defun custom-initialize-changed (symbol exp)
"Initialize SYMBOL with EXP.
Like `custom-initialize-reset', but only use the `:set' function if
not using the standard setting.
For the standard setting, use `set-default'."
(cond ((default-boundp symbol)
(funcall (or (get symbol 'custom-set) 'set-default)
symbol
(funcall (or (get symbol 'custom-get) 'default-value)
symbol)))
((get symbol 'saved-value)
(funcall (or (get symbol 'custom-set) 'set-default)
symbol
(eval (car (get symbol 'saved-value)))))
(t
(set-default symbol (eval value)))))
(condition-case nil
(let ((def (default-toplevel-value symbol)))
(funcall (or (get symbol 'custom-set) #'set-default-toplevel-value)
symbol
(let ((getter (get symbol 'custom-get)))
(if getter (funcall getter symbol) def))))
(error
(cond
((get symbol 'saved-value)
(funcall (or (get symbol 'custom-set) #'set-default-toplevel-value)
symbol
(eval (car (get symbol 'saved-value)))))
(t
(set-default symbol (eval exp)))))))
(defvar custom-delayed-init-variables nil
"List of variables whose initialization is pending.")

View file

@ -134,6 +134,7 @@
;;; Code:
(require 'cl-lib)
(require 'frameset)
(defvar desktop-file-version "206"
"Version number of desktop file format.
@ -372,7 +373,7 @@ modes are restored automatically; they should not be listed here."
:group 'desktop)
(defcustom desktop-restore-frames t
"When non-nil, save window/frame configuration to desktop file."
"When non-nil, save frames to desktop file."
:type 'boolean
:group 'desktop
:version "24.4")
@ -399,7 +400,7 @@ few pixels, especially near the right / bottom borders of the screen."
:group 'desktop
:version "24.4")
(defcustom desktop-restoring-reuses-frames t
(defcustom desktop-restore-reuses-frames t
"If t, restoring frames reuses existing frames.
If nil, existing frames are deleted.
If `keep', existing frames are kept and not reused."
@ -409,13 +410,6 @@ If `keep', existing frames are kept and not reused."
:group 'desktop
:version "24.4")
(defcustom desktop-before-saving-frames-functions nil
"Abnormal hook run before saving frames.
Functions in this hook are called with one argument, a live frame."
:type 'hook
:group 'desktop
:version "24.4")
(defcustom desktop-file-name-format 'absolute
"Format in which desktop file names should be saved.
Possible values are:
@ -599,7 +593,7 @@ DIRNAME omitted or nil means use `desktop-dirname'."
"Checksum of the last auto-saved contents of the desktop file.
Used to avoid writing contents unchanged between auto-saves.")
(defvar desktop-saved-frame-states nil
(defvar desktop-saved-frameset nil
"Saved state of all frames.
Only valid during frame saving & restoring; intended for internal use.")
@ -649,7 +643,10 @@ DIRNAME omitted or nil means use `desktop-dirname'."
"Empty the Desktop.
This kills all buffers except for internal ones and those with names matched by
a regular expression in the list `desktop-clear-preserve-buffers'.
Furthermore, it clears the variables listed in `desktop-globals-to-clear'."
Furthermore, it clears the variables listed in `desktop-globals-to-clear'.
When called interactively and `desktop-restore-frames' is non-nil, it also
deletes all frames except the selected one (and its minibuffer frame,
if different)."
(interactive)
(desktop-lazy-abort)
(dolist (var desktop-globals-to-clear)
@ -667,7 +664,21 @@ Furthermore, it clears the variables listed in `desktop-globals-to-clear'."
(unless (or (eq (aref bufname 0) ?\s) ;; Don't kill internal buffers
(string-match-p preserve-regexp bufname))
(kill-buffer buffer)))))
(delete-other-windows))
(delete-other-windows)
(when (and desktop-restore-frames
;; Non-interactive calls to desktop-clear happen before desktop-read
;; which already takes care of frame restoration and deletion.
(called-interactively-p 'any))
(let* ((this (selected-frame))
(mini (window-frame (minibuffer-window this)))) ; in case they difer
(dolist (frame (sort (frame-list) #'frameset-sort-frames-for-deletion))
(condition-case err
(unless (or (eq frame this)
(eq frame mini)
(frame-parameter frame 'desktop-dont-clear))
(delete-frame frame))
(error
(delay-warning 'desktop (error-message-string err))))))))
;; ----------------------------------------------------------------------------
(unless noninteractive
@ -890,223 +901,41 @@ DIRNAME must be the directory in which the desktop file will be saved."
;; ----------------------------------------------------------------------------
(defvar desktop-filter-parameters-alist
'((background-color . desktop--filter-*-color)
(buffer-list . t)
(buffer-predicate . t)
(buried-buffer-list . t)
(desktop--font . desktop--filter-restore-desktop-parm)
(desktop--fullscreen . desktop--filter-restore-desktop-parm)
(desktop--height . desktop--filter-restore-desktop-parm)
(desktop--width . desktop--filter-restore-desktop-parm)
(font . desktop--filter-save-desktop-parm)
(font-backend . t)
(foreground-color . desktop--filter-*-color)
(fullscreen . desktop--filter-save-desktop-parm)
(height . desktop--filter-save-desktop-parm)
(left . desktop--filter-iconified-position)
(minibuffer . desktop--filter-minibuffer)
(name . t)
(outer-window-id . t)
(parent-id . t)
(top . desktop--filter-iconified-position)
(tty . desktop--filter-tty*)
(tty-type . desktop--filter-tty*)
(width . desktop--filter-save-desktop-parm)
(window-id . t)
(window-system . t))
(append '((font-backend . t)
(name . t)
(outer-window-id . t)
(parent-id . t)
(tty . desktop--filter-tty*)
(tty-type . desktop--filter-tty*)
(window-id . t)
(window-system . t))
frameset-filter-alist)
"Alist of frame parameters and filtering functions.
Each element is a cons (PARAM . FILTER), where PARAM is a parameter
name (a symbol identifying a frame parameter), and FILTER can be t
\(meaning the parameter is removed from the parameter list on saving
and restoring), or a function that will be called with three args:
CURRENT a cons (PARAM . VALUE), where PARAM is the one being
filtered and VALUE is its current value
PARAMETERS the complete alist of parameters being filtered
SAVING non-nil if filtering before saving state, nil otherwise
The FILTER function must return:
nil CURRENT is removed from the list
t CURRENT is left as is
(PARAM' . VALUE') replace CURRENT with this
Frame parameters not on this list are passed intact.")
(defvar desktop--target-display nil
"Either (minibuffer . VALUE) or nil.
This refers to the current frame config being processed inside
`frame--restore-frames' and its auxiliary functions (like filtering).
If nil, there is no need to change the display.
If non-nil, display parameter to use when creating the frame.
Internal use only.")
(defun desktop-switch-to-gui-p (parameters)
"True when switching to a graphic display.
Return t if PARAMETERS describes a text-only terminal and
the target is a graphic display; otherwise return nil.
Only meaningful when called from a filtering function in
`desktop-filter-parameters-alist'."
(and desktop--target-display ; we're switching
(null (cdr (assq 'display parameters))) ; from a tty
(cdr desktop--target-display))) ; to a GUI display
(defun desktop-switch-to-tty-p (parameters)
"True when switching to a text-only terminal.
Return t if PARAMETERS describes a graphic display and
the target is a text-only terminal; otherwise return nil.
Only meaningful when called from a filtering function in
`desktop-filter-parameters-alist'."
(and desktop--target-display ; we're switching
(cdr (assq 'display parameters)) ; from a GUI display
(null (cdr desktop--target-display)))) ; to a tty
Its format is identical to `frameset-filter-alist' (which see).")
(defun desktop--filter-tty* (_current parameters saving)
;; Remove tty and tty-type parameters when switching
;; to a GUI frame.
(or saving
(not (desktop-switch-to-gui-p parameters))))
(not (frameset-switch-to-gui-p parameters))))
(defun desktop--filter-*-color (current parameters saving)
;; Remove (foreground|background)-color parameters
;; when switching to a GUI frame if they denote an
;; "unspecified" color.
(or saving
(not (desktop-switch-to-gui-p parameters))
(not (stringp (cdr current)))
(not (string-match-p "^unspecified-[fb]g$" (cdr current)))))
(defun desktop--check-dont-save (frame)
(not (frame-parameter frame 'desktop-dont-save)))
(defun desktop--filter-minibuffer (current _parameters saving)
;; When minibuffer is a window, save it as minibuffer . t
(or (not saving)
(if (windowp (cdr current))
'(minibuffer . t)
t)))
(defconst desktop--app-id `(desktop . ,desktop-file-version))
(defun desktop--filter-restore-desktop-parm (current parameters saving)
;; When switching to a GUI frame, convert desktop--XXX parameter to XXX
(or saving
(not (desktop-switch-to-gui-p parameters))
(let ((val (cdr current)))
(if (eq val :desktop-processed)
nil
(cons (intern (substring (symbol-name (car current))
9)) ;; (length "desktop--")
val)))))
(defun desktop--filter-save-desktop-parm (current parameters saving)
;; When switching to a tty frame, save parameter XXX as desktop--XXX so it
;; can be restored in a subsequent GUI session, unless it already exists.
(cond (saving t)
((desktop-switch-to-tty-p parameters)
(let ((sym (intern (format "desktop--%s" (car current)))))
(if (assq sym parameters)
nil
(cons sym (cdr current)))))
((desktop-switch-to-gui-p parameters)
(let* ((dtp (assq (intern (format "desktop--%s" (car current)))
parameters))
(val (cdr dtp)))
(if (eq val :desktop-processed)
nil
(setcdr dtp :desktop-processed)
(cons (car current) val))))
(t t)))
(defun desktop--filter-iconified-position (_current parameters saving)
;; When saving an iconified frame, top & left are meaningless,
;; so remove them to allow restoring to a default position.
(not (and saving (eq (cdr (assq 'visibility parameters)) 'icon))))
(defun desktop-restore-in-original-display-p ()
"True if saved frames' displays should be honored."
(cond ((daemonp) t)
((eq system-type 'windows-nt) nil)
(t (null desktop-restore-in-current-display))))
(defun desktop--filter-frame-parms (parameters saving)
"Filter frame parameters and return filtered list.
PARAMETERS is a parameter alist as returned by `frame-parameters'.
If SAVING is non-nil, filtering is happening before saving frame state;
otherwise, filtering is being done before restoring frame state.
Parameters are filtered according to the setting of
`desktop-filter-parameters-alist' (which see).
Internal use only."
(let ((filtered nil))
(dolist (param parameters)
(let ((filter (cdr (assq (car param) desktop-filter-parameters-alist)))
this)
(cond (;; no filter: pass param
(null filter)
(push param filtered))
(;; filter = t; skip param
(eq filter t))
(;; filter func returns nil: skip param
(null (setq this (funcall filter param parameters saving))))
(;; filter func returns t: pass param
(eq this t)
(push param filtered))
(;; filter func returns a new param: use it
t
(push this filtered)))))
;; Set the display parameter after filtering, so that filter functions
;; have access to its original value.
(when desktop--target-display
(let ((display (assq 'display filtered)))
(if display
(setcdr display (cdr desktop--target-display))
(push desktop--target-display filtered))))
filtered))
(defun desktop--process-minibuffer-frames (frames)
;; Adds a desktop--mini parameter to frames
;; desktop--mini is a list (MINIBUFFER NUMBER DEFAULT?) where
;; MINIBUFFER t if the frame (including minibuffer-only) owns a minibuffer
;; NUMBER if MINIBUFFER = t, an ID for the frame; if nil, the ID of
;; the frame containing the minibuffer used by this frame
;; DEFAULT? if t, this frame is the value of default-minibuffer-frame
(let ((count 0))
;; Reset desktop--mini for all frames
(dolist (frame (frame-list))
(set-frame-parameter frame 'desktop--mini nil))
;; Number all frames with its own minibuffer
(dolist (frame (minibuffer-frame-list))
(set-frame-parameter frame 'desktop--mini
(list t
(cl-incf count)
(eq frame default-minibuffer-frame))))
;; Now link minibufferless frames with their minibuffer frames
(dolist (frame frames)
(unless (frame-parameter frame 'desktop--mini)
(let ((mb-frame (window-frame (minibuffer-window frame))))
;; Frames whose minibuffer frame has been filtered out will have
;; desktop--mini = nil, so desktop-restore-frames will restore them
;; according to their minibuffer parameter. Set up desktop--mini
;; for the rest.
(when (memq mb-frame frames)
(set-frame-parameter frame 'desktop--mini
(list nil
(cl-second (frame-parameter mb-frame 'desktop--mini))
nil))))))))
(defun desktop-save-frames ()
"Save frame state in `desktop-saved-frame-states'.
Runs the hook `desktop-before-saving-frames-functions'.
(defun desktop-save-frameset ()
"Save the state of existing frames in `desktop-saved-frameset'.
Frames with a non-nil `desktop-dont-save' parameter are not saved."
(setq desktop-saved-frame-states
(setq desktop-saved-frameset
(and desktop-restore-frames
(let ((frames (cl-delete-if
(lambda (frame)
(run-hook-with-args 'desktop-before-saving-frames-functions frame)
(frame-parameter frame 'desktop-dont-save))
(frame-list))))
;; In case some frame was deleted by a hook function
(setq frames (cl-delete-if-not #'frame-live-p frames))
(desktop--process-minibuffer-frames frames)
(mapcar (lambda (frame)
(cons (desktop--filter-frame-parms (frame-parameters frame) t)
(window-state-get (frame-root-window frame) t)))
frames)))))
(let ((name (concat user-login-name "@" system-name
(format-time-string " %Y-%m-%d %T"))))
(frameset-save nil
:filters desktop-filter-parameters-alist
:predicate #'desktop--check-dont-save
:properties (list :app desktop--app-id
:name name))))))
;;;###autoload
(defun desktop-save (dirname &optional release auto-save)
@ -1148,11 +977,11 @@ and don't save the buffer if they are the same."
(insert "\n;; Global section:\n")
;; Called here because we save the window/frame state as a global
;; variable for compatibility with previous Emacsen.
(desktop-save-frames)
(unless (memq 'desktop-saved-frame-states desktop-globals-to-save)
(desktop-outvar 'desktop-saved-frame-states))
(desktop-save-frameset)
(unless (memq 'desktop-saved-frameset desktop-globals-to-save)
(desktop-outvar 'desktop-saved-frameset))
(mapc (function desktop-outvar) desktop-globals-to-save)
(setq desktop-saved-frame-states nil) ; after saving desktop-globals-to-save
(setq desktop-saved-frameset nil) ; after saving desktop-globals-to-save
(when (memq 'kill-ring desktop-globals-to-save)
(insert
"(setq kill-ring-yank-pointer (nthcdr "
@ -1210,319 +1039,26 @@ This function also sets `desktop-dirname' to nil."
(defvar desktop-lazy-timer nil)
;; ----------------------------------------------------------------------------
(defvar desktop--reuse-list nil
"Internal use only.")
(defun desktop-restoring-frameset-p ()
"True if calling `desktop-restore-frameset' will actually restore it."
(and desktop-restore-frames desktop-saved-frameset t))
(defun desktop--compute-pos (value left/top right/bottom)
(pcase value
(`(+ ,val) (+ left/top val))
(`(- ,val) (+ right/bottom val))
(val val)))
(defun desktop--move-onscreen (frame)
"If FRAME is offscreen, move it back onscreen and, if necessary, resize it.
When forced onscreen, frames wider than the monitor's workarea are converted
to fullwidth, and frames taller than the workarea are converted to fullheight.
NOTE: This only works for non-iconified frames."
(pcase-let* ((`(,left ,top ,width ,height) (cl-cdadr (frame-monitor-attributes frame)))
(right (+ left width -1))
(bottom (+ top height -1))
(fr-left (desktop--compute-pos (frame-parameter frame 'left) left right))
(fr-top (desktop--compute-pos (frame-parameter frame 'top) top bottom))
(ch-width (frame-char-width frame))
(ch-height (frame-char-height frame))
(fr-width (max (frame-pixel-width frame) (* ch-width (frame-width frame))))
(fr-height (max (frame-pixel-height frame) (* ch-height (frame-height frame))))
(fr-right (+ fr-left fr-width -1))
(fr-bottom (+ fr-top fr-height -1)))
(when (pcase desktop-restore-forces-onscreen
;; Any corner is outside the screen.
(`all (or (< fr-bottom top) (> fr-bottom bottom)
(< fr-left left) (> fr-left right)
(< fr-right left) (> fr-right right)
(< fr-top top) (> fr-top bottom)))
;; Displaced to the left, right, above or below the screen.
(`t (or (> fr-left right)
(< fr-right left)
(> fr-top bottom)
(< fr-bottom top)))
(_ nil))
(let ((fullwidth (> fr-width width))
(fullheight (> fr-height height))
(params nil))
;; Position frame horizontally.
(cond (fullwidth
(push `(left . ,left) params))
((> fr-right right)
(push `(left . ,(+ left (- width fr-width))) params))
((< fr-left left)
(push `(left . ,left) params)))
;; Position frame vertically.
(cond (fullheight
(push `(top . ,top) params))
((> fr-bottom bottom)
(push `(top . ,(+ top (- height fr-height))) params))
((< fr-top top)
(push `(top . ,top) params)))
;; Compute fullscreen state, if required.
(when (or fullwidth fullheight)
(push (cons 'fullscreen
(cond ((not fullwidth) 'fullheight)
((not fullheight) 'fullwidth)
(t 'maximized)))
params))
;; Finally, move the frame back onscreen.
(when params
(modify-frame-parameters frame params))))))
(defun desktop--find-frame (predicate display &rest args)
"Find a suitable frame in `desktop--reuse-list'.
Look through frames whose display property matches DISPLAY and
return the first one for which (PREDICATE frame ARGS) returns t.
If PREDICATE is nil, it is always satisfied. Internal use only.
This is an auxiliary function for `desktop--select-frame'."
(cl-find-if (lambda (frame)
(and (equal (frame-parameter frame 'display) display)
(or (null predicate)
(apply predicate frame args))))
desktop--reuse-list))
(defun desktop--select-frame (display frame-cfg)
"Look for an existing frame to reuse.
DISPLAY is the display where the frame will be shown, and FRAME-CFG
is the parameter list of the frame being restored. Internal use only."
(if (eq desktop-restoring-reuses-frames t)
(let ((frame nil)
mini)
;; There are no fancy heuristics there. We could implement some
;; based on frame size and/or position, etc., but it is not clear
;; that any "gain" (in the sense of reduced flickering, etc.) is
;; worth the added complexity. In fact, the code below mainly
;; tries to work nicely when M-x desktop-read is used after a desktop
;; session has already been loaded. The other main use case, which
;; is the initial desktop-read upon starting Emacs, should usually
;; only have one, or very few, frame(s) to reuse.
(cond ((null display)
;; When the target is tty, every existing frame is reusable.
(setq frame (desktop--find-frame nil display)))
((car (setq mini (cdr (assq 'desktop--mini frame-cfg))))
;; If the frame has its own minibuffer, let's see whether
;; that frame has already been loaded (which can happen after
;; M-x desktop-read).
(setq frame (desktop--find-frame
(lambda (f m)
(equal (frame-parameter f 'desktop--mini) m))
display mini))
;; If it has not been loaded, and it is not a minibuffer-only frame,
;; let's look for an existing non-minibuffer-only frame to reuse.
(unless (or frame (eq (cdr (assq 'minibuffer frame-cfg)) 'only))
(setq frame (desktop--find-frame
(lambda (f)
(let ((w (frame-parameter f 'minibuffer)))
(and (window-live-p w)
(window-minibuffer-p w)
(eq (window-frame w) f))))
display))))
(mini
;; For minibufferless frames, check whether they already exist,
;; and that they are linked to the right minibuffer frame.
(setq frame (desktop--find-frame
(lambda (f n)
(pcase-let (((and m `(,hasmini ,num))
(frame-parameter f 'desktop--mini)))
(and m
(null hasmini)
(= num n)
(equal (cl-second (frame-parameter
(window-frame (minibuffer-window f))
'desktop--mini))
n))))
display (cl-second mini))))
(t
;; Default to just finding a frame in the same display.
(setq frame (desktop--find-frame nil display))))
;; If found, remove from the list.
(when frame
(setq desktop--reuse-list (delq frame desktop--reuse-list)))
frame)
nil))
(defun desktop--make-frame (frame-cfg window-cfg)
"Set up a frame according to its saved state.
That means either creating a new frame or reusing an existing one.
FRAME-CFG is the parameter list of the new frame; WINDOW-CFG is
its window state. Internal use only."
(let* ((fullscreen (cdr (assq 'fullscreen frame-cfg)))
(lines (assq 'tool-bar-lines frame-cfg))
(filtered-cfg (desktop--filter-frame-parms frame-cfg nil))
(display (cdr (assq 'display filtered-cfg))) ;; post-filtering
alt-cfg frame)
;; This works around bug#14795 (or feature#14795, if not a bug :-)
(setq filtered-cfg (assq-delete-all 'tool-bar-lines filtered-cfg))
(push '(tool-bar-lines . 0) filtered-cfg)
(when fullscreen
;; Currently Emacs has the limitation that it does not record the size
;; and position of a frame before maximizing it, so we cannot save &
;; restore that info. Instead, when restoring, we resort to creating
;; invisible "fullscreen" frames of default size and then maximizing them
;; (and making them visible) which at least is somewhat user-friendly
;; when these frames are later de-maximized.
(let ((width (and (eq fullscreen 'fullheight) (cdr (assq 'width filtered-cfg))))
(height (and (eq fullscreen 'fullwidth) (cdr (assq 'height filtered-cfg))))
(visible (assq 'visibility filtered-cfg)))
(setq filtered-cfg (cl-delete-if (lambda (p)
(memq p '(visibility fullscreen width height)))
filtered-cfg :key #'car))
(when width
(setq filtered-cfg (append `((user-size . t) (width . ,width))
filtered-cfg)))
(when height
(setq filtered-cfg (append `((user-size . t) (height . ,height))
filtered-cfg)))
;; These are parameters to apply after creating/setting the frame.
(push visible alt-cfg)
(push (cons 'fullscreen fullscreen) alt-cfg)))
;; Time to find or create a frame an apply the big bunch of parameters.
;; If a frame needs to be created and it falls partially or wholly offscreen,
;; sometimes it gets "pushed back" onscreen; however, moving it afterwards is
;; allowed. So we create the frame as invisible and then reapply the full
;; parameter list (including position and size parameters).
(setq frame (or (desktop--select-frame display filtered-cfg)
(make-frame-on-display display
(cons '(visibility)
(cl-loop
for param in '(left top width height minibuffer)
collect (assq param filtered-cfg))))))
(modify-frame-parameters frame
(if (eq (frame-parameter frame 'fullscreen) fullscreen)
;; Workaround for bug#14949
(assq-delete-all 'fullscreen filtered-cfg)
filtered-cfg))
;; If requested, force frames to be onscreen.
(when (and desktop-restore-forces-onscreen
;; FIXME: iconified frames should be checked too,
;; but it is impossible without deiconifying them.
(not (eq (frame-parameter frame 'visibility) 'icon)))
(desktop--move-onscreen frame))
;; Let's give the finishing touches (visibility, tool-bar, maximization).
(when lines (push lines alt-cfg))
(when alt-cfg (modify-frame-parameters frame alt-cfg))
;; Now restore window state.
(window-state-put window-cfg (frame-root-window frame) 'safe)
frame))
(defun desktop--sort-states (state1 state2)
;; Order: default minibuffer frame
;; other frames with minibuffer, ascending ID
;; minibufferless frames, ascending ID
(pcase-let ((`(,_p1 ,hasmini1 ,num1 ,default1) (assq 'desktop--mini (car state1)))
(`(,_p2 ,hasmini2 ,num2 ,default2) (assq 'desktop--mini (car state2))))
(cond (default1 t)
(default2 nil)
((eq hasmini1 hasmini2) (< num1 num2))
(t hasmini1))))
(defun desktop-restoring-frames-p ()
"True if calling `desktop-restore-frames' will actually restore frames."
(and desktop-restore-frames desktop-saved-frame-states t))
(defun desktop-restore-frames ()
"Restore window/frame configuration.
This function depends on the value of `desktop-saved-frame-states'
(defun desktop-restore-frameset ()
"Restore the state of a set of frames.
This function depends on the value of `desktop-saved-frameset'
being set (usually, by reading it from the desktop)."
(when (desktop-restoring-frames-p)
(let* ((frame-mb-map nil) ;; Alist of frames with their own minibuffer
(delete-saved (eq desktop-restore-in-current-display 'delete))
(forcing (not (desktop-restore-in-original-display-p)))
(target (and forcing (cons 'display (frame-parameter nil 'display)))))
(when (desktop-restoring-frameset-p)
(frameset-restore desktop-saved-frameset
:filters desktop-filter-parameters-alist
:reuse-frames desktop-restore-reuses-frames
:force-display desktop-restore-in-current-display
:force-onscreen desktop-restore-forces-onscreen)))
;; Sorting saved states allows us to easily restore minibuffer-owning frames
;; before minibufferless ones.
(setq desktop-saved-frame-states (sort desktop-saved-frame-states
#'desktop--sort-states))
;; Potentially all existing frames are reusable. Later we will decide which ones
;; to reuse, and how to deal with any leftover.
(setq desktop--reuse-list (frame-list))
(dolist (state desktop-saved-frame-states)
(condition-case err
(pcase-let* ((`(,frame-cfg . ,window-cfg) state)
((and d-mini `(,hasmini ,num ,default))
(cdr (assq 'desktop--mini frame-cfg)))
(frame nil) (to-tty nil))
;; Only set target if forcing displays and the target display is different.
(if (or (not forcing)
(equal target (or (assq 'display frame-cfg) '(display . nil))))
(setq desktop--target-display nil)
(setq desktop--target-display target
to-tty (null (cdr target))))
;; Time to restore frames and set up their minibuffers as they were.
;; We only skip a frame (thus deleting it) if either:
;; - we're switching displays, and the user chose the option to delete, or
;; - we're switching to tty, and the frame to restore is minibuffer-only.
(unless (and desktop--target-display
(or delete-saved
(and to-tty
(eq (cdr (assq 'minibuffer frame-cfg)) 'only))))
;; Restore minibuffers. Some of this stuff could be done in a filter
;; function, but it would be messy because restoring minibuffers affects
;; global state; it's best to do it here than add a bunch of global
;; variables to pass info back-and-forth to/from the filter function.
(cond
((null d-mini)) ;; No desktop--mini. Process as normal frame.
(to-tty) ;; Ignore minibuffer stuff and process as normal frame.
(hasmini ;; Frame has minibuffer (or it is minibuffer-only).
(when (eq (cdr (assq 'minibuffer frame-cfg)) 'only)
(setq frame-cfg (append '((tool-bar-lines . 0) (menu-bar-lines . 0))
frame-cfg))))
(t ;; Frame depends on other frame's minibuffer window.
(let ((mb-frame (cdr (assq num frame-mb-map))))
(unless (frame-live-p mb-frame)
(error "Minibuffer frame %s not found" num))
(let ((mb-param (assq 'minibuffer frame-cfg))
(mb-window (minibuffer-window mb-frame)))
(unless (and (window-live-p mb-window)
(window-minibuffer-p mb-window))
(error "Not a minibuffer window %s" mb-window))
(if mb-param
(setcdr mb-param mb-window)
(push (cons 'minibuffer mb-window) frame-cfg))))))
;; OK, we're ready at last to create (or reuse) a frame and
;; restore the window config.
(setq frame (desktop--make-frame frame-cfg window-cfg))
;; Set default-minibuffer if required.
(when default (setq default-minibuffer-frame frame))
;; Store NUM/frame to assign to minibufferless frames.
(when hasmini (push (cons num frame) frame-mb-map))))
(error
(delay-warning 'desktop (error-message-string err) :error))))
;; In case we try to delete the initial frame, we want to make sure that
;; other frames are already visible (discussed in thread for bug#14841).
(sit-for 0 t)
;; Delete remaining frames, but do not fail if some resist being deleted.
(unless (eq desktop-restoring-reuses-frames 'keep)
(dolist (frame desktop--reuse-list)
(condition-case err
(delete-frame frame)
(error
(delay-warning 'desktop (error-message-string err))))))
(setq desktop--reuse-list nil)
;; Make sure there's at least one visible frame, and select it.
(unless (or (daemonp)
(cl-find-if #'frame-visible-p (frame-list)))
(let ((visible (if (frame-live-p default-minibuffer-frame)
default-minibuffer-frame
(car (frame-list)))))
(make-frame-visible visible)
(select-frame-set-input-focus visible))))))
;; Just to silence the byte compiler.
;; Dynamicaly bound in `desktop-read'.
(defvar desktop-first-buffer)
(defvar desktop-buffer-ok-count)
(defvar desktop-buffer-fail-count)
;;;###autoload
(defun desktop-read (&optional dirname)
@ -1583,7 +1119,7 @@ Using it may cause conflicts. Use it anyway? " owner)))))
(file-error (message "Couldn't record use of desktop file")
(sit-for 1))))
(unless (desktop-restoring-frames-p)
(unless (desktop-restoring-frameset-p)
;; `desktop-create-buffer' puts buffers at end of the buffer list.
;; We want buffers existing prior to evaluating the desktop (and
;; not reused) to be placed at the end of the buffer list, so we
@ -1593,9 +1129,14 @@ Using it may cause conflicts. Use it anyway? " owner)))))
(switch-to-buffer (car (buffer-list))))
(run-hooks 'desktop-delay-hook)
(setq desktop-delay-hook nil)
(desktop-restore-frames)
(desktop-restore-frameset)
(run-hooks 'desktop-after-read-hook)
(message "Desktop: %d buffer%s restored%s%s."
(message "Desktop: %s%d buffer%s restored%s%s."
(if desktop-saved-frameset
(let ((fn (length (frameset-states desktop-saved-frameset))))
(format "%d frame%s, "
fn (if (= fn 1) "" "s")))
"")
desktop-buffer-ok-count
(if (= 1 desktop-buffer-ok-count) "" "s")
(if (< 0 desktop-buffer-fail-count)
@ -1605,7 +1146,7 @@ Using it may cause conflicts. Use it anyway? " owner)))))
(format ", %d to restore lazily"
(length desktop-buffer-args-list))
""))
(unless (desktop-restoring-frames-p)
(unless (desktop-restoring-frameset-p)
;; Bury the *Messages* buffer to not reshow it when burying
;; the buffer we switched to above.
(when (buffer-live-p (get-buffer "*Messages*"))
@ -1618,6 +1159,7 @@ Using it may cause conflicts. Use it anyway? " owner)))))
(walk-window-tree (lambda (window)
(set-window-prev-buffers window nil)
(set-window-next-buffers window nil))))
(setq desktop-saved-frameset nil)
t))
;; No desktop file found.
(desktop-clear)
@ -1743,14 +1285,6 @@ integer, start a new timer to call `desktop-auto-save' in that many seconds."
;; Create a buffer, load its file, set its mode, ...;
;; called from Desktop file only.
;; Just to silence the byte compiler.
(defvar desktop-first-buffer) ; Dynamically bound in `desktop-read'
;; Bound locally in `desktop-read'.
(defvar desktop-buffer-ok-count)
(defvar desktop-buffer-fail-count)
(defun desktop-create-buffer
(file-version
buffer-filename

View file

@ -2280,7 +2280,6 @@ For that it has to be fbound with a non-autoload definition."
(defun ad-compile-function (function)
"Byte-compile the assembled advice function."
(require 'bytecomp)
(require 'warnings) ;To define warning-suppress-types before we let-bind it.
(let ((byte-compile-warnings byte-compile-warnings)
;; Don't pop up windows showing byte-compiler warnings.
(warning-suppress-types '((bytecomp))))

View file

@ -419,7 +419,7 @@ See `%s' for more information on %s."
;; Go through existing buffers.
(dolist (buf (buffer-list))
(with-current-buffer buf
(if ,global-mode (,turn-on) (when ,mode (,mode -1))))))
(if ,global-mode (funcall #',turn-on) (when ,mode (,mode -1))))))
;; Autoloading define-globalized-minor-mode autoloads everything
;; up-to-here.
@ -449,8 +449,8 @@ See `%s' for more information on %s."
(if ,mode
(progn
(,mode -1)
(,turn-on))
(,turn-on))))
(funcall #',turn-on))
(funcall #',turn-on))))
(setq ,MODE-major-mode major-mode)))))
(put ',MODE-enable-in-buffers 'definition-name ',global-mode)
@ -589,7 +589,7 @@ BODY is executed after moving to the destination location."
(prog1 (or (< (- (point-max) (point-min)) (buffer-size)))
(widen))))
,body
(when was-narrowed (,narrowfun)))))))
(when was-narrowed (funcall #',narrowfun)))))))
(unless name (setq name base-name))
`(progn
(defun ,next-sym (&optional count)
@ -601,13 +601,13 @@ BODY is executed after moving to the destination location."
,(funcall when-narrowed
`(if (not (re-search-forward ,re nil t count))
(if (looking-at ,re)
(goto-char (or ,(if endfun `(,endfun)) (point-max)))
(goto-char (or ,(if endfun `(funcall #',endfun)) (point-max)))
(user-error "No next %s" ,name))
(goto-char (match-beginning 0))
(when (and (eq (current-buffer) (window-buffer (selected-window)))
(called-interactively-p 'interactive))
(let ((endpt (or (save-excursion
,(if endfun `(,endfun)
,(if endfun `(funcall #',endfun)
`(re-search-forward ,re nil t 2)))
(point-max))))
(unless (pos-visible-in-window-p endpt nil t)

View file

@ -110,7 +110,9 @@ It has `lisp-mode-abbrev-table' as its parent."
"define-compiler-macro" "define-modify-macro"
"defsetf" "define-setf-expander"
"define-method-combination"
"defgeneric" "defmethod") t))
"defgeneric" "defmethod"
"cl-defun" "cl-defsubst" "cl-defmacro"
"cl-define-compiler-macro") t))
"\\s-+\\(\\(\\sw\\|\\s_\\)+\\)"))
2)
(list (purecopy "Variables")
@ -132,7 +134,8 @@ It has `lisp-mode-abbrev-table' as its parent."
(regexp-opt
'("defgroup" "deftheme" "deftype" "defstruct"
"defclass" "define-condition" "define-widget"
"defface" "defpackage") t))
"defface" "defpackage" "cl-deftype"
"cl-defstruct") t))
"\\s-+'?\\(\\(\\sw\\|\\s_\\)+\\)"))
2))

View file

@ -296,7 +296,7 @@ contrast, `package-user-dir' contains packages for personal use."
(:constructor
package-desc-from-define
(name-string version-string &optional summary requirements
&key kind archive
&key kind archive &allow-other-keys
&aux
(name (intern name-string))
(version (version-to-list version-string))

View file

@ -319,7 +319,7 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
(eq 'color
;; emacs/xemacs compatibility
(if (fboundp 'frame-parameter)
(frame-parameter (selected-frame) 'display-type)
(frame-parameter nil 'display-type)
(if (fboundp 'frame-property)
(frame-property (selected-frame) 'display-type)))))

View file

@ -1,4 +1,4 @@
;;; files.el --- file input and output commands for Emacs
;;; files.el --- file input and output commands for Emacs -*- lexical-binding:t -*-
;; Copyright (C) 1985-1987, 1992-2013 Free Software Foundation, Inc.
@ -3645,20 +3645,19 @@ is found. Returns the new class name."
(with-temp-buffer
;; This is with-demoted-errors, but we want to mention dir-locals
;; in any error message.
(let (err)
(condition-case err
(progn
(insert-file-contents file)
(unless (zerop (buffer-size))
(let* ((dir-name (file-name-directory file))
(class-name (intern dir-name))
(variables (let ((read-circle nil))
(read (current-buffer)))))
(dir-locals-set-class-variables class-name variables)
(dir-locals-set-directory-class dir-name class-name
(nth 5 (file-attributes file)))
class-name)))
(error (message "Error reading dir-locals: %S" err) nil)))))
(condition-case err
(progn
(insert-file-contents file)
(unless (zerop (buffer-size))
(let* ((dir-name (file-name-directory file))
(class-name (intern dir-name))
(variables (let ((read-circle nil))
(read (current-buffer)))))
(dir-locals-set-class-variables class-name variables)
(dir-locals-set-directory-class dir-name class-name
(nth 5 (file-attributes file)))
class-name)))
(error (message "Error reading dir-locals: %S" err) nil))))
(defcustom enable-remote-dir-locals nil
"Non-nil means dir-local variables will be applied to remote files."
@ -3666,6 +3665,8 @@ is found. Returns the new class name."
:type 'boolean
:group 'find-file)
(defvar hack-dir-local-variables--warned-coding nil)
(defun hack-dir-local-variables ()
"Read per-directory local variables for the current buffer.
Store the directory-local variables in `dir-local-variables-alist'
@ -3697,8 +3698,10 @@ This does nothing if either `enable-local-variables' or
(when variables
(dolist (elt variables)
(if (eq (car elt) 'coding)
(display-warning :warning
"Coding cannot be specified by dir-locals")
(unless hack-dir-local-variables--warned-coding
(setq hack-dir-local-variables--warned-coding t)
(display-warning :warning
"Coding cannot be specified by dir-locals"))
(unless (memq (car elt) '(eval mode))
(setq dir-local-variables-alist
(assq-delete-all (car elt) dir-local-variables-alist)))
@ -4145,9 +4148,9 @@ FILENAME defaults to `buffer-file-name'."
(file-name-sans-extension
(file-name-nondirectory (or filename (buffer-file-name)))))
(defcustom make-backup-file-name-function nil
(defcustom make-backup-file-name-function
#'make-backup-file-name--default-function
"A function to use instead of the default `make-backup-file-name'.
A value of nil gives the default `make-backup-file-name' behavior.
This could be buffer-local to do something special for specific
files. If you define it, you may need to change `backup-file-name-p'
@ -4155,8 +4158,7 @@ and `file-name-sans-versions' too.
See also `backup-directory-alist'."
:group 'backup
:type '(choice (const :tag "Default" nil)
(function :tag "Your function")))
:type '(function :tag "Your function"))
(defcustom backup-directory-alist nil
"Alist of filename patterns and backup directory names.
@ -4216,24 +4218,26 @@ Checks for files in `temporary-file-directory',
Normally this will just be the file's name with `~' appended.
Customization hooks are provided as follows.
If the variable `make-backup-file-name-function' is non-nil, its value
should be a function which will be called with FILE as its argument;
the resulting name is used.
The value of `make-backup-file-name-function' should be a function which
will be called with FILE as its argument; the resulting name is used.
Otherwise a match for FILE is sought in `backup-directory-alist'; see
By default, a match for FILE is sought in `backup-directory-alist'; see
the documentation of that variable. If the directory for the backup
doesn't exist, it is created."
(if make-backup-file-name-function
(funcall make-backup-file-name-function file)
(if (and (eq system-type 'ms-dos)
(not (msdos-long-file-names)))
(let ((fn (file-name-nondirectory file)))
(concat (file-name-directory file)
(or (and (string-match "\\`[^.]+\\'" fn)
(concat (match-string 0 fn) ".~"))
(and (string-match "\\`[^.]+\\.\\(..?\\)?" fn)
(concat (match-string 0 fn) "~")))))
(concat (make-backup-file-name-1 file) "~"))))
(funcall (or make-backup-file-name-function
#'make-backup-file-name--default-function)
file))
(defun make-backup-file-name--default-function (file)
(if (and (eq system-type 'ms-dos)
(not (msdos-long-file-names)))
(let ((fn (file-name-nondirectory file)))
(concat (file-name-directory file)
(or (and (string-match "\\`[^.]+\\'" fn)
(concat (match-string 0 fn) ".~"))
(and (string-match "\\`[^.]+\\.\\(..?\\)?" fn)
(concat (match-string 0 fn) "~")))))
(concat (make-backup-file-name-1 file) "~")))
(defun make-backup-file-name-1 (file)
"Subroutine of `make-backup-file-name' and `find-backup-file-name'."
@ -5254,14 +5258,20 @@ It also has access to the `preserve-modes' argument of `revert-buffer'
via the `revert-buffer-preserve-modes' dynamic variable.")
(put 'revert-buffer-insert-file-contents-function 'permanent-local t)
(defvar revert-buffer-insert-file-contents-function nil
(defvar revert-buffer-insert-file-contents-function
#'revert-buffer-insert-file-contents--default-function
"Function to use to insert contents when reverting this buffer.
Gets two args, first the nominal file name to use,
and second, t if reading the auto-save file.
The function you specify is responsible for updating (or preserving) point.")
(defvar buffer-stale-function nil
(defun buffer-stale--default-function (&optional _noconfirm)
(and buffer-file-name
(file-readable-p buffer-file-name)
(not (verify-visited-file-modtime (current-buffer)))))
(defvar buffer-stale-function #'buffer-stale--default-function
"Function to check whether a non-file buffer needs reverting.
This should be a function with one optional argument NOCONFIRM.
Auto Revert Mode passes t for NOCONFIRM. The function should return
@ -5382,62 +5392,11 @@ non-nil, it is called instead of rereading visited file contents."
(local-hook (when (local-variable-p 'after-revert-hook)
after-revert-hook))
(inhibit-read-only t))
(cond
(revert-buffer-insert-file-contents-function
(unless (eq buffer-undo-list t)
;; Get rid of all undo records for this buffer.
(setq buffer-undo-list nil))
;; Don't make undo records for the reversion.
(let ((buffer-undo-list t))
(funcall revert-buffer-insert-file-contents-function
file-name auto-save-p)))
((not (file-exists-p file-name))
(error (if buffer-file-number
"File %s no longer exists!"
"Cannot revert nonexistent file %s")
file-name))
((not (file-readable-p file-name))
(error (if buffer-file-number
"File %s no longer readable!"
"Cannot revert unreadable file %s")
file-name))
(t
;; Bind buffer-file-name to nil
;; so that we don't try to lock the file.
(let ((buffer-file-name nil))
(or auto-save-p
(unlock-buffer)))
(widen)
(let ((coding-system-for-read
;; Auto-saved file should be read by Emacs's
;; internal coding.
(if auto-save-p 'auto-save-coding
(or coding-system-for-read
(and
buffer-file-coding-system-explicit
(car buffer-file-coding-system-explicit))))))
(if (and (not enable-multibyte-characters)
coding-system-for-read
(not (memq (coding-system-base
coding-system-for-read)
'(no-conversion raw-text))))
;; As a coding system suitable for multibyte
;; buffer is specified, make the current
;; buffer multibyte.
(set-buffer-multibyte t))
;; This force after-insert-file-set-coding
;; (called from insert-file-contents) to set
;; buffer-file-coding-system to a proper value.
(kill-local-variable 'buffer-file-coding-system)
;; Note that this preserves point in an intelligent way.
(if revert-buffer-preserve-modes
(let ((buffer-file-format buffer-file-format))
(insert-file-contents file-name (not auto-save-p)
nil nil t))
(insert-file-contents file-name (not auto-save-p)
nil nil t)))))
;; FIXME: Throw away undo-log when preserve-modes is nil?
(funcall
(or revert-buffer-insert-file-contents-function
#'revert-buffer-insert-file-contents--default-function)
file-name auto-save-p)
;; Recompute the truename in case changes in symlinks
;; have changed the truename.
(setq buffer-file-truename
@ -5452,6 +5411,56 @@ non-nil, it is called instead of rereading visited file contents."
(run-hooks 'revert-buffer-internal-hook))
t)))))
(defun revert-buffer-insert-file-contents--default-function (file-name auto-save-p)
(cond
((not (file-exists-p file-name))
(error (if buffer-file-number
"File %s no longer exists!"
"Cannot revert nonexistent file %s")
file-name))
((not (file-readable-p file-name))
(error (if buffer-file-number
"File %s no longer readable!"
"Cannot revert unreadable file %s")
file-name))
(t
;; Bind buffer-file-name to nil
;; so that we don't try to lock the file.
(let ((buffer-file-name nil))
(or auto-save-p
(unlock-buffer)))
(widen)
(let ((coding-system-for-read
;; Auto-saved file should be read by Emacs's
;; internal coding.
(if auto-save-p 'auto-save-coding
(or coding-system-for-read
(and
buffer-file-coding-system-explicit
(car buffer-file-coding-system-explicit))))))
(if (and (not enable-multibyte-characters)
coding-system-for-read
(not (memq (coding-system-base
coding-system-for-read)
'(no-conversion raw-text))))
;; As a coding system suitable for multibyte
;; buffer is specified, make the current
;; buffer multibyte.
(set-buffer-multibyte t))
;; This force after-insert-file-set-coding
;; (called from insert-file-contents) to set
;; buffer-file-coding-system to a proper value.
(kill-local-variable 'buffer-file-coding-system)
;; Note that this preserves point in an intelligent way.
(if revert-buffer-preserve-modes
(let ((buffer-file-format buffer-file-format))
(insert-file-contents file-name (not auto-save-p)
nil nil t))
(insert-file-contents file-name (not auto-save-p)
nil nil t))))))
(defun recover-this-file ()
"Recover the visited file--get contents from its last auto-save file."
(interactive)
@ -6204,9 +6213,10 @@ normally equivalent short `-D' option is just passed on to
;; directory if FILE is a symbolic link.
(unless full-directory-p
(setq switches
(if (stringp switches)
(concat switches " -d")
(add-to-list 'switches "-d" 'append))))
(cond
((stringp switches) (concat switches " -d"))
((member "-d" switches) switches)
(t (append switches '("-d"))))))
(apply 'call-process
insert-directory-program nil t nil
(append
@ -6479,7 +6489,7 @@ With prefix ARG, silently save all file-visiting buffers, then kill.
If emacsclient was started with a list of filenames to edit, then
only these files will be asked to be saved."
(interactive "P")
(if (frame-parameter (selected-frame) 'client)
(if (frame-parameter nil 'client)
(server-save-buffers-kill-terminal arg)
(save-buffers-kill-emacs arg)))

693
lisp/frameset.el Normal file
View file

@ -0,0 +1,693 @@
;;; frameset.el --- save and restore frame and window setup -*- lexical-binding: t -*-
;; Copyright (C) 2013 Free Software Foundation, Inc.
;; Author: Juanma Barranquero <lekktu@gmail.com>
;; Keywords: convenience
;; 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:
;; This file provides a set of operations to save a frameset (the state
;; of all or a subset of the existing frames and windows), both
;; in-session and persistently, and restore it at some point in the
;; future.
;;
;; It should be noted that restoring the frames' windows depends on
;; the buffers they are displaying, but this package does not provide
;; any way to save and restore sets of buffers (see desktop.el for
;; that). So, it's up to the user of frameset.el to make sure that
;; any relevant buffer is loaded before trying to restore a frameset.
;; When a window is restored and a buffer is missing, the window will
;; be deleted unless it is the last one in the frame, in which case
;; some previous buffer will be shown instead.
;;; Code:
(require 'cl-lib)
;; Framesets have two fields:
;; - properties: a property list to store both frameset-specific and
;; user-defined serializable data. Currently defined properties
;; include:
;; :version ID - Identifies the version of the frameset struct;
;; this is the only property always present and
;; must not be modified.
;; :app APPINFO - Freeform. Can be used by applications and
;; packages to indicate the intended (but by no
;; means exclusive) use of the frameset. For
;; example, currently desktop.el sets :app to
;; `(desktop . ,desktop-file-version).
;; :name NAME - The name of the frameset instance; a string.
;; :desc TEXT - A description for user consumption (to choose
;; among framesets, etc.); a string.
;; - states: an alist of items (FRAME-PARAMETERS . WINDOW-STATE) in
;; no particular order. Each item represents a frame to be
;; restored.
(cl-defstruct (frameset (:type list) :named
(:copier nil)
(:predicate nil))
properties ;; property list
states) ;; list of conses (frame-state . window-state)
(defun copy-frameset (frameset)
"Return a copy of FRAMESET.
This is a deep copy done with `copy-tree'."
(copy-tree frameset t))
;;;###autoload
(defun frameset-p (frameset)
"If FRAMESET is a frameset, return its :version.
Else return nil."
(and (eq (car-safe frameset) 'frameset)
(plist-get (cl-second frameset) :version)))
;; A setf'able accessor to the frameset's properties
(defun frameset-prop (frameset prop)
"Return the value of the PROP property of FRAMESET.
Properties other than :version can be set with
(setf (frameset-prop FRAMESET PROP) NEW-VALUE)"
(plist-get (frameset-properties frameset) prop))
(gv-define-setter frameset-prop (val fs prop)
(macroexp-let2 nil v val
`(progn
(cl-assert (not (eq ,prop :version)) t ":version can not be set")
(setf (frameset-properties ,fs)
(plist-put (frameset-properties ,fs) ,prop ,v))
,v)))
;; Filtering
(defvar frameset-filter-alist
'((background-color . frameset-filter-sanitize-color)
(buffer-list . t)
(buffer-predicate . t)
(buried-buffer-list . t)
(font . frameset-filter-save-parm)
(foreground-color . frameset-filter-sanitize-color)
(fullscreen . frameset-filter-save-parm)
(GUI:font . frameset-filter-restore-parm)
(GUI:fullscreen . frameset-filter-restore-parm)
(GUI:height . frameset-filter-restore-parm)
(GUI:width . frameset-filter-restore-parm)
(height . frameset-filter-save-parm)
(left . frameset-filter-iconified)
(minibuffer . frameset-filter-minibuffer)
(top . frameset-filter-iconified)
(width . frameset-filter-save-parm))
"Alist of frame parameters and filtering functions.
Each element is a cons (PARAM . ACTION), where PARAM is a parameter
name (a symbol identifying a frame parameter), and ACTION can be:
t The parameter is always removed from the parameter list.
:save The parameter is removed when saving the frame.
:restore The parameter is removed when restoring the frame.
FILTER A filter function.
FILTER can be a symbol FILTER-FUN, or a list (FILTER-FUN ARGS...).
It will be called with four arguments CURRENT, FILTERED, PARAMETERS
and SAVING, plus any additional ARGS:
CURRENT A cons (PARAM . VALUE), where PARAM is the one being
filtered and VALUE is its current value.
FILTERED The alist of parameters filtered so far.
PARAMETERS The complete alist of parameters being filtered,
SAVING Non-nil if filtering before saving state, nil otherwise.
The FILTER-FUN function must return:
nil CURRENT is removed from the list.
t CURRENT is left as is.
(PARAM' . VALUE') Replace CURRENT with this.
Frame parameters not on this list are passed intact.")
(defvar frameset--target-display nil
;; Either (minibuffer . VALUE) or nil.
;; This refers to the current frame config being processed inside
;; `frame--restore-frames' and its auxiliary functions (like filtering).
;; If nil, there is no need to change the display.
;; If non-nil, display parameter to use when creating the frame.
"Internal use only.")
(defun frameset-switch-to-gui-p (parameters)
"True when switching to a graphic display.
Return t if PARAMETERS describes a text-only terminal and
the target is a graphic display; otherwise return nil.
Only meaningful when called from a filtering function in
`frameset-filter-alist'."
(and frameset--target-display ; we're switching
(null (cdr (assq 'display parameters))) ; from a tty
(cdr frameset--target-display))) ; to a GUI display
(defun frameset-switch-to-tty-p (parameters)
"True when switching to a text-only terminal.
Return t if PARAMETERS describes a graphic display and
the target is a text-only terminal; otherwise return nil.
Only meaningful when called from a filtering function in
`frameset-filter-alist'."
(and frameset--target-display ; we're switching
(cdr (assq 'display parameters)) ; from a GUI display
(null (cdr frameset--target-display)))) ; to a tty
(defun frameset-filter-sanitize-color (current _filtered parameters saving)
"When switching to a GUI frame, remove \"unspecified\" colors.
Useful as a filter function for tty-specific parameters."
(or saving
(not (frameset-switch-to-gui-p parameters))
(not (stringp (cdr current)))
(not (string-match-p "^unspecified-[fb]g$" (cdr current)))))
(defun frameset-filter-minibuffer (current _filtered _parameters saving)
"When saving, convert (minibuffer . #<window>) parameter to (minibuffer . t)."
(or (not saving)
(if (windowp (cdr current))
'(minibuffer . t)
t)))
(defun frameset-filter-save-parm (current _filtered parameters saving
&optional prefix)
"When switching to a tty frame, save parameter P as PREFIX:P.
The parameter can be later restored with `frameset-filter-restore-parm'.
PREFIX defaults to `GUI'."
(unless prefix (setq prefix 'GUI))
(cond (saving t)
((frameset-switch-to-tty-p parameters)
(let ((prefix:p (intern (format "%s:%s" prefix (car current)))))
(if (assq prefix:p parameters)
nil
(cons prefix:p (cdr current)))))
((frameset-switch-to-gui-p parameters)
(not (assq (intern (format "%s:%s" prefix (car current))) parameters)))
(t t)))
(defun frameset-filter-restore-parm (current filtered parameters saving)
"When switching to a GUI frame, restore PREFIX:P parameter as P.
CURRENT must be of the form (PREFIX:P . value)."
(or saving
(not (frameset-switch-to-gui-p parameters))
(let* ((prefix:p (symbol-name (car current)))
(p (intern (substring prefix:p
(1+ (string-match-p ":" prefix:p)))))
(val (cdr current))
(found (assq p filtered)))
(if (not found)
(cons p val)
(setcdr found val)
nil))))
(defun frameset-filter-iconified (_current _filtered parameters saving)
"Remove CURRENT when saving an iconified frame.
This is used for positions parameters `left' and `top', which are
meaningless in an iconified frame, so the frame is restored in a
default position."
(not (and saving (eq (cdr (assq 'visibility parameters)) 'icon))))
(defun frameset-keep-original-display-p (force-display)
"True if saved frames' displays should be honored."
(cond ((daemonp) t)
((eq system-type 'windows-nt) nil)
(t (null force-display))))
(defun frameset-filter-params (parameters filter-alist saving)
"Filter parameter list PARAMETERS and return a filtered list.
FILTER-ALIST is an alist of parameter filters, in the format of
`frameset-filter-alist' (which see).
SAVING is non-nil while filtering parameters to save a frameset,
nil while the filtering is done to restore it."
(let ((filtered nil))
(dolist (current parameters)
(pcase (cdr (assq (car current) filter-alist))
(`nil
(push current filtered))
(`t
nil)
(:save
(unless saving (push current filtered)))
(:restore
(when saving (push current filtered)))
((or `(,fun . ,args) (and fun (pred fboundp)))
(let ((this (apply fun current filtered parameters saving args)))
(when this
(push (if (eq this t) current this) filtered))))
(other
(delay-warning 'frameset (format "Unknown filter %S" other) :error))))
;; Set the display parameter after filtering, so that filter functions
;; have access to its original value.
(when frameset--target-display
(let ((display (assq 'display filtered)))
(if display
(setcdr display (cdr frameset--target-display))
(push frameset--target-display filtered))))
filtered))
;; Saving framesets
(defun frameset--set-id (frame)
"Set FRAME's `frameset-id' if not yet set.
Internal use only."
(unless (frame-parameter frame 'frameset-id)
(set-frame-parameter frame
'frameset-id
(mapconcat (lambda (n) (format "%04X" n))
(cl-loop repeat 4 collect (random 65536))
"-"))))
(defun frameset--process-minibuffer-frames (frame-list)
"Process FRAME-LIST and record minibuffer relationships.
FRAME-LIST is a list of frames."
;; Record frames with their own minibuffer
(dolist (frame (minibuffer-frame-list))
(when (memq frame frame-list)
(frameset--set-id frame)
;; For minibuffer-owning frames, frameset--mini is a cons
;; (t . DEFAULT?), where DEFAULT? is a boolean indicating whether
;; the frame is the one pointed out by `default-minibuffer-frame'.
(set-frame-parameter frame
'frameset--mini
(cons t (eq frame default-minibuffer-frame)))))
;; Now link minibufferless frames with their minibuffer frames
(dolist (frame frame-list)
(unless (frame-parameter frame 'frameset--mini)
(frameset--set-id frame)
(let* ((mb-frame (window-frame (minibuffer-window frame)))
(id (and mb-frame (frame-parameter mb-frame 'frameset-id))))
(if (null id)
(error "Minibuffer frame %S for %S is excluded" mb-frame frame)
;; For minibufferless frames, frameset--mini is a cons
;; (nil . FRAME-ID), where FRAME-ID is the frameset-id of
;; the frame containing its minibuffer window.
(set-frame-parameter frame
'frameset--mini
(cons nil id)))))))
;;;###autoload
(cl-defun frameset-save (frame-list &key filters predicate properties)
"Return the frameset of FRAME-LIST, a list of frames.
If nil, FRAME-LIST defaults to all live frames.
FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'.
PREDICATE is a predicate function, which must return non-nil for frames that
should be saved; it defaults to saving all frames from FRAME-LIST.
PROPERTIES is a user-defined property list to add to the frameset."
(let ((frames (cl-delete-if-not #'frame-live-p
(cl-delete-if-not (or predicate #'framep)
(or (copy-sequence frame-list)
(frame-list))))))
(frameset--process-minibuffer-frames frames)
(make-frameset :properties (append '(:version 1) properties)
:states (mapcar
(lambda (frame)
(cons
(frameset-filter-params (frame-parameters frame)
(or filters
frameset-filter-alist)
t)
(window-state-get (frame-root-window frame) t)))
frames))))
;; Restoring framesets
(defvar frameset--reuse-list nil
"Internal use only.")
(defun frameset--compute-pos (value left/top right/bottom)
(pcase value
(`(+ ,val) (+ left/top val))
(`(- ,val) (+ right/bottom val))
(val val)))
(defun frameset--move-onscreen (frame force-onscreen)
"If FRAME is offscreen, move it back onscreen and, if necessary, resize it.
For the description of FORCE-ONSCREEN, see `frameset-restore'.
When forced onscreen, frames wider than the monitor's workarea are converted
to fullwidth, and frames taller than the workarea are converted to fullheight.
NOTE: This only works for non-iconified frames. Internal use only."
(pcase-let* ((`(,left ,top ,width ,height) (cl-cdadr (frame-monitor-attributes frame)))
(right (+ left width -1))
(bottom (+ top height -1))
(fr-left (frameset--compute-pos (frame-parameter frame 'left) left right))
(fr-top (frameset--compute-pos (frame-parameter frame 'top) top bottom))
(ch-width (frame-char-width frame))
(ch-height (frame-char-height frame))
(fr-width (max (frame-pixel-width frame) (* ch-width (frame-width frame))))
(fr-height (max (frame-pixel-height frame) (* ch-height (frame-height frame))))
(fr-right (+ fr-left fr-width -1))
(fr-bottom (+ fr-top fr-height -1)))
(when (pcase force-onscreen
;; Any corner is outside the screen.
(`all (or (< fr-bottom top) (> fr-bottom bottom)
(< fr-left left) (> fr-left right)
(< fr-right left) (> fr-right right)
(< fr-top top) (> fr-top bottom)))
;; Displaced to the left, right, above or below the screen.
(`t (or (> fr-left right)
(< fr-right left)
(> fr-top bottom)
(< fr-bottom top)))
;; Fully inside, no need to do anything.
(_ nil))
(let ((fullwidth (> fr-width width))
(fullheight (> fr-height height))
(params nil))
;; Position frame horizontally.
(cond (fullwidth
(push `(left . ,left) params))
((> fr-right right)
(push `(left . ,(+ left (- width fr-width))) params))
((< fr-left left)
(push `(left . ,left) params)))
;; Position frame vertically.
(cond (fullheight
(push `(top . ,top) params))
((> fr-bottom bottom)
(push `(top . ,(+ top (- height fr-height))) params))
((< fr-top top)
(push `(top . ,top) params)))
;; Compute fullscreen state, if required.
(when (or fullwidth fullheight)
(push (cons 'fullscreen
(cond ((not fullwidth) 'fullheight)
((not fullheight) 'fullwidth)
(t 'maximized)))
params))
;; Finally, move the frame back onscreen.
(when params
(modify-frame-parameters frame params))))))
(defun frameset--find-frame (predicate display &rest args)
"Find a frame in `frameset--reuse-list' satisfying PREDICATE.
Look through available frames whose display property matches DISPLAY
and return the first one for which (PREDICATE frame ARGS) returns t.
If PREDICATE is nil, it is always satisfied. Internal use only."
(cl-find-if (lambda (frame)
(and (equal (frame-parameter frame 'display) display)
(or (null predicate)
(apply predicate frame args))))
frameset--reuse-list))
(defun frameset--reuse-frame (display frame-cfg)
"Look for an existing frame to reuse.
DISPLAY is the display where the frame will be shown, and FRAME-CFG
is the parameter list of the frame being restored. Internal use only."
(let ((frame nil)
mini)
;; There are no fancy heuristics there. We could implement some
;; based on frame size and/or position, etc., but it is not clear
;; that any "gain" (in the sense of reduced flickering, etc.) is
;; worth the added complexity. In fact, the code below mainly
;; tries to work nicely when M-x desktop-read is used after a
;; desktop session has already been loaded. The other main use
;; case, which is the initial desktop-read upon starting Emacs,
;; will usually have only one frame, and should already work.
(cond ((null display)
;; When the target is tty, every existing frame is reusable.
(setq frame (frameset--find-frame nil display)))
((car (setq mini (cdr (assq 'frameset--mini frame-cfg))))
;; If the frame has its own minibuffer, let's see whether
;; that frame has already been loaded (which can happen after
;; M-x desktop-read).
(setq frame (frameset--find-frame
(lambda (f id)
(string= (frame-parameter f 'frameset-id) id))
display (cdr mini)))
;; If it has not been loaded, and it is not a minibuffer-only frame,
;; let's look for an existing non-minibuffer-only frame to reuse.
(unless (or frame (eq (cdr (assq 'minibuffer frame-cfg)) 'only))
(setq frame (frameset--find-frame
(lambda (f)
(let ((w (frame-parameter f 'minibuffer)))
(and (window-live-p w)
(window-minibuffer-p w)
(eq (window-frame w) f))))
display))))
(mini
;; For minibufferless frames, check whether they already exist,
;; and that they are linked to the right minibuffer frame.
(setq frame (frameset--find-frame
(lambda (f id mini-id)
(and (string= (frame-parameter f 'frameset-id) id)
(string= (frame-parameter (window-frame (minibuffer-window f))
'frameset-id)
mini-id)))
display (cdr (assq 'frameset-id frame-cfg)) (cdr mini))))
(t
;; Default to just finding a frame in the same display.
(setq frame (frameset--find-frame nil display))))
;; If found, remove from the list.
(when frame
(setq frameset--reuse-list (delq frame frameset--reuse-list)))
frame))
(defun frameset--get-frame (frame-cfg window-cfg filters force-onscreen)
"Set up and return a frame according to its saved state.
That means either reusing an existing frame or creating one anew.
FRAME-CFG is the frame's parameter list; WINDOW-CFG is its window state.
For the meaning of FORCE-ONSCREEN, see `frameset-restore'."
(let* ((fullscreen (cdr (assq 'fullscreen frame-cfg)))
(lines (assq 'tool-bar-lines frame-cfg))
(filtered-cfg (frameset-filter-params frame-cfg filters nil))
(display (cdr (assq 'display filtered-cfg))) ;; post-filtering
alt-cfg frame)
;; This works around bug#14795 (or feature#14795, if not a bug :-)
(setq filtered-cfg (assq-delete-all 'tool-bar-lines filtered-cfg))
(push '(tool-bar-lines . 0) filtered-cfg)
(when fullscreen
;; Currently Emacs has the limitation that it does not record the size
;; and position of a frame before maximizing it, so we cannot save &
;; restore that info. Instead, when restoring, we resort to creating
;; invisible "fullscreen" frames of default size and then maximizing them
;; (and making them visible) which at least is somewhat user-friendly
;; when these frames are later de-maximized.
(let ((width (and (eq fullscreen 'fullheight) (cdr (assq 'width filtered-cfg))))
(height (and (eq fullscreen 'fullwidth) (cdr (assq 'height filtered-cfg))))
(visible (assq 'visibility filtered-cfg)))
(setq filtered-cfg (cl-delete-if (lambda (p)
(memq p '(visibility fullscreen width height)))
filtered-cfg :key #'car))
(when width
(setq filtered-cfg (append `((user-size . t) (width . ,width))
filtered-cfg)))
(when height
(setq filtered-cfg (append `((user-size . t) (height . ,height))
filtered-cfg)))
;; These are parameters to apply after creating/setting the frame.
(push visible alt-cfg)
(push (cons 'fullscreen fullscreen) alt-cfg)))
;; Time to find or create a frame an apply the big bunch of parameters.
;; If a frame needs to be created and it falls partially or fully offscreen,
;; sometimes it gets "pushed back" onscreen; however, moving it afterwards is
;; allowed. So we create the frame as invisible and then reapply the full
;; parameter list (including position and size parameters).
(setq frame (or (and frameset--reuse-list
(frameset--reuse-frame display filtered-cfg))
(make-frame-on-display display
(cons '(visibility)
(cl-loop
for param in '(left top width height minibuffer)
collect (assq param filtered-cfg))))))
(modify-frame-parameters frame
(if (eq (frame-parameter frame 'fullscreen) fullscreen)
;; Workaround for bug#14949
(assq-delete-all 'fullscreen filtered-cfg)
filtered-cfg))
;; If requested, force frames to be onscreen.
(when (and force-onscreen
;; FIXME: iconified frames should be checked too,
;; but it is impossible without deiconifying them.
(not (eq (frame-parameter frame 'visibility) 'icon)))
(frameset--move-onscreen frame force-onscreen))
;; Let's give the finishing touches (visibility, tool-bar, maximization).
(when lines (push lines alt-cfg))
(when alt-cfg (modify-frame-parameters frame alt-cfg))
;; Now restore window state.
(window-state-put window-cfg (frame-root-window frame) 'safe)
frame))
(defun frameset--sort-states (state1 state2)
"Predicate to sort frame states in a suitable order to be created.
It sorts minibuffer-owning frames before minibufferless ones."
(pcase-let ((`(,hasmini1 ,id-def1) (assq 'frameset--mini (car state1)))
(`(,hasmini2 ,id-def2) (assq 'frameset--mini (car state2))))
(cond ((eq id-def1 t) t)
((eq id-def2 t) nil)
((not (eq hasmini1 hasmini2)) (eq hasmini1 t))
((eq hasmini1 nil) (string< id-def1 id-def2))
(t t))))
(defun frameset-sort-frames-for-deletion (frame1 _frame2)
"Predicate to sort live frames for deletion.
Minibufferless frames must go first to avoid errors when attempting
to delete a frame whose minibuffer window is used by another frame."
(not (frame-parameter frame1 'minibuffer)))
;;;###autoload
(cl-defun frameset-restore (frameset &key filters reuse-frames force-display force-onscreen)
"Restore a FRAMESET into the current display(s).
FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'.
REUSE-FRAMES describes how to reuse existing frames while restoring a frameset:
t Reuse any existing frame if possible; delete leftover frames.
nil Restore frameset in new frames and delete existing frames.
keep Restore frameset in new frames and keep the existing ones.
LIST A list of frames to reuse; only these will be reused, if possible,
and any leftover one will be deleted; other frames not on this
list will be kept.
FORCE-DISPLAY can be:
t Frames will be restored in the current display.
nil Frames will be restored, if possible, in their original displays.
delete Frames in other displays will be deleted instead of restored.
FORCE-ONSCREEN can be:
all Force onscreen any frame fully or partially offscreen.
t Force onscreen only those frames that are fully offscreen.
nil Do not force any frame back onscreen.
All keywords default to nil."
(cl-assert (frameset-p frameset))
(let* ((delete-saved (eq force-display 'delete))
(forcing (not (frameset-keep-original-display-p force-display)))
(target (and forcing (cons 'display (frame-parameter nil 'display))))
other-frames)
;; frameset--reuse-list is a list of frames potentially reusable. Later we
;; will decide which ones can be reused, and how to deal with any leftover.
(pcase reuse-frames
((or `nil `keep)
(setq frameset--reuse-list nil
other-frames (frame-list)))
((pred consp)
(setq frameset--reuse-list (copy-sequence reuse-frames)
other-frames (cl-delete-if (lambda (frame)
(memq frame frameset--reuse-list))
(frame-list))))
(_
(setq frameset--reuse-list (frame-list)
other-frames nil)))
;; Sort saved states to guarantee that minibufferless frames will be created
;; after the frames that contain their minibuffer windows.
(dolist (state (sort (copy-sequence (frameset-states frameset))
#'frameset--sort-states))
(condition-case-unless-debug err
(pcase-let* ((`(,frame-cfg . ,window-cfg) state)
((and d-mini `(,hasmini . ,mb-id))
(cdr (assq 'frameset--mini frame-cfg)))
(default (and (booleanp mb-id) mb-id))
(frame nil) (to-tty nil))
;; Only set target if forcing displays and the target display is different.
(if (or (not forcing)
(equal target (or (assq 'display frame-cfg) '(display . nil))))
(setq frameset--target-display nil)
(setq frameset--target-display target
to-tty (null (cdr target))))
;; If keeping non-reusable frames, and the frame-id of one of them
;; matches the frame-id of a frame being restored (because, for example,
;; the frameset has already been read in the same session), remove the
;; frame-id from the non-reusable frame, which is not useful anymore.
(when (and other-frames
(or (eq reuse-frames 'keep) (consp reuse-frames)))
(let ((dup (cl-find (cdr (assq 'frameset-frame-id frame-cfg))
other-frames
:key (lambda (frame)
(frame-parameter frame 'frameset-frame-id))
:test #'string=)))
(when dup
(set-frame-parameter dup 'frameset-frame-id nil))))
;; Time to restore frames and set up their minibuffers as they were.
;; We only skip a frame (thus deleting it) if either:
;; - we're switching displays, and the user chose the option to delete, or
;; - we're switching to tty, and the frame to restore is minibuffer-only.
(unless (and frameset--target-display
(or delete-saved
(and to-tty
(eq (cdr (assq 'minibuffer frame-cfg)) 'only))))
;; Restore minibuffers. Some of this stuff could be done in a filter
;; function, but it would be messy because restoring minibuffers affects
;; global state; it's best to do it here than add a bunch of global
;; variables to pass info back-and-forth to/from the filter function.
(cond
((null d-mini)) ;; No frameset--mini. Process as normal frame.
(to-tty) ;; Ignore minibuffer stuff and process as normal frame.
(hasmini ;; Frame has minibuffer (or it is minibuffer-only).
(when (eq (cdr (assq 'minibuffer frame-cfg)) 'only)
(setq frame-cfg (append '((tool-bar-lines . 0) (menu-bar-lines . 0))
frame-cfg))))
(t ;; Frame depends on other frame's minibuffer window.
(let* ((mb-frame (or (cl-find-if
(lambda (f)
(string= (frame-parameter f 'frameset-id)
mb-id))
(frame-list))
(error "Minibuffer frame %S not found" mb-id)))
(mb-param (assq 'minibuffer frame-cfg))
(mb-window (minibuffer-window mb-frame)))
(unless (and (window-live-p mb-window)
(window-minibuffer-p mb-window))
(error "Not a minibuffer window %s" mb-window))
(if mb-param
(setcdr mb-param mb-window)
(push (cons 'minibuffer mb-window) frame-cfg))))))
;; OK, we're ready at last to create (or reuse) a frame and
;; restore the window config.
(setq frame (frameset--get-frame frame-cfg window-cfg
(or filters frameset-filter-alist)
force-onscreen))
;; Set default-minibuffer if required.
(when default (setq default-minibuffer-frame frame)))
(error
(delay-warning 'frameset (error-message-string err) :error))))
;; In case we try to delete the initial frame, we want to make sure that
;; other frames are already visible (discussed in thread for bug#14841).
(sit-for 0 t)
;; Delete remaining frames, but do not fail if some resist being deleted.
(unless (eq reuse-frames 'keep)
(dolist (frame (sort (nconc (if (listp reuse-frames) nil other-frames)
frameset--reuse-list)
#'frameset-sort-frames-for-deletion))
(condition-case err
(delete-frame frame)
(error
(delay-warning 'frameset (error-message-string err))))))
(setq frameset--reuse-list nil)
;; Make sure there's at least one visible frame.
(unless (or (daemonp) (visible-frame-list))
(make-frame-visible (car (frame-list))))))
(provide 'frameset)
;;; frameset.el ends here

View file

@ -1,5 +1,76 @@
2013-08-02 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus-delay.el (gnus-delay-article): Fix typo.
* gnus-group.el (gnus-group-delete-articles): Allow deleting only "old"
articles.
* gnus-delay.el (gnus-delay-article): Run `message-send-hook' so that
we can get spell-checking etc.
2013-08-02 Katsumi Yamaoka <yamaoka@jpl.org>
* rfc2047.el (rfc2047-encode-message-header): Unify charsets into
a single one used for encoding the whole text in a header.
2013-08-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* message.el (message-ignored-news-headers): Delete X-Gnus-Delayed
before sending.
* mm-decode.el (mm-command-output): New face.
(mm-display-external): Use it.
2013-08-01 Kan-Ru Chen (陳侃如) <kanru@kanru.info> (tiny change)
* nnmbox.el (nnmbox-request-article): Don't change point.
2013-08-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus-icalendar.el (gnus-icalendar-event:inline-reply-buttons):
Include `handle' parameter.
2013-08-01 Jan Tatarik <jan.tatarik@gmail.com>
* gnus-icalendar.el: New file.
2013-08-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus-int.el (gnus-warp-to-article): Mention that warp means jump.
* gnus-uu.el (gnus-uu-mark-thread, gnus-uu-unmark-thread): Work with
dummy roots, too.
2013-08-01 David Edmondson <dme@dme.org>
* mml2015.el (mml2015-epg-key-image-to-string): Protect against bugging
out on ttys.
2013-08-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus-start.el (gnus-dribble-save): Only save the dribble file if it's
not empty.
* nnrss.el (nnrss-discover-feed): Indent.
2013-08-01 Katsumi Yamaoka <yamaoka@jpl.org>
* gnus-util.el (gnus-emacs-completing-read): Isolate XEmacs stuff.
2013-07-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
* gnus-start.el (gnus-read-active-for-groups): Always mark the data as
dirty to ensure nnimap data being saved.
2013-07-30 Tassilo Horn <tsdh@gnu.org>
* gnus-sum.el (gnus-summary-make-menu-bar): Add "Current thread score"
menu entry.
* gnus-score.el (gnus-summary-current-score): Use prefix arg to show
the current thread's total score instead of the current article's
score.
* gnus-sum.el (gnus-subthread-sort-functions): New defcustom.
(gnus-sort-threads-recursively): Delete defcustom.
(gnus-sort-threads-recursive): Adapt accordingly.

View file

@ -80,6 +80,8 @@ DELAY is a string, giving the length of the time. Possible values are:
(list (read-string
"Target date (YYYY-MM-DD), time (hh:mm), or length of delay (units in [mhdwMY]): "
gnus-delay-default-delay)))
;; Allow spell checking etc.
(run-hooks 'message-send-hook)
(let (num unit days year month day hour minute deadline)
(cond ((string-match
"\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\)"

View file

@ -2796,14 +2796,21 @@ server."
(lambda (group)
(gnus-group-delete-group group nil t))))))
(defun gnus-group-delete-articles (group)
"Delete all articles in the current group."
(interactive (list (gnus-group-group-name)))
(defun gnus-group-delete-articles (group &optional oldp)
"Delete all articles in the current group.
If OLDP (the prefix), only delete articles that are \"old\",
according to the expiry settings. Note that this will delete old
not-expirable articles, too."
(interactive (list (gnus-group-group-name)
current-prefix-arg))
(let ((articles (gnus-uncompress-range (gnus-active group))))
(when (gnus-yes-or-no-p
(format "Do you really want to delete these %d articles forever? "
(length articles)))
(gnus-request-expire-articles articles group 'force))))
(gnus-request-expire-articles articles group
(if current-prefix-arg
nil
'force)))))
(defun gnus-group-delete-group (group &optional force no-prompt)
"Delete the current group. Only meaningful with editable groups.

837
lisp/gnus/gnus-icalendar.el Normal file
View file

@ -0,0 +1,837 @@
;;; gnus-icalendar.el --- reply to iCalendar meeting requests
;; Copyright (C) 2013 Free Software Foundation, Inc.
;; Author: Jan Tatarik <Jan.Tatarik@gmail.com>
;; Keywords: mail, icalendar, org
;; This program 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.
;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; To install:
;; (require 'gnus-icalendar)
;; (gnus-icalendar-setup)
;; to enable optional iCalendar->Org sync functionality
;; NOTE: both the capture file and the headline(s) inside must already exist
;; (setq gnus-icalendar-org-capture-file "~/org/notes.org")
;; (setq gnus-icalendar-org-capture-headline '("Calendar"))
;; (gnus-icalendar-org-setup)
;;; Code:
(require 'icalendar)
(require 'eieio)
(require 'mm-decode)
(require 'gnus-sum)
(eval-when-compile (require 'cl))
(defun gnus-icalendar-find-if (pred seq)
(catch 'found
(while seq
(when (funcall pred (car seq))
(throw 'found (car seq)))
(pop seq))))
;;;
;;; ical-event
;;;
(defclass gnus-icalendar-event ()
((organizer :initarg :organizer
:accessor gnus-icalendar-event:organizer
:initform ""
:type (or null string))
(summary :initarg :summary
:accessor gnus-icalendar-event:summary
:initform ""
:type (or null string))
(description :initarg :description
:accessor gnus-icalendar-event:description
:initform ""
:type (or null string))
(location :initarg :location
:accessor gnus-icalendar-event:location
:initform ""
:type (or null string))
(start :initarg :start
:accessor gnus-icalendar-event:start
:initform ""
:type (or null string))
(end :initarg :end
:accessor gnus-icalendar-event:end
:initform ""
:type (or null string))
(recur :initarg :recur
:accessor gnus-icalendar-event:recur
:initform ""
:type (or null string))
(uid :initarg :uid
:accessor gnus-icalendar-event:uid
:type string)
(method :initarg :method
:accessor gnus-icalendar-event:method
:initform "PUBLISH"
:type (or null string))
(rsvp :initarg :rsvp
:accessor gnus-icalendar-event:rsvp
:initform nil
:type (or null boolean)))
"generic iCalendar Event class")
(defclass gnus-icalendar-event-request (gnus-icalendar-event)
nil
"iCalendar class for REQUEST events")
(defclass gnus-icalendar-event-cancel (gnus-icalendar-event)
nil
"iCalendar class for CANCEL events")
(defclass gnus-icalendar-event-reply (gnus-icalendar-event)
nil
"iCalendar class for REPLY events")
(defmethod gnus-icalendar-event:recurring-p ((event gnus-icalendar-event))
"Return t if EVENT is recurring."
(not (null (gnus-icalendar-event:recur event))))
(defmethod gnus-icalendar-event:recurring-freq ((event gnus-icalendar-event))
"Return recurring frequency of EVENT."
(let ((rrule (gnus-icalendar-event:recur event)))
(string-match "FREQ=\\([[:alpha:]]+\\)" rrule)
(match-string 1 rrule)))
(defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event))
"Return recurring interval of EVENT."
(let ((rrule (gnus-icalendar-event:recur event))
(default-interval 1))
(string-match "INTERVAL=\\([[:digit:]]+\\)" rrule)
(or (match-string 1 rrule)
default-interval)))
(defmethod gnus-icalendar-event:start-time ((event gnus-icalendar-event))
"Return time value of the EVENT start date."
(date-to-time (gnus-icalendar-event:start event)))
(defmethod gnus-icalendar-event:end-time ((event gnus-icalendar-event))
"Return time value of the EVENT end date."
(date-to-time (gnus-icalendar-event:end event)))
(defun gnus-icalendar-event--decode-datefield (ical field zone-map &optional date-style)
(let* ((calendar-date-style (or date-style 'european))
(date (icalendar--get-event-property ical field))
(date-zone (icalendar--find-time-zone
(icalendar--get-event-property-attributes
ical field)
zone-map))
(date-decoded (icalendar--decode-isodatetime date nil date-zone)))
(concat (icalendar--datetime-to-iso-date date-decoded "-")
" "
(icalendar--datetime-to-colontime date-decoded))))
(defun gnus-icalendar-event--find-attendee (ical name-or-email)
(let* ((event (car (icalendar--all-events ical)))
(event-props (caddr event)))
(labels ((attendee-name (att) (plist-get (cadr att) 'CN))
(attendee-email (att)
(replace-regexp-in-string "^.*MAILTO:" "" (caddr att)))
(attendee-prop-matches-p (prop)
(and (eq (car prop) 'ATTENDEE)
(or (member (attendee-name prop) name-or-email)
(let ((att-email (attendee-email prop)))
(gnus-icalendar-find-if (lambda (email)
(string-match email att-email))
name-or-email))))))
(gnus-icalendar-find-if #'attendee-prop-matches-p event-props))))
(defun gnus-icalendar-event-from-ical (ical &optional attendee-name-or-email)
(let* ((event (car (icalendar--all-events ical)))
(zone-map (icalendar--convert-all-timezones ical))
(organizer (replace-regexp-in-string
"^.*MAILTO:" ""
(or (icalendar--get-event-property event 'ORGANIZER) "")))
(prop-map '((summary . SUMMARY)
(description . DESCRIPTION)
(location . LOCATION)
(recur . RRULE)
(uid . UID)))
(method (caddr (assoc 'METHOD (caddr (car (nreverse ical))))))
(attendee (when attendee-name-or-email
(gnus-icalendar-event--find-attendee ical attendee-name-or-email)))
(args (list :method method
:organizer organizer
:start (gnus-icalendar-event--decode-datefield event 'DTSTART zone-map)
:end (gnus-icalendar-event--decode-datefield event 'DTEND zone-map)
:rsvp (string= (plist-get (cadr attendee) 'RSVP)
"TRUE")))
(event-class (pcase method
("REQUEST" 'gnus-icalendar-event-request)
("CANCEL" 'gnus-icalendar-event-cancel)
("REPLY" 'gnus-icalendar-event-reply)
(_ 'gnus-icalendar-event))))
(labels ((map-property (prop)
(let ((value (icalendar--get-event-property event prop)))
(when value
;; ugly, but cannot get
;;replace-regexp-in-string work with "\\" as
;;REP, plus we should also handle "\\;"
(replace-regexp-in-string
"\\\\," ","
(replace-regexp-in-string
"\\\\n" "\n" (substring-no-properties value))))))
(accumulate-args (mapping)
(destructuring-bind (slot . ical-property) mapping
(setq args (append (list
(intern (concat ":" (symbol-name slot)))
(map-property ical-property))
args)))))
(mapc #'accumulate-args prop-map)
(apply 'make-instance event-class args))))
(defun gnus-icalendar-event-from-buffer (buf &optional attendee-name-or-email)
"Parse RFC5545 iCalendar in buffer BUF and return an event object.
Return a gnus-icalendar-event object representing the first event
contained in the invitation. Return nil for calendars without an event entry.
ATTENDEE-NAME-OR-EMAIL is a list of strings that will be matched
against the event's attendee names and emails. Invitation rsvp
status will be retrieved from the first matching attendee record."
(let ((ical (with-current-buffer (icalendar--get-unfolded-buffer (get-buffer buf))
(goto-char (point-min))
(icalendar--read-element nil nil))))
(when ical
(gnus-icalendar-event-from-ical ical attendee-name-or-email))))
;;;
;;; gnus-icalendar-event-reply
;;;
(defun gnus-icalendar-event--build-reply-event-body (ical-request status identities)
(let ((summary-status (capitalize (symbol-name status)))
(attendee-status (upcase (symbol-name status)))
reply-event-lines)
(labels ((update-summary (line)
(if (string-match "^[^:]+:" line)
(replace-match (format "\\&%s: " summary-status) t nil line)
line))
(update-dtstamp ()
(format-time-string "DTSTAMP:%Y%m%dT%H%M%SZ" nil t))
(attendee-matches-identity (line)
(gnus-icalendar-find-if (lambda (name) (string-match-p name line))
identities))
(update-attendee-status (line)
(when (and (attendee-matches-identity line)
(string-match "\\(PARTSTAT=\\)[^;]+" line))
(replace-match (format "\\1%s" attendee-status) t nil line)))
(process-event-line (line)
(when (string-match "^\\([^;:]+\\)" line)
(let* ((key (match-string 0 line))
;; NOTE: not all of the below fields are mandatory,
;; but they are often present in other clients'
;; replies. Can be helpful for debugging, too.
(new-line (pcase key
("ATTENDEE" (update-attendee-status line))
("SUMMARY" (update-summary line))
("DTSTAMP" (update-dtstamp))
((or "ORGANIZER" "DTSTART" "DTEND"
"LOCATION" "DURATION" "SEQUENCE"
"RECURRENCE-ID" "UID") line)
(_ nil))))
(when new-line
(push new-line reply-event-lines))))))
(mapc #'process-event-line (split-string ical-request "\n"))
(unless (gnus-icalendar-find-if (lambda (x) (string-match "^ATTENDEE" x))
reply-event-lines)
(error "Could not find an event attendee matching given identity"))
(mapconcat #'identity `("BEGIN:VEVENT"
,@(nreverse reply-event-lines)
"END:VEVENT")
"\n"))))
(defun gnus-icalendar-event-reply-from-buffer (buf status identities)
"Build a calendar event reply for request contained in BUF.
The reply will have STATUS (`accepted', `tentative' or `declined').
The reply will be composed for attendees matching any entry
on the IDENTITIES list."
(flet ((extract-block (blockname)
(save-excursion
(let ((block-start-re (format "^BEGIN:%s" blockname))
(block-end-re (format "^END:%s" blockname))
start)
(when (re-search-forward block-start-re nil t)
(setq start (line-beginning-position))
(re-search-forward block-end-re)
(buffer-substring-no-properties start (line-end-position)))))))
(let (zone event)
(with-current-buffer (icalendar--get-unfolded-buffer (get-buffer buf))
(goto-char (point-min))
(setq zone (extract-block "VTIMEZONE")
event (extract-block "VEVENT")))
(when event
(let ((contents (list "BEGIN:VCALENDAR"
"METHOD:REPLY"
"PRODID:Gnus"
"VERSION:2.0"
zone
(gnus-icalendar-event--build-reply-event-body event status identities)
"END:VCALENDAR")))
(mapconcat #'identity (delq nil contents) "\n"))))))
;;;
;;; gnus-icalendar-org
;;;
;;; TODO: this is an optional feature, and it's only available with org-mode
;;; 7+, so will need to properly handle emacsen with no/outdated org-mode
(require 'org)
(require 'org-capture)
(defgroup gnus-icalendar-org nil
"Settings for Calendar Event gnus/org integration."
:group 'gnus-icalendar
:prefix "gnus-icalendar-org-")
(defcustom gnus-icalendar-org-capture-file nil
"Target Org file for storing captured calendar events."
:type 'file
:group 'gnus-icalendar-org)
(defcustom gnus-icalendar-org-capture-headline nil
"Target outline in `gnus-icalendar-org-capture-file' for storing captured events."
:type '(repeat string)
:group 'gnus-icalendar-org)
(defcustom gnus-icalendar-org-template-name "used by gnus-icalendar-org"
"Org-mode template name."
:type '(string)
:group 'gnus-icalendar-org)
(defcustom gnus-icalendar-org-template-key "#"
"Org-mode template hotkey."
:type '(string)
:group 'gnus-icalendar-org)
(defvar gnus-icalendar-org-enabled-p nil)
(defmethod gnus-icalendar-event:org-repeat ((event gnus-icalendar-event))
"Return `org-mode' timestamp repeater string for recurring EVENT.
Return nil for non-recurring EVENT."
(when (gnus-icalendar-event:recurring-p event)
(let* ((freq-map '(("HOURLY" . "h")
("DAILY" . "d")
("WEEKLY" . "w")
("MONTHLY" . "m")
("YEARLY" . "y")))
(org-freq (cdr (assoc (gnus-icalendar-event:recurring-freq event) freq-map))))
(when org-freq
(format "+%s%s" (gnus-icalendar-event:recurring-interval event) org-freq)))))
(defmethod gnus-icalendar-event:org-timestamp ((event gnus-icalendar-event))
"Build `org-mode' timestamp from EVENT start/end dates and recurrence info."
(let* ((start (gnus-icalendar-event:start-time event))
(end (gnus-icalendar-event:end-time event))
(start-date (format-time-string "%Y-%m-%d %a" start t))
(start-time (format-time-string "%H:%M" start t))
(end-date (format-time-string "%Y-%m-%d %a" end t))
(end-time (format-time-string "%H:%M" end t))
(org-repeat (gnus-icalendar-event:org-repeat event))
(repeat (if org-repeat (concat " " org-repeat) "")))
(if (equal start-date end-date)
(format "<%s %s-%s%s>" start-date start-time end-time repeat)
(format "<%s %s>--<%s %s>" start-date start-time end-date end-time))))
;; TODO: make the template customizable
(defmethod gnus-icalendar-event->org-entry ((event gnus-icalendar-event) reply-status)
"Return string with new `org-mode' entry describing EVENT."
(with-temp-buffer
(org-mode)
(with-slots (organizer summary description location
recur uid) event
(let* ((reply (if reply-status (capitalize (symbol-name reply-status))
"Not replied yet"))
(props `(("ICAL_EVENT" . "t")
("ID" . ,uid)
("DT" . ,(gnus-icalendar-event:org-timestamp event))
("ORGANIZER" . ,(gnus-icalendar-event:organizer event))
("LOCATION" . ,(gnus-icalendar-event:location event))
("RRULE" . ,(gnus-icalendar-event:recur event))
("REPLY" . ,reply))))
(insert (format "* %s (%s)\n\n" summary location))
(mapc (lambda (prop)
(org-entry-put (point) (car prop) (cdr prop)))
props))
(when description
(save-restriction
(narrow-to-region (point) (point))
(insert description)
(indent-region (point-min) (point-max) 2)
(fill-region (point-min) (point-max))))
(buffer-string))))
(defun gnus-icalendar--deactivate-org-timestamp (ts)
(replace-regexp-in-string "[<>]"
(lambda (m) (pcase m ("<" "[") (">" "]")))
ts))
(defun gnus-icalendar-find-org-event-file (event &optional org-file)
"Return the name of the file containing EVENT org entry.
Return nil when not found.
All org agenda files are searched for the EVENT entry. When
the optional ORG-FILE argument is specified, only that one file
is searched."
(let ((uid (gnus-icalendar-event:uid event))
(files (or org-file (org-agenda-files t 'ifmode))))
(flet
((find-event-in (file)
(org-check-agenda-file file)
(with-current-buffer (find-file-noselect file)
(let ((event-pos (org-find-entry-with-id uid)))
(when (and event-pos
(string= (cdr (assoc "ICAL_EVENT" (org-entry-properties event-pos)))
"t"))
(throw 'found file))))))
(gnus-icalendar-find-if #'find-event-in files))))
(defun gnus-icalendar--show-org-event (event &optional org-file)
(let ((file (gnus-icalendar-find-org-event-file event org-file)))
(when file
(switch-to-buffer (find-file file))
(goto-char (org-find-entry-with-id (gnus-icalendar-event:uid event)))
(org-show-entry))))
(defun gnus-icalendar--update-org-event (event reply-status &optional org-file)
(let ((file (gnus-icalendar-find-org-event-file event org-file)))
(when file
(with-current-buffer (find-file-noselect file)
(with-slots (uid summary description organizer location recur) event
(let ((event-pos (org-find-entry-with-id uid)))
(when event-pos
(goto-char event-pos)
;; update the headline, keep todo, priority and tags, if any
(save-excursion
(let* ((priority (org-entry-get (point) "PRIORITY"))
(headline (delq nil (list
(org-entry-get (point) "TODO")
(when priority (format "[#%s]" priority))
(format "%s (%s)" summary location)
(org-entry-get (point) "TAGS")))))
(re-search-forward "^\\*+ " (line-end-position))
(delete-region (point) (line-end-position))
(insert (mapconcat #'identity headline " "))))
;; update props and description
(let ((entry-end (org-entry-end-position))
(entry-outline-level (org-outline-level)))
;; delete body of the entry, leave org drawers intact
(save-restriction
(org-narrow-to-element)
(goto-char entry-end)
(re-search-backward "^[\t ]*:END:")
(forward-line)
(delete-region (point) entry-end))
;; put new event description in the entry body
(when description
(save-restriction
(narrow-to-region (point) (point))
(insert "\n" (replace-regexp-in-string "[\n]+$" "\n" description) "\n")
(indent-region (point-min) (point-max) (1+ entry-outline-level))
(fill-region (point-min) (point-max))))
;; update entry properties
(org-entry-put event-pos "DT" (gnus-icalendar-event:org-timestamp event))
(org-entry-put event-pos "ORGANIZER" organizer)
(org-entry-put event-pos "LOCATION" location)
(org-entry-put event-pos "RRULE" recur)
(when reply-status (org-entry-put event-pos "REPLY"
(capitalize (symbol-name reply-status))))
(save-buffer)))))))))
(defun gnus-icalendar--cancel-org-event (event &optional org-file)
(let ((file (gnus-icalendar-find-org-event-file event org-file)))
(when file
(with-current-buffer (find-file-noselect file)
(let ((event-pos (org-find-entry-with-id (gnus-icalendar-event:uid event))))
(when event-pos
(let ((ts (org-entry-get event-pos "DT")))
(when ts
(org-entry-put event-pos "DT" (gnus-icalendar--deactivate-org-timestamp ts))
(save-buffer)))))))))
(defun gnus-icalendar--get-org-event-reply-status (event &optional org-file)
(let ((file (gnus-icalendar-find-org-event-file event org-file)))
(when file
(save-excursion
(with-current-buffer (find-file-noselect file)
(let ((event-pos (org-find-entry-with-id (gnus-icalendar-event:uid event))))
(org-entry-get event-pos "REPLY")))))))
(defun gnus-icalendar-insinuate-org-templates ()
(unless (gnus-icalendar-find-if (lambda (x) (string= (cadr x) gnus-icalendar-org-template-name))
org-capture-templates)
(setq org-capture-templates
(append `((,gnus-icalendar-org-template-key
,gnus-icalendar-org-template-name
entry
(file+olp ,gnus-icalendar-org-capture-file ,@gnus-icalendar-org-capture-headline)
"%i"
:immediate-finish t))
org-capture-templates))
;; hide the template from interactive template selection list
;; (org-capture)
;; NOTE: doesn't work when capturing from string
;; (when (boundp 'org-capture-templates-contexts)
;; (push `(,gnus-icalendar-org-template-key "" ((in-mode . "gnus-article-mode")))
;; org-capture-templates-contexts))
))
(defun gnus-icalendar:org-event-save (event reply-status)
(with-temp-buffer
(org-capture-string (gnus-icalendar-event->org-entry event reply-status)
gnus-icalendar-org-template-key)))
(defun gnus-icalendar-show-org-agenda (event)
(let* ((time-delta (time-subtract (gnus-icalendar-event:end-time event)
(gnus-icalendar-event:start-time event)))
(duration-days (1+ (/ (+ (* (car time-delta) (expt 2 16))
(cadr time-delta))
86400))))
(org-agenda-list nil (gnus-icalendar-event:start event) duration-days)))
(defmethod gnus-icalendar-event:sync-to-org ((event gnus-icalendar-event-request) reply-status)
(if (gnus-icalendar-find-org-event-file event)
(gnus-icalendar--update-org-event event reply-status)
(gnus-icalendar:org-event-save event reply-status)))
(defmethod gnus-icalendar-event:sync-to-org ((event gnus-icalendar-event-cancel))
(when (gnus-icalendar-find-org-event-file event)
(gnus-icalendar--cancel-org-event event)))
(defun gnus-icalendar-org-setup ()
(if (and gnus-icalendar-org-capture-file gnus-icalendar-org-capture-headline)
(progn
(gnus-icalendar-insinuate-org-templates)
(setq gnus-icalendar-org-enabled-p t))
(message "Cannot enable Calendar->Org: missing capture file, headline")))
;;;
;;; gnus-icalendar
;;;
(defgroup gnus-icalendar nil
"Settings for inline display of iCalendar invitations."
:group 'gnus-article
:prefix "gnus-icalendar-")
(defcustom gnus-icalendar-reply-bufname "*CAL*"
"Buffer used for building iCalendar invitation reply."
:type '(string)
:group 'gnus-icalendar)
(make-variable-buffer-local
(defvar gnus-icalendar-reply-status nil))
(make-variable-buffer-local
(defvar gnus-icalendar-event nil))
(make-variable-buffer-local
(defvar gnus-icalendar-handle nil))
(defvar gnus-icalendar-identities
(apply #'append
(mapcar (lambda (x) (if (listp x) x (list x)))
(list user-full-name (regexp-quote user-mail-address)
; NOTE: this one can be a list
gnus-ignored-from-addresses))))
;; TODO: make the template customizable
(defmethod gnus-icalendar-event->gnus-calendar ((event gnus-icalendar-event) &optional reply-status)
"Format an overview of EVENT details."
(flet ((format-header (x)
(format "%-12s%s"
(propertize (concat (car x) ":") 'face 'bold)
(cadr x))))
(with-slots (organizer summary description location recur uid method rsvp) event
(let ((headers `(("Summary" ,summary)
("Location" ,location)
("Time" ,(gnus-icalendar-event:org-timestamp event))
("Organizer" ,organizer)
("Method" ,method))))
(when (and (not (gnus-icalendar-event-reply-p event)) rsvp)
(setq headers (append headers
`(("Status" ,(or reply-status "Not replied yet"))))))
(concat
(mapconcat #'format-header headers "\n")
"\n\n"
description)))))
(defmacro gnus-icalendar-with-decoded-handle (handle &rest body)
"Execute BODY in buffer containing the decoded contents of HANDLE."
(let ((charset (make-symbol "charset")))
`(let ((,charset (cdr (assoc 'charset (mm-handle-type ,handle)))))
(with-temp-buffer
(mm-insert-part ,handle)
(when (string= ,charset "utf-8")
(mm-decode-coding-region (point-min) (point-max) 'utf-8))
,@body))))
(defun gnus-icalendar-event-from-handle (handle &optional attendee-name-or-email)
(gnus-icalendar-with-decoded-handle handle
(gnus-icalendar-event-from-buffer (current-buffer) attendee-name-or-email)))
(defun gnus-icalendar-insert-button (text callback data)
;; FIXME: the gnus-mime-button-map keymap does not make sense for this kind
;; of button.
(let ((start (point)))
(gnus-add-text-properties
start
(progn
(insert "[ " text " ]")
(point))
`(gnus-callback
,callback
keymap ,gnus-mime-button-map
face ,gnus-article-button-face
gnus-data ,data))
(widget-convert-button 'link start (point)
:action 'gnus-widget-press-button
:button-keymap gnus-widget-button-keymap)))
(defun gnus-icalendar-send-buffer-by-mail (buffer-name subject)
(let ((message-signature nil))
(with-current-buffer gnus-summary-buffer
(gnus-summary-reply)
(message-goto-body)
(mml-insert-multipart "alternative")
(mml-insert-empty-tag 'part 'type "text/plain")
(mml-attach-buffer buffer-name "text/calendar; method=REPLY; charset=UTF-8")
(message-goto-subject)
(delete-region (line-beginning-position) (line-end-position))
(insert "Subject: " subject)
(message-send-and-exit))))
(defun gnus-icalendar-reply (data)
(let* ((handle (car data))
(status (cadr data))
(event (caddr data))
(reply (gnus-icalendar-with-decoded-handle handle
(gnus-icalendar-event-reply-from-buffer
(current-buffer) status gnus-icalendar-identities))))
(when reply
(flet ((fold-icalendar-buffer ()
(goto-char (point-min))
(while (re-search-forward "^\\(.\\{72\\}\\)\\(.+\\)$" nil t)
(replace-match "\\1\n \\2")
(goto-char (line-beginning-position)))))
(let ((subject (concat (capitalize (symbol-name status))
": " (gnus-icalendar-event:summary event))))
(with-current-buffer (get-buffer-create gnus-icalendar-reply-bufname)
(delete-region (point-min) (point-max))
(insert reply)
(fold-icalendar-buffer)
(gnus-icalendar-send-buffer-by-mail (buffer-name) subject))
;; Back in article buffer
(setq-local gnus-icalendar-reply-status status)
(when gnus-icalendar-org-enabled-p
(gnus-icalendar--update-org-event event status)
;; refresh article buffer to update the reply status
(with-current-buffer gnus-summary-buffer
(gnus-summary-show-article))))))))
(defun gnus-icalendar-sync-event-to-org (event)
(gnus-icalendar-event:sync-to-org event gnus-icalendar-reply-status))
(defmethod gnus-icalendar-event:inline-reply-buttons ((event gnus-icalendar-event) handle)
(when (gnus-icalendar-event:rsvp event)
`(("Accept" gnus-icalendar-reply (,handle accepted ,event))
("Tentative" gnus-icalendar-reply (,handle tentative ,event))
("Decline" gnus-icalendar-reply (,handle declined ,event)))))
(defmethod gnus-icalendar-event:inline-reply-buttons ((event gnus-icalendar-event-reply) handle)
"No buttons for REPLY events."
nil)
(defmethod gnus-icalendar-event:inline-reply-status ((event gnus-icalendar-event))
(or (when gnus-icalendar-org-enabled-p
(gnus-icalendar--get-org-event-reply-status event))
"Not replied yet"))
(defmethod gnus-icalendar-event:inline-reply-status ((event gnus-icalendar-event-reply))
"No reply status for REPLY events."
nil)
(defmethod gnus-icalendar-event:inline-org-buttons ((event gnus-icalendar-event))
(let* ((org-entry-exists-p (gnus-icalendar-find-org-event-file event))
(export-button-text (if org-entry-exists-p "Update Org Entry" "Export to Org")))
(delq nil (list
`("Show Agenda" gnus-icalendar-show-org-agenda ,event)
(when (gnus-icalendar-event-request-p event)
`(,export-button-text gnus-icalendar-sync-event-to-org ,event))
(when org-entry-exists-p
`("Show Org Entry" gnus-icalendar--show-org-event ,event))))))
(defun gnus-icalendar-mm-inline (handle)
(let ((event (gnus-icalendar-event-from-handle handle gnus-icalendar-identities)))
(setq gnus-icalendar-reply-status nil)
(when event
(flet ((insert-button-group (buttons)
(when buttons
(mapc (lambda (x)
(apply 'gnus-icalendar-insert-button x)
(insert " "))
buttons)
(insert "\n\n"))))
(insert-button-group
(gnus-icalendar-event:inline-reply-buttons event handle))
(when gnus-icalendar-org-enabled-p
(insert-button-group (gnus-icalendar-event:inline-org-buttons event)))
(setq gnus-icalendar-event event
gnus-icalendar-handle handle)
(insert (gnus-icalendar-event->gnus-calendar
event
(gnus-icalendar-event:inline-reply-status event)))))))
(defun gnus-icalendar-save-part (handle)
(let (event)
(when (and (equal (car (mm-handle-type handle)) "text/calendar")
(setq event (gnus-icalendar-event-from-handle handle gnus-icalendar-identities)))
(gnus-icalendar-event:sync-to-org event))))
(defun gnus-icalendar-save-event ()
"Save the Calendar event in the text/calendar part under point."
(interactive)
(gnus-article-check-buffer)
(let ((data (get-text-property (point) 'gnus-data)))
(when data
(gnus-icalendar-save-part data))))
(defun gnus-icalendar-reply-accept ()
"Accept invitation in the current article."
(interactive)
(with-current-buffer gnus-article-buffer
(gnus-icalendar-reply (list gnus-icalendar-handle 'accepted gnus-icalendar-event))
(setq-local gnus-icalendar-reply-status 'accepted)))
(defun gnus-icalendar-reply-tentative ()
"Send tentative response to invitation in the current article."
(interactive)
(with-current-buffer gnus-article-buffer
(gnus-icalendar-reply (list gnus-icalendar-handle 'tentative gnus-icalendar-event))
(setq-local gnus-icalendar-reply-status 'tentative)))
(defun gnus-icalendar-reply-decline ()
"Decline invitation in the current article."
(interactive)
(with-current-buffer gnus-article-buffer
(gnus-icalendar-reply (list gnus-icalendar-handle 'declined gnus-icalendar-event))
(setq-local gnus-icalendar-reply-status 'declined)))
(defun gnus-icalendar-event-export ()
"Export calendar event to `org-mode', or update existing agenda entry."
(interactive)
(with-current-buffer gnus-article-buffer
(gnus-icalendar-sync-event-to-org gnus-icalendar-event))
;; refresh article buffer in case the reply had been sent before initial org
;; export
(with-current-buffer gnus-summary-buffer
(gnus-summary-show-article)))
(defun gnus-icalendar-event-show ()
"Display `org-mode' agenda entry related to the calendar event."
(interactive)
(gnus-icalendar--show-org-event
(with-current-buffer gnus-article-buffer
gnus-icalendar-event)))
(defun gnus-icalendar-event-check-agenda ()
"Display `org-mode' agenda for days between event start and end dates."
(interactive)
(gnus-icalendar-show-org-agenda
(with-current-buffer gnus-article-buffer gnus-icalendar-event)))
(defun gnus-icalendar-setup ()
(add-to-list 'mm-inlined-types "text/calendar")
(add-to-list 'mm-automatic-display "text/calendar")
(add-to-list 'mm-inline-media-tests '("text/calendar" gnus-icalendar-mm-inline identity))
(gnus-define-keys (gnus-summary-calendar-map "i" gnus-summary-mode-map)
"a" gnus-icalendar-reply-accept
"t" gnus-icalendar-reply-tentative
"d" gnus-icalendar-reply-decline
"c" gnus-icalendar-event-check-agenda
"e" gnus-icalendar-event-export
"s" gnus-icalendar-event-show)
(require 'gnus-art)
(add-to-list 'gnus-mime-action-alist
(cons "save calendar event" 'gnus-icalendar-save-event)
t))
(provide 'gnus-icalendar)
;;; gnus-icalendar.el ends here

View file

@ -582,8 +582,8 @@ This is the string that Gnus uses to identify the group."
(gnus-group-method group)))
(defun gnus-warp-to-article ()
"Warps from an article in a virtual group to the article in its
real group. Does nothing on a real group."
"Jump from an article in a virtual group to the article in its real group.
Does nothing in a real group."
(interactive)
(when (gnus-virtual-group-p gnus-newsgroup-name)
(let ((gnus-command-method

View file

@ -1071,10 +1071,15 @@ EXTRA is the possible non-standard header."
(push (cons article n) gnus-newsgroup-scored)))
(gnus-summary-update-line)))
(defun gnus-summary-current-score ()
"Return the score of the current article."
(interactive)
(gnus-message 1 "%s" (gnus-summary-article-score)))
(defun gnus-summary-current-score (arg)
"Return the score of the current article.
With prefix ARG, return the total score of the current (sub)thread."
(interactive "P")
(gnus-message 1 "%s" (if arg
(gnus-thread-total-score
(gnus-id-to-thread
(mail-header-id (gnus-summary-article-header))))
(gnus-summary-article-score))))
(defun gnus-score-change-score-file (file)
"Change current score alist."

View file

@ -944,7 +944,8 @@ If REGEXP is given, lines that match it will be deleted."
(when (and gnus-dribble-buffer
(buffer-name gnus-dribble-buffer))
(with-current-buffer gnus-dribble-buffer
(save-buffer))))
(when (> (buffer-size) 0)
(save-buffer)))))
(defun gnus-dribble-clear ()
(when (gnus-buffer-exists-p gnus-dribble-buffer)
@ -1807,6 +1808,9 @@ backend check whether the group actually exists."
(or (not (gnus-agent-method-p method))
(gnus-online method)))
(gnus-finish-retrieve-group-infos method infos early-data)
;; We may have altered the data now, so mark the dribble buffer
;; as dirty so that it gets saved.
(gnus-dribble-touch)
(gnus-agent-save-active method))
;; Most backends have -retrieve-groups.
((gnus-check-backend-function 'retrieve-groups (car method))

View file

@ -2359,7 +2359,8 @@ increase the score of each group you read."
["Mark above" gnus-summary-mark-above t]
["Tick above" gnus-summary-tick-above t]
["Clear above" gnus-summary-clear-above t])
["Current score" gnus-summary-current-score t]
["Current article score" gnus-summary-current-score t]
["Current thread score" (gnus-summary-current-score 'total) t]
["Set score" gnus-summary-set-score t]
["Switch current score file..." gnus-score-change-score-file t]
["Set mark below..." gnus-score-set-mark-below t]

View file

@ -1558,12 +1558,15 @@ SPEC is a predicate specifier that contains stuff like `or', `and',
"Call standard `completing-read-function'."
(let ((completion-styles gnus-completion-styles))
(completing-read prompt
;; Old XEmacs (at least 21.4) expect an alist,
;; in which the car of each element is a string,
;; for collection.
(mapcar (lambda (elem)
(list (format "%s" (or (car-safe elem) elem))))
collection)
(if (featurep 'xemacs)
;; Old XEmacs (at least 21.4) expect an alist,
;; in which the car of each element is a string,
;; for collection.
(mapcar
(lambda (elem)
(list (format "%s" (or (car-safe elem) elem))))
collection)
collection)
nil require-match initial-input history def)))
(autoload 'ido-completing-read "ido")

View file

@ -640,7 +640,7 @@ When called interactively, prompt for REGEXP."
(let ((level (gnus-summary-thread-level)))
(while (and (gnus-summary-set-process-mark
(gnus-summary-article-number))
(zerop (gnus-summary-next-subject 1 nil t))
(zerop (forward-line 1))
(> (gnus-summary-thread-level) level)))))
(gnus-summary-position-point))
@ -650,7 +650,7 @@ When called interactively, prompt for REGEXP."
(let ((level (gnus-summary-thread-level)))
(while (and (gnus-summary-remove-process-mark
(gnus-summary-article-number))
(zerop (gnus-summary-next-subject 1))
(zerop (forward-line 1))
(> (gnus-summary-thread-level) level))))
(gnus-summary-position-point))

View file

@ -264,7 +264,7 @@ This is a list of regexps and regexp matches."
:type 'sexp)
(defcustom message-ignored-news-headers
"^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:\\|^X-Message-SMTP-Method:"
"^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:\\|^X-Message-SMTP-Method:\\|^X-Gnus-Delayed:"
"*Regexp of headers to be removed unconditionally before posting."
:group 'message-news
:group 'message-headers

View file

@ -63,6 +63,18 @@
:group 'news
:group 'multimedia)
(defface mm-command-output
'((((class color)
(background dark))
(:foreground "ForestGreen"))
(((class color)
(background light))
(:foreground "red3"))
(t
(:italic t)))
"Face used for displaying output from commands."
:group 'mime-display)
;;; Convenience macros.
(defmacro mm-handle-buffer (handle)
@ -983,9 +995,12 @@ external if displayed external."
(let ((buffer-read-only nil)
(point (point)))
(forward-line 2)
(mm-insert-inline
handle (with-current-buffer buffer
(buffer-string)))
(let ((start (point)))
(mm-insert-inline
handle (with-current-buffer buffer
(buffer-string)))
(put-text-property start (point)
'face 'mm-command-output))
(goto-char point))))
(when (buffer-live-p buffer)
(kill-buffer buffer)))

View file

@ -885,17 +885,19 @@ If set, it overrides the setting of `mml2015-sign-with-sender'."
(defun mml2015-epg-key-image-to-string (key-id)
"Return a string with the image of a key, if any"
(let* ((result "")
(key-image (mml2015-epg-key-image key-id)))
(when key-image
(setq result " ")
(put-text-property
1 2 'display
(gnus-rescale-image key-image
(cons mml2015-maximum-key-image-dimension
mml2015-maximum-key-image-dimension))
result))
result))
(let ((key-image (mml2015-epg-key-image key-id)))
(if (not key-image)
""
(condition-case error
(let ((result " "))
(put-text-property
1 2 'display
(gnus-rescale-image key-image
(cons mml2015-maximum-key-image-dimension
mml2015-maximum-key-image-dimension))
result)
result)
(error "")))))
(defun mml2015-epg-signature-to-string (signature)
(concat (epg-signature-to-string signature)

View file

@ -148,28 +148,29 @@
(deffoo nnmbox-request-article (article &optional newsgroup server buffer)
(nnmbox-possibly-change-newsgroup newsgroup server)
(with-current-buffer nnmbox-mbox-buffer
(when (nnmbox-find-article article)
(let (start stop)
(re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
(setq start (point))
(forward-line 1)
(setq stop (if (re-search-forward (concat "^"
message-unix-mail-delimiter)
nil 'move)
(match-beginning 0)
(point)))
(let ((nntp-server-buffer (or buffer nntp-server-buffer)))
(set-buffer nntp-server-buffer)
(erase-buffer)
(insert-buffer-substring nnmbox-mbox-buffer start stop)
(goto-char (point-min))
(while (looking-at "From ")
(delete-char 5)
(insert "X-From-Line: ")
(forward-line 1))
(if (numberp article)
(cons nnmbox-current-group article)
(nnmbox-article-group-number nil)))))))
(save-excursion
(when (nnmbox-find-article article)
(let (start stop)
(re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
(setq start (point))
(forward-line 1)
(setq stop (if (re-search-forward (concat "^"
message-unix-mail-delimiter)
nil 'move)
(match-beginning 0)
(point)))
(let ((nntp-server-buffer (or buffer nntp-server-buffer)))
(set-buffer nntp-server-buffer)
(erase-buffer)
(insert-buffer-substring nnmbox-mbox-buffer start stop)
(goto-char (point-min))
(while (looking-at "From ")
(delete-char 5)
(insert "X-From-Line: ")
(forward-line 1))
(if (numberp article)
(cons nnmbox-current-group article)
(nnmbox-article-group-number nil))))))))
(deffoo nnmbox-request-group (group &optional server dont-check info)
(nnmbox-possibly-change-newsgroup nil server)
@ -255,14 +256,14 @@
(if (setq is-old
(nnmail-expired-article-p
newsgroup
(buffer-substring
(point) (progn (end-of-line) (point))) force))
(buffer-substring (point) (line-end-position))
force))
(progn
(unless (eq nnmail-expiry-target 'delete)
(with-temp-buffer
(nnmbox-request-article (car articles)
newsgroup server
(current-buffer))
newsgroup server
(current-buffer))
(let ((nnml-current-directory nil))
(nnmail-expiry-target-group
nnmail-expiry-target newsgroup)))

View file

@ -933,30 +933,30 @@ whether they are `offsite' or `onsite'."
rss-offsite-in rdf-offsite-in xml-offsite-in)))
(defun nnrss-discover-feed (url)
"Given a page, find an RSS feed using Mark Pilgrim's
`ultra-liberal rss locator'."
"Given a page, find an RSS feed.
Use Mark Pilgrim's `ultra-liberal rss locator'."
(let ((parsed-page (nnrss-fetch url)))
;; 1. if this url is the rss, use it.
;; 1. if this url is the rss, use it.
(if (nnrss-rss-p parsed-page)
(let ((rss-ns (nnrss-get-namespace-prefix parsed-page "http://purl.org/rss/1.0/")))
(nnrss-rss-title-description rss-ns parsed-page url))
;; 2. look for the <link rel="alternate"
;; type="application/rss+xml" and use that if it is there.
;; 2. look for the <link rel="alternate"
;; type="application/rss+xml" and use that if it is there.
(let ((links (nnrss-get-rsslinks parsed-page)))
(if links
(let* ((xml (nnrss-fetch
(cdr (assoc 'href (cadar links)))))
(rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/")))
(nnrss-rss-title-description rss-ns xml (cdr (assoc 'href (cadar links)))))
(rss-ns (nnrss-get-namespace-prefix
xml "http://purl.org/rss/1.0/")))
(nnrss-rss-title-description
rss-ns xml (cdr (assoc 'href (cadar links)))))
;; 3. look for links on the site in the following order:
;; - onsite links ending in .rss, .rdf, or .xml
;; - onsite links containing any of the above
;; - offsite links ending in .rss, .rdf, or .xml
;; - offsite links containing any of the above
;; 3. look for links on the site in the following order:
;; - onsite links ending in .rss, .rdf, or .xml
;; - onsite links containing any of the above
;; - offsite links ending in .rss, .rdf, or .xml
;; - offsite links containing any of the above
(let* ((base-uri (progn (string-match ".*://[^/]+/?" url)
(match-string 0 url)))
(hrefs (nnrss-order-hrefs
@ -969,9 +969,9 @@ whether they are `offsite' or `onsite'."
(setq rss-link (nnrss-rss-title-description
rss-ns href-data (car hrefs))))
(setq hrefs (cdr hrefs)))))
(if rss-link rss-link
;; 4. check syndic8
(if rss-link
rss-link
;; 4. check syndic8
(nnrss-find-rss-via-syndic8 url))))))))
(defun nnrss-find-rss-via-syndic8 (url)

View file

@ -235,85 +235,96 @@ Should be called narrowed to the head of the message."
(interactive "*")
(save-excursion
(goto-char (point-min))
(let (alist elem method)
(let (alist elem method charsets)
(while (not (eobp))
(save-restriction
(rfc2047-narrow-to-field)
(setq method nil
alist rfc2047-header-encoding-alist)
(while (setq elem (pop alist))
(when (or (and (stringp (car elem))
(looking-at (car elem)))
(eq (car elem) t))
(setq alist nil
method (cdr elem))))
(if (not (rfc2047-encodable-p))
(prog2
(when (eq method 'address-mime)
(rfc2047-quote-special-characters-in-quoted-strings))
(if (and (eq (mm-body-7-or-8) '8bit)
(mm-multibyte-p)
(mm-coding-system-p
(car message-posting-charset)))
;; 8 bit must be decoded.
(mm-encode-coding-region
(point-min) (point-max)
(mm-charset-to-coding-system
(car message-posting-charset))))
;; No encoding necessary, but folding is nice
(when nil
(rfc2047-fold-region
(save-excursion
(goto-char (point-min))
(skip-chars-forward "^:")
(when (looking-at ": ")
(forward-char 2))
(point))
(point-max))))
;; We found something that may perhaps be encoded.
(re-search-forward "^[^:]+: *" nil t)
(cond
((eq method 'address-mime)
(rfc2047-encode-region (point) (point-max)))
((eq method 'mime)
(let ((rfc2047-encoding-type 'mime))
(rfc2047-encode-region (point) (point-max))))
((eq method 'default)
(if (and (featurep 'mule)
(if (boundp 'enable-multibyte-characters)
(default-value 'enable-multibyte-characters))
mail-parse-charset)
(mm-encode-coding-region (point) (point-max)
mail-parse-charset)))
;; We get this when CC'ing messages to newsgroups with
;; 8-bit names. The group name mail copy just got
;; unconditionally encoded. Previously, it would ask
;; whether to encode, which was quite confusing for the
;; user. If the new behavior is wrong, tell me. I have
;; left the old code commented out below.
;; -- Per Abrahamsen <abraham@dina.kvl.dk> Date: 2001-10-07.
;; Modified by Dave Love, with the commented-out code changed
;; in accordance with changes elsewhere.
((null method)
(rfc2047-encode-region (point) (point-max)))
;;; ((null method)
;;; (if (or (message-options-get
;;; 'rfc2047-encode-message-header-encode-any)
;;; (message-options-set
;;; 'rfc2047-encode-message-header-encode-any
;;; (y-or-n-p
;;; "Some texts are not encoded. Encode anyway?")))
;;; (rfc2047-encode-region (point-min) (point-max))
;;; (error "Cannot send unencoded text")))
((mm-coding-system-p method)
(if (or (and (featurep 'mule)
(if (boundp 'enable-multibyte-characters)
(default-value 'enable-multibyte-characters)))
(featurep 'file-coding))
(mm-encode-coding-region (point) (point-max) method)))
;; Hm.
(t)))
(goto-char (point-max)))))))
alist rfc2047-header-encoding-alist
charsets (mm-find-mime-charset-region (point-min) (point-max)))
;; M$ Outlook boycotts decoding of a header if it consists
;; of two or more encoded words and those charsets differ;
;; it seems to decode all words in a header from a charset
;; found first in the header. So, we unify the charsets into
;; a single one used for encoding the whole text in a header.
(let ((mm-coding-system-priorities
(if (= (length charsets) 1)
(cons (mm-charset-to-coding-system (car charsets))
mm-coding-system-priorities)
mm-coding-system-priorities)))
(while (setq elem (pop alist))
(when (or (and (stringp (car elem))
(looking-at (car elem)))
(eq (car elem) t))
(setq alist nil
method (cdr elem))))
(if (not (rfc2047-encodable-p))
(prog2
(when (eq method 'address-mime)
(rfc2047-quote-special-characters-in-quoted-strings))
(if (and (eq (mm-body-7-or-8) '8bit)
(mm-multibyte-p)
(mm-coding-system-p
(car message-posting-charset)))
;; 8 bit must be decoded.
(mm-encode-coding-region
(point-min) (point-max)
(mm-charset-to-coding-system
(car message-posting-charset))))
;; No encoding necessary, but folding is nice
(when nil
(rfc2047-fold-region
(save-excursion
(goto-char (point-min))
(skip-chars-forward "^:")
(when (looking-at ": ")
(forward-char 2))
(point))
(point-max))))
;; We found something that may perhaps be encoded.
(re-search-forward "^[^:]+: *" nil t)
(cond
((eq method 'address-mime)
(rfc2047-encode-region (point) (point-max)))
((eq method 'mime)
(let ((rfc2047-encoding-type 'mime))
(rfc2047-encode-region (point) (point-max))))
((eq method 'default)
(if (and (featurep 'mule)
(if (boundp 'enable-multibyte-characters)
(default-value 'enable-multibyte-characters))
mail-parse-charset)
(mm-encode-coding-region (point) (point-max)
mail-parse-charset)))
;; We get this when CC'ing messages to newsgroups with
;; 8-bit names. The group name mail copy just got
;; unconditionally encoded. Previously, it would ask
;; whether to encode, which was quite confusing for the
;; user. If the new behavior is wrong, tell me. I have
;; left the old code commented out below.
;; -- Per Abrahamsen <abraham@dina.kvl.dk> Date: 2001-10-07.
;; Modified by Dave Love, with the commented-out code changed
;; in accordance with changes elsewhere.
((null method)
(rfc2047-encode-region (point) (point-max)))
;;; ((null method)
;;; (if (or (message-options-get
;;; 'rfc2047-encode-message-header-encode-any)
;;; (message-options-set
;;; 'rfc2047-encode-message-header-encode-any
;;; (y-or-n-p
;;; "Some texts are not encoded. Encode anyway?")))
;;; (rfc2047-encode-region (point-min) (point-max))
;;; (error "Cannot send unencoded text")))
((mm-coding-system-p method)
(if (or (and (featurep 'mule)
(if (boundp 'enable-multibyte-characters)
(default-value 'enable-multibyte-characters)))
(featurep 'file-coding))
(mm-encode-coding-region (point) (point-max) method)))
;; Hm.
(t)))
(goto-char (point-max))))))))
;; Fixme: This, and the require below may not be the Right Thing, but
;; should be safe just before release. -- fx 2001-02-08

View file

@ -1050,7 +1050,7 @@ currently used by buffers."
"Toggle current view to buffers with filename matching QUALIFIER."
(:description "filename"
:reader (read-from-minibuffer "Filter by filename (regexp): "))
(ibuffer-awhen (buffer-local-value 'buffer-file-name buf)
(ibuffer-awhen (with-current-buffer buf (ibuffer-buffer-file-name))
(string-match qualifier it)))
;;;###autoload (autoload 'ibuffer-filter-by-size-gt "ibuf-ext")

View file

@ -2631,29 +2631,7 @@ will be inserted before the group at point."
;;; Start of automatically extracted autoloads.
;;;### (autoloads (ibuffer-do-occur ibuffer-mark-dired-buffers ibuffer-mark-read-only-buffers
;;;;;; ibuffer-mark-special-buffers ibuffer-mark-old-buffers ibuffer-mark-compressed-file-buffers
;;;;;; ibuffer-mark-help-buffers ibuffer-mark-dissociated-buffers
;;;;;; ibuffer-mark-unsaved-buffers ibuffer-mark-modified-buffers
;;;;;; ibuffer-mark-by-mode ibuffer-mark-by-file-name-regexp ibuffer-mark-by-mode-regexp
;;;;;; ibuffer-mark-by-name-regexp ibuffer-copy-filename-as-kill
;;;;;; ibuffer-diff-with-file ibuffer-jump-to-buffer ibuffer-do-kill-lines
;;;;;; ibuffer-backwards-next-marked ibuffer-forward-next-marked
;;;;;; ibuffer-add-to-tmp-show ibuffer-add-to-tmp-hide ibuffer-bs-show
;;;;;; ibuffer-invert-sorting ibuffer-toggle-sorting-mode ibuffer-switch-to-saved-filters
;;;;;; ibuffer-add-saved-filters ibuffer-delete-saved-filters ibuffer-save-filters
;;;;;; ibuffer-or-filter ibuffer-negate-filter ibuffer-exchange-filters
;;;;;; ibuffer-decompose-filter ibuffer-pop-filter ibuffer-filter-disable
;;;;;; ibuffer-switch-to-saved-filter-groups ibuffer-delete-saved-filter-groups
;;;;;; ibuffer-save-filter-groups ibuffer-yank-filter-group ibuffer-yank
;;;;;; ibuffer-kill-line ibuffer-kill-filter-group ibuffer-jump-to-filter-group
;;;;;; ibuffer-clear-filter-groups ibuffer-decompose-filter-group
;;;;;; ibuffer-pop-filter-group ibuffer-set-filter-groups-by-mode
;;;;;; ibuffer-filters-to-filter-group ibuffer-included-in-filters-p
;;;;;; ibuffer-backward-filter-group ibuffer-forward-filter-group
;;;;;; ibuffer-toggle-filter-group ibuffer-mouse-toggle-filter-group
;;;;;; ibuffer-interactive-filter-by-mode ibuffer-mouse-filter-by-mode
;;;;;; ibuffer-auto-mode) "ibuf-ext" "ibuf-ext.el" "2c628e6cde385119c5f7b43cc1efe1a1")
;;;### (autoloads nil "ibuf-ext" "ibuf-ext.el" "d06b2735a74954e0c6922a811de7608c")
;;; Generated autoloads from ibuf-ext.el
(autoload 'ibuffer-auto-mode "ibuf-ext" "\

View file

@ -1019,6 +1019,7 @@ windows in the frame are removed."
(when delete-other-windows-flag
(delete-other-windows)))
;; FIXME: Maybe out of date? --xfq
(if (boundp 'customize-package-emacs-version-alist)
(add-to-list 'customize-package-emacs-version-alist
'(MH-E ("6.0" . "22.1") ("6.1" . "22.1") ("7.0" . "22.1")

View file

@ -568,6 +568,17 @@ for use at QPOS."
(cl-assert (string-prefix-p prefix completion 'ignore-case) t)
(let* ((new (substring completion (length prefix)))
(qnew (funcall qfun new))
(qprefix
(if (not completion-ignore-case)
qprefix
;; Make qprefix inherit the case from `completion'.
(let* ((rest (substring completion
0 (length prefix)))
(qrest (funcall qfun rest)))
(if (completion--string-equal-p qprefix qrest)
(propertize qrest 'face
'completions-common-part)
qprefix))))
(qcompletion (concat qprefix qnew)))
;; FIXME: Similarly here, Cygwin's mapping trips this
;; assertion.

View file

@ -816,8 +816,8 @@ first, if that exists."
;; When connected to various displays, be careful to use the display of
;; the currently selected frame, rather than the original start display,
;; which may not even exist any more.
(if (stringp (frame-parameter (selected-frame) 'display))
(setenv "DISPLAY" (frame-parameter (selected-frame) 'display)))
(if (stringp (frame-parameter nil 'display))
(setenv "DISPLAY" (frame-parameter nil 'display)))
(if (and (consp function)
(not (functionp function)))
;; The `function' can be an alist; look down it for first match

View file

@ -309,7 +309,7 @@ word(s) will be searched for via `eww-search-prefix'."
(goto-char (point-min))))
(defun eww-setup-buffer ()
(pop-to-buffer (get-buffer-create "*eww*"))
(switch-to-buffer (get-buffer-create "*eww*"))
(let ((inhibit-read-only t))
(remove-overlays)
(erase-buffer))

View file

@ -128,6 +128,9 @@ values:
:use-starttls-if-possible is a boolean that says to do opportunistic
STARTTLS upgrades even if Emacs doesn't have built-in TLS functionality.
:nogreeting is a boolean that can be used to inhibit waiting for
a greeting from the server.
:nowait is a boolean that says the connection should be made
asynchronously, if possible."
(unless (featurep 'make-network-process)
@ -211,7 +214,8 @@ STARTTLS upgrades even if Emacs doesn't have built-in TLS functionality.
;; Return (STREAM GREETING CAPABILITIES RESULTING-TYPE)
(stream (make-network-process :name name :buffer buffer
:host host :service service))
(greeting (network-stream-get-response stream start eoc))
(greeting (and (not (plist-get parameters :nogreeting))
(network-stream-get-response stream start eoc)))
(capabilities (network-stream-command stream capability-command
eo-capa))
(resulting-type 'plain)

View file

@ -143,7 +143,7 @@ cid: URL as the argument.")
(define-key map [tab] 'shr-next-link)
(define-key map [backtab] 'shr-previous-link)
(define-key map [follow-link] 'mouse-face)
(define-key map [mouse-2] 'shr-mouse-browse-url)
(define-key map [mouse-2] 'shr-browse-url)
(define-key map "I" 'shr-insert-image)
(define-key map "w" 'shr-copy-url)
(define-key map "u" 'shr-copy-url)
@ -664,10 +664,11 @@ size, and full-buffer size."
(mouse-set-point ev)
(shr-browse-url))
(defun shr-browse-url (&optional external)
(defun shr-browse-url (&optional external mouse-event)
"Browse the URL under point.
If EXTERNAL, browse the URL using `shr-external-browser'."
(interactive "P")
(interactive (list current-prefix-arg last-nonmenu-event))
(mouse-set-point mouse-event)
(let ((url (get-text-property (point) 'shr-url)))
(cond
((not url)
@ -832,6 +833,8 @@ START, and END. Note that START and END should be markers."
start (point)
(list 'shr-url url
'help-echo (if title (format "%s (%s)" url title) url)
'follow-link t
'mouse-face 'highlight
'keymap shr-map)))
(defun shr-encode-url (url)

View file

@ -85,53 +85,74 @@
(cons 'tramp-adb-file-name-p 'tramp-adb-file-name-handler))
(defconst tramp-adb-file-name-handler-alist
'((directory-file-name . tramp-handle-directory-file-name)
(dired-uncache . tramp-handle-dired-uncache)
(file-name-as-directory . tramp-handle-file-name-as-directory)
(file-name-completion . tramp-handle-file-name-completion)
(file-name-all-completions . tramp-adb-handle-file-name-all-completions)
(file-attributes . tramp-adb-handle-file-attributes)
(file-name-directory . tramp-handle-file-name-directory)
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
(file-truename . tramp-adb-handle-file-truename)
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
(file-name-as-directory . tramp-handle-file-name-as-directory)
(file-regular-p . tramp-handle-file-regular-p)
(file-remote-p . tramp-handle-file-remote-p)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
(file-directory-p . tramp-adb-handle-file-directory-p)
(file-symlink-p . tramp-handle-file-symlink-p)
;; FIXME: This is too sloppy.
(file-executable-p . tramp-handle-file-exists-p)
(file-exists-p . tramp-handle-file-exists-p)
(file-readable-p . tramp-handle-file-exists-p)
(file-writable-p . tramp-adb-handle-file-writable-p)
(file-local-copy . tramp-adb-handle-file-local-copy)
(file-modes . tramp-handle-file-modes)
(file-notify-add-watch . tramp-handle-file-notify-add-watch)
(file-notify-rm-watch . ignore)
(expand-file-name . tramp-adb-handle-expand-file-name)
(find-backup-file-name . tramp-handle-find-backup-file-name)
'((access-file . ignore)
(add-name-to-file . tramp-adb-handle-copy-file)
;; `byte-compiler-base-file-name' performed by default handler.
;; `copy-directory' performed by default handler.
(copy-file . tramp-adb-handle-copy-file)
(delete-directory . tramp-adb-handle-delete-directory)
(delete-file . tramp-adb-handle-delete-file)
;; `diff-latest-backup-file' performed by default handler.
(directory-file-name . tramp-handle-directory-file-name)
(directory-files . tramp-handle-directory-files)
(directory-files-and-attributes
. tramp-adb-handle-directory-files-and-attributes)
(make-directory . tramp-adb-handle-make-directory)
(delete-directory . tramp-adb-handle-delete-directory)
(delete-file . tramp-adb-handle-delete-file)
(load . tramp-handle-load)
(dired-call-process . ignore)
(dired-compress-file . ignore)
(dired-uncache . tramp-handle-dired-uncache)
(expand-file-name . tramp-adb-handle-expand-file-name)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
(file-acl . ignore)
(file-attributes . tramp-adb-handle-file-attributes)
(file-directory-p . tramp-adb-handle-file-directory-p)
;; `file-equal-p' performed by default handler.
;; FIXME: This is too sloppy.
(file-executable-p . tramp-handle-file-exists-p)
(file-exists-p . tramp-handle-file-exists-p)
;; `file-in-directory-p' performed by default handler.
(file-local-copy . tramp-adb-handle-file-local-copy)
(file-modes . tramp-handle-file-modes)
(file-name-all-completions . tramp-adb-handle-file-name-all-completions)
(file-name-as-directory . tramp-handle-file-name-as-directory)
(file-name-completion . tramp-handle-file-name-completion)
(file-name-directory . tramp-handle-file-name-directory)
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
(file-notify-add-watch . tramp-handle-file-notify-add-watch)
(file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
(file-ownership-preserved-p . ignore)
(file-readable-p . tramp-handle-file-exists-p)
(file-regular-p . tramp-handle-file-regular-p)
(file-remote-p . tramp-handle-file-remote-p)
(file-selinux-context . ignore)
(file-symlink-p . tramp-handle-file-symlink-p)
(file-truename . tramp-adb-handle-file-truename)
(file-writable-p . tramp-adb-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `find-file-noselect' performed by default handler.
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-adb-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
(load . tramp-handle-load)
;; `make-auto-save-file-name' performed by default handler.
(make-directory . tramp-adb-handle-make-directory)
(make-directory-internal . ignore)
(make-symbolic-link . ignore)
(process-file . tramp-adb-handle-process-file)
(rename-file . tramp-adb-handle-rename-file)
(set-file-acl . ignore)
(set-file-modes . tramp-adb-handle-set-file-modes)
(set-file-selinux-context . ignore)
(set-file-times . tramp-adb-handle-set-file-times)
(set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
(shell-command . tramp-adb-handle-shell-command)
(start-file-process . tramp-adb-handle-start-file-process)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
(vc-registered . ignore) ;no vc control files on Android devices
(write-region . tramp-adb-handle-write-region)
(set-file-modes . tramp-adb-handle-set-file-modes)
(set-file-times . tramp-adb-handle-set-file-times)
(copy-file . tramp-adb-handle-copy-file)
(rename-file . tramp-adb-handle-rename-file)
(process-file . tramp-adb-handle-process-file)
(shell-command . tramp-adb-handle-shell-command)
(start-file-process . tramp-adb-handle-start-file-process))
(vc-registered . ignore)
(verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
(write-region . tramp-adb-handle-write-region))
"Alist of handler functions for Tramp ADB method.")
;; It must be a `defsubst' in order to push the whole code into
@ -599,6 +620,9 @@ But handle the case, if the \"test\" command is not available."
(tramp-error v 'file-error "Cannot write: `%s' filename"))
(delete-file tmpfile)))
(when (or (eq visit t) (stringp visit))
(set-visited-file-modtime))
(unless (equal curbuf (current-buffer))
(tramp-error
v 'file-error

View file

@ -403,10 +403,10 @@ Every entry is a list (NAME ADDRESS).")
;; New handlers should be added here.
(defconst tramp-gvfs-file-name-handler-alist
'(
(access-file . ignore)
'((access-file . ignore)
(add-name-to-file . tramp-gvfs-handle-copy-file)
;; `byte-compiler-base-file-name' performed by default handler.
;; `copy-directory' performed by default handler.
(copy-file . tramp-gvfs-handle-copy-file)
(delete-directory . tramp-gvfs-handle-delete-directory)
(delete-file . tramp-gvfs-handle-delete-file)
@ -418,14 +418,15 @@ Every entry is a list (NAME ADDRESS).")
(dired-call-process . ignore)
(dired-compress-file . ignore)
(dired-uncache . tramp-handle-dired-uncache)
;; `executable-find' is not official yet. performed by default handler.
(expand-file-name . tramp-gvfs-handle-expand-file-name)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
(file-acl . ignore)
(file-attributes . tramp-gvfs-handle-file-attributes)
(file-directory-p . tramp-gvfs-handle-file-directory-p)
;; `file-equal-p' performed by default handler.
(file-executable-p . tramp-gvfs-handle-file-executable-p)
(file-exists-p . tramp-handle-file-exists-p)
;; `file-in-directory-p' performed by default handler.
(file-local-copy . tramp-gvfs-handle-file-local-copy)
(file-modes . tramp-handle-file-modes)
(file-name-all-completions . tramp-gvfs-handle-file-name-all-completions)
@ -435,8 +436,8 @@ Every entry is a list (NAME ADDRESS).")
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
(file-notify-add-watch . tramp-handle-file-notify-add-watch)
(file-notify-rm-watch . ignore)
(file-notify-add-watch . tramp-gvfs-handle-file-notify-add-watch)
(file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
(file-ownership-preserved-p . ignore)
(file-readable-p . tramp-gvfs-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
@ -451,6 +452,7 @@ Every entry is a list (NAME ADDRESS).")
(insert-directory . tramp-gvfs-handle-insert-directory)
(insert-file-contents . tramp-gvfs-handle-insert-file-contents)
(load . tramp-handle-load)
;; `make-auto-save-file-name' performed by default handler.
(make-directory . tramp-gvfs-handle-make-directory)
(make-directory-internal . ignore)
(make-symbolic-link . ignore)
@ -459,15 +461,15 @@ Every entry is a list (NAME ADDRESS).")
(set-file-acl . ignore)
(set-file-modes . ignore)
(set-file-selinux-context . ignore)
(set-visited-file-modtime . tramp-gvfs-handle-set-visited-file-modtime)
(set-file-times . ignore)
(set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
(shell-command . ignore)
(start-file-process . ignore)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
(vc-registered . ignore)
;; `verify-visited-file-modtime' performed by default handler.
(write-region . tramp-gvfs-handle-write-region)
)
(verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
(write-region . tramp-gvfs-handle-write-region))
"Alist of handler functions for Tramp GVFS method.
Operations not mentioned here will be handled by the default Emacs primitives.")
@ -555,28 +557,6 @@ will be traced by Tramp with trace level 6."
(tramp-compat-font-lock-add-keywords
'emacs-lisp-mode '("\\<with-tramp-dbus-call-method\\>"))
(defmacro with-tramp-gvfs-error-message (filename handler &rest args)
"Apply a Tramp GVFS `handler'.
In case of an error, modify the error message by replacing
`filename' with its GVFS mounted name."
`(let ((fuse-file-name (regexp-quote (tramp-gvfs-fuse-file-name ,filename)))
elt)
(condition-case err
(tramp-compat-funcall ,handler ,@args)
(error
(setq elt (cdr err))
(while elt
(when (and (stringp (car elt))
(string-match fuse-file-name (car elt)))
(setcar elt (replace-match ,filename t t (car elt))))
(setq elt (cdr elt)))
(signal (car err) (cdr err))))))
(put 'with-tramp-gvfs-error-message 'lisp-indent-function 2)
(put 'with-tramp-gvfs-error-message 'edebug-form-spec '(form symbolp body))
(tramp-compat-font-lock-add-keywords
'emacs-lisp-mode '("\\<with-tramp-gvfs-error-message\\>"))
(defvar tramp-gvfs-dbus-event-vector nil
"Current Tramp file name to be used, as vector.
It is needed when D-Bus signals or errors arrive, because there
@ -943,6 +923,64 @@ is no information where to trace the message.")
v (concat localname filename)
"file-name-all-completions" result))))))))
(defun tramp-gvfs-handle-file-notify-add-watch (file-name flags callback)
"Like `file-notify-add-watch' for Tramp files."
(setq file-name (expand-file-name file-name))
(with-parsed-tramp-file-name file-name nil
(let ((p (start-process
"gvfs-monitor-file" (generate-new-buffer " *gvfs-monitor-file*")
"gvfs-monitor-file" (tramp-gvfs-url-file-name file-name))))
(if (not (processp p))
(tramp-error
v 'file-notify-error "gvfs-monitor-file failed to start")
(tramp-compat-set-process-query-on-exit-flag p nil)
(set-process-filter p 'tramp-gvfs-file-gvfs-monitor-file-process-filter)
(with-current-buffer (process-buffer p)
(setq default-directory (file-name-directory file-name)))
p))))
(defun tramp-gvfs-file-gvfs-monitor-file-process-filter (proc string)
"Read output from \"gvfs-monitor-file\" and add corresponding file-notify events."
(let* ((rest-string (tramp-compat-process-get proc 'rest-string))
(dd (with-current-buffer (process-buffer proc) default-directory))
(ddu (regexp-quote (tramp-gvfs-url-file-name dd))))
(when rest-string
(tramp-message proc 10 "Previous string:\n%s" rest-string))
(tramp-message proc 6 "%S\n%s" proc string)
(setq string (concat rest-string string)
;; Attribute change is returned in unused wording.
string (replace-regexp-in-string
"ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string))
(while (string-match
(concat "^[\n\r]*"
"File Monitor Event:[\n\r]+"
"File = \\([^\n\r]+\\)[\n\r]+"
"Event = \\([^[:blank:]]+\\)[\n\r]+")
string)
(let ((action (intern-soft
(replace-regexp-in-string
"_" "-" (downcase (match-string 2 string)))))
(file (match-string 1 string)))
(setq string (replace-match "" nil nil string))
;; File names are returned as URL paths. We must convert them.
(when (string-match ddu file)
(setq file (replace-match dd nil nil file)))
(while (string-match "%\\([0-9A-F]\\{2\\}\\)" file)
(setq file
(replace-match
(char-to-string (string-to-number (match-string 1 file) 16))
nil nil file)))
;; Usually, we would add an Emacs event now. Unfortunately,
;; `unread-command-events' does not accept several events at
;; once. Therefore, we apply the callback directly.
(tramp-compat-funcall 'file-notify-callback (list proc action file))))
;; Save rest of the string.
(when (zerop (length string)) (setq string nil))
(when string (tramp-message proc 10 "Rest string:\n%s" string))
(tramp-compat-process-put proc 'rest-string string)))
(defun tramp-gvfs-handle-file-readable-p (filename)
"Like `file-readable-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
@ -1054,22 +1092,6 @@ is no information where to trace the message.")
(tramp-flush-file-property v (file-name-directory localname))
(tramp-flush-file-property v localname))))))
(defun tramp-gvfs-handle-set-visited-file-modtime (&optional time-list)
"Like `set-visited-file-modtime' for Tramp files."
(unless (buffer-file-name)
(error "Can't set-visited-file-modtime: buffer `%s' not visiting a file"
(buffer-name)))
(unless time-list
(let ((f (buffer-file-name)))
(with-parsed-tramp-file-name f nil
(let ((remote-file-name-inhibit-cache t)
(attr (file-attributes f)))
;; '(-1 65535) means file doesn't exists yet.
(setq time-list (or (nth 5 attr) '(-1 65535)))))))
;; We use '(0 0) as a don't-know value.
(unless (not (equal time-list '(0 0)))
(tramp-run-real-handler 'set-visited-file-modtime (list time-list))))
(defun tramp-gvfs-handle-write-region
(start end filename &optional append visit lockname confirm)
"Like `write-region' for Tramp files."
@ -1082,7 +1104,7 @@ is no information where to trace the message.")
(let ((tmpfile (tramp-compat-make-temp-file filename)))
(write-region start end tmpfile)
(condition-case nil
(rename-file tmpfile filename)
(rename-file tmpfile filename 'ok-if-already-exists)
(error
(delete-file tmpfile)
(tramp-error
@ -1137,24 +1159,6 @@ is no information where to trace the message.")
(dbus-unescape-from-identifier
(replace-regexp-in-string "^.*/\\([^/]+\\)$" "\\1" object-path)))
(defun tramp-gvfs-fuse-file-name (filename)
"Return FUSE file name, which is directly accessible."
(with-parsed-tramp-file-name (expand-file-name filename) nil
(tramp-gvfs-maybe-open-connection v)
(let ((prefix (tramp-get-file-property v "/" "prefix" ""))
(fuse-mountpoint
(tramp-get-file-property v "/" "fuse-mountpoint" nil)))
(unless fuse-mountpoint
(tramp-error
v 'file-error "There is no FUSE mount point for `%s'" filename))
;; We must hide the prefix, if any.
(when (string-match (concat "^" (regexp-quote prefix)) localname)
(setq localname (replace-match "" t t localname)))
(tramp-message
v 10 "remote file `%s' is local file `%s'"
filename (concat fuse-mountpoint localname))
(concat fuse-mountpoint localname))))
(defun tramp-bluez-address (device)
"Return bluetooth device address from a given bluetooth DEVICE name."
(when (stringp device)

View file

@ -801,73 +801,78 @@ existence, and file readability. Input shall be read via
here-document, otherwise the command could exceed maximum length
of command line.")
;; New handlers should be added here. The following operations can be
;; handled using the normal primitives: file-name-sans-versions,
;; get-file-buffer.
;; New handlers should be added here.
(defconst tramp-sh-file-name-handler-alist
'((load . tramp-handle-load)
(make-symbolic-link . tramp-sh-handle-make-symbolic-link)
(file-name-as-directory . tramp-handle-file-name-as-directory)
(file-name-directory . tramp-handle-file-name-directory)
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
(file-truename . tramp-sh-handle-file-truename)
(file-exists-p . tramp-sh-handle-file-exists-p)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
(file-directory-p . tramp-sh-handle-file-directory-p)
(file-executable-p . tramp-sh-handle-file-executable-p)
(file-readable-p . tramp-sh-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
(file-symlink-p . tramp-handle-file-symlink-p)
(file-writable-p . tramp-sh-handle-file-writable-p)
(file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p)
(file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p)
(file-attributes . tramp-sh-handle-file-attributes)
(file-modes . tramp-handle-file-modes)
'(;; `access-file' performed by default handler.
(add-name-to-file . tramp-sh-handle-add-name-to-file)
;; `byte-compiler-base-file-name' performed by default handler.
(copy-directory . tramp-sh-handle-copy-directory)
(copy-file . tramp-sh-handle-copy-file)
(delete-directory . tramp-sh-handle-delete-directory)
(delete-file . tramp-sh-handle-delete-file)
;; `diff-latest-backup-file' performed by default handler.
(directory-file-name . tramp-handle-directory-file-name)
(directory-files . tramp-handle-directory-files)
(directory-files-and-attributes
. tramp-sh-handle-directory-files-and-attributes)
(file-name-all-completions . tramp-sh-handle-file-name-all-completions)
(file-name-completion . tramp-handle-file-name-completion)
(add-name-to-file . tramp-sh-handle-add-name-to-file)
(copy-file . tramp-sh-handle-copy-file)
(copy-directory . tramp-sh-handle-copy-directory)
(rename-file . tramp-sh-handle-rename-file)
(set-file-modes . tramp-sh-handle-set-file-modes)
(set-file-times . tramp-sh-handle-set-file-times)
(make-directory . tramp-sh-handle-make-directory)
(delete-directory . tramp-sh-handle-delete-directory)
(delete-file . tramp-sh-handle-delete-file)
(directory-file-name . tramp-handle-directory-file-name)
;; `executable-find' is not official yet.
(executable-find . tramp-sh-handle-executable-find)
(start-file-process . tramp-sh-handle-start-file-process)
(process-file . tramp-sh-handle-process-file)
(shell-command . tramp-handle-shell-command)
(insert-directory . tramp-sh-handle-insert-directory)
(expand-file-name . tramp-sh-handle-expand-file-name)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(file-local-copy . tramp-sh-handle-file-local-copy)
(file-remote-p . tramp-handle-file-remote-p)
(insert-file-contents . tramp-handle-insert-file-contents)
(insert-file-contents-literally
. tramp-sh-handle-insert-file-contents-literally)
(write-region . tramp-sh-handle-write-region)
(find-backup-file-name . tramp-handle-find-backup-file-name)
(make-auto-save-file-name . tramp-sh-handle-make-auto-save-file-name)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
;; `dired-call-process' performed by default handler.
(dired-compress-file . tramp-sh-handle-dired-compress-file)
(dired-recursive-delete-directory
. tramp-sh-handle-dired-recursive-delete-directory)
(dired-uncache . tramp-handle-dired-uncache)
(set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime)
(verify-visited-file-modtime . tramp-sh-handle-verify-visited-file-modtime)
(file-selinux-context . tramp-sh-handle-file-selinux-context)
(set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
(expand-file-name . tramp-sh-handle-expand-file-name)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
(file-acl . tramp-sh-handle-file-acl)
(set-file-acl . tramp-sh-handle-set-file-acl)
(vc-registered . tramp-sh-handle-vc-registered)
(file-attributes . tramp-sh-handle-file-attributes)
(file-directory-p . tramp-sh-handle-file-directory-p)
;; `file-equal-p' performed by default handler.
(file-executable-p . tramp-sh-handle-file-executable-p)
(file-exists-p . tramp-sh-handle-file-exists-p)
;; `file-in-directory-p' performed by default handler.
(file-local-copy . tramp-sh-handle-file-local-copy)
(file-modes . tramp-handle-file-modes)
(file-name-all-completions . tramp-sh-handle-file-name-all-completions)
(file-name-as-directory . tramp-handle-file-name-as-directory)
(file-name-completion . tramp-handle-file-name-completion)
(file-name-directory . tramp-handle-file-name-directory)
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p)
(file-notify-add-watch . tramp-sh-handle-file-notify-add-watch)
(file-notify-rm-watch . tramp-sh-handle-file-notify-rm-watch))
(file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
(file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p)
(file-readable-p . tramp-sh-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
(file-remote-p . tramp-handle-file-remote-p)
(file-selinux-context . tramp-sh-handle-file-selinux-context)
(file-symlink-p . tramp-handle-file-symlink-p)
(file-truename . tramp-sh-handle-file-truename)
(file-writable-p . tramp-sh-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `find-file-noselect' performed by default handler.
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-sh-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
(insert-file-contents-literally
. tramp-sh-handle-insert-file-contents-literally)
(load . tramp-handle-load)
(make-auto-save-file-name . tramp-sh-handle-make-auto-save-file-name)
(make-directory . tramp-sh-handle-make-directory)
(make-symbolic-link . tramp-sh-handle-make-symbolic-link)
(process-file . tramp-sh-handle-process-file)
(rename-file . tramp-sh-handle-rename-file)
(set-file-acl . tramp-sh-handle-set-file-acl)
(set-file-modes . tramp-sh-handle-set-file-modes)
(set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
(set-file-times . tramp-sh-handle-set-file-times)
(set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime)
(shell-command . tramp-handle-shell-command)
(start-file-process . tramp-sh-handle-start-file-process)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
(vc-registered . tramp-sh-handle-vc-registered)
(verify-visited-file-modtime . tramp-sh-handle-verify-visited-file-modtime)
(write-region . tramp-sh-handle-write-region))
"Alist of handler functions.
Operations not mentioned here will be handled by the normal Emacs functions.")
@ -2284,9 +2289,7 @@ The method used must be an out-of-band method."
(tramp-get-method-parameter method 'tramp-copy-env))))
;; Check for program.
(unless (let ((default-directory
(tramp-compat-temporary-file-directory)))
(executable-find copy-program))
(unless (executable-find copy-program)
(tramp-error
v 'file-error "Cannot find copy program: %s" copy-program))
@ -2667,11 +2670,6 @@ the result will be a local, non-Tramp, filename."
;;; Remote commands:
(defun tramp-sh-handle-executable-find (command)
"Like `executable-find' for Tramp files."
(with-parsed-tramp-file-name default-directory nil
(tramp-find-executable v command (tramp-get-remote-path v) t)))
(defun tramp-process-sentinel (proc event)
"Flush file caches."
(unless (memq (process-status proc) '(run open))
@ -3430,8 +3428,8 @@ Fall back to normal file name handler if no Tramp handler exists."
(file-remote-p default-directory)))
(rest-string (tramp-compat-process-get proc 'rest-string)))
(when rest-string
(tramp-message proc 10 (format "Previous string:\n%s" rest-string)))
(tramp-message proc 6 (format "%S\n%s" proc string))
(tramp-message proc 10 "Previous string:\n%s" rest-string))
(tramp-message proc 6 "%S\n%s" proc string)
(setq string (concat rest-string string)
;; Attribute change is returned in unused wording.
string (replace-regexp-in-string
@ -3463,12 +3461,12 @@ Fall back to normal file name handler if no Tramp handler exists."
;; Save rest of the string.
(when (zerop (length string)) (setq string nil))
(when string (tramp-message proc 10 (format "Rest string:\n%s" string)))
(when string (tramp-message proc 10 "Rest string:\n%s" string))
(tramp-compat-process-put proc 'rest-string string)))
(defun tramp-sh-file-inotifywait-process-filter (proc string)
"Read output from \"inotifywait\" and add corresponding file-notify events."
(tramp-message proc 6 (format "%S\n%s" proc string))
(tramp-message proc 6 "%S\n%s" proc string)
(dolist (line (split-string string "[\n\r]+" 'omit-nulls))
;; Check, whether there is a problem.
(unless
@ -3492,15 +3490,6 @@ Fall back to normal file name handler if no Tramp handler exists."
;; once. Therefore, we apply the callback directly.
(tramp-compat-funcall 'file-notify-callback object))))
(defvar file-notify-descriptors)
(defun tramp-sh-handle-file-notify-rm-watch (proc)
"Like `file-notify-rm-watch' for Tramp files."
;; The descriptor must be a process object.
(unless (and (processp proc) (gethash proc file-notify-descriptors))
(tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc))
(tramp-message proc 6 (format "Kill %S" proc))
(kill-process proc))
;;; Internal Functions:
(defun tramp-maybe-send-script (vec script name)
@ -3618,7 +3607,7 @@ This function expects to be in the right *tramp* buffer."
I.e., for each directory in `tramp-remote-path', it is tested
whether it exists and if so, it is added to the environment
variable PATH."
(tramp-message vec 5 (format "Setting $PATH environment variable"))
(tramp-message vec 5 "Setting $PATH environment variable")
(tramp-send-command
vec (format "PATH=%s; export PATH"
(mapconcat 'identity (tramp-get-remote-path vec) ":"))))

View file

@ -177,8 +177,7 @@ See `tramp-actions-before-shell' for more info.")
;; New handlers should be added here.
(defconst tramp-smb-file-name-handler-alist
'(
;; `access-file' performed by default handler.
'(;; `access-file' performed by default handler.
(add-name-to-file . tramp-smb-handle-add-name-to-file)
;; `byte-compiler-base-file-name' performed by default handler.
(copy-directory . tramp-smb-handle-copy-directory)
@ -198,8 +197,10 @@ See `tramp-actions-before-shell' for more info.")
(file-acl . tramp-smb-handle-file-acl)
(file-attributes . tramp-smb-handle-file-attributes)
(file-directory-p . tramp-smb-handle-file-directory-p)
;; `file-equal-p' performed by default handler.
(file-executable-p . tramp-handle-file-exists-p)
(file-exists-p . tramp-handle-file-exists-p)
;; `file-in-directory-p' performed by default handler.
(file-local-copy . tramp-smb-handle-file-local-copy)
(file-modes . tramp-handle-file-modes)
(file-name-all-completions . tramp-smb-handle-file-name-all-completions)
@ -210,7 +211,7 @@ See `tramp-actions-before-shell' for more info.")
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
(file-notify-add-watch . tramp-handle-file-notify-add-watch)
(file-notify-rm-watch . ignore)
(file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
(file-ownership-preserved-p . ignore)
(file-readable-p . tramp-handle-file-exists-p)
(file-regular-p . tramp-handle-file-regular-p)
@ -225,6 +226,7 @@ See `tramp-actions-before-shell' for more info.")
(insert-directory . tramp-smb-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
(load . tramp-handle-load)
;; `make-auto-save-file-name' performed by default handler.
(make-directory . tramp-smb-handle-make-directory)
(make-directory-internal . tramp-smb-handle-make-directory-internal)
(make-symbolic-link . tramp-smb-handle-make-symbolic-link)
@ -234,15 +236,14 @@ See `tramp-actions-before-shell' for more info.")
(set-file-modes . tramp-smb-handle-set-file-modes)
(set-file-selinux-context . ignore)
(set-file-times . ignore)
(set-visited-file-modtime . ignore)
(set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
(shell-command . tramp-handle-shell-command)
(start-file-process . tramp-smb-handle-start-file-process)
(substitute-in-file-name . tramp-smb-handle-substitute-in-file-name)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
(vc-registered . ignore)
(verify-visited-file-modtime . ignore)
(write-region . tramp-smb-handle-write-region)
)
(verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
(write-region . tramp-smb-handle-write-region))
"Alist of handler functions for Tramp SMB method.
Operations not mentioned here will be handled by the default Emacs primitives.")
@ -1786,9 +1787,7 @@ Returns nil if an error message has appeared."
(tramp-get-buffer vec)
;; Check for program.
(unless (let ((default-directory
(tramp-compat-temporary-file-directory)))
(executable-find tramp-smb-winexe-program))
(unless (executable-find tramp-smb-winexe-program)
(tramp-error
vec 'file-error "Cannot find program: %s" tramp-smb-winexe-program))

View file

@ -1975,11 +1975,11 @@ ARGS are the arguments OPERATION has been called with."
'dired-compress-file 'dired-uncache
'file-accessible-directory-p 'file-attributes
'file-directory-p 'file-executable-p 'file-exists-p
'file-local-copy 'file-remote-p 'file-modes
'file-local-copy 'file-modes
'file-name-as-directory 'file-name-directory
'file-name-nondirectory 'file-name-sans-versions
'file-ownership-preserved-p 'file-readable-p
'file-regular-p 'file-symlink-p 'file-truename
'file-regular-p 'file-remote-p 'file-symlink-p 'file-truename
'file-writable-p 'find-backup-file-name 'find-file-noselect
'get-file-buffer 'insert-directory 'insert-file-contents
'load 'make-directory 'make-directory-internal
@ -2008,7 +2008,7 @@ ARGS are the arguments OPERATION has been called with."
;; Emacs 23+ only.
'copy-directory
;; Emacs 24+ only.
'file-in-directory-p 'file-equal-p
'file-equal-p 'file-in-directory-p
;; XEmacs only.
'dired-make-relative-symlink
'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail))
@ -3287,14 +3287,78 @@ beginning of local filename are not substituted."
;; for backward compatibility.
(expand-file-name "~/"))
(defun tramp-handle-set-visited-file-modtime (&optional time-list)
"Like `set-visited-file-modtime' for Tramp files."
(unless (buffer-file-name)
(error "Can't set-visited-file-modtime: buffer `%s' not visiting a file"
(buffer-name)))
(unless time-list
(let ((remote-file-name-inhibit-cache t))
;; '(-1 65535) means file doesn't exists yet.
(setq time-list
(or (nth 5 (file-attributes (buffer-file-name))) '(-1 65535)))))
;; We use '(0 0) as a don't-know value.
(unless (equal time-list '(0 0))
(tramp-run-real-handler 'set-visited-file-modtime (list time-list))))
(defun tramp-handle-verify-visited-file-modtime (&optional buf)
"Like `verify-visited-file-modtime' for Tramp files.
At the time `verify-visited-file-modtime' calls this function, we
already know that the buffer is visiting a file and that
`visited-file-modtime' does not return 0. Do not call this
function directly, unless those two cases are already taken care
of."
(with-current-buffer (or buf (current-buffer))
(let ((f (buffer-file-name)))
;; There is no file visiting the buffer, or the buffer has no
;; recorded last modification time, or there is no established
;; connection.
(if (or (not f)
(eq (visited-file-modtime) 0)
(not (tramp-file-name-handler 'file-remote-p f nil 'connected)))
t
(with-parsed-tramp-file-name f nil
(let* ((remote-file-name-inhibit-cache t)
(attr (file-attributes f))
(modtime (nth 5 attr))
(mt (visited-file-modtime)))
(cond
;; File exists, and has a known modtime.
((and attr (not (equal modtime '(0 0))))
(< (abs (tramp-time-diff
modtime
;; For compatibility, deal with both the old
;; (HIGH . LOW) and the new (HIGH LOW) return
;; values of `visited-file-modtime'.
(if (atom (cdr mt))
(list (car mt) (cdr mt))
mt)))
2))
;; Modtime has the don't know value.
(attr t)
;; If file does not exist, say it is not modified if and
;; only if that agrees with the buffer's record.
(t (equal mt '(-1 65535))))))))))
(defun tramp-handle-file-notify-add-watch (filename flags callback)
"Like `file-notify-add-watch' for Tramp files."
;; This is the default handler. Some packages might have its own one.
;; This is the default handler. tramp-gvfs.el and tramp-sh.el have
;; its own one.
(setq filename (expand-file-name filename))
(with-parsed-tramp-file-name filename nil
(tramp-error
v 'file-notify-error "File notification not supported for `%s'" filename)))
(defvar file-notify-descriptors)
(defun tramp-handle-file-notify-rm-watch (proc)
"Like `file-notify-rm-watch' for Tramp files."
;; The descriptor must be a process object.
(unless (and (processp proc) (gethash proc file-notify-descriptors))
(tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc))
(tramp-message proc 6 "Kill %S" proc)
(kill-process proc))
;;; Functions for establishing connection:
;; The following functions are actions to be taken when seeing certain
@ -3951,16 +4015,12 @@ This is needed because for some Emacs flavors Tramp has
defadvised `call-process' to behave like `process-file'. The
Lisp error raised when PROGRAM is nil is trapped also, returning 1.
Furthermore, traces are written with verbosity of 6."
(let ((default-directory
(if (file-remote-p default-directory)
(tramp-compat-temporary-file-directory)
default-directory)))
(tramp-message
(vector tramp-current-method tramp-current-user tramp-current-host nil nil)
6 "%s %s %s" program infile args)
(if (executable-find program)
(apply 'call-process program infile destination display args)
1)))
(tramp-message
(vector tramp-current-method tramp-current-user tramp-current-host nil nil)
6 "%s %s %s" program infile args)
(if (executable-find program)
(apply 'call-process program infile destination display args)
1))
;;;###tramp-autoload
(defun tramp-read-passwd (proc &optional prompt)

View file

@ -1611,7 +1611,7 @@ With ARG non-nil, silently save all file-visiting buffers, then kill.
If emacsclient was started with a list of filenames to edit, then
only these files will be asked to be saved."
(let ((proc (frame-parameter (selected-frame) 'client)))
(let ((proc (frame-parameter nil 'client)))
(cond ((eq proc 'nowait)
;; Nowait frames have no client buffer list.
(if (cdr (frame-list))

View file

@ -250,7 +250,7 @@ frame."
(defcustom speedbar-query-confirmation-method 'all
"Query control for file operations.
The 'always flag means to always query before file operations.
The 'all flag means to always query before file operations.
The 'none-but-delete flag means to not query before any file
operations, except before a file deletion."
:group 'speedbar

View file

@ -229,7 +229,7 @@ When called with a raw C-u prefix, rescan the document first."
(car (reftex-where-am-I))))
(unsplittable (if (fboundp 'frame-property)
(frame-property (selected-frame) 'unsplittable)
(frame-parameter (selected-frame) 'unsplittable)))
(frame-parameter nil 'unsplittable)))
offset toc-window)
(if (setq toc-window (get-buffer-window
@ -587,7 +587,7 @@ With prefix arg 1, restrict index to the section at point."
(let ((unsplittable
(if (fboundp 'frame-property)
(frame-property (selected-frame) 'unsplittable)
(frame-parameter (selected-frame) 'unsplittable)))
(frame-parameter nil 'unsplittable)))
(reftex-rebuilding-toc t))
(if unsplittable
(switch-to-buffer

View file

@ -1,3 +1,8 @@
2013-07-31 Stefan Monnier <monnier@iro.umontreal.ca>
* url-handlers.el (url-file-name-completion)
(url-file-name-all-completions): Don't signal errors (bug#14806).
2013-07-22 Stefan Monnier <monnier@iro.umontreal.ca>
* url-http.el (status): Remove, unused.

View file

@ -311,11 +311,17 @@ They count bytes from the beginning of the body."
(put 'insert-file-contents 'url-file-handlers 'url-insert-file-contents)
(defun url-file-name-completion (url directory &optional predicate)
(error "Unimplemented"))
;; Even if it's not implemented, it's not an error to ask for completion,
;; in case it's available (bug#14806).
;; (error "Unimplemented")
url)
(put 'file-name-completion 'url-file-handlers 'url-file-name-completion)
(defun url-file-name-all-completions (file directory)
(error "Unimplemented"))
;; Even if it's not implemented, it's not an error to ask for completion,
;; in case it's available (bug#14806).
;; (error "Unimplemented")
nil)
(put 'file-name-all-completions
'url-file-handlers 'url-file-name-all-completions)

View file

@ -562,19 +562,7 @@ file(s)."
(interactive
(list (if (use-region-p) (region-beginning) (point))
(if (use-region-p) (region-end) (point))))
(let ((fr (log-view-current-tag beg))
(to (log-view-current-tag end)))
(when (string-equal fr to)
(save-excursion
(goto-char end)
(log-view-msg-next)
(setq to (log-view-current-tag))))
(vc-diff-internal
t (list log-view-vc-backend
(if log-view-per-file-logs
(list (log-view-current-file))
log-view-vc-fileset))
to fr)))
(log-view-diff-common beg end))
(defun log-view-diff-changeset (beg end)
"Get the diff between two revisions.
@ -589,20 +577,29 @@ considered file(s)."
(interactive
(list (if (use-region-p) (region-beginning) (point))
(if (use-region-p) (region-end) (point))))
(when (eq (vc-call-backend log-view-vc-backend 'revision-granularity) 'file)
(log-view-diff-common beg end t))
(defun log-view-diff-common (beg end &optional whole-changeset)
(when (and whole-changeset
(eq (vc-call-backend log-view-vc-backend 'revision-granularity)
'file))
(error "The %s backend does not support changeset diffs" log-view-vc-backend))
(let ((fr (log-view-current-tag beg))
(to (log-view-current-tag end)))
(let ((to (log-view-current-tag beg))
(fr (log-view-current-tag end)))
(when (string-equal fr to)
;; TO and FR are the same, look at the previous revision.
(setq to (vc-call-backend log-view-vc-backend 'previous-revision nil fr)))
(setq fr (vc-call-backend log-view-vc-backend 'previous-revision nil fr)))
(vc-diff-internal
t
;; We want to see the diff for all the files in the changeset, so
;; pass NIL for the file list. The value passed here should
;; follow what `vc-deduce-fileset' returns.
(list log-view-vc-backend nil)
to fr)))
t (list log-view-vc-backend
;; The value passed here should follow what
;; `vc-deduce-fileset' returns. If we want to see the
;; diff for all the files in the changeset, pass NIL for
;; the file list.
(unless whole-changeset
(if log-view-per-file-logs
(list (log-view-current-file))
log-view-vc-fileset)))
fr to)))
(provide 'log-view)

View file

@ -282,7 +282,7 @@ See `run-hooks'."
(define-key map "Q" 'vc-dir-query-replace-regexp)
(define-key map (kbd "M-s a C-s") 'vc-dir-isearch)
(define-key map (kbd "M-s a M-C-s") 'vc-dir-isearch-regexp)
(define-key map "I" 'vc-dir-ignore)
(define-key map "G" 'vc-dir-ignore)
;; Hook up the menu.
(define-key map [menu-bar vc-dir-mode]

View file

@ -918,6 +918,7 @@ current, and kill the buffer that visits the link."
(define-key map "c" 'vc-rollback)
(define-key map "d" 'vc-dir)
(define-key map "g" 'vc-annotate)
(define-key map "G" 'vc-ignore)
(define-key map "h" 'vc-insert-headers)
(define-key map "i" 'vc-register)
(define-key map "l" 'vc-print-log)
@ -1002,6 +1003,9 @@ current, and kill the buffer that visits the link."
(bindings--define-key map [vc-register]
'(menu-item "Register" vc-register
:help "Register file set into a version control system"))
(bindings--define-key map [vc-ignore]
'(menu-item "Ignore File..." vc-ignore
:help "Ignore a file under current version control system"))
(bindings--define-key map [vc-dir]
'(menu-item "VC Dir" vc-dir
:help "Show the VC status of files in a directory"))

View file

@ -1471,6 +1471,12 @@ documentation."
;; PROBLEM 6: 8 or more SPACEs after TAB
(whitespace-cleanup-region (point-min) (point-max)))))
(defun whitespace-ensure-local-variables ()
"Set `whitespace-indent-tabs-mode' and `whitespace-tab-width' locally."
(set (make-local-variable 'whitespace-indent-tabs-mode)
indent-tabs-mode)
(set (make-local-variable 'whitespace-tab-width)
tab-width))
;;;###autoload
(defun whitespace-cleanup-region (start end)
@ -1517,6 +1523,7 @@ documentation."
;; read-only buffer
(whitespace-warn-read-only "cleanup region")
;; non-read-only buffer
(whitespace-ensure-local-variables)
(let ((rstart (min start end))
(rend (copy-marker (max start end)))
(indent-tabs-mode whitespace-indent-tabs-mode)
@ -2095,7 +2102,6 @@ resultant list will be returned."
(defvar whitespace-display-table-was-local nil
"Used to remember whether a buffer initially had a local display table.")
(defun whitespace-turn-on ()
"Turn on whitespace visualization."
;; prepare local hooks
@ -2108,10 +2114,7 @@ resultant list will be returned."
(if (listp whitespace-style)
whitespace-style
(list whitespace-style)))
(set (make-local-variable 'whitespace-indent-tabs-mode)
indent-tabs-mode)
(set (make-local-variable 'whitespace-tab-width)
tab-width)
(whitespace-ensure-local-variables)
;; turn on whitespace
(when whitespace-active-style
(whitespace-color-on)

View file

@ -1,3 +1,191 @@
2013-08-03 Paul Eggert <eggert@cs.ucla.edu>
* composite.h: Minor fixups.
(composition_registered_p): Rename from COMPOSITION_REGISTERD_P
to fix a misspelling, and change it to an inline function while
we're at it (it need not be a macro). All uses changed.
(composition_method, composition_valid_p):
Rewrite to avoid assignments in if-conditions.
2013-08-03 Dmitry Antipov <dmantipov@yandex.ru>
Do not use global Lisp_Object in composition macros.
* composite.h (composition_temp): Remove declaration.
(COMPOSITION_METHOD, COMPOSITION_VALID_P): Replace with...
(composition_method, composition_valid_p): ...inline functions.
(compose_region): Remove the leftover.
* composite.c (composition_temp): Remove.
(run_composition_function, update_compositions)
(composition_compute_stop_pos, composition_adjust_point)
(Ffind_composition_internal):
* coding.c (handle_composition_annotation):
* xdisp.c (handle_composition_prop, check_point_in_composition):
Related users changed.
2013-08-03 Dmitry Antipov <dmantipov@yandex.ru>
Drop FRAME_PTR typedef.
* composite.c, font.c, font.h, fontset.c, fontset.h, frame.c, frame.h:
* ftfont.c, ftxfont.c, gtkutil.c, gtkutil.h, image.c, keyboard.c:
* menu.c, menu.h, msdos.c, nsfns.m, nsfont.m, nsmenu.m, nsterm.h:
* nsterm.m, scroll.c, term.c, w32fns.c, w32font.c, w32font.h:
* w32inevt.c, w32inevt.h, w32menu.c, w32notify.c, w32term.c, w32term.h:
* w32uniscribe.c, w32xfns.c, widget.c, window.c, xdisp.c, xfaces.c:
* xfns.c, xfont.c, xftfont.c, xmenu.c, xselect.c, xterm.c:
All related users changed.
2013-08-02 Stefan Monnier <monnier@iro.umontreal.ca>
* eval.c (default_toplevel_binding): New function.
(Fdefvar): Use it.
(unbind_to, backtrace_eval_unrewind): Do a bit of CSE simplification.
(Fdefault_toplevel_value, Fset_default_toplevel_value): New subrs.
(syms_of_eval): Export them.
* data.c (Fdefault_value): Micro cleanup.
* term.c (init_tty): Use "false".
2013-08-02 Dmitry Antipov <dmantipov@yandex.ru>
Fix X GC leak in GTK and raw (no toolkit) X ports.
* xterm.c (x_free_frame_resources): If white and black relief
GCs are allocated, always free them here.
* xfns.c (x_make_gc): Omit redundant initialization.
* widget.c (create_frame_gcs): Remove the leftover.
(EmacsFrameDestroy): Do nothing because all GCs are now freed
in x_free_frame_resources.
2013-08-02 Jan Djärv <jan.h.d@swipnet.se>
* nsterm.m (windowWillResize:toSize:): Only change title if
! maximizing_resize && FULLSCREEN_NONE (Bug#15005). strdup title before
modifying it.
(viewDidEndLiveResize): New method.
* nsterm.h (EmacsView): Add maximizing_resize, put it and old_title
inside NS_IMPL_COCOA.
2013-08-02 Dmitry Antipov <dmantipov@yandex.ru>
* insdel.c (adjust_after_replace, replace_range, del_range_2):
Do not check whether undo is enabled because record_insert and
record_delete does that themselves.
2013-08-02 Dmitry Antipov <dmantipov@yandex.ru>
* xterm.h (struct x_output) [HAVE_X_I18N]: Remove xic_base_fontname
member which is not really used any more.
(FRAME_XIC_BASE_FONTNAME): Remove.
* xfns.c (xic_free_fontset): Adjust user.
* xmenu.c (mouse_position_for_popup, x_activate_menubar)
(update_frame_menubar, set_frame_menubar, free_frame_menubar)
(create_and_show_popup_menu, xmenu_show, create_and_show_dialog)
(xdialog_show): Use eassert for debugging check.
* w32term.c (x_unfocus_frame): Remove unused dummy function.
2013-08-01 Paul Eggert <eggert@cs.ucla.edu>
* fileio.c, fns.c (merge): Move extern decl from here ...
* lisp.h (merge): ... to here.
2013-08-01 Dmitry Antipov <dmantipov@yandex.ru>
Fix last font-related change.
* w32font.h (w32font_list_internal, w32font_match_internal):
Fix prototype.
* w32uniscribe.c (uniscribe_list, uniscribe_match):
(uniscribe_list_family): Adjust to match font API change.
MS-Windows breakage reported by Juanma Barranquero <lekktu@gmail.com>
at http://lists.gnu.org/archive/html/emacs-devel/2013-08/msg00006.html.
2013-08-01 Dmitry Antipov <dmantipov@yandex.ru>
* frame.h (FRAME_MOUSE_UPDATE):
* nsterm.m (ns_frame_up_to_date): Omit redundant check
whether hlinfo->mouse_face_mouse_frame is non-NULL.
2013-08-01 Dmitry Antipov <dmantipov@yandex.ru>
Avoid redundant Lisp_Object <-> struct frame conversions in font API.
* font.h (struct font_driver): Change list, match, and list_family
functions to accept struct frame * as first arg.
* font.c (font_score, font_compare, font_sort_entities): Remove
prototypes.
(font_sort_entities, font_list_entities, font_select_entity):
(font_find_for_lface, Flist_fonts, Ffont_family_list): Adjust to
match font API change.
* xfont.c (xfont_list, xfont_match, xfont_list_family):
* ftfont.c (ftfont_list, ftfont_match, ftfont_list_family):
* ftxfont.c (ftxfont_list, ftxfont_match):
* xftfont.c (xftfont_list, xftfont_match):
* nsfont.m (nsfont_list, nsfont_match, nsfont_list_family):
* w32font.c (w32font_list, w32font_match, w32font_list):
(w32font_list_internal, w32_font_match_internal): Likewise.
* xfaces.c (Fx_family_fonts): Adjust user.
2013-08-01 Dmitry Antipov <dmantipov@yandex.ru>
Do not use pure Xism x_wm_set_icon_position in non-X ports.
* frame.c (x_set_frame_parameters): Call to x_wm_set_icon_position
only if HAVE_X_WINDOWS is in use.
* frame.h (x_set_frame_parameters): Move under HAVE_X_WINDOWS.
* nsterm.m (x_wm_set_icon_position): Remove no-op.
* w32term.c (x_wm_set_icon_position): Likewise.
* w32fns.c (x_icon): Adjust user.
2013-08-01 Dmitry Antipov <dmantipov@yandex.ru>
* xterm.c (last_mouse_press_frame): Remove the
leftover which is not really used any more.
(handle_one_xevent, syms_of_xterm): Adjust users.
(x_flush): Call XFlush once per each X display, not frame.
This is better because this code always unconditionally skips
non-X frames in Vframe_list and issues the only XFlush if we
have more than one X frame on the same X display.
(any_help_event_p, x_draw_glyph_string_background, x_display_ok):
Use bool for booleans.
(x_draw_glyph_string_background, cvt_string_to_pixel):
(cvt_pixel_dtor): Drop unnecessary prototypes.
* xterm.h (x_display_ok): Adjust prototype.
2013-07-31 Dmitry Antipov <dmantipov@yandex.ru>
Drop unnecessary functions that deals with frame pixel size.
* frame.h, msdos.h, w32term.h, xterm.h (x_pixel_width)
(x_pixel_height): Drop prototypes.
* msdos.c, nsfns.m, w32fns.c, xfns.c (x_pixel_width)
(x_pixel_height): Drop implementations.
* frame.c (Fframe_pixel_height): Use FRAME_PIXEL_HEIGHT
which should be always valid for window frame.
(Frame_pixel_width): Likewise with FRAME_PIXEL_WIDTH.
* w32menu.c (Fx_popup_dialog):
* xmenu.c (Fx_popup_dialog): Likewise for both.
2013-07-31 Dmitry Antipov <dmantipov@yandex.ru>
* frame.c (Fmake_terminal_frame): Use store_in_alist to setup
frame parameters and call to Fmodify_frame_parameters just once.
(Fset_frame_height, Fset_frame_width): Mention nil frame in docstring.
(Fset_frame_size, Fset_frame_position): Use decode_live_frame
and mention nil frame in docstring.
2013-07-31 Dmitry Antipov <dmantipov@yandex.ru>
* frame.c (make_frame, x_set_frame_parameters): Use bool for boolean.
(x_figure_window_size): Likewise. Adjust to return long.
(syms_of_frame): Do not DEFSYM Qterminal_live_p.
(toplevel): Move Qterminal_live_p to...
* terminal.c (toplevel): ...here, make it static, and...
(syms_of_terminal): ...DEFSYM here.
* frame.h (Qterminal_live_p): Remove declaration.
(make_frame, x_figure_window_size): Adjust prototype.
* nsfns.m (Fx_create_frame): Use long for window flags.
2013-07-30 Paul Eggert <eggert@cs.ucla.edu>
Fix tempfile bug on platforms lacking mkostemp and mkstemp (Bug#14986).
* callproc.c (create_temp_file) [! (HAVE_MKOSTEMP || HAVE_MKSTEMP)]:
Do not assume that emacs_close (INT_MAX) is a no-op.
2013-07-30 Dmitry Antipov <dmantipov@yandex.ru>
* xfaces.c (make_face_cache): For struct face_cache, prefer
@ -325,7 +513,7 @@
code a bit. It makes no difference on POSIXish platforms but
apparently it fixes a bug on w32.
Fix bug where insert-file-contents closes a file twice. (Bug#14839).
Fix bug where insert-file-contents closes a file twice (Bug#14839).
* fileio.c (close_file_unwind): Don't close if FD is negative;
this can happen when unwinding a zapped file descriptor.
(Finsert_file_contents): Unwind-protect the fd before the point marker,
@ -478,7 +666,7 @@
(make_lispy_focus_in, make_lispy_focus_out): Declare and define.
(kbd_buffer_get_event): For FOCUS_IN, make a focus_in event if no
switch frame event is made. Check ! NILP (event->arg) if X11 (moved
from xterm.c). Make focus_out event for FOCUS_OUT_EVENT if NS or X11
from xterm.c). Make focus_out event for FOCUS_OUT_EVENT if NS or X11
and there is a focused frame.
(head_table): Add focus-in and focus-out.
(keys_of_keyboard): Add focus-in and focus-out to Vspecial_event_map,
@ -851,7 +1039,7 @@
(emacswrite_sig, emacs_perror): New functions.
* xrdb.c (fatal): Don't invoke perror, since errno might be garbage.
2013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change).
2013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change)
* image.c (imagemagick_load_image): Do not use MagickExportImagePixels
on NS even if it is present. Pixmap on NS is a void*.
@ -1526,7 +1714,7 @@
Now static.
* lisp.h: Remove the abovementioned defns and decls.
Use functions, not macros, for XINT etc. (Bug#11935).
Use functions, not macros, for XINT etc (Bug#11935).
In lisp.h, prefer functions to function-like macros, and
constants to object-like macros, when either will do. This:
. simplifies use, as there's no more need to worry about

View file

@ -1018,13 +1018,14 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args)
#else
errno = EEXIST;
mktemp (tempfile);
/* INT_MAX denotes success, because close (INT_MAX) does nothing. */
fd = *tempfile ? INT_MAX : -1;
fd = *tempfile ? 0 : -1;
#endif
if (fd < 0)
report_file_error ("Failed to open temporary file using pattern",
pattern);
#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP
emacs_close (fd);
#endif
}
record_unwind_protect (delete_temp_file, filename_string);

View file

@ -7497,7 +7497,7 @@ handle_composition_annotation (ptrdiff_t pos, ptrdiff_t limit,
/* We found a composition. Store the corresponding
annotation data in BUF. */
int *head = buf;
enum composition_method method = COMPOSITION_METHOD (prop);
enum composition_method method = composition_method (prop);
int nchars = COMPOSITION_LENGTH (prop);
ADD_COMPOSITION_DATA (buf, nchars, 0, method);

View file

@ -160,10 +160,6 @@ static Lisp_Object Qauto_composition_function;
auto-compositions. */
#define MAX_AUTO_COMPOSITION_LOOKBACK 3
/* Temporary variable used in macros COMPOSITION_XXX. */
Lisp_Object composition_temp;
/* Return COMPOSITION-ID of a composition at buffer position
CHARPOS/BYTEPOS and length NCHARS. The `composition' property of
the sequence is PROP. STRING, if non-nil, is a string that
@ -478,11 +474,11 @@ run_composition_function (ptrdiff_t from, ptrdiff_t to, Lisp_Object prop)
valid too. */
if (from > BEGV
&& find_composition (from - 1, -1, &start, &end, &prop, Qnil)
&& !COMPOSITION_VALID_P (start, end, prop))
&& !composition_valid_p (start, end, prop))
from = start;
if (to < ZV
&& find_composition (to, -1, &start, &end, &prop, Qnil)
&& !COMPOSITION_VALID_P (start, end, prop))
&& !composition_valid_p (start, end, prop))
to = end;
if (!NILP (Ffboundp (func)))
call2 (func, make_number (from), make_number (to));
@ -524,7 +520,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
latter to the copy of it. */
if (from > BEGV
&& find_composition (from - 1, -1, &start, &end, &prop, Qnil)
&& COMPOSITION_VALID_P (start, end, prop))
&& composition_valid_p (start, end, prop))
{
min_pos = start;
if (end > to)
@ -538,7 +534,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
}
else if (from < ZV
&& find_composition (from, -1, &start, &from, &prop, Qnil)
&& COMPOSITION_VALID_P (start, from, prop))
&& composition_valid_p (start, from, prop))
{
if (from > to)
max_pos = from;
@ -553,7 +549,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
(to - 1). */
while (from < to - 1
&& find_composition (from, to, &start, &from, &prop, Qnil)
&& COMPOSITION_VALID_P (start, from, prop)
&& composition_valid_p (start, from, prop)
&& from < to - 1)
run_composition_function (start, from, prop);
}
@ -562,7 +558,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
{
if (from < to
&& find_composition (to - 1, -1, &start, &end, &prop, Qnil)
&& COMPOSITION_VALID_P (start, end, prop))
&& composition_valid_p (start, end, prop))
{
/* TO should be also at composition boundary. But,
insertion or deletion will make two compositions adjacent
@ -580,7 +576,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
}
else if (to < ZV
&& find_composition (to, -1, &start, &end, &prop, Qnil)
&& COMPOSITION_VALID_P (start, end, prop))
&& composition_valid_p (start, end, prop))
{
run_composition_function (start, end, prop);
max_pos = end;
@ -901,7 +897,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
Lisp_Object string)
{
ptrdiff_t count = SPECPDL_INDEX ();
FRAME_PTR f = XFRAME (win->frame);
struct frame *f = XFRAME (win->frame);
Lisp_Object pos = make_number (charpos);
ptrdiff_t to;
ptrdiff_t pt = PT, pt_byte = PT_BYTE;
@ -1012,7 +1008,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
if (charpos < endpos
&& find_composition (charpos, endpos, &start, &end, &prop, string)
&& start >= charpos
&& COMPOSITION_VALID_P (start, end, prop))
&& composition_valid_p (start, end, prop))
{
cmp_it->stop_pos = endpos = start;
cmp_it->ch = -1;
@ -1672,7 +1668,7 @@ composition_adjust_point (ptrdiff_t last_pt, ptrdiff_t new_pt)
/* At first check the static composition. */
if (get_property_and_range (new_pt, Qcomposition, &val, &beg, &end, Qnil)
&& COMPOSITION_VALID_P (beg, end, val))
&& composition_valid_p (beg, end, val))
{
if (beg < new_pt /* && end > new_pt <- It's always the case. */
&& (last_pt <= beg || last_pt >= end))
@ -1872,12 +1868,12 @@ See `find-composition' for more details. */)
&& (e <= XINT (pos) ? e > end : s < start))
return list3 (make_number (s), make_number (e), gstring);
}
if (!COMPOSITION_VALID_P (start, end, prop))
if (!composition_valid_p (start, end, prop))
return list3 (make_number (start), make_number (end), Qnil);
if (NILP (detail_p))
return list3 (make_number (start), make_number (end), Qt);
if (COMPOSITION_REGISTERD_P (prop))
if (composition_registered_p (prop))
id = COMPOSITION_ID (prop);
else
{
@ -1890,7 +1886,7 @@ See `find-composition' for more details. */)
if (id >= 0)
{
Lisp_Object components, relative_p, mod_func;
enum composition_method method = COMPOSITION_METHOD (prop);
enum composition_method method = composition_method (prop);
int width = composition_table[id]->width;
components = Fcopy_sequence (COMPOSITION_COMPONENTS (prop));

View file

@ -49,69 +49,41 @@ enum composition_method {
/* Maximum number of components a single composition can have. */
#define MAX_COMPOSITION_COMPONENTS 16
/* These macros access information about a composition that
/* These operations access information about a composition that
has `composition' property PROP. PROP is:
((LENGTH . COMPONENTS) . MODIFICATION-FUNC)
or
(COMPOSITION-ID . (LENGTH COMPONENTS . MODIFICATION-FUNC))
They don't check validity of PROP. */
/* Temporary variable used only in the following macros. */
extern Lisp_Object composition_temp;
/* Return 1 if the composition is already registered. */
#define COMPOSITION_REGISTERD_P(prop) INTEGERP (XCAR (prop))
/* Return true if PROP is already registered. */
COMPOSITE_INLINE bool
composition_registered_p (Lisp_Object prop)
{
return INTEGERP (XCAR (prop));
}
/* Return ID number of the already registered composition. */
#define COMPOSITION_ID(prop) XINT (XCAR (prop))
/* Return length of the composition. */
#define COMPOSITION_LENGTH(prop) \
(COMPOSITION_REGISTERD_P (prop) \
(composition_registered_p (prop) \
? XINT (XCAR (XCDR (prop))) \
: XINT (XCAR (XCAR (prop))))
/* Return components of the composition. */
#define COMPOSITION_COMPONENTS(prop) \
(COMPOSITION_REGISTERD_P (prop) \
(composition_registered_p (prop) \
? XCAR (XCDR (XCDR (prop))) \
: XCDR (XCAR (prop)))
/* Return modification function of the composition. */
#define COMPOSITION_MODIFICATION_FUNC(prop) \
(COMPOSITION_REGISTERD_P (prop) \
(composition_registered_p (prop) \
? XCDR (XCDR (XCDR (prop))) \
: CONSP (prop) ? XCDR (prop) : Qnil)
/* Return the method of composition. */
#define COMPOSITION_METHOD(prop) \
(COMPOSITION_REGISTERD_P (prop) \
? composition_table[COMPOSITION_ID (prop)]->method \
: (composition_temp = XCDR (XCAR (prop)), \
(NILP (composition_temp) \
? COMPOSITION_RELATIVE \
: (INTEGERP (composition_temp) || STRINGP (composition_temp)) \
? COMPOSITION_WITH_ALTCHARS \
: COMPOSITION_WITH_RULE_ALTCHARS)))
/* Return 1 if the composition is valid. It is valid if length of
the composition equals to (END - START). */
#define COMPOSITION_VALID_P(start, end, prop) \
(CONSP (prop) \
&& (COMPOSITION_REGISTERD_P (prop) \
? (COMPOSITION_ID (prop) >= 0 \
&& COMPOSITION_ID (prop) <= n_compositions \
&& CONSP (XCDR (prop))) \
: (composition_temp = XCAR (prop), \
(CONSP (composition_temp) \
&& (composition_temp = XCDR (composition_temp), \
(NILP (composition_temp) \
|| STRINGP (composition_temp) \
|| VECTORP (composition_temp) \
|| INTEGERP (composition_temp) \
|| CONSP (composition_temp)))))) \
&& (end - start) == COMPOSITION_LENGTH (prop))
/* Return the Nth glyph of composition specified by CMP. CMP is a
pointer to `struct composition'. */
#define COMPOSITION_GLYPH(cmp, n) \
@ -227,12 +199,48 @@ extern bool find_composition (ptrdiff_t, ptrdiff_t, ptrdiff_t *, ptrdiff_t *,
Lisp_Object *, Lisp_Object);
extern void update_compositions (ptrdiff_t, ptrdiff_t, int);
extern void make_composition_value_copy (Lisp_Object);
extern void compose_region (int, int, Lisp_Object, Lisp_Object,
Lisp_Object);
extern void syms_of_composite (void);
extern void compose_text (ptrdiff_t, ptrdiff_t, Lisp_Object, Lisp_Object,
Lisp_Object);
/* Return the method of a composition with property PROP. */
COMPOSITE_INLINE enum composition_method
composition_method (Lisp_Object prop)
{
if (composition_registered_p (prop))
return composition_table[COMPOSITION_ID (prop)]->method;
else
{
Lisp_Object temp = XCDR (XCAR (prop));
return (NILP (temp)
? COMPOSITION_RELATIVE
: INTEGERP (temp) || STRINGP (temp)
? COMPOSITION_WITH_ALTCHARS
: COMPOSITION_WITH_RULE_ALTCHARS);
}
}
/* Given offsets START and END, return true if PROP is a valid composition
property with length END - START. */
COMPOSITE_INLINE bool
composition_valid_p (ptrdiff_t start, ptrdiff_t end, Lisp_Object prop)
{
return (CONSP (prop)
&& (composition_registered_p (prop)
? (COMPOSITION_ID (prop) >= 0
&& COMPOSITION_ID (prop) <= n_compositions
&& CONSP (XCDR (prop)))
: (CONSP (XCAR (prop))
&& (NILP (XCDR (XCAR (prop)))
|| STRINGP (XCDR (XCAR (prop)))
|| VECTORP (XCDR (XCAR (prop)))
|| INTEGERP (XCDR (XCAR (prop)))
|| CONSP (XCDR (XCAR (prop))))))
&& COMPOSITION_LENGTH (prop) == end - start);
}
/* Macros for lispy glyph-string. This is completely different from
struct glyph_string. */

View file

@ -1384,9 +1384,7 @@ for this variable. The default value is meaningful for variables with
local bindings in certain buffers. */)
(Lisp_Object symbol)
{
register Lisp_Object value;
value = default_value (symbol);
Lisp_Object value = default_value (symbol);
if (!EQ (value, Qunbound))
return value;

View file

@ -658,6 +658,51 @@ The return value is BASE-VARIABLE. */)
return base_variable;
}
static union specbinding *
default_toplevel_binding (Lisp_Object symbol)
{
union specbinding *binding = NULL;
union specbinding *pdl = specpdl_ptr;
while (pdl > specpdl)
{
switch ((--pdl)->kind)
{
case SPECPDL_LET_DEFAULT:
case SPECPDL_LET:
if (EQ (specpdl_symbol (pdl), symbol))
binding = pdl;
break;
}
}
return binding;
}
DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_value, 1, 1, 0,
doc: /* Return SYMBOL's toplevel default value.
"Toplevel" means outside of any let binding. */)
(Lisp_Object symbol)
{
union specbinding *binding = default_toplevel_binding (symbol);
Lisp_Object value
= binding ? specpdl_old_value (binding) : Fdefault_value (symbol);
if (!EQ (value, Qunbound))
return value;
xsignal1 (Qvoid_variable, symbol);
}
DEFUN ("set-default-toplevel-value", Fset_default_toplevel_value,
Sset_default_toplevel_value, 2, 2, 0,
doc: /* Set SYMBOL's toplevel default value to VALUE.
"Toplevel" means outside of any let binding. */)
(Lisp_Object symbol, Lisp_Object value)
{
union specbinding *binding = default_toplevel_binding (symbol);
if (binding)
set_specpdl_old_value (binding, value);
else
Fset_default (symbol, value);
return Qnil;
}
DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
doc: /* Define SYMBOL as a variable, and return SYMBOL.
@ -706,18 +751,10 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
else
{ /* Check if there is really a global binding rather than just a let
binding that shadows the global unboundness of the var. */
union specbinding *pdl = specpdl_ptr;
while (pdl > specpdl)
union specbinding *binding = default_toplevel_binding (sym);
if (binding && EQ (specpdl_old_value (binding), Qunbound))
{
if ((--pdl)->kind >= SPECPDL_LET
&& EQ (specpdl_symbol (pdl), sym)
&& EQ (specpdl_old_value (pdl), Qunbound))
{
message_with_string
("Warning: defvar ignored because %s is let-bound",
SYMBOL_NAME (sym), 1);
break;
}
set_specpdl_old_value (binding, eval_sub (XCAR (tail)));
}
}
tail = XCDR (tail);
@ -3311,19 +3348,21 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
case SPECPDL_BACKTRACE:
break;
case SPECPDL_LET:
/* If variable has a trivial value (no forwarding), we can
just set it. No need to check for constant symbols here,
since that was already done by specbind. */
if (XSYMBOL (specpdl_symbol (specpdl_ptr))->redirect
== SYMBOL_PLAINVAL)
SET_SYMBOL_VAL (XSYMBOL (specpdl_symbol (specpdl_ptr)),
specpdl_old_value (specpdl_ptr));
else
/* NOTE: we only ever come here if make_local_foo was used for
the first time on this var within this let. */
Fset_default (specpdl_symbol (specpdl_ptr),
specpdl_old_value (specpdl_ptr));
break;
{ /* If variable has a trivial value (no forwarding), we can
just set it. No need to check for constant symbols here,
since that was already done by specbind. */
struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (specpdl_ptr));
if (sym->redirect == SYMBOL_PLAINVAL)
{
SET_SYMBOL_VAL (sym, specpdl_old_value (specpdl_ptr));
break;
}
else
{ /* FALLTHROUGH!!
NOTE: we only ever come here if make_local_foo was used for
the first time on this var within this let. */
}
}
case SPECPDL_LET_DEFAULT:
Fset_default (specpdl_symbol (specpdl_ptr),
specpdl_old_value (specpdl_ptr));
@ -3511,24 +3550,23 @@ backtrace_eval_unrewind (int distance)
case SPECPDL_BACKTRACE:
break;
case SPECPDL_LET:
/* If variable has a trivial value (no forwarding), we can
just set it. No need to check for constant symbols here,
since that was already done by specbind. */
if (XSYMBOL (specpdl_symbol (tmp))->redirect
== SYMBOL_PLAINVAL)
{
struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp));
Lisp_Object old_value = specpdl_old_value (tmp);
set_specpdl_old_value (tmp, SYMBOL_VAL (sym));
SET_SYMBOL_VAL (sym, old_value);
break;
}
else
{
/* FALLTHROUGH!
NOTE: we only ever come here if make_local_foo was used for
the first time on this var within this let. */
}
{ /* If variable has a trivial value (no forwarding), we can
just set it. No need to check for constant symbols here,
since that was already done by specbind. */
struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp));
if (sym->redirect == SYMBOL_PLAINVAL)
{
Lisp_Object old_value = specpdl_old_value (tmp);
set_specpdl_old_value (tmp, SYMBOL_VAL (sym));
SET_SYMBOL_VAL (sym, old_value);
break;
}
else
{ /* FALLTHROUGH!!
NOTE: we only ever come here if make_local_foo was used for
the first time on this var within this let. */
}
}
case SPECPDL_LET_DEFAULT:
{
Lisp_Object sym = specpdl_symbol (tmp);
@ -3796,6 +3834,8 @@ alist of active lexical bindings. */);
defsubr (&Ssetq);
defsubr (&Squote);
defsubr (&Sfunction);
defsubr (&Sdefault_toplevel_value);
defsubr (&Sset_default_toplevel_value);
defsubr (&Sdefvar);
defsubr (&Sdefvaralias);
defsubr (&Sdefconst);

View file

@ -5096,8 +5096,6 @@ This calls `write-region-annotate-functions' at the start, and
return Qnil;
}
Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
doc: /* Return t if (car A) is numerically less than (car B). */)
(Lisp_Object a, Lisp_Object b)

View file

@ -1738,8 +1738,6 @@ See also the function `nreverse', which is used more often. */)
return new;
}
Lisp_Object merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred);
DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
doc: /* Sort LIST, stably, comparing elements using PREDICATE.
Returns the sorted list. LIST is modified by side effects.

View file

@ -204,9 +204,9 @@ font_make_object (int size, Lisp_Object entity, int pixelsize)
static int font_pixel_size (FRAME_PTR f, Lisp_Object);
static Lisp_Object font_open_entity (FRAME_PTR, Lisp_Object, int);
static Lisp_Object font_matching_entity (FRAME_PTR, Lisp_Object *,
static int font_pixel_size (struct frame *f, Lisp_Object);
static Lisp_Object font_open_entity (struct frame *, Lisp_Object, int);
static Lisp_Object font_matching_entity (struct frame *, Lisp_Object *,
Lisp_Object);
static unsigned font_encode_char (Lisp_Object, int);
@ -269,7 +269,7 @@ font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
/* Return a pixel size of font-spec SPEC on frame F. */
static int
font_pixel_size (FRAME_PTR f, Lisp_Object spec)
font_pixel_size (struct frame *f, Lisp_Object spec)
{
#ifdef HAVE_WINDOW_SYSTEM
Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
@ -2037,11 +2037,6 @@ font_otf_Anchor (OTF_Anchor *anchor)
/* Font sorting. */
static unsigned font_score (Lisp_Object, Lisp_Object *);
static int font_compare (const void *, const void *);
static Lisp_Object font_sort_entities (Lisp_Object, Lisp_Object,
Lisp_Object, int);
static double
font_rescale_ratio (Lisp_Object font_entity)
{
@ -2186,14 +2181,14 @@ font_compare (const void *d1, const void *d2)
such a case. */
static Lisp_Object
font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int best_only)
font_sort_entities (Lisp_Object list, Lisp_Object prefer,
struct frame *f, int best_only)
{
Lisp_Object prefer_prop[FONT_SPEC_MAX];
int len, maxlen, i;
struct font_sort_data *data;
unsigned best_score;
Lisp_Object best_entity;
struct frame *f = XFRAME (frame);
Lisp_Object tail, vec IF_LINT (= Qnil);
USE_SAFE_ALLOCA;
@ -2201,7 +2196,7 @@ font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int
prefer_prop[i] = AREF (prefer, i);
if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
prefer_prop[FONT_SIZE_INDEX]
= make_number (font_pixel_size (XFRAME (frame), prefer));
= make_number (font_pixel_size (f, prefer));
if (NILP (XCDR (list)))
{
@ -2502,14 +2497,14 @@ font_match_p (Lisp_Object spec, Lisp_Object font)
is a number frames sharing this cache, and FONT-CACHE-DATA is a
cons (FONT-SPEC FONT-ENTITY ...). */
static void font_prepare_cache (FRAME_PTR, struct font_driver *);
static void font_finish_cache (FRAME_PTR, struct font_driver *);
static Lisp_Object font_get_cache (FRAME_PTR, struct font_driver *);
static void font_clear_cache (FRAME_PTR, Lisp_Object,
static void font_prepare_cache (struct frame *, struct font_driver *);
static void font_finish_cache (struct frame *, struct font_driver *);
static Lisp_Object font_get_cache (struct frame *, struct font_driver *);
static void font_clear_cache (struct frame *, Lisp_Object,
struct font_driver *);
static void
font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
font_prepare_cache (struct frame *f, struct font_driver *driver)
{
Lisp_Object cache, val;
@ -2531,7 +2526,7 @@ font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
static void
font_finish_cache (FRAME_PTR f, struct font_driver *driver)
font_finish_cache (struct frame *f, struct font_driver *driver)
{
Lisp_Object cache, val, tmp;
@ -2552,7 +2547,7 @@ font_finish_cache (FRAME_PTR f, struct font_driver *driver)
static Lisp_Object
font_get_cache (FRAME_PTR f, struct font_driver *driver)
font_get_cache (struct frame *f, struct font_driver *driver)
{
Lisp_Object val = driver->get_cache (f);
Lisp_Object type = driver->type;
@ -2567,7 +2562,7 @@ font_get_cache (FRAME_PTR f, struct font_driver *driver)
static void
font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver)
font_clear_cache (struct frame *f, Lisp_Object cache, struct font_driver *driver)
{
Lisp_Object tail, elt;
Lisp_Object tail2, entity;
@ -2692,9 +2687,8 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
same font-driver. */
Lisp_Object
font_list_entities (Lisp_Object frame, Lisp_Object spec)
font_list_entities (struct frame *f, Lisp_Object spec)
{
FRAME_PTR f = XFRAME (frame);
struct font_driver_list *driver_list = f->font_driver_list;
Lisp_Object ftype, val;
Lisp_Object list = Qnil;
@ -2738,7 +2732,7 @@ font_list_entities (Lisp_Object frame, Lisp_Object spec)
{
Lisp_Object copy;
val = driver_list->driver->list (frame, scratch_font_spec);
val = driver_list->driver->list (f, scratch_font_spec);
if (NILP (val))
val = zero_vector;
else
@ -2766,14 +2760,12 @@ font_list_entities (Lisp_Object frame, Lisp_Object spec)
font-related attributes. */
static Lisp_Object
font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
font_matching_entity (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
{
struct font_driver_list *driver_list = f->font_driver_list;
Lisp_Object ftype, size, entity;
Lisp_Object frame;
Lisp_Object work = copy_font_spec (spec);
XSETFRAME (frame, f);
ftype = AREF (spec, FONT_TYPE_INDEX);
size = AREF (spec, FONT_SIZE_INDEX);
@ -2797,7 +2789,7 @@ font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
entity = XCDR (entity);
else
{
entity = driver_list->driver->match (frame, work);
entity = driver_list->driver->match (f, work);
copy = copy_font_spec (work);
ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
@ -2814,7 +2806,7 @@ font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
opened font object. */
static Lisp_Object
font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
font_open_entity (struct frame *f, Lisp_Object entity, int pixel_size)
{
struct font_driver_list *driver_list;
Lisp_Object objlist, size, val, font_object;
@ -2892,7 +2884,7 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
/* Close FONT_OBJECT that is opened on frame F. */
static void
font_close_object (FRAME_PTR f, Lisp_Object font_object)
font_close_object (struct frame *f, Lisp_Object font_object)
{
struct font *font = XFONT_OBJECT (font_object);
@ -2912,7 +2904,7 @@ font_close_object (FRAME_PTR f, Lisp_Object font_object)
FONT is a font-entity and it must be opened to check. */
int
font_has_char (FRAME_PTR f, Lisp_Object font, int c)
font_has_char (struct frame *f, Lisp_Object font, int c)
{
struct font *fontp;
@ -3039,12 +3031,12 @@ font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
supports C and is the best match for ATTRS and PIXEL_SIZE. */
static Lisp_Object
font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs, int pixel_size, int c)
font_select_entity (struct frame *f, Lisp_Object entities,
Lisp_Object *attrs, int pixel_size, int c)
{
Lisp_Object font_entity;
Lisp_Object prefer;
int i;
FRAME_PTR f = XFRAME (frame);
if (NILP (XCDR (entities))
&& ASIZE (XCAR (entities)) == 1)
@ -3075,7 +3067,7 @@ font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs,
FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
return font_sort_entities (entities, prefer, frame, c);
return font_sort_entities (entities, prefer, f, c);
}
/* Return a font-entity that satisfies SPEC and is the best match for
@ -3083,10 +3075,10 @@ font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs,
character that the entity must support. */
Lisp_Object
font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int c)
{
Lisp_Object work;
Lisp_Object frame, entities, val;
Lisp_Object entities, val;
Lisp_Object foundry[3], *family, registry[3], adstyle[3];
int pixel_size;
int i, j, k, l;
@ -3118,7 +3110,6 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
work = copy_font_spec (spec);
ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
XSETFRAME (frame, f);
pixel_size = font_pixel_size (f, spec);
if (pixel_size == 0 && INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
{
@ -3212,10 +3203,10 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
for (l = 0; SYMBOLP (adstyle[l]); l++)
{
ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
entities = font_list_entities (frame, work);
entities = font_list_entities (f, work);
if (! NILP (entities))
{
val = font_select_entity (frame, entities,
val = font_select_entity (f, entities,
attrs, pixel_size, c);
if (! NILP (val))
return val;
@ -3231,7 +3222,7 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
Lisp_Object
font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
font_open_for_lface (struct frame *f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
{
int size;
@ -3278,7 +3269,7 @@ font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_O
font-object. */
Lisp_Object
font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
font_load_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
{
Lisp_Object entity, name;
@ -3307,7 +3298,7 @@ font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
/* Make FACE on frame F ready to use the font opened for FACE. */
void
font_prepare_for_face (FRAME_PTR f, struct face *face)
font_prepare_for_face (struct frame *f, struct face *face)
{
if (face->font->driver->prepare_face)
face->font->driver->prepare_face (f, face);
@ -3317,7 +3308,7 @@ font_prepare_for_face (FRAME_PTR f, struct face *face)
/* Make FACE on frame F stop using the font opened for FACE. */
void
font_done_for_face (FRAME_PTR f, struct face *face)
font_done_for_face (struct frame *f, struct face *face)
{
if (face->font->driver->done_face)
face->font->driver->done_face (f, face);
@ -3329,7 +3320,7 @@ font_done_for_face (FRAME_PTR f, struct face *face)
font is found, return Qnil. */
Lisp_Object
font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
font_open_by_spec (struct frame *f, Lisp_Object spec)
{
Lisp_Object attrs[LFACE_VECTOR_SIZE];
@ -3353,7 +3344,7 @@ font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
found, return Qnil. */
Lisp_Object
font_open_by_name (FRAME_PTR f, Lisp_Object name)
font_open_by_name (struct frame *f, Lisp_Object name)
{
Lisp_Object args[2];
Lisp_Object spec, ret;
@ -3383,7 +3374,7 @@ font_open_by_name (FRAME_PTR f, Lisp_Object name)
(e.g. syms_of_xfont). */
void
register_font_driver (struct font_driver *driver, FRAME_PTR f)
register_font_driver (struct font_driver *driver, struct frame *f)
{
struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
struct font_driver_list *prev, *list;
@ -3411,7 +3402,7 @@ register_font_driver (struct font_driver *driver, FRAME_PTR f)
}
void
free_font_driver_list (FRAME_PTR f)
free_font_driver_list (struct frame *f)
{
struct font_driver_list *list, *next;
@ -3433,7 +3424,7 @@ free_font_driver_list (FRAME_PTR f)
F. */
Lisp_Object
font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
font_update_drivers (struct frame *f, Lisp_Object new_drivers)
{
Lisp_Object active_drivers = Qnil;
struct font_driver_list *list;
@ -3522,7 +3513,7 @@ font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
}
int
font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
font_put_frame_data (struct frame *f, struct font_driver *driver, void *data)
{
struct font_data_list *list, *prev;
@ -3556,7 +3547,7 @@ font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
void *
font_get_frame_data (FRAME_PTR f, struct font_driver *driver)
font_get_frame_data (struct frame *f, struct font_driver *driver)
{
struct font_data_list *list;
@ -3630,7 +3621,7 @@ static Lisp_Object
font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
Lisp_Object string)
{
FRAME_PTR f;
struct frame *f;
bool multibyte;
Lisp_Object font_object;
@ -4110,12 +4101,10 @@ control the order of the returned list. Fonts are sorted by
how close they are to PREFER. */)
(Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
{
struct frame *f = decode_live_frame (frame);
Lisp_Object vec, list;
EMACS_INT n = 0;
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
CHECK_FONT_SPEC (font_spec);
if (! NILP (num))
{
@ -4127,7 +4116,7 @@ how close they are to PREFER. */)
if (! NILP (prefer))
CHECK_FONT_SPEC (prefer);
list = font_list_entities (frame, font_spec);
list = font_list_entities (f, font_spec);
if (NILP (list))
return Qnil;
if (NILP (XCDR (list))
@ -4135,7 +4124,7 @@ how close they are to PREFER. */)
return list1 (AREF (XCAR (list), 0));
if (! NILP (prefer))
vec = font_sort_entities (list, prefer, frame, 0);
vec = font_sort_entities (list, prefer, f, 0);
else
vec = font_vconcat_entity_vectors (list);
if (n == 0 || n >= ASIZE (vec))
@ -4163,13 +4152,11 @@ If FRAME is omitted or nil, the selected frame is used. */)
struct font_driver_list *driver_list;
Lisp_Object list = Qnil;
XSETFRAME (frame, f);
for (driver_list = f->font_driver_list; driver_list;
driver_list = driver_list->next)
if (driver_list->driver->list_family)
{
Lisp_Object val = driver_list->driver->list_family (frame);
Lisp_Object val = driver_list->driver->list_family (f);
Lisp_Object tail = list;
for (; CONSP (val); val = XCDR (val))
@ -4247,7 +4234,7 @@ DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
FOR_EACH_FRAME (list, frame)
{
FRAME_PTR f = XFRAME (frame);
struct frame *f = XFRAME (frame);
struct font_driver_list *driver_list = f->font_driver_list;
for (; driver_list; driver_list = driver_list->next)
@ -4795,7 +4782,7 @@ Type C-l to recover what previously shown. */)
(Lisp_Object font_object, Lisp_Object string)
{
Lisp_Object frame = selected_frame;
FRAME_PTR f = XFRAME (frame);
struct frame *f = XFRAME (frame);
struct font *font;
struct face *face;
int i, len, width;

View file

@ -504,7 +504,7 @@ struct font_driver
/* Return a cache of font-entities on frame F. The cache must be a
cons whose cdr part is the actual cache area. */
Lisp_Object (*get_cache) (FRAME_PTR F);
Lisp_Object (*get_cache) (struct frame *f);
/* List fonts exactly matching with FONT_SPEC on FRAME. The value
is a list of font-entities. The font properties to be considered
@ -527,7 +527,7 @@ struct font_driver
This and the following `match' are the only APIs that allocate
font-entities. */
Lisp_Object (*list) (Lisp_Object frame, Lisp_Object font_spec);
Lisp_Object (*list) (struct frame *frame, Lisp_Object font_spec);
/* Return a font-entity most closely matching with FONT_SPEC on
FRAME. Which font property to consider, and how to calculate the
@ -536,12 +536,12 @@ struct font_driver
The properties that the font-entity has is the same as `list'
method. */
Lisp_Object (*match) (Lisp_Object frame, Lisp_Object font_spec);
Lisp_Object (*match) (struct frame *f, Lisp_Object spec);
/* Optional.
List available families. The value is a list of family names
(symbols). */
Lisp_Object (*list_family) (Lisp_Object frame);
Lisp_Object (*list_family) (struct frame *f);
/* Optional (if FONT_EXTRA_INDEX is not Lisp_Save_Value).
Free FONT_EXTRA_INDEX field of FONT_ENTITY. */
@ -549,21 +549,21 @@ struct font_driver
/* Open a font specified by FONT_ENTITY on frame F. If the font is
scalable, open it with PIXEL_SIZE. */
Lisp_Object (*open) (FRAME_PTR f, Lisp_Object font_entity,
Lisp_Object (*open) (struct frame *f, Lisp_Object font_entity,
int pixel_size);
/* Close FONT on frame F. */
void (*close) (FRAME_PTR f, struct font *font);
void (*close) (struct frame *f, struct font *font);
/* Optional (if FACE->extra is not used).
Prepare FACE for displaying characters by FONT on frame F by
storing some data in FACE->extra. If successful, return 0.
Otherwise, return -1. */
int (*prepare_face) (FRAME_PTR f, struct face *face);
int (*prepare_face) (struct frame *f, struct face *face);
/* Optional.
Done FACE for displaying characters by FACE->font on frame F. */
void (*done_face) (FRAME_PTR f, struct face *face);
void (*done_face) (struct frame *f, struct face *face);
/* Optional.
If FONT (FONT-ENTITY or FONT-OBJECT) has a glyph for character C
@ -646,12 +646,12 @@ struct font_driver
Make the font driver ready for frame F. Usually this function
makes some data specific to F and stores it in F by calling
font_put_frame_data (). */
int (*start_for_frame) (FRAME_PTR f);
int (*start_for_frame) (struct frame *f);
/* Optional.
End using the driver for frame F. Usually this function free
some data stored for F. */
int (*end_for_frame) (FRAME_PTR f);
int (*end_for_frame) (struct frame *f);
/* Optional.
@ -674,7 +674,7 @@ struct font_driver
If FONT is usable on frame F, return 0. Otherwise return -1.
This method is used only for debugging. If this method is NULL,
Emacs assumes that the font is usable on any frame. */
int (*check) (FRAME_PTR F, struct font *font);
int (*check) (struct frame *f, struct font *font);
/* Optional.
@ -698,8 +698,8 @@ struct font_driver
/* Chain of font drivers. There's one global font driver list
(font_driver_list in font.c). In addition, each frame has its own
font driver list at FRAME_PTR->font_driver_list. */
(font_driver_list in font.c). In addition, each frame has
its own font driver list at F->font_driver_list. */
struct font_driver_list
{
@ -713,8 +713,8 @@ struct font_driver_list
};
/* Chain of arbitrary data specific to each font driver. Each frame
has its own font data list at FRAME_PTR->font_data_list. */
/* Chain of arbitrary data specific to each font driver.
Each frame has its own font data list at F->font_data_list. */
struct font_data_list
{
@ -742,28 +742,27 @@ extern Lisp_Object font_style_symbolic (Lisp_Object font,
bool for_face);
extern bool font_match_p (Lisp_Object spec, Lisp_Object font);
extern Lisp_Object font_list_entities (Lisp_Object frame,
Lisp_Object spec);
extern Lisp_Object font_list_entities (struct frame *, Lisp_Object);
extern Lisp_Object font_get_name (Lisp_Object font_object);
extern Lisp_Object font_spec_from_name (Lisp_Object font_name);
extern Lisp_Object font_get_frame (Lisp_Object font_object);
extern int font_has_char (FRAME_PTR, Lisp_Object, int);
extern int font_has_char (struct frame *, Lisp_Object, int);
extern void font_clear_prop (Lisp_Object *attrs,
enum font_property_index prop);
extern Lisp_Object font_find_for_lface (FRAME_PTR f, Lisp_Object *lface,
extern Lisp_Object font_find_for_lface (struct frame *f, Lisp_Object *lface,
Lisp_Object spec, int c);
extern Lisp_Object font_open_for_lface (FRAME_PTR f, Lisp_Object entity,
extern Lisp_Object font_open_for_lface (struct frame *f, Lisp_Object entity,
Lisp_Object *lface,
Lisp_Object spec);
extern Lisp_Object font_load_for_lface (FRAME_PTR f, Lisp_Object *lface,
extern Lisp_Object font_load_for_lface (struct frame *f, Lisp_Object *lface,
Lisp_Object spec);
extern void font_prepare_for_face (FRAME_PTR f, struct face *face);
extern void font_done_for_face (FRAME_PTR f, struct face *face);
extern void font_prepare_for_face (struct frame *f, struct face *face);
extern void font_done_for_face (struct frame *f, struct face *face);
extern Lisp_Object font_open_by_spec (FRAME_PTR f, Lisp_Object spec);
extern Lisp_Object font_open_by_name (FRAME_PTR f, Lisp_Object name);
extern Lisp_Object font_open_by_spec (struct frame *f, Lisp_Object spec);
extern Lisp_Object font_open_by_name (struct frame *f, Lisp_Object name);
extern Lisp_Object font_intern_prop (const char *str, ptrdiff_t len,
bool force_symbol);
@ -778,9 +777,9 @@ extern ptrdiff_t font_unparse_xlfd (Lisp_Object font, int pixel_size,
char *name, int bytes);
extern int font_unparse_fcname (Lisp_Object font, int pixel_size,
char *name, int bytes);
extern void register_font_driver (struct font_driver *driver, FRAME_PTR f);
extern void free_font_driver_list (FRAME_PTR f);
extern Lisp_Object font_update_drivers (FRAME_PTR f, Lisp_Object list);
extern void register_font_driver (struct font_driver *driver, struct frame *f);
extern void free_font_driver_list (struct frame *f);
extern Lisp_Object font_update_drivers (struct frame *f, Lisp_Object list);
extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *,
struct window *, struct face *,
Lisp_Object);
@ -789,10 +788,10 @@ extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object);
extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,
Lisp_Object val);
extern int font_put_frame_data (FRAME_PTR f,
extern int font_put_frame_data (struct frame *f,
struct font_driver *driver,
void *data);
extern void *font_get_frame_data (FRAME_PTR f,
extern void *font_get_frame_data (struct frame *f,
struct font_driver *driver);
extern void font_filter_properties (Lisp_Object font,

View file

@ -539,8 +539,9 @@ fontset_find_font (Lisp_Object fontset, int c, struct face *face, int id,
{
Lisp_Object vec, font_group;
int i, charset_matched = 0, found_index;
FRAME_PTR f = (FRAMEP (FONTSET_FRAME (fontset))
? XFRAME (FONTSET_FRAME (fontset)) : XFRAME (selected_frame));
struct frame *f = (FRAMEP (FONTSET_FRAME (fontset))
? XFRAME (FONTSET_FRAME (fontset))
: XFRAME (selected_frame));
Lisp_Object rfont_def;
font_group = fontset_get_font_group (fontset, fallback ? -1 : c);
@ -859,7 +860,7 @@ fontset_ascii (int id)
}
static void
free_realized_fontset (FRAME_PTR f, Lisp_Object fontset)
free_realized_fontset (struct frame *f, Lisp_Object fontset)
{
#if 0
Lisp_Object tail;
@ -877,7 +878,7 @@ free_realized_fontset (FRAME_PTR f, Lisp_Object fontset)
free_realized_face. */
void
free_face_fontset (FRAME_PTR f, struct face *face)
free_face_fontset (struct frame *f, struct face *face)
{
Lisp_Object fontset;
@ -930,7 +931,7 @@ face_suitable_for_char_p (struct face *face, int c)
the macro FACE_FOR_CHAR. */
int
face_for_char (FRAME_PTR f, struct face *face, int c, int pos, Lisp_Object object)
face_for_char (struct frame *f, struct face *face, int c, int pos, Lisp_Object object)
{
Lisp_Object fontset, rfont_def, charset;
int face_id;
@ -1048,7 +1049,7 @@ font_for_char (struct face *face, int c, int pos, Lisp_Object object)
Called from realize_x_face. */
int
make_fontset_for_ascii_face (FRAME_PTR f, int base_fontset_id, struct face *face)
make_fontset_for_ascii_face (struct frame *f, int base_fontset_id, struct face *face)
{
Lisp_Object base_fontset, fontset, frame;
@ -1227,7 +1228,7 @@ If REGEXPP is non-nil, PATTERN is a regular expression. */)
/* Return a list of base fontset names matching PATTERN on frame F. */
Lisp_Object
list_fontsets (FRAME_PTR f, Lisp_Object pattern, int size)
list_fontsets (struct frame *f, Lisp_Object pattern, int size)
{
Lisp_Object frame, regexp, val;
int id;
@ -1284,7 +1285,7 @@ free_realized_fontsets (Lisp_Object base)
for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
tail = XCDR (tail))
{
FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
struct frame *f = XFRAME (FONTSET_FRAME (this));
int face_id = XINT (XCDR (XCAR (tail)));
struct face *face = FACE_FROM_ID (f, face_id);
@ -1612,7 +1613,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
name = FONTSET_NAME (fontset);
FOR_EACH_FRAME (tail, fr)
{
FRAME_PTR f = XFRAME (fr);
struct frame *f = XFRAME (fr);
Lisp_Object font_object;
struct face *face;
@ -2140,7 +2141,7 @@ dump_fontset (Lisp_Object fontset)
frame = FONTSET_FRAME (fontset);
if (FRAMEP (frame))
{
FRAME_PTR f = XFRAME (frame);
struct frame *f = XFRAME (frame);
if (FRAME_LIVE_P (f))
ASET (vec, 1,

View file

@ -28,12 +28,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
struct face;
extern void free_face_fontset (FRAME_PTR, struct face *);
extern int face_for_char (FRAME_PTR, struct face *, int,
extern void free_face_fontset (struct frame *, struct face *);
extern int face_for_char (struct frame *, struct face *, int,
int, Lisp_Object);
extern Lisp_Object font_for_char (struct face *, int, int, Lisp_Object);
extern int make_fontset_for_ascii_face (FRAME_PTR, int, struct face *);
extern int make_fontset_for_ascii_face (struct frame *, int, struct face *);
extern int fontset_from_font (Lisp_Object);
extern int fs_query_fontset (Lisp_Object, int);
extern Lisp_Object list_fontsets (struct frame *, Lisp_Object, int);

View file

@ -69,7 +69,6 @@ Lisp_Object Qnoelisp;
static Lisp_Object Qx_frame_parameter;
Lisp_Object Qx_resource_name;
Lisp_Object Qterminal;
Lisp_Object Qterminal_live_p;
/* Frame parameters (set or reported). */
@ -310,7 +309,7 @@ predicates which report frame's specific UI-related capabilities. */)
}
struct frame *
make_frame (int mini_p)
make_frame (bool mini_p)
{
Lisp_Object frame;
register struct frame *f;
@ -725,16 +724,13 @@ affects all frames on the same terminal device. */)
adjust_glyphs (f);
calculate_costs (f);
XSETFRAME (frame, f);
store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
store_in_alist (&parms, Qtty,
(t->display_info.tty->name
? build_string (t->display_info.tty->name)
: Qnil));
Fmodify_frame_parameters (frame, parms);
Fmodify_frame_parameters
(frame, list1 (Fcons (Qtty_type,
build_string (t->display_info.tty->type))));
if (t->display_info.tty->name != NULL)
Fmodify_frame_parameters
(frame, list1 (Fcons (Qtty,
build_string (t->display_info.tty->name))));
else
Fmodify_frame_parameters (frame, list1 (Fcons (Qtty, Qnil)));
/* Make the frame face alist be frame-specific, so that each
frame could change its face definitions independently. */
@ -1097,7 +1093,7 @@ Otherwise, include all frames. */)
(Exception: if F is the terminal frame, and we are using X, return 1.) */
static int
other_visible_frames (FRAME_PTR f)
other_visible_frames (struct frame *f)
{
Lisp_Object frames, this;
@ -1471,7 +1467,7 @@ passing the normal return value to that function as an argument,
and returns whatever that function returns. */)
(void)
{
FRAME_PTR f;
struct frame *f;
Lisp_Object lispy_dummy;
Lisp_Object x, y, retval;
struct gcpro gcpro1;
@ -1517,7 +1513,7 @@ to read the mouse position, it returns the selected frame for FRAME
and nil for X and Y. */)
(void)
{
FRAME_PTR f;
struct frame *f;
Lisp_Object lispy_dummy;
Lisp_Object x, y;
@ -2365,7 +2361,7 @@ to `frame-height'). */)
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
return make_number (x_pixel_height (f));
return make_number (FRAME_PIXEL_HEIGHT (f));
else
#endif
return make_number (FRAME_LINES (f));
@ -2382,7 +2378,7 @@ If FRAME is omitted or nil, the selected frame is used. */)
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
return make_number (x_pixel_width (f));
return make_number (FRAME_PIXEL_WIDTH (f));
else
#endif
return make_number (FRAME_COLS (f));
@ -2407,8 +2403,9 @@ is used. */)
DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
doc: /* Specify that the frame FRAME has LINES lines.
Optional third arg non-nil means that redisplay should use LINES lines
but that the idea of the actual height of the frame should not be changed. */)
If FRAME is nil, the selected frame is used. Optional third arg
non-nil means that redisplay should use LINES lines but that the
idea of the actual height of the frame should not be changed. */)
(Lisp_Object frame, Lisp_Object lines, Lisp_Object pretend)
{
register struct frame *f = decode_live_frame (frame);
@ -2431,8 +2428,9 @@ but that the idea of the actual height of the frame should not be changed. */)
DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
doc: /* Specify that the frame FRAME has COLS columns.
Optional third arg non-nil means that redisplay should use COLS columns
but that the idea of the actual width of the frame should not be changed. */)
If FRAME is nil, the selected frame is used. Optional third arg
non-nil means that redisplay should use COLS columns but that the
idea of the actual width of the frame should not be changed. */)
(Lisp_Object frame, Lisp_Object cols, Lisp_Object pretend)
{
register struct frame *f = decode_live_frame (frame);
@ -2454,15 +2452,14 @@ but that the idea of the actual width of the frame should not be changed. */)
}
DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
doc: /* Sets size of FRAME to COLS by ROWS, measured in characters. */)
doc: /* Sets size of FRAME to COLS by ROWS, measured in characters.
If FRAME is nil, the selected frame is used. */)
(Lisp_Object frame, Lisp_Object cols, Lisp_Object rows)
{
register struct frame *f;
register struct frame *f = decode_live_frame (frame);
CHECK_LIVE_FRAME (frame);
CHECK_TYPE_RANGED_INTEGER (int, cols);
CHECK_TYPE_RANGED_INTEGER (int, rows);
f = XFRAME (frame);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
@ -2484,17 +2481,16 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
DEFUN ("set-frame-position", Fset_frame_position,
Sset_frame_position, 3, 3, 0,
doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
This is actually the position of the upper left corner of the frame.
Negative values for XOFFSET or YOFFSET are interpreted relative to
the rightmost or bottommost possible position (that stays within the screen). */)
If FRAME is nil, the selected frame is used. XOFFSET and YOFFSET are
actually the position of the upper left corner of the frame. Negative
values for XOFFSET or YOFFSET are interpreted relative to the rightmost
or bottommost possible position (that stays within the screen). */)
(Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
{
register struct frame *f;
register struct frame *f = decode_live_frame (frame);
CHECK_LIVE_FRAME (frame);
CHECK_TYPE_RANGED_INTEGER (int, xoffset);
CHECK_TYPE_RANGED_INTEGER (int, yoffset);
f = XFRAME (frame);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
@ -2614,7 +2610,7 @@ x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int
to store the new value in the parameter alist. */
void
x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
x_set_frame_parameters (struct frame *f, Lisp_Object alist)
{
Lisp_Object tail;
@ -2633,9 +2629,9 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
Lisp_Object *parms;
Lisp_Object *values;
ptrdiff_t i, p;
int left_no_change = 0, top_no_change = 0;
int icon_left_no_change = 0, icon_top_no_change = 0;
int size_changed = 0;
bool left_no_change = 0, top_no_change = 0;
bool icon_left_no_change = 0, icon_top_no_change = 0;
bool size_changed = 0;
struct gcpro gcpro1, gcpro2;
i = 0;
@ -2871,10 +2867,11 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
/* Actually set that position, and convert to absolute. */
x_set_offset (f, leftpos, toppos, -1);
}
#ifdef HAVE_X_WINDOWS
if ((!NILP (icon_left) || !NILP (icon_top))
&& ! (icon_left_no_change && icon_top_no_change))
x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
#endif /* HAVE_X_WINDOWS */
}
UNGCPRO;
@ -3351,7 +3348,7 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
/* Return non-nil if frame F wants a bitmap icon. */
Lisp_Object
x_icon_type (FRAME_PTR f)
x_icon_type (struct frame *f)
{
Lisp_Object tem;
@ -3939,8 +3936,8 @@ On Nextstep, this just calls `ns-parse-geometry'. */)
#define DEFAULT_ROWS 35
#define DEFAULT_COLS 80
int
x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p)
long
x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
{
register Lisp_Object tem0, tem1, tem2;
long window_prompting = 0;
@ -4291,7 +4288,6 @@ syms_of_frame (void)
DEFSYM (Qx_frame_parameter, "x-frame-parameter");
DEFSYM (Qterminal, "terminal");
DEFSYM (Qterminal_live_p, "terminal-live-p");
DEFSYM (Qgeometry, "geometry");
DEFSYM (Qworkarea, "workarea");

View file

@ -591,8 +591,6 @@ default_pixels_per_inch_y (void)
/* Return a pointer to the image cache of frame F. */
#define FRAME_IMAGE_CACHE(F) ((F)->terminal->image_cache)
typedef struct frame *FRAME_PTR;
#define XFRAME(p) \
(eassert (FRAMEP (p)), (struct frame *) XUNTAG (p, Lisp_Vectorlike))
#define XSETFRAME(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FRAME))
@ -929,10 +927,9 @@ typedef struct frame *FRAME_PTR;
if (frame == hlinfo->mouse_face_mouse_frame) \
{ \
block_input (); \
if (hlinfo->mouse_face_mouse_frame) \
note_mouse_highlight (hlinfo->mouse_face_mouse_frame, \
hlinfo->mouse_face_mouse_x, \
hlinfo->mouse_face_mouse_y); \
note_mouse_highlight (hlinfo->mouse_face_mouse_frame, \
hlinfo->mouse_face_mouse_x, \
hlinfo->mouse_face_mouse_y); \
unblock_input (); \
} \
} while (0)
@ -952,7 +949,7 @@ typedef struct frame *FRAME_PTR;
extern Lisp_Object Qframep, Qframe_live_p;
extern Lisp_Object Qtty, Qtty_type;
extern Lisp_Object Qtty_color_mode;
extern Lisp_Object Qterminal, Qterminal_live_p;
extern Lisp_Object Qterminal;
extern Lisp_Object Qnoelisp;
extern struct frame *last_nonminibuf_frame;
@ -962,7 +959,7 @@ extern struct frame *decode_window_system_frame (Lisp_Object);
extern struct frame *decode_live_frame (Lisp_Object);
extern struct frame *decode_any_frame (Lisp_Object);
extern struct frame *make_initial_frame (void);
extern struct frame *make_frame (int);
extern struct frame *make_frame (bool);
#ifdef HAVE_WINDOW_SYSTEM
extern struct frame *make_minibuffer_frame (void);
extern struct frame *make_frame_without_minibuffer (Lisp_Object,
@ -1207,8 +1204,7 @@ extern Lisp_Object Qrun_hook_with_args;
extern void x_set_scroll_bar_default_width (struct frame *);
extern void x_set_offset (struct frame *, int, int, int);
extern void x_wm_set_icon_position (struct frame *, int, int);
extern void x_wm_set_size_hint (FRAME_PTR f, long flags, bool user_position);
extern void x_wm_set_size_hint (struct frame *f, long flags, bool user_position);
extern Lisp_Object x_new_font (struct frame *, Lisp_Object, int);
@ -1242,7 +1238,7 @@ extern void x_set_scroll_bar_width (struct frame *, Lisp_Object,
extern Lisp_Object x_icon_type (struct frame *);
extern int x_figure_window_size (struct frame *, Lisp_Object, int);
extern long x_figure_window_size (struct frame *, Lisp_Object, bool);
extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object);
@ -1264,8 +1260,6 @@ extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
extern void x_make_frame_visible (struct frame *f);
extern void x_make_frame_invisible (struct frame *f);
extern void x_iconify_frame (struct frame *f);
extern int x_pixel_width (struct frame *f);
extern int x_pixel_height (struct frame *f);
extern void x_set_frame_alpha (struct frame *f);
extern void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_tool_bar_lines (struct frame *f,
@ -1280,9 +1274,12 @@ extern void x_set_menu_bar_lines (struct frame *,
extern void free_frame_menubar (struct frame *);
extern void x_free_frame_resources (struct frame *);
#if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT
#if defined HAVE_X_WINDOWS
extern void x_wm_set_icon_position (struct frame *, int, int);
#if !defined USE_X_TOOLKIT
extern char *x_get_resource_string (const char *, const char *);
#endif
#endif
extern void x_query_colors (struct frame *f, XColor *, int);
extern void x_query_color (struct frame *f, XColor *);

View file

@ -493,12 +493,12 @@ ftfont_get_otf (struct ftfont_info *ftfont_info)
}
#endif /* HAVE_LIBOTF */
static Lisp_Object ftfont_get_cache (FRAME_PTR);
static Lisp_Object ftfont_list (Lisp_Object, Lisp_Object);
static Lisp_Object ftfont_match (Lisp_Object, Lisp_Object);
static Lisp_Object ftfont_list_family (Lisp_Object);
static Lisp_Object ftfont_open (FRAME_PTR, Lisp_Object, int);
static void ftfont_close (FRAME_PTR, struct font *);
static Lisp_Object ftfont_get_cache (struct frame *);
static Lisp_Object ftfont_list (struct frame *, Lisp_Object);
static Lisp_Object ftfont_match (struct frame *, Lisp_Object);
static Lisp_Object ftfont_list_family (struct frame *);
static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
static void ftfont_close (struct frame *, struct font *);
static int ftfont_has_char (Lisp_Object, int);
static unsigned ftfont_encode_char (struct font *, int);
static int ftfont_text_extents (struct font *, unsigned *, int,
@ -568,7 +568,7 @@ struct font_driver ftfont_driver =
};
static Lisp_Object
ftfont_get_cache (FRAME_PTR f)
ftfont_get_cache (struct frame *f)
{
return freetype_font_cache;
}
@ -884,7 +884,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
}
static Lisp_Object
ftfont_list (Lisp_Object frame, Lisp_Object spec)
ftfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object val = Qnil, family, adstyle;
int i;
@ -1080,7 +1080,7 @@ ftfont_list (Lisp_Object frame, Lisp_Object spec)
}
static Lisp_Object
ftfont_match (Lisp_Object frame, Lisp_Object spec)
ftfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = Qnil;
FcPattern *pattern, *match = NULL;
@ -1130,7 +1130,7 @@ ftfont_match (Lisp_Object frame, Lisp_Object spec)
}
static Lisp_Object
ftfont_list_family (Lisp_Object frame)
ftfont_list_family (struct frame *f)
{
Lisp_Object list = Qnil;
FcPattern *pattern = NULL;
@ -1173,7 +1173,7 @@ ftfont_list_family (Lisp_Object frame)
static Lisp_Object
ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
struct ftfont_info *ftfont_info;
struct font *font;
@ -1317,7 +1317,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
}
static void
ftfont_close (FRAME_PTR f, struct font *font)
ftfont_close (struct frame *f, struct font *font)
{
struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
Lisp_Object val, cache;

View file

@ -57,7 +57,7 @@ struct ftxfont_frame_data
/* Return an array of 6 GCs for antialiasing. */
static GC *
ftxfont_get_gcs (FRAME_PTR f, long unsigned int foreground, long unsigned int background)
ftxfont_get_gcs (struct frame *f, long unsigned int foreground, long unsigned int background)
{
XColor color;
XGCValues xgcv;
@ -134,7 +134,7 @@ ftxfont_get_gcs (FRAME_PTR f, long unsigned int foreground, long unsigned int ba
}
static int
ftxfont_draw_bitmap (FRAME_PTR f, GC gc_fore, GC *gcs, struct font *font,
ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
unsigned int code, int x, int y, XPoint *p, int size,
int *n, bool flush)
{
@ -212,7 +212,7 @@ ftxfont_draw_bitmap (FRAME_PTR f, GC gc_fore, GC *gcs, struct font *font,
}
static void
ftxfont_draw_background (FRAME_PTR f, struct font *font, GC gc, int x, int y,
ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y,
int width)
{
XGCValues xgcv;
@ -226,9 +226,9 @@ ftxfont_draw_background (FRAME_PTR f, struct font *font, GC gc, int x, int y,
}
static Lisp_Object
ftxfont_list (Lisp_Object frame, Lisp_Object spec)
ftxfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object list = ftfont_driver.list (frame, spec), tail;
Lisp_Object list = ftfont_driver.list (f, spec), tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx);
@ -236,9 +236,9 @@ ftxfont_list (Lisp_Object frame, Lisp_Object spec)
}
static Lisp_Object
ftxfont_match (Lisp_Object frame, Lisp_Object spec)
ftxfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = ftfont_driver.match (frame, spec);
Lisp_Object entity = ftfont_driver.match (f, spec);
if (VECTORP (entity))
ASET (entity, FONT_TYPE_INDEX, Qftx);
@ -246,7 +246,7 @@ ftxfont_match (Lisp_Object frame, Lisp_Object spec)
}
static Lisp_Object
ftxfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
ftxfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
Lisp_Object font_object;
struct font *font;
@ -260,7 +260,7 @@ ftxfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
}
static void
ftxfont_close (FRAME_PTR f, struct font *font)
ftxfont_close (struct frame *f, struct font *font)
{
ftfont_driver.close (f, font);
}
@ -269,7 +269,7 @@ static int
ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
bool with_background)
{
FRAME_PTR f = s->f;
struct frame *f = s->f;
struct face *face = s->face;
struct font *font = s->font;
XPoint p[0x700];
@ -338,7 +338,7 @@ ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
}
static int
ftxfont_end_for_frame (FRAME_PTR f)
ftxfont_end_for_frame (struct frame *f)
{
struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver);

View file

@ -136,7 +136,7 @@ static GdkDisplay *gdpy_def;
W can be a GtkMenu or a GtkWindow widget. */
static void
xg_set_screen (GtkWidget *w, FRAME_PTR f)
xg_set_screen (GtkWidget *w, struct frame *f)
{
if (FRAME_X_DISPLAY (f) != DEFAULT_GDK_DISPLAY ())
{
@ -280,7 +280,7 @@ xg_create_default_cursor (Display *dpy)
}
static GdkPixbuf *
xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
xg_get_pixbuf_from_pixmap (struct frame *f, Pixmap pix)
{
int iunused;
GdkPixbuf *tmp_buf;
@ -311,7 +311,7 @@ xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
/* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */
static GdkPixbuf *
xg_get_pixbuf_from_pix_and_mask (FRAME_PTR f,
xg_get_pixbuf_from_pix_and_mask (struct frame *f,
Pixmap pix,
Pixmap mask)
{
@ -387,7 +387,7 @@ file_for_image (Lisp_Object image)
If OLD_WIDGET is not NULL, that widget is modified. */
static GtkWidget *
xg_get_image_for_pixmap (FRAME_PTR f,
xg_get_image_for_pixmap (struct frame *f,
struct image *img,
GtkWidget *widget,
GtkImage *old_widget)
@ -641,7 +641,7 @@ hierarchy_ch_cb (GtkWidget *widget,
GtkWidget *previous_toplevel,
gpointer user_data)
{
FRAME_PTR f = (FRAME_PTR) user_data;
struct frame *f = (struct frame *) user_data;
struct x_output *x = f->output_data.x;
GtkWidget *top = gtk_widget_get_toplevel (x->ttip_lbl);
@ -663,7 +663,7 @@ qttip_cb (GtkWidget *widget,
GtkTooltip *tooltip,
gpointer user_data)
{
FRAME_PTR f = (FRAME_PTR) user_data;
struct frame *f = (struct frame *) user_data;
struct x_output *x = f->output_data.x;
if (x->ttip_widget == NULL)
{
@ -707,7 +707,7 @@ qttip_cb (GtkWidget *widget,
Return true if a system tooltip is available. */
bool
xg_prepare_tooltip (FRAME_PTR f,
xg_prepare_tooltip (struct frame *f,
Lisp_Object string,
int *width,
int *height)
@ -764,7 +764,7 @@ xg_prepare_tooltip (FRAME_PTR f,
xg_prepare_tooltip must have been called before this function. */
void
xg_show_tooltip (FRAME_PTR f, int root_x, int root_y)
xg_show_tooltip (struct frame *f, int root_x, int root_y)
{
#ifdef USE_GTK_TOOLTIP
struct x_output *x = f->output_data.x;
@ -783,7 +783,7 @@ xg_show_tooltip (FRAME_PTR f, int root_x, int root_y)
system tooltips). */
bool
xg_hide_tooltip (FRAME_PTR f)
xg_hide_tooltip (struct frame *f)
{
bool ret = 0;
#ifdef USE_GTK_TOOLTIP
@ -827,7 +827,7 @@ my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
F is the frame we shall set geometry for. */
static void
xg_set_geometry (FRAME_PTR f)
xg_set_geometry (struct frame *f)
{
if (f->size_hint_flags & (USPosition | PPosition))
{
@ -865,7 +865,7 @@ xg_set_geometry (FRAME_PTR f)
and use a GtkFixed widget, this doesn't happen automatically. */
static void
xg_clear_under_internal_border (FRAME_PTR f)
xg_clear_under_internal_border (struct frame *f)
{
if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
{
@ -903,7 +903,7 @@ xg_clear_under_internal_border (FRAME_PTR f)
PIXELWIDTH, PIXELHEIGHT is the new size in pixels. */
void
xg_frame_resized (FRAME_PTR f, int pixelwidth, int pixelheight)
xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
{
int rows, columns;
@ -939,7 +939,7 @@ xg_frame_resized (FRAME_PTR f, int pixelwidth, int pixelheight)
COLUMNS/ROWS is the size the edit area shall have after the resize. */
void
xg_frame_set_char_size (FRAME_PTR f, int cols, int rows)
xg_frame_set_char_size (struct frame *f, int cols, int rows)
{
int pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
+ FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
@ -1002,7 +1002,7 @@ xg_frame_set_char_size (FRAME_PTR f, int cols, int rows)
The policy is to keep the number of editable lines. */
static void
xg_height_or_width_changed (FRAME_PTR f)
xg_height_or_width_changed (struct frame *f)
{
gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
FRAME_TOTAL_PIXEL_WIDTH (f),
@ -1042,7 +1042,7 @@ xg_win_to_widget (Display *dpy, Window wdesc)
/* Set the background of widget W to PIXEL. */
static void
xg_set_widget_bg (FRAME_PTR f, GtkWidget *w, long unsigned int pixel)
xg_set_widget_bg (struct frame *f, GtkWidget *w, long unsigned int pixel)
{
#ifdef HAVE_GTK3
GdkRGBA bg;
@ -1093,7 +1093,7 @@ style_changed_cb (GObject *go,
Lisp_Object rest, frame;
FOR_EACH_FRAME (rest, frame)
{
FRAME_PTR f = XFRAME (frame);
struct frame *f = XFRAME (frame);
if (FRAME_LIVE_P (f)
&& FRAME_X_P (f)
&& FRAME_X_DISPLAY (f) == dpy)
@ -1115,7 +1115,7 @@ delete_cb (GtkWidget *widget,
#ifdef HAVE_GTK3
/* The event doesn't arrive in the normal event loop. Send event
here. */
FRAME_PTR f = (FRAME_PTR) user_data;
struct frame *f = (struct frame *) user_data;
struct input_event ie;
EVENT_INIT (ie);
@ -1131,7 +1131,7 @@ delete_cb (GtkWidget *widget,
Return true if creation succeeded. */
bool
xg_create_frame_widgets (FRAME_PTR f)
xg_create_frame_widgets (struct frame *f)
{
GtkWidget *wtop;
GtkWidget *wvbox, *whbox;
@ -1300,7 +1300,7 @@ xg_create_frame_widgets (FRAME_PTR f)
}
void
xg_free_frame_widgets (FRAME_PTR f)
xg_free_frame_widgets (struct frame *f)
{
if (FRAME_GTK_OUTER_WIDGET (f))
{
@ -1332,7 +1332,7 @@ xg_free_frame_widgets (FRAME_PTR f)
flag (this is useful when FLAGS is 0). */
void
x_wm_set_size_hint (FRAME_PTR f, long int flags, bool user_position)
x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
{
/* Must use GTK routines here, otherwise GTK resets the size hints
to its own defaults. */
@ -1432,7 +1432,7 @@ x_wm_set_size_hint (FRAME_PTR f, long int flags, bool user_position)
BG is the pixel value to change to. */
void
xg_set_background_color (FRAME_PTR f, long unsigned int bg)
xg_set_background_color (struct frame *f, long unsigned int bg)
{
if (FRAME_GTK_WIDGET (f))
{
@ -1447,7 +1447,7 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
functions so GTK does not overwrite the icon. */
void
xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, Pixmap icon_mask)
xg_set_frame_icon (struct frame *f, Pixmap icon_pixmap, Pixmap icon_mask)
{
GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (f,
icon_pixmap,
@ -1693,7 +1693,7 @@ xg_maybe_add_timer (gpointer data)
The dialog W is not destroyed when this function returns. */
static int
xg_dialog_run (FRAME_PTR f, GtkWidget *w)
xg_dialog_run (struct frame *f, GtkWidget *w)
{
ptrdiff_t count = SPECPDL_INDEX ();
struct xg_dialog_data dd;
@ -1813,7 +1813,7 @@ xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data)
Returns the created widget. */
static GtkWidget *
xg_get_file_with_chooser (FRAME_PTR f,
xg_get_file_with_chooser (struct frame *f,
char *prompt,
char *default_filename,
bool mustmatch_p, bool only_dir_p,
@ -1935,7 +1935,7 @@ xg_get_file_name_from_selector (GtkWidget *w)
Returns the created widget. */
static GtkWidget *
xg_get_file_with_selection (FRAME_PTR f,
xg_get_file_with_selection (struct frame *f,
char *prompt,
char *default_filename,
bool mustmatch_p, bool only_dir_p,
@ -1977,7 +1977,7 @@ xg_get_file_with_selection (FRAME_PTR f,
The returned string must be freed by the caller. */
char *
xg_get_file_name (FRAME_PTR f,
xg_get_file_name (struct frame *f,
char *prompt,
char *default_filename,
bool mustmatch_p,
@ -2051,7 +2051,7 @@ extern Lisp_Object Qxft;
DEFAULT_NAME, if non-zero, is the default font name. */
Lisp_Object
xg_get_font (FRAME_PTR f, const char *default_name)
xg_get_font (struct frame *f, const char *default_name)
{
GtkWidget *w;
int done = 0;
@ -2169,7 +2169,7 @@ static xg_list_node xg_menu_item_cb_list;
allocated xg_menu_cb_data if CL_DATA is NULL. */
static xg_menu_cb_data *
make_cl_data (xg_menu_cb_data *cl_data, FRAME_PTR f, GCallback highlight_cb)
make_cl_data (xg_menu_cb_data *cl_data, struct frame *f, GCallback highlight_cb)
{
if (! cl_data)
{
@ -2201,7 +2201,7 @@ make_cl_data (xg_menu_cb_data *cl_data, FRAME_PTR f, GCallback highlight_cb)
static void
update_cl_data (xg_menu_cb_data *cl_data,
FRAME_PTR f,
struct frame *f,
GCallback highlight_cb)
{
if (cl_data)
@ -2251,7 +2251,7 @@ xg_mark_data (void)
FOR_EACH_FRAME (rest, frame)
{
FRAME_PTR f = XFRAME (frame);
struct frame *f = XFRAME (frame);
if (FRAME_X_P (f) && FRAME_GTK_OUTER_WIDGET (f))
{
@ -2480,7 +2480,7 @@ xg_have_tear_offs (void)
static GtkWidget *
xg_create_one_menuitem (widget_value *item,
FRAME_PTR f,
struct frame *f,
GCallback select_cb,
GCallback highlight_cb,
xg_menu_cb_data *cl_data,
@ -2551,7 +2551,7 @@ xg_create_one_menuitem (widget_value *item,
static GtkWidget *
create_menus (widget_value *data,
FRAME_PTR f,
struct frame *f,
GCallback select_cb,
GCallback deactivate_cb,
GCallback highlight_cb,
@ -2694,9 +2694,9 @@ create_menus (widget_value *data,
Returns the widget created. */
GtkWidget *
xg_create_widget (const char *type, const char *name, FRAME_PTR f, widget_value *val,
GCallback select_cb, GCallback deactivate_cb,
GCallback highlight_cb)
xg_create_widget (const char *type, const char *name, struct frame *f,
widget_value *val, GCallback select_cb,
GCallback deactivate_cb, GCallback highlight_cb)
{
GtkWidget *w = 0;
bool menu_bar_p = strcmp (type, "menubar") == 0;
@ -2802,7 +2802,7 @@ xg_destroy_widgets (GList *list)
static void
xg_update_menubar (GtkWidget *menubar,
FRAME_PTR f,
struct frame *f,
GList **list,
GList *iter,
int pos,
@ -3119,7 +3119,7 @@ xg_update_radio_item (widget_value *val, GtkWidget *w)
static GtkWidget *
xg_update_submenu (GtkWidget *submenu,
FRAME_PTR f,
struct frame *f,
widget_value *val,
GCallback select_cb,
GCallback deactivate_cb,
@ -3261,8 +3261,8 @@ xg_update_submenu (GtkWidget *submenu,
HIGHLIGHT_CB is the callback to call when entering/leaving menu items. */
void
xg_modify_menubar_widgets (GtkWidget *menubar, FRAME_PTR f, widget_value *val,
bool deep_p,
xg_modify_menubar_widgets (GtkWidget *menubar, struct frame *f,
widget_value *val, bool deep_p,
GCallback select_cb, GCallback deactivate_cb,
GCallback highlight_cb)
{
@ -3336,7 +3336,7 @@ static void
menubar_map_cb (GtkWidget *w, gpointer user_data)
{
GtkRequisition req;
FRAME_PTR f = (FRAME_PTR) user_data;
struct frame *f = (struct frame *) user_data;
gtk_widget_get_preferred_size (w, NULL, &req);
if (FRAME_MENUBAR_HEIGHT (f) != req.height)
{
@ -3349,7 +3349,7 @@ menubar_map_cb (GtkWidget *w, gpointer user_data)
changed. */
void
xg_update_frame_menubar (FRAME_PTR f)
xg_update_frame_menubar (struct frame *f)
{
struct x_output *x = f->output_data.x;
GtkRequisition req;
@ -3387,7 +3387,7 @@ xg_update_frame_menubar (FRAME_PTR f)
This is used when deleting a frame, and when turning off the menu bar. */
void
free_frame_menubar (FRAME_PTR f)
free_frame_menubar (struct frame *f)
{
struct x_output *x = f->output_data.x;
@ -3406,7 +3406,7 @@ free_frame_menubar (FRAME_PTR f)
}
bool
xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
xg_event_is_for_menubar (struct frame *f, XEvent *event)
{
struct x_output *x = f->output_data.x;
GList *iter;
@ -3619,7 +3619,7 @@ xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
to set resources for the widget. */
void
xg_create_scroll_bar (FRAME_PTR f,
xg_create_scroll_bar (struct frame *f,
struct scroll_bar *bar,
GCallback scroll_callback,
GCallback end_callback,
@ -3681,7 +3681,7 @@ xg_create_scroll_bar (FRAME_PTR f,
/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */
void
xg_remove_scroll_bar (FRAME_PTR f, ptrdiff_t scrollbar_id)
xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id)
{
GtkWidget *w = xg_get_widget_from_map (scrollbar_id);
if (w)
@ -3699,7 +3699,7 @@ xg_remove_scroll_bar (FRAME_PTR f, ptrdiff_t scrollbar_id)
WIDTH, HEIGHT is the size in pixels the bar shall have. */
void
xg_update_scrollbar_pos (FRAME_PTR f,
xg_update_scrollbar_pos (struct frame *f,
ptrdiff_t scrollbar_id,
int top,
int left,
@ -3781,7 +3781,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
{
GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
if (wscroll && NILP (bar->dragging))
{
@ -3861,7 +3861,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
frame. This function does additional checks. */
bool
xg_event_is_for_scrollbar (FRAME_PTR f, XEvent *event)
xg_event_is_for_scrollbar (struct frame *f, XEvent *event)
{
bool retval = 0;
@ -3946,7 +3946,8 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
intptr_t mod = (intptr_t) gmod;
FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
struct frame *f = (struct frame *) g_object_get_data (G_OBJECT (w),
XG_FRAME_DATA);
Lisp_Object key, frame;
struct input_event event;
EVENT_INIT (event);
@ -4149,7 +4150,7 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
GtkWidget *w,
gpointer client_data)
{
FRAME_PTR f = (FRAME_PTR) client_data;
struct frame *f = (struct frame *) client_data;
g_object_set (G_OBJECT (w), "show-arrow", !x_gtk_whole_detached_tool_bar,
NULL);
@ -4186,7 +4187,7 @@ xg_tool_bar_attach_callback (GtkHandleBox *wbox,
GtkWidget *w,
gpointer client_data)
{
FRAME_PTR f = (FRAME_PTR) client_data;
struct frame *f = (struct frame *) client_data;
g_object_set (G_OBJECT (w), "show-arrow", TRUE, NULL);
if (f)
@ -4224,7 +4225,8 @@ xg_tool_bar_help_callback (GtkWidget *w,
gpointer client_data)
{
intptr_t idx = (intptr_t) client_data;
FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
struct frame *f = (struct frame *) g_object_get_data (G_OBJECT (w),
XG_FRAME_DATA);
Lisp_Object help, frame;
if (! f || ! f->n_tool_bar_items || NILP (f->tool_bar_items))
@ -4297,7 +4299,7 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
/* Attach a tool bar to frame F. */
static void
xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
xg_pack_tool_bar (struct frame *f, Lisp_Object pos)
{
struct x_output *x = f->output_data.x;
bool into_hbox = EQ (pos, Qleft) || EQ (pos, Qright);
@ -4354,7 +4356,7 @@ xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
x->toolbar_is_packed = true;
}
static bool xg_update_tool_bar_sizes (FRAME_PTR f);
static bool xg_update_tool_bar_sizes (struct frame *f);
static void
tb_size_cb (GtkWidget *widget,
@ -4364,7 +4366,7 @@ tb_size_cb (GtkWidget *widget,
/* When tool bar is created it has one preferred size. But when size is
allocated between widgets, it may get another. So we must update
size hints if tool bar size changes. Seen on Fedora 18 at least. */
FRAME_PTR f = (FRAME_PTR) user_data;
struct frame *f = (struct frame *) user_data;
if (xg_update_tool_bar_sizes (f))
x_wm_set_size_hint (f, 0, 0);
}
@ -4372,7 +4374,7 @@ tb_size_cb (GtkWidget *widget,
/* Create a tool bar for frame F. */
static void
xg_create_tool_bar (FRAME_PTR f)
xg_create_tool_bar (struct frame *f)
{
struct x_output *x = f->output_data.x;
#if GTK_CHECK_VERSION (3, 3, 6)
@ -4415,7 +4417,7 @@ xg_create_tool_bar (FRAME_PTR f)
Returns IMAGE if RTL is not found. */
static Lisp_Object
find_rtl_image (FRAME_PTR f, Lisp_Object image, Lisp_Object rtl)
find_rtl_image (struct frame *f, Lisp_Object image, Lisp_Object rtl)
{
int i;
Lisp_Object file, rtl_name;
@ -4443,7 +4445,7 @@ find_rtl_image (FRAME_PTR f, Lisp_Object image, Lisp_Object rtl)
}
static GtkToolItem *
xg_make_tool_item (FRAME_PTR f,
xg_make_tool_item (struct frame *f,
GtkWidget *wimage,
GtkWidget **wbutton,
const char *label,
@ -4606,7 +4608,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
}
static bool
xg_update_tool_bar_sizes (FRAME_PTR f)
xg_update_tool_bar_sizes (struct frame *f)
{
struct x_output *x = f->output_data.x;
GtkRequisition req;
@ -4654,7 +4656,7 @@ xg_update_tool_bar_sizes (FRAME_PTR f)
/* Update the tool bar for frame F. Add new buttons and remove old. */
void
update_frame_tool_bar (FRAME_PTR f)
update_frame_tool_bar (struct frame *f)
{
int i, j;
struct x_output *x = f->output_data.x;
@ -4929,7 +4931,7 @@ update_frame_tool_bar (FRAME_PTR f)
Remove the tool bar. */
void
free_frame_tool_bar (FRAME_PTR f)
free_frame_tool_bar (struct frame *f)
{
struct x_output *x = f->output_data.x;
@ -4976,7 +4978,7 @@ free_frame_tool_bar (FRAME_PTR f)
}
void
xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos)
xg_change_toolbar_position (struct frame *f, Lisp_Object pos)
{
struct x_output *x = f->output_data.x;
GtkWidget *top_widget = TOOLBAR_TOP_WIDGET (x);

View file

@ -55,7 +55,7 @@ typedef struct xg_menu_cb_data_
{
xg_list_node ptrs;
FRAME_PTR f;
struct frame *f;
Lisp_Object menu_bar_vector;
int menu_bar_items_used;
GCallback highlight_cb;
@ -81,46 +81,46 @@ extern void free_widget_value (struct _widget_value *);
extern bool xg_uses_old_file_dialog (void) ATTRIBUTE_CONST;
extern char *xg_get_file_name (FRAME_PTR f,
extern char *xg_get_file_name (struct frame *f,
char *prompt,
char *default_filename,
bool mustmatch_p,
bool only_dir_p);
extern Lisp_Object xg_get_font (FRAME_PTR f, const char *);
extern Lisp_Object xg_get_font (struct frame *f, const char *);
extern GtkWidget *xg_create_widget (const char *type,
const char *name,
FRAME_PTR f,
struct frame *f,
struct _widget_value *val,
GCallback select_cb,
GCallback deactivate_cb,
GCallback highlight_cb);
extern void xg_modify_menubar_widgets (GtkWidget *menubar,
FRAME_PTR f,
struct frame *f,
struct _widget_value *val,
bool deep_p,
GCallback select_cb,
GCallback deactivate_cb,
GCallback highlight_cb);
extern void xg_update_frame_menubar (FRAME_PTR f);
extern void xg_update_frame_menubar (struct frame *f);
extern bool xg_event_is_for_menubar (FRAME_PTR f, XEvent *event);
extern bool xg_event_is_for_menubar (struct frame *f, XEvent *event);
extern bool xg_have_tear_offs (void);
extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid);
extern void xg_create_scroll_bar (FRAME_PTR f,
extern void xg_create_scroll_bar (struct frame *f,
struct scroll_bar *bar,
GCallback scroll_callback,
GCallback end_callback,
const char *scroll_bar_name);
extern void xg_remove_scroll_bar (FRAME_PTR f, ptrdiff_t scrollbar_id);
extern void xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id);
extern void xg_update_scrollbar_pos (FRAME_PTR f,
extern void xg_update_scrollbar_pos (struct frame *f,
ptrdiff_t scrollbar_id,
int top,
int left,
@ -131,40 +131,40 @@ extern void xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
int portion,
int position,
int whole);
extern bool xg_event_is_for_scrollbar (FRAME_PTR f, XEvent *event);
extern bool xg_event_is_for_scrollbar (struct frame *f, XEvent *event);
extern int xg_get_default_scrollbar_width (void);
extern void update_frame_tool_bar (FRAME_PTR f);
extern void free_frame_tool_bar (FRAME_PTR f);
extern void xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos);
extern void update_frame_tool_bar (struct frame *f);
extern void free_frame_tool_bar (struct frame *f);
extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos);
extern void xg_frame_resized (FRAME_PTR f,
extern void xg_frame_resized (struct frame *f,
int pixelwidth,
int pixelheight);
extern void xg_frame_set_char_size (FRAME_PTR f, int cols, int rows);
extern void xg_frame_set_char_size (struct frame *f, int cols, int rows);
extern GtkWidget * xg_win_to_widget (Display *dpy, Window wdesc);
extern void xg_display_open (char *display_name, Display **dpy);
extern void xg_display_close (Display *dpy);
extern GdkCursor * xg_create_default_cursor (Display *dpy);
extern bool xg_create_frame_widgets (FRAME_PTR f);
extern void xg_free_frame_widgets (FRAME_PTR f);
extern void xg_set_background_color (FRAME_PTR f, unsigned long bg);
extern bool xg_create_frame_widgets (struct frame *f);
extern void xg_free_frame_widgets (struct frame *f);
extern void xg_set_background_color (struct frame *f, unsigned long bg);
extern bool xg_check_special_colors (struct frame *f,
const char *color_name,
XColor *color);
extern void xg_set_frame_icon (FRAME_PTR f,
extern void xg_set_frame_icon (struct frame *f,
Pixmap icon_pixmap,
Pixmap icon_mask);
extern bool xg_prepare_tooltip (FRAME_PTR f,
extern bool xg_prepare_tooltip (struct frame *f,
Lisp_Object string,
int *width,
int *height);
extern void xg_show_tooltip (FRAME_PTR f, int root_x, int root_y);
extern bool xg_hide_tooltip (FRAME_PTR f);
extern void xg_show_tooltip (struct frame *f, int root_x, int root_y);
extern bool xg_hide_tooltip (struct frame *f);
/* Mark all callback data that are Lisp_object:s during GC. */

View file

@ -164,20 +164,20 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
/* Functions to access the contents of a bitmap, given an id. */
int
x_bitmap_height (FRAME_PTR f, ptrdiff_t id)
x_bitmap_height (struct frame *f, ptrdiff_t id)
{
return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
}
int
x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
x_bitmap_width (struct frame *f, ptrdiff_t id)
{
return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
}
#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
ptrdiff_t
x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
x_bitmap_pixmap (struct frame *f, ptrdiff_t id)
{
/* HAVE_NTGUI needs the explicit cast here. */
return (ptrdiff_t) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
@ -186,7 +186,7 @@ x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
#ifdef HAVE_X_WINDOWS
int
x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
x_bitmap_mask (struct frame *f, ptrdiff_t id)
{
return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
}
@ -195,7 +195,7 @@ x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
/* Allocate a new bitmap record. Returns index of new record. */
static ptrdiff_t
x_allocate_bitmap_record (FRAME_PTR f)
x_allocate_bitmap_record (struct frame *f)
{
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
ptrdiff_t i;
@ -216,7 +216,7 @@ x_allocate_bitmap_record (FRAME_PTR f)
/* Add one reference to the reference count of the bitmap with id ID. */
void
x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
x_reference_bitmap (struct frame *f, ptrdiff_t id)
{
++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
}
@ -384,7 +384,7 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
/* Remove reference to bitmap with id number ID. */
void
x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id)
x_destroy_bitmap (struct frame *f, ptrdiff_t id)
{
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);

View file

@ -1211,12 +1211,9 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
adjust_markers_for_insert (from, from_byte,
from + len, from_byte + len_byte, 0);
if (! EQ (BVAR (current_buffer, undo_list), Qt))
{
if (nchars_del > 0)
record_delete (from, prev_text);
record_insert (from, len);
}
if (nchars_del > 0)
record_delete (from, prev_text);
record_insert (from, len);
if (len > nchars_del)
adjust_overlays_for_insert (from, len - nchars_del);
@ -1373,12 +1370,12 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
emacs_abort ();
#endif
if (! EQ (BVAR (current_buffer, undo_list), Qt))
/* Record the insertion first, so that when we undo,
the deletion will be undone first. Thus, undo
will insert before deleting, and thus will keep
the markers before and after this text separate. */
if (!NILP (deletion))
{
/* Record the insertion first, so that when we undo,
the deletion will be undone first. Thus, undo
will insert before deleting, and thus will keep
the markers before and after this text separate. */
record_insert (from + SCHARS (deletion), inschars);
record_delete (from, deletion);
}
@ -1718,8 +1715,7 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
so that undo handles this after reinserting the text. */
adjust_markers_for_delete (from, from_byte, to, to_byte);
if (! EQ (BVAR (current_buffer, undo_list), Qt))
record_delete (from, deletion);
record_delete (from, deletion);
MODIFF++;
CHARS_MODIFF = MODIFF;

View file

@ -1281,7 +1281,7 @@ static
#endif
bool ignore_mouse_drag_p;
static FRAME_PTR
static struct frame *
some_mouse_moved (void)
{
Lisp_Object tail, frame;
@ -2163,7 +2163,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
This causes trouble if we are trying to read a mouse motion
event (i.e., if we are inside a `track-mouse' form), so we
restore the mouse_moved flag. */
FRAME_PTR f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
struct frame *f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
help = call1 (Qmouse_fixup_help_message, help);
if (f)
f->mouse_moved = 1;
@ -4152,7 +4152,7 @@ kbd_buffer_get_event (KBOARD **kbp,
/* Try generating a mouse motion event. */
else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
{
FRAME_PTR f = some_mouse_moved ();
struct frame *f = some_mouse_moved ();
Lisp_Object bar_window;
enum scroll_bar_part part;
Lisp_Object x, y;
@ -5898,7 +5898,7 @@ make_lispy_event (struct input_event *event)
case DRAG_N_DROP_EVENT:
{
FRAME_PTR f;
struct frame *f;
Lisp_Object head, position;
Lisp_Object files;
@ -5977,7 +5977,7 @@ make_lispy_event (struct input_event *event)
#ifdef HAVE_GPM
case GPM_CLICK_EVENT:
{
FRAME_PTR f = XFRAME (event->frame_or_window);
struct frame *f = XFRAME (event->frame_or_window);
Lisp_Object head, position;
Lisp_Object *start_pos_ptr;
Lisp_Object start_pos;
@ -6031,7 +6031,7 @@ make_lispy_event (struct input_event *event)
}
static Lisp_Object
make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_part part,
make_lispy_movement (struct frame *frame, Lisp_Object bar_window, enum scroll_bar_part part,
Lisp_Object x, Lisp_Object y, Time t)
{
/* Is it a scroll bar movement? */

View file

@ -3302,6 +3302,7 @@ extern struct hash_table_test hashtest_eql, hashtest_equal;
extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t);
extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object do_yes_or_no_p (Lisp_Object);
extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
extern Lisp_Object concat3 (Lisp_Object, Lisp_Object, Lisp_Object);

View file

@ -867,7 +867,8 @@ update_submenu_strings (widget_value *first_wv)
VECTOR is an array of menu events for the whole menu. */
void
find_and_call_menu_selection (FRAME_PTR f, int menu_bar_items_used, Lisp_Object vector, void *client_data)
find_and_call_menu_selection (struct frame *f, int menu_bar_items_used,
Lisp_Object vector, void *client_data)
{
Lisp_Object prefix, entry;
Lisp_Object *subprefix_stack;
@ -950,7 +951,7 @@ find_and_call_menu_selection (FRAME_PTR f, int menu_bar_items_used, Lisp_Object
/* As above, but return the menu selection instead of storing in kb buffer.
If KEYMAPS, return full prefixes to selection. */
Lisp_Object
find_and_return_menu_selection (FRAME_PTR f, bool keymaps, void *client_data)
find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data)
{
Lisp_Object prefix, entry;
int i;
@ -1060,7 +1061,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
Lisp_Object title;
const char *error_name = NULL;
Lisp_Object selection = Qnil;
FRAME_PTR f = NULL;
struct frame *f = NULL;
Lisp_Object x, y, window;
bool keymaps = 0;
bool for_click = 0;
@ -1116,7 +1117,7 @@ no quit occurs and `x-popup-menu' returns nil. */)
if (get_current_pos_p)
{
/* Use the mouse's current position. */
FRAME_PTR new_f = SELECTED_FRAME ();
struct frame *new_f = SELECTED_FRAME ();
#ifdef HAVE_X_WINDOWS
/* Can't use mouse_position_hook for X since it returns
coordinates relative to the window the mouse is in,

Some files were not shown because too many files have changed in this diff Show more