This is specifier.h in view mode; [Download] [Up]
/* Generic specifier list implementation
Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
Copyright (C) 1995 Ben Wing
This file is part of XEmacs.
XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Synched up with: Not in FSF. */
#ifndef _XEMACS_SPECIFIER_H_
#define _XEMACS_SPECIFIER_H_
struct specifier_methods
{
CONST char *name;
Lisp_Object predicate_symbol;
/* Implementation specific methods: */
/* #### Document me */
/* Create method */
void (*create_method) (Lisp_Object specifier);
/* Mark method */
void (*mark_method) (Lisp_Object specifier, void (*markobj) (Lisp_Object));
/* Equal method */
int (*equal_method) (Lisp_Object sp1, Lisp_Object sp2, int depth);
/* Hash method */
unsigned long (*hash_method) (Lisp_Object specifier, int depth);
/* Validate method: Given an instantiator, return non-zero if it's
valid for this specifier type, zero otherwise. If NO_ERROR
is zero, the validation method can signal an error if the
instantiator is invalid. (This is so that a more explanatory
error message can be issued.) Even if NO_ERROR is zero,
however, this function can go ahead and return 0 for an
invalid instantiator. (In that case, the caller gets a generic
error message "Invalid instantiator".) If this functions is not
present, all instantiators are considered valid. */
int (*validate_method) (Lisp_Object instantiator, int no_error);
/* Instantiate method */
Lisp_Object (*instantiate_method) (Lisp_Object specifier,
Lisp_Object domain,
Lisp_Object instantiator,
int no_error_or_quit);
/* Going-to-add method: Called when an instantiator is about
to be added to a specifier. This function can specify
that different instantiators should be used instead by
returning an inst-list (possibly containing zero elements).
If the instantiator is fine as-is, return Qt. The
instantiator has been copied with copy-tree, so feel
free to reuse parts of it to create a new instantiator.
The tag-set, however, is not copied and is not canonicalized
(that will be done on the result of this function).
*/
Lisp_Object (*going_to_add_method) (Lisp_Object specifier,
Lisp_Object locale,
Lisp_Object tag_set,
Lisp_Object instantiator);
/* After-change method */
void (*after_change_method) (Lisp_Object specifier,
Lisp_Object locale);
int extra_data_size;
};
struct Lisp_Specifier
{
struct lcrecord_header header;
struct specifier_methods *methods;
/* we keep a chained list of all current specifiers, for GC cleanup
purposes. Do NOT mark through this, or specifiers will never
be GC'd. */
Lisp_Object next_specifier;
/* This is a straight list of instantiators. */
Lisp_Object global_specs;
/* These are all assoc lists where the key is type of object the
list represents (buffer, window, etc.) and the associated list is
the actual list of instantiators. */
Lisp_Object device_specs;
Lisp_Object frame_specs;
Lisp_Object window_specs;
Lisp_Object buffer_specs;
struct specifier_caching *caching;
Lisp_Object fallback;
/* type-specific extra data attached to a specifier */
char data[1];
};
DECLARE_LRECORD (specifier, struct Lisp_Specifier);
#define XSPECIFIER(x) XRECORD (x, specifier, struct Lisp_Specifier)
#define XSETSPECIFIER(x, p) XSETRECORD (x, p, specifier)
#define SPECIFIERP(x) RECORDP (x, specifier)
#define CHECK_SPECIFIER(x, i) CHECK_RECORD (x, specifier)
/***** Calling a specifier method *****/
#define HAS_SPECMETH_P(sp, m) ((sp)->methods->m##_method)
#define SPECMETH(sp, m, args) (((sp)->methods->m##_method) args)
/* Call a void-returning specifier method, if it exists */
#define MAYBE_SPECMETH(sp, m, args) \
do { \
struct Lisp_Specifier *_maybe_specmeth_sp = (sp); \
if (HAS_SPECMETH_P (_maybe_specmeth_sp, m)) \
SPECMETH (_maybe_specmeth_sp, m, args); \
} while (0)
MAC_DECLARE_EXTERN (struct Lisp_Specifier *, mactemp_specmeth_or_given)
/* Call a specifier method, if it exists; otherwise return
the specified value */
#define SPECMETH_OR_GIVEN(sp, m, args, given) \
MAC_BEGIN \
MAC_DECLARE (struct Lisp_Specifier *, mactemp_specmeth_or_given, sp) \
HAS_SPECMETH_P (mactemp_specmeth_or_given, m) ? \
SPECMETH (mactemp_specmeth_or_given, m, args) : (given) \
MAC_END
/***** Defining new specifier types *****/
#define DECLARE_SPECIFIER_TYPE(type) \
extern struct specifier_methods * type##_specifier_methods
#define DEFINE_SPECIFIER_TYPE(type) \
struct specifier_methods * type##_specifier_methods
#define INITIALIZE_SPECIFIER_TYPE(type, obj_name, pred_sym) \
do { \
type##_specifier_methods = \
malloc_type_and_zero (struct specifier_methods); \
type##_specifier_methods->name = obj_name; \
defsymbol (&type##_specifier_methods->predicate_symbol, \
pred_sym); \
add_entry_to_specifier_type_list (Q##type, \
type##_specifier_methods); \
} while (0) \
#define INITIALIZE_SPECIFIER_TYPE_WITH_DATA(type, obj_name, pred_sym) \
do { \
INITIALIZE_SPECIFIER_TYPE (type, obj_name, pred_sym); \
type##_specifier_methods->extra_data_size = \
sizeof (struct type##_specifier); \
} while (0)
/* Declare that specifier-type TYPE has method M; used in
initialization routines */
#define SPECIFIER_HAS_METHOD(type, m) \
(type##_specifier_methods->m##_method = type##_##m)
/***** Macros for accessing specifier types *****/
#define SPECIFIER_IS_TYPE(sp, type) \
((sp)->methods == type##_specifier_methods)
#ifdef ERROR_CHECK_TYPECHECK
MAC_DECLARE_EXTERN (struct Lisp_Specifier *, mactemp_specifier_data)
# define SPECIFIER_TYPE_DATA(sp, type) \
MAC_BEGIN \
MAC_DECLARE (struct Lisp_Specifier *, mactemp_specifier_data, sp) \
assert (SPECIFIER_IS_TYPE (mactemp_specifier_data, type)) \
MAC_SEP \
(struct type##_specifier *) mactemp_specifier_data->data \
MAC_END
#else
# define SPECIFIER_TYPE_DATA(sp, type) \
((struct type##_specifier *) (sp)->data)
#endif
/* #### Need to create ERROR_CHECKING versions of these. */
#define XSPECIFIER_TYPE(x, type) XSPECIFIER (x)
#define XSETSPECIFIER_TYPE(x, p, type) XSETSPECIFIER (x, p)
#define SPECIFIER_TYPEP(x, type) \
(SPECIFIERP (x) && SPECIFIER_IS_TYPE (XSPECIFIER (x), type))
#define CHECK_SPECIFIER_TYPE(x, i, type) \
do { \
CHECK_SPECIFIER (x, i); \
if (!(SPECIFIERP (x) && SPECIFIER_IS_TYPE (XSPECIFIER (x), \
type))) \
x = wrong_type_argument \
(type##_specifier_methods->predicate_symbol, x); \
} while (0)
/***** Miscellaneous structures *****/
enum spec_locale_type
{
LOCALE_GLOBAL,
LOCALE_DEVICE,
LOCALE_FRAME,
LOCALE_WINDOW,
LOCALE_BUFFER
};
enum spec_add_meth
{
SPEC_PREPEND,
SPEC_APPEND,
SPEC_REMOVE_TAG_SET_PREPEND,
SPEC_REMOVE_TAG_SET_APPEND,
SPEC_REMOVE_LOCALE,
SPEC_REMOVE_LOCALE_TYPE,
SPEC_REMOVE_ALL
};
struct specifier_caching
{
int offset_into_struct_window;
void (*value_changed_in_window) (Lisp_Object specifier, struct window *w,
Lisp_Object oldval);
int offset_into_struct_frame;
void (*value_changed_in_frame) (Lisp_Object specifier, struct frame *f,
Lisp_Object oldval);
};
extern Lisp_Object decode_locale (Lisp_Object locale);
extern Lisp_Object decode_locale_list (Lisp_Object locale);
extern Lisp_Object decode_domain (Lisp_Object domain);
extern enum spec_add_meth
decode_how_to_add_specification (Lisp_Object how_to_add);
extern Lisp_Object decode_specifier_tag_set (Lisp_Object tag_set);
extern void add_entry_to_specifier_type_list (Lisp_Object symbol,
struct specifier_methods *meths);
extern void set_specifier_caching (Lisp_Object specifier,
int struct_window_offset,
void (*value_changed_in_window)
(Lisp_Object specifier, struct window *w,
Lisp_Object oldval),
int struct_frame_offset,
void (*value_changed_in_frame)
(Lisp_Object specifier, struct frame *f,
Lisp_Object oldval));
extern void set_specifier_fallback (Lisp_Object specifier,
Lisp_Object fallback);
extern void recompute_all_cached_specifiers_in_window (struct window *w);
extern void recompute_all_cached_specifiers_in_frame (struct frame *f);
extern void cleanup_specifiers (void);
extern int finish_marking_specifiers (int (*obj_marked_p) (Lisp_Object),
void (*markobj) (Lisp_Object));
extern void prune_specifiers (int (*obj_marked_p) (Lisp_Object));
extern void setup_device_initial_specifier_tags (struct device *d);
DECLARE_SPECIFIER_TYPE (generic);
#define XGENERIC_SPECIFIER(x) XSPECIFIER_TYPE (x, generic)
#define XSETGENERIC_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, generic)
#define GENERIC_SPECIFIERP(x) SPECIFIER_TYPEP (x, generic)
#define CHECK_GENERIC_SPECIFIER(x, i) CHECK_SPECIFIER_TYPE (x, i, generic)
DECLARE_SPECIFIER_TYPE (integer);
#define XINTEGER_SPECIFIER(x) XSPECIFIER_TYPE (x, integer)
#define XSETINTEGER_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, integer)
#define INTEGER_SPECIFIERP(x) SPECIFIER_TYPEP (x, integer)
#define CHECK_INTEGER_SPECIFIER(x, i) CHECK_SPECIFIER_TYPE (x, i, integer)
DECLARE_SPECIFIER_TYPE (natnum);
#define XNATNUM_SPECIFIER(x) XSPECIFIER_TYPE (x, natnum)
#define XSETNATNUM_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, natnum)
#define NATNUM_SPECIFIERP(x) SPECIFIER_TYPEP (x, natnum)
#define CHECK_NATNUM_SPECIFIER(x, i) CHECK_SPECIFIER_TYPE (x, i, natnum)
DECLARE_SPECIFIER_TYPE (boolean);
#define XBOOLEAN_SPECIFIER(x) XSPECIFIER_TYPE (x, boolean)
#define XSETBOOLEAN_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, boolean)
#define BOOLEAN_SPECIFIERP(x) SPECIFIER_TYPEP (x, boolean)
#define CHECK_BOOLEAN_SPECIFIER(x, i) CHECK_SPECIFIER_TYPE (x, i, boolean)
#endif /* _XEMACS_SPECIFIER_H_ */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.