Mercurial > hg > xemacs-beta
changeset 5082:37a17808de95
Merge.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Fri, 26 Feb 2010 15:24:58 +0000 |
parents | 5502045ec510 (diff) baffa6ca776a (current diff) |
children | 88f955fa5a7f |
files | lisp/ChangeLog |
diffstat | 51 files changed, 2421 insertions(+), 1656 deletions(-) [+] |
line wrap: on
line diff
--- a/etc/ChangeLog Fri Feb 26 15:22:15 2010 +0000 +++ b/etc/ChangeLog Fri Feb 26 15:24:58 2010 +0000 @@ -1,3 +1,8 @@ +2010-02-22 Ben Wing <ben@xemacs.org> + + * dbxrc.in: + test-harness.el is in lisp directory now. + 2010-01-28 Jerry James <james@xemacs.org> * tests/external-widget/Makefile: Add copyright and license
--- a/etc/dbxrc.in Fri Feb 26 15:22:15 2010 +0000 +++ b/etc/dbxrc.in Fri Feb 26 15:24:58 2010 +0000 @@ -4,6 +4,7 @@ ## The generated file depends on src/config.h (currently only in one place). ## Copyright (C) 1998 Free Software Foundation, Inc. +## Copyright (C) 2010 Ben Wing. ## This file is part of XEmacs. @@ -194,7 +195,7 @@ end function check-xemacs { - run -batch -l ../tests/automated/test-harness.el -f batch-test-emacs ../tests/automated + run -batch -l test-harness -f batch-test-emacs ../tests/automated } document check-temacs << 'end' @@ -205,7 +206,7 @@ end function check-temacs { - run-temacs -q -batch -l ../tests/automated/test-harness.el -f batch-test-emacs ../tests/automated + run-temacs -q -batch -l test-harness -f batch-test-emacs ../tests/automated } document update-elc << 'end'
--- a/lib-src/ChangeLog Fri Feb 26 15:22:15 2010 +0000 +++ b/lib-src/ChangeLog Fri Feb 26 15:24:58 2010 +0000 @@ -1,3 +1,10 @@ +2010-02-25 Ben Wing <ben@xemacs.org> + + * make-docfile.c: + * make-docfile.c (write_c_args): + Convert newlines to spaces so that argument lists are always on one + line, because that's what function-documentation-1 expects. + 2010-02-11 Vin Shelton <acs@xemacs.org> * winclient.c: Bump connection retries to 20 because some people
--- a/lib-src/make-docfile.c Fri Feb 26 15:22:15 2010 +0000 +++ b/lib-src/make-docfile.c Fri Feb 26 15:24:58 2010 +0000 @@ -3,7 +3,7 @@ Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1998, 1999 J. Kean Johnston. - Copyright (C) 2001, 2002 Ben Wing. + Copyright (C) 2001, 2002, 2010 Ben Wing. This file is part of XEmacs. @@ -651,11 +651,11 @@ } /* Print the C argument list as it would appear in lisp: - print underscores as hyphens, and print commas and newlines + print underscores as hyphens, and print commas, tabs and newlines as spaces. Collapse adjacent spaces into one. */ if (c == '_') c = '-'; - else if (c == ',' /* || c == '\n' */) + else if (c == ',' || c == '\n' || c == '\t') c = ' '; /* XEmacs change: handle \n below for readability */ @@ -682,18 +682,28 @@ in_ident = 0; just_spaced = 0; } - /* XEmacs change: if the character is carriage return or linefeed, - escape it for the compiler */ +#if 0 + /* [[ XEmacs change: if the character is carriage return or linefeed, + escape it for the compiler ]] I doubt the clause with '\r' ever + worked right, and outputting newlines now screws up the regexp + in function-documentation-1, so don't do this; instead, we treat + newlines like spaces. --ben */ else if (c == '\n') { putc('\\', out); putc('\n', out); + c = ' '; } else if (c == '\r') { putc('\\', out); putc('\r', out); } +#else + else if (c == '\r') /* Just eat it, since we expect a newline to + follow */ + ; +#endif /* (not) 0 */ else if (c != ' ' || !just_spaced) { if (c >= 'a' && c <= 'z')
--- a/lisp/ChangeLog Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/ChangeLog Fri Feb 26 15:24:58 2010 +0000 @@ -1,3 +1,88 @@ +2010-02-25 Didier Verna <didier@xemacs.org> + + The background-placement face property. + * cl-macs.el (face-background-placement): New defsetf. + * cus-face.el (custom-face-attributes): + * faces.el (face-interactive): + * faces.el (set-face-property): + * faces.el (face-equal): + * faces.el (init-other-random-faces): Update. + * faces.el (face-background-placement): + * faces.el (set-face-background-placement): + * faces.el (face-background-placement-instance): + * faces.el (face-background-placement-instance-p): + * frame.el (set-frame-background-placement): + * frame.el (frame-background-placement): + * frame.el (frame-background-placement-instance): + * objects.el (make-face-background-placement-specifier): New. + +c2010-02-25 Ben Wing <ben@xemacs.org> + + * autoload.el (make-autoload): + Call cl-function-arglist with one arg. + + * cl-macs.el (cl-function-arglist): + * cl-macs.el (cl-transform-lambda): + Make cl-function-arglist take only one arg, the arglist; no + function name passed. Also make sure to print () instead of nil + when empty arglist, or function-documentation-1 won't recognize + the arguments: line. + * help.el (function-arglist): If empty arg, don't display extra + space after function name. + +2010-02-24 Aidan Kehoe <kehoea@parhasard.net> + + * cl-extra.el (constantly): + Normally return a compiled function from #'constantly if we are + handed a single argument. Shouldn't actually matter, the overhead + for returning a single constant in a lambda form vs. in a compiled + function is minuscule, but using compiled functions as much as + possible is good style in XEmacs, our interpreter is not stellar + (nor indeed should it need to be). + +2010-02-23 Ben Wing <ben@xemacs.org> + + * help.el: fux typo in comment. (oops) + +2010-02-23 Ben Wing <ben@xemacs.org> + + * autoload.el: + * autoload.el (make-autoload): + * cl-macs.el (cl-function-arglist): + * cl-macs.el (cl-transform-lambda): + Don't add argument list with the tag "Common Lisp lambda list:"; + instead add in "standard" form using "arguments:" and omitting the + function name. Add an arg to `cl-function-arglist' to omit the + name and use it in autoload.el instead of just hacking it off. + + * help.el: + * help.el (function-arglist): + * help.el (function-documentation-1): New. + Extract out common code to recognize and/or strip the arglist from + documentation into `function-documentation-1'. Use in + `function-arglist' and `function-documentation'. Modify + `function-arglist' so it looks for the `arguments: ' stuff in all + doc strings, not just subrs/autoloads, so that CL functions get + recognized properly. Change the regexp used to match "arguments: " + specs to allow nested parens inside the arg list (happens when you + have a default value specified in a CL arglist). + +2010-02-22 Ben Wing <ben@xemacs.org> + + * test-harness.el: + * test-harness.el (test-harness-from-buffer): + * test-harness.el (batch-test-emacs): + Move file from tests/automated into lisp/ so it gets + byte-compiled. This significantly reduces the amount of extra + crap in outputted backtraces. Delete hack in batch-test-emacs to + look for test-harness.el in the test directory since it's not there + any more. + + Also, in `Check-Message', incorporate call to `Skip-Test-Unless' + in the macro output rather than its body, to avoid problems byte- + compiling the file -- `Skip-Test-Unless' isn't available in the + environment during byte-compilation so we can't call it then. + 2010-02-22 Ben Wing <ben@xemacs.org> * cl-seq.el: @@ -86,6 +171,17 @@ Fix errors preventing this from working properly, account for words like "entry" pluralized to "entries". +2010-02-22 Aidan Kehoe <kehoea@parhasard.net> + + * cl-extra.el (constantly): + Add this function, from ANSI Common Lisp, using the SBCL extension + that extra arguments to it are passed back as multiple values in + the constructed function. + * cl-macs.el (constantly): + In the compiler macro for #'constantly, construct a + compiled-function object almost every time, at compile time when + all arguments are constant, and at runtime when they vary. + 2010-02-08 Ben Wing <ben@xemacs.org> * help.el (describe-function-1):
--- a/lisp/autoload.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/autoload.el Fri Feb 26 15:24:58 2010 +0000 @@ -2,7 +2,7 @@ ;; Copyright (C) 1991-1994, 1997, 2003 Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. -;; Copyright (C) 1996, 2000, 2002, 2003, 2004 Ben Wing. +;; Copyright (C) 1996, 2000, 2002, 2003, 2004, 2010 Ben Wing. ;; Original Author: Roland McGrath <roland@gnu.ai.mit.edu> ;; Heavily Modified: XEmacs Maintainers @@ -286,14 +286,11 @@ (body (nthcdr (get car 'doc-string-elt) form)) (doc (if (stringp (car body)) (pop body)))) (if (memq car '(defmacro defmacro* defun defun*)) - (let ((arglist (nth 2 form)) - (placeholder (eval-when-compile (gensym)))) + (let ((arglist (nth 2 form))) (setq doc (concat (or doc "") "\n\narguments: " - (replace-in-string - (cl-function-arglist placeholder arglist) - (format "^(%s ?" placeholder) - "(") "\n")))) + (cl-function-arglist arglist) + "\n")))) ;; `define-generic-mode' quotes the name, so take care of that (list 'autoload (if (listp name) name (list 'quote name)) file doc (or (and (memq car '(define-skeleton define-derived-mode
--- a/lisp/cl-extra.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/cl-extra.el Fri Feb 26 15:24:58 2010 +0000 @@ -612,6 +612,32 @@ ((memq (car plst) indicator-list) (return (values (car plst) (cadr plst) plst)))))) +;; See also the compiler macro in cl-macs.el. +(defun constantly (value &rest more-values) + "Construct a function always returning VALUE, and possibly MORE-VALUES. + +The constructed function accepts any number of arguments, and ignores them. + +Members of MORE-VALUES, if provided, will be passed as multiple values; see +`multiple-value-bind' and `multiple-value-setq'." + (symbol-macrolet + ((arglist '(&rest ignore))) + (if (or more-values (eval-when-compile (not (cl-compiling-file)))) + `(lambda ,arglist (values-list ',(cons value more-values))) + (make-byte-code + arglist + (eval-when-compile + (let ((compiled (byte-compile-sexp #'(lambda (&rest ignore) + (declare (ignore ignore)) + 'placeholder)))) + (assert (and + (equal [placeholder] + (compiled-function-constants compiled)) + (= 1 (compiled-function-stack-depth compiled))) + t + "Our assumptions about compiled code appear not to hold.") + (compiled-function-instructions compiled))) + (vector value) 1)))) ;;; Hash tables.
--- a/lisp/cl-macs.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/cl-macs.el Fri Feb 26 15:24:58 2010 +0000 @@ -297,9 +297,9 @@ (mapcar 'cl-upcase-arg arg))) (t arg))) ; Maybe we are in initializer -;; npak@ispras.ru +;; npak@ispras.ru, modified by ben@666.com ;;;###autoload -(defun cl-function-arglist (name arglist) +(defun cl-function-arglist (arglist) "Returns string with printed representation of arguments list. Supports Common Lisp lambda lists." (if (not (or (listp arglist) (symbolp arglist))) @@ -307,21 +307,20 @@ (check-argument-type #'true-list-p arglist) (let ((print-gensym nil)) (condition-case nil - (prin1-to-string - (cons (if (eq name 'cl-none) 'lambda name) - (cond ((null arglist) nil) - ((listp arglist) (cl-upcase-arg arglist)) - ((symbolp arglist) - (cl-upcase-arg (list '&rest arglist))) - (t (wrong-type-argument 'listp arglist))))) - (t "Not available"))))) + (let ((args (cond ((null arglist) nil) + ((listp arglist) (cl-upcase-arg arglist)) + ((symbolp arglist) + (cl-upcase-arg (list '&rest arglist))) + (t (wrong-type-argument 'listp arglist))))) + (if args (prin1-to-string args) "()")) + (t "Not available"))))) (defun cl-transform-lambda (form bind-block) (let* ((args (car form)) (body (cdr form)) (bind-defs nil) (bind-enquote nil) (bind-inits nil) (bind-lets nil) (bind-forms nil) (header nil) (simple-args nil) - (complex-arglist (cl-function-arglist bind-block args)) + (complex-arglist (cl-function-arglist args)) (doc "")) (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) (push (pop body) header)) @@ -348,12 +347,12 @@ ;; Add CL lambda list to documentation, if the CL lambda list differs ;; from the non-CL lambda list. npak@ispras.ru (unless (equal complex-arglist - (cl-function-arglist bind-block simple-args)) + (cl-function-arglist simple-args)) (and (stringp (car header)) (setq doc (pop header))) - (push (concat doc - "\n\nCommon Lisp lambda list:\n" - " " complex-arglist "\n\n") - header)) + ;; Stick the arguments onto the end of the doc string in a way that + ;; will be recognized specially by `function-arglist'. + (push (concat doc "\n\narguments: " complex-arglist "\n") + header)) (if (null args) (list* nil simple-args (nconc header body)) (if (memq '&optional simple-args) (push '&optional args)) @@ -2160,6 +2159,8 @@ (defsetf face-background (f &optional s) (x) (list 'set-face-background f x s)) (defsetf face-background-pixmap (f &optional s) (x) (list 'set-face-background-pixmap f x s)) +(defsetf face-background-placement (f &optional s) (x) + (list 'set-face-background-placement f x s)) (defsetf face-font (f &optional s) (x) (list 'set-face-font f x s)) (defsetf face-foreground (f &optional s) (x) (list 'set-face-foreground f x s)) (defsetf face-underline-p (f &optional s) (x) @@ -3551,6 +3552,41 @@ (define-compiler-macro notevery (&whole form &rest cl-rest) (cons 'not (cons 'every (cdr cl-rest)))) +(define-compiler-macro constantly (&whole form value &rest more-values) + (cond + ((< (length form) 2) + ;; Error at runtime: + form) + ((cl-const-exprs-p (cdr form)) + `#'(lambda (&rest ignore) (values ,@(cdr form)))) + (t + (let* ((num-values (length (cdr form))) + (placeholders-counts (make-vector num-values -1)) + (placeholders (loop + for i from 0 below num-values + collect (make-symbol (format "%d" i)))) + (compiled + (byte-compile-sexp + `#'(lambda (&rest ignore) + ;; Compiles to a references into the compiled function + ;; constants vector: + (values ,@(mapcar #'quote-maybe placeholders))))) + position) + `(make-byte-code '(&rest ignore) + ,(compiled-function-instructions compiled) + (vector ,@(loop + for constant across (compiled-function-constants compiled) + collect (if (setq position + (position constant placeholders)) + (prog2 + (incf (aref placeholders-counts position)) + (nth position (cdr form))) + (quote-maybe constant)) + finally + (assert (every #'zerop placeholders-counts) + t "Placeholders should each have been used once"))) + ,(compiled-function-stack-depth compiled)))))) + (mapc #'(lambda (y) (put (car y) 'side-effect-free t)
--- a/lisp/cus-face.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/cus-face.el Fri Feb 26 15:24:58 2010 +0000 @@ -1,6 +1,7 @@ ;;; cus-face.el -- Support for Custom faces. ;; ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. +;; Copyright (C) 2010 Didier Verna ;; ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> ;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org> @@ -83,7 +84,12 @@ :help-echo "\ Name of background pixmap file.") set-face-background-pixmap custom-face-background-pixmap) - (:dim (toggle :format "%[Dim%]: %v\n" + (:background-placement (choice :tag "Background placement" :value relative + (const :tag "Relative" :value relative) + (const :tag "Absolute" :value absolute)) + set-face-background-placement + face-background-placement) + (:dim (toggle :format "%[Dim%]: %v\n" :help-echo "Control whether the text should be dimmed.") set-face-dim-p face-dim-p) (:bold (toggle :format "%[Bold%]: %v\n"
--- a/lisp/faces.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/faces.el Fri Feb 26 15:24:58 2010 +0000 @@ -3,6 +3,7 @@ ;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1995 Board of Trustees, University of Illinois ;; Copyright (C) 1995, 1996, 2002, 2005 Ben Wing +;; Copyright (C) 2010 Didier Verna ;; Author: Ben Wing <ben@xemacs.org> ;; Keywords: faces, internal, dumped @@ -87,6 +88,8 @@ (color-instance-name default)) ((image-instance-p default) (image-instance-file-name default)) + ((face-background-placement-instance-p default) + (symbol-name default)) (t default)))))) (list face (if (equal value "") nil value)))) @@ -333,6 +336,11 @@ Only used by faces on X and MS Windows devices. For valid instantiators, see `make-image-specifier'. + background-placement The placement of the face's background pixmap. + Only used by faces on X devices. + For valid instantiators, + see `make-face-background-placement-specifier'. + underline Underline all text covered by this face. For valid instantiators, see `make-face-boolean-specifier'. @@ -716,6 +724,45 @@ (list face (if (equal file "") nil file)))) (set-face-property face 'background-pixmap file)) +(defun face-background-placement (face &optional domain default no-fallback) + "Return FACE's background placement in DOMAIN. +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property face 'background-placement domain default no-fallback)) + +(defun set-face-background-placement (face placement &optional locale tag-set + how-to-add) + "Change the background-placement property of FACE to PLACEMENT. +PLACEMENT is normally a background-placement instantiator; see +`make-face-background-placement-specifier'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and +HOW-TO-ADD arguments." + (interactive (face-interactive "background placement")) + ;; When called non-interactively (for example via custom), PLACEMENT is + ;; expected to be a symbol. -- dvl + (unless (symbolp placement) + (setq placement (intern placement))) + (set-face-property face 'background-placement placement locale tag-set + how-to-add)) + +(defun face-background-placement-instance (face &optional domain default + no-fallback) + "Return FACE's background-placement instance in DOMAIN. +Return value will be a background-placement instance object. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), +and an instance object describing the background placement in that particular +window and buffer will be returned. + +See `face-property-instance' for more information." + (face-property-instance face 'background-placement domain default + no-fallback)) + +(defun face-background-placement-instance-p (object) + "Return t if OBJECT is a face-background-placement instance." + (or (eq object 'absolute) (eq object 'relative))) + (defun face-display-table (face &optional locale tag-set exact-p) "Return the display table spec of FACE in LOCALE, or nil if unspecified.. @@ -871,7 +918,7 @@ (let ((device (dfw-device domain)) (common-props '(foreground background font display-table underline dim inherit)) - (win-props '(background-pixmap strikethru)) + (win-props '(background-pixmap background-placement strikethru)) (tty-props '(highlight blinking reverse))) ;; First check the properties which are used in common between the @@ -1943,7 +1990,8 @@ ;; element faces. So take the modeline face information from its ;; fallbacks, themselves ultimately set up in faces.c: (loop - for face-property in '(foreground background background-pixmap) + for face-property in '(foreground background + background-pixmap background-placement) do (when (and (setq face-property (face-property 'modeline face-property)) (null (specifier-instance face-property device nil t)) (specifier-instance face-property device))
--- a/lisp/frame.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/frame.el Fri Feb 26 15:24:58 2010 +0000 @@ -3,6 +3,7 @@ ;; Copyright (C) 1993, 1994, 1996, 1997, 2000, 2001, 2003 ;; Free Software Foundation, Inc. ;; Copyright (C) 1995, 1996 Ben Wing. +;; Copyright (C) 2010 Didier Verna ;; Maintainer: XEmacs Development Team ;; Keywords: internal, dumped @@ -1015,6 +1016,28 @@ "Set property PROP of FRAME to VAL. See `set-frame-properties'." (set-frame-properties frame (list prop val))) +(defun set-frame-background-placement (placement) + "Set the background placement of the selected frame to PLACEMENT. +When called interactively, prompt for the placement to use." + (interactive (list (intern (completing-read "Placement: " + '(("absolute" absolute) + ("relative" relative)) + nil t)))) + (set-face-background-placement 'default placement (selected-frame))) + +(defun frame-background-placement () + "Retrieve the selected frame's background placement." + (interactive) + (face-background-placement 'default (selected-frame))) + +(defun frame-background-placement-instance () + "Retrieve the selected frame's background placement instance." + (interactive) + (face-background-placement-instance 'default (selected-frame))) + +;; #### FIXME: misnomers ! The functions below should be called +;; set-frame-<blabla> -- dvl. + ;; XEmacs change: this function differs significantly from Emacs. (defun set-background-color (color-name) "Set the background color of the selected frame to COLOR-NAME.
--- a/lisp/help.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/help.el Fri Feb 26 15:24:58 2010 +0000 @@ -1,7 +1,7 @@ ;; help.el --- help commands for XEmacs. ;; Copyright (C) 1985, 1986, 1992-4, 1997 Free Software Foundation, Inc. -;; Copyright (C) 2001, 2002, 2003 Ben Wing. +;; Copyright (C) 2001, 2002, 2003, 2010 Ben Wing. ;; Maintainer: FSF ;; Keywords: help, internal, dumped @@ -1182,27 +1182,21 @@ (fndef (if (eq (car-safe fnc) 'macro) (cdr fnc) fnc)) + (args (cdr (function-documentation-1 function t))) (arglist - (cond ((compiled-function-p fndef) - (compiled-function-arglist fndef)) - ((eq (car-safe fndef) 'lambda) - (nth 1 fndef)) - ((or (subrp fndef) (eq 'autoload (car-safe fndef))) - (let* ((doc (documentation function)) - (args (and doc - (string-match - "[\n\t ]*\narguments: ?(\\([^)]*\\))\n?\\'" - doc) - (match-string 1 doc))) - (args (and args (replace-in-string args - "[ ]*\\\\\n[ \t]*" - " " t)))) - ;; If there are no arguments documented for the - ;; subr, rather don't print anything. - (cond ((null args) t) - ((equal args "") nil) - (args)))) - (t t))) + (or args + (cond ((compiled-function-p fndef) + (compiled-function-arglist fndef)) + ((eq (car-safe fndef) 'lambda) + (nth 1 fndef)) + ((or (subrp fndef) (eq 'autoload (car-safe fndef))) + + ;; If there are no arguments documented for the + ;; subr, rather don't print anything. + (cond ((null args) t) + ((equal args "") nil) + (args))) + (t t)))) (print-gensym nil)) (cond ((listp arglist) (prin1-to-string @@ -1215,22 +1209,35 @@ t)) ((stringp arglist) - (format "(%s %s)" function arglist))))) + (if (> (length arglist) 0) + (format "(%s %s)" function arglist) + (format "(%s)" function)))))) + +;; If STRIP-ARGLIST is true, return a cons (DOC . ARGS) of the documentation +;; with any embedded arglist stripped out, and the arglist that was stripped +;; out. If STRIP-ARGLIST is false, the cons will be (FULL-DOC . nil), +;; where FULL-DOC is the full documentation without the embedded arglist +;; stripped out. +(defun function-documentation-1 (function &optional strip-arglist) + (let ((doc (condition-case nil + (or (documentation function) + (gettext "not documented")) + (void-function "(alias for undefined function)") + (error "(unexpected error from `documentation')"))) + args) + (when (and strip-arglist + (string-match "[\n\t ]*\narguments: ?(\\(.*\\))\n?\\'" doc)) + (setq args (match-string 1 doc)) + (setq doc (substring doc 0 (match-beginning 0))) + (and args (setq args (replace-in-string args "[ ]*\\\\\n[ \t]*" " " t))) + (and (zerop (length doc)) (setq doc (gettext "not documented")))) + (cons doc args))) (defun function-documentation (function &optional strip-arglist) "Return a string giving the documentation for FUNCTION, if any. If the optional argument STRIP-ARGLIST is non-nil, remove the arglist -part of the documentation of internal subroutines." - (let ((doc (condition-case nil - (or (documentation function) - (gettext "not documented")) - (void-function "(alias for undefined function)") - (error "(unexpected error from `documention')")))) - (when (and strip-arglist - (string-match "[\n\t ]*\narguments: ?(\\([^)]*\\))\n?\\'" doc)) - (setq doc (substring doc 0 (match-beginning 0))) - (and (zerop (length doc)) (setq doc (gettext "not documented")))) - doc)) +part of the documentation of internal subroutines, CL lambda forms, etc." + (car (function-documentation-1 function strip-arglist))) ;; replacement for `princ' that puts the text in the specified face, ;; if possible
--- a/lisp/objects.el Fri Feb 26 15:22:15 2010 +0000 +++ b/lisp/objects.el Fri Feb 26 15:24:58 2010 +0000 @@ -2,6 +2,7 @@ ;; Copyright (C) 1994, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1995 Ben Wing +;; Copyright (C) 2010 Didier Verna ;; Author: Chuck Thompson <cthomp@xemacs.org> ;; Author: Ben Wing <ben@xemacs.org> @@ -194,4 +195,18 @@ if non-nil, means to invert the sense of the inherited property." (make-specifier-and-init 'face-boolean spec-list)) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; face-background-placement specifiers + +(defun make-face-background-placement-specifier (spec-list) + "Return a new `face-background-placement' specifier object. +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-background-placement specifiers are: +-- absolute or relative (symbols), +-- a vector of one element: a face to inherit from." + (make-specifier-and-init 'face-background-placement spec-list)) + ;;; objects.el ends here.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/test-harness.el Fri Feb 26 15:24:58 2010 +0000 @@ -0,0 +1,835 @@ +;; test-harness.el --- Run Emacs Lisp test suites. + +;;; Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. +;;; Copyright (C) 2002, 2010 Ben Wing. + +;; Author: Martin Buchholz +;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org> +;; Keywords: testing + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;;; A test suite harness for testing XEmacs. +;;; The actual tests are in other files in this directory. +;;; Basically you just create files of emacs-lisp, and use the +;;; Assert, Check-Error, Check-Message, and Check-Error-Message functions +;;; to create tests. See `test-harness-from-buffer' below. +;;; Don't suppress tests just because they're due to known bugs not yet +;;; fixed -- use the Known-Bug-Expect-Failure and +;;; Implementation-Incomplete-Expect-Failure wrapper macros to mark them. +;;; A lot of the tests we run push limits; suppress Ebola message with the +;;; Ignore-Ebola wrapper macro. +;;; Some noisy code will call `message'. Output from `message' can be +;;; suppressed with the Silence-Message macro. Functions that are known to +;;; issue messages include `write-region', `find-tag', `tag-loop-continue', +;;; `insert', and `mark-whole-buffer'. N.B. The Silence-Message macro +;;; currently does not suppress the newlines printed by `message'. +;;; Definitely do not use Silence-Message with Check-Message. +;;; In general it should probably only be used on code that prepares for a +;;; test, not on tests. +;;; +;;; You run the tests using M-x test-emacs-test-file, +;;; or $(EMACS) -batch -l test-harness -f batch-test-emacs file ... +;;; which is run for you by the `make check' target in the top-level Makefile. + +(require 'bytecomp) + +(defvar unexpected-test-suite-failures 0 + "Cumulative number of unexpected failures since test-harness was loaded. + +\"Unexpected failures\" are those caught by a generic handler established +outside of the test context. As such they involve an abort of the test +suite for the file being tested. + +They often occur during preparation of a test or recording of the results. +For example, an executable used to generate test data might not be present +on the system, or a system error might occur while reading a data file.") + +(defvar unexpected-test-suite-failure-files nil + "List of test files causing unexpected failures.") + +;; Declared for dynamic scope; _do not_ initialize here. +(defvar unexpected-test-file-failures) + +(defvar test-harness-bug-expected nil + "Non-nil means a bug is expected; backtracing/debugging should not happen.") + +(defvar test-harness-test-compiled nil + "Non-nil means the test code was compiled before execution. + +You probably should not make tests depend on compilation. +However, it can be useful to conditionally change messages based on whether +the code was compiled or not. For example, the case that motivated the +implementation of this variable: + +\(when test-harness-test-compiled + ;; this ha-a-ack depends on the failing compiled test coming last + \(setq test-harness-failure-tag + \"KNOWN BUG - fix reverted; after 2003-10-31 notify stephen\n\"))") + +(defvar test-harness-verbose + (and (not noninteractive) (> (device-baud-rate) search-slow-speed)) + "*Non-nil means print messages describing progress of emacs-tester.") + +(defvar test-harness-unexpected-error-enter-debugger debug-on-error + "*Non-nil means enter debugger when an unexpected error occurs. +Only applies interactively. Normally true if `debug-on-error' has been set. +See also `test-harness-assertion-failure-enter-debugger' and +`test-harness-unexpected-error-show-backtrace'.") + +(defvar test-harness-assertion-failure-enter-debugger debug-on-error + "*Non-nil means enter debugger when an assertion failure occurs. +Only applies interactively. Normally true if `debug-on-error' has been set. +See also `test-harness-unexpected-error-enter-debugger' and +`test-harness-assertion-failure-show-backtrace'.") + +(defvar test-harness-unexpected-error-show-backtrace t + "*Non-nil means show backtrace upon unexpected error. +Only applies when debugger is not entered. Normally true by default. See also +`test-harness-unexpected-error-enter-debugger' and +`test-harness-assertion-failure-show-backtrace'.") + +(defvar test-harness-assertion-failure-show-backtrace stack-trace-on-error + "*Non-nil means show backtrace upon assertion failure. +Only applies when debugger is not entered. Normally true if +`stack-trace-on-error' has been set. See also +`test-harness-assertion-failure-enter-debugger' and +`test-harness-unexpected-error-show-backtrace'.") + +(defvar test-harness-file-results-alist nil + "Each element is a list (FILE SUCCESSES TESTS). +The order is the reverse of the order in which tests are run. + +FILE is a string naming the test file. +SUCCESSES is a non-negative integer, the number of successes. +TESTS is a non-negative integer, the number of tests run.") + +(defvar test-harness-risk-infloops nil + "*Non-nil to run tests that may loop infinitely in buggy implementations.") + +(defvar test-harness-current-file nil) + +(defvar emacs-lisp-file-regexp (purecopy "\\.el\\'") + "*Regexp which matches Emacs Lisp source files.") + +(defconst test-harness-file-summary-template + (format "%%-%ds %%%dd of %%%dd tests successful (%%3d%%%%)." + (length "byte-compiler-tests.el:") ; use the longest file name + 5 + 5) + "Format for summary lines printed after each file is run.") + +(defconst test-harness-null-summary-template + (format "%%-%ds No tests run." + (length "byte-compiler-tests.el:")) ; use the longest file name + "Format for \"No tests\" lines printed after a file is run.") + +(defconst test-harness-aborted-summary-template + (format "%%-%ds %%%dd tests completed (aborted)." + (length "byte-compiler-tests.el:") ; use the longest file name + 5) + "Format for summary lines printed after a test run on a file was aborted.") + +;;;###autoload +(defun test-emacs-test-file (filename) + "Test a file of Lisp code named FILENAME. +The output file's name is made by appending `c' to the end of FILENAME." + (interactive + (let ((file buffer-file-name) + (file-name nil) + (file-dir nil)) + (and file + (eq (cdr (assq 'major-mode (buffer-local-variables))) + 'emacs-lisp-mode) + (setq file-name (file-name-nondirectory file) + file-dir (file-name-directory file))) + (list (read-file-name "Test file: " file-dir nil nil file-name)))) + ;; Expand now so we get the current buffer's defaults + (setq filename (expand-file-name filename)) + + ;; If we're testing a file that's in a buffer and is modified, offer + ;; to save it first. + (or noninteractive + (let ((b (get-file-buffer (expand-file-name filename)))) + (if (and b (buffer-modified-p b) + (y-or-n-p (format "save buffer %s first? " (buffer-name b)))) + (save-excursion (set-buffer b) (save-buffer))))) + + (if (or noninteractive test-harness-verbose) + (message "Testing %s..." filename)) + (let ((test-harness-current-file filename) + input-buffer) + (save-excursion + (setq input-buffer (get-buffer-create " *Test Input*")) + (set-buffer input-buffer) + (erase-buffer) + (insert-file-contents filename) + ;; Run hooks including the uncompression hook. + ;; If they change the file name, then change it for the output also. + (let ((buffer-file-name filename) + (default-major-mode 'emacs-lisp-mode) + (enable-local-eval nil)) + (normal-mode) + (setq filename buffer-file-name))) + (test-harness-from-buffer input-buffer filename) + (kill-buffer input-buffer) + )) + +(defsubst test-harness-assertion-failure-do-debug (error-info) + "Maybe enter debugger or display a backtrace on assertion failure. +ERROR-INFO is a cons of the args (SIG . DATA) that were passed to `signal'. +The debugger will be entered if noninteractive and +`test-harness-unexpected-error-enter-debugger' is non-nil; else, a +backtrace will be displayed if `test-harness-unexpected-error-show-backtrace' +is non-nil." + (when (not test-harness-bug-expected) + (cond ((and (not noninteractive) + test-harness-assertion-failure-enter-debugger) + (funcall debugger 'error error-info)) + (test-harness-assertion-failure-show-backtrace + (backtrace nil t))))) + +(defsubst test-harness-unexpected-error-do-debug (error-info) + "Maybe enter debugger or display a backtrace on unexpected error. +ERROR-INFO is a cons of the args (SIG . DATA) that were passed to `signal'. +The debugger will be entered if noninteractive and +`test-harness-unexpected-error-enter-debugger' is non-nil; else, a +backtrace will be displayed if `test-harness-unexpected-error-show-backtrace' +is non-nil." + (when (not test-harness-bug-expected) + (cond ((and (not noninteractive) + test-harness-unexpected-error-enter-debugger) + (funcall debugger 'error error-info)) + (test-harness-unexpected-error-show-backtrace + (backtrace nil t))))) + +(defsubst test-harness-unexpected-error-condition-handler (error-info context-msg) + "Condition handler for when unexpected errors occur. +Useful in conjunction with `call-with-condition-handler'. ERROR-INFO is the +value passed to the condition handler. CONTEXT-MSG is a string indicating +the context in which the unexpected error occurred. A message is outputted +including CONTEXT-MSG in it, `unexpected-test-file-failures' is incremented, +and `test-harness-unexpected-error-do-debug' is called, which may enter the +debugger or output a backtrace, depending on the settings of +`test-harness-unexpected-error-enter-debugger' and +`test-harness-unexpected-error-show-backtrace'. + +The function returns normally, which causes error-handling processing to +continue; if you want to catch the error, you also need to wrap everything +in `condition-case'. See also `test-harness-error-wrap', which does this +wrapping." + (incf unexpected-test-file-failures) + (princ (format "Unexpected error %S while %s\n" + error-info context-msg)) + (message "Unexpected error %S while %s." error-info context-msg) + (test-harness-unexpected-error-do-debug error-info)) + +(defmacro test-harness-error-wrap (context-msg abort-msg &rest body) + "Wrap BODY so that unexpected errors are caught. +The debugger will be entered if noninteractive and +`test-harness-unexpected-error-enter-debugger' is non-nil; else, a backtrace +will be displayed if `test-harness-unexpected-error-show-backtrace' is +non-nil. CONTEXT-MSG is displayed as part of a message shown before entering +the debugger or showing a backtrace, and ABORT-MSG, if non-nil, is displayed +afterwards. See " + `(condition-case nil + (call-with-condition-handler + #'(lambda (error-info) + (test-harness-unexpected-error-condition-handler + error-info ,context-msg)) + #'(lambda () + ,@body)) + (error ,(if abort-msg `(message ,abort-msg) nil)))) + +(defun test-harness-read-from-buffer (buffer) + "Read forms from BUFFER, and turn it into a lambda test form." + (let ((body nil)) + (goto-char (point-min) buffer) + (condition-case nil + (call-with-condition-handler + #'(lambda (error-info) + ;; end-of-file is expected, so don't output error or backtrace + ;; or enter debugger in this case. + (unless (eq 'end-of-file (car error-info)) + (test-harness-unexpected-error-condition-handler + error-info "reading forms from buffer"))) + #'(lambda () + (while t + (setq body (cons (read buffer) body))))) + (error nil)) + `(lambda () + (defvar passes) + (defvar assertion-failures) + (defvar no-error-failures) + (defvar wrong-error-failures) + (defvar missing-message-failures) + (defvar other-failures) + + (defvar trick-optimizer) + + ,@(nreverse body)))) + +(defun test-harness-from-buffer (inbuffer filename) + "Run tests in buffer INBUFFER, visiting FILENAME." + (defvar trick-optimizer) + (let ((passes 0) + (assertion-failures 0) + (no-error-failures 0) + (wrong-error-failures 0) + (missing-message-failures 0) + (other-failures 0) + (unexpected-test-file-failures 0) + + ;; #### perhaps this should be a defvar, and output at the very end + ;; OTOH, this way AC types can use a null EMACSPACKAGEPATH to find + ;; what stuff is needed, and ways to avoid using them + (skipped-test-reasons (make-hash-table :test 'equal)) + + (trick-optimizer nil) + (debug-on-error t) + ) + (with-output-to-temp-buffer "*Test-Log*" + (princ (format "Testing %s...\n\n" filename)) + + (defconst test-harness-failure-tag "FAIL") + (defconst test-harness-success-tag "PASS") + +;;;;; BEGIN DEFINITION OF MACROS USEFUL IN TEST CODE + + (defmacro Known-Bug-Expect-Failure (&rest body) + "Wrap a BODY that consists of tests that are known to fail. +This causes messages to be printed on failure indicating that this is expected, +and on success indicating that this is unexpected." + `(let ((test-harness-bug-expected t) + (test-harness-failure-tag "KNOWN BUG") + (test-harness-success-tag "PASS (FAILURE EXPECTED)")) + ,@body)) + + (defmacro Known-Bug-Expect-Error (expected-error &rest body) + "Wrap a BODY that consists of tests that are known to trigger an error. +This causes messages to be printed on failure indicating that this is expected, +and on success indicating that this is unexpected." + (let ((quoted-body (if (= 1 (length body)) + `(quote ,(car body)) `(quote (progn ,@body))))) + `(let ((test-harness-bug-expected t) + (test-harness-failure-tag "KNOWN BUG") + (test-harness-success-tag "PASS (FAILURE EXPECTED)")) + (condition-case error-info + (progn + (setq trick-optimizer (progn ,@body)) + (Print-Pass + "%S executed successfully, but expected error %S" + ,quoted-body + ',expected-error) + (incf passes)) + (,expected-error + (Print-Failure "%S ==> error %S, as expected" + ,quoted-body ',expected-error) + (incf no-error-failures)) + (error + (Print-Failure "%S ==> expected error %S, got error %S instead" + ,quoted-body ',expected-error error-info) + (incf wrong-error-failures)))))) + + (defmacro Implementation-Incomplete-Expect-Failure (&rest body) + "Wrap a BODY containing tests that are known to fail due to incomplete code. +This causes messages to be printed on failure indicating that the +implementation is incomplete (and hence the failure is expected); and on +success indicating that this is unexpected." + `(let ((test-harness-bug-expected t) + (test-harness-failure-tag "IMPLEMENTATION INCOMPLETE") + (test-harness-success-tag "PASS (FAILURE EXPECTED)")) + ,@body)) + + (defun Print-Failure (fmt &rest args) + (setq fmt (format "%s: %s" test-harness-failure-tag fmt)) + (if (noninteractive) (apply #'message fmt args)) + (princ (concat (apply #'format fmt args) "\n"))) + + (defun Print-Pass (fmt &rest args) + (setq fmt (format "%s: %s" test-harness-success-tag fmt)) + (and test-harness-verbose + (princ (concat (apply #'format fmt args) "\n")))) + + (defun Print-Skip (test reason &optional fmt &rest args) + (setq fmt (concat "SKIP: %S BECAUSE %S" fmt)) + (princ (concat (apply #'format fmt test reason args) "\n"))) + + (defmacro Skip-Test-Unless (condition reason description &rest body) + "Unless CONDITION is satisfied, skip test BODY. +REASON is a description of the condition failure, and must be unique (it +is used as a hash key). DESCRIPTION describes the tests that were skipped. +BODY is a sequence of expressions and may contain several tests." + `(if (not ,condition) + (let ((count (gethash ,reason skipped-test-reasons))) + (puthash ,reason (if (null count) 1 (1+ count)) + skipped-test-reasons) + (Print-Skip ,description ,reason)) + ,@body)) + + (defmacro Assert (assertion &optional failing-case description) + "Test passes if ASSERTION is true. +Optional FAILING-CASE describes the particular failure. Optional +DESCRIPTION describes the assertion; by default, the unevalated assertion +expression is given. FAILING-CASE and DESCRIPTION are useful when Assert +is used in a loop." + (let ((description + (or description `(quote ,assertion)))) + `(condition-case nil + (call-with-condition-handler + #'(lambda (error-info) + (if (eq 'cl-assertion-failed (car error-info)) + (progn + (Print-Failure + (if ,failing-case + "Assertion failed: %S; failing case = %S" + "Assertion failed: %S") + ,description ,failing-case) + (incf assertion-failures) + (test-harness-assertion-failure-do-debug error-info)) + (Print-Failure + (if ,failing-case + "%S ==> error: %S; failing case = %S" + "%S ==> error: %S") + ,description error-info ,failing-case) + (incf other-failures) + (test-harness-unexpected-error-do-debug error-info))) + #'(lambda () + (assert ,assertion) + (Print-Pass "%S" ,description) + (incf passes))) + (cl-assertion-failed nil)))) + +;;;;; BEGIN DEFINITION OF SPECIFIC KINDS OF ASSERT MACROS + + (defmacro Assert-test (test testval expected &optional failing-case + description) + "Test passes if TESTVAL compares correctly to EXPECTED using TEST. +TEST should be a two-argument predicate (i.e. a function of two arguments +that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=', +'>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the +particular failure; any value given here will be concatenated with a phrase +describing the expected and actual values of the comparison. Optional +DESCRIPTION describes the assertion; by default, the unevalated comparison +expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert +is used in a loop." + (let* ((assertion `(,test ,testval ,expected)) + (failmsg `(format "%S should be `%s' to %S but isn't" + ,testval ',test ,expected)) + (failmsg2 (if failing-case `(concat + (format "%S, " ,failing-case) + ,failmsg) + failmsg))) + `(Assert ,assertion ,failmsg2 ,description))) + + (defmacro Assert-test-not (test testval expected &optional failing-case + description) + "Test passes if TESTVAL does not compare correctly to EXPECTED using TEST. +TEST should be a two-argument predicate (i.e. a function of two arguments +that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=', +'>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the +particular failure; any value given here will be concatenated with a phrase +describing the expected and actual values of the comparison. Optional +DESCRIPTION describes the assertion; by default, the unevalated comparison +expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert +is used in a loop." + (let* ((assertion `(not (,test ,testval ,expected))) + (failmsg `(format "%S shouldn't be `%s' to %S but is" + ,testval ',test ,expected)) + (failmsg2 (if failing-case `(concat + (format "%S, " ,failing-case) + ,failmsg) + failmsg))) + `(Assert ,assertion ,failmsg2 ,description))) + + ;; Specific versions of `Assert-test'. These are just convenience + ;; functions, functioning identically to `Assert-test', and duplicating + ;; the doc string for each would be too annoying. + (defmacro Assert-eq (testval expected &optional failing-case + description) + `(Assert-test eq ,testval ,expected ,failing-case ,description)) + (defmacro Assert-eql (testval expected &optional failing-case + description) + `(Assert-test eql ,testval ,expected ,failing-case ,description)) + (defmacro Assert-equal (testval expected &optional failing-case + description) + `(Assert-test equal ,testval ,expected ,failing-case ,description)) + (defmacro Assert-equalp (testval expected &optional failing-case + description) + `(Assert-test equalp ,testval ,expected ,failing-case ,description)) + (defmacro Assert-string= (testval expected &optional failing-case + description) + `(Assert-test string= ,testval ,expected ,failing-case ,description)) + (defmacro Assert= (testval expected &optional failing-case + description) + `(Assert-test = ,testval ,expected ,failing-case ,description)) + (defmacro Assert<= (testval expected &optional failing-case + description) + `(Assert-test <= ,testval ,expected ,failing-case ,description)) + + ;; Specific versions of `Assert-test-not'. These are just convenience + ;; functions, functioning identically to `Assert-test-not', and + ;; duplicating the doc string for each would be too annoying. + (defmacro Assert-not-eq (testval expected &optional failing-case + description) + `(Assert-test-not eq ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-eql (testval expected &optional failing-case + description) + `(Assert-test-not eql ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-equal (testval expected &optional failing-case + description) + `(Assert-test-not equal ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-equalp (testval expected &optional failing-case + description) + `(Assert-test-not equalp ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not-string= (testval expected &optional failing-case + description) + `(Assert-test-not string= ,testval ,expected ,failing-case ,description)) + (defmacro Assert-not= (testval expected &optional failing-case + description) + `(Assert-test-not = ,testval ,expected ,failing-case ,description)) + + (defmacro Check-Error (expected-error &rest body) + (let ((quoted-body (if (= 1 (length body)) + `(quote ,(car body)) `(quote (progn ,@body))))) + `(condition-case error-info + (progn + (setq trick-optimizer (progn ,@body)) + (Print-Failure "%S executed successfully, but expected error %S" + ,quoted-body + ',expected-error) + (incf no-error-failures)) + (,expected-error + (Print-Pass "%S ==> error %S, as expected" + ,quoted-body ',expected-error) + (incf passes)) + (error + (Print-Failure "%S ==> expected error %S, got error %S instead" + ,quoted-body ',expected-error error-info) + (incf wrong-error-failures))))) + + (defmacro Check-Error-Message (expected-error expected-error-regexp + &rest body) + (let ((quoted-body (if (= 1 (length body)) + `(quote ,(car body)) `(quote (progn ,@body))))) + `(condition-case error-info + (progn + (setq trick-optimizer (progn ,@body)) + (Print-Failure "%S executed successfully, but expected error %S" + ,quoted-body ',expected-error) + (incf no-error-failures)) + (,expected-error + ;; #### Damn, this binding doesn't capture frobs, eg, for + ;; invalid_argument() ... you only get the REASON. And for + ;; wrong_type_argument(), there's no reason only FROBs. + ;; If this gets fixed, fix tests in regexp-tests.el. + (let ((error-message (second error-info))) + (if (string-match ,expected-error-regexp error-message) + (progn + (Print-Pass "%S ==> error %S %S, as expected" + ,quoted-body error-message ',expected-error) + (incf passes)) + (Print-Failure "%S ==> got error %S as expected, but error message %S did not match regexp %S" + ,quoted-body ',expected-error error-message ,expected-error-regexp) + (incf wrong-error-failures)))) + (error + (Print-Failure "%S ==> expected error %S, got error %S instead" + ,quoted-body ',expected-error error-info) + (incf wrong-error-failures))))) + + ;; Do not use this with Silence-Message. + (defmacro Check-Message (expected-message-regexp &rest body) + (let ((quoted-body (if (= 1 (length body)) + `(quote ,(car body)) + `(quote (progn ,@body))))) + `(Skip-Test-Unless (fboundp 'defadvice) "can't defadvice" + expected-message-regexp + (let ((messages "")) + (defadvice message (around collect activate) + (defvar messages) + (let ((msg-string (apply 'format (ad-get-args 0)))) + (setq messages (concat messages msg-string)) + msg-string)) + (ignore-errors + (call-with-condition-handler + #'(lambda (error-info) + (Print-Failure "%S ==> unexpected error %S" + ,quoted-body error-info) + (incf other-failures) + (test-harness-unexpected-error-do-debug error-info)) + #'(lambda () + (setq trick-optimizer (progn ,@body)) + (if (string-match ,expected-message-regexp messages) + (progn + (Print-Pass + "%S ==> value %S, message %S, matching %S, as expected" + ,quoted-body trick-optimizer messages + ',expected-message-regexp) + (incf passes)) + (Print-Failure + "%S ==> value %S, message %S, NOT matching expected %S" + ,quoted-body trick-optimizer messages + ',expected-message-regexp) + (incf missing-message-failures))))) + (ad-unadvise 'message))))) + + ;; #### Perhaps this should override `message' itself, too? + (defmacro Silence-Message (&rest body) + `(flet ((append-message (&rest args) ()) + (clear-message (&rest args) ())) + ,@body)) + + (defmacro Ignore-Ebola (&rest body) + `(let ((debug-issue-ebola-notices -42)) ,@body)) + + (defun Int-to-Marker (pos) + (save-excursion + (set-buffer standard-output) + (save-excursion + (goto-char pos) + (point-marker)))) + + (princ "Testing Interpreted Lisp\n\n") + + (test-harness-error-wrap + "executing interpreted code" + "Test suite execution aborted." + (funcall (test-harness-read-from-buffer inbuffer))) + + (princ "\nTesting Compiled Lisp\n\n") + + (let (code + (test-harness-test-compiled t)) + (test-harness-error-wrap + "byte-compiling code" nil + (setq code + ;; our lisp code is often intentionally dubious, + ;; so throw away _all_ the byte compiler warnings. + (letf (((symbol-function 'byte-compile-warn) + 'ignore)) + (byte-compile (test-harness-read-from-buffer + inbuffer)))) + ) + + (test-harness-error-wrap "executing byte-compiled code" + "Test suite execution aborted." + (if code (funcall code))) + ) + (princ (format "\nSUMMARY for %s:\n" filename)) + (princ (format "\t%5d passes\n" passes)) + (princ (format "\t%5d assertion failures\n" assertion-failures)) + (princ (format "\t%5d errors that should have been generated, but weren't\n" no-error-failures)) + (princ (format "\t%5d wrong-error failures\n" wrong-error-failures)) + (princ (format "\t%5d missing-message failures\n" missing-message-failures)) + (princ (format "\t%5d other failures\n" other-failures)) + (let* ((total (+ passes + assertion-failures + no-error-failures + wrong-error-failures + missing-message-failures + other-failures)) + (basename (file-name-nondirectory filename)) + (summary-msg + (cond ((> unexpected-test-file-failures 0) + (format test-harness-aborted-summary-template + (concat basename ":") total)) + ((> total 0) + (format test-harness-file-summary-template + (concat basename ":") + passes total (/ (* 100 passes) total))) + (t + (format test-harness-null-summary-template + (concat basename ":"))))) + (reasons "")) + (maphash (lambda (key value) + (setq reasons + (concat reasons + (format "\n %d tests skipped because %s." + value key)))) + skipped-test-reasons) + (when (> (length reasons) 1) + (setq summary-msg (concat summary-msg reasons " + It may be that XEmacs cannot find your installed packages. Set + EMACSPACKAGEPATH to the package hierarchy root or configure with + --package-path to enable the skipped tests."))) + (setq test-harness-file-results-alist + (cons (list filename passes total) + test-harness-file-results-alist)) + (message "%s" summary-msg)) + (when (> unexpected-test-file-failures 0) + (setq unexpected-test-suite-failure-files + (cons filename unexpected-test-suite-failure-files)) + (setq unexpected-test-suite-failures + (+ unexpected-test-suite-failures unexpected-test-file-failures)) + (message "Test suite execution failed unexpectedly.")) + (fmakunbound 'Assert) + (fmakunbound 'Check-Error) + (fmakunbound 'Check-Message) + (fmakunbound 'Check-Error-Message) + (fmakunbound 'Ignore-Ebola) + (fmakunbound 'Int-to-Marker) + (and noninteractive + (message "%s" (buffer-substring-no-properties + nil nil "*Test-Log*"))) + ))) + +(defvar test-harness-results-point-max nil) +(defmacro displaying-emacs-test-results (&rest body) + `(let ((test-harness-results-point-max test-harness-results-point-max)) + ;; Log the file name. + (test-harness-log-file) + ;; Record how much is logged now. + ;; We will display the log buffer if anything more is logged + ;; before the end of BODY. + (or test-harness-results-point-max + (save-excursion + (set-buffer (get-buffer-create "*Test-Log*")) + (setq test-harness-results-point-max (point-max)))) + (unwind-protect + (condition-case error-info + (progn ,@body) + (error + (test-harness-report-error error-info))) + (save-excursion + ;; If there were compilation warnings, display them. + (set-buffer "*Test-Log*") + (if (= test-harness-results-point-max (point-max)) + nil + (if temp-buffer-show-function + (let ((show-buffer (get-buffer-create "*Test-Log-Show*"))) + (save-excursion + (set-buffer show-buffer) + (setq buffer-read-only nil) + (erase-buffer)) + (copy-to-buffer show-buffer + (save-excursion + (goto-char test-harness-results-point-max) + (forward-line -1) + (point)) + (point-max)) + (funcall temp-buffer-show-function show-buffer)) + (select-window + (prog1 (selected-window) + (select-window (display-buffer (current-buffer))) + (goto-char test-harness-results-point-max) + (recenter 1))))))))) + +(defun batch-test-emacs-1 (file) + (condition-case error-info + (progn (test-emacs-test-file file) t) + (error + (princ ">>Error occurred processing ") + (princ file) + (princ ": ") + (display-error error-info nil) + (terpri) + nil))) + +(defun batch-test-emacs () + "Run `test-harness' on the files remaining on the command line. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. +Each file is processed even if an error occurred previously. +A directory can be given as well, and all files will be processed. +For example, invoke \"xemacs -batch -f batch-test-emacs tests\"" + ;; command-line-args-left is what is left of the command line (from + ;; startup.el) + (defvar command-line-args-left) ;Avoid 'free variable' warning + (defvar debug-issue-ebola-notices) + (if (not noninteractive) + (error "`batch-test-emacs' is to be used only with -batch")) + (let ((error nil)) + (dolist (file command-line-args-left) + (if (file-directory-p file) + (dolist (file-in-dir (directory-files file t)) + (when (and (string-match emacs-lisp-file-regexp file-in-dir) + (not (or (auto-save-file-name-p file-in-dir) + (backup-file-name-p file-in-dir)))) + (or (batch-test-emacs-1 file-in-dir) + (setq error t)))) + (or (batch-test-emacs-1 file) + (setq error t)))) + (let ((namelen 0) + (succlen 0) + (testlen 0) + (results test-harness-file-results-alist)) + ;; compute maximum lengths of variable components of report + ;; probably should just use (length "byte-compiler-tests.el") + ;; and 5-place sizes -- this will also work for the file-by-file + ;; printing when Adrian's kludge gets reverted + (flet ((print-width (i) + (let ((x 10) (y 1)) + (while (>= i x) + (setq x (* 10 x) y (1+ y))) + y))) + (while results + (let* ((head (car results)) + (nn (length (file-name-nondirectory (first head)))) + (ss (print-width (second head))) + (tt (print-width (third head)))) + (when (> nn namelen) (setq namelen nn)) + (when (> ss succlen) (setq succlen ss)) + (when (> tt testlen) (setq testlen tt))) + (setq results (cdr results)))) + ;; create format and print + (let ((results (reverse test-harness-file-results-alist))) + (while results + (let* ((head (car results)) + (basename (file-name-nondirectory (first head))) + (nsucc (second head)) + (ntest (third head))) + (cond ((member (first head) unexpected-test-suite-failure-files) + (message test-harness-aborted-summary-template + (concat basename ":") + ntest)) + ((> ntest 0) + (message test-harness-file-summary-template + (concat basename ":") + nsucc + ntest + (/ (* 100 nsucc) ntest))) + (t + (message test-harness-null-summary-template + (concat basename ":")))) + (setq results (cdr results))))) + (when (> unexpected-test-suite-failures 0) + (message "\n***** There %s %d unexpected test suite %s in %s:" + (if (= unexpected-test-suite-failures 1) "was" "were") + unexpected-test-suite-failures + (if (= unexpected-test-suite-failures 1) "failure" "failures") + (if (= (length unexpected-test-suite-failure-files) 1) + "file" + "files")) + (while unexpected-test-suite-failure-files + (let ((line (pop unexpected-test-suite-failure-files))) + (while (and (< (length line) 61) + unexpected-test-suite-failure-files) + (setq line + (concat line " " + (pop unexpected-test-suite-failure-files)))) + (message line))))) + (message "\nDone") + (kill-emacs (if error 1 0)))) + +(provide 'test-harness) + +;;; test-harness.el ends here
--- a/man/ChangeLog Fri Feb 26 15:22:15 2010 +0000 +++ b/man/ChangeLog Fri Feb 26 15:24:58 2010 +0000 @@ -1,3 +1,8 @@ +2010-02-25 Didier Verna <didier@xemacs.org> + + The background-placement face property. + * xemacs/custom.texi (Faces): Document it. + 2010-02-20 Ben Wing <ben@xemacs.org> * internals/internals.texi (Intro to Window and Frame Geometry):
--- a/man/xemacs/custom.texi Fri Feb 26 15:22:15 2010 +0000 +++ b/man/xemacs/custom.texi Fri Feb 26 15:24:58 2010 +0000 @@ -2080,6 +2080,8 @@ Change the background pixmap of the given @var{face}. @item M-x set-face-background-pixmap-file A simpler version but with filename completion. +@item M-x set-face-background-placement +Change the placement of the background pixmap of the given @var{face}. @item M-x set-face-font Change the font of the given @var{face}. @item M-x set-face-foreground @@ -2161,6 +2163,18 @@ as much control on the pixmap instantiator, but provides filename completion. +@findex set-face-background-placement +You can set the placement of the background pixmap of the specified +@var{face} with the function @code{set-face-background-placement}. The +placement argument can be either @code{absolute} or @code{relative} (the +default). A @code{relative} placement means that the pixmap is attached +to the frame and moves with it. An @code{absolute} placement means that +the pixmap is rather attached to the frame's root window, so that when +you move the frame on the screen, it will appear to ``slide'' on the +pixmap. This placement mode can be used to achieve pseudo-translucency +for a frame, for example by setting the default face's background pixmap +to the root window's one. + @findex set-face-font You can set the font of the specified @var{face} with the function @code{set-face-font}. The @var{font} argument should be a string, the
--- a/src/.gdbinit.in.in Fri Feb 26 15:22:15 2010 +0000 +++ b/src/.gdbinit.in.in Fri Feb 26 15:24:58 2010 +0000 @@ -159,7 +159,7 @@ end define check-xemacs-arg - run -vanilla -batch -l @srcdir@/../tests/automated/test-harness.el -f batch-test-emacs @srcdir@/../tests/$arg0 + run -vanilla -batch -l test-harness -f batch-test-emacs @srcdir@/../tests/$arg0 end define check-xemacs @@ -178,7 +178,7 @@ define check-temacs-arg environment-to-run-temacs - run -nd -no-packages -batch -l @srcdir@/../lisp/loadup.el run-temacs -q -batch -l @srcdir@/../tests/automated/test-harness.el -f batch-test-emacs @srcdir@/../tests/$arg0 + run -nd -no-packages -batch -l @srcdir@/../lisp/loadup.el run-temacs -q -batch -l test-harness -f batch-test-emacs @srcdir@/../tests/$arg0 define check-temacs if $argc == 0
--- a/src/ChangeLog Fri Feb 26 15:22:15 2010 +0000 +++ b/src/ChangeLog Fri Feb 26 15:24:58 2010 +0000 @@ -1,3 +1,220 @@ +2010-02-25 Didier Verna <didier@xemacs.org> + + The background-placement face property. + * console-x-impl.h (struct x_frame): Add new slots x and y. + * console-x-impl.h (FRAME_X_X, FRAME_X_Y): New slot accessors. + * console-gtk-impl.h: Fake something similar for potential port. + * frame-x.c (x_get_frame_text_position): New function. + * frame-x.c (x_init_frame_3): Use it. + * event-Xt.c (emacs_Xt_handle_magic_event): Eat spurious + ConfigureNotify events, get the frame position and mark frame + faces changed. + * objects-impl.h: The face_background_placement_specifier + structure and its accessors. + * objects.c: New symbols Qabsolute and Qrelative. + * objects.c (face_background_placement_create): + * objects.c (face_background_placement_mark): + * objects.c (face_background_placement_instantiate): + * objects.c (face_background_placement_validate): + * objects.c (face_background_placement_after_change): + * objects.c (set_face_background_placement_attached_to): New. + * objects.h (set_face_background_palcement_attached_to): Declare + the one above. + * objects.c (syms_of_objects): + * objects.c (specifier_type_create_objects): + * objects.c (reinit_specifier_type_create_objects): + * objects.c (reinit_vars_of_objects): Update for the modifications + above. + * console-xlike-inc.h (XLIKE_GC_TS_X_ORIGIN, XLIKE_GC_TS_X_ORIGIN): + New X11/Gtk compatibility macros. + * redisplay-xlike-inc.c (XLIKE_get_gc): Add a background placement + argument and handle it. + * gtk-glue.c (face_to_gc): + * redisplay-xlike-inc.c (XLIKE_output_string): + * redisplay-xlike-inc.c (XLIKE_output_pixmap): + * redisplay-xlike-inc.c (XLIKE_output_blank): + * redisplay-xlike-inc.c (XLIKE_output_horizontal_line): + * redisplay-xlike-inc.c (XLIKE_output_eol_cursor): Update + accordingly. + * console-impl.h (struct console_methods): Add a background + placement (Lisp_Object) argument to the clear_region method. + * console-stream.c (stream_clear_region): + * redisplay-tty.c (tty_clear_region): + * redisplay-msw.c (mswindows_clear_region): + * redisplay-xlike-inc.c (XLIKE_clear_region): Update accordingly. + * redisplay-output.c (redisplay_clear_region): Handle the + background placement property and update the call to the + clear_region method. + * faces.h (struct Lisp_Face): + * faces.h (struct face_cachel): Add a background placement slot. + * faces.h (WINDOW_FACE_CACHEL_BACKGROUND_PLACEMENT): New accessor. + * faces.c (mark_face): + * faces.c (face_equal): + * faces.c (face_getprop): + * faces.c (face_putprop): + * faces.c (face_remprop): + * faces.c (face_plist): + * faces.c (reset_face): + * faces.c (mark_face_cachels): + * faces.c (update_face_cachel_data): + * faces.c (merge_face_cachel_data): + * faces.c (reset_face_cachel): + * faces.c (Fmake_face): + * faces.c (Fcopy_face): Handle the background placement property. + * faces.c (syms_of_faces): + * faces.c (vars_of_faces): + * faces.c (complex_vars_of_faces): Update accordingly. + +2010-02-25 Ben Wing <ben@xemacs.org> + + * frame-impl.h: + Create some new macros for more clearly getting the size/edges + of various rectangles surrounding the paned area. + * frame.c (change_frame_size_1): + Use the new macros. Clean up change_frame_size_1 and make sure + the internal border width gets taken into account -- that was what + was causing the clipped bottom and right. + +2010-02-25 Ben Wing <ben@xemacs.org> + + * EmacsFrame.c (EmacsFrameSetValues): + * frame-impl.h: + * frame-impl.h (struct frame): + * frame-impl.h (FRAME_THEORETICAL_TOP_TOOLBAR_HEIGHT): + * frame-impl.h (FRAME_THEORETICAL_TOP_TOOLBAR_BORDER_WIDTH): + * frame-impl.h (FRAME_REAL_TOP_TOOLBAR_HEIGHT): + * frame-impl.h (FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH): + * frame-impl.h (FRAME_REAL_TOP_TOOLBAR_VISIBLE): + * frame-impl.h (FRAME_REAL_TOP_TOOLBAR_BOUNDS): + * frame.h: + * frame.h (enum edge_pos): + * gutter.c: + * gutter.c (get_gutter_coords): + * gutter.c (display_boxes_in_gutter_p): + * gutter.c (construct_window_gutter_spec): + * gutter.c (calculate_gutter_size_from_display_lines): + * gutter.c (calculate_gutter_size): + * gutter.c (output_gutter): + * gutter.c (clear_gutter): + * gutter.c (mark_gutters): + * gutter.c (gutter_extent_signal_changed_region_maybe): + * gutter.c (update_gutter_geometry): + * gutter.c (update_frame_gutter_geometry): + * gutter.c (update_frame_gutters): + * gutter.c (reset_gutter_display_lines): + * gutter.c (redraw_exposed_gutter): + * gutter.c (redraw_exposed_gutters): + * gutter.c (free_frame_gutters): + * gutter.c (decode_gutter_position): + * gutter.c (Fset_default_gutter_position): + * gutter.c (Fgutter_pixel_width): + * gutter.c (Fgutter_pixel_height): + * gutter.c (recompute_overlaying_specifier): + * gutter.c (gutter_specs_changed_1): + * gutter.c (gutter_specs_changed): + * gutter.c (top_gutter_specs_changed): + * gutter.c (bottom_gutter_specs_changed): + * gutter.c (left_gutter_specs_changed): + * gutter.c (right_gutter_specs_changed): + * gutter.c (gutter_geometry_changed_in_window): + * gutter.c (init_frame_gutters): + * gutter.c (specifier_vars_of_gutter): + * gutter.h: + * gutter.h (WINDOW_REAL_TOP_GUTTER_BOUNDS): + * gutter.h (FRAME_TOP_GUTTER_BOUNDS): + * lisp.h (enum edge_style): + * native-gtk-toolbar.c: + * native-gtk-toolbar.c (gtk_output_toolbar): + * native-gtk-toolbar.c (gtk_clear_toolbar): + * native-gtk-toolbar.c (gtk_output_frame_toolbars): + * native-gtk-toolbar.c (gtk_initialize_frame_toolbars): + * toolbar-msw.c: + * toolbar-msw.c (TOOLBAR_HANDLE): + * toolbar-msw.c (allocate_toolbar_item_id): + * toolbar-msw.c (mswindows_clear_toolbar): + * toolbar-msw.c (mswindows_output_toolbar): + * toolbar-msw.c (mswindows_move_toolbar): + * toolbar-msw.c (mswindows_redraw_exposed_toolbars): + * toolbar-msw.c (mswindows_initialize_frame_toolbars): + * toolbar-msw.c (mswindows_output_frame_toolbars): + * toolbar-msw.c (mswindows_clear_frame_toolbars): + * toolbar-msw.c (DELETE_TOOLBAR): + * toolbar-msw.c (mswindows_free_frame_toolbars): + * toolbar-msw.c (mswindows_get_toolbar_button_text): + * toolbar-xlike.c: + * toolbar-xlike.c (__prepare_button_area): + * toolbar-xlike.c (XLIKE_OUTPUT_BUTTONS_LOOP): + * toolbar-xlike.c (xlike_output_toolbar): + * toolbar-xlike.c (xlike_clear_toolbar): + * toolbar-xlike.c (xlike_output_frame_toolbars): + * toolbar-xlike.c (xlike_clear_frame_toolbars): + * toolbar-xlike.c (xlike_redraw_exposed_toolbar): + * toolbar-xlike.c (xlike_redraw_exposed_toolbars): + * toolbar-xlike.c (xlike_redraw_frame_toolbars): + * toolbar.c: + * toolbar.c (decode_toolbar_position): + * toolbar.c (Fset_default_toolbar_position): + * toolbar.c (mark_frame_toolbar_buttons_dirty): + * toolbar.c (compute_frame_toolbar_buttons): + * toolbar.c (set_frame_toolbar): + * toolbar.c (compute_frame_toolbars_data): + * toolbar.c (update_frame_toolbars_geometry): + * toolbar.c (init_frame_toolbars): + * toolbar.c (get_toolbar_coords): + * toolbar.c (CHECK_TOOLBAR): + * toolbar.c (toolbar_buttons_at_pixpos): + * toolbar.c (CTB_ERROR): + * toolbar.c (recompute_overlaying_specifier): + * toolbar.c (specifier_vars_of_toolbar): + * toolbar.h: + * toolbar.h (SET_TOOLBAR_WAS_VISIBLE_FLAG): + Create new enum edge_pos with TOP_EDGE, BOTTOM_EDGE, LEFT_EDGE, + RIGHT_EDGE; subsume TOP_BORDER, TOP_GUTTER, enum toolbar_pos, + enum gutter_pos, etc. + + Create EDGE_POS_LOOP, subsuming GUTTER_POS_LOOP. + + Create NUM_EDGES, use in many places instead of hardcoded '4'. + + Instead of top_toolbar_was_visible, bottom_toolbar_was_visible, + etc. make an array toolbar_was_visible[NUM_EDGES]. This increases + the frame size by 15 bytes or so (could be 3 if we use Boolbytes) + but hardly seems w to matter -- frames are heavy weight objects + anyway. Same with top_gutter_was_visible, etc. + + Remove duplicated SET_TOOLBAR_WAS_VISIBLE_FLAG and put defn in + one place (toolbar.h). + +2010-02-24 Didier Verna <didier@xemacs.org> + + Modify XLIKE_get_gc's prototype. + * redisplay-xlike-inc.c (XLIKE_get_gc): Take a frame instead of a + device as first argument. + * redisplay-xlike-inc.c (XLIKE_output_string): Update caller. + * redisplay-xlike-inc.c (XLIKE_output_pixmap): Ditto. + * redisplay-xlike-inc.c (XLIKE_output_blank): Ditto. + * redisplay-xlike-inc.c (XLIKE_output_horizontal_line): Ditto. + * redisplay-xlike-inc.c (XLIKE_clear_region): Ditto. + * redisplay-xlike-inc.c (XLIKE_output_eol_cursor): Ditto. + * console-gtk.h (gtk_get_gc): Take a frame instead of a device as + first argument. + * gtk-glue.c (face_to_gc): Update caller. + +2010-02-24 Didier Verna <didier@xemacs.org> + + * glyphs.c: Clarify comment about potential_pixmap_file_instantiator. + * glyphs.c (xbm_mask_file_munging): Clarify comment, remove + unreachable condition and provide a cuple of assertions. + * glyphs.c (xbm_normalize): Clarify comments, error on mask file + not found. + * glyphs.c (xface_normalize): Ditto, and handle inline data properly. + +2010-02-22 Ben Wing <ben@xemacs.org> + + * .gdbinit.in.in: + * Makefile.in.in (batch_test_emacs): + test-harness.el is in lisp directory now so change how we call it. + 2010-02-22 Ben Wing <ben@xemacs.org> * alloc.c (object_memory_usage_stats):
--- a/src/EmacsFrame.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/EmacsFrame.c Fri Feb 26 15:24:58 2010 +0000 @@ -411,49 +411,49 @@ if (cur->emacs_frame.top_toolbar_height != new_->emacs_frame.top_toolbar_height) Fadd_spec_to_specifier - (Vtoolbar_size[TOP_TOOLBAR], + (Vtoolbar_size[TOP_EDGE], make_int (new_->emacs_frame.top_toolbar_height), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.bottom_toolbar_height != new_->emacs_frame.bottom_toolbar_height) Fadd_spec_to_specifier - (Vtoolbar_size[BOTTOM_TOOLBAR], + (Vtoolbar_size[BOTTOM_EDGE], make_int (new_->emacs_frame.bottom_toolbar_height), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.left_toolbar_width != new_->emacs_frame.left_toolbar_width) Fadd_spec_to_specifier - (Vtoolbar_size[LEFT_TOOLBAR], + (Vtoolbar_size[LEFT_EDGE], make_int (new_->emacs_frame.left_toolbar_width), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.right_toolbar_width != new_->emacs_frame.right_toolbar_width) Fadd_spec_to_specifier - (Vtoolbar_size[RIGHT_TOOLBAR], + (Vtoolbar_size[RIGHT_EDGE], make_int (new_->emacs_frame.right_toolbar_width), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.top_toolbar_border_width != new_->emacs_frame.top_toolbar_border_width) Fadd_spec_to_specifier - (Vtoolbar_border_width[TOP_TOOLBAR], + (Vtoolbar_border_width[TOP_EDGE], make_int (new_->emacs_frame.top_toolbar_border_width), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.bottom_toolbar_border_width != new_->emacs_frame.bottom_toolbar_border_width) Fadd_spec_to_specifier - (Vtoolbar_border_width[BOTTOM_TOOLBAR], + (Vtoolbar_border_width[BOTTOM_EDGE], make_int (new_->emacs_frame.bottom_toolbar_border_width), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.left_toolbar_border_width != new_->emacs_frame.left_toolbar_border_width) Fadd_spec_to_specifier - (Vtoolbar_border_width[LEFT_TOOLBAR], + (Vtoolbar_border_width[LEFT_EDGE], make_int (new_->emacs_frame.left_toolbar_border_width), wrap_frame (f), Qnil, Qnil); if (cur->emacs_frame.right_toolbar_border_width != new_->emacs_frame.right_toolbar_border_width) Fadd_spec_to_specifier - (Vtoolbar_border_width[RIGHT_TOOLBAR], + (Vtoolbar_border_width[RIGHT_EDGE], make_int (new_->emacs_frame.right_toolbar_border_width), wrap_frame (f), Qnil, Qnil); #endif /* HAVE_TOOLBARS */
--- a/src/Makefile.in.in Fri Feb 26 15:22:15 2010 +0000 +++ b/src/Makefile.in.in Fri Feb 26 15:24:58 2010 +0000 @@ -882,7 +882,7 @@ ###################### Automated tests testdir = $(SRC)/../tests/automated -batch_test_emacs = $(BATCH_PACKAGES) -l $(testdir)/test-harness.el -f batch-test-emacs $(testdir) +batch_test_emacs = $(BATCH_PACKAGES) -l test-harness -f batch-test-emacs $(testdir) ## `config-changed' is useful if you are building both Unicode-internal ## and old-Mule workspaces using --srcdir and don't run configure before
--- a/src/console-gtk-impl.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/console-gtk-impl.h Fri Feb 26 15:24:58 2010 +0000 @@ -159,6 +159,11 @@ /* The widget of the edit portion of this frame; this is a GtkDrawingArea, and the window of this widget is what the redisplay code draws on. */ GtkWidget *edit_widget; + /* #### WARNING: this does not currently work. -- dvl + Position of the edit widget above, for absolute background placement. + + int x, y; + */ /* Lists the widgets above the text area, in the proper order. */ GtkWidget *top_widgets[MAX_CONCURRENT_TOP_WIDGETS]; @@ -213,6 +218,10 @@ #define FRAME_GTK_DATA(f) FRAME_TYPE_DATA (f, gtk) +/* #### WARNING: this does not currently work. -- dvl + #define FRAME_GTK_X(f) (FRAME_GTK_DATA (f)->x) + #define FRAME_GTK_Y(f) (FRAME_GTK_DATA (f)->y) +*/ #define FRAME_GTK_SHELL_WIDGET(f) (FRAME_GTK_DATA (f)->widget) #define FRAME_GTK_CONTAINER_WIDGET(f) (FRAME_GTK_DATA (f)->container) #define FRAME_GTK_MENUBAR_WIDGET(f) (FRAME_GTK_DATA (f)->menubar_widget)
--- a/src/console-gtk.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/console-gtk.h Fri Feb 26 15:24:58 2010 +0000 @@ -64,7 +64,8 @@ int start_pixpos, int width, face_index findex, int cursor, int cursor_start, int cursor_width, int cursor_height); -GdkGC *gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg, +GdkGC *gtk_get_gc (struct frame *f, + Lisp_Object font, Lisp_Object fg, Lisp_Object bg, Lisp_Object bg_pmap, Lisp_Object lwidth); int gtk_initialize_frame_menubar (struct frame *f);
--- a/src/console-impl.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/console-impl.h Fri Feb 26 15:24:58 2010 +0000 @@ -153,9 +153,10 @@ int (*eol_cursor_width_method) (void); void (*output_vertical_divider_method) (struct window *, int); void (*clear_to_window_end_method) (struct window *, int, int); - void (*clear_region_method) (Lisp_Object, struct device*, struct frame*, face_index, - int, int, int, int, - Lisp_Object, Lisp_Object, Lisp_Object); + void (*clear_region_method) (Lisp_Object, struct device*, struct frame*, + face_index, int, int, int, int, + Lisp_Object, Lisp_Object, + Lisp_Object, Lisp_Object); void (*clear_frame_method) (struct frame *); void (*window_output_begin_method) (struct window *); void (*frame_output_begin_method) (struct frame *);
--- a/src/console-stream.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/console-stream.c Fri Feb 26 15:24:58 2010 +0000 @@ -282,7 +282,8 @@ int UNUSED (x), int UNUSED (y), int UNUSED (width), int UNUSED (height), Lisp_Object UNUSED (fcolor), Lisp_Object UNUSED (bcolor), - Lisp_Object UNUSED (background_pixmap)) + Lisp_Object UNUSED (background_pixmap), + Lisp_Object UNUSED (background_placement)) { ABORT (); }
--- a/src/console-x-impl.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/console-x-impl.h Fri Feb 26 15:24:58 2010 +0000 @@ -2,6 +2,7 @@ Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. Copyright (C) 1996, 2002, 2003 Ben Wing. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -265,6 +266,8 @@ /* The widget of the edit portion of this frame; this is an EmacsFrame, and the window of this widget is what the redisplay code draws on. */ Widget edit_widget; + /* Position of the edit widget above, for absolute background placement. */ + int x, y; /* Lists the widgets above the text area, in the proper order. Used by the EmacsManager. */ @@ -360,6 +363,8 @@ #endif /* NEW_GC */ #define FRAME_X_DATA(f) FRAME_TYPE_DATA (f, x) +#define FRAME_X_X(f) (FRAME_X_DATA (f)->x) +#define FRAME_X_Y(f) (FRAME_X_DATA (f)->y) #define FRAME_X_SHELL_WIDGET(f) (FRAME_X_DATA (f)->widget) #define FRAME_X_CONTAINER_WIDGET(f) (FRAME_X_DATA (f)->container) #define FRAME_X_MENUBAR_WIDGET(f) (FRAME_X_DATA (f)->menubar_widget) @@ -407,6 +412,8 @@ extern struct console_type *x_console_type; +void x_get_frame_text_position (struct frame *); + #endif /* HAVE_X_WINDOWS */ #endif /* INCLUDED_console_x_impl_h_ */
--- a/src/console-xlike-inc.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/console-xlike-inc.h Fri Feb 26 15:24:58 2010 +0000 @@ -169,6 +169,8 @@ #define XLIKE_GC_LINE_WIDTH GCLineWidth #define XLIKE_GC_STIPPLE GCStipple #define XLIKE_GC_TILE GCTile +#define XLIKE_GC_TS_X_ORIGIN GCTileStipXOrigin +#define XLIKE_GC_TS_Y_ORIGIN GCTileStipYOrigin #define XLIKE_GX_COPY GXcopy #define XLIKE_GX_XOR GXxor @@ -258,6 +260,8 @@ #define XLIKE_GC_LINE_WIDTH GDK_GC_LINE_WIDTH #define XLIKE_GC_STIPPLE GDK_GC_STIPPLE #define XLIKE_GC_TILE GDK_GC_TILE +#define XLIKE_GC_TS_X_ORIGIN GDK_GC_TS_X_ORIGIN +#define XLIKE_GC_TS_Y_ORIGIN GDK_GC_TS_Y_ORIGIN #define XLIKE_GX_COPY GDK_COPY #define XLIKE_GX_XOR GDK_XOR
--- a/src/event-Xt.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/event-Xt.c Fri Feb 26 15:24:58 2010 +0000 @@ -2,6 +2,7 @@ Copyright (C) 1991-5, 1997 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. Copyright (C) 1996, 2001, 2002, 2003, 2010 Ben Wing. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -1898,6 +1899,25 @@ break; case ConfigureNotify: + { + XEvent xev; + + /* Let's eat all events of that type to avoid useless + reconfigurations. */ + while (XCheckTypedWindowEvent + (DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE (f))), + XtWindow (FRAME_X_TEXT_WIDGET (f)), + ConfigureNotify, + &xev) + == True); + } + /* #### NOTE: in fact, the frame faces didn't really change, but if some + #### of them have their background-placement property set to + #### absolute, we need a redraw. This is semantically equivalent to + #### changing the background pixmap. -- dvl */ + x_get_frame_text_position (f); + MARK_FRAME_FACES_CHANGED (f); + #ifdef HAVE_XIM XIM_SetGeometry (f); #endif
--- a/src/faces.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/faces.c Fri Feb 26 15:24:58 2010 +0000 @@ -3,6 +3,7 @@ Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995, 1996, 2001, 2002, 2005, 2010 Ben Wing. Copyright (C) 1995 Sun Microsystems, Inc. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -42,7 +43,7 @@ Lisp_Object Qfacep; Lisp_Object Qforeground, Qbackground, Qdisplay_table; -Lisp_Object Qbackground_pixmap, Qunderline, Qdim; +Lisp_Object Qbackground_pixmap, Qbackground_placement, Qunderline, Qdim; Lisp_Object Qblinking, Qstrikethru; Lisp_Object Qinit_face_from_resources; @@ -111,6 +112,7 @@ mark_object (face->font); mark_object (face->display_table); mark_object (face->background_pixmap); + mark_object (face->background_placement); mark_object (face->underline); mark_object (face->strikethru); mark_object (face->highlight); @@ -162,6 +164,9 @@ internal_equal (f1->font, f2->font, depth) && internal_equal (f1->display_table, f2->display_table, depth) && internal_equal (f1->background_pixmap, f2->background_pixmap, depth) && + internal_equal (f1->background_placement, + f2->background_placement, + depth) && internal_equal (f1->underline, f2->underline, depth) && internal_equal (f1->strikethru, f2->strikethru, depth) && internal_equal (f1->highlight, f2->highlight, depth) && @@ -192,18 +197,19 @@ Lisp_Face *f = XFACE (obj); return - (EQ (prop, Qforeground) ? f->foreground : - EQ (prop, Qbackground) ? f->background : - EQ (prop, Qfont) ? f->font : - EQ (prop, Qdisplay_table) ? f->display_table : - EQ (prop, Qbackground_pixmap) ? f->background_pixmap : - EQ (prop, Qunderline) ? f->underline : - EQ (prop, Qstrikethru) ? f->strikethru : - EQ (prop, Qhighlight) ? f->highlight : - EQ (prop, Qdim) ? f->dim : - EQ (prop, Qblinking) ? f->blinking : - EQ (prop, Qreverse) ? f->reverse : - EQ (prop, Qdoc_string) ? f->doc_string : + (EQ (prop, Qforeground) ? f->foreground : + EQ (prop, Qbackground) ? f->background : + EQ (prop, Qfont) ? f->font : + EQ (prop, Qdisplay_table) ? f->display_table : + EQ (prop, Qbackground_pixmap) ? f->background_pixmap : + EQ (prop, Qbackground_placement) ? f->background_placement : + EQ (prop, Qunderline) ? f->underline : + EQ (prop, Qstrikethru) ? f->strikethru : + EQ (prop, Qhighlight) ? f->highlight : + EQ (prop, Qdim) ? f->dim : + EQ (prop, Qblinking) ? f->blinking : + EQ (prop, Qreverse) ? f->reverse : + EQ (prop, Qdoc_string) ? f->doc_string : external_plist_get (&f->plist, prop, 0, ERROR_ME)); } @@ -212,16 +218,17 @@ { Lisp_Face *f = XFACE (obj); - if (EQ (prop, Qforeground) || - EQ (prop, Qbackground) || - EQ (prop, Qfont) || - EQ (prop, Qdisplay_table) || - EQ (prop, Qbackground_pixmap) || - EQ (prop, Qunderline) || - EQ (prop, Qstrikethru) || - EQ (prop, Qhighlight) || - EQ (prop, Qdim) || - EQ (prop, Qblinking) || + if (EQ (prop, Qforeground) || + EQ (prop, Qbackground) || + EQ (prop, Qfont) || + EQ (prop, Qdisplay_table) || + EQ (prop, Qbackground_pixmap) || + EQ (prop, Qbackground_placement) || + EQ (prop, Qunderline) || + EQ (prop, Qstrikethru) || + EQ (prop, Qhighlight) || + EQ (prop, Qdim) || + EQ (prop, Qblinking) || EQ (prop, Qreverse)) return 0; @@ -242,16 +249,17 @@ { Lisp_Face *f = XFACE (obj); - if (EQ (prop, Qforeground) || - EQ (prop, Qbackground) || - EQ (prop, Qfont) || - EQ (prop, Qdisplay_table) || - EQ (prop, Qbackground_pixmap) || - EQ (prop, Qunderline) || - EQ (prop, Qstrikethru) || - EQ (prop, Qhighlight) || - EQ (prop, Qdim) || - EQ (prop, Qblinking) || + if (EQ (prop, Qforeground) || + EQ (prop, Qbackground) || + EQ (prop, Qfont) || + EQ (prop, Qdisplay_table) || + EQ (prop, Qbackground_pixmap) || + EQ (prop, Qbackground_placement) || + EQ (prop, Qunderline) || + EQ (prop, Qstrikethru) || + EQ (prop, Qhighlight) || + EQ (prop, Qdim) || + EQ (prop, Qblinking) || EQ (prop, Qreverse)) return -1; @@ -270,17 +278,18 @@ Lisp_Face *face = XFACE (obj); Lisp_Object result = face->plist; - result = cons3 (Qreverse, face->reverse, result); - result = cons3 (Qblinking, face->blinking, result); - result = cons3 (Qdim, face->dim, result); - result = cons3 (Qhighlight, face->highlight, result); - result = cons3 (Qstrikethru, face->strikethru, result); - result = cons3 (Qunderline, face->underline, result); - result = cons3 (Qbackground_pixmap, face->background_pixmap, result); - result = cons3 (Qdisplay_table, face->display_table, result); - result = cons3 (Qfont, face->font, result); - result = cons3 (Qbackground, face->background, result); - result = cons3 (Qforeground, face->foreground, result); + result = cons3 (Qreverse, face->reverse, result); + result = cons3 (Qblinking, face->blinking, result); + result = cons3 (Qdim, face->dim, result); + result = cons3 (Qhighlight, face->highlight, result); + result = cons3 (Qstrikethru, face->strikethru, result); + result = cons3 (Qunderline, face->underline, result); + result = cons3 (Qbackground_placement, face->background_placement, result); + result = cons3 (Qbackground_pixmap, face->background_pixmap, result); + result = cons3 (Qdisplay_table, face->display_table, result); + result = cons3 (Qfont, face->font, result); + result = cons3 (Qbackground, face->background, result); + result = cons3 (Qforeground, face->foreground, result); return result; } @@ -293,6 +302,7 @@ { XD_LISP_OBJECT, offsetof (Lisp_Face, font) }, { XD_LISP_OBJECT, offsetof (Lisp_Face, display_table) }, { XD_LISP_OBJECT, offsetof (Lisp_Face, background_pixmap) }, + { XD_LISP_OBJECT, offsetof (Lisp_Face, background_placement) }, { XD_LISP_OBJECT, offsetof (Lisp_Face, underline) }, { XD_LISP_OBJECT, offsetof (Lisp_Face, strikethru) }, { XD_LISP_OBJECT, offsetof (Lisp_Face, highlight) }, @@ -386,6 +396,7 @@ f->font = Qnil; f->display_table = Qnil; f->background_pixmap = Qnil; + f->background_placement = Qnil; f->underline = Qnil; f->strikethru = Qnil; f->highlight = Qnil; @@ -845,6 +856,8 @@ set_font_attached_to (f->font, face, Qfont); f->background_pixmap = Fmake_specifier (Qimage); set_image_attached_to (f->background_pixmap, face, Qbackground_pixmap); + f->background_placement = Fmake_specifier (Qface_background_placement); + set_face_background_placement_attached_to (f->background_placement, face); f->display_table = Fmake_specifier (Qdisplay_table); f->underline = Fmake_specifier (Qface_boolean); set_face_boolean_attached_to (f->underline, face, Qunderline); @@ -873,6 +886,9 @@ set_specifier_fallback (f->background_pixmap, Fget (Vdefault_face, Qbackground_pixmap, Qunbound)); + set_specifier_fallback (f->background_placement, + Fget (Vdefault_face, Qbackground_placement, + Qunbound)); set_specifier_fallback (f->display_table, Fget (Vdefault_face, Qdisplay_table, Qunbound)); set_specifier_fallback (f->underline, @@ -1067,6 +1083,7 @@ mark_object (cachel->background); mark_object (cachel->display_table); mark_object (cachel->background_pixmap); + mark_object (cachel->background_placement); } } @@ -1423,6 +1440,9 @@ FROB (background_pixmap); MAYBE_UNFROB_BACKGROUND_PIXMAP; } + + FROB (background_placement); + #undef FROB #undef MAYBE_UNFROB_BACKGROUND_PIXMAP @@ -1486,6 +1506,7 @@ FROB (background); FROB (display_table); FROB (background_pixmap); + FROB (background_placement); FROB (underline); FROB (strikethru); FROB (highlight); @@ -1536,6 +1557,7 @@ } cachel->display_table = Qunbound; cachel->background_pixmap = Qunbound; + cachel->background_placement = Qunbound; FACE_CACHEL_FONT_SPECIFIED (cachel)->size = sizeof(cachel->font_specified); FACE_CACHEL_FONT_UPDATED (cachel)->size = sizeof(cachel->font_updated); } @@ -1901,8 +1923,8 @@ /* If the locale could affect the frame value, then call update_EmacsFrames just in case. */ if (default_face && - (EQ (property, Qforeground) || - EQ (property, Qbackground) || + (EQ (property, Qforeground) || + EQ (property, Qbackground) || EQ (property, Qfont))) update_EmacsFrames (locale, property); @@ -1996,6 +2018,7 @@ COPY_PROPERTY (font); COPY_PROPERTY (display_table); COPY_PROPERTY (background_pixmap); + COPY_PROPERTY (background_placement); COPY_PROPERTY (underline); COPY_PROPERTY (strikethru); COPY_PROPERTY (highlight); @@ -2126,6 +2149,7 @@ /* Qfont defined in general.c */ DEFSYMBOL (Qdisplay_table); DEFSYMBOL (Qbackground_pixmap); + DEFSYMBOL (Qbackground_placement); DEFSYMBOL (Qunderline); DEFSYMBOL (Qstrikethru); /* Qhighlight, Qreverse defined in general.c */ @@ -2199,6 +2223,7 @@ syms[n++] = Qfont; syms[n++] = Qdisplay_table; syms[n++] = Qbackground_pixmap; + syms[n++] = Qbackground_placement; syms[n++] = Qunderline; syms[n++] = Qstrikethru; syms[n++] = Qhighlight; @@ -2517,6 +2542,9 @@ set_specifier_fallback (Fget (Vmodeline_face, Qbackground_pixmap, Qnil), Fget (Vgui_element_face, Qbackground_pixmap, Qunbound)); + set_specifier_fallback (Fget (Vmodeline_face, Qbackground_placement, Qnil), + Fget (Vgui_element_face, Qbackground_placement, + Qunbound)); /* toolbar is another gui element */ Vtoolbar_face = Fmake_face (Qtoolbar, @@ -2529,6 +2557,9 @@ set_specifier_fallback (Fget (Vtoolbar_face, Qbackground_pixmap, Qnil), Fget (Vgui_element_face, Qbackground_pixmap, Qunbound)); + set_specifier_fallback (Fget (Vtoolbar_face, Qbackground_placement, Qnil), + Fget (Vgui_element_face, Qbackground_placement, + Qunbound)); /* vertical divider is another gui element */ Vvertical_divider_face = Fmake_face (Qvertical_divider, @@ -2543,6 +2574,10 @@ Qunbound), Fget (Vgui_element_face, Qbackground_pixmap, Qunbound)); + set_specifier_fallback (Fget (Vvertical_divider_face, Qbackground_placement, + Qnil), + Fget (Vgui_element_face, Qbackground_placement, + Qunbound)); /* widget is another gui element */ Vwidget_face = Fmake_face (Qwidget,
--- a/src/faces.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/faces.h Fri Feb 26 15:24:58 2010 +0000 @@ -1,6 +1,7 @@ /* Face data structures. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995, 2002, 2010 Ben Wing + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -47,6 +48,7 @@ Lisp_Object display_table; Lisp_Object background_pixmap; + Lisp_Object background_placement; Lisp_Object underline; Lisp_Object strikethru; @@ -172,6 +174,7 @@ Lisp_Object display_table; Lisp_Object background_pixmap; + Lisp_Object background_placement; unsigned int underline :1; unsigned int strikethru :1; @@ -188,6 +191,7 @@ unsigned int background_specified :1; unsigned int display_table_specified :1; unsigned int background_pixmap_specified :1; + unsigned int background_placement_specified :1; unsigned int strikethru_specified :1; unsigned int underline_specified :1; @@ -340,6 +344,8 @@ (WINDOW_FACE_CACHEL (window, index)->display_table) #define WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP(window, index) \ (WINDOW_FACE_CACHEL (window, index)->background_pixmap) +#define WINDOW_FACE_CACHEL_BACKGROUND_PLACEMENT(window, index) \ + (WINDOW_FACE_CACHEL (window, index)->background_placement) #define WINDOW_FACE_CACHEL_DIRTY(window, index) \ (WINDOW_FACE_CACHEL (window, index)->dirty) #define WINDOW_FACE_CACHEL_UNDERLINE_P(window, index) \ @@ -396,6 +402,11 @@ FACE_PROPERTY_INSTANCE (face, Qdisplay_table, domain, 0, Qzero) #define FACE_BACKGROUND_PIXMAP(face, domain) \ FACE_PROPERTY_INSTANCE (face, Qbackground_pixmap, domain, 0, Qzero) + +extern Lisp_Object Qbackground_placement; +#define FACE_BACKGROUND_PLACEMENT(face, domain) \ + FACE_PROPERTY_INSTANCE (face, Qbackground_placement, domain, 0, Qzero) + #define FACE_UNDERLINE_P(face, domain) \ (!NILP (FACE_PROPERTY_INSTANCE (face, Qunderline, domain, 0, Qzero))) #define FACE_STRIKETHRU_P(face, domain) \
--- a/src/frame-impl.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/frame-impl.h Fri Feb 26 15:24:58 2010 +0000 @@ -100,17 +100,23 @@ /* Size of toolbars as seen by redisplay. This is used to determine whether to re-layout windows by a call to change_frame_size early in redisplay_frame. */ - int current_toolbar_size[4]; + int current_toolbar_size[NUM_EDGES]; #endif /* Size of gutters as seen by redisplay. This is used to determine whether to re-layout windows by a call to change_frame_size early in redisplay_frame. */ - int current_gutter_bounds[4]; + int current_gutter_bounds[NUM_EDGES]; + + /* Toolbar visibility */ + int toolbar_was_visible[NUM_EDGES]; + + /* gutter visibility */ + int gutter_was_visible[NUM_EDGES]; /* Dynamic arrays of display lines for gutters */ - display_line_dynarr *current_display_lines[4]; - display_line_dynarr *desired_display_lines[4]; + display_line_dynarr *current_display_lines[NUM_EDGES]; + display_line_dynarr *desired_display_lines[NUM_EDGES]; /* A structure of auxiliary data specific to the device type. For example, struct x_frame is for X window frames; defined in @@ -160,16 +166,6 @@ /* True if frame's root window can't be split. */ unsigned int no_split :1; - unsigned int top_toolbar_was_visible :1; - unsigned int bottom_toolbar_was_visible :1; - unsigned int left_toolbar_was_visible :1; - unsigned int right_toolbar_was_visible :1; - /* gutter visibility */ - unsigned int top_gutter_was_visible :1; - unsigned int bottom_gutter_was_visible :1; - unsigned int left_gutter_was_visible :1; - unsigned int right_gutter_was_visible :1; - /* redisplay flags */ unsigned int buffers_changed :1; unsigned int clip_changed :1; @@ -581,13 +577,13 @@ : 0) #define FRAME_THEORETICAL_TOP_TOOLBAR_HEIGHT(f) \ - FRAME_THEORETICAL_TOOLBAR_SIZE (f, TOP_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_SIZE (f, TOP_EDGE) #define FRAME_THEORETICAL_BOTTOM_TOOLBAR_HEIGHT(f) \ - FRAME_THEORETICAL_TOOLBAR_SIZE (f, BOTTOM_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_SIZE (f, BOTTOM_EDGE) #define FRAME_THEORETICAL_LEFT_TOOLBAR_WIDTH(f) \ - FRAME_THEORETICAL_TOOLBAR_SIZE (f, LEFT_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_SIZE (f, LEFT_EDGE) #define FRAME_THEORETICAL_RIGHT_TOOLBAR_WIDTH(f) \ - FRAME_THEORETICAL_TOOLBAR_SIZE (f, RIGHT_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_SIZE (f, RIGHT_EDGE) #define FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH(f, pos) \ (FRAME_RAW_THEORETICAL_TOOLBAR_VISIBLE (f, pos) \ @@ -595,13 +591,13 @@ : 0) #define FRAME_THEORETICAL_TOP_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, TOP_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, TOP_EDGE) #define FRAME_THEORETICAL_BOTTOM_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, BOTTOM_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, BOTTOM_EDGE) #define FRAME_THEORETICAL_LEFT_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, LEFT_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, LEFT_EDGE) #define FRAME_THEORETICAL_RIGHT_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, RIGHT_TOOLBAR) + FRAME_THEORETICAL_TOOLBAR_BORDER_WIDTH (f, RIGHT_EDGE) /* This returns the window-local value rather than the frame-local value; that tells you about what's actually visible rather than what should @@ -670,40 +666,40 @@ 2 * FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos)) #define FRAME_REAL_TOP_TOOLBAR_HEIGHT(f) \ - FRAME_REAL_TOOLBAR_SIZE (f, TOP_TOOLBAR) + FRAME_REAL_TOOLBAR_SIZE (f, TOP_EDGE) #define FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT(f) \ - FRAME_REAL_TOOLBAR_SIZE (f, BOTTOM_TOOLBAR) + FRAME_REAL_TOOLBAR_SIZE (f, BOTTOM_EDGE) #define FRAME_REAL_LEFT_TOOLBAR_WIDTH(f) \ - FRAME_REAL_TOOLBAR_SIZE (f, LEFT_TOOLBAR) + FRAME_REAL_TOOLBAR_SIZE (f, LEFT_EDGE) #define FRAME_REAL_RIGHT_TOOLBAR_WIDTH(f) \ - FRAME_REAL_TOOLBAR_SIZE (f, RIGHT_TOOLBAR) + FRAME_REAL_TOOLBAR_SIZE (f, RIGHT_EDGE) #define FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, TOP_TOOLBAR) + FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, TOP_EDGE) #define FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, BOTTOM_TOOLBAR) + FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, BOTTOM_EDGE) #define FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, LEFT_TOOLBAR) + FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, LEFT_EDGE) #define FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH(f) \ - FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, RIGHT_TOOLBAR) + FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, RIGHT_EDGE) #define FRAME_REAL_TOP_TOOLBAR_VISIBLE(f) \ - FRAME_REAL_TOOLBAR_VISIBLE (f, TOP_TOOLBAR) + FRAME_REAL_TOOLBAR_VISIBLE (f, TOP_EDGE) #define FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE(f) \ - FRAME_REAL_TOOLBAR_VISIBLE (f, BOTTOM_TOOLBAR) + FRAME_REAL_TOOLBAR_VISIBLE (f, BOTTOM_EDGE) #define FRAME_REAL_LEFT_TOOLBAR_VISIBLE(f) \ - FRAME_REAL_TOOLBAR_VISIBLE (f, LEFT_TOOLBAR) + FRAME_REAL_TOOLBAR_VISIBLE (f, LEFT_EDGE) #define FRAME_REAL_RIGHT_TOOLBAR_VISIBLE(f) \ - FRAME_REAL_TOOLBAR_VISIBLE (f, RIGHT_TOOLBAR) + FRAME_REAL_TOOLBAR_VISIBLE (f, RIGHT_EDGE) #define FRAME_REAL_TOP_TOOLBAR_BOUNDS(f) \ - FRAME_REAL_TOOLBAR_BOUNDS (f, TOP_TOOLBAR) + FRAME_REAL_TOOLBAR_BOUNDS (f, TOP_EDGE) #define FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS(f) \ - FRAME_REAL_TOOLBAR_BOUNDS (f, BOTTOM_TOOLBAR) + FRAME_REAL_TOOLBAR_BOUNDS (f, BOTTOM_EDGE) #define FRAME_REAL_LEFT_TOOLBAR_BOUNDS(f) \ - FRAME_REAL_TOOLBAR_BOUNDS (f, LEFT_TOOLBAR) + FRAME_REAL_TOOLBAR_BOUNDS (f, LEFT_EDGE) #define FRAME_REAL_RIGHT_TOOLBAR_BOUNDS(f) \ - FRAME_REAL_TOOLBAR_BOUNDS (f, RIGHT_TOOLBAR) + FRAME_REAL_TOOLBAR_BOUNDS (f, RIGHT_EDGE) /************************************************************************/ /* frame dimensions defined using toolbars and gutters */ @@ -731,4 +727,66 @@ #define FRAME_RIGHT_BORDER_END(f) \ (FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_BOUNDS (f)) + +/************************************************************************/ +/* frame dimensions defined using toolbars and gutters */ +/************************************************************************/ + +/* Bounds of the area framed by the toolbars is the client area -- + (0, 0) - (FRAME_PIXWIDTH, FRAME_PIXHEIGHT). */ + +/* Bounds of the area framed by the gutters -- inside of the toolbars, + outside of everything else. */ + +#define FRAME_GUTTER_TOP_EDGE(f) \ + FRAME_REAL_TOOLBAR_BOUNDS (f, TOP_EDGE) +#define FRAME_GUTTER_BOTTOM_EDGE(f) \ + (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOOLBAR_BOUNDS (f, BOTTOM_EDGE)) +#define FRAME_GUTTER_LEFT_EDGE(f) \ + FRAME_REAL_TOOLBAR_BOUNDS (f, LEFT_EDGE) +#define FRAME_GUTTER_RIGHT_EDGE(f) \ + (FRAME_PIXWIDTH (f) - FRAME_REAL_TOOLBAR_BOUNDS (f, RIGHT_EDGE)) + +/* Bounds of the area framed by the internal border width -- inside of the + toolbars and gutters. */ + +#define FRAME_INTERNAL_BORDER_TOP_EDGE(f) \ + (FRAME_GUTTER_TOP_EDGE (f) + FRAME_GUTTER_BOUNDS (f, TOP_EDGE)) +#define FRAME_INTERNAL_BORDER_BOTTOM_EDGE(f) \ + (FRAME_GUTTER_BOTTOM_EDGE (f) - FRAME_GUTTER_BOUNDS (f, BOTTOM_EDGE)) +#define FRAME_INTERNAL_BORDER_LEFT_EDGE(f) \ + (FRAME_GUTTER_LEFT_EDGE (f) + FRAME_GUTTER_BOUNDS (f, LEFT_EDGE)) +#define FRAME_INTERNAL_BORDER_RIGHT_EDGE(f) \ + (FRAME_GUTTER_RIGHT_EDGE (f) - FRAME_GUTTER_BOUNDS (f, RIGHT_EDGE)) + +/* These are the bounds of the paned area -- inside of the toolbars, + gutters, and internal border width. The paned area is the same as the + area occupied by windows, including the minibuffer. See long comment in + frame.c. */ + +#define FRAME_PANED_TOP_EDGE(f) \ + (FRAME_INTERNAL_BORDER_TOP_EDGE (f) + FRAME_INTERNAL_BORDER_HEIGHT (f)) +#define FRAME_PANED_BOTTOM_EDGE(f) \ + (FRAME_INTERNAL_BORDER_BOTTOM_EDGE (f) - FRAME_INTERNAL_BORDER_HEIGHT (f)) +#define FRAME_PANED_LEFT_EDGE(f) \ + (FRAME_INTERNAL_BORDER_LEFT_EDGE (f) + FRAME_INTERNAL_BORDER_WIDTH (f)) +#define FRAME_PANED_RIGHT_EDGE(f) \ + (FRAME_INTERNAL_BORDER_RIGHT_EDGE (f) - FRAME_INTERNAL_BORDER_WIDTH (f)) + +/* Thickness of non-paned area at edge of frame; + + FRAME_PANED_TOP_EDGE (f) == FRAME_NONPANED_SIZE (f, TOP_EDGE) + FRAME_PANED_LEFT_EDGE (f) == FRAME_NONPANED_SIZE (f, LEFT_EDGE) + FRAME_PANED_BOTTOM_EDGE (f) == + FRAME_PIXHEIGHT (f) - FRAME_NONPANED_SIZE (f, BOTTOM_EDGE) + FRAME_PANED_RIGHT_EDGE (f) == + FRAME_PIXWIDTH (f) - FRAME_NONPANED_SIZE (f, RIGHT_EDGE) + +*/ +#define FRAME_NONPANED_SIZE(f, pos) \ + (FRAME_REAL_TOOLBAR_BOUNDS (f, pos) + FRAME_GUTTER_BOUNDS (f, pos) + \ + FRAME_INTERNAL_BORDER_SIZE (f, pos)) + + + #endif /* INCLUDED_frame_impl_h_ */
--- a/src/frame-x.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/frame-x.c Fri Feb 26 15:24:58 2010 +0000 @@ -1,6 +1,7 @@ /* Functions for the X window system. Copyright (C) 1989, 1992-5, 1997 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 2001, 2002, 2004, 2010 Ben Wing. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -537,6 +538,23 @@ *y = xwa.y; } +void x_get_frame_text_position (struct frame *f) +{ + Display *dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE (f))); + Window window = XtWindow (FRAME_X_TEXT_WIDGET (f)); + Window root, child; + int x, y; + unsigned int width, height, border_width; + unsigned int depth; + + XGetGeometry (dpy, window, &root, &x, &y, &width, &height, &border_width, + &depth); + XTranslateCoordinates (dpy, window, root, 0, 0, &x, &y, &child); + + FRAME_X_X (f) = x; + FRAME_X_Y (f) = y; +} + #if 0 static void x_smash_bastardly_shell_position (Widget shell) @@ -2119,9 +2137,13 @@ static void x_init_frame_3 (struct frame *f) { - /* Pop up the frame. */ - + /* #### NOTE: This whole business of splitting frame initialization into + #### different functions is somewhat messy. The latest one seems a good + #### place to initialize the edit widget's position because we're sure + #### that the frame is now relalized. -- dvl */ + x_popup_frame (f); + x_get_frame_text_position (f); } static void
--- a/src/frame.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/frame.c Fri Feb 26 15:24:58 2010 +0000 @@ -3595,22 +3595,13 @@ /* We need to remove the boundaries of the paned area (see top of file) from the total-area pixel size, which is what we have now. - - #### We should also be subtracting the internal borders. */ + */ new_pixheight -= - (FRAME_REAL_TOP_TOOLBAR_BOUNDS (f) - + FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS (f) - + FRAME_TOP_GUTTER_BOUNDS (f) - + FRAME_BOTTOM_GUTTER_BOUNDS (f)); - + (FRAME_NONPANED_SIZE (f, TOP_EDGE) + FRAME_NONPANED_SIZE (f, BOTTOM_EDGE)); new_pixwidth -= - (FRAME_REAL_LEFT_TOOLBAR_BOUNDS (f) - + FRAME_REAL_RIGHT_TOOLBAR_BOUNDS (f) - + FRAME_LEFT_GUTTER_BOUNDS (f) - + FRAME_RIGHT_GUTTER_BOUNDS (f)); - - XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top - = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); + (FRAME_NONPANED_SIZE (f, LEFT_EDGE) + FRAME_NONPANED_SIZE (f, RIGHT_EDGE)); + + XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = FRAME_PANED_TOP_EDGE (f); if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f)) @@ -3636,8 +3627,7 @@ new_pixheight - minibuf_height, 0); XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top = - FRAME_TOP_BORDER_END (f) + - FRAME_TOP_GUTTER_BOUNDS (f) + + FRAME_PANED_TOP_EDGE (f) + FRAME_BOTTOM_GUTTER_BOUNDS (f) + new_pixheight - minibuf_height; @@ -3651,14 +3641,13 @@ if (FRAME_TTY_P (f)) f->pixheight = newheight; - XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = - FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f); + XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = FRAME_PANED_LEFT_EDGE (f); set_window_pixwidth (FRAME_ROOT_WINDOW (f), new_pixwidth, 0); if (FRAME_HAS_MINIBUF_P (f)) { XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_left = - FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f); + FRAME_PANED_LEFT_EDGE (f); set_window_pixwidth (FRAME_MINIBUF_WINDOW (f), new_pixwidth, 0); } @@ -3666,10 +3655,10 @@ if (FRAME_TTY_P (f)) f->pixwidth = newwidth; - /* #### On MS Windows, this references FRAME_PIXWIDTH() and FRAME_PIXHEIGHT(). - I'm not sure we can count on those values being set. Instead we should - use the total pixel size we got near the top by calling - frame_conversion_internal(). We should inline the logic in + /* #### On MS Windows, this references FRAME_PIXWIDTH() and + FRAME_PIXHEIGHT(). I'm not sure we can count on those values being + set. Instead we should use the total pixel size we got near the top + by calling frame_conversion_internal(). We should inline the logic in get_frame_char_size() here and change that function so it just looks at FRAME_CHARWIDTH() and FRAME_CHARHEIGHT(). */ get_frame_char_size (f, &FRAME_CHARWIDTH (f), &FRAME_CHARHEIGHT (f));
--- a/src/frame.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/frame.h Fri Feb 26 15:24:58 2010 +0000 @@ -161,4 +161,18 @@ void init_frame (void); +enum edge_pos +{ + TOP_EDGE, + BOTTOM_EDGE, + LEFT_EDGE, + RIGHT_EDGE, + NUM_EDGES +}; + +/* Iterate over all possible edge positions */ +#define EDGE_POS_LOOP(var) \ + for (var = (enum edge_pos) 0; var < NUM_EDGES; \ + var = (enum edge_pos) (var + 1)) + #endif /* INCLUDED_frame_h_ */
--- a/src/glyphs.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/glyphs.c Fri Feb 26 15:24:58 2010 +0000 @@ -4,7 +4,7 @@ Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004, 2005 Ben Wing Copyright (C) 1995 Sun Microsystems Copyright (C) 1998, 1999, 2000 Andy Piper - Copyright (C) 2007 Didier Verna + Copyright (C) 2007, 2010 Didier Verna This file is part of XEmacs. @@ -2521,15 +2521,16 @@ /* pixmap file functions */ /************************************************************************/ -/* If INSTANTIATOR refers to inline data, return Qt. - If INSTANTIATOR refers to data in a file, return the full filename - if it exists, Qnil if there's no console method for locating the file, or - (filename) if there was an error locating the file. +/* - If INSTANTIATOR refers to inline data, or there is no file keyword, we + have nothing to do, so return Qt. + - If INSTANTIATOR refers to data in a file, return the full filename + if it exists; otherwise, return '(filename), meaning "file not found". + - If there is no locate_pixmap_file method for this console, return Qnil. FILE_KEYWORD and DATA_KEYWORD are symbols specifying the keywords used to look up the file and inline data, - respectively, in the instantiator. Normally these would - be Q_file and Q_data, but might be different for mask data. */ + respectively, in the instantiator. These would be Q_file and Q_data, + Q_mask_file or Q_mask_data. */ Lisp_Object potential_pixmap_file_instantiator (Lisp_Object instantiator, @@ -2736,18 +2737,20 @@ return Qnil; /* not reached */ } +/* This function attempts to find implicit mask files by appending "Mask" or + "msk" to the original bitmap file name. This is more or less standard: a + number of bitmaps in /usr/include/X11/bitmaps use it. */ Lisp_Object xbm_mask_file_munging (Lisp_Object alist, Lisp_Object file, Lisp_Object mask_file, Lisp_Object console_type) { - /* This is unclean but it's fairly standard -- a number of the - bitmaps in /usr/include/X11/bitmaps use it -- so we support - it. */ - if (EQ (mask_file, Qt) - /* don't override explicitly specified mask data. */ - && NILP (assq_no_quit (Q_mask_data, alist)) - && !EQ (file, Qt)) + /* Let's try to find an implicit mask file if we have neither an explicit + mask file name, nor inline mask data. Note that no errors are reported in + case of failure because the mask file we're looking for might not + exist. */ + if (EQ (mask_file, Qt) && NILP (assq_no_quit (Q_mask_data, alist))) { + assert (!EQ (file, Qt) && !EQ (file, Qnil)); mask_file = MAYBE_LISP_CONTYPE_METH (decode_console_type(console_type, ERROR_ME), locate_pixmap_file, (concat2 (file, build_ascstring ("Mask")))); @@ -2757,10 +2760,14 @@ locate_pixmap_file, (concat2 (file, build_ascstring ("msk")))); } + /* We got a mask file, either explicitely or from the search above. */ if (!NILP (mask_file)) { - Lisp_Object mask_data = - bitmap_to_lisp_data (mask_file, 0, 0, 0); + Lisp_Object mask_data; + + assert (!EQ (mask_file, Qt)); + + mask_data = bitmap_to_lisp_data (mask_file, 0, 0, 0); alist = remassq_no_quit (Q_mask_file, alist); /* there can't be a :mask-data at this point. */ alist = Fcons (Fcons (Q_mask_file, mask_file), @@ -2776,9 +2783,8 @@ xbm_normalize (Lisp_Object inst, Lisp_Object console_type, Lisp_Object UNUSED (dest_mask)) { - Lisp_Object file = Qnil, mask_file = Qnil; + Lisp_Object file = Qnil, mask_file = Qnil, alist = Qnil; struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object alist = Qnil; GCPRO3 (file, mask_file, alist); @@ -2796,7 +2802,9 @@ mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file, Q_mask_data, console_type); - if (NILP (file)) /* normalization impossible for the console type */ + /* No locate_pixmap_file method for this console type, so we can't get a + file (neither a mask file BTW). */ + if (NILP (file)) RETURN_UNGCPRO (Qnil); if (CONSP (file)) /* failure locating filename */ @@ -2804,6 +2812,11 @@ "no such file or directory", Fcar (file)); + if (CONSP (mask_file)) /* failure locating filename */ + signal_double_image_error ("Opening bitmap mask file", + "no such file or directory", + Fcar (mask_file)); + if (EQ (file, Qt) && EQ (mask_file, Qt)) /* no conversion necessary */ RETURN_UNGCPRO (inst); @@ -2863,10 +2876,8 @@ xface_normalize (Lisp_Object inst, Lisp_Object console_type, Lisp_Object UNUSED (dest_mask)) { - /* This function can call lisp */ - Lisp_Object file = Qnil, mask_file = Qnil; + Lisp_Object file = Qnil, mask_file = Qnil, alist = Qnil; struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object alist = Qnil; GCPRO3 (file, mask_file, alist); @@ -2884,28 +2895,34 @@ mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file, Q_mask_data, console_type); - if (NILP (file)) /* normalization impossible for the console type */ + /* No locate_pixmap_file method for this console type, so we can't get a + file (neither a mask file BTW). */ + if (NILP (file)) RETURN_UNGCPRO (Qnil); if (CONSP (file)) /* failure locating filename */ - signal_double_image_error ("Opening bitmap file", + signal_double_image_error ("Opening face file", "no such file or directory", Fcar (file)); + if (CONSP (mask_file)) /* failure locating filename */ + signal_double_image_error ("Opening face mask file", + "no such file or directory", + Fcar (mask_file)); + if (EQ (file, Qt) && EQ (mask_file, Qt)) /* no conversion necessary */ RETURN_UNGCPRO (inst); alist = tagged_vector_to_alist (inst); - { - /* #### FIXME: what if EQ (file, Qt) && !EQ (mask, Qt) ? Is that possible? - If so, we have a problem... -- dvl */ - Lisp_Object data = make_string_from_file (file); - alist = remassq_no_quit (Q_file, alist); - /* there can't be a :data at this point. */ - alist = Fcons (Fcons (Q_file, file), - Fcons (Fcons (Q_data, data), alist)); - } + if (!EQ (file, Qt)) + { + Lisp_Object data = make_string_from_file (file); + alist = remassq_no_quit (Q_file, alist); + /* there can't be a :data at this point. */ + alist = Fcons (Fcons (Q_file, file), + Fcons (Fcons (Q_data, data), alist)); + } alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
--- a/src/gtk-glue.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/gtk-glue.c Fri Feb 26 15:24:58 2010 +0000 @@ -208,17 +208,21 @@ static GdkGC * face_to_gc (Lisp_Object face) { - Lisp_Object device = Fselected_device (Qnil); + Lisp_Object frame = Fselected_frame (Qnil); - return (gtk_get_gc (XDEVICE (device), + return (gtk_get_gc (XFRAME (frame), Fspecifier_instance (Fget (face, Qfont, Qnil), - device, Qnil, Qnil), + frame, Qnil, Qnil), Fspecifier_instance (Fget (face, Qforeground, Qnil), - device, Qnil, Qnil), + frame, Qnil, Qnil), Fspecifier_instance (Fget (face, Qbackground, Qnil), - device, Qnil, Qnil), + frame, Qnil, Qnil), Fspecifier_instance (Fget (face, Qbackground_pixmap, - Qnil), device, Qnil, Qnil), + Qnil), + frame, Qnil, Qnil), + Fspecifier_instance (Fget (face, Qbackground_placement, + Qnil), + frame, Qnil, Qnil), Qnil)); }
--- a/src/gutter.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/gutter.c Fri Feb 26 15:24:58 2010 +0000 @@ -36,10 +36,10 @@ #include "window.h" #include "gutter.h" -Lisp_Object Vgutter[4]; -Lisp_Object Vgutter_size[4]; -Lisp_Object Vgutter_visible_p[4]; -Lisp_Object Vgutter_border_width[4]; +Lisp_Object Vgutter[NUM_EDGES]; +Lisp_Object Vgutter_size[NUM_EDGES]; +Lisp_Object Vgutter_visible_p[NUM_EDGES]; +Lisp_Object Vgutter_border_width[NUM_EDGES]; Lisp_Object Vdefault_gutter, Vdefault_gutter_visible_p; Lisp_Object Vdefault_gutter_width, Vdefault_gutter_height; @@ -52,46 +52,7 @@ Lisp_Object Qdefault_gutter_position_changed_hook; static void -update_gutter_geometry (struct frame *f, enum gutter_pos pos); - -#define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ - do { \ - switch (pos) \ - { \ - case TOP_GUTTER: \ - (frame)->top_gutter_was_visible = flag; \ - break; \ - case BOTTOM_GUTTER: \ - (frame)->bottom_gutter_was_visible = flag; \ - break; \ - case LEFT_GUTTER: \ - (frame)->left_gutter_was_visible = flag; \ - break; \ - case RIGHT_GUTTER: \ - (frame)->right_gutter_was_visible = flag; \ - break; \ - default: \ - ABORT (); \ - } \ - } while (0) - -static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) -{ - switch (pos) - { - case TOP_GUTTER: - return frame->top_gutter_was_visible; - case BOTTOM_GUTTER: - return frame->bottom_gutter_was_visible; - case LEFT_GUTTER: - return frame->left_gutter_was_visible; - case RIGHT_GUTTER: - return frame->right_gutter_was_visible; - default: - ABORT (); - return 0; /* To keep the compiler happy */ - } -} +update_gutter_geometry (struct frame *f, enum edge_pos pos); #if 0 static Lisp_Object @@ -172,7 +133,7 @@ if it is not the window nearest the gutter. Instead we predetermine the nearest window and then use that.*/ static void -get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, +get_gutter_coords (struct frame *f, enum edge_pos pos, int *x, int *y, int *width, int *height) { struct window @@ -181,7 +142,7 @@ right. */ switch (pos) { - case TOP_GUTTER: + case TOP_EDGE: *x = FRAME_LEFT_BORDER_END (f); *y = FRAME_TOP_BORDER_END (f); *width = FRAME_RIGHT_BORDER_START (f) @@ -189,7 +150,7 @@ *height = FRAME_TOP_GUTTER_BOUNDS (f); break; - case BOTTOM_GUTTER: + case BOTTOM_EDGE: *x = FRAME_LEFT_BORDER_END (f); *y = WINDOW_BOTTOM (bot); *width = FRAME_RIGHT_BORDER_START (f) @@ -197,7 +158,7 @@ *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); break; - case LEFT_GUTTER: + case LEFT_EDGE: *x = FRAME_LEFT_BORDER_END (f); *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); *width = FRAME_LEFT_GUTTER_BOUNDS (f); @@ -205,7 +166,7 @@ - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); break; - case RIGHT_GUTTER: + case RIGHT_EDGE: *x = FRAME_RIGHT_BORDER_START (f) - FRAME_RIGHT_GUTTER_BOUNDS (f); *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); @@ -230,8 +191,8 @@ int display_boxes_in_gutter_p (struct frame *f, struct display_box* db, struct display_glyph_area* dga) { - enum gutter_pos pos; - GUTTER_POS_LOOP (pos) + enum edge_pos pos; + EDGE_POS_LOOP (pos) { if (FRAME_GUTTER_VISIBLE (f, pos)) { @@ -257,7 +218,7 @@ /* Convert the gutter specifier into something we can actually display. */ static Lisp_Object construct_window_gutter_spec (struct window* w, - enum gutter_pos pos) + enum edge_pos pos) { Lisp_Object rest, *args; int nargs = 0; @@ -289,14 +250,14 @@ what height will accommodate all lines. This is useless on left and right gutters as we always have a maximal number of lines. */ static int -calculate_gutter_size_from_display_lines (enum gutter_pos pos, +calculate_gutter_size_from_display_lines (enum edge_pos pos, display_line_dynarr* ddla) { int size = 0; struct display_line *dl; /* For top and bottom the calculation is easy. */ - if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER) + if (pos == TOP_EDGE || pos == BOTTOM_EDGE) { /* grab coordinates of last line */ if (Dynarr_length (ddla)) @@ -333,7 +294,7 @@ } static Lisp_Object -calculate_gutter_size (struct window *w, enum gutter_pos pos) +calculate_gutter_size (struct window *w, enum edge_pos pos) { struct frame* f = XFRAME (WINDOW_FRAME (w)); display_line_dynarr *ddla; @@ -379,7 +340,7 @@ } static void -output_gutter (struct frame *f, enum gutter_pos pos, int force) +output_gutter (struct frame *f, enum edge_pos pos, int force) { Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); struct device *d = XDEVICE (f->device); @@ -426,9 +387,9 @@ { #ifdef DEBUG_GUTTERS stderr_out ("gutter redisplay [%s %dx%d@%d+%d] triggered by %s,\n", - pos == TOP_GUTTER ? "TOP" : - pos == BOTTOM_GUTTER ? "BOTTOM" : - pos == LEFT_GUTTER ? "LEFT" : "RIGHT", + pos == TOP_EDGE ? "TOP" : + pos == BOTTOM_EDGE ? "BOTTOM" : + pos == LEFT_EDGE ? "LEFT" : "RIGHT", width, height, x, y, force ? "force" : f->faces_changed ? "f->faces_changed" : f->frame_changed ? "f->frame_changed" : @@ -512,7 +473,7 @@ } static void -clear_gutter (struct frame *f, enum gutter_pos pos) +clear_gutter (struct frame *f, enum edge_pos pos) { int x, y, width, height; Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); @@ -520,7 +481,7 @@ Vwidget_face); get_gutter_coords (f, pos, &x, &y, &width, &height); - SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); + f->gutter_was_visible[pos] = 0; redisplay_clear_region (window, findex, x, y, width, height); } @@ -537,8 +498,8 @@ void mark_gutters (struct frame *f) { - enum gutter_pos pos; - GUTTER_POS_LOOP (pos) + enum edge_pos pos; + EDGE_POS_LOOP (pos) { if (f->current_display_lines[pos]) mark_redisplay_structs (f->current_display_lines[pos]); @@ -564,11 +525,11 @@ FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) { struct frame *f = XFRAME (XCAR (frmcons)); - enum gutter_pos pos; + enum edge_pos pos; Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); struct window* w = XWINDOW (window); - GUTTER_POS_LOOP (pos) + EDGE_POS_LOOP (pos) { if (EQ (WINDOW_GUTTER (w, pos), obj)) { @@ -581,7 +542,7 @@ /* We have to change the gutter geometry separately to the gutter update since it needs to occur outside of redisplay proper. */ static void -update_gutter_geometry (struct frame *f, enum gutter_pos pos) +update_gutter_geometry (struct frame *f, enum edge_pos pos) { /* If the gutter geometry has changed then re-layout the frame. If we are in display there is almost no point in doing @@ -607,13 +568,13 @@ || f->frame_layout_changed || f->windows_structure_changed) { - enum gutter_pos pos; + enum edge_pos pos; /* If the gutter geometry has changed then re-layout the frame. If we are in display there is almost no point in doing anything else since the frame size changes will be delayed until we are out of redisplay proper. */ - GUTTER_POS_LOOP (pos) + EDGE_POS_LOOP (pos) { update_gutter_geometry (f, pos); } @@ -629,7 +590,7 @@ f->windows_changed || f->windows_structure_changed || f->extents_changed || f->frame_layout_changed) { - enum gutter_pos pos; + enum edge_pos pos; /* We don't actually care about these when outputting the gutter so locally disable them. */ @@ -639,12 +600,12 @@ f->buffers_changed = 0; /* and output */ - GUTTER_POS_LOOP (pos) + EDGE_POS_LOOP (pos) { if (FRAME_GUTTER_VISIBLE (f, pos)) output_gutter (f, pos, 0); - else if (gutter_was_visible (f, pos)) + else if (f->gutter_was_visible[pos]) clear_gutter (f, pos); } @@ -657,8 +618,8 @@ void reset_gutter_display_lines (struct frame* f) { - enum gutter_pos pos; - GUTTER_POS_LOOP (pos) + enum edge_pos pos; + EDGE_POS_LOOP (pos) { if (f->current_display_lines[pos]) Dynarr_reset (f->current_display_lines[pos]); @@ -666,7 +627,7 @@ } static void -redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, +redraw_exposed_gutter (struct frame *f, enum edge_pos pos, int x, int y, int width, int height) { int g_x, g_y, g_width, g_height; @@ -697,10 +658,10 @@ redraw_exposed_gutters (struct frame *f, int x, int y, int width, int height) { - enum gutter_pos pos; + enum edge_pos pos; /* We are already inside the critical section -- our caller did that. */ - GUTTER_POS_LOOP (pos) + EDGE_POS_LOOP (pos) { if (FRAME_GUTTER_VISIBLE (f, pos)) redraw_exposed_gutter (f, pos, x, y, width, height); @@ -710,8 +671,8 @@ void free_frame_gutters (struct frame *f) { - enum gutter_pos pos; - GUTTER_POS_LOOP (pos) + enum edge_pos pos; + EDGE_POS_LOOP (pos) { if (f->current_display_lines[pos]) { @@ -726,16 +687,16 @@ } } -static enum gutter_pos +static enum edge_pos decode_gutter_position (Lisp_Object position) { - if (EQ (position, Qtop)) return TOP_GUTTER; - if (EQ (position, Qbottom)) return BOTTOM_GUTTER; - if (EQ (position, Qleft)) return LEFT_GUTTER; - if (EQ (position, Qright)) return RIGHT_GUTTER; + if (EQ (position, Qtop)) return TOP_EDGE; + if (EQ (position, Qbottom)) return BOTTOM_EDGE; + if (EQ (position, Qleft)) return LEFT_EDGE; + if (EQ (position, Qright)) return RIGHT_EDGE; invalid_constant ("Invalid gutter position", position); - RETURN_NOT_REACHED (TOP_GUTTER); + RETURN_NOT_REACHED (TOP_EDGE); } DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /* @@ -745,8 +706,8 @@ */ (position)) { - enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position); - enum gutter_pos new_ = decode_gutter_position (position); + enum edge_pos cur = decode_gutter_position (Vdefault_gutter_position); + enum edge_pos new_ = decode_gutter_position (position); if (cur != new_) { @@ -760,7 +721,7 @@ set_specifier_fallback (Vgutter[new_], Vdefault_gutter); set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero))); set_specifier_fallback (Vgutter_size[new_], - new_ == TOP_GUTTER || new_ == BOTTOM_GUTTER + new_ == TOP_EDGE || new_ == BOTTOM_EDGE ? Vdefault_gutter_height : Vdefault_gutter_width); set_specifier_fallback (Vgutter_border_width[cur], @@ -797,7 +758,7 @@ (pos, locale)) { int x, y, width, height; - enum gutter_pos p = TOP_GUTTER; + enum edge_pos p = TOP_EDGE; struct frame *f = decode_frame (FW_FRAME (locale)); if (NILP (pos)) @@ -818,7 +779,7 @@ (pos, locale)) { int x, y, width, height; - enum gutter_pos p = TOP_GUTTER; + enum edge_pos p = TOP_EDGE; struct frame *f = decode_frame (FW_FRAME (locale)); if (NILP (pos)) @@ -880,26 +841,26 @@ specifier caching changes */ static void -recompute_overlaying_specifier (Lisp_Object real_one[4]) +recompute_overlaying_specifier (Lisp_Object real_one[NUM_EDGES]) { - enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position); + enum edge_pos pos = decode_gutter_position (Vdefault_gutter_position); Fset_specifier_dirty_flag (real_one[pos]); } static void gutter_specs_changed (Lisp_Object specifier, struct window *w, - Lisp_Object oldval, enum gutter_pos pos); + Lisp_Object oldval, enum edge_pos pos); static void gutter_specs_changed_1 (Lisp_Object arg) { gutter_specs_changed (X1ST (arg), XWINDOW (X2ND (arg)), - X3RD (arg), (enum gutter_pos) XINT (X4TH (arg))); + X3RD (arg), (enum edge_pos) XINT (X4TH (arg))); free_list (arg); } static void gutter_specs_changed (Lisp_Object specifier, struct window *w, - Lisp_Object oldval, enum gutter_pos pos) + Lisp_Object oldval, enum edge_pos pos) { if (in_display) register_post_redisplay_action (gutter_specs_changed_1, @@ -926,28 +887,28 @@ top_gutter_specs_changed (Lisp_Object specifier, struct window *w, Lisp_Object oldval) { - gutter_specs_changed (specifier, w, oldval, TOP_GUTTER); + gutter_specs_changed (specifier, w, oldval, TOP_EDGE); } static void bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w, Lisp_Object oldval) { - gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER); + gutter_specs_changed (specifier, w, oldval, BOTTOM_EDGE); } static void left_gutter_specs_changed (Lisp_Object specifier, struct window *w, Lisp_Object oldval) { - gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER); + gutter_specs_changed (specifier, w, oldval, LEFT_EDGE); } static void right_gutter_specs_changed (Lisp_Object specifier, struct window *w, Lisp_Object oldval) { - gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER); + gutter_specs_changed (specifier, w, oldval, RIGHT_EDGE); } static void @@ -980,8 +941,8 @@ oldval)); else { - enum gutter_pos pos; - GUTTER_POS_LOOP (pos) + enum edge_pos pos; + EDGE_POS_LOOP (pos) { w->real_gutter_size[pos] = w->gutter_size[pos]; if (EQ (w->real_gutter_size[pos], Qautodetect) @@ -1152,12 +1113,12 @@ void init_frame_gutters (struct frame *f) { - enum gutter_pos pos; + enum edge_pos pos; struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); /* We are here as far in frame creation so cached specifiers are already recomputed, and possibly modified by resource initialization. We need to recalculate autodetected gutters. */ - GUTTER_POS_LOOP (pos) + EDGE_POS_LOOP (pos) { w->real_gutter[pos] = construct_window_gutter_spec (w, pos); w->real_gutter_size[pos] = w->gutter_size[pos]; @@ -1171,7 +1132,7 @@ } /* Keep a record of the current sizes of things. */ - GUTTER_POS_LOOP (pos) + EDGE_POS_LOOP (pos) { f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); } @@ -1279,19 +1240,19 @@ 0, 0, 1); DEFVAR_SPECIFIER ("top-gutter", - &Vgutter[TOP_GUTTER] /* + &Vgutter[TOP_EDGE] /* Specifier for the gutter at the top of the frame. Use `set-specifier' to change this. See `default-gutter' for a description of a valid gutter instantiator. */ ); - Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); - set_specifier_caching (Vgutter[TOP_GUTTER], - offsetof (struct window, gutter[TOP_GUTTER]), + Vgutter[TOP_EDGE] = Fmake_specifier (Qgutter); + set_specifier_caching (Vgutter[TOP_EDGE], + offsetof (struct window, gutter[TOP_EDGE]), top_gutter_specs_changed, 0, 0, 1); DEFVAR_SPECIFIER ("bottom-gutter", - &Vgutter[BOTTOM_GUTTER] /* + &Vgutter[BOTTOM_EDGE] /* Specifier for the gutter at the bottom of the frame. Use `set-specifier' to change this. See `default-gutter' for a description of a valid gutter instantiator. @@ -1301,14 +1262,14 @@ `bottom-gutter-height') is 0; thus, a bottom gutter will not be displayed even if you provide a value for `bottom-gutter'. */ ); - Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); - set_specifier_caching (Vgutter[BOTTOM_GUTTER], - offsetof (struct window, gutter[BOTTOM_GUTTER]), + Vgutter[BOTTOM_EDGE] = Fmake_specifier (Qgutter); + set_specifier_caching (Vgutter[BOTTOM_EDGE], + offsetof (struct window, gutter[BOTTOM_EDGE]), bottom_gutter_specs_changed, 0, 0, 1); DEFVAR_SPECIFIER ("left-gutter", - &Vgutter[LEFT_GUTTER] /* + &Vgutter[LEFT_EDGE] /* Specifier for the gutter at the left edge of the frame. Use `set-specifier' to change this. See `default-gutter' for a description of a valid gutter instantiator. @@ -1318,14 +1279,14 @@ `left-gutter-width') is 0; thus, a left gutter will not be displayed even if you provide a value for `left-gutter'. */ ); - Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); - set_specifier_caching (Vgutter[LEFT_GUTTER], - offsetof (struct window, gutter[LEFT_GUTTER]), + Vgutter[LEFT_EDGE] = Fmake_specifier (Qgutter); + set_specifier_caching (Vgutter[LEFT_EDGE], + offsetof (struct window, gutter[LEFT_EDGE]), left_gutter_specs_changed, 0, 0, 1); DEFVAR_SPECIFIER ("right-gutter", - &Vgutter[RIGHT_GUTTER] /* + &Vgutter[RIGHT_EDGE] /* Specifier for the gutter at the right edge of the frame. Use `set-specifier' to change this. See `default-gutter' for a description of a valid gutter instantiator. @@ -1335,9 +1296,9 @@ `right-gutter-width') is 0; thus, a right gutter will not be displayed even if you provide a value for `right-gutter'. */ ); - Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); - set_specifier_caching (Vgutter[RIGHT_GUTTER], - offsetof (struct window, gutter[RIGHT_GUTTER]), + Vgutter[RIGHT_EDGE] = Fmake_specifier (Qgutter); + set_specifier_caching (Vgutter[RIGHT_EDGE], + offsetof (struct window, gutter[RIGHT_EDGE]), right_gutter_specs_changed, 0, 0, 1); @@ -1345,10 +1306,10 @@ changed with `set-default-gutter-position'. */ fb = list1 (Fcons (Qnil, Qnil)); set_specifier_fallback (Vdefault_gutter, fb); - set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter); - set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb); - set_specifier_fallback (Vgutter[LEFT_GUTTER], fb); - set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb); + set_specifier_fallback (Vgutter[TOP_EDGE], Vdefault_gutter); + set_specifier_fallback (Vgutter[BOTTOM_EDGE], fb); + set_specifier_fallback (Vgutter[LEFT_EDGE], fb); + set_specifier_fallback (Vgutter[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /* *Height of the default gutter, if it's oriented horizontally. @@ -1394,51 +1355,51 @@ 0, 0, 1); DEFVAR_SPECIFIER ("top-gutter-height", - &Vgutter_size[TOP_GUTTER] /* + &Vgutter_size[TOP_EDGE] /* *Height of the top gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); - set_specifier_caching (Vgutter_size[TOP_GUTTER], - offsetof (struct window, gutter_size[TOP_GUTTER]), + Vgutter_size[TOP_EDGE] = Fmake_specifier (Qgutter_size); + set_specifier_caching (Vgutter_size[TOP_EDGE], + offsetof (struct window, gutter_size[TOP_EDGE]), gutter_geometry_changed_in_window, 0, 0, 1); DEFVAR_SPECIFIER ("bottom-gutter-height", - &Vgutter_size[BOTTOM_GUTTER] /* + &Vgutter_size[BOTTOM_EDGE] /* *Height of the bottom gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); - set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], - offsetof (struct window, gutter_size[BOTTOM_GUTTER]), + Vgutter_size[BOTTOM_EDGE] = Fmake_specifier (Qgutter_size); + set_specifier_caching (Vgutter_size[BOTTOM_EDGE], + offsetof (struct window, gutter_size[BOTTOM_EDGE]), gutter_geometry_changed_in_window, 0, 0, 1); DEFVAR_SPECIFIER ("left-gutter-width", - &Vgutter_size[LEFT_GUTTER] /* + &Vgutter_size[LEFT_EDGE] /* *Width of left gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qgutter_size); - set_specifier_caching (Vgutter_size[LEFT_GUTTER], - offsetof (struct window, gutter_size[LEFT_GUTTER]), + Vgutter_size[LEFT_EDGE] = Fmake_specifier (Qgutter_size); + set_specifier_caching (Vgutter_size[LEFT_EDGE], + offsetof (struct window, gutter_size[LEFT_EDGE]), gutter_geometry_changed_in_window, 0, 0, 1); DEFVAR_SPECIFIER ("right-gutter-width", - &Vgutter_size[RIGHT_GUTTER] /* + &Vgutter_size[RIGHT_EDGE] /* *Width of right gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qgutter_size); - set_specifier_caching (Vgutter_size[RIGHT_GUTTER], - offsetof (struct window, gutter_size[RIGHT_GUTTER]), + Vgutter_size[RIGHT_EDGE] = Fmake_specifier (Qgutter_size); + set_specifier_caching (Vgutter_size[RIGHT_EDGE], + offsetof (struct window, gutter_size[RIGHT_EDGE]), gutter_geometry_changed_in_window, 0, 0, 1); fb = Qnil; @@ -1475,11 +1436,11 @@ if (!NILP (fb)) set_specifier_fallback (Vdefault_gutter_width, fb); - set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height); + set_specifier_fallback (Vgutter_size[TOP_EDGE], Vdefault_gutter_height); fb = list1 (Fcons (Qnil, Qzero)); - set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb); - set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb); - set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb); + set_specifier_fallback (Vgutter_size[BOTTOM_EDGE], fb); + set_specifier_fallback (Vgutter_size[LEFT_EDGE], fb); + set_specifier_fallback (Vgutter_size[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("default-gutter-border-width", &Vdefault_gutter_border_width /* @@ -1502,55 +1463,55 @@ 0, 0, 0); DEFVAR_SPECIFIER ("top-gutter-border-width", - &Vgutter_border_width[TOP_GUTTER] /* + &Vgutter_border_width[TOP_EDGE] /* *Border width of the top gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vgutter_border_width[TOP_GUTTER], + Vgutter_border_width[TOP_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vgutter_border_width[TOP_EDGE], offsetof (struct window, - gutter_border_width[TOP_GUTTER]), + gutter_border_width[TOP_EDGE]), gutter_geometry_changed_in_window, 0, 0, 0); DEFVAR_SPECIFIER ("bottom-gutter-border-width", - &Vgutter_border_width[BOTTOM_GUTTER] /* + &Vgutter_border_width[BOTTOM_EDGE] /* *Border width of the bottom gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], + Vgutter_border_width[BOTTOM_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vgutter_border_width[BOTTOM_EDGE], offsetof (struct window, - gutter_border_width[BOTTOM_GUTTER]), + gutter_border_width[BOTTOM_EDGE]), gutter_geometry_changed_in_window, 0, 0, 0); DEFVAR_SPECIFIER ("left-gutter-border-width", - &Vgutter_border_width[LEFT_GUTTER] /* + &Vgutter_border_width[LEFT_EDGE] /* *Border width of left gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], + Vgutter_border_width[LEFT_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vgutter_border_width[LEFT_EDGE], offsetof (struct window, - gutter_border_width[LEFT_GUTTER]), + gutter_border_width[LEFT_EDGE]), gutter_geometry_changed_in_window, 0, 0, 0); DEFVAR_SPECIFIER ("right-gutter-border-width", - &Vgutter_border_width[RIGHT_GUTTER] /* + &Vgutter_border_width[RIGHT_EDGE] /* *Border width of right gutter. This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], + Vgutter_border_width[RIGHT_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vgutter_border_width[RIGHT_EDGE], offsetof (struct window, - gutter_border_width[RIGHT_GUTTER]), + gutter_border_width[RIGHT_EDGE]), gutter_geometry_changed_in_window, 0, 0, 0); fb = Qnil; @@ -1567,11 +1528,11 @@ if (!NILP (fb)) set_specifier_fallback (Vdefault_gutter_border_width, fb); - set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width); + set_specifier_fallback (Vgutter_border_width[TOP_EDGE], Vdefault_gutter_border_width); fb = list1 (Fcons (Qnil, Qzero)); - set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb); - set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb); - set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb); + set_specifier_fallback (Vgutter_border_width[BOTTOM_EDGE], fb); + set_specifier_fallback (Vgutter_border_width[LEFT_EDGE], fb); + set_specifier_fallback (Vgutter_border_width[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /* *Whether the default gutter is visible. @@ -1596,64 +1557,64 @@ 0, 0, 0); DEFVAR_SPECIFIER ("top-gutter-visible-p", - &Vgutter_visible_p[TOP_GUTTER] /* + &Vgutter_visible_p[TOP_EDGE] /* *Whether the top gutter is visible. This is a specifier; use `set-specifier' to change it. See `default-gutter-visible-p' for more information. */ ); - Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible); - set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], + Vgutter_visible_p[TOP_EDGE] = Fmake_specifier (Qgutter_visible); + set_specifier_caching (Vgutter_visible_p[TOP_EDGE], offsetof (struct window, - gutter_visible_p[TOP_GUTTER]), + gutter_visible_p[TOP_EDGE]), top_gutter_specs_changed, 0, 0, 0); DEFVAR_SPECIFIER ("bottom-gutter-visible-p", - &Vgutter_visible_p[BOTTOM_GUTTER] /* + &Vgutter_visible_p[BOTTOM_EDGE] /* *Whether the bottom gutter is visible. This is a specifier; use `set-specifier' to change it. See `default-gutter-visible-p' for more information. */ ); - Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible); - set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], + Vgutter_visible_p[BOTTOM_EDGE] = Fmake_specifier (Qgutter_visible); + set_specifier_caching (Vgutter_visible_p[BOTTOM_EDGE], offsetof (struct window, - gutter_visible_p[BOTTOM_GUTTER]), + gutter_visible_p[BOTTOM_EDGE]), bottom_gutter_specs_changed, 0, 0, 0); DEFVAR_SPECIFIER ("left-gutter-visible-p", - &Vgutter_visible_p[LEFT_GUTTER] /* + &Vgutter_visible_p[LEFT_EDGE] /* *Whether the left gutter is visible. This is a specifier; use `set-specifier' to change it. See `default-gutter-visible-p' for more information. */ ); - Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible); - set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], + Vgutter_visible_p[LEFT_EDGE] = Fmake_specifier (Qgutter_visible); + set_specifier_caching (Vgutter_visible_p[LEFT_EDGE], offsetof (struct window, - gutter_visible_p[LEFT_GUTTER]), + gutter_visible_p[LEFT_EDGE]), left_gutter_specs_changed, 0, 0, 0); DEFVAR_SPECIFIER ("right-gutter-visible-p", - &Vgutter_visible_p[RIGHT_GUTTER] /* + &Vgutter_visible_p[RIGHT_EDGE] /* *Whether the right gutter is visible. This is a specifier; use `set-specifier' to change it. See `default-gutter-visible-p' for more information. */ ); - Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible); - set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], + Vgutter_visible_p[RIGHT_EDGE] = Fmake_specifier (Qgutter_visible); + set_specifier_caching (Vgutter_visible_p[RIGHT_EDGE], offsetof (struct window, - gutter_visible_p[RIGHT_GUTTER]), + gutter_visible_p[RIGHT_EDGE]), right_gutter_specs_changed, 0, 0, 0); /* initially, top inherits from default; this can be changed with `set-default-gutter-position'. */ fb = list1 (Fcons (Qnil, Qt)); set_specifier_fallback (Vdefault_gutter_visible_p, fb); - set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER], + set_specifier_fallback (Vgutter_visible_p[TOP_EDGE], Vdefault_gutter_visible_p); - set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb); - set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb); - set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb); + set_specifier_fallback (Vgutter_visible_p[BOTTOM_EDGE], fb); + set_specifier_fallback (Vgutter_visible_p[LEFT_EDGE], fb); + set_specifier_fallback (Vgutter_visible_p[RIGHT_EDGE], fb); }
--- a/src/gutter.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/gutter.h Fri Feb 26 15:24:58 2010 +0000 @@ -1,5 +1,6 @@ /* Define general gutter support. Copyright (C) 1999 Andy Piper. + Copyright (C) 2010 Ben Wing. This file is part of XEmacs. @@ -36,18 +37,6 @@ #define DEFAULT_GUTTER_WIDTH 40 #define DEFAULT_GUTTER_BORDER_WIDTH 2 -enum gutter_pos -{ - TOP_GUTTER = 0, - BOTTOM_GUTTER = 1, - LEFT_GUTTER = 2, - RIGHT_GUTTER = 3 -}; - -/* Iterate over all possible gutter positions */ -#define GUTTER_POS_LOOP(var) \ - for (var = (enum gutter_pos) 0; var < 4; var = (enum gutter_pos) (var + 1)) - extern Lisp_Object Qgutter; extern Lisp_Object Vgutter_size[4]; @@ -97,13 +86,13 @@ /* these macros predicate size on position and type of window */ #define WINDOW_REAL_TOP_GUTTER_BOUNDS(w) \ - WINDOW_REAL_GUTTER_BOUNDS (w,TOP_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (w,TOP_EDGE) #define WINDOW_REAL_BOTTOM_GUTTER_BOUNDS(w) \ - WINDOW_REAL_GUTTER_BOUNDS (w,BOTTOM_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (w,BOTTOM_EDGE) #define WINDOW_REAL_LEFT_GUTTER_BOUNDS(w) \ - WINDOW_REAL_GUTTER_BOUNDS (w,LEFT_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (w,LEFT_EDGE) #define WINDOW_REAL_RIGHT_GUTTER_BOUNDS(w) \ - WINDOW_REAL_GUTTER_BOUNDS (w,RIGHT_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (w,RIGHT_EDGE) #define FRAME_GUTTER_VISIBLE(f, pos) \ WINDOW_REAL_GUTTER_VISIBLE (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), pos) @@ -119,12 +108,12 @@ /* these macros predicate size on position and type of window */ #define FRAME_TOP_GUTTER_BOUNDS(f) \ - WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), TOP_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), TOP_EDGE) #define FRAME_BOTTOM_GUTTER_BOUNDS(f) \ - WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), BOTTOM_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), BOTTOM_EDGE) #define FRAME_LEFT_GUTTER_BOUNDS(f) \ - WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), LEFT_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), LEFT_EDGE) #define FRAME_RIGHT_GUTTER_BOUNDS(f) \ - WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), RIGHT_GUTTER) + WINDOW_REAL_GUTTER_BOUNDS (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)), RIGHT_EDGE) #endif /* INCLUDED_gutter_h_ */
--- a/src/lisp.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/lisp.h Fri Feb 26 15:24:58 2010 +0000 @@ -1544,16 +1544,6 @@ RUN_HOOKS_UNTIL_FAILURE }; -#ifdef HAVE_TOOLBARS -enum toolbar_pos -{ - TOP_TOOLBAR, - BOTTOM_TOOLBAR, - LEFT_TOOLBAR, - RIGHT_TOOLBAR -}; -#endif - enum edge_style { EDGE_ETCHED_IN,
--- a/src/native-gtk-toolbar.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/native-gtk-toolbar.c Fri Feb 26 15:24:58 2010 +0000 @@ -1,5 +1,6 @@ /* toolbar implementation -- GTK interface. Copyright (C) 2000 Aaron Lehmann + Copyright (C) 2010 Ben Wing. This file is part of XEmacs. @@ -32,29 +33,8 @@ #include "toolbar.h" #include "window.h" -#define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ - do { \ - switch (pos) \ - { \ - case TOP_TOOLBAR: \ - (frame)->top_toolbar_was_visible = flag; \ - break; \ - case BOTTOM_TOOLBAR: \ - (frame)->bottom_toolbar_was_visible = flag; \ - break; \ - case LEFT_TOOLBAR: \ - (frame)->left_toolbar_was_visible = flag; \ - break; \ - case RIGHT_TOOLBAR: \ - (frame)->right_toolbar_was_visible = flag; \ - break; \ - default: \ - ABORT (); \ - } \ - } while (0) - static void -gtk_clear_toolbar (struct frame *f, enum toolbar_pos pos); +gtk_clear_toolbar (struct frame *f, enum edge_pos pos); static void gtk_toolbar_callback (GtkWidget *UNUSED (w), gpointer user_data) @@ -66,7 +46,7 @@ static void -gtk_output_toolbar (struct frame *f, enum toolbar_pos pos) +gtk_output_toolbar (struct frame *f, enum edge_pos pos) { GtkWidget *toolbar; Lisp_Object button, window, glyph, instance; @@ -114,7 +94,7 @@ { gtk_clear_toolbar (f, pos); FRAME_GTK_TOOLBAR_WIDGET (f)[pos] = toolbar = - gtk_toolbar_new (((pos == TOP_TOOLBAR) || (pos == BOTTOM_TOOLBAR)) ? + gtk_toolbar_new (((pos == TOP_EDGE) || (pos == BOTTOM_EDGE)) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_BOTH); } @@ -193,7 +173,7 @@ } static void -gtk_clear_toolbar (struct frame *f, enum toolbar_pos pos) +gtk_clear_toolbar (struct frame *f, enum edge_pos pos) { FRAME_GTK_TOOLBAR_CHECKSUM (f, pos) = 0; SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0); @@ -204,25 +184,15 @@ static void gtk_output_frame_toolbars (struct frame *f) { - if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - gtk_output_toolbar (f, TOP_TOOLBAR); - else if (f->top_toolbar_was_visible) - gtk_clear_toolbar (f, TOP_TOOLBAR); - - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - gtk_output_toolbar (f, BOTTOM_TOOLBAR); - else if (f->bottom_toolbar_was_visible) - gtk_clear_toolbar (f, LEFT_TOOLBAR); + enum edge_pos pos; - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - gtk_output_toolbar (f, LEFT_TOOLBAR); - else if (f->left_toolbar_was_visible) - gtk_clear_toolbar (f, LEFT_TOOLBAR); - - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - gtk_output_toolbar (f, RIGHT_TOOLBAR); - else if (f->right_toolbar_was_visible) - gtk_clear_toolbar (f, RIGHT_TOOLBAR); + EDGE_POS_LOOP (pos) + { + if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + gtk_output_toolbar (f, pos); + else if (f->toolbar_was_visible[pos]) + gtk_clear_toolbar (f, pos); + } } static void
--- a/src/objects-impl.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/objects-impl.h Fri Feb 26 15:24:58 2010 +0000 @@ -1,6 +1,7 @@ /* Generic object functions -- header implementation. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995, 1996, 2002 Ben Wing. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -93,6 +94,31 @@ #define CONCHECK_FACE_BOOLEAN_SPECIFIER(x) \ CONCHECK_SPECIFIER_TYPE (x, face_boolean) +/***************************************************************************** + * Background Placement Specifier Object * + *****************************************************************************/ + +struct face_background_placement_specifier +{ + Lisp_Object face; /* face this is attached to, or nil */ +}; + +#define FACE_BACKGROUND_PLACEMENT_SPECIFIER_DATA(g) \ + SPECIFIER_TYPE_DATA (g, face_background_placement) +#define FACE_BACKGROUND_PLACEMENT_SPECIFIER_FACE(g) \ + (FACE_BACKGROUND_PLACEMENT_SPECIFIER_DATA (g)->face) + +DECLARE_SPECIFIER_TYPE (face_background_placement); +extern Lisp_Object Qface_background_placement, Qabsolute, Qrelative; +#define XFACE_BACKGROUND_PLACEMENT_SPECIFIER(x) \ + XSPECIFIER_TYPE (x, face_background_placement) +#define FACE_BACKGROUND_PLACEMENT_SPECIFIERP(x) \ + SPECIFIER_TYPEP (x, face_background_placement) +#define CHECK_FACE_BACKGROUND_PLACEMENT_SPECIFIER(x) \ + CHECK_SPECIFIER_TYPE (x, face_background_placement) +#define CONCHECK_FACE_BACKGROUND_PLACEMENT_SPECIFIER(x) \ + CONCHECK_SPECIFIER_TYPE (x, face_background_placement) + /**************************************************************************** * Color Instance Object * ****************************************************************************/
--- a/src/objects.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/objects.c Fri Feb 26 15:24:58 2010 +0000 @@ -2,6 +2,7 @@ Copyright (C) 1995 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995, 1996, 2002, 2004, 2005, 2010 Ben Wing. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -1212,6 +1213,130 @@ } +/***************************************************************************** + Face Background Placement Object + ****************************************************************************/ +Lisp_Object Qabsolute, Qrelative; + +static const struct memory_description +face_background_placement_specifier_description[] = { + { XD_LISP_OBJECT, offsetof (struct face_background_placement_specifier, + face) }, + { XD_END } +}; + +DEFINE_SPECIFIER_TYPE_WITH_DATA (face_background_placement); +Lisp_Object Qface_background_placement; + +static void +face_background_placement_create (Lisp_Object obj) +{ + Lisp_Specifier *face_background_placement + = XFACE_BACKGROUND_PLACEMENT_SPECIFIER (obj); + + FACE_BACKGROUND_PLACEMENT_SPECIFIER_FACE (face_background_placement) = Qnil; +} + +static void +face_background_placement_mark (Lisp_Object obj) +{ + Lisp_Specifier *face_background_placement + = XFACE_BACKGROUND_PLACEMENT_SPECIFIER (obj); + + mark_object + (FACE_BACKGROUND_PLACEMENT_SPECIFIER_FACE (face_background_placement)); +} + +/* No equal or hash methods; ignore the face the background-placement is based + off of for `equal' */ + +extern Lisp_Object Qbackground_placement; + +static Lisp_Object +face_background_placement_instantiate (Lisp_Object UNUSED (specifier), + Lisp_Object UNUSED (matchspec), + Lisp_Object domain, + Lisp_Object instantiator, + Lisp_Object depth, + int no_fallback) +{ + /* When called, we're inside of call_with_suspended_errors(), + so we can freely error. */ + if (EQ (instantiator, Qabsolute) || EQ (instantiator, Qrelative)) + return instantiator; + else if (VECTORP (instantiator)) + { + assert (XVECTOR_LENGTH (instantiator) == 1); + + return FACE_PROPERTY_INSTANCE_1 + (Fget_face (XVECTOR_DATA (instantiator)[0]), + Qbackground_placement, domain, ERROR_ME, no_fallback, depth); + } + else + ABORT (); /* Eh? */ + + return Qunbound; +} + +static void +face_background_placement_validate (Lisp_Object instantiator) +{ + if (EQ (instantiator, Qabsolute) || EQ (instantiator, Qrelative)) + return; + else if (VECTORP (instantiator) && + (XVECTOR_LENGTH (instantiator) == 1)) + { + Lisp_Object face = XVECTOR_DATA (instantiator)[0]; + + Fget_face (face); /* just to check that the face exists -- dvl */ + } + else if (VECTORP (instantiator)) + sferror ("Wrong length for background-placement inheritance spec", + instantiator); + else + invalid_argument + ("\ +Background-placement instantiator must be absolute, relative or vector", + instantiator); +} + +static void +face_background_placement_after_change (Lisp_Object specifier, + Lisp_Object locale) +{ + Lisp_Object face + = FACE_BACKGROUND_PLACEMENT_SPECIFIER_FACE + (XFACE_BACKGROUND_PLACEMENT_SPECIFIER (specifier)); + + if (!NILP (face)) + { + face_property_was_changed (face, Qbackground_placement, locale); + if (BUFFERP (locale)) + XBUFFER (locale)->buffer_local_face_property = 1; + } +} + +void +set_face_background_placement_attached_to (Lisp_Object obj, Lisp_Object face) +{ + Lisp_Specifier *face_background_placement + = XFACE_BACKGROUND_PLACEMENT_SPECIFIER (obj); + + FACE_BACKGROUND_PLACEMENT_SPECIFIER_FACE (face_background_placement) = face; +} + +DEFUN ("face-background-placement-specifier-p", Fface_background_placement_specifier_p, 1, 1, 0, /* +Return non-nil if OBJECT is a face-background-placement specifier. + +See `make-face-background-placement-specifier' for a description of possible +face-background-placement instantiators. +*/ + (object)) +{ + return FACE_BACKGROUND_PLACEMENT_SPECIFIERP (object) ? Qt : Qnil; +} + + /************************************************************************/ /* initialization */ /************************************************************************/ @@ -1225,6 +1350,7 @@ DEFSUBR (Fcolor_specifier_p); DEFSUBR (Ffont_specifier_p); DEFSUBR (Fface_boolean_specifier_p); + DEFSUBR (Fface_background_placement_specifier_p); DEFSYMBOL_MULTIWORD_PREDICATE (Qcolor_instancep); DEFSUBR (Fmake_color_instance); @@ -1249,6 +1375,10 @@ /* Qcolor, Qfont defined in general.c */ DEFSYMBOL (Qface_boolean); + + DEFSYMBOL (Qface_background_placement); + DEFSYMBOL (Qabsolute); + DEFSYMBOL (Qrelative); } void @@ -1258,26 +1388,35 @@ INITIALIZE_SPECIFIER_TYPE_WITH_DATA (font, "font", "font-specifier-p"); INITIALIZE_SPECIFIER_TYPE_WITH_DATA (face_boolean, "face-boolean", "face-boolean-specifier-p"); + INITIALIZE_SPECIFIER_TYPE_WITH_DATA (face_background_placement, + "face-background-placement", + "\ +face-background-placement-specifier-p"); SPECIFIER_HAS_METHOD (color, instantiate); SPECIFIER_HAS_METHOD (font, instantiate); SPECIFIER_HAS_METHOD (face_boolean, instantiate); + SPECIFIER_HAS_METHOD (face_background_placement, instantiate); SPECIFIER_HAS_METHOD (color, validate); SPECIFIER_HAS_METHOD (font, validate); SPECIFIER_HAS_METHOD (face_boolean, validate); + SPECIFIER_HAS_METHOD (face_background_placement, validate); SPECIFIER_HAS_METHOD (color, create); SPECIFIER_HAS_METHOD (font, create); SPECIFIER_HAS_METHOD (face_boolean, create); + SPECIFIER_HAS_METHOD (face_background_placement, create); SPECIFIER_HAS_METHOD (color, mark); SPECIFIER_HAS_METHOD (font, mark); SPECIFIER_HAS_METHOD (face_boolean, mark); + SPECIFIER_HAS_METHOD (face_background_placement, mark); SPECIFIER_HAS_METHOD (color, after_change); SPECIFIER_HAS_METHOD (font, after_change); SPECIFIER_HAS_METHOD (face_boolean, after_change); + SPECIFIER_HAS_METHOD (face_background_placement, after_change); #ifdef MULE SPECIFIER_HAS_METHOD (font, validate_matchspec); @@ -1290,6 +1429,7 @@ REINITIALIZE_SPECIFIER_TYPE (color); REINITIALIZE_SPECIFIER_TYPE (font); REINITIALIZE_SPECIFIER_TYPE (face_boolean); + REINITIALIZE_SPECIFIER_TYPE (face_background_placement); } void
--- a/src/objects.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/objects.h Fri Feb 26 15:24:58 2010 +0000 @@ -76,4 +76,12 @@ void set_face_boolean_attached_to (Lisp_Object obj, Lisp_Object face, Lisp_Object property); +/***************************************************************************** + * Face Background Placement Specifier Object * + *****************************************************************************/ + +void set_face_background_placement_attached_to +(Lisp_Object obj, Lisp_Object face); + + #endif /* INCLUDED_objects_h_ */
--- a/src/redisplay-msw.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/redisplay-msw.c Fri Feb 26 15:24:58 2010 +0000 @@ -1212,8 +1212,13 @@ struct device *UNUSED (d), struct frame *f, face_index UNUSED (findex), int x, int y, int width, int height, Lisp_Object fcolor, - Lisp_Object bcolor, Lisp_Object background_pixmap) + Lisp_Object bcolor, + Lisp_Object background_pixmap, + Lisp_Object background_placement) { + /* #### FIXME: don't know how to handle background_placement in mswindows. + -- dvl */ + RECT rect = { x, y, x+width, y+height }; HDC hdc = get_frame_dc (f, 1);
--- a/src/redisplay-output.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/redisplay-output.c Fri Feb 26 15:24:58 2010 +0000 @@ -3,6 +3,7 @@ Copyright (C) 1995, 1996, 2002, 2003 Ben Wing. Copyright (C) 1996 Chuck Thompson. Copyright (C) 1999, 2002 Andy Piper. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -1721,6 +1722,7 @@ struct frame *f = NULL; struct device *d; Lisp_Object background_pixmap = Qunbound; + Lisp_Object background_placement = Qunbound; Lisp_Object fcolor = Qnil, bcolor = Qnil; if (!width || !height) @@ -1765,22 +1767,26 @@ /* #### maybe we could implement such that a string can be a background pixmap? */ background_pixmap = temp; + background_placement + = WINDOW_FACE_CACHEL_BACKGROUND_PLACEMENT (w, findex); } } else { temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale); - + if (IMAGE_INSTANCEP (temp) && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) { background_pixmap = temp; + background_placement + = FACE_BACKGROUND_PLACEMENT (Vdefault_face, locale); } } } - if (!UNBOUNDP (background_pixmap) && - XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0) + if (!UNBOUNDP (background_pixmap) + && XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0) { if (w) { @@ -1804,8 +1810,9 @@ if (UNBOUNDP (background_pixmap)) background_pixmap = Qnil; - DEVMETH (d, clear_region, - (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap)); + DEVMETH (d, clear_region, (locale, d, f, findex, x, y, width, height, + fcolor, bcolor, + background_pixmap, background_placement)); } /****************************************************************************
--- a/src/redisplay-tty.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/redisplay-tty.c Fri Feb 26 15:24:58 2010 +0000 @@ -428,7 +428,8 @@ struct frame * f, face_index findex, int x, int y, int width, int height, Lisp_Object UNUSED (fcolor), Lisp_Object UNUSED (bcolor), - Lisp_Object UNUSED (background_pixmap)) + Lisp_Object UNUSED (background_pixmap), + Lisp_Object UNUSED (background_placement)) { struct console *c = XCONSOLE (FRAME_CONSOLE (f)); int line;
--- a/src/redisplay-xlike-inc.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/redisplay-xlike-inc.c Fri Feb 26 15:24:58 2010 +0000 @@ -3,6 +3,7 @@ Copyright (C) 1994 Lucid, Inc. Copyright (C) 1995 Sun Microsystems, Inc. Copyright (C) 2002, 2003, 2005, 2009, 2010 Ben Wing. + Copyright (C) 2010 Didier Verna This file is part of XEmacs. @@ -812,8 +813,9 @@ /* Called as gtk_get_gc from gtk-glue.c */ -XLIKE_GC XLIKE_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, - Lisp_Object bg, Lisp_Object bg_pmap, +XLIKE_GC XLIKE_get_gc (struct frame *f, Lisp_Object font, + Lisp_Object fg, Lisp_Object bg, + Lisp_Object bg_pixmap, Lisp_Object bg_placement, Lisp_Object lwidth); /***************************************************************************** @@ -822,9 +824,12 @@ Given a number of parameters return a GC with those properties. ****************************************************************************/ XLIKE_GC -XLIKE_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, - Lisp_Object bg, Lisp_Object bg_pmap, Lisp_Object lwidth) +XLIKE_get_gc (struct frame *f, Lisp_Object font, + Lisp_Object fg, Lisp_Object bg, + Lisp_Object bg_pixmap, Lisp_Object bg_placement, + Lisp_Object lwidth) { + struct device *d = XDEVICE (f->device); XLIKE_GCVALUES gcv; unsigned long mask; @@ -836,7 +841,8 @@ gcv.clip_x_origin = 0; gcv.clip_y_origin = 0; XLIKE_SET_GC_FILL (gcv, XLIKE_FILL_SOLID); - mask = XLIKE_GC_EXPOSURES | XLIKE_GC_CLIP_MASK | XLIKE_GC_CLIP_X_ORIGIN | XLIKE_GC_CLIP_Y_ORIGIN; + mask = XLIKE_GC_EXPOSURES + | XLIKE_GC_CLIP_MASK | XLIKE_GC_CLIP_X_ORIGIN | XLIKE_GC_CLIP_Y_ORIGIN; mask |= XLIKE_GC_FILL; if (!NILP (font) @@ -882,7 +888,7 @@ /* This special case comes from a request to draw text with a face which has the dim property. We'll use a stippled foreground GC. */ - if (EQ (bg_pmap, Qdim)) + if (EQ (bg_pixmap, Qdim)) { assert (DEVICE_XLIKE_GRAY_PIXMAP (d) != XLIKE_NONE); @@ -890,21 +896,35 @@ gcv.stipple = DEVICE_XLIKE_GRAY_PIXMAP (d); mask |= (XLIKE_GC_FILL | XLIKE_GC_STIPPLE); } - else if (IMAGE_INSTANCEP (bg_pmap) - && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap))) + else if (IMAGE_INSTANCEP (bg_pixmap) + && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pixmap))) { - if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0) + if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pixmap) == 0) { XLIKE_SET_GC_FILL (gcv, XLIKE_FILL_OPAQUE_STIPPLED); - gcv.stipple = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pmap); + gcv.stipple = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pixmap); mask |= (XLIKE_GC_STIPPLE | XLIKE_GC_FILL); } else { XLIKE_SET_GC_FILL (gcv, XLIKE_FILL_TILED); - gcv.tile = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pmap); + gcv.tile = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pixmap); mask |= (XLIKE_GC_TILE | XLIKE_GC_FILL); } + if (EQ (bg_placement, Qabsolute)) + { +#ifdef THIS_IS_GTK + /* #### WARNING: this does not currently work. -- dvl + gcv.ts_x_origin = - FRAME_GTK_X (f); + gcv.ts_y_origin = - FRAME_GTK_Y (f); + mask |= (XLIKE_GC_TS_X_ORIGIN | XLIKE_GC_TS_Y_ORIGIN); + */ +#else + gcv.ts_x_origin = - FRAME_X_X (f); + gcv.ts_y_origin = - FRAME_X_Y (f); + mask |= (XLIKE_GC_TS_X_ORIGIN | XLIKE_GC_TS_Y_ORIGIN); +#endif + } } if (!NILP (lwidth)) @@ -1076,8 +1096,8 @@ && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap)) bgc = 0; else - bgc = XLIKE_get_gc (d, Qnil, cachel->foreground, cachel->background, - bg_pmap, Qnil); + bgc = XLIKE_get_gc (f, Qnil, cachel->foreground, cachel->background, + bg_pmap, cachel->background_placement, Qnil); if (bgc) { @@ -1157,8 +1177,8 @@ fg = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0); bg = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0); #endif - gc = XLIKE_get_gc (d, font, cursor_cachel->foreground, - cursor_cachel->background, Qnil, Qnil); + gc = XLIKE_get_gc (f, font, cursor_cachel->foreground, + cursor_cachel->background, Qnil, Qnil, Qnil); } else if (cachel->dim) { @@ -1179,8 +1199,8 @@ fg = XFT_FROB_LISP_COLOR (cachel->foreground, 1); bg = XFT_FROB_LISP_COLOR (cachel->background, 0); #endif - gc = XLIKE_get_gc (d, font, cachel->foreground, cachel->background, - Qdim, Qnil); + gc = XLIKE_get_gc (f, font, cachel->foreground, cachel->background, + Qdim, Qnil, Qnil); } else { @@ -1188,8 +1208,8 @@ fg = XFT_FROB_LISP_COLOR (cachel->foreground, 0); bg = XFT_FROB_LISP_COLOR (cachel->background, 0); #endif - gc = XLIKE_get_gc (d, font, cachel->foreground, cachel->background, - Qnil, Qnil); + gc = XLIKE_get_gc (f, font, cachel->foreground, cachel->background, + Qnil, Qnil, Qnil); } #ifdef USE_XFT { @@ -1462,8 +1482,8 @@ { XLIKE_RECTANGLE clip_box; XLIKE_GC cgc; - cgc = XLIKE_get_gc (d, font, cursor_cachel->foreground, - cursor_cachel->background, Qnil, Qnil); + cgc = XLIKE_get_gc (f, font, cursor_cachel->foreground, + cursor_cachel->background, Qnil, Qnil, Qnil); clip_box.x = 0; clip_box.y = 0; @@ -1534,13 +1554,14 @@ if (!NILP (bar_cursor_value)) { - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, Qnil, + Qnil, Qnil, make_int (bar_width)); } else { - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, - Qnil, Qnil, Qnil); + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, + Qnil, Qnil, Qnil, Qnil); } tmp_y = dl->ypos - bogusly_obtained_ascent_value; @@ -1728,7 +1749,8 @@ get_builtin_face_cache_index (w, Vtext_cursor_face)); - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil, + Qnil); if (cursor_width > db->xpos + dga->width - cursor_start) cursor_width = db->xpos + dga->width - cursor_start; @@ -1872,11 +1894,13 @@ bg_pmap = Qnil; if (NILP (bg_pmap)) - gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), - Qnil, Qnil, Qnil); + gc = XLIKE_get_gc (f, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), + Qnil, Qnil, Qnil, Qnil); else - gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex), - WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap, + gc = XLIKE_get_gc (f, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex), + WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), + bg_pmap, + WINDOW_FACE_CACHEL_BACKGROUND_PLACEMENT (w, rb->findex), Qnil); XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, y, width, height); @@ -1897,7 +1921,8 @@ (WINDOW_FACE_CACHEL (w, rb->findex), Vcharset_ascii)); - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, Qnil, + Qnil, Qnil, Qnil); cursor_y = dl->ypos - fi->ascent; cursor_height = fi->height; @@ -1915,8 +1940,9 @@ { int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2; - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, - Qnil, Qnil, make_int (bar_width)); + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, + Qnil, Qnil, Qnil, + make_int (bar_width)); XLIKE_DRAW_LINE (dpy, x_win, gc, cursor_start + bar_width - 1, cursor_y, cursor_start + bar_width - 1, cursor_y + cursor_height - 1); @@ -1959,9 +1985,9 @@ /* First clear the area not covered by the line. */ if (height - rb->object.hline.thickness > 0) { - gc = XLIKE_get_gc (d, Qnil, + gc = XLIKE_get_gc (f, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex), - Qnil, Qnil, Qnil); + Qnil, Qnil, Qnil, Qnil); if (ypos2 - ypos1 > 0) XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1); @@ -1977,8 +2003,8 @@ } #else /* THIS_IS_X */ /* Now draw the line. */ - gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), - Qnil, Qnil, Qnil); + gc = XLIKE_get_gc (f, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), + Qnil, Qnil, Qnil, Qnil); if (ypos2 < ypos1) ypos2 = ypos1; @@ -1999,8 +2025,10 @@ static void XLIKE_clear_region (Lisp_Object UNUSED (locale), struct device* d, struct frame* f, face_index UNUSED (findex), int x, int y, - int width, int height, Lisp_Object fcolor, - Lisp_Object bcolor, Lisp_Object background_pixmap) + int width, int height, + Lisp_Object fcolor, Lisp_Object bcolor, + Lisp_Object background_pixmap, + Lisp_Object background_placement) { XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); @@ -2008,7 +2036,8 @@ if (!UNBOUNDP (background_pixmap)) { - gc = XLIKE_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil); + gc = XLIKE_get_gc (f, Qnil, fcolor, bcolor, + background_pixmap, background_placement, Qnil); } if (gc) @@ -2054,7 +2083,8 @@ if (NILP (w->text_cursor_visible_p)) return; - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, Qnil, + Qnil, Qnil, Qnil); default_face_font_info (window, &defascent, 0, 0, &defheight, 0); @@ -2078,7 +2108,8 @@ { int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2; - gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, + gc = XLIKE_get_gc (f, Qnil, cursor_cachel->background, Qnil, + Qnil, Qnil, make_int (bar_width)); XLIKE_DRAW_LINE (dpy, x_win, gc, x + bar_width - 1, cursor_y, x + bar_width - 1, cursor_y + cursor_height - 1);
--- a/src/toolbar-msw.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/toolbar-msw.c Fri Feb 26 15:24:58 2010 +0000 @@ -1,7 +1,7 @@ /* toolbar implementation -- mswindows interface. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2002, 2010 Ben Wing. Copyright (C) 1996 Chuck Thompson. Copyright (C) 1998 Andy Piper. @@ -52,39 +52,18 @@ #define TOOLBAR_ITEM_ID_BITS(x) (((x) & 0x3FFF) | 0x4000) #define TOOLBAR_ID_BIAS 16 #define TOOLBAR_HANDLE(f,p) \ -GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + p) +GetDlgItem (FRAME_MSWINDOWS_HANDLE (f), TOOLBAR_ID_BIAS + p) #define MSWINDOWS_BUTTON_SHADOW_THICKNESS 2 #define MSWINDOWS_BLANK_SIZE 5 #define MSWINDOWS_MINIMUM_TOOLBAR_SIZE 8 static void -mswindows_move_toolbar (struct frame *f, enum toolbar_pos pos); - -#define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ - do { \ - switch (pos) \ - { \ - case TOP_TOOLBAR: \ - (frame)->top_toolbar_was_visible = flag; \ - break; \ - case BOTTOM_TOOLBAR: \ - (frame)->bottom_toolbar_was_visible = flag; \ - break; \ - case LEFT_TOOLBAR: \ - (frame)->left_toolbar_was_visible = flag; \ - break; \ - case RIGHT_TOOLBAR: \ - (frame)->right_toolbar_was_visible = flag; \ - break; \ - default: \ - ABORT (); \ - } \ - } while (0) +mswindows_move_toolbar (struct frame *f, enum edge_pos pos); static int allocate_toolbar_item_id (struct frame *f, struct toolbar_button *button, - enum toolbar_pos UNUSED (pos)) + enum edge_pos UNUSED (pos)) { /* hmm what do we generate an id based on */ int id = TOOLBAR_ITEM_ID_BITS (internal_hash (button->callback, 0)); @@ -97,7 +76,7 @@ } static void -mswindows_clear_toolbar (struct frame *f, enum toolbar_pos pos, +mswindows_clear_toolbar (struct frame *f, enum edge_pos pos, int UNUSED (thickness_change)) { HIMAGELIST ilist = NULL; @@ -123,11 +102,11 @@ qxeSendMessage (toolbarwnd, TB_GETIMAGELIST, 0, (LONG) &ilist); if (ilist) { - ImageList_Destroy(ilist); + ImageList_Destroy (ilist); } qxeSendMessage (toolbarwnd, TB_SETIMAGELIST, 0, (LPARAM)NULL); - ShowWindow(toolbarwnd, SW_HIDE); + ShowWindow (toolbarwnd, SW_HIDE); } FRAME_MSWINDOWS_TOOLBAR_CHECKSUM (f, pos) = 0; @@ -135,7 +114,7 @@ } static void -mswindows_output_toolbar (struct frame *f, enum toolbar_pos pos) +mswindows_output_toolbar (struct frame *f, enum edge_pos pos) { int x, y, bar_width, bar_height, vert; int width=-1, height=-1, bmwidth=0, bmheight=0, maxbmwidth, maxbmheight; @@ -208,7 +187,7 @@ struct toolbar_button *tb = XTOOLBAR_BUTTON (button); checksum = HASH5 (checksum, - internal_hash (get_toolbar_button_glyph(w, tb), 0), + internal_hash (get_toolbar_button_glyph (w, tb), 0), internal_hash (tb->callback, 0), width, LISP_HASH (w->toolbar_buttons_captioned_p)); @@ -217,7 +196,7 @@ } /* only rebuild if something has changed */ - if (!toolbarwnd || FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)!=checksum) + if (!toolbarwnd || FRAME_MSWINDOWS_TOOLBAR_CHECKSUM (f,pos)!=checksum) { /* remove the old one */ mswindows_clear_toolbar (f, pos, 0); @@ -401,7 +380,7 @@ /* finally populate with images */ if (qxeSendMessage (toolbarwnd, TB_BUTTONSTRUCTSIZE, - (WPARAM)sizeof(TBBUTTON), (LPARAM)0) == -1) + (WPARAM)sizeof (TBBUTTON), (LPARAM)0) == -1) { mswindows_clear_toolbar (f, pos, 0); gui_error ("couldn't set button structure size", Qunbound); @@ -446,7 +425,7 @@ else { RECT tmp; - qxeSendMessage (toolbarwnd, TB_SETROWS, MAKEWPARAM(1, FALSE), + qxeSendMessage (toolbarwnd, TB_SETROWS, MAKEWPARAM (1, FALSE), (LPARAM)&tmp); } @@ -475,10 +454,10 @@ } static void -mswindows_move_toolbar (struct frame *f, enum toolbar_pos pos) +mswindows_move_toolbar (struct frame *f, enum edge_pos pos) { int bar_x, bar_y, bar_width, bar_height, vert; - HWND toolbarwnd = TOOLBAR_HANDLE(f,pos); + HWND toolbarwnd = TOOLBAR_HANDLE (f,pos); if (toolbarwnd) { @@ -490,19 +469,19 @@ by Windows and by XEmacs. */ switch (pos) { - case TOP_TOOLBAR: + case TOP_EDGE: bar_x--; bar_y-=2; bar_width+=3; bar_height+=3; break; - case LEFT_TOOLBAR: + case LEFT_EDGE: bar_x--; bar_y-=2; bar_height++; bar_width++; break; - case BOTTOM_TOOLBAR: + case BOTTOM_EDGE: bar_y-=2; bar_width+=4; bar_height+=4; break; - case RIGHT_TOOLBAR: + case RIGHT_EDGE: bar_y-=2; bar_x++; bar_width++; bar_height++; break; @@ -517,19 +496,14 @@ int UNUSED (x), int UNUSED (y), int UNUSED (width), int UNUSED (height)) { + enum edge_pos pos; assert (FRAME_MSWINDOWS_P (f)); - if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - mswindows_move_toolbar (f, TOP_TOOLBAR); - - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - mswindows_move_toolbar (f, BOTTOM_TOOLBAR); - - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - mswindows_move_toolbar (f, LEFT_TOOLBAR); - - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - mswindows_move_toolbar (f, RIGHT_TOOLBAR); + EDGE_POS_LOOP (pos) + { + if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + mswindows_move_toolbar (f, pos); + } } static void @@ -542,41 +516,33 @@ static void mswindows_initialize_frame_toolbars (struct frame *UNUSED (f)) { - } static void mswindows_output_frame_toolbars (struct frame *f) { + enum edge_pos pos; assert (FRAME_MSWINDOWS_P (f)); - if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - mswindows_output_toolbar (f, TOP_TOOLBAR); - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - mswindows_output_toolbar (f, BOTTOM_TOOLBAR); - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - mswindows_output_toolbar (f, LEFT_TOOLBAR); - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - mswindows_output_toolbar (f, RIGHT_TOOLBAR); + EDGE_POS_LOOP (pos) + { + if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + mswindows_output_toolbar (f, pos); + } } static void mswindows_clear_frame_toolbars (struct frame *f) { + enum edge_pos pos; assert (FRAME_MSWINDOWS_P (f)); - if (f->top_toolbar_was_visible - && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - mswindows_clear_toolbar (f, TOP_TOOLBAR, 0); - if (f->bottom_toolbar_was_visible - && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - mswindows_clear_toolbar (f, BOTTOM_TOOLBAR, 0); - if (f->left_toolbar_was_visible - && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - mswindows_clear_toolbar (f, LEFT_TOOLBAR, 0); - if (f->right_toolbar_was_visible - && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - mswindows_clear_toolbar (f, RIGHT_TOOLBAR, 0); + EDGE_POS_LOOP (pos) + { + if (f->toolbar_was_visible[pos] + && !FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + mswindows_clear_toolbar (f, pos, 0); + } } static void @@ -584,15 +550,15 @@ { HWND twnd=NULL; #define DELETE_TOOLBAR(pos) \ - mswindows_clear_toolbar(f, pos, 0); \ - if ((twnd=GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), \ + mswindows_clear_toolbar (f, pos, 0); \ + if ((twnd=GetDlgItem (FRAME_MSWINDOWS_HANDLE (f), \ TOOLBAR_ID_BIAS + pos))) \ - DestroyWindow(twnd) + DestroyWindow (twnd) - DELETE_TOOLBAR(TOP_TOOLBAR); - DELETE_TOOLBAR(BOTTOM_TOOLBAR); - DELETE_TOOLBAR(LEFT_TOOLBAR); - DELETE_TOOLBAR(RIGHT_TOOLBAR); + DELETE_TOOLBAR (TOP_EDGE); + DELETE_TOOLBAR (BOTTOM_EDGE); + DELETE_TOOLBAR (LEFT_EDGE); + DELETE_TOOLBAR (RIGHT_EDGE); #undef DELETE_TOOLBAR }
--- a/src/toolbar-xlike.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/toolbar-xlike.c Fri Feb 26 15:24:58 2010 +0000 @@ -38,14 +38,14 @@ /* Only a very few things need to differ based on the toolkit used. ** -** Some of the routines used assert(FRAME_yyy_P(f)) checks, this is +** Some of the routines used assert (FRAME_yyy_P(f)) checks, this is ** now abstracted into __INTERNAL_APPROPRIATENESS_CHECK(). When we ** add new window systems that use this code, we should either add a ** new case here, or just remove the checks completely. ** ** At least for X & GTK redraw_frame_toolbars() might end up getting ** called before we are completely initialized. To avoid this, we use -** the __INTERNAL_MAPPED_P(f) macro, that should return 0 if we should +** the __INTERNAL_MAPPED_P (f) macro, that should return 0 if we should ** not draw the toolbars yet. When we add new window systems that use ** this code, we should add a new case here, if they need it. ** @@ -85,7 +85,7 @@ Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); struct window *w = XWINDOW (window); int shadow_thickness; - int def_shadow_thickness = XINT (Fspecifier_instance(Vtoolbar_shadow_thickness, window, Qnil, Qnil)); + int def_shadow_thickness = XINT (Fspecifier_instance (Vtoolbar_shadow_thickness, window, Qnil, Qnil)); face_index toolbar_findex; if (tb->vertical) @@ -103,7 +103,7 @@ toolbar_findex = get_builtin_face_cache_index (w, Vtoolbar_face); - /* Blank toolbar buttons that should be 3d will have EQ(tb->up_glyph, Qt) + /* Blank toolbar buttons that should be 3d will have EQ (tb->up_glyph, Qt) ** Blank toolbar buttons that should be flat will have NILP (tb->up_glyph) ** ** Real toolbar buttons will check tb->enabled && tb->down @@ -143,7 +143,7 @@ MAYBE_DEVMETH (d, bevel_area, (w, toolbar_findex, sx + x_adj, sy + y_adj, swidth + width_adj, - sheight + height_adj, abs(shadow_thickness), + sheight + height_adj, abs (shadow_thickness), EDGE_ALL, (shadow_thickness < 0) ? EDGE_BEVEL_IN : EDGE_BEVEL_OUT)); } @@ -370,7 +370,7 @@ return (size); } -#define XLIKE_OUTPUT_BUTTONS_LOOP(left) \ +#define XLIKE_OUTPUT_BUTTONS_LOOP(left) \ do { \ while (!NILP (button)) \ { \ @@ -436,29 +436,8 @@ } \ } while (0) -#define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ - do { \ - switch (pos) \ - { \ - case TOP_TOOLBAR: \ - (frame)->top_toolbar_was_visible = flag; \ - break; \ - case BOTTOM_TOOLBAR: \ - (frame)->bottom_toolbar_was_visible = flag; \ - break; \ - case LEFT_TOOLBAR: \ - (frame)->left_toolbar_was_visible = flag; \ - break; \ - case RIGHT_TOOLBAR: \ - (frame)->right_toolbar_was_visible = flag; \ - break; \ - default: \ - ABORT (); \ - } \ - } while (0) - static void -xlike_output_toolbar (struct frame *f, enum toolbar_pos pos) +xlike_output_toolbar (struct frame *f, enum edge_pos pos) { int x, y, bar_width, bar_height, vert; int max_pixpos, right_size, right_start, blank_size; @@ -582,7 +561,7 @@ } static void -xlike_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change) +xlike_clear_toolbar (struct frame *f, enum edge_pos pos, int thickness_change) { Lisp_Object frame; int x, y, width, height, vert; @@ -594,7 +573,7 @@ to clear any excess toolbar if the size shrinks. */ if (thickness_change < 0) { - if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR) + if (pos == LEFT_EDGE || pos == RIGHT_EDGE) { x = x + width + thickness_change; width = -thickness_change; @@ -616,42 +595,32 @@ void xlike_output_frame_toolbars (struct frame *f) { - __INTERNAL_APPROPRIATENESS_CHECK(f); - - if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - xlike_output_toolbar (f, TOP_TOOLBAR); + enum edge_pos pos; + __INTERNAL_APPROPRIATENESS_CHECK (f); - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - xlike_output_toolbar (f, BOTTOM_TOOLBAR); - - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - xlike_output_toolbar (f, LEFT_TOOLBAR); - - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - xlike_output_toolbar (f, RIGHT_TOOLBAR); + EDGE_POS_LOOP (pos) + { + if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + xlike_output_toolbar (f, pos); + } } void xlike_clear_frame_toolbars (struct frame *f) { - __INTERNAL_APPROPRIATENESS_CHECK(f); + enum edge_pos pos; + __INTERNAL_APPROPRIATENESS_CHECK (f); - if (f->top_toolbar_was_visible - && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - xlike_clear_toolbar (f, TOP_TOOLBAR, 0); - if (f->bottom_toolbar_was_visible - && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - xlike_clear_toolbar (f, BOTTOM_TOOLBAR, 0); - if (f->left_toolbar_was_visible - && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - xlike_clear_toolbar (f, LEFT_TOOLBAR, 0); - if (f->right_toolbar_was_visible - && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - xlike_clear_toolbar (f, RIGHT_TOOLBAR, 0); + EDGE_POS_LOOP (pos) + { + if (f->toolbar_was_visible[pos] + && !FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + xlike_clear_toolbar (f, pos, 0); + } } static void -xlike_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y, +xlike_redraw_exposed_toolbar (struct frame *f, enum edge_pos pos, int x, int y, int width, int height) { int bar_x, bar_y, bar_width, bar_height, vert; @@ -701,19 +670,14 @@ xlike_redraw_exposed_toolbars (struct frame *f, int x, int y, int width, int height) { - __INTERNAL_APPROPRIATENESS_CHECK(f); - - if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) - xlike_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height); + enum edge_pos pos; + __INTERNAL_APPROPRIATENESS_CHECK (f); - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) - xlike_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height); - - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) - xlike_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height); - - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) - xlike_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height); + EDGE_POS_LOOP (pos) + { + if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) + xlike_redraw_exposed_toolbar (f, pos, x, y, width, height); + } } void @@ -724,7 +688,7 @@ particular before we have actually mapped it. That routine can call this one. So, we need to make sure that the frame is actually ready before we try and draw all over it. */ - if (__INTERNAL_MAPPED_P(f)) + if (__INTERNAL_MAPPED_P (f)) xlike_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f)); }
--- a/src/toolbar.c Fri Feb 26 15:22:15 2010 +0000 +++ b/src/toolbar.c Fri Feb 26 15:24:58 2010 +0000 @@ -37,10 +37,10 @@ #include "toolbar.h" #include "window.h" -Lisp_Object Vtoolbar[4]; -Lisp_Object Vtoolbar_size[4]; -Lisp_Object Vtoolbar_visible_p[4]; -Lisp_Object Vtoolbar_border_width[4]; +Lisp_Object Vtoolbar[NUM_EDGES]; +Lisp_Object Vtoolbar_size[NUM_EDGES]; +Lisp_Object Vtoolbar_visible_p[NUM_EDGES]; +Lisp_Object Vtoolbar_border_width[NUM_EDGES]; Lisp_Object Vdefault_toolbar, Vdefault_toolbar_visible_p; Lisp_Object Vdefault_toolbar_width, Vdefault_toolbar_height; @@ -232,16 +232,16 @@ } -static enum toolbar_pos +static enum edge_pos decode_toolbar_position (Lisp_Object position) { - if (EQ (position, Qtop)) return TOP_TOOLBAR; - if (EQ (position, Qbottom)) return BOTTOM_TOOLBAR; - if (EQ (position, Qleft)) return LEFT_TOOLBAR; - if (EQ (position, Qright)) return RIGHT_TOOLBAR; + if (EQ (position, Qtop)) return TOP_EDGE; + if (EQ (position, Qbottom)) return BOTTOM_EDGE; + if (EQ (position, Qleft)) return LEFT_EDGE; + if (EQ (position, Qright)) return RIGHT_EDGE; invalid_constant ("Invalid toolbar position", position); - RETURN_NOT_REACHED (TOP_TOOLBAR); + RETURN_NOT_REACHED (TOP_EDGE); } DEFUN ("set-default-toolbar-position", Fset_default_toolbar_position, 1, 1, 0, /* @@ -251,8 +251,8 @@ */ (position)) { - enum toolbar_pos cur = decode_toolbar_position (Vdefault_toolbar_position); - enum toolbar_pos new_ = decode_toolbar_position (position); + enum edge_pos cur = decode_toolbar_position (Vdefault_toolbar_position); + enum edge_pos new_ = decode_toolbar_position (position); if (cur != new_) { @@ -264,7 +264,7 @@ set_specifier_fallback (Vtoolbar[new_], Vdefault_toolbar); set_specifier_fallback (Vtoolbar_size[cur], list1 (Fcons (Qnil, Qzero))); set_specifier_fallback (Vtoolbar_size[new_], - new_ == TOP_TOOLBAR || new_ == BOTTOM_TOOLBAR + new_ == TOP_EDGE || new_ == BOTTOM_EDGE ? Vdefault_toolbar_height : Vdefault_toolbar_width); set_specifier_fallback (Vtoolbar_border_width[cur], @@ -590,7 +590,7 @@ } void -mark_frame_toolbar_buttons_dirty (struct frame *f, enum toolbar_pos pos) +mark_frame_toolbar_buttons_dirty (struct frame *f, enum edge_pos pos) { Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos); @@ -604,7 +604,7 @@ } static Lisp_Object -compute_frame_toolbar_buttons (struct frame *f, enum toolbar_pos pos, +compute_frame_toolbar_buttons (struct frame *f, enum edge_pos pos, Lisp_Object toolbar) { Lisp_Object buttons, prev_button, first_button; @@ -713,7 +713,7 @@ } static void -set_frame_toolbar (struct frame *f, enum toolbar_pos pos) +set_frame_toolbar (struct frame *f, enum edge_pos pos) { struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); Lisp_Object toolbar = w->toolbar[pos]; @@ -725,10 +725,10 @@ static void compute_frame_toolbars_data (struct frame *f) { - set_frame_toolbar (f, TOP_TOOLBAR); - set_frame_toolbar (f, BOTTOM_TOOLBAR); - set_frame_toolbar (f, LEFT_TOOLBAR); - set_frame_toolbar (f, RIGHT_TOOLBAR); + set_frame_toolbar (f, TOP_EDGE); + set_frame_toolbar (f, BOTTOM_EDGE); + set_frame_toolbar (f, LEFT_EDGE); + set_frame_toolbar (f, RIGHT_EDGE); } /* Update the toolbar geometry separately from actually displaying the @@ -762,14 +762,15 @@ unchanged, as it will hose windows whose pixsizes are not multiple of character sizes. */ - for (pos = 0; pos < 4; pos++) + EDGE_POS_LOOP (pos) if (FRAME_REAL_TOOLBAR_SIZE (f, pos) != FRAME_CURRENT_TOOLBAR_SIZE (f, pos)) frame_size_changed = 1; - for (pos = 0; pos < 4; pos++) { - f->current_toolbar_size[pos] = FRAME_REAL_TOOLBAR_SIZE (f, pos); - } + EDGE_POS_LOOP (pos) + { + f->current_toolbar_size[pos] = FRAME_REAL_TOOLBAR_SIZE (f, pos); + } /* Removed the check for the minibuffer here. We handle this more correctly now by consistently using @@ -833,7 +834,7 @@ already recomputed, and possibly modified by resource initialization. Remember current toolbar geometry so next redisplay will not needlessly relayout toolbars. */ - for (pos = 0; pos < 4; pos++) + EDGE_POS_LOOP (pos) f->current_toolbar_size[pos] = FRAME_REAL_TOOLBAR_SIZE (f, pos); } } @@ -868,7 +869,7 @@ } void -get_toolbar_coords (struct frame *f, enum toolbar_pos pos, int *x, int *y, +get_toolbar_coords (struct frame *f, enum edge_pos pos, int *x, int *y, int *width, int *height, int *vert, int for_layout) { int visible_top_toolbar_height, visible_bottom_toolbar_height; @@ -892,7 +893,7 @@ switch (pos) { - case TOP_TOOLBAR: + case TOP_EDGE: *x = 1; *y = 0; /* #### should be 1 if no menubar */ *width = FRAME_PIXWIDTH (f) - 2; @@ -900,7 +901,7 @@ 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) - adjust; *vert = 0; break; - case BOTTOM_TOOLBAR: + case BOTTOM_EDGE: *x = 1; *y = FRAME_PIXHEIGHT (f) - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) - 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f); @@ -909,7 +910,7 @@ 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f) - adjust; *vert = 0; break; - case LEFT_TOOLBAR: + case LEFT_EDGE: *x = 1; *y = visible_top_toolbar_height; *width = FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) + @@ -918,7 +919,7 @@ visible_bottom_toolbar_height - 1); *vert = 1; break; - case RIGHT_TOOLBAR: + case RIGHT_EDGE: *x = FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) - 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f); *y = visible_top_toolbar_height; @@ -934,7 +935,7 @@ } #define CHECK_TOOLBAR(pos) do { \ - if (FRAME_REAL_##pos##_VISIBLE (f)) \ + if (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)) \ { \ int x, y, width, height, vert; \ \ @@ -950,10 +951,10 @@ static Lisp_Object toolbar_buttons_at_pixpos (struct frame *f, int x_coord, int y_coord) { - CHECK_TOOLBAR (TOP_TOOLBAR); - CHECK_TOOLBAR (BOTTOM_TOOLBAR); - CHECK_TOOLBAR (LEFT_TOOLBAR); - CHECK_TOOLBAR (RIGHT_TOOLBAR); + CHECK_TOOLBAR (TOP_EDGE); + CHECK_TOOLBAR (BOTTOM_EDGE); + CHECK_TOOLBAR (LEFT_EDGE); + CHECK_TOOLBAR (RIGHT_EDGE); return Qnil; } @@ -997,9 +998,9 @@ DEFINE_SPECIFIER_TYPE (toolbar); -#define CTB_ERROR(msg) do { \ - maybe_signal_error (Qinvalid_argument, msg, button, Qtoolbar, errb); \ - RETURN_SANS_WARNINGS Qnil; \ +#define CTB_ERROR(msg) do { \ + maybe_signal_error (Qinvalid_argument, msg, button, Qtoolbar, errb); \ + RETURN_SANS_WARNINGS Qnil; \ } while (0) /* Returns Q_style if key was :style, Qt if ok otherwise, Qnil if error. */ @@ -1216,9 +1217,9 @@ specifier caching changes */ static void -recompute_overlaying_specifier (Lisp_Object real_one[4]) +recompute_overlaying_specifier (Lisp_Object real_one[NUM_EDGES]) { - enum toolbar_pos pos = decode_toolbar_position (Vdefault_toolbar_position); + enum edge_pos pos = decode_toolbar_position (Vdefault_toolbar_position); Fset_specifier_dirty_flag (real_one[pos]); } @@ -1501,19 +1502,19 @@ 0, 0, 0); DEFVAR_SPECIFIER ("top-toolbar", - &Vtoolbar[TOP_TOOLBAR] /* + &Vtoolbar[TOP_EDGE] /* Specifier for the toolbar at the top of the frame. Use `set-specifier' to change this. See `default-toolbar' for a description of a valid toolbar instantiator. */ ); - Vtoolbar[TOP_TOOLBAR] = Fmake_specifier (Qtoolbar); - set_specifier_caching (Vtoolbar[TOP_TOOLBAR], - offsetof (struct window, toolbar[TOP_TOOLBAR]), + Vtoolbar[TOP_EDGE] = Fmake_specifier (Qtoolbar); + set_specifier_caching (Vtoolbar[TOP_EDGE], + offsetof (struct window, toolbar[TOP_EDGE]), toolbar_specs_changed, 0, 0, 0); DEFVAR_SPECIFIER ("bottom-toolbar", - &Vtoolbar[BOTTOM_TOOLBAR] /* + &Vtoolbar[BOTTOM_EDGE] /* Specifier for the toolbar at the bottom of the frame. Use `set-specifier' to change this. See `default-toolbar' for a description of a valid toolbar instantiator. @@ -1523,14 +1524,14 @@ `bottom-toolbar-height') is 0; thus, a bottom toolbar will not be displayed even if you provide a value for `bottom-toolbar'. */ ); - Vtoolbar[BOTTOM_TOOLBAR] = Fmake_specifier (Qtoolbar); - set_specifier_caching (Vtoolbar[BOTTOM_TOOLBAR], - offsetof (struct window, toolbar[BOTTOM_TOOLBAR]), + Vtoolbar[BOTTOM_EDGE] = Fmake_specifier (Qtoolbar); + set_specifier_caching (Vtoolbar[BOTTOM_EDGE], + offsetof (struct window, toolbar[BOTTOM_EDGE]), toolbar_specs_changed, 0, 0, 0); DEFVAR_SPECIFIER ("left-toolbar", - &Vtoolbar[LEFT_TOOLBAR] /* + &Vtoolbar[LEFT_EDGE] /* Specifier for the toolbar at the left edge of the frame. Use `set-specifier' to change this. See `default-toolbar' for a description of a valid toolbar instantiator. @@ -1540,14 +1541,14 @@ `left-toolbar-width') is 0; thus, a left toolbar will not be displayed even if you provide a value for `left-toolbar'. */ ); - Vtoolbar[LEFT_TOOLBAR] = Fmake_specifier (Qtoolbar); - set_specifier_caching (Vtoolbar[LEFT_TOOLBAR], - offsetof (struct window, toolbar[LEFT_TOOLBAR]), + Vtoolbar[LEFT_EDGE] = Fmake_specifier (Qtoolbar); + set_specifier_caching (Vtoolbar[LEFT_EDGE], + offsetof (struct window, toolbar[LEFT_EDGE]), toolbar_specs_changed, 0, 0, 0); DEFVAR_SPECIFIER ("right-toolbar", - &Vtoolbar[RIGHT_TOOLBAR] /* + &Vtoolbar[RIGHT_EDGE] /* Specifier for the toolbar at the right edge of the frame. Use `set-specifier' to change this. See `default-toolbar' for a description of a valid toolbar instantiator. @@ -1557,9 +1558,9 @@ `right-toolbar-width') is 0; thus, a right toolbar will not be displayed even if you provide a value for `right-toolbar'. */ ); - Vtoolbar[RIGHT_TOOLBAR] = Fmake_specifier (Qtoolbar); - set_specifier_caching (Vtoolbar[RIGHT_TOOLBAR], - offsetof (struct window, toolbar[RIGHT_TOOLBAR]), + Vtoolbar[RIGHT_EDGE] = Fmake_specifier (Qtoolbar); + set_specifier_caching (Vtoolbar[RIGHT_EDGE], + offsetof (struct window, toolbar[RIGHT_EDGE]), toolbar_specs_changed, 0, 0, 0); @@ -1567,10 +1568,10 @@ changed with `set-default-toolbar-position'. */ fb = list1 (Fcons (Qnil, Qnil)); set_specifier_fallback (Vdefault_toolbar, fb); - set_specifier_fallback (Vtoolbar[TOP_TOOLBAR], Vdefault_toolbar); - set_specifier_fallback (Vtoolbar[BOTTOM_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar[LEFT_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar[RIGHT_TOOLBAR], fb); + set_specifier_fallback (Vtoolbar[TOP_EDGE], Vdefault_toolbar); + set_specifier_fallback (Vtoolbar[BOTTOM_EDGE], fb); + set_specifier_fallback (Vtoolbar[LEFT_EDGE], fb); + set_specifier_fallback (Vtoolbar[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("default-toolbar-height", &Vdefault_toolbar_height /* *Height of the default toolbar, if it's oriented horizontally. @@ -1632,59 +1633,59 @@ default_toolbar_size_changed_in_frame, 0); DEFVAR_SPECIFIER ("top-toolbar-height", - &Vtoolbar_size[TOP_TOOLBAR] /* + &Vtoolbar_size[TOP_EDGE] /* *Height of the top toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_size[TOP_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_size[TOP_TOOLBAR], - offsetof (struct window, toolbar_size[TOP_TOOLBAR]), + Vtoolbar_size[TOP_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_size[TOP_EDGE], + offsetof (struct window, toolbar_size[TOP_EDGE]), toolbar_geometry_changed_in_window, - offsetof (struct frame, toolbar_size[TOP_TOOLBAR]), + offsetof (struct frame, toolbar_size[TOP_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("bottom-toolbar-height", - &Vtoolbar_size[BOTTOM_TOOLBAR] /* + &Vtoolbar_size[BOTTOM_EDGE] /* *Height of the bottom toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_size[BOTTOM_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_size[BOTTOM_TOOLBAR], - offsetof (struct window, toolbar_size[BOTTOM_TOOLBAR]), + Vtoolbar_size[BOTTOM_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_size[BOTTOM_EDGE], + offsetof (struct window, toolbar_size[BOTTOM_EDGE]), toolbar_geometry_changed_in_window, - offsetof (struct frame, toolbar_size[BOTTOM_TOOLBAR]), + offsetof (struct frame, toolbar_size[BOTTOM_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("left-toolbar-width", - &Vtoolbar_size[LEFT_TOOLBAR] /* + &Vtoolbar_size[LEFT_EDGE] /* *Width of left toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_size[LEFT_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_size[LEFT_TOOLBAR], - offsetof (struct window, toolbar_size[LEFT_TOOLBAR]), + Vtoolbar_size[LEFT_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_size[LEFT_EDGE], + offsetof (struct window, toolbar_size[LEFT_EDGE]), toolbar_geometry_changed_in_window, - offsetof (struct frame, toolbar_size[LEFT_TOOLBAR]), + offsetof (struct frame, toolbar_size[LEFT_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("right-toolbar-width", - &Vtoolbar_size[RIGHT_TOOLBAR] /* + &Vtoolbar_size[RIGHT_EDGE] /* *Width of right toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_size[RIGHT_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_size[RIGHT_TOOLBAR], - offsetof (struct window, toolbar_size[RIGHT_TOOLBAR]), + Vtoolbar_size[RIGHT_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_size[RIGHT_EDGE], + offsetof (struct window, toolbar_size[RIGHT_EDGE]), toolbar_geometry_changed_in_window, - offsetof (struct frame, toolbar_size[RIGHT_TOOLBAR]), + offsetof (struct frame, toolbar_size[RIGHT_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("toolbar-shadow-thickness", @@ -1750,11 +1751,11 @@ if (!NILP (fb)) set_specifier_fallback (Vdefault_toolbar_width, fb); - set_specifier_fallback (Vtoolbar_size[TOP_TOOLBAR], Vdefault_toolbar_height); + set_specifier_fallback (Vtoolbar_size[TOP_EDGE], Vdefault_toolbar_height); fb = list1 (Fcons (Qnil, Qzero)); - set_specifier_fallback (Vtoolbar_size[BOTTOM_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar_size[LEFT_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar_size[RIGHT_TOOLBAR], fb); + set_specifier_fallback (Vtoolbar_size[BOTTOM_EDGE], fb); + set_specifier_fallback (Vtoolbar_size[LEFT_EDGE], fb); + set_specifier_fallback (Vtoolbar_size[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("default-toolbar-border-width", &Vdefault_toolbar_border_width /* @@ -1786,67 +1787,67 @@ default_toolbar_border_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("top-toolbar-border-width", - &Vtoolbar_border_width[TOP_TOOLBAR] /* + &Vtoolbar_border_width[TOP_EDGE] /* *Border width of the top toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_border_width[TOP_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_border_width[TOP_TOOLBAR], + Vtoolbar_border_width[TOP_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_border_width[TOP_EDGE], offsetof (struct window, - toolbar_border_width[TOP_TOOLBAR]), + toolbar_border_width[TOP_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_border_width[TOP_TOOLBAR]), + toolbar_border_width[TOP_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("bottom-toolbar-border-width", - &Vtoolbar_border_width[BOTTOM_TOOLBAR] /* + &Vtoolbar_border_width[BOTTOM_EDGE] /* *Border width of the bottom toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_border_width[BOTTOM_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_border_width[BOTTOM_TOOLBAR], + Vtoolbar_border_width[BOTTOM_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_border_width[BOTTOM_EDGE], offsetof (struct window, - toolbar_border_width[BOTTOM_TOOLBAR]), + toolbar_border_width[BOTTOM_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_border_width[BOTTOM_TOOLBAR]), + toolbar_border_width[BOTTOM_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("left-toolbar-border-width", - &Vtoolbar_border_width[LEFT_TOOLBAR] /* + &Vtoolbar_border_width[LEFT_EDGE] /* *Border width of left toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_border_width[LEFT_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_border_width[LEFT_TOOLBAR], + Vtoolbar_border_width[LEFT_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_border_width[LEFT_EDGE], offsetof (struct window, - toolbar_border_width[LEFT_TOOLBAR]), + toolbar_border_width[LEFT_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_border_width[LEFT_TOOLBAR]), + toolbar_border_width[LEFT_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("right-toolbar-border-width", - &Vtoolbar_border_width[RIGHT_TOOLBAR] /* + &Vtoolbar_border_width[RIGHT_EDGE] /* *Border width of right toolbar. This is a specifier; use `set-specifier' to change it. See `default-toolbar-height' for more information. */ ); - Vtoolbar_border_width[RIGHT_TOOLBAR] = Fmake_specifier (Qnatnum); - set_specifier_caching (Vtoolbar_border_width[RIGHT_TOOLBAR], + Vtoolbar_border_width[RIGHT_EDGE] = Fmake_specifier (Qnatnum); + set_specifier_caching (Vtoolbar_border_width[RIGHT_EDGE], offsetof (struct window, - toolbar_border_width[RIGHT_TOOLBAR]), + toolbar_border_width[RIGHT_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_border_width[RIGHT_TOOLBAR]), + toolbar_border_width[RIGHT_EDGE]), frame_size_slipped, 0); fb = Qnil; @@ -1865,11 +1866,11 @@ if (!NILP (fb)) set_specifier_fallback (Vdefault_toolbar_border_width, fb); - set_specifier_fallback (Vtoolbar_border_width[TOP_TOOLBAR], Vdefault_toolbar_border_width); + set_specifier_fallback (Vtoolbar_border_width[TOP_EDGE], Vdefault_toolbar_border_width); fb = list1 (Fcons (Qnil, Qzero)); - set_specifier_fallback (Vtoolbar_border_width[BOTTOM_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar_border_width[LEFT_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar_border_width[RIGHT_TOOLBAR], fb); + set_specifier_fallback (Vtoolbar_border_width[BOTTOM_EDGE], fb); + set_specifier_fallback (Vtoolbar_border_width[LEFT_EDGE], fb); + set_specifier_fallback (Vtoolbar_border_width[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("default-toolbar-visible-p", &Vdefault_toolbar_visible_p /* *Whether the default toolbar is visible. @@ -1899,78 +1900,78 @@ default_toolbar_visible_p_changed_in_frame, 0); DEFVAR_SPECIFIER ("top-toolbar-visible-p", - &Vtoolbar_visible_p[TOP_TOOLBAR] /* + &Vtoolbar_visible_p[TOP_EDGE] /* *Whether the top toolbar is visible. This is a specifier; use `set-specifier' to change it. See `default-toolbar-visible-p' for more information. */ ); - Vtoolbar_visible_p[TOP_TOOLBAR] = Fmake_specifier (Qboolean); - set_specifier_caching (Vtoolbar_visible_p[TOP_TOOLBAR], + Vtoolbar_visible_p[TOP_EDGE] = Fmake_specifier (Qboolean); + set_specifier_caching (Vtoolbar_visible_p[TOP_EDGE], offsetof (struct window, - toolbar_visible_p[TOP_TOOLBAR]), + toolbar_visible_p[TOP_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_visible_p[TOP_TOOLBAR]), + toolbar_visible_p[TOP_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("bottom-toolbar-visible-p", - &Vtoolbar_visible_p[BOTTOM_TOOLBAR] /* + &Vtoolbar_visible_p[BOTTOM_EDGE] /* *Whether the bottom toolbar is visible. This is a specifier; use `set-specifier' to change it. See `default-toolbar-visible-p' for more information. */ ); - Vtoolbar_visible_p[BOTTOM_TOOLBAR] = Fmake_specifier (Qboolean); - set_specifier_caching (Vtoolbar_visible_p[BOTTOM_TOOLBAR], + Vtoolbar_visible_p[BOTTOM_EDGE] = Fmake_specifier (Qboolean); + set_specifier_caching (Vtoolbar_visible_p[BOTTOM_EDGE], offsetof (struct window, - toolbar_visible_p[BOTTOM_TOOLBAR]), + toolbar_visible_p[BOTTOM_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_visible_p[BOTTOM_TOOLBAR]), + toolbar_visible_p[BOTTOM_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("left-toolbar-visible-p", - &Vtoolbar_visible_p[LEFT_TOOLBAR] /* + &Vtoolbar_visible_p[LEFT_EDGE] /* *Whether the left toolbar is visible. This is a specifier; use `set-specifier' to change it. See `default-toolbar-visible-p' for more information. */ ); - Vtoolbar_visible_p[LEFT_TOOLBAR] = Fmake_specifier (Qboolean); - set_specifier_caching (Vtoolbar_visible_p[LEFT_TOOLBAR], + Vtoolbar_visible_p[LEFT_EDGE] = Fmake_specifier (Qboolean); + set_specifier_caching (Vtoolbar_visible_p[LEFT_EDGE], offsetof (struct window, - toolbar_visible_p[LEFT_TOOLBAR]), + toolbar_visible_p[LEFT_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_visible_p[LEFT_TOOLBAR]), + toolbar_visible_p[LEFT_EDGE]), frame_size_slipped, 0); DEFVAR_SPECIFIER ("right-toolbar-visible-p", - &Vtoolbar_visible_p[RIGHT_TOOLBAR] /* + &Vtoolbar_visible_p[RIGHT_EDGE] /* *Whether the right toolbar is visible. This is a specifier; use `set-specifier' to change it. See `default-toolbar-visible-p' for more information. */ ); - Vtoolbar_visible_p[RIGHT_TOOLBAR] = Fmake_specifier (Qboolean); - set_specifier_caching (Vtoolbar_visible_p[RIGHT_TOOLBAR], + Vtoolbar_visible_p[RIGHT_EDGE] = Fmake_specifier (Qboolean); + set_specifier_caching (Vtoolbar_visible_p[RIGHT_EDGE], offsetof (struct window, - toolbar_visible_p[RIGHT_TOOLBAR]), + toolbar_visible_p[RIGHT_EDGE]), toolbar_geometry_changed_in_window, offsetof (struct frame, - toolbar_visible_p[RIGHT_TOOLBAR]), + toolbar_visible_p[RIGHT_EDGE]), frame_size_slipped, 0); /* initially, top inherits from default; this can be changed with `set-default-toolbar-position'. */ fb = list1 (Fcons (Qnil, Qt)); set_specifier_fallback (Vdefault_toolbar_visible_p, fb); - set_specifier_fallback (Vtoolbar_visible_p[TOP_TOOLBAR], + set_specifier_fallback (Vtoolbar_visible_p[TOP_EDGE], Vdefault_toolbar_visible_p); - set_specifier_fallback (Vtoolbar_visible_p[BOTTOM_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar_visible_p[LEFT_TOOLBAR], fb); - set_specifier_fallback (Vtoolbar_visible_p[RIGHT_TOOLBAR], fb); + set_specifier_fallback (Vtoolbar_visible_p[BOTTOM_EDGE], fb); + set_specifier_fallback (Vtoolbar_visible_p[LEFT_EDGE], fb); + set_specifier_fallback (Vtoolbar_visible_p[RIGHT_EDGE], fb); DEFVAR_SPECIFIER ("toolbar-buttons-captioned-p", &Vtoolbar_buttons_captioned_p /*
--- a/src/toolbar.h Fri Feb 26 15:22:15 2010 +0000 +++ b/src/toolbar.h Fri Feb 26 15:24:58 2010 +0000 @@ -1,6 +1,6 @@ /* Define general toolbar support. Copyright (C) 1995 Board of Trustees, University of Illinois. - Copyright (C) 1995, 1996 Ben Wing. + Copyright (C) 1995, 1996, 2010 Ben Wing. Copyright (C) 1996 Chuck Thompson. This file is part of XEmacs. @@ -33,6 +33,11 @@ ((frame)->toolbar_buttons[pos]) #define FRAME_CURRENT_TOOLBAR_SIZE(frame, pos) \ ((frame)->current_toolbar_size[pos]) +#define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ + do { \ + (frame)->toolbar_was_visible[pos] = flag; \ + } while (0) + #define DEVICE_SUPPORTS_TOOLBARS_P(d) \ HAS_DEVMETH_P (d, output_frame_toolbars) @@ -76,7 +81,7 @@ #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) -void get_toolbar_coords (struct frame *f, enum toolbar_pos pos, int *x, +void get_toolbar_coords (struct frame *f, enum edge_pos pos, int *x, int *y, int *width, int *height, int *vert, int for_layout); Lisp_Object toolbar_button_at_pixpos (struct frame *f, int x_coord, @@ -106,7 +111,7 @@ void free_frame_toolbars (struct frame *f); Lisp_Object get_toolbar_button_glyph (struct window *w, struct toolbar_button *tb); -void mark_frame_toolbar_buttons_dirty (struct frame *f, enum toolbar_pos pos); +void mark_frame_toolbar_buttons_dirty (struct frame *f, enum edge_pos pos); #endif /* HAVE_TOOLBARS */
--- a/tests/automated/test-harness.el Fri Feb 26 15:22:15 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,840 +0,0 @@ -;; test-harness.el --- Run Emacs Lisp test suites. - -;;; Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. -;;; Copyright (C) 2002, 2010 Ben Wing. - -;; Author: Martin Buchholz -;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org> -;; Keywords: testing - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: Not in FSF. - -;;; Commentary: - -;;; A test suite harness for testing XEmacs. -;;; The actual tests are in other files in this directory. -;;; Basically you just create files of emacs-lisp, and use the -;;; Assert, Check-Error, Check-Message, and Check-Error-Message functions -;;; to create tests. See `test-harness-from-buffer' below. -;;; Don't suppress tests just because they're due to known bugs not yet -;;; fixed -- use the Known-Bug-Expect-Failure and -;;; Implementation-Incomplete-Expect-Failure wrapper macros to mark them. -;;; A lot of the tests we run push limits; suppress Ebola message with the -;;; Ignore-Ebola wrapper macro. -;;; Some noisy code will call `message'. Output from `message' can be -;;; suppressed with the Silence-Message macro. Functions that are known to -;;; issue messages include `write-region', `find-tag', `tag-loop-continue', -;;; `insert', and `mark-whole-buffer'. N.B. The Silence-Message macro -;;; currently does not suppress the newlines printed by `message'. -;;; Definitely do not use Silence-Message with Check-Message. -;;; In general it should probably only be used on code that prepares for a -;;; test, not on tests. -;;; -;;; You run the tests using M-x test-emacs-test-file, -;;; or $(EMACS) -batch -l .../test-harness.el -f batch-test-emacs file ... -;;; which is run for you by the `make check' target in the top-level Makefile. - -(require 'bytecomp) - -(defvar unexpected-test-suite-failures 0 - "Cumulative number of unexpected failures since test-harness was loaded. - -\"Unexpected failures\" are those caught by a generic handler established -outside of the test context. As such they involve an abort of the test -suite for the file being tested. - -They often occur during preparation of a test or recording of the results. -For example, an executable used to generate test data might not be present -on the system, or a system error might occur while reading a data file.") - -(defvar unexpected-test-suite-failure-files nil - "List of test files causing unexpected failures.") - -;; Declared for dynamic scope; _do not_ initialize here. -(defvar unexpected-test-file-failures) - -(defvar test-harness-bug-expected nil - "Non-nil means a bug is expected; backtracing/debugging should not happen.") - -(defvar test-harness-test-compiled nil - "Non-nil means the test code was compiled before execution. - -You probably should not make tests depend on compilation. -However, it can be useful to conditionally change messages based on whether -the code was compiled or not. For example, the case that motivated the -implementation of this variable: - -\(when test-harness-test-compiled - ;; this ha-a-ack depends on the failing compiled test coming last - \(setq test-harness-failure-tag - \"KNOWN BUG - fix reverted; after 2003-10-31 notify stephen\n\"))") - -(defvar test-harness-verbose - (and (not noninteractive) (> (device-baud-rate) search-slow-speed)) - "*Non-nil means print messages describing progress of emacs-tester.") - -(defvar test-harness-unexpected-error-enter-debugger debug-on-error - "*Non-nil means enter debugger when an unexpected error occurs. -Only applies interactively. Normally true if `debug-on-error' has been set. -See also `test-harness-assertion-failure-enter-debugger' and -`test-harness-unexpected-error-show-backtrace'.") - -(defvar test-harness-assertion-failure-enter-debugger debug-on-error - "*Non-nil means enter debugger when an assertion failure occurs. -Only applies interactively. Normally true if `debug-on-error' has been set. -See also `test-harness-unexpected-error-enter-debugger' and -`test-harness-assertion-failure-show-backtrace'.") - -(defvar test-harness-unexpected-error-show-backtrace t - "*Non-nil means show backtrace upon unexpected error. -Only applies when debugger is not entered. Normally true by default. See also -`test-harness-unexpected-error-enter-debugger' and -`test-harness-assertion-failure-show-backtrace'.") - -(defvar test-harness-assertion-failure-show-backtrace stack-trace-on-error - "*Non-nil means show backtrace upon assertion failure. -Only applies when debugger is not entered. Normally true if -`stack-trace-on-error' has been set. See also -`test-harness-assertion-failure-enter-debugger' and -`test-harness-unexpected-error-show-backtrace'.") - -(defvar test-harness-file-results-alist nil - "Each element is a list (FILE SUCCESSES TESTS). -The order is the reverse of the order in which tests are run. - -FILE is a string naming the test file. -SUCCESSES is a non-negative integer, the number of successes. -TESTS is a non-negative integer, the number of tests run.") - -(defvar test-harness-risk-infloops nil - "*Non-nil to run tests that may loop infinitely in buggy implementations.") - -(defvar test-harness-current-file nil) - -(defvar emacs-lisp-file-regexp (purecopy "\\.el\\'") - "*Regexp which matches Emacs Lisp source files.") - -(defconst test-harness-file-summary-template - (format "%%-%ds %%%dd of %%%dd tests successful (%%3d%%%%)." - (length "byte-compiler-tests.el:") ; use the longest file name - 5 - 5) - "Format for summary lines printed after each file is run.") - -(defconst test-harness-null-summary-template - (format "%%-%ds No tests run." - (length "byte-compiler-tests.el:")) ; use the longest file name - "Format for \"No tests\" lines printed after a file is run.") - -(defconst test-harness-aborted-summary-template - (format "%%-%ds %%%dd tests completed (aborted)." - (length "byte-compiler-tests.el:") ; use the longest file name - 5) - "Format for summary lines printed after a test run on a file was aborted.") - -;;;###autoload -(defun test-emacs-test-file (filename) - "Test a file of Lisp code named FILENAME. -The output file's name is made by appending `c' to the end of FILENAME." - (interactive - (let ((file buffer-file-name) - (file-name nil) - (file-dir nil)) - (and file - (eq (cdr (assq 'major-mode (buffer-local-variables))) - 'emacs-lisp-mode) - (setq file-name (file-name-nondirectory file) - file-dir (file-name-directory file))) - (list (read-file-name "Test file: " file-dir nil nil file-name)))) - ;; Expand now so we get the current buffer's defaults - (setq filename (expand-file-name filename)) - - ;; If we're testing a file that's in a buffer and is modified, offer - ;; to save it first. - (or noninteractive - (let ((b (get-file-buffer (expand-file-name filename)))) - (if (and b (buffer-modified-p b) - (y-or-n-p (format "save buffer %s first? " (buffer-name b)))) - (save-excursion (set-buffer b) (save-buffer))))) - - (if (or noninteractive test-harness-verbose) - (message "Testing %s..." filename)) - (let ((test-harness-current-file filename) - input-buffer) - (save-excursion - (setq input-buffer (get-buffer-create " *Test Input*")) - (set-buffer input-buffer) - (erase-buffer) - (insert-file-contents filename) - ;; Run hooks including the uncompression hook. - ;; If they change the file name, then change it for the output also. - (let ((buffer-file-name filename) - (default-major-mode 'emacs-lisp-mode) - (enable-local-eval nil)) - (normal-mode) - (setq filename buffer-file-name))) - (test-harness-from-buffer input-buffer filename) - (kill-buffer input-buffer) - )) - -(defsubst test-harness-assertion-failure-do-debug (error-info) - "Maybe enter debugger or display a backtrace on assertion failure. -ERROR-INFO is a cons of the args (SIG . DATA) that were passed to `signal'. -The debugger will be entered if noninteractive and -`test-harness-unexpected-error-enter-debugger' is non-nil; else, a -backtrace will be displayed if `test-harness-unexpected-error-show-backtrace' -is non-nil." - (when (not test-harness-bug-expected) - (cond ((and (not noninteractive) - test-harness-assertion-failure-enter-debugger) - (funcall debugger 'error error-info)) - (test-harness-assertion-failure-show-backtrace - (backtrace nil t))))) - -(defsubst test-harness-unexpected-error-do-debug (error-info) - "Maybe enter debugger or display a backtrace on unexpected error. -ERROR-INFO is a cons of the args (SIG . DATA) that were passed to `signal'. -The debugger will be entered if noninteractive and -`test-harness-unexpected-error-enter-debugger' is non-nil; else, a -backtrace will be displayed if `test-harness-unexpected-error-show-backtrace' -is non-nil." - (when (not test-harness-bug-expected) - (cond ((and (not noninteractive) - test-harness-unexpected-error-enter-debugger) - (funcall debugger 'error error-info)) - (test-harness-unexpected-error-show-backtrace - (backtrace nil t))))) - -(defsubst test-harness-unexpected-error-condition-handler (error-info context-msg) - "Condition handler for when unexpected errors occur. -Useful in conjunction with `call-with-condition-handler'. ERROR-INFO is the -value passed to the condition handler. CONTEXT-MSG is a string indicating -the context in which the unexpected error occurred. A message is outputted -including CONTEXT-MSG in it, `unexpected-test-file-failures' is incremented, -and `test-harness-unexpected-error-do-debug' is called, which may enter the -debugger or output a backtrace, depending on the settings of -`test-harness-unexpected-error-enter-debugger' and -`test-harness-unexpected-error-show-backtrace'. - -The function returns normally, which causes error-handling processing to -continue; if you want to catch the error, you also need to wrap everything -in `condition-case'. See also `test-harness-error-wrap', which does this -wrapping." - (incf unexpected-test-file-failures) - (princ (format "Unexpected error %S while %s\n" - error-info context-msg)) - (message "Unexpected error %S while %s." error-info context-msg) - (test-harness-unexpected-error-do-debug error-info)) - -(defmacro test-harness-error-wrap (context-msg abort-msg &rest body) - "Wrap BODY so that unexpected errors are caught. -The debugger will be entered if noninteractive and -`test-harness-unexpected-error-enter-debugger' is non-nil; else, a backtrace -will be displayed if `test-harness-unexpected-error-show-backtrace' is -non-nil. CONTEXT-MSG is displayed as part of a message shown before entering -the debugger or showing a backtrace, and ABORT-MSG, if non-nil, is displayed -afterwards. See " - `(condition-case nil - (call-with-condition-handler - #'(lambda (error-info) - (test-harness-unexpected-error-condition-handler - error-info ,context-msg)) - #'(lambda () - ,@body)) - (error ,(if abort-msg `(message ,abort-msg) nil)))) - -(defun test-harness-read-from-buffer (buffer) - "Read forms from BUFFER, and turn it into a lambda test form." - (let ((body nil)) - (goto-char (point-min) buffer) - (condition-case nil - (call-with-condition-handler - #'(lambda (error-info) - ;; end-of-file is expected, so don't output error or backtrace - ;; or enter debugger in this case. - (unless (eq 'end-of-file (car error-info)) - (test-harness-unexpected-error-condition-handler - error-info "reading forms from buffer"))) - #'(lambda () - (while t - (setq body (cons (read buffer) body))))) - (error nil)) - `(lambda () - (defvar passes) - (defvar assertion-failures) - (defvar no-error-failures) - (defvar wrong-error-failures) - (defvar missing-message-failures) - (defvar other-failures) - - (defvar trick-optimizer) - - ,@(nreverse body)))) - -(defun test-harness-from-buffer (inbuffer filename) - "Run tests in buffer INBUFFER, visiting FILENAME." - (defvar trick-optimizer) - (let ((passes 0) - (assertion-failures 0) - (no-error-failures 0) - (wrong-error-failures 0) - (missing-message-failures 0) - (other-failures 0) - (unexpected-test-file-failures 0) - - ;; #### perhaps this should be a defvar, and output at the very end - ;; OTOH, this way AC types can use a null EMACSPACKAGEPATH to find - ;; what stuff is needed, and ways to avoid using them - (skipped-test-reasons (make-hash-table :test 'equal)) - - (trick-optimizer nil) - (debug-on-error t) - ) - (with-output-to-temp-buffer "*Test-Log*" - (princ (format "Testing %s...\n\n" filename)) - - (defconst test-harness-failure-tag "FAIL") - (defconst test-harness-success-tag "PASS") - -;;;;; BEGIN DEFINITION OF MACROS USEFUL IN TEST CODE - - (defmacro Known-Bug-Expect-Failure (&rest body) - "Wrap a BODY that consists of tests that are known to fail. -This causes messages to be printed on failure indicating that this is expected, -and on success indicating that this is unexpected." - `(let ((test-harness-bug-expected t) - (test-harness-failure-tag "KNOWN BUG") - (test-harness-success-tag "PASS (FAILURE EXPECTED)")) - ,@body)) - - (defmacro Known-Bug-Expect-Error (expected-error &rest body) - "Wrap a BODY that consists of tests that are known to trigger an error. -This causes messages to be printed on failure indicating that this is expected, -and on success indicating that this is unexpected." - (let ((quoted-body (if (= 1 (length body)) - `(quote ,(car body)) `(quote (progn ,@body))))) - `(let ((test-harness-bug-expected t) - (test-harness-failure-tag "KNOWN BUG") - (test-harness-success-tag "PASS (FAILURE EXPECTED)")) - (condition-case error-info - (progn - (setq trick-optimizer (progn ,@body)) - (Print-Pass - "%S executed successfully, but expected error %S" - ,quoted-body - ',expected-error) - (incf passes)) - (,expected-error - (Print-Failure "%S ==> error %S, as expected" - ,quoted-body ',expected-error) - (incf no-error-failures)) - (error - (Print-Failure "%S ==> expected error %S, got error %S instead" - ,quoted-body ',expected-error error-info) - (incf wrong-error-failures)))))) - - (defmacro Implementation-Incomplete-Expect-Failure (&rest body) - "Wrap a BODY containing tests that are known to fail due to incomplete code. -This causes messages to be printed on failure indicating that the -implementation is incomplete (and hence the failure is expected); and on -success indicating that this is unexpected." - `(let ((test-harness-bug-expected t) - (test-harness-failure-tag "IMPLEMENTATION INCOMPLETE") - (test-harness-success-tag "PASS (FAILURE EXPECTED)")) - ,@body)) - - (defun Print-Failure (fmt &rest args) - (setq fmt (format "%s: %s" test-harness-failure-tag fmt)) - (if (noninteractive) (apply #'message fmt args)) - (princ (concat (apply #'format fmt args) "\n"))) - - (defun Print-Pass (fmt &rest args) - (setq fmt (format "%s: %s" test-harness-success-tag fmt)) - (and test-harness-verbose - (princ (concat (apply #'format fmt args) "\n")))) - - (defun Print-Skip (test reason &optional fmt &rest args) - (setq fmt (concat "SKIP: %S BECAUSE %S" fmt)) - (princ (concat (apply #'format fmt test reason args) "\n"))) - - (defmacro Skip-Test-Unless (condition reason description &rest body) - "Unless CONDITION is satisfied, skip test BODY. -REASON is a description of the condition failure, and must be unique (it -is used as a hash key). DESCRIPTION describes the tests that were skipped. -BODY is a sequence of expressions and may contain several tests." - `(if (not ,condition) - (let ((count (gethash ,reason skipped-test-reasons))) - (puthash ,reason (if (null count) 1 (1+ count)) - skipped-test-reasons) - (Print-Skip ,description ,reason)) - ,@body)) - - (defmacro Assert (assertion &optional failing-case description) - "Test passes if ASSERTION is true. -Optional FAILING-CASE describes the particular failure. Optional -DESCRIPTION describes the assertion; by default, the unevalated assertion -expression is given. FAILING-CASE and DESCRIPTION are useful when Assert -is used in a loop." - (let ((description - (or description `(quote ,assertion)))) - `(condition-case nil - (call-with-condition-handler - #'(lambda (error-info) - (if (eq 'cl-assertion-failed (car error-info)) - (progn - (Print-Failure - (if ,failing-case - "Assertion failed: %S; failing case = %S" - "Assertion failed: %S") - ,description ,failing-case) - (incf assertion-failures) - (test-harness-assertion-failure-do-debug error-info)) - (Print-Failure - (if ,failing-case - "%S ==> error: %S; failing case = %S" - "%S ==> error: %S") - ,description error-info ,failing-case) - (incf other-failures) - (test-harness-unexpected-error-do-debug error-info))) - #'(lambda () - (assert ,assertion) - (Print-Pass "%S" ,description) - (incf passes))) - (cl-assertion-failed nil)))) - -;;;;; BEGIN DEFINITION OF SPECIFIC KINDS OF ASSERT MACROS - - (defmacro Assert-test (test testval expected &optional failing-case - description) - "Test passes if TESTVAL compares correctly to EXPECTED using TEST. -TEST should be a two-argument predicate (i.e. a function of two arguments -that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=', -'>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the -particular failure; any value given here will be concatenated with a phrase -describing the expected and actual values of the comparison. Optional -DESCRIPTION describes the assertion; by default, the unevalated comparison -expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert -is used in a loop." - (let* ((assertion `(,test ,testval ,expected)) - (failmsg `(format "%S should be `%s' to %S but isn't" - ,testval ',test ,expected)) - (failmsg2 (if failing-case `(concat - (format "%S, " ,failing-case) - ,failmsg) - failmsg))) - `(Assert ,assertion ,failmsg2 ,description))) - - (defmacro Assert-test-not (test testval expected &optional failing-case - description) - "Test passes if TESTVAL does not compare correctly to EXPECTED using TEST. -TEST should be a two-argument predicate (i.e. a function of two arguments -that returns t or nil), such as `eq', `eql', `equal', `equalp', `=', `<=', -'>', 'file-newer-than-file-p' etc. Optional FAILING-CASE describes the -particular failure; any value given here will be concatenated with a phrase -describing the expected and actual values of the comparison. Optional -DESCRIPTION describes the assertion; by default, the unevalated comparison -expressions are given. FAILING-CASE and DESCRIPTION are useful when Assert -is used in a loop." - (let* ((assertion `(not (,test ,testval ,expected))) - (failmsg `(format "%S shouldn't be `%s' to %S but is" - ,testval ',test ,expected)) - (failmsg2 (if failing-case `(concat - (format "%S, " ,failing-case) - ,failmsg) - failmsg))) - `(Assert ,assertion ,failmsg2 ,description))) - - ;; Specific versions of `Assert-test'. These are just convenience - ;; functions, functioning identically to `Assert-test', and duplicating - ;; the doc string for each would be too annoying. - (defmacro Assert-eq (testval expected &optional failing-case - description) - `(Assert-test eq ,testval ,expected ,failing-case ,description)) - (defmacro Assert-eql (testval expected &optional failing-case - description) - `(Assert-test eql ,testval ,expected ,failing-case ,description)) - (defmacro Assert-equal (testval expected &optional failing-case - description) - `(Assert-test equal ,testval ,expected ,failing-case ,description)) - (defmacro Assert-equalp (testval expected &optional failing-case - description) - `(Assert-test equalp ,testval ,expected ,failing-case ,description)) - (defmacro Assert-string= (testval expected &optional failing-case - description) - `(Assert-test string= ,testval ,expected ,failing-case ,description)) - (defmacro Assert= (testval expected &optional failing-case - description) - `(Assert-test = ,testval ,expected ,failing-case ,description)) - (defmacro Assert<= (testval expected &optional failing-case - description) - `(Assert-test <= ,testval ,expected ,failing-case ,description)) - - ;; Specific versions of `Assert-test-not'. These are just convenience - ;; functions, functioning identically to `Assert-test-not', and - ;; duplicating the doc string for each would be too annoying. - (defmacro Assert-not-eq (testval expected &optional failing-case - description) - `(Assert-test-not eq ,testval ,expected ,failing-case ,description)) - (defmacro Assert-not-eql (testval expected &optional failing-case - description) - `(Assert-test-not eql ,testval ,expected ,failing-case ,description)) - (defmacro Assert-not-equal (testval expected &optional failing-case - description) - `(Assert-test-not equal ,testval ,expected ,failing-case ,description)) - (defmacro Assert-not-equalp (testval expected &optional failing-case - description) - `(Assert-test-not equalp ,testval ,expected ,failing-case ,description)) - (defmacro Assert-not-string= (testval expected &optional failing-case - description) - `(Assert-test-not string= ,testval ,expected ,failing-case ,description)) - (defmacro Assert-not= (testval expected &optional failing-case - description) - `(Assert-test-not = ,testval ,expected ,failing-case ,description)) - - (defmacro Check-Error (expected-error &rest body) - (let ((quoted-body (if (= 1 (length body)) - `(quote ,(car body)) `(quote (progn ,@body))))) - `(condition-case error-info - (progn - (setq trick-optimizer (progn ,@body)) - (Print-Failure "%S executed successfully, but expected error %S" - ,quoted-body - ',expected-error) - (incf no-error-failures)) - (,expected-error - (Print-Pass "%S ==> error %S, as expected" - ,quoted-body ',expected-error) - (incf passes)) - (error - (Print-Failure "%S ==> expected error %S, got error %S instead" - ,quoted-body ',expected-error error-info) - (incf wrong-error-failures))))) - - (defmacro Check-Error-Message (expected-error expected-error-regexp - &rest body) - (let ((quoted-body (if (= 1 (length body)) - `(quote ,(car body)) `(quote (progn ,@body))))) - `(condition-case error-info - (progn - (setq trick-optimizer (progn ,@body)) - (Print-Failure "%S executed successfully, but expected error %S" - ,quoted-body ',expected-error) - (incf no-error-failures)) - (,expected-error - ;; #### Damn, this binding doesn't capture frobs, eg, for - ;; invalid_argument() ... you only get the REASON. And for - ;; wrong_type_argument(), there's no reason only FROBs. - ;; If this gets fixed, fix tests in regexp-tests.el. - (let ((error-message (second error-info))) - (if (string-match ,expected-error-regexp error-message) - (progn - (Print-Pass "%S ==> error %S %S, as expected" - ,quoted-body error-message ',expected-error) - (incf passes)) - (Print-Failure "%S ==> got error %S as expected, but error message %S did not match regexp %S" - ,quoted-body ',expected-error error-message ,expected-error-regexp) - (incf wrong-error-failures)))) - (error - (Print-Failure "%S ==> expected error %S, got error %S instead" - ,quoted-body ',expected-error error-info) - (incf wrong-error-failures))))) - - ;; Do not use this with Silence-Message. - (defmacro Check-Message (expected-message-regexp &rest body) - (Skip-Test-Unless (fboundp 'defadvice) - "can't defadvice" - expected-message-regexp - (let ((quoted-body (if (= 1 (length body)) - `(quote ,(car body)) - `(quote (progn ,@body))))) - `(let ((messages "")) - (defadvice message (around collect activate) - (defvar messages) - (let ((msg-string (apply 'format (ad-get-args 0)))) - (setq messages (concat messages msg-string)) - msg-string)) - (ignore-errors - (call-with-condition-handler - #'(lambda (error-info) - (Print-Failure "%S ==> unexpected error %S" - ,quoted-body error-info) - (incf other-failures) - (test-harness-unexpected-error-do-debug error-info)) - #'(lambda () - (setq trick-optimizer (progn ,@body)) - (if (string-match ,expected-message-regexp messages) - (progn - (Print-Pass - "%S ==> value %S, message %S, matching %S, as expected" - ,quoted-body trick-optimizer messages - ',expected-message-regexp) - (incf passes)) - (Print-Failure - "%S ==> value %S, message %S, NOT matching expected %S" - ,quoted-body trick-optimizer messages - ',expected-message-regexp) - (incf missing-message-failures))))) - (ad-unadvise 'message))))) - - ;; #### Perhaps this should override `message' itself, too? - (defmacro Silence-Message (&rest body) - `(flet ((append-message (&rest args) ()) - (clear-message (&rest args) ())) - ,@body)) - - (defmacro Ignore-Ebola (&rest body) - `(let ((debug-issue-ebola-notices -42)) ,@body)) - - (defun Int-to-Marker (pos) - (save-excursion - (set-buffer standard-output) - (save-excursion - (goto-char pos) - (point-marker)))) - - (princ "Testing Interpreted Lisp\n\n") - - (test-harness-error-wrap - "executing interpreted code" - "Test suite execution aborted." - (funcall (test-harness-read-from-buffer inbuffer))) - - (princ "\nTesting Compiled Lisp\n\n") - - (let (code - (test-harness-test-compiled t)) - (test-harness-error-wrap - "byte-compiling code" nil - (setq code - ;; our lisp code is often intentionally dubious, - ;; so throw away _all_ the byte compiler warnings. - (letf (((symbol-function 'byte-compile-warn) - 'ignore)) - (byte-compile (test-harness-read-from-buffer - inbuffer)))) - ) - - (test-harness-error-wrap "executing byte-compiled code" - "Test suite execution aborted." - (if code (funcall code))) - ) - (princ (format "\nSUMMARY for %s:\n" filename)) - (princ (format "\t%5d passes\n" passes)) - (princ (format "\t%5d assertion failures\n" assertion-failures)) - (princ (format "\t%5d errors that should have been generated, but weren't\n" no-error-failures)) - (princ (format "\t%5d wrong-error failures\n" wrong-error-failures)) - (princ (format "\t%5d missing-message failures\n" missing-message-failures)) - (princ (format "\t%5d other failures\n" other-failures)) - (let* ((total (+ passes - assertion-failures - no-error-failures - wrong-error-failures - missing-message-failures - other-failures)) - (basename (file-name-nondirectory filename)) - (summary-msg - (cond ((> unexpected-test-file-failures 0) - (format test-harness-aborted-summary-template - (concat basename ":") total)) - ((> total 0) - (format test-harness-file-summary-template - (concat basename ":") - passes total (/ (* 100 passes) total))) - (t - (format test-harness-null-summary-template - (concat basename ":"))))) - (reasons "")) - (maphash (lambda (key value) - (setq reasons - (concat reasons - (format "\n %d tests skipped because %s." - value key)))) - skipped-test-reasons) - (when (> (length reasons) 1) - (setq summary-msg (concat summary-msg reasons " - It may be that XEmacs cannot find your installed packages. Set - EMACSPACKAGEPATH to the package hierarchy root or configure with - --package-path to enable the skipped tests."))) - (setq test-harness-file-results-alist - (cons (list filename passes total) - test-harness-file-results-alist)) - (message "%s" summary-msg)) - (when (> unexpected-test-file-failures 0) - (setq unexpected-test-suite-failure-files - (cons filename unexpected-test-suite-failure-files)) - (setq unexpected-test-suite-failures - (+ unexpected-test-suite-failures unexpected-test-file-failures)) - (message "Test suite execution failed unexpectedly.")) - (fmakunbound 'Assert) - (fmakunbound 'Check-Error) - (fmakunbound 'Check-Message) - (fmakunbound 'Check-Error-Message) - (fmakunbound 'Ignore-Ebola) - (fmakunbound 'Int-to-Marker) - (and noninteractive - (message "%s" (buffer-substring-no-properties - nil nil "*Test-Log*"))) - ))) - -(defvar test-harness-results-point-max nil) -(defmacro displaying-emacs-test-results (&rest body) - `(let ((test-harness-results-point-max test-harness-results-point-max)) - ;; Log the file name. - (test-harness-log-file) - ;; Record how much is logged now. - ;; We will display the log buffer if anything more is logged - ;; before the end of BODY. - (or test-harness-results-point-max - (save-excursion - (set-buffer (get-buffer-create "*Test-Log*")) - (setq test-harness-results-point-max (point-max)))) - (unwind-protect - (condition-case error-info - (progn ,@body) - (error - (test-harness-report-error error-info))) - (save-excursion - ;; If there were compilation warnings, display them. - (set-buffer "*Test-Log*") - (if (= test-harness-results-point-max (point-max)) - nil - (if temp-buffer-show-function - (let ((show-buffer (get-buffer-create "*Test-Log-Show*"))) - (save-excursion - (set-buffer show-buffer) - (setq buffer-read-only nil) - (erase-buffer)) - (copy-to-buffer show-buffer - (save-excursion - (goto-char test-harness-results-point-max) - (forward-line -1) - (point)) - (point-max)) - (funcall temp-buffer-show-function show-buffer)) - (select-window - (prog1 (selected-window) - (select-window (display-buffer (current-buffer))) - (goto-char test-harness-results-point-max) - (recenter 1))))))))) - -(defun batch-test-emacs-1 (file) - (condition-case error-info - (progn (test-emacs-test-file file) t) - (error - (princ ">>Error occurred processing ") - (princ file) - (princ ": ") - (display-error error-info nil) - (terpri) - nil))) - -(defun batch-test-emacs () - "Run `test-harness' on the files remaining on the command line. -Use this from the command line, with `-batch'; -it won't work in an interactive Emacs. -Each file is processed even if an error occurred previously. -A directory can be given as well, and all files will be processed -- -however, the file test-harness.el, which implements the test harness, -will be skipped. -For example, invoke \"xemacs -batch -f batch-test-emacs tests\"" - ;; command-line-args-left is what is left of the command line (from - ;; startup.el) - (defvar command-line-args-left) ;Avoid 'free variable' warning - (defvar debug-issue-ebola-notices) - (if (not noninteractive) - (error "`batch-test-emacs' is to be used only with -batch")) - (let ((error nil)) - (dolist (file command-line-args-left) - (if (file-directory-p file) - (dolist (file-in-dir (directory-files file t)) - (when (and (string-match emacs-lisp-file-regexp file-in-dir) - (not (or (auto-save-file-name-p file-in-dir) - (backup-file-name-p file-in-dir) - (equal (file-name-nondirectory file-in-dir) - "test-harness.el")))) - (or (batch-test-emacs-1 file-in-dir) - (setq error t)))) - (or (batch-test-emacs-1 file) - (setq error t)))) - (let ((namelen 0) - (succlen 0) - (testlen 0) - (results test-harness-file-results-alist)) - ;; compute maximum lengths of variable components of report - ;; probably should just use (length "byte-compiler-tests.el") - ;; and 5-place sizes -- this will also work for the file-by-file - ;; printing when Adrian's kludge gets reverted - (flet ((print-width (i) - (let ((x 10) (y 1)) - (while (>= i x) - (setq x (* 10 x) y (1+ y))) - y))) - (while results - (let* ((head (car results)) - (nn (length (file-name-nondirectory (first head)))) - (ss (print-width (second head))) - (tt (print-width (third head)))) - (when (> nn namelen) (setq namelen nn)) - (when (> ss succlen) (setq succlen ss)) - (when (> tt testlen) (setq testlen tt))) - (setq results (cdr results)))) - ;; create format and print - (let ((results (reverse test-harness-file-results-alist))) - (while results - (let* ((head (car results)) - (basename (file-name-nondirectory (first head))) - (nsucc (second head)) - (ntest (third head))) - (cond ((member (first head) unexpected-test-suite-failure-files) - (message test-harness-aborted-summary-template - (concat basename ":") - ntest)) - ((> ntest 0) - (message test-harness-file-summary-template - (concat basename ":") - nsucc - ntest - (/ (* 100 nsucc) ntest))) - (t - (message test-harness-null-summary-template - (concat basename ":")))) - (setq results (cdr results))))) - (when (> unexpected-test-suite-failures 0) - (message "\n***** There %s %d unexpected test suite %s in %s:" - (if (= unexpected-test-suite-failures 1) "was" "were") - unexpected-test-suite-failures - (if (= unexpected-test-suite-failures 1) "failure" "failures") - (if (= (length unexpected-test-suite-failure-files) 1) - "file" - "files")) - (while unexpected-test-suite-failure-files - (let ((line (pop unexpected-test-suite-failure-files))) - (while (and (< (length line) 61) - unexpected-test-suite-failure-files) - (setq line - (concat line " " - (pop unexpected-test-suite-failure-files)))) - (message line))))) - (message "\nDone") - (kill-emacs (if error 1 0)))) - -(provide 'test-harness) - -;;; test-harness.el ends here