Notes on the inner workings of XEmacs


----------------------------------------------------------------------
---------------------------- allocation ------------------------------
----------------------------------------------------------------------

1. Lowest-level allocation:

  Lisp_Object malloc_warning_1 (str) 
  void malloc_warning (str) 
  memory_full () 
  long * xmalloc (size) 
  long * xrealloc (block, size) 

xmalloc() and xrealloc() call malloc() and realloc(), and if the result
returned is 0 (no free memory), call memory_full().  malloc_warning() is
called by malloc() when there is almost no free memory, and in turn calls
malloc_warning_1() to issue a warning to the user.  Note that Emacs has its
own malloc(), realloc(), and free() defined in malloc.c.

2. General:

VALIDATE_LISP_STORAGE(address, size)
INCREMENT_CONS_COUNTER(size)
int consing_since_gc;
int gc_cons_threshold;

/* Nonzero during gc */
int gc_in_progress;

/* Nonzero when calling the hooks in Energize-beta */
Lisp_Object Qgc_currently_forbidden;
int gc_currently_forbidden;

[some other stuff]

VALIDATE_LISP_STORAGE() is called whenever a new address is returned from
malloc() that is supposed to go within a Lisp object.  It verifies that the
address will actually fit (since Lisp addresses have to fit within 24 or 26
bits) and calls memory_full() if not.  INCREMENT_CONS_COUNTER() is called
whenever certain Lisp objects are created, and updates consing_since_gc, the
number of bytes of Lisp objects created since the last garbage collection.
When this number reaches gc_cons_threshold, a garbage collection is begun.
[INCREMENT_CONS_COUNTER() optionally calls cadillac_record_backtrace(); what
is this?]


3. Creation of primitive objects:


 static void init_extents () 
 EXTENT make_extent () 
 DUP make_extent_replica () 

3a. cons

 void init_cons () 
  free_cons (ptr) 
 DEFUN ("cons", Fcons, Scons, 2, 2, 0, "Create a new cons, give it CAR and CDR as components, and return it.") (car, cdr) 
#define CONS_BLOCK_SIZE \
  ((1020 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons))
struct cons_block
  {
    struct cons_block *next;
    struct Lisp_Cons conses[CONS_BLOCK_SIZE];
  };

struct cons_block *cons_block;
int cons_block_index;

struct Lisp_Cons *cons_free_list;

Cons cells are stored in cons blocks (struct cons_block), which contain a
"next" field and an array of conses.  cons blocks are calculated to occupy
exactly 1024 bytes of memory including malloc info.  "cons_block" points to
the first (most recent) cons block in the chain.  As cons cells are freed,
they are added to the cons_free_list (threaded through the car field), and
new cells are taken from this list first.  If no more such cells are
available, a new is obtained from the current cons block (cons_block_index
specifies the index of the next free cell), and if there are no free cells, a
new cons block is created.  VALIDATE_LISP_STORAGE() and
INCREMENT_CONS_COUNT() are called as necessary.  init_cons() creates the
first cons block, and Fcons() and free_cons() create and free cons cells as
indicated.

3b. list

 DEFUN ("list", Flist, Slist, 0, MANY, 0, "Return a newly created list with specified arguments as elements.\n\ Any number of arguments, even zero arguments, are allowed.") (nargs, args) 
 DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, "Return a newly created
list of length LENGTH, with each element being INIT.") (length, init)

No surprises here.  Fmake_list() creates a list of specified length by
calling Fcons() repeatedly and Flist() calls Fmake_list() and then traipses
down the list, filling in the "car" fields.
 
3c. float

 void init_float () 
  free_float (ptr) 
 Lisp_Object make_float (float_value) 

#define FLOAT_BLOCK_SIZE \
  ((1020 - sizeof (struct float_block *)) / sizeof (struct Lisp_Float))

struct float_block
  {
    struct float_block *next;
    struct Lisp_Float floats[FLOAT_BLOCK_SIZE];
  };

struct float_block *float_block;
int float_block_index;

struct Lisp_Float *float_free_list;

Floats are allocated exactly like cons cells above.  Floats on the free list
are threaded through the "type" field.

3d. vector

struct Lisp_Vector *all_vectors;

 DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, "Return a newly created vector of length LENGTH, with each element being INIT.\n\ See also the function `vector'.") (length, init) 
 DEFUN ("vector", Fvector, Svector, 0, MANY, 0, "Return a newly created vector with specified arguments as elements.\n\ Any number of arguments, even zero arguments, are allowed.") (nargs, args) 

Each vector is allocated as a chunk of memory of the right size, and all
vectors are kept on the list "all_vectors", threaded through the "next"
field.  Note that "struct Lisp_Vector" appears to contain space for only one
element.  However, indexing off the end of this array simply accesses the
rest of the space allocated for the elements.

3e. byte code objects

(DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
  "Create a byte-code object with specified arguments as elements.\n\
At least four arguments are required; only six have any significance.")
(nargs, args) 

calls make_pure_vector(); [what does this do?]

3f. symbols

#define SYMBOL_BLOCK_SIZE \
  ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol))

struct symbol_block
  {
    struct symbol_block *next;
    struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE];
  };

struct symbol_block *symbol_block;
int symbol_block_index;

struct Lisp_Symbol *symbol_free_list;

 void init_symbol () 
 DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, "Return a newly allocated uninterned symbol whose name is NAME.\n\ Its value and function definition are void, and its property list is nil.") (str) 
#define MARKER_BLOCK_SIZE \
  ((1020 - sizeof (struct marker_block *)) / sizeof (struct Lisp_Marker))

Symbols are allocated exactly like cons cells above.  The symbol's name is
bound to the string given, the symbol's plist is bound to Qnil, and the
function and value fields are marked unbound (bound to variable Qunbound).
Symbols on the free list are threaded through the "next" field, which is also
used for threading in an obarray.

3g. markers

struct marker_block
  {
    struct marker_block *next;
    struct Lisp_Marker markers[MARKER_BLOCK_SIZE];
  };

struct marker_block *marker_block;
int marker_block_index;

struct Lisp_Marker *marker_free_list;

 void init_marker () 
 DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, "Return a newly
allocated marker which does not point at any place.") () 

Markers are allocated exactly like cons cells above.  Markers on the free
list are threaded through the "chain" field.

3h. string

  static void init_strings () 
  static struct Lisp_String * make_string_internal () 
  static struct string_chars * allocate_string_chars (size, fullsize) 
  static Lisp_Object make_uninit_string (length) 
  DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0, "Return a newly created string of length LENGTH, with each element being INIT.\n\ Both LENGTH and INIT must be numbers.") (length, init) 
  Lisp_Object make_string_from_buffer (buf, index, length) 
  Lisp_Object make_string (contents, length) 
  Lisp_Object build_string (str) 
  Lisp_Object make_pure_string (data, length) 

/* If SIZE is the length of a string, this returns how many bytes
   the string occupies in a string_chars_block (including padding).  */
#define PAD ((sizeof (struct Lisp_String *)) - 1)
#define ROUND_UP_STRING_SIZE(s) (((s) + 1 + PAD) & ~PAD)
#define STRING_FULLSIZE(size) \
ROUND_UP_STRING_SIZE ((size) + sizeof (struct Lisp_String *))

#define STRING_BLOCK_SIZE \
((1020 - sizeof (struct string_block *)) / sizeof (struct Lisp_String))
/* String blocks contain this many useful bytes.
   8188 is power of 2, minus 4 for malloc overhead. */
#define STRING_CHARS_BLOCK_SIZE \
(8188 - ((2 * sizeof (struct string_chars_block *))+ sizeof (int)))

struct string_chars
{
  struct Lisp_String *string;
  unsigned char chars[1];
};

#define SLOT_OFFSET(type, slot_name) \
((unsigned) (((char *) (&(((type *)0)->slot_name))) - ((char *) 0)))
#define CHARS_TO_STRING_CHAR(x) \
((struct string_chars *)\
 (((char *) (x)) - (SLOT_OFFSET(struct string_chars, chars))))

/* Block header for small strings. */
struct string_chars_block
{
  struct string_chars_block *next;
  struct string_chars_block *prev;
  int pos;
  unsigned char chars[STRING_CHARS_BLOCK_SIZE];
};

struct string_block
{
  struct string_block *next;
  struct Lisp_String strings[STRING_BLOCK_SIZE];
};

struct string_block *string_block;
static int string_block_index;
static struct Lisp_String *string_free_list;

struct string_chars_block *current_string_chars_block;
struct string_chars_block *first_string_chars_block;

#define NONRELOCATING_STRING_SIZE(size) ((size) >= 1020)
#define BIG_STRING_SIZE(size) (NONRELOCATING_STRING_SIZE(size))

struct Lisp_String
  {
    int size;
    Lisp_Object dup_list;
    unsigned char *data;
  }

A string consists of a struct Lisp_String, plus the actual string data.
The struct Lisp_String consists of the length of the string and a
pointer to the data, plus a chain field "dup_list", used for threading
the list of free struct Lisp_String's.  struct Lisp_String's are managed
exactly like cons cells.  make_string_internal() returns a pointer to a
new struct Lisp_String.

The string data itself is stored in struct string_chars_block's, if the
string is less than a certain size (about 1K bytes).  A struct
string_chars_block occupies exactly 8K bytes, and holds a certain amount
of raw storage plus forward and backward link pointers and an index into
the storage, indicating where the unused part starts.  The storage is
chunked out in struct string_chars's, each of which consists of a
pointer to the struct Lisp_String for this string plus the actual string
data, padded out to a multiple of 4 bytes.  A new struct
string_chars_block is allocated if the existing one does not have enough
space, and all such structures are linked together and pointed to by
first_string_chars_block and current_string_chars_block.

If the string is larger than about 1K bytes (see BIG_STRING_SIZE() and
NONRELOCATING_STRING_SIZE()), a struct string_chars of the proper size
is simply malloc()ed.

allocate_string_chars() allocates and returns a struct string_chars() of
the proper size.  make_uninit_string() uses this function and
make_string_internal(), and returns a Lisp_Object that points to a
completed struct Lisp_String.  make-string, make_string(), and
build_string() call make_uninit_string() and then fill in the data.
make_string_from_buffer(), which makes a string from a section of a
buffer's text, is similar but first moves the gap out the way and also
calls replicate_extents() [see ?????] (see "buffers").


3i. pure

 Lisp_Object pure_cons (car, cdr) 
  Lisp_Object make_pure_float (num) 
  Lisp_Object make_pure_vector (len, stat_type) make_pure_vector (len) 
 DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, "Make a copy of OBJECT in pure storage.\n\ Recursively copies contents of vectors and cons cells.\n\ Does not copy symbols.") (obj) 

4. garbage collection

  void staticpro (varaddress) 
    void BTL_before_Fgarbage_collect_stub () 
 static void mark_object (), mark_buffer () static void mark_event (), mark_command_event_queue () static void clear_marks (), gc_sweep () static void compact_string_chars ()  static void mark_one_extent (extent) 
  static void mark_extents (extent) 
   static void mark_object (objptr) 
  static void mark_buffer (buffer) 
  static void mark_event (ptr) 
  static void mark_command_event_queue () 
  static void gc_sweep () 
  static void compact_string_chars () 
 DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", "Reclaim storage for Lisp objects no longer needed.\n\ Returns info on amount of space in use:\n\ ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS\n\ (USED-FLOATS . FREE-FLOATS) (USED-EVENTS . FREE-EVENTS))\n\ Garbage collection happens automatically if you cons more than\n\ `gc-cons-threshold' bytes of Lisp data since previous garbage collection.") () 
  init_alloc_once () 
 init_alloc () 
 void syms_of_alloc () 

Garbage collection involves going through all referenceable memory and
marking it, and then freeing all unreferenceable memory.  Garbage
collection can happen any time anything is evaluated.  If a function
creates a cons cell or anything else that is allocated and then calls
any function that might directly or indirectly call Feval(), it must
"protect" or "gcpro" that object; this involves putting it on a list of
referenced objects that garbage-collect pays attention to.  The object
must be ungcpro'ed when done.  The macros GCPRO1(), GCPRO2(), GCPRO3(),
and GCPRO4() protect that many objects, and use local variables struct
gcpro gcpro1, gcpro2, gcpro3, and gcpro4, which must have been declared
at the top of the function.  These macros actually store the address of
the passed object(s) into the appropriate struct gcpro(s) and add the
structure(s) onto the head of the linked list pointed to by "gcprolist".
The reason for storing the addresses, and not the objects themselves, is
so that the variables holding the objects can be modified if the object
is relocated, and also so that things still work correctly if you change
the value of the variable holding the object.  Consequently, you must
give lvalues as arguments to GCPRO*().  UNGCPRO() removes the struct
gcpro's off the list.

staticpro() is similar to GCPRO() for global and static variables and
adds an entry to the array staticvec[].

Garbage collection looks in the following places to find referenced
memory:

1) variables on the staticvec[] list, added with staticpro().
2) variables on the gcprolist.
3) objects in any backtrace structures on the backtrace_list. (see "eval")
4) specpdl
5) catchlist
6) handlerlist
7) any objects referenced by objects discovered above (e.g. if a cons is
referenced, then its car and cdr are also referenced).

Note that all symbols in the obarray (i.e. all global symbols) are
marked, because (1) obarray (a vector) is staticpro'd, (2) when marking
a vector all its elements are marked, and (3) when marking a symbol, the
symbol pointed to by the "next" field is marked.  The next field is used
to link together symbols on the free list, but for in-use symbols is
always 0 unless the symbol is in an obarray.

----------------------------------------------------------------------
----------------------------- bitmaps --------------------------------
----------------------------------------------------------------------



----------------------------------------------------------------------
----------------------------- buffers --------------------------------
----------------------------------------------------------------------

[buffer.c, buffer.h]

struct buffer_text
  {
    unsigned char *beg;		/* Actual address of buffer contents. */    
    int begv;			/* Index of beginning of accessible range. */
    int pt;			/* Position of point in buffer. */
    int gpt;			/* Index of gap in buffer. */
    int zv;			/* Index of end of accessible range. */
    int z;			/* Index of end of buffer. */
    int gap_size;		/* Size of buffer's gap */
    int modiff;			/* This counts buffer-modification events
				   for this buffer.  It is incremented for
				   each such event, and never otherwise
				   changed.  */
    int face_change;		/* This is set when a change in how the text
				   should be displayed (e.g., font, color)
				   is made. */
  };

struct buffer
  {
    /* Everything before the `name' slot must be of a non-Lisp_Object type,
       and every slot after `name' must be a Lisp_Object.

       Check out mark_buffer (alloc.c) to see why.
     */

    /* This structure holds the coordinates of the buffer contents.  */
    struct buffer_text text;

    /* Next buffer, in chain of all buffers including killed buffers.
       This chain is used only for garbage collection, in order to
       collect killed buffers properly.  */
    struct buffer *next;

    /* Flags saying which DEFVAR_PER_BUFFER variables
       are local to this buffer.  */
    int local_var_flags;

    /* Value of text.modiff when buffer last saved */
    int save_modified;

    /* Set to the modtime of the visited file when read or written.
       -1 means visited file was nonexistent.
       0 means visited file modtime unknown; in no case complain
       about any mismatch on next save attempt.  */
    int modtime;

    /* the value of text.modiff at the last auto-save. */
    int auto_save_modified;

    /* Position in buffer at which display started
       the last time this buffer was displayed */
    int last_window_start;

    struct stack_of_extents *cached_stack;

    /* These next two are exceptions -- both slots are be handled 
       "specially" by gc_sweep, and their contents are not lisp-accessible 
       as a local variable, but they are Lisp_Objects. */

    /* The markers that refer to this buffer.  This
       is actually a single marker -- successive elements in its marker
       `chain' are the other markers referring to this buffer */
    Lisp_Object markers;

    /* Active regions in this buffer. */
    Lisp_Object extents;

    /* Everything from here down must be a Lisp_Object */

    /* the name of this buffer */
    Lisp_Object name;
#undef MARKED_SLOT
#define MARKED_SLOT(x) Lisp_Object x
#include "bufslots.h"
};

bufslots.h:


    /* the name of the file associated with this buffer */
    MARKED_SLOT (filename);

    /* the truename of the filename (via the realpath() system call) */
    MARKED_SLOT (truename);

    /* Dir for expanding relative pathnames */
    MARKED_SLOT (directory);

    /* true iff this buffer has been been backed
       up (if you write to its associated file
       and it hasn't been backed up, then a
       backup will be made) */
    MARKED_SLOT (backed_up);

    /* Length of file when last read or saved. */
    MARKED_SLOT (save_length);

    /* file name used for auto-saving this buffer */
    MARKED_SLOT (auto_save_file_name);

    /* Non-nil if buffer read-only */
    MARKED_SLOT (read_only);

    /* "The mark"; no longer allowed to be nil */
    MARKED_SLOT (mark);

    /* Alist of elements (SYMBOL . VALUE-IN-THIS-BUFFER)
       for all per-buffer variables of this buffer.  */
    MARKED_SLOT (local_var_alist);

    /* Symbol naming major mode (eg lisp-mode) */
    MARKED_SLOT (major_mode);

    /* Pretty name of major mode (eg "Lisp") */
    MARKED_SLOT (mode_name);

    /* Format string for mode line */
    MARKED_SLOT (mode_line_format);

    /* Keys that are bound local to this buffer */
    MARKED_SLOT (keymap);
    /* Local bindings for mouse buttons, expressed as a keymap.  */
    MARKED_SLOT (mouse_map);
    /* Local bindings for function keys. */
    MARKED_SLOT (function_key_map);
    /* This buffer's local abbrev table */
    MARKED_SLOT (abbrev_table);
    /* This buffer's syntax table. */
    MARKED_SLOT (syntax_table);

    /* Values of several buffer-local variables.

       tab-width is buffer-local so that redisplay can find it
       in buffers that are not current */
    MARKED_SLOT (case_fold_search);
    MARKED_SLOT (tab_width);
    MARKED_SLOT (fill_column);
    MARKED_SLOT (left_margin);

    /* Function to call when insert space past fill column */
    MARKED_SLOT (auto_fill_function);

    /* String of length 256 mapping each char to its lower-case version.  */
    MARKED_SLOT (downcase_table);
    /* String of length 256 mapping each char to its upper-case version.  */
    MARKED_SLOT (upcase_table);

    /* Non-nil means do not display continuation lines */
    MARKED_SLOT (truncate_lines);
    /* Non-nil means display ctl chars with uparrow */
    MARKED_SLOT (ctl_arrow);
    /* Non-nil means do selective display;
       See doc string in syms_of_buffer (buffer.c) for details.  */
    MARKED_SLOT (selective_display);
