From 358641245533b52798008cc40a47abfb84481c1f Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:34:38 +0000 Subject: [PATCH 01/42] Various small changes in addition to the following. (Converting Representations): Clarify behavior of `string-make-multibyte' and `string-to-multibyte' for unibyte all ASCII arguments. (Character Sets): Document the variable `charset-list' and adapt the definition of the function `charset-list' accordingly. (Translation of Characters): Clarify use of generic characters in `make-translation-table'. Clarify and correct the description of the use of translation tables in encoding and decoding. (User-Chosen Coding Systems): Correct and clarify the description of `select-safe-coding-system'. (Default Coding Systems): Clarify description of `file-coding-system-alist'. --- lispref/nonascii.texi | 228 +++++++++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 81 deletions(-) diff --git a/lispref/nonascii.texi b/lispref/nonascii.texi index 72dd46d19eb..0c07b394e93 100644 --- a/lispref/nonascii.texi +++ b/lispref/nonascii.texi @@ -96,13 +96,15 @@ default value to @code{nil} early in startup. @defun position-bytes position @tindex position-bytes Return the byte-position corresponding to buffer position @var{position} -in the current buffer. +in the current buffer. If @var{position} is out of range, the value +is @code{nil}. @end defun @defun byte-to-position byte-position @tindex byte-to-position Return the buffer position corresponding to byte-position -@var{byte-position} in the current buffer. +@var{byte-position} in the current buffer. If @var{byte-position} is +out of range, the value is @code{nil}. @end defun @defun multibyte-string-p string @@ -173,6 +175,9 @@ multibyte character. The value should be a char-table, or @code{nil}. If this is non-@code{nil}, it overrides @code{nonascii-insert-offset}. @end defvar +The next three functions either return the argument @var{string}, or a +newly created string with no text properties. + @defun string-make-unibyte string This function converts the text of @var{string} to unibyte representation, if it isn't already, and returns the result. If @@ -186,15 +191,23 @@ fails, this function takes just the low 8 bits of each character. @defun string-make-multibyte string This function converts the text of @var{string} to multibyte representation, if it isn't already, and returns the result. If -@var{string} is a multibyte string, it is returned unchanged. -The function @code{unibyte-char-to-multibyte} is used to convert -each unibyte character to a multibyte character. +@var{string} is a multibyte string or consists entirely of +@acronym{ASCII} characters, it is returned unchanged. In particular, +if @var{string} is unibyte and entirely @acronym{ASCII}, the returned +string is unibyte. (When the characters are all @acronym{ASCII}, +Emacs primitives will treat the string the same way whether it is +unibyte or multibyte.) If @var{string} is unibyte and contains +non-@acronym{ASCII} characters, the function +@code{unibyte-char-to-multibyte} is used to convert each unibyte +character to a multibyte character. @end defun @defun string-to-multibyte string This function returns a multibyte string containing the same sequence -of character codes as @var{string}. If @var{string} is a multibyte -string, the value is the equal to @var{string}. +of character codes as @var{string}. Unlike +@code{string-make-multibyte}, this function unconditionally returns a +multibyte string. If @var{string} is a multibyte string, it is +returned unchanged. @end defun @node Selecting a Representation @@ -280,8 +293,8 @@ text representations. @end example If the optional argument @var{genericp} is non-@code{nil}, this -function returns @code{t} if @var{charcode} is a generic character -(@pxref{Splitting Characters}). +function also returns @code{t} if @var{charcode} is a generic +character (@pxref{Splitting Characters}). @end defun @node Character Sets @@ -311,13 +324,19 @@ Returns @code{t} if @var{object} is a symbol that names a character set, @code{nil} otherwise. @end defun +@defvar charset-list +The value is a list of all defined character set names. +@end defvar + @defun charset-list -This function returns a list of all defined character set names. +This function returns the value of @code{charset-list}. It is only +provided for backward compatibility. @end defun @defun char-charset character This function returns the name of the character set that @var{character} -belongs to. +belongs to, or the symbol @code{unknown} if @var{character} is not a +valid character. @end defun @defun charset-plist charset @@ -378,6 +397,9 @@ Return a list containing the name of the character set of identify @var{character} within that character set. The number of byte values is the character set's dimension. +If @var{character} is invalid as a character code, @code{split-char} +returns a list consisting of the symbol @code{unknown} and @var{character}. + @example (split-char 2248) @result{} (latin-iso8859-1 72) @@ -463,11 +485,11 @@ current buffer. @cindex character translation tables @cindex translation tables - A @dfn{translation table} specifies a mapping of characters -into characters. These tables are used in encoding and decoding, and -for other purposes. Some coding systems specify their own particular -translation tables; there are also default translation tables which -apply to all other coding systems. + A @dfn{translation table} is a char-table that specifies a mapping +of characters into characters. These tables are used in encoding and +decoding, and for other purposes. Some coding systems specify their +own particular translation tables; there are also default translation +tables which apply to all other coding systems. @defun make-translation-table &rest translations This function returns a translation table based on the argument @@ -483,24 +505,30 @@ character, say @var{to-alt}, @var{from} is also translated to You can also map one whole character set into another character set with the same dimension. To do this, you specify a generic character (which designates a character set) for @var{from} (@pxref{Splitting Characters}). -In this case, @var{to} should also be a generic character, for another -character set of the same dimension. Then the translation table -translates each character of @var{from}'s character set into the -corresponding character of @var{to}'s character set. +In this case, if @var{to} is also a generic character, its character +set should have the same dimension as @var{from}'s. Then the +translation table translates each character of @var{from}'s character +set into the corresponding character of @var{to}'s character set. If +@var{from} is a generic character and @var{to} is an ordinary +character, then the translation table translates every character of +@var{from}'s character set into @var{to}. @end defun In decoding, the translation table's translations are applied to the characters that result from ordinary decoding. If a coding system has -property @code{character-translation-table-for-decode}, that specifies -the translation table to use. Otherwise, if -@code{standard-translation-table-for-decode} is non-@code{nil}, decoding -uses that table. +property @code{translation-table-for-decode}, that specifies the +translation table to use. (This is a property of the coding system, +as returned by @code{coding-system-get}, not a property of the symbol +that is the coding system's name. @xref{Coding System Basics,, Basic +Concepts of Coding Systems}.) Otherwise, if +@code{standard-translation-table-for-decode} is non-@code{nil}, +decoding uses that table. In encoding, the translation table's translations are applied to the characters in the buffer, and the result of translation is actually encoded. If a coding system has property -@code{character-translation-table-for-encode}, that specifies the -translation table to use. Otherwise the variable +@code{translation-table-for-encode}, that specifies the translation +table to use. Otherwise the variable @code{standard-translation-table-for-encode} specifies the translation table. @@ -516,7 +544,8 @@ coding systems that don't specify any other translation table. @defvar translation-table-for-input Self-inserting characters are translated through this translation -table before they are inserted. +table before they are inserted. This variable automatically becomes +buffer-local when set. @end defvar @node Coding Systems @@ -686,7 +715,7 @@ systems as well. @defun coding-system-p object This function returns @code{t} if @var{object} is a coding system -name. +name or @code{nil}. @end defun @defun check-coding-system coding-system @@ -701,6 +730,9 @@ except for its eol conversion, which is specified by @code{eol-type}. @var{eol-type} should be @code{unix}, @code{dos}, @code{mac}, or @code{nil}. If it is @code{nil}, the returned coding system determines the end-of-line conversion from the data. + +@var{eol-type} may also be 0, 1 or 2, standing for @code{unix}, +@code{dos} and @code{mac}, respectively. @end defun @defun coding-system-change-text-conversion eol-coding text-coding @@ -745,55 +777,79 @@ return value is just one coding system, the one that is highest in priority. If the region contains only @acronym{ASCII} characters, the value -is @code{undecided} or @code{(undecided)}. +is @code{undecided} or @code{(undecided)}, or a variant specifying +end-of-line conversion, if that can be deduced from the text. @end defun -@defun detect-coding-string string highest +@defun detect-coding-string string &optional highest This function is like @code{detect-coding-region} except that it operates on the contents of @var{string} instead of bytes in the buffer. @end defun - @xref{Process Information}, for how to examine or set the coding -systems used for I/O to a subprocess. + @xref{Coding systems for a subprocess,, Process Information}, in +particular the description of the functions +@code{process-coding-system} and @code{set-process-coding-system}, for +how to examine or set the coding systems used for I/O to a subprocess. @node User-Chosen Coding Systems @subsection User-Chosen Coding Systems @cindex select safe coding system -@defun select-safe-coding-system from to &optional default-coding-system accept-default-p +@defun select-safe-coding-system from to &optional default-coding-system accept-default-p file This function selects a coding system for encoding specified text, asking the user to choose if necessary. Normally the specified text -is the text in the current buffer between @var{from} and @var{to}, -defaulting to the whole buffer if they are @code{nil}. If @var{from} -is a string, the string specifies the text to encode, and @var{to} is -ignored. +is the text in the current buffer between @var{from} and @var{to}. If +@var{from} is a string, the string specifies the text to encode, and +@var{to} is ignored. If @var{default-coding-system} is non-@code{nil}, that is the first coding system to try; if that can handle the text, @code{select-safe-coding-system} returns that coding system. It can also be a list of coding systems; then the function tries each of them -one by one. After trying all of them, it next tries the user's most -preferred coding system (@pxref{Recognize Coding, -prefer-coding-system, the description of @code{prefer-coding-system}, -emacs, GNU Emacs Manual}), and after that the current buffer's value -of @code{buffer-file-coding-system} (if it is not @code{undecided}). +one by one. After trying all of them, it next tries the current +buffer's value of @code{buffer-file-coding-system} (if it is not +@code{undecided}), then the value of +@code{default-buffer-file-coding-system} and finally the user's most +preferred coding system, which the user can set using the command +@code{prefer-coding-system} (@pxref{Recognize Coding,, Recognizing +Coding Systems, emacs, The GNU Emacs Manual}). If one of those coding systems can safely encode all the specified text, @code{select-safe-coding-system} chooses it and returns it. Otherwise, it asks the user to choose from a list of coding systems which can encode all the text, and returns the user's choice. +@var{default-coding-system} can also be a list whose first element is +t and whose other elements are coding systems. Then, if no coding +system in the list can handle the text, @code{select-safe-coding-system} +queries the user immediately, without trying any of the three +alternatives described above. + The optional argument @var{accept-default-p}, if non-@code{nil}, -should be a function to determine whether the coding system selected -without user interaction is acceptable. If this function returns -@code{nil}, the silently selected coding system is rejected, and the -user is asked to select a coding system from a list of possible -candidates. +should be a function to determine whether a coding system selected +without user interaction is acceptable. @code{select-safe-coding-system} +calls this function with one argument, the base coding system of the +selected coding system. If @var{accept-default-p} returns @code{nil}, +@code{select-safe-coding-system} rejects the silently selected coding +system, and asks the user to select a coding system from a list of +possible candidates. @vindex select-safe-coding-system-accept-default-p If the variable @code{select-safe-coding-system-accept-default-p} is non-@code{nil}, its value overrides the value of @var{accept-default-p}. + +As a final step, before returning the chosen coding system, +@code{select-safe-coding-system} checks whether that coding system is +consistent with what would be selected if the contents of the region +were read from a file. (If not, this could lead to data corruption in +a file subsequently re-visited and edited.) Normally, +@code{select-safe-coding-system} uses @code{buffer-file-name} as the +file for this purpose, but if @var{file} is non-@code{nil}, it uses +that file instead (this can be relevant for @code{write-region} and +similar functions). If it detects an apparent inconsistency, +@code{select-safe-coding-system} queries the user before selecting the +coding system. @end defun Here are two functions you can use to let the user specify a coding @@ -846,17 +902,19 @@ reading and writing particular files. Each element has the form expression that matches certain file names. The element applies to file names that match @var{pattern}. -The @acronym{CDR} of the element, @var{coding}, should be either a coding +The @sc{cdr} of the element, @var{coding}, should be either a coding system, a cons cell containing two coding systems, or a function name (a symbol with a function definition). If @var{coding} is a coding system, that coding system is used for both reading the file and writing it. If -@var{coding} is a cons cell containing two coding systems, its @acronym{CAR} -specifies the coding system for decoding, and its @acronym{cdr} specifies the +@var{coding} is a cons cell containing two coding systems, its @sc{car} +specifies the coding system for decoding, and its @sc{cdr} specifies the coding system for encoding. -If @var{coding} is a function name, the function must return a coding -system or a cons cell containing two coding systems. This value is used -as described above. +If @var{coding} is a function name, the function should take one +argument, a list of all arguments passed to +@code{find-operation-coding-system}. It must return a coding system +or a cons cell containing two coding systems. This value has the same +meaning as described above. @end defvar @defvar process-coding-system-alist @@ -923,7 +981,7 @@ performing @var{operation} with @var{arguments}. The value has this form: @example -(@var{decoding-system} @var{encoding-system}) +(@var{decoding-system} . @var{encoding-system}) @end example The first element, @var{decoding-system}, is the coding system to use @@ -948,7 +1006,6 @@ or port number. This function looks up the target in @code{file-coding-system-alist}, @code{process-coding-system-alist}, or @code{network-coding-system-alist}, depending on @var{operation}. -@xref{Default Coding Systems}. @end defun @node Specifying Coding Systems @@ -1040,33 +1097,41 @@ decoding functions produce sequences of bytes; the encoding functions are meant to operate on sequences of bytes. All of these functions discard text properties. -@defun encode-coding-region start end coding-system -This function encodes the text from @var{start} to @var{end} according +@deffn Command encode-coding-region start end coding-system +This command encodes the text from @var{start} to @var{end} according to coding system @var{coding-system}. The encoded text replaces the original text in the buffer. The result of encoding is logically a sequence of bytes, but the buffer remains multibyte if it was multibyte before. -@end defun -@defun encode-coding-string string coding-system +This command returns the length of the encoded text. +@end deffn + +@defun encode-coding-string string coding-system &optional nocopy This function encodes the text in @var{string} according to coding system @var{coding-system}. It returns a new string containing the -encoded text. The result of encoding is a unibyte string. +encoded text, except when @var{nocopy} is non-@code{nil}, in which +case the function may return @var{string} itself if the encoding +operation is trivial. The result of encoding is a unibyte string. @end defun -@defun decode-coding-region start end coding-system -This function decodes the text from @var{start} to @var{end} according +@deffn Command decode-coding-region start end coding-system +This command decodes the text from @var{start} to @var{end} according to coding system @var{coding-system}. The decoded text replaces the original text in the buffer. To make explicit decoding useful, the text before decoding ought to be a sequence of byte values, but both multibyte and unibyte buffers are acceptable. -@end defun -@defun decode-coding-string string coding-system +This command returns the length of the decoded text. +@end deffn + +@defun decode-coding-string string coding-system &optional nocopy This function decodes the text in @var{string} according to coding system @var{coding-system}. It returns a new string containing the -decoded text. To make explicit decoding useful, the contents of -@var{string} ought to be a sequence of byte values, but a multibyte +decoded text, except when @var{nocopy} is non-@code{nil}, in which +case the function may return @var{string} itself if the decoding +operation is trivial. To make explicit decoding useful, the contents +of @var{string} ought to be a sequence of byte values, but a multibyte string is acceptable. @end defun @@ -1095,22 +1160,22 @@ This function returns the coding system that is in use for decoding keyboard input---or @code{nil} if no coding system is to be used. @end defun -@defun set-keyboard-coding-system coding-system -This function specifies @var{coding-system} as the coding system to +@deffn Command set-keyboard-coding-system coding-system +This command specifies @var{coding-system} as the coding system to use for decoding keyboard input. If @var{coding-system} is @code{nil}, that means do not decode keyboard input. -@end defun +@end deffn @defun terminal-coding-system This function returns the coding system that is in use for encoding terminal output---or @code{nil} for no encoding. @end defun -@defun set-terminal-coding-system coding-system -This function specifies @var{coding-system} as the coding system to use +@deffn Command set-terminal-coding-system coding-system +This command specifies @var{coding-system} as the coding system to use for encoding terminal output. If @var{coding-system} is @code{nil}, that means do not encode terminal output. -@end defun +@end deffn @node MS-DOS File Types @subsection MS-DOS File Types @@ -1193,18 +1258,18 @@ in any fashion.) It is @code{nil} if no input method is active in the buffer now. @end defvar -@defvar default-input-method +@defopt default-input-method This variable holds the default input method for commands that choose an input method. Unlike @code{current-input-method}, this variable is normally global. -@end defvar +@end defopt -@defun set-input-method input-method -This function activates input method @var{input-method} for the current +@deffn Command set-input-method input-method +This command activates input method @var{input-method} for the current buffer. It also sets @code{default-input-method} to @var{input-method}. -If @var{input-method} is @code{nil}, this function deactivates any input +If @var{input-method} is @code{nil}, this command deactivates any input method for the current buffer. -@end defun +@end deffn @defun read-input-method-name prompt &optional default inhibit-null This function reads an input method name with the minibuffer, prompting @@ -1240,7 +1305,8 @@ it is good for. @end defvar The fundamental interface to input methods is through the -variable @code{input-method-function}. @xref{Reading One Event}. +variable @code{input-method-function}. @xref{Reading One Event}, +and @ref{Invoking the Input Method}. @node Locales @section Locales @@ -1294,14 +1360,14 @@ through @code{MON_12}). @item paper Return a list @code{(@var{width} @var{height})} for the default paper -size measured in milimeters (locale items @code{PAPER_WIDTH} and +size measured in millimeters (locale items @code{PAPER_WIDTH} and @code{PAPER_HEIGHT}). @end table If the system can't provide the requested information, or if @var{item} is not one of those symbols, the value is @code{nil}. All strings in the return value are decoded using -@code{locale-coding-system}. @xref{Locales,,, libc, GNU Libc Manual}, +@code{locale-coding-system}. @xref{Locales,,, libc, The GNU Libc Manual}, for more information about locales and locale items. @end defun From 136b1dff192e1b0345c5ac92b9ed2231af2e65e1 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:38:35 +0000 Subject: [PATCH 02/42] (Process Information): Add anchor. --- lispref/processes.texi | 1 + 1 file changed, 1 insertion(+) diff --git a/lispref/processes.texi b/lispref/processes.texi index c991cf300e3..8e32962de67 100644 --- a/lispref/processes.texi +++ b/lispref/processes.texi @@ -676,6 +676,7 @@ instead of a terminal (see @code{process-connection-type} in @ref{Asynchronous Processes}). @end defun +@anchor{Coding systems for a subprocess} @defun process-coding-system process This function returns a cons cell describing the coding systems in use for decoding output from @var{process} and for encoding input to From 636a7460c98ebbe224b2df8425fd6793a884b15a Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:42:52 +0000 Subject: [PATCH 03/42] (Function Indirection): Describe the errors that `indirect-function' can signal. (Eval): Clarify the descriptions of `eval-region' and `values'. Describe `eval-buffer' instead of `eval-current-buffer' and mention `eval-current-buffer' as an alias for `current-buffer'. Correct the description and mention all optional arguments. --- lispref/eval.texi | 56 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/lispref/eval.texi b/lispref/eval.texi index 165889e75ed..fcfde5849dd 100644 --- a/lispref/eval.texi +++ b/lispref/eval.texi @@ -319,6 +319,10 @@ This function returns the meaning of @var{function} as a function. If definition and starts over with that value. If @var{function} is not a symbol, then it returns @var{function} itself. +This function signals a @code{void-function} error if the final +symbol is unbound and a @code{cyclic-function-indirection} error if +there is a loop in the chain of symbols. + Here is how you could define @code{indirect-function} in Lisp: @smallexample @@ -625,32 +629,51 @@ The number of currently active calls to @code{eval} is limited to @code{max-lisp-eval-depth} (see below). @end defun +@anchor{Definition of eval-region} @deffn Command eval-region start end &optional stream read-function This function evaluates the forms in the current buffer in the region defined by the positions @var{start} and @var{end}. It reads forms from the region and calls @code{eval} on them until the end of the region is reached, or until an error is signaled and not handled. -If @var{stream} is non-@code{nil}, the values that result from -evaluating the expressions in the region are printed using @var{stream}. -@xref{Output Streams}. +By default, @code{eval-region} does not produce any output. However, +if @var{stream} is non-@code{nil}, any output produced by output +functions (@pxref{Output Functions}), as well as the values that +result from evaluating the expressions in the region are printed using +@var{stream}. @xref{Output Streams}. -If @var{read-function} is non-@code{nil}, it should be a function, which -is used instead of @code{read} to read expressions one by one. This -function is called with one argument, the stream for reading input. You -can also use the variable @code{load-read-function} (@pxref{How Programs -Do Loading}) to specify this function, but it is more robust to use the +If @var{read-function} is non-@code{nil}, it should be a function, +which is used instead of @code{read} to read expressions one by one. +This function is called with one argument, the stream for reading +input. You can also use the variable @code{load-read-function} +(@pxref{Definition of load-read-function,, How Programs Do Loading}) +to specify this function, but it is more robust to use the @var{read-function} argument. -@code{eval-region} always returns @code{nil}. +@code{eval-region} does not move point. It always returns @code{nil}. @end deffn @cindex evaluation of buffer contents -@deffn Command eval-current-buffer &optional stream -This is like @code{eval-region} except that it operates on the whole -buffer. +@deffn Command eval-buffer &optional buffer-or-name stream filename unibyte print +This is similar to @code{eval-region}, but the arguments provide +different optional features. @code{eval-buffer} operates on the +entire accessible portion of buffer @var{buffer-or-name}. +@var{buffer-or-name} can be a buffer, a buffer name (a string), or +@code{nil} (or omitted), which means to use the current buffer. +@var{stream} is used as in @code{eval-region}, unless @var{stream} is +@code{nil} and @var{print} non-@code{nil}. In that case, values that +result from evaluating the expressions are still discarded, but the +output of the output functions is printed in the echo area. +@var{filename} is the file name to use for @code{load-history} +(@pxref{Unloading}), and defaults to @code{buffer-file-name} +(@pxref{Buffer File Name}). If @var{unibyte} is non-@code{nil}, +@code{read} converts strings to unibyte whenever possible. + +@findex eval-current-buffer +@code{eval-current-buffer} is an alias for this command. @end deffn +@anchor{Definition of max-lisp-eval-depth} @defvar max-lisp-eval-depth This variable defines the maximum depth allowed in calls to @code{eval}, @code{apply}, and @code{funcall} before an error is signaled (with error @@ -670,14 +693,17 @@ Entry to the Lisp debugger increases the value, if there is little room left, to make sure the debugger itself has room to execute. @code{max-specpdl-size} provides another limit on nesting. -@xref{Local Variables}. +@xref{Definition of max-specpdl-size,, Local Variables}. @end defvar @defvar values The value of this variable is a list of the values returned by all the expressions that were read, evaluated, and printed from buffers -(including the minibuffer) by the standard Emacs commands which do this. -The elements are ordered most recent first. +(including the minibuffer) by the standard Emacs commands which do +this. (Note that this does @emph{not} include evaluation in +@samp{*ielm*} buffers, nor evaluation using @kbd{C-j} in +@code{lisp-interaction-mode}.) The elements are ordered most recent +first. @example @group From b51785c1212fceae6491be5e670dc4f935d91cde Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:45:43 +0000 Subject: [PATCH 04/42] (Lisp Data Types): Mention that certain variables can only take on a restricted set of values and add an xref to the new node "Variables with Restricted Values". --- lispref/objects.texi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lispref/objects.texi b/lispref/objects.texi index 4c905cb969e..6cb5adb72b8 100644 --- a/lispref/objects.texi +++ b/lispref/objects.texi @@ -42,7 +42,9 @@ it as a number; Lisp knows it is a vector, not a number. variable, and the type is known by the compiler but not represented in the data. Such type declarations do not exist in Emacs Lisp. A Lisp variable can have any type of value, and it remembers whatever value -you store in it, type and all. +you store in it, type and all. (Actually, a small number of Emacs +Lisp variables can only take on values of a certain type. +@xref{Variables with Restricted Values}.) This chapter describes the purpose, printed representation, and read syntax of each of the standard types in GNU Emacs Lisp. Details on how From 74ab3aa34adc0dc51e825e22fed1be7f89a09fbf Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:49:55 +0000 Subject: [PATCH 05/42] (Variables with Restricted Values): New node. --- lispref/variables.texi | 47 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/lispref/variables.texi b/lispref/variables.texi index 36cc2e47fe4..bbe7358b5d7 100644 --- a/lispref/variables.texi +++ b/lispref/variables.texi @@ -43,6 +43,8 @@ variable. * Future Local Variables:: New kinds of local values we might add some day. * Variable Aliases:: Variables that are aliases for other variables. * File Local Variables:: Handling local variable lists in files. +* Variables with Restricted Values:: Non-constant variables whose value can + @emph{not} be an arbitrary Lisp object. @end menu @node Global Variables @@ -258,19 +260,21 @@ These kinds of bindings work somewhat like ordinary local bindings, but they are localized depending on ``where'' you are in Emacs, rather than localized in time. +@anchor{Definition of max-specpdl-size} @defvar max-specpdl-size @cindex variable limit error @cindex evaluation error @cindex infinite recursion This variable defines the limit on the total number of local variable -bindings and @code{unwind-protect} cleanups (@pxref{Nonlocal Exits}) -that are allowed before signaling an error (with data @code{"Variable -binding depth exceeds max-specpdl-size"}). +bindings and @code{unwind-protect} cleanups (@pxref{Cleanups,, +Cleaning Up from Nonlocal Exits}) that are allowed before signaling an +error (with data @code{"Variable binding depth exceeds +max-specpdl-size"}). This limit, with the associated error when it is exceeded, is one way that Lisp avoids infinite recursion on an ill-defined function. @code{max-lisp-eval-depth} provides another limit on depth of nesting. -@xref{Eval}. +@xref{Definition of max-lisp-eval-depth,, Eval}. The default value is 600. Entry to the Lisp debugger increases the value, if there is little room left, to make sure the debugger itself @@ -1813,6 +1817,41 @@ could include functions to call. So Emacs discards all text properties from string values specified in a file's local variables list. +@node Variables with Restricted Values +@section Variables with Restricted Values + + Ordinary Lisp variables can be assigned any value that is a valid +Lisp object. However, certain Lisp variables are not defined in Lisp, +but in C. Most of these variables are defined in the C code using +@code{DEFVAR_LISP}. Like variables defined in Lisp, these can take on +any value. However, some variables are defined using +@code{DEFVAR_INT} or @code{DEFVAR_BOOL}. @xref{Defining Lisp +variables in C,, Writing Emacs Primitives}, in particular the +description of functions of the type @code{syms_of_@var{filename}}, +for a brief discussion of the C implementation. + + Variables of type @code{DEFVAR_BOOL} can only take on the values +@code{nil} or @code{t}. Attempting to assign them any other value +will set them to @code{t}: + +@example +(let ((display-hourglass 5)) + display-hourglass) + @result{} t +@end example + +@defvar byte-boolean-vars +This variable holds a list of all variables of type @code{DEFVAR_BOOL}. +@end defvar + + Variables of type @code{DEFVAR_INT} can only take on integer values. +Attempting to assign them any other value will result in an error: + +@example +(setq window-min-height 5.0) +@error{} Wrong type argument: integerp, 5.0 +@end example + @ignore arch-tag: 5ff62c44-2b51-47bb-99d4-fea5aeec5d3e @end ignore From 568ffbeed8969f6031d99b06c58b10bc963f8511 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:52:43 +0000 Subject: [PATCH 06/42] (Pure Storage): Mention that `purecopy' does not copy text properties. (Object Internals): Now 29 bits are used (in most implementations) to address Lisp objects. --- lispref/internals.texi | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lispref/internals.texi b/lispref/internals.texi index c8cf5ed0f7c..2a4572560a7 100644 --- a/lispref/internals.texi +++ b/lispref/internals.texi @@ -81,8 +81,9 @@ faster. On modern machines, it is usually not advisable. After @file{loadup.el} reads @file{site-load.el}, it finds the documentation strings for primitive and preloaded functions (and -variables) in the file @file{etc/DOC} where they are stored, by calling -@code{Snarf-documentation} (@pxref{Accessing Documentation}). +variables) in the file @file{etc/DOC} where they are stored, by +calling @code{Snarf-documentation} (@pxref{Definition of +Snarf-documentation,, Accessing Documentation}). @cindex @file{site-init.el} You can specify other Lisp expressions to execute just before dumping @@ -151,10 +152,10 @@ preload additional libraries or add features to the standard ones. @defun purecopy object This function makes a copy in pure storage of @var{object}, and returns it. It copies a string by simply making a new string with the same -characters in pure storage. It recursively copies the contents of -vectors and cons cells. It does not make copies of other objects such -as symbols, but just returns them unchanged. It signals an error if -asked to copy markers. +characters, but without text properties, in pure storage. It +recursively copies the contents of vectors and cons cells. It does +not make copies of other objects such as symbols, but just returns +them unchanged. It signals an error if asked to copy markers. This function is a no-op except while Emacs is being built and dumped; it is usually called only in the file @file{emacs/lisp/loaddefs.el}, but @@ -367,7 +368,7 @@ until the subsequent garbage collection, at which time @code{garbage-collect} will set the threshold back to 10,000. @end defopt - The value return by @code{garbage-collect} describes the amount of + The value returned by @code{garbage-collect} describes the amount of memory used by Lisp data, broken down by data type. By contrast, the function @code{memory-limit} provides information on the total amount of memory Emacs is currently using. @@ -595,9 +596,9 @@ protected in the current function. It is necessary to do this explicitly. GC-protected; as long as the object is not recycled, all pointers to it remain valid. So if you are sure that a local variable points to an object that will be preserved by some other pointer, that local -variable does not need a GCPRO. (Formerly, strings were an exception -to this rule; in older Emacs versions, every pointer to a string -needed to be marked by GC.) +variable does not need a @code{GCPRO}. (Formerly, strings were an +exception to this rule; in older Emacs versions, every pointer to a +string needed to be marked by GC.) The macro @code{GCPRO1} protects just one local variable. If you want to protect two, use @code{GCPRO2} instead; repeating @@ -612,7 +613,7 @@ Alas, we can't explain all the tricky details here. accept two arguments at the C level: the number of Lisp arguments, and a @code{Lisp_Object *} pointer to a C vector containing those Lisp arguments. This C vector may be part of a Lisp vector, but it need -not be. The responsibility for using GCPRO to protecting the Lisp +not be. The responsibility for using @code{GCPRO} to protect the Lisp arguments from GC if necessary rests with the caller in this case, since the caller allocated or found the storage for them. @@ -651,6 +652,7 @@ file, add to it a @code{syms_of_@var{filename}} (e.g., of these functions are called, and add a call to @code{syms_of_@var{filename}} there. +@anchor{Defining Lisp variables in C} @vindex byte-boolean-vars The function @code{syms_of_@var{filename}} is also the place to define any C variables that are to be visible as Lisp variables. @@ -761,9 +763,9 @@ knows about it. data are stored in a heap and the only access that programs have to it is through pointers. Pointers are thirty-two bits wide in most implementations. Depending on the operating system and type of machine -for which you compile Emacs, twenty-eight bits are used to address the -object, and the remaining four bits are used for a GC mark bit and the -tag that identifies the object's type. +for which you compile Emacs, twenty-nine bits are used to address the +object, and the remaining three bits are used for the tag that +identifies the object's type. Because Lisp objects are represented as tagged pointers, it is always possible to determine the Lisp data type of any object. The C data type From 4bdcd3ef21b00a16d1ea1edb2508df8c63d17069 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:54:16 +0000 Subject: [PATCH 07/42] Replace all occurrences of @acronym{CAR} with @sc{car}, for consistency with the rest of the Elisp manual. `car' and `cdr' are historically acronyms, but are no longer widely thought of as such. --- lispref/commands.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lispref/commands.texi b/lispref/commands.texi index a2838c68bb9..a46ff938e3a 100644 --- a/lispref/commands.texi +++ b/lispref/commands.texi @@ -1096,7 +1096,7 @@ arguments to the key-binding lookup and modification functions. Emacs supports four kinds of mouse events: click events, drag events, button-down events, and motion events. All mouse events are represented -as lists. The @acronym{CAR} of the list is the event type; this says which +as lists. The @sc{car} of the list is the event type; this says which mouse button was involved, and which modifier keys were used with it. The event type can also distinguish double or triple button presses (@pxref{Repeat Events}). The rest of the list elements give position @@ -1560,7 +1560,7 @@ into another window. That produces a pair of events like these: key binding purposes. For a keyboard event, the event type equals the event value; thus, the event type for a character is the character, and the event type for a function key symbol is the symbol itself. For -events that are lists, the event type is the symbol in the @acronym{CAR} of +events that are lists, the event type is the symbol in the @sc{car} of the list. Thus, the event type is always a symbol or a character. Two events of the same type are equivalent where key bindings are @@ -2583,7 +2583,7 @@ This function returns the numeric meaning of a valid raw prefix argument value, @var{arg}. The argument may be a symbol, a number, or a list. If it is @code{nil}, the value 1 is returned; if it is @code{-}, the value @minus{}1 is returned; if it is a number, that number is returned; -if it is a list, the @acronym{CAR} of that list (which should be a number) is +if it is a list, the @sc{car} of that list (which should be a number) is returned. @end defun From 1bff11dc2774c1bdcbe8e8758c50c16197e52153 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:57:38 +0000 Subject: [PATCH 08/42] (Accessing Documentation): Add anchor. --- lispref/help.texi | 1 + 1 file changed, 1 insertion(+) diff --git a/lispref/help.texi b/lispref/help.texi index 7675e38e81e..343ffb66078 100644 --- a/lispref/help.texi +++ b/lispref/help.texi @@ -259,6 +259,7 @@ as shown above for the @code{goal-column} variable, means that it is a user option; see the description of @code{defvar} in @ref{Defining Variables}. +@anchor{Definition of Snarf-documentation} @defun Snarf-documentation filename This function is used only during Emacs initialization, just before the runnable Emacs is dumped. It finds the file offsets of the From da9f5ab259d318537f08bb7942e7f31e4d6ad9c9 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 03:59:14 +0000 Subject: [PATCH 09/42] (How Programs Do Loading): Add anchor. --- lispref/loading.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lispref/loading.texi b/lispref/loading.texi index 0865914c45d..e171fc70fdf 100644 --- a/lispref/loading.texi +++ b/lispref/loading.texi @@ -140,6 +140,7 @@ This variable is non-@code{nil} if Emacs is in the process of loading a file, and it is @code{nil} otherwise. @end defvar +@anchor{Definition of load-read-function} @defvar load-read-function This variable specifies an alternate expression-reading function for @code{load} and @code{eval-region} to use instead of @code{read}. @@ -150,7 +151,7 @@ functions should use @code{read}. Instead of using this variable, it is cleaner to use another, newer feature: to pass the function as the @var{read-function} argument to -@code{eval-region}. @xref{Eval}. +@code{eval-region}. @xref{Definition of eval-region,, Eval}. @end defvar For information about how @code{load} is used in building Emacs, see From 70057f39ff1190a07a3815052b038ebd6a8e2b9b Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 04:00:56 +0000 Subject: [PATCH 10/42] (Documentation Tips): Add anchor. --- lispref/tips.texi | 1 + 1 file changed, 1 insertion(+) diff --git a/lispref/tips.texi b/lispref/tips.texi index 1b40685ba5d..ec53dc420dd 100644 --- a/lispref/tips.texi +++ b/lispref/tips.texi @@ -647,6 +647,7 @@ The argument FOO can be either a number This prevents the open-parenthesis from being treated as the start of a defun (@pxref{Defuns,, Defuns, emacs, The GNU Emacs Manual}). +@anchor{Docstring hyperlinks} @item @iftex When a documentation string refers to a Lisp symbol, write it as it From 68e74f257897da0025f3236a58d61949e6dfe137 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 04:03:49 +0000 Subject: [PATCH 11/42] *** empty log message *** --- lispref/ChangeLog | 46 +++++++++++++++++++++++++++++++++++++++++++- lispref/display.texi | 5 +++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lispref/ChangeLog b/lispref/ChangeLog index 85a5f506739..753c02afd46 100644 --- a/lispref/ChangeLog +++ b/lispref/ChangeLog @@ -1,3 +1,47 @@ +2003-12-24 Luc Teirlinck + + * display.texi, eval.texi, help.texi, internals.texi, loading.texi: + * nonascii.texi, processes.texi, tips.texi, variables.texi: + Add or change various xrefs and anchors. + + * commands.texi: Replace all occurrences of @acronym{CAR} with + @sc{car}, for consistency with the rest of the Elisp manual. + `car' and `cdr' are historically acronyms, but are no longer + widely thought of as such. + + * internals.texi (Pure Storage): Mention that `purecopy' does not + copy text properties. + (Object Internals): Now 29 bits are used (in most implementations) + to address Lisp objects. + + * variables.texi (Variables with Restricted Values): New node. + + * objects.texi (Lisp Data Types): Mention that certain variables + can only take on a restricted set of values and add an xref to + the new node "Variables with Restricted Values". + + * eval.texi (Function Indirection): Describe the errors that + `indirect-function' can signal. + (Eval): Clarify the descriptions of `eval-region' and `values'. + Describe `eval-buffer' instead of `eval-current-buffer' and + mention `eval-current-buffer' as an alias for `current-buffer'. + Correct the description and mention all optional arguments. + + * nonascii.texi : Various small changes in addition to the + following. + (Converting Representations): Clarify behavior of + `string-make-multibyte' and `string-to-multibyte' for unibyte all + ASCII arguments. + (Character Sets): Document the variable `charset-list' and adapt + the definition of the function `charset-list' accordingly. + (Translation of Characters): Clarify use of generic characters in + `make-translation-table'. Clarify and correct the description of + the use of translation tables in encoding and decoding. + (User-Chosen Coding Systems): Correct and clarify the description + of `select-safe-coding-system'. + (Default Coding Systems): Clarify description of + `file-coding-system-alist'. + 2003-11-30 Luc Teirlinck * strings.texi (Text Comparison): Correctly describe when two @@ -42,7 +86,7 @@ 2003-11-20 Luc Teirlinck - * positions.texi (Positions): Mention that, if a marker is used a + * positions.texi (Positions): Mention that, if a marker is used as a position, its buffer is ignored. * markers.texi (Overview of Markers): Mention it here too. diff --git a/lispref/display.texi b/lispref/display.texi index 186703b13b0..449a42b18c5 100644 --- a/lispref/display.texi +++ b/lispref/display.texi @@ -805,8 +805,9 @@ If the @var{forms} do not change the major mode in the output buffer, so that it is still Help mode at the end of their execution, then @code{with-output-to-temp-buffer} makes this buffer read-only at the end, and also scans it for function and variable names to make them -into clickable cross-references. @xref{Documentation Tips, , Tips for -Documentation Strings}. +into clickable cross-references. @xref{Docstring hyperlinks, , Tips +for Documentation Strings}, in particular the item on hyperlinks in +documentation strings, for more details. The string @var{buffer-name} specifies the temporary buffer, which need not already exist. The argument must be a string, not a buffer. From 070b546b23ff2bf27c1cbe15aaff285fe9dfe29a Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 04:20:44 +0000 Subject: [PATCH 12/42] Remove trailing whitespace --- lispref/nonascii.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lispref/nonascii.texi b/lispref/nonascii.texi index 0c07b394e93..e66c7d15757 100644 --- a/lispref/nonascii.texi +++ b/lispref/nonascii.texi @@ -732,7 +732,7 @@ except for its eol conversion, which is specified by @code{eol-type}. the end-of-line conversion from the data. @var{eol-type} may also be 0, 1 or 2, standing for @code{unix}, -@code{dos} and @code{mac}, respectively. +@code{dos} and @code{mac}, respectively. @end defun @defun coding-system-change-text-conversion eol-coding text-coding From 077347180056db5004312e8c095f4d524766bf80 Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 04:52:54 +0000 Subject: [PATCH 13/42] Remove trailing whitespace. --- lispref/commands.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lispref/commands.texi b/lispref/commands.texi index a46ff938e3a..a8350b88d82 100644 --- a/lispref/commands.texi +++ b/lispref/commands.texi @@ -1172,7 +1172,7 @@ which the click occurred. It is one of the symbols @code{mode-line}, @item @var{x}, @var{y} These are the pixel-denominated coordinates of the click, relative to -the top left corner of @var{window}, which is @code{(0 . 0)}. +the top left corner of @var{window}, which is @code{(0 . 0)}. For the mode or header line, @var{y} does not have meaningful data. For the vertical line, @var{x} does not have meaningful data. @@ -1188,7 +1188,7 @@ an image object as returned by @code{find-image} if click was in an image. @item @var{string} This is the string on which the click occurred, including any -properties. +properties. @item @var{string-pos} This is the position in the string on which the click occurred, From 8290faa335bcb23063c9ee355ccfa1b6def202c6 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Thu, 25 Dec 2003 11:06:14 +0000 Subject: [PATCH 14/42] (jka-compr-insert-file-contents): Avoid error when file not found. --- lisp/ChangeLog | 5 +++++ lisp/jka-compr.el | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 5c667e0b353..a865e943a11 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2003-12-25 Andreas Schwab + + * jka-compr.el (jka-compr-insert-file-contents): Avoid error when + file not found. + 2003-12-08 Miles Bader * dired.el (dired-between-files): Always use dired-move-to-filename, diff --git a/lisp/jka-compr.el b/lisp/jka-compr.el index dd56c9c0f31..aae0f0f85c1 100644 --- a/lisp/jka-compr.el +++ b/lisp/jka-compr.el @@ -590,10 +590,11 @@ There should be no more than seven characters after the final `/'." (file-exists-p local-copy) (delete-file local-copy))) - (decode-coding-inserted-region - (point) (+ (point) size) - (jka-compr-byte-compiler-base-file-name file) - visit beg end replace) + (unless notfound + (decode-coding-inserted-region + (point) (+ (point) size) + (jka-compr-byte-compiler-base-file-name file) + visit beg end replace)) (and visit From 56ffd194371f38239589eb0f818682a0b2e0dbac Mon Sep 17 00:00:00 2001 From: Thien-Thi Nguyen Date: Thu, 25 Dec 2003 12:13:59 +0000 Subject: [PATCH 15/42] (tgetst1): Scan for "%pN"; if all N are continuous in [1,9], remove all "%pN". --- src/ChangeLog | 5 +++++ src/termcap.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/ChangeLog b/src/ChangeLog index 4adadd84db1..f3b9d0f81ea 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2003-12-25 Thien-Thi Nguyen + + * termcap.c (tgetst1): Scan for "%pN"; if all + N are continuous in [1,9], remove all "%pN". + 2003-12-24 Jan Dj,Ad(Brv * gtkutil.c (xg_frame_set_char_size): Call x_wm_set_size_hint. diff --git a/src/termcap.c b/src/termcap.c index b1e0a87936e..a1c068e0964 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -284,6 +284,52 @@ tgetst1 (ptr, area) } *r++ = c; } + + /* Sometimes entries have "%pN" which means use parameter N in the + next %-substitution. If all such N are continuous in the range + [1,9] we can remove each "%pN" because they are redundant, thus + reducing bandwidth requirements. True, Emacs is well beyond the + days of 150baud teletypes, but some of its users aren't much so. + + This pass could probably be integrated into the one above but + abbreviation expansion makes that effort a little more hairy than + its worth; this is cleaner. */ + { + register int last_p_param = 0; + int remove_p_params = 1; + struct { char *beg; int len; } cut[11]; + + for (cut[0].beg = p = ret; p < r - 3; p++) + { + if (!remove_p_params) + break; + if (*p == '%' && *(p + 1) == 'p') + { + if (*(p + 2) - '0' == 1 + last_p_param) + { + cut[last_p_param].len = p - cut[last_p_param].beg; + last_p_param++; + p += 3; + cut[last_p_param].beg = p; + } + else /* not continuous: bail */ + remove_p_params = 0; + if (last_p_param > 10) /* too many: bail */ + remove_p_params = 0; + } + } + if (remove_p_params && last_p_param) + { + register int i; + char *wp; + + cut[last_p_param].len = r - cut[last_p_param].beg; + for (i = 0, wp = ret; i <= last_p_param; wp += cut[i++].len) + bcopy (cut[i].beg, wp, cut[i].len); + r = wp; + } + } + *r = '\0'; /* Update *AREA. */ if (area) From 67fafe38b4adee614a20f50d33849631e0ab82f5 Mon Sep 17 00:00:00 2001 From: Markus Rost Date: Thu, 25 Dec 2003 14:10:31 +0000 Subject: [PATCH 16/42] (Fringes): Fix typo "set-buffer-window" -> "set-window-buffer". --- lispref/ChangeLog | 4 ++++ lispref/display.texi | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lispref/ChangeLog b/lispref/ChangeLog index 753c02afd46..1b9aabffe46 100644 --- a/lispref/ChangeLog +++ b/lispref/ChangeLog @@ -1,3 +1,7 @@ +2003-12-25 Markus Rost + + * display.texi (Fringes): Fix typo "set-buffer-window". + 2003-12-24 Luc Teirlinck * display.texi, eval.texi, help.texi, internals.texi, loading.texi: diff --git a/lispref/display.texi b/lispref/display.texi index 449a42b18c5..abbbab0ce79 100644 --- a/lispref/display.texi +++ b/lispref/display.texi @@ -2528,7 +2528,7 @@ fringe in pixels. The values of these variables take effect when you display the buffer in a window. If you change them while the buffer is visible, -you can call @code{set-buffer-window} to display it in a window again. +you can call @code{set-window-buffer} to display it in a window again. @defun set-window-fringes window left &optional right outside-margins This function sets the fringe widthes of window @var{window}. From b91485007d4c4fd637291364eecd363e1cecfa9d Mon Sep 17 00:00:00 2001 From: Lars Hansen Date: Thu, 25 Dec 2003 17:12:59 +0000 Subject: [PATCH 17/42] (Fdirectory_files, Fdirectory_files_and_attributes): Arguments GCPRO'ed in call to file name handler. --- src/ChangeLog | 5 +++++ src/dired.c | 27 ++++----------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index f3b9d0f81ea..1d153f72530 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2003-12-25 Lars Hansen + + * dired.c (Fdirectory_files, Fdirectory_files_and_attributes): + Arguments GCPRO'ed in call to file name handler. + 2003-12-25 Thien-Thi Nguyen * termcap.c (tgetst1): Scan for "%pN"; if all diff --git a/src/dired.c b/src/dired.c index 52a19f4fdc6..3bcd3051c25 100644 --- a/src/dired.c +++ b/src/dired.c @@ -359,17 +359,8 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable. call the corresponding file handler. */ handler = Ffind_file_name_handler (directory, Qdirectory_files); if (!NILP (handler)) - { - Lisp_Object args[6]; - - args[0] = handler; - args[1] = Qdirectory_files; - args[2] = directory; - args[3] = full; - args[4] = match; - args[5] = nosort; - return Ffuncall (6, args); - } + return call5 (handler, Qdirectory_files, directory, + full, match, nosort); return directory_files_internal (directory, full, match, nosort, 0, Qnil); } @@ -395,18 +386,8 @@ ID-FORMAT specifies the preferred format of attributes uid and gid, see call the corresponding file handler. */ handler = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes); if (!NILP (handler)) - { - Lisp_Object args[7]; - - args[0] = handler; - args[1] = Qdirectory_files_and_attributes; - args[2] = directory; - args[3] = full; - args[4] = match; - args[5] = nosort; - args[6] = id_format; - return Ffuncall (7, args); - } + return call6 (handler, Qdirectory_files_and_attributes, + directory, full, match, nosort, id_format); return directory_files_internal (directory, full, match, nosort, 1, id_format); } From 86408abdf4871166dadc6694cfa309244a4c46fb Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 17:31:23 +0000 Subject: [PATCH 18/42] (Fcompleting_read): Undo previous change. --- src/minibuf.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/minibuf.c b/src/minibuf.c index 4c98f7ba708..baeb0cef7b5 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -1578,10 +1578,13 @@ Completion ignores case if the ambient value of Lisp_Object prompt, table, predicate, require_match, initial_input; Lisp_Object hist, def, inherit_input_method; { - Lisp_Object val, histvar, histpos; + Lisp_Object val, histvar, histpos, position; + Lisp_Object init; + int pos = 0; int count = SPECPDL_INDEX (); struct gcpro gcpro1; + init = initial_input; GCPRO1 (def); specbind (Qminibuffer_completion_table, table); @@ -1590,6 +1593,23 @@ Completion ignores case if the ambient value of EQ (require_match, Qt) ? Qnil : require_match); last_exact_completion = Qnil; + position = Qnil; + if (!NILP (init)) + { + if (CONSP (init)) + { + position = Fcdr (init); + init = Fcar (init); + } + CHECK_STRING (init); + if (!NILP (position)) + { + CHECK_NUMBER (position); + /* Convert to distance from end of input. */ + pos = XINT (position) - SCHARS (init); + } + } + if (SYMBOLP (hist)) { histvar = hist; @@ -1608,7 +1628,7 @@ Completion ignores case if the ambient value of val = read_minibuf (NILP (require_match) ? Vminibuffer_local_completion_map : Vminibuffer_local_must_match_map, - initial_input, prompt, Qnil, 0, + init, prompt, make_number (pos), 0, histvar, histpos, def, 0, !NILP (inherit_input_method)); From 7b86ef7dbb2e9e72e8fffcd2acec769f306a276d Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 17:44:48 +0000 Subject: [PATCH 19/42] (ffap-read-file-or-url): Revert previous change. --- lisp/ffap.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/ffap.el b/lisp/ffap.el index b249ce8daa0..668700a5c1f 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1216,7 +1216,7 @@ which may actually result in an url rather than a filename." 'ffap-read-file-or-url-internal dir nil - (if dir (cons guess (1+ (length dir))) guess) + (if dir (cons guess (length dir)) guess) (list 'file-name-history)))) ;; Do file substitution like (interactive "F"), suggested by MCOOK. (or (ffap-url-p guess) (setq guess (substitute-in-file-name guess))) From fc052137c5511debc81094aab706ccf1d6a7581f Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 18:07:44 +0000 Subject: [PATCH 20/42] *** empty log message *** --- lisp/ChangeLog | 4 ++++ src/ChangeLog | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index a865e943a11..da52c2aa190 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,7 @@ +2003-12-25 Luc Teirlinck + + * ffap.el (ffap-read-file-or-url): Revert previous change. + 2003-12-25 Andreas Schwab * jka-compr.el (jka-compr-insert-file-contents): Avoid error when diff --git a/src/ChangeLog b/src/ChangeLog index 1d153f72530..fc1445a46dd 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2003-12-25 Luc Teirlinck + + * minibuf.c (Fcompleting_read): Undo previous change. + 2003-12-25 Lars Hansen * dired.c (Fdirectory_files, Fdirectory_files_and_attributes): From d7fc69d16f9aa806b6c73fc6967f1ad62309fa67 Mon Sep 17 00:00:00 2001 From: "Robert J. Chassell" Date: Thu, 25 Dec 2003 20:20:50 +0000 Subject: [PATCH 21/42] (texinfo-multi-file-update): create a new list of included files, called `files-with-node-lines', that only have node lines. This way @include commands can include any file, such as version and update files without node lines, not just files that are chapters. --- lisp/textmodes/texnfo-upd.el | 39 ++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el index fb44acbff4f..17b0affac92 100644 --- a/lisp/textmodes/texnfo-upd.el +++ b/lisp/textmodes/texnfo-upd.el @@ -1,6 +1,6 @@ ;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files -;; Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2003 Free Software Foundation, Inc. ;; Author: Robert J. Chassell ;; Maintainer: bug-texinfo@gnu.org @@ -1795,25 +1795,34 @@ Thus, normally, each included file contains one, and only one, chapter." ;; description slot of a menu as a description. (let ((case-fold-search t) - menu-list next-node-name previous-node-name) + menu-list next-node-name previous-node-name files-with-node-lines) - ;; Find the name of the first node of the first included file. - (set-buffer (find-file-noselect (car (cdr files)))) + ;; Create a new list of included files that only have node lines + (while files + (set-buffer (find-file-noselect (car files))) + (widen) + (goto-char (point-min)) + (when (re-search-forward "^@node" nil t) + (setq files-with-node-lines (cons (car files) files-with-node-lines))) + (setq files (cdr files))) + (setq files-with-node-lines (nreverse files-with-node-lines)) + + ;; Find the name of the first node in a subsequent file + ;; and copy it into the variable next-node-name + (set-buffer (find-file-noselect (car (cdr files-with-node-lines)))) (widen) (goto-char (point-min)) - (if (not (re-search-forward "^@node" nil t)) - (error "No `@node' line found in %s" (buffer-name))) (beginning-of-line) (texinfo-check-for-node-name) (setq next-node-name (texinfo-copy-node-name)) - (push (cons next-node-name (prog1 "" (forward-line 1))) ;; Use following to insert section titles automatically. ;; (texinfo-copy-next-section-title) menu-list) ;; Go to outer file - (set-buffer (find-file-noselect (pop files))) + ;; `pop' is analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE))) + (set-buffer (find-file-noselect (pop files-with-node-lines))) (goto-char (point-min)) (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)) (error "This buffer needs a Top node")) @@ -1824,18 +1833,16 @@ Thus, normally, each included file contains one, and only one, chapter." (beginning-of-line) (setq previous-node-name "Top") - (while files + (while files-with-node-lines - (if (not (cdr files)) + (if (not (cdr files-with-node-lines)) ;; No next file (setq next-node-name "") ;; Else, ;; find the name of the first node in the next file. - (set-buffer (find-file-noselect (car (cdr files)))) + (set-buffer (find-file-noselect (car (cdr files-with-node-lines)))) (widen) (goto-char (point-min)) - (if (not (re-search-forward "^@node" nil t)) - (error "No `@node' line found in %s" (buffer-name))) (beginning-of-line) (texinfo-check-for-node-name) (setq next-node-name (texinfo-copy-node-name)) @@ -1845,10 +1852,8 @@ Thus, normally, each included file contains one, and only one, chapter." menu-list)) ;; Go to node to be updated. - (set-buffer (find-file-noselect (car files))) + (set-buffer (find-file-noselect (car files-with-node-lines))) (goto-char (point-min)) - (if (not (re-search-forward "^@node" nil t)) - (error "No `@node' line found in %s" (buffer-name))) (beginning-of-line) ;; Update other menus and nodes if requested. @@ -1862,7 +1867,7 @@ Thus, normally, each included file contains one, and only one, chapter." (beginning-of-line) (setq previous-node-name (texinfo-copy-node-name)) - (setq files (cdr files))) + (setq files-with-node-lines (cdr files-with-node-lines))) (nreverse menu-list))) (defun texinfo-multi-files-insert-main-menu (menu-list) From c7211bc5311e640b212da5c3bf780ac10ce5a08f Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Fri, 26 Dec 2003 11:39:22 +0000 Subject: [PATCH 22/42] *** empty log message *** --- src/composite.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/composite.c b/src/composite.c index b4e931c6a20..f8e655a3685 100644 --- a/src/composite.c +++ b/src/composite.c @@ -842,9 +842,12 @@ syms_of_composite () args[0] = QCtest; args[1] = Qequal; + /* We used to make the hash table weak so that unreferenced + compostions can be garbage-collected. But, usually once + created compositions are repeatedly used in an Emacs session, + and thus it's not worth to save memory in such a way. So, we + make the table not weak. */ args[2] = QCweakness; - /* Fixme: It seems that a weak hash table leads to segfault in GC, - but I have not yet found why. -- handa@m17n.org */ args[3] = Qnil; args[4] = QCsize; args[5] = make_number (311); From c91406620cbf11dd9293ac52d6ee55f3dcf2a5fd Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 27 Dec 2003 08:18:42 +0000 Subject: [PATCH 23/42] (rlog_options): Append -rbranchtag if CVS/Tag indicates a tag, and if the user has not specified an rlog option. Adapted from a suggestion by Martin Stjernholm in . (Copyright): Update to 2003. --- lib-src/ChangeLog | 10 +++++++++- lib-src/rcs2log | 26 +++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 1a0774e7e57..542761fda2f 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,11 @@ +2003-12-27 Paul Eggert + + * rcs2log (rlog_options): Append -rbranchtag if CVS/Tag indicates + a tag, and if the user has not specified an rlog option. + Adapted from a suggestion by Martin Stjernholm in + . + (Copyright): Update to 2003. + 2003-12-24 Thien-Thi Nguyen * make-docfile.c (main): For return code, no longer special-case VMS. @@ -5461,7 +5469,7 @@ Tue Jul 1 01:09:07 1997 Geoff Voelker ;; coding: iso-2022-7bit ;; End: - Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002 + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. diff --git a/lib-src/rcs2log b/lib-src/rcs2log index 86a3f6722cd..9528e6b1d9c 100755 --- a/lib-src/rcs2log +++ b/lib-src/rcs2log @@ -29,9 +29,9 @@ Options: Report bugs to .' -Id='$Id: rcs2log,v 1.50 2002/02/03 17:31:31 eggert Exp $' +Id='$Id: rcs2log,v 1.51 2003/09/01 15:45:03 miles Exp $' -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2002 +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2002, 2003 # Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify @@ -49,7 +49,7 @@ Id='$Id: rcs2log,v 1.50 2002/02/03 17:31:31 eggert Exp $' # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -Copyright='Copyright (C) 2002 Free Software Foundation, Inc. +Copyright='Copyright (C) 2003 Free Software Foundation, Inc. This program comes with NO WARRANTY, to the extent permitted by law. You may redistribute copies of this program under the terms of the GNU General Public License. @@ -195,8 +195,9 @@ case $rlogfile in # If no rlog options are given, # log the revisions checked in since the first ChangeLog entry. - # Since ChangeLog is only by date, some of these revisions may be duplicates of - # what's already in ChangeLog; it's the user's responsibility to remove them. + # Since ChangeLog is only by date, some of these revisions may be + # duplicates of what's already in ChangeLog; it's the user's + # responsibility to remove them. case $rlog_options in '') if test -s "$changelog" @@ -281,6 +282,21 @@ case $rlogfile in esac done + # If no rlog options are given, and if we are in a tagged CVS branch, + # log only the changes in that branch. + case $rlog_options in + '') + if test -f CVS/Tag + then + CVSTAG=`cat &2 "$0: invalid CVS/Tag"; exit 1;; + esac + fi;; + esac fi # Use $rlog's -zLT option, if $rlog supports it. From cfa921fd39a965d78ee9ebfe8855afee524b1987 Mon Sep 17 00:00:00 2001 From: Per Abrahamsen Date: Sat, 27 Dec 2003 16:41:13 +0000 Subject: [PATCH 24/42] 2003-12-12 Jesper Harder * cus-edit.el (custom-add-parent-links): Define "many". 2003-12-08 Per Abrahamsen * wid-edit.el (widget-child-value-get, widget-child-value-inline) (widget-child-validate, widget-type-value-create) (widget-type-default-get, widget-type-match): New functions. (lazy): New widget. (menu-choice, checklist, radio-button-choice, editable-list) (group, documentation-string): Removed redundant (per 2003-10-25 change) calls to `widget-children-value-delete'. (widget-choice-value-get, widget-choice-value-inline): Removed functions. (menu-choice): Updated widget. --- lisp/ChangeLog | 17 +++++++ lisp/cus-edit.el | 3 +- lisp/wid-edit.el | 110 +++++++++++++++++++++++++++++++++++------ lispref/customize.texi | 73 ++++++++++++++++++++++++++- 4 files changed, 185 insertions(+), 18 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index da52c2aa190..a2e7f95747c 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -76,6 +76,23 @@ * info.el (Info-unescape-quotes, Info-split-parameter-string) (Info-goto-emacs-command-node): Doc fixes. +2003-12-12 Jesper Harder + + * cus-edit.el (custom-add-parent-links): Define "many". + +2003-12-08 Per Abrahamsen + + * wid-edit.el (widget-child-value-get, widget-child-value-inline) + (widget-child-validate, widget-type-value-create) + (widget-type-default-get, widget-type-match): New functions. + (lazy): New widget. + (menu-choice, checklist, radio-button-choice, editable-list) + (group, documentation-string): Removed redundant (per 2003-10-25 + change) calls to `widget-children-value-delete'. + (widget-choice-value-get, widget-choice-value-inline): Removed + functions. + (menu-choice): Updated widget. + 2003-12-03 Kenichi Handa * language/cyrillic.el: Register "microsoft-cp1251" in diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index bf92e8df9cf..fc5e7ecb8af 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1970,7 +1970,8 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"." (setq parents (cons symbol parents)))))) (and (null (get symbol 'custom-links)) ;No links of its own. (= (length parents) 1) ;A single parent. - (let ((links (get (car parents) 'custom-links))) + (let* ((links (get (car parents) 'custom-links)) + (many (> (length links) 2))) (when links (insert "\nParent documentation: ") (while links diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 4c70334e908..63a254d1d67 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -1267,6 +1267,42 @@ Optional EVENT is the event that triggered the action." found (widget-apply child :validate))) found)) +(defun widget-child-value-get (widget) + "Get the value of the first member of :children in WIDGET." + (widget-value (car (widget-get widget :children)))) + +(defun widget-child-value-inline (widget) + "Get the inline value of the first member of :children in WIDGET." + (widget-apply (car (widget-get widget :children)) :value-inline)) + +(defun widget-child-validate (widget) + "The result of validating the first member of :children in WIDGET." + (widget-apply (car (widget-get widget :children)) :validate)) + +(defun widget-type-value-create (widget) + "Convert and instantiate the value of the :type attribute of WIDGET. +Store the newly created widget in the :children attribute. + +The value of the :type attribute should be an unconverted widget type." + (let ((value (widget-get widget :value)) + (type (widget-get widget :type))) + (widget-put widget :children + (list (widget-create-child-value widget + (widget-convert type) + value))))) + +(defun widget-type-default-get (widget) + "Get default value from the :type attribute of WIDGET. + +The value of the :type attribute should be an unconverted widget type." + (widget-default-get (widget-convert (widget-get widget :type)))) + +(defun widget-type-match (widget value) + "Non-nil if the :type value of WIDGET matches VALUE. + +The value of the :type attribute should be an unconverted widget type." + (widget-apply (widget-convert (widget-get widget :type)) :match value)) + (defun widget-types-copy (widget) "Copy :args as widget types in WIDGET." (widget-put widget :args (mapcar 'widget-copy (widget-get widget :args))) @@ -1862,9 +1898,8 @@ the earlier input." :tag "choice" :void '(item :format "invalid (%t)\n") :value-create 'widget-choice-value-create - :value-delete 'widget-children-value-delete - :value-get 'widget-choice-value-get - :value-inline 'widget-choice-value-inline + :value-get 'widget-child-value-get + :value-inline 'widget-child-value-inline :default-get 'widget-choice-default-get :mouse-down-action 'widget-choice-mouse-down-action :action 'widget-choice-action @@ -1901,14 +1936,6 @@ the earlier input." widget void :value value))) (widget-put widget :choice void)))))) -(defun widget-choice-value-get (widget) - ;; Get value of the child widget. - (widget-value (car (widget-get widget :children)))) - -(defun widget-choice-value-inline (widget) - ;; Get value of the child widget. - (widget-apply (car (widget-get widget :children)) :value-inline)) - (defun widget-choice-default-get (widget) ;; Get default for the first choice. (widget-default-get (car (widget-get widget :args)))) @@ -2099,7 +2126,6 @@ when he invoked the menu." :entry-format "%b %v" :greedy nil :value-create 'widget-checklist-value-create - :value-delete 'widget-children-value-delete :value-get 'widget-checklist-value-get :validate 'widget-checklist-validate :match 'widget-checklist-match @@ -2276,7 +2302,6 @@ Return an alist of (TYPE MATCH)." :format "%v" :entry-format "%b %v" :value-create 'widget-radio-value-create - :value-delete 'widget-children-value-delete :value-get 'widget-radio-value-get :value-inline 'widget-radio-value-inline :value-set 'widget-radio-value-set @@ -2466,7 +2491,6 @@ Return an alist of (TYPE MATCH)." :format-handler 'widget-editable-list-format-handler :entry-format "%i %d %v" :value-create 'widget-editable-list-value-create - :value-delete 'widget-children-value-delete :value-get 'widget-editable-list-value-get :validate 'widget-children-validate :match 'widget-editable-list-match @@ -2637,7 +2661,6 @@ Return an alist of (TYPE MATCH)." :copy 'widget-types-copy :format "%v" :value-create 'widget-group-value-create - :value-delete 'widget-children-value-delete :value-get 'widget-editable-list-value-get :default-get 'widget-group-default-get :validate 'widget-children-validate @@ -2803,7 +2826,6 @@ link for that string." "A documentation string." :format "%v" :action 'widget-documentation-string-action - :value-delete 'widget-children-value-delete :value-create 'widget-documentation-string-value-create) (defun widget-documentation-string-value-create (widget) @@ -3250,6 +3272,62 @@ To use this type, you must define :match or :match-alternatives." (widget-group-match widget (widget-apply widget :value-to-internal value)))) +;;; The `lazy' Widget. +;; +;; Recursive datatypes. + +(define-widget 'lazy 'default + "Base widget for recursive datastructures. + +The `lazy' widget will, when instantiated, contain a single inferior +widget, of the widget type specified by the :type parameter. The +value of the `lazy' widget is the same as the value of the inferior +widget. When deriving a new widget from the 'lazy' widget, the :type +parameter is allowed to refer to the widget currently being defined, +thus allowing recursive datastructures to be described. + +The :type parameter takes the same arguments as the defcustom +parameter with the same name. + +Most composite widgets, i.e. widgets containing other widgets, does +not allow recursion. That is, when you define a new widget type, none +of the inferior widgets may be of the same type you are currently +defining. + +In Lisp, however, it is custom to define datastructures in terms of +themselves. A list, for example, is defined as either nil, or a cons +cell whose cdr itself is a list. The obvious way to translate this +into a widget type would be + + (define-widget 'my-list 'choice + \"A list of sexps.\" + :tag \"Sexp list\" + :args '((const nil) (cons :value (nil) sexp my-list))) + +Here we attempt to define my-list as a choice of either the constant +nil, or a cons-cell containing a sexp and my-lisp. This will not work +because the `choice' widget does not allow recursion. + +Using the `lazy' widget you can overcome this problem, as in this +example: + + (define-widget 'sexp-list 'lazy + \"A list of sexps.\" + :tag \"Sexp list\" + :type '(choice (const nil) (cons :value (nil) sexp sexp-list)))" + :format "%{%t%}: %v" + ;; We don't convert :type because we want to allow recursive + ;; datastructures. This is slow, so we should not create speed + ;; critical widgets by deriving from this. + :convert-widget 'widget-value-convert-widget + :value-create 'widget-type-value-create + :value-get 'widget-child-value-get + :value-inline 'widget-child-value-inline + :default-get 'widget-type-default-get + :match 'widget-type-match + :validate 'widget-child-validate) + + ;;; The `plist' Widget. ;; ;; Property lists. diff --git a/lispref/customize.texi b/lispref/customize.texi index 8621cb65662..90600f410b7 100644 --- a/lispref/customize.texi +++ b/lispref/customize.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Emacs Lisp Reference Manual. -@c Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. +@c Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc. @c See the file elisp.texi for copying conditions. @setfilename ../info/customize @node Customization, Loading, Macros, Top @@ -373,6 +373,7 @@ equivalent to @code{(string)}. * Composite Types:: * Splicing into Lists:: * Type Keywords:: +* Defining New Types:: @end menu All customization types are implemented as widgets; see @ref{Top, , @@ -1056,6 +1057,76 @@ arguments, which will be used when creating the @code{radio-button} or @end ignore @end table +@node Defining New Types +@subsection Defining New Types + +In the previous sections we have described how to construct elaborate +type specifications for @code{defcustom}. In some cases you may want to +give such a type specification a name. The obvious case is when you are +using the same type for many user options, rather than repeat the +specification for each option, you can give the type specification a +name once, and use that name each @code{defcustom}. The other case is +when a user option accept a recursive datastructure. To make it +possible for a datatype to refer to itself, it needs to have a name. + +Since custom types are implemented as widgets, the way to define a new +customize type is to define a new widget. We are not going to describe +the widget interface here in details, see @ref{Top, , Introduction, +widget, The Emacs Widget Library}, for that. Instead we are going to +demonstrate the minimal functionality needed for defining new customize +types by a simple example. + +@example +(define-widget 'binary-tree-of-string 'lazy + "A binary tree made of cons-cells and strings." + :offset 4 + :tag "Node" + :type '(choice (string :tag "Leaf" :value "") + (cons :tag "Interior" + :value ("" . "") + binary-tree-of-string + binary-tree-of-string))) + +(defcustom foo-bar "" + "Sample variable holding a binary tree of strings." + :type 'binary-tree-of-string) +@end example + +The function to define a new widget is name @code{define-widget}. The +first argument is the symbol we want to make a new widget type. The +second argument is a symbol representing an existing widget, the new +widget is going to be defined in terms of difference from the existing +widget. For the purpose of defining new customization types, the +@code{lazy} widget is perfect, because it accept a @code{:type} keyword +argument with the same syntax as the keyword argument to +@code{defcustom} with the same name. The third argument is a +documentation string for the new widget. You will be able to see that +string with the @kbd{M-x widget-browse @key{ret} binary-tree-of-string +@key{ret}} command. + +After these mandatory arguments follows the keyword arguments. The most +important is @code{:type}, which describes the datatype we want to match +with this widget. Here a @code{binary-tree-of-string} is described as +being either a string, or a cons-cell whose car and cdr are themselves +both @code{binary-tree-of-string}. Note the reference to the widget +type we are currently in the process of defining. The @code{:tag} +attribute is a string to name the widget in the user interface, and the +@code{:offset} argument are there to ensure that child nodes are +indented four spaces relatively to the parent node, making the tree +structure apparent in the customization buffer. + +The @code{defcustom} shows how the new widget can be used as an ordinary +customization type. + +If you wonder about the name @code{lazy}, know that the other composite +widgets convert their inferior widgets to internal form when the widget +is instantiated in a buffer. This conversion is recursive, so the +inferior widgets will convert @emph{their} inferior widgets. If the +datastructure is itself recursive, this conversion will go on forever, +or at least until Emacs run out of stack space. The @code{lazy} widget +stop this recursion, it will only convert its @code{:type} argument when +needed. + @ignore arch-tag: d1b8fad3-f48c-4ce4-a402-f73b5ef19bd2 @end ignore From 80ca57997d02e9136ae1017cd6f141bc4da6f188 Mon Sep 17 00:00:00 2001 From: Lars Hansen Date: Sat, 27 Dec 2003 18:12:39 +0000 Subject: [PATCH 25/42] (ls-lisp-insert-directory): Add parameter 'string in calls to directory-files-and-attributes and file-attributes. (ls-lisp-format): Remove system dependent handling of user and group id's. --- lisp/ChangeLog | 7 +++++++ lisp/ls-lisp.el | 21 ++++++--------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index a2e7f95747c..09992ed03ad 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,10 @@ +2003-12-27 Lars Hansen + + * ls-lisp.el (ls-lisp-insert-directory): Add parameter 'string in + calls to directory-files-and-attributes and file-attributes. + (ls-lisp-format): Remove system dependent handling of user and + group id's. + 2003-12-25 Luc Teirlinck * ffap.el (ffap-read-file-or-url): Revert previous change. diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el index 7554bce0a3b..521729b764f 100644 --- a/lisp/ls-lisp.el +++ b/lisp/ls-lisp.el @@ -267,7 +267,7 @@ not contain `d', so that a full listing is expected." (let* ((dir (file-name-as-directory file)) (default-directory dir) ; so that file-attributes works (file-alist - (directory-files-and-attributes dir nil wildcard-regexp t)) + (directory-files-and-attributes dir nil wildcard-regexp t 'string)) (now (current-time)) (sum 0) ;; do all bindings here for speed @@ -329,7 +329,7 @@ not contain `d', so that a full listing is expected." ;; so must make it a relative filename as ls does: (if (eq (aref file (1- (length file))) ?/) (setq file (substring file 0 -1))) - (let ((fattr (file-attributes file))) + (let ((fattr (file-attributes file 'string))) (if fattr (insert (ls-lisp-format file fattr (nth 7 fattr) switches time-index (current-time))) @@ -522,23 +522,14 @@ SWITCHES, TIME-INDEX and NOW give the full switch list and time data." ;; They tend to be bogus on non-UNIX platforms anyway so ;; optionally hide them. (if (memq 'uid ls-lisp-verbosity) - ;; (user-login-name uid) works on Windows NT but not - ;; on 9x and maybe not on some other platforms, so... + ;; uid can be a sting or an integer (let ((uid (nth 2 file-attr))) - (if (= uid (user-uid)) - (format " %-8s" (user-login-name)) - (format " %-8d" uid)))) + (format (if (stringp uid) " %-8s" " %-8d") uid))) (if (not (memq ?G switches)) ; GNU ls -- shows group by default (if (or (memq ?g switches) ; UNIX ls -- no group by default (memq 'gid ls-lisp-verbosity)) - (if (memq system-type '(macos windows-nt ms-dos)) - ;; No useful concept of group... - " root" - (let* ((gid (nth 3 file-attr)) - (group (user-login-name gid))) - (if group - (format " %-8s" group) - (format " %-8d" gid)))))) + (let ((gid (nth 3 file-attr))) + (format (if (stringp gid) " %-8s" " %-8d") gid)))) (ls-lisp-format-file-size file-size (memq ?h switches)) " " (ls-lisp-format-time file-attr time-index now) From 631ec144a13cc3553d63934bf741ef5a25bad016 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 27 Dec 2003 21:56:10 +0000 Subject: [PATCH 26/42] *** empty log message *** --- lisp/ChangeLog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 09992ed03ad..c737c003eb9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,18 @@ +2003-12-27 Kim F. Storm + + * ido.el: Handle non-readable directories. + (ido-decorations): Add 9th element for non-readable directory. + (ido-directory-nonreadable): New dynamic var. + (ido-set-current-directory): Set it. + (ido-read-buffer, ido-file-internal): + (ido-read-file-name, ido-read-directory-name): Let-bind it. + (ido-file-name-all-completions1): Return empty list for + non-readable directory. + (ido-exhibit): Print [Not readable] if directory is not readable. + (ido-expand-directory): New defun (based on tiny fix from Karl Chen). + (ido-read-file-name, ido-file-internal, ido-read-directory-name): + Use it. + 2003-12-27 Lars Hansen * ls-lisp.el (ls-lisp-insert-directory): Add parameter 'string in From a70343bdfdeb5fbbebcfb767b6a2d0ca2e973054 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 27 Dec 2003 21:56:51 +0000 Subject: [PATCH 27/42] Handle non-readable directories. (ido-decorations): Add 9th element for non-readable directory. (ido-directory-nonreadable): New dynamic var. (ido-set-current-directory): Set it. (ido-read-buffer, ido-file-internal): (ido-read-file-name, ido-read-directory-name): Let-bind it. (ido-file-name-all-completions1): Return empty list for non-readable directory. (ido-exhibit): Print [Not readable] if directory is not readable. (ido-expand-directory): New defun (based on tiny fix from Karl Chen). (ido-read-file-name, ido-file-internal, ido-read-directory-name): Use it. --- lisp/ido.el | 115 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/lisp/ido.el b/lisp/ido.el index 57736ae7d26..165142ea222 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -685,16 +685,17 @@ Obsolete. Set 3rd element of `ido-decorations' instead." :type '(choice string (const nil)) :group 'ido) -(defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]") +(defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]" " [Not readable]") "*List of strings used by ido to display the alternatives in the minibuffer. -There are 8 elements in this list, each is a pair of strings: +There are 9 elements in this list: 1st and 2nd elements are used as brackets around the prospect list, 3rd element is the separator between prospects (ignored if ido-separator is set), 4th element is the string inserted at the end of a truncated list of prospects, 5th and 6th elements are used as brackets around the common match string which can be completed using TAB, 7th element is the string displayed when there are a no matches, and -8th element displayed if there is a single match (and faces are not used)." +8th element is displayed if there is a single match (and faces are not used). +9th element is displayed when the current directory is non-readable." :type '(repeat string) :group 'ido) @@ -931,6 +932,9 @@ it doesn't interfere with other minibuffer usage.") ;; `ido-cur-list'. It is in no specific order. (defvar ido-ignored-list) +;; Remember if current directory is non-readable (so we cannot do completion). +(defvar ido-directory-nonreadable) + ;; Keep current item list if non-nil. (defvar ido-keep-item-list) @@ -1406,6 +1410,7 @@ This function also adds a hook to the minibuffer." (setq ido-current-directory dir) (if (get-buffer ido-completion-buffer) (kill-buffer ido-completion-buffer)) + (setq ido-directory-nonreadable (not (file-readable-p dir))) t)) (defun ido-set-current-home (&optional dir) @@ -1812,7 +1817,8 @@ PROMPT is the prompt to give to the user. DEFAULT if given is the default buffer to be selected, which will go to the front of the list. If REQUIRE-MATCH is non-nil, an existing-buffer must be selected. If INITIAL is non-nil, it specifies the initial input string." - (let ((ido-current-directory nil)) + (let ((ido-current-directory nil) + (ido-directory-nonreadable nil)) (ido-read-internal 'buffer prompt 'ido-buffer-history default require-match initial))) (defun ido-record-work-directory (&optional dir) @@ -1851,12 +1857,18 @@ If INITIAL is non-nil, it specifies the initial input string." (if (> (length ido-work-file-list) ido-max-work-file-list) (setcdr (nthcdr (1- ido-max-work-file-list) ido-work-file-list) nil)))) +(defun ido-expand-directory (dir) + ;; Expand DIR or use DEFAULT-DIRECTORY if nil. + ;; Add final slash to result in case it was missing from DEFAULT-DIRECTORY. + (ido-final-slash (expand-file-name (or dir default-directory)) t)) + (defun ido-file-internal (method &optional fallback default prompt item initial) ;; Internal function for ido-find-file and friends (unless item (setq item 'file)) - (let ((ido-current-directory (expand-file-name (or default default-directory))) - filename) + (let* ((ido-current-directory (ido-expand-directory default)) + (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) + filename) (cond ((or (not ido-mode) (ido-is-slow-ftp-host)) @@ -2693,30 +2705,33 @@ for first matching file." (setq ido-temp-list items))) (defun ido-file-name-all-completions1 (dir) - (if (and ido-enable-tramp-completion - (string-match "\\`/\\([^/:]+:\\([^/:@]+@\\)?\\)\\'" dir)) + (cond + ((not (file-readable-p dir)) '()) + ((and ido-enable-tramp-completion + (string-match "\\`/\\([^/:]+:\\([^/:@]+@\\)?\\)\\'" dir)) - ;; Trick tramp's file-name-all-completions handler to DTRT, as it - ;; has some pretty obscure requirements. This seems to work... - ;; /ftp: => (f-n-a-c "/ftp:" "") - ;; /ftp:kfs: => (f-n-a-c "" "/ftp:kfs:") - ;; /ftp:kfs@ => (f-n-a-c "ftp:kfs@" "/") - ;; /ftp:kfs@kfs: => (f-n-a-c "" "/ftp:kfs@kfs:") - ;; Currently no attempt is made to handle multi: stuff. + ;; Trick tramp's file-name-all-completions handler to DTRT, as it + ;; has some pretty obscure requirements. This seems to work... + ;; /ftp: => (f-n-a-c "/ftp:" "") + ;; /ftp:kfs: => (f-n-a-c "" "/ftp:kfs:") + ;; /ftp:kfs@ => (f-n-a-c "ftp:kfs@" "/") + ;; /ftp:kfs@kfs: => (f-n-a-c "" "/ftp:kfs@kfs:") + ;; Currently no attempt is made to handle multi: stuff. - (let* ((prefix (match-string 1 dir)) - (user-flag (match-beginning 2)) - (len (and prefix (length prefix))) - compl) - (if user-flag - (setq dir (substring dir 1))) - (require 'tramp nil t) - (ido-trace "tramp complete" dir) - (setq compl (file-name-all-completions dir (if user-flag "/" ""))) - (if (> len 0) - (mapcar (lambda (c) (substring c len)) compl) - compl)) - (file-name-all-completions "" dir))) + (let* ((prefix (match-string 1 dir)) + (user-flag (match-beginning 2)) + (len (and prefix (length prefix))) + compl) + (if user-flag + (setq dir (substring dir 1))) + (require 'tramp nil t) + (ido-trace "tramp complete" dir) + (setq compl (file-name-all-completions dir (if user-flag "/" ""))) + (if (> len 0) + (mapcar (lambda (c) (substring c len)) compl) + compl))) + (t + (file-name-all-completions "" dir)))) (defun ido-file-name-all-completions (dir) ;; Return name of all files in DIR @@ -3518,6 +3533,11 @@ For details of keybindings, do `\\[describe-function] ido-find-file'." (expand-file-name "/" ido-current-directory) "/")) (setq refresh t)) + ((and ido-directory-nonreadable + (file-directory-p (concat ido-current-directory (file-name-directory contents)))) + (ido-set-current-directory + (concat ido-current-directory (file-name-directory contents))) + (setq refresh t)) (t (ido-trace "try single dir") (setq try-single-dir-match t)))) @@ -3574,6 +3594,7 @@ For details of keybindings, do `\\[describe-function] ido-find-file'." (exit-minibuffer)) (when (and (not ido-matches) + (not ido-directory-nonreadable) ;; ido-rescan ? ido-process-ignore-lists ido-ignored-list) @@ -3596,7 +3617,8 @@ For details of keybindings, do `\\[describe-function] ido-find-file'." (memq ido-cur-item '(file dir)) (not (ido-is-root-directory)) (> (length contents) 1) - (not (string-match "[$]" contents))) + (not (string-match "[$]" contents)) + (not ido-directory-nonreadable)) (ido-trace "merge?") (if ido-use-merged-list (ido-undo-merge-work-directory contents nil) @@ -3658,9 +3680,12 @@ For details of keybindings, do `\\[describe-function] ido-find-file'." (setq comps (cons first (cdr comps))))) (cond ((null comps) - (if ido-report-no-match - (nth 6 ido-decorations) ;; [No Match] - "")) + (cond + (ido-directory-nonreadable + (or (nth 8 ido-decorations) " [Not readable]")) + (ido-report-no-match + (nth 6 ido-decorations)) ;; [No match] + (t ""))) ((null (cdr comps)) ;one match (concat (if (> (length (ido-name (car comps))) (length name)) @@ -3771,13 +3796,14 @@ See `read-file-name' for additional parameters." (ido-read-directory-name prompt dir default-filename mustmatch initial)) ((and (not (memq this-command ido-read-file-name-non-ido)) (or (null predicate) (eq predicate 'file-exists-p))) - (let (filename - ido-saved-vc-hb - (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends)) - (ido-current-directory (expand-file-name (or dir default-directory))) - (ido-work-directory-index -1) - (ido-work-file-index -1) - (ido-find-literal nil)) + (let* (filename + ido-saved-vc-hb + (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends)) + (ido-current-directory (ido-expand-directory dir)) + (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) + (ido-work-directory-index -1) + (ido-work-file-index -1) + (ido-find-literal nil)) (setq filename (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial)) (if filename @@ -3790,11 +3816,12 @@ See `read-file-name' for additional parameters." (defun ido-read-directory-name (prompt &optional dir default-dirname mustmatch initial) "Read directory name, prompting with PROMPT and completing in directory DIR. See `read-file-name' for additional parameters." - (let (filename - ido-saved-vc-hb - (ido-current-directory (expand-file-name (or dir default-directory))) - (ido-work-directory-index -1) - (ido-work-file-index -1)) + (let* (filename + ido-saved-vc-hb + (ido-current-directory (ido-expand-directory dir)) + (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) + (ido-work-directory-index -1) + (ido-work-file-index -1)) (setq filename (ido-read-internal 'dir prompt 'ido-file-history default-dirname mustmatch initial)) (if filename From 942b13fa0d42e216c3a9fcc012d311f121311d8a Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 27 Dec 2003 22:03:40 +0000 Subject: [PATCH 28/42] (eval.o): Depend on dispextern.h. --- src/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.in b/src/Makefile.in index 07b3c828650..cd9fb8b6f57 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1171,7 +1171,7 @@ alloc.o: alloc.c process.h frame.h window.h buffer.h puresize.h syssignal.h key bytecode.o: bytecode.c buffer.h syntax.h charset.h window.h $(config_h) data.o: data.c buffer.h puresize.h charset.h syssignal.h keyboard.h $(config_h) eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h \ - $(config_h) + dispextern.h $(config_h) floatfns.o: floatfns.c $(config_h) fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \ frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h From 9fc63a8939697c4daa2e56b9829eebe2cc204bf4 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 27 Dec 2003 22:24:01 +0000 Subject: [PATCH 29/42] (show_help_event): Remove unused code. --- src/xmenu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xmenu.c b/src/xmenu.c index 3e99a1c506d..669d8177c15 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -99,7 +99,6 @@ Lisp_Object Vmenu_updating_frame; Lisp_Object Qdebug_on_next_call; extern Lisp_Object Qmenu_bar; -extern Lisp_Object Qmouse_click, Qevent_kind; extern Lisp_Object QCtoggle, QCradio; @@ -1304,6 +1303,7 @@ show_help_event (f, widget, help) } else { +#if 0 /* This code doesn't do anything useful. ++kfs */ /* WIDGET is the popup menu. It's parent is the frame's widget. See which frame that is. */ xt_or_gtk_widget frame_widget = XtParent (widget); @@ -1317,7 +1317,7 @@ show_help_event (f, widget, help) FRAME_X_P (f) && f->output_data.x->widget == frame_widget)) break; } - +#endif show_help_echo (help, Qnil, Qnil, Qnil, 1); } } From f2dcea2bf92c7cb7d05110b63c187de1b73544ab Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 27 Dec 2003 23:16:53 +0000 Subject: [PATCH 30/42] (Qmouse_click, Qevent_kind): Remove unused externs. --- src/w32menu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/w32menu.c b/src/w32menu.c index 49ced7fd11c..5f8f8a4e5e0 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -153,7 +153,6 @@ Lisp_Object Vmenu_updating_frame; Lisp_Object Qdebug_on_next_call; extern Lisp_Object Qmenu_bar; -extern Lisp_Object Qmouse_click, Qevent_kind; extern Lisp_Object QCtoggle, QCradio; From db4f9403e18676d597721c4e9fa36809bd9e6d0d Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 27 Dec 2003 23:19:43 +0000 Subject: [PATCH 31/42] (Qface, Qmouse_face): Remove unused externs. --- src/macterm.c | 2 -- src/w32term.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/macterm.c b/src/macterm.c index f0f5a3f4722..8ef25e43856 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -253,8 +253,6 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name; extern Lisp_Object Vx_no_window_manager; -extern Lisp_Object Qface, Qmouse_face; - extern int errno; /* A mask of extra modifier bits to put into every keyboard char. */ diff --git a/src/w32term.c b/src/w32term.c index 3e4543471c3..d7248499c22 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -221,8 +221,6 @@ static int input_signal_count; extern Lisp_Object Vcommand_line_args, Vsystem_name; -extern Lisp_Object Qface, Qmouse_face; - #ifndef USE_CRT_DLL extern int errno; #endif From 01b1f0c05b794f86c98e6ad36086e02aa8927482 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:09:49 +0000 Subject: [PATCH 32/42] (FACE_ID_BITS, MAX_FACE_ID): New defines. (struct glyph): New members, ascent and descent. Used to save this glyph's ascent and descent, instead of having. (struct glyph): Declare member face_id using FACE_ID_BITS. (find_hot_spot): Add prototype. --- src/dispextern.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dispextern.h b/src/dispextern.h index f306a939db2..25c8227d773 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -321,6 +321,9 @@ struct glyph /* Width in pixels. */ short pixel_width; + /* Ascent and descent in pixels. */ + short ascent, descent; + /* Vertical offset. If < 0, the glyph is displayed raised, if > 0 the glyph is displayed lowered. */ short voffset; @@ -359,8 +362,10 @@ struct glyph doesn't have a glyph in a font. */ unsigned glyph_not_available_p : 1; +#define FACE_ID_BITS 21 + /* Face of the glyph. */ - unsigned face_id : 21; + unsigned face_id : FACE_ID_BITS; /* Type of font used to display the character glyph. May be used to determine which set of functions to use to obtain font metrics @@ -1493,6 +1498,7 @@ enum face_id BASIC_FACE_ID_SENTINEL }; +#define MAX_FACE_ID ((1 << FACE_ID_BITS) - 1) /* A cache of realized faces. Each frame has its own cache because Emacs allows different frame-local face definitions. */ @@ -2536,6 +2542,7 @@ extern void x_draw_vertical_border P_ ((struct window *w)); extern void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); extern void get_glyph_string_clip_rect P_ ((struct glyph_string *, NativeRectangle *nr)); +extern Lisp_Object find_hot_spot P_ ((Lisp_Object, int, int)); extern void note_mouse_highlight P_ ((struct frame *, int, int)); extern void x_clear_window_mouse_face P_ ((struct window *)); extern void cancel_mouse_face P_ ((struct frame *)); From 60bf162981c3f6fada160812ed248c0f9c6ebc92 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:10:12 +0000 Subject: [PATCH 33/42] (buffer_posn_from_coords): Fix calculation of dy for image glyph using image's ascent. (mode_line_string): Return image glyph as object clicked on. Adjust y0 for image glyph using image's ascent. --- src/dispnew.c | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/dispnew.c b/src/dispnew.c index 279c1f10e58..09a651d5d7c 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -5702,8 +5702,6 @@ buffer_posn_from_coords (w, x, y, dx, dy, object, pos) struct it it; struct buffer *old_current_buffer = current_buffer; struct text_pos startp; - struct glyph_row *row; - struct image *img; int x0, x1; current_buffer = XBUFFER (w->buffer); @@ -5716,25 +5714,44 @@ buffer_posn_from_coords (w, x, y, dx, dy, object, pos) move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1, MOVE_TO_X | MOVE_TO_Y); - /* Add extra (default width) columns if clicked after EOL. */ - x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x); - if (x0 > x1) - it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w); - current_buffer = old_current_buffer; *dx = x0 + it.first_visible_x - it.current_x; *dy = *y - it.current_y; + *object = w->buffer; + #ifdef HAVE_WINDOW_SYSTEM - if (it.what == IT_IMAGE - && (img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL - && !NILP (img->spec)) - *object = img->spec; + if (it.what == IT_IMAGE) + { + struct image *img; + if ((img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL + && !NILP (img->spec)) + { + struct glyph_row *row = MATRIX_ROW (w->current_matrix, it.vpos); + struct glyph *glyph; + + if (it.hpos < row->used[TEXT_AREA] + && (glyph = row->glyphs[TEXT_AREA] + it.hpos, + glyph->type == IMAGE_GLYPH)) + { + *dy -= row->ascent - glyph->ascent; + *object = img->spec; + } + } + } else #endif - *object = STRINGP (it.string) ? it.string : w->buffer; + if (STRINGP (it.string)) + *object = it.string; + *pos = it.current; + + /* Add extra (default width) columns if clicked after EOL. */ + x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x); + if (x0 > x1) + it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w); + *x = it.hpos; *y = it.vpos; } @@ -5854,6 +5871,16 @@ marginal_area_string (w, x, y, dx, dy, part, charpos) { string = glyph->object; *charpos = glyph->charpos; +#ifdef HAVE_WINDOW_SYSTEM + if (glyph->type == IMAGE_GLYPH) + { + struct image *img; + img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id); + if (img != NULL) + string = img->spec; + y0 -= row->ascent - glyph->ascent; + } +#endif } else /* Add extra (default width) columns if clicked after EOL. */ From 2e3f0f616bd831dbc6a09c9f753085c6caf563f8 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:10:41 +0000 Subject: [PATCH 34/42] (Qimage): Remove extern (now in lisp.h). (QCmap): Declare extern. (make_lispy_position): When position is inside image hot-spot, use hot-spot element as posn element. --- src/keyboard.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/keyboard.c b/src/keyboard.c index 6148a2510b8..3ac73750afc 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -587,7 +587,7 @@ Lisp_Object Qvertical_scroll_bar; Lisp_Object Qmenu_bar; extern Lisp_Object Qleft_margin, Qright_margin; extern Lisp_Object Qleft_fringe, Qright_fringe; -extern Lisp_Object Qimage; +extern Lisp_Object QCmap; Lisp_Object recursive_edit_unwind (), command_loop (); Lisp_Object Fthis_command_keys (); @@ -5024,6 +5024,19 @@ make_lispy_position (f, x, y, time) string = marginal_area_string (w, &rx, &ry, &dx, &dy, part, &charpos); if (STRINGP (string)) object = Fcons (string, make_number (charpos)); +#ifdef HAVE_WINDOW_SYSTEM + else if (IMAGEP (string)) + { + Lisp_Object image_map, hotspot; + object = string; + if ((image_map = Fplist_get (XCDR (object), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + posn = XCAR (hotspot); + } +#endif } else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE) { @@ -5059,8 +5072,19 @@ make_lispy_position (f, x, y, time) if (STRINGP (string)) object = Fcons (string, make_number (CHARPOS (p.string_pos))); - else if (CONSP (string) && EQ (XCAR (string), Qimage)) - object = string; +#ifdef HAVE_WINDOW_SYSTEM + else if (IMAGEP (string)) + { + Lisp_Object image_map, hotspot; + object = string; + if ((image_map = Fplist_get (XCDR (object), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + posn = XCAR (hotspot); + } +#endif } } From dea9b52152ce21296c22e996c29e80d3b542b450 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:11:03 +0000 Subject: [PATCH 35/42] (IMAGEP): New macro to test for image object type. (Qimage): Declare extern. --- src/lisp.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lisp.h b/src/lisp.h index 94de2c2960f..e1f939581db 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1381,6 +1381,10 @@ typedef unsigned char UCHAR; #define GC_FRAMEP(x) GC_PSEUDOVECTORP (x, PVEC_FRAME) #define SUB_CHAR_TABLE_P(x) (CHAR_TABLE_P (x) && NILP (XCHAR_TABLE (x)->top)) + +/* Test for image (image . spec) */ +#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage)) + #define GC_EQ(x, y) EQ (x, y) @@ -2283,6 +2287,7 @@ extern Lisp_Object Qinhibit_point_motion_hooks; extern Lisp_Object Qinhibit_redisplay, Qdisplay; extern Lisp_Object Qinhibit_eval_during_redisplay; extern Lisp_Object Qmessage_truncate_lines; +extern Lisp_Object Qimage; extern Lisp_Object Vmessage_log_max; extern int message_enable_multibyte; extern Lisp_Object echo_area_buffer[2]; From 82cf95a792459f8dd7a1118f47c1a1dbec962bc9 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:11:49 +0000 Subject: [PATCH 36/42] (Qimage): Remove extern (now in lisp.h). (valid_image_p, parse_image_spec): Use IMAGEP macro. --- src/macfns.c | 9 ++------- src/w32fns.c | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/macfns.c b/src/macfns.c index 1634809ca3e..0f87556fb1e 100644 --- a/src/macfns.c +++ b/src/macfns.c @@ -3460,11 +3460,6 @@ If DISPLAY is omitted or nil, that stands for the selected frame's display. */) static struct image_type *image_types; -/* The symbol `image' which is the car of the lists used to represent - images in Lisp. */ - -extern Lisp_Object Qimage; - /* The symbol `xbm' which is used as the type symbol for XBM images. */ Lisp_Object Qxbm; @@ -3543,7 +3538,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object symbol = Fplist_get (XCDR (object), QCtype); struct image_type *type = lookup_image_type (symbol); @@ -3633,7 +3628,7 @@ parse_image_spec (spec, keywords, nkeywords, type) int i; Lisp_Object plist; - if (!CONSP (spec) || !EQ (XCAR (spec), Qimage)) + if (!IMAGEP (spec)) return 0; plist = XCDR (spec); diff --git a/src/w32fns.c b/src/w32fns.c index d8572265bef..7bffea34a28 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -6937,11 +6937,6 @@ DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0, static struct image_type *image_types; -/* The symbol `image' which is the car of the lists used to represent - images in Lisp. */ - -extern Lisp_Object Qimage; - /* The symbol `xbm' which is used as the type symbol for XBM images. */ Lisp_Object Qxbm; @@ -7021,7 +7016,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object tem; @@ -7123,7 +7118,7 @@ parse_image_spec (spec, keywords, nkeywords, type) int i; Lisp_Object plist; - if (!CONSP (spec) || !EQ (XCAR (spec), Qimage)) + if (!IMAGEP (spec)) return 0; plist = XCDR (spec); From 493fdc3cc3fad407c3ad3476d88658f6be8eb244 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:12:27 +0000 Subject: [PATCH 37/42] (Qarrow, Qhand, Qtext, Qpointer): New variables for pointer types. (Qrelative_width, Qalign_to): Remove unused variables. (Vvoid_text_area_pointer): Replace Vshow_text_cursor_in_void. (QCmap, QCpointer, Qrect, Qcircle, Qpoly): New variables for image maps. (x_y_to_hpos_vpos): Return glyph relative coordinates through new dx and dy args. Remove buffer_only_p arg (always 0). Simplify code accordingly. (get_glyph_string_clip_rect): Draw cursor using glyph's rather than row's ascent and height, to get sensible height on tall rows. (build_desired_tool_bar_string): Remove Qimage extern. (get_tool_bar_item): Fix call to x_y_to_hpos_vpos. (produce_image_glyph): Adjust it.ascent to minimum row ascent if image glyph is alone on the last line. (append_glyph, append_composite_glyph, produce_image_glyph) (append_stretch_glyph): Set glyph's ascent and descent. (on_hot_spot_p): New function to check if position is inside an rectangular, circular, or polygon-shaped image hot-spot, (find_hot_spot): New function to search for image hot-spot. (Flookup_image_map): New defun to search for image hot-spot. (define_frame_cursor1): New aux function to determine frame pointer. (note_mode_line_or_margin_highlight, note_mouse_highlight): Handle `pointer' text property and :pointer image property to control frame pointer shape. Detect image hot-spots for pointer and help_echo properties. Use define_frame_cursor1. (note_mouse_highlight): Use Vvoid_text_area_pointer. (syms_of_xdisp): Defsubr new defun. Intern and staticpro new variables. DEFVAR_LISP Vvoid_text_area_pointer instead of Vshow_text_cursor_in_void. --- src/xdisp.c | 449 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 397 insertions(+), 52 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index c2717552cc5..8a6f36ef17b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -242,6 +242,9 @@ Lisp_Object Qbuffer_position, Qposition, Qobject; /* Cursor shapes */ Lisp_Object Qbar, Qhbar, Qbox, Qhollow; +/* Pointer shapes */ +Lisp_Object Qarrow, Qhand, Qtext; + Lisp_Object Qrisky_local_variable; /* Holds the list (error). */ @@ -290,7 +293,7 @@ int inhibit_eval_during_redisplay; /* Names of text properties relevant for redisplay. */ -Lisp_Object Qdisplay, Qrelative_width, Qalign_to; +Lisp_Object Qdisplay; extern Lisp_Object Qface, Qinvisible, Qwidth; /* Symbols used in text property values. */ @@ -298,7 +301,7 @@ extern Lisp_Object Qface, Qinvisible, Qwidth; Lisp_Object Vdisplay_pixels_per_inch; Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height; Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; -Lisp_Object Qmargin; +Lisp_Object Qmargin, Qpointer; extern Lisp_Object Qheight; extern Lisp_Object QCwidth, QCheight, QCascent; extern Lisp_Object Qscroll_bar; @@ -311,7 +314,7 @@ Lisp_Object Vshow_trailing_whitespace; i.e. in blank areas after eol and eob. This used to be the default in 21.3. */ -Lisp_Object Vshow_text_cursor_in_void; +Lisp_Object Vvoid_text_area_pointer; /* Name of the face used to highlight trailing whitespace. */ @@ -322,6 +325,10 @@ Lisp_Object Qtrailing_whitespace; Lisp_Object Qimage; +/* The image map types. */ +Lisp_Object QCmap, QCpointer; +Lisp_Object Qrect, Qcircle, Qpoly; + /* Non-zero means print newline to stdout before next mini-buffer message. */ @@ -1582,11 +1589,10 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y) date. */ static struct glyph * -x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) +x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area) struct window *w; int x, y; - int *hpos, *vpos, *area; - int buffer_only_p; + int *hpos, *vpos, *dx, *dy, *area; { struct glyph *glyph, *end; struct glyph_row *row = NULL; @@ -1637,23 +1643,22 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) /* Find glyph containing X. */ glyph = row->glyphs[*area]; end = glyph + row->used[*area]; - while (glyph < end) + x -= x0; + while (glyph < end && x >= glyph->pixel_width) { - if (x < x0 + glyph->pixel_width) - { - if (w->pseudo_window_p) - break; - else if (!buffer_only_p || BUFFERP (glyph->object)) - break; - } - - x0 += glyph->pixel_width; + x -= glyph->pixel_width; ++glyph; } if (glyph == end) return NULL; + if (dx) + { + *dx = x; + *dy = y - (row->y + row->ascent - glyph->ascent); + } + *hpos = glyph - row->glyphs[*area]; return glyph; } @@ -1741,20 +1746,28 @@ get_glyph_string_clip_rect (s, nr) r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y); -#ifdef HAVE_NTGUI - /* ++KFS: From W32 port, but it looks ok for all platforms to me. */ /* If drawing the cursor, don't let glyph draw outside its advertised boundaries. Cleartype does this under some circumstances. */ if (s->hl == DRAW_CURSOR) { + struct glyph *glyph = s->first_glyph; + int height; + if (s->x > r.x) { r.width -= s->x - r.x; r.x = s->x; } - r.width = min (r.width, s->first_glyph->pixel_width); + r.width = min (r.width, glyph->pixel_width); + + /* Don't draw cursor glyph taller than our actual glyph. */ + height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent); + if (height < r.height) + { + r.y = s->ybase + glyph->descent - height; + r.height = height; + } } -#endif #ifdef CONVERT_FROM_XRECT CONVERT_FROM_XRECT (r, *nr); @@ -8279,7 +8292,7 @@ build_desired_tool_bar_string (f) int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); int hmargin, vmargin, relief, idx, end; - extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage; + extern Lisp_Object QCrelief, QCmargin, QCconversion; /* If image is a vector, choose the image according to the button state. */ @@ -8696,7 +8709,7 @@ get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) int area; /* Find the glyph under X/Y. */ - *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); + *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area); if (*glyph == NULL) return -1; @@ -17685,6 +17698,8 @@ append_glyph (it) glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; + glyph->ascent = it->ascent; + glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = CHAR_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -17719,6 +17734,8 @@ append_composite_glyph (it) glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; + glyph->ascent = it->ascent; + glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = COMPOSITE_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -17767,6 +17784,7 @@ produce_image_glyph (it) { struct image *img; struct face *face; + int face_ascent, glyph_ascent; xassert (it->what == IT_IMAGE); @@ -17778,10 +17796,15 @@ produce_image_glyph (it) PREPARE_FACE_FOR_DISPLAY (it->f, face); prepare_image_for_display (it->f, img); - it->ascent = it->phys_ascent = image_ascent (img, face); + it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face); it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent; it->pixel_width = img->width + 2 * img->hmargin; + /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */ + face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f); + if (face_ascent > it->ascent) + it->ascent = it->phys_ascent = face_ascent; + it->nglyphs = 1; if (face->box != FACE_NO_BOX) @@ -17811,6 +17834,8 @@ produce_image_glyph (it) glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; + glyph->ascent = glyph_ascent; + glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = IMAGE_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -17850,6 +17875,8 @@ append_stretch_glyph (it, object, width, height, ascent) glyph->charpos = CHARPOS (it->position); glyph->object = object; glyph->pixel_width = width; + glyph->ascent = ascent; + glyph->descent = height - ascent; glyph->voffset = it->voffset; glyph->type = STRETCH_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -19945,6 +19972,189 @@ fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p) } +/* See if position X, Y is within a hot-spot of an image. */ + +static int +on_hot_spot_p (hot_spot, x, y) + Lisp_Object hot_spot; + int x, y; +{ + if (!CONSP (hot_spot)) + return 0; + + if (EQ (XCAR (hot_spot), Qrect)) + { + /* CDR is (Top-Left . Bottom-Right) = ((x0 . y0) . (x1 . y1)) */ + Lisp_Object rect = XCDR (hot_spot); + Lisp_Object tem; + if (!CONSP (rect)) + return 0; + if (!CONSP (XCAR (rect))) + return 0; + if (!CONSP (XCDR (rect))) + return 0; + if (!(tem = XCAR (XCAR (rect)), INTEGERP (tem) && x >= XINT (tem))) + return 0; + if (!(tem = XCDR (XCAR (rect)), INTEGERP (tem) && y >= XINT (tem))) + return 0; + if (!(tem = XCAR (XCDR (rect)), INTEGERP (tem) && x <= XINT (tem))) + return 0; + if (!(tem = XCDR (XCDR (rect)), INTEGERP (tem) && y <= XINT (tem))) + return 0; + return 1; + } + else if (EQ (XCAR (hot_spot), Qcircle)) + { + /* CDR is (Center . Radius) = ((x0 . y0) . r) */ + Lisp_Object circ = XCDR (hot_spot); + Lisp_Object lr, lx0, ly0; + if (CONSP (circ) + && CONSP (XCAR (circ)) + && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr)) + && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0)) + && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0))) + { + double r = XFLOATINT (lr); + double dx = XINT (lx0) - x; + double dy = XINT (ly0) - y; + return (dx * dx + dy * dy <= r * r); + } + } + else if (EQ (XCAR (hot_spot), Qpoly)) + { + /* CDR is [x0 y0 x1 y1 x2 y2 ...x(n-1) y(n-1)] */ + if (VECTORP (XCDR (hot_spot))) + { + struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot)); + Lisp_Object *poly = v->contents; + int n = v->size; + int i; + int inside = 0; + Lisp_Object lx, ly; + int x0, y0; + + /* Need an even number of coordinates, and at least 3 edges. */ + if (n < 6 || n & 1) + return 0; + + /* Count edge segments intersecting line from (X,Y) to (X,infinity). + If count is odd, we are inside polygon. Pixels on edges + may or may not be included depending on actual geometry of the + polygon. */ + if ((lx = poly[n-2], !INTEGERP (lx)) + || (ly = poly[n-1], !INTEGERP (lx))) + return 0; + x0 = XINT (lx), y0 = XINT (ly); + for (i = 0; i < n; i += 2) + { + int x1 = x0, y1 = y0; + if ((lx = poly[i], !INTEGERP (lx)) + || (ly = poly[i+1], !INTEGERP (ly))) + return 0; + x0 = XINT (lx), y0 = XINT (ly); + + /* Does this segment cross the X line? */ + if (x0 >= x) + { + if (x1 >= x) + continue; + } + else if (x1 < x) + continue; + if (y > y0 && y > y1) + continue; + if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0)) + inside = !inside; + } + return inside; + } + } + else + return 0; +} + +Lisp_Object +find_hot_spot (map, x, y) + Lisp_Object map; + int x, y; +{ + while (CONSP (map)) + { + if (CONSP (XCAR (map)) + && on_hot_spot_p (XCAR (XCAR (map)), x, y)) + return XCAR (map); + map = XCDR (map); + } + + return Qnil; +} + +DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map, + 3, 3, 0, + doc: /* Lookup in image map MAP coordinates X and Y. +An image map is an alist where each element has the format (AREA ID PLIST). +An AREA is specified as either a rectangle, a circle, or a polygon: +A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the +pixel coordinates of the upper left and bottom right corners. +A circle is a cons (circle . ((x0 . y0) . r)) specifying the center +and the radius of the circle; r may be a float or integer. +A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the +vector describes one corner in the polygon. +Returns the alist element for the first matching AREA in MAP. */) + (map, x, y) + Lisp_Object map; + Lisp_Object x, y; +{ + int ix, iy; + if (NILP (map)) + return Qnil; + + if (!INTEGERP (x)) + wrong_type_argument (Qintegerp, x); + if (!INTEGERP (y)) + wrong_type_argument (Qintegerp, y); + + return find_hot_spot (map, XINT (x), XINT (y)); +} + + +/* Display frame CURSOR, optionally using shape defined by POINTER. */ +static void +define_frame_cursor1 (f, cursor, pointer) + struct frame *f; + Cursor cursor; + Lisp_Object pointer; +{ + if (!NILP (pointer)) + { + if (EQ (pointer, Qarrow)) + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + else if (EQ (pointer, Qhand)) + cursor = FRAME_X_OUTPUT (f)->hand_cursor; + else if (EQ (pointer, Qtext)) + cursor = FRAME_X_OUTPUT (f)->text_cursor; + else if (EQ (pointer, intern ("hdrag"))) + cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; +#ifdef HAVE_X_WINDOWS + else if (EQ (pointer, intern ("vdrag"))) + cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; +#endif + else if (EQ (pointer, intern ("hourglass"))) + cursor = FRAME_X_OUTPUT (f)->hourglass_cursor; + else if (EQ (pointer, Qmodeline)) + cursor = FRAME_X_OUTPUT (f)->modeline_cursor; + else + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + } + +#ifndef HAVE_CARBON + if (cursor != No_Cursor) +#else + if (bcmp (&cursor, &No_Cursor, sizeof (Cursor))) +#endif + rif->define_frame_cursor (f, cursor); +} + /* Take proper action when mouse has moved to the mode or header line or marginal area AREA of window W, x-position X and y-position Y. X is relative to the start of the text display area of W, so the @@ -19960,18 +20170,24 @@ note_mode_line_or_margin_highlight (w, x, y, area) struct frame *f = XFRAME (w->frame); Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; - int charpos; - Lisp_Object string, help, map, pos; + Lisp_Object pointer = Qnil; + int charpos, dx, dy; + Lisp_Object string; + Lisp_Object pos, help, image; if (area == ON_MODE_LINE || area == ON_HEADER_LINE) string = mode_line_string (w, &x, &y, 0, 0, area, &charpos); else - string = marginal_area_string (w, &x, &y, 0, 0, area, &charpos); + { + x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); + string = marginal_area_string (w, &x, &y, &dx, &dy, area, &charpos); + } + + help = Qnil; if (STRINGP (string)) { pos = make_number (charpos); - /* If we're on a string with `help-echo' text property, arrange for the help to be displayed. This is done by setting the global variable help_echo_string to the help string. */ @@ -19984,9 +20200,13 @@ note_mode_line_or_margin_highlight (w, x, y, area) help_echo_pos = charpos; } + if (NILP (pointer)) + pointer = Fget_text_property (pos, Qpointer, string); + /* Change the mouse pointer according to what is under X/Y. */ - if (area == ON_MODE_LINE) + if (NILP (pointer) && area == ON_MODE_LINE) { + Lisp_Object map; map = Fget_text_property (pos, Qlocal_map, string); if (!KEYMAPP (map)) map = Fget_text_property (pos, Qkeymap, string); @@ -19994,8 +20214,42 @@ note_mode_line_or_margin_highlight (w, x, y, area) cursor = dpyinfo->vertical_scroll_bar_cursor; } } + else if (IMAGEP (string)) + { + Lisp_Object image_map, hotspot; + if ((image_map = Fplist_get (XCDR (string), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + { + Lisp_Object area_id, plist; - rif->define_frame_cursor (f, cursor); + area_id = XCAR (hotspot); + /* Could check AREA_ID to see if we enter/leave this hot-spot. + If so, we could look for mouse-enter, mouse-leave + properties in PLIST (and do something...). */ + if ((plist = XCDR (hotspot), CONSP (plist))) + { + pointer = Fplist_get (plist, Qpointer); + if (NILP (pointer)) + pointer = Qhand; + help = Fplist_get (plist, Qhelp_echo); + if (!NILP (help)) + { + help_echo_string = help; + /* Is this correct? ++kfs */ + XSETWINDOW (help_echo_window, w); + help_echo_object = w->buffer; + help_echo_pos = charpos; + } + } + if (NILP (pointer)) + pointer = Fplist_get (XCDR (string), QCpointer); + } + } + + define_frame_cursor1 (f, cursor, pointer); } @@ -20015,6 +20269,7 @@ note_mouse_highlight (f, x, y) Lisp_Object window; struct window *w; Cursor cursor = No_Cursor; + Lisp_Object pointer = Qnil; /* Takes precedence over cursor! */ struct buffer *b; /* When a menu is active, don't highlight because this looks odd. */ @@ -20052,7 +20307,6 @@ note_mouse_highlight (f, x, y) return; /* Reset help_echo_string. It will get recomputed below. */ - /* ++KFS: X version didn't do this, but it looks harmless. */ help_echo_string = Qnil; /* Convert to window-relative pixel coordinates. */ @@ -20090,7 +20344,7 @@ note_mouse_highlight (f, x, y) && XFASTINT (w->last_modified) == BUF_MODIFF (b) && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) { - int hpos, vpos, pos, i, area; + int hpos, vpos, pos, i, dx, dy, area; struct glyph *glyph; Lisp_Object object; Lisp_Object mouse_face = Qnil, overlay = Qnil, position; @@ -20100,7 +20354,45 @@ note_mouse_highlight (f, x, y) int obegv, ozv, same_region; /* Find the glyph under X/Y. */ - glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); + glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area); + + /* Look for :pointer property on image. */ + if (glyph != NULL && glyph->type == IMAGE_GLYPH) + { + struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id); + if (img != NULL && IMAGEP (img->spec)) + { + Lisp_Object image_map, hotspot; + if ((image_map = Fplist_get (XCDR (img->spec), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + { + Lisp_Object area_id, plist; + + area_id = XCAR (hotspot); + /* Could check AREA_ID to see if we enter/leave this hot-spot. + If so, we could look for mouse-enter, mouse-leave + properties in PLIST (and do something...). */ + if ((plist = XCDR (hotspot), CONSP (plist))) + { + pointer = Fplist_get (plist, Qpointer); + if (NILP (pointer)) + pointer = Qhand; + help_echo_string = Fplist_get (plist, Qhelp_echo); + if (!NILP (help_echo_string)) + { + help_echo_window = window; + help_echo_object = glyph->object; + help_echo_pos = glyph->charpos; + } + } + } + if (NILP (pointer)) + pointer = Fplist_get (XCDR (img->spec), QCpointer); + } + } /* Clear mouse face if X/Y not over text. */ if (glyph == NULL @@ -20109,8 +20401,13 @@ note_mouse_highlight (f, x, y) { if (clear_mouse_face (dpyinfo)) cursor = No_Cursor; - if (NILP (Vshow_text_cursor_in_void)) - cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + if (NILP (pointer)) + { + if (area != TEXT_AREA) + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + else + pointer = Vvoid_text_area_pointer; + } goto set_cursor; } @@ -20123,9 +20420,6 @@ note_mouse_highlight (f, x, y) if (BUFFERP (object) && pos > BUF_Z (b)) goto set_cursor; - if (glyph->type == IMAGE_GLYPH) - cursor = FRAME_X_OUTPUT (f)->nontext_cursor; - /* Make the window's buffer temporarily current for overlays_at and compute_char_face. */ obuf = current_buffer; @@ -20369,7 +20663,7 @@ note_mouse_highlight (f, x, y) check_help_echo: /* Look for a `help-echo' property. */ - { + if (NILP (help_echo_string)) { Lisp_Object help, overlay; /* Check overlays first. */ @@ -20435,6 +20729,46 @@ note_mouse_highlight (f, x, y) } } + /* Look for a `pointer' property. */ + if (NILP (pointer)) + { + /* Check overlays first. */ + for (i = noverlays - 1; i >= 0 && NILP (pointer); --i) + pointer = Foverlay_get (overlay_vec[i], Qpointer); + + if (NILP (pointer)) + { + Lisp_Object object = glyph->object; + int charpos = glyph->charpos; + + /* Try text properties. */ + if (STRINGP (object) + && charpos >= 0 + && charpos < SCHARS (object)) + { + pointer = Fget_text_property (make_number (charpos), + Qpointer, object); + if (NILP (pointer)) + { + /* If the string itself doesn't specify a pointer, + see if the buffer text ``under'' it does. */ + struct glyph_row *r + = MATRIX_ROW (w->current_matrix, vpos); + int start = MATRIX_ROW_START_CHARPOS (r); + int pos = string_buffer_position (w, object, start); + if (pos > 0) + pointer = Fget_char_property (make_number (pos), + Qpointer, w->buffer); + } + } + else if (BUFFERP (object) + && charpos >= BEGV + && charpos < ZV) + pointer = Fget_text_property (make_number (charpos), + Qpointer, object); + } + } + BEGV = obegv; ZV = ozv; current_buffer = obuf; @@ -20442,12 +20776,7 @@ note_mouse_highlight (f, x, y) set_cursor: -#ifndef HAVE_CARBON - if (cursor != No_Cursor) -#else - if (bcmp (&cursor, &No_Cursor, sizeof (Cursor))) -#endif - rif->define_frame_cursor (f, cursor); + define_frame_cursor1 (f, cursor, pointer); } @@ -21043,6 +21372,7 @@ syms_of_xdisp () #endif #ifdef HAVE_WINDOW_SYSTEM defsubr (&Stool_bar_lines_needed); + defsubr (&Slookup_image_map); #endif defsubr (&Sformat_mode_line); @@ -21076,16 +21406,14 @@ syms_of_xdisp () staticpro (&Qspace); Qmargin = intern ("margin"); staticpro (&Qmargin); + Qpointer = intern ("pointer"); + staticpro (&Qpointer); Qleft_margin = intern ("left-margin"); staticpro (&Qleft_margin); Qright_margin = intern ("right-margin"); staticpro (&Qright_margin); - Qalign_to = intern ("align-to"); - staticpro (&Qalign_to); QCalign_to = intern (":align-to"); staticpro (&QCalign_to); - Qrelative_width = intern ("relative-width"); - staticpro (&Qrelative_width); QCrelative_width = intern (":relative-width"); staticpro (&QCrelative_width); QCrelative_height = intern (":relative-height"); @@ -21104,6 +21432,16 @@ syms_of_xdisp () staticpro (&Qtrailing_whitespace); Qimage = intern ("image"); staticpro (&Qimage); + QCmap = intern (":map"); + staticpro (&QCmap); + QCpointer = intern (":pointer"); + staticpro (&QCpointer); + Qrect = intern ("rect"); + staticpro (&Qrect); + Qcircle = intern ("circle"); + staticpro (&Qcircle); + Qpoly = intern ("poly"); + staticpro (&Qpoly); Qmessage_truncate_lines = intern ("message-truncate-lines"); staticpro (&Qmessage_truncate_lines); Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows"); @@ -21128,6 +21466,12 @@ syms_of_xdisp () staticpro (&Qbox); Qhollow = intern ("hollow"); staticpro (&Qhollow); + Qhand = intern ("hand"); + staticpro (&Qhand); + Qarrow = intern ("arrow"); + staticpro (&Qarrow); + Qtext = intern ("text"); + staticpro (&Qtext); Qrisky_local_variable = intern ("risky-local-variable"); staticpro (&Qrisky_local_variable); Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces"); @@ -21181,10 +21525,11 @@ wide as that tab on the display. */); The face used for trailing whitespace is `trailing-whitespace'. */); Vshow_trailing_whitespace = Qnil; - DEFVAR_LISP ("show-text-cursor-in-void", &Vshow_text_cursor_in_void, - doc: /* Non-nil means show the text cursor in void text areas. -The default is to show the non-text (typically arrow) cursor. */); - Vshow_text_cursor_in_void = Qnil; + DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer, + doc: /* The pointer shape to show in void text areas. +Nil means to show the text pointer. Other options are `arrow', `text', +`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */); + Vvoid_text_area_pointer = Qarrow; DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay, doc: /* Non-nil means don't actually do any redisplay. From d7078aefa029a7f6beea9fb0803305600ab7d0f5 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:12:45 +0000 Subject: [PATCH 38/42] (cache_face): Abort if c->size exceeds MAX_FACE_ID. --- src/xfaces.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/xfaces.c b/src/xfaces.c index f079e2e4484..55455abdbd7 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -5577,12 +5577,19 @@ cache_face (c, face, hash) face->id = i; /* Maybe enlarge C->faces_by_id. */ - if (i == c->used && c->used == c->size) + if (i == c->used) { - int new_size = 2 * c->size; - int sz = new_size * sizeof *c->faces_by_id; - c->faces_by_id = (struct face **) xrealloc (c->faces_by_id, sz); - c->size = new_size; + if (c->used == c->size) + { + int new_size, sz; + new_size = min (2 * c->size, MAX_FACE_ID); + if (new_size == c->size) + abort (); /* Alternatives? ++kfs */ + sz = new_size * sizeof *c->faces_by_id; + c->faces_by_id = (struct face **) xrealloc (c->faces_by_id, sz); + c->size = new_size; + } + c->used++; } #if GLYPH_DEBUG @@ -5601,8 +5608,6 @@ cache_face (c, face, hash) #endif /* GLYPH_DEBUG */ c->faces_by_id[i] = face; - if (i == c->used) - ++c->used; } From 15aa58c18e557ead24010b7c9f78bd94d5579cf8 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:13:10 +0000 Subject: [PATCH 39/42] (x_set_mouse_color): Remove bogus x_check_errors call. (Qimage): Remove extern (now in lisp.h). (valid_image_p, parse_image_spec): Use IMAGEP macro. --- src/xfns.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index cd50cbbc919..e940b16eba1 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1300,7 +1300,6 @@ x_set_mouse_color (f, arg, oldval) hourglass_cursor = XCreateFontCursor (dpy, XC_watch); x_check_errors (dpy, "bad hourglass pointer cursor: %s"); - x_check_errors (dpy, "bad nontext pointer cursor: %s"); if (!NILP (Vx_mode_pointer_shape)) { CHECK_NUMBER (Vx_mode_pointer_shape); @@ -4416,11 +4415,6 @@ the excessive values are ignored. */) static struct image_type *image_types; -/* The symbol `image' which is the car of the lists used to represent - images in Lisp. */ - -extern Lisp_Object Qimage; - /* The symbol `xbm' which is used as the type symbol for XBM images. */ Lisp_Object Qxbm; @@ -4500,7 +4494,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object tem; @@ -4602,7 +4596,7 @@ parse_image_spec (spec, keywords, nkeywords, type) int i; Lisp_Object plist; - if (!CONSP (spec) || !EQ (XCAR (spec), Qimage)) + if (!IMAGEP (spec)) return 0; plist = XCDR (spec); From 83c6eb57fcd9dc47e0d9ec84d40be5235985736c Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:13:34 +0000 Subject: [PATCH 40/42] (Qface, Qmouse_face): Remove unused externs. (x_draw_hollow_cursor): Draw cursor using glyph's rather than row's ascent and descent, to get a sensible height on tall rows. --- src/xterm.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index a3117846702..635ba643035 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -287,7 +287,7 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name; extern Lisp_Object Vx_no_window_manager; -extern Lisp_Object Qface, Qmouse_face, Qeql; +extern Lisp_Object Qeql; extern int errno; @@ -7271,13 +7271,6 @@ x_draw_hollow_cursor (w, row) struct glyph *cursor_glyph; GC gc; - /* Compute frame-relative coordinates from window-relative - coordinates. */ - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y) - + row->ascent - w->phys_cursor_ascent); - h = row->height - 1; - /* Get the glyph the cursor is on. If we can't tell because the current matrix is invalid or such, give up. */ cursor_glyph = get_phys_cursor_glyph (w); @@ -7294,6 +7287,19 @@ x_draw_hollow_cursor (w, row) wd = min (FRAME_COLUMN_WIDTH (f), wd); w->phys_cursor_width = wd; + /* Compute frame-relative coordinates from window-relative + coordinates. */ + x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y); + + /* Compute the proper height and ascent of the rectangle, based + on the actual glyph. Using the full height of the row looks + bad when there are tall images on that row. */ + h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent); + if (h < row->height) + y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h; + h--; + /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ xgcv.foreground = f->output_data.x->cursor_pixel; From 204fb75e80e828ddcc944a41907a7fcd69099964 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:15:01 +0000 Subject: [PATCH 41/42] Fix cursor glyph height on tall rows. Add image map feature. Add pointer text property. --- src/ChangeLog | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/ChangeLog b/src/ChangeLog index fc1445a46dd..53cc3b8ad2f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,80 @@ +2003-12-28 Kim F. Storm + + * Makefile.in (eval.o): Depend on dispextern.h. + + * dispnew.c (buffer_posn_from_coords): Fix calculation of dy for + image glyph using image's ascent. + (mode_line_string): Return image glyph as object clicked on. + Adjust y0 for image glyph using image's ascent. + + * dispextern.h (FACE_ID_BITS, MAX_FACE_ID): New defines. + (struct glyph): New members, ascent and descent. Used to save + this glyph's ascent and descent, instead of having. + (struct glyph): Declare member face_id using FACE_ID_BITS. + (find_hot_spot): Add prototype. + + * keyboard.c (Qimage): Remove extern (now in lisp.h). + (QCmap): Declare extern. + (make_lispy_position): When position is inside image hot-spot, + use hot-spot element's id as posn element. + + * lisp.h (IMAGEP): New macro to test for image object type. + (Qimage): Declare extern. + + * macfns.c (Qimage): Remove extern (now in lisp.h). + (valid_image_p, parse_image_spec): Use IMAGEP macro. + + * macterm.c (Qface, Qmouse_face): Remove unused externs. + + * w32fns.c (Qimage): Remove extern (now in lisp.h). + (valid_image_p, parse_image_spec): Use IMAGEP macro. + + * w32menu.c (Qmouse_click, Qevent_kind): Remove unused externs. + + * w32term.c (Qface, Qmouse_face): Remove unused externs. + + * xdisp.c (Qarrow, Qhand, Qtext, Qpointer): New variables for + pointer types. + (Qrelative_width, Qalign_to): Remove unused variables. + (Vvoid_text_area_pointer): Replace Vshow_text_cursor_in_void. + (QCmap, QCpointer, Qrect, Qcircle, Qpoly): New variables for + image maps. + (x_y_to_hpos_vpos): Return glyph relative coordinates through + new dx and dy args. + Remove buffer_only_p arg (always 0). Simplify code accordingly. + (get_glyph_string_clip_rect): Draw cursor using glyph's rather + than row's ascent and height, to get sensible height on tall rows. + (build_desired_tool_bar_string): Remove Qimage extern. + (get_tool_bar_item): Fix call to x_y_to_hpos_vpos. + (produce_image_glyph): Adjust it.ascent to minimum row ascent if + image glyph is alone on the last line. + (append_glyph, append_composite_glyph, produce_image_glyph) + (append_stretch_glyph): Set glyph's ascent and descent. + (on_hot_spot_p): New function to check if position is inside an + rectangular, circular, or polygon-shaped image hot-spot, + (find_hot_spot): New function to search for image hot-spot. + (Flookup_image_map): New defun to search for image hot-spot. + (define_frame_cursor1): New aux function to determine frame pointer. + (note_mode_line_or_margin_highlight, note_mouse_highlight): + Handle `pointer' text property and :pointer image property to + control frame pointer shape. Detect image hot-spots for pointer + and help_echo properties. Use define_frame_cursor1. + (note_mouse_highlight): Use Vvoid_text_area_pointer. + (syms_of_xdisp): Defsubr new defun. Intern and staticpro new variables. + DEFVAR_LISP Vvoid_text_area_pointer instead of Vshow_text_cursor_in_void. + + * xfaces.c (cache_face): Abort if c->size exceeds MAX_FACE_ID. + + * xfns.c (x_set_mouse_color): Remove bogus x_check_errors call. + (Qimage): Remove extern (now in lisp.h). + (valid_image_p, parse_image_spec): Use IMAGEP macro. + + * xmenu.c (show_help_event): Remove unused code. + + * xterm.c (Qface, Qmouse_face): Remove unused externs. + (x_draw_hollow_cursor): Draw cursor using glyph's rather than + row's ascent and descent, to get a sensible height on tall rows. + 2003-12-25 Luc Teirlinck * minibuf.c (Fcompleting_read): Undo previous change. From 69348b2a71cbabeb23e3b7d5dce354c5bc4bd311 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sun, 28 Dec 2003 00:40:46 +0000 Subject: [PATCH 42/42] Add pointer text property. Add image maps. --- etc/NEWS | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index c4e9291c5ae..13a8b93dc0f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1740,6 +1740,40 @@ return value of `get-char-property' called with those arguments and whose cdr is the overlay in which the property was found, or nil if it was found as a text property or not found at all. +** The mouse pointer shape in void text areas (i.e. after the end of a +line or below the last line in the buffer) of the text window is now +controlled by the new variable `void-text-area-pointer'. The default +is to use the `arrow' (non-text) pointer. Other choices are `text' +(or nil), `hand', `vdrag', `hdrag', `modeline', and `hourglass'. + +** The mouse pointer shape over an image can now be controlled by the +:pointer image property. + +** The mouse pointer shape over ordinary text or images may now be +controlled/overriden via the `pointer' text property. + +** Images may now have an associated image map via the :map property. + +An image map is an alist where each element has the format (AREA ID PLIST). +An AREA is specified as either a rectangle, a circle, or a polygon: +A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the +pixel coordinates of the upper left and bottom right corners. +A circle is a cons (circle . ((x0 . y0) . r)) specifying the center +and the radius of the circle; r may be a float or integer. +A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the +vector describes one corner in the polygon. + +When the mouse pointer is above a hot-spot area of an image, the +PLIST of that hot-spot is consulted; if it contains a `help-echo' +property it defines a tool-tip for the hot-spot, and if it contains +a `pointer' property, it defines the shape of the mouse cursor when +it is over the hot-spot. See the variable 'void-area-text-pointer' +for possible pointer shapes. + +When you click the mouse when the mouse pointer is over a hot-spot, +an event is composed by combining the ID of the hot-spot with the +mouse event, e.g. [area4 mouse-1] if the hot-spot's ID is `area4'. + ** Mouse event enhancements: *** Mouse clicks on fringes now generates left-fringe or right-fringes