This commit was generated by cvs2svn to compensate for changes in r1479,
authortomo <tomo>
Tue, 6 Jun 2000 04:18:26 +0000 (04:18 +0000)
committertomo <tomo>
Tue, 6 Jun 2000 04:18:26 +0000 (04:18 +0000)
which included commits to RCS files with non-trunk default branches.

82 files changed:
etc/Emacs.ad
lib-src/ChangeLog
lib-src/config.values.in
lib-src/make-docfile.c
lisp/faces.el
lisp/font-lock.el
lisp/glyphs.el
lisp/keydefs.el
lisp/loadhist.el
lisp/menubar-items.el
lisp/minibuf.el
lisp/objects.el
lisp/packages.el
lisp/process.el
lisp/simple.el
lisp/specifier.el
lisp/toolbar.el
lwlib/ChangeLog
man/ChangeLog
man/internals/internals.texi
man/lispref/compile.texi
man/lispref/databases.texi
man/lispref/display.texi
man/lispref/extents.texi
man/lispref/faces.texi
man/lispref/glyphs.texi
man/lispref/modes.texi
man/lispref/specifiers.texi
man/lispref/toolbar.texi
man/xemacs/basic.texi
man/xemacs/entering.texi
man/xemacs/mini.texi
man/xemacs/startup.texi
nt/ChangeLog
src/callproc.c
src/cmdloop.c
src/console-msw.c
src/console-msw.h
src/device-msw.c
src/device.h
src/eval.c
src/event-Xt.c
src/event-msw.c
src/event-stream.c
src/frame-msw.c
src/frame.h
src/frameslots.h
src/general.c
src/glyphs-msw.c
src/glyphs-msw.h
src/glyphs-widget.c
src/glyphs-x.c
src/glyphs-x.h
src/glyphs.h
src/gui-msw.c
src/gui-x.c
src/gui.c
src/nt.c
src/nt.h
src/ntheap.c
src/ntheap.h
src/ntplay.c
src/ntproc.c
src/objects.c
src/paths.h.in
src/print.c
src/process-nt.c
src/process.c
src/rangetab.c
src/s/cygwin32.h
src/scrollbar.c
src/specifier.c
src/specifier.h
src/toolbar-msw.c
src/toolbar.c
src/unexelf.c
src/unexnt.c
src/window.c
src/window.h
tests/ChangeLog
tests/glyph-test.el
version.sh

index 39ac03a..65773f1 100644 (file)
@@ -267,7 +267,7 @@ Ctrl<KeyPress>m: ArmAndActivate()\n
 ! Native Widget translations
 ! ======================= 
 Emacs*Text*translations: #override\n\
-       <Btn1Down>:     widget-focus-in()\n
+       <Btn1Down>:     widget-focus-in() select-start()\n
 
 ! XIM input method style 
 ! ======================= 
index 4204c58..0ce9a98 100644 (file)
@@ -1,3 +1,16 @@
+2000-05-28  Martin Buchholz <martin@xemacs.org>
+
+       * XEmacs 21.2.34 is released.
+
+2000-05-11  Ben Wing  <ben@xemacs.org>
+
+       * i.c (get_command): fix unused var warning.
+       
+       * make-docfile.c (MDGET):
+       * make-docfile.c (read_c_string):
+       rewrite and reindent -- handle closing doc string comment that's
+       not at beg of line.
+
 2000-05-01  Martin Buchholz <martin@xemacs.org>
 
        * XEmacs 21.2.33 is released.
index c3e3de9..e71f67b 100644 (file)
@@ -45,8 +45,6 @@ LIBS "@LIBS@"
 LISPDIR "@LISPDIR@"
 LISPDIR_USER_DEFINED "@LISPDIR_USER_DEFINED@"
 LN_S "@LN_S@"
-LOCKDIR "@LOCKDIR@"
-LOCKDIR_USER_DEFINED "@LOCKDIR_USER_DEFINED@"
 MAKE_SUBDIR "@MAKE_SUBDIR@"
 MODULEDIR "@MODULEDIR@"
 MODULEDIR_USER_DEFINED "@MODULEDIR_USER_DEFINED@"
@@ -116,7 +114,6 @@ libexecdir "@libexecdir@"
 libs_xauth "@libs_xauth@"
 lispdir "@lispdir@"
 localstatedir "@localstatedir@"
-lockdir "@lockdir@"
 lwlib_objs "@lwlib_objs@"
 machfile "@machfile@"
 mandir "@mandir@"
index 141287a..d971a11 100644 (file)
@@ -303,48 +303,59 @@ char buf[128];
  Convert escape sequences \n and \t to newline and tab;
  discard \ followed by newline.  */
 
+#define MDGET do { prevc = c; c = getc (infile); } while (0)
 static int
 read_c_string (FILE *infile, int printflag, int c_docstring)
 {
-  register int c;
+  register int prevc = 0, c = 0;
   char *p = buf;
   int start = -1;
 
-  c = getc (infile);
+  MDGET;
   while (c != EOF)
     {
       while ((c_docstring || c != '"') && c != EOF)
        {
-         if (start)
+         if (c == '*')
            {
-             if (c == '*')
+             int cc = getc (infile);
+             if (cc == '/')
                {
-                 int cc = getc (infile);
-                 if (cc == '/')
-                   break;
-                 else
-                   ungetc (cc, infile);
+                 if (prevc != '\n')
+                   {
+                     if (printflag > 0)
+                       {
+                         if (ellcc)
+                           fprintf (outfile, "\\n\\");
+                         putc ('\n', outfile);
+                       }
+                     else if (printflag < 0)
+                       *p++ = '\n';
+                   }
+                 break;
                }
+             else
+               ungetc (cc, infile);
+           }
 
-             if (start != -1)
+         if (start == 1)
+           {
+             if (printflag > 0)
                {
-                 if (printflag > 0)
-            {
-              if (ellcc)
-                fprintf (outfile, "\\n\\");
-              putc ('\n', outfile);
-            }
-                 else if (printflag < 0)
-                   *p++ = '\n';
+                 if (ellcc)
+                   fprintf (outfile, "\\n\\");
+                 putc ('\n', outfile);
                }
+             else if (printflag < 0)
+               *p++ = '\n';
            }
 
          if (c == '\\')
            {
-             c = getc (infile);
+             MDGET;
              if (c == '\n')
                {
-                 c = getc (infile);
+                 MDGET;
                  start = 1;
                  continue;
                }
@@ -358,32 +369,36 @@ read_c_string (FILE *infile, int printflag, int c_docstring)
          else
            {
              start = 0;
-             if (printflag > 0) {
-                if (ellcc && c == '"')
-                  putc ('\\', outfile);
-               putc (c, outfile);
-              }
+             if (printflag > 0)
+               {
+                 if (ellcc && c == '"')
+                   putc ('\\', outfile);
+                 putc (c, outfile);
+               }
              else if (printflag < 0)
                *p++ = c;
            }
-         c = getc (infile);
+         MDGET;
        }
       /* look for continuation of string */
       if (Current_file_type == c_file)
        {
-         while (isspace (c = getc (infile)))
-           ;
+         do
+           {
+             MDGET;
+           }
+         while (isspace (c));
          if (c != '"')
            break;
        }
       else
        {
-         c = getc (infile);
+         MDGET;
          if (c != '"')
            break;
          /* If we had a "", concatenate the two strings.  */
        }
-      c = getc (infile);
+      MDGET;
     }
 
   if (printflag < 0)
index 616c510..d149cb0 100644 (file)
@@ -292,41 +292,41 @@ If PROPERTY is not a built-in property, then this function will
 The following symbols have predefined meanings:
 
  foreground         The foreground color of the face.
-                    For valid instantiators, see `color-specifier-p'.
+                    For valid instantiators, see `make-color-specifier'.
 
  background         The background color of the face.
-                    For valid instantiators, see `color-specifier-p'.
+                    For valid instantiators, see `make-color-specifier'.
 
  font               The font used to display text covered by this face.
-                    For valid instantiators, see `font-specifier-p'.
+                    For valid instantiators, see `make-font-specifier'.
 
  display-table      The display table of the face.
                     This should be a vector of 256 elements.
 
  background-pixmap  The pixmap displayed in the background of the face.
                     Only used by faces on X devices.
-                    For valid instantiators, see `image-specifier-p'.
+                    For valid instantiators, see `make-image-specifier'.
 
  underline          Underline all text covered by this face.
-                    For valid instantiators, see `face-boolean-specifier-p'.
+                    For valid instantiators, see `make-face-boolean-specifier'.
 
  strikethru         Draw a line through all text covered by this face.
-                    For valid instantiators, see `face-boolean-specifier-p'.
+                    For valid instantiators, see `make-face-boolean-specifier'.
 
  highlight          Highlight all text covered by this face.
                     Only used by faces on TTY devices.
-                    For valid instantiators, see `face-boolean-specifier-p'.
+                    For valid instantiators, see `make-face-boolean-specifier'.
 
  dim                Dim all text covered by this face.
-                    For valid instantiators, see `face-boolean-specifier-p'.
+                    For valid instantiators, see `make-face-boolean-specifier'.
 
  blinking           Blink all text covered by this face.
                     Only used by faces on TTY devices.
-                    For valid instantiators, see `face-boolean-specifier-p'.
+                    For valid instantiators, see `make-face-boolean-specifier'.
 
  reverse            Reverse the foreground and background colors.
                     Only used by faces on TTY devices.
-                    For valid instantiators, see `face-boolean-specifier-p'.
+                    For valid instantiators, see `make-face-boolean-specifier'.
 
  doc-string         Description of what the face's normal use is.
                     NOTE: This is not a specifier, unlike all
@@ -433,7 +433,7 @@ See `face-property-instance' for more information."
 
 FACE may be either a face object or a symbol representing a face.
 
-FONT should be an instantiator (see `font-specifier-p'), a list of
+FONT should be an instantiator (see `make-font-specifier'), a list of
   instantiators, an alist of specifications (each mapping a
   locale to an instantiator list), or a font specifier object.
 
@@ -490,7 +490,7 @@ See `face-property-instance' for more information."
 
 FACE may be either a face object or a symbol representing a face.
 
-COLOR should be an instantiator (see `color-specifier-p'), a list of
+COLOR should be an instantiator (see `make-color-specifier'), a list of
   instantiators, an alist of specifications (each mapping a locale to
   an instantiator list), or a color specifier object.
 
@@ -547,7 +547,7 @@ See `face-property-instance' for more information."
 
 FACE may be either a face object or a symbol representing a face.
 
-COLOR should be an instantiator (see `color-specifier-p'), a list of
+COLOR should be an instantiator (see `make-color-specifier'), a list of
   instantiators, an alist of specifications (each mapping a locale to
   an instantiator list), or a color specifier object.
 
@@ -595,7 +595,7 @@ This property is only used on window system devices.
 
 FACE may be either a face object or a symbol representing a face.
 
-PIXMAP should be an instantiator (see `image-specifier-p'), a list
+PIXMAP should be an instantiator (see `make-image-specifier'), a list
   of instantiators, an alist of specifications (each mapping a locale
   to an instantiator list), or an image specifier object.
 
@@ -652,7 +652,7 @@ See `face-property-instance' for the semantics of the DOMAIN argument."
                                  how-to-add)
   "Change the underline property of FACE to UNDERLINE-P.
 UNDERLINE-P is normally a face-boolean instantiator; see
- `face-boolean-specifier-p'.
+ `make-face-boolean-specifier'.
 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
  HOW-TO-ADD arguments."
   (interactive (face-interactive "underline-p" "underlined"))
@@ -667,7 +667,7 @@ See `face-property-instance' for the semantics of the DOMAIN argument."
                                  how-to-add)
   "Change whether FACE is strikethru-d (i.e. struck through) in LOCALE.
 STRIKETHRU-P is normally a face-boolean instantiator; see
- `face-boolean-specifier-p'.
+ `make-face-boolean-specifier'.
 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
  HOW-TO-ADD arguments."
   (interactive (face-interactive "strikethru-p" "strikethru-d"))
@@ -682,7 +682,7 @@ See `face-property-instance' for the semantics of the DOMAIN argument."
                                  how-to-add)
   "Change whether FACE is highlighted in LOCALE (TTY locales only).
 HIGHLIGHT-P is normally a face-boolean instantiator; see
- `face-boolean-specifier-p'.
+ `make-face-boolean-specifier'.
 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
  HOW-TO-ADD arguments."
   (interactive (face-interactive "highlight-p" "highlighted"))
@@ -696,7 +696,7 @@ See `face-property-instance' for the semantics of the DOMAIN argument."
 (defun set-face-dim-p (face dim-p &optional locale tag-set how-to-add)
   "Change whether FACE is dimmed in LOCALE.
 DIM-P is normally a face-boolean instantiator; see
- `face-boolean-specifier-p'.
+ `make-face-boolean-specifier'.
 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
  HOW-TO-ADD arguments."
   (interactive (face-interactive "dim-p" "dimmed"))
@@ -711,7 +711,7 @@ See `face-property-instance' for the semantics of the DOMAIN argument."
                                 how-to-add)
   "Change whether FACE is blinking in LOCALE (TTY locales only).
 BLINKING-P is normally a face-boolean instantiator; see
- `face-boolean-specifier-p'.
+ `make-face-boolean-specifier'.
 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
  HOW-TO-ADD arguments."
   (interactive (face-interactive "blinking-p" "blinking"))
@@ -725,7 +725,7 @@ See `face-property-instance' for the semantics of the DOMAIN argument."
 (defun set-face-reverse-p (face reverse-p &optional locale tag-set how-to-add)
   "Change whether FACE is reversed in LOCALE (TTY locales only).
 REVERSE-P is normally a face-boolean instantiator; see
- `face-boolean-specifier-p'.
+ `make-face-boolean-specifier'.
 See `set-face-property' for the semantics of the LOCALE, TAG-SET, and
  HOW-TO-ADD arguments."
   (interactive (face-interactive "reverse-p" "reversed"))
index 3969793..ce98ccc 100644 (file)
@@ -178,8 +178,8 @@ The size is measured in characters.  This affects `font-lock-fontify-region'
 but not `font-lock-fontify-buffer'. (In other words, when you first visit
 a file and it gets fontified, you will see status messages no matter what
 size the file is.  However, if you do something else like paste a
-chunk of text or revert a buffer, you will see status messages only if the
-changed region is large enough.)
+chunk of text, you will see status messages only if the changed region is
+large enough.)
 
 Note that setting `font-lock-verbose' to nil disables the status
 messages entirely."
@@ -318,95 +318,123 @@ megabyte for buffers in `rmail-mode', and size is irrelevant otherwise."
 
 ;;;###autoload
 (defvar font-lock-keywords nil
-  "A list of the keywords to highlight.
-Each element should be of the form:
-
- MATCHER
- (MATCHER . MATCH)
- (MATCHER . FACENAME)
- (MATCHER . HIGHLIGHT)
- (MATCHER HIGHLIGHT ...)
- (eval . FORM)
-
-where HIGHLIGHT should be either MATCH-HIGHLIGHT or MATCH-ANCHORED.
-
-FORM is an expression, whose value should be a keyword element,
-evaluated when the keyword is (first) used in a buffer.  This feature
-can be used to provide a keyword that can only be generated when Font
-Lock mode is actually turned on.
+  "A list defining the keywords for `font-lock-mode' to highlight.
+
+ FONT-LOCK-KEYWORDS := List of FONT-LOCK-FORM's.
+
+ FONT-LOCK-FORM     :== MATCHER
+                      | (MATCHER . MATCH)
+                      | (MATCHER . FACE-FORM)
+                      | (MATCHER . HIGHLIGHT)
+                      | (MATCHER HIGHLIGHT ...)
+                      | (eval . FORM)
+
+ MATCHER            :== A string containing a regexp.
+                      | A variable containing a regexp to search for.
+                      | A function to call to make the search.
+                        It is called with one arg, the limit of the search,
+                        and should leave MATCH results in the XEmacs global
+                        match data.
+
+ MATCH              :== An integer match subexpression number from MATCHER.
+
+ FACE-FORM           :== The symbol naming a defined face.
+                      | Expression whos value is the face name to use.  If you
+                        want FACE-FORM to be a symbol that evaluates to a face,
+                        use a form like \"(progn sym)\".
+
+ HIGHLIGHT          :== MATCH-HIGHLIGHT
+                      | MATCH-ANCHORED
+
+ FORM               :== Expression returning a FONT-LOCK-FORM, evaluated when
+                        the FONT-LOCK-FORM is first used in a buffer.  This
+                        feature can be used to provide a FONT-LOCK-FORM that
+                        can only be generated when Font Lock mode is actually
+                        turned on.
+
+ MATCH-HIGHLIGHT    :== (MATCH FACE-FORM OVERRIDE LAXMATCH)
+
+ OVERRIDE           :== t        - overwrite existing fontification
+                      | 'keep    - only parts not already fontified are
+                                   highlighted.
+                      | 'prepend - merge faces, this fontification has
+                                   precedence over existing
+                      | 'append  - merge faces, existing fontification has
+                                   precedence over
+                                   this face.
+
+ LAXMATCH           :== If non-nil, no error is signalled if there is no MATCH
+                        in MATCHER.
+
+ MATCH-ANCHORED     :== (ANCHOR-MATCHER PRE-MATCH-FORM \\
+                                          POST-MATCH-FORM MATCH-HIGHLIGHT ...)
+
+ ANCHOR-MATCHER     :== Like a MATCHER, except that the limit of the search
+                        defaults to the end of the line after PRE-MATCH-FORM
+                        is evaluated.  However, if PRE-MATCH-FORM returns a
+                        position greater than the end of the line, that
+                        position is used as the limit of the search.  It is
+                        generally a bad idea to return a position greater than
+                        the end of the line, i.e., cause the ANCHOR-MATCHER
+                        search to span lines.
+
+ PRE-MATCH-FORM     :== Evaluated before the ANCHOR-MATCHER is used, therefore
+                        can be used to initialize before, ANCHOR-MATCHER is
+                        used.  Typically, PRE-MATCH-FORM is used to move to
+                        some position relative to the original MATCHER, before
+                        starting with the ANCHOR-MATCHER.
+
+ POST-MATCH-FORM    :== Like PRE-MATCH-FORM, but used to clean up after the
+                        ANCHOR-MATCHER.  It might be used to move, before
+                        resuming with MATCH-ANCHORED's parent's MATCHER.
+
+For example, an element of the first form highlights (if not already highlighted):
+
+  \"\\\\<foo\\\\>\"                    Discrete occurrences of \"foo\" in the value
+                                 of the variable `font-lock-keyword-face'.
+
+  (\"fu\\\\(bar\\\\)\" . 1)            Substring \"bar\" within all occurrences of
+                                 \"fubar\" in the value of
+                                 `font-lock-keyword-face'.
+
+  (\"fubar\" . fubar-face)         Occurrences of \"fubar\" in the value of
+                                 `fubar-face'.
+
+  (\"foo\\\\|bar\" 0 foo-bar-face t) Occurrences of either \"foo\" or \"bar\" in the
+                                 value of `foo-bar-face', even if already
+                                 highlighted.
+
+  (fubar-match 1 fubar-face)     The first subexpression within all
+                                 occurrences of whatever the function
+                                 `fubar-match' finds and matches in the value
+                                 of `fubar-face'.
+
+  (\"\\\\<anchor\\\\>\" (0 anchor-face) (\"\\\\<item\\\\>\" nil nil (0 item-face)))
+   -------------- ---------------  ------------ --- --- -------------
+       |            |               |            |   |          |
+   MATCHER          |         ANCHOR-MATCHER     |   +------+ MATCH-HIGHLIGHT
+             MATCH-HIGHLIGHT                 PRE-MATCH-FORM |
+                                                           POST-MATCH-FORM
+
+  Discrete occurrences of \"anchor\" in the value of `anchor-face', and
+  subsequent discrete occurrences of \"item\" (on the same line) in the value
+  of `item-face'.  (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil.
+  Therefore \"item\" is initially searched for starting from the end of the
+  match of \"anchor\", and searching for subsequent instance of \"anchor\"
+  resumes from where searching for \"item\" concluded.)
 
 For highlighting single items, typically only MATCH-HIGHLIGHT is required.
-However, if an item or (typically) items is to be highlighted following the
-instance of another item (the anchor) then MATCH-ANCHORED may be required.
-
-MATCH-HIGHLIGHT should be of the form:
-
- (MATCH FACENAME OVERRIDE LAXMATCH)
-
-Where MATCHER can be either the regexp to search for, a variable
-containing the regexp to search for, or the function to call to make
-the search (called with one argument, the limit of the search).  MATCH
-is the subexpression of MATCHER to be highlighted.  FACENAME is either
-a symbol naming a face, or an expression whose value is the face name
-to use.  If you want FACENAME to be a symbol that evaluates to a face,
-use a form like \"(progn sym)\".
-
-OVERRIDE and LAXMATCH are flags.  If OVERRIDE is t, existing fontification may
-be overwritten.  If `keep', only parts not already fontified are highlighted.
-If `prepend' or `append', existing fontification is merged with the new, in
-which the new or existing fontification, respectively, takes precedence.
-If LAXMATCH is non-nil, no error is signalled if there is no MATCH in MATCHER.
-
-For example, an element of the form highlights (if not already highlighted):
-
- \"\\\\\\=<foo\\\\\\=>\"               Discrete occurrences of \"foo\" in the value of the
-                       variable `font-lock-keyword-face'.
- (\"fu\\\\(bar\\\\)\" . 1)     Substring \"bar\" within all occurrences of \"fubar\" in
-                       the value of `font-lock-keyword-face'.
- (\"fubar\" . fubar-face)      Occurrences of \"fubar\" in the value of `fubar-face'.
- (\"foo\\\\|bar\" 0 foo-bar-face t)
-                       Occurrences of either \"foo\" or \"bar\" in the value
-                       of `foo-bar-face', even if already highlighted.
-
-MATCH-ANCHORED should be of the form:
-
- (MATCHER PRE-MATCH-FORM POST-MATCH-FORM MATCH-HIGHLIGHT ...)
-
-Where MATCHER is as for MATCH-HIGHLIGHT with one exception; see below.
-PRE-MATCH-FORM and POST-MATCH-FORM are evaluated before the first, and after
-the last, instance MATCH-ANCHORED's MATCHER is used.  Therefore they can be
-used to initialize before, and cleanup after, MATCHER is used.  Typically,
-PRE-MATCH-FORM is used to move to some position relative to the original
-MATCHER, before starting with MATCH-ANCHORED's MATCHER.  POST-MATCH-FORM might
-be used to move, before resuming with MATCH-ANCHORED's parent's MATCHER.
-
-For example, an element of the form highlights (if not already highlighted):
-
- (\"\\\\\\=<anchor\\\\\\=>\" (0 anchor-face) (\"\\\\\\=<item\\\\\\=>\" nil nil (0 item-face)))
-
- Discrete occurrences of \"anchor\" in the value of `anchor-face', and subsequent
- discrete occurrences of \"item\" (on the same line) in the value of `item-face'.
- (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil.  Therefore \"item\" is
- initially searched for starting from the end of the match of \"anchor\", and
- searching for subsequent instance of \"anchor\" resumes from where searching
- for \"item\" concluded.)
-
-The above-mentioned exception is as follows.  The limit of the MATCHER search
-defaults to the end of the line after PRE-MATCH-FORM is evaluated.
-However, if PRE-MATCH-FORM returns a position greater than the position after
-PRE-MATCH-FORM is evaluated, that position is used as the limit of the search.
-It is generally a bad idea to return a position greater than the end of the
-line, i.e., cause the MATCHER search to span lines.
-
-Note that the MATCH-ANCHORED feature is experimental; in the future, we may
-replace it with other ways of providing this functionality.
+However, if an item or (typically) several items are to be highlighted
+following the instance of another item (the anchor) then MATCH-ANCHORED may be
+required.
 
 These regular expressions should not match text which spans lines.  While
-\\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating
-when you edit the buffer does not, since it considers text one line at a time.
+\\[font-lock-fontify-buffer] handles multi-line patterns correctly, updating when you
+edit the buffer does not, since it considers text one line at a time.
 
-Be very careful composing regexps for this list;
-the wrong pattern can dramatically slow things down!")
+Be very careful composing regexps for this list; the wrong pattern can
+dramatically slow things down!
+")
 ;;;###autoload
 (make-variable-buffer-local 'font-lock-keywords)
 
@@ -829,11 +857,6 @@ See the variable `font-lock-keywords' for customization."
     (set (make-local-variable 'font-lock-mode) on-p)
     (cond (on-p
           (font-lock-set-defaults-1)
-          (make-local-hook 'before-revert-hook)
-          (make-local-hook 'after-revert-hook)
-          ;; If buffer is reverted, must clean up the state.
-          (add-hook 'before-revert-hook 'font-lock-revert-setup nil t)
-          (add-hook 'after-revert-hook 'font-lock-revert-cleanup nil t)
           (run-hooks 'font-lock-mode-hook)
           (cond (font-lock-fontified
                  nil)
@@ -845,13 +868,9 @@ See the variable `font-lock-keywords' for customization."
                             (buffer-name)))))
          (font-lock-fontified
           (setq font-lock-fontified nil)
-          (remove-hook 'before-revert-hook 'font-lock-revert-setup t)
-          (remove-hook 'after-revert-hook 'font-lock-revert-cleanup t)
           (font-lock-unfontify-region (point-min) (point-max))
           (font-lock-thing-lock-cleanup))
          (t
-          (remove-hook 'before-revert-hook 'font-lock-revert-setup t)
-          (remove-hook 'after-revert-hook 'font-lock-revert-cleanup t)
           (font-lock-thing-lock-cleanup)))
     (redraw-modeline)))
 
@@ -974,45 +993,46 @@ This can take a while for large buffers."
 (defun font-lock-unfontify-region (beg end &optional loudly)
   (funcall font-lock-unfontify-region-function beg end loudly))
 
-;; #### In these functions, the FSF is careful to do
-;; (save-restriction
-;;   (widen)
-;; before anything else.  Should we copy?
 (defun font-lock-default-fontify-buffer ()
   (interactive)
-  (let ((was-on font-lock-mode)
-       (font-lock-verbose (or font-lock-verbose (interactive-p)))
-       (font-lock-message-threshold 0)
-       (aborted nil))
-    ;; Turn it on to run hooks and get the right font-lock-keywords.
-    (or was-on (font-lock-mode 1))
-    (font-lock-unfontify-region (point-min) (point-max) t)
-;;    (buffer-syntactic-context-flush-cache)
+  ;; if we don't widen, then the C code will fail to
+  ;; realize that we're inside a comment.
+  (save-restriction
+    (widen)
+    (let ((was-on font-lock-mode)
+         (font-lock-verbose (or font-lock-verbose (interactive-p)))
+         (font-lock-message-threshold 0)
+         (aborted nil))
+      ;; Turn it on to run hooks and get the right font-lock-keywords.
+      (or was-on (font-lock-mode 1))
+      (font-lock-unfontify-region (point-min) (point-max) t)
+      ;;    (buffer-syntactic-context-flush-cache)
     
-    ;; If a ^G is typed during fontification, abort the fontification, but
-    ;; return normally (do not signal.)  This is to make it easy to abort
-    ;; fontification if it's taking a long time, without also causing the
-    ;; buffer not to pop up.  If a real abort is desired, the user can ^G
-    ;; again.
-    ;;
-    ;; Possibly this should happen down in font-lock-fontify-region instead
-    ;; of here, but since that happens from the after-change-hook (meaning
-    ;; much more frequently) I'm afraid of the bad consequences of stealing
-    ;; the interrupt character at inopportune times.
-    ;;
-    (condition-case nil
-       (save-excursion
-         (font-lock-fontify-region (point-min) (point-max)))
-      (t
-       (setq aborted t)))
-
-    (or was-on         ; turn it off if it was off.
-       (let ((font-lock-fontified nil)) ; kludge to prevent defontification
-         (font-lock-mode 0)))
-    (set (make-local-variable 'font-lock-fontified) t)
-    (when (and aborted font-lock-verbose)
-      (lprogress-display 'font-lock "Fontifying %s... aborted." 'abort (buffer-name))))
-  (run-hooks 'font-lock-after-fontify-buffer-hook))
+      ;; If a ^G is typed during fontification, abort the fontification, but
+      ;; return normally (do not signal.)  This is to make it easy to abort
+      ;; fontification if it's taking a long time, without also causing the
+      ;; buffer not to pop up.  If a real abort is desired, the user can ^G
+      ;; again.
+      ;;
+      ;; Possibly this should happen down in font-lock-fontify-region instead
+      ;; of here, but since that happens from the after-change-hook (meaning
+      ;; much more frequently) I'm afraid of the bad consequences of stealing
+      ;; the interrupt character at inopportune times.
+      ;;
+      (condition-case nil
+         (save-excursion
+           (font-lock-fontify-region (point-min) (point-max)))
+       (t
+        (setq aborted t)))
+
+      (or was-on                       ; turn it off if it was off.
+         (let ((font-lock-fontified nil)) ; kludge to prevent defontification
+           (font-lock-mode 0)))
+      (set (make-local-variable 'font-lock-fontified) t)
+      (when (and aborted font-lock-verbose)
+       (lprogress-display 'font-lock "Fontifying %s... aborted."
+                          'abort (buffer-name))))
+    (run-hooks 'font-lock-after-fontify-buffer-hook)))
 
 (defun font-lock-default-unfontify-buffer ()
   (font-lock-unfontify-region (point-min) (point-max))
@@ -1058,10 +1078,7 @@ This can take a while for large buffers."
     (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil))))
 
 ;; Following is the original FSF version (similar to our original
-;; version, before all the crap I added below).
-;;
-;; Probably that crap should either be fixed up so it works better,
-;; or tossed away.
+;; version, before the deferred stuff was added).
 ;;
 ;; I think that lazy-lock v2 tries to do something similar.
 ;; Those efforts should be merged.
@@ -1075,111 +1092,97 @@ This can take a while for large buffers."
 ;      (progn (goto-char beg) (beginning-of-line) (point))
 ;      (progn (goto-char end) (forward-line 1) (point))))))
 
-(defvar font-lock-old-extent nil)
-(defvar font-lock-old-len 0)
-
-(defun font-lock-fontify-glumped-region ()
-  ;; even if something goes wrong in the fontification, mark the glumped
-  ;; region as fontified; otherwise, the same error might get signaled
-  ;; after every command.
-  (unwind-protect
-      ;; buffer/extent may be deleted.
-      (if (and (extent-live-p font-lock-old-extent)
-              (buffer-live-p (extent-object font-lock-old-extent)))
-         (save-excursion
-           (set-buffer (extent-object font-lock-old-extent))
-           (font-lock-after-change-function-1
-            (extent-start-position font-lock-old-extent)
-            (extent-end-position font-lock-old-extent)
-            font-lock-old-len)))
-    (detach-extent font-lock-old-extent)
-    (setq font-lock-old-extent nil)))
+(defvar font-lock-always-fontify-immediately nil
+  "Set this to non-nil to disable font-lock deferral.
+Otherwise, changes to existing text will not be processed until the
+next redisplay cycle, avoiding excessive fontification when many
+buffer modifications are performed or a buffer is reverted.")
 
-(defun font-lock-pre-idle-hook ()
-  (condition-case nil
-      (if font-lock-old-extent
-         (font-lock-fontify-glumped-region))
-    (error (warn "Error caught in `font-lock-pre-idle-hook'"))))
+(defvar font-lock-pending-extent-table (make-hash-table :weakness 'key))
+(defvar font-lock-range-table (make-range-table))
 
-(defvar font-lock-always-fontify-immediately nil
-  "Set this to non-nil to disable font-lock deferral.")
+(defun font-lock-pre-idle-hook ()
+  (condition-case font-lock-error
+      (if (> (hash-table-count font-lock-pending-extent-table) 0)
+         (font-lock-fontify-pending-extents))
+    (error (warn "Error caught in `font-lock-pre-idle-hook': %s"
+                font-lock-error))))
 
 ;;; called when any modification is made to buffer text.  This function
-;;; attempts to glump adjacent changes together so that excessive
-;;; fontification is avoided.  This function could easily be adapted
-;;; to other after-change-functions.
+;;; remembers the changed ranges until the next redisplay, at which point
+;;; the extents are merged and pruned, and the resulting ranges fontified.
+;;; This function could easily be adapted to other after-change-functions.
 
 (defun font-lock-after-change-function (beg end old-len)
-  (let ((obeg (and font-lock-old-extent
-                  (extent-start-position font-lock-old-extent)))
-       (oend (and font-lock-old-extent
-                  (extent-end-position font-lock-old-extent)))
-       (bc-end (+ beg old-len)))
-
-    ;; If this change can't be merged into the glumped one,
-    ;; we need to fontify the glumped one right now.
-    (if (and font-lock-old-extent
-            (or (not (eq (current-buffer)
-                         (extent-object font-lock-old-extent)))
-                (< bc-end obeg)
-                (> beg oend)))
-       (font-lock-fontify-glumped-region))
-  
-    (if font-lock-old-extent
-       ;; Update glumped region.
-       (progn
-         ;; Any characters in the before-change region that are
-         ;; outside the glumped region go into the glumped
-         ;; before-change region.
-         (if (> bc-end oend)
-             (setq font-lock-old-len (+ font-lock-old-len (- bc-end oend))))
-         (if (> obeg beg)
-             (setq font-lock-old-len (+ font-lock-old-len (- obeg beg))))
-         ;; New glumped region is the union of the glumped region
-         ;; and the new region.
-         (set-extent-endpoints font-lock-old-extent
-                               (min obeg beg)
-                               (max oend end)))
-
-      ;; No glumped region, so create one.
-      (setq font-lock-old-extent (make-extent beg end))
-      (set-extent-property font-lock-old-extent 'detachable nil)
-      (set-extent-property font-lock-old-extent 'end-open nil)
-      (setq font-lock-old-len old-len))
-
+  (when font-lock-mode
+    (let ((ex (make-extent beg end)))
+      (set-extent-property ex 'detachable nil)
+      (set-extent-property ex 'end-open nil)
+      (let ((exs (gethash (current-buffer) font-lock-pending-extent-table)))
+       (push ex exs)
+       (puthash (current-buffer) exs font-lock-pending-extent-table)))
     (if font-lock-always-fontify-immediately
-       (font-lock-fontify-glumped-region))))
-
-(defun font-lock-after-change-function-1 (beg end old-len)
-  (if (null font-lock-mode)
-      nil
-    (save-excursion
-      (save-restriction
-       ;; if we don't widen, then fill-paragraph (and any command that
-       ;; operates on a narrowed region) confuses things, because the C
-       ;; code will fail to realize that we're inside a comment.
-       (widen)
-       (save-match-data
-         (let ((zmacs-region-stays zmacs-region-stays)) ; protect from change!
-           (goto-char beg)
-           ;; Maybe flush the internal cache used by syntactically-sectionize.
-           ;; (It'd be nice if this was more automatic.)  Any deletions mean
-           ;; the cache is invalid, and insertions at beginning or end of line
-           ;; mean that the bol cache might be invalid.
-;;         (if (or (> old-len 0) (bobp) (= (preceding-char) ?\n))
-;;             (buffer-syntactic-context-flush-cache))
-
-           ;; Always recompute the whole line.
-           (goto-char end)
-           (forward-line 1)
-           (setq end (point))
-           (goto-char beg)
-           (beginning-of-line)
-           (setq beg (point))
-           ;; Rescan between start of line from `beg' and start of line after
-           ;; `end'.
-           (font-lock-fontify-region beg end)))))))
-
+       (font-lock-fontify-pending-extents))))
+
+(defun font-lock-fontify-pending-extents ()
+  ;; ah, the beauty of mapping functions.
+  ;; this function is actually shorter than the old version, which handled
+  ;; only one buffer and one contiguous region!
+  (save-match-data
+    (maphash
+     #'(lambda (buffer exs)
+        ;; remove first, to avoid infinite reprocessing if error
+        (remhash buffer font-lock-pending-extent-table)
+        (when (buffer-live-p buffer)
+          (clear-range-table font-lock-range-table)
+          (with-current-buffer buffer
+            (save-excursion
+              (save-restriction
+                ;; if we don't widen, then the C code will fail to
+                ;; realize that we're inside a comment.
+                (widen)
+                (let ((zmacs-region-stays
+                       zmacs-region-stays)) ; protect from change!
+                  (mapc
+                   #'(lambda (ex)
+                       ;; paranoia.
+                       (when (and (extent-live-p ex)
+                                  (not (extent-detached-p ex)))
+                         ;; first expand the ranges to full lines, because
+                         ;; that is what will be fontified; then use a
+                         ;; range table to merge the ranges.
+                         (let* ((beg (extent-start-position ex))
+                                (end (extent-end-position ex))
+                                (beg (progn (goto-char beg)
+                                            (beginning-of-line)
+                                            (point)))
+                                (end (progn (goto-char end)
+                                            (forward-line 1)
+                                            (point))))
+                           (detach-extent ex)
+                           (put-range-table beg end t
+                                            font-lock-range-table))))
+                   exs)
+                  (map-range-table
+                   #'(lambda (beg end val)
+                       ;; Maybe flush the internal cache used by
+                       ;; syntactically-sectionize.  (It'd be nice if this
+                       ;; was more automatic.)  Any deletions mean the
+                       ;; cache is invalid, and insertions at beginning or
+                       ;; end of line mean that the bol cache might be
+                       ;; invalid.
+                       ;; #### This code has been commented out for some time
+                       ;; now and is bit-rotting.  Someone should look into
+                       ;; this.
+;;                     (if (or change-was-deletion (bobp)
+;;                             (= (preceding-char) ?\n))
+;;                         (buffer-syntactic-context-flush-cache))
+                       (if (and (= beg (point-min))
+                                (= end (point-max)))
+                           (font-lock-fontify-buffer)
+                         (font-lock-fontify-region beg end)))
+                   font-lock-range-table)))))))
+     font-lock-pending-extent-table)))
 \f
 ;; Syntactic fontification functions.
 
@@ -1567,28 +1570,6 @@ START should be at the beginning of a line."
        ((and (boundp 'lazy-lock-mode) lazy-lock-mode)
         (lazy-lock-after-fontify-buffer))))
 
-;; If the buffer is about to be reverted, it won't be fontified afterward.
-;(defun font-lock-revert-setup ()
-;  (setq font-lock-fontified nil))
-
-;; If the buffer has just been reverted, normally that turns off
-;; Font Lock mode.  So turn the mode back on if necessary.
-;; sb 1999-03-03 -- The above comment no longer appears to be operative as
-;; the first call to normal-mode *will* restore the font-lock state and
-;; this call forces a second font-locking to occur when reverting a buffer,
-;; which is wasteful at best. 
-;;(defun font-lock-revert-cleanup ())
-
-;; <andy@xemacs.org> 12-10-99. This still does not work right, I think
-;; after change functions will still get us. The simplest thing to do
-;; is unconditionally turn-off font-lock before revert (and thus nuke
-;; all hooks) and then turn it on again afterwards. This also happens
-;; to be much faster because fontifying from scratch is better than
-;; trying to do incremental changes for the whole buffer.
-
-(defalias 'font-lock-revert-cleanup 'turn-on-font-lock)
-(defalias 'font-lock-revert-setup 'turn-off-font-lock)
-
 \f
 ;; Various functions.
 
@@ -2369,7 +2350,7 @@ The name is assumed to begin with a capital letter.")
 
         ;; Class names:
         (list (concat "\\<\\(class\\|interface\\)\\>\\s *"
-                                                                java-font-lock-identifier-regexp)
+                      java-font-lock-identifier-regexp)
               2 'font-lock-function-name-face)
         
         ;; Package declarations:
index 08a791a..dc3b882 100644 (file)
@@ -1,7 +1,7 @@
 ;;; glyphs.el --- Lisp interface to C glyphs
 
 ;; Copyright (C) 1994, 1997 Free Software Foundation, Inc.
-;; Copyright (C) 1995, 1996 Ben Wing.
+;; Copyright (C) 1995, 1996, 2000 Ben Wing.
 
 ;; Author: Chuck Thompson <cthomp@cs.uiuc.edu>, Ben Wing <ben@xemacs.org>
 ;; Maintainer: XEmacs Development Team
 
 ;;; Synched up with: Not in FSF.
 
+;;; Authorship:
+
+;; Prototype created 1995 by Chuck Thompson.
+;; Completely rewritten by Ben Wing, 1995.
+;; Various cleanups (esp. doc strings) by Ben Wing, May 2000.
+
 ;;; Commentary:
 
 ;; This file is dumped with XEmacs.
 
 ;;; Code:
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; font specifiers
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; image specifiers
 
 (defun make-image-specifier (spec-list)
   "Return a new `image' specifier object with the specification list SPEC-LIST.
 SPEC-LIST can be a list of specifications (each of which is a cons of a
 locale and a list of instantiators), a single instantiator, or a list
 of instantiators.  See `make-specifier' for more information about
-specifiers."
+specifiers.
+
+An image specifier is used for images (pixmaps, widgets and the like).
+It is used to describe the actual image in a glyph.  It is instanced
+as an image-instance.  Note that \"image\" as used in XEmacs does not
+actually refer to what the term \"image\" normally means (a picture,
+e.g. in .GIF or .JPG format, and called a \"pixmap\" in XEmacs), but
+includes all types of graphical elements, including pixmaps, widgets
+\(buttons, sliders, text fields, etc.) and even strings of text.
+
+Note that, in practice, you rarely, if ever, need to actually create
+an image specifier! (The function `make-image-specifier' exists mainly
+for completeness.) Pretty much the only use for image specifiers is to
+control how glyphs are displayed, and the image specifier associated
+with a glyph (the `image' property of a glyph) is created
+automatically when a glyph is created (see `make-glyph') and need not
+\(and cannot, for that matter) ever be changed.  In fact, the design
+decision to create a separate image specifier type, rather than make
+glyphs themselves be specifiers, is debatable -- the other properties
+of glyphs are rarely used and could conceivably have been incorporated
+into the glyph's instantiator.  The rarely used glyph types (buffer,
+pointer, icon) could also have been incorporated into the instantiator.
+
+Image instantiators come in many formats: `xbm', `xpm', `gif', `jpeg',
+etc.  This describes the format of the data describing the image.  The
+resulting image instances also come in many types -- `mono-pixmap',
+`color-pixmap', `text', `pointer', etc.  This refers to the behavior of
+the image and the sorts of places it can appear. (For example, a
+color-pixmap image has fixed colors specified for it, while a
+mono-pixmap image comes in two unspecified shades \"foreground\" and
+\"background\" that are determined from the face of the glyph or
+surrounding text; a text image appears as a string of text and has an
+unspecified foreground, background, and font; a pointer image behaves
+like a mono-pixmap image but can only be used as a mouse pointer
+\[mono-pixmap images cannot be used as mouse pointers]; etc.) It is
+important to keep the distinction between image instantiator format and
+image instance type in mind.  Typically, a given image instantiator
+format can result in many different image instance types (for example,
+`xpm' can be instanced as `color-pixmap', `mono-pixmap', or `pointer';
+whereas `cursor-font' can be instanced only as `pointer'), and a
+particular image instance type can be generated by many different
+image instantiator formats (e.g.  `color-pixmap' can be generated by `xpm',
+`gif', `jpeg', etc.).
+
+See `make-image-instance' for a more detailed discussion of image
+instance types.
+
+An image instantiator should be a string or a vector of the form
+
+ [FORMAT :KEYWORD VALUE ...]
+
+i.e. a format symbol followed by zero or more alternating keyword-value
+pairs.  FORMAT should be one of
+
+'nothing
+   Don't display anything; no keywords are valid for this.
+   Can only be instanced as `nothing'.
+'string
+   Display this image as a text string.  Can only be instanced
+   as `text', although support for instancing as `mono-pixmap'
+   and `color-pixmap' should be added.
+'formatted-string
+   Display this image as a text string, with replaceable fields;
+   not currently implemented. (It is, instead, equivalent to `string'.)
+'xbm
+   An X bitmap; only if X or MS Windows support was compiled into this
+   XEmacs.  Can be instanced as `mono-pixmap', `color-pixmap', or `pointer'.
+'xpm
+   An XPM pixmap; only if XPM support was compiled into this XEmacs.
+   Can be instanced as `color-pixmap', `mono-pixmap', or `pointer'.
+'xface
+   An X-Face bitmap, used to encode people's faces in e-mail messages;
+   only if X-Face support was compiled into this XEmacs.  Can be
+   instanced as `mono-pixmap', `color-pixmap', or `pointer'.
+'gif
+   A GIF87 or GIF89 image; only if GIF support was compiled into this
+   XEmacs.  NOTE: only the first frame of animated gifs will be displayed.
+   Can be instanced as `color-pixmap'.
+'jpeg
+   A JPEG image; only if JPEG support was compiled into this XEmacs.
+   Can be instanced as `color-pixmap'.
+'png
+   A PNG image; only if PNG support was compiled into this XEmacs.
+   Can be instanced as `color-pixmap'.
+'tiff
+   A TIFF image; only if TIFF support was compiled into this XEmacs.
+   Can be instanced as `color-pixmap'.
+'bmp
+   A MS Windows BMP image; only if MS Windows support was compiled into
+   this XEmacs.  Can be instanced as `color-pixmap'.
+'cursor-font
+   One of the standard cursor-font names, such as \"watch\" or
+   \"right_ptr\" under X.  Under X, this is, more specifically, any
+   of the standard cursor names from appendix B of the Xlib manual
+   [also known as the file <X11/cursorfont.h>] minus the XC_ prefix.
+   On other window systems, the valid names will be specific to the
+   type of window system.  Can only be instanced as `pointer'.
+'mswindows-resource
+   An MS Windows pointer resource.  Specifies a resource to retrieve
+   directly from the system (an OEM resource) or from a file, particularly
+   an executable file.  If the resource is to be retrieved from a file, use
+   :file and optionally :resource-id.  Otherwise use :resource-id.  Always
+   specify :resource-type to specify the type (cursor, bitmap or icon) of
+   the resource.  Possible values for :resource-id are listed below.  Can
+   be instanced as `pointer' or `color-pixmap'.
+'font
+   A glyph from a font; i.e. the name of a font, and glyph index into it
+   of the form \"FONT fontname index [[mask-font] mask-index]\".
+   Currently can only be instanced as `pointer', although this should
+   probably be fixed.
+'subwindow
+   An embedded windowing system window.  Can only be instanced as
+   `subwindow'.
+'button
+   A button widget; either a push button, radio button or toggle button.
+   Can only be instanced as `widget'.
+'combo-box
+   A drop list of selectable items in a widget, for editing text.
+   Can only be instanced as `widget'.
+'edit-field
+   A text editing widget.  Can only be instanced as `widget'.
+'label
+   A static, text-only, widget; for displaying text.  Can only be instanced
+   as `widget'.
+'layout
+   A widget for controlling the positioning of children underneath it.
+   Through the use of nested layouts, a widget hierarchy can be created
+   which can have the appearance of any standard dialog box or similar
+   arrangement; all of this is counted as one \"glyph\" and could appear
+   in many of the places that expect a single glyph.  Can only be instanced
+   as `widget'.
+'native-layout
+   The native version of a layout widget.  #### Document me better!
+   Can only be instanced as `widget'.
+'progress-gauge
+   A sliding widget, for showing progress.  Can only be instanced as
+   `widget'.
+'tab-control
+   A tab widget; a series of user selectable tabs.  Can only be instanced
+   as `widget'.
+'tree-view
+   A folding widget.  Can only be instanced as `widget'.
+'scrollbar
+   A scrollbar widget.  Can only be instanced as `widget'.
+'autodetect
+   XEmacs tries to guess what format the data is in.  If X support
+   exists, the data string will be checked to see if it names a filename.
+   If so, and this filename contains XBM or XPM data, the appropriate
+   sort of pixmap or pointer will be created. [This includes picking up
+   any specified hotspot or associated mask file.] Otherwise, if `pointer'
+   is one of the allowable image-instance types and the string names a
+   valid cursor-font name, the image will be created as a pointer.
+   Otherwise, the image will be displayed as text.  If no X support
+   exists, the image will always be displayed as text.  Can be instanced as
+   `mono-pixmap', `color-pixmap', `pointer', or `text'.
+'inherit
+   Inherit from the background-pixmap property of a face.  Can only be
+   instanced as `mono-pixmap'.
+
+The valid keywords are:
+
+:data
+   Inline data.  For most formats above, this should be a string.  For
+   XBM images, this should be a list of three elements: width, height, and
+   a string of bit data.  This keyword is valid for all of the bitmap/pixmap
+   formats, as well as `string', `formatted-string', `font', `cursor-font',
+   and `autodetect'.
+:file
+   Data is contained in a file.  The value is the name of this file.
+   If both :data and :file are specified, the image is created from
+   what is specified in :data and the string in :file becomes the
+   value of the `image-instance-file-name' function when applied to
+   the resulting image-instance.  This keyword is valid for all of the
+   bitmap/pixmap formats as well as `mswindows-resource'.
+:foreground
+:background
+   For `xbm', `xface', `cursor-font', `widget' and `font'.  These keywords
+   allow you to explicitly specify foreground and background colors.
+   The argument should be anything acceptable to `make-color-instance'.
+   This will cause what would be a `mono-pixmap' to instead be colorized
+   as a two-color color-pixmap, and specifies the foreground and/or
+   background colors for a pointer instead of black and white.
+:mask-data
+   For `xbm' and `xface'.  This specifies a mask to be used with the
+   bitmap.  The format is a list of width, height, and bits, like for
+   :data.
+:mask-file
+   For `xbm' and `xface'.  This specifies a file containing the mask data.
+   If neither a mask file nor inline mask data is given for an XBM image,
+   and the XBM image comes from a file, XEmacs will look for a mask file
+   with the same name as the image file but with \"Mask\" or \"msk\"
+   appended.  For example, if you specify the XBM file \"left_ptr\"
+   [usually located in \"/usr/include/X11/bitmaps\"], the associated
+   mask file \"left_ptrmsk\" will automatically be picked up.
+:hotspot-x
+:hotspot-y
+   For `xbm' and `xface'.  These keywords specify a hotspot if the image
+   is instantiated as a `pointer'.  Note that if the XBM image file
+   specifies a hotspot, it will automatically be picked up if no
+   explicit hotspot is given.
+:color-symbols
+   Only for `xpm'.  This specifies an alist that maps strings
+   that specify symbolic color names to the actual color to be used
+   for that symbolic color (in the form of a string or a color-specifier
+   object).  If this is not specified, the contents of `xpm-color-symbols'
+   are used to generate the alist.
+:resource-id
+   Only for `mswindows-resource'.  This must be either an integer (which
+   directly specifies a resource number) or a string.  Valid strings are
+
+   -- For bitmaps:
+
+   \"close\", \"uparrow\", \"dnarrow\", \"rgarrow\", \"lfarrow\",
+   \"reduce\", \"zoom\", \"restore\", \"reduced\", \"zoomd\",
+   \"restored\", \"uparrowd\", \"dnarrowd\", \"rgarrowd\", \"lfarrowd\",
+   \"mnarrow\", \"combo\", \"uparrowi\", \"dnarrowi\", \"rgarrowi\",
+   \"lfarrowi\", \"size\", \"btsize\", \"check\", \"checkboxes\", and
+   \"btncorners\".
+
+   -- For cursors:
+
+   \"normal\", \"ibeam\", \"wait\", \"cross\", \"up\", \"sizenwse\",
+   \"sizenesw\", \"sizewe\", \"sizens\", \"sizeall\", and \"no\".
+
+   -- For icons:
+
+   \"sample\", \"hand\", \"ques\", \"bang\", \"note\", and \"winlogo\".
+:resource-type
+   Only for `mswindows-resource'.  This must be a symbol, either `cursor',
+   `icon', or `bitmap', specifying the type of resource to be retrieved.
+:face
+   Only for `inherit'.  This specifies the face to inherit from.
+   For widgets this also specifies the face to use for display. It defaults
+   to gui-element-face.
+
+Keywords accepted as menu item specs are also accepted by widgets.
+These are `:selected', `:active', `:suffix', `:keys', `:style',
+`:filter', `:config', `:included', `:key-sequence', `:accelerator',
+`:label' and `:callback'.
+
+If instead of a vector, the instantiator is a string, it will be
+converted into a vector by looking it up according to the specs in the
+`console-type-image-conversion-list' (q.v.) for the console type of
+the domain (usually a window; sometimes a frame or device) over which
+the image is being instantiated.
+
+If the instantiator specifies data from a file, the data will be read
+in at the time that the instantiator is added to the image (which may
+be well before when the image is actually displayed), and the
+instantiator will be converted into one of the inline-data forms, with
+the filename retained using a :file keyword.  This implies that the
+file must exist when the instantiator is added to the image, but does
+not need to exist at any other time (e.g. it may safely be a temporary
+file).
+"
   (make-specifier-and-init 'image spec-list))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; glyphs
 
 (defconst built-in-glyph-specifiers
   '(image contrib-p baseline)
-  "A list of the built-in face properties that are specifiers.")
+  "A list of the built-in glyph properties that are specifiers.")
 
 (defun glyph-property (glyph property &optional locale)
   "Return GLYPH's value of PROPERTY in LOCALE.
@@ -287,7 +547,7 @@ See `glyph-property-instance' for more information."
   "Change the image of GLYPH in LOCALE.
 
 SPEC should be an instantiator (a string or vector; see
-  `image-specifier-p' for a description of possible values here),
+  `make-image-specifier' for a description of possible values here),
   a list of (possibly tagged) instantiators, an alist of specifications
   (each mapping a locale to an instantiator list), or an image specifier
   object.
@@ -380,20 +640,162 @@ See `set-glyph-property' for more information."
   (set-glyph-property glyph 'baseline spec locale tag-set how-to-add))
 
 (defun make-glyph (&optional spec-list type)
-  "Return a new `glyph' object of type TYPE.
-
-TYPE should be one of `buffer' (used for glyphs in an extent, the modeline,
+  "Create a new glyph of type TYPE.
+
+A glyph in XEmacs does NOT refer to a single unit of textual display (the
+XEmacs term for this is \"rune\"), but rather is an object encapsulating
+a graphical element, such as an image or widget (an element such as a
+button or text field; \"widget\" is the term for this under X Windows,
+and it's called a \"control\" under MS Windows).  This graphical element
+could appear in a buffer, a margin, a gutter, or a toolbar, or as a mouse
+pointer or an icon, for example.
+
+Creating a glyph using `make-glyph' does not specify *where* the glyph
+will be used, but it does specify *what* the glyph will look like.  In
+particular, SPEC-LIST is used to specify this, and it's used to
+initialize the glyph's `image' property, which is an image
+specifier. (Note that \"image\" as used in the context of a glyph's
+`image' property or in the terms \"image specifier\", \"image
+instantiator\", or \"image instance\" does not refer to what people
+normally think of as an image (which in XEmacs is called a
+\"pixmap\"), but to any graphical element -- a pixmap, a widget, or
+even a block of text, when used in the places that call for a glyph.)
+The format of the SPEC-LIST is typically an image instantiator (a
+string or a vector; see `make-image-specifier' for a detailed description
+of the valid image instantiators), but can also be a list of such
+instantiators (each one in turn is tried until an image is
+successfully produced), a cons of a locale (frame, buffer, etc.)  and
+an instantiator, a list of such conses, or any other form accepted by
+`canonicalize-spec-list'.
+
+If you're not familiar with specifiers, you should be in order to
+understand how glyphs work.  The clearest introduction to specifiers
+is in the Lispref manual, available under Info. (Choose
+Help->Info->Info Contents on the menubar or type \\[info].) You can
+also see `make-specifier' for a capsule summary.  What's important to
+keep in mind is that a specifier lets you set a different value for
+any particular buffer, window, frame, device, or console.  This allows
+for a great deal of flexibility; in particular, only one global glyph
+needs to exist for a particular purpose (e.g. the icon used to represent
+an iconified frame, the mouse pointer used over particular areas of a
+frame, etc.), and in these cases you do not create your own glyph, but
+rather modify the existing one.
+
+As well as using SPEC-LIST to initialize the glyph, you can set
+specifications using `set-glyph-image'.  Note that, due to a possibly
+questionable historical design decision, a glyph itself is not
+actually a specifier, but rather is an object containing an image
+specifier (as well as other, seldom-used properties).  Therefore, you
+cannot set or access specifications for the glyph's image by directly
+using `set-specifier', `specifier-instance' or the like on the glyph;
+instead use them on `(glyph-image GLYPH)' or use the convenience
+functions `set-glyph-image', `glyph-image-instance', and
+`glyph-image'.
+
+Once you have created a glyph, you specify where it will be used as follows:
+
+-- To insert a glyph into a buffer, create an extent in the buffer and then
+   use `set-extent-begin-glyph' or `set-extent-end-glyph' to set a glyph
+   to be displayed at the corresponding edge of the extent. (It is common
+   to create zero-width extents for this purpose.)
+
+-- To insert a glyph into the left or right margin of a buffer, first
+   make sure the margin is visible by setting a value for the specifiers
+   `left-margin-width' or `right-margin-width'. (Not strictly necessary
+   when using margin glyphs with layout policy `whitespace'.) Then follow
+   the same procedure above for inserting a glyph in a buffer, and then
+   set a non-default layout policy for the glyph using
+   `set-extent-begin-glyph-layout' or `set-extent-end-glyph-layout'.
+   Alternatively, use the high-level annotations API (see
+   `make-annotation'). (In point of fact, you can also use the annotations
+   API for glyphs in a buffer, by setting a layout policy of `text'.)
+
+-- To insert a glyph into the modeline, just put the glyph directly as
+   one of the modeline elements. (Unfortunately you can't currently
+   put a begin glyph or end glyph on one of the modeline extents --
+   they're ignored.)
+
+-- To insert a glyph into a toolbar, specify it as part of a toolbar
+   instantiator (typically set on the specifier `default-toolbar').
+   See `default-toolbar' for more information. (Note that it is standard
+   practice to use a symbol in place of the glyph list in the toolbar
+   instantiator; the symbol is evalled to get the glyph list.  This
+   facilitates both creating the toolbar instantiator and modifying
+   individual glyphs in a toolbar later on.  For example, you can
+   change the way that the Mail toolbar button looks by modifying the
+   value of the variable `toolbar-mail-icon' (in general, `toolbar-*-icon')
+   and then calling `(set-specifier-dirty-flag default-toolbar)'.
+   (#### Unfortunately this doesn't quite work the way it should; the
+   change will appear in new frames, but not existing ones.
+
+-- To insert a glyph into a gutter, create or modify a gutter instantiator
+   (typically set on the specifier `default-gutter').  Gutter instantiators
+   consist of strings or lists of strings, so to insert a glyph, create an
+   extent over the string, and use `set-extent-begin-glyph' or
+   `set-extent-end-glyph' to set a glyph to be displayed at the corresponding
+   edge of the extent, just like for glyphs in a buffer.
+
+-- To use a glyph as the icon for a frame, you do not actually create a new
+   glyph; rather, you change the specifications for the existing glyph
+   `frame-icon-glyph'. (Remember that, because of the specifier nature of
+   glyphs, you can set different values for any particular buffer or frame.)
+
+-- To use a glyph as the mouse pointer, in general you do not create a
+   new glyph, but rather you change the specifications of various existing
+   glyphs, such as `text-pointer-glyph' for the pointer used over text,
+   `modeline-pointer-glyph' for the pointer used over the modeline, etc.
+   Do an apropos over `*-pointer-glyph' to find all of them. (Note also
+   that you can temporarily set the mouse pointer to some specific shape
+   by using `set-frame-pointer', which takes an image instace, as obtained
+   from calling `glyph-image-instance' on a glyph of type `pointer' --
+   either one of the above-mentioned variables or one you created yourself.
+   (See below for what it means to create a glyph of type `pointer'.)
+   This pointer will last only until the next mouse motion event is
+   processed or certain other things happen, such as creating or deleting
+   a window. (In fact, the above-mentioned pointer glyph variables are
+   implemented as part of the default handler for mouse motion events.
+   If you want to customize this behavior, take a look at `mode-motion-hook',
+   or `mouse-motion-handler' if you really want to get low-level.)
+
+-- To use a glyph to control the shape of miscellaneous redisplay effects
+   such as the truncation and continuation markers, set the appropriate
+   existing glyph variables, as for icons and pointers above.  See
+   `continuation-glyph', `control-arrow-glyph', `hscroll-glyph',
+   `invisible-text-glyph', `octal-escape-glyph', and `truncation-glyph'.
+   See also `overlay-arrow-string', an odd redisplay leftover which can
+   be set to a glyph you created, and will cause the glyph to be displayed
+   on top of the text position specified in the marker stored in
+   `overlay-arrow-position'.
+
+-- To use a glyph in a display table (i.e. to control the appearance of
+   any individual character), create the appropriate character glyphs
+   and then set a specification for the specifier `current-display-table',
+   which controls the appearance of characters.  You can also set an
+   overriding display table for use with text displayed in a particular
+   face; see `set-face-display-table' and `make-display-table'.
+   #### Note: Display tables do not currently support general Mule
+   characters.  They will be overhauled at some point to support this
+   and to provide other features required under Mule.
+
+-- To use a glyph as the background pixmap of a face: Note that the
+   background pixmap of a face is actually an image specifier -- probably
+   the only place in XEmacs where an image specifier occurs outside of
+   a glyph.  Similarly to how the glyph's image specifier works, you
+   don't create your own image specifier, but rather add specifications
+   to the existing one (using `set-face-background-pixmap').  Note that
+   the image instance that is generated in order to actually display the
+   background pixmap is of type `mono-pixmap', meaning that it's a two-color
+   image and the foreground and background of the image get filled in with
+   the corresponding colors from the face.
+
+It is extremely rare that you will ever have to specify a value for TYPE,
+which should be one of `buffer' (used for glyphs in an extent, the modeline,
 the toolbar, or elsewhere in a buffer), `pointer' (used for the mouse-pointer),
-or `icon' (used for a frame's icon), and defaults to `buffer'.
-
-SPEC-LIST is used to initialize the glyph's image.  It is typically an
-image instantiator (a string or a vector; see `image-specifier-p' for
-a detailed description of the valid image instantiators), but can also
-be a list of such instantiators (each one in turn is tried until an
-image is successfully produced), a cons of a locale (frame, buffer, etc.)
-and an instantiator, a list of such conses, or any other form accepted
-by `canonicalize-spec-list'.  See `make-specifier' for more information
-about specifiers."
+or `icon' (used for a frame's icon), and defaults to `buffer'.  The only cases
+where it needs to be specified is when creating icon or pointer glyphs, and
+in both cases the necessary glyphs have already been created at startup and
+are accessed through the appropriate variables, e.g. `text-pointer-glyph'
+(or in general, `*-pointer-glyph') and `frame-icon-glyph'."
   (let ((glyph (make-glyph-internal type)))
     (and spec-list (set-glyph-image glyph spec-list))
     glyph))
@@ -412,38 +814,22 @@ about specifiers."
 
 (defun make-pointer-glyph (&optional spec-list)
   "Return a new `pointer-glyph' object with the specification list SPEC-LIST.
-
 This is equivalent to calling `make-glyph', specifying a type of `pointer'.
+See `make-glyph' for more information.
 
-SPEC-LIST is used to initialize the glyph's image.  It is typically an
-image instantiator (a string or a vector; see `image-specifier-p' for
-a detailed description of the valid image instantiators), but can also
-be a list of such instantiators (each one in turn is tried until an
-image is successfully produced), a cons of a locale (frame, buffer, etc.)
-and an instantiator, a list of such conses, or any other form accepted
-by `canonicalize-spec-list'.  See `make-specifier' for more information
-about specifiers.
-
-You can also create a glyph with an empty SPEC-LIST and add image
-instantiators afterwards using `set-glyph-image'."
+It is extremely unlikely that you will ever need to create a pointer glyph.
+Instead, you probably want to be calling `set-glyph-image' on an existing
+glyph, e.g. `text-pointer-glyph'."
   (make-glyph spec-list 'pointer))
 
 (defun make-icon-glyph (&optional spec-list)
   "Return a new `icon-glyph' object with the specification list SPEC-LIST.
-
 This is equivalent to calling `make-glyph', specifying a type of `icon'.
+See `make-glyph' for more information.
 
-SPEC-LIST is used to initialize the glyph's image.  It is typically an
-image instantiator (a string or a vector; see `image-specifier-p' for
-a detailed description of the valid image instantiators), but can also
-be a list of such instantiators (each one in turn is tried until an
-image is successfully produced), a cons of a locale (frame, buffer, etc.)
-and an instantiator, a list of such conses, or any other form accepted
-by `canonicalize-spec-list'.  See `make-specifier' for more information
-about specifiers.
-
-You can also create a glyph with an empty SPEC-LIST and add image
-instantiators afterwards using `set-glyph-image'."
+It is extremely unlikely that you will ever need to create a icon glyph.
+Instead, you probably want to be calling `set-glyph-image' on
+`frame-icon-glyph'."
   (make-glyph spec-list 'icon))
 
 (defun nothing-image-instance-p (object)
@@ -468,9 +854,12 @@ instantiators afterwards using `set-glyph-image'."
   "Return t if OBJECT is an image instance of type `pointer'."
   (and (image-instance-p object) (eq 'pointer (image-instance-type object))))
 
+(defun widget-image-instance-p (object)
+  "Return t if OBJECT is an image instance of type `widget'."
+  (and (image-instance-p object) (eq 'widget (image-instance-type object))))
+
 (defun subwindow-image-instance-p (object)
-  "Return t if OBJECT is an image instance of type `subwindow'.
-Subwindows are not implemented in this version of XEmacs."
+  "Return t if OBJECT is an image instance of type `subwindow'."
   (and (image-instance-p object) (eq 'subwindow (image-instance-type object))))
 
 ;;;;;;;;;; the built-in glyphs
index 82652ea..765ee58 100644 (file)
@@ -385,6 +385,7 @@ Keymap for characters following C-c.")
 ;; Default binding of "Control-h" is help.
 (define-key global-map 'backspace 'delete-backward-char)
 (define-key global-map '(meta backspace) 'backward-kill-word)
+(define-key global-map [(control x) backspace] 'backward-kill-sentence)
 
 (define-key global-map "\M-\C-z" 'activate-region)
 
@@ -549,24 +550,26 @@ Keymap for characters following C-c.")
 (define-key global-map '(control kp-down) 'forward-block-of-lines)
 
 ;; context-sensitive movement
-;; (meta control left/right) should be reserved for bindings that
-;; switch between buffers/web pages/etc.
 (define-key global-map '(meta left)    'backward-sexp)
 (define-key global-map '(meta right)   'forward-sexp)
-(define-key global-map '(meta up)      'backward-sentence)
-(define-key global-map '(meta down)    'forward-sentence)
-(define-key global-map '(meta control up) 'backward-paragraph)
-(define-key global-map '(meta control down) 'forward-paragraph)
+(define-key global-map '(meta up)      'backward-paragraph)
+(define-key global-map '(meta down)    'forward-paragraph)
+(define-key global-map '(meta control left) 'backward-sentence)
+(define-key global-map '(meta control right) 'forward-sentence)
+(define-key global-map '(meta control up) 'scroll-down-one)
+(define-key global-map '(meta control down) 'scroll-up-one)
 (define-key global-map '(meta control home)    'beginning-of-defun)
 (define-key global-map '(meta control end)     'end-of-defun)
 (define-key global-map '(meta control prior)   'backward-page)
 (define-key global-map '(meta control next)    'forward-page)
 (define-key global-map '(meta kp-left)  'backward-sexp)
 (define-key global-map '(meta kp-right) 'forward-sexp)
-(define-key global-map '(meta kp-up)   'backward-sentence)
-(define-key global-map '(meta kp-down) 'forward-sentence)
-(define-key global-map '(meta control kp-up) 'backward-paragraph)
-(define-key global-map '(meta control kp-down) 'forward-paragraph)
+(define-key global-map '(meta kp-up)   'backward-paragraph)
+(define-key global-map '(meta kp-down) 'forward-paragraph)
+(define-key global-map '(meta control kp-left) 'backward-sentence)
+(define-key global-map '(meta control kp-right) 'forward-sentence)
+(define-key global-map '(meta control kp-up) 'scroll-down-one)
+(define-key global-map '(meta control kp-down) 'scroll-up-one)
 (define-key global-map '(meta control kp-home) 'beginning-of-defun)
 (define-key global-map '(meta control kp-end)  'end-of-defun)
 (define-key global-map '(meta control kp-prior)        'backward-page)
index 7783fd3..228aa09 100644 (file)
@@ -123,7 +123,11 @@ is nil, raise an error."
       (when dependents
        (error "Loaded libraries %s depend on %s"
               (prin1-to-string dependents) file))))
-  (let* ((flist (feature-symbols feature)) (file (car flist)))
+  (let* ((flist (feature-symbols feature))
+        (file (car flist)))
+    (flet ((reset-aload (x)
+            (let ((aload (get x 'autoload)))
+              (if aload (fset x (cons 'autoload aload))))))
     (mapcar
      #'(lambda (x)
         (cond ((stringp x) nil)
@@ -131,12 +135,17 @@ is nil, raise an error."
                ;; Remove any feature names that this file provided.
                (if (eq (car x) 'provide)
                    (setq features (delq (cdr x) features))))
-              ((boundp x) (makunbound x))
+              ((and (boundp x)
+                    (fboundp x))
+               (makunbound x)
+               (fmakunbound x)
+               (reset-aload x))
+              ((boundp x)
+               (makunbound x))
               ((fboundp x)
                (fmakunbound x)
-               (let ((aload (get x 'autoload)))
-                 (if aload (fset x (cons 'autoload aload)))))))
-     (cdr flist))
+               (reset-aload x))))
+     (cdr flist)))
     ;; Delete the load-history element for this file.
     (let ((elt (assoc file load-history)))
       (setq load-history (delq elt load-history)))))
index eda0c93..c61764c 100644 (file)
@@ -1374,7 +1374,8 @@ which will not be used as accelerators."
        ;; #### there should be something that holds the name that the init
        ;; file should be created as, when it's not present.
        (progn (find-file (or user-init-file "~/.emacs"))
-             (emacs-lisp-mode))]
+             (or (eq major-mode 'emacs-lisp-mode)
+                 (emacs-lisp-mode)))]
       ["%_Save Options to .emacs File" customize-save-customized]
       )
 
@@ -1866,13 +1867,13 @@ If this is a relative filename, it is put into the same directory as your
                                          current-language-environment))
                            `([,(car lang)
                               (help-with-tutorial nil ,(cdr tut))]))))
-                language-info-alist))
-     ;; Non mule tutorials.
-     (mapcar #'(lambda (lang)
-                `[,(car lang)
-                  (help-with-tutorial ,(format "TUTORIAL.%s"
-                                               (cadr lang)))])
-            tutorial-supported-languages))))
+                language-info-alist)
+       ;; Non mule tutorials.
+       (mapcar #'(lambda (lang)
+                  `[,(car lang)
+                    (help-with-tutorial ,(format "TUTORIAL.%s"
+                                                 (cadr lang)))])
+              tutorial-supported-languages)))))
 
 \f
 (set-menubar default-menubar)
index 342f5bd..6343c2d 100644 (file)
@@ -1544,6 +1544,24 @@ If DEFAULT-VALUE is non-nil, return that if user enters an empty
            (setq n (1+ n))))
       new)))
 
+
+;; Wrapper for `directory-files' for use in generating completion lists.
+;; Generates output in the same format as `file-name-all-completions'.
+;;
+;; The EFS replacement for `directory-files' doesn't support the FILES-ONLY
+;; option, so it has to be faked.  The listing cache will hopefully
+;; improve the performance of this operation.
+(defun minibuf-directory-files (dir &optional match-regexp files-only)
+  (let ((want-file (or (eq files-only nil) (eq files-only t)))
+        (want-dirs (or (eq files-only nil) (not (eq files-only t)))))
+    (delete nil
+            (mapcar (function (lambda (f)
+                                (if (file-directory-p (expand-file-name f dir))
+                                    (and want-dirs (file-name-as-directory f))
+                                  (and want-file f))))
+                    (delete "." (directory-files dir nil match-regexp))))))
+
+
 (defun read-file-name-2 (history prompt dir default
                                 must-match initial-contents
                                 completer)
@@ -1632,7 +1650,7 @@ If DEFAULT-VALUE is non-nil, return that if user enters an empty
       (reset-buffer completion-buf)
       (let ((standard-output completion-buf))
        (display-completion-list
-        (delete "." (directory-files full nil nil nil (if dir-p 'directory)))
+         (minibuf-directory-files full nil (if dir-p 'directory))
         :user-data dir-p
         :reference-buffer minibuf
         :activate-callback 'read-file-name-activate-callback)
@@ -1825,7 +1843,9 @@ DIR defaults to current buffer's directory default."
             ((eq action 't)
              ;; all completions
              (mapcar #'un-substitute-in-file-name
-                     (file-name-all-completions name dir)))
+                     (if (string= name "")
+                         (delete "./" (file-name-all-completions "" dir))
+                       (file-name-all-completions name dir))))
             (t;; nil
              ;; complete
              (let* ((d (or dir default-directory))
@@ -1854,17 +1874,13 @@ DIR defaults to current buffer's directory default."
    #'(lambda (action orig string specdir dir name)
       (let* ((dirs #'(lambda (fn)
                       (let ((l (if (equal name "")
-                                   (directory-files
+                                   (minibuf-directory-files
                                     dir
-                                    nil
                                     ""
-                                    nil
                                     'directories)
-                                 (directory-files
+                                 (minibuf-directory-files
                                   dir
-                                  nil
                                   (concat "\\`" (regexp-quote name))
-                                  nil
                                   'directories))))
                         (mapcar fn
                                 ;; Wretched unix
@@ -1947,7 +1963,7 @@ whether it is a file(/result) or a directory (/result/)."
   (let ((standard-output (window-buffer window)))
     (condition-case nil
        (display-completion-list
-        (directory-files dir nil nil nil t)
+        (minibuf-directory-files dir nil t)
         :window-width (window-width window)
         :window-height (window-text-area-height window)
         :completion-string ""
@@ -1963,7 +1979,7 @@ whether it is a file(/result) or a directory (/result/)."
   (let ((standard-output (window-buffer window)))
     (condition-case nil
        (display-completion-list
-        (delete "." (directory-files dir nil nil nil 1))
+        (minibuf-directory-files dir nil 1)
         :window-width (window-width window)
         :window-height (window-text-area-height window)
         :completion-string ""
index 9c1d690..86b7bd8 100644 (file)
 SPEC-LIST can be a list of specifications (each of which is a cons of a
 locale and a list of instantiators), a single instantiator, or a list
 of instantiators.  See `make-specifier' for more information about
-specifiers."
+specifiers.
+
+Valid instantiators for font specifiers are:
+
+-- a string naming a font (e.g. under X this might be
+   \"-*-courier-medium-r-*-*-*-140-*-*-*-*-iso8859-*\" for a 14-point
+   upright medium-weight Courier font)
+-- a font instance (use that instance directly if the device matches,
+   or use the string that generated it)
+-- a vector of no elements (only on TTY's; this means to set no font
+   at all, thus using the \"natural\" font of the terminal's text)
+-- a vector of one element (a face to inherit from)
+"
   (make-specifier-and-init 'font spec-list))
 
 (defun font-name (font &optional domain charset)
@@ -127,7 +139,21 @@ and is equivalent to the sum of the font instance's ascent and descent."
 SPEC-LIST can be a list of specifications (each of which is a cons of a
 locale and a list of instantiators), a single instantiator, or a list
 of instantiators.  See `make-specifier' for a detailed description of
-how specifiers work."
+how specifiers work.
+
+Valid instantiators for color specifiers are:
+
+-- a string naming a color (e.g. under X this might be \"lightseagreen2\"
+   or \"#F534B2\")
+-- a color instance (use that instance directly if the device matches,
+   or use the string that generated it)
+-- a vector of no elements (only on TTY's; this means to set no color
+   at all, thus using the \"natural\" color of the terminal's text)
+-- a vector of one or two elements: a face to inherit from, and
+   optionally a symbol naming which property of that face to inherit,
+   either `foreground' or `background' (if omitted, defaults to the same
+   property that this color specifier is used for; if this specifier is
+   not part of a face, the instantiator would not be valid)."
   (make-specifier-and-init 'color spec-list))
 
 (defun color-name (color &optional domain)
@@ -146,4 +172,24 @@ to using `specifier-instance' and applying `color-instance-rgb-components'
 to the result.  See `make-specifier' for more information about specifiers."
   (ws-object-property-1 'color-instance-rgb-components color domain))
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; face-boolean specifiers
+
+(defun make-face-boolean-specifier (spec-list)
+  "Return a new `face-boolean' specifier object with the given spec list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for a detailed description of
+how specifiers work.
+
+Valid instantiators for face-boolean specifiers are
+
+-- t or nil
+-- a vector of two or three elements: a face to inherit from,
+   optionally a symbol naming the property of that face to inherit from
+   (if omitted, defaults to the same property that this face-boolean
+   specifier is used for; if this specifier is not part of a face,
+   the instantiator would not be valid), and optionally a value which,
+   if non-nil, means to invert the sense of the inherited property."
+  (make-specifier-and-init 'color spec-list))
+
 ;;; objects.el ends here.
index 2d1eaf3..9ecd6db 100644 (file)
@@ -38,8 +38,8 @@
 ;;   (this goes for any package loaded before `subr.el'.)
 ;;
 ;; - not to use macros, because they are not yet available (and this
-;;   file must be loadable uncompiled.)  This rules out CL-style
-;;   macros like `when', for instance.
+;;   file must be loadable uncompiled.)  Built in macros, such as
+;;   `when' and `unless' are fine, of course.
 ;;
 ;; - not to use `defcustom'.  If you must add user-customizable
 ;;   variables here, use `defvar', and add the variable to
index c0602de..1fc438a 100644 (file)
@@ -129,7 +129,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you
              (if buffer
                  (set-marker (process-mark proc) (point buffer) buffer))
              (unwind-protect
-                 (progn
+                 (prog1
                    (catch 'call-process-done
                      (when (not discard)
                        (set-process-sentinel
index cf2652a..9ece9ae 100644 (file)
@@ -2001,6 +2001,17 @@ is nil.  If BUFFER is nil, the current buffer is assumed."
       (beginning-of-buffer nil)
       (end-of-buffer nil))))
 
+(defun scroll-up-one ()
+  "Scroll text of current window upward one line.
+On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
+On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
+signaled.
+
+If `signal-error-on-buffer-boundary' is nil, attempts to scroll past buffer
+boundaries do not cause an error to be signaled."
+  (interactive "_")
+  (scroll-up-command 1))
+
 (defun scroll-up-command (&optional n)
   "Scroll text of current window upward ARG lines; or near full screen if no ARG.
 A near full screen is `next-screen-context-lines' less than a full screen.
@@ -2020,6 +2031,17 @@ boundaries do not cause an error to be signaled."
       (beginning-of-buffer nil)
       (end-of-buffer nil))))
 
+(defun scroll-down-one ()
+  "Scroll text of current window downward one line.
+On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
+On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
+signaled.
+
+If `signal-error-on-buffer-boundary' is nil, attempts to scroll past buffer
+boundaries do not cause an error to be signaled."
+  (interactive "_")
+  (scroll-down-command 1))
+
 (defun scroll-down-command (&optional n)
   "Scroll text of current window downward ARG lines; or near full screen if no ARG.
 A near full screen is `next-screen-context-lines' less than a full screen.
index 5653975..08b037e 100644 (file)
@@ -1,7 +1,7 @@
 ;;; specifier.el --- Lisp interface to specifiers
 
 ;; Copyright (C) 1997 Free Software Foundation, Inc.
-;; Copyright (C) 1995, 1996 Ben Wing.
+;; Copyright (C) 1995, 1996, 2000 Ben Wing.
 
 ;; Author: Ben Wing <ben@xemacs.org>
 ;; Keywords: internal, dumped
@@ -275,18 +275,20 @@ indicate that it applies everywhere.  LOCALE usually defaults to
 
 VALUE is usually what is called an \"instantiator\" (which, roughly
 speaking, corresponds to the \"value\" of the property governed by
-SPECIFIER).  The valid instantiators for SPECIFIER depend on the
-type of SPECIFIER (which you can determine using `specifier-type').
-The specifier `scrollbar-width', for example, is of type `integer',
-meaning its valid instantiators are integers.  The specifier
-governing the background color of the `default' face (you can
-retrieve this specifier using `(face-background 'default)') is
-of type `color', meaning its valid instantiators are strings naming
-colors and color-instance objects.  For some types of specifiers,
-such as `image' and `toolbar', the instantiators can be very
-complex.  Generally this is documented in the appropriate predicate
-function -- `color-specifier-p', `image-specifier-p',
-`toolbar-specifier-p', etc.
+SPECIFIER).  The valid instantiators for SPECIFIER depend on the type
+of SPECIFIER (which you can determine using `specifier-type').  The
+specifier `scrollbar-width', for example, is of type `integer',
+meaning its valid instantiators are integers.  The specifier governing
+the background color of the `default' face (you can retrieve this
+specifier using `(face-background 'default)') is of type `color',
+meaning its valid instantiators are strings naming colors and
+color-instance objects.  For some types of specifiers, such as `image'
+and `toolbar', the instantiators can be very complex.  Generally this
+is documented in the appropriate creation function --
+e.g. `make-color-specifier', `make-font-specifier',
+`make-image-specifier' -- or in the global variable holding the most
+common specifier for that type (`default-toolbar', `default-gutter',
+`current-display-table').
 
 NOTE: It does *not* work to give a VALUE of nil as a way of
 removing the specifications for a locale.  Use `remove-specifier'
@@ -526,6 +528,58 @@ Example:
                                              ,(car oldval))))
                                       oldvallist varlist))))))))
 
+(defun make-integer-specifier (spec-list)
+  "Return a new `integer' specifier object with the given specification list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for more information about
+specifiers.
+
+Valid instantiators for integer specifiers are integers."
+  (make-specifier-and-init 'integer spec-list))
+
+(defun make-boolean-specifier (spec-list)
+  "Return a new `boolean' specifier object with the given specification list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for more information about
+specifiers.
+
+Valid instantiators for boolean specifiers are t and nil."
+  (make-specifier-and-init 'boolean spec-list))
+
+(defun make-natnum-specifier (spec-list)
+  "Return a new `natnum' specifier object with the given specification list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for more information about
+specifiers.
+
+Valid instantiators for natnum specifiers are non-negative integers."
+  (make-specifier-and-init 'natnum spec-list))
+
+(defun make-generic-specifier (spec-list)
+  "Return a new `generic' specifier object with the given specification list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for more information about
+specifiers.
+
+Valid instantiators for generic specifiers are all Lisp values.
+They are returned back unchanged when a specifier is instantiated."
+  (make-specifier-and-init 'generic spec-list))
+
+(defun make-display-table-specifier (spec-list)
+  "Return a new `display-table' specifier object with the given spec list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for more information about
+specifiers.
+
+Valid instantiators for display-table specifiers are described in
+detail in the doc string for `current-display-table'."
+  (make-specifier-and-init 'display-table spec-list))
+
 ;; Evaluate this for testing:
 ; (cl-prettyexpand '(let-specifier ((modeline-shadow-thickness 0 (selected-window) 'x) (fubar (value) baz)) (sit-for 1)))
 \f
index 772abf5..74d44e7 100644 (file)
@@ -198,4 +198,21 @@ as an argument if release is over a blank area of the toolbar."
   (setq zmacs-region-stays t)
   (release-toolbar-button-internal event nil))
 
+(defun make-toolbar-specifier (spec-list)
+  "Return a new `toolbar' specifier object with the given specification list.
+SPEC-LIST can be a list of specifications (each of which is a cons of a
+locale and a list of instantiators), a single instantiator, or a list
+of instantiators.  See `make-specifier' for more information about
+specifiers.
+
+Toolbar specifiers are used to specify the format of a toolbar.
+The values of the variables `default-toolbar', `top-toolbar',
+`left-toolbar', `right-toolbar', and `bottom-toolbar' are always
+toolbar specifiers.
+
+Valid toolbar instantiators are called \"toolbar descriptors\"
+and are lists of vectors.  See `default-toolbar' for a description
+of the exact format."
+  (make-specifier-and-init 'toolbar spec-list))
+
 ;;; toolbar.el ends here
index bba50dc..f2ac1bd 100644 (file)
@@ -1,3 +1,7 @@
+2000-05-28  Martin Buchholz <martin@xemacs.org>
+
+       * XEmacs 21.2.34 is released.
+
 2000-05-01  Martin Buchholz <martin@xemacs.org>
 
        * XEmacs 21.2.33 is released.
index 41ff8e5..94fd8f1 100644 (file)
@@ -1,3 +1,31 @@
+2000-05-28  Martin Buchholz <martin@xemacs.org>
+
+       * XEmacs 21.2.34 is released.
+
+2000-05-17  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+       * xemacs/basic.texi: Document translation of tutorial.
+       * xemacs/startup.texi: Remove lock-directory.
+       * xemacs/enterings.texi: Update.
+
+2000-05-17  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+       * lispref/display.texi:
+       * lispref/faces.texi:
+       * lispref/glyphs.texi:
+       * lispref/gutter.texi:
+       * lispref/modes.texi:
+       * lispref/specifiers.texi:
+       * lispref/toolbar.texi:
+       Update.  Merge Ben's doc-string update.
+
+2000-05-08  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+       * xemacs/basic.texi:
+       * xemacs/enterings.texi:
+       * xemacs/mini.texi:
+       Partial sync with FSF Emacs 20.6 and some update.
+
 2000-05-01  Martin Buchholz <martin@xemacs.org>
 
        * XEmacs 21.2.33 is released.
index dc213f4..e46d7f2 100644 (file)
@@ -5051,7 +5051,7 @@ For a description about the internals: @xref{lrecords}.
 
 Our next candidates are the other objects that behave quite differently
 than everything else: the strings. They consists of two parts, a
-fixed-size portion (@code{struct Lisp_string}) holding the string's
+fixed-size portion (@code{struct Lisp_String}) holding the string's
 length, its property list and a pointer to the second part, and the
 actual string data, which is stored in string-chars blocks comparable to
 frob blocks. In this block, the data is not only freed, but also a
@@ -5787,7 +5787,7 @@ field and a pointer to an associated array of lrecord_description.
 @node Dumping phase, Reloading phase, Data descriptions, Dumping
 @section Dumping phase
 
-Dumping is done by calling the function pdump() (in alloc.c) which is
+Dumping is done by calling the function pdump() (in dumper.c) which is
 invoked from Fdump_emacs (in emacs.c).  This function performs a number
 of tasks.
 
index 8d92bd0..6feb3e0 100644 (file)
@@ -235,7 +235,7 @@ prevent processing of subsequent files.  (The file that gets the error
 will not, of course, produce any compiled code.)
 
 @example
-% emacs -batch -f batch-byte-compile *.el
+% xemacs -batch -f batch-byte-compile *.el
 @end example
 @end defun
 
index 0b11270..fdc5c74 100644 (file)
@@ -31,7 +31,7 @@ select the type of database file to use.  (Note:  XEmacs may not
 support both of these types.)
 
 For a @var{type} of @code{'dbm}, there are no subtypes, so
-@var{subtype} should by @code{nil}.
+@var{subtype} should be @code{nil}.
 
 For a @var{type} of @code{'berkeley_db}, the following subtypes are
 available:  @code{'hash}, @code{'btree}, and @code{'recno}.  See the
index 1517f0f..1a85ffc 100644 (file)
@@ -996,6 +996,71 @@ the contents of a display table, using additional indirection
 to a ``glyph table'' and such.  Note that ``glyph'' has a different
 meaning in XEmacs.)
 
+@defvar current-display-table
+
+The display table currently in use.  This is a specifier.
+
+Display tables are used to control how characters are displayed.  Each
+time that redisplay processes a character, it is looked up in all the
+display tables that apply (obtained by calling @code{specifier-instance}
+on @code{current-display-table} and any overriding display tables
+specified in currently active faces).  The first entry found that
+matches the character determines how the character is displayed.  If
+there is no matching entry, the default display method is
+used. (Non-control characters are displayed as themselves and control
+characters are displayed according to the buffer-local variable
+@code{ctl-arrow}.  Control characters are further affected by
+@code{control-arrow-glyph} and @code{octal-escape-glyph}.)
+
+Each instantiator in this specifier and the display-table specifiers
+in faces is a display table or a list of such tables.  If a list, each
+table will be searched in turn for an entry matching a particular
+character.  Each display table is one of
+
+@itemize @bullet
+@item
+A vector, specifying values for characters starting at 0.
+@item
+A char table, either of type @code{char} or @code{generic}.
+@item
+A range table.
+@end itemize
+
+Each entry in a display table should be one of
+
+@itemize @bullet
+@item
+nil (this entry is ignored and the search continues).
+@item
+A character (use this character; if it happens to be the same as
+the original character, default processing happens, otherwise
+redisplay attempts to display this character directly;
+#### At some point recursive display-table lookup will be
+implemented).
+@item
+A string (display each character in the string directly;
+#### At some point recursive display-table lookup will be
+implemented).
+@item
+A glyph (display the glyph;
+#### At some point recursive display-table lookup will be
+implemented when a string glyph is being processed).
+@item
+A cons of the form (format "@var{string}") where @var{string} is a
+printf-like spec used to process the character. #### Unfortunately no
+formatting directives other than %% are implemented.
+@item
+A vector (each element of the vector is processed recursively;
+in such a case, nil elements in the vector are simply ignored).
+
+#### At some point in the near future, display tables are likely to
+be expanded to include other features, such as referencing characters
+in particular fonts and allowing the character search to continue
+all the way up the chain of specifier instantiators.  These features
+are necessary to properly display Unicode characters.
+@end itemize
+@end defvar
+
   Individual faces can also specify an overriding display table;
 this is set using @code{set-face-display-table}.  @xref{Faces}.
 
index e332f78..a654d69 100644 (file)
@@ -94,9 +94,9 @@ functions in preference to the lower-level extent functions.  For more
 information, @xref{Annotations}.
 
   If an extent has its @code{detachable} property set, it will become
-@dfn{detached} (i.e. no longer in the buffer) when all its text its
+@dfn{detached} (i.e. no longer in the buffer) when all its text is
 deleted.  Otherwise, it will simply shrink down to zero-length and
-sit it the same place in the buffer.  By default, the @code{detachable}
+sit in the same place in the buffer.  By default, the @code{detachable}
 property is set on newly-created extents.  @xref{Detached Extents}.
 
   If an extent has its @code{duplicable} property set, it will be
index 9afd173..ee36e15 100644 (file)
@@ -476,6 +476,33 @@ This predicate returns @code{t} if @var{object} is a font specifier, and
 @code{nil} otherwise.
 @end defun
 
+@defun make-font-specifier spec-list
+
+Return a new @code{font} specifier object with the given specification
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.  @xref{Specifiers}, for more information
+about specifiers.
+
+Valid instantiators for font specifiers are:
+
+@itemize @bullet
+
+@item
+A string naming a font (e.g. under X this might be
+"-*-courier-medium-r-*-*-*-140-*-*-*-*-iso8859-*" for a 14-point
+upright medium-weight Courier font).
+@item
+A font instance (use that instance directly if the device matches,
+or use the string that generated it).
+@item
+A vector of no elements (only on TTY's; this means to set no font
+at all, thus using the "natural" font of the terminal's text).
+@item
+A vector of one element (a face to inherit from).
+@end itemize
+@end defun
+
 @node Font Instances
 @subsection Font Instances
 
@@ -634,6 +661,63 @@ applying @code{font-instance-properties} to the result.
 This function returns non-@code{nil} if @var{object} is a color specifier.
 @end defun
 
+@defun make-color-specifier spec-list
+
+Return a new @code{color} specifier object with the given specification
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.  @xref{Specifiers}, for a detailed
+description of how specifiers work.
+
+Valid instantiators for color specifiers are:
+
+@itemize @bullet
+@item
+A string naming a color (e.g. under X this might be "lightseagreen2" or
+"#F534B2").
+
+@item
+A color instance (use that instance directly if the device matches,
+or use the string that generated it).
+
+@item
+A vector of no elements (only on TTY's; this means to set no color at
+all, thus using the "natural" color of the terminal's text).
+
+@item
+A vector of one or two elements: a face to inherit from, and optionally
+a symbol naming which property of that face to inherit, either
+@code{foreground} or @code{background} (if omitted, defaults to the same
+property that this color specifier is used for; if this specifier is not
+part of a face, the instantiator would not be valid).
+@end itemize
+@end defun
+
+@defun make-face-boolean-specifier spec-list
+
+Return a new @code{face-boolean} specifier object with the given spec
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.  @xref{Specifiers}, for a detailed
+description of how specifiers work.
+
+Valid instantiators for face-boolean specifiers are
+
+@itemize @bullet
+@item
+t or nil.
+@item
+A vector of two or three elements: a face to inherit from, optionally a
+symbol naming the property of that face to inherit from (if omitted,
+defaults to the same property that this face-boolean specifier is used
+for; if this specifier is not part of a face, the instantiator would not
+be valid), and optionally a value which, if non-nil, means to invert the
+sense of the inherited property.
+@end itemize
+
+@end defun
+
+
 @node Color Instances
 @subsection Color Instances
 @cindex color instances
index 3cffa49..8373674 100644 (file)
@@ -7,15 +7,15 @@
 @chapter Glyphs
 @cindex glyphs
 
-  A @dfn{glyph} is an object that is used for pixmaps and images of all
-sorts, as well as for things that ``act'' like pixmaps, such as
-non-textual strings (@dfn{annotations}) displayed in a buffer or in the
-margins.  It is used in begin-glyphs and end-glyphs attached to extents,
-marginal and textual annotations, overlay arrows (@code{overlay-arrow-*}
-variables), toolbar buttons, mouse pointers, frame icons, truncation and
-continuation markers, and the like. (Basically, any place there is an
-image or something that acts like an image, there will be a glyph object
-representing it.)
+  A @dfn{glyph} is an object that is used for pixmaps, widgets and
+images of all sorts, as well as for things that ``act'' like pixmaps,
+such as non-textual strings (@dfn{annotations}) displayed in a buffer or
+in the margins.  It is used in begin-glyphs and end-glyphs attached to
+extents, marginal and textual annotations, overlay arrows
+(@code{overlay-arrow-*} variables), toolbar buttons, mouse pointers,
+frame icons, truncation and continuation markers, and the
+like. (Basically, any place there is an image or something that acts
+like an image, there will be a glyph object representing it.)
 
   The actual image that is displayed (as opposed to its position or
 clipping) is defined by an @dfn{image specifier} object contained
@@ -71,6 +71,179 @@ one of @code{buffer} (used for glyphs in an extent, the modeline, the
 toolbar, or elsewhere in a buffer), @code{pointer} (used for the
 mouse-pointer), or @code{icon} (used for a frame's icon), and defaults
 to @code{buffer}.  @xref{Glyph Types}.
+
+A glyph in XEmacs does @strong{NOT} refer to a single unit of textual
+display (the XEmacs term for this is @dfn{rune}), but rather is an
+object encapsulating a graphical element, such as an image or widget (an
+element such as a button or text field; @dfn{widget} is the term for
+this under X Windows, and it's called a @dfn{control} under MS Windows).
+This graphical element could appear in a buffer, a margin, a gutter, or
+a toolbar, or as a mouse pointer or an icon, for example.
+
+Creating a glyph using @code{make-glyph} does not specify @emph{where}
+the glyph will be used, but it does specify @emph{what} the glyph will
+look like.  In particular, SPEC-LIST is used to specify this, and it's
+used to initialize the glyph's @code{image} property, which is an image
+specifier. (Note that @dfn{image} as used in the context of a glyph's
+@code{image} property or in the terms @dfn{image specifier}, @dfn{image
+instantiator}, or @dfn{image instance} does not refer to what people
+normally think of as an image (which in XEmacs is called a
+@dfn{pixmap}), but to any graphical element---a pixmap, a widget, or
+even a block of text, when used in the places that call for a glyph.)
+The format of the SPEC-LIST is typically an image instantiator (a string
+or a vector; @ref{Image Specifiers}), but can also be a list of such
+instantiators (each one in turn is tried until an image is successfully
+produced), a cons of a locale (frame, buffer, etc.)  and an
+instantiator, a list of such conses, or any other form accepted by
+@code{canonicalize-spec-list}. @xref{Specifiers}, for more information
+about specifiers.
+
+If you're not familiar with specifiers, you should be in order to
+understand how glyphs work.  The clearest introduction to specifiers
+is in the Lispref manual, available under Info. (Choose
+Help->Info->Info Contents on the menubar or type C-h i.) You can
+also see @code{make-specifier} for a capsule summary.  What's important to
+keep in mind is that a specifier lets you set a different value for
+any particular buffer, window, frame, device, or console.  This allows
+for a great deal of flexibility; in particular, only one global glyph
+needs to exist for a particular purpose (e.g. the icon used to represent
+an iconified frame, the mouse pointer used over particular areas of a
+frame, etc.), and in these cases you do not create your own glyph, but
+rather modify the existing one.
+
+As well as using @var{spec-list} to initialize the glyph, you can set
+specifications using @code{set-glyph-image}.  Note that, due to a
+possibly questionable historical design decision, a glyph itself is not
+actually a specifier, but rather is an object containing an image
+specifier (as well as other, seldom-used properties).  Therefore, you
+cannot set or access specifications for the glyph's image by directly
+using @code{set-specifier}, @code{specifier-instance} or the like on the
+glyph; instead use them on @code{(glyph-image @var{glyph})} or use the
+convenience functions @code{set-glyph-image},
+@code{glyph-image-instance}, and @code{glyph-image}.
+
+Once you have created a glyph, you specify where it will be used as
+follows:
+
+@itemize @bullet
+@item
+To insert a glyph into a buffer, create an extent in the buffer and then
+use @code{set-extent-begin-glyph} or @code{set-extent-end-glyph} to set
+a glyph to be displayed at the corresponding edge of the extent. (It is
+common to create zero-width extents for this purpose.)
+
+@item
+To insert a glyph into the left or right margin of a buffer, first
+make sure the margin is visible by setting a value for the specifiers
+@code{left-margin-width} or @code{right-margin-width}. (Not strictly necessary
+when using margin glyphs with layout policy @code{whitespace}.) Then follow
+the same procedure above for inserting a glyph in a buffer, and then
+set a non-default layout policy for the glyph using
+@code{set-extent-begin-glyph-layout} or @code{set-extent-end-glyph-layout}.
+Alternatively, use the high-level annotations API (see
+@code{make-annotation}). (In point of fact, you can also use the annotations
+API for glyphs in a buffer, by setting a layout policy of @code{text}.)
+
+@item
+To insert a glyph into the modeline, just put the glyph directly as one
+of the modeline elements. (Unfortunately you can't currently put a begin
+glyph or end glyph on one of the modeline extents---they're ignored.)
+
+@item
+To insert a glyph into a toolbar, specify it as part of a toolbar
+instantiator (typically set on the specifier @code{default-toolbar}).
+See @code{default-toolbar} for more information. (Note that it is
+standard practice to use a symbol in place of the glyph list in the
+toolbar instantiator; the symbol is evalled to get the glyph list.  This
+facilitates both creating the toolbar instantiator and modifying
+individual glyphs in a toolbar later on.  For example, you can change
+the way that the Mail toolbar button looks by modifying the value of the
+variable @code{toolbar-mail-icon} (in general, @code{toolbar-*-icon})
+and then calling @code{(set-specifier-dirty-flag default-toolbar)}.
+(#### Unfortunately this doesn't quite work the way it should; the
+change will appear in new frames, but not existing ones.
+
+@item
+To insert a glyph into a gutter, create or modify a gutter instantiator
+(typically set on the specifier @code{default-gutter}).  Gutter
+instantiators consist of strings or lists of strings, so to insert a
+glyph, create an extent over the string, and use
+@code{set-extent-begin-glyph} or @code{set-extent-end-glyph} to set a
+glyph to be displayed at the corresponding edge of the extent, just like
+for glyphs in a buffer.
+
+@item
+To use a glyph as the icon for a frame, you do not actually create a new
+glyph; rather, you change the specifications for the existing glyph
+@code{frame-icon-glyph}. (Remember that, because of the specifier nature
+of glyphs, you can set different values for any particular buffer or
+frame.)
+
+@item
+To use a glyph as the mouse pointer, in general you do not create a new
+glyph, but rather you change the specifications of various existing
+glyphs, such as @code{text-pointer-glyph} for the pointer used over
+text, @code{modeline-pointer-glyph} for the pointer used over the
+modeline, etc.  Do an apropos over @code{*-pointer-glyph} to find all of
+them. (Note also that you can temporarily set the mouse pointer to some
+specific shape by using @code{set-frame-pointer}, which takes an image
+instace, as obtained from calling @code{glyph-image-instance} on a glyph
+of type @code{pointer} -- either one of the above-mentioned variables or
+one you created yourself.  (See below for what it means to create a
+glyph of type @code{pointer}.)  This pointer will last only until the
+next mouse motion event is processed or certain other things happen,
+such as creating or deleting a window. (In fact, the above-mentioned
+pointer glyph variables are implemented as part of the default handler
+for mouse motion events.  If you want to customize this behavior, take a
+look at @code{mode-motion-hook}, or @code{mouse-motion-handler} if you
+really want to get low-level.)
+
+@item
+To use a glyph to control the shape of miscellaneous redisplay effects
+such as the truncation and continuation markers, set the appropriate
+existing glyph variables, as for icons and pointers above.  See
+@code{continuation-glyph}, @code{control-arrow-glyph},
+@code{hscroll-glyph}, @code{invisible-text-glyph},
+@code{octal-escape-glyph}, and @code{truncation-glyph}.  See also
+@code{overlay-arrow-string}, an odd redisplay leftover which can be set
+to a glyph you created, and will cause the glyph to be displayed on top
+of the text position specified in the marker stored in
+@code{overlay-arrow-position}.
+
+@item
+To use a glyph in a display table (i.e. to control the appearance of any
+individual character), create the appropriate character glyphs and then
+set a specification for the specifier @code{current-display-table},
+which controls the appearance of characters.  You can also set an
+overriding display table for use with text displayed in a particular
+face; see @code{set-face-display-table} and @code{make-display-table}.
+#### Note: Display tables do not currently support general Mule
+characters.  They will be overhauled at some point to support this
+and to provide other features required under Mule.
+
+@item
+To use a glyph as the background pixmap of a face: Note that the
+background pixmap of a face is actually an image specifier -- probably
+the only place in XEmacs where an image specifier occurs outside of a
+glyph.  Similarly to how the glyph's image specifier works, you don't
+create your own image specifier, but rather add specifications to the
+existing one (using @code{set-face-background-pixmap}).  Note that the
+image instance that is generated in order to actually display the
+background pixmap is of type @code{mono-pixmap}, meaning that it's a
+two-color image and the foreground and background of the image get
+filled in with the corresponding colors from the face.
+@end itemize
+
+It is extremely rare that you will ever have to specify a value for
+TYPE, which should be one of @code{buffer} (used for glyphs in an
+extent, the modeline, the toolbar, or elsewhere in a buffer),
+@code{pointer} (used for the mouse-pointer), or @code{icon} (used for a
+frame's icon), and defaults to @code{buffer}.  The only cases where it
+needs to be specified is when creating icon or pointer glyphs, and in
+both cases the necessary glyphs have already been created at startup and
+are accessed through the appropriate variables,
+e.g. @code{text-pointer-glyph} (or in general, @code{*-pointer-glyph})
+and @code{frame-icon-glyph}.  @xref{Glyph Types}.
 @end defun
 
 @defun make-glyph-internal &optional type
@@ -78,13 +251,25 @@ This function creates a new, uninitialized glyph of type @var{type}.
 @end defun
 
 @defun make-pointer-glyph &optional spec-list
-This function is equivalent to calling @code{make-glyph} with a
-@var{type} of @code{pointer}.
+
+Return a new @code{pointer-glyph} object with the specification list
+@var{spec-list}.  This function is equivalent to calling
+@code{make-glyph} with a @var{type} of @code{pointer}.
+
+It is extremely unlikely that you will ever need to create a pointer
+glyph.  Instead, you probably want to be calling @code{set-glyph-image}
+on an existing glyph, e.g. @code{text-pointer-glyph}.
 @end defun
 
 @defun make-icon-glyph &optional spec-list
-This function is equivalent to calling @code{make-glyph} with a
-@var{type} of @code{icon}.
+
+Return a new @code{pointer-glyph} object with the specification list
+@var{spec-list}.  This function is equivalent to calling
+@code{make-glyph} with a @var{type} of @code{icon}.
+
+It is extremely unlikely that you will ever need to create a pointer
+glyph.  Instead, you probably want to be calling @code{set-glyph-image}
+on an existing glyph, e.g. @code{text-pointer-glyph}.
 @end defun
 
 @node Glyph Properties
@@ -420,10 +605,21 @@ a glyph.
 @end defun
 
 @defun make-image-specifier spec-list
-This function creates a new image specifier object and initializes
-it according to @var{spec-list}.  It is unlikely that you will ever
-want to do this, but this function is provided for completeness and
-for experimentation purposes.  @xref{Specifiers}.
+This function creates a new image specifier object and initializes it
+according to @var{spec-list}. @xref{Specifiers}.
+
+Note that, in practice, you rarely, if ever, need to actually create an
+image specifier! (This function exists mainly for completeness.) Pretty
+much the only use for image specifiers is to control how glyphs are
+displayed, and the image specifier associated with a glyph (the
+@code{image} property of a glyph) is created automatically when a glyph
+is created and need not (and cannot, for that matter) ever be changed
+(@pxref{Glyphs}).  In fact, the design decision to create a separate
+image specifier type, rather than make glyphs themselves be specifiers,
+is debatable---the other properties of glyphs are rarely used and could
+conceivably have been incorporated into the glyph's instantiator.  The
+rarely used glyph types (buffer, pointer, icon) could also have been
+incorporated into the instantiator.
 @end defun
 
   Image instantiators come in many formats: @code{xbm}, @code{xpm},
@@ -516,8 +712,49 @@ A glyph from a font; i.e. the name of a font, and glyph index into it
 of the form @samp{@var{font} fontname index [[mask-font] mask-index]}.
 Only if X support was compiled into this XEmacs.  Currently can only be
 instanced as @code{pointer}, although this should probably be fixed.
+@item mswindows-resource
+An MS Windows pointer resource.  Specifies a resource to retrieve
+directly from the system (an OEM resource) or from a file, particularly
+an executable file.  If the resource is to be retrieved from a file, use
+:file and optionally :resource-id.  Otherwise use :resource-id.  Always
+specify :resource-type to specify the type (cursor, bitmap or icon) of
+the resource.  Possible values for :resource-id are listed below.  Can
+be instanced as @code{pointer} or @code{color-pixmap}.
 @item subwindow
-An embedded X window; not currently implemented.
+An embedded windowing system window.  Can only be instanced as
+@code{subwindow}.
+@item button
+A button widget; either a push button, radio button or toggle button.
+Can only be instanced as @code{widget}.
+@item combo-box
+A drop list of selectable items in a widget, for editing text.
+Can only be instanced as @code{widget}.
+@item edit-field
+A text editing widget.  Can only be instanced as @code{widget}.
+@item label
+A static, text-only, widget; for displaying text.  Can only be instanced
+as @code{widget}.
+@item layout
+A widget for controlling the positioning of children underneath it.
+Through the use of nested layouts, a widget hierarchy can be created
+which can have the appearance of any standard dialog box or similar
+arrangement; all of this is counted as one @dfn{glyph} and could appear
+in many of the places that expect a single glyph.  Can only be instanced
+as @code{widget}.
+@item native-layout
+@c   #### Document me better!
+The native version of a layout widget.
+Can only be instanced as @code{widget}.
+@item progress-gauge
+A sliding widget, for showing progress.  Can only be instanced as
+@code{widget}.
+@item tab-control
+A tab widget; a series of user selectable tabs.  Can only be instanced
+as @code{widget}.
+@item tree-view
+A folding widget.  Can only be instanced as @code{widget}.
+@item scrollbar
+A scrollbar widget.  Can only be instanced as @code{widget}.
 @item autodetect
 XEmacs tries to guess what format the data is in.  If X support exists,
 the data string will be checked to see if it names a filename.  If so,
@@ -528,6 +765,9 @@ is one of the allowable image-instance types and the string names a
 valid cursor-font name, the image will be created as a pointer.
 Otherwise, the image will be displayed as text.  If no X support exists,
 the image will always be displayed as text.
+@item inherit
+Inherit from the background-pixmap property of a face.  Can only be
+instanced as @code{mono-pixmap}.
 @end table
 
 The valid keywords are:
@@ -587,8 +827,44 @@ specify symbolic color names to the actual color to be used for that
 symbolic color (in the form of a string or a color-specifier object).
 If this is not specified, the contents of @code{xpm-color-symbols} are
 used to generate the alist.
+@item :resource-id
+Only for @code{mswindows-resource}.  This must be either an integer
+(which directly specifies a resource number) or a string.  Valid strings
+are
+
+For bitmaps:
+
+"close", "uparrow", "dnarrow", "rgarrow", "lfarrow",
+"reduce", "zoom", "restore", "reduced", "zoomd",
+"restored", "uparrowd", "dnarrowd", "rgarrowd", "lfarrowd",
+"mnarrow", "combo", "uparrowi", "dnarrowi", "rgarrowi",
+"lfarrowi", "size", "btsize", "check", "checkboxes", and
+"btncorners".
+
+For cursors:
+
+"normal", "ibeam", "wait", "cross", "up", "sizenwse",
+"sizenesw", "sizewe", "sizens", "sizeall", and "no".
+
+For icons:
+
+"sample", "hand", "ques", "bang", "note", and "winlogo".
+@item :resource-type
+Only for @code{mswindows-resource}.  This must be a symbol, either
+@code{cursor}, @code{icon}, or @code{bitmap}, specifying the type of
+resource to be retrieved.
+@item :face
+Only for @code{inherit}.  This specifies the face to inherit from.  For
+widgets this also specifies the face to use for display. It defaults to
+gui-element-face.
 @end table
 
+Keywords accepted as menu item specs are also accepted by widgets.
+These are @code{:selected}, @code{:active}, @code{:suffix},
+@code{:keys}, @code{:style}, @code{:filter}, @code{:config},
+@code{:included}, @code{:key-sequence}, @code{:accelerator},
+@code{:label} and @code{:callback}.
+
 If instead of a vector, the instantiator is a string, it will be
 converted into a vector by looking it up according to the specs in the
 @code{console-type-image-conversion-list} for the console type of
@@ -770,10 +1046,14 @@ This function returns non-@code{nil} if @var{object} is an image
 instance of type @code{nothing}.
 @end defun
 
+@defun widget-image-instance-p object
+Return t if @var{object} is an image instance of type @code{widget}.
+@end defun
+
 @node Image Instance Functions
 @subsubsection Image Instance Functions
 
-@defun make-image-instance data &optional device dest-types no-error
+@defun make-image-instance data &optional domain dest-types no-error
 This function creates a new image-instance object.
 
 @var{data} is an image instantiator, which describes the image
@@ -789,14 +1069,47 @@ image formats, the most natural types are @code{color-pixmap}, followed
 by @code{mono-pixmap}, followed by @code{pointer}.  For the string and
 formatted-string formats, the most natural types are @code{text},
 followed by @code{mono-pixmap} (not currently implemented), followed by
-@code{color-pixmap} (not currently implemented).  The other formats can
-only be instantiated as one type. (If you want to control more
-specifically the order of the types into which an image is instantiated,
-just call @code{make-image-instance} repeatedly until it succeeds,
-passing less and less preferred destination types each time.
+@code{color-pixmap} (not currently implemented).  For MS Windows
+resources, the most natural type for pointer resources is
+@code{pointer}, and for the others it's @code{color-pixmap}.  The other
+formats can only be instantiated as one type. (If you want to control
+more specifically the order of the types into which an image is
+instantiated, just call @code{make-image-instance} repeatedly until it
+succeeds, passing less and less preferred destination types each time.
 
 If @var{dest-types} is omitted, all possible types are allowed.
 
+@var{domain} specifies the domain to which the image instance will be
+attached.  This domain is termed the @dfn{governing domain}.  The type
+of the governing domain depends on the image instantiator
+format. (Although, more correctly, it should probably depend on the
+image instance type.) For example, pixmap image instances are specific
+to a device, but widget image instances are specific to a particular
+XEmacs window because in order to display such a widget when two windows
+onto the same buffer want to display the widget, two separate underlying
+widgets must be created. (That's because a widget is actually a child
+window-system window, and all window-system windows have a unique
+existence on the screen.) This means that the governing domain for a
+pixmap image instance will be some device (most likely, the only
+existing device), whereas the governing domain for a widget image
+instance will be some XEmacs window.
+
+If you specify an overly general @var{domain} (e.g. a frame when a
+window was wanted), an error is signaled.  If you specify an overly
+specific @var{domain} (e.g. a window when a device was wanted), the
+corresponding general domain is fetched and used instead.  For
+@code{make-image-instance}, it makes no difference whether you specify
+an overly specific domain or the properly general domain derived from
+it.  However, it does matter when creating an image instance by
+instantiating a specifier or glyph (e.g. with
+@code{glyph-image-instance}), because the more specific domain causes
+spec lookup to start there and proceed to more general domains. (It
+would also matter when creating an image instance with an instantiator
+format of @code{inherit}, but we currently disallow this. #### We should
+fix this.)
+n
+If omitted, @var{domain} defaults to the selected window.
+
 @var{no-error} controls what happens when the image cannot be generated.
 If @var{nil}, an error message is generated.  If @var{t}, no messages
 are generated and this function returns @var{nil}.  If anything else, a
@@ -818,6 +1131,17 @@ returned.
 This function returns the name of the given image instance.
 @end defun
 
+@defun image-instance-domain image-instance
+
+Return the governing domain of the given @var{image-instance}.  The
+governing domain of an image instance is the domain that the image
+instance is specific to.  It is @emph{NOT} necessarily the domain that
+was given to the call to @code{specifier-instance} that resulted in the
+creation of this image instance.  See @code{make-image-instance} for
+more information on governing domains.
+@end defun
+
+
 @defun image-instance-string image-instance
 This function returns the string of the given image instance.  This will
 only be non-@code{nil} for text image instances.
index 332a960..d338082 100644 (file)
@@ -920,7 +920,7 @@ is controlled using the @code{modeline} face.  @xref{Faces}.
 
   The modeline contents are controlled by a data structure of lists,
 strings, symbols, and numbers kept in the buffer-local variable
-@code{mode-line-format}.  The data structure is called a @dfn{modeline
+@code{modeline-format}.  The data structure is called a @dfn{modeline
 construct}, and it is built in recursive fashion out of simpler modeline
 constructs.  The same data structure is used for constructing
 frame titles (@pxref{Frame Titles}).
@@ -943,8 +943,8 @@ Because of this, very few modes need to alter @code{modeline-format}.
 For most purposes, it is sufficient to alter the variables referenced by
 @code{modeline-format}.
 
-  A modeline construct may be a list, a symbol, or a string.  If the
-value is a list, each element may be a list, a symbol, or a string.
+  A modeline construct may be a string, symbol, glyph, generic
+specifier, list or cons cell.
 
 @table @code
 @cindex percent symbol in modeline
@@ -956,13 +956,22 @@ is left justified).  @xref{%-Constructs}.
 
 @item @var{symbol}
 A symbol as a modeline construct stands for its value.  The value of
-@var{symbol} is used as a modeline construct, in place of @var{symbol}.
-However, the symbols @code{t} and @code{nil} are ignored; so is any
-symbol whose value is void.
+@var{symbol} is processed as a modeline construct, in place of
+@var{symbol}.  However, the symbols @code{t} and @code{nil} are ignored;
+so is any symbol whose value is void.
 
 There is one exception: if the value of @var{symbol} is a string, it is
 displayed verbatim: the @code{%}-constructs are not recognized.
 
+@item @var{glyph}
+A glyph is displayed as is.
+
+@item @var{generic-specifier}
+A @var{generic-specifier} (i.e. a specifier of type @code{generic})
+stands for its instance.  The instance of @var{generic-specifier} is
+computed in the current window using the equivalent of
+@code{specifier-instance} and the value is processed.
+
 @item (@var{string} @var{rest}@dots{}) @r{or} (@var{list} @var{rest}@dots{})
 A list whose first element is a string or list means to process all the
 elements recursively and concatenate the results.  This is the most
@@ -987,6 +996,19 @@ if @var{width} is negative) on the right.
 
 For example, the usual way to show what percentage of a buffer is above
 the top of the window is to use a list like this: @code{(-3 "%p")}.
+
+@item (@var{extent} @var{rest}@dots{})
+
+A list whose car is an extent means the cdr of the list is processed
+normally but the results are displayed using the face of the extent, and
+mouse clicks over this section are processed using the keymap of the
+extent. (In addition, if the extent has a help-echo property, that
+string will be echoed when the mouse moves over this section.) If
+extents are nested, all keymaps are properly consulted when processing
+mouse clicks, but multiple faces are not correctly merged (only the
+first face is used), and lists of faces are not correctly handled.
+@c #### Document generate-modeline-string.
+@c See `generated-modeline-string' for more information.
 @end table
 
   If you do alter @code{modeline-format} itself, the new value should
@@ -1202,10 +1224,10 @@ The status of the subprocess belonging to the current buffer, obtained with
 
 @c The following two may only apply in XEmacs.
 @item %l
-the current line number.
+The current line number.
 
 @item %S
-the name of the selected frame; this is only meaningful under the
+The name of the selected frame; this is only meaningful under the
 X Window System.  @xref{Frame Name}.
 
 @item %t
@@ -1226,6 +1248,9 @@ visible on screen; or @samp{Bottom} or @samp{All}.
 @samp{Narrow} when narrowing is in effect; nothing otherwise (see
 @code{narrow-to-region} in @ref{Narrowing}).
 
+@item %C
+Under XEmacs/mule, the mnemonic for @code{buffer-file-coding-system}.
+
 @item %[
 An indication of the depth of recursive editing levels (not counting
 minibuffer levels): one @samp{[} for each editing level.
index 89bd121..660d251 100644 (file)
@@ -703,7 +703,7 @@ and can be used to restrict the scope of that instantiator to a
 particular device class or device type and/or to mark instantiators
 added by a particular package so that they can be later removed.
 
-A specifier tag set consists of a list of zero of more specifier tags,
+A specifier tag set consists of a list of zero or more specifier tags,
 each of which is a symbol that is recognized by XEmacs as a tag.  (The
 valid device types and device classes are always tags, as are any tags
 defined by @code{define-specifier-tag}.) It is called a ``tag set'' (as
@@ -934,11 +934,11 @@ of the symbols @code{generic}, @code{integer}, @code{natnum},
 @code{face-boolean}, or @code{toolbar}.
 
 For more information on particular types of specifiers, see the
-functions @code{generic-specifier-p}, @code{integer-specifier-p},
-@code{natnum-specifier-p}, @code{boolean-specifier-p},
-@code{color-specifier-p}, @code{font-specifier-p},
-@code{image-specifier-p}, @code{face-boolean-specifier-p}, and
-@code{toolbar-specifier-p}.
+functions @code{make-generic-specifier}, @code{make-integer-specifier},
+@code{make-natnum-specifier}, @code{make-boolean-specifier},
+@code{make-color-specifier}, @code{make-font-specifier},
+@code{make-image-specifier}, @code{make-face-boolean-specifier}, and
+@code{make-toolbar-specifier}.
 @end defun
 
 @defun make-specifier-and-init type spec-list &optional dont-canonicalize
@@ -954,6 +954,59 @@ this conversion is not performed, and the @var{spec-list} must already
 be in full form.  See @code{canonicalize-spec-list}.
 @end defun
 
+@defun make-integer-specifier spec-list
+
+Return a new @code{integer} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.
+
+Valid instantiators for integer specifiers are integers.
+@end defun
+
+@defun make-boolean-specifier spec-list
+
+Return a new @code{boolean} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.
+
+Valid instantiators for boolean specifiers are @code{t} and @code{nil}.
+@end defun
+
+@defun make-natnum-specifier spec-list
+
+Return a new @code{natnum} specifier object with the given specification
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.
+
+Valid instantiators for natnum specifiers are non-negative integers.
+@end defun
+
+@defun make-generic-specifier spec-list
+
+Return a new @code{generic} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.
+
+Valid instantiators for generic specifiers are all Lisp values.  They
+are returned back unchanged when a specifier is instantiated.
+@end defun
+
+@defun make-display-table-specifier spec-list
+
+Return a new @code{display-table} specifier object with the given spec
+list.  @var{spec-list} can be a list of specifications (each of which is
+a cons of a locale and a list of instantiators), a single instantiator,
+or a list of instantiators.
+
+Valid instantiators for display-table specifiers are described in detail
+in the doc string for @code{current-display-table} (@pxref{Active
+Display Table}).
+@end defun
+
 @node Specifier Validation Functions
 @section Functions for Checking the Validity of Specifier Components
 
index 13747cd..3d725a6 100644 (file)
@@ -9,7 +9,9 @@
 
 @menu
 * Toolbar Intro::              An introduction.
-* Toolbar Descriptor Format::  How to create a toolbar.
+* Creating Toolbar::            How to create a toolbar.
+* Toolbar Descriptor Format::  Accessing and modifying a toolbar's
+                                  properties.
 * Specifying the Toolbar::     Setting a toolbar's contents.
 * Other Toolbar Variables::    Controlling the size of toolbars.
 @end menu
@@ -57,6 +59,27 @@ from the default just sets the position-specific specifiers, and if
 the user sets the default toolbar to the same position, it will just
 not be visible.
 
+@node Creating Toolbar
+@section Creating Toolbar
+
+@defun make-toolbar-specifier spec-list
+
+Return a new @code{toolbar} specifier object with the given
+specification list.  @var{spec-list} can be a list of specifications
+(each of which is a cons of a locale and a list of instantiators), a
+single instantiator, or a list of instantiators.  @xref{Specifiers}, for
+more information about specifiers.
+
+Toolbar specifiers are used to specify the format of a toolbar.  The
+values of the variables @code{default-toolbar}, @code{top-toolbar},
+@code{left-toolbar}, @code{right-toolbar}, and @code{bottom-toolbar} are
+always toolbar specifiers.
+
+Valid toolbar instantiators are called "toolbar descriptors"
+and are lists of vectors.  See @code{default-toolbar} for a description
+of the exact format.
+@end defun
+
 @node Toolbar Descriptor Format
 @section Toolbar Descriptor Format
 
index 32cfc00..2c6f1c6 100644 (file)
@@ -1,4 +1,6 @@
-
+@c This is part of the XEmacs manual.
+@c Copyright (C) 1985, 86, 87, 93, 94, 95, 1997 Free Software Foundation, Inc.
+@c See file xemacs.texi for copying conditions.
 @node Basic, Undo, Startup Paths, Top
 @chapter Basic Editing Commands
 
@@ -7,8 +9,34 @@
   We now give the basics of how to enter text, make corrections, and
 save the text in a file.  If this material is new to you, you might
 learn it more easily by running the Emacs learn-by-doing tutorial.  To
-do this, type @kbd{Control-h t} (@code{help-with-tutorial}).
+use the tutorial, run Emacs and type @kbd{Control-h t}
+(@code{help-with-tutorial}).  You can also use @b{Tutorials} item from
+the @b{Help} menu.
+
+XEmacs comes with many translations of tutorial.  If your XEmacs is with
+MULE and you set up language environment correctly, XEmacs choses right
+tutorial when available (@pxref{Language Environments}).  If you want
+specific translation, give @kbd{C-h t} a prefix argument, like @kbd{C-u
+C-h t}.
+
+  To clear the screen and redisplay, type @kbd{C-l} (@code{recenter}).
+
+@menu
 
+* Inserting Text::      Inserting text by simply typing it.
+* Moving Point::        How to move the cursor to the place where you want to
+                         change something.
+* Erasing::            Deleting and killing text.
+* Files: Basic Files.   Visiting, creating, and saving files.
+* Help: Basic Help.     Asking what a character does.
+* Blank Lines::                Commands to make or delete blank lines.
+* Continuation Lines::  Lines too wide for the screen.
+* Position Info::       What page, line, row, or column is point on?
+* Arguments::          Numeric arguments for repeating a command.
+@c * Repeating::           A short-cut for repeating the previous command.
+@end menu
+
+@node Inserting Text, Moving Point, , Basic
 @section Inserting Text
 
 @cindex insertion
@@ -16,74 +44,92 @@ do this, type @kbd{Control-h t} (@code{help-with-tutorial}).
 @cindex cursor
 @cindex graphic characters
   To insert printing characters into the text you are editing, just type
-them.  This inserts the characters into the buffer at the cursor (that
-is, at @dfn{point}; @pxref{Point}).  The cursor moves forward.  Any
-characters after the cursor move forward too.  If the text in the buffer
-is @samp{FOOBAR}, with the cursor before the @samp{B}, and you type
-@kbd{XX}, the result is @samp{FOOXXBAR}, with the cursor still before the
-@samp{B}.
-
-@kindex DEL
+them.  This inserts the characters you type into the buffer at the
+cursor (that is, at @dfn{point}; @pxref{Point}).  The cursor moves
+forward, and any text after the cursor moves forward too.  If the text
+in the buffer is @samp{FOOBAR}, with the cursor before the @samp{B},
+then if you type @kbd{XX}, you get @samp{FOOXXBAR}, with the cursor
+still before the @samp{B}.
+
+@kindex BS
 @cindex deletion
-   To @dfn{delete} text you have just inserted, use @key{DEL}.
-@key{DEL} deletes the character @var{before} the cursor (not the one
-that the cursor is on top of or under; that is the character @var{after}
-the cursor).  The cursor and all characters after it move backwards.
-Therefore, if you type a printing character and then type @key{DEL},
-they cancel out.
+   To @dfn{delete} text you have just inserted, use @key{BS}.  @key{BS}
+deletes the character @emph{before} the cursor (not the one that the
+cursor is on top of or under; that is the character @var{after} the
+cursor).  The cursor and all characters after it move backwards.
+Therefore, if you type a printing character and then type @key{BS}, they
+cancel out.
 
 @kindex RET
 @cindex newline
    To end a line and start typing a new one, type @key{RET}.  This
 inserts a newline character in the buffer.  If point is in the middle of
 a line, @key{RET} splits the line.  Typing @key{DEL} when the cursor is
-at the beginning of a line rubs out the newline before the line, thus
-joining the line with the preceding line.
+at the beginning of a line deletes the preceding newline, thus joining
+the line with the preceding line.
 
-  Emacs automatically splits lines when they become too long, if you
-turn on a special mode called @dfn{Auto Fill} mode.  @xref{Filling}, for
-information on using Auto Fill mode.
+  Emacs can split lines automatically when they become too long, if you
+turn on a special minor mode called @dfn{Auto Fill} mode.
+@xref{Filling}, for how to use Auto Fill mode.
 
-@findex delete-backward-char
-@findex newline
-@findex self-insert
-  Customization information: @key{DEL}, in most modes, runs the command
-@code{delete-backward-char}; @key{RET} runs the command @code{newline},
-and self-inserting printing characters run the command
-@code{self-insert}, which inserts whatever character was typed to invoke
-it.  Some major modes rebind @key{DEL} to other commands.
+  If you prefer to have text characters replace (overwrite) existing
+text rather than shove it to the right, you can enable Overwrite mode,
+a minor mode.  @xref{Minor Modes}.
 
 @cindex quoting
 @kindex C-q
 @findex quoted-insert
-  Direct insertion works for printing characters and @key{SPC}, but
-other characters act as editing commands and do not insert themselves.
-If you need to insert a control character or a character whose code is
-above 200 octal, you must @dfn{quote} it by typing the character
-@kbd{control-q} (@code{quoted-insert}) first.  There are two ways to use
-@kbd{C-q}:@refill
+  Direct insertion works for printing characters and @key{SPC}, but other
+characters act as editing commands and do not insert themselves.  If you
+need to insert a control character or a character whose code is above 200
+octal, you must @dfn{quote} it by typing the character @kbd{Control-q}
+(@code{quoted-insert}) first.  (This character's name is normally written
+@kbd{C-q} for short.)  There are two ways to use @kbd{C-q}:
 
 @itemize @bullet
 @item
-@kbd{Control-q} followed by any non-graphic character (even @kbd{C-g})
+@kbd{C-q} followed by any non-graphic character (even @kbd{C-g})
 inserts that character.
+
 @item
-@kbd{Control-q} followed by three octal digits inserts the character
-with the specified character code.
+@kbd{C-q} followed by a sequence of octal digits inserts the character
+with the specified octal character code.  You can use any number of
+octal digits; any non-digit terminates the sequence.  If the terminating
+character is @key{RET}, it serves only to terminate the sequence; any
+other non-digit is itself used as input after terminating the sequence.
+(The use of octal sequences is disabled in ordinary non-binary Overwrite
+mode, to give you a convenient way to insert a digit instead of
+overwriting with it.)
 @end itemize
 
 @noindent
 A numeric argument to @kbd{C-q} specifies how many copies of the quoted
 character should be inserted (@pxref{Arguments}).
 
-  If you prefer to have text characters replace (overwrite) existing
-text instead of moving it to the right, you can enable Overwrite mode, a
-minor mode.  @xref{Minor Modes}.
+@findex backward-or-forward-delete-char
+@findex newline
+@findex self-insert
+  Customization information: @key{DEL}, in most modes, runs the command
+@code{backward-or-forward-delete-char}; @key{RET} runs the command
+@code{newline}, and self-inserting printing characters run the command
+@code{self-insert}, which inserts whatever character was typed to invoke
+it.  Some major modes rebind @key{DEL} to other commands.
 
+@node Moving Point, Erasing, Inserting Text, Basic
 @section Changing the Location of Point
 
+@cindex arrow keys
+@kindex LEFT
+@kindex RIGHT
+@kindex UP
+@kindex DOWN
+@cindex moving point
+@cindex movement
+@cindex cursor motion
+@cindex moving the cursor
   To do more than insert characters, you have to know how to move point
-(@pxref{Point}).  Here are a few of the available commands.
+(@pxref{Point}).  The simplest way to do this is with arrow keys, or by
+clicking the left mouse button where you want to move to.
 
   NOTE: Many of the following commands have two versions, one that uses
 the function keys (e.g. @key{LEFT} or @key{END}) and one that doesn't.
@@ -149,7 +195,10 @@ Move forward one word (@code{forward-word}).
 Move backward one word (@code{backward-word}).
 @item C-n
 @itemx DOWN
-Move down one line, vertically (@code{next-line}).  This command attempts to keep the horizontal position unchanged, so if you start in the middle of one line, you end in the middle of the next.  When on the last line of text, @kbd{C-n} creates a new line and moves onto it.
+Move down one line, vertically (@code{next-line}).  This command
+attempts to keep the horizontal position unchanged, so if you start in
+the middle of one line, you end in the middle of the next.  When on the
+last line of text, @kbd{C-n} creates a new line and moves onto it.
 @item C-p
 @itemx UP
 Move up one line, vertically (@code{previous-line}).
@@ -163,14 +212,16 @@ Move up one page, vertically (@code{scroll-down}).
 Clear the frame and reprint everything (@code{recenter}).  Text moves
 on the frame to bring point to the center of the window.
 @item M-r
-Move point to left margin on the line halfway down the frame or
-window (@code{move-to-window-line}).  Text does not move on the
-frame.  A numeric argument says how many screen lines down from the
-top of the window (zero for the top).  A negative argument counts from
-the bottom (@minus{}1 for the bottom).
+Move point to left margin, vertically centered in the window
+(@code{move-to-window-line}).  Text does not move on the screen.
+
+A numeric argument says which screen line to place point on.  It counts
+screen lines down from the top of the window (zero for the top line).  A
+negative argument counts lines from the bottom (@minus{}1 for the bottom
+line).
 @item C-t
 Transpose two characters, the ones before and after the cursor
-@*(@code{transpose-chars}).
+(@code{transpose-chars}).
 @item M-<
 @itemx C-HOME
 Move to the top of the buffer (@code{beginning-of-buffer}).  With
@@ -180,35 +231,46 @@ numeric argument @var{n}, move to @var{n}/10 of the way from the top.
 @itemx C-END
 Move to the end of the buffer (@code{end-of-buffer}).
 @item M-x goto-char
-Read a number @var{n} and move the cursor to character number @var{n}.
+Read a number @var{n} and move point to buffer position @var{n}.
 Position 1 is the beginning of the buffer.
 @item M-g
-Read a number @var{n} and move cursor to line number @var{n}
+Read a number @var{n} and move point to line number @var{n}
 (@code{goto-line}).  Line 1 is the beginning of the buffer.
-@item C-x C-n
+@c @item C-x C-n
+@item M-x set-goal-column
 @findex set-goal-column
 Use the current column of point as the @dfn{semi-permanent goal column} for
 @kbd{C-n} and @kbd{C-p} (@code{set-goal-column}).  Henceforth, those
 commands always move to this column in each line moved into, or as
 close as possible given the contents of the line.  This goal column remains
 in effect until canceled.
-@item C-u C-x C-n
+@c @item C-u C-x C-n
+@item C-u M-x set-goal-column
 Cancel the goal column.  Henceforth, @kbd{C-n} and @kbd{C-p} once
 again try to avoid changing the horizontal position, as usual.
 @end table
 
 @vindex track-eol
   If you set the variable @code{track-eol} to a non-@code{nil} value,
-@kbd{C-n} and @kbd{C-p} move to the end of the line when at the end of
-the starting line.  By default, @code{track-eol} is @code{nil}.
+then @kbd{C-n} and @kbd{C-p} when at the end of the starting line move
+to the end of another line.  Normally, @code{track-eol} is @code{nil}.
+@xref{Variables}, for how to set variables such as @code{track-eol}.
+
+@vindex next-line-add-newlines
+  Normally, @kbd{C-n} on the last line of a buffer appends a newline to
+it.  If the variable @code{next-line-add-newlines} is @code{nil}, then
+@kbd{C-n} gets an error instead (like @kbd{C-p} on the first line).
 
+@node Erasing, Basic Files, Moving Point, Basic
 @section Erasing Text
 
 @table @kbd
 @item @key{DEL}
-Delete the character before the cursor (@code{delete-backward-char}).
+Delete the character before or after point
+(@code{backward-or-forward-delete-char}).  You can customize
+this behavior by setting the variable @code{delete-key-deletes-forward}.
 @item C-d
-Delete the character after the cursor (@code{delete-char}).
+Delete the character after point (@code{delete-char}).
 @item C-k
 Kill to the end of the line (@code{kill-line}).
 @item M-d
@@ -218,30 +280,34 @@ Kill back to the beginning of the previous word
 (@code{backward-kill-word}).
 @end table
 
-  In contrast to the @key{DEL} key, which deletes the character before
-the cursor, @kbd{Control-d} deletes the character after the cursor,
-causing the rest of the text on the line to shift left.  If
-@kbd{Control-d} is typed at the end of a line, that line and the next
-line are joined.
-
-  To erase a larger amount of text, use @kbd{Control-k}, which kills a
-line at a time.  If you use @kbd{C-k} at the beginning or in the middle
-of a line, it kills all the text up to the end of the line.  If you use
-@kbd{C-k} at the end of a line, it joins that line and the next
-line.
+@cindex killing characters and lines
+@cindex deleting characters and lines
+@cindex erasing characters and lines
+  You already know about the @key{DEL} key which deletes the character
+before point (that is, before the cursor).  Another key, @kbd{Control-d}
+(@kbd{C-d} for short), deletes the character after point (that is, the
+character that the cursor is on).  This shifts the rest of the text on
+the line to the left.  If you type @kbd{C-d} at the end of a line, it
+joins together that line and the next line.
+
+  To erase a larger amount of text, use the @kbd{C-k} key, which kills a
+line at a time.  If you type @kbd{C-k} at the beginning or middle of a
+line, it kills all the text up to the end of the line.  If you type
+@kbd{C-k} at the end of a line, it joins that line and the next line.
 
   @xref{Killing}, for more flexible ways of killing text.
 
+@node Basic Files, Basic Help, Erasing, Basic
 @section Files
 
 @cindex files
-  The commands above are sufficient for creating and altering text in an
-Emacs buffer.  More advanced Emacs commands just make things easier.  But
-to keep any text permanently you must put it in a @dfn{file}.  Files are
-named units of text which are stored by the operating system and which
-you can retrieve by name.  To look at or use the contents of a file in
-any way, including editing the file with Emacs, you must specify the
-file name.
+  The commands described above are sufficient for creating and altering
+text in an Emacs buffer; the more advanced Emacs commands just make
+things easier.  But to keep any text permanently you must put it in a
+@dfn{file}.  Files are named units of text which are stored by the
+operating system for you to retrieve later by name.  To look at or use
+the contents of a file in any way, including editing the file with
+Emacs, you must specify the file name.
 
   Consider a file named @file{/usr/rms/foo.c}.  To begin editing
 this file from Emacs, type:
@@ -251,54 +317,51 @@ C-x C-f /usr/rms/foo.c @key{RET}
 @end example
 
 @noindent
-The file name is given as an @dfn{argument} to the command @kbd{C-x
-C-f} (@code{find-file}).  The command uses the @dfn{minibuffer} to
-read the argument.  You have to type @key{RET} to terminate the argument
-(@pxref{Minibuffer}).@refill
+Here the file name is given as an @dfn{argument} to the command @kbd{C-x
+C-f} (@code{find-file}).  That command uses the @dfn{minibuffer} to
+read the argument, and you type @key{RET} to terminate the argument
+(@pxref{Minibuffer}).
 
   You can also use the @b{Open...} menu item from the @b{File} menu, then
 type the name of the file to the prompt.
 
-  Emacs obeys the command by @dfn{visiting} the file: it creates a
-buffer, copies the contents of the file into the buffer, and then
-displays the buffer for you to edit.  You can make changes in the
-buffer, and then @dfn{save} the file by typing @kbd{C-x C-s}
-(@code{save-buffer}) or choosing @b{Save Buffer} from the @b{File} menu.
-This makes the changes permanent by copying the altered contents of the
-buffer back into the file @file{/usr/rms/foo.c}.  Until then, the
-changes are only inside your Emacs buffer, and the file @file{foo.c} is
-not changed.@refill
+  Emacs obeys the command by @dfn{visiting} the file: creating a buffer,
+copying the contents of the file into the buffer, and then displaying
+the buffer for you to edit.  If you alter the text, you can @dfn{save}
+the new text in the file by typing @kbd{C-x C-s} (@code{save-buffer}) or
+choosing @b{Save Buffer} from the @b{File} menu.  This makes the changes
+permanent by copying the altered buffer contents back into the file
+@file{/usr/rms/foo.c}.  Until you save, the changes exist only inside
+Emacs, and the file @file{foo.c} is unaltered.
 
   To create a file, visit the file with @kbd{C-x C-f} as if it already
 existed or choose @b{Open...} from the @b{File} menu and provide the
-name for the new file in the minibuffer.  Emacs will create an empty
-buffer in which you can insert the text you want to put in the file.
-When you save the buffer with @kbd{C-x C-s}, or by choosing @b{Save
-Buffer} from the @b{File} menu, the file is created.
+name for the new file.  Emacs will create an empty buffer in which you
+can insert the text you want to put in the file.  When you save the
+buffer with @kbd{C-x C-s}, or by choosing @b{Save Buffer} from the
+@b{File} menu, the file is created.
 
-  To learn more about using files, @pxref{Files}.
+  To learn more about using files, @xref{Files}.
 
+@node Basic Help, Blank Lines, Basic Files, Basic
 @section Help
 
-  If you forget what a key does, you can use the Help character
-(@kbd{C-h}) to find out: Type @kbd{C-h k} followed by the key you want
-to know about.  For example, @kbd{C-h k C-n} tells you what @kbd{C-n}
+@cindex getting help with keys
+  If you forget what a key does, you can find out with the Help
+character, which is @kbd{C-h} (or @key{F1}, which is an alias for
+@kbd{C-h}).  Type @kbd{C-h k} followed by the key you want to know
+about; for example, @kbd{C-h k C-n} tells you all about what @kbd{C-n}
 does.  @kbd{C-h} is a prefix key; @kbd{C-h k} is just one of its
 subcommands (the command @code{describe-key}).  The other subcommands of
-@kbd{C-h} provide different kinds of help.  Type @kbd{C-h} three times
-to get a description of all the help facilities.  @xref{Help}.@refill
-
-@menu
-* Blank Lines::        Commands to make or delete blank lines.
-* Continuation Lines:: Lines too wide for the frame.
-* Position Info::      What page, line, row, or column is point on?
-* Arguments::         Numeric arguments for repeating a command.
-@end menu
+@kbd{C-h} provide different kinds of help.  Type @kbd{C-h} twice to get
+a description of all the help facilities.  @xref{Help}.
 
-@node Blank Lines, Continuation Lines, Basic, Basic
+@node Blank Lines, Continuation Lines, Basic Help, Basic
 @section Blank Lines
 
-  Here are special commands and techniques for entering and removing
+@cindex inserting blank lines
+@cindex deleting blank lines
+  Here are special commands and techniques for putting in and taking out
 blank lines.
 
 @c widecommands
@@ -315,55 +378,65 @@ Delete all but one of many consecutive blank lines
 @cindex blank lines
 @findex open-line
 @findex delete-blank-lines
-  When you want to insert a new line of text before an existing line,
-you just type the new line of text, followed by @key{RET}.  If you
-prefer to create a blank line first and then insert the desired text,
-use the key @kbd{C-o} (@code{open-line}), which inserts a newline after
-point but leaves point in front of the newline.  Then type
-the text into the new line.  @kbd{C-o F O O} has the same effect as
-@kbd{F O O @key{RET}}, except for the final location of point.
-
-  To create several blank lines, type @kbd{C-o} several times, or
-give @kbd{C-o} an argument indicating how many blank lines to create.
-@xref{Arguments}, for more information.
-
-  If you have many blank lines in a row and want to get rid of them, use
-@kbd{C-x C-o} (@code{delete-blank-lines}).  If point is on a blank
-line which is adjacent to at least one other blank line, @kbd{C-x C-o}
-deletes all but one of the blank lines.
-If point is on a blank line with no other adjacent blank line, the
-sole blank line is deleted.  If point is on a non-blank
-line, @kbd{C-x C-o} deletes any blank lines following that non-blank
-line.
+  When you want to insert a new line of text before an existing line, you
+can do it by typing the new line of text, followed by @key{RET}.
+However, it may be easier to see what you are doing if you first make a
+blank line and then insert the desired text into it.  This is easy to do
+using the key @kbd{C-o} (@code{open-line}), which inserts a newline
+after point but leaves point in front of the newline.  After @kbd{C-o},
+type the text for the new line.  @kbd{C-o F O O} has the same effect as
+@w{@kbd{F O O @key{RET}}}, except for the final location of point.
+
+  You can make several blank lines by typing @kbd{C-o} several times, or
+by giving it a numeric argument to tell it how many blank lines to make.
+@xref{Arguments}, for how.  If you have a fill prefix, then @kbd{C-o}
+command inserts the fill prefix on the new line, when you use it at the
+beginning of a line.  @xref{Fill Prefix}.
+
+  The easy way to get rid of extra blank lines is with the command
+@kbd{C-x C-o} (@code{delete-blank-lines}).  @kbd{C-x C-o} in a run of
+several blank lines deletes all but one of them.  @kbd{C-x C-o} on a
+solitary blank line deletes that blank line.  When point is on a
+nonblank line, @kbd{C-x C-o} deletes any blank lines following that
+nonblank line.
 
 @node Continuation Lines, Position Info, Blank Lines, Basic
 @section Continuation Lines
 
 @cindex continuation line
-  If you add too many characters to one line without breaking with a
-@key{RET}, the line grows to occupy two (or more) screen lines, with a
-curved arrow at the extreme right margin of all but the last line.  The
-curved arrow indicates that the following screen line is not really a
-distinct line in the text, but just the @dfn{continuation} of a line too
-long to fit the frame.  You can use Auto Fill mode (@pxref{Filling})
-to have Emacs insert newlines automatically when a line gets too long.
-
+@cindex wrapping
+@cindex line wrapping
+  If you add too many characters to one line without breaking it with
+@key{RET}, the line will grow to occupy two (or more) lines on the
+screen, with a curved arrow at the extreme right margin of all but the
+last of them.  The curved arrow says that the following screen line is
+not really a distinct line in the text, but just the @dfn{continuation}
+of a line too long to fit the screen.  Continuation is also called
+@dfn{line wrapping}.
+
+  Sometimes it is nice to have Emacs insert newlines automatically when
+a line gets too long.  Continuation on the screen does not do that.  Use
+Auto Fill mode (@pxref{Filling}) if that's what you want.
 
 @vindex truncate-lines
 @cindex truncation
   Instead of continuation, long lines can be displayed by @dfn{truncation}.
 This means that all the characters that do not fit in the width of the
 frame or window do not appear at all.  They remain in the buffer,
-temporarily invisible.  Three diagonal dots in the last column (instead of
-the curved arrow inform you that truncation is in effect.
+temporarily invisible.  Right arrow in the last column (instead of the
+curved arrow) inform you that truncation is in effect.
+
+  Truncation instead of continuation happens whenever horizontal
+scrolling is in use, and optionally in all side-by-side windows
+(@pxref{Windows}).  You can enable truncation for a particular buffer by
+setting the variable @code{truncate-lines} to non-@code{nil} in that
+buffer.  (@xref{Variables}.)  Altering the value of
+@code{truncate-lines} makes it local to the current buffer; until that
+time, the default value is in effect.  The default is initially
+@code{nil}.  @xref{Locals}.
 
-  To turn off continuation for a particular buffer, set the
-variable @code{truncate-lines} to non-@code{nil} in that buffer.
-Truncation instead of continuation also happens whenever horizontal
-scrolling is in use, and optionally whenever side-by-side windows are in
-use (@pxref{Windows}).  Altering the value of @code{truncate-lines} makes
-it local to the current buffer; until that time, the default value is in
-effect.  The default is initially @code{nil}.  @xref{Locals}.@refill
+  @xref{Display Vars}, for additional variables that affect how text is
+displayed.
 
 @node Position Info, Arguments, Continuation Lines, Basic
 @section Cursor Position Information
@@ -380,9 +453,12 @@ information, it is not displayed all the time.
 Print page number of point, and line number within page.
 @item M-x what-line
 Print line number of point in the buffer.
+@item M-x line-number-mode
+Toggle automatic display of current line number.
 @item M-=
-Print number of lines and characters in the current region 
-(@code{count-lines-region}).
+Print number of lines and characters in the current region
+(@code{count-lines-region}).  @xref{Mark}, for information about the
+region.
 @item C-x =
 Print character code of character after point, character position of
 point, and column of point (@code{what-cursor-position}).
@@ -396,6 +472,7 @@ point, and column of point (@code{what-cursor-position}).
 @findex count-lines-region
 
   There are several commands for printing line numbers:
+
 @itemize @bullet
 @item
 @kbd{M-x what-line} counts lines from the beginning of the file and
@@ -407,26 +484,28 @@ goto-line}.
 counts lines within the page, printing both of them.  @xref{Pages}, for
 the command @kbd{C-x l}, which counts the lines in the current page.
 @item
-@kbd{M-=} (@code{count-lines-region}) prints the number of lines in
-the region (@pxref{Mark}).
+@kbd{M-=} (@code{count-lines-region}) prints the number of lines in the
+region (@pxref{Mark}).  @xref{Pages}, for the command @kbd{C-x l} which
+counts the lines in the
 @end itemize
 
 @kindex C-x =
 @findex what-cursor-position
-  The command @kbd{C-x =} (@code{what-cursor-position}) provides
-information about point and about the column the cursor is in.
-It prints a line in the echo area that looks like this:
+  The command @kbd{C-x =} (@code{what-cursor-position}) can be used to find out
+the column that the cursor is in, and other miscellaneous information about
+point.  It prints a line in the echo area that looks like this:
 
 @example
-Char: x (0170)  point=65986 of 563027(12%)  column 44
+Char: c (0143, 99, 0x63)  point=18862 of 24800(76%)  column 53 
 @end example
 
 @noindent
-(In fact, this is the output produced when point is before @samp{column 44}
-in the example.)
+(In fact, this is the output produced when point is before @samp{column
+53} in the example.)
 
-  The two values after @samp{Char:} describe the character following point,
-first by showing it and second by giving its octal character code.
+  The four values after @samp{Char:} describe the character that follows
+point, first by showing it and then by giving its character code in
+octal, decimal and hex. 
 
   @samp{point=} is followed by the position of point expressed as a character
 count.  The front of the buffer counts as position 1, one character later
@@ -434,8 +513,8 @@ as 2, and so on.  The next, larger number is the total number of characters
 in the buffer.  Afterward in parentheses comes the position expressed as a
 percentage of the total size.
 
-  @samp{column} is followed by the horizontal position of point, in columns
-from the left edge of the window.
+  @samp{column} is followed by the horizontal position of point, in
+columns from the left edge of the window.
 
   If the buffer has been narrowed, making some of the text at the
 beginning and the end temporarily invisible, @kbd{C-x =} prints
@@ -443,7 +522,7 @@ additional text describing the current visible range.  For example, it
 might say:
 
 @smallexample
-Char: x (0170)  point=65986 of 563025(12%) <65102 - 68533>  column 44
+Char: c (0143, 99, 0x63)  point=19674 of 24575(80%) <19591 - 19703>  column 69 
 @end smallexample
 
 @noindent
@@ -463,12 +542,15 @@ point=563026 of 563025(100%)  column 0
 @section Numeric Arguments
 @cindex numeric arguments
 
-  Any Emacs command can be given a @dfn{numeric argument}.  Some commands
-interpret the argument as a repetition count.  For example, giving an
-argument of ten to the key @kbd{C-f} (the command @code{forward-char}, move
-forward one character) moves forward ten characters.  With these commands,
-no argument is equivalent to an argument of one.  Negative arguments are
-allowed.  Often they tell a command to move or act backwards.
+  In mathematics and computer usage, the word @dfn{argument} means
+``data provided to a function or operation.''  Any Emacs command can be
+given a @dfn{numeric argument} (also called a @dfn{prefix argument}).
+Some commands interpret the argument as a repetition count.  For
+example, giving an argument of ten to the key @kbd{C-f} (the command
+@code{forward-char}, move forward one character) moves forward ten
+characters.  With these commands, no argument is equivalent to an
+argument of one.  Negative arguments are allowed.  Often they tell a
+command to move or act  in the opposite direction.
 
 @kindex M-1
 @kindex M-@t{-}
@@ -482,18 +564,21 @@ minus sign while holding down the @key{META} key.  For example,
 M-5 C-n
 @end example
 @noindent
-moves down five lines.  The characters @kbd{Meta-1}, @kbd{Meta-2}, and
-so on, as well as @kbd{Meta--}, do this because they are keys bound to
-commands (@code{digit-argument} and @code{negative-argument}) that are
-defined to contribute to an argument for the next command.
+would move down five lines.  The characters @kbd{Meta-1}, @kbd{Meta-2},
+and so on, as well as @kbd{Meta--}, do this because they are keys bound
+to commands (@code{digit-argument} and @code{negative-argument}) that
+are defined to contribute to an argument for the next command.  Digits
+and @kbd{-} modified with Control, or Control and Meta, also specify
+numeric arguments.
 
 @kindex C-u
 @findex universal-argument
   Another way of specifying an argument is to use the @kbd{C-u}
-(@code{universal-argument}) command followed by the digits of the argument.
-With @kbd{C-u}, you can type the argument digits without holding
-down shift keys.  To type a negative argument, start with a minus sign.
-Just a minus sign normally means @minus{}1.  @kbd{C-u} works on all terminals.
+(@code{universal-argument}) command followed by the digits of the
+argument.  With @kbd{C-u}, you can type the argument digits without
+holding down modifier keys; @kbd{C-u} works on all terminals.  To type a
+negative argument, type a minus sign after @kbd{C-u}.  Just a minus sign
+without digits normally means @minus{}1.
 
   @kbd{C-u} followed by a character which is neither a digit nor a minus
 sign has the special meaning of ``multiply by four''.  It multiplies the
@@ -503,7 +588,7 @@ is a good way to move forward ``fast'', since it moves about 1/5 of a line
 in the usual size frame.  Other useful combinations are @kbd{C-u C-n},
 @kbd{C-u C-u C-n} (move down a good fraction of a frame), @kbd{C-u C-u
 C-o} (make ``a lot'' of blank lines), and @kbd{C-u C-k} (kill four
-lines).@refill
+lines).
 
   Some commands care only about whether there is an argument and not about
 its value.  For example, the command @kbd{M-q} (@code{fill-paragraph}) with
@@ -519,32 +604,47 @@ special: it kills the text up to the next newline, or, if point is right at
 the end of the line, it kills the newline itself.  Thus, two @kbd{C-k}
 commands with no arguments can kill a non-blank line, just like @kbd{C-k}
 with an argument of one.  (@xref{Killing}, for more information on
-@kbd{C-k}.)@refill
+@kbd{C-k}.)
 
   A few commands treat a plain @kbd{C-u} differently from an ordinary
 argument.  A few others may treat an argument of just a minus sign
-differently from an argument of @minus{}1.  These unusual cases will be
-described when they come up; they are always to make the individual
-command more convenient to use.
+differently from an argument of @minus{}1.  These unusual cases are
+described when they come up; they are always for reasons of convenience
+of use of the individual command.
+
+  You can use a numeric argument to insert multiple copies of a
+character.  This is straightforward unless the character is a digit; for
+example, @kbd{C-u 6 4 a} inserts 64 copies of the character @samp{a}.
+But this does not work for inserting digits; @kbd{C-u 6 4 1} specifies
+an argument of 641, rather than inserting anything.  To separate the
+digit to insert from the argument, type another @kbd{C-u}; for example,
+@kbd{C-u 6 4 C-u 1} does insert 64 copies of the character @samp{1}.
+
+  We use the term ``prefix argument'' as well as ``numeric argument'' to
+emphasize that you type the argument before the command, and to
+distinguish these arguments from minibuffer arguments that come after
+the command.
 
-@c section Autoarg Mode
 @ignore
-@cindex autoarg mode
-  Users of ASCII keyboards may prefer to use Autoarg mode.  Autoarg mode
-means that you don't need to type @kbd{C-u} to specify a numeric argument.
-Instead, you type just the digits.  Digits followed by an ordinary
-inserting character are themselves inserted, but digits followed by an
-Escape or Control character serve as an argument to it and are not
-inserted.  A minus sign can also be part of an argument, but only at the
-beginning.  If you type a minus sign following some digits, both the digits
-and the minus sign are inserted.
-
-  To use Autoarg mode, set the variable Autoarg Mode nonzero.
-@xref{Variables}.
-
-  Autoargument digits echo at the bottom of the frame; the first
-nondigit causes them to be inserted or uses them as an argument.  To
-insert some digits and nothing else, you must follow them with a Space
-and then rub it out.  @kbd{C-g} cancels the digits, while Delete inserts
-them all and then rubs out the last.
+@node Repeating
+@section Repeating a Command
+@cindex repeating a command
+
+@kindex C-x z
+@findex repeat
+  The command @kbd{C-x z} (@code{repeat}) provides another way to repeat
+an Emacs command many times.  This command repeats the previous Emacs
+command, whatever that was.  Repeating a command uses the same arguments
+that were used before; it does not read new arguments each time.
+
+  To repeat the command more than once, type additional @kbd{z}'s: each
+@kbd{z} repeats the command one more time.  Repetition ends when you
+type a character other than @kbd{z}, or press a mouse button.
+
+  For example, suppose you type @kbd{C-u 2 0 C-d} to delete 20
+characters.  You can repeat that command (including its argument) three
+additional times, to delete a total of 80 characters, by typing @kbd{C-x
+z z z}.  The first @kbd{C-x z} repeats the command once, and each
+subsequent @kbd{z} repeats it once again.
+
 @end ignore
index 2c9b33c..00d45ae 100644 (file)
@@ -1,53 +1,91 @@
-
+@c This is part of the XEmacs manual.
+@c Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c See file xemacs.texi for copying conditions.
 @node Entering Emacs, Exiting, Pull-down Menus, Top
 @chapter Entering and Exiting Emacs
-@cindex entering Emacs
 @cindex entering XEmacs
+@cindex starting XEmacs
 
-  The usual way to invoke Emacs is to type @kbd{emacs @key{RET}} at the
-shell (for XEmacs, type @kbd{xemacs @key{RET}}).  Emacs clears the
-screen and then displays an initial advisory message and copyright
-notice.  You can begin typing Emacs commands immediately afterward.
+  The usual way to invoke XEmacs is to type @kbd{xemacs @key{RET}} at
+the shell.  XEmacs clears the screen and then displays an initial
+advisory message and copyright notice.  You can begin typing XEmacs
+commands immediately afterward.
 
-  Some operating systems insist on discarding all type-ahead when Emacs
-starts up; they give Emacs no way to prevent this.  Therefore, it is
-wise to wait until Emacs clears the screen before typing the first
+  Some operating systems insist on discarding all type-ahead when XEmacs
+starts up; they give XEmacs no way to prevent this.  Therefore, it is
+advisable to wait until XEmacs clears the screen before typing your first
 editing command.
 
+  If you run XEmacs from a shell window under the X Window System, run it
+in the background with @samp{xemacs&}.  This way, XEmacs does not tie up
+the shell window, so you can use that to run other shell commands while
+XEmacs operates its own X windows.  You can begin typing XEmacs commands
+as soon as you direct your keyboard input to the XEmacs frame.
+
 @vindex initial-major-mode
   Before Emacs reads the first command, you have not had a chance to
-give a command to specify a file to edit.  Since Emacs must always have a
-current buffer for editing, it presents a buffer, by default, a buffer named
-@samp{*scratch*}.  The buffer is in Lisp Interaction
-mode; you can use it to type Lisp expressions and evaluate them, or you
-can ignore that capability and simply doodle.  You can specify a
-different major mode for this buffer by setting the variable
-@code{initial-major-mode} in your init file.  @xref{Init File}.
+give a command to specify a file to edit.  Since Emacs must always have
+a current buffer for editing, it presents a buffer, by default, a buffer
+named @samp{*scratch*}.  The buffer is in Lisp Interaction mode; you can
+use it to type Lisp expressions and evaluate them, or you can ignore
+that capability and simply doodle.  (You can specify a different major
+mode for this buffer by setting the variable @code{initial-major-mode}
+in your init file.  @xref{Init File}.)
+
+  It is possible to specify files to be visited, Lisp files to be
+loaded, and functions to be called, by giving Emacs arguments in the
+shell command line.  @xref{Command Switches}.  But we don't recommend
+doing this.  The feature exists mainly for compatibility with other
+editors.
 
-  It is possible to give Emacs arguments in the shell command line to
-specify files to visit, Lisp files to load, and functions to call.
+  Many other editors are designed to be started afresh each time you
+want to edit.  You edit one file and then exit the editor.  The next
+time you want to edit either another file or the same one, you must run
+the editor again.  With these editors, it makes sense to use a
+command-line argument to say which file to edit.
+
+  But starting a new Emacs each time you want to edit a different file
+does not make sense.  For one thing, this would be annoyingly slow.  For
+another, this would fail to take advantage of Emacs's ability to visit
+more than one file in a single editing session.  And it would lose the
+other accumulated context, such as registers, undo history, and the mark
+ring.
+
+  The recommended way to use XEmacs is to start it only once, just
+after you log in, and do all your editing in the same Emacs session.
+Each time you want to edit a different file, you visit it with the
+existing Emacs, which eventually comes to have many files in it ready
+for editing.  Usually you do not kill the Emacs until you are about to
+log out.  @xref{Files}, for more information on visiting more than one
+file.
 
 @node Exiting, Command Switches, Entering Emacs, Top
 @section Exiting Emacs
 @cindex exiting
 @cindex killing Emacs
 @cindex suspending
+@cindex leaving Emacs
+@cindex quitting Emacs
 @cindex shrinking XEmacs frame
 
   There are two commands for exiting Emacs because there are two kinds
 of exiting: @dfn{suspending} Emacs and @dfn{killing} Emacs.
-@dfn{Suspending} means stopping Emacs temporarily and returning control
-to its superior (usually the shell), allowing you to resume editing
-later in the same Emacs job, with the same files, same kill ring, same
-undo history, and so on.  This is the usual way to exit.  @dfn{Killing}
-Emacs means destroying the Emacs job.  You can run Emacs again later,
-but you will get a fresh Emacs; there is no way to resume the same
-editing session after it has been killed.
+
+  @dfn{Suspending} means stopping Emacs temporarily and returning
+control to its parent process (usually a shell), allowing you to resume
+editing later in the same Emacs job, with the same buffers, same kill
+ring, same undo history, and so on.  This is the usual way to exit.
+
+  @dfn{Killing} Emacs means destroying the Emacs job.  You can run Emacs
+again later, but you will get a fresh Emacs; there is no way to resume
+the same editing session after it has been killed.
 
 @table @kbd
 @item C-z
-Suspend Emacs (@code{suspend-emacs}).  If used under the X window system,
-shrink the X window containing the Emacs frame to an icon (see below).
+Suspend Emacs or iconify a frame
+(@code{suspend-emacs-or-iconify-frame}).  If used under the X window
+system, shrink the X window containing the Emacs frame to an icon (see
+below).
 @item C-x C-c
 Kill Emacs (@code{save-buffers-kill-emacs}).
 @end table
@@ -56,45 +94,68 @@ If you use XEmacs under the X window system, @kbd{C-z} shrinks
 the X window containing the Emacs frame to an icon.  The Emacs process
 is stopped temporarily, and control is returned to the window manager.
 If more than one frame is associated with the Emacs process, only the
-frame from which you used @kbd{C-z} is retained.  The X windows
-containing the other Emacs frames are closed. 
+frame from which you used @kbd{C-z} is iconified.
 
 To activate the "suspended" Emacs, use the appropriate window manager
 mouse gestures.  Usually left-clicking on the icon reactivates and
 reopens the X window containing the Emacs frame, but the window manager
 you use determines what exactly happens.  To actually kill the Emacs
-process, use @kbd{C-x C-c} or the @b{Exit Emacs} item on the @b{File}
+process, use @kbd{C-x C-c} or the @b{Exit XEmacs} item on the @b{File}
 menu.
 
 @kindex C-z
 @findex suspend-emacs
-  On systems that do not permit programs to be suspended, @kbd{C-z} runs
-an inferior shell that communicates directly with the terminal, and
-Emacs waits until you exit the subshell.  On these systems, the only way
-to return to the shell from which Emacs was started (to log out, for
-example) is to kill Emacs.  @kbd{C-d} or @code{exit} are typical
-commands to exit a subshell.
+  To suspend Emacs, type @kbd{C-z} (@code{suspend-emacs}).  This takes
+you back to the shell from which you invoked Emacs.  You can resume
+Emacs with the shell command @samp{%xemacs} in most common shells.
+
+  On systems that do not support suspending programs, @kbd{C-z} starts
+an inferior shell that communicates directly with the terminal.
+Emacs waits until you exit the subshell.  (The way to do that is
+probably with @kbd{C-d} or @samp{exit}, but it depends on which shell
+you use.)  The only way on these systems to get back to the shell from
+which Emacs was run (to log out, for example) is to kill Emacs.
+
+  Suspending also fails if you run Emacs under a shell that doesn't
+support suspending programs, even if the system itself does support it.
+In such a case, you can set the variable @code{cannot-suspend} to a
+non-@code{nil} value to force @kbd{C-z} to start an inferior shell.
+(One might also describe Emacs's parent shell as ``inferior'' for
+failing to support job control properly, but that is a matter of taste.)
+
+  When Emacs communicates directly with an X server and creates its own
+dedicated X windows, @kbd{C-z} has a different meaning.  Suspending an
+applications that uses its own X windows is not meaningful or useful.
+Instead, @kbd{C-z} runs the command @code{iconify-or-deiconify-frame},
+which temporarily closes up the selected Emacs frame.
+The way to get back to a shell window is with the window manager.
 
 @kindex C-x C-c
 @findex save-buffers-kill-emacs
   To kill Emacs, type @kbd{C-x C-c} (@code{save-buffers-kill-emacs}).  A
-two-character key is used for this to make it harder to type.  In
-XEmacs, selecting the @b{Exit Emacs} option of the @b{File} menu is an
-alternate way of issuing the command.
+two-character key is used for this to make it harder to type.  Selecting
+the @b{Exit XEmacs} option of the @b{File} menu is an alternate way of
+issuing the command.
 
 Unless a numeric argument is used, this command first offers to save any
-modified buffers.  If you do not save all buffers, you are asked for
-reconfirmation with @kbd{yes} before killing Emacs, since any changes
-not saved will be lost.  If any subprocesses are still running, @kbd{C-x
-C-c} asks you to confirm killing them, since killing Emacs kills the
-subprocesses simultaneously.
-
-  In most programs running on Unix, certain characters may instantly
-suspend or kill the program.  (In Berkeley Unix these characters are
-normally @kbd{C-z} and @kbd{C-c}.)  @i{This Unix feature is turned off
-while you are in Emacs.} The meanings of @kbd{C-z} and @kbd{C-x C-c} as
-keys in Emacs were inspired by the standard Berkeley Unix meanings of
-@kbd{C-z} and @kbd{C-c}, but that is their only relationship with Unix.
-You could customize these keys to do anything (@pxref{Keymaps}).
-
-@c ??? What about system V here?
+modified file-visiting buffers.  If you do not save all buffers, you are
+asked for reconfirmation with @kbd{yes} before killing Emacs, since any
+changes not saved will be lost forever.  If any subprocesses are still
+running, @kbd{C-x C-c} asks you to confirm killing them, since killing
+Emacs will kill the subprocesses immediately.
+
+  There is no way to restart an Emacs session once you have killed it.
+You can, however, arrange for Emacs to record certain session
+information, such as which files are visited, when you kill it, so that
+the next time you restart Emacs it will try to visit the same files and
+so on.
+@c @xref{Saving Emacs Sessions}.
+
+  The operating system usually listens for certain special characters
+whose meaning is to kill or suspend the program you are running.
+@b{This operating system feature is turned off while you are in Emacs.}
+The meanings of @kbd{C-z} and @kbd{C-x C-c} as keys in Emacs were
+inspired by the use of @kbd{C-z} and @kbd{C-c} on several operating
+systems as the characters for stopping or killing a program, but that is
+their only relationship with the operating system.  You can customize
+these keys to run any commands of your choice (@pxref{Keymaps}).
index 3d75b35..3976ba6 100644 (file)
@@ -135,7 +135,10 @@ argument.  @xref{Windows}.
 however.  You cannot switch buffers in it---the minibuffer and its
 window are permanently attached.  Also, you cannot split or kill the
 minibuffer window. But you can make it taller in the normal fashion with
-@kbd{C-x ^}.
+@kbd{C-x ^}.  If you enable Resize-Minibuffer mode, then the
+minibuffer window expands vertically as necessary to hold the text that
+you put in the minibuffer.  Use @kbd{M-x resize-minibuffer-mode} to
+enable or disable this minor mode (@pxref{Minor Modes}).
 
 @kindex C-M-v
   If while in the minibuffer you issue a command that displays help text
@@ -227,7 +230,7 @@ possibilities for the very next character---it could be any of
 @samp{c-}---so no more characters are added; instead, @key{TAB}
 displays a list of all possible completions in another window.
 
-  If you go on to type @kbd{f @key{TAB}}, this @key{TAB} sees
+  If you go on to type @kbd{-f @key{TAB}}, this @key{TAB} sees
 @samp{auto-f}.  The only command name starting this way is
 @code{auto-fill-mode}, so completion fills in the rest of that.  You now
 have @samp{auto-fill-mode} in the minibuffer after typing just @kbd{au
@@ -285,6 +288,15 @@ completions chooses that completion (@code{mouse-choose-completion}).
 You normally use this command while point is in the minibuffer; but you
 must click in the list of completions, not in the minibuffer itself.
 
+@findex switch-to-completions
+@item @key{PRIOR}
+@itemx M-v
+Typing @key{PRIOR} or @kbd{M-v}, while in the minibuffer, selects the
+window showing the completion list buffer
+(@code{switch-to-completions}).  This paves the way for using the
+commands below.  (Selecting that window in the usual ways has the same
+effect, but this way is more convenient.)
+
 @findex choose-completion
 @item @key{RET}
 Typing @key{RET} @emph{in the completion list buffer} chooses the
@@ -375,6 +387,12 @@ then in contexts where @code{completing-read} allows answers that are
 not valid completions, an extra @key{RET} must be typed to confirm the
 response.  This is helpful for catching typos.
 
+@cindex Icomplete mode
+  Icomplete mode presents a constantly-updated display that tells you
+what completions are available for the text you've entered so far.  The
+command to enable or disable this minor mode is @kbd{M-x
+icomplete-mode}.
+
 @node Minibuffer History, Repetition, Completion, Minibuffer
 @section Minibuffer History
 @cindex minibuffer history
@@ -479,11 +497,11 @@ the command name.
 @item C-x @key{ESC} @key{ESC}
 Re-execute a recent minibuffer command (@code{repeat-complex-command}).
 @item M-p
-Within @kbd{C-x @key{ESC}}, move to previous recorded command
+Within @kbd{C-x @key{ESC} @key{ESC}}, move to previous recorded command
 (@code{previous-history-element}).
 @item M-n
-Within @kbd{C-x @key{ESC}}, move to the next (more recent) recorded
-command (@code{next-history-element}).
+Within @kbd{C-x @key{ESC} @key{ESC}}, move to the next (more recent)
+recorded command (@code{next-history-element}).
 @item M-x list-command-history
 Display the entire command history, showing all the commands
 @kbd{C-x @key{ESC} @key{ESC}} can repeat, most recent first.
index 263feb5..3fca5ee 100644 (file)
@@ -158,16 +158,6 @@ variable @code{INFOPATH}
 @vindex INFOPATH
 to @code{Info-directory-list}.
 
-@item lock-directory
-@itemx superlock-file
-@vindex lock-directory
-@vindex superlock-file
-Are the site-specific locations of the lock directory and the superlock
-file, respectively.  The @code{lock-directory} variable may also be
-initialized from the @code{EMACSLOCKDIR}
-@vindex EMACSLOCKDIR
-environment variable.
-
 @item exec-directory
 @vindex exec-directory
 Is the directory of architecture-dependent files that come with XEmacs,
index b8bbb4d..3d55b83 100644 (file)
@@ -1,3 +1,11 @@
+2000-05-28  Martin Buchholz <martin@xemacs.org>
+
+       * XEmacs 21.2.34 is released.
+
+2000-05-12  Craig Lanning  <CraigL@DyCon.com>
+
+       * inc\sys\socket.h: Don't define timeval as ws_timeval for mingw32
+
 2000-05-01  Martin Buchholz <martin@xemacs.org>
 
        * XEmacs 21.2.33 is released.
index 7e44f9e..1ce04b0 100644 (file)
@@ -188,7 +188,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you
   char *bufptr = buf;
   int bufsize = 16384;
   int speccount = specpdl_depth ();
-  struct gcpro gcpro1, gcpro2;
+  struct gcpro gcpro1, gcpro2, gcpro3;
   char **new_argv = alloca_array (char *, max (2, nargs - 2));
 
   /* File to use for stderr in the child.
@@ -235,7 +235,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you
     NUNGCPRO;
   }
 
-  GCPRO1 (current_dir);
+  GCPRO2 (current_dir, path);
 
   if (nargs >= 2 && ! NILP (args[1]))
     {
@@ -250,7 +250,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you
 
   UNGCPRO;
 
-  GCPRO2 (infile, current_dir);                /* Fexpand_file_name might trash it */
+  GCPRO3 (infile, current_dir, path);          /* Fexpand_file_name might trash it */
 
   if (nargs >= 3)
     {
index eba7f4d..e015320 100644 (file)
@@ -121,6 +121,10 @@ You should almost certainly not be using this.
   stderr_out ("*** Backtrace\n");
   Fbacktrace (Qexternal_debugging_output, Qt);
   stderr_out ("*** Killing XEmacs\n");
+#ifdef HAVE_MS_WINDOWS
+  Fmswindows_message_box (build_string ("Initialization error"),
+                         Qnil, Qnil);
+#endif
   return Fkill_emacs (make_int (-1));
 }
 
index 0eb61e1..df68e17 100644 (file)
@@ -28,14 +28,51 @@ Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include "lisp.h"
-#include "events.h"
-#include "opaque.h"
 
+#include "buffer.h"
 #include "console-msw.h"
+#include "events.h"
+#include "opaque.h"
 
 DEFINE_CONSOLE_TYPE (mswindows);
 DEFINE_CONSOLE_TYPE (msprinter);
 
+Lisp_Object Qabortretryignore;
+Lisp_Object Qapplmodal;
+Lisp_Object Qdefault_desktop_only;
+Lisp_Object Qdefbutton1;
+Lisp_Object Qdefbutton2;
+Lisp_Object Qdefbutton3;
+Lisp_Object Qdefbutton4;
+/* Lisp_Object Qhelp; */
+Lisp_Object Qiconasterisk;
+Lisp_Object Qiconexclamation;
+Lisp_Object Qiconhand;
+Lisp_Object Qiconinformation;
+Lisp_Object Qiconquestion;
+Lisp_Object Qiconstop;
+/* Lisp_Object Qok; */
+Lisp_Object Qokcancel;
+Lisp_Object Qretrycancel;
+/* Lisp_Object Qright; */
+Lisp_Object Qrtlreading;
+Lisp_Object Qservice_notification;
+Lisp_Object Qsetforeground;
+Lisp_Object Qsystemmodal;
+Lisp_Object Qtaskmodal;
+Lisp_Object Qtopmost;
+Lisp_Object Qyesno;
+Lisp_Object Qyesnocancel;
+
+/* Lisp_Object Qabort; */
+/* Lisp_Object Qcancel; */
+/* Lisp_Object Qignore; */
+/* Lisp_Object Qno; */
+/* Lisp_Object Qok; */
+/* Lisp_Object Qretry; */
+/* Lisp_Object Qyes; */
+
+
 /************************************************************************/
 /*                       mswindows console methods                      */
 /************************************************************************/
@@ -261,6 +298,242 @@ DSYMNAME (Lisp_Object obj)
 
 #endif /* DEBUG_XEMACS */
 
+DEFUN ("mswindows-message-box", Fmswindows_message_box, 1, 3, 0, /*
+Pop up an MS Windows message box.
+MESSAGE is the string to display.  Optional argument FLAG controls
+what appears in the box and how it behaves; it is a symbol or list of
+symbols, described below.  Second optional argument TITLE controls the
+title bar; if omitted, a standard title bar will be used, probably
+displaying "XEmacs".
+
+Possible flags are
+
+
+-- To specify the buttons in the message box:
+
+abortretryignore 
+  The message box contains three push buttons: Abort, Retry, and Ignore. 
+ok 
+  The message box contains one push button: OK. This is the default. 
+okcancel 
+  The message box contains two push buttons: OK and Cancel. 
+retrycancel 
+  The message box contains two push buttons: Retry and Cancel. 
+yesno 
+  The message box contains two push buttons: Yes and No. 
+yesnocancel 
+  The message box contains three push buttons: Yes, No, and Cancel. 
+
+
+-- To display an icon in the message box:
+iconexclamation, iconwarning
+  An exclamation-point icon appears in the message box. 
+iconinformation, iconasterisk
+  An icon consisting of a lowercase letter i in a circle appears in
+  the message box. 
+iconquestion
+  A question-mark icon appears in the message box. 
+iconstop, iconerror, iconhand
+  A stop-sign icon appears in the message box. 
+
+
+-- To indicate the default button: 
+
+defbutton1
+  The first button is the default button.  This is the default.
+defbutton2
+  The second button is the default button. 
+defbutton3
+  The third button is the default button. 
+defbutton4
+  The fourth button is the default button. 
+
+
+-- To indicate the modality of the dialog box:
+applmodal
+  The user must respond to the message box before continuing work in
+  the window identified by the hWnd parameter. However, the user can
+  move to the windows of other applications and work in those windows.
+  Depending on the hierarchy of windows in the application, the user
+  may be able to move to other windows within the application. All
+  child windows of the parent of the message box are automatically
+  disabled, but popup windows are not.  This is the default.
+systemmodal
+  Same as applmodal except that the message box has the WS_EX_TOPMOST
+  style. Use system-modal message boxes to notify the user of serious,
+  potentially damaging errors that require immediate attention (for
+  example, running out of memory). This flag has no effect on the
+  user's ability to interact with windows other than those associated
+  with hWnd.
+taskmodal
+  Same as applmodal except that all the top-level windows belonging to
+  the current task are disabled if the hWnd parameter is NULL. Use
+  this flag when the calling application or library does not have a
+  window handle available but still needs to prevent input to other
+  windows in the current application without suspending other
+  applications.
+
+
+In addition, you can specify the following flags: 
+
+default-desktop-only 
+  The desktop currently receiving input must be a default desktop;
+  otherwise, the function fails. A default desktop is one an
+  application runs on after the user has logged on.
+help 
+  Adds a Help button to the message box. Choosing the Help button or
+  pressing F1 generates a Help event.
+right 
+  The text is right-justified. 
+rtlreading 
+  Displays message and caption text using right-to-left reading order
+  on Hebrew and Arabic systems.
+setforeground 
+  The message box becomes the foreground window. Internally, Windows
+  calls the SetForegroundWindow function for the message box.
+topmost 
+  The message box is created with the WS_EX_TOPMOST window style. 
+service-notification 
+  Windows NT only: The caller is a service notifying the user of an
+  event. The function displays a message box on the current active
+  desktop, even if there is no user logged on to the computer.  If
+  this flag is set, the hWnd parameter must be NULL. This is so the
+  message box can appear on a desktop other than the desktop
+  corresponding to the hWnd.
+
+
+
+The return value is one of the following menu-item values returned by
+the dialog box:
+abort
+  Abort button was selected. 
+cancel
+  Cancel button was selected. 
+ignore
+  Ignore button was selected. 
+no
+  No button was selected. 
+ok
+  OK button was selected. 
+retry
+  Retry button was selected. 
+yes
+  Yes button was selected. 
+
+If a message box has a Cancel button, the function returns the
+`cancel' value if either the ESC key is pressed or the Cancel button
+is selected.  If the message box has no Cancel button, pressing ESC has
+no effect.  */
+       (message_, flags, title))
+{
+  Lisp_Object tail;
+  Extbyte *msgout;
+  Extbyte *titleout = 0;
+  UINT sty = 0;
+
+  if (noninteractive)
+    return Qcancel;
+
+  if (!CONSP (flags))
+    {
+      CHECK_SYMBOL (flags);
+      flags = list1 (flags);
+    }
+
+  CHECK_STRING (message_);
+  TO_EXTERNAL_FORMAT (LISP_STRING, message_,
+                     C_STRING_ALLOCA, msgout,
+                     Qmswindows_tstr);
+  
+  if (!NILP (title))
+    {
+      CHECK_STRING (title);
+      TO_EXTERNAL_FORMAT (LISP_STRING, title,
+                         C_STRING_ALLOCA, titleout,
+                         Qmswindows_tstr);
+    }
+
+  EXTERNAL_LIST_LOOP (tail, flags)
+    {
+      Lisp_Object st = XCAR (tail);
+      CHECK_SYMBOL (st);
+      if (0)
+       ;
+#define FROB(sym, val) else if (EQ (st, sym)) sty |= val
+      FROB (Qabortretryignore, MB_ABORTRETRYIGNORE);
+      FROB (Qapplmodal, MB_APPLMODAL);
+      FROB (Qdefault_desktop_only, MB_DEFAULT_DESKTOP_ONLY);
+      FROB (Qdefbutton1, MB_DEFBUTTON1);
+      FROB (Qdefbutton2, MB_DEFBUTTON2);
+      FROB (Qdefbutton3, MB_DEFBUTTON3);
+      FROB (Qdefbutton4, MB_DEFBUTTON4);
+      FROB (Qhelp, MB_HELP);
+      FROB (Qiconasterisk, MB_ICONASTERISK);
+      FROB (Qiconexclamation, MB_ICONEXCLAMATION);
+      FROB (Qiconhand, MB_ICONHAND);
+      FROB (Qiconinformation, MB_ICONINFORMATION);
+      FROB (Qiconquestion, MB_ICONQUESTION);
+      FROB (Qiconstop, MB_ICONSTOP);
+      FROB (Qok, MB_OK);
+      FROB (Qokcancel, MB_OKCANCEL);
+      FROB (Qretrycancel, MB_RETRYCANCEL);
+      FROB (Qright, MB_RIGHT);
+      FROB (Qrtlreading, MB_RTLREADING);
+      FROB (Qservice_notification, MB_SERVICE_NOTIFICATION);
+      FROB (Qsetforeground, MB_SETFOREGROUND);
+      FROB (Qsystemmodal, MB_SYSTEMMODAL);
+      FROB (Qtaskmodal, MB_TASKMODAL);
+      FROB (Qtopmost, MB_TOPMOST);
+      FROB (Qyesno, MB_YESNO);
+      FROB (Qyesnocancel, MB_YESNOCANCEL);
+#undef FROB
+
+      else
+       signal_simple_error ("Unrecognized flag", st);
+    }
+
+  {
+    int retval = MessageBox (NULL, msgout, titleout, sty);
+
+    if (retval == 0)
+      error ("Out of memory when calling `mswindows-message-box'");
+
+#define FROB(sym, val) if (retval == val) return sym
+    FROB (Qabort, IDABORT);
+    FROB (Qcancel, IDCANCEL);
+    FROB (Qignore, IDIGNORE);
+    FROB (Qno, IDNO);
+    FROB (Qok, IDOK);
+    FROB (Qretry, IDRETRY);
+    FROB (Qyes, IDYES);
+#undef FROB
+    
+    signal_simple_error ("Unknown return value from MessageBox()",
+                        make_int (retval));
+  }
+
+  return Qnil;
+}
+
+void
+mswindows_output_last_error (char *frob)
+{
+  LPVOID lpMsgBuf;
+  int errval = GetLastError();
+  
+  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
+                | FORMAT_MESSAGE_FROM_SYSTEM,
+                NULL, errval,
+                MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                (LPTSTR) &lpMsgBuf,
+                0,
+                NULL);
+  stderr_out ("last error during %s is %d: %s\n",
+             frob, errval, (char*)lpMsgBuf);
+}
 
 \f
 /************************************************************************/
@@ -270,6 +543,42 @@ DSYMNAME (Lisp_Object obj)
 void
 syms_of_console_mswindows (void)
 {
+  defsymbol (&Qabortretryignore, "abortretryignore");
+  defsymbol (&Qapplmodal, "applmodal");
+  defsymbol (&Qdefault_desktop_only, "default-desktop-only");
+  defsymbol (&Qdefbutton1, "defbutton1");
+  defsymbol (&Qdefbutton2, "defbutton2");
+  defsymbol (&Qdefbutton3, "defbutton3");
+  defsymbol (&Qdefbutton4, "defbutton4");
+  /* defsymbol (&Qhelp, "help"); */
+  defsymbol (&Qiconasterisk, "iconasterisk");
+  defsymbol (&Qiconexclamation, "iconexclamation");
+  defsymbol (&Qiconhand, "iconhand");
+  defsymbol (&Qiconinformation, "iconinformation");
+  defsymbol (&Qiconquestion, "iconquestion");
+  defsymbol (&Qiconstop, "iconstop");
+  /* defsymbol (&Qok, "ok"); */
+  defsymbol (&Qokcancel, "okcancel");
+  defsymbol (&Qretrycancel, "retrycancel");
+  /* defsymbol (&Qright, "right"); */
+  defsymbol (&Qrtlreading, "rtlreading");
+  defsymbol (&Qservice_notification, "service-notification");
+  defsymbol (&Qsetforeground, "setforeground");
+  defsymbol (&Qsystemmodal, "systemmodal");
+  defsymbol (&Qtaskmodal, "taskmodal");
+  defsymbol (&Qtopmost, "topmost");
+  defsymbol (&Qyesno, "yesno");
+  defsymbol (&Qyesnocancel, "yesnocancel");
+
+  /* defsymbol (&Qabort, "abort"); */
+  /* defsymbol (&Qcancel, "cancel"); */
+  /* defsymbol (&Qignore, "ignore"); */
+  /* defsymbol (&Qno, "no"); */
+  /* defsymbol (&Qok, "ok"); */
+  /* defsymbol (&Qretry, "retry"); */
+  /* defsymbol (&Qyes, "yes"); */
+
+  DEFSUBR (Fmswindows_message_box);
 }
 
 void
index b5c3573..eacfbf5 100644 (file)
@@ -33,13 +33,8 @@ Boston, MA 02111-1307, USA.  */
 #define INCLUDED_console_msw_h_
 
 #include "console.h"
-#include <windows.h>
-#include <ddeml.h>     /* DDE management library */
-#if !defined(__CYGWIN32__) && !defined(__MINGW32__) \
-       || CYGWIN_VERSION_DLL_MAJOR > 20
-#include <shellapi.h>  /* FileManager/Explorer drag and drop */
-#include <commctrl.h>
-#endif
+#include "syswindows.h"
+#include "syscommctrl.h"
 
 #ifdef HAVE_XPM
 #include <X11/xpm.h>
@@ -164,6 +159,9 @@ struct mswindows_frame
   /* DC for this win32 window */
   HDC hdc;
 
+  /* Used with DeferWindowPos */
+  HDWP hdwp;
+
   /* Time of last click event, for button 2 emul */
   DWORD last_click_time;
 
@@ -352,4 +350,7 @@ Lisp_Object mswindows_handle_gui_wm_command (struct frame* f,
 
 int msw_windows9x_p (void);
 
+
+void mswindows_output_last_error (char *frob);
+
 #endif /* INCLUDED_console_msw_h_ */
index 1734233..76ef314 100644 (file)
@@ -40,13 +40,6 @@ Boston, MA 02111-1307, USA.  */
 #include "frame.h"
 #include "sysdep.h"
 
-#if (defined (__CYGWIN32__) || defined(__MINGW32__)) && \
-       CYGWIN_VERSION_DLL_MAJOR < 21
-extern BOOL WINAPI DdeFreeStringHandle(DWORD,HSZ);
-#else
-#include <winspool.h>
-#endif
-
 #if !(defined (__CYGWIN32__) || defined(__MINGW32__))
 # include <objbase.h>  /* For CoInitialize */
 #endif
index d33b1ea..31f5388 100644 (file)
@@ -426,6 +426,8 @@ int valid_device_class_p (Lisp_Object class);
 #define MARK_DEVICE_WINDOWS_STRUCTURE_CHANGED(d)       \
   ((void) (windows_structure_changed = (d)->windows_structure_changed = 1))
 
+/* #### unify this with DOMAIN_DEVICE once the latter has image instances
+   expunged from it. */
 /* This turns out to be used heavily so we make it a macro to make it
    inline.  Also, the majority of the time the object will turn out to
    be a window so we move it from being checked last to being checked
index 803d96a..da95e4e 100644 (file)
@@ -143,10 +143,6 @@ Lisp_Object Vcurrent_warning_class;
 /* Special catch tag used in call_with_suspended_errors(). */
 Lisp_Object Qunbound_suspended_errors_tag;
 
-/* Non-nil means we're going down, so we better not run any hooks
-   or do other non-essential stuff. */
-int preparing_for_armageddon;
-
 /* Non-nil means record all fset's and provide's, to be undone
    if the file being autoloaded is not fully loaded.
    They are recorded by being consed onto the front of Vautoload_queue:
@@ -4901,8 +4897,8 @@ function calls.
                      Fprin1 (backlist->args[i], stream);
                    }
                }
+             write_c_string (")\n", stream);
            }
-         write_c_string (")\n", stream);
          backlist = backlist->next;
        }
     }
index 154e5f0..78b1c40 100644 (file)
@@ -86,8 +86,6 @@ XtAppContext Xt_app_con;
 /* Do we accept events sent by other clients? */
 int x_allow_sendevents;
 
-int modifier_keys_are_sticky;
-
 #ifdef DEBUG_XEMACS
 int x_debug_events;
 #endif
@@ -3160,15 +3158,6 @@ vars_of_event_Xt (void)
   dispatch_event_queue_tail = Qnil;
   pdump_wire (&dispatch_event_queue_tail);
 
-  DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
-*Non-nil makes modifier keys sticky.
-This means that you can release the modifier key before pressing down
-the key that you wish to be modified.  Although this is non-standard
-behavior, it is recommended because it reduces the strain on your hand,
-thus reducing the incidence of the dreaded Emacs-pinky syndrome.
-*/ );
-  modifier_keys_are_sticky = 0;
-
   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
 *Non-nil means to allow synthetic events.  Nil means they are ignored.
 Beware: allowing emacs to process SendEvents opens a big security hole.
index a949be8..5b7d03b 100644 (file)
@@ -1,4 +1,4 @@
-/* The  mswindows event_stream interface.
+/* The mswindows event_stream interface.
    Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
    Copyright (C) 1996, 2000 Ben Wing.
@@ -58,6 +58,7 @@ Boston, MA 02111-1307, USA.  */
 #include "process.h"
 #include "redisplay.h"
 #include "select.h"
+#include "window.h"
 #include "sysproc.h"
 #include "syswait.h"
 #include "systime.h"
@@ -78,10 +79,6 @@ typedef unsigned int SOCKET;
 # include <shlobj.h>   /* For IShellLink */
 #endif
 
-#if defined (__CYGWIN32__) && (CYGWIN_VERSION_DLL_MAJOR < 20)
-typedef NMHDR *LPNMHDR;
-#endif
-
 #ifdef HAVE_MENUBARS
 #define ADJR_MENUFLAG TRUE
 #else
@@ -103,6 +100,8 @@ static int mswindows_modifier_state (BYTE* keymap, int has_AltGr);
 static void mswindows_set_chord_timer (HWND hwnd);
 static int mswindows_button2_near_enough (POINTS p1, POINTS p2);
 static int mswindows_current_layout_has_AltGr (void);
+static int mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam,
+                                             int downp, int keyp);
 
 static struct event_stream *mswindows_event_stream;
 
@@ -151,6 +150,10 @@ int mswindows_mouse_button_max_skew_x;
 int mswindows_mouse_button_max_skew_y;
 int mswindows_mouse_button_tolerance;
 
+#ifdef DEBUG_XEMACS
+int mswindows_debug_events;
+#endif
+
 /* This is the event signaled by the event pump.
    See mswindows_pump_outstanding_events for comments */
 static Lisp_Object mswindows_error_caught_in_modal_loop;
@@ -936,17 +939,21 @@ mswindows_enqueue_process_event (Lisp_Process* p)
 }
 
 static void
-mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, DWORD when)
+mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where,
+                                     DWORD when)
 {
+  int downp = (msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN ||
+              msg == WM_RBUTTONDOWN);
 
   /* We always use last message time, because mouse button
      events may get delayed, and XEmacs double click
      recognition will fail */
 
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-  Lisp_Event* event = XEVENT(emacs_event);
+  Lisp_Event* event = XEVENT (emacs_event);
 
-  event->channel = mswindows_find_frame(hwnd);
+  mswindows_handle_sticky_modifiers (0, 0, downp, 0);
+  event->channel = mswindows_find_frame (hwnd);
   event->timestamp = when;
   event->event.button.button =
     (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 :
@@ -955,8 +962,7 @@ mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, DWORD w
   event->event.button.y = where.y;
   event->event.button.modifiers = mswindows_modifier_state (NULL, 0);
 
-  if (msg==WM_LBUTTONDOWN || msg==WM_MBUTTONDOWN ||
-      msg==WM_RBUTTONDOWN)
+  if (downp)
     {
       event->event_type = button_press_event;
       SetCapture (hwnd);
@@ -1664,6 +1670,9 @@ mswindows_handle_paint (struct frame *frame)
         windows are unmapped, however once we are in the guts of
         WM_PAINT we need to make sure that we don't register
         unmaps then because they will not actually occur. */
+      /* #### commenting out the next line seems to fix some problems
+        but not all.  only andy currently understands this stuff and
+        he needs to review it more carefully. --ben */
       if (!check_for_ignored_expose (frame, x, y, width, height))
        {
          hold_ignored_expose_registration = 1;
@@ -1681,17 +1690,288 @@ mswindows_handle_paint (struct frame *frame)
 static int
 key_needs_default_processing_p (UINT vkey)
 {
-  if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU)
+  if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU
+      /* if we let ALT activate the menu like this, then sticky ALT-modified
+        keystrokes become impossible. */
+      && !modifier_keys_are_sticky)
     return 1;
 
   return 0;
 }
 
+/* key-handling code is always ugly.  It just ends up working out
+   that way.
+
+   #### Most of the sticky-modifier code below is copied from similar
+   code in event-Xt.c.  They should somehow or other be merged.
+
+   Here are some pointers:
+
+   -- DOWN_MASK indicates which modifiers should be treated as "down"
+      when the corresponding upstroke happens.  It gets reset for
+      a particular modifier when that modifier goes up, and reset
+      for all modifiers when a non-modifier key is pressed.  Example:
+
+      I press Control-A-Shift and then release Control-A-Shift.
+      I want the Shift key to be sticky but not the Control key.
+
+   -- If a modifier key is sticky, I can unstick it by pressing
+      the modifier key again. */
+
+static WPARAM last_downkey;
+static int need_to_add_mask, down_mask;
+
+#define XEMSW_LCONTROL (1<<0)
+#define XEMSW_RCONTROL (1<<1)
+#define XEMSW_LSHIFT (1<<2)
+#define XEMSW_RSHIFT (1<<3)
+#define XEMSW_LMENU (1<<4)
+#define XEMSW_RMENU (1<<5)
+
+static int
+mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam,
+                                  int downp, int keyp)
+{
+  int mods = 0;
+
+  if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */
+    return 0;
+
+  if (! (keyp &&
+        (wParam == VK_CONTROL || wParam == VK_LCONTROL ||
+         wParam == VK_RCONTROL ||
+         wParam == VK_MENU || wParam == VK_LMENU ||
+         wParam == VK_RMENU ||
+         wParam == VK_SHIFT || wParam == VK_LSHIFT ||
+         wParam == VK_RSHIFT)))
+    { /* Not a modifier key */
+      if (downp && keyp && !last_downkey)
+       last_downkey = wParam;
+      /* If I hold press-and-release the Control key and then press
+        and hold down the right arrow, I want it to auto-repeat
+        Control-Right.  On the other hand, if I do the same but
+        manually press the Right arrow a bunch of times, I want
+        to see one Control-Right and then a bunch of Rights.
+        This means that we need to distinguish between an
+        auto-repeated key and a key pressed and released a bunch
+        of times. */
+      else if (downp && !keyp ||
+              (downp && keyp && last_downkey &&
+               (wParam != last_downkey ||
+                /* the "previous key state" bit indicates autorepeat */
+                ! (lParam & (1 << 30)))))
+       {
+         need_to_add_mask = 0;
+         last_downkey = 0;
+       }
+      if (downp)
+       down_mask = 0;
+
+      mods = need_to_add_mask;
+    }
+  else                          /* Modifier key pressed */
+    {
+      /* If a non-modifier key was pressed in the middle of a bunch
+        of modifiers, then it unsticks all the modifiers that were
+        previously pressed.  We cannot unstick the modifiers until
+        now because we want to check for auto-repeat of the
+        non-modifier key. */
+
+      if (last_downkey)
+       {
+         last_downkey = 0;
+         need_to_add_mask = 0;
+       }
+
+#define FROB(mask)                             \
+do {                                           \
+  if (downp && keyp)                           \
+    {                                          \
+      /* If modifier key is already sticky,    \
+         then unstick it.  Note that we do     \
+         not test down_mask to deal with the   \
+        unlikely but possible case that the    \
+        modifier key auto-repeats. */          \
+      if (need_to_add_mask & mask)             \
+       {                                       \
+         need_to_add_mask &= ~mask;            \
+         down_mask &= ~mask;                   \
+       }                                       \
+      else                                     \
+       down_mask |= mask;                      \
+    }                                          \
+  else                                         \
+    {                                          \
+      if (down_mask & mask)                    \
+       {                                       \
+         down_mask &= ~mask;                   \
+         need_to_add_mask |= mask;             \
+       }                                       \
+    }                                          \
+} while (0)
+
+      if (wParam == VK_CONTROL && (lParam & 0x1000000)
+         || wParam == VK_RCONTROL)
+       FROB (XEMSW_RCONTROL);
+      if (wParam == VK_CONTROL && !(lParam & 0x1000000)
+         || wParam == VK_LCONTROL)
+       FROB (XEMSW_LCONTROL);
+
+      if (wParam == VK_SHIFT && (lParam & 0x1000000)
+         || wParam == VK_RSHIFT)
+       FROB (XEMSW_RSHIFT);
+      if (wParam == VK_SHIFT && !(lParam & 0x1000000)
+         || wParam == VK_LSHIFT)
+       FROB (XEMSW_LSHIFT);
+
+      if (wParam == VK_MENU && (lParam & 0x1000000)
+         || wParam == VK_RMENU)
+       FROB (XEMSW_RMENU);
+      if (wParam == VK_MENU && !(lParam & 0x1000000)
+         || wParam == VK_LMENU)
+       FROB (XEMSW_LMENU);
+    }
+#undef FROB
+
+  if (mods && downp)
+    {
+      BYTE keymap[256];
+
+      GetKeyboardState (keymap);
+
+      if (mods & XEMSW_LCONTROL)
+       {
+         keymap [VK_CONTROL] |= 0x80;
+         keymap [VK_LCONTROL] |= 0x80;
+       }
+      if (mods & XEMSW_RCONTROL)
+       {
+         keymap [VK_CONTROL] |= 0x80;
+         keymap [VK_RCONTROL] |= 0x80;
+       }
+
+      if (mods & XEMSW_LSHIFT)
+       {
+         keymap [VK_SHIFT] |= 0x80;
+         keymap [VK_LSHIFT] |= 0x80;
+       }
+      if (mods & XEMSW_RSHIFT)
+       {
+         keymap [VK_SHIFT] |= 0x80;
+         keymap [VK_RSHIFT] |= 0x80;
+       }
+
+      if (mods & XEMSW_LMENU)
+       {
+         keymap [VK_MENU] |= 0x80;
+         keymap [VK_LMENU] |= 0x80;
+       }
+      if (mods & XEMSW_RMENU)
+       {
+         keymap [VK_MENU] |= 0x80;
+         keymap [VK_RMENU] |= 0x80;
+       }
+
+      SetKeyboardState (keymap);
+      return 1;
+    }
+
+  return 0;
+}
+
+static void
+clear_sticky_modifiers (void)
+{
+  need_to_add_mask = 0;
+  last_downkey     = 0;
+  down_mask        = 0;
+}
+
+#ifdef DEBUG_XEMACS
+
+static void
+output_modifier_keyboard_state (void)
+{
+  BYTE keymap[256];
+
+  GetKeyboardState (keymap);
+
+  stderr_out ("GetKeyboardState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
+             keymap[VK_MENU] & 0x80 ? 1 : 0,
+             keymap[VK_MENU] & 0x1 ? 1 : 0,
+             keymap[VK_LMENU] & 0x80 ? 1 : 0,
+             keymap[VK_LMENU] & 0x1 ? 1 : 0,
+             keymap[VK_RMENU] & 0x80 ? 1 : 0,
+             keymap[VK_RMENU] & 0x1 ? 1 : 0);
+  stderr_out ("GetKeyboardState VK_CONTROL %d %d VK_LCONTROL %d %d VK_RCONTROL %d %d\n",
+             keymap[VK_CONTROL] & 0x80 ? 1 : 0,
+             keymap[VK_CONTROL] & 0x1 ? 1 : 0,
+             keymap[VK_LCONTROL] & 0x80 ? 1 : 0,
+             keymap[VK_LCONTROL] & 0x1 ? 1 : 0,
+             keymap[VK_RCONTROL] & 0x80 ? 1 : 0,
+             keymap[VK_RCONTROL] & 0x1 ? 1 : 0);
+  stderr_out ("GetKeyboardState VK_SHIFT %d %d VK_LSHIFT %d %d VK_RSHIFT %d %d\n",
+             keymap[VK_SHIFT] & 0x80 ? 1 : 0,
+             keymap[VK_SHIFT] & 0x1 ? 1 : 0,
+             keymap[VK_LSHIFT] & 0x80 ? 1 : 0,
+             keymap[VK_LSHIFT] & 0x1 ? 1 : 0,
+             keymap[VK_RSHIFT] & 0x80 ? 1 : 0,
+             keymap[VK_RSHIFT] & 0x1 ? 1 : 0);
+}
+
+/* try to debug the stuck-alt-key problem.
+
+ #### this happens only inconsistently, and may only happen when using
+ StickyKeys in the Win2000 accessibility section of the control panel,
+ which is extremely broken for other reasons.  */
+
+static void
+output_alt_keyboard_state (void)
+{
+  BYTE keymap[256];
+  SHORT keystate[3];
+  // SHORT asyncstate[3];
+
+  GetKeyboardState (keymap);
+  keystate[0] = GetKeyState (VK_MENU);
+  keystate[1] = GetKeyState (VK_LMENU);
+  keystate[2] = GetKeyState (VK_RMENU);
+  /* Doing this interferes with key processing. */
+/*   asyncstate[0] = GetAsyncKeyState (VK_MENU); */
+/*   asyncstate[1] = GetAsyncKeyState (VK_LMENU); */
+/*   asyncstate[2] = GetAsyncKeyState (VK_RMENU); */
+
+  stderr_out ("GetKeyboardState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
+             keymap[VK_MENU] & 0x80 ? 1 : 0,
+             keymap[VK_MENU] & 0x1 ? 1 : 0,
+             keymap[VK_LMENU] & 0x80 ? 1 : 0,
+             keymap[VK_LMENU] & 0x1 ? 1 : 0,
+             keymap[VK_RMENU] & 0x80 ? 1 : 0,
+             keymap[VK_RMENU] & 0x1 ? 1 : 0);
+  stderr_out ("GetKeyState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
+             keystate[0] & 0x8000 ? 1 : 0,
+             keystate[0] & 0x1 ? 1 : 0,
+             keystate[1] & 0x8000 ? 1 : 0,
+             keystate[1] & 0x1 ? 1 : 0,
+             keystate[2] & 0x8000 ? 1 : 0,
+             keystate[2] & 0x1 ? 1 : 0);
+/*   stderr_out ("GetAsyncKeyState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n", */
+/*           asyncstate[0] & 0x8000 ? 1 : 0, */
+/*           asyncstate[0] & 0x1 ? 1 : 0, */
+/*           asyncstate[1] & 0x8000 ? 1 : 0, */
+/*           asyncstate[1] & 0x1 ? 1 : 0, */
+/*           asyncstate[2] & 0x8000 ? 1 : 0, */
+/*           asyncstate[2] & 0x1 ? 1 : 0); */
+}
+
+#endif /* DEBUG_XEMACS */  
+
+
 /*
  * The windows procedure for the window class XEMACS_CLASS
  */
 LRESULT WINAPI
-mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
   /* Note: Remember to initialize emacs_event and event before use.
      This code calls code that can GC. You must GCPRO before calling such code. */
@@ -1726,11 +2006,23 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
     case WM_KEYUP:
     case WM_SYSKEYUP:
+
       /* See Win95 comment under WM_KEYDOWN */
       {
        BYTE keymap[256];
        int should_set_keymap = 0;
 
+#ifdef DEBUG_XEMACS
+       if (mswindows_debug_events)
+         {
+           stderr_out ("%s wparam=%d lparam=%d\n",
+                       message == WM_KEYUP ? "WM_KEYUP" : "WM_SYSKEYUP",
+                       wParam, (int)lParam);
+           output_alt_keyboard_state ();
+         }         
+#endif /* DEBUG_XEMACS */  
+
+       mswindows_handle_sticky_modifiers (wParam, lParam, 0, 1);
        if (wParam == VK_CONTROL)
          {
            GetKeyboardState (keymap);
@@ -1744,12 +2036,13 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
            should_set_keymap = 1;
          }
 
-       if (should_set_keymap
-           && (message != WM_SYSKEYUP
-               || NILP (Vmenu_accelerator_enabled)))
+       if (should_set_keymap)
+         //        && (message != WM_SYSKEYUP
+         //    || NILP (Vmenu_accelerator_enabled)))
          SetKeyboardState (keymap);
 
       }
+      
       if (key_needs_default_processing_p (wParam))
        goto defproc;
       else
@@ -1757,6 +2050,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
     case WM_KEYDOWN:
     case WM_SYSKEYDOWN:
+
       /* In some locales the right-hand Alt key is labelled AltGr. This key
        * should produce alternative charcaters when combined with another key.
        * eg on a German keyboard pressing AltGr+q should produce '@'.
@@ -1766,24 +2060,58 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        * We get round this by removing all modifiers from the keymap before
        * calling TranslateMessage() unless AltGr is *really* down. */
       {
-       BYTE keymap[256];
+       BYTE keymap_trans[256];
+       BYTE keymap_orig[256];
+       BYTE keymap_sticky[256];
        int has_AltGr = mswindows_current_layout_has_AltGr ();
-       int mods;
+       int mods = 0;
        int extendedp = lParam & 0x1000000;
        Lisp_Object keysym;
+       int sticky_changed;
 
+#ifdef DEBUG_XEMACS
+       if (mswindows_debug_events)
+         {
+           stderr_out ("%s wparam=%d lparam=%d\n",
+                       message == WM_KEYDOWN ? "WM_KEYDOWN" : "WM_SYSKEYDOWN",
+                       wParam, (int)lParam);
+           output_alt_keyboard_state ();
+         }         
+#endif /* DEBUG_XEMACS */  
+
+       GetKeyboardState (keymap_orig);
        frame = XFRAME (mswindows_find_frame (hwnd));
-       GetKeyboardState (keymap);
-       mods = mswindows_modifier_state (keymap, has_AltGr);
+       if ((sticky_changed =
+            mswindows_handle_sticky_modifiers (wParam, lParam, 1, 1)))
+         {
+           GetKeyboardState (keymap_sticky);
+           if (keymap_sticky[VK_MENU] & 0x80)
+             {
+               message = WM_SYSKEYDOWN;
+               /* We have to set the "context bit" so that the
+                  TranslateMessage() call below that generates the
+                  SYSCHAR message does its thing; see the documentation
+                  on WM_SYSKEYDOWN */
+               lParam |= 1 << 29;
+             }
+         }
+       else
+         memcpy (keymap_sticky, keymap_orig, 256);
+
+       mods = mswindows_modifier_state (keymap_sticky, has_AltGr);
 
        /* Handle non-printables */
        if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods,
                                                           extendedp)))
-         mswindows_enqueue_keypress_event (hwnd, keysym, mods);
+         {
+           mswindows_enqueue_keypress_event (hwnd, keysym, mods);
+           if (sticky_changed)
+             SetKeyboardState (keymap_orig);
+         }
        else    /* Normal keys & modifiers */
          {
-           Emchar quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
-           BYTE keymap_orig[256];
+           Emchar quit_ch =
+             CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
            POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
            MSG msg, tranmsg;
            int potential_accelerator = 0;
@@ -1800,11 +2128,15 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             * to loosely track Left and Right modifiers on behalf of the OS,
             * without screwing up Windows NT which tracks them properly. */
            if (wParam == VK_CONTROL)
-             keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
+             {
+               keymap_orig[extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
+               keymap_sticky[extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
+             }
            else if (wParam == VK_MENU)
-             keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
-
-           memcpy (keymap_orig, keymap, 256);
+             {
+               keymap_orig[extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
+               keymap_sticky[extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
+             }
 
            if (!NILP (Vmenu_accelerator_enabled) &&
                !(mods & XEMACS_MOD_SHIFT) && message == WM_SYSKEYDOWN)
@@ -1813,24 +2145,27 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
            /* Remove shift modifier from an ascii character */
            mods &= ~XEMACS_MOD_SHIFT;
 
+           memcpy (keymap_trans, keymap_sticky, 256);
+
            /* Clear control and alt modifiers unless AltGr is pressed */
-           keymap [VK_RCONTROL] = 0;
-           keymap [VK_LMENU] = 0;
-           if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80)
-               || !(keymap [VK_RMENU] & 0x80))
+           keymap_trans[VK_RCONTROL] = 0;
+           keymap_trans[VK_LMENU] = 0;
+           if (!has_AltGr || !(keymap_trans[VK_LCONTROL] & 0x80)
+               || !(keymap_trans[VK_RMENU] & 0x80))
              {
-               keymap [VK_LCONTROL] = 0;
-               keymap [VK_CONTROL] = 0;
-               keymap [VK_RMENU] = 0;
-               keymap [VK_MENU] = 0;
+               keymap_trans[VK_LCONTROL] = 0;
+               keymap_trans[VK_CONTROL] = 0;
+               keymap_trans[VK_RMENU] = 0;
+               keymap_trans[VK_MENU] = 0;
              }
-           SetKeyboardState (keymap);
+           SetKeyboardState (keymap_trans);
 
            /* Maybe generate some WM_[SYS]CHARs in the queue */
            TranslateMessage (&msg);
 
            while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)
-                  || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE))
+                  || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR,
+                                  PM_REMOVE))
              {
                int mods1 = mods;
                WPARAM ch = tranmsg.wParam;
@@ -1840,9 +2175,12 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   upon dequeueing the event */
                /* #### This might also not withstand localization, if
                   quit character is not a latin-1 symbol */
-               if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL) && quit_ch + 'a' - 1 == ch)
-                    || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL) && quit_ch == ch))
-                   && ((mods  & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT)) == 0))
+               if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL)
+                     && quit_ch + 'a' - 1 == ch)
+                    || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL)
+                        && quit_ch == ch))
+                   && ((mods  & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT))
+                       == 0))
                  {
                    mods1 |= FAKE_MOD_QUIT;
                    ++mswindows_quit_chars_count;
@@ -1855,16 +2193,21 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                  }
                mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1);
              } /* while */
-           SetKeyboardState (keymap_orig);
+
            /* This generates WM_SYSCHAR messages, which are interpreted
               by DefWindowProc as the menu selections. */
            if (got_accelerator)
              { 
+               SetKeyboardState (keymap_sticky);
                TranslateMessage (&msg);
+               SetKeyboardState (keymap_orig);
                goto defproc;
              }
+
+           SetKeyboardState (keymap_orig);
          } /* else */
       }
+
       if (key_needs_default_processing_p (wParam))
        goto defproc;
       else
@@ -2389,7 +2732,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                       (XCOLOR_INSTANCE
                        (FACE_BACKGROUND
                         (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
-                         XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
+                         XIMAGE_INSTANCE_FRAME (image_instance)))));
                  }
                last_widget_brushed = ii;
                SetTextColor
@@ -2398,7 +2741,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   (XCOLOR_INSTANCE
                    (FACE_FOREGROUND
                     (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
-                     XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
+                     XIMAGE_INSTANCE_FRAME (image_instance)))));
                SetBkMode (hdc, OPAQUE);
                SetBkColor
                  (hdc,
@@ -2406,7 +2749,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   (XCOLOR_INSTANCE
                    (FACE_BACKGROUND
                     (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
-                     XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
+                     XIMAGE_INSTANCE_FRAME (image_instance)))));
                return (LRESULT)widget_brush;
              }
          }
@@ -2582,13 +2925,15 @@ mswindows_current_layout_has_AltGr (void)
 
 /* Returns the state of the modifier keys in the format expected by the
  * Lisp_Event key_data, button_data and motion_data modifiers member */
-int mswindows_modifier_state (BYTE* keymap, int has_AltGr)
+static int
+mswindows_modifier_state (BYTE* keymap, int has_AltGr)
 {
   int mods = 0;
+  BYTE keymap2[256];
 
   if (keymap == NULL)
     {
-      keymap = (BYTE*) alloca(256);
+      keymap = keymap2;
       GetKeyboardState (keymap);
       has_AltGr = mswindows_current_layout_has_AltGr ();
     }
@@ -2839,18 +3184,19 @@ emacs_mswindows_handle_magic_event (Lisp_Event *emacs_event)
        struct frame *f = XFRAME (frame);
        int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS);
        Lisp_Object conser;
+       struct gcpro gcpro1;
 
-       /* struct gcpro gcpro1; */
-
-       /* Clear sticky modifiers here (if we had any) */
+       /* On focus change, clear all memory of sticky modifiers
+          to avoid non-intuitive behavior. */
+       clear_sticky_modifiers ();
 
        conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
-       /* GCPRO1 (conser); XXX Not necessary? */
+       GCPRO1 (conser);
        emacs_handle_focus_change_preliminary (conser);
        /* Under X the stuff up to here is done in the X event handler.
           I Don't know why */
        emacs_handle_focus_change_final (conser);
-       /* UNGCPRO; */
+       UNGCPRO;
 
       }
       break;
@@ -3165,6 +3511,20 @@ vars_of_event_mswindows (void)
   mswindows_error_caught_in_modal_loop = Qnil;
   staticpro (&mswindows_error_caught_in_modal_loop);
 
+
+#ifdef DEBUG_XEMACS
+  DEFVAR_INT ("mswindows-debug-events", &mswindows_debug_events /*
+If non-zero, display debug information about Windows events that XEmacs sees.
+Information is displayed in a console window.  Currently defined values are:
+
+1 == non-verbose output
+2 == verbose output
+
+#### Unfortunately, not yet implemented.
+*/ );
+  mswindows_debug_events = 0;
+#endif
+
   DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu",
               &mswindows_alt_by_itself_activates_menu /*
 *Controls whether pressing and releasing the Alt key activates the menubar.
index e2b46bb..e3cbf1f 100644 (file)
@@ -121,6 +121,8 @@ Lisp_Object Qpre_idle_hook, Vpre_idle_hook;
 /* Control gratuitous keyboard focus throwing. */
 int focus_follows_mouse;
 
+int modifier_keys_are_sticky;
+
 #if 0 /* FSF Emacs crap */
 /* Hook run after a command if there's no more input soon.  */
 Lisp_Object Qpost_command_idle_hook, Vpost_command_idle_hook;
@@ -4754,6 +4756,15 @@ you should *bind* this, not set it.
 */ );
     Vretry_undefined_key_binding_unshifted = Qt;
 
+  DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
+*Non-nil makes modifier keys sticky.
+This means that you can release the modifier key before pressing down
+the key that you wish to be modified.  Although this is non-standard
+behavior, it is recommended because it reduces the strain on your hand,
+thus reducing the incidence of the dreaded Emacs-pinky syndrome.
+*/ );
+  modifier_keys_are_sticky = 0;
+
 #ifdef HAVE_XIM
   DEFVAR_LISP ("composed-character-default-binding",
                &Vcomposed_character_default_binding /*
index f049a23..6679792 100644 (file)
@@ -127,13 +127,6 @@ mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
     abs (XINT (height));
       
   /* Misc frame stuff */
-  FRAME_MSWINDOWS_DATA(f)->button2_need_lbutton = 0;
-  FRAME_MSWINDOWS_DATA(f)->button2_need_rbutton = 0;
-  FRAME_MSWINDOWS_DATA(f)->button2_is_down = 0;
-  FRAME_MSWINDOWS_DATA(f)->ignore_next_lbutton_up = 0;
-  FRAME_MSWINDOWS_DATA(f)->ignore_next_rbutton_up = 0;
-  FRAME_MSWINDOWS_DATA(f)->sizing = 0;
-  FRAME_MSWINDOWS_DATA(f)->paint_pending = 0;
   FRAME_MSWINDOWS_MENU_HASH_TABLE(f) = Qnil;
 #ifdef HAVE_TOOLBARS
   FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) = 
index e77a490..ceae5b0 100644 (file)
@@ -94,9 +94,6 @@ struct frame
 
   int modiff;
 
-  /* subwindow cache elements for this frame */
-  subwindow_cachel_dynarr *subwindow_cachels;
-
   struct expose_ignore* subwindow_exposures;
   struct expose_ignore* subwindow_exposures_tail;
 
@@ -547,7 +544,7 @@ extern int frame_changed;
   NON_LVALUE ((f)->last_nonminibuf_window)
 #define FRAME_SB_VCACHE(f) ((f)->sb_vcache)
 #define FRAME_SB_HCACHE(f) ((f)->sb_hcache)
-#define FRAME_SUBWINDOW_CACHE(f) ((f)->subwindow_cachels)
+#define FRAME_SUBWINDOW_CACHE(f) ((f)->subwindow_instance_cache)
 
 #if 0 /* FSFmacs */
 
index 4fe27bf..c473817 100644 (file)
@@ -145,6 +145,9 @@ Boston, MA 02111-1307, USA.  */
   MARKED_SLOT_ARRAY (toolbar_border_width, 4);
 #endif
 
+/* Cache of subwindow instances for this frame */
+  MARKED_SLOT (subwindow_instance_cache);
+
   /* Possible frame-local default for outside margin widths. */
   MARKED_SLOT (left_margin_width);
   MARKED_SLOT (right_margin_width);
index e3c8e4c..7ed8d4c 100644 (file)
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include "lisp.h"
 
+Lisp_Object Qabort;
 Lisp_Object Qactually_requested;
 Lisp_Object Qafter;
 Lisp_Object Qall;
@@ -47,8 +48,9 @@ Lisp_Object Qbottom;
 Lisp_Object Qbottom_margin;
 Lisp_Object Qbuffer;
 Lisp_Object Qbutton;
-Lisp_Object Qcenter;
+Lisp_Object Qcancel;
 Lisp_Object Qcategory;
+Lisp_Object Qcenter;
 Lisp_Object Qchannel;
 Lisp_Object Qchar;
 Lisp_Object Qcharacter;
@@ -82,18 +84,20 @@ Lisp_Object Qface;
 Lisp_Object Qfile_name;
 Lisp_Object Qfont;
 Lisp_Object Qframe;
-Lisp_Object Qfunction;
 Lisp_Object Qfuncall;
+Lisp_Object Qfunction;
 Lisp_Object Qgap_overhead;
 Lisp_Object Qgeneric;
 Lisp_Object Qgeometry;
 Lisp_Object Qglobal;
 Lisp_Object Qgutter;
 Lisp_Object Qheight;
+Lisp_Object Qhelp;
 Lisp_Object Qhighlight;
 Lisp_Object Qhorizontal;
 Lisp_Object Qicon;
 Lisp_Object Qid;
+Lisp_Object Qignore;
 Lisp_Object Qimage;
 Lisp_Object Qinfo;
 Lisp_Object Qinherit;
@@ -122,11 +126,13 @@ Lisp_Object Qmotion;
 Lisp_Object Qmsprinter;
 Lisp_Object Qmswindows;
 Lisp_Object Qname;
+Lisp_Object Qno;
 Lisp_Object Qnone;
 Lisp_Object Qnot;
 Lisp_Object Qnothing;
 Lisp_Object Qnotice;
 Lisp_Object Qobject;
+Lisp_Object Qok;
 Lisp_Object Qold_assoc;
 Lisp_Object Qold_delete;
 Lisp_Object Qold_delq;
@@ -147,6 +153,7 @@ Lisp_Object Qrassoc;
 Lisp_Object Qrassq;
 Lisp_Object Qrequire;
 Lisp_Object Qresource;
+Lisp_Object Qretry;
 Lisp_Object Qreturn;
 Lisp_Object Qreverse;
 Lisp_Object Qright;
@@ -179,16 +186,18 @@ Lisp_Object Qunimplemented;
 Lisp_Object Qvalue_assoc;
 Lisp_Object Qvertical;
 Lisp_Object Qwarning;
-Lisp_Object Qwidth;
 Lisp_Object Qwidget;
+Lisp_Object Qwidth;
 Lisp_Object Qwindow;
 Lisp_Object Qwindow_system;
 Lisp_Object Qx;
 Lisp_Object Qy;
+Lisp_Object Qyes;
 
 void
 syms_of_general (void)
 {
+  defsymbol (&Qabort, "abort");
   defsymbol (&Qactually_requested, "actually-requested");
   defsymbol (&Qafter, "after");
   defsymbol (&Qall, "all");
@@ -205,6 +214,7 @@ syms_of_general (void)
   defsymbol (&Qbottom_margin, "bottom-margin");
   defsymbol (&Qbuffer, "buffer");
   defsymbol (&Qbutton, "button");
+  defsymbol (&Qcancel, "cancel");
   defsymbol (&Qcategory, "category");
   defsymbol (&Qcenter, "center");
   defsymbol (&Qchannel, "channel");
@@ -240,18 +250,20 @@ syms_of_general (void)
   defsymbol (&Qfile_name, "file-name");
   defsymbol (&Qfont, "font");
   defsymbol (&Qframe, "frame");
-  defsymbol (&Qfunction, "function");
   defsymbol (&Qfuncall, "funcall");
+  defsymbol (&Qfunction, "function");
   defsymbol (&Qgap_overhead, "gap-overhead");
   defsymbol (&Qgeneric, "generic");
   defsymbol (&Qgeometry, "geometry");
   defsymbol (&Qglobal, "global");
   defsymbol (&Qgutter, "gutter");
   defsymbol (&Qheight, "height");
+  defsymbol (&Qhelp, "help");
   defsymbol (&Qhighlight, "highlight");
   defsymbol (&Qhorizontal, "horizontal");
   defsymbol (&Qicon, "icon");
   defsymbol (&Qid, "id");
+  defsymbol (&Qignore, "ignore");
   defsymbol (&Qimage, "image");
   defsymbol (&Qinfo, "info");
   defsymbol (&Qinherit, "inherit");
@@ -280,11 +292,13 @@ syms_of_general (void)
   defsymbol (&Qmsprinter, "msprinter");
   defsymbol (&Qmswindows, "mswindows");
   defsymbol (&Qname, "name");
+  defsymbol (&Qno, "no");
   defsymbol (&Qnone, "none");
   defsymbol (&Qnot, "not");
   defsymbol (&Qnothing, "nothing");
   defsymbol (&Qnotice, "notice");
   defsymbol (&Qobject, "object");
+  defsymbol (&Qok, "ok");
   defsymbol (&Qold_assoc, "old-assoc");
   defsymbol (&Qold_delete, "old-delete");
   defsymbol (&Qold_delq, "old-delq");
@@ -305,6 +319,7 @@ syms_of_general (void)
   defsymbol (&Qrassq, "rassq");
   defsymbol (&Qrequire, "require");
   defsymbol (&Qresource, "resource");
+  defsymbol (&Qretry, "retry");
   defsymbol (&Qreturn, "return");
   defsymbol (&Qreverse, "reverse");
   defsymbol (&Qright, "right");
@@ -337,10 +352,11 @@ syms_of_general (void)
   defsymbol (&Qvalue_assoc, "value-assoc");
   defsymbol (&Qvertical, "vertical");
   defsymbol (&Qwarning, "warning");
-  defsymbol (&Qwidth, "width");
   defsymbol (&Qwidget, "widget");
+  defsymbol (&Qwidth, "width");
   defsymbol (&Qwindow, "window");
   defsymbol (&Qwindow_system, "window-system");
   defsymbol (&Qx, "x");
   defsymbol (&Qy, "y");
+  defsymbol (&Qyes, "yes");
 }
index 440e272..1320e03 100644 (file)
@@ -20,7 +20,7 @@ Boston, MA 02111-1307, USA.  */
 
 /* Synched up with: Not in FSF. */
 
-/* written by Andy Piper <andy@xemacs.org> plagerising bits from
+/* written by Andy Piper <andy@xemacs.org> plagiarising bits from
    glyphs-x.c */
 
 #include <config.h>
@@ -57,7 +57,6 @@ DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
-DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
 #ifdef HAVE_JPEG
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
 #endif
@@ -80,6 +79,8 @@ DEFINE_DEVICE_IIFORMAT (msprinter, xbm);
 DEFINE_DEVICE_IIFORMAT (mswindows, xface);
 DEFINE_DEVICE_IIFORMAT (msprinter, xface);
 #endif
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
+DEFINE_DEVICE_IIFORMAT (mswindows, native_layout);
 DEFINE_DEVICE_IIFORMAT (mswindows, button);
 DEFINE_DEVICE_IIFORMAT (mswindows, edit_field);
 DEFINE_DEVICE_IIFORMAT (mswindows, subwindow);
@@ -132,8 +133,7 @@ get_device_compdc (struct device *d)
  */
 static void init_image_instance_geometry (Lisp_Image_Instance *ii)
 {
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  struct device *d = XDEVICE (device);
+  struct device *d = DOMAIN_XDEVICE (ii->domain);
   
   if (/* #### Scaleable && */ DEVICE_MSPRINTER_P (d))
     {
@@ -349,8 +349,7 @@ init_image_instance_from_dibitmap (Lisp_Image_Instance *ii,
                                   int x_hot, int y_hot,
                                   int create_mask)
 {
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  struct device *d = XDEVICE (device);
+  struct device *d = XDEVICE (IMAGE_INSTANCE_DEVICE (ii));
   void* bmp_buf=0;
   enum image_instance_type type;
   HBITMAP bitmap;
@@ -2072,11 +2071,13 @@ extern int debug_widget_instances;
 static void
 mswindows_finalize_image_instance (Lisp_Image_Instance *p)
 {
-  if (DEVICE_LIVE_P (XDEVICE (p->device)))
+  if (!p->data)
+    return;
+
+  if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
     {
-      if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET
-         ||
-         IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
+      if (image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (p))
+         & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
        {
 #ifdef DEBUG_WIDGETS
          debug_widget_instances--;
@@ -2139,6 +2140,14 @@ mswindows_widget_hfont (Lisp_Image_Instance *p,
   return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike);
 }
 
+static HDWP
+begin_defer_window_pos (struct frame *f)
+{
+  if (FRAME_MSWINDOWS_DATA (f)->hdwp == 0)
+    FRAME_MSWINDOWS_DATA (f)->hdwp = BeginDeferWindowPos (10);
+  return FRAME_MSWINDOWS_DATA (f)->hdwp;
+}
+  
 /* unmap the image if it is a widget. This is used by redisplay via
    redisplay_unmap_subwindows */
 static void
@@ -2146,11 +2155,26 @@ mswindows_unmap_subwindow (Lisp_Image_Instance *p)
 {
   if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
     {
-      SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
-                   NULL,
-                   0, 0, 0, 0,
-                   SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE
-                   | SWP_NOSENDCHANGING);
+      struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
+      HDWP hdwp = begin_defer_window_pos (f);
+      HDWP new_hdwp;
+      new_hdwp = DeferWindowPos (hdwp, IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
+                                NULL,
+                                0, 0, 0, 0,
+                                SWP_HIDEWINDOW | SWP_NOACTIVATE |
+                                SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
+                                /* Setting this flag causes the call to
+                                   DeferWindowPos to fail with
+                                   "Invalid parameter".  I don't understand
+                                   why we bother to try and set this
+                                   anyway. -- ben */
+                                /* | SWP_NOSENDCHANGING */
+                                );
+      if (!new_hdwp)
+       mswindows_output_last_error ("unmapping");
+      else
+       hdwp = new_hdwp;
+      FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
       if (GetFocus() == WIDGET_INSTANCE_MSWINDOWS_HANDLE (p))
        SetFocus (GetParent (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
     }
@@ -2162,6 +2186,9 @@ static void
 mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                         struct display_glyph_area* dga)
 {
+  struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
+  HDWP hdwp = begin_defer_window_pos (f);
+  HDWP new_hdwp;
   /* move the window before mapping it ... */
   SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
                NULL,
@@ -2175,12 +2202,24 @@ mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                SWP_NOZORDER | SWP_NOSIZE
                | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
   /* ... now map it - we are not allowed to move it at the same time. */
-  SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
-               NULL,
-               0, 0, 0, 0,
-               SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
-               | SWP_SHOWWINDOW | SWP_NOCOPYBITS
-               | SWP_NOSENDCHANGING);
+  new_hdwp = DeferWindowPos (hdwp, IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
+                            NULL,
+                            0, 0, 0, 0,
+                            SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
+                            | SWP_SHOWWINDOW
+                            /* | SWP_NOCOPYBITS */
+                            /* Setting this flag causes the call to
+                               DeferWindowPos to fail with
+                               "Invalid parameter".  I don't understand
+                               why we bother to try and set this
+                               anyway. -- ben */
+                            /* | SWP_NOSENDCHANGING */
+                            | SWP_NOACTIVATE);
+  if (!new_hdwp)
+    mswindows_output_last_error ("mapping");
+  else
+    hdwp = new_hdwp;
+  FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
 }
 
 /* resize the subwindow instance */
@@ -2188,11 +2227,12 @@ static void
 mswindows_resize_subwindow (Lisp_Image_Instance* ii, int w, int h)
 {
   /* Set the size of the control .... */
-  SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
-               NULL,
-               0, 0, w, h,
-               SWP_NOZORDER | SWP_NOMOVE
-               | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
+  if (!SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+                    NULL,
+                    0, 0, w, h,
+                    SWP_NOZORDER | SWP_NOMOVE
+                    | SWP_NOCOPYBITS | SWP_NOSENDCHANGING))
+    mswindows_output_last_error ("resizing");
 }
 
 /* Simply resize the window here. */
@@ -2210,17 +2250,16 @@ static void
 mswindows_update_widget (Lisp_Image_Instance *p)
 {
   /* Possibly update the face font and colors. */
-  if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
-      ||
-      XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (p))->faces_changed
-      ||
-      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
+  if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (p))
+      && (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
+         || XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
+         || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)))
     {
       /* set the widget font from the widget face */
       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
                   WM_SETFONT,
                   (WPARAM) mswindows_widget_hfont
-                  (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)),
+                  (p, IMAGE_INSTANCE_FRAME (p)),
                   MAKELPARAM (TRUE, 0));
     }
   /* Possibly update the dimensions. */
@@ -2231,7 +2270,8 @@ mswindows_update_widget (Lisp_Image_Instance *p)
                                  IMAGE_INSTANCE_HEIGHT (p));
     }
   /* Possibly update the text in the widget. */
-  if (IMAGE_INSTANCE_TEXT_CHANGED (p))
+  if (IMAGE_INSTANCE_TEXT_CHANGED (p)
+      && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (p)))
     {
       Extbyte* lparam=0;
       TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p),
@@ -2249,7 +2289,7 @@ static int
 mswindows_register_gui_item (Lisp_Object image_instance,
                             Lisp_Object gui, Lisp_Object domain)
 {
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   struct frame* f = XFRAME (frame);
   int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f),
                             gui,
@@ -2278,7 +2318,7 @@ mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instant
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   HWND wnd;
 
   CHECK_MSWINDOWS_DEVICE (device);
@@ -2400,7 +2440,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   /* this function can call lisp */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   Extbyte* nm=0;
   HWND wnd;
   int id = 0xffff;
@@ -2438,7 +2478,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
                        IMAGE_INSTANCE_WIDGET_WIDTH (ii),
                        IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
                        /* parent window */
-                       FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
+                       DOMAIN_MSWINDOWS_HANDLE (domain),
                        (HMENU)id,       /* No menu */
                        NULL, /* must be null for this class */
                        NULL)) == NULL)
@@ -2468,9 +2508,32 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
   SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
   /* set the widget font from the widget face */
-  SendMessage (wnd, WM_SETFONT,
-              (WPARAM) mswindows_widget_hfont (ii, domain),
-              MAKELPARAM (TRUE, 0));
+  if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+    SendMessage (wnd, WM_SETFONT,
+                (WPARAM) mswindows_widget_hfont (ii, domain),
+                MAKELPARAM (TRUE, 0));
+}
+
+/* Instantiate a native layout widget. */
+static void
+mswindows_native_layout_instantiate (Lisp_Object image_instance,
+                                    Lisp_Object instantiator,
+                                    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                                    int dest_mask, Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+  mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+                               pointer_bg, dest_mask, domain, "STATIC", 
+                               /* Approximation to styles available with
+                                  an XEmacs layout. */
+                               EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+                                   Qetched_in) ||
+                               EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+                                   Qetched_out) ||
+                               GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
+                               ? SS_ETCHEDFRAME : SS_SUNKEN,
+                               0);
 }
 
 /* Instantiate a button widget. Unfortunately instantiated widgets are
@@ -2593,7 +2656,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in
                         (XCOLOR_INSTANCE
                          (FACE_BACKGROUND
                           (XIMAGE_INSTANCE_WIDGET_FACE (ii),
-                           XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
+                           XIMAGE_INSTANCE_FRAME (ii))))));
 #endif
 #ifdef PBS_SETBARCOLOR
   SendMessage (wnd, PBS_SETBARCOLOR, 0,
@@ -2601,7 +2664,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in
                          (XCOLOR_INSTANCE
                           (FACE_FOREGROUND
                            (XIMAGE_INSTANCE_WIDGET_FACE (ii),
-                            XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
+                            XIMAGE_INSTANCE_FRAME (ii))))));
 #endif
 }
 
@@ -2785,7 +2848,7 @@ mswindows_tab_control_update (Lisp_Object image_instance)
       LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
        {
          add_tab_item (image_instance, wnd, XCAR (rest),
-                       IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), i);
+                       IMAGE_INSTANCE_FRAME (ii), i);
          if (gui_item_selected_p (XCAR (rest)))
            selected = i;
          i++;
@@ -3013,7 +3076,6 @@ image_instantiator_format_create_glyphs_mswindows (void)
 {
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, nothing);
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, string);
-  IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, layout);
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, formatted_string);
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, inherit);
   /* image-instantiator types */
@@ -3046,44 +3108,41 @@ image_instantiator_format_create_glyphs_mswindows (void)
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, gif);
 #endif
 #ifdef HAVE_WIDGETS
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
+  /* layout widget */
+  IIFORMAT_VALID_CONSOLE (mswindows, layout);
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, native_layout);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, native_layout, instantiate);
   /* button widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, update);
-
+  /* edit-field widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
   IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
-
+  /* subwindow */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
   IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
-
-  INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
-
   /* label */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
   IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
-
   /* combo box */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box);
   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property);
   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate);
-
   /* scrollbar */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
   IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
-
   /* progress gauge */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, update);
   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate);
-
   /* tree view widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view);
   /*  IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/
   IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate);
-
   /* tab control widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
   IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
index 80d7c64..c2cba15 100644 (file)
@@ -96,14 +96,21 @@ struct mswindows_subwindow_data
 };
 
 #define MSWINDOWS_SUBWINDOW_DATA(i) \
-((struct mswindows_subwindow_data *) (i)->data)
-
+  ((struct mswindows_subwindow_data *) (i)->data)
 #define IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW(i) \
      (MSWINDOWS_SUBWINDOW_DATA (i)->clip_window)
 
+#define XIMAGE_INSTANCE_MSWINDOWS_SUBWINDOW_DATA(i) \
+  MSWINDOWS_SUBWINDOW_DATA (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW(i) \
   IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (XIMAGE_INSTANCE (i))
 
+#define DOMAIN_MSWINDOWS_HANDLE(domain) \
+  ((IMAGE_INSTANCEP (domain) && \
+  XIMAGE_INSTANCE_MSWINDOWS_SUBWINDOW_DATA (domain)) ? \
+   XWIDGET_INSTANCE_MSWINDOWS_HANDLE (domain) : \
+   FRAME_MSWINDOWS_HANDLE (DOMAIN_XFRAME (domain)))
+
 #endif /* HAVE_MS_WINDOWS */
 
 #endif /* INCLUDED_glyphs_msw_h_ */
index 8456c25..d7c8c58 100644 (file)
@@ -55,12 +55,13 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control);
 Lisp_Object Qtab_control;
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout);
 Lisp_Object Qlayout;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout);
+Lisp_Object Qnative_layout;
 
 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
 Lisp_Object Q_image, Q_text, Q_orientation, Q_justify, Q_border;
+Lisp_Object Q_margin_width;
 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
-Lisp_Object Vwidget_callback_current_channel;
-Lisp_Object Qwidget_callback_current_channel;
 
 #ifdef DEBUG_WIDGETS
 int debug_widget_instances;
@@ -274,7 +275,7 @@ widget_property (Lisp_Object image_instance, Lisp_Object prop)
     return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
 
   /* .. then try device specific methods ... */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+  meths = decode_device_ii_format (image_instance_device (image_instance),
                                   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
                                   ERROR_ME_NOT);
   if (meths && HAS_IIFORMAT_METH_P (meths, property))
@@ -304,7 +305,7 @@ widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object v
     }
 
   /* Now try device specific methods first ... */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+  meths = decode_device_ii_format (image_instance_device (image_instance), 
                                   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
                                   ERROR_ME_NOT);
   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
@@ -331,30 +332,32 @@ widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object v
 }
 
 /* Like the rest of redisplay, we want widget updates to occur
-asynchronously. Thus toolkit specific methods for setting properties
-must be called by redisplay instead of by *_set_property. Thus
-*_set_property records the change and this function actually
-implements it. We want to be slightly clever about this however by
-supplying format specific functions for the updates instead of lumping
-them all into this function. Note that there is no need for format
-generic functions. */
+   asynchronously. Thus toolkit specific methods for setting
+   properties must be called by redisplay instead of by
+   *_set_property. Thus *_set_property records the change and this
+   function actually implements it. We want to be slightly clever
+   about this however by supplying format specific functions for the
+   updates instead of lumping them all into this function. Note that
+   there is no need for format generic functions. */
 void
 update_widget (Lisp_Object widget)
 {
   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
   struct image_instantiator_methods* meths;
 
-  if (IMAGE_INSTANCE_TYPE (ii) != IMAGE_WIDGET)
+  if (!WIDGET_IMAGE_INSTANCEP (widget)
+      || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+      || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
     return;
 
   /* Device generic methods. We must update the widget's size as it
      may have been changed by the the layout routines. We also do this
      here so that explicit resizing from lisp does not result in
      synchronous updates. */
-  MAYBE_DEVMETH (XDEVICE (ii->device), update_widget, (ii));
+  MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), update_widget, (ii));
 
   /* Device-format specific methods */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+  meths = decode_device_ii_format (image_instance_device (widget), 
                                   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
                                   ERROR_ME_NOT);
   MAYBE_IIFORMAT_METH (meths, update, (widget));
@@ -389,7 +392,7 @@ widget_query_geometry (Lisp_Object image_instance,
       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
     {
       /* .. then try device specific methods ... */
-      meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+      meths = decode_device_ii_format (image_instance_device (image_instance),
                                       IMAGE_INSTANCE_WIDGET_TYPE (ii), 
                                       ERROR_ME_NOT);
       if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
@@ -437,7 +440,7 @@ widget_query_geometry (Lisp_Object image_instance,
     }
 }
 
-static void 
+static int 
 widget_layout (Lisp_Object image_instance, 
               unsigned int width, unsigned int height, Lisp_Object domain)
 {
@@ -445,21 +448,22 @@ widget_layout (Lisp_Object image_instance,
   struct image_instantiator_methods* meths;
 
   /* .. then try device specific methods ... */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+  meths = decode_device_ii_format (image_instance_device (image_instance),
                                   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
                                   ERROR_ME_NOT);
   if (meths && HAS_IIFORMAT_METH_P (meths, layout))
-    IIFORMAT_METH (meths, layout, (image_instance, 
-                                  width, height, domain));
+    return IIFORMAT_METH (meths, layout, (image_instance, 
+                                         width, height, domain));
   else
     {
       /* ... then format specific methods ... */
       meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
                                       ERROR_ME_NOT);
       if (meths && HAS_IIFORMAT_METH_P (meths, layout))
-       IIFORMAT_METH (meths, layout, (image_instance, 
-                                      width, height, domain));
+       return IIFORMAT_METH (meths, layout, (image_instance, 
+                                             width, height, domain));
     }
+  return 1;
 }
 
 static void
@@ -516,6 +520,7 @@ initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
   IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
   SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
   IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
+  IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil;
   IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
   IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
   IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
@@ -547,15 +552,15 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
   Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
   Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
+  Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width);
   int pw=0, ph=0, tw=0, th=0;
   
   /* this just does pixel type sizing */
   subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
                         dest_mask, domain);
-
-  if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK)))
-    incompatible_image_types (instantiator, dest_mask, 
-                             IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK);
+  
+  if (!(dest_mask & IMAGE_WIDGET_MASK))
+    incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
 
   initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
 
@@ -566,57 +571,10 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   if (!NILP (face))
     SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
   
-  /* Do layout specific initialisation. This feels a bit tacky, but
-     the alternative is a myriad of different little functions. */
-  if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
-    {
-      Lisp_Object rest, children = Qnil;
-      Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
-
-      if (NILP (orient))
-       {
-         IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
-       }
-      IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT;
-      
-      if (EQ (border, Qt))
-       {
-         IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
-       }
-      else if (GLYPHP (border))
-       {
-         /* We are going to be sneaky here and add the border text as
-            just another child, the layout and output routines don't know
-            this and will just display at the offsets we prescribe. */
-         Lisp_Object gii = glyph_image_instance (border, domain, ERROR_ME, 1);
-         /* make sure we are designated as the parent. */
-         XIMAGE_INSTANCE_PARENT (gii) = image_instance;
-         children = Fcons (gii, children);
-         IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
-       }
-      else
-       {
-         IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
-       }
-
-      /* Pick up the sub-widgets. */
-      LIST_LOOP (rest, items)
-       {
-         /* make sure the image is instantiated */
-         Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
-         /* make sure we are designated as the parent. */
-         XIMAGE_INSTANCE_PARENT (gii) = image_instance;
-         children = Fcons (gii, children);
-       }
-      /* Make sure elements in the layout are in the order the
-        user expected. */
-      children = Fnreverse (children);
-      IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
-    }
   /* retrieve the gui item information. This is easy if we have been
      provided with a vector, more difficult if we have just been given
      keywords */
-  else if (STRINGP (desc) || NILP (desc))
+  if (STRINGP (desc) || NILP (desc))
     {
       /* big cheat - we rely on the fact that a gui item looks like an instantiator */
       IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
@@ -626,14 +584,16 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   else
     IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
       gui_parse_item_keywords_no_errors (desc);
-
+      
   /* Pick up the orientation before we do our first layout. */
   if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
     IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
 
   /* parse more gui items out of the properties */
   if (!NILP (props)
-      && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
+      && 
+      !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+      && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
     {
       if (NILP (items))
        {
@@ -709,15 +669,23 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
     }
 
-  /* When we create the widgets the window system expects a valid
-     size, so If we still don' t have sizes, call layout to pick them
-     up. If query_geometry or layout relies on the widget being in
-     existence then we are in catch 22. */
-  image_instance_layout (image_instance, 
-                        pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY,
-                        ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY,
-                        domain);
+  /* Pick up the margin width. */
+  if (!NILP (mwidth))
+    IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth);
+
+  /* Layout for the layout widget is premature at this point since the
+     children will not have been instantiated. We can't instantiate
+     them until the device instantiation method for the layout has
+     been executed. We do however want to record any specified
+     dimensions. */
+  if (pw)      IMAGE_INSTANCE_WIDTH (ii) = pw;
+  if (ph)      IMAGE_INSTANCE_HEIGHT (ii) = ph;
+}
 
+static void
+widget_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                        Lisp_Object domain)
+{
 #ifdef DEBUG_WIDGETS
   debug_widget_instances++;
   stderr_out ("instantiated ");
@@ -878,12 +846,6 @@ progress_gauge_set_property (Lisp_Object image_instance,
 /*****************************************************************************
  *                              widget layout                               *
  *****************************************************************************/
-static int
-layout_possible_dest_types (void)
-{
-  return IMAGE_LAYOUT_MASK;
-}
-
 /* we need to convert things like glyphs to images, eval expressions
    etc.*/
 static Lisp_Object
@@ -911,6 +873,79 @@ layout_normalize (Lisp_Object inst, Lisp_Object console_type)
   return inst;
 }
 
+static void
+layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                   Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                   int dest_mask, Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
+  Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
+
+  /* Do widget type instantiation first. */
+  widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
+                     dest_mask, domain);
+
+  if (NILP (orient))
+    {
+      IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
+    }
+      
+  if (EQ (border, Qt))
+    {
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
+    }
+  else
+    {
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
+    }
+  /* We don't do the children yet as we might not have a containing
+     window. */
+}
+
+static void
+layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                        Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+  Lisp_Object rest, children = Qnil;
+
+  if (GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
+    {
+      /* We are going to be sneaky here and add the border text as
+        just another child, the layout and output routines don't know
+        this and will just display at the offsets we prescribe. */
+      Lisp_Object gii = glyph_image_instance 
+       (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+        image_instance, ERROR_ME, 1);
+
+      if (!IMAGE_INSTANCEP (gii))
+       return;
+      /* make sure we are designated as the parent. */
+      XIMAGE_INSTANCE_PARENT (gii) = image_instance;
+      children = Fcons (gii, children);
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
+    }
+
+  /* Pick up the sub-widgets. */
+  LIST_LOOP (rest, items)
+    {
+      /* make sure the image is instantiated */
+      Lisp_Object gii = glyph_image_instance (XCAR (rest), 
+                                             image_instance, ERROR_ME, 1);
+      if (!IMAGE_INSTANCEP (gii))
+       return;
+      /* make sure we are designated as the parent. */
+      XIMAGE_INSTANCE_PARENT (gii) = image_instance;
+      children = Fcons (gii, children);
+    }
+  /* Make sure elements in the layout are in the order the
+     user expected. */
+  children = Fnreverse (children);
+  IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
+}
+
 /* Layout widget. Sizing commentary: we have a number of problems that
    we would like to address. Some consider some of these more
    important than others. It used to be that size information was
@@ -969,6 +1004,10 @@ layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
   int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
   unsigned int gheight, gwidth;
 
+  /* If we are not initialized then we won't have any children. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+      return;
+
   /* First just set up what we already have. */
   if (width)   *width = IMAGE_INSTANCE_WIDTH (ii);
   if (height)  *height = IMAGE_INSTANCE_HEIGHT (ii);
@@ -1018,9 +1057,11 @@ layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
     }
   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
           == LAYOUT_HORIZONTAL)
-    *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2;
+    *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH +
+                     IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2;
   else 
-    *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2;
+    *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 + 
+                         IMAGE_INSTANCE_MARGIN_WIDTH (ii));
 
   /* Work out vertical spacings. */
   if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
@@ -1032,12 +1073,14 @@ layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
     }
   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
           == LAYOUT_VERTICAL)
-    *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
+    *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT +
+                      IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
   else
-    *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
+    *height = maxph + (2 * WIDGET_BORDER_HEIGHT +
+                      IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
 }
 
-static void
+int
 layout_layout (Lisp_Object image_instance, 
               unsigned int width, unsigned int height, Lisp_Object domain)
 {
@@ -1047,7 +1090,11 @@ layout_layout (Lisp_Object image_instance,
   int x, y, maxph = 0, maxpw = 0, nitems = 0,
     horiz_spacing, vert_spacing, ph_adjust = 0;
   unsigned int gheight, gwidth;
-  
+
+  /* If we are not initialized then we won't have any children. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+      return 0;
+
   /* Pick up the border text if we have one. */
   if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
     {
@@ -1095,20 +1142,26 @@ layout_layout (Lisp_Object image_instance,
           == LAYOUT_HORIZONTAL)
     /* We have a larger area to display in so distribute the space
        evenly. */
-    horiz_spacing = (width - maxpw) / (nitems + 1);
+    horiz_spacing = (width - (maxpw + 
+                             IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) 
+      / (nitems + 1);
   else
-    horiz_spacing = (width - maxpw) / 2;
+    horiz_spacing = (width - maxpw) / 2
+      - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
 
   if (height < maxph)
     vert_spacing = WIDGET_BORDER_HEIGHT * 2;
   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
           == LAYOUT_VERTICAL)
-    vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1);
+    vert_spacing = (height - (maxph + ph_adjust + 
+                             IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) 
+      / (nitems + 1);
   else
-    vert_spacing = (height - (maxph + ph_adjust)) / 2;
+    vert_spacing = (height - (maxph + ph_adjust)) / 2 
+      - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
 
-  y = vert_spacing + ph_adjust;
-  x = horiz_spacing;
+  y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
+  x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
 
   /* Now flip through putting items where we want them, paying
      attention to justification. Make sure we don't mess with the
@@ -1156,6 +1209,41 @@ layout_layout (Lisp_Object image_instance,
       /* Now layout subwidgets if they require it. */
       image_instance_layout (glyph, gwidth, gheight, domain);
     }
+  return 1;
+}
+
+/* Layout subwindows if they are real subwindows. */
+static int
+native_layout_layout (Lisp_Object image_instance,
+                     unsigned int width, unsigned int height,
+                     Lisp_Object domain)
+{
+  Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object rest;
+  
+  /* The first time this gets called, the layout will be only
+     partially instantiated. The children get done in
+     post_instantiate. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+    return 0;
+
+  /* Defining this overrides the default layout_layout so we first have to call that to get 
+     suitable instances and values set up. */
+  layout_layout (image_instance, width, height, domain);
+
+  LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))
+    {
+      struct display_glyph_area dga;
+      dga.xoffset = 0;
+      dga.yoffset = 0;
+      dga.width = IMAGE_INSTANCE_WIDTH (ii);
+      dga.height = IMAGE_INSTANCE_HEIGHT (ii);
+
+      map_subwindow (XCAR (rest), 
+                    IMAGE_INSTANCE_XOFFSET (ii),
+                    IMAGE_INSTANCE_YOFFSET (ii), &dga);
+    }
+  return 1;
 }
 
 \f
@@ -1176,12 +1264,12 @@ syms_of_glyphs_widget (void)
   defkeyword (&Q_orientation, ":orientation");
   defkeyword (&Q_justify, ":justify");
   defkeyword (&Q_border, ":border");
+  defkeyword (&Q_margin_width, ":margin-width");
 
   defsymbol (&Qetched_in, "etched-in");
   defsymbol (&Qetched_out, "etched-out");
   defsymbol (&Qbevel_in, "bevel-in");
   defsymbol (&Qbevel_out, "bevel-out");
-  defsymbol (&Qwidget_callback_current_channel, "widget-callback-current-channel");
 }
 
 #define VALID_GUI_KEYWORDS(type) do {                                                  \
@@ -1225,7 +1313,9 @@ static void image_instantiator_buttons (void)
   IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
+  IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (button, query_geometry);
   IIFORMAT_VALID_KEYWORD (button,
                          Q_image, check_valid_glyph_or_instantiator);
@@ -1239,6 +1329,8 @@ static void image_instantiator_edit_fields (void)
   IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow);
   VALID_WIDGET_KEYWORDS (edit_field);
   VALID_GUI_KEYWORDS (edit_field);
 }
@@ -1248,6 +1340,8 @@ static void image_instantiator_combo_box (void)
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
   IIFORMAT_HAS_METHOD (combo_box, validate);
   IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow);
+
   VALID_GUI_KEYWORDS (combo_box);
 
   IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
@@ -1263,6 +1357,8 @@ static void image_instantiator_scrollbar (void)
   IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow);
   VALID_GUI_KEYWORDS (scrollbar);
 
   IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int_or_function);
@@ -1276,6 +1372,8 @@ static void image_instantiator_progress_guage (void)
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (progress_gauge, set_property);
   VALID_WIDGET_KEYWORDS (progress_gauge);
   VALID_GUI_KEYWORDS (progress_gauge);
@@ -1287,6 +1385,8 @@ static void image_instantiator_tree_view (void)
   IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
   IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (tree_view, query_geometry);
   VALID_WIDGET_KEYWORDS (tree_view);
   VALID_GUI_KEYWORDS (tree_view);
@@ -1299,6 +1399,8 @@ static void image_instantiator_tab_control (void)
   IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
   IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (tab_control, query_geometry);
   IIFORMAT_HAS_METHOD (tab_control, set_property);
   VALID_WIDGET_KEYWORDS (tab_control);
@@ -1312,24 +1414,50 @@ static void image_instantiator_labels (void)
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
   IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow);
   VALID_WIDGET_KEYWORDS (label);
   IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
 }
 
+#define VALID_LAYOUT_KEYWORDS(layout) \
+  VALID_WIDGET_KEYWORDS (layout);                                              \
+  IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation);     \
+  IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);       \
+  IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);               \
+  IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int);    \
+  IIFORMAT_VALID_KEYWORD (layout, Q_items,                             \
+                         check_valid_glyph_or_instantiator_list)
+
 static void image_instantiator_layout (void)
 {
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
-  IIFORMAT_HAS_METHOD (layout, possible_dest_types);
-  IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget);
+  IIFORMAT_HAS_METHOD (layout, instantiate);
+  IIFORMAT_HAS_METHOD (layout, post_instantiate);
+  IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (layout, normalize);
   IIFORMAT_HAS_METHOD (layout, query_geometry);
   IIFORMAT_HAS_METHOD (layout, layout);
-  VALID_WIDGET_KEYWORDS (layout);
-  IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation);
-  IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);
-  IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);
-  IIFORMAT_VALID_KEYWORD (layout, Q_items,
-                         check_valid_glyph_or_instantiator_list);
+
+  VALID_GUI_KEYWORDS (layout);
+  VALID_LAYOUT_KEYWORDS (layout);
+}
+
+static void image_instantiator_native_layout (void)
+{
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout");
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout);
+  IIFORMAT_HAS_METHOD (native_layout, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout);
+
+  VALID_GUI_KEYWORDS (native_layout);
+  VALID_LAYOUT_KEYWORDS (native_layout);
 }
 
 void
@@ -1345,6 +1473,7 @@ image_instantiator_format_create_glyphs_widget (void)
   image_instantiator_tab_control();
   image_instantiator_labels();
   image_instantiator_layout();
+  image_instantiator_native_layout();
 }
 
 void
@@ -1359,10 +1488,4 @@ void
 vars_of_glyphs_widget (void)
 {
   reinit_vars_of_glyphs_widget ();
-
-  DEFVAR_LISP ("widget-callback-current-channel", &Vwidget_callback_current_channel /*
-The domain that is current when a widget callback is invoked.
-This is invariably the frame that the widget is instantiated in.
-*/);
-  Vwidget_callback_current_channel = Qnil;
 }
index 4ed6e97..2b6d350 100644 (file)
@@ -98,7 +98,6 @@ DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
-DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
 #ifdef HAVE_JPEG
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
 #endif
@@ -128,7 +127,9 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
 
 #ifdef HAVE_WIDGETS
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
 DEFINE_DEVICE_IIFORMAT (x, widget);
+DEFINE_DEVICE_IIFORMAT (x, native_layout);
 DEFINE_DEVICE_IIFORMAT (x, button);
 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
 DEFINE_DEVICE_IIFORMAT (x, edit_field);
@@ -394,11 +395,14 @@ x_finalize_image_instance (Lisp_Image_Instance *p)
   if (!p->data)
     return;
 
-  if (DEVICE_LIVE_P (XDEVICE (p->device)))
+  if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
     {
-      Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
-
-      if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
+      Display *dpy = DEVICE_X_DISPLAY 
+       (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
+      if (0)
+       ;
+#ifdef HAVE_WIDGETS
+      else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
        {
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
            {
@@ -408,10 +412,15 @@ x_finalize_image_instance (Lisp_Image_Instance *p)
 #endif
              lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
              lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
+
+             /* We can release the callbacks again. */
+             ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
+
              IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
              IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
            }
        }
+#endif
       else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
        {
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
@@ -2210,11 +2219,11 @@ x_update_widget (Lisp_Image_Instance *p)
   /* Possibly update the colors and font */
   if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
       ||
-      XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (p))->faces_changed
+      XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
       ||
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
     {
-      update_widget_face (wv, p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p));
+      update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
     }
 
   /* Possibly update the text. */
@@ -2267,15 +2276,15 @@ x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   /* This function can GC */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   struct frame* f = XFRAME (frame);
   Display *dpy;
   Screen *xs;
   Window pw, win;
   XSetWindowAttributes xswa;
   Mask valueMask = 0;
-  unsigned int w = IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii),
-    h = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii);
+  unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
+    h = IMAGE_INSTANCE_HEIGHT (ii);
 
   if (!DEVICE_X_P (XDEVICE (device)))
     signal_simple_error ("Not an X device", device);
@@ -2420,7 +2429,7 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
   struct device* d = XDEVICE (device);
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   struct frame* f = XFRAME (frame);
   char* nm=0;
   Widget wid;
@@ -2478,12 +2487,12 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
      anymore...*/
   pixel = FACE_FOREGROUND
     (IMAGE_INSTANCE_WIDGET_FACE (ii),
-     IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+     IMAGE_INSTANCE_FRAME (ii));
   fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
 
   pixel = FACE_BACKGROUND
     (IMAGE_INSTANCE_WIDGET_FACE (ii),
-     IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+     IMAGE_INSTANCE_FRAME (ii));
   bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
 
   lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
@@ -2513,6 +2522,9 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   XtSetMappedWhenManaged (wid, TRUE);
 
   free_widget_value_tree (wv);
+  /* A kludgy but simple way to make sure the callback for a widget
+     doesn't get deleted. */
+  gcpro_popup_callbacks (id);
 }
 
 /* get properties of a control */
@@ -2529,6 +2541,18 @@ x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
   return Qunbound;
 }
 
+/* Instantiate a layout control for putting other widgets in. */
+static void
+x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                            int dest_mask, Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+  x_widget_instantiate (image_instance, instantiator, pointer_fg,
+                       pointer_bg, dest_mask, domain, "layout", 0);
+}
+
 /* Instantiate a button widget. Unfortunately instantiated widgets are
    particular to a frame since they need to have a parent. It's not
    like images where you just select the image into the context you
@@ -2692,7 +2716,7 @@ x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                                IMAGE_INSTANCE_WIDGET_ITEMS (ii));
 
   update_tab_widget_face (wv, ii,
-                         IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+                         IMAGE_INSTANCE_FRAME (ii));
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "tab-control", wv);
@@ -2707,7 +2731,7 @@ x_tab_control_update (Lisp_Object image_instance)
   /* Possibly update the face. */
   if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
       ||
-      XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))->faces_changed
+      XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
       ||
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
@@ -2718,7 +2742,7 @@ x_tab_control_update (Lisp_Object image_instance)
        return;
 
       update_tab_widget_face (wv, ii,
-                             IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+                             IMAGE_INSTANCE_FRAME (ii));
 
       lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
     }
@@ -2775,7 +2799,9 @@ image_instantiator_format_create_glyphs_x (void)
 {
   IIFORMAT_VALID_CONSOLE (x, nothing);
   IIFORMAT_VALID_CONSOLE (x, string);
+#ifdef HAVE_WIDGETS
   IIFORMAT_VALID_CONSOLE (x, layout);
+#endif
   IIFORMAT_VALID_CONSOLE (x, formatted_string);
   IIFORMAT_VALID_CONSOLE (x, inherit);
 #ifdef HAVE_XPM
@@ -2800,12 +2826,15 @@ image_instantiator_format_create_glyphs_x (void)
   INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
   IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
 #ifdef HAVE_WIDGETS
+  /* layout widget */
+  INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
+  IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
   /* button widget */
   INITIALIZE_DEVICE_IIFORMAT (x, button);
   IIFORMAT_HAS_DEVMETHOD (x, button, property);
   IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
   IIFORMAT_HAS_DEVMETHOD (x, button, update);
-
+  /* general widget methods. */
   INITIALIZE_DEVICE_IIFORMAT (x, widget);
   IIFORMAT_HAS_DEVMETHOD (x, widget, property);
   /* progress gauge */
index 3ef30f3..791926b 100644 (file)
@@ -122,6 +122,11 @@ struct x_subwindow_data
   (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.id)
 #define IMAGE_INSTANCE_X_CLIPWIDGET(i) \
   (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.clip_window)
+#define IMAGE_INSTANCE_X_SUBWINDOW_ID(i) \
+  (* (Window *) & IMAGE_INSTANCE_SUBWINDOW_ID (i))
+#define IMAGE_INSTANCE_X_WIDGET_ID(i) \
+  (* (Widget *) & IMAGE_INSTANCE_SUBWINDOW_ID (i))
+
 #define XIMAGE_INSTANCE_X_SUBWINDOW_PARENT(i) \
   IMAGE_INSTANCE_X_SUBWINDOW_PARENT (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(i) \
@@ -136,10 +141,14 @@ struct x_subwindow_data
   IMAGE_INSTANCE_X_CLIPWIDGET (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_X_CLIPWINDOW(i) \
   IMAGE_INSTANCE_X_CLIPWINDOW (XIMAGE_INSTANCE (i))
-#define IMAGE_INSTANCE_X_SUBWINDOW_ID(i) \
-  (* (Window *) & IMAGE_INSTANCE_SUBWINDOW_ID (i))
-#define IMAGE_INSTANCE_X_WIDGET_ID(i) \
-  (* (Widget *) & IMAGE_INSTANCE_SUBWINDOW_ID (i))
+#define XIMAGE_INSTANCE_X_WIDGET_ID(i) \
+  IMAGE_INSTANCE_X_WIDGET_ID (XIMAGE_INSTANCE (i))
+
+#define DOMAIN_X_WIDGET(domain) \
+  ((IMAGE_INSTANCEP (domain) && \
+  X_SUBWINDOW_INSTANCE_DATA (XIMAGE_INSTANCE (domain))) ? \
+   XIMAGE_INSTANCE_X_WIDGET_ID (domain) : \
+   FRAME_X_CONTAINER_WIDGET (f) (DOMAIN_XFRAME (domain)))
 
 #endif /* HAVE_X_WINDOWS */
 #endif /* INCLUDED_glyphs_x_h_ */
index 77ae598..95fc7f6 100644 (file)
@@ -50,19 +50,21 @@ struct image_instantiator_methods;
   tiff                         color-pixmap
   bmp                          color-pixmap
   cursor-font                  pointer
-  mswindows-resource           pointer
+  mswindows-resource           pointer, color-pixmap
   font                         pointer
   subwindow                    subwindow
   inherit                      mono-pixmap
   autodetect                   mono-pixmap, color-pixmap, pointer, text
   button                       widget
   edit-field                   widget
-  combo        -box                    widget
+  combo-box                    widget
   progress-gauge               widget
   tab-control                  widget
   tree-view                    widget
   scrollbar                    widget
-  static                       widget
+  label                                widget
+  layout                       widget
+  native-layout                        widget
 */
 
 /* These are methods specific to a particular format of image instantiator
@@ -96,6 +98,13 @@ enum image_instance_geometry
 #define WIDGET_BORDER_HEIGHT 4
 #define WIDGET_BORDER_WIDTH 4
 
+enum governing_domain
+{
+  GOVERNING_DOMAIN_WINDOW,
+  GOVERNING_DOMAIN_FRAME,
+  GOVERNING_DOMAIN_DEVICE
+};
+
 struct image_instantiator_methods
 {
   Lisp_Object symbol;
@@ -120,6 +129,10 @@ struct image_instantiator_methods
   Lisp_Object (*normalize_method) (Lisp_Object instantiator,
                                   Lisp_Object console_type);
 
+  /* Governing domain method: Return an int indicating what type of
+     domain an instance in this format is governed by. */
+  int (*governing_domain_method) (void);
+
   /* Possible-dest-types method: Return a mask indicating what dest types
      are compatible with this format. */
   int (*possible_dest_types_method) (void);
@@ -134,6 +147,11 @@ struct image_instantiator_methods
                              Lisp_Object pointer_bg,
                              int dest_mask,
                              Lisp_Object domain);
+  /* Post instantiate method: finish instantiation of the image
+     instance. */
+  void (*post_instantiate_method) (Lisp_Object image_instance,
+                                  Lisp_Object instantiator,
+                                  Lisp_Object domain);
   /* Property method: Given an image instance, return device specific
      properties. */
   Lisp_Object (*property_method) (Lisp_Object image_instance,
@@ -155,10 +173,10 @@ struct image_instantiator_methods
                                 Lisp_Object domain);
 
   /* Layout the instance and its children bounded by the provided
-     dimensions. */
-  void (*layout_method) (Lisp_Object image_instance,
-                                 unsigned int width, unsigned int height,
-                                 Lisp_Object domain);
+     dimensions. Returns success or failure. */
+  int (*layout_method) (Lisp_Object image_instance,
+                       unsigned int width, unsigned int height,
+                       Lisp_Object domain);
 };
 
 /***** Calling an image-instantiator method *****/
@@ -187,7 +205,7 @@ do {                                                        \
    the specified value */
 
 #define IIFORMAT_METH_OR_GIVEN(mstruc, m, args, given) \
-  (HAS_IIFORMAT_METH_P (mstruc, m) ?                   \
+  ((mstruc && HAS_IIFORMAT_METH_P (mstruc, m)) ?               \
    IIFORMAT_METH (mstruc, m, args) : (given))
 
 /***** Defining new image-instantiator types *****/
@@ -336,6 +354,7 @@ void initialize_subwindow_image_instance (Lisp_Image_Instance*);
 void subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
                            int dest_mask, Lisp_Object domain);
+int subwindow_governing_domain (void);
 void widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                         Lisp_Object pointer_fg, Lisp_Object pointer_bg,
                         int dest_mask, Lisp_Object domain);
@@ -346,6 +365,9 @@ void image_instance_query_geometry (Lisp_Object image_instance,
 void image_instance_layout (Lisp_Object image_instance,
                            unsigned int width, unsigned int height,
                            Lisp_Object domain);
+int layout_layout (Lisp_Object image_instance,
+                  unsigned int width, unsigned int height,
+                  Lisp_Object domain);
 int invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w);
 
 DECLARE_DOESNT_RETURN (incompatible_image_types (Lisp_Object instantiator,
@@ -395,6 +417,18 @@ DECLARE_LRECORD (image_instance, Lisp_Image_Instance);
 #define CHECK_IMAGE_INSTANCE(x) CHECK_RECORD (x, image_instance)
 #define CONCHECK_IMAGE_INSTANCE(x) CONCHECK_RECORD (x, image_instance)
 
+#ifdef ERROR_CHECK_GLYPHS
+void check_image_instance_structure (Lisp_Object instance);
+void check_window_subwindow_cache (struct window* w);
+#define ERROR_CHECK_IMAGE_INSTANCE(ii) \
+  check_image_instance_structure (ii)
+#define ERROR_CHECK_SUBWINDOW_CACHE(w) \
+  check_window_subwindow_cache (w)
+#else
+#define ERROR_CHECK_IMAGE_INSTANCE(ii)
+#define ERROR_CHECK_SUBWINDOW_CACHE(w)
+#endif
+
 enum image_instance_type
 {
   IMAGE_UNKNOWN,
@@ -404,8 +438,7 @@ enum image_instance_type
   IMAGE_COLOR_PIXMAP,
   IMAGE_POINTER,
   IMAGE_SUBWINDOW,
-  IMAGE_WIDGET,
-  IMAGE_LAYOUT
+  IMAGE_WIDGET
 };
 
 #define IMAGE_NOTHING_MASK (1 << 0)
@@ -415,7 +448,13 @@ enum image_instance_type
 #define IMAGE_POINTER_MASK (1 << 4)
 #define IMAGE_SUBWINDOW_MASK (1 << 5)
 #define IMAGE_WIDGET_MASK (1 << 6)
-#define IMAGE_LAYOUT_MASK (1 << 7)
+
+/* This depends on the fact that enums are assigned consecutive
+   integers starting at 0. (Remember that IMAGE_UNKNOWN is the
+   first enum.) I'm fairly sure this behavior is ANSI-mandated,
+   so there should be no portability problems here. */
+#define image_instance_type_to_mask(type) \
+  ((int) (1 << ((int) (type) - 1)))
 
 #define IMAGE_INSTANCE_TYPE_P(ii, type) \
 (IMAGE_INSTANCEP (ii) && XIMAGE_INSTANCE_TYPE (ii) == type)
@@ -434,8 +473,6 @@ enum image_instance_type
      IMAGE_INSTANCE_TYPE_P (ii, IMAGE_SUBWINDOW)
 #define WIDGET_IMAGE_INSTANCEP(ii) \
      IMAGE_INSTANCE_TYPE_P (ii, IMAGE_WIDGET)
-#define LAYOUT_IMAGE_INSTANCEP(ii) \
-     IMAGE_INSTANCE_TYPE_P (ii, IMAGE_LAYOUT)
 
 #define CHECK_NOTHING_IMAGE_INSTANCE(x) do {                   \
   CHECK_IMAGE_INSTANCE (x);                                    \
@@ -480,23 +517,20 @@ enum image_instance_type
     x = wrong_type_argument (Qwidget_image_instance_p, (x));   \
 } while (0)
 
-#define CHECK_LAYOUT_IMAGE_INSTANCE(x) do {                    \
-  CHECK_IMAGE_INSTANCE (x);                                    \
-  if (!LAYOUT_IMAGE_INSTANCEP (x))                             \
-    x = wrong_type_argument (Qlayout_image_instance_p, (x));   \
-} while (0)
-
 struct Lisp_Image_Instance
 {
   struct lcrecord_header header;
-  Lisp_Object device;
+  Lisp_Object domain;          /* The domain in which we were cached. */
+  Lisp_Object device;          /* The device of the domain. Recorded
+                                  since the domain may get deleted
+                                  before us. */
   Lisp_Object name;
   /* The glyph from which we were instantiated. This is a weak
      reference. */
   Lisp_Object parent;
   enum image_instance_type type;
   unsigned int x_offset, y_offset;     /* for layout purposes */
-  unsigned int width, height;
+  unsigned int width, height, margin_width;
   unsigned long display_hash; /* Hash value representing the structure
                                 of the image_instance when it was
                                 last displayed. */
@@ -505,6 +539,7 @@ struct Lisp_Image_Instance
   unsigned int text_changed : 1;
   unsigned int layout_changed : 1; 
   unsigned int optimize_output : 1; /* For outputting layouts. */
+  unsigned int initialized : 1; /* When we're fully done. */
 
   union
   {
@@ -529,22 +564,29 @@ struct Lisp_Image_Instance
     } pixmap; /* used for pointers as well */
     struct
     {
-      Lisp_Object frame;
       void* subwindow;         /* specific devices can use this as necessary */
-      unsigned int being_displayed : 1;        /* used to detect when needs to be unmapped */
+      struct 
+      {                                /* We need these so we can do without
+                                  subwindow_cachel */
+       unsigned int x, y;      
+       unsigned int width, height;
+      } display_data;
+      unsigned int being_displayed : 1; /* used to detect when needs
+                                          to be unmapped */
       unsigned int v_resize : 1;       /* Whether the vsize is allowed to change. */
       unsigned int h_resize : 1;       /* Whether the hsize is allowed to change. */
       unsigned int orientation : 1; /* Vertical or horizontal. */
       unsigned int justification : 2; /* Left, right or center. */
-      /* Face for colors and font. We specify this here becuase we
+      /* Face for colors and font. We specify this here because we
         want people to be able to put :face in the instantiator
         spec. Using gyph-face is more inconvenient, although more
         general. */
       Lisp_Object face;
       Lisp_Object type;
       Lisp_Object props;       /* properties or border*/
-      Lisp_Object items;       /* a list of gui_items or children */
+      Lisp_Object items;       /* a list of displayed gui_items */
       Lisp_Object pending_items; /* gui_items that should be displayed */
+      Lisp_Object children;    /* a list of children */
       Lisp_Object width;       /* dynamic width spec. */
       Lisp_Object height;      /* dynamic height spec. */
       /* Change flags to augment dirty. */
@@ -568,7 +610,10 @@ struct Lisp_Image_Instance
 #define IMAGE_INSTANCE_HASH_DEPTH 0
 
 /* Accessor macros. */
+#define IMAGE_INSTANCE_DOMAIN(i) ((i)->domain)
+#define IMAGE_INSTANCE_DOMAIN_LIVE_P(i) (DOMAIN_LIVE_P ((i)->domain))
 #define IMAGE_INSTANCE_DEVICE(i) ((i)->device)
+#define IMAGE_INSTANCE_FRAME(i) (DOMAIN_FRAME ((i)->domain))
 #define IMAGE_INSTANCE_NAME(i) ((i)->name)
 #define IMAGE_INSTANCE_PARENT(i) ((i)->parent)
 #define IMAGE_INSTANCE_GLYPH(i) (image_instance_parent_glyph(i))
@@ -576,14 +621,18 @@ struct Lisp_Image_Instance
 #define IMAGE_INSTANCE_XOFFSET(i) ((i)->x_offset)
 #define IMAGE_INSTANCE_YOFFSET(i) ((i)->y_offset)
 #define IMAGE_INSTANCE_WIDTH(i) ((i)->width)
+#define IMAGE_INSTANCE_MARGIN_WIDTH(i) ((i)->margin_width)
 #define IMAGE_INSTANCE_HEIGHT(i) ((i)->height)
+#define IMAGE_INSTANCE_INITIALIZED(i) ((i)->initialized)
 #define IMAGE_INSTANCE_DISPLAY_HASH(i) ((i)->display_hash)
 #define IMAGE_INSTANCE_PIXMAP_TYPE_P(i)                        \
  ((IMAGE_INSTANCE_TYPE (i) == IMAGE_MONO_PIXMAP)       \
   || (IMAGE_INSTANCE_TYPE (i) == IMAGE_COLOR_PIXMAP))
 #define IMAGE_INSTANCE_DIRTYP(i) ((i)->dirty)
 #define IMAGE_INSTANCE_NEEDS_LAYOUT(i) \
-  (IMAGE_INSTANCE_DIRTYP (i) && IMAGE_INSTANCE_LAYOUT_CHANGED (i))
+  ((IMAGE_INSTANCE_DIRTYP (i) && IMAGE_INSTANCE_LAYOUT_CHANGED (i)) \
+   || (FRAMEP (IMAGE_INSTANCE_FRAME (i)) \
+       && XFRAME (IMAGE_INSTANCE_FRAME (i))->size_changed))
 #define IMAGE_INSTANCE_FACE(i) \
   (GLYPHP (IMAGE_INSTANCE_GLYPH (i)) ? \
    XGLYPH_FACE (IMAGE_INSTANCE_GLYPH (i)) : Qnil)
@@ -627,12 +676,14 @@ struct Lisp_Image_Instance
 #define IMAGE_INSTANCE_PIXMAP_TIMEOUT(i) ((i)->u.pixmap.timeout)
 
 /* Subwindow properties */
-#define IMAGE_INSTANCE_SUBWINDOW_WIDTH(i) \
- IMAGE_INSTANCE_WIDTH(i)
-#define IMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) \
-  IMAGE_INSTANCE_HEIGHT(i)
 #define IMAGE_INSTANCE_SUBWINDOW_ID(i) ((i)->u.subwindow.subwindow)
-#define IMAGE_INSTANCE_SUBWINDOW_FRAME(i) ((i)->u.subwindow.frame)
+/* Display data. */
+#define IMAGE_INSTANCE_DISPLAY_X(i) ((i)->u.subwindow.display_data.x)
+#define IMAGE_INSTANCE_DISPLAY_Y(i) ((i)->u.subwindow.display_data.y)
+#define IMAGE_INSTANCE_DISPLAY_WIDTH(i) \
+  ((i)->u.subwindow.display_data.width)
+#define IMAGE_INSTANCE_DISPLAY_HEIGHT(i) \
+  ((i)->u.subwindow.display_data.height)
 #define IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(i) \
 ((i)->u.subwindow.being_displayed)
 #define IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP(i) \
@@ -669,11 +720,17 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (i)) :  \
 #define IMAGE_INSTANCE_WIDGET_TEXT(i) XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (i))->name
 
 /* Layout properties */
-#define IMAGE_INSTANCE_LAYOUT_CHILDREN(i) ((i)->u.subwindow.items)
+#define IMAGE_INSTANCE_LAYOUT_CHILDREN(i) ((i)->u.subwindow.children)
 #define IMAGE_INSTANCE_LAYOUT_BORDER(i) ((i)->u.subwindow.props)
 
+#define XIMAGE_INSTANCE_DOMAIN(i) \
+  IMAGE_INSTANCE_DOMAIN (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_DOMAIN_LIVE_P(i) \
+  IMAGE_INSTANCE_DOMAIN_LIVE_P (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_DEVICE(i) \
   IMAGE_INSTANCE_DEVICE (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_FRAME(i) \
+  IMAGE_INSTANCE_FRAME (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_NAME(i) \
   IMAGE_INSTANCE_NAME (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_GLYPH(i) \
@@ -694,8 +751,12 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (i)) :   \
   IMAGE_INSTANCE_NEEDS_LAYOUT (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_WIDTH(i) \
   IMAGE_INSTANCE_WIDTH (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_MARGIN_WIDTH(i) \
+  IMAGE_INSTANCE_MARGIN_WIDTH (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_HEIGHT(i) \
   IMAGE_INSTANCE_HEIGHT (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_INITIALIZED(i) \
+  IMAGE_INSTANCE_INITIALIZED (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_FACE(i) \
   IMAGE_INSTANCE_FACE (XIMAGE_INSTANCE (i))
 
@@ -767,14 +828,16 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (i)) :  \
 #define XIMAGE_INSTANCE_LAYOUT_BORDER(i) \
   IMAGE_INSTANCE_LAYOUT_BORDER (XIMAGE_INSTANCE (i))
 
-#define XIMAGE_INSTANCE_SUBWINDOW_WIDTH(i) \
-  IMAGE_INSTANCE_SUBWINDOW_WIDTH (XIMAGE_INSTANCE (i))
-#define XIMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) \
-  IMAGE_INSTANCE_SUBWINDOW_HEIGHT (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_SUBWINDOW_ID(i) \
   IMAGE_INSTANCE_SUBWINDOW_ID (XIMAGE_INSTANCE (i))
-#define XIMAGE_INSTANCE_SUBWINDOW_FRAME(i) \
-  IMAGE_INSTANCE_SUBWINDOW_FRAME (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_DISPLAY_X(i) \
+  IMAGE_INSTANCE_DISPLAY_X (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_DISPLAY_Y(i) \
+  IMAGE_INSTANCE_DISPLAY_Y (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_DISPLAY_WIDTH(i) \
+  IMAGE_INSTANCE_DISPLAY_WIDTH (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_DISPLAY_HEIGHT(i) \
+  IMAGE_INSTANCE_DISPLAY_HEIGHT (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(i) \
   IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (XIMAGE_INSTANCE (i))
 #define XIMAGE_INSTANCE_SUBWINDOW_ORIENT(i) \
@@ -785,6 +848,11 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (i)) :   \
 #define MARK_IMAGE_INSTANCE_CHANGED(i) \
   (IMAGE_INSTANCE_DIRTYP (i) = 1);
 
+Lisp_Object image_instance_device (Lisp_Object instance);
+Lisp_Object image_instance_frame (Lisp_Object instance);
+Lisp_Object image_instance_window (Lisp_Object instance);
+int image_instance_live_p (Lisp_Object instance);
+
 #ifdef HAVE_XPM
 Lisp_Object evaluate_xpm_color_symbols (void);
 Lisp_Object pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid);
@@ -883,8 +951,7 @@ extern Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y;
 extern Lisp_Object Q_foreground, Q_background, Q_face, Q_descriptor, Q_group;
 extern Lisp_Object Q_width, Q_height, Q_pixel_width, Q_pixel_height, Q_text;
 extern Lisp_Object Q_items, Q_properties, Q_image, Qimage_conversion_error;
-extern Lisp_Object Q_orientation, Qupdate_widget_instances;
-extern Lisp_Object Qwidget_callback_current_channel;
+extern Lisp_Object Q_orientation, Q_margin_width;
 extern Lisp_Object Vcontinuation_glyph, Vcontrol_arrow_glyph, Vhscroll_glyph;
 extern Lisp_Object Vinvisible_text_glyph, Voctal_escape_glyph, Vtruncation_glyph;
 extern Lisp_Object Vxemacs_logo;
@@ -949,18 +1016,55 @@ struct glyph_cachel
 #define OCT_ESC_GLYPH_INDEX    (glyph_index) 4
 #define INVIS_GLYPH_INDEX      (glyph_index) 5
 
-#define GLYPH_CACHEL(window, index)                    \
-  Dynarr_atp (window->glyph_cachels, index)
-#define GLYPH_CACHEL_GLYPH(window, index)              \
-  Dynarr_atp (window->glyph_cachels, index)->glyph
-#define GLYPH_CACHEL_WIDTH(window, index)              \
-  Dynarr_atp (window->glyph_cachels, index)->width
-#define GLYPH_CACHEL_ASCENT(window, index)             \
-  Dynarr_atp (window->glyph_cachels, index)->ascent
-#define GLYPH_CACHEL_DESCENT(window, index)            \
-  Dynarr_atp (window->glyph_cachels, index)->descent
-#define GLYPH_CACHEL_DIRTYP(window, index)             \
-  Dynarr_atp (window->glyph_cachels, index)->dirty
+#ifdef ERROR_CHECK_GLYPHS
+
+#include "window.h"
+
+INLINE_HEADER int
+GLYPH_CACHEL_WIDTH (struct window *window, int ind);
+INLINE_HEADER int
+GLYPH_CACHEL_WIDTH (struct window *window, int ind)
+{
+  int wid = Dynarr_atp (window->glyph_cachels, ind)->width;
+  assert (wid >= 0 && wid < 10000);
+  return wid;
+}
+INLINE_HEADER int
+GLYPH_CACHEL_ASCENT (struct window *window, int ind);
+INLINE_HEADER int
+GLYPH_CACHEL_ASCENT (struct window *window, int ind)
+{
+  int wid = Dynarr_atp (window->glyph_cachels, ind)->ascent;
+  assert (wid >= 0 && wid < 10000);
+  return wid;
+}
+INLINE_HEADER int
+GLYPH_CACHEL_DESCENT (struct window *window, int ind);
+INLINE_HEADER int
+GLYPH_CACHEL_DESCENT (struct window *window, int ind)
+{
+  int wid = Dynarr_atp (window->glyph_cachels, ind)->descent;
+  assert (wid >= 0 && wid < 10000);
+  return wid;
+}
+
+#else /* not ERROR_CHECK_GLYPHS */
+
+#define GLYPH_CACHEL_WIDTH(window, ind)                \
+  Dynarr_atp (window->glyph_cachels, ind)->width
+#define GLYPH_CACHEL_ASCENT(window, ind)               \
+  Dynarr_atp (window->glyph_cachels, ind)->ascent
+#define GLYPH_CACHEL_DESCENT(window, ind)              \
+  Dynarr_atp (window->glyph_cachels, ind)->descent
+
+#endif /* not ERROR_CHECK_GLYPHS */
+
+#define GLYPH_CACHEL(window, ind)                      \
+  Dynarr_atp (window->glyph_cachels, ind)
+#define GLYPH_CACHEL_GLYPH(window, ind)                \
+  Dynarr_atp (window->glyph_cachels, ind)->glyph
+#define GLYPH_CACHEL_DIRTYP(window, ind)               \
+  Dynarr_atp (window->glyph_cachels, ind)->dirty
 
 void mark_glyph_cachels (glyph_cachel_dynarr *elements);
 void mark_glyph_cachels_as_not_updated (struct window *w);
@@ -985,34 +1089,17 @@ void get_display_tables (struct window *, face_index,
  *                            Subwindow Object                              *
  ****************************************************************************/
 
-/* redisplay needs a per-frame cache of subwindows being displayed so
- * that we known when to unmap them */
-typedef struct subwindow_cachel subwindow_cachel;
-struct subwindow_cachel
-{
-  Lisp_Object subwindow;
-  unsigned int x, y;
-  unsigned int width, height;
-  unsigned int being_displayed : 1;
-  unsigned int updated : 1;
-};
-
-typedef struct
-{
-  Dynarr_declare (subwindow_cachel);
-} subwindow_cachel_dynarr;
-
-void mark_subwindow_cachels (subwindow_cachel_dynarr *elements);
-void mark_subwindow_cachels_as_not_updated (struct frame *f);
-void reset_subwindow_cachels (struct frame *f);
 void unmap_subwindow (Lisp_Object subwindow);
 void map_subwindow (Lisp_Object subwindow, int x, int y,
                    struct display_glyph_area *dga);
 int find_matching_subwindow (struct frame* f, int x, int y, int width, int height);
 void update_widget (Lisp_Object widget);
+void update_widget_instances (Lisp_Object frame);
 void update_subwindow (Lisp_Object subwindow);
 Lisp_Object image_instance_parent_glyph (struct Lisp_Image_Instance*);
 int image_instance_changed (Lisp_Object image);
+void free_frame_subwindow_instance_cache (struct frame* f);
+void reset_frame_subwindow_instance_cache (struct frame* f);
 
 struct expose_ignore
 {
index 9fd0b37..503c631 100644 (file)
@@ -22,13 +22,13 @@ Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include "lisp.h"
+#include "console-msw.h"
 #include "redisplay.h"
 #include "gui.h"
 #include "glyphs.h"
 #include "frame.h"
-#include "events.h"
 #include "elhash.h"
-#include "console-msw.h"
+#include "events.h"
 #include "buffer.h"
 
 /*
@@ -84,15 +84,8 @@ mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, LPARAM id)
 
   mswindows_enqueue_dispatch_event (event);
   /* The result of this evaluation could cause other instances to change so 
-     enqueue an update callback to check this. We also have to make sure that
-     the function does not appear in the command history.
-     #### I'm sure someone can tell me how to optimize this. */
-  mswindows_enqueue_misc_user_event
-    (frame, Qeval, 
-     list3 (Qlet,
-           list2 (Qthis_command,
-                  Qlast_command),
-           list2 (Qupdate_widget_instances, frame)));
+     enqueue an update callback to check this. */
+  enqueue_magic_eval_event (update_widget_instances, frame);
   return Qt;
 }
 
index 2cade75..8aebe30 100644 (file)
@@ -229,10 +229,6 @@ popup_selection_callback (Widget widget, LWLIB_ID ignored_id,
   VOID_TO_LISP (data, client_data);
   XSETFRAME (frame, f);
 
-  image_instance = XCAR (data);
-  callback = XCAR (XCDR (data));
-  callback_ex = XCDR (XCDR (data));
-
 #if 0
   /* #### What the hell?  I can't understand why this call is here,
      and doing it is really courting disaster in the new event
@@ -255,6 +251,9 @@ popup_selection_callback (Widget widget, LWLIB_ID ignored_id,
     }
   else
     {
+      image_instance = XCAR (data);
+      callback = XCAR (XCDR (data));
+      callback_ex = XCDR (XCDR (data));
       update_subwindows_p = 1;
 
       if (!NILP (callback_ex) && !UNBOUNDP (callback_ex))
@@ -294,16 +293,9 @@ popup_selection_callback (Widget widget, LWLIB_ID ignored_id,
   if (!NILP (event))
     enqueue_Xt_dispatch_event (event);
   /* The result of this evaluation could cause other instances to change so 
-     enqueue an update callback to check this. We also have to make sure that
-     the function does not appear in the command history.
-     #### I'm sure someone can tell me how to optimize this. */
+     enqueue an update callback to check this. */
   if (update_subwindows_p && !NILP (event))
-    signal_special_Xt_user_event (frame, Qeval,
-                                 list3 (Qlet,
-                                        list2 (Qthis_command,
-                                               Qlast_command),
-                                        list2 (Qupdate_widget_instances,
-                                               frame)));
+    enqueue_magic_eval_event (update_widget_instances, frame);
 }
 
 #if 1
index 5705cea..47e21a5 100644 (file)
--- a/src/gui.c
+++ b/src/gui.c
@@ -81,10 +81,10 @@ get_gui_callback (Lisp_Object data, Lisp_Object *fn, Lisp_Object *arg)
       Vquit_flag = Qt;
     }
   else if (SYMBOLP (data)
-      || (COMPILED_FUNCTIONP (data)
-         && XCOMPILED_FUNCTION (data)->flags.interactivep)
-      || (CONSP (data) && (EQ (XCAR (data), Qlambda))
-         && !NILP (Fassq (Qinteractive, Fcdr (Fcdr (data))))))
+          || (COMPILED_FUNCTIONP (data)
+              && XCOMPILED_FUNCTION (data)->flags.interactivep)
+          || (CONSP (data) && (EQ (XCAR (data), Qlambda))
+              && !NILP (Fassq (Qinteractive, Fcdr (Fcdr (data))))))
     {
       *fn = Qcall_interactively;
       *arg = data;
index bd14ddc..bf46ba2 100644 (file)
--- a/src/nt.c
+++ b/src/nt.c
@@ -47,8 +47,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include <stdlib.h>
 #include <stdio.h>
 
-#include <windows.h>
-#include <mmsystem.h>
+#include "syswindows.h"
 
 #include "nt.h"
 #include <sys/dir.h>
@@ -2004,9 +2003,15 @@ int setitimer (int kind, const struct itimerval* itnew,
     return errno = EINVAL;
 }
 
+\f
+/*--------------------------------------------------------------------*/
+/*                        Memory-mapped files                         */
+/*--------------------------------------------------------------------*/
+
 int
 open_input_file (file_data *p_file, const char *filename)
 {
+  /* Synched with FSF 20.6.  We fixed some warnings. */
   HANDLE file;
   HANDLE file_mapping;
   void  *file_base;
@@ -2036,6 +2041,179 @@ open_input_file (file_data *p_file, const char *filename)
   return TRUE;
 }
 
+int
+open_output_file (file_data *p_file, const char *filename, unsigned long size)
+{
+  /* Synched with FSF 20.6.  We fixed some warnings. */
+  HANDLE file;
+  HANDLE file_mapping;
+  void  *file_base;
+
+  file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+  if (file == INVALID_HANDLE_VALUE) 
+    return FALSE;
+
+  file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE, 
+                                   0, size, NULL);
+  if (!file_mapping) 
+    return FALSE;
+  
+  file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
+  if (file_base == NULL) 
+    return FALSE;
+  
+  p_file->name = filename;
+  p_file->size = size;
+  p_file->file = file;
+  p_file->file_mapping = file_mapping;
+  p_file->file_base = (char*) file_base;
+
+  return TRUE;
+}
+
+#if 1 /* !defined(__MINGW32__) */
+/* Return pointer to section header for section containing the given
+   relative virtual address. */
+static IMAGE_SECTION_HEADER *
+rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
+{
+  /* Synched with FSF 20.6.  We added MINGW32 stuff. */
+  PIMAGE_SECTION_HEADER section;
+  int i;
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+    {
+      /* Some linkers (eg. the NT SDK linker I believe) swapped the
+        meaning of these two values - or rather, they ignored
+        VirtualSize entirely and always set it to zero.  This affects
+        some very old exes (eg. gzip dated Dec 1993).  Since
+        mswindows_executable_type relies on this function to work reliably,
+        we need to cope with this.  */
+      DWORD real_size = max (section->SizeOfRawData,
+                            section->Misc.VirtualSize);
+      if (rva >= section->VirtualAddress
+         && rva < section->VirtualAddress + real_size)
+       return section;
+      section++;
+    }
+  return NULL;
+}
+#endif
+
+void
+mswindows_executable_type (const char * filename, int * is_dos_app,
+                          int * is_cygnus_app)
+{
+  /* Synched with FSF 20.6.  We added MINGW32 stuff and casts. */
+  file_data executable;
+  char * p;
+
+  /* Default values in case we can't tell for sure.  */
+  *is_dos_app = FALSE;
+  *is_cygnus_app = FALSE;
+
+  if (!open_input_file (&executable, filename))
+    return;
+
+  p = strrchr (filename, '.');
+
+  /* We can only identify DOS .com programs from the extension. */
+  if (p && stricmp (p, ".com") == 0)
+    *is_dos_app = TRUE;
+  else if (p && (stricmp (p, ".bat") == 0 ||
+                stricmp (p, ".cmd") == 0))
+    {
+      /* A DOS shell script - it appears that CreateProcess is happy to
+        accept this (somewhat surprisingly); presumably it looks at
+        COMSPEC to determine what executable to actually invoke.
+        Therefore, we have to do the same here as well. */
+      /* Actually, I think it uses the program association for that
+        extension, which is defined in the registry.  */
+      p = egetenv ("COMSPEC");
+      if (p)
+       mswindows_executable_type (p, is_dos_app, is_cygnus_app);
+    }
+  else
+    {
+      /* Look for DOS .exe signature - if found, we must also check that
+        it isn't really a 16- or 32-bit Windows exe, since both formats
+        start with a DOS program stub.  Note that 16-bit Windows
+        executables use the OS/2 1.x format. */
+
+#if 0 /* defined( __MINGW32__ ) */
+      /* mingw32 doesn't have enough headers to detect cygwin
+        apps, just do what we can. */
+      FILHDR * exe_header;
+
+      exe_header = (FILHDR*) executable.file_base;
+      if (exe_header->e_magic != DOSMAGIC)
+       goto unwind;
+
+      if ((char*) exe_header->e_lfanew > (char*) executable.size)
+       {
+         /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
+         *is_dos_app = TRUE;
+       } 
+      else if (exe_header->nt_signature != NT_SIGNATURE)
+       {
+         *is_dos_app = TRUE;
+       }
+#else
+      IMAGE_DOS_HEADER * dos_header;
+      IMAGE_NT_HEADERS * nt_header;
+
+      dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
+      if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
+       goto unwind;
+         
+      nt_header = (PIMAGE_NT_HEADERS) ((char*) dos_header + dos_header->e_lfanew);
+         
+      if ((char*) nt_header > (char*) dos_header + executable.size) 
+       {
+         /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
+         *is_dos_app = TRUE;
+       } 
+      else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
+              LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
+       {
+         *is_dos_app = TRUE;
+       }
+      else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
+       {
+         /* Look for cygwin.dll in DLL import list. */
+         IMAGE_DATA_DIRECTORY import_dir =
+           nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+         IMAGE_IMPORT_DESCRIPTOR * imports;
+         IMAGE_SECTION_HEADER * section;
+
+         section = rva_to_section (import_dir.VirtualAddress, nt_header);
+         imports = (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress,
+                                                           section, executable);
+             
+         for ( ; imports->Name; imports++)
+           {
+             char *dllname = (char*) RVA_TO_PTR (imports->Name, section, executable);
+
+             /* The exact name of the cygwin dll has changed with
+                various releases, but hopefully this will be reasonably
+                future proof.  */
+             if (strncmp (dllname, "cygwin", 6) == 0)
+               {
+                 *is_cygnus_app = TRUE;
+                 break;
+               }
+           }
+       }
+#endif
+    }
+
+ unwind:
+  close_file_data (&executable);
+}
+
 /* Close the system structures associated with the given file.  */
 void
 close_file_data (file_data *p_file)
index a20a68d..edc1333 100644 (file)
--- a/src/nt.h
+++ b/src/nt.h
@@ -40,41 +40,6 @@ Boston, MA 02111-1307, USA.  */
 #define X_OK 1
 #define F_OK 0
 
-/* File descriptor set emulation.  */
-
-#if 0 /* These are defined in winsock.h.
-        FD_SETSIZE is defined 64. Let's not full the runtime. */
-
-/* The MSVC multithreaded statically-linked runtime library has limit
-   of 256 descriptors by default (the single-threaded static library
-   has a limit of 64 descriptors, and the DLL versions both have a
-   limit of 512).  Beware.  Should this be set to 512?  */
-#define FD_SETSIZE  256
-typedef struct {
-  unsigned int bits[FD_SETSIZE / 32];
-} fd_set;
-
-/* standard access macros */
-#define FD_SET(n, p) \
-  do { \
-    if ((n) < FD_SETSIZE) { \
-      (p)->bits[(n)/32] |= (1 << (n)%32); \
-    } \
-  } while (0)
-#define FD_CLR(n, p) \
-  do { \
-    if ((n) < FD_SETSIZE) { \
-      (p)->bits[(n)/32] &= ~(1 << (n)%32); \
-    } \
-  } while (0)
-#define FD_ISSET(n, p) ((n) < FD_SETSIZE ? ((p)->bits[(n)/32] & (1 << (n)%32)) : 0)
-#define FD_ZERO(p) memset((p), 0, sizeof(fd_set))
-
-#define SELECT_TYPE fd_set
-#define MAXDESC FD_SETSIZE
-
-#endif /* 0 */
-
 /* ------------------------------------------------------------------------- */
 
 /* child_process.status values */
@@ -113,7 +78,7 @@ typedef struct
   child_process *  cp;
 } filedesc;
 
-extern filedesc fd_info [ MAXDESC ];
+extern filedesc fd_info [];
 
 /* fd_info flag definitions */
 #define FILE_READ    0x0001
@@ -147,7 +112,37 @@ extern LPBYTE nt_get_resource (char * key, LPDWORD type);
 void set_process_dir (const char * dir);
 time_t convert_time (FILETIME ft);
 
-extern void init_ntproc ();
+extern void init_ntproc (void);
 extern void term_ntproc (int unused);
 
+/* ----------------------------------------------------------------- */
+/* Useful routines for manipulating memory-mapped files. */
+
+typedef struct file_data
+{
+  const char    *name;
+  unsigned long  size;
+  HANDLE         file;
+  HANDLE         file_mapping;
+  char *file_base;
+} file_data;
+
+#define OFFSET_TO_RVA(var,section) \
+         (section->VirtualAddress + ((DWORD)(var) - section->PointerToRawData))
+
+#define RVA_TO_OFFSET(var,section) \
+         (section->PointerToRawData + ((DWORD)(var) - section->VirtualAddress))
+
+#define RVA_TO_PTR(var,section,filedata) \
+         ((void *)(RVA_TO_OFFSET(var,section) + (filedata).file_base))
+
+int open_input_file (file_data *p_file, const char *name);
+int open_output_file (file_data *p_file, const char *name, unsigned long size);
+void close_file_data (file_data *p_file);
+void mswindows_executable_type (const char * filename, int * is_dos_app,
+                               int * is_cygnus_app);
+
+/* In process-nt.c */
+extern int compare_env (const void *strp1, const void *strp2);
+
 #endif /* INCLUDED_nt_h_ */
index 9372dd1..6695203 100644 (file)
@@ -227,17 +227,44 @@ sbrk (unsigned long increment)
 void
 recreate_heap (char *executable_path)
 {
-  void *tmp;
-
   /* First reserve the upper part of our heap.  (We reserve first
-     because there have been problems in the past where doing the
-     mapping first has loaded DLLs into the VA space of our heap.)  */
-  tmp = VirtualAlloc ((void *) get_heap_end (),
-                     get_reserved_heap_size () - get_committed_heap_size (),
-                     MEM_RESERVE,
-                     PAGE_NOACCESS);
+        because there have been problems in the past where doing the
+        mapping first has loaded DLLs into the VA space of our heap.)  */
+
+  /* Query the region at the end of the committed heap */
+  void *tmp;
+  MEMORY_BASIC_INFORMATION info;
+  DWORD size;
+  unsigned char* base = get_heap_end ();
+  unsigned char* end  = base + get_reserved_heap_size () - get_committed_heap_size ();
+  VirtualQuery (base, &info, sizeof info);
+  if (info.State != MEM_FREE)
+       {
+         /* Oops, something has already reserved or commited it, nothing we can do but exit */
+         char buf[256];
+         wsprintf(buf,
+                          "XEmacs cannot start because the memory region required by the heap is not available.\n"
+                          "(BaseAddress = 0x%lx, AllocationBase = 0x%lx, Size = 0x%lx, State = %s, Type = %s)",
+                          info.BaseAddress, info.AllocationBase, info.RegionSize,
+                          info.State == MEM_COMMIT ? "COMMITED" : "RESERVED",
+                          info.Type == MEM_IMAGE ? "IMAGE" : info.Type == MEM_MAPPED ? "MAPPED" : "PRIVATE");
+         MessageBox(NULL, buf, "XEmacs", MB_OK | MB_ICONSTOP);
+         exit(1);
+       }
+
+  /* Now try and reserve as much as possible */
+  size = min (info.RegionSize, end - base);
+  tmp = VirtualAlloc (base, size, MEM_RESERVE, PAGE_NOACCESS);
   if (!tmp)
-    exit (1);
+       {
+         /* Can't reserve it, nothing we can do but exit */
+         char buf[256];
+         wsprintf(buf,
+                          "XEmacs cannot start because it couldn't reserve space required for the heap.\n"
+                          "(VirtualAlloc at 0x%lx of 0x%lx failed (%d))", base, size, GetLastError());
+         MessageBox(NULL, buf, "XEmacs", MB_OK | MB_ICONSTOP);
+         exit (1);
+       }
 
   /* We read in the data for the .bss section from the executable
      first and map in the heap from the executable second to prevent
index 091cf0c..8760f42 100644 (file)
@@ -76,28 +76,4 @@ extern void cache_system_info (void);
 extern unsigned char *round_to_next (unsigned char *address, 
                                     unsigned long align);
 
-/* ----------------------------------------------------------------- */
-/* Useful routines for manipulating memory-mapped files. */
-
-typedef struct file_data {
-  const char    *name;
-  unsigned long  size;
-  HANDLE         file;
-  HANDLE         file_mapping;
-  char *file_base;
-} file_data;
-
-#define OFFSET_TO_RVA(var,section) \
-         (section->VirtualAddress + ((DWORD)(var) - section->PointerToRawData))
-
-#define RVA_TO_OFFSET(var,section) \
-         (section->PointerToRawData + ((DWORD)(var) - section->VirtualAddress))
-
-#define RVA_TO_PTR(var,section,filedata) \
-         ((void *)(RVA_TO_OFFSET(var,section) + (filedata).file_base))
-
-int open_input_file (file_data *p_file, const char *name);
-int open_output_file (file_data *p_file, const char *name, unsigned long size);
-void close_file_data (file_data *p_file);
-
 #endif /* INCLUDED_ntheap_h_ */
index bbfa228..c19870d 100644 (file)
@@ -18,19 +18,13 @@ along with XEmacs; see the file COPYING.  If not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.*/
 
-#include <windows.h>
 #include <config.h>
 #include <stdio.h>
 #include "sysfile.h"
+#include "syswindows.h"
 #include "lisp.h"
 #include "nativesound.h"
 
-#if (defined (__CYGWIN32__) || defined(__MINGW32__)) && \
-       CYGWIN_VERSION_DLL_MAJOR < 21
-extern BOOL WINAPI PlaySound(LPCSTR,HMODULE,DWORD);
-#else
-#include <mmsystem.h>
-#endif
 static int play_sound_data_1 (unsigned char *data, int length,
                               int volume, int convert);
 
index a6159f4..eebf13f 100644 (file)
@@ -458,156 +458,6 @@ create_child (const char *exe, char *cmdline, char *env,
   return FALSE;
 }
 
-#ifndef __MINGW32__
-/* Return pointer to section header for section containing the given
-   relative virtual address. */
-static IMAGE_SECTION_HEADER *
-rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
-{
-  PIMAGE_SECTION_HEADER section;
-  int i;
-
-  section = IMAGE_FIRST_SECTION (nt_header);
-
-  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
-    {
-      if (rva >= section->VirtualAddress
-         && rva < section->VirtualAddress + section->SizeOfRawData)
-       return section;
-      section++;
-    }
-  return NULL;
-}
-#endif
-
-void
-win32_executable_type (const char * filename, int * is_dos_app, int * is_cygnus_app)
-{
-  file_data executable;
-  char * p;
-
-  /* Default values in case we can't tell for sure.  */
-  *is_dos_app = FALSE;
-  *is_cygnus_app = FALSE;
-
-  if (!open_input_file (&executable, filename))
-    return;
-
-  p = strrchr (filename, '.');
-
-      /* We can only identify DOS .com programs from the extension. */
-      if (p && stricmp (p, ".com") == 0)
-    *is_dos_app = TRUE;
-  else if (p && (stricmp (p, ".bat") == 0 ||
-                stricmp (p, ".cmd") == 0))
-    {
-      /* A DOS shell script - it appears that CreateProcess is happy to
-        accept this (somewhat surprisingly); presumably it looks at
-        COMSPEC to determine what executable to actually invoke.
-            Therefore, we have to do the same here as well. */
-      /* Actually, I think it uses the program association for that
-        extension, which is defined in the registry.  */
-      p = egetenv ("COMSPEC");
-      if (p)
-       win32_executable_type (p, is_dos_app, is_cygnus_app);
-    }
-      else
-       {
-      /* Look for DOS .exe signature - if found, we must also check that
-        it isn't really a 16- or 32-bit Windows exe, since both formats
-        start with a DOS program stub.  Note that 16-bit Windows
-        executables use the OS/2 1.x format. */
-
-#ifdef __MINGW32__
-         /* mingw32 doesn't have enough headers to detect cygwin
-             apps, just do what we can. */
-         FILHDR * exe_header;
-
-         exe_header = (FILHDR*) executable.file_base;
-         if (exe_header->e_magic != DOSMAGIC)
-           goto unwind;
-
-         if ((char*) exe_header->e_lfanew > (char*) executable.size)
-           {
-             /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
-             *is_dos_app = TRUE;
-           } 
-         else if (exe_header->nt_signature != NT_SIGNATURE)
-           {
-             *is_dos_app = TRUE;
-           }
-#else
-         IMAGE_DOS_HEADER * dos_header;
-         IMAGE_NT_HEADERS * nt_header;
-
-         dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
-         if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
-           goto unwind;
-         
-         nt_header = (PIMAGE_NT_HEADERS) ((char*) dos_header + dos_header->e_lfanew);
-         
-         if ((char*) nt_header > (char*) dos_header + executable.size) 
-           {
-             /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
-             *is_dos_app = TRUE;
-           } 
-         else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
-                  LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
-           {
-             *is_dos_app = TRUE;
-           }
-         else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
-           {
-             /* Look for cygwin.dll in DLL import list. */
-             IMAGE_DATA_DIRECTORY import_dir =
-               nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
-             IMAGE_IMPORT_DESCRIPTOR * imports;
-             IMAGE_SECTION_HEADER * section;
-
-             section = rva_to_section (import_dir.VirtualAddress, nt_header);
-             imports = (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress,
-                                                               section, executable);
-             
-             for ( ; imports->Name; imports++)
-               {
-                 char *dllname = (char*) RVA_TO_PTR (imports->Name, section, executable);
-
-                 if (strcmp (dllname, "cygwin.dll") == 0)
-                   {
-                     *is_cygnus_app = TRUE;
-                     break;
-                   }
-               }
-           }
-#endif
-       }
-
- unwind:
-      close_file_data (&executable);
-}
-
-int
-compare_env (const void *strp1, const void *strp2)
-{
-  const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
-
-  while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
-    {
-      if ((*str1) > (*str2))
-       return 1;
-      else if ((*str1) < (*str2))
-       return -1;
-      str1++, str2++;
-    }
-
-  if (*str1 == '=' && *str2 == '=')
-    return 0;
-  else if (*str1 == '=')
-    return -1;
-  else
-    return 1;
-}
-
 void
 merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
 {
@@ -691,7 +541,7 @@ sys_spawnve (int mode, const char *cmdname,
      was compiled with the Cygnus GNU toolchain and hence relies on
      cygwin.dll to parse the command line - we use this to decide how to
      escape quote chars in command line args that must be quoted). */
-  win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
+  mswindows_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
 
   /* On Windows 95, if cmdname is a DOS app, we invoke a helper
      application to start it by specifying the helper app as cmdname,
index e91dbed..2c27ff2 100644 (file)
@@ -507,7 +507,7 @@ color_instantiate (Lisp_Object specifier, Lisp_Object matchspec,
 {
   /* When called, we're inside of call_with_suspended_errors(),
      so we can freely error. */
-  Lisp_Object device = DFW_DEVICE (domain);
+  Lisp_Object device = DOMAIN_DEVICE (domain);
   struct device *d = XDEVICE (device);
 
   if (COLOR_INSTANCEP (instantiator))
@@ -631,19 +631,7 @@ set_color_attached_to (Lisp_Object obj, Lisp_Object face, Lisp_Object property)
 DEFUN ("color-specifier-p", Fcolor_specifier_p, 1, 1, 0, /*
 Return t if OBJECT is a color specifier.
 
-Valid instantiators for color specifiers are:
-
--- a string naming a color (e.g. under X this might be "lightseagreen2"
-   or "#F534B2")
--- a color instance (use that instance directly if the device matches,
-   or use the string that generated it)
--- a vector of no elements (only on TTY's; this means to set no color
-   at all, thus using the "natural" color of the terminal's text)
--- a vector of one or two elements: a face to inherit from, and
-   optionally a symbol naming which property of that face to inherit,
-   either `foreground' or `background' (if omitted, defaults to the same
-   property that this color specifier is used for; if this specifier is
-   not part of a face, the instantiator would not be valid)
+See `make-color-specifier' for a description of possible color instantiators.
 */
        (object))
 {
@@ -706,7 +694,7 @@ font_instantiate (Lisp_Object specifier, Lisp_Object matchspec,
 {
   /* When called, we're inside of call_with_suspended_errors(),
      so we can freely error. */
-  Lisp_Object device = DFW_DEVICE (domain);
+  Lisp_Object device = DOMAIN_DEVICE (domain);
   struct device *d = XDEVICE (device);
   Lisp_Object instance;
 
@@ -841,16 +829,7 @@ set_font_attached_to (Lisp_Object obj, Lisp_Object face, Lisp_Object property)
 DEFUN ("font-specifier-p", Ffont_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a font specifier.
 
-Valid instantiators for font specifiers are:
-
--- a string naming a font (e.g. under X this might be
-   "-*-courier-medium-r-*-*-*-140-*-*-*-*-iso8859-*" for a 14-point
-   upright medium-weight Courier font)
--- a font instance (use that instance directly if the device matches,
-   or use the string that generated it)
--- a vector of no elements (only on TTY's; this means to set no font
-   at all, thus using the "natural" font of the terminal's text)
--- a vector of one element (a face to inherit from)
+See `make-font-specifier' for a description of possible font instantiators.
 */
        (object))
 {
@@ -986,15 +965,8 @@ set_face_boolean_attached_to (Lisp_Object obj, Lisp_Object face,
 DEFUN ("face-boolean-specifier-p", Fface_boolean_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a face-boolean specifier.
 
-Valid instantiators for face-boolean specifiers are
-
--- t or nil
--- a vector of two or three elements: a face to inherit from,
-   optionally a symbol naming the property of that face to inherit from
-   (if omitted, defaults to the same property that this face-boolean
-   specifier is used for; if this specifier is not part of a face,
-   the instantiator would not be valid), and optionally a value which,
-   if non-nil, means to invert the sense of the inherited property.
+See `make-face-boolean-specifier' for a description of possible
+face-boolean instantiators.
 */
        (object))
 {
index 1a6b627..c1ca13d 100644 (file)
                        is where architecture-independent files are
                        searched for.
 
-   PATH_LOCK           The name of the directory that contains lock files
-                       with which we record what files are being modified in 
-                       Emacs.  This directory should be writable by everyone.
-                       If this is specified, the string must end with a slash!
-
    PATH_INFO           This is where the info documentation is installed.
 
    PATH_INFOPATH       The default value of `Info-directory-list'.
 #define PATH_DATA "@ETCDIR@"
 #endif
 
-#ifdef LOCKDIR_USER_DEFINED
-#define PATH_LOCK "@LOCKDIR@"
-#endif
-
 #ifdef DOCDIR_USER_DEFINED
 #define PATH_DOC "@DOCDIR@"
 #endif
index dfe2e1c..4d1664f 100644 (file)
@@ -106,6 +106,10 @@ FILE *termscript;  /* Stdio stream being used for copy of all output.  */
 
 int stdout_needs_newline;
 
+#ifdef WINDOWSNT
+static int no_useful_stderr;
+#endif
+
 static void
 std_handle_out_external (FILE *stream, Lisp_Object lstream,
                         const Extbyte *extptr, Extcount extlen,
@@ -117,9 +121,12 @@ std_handle_out_external (FILE *stream, Lisp_Object lstream,
   if (stream)
     {
 #ifdef WINDOWSNT
+      if (!no_useful_stderr)
+       no_useful_stderr = GetStdHandle (STD_ERROR_HANDLE) == 0 ? 1 : -1;
+
       /* we typically have no useful stdout/stderr under windows if we're
         being invoked graphically. */
-      if (!noninteractive)
+      if (!noninteractive || no_useful_stderr > 0)
        msw_output_console_string (extptr, extlen);
       else
 #endif
@@ -174,9 +181,16 @@ std_handle_out_va (FILE *stream, const char *fmt, va_list args)
   int retval;
 
   retval = vsprintf ((char *) kludge, fmt, args);
-  TO_EXTERNAL_FORMAT (DATA, (kludge, strlen ((char *) kludge)),
-                     ALLOCA, (extptr, extlen),
-                     Qnative);
+  if (initialized && !fatal_error_in_progress)
+    TO_EXTERNAL_FORMAT (DATA, (kludge, strlen ((char *) kludge)),
+                       ALLOCA, (extptr, extlen),
+                       Qnative);
+  else
+    {
+      extptr = (Extbyte *) kludge;
+      extlen = (Extcount) strlen ((char *) kludge);
+    }
+  
   std_handle_out_external (stream, Qnil, extptr, extlen, 1, 1);
   return retval;
 }
@@ -190,7 +204,10 @@ stderr_out (const char *fmt, ...)
   int retval;
   va_list args;
   va_start (args, fmt);
-  retval = std_handle_out_va (stderr, GETTEXT (fmt), args);
+  retval =
+    std_handle_out_va
+    (stderr, initialized && !fatal_error_in_progress ? GETTEXT (fmt) : fmt,
+     args);
   va_end (args);
   return retval;
 }
@@ -204,7 +221,10 @@ stdout_out (const char *fmt, ...)
   int retval;
   va_list args;
   va_start (args, fmt);
-  retval = std_handle_out_va (stdout, GETTEXT (fmt), args);
+  retval =
+    std_handle_out_va
+    (stdout, initialized && !fatal_error_in_progress ? GETTEXT (fmt) : fmt,
+     args);
   va_end (args);
   return retval;
 }
index 9839bdf..5518ccb 100644 (file)
@@ -26,9 +26,11 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include "lisp.h"
 
+#include "buffer.h"
 #include "console-msw.h"
 #include "hash.h"
 #include "lstream.h"
+#include "nt.h"
 #include "process.h"
 #include "procimpl.h"
 #include "sysdep.h"
@@ -45,9 +47,6 @@ Boston, MA 02111-1307, USA.  */
 /* Arbitrary size limit for code fragments passed to run_in_other_process */
 #define FRAGMENT_CODE_SIZE 32
 
-/* Bound by winnt.el */
-Lisp_Object Qnt_quote_process_args;
-
 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */
 struct nt_process_data
 {
@@ -57,6 +56,10 @@ struct nt_process_data
   int need_enable_child_signals;
 };
 
+/* Control how args are quoted to ensure correct parsing by child
+   process. */
+Lisp_Object Vmswindows_quote_process_args;
+
 /* Control whether create_child causes the process to inherit Emacs'
    console window, or be given a new one of its own.  The default is
    nil, to allow multiple DOS programs to run on Win95.  Having separate
@@ -676,22 +679,49 @@ signal_cannot_launch (Lisp_Object image_file, DWORD err)
 }
 
 static void
-ensure_console_window_exists ()
+ensure_console_window_exists (void)
 {
   if (msw_windows9x_p ())
     msw_hide_console ();
 }
 
+int
+compare_env (const void *strp1, const void *strp2)
+{
+  const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
+
+  while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
+    {
+      if ((*str1) > (*str2))
+       return 1;
+      else if ((*str1) < (*str2))
+       return -1;
+      str1++, str2++;
+    }
+
+  if (*str1 == '=' && *str2 == '=')
+    return 0;
+  else if (*str1 == '=')
+    return -1;
+  else
+    return 1;
+}
+
 static int
 nt_create_process (Lisp_Process *p,
                   Lisp_Object *argv, int nargv,
                   Lisp_Object program, Lisp_Object cur_dir)
 {
+  /* Synched up with sys_spawnve in FSF 20.6.  Significantly different
+     but still synchable. */
   HANDLE hmyshove, hmyslurp, hprocin, hprocout, hprocerr;
-  LPTSTR command_line;
+  Extbyte *command_line;
   BOOL do_io, windowed;
   char *proc_env;
 
+  /* No need to DOS-ize the filename; expand-file-name (called prior)
+     already does this. */
+
   /* Find out whether the application is windowed or not */
   {
     /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most
@@ -739,54 +769,258 @@ nt_create_process (Lisp_Process *p,
       CreatePipe (&hmyslurp, &hprocout, &sa, 0);
 
       /* Duplicate the stdout handle for use as stderr */
-      DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(), &hprocerr,
-       0, TRUE, DUPLICATE_SAME_ACCESS);
+      DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(),
+                     &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS);
 
       /* Stupid Win32 allows to create a pipe with *both* ends either
         inheritable or not. We need process ends inheritable, and local
         ends not inheritable. */
-      DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp,
-                      0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
+      DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(),
+                      &htmp, 0, FALSE,
+                      DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
       hmyshove = htmp;
-      DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(), &htmp,
-                      0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
+      DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(),
+                      &htmp, 0, FALSE,
+                      DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
       hmyslurp = htmp;
     }
 
-  /* Convert an argv vector into Win32 style command line by a call to
-     lisp function `nt-quote-process-args' which see (in winnt.el)*/
+  /* Convert an argv vector into Win32 style command line. */
   {
     int i;
-    Lisp_Object args_or_ret = Qnil;
-    struct gcpro gcpro1;
+    Bufbyte **quoted_args;
+    int is_dos_app, is_cygnus_app;
+    int do_quoting = 0;
+    char escape_char = 0;
+
+    nargv++; /* include program; we access argv offset by 1 below */
+    quoted_args = alloca_array (Bufbyte *, nargv);
+
+    /* Determine whether program is a 16-bit DOS executable, or a Win32
+       executable that is implicitly linked to the Cygnus dll (implying it
+       was compiled with the Cygnus GNU toolchain and hence relies on
+       cygwin.dll to parse the command line - we use this to decide how to
+       escape quote chars in command line args that must be quoted). */
+    mswindows_executable_type (XSTRING_DATA (program),
+                              &is_dos_app, &is_cygnus_app);
 
-    GCPRO1 (args_or_ret);
+#if 0
+    /* #### we need to port this. */
+    /* On Windows 95, if cmdname is a DOS app, we invoke a helper
+       application to start it by specifying the helper app as cmdname,
+       while leaving the real app name as argv[0].  */
+    if (is_dos_app)
+      {
+       cmdname = (char*) alloca (MAXPATHLEN);
+       if (egetenv ("CMDPROXY"))
+         strcpy ((char*)cmdname, egetenv ("CMDPROXY"));
+       else
+         {
+           strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory));
+           strcat ((char*)cmdname, "cmdproxy.exe");
+         }
+      }
+#endif
+  
+    /* we have to do some conjuring here to put argv and envp into the
+       form CreateProcess wants...  argv needs to be a space separated/null
+       terminated list of parameters, and envp is a null
+       separated/double-null terminated list of parameters.
+
+       Additionally, zero-length args and args containing whitespace or
+       quote chars need to be wrapped in double quotes - for this to work,
+       embedded quotes need to be escaped as well.  The aim is to ensure
+       the child process reconstructs the argv array we start with
+       exactly, so we treat quotes at the beginning and end of arguments
+       as embedded quotes.
+
+       The Win32 GNU-based library from Cygnus doubles quotes to escape
+       them, while MSVC uses backslash for escaping.  (Actually the MSVC
+       startup code does attempt to recognize doubled quotes and accept
+       them, but gets it wrong and ends up requiring three quotes to get a
+       single embedded quote!)  So by default we decide whether to use
+       quote or backslash as the escape character based on whether the
+       binary is apparently a Cygnus compiled app.
+
+       Note that using backslash to escape embedded quotes requires
+       additional special handling if an embedded quote is already
+       preceded by backslash, or if an arg requiring quoting ends with
+       backslash.  In such cases, the run of escape characters needs to be
+       doubled.  For consistency, we apply this special handling as long
+       as the escape character is not quote.
+   
+       Since we have no idea how large argv and envp are likely to be we
+       figure out list lengths on the fly and allocate them.  */
+  
+    if (!NILP (Vmswindows_quote_process_args))
+      {
+       do_quoting = 1;
+       /* Override escape char by binding mswindows-quote-process-args to
+          desired character, or use t for auto-selection.  */
+       if (INTP (Vmswindows_quote_process_args))
+         escape_char = (char) XINT (Vmswindows_quote_process_args);
+       else
+         escape_char = is_cygnus_app ? '"' : '\\';
+      }
+  
+    /* do argv...  */
+    for (i = 0; i < nargv; ++i)
+      {
+       Bufbyte *targ = XSTRING_DATA (i == 0 ? program : argv[i - 1]);
+       Bufbyte *p = targ;
+       int need_quotes = 0;
+       int escape_char_run = 0;
+       int arglen = 0;
+
+       if (*p == 0)
+         need_quotes = 1;
+       for ( ; *p; p++)
+         {
+           if (*p == '"')
+             {
+               /* allow for embedded quotes to be escaped */
+               arglen++;
+               need_quotes = 1;
+               /* handle the case where the embedded quote is already escaped */
+               if (escape_char_run > 0)
+                 {
+                   /* To preserve the arg exactly, we need to double the
+                      preceding escape characters (plus adding one to
+                      escape the quote character itself).  */
+                   arglen += escape_char_run;
+                 }
+             }
+           else if (*p == ' ' || *p == '\t')
+             {
+               need_quotes = 1;
+             }
+
+           if (*p == escape_char && escape_char != '"')
+             escape_char_run++;
+           else
+             escape_char_run = 0;
+         }
+       if (need_quotes)
+         {
+           arglen += 2;
+           /* handle the case where the arg ends with an escape char - we
+              must not let the enclosing quote be escaped.  */
+           if (escape_char_run > 0)
+             arglen += escape_char_run;
+         }
+       arglen += strlen (targ) + 1;
+
+       quoted_args[i] = alloca_array (Bufbyte, arglen); 
+      }
 
     for (i = 0; i < nargv; ++i)
-      args_or_ret = Fcons (*argv++, args_or_ret);
-    args_or_ret = Fnreverse (args_or_ret);
-    args_or_ret = Fcons (program, args_or_ret);
+      {
+       Bufbyte *targ = XSTRING_DATA (i == 0 ? program : argv[i - 1]);
+       Bufbyte *p = targ;
+       int need_quotes = 0;
+       Bufbyte *parg = quoted_args[i];
+
+       if (*p == 0)
+         need_quotes = 1;
 
-    args_or_ret = call1 (Qnt_quote_process_args, args_or_ret);
+       if (do_quoting)
+         {
+           for ( ; *p; p++)
+             if (*p == ' ' || *p == '\t' || *p == '"')
+               need_quotes = 1;
+         }
+       if (need_quotes)
+         {
+           int escape_char_run = 0;
+           Bufbyte * first;
+           Bufbyte * last;
+
+           p = targ;
+           first = p;
+           last = p + strlen (p) - 1;
+           *parg++ = '"';
+#if 0
+           /* This version does not escape quotes if they occur at the
+              beginning or end of the arg - this could lead to incorrect
+              behavior when the arg itself represents a command line
+              containing quoted args.  I believe this was originally done
+              as a hack to make some things work, before
+              `mswindows-quote-process-args' was added.  */
+           while (*p)
+             {
+               if (*p == '"' && p > first && p < last)
+                 *parg++ = escape_char;        /* escape embedded quotes */
+               *parg++ = *p++;
+             }
+#else
+           for ( ; *p; p++)
+             {
+               if (*p == '"')
+                 {
+                   /* double preceding escape chars if any */
+                   while (escape_char_run > 0)
+                     {
+                       *parg++ = escape_char;
+                       escape_char_run--;
+                     }
+                   /* escape all quote chars, even at beginning or end */
+                   *parg++ = escape_char;
+                 }
+               *parg++ = *p;
+
+               if (*p == escape_char && escape_char != '"')
+                 escape_char_run++;
+               else
+                 escape_char_run = 0;
+             }
+           /* double escape chars before enclosing quote */
+           while (escape_char_run > 0)
+             {
+               *parg++ = escape_char;
+               escape_char_run--;
+             }
+#endif
+           *parg++ = '"';
+         }
+       else
+         {
+           strcpy (parg, targ);
+           parg += strlen (targ);
+         }
+       *parg = '\0';
+      }
 
-    if (!STRINGP (args_or_ret))
-      /* Luser wrote his/her own clever version */
-      error ("Bogus return value from `nt-quote-process-args'");
+    {
+      int total_cmdline_len = 0;
+      Extcount *extargcount = (Extcount *) alloca_array (Extcount, nargv);
+      Extbyte **extarg = (Extbyte **) alloca_array (Extbyte *, nargv);
+      Extbyte *command_ptr;
 
-    command_line = alloca_array (char, (XSTRING_LENGTH (program)
-                                       + XSTRING_LENGTH (args_or_ret) + 2));
-    strcpy (command_line, XSTRING_DATA (program));
-    strcat (command_line, " ");
-    strcat (command_line, XSTRING_DATA (args_or_ret));
+      for (i = 0; i < nargv; ++i)
+       {
+         TO_EXTERNAL_FORMAT (C_STRING, quoted_args[i], ALLOCA,
+                             (extarg[i], extargcount[i]), Qmswindows_tstr);
+         /* account for space and terminating null */
+         total_cmdline_len += extargcount[i] + EITCHAR_SIZE;
+       }
 
-    UNGCPRO; /* args_or_ret */
+      command_line = alloca_array (char, total_cmdline_len);
+      command_ptr = command_line;
+      for (i = 0; i < nargv; ++i)
+       {
+         memcpy (command_ptr, extarg[i], extargcount[i]);
+         command_ptr += extargcount[i];
+         EICOPY_TCHAR (command_ptr, ' ');
+         command_ptr += EITCHAR_SIZE;
+       }
+      EICOPY_TCHAR (command_ptr, '\0');
+      command_ptr += EITCHAR_SIZE;
+    }
   }
-
   /* Set `proc_env' to a nul-separated array of the strings in
      Vprocess_environment terminated by 2 nuls.  */
  
   {
-    extern int compare_env (const char **strp1, const char **strp2);
     char **env;
     REGISTER Lisp_Object tem;
     REGISTER char **new_env;
@@ -798,6 +1032,17 @@ nt_create_process (Lisp_Process *p,
          && STRINGP (XCAR (tem)));
         tem = XCDR (tem))
       new_length++;
+
+    /* FSF adds an extra env var to hold the current process ID of the
+       Emacs process.  Apparently this is used only by emacsserver.c,
+       which we have superseded to gnuserv.c. (#### Does it work under
+       MS Windows?)
+
+       sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", 
+         GetCurrentProcessId ());
+       arglen += strlen (ppid_env_var_buffer) + 1;
+       numenv++;
+    */
     
     /* new_length + 1 to include terminating 0.  */
     env = new_env = alloca_array (char *, new_length + 1);
@@ -1082,7 +1327,7 @@ nt_kill_child_process (Lisp_Object proc, int signo,
 }
 
 /*
- * Kill any process in the system given its PID.
+ * Kill any process in the system given its PID
  *
  * Returns zero if a signal successfully sent, or
  * negative number upon failure
@@ -1339,12 +1584,25 @@ process_type_create_nt (void)
 void
 syms_of_process_nt (void)
 {
-  defsymbol (&Qnt_quote_process_args, "nt-quote-process-args");
 }
 
 void
 vars_of_process_nt (void)
 {
+  DEFVAR_LISP ("mswindows-quote-process-args",
+              &Vmswindows_quote_process_args /*
+Non-nil enables quoting of process arguments to ensure correct parsing.
+Because Windows does not directly pass argv arrays to child processes,
+programs have to reconstruct the argv array by parsing the command
+line string.  For an argument to contain a space, it must be enclosed
+in double quotes or it will be parsed as multiple arguments.
+
+If the value is a character, that character will be used to escape any
+quote characters that appear, otherwise a suitable escape character
+will be chosen based on the type of the program (normal or Cygwin).
+*/ );                                                            
+  Vmswindows_quote_process_args = Qt;
+
   DEFVAR_LISP ("mswindows-start-process-share-console",
               &Vmswindows_start_process_share_console /*
 When nil, new child processes are given a new console.
index f5e5dae..774f53a 100644 (file)
@@ -1073,24 +1073,25 @@ See `set-process-filter' for more info on filter functions.
   return XPROCESS (proc)->filter;
 }
 
-DEFUN ("process-send-region", Fprocess_send_region, 3, 3, 0, /*
-Send current contents of region as input to PROCESS.
+DEFUN ("process-send-region", Fprocess_send_region, 3, 4, 0, /*
+Send current contents of the region between START and END as input to PROCESS.
 PROCESS may be a process name or an actual process.
-Called from program, takes three arguments, PROCESS, START and END.
+BUFFER specifies the buffer to look in; if nil, the current buffer is used.
 If the region is more than 500 or so characters long,
 it is sent in several bunches.  This may happen even for shorter regions.
 Output from processes can arrive in between bunches.
 */
-       (process, start, end))
+       (process, start, end, buffer))
 {
   /* This function can GC */
   Lisp_Object proc = get_process (process);
   Bufpos st, en;
+  struct buffer *buf = decode_buffer (buffer, 0);
 
-  get_buffer_range_char (current_buffer, start, end, &st, &en, 0);
+  XSETBUFFER (buffer, buf);
+  get_buffer_range_char (buf, start, end, &st, &en, 0);
 
-  send_process (proc, Fcurrent_buffer (), 0,
-                st, en - st);
+  send_process (proc, buffer, 0, st, en - st);
   return Qnil;
 }
 
index fc29885..a8556d2 100644 (file)
@@ -443,10 +443,47 @@ Flush TABLE.
 DEFUN ("map-range-table", Fmap_range_table, 2, 2, 0, /*
 Map FUNCTION over entries in TABLE, calling it with three args,
 the beginning and end of the range and the corresponding value.
+
+Results are guaranteed to be correct (i.e. each entry processed
+exactly once) if FUNCTION modifies or deletes the current entry
+(i.e. passes the current range to `put-range-table' or
+`remove-range-table'), but not otherwise.
 */
        (function, table))
 {
-  error ("not yet implemented");
+  Lisp_Range_Table *rt;
+  int i;
+
+  CHECK_RANGE_TABLE (table);
+  CHECK_FUNCTION (function);
+
+  rt = XRANGE_TABLE (table);
+
+  /* Do not "optimize" by pulling out the length computation below!
+     FUNCTION may have changed the table. */
+  for (i = 0; i < Dynarr_length (rt->entries); i++)
+    {
+      struct range_table_entry *entry = Dynarr_atp (rt->entries, i);
+      EMACS_INT first, last;
+      Lisp_Object args[4];
+      int oldlen;
+      
+    again:
+      first = entry->first;
+      last = entry->last;
+      oldlen = Dynarr_length (rt->entries);
+      args[0] = function;
+      args[1] = make_int (first);
+      args[2] = make_int (last);
+      args[3] = entry->val;
+      Ffuncall (countof (args), args);
+      /* Has FUNCTION removed the entry? */
+      if (oldlen > Dynarr_length (rt->entries)
+         && i < Dynarr_length (rt->entries)
+         && (first != entry->first || last != entry->last))
+       goto again;
+      }
+
   return Qnil;
 }
 
index 937adab..dd7e7da 100644 (file)
@@ -85,63 +85,9 @@ extern int utimes(char *file, struct timeval *tvp);
 extern int srandom( unsigned seed);
 extern long random();
 
-# define SND_ASYNC             1
-# define SND_NODEFAULT         2
-# define SND_MEMORY            4
-# define SND_FILENAME          0x2000L
-# define VK_APPS                       0x5D
-# define SIF_TRACKPOS  0x0010
-# define ICC_BAR_CLASSES 4
-# define FW_BLACK      FW_HEAVY
-# define FW_ULTRABOLD  FW_EXTRABOLD
-# define FW_DEMIBOLD   FW_SEMIBOLD
-# define FW_ULTRALIGHT FW_EXTRALIGHT
-# define APPCMD_FILTERINITS    0x20L
-# define CBF_FAIL_SELFCONNECTIONS 0x1000
-# define CBF_SKIP_ALLNOTIFICATIONS     0x3C0000
-# define CBF_FAIL_ADVISES      0x4000
-# define CBF_FAIL_POKES                0x10000
-# define CBF_FAIL_REQUESTS     0x20000
-# define SZDDESYS_TOPIC                "System"
-# define JOHAB_CHARSET                 130
-# define MAC_CHARSET           77
 # endif
 #endif
 
-#ifndef SPI_GETWHEELSCROLLLINES
-#define SPI_GETWHEELSCROLLLINES 104
-#endif
-#ifndef WHEEL_PAGESCROLL
-#define WHEEL_PAGESCROLL (UINT_MAX)
-#endif
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120
-#endif
-#ifndef WM_MOUSEWHEEL
-#define WM_MOUSEWHEEL 0x20A
-#endif
-#ifndef TCS_BOTTOM
-#define TCS_BOTTOM 0x0002
-#endif
-#ifndef TCS_VERTICAL
-#define TCS_VERTICAL 0x0080
-#endif
-#ifndef PHYSICALWIDTH
-#define PHYSICALWIDTH 110
-#endif
-#ifndef PHYSICALHEIGHT
-#define PHYSICALHEIGHT 111
-#endif
-#ifndef PHYSICALOFFSETX
-#define PHYSICALOFFSETX 112
-#endif
-#ifndef PHYSICALOFFSETY
-#define PHYSICALOFFSETY 113
-#endif
-
-
-#define PBS_SMOOTH              0x01
-
 #ifdef HAVE_MS_WINDOWS
 #define HAVE_NTGUI
 #define HAVE_FACES
@@ -153,7 +99,7 @@ extern long random();
 
 #define C_SWITCH_SYSTEM -Wno-sign-compare -fno-caller-saves
 #define LIBS_SYSTEM -lwinmm
-
+#define WIN32_LEAN_AND_MEAN
 
 #define TEXT_START -1
 #define TEXT_END -1
index 18360c0..ffa3c12 100644 (file)
@@ -735,26 +735,26 @@ behavior.
      with their standard behaviors.  It is not possible to hide the
      differences down in lwlib because knowledge of XEmacs buffer and
      cursor motion routines is necessary. */
-#if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
-    defined (LWLIB_SCROLLBARS_ATHENA3D) || defined(HAVE_MS_WINDOWS)
-  window_scroll (window, Qnil, -1, ERROR_ME_NOT);
-#else /* Athena */
-  {
-    Bufpos bufpos;
-    Lisp_Object value = Fcdr (object);
 
-    CHECK_INT (value);
-    Fmove_to_window_line (Qzero, window);
-    /* can't use Fvertical_motion() because it moves the buffer point
-       rather than the window's point.
-
-       #### It does?  Why does it take a window argument then? */
-    bufpos = vmotion (XWINDOW (window), XINT (Fwindow_point (window)),
-                     XINT (value), 0);
-    Fset_window_point (window, make_int (bufpos));
-    Fcenter_to_window_line (Qzero, window);
-  }
-#endif /* Athena */
+  if (NILP (XCDR (object)))
+    window_scroll (window, Qnil, -1, ERROR_ME_NOT);
+  else
+    {
+      Bufpos bufpos;
+      Lisp_Object value = Fcdr (object);
+
+      CHECK_INT (value);
+      Fmove_to_window_line (Qzero, window);
+      /* can't use Fvertical_motion() because it moves the buffer point
+        rather than the window's point.
+
+        #### It does?  Why does it take a window argument then? */
+      bufpos = vmotion (XWINDOW (window), XINT (Fwindow_point (window)),
+                       XINT (value), 0);
+      Fset_window_point (window, make_int (bufpos));
+      Fcenter_to_window_line (Qzero, window);
+    }
+
   zmacs_region_stays = 1;
   return Qnil;
 }
@@ -776,17 +776,17 @@ behavior.
      with their standard behaviors.  It is not possible to hide the
      differences down in lwlib because knowledge of XEmacs buffer and
      cursor motion routines is necessary. */
-#if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
-    defined (LWLIB_SCROLLBARS_ATHENA3D) || defined (HAVE_MS_WINDOWS)
-  window_scroll (window, Qnil, 1, ERROR_ME_NOT);
-#else /* Athena */
-  {
-    Lisp_Object value = Fcdr (object);
-    CHECK_INT (value);
-    Fmove_to_window_line (value, window);
-    Fcenter_to_window_line (Qzero, window);
-  }
-#endif /* Athena */
+
+  if (NILP (XCDR (object)))
+    window_scroll (window, Qnil, 1, ERROR_ME_NOT);
+  else
+    {
+      Lisp_Object value = Fcdr (object);
+      CHECK_INT (value);
+      Fmove_to_window_line (value, window);
+      Fcenter_to_window_line (Qzero, window);
+    }
+
   zmacs_region_stays = 1;
   return Qnil;
 }
index 4318bf8..5338b03 100644 (file)
@@ -532,31 +532,52 @@ Return a new specifier object of type TYPE.
 
 A specifier is an object that can be used to keep track of a property
 whose value can be per-buffer, per-window, per-frame, or per-device,
-and can further be restricted to a particular console-type or device-class.
-Specifiers are used, for example, for the various built-in properties of a
-face; this allows a face to have different values in different frames,
-buffers, etc.  For more information, see `specifier-instance',
+and can further be restricted to a particular console-type or
+device-class.  Specifiers are used, for example, for the various
+built-in properties of a face; this allows a face to have different
+values in different frames, buffers, etc.
+
+When speaking of the value of a specifier, it is important to
+distinguish between the *setting* of a specifier, called an
+\"instantiator\", and the *actual value*, called an \"instance\".  You
+put various possible instantiators (i.e. settings) into a specifier
+and associate them with particular locales (buffer, window, frame,
+device, global), and then the instance (i.e. actual value) is
+retrieved in a specific domain (window, frame, device) by looking
+through the possible instantiators (i.e. settings).  This process is
+called \"instantiation\".
+To put settings into a specifier, use `set-specifier', or the
+lower-level functions `add-spec-to-specifier' and
+`add-spec-list-to-specifier'.  You can also temporarily bind a setting
+to a specifier using `let-specifier'.  To retrieve settings, use
+`specifier-specs', or its lower-level counterpart
+`specifier-spec-list'.  To determine the actual value, use
+`specifier-instance'.
+
+For more information, see `set-specifier', `specifier-instance',
 `specifier-specs', and `add-spec-to-specifier'; or, for a detailed
-description of specifiers, including how they are instantiated over a
-particular domain (i.e. how their value in that domain is determined),
-see the chapter on specifiers in the XEmacs Lisp Reference Manual.
+description of specifiers, including how exactly the instantiation
+process works, see the chapter on specifiers in the XEmacs Lisp
+Reference Manual.
 
 TYPE specifies the particular type of specifier, and should be one of
-the symbols 'generic, 'integer, 'boolean, 'color, 'font, 'image,
-'face-boolean, 'gutter, 'gutter-size, 'gutter-visible or 'toolbar.
+the symbols 'generic, 'integer, 'natnum, 'boolean, 'color, 'font,
+'image, 'face-boolean, 'display-table, 'gutter, 'gutter-size,
+'gutter-visible or 'toolbar.
 
 For more information on particular types of specifiers, see the
-functions `generic-specifier-p', `integer-specifier-p',
-`boolean-specifier-p', `color-specifier-p', `font-specifier-p',
-`image-specifier-p', `face-boolean-specifier-p', `gutter-specifier-p,
-`gutter-size-specifier-p, `gutter-visible-specifier-p and
-`toolbar-specifier-p'.
+functions `make-generic-specifier', `make-integer-specifier',
+`make-natnum-specifier', `make-boolean-specifier',
+`make-color-specifier', `make-font-specifier', `make-image-specifier',
+`make-face-boolean-specifier', `make-gutter-size-specifier',
+`make-gutter-visible-specifier', `default-toolbar', `default-gutter',
+and `current-display-table'.
 */
        (type))
 {
   /* This function can GC */
-  struct specifier_methods *meths = decode_specifier_type (type,
-                                                          ERROR_ME);
+  struct specifier_methods *meths = decode_specifier_type (type, ERROR_ME);
 
   return make_specifier (meths);
 }
@@ -609,15 +630,19 @@ Valid locales are devices, frames, windows, buffers, and 'global.
 DEFUN ("valid-specifier-domain-p", Fvalid_specifier_domain_p, 1, 1, 0, /*
 Return t if DOMAIN is a valid specifier domain.
 A domain is used to instance a specifier (i.e. determine the specifier's
-value in that domain).  Valid domains are windows, frames, and devices.
-\(nil is not valid.)
+value in that domain).  Valid domains are image instances, windows, frames,
+and devices. \(nil is not valid.) image instances are pseudo-domains since
+instantiation will actually occur in the window the image instance itself is
+instantiated in.
 */
      (domain))
 {
   /* This cannot GC. */
   return ((DEVICEP (domain) && DEVICE_LIVE_P (XDEVICE (domain))) ||
          (FRAMEP  (domain) && FRAME_LIVE_P  (XFRAME  (domain))) ||
-         (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))))
+         (WINDOWP (domain) && WINDOW_LIVE_P (XWINDOW (domain))) ||
+         /* #### get image instances out of domains! */
+         IMAGE_INSTANCEP (domain))
     ? Qt : Qnil;
 }
 
@@ -729,7 +754,7 @@ check_valid_domain (Lisp_Object domain)
     signal_simple_error ("Invalid specifier domain", domain);
 }
 
-static Lisp_Object
+Lisp_Object
 decode_domain (Lisp_Object domain)
 {
   if (NILP (domain))
@@ -2435,7 +2460,7 @@ specifier_instance_from_inst_list (Lisp_Object specifier,
   GCPRO2 (specifier, inst_list);
 
   sp = XSPECIFIER (specifier);
-  device = DFW_DEVICE (domain);
+  device = DOMAIN_DEVICE (domain);
 
   if (no_quit)
   /* The instantiate method is allowed to call eval.  Since it
@@ -2515,16 +2540,20 @@ specifier_instance (Lisp_Object specifier, Lisp_Object matchspec,
 
   /* Attempt to determine buffer, window, frame, and device from the
      domain. */
-  if (WINDOWP (domain))
+  /* #### get image instances out of domains! */
+  if (IMAGE_INSTANCEP (domain))
+    window = DOMAIN_WINDOW (domain);
+  else if (WINDOWP (domain))
     window = domain;
   else if (FRAMEP (domain))
     frame = domain;
   else if (DEVICEP (domain))
     device = domain;
   else
-    /* #### dmoore - dammit, this should just signal an error or something
-       shouldn't it?
-       #### No. Errors are handled in Lisp primitives implementation.
+    /* dmoore writes: [dammit, this should just signal an error or something
+       shouldn't it?]
+
+       No. Errors are handled in Lisp primitives implementation.
        Invalid domain is a design error here - kkm. */
     abort ();
 
@@ -2959,8 +2988,9 @@ DEFINE_SPECIFIER_TYPE (generic);
 
    What really needs to be done is to write a function
    `make-specifier-type' that creates new specifier types.
-   #### I'll look into this for 19.14.
- */
+
+   #### [I'll look into this for 19.14.]  Well, sometime. (Currently
+   May 2000, 21.2 is in development.  19.14 was released in June 1996.) */
 
 "A generic specifier is a generalized kind of specifier with user-defined\n"
 "semantics.  The instantiator can be any kind of Lisp object, and the\n"
@@ -2997,8 +3027,8 @@ DEFINE_SPECIFIER_TYPE (generic);
 DEFUN ("generic-specifier-p", Fgeneric_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a generic specifier.
 
-A generic specifier allows any kind of Lisp object as an instantiator,
-and returns back the Lisp object unchanged when it is instantiated.
+See `make-generic-specifier' for a description of possible generic
+instantiators.
 */
        (object))
 {
@@ -3020,6 +3050,9 @@ integer_validate (Lisp_Object instantiator)
 
 DEFUN ("integer-specifier-p", Finteger_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is an integer specifier.
+
+See `make-integer-specifier' for a description of possible integer
+instantiators.
 */
        (object))
 {
@@ -3040,6 +3073,9 @@ natnum_validate (Lisp_Object instantiator)
 
 DEFUN ("natnum-specifier-p", Fnatnum_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a natnum (non-negative-integer) specifier.
+
+See `make-natnum-specifier' for a description of possible natnum
+instantiators.
 */
        (object))
 {
@@ -3061,6 +3097,9 @@ boolean_validate (Lisp_Object instantiator)
 
 DEFUN ("boolean-specifier-p", Fboolean_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a boolean specifier.
+
+See `make-boolean-specifier' for a description of possible boolean
+instantiators.
 */
        (object))
 {
@@ -3073,11 +3112,11 @@ Return non-nil if OBJECT is a boolean specifier.
 
 DEFINE_SPECIFIER_TYPE (display_table);
 
-#define VALID_SINGLE_DISPTABLE_INSTANTIATOR_P(instantiator)                    \
-  (VECTORP (instantiator)                                                      \
-   || (CHAR_TABLEP (instantiator)                                              \
-       && (XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_CHAR             \
-          || XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_GENERIC))      \
+#define VALID_SINGLE_DISPTABLE_INSTANTIATOR_P(instantiator)               \
+  (VECTORP (instantiator)                                                 \
+   || (CHAR_TABLEP (instantiator)                                         \
+       && (XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_CHAR        \
+          || XCHAR_TABLE_TYPE (instantiator) == CHAR_TABLE_TYPE_GENERIC)) \
    || RANGE_TABLEP (instantiator))
 
 static void
@@ -3109,6 +3148,9 @@ display_table_validate (Lisp_Object instantiator)
 
 DEFUN ("display-table-specifier-p", Fdisplay_table_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a display-table specifier.
+
+See `current-display-table' for a description of possible display-table
+instantiators.
 */
        (object))
 {
index 17461cb..5758637 100644 (file)
@@ -413,6 +413,48 @@ struct specifier_caching
                                  Lisp_Object oldval);
 };
 
+/* #### get image instances out of domains! */
+
+/* #### I think the following should abort() rather than return nil
+   when an invalid domain is given; much more likely we'll catch design
+   errors early. --ben */
+
+/* This turns out to be used heavily so we make it a macro to make it
+   inline.  Also, the majority of the time the object will turn out to
+   be a window so we move it from being checked last to being checked
+   first. */
+#define DOMAIN_DEVICE(obj)                                     \
+   (WINDOWP (obj) ? WINDOW_DEVICE (XWINDOW (obj))              \
+  : (FRAMEP  (obj) ? FRAME_DEVICE (XFRAME (obj))               \
+  : (DEVICEP (obj) ? obj                                       \
+  : (IMAGE_INSTANCEP (obj) ? image_instance_device (obj)       \
+  : Qnil))))
+
+#define DOMAIN_FRAME(obj)                              \
+   (WINDOWP (obj) ? WINDOW_FRAME (XWINDOW (obj))       \
+  : (FRAMEP  (obj) ? obj                               \
+  : (IMAGE_INSTANCEP (obj) ? image_instance_frame (obj)        \
+  : Qnil)))
+
+#define DOMAIN_WINDOW(obj)                                     \
+   (WINDOWP (obj) ? obj                                                \
+  : (IMAGE_INSTANCEP (obj) ? image_instance_window (obj)       \
+  : Qnil))
+
+#define DOMAIN_LIVE_P(obj)                                     \
+   (WINDOWP (obj) ? WINDOW_LIVE_P (XWINDOW (obj))              \
+  : (FRAMEP  (obj) ? FRAME_LIVE_P (XFRAME (obj))               \
+  : (DEVICEP (obj) ? DEVICE_LIVE_P (XDEVICE (obj))             \
+  : (IMAGE_INSTANCEP (obj) ? image_instance_live_p (obj)       \
+  : 0))))
+
+#define DOMAIN_XDEVICE(obj)                    \
+  (XDEVICE (DOMAIN_DEVICE (obj)))
+#define DOMAIN_XFRAME(obj)                     \
+  (XFRAME (DOMAIN_FRAME (obj)))
+#define DOMAIN_XWINDOW(obj)                    \
+  (XWINDOW (DOMAIN_WINDOW (obj)))
+
 EXFUN (Fcopy_specifier, 6);
 EXFUN (Fmake_specifier, 1);
 EXFUN (Fset_specifier_dirty_flag, 1);
@@ -426,6 +468,7 @@ Lisp_Object decode_locale_list (Lisp_Object locale);
 extern enum spec_add_meth
 decode_how_to_add_specification (Lisp_Object how_to_add);
 Lisp_Object decode_specifier_tag_set (Lisp_Object tag_set);
+Lisp_Object decode_domain (Lisp_Object domain);
 
 void add_entry_to_specifier_type_list (Lisp_Object symbol,
                                       struct specifier_methods *meths);
index 7c2179c..07baead 100644 (file)
@@ -46,18 +46,7 @@ Boston, MA 02111-1307, USA.  */
 #define TOOLBAR_ID_BIAS 16
 #define TOOLBAR_HANDLE(f,p) \
 GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + p)
-#ifndef TB_SETIMAGELIST
-#define TB_SETIMAGELIST (WM_USER + 48)
-#define TB_GETIMAGELIST (WM_USER + 49)
-#define TB_SETDISABLEDIMAGELIST (WM_USER + 54)
-#define TB_GETDISABLEDIMAGELIST (WM_USER + 55)
-#endif
-#ifndef TB_SETPADDING
-#define TB_SETPADDING   (WM_USER + 87)
-#endif
-#ifndef TBSTYLE_FLAT
-#define TBSTYLE_FLAT 0x800
-#endif
+
 #define MSWINDOWS_BUTTON_SHADOW_THICKNESS 2
 #define MSWINDOWS_BLANK_SIZE 5
 #define MSWINDOWS_MINIMUM_TOOLBAR_SIZE 8
index 963d373..b93fcd6 100644 (file)
@@ -1160,14 +1160,9 @@ toolbar_after_change (Lisp_Object specifier, Lisp_Object locale)
 
 DEFUN ("toolbar-specifier-p", Ftoolbar_specifier_p, 1, 1, 0, /*
 Return non-nil if OBJECT is a toolbar specifier.
-Toolbar specifiers are used to specify the format of a toolbar.
-The values of the variables `default-toolbar', `top-toolbar',
-`left-toolbar', `right-toolbar', and `bottom-toolbar' are always
-toolbar specifiers.
-
-Valid toolbar instantiators are called "toolbar descriptors"
-and are lists of vectors.  See `default-toolbar' for a description
-of the exact format.
+
+See `make-toolbar-specifier' for a description of possible toolbar
+instantiators.
 */
        (object))
 {
index d91ae33..f1da87a 100644 (file)
@@ -494,16 +494,6 @@ typedef struct {
 # define SHN_ABS       Elf_eshn_absolute
 # define SHN_COMMON    Elf_eshn_common
 
-/*
- * The magic of picking the right size types is handled by the ELFSIZE
- * definition above.
- */
-# ifdef __STDC__
-#  define ElfW(type)    Elf_##type
-# else
-#  define ElfW(type)    Elf_/**/type
-# endif
-
 # ifdef __alpha__
 #  include <sys/exec_ecoff.h>
 #  define HDRR         struct ecoff_symhdr
@@ -685,7 +675,6 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
       old_sbss_index = -1;
       old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
       old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
-      new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
       new_data2_index = old_bss_index;
     }
   else
@@ -693,7 +682,6 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
       old_bss_addr = OLD_SECTION_H(old_sbss_index).sh_addr;
       old_bss_size = OLD_SECTION_H(old_bss_index).sh_size
        + OLD_SECTION_H(old_sbss_index).sh_size;
-      new_data2_offset = OLD_SECTION_H(old_sbss_index).sh_offset;
       new_data2_index = old_sbss_index;
     }
 
@@ -711,6 +699,20 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
     if (old_mdebug_index == old_file_h->e_shnum)
        old_mdebug_index = 0;
 
+  for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum;
+       old_data_index++)
+    {
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .data - found %s\n",
+              old_section_names + OLD_SECTION_H (old_data_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
+                  ".data"))
+       break;
+    }
+    if (old_data_index == old_file_h->e_shnum)
+       old_data_index = 0;
+
 #if defined (emacs) || !defined (DEBUG)
   new_bss_addr = (ElfW(Addr)) sbrk (0);
 #else
@@ -718,6 +720,8 @@ unexec (char *new_name, char *old_name, unsigned int data_start,
 #endif
   new_data2_addr = old_bss_addr;
   new_data2_size = new_bss_addr - old_bss_addr;
+  new_data2_offset  = OLD_SECTION_H (old_data_index).sh_offset +
+    (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
 
 #ifdef DEBUG
   fprintf (stderr, "old_bss_index %d\n", old_bss_index);
index 53abecf..d10f745 100644 (file)
@@ -61,6 +61,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include <fcntl.h>
 #include <windows.h>
 
+#include "nt.h"
+#include "ntheap.h"
+
 /* From IMAGEHLP.H which is not installed by default by MSVC < 5 */
 /* The IMAGEHLP.DLL library is not distributed by default with Windows95 */
 typedef PIMAGE_NT_HEADERS
@@ -72,9 +75,8 @@ typedef PIMAGE_NT_HEADERS
 extern BOOL ctrl_c_handler (unsigned long type);
 #endif
 
-#include "ntheap.h"
-
-/* Sync with FSF Emacs 19.34.6 note: struct file_data is now defined in ntheap.h */
+/* Sync with FSF Emacs 19.34.6
+   note: struct file_data is now defined in nt.h */
 
 enum {
   HEAP_UNINITIALIZED = 1,
@@ -282,40 +284,6 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss,
   close_file_data (&out_file);
 }
 
-
-/* File handling.  */
-
-
-int
-open_output_file (file_data *p_file, const char *filename, unsigned long size)
-{
-  HANDLE file;
-  HANDLE file_mapping;
-  void  *file_base;
-
-  file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
-                    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
-  if (file == INVALID_HANDLE_VALUE) 
-    return FALSE;
-
-  file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE, 
-                                   0, size, NULL);
-  if (!file_mapping) 
-    return FALSE;
-  
-  file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
-  if (file_base == NULL) 
-    return FALSE;
-  
-  p_file->name = filename;
-  p_file->size = size;
-  p_file->file = file;
-  p_file->file_mapping = file_mapping;
-  p_file->file_base = (char*) file_base;
-
-  return TRUE;
-}
-
 /* Routines to manipulate NT executable file sections.  */
 
 #ifndef DUMP_SEPARATE_SECTION
index 473c778..c3e511f 100644 (file)
@@ -281,9 +281,9 @@ allocate_window (void)
   p->face_cachels     = Dynarr_new (face_cachel);
   p->glyph_cachels    = Dynarr_new (glyph_cachel);
   p->line_start_cache = Dynarr_new (line_start_cache);
-  p->subwindow_instance_cache = make_lisp_hash_table (10,
+  p->subwindow_instance_cache = make_lisp_hash_table (30,
                                                      HASH_TABLE_KEY_WEAK,
-                                                     HASH_TABLE_EQ);
+                                                     HASH_TABLE_EQUAL);
   p->line_cache_last_updated = Qzero;
   INIT_DISP_VARIABLE (last_point_x, 0);
   INIT_DISP_VARIABLE (last_point_y, 0);
@@ -1867,6 +1867,34 @@ replace_window (Lisp_Object old, Lisp_Object replacement)
   /* #### Here, if replacement is a vertical combination
      and so is its new parent, we should make replacement's
      children be children of that parent instead. */
+
+  ERROR_CHECK_SUBWINDOW_CACHE (p);
+}
+
+static int
+window_unmap_subwindows_cache_mapper (Lisp_Object key, Lisp_Object value,
+                                     void *flag_closure)
+{
+  /* value can be nil; we cache failures as well as successes */
+  if (!NILP (value))
+    {
+      struct frame* f = XFRAME (XIMAGE_INSTANCE_FRAME (value));
+      unmap_subwindow (value);
+      /* In case GC doesn't catch up fast enough, remove from the frame
+        cache also. Otherwise code that checks the sanity of the instance
+        will fail. */
+      XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
+       = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
+    }
+  return 0;
+}
+
+static void
+window_unmap_subwindows (struct window* w)
+{
+  assert (!NILP (w->subwindow_instance_cache));
+  elisp_maphash (window_unmap_subwindows_cache_mapper,
+                w->subwindow_instance_cache, 0);
 }
 
 /* we're deleting W; set the structure of W to indicate this. */
@@ -1874,6 +1902,20 @@ replace_window (Lisp_Object old, Lisp_Object replacement)
 static void
 mark_window_as_deleted (struct window *w)
 {
+  /* The window instance cache is going away now, so need to get the
+     cachels reset by redisplay. */
+  MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
+
+  /* The cache is going away. If we leave unmapping to
+     reset_subwindow_cachels then we get in a situation where the
+     domain (the window) has been deleted but we still need access to
+     its attributes in order to unmap windows properly. Since the
+     subwindows are going to get GC'd anyway as a result of the domain
+     going away, it is safer to just unmap them all while we know the
+     domain is still valid. */
+  ERROR_CHECK_SUBWINDOW_CACHE (w);
+  window_unmap_subwindows (w);
+
   /* In the loop
      (while t (split-window) (delete-window))
      we end up with a tree of deleted windows which are all connected
@@ -1885,13 +1927,13 @@ mark_window_as_deleted (struct window *w)
      Since the window-configuration code doesn't need any of the
      pointers to other windows (they are all recreated from the
      window-config data), we set them all to nil so that we
-     are able to collect more actual garbage.
-   */
+     are able to collect more actual garbage. */
   w->next = Qnil;
   w->prev = Qnil;
   w->hchild = Qnil;
   w->vchild = Qnil;
   w->parent = Qnil;
+  w->subwindow_instance_cache = Qnil;
 
   w->dead = 1;
 
@@ -1928,6 +1970,7 @@ will automatically call `save-buffers-kill-emacs'.)
     window = Fselected_window (Qnil);
   else
     CHECK_WINDOW (window);
+
   w = XWINDOW (window);
 
   /* It's okay to delete an already-deleted window.  */
@@ -3475,9 +3518,9 @@ make_dummy_parent (Lisp_Object window)
   p->face_cachels     = Dynarr_new (face_cachel);
   p->glyph_cachels    = Dynarr_new (glyph_cachel);
   p->subwindow_instance_cache = 
-    make_lisp_hash_table (10,
+    make_lisp_hash_table (30,
                          HASH_TABLE_KEY_WEAK,
-                         HASH_TABLE_EQ);
+                         HASH_TABLE_EQUAL);
 
   /* Put new into window structure in place of window */
   replace_window (window, new);
@@ -5173,6 +5216,11 @@ by `current-window-configuration' (which see).
 
       mark_windows_in_use (f, 1);
 
+      /* Force subwindows to be reinstantiated. They are all going
+         anyway and if we don't do this GC may not happen between now
+         and the next time we check their integrity. */
+      reset_frame_subwindow_instance_cache (f);
+
 #if 0
       /* JV: This is bogus,
         First of all, the units are inconsistent. The frame sizes are measured
@@ -5315,6 +5363,14 @@ by `current-window-configuration' (which see).
          w->hscroll = p->hscroll;
          w->modeline_hscroll = p->modeline_hscroll;
          w->line_cache_last_updated = Qzero;
+         /* The subwindow instance cache isn't preserved across
+            window configurations, and in fact doing so would be
+            wrong. We just reset to zero and then redisplay will fill
+            it up as needed. */
+         w->subwindow_instance_cache =
+           make_lisp_hash_table (30,
+                                 HASH_TABLE_KEY_WEAK,
+                                 HASH_TABLE_EQUAL);
          SET_LAST_MODIFIED (w, 1);
          SET_LAST_FACECHANGE (w);
          w->config_mark = 0;
index 8144a47..15ce2b3 100644 (file)
@@ -387,9 +387,13 @@ int invalidate_vertical_divider_cache_in_window (struct window *w,
 int window_divider_width (struct window *w);
 
 #define WINDOW_FRAME(w) ((w)->frame)
+#define WINDOW_XFRAME(w) XFRAME (WINDOW_FRAME (w))
 #define WINDOW_BUFFER(w) ((w)->buffer)
+#define WINDOW_XBUFFER(w) XBUFFER (WINDOW_BUFFER (w))
 #define WINDOW_DEVICE(w) FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))
+#define WINDOW_XDEVICE(w) XDEVICE (WINDOW_DEVICE (w))
 #define WINDOW_CONSOLE(w) DEVICE_CONSOLE (XDEVICE (WINDOW_DEVICE (w)))
+#define WINDOW_XCONSOLE(w) XCONSOLE (WINDOW_CONSOLE (w))
 
 /* XEmacs window size and positioning macros. */
 #define WINDOW_TOP(w) ((w)->pixel_top)
index 36e7a61..821a5a1 100644 (file)
@@ -1,3 +1,7 @@
+2000-05-28  Martin Buchholz <martin@xemacs.org>
+
+       * XEmacs 21.2.34 is released.
+
 2000-05-01  Martin Buchholz <martin@xemacs.org>
 
        * XEmacs 21.2.33 is released.
index c325e36..b5d1727 100644 (file)
 ;; layout
 (setq layout 
       (make-glyph
-       [layout :pixel-width 200 :pixel-height 250
+       [layout :descriptor "The Layout"
               :orientation vertical
               :justify left
               :border [string :data "Hello There Mrs"]
-              :items ([layout :orientation horizontal
-                              :items (radio-button1 radio-button2)]
+              :items ([native-layout :orientation horizontal
+                                     :items (radio-button1 radio-button2)]
                       edit-field toggle-button label str)]))
 (set-glyph-face layout 'gui-element)
 (set-extent-begin-glyph
index ea26a94..44b7645 100644 (file)
@@ -2,8 +2,8 @@
 emacs_is_beta=t
 emacs_major_version=21
 emacs_minor_version=2
-emacs_beta_version=33
-xemacs_codename="Melpomene"
+emacs_beta_version=34
+xemacs_codename="Molpe"
 infodock_major_version=4
 infodock_minor_version=0
 infodock_build_version=8