#ifndef old
    /* Non-nil means show ... at end of line followed by invisible lines.  */
    MARKED_SLOT (selective_display_ellipses);
#endif
    /* Alist of (FUNCTION . STRING) for each minor mode enabled in buffer. */
    MARKED_SLOT (minor_modes);
    /* t if "self-insertion" should overwrite */
    MARKED_SLOT (overwrite_mode);
    /* non-nil means abbrev mode is on.  Expand abbrevs automatically. */
    MARKED_SLOT (abbrev_mode);

    /* Display table to use for text in this buffer. */
    MARKED_SLOT (display_table);
    /* Translate table for case-folding search.  */
    MARKED_SLOT (case_canon_table);
    /* Inverse translate (equivalence class) table for case-folding search.  */
    MARKED_SLOT (case_eqv_table);

    /* Changes in the buffer are recorded here for undo.
       t means don't record anything.  */
    MARKED_SLOT (undo_list);

    /* A redundant copy of text.pt, in the form of a marker.  Every time one
       is updated, so is the other.
     */
    MARKED_SLOT (point_marker);

    /* If dedicated_screen is non-nil, display_buffer tries to use it instead
       of the current screen */
    MARKED_SLOT (dedicated_screen);

-------

Vbuffer_alist, a Lisp object, holds an assoc-list mapping strings (buffer
names) to buffer objects.  Furthermore, each screen contains its own
buffer_alist, which holds the same information but possibly in a
different order.

Fbuffer_list(), Fget_buffer(), and Fget_file_buffer() do the expected
things, working on the buffer list(s).  push_buffer_alist() and
delete_from_buffer_alist() add to the end of or delete from all the
buffer lists.

struct buffer holds all the info for a buffer.  This includes struct
buffer_text (which holds the actual text), built-in buffer-local
variables, plus various other things.  Each struct buffer is separately
malloc'ed() and all allocated buffers are linked together through the
field "next".

A pointer to the current buffer is contained in "current_buffer".

struct buffer_text:

The text in a buffer is maintained consecutively in memory, with the
exception of a "gap" somewhere in the text.  Inserting text is done by
moving the gap to the right place in the text and then copying the text
in.  If the gap is too small to hold the text, it is enlarged and all the
following text is moved to accommodate it.  Since this is an expensive
operation, the size of the new gap is made quite large (specifically,
2000 plus one-tenth the size of the buffer).  This is very efficient when
there is a lot of locality in the insertion, and has the advantage that
accessing the character at a particular position is still relatively
easy.

When text is deleted, a similar process is followed -- the gap is moved
to where the deletion should occur and is enlarged appropriately.  There
is currently no limit on the size of the gap, meaning that memory
allocated for a buffer will never be freed until the buffer is killed.
[does it happen even then?]

When inserting and deleting text, it is also necessary to change the
various positions and markers.

The elements of struct buffer_text are:

struct buffer_text
  {
    unsigned char *beg;		/* Actual address of buffer contents. */    
    int begv;			/* Index of beginning of accessible range. */
    int pt;			/* Position of point in buffer. */
    int gpt;			/* Index of gap in buffer. */
    int zv;			/* Index of end of accessible range. */
    int z;			/* Index of end of buffer. */
    int gap_size;		/* Size of buffer's gap */
    int modiff;			/* This counts buffer-modification events
				   for this buffer.  It is incremented for
				   each such event, and never otherwise
				   changed.  */
    int face_change;		/* This is set when a change in how the text
				   should be displayed (e.g., font, color)
				   is made. */
  };

Note that character indices into buffers begin at 1.

Numerous macros are defined to make accessing the above fields easier:

BUF_CHAR_ADDRESS(buf, pos) and CHAR_ADDRESS(pos) [for the current buffer]
return the address of the character specified by the given index.  They
call BUF_TRUE_POS(buf, pos), which adjusts a character index by the
appropriate amount if it is after the gap.  PTR_CHAR_POS(pos) [for the
current buffer], reverses this process and returns the index
corresponding to the given address.  BUF_CHAR_AT(buf, pos) and
CHAR_AT(pos) return the actual character at the given index.

BEGV, PT, GPT, ZV, Z, MODIFF, GAP_SIZE, and FACECHANGE access the
corresponding elements in the current buffer.  BEG and BEG_ADDR return
the index and address of the beginning of the current buffer (note that
BEG is always 1).  BEGV_ADDR, PT_ADDR, GPT_ADDR and ZV_ADDR return the
addresses corresponding to the specified indices for the current buffer.
GAP_END_ADDR returns the address of the character in the current buffer
following the end of the gap.  Corresponding macros BUF_BEGV, BUF_PT,
BUF_GPT, BUF_ZV, BUF_Z, BUF_MODIFF, BUF_GAP_SIZE, BUF_FACECHANGE,
BUF_BEG, and BUF_BEG_ADDR work on a specified buffer.

[there's some more junk in buffer.h]

Manipulating the gap:

  void gap_left (pos, newgap)
  void gap_right (pos)
  void move_gap (pos)
  void make_gap (increment)

move_gap() moves the gap the specified amount up or down, calling
gap_left() or gap_right to do the work.  They work as expected, except
that they (optionally) change beg_unchanged and end_unchanged [look these
up], check for ^G every 32,000 characters [look up macro QUIT], and call
adjust_markers() and adjust_extents() when done.

make_gap() increases the gap at least by the specified size, according to
the formula above.  It calls BUFFER_REALLOC() to make more space and
calls gap_left() to move the new "end gap" consecutive with the old gap,
inhibiting ^G throughout.


Inserting text:

  void insert_relocatable_raw_string (string, length, obj)
  void insert_from_string (obj, pos, length)
  void insert_raw_string (string, length)
  void insert (string, length)
  void insert_string (s)
  void insert_char (c)
  void insert_before_markers (string, length)
  void insert_from_string_before_markers (string, pos, length)
  void insert_buffer_string (b, index, length)

The two routines that actually insert text are
insert_relocatable_raw_string() and insert_from_string().
insert_raw_string(), insert(), insert_string(), and insert_char() do
the same thing, the former two just calling
insert_relocatable_raw_string() with a NULL pointer passed as obj, and
the latter two just calling insert_raw_string() with the correct length.

void adjust_markers (from, to, amount)
  void prepare_to_modify_buffer (start, end)
 void modify_region (start, end)
 static Lisp_Object before_change_function_restore (value)
 static Lisp_Object after_change_function_restore (value)
  signal_before_change (start, end)
  signal_after_change (pos, lendel, lenins)
  void del_range (from, to)

Creation of a new buffer is actually done in Fget_buffer_create().  


----------------------------------------------------------------------
------------------------------ display -------------------------------
----------------------------------------------------------------------

/* Nonzero if head_clip or tail_clip of current buffer has changed
   since last redisplay that finished */
int clip_changed;

/* Nonzero if window sizes or contents have changed
   since last redisplay that finished */
int windows_or_buffers_changed;

void mark_window_display_accurate(window, accurate_p)
	Specifies whether

void redraw_screen(screen)
	Sets up the screen for complete redisplay.  Physically clears the
	screen and sets various flags to indicate that the entire contents
	of the screen are garbaged.

redraw-screen
	Lisp entry to redraw_screen().

redraw-display
	Calls redraw-screen on all screens.

redisplay()
	Main external entry point for redisplay.  Updates all screens on the
	physical display.

	1) update_psheets()
	2) in_display++
	3) invalidate each screen's desired glyphs (reset the enable[] array).
	4) deal with the echo area.
	5) update the redisplay structure (desired glyphs):
		a) if only local changes were made, take a shortcut.
		b) otherwise redo the whole structure (redisplay_window()).
	6) update the physical screen.  Calls update_screen() on any screens
	   that need to be updated.
	7) mark the updated windows as accurate.
	8) in_display--
	9) update_screen_menubars()

redisplay_windows(window)
	Redisplay the specified window and all the siblings after it.  Calls
	redisplay_window().

redisplay_window(window, just_this_one)
	Redisplay the specified window.  If this is a combination window,
	redisplay all its children through redisplay_windows().  Does not
	actually change the physical display.  Calls try_window() or
	try_window_id().

try_window(window, pos)
	Do a full redisplay on the specified window.  Does not actually change
	the physical display.  Called by redisplay_window().

try_window_id(window)
	Attempt to do a redisplay on the specified window when only local
	changes happened.  Does not actually change the physical display.
	Called by redisplay_window().

int update_screen(screen, force, inhibit_hairy_id)
	Update a screen.  Essentially calls update_line() or x_update_line()
	on each line.  Break off updating if input is pending, unless
	"force" is non-zero.  Return value is non-zero is update broken off
	due to pending input.

	1. if not "force" and input is pending, invalidate all the lines of
	   the screen's desired glyphs and return.
	2. update_begin() (just sets updating_screen)
	3. if ...
	4. loop over all lines (possibly breaking if input pending) -- if the
	   line in desired glyphs is valid, display it with x_update_line()
	5. set the cursor position properly
	6. invalidate desired glyphs.
	7. update_end()
	8. deal with the termscript if necessary

void x_update_line(screen, vpos, pix_y)
	Update line "vpos" on screen "screen".  "pix_y" is the position of
	the top of the line, in pixels.  Calls x_write_glyphs(),
	x_clear_display_line(), and x_clear_display_line_end() as necessary.

	1. save the characteristics for this line in current glyphs (for use
	   later on in this function)
	2. move the characteristics in desired glyphs for this line into
	   current glyphs
	3. if the line is blank, erase any line that might have been there
	   before (x_clear_display_line()) and return.
	4. otherwise, attempt to do the minimum amount of effort to get a
	   correctly displayed line.  You figure out what's going on here.
	   I don't think it's robust.  x_clear_display_line(),
	   x_write_glyphs(), and/or x_clear_display_line_end() may be
	   called.

void x_clear_display_line(vpos, pix_width)
void x_clear_display_line_end(vpos)

	Clear a line or part of a line.  Calls XClearArea().

int x_write_glyphs(screen, left, top, n, force_gc, box_p)

	The routine that actually draws text or a cursor.  "left" and "top"
	specify the position in characters where the drawing starts.  "n"
	specifies the number of characters to write. "box_p" specifies
	whether to draw a box around the text.  ["force_gc"?]
	Looks in "current_glyphs" to get text to write.

	1. If any parameters are invalid or something is wrong with
	   current_glyphs, return. (abort?)
	2. Erase the cursor if it's in the region we're writing to.
	3. Find the correct run.
	4. Deal with graphics contexts. /** CHANGE **/
	5. Find the correct place within the run; determine the pixel offset
	   where we should start displaying.
	6. If the run to be displayed is text:
		a. clear the area to be displayed in, if necessary.
		b. display the text, displaying a box if necessary.  Apparently
		   deals with the background or whatever. [?]
		c. deal with underlining. (this should be done in the callback
		   routine)
	7. If the run to be displayed is "column_glyph":
	8. If the run to be displayed is a "glyph" (bitmap), display the
	   bitmap.  Does some odd junk.
	9. If the run to be displayed is "space":
	10. Loop till all glyphs are displayed.

xx. displaying/removing the cursor

void erase_screen_cursor_if_needed(screen)
void erase_cursor_if_needed(void)
void erase_screen_cursor_if_needed_and_in_region(screen, x, y, n)
void draw_screen_cursor_if_needed(screen)
void x_screen_redraw_cursor(screen)

	Draw or erase a cursor, either for the specified screen or the
	currently active screen (current_screen or updating_screen).
	Possibly only remove cursor if it's on the specified line and
	between character positions "x" and "x+n" inclusive.  Calls
	x_display_cursor().

void x_display_bar_cursor(screen, on)
int x_draw_empty_box(screen)
int x_draw_square(screen)
int x_erase_square(screen)
int x_display_box_cursor(screen, on)
int x_display_cursor(screen, on)

	Actually do the cursor displaying/removing.  Calls XClearArea() or
	x_write_glyphs().

other:

x_draw_lineinfo_border()
x_clear_lineinfo_glyph()
XTwrite_glyphs()
XTclear_end_of_line()
XTclear_screen()
XTflash()
XTsimple_beep()
XTring_bell()
XTset_terminal_window()
stufflines()
scraplines()
XTins_del_lines()
repaint_lines()
x_new_selected_screen()
x_event_name()
x_error_handler()
x_IO_error_handler()

#ifdef ENERGIZE
reasonable_glyph_index_p()
allocate_x_bitmaps()
possible_energize_glyph_index_p()
allocate_x_bitmaps_index()
free_all_x_bitmaps_indices()
free_x_bitmaps_index()
#endif

init_bitmap_tables()
report_broken_pipe()
make_argc_argv()
make_arg_list()
x_term_init()
x_update_wm_hints()
x_calc_absolute_position()
x_set_offset()
x_set_window_size()
x_set_mouse_position()
handle_raise_error()
x_raise_screen()
x_lower_screen()
x_make_screen_visible()
x_make_screen_invisible()
x_iconify_screen()
x_focus_screen()
x_destroy_window()

----------------------------------------------------------------------
-------------------------------- eval --------------------------------
----------------------------------------------------------------------

struct backtrace
  {
    struct backtrace *next;
    Lisp_Object *function;
    Lisp_Object *args;		/* Points to vector of args. */
    int nargs;			/* length of vector */
				/* if nargs is UNEVALLED, args points to
				   slot holding list of unevalled args */
#ifdef EMACS_BTL
    /* The value of a Lisp integer that specifies the symbol being
       "invoked" by this node in the backtrace, or 0 if the backtrace
       doesn't correspond to a such an invocation */
    int id_number;
#endif
    char evalargs;
    char debug_on_exit;		/* Nonzero means call value of debugger
				   when done with this operation. */
  };

Feval() evaluates the form (a Lisp object) that is passed to it.  Note
that evaluation is only non-trivial for two types of objects: symbols
and conses.  Under normal circumstances (i.e. not mocklisp) a symbol is
evaluated simply by calling symbol-value on it and returning the value.

Evaluating a cons means calling a function.  First, eval checks to see
if garbage-collection is necessary, and calls Fgarbage_collect() if so.
It then increases the evaluation depth by 1 (lisp_eval_depth and
max_lisp_eval_depth) and adds an element to the linked list of struct
backtrace's ("backtrace_list").  Each such structure contains a pointer
to the function being called plus a list of the function's arguments.
Originally these values are stored unevalled, and as they are evaluated,
the backtrace structure is updated.  Garbage collection pays attention
to the objects pointed to in the backtrace structures (garbage
collection might happen while a function is being called or while an
argument is being evaluated, and there could easily be no other
references to the arguments in the argument list; once an argument is
evaluated, however, the unevalled version is not needed by eval, and so
the backtrace structure is changed).

At this point, the function to be called is determined by looking at the
car of the cons (if this is a symbol, its function definition is
retrieved and the process repeated).  The function should then consist
of either a Lisp_Subr (built-in function), a Lisp_Compiled object, or a
cons whose car is the symbol "autoload", "macro", "lambda", or
"mocklisp".

If the function is a Lisp_Subr, the lisp object points to a struct
Lisp_Subr (created by DEFUN()), which contains a pointer to the C
function, a minimum and maximum number of arguments (possibly the
special constants MANY or UNEVALLED), a pointer to the symbol referring
to that subr, and a couple of other things.  If the subr wants its
arguments UNEVALLED, they are passed raw as a list.  Otherwise, an array
of evaluated arguments is created and put into the backtrace structure,
and either passed whole (MANY) or each argument is passed as a C
argument.

If the function is a Lisp_Compiled object or a lambda, apply_lambda() is
called.  If the function is a macro, [..... fill in] is done.  If the
function is an autoload, do_autoload() is called to load the definition
and then eval starts over [explain this more].  If the function is a
mocklisp, ml_apply() is called.

When eval exits, the evaluation depth is reduced by one, the debugger is
called if appropriate, and the current backtrace structure is removed
from the list.

apply_lambda() is passed a function, a list of arguments, and a flag
indicating whether to evaluate the arguments.  It creates an array of
(possibly) evaluated arguments and fixes up the backtrace structure,
just like eval does.  Then it calls funcall_lambda().

funcall_lambda() goes through the formal arguments to the function and
binds them to the actual arguments, checking for "&rest" and "&optional"
symbols in the formal arguments and making sure the number of actual
arguments is correct.  Then either progn or byte-code is called to
actually execute the body and return a value.

Ffuncall() implements Lisp "funcall".  (funcall fun x1 x2 x3 ...) is
equivalent to (eval (list fun (quote x1) (quote x2) (quote x3) ...)).
Ffuncall() contains its own code to do the evaluation, however, and is
almost identical to eval.

Fapply() implements Lisp "apply", which is very similar to funcall
except that if the last argument is a list, the result is the same as if
each of the arguments in the list had been passed separately.  Fapply()
does some business to expand the last argument if it's a list, then
calls Ffuncall() to do the work.

apply1(), call0(), call1(), call2(), and call3() call a function,
passing it the argument(s) given (the arguments are given as separate C
arguments rather than being passed as an array).  apply1() uses "apply"
while the others use "funcall".

2. specbindings

struct specbinding
  {
    Lisp_Object symbol, old_value;
    Lisp_Object (*func) ();
    Lisp_Object unused;		/* Dividing by 16 is faster than by 12 */
  };

struct specbinding is used for local-variable bindings and
unwind-protects.  "specpdl" holds an array of struct specbinding's,
"specpdl_ptr" points to the beginning of the free bindings in the array,
"specpdl_size" specifies the total number of binding slots in the array,
and "max_specpdl_size" specifies the maximum number of bindings the
array can be expanded to hold.  grow_specpdl() increases the size of the
specpdl array, multiplying its size by 2 but never exceeding
max_specpdl_size (except that if this number is less than 400, it is
first set to 400).

specbind() binds a symbol to a value and is used for local variables and
"let" forms.  The symbol and its old value (which might be Qunbound,
indicating no prior value) are recorded in the specpdl array, and
specpdl_size is increased by 1.

record_unwind_protect() implements an unwind-protect, which, when placed
around a section of code, ensures that some specified cleanup routine
will be executed even if the code exits abnormally (e.g. through a throw
or quit).  record_unwind_protect() simply adds a new specbinding to the
specpdl array and stores the appropriate information in it.  The cleanup
routine can either be a C function, which is stored in the "func" field,
or a progn form, which is stored in the "old_value" field.

unbind_to() removes specbindings from the specpdl array until the
specified position is reached.  The specbinding can be one of three
types: (1) an unwind-protect with a C cleanup function ("func" is not 0
-- old_value holds an argument to be passed to the function); (2) an
unwind-protect with a Lisp form ("func" is 0 and "symbol" is NIL --
old_value holds the form to be executed with Fprogn()); or (3) a
local-variable binding ("func" is 0 and "symbol" is not NIL -- old_value
holds the old value, which is stored as the symbol's value).

3. special forms

3a. or, and, if, cond, progn, prog1, prog2, setq, quote, function, let*,
let, while

All of these are very simple and work as expected, calling Feval() or
Fprogn() as necessary and (in the case of let and let*) using specbind()
to create bindings and unbind_to() to undo the bindings when finished.
Note that these functions do a lot of GCPRO()ing to protect their
arguments from garbage collection because they call Feval() (see
"garbage collection").

3b. catch, throw

struct catchtag
  {
    Lisp_Object tag;
    Lisp_Object val;
    struct catchtag *next;
    struct gcpro *gcpro;
    jmp_buf jmp;
    struct backtrace *backlist;
    int lisp_eval_depth;
    int pdlcount;
  };

"catch" is a Lisp function that places a catch around a body of code.  A
catch is a means of non-local exit from the code.  When a catch is
created, a tag is specified, and executing a "throw" to this tag will
exit from the body of code caught with this tag, and its value will be
the value given in the call to "throw".  If there is no such call, the
code will be executed normally.

Information pertaining to a catch is held in a struct catchtag, which is
placed at the head of a linked list pointed to by "catchlist".
internal_catch() is passed a C function to call (Fprogn() when Lisp
"catch" is called) and arguments to give it, and places a catch around
the function.  Each struct catchtag is held in the stack frame of the
internal_catch() instance that created the catch.

internal_catch() is fairly straightforward.  It stores into the struct
catchtag the tag name and the current values of backtrace_list,
lisp_eval_depth, gcprolist, and the offset into the specpdl array, sets
a jump point with _setjmp() (storing the jump point into the struct
catchtag), and calls the function.  Control will return to
internal_catch() either when the function exits normally or through a
_longjmp() to this jump point.  In the latter case, "throw" will store
the value to be returned into the struct catchtag before jumping.  When
it's done, internal_catch() removes the struct catchtag from the
catchlist and returns the proper value.

Fthrow() goes up through the catchlist until it finds one with a
matching tag.  It then calls unbind_catch() to restore everything to
what it was when the appropriate catch was set, stores the return value
in the struct catchtag, and jumps (with _longjmp()) to its jump point.

unbind_catch() removes all catches from the catchlist until it finds the
correct one.  Some of the catches might have been placed for
error-trapping, and if so, the appropriate entries on the handlerlist
must be removed (see "errors").  unbind_catch() also restores the values
of gcprolist, backtrace_list, and lisp_eval, and calls unbind_to() to
undo any specbindings created since the catch.

3c. other [fill in]



----------------------------------------------------------------------
-------------------------------- events ------------------------------
----------------------------------------------------------------------

typedef enum emacs_event_type {
  empty_event,
  key_press_event,
  button_press_event,
  button_release_event,
  pointer_motion_event,
  process_event,
  timeout_event,
  magic_event,
  eval_event,
  menu_event,
  dead_event
} emacs_event_type;

#define first_event_type empty_event
#define last_event_type dead_event

struct key_data {
  int               key;
  unsigned char     modifiers;
};

struct button_data {
  int               button;
  unsigned char     modifiers;
  int               x, y;
};

struct motion_data {
  int               x, y;
};

struct process_data {
  Lisp_Object       process;
};

struct timeout_data {
  Lisp_Object       function;
  Lisp_Object	    object;
  int		    id_number;
};

struct eval_data {
  Lisp_Object       function;
  Lisp_Object	    object;
};

#ifndef MAX_UNDERLYING_EVENT_SIZE
# ifdef HAVE_X_WINDOWS
#  define MAX_UNDERLYING_EVENT_SIZE (sizeof (XEvent))
# else
#  define MAX_UNDERLYING_EVENT_SIZE 1
# endif
#endif

struct magic_data {
  char		   underlying_event [MAX_UNDERLYING_EVENT_SIZE];
};

struct Lisp_Event {
  emacs_event_type	event_type;
  Lisp_Object		channel;
  unsigned int		timestamp;
  union {
    struct key_data	key;
    struct button_data	button;
    struct motion_data	motion;
    struct process_data	process;
    struct timeout_data	timeout;
    struct eval_data	eval;   /* menu_event uses this too */
    struct magic_data	magic;
  } event;
  struct Lisp_Event	*next;	/* - For dead events, this is the next dead
				     one.
				   - For events on the command_event_queue,
				     this is the next one on the queue.
				   - Otherwise it's 0.
				 */
};

struct event_stream {
  int  (*event_pending_p)	(int);
  void (*next_event_cb)		(struct Lisp_Event *);
  void (*handle_magic_event_cb)	(struct Lisp_Event *);
  int  (*generate_wakeup_cb)	(unsigned int, unsigned int,
				 Lisp_Object, Lisp_Object);
  void (*disable_wakeup_cb)	(int);
  void (*select_tty_cb)		(int);
  void (*unselect_tty_cb)	(int);
  void (*select_process_cb)	(struct Lisp_Process *);
  void (*unselect_process_cb)	(struct Lisp_Process *);
#ifdef SIGIO
  void (*sigio_cb)		();
#endif
};

The event code is designed to be essentially system-independent.  struct
event_stream holds functions that interface between the generic event
routines in Emacs and the specific window system, such as X.  There is
one instance, called "event_stream", of this structure.  The event
itself is held in struct Lisp_Event, which is filled in by the
system-specific next_event_cb.

1. managing struct Lisp_Event's [event-alloc.c]

allocate-event, deallocate-event, and copy-event are in event-alloc.c;
see its description.  This module also contains some routines used
during garbage-collection.

2. converting event types [events.c]

character_to_event(), event_to_character(), event-to-character, and
character-to-event convert between ASCII characters and keypresses
corresponding to the characters.  If the event was not a keypress,
event_to_character() returns -1 and event-to-character returns NIL.  These
functions convert between ASCII representation and the split-up event
representation (keysym plus mod keys).

format_event_object() takes an event of any type and returns a short string
describing to this event. (e.g. M-C-x for a keypress of meta-control-X).

3. event predicates

eventp, key-press-event-p, button-press-event-p, button-release-event-p,
button-event-p, motion-event-p, process-event-p, timeout-event-p,
menu-event-p, and eval-event-p are fairly self-explanatory.

4. event properties

event-timestamp, event-key, event-button, event-modifier-bits,
event-modifiers, event-x-pixel, event-y-pixel, event-window, event-point,
event-x, event-y, event-glyph, event-process, event-function, and
event-object are fairly clear.  Some of these routines call
event_pixel_translation(), which takes a motion or button event and returns
the window, x and y character position, buffer, and glyph over which the
event occurred [what is a glyph?].  The work is actually done by
pixel_to_glyph_translation (see "display").

event_equal(), used by equal, compares two events.


5. obtaining events

NOTE: I am not sure whether the routines below ever get executed
asynchronously.  If so, life gets messy.

next-event fills in a struct Lisp_Event with an event.  The event comes
from one of three places:

1) unread-command-event, if not NIL (copied with copy-event)
2) a keyboard macro, if we're in one (pop_kbd_macro_event())
3) next_event_internal()

Before getting an event, next-event refreshes the screen (redisplay())
if there is no event pending (detect_input_pending()).  After getting an
event, next-event does various processing:

1) maybe_status_notify() is called.

2) for key-presses, maybe_do_auto_save() is called.

3) for key-presses and button events, things are set up so that the
event will be echoed in the echo area after a fixed amount of time.

4) for "command events" (key-presses, button actions, and menu
selections), [V]last-input-event, [V]last-input-char,
[V]last-input-time, [V]this-command-keys (visible as Lisp function
this-command-keys), and recent_keys_ring (visible as Lisp function
recent-keys-ring) are updated/  If we're defining a keyboard macro, the
macros is updated.

5) if the help key was pressed (variable "help_char"),
execute_help_form() is called.
   
next_event_internal() obtains an event either from the
command_event_queue or, if this is empty, by calling next_event_cb.
(The queue is linked through the "next" field of struct Lisp_Event;
events are placed on the queue by enqueue_command_event(), which is
called by some functions that read events, filter some of them out, and
put the remaining ones back.)  next_event_internal() also checks if the
event was a keypress of interrupt_char (defined to be ^G in keyboard.c),
and calls interrupt_signal() if so.

detect_input_pending() and input-pending-p look for input by calling
event_stream->event_pending_p and looking in [V]unread-command-event and
the command_event_queue (they do not check for an executing keyboard
macro, though).

discard-input cancels any command events pending (and any keyboard
macros currently executing), and puts the others onto the
command_event_queue.  There is a comment about a "race condition",
which is not a good sign.

next-command-event and read-char are higher-level interfaces to
next-event.  next-command-event gets the next "command" event (i.e.
keypress, mouse event, or menu selection), calling dispatch-event on
any others.  read-char calls next-command-event and uses
event_to_character() to return the ASCII equivalent.

accept-process-output???

6, 7, ... [more event stuff]

----------------------------------------------------------------------
---------------------- execution of Lisp code ------------------------
----------------------------------------------------------------------

Main data structures during Lisp execution:

1. staticvec[]: lists all global and static C variables that hold Lisp
objects.  Used during garbage collection.  See "allocation".



gcprolist, specpdl, and backtrace_list are stacks that are added to and
removed from as Lisp and C functions are entered and exited.

2. gcprolist: points to a linked list of struct gcpro's, listing
currently-active C local variables that hold Lisp objects.  Each struct
gcpro is located in the same stack frame as the local variable it
references.  Used during garbage collection.  See "allocation".

3. specpdl: points to an array of struct specbinding's, each of which
references a currently-active Lisp local binding or a currently-active
unwind-protect.  See "eval".

4. backtrace_list: points to a linked list of struct backtrace's, each
of which gives information about a Lisp function call currently
executing.  Each struct backtrace is located in the stack frame of the
Feval() or Ffuncall() instance that initiated the function call.  See
"eval".



5. Vobarray: holds the obarray, which lists all symbols that have been
interned.  The obarray is a vector of linked lists arranged as a
separately-chained hash table.  See "obarray".

6. catchlist: points to a linked list of struct catchtag's, each of
which specifies a catch that is currently active.  Each struct catchtag
is located in the stack frame of the instance of internal_catch(),
Fcondition_case(), or internal_condition_case() that created the catch.
See "eval -- special forms".

7. handlerlist: points to a linked list of struct handler's, each of
which corresponds to a condition-case that is currently active.  Each
struct handler is located in the stack frame of the instance of
Fcondition_case() or internal_condition_case() that created the
condition-case.  See "errors".


----------------------------------------------------------------------
------------------------------ Extents -------------------------------
----------------------------------------------------------------------

[extents.c]
[extents.h]

An "extent" is a region of text with a certain property, such as
invisible, read-only, or highlighted.  Extents can overlap, and the
text under overlapping extents has all the properties of the extents
lying over that text. [what if some properties contradict each other?]

1. structures

typedef struct 
{
  int seal;                     /* must be EXTENT_SEAL */
  Id id;
  int extentType;               /* oneof CEAttribute, CEAbbreviation, etc. */
  Lisp_Object extent;           /* corresponding extent */
#ifdef ENERGIZE
  Lisp_Object start_glyph_index;
  Lisp_Object end_glyph_index;
#endif
  union
    {
      struct
        {                       /* CEAttribute */
          int attrValue;
        } attr;
      struct 
        {                       /* CEAbbreviation */
          Boolean isOpened;
        } abbrev;
      struct 
        {                       /* CEGeneric */
          GenericData* gData;
        } generic;
    } u;
} Extent_Data;

1a. struct extent

struct extent
{
  unsigned short flags;
  /* non-zero only for "extended type extents" */
  unsigned short secondary_type;
  int start;
  int end;
  struct extent *next;
  struct extent *previous;
  struct extent *e_next;
  struct extent *e_previous;
  int attr_index;
  Lisp_Object buffer;
  Lisp_Object user_data;
};

"start", "end" are the limits of the extent.  "buffer" is the buffer this
extent refers to.  "flags" is the properties of the extent, defined in
extents.h.  "next", "previous", "e_next", and "e_previous" are used to
link all the extents together.  Extents are linked in two bidirectional
linked lists -- one ordered by start position ("next", "previous") and
the other by end position ("e_next", "e_previous").  "user_data" is any
extra data that the user might choose to associate with an extent.

attr_index?  secondary_type?

typedef struct extent *EXTENT;

1b. extent indices

The start and end positions of an extent are simple character indices.  This
is not necessarily the same as the buffer index, because the latter takes
the gap into account. (see "buffer")

buffer_pos_to_extent_index(pos, buf)
extent_index_to_buffer_pos(index, pos)
	These functions perform the conversion between buffer indices and
	extent indices.

1c. extent lists

Extents are linked in two bi-directional linked lists.  The orderings for
these two lists are called "display" or "normal" order and "e-order", which
are essentially sorting by start and end positions, respectively.

splice_extent_into_buffer(extent, buffer)
	Inserts an extent into the linked lists.
detach_extent()
	Removes an extent from the linked lists and sets its start and end
	positions to 0.
next-extent
next-e-extent
	Returns the next extent in the specified list.

1. creating an extent

Extents are managed just like cons cells -- see "allocation".

make_extent(void) [alloc.c]
	Allocates and returns a new extent.
make-extent
	Creates a new extent; calls make_extent_internal().
make_extent_internal(from, to, buffer, extent_data)
	Allocates an extent, sets the position of the extent, and inserts it
	into the buffer's extent lists.
delete-extent
	Destroys an extent; calls destroy_extent() and sets some flags
	indicating that the buffer's display has changed.
destroy_extent()
	Removes an extent from the buffer's extent lists and clears its values.
	It will be reclaimed during garbage collection.

3. extent properties

EF_*
	Masks referring to particular properties in the extent's "flags" field.
SET_EXTENT_FLAG()
CLEAR_EXTENT_FLAG()
EXTENT_FLAG_P()
	Macros that get or set particular properties in the "flags" field.

extent-start-position
extent-end-position
extent-length
extent-buffer
	Return the respective properties of an extent.
update-extent
	Change the start and end positions of an extent.  This detaches the
	extent, sets the positions, and inserts the extent back into the buffer's
	extent lists.
update_extent()
	Does the same thing as update-extent, but has separate code.

extent-attributes
set-extent-attribute
	Get or set the attributes (invisible, highlighted, etc.) of an extent.

extent-data
set-extent-data
	get or set the user data for an extent.

4. mapping over extent lists

typedef int (*emf)(EXTENT extent, void *arg);
typedef int (*elisp_emf)(Lisp_Object extent_obj, void *arg);

struct slow_map_extents_arg
{
  Lisp_Object map_arg;
  Lisp_Object map_routine;
};


map-extents
	Calls a function on all extents overlapping a specified range.
	map_extents() is called and given as its function either the
	specified function (if it's a built-in subr) or
	slow_map_extents_function (if the specified function is a user
	function).
map_extents()
	Calls a function on all extents overlapping a specified range.
	It marches down the display-order list of extents and checks
	each one to see if the range matches.  The function is called
	with two arguments -- the extent itself and a user-supplied
	value.
slow_map_extents_function()
	Function given to map_extents() so that user-defined Lisp functions
	can be mapped.  The second argument given to it is a struct
	slow_map_extents_arg, containing the Lisp function and the actual
	argument to be given to it.  call2() is used to call the function.

5. determine the smallest enclosing extent for a position

struct extent_at_struct
{
  EXTENT best_match;
  int flag;
};

extent-at
	Determines the smallest extent overlapping a specified position and
	having the specified properties.  Calls extent_at().
extent_at()
	Does the actual work.  Maps the function extent_at_mf() over all
	extents.  The argument given is of type struct extent_at_struct.
extent_at_mf()
	The map function used by extent_at().  Checks the extent to see if
	it's a candidate and is smaller than the smallest one found so far.

6. highlighting an extnt

The display code looks in [V]last-highlighted-extent to determine which
extent should be highlighted.

extent_highlightable_p()
	True if an extent has the "highlightable" property.
do_highlight()
	Highlight or unhighlight an extent.  This involves changing
	[V]last-highlighted-extent and setting some flags indicating that
	the buffer has changed.
highlight-extent
	Highlight an extent if it has the "highlightable" property.  Calls
	do_highlight().
force-highlight-extent
	Highlight an extent always.  Calls do_highlight().

7. Dealing with textual change

The range of an extent is adjusted when text is inserted or deleted.
In addition, some extents must be deleted entirely.

[extents.c]

/* not used at the moment */   
struct process_extents_for_insertion_struct
{
  int opoint;
  int length;
  struct buffer *buf;
};
   
struct process_extents_for_deletion_struct
{
  int start;
  int end;
  int destroy_included_extents;
};

adjust_extent_index()
adjust_extents()

process_extents_for_insertion()
process_extents_for_deletion_mf()
process_extents_for_deletion()
process_extents_for_destruction()


8. checking the read-only property of a range of extent

verify_extent_modification() is called by prepare_to_modify_buffer() in
insdel.c, and makes sure that none of the region about to be modified is
read-only.

struct end_points
{
  int start;
  int end;
};

verify_extent_modification(buffer, from, to)
	Make sure none of the text in the specified range is read-only.
	Maps verify_extent_mf() over all extents.  The argument given to this
	function is of type struct end_points.
verify_extent_mf()
	Called by map_extents().  Signals an error if the specified extent is
	read-only and overlaps the specified range of text.

9. extent fragments

An "extent fragment" is a structure holding all of the extents overlapping
a particular position, as well as the range of positions around
the specified position which have exactly the same extents overlapping
them (i.e. the maximum range containing this position in which no extents
begin or end).  All characters in this range have exactly the same
properties.

[extents.h]

struct extent_fragment
{
  /* buffer and modification event of buffer for this fragment */
  struct buffer *buf;
  int modiff;
  int face_change;
  /* covers buffer positions [from, to-1] */
  int from;
  int to;
  /* these are the buffer array indices of positions from and to */
  int start_index;
  int end_index;
  /* first extent past the stack */
  EXTENT first_extent_past_stack;
  int number_of_extents;
  EXTENT *extents_stack;
  int extents_stack_length;
  struct face *fp;
};

typedef struct extent_fragment *EXTENT_FRAGMENT;

struct extent_fragment extent_fragment;
int extent_cache_invalid;

"buf" is the buffer this extent fragment refers to, and "modiff" and
"face_change" hold the values of these buffer fields when the extent
fragment was created.  "from" and "to" are the range in buffer indices,
and "start_index" and "end_index" the corresponding range in extent
indices (i.e. the former range takes into account the gap).  "extents_stack"
is the array of extents overlapping the range, and "number_of_extents"
the number of extents in this array.  "extents_stack_length" is the
actual size of the array, which is >= number_of_extents (the array is
realloc()ed as necessary to accommodate more extents).
"first_extent_past_stack" is the first extent whose start position is past
the end of the range.

The global variable "extent_fragment" is of type struct extent_fragment
and is used by the extent fragment routines.

init_extent_fragment(void)
	Initializes the variable "extent_fragment".
buffer_extent_fragment_at(pos, buffer, screen)
	Determines the extent fragment surrounding the specified position.  It
	first checks if the previously-calculated extent fragment is still
	valid (by looking at "extent_cache_invalid" and the values of MODIFF
	and FACE_CHANGE stored in the variable "extent_fragment", among
	other things), and only	does the recalculation (by calling
	befa_internal()) if not.  A pointer to "extent_fragment" is returned.
internal_befa(pos, buffer)
	Actually calculates the extent fragment.  Returns a pointer to
	"extent_fragment".

10. stack of extents

Every buffer has a "stack of extents", which is used to speed up traversing
through the extents, looking for extents that overlap a particular range.
The stack of extents is used by buffer_starting_extent(), which returns an
extent that you can start such a traversal at.  The stack of extents is
stored in a buffer's "cached_stack" field and is held in a "struct
stack_of_extents".  This structure contains a buffer position, an array of
all the extents that overlap the position, and the "previous" extent,
which is the last extent (in display order) that does not overlap the
position and which comes before (in display order) all the extents that
do.

The code to manipulate a stack of extents is hairy and involved, and there
are lots of comments in extents.c.

/* sort of a mini-version of the extents fragment -- each buffer
   with an extents list gets one of these */
struct stack_of_extents
{
  /* an extent "before" those on the stack, or 0 if none is known */
  EXTENT previous_extent;
  /* buf_index over which this stack lies */
  int buf_index;
  EXTENT *stack;
  int stack_length;
  int stack_index;
};

soe_to_lisp()
stack-of-extents
verify_buffer_stack()
soe_push()
soe_duplicate()
soe_delq()
init_buffer_cached_stack()
soe_clear()
soe_prune()
free_buffer_cached_stack()
cleanup_old_stack()
update_cache_forward()

11. extent replicas

[I think] Extent replicas are used when text is cut or copied from a buffer.
the extents that overlap the text are copied into extent replicas that are
attached to the text.

[extents.h]

struct extent_replica
{
  int start;
  int end;
  Lisp_Object extent;
};

typedef struct extent_replica *EXTENT_REPLICA;
typedef struct extent_replica *DUP;

struct merge_replicas_struct
{
  Lisp_Object dup_list;
  int entry_offset;
  int entry_length;
};

[extents.c]

struct replicate_extents_struct
{
  int from;
  int length;
  struct buffer *buf;
  Lisp_Object head;
  Lisp_Object nconc_cell;
};

replicate_extents_mf()
replicate_extents()
splice_in_extent_replicas()
merge_replicas()
add_to_replicas_lists()
merge_replicas_concatenating_mf()
mrp_pred()
merge_replicas_pruning_mf()

x. miscellaneous

check_from_to(from, to, buf)
	Make sure that positions "from" and "to" lie within the buffer "buf".
extent_endpoint(extent, endp)
	Returns the start or end point of the specified extent, as a *buffer*
	index.
extent_index_offset()
buffer_starting_extent()
syms_of_extents()

y. not yet dealt with

set_extent_flags()
set_extent_attributes_index()
install_extent_glyphs()
restore_extent_state()

extent_to_generic_id()
make_extent_for_data()
extent_glyph_at()
extent-to-generic-id
glyph_in_column_p()
restore-extent

set_point_internal()
set_point()
set_buffer_point()
last_visible_position()

----------------------------------------------------------------------
------------------------------- Faces --------------------------------
----------------------------------------------------------------------

struct face
{
  unsigned char underline;
  unsigned char hilited;
  unsigned char modif;
#ifdef HAVE_X_WINDOWS
  GC 		facegc;
  XFontStruct*	font;
#if 0
  char* 	font_name;	/* missing piece of info from XFontStruct... */
#endif				/* we store this up in lisp now */
  unsigned long	foreground;
  unsigned long	background;
  Pixmap	back_pixmap;
  unsigned int	pixmap_w, pixmap_h, pixmap_depth;
#endif /* HAVE_X_WINDOWS */
};

About faces:

A face is represented on the Lisp level as an array of 8 elements, the first
of which is the symbol 'face:

element:	meaning:
0		'face
1		name of face
2		face id number
3		name of face's font or nil
4		name of foreground color
5		name of background color
6		name of background pixmap
7		whether face is underlined

In the C code, faces are stored as a struct face:

struct face
{
  unsigned char underline;
  unsigned char hilited;
  unsigned char modif;
  unsigned char fill_style;
  struct font *font;
  unsigned long	foreground;
  unsigned long	background;
  struct x_bitmap *back_pixmap;
};

Every screen contains an alist of all the faces, associating the face's name
with its representation as a Lisp vector.  In addition, each screen contains
an array of pointers to struct face's, one per face, indexed by the face's
id number.  Note that the Lisp data shadows the C data and that each screen
contains a separate copy of all the faces; this is so that faces of the same
name (e.g. "default" or "modeline") can display differently for different
screens.

In struct screen, "face_alist" is the screen's alist of faces, "faces" is the
array of pointers to struct face's, and "n_faces" is the number of elements
in the array.

make-face creates a new face with a specified name, setting its name and id
number and leaving its other attributes unspecified.  It modifies the
face-alist of all the screens and calls make-face-internal to create the
struct face's and modify the C pointers.

Individual characteristics of a face are modified with set-face-font,
set-face-foreground, set-face-background, set-face-background-pixmap,
and set-face-underline.  All of these allow modifying the characteristic
of the face only on one screen or on all screens.  All call set-face-1, which
modifies the Lisp faces appropriately and calls set-face-attribute-internal
to change the C structures.  This function calls load_pixmap(), load_font(),
load_color(), etc. as necessary.

Individual characteristics of a face are retrieved with face-name, face-id,
face-font, face-foreground, face-background, face-background-pixmap, and
face-underline-p.


----------------------------------------------------------------------
------------------------------ Fonts ---------------------------------
----------------------------------------------------------------------

The font type is XFontStruct.

#define FONT_WIDTH(f)	((f)->max_bounds.width)
#define FONT_HEIGHT(f)	((f)->ascent + (f)->descent)
#define TOTAL_HEIGHT(f)	((f)->ascent + (f)->descent + x_interline_space)
#define FONT_BASE(f)    ((f)->ascent)

FONT_ASCENT(f) [xdisp.c] is equivalent to FONT_BASE(f).
x_interline_space is the space in pixels to be placed between lines.

The baseline is the line on which all characters are to be placed.  Some
characters extend below the baseline as well as above it (e.g. lowercase g).
The "ascent" is the number of pixels the character extends above the
baseline, and the "descent" the number of pixels the character extends below
the baseline.  These two values vary from character to character.

The default font for a screen is contained in screen->display.x->font.

----------------------------------------------------------------------
-------------------------- Fundamental Types -------------------------
----------------------------------------------------------------------

Lisp_Object is the main type.  This is just a 32-bit int, of which the lowest
24 (or 26) bits are the value of the type (either an integer or a pointer
to the type's actual value), the remaining bits except 1 specify the type,
and the highest bit is a garbage-collection bit that is always 0 when not
in garbage-collection.  Accessing the value of a Lisp_Object as a particular
type is done through the macros in lisp.h, which are all in capital letters
without any underscores, and begin with X (e.g. XINT(), XSYMBOL(), etc.).
These macros mask off the type bits and cast the value to the correct integer
or pointer type.

The types (enum Lisp_Type) are:

Lisp_Int
	Integer.  XINT(obj) is the integer value. 

Lisp_Symbol
	Symbol.  XSYMBOL (object) points to a struct Lisp_Symbol. 

Lisp_Marker
	Marker (buffer ptr).  XMARKER(object) points to a struct Lisp_Marker. 

Lisp_String
	String.  XSTRING (object) points to a struct Lisp_String.
	The length of the string, and its contents, are stored therein. 

Lisp_Vector
	Vector of Lisp objects.  XVECTOR(object) points to a struct
	Lisp_Vector.  The length of the vector, and its contents, are
	stored therein. 

Lisp_Cons
	Cons.  XCONS (object) points to a struct Lisp_Cons. 

Lisp_Compiled
	Byte-compiled function.  A vector of 4 to 6 elements which are the
        arglist, bytecode-string, constant vector, stack size,
        (optional) doc string, and (optional) interactive spec.  

Lisp_Buffer
	Editor buffer.  XBUFFER(obj) points to a struct buffer.  

Lisp_Subr
	Built-in function.  XSUBR(obj) points to a struct Lisp_Subr
        which describes how to call the function, and its documentation,
        as well as pointing to the code. 

Lisp_Internal
	Internal value return by subroutines of read.
	The user never sees this data type.
        Its value is just a number. 

Lisp_Intfwd
	Forwarding pointer to an int variable.
        This is allowed only in the value cell of a symbol,
        and it means that the symbol's value really lives in the
        specified int variable.
        XINTPTR(obj) points to the int variable. 

Lisp_Boolfwd
	Boolean forwarding pointer to an int variable.
        This is like Lisp_Intfwd except that the ostensible
        "value" of the symbol is t if the int variable is nonzero,
        nil if it is zero.  XINTPTR(obj) points to the int variable. 

Lisp_Process
	Object describing a connection to a subprocess.
        It points to storage of type struct Lisp_Process.

Lisp_Objfwd
	Forwarding pointer to a Lisp_Object variable.
        This is allowed only in the value cell of a symbol,
        and it means that the symbol's value really lives in the
        specified variable.
        XOBJFWD(obj) points to the Lisp_Object variable. 

Lisp_Screen
	Pointer to a vector-like object describing a display screen
        on which Emacs can display a window hierarchy.  

Lisp_Internal_Stream
	Used when a FILE * value needs to be passed
        in an argument of type Lisp_Object.
        You must do *(FILE **) XPNTR(obj) to get the value.
        The user will never see this data type. 

Lisp_Buffer_Local_Value
	Used in a symbol value cell when the symbol's value is per-buffer.
        The actual contents are a cons cell which starts a list like this:
        (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)).

	BUFFER is the last buffer for which this symbol's value was
	made up to date.

        CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
	b_local_var_alist, that being the element whose car is this variable.
        Or it can be a pointer to the (CURRENT-ALIST-ELEMENT .DEFAULT-VALUE),
	if BUFFER does not have an element in its alist for this variable
	(that is, if BUFFER sees the default value of this variable).

	If we want to examine or set the value and BUFFER is current,
	we just examine or set REALVALUE.
	If BUFFER is not current, we store the current REALVALUE value into
	CURRENT-ALIST-ELEMENT, then find the appropriate alist element for
	the buffer now current and set up CURRENT-ALIST-ELEMENT.
	Then we set REALVALUE out of that element, and store into BUFFER.

	If we are setting the variable and the current buffer does not have
	an alist entry for this variable, an alist entry is created.

	Note that REALVALUE can be a forwarding pointer.
	Each time it is examined or set, forwarding must be done.  

Lisp_Some_Buffer_Local_Value
	Like Lisp_Buffer_Local_Value with one difference:
	merely setting the variable while some buffer is current
	does not cause that buffer to have its own local value of this
	variable.  Only make-local-variable does that.  

Lisp_Buffer_Objfwd
	Like Lisp_Objfwd except that value lives in a slot
        in the current buffer.  Value is byte index of slot within buffer 

Lisp_Void
	In symbol value cell, means var is unbound.
        In symbol function cell, means function name is undefined. 

Lisp_Window
	Window used for Emacs display.
        Data inside looks like a Lisp_Vector.  

Lisp_Window_Configuration
	Used by save,set,restore-window-configuration 

Lisp_Extent
	An active region in buffer or string.  XEXTENT (obj) is
        typedef EXTENT. 

Lisp_Extent_Data

Lisp_Extent_Replica

Lisp_Float

Lisp_Event

Lisp_Keymap

	Lisp objects are created through various functions, some of which
just mirror just mirror Lisp primitives.  make_number() converts a
number into a Lisp_object, without allocating any space.  Fmake_vector()
creates a vector of a specified size.

----------------------------------------------------------------------
------------------------------- glyphs -------------------------------
----------------------------------------------------------------------

[dispnew.c, xdisp.c]

A "glyph" is (more or less) a single character to be displayed on the
screen.  Note that a character in the text may be displayed as more than
one glyph (e.g. "^L" is normally displayed as two glyphs, ^ and L.)
Internally, a glyph is of type GLYPH, which is actually a 16-bit value
but normally just holds a regular character.

1. structures

/* This structure is used for the actual display of text on a screen.

   There are two instantiations of it:  the glyphs currently displayed,
   and the glyphs we desire to display.  The latter object is generated
   from buffers being displayed. */

struct screen_glyphs
  {
#ifdef MULTI_SCREEN
    struct screen *screen;	/* Screen these glyphs belong to. */
#endif /* MULTI_SCREEN */
    int height;
    int width;

    int *used;			/* Vector of widths (in chars) of lines. */
    GLYPH **glyphs;		/* glyphs[Y][X] is the GLYPH at X,Y. */
    GLYPH *total_contents;	/* The actual contents. `glyphs' points here */
    char *enable;		/* Vector indicating meaningful contents. */
    int   *bufp;		/* Buffer offset of this line's first char. */
    int *nruns;			/* N runs of differently displayed text. */
    struct run **face_list;
    struct run *faces;

#ifdef HAVE_X_WINDOWS
    short *top_left_x;		/* Pixel position of top left corner */
    short *top_left_y;
    short *pix_width;		/* Pixel width of line. */
    short *pix_height;		/* Pixel height of line. */
    short *max_ascent;		/* Pixel value of max font->ascent of line. */
#endif	/* HAVE_X_WINDOWS */
  };

"struct screen_glyphs" is a complete description of what is currently
displayed on a screen.  The text is stored as a two-dimensional array
of glyphs along with a series of "runs" describing how the text is to
be displayed.  Each line has a number of such runs, and each run
describes how a particular chunk of text is to be displayed (i.e. if
there is a font change on a line, a new run will start there).

"screen" is the screen this structure refers to, and "height" and "width"
are the size of the screen in glyphs.  "pix_height" and "pix_width" are
arrays specifying the height and width of each line in pixels. (note that
"pix_height" includes the interline space) "max_ascent"
is an array specifying the maximum ascent of each line, in pixels -- i.e.
the maximum height the line extends above its baseline (each character is
made up of an ascent and a descent, and the total height of the character is
determined by adding these two values plus the interline space).

"used" is an array specifying,
for each line, the number of text characters (not glyphs) on that line.
"glyphs" is an array of vectors, each describing the glyphs on a line.
The vectors themselves are stored contiguously in "total_contents".  Note
that at the end of each line of glyphs there is a NULL_GLYPH.

"nruns" is an array specifying the number of runs on each line.  "face_list"
is an array of vectors, each listing the runs on a line.

"enable" is an array specifying, for each line, whether the glyph contents
of that line are valid.  For the "current glyphs" structure, this array
is reset when screen lines become garbaged.  For the "desired glyphs"
structure, this is reset when the structure is cleared out prior to
redisplay.

"top_left_x" and "top_left_y" are arrays specifying, for each line, the
pixel coordinate of the top left corner of the line.

0. validating/invalidating lines of text

cancel_line(vpos, screen)
	Invalidate the specified line.  This resets the enable[] value in
	the screen's desired glyphs.
clear_screen_records(screen)
	Invalidate all the lines in the screen's current glyphs.

1. converting text characters to glyphs; display tables

struct glyphs_from_chars
  {
	UCHAR c;
	GLYPH *glyphs;
#ifdef LINE_INFO_COLUMN
	Lisp_Object info_column_glyphs;
#endif
	int columns;
	struct face *faceptr;
	Lisp_Object begin_class[GLYPH_CLASS_VECTOR_SIZE];
	Lisp_Object end_class[GLYPH_CLASS_VECTOR_SIZE];
	short n_nonfont;
	int next_visible;
	UCHAR begin_or_end;		/* 0:none, 1:end, 2:begin, 3:both */
#ifdef HAVE_X_WINDOWS
	int begin_columns;
	int begin_pixel_width;
	int end_columns;
	int end_pixel_width;
	int pixel_width;
	int pixel_height;
#endif
	/* The chars in the buffer being processed that lie between
	   [run_pos_lower, run_pos_upper] are promised to be in the same run,
	   and to be separated from begin and/or end glyphs, provided they fit
	   on the same line. This means that there are NO pixel-maps
	   (sometimes called glyphs in other contexts) or font changes in the
	   display of the chars in this range. It is NOT promised to be a
	   maximal such range. */
	int run_pos_lower;
	int run_pos_upper;
  };

The "display table" controls the way characters are displayed.  There is
a default display table, [V]standard-display-table, and "display_table" is
a built-in buffer-local field in struct buffer.  A display table is a Lisp
vector of 261 elements.  The first 256 correspond to all possible
characters, and the last 5 refer to special characters (the "control glyph"
for displaying control characters, the "escape glyph" when characters are
displayed in octal, the "continuation glyph" for long lines, etc.) -- see
buffer.c, "buffer-display-table".  Each element is a "rope", which is a
string that is interpreted to be an array of glyphs, i.e. a double-character
string.  If an element of the display table is NIL, a default interpretation
is substituted.  The built-in buffer-local variable "ctl-arrow" controls
how the default is printed.  The defaults are:

1) printable characters, and characters deemed to be printable through
   ctl-arrow: the character itself.
2) control characters, if ctl-arrow is not nil: the "control glyph"
   followed by a printable glyph for the character.
3) tab: the correct number of instances of TABGLYPH, which is defined to
   be '\t'.  (note that this substitution *always* happens; i.e. the rope
   for "tab" sitting in the display table is ignored.)
4) other characters: the "escape glyph" followed by the octal representation
   of the character.
5) the control glyph: ^.
6) the escape glyph: \.


struct glyphs_from_chars is used to hold the glyphs corresponding to a
string of characters.  Some of the functions below return a pointer to
such a structure.  They use a static variable "char_glyphs".

GLYPH_SET_VALUE(g, v)
	Macro to set a glyph's value.  Just does "g = v".
GLYPH_FROM_CHAR(c)
	Converts a character to a glyph.  Just does (GLYPH) c.
struct glyphs_from_chars *
glyphs_from_char(screen, c, g, tab_width, ctl_arrow, fp, dp,
			hscroll, columns, tab_offset, pixel_values)
	Determines and returns the glyphs that correspond to a text character
	"c".  The glyphs are returned through "g", a pointer to an array of
	glyphs.  Also returns a pointer to "char_glyphs", which contains this
	same information plus values in the fields "columns", "pixel_width",
	and "pixel_height".  See above description of glyphs for a description
	of how this actually works.
update_cache(buffer, extfrag)
	Used by glyphs_from_bufpos() to cache the information last returned from
	buffer_extent_fragment_at().
struct glyphs_from_chars *
glyphs_from_bufpos (screen, buffer, pos, dp, hscroll, columns, tab_offset,
			direction, only_nonchars)
	Similar to glyphs_from_char() but also deals with "begin glyphs" and
	"end glyphs". (used only when XEmacs is linked with Energize)
	This requires looking at the extent
	fragment for the specified position.  Calculating an extent fragment is
	an expensive operation, so the last-calculated extent fragment is cached
	in case	it's still valid. (However, buffer_extent_fragment_at(), which
	is called to compute the extent fragment, does its own caching, so the
	caching done here is worthless.) "last_buffer", "last_screen",
	"last_buffer_modiff", "last_buffer_facechange", "last_buffer_extfrag",
	"last_extfrag_from_pos", "last_extfrag_to_pos", and "last_extfrag_face"
	are used to do the cachine.
		Some code is duplicated between this function and
	glyphs_from_chars().  Instead of using a user-supplied glyph array, the
	static variable "measure_glyphs" is used.   A pointer to the static
	variable "displayed_glyphs" is returned.

2. begin and end glyphs

I'm not sure what these are, but they only seem to exist when XEmacs
is linked with Energize.  Some day I may figure out what they are and see
if they're neat feature, but not now.  Suffice to say, if ENERGIZE is not
defined there will never be any.

3. runs

enum run_type
{
  unused_run,
  glyph,
  column_glyph,
  font,
  space,
  window			/* indicate a window change */
};

The run types are as follows:

unused_glyph:
glyph: a bitmap.
column_glyph:
font: characters to be displayed in a particular font.
space:
window:

struct run
{
  enum run_type type;
  int length;			/* Length in glyphs */
  struct face *faceptr;
  struct window* w;		/* window starting here */
  int bufp;			/* position in buffer */
  Lisp_Object class;		/* extent containing, if any */
  int begin_p;			/* 1 begin glyph 0 if end glyph*/
#ifdef HAVE_X_WINDOWS
  int pix_length;		/* Length in pixels */
#endif
#ifdef LINE_INFO_COLUMN
  int lineinfo_glyph_index;	/* Since glyphs in the lineinfo column don't
				   go into the glyphs array (because they
				   don't take up screen space) we need to
				   store them somewhere. */
#endif
};

A "run" is a part of a line of text that is to be displayed with a
particular characteristic.  If different parts of a line of text are
to be displayed with different characteristics, these different parts
will be described with different runs.  Runs are stored within a
struct screen_glyphs, as described above.

"struct run" specifies a run. "type" is the type of run, "length" the
number of glyphs in the run, "faceptr" the characteristics of the text
to be displayed, "w" the window in which the run occurs [check this??].

int new_run(screen, vpos, type, faceptr)
	Adds a new run to the screen's "desired_glyphs" structure.  "vpos"
	is the line on which the run occurs, and "type" and "faceptr" are
	the run's characteristics.  Returns the index of this run in the
	vector of runs for this line.
struct run *append_run(screen, vpos, type, class, faceptr, begin_p)
	Similar to new_run().  In addition, sets the run's "class" and "begin_p"
	values.  Return value is different.
void right_shift_runs(screen, vpos, run, nslots)
	Right-shift the lines on line "vpos" in the screen's "desired_glyphs"
	structure by "nslots" runs, starting at run "run".  The new slots
	are not initialized.
SET_RUN(screen, vpos, run, type, len, face, class, begin_p, pix_length)
	Initializes a run with the specified values.


4. updating the glyphs in struct screen_glyphs

void append_glyph(screen, vpos, glyph, type, class, faceptr, begin_p)
	Adds a glyph to the screen's "desired_glyphs" structure, at the
	end of the line "vpos".  "type", "class" and "faceptr" specify
	the characteristics of this glyph; if the last run on the
	specified line does not match these characteristics, a new run
	is created.  The various arrays are updated as necessary.
void remove_glyph(screen, vpos)
	Removes the last glyph on line "vpos" in the screen's "desired_glyphs"
	structure.  If this causes the last run to shrink to zero glyphs in
	length, the run is removed.  All structures are updated as necessary
	except pix_height[].
void overlay_glyph(screen, vpos, glyph, type, class, faceptr, column, begin_p)
	Overlays the glyph at column "column" on line "vpos" in the screen's
	"desired_glyphs" structure.  "type", "class" and "faceptr" specify
	the characteristics of this glyph; if the run at the specified position
	does not match, that run is split as necessary and a new run inserted
	as necessary. (Note that the code does not currently handle the case
	where a run must be split in the middle) All structures are updated as
	necessary except pix_height[].  May call right_shift_runs() to insert
	a run.
int display_string(w, vpos, string, hpos, truncate, mincol, maxcol,
	this_face, pix_width_ptr)
/* Display NULL-terminated STRING on one line of window W, starting at HPOS.
   Display at position VPOS.  Caller should have done get_display_line.

   TRUNCATE is GLYPH to display at end if truncated.  Zero for none.

   MINCOL is the first column ok to end at.  (Pad with spaces to this col.)
   MAXCOL is the last column ok to end at.  Truncate here.
     -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
   Both count from the left edge of the screen, as does HPOS.
   The right edge of W is an implicit maximum.
   If TRUNCATE is nonzero, the implicit maximum is one column before the edge.

   Display is performed using FACE, unless that is 0, then the screen
   default face is used.  Each new string on the smae line consitutes a
   different run.

   Returns ending hpos on the line.

   If PIX_WIDTH_PTR is nonzero, it is a pointer to an int variable that
   will be set to the pixel width of the string.   */
   Changes the "desired_glyphs" structure of the window's screen.  Pads
   as necessary with spaces to reach position "hpos"; then overlays or
   appends the glyphs, using overlay_glyph() or append_glyph().
   glyphs_from_char() is first called to convert a character to one or more
   glyphs; the standard display table [V]standard-display-table is used for
   this purpose. [why???] If the string needs to be truncated, any extra
   glyphs that got added beyond the end are removed and the glyph
   "TRUNCATOR_BITMAP" is added.  If necessary, the end is padded with spaces.

5. displaying the mode line

decode_mode_spec()
display_mode_element()
display_mode_line()

6. displaying the title

screen_title_display_string()
x_format_screen_title()


9. other utility routines

run_from_glyph_index()
get_glyph_dimensions()
add_in_column_glyph()
int pixel_to_glyph_translation(struct screen *s, unsigned int pix_x,
	unsigned int pix_y, int *x,	int *y,	struct window **w, int *bufp,
	int *gly, Lisp_Object *class, int *begin_p)

	Determine the glyph under the pixel (pix_x, pix_y) on the screen "s".
	The glyph itself is returned in "gly", its coordinates in (x, y),
	the window containing these coordinates in "w", ...


10. misc

init_xdisp()
syms_of_xdisp()

----------------------------------------------------------------------
--------------------------- input blocking ---------------------------
----------------------------------------------------------------------

what the hell is this?  This is found in free-hooks.c.  BLOCK_INPUT(),
UNBLOCK_INPUT(), and other such macros are called all over the place.


----------------------------------------------------------------------
------------------------------ main loop -----------------------------
----------------------------------------------------------------------

The main loop is recursive-edit, which is called by main() and in
various other places.  recursive-edit and the functions below it do lots
of unwind-protecting, condition-casing, and catching because of the
possibility of a non-local exit from recursive-edit (see flowchart).  If
we are at the top level and "top-level" contains a Lisp form, it is
executed (this is set by loadup.el, which is normally run from the
command line when the original bare Emacs is converted to the full
version).  Normally "normal-top-level" (in startup.el) is called, and
processes the command line and does other such stuff.

command_loop_1() is then called, and it is the real main loop.  All it
does is loop until ^G is hit (or until a sub-function causes a non-local
exit), getting an event and dispatching it.

----------------------------------------------------------------------
-------------------------------- menus -------------------------------
----------------------------------------------------------------------

A menu is set by setting the value of the variable "current-menubar" (which
may be buffer-local) and then calling "set-menubar-dirty_flag" to signal
a change.  This will cause the menu to be redrawn at the next redisplay.
The format of the data in "current-menubar" is described in menubar.c.

Internally the data in current-menubar is parsed into a tree of
widget_value's (defined in lwlib.h); this is accomplished by the recursive
function menu_item_descriptor_to_widget_value(), called by
compute_menubar_data().  Such a tree is deallocated using
free_widget_value().

update_screen_menubars() is one of the external entry points.  This checks
to see, for each screen, if that screen's menubar needs to be updated.  This
is the case if

1) set-menubar-dirty-flag was called since the last redisplay.  (This
   function sets the C variable menubar_has_changed.)
2) The buffer displayed in the screen has changed.
3) The screen has no menubar currently displayed.

set_screen_menubar() is called for each such screen.  This function calls
compute_menubar_data() to create the tree of widget_value's, then calls
lw_create_widget(), lw_modify_all_widgets(), and/or lw_destroy_all_widgets()
to create the X-Toolkit widget associated with the menu.

update_psheets(), the other external entry point, actually changes the menus
being displayed.  It uses the widgets fixed by update_screen_menubars() and
calls various X functions to ensure that the menus are displayed properly.

The menubar widget is set up so that pre_activate_callback() is called when
the menu is first selected (i.e. mouse button goes down), and
menubar_selection_callback() is called when an item is selected.
pre_activate_callback() calls the function in activate-menubar-hook, which
can change the menubar (this is described in menubar.c).  If the menubar 
is changed, set_screen_menubars() is called.  menubar_selection_callback()
enqueues a menu event, putting in it a function to call (either "eval"
or "call-interactively") and its argument, which is the callback function
or form given in the menu's description.


----------------------------------------------------------------------
----------------------------- minibuffers ----------------------------
----------------------------------------------------------------------


----------------------------------------------------------------------
---------------------------- naming scheme ---------------------------
----------------------------------------------------------------------

'F...'	C functions corresponding to Lisp primitives
'S...'	struct Lisp_Subr's corresponding to Lisp primitives
'V...'	C variables tied to built-in Lisp variables
'Q...'  C structures corresponding to Lisp constants, such as Qt and Qnil
'QK..'  C variables holding Lisp_Objects containing keysym names


----------------------------------------------------------------------
--------------------- naming scheme of functions ---------------------
----------------------------------------------------------------------

All built-in primitives are Lisp objects of type Lisp_Subr.  They point
to a struct Lisp_Subr, which contains a pointer to the C function for
the primitive, the minimum and maximum number of arguments, a string
holding the name of the primitive, and a few other things.  The
corresponding C function is named by prepending an 'F' to the
primitive's name, and the corresponding struct Lisp_Subr is named by
prepending an 'S' to the primitive's name.  The macro DEFUN is used to
automate the C declarations of primitives.


----------------------------------------------------------------------
------------------------------- obarray ------------------------------
----------------------------------------------------------------------

An obarray is a hash table that indexes strings to their corresponding
symbols.  obarrays are Lisp vectors of symbols.  Chaining is done
through a special, normally inaccessible field of struct Lisp_Symbol.
Emacs maintains a global obarray for all the interned strings.

OBARRAY_SIZE (manifest constant) [lread.c] is the size of the
	global obarray, which is 509.

Vobarray holds the global obarray.

init_obarray() [lread.c] allocates space for the global obarray and
initializes the obarray, which involves creating a few important
symbols and putting NIL into the obarray.

hash_string() [lread.c] hashes a string into an unsigned int.

check_obarray() [lread.c] makes sure that an obarray passed as an
argument to a Lisp function is the right type.

oblookup() [lread.c] looks up a string in an obarray, returning the
corresponding symbol if the string is found, or returning the hash value
otherwise.

map_obarray() [lread.c] applies a C function to every element in an
obarray.

Fmapatoms() [lread.c] is a Lisp primitive that does the same thing as
map_obarray().

Adding to an obarray is performed within the Fintern() function.

----------------------------------------------------------------------
---------------------------- point motion ----------------------------
----------------------------------------------------------------------

----------------------------------------------------------------------
------------------------------ redisplay -----------------------------
----------------------------------------------------------------------

1. Important variables

selected_screen
	The currently selected screen (struct screen *).
selected_window
	The currently selected window on the currently selected screen
	(struct window *).
(struct screen).garbaged
	True if the screen needs to be completely redisplayed.
(struct screen).visible
	True if the screen is currently visible.  Changed by
	make-screen-visible and make-screen-invisible.
windows_or_buffers_changed
	Non-zero if any part of the display needs to change.
noninteractive
	True if we are not in an interactive Emacs (if Emacs was invoked with
	the -batch option).  In this case, nothing is displayed except for
	messages sent with message(), which are sent to stderr.
in_display
	True if we are currently updating the display.
Vscreen_list
	List of all the screens that currently exist.
clip_changed
	?
redraw_mode_line
	Non-zero if the mode line for the current screen needs to be redrawn.

----------------------------------------------------------------------
------------------------------- screens ------------------------------
----------------------------------------------------------------------

[from screen.h]

struct screen
{
  int size;
  struct Lisp_Vector *next;

  /* glyphs as they appear on the screen */
  struct screen_glyphs *current_glyphs;

  /* glyphs we'd like to appear on the screen */
  struct screen_glyphs *desired_glyphs;

  /* Cost of inserting 1 line on this screen */
  int *insert_line_cost;

  /* Cost of deleting 1 line on this screen */
  int *delete_line_cost;

  /* Cost of inserting n lines on this screen */
  int *insert_n_lines_cost;

  /* Cost of deleting n lines on this screen */
  int *delete_n_lines_cost;

  /* glyphs for the mode line */
  struct screen_glyphs *temp_glyphs;

  /* Intended cursor position of this screen.
     Measured in characters, counting from upper left corner
     within the screen.  */
  int cursor_x;
  int cursor_y;

  /* Is the cursor turned off? */
  int cursor_erased;

  /* Actual cursor position of this screen.
     (Not used for terminal screens.)  */
  int phys_cursor_x;
  int phys_cursor_y;

  /* Size of this screen, in units of characters.  */
  int height;
  int width;

  /* New height and width for pending size change.  0 if no change pending.  */
  int new_height, new_width;

  /* Name of this screen: a Lisp string.  */
  Lisp_Object name;

  /* This screen's root window.  Every screen has one.
     If the screen has only a minibuffer window, this is it.
     Otherwise, if the screen has a minibuffer window, this is its sibling.  */
  Lisp_Object root_window;

  /* This screen's selected window.
     Each screen has its own window hierarchy
     and one of the windows in it is selected within the screen.
     The selected window of the selected screen is Emacs's selected window.  */
  Lisp_Object selected_window;

  /* This screen's minibuffer window.
     Most screens have their own minibuffer windows,
     but only the selected screen's minibuffer window
     can actually appear to exist.  */
  Lisp_Object minibuffer_window;

  /* A copy of the global Vbuffer_list, to maintain a per-screen buffer
     ordering.  The Vbuffer_list variable and the buffer_list slot of each
     screen contain exactly the same data, just in different orders.  */
  Lisp_Object buffer_alist;

  /* Parameter alist of this screen.
     These are the parameters specified when creating the screen
     or modified with modify-screen-parameters.  */
  Lisp_Object param_alist;

  /* Vector representing the menubar currently displayed.  See menubar.c. */
  Lisp_Object menubar_data;

  /* The output method says how the contents of this screen
     are displayed.  It could be using termcap, or using an X window.  */
  enum output_method output_method;

  /* A structure of auxiliary data used for displaying the contents.
     struct x_display is used for X window screens;
     it is defined in xterm.h.  */
  union display { struct x_display *x; int nothing; } display;

  /* Nonzero if last attempt at redisplay on this screen was preempted.  */
  char display_preempted;

  /* Nonzero if screen is currently displayed.  */
  char visible;

  /* Nonzero if window is currently iconified.
     This and visible are mutually exclusive.  */
  char iconified;

  /* Nonzero if this screen should be redrawn.  */
  char garbaged;

  /* True if screen actually has a  minibuffer window on it.
     0 if using a minibuffer window that isn't on this screen.  */
  char has_minibuffer;
     
  /* 0 means, if this screen has just one window,
     show no modeline for that window.  */
  char wants_modeline;

  /* True if screen's root window can't be split.  */
  char no_split;

  /* Storage for messages to this screen. */
  char *message_buf;

  /* list of faces */
  struct face**	faces;
  int n_faces;

  /* the lisp data (shadowing the C data) */
  Lisp_Object face_alist;

#ifdef ENERGIZE
  DisplayContext*	display_context;
#endif
};

/* Each X screen object points to its own struct x_display object
   in the display.x field.  The x_display structure contains all
   the information that is specific to X windows.  */

struct x_display
{
  /* Position of the X window (x and y offsets in root window).  */
  int left_pos;
  int top_pos;

  /* Size of the X window in pixels, including internal border. */
  int pixel_height, pixel_width;
#ifdef DEADX
  /* Here are the Graphics Contexts for the default font. */
  GC normal_gc;				/* Normal video */
  GC reverse_gc;			/* Reverse video */
  GC cursor_gc;				/* cursor drawing */
#ifdef LINE_INFO_COLUMN
  GC line_info_gc;			/* lineinfo column */
#endif
#endif

  /* Width of the internal border.  This is a line of background color
     just inside the window's border.  When the screen is selected,
     a highlighting is displayed inside the internal border.  */

  int internal_border_width;

#ifdef LINE_INFO_COLUMN
  /* Width of the line info column.  The line info column appears to
     the left of the left margin, inside the internal border.  It is
     used to display glyphs related to each line. */
  int line_info_column_width;
  int default_line_info_column_width;
#ifdef DEADX
  PIX_TYPE line_info_background_pixel;
#endif

  FONT_TYPE *font;
#endif
  int text_height;

  /* Flag to set when the X window needs to be completely repainted. */
  int needs_exposure;

#ifdef DEADX
  /* The widget of this screen.  This is the window of a "shell" widget. */
  Widget widget;
  /* The XmPanedWindows... */
  Widget column_widget;
#ifdef LINE_INFO_WIDGET
  Widget row_widget;
  /* The widget of the line-info widget */
  Widget lineinfo_widget;
#endif
  /* The widget of the edit portion of this screen; the window in
     "window_desc" is inside of this. */
  Widget edit_widget;

  Widget menubar_widget;
#endif

#ifdef ENERGIZE
  /* The Energize property-sheets.  The current_ slots are the ones which are
     actually on the screen.  The desired_ slots are the ones which should
     be there.  Redisplay synchs these.
   */
  int *current_psheets;
  int *desired_psheets;
  int current_psheet_count;
  int desired_psheet_count;
  Lisp_Object current_psheet_buffer;
  Lisp_Object desired_psheet_buffer;
#endif

  /* This is true if we own the window, that is, it is not a window that
     was created by another process.  If we don't own the window, we aren't
     allowed to destroy it. "The window" referred to is always window_desc;
     if USE_WIDGET is true, we always own the window inside of the
     edit_widget. */
  char own_window;

  /* Whether this screen has the keyboard focus locked on it, whether the
     mouse is in this screen, and whether this is the screen currently
     receiving keyboard input.  In point-to-type mode, focus_p will never
     be true, and mouse_p and input_p will be the same.  In click-to-type
     mode, input_p will be the same as focus_p, and mouse_p will vary.
     Generally, input_p is the only interesting value, but the other two
     are necessary state to correctly interpret the interactions between
     FocusIn, FocusOut, EnterNotify, and LeaveNotify events.
     
     These must be per-screen properties instead of global variables,
     because screens are not necessarily on the same monitor, so more than
     one can have a mouse, and more than one can have keyboard focus.
   */
  char focus_p;
  char mouse_p;
  char input_p;
  
  /* 1 if the screen is completely visible on the display, 0 otherwise.
     if 0 the screen may have been iconified or may be totally
     or parrtially hidden by another X window */
  char totally_visible_p;
};

[
"text_height" is (more or less) the maximum height of any character that
might be displayed on the screens; specifically, it is the maximum, over
all the fonts displayed on the screen, of the sum of the font's "ascent"
and "descent" values.
]

A "screen" corresponds to one window in the underlying windowing system.
In a non-windowing environment, there is only one screen, corresponding
to the entire screen.  Each "screen" is divided up into non-overlapping
"windows", which the windowing system knows nothing about.

Screens are allocated like windows -- i.e. allocated as vectors of the
proper size, and then the type of the Lisp_Object is set to Lisp_Screen.
The screens structure contains screen-specific properties such as the
screen's size, the cursor position, whether the cursor is displayed, the
tree of windows that the screen consists of, what the menus look like,
insertion/deletion costs, etc.  The actual text on the screen is held
in "current_glyphs", a pointer to a struct screen_glyphs (see "glyphs").
"desired_glyphs" points to another struct screen_glyphs, containing the
text that the screen should next display.

The window-system-specific information is held in "display" (and should
be a void pointer).  display.nothing is for accessing the value raw --
nothing == 0 means that the screen has been deleted (it will be garbage-
collected along with the rest of the vectors); nothing == 1 means that
this is a "terminal" screen (a screen corresponding to the entire
physical screen, used in non-windowing systems).  Window-system-specific
stuff is done by calling x_* functions; these functions manipulate the
display structure.

1. variables

Vscreen_list points to a list of all the screens, chained through the
"next" field.  selected_screen is the screen currently selected.

2. creating a screen

make_screen(), make_screen_without_minibuffer(),
make_minibuffer_screen(), and make_terminal_screen() allocate and
initialize a struct screen.  A root window (and optionally a minibuffer
window) is allocated.  The glyph structures are not allocated.
make_screen() actually does the work and takes a parameter indicating
whether to create a minibuffer window.  make_screen_without_minibuffer()
uses make_screen() to create a screen without its own minibuffer and
gives the screen either the specified minibuffer or the global
minibuffer, taken from "global-minibuffer-screen" (see "minibuffers").
make_minibuffer_screen() makes a screen without a minibuffer and then
converts the root window into a minibuffer.  make_terminal_screen()
creates a screen and sets some parameters to indicate that it's actually
the screen corresponding to stdio.  Only make_terminal_screen() changes
Vscreen_list.

delete-screen deletes a screen.  This involves setting display.nothing to 0,
removing the screen from Vscreen_list, and calling x_destroy_window() to
do the physical work.  Checks are performed to see if the currently selected
screen is being deleted, the global minibuffer screen is being deleted,
or the only screen is being deleted.

3. selecting a screen

select-screen calls select_screen(), which sets selected_screen,
optionally runs the old screen's deselect-screen hook and the new
screen's select-screen hook, selects the screen's "selected_window",
sets the minibuffer, and calls x_new_selected_screen() and
x_focus_screen() to do the display work.

4. information about screens

selected-screen, window-screen, screen-root-window, screenp, and
screen-selected-window return properties of screens.

5. The screen list

Vscreen_list is the list of all the screens.  Elements are deleted from
it using Fdelq() and are added manually to the front.  screen-list,
next-screen, next_screen(), and prev_screen() return information about
the list of screens.

5. mouse position

read_mouse_position(), read-mouse-position, set-mouse-position
[need more about this]

6. screen visibility

make-screen-visible, make-screen-invisible, iconify-screen, deiconify-screen,
screen-visible-p, visible-screen-list [more about this], raise-screen,
lower-screen, screen-totally-visible-p

7. screen properties

screen-height, screen-width, screen-name, internal_set_screen_size(),
set-screen-height, set-screen-width, set-screen-size, set-screen-position,

8. coordinates

coordinates_in_window(), coordinates-in-window-p, window_from_coordinates(),
locate-window-from-coordinates

9. misc

choose_minibuf_screen(), syms_of_screen()

10. X functions and the screen.c functions that call them

x_new_selected_screen(screen *s)
	called by: select_screen()
x_focus_screen(screen *s)
	called by: select_screen()
x_destroy_window(screen *s, union display displ)
	called by: delete-screen
x_read_mouse_position(screen *s, int *x, int *y)
	called by: read_mouse_position()
x_set_mouse_position(screen *s, int x, int y)
	called by: set-mouse-position
x_make_screen_visible(screen *s)
	called by: make-screen-visible, deiconify-screen
x_make_screen_invisible(screen *s)
	called by: make-screen-invisible
x_iconify_screen(screen *s)
	called by: iconify-screen
x_report_screen_params(screen *s, Lisp_Object *alist)
	called by: screen-parameters
x_set_screen_values(screen *s, Lisp_Object alist)
	called by: modify-screen-parameters
x_set_window_size(screen *s, int cols, int rows)
	called by: internal_set_screen_size()
x_set_offset(screen *s, int x, int y)
	called by: set-screen-position
x_raise_screen(screen *s, int
	called by: raise-screen
x_lower_screen(screen *s)
	called by: lower-screen


----------------------------------------------------------------------
------------------------------- symbols ------------------------------
----------------------------------------------------------------------

struct Lisp_Symbol
  {
    struct Lisp_String *name;
    Lisp_Object value;
    Lisp_Object function;
    Lisp_Object plist;
    struct Lisp_Symbol *next;	/* -> next symbol in this obarray bucket */
  };

[intern??]

----------------------------------------------------------------------
-------------- symbol-values and buffer-local variables --------------
----------------------------------------------------------------------

(code is contained in data.c)

Normally the value field of a symbol contains a Lisp object that is the
value of that symbol.  In some cases, however (depending on the type of
the object stored in the field), the value must be obtained by
indirection.  Here are the special types, and their descriptions in
lisp.h:

Lisp_Intfwd
	Forwarding pointer to an int variable.
        This is allowed only in the value cell of a symbol,
        and it means that the symbol's value really lives in the
        specified int variable.
        XINTPTR(obj) points to the int variable. 

Lisp_Boolfwd
	Boolean forwarding pointer to an int variable.
        This is like Lisp_Intfwd except that the ostensible
        "value" of the symbol is t if the int variable is nonzero,
        nil if it is zero.  XINTPTR(obj) points to the int variable. 

Lisp_Objfwd
	Forwarding pointer to a Lisp_Object variable.
        This is allowed only in the value cell of a symbol,
        and it means that the symbol's value really lives in the
        specified variable.
        XOBJFWD(obj) points to the Lisp_Object variable. 

Lisp_Buffer_Local_Value
	Used in a symbol value cell when the symbol's value is per-buffer.
        The actual contents are a cons cell which starts a list like this:
        (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)).

	BUFFER is the last buffer for which this symbol's value was
	made up to date.

        CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
	b_local_var_alist, that being the element whose car is this variable.
        Or it can be a pointer to the (CURRENT-ALIST-ELEMENT .DEFAULT-VALUE),
	if BUFFER does not have an element in its alist for this variable
	(that is, if BUFFER sees the default value of this variable).

	If we want to examine or set the value and BUFFER is current,
	we just examine or set REALVALUE.
	If BUFFER is not current, we store the current REALVALUE value into
	CURRENT-ALIST-ELEMENT, then find the appropriate alist element for
	the buffer now current and set up CURRENT-ALIST-ELEMENT.
	Then we set REALVALUE out of that element, and store into BUFFER.

	If we are setting the variable and the current buffer does not have
	an alist entry for this variable, an alist entry is created.

	Note that REALVALUE can be a forwarding pointer.
	Each time it is examined or set, forwarding must be done.  

Lisp_Some_Buffer_Local_Value
	Like Lisp_Buffer_Local_Value with one difference:
	merely setting the variable while some buffer is current
	does not cause that buffer to have its own local value of this
	variable.  Only make-local-variable does that.  

Lisp_Buffer_Objfwd
	Like Lisp_Objfwd except that value lives in a slot
        in the current buffer.  Value is byte index of slot within buffer 

Lisp_Void
	In symbol value cell, means var is unbound.
        In symbol function cell, means function name is undefined. 


(from data.c, section "symbol-values")

C: do_symval_forwarding(), store_symval_forwarding(),
swap_in_symval_forwarding(), default_value() 

Lisp: symbol-value, set, default-boundp, default-value, set-default,
setq-default, make-variable-buffer-local, make-local-variable,
kill-local-variable



The forwarding types Lisp_Intfwd, Lisp_Boolfwd, and Lisp_Objfwd are used
when a Lisp variable mirrors the value of some C variable in the code.
[examples here] Such Lisp variables are defined with defvar_lisp(),
defvar_lisp_nopro(), defvar_bool(), and defvar_int() [lread.c].  Often,
the equivalent macros DEFVARLISP(), DEFVARBOOL(), DEFVARINT(),
DEFVAR_LISP(), DEFVAR_LISP_NOPRO(), DEFVAR_BOOL(), and DEFVAR_INT() are
used instead.  All of these functions simply intern the specified
variable and set the symbol's value field to the proper type and
pointer.  defvar_lisp() calls staticpro() on the Lisp variable pointed
to, while defvar_lisp_nopro() does not (see "allocation").

The type Lisp_Buffer_Objfwd refers to Lisp variables whose values mirror
per-buffer C variables held in fields ("slots") in struct buffer (each
such slot contains a Lisp object, and the slots are defined in
bufslots.h; see "buffers" for more information).  The value stored in
the symbol's value field is a byte offset into a struct buffer.
defvar_per_buffer() or the equivalent macros DEFVARPERBUFFER() or
DEFVAR_PER_BUFFER() define Lisp variables of this type.  Some such
variables have separate values for every buffer; others have default
values, just like for normal buffer-local variables.

The special struct buffer "buffer_local_symbols" contains, in each slot
for which a shadowing Lisp variable has been defined, a pointer to that
variable's symbol.  defvar_per_buffer() sets this.  struct buffer
"buffer_local_flags" indicates, for each slot, what the status of the
corresponding variable is: 0 in the slot means no variable exists; -1
means the variable is always local to each buffer; otherwise the slot
contains a mask value.  This mask value references a bit in the struct
buffer field "local_var_flags" indicating whether the corresponding
variable has its own value in this buffer.  Note that even when a buffer
does not have a local value for a particular slot variable, the slot in
that buffer will always contain the correct (i.e. default) value.
Setting a default value sets the slots of all buffers that do not have a
local value.  struct buffer "buffer_defaults" contains these default
values, for each slot that has one.  init_buffer_once() initializes
these special structs, and syms_of_buffer() defines most of the Lisp
variables that shadow slots.

do_symval_forwarding() accesses the value of a symbol, correctly dealing
with the four types of forwarding (it does not deal with normal
buffer-local variables, though -- see below).  Similarly,
store_symval_forwarding() stores a value in a symbol and deals with
forwarding types (it, too, does not deal with normal buffer-local
variables, nor does it change the flag in local_var_flags if a slot
variable formerly had no local value).  Note that symbol-value does not
actually call do_symval_forwarding(), but does exactly the equivalent
thing when dealing with forwarding pointers.

Normal buffer-local variables are tricky.  For each buffer that has its
own local value of a variable, there is an entry in the field
"local_var_alist" (an assoc-list associating symbols with values) in the
corresponding struct buffer.  In the value field of each buffer-local
variable's symbol is a list, as follows:

(REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)

BUFFER is the last buffer in which this variable was accessed or
changed; REALVALUE is the current value of this variable in that buffer;
and CURRENT-ALIST-ELEMENT points to the entry for this variable in that
buffer's local_var_alist, or points to the cons (CURRENT-ALIST-ELEMENT .
DEFAULT-VALUE) if no local value exists.  Note that the assoc-list entry
pointed to by CURRENT-ALIST-ELEMENT may not contain the most recent
value of the variable, but REALVALUE always will.

swap_in_symval_forwarding() returns the value of a buffer-local variable
in the current buffer, and, if necessary, updates the list above for the
current buffer.

There's some more tricky complexity here depending on whether the
buffer-local variable is of type Lisp_Buffer_Local_Variable (if the
variable doesn't have a local value and you set it, a local value is
created) or Lisp_Some_Buffer_Local_Variable (local values are only
created by calling make-local-variable) and depending on whether the
default value for the variable (i.e. that value the variable had when
make-local-variable or make-variable-buffer-local) was a forwarding
pointer.  Look in set, symbol-value, default-value, default_value(),
default-boundp, set-default, setq-default, make-local-variable,
make-variable-buffer-local, kill-local-variable,
kill-all-local-variables [buffer.c].  It's truly ugly.

----------------------------------------------------------------------
------------------------------ windows -------------------------------
----------------------------------------------------------------------

[from window.h]

/* Windows are allocated as if they were vectors, but then the
Lisp data type is changed to Lisp_Window.  They are garbage
collected along with the vectors.

All windows in use are arranged into a tree, with pointers up and down.

Windows that are leaves of the tree are actually displayed
and show the contents of buffers.  Windows that are not leaves
are used for representing the way groups of leaf windows are
arranged on the screen.  Leaf windows never become non-leaves.
They are deleted only by calling delete-window on them (but
this can be done implicitly).  Combination windows can be created
and deleted at any time.

A leaf window has a non-nil buffer field, and also
 has markers in its start and pointm fields.  Non-leaf windows
 have nil in these fields.

Non-leaf windows are either vertical or horizontal combinations.

A vertical combination window has children that are arranged on the screen
one above the next.  Its vchild field points to the uppermost child.
The parent field of each of the children points to the vertical
combination window.  The next field of each child points to the
child below it, or is nil for the lowest child.  The prev field
of each child points to the child above it, or is nil for the
highest child.

A horizontal combination window has children that are side by side.
Its hchild field points to the leftmost child.  In each child
the next field points to the child to the right and the prev field
points to the child to the left.

The children of a vertical combination window may be leaf windows
or horizontal combination windows.  The children of a horizontal
combination window may be leaf windows or vertical combination windows.

At the top of the tree are two windows which have nil as parent.
The second of these is minibuf_window.  The first one manages all
the screen area that is not minibuffer, and is called the root window.
Different windows can be the root at different times;
initially the root window is a leaf window, but if more windows
are created then that leaf window ceases to be root and a newly
made combination window becomes root instead.

In any case, prev of the minibuf window is the root window and
next of the root window is the minibuf window.  To find the
root window at any time, do XWINDOW (minibuf_window)->prev.

*/

