Merge from mainline.
This commit is contained in:
commit
99191b89ff
138 changed files with 4270 additions and 2495 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 they’ll 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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
25
etc/NEWS
25
etc/NEWS
|
@ -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.
|
||||
|
||||
|
|
9
etc/TODO
9
etc/TODO
|
@ -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?)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.net)Emacs 板众多网友及众多 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
197
lisp/ChangeLog
197
lisp/ChangeLog
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.")
|
||||
|
|
622
lisp/desktop.el
622
lisp/desktop.el
|
@ -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
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)))))
|
||||
|
||||
|
|
206
lisp/files.el
206
lisp/files.el
|
@ -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
693
lisp/frameset.el
Normal 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
|
|
@ -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.
|
||||
|
|
|
@ -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]+\\)"
|
||||
|
|
|
@ -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
837
lisp/gnus/gnus-icalendar.el
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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" "\
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) ":"))))
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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)
|
||||
|
|
196
src/ChangeLog
196
src/ChangeLog
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
124
src/eval.c
124
src/eval.c
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
107
src/font.c
107
src/font.c
|
@ -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;
|
||||
|
|
59
src/font.h
59
src/font.h
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
74
src/frame.c
74
src/frame.c
|
@ -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");
|
||||
|
|
25
src/frame.h
25
src/frame.h
|
@ -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 *);
|
||||
|
|
24
src/ftfont.c
24
src/ftfont.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
126
src/gtkutil.c
126
src/gtkutil.c
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
14
src/image.c
14
src/image.c
|
@ -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);
|
||||
|
||||
|
|
22
src/insdel.c
22
src/insdel.c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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? */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue