(U+6215): Apply new conventions for glyph granularity.
[chise/xemacs-chise.git.1] / man / lispref / specifiers.texi
index 43d9088..dfdc88a 100644 (file)
@@ -1,6 +1,7 @@
 @c -*-texinfo-*-
 @c This is part of the XEmacs Lisp Reference Manual.
 @c Copyright (C) 1995, 1996 Ben Wing.
+@c Copyright (C) 2002, 2004 Free Software Foundation, Inc.
 @c See the file lispref.texi for copying conditions.
 @setfilename ../../info/specifiers.info
 @node Specifiers, Faces and Window-System Objects, Extents, top
@@ -8,54 +9,56 @@
 @cindex specifier
 
 A specifier is an object used to keep track of a property whose value
-may vary depending on the particular situation (e.g. particular buffer
-displayed in a particular window) that it is used in.  The value of many
-built-in properties, such as the font, foreground, background, and such
-properties of a face and variables such as
-@code{modeline-shadow-thickness} and @code{top-toolbar-height}, is
-actually a specifier object.  The specifier object, in turn, is
-``instanced'' in a particular situation to yield the real value
-of the property in that situation.
+should vary according to @emph{display context}, a window, a frame, or
+device.  The value of many built-in properties, such as the font,
+foreground, background, and such properties of a face and variables
+such as @code{modeline-shadow-thickness} and
+@code{top-toolbar-height}, is actually a specifier object.  The
+specifier object, in turn, is ``instanced'' in a particular situation
+to yield the real value of the property in the current context.
 
 @defun specifierp object
 This function returns non-@code{nil} if @var{object} is a specifier.
 @end defun
 
 @menu
-* Introduction to Specifiers:: Specifiers provide a clean way for
-                               display and other properties to vary
-                               (under user control) in a wide variety
-                               of contexts.
-* Specifiers In-Depth::                Gory details about specifier innards.
-* Specifier Instancing::       Instancing means obtaining the ``value'' of
-                               a specifier in a particular context.
-* Specifier Types::            Specifiers come in different flavors.
-* Adding Specifications::      Specifications control a specifier's ``value''
-                               by giving conditions under which a
-                               particular value is valid.
-* Retrieving Specifications::  Querying a specifier's specifications.
-* Specifier Tag Functions::    Working with specifier tags.
+* Introduction to Specifiers::  Specifiers provide a clean way for
+                                display and other properties to vary
+                                (under user control) in a wide variety
+                                of contexts.
+* Simple Specifier Usage::      Getting started with specifiers.
+* Specifiers In-Depth::         Gory details about specifier innards.
+* Specifier Instancing::        Instancing means obtaining the ``value'' of
+                                a specifier in a particular context.
+* Specifier Types::             Specifiers come in different flavors.
+* Adding Specifications::       Specifications control a specifier's ``value''
+                                by giving conditions under which a
+                                particular value is valid.
+* Retrieving Specifications::   Querying a specifier's specifications.
+* Specifier Tag Functions::     Working with specifier tags.
 * Specifier Instancing Functions::
-                               Functions to instance a specifier.
-* Specifier Example::          Making all this stuff clearer.
-* Creating Specifiers::                Creating specifiers for your own use.
+                                Functions to instance a specifier.
+* Specifier Examples::          Making all this stuff clearer.
+* Creating Specifiers::         Creating specifiers for your own use.
 * Specifier Validation Functions::
-                               Validating the components of a specifier.
+                                Validating the components of a specifier.
 * Other Specification Functions::
-                               Other ways of working with specifications.
+                                Other ways of working with specifications.
 @end menu
 
 @node Introduction to Specifiers
 @section Introduction to Specifiers
 
-Sometimes you may want the value of a property to vary depending on
-the context the property is used in.  A simple example of this in XEmacs
-is buffer-local variables.  For example, the variable
+Perhaps the most useful way to explain specifiers is via an analogy.
+Emacs Lisp programmers are used to @emph{buffer-local variables}
+@ref{Buffer-Local Variables}. For example, the variable
 @code{modeline-format}, which controls the format of the modeline, can
 have different values depending on the particular buffer being edited.
 The variable has a default value which most modes will use, but a
-specialized package such as Calendar might change the variable so
-as to tailor the modeline to its own purposes.
+specialized package such as Calendar might change the variable so as to
+tailor the modeline to its own purposes. Other variables are perhaps
+best thought of as ``mode local,'' such as font-lock keywords, but they
+are implemented as buffer locals.
 
 Other properties (such as those that can be changed by the
 @code{modify-frame-parameters} function, for example the color of the
@@ -70,11 +73,41 @@ displayed on a particular frame, another value in all other buffers
 displayed in all other frames on any mono (two-color, e.g. black and
 white only) displays, and a default value in all other circumstances.
 
-A @dfn{specifier} is a generalization of this, allowing a great deal
-of flexibility in controlling exactly what value a property has in which
-circumstances.  It is most commonly used for display properties, such as
-an image or the foreground color of a face.  As a simple example, you can
-specify that the foreground of the default face be
+Specifiers generalize both buffer- and frame-local properties.
+Specifiers vary according to the @emph{display} context.  Font-lock
+keywords in a buffer will be the same no matter which window the
+buffer is displayed in, but windows on TTY devices will simply not be
+capable of the flexibility that windows on modern GUI devices are.
+Specifiers provide a way for the programmer to @emph{declare} that an
+emphasized text should be italic on GUI devices and inverse video on
+TTYs.  They also provide a way for the programmer to declare
+fallbacks, so that a color specified as ``chartreuse'' where possible
+can fall back to ``yellow'' on devices where only ANSI (4-bit) color
+is available.  The complex calculations and device querying are
+transparent to both user and programmer.  You ask for what you want;
+it's up to XEmacs to provide it, or a reasonable approximation.
+
+We call such a declaration a @dfn{specification}.  A @dfn{specification}
+applies in a particular @dfn{locale}, which is a window, buffer, frame,
+device, or the global locale.  The value part of the specification is
+called an @dfn{instantiator}.  The process of determining the value in a
+particular context, or @dfn{domain}, is called @dfn{instantiation} or
+@dfn{instancing}.  A domain is a window, frame, or device.
+
+The difference between @dfn{locale} and @dfn{domain} is somewhat subtle.
+You may think of a locale as a class of domains, which may span
+different devices.  Since the specification is abstract (a Lisp form),
+you can state it without reference to a device.  On the other hand, when
+you instantiate a specification, you must know the type of the device.
+It is useless to specify that ``blue means emphasis'' on a monochrome
+device.  Thus instantiation requires specification of the device on
+which it will be rendered.
+
+Thus a @dfn{specifier} allows a great deal of flexibility in
+controlling exactly what value a property has in which circumstances.
+Specifiers are most commonly used for display properties, such as an image or
+the foreground color of a face.  As a simple example, you can specify
+that the foreground of the default face be
 
 @itemize @bullet
 @item
@@ -98,6 +131,150 @@ red for all other buffers displayed on a color device
 white for all other buffers
 @end itemize
 
+@node Simple Specifier Usage
+@section Simple Specifier Usage
+@cindex specifier examples
+@cindex examples, specifier
+@cindex adding a button to a toolbar
+@cindex toolbar button, adding
+
+A useful specifier application is adding a button to a toolbar.  XEmacs
+provides several toolbars, one along each edge of the frame.  Normally
+only one is used at a time, the default.  The default toolbar is
+actually a specifier object which is the value of
+@code{default-toolbar}.  @xref{Toolbar Intro}.
+
+The specification of a toolbar is simple:  it is a list of buttons.
+Each button is a vector with four elements:  an icon, a command, the
+enabled flag, and a help string.  Let's retrieve the instance of the
+toolbar you see in the selected frame.
+
+@example
+(specifier-instance default-toolbar)
+@end example
+
+The value returned is, as promised, a list of vectors.  Now let's build
+up a button, and add it to the toolbar.  Our button will invoke the last
+defined keyboard macro.  This is an alternative to
+@code{name-last-kbd-macro} for creating a persistent macro, rather than
+an alias for @kbd{C-x e}.
+
+A toolbar button icon can be quite sophisticated, with different images
+for button up, button down, and disabled states, and a similar set with
+captions.  We'll use a very simple icon, but we have to jump through a
+few non-obvious hoops designed to support the sophisticated applications.
+The rest of the button descriptor is straightforward.
+
+@example
+(setq toolbar-my-kbd-macro-button
+  `[ (list (make-glyph "MyKbdMac"))
+     (lambda () (interactive) (execute-kbd-macro ,last-kbd-macro))
+     t
+     "Execute a previously defined keyboard macro." ])
+
+(set-specifier default-toolbar
+               (cons toolbar-my-kbd-macro-button
+                     (specifier-specs default-toolbar 'global))
+               'global)
+@end example
+
+To remove the button, just substitute the function @code{delete} for the
+@code{cons} above.
+
+What is the difference between @code{specifier-instance}, which we used
+in the example of retrieving the toolbar descriptor, and
+@code{specifier-specs}, which was used in the toolbar manipulating code?
+@code{specifier-specs} retrieves a copy of the instantiator, which is
+abstract and does not depend on context.  @code{specifier-instance}, on
+the other hand, actually instantiates the specification, and returns the
+result for the given context.  Another way to express this is:
+@code{specifier-specs} takes a @emph{locale} as an argument, while
+@code{specifier-instance} takes a @emph{domain}.  The reason for
+providing @code{specifier-instance} is that sometimes you wish to see
+the object that XEmacs will actually use.  @code{specifier-specs}, on
+the other hand, shows you what the programmer (or user) requested.  When
+a program manipulates specifications, clearly it's the latter that is
+desirable.
+
+In the case of the toolbar descriptor, it turns out that these are the
+same:  the instancing process is trivial.  However, many specifications
+have non-trivial instancing.  Compare the results of the following forms
+on my system.  (The @samp{(cdr (first ...))} form is due to my use of
+Mule.  On non-Mule XEmacsen, just use @code{specifier-specs}.)
+
+@example
+(cdr (first (specifier-specs (face-font 'default) 'global)))
+=> "-*--14-*jisx0208*-0"
+
+(specifier-instance (face-font 'default))
+#<font-instance "-*--14-*jisx0208*-0" on #<x-device on ":0.0" 0x970> 0xe0028b 0x176b>
+@end example
+
+In this case, @code{specifier-instance} returns an opaque object;
+programs can't work on it, they can only pass it around.  Worse, in some
+environments the instantiation will fail, resulting in a different value
+(when another instantiation succeeds), or worse yet, an error, if all
+attempts to instance the specifier fail.  @code{specifier-instance} is
+context-dependent, even for the exact same specification.
+@code{specifier-specs} is deterministic, and only depends on the
+specifications.
+
+Note that in the toolbar-changing code we operate in the global locale.
+This means that narrower locales, if they have specifications, will
+shadow our changes.  (Specifier instancing does not merge
+specifications.  It selects the "highest-priority successful
+specification" and instances that.)
+
+In fact, in our example, it seems pretty likely that different buffers
+@emph{should} have different buttons.  (The icon can be the same, but
+the keyboard macro you create in a Dired buffer is highly unlikely to be
+useful in a LaTeX buffer!)  Here's one way to implement this:
+
+@example
+(setq toolbar-my-kbd-macro-button
+  `[ (list (make-glyph "MyKbdMac"))
+     (lambda () (interactive) (execute-kbd-macro ,last-kbd-macro))
+     t
+     "Execute a previously defined keyboard macro." ])
+
+(set-specifier default-toolbar
+               (cons toolbar-my-kbd-macro-button
+                     (cond ((specifier-specs default-toolbar
+                                             (current-buffer)))
+                           ((specifier-specs default-toolbar
+                                             'global)))
+               (current-buffer))
+@end example
+
+Finally, a cautionary note: the use of @code{specifier-specs} in the
+code above is for expository purposes.  Don't use it in production code.
+In fact, the @code{set-specifier} form above is likely to fail
+occasionally, because you can add many specifications for the same
+locale.
+
+In these cases, @code{specifier-specs} will return a list.  A further
+refinement is that a specification may be associated with a set of
+@dfn{specifier tags}.  If the list of specifier tags is non-nil, then
+@code{specifier-specs} will return a cons of the tag set and the
+instantiator.  Evidently @code{specifier-specs} is a bit unreliable.
+(For toolbars, the code above should work 99% of the time, because
+toolbars are rarely changed.  Since instantiation is trivial, multiple
+specs are not useful---the first one always succeeds.)
+
+In fact, @code{specifier-specs} is intended to be used to display specs
+to humans with a minimum of clutter. The robust way to access
+specifications is via @code{specifier-spec-list}. @xref{Adding
+Specifications}, for the definition of @dfn{spec-list}. @xref{Retrieving
+Specifications}, for documentation of @code{specifier-specs} and
+@code{specifier-spec-list}. To get the desired effect, replace the form
+@code{(specifier-spec default-toolbar 'global)} with
+
+@example
+(cdr (second (first (specifier-spec-list default-toolbar 'global))))
+@end example
+
+(It should be obvious why the example uses the lazy unreliable method!)
+
 @node Specifiers In-Depth
 @section In-Depth Overview of a Specifier
 @cindex specification (in a specifier)
@@ -121,12 +298,36 @@ white for all other buffers
 @cindex specifier, tag
 @cindex specifier, tag set
 
-A specifier object encapsulates a set of @dfn{specifications}, each of
-which says what its value should be if a particular condition applies.
+Having variables vary according the editing context is very useful, and
+the buffer is the natural ``atomic'' unit of editing context.  In a GUI
+environment, it can be similarly useful to have variables whose values
+vary according to display context.  The atomic unit of display context
+is the Emacs window.  Buffers are cleanly grouped by modes, but windows
+are not so easily pigeonholed.  On the one hand, a window displays a
+buffer, and thus one possible hierarchy is window, buffer, mode.  On the
+other, a window is a component of a frame.  This generates the window,
+frame, device hierarchy.  Finally, there are objects such as toolbars
+whose properties are described by specifiers.  These do not fit
+naturally into either hierarchy.  This problem is as yet not cleanly
+solved.
+
+Another potential source of conceptual confusion is the instantiation
+process.  Instantiating a buffer-local variable is simple: at any given
+point in time there is a current buffer, and its local values are used
+and set whenever the variable is accessed, unless the programmer goes to
+some special effort (uses @code{default-value} and @code{set-default}.
+However, a specifier object encapsulates a set of @dfn{specifications},
+each of which says what its value should be if a particular condition
+applies.  Several such conditions might apply simultaneously in a given
+window.
+
 For example, one specification might be ``The value should be
 darkseagreen2 on X devices'' another might be ``The value should be blue
-in the *Help* buffer''.  In specifier terminology, these conditions are
-called @dfn{locales} and the values are called @dfn{instantiators}.
+in the *Help* buffer''.  So what do we do for "the *Help* buffer on an X
+device"?  The answer is simple: give each type of locale a priority and
+check them in priority order, returning the first instantiator that
+successfully instantiates a value.
+
 Given a specifier, a logical question is ``What is its value in a
 particular situation?'' This involves looking through the specifications
 to see which ones apply to this particular situation, and perhaps
@@ -140,6 +341,13 @@ of the default face and @dfn{instances} it in the domain given by that
 window; in other words, it asks the specifier, ``What is your value in
 this window?''.
 
+Note that the redisplay example is in a sense canonical.  That is,
+specifiers are designed to present a uniform and @emph{efficient} API
+to redisplay.  It is the efficiency constraint that motivates the
+introduction of specifier tags, and many restrictions on access (for
+example, a buffer is not a domain, and you cannot instantiate a
+specifier over a buffer).
+
 More specifically, a specifier contains a set of @dfn{specifications},
 each of which associates a @dfn{locale} (a window object, a buffer
 object, a frame object, a device object, or the symbol @code{global})
@@ -160,8 +368,9 @@ same specifier and not interfere with each other.  Each tag can have a
 device. (If a tag does not have a predicate, it matches all devices.)
 All tags in a tag set must match a device for the associated inst-pair
 to be instantiable over that device.  (A null tag set is perfectly
-valid.)
+valid, and trivially matches all devices.)
 
+@c #### don't we have more device types now, gtk, ms-windows, mac-carbon?
 The valid device types (normally @code{x}, @code{tty}, and
 @code{stream}) and device classes (normally @code{color},
 @code{grayscale}, and @code{mono}) can always be used as tags, and match
@@ -169,7 +378,7 @@ devices of the associated type or class (@pxref{Consoles and Devices}).
 User-defined tags may be defined, with an optional predicate specified.
 An application can create its own tag, use it to mark all its
 instantiators, and be fairly confident that it will not interfere with
-other applications that modify the same specifier -- Functions that add
+other applications that modify the same specifier---Functions that add
 a specification to a specifier usually only overwrite existing
 inst-pairs with the same tag set as was given, and a particular tag or
 tag set can be specified when removing instantiators.
@@ -196,7 +405,7 @@ under X is usually a wildcard specification that may resolve to
 different font names, with possibly different foundries, widths, etc.,
 on different devices), the extra properties of that font on that
 device, etc.  Furthermore, this conversion (called @dfn{instantiation})
-might fail -- a font or color might not exist on a particular device,
+might fail---a font or color might not exist on a particular device,
 for example.
 
 @node Specifier Instancing
@@ -325,7 +534,7 @@ or the symbol @code{nil}.
 @item toolbar
 The valid instantiators are toolbar descriptors, which are lists
 of toolbar-button descriptors (each of which is a vector of two
-or four elements).  @xref{Toolbar} for more information.
+or four elements).  @xref{Toolbar}, for more information.
 @end table
 
 Color and font instance objects can also be used in turn as
@@ -335,9 +544,9 @@ directly as the new instance object, but only if they are of the same
 device.  If the devices differ, the base color or font of the
 instantiating object is effectively used instead as the instantiator.
 
-@xref{Faces and Window-System Objects} for more information on fonts,
-colors, and face-boolean specifiers.  @xref{Glyphs} for more information
-about image specifiers.  @xref{Toolbar} for more information on toolbar
+@xref{Faces and Window-System Objects}, for more information on fonts,
+colors, and face-boolean specifiers.  @xref{Glyphs}, for more information
+about image specifiers.  @xref{Toolbar}, for more information on toolbar
 specifiers.
 
 @defun specifier-type specifier
@@ -474,11 +683,16 @@ specifications.
 the existing ones, and has the same semantics as for
 @code{add-spec-to-specifier}.
 
-In many circumstances, the higher-level function @code{set-specifier} is
-more convenient and should be used instead.
+The higher-level function @code{set-specifier} is often
+more convenient because it allows abbreviations of spec-lists to be used
+instead of the heavily nested canonical syntax.  However, one should
+take great care in using them with specifiers types which can have lists
+as instantiators, such as toolbar specifiers and generic specifiers.  In
+those cases it's probably best to use @code{add-spec-to-specifier} or
+@code{add-spec-list-to-specifier}.
 @end defun
 
-@deffn Macro let-specifier specifier-list &rest body
+@defspec let-specifier specifier-list &rest body
 This special form temporarily adds specifications to specifiers,
 evaluates forms in @var{body} and restores the specifiers to their
 previous states.  The specifiers and their temporary specifications are
@@ -516,18 +730,19 @@ selected window for the duration of a second:
 (let-specifier ((modeline-shadow-thickness 0 (selected-window)))
   (sit-for 1))
 @end example
-@end deffn
+@end defspec
 
-@defun set-specifier specifier value &optional how-to-add
+@defun set-specifier specifier value &optional locale tag-set how-to-add
 This function adds some specifications to @var{specifier}.  @var{value}
 can be a single instantiator or tagged instantiator (added as a global
 specification), a list of tagged and/or untagged instantiators (added as
 a global specification), a cons of a locale and instantiator or locale
 and instantiator list, a list of such conses, or nearly any other
 reasonable form.  More specifically, @var{value} can be anything
-accepted by @code{canonicalize-spec-list}.
+accepted by @code{canonicalize-spec-list} (described below).
 
-@var{how-to-add} is the same as in @code{add-spec-to-specifier}.
+@var{locale}, @var{tag-set}, and @var{how-to-add} are the same as in
+@code{add-spec-to-specifier}.
 
 Note that @code{set-specifier} is exactly complementary to
 @code{specifier-specs} except in the case where @var{specifier} has no
@@ -537,7 +752,10 @@ specs at all in it but @code{nil} is a valid instantiator (in that case,
 adding a global instantiator and its value is @code{nil}''), or in
 strange cases where there is an ambiguity between a spec-list and an
 inst-list, etc. (The built-in specifier types are designed in such a way
-as to avoid any such ambiguities.)
+as to avoid any such ambiguities.)  For robust code,
+@code{set-specifier} should probably be avoided for specifier types
+which accept lists as instantiators (currently toolbar specifiers and
+generic specifiers).
 
 If you want to work with spec-lists, you should probably not use these
 functions, but should use the lower-level functions
@@ -600,6 +818,10 @@ specifications).
 @var{specifier-type} specifies the type of specifier that this
 @var{spec-list} will be used for.
 
+If @var{noerror} is @code{nil}, signal an error if the spec-list is
+invalid; otherwise return @code{t} for an invalid spec-list.  (Note that
+this cannot be confused with a canonical spec-list.)
+
 Canonicalizing means converting to the full form for a spec-list, i.e.
 @code{((@var{locale} (@var{tag-set} . @var{instantiator}) ...) ...)}.
 This function accepts a possibly abbreviated specification or a list of
@@ -611,8 +833,59 @@ This function tries extremely hard to resolve any ambiguities,
 and the built-in specifier types (font, image, toolbar, etc.) are
 designed so that there won't be any ambiguities.
 
-If @var{noerror} is @code{nil}, signal an error if the spec-list is
-invalid; otherwise return @code{t}.
+The canonicalization algorithm is as follows:
+
+@enumerate
+@item
+Attempt to parse @var{spec-list} as a single, possibly abbreviated,
+specification.
+@item
+If that fails, attempt to parse @var{spec-list} as a list of (abbreviated)
+specifications.
+@item
+If that fails, @var{spec-list} is invalid.
+@end enumerate
+
+A possibly abbreviated specification @var{spec} is parsed by
+
+@enumerate
+@item
+Attempt to parse @var{spec} as a possibly abbreviated inst-list.
+@item
+If that fails, attempt to parse @var{spec} as a cons of a locale and an
+(abbreviated) inst-list.
+@item
+If that fails, @var{spec} is invalid.
+@end enumerate
+
+A possibly abbreviated inst-list @var{inst-list} is parsed by
+
+@enumerate
+@item
+Attempt to parse @var{inst-list} as a possibly abbreviated inst-pair.
+@item
+If that fails, attempt to parse @var{inst-list} as a list of (abbreviated)
+inst-pairs.
+@item
+If that fails, @var{inst-list} is invalid.
+@end enumerate
+
+A possibly abbreviated inst-pair @var{inst-pair} is parsed by
+
+@enumerate
+@item
+Check if @var{inst-pair} is @code{valid-instantiator-p}.
+@item
+If not, check if @var{inst-pair} is a cons of something that is a tag, ie,
+@code{valid-specifier-tag-p}, and something that is @code{valid-instantiator-p}.
+@item
+If not, check if @var{inst-pair} is a cons of a list of tags and something that
+is @code{valid-instantiator-p}.
+@item
+Otherwise, @var{inst-pair} is invalid.
+@end enumerate
+
+In summary, this function generally prefers more abbreviated forms.
 @end defun
 
 @node Retrieving Specifications
@@ -626,7 +899,7 @@ If @var{locale} is a particular locale (a window, buffer, frame, device,
 or the symbol @code{global}), a spec-list consisting of the
 specification for that locale will be returned.
 
-If @var{locale} is a locale type (i.e. a symbol @code{window},
+If @var{locale} is a locale type (i.e. one of the symbols @code{window},
 @code{buffer}, @code{frame}, or @code{device}), a spec-list of the
 specifications for all locales of that type will be returned.
 
@@ -639,7 +912,7 @@ on each element of the list and the results concatenated together.
 
 Only instantiators where @var{tag-set} (a list of zero or more tags) is
 a subset of (or possibly equal to) the instantiator's tag set are
-returned.  (The default value of@code{ nil} is a subset of all tag sets,
+returned.  (The default value of @code{nil} is a subset of all tag sets,
 so in this case no instantiators will be screened out.) If @var{exact-p}
 is non-@code{nil}, however, @var{tag-set} must be equal to an
 instantiator's tag set for the instantiator to be returned.
@@ -703,7 +976,7 @@ and can be used to restrict the scope of that instantiator to a
 particular device class or device type and/or to mark instantiators
 added by a particular package so that they can be later removed.
 
-A specifier tag set consists of a list of zero of more specifier tags,
+A specifier tag set consists of a list of zero or more specifier tags,
 each of which is a symbol that is recognized by XEmacs as a tag.  (The
 valid device types and device classes are always tags, as are any tags
 defined by @code{define-specifier-tag}.) It is called a ``tag set'' (as
@@ -774,7 +1047,7 @@ This function returns the predicate for the given specifier tag.
 @section Functions for Instancing a Specifier
 
 @defun specifier-instance specifier &optional domain default no-fallback
-This function instantiates @var{specifier} (return its value) in
+This function instantiates @var{specifier} (returns its value) in
 @var{domain}.  If no instance can be generated for this domain, return
 @var{default}.
 
@@ -828,6 +1101,34 @@ returned value will be a font-instance object.  For images, the returned
 value will be a string, pixmap, or subwindow.
 @end defun
 
+@defun specifier-matching-instance specifier matchspec &optional domain default no-fallback
+This function returns an instance for @var{specifier} in @var{domain}
+that matches @var{matchspec}.  If no instance can be generated for
+@var{domain}, return @var{default}.
+
+This function is identical to @code{specifier-instance} except that a
+specification will only be considered if it matches @var{matchspec}.
+The definition of ``match,'' and allowed values for @var{matchspec}, are
+dependent on the particular type of specifier.  Here are some examples:
+
+@itemize
+@item
+For chartable (e.g. display table) specifiers, @var{matchspec} should be a
+character, and the specification (a chartable) must give a value for
+that character in order to be considered.  This allows you to specify,
+@emph{e.g.}, a buffer-local display table that only gives values for particular
+characters.  All other characters are handled as if the buffer-local
+display table is not there. (Chartable specifiers are not yet
+implemented.)
+@item
+For font specifiers, @var{matchspec} should be a charset,
+and the specification (a font string) must have
+a registry that matches the charset's registry.  (This only makes sense
+with Mule support.)  This makes it easy to choose a font that can
+display a particular character.  (This is what redisplay does, in fact.)
+@end itemize
+@end defun
+
 @defun specifier-instance-from-inst-list specifier domain inst-list &optional default
 This function attempts to convert a particular inst-list into an
 instance.  This attempts to instantiate @var{inst-list} in the given
@@ -837,8 +1138,8 @@ In most circumstances, you should not use this function; use
 @code{specifier-instance} instead.
 @end defun
 
-@node Specifier Example
-@section Example of Specifier Usage
+@node Specifier Examples
+@section Examples of Specifier Usage
 
 Now let us present an example to clarify the theoretical discussions we
 have been through.  In this example, we will use the general specifier
@@ -861,9 +1162,9 @@ First, let's retrieve the specifier:
     @result{}   ((#<buffer "device.c"> (nil . "forest green"))
                  (#<window on "Makefile" 0x8a2b> (nil . "hot pink"))
                  (#<x-frame "emacs" 0x4ac> (nil . "puke orange")
-                                          (nil . "moccasin"))
+                                           (nil . "moccasin"))
                  (#<x-frame "VM" 0x4ac> (nil . "magenta"))
-                (global ((tty) . "cyan") (nil . "white"))
+                 (global ((tty) . "cyan") (nil . "white"))
                 )
 @end example
 
@@ -890,7 +1191,7 @@ The result is arrived at like this:
 @enumerate
 @item
 First, we look for a specification matching the buffer displayed in the
-window, i.e. @samp{*scratch}.  There are none, so we proceed.
+window, i.e. @samp{*scratch*}.  There are none, so we proceed.
 @item
 Then, we look for a specification matching the window itself.  Again, there
 are none.
@@ -911,6 +1212,143 @@ our window is on recognizes the color @samp{moccasin}, and so the
 instantiation method succeeds and returns a color instance.
 @end enumerate
 
+Here's another example, which implements something like GNU Emacs's
+``frame-local'' variables.
+
+@example
+;; Implementation
+
+;; There are probably better ways to write this macro
+;; Heaven help you if VAR is a buffer-local; you will become very
+;; confused.  Probably should error on that.
+(defmacro define-frame-local-variable (var)
+  "Make the unbound symbol VAR become a frame-local variable."
+  (let ((val (if (boundp var) (symbol-value var) nil)))
+    `(progn
+      (setq ,var (make-specifier 'generic))
+      (add-spec-to-specifier ,var ',val 'global))))
+
+;; I'm not real happy about this terminology, how can `setq' be a defun?
+;; But `frame-set' would have people writing "(frame-set 'foo value)".
+(defun frame-setq (var value &optional frame)
+  "Set the local value of VAR to VALUE in FRAME.
+
+FRAME defaults to the selected frame."
+  (and frame (not (framep frame))
+       (error 'invalid-argument "FRAME must be a frame", frame))
+  (add-spec-to-specifier var value (or frame (selected-frame))))
+
+(defun frame-value (var &optional frame)
+  "Get the local value of VAR in FRAME.
+
+FRAME defaults to the selected frame."
+  (and frame (not (framep frame))
+       (error 'invalid-argument "FRAME must be a frame", frame))
+  ;; this is not just a map from frames to values; it also falls back
+  ;; to the global value
+  (specifier-instance var (or frame (selected-frame))))
+
+;; for completeness
+(defun frame-set-default (var value)
+  "Set the default value of frame-local variable VAR to VALUE."
+  (add-spec-to-specifier var value 'global))
+
+(defun frame-get-default (var)
+  "Get the default value of frame-local variable VAR."
+  (car (specifier-specs var 'global)))
+@end example
+
+Now you can execute the above definitions (eg, with @code{eval-last-sexp})
+and switch to @file{*scratch*} to play.  Things will work differently if
+you already have a variable named @code{foo}.
+
+@example
+;; Usage
+
+foo
+@error{} Symbol's value as variable is void: foo
+
+(define-frame-local-variable foo)
+@result{} nil
+
+;; the value of foo is a specifier, which is an opaque object;
+;; you must use accessor functions to get values
+
+foo
+@result{} #<generic-specifier global=(nil) 0x4f5cb>
+
+;; since no frame-local value is set, the global value (which is the
+;; constant `nil') is returned
+(frame-value foo)
+@result{} nil
+
+;; get the default explicitly
+(frame-get-default foo)
+@result{} nil
+
+;; get the whole specification list
+(specifier-specs foo 'global)
+@result{} (nil)
+
+;; give foo a frame-local value
+
+(frame-setq foo 'bar)
+@result{} nil
+
+;; access foo in several ways
+
+;; Note that the print function for this kind of specifier only
+;; gives you the global setting.  To get the full list of specs for
+;; debugging or study purposes, you must use specifier-specs or
+;; specifier-spec-list.
+foo
+@result{} #<generic-specifier global=(nil) 0x4f5cb>
+
+;; get the whole specification list
+(specifier-specs foo)
+@result{} ((#<x-frame "Message" 0x1bd66> (nil . bar)) (global (nil)))
+
+;; get the frame-local value
+(frame-value foo)
+@result{} bar
+
+;; get the default explicitly
+(frame-get-default foo)
+@result{} nil
+
+;; Switch to another frame and evaluate:
+;; C-x 5 o M-: (frame-setq foo 'baz) RET M-: (frame-value foo) RET
+@result{} baz
+
+;; Switch back.
+;; C-x 5 o
+(specifier-specs foo)
+@result{} ((#<x-frame "emacs" 0x28ec> (nil . baz))
+    (#<x-frame "Message" 0x1bd66> (nil . bar))
+    (global (nil)))
+
+(frame-value foo)
+@result{} bar
+
+(frame-get-default foo)
+@result{} nil
+@end example
+
+Note that since specifiers generalize both frame-local and buffer-local
+variables in a sensible way, XEmacs is not likely to put a high priority
+on implementing frame-local variables.
+@c Thanks to Jerry James for the following explanation.  He is not
+@c responsible for its use here, Stephen Turnbull is.
+In fact, some developers think that frame-local variables are evil for
+the same reason that buffer-local variables are evil: the declaration is
+both global and invisible.  That is, you cannot tell whether a variable
+is ``normal,'' buffer-local, or frame-local just by looking at it.  So
+if you have namespace management problems, and some other Lisp package
+happens to use a variable name that you already declared frame- or
+buffer-local, weird stuff happens, and it is extremely hard to track
+down.
+
+
 @node Creating Specifiers
 @section Creating New Specifier Objects
 
@@ -922,8 +1360,8 @@ whose value can be per-buffer, per-window, per-frame, or per-device,
 and can further be restricted to a particular device-type or device-class.
 Specifiers are used, for example, for the various built-in properties of a
 face; this allows a face to have different values in different frames,
-buffers, etc.  For more information, see `specifier-instance',
-`specifier-specs', and `add-spec-to-specifier'; or, for a detailed
+buffers, etc.  For more information, see @code{specifier-instance},
+@code{specifier-specs}, and @code{add-spec-to-specifier}; or, for a detailed
 description of specifiers, including how they are instantiated over a
 particular domain (i.e. how their value in that domain is determined),
 see the chapter on specifiers in the XEmacs Lisp Reference Manual.
@@ -934,24 +1372,81 @@ of the symbols @code{generic}, @code{integer}, @code{natnum},
 @code{face-boolean}, or @code{toolbar}.
 
 For more information on particular types of specifiers, see the
-functions @code{generic-specifier-p}, @code{integer-specifier-p},
-@code{natnum-specifier-p}, @code{boolean-specifier-p},
-@code{color-specifier-p}, @code{font-specifier-p},
-@code{image-specifier-p}, @code{face-boolean-specifier-p}, and
-@code{toolbar-specifier-p}.
+functions @code{make-generic-specifier}, @code{make-integer-specifier},
+@code{make-natnum-specifier}, @code{make-boolean-specifier},
+@code{make-color-specifier}, @code{make-font-specifier},
+@code{make-image-specifier}, @code{make-face-boolean-specifier}, and
+@code{make-toolbar-specifier}.
 @end defun
 
 @defun make-specifier-and-init type spec-list &optional dont-canonicalize
-This function creates and initialize a new specifier.
+This function creates and initializes a new specifier.
 
-This is a front-end onto @code{make-specifier} that allows you to create
+This is a convenience API combining @code{make-specifier} and
+@code{set-specifier} that allows you to create
 a specifier and add specs to it at the same time.  @var{type} specifies
-the specifier type.  @var{spec-list} supplies the specification(s) to be
-added to the specifier. Normally, almost any reasonable abbreviation of
-the full spec-list form is accepted, and is converted to the full form;
-however, if optional argument @var{dont-canonicalize} is non-@code{nil},
-this conversion is not performed, and the @var{spec-list} must already
-be in full form.  See @code{canonicalize-spec-list}.
+the specifier type.  Allowed types are as for @code{make-specifier}.
+
+@var{spec-list} supplies the specification(s) to be
+added to the specifier.  Any abbreviation of
+the full spec-list form accepted by @code{canonicalize-spec-list} may
+be used.
+However, if the optional argument @var{dont-canonicalize} is non-@code{nil},
+canonicalization is not performed, and the @var{spec-list} must already
+be in full form.
+@end defun
+
+@defun make-integer-specifier spec-list
+
+Return a new @code{integer} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.
+
+Valid instantiators for integer specifiers are integers.
+@end defun
+
+@defun make-boolean-specifier spec-list
+
+Return a new @code{boolean} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.
+
+Valid instantiators for boolean specifiers are @code{t} and @code{nil}.
+@end defun
+
+@defun make-natnum-specifier spec-list
+
+Return a new @code{natnum} specifier object with the given specification
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.
+
+Valid instantiators for natnum specifiers are non-negative integers.
+@end defun
+
+@defun make-generic-specifier spec-list
+
+Return a new @code{generic} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.
+
+Valid instantiators for generic specifiers are all Lisp values.  They
+are returned back unchanged when a specifier is instantiated.
+@end defun
+
+@defun make-display-table-specifier spec-list
+
+Return a new @code{display-table} specifier object with the given spec
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.
+
+Valid instantiators for display-table specifiers are described in detail
+in the doc string for @code{current-display-table} (@pxref{Active
+Display Table}).
 @end defun
 
 @node Specifier Validation Functions
@@ -971,7 +1466,7 @@ buffer, and @code{global}.  (@code{nil} is not valid.)
 @end defun
 
 @defun valid-specifier-locale-type-p locale-type
-Given a specifier @var{locale-type}, this function returns non-nil if it
+Given a specifier @var{locale-type}, this function returns non-@code{nil} if it
 is valid.  Valid locale types are the symbols @code{global},
 @code{device}, @code{frame}, @code{window}, and @code{buffer}. (Note,
 however, that in functions that accept either a locale or a locale type,
@@ -1048,7 +1543,7 @@ is non-@code{nil}, however, @var{tag-set} must be equal to an
 instantiator's tag set for the instantiator to be copied.
 
 Optional argument @var{how-to-add} specifies what to do with existing
-specifications in @var{dest}.  If nil, then whichever locales or locale
+specifications in @var{dest}.  If @code{nil}, then whichever locales or locale
 types are copied will first be completely erased in @var{dest}.
 Otherwise, it is the same as in @code{add-spec-to-specifier}.
 @end defun
@@ -1083,12 +1578,15 @@ instantiator's tag set for the instantiator to be removed.
 This function applies @var{func} to the specification(s) for
 @var{locale} in @var{specifier}.
 
-If @var{locale} is a locale, @var{func} will be called for that locale.
+If optional @var{locale} is a locale, @var{func} will be called for that
+locale.
 If @var{locale} is a locale type, @var{func} will be mapped over all
 locales of that type.  If @var{locale} is @code{nil} or the symbol
 @code{all}, @var{func} will be mapped over all locales in
 @var{specifier}.
 
+Optional @var{ms-maparg} will be passed to @var{ms-func}.
+
 @var{func} is called with four arguments: the @var{specifier}, the
 locale being mapped over, the inst-list for that locale, and the
 optional @var{maparg}.  If any invocation of @var{func} returns
@@ -1100,4 +1598,3 @@ value returned from @code{map-specifier}.  Otherwise,
 @defun specifier-locale-type-from-locale locale
 Given a specifier @var{locale}, this function returns its type.
 @end defun
-