struct window
  {
    /* The first two fields are really the header of a vector */
    /* The window code does not refer to them.  */
    int size;
    struct Lisp_Vector *vec_next;
    /* The screen this window is on.  */
    Lisp_Object screen;
    /* t if this window is a minibuffer window.  */
    Lisp_Object mini_p;
    /* Following child (to right or down) at same level of tree */
    Lisp_Object next;
    /* Preceding child (to left or up) at same level of tree */
    Lisp_Object prev;
    /* First child of this window. */
    /* vchild is used if this is a vertical combination,
       hchild if this is a horizontal combination. */
    Lisp_Object hchild, vchild;
    /* The window this one is a child of. */
    Lisp_Object parent;
    /* The upper left corner coordinates of this window,
       as integers relative to upper left corner of screen = 0, 0 */
    Lisp_Object left;
    Lisp_Object top;
    /* The size of the window */
    Lisp_Object height;
    Lisp_Object width;
    /* The buffer displayed in this window */
    /* Of the fields vchild, hchild and buffer, only one is non-nil.  */
    Lisp_Object buffer;
    /* A marker pointing to where in the text to start displaying */
    Lisp_Object start;
    /* A marker pointing to where in the text point is in this window,
       used only when the window is not selected.
       This exists so that when multiple windows show one buffer
       each one can have its own value of point.  */
    Lisp_Object pointm;
    /* Non-nil means next redisplay must use the value of start
       set up for it in advance.  Set by scrolling commands.  */
    Lisp_Object force_start;
    /* Number of columns display within the window is scrolled to the left.  */
    Lisp_Object hscroll;
    /* Number saying how recently window was selected */
    Lisp_Object use_time;
    /* Unique number of window assigned when it was created */
    Lisp_Object sequence_number;
    /* No permanent meaning; used by save-window-excursion's bookkeeping */
    Lisp_Object temslot;
    /* text.modified of displayed buffer as of last time display completed */
    Lisp_Object last_modified;
    /* Value of point at that time */
    Lisp_Object last_point;
    /* buf.face_change as of last time display completed */
    Lisp_Object last_facechange;
/* The rest are currently not used or only half used */
    /* Screen coords of point at that time */
    Lisp_Object last_point_x;
    Lisp_Object last_point_y;
    /* Screen coords of mark as of last time display completed */
    /* May be nil if mark does not exist or was not on screen */
    Lisp_Object last_mark_x;
    Lisp_Object last_mark_y;
    /* Number of characters in buffer past bottom of window,
       as of last redisplay that finished. */
    Lisp_Object window_end_pos;
    /* t if window_end_pos is truly valid.
       This is nil if nontrivial redisplay is preempted
       since in that case the screen image that window_end_pos
       did not get onto the screen.  */
    Lisp_Object window_end_valid;
    /* Vertical position (relative to window top) of that buffer position
       of the first of those characters */
    Lisp_Object window_end_vpos;
    /* Non-nil means must regenerate mode line of this window */
    Lisp_Object redo_mode_line;
    /* Non-nil means current value of `start'
       was the beginning of a line when it was chosen.  */
    Lisp_Object start_at_line_beg;
    /* Display-table to use for displaying chars in this window.
       Nil means use the buffer's own display-table.  */
    Lisp_Object display_table;
    /* Non-nil means window is marked as dedicated.  */
    Lisp_Object dedicated;
  };

1. general-purpose

make_window() creates and initializes a new window.  As described above,
a struct window is allocated and garbage-collected as a vector.  This
works because struct window and struct Lisp_Vector share their first few
fields; the remaining fields of struct window are all Lisp_Object's, and
these fields appear simply as elements of the vector. "sequence_number"
is used to assign a sequence number to a window; this variable is
incremented each time a window is created.

windowp asks whether a particular object is a Lisp_Window.
selected-window returns the window that the cursor appears in; this is
held in "selected_window".

----------------------------------------------------------------------
----------------------------- X interface ----------------------------
----------------------------------------------------------------------

x_write_glyphs()






----------------------------------------------------------------------
-------------------------------- files -------------------------------
----------------------------------------------------------------------

----------------------------------------------------------------------
ColumnWidget.c
----------------------------------------------------------------------


	some X stuff --?

----------------------------------------------------------------------
EmacsShell.c
----------------------------------------------------------------------

	more X stuff --?

----------------------------------------------------------------------
ScreenWidget.c
----------------------------------------------------------------------

	more X stuff --?

----------------------------------------------------------------------
abbrev.c
----------------------------------------------------------------------

Implements minor-mode "Abbrev". [section ??] [more detail here]

Lisp functions: make-abbrev-table, clear-abbrev-table, define-abbrev,
define-global-abbrev, define-mode-abbrev, abbrev-symbol,
abbrev-expansion, expand-abbrev, unexpand-abbrev,
insert-abbrev-table-description, define-abbrev-table

Lisp variables: abbrev-table-name-list, global-abbrev-table,
fundamental-mode-abbrev-table, last-abbrev, last-abbrev-text,
last-abbrev-location, abbrev-start-location,
abbrev-start-location-buffer, local-abbrev-table, abbrevs-changed,
abbrev-all-caps, pre-abbrev-expand-hook

C functions: write_abbrev(), describe_abbrev(), syms_of_abbrev()

C variables:

----------------------------------------------------------------------
alloc.c (** system-dependent **)
----------------------------------------------------------------------

A. low-level allocation

C functions: malloc_warning_1(), malloc_warning(), memory_full(),
xmalloc(), xrealloc()

B. allocation of particular types

1. extents: EXTENT_BLOCK_SIZE, DUP_BLOCK_SIZE, struct extent_block,
struct dup_block, extent_block, extent_block_index, extent_free_list,
dup_block, dup_block_index, dup_free_list, init_extents(),
make_extent(), make_extent_replica()

2. floats: FLOAT_BLOCK_SIZE, struct float_block, float_block,
float_block_index, float_free_list, init_float(), free_float(),
make_float()

3. conses: CONS_BLOCK_SIZE, struct cons_block, cons_block,
cons_block_index, cons_free_list, init_cons(), free_cons()

Lisp: cons, list, make-list

4. vectors: all_vectors

Lisp: make-vector, vector, make-byte-code

5. symbols: SYMBOL_BLOCK_SIZE, struct symbol_block, symbol_block,
symbol_block_index, symbol_free_list, init_symbol()

Lisp: make-symbol

6. markers: MARKER_BLOCK_SIZE, struct marker_block, marker_block,
marker_block_index, marker_free_list, init_marker()

Lisp: make-marker

7. strings: PAD, ROUND_UP_STRING_SIZE(), STRING_FULL_SIZE(),
STRING_BLOCK_SIZE, STRING_CHARS_BLOCK_SIZE, struct string_chars,
SLOT_OFFSET(), CHARS_TO_STRING_CHAR(), struct string_chars_block, struct
string_block, string_block, string_block_index, string_free_list,
current_string_chars_block, first_string_chars_block,
NONRELOCATING_STRING_SIZE(), BIG_STRING_SIZE(), init_strings(),
make_string_internal(), allocate_string_chars(), make_uninit_string(),
make_string_from_buffer, make_string(), build_string()

Lisp: make-string

C. pure storage

C: tl, tf, ts, make_pure_string(), pure_cons(), make_pure_float(),
make_pure_vector()

Lisp: purecopy

D. garbage collection

C: gcprolist, NSTATICS, staticvec[], staticidx, staticpro(),
ARRAY_MARK_FLAG, BTL_before_Fgarbage_collect_stub(), total_conses,
total_markers, total_symbols, total_vector_size, total_string_size,
total_strings, total_short_strings, total_free_strings,
total_free_conses, total_free_markers, total_free_symbols,
total_free_flota, total_floats, total_free_events, total_events,
mark_one_extent(), mark_extents(), total_free_extents, total_extents,
total_free_dups, total_dups, current_pointer_shape, mark_object(),
mark_buffer(), mark_event(), mark_command_event_queue(), gc_sweep(),
compact_string_chars(), init_alloc_once(), init_alloc(), syms_of_alloc()

Lisp: garbage-collect

alloca.c (** system-dependent **)

Implementation of alloca(), which allocates memory space (originally off
the stack) that is automatically freed upon exit of the function.  This
version actually uses malloc(), and deallocates the space at some point
after the calling function has exited (upon each call to alloca() it
checks for stuff allocated in a lower stack frame)

----------------------------------------------------------------------
buffer.c
----------------------------------------------------------------------

Lots of stuff relating to buffers.  Code to create, destroy, select and
deselect buffers, return or change properties of a buffer, and do other
things that apply to a buffer as a whole.  No code to change the text in
a buffer or do low-level buffer-local-variable stuff.

current_buffer, all_buffers, buffer_defaults, buffer_local_flags,
buffer_local_symbols, check_protected_fields, nsberror(),
find_file_compare_truenames, file_file_use_truenames,
push_buffer_alist(), delete_from_buffer_alist(), buffer_count,
reset_buffer(), reset_buffer_local_variables(),
count_modified_buffers(), record_buffer(), internal_set_buffer(),
validate_region(), init_buffer_once(), init_buffer(), syms_of_buffer(),
keys_of_buffer()

Lisp: [V]buffer-defaults, [V]buffer-local-symbols, [V]buffer-alist,
[V]before-change-function, [V]after-change-function, [V]first-change-function,
[Q]fundamental-mode, [Q]mode-class, [Q]permanent-local,
[Q]protected_field, [QS]Fundamental, buffer-list, get-buffer,
get-file-buffer, get-buffer-create, generate-new-buffer, buffer-name,
buffer-file-name, buffer-local-variables, buffer-dedicated-screen,
set-buffer-dedicated-screen, buffer-modified-p, set-buffer-modified-p,
rename-buffer, other-buffer, buffer-disable-undo, buffer-enable-undo,
switch-to-buffer, pop-to-buffer, current-buffer, set-buffer,
barf-if-buffer-read-only, bury-buffer, erase-buffer,
kill-all-local-variables, region-fields, kill-buffer,
buffer-modified-tick

----------------------------------------------------------------------
bytecode.c
----------------------------------------------------------------------

Contains the function "byte-code", which is the byte-code interpreter.
It simulates a simple stack-based machine.

----------------------------------------------------------------------
callint.c
----------------------------------------------------------------------

Implements the functions call-interactively and prefix-numeric-value.
call-interactively scans through the function looking for an interactive
specification, and requests arguments for the user according to this
specification.  These arguments are then passed to the function.

C: num_input_chars, quotify_args(), callint_argfuns[], check_mark(),
syms_of_callint()

Lisp: [V]prefix-arg, [V]current-prefix-arg, [Q]minus,
[Q]call-interactively, [V]command-history, [V]command-debug-status,
[Q]command-debug-status, interactive, [V]current-mouse-event,
call-interactively, prefix-numeric-value

----------------------------------------------------------------------
callproc.c (** system-dependent **)
----------------------------------------------------------------------

Implements call-process and call-process-region, which synchronously
spawn a subprocess and place the output in a specified buffer.

C: synch_process_alive, synch_process_death, synch_process_retcode,
call_process_cleanup(), fork_error, report_fork_error(), child_setup(),
init_callproc(), syms_of_callproc()
 
Lisp: [V]exec-path, [V]exec-directory, [V]shell-file-name,
[V]process-environment, call-process, call-process-region, 

----------------------------------------------------------------------
casefiddle.c
----------------------------------------------------------------------

Implements Lisp functions that change the case of text.  Actual work is
done by casify_object() and casify_region().  They call macros UPCASE(),
DOWNCASE(), etc. defined in lisp.h.  These macros work by looking at the
case table for the buffer.  See also casetab.c.

C: enum case_action, casify_object(), casify_region(),
upcase_initials_region(), operate_on_word(), syms_of_casefiddle(),
keys_of_casefiddle()

Lisp: upcase, downcase, capitalize, upcase-region, downcase-region,
capitalize-region, upcase-word, downcase-word, capitalize-word

----------------------------------------------------------------------
casetab.c
----------------------------------------------------------------------

Implements functions that operate on case tables.  Case tables are
built-in buffer properties, stored in a struct buffer.  The
case-changing functions in casefiddle.c look at the case tables.

C: check_case_table(), set_case_table(), compute_trt_inverse(),
init_casetab_once(), syms_of_casetab()

Lisp: [Q]case-table-p, [V]ascii-downcase-table, [V]ascii-upcase-table,
[V]ascii-canon-table, [V]ascii-eqv-table, case-table-p,
current-case-table, standard-case-table, set-case-table,
set-standard-case-table

----------------------------------------------------------------------
cm.c (** system-dependent **)
----------------------------------------------------------------------

Provides an optimized, terminal-independent method for moving the cursor
to a specified location.  cmgoto() is the function that does this.

C: cost, evalcost(), cmputc(), addcol(), cmcostinit(), COST(), CMCOST(),
calccost(), cmgoto(), Wcm_clear(), Wcm_init()

----------------------------------------------------------------------
cmds.c
----------------------------------------------------------------------

Implements basic cursor motion and editing commands.
internal_self_insert() does the work of inserting a character, and has
special checks for overwrite mode, abbrevs (calls Fexpand_abbrev()),
auto-fill-mode (calls the current buffer's auto-fill function), and
paren-blinking (calls Vblink_paren_function).  Not pretty. [what about
zmacs_region_stays?]

C: zmacs_region_stays, internal_self_insert(), syms_of_cmds(),
keys_of_cmds()

Lisp: [Q]kill-forward-chars, [Q]kill-backward-chars,
[V]blink-paren-function, forward-char, backward-char, forward-line,
beginning-of-line, end-of-line, delete-char, delete-backward-char,
self-insert-command, newline
 
----------------------------------------------------------------------
crt0.c (** system-dependent **)
----------------------------------------------------------------------

This is a replacement for the standard system-dependent start-up routine
_start().  This replacement is necessary for VAX 4.2 but not for most
other machines.

----------------------------------------------------------------------
data.c
----------------------------------------------------------------------

Implements basic data manipulation routines for the Lisp interpreter
and some error-handling functions.  Includes code to handle buffer-local
variables.

1. errors

C: wrong_type_argument(), pure_write_error(), args_out_of_range(),
args_out_of_range_3(), arith_error()

2. integers

C: make_number(), sign_extend_temp, sign_extend_lisp_int()

3. data type predicates

Lisp: eq, null, consp, atom, listp, nlistp, symbolp, vectorp, stringp,
arrayp, sequencep, bufferp, markerp, integer-or-marker-p, subrp,
compiled-function-p, char-or-string-p, integerp, natnump, floatp,
numberp, number-or-marker-p, extentp

4. list manipulation

Lisp: car, car-safe, cdr, cdr-safe, setcar, setcdr

5. symbol manipulation

Lisp: boundp, fboundp, makunbound, fmakunbound, symbol-function,
symbol-plist, symbol-name, fset, setplist

6. symbol values

C: do_symval_forwarding(), store_symval_forwarding(),
swap_in_symval_forwarding(), default_value() 

Lisp: symbol-value, set, default-boundp, default-value, set-default,
setq-default, make-variable-buffer-local, make-local-variable,
kill-local-variable

8. vector manipulation

C: Farray_length()

Lisp: aref, aset

9. arithmetic

C: enum comparison, arithcompare(); enum arithop, arith_driver(),
float_arith_driver()

Lisp: =, <, >, <=, >=, /=, zerop; int-to-string, string-to-int; +, -, *,
/, %, max, min, logand, logior, logxor, ash, lsh, 1+, 1-, lognot

10. misc: syms_of_data(), init_data()

----------------------------------------------------------------------
dired.c (** system-dependent **)
----------------------------------------------------------------------

Includes routines to obtain file and directory information.

Lisp: [V]completion-ignored-extensions, [Q]completion-ignore-case,
directory-files, file-name-completion, file-attributes

C: file_name_completion(), file_name_completion_stat(), make_time(),
syms_of_dired()

----------------------------------------------------------------------
dispnew.c (** system-dependent **)
----------------------------------------------------------------------

1. general variables

C: screen_garbaged, display_completed, visible_bell, inverse_video,
baud_rate, cursor_in_echo_area, selected_screen, ophys_lines,
ophys_lines_length, termscript, Wcm, ospeed, in_display,
delayed_size_change, delayed_screen_height, delayed_screen_width

Lisp: [V]window-system, [V]window-system-version, [V]glyph-table,
[V]standard-display-table, [Q]cursor-in-echo-area

2.

C: make_screen_glyphs(), free_screen_glyphs(), remake_screen_glyphs(),
line_hash_code(), line_draw_cost(), cancel_line(),
clear_screen_records(), get_display_line(), safe_bcopy(),
rotate_vector(), scroll_screen_lines(), preserve_other_columns(),
cancel_my_columns(), direct_output_for_insert(),
direct_output_forward_char(), count_blanks(), count_match(),
update_line(), x_update_line(), update_screen(), scrolling(),
pixel_to_glyph_translation(), window_change_signal(),
change_screen_size(), bitch_at_user()

Lisp: open-termscript, send-string-to-terminal, ding

3. initialization

C: terminal_type, init_display(), syms_of_display()

Lisp: initialize-first-screen

----------------------------------------------------------------------
doc.c
----------------------------------------------------------------------

----------------------------------------------------------------------
doprnt.c
----------------------------------------------------------------------

----------------------------------------------------------------------
editfns.c
----------------------------------------------------------------------

----------------------------------------------------------------------
editorside.c (** system-dependent **)
----------------------------------------------------------------------

----------------------------------------------------------------------
elhash.c
----------------------------------------------------------------------

----------------------------------------------------------------------
emacs.c:
----------------------------------------------------------------------

This contains main().  main() is straightforward -- first it handles
some of the low-level options and traps some signals, then it proceeds to
initialization:

	1) initialize the various data structures
	2) intern the built-in symbols
	3) set the default key bindings
	4) miscellaneous (e.g. get the complete pathname of Emacs)
	5) enter the editing loop (Frecursive_edit)



----------------------------------------------------------------------
environ.c
----------------------------------------------------------------------


----------------------------------------------------------------------
eval.c
----------------------------------------------------------------------



----------------------------------------------------------------------
event-Xt.c
----------------------------------------------------------------------



----------------------------------------------------------------------
event-alloc.c
----------------------------------------------------------------------

This module contains routines that manage "struct Lisp_Event", which
holds the information for a single event.  These routines allocate,
de-allocate, and assist in garbage-collecting the structures.


C: event_free_list, struct event_block, event_blocks, event_block_index,
deinitialize_event(), get_more_events(), free_unmarked_events(),
prepare_to_gc_events(), syms_of_event_alloc()

Lisp: allocate-event, deallocate-event, copy-event

Not terribly interesting.  Events are managed just like cons cells.


----------------------------------------------------------------------
event-stream.c
----------------------------------------------------------------------


Lisp: [Q]undefined, [V]mouse-motion-handler, input-pending-p,
next-event, next-command-event, read-char, discard-input,
accept-process-output, dispatch-event, read-key-sequence

C: event_stream, struct command_builder, command_event_queue,
keystrokes, maybe_kbd_translate(), maybe_do_auto_save(), print_help(),
execute_help_form(), detect_input_pending(), enqueue_command_event(),
num_input_chars, next_event_internal(), deactivate_netconn(),
dispatch_event_internal(), syms_of_event_stream()

2. timeout

Lisp: sleep-for, sit-for, sleep-for-millisecs, add-timeout,
disable-timeout

C: lisp_number_to_milliseconds(), wait_delaying_user_input()

3. echo

C: echo_char_event(), echo_prompt(), echo_keystrokes, maybe_echo_keys(),
cancel_echoing()


----------------------------------------------------------------------
events.c
----------------------------------------------------------------------


4. commands

Lisp: [V]this-command-keys

C: command_builder_find_leaf(), find_leaf_unwind(), recent_keys_ring,
recent_keys_ring_index, this_command_keys_count,
reset_this_command_keys, reset_this_command_keys_fn(),
push_command_keys_vector(), push_recent_keys_vector(),
store_recent_key(), command_builder_push(),
command_builder_push_meta_hack(), self_insert_countdown,
compose_command(), dispatch_command_event_internal(),
dispatch_menu_event()


----------------------------------------------------------------------
extents.c
----------------------------------------------------------------------



----------------------------------------------------------------------
faces.c
----------------------------------------------------------------------


----------------------------------------------------------------------
fileio.c
----------------------------------------------------------------------


----------------------------------------------------------------------
filelock.c
----------------------------------------------------------------------


----------------------------------------------------------------------
filemode.c
----------------------------------------------------------------------



----------------------------------------------------------------------
floatfns.c
----------------------------------------------------------------------


----------------------------------------------------------------------
fns.c
----------------------------------------------------------------------



----------------------------------------------------------------------
free-hook.c
----------------------------------------------------------------------


----------------------------------------------------------------------
gmalloc.c
----------------------------------------------------------------------


----------------------------------------------------------------------
hash.c
----------------------------------------------------------------------


----------------------------------------------------------------------
indent.c
----------------------------------------------------------------------


----------------------------------------------------------------------
insdel.c
----------------------------------------------------------------------


----------------------------------------------------------------------
keyboard.c
----------------------------------------------------------------------

Lisp: [Q]disabled, [V]disabled-command-hook, [V]help-form,
[V]global-function-map, [V]last-command-event, [V]last-command-char,
[V]last-input-event, [V]last-input-char, [V]unread-command-event,
[V]last-command, [V]this-command, [V]last-input-time,
[V]mouse-left-hook, [V]mouse-enter-hook, [V]map-screen-hook,
[V]unmap-screen-hook, [V]mouse-motion-handler, [Q]self-insert-command,
[Q]forward-char, [Q]backward-char, [V]top-level,
[V]keyboard-translate-table, command-execute,
execute-extended-command, recent-keys, this-command-keys,
recursion-depth, open-dribble-file, suspend-emacs, set-input-mode 

C: waiting_for_input, immediate_quit, help_char, interrupt_char,
current_global_map, minibuf_level, echo_area_glyphs, command_loop_level,
num_input_keys, dribble, meta_key, input_available_clear_word,
interrupt_input, interrupts_deferred, flow_control, keyboard_init_hook,
polling_period, polling_for_input, poll_suppress_count,
input_poll_signal(), start_polling(), stop_polling(),
input_available_signal(), map_prompt(), stuff_buffered_input(),
set_waiting_for_input(), clear_waiting_for_input(), interrupt_signal(),
init_keyboard(), syms_of_keyboard(), keys_of_keyboard()  

recursive-edit (main loop)

C: recursive_edit_1(), recursive_edit_unwind(), cmd_error(),
command_loop(), command_loop_2(), top_level_2(), top_level_1(),
command_loop_1()

Lisp: recursive-edit, top-level, exit-recursive-edit, abort-recursive-edit

----------------------------------------------------------------------
keymap.c
----------------------------------------------------------------------


----------------------------------------------------------------------
lastfile.c
----------------------------------------------------------------------


----------------------------------------------------------------------
libsst.c
----------------------------------------------------------------------


----------------------------------------------------------------------
lread.c:
----------------------------------------------------------------------


1. Lisp I/O and parsing

Lisp: [Q]read-char, [Q]get-file-char, [Q]standard-input,
[Q]variable-documentation, [V]values, [V]standard-input,
[V]after-load-alist, [V]load-path, get-file-char, load, locate-file,
eval-buffer, eval-region, read, read-from-string, 

C: load_in_progress, instream, read_pure, read_from_string_index,
read_from_string_limit, READCHAR, UNREAD(), readchar(), unreadchar(),
load_unwind(), comlete_filename_p(), locate_file(), unreadpure(),
readevalloop(), read0(), read_buffer_size, read_buffer, read_escape(),
read1(), isfloat_string(), read_vector(), read_list(), init_read(),
syms_of_read()

2. obarray

Lisp: [V]obarray, intern, intern-soft, mapatoms 

C: initial_obarray, check_obarray(), intern(), oblookup(),
hash_string(), map_obarray(), mapatoms_1(), OBARRAY_SIZE, init_obarray()

3. defining Lisp symbols

C: defsubr(), defalias(), defvar_int(), defvar_bool(), defvar_lisp(),
defvar_lisp_nopro(), defvar_per_buffer() 


----------------------------------------------------------------------
macros.c
----------------------------------------------------------------------


----------------------------------------------------------------------
malloc.c
----------------------------------------------------------------------


----------------------------------------------------------------------
marker.c
----------------------------------------------------------------------


----------------------------------------------------------------------
menubar.c
----------------------------------------------------------------------


----------------------------------------------------------------------
menuitems.c
----------------------------------------------------------------------


----------------------------------------------------------------------
minibuf.c
----------------------------------------------------------------------


----------------------------------------------------------------------
mocklisp.c
----------------------------------------------------------------------


----------------------------------------------------------------------
play.c
----------------------------------------------------------------------


----------------------------------------------------------------------
pre-crt0.c
----------------------------------------------------------------------


----------------------------------------------------------------------
print.c
----------------------------------------------------------------------


----------------------------------------------------------------------
process.c
----------------------------------------------------------------------


----------------------------------------------------------------------
ralloc.c
----------------------------------------------------------------------


----------------------------------------------------------------------
realpath.c
----------------------------------------------------------------------


----------------------------------------------------------------------
regex.c
----------------------------------------------------------------------


----------------------------------------------------------------------
screen.c
----------------------------------------------------------------------

Routines dealing with "struct screen".  This structure contains
information about an Emacs "screen", which corresponds to a window in
the windowing system.  Each "screen" is divided up into Emacs's own
non-overlapping "windows", which the windowing system knows nothing
about.

Many of these routines call routines in xterm.c to actually change the
physical display.

----------------------------------------------------------------------
scroll.c
----------------------------------------------------------------------


----------------------------------------------------------------------
search.c
----------------------------------------------------------------------


----------------------------------------------------------------------
sunOS-fix.c
----------------------------------------------------------------------


----------------------------------------------------------------------
sunfns.c
----------------------------------------------------------------------


----------------------------------------------------------------------
syntax.c
----------------------------------------------------------------------


----------------------------------------------------------------------
sysdep.c
----------------------------------------------------------------------


----------------------------------------------------------------------
term.c
----------------------------------------------------------------------


----------------------------------------------------------------------
termcap.c
----------------------------------------------------------------------


----------------------------------------------------------------------
terminfo.c
----------------------------------------------------------------------


----------------------------------------------------------------------
tparam.c
----------------------------------------------------------------------


----------------------------------------------------------------------
undo.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexconvex.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexec.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexelf.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexencap.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexenix.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexhp9k800.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexmips.c
----------------------------------------------------------------------


----------------------------------------------------------------------
unexsunos4.c
----------------------------------------------------------------------


----------------------------------------------------------------------
vm-limit.c
----------------------------------------------------------------------


----------------------------------------------------------------------
vms-pp.c
----------------------------------------------------------------------


----------------------------------------------------------------------
vmsfns.c
----------------------------------------------------------------------


----------------------------------------------------------------------
vmsmap.c
----------------------------------------------------------------------


----------------------------------------------------------------------
vmsproc.c
----------------------------------------------------------------------


----------------------------------------------------------------------
window.c
----------------------------------------------------------------------


----------------------------------------------------------------------
xdisp.c (** system-dependent **)
----------------------------------------------------------------------

1. variables

C: noninteractive_need_newline, this_line_bufpos, this_line_endpos,
this_line_vpos, this_line_start_hpos, this_line_buffer,
previous_echo_glyphs, last_arrow_position, last_arrow_string,
overlay_arrow_seen, scroll_step, blank_end_of_window, buffer_shared,
cursor_vpos, cursor_hpos, debug_end_pos, mode_line_inverse_video,
minibuf_prompt, minibuf_prompt_width, minibuf_prompt_pix_width,
echo_area_buffer, echo_area_glyphs, redraw_mode_line, beg_unchanged,
end_unchanged, unchanged_modified, clip_changed,
windows_or_buffers_changed

Lisp: [V]global-mode-string, [V]overlay-arrow-position,
[V]overlay-arrow-string, [V]minibuffer-list

2.

C: redraw_screen(), echo_area_display(), message_buf, message(),
redisplay(), redisplay_preserving_echo_area(),
mark_window_display_accurate(), redisplay_windows(), redisplay_window(),
initialize_first_screen(), try_window(), try_window_id(), copy_rope()

Lisp: redraw-display

3.

C: char_glyphs(), measure_glyphs, GLYPH_SET_VALUE(), glyphs_from_char(),
last_buffer, last_screen, last_buffer_modiff, last_buffer_facechange,
last_buffer_extfrag, last_extfrag_from_pos, last_extfrag_to_pos,
last_extfrag_face, displayed_glyphs, update_cache(),
glyphs_from_bufpos(), new_run(), glyph_pixel_width(), stuff_glyph(),
install_first_runs(), append_run(), append_glyph(), [it goes on]


----------------------------------------------------------------------
xfns.c
----------------------------------------------------------------------


----------------------------------------------------------------------
xselect.c
----------------------------------------------------------------------


----------------------------------------------------------------------
xterm.c [2729 lines] [** system-dependent **]
----------------------------------------------------------------------

This module contains functions that interface between Emacs and the
X display routines.

----------------------------------------------------------------------
xutils.c [158 lines]
----------------------------------------------------------------------



#fff#		config.h	free-hook.c	ndir.h		terminfo.c
COPYING		config.h-dist	getpagesize.h	param.h		termopts.h
ColumnWidget.c	connmemory.h	glyfs.h		paths.h		tparam.c
ColumnWidget.h	crt0.c		gmalloc.c	paths.h-dist	uaf.h
ColumnWidgetP.h	data.c		gnu.h		play.c		undo.c
EmacsShell.c	dir.h		hash.c		pre-crt0.c	unexconvex.c
EmacsShell.h	dired.c		hash.h		print.c		unexec.c
EmacsShellP.h	dispextern.h	indent.c	process.c	unexelf.c
FILES		dispnew.c	indent.h	process.h	unexencap.c
Makefile	disptab.h	insdel.c	puresize.h	unexenix.c
README		doc.c		ioctl.h		pwd.h		unexhp9k800.c
ScreenWidget.c	doprnt.c	keyboard.c	ralloc.c	unexmips.c
ScreenWidget.h	editfns.c	keymap.c	realpath.c	unexsunos4.c
ScreenWidgetP.h	editorside.c	keymap.h	regex.c		vlimit.h
abbrev.c	editorside.h	lastfile.c	regex.h		vm-limit.c
acldef.h	elhash.c	lemacs*		s/		vms-pp.c
alloc.c		emacs.c		libsst.c	screen.c	vmsfns.c
alloca.c	environ.c	libsst.h	screen.h	vmsmap.c
backtrace.h	eval.c		line.h		scroll.c	vmspaths.h
bitmaps.h	event-Xt.c	lisp.h		search.c	vmsproc.c
blockio.h	event-alloc.c	lread.c		sink.h		vmsproc.h
buffer.c	event-stream.c	lwlib/		sink11.h	window.c
buffer.h	events.c	m/		sink11mask.h	window.h
bufslots.h	events.h	m-delta.h	sinkmask.h	x11term.h
bytecode.c	extents-data.h	macros.c	sunOS-fix.c	xdisp.c
callint.c	extents.c	macros.h	sunfns.c	xfns.c
callproc.c	extents.h	malloc.c	syntax.c	xselect.c
casefiddle.c	faces.c		marker.c	syntax.h	xterm.c
casetab.c	faces.h		mem_limits.h	sysdep.c	xterm.h
chpdef.h	fileio.c	menubar.c	tags		xutils.c
cm.c		filelock.c	menuitems.c	term.c		ymakefile
cm.h		filemode.c	menuitems.h	termcap.c
cmds.c		floatfns.c	minibuf.c	termchar.h
commands.h	fns.c		mocklisp.c	termhooks.h

     323    1106    9924 ColumnWidget.c
     497    1507   14727 EmacsShell.c
     603    1850   18835 ScreenWidget.c
     559    2134   17245 abbrev.c
    2173    6770   55031 alloc.c
     191     813    5217 alloca.c
    1749    7269   57759 buffer.c
    1160    3129   22649 bytecode.c
     591    2436   17504 callint.c
     581    2069   15289 callproc.c
     268    1029    7432 casefiddle.c
     251     952    7406 casetab.c
     414    1651   10042 cm.c
     373    1351   10019 cmds.c
     534    2006   13346 crt0.c
    1976    6797   53950 data.c
     502    1936   14357 dired.c
    2388    8358   67503 dispnew.c
     465    1864   13021 doc.c
     137     558    3635 doprnt.c
    1363    5380   38484 editfns.c
    4143   11784  114483 editorside.c
     441    1244   11139 elhash.c
    1126    3733   27718 emacs.c
     316    1133    7780 environ.c
    2340    8342   62039 eval.c
    1607    5986   51340 event-Xt.c
     266    1094    8091 event-alloc.c
    1790    6902   55205 event-stream.c
     748    2997   24085 events.c
    2926   10080   85426 extents.c
     974    3196   25777 faces.c
    3117   12253   84469 fileio.c
     401    1400   10011 filelock.c
     199     747    4685 filemode.c
     551    1801   12180 floatfns.c
    1854    6656   46069 fns.c
     606    1743   13957 free-hook.c
    1154    4849   34011 gmalloc.c
     438    1295   10260 hash.c
     898    3406   25386 indent.c
     642    2208   15464 insdel.c
    1271    4773   35191 keyboard.c
    2828   11260   87787 keymap.c
      38     255    1464 lastfile.c
     489    1810   10622 libsst.c
    1578    5464   39596 lread.c
     343    1177    9735 macros.c
     895    4257   25043 malloc.c
     312    1084    7945 marker.c
     941    3576   28123 menubar.c
      92     310    2368 menuitems.c
    1391    5090   42280 minibuf.c
     243     850    6078 mocklisp.c
     241     745    5162 play.c
       9      70     398 pre-crt0.c
    1157    3873   31600 print.c
    2439    8866   65634 process.c
     419    1359    9626 ralloc.c
     150     596    4512 realpath.c
    1715    6664   44455 regex.c
    1185    3743   30745 screen.c
     618    2681   19707 scroll.c
    1321    5852   38557 search.c
      20      97     569 sunOS-fix.c
     501    1770   13955 sunfns.c
    1255    4553   33716 syntax.c
    3742   12786   86731 sysdep.c
    1476    4931   39070 term.c
     672    2365   14167 termcap.c
      50     274    1717 terminfo.c
     275    1133    6768 tparam.c
     301    1142    8200 undo.c
     809    3347   21994 unexconvex.c
     855    3498   23421 unexec.c
     625    2733   22706 unexelf.c
     116     375    3198 unexencap.c
     262    1086    7723 unexenix.c
     293    1215    9003 unexhp9k800.c
     290    1065    8585 unexmips.c
     294    1263    7858 unexsunos4.c
     126     439    3000 vm-limit.c
     242    1014    7117 vms-pp.c
     960    3610   26453 vmsfns.c
     224     893    6013 vmsmap.c
     786    2399   17633 vmsproc.c
    2734    9684   78257 window.c
    3860   13490  111868 xdisp.c
    2228    7365   63070 xfns.c
    1849    7090   57502 xselect.c
    2729    7694   73831 xterm.c
     158     548    4387 xutils.c
   91042  326028 2508090 total
