changeset 83066:887bb2eb4a89

Merged in changes from CVS HEAD Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-116 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-117 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-106
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 28 Feb 2004 01:33:17 +0000
parents a871be7b26a5 (current diff) 6c8849d06ab3 (diff)
children b44978264e1d
files lisp/ChangeLog src/dispextern.h src/emacs.c src/keyboard.c src/macterm.c src/macterm.h
diffstat 14 files changed, 3415 insertions(+), 1430 deletions(-) [+]
line wrap: on
line diff
--- a/admin/make-tarball.txt	Sat Feb 28 01:23:39 2004 +0000
+++ b/admin/make-tarball.txt	Sat Feb 28 01:33:17 2004 +0000
@@ -1,5 +1,6 @@
 Instructions to create pretest or release tarballs.
--- originally written by Eli Zaretskii, amended by Francesco Potort́
+-- originally written by Gerd Moellmann, amended by Francesco Potort́
+   with the initial help of Eli Zaretskii
 
 For each step, check for possible errors.
 
--- a/lisp/ChangeLog	Sat Feb 28 01:23:39 2004 +0000
+++ b/lisp/ChangeLog	Sat Feb 28 01:33:17 2004 +0000
@@ -1,3 +1,13 @@
+2004-02-25  Vinicius Jose Latorre  <viniciusjl@ig.com.br>
+
+	* ebnf2ps.el: Doc fix.  For compatibility with Emacs 20, define
+	assq-delete-all if it's not defined.
+	(ebnf-generate-region): Code fix.
+
+	* printing.el: Doc fix.
+	(pr-version): New version number (6.7.2).
+	(pr-command): Return empty string if command is an empty string.
+
 2004-02-24  Vinicius Jose Latorre  <viniciusjl@ig.com.br>
 
 	* ebnf-abn.el: New file, implements an ABNF parser.
--- a/lisp/printing.el	Sat Feb 28 01:23:39 2004 +0000
+++ b/lisp/printing.el	Sat Feb 28 01:33:17 2004 +0000
@@ -1,17 +1,17 @@
 ;;; printing.el --- printing utilities
 
-;; Copyright (C) 2000, 2001, 2002, 2003
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004
 ;; Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br>
 ;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;; Time-stamp: <2004/02/26 00:43:07 vinicius>
 ;; Keywords: wp, print, PostScript
-;; Time-stamp: <2002/09/11 16:59:00 vinicius>
-;; Version: 6.7.1
+;; Version: 6.7.2
 ;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/
 
-(defconst pr-version "6.7.1"
-  "printing.el, v 6.7.1 <2002/09/11 vinicius>
+(defconst pr-version "6.7.2"
+  "printing.el, v 6.7.2 <2004/02/26 vinicius>
 
 Please send all bug fixes and enhancements to
 	Vinicius Jose Latorre <vinicius@cpqd.com.br>
@@ -255,9 +255,9 @@
 ;;    PREFIX:
 ;;    `pr-interface'	buffer interface for printing package.
 ;;    `pr-help'		help for printing package.
-;;    `pr-ps-name'	select interactively a PostScript printer.
-;;    `pr-txt-name'	select interactively a text printer.
-;;    `pr-ps-utility'	select interactively a PostScript utility.
+;;    `pr-ps-name'	interactively select a PostScript printer.
+;;    `pr-txt-name'	interactively select a text printer.
+;;    `pr-ps-utility'	interactively select a PostScript utility.
 ;;    `pr-show-*-setup'	show current settings.
 ;;    `pr-ps-*'		deal with PostScript code generation.
 ;;    `pr-txt-*'	deal with text generation.
@@ -381,9 +381,11 @@
 ;;
 ;; `pr-ps-temp-file'		Specify PostScript temporary file name.
 ;;
-;; `pr-gv-command'		Specify path and name of gsview program.
-;;
-;; `pr-gs-command'		Specify path and name of ghostscript program.
+;; `pr-gv-command'		Specify path and name of the gsview/gv
+;;				utility.
+;;
+;; `pr-gs-command'		Specify path and name of the ghostscript
+;;				utility.
 ;;
 ;; `pr-gs-switches'		Specify ghostscript switches.
 ;;
@@ -408,8 +410,8 @@
 ;;
 ;; `pr-auto-region'		Non-nil means region is automagically detected.
 ;;
-;; `pr-auto-mode'		Non-nil means major-mode printing is prefered
-;;				over normal printing.
+;; `pr-auto-mode'		Non-nil means major-mode specific printing is
+;;				prefered over normal printing.
 ;;
 ;; `pr-mode-alist'		Specify an alist for a major-mode and printing
 ;;				function.
@@ -526,8 +528,8 @@
 ;;     15 |   Print All Pages          >|--\ |  |Mode     |   +------------+
 ;;        +-----------------------------+  | |  +---------+   |[ ]Landscape| Id
 ;; IV  16 |[ ]Spool Buffer              |  | |  +-C-------+   |[ ]Duplex   | Ie
-;;     17 |[ ]Print with-faces          |  | \--|( )name A|   |[ ]Tumble   | If
-;;     18 |[ ]Print Using Ghostscript   |  |    |( )name B|   +------------+
+;;     17 |[ ]Print with faces          |  | \--|( )name A|   |[ ]Tumble   | If
+;;     18 |[ ]Print via Ghostscript     |  |    |( )name B|   +------------+
 ;;        +-----------------------------+  |    |...      |
 ;; V   19 |[ ]Auto Region               |  |    |(*)name  |
 ;;     20 |[ ]Auto Mode                 |  |    |...      |
@@ -690,7 +692,7 @@
 ;;	  declared in `pr-mode-alist', the `*-buffer*' and `*-region*' commands
 ;;	  behave like `*-mode*' commands.
 ;;
-;;    21. If you want that Printing menu stays poped up while you are setting
+;;    21. If you want that Printing menu stays open while you are setting
 ;;	  toggle options, turn on this option.  The variables
 ;;	  `pr-menu-char-height' and `pr-menu-char-width' are used to guess the
 ;;	  menu position, so don't forget to adjust these variables if menu
@@ -1157,9 +1159,9 @@
 			'prt_06a
 			'my_printer
 
-COMMAND		Name of program for printing a text file.  On MS-DOS and
-		MS-Windows systems, if the value is an empty string then Emacs
-		will write directly to the printer port named by NAME (see text
+COMMAND		Name of the program for printing a text file.  On MS-DOS and
+		MS-Windows systems, if the value is an empty string, then Emacs
+		will write directly to the printer port given by NAME (see text
 		below), that is, the NAME should be something like \"PRN\" or
 		\"LPT1:\".
 		If NAME is something like \"\\\\\\\\host\\\\share-name\" then
@@ -1287,11 +1289,11 @@
 			'prt_06a
 			'my_printer
 
-COMMAND		Name of program for printing a PostScript file.  On MS-DOS and
-		MS-Windows systems, if the value is an empty string then Emacs
-		will write directly to the printer port named by NAME (see text
-		below), that is, the NAME should be something like \"PRN\" or
-		\"LPT1:\".
+COMMAND		Name of the program for printing a PostScript file.  On MS-DOS
+		and MS-Windows systems, if the value is an empty string then
+		Emacs will write directly to the printer port given by NAME
+		(see text below), that is, the NAME should be something like
+		\"PRN\" or \"LPT1:\".
 		If NAME is something like \"\\\\\\\\host\\\\share-name\" then
 		COMMAND shouldn't be an empty string.
 		The programs `print' and `nprint' (the standard print programs
@@ -1472,10 +1474,10 @@
   (if ps-windows-system
       "gsview32.exe"
     "gv")
-  "*Specify path and name of gsview program.
+  "*Specify path and name of the gsview/gv utility.
 
 See also `pr-path-alist'."
-  :type '(string :tag "Ghostview Program")
+  :type '(string :tag "Ghostview Utility")
   :group 'printing)
 
 
@@ -1483,10 +1485,10 @@
   (if ps-windows-system
       "gswin32.exe"
     "gs")
-  "*Specify path and name of ghostscript program.
+  "*Specify path and name of the ghostscript utility.
 
 See also `pr-path-alist'."
-  :type '(string :tag "Ghostscript Program")
+  :type '(string :tag "Ghostscript Utility")
   :group 'printing)
 
 
@@ -1524,7 +1526,7 @@
   (if ps-windows-system
       "mswinpr2"
     "uniprint")
-  "*Specify ghostscript device switch value (-sDEVICE=).
+  "*Specify the ghostscript device switch value (-sDEVICE=).
 
 A note on the gs switches:
 
@@ -1609,7 +1611,7 @@
 
 
 (defcustom pr-auto-mode t
-  "*Non-nil means major-mode printing is prefered over normal printing.
+  "*Non-nil means major-mode specific printing is prefered over normal printing.
 
 That is, if current major-mode is declared in `pr-mode-alist', the `*-buffer*'
 and `*-region*' commands will behave like `*-mode*' commands; otherwise,
@@ -1876,9 +1878,9 @@
 		    . for Windows system:
 			\"c:/psutils/psnup -q\"
 
-MUST-SWITCHES	List of sexp's to pass as options for PostScript utility
+MUST-SWITCHES	List of sexp's to pass as options to the PostScript utility
 		program.  These options are necessary to process the utility
-		program and must be place before any other switches.
+		program and must be placed before any other switches.
 		Example:
 		    . for psnup:
 			'(\"-q\")
@@ -1921,7 +1923,7 @@
 		    . for mpage
 			\">\" ; mpage ... input > output
 
-SWITCHES	List of sexp's to pass as extra options for PostScript utility
+SWITCHES	List of sexp's to pass as extra options to the PostScript utility
 		program.
 		Example:
 		    . for psnup
@@ -2202,8 +2204,8 @@
 			      |    Print All Pages          >|
 			      +------------------------------+
    `postscript-process'	      |[ ] Spool Buffer              |
-			      |[ ] Print with-faces          |
-			      |[ ] Print Using Ghostscript   |
+			      |[ ] Print with faces          |
+			      |[ ] Print via Ghostscript     |
 			      +------------------------------+
    `printing'		      |[ ] Auto Region               |
 			      |[ ] Auto Mode                 |
@@ -2299,7 +2301,7 @@
 
 
 (defvar pr-txt-switches nil
-  "List of sexp's to pass as extra options for text printer program.
+  "List of sexp's to pass as extra options to the text printer program.
 See `pr-txt-printer-alist'.")
 
 
@@ -2314,7 +2316,7 @@
 
 
 (defvar pr-ps-switches nil
-  "List of sexp's to pass as extra options for PostScript printer program.
+  "List of sexp's to pass as extra options to the PostScript printer program.
 See `pr-ps-printer-alist'.")
 
 
@@ -2556,11 +2558,11 @@
 	 :style toggle :selected pr-spool-p
 	 :included (pr-visible-p 'postscript-process)
 	 :help "Toggle PostScript spooling"]
-	["Print with-faces"        pr-toggle-faces
+	["Print with faces"        pr-toggle-faces
 	 :style toggle :selected pr-faces-p
 	 :included (pr-visible-p 'postscript-process)
 	 :help "Toggle PostScript printing with faces"]
-	["Print Using Ghostscript" pr-toggle-ghostscript
+	["Print via Ghostscript" pr-toggle-ghostscript
 	 :style toggle :selected pr-print-using-ghostscript
 	 :included (pr-visible-p 'postscript-process)
 	 :help "Toggle PostScript generation using ghostscript"]
@@ -2746,10 +2748,10 @@
 	["Spool Buffer"            pr-toggle-spool
 	 :style toggle :selected pr-spool-p
 	 :included (pr-visible-p 'postscript-process)]
-	["Print with-faces"        pr-toggle-faces
+	["Print with faces"        pr-toggle-faces
 	 :style toggle :selected pr-faces-p
 	 :included (pr-visible-p 'postscript-process)]
-	["Print Using Ghostscript" pr-toggle-ghostscript
+	["Print via Ghostscript" pr-toggle-ghostscript
 	 :style toggle :selected pr-print-using-ghostscript
 	 :included (pr-visible-p 'postscript-process)]
 	"--"
@@ -2870,8 +2872,8 @@
     15 |   Print All Pages          >|--\\ |  |Mode     |   +------------+
        +-----------------------------+  | |  +---------+   |[ ]Landscape| Id
 IV  16 |[ ]Spool Buffer              |  | |  +-C-------+   |[ ]Duplex   | Ie
-    17 |[ ]Print with-faces          |  | \\--|( )name A|   |[ ]Tumble   | If
-    18 |[ ]Print Using Ghostscript   |  |    |( )name B|   +------------+
+    17 |[ ]Print with faces          |  | \\--|( )name A|   |[ ]Tumble   | If
+    18 |[ ]Print via Ghostscript     |  |    |( )name B|   +------------+
        +-----------------------------+  |    |...      |
 V   19 |[ ]Auto Region               |  |    |(*)name  |
     20 |[ ]Auto Mode                 |  |    |...      |
@@ -2945,9 +2947,9 @@
       save temporarily the PostScript code generated in a buffer and print it
       later.  The option `Despool...' despools the PostScript spooling buffer
       directly on a printer.  If you type C-u before choosing this option,
-      the PostScript code generated is saved in a file instead of sending to
-      printer.  To spool the PostScript code generated you need to turn on
-      the option 16.  This option is enabled if spooling is on (option 16).
+      the PostScript code generated is saved in a file instead of sending it to
+      the printer.  To spool the PostScript code generated you need to turn on
+      option 16.  This option is enabled if spooling is on (option 16).
       See also the NOTE 1, NOTE 2 and NOTE 3 on option 1.
 
    3. You can select a new PostScript printer to send PostScript code
@@ -3032,7 +3034,7 @@
        declared in `pr-mode-alist', the `*-buffer*' and `*-region*' commands
        behave like `*-mode*' commands.
 
-   21. If you want that Printing menu stays poped while you are setting
+   21. If you want that Printing menu stays open while you are setting
        toggle options, turn on this option.  The variables
        `pr-menu-char-height' and `pr-menu-char-width' are used to guess the
        menu position, so don't forget to adjust these variables if menu
@@ -3237,7 +3239,7 @@
 	 behave like `*-mode*' commands.
 
       * Menu Lock:
-	 If you want that Printing menu stays poped while you are setting
+	 If you want that Printing menu stays open while you are setting
 	 toggle options, turn on this option.  The variables
 	 `pr-menu-char-height' and `pr-menu-char-width' are used to guess the
 	 menu position, so don't forget to adjust these variables if menu
@@ -3247,13 +3249,13 @@
 	 To spool the PostScript code generated.  You can despool later by
 	 setting Despool option on PostScript printer section.
 
-      * Print with-faces:
+      * Print with faces:
 	 If you use colors in your buffers and want to see these colors on your
 	 PostScript code generated, turn on this option.  If you have a
 	 black/white PostScript printer, these colors are displayed in gray
 	 scale by PostScript printer interpreter.
 
-      * Print Using Ghostscript:
+      * Print via Ghostscript:
 	 If you don't have a PostScript printer to send PostScript files, turn
 	 on this option.  When this option is on, the ghostscript is used to
 	 print PostScript files.  In GNU or Unix system, if ghostscript is set
@@ -3294,9 +3296,9 @@
 (defun pr-interface (&optional buffer)
   "Activate the printing interface buffer.
 
-If BUFFER is nil, it uses the current buffer for printing.
-
-For more informations, type \\[pr-interface-help]."
+If BUFFER is nil, the current buffer is used for printing.
+
+For more information, type \\[pr-interface-help]."
   (interactive)
   (save-excursion
     (set-buffer (or buffer (current-buffer)))
@@ -3799,7 +3801,7 @@
   (and (stringp filename) (file-exists-p filename)
        ;; printing
        (let ((file (pr-expand-file-name filename)))
-	 (if (string-equal pr-ps-command "")
+	 (if (string= pr-ps-command "")
 	     (let ((ps-spool-buffer (get-buffer-create ps-spool-buffer-name)))
 	       (save-excursion
 		 (set-buffer ps-spool-buffer)
@@ -3901,7 +3903,7 @@
 (defun pr-toggle-faces ()
   "Toggle printing with faces."
   (interactive)
-  (pr-toggle 'pr-faces-p "Printing with-faces"
+  (pr-toggle 'pr-faces-p "Printing with faces"
 	     'postscript-process 1 12 'toggle))
 
 
@@ -4008,28 +4010,28 @@
 
 ;;;###autoload
 (defun pr-customize (&rest ignore)
-  "Customization of `printing' group."
+  "Customization of the `printing' group."
   (interactive)
   (customize-group 'printing))
 
 
 ;;;###autoload
 (defun lpr-customize (&rest ignore)
-  "Customization of `lpr' group."
+  "Customization of the `lpr' group."
   (interactive)
   (customize-group 'lpr))
 
 
 ;;;###autoload
 (defun pr-help (&rest ignore)
-  "Help for printing package."
+  "Help for the printing package."
   (interactive)
   (pr-show-setup pr-help-message "*Printing Help*"))
 
 
 ;;;###autoload
 (defun pr-ps-name ()
-  "Select interactively a PostScript printer."
+  "Interactively select a PostScript printer."
   (interactive)
   (pr-menu-set-ps-title
    (pr-complete-alist "PostScript printer" pr-ps-printer-alist pr-ps-name)))
@@ -4037,7 +4039,7 @@
 
 ;;;###autoload
 (defun pr-txt-name ()
-  "Select interactively a text printer."
+  "Interactively select a text printer."
   (interactive)
   (pr-menu-set-txt-title
    (pr-complete-alist "Text printer" pr-txt-printer-alist pr-txt-name)))
@@ -4045,7 +4047,7 @@
 
 ;;;###autoload
 (defun pr-ps-utility ()
-  "Select interactively a PostScript utility."
+  "Interactively select a PostScript utility."
   (interactive)
   (pr-menu-set-utility-title
    (pr-complete-alist "Postscript utility" pr-ps-utility-alist pr-ps-utility)))
@@ -4527,6 +4529,10 @@
   (+ index 2))
 
 
+(defvar pr-menu-position nil)
+(defvar pr-menu-state nil)
+
+
 (eval-and-compile
   (cond
    ((eq ps-print-emacs-type 'xemacs)
@@ -4560,60 +4566,55 @@
 	       (- (cdr pos)		; Y
 		  (* (pr-menu-index entry index) pr-menu-char-height)))
 	 (selected-frame))))		; frame
-    )))
-
-
-(defvar pr-menu-position nil)
-(defvar pr-menu-state nil)
-
-
-(cond
- ((eq ps-print-emacs-type 'emacs)
-  ;; GNU Emacs
-  (defun pr-menu-lock (entry index horizontal state path)
-    (when (and (not (interactive-p)) pr-menu-lock)
-      (or (and pr-menu-position (eq state pr-menu-state))
-	  (setq pr-menu-position (pr-menu-position entry index horizontal)
-		pr-menu-state    state))
-      (let* ((menu   (pr-menu-lookup path))
-	     (result (x-popup-menu pr-menu-position menu)))
-	(and result
-	     (let ((command (lookup-key menu (vconcat result))))
-	       (if (fboundp command)
-		   (funcall command)
-		 (eval command)))))
-      (setq pr-menu-position nil)))
-
-  ;; GNU Emacs
-  (defun pr-menu-lookup (path)
-    (let ((ipath pr-menu-bar))
-      (lookup-key global-map
-		  (if path
-		      (vconcat ipath
-			       (mapcar 'pr-get-symbol
-				       (if (listp path)
-					   path
-					 (list path))))
-		    ipath)))))
-
-
- ((eq ps-print-emacs-type 'xemacs)
-  ;; XEmacs
-  (defun pr-menu-lock (entry index horizontal state path)
-    (when (and (not (interactive-p)) pr-menu-lock)
-      (or (and pr-menu-position (eq state pr-menu-state))
-	  (setq pr-menu-position (pr-menu-position entry index horizontal)
-		pr-menu-state    state))
-      (let* ((menu   (pr-menu-lookup path))
-	     (result (pr-x-get-popup-menu-response menu pr-menu-position)))
-	(and (pr-x-misc-user-event-p result)
-	     (funcall (pr-x-event-function result)
-		      (pr-x-event-object result))))
-      (setq pr-menu-position nil)))
-
-  ;; XEmacs
-  (defun pr-menu-lookup (path)
-    (car (pr-x-find-menu-item current-menubar (cons "Printing" path))))))
+    ))
+
+  (cond
+   ((eq ps-print-emacs-type 'emacs)
+    ;; GNU Emacs
+    (defun pr-menu-lookup (path)
+      (let ((ipath pr-menu-bar))
+	(lookup-key global-map
+		    (if path
+			(vconcat ipath
+				 (mapcar 'pr-get-symbol
+					 (if (listp path)
+					     path
+					   (list path))))
+		      ipath))))
+
+    ;; GNU Emacs
+    (defun pr-menu-lock (entry index horizontal state path)
+      (when (and (not (interactive-p)) pr-menu-lock)
+	(or (and pr-menu-position (eq state pr-menu-state))
+	    (setq pr-menu-position (pr-menu-position entry index horizontal)
+		  pr-menu-state    state))
+	(let* ((menu   (pr-menu-lookup path))
+	       (result (x-popup-menu pr-menu-position menu)))
+	  (and result
+	       (let ((command (lookup-key menu (vconcat result))))
+		 (if (fboundp command)
+		     (funcall command)
+		   (eval command)))))
+	(setq pr-menu-position nil))))
+
+
+   ((eq ps-print-emacs-type 'xemacs)
+    ;; XEmacs
+    (defun pr-menu-lookup (path)
+      (car (pr-x-find-menu-item current-menubar (cons "Printing" path))))
+
+    ;; XEmacs
+    (defun pr-menu-lock (entry index horizontal state path)
+      (when (and (not (interactive-p)) pr-menu-lock)
+	(or (and pr-menu-position (eq state pr-menu-state))
+	    (setq pr-menu-position (pr-menu-position entry index horizontal)
+		  pr-menu-state    state))
+	(let* ((menu   (pr-menu-lookup path))
+	       (result (pr-x-get-popup-menu-response menu pr-menu-position)))
+	  (and (pr-x-misc-user-event-p result)
+	       (funcall (pr-x-event-function result)
+			(pr-x-event-object result))))
+	(setq pr-menu-position nil))))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -4642,19 +4643,19 @@
 
 
 (defvar pr-ps-printer-menu-modified  t
-  "Non-nil means `pr-ps-printer-alist' was modified and need to update menu.")
+  "Non-nil means `pr-ps-printer-alist' was modified and we need to update menu.")
 (defvar pr-txt-printer-menu-modified t
-  "Non-nil means `pr-txt-printer-alist' was modified and need to update menu.")
+  "Non-nil means `pr-txt-printer-alist' was modified and we need to update menu.")
 (defvar pr-ps-utility-menu-modified t
-  "Non-nil means `pr-ps-utility-alist' was modified and need to update menu.")
+  "Non-nil means `pr-ps-utility-alist' was modified and we need to update menu.")
 
 
 (defconst pr-even-or-odd-alist
-  '((nil        . "Print All   Pages")
-    (even-page  . "Print Even  Pages")
-    (odd-page   . "Print Odd   Pages")
+  '((nil        . "Print All Pages")
+    (even-page  . "Print Even Pages")
+    (odd-page   . "Print Odd Pages")
     (even-sheet . "Print Even Sheets")
-    (odd-sheet  . "Print Odd  Sheets")))
+    (odd-sheet  . "Print Odd Sheets")))
 
 
 (defun pr-menu-create (name alist var-sym fun entry index)
@@ -4881,12 +4882,12 @@
     newname)
    (set var-sym newname)))
 
-
+;; GNU Emacs
 (defun pr-menu-set-item-name (item name)
   (and item
        (setcar (nthcdr 2 item) name)))	; ITEM-NAME
 
-
+;; GNU Emacs
 (defun pr-menu-get-item (name-list)
   ;; NAME-LIST is a string or a list of strings.
   (let ((ipath pr-menu-bar)
@@ -5471,6 +5472,8 @@
 (defun pr-command (command)
   "Return absolute file name specification for COMMAND.
 
+If COMMAND is an empty string, return it.
+
 If COMMAND is already an absolute file name specification, return it.
 Else it uses `pr-path-alist' to find COMMAND, if find it then return it;
 otherwise, gives an error.
@@ -5480,14 +5483,17 @@
 
 If Emacs is running on Windows 95/98/NT/2000, tries to find COMMAND,
 COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
-  (pr-dosify-path
-   (or (pr-find-command command)
-       (pr-path-command (cond (pr-cygwin-system  'cygwin)
-			      (ps-windows-system 'windows)
-			      (t                 'unix))
-			(file-name-nondirectory command)
-			nil)
-       (error "Command not found: %s" (file-name-nondirectory command)))))
+  (if (string= command "")
+      command
+    (pr-dosify-path
+     (or (pr-find-command command)
+	 (pr-path-command (cond (pr-cygwin-system  'cygwin)
+				(ps-windows-system 'windows)
+				(t                 'unix))
+			  (file-name-nondirectory command)
+			  nil)
+	 (error "Command not found: %s"
+		(file-name-nondirectory command))))))
 
 
 (defun pr-path-command (symbol command sym-list)
@@ -5715,7 +5721,7 @@
 	     (if (pr-interface-directory widget)
 		 (pr-widget-field-action widget event)
 	       (ding)
-	       (message "It should be a readable directory")))
+	       (message "Please specify a readable directory")))
    pr-i-directory)
   ;;    1b. Directory: File Regexp
   (widget-create 'regexp
@@ -5739,7 +5745,7 @@
 	     (if (pr-interface-infile widget)
 		 (pr-widget-field-action widget event)
 	       (ding)
-	       (message "It should be a readable PostScript file")))
+	       (message "Please specify a readable PostScript file")))
    pr-i-ps-file)
   ;;    1c. PostScript File: PostScript Utility
   (pr-insert-menu "PostScript Utility" 'pr-ps-utility
@@ -5766,7 +5772,7 @@
 	    (if pr-spool-p
 		(setq pr-i-despool (not pr-i-despool))
 	      (ding)
-	      (message "It despool only when it's spooling")
+	      (message "Can despool only when spooling is actually selected")
 	      (setq pr-i-despool nil))
 	    (widget-value-set widget pr-i-despool)
 	    (widget-setup))		; MUST be called after widget-value-set
@@ -5792,7 +5798,7 @@
 				(y-or-n-p "File exists; overwrite? "))))
 		 (pr-widget-field-action widget event)
 	       (ding)
-	       (message "It should be a writable PostScript file")))
+	       (message "Please specify a writable PostScript file")))
    pr-i-out-file)
   ;; 2. PostScript Printer: N-Up
   (widget-create
@@ -5809,7 +5815,7 @@
 		     (message " ")
 		     (setq pr-i-n-up value))
 		 (ding)
-		 (message "It should be an integer between 1 and 100"))))
+		 (message "Please specify an integer between 1 and 100"))))
    pr-i-n-up))
 
 
@@ -5857,23 +5863,23 @@
 			    (pr-update-checkbox 'pr-i-despool)))
 		      " Spool Buffer")
 
-  ;; 4. Settings: Duplex                Print with-faces
+  ;; 4. Settings: Duplex                Print with faces
   (pr-insert-checkbox "\n  "
 		      'ps-spool-duplex
 		      #'(lambda (&rest ignore)
 			  (setq ps-spool-duplex (not ps-spool-duplex)
 				pr-file-duplex  ps-spool-duplex))
 		      " Duplex                ")
-  (pr-insert-toggle 'pr-faces-p " Print with-faces")
-
-  ;; 4. Settings: Tumble                Print Using Ghostscript
+  (pr-insert-toggle 'pr-faces-p " Print with faces")
+
+  ;; 4. Settings: Tumble                Print via Ghostscript
   (pr-insert-checkbox "\n  "
 		      'ps-spool-tumble
 		      #'(lambda (&rest ignore)
 			  (setq ps-spool-tumble (not ps-spool-tumble)
 				pr-file-tumble  ps-spool-tumble))
 		      " Tumble                ")
-  (pr-insert-toggle 'pr-print-using-ghostscript " Print Using Ghostscript\n  ")
+  (pr-insert-toggle 'pr-print-using-ghostscript " Print via Ghostscript\n  ")
 
   ;; 4. Settings: Upside-Down           Page Parity
   (pr-insert-toggle 'ps-print-upside-down " Upside-Down           ")
@@ -5962,7 +5968,7 @@
 		  (pr-txt-buffer)))
 	       )))
        ((eq pr-i-process 'file)
-	(error "It should be a text file"))
+	(error "Please specify a text file"))
        (t
 	(error "Internal error: `pr-i-process' = %S" pr-i-process))
        )
@@ -5987,7 +5993,7 @@
 	     (pr-printify-region)
 	   (pr-printify-buffer))))
        ((eq pr-i-process 'file)
-	(error "It can't printify a PostScript file"))
+	(error "Cannot printify a PostScript file"))
        (t
 	(error "Internal error: `pr-i-process' = %S" pr-i-process))
        )
@@ -6034,7 +6040,7 @@
 	 ((eq pr-i-process 'file)
 	  (cond ((or (file-directory-p pr-i-ps-file)
 		     (not (file-readable-p pr-i-ps-file)))
-		 (error "It should be a readable PostScript file"))
+		 (error "Please specify a readable PostScript file"))
 		(pr-i-ps-as-is
 		 (pr-interface-save
 		  (funcall ps-file pr-i-ps-file)))
@@ -6070,7 +6076,7 @@
 	 (error "Internal error: `pr-i-ps-send' = %S" pr-i-ps-send))
 	((or (file-directory-p pr-i-out-file)
 	     (not (file-writable-p pr-i-out-file)))
-	 (error "It should be a writable PostScript file"))
+	 (error "Please specify a writable PostScript file"))
 	((or (not (file-exists-p pr-i-out-file))
 	     pr-i-answer-yes
 	     (setq pr-i-answer-yes
@@ -6084,12 +6090,12 @@
 (defun pr-i-directory ()
   (or (and (file-directory-p pr-i-directory)
 	   (file-readable-p pr-i-directory))
-      (error "It should be a readable directory")))
+      (error "Please specify be a readable directory")))
 
 
 (defun pr-interface-directory (widget &rest ignore)
   (and pr-buffer-verbose
-       (message "Type M-TAB or ESC TAB for file completion"))
+       (message "You can use M-TAB or ESC TAB for file completion"))
   (let ((dir (widget-value widget)))
     (and (file-directory-p dir)
 	 (file-readable-p dir)
@@ -6098,7 +6104,7 @@
 
 (defun pr-interface-infile (widget &rest ignore)
   (and pr-buffer-verbose
-       (message "Type M-TAB or ESC TAB for file completion"))
+       (message "You can use M-TAB or ESC TAB for file completion"))
   (let ((file (widget-value widget)))
     (and (not (file-directory-p file))
 	 (file-readable-p file)
@@ -6108,7 +6114,7 @@
 (defun pr-interface-outfile (widget &rest ignore)
   (setq pr-i-answer-yes nil)
   (and pr-buffer-verbose
-       (message "Type M-TAB or ESC TAB for file completion"))
+       (message "You can use M-TAB or ESC TAB for file completion"))
   (let ((file (widget-value widget)))
     (and (not (file-directory-p file))
 	 (file-writable-p file)
--- a/lisp/progmodes/ebnf2ps.el	Sat Feb 28 01:23:39 2004 +0000
+++ b/lisp/progmodes/ebnf2ps.el	Sat Feb 28 01:33:17 2004 +0000
@@ -5,7 +5,7 @@
 
 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
-;; Time-stamp: <2004/02/24 20:48:53 vinicius>
+;; Time-stamp: <2004/02/25 20:17:43 vinicius>
 ;; Keywords: wp, ebnf, PostScript
 ;; Version: 4.0
 ;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/
@@ -1041,7 +1041,7 @@
 ;; Acknowledgements
 ;; ----------------
 ;;
-;; Thanks to Drew Adams <?@?> for suggestions:
+;; Thanks to Drew Adams <drew.adams@oracle.com> for suggestions:
 ;;    - `ebnf-production-name-p', `ebnf-stop-on-error',
 ;;	`ebnf-file-suffix-regexp'and `ebnf-special-show-delimiter' variables.
 ;;    - `ebnf-delete-style', `ebnf-eps-file' and `ebnf-eps-directory'
@@ -1065,6 +1065,22 @@
 (and (string< ps-print-version "5.2.3")
      (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
 
+
+;; to avoid gripes with Emacs 20
+(eval-and-compile
+  (or (fboundp 'assq-delete-all)
+      (defun assq-delete-all (key alist)
+	"Delete from ALIST all elements whose car is KEY.
+Return the modified alist.
+Elements of ALIST that are not conses are ignored."
+	(let ((tail alist))
+	  (while tail
+	    (if (and (consp (car tail))
+		     (eq (car (car tail)) key))
+		(setq alist (delq (car tail) alist)))
+	    (setq tail (cdr tail)))
+	  alist))))
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; User Variables:
@@ -4471,12 +4487,12 @@
 	     (setq the-point (max (1- (point)) (point-min))
 		   error-msg (concat error-msg ": "
 				     (error-message-string data)
-				     (if (string= error-msg "SYNTAX")
-					 (format ". At %d in buffer \"%s\"."
-						 the-point
-						 (buffer-name))
-				       (format ". In buffer \"%s\"."
-					       (buffer-name))))))))))
+				     ", "
+				     (and (string= error-msg "SYNTAX")
+					  (format "at position %d "
+						  the-point))
+				     (format "in buffer \"%s\"."
+					     (buffer-name)))))))))
     (cond
      ;; error occurred
      (error-msg
--- a/src/ChangeLog	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/ChangeLog	Sat Feb 28 01:33:17 2004 +0000
@@ -1,5 +1,221 @@
+2004-02-26  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>
+	
+	* s/darwin.h (LD_SWITCH_SYSTEM_TEMACS): Add `-framework
+	QuickTime'.
+	
+	* dispextern.h [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+	macgui.h).
+	
+	* emacs.c (main) [HAVE_CARBON]: Call init_xfns.
+	
+	* macgui.h [MAC_OSX]: Include Carbon/Carbon.h.
+	(mktime, DEBUG, Z, free, malloc, realloc, max, min)
+	(init_process) [MAC_OSX] : Avoid conflicts with Carbon/Carbon.h.
+	[!MAC_OSX]: Include QDOffscreen.h and Controls.h.
+	(INFINITY) [MAC_OSX]: Avoid conflict with definition in math.h.
+	(Bitmap): Remove typedef.
+	(Pixmap): Change int to GWorldPtr.
+
+	* macmenu.c [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+	macgui.h).
+	
+	* macterm.h [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+	macgui.h).
+	(RED16_FROM_ULONG, GREEN16_FROM_ULONG, BLUE16_FROM_ULONG): New
+	#define to extract 16-bit depth color components from unsigned
+	long representation.
+	(PIX_MASK_DRAW, PIX_MASK_RETAIN): New #define to represent pixel
+	colors used for masks.
+	(struct mac_display_info): Add color_p.  Remove n_cbits.
+	
+	* macfns.c: Include sys/types.h and sys/stat.h.
+	[MAC_OSX]: Do not include Carbon/Carbon.h (now in macgui.h).
+	Include QuickTime/QuickTime.h.
+	(XCreatePixmap, XCreatePixmapFromBitmapData, XFreePixmap)
+	(XSetForeground, mac_draw_line_to_pixmap): Add externs for
+	functions defined in macterm.c.
+	(XImagePtr): New typedef.  Corresponds to XImage * in xfns.c.
+	(ZPixmap): New #define for compatibility with xfns.c.
+	(XGetImage, XPutPixel, XGetPixel, XDestroyImage)
+	(x_create_x_image_and_pixmap, x_destroy_x_image, x_put_x_image)
+	(find_image_fsspec, image_load_qt_1, image_load_quicktime): New
+	functions.
+	(four_corners_best, x_create_x_image_and_pixmap)
+	(x_destroy_x_image, unwind_create_frame, x_disable_image,
+	(x_edge_detection, init_color_table, colors_in_color_table,
+	(lookup_rgb_color, lookup_pixel_color, postprocess_image)
+	(x_put_x_image, slurp_file, xbm_scan, xbm_load, xbm_load_image)
+	(xbm_image_p, xbm_read_bitmap_data, xbm_file_p, x_to_xcolors)
+	(x_from_xcolors, x_detect_edges): New declarations (from xfns.c).
+	(mac_color_map_lookup, x_to_mac_color): Fix Lisp_Object/unsigned
+	long mixup.
+	(mac_defined_color, x_to_x_colors): Use RED16_FROM_ULONG etc.
+	(x_decode_color): Don't use n_cbits (in struct mac_display_info).
+	(x_set_foreground_color, x_set_cursor_color): Sync with w32fns.c.
+	(x_set_cursor_type, Fxw_color_values, valid_image_p)
+	(image_value_type, parse_image_spec, image_ascent, x_clear_image)
+	(x_alloc_image_color, clear_image_cache, lookup_image)
+	(x_find_image_file, xbm_read_bitmap_file_data)
+	(enum xbm_keyword_index, xbm_format, xbm_image_p, xbm_scan)
+	(xbm_read_bitmap_data, xbm_load, pbm_image_p, pbm_scan_number)
+	(enum pbm_keyword_index, pbm_format, enum png_keyword_index)
+	(png_format, png_image_p, enum jpeg_keyword_index, jpeg_format)
+	(jpeg_image_p, enum tiff_keyword_index, tiff_format, tiff_image_p)
+	(enum gif_keyword_index, gif_format, gif_image_p): Sync with
+	xfns.c.
+	(x_make_gc): Sync with xfns.c.  Enclose unused `border_tile' with
+	#if 0.
+	(x_free_gcs): Sync with xfns.c.  Enclose unused `border_tile' with
+	#if 0.  Free white_relief.gc and black_relief.gc.
+	(unwind_create_frame, x_emboss, x_laplace, x_edge_detection): New
+	functions (from xfns.c).
+	(Fx_create_frame): Record unwind_create_frame.
+	(Fxw_display_color_p): Use dpyinfo->color_p.
+	(Fx_display_grayscale_p, Fx_display_planes): Don't use
+	dpyinfo->n_cbits.
+	(Fx_display_color_cells): Use dpyinfo->n_planes;
+	(QCmatrix, QCcolor_adjustment, QCmask, Qemboss, Qedge_detection)
+	(Qheuristic, cross_disabled_images, emboss_matrix)
+	(laplace_matrix): New variables (from xfns.c).
+	(Fimage_size, Fimage_mask_p, four_corners_best, image_background)
+	(x_clear_image_1, postprocess_image, slurp_file, xbm_load_image)
+	(xbm_file_p, x_to_xcolors, x_from_xcolors, x_detect_edges)
+	(image_background_transparent): New function (from xfns.c).  Use
+	PIX_MASK_DRAW/PIX_MASK_RETAIN.
+	(image_load_quicktime): Add declaration.
+	[MAC_OSX] (image_load_quartz2d): Likewise.
+	[MAC_OSX] (CGImageCreateWithPNGDataProviderProcType): New typedef.
+	[MAC_OSX] (MyCGImageCreateWithPNGDataProvider): New variable.
+	[MAC_OSX] (init_image_func_pointer, image_load_quartz2d): New
+	functions.
+	(xbm_load_image_from_file, x_laplace_read_row)
+	(x_laplace_write_row, pbm_read_file): Remove functions.
+	[HAVE_XPM] (enum xpm_keyword_index, xpm_format, xpm_image_p)
+	(xpm_load): Sync with xfns.c (although XPM is not supported yet).
+	(colors_in_color_table): Sync with xfns.c (although not used).
+	(lookup_rgb_color): Don't lookup color table.  Just do gamma
+	correction.
+	(COLOR_INTENSITY): New #define (from xfns.c).
+	(x_disable_image): New function (from xfns.c).  Use
+	PIX_MASK_DRAW/PIX_MASK_RETAIN.
+	(x_build_heuristic_mask): Sync with xfns.c.  Use
+	PIX_MASK_DRAW/PIX_MASK_RETAIN.
+	(HAVE_PBM): Remove #ifdef.
+	(pbm_load): Sync with xfns.c.  Set img->width and img->height
+	before IMAGE_BACKGROUND.
+	(png_image_p, png_load): Don't enclose declarations with #if
+	HAVE_PNG.
+	(Qpng, enum png_keyword_index, png_format, png_type, png_image_p):
+	Don't enclose with #if HAVE_PNG.
+	[!HAVE_PNG] (png_load) [MAC_OSX]: Use image_load_quartz2d if a
+	symbol _CGImageCreateWithPNGDataProvider is defined.  Otherwise
+	use image_load_quicktime.
+	[!HAVE_PNG] (png_load) [!MAC_OSX]: Use image_load_quicktime.
+	[HAVE_PNG] (png_load): Sync with xfns.c.  Use
+	PIX_MASK_DRAW/PIX_MASK_RETAIN.
+	(jpeg_image_p, jpeg_load): Don't enclose declarations with #if
+	HAVE_JPEG.
+	(Qjpeg, enum jpeg_keyword_index, jpeg_format, jpeg_type)
+	(jpeg_image_p): Don't enclose with #if HAVE_JPEG.
+	[!HAVE_JPEG] (jpeg_load) [MAC_OSX]: Use image_load_quartz2d.
+	[!HAVE_JPEG] (jpeg_load) [!MAC_OSX]: Use image_load_quicktime.
+	[HAVE_JPEG] (jpeg_load): Sync with xfns.c.
+	(tiff_image_p, tiff_load): Don't enclose declarations with #if
+	HAVE_TIFF.
+	(Qtiff, enum tiff_keyword_index, tiff_format, tiff_type)
+	(tiff_image_p): Don't enclose with #if HAVE_TIFF.
+	[!HAVE_TIFF] (tiff_load): Use image_load_quicktime.
+	[HAVE_TIFF] (tiff_error_handler, tiff_warning_handler): New
+	functions (from xfns.c).
+	[HAVE_TIFF] (tiff_load): Sync with xfns.c.
+	(gif_image_p, gif_load): Don't enclose declarations with #if
+	HAVE_GIF.
+	(Qgif, enum gif_keyword_index, gif_format, gif_type, gif_image_p):
+	Don't enclose with #if HAVE_GIF.
+	[!HAVE_GIF] (gif_load): Use Quicktime Movie Toolbox if it is
+	animated gif.  Otherwise use image_load_quicktime.
+	[HAVE_GIF] (gif_lib.h): Temporarily define DrawText as
+	gif_DrawText to avoid conflict with QuickdrawText.h.
+	[HAVE_GIF] (gif_load): Sync with xfns.c.
+	(enum gs_keyword_index, gs_format, gs_image_p, gs_load)
+	[HAVE_GHOSTSCRIPT] (x_kill_gs_process): Sync with xfns.c (although
+	Ghostscript is not supported yet).
+	(syms_of_macfns): Initialize Qemboss, Qedge_detection, Qheuristic,
+	QCmatrix, QCcolor_adjustment, and QCmask.  Add DEFVAR_BOOL
+	cross_disabled_images (from xfns.c).  Remove #if 0 for supported
+	image types.  Remove #if HAVE_JPEG, HAVE_TIFF, HAVE_GIF, and
+	HAVE_PNG.  Add defsubr for Simage_size and Simage_mask_p.
+	(init_xfns): Remove #if HAVE_JPEG, HAVE_TIFF, HAVE_GIF, and
+	HAVE_PNG.  Call EnterMovies to support animated gifs.  Call
+	init_image_func_pointer to bind a symbol
+	_CGImageCreateWithPNGDataProvider if it is defined.
+	
+	* macterm.c [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+	macgui.h).
+	(x_draw_bar_cursor): Sync declaration with xterm.c.
+	(XFreePixmap, mac_draw_rectangle_to_pixmap, mac_copy_area)
+	(mac_copy_area_to_pixmap): Implementation with GWorld (offscreen
+	graphics).
+	(mac_set_forecolor, mac_set_backcolor): Use RED16_FROM_ULONG etc.
+	(mac_draw_line_to_pixmap, XCreatePixmap)
+	(XCreatePixmapFromBitmapData, mac_fill_rectangle_to_pixmap)
+	(mac_copy_area_with_mask, mac_copy_area_with_mask_to_pixmap): New
+	functions.
+	(mac_draw_bitmap) [TARGET_API_MAC_CARBON]: Use
+	GetPortBitMapForCopyBits instead of the cast to Bitmap *.  Cast
+	bits to char *.
+	(reflect_byte): New function (from w32fns.c).
+	(mac_create_bitmap_from_bitmap_data): Use it and don't stuff bits
+	due to byte alignment.
+	(mac_scroll_area) [TARGET_API_MAC_CARBON]: Use
+	GetPortBitMapForCopyBits instead of the cast to Bitmap *.
+	(XSetForeground): Remove static (now used in macfns.c).
+	(HIGHLIGHT_COLOR_DARK_BOOST_LIMIT): New #define (from w32term.c).
+	(mac_alloc_lighter_color, x_destroy_window): Sync with w32term.c.
+	(x_setup_relief_color, x_setup_relief_colors, x_draw_box_rect)
+	(x_draw_glyph_string_box, x_draw_image_foreground)
+	(x_draw_image_foreground_1, x_draw_image_glyph_string)
+	(x_draw_stretch_glyph_string, x_draw_glyph_string)
+	(x_draw_hollow_cursor, x_draw_bar_cursor, mac_draw_window_cursor):
+	Sync with xterm.c.
+	(x_draw_relief_rect): Sync with xterm.c.  Make 1 pixel shorter
+	than the xterm.c version when a strictly horizontal or vertical
+	line is drawn.
+	(XTset_terminal_window): Add static.
+	(x_make_frame_visible): Add UNBLOCK_INPUT.
+	(x_free_frame_resources): New funcion (from xterm.c).
+	(XTread_socket): Call handle_tool_bar_click if mouse up/down event
+	occurs in tool bar area.
+	(mac_initialize_display_info): Remove dpyinfo->n_cbits.  Set
+	dpyinfo->color_p.  Determine dpyinfo->n_planes using HasDepth.
+	Initialize image cache.
+	(stricmp, wildstrieq, mac_font_pattern_match, mac_font_match):
+	Enclose unused functions with #if 0.
+	(Qbig5, Qcn_gb, Qsjis, Qeuc_kr): New variables.
+	(decode_mac_font_name): New function to apply code conversions
+	from a mac font name to an XLFD font name according to its script
+	code.
+	(x_font_name_to_mac_font_name): Apply code conversion from an XLFD
+	font name to a mac font name according to REGISTRY and ENCODING
+	fields.
+	(init_font_name_table) [TARGET_API_MAC_CARBON]: Don't use a font
+	whose name starts with `.'.
+	(init_font_name_table): Use decode_mac_font_name.  Add both
+	jisx0208.1983-sjis and jisx0201.1976-0 entries if the script code
+	of a font is smJapanese.
+	(mac_do_list_fonts): New function to list fonts that match a given
+	pattern.
+	(x_list_fonts, XLoadQueryFont): Use it.
+	(XLoadQueryFont): Set rbearing field for each variable width
+	character to avoid needless redraw.
+	(syms_of_macterm): Initialize Qbig5, Qcn_gb, Qsjis, and Qeuc_kr.
+
 2004-02-26  Kim F. Storm  <storm@cua.dk>
 
+	* keyboard.c (NREAD_INPUT_EVENTS): Temporarily increase to 512
+	as read_socket_hook handler on X aborts if buffer is too small
+	and W32 handler doesn't always check buffer limit.
+
 	* xdisp.c (handle_single_display_prop): Handle left-fringe and
 	right-fringe similar to a display margin image.  Specifically,
 	the characters having the fringe prop are no longer shown, and
--- a/src/dispextern.h	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/dispextern.h	Sat Feb 28 01:33:17 2004 +0000
@@ -61,38 +61,8 @@
 #ifdef HAVE_CARBON
 #include "macgui.h"
 typedef struct mac_display_info Display_Info;
-
-/* Include Carbon.h to define Cursor and Rect.  */
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
-
 #endif
 
-
 #ifndef NativeRectangle
 #define NativeRectangle int
 #endif
--- a/src/emacs.c	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/emacs.c	Sat Feb 28 01:33:17 2004 +0000
@@ -1589,7 +1589,7 @@
 #endif /* VMS */
       init_display ();	/* Determine terminal type.  Calls init_sys_modes.  */
     }
-#if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT)
+#if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT) || defined (HAVE_CARBON)
   init_xfns ();
 #endif /* HAVE_X_WINDOWS */
   init_fns ();
--- a/src/keyboard.c	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/keyboard.c	Sat Feb 28 01:33:17 2004 +0000
@@ -6578,7 +6578,7 @@
    a small buffer of input events -- and then poll for more input if we
    read a full buffer of input events.  */
 
-#define NREAD_INPUT_EVENTS 8
+#define NREAD_INPUT_EVENTS 512
 
 static int
 read_avail_input (expected)
--- a/src/macfns.c	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/macfns.c	Sat Feb 28 01:33:17 2004 +0000
@@ -54,6 +54,8 @@
 /*#include <commdlg.h>
 #include <shellapi.h>*/
 #include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -62,32 +64,7 @@
 #endif
 
 #ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
+#include <QuickTime/QuickTime.h>
 #else /* not MAC_OSX */
 #include <Windows.h>
 #include <Gestalt.h>
@@ -209,6 +186,12 @@
 extern void x_find_ccl_program (struct font_info *);
 extern struct font_info *x_query_font (struct frame *, char *);
 extern void mac_initialize ();
+extern Pixmap XCreatePixmap (Display *, WindowPtr, unsigned int, unsigned int, unsigned int);
+extern Pixmap XCreatePixmapFromBitmapData (Display *, WindowPtr, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
+extern void XFreePixmap (Display *, Pixmap);
+extern void XSetForeground (Display *, GC, unsigned long);
+extern void mac_draw_line_to_pixmap (Display *, Pixmap, GC, int, int, int, int);
+
 
 /* compare two strings ignoring case */
 
@@ -552,13 +535,89 @@
       xfree (dpyinfo->bitmaps[i].bitmap_data);
   dpyinfo->bitmaps_last = 0;
 }
+
+
 
-/* Connect the frame-parameter names for W32 frames
-   to the ways of passing the parameter values to the window system.
-
-   The name of a parameter, as a Lisp symbol,
-   has an `x-frame-parameter' property which is an integer in Lisp
-   but can be interpreted as an `enum x_frame_parm' in C.  */
+/* Mac equivalent of XImage.  */
+typedef Pixmap XImagePtr;
+#define ZPixmap 0 		/* arbitrary */
+
+static XImagePtr
+XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
+     Display *display;		/* not used */
+     Pixmap pixmap;
+     int x, y;			/* not used */
+     unsigned int width, height; /* not used */
+     unsigned long plane_mask; 	/* not used */
+     int format;		/* not used */
+{
+#if GLYPH_DEBUG
+  xassert (x == 0 && y == 0);
+  {
+    Rect ri, rp;
+    SetRect (&ri, 0, 0, width, height);
+    xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
+  }
+  xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
+#endif
+
+  LockPixels (GetGWorldPixMap (pixmap));
+
+  return pixmap;
+}
+
+static void
+XPutPixel (ximage, x, y, pixel)
+     XImagePtr ximage;
+     int x, y;
+     unsigned long pixel;
+{
+  RGBColor color;
+
+  SetGWorld (ximage, NULL);
+
+  color.red = RED16_FROM_ULONG (pixel);
+  color.green = GREEN16_FROM_ULONG (pixel);
+  color.blue = BLUE16_FROM_ULONG (pixel);
+  SetCPixel (x, y, &color);
+}
+
+static unsigned long
+XGetPixel (ximage, x, y)
+     XImagePtr ximage;
+     int x, y;
+{
+  RGBColor color;
+
+  SetGWorld (ximage, NULL);
+
+  GetCPixel (x, y, &color);
+  return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
+}
+
+static void
+XDestroyImage (ximg)
+     XImagePtr ximg;
+{
+  UnlockPixels (GetGWorldPixMap (ximg));
+}
+
+
+
+/* Useful functions defined in the section
+   `Image type independent image structures' below. */
+
+static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
+					    unsigned long height));
+
+static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
+					    int depth, XImagePtr *ximg,
+					    Pixmap *pixmap));
+
+static void x_destroy_x_image P_ ((XImagePtr ximg));
+
+static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
+static void x_disable_image P_ ((struct frame *, struct image *));
 
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -581,6 +640,13 @@
 							     Lisp_Object,
 							     char *, char *,
 							     int));
+static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
+				  Lisp_Object));
+static void init_color_table P_ ((void));
+static void free_color_table P_ ((void));
+static unsigned long *colors_in_color_table P_ ((int *n));
+static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
+static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
 
 /* Store the screen positions of frame F into XPTR and YPTR.
    These are the positions of the containing window manager window,
@@ -1382,7 +1448,7 @@
   { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
 };
 
-unsigned long
+Lisp_Object
 mac_color_map_lookup (colorname)
      char *colorname;
 {
@@ -1394,7 +1460,7 @@
   for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
     if (stricmp (colorname, mac_color_map[i].name) == 0)
       {
-        ret = mac_color_map[i].color;
+        ret = make_number (mac_color_map[i].color);
         break;
       }
 
@@ -1463,7 +1529,7 @@
 	      if (i == 2)
 		{
 		  UNBLOCK_INPUT;
-		  return (colorval);
+		  return make_number (colorval);
 		}
 	      color = end;
 	    }
@@ -1516,7 +1582,7 @@
 	      if (*end != '\0')
 		break;
 	      UNBLOCK_INPUT;
-	      return (colorval);
+	      return make_number (colorval);
 	    }
 	  if (*end != '/')
 	    break;
@@ -1557,7 +1623,7 @@
 	      if (*end != '\0')
 		break;
 	      UNBLOCK_INPUT;
-	      return (colorval);
+	      return make_number (colorval);
 	    }
 	  if (*end != '/')
 	    break;
@@ -1616,9 +1682,9 @@
         }
 
       color_def->pixel = mac_color_ref;
-      color_def->red = RED_FROM_ULONG (mac_color_ref);
-      color_def->green = GREEN_FROM_ULONG (mac_color_ref);
-      color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
+      color_def->red = RED16_FROM_ULONG (mac_color_ref);
+      color_def->green = GREEN16_FROM_ULONG (mac_color_ref);
+      color_def->blue = BLUE16_FROM_ULONG (mac_color_ref);
 
       return 1;
     }
@@ -1649,8 +1715,7 @@
     return WHITE_PIX_DEFAULT (f);
 
 #if 0
-  if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
-       * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
+  if (FRAME_MAC_DISPLAY_INFO (f)->n_planes) == 1)
     return def;
 #endif
 
@@ -1674,8 +1739,11 @@
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  FRAME_FOREGROUND_PIXEL (f)
-    = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  unsigned long fg, old_fg;
+
+  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  old_fg = FRAME_FOREGROUND_PIXEL (f);
+  FRAME_FOREGROUND_PIXEL (f) = fg;
 
   if (FRAME_MAC_WINDOW (f) != 0)
     {
@@ -1856,36 +1924,42 @@
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  unsigned long fore_pixel;
+  unsigned long fore_pixel, pixel;
 
   if (!NILP (Vx_cursor_fore_pixel))
     fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
 				 WHITE_PIX_DEFAULT (f));
   else
     fore_pixel = FRAME_BACKGROUND_PIXEL (f);
-  f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+
+  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
 
   /* Make sure that the cursor color differs from the background color.  */
-  if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
-    {
-      f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
-      if (f->output_data.mac->cursor_pixel == fore_pixel)
+  if (pixel == FRAME_BACKGROUND_PIXEL (f))
+    {
+      pixel = f->output_data.mac->mouse_pixel;
+      if (pixel == fore_pixel)
 	fore_pixel = FRAME_BACKGROUND_PIXEL (f);
     }
-  FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
-
-#if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
+
+  f->output_data.mac->cursor_foreground_pixel = fore_pixel;
+  f->output_data.mac->cursor_pixel = pixel;
+
   if (FRAME_MAC_WINDOW (f) != 0)
     {
+      BLOCK_INPUT;
+      /* Update frame's cursor_gc.  */
+      f->output_data.mac->cursor_gc->foreground = fore_pixel;
+      f->output_data.mac->cursor_gc->background = pixel;
+
+      UNBLOCK_INPUT;
+
       if (FRAME_VISIBLE_P (f))
 	{
-	  BLOCK_INPUT;
-	  display_and_set_cursor (f, 0);
-	  display_and_set_cursor (f, 1);
-	  UNBLOCK_INPUT;
+	  x_update_cursor (f, 0);
+	  x_update_cursor (f, 1);
 	}
     }
-#endif
 
   update_face_from_frame_parameter (f, Qcursor_color, arg);
 }
@@ -1893,11 +1967,13 @@
 /* Set the border-color of frame F to pixel value PIX.
    Note that this does not fully take effect if done before
    F has a window.  */
+
 void
 x_set_border_pixel (f, pix)
      struct frame *f;
      int pix;
 {
+
   f->output_data.mac->border_pixel = pix;
 
   if (FRAME_MAC_WINDOW (f) != 0 && f->border_width > 0)
@@ -1926,6 +2002,7 @@
   update_face_from_frame_parameter (f, Qborder_color, arg);
 }
 
+
 void
 x_set_cursor_type (f, arg, oldval)
      FRAME_PTR f;
@@ -1933,9 +2010,8 @@
 {
   set_frame_cursor_types (f, arg);
 
-  /* Make sure the cursor gets redrawn.  This is overkill, but how
-     often do people change cursor types?  */
-  update_mode_lines++;
+  /* Make sure the cursor gets redrawn.  */
+  cursor_type_changed = 1;
 }
 
 #if 0 /* MAC_TODO: really no icon for Mac */
@@ -2597,7 +2673,7 @@
 
   BLOCK_INPUT;
 
-  /* Create the GC's of this frame.
+  /* Create the GCs of this frame.
      Note that many default values are used.  */
 
   /* Normal video */
@@ -2629,10 +2705,104 @@
   f->output_data.mac->white_relief.gc = 0;
   f->output_data.mac->black_relief.gc = 0;
 
+#if 0
+  /* Create the gray border tile used when the pointer is not in
+     the frame.  Since this depends on the frame's pixel values,
+     this must be done on a per-frame basis.  */
+  f->output_data.x->border_tile
+    = (XCreatePixmapFromBitmapData
+       (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
+	gray_bits, gray_width, gray_height,
+	f->output_data.x->foreground_pixel,
+	f->output_data.x->background_pixel,
+	DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
+#endif
+
   UNBLOCK_INPUT;
 }
 
 
+/* Free what was was allocated in x_make_gc.  */
+
+void
+x_free_gcs (f)
+     struct frame *f;
+{
+  Display *dpy = FRAME_MAC_DISPLAY (f);
+
+  BLOCK_INPUT;
+
+  if (f->output_data.mac->normal_gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->normal_gc);
+      f->output_data.mac->normal_gc = 0;
+    }
+
+  if (f->output_data.mac->reverse_gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->reverse_gc);
+      f->output_data.mac->reverse_gc = 0;
+    }
+
+  if (f->output_data.mac->cursor_gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->cursor_gc);
+      f->output_data.mac->cursor_gc = 0;
+    }
+
+#if 0
+  if (f->output_data.mac->border_tile)
+    {
+      XFreePixmap (dpy, f->output_data.mac->border_tile);
+      f->output_data.mac->border_tile = 0;
+    }
+#endif
+
+  if (f->output_data.mac->white_relief.gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->white_relief.gc);
+      f->output_data.mac->white_relief.gc = 0;
+    }
+
+  if (f->output_data.mac->black_relief.gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->black_relief.gc);
+      f->output_data.mac->black_relief.gc = 0;
+    }
+
+  UNBLOCK_INPUT;
+}
+
+
+/* Handler for signals raised during x_create_frame and
+   x_create_top_frame.  FRAME is the frame which is partially
+   constructed.  */
+
+static Lisp_Object
+unwind_create_frame (frame)
+     Lisp_Object frame;
+{
+  struct frame *f = XFRAME (frame);
+
+  /* If frame is ``official'', nothing to do.  */
+  if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
+    {
+#if GLYPH_DEBUG
+      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+#endif
+
+      x_free_frame_resources (f);
+
+      /* Check that reference counts are indeed correct.  */
+      xassert (dpyinfo->reference_count == dpyinfo_refcount);
+      xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+      return Qt;
+    }
+
+  return Qnil;
+}
+
+
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
        doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
@@ -2736,10 +2906,7 @@
   FRAME_FONTSET (f) = -1;
   f->output_data.mac->scroll_bar_foreground_pixel = -1;
   f->output_data.mac->scroll_bar_background_pixel = -1;
-
-#if 0
-  FRAME_FONTSET (f) = -1;
-#endif
+  record_unwind_protect (unwind_create_frame, frame);
 
   f->icon_name
     = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
@@ -2790,17 +2957,18 @@
     /* First, try whatever font the caller has specified.  */
     if (STRINGP (font))
       {
-        tem = Fquery_fontset (font, Qnil);
-        if (STRINGP (tem))
-          font = x_new_fontset (f, SDATA (tem));
-        else
-          font = x_new_font (f, SDATA (font));
+	tem = Fquery_fontset (font, Qnil);
+	if (STRINGP (tem))
+	  font = x_new_fontset (f, SDATA (tem));
+	else
+	  font = x_new_font (f, SDATA (font));
       }
+
     /* Try out a font which we hope has bold and italic variations.  */
     if (! STRINGP (font))
       font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
     /* If those didn't work, look for something which will at least work.  */
-    if (!STRINGP (font))
+    if (! STRINGP (font))
       font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
     if (! STRINGP (font))
       font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
@@ -3011,12 +3179,9 @@
     {
       Lisp_Object rgb[3];
 
-      rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
-                            | RED_FROM_ULONG (foo.pixel));
-      rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
-                            | GREEN_FROM_ULONG (foo.pixel));
-      rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
-                            | BLUE_FROM_ULONG (foo.pixel));
+      rgb[0] = make_number (foo.red);
+      rgb[1] = make_number (foo.green);
+      rgb[2] = make_number (foo.blue);
       return Flist (3, rgb);
     }
   else
@@ -3030,7 +3195,7 @@
 {
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
-  if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
+  if (!dpyinfo->color_p)
     return Qnil;
 
   return Qt;
@@ -3048,7 +3213,7 @@
 {
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
-  if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
+  if (dpyinfo->n_planes <= 1)
     return Qnil;
 
   return Qt;
@@ -3093,7 +3258,7 @@
 {
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
-  return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
+  return make_number (dpyinfo->n_planes);
 }
 
 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
@@ -3108,7 +3273,7 @@
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
   /* MAC_TODO: check whether this is right */
-  return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
+  return make_number (dpyinfo->n_planes >= 8 ? 256 : 1 << dpyinfo->n_planes - 1);
 }
 
 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
@@ -3446,6 +3611,7 @@
   return Qnil;
 }
 
+
 
 /***********************************************************************
 			    Image types
@@ -3470,11 +3636,11 @@
 extern Lisp_Object QCdata, QCtype;
 Lisp_Object QCascent, QCmargin, QCrelief;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
 /* Other symbols.  */
 
-Lisp_Object Qlaplace;
+Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
 
 /* Time in seconds after which images should be removed from the cache
    if not displayed.  */
@@ -3487,6 +3653,7 @@
 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
 static void x_laplace P_ ((struct frame *, struct image *));
+static void x_emboss P_ ((struct frame *, struct image *));
 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
 				       Lisp_Object));
 
@@ -3540,11 +3707,22 @@
 
   if (IMAGEP (object))
     {
-      Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
-      struct image_type *type = lookup_image_type (symbol);
-
-      if (type)
-	valid_p = type->valid_p (object);
+      Lisp_Object tem;
+
+      for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
+	if (EQ (XCAR (tem), QCtype))
+	  {
+	    tem = XCDR (tem);
+	    if (CONSP (tem) && SYMBOLP (XCAR (tem)))
+	      {
+		struct image_type *type;
+		type = lookup_image_type (XCAR (tem));
+		if (type)
+		  valid_p = type->valid_p (object);
+	      }
+
+	    break;
+	  }
     }
 
   return valid_p;
@@ -3554,8 +3732,8 @@
 /* Log error message with format string FORMAT and argument ARG.
    Signaling an error, e.g. when an image cannot be loaded, is not a
    good idea because this would interrupt redisplay, and the error
-   message display would lead to another redisplay. This function
-   therefore simply displays a message. */
+   message display would lead to another redisplay.  This function
+   therefore simply displays a message.  */
 
 static void
 image_error (format, arg1, arg2)
@@ -3575,6 +3753,7 @@
 {
   IMAGE_DONT_CHECK_VALUE_TYPE,
   IMAGE_STRING_VALUE,
+  IMAGE_STRING_OR_NIL_VALUE,
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
@@ -3654,7 +3833,7 @@
 	  break;
 
       if (i == nkeywords)
-        continue;
+	continue;
 
       /* Record that we recognized the keyword.  If a keywords
 	 was found more than once, it's an error.  */
@@ -3672,6 +3851,11 @@
 	    return 0;
 	  break;
 
+	case IMAGE_STRING_OR_NIL_VALUE:
+	  if (!STRINGP (value) && !NILP (value))
+	    return 0;
+	  break;
+
 	case IMAGE_SYMBOL_VALUE:
 	  if (!SYMBOLP (value))
 	    return 0;
@@ -3691,7 +3875,7 @@
 	    break;
 	  return 0;
 
-        case IMAGE_ASCENT_VALUE:
+	case IMAGE_ASCENT_VALUE:
 	  if (SYMBOLP (value) && EQ (value, Qcenter))
 	    break;
 	  else if (INTEGERP (value)
@@ -3780,6 +3964,63 @@
 }
 
 
+DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
+       doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
+PIXELS non-nil means return the size in pixels, otherwise return the
+size in canonical character units.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, pixels, frame)
+     Lisp_Object spec, pixels, frame;
+{
+  Lisp_Object size;
+
+  size = Qnil;
+  if (valid_image_p (spec))
+    {
+      struct frame *f = check_x_frame (frame);
+      int id = lookup_image (f, spec);
+      struct image *img = IMAGE_FROM_ID (f, id);
+      int width = img->width + 2 * img->hmargin;
+      int height = img->height + 2 * img->vmargin;
+
+      if (NILP (pixels))
+	size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
+		      make_float ((double) height / FRAME_LINE_HEIGHT (f)));
+      else
+	size = Fcons (make_number (width), make_number (height));
+    }
+  else
+    error ("Invalid image specification");
+
+  return size;
+}
+
+
+DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
+       doc: /* Return t if image SPEC has a mask bitmap.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, frame)
+     Lisp_Object spec, frame;
+{
+  Lisp_Object mask;
+
+  mask = Qnil;
+  if (valid_image_p (spec))
+    {
+      struct frame *f = check_x_frame (frame);
+      int id = lookup_image (f, spec);
+      struct image *img = IMAGE_FROM_ID (f, id);
+      if (img->mask)
+	mask = Qt;
+    }
+  else
+    error ("Invalid image specification");
+
+  return mask;
+}
+
 
 
 /***********************************************************************
@@ -3876,8 +4117,12 @@
   if (img->ascent == CENTERED_IMAGE_ASCENT)
     {
       if (face->font)
-	ascent = height / 2 - (FONT_DESCENT(face->font)
-                               - FONT_BASE(face->font)) / 2;
+	/* This expression is arranged so that if the image can't be
+	   exactly centered, it will be moved slightly up.  This is
+	   because a typical font is `top-heavy' (due to the presence
+	   uppercase letters), so the image placement should err towards
+	   being top-heavy too.  It also just generally looks better.  */
+	ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
       else
 	ascent = height / 2;
     }
@@ -3887,18 +4132,155 @@
   return ascent;
 }
 
+
+/* Image background colors.  */
+
+static unsigned long
+four_corners_best (ximg, width, height)
+     XImagePtr ximg;
+     unsigned long width, height;
+{
+  unsigned long corners[4], best;
+  int i, best_count;
+
+  /* Get the colors at the corners of ximg.  */
+  corners[0] = XGetPixel (ximg, 0, 0);
+  corners[1] = XGetPixel (ximg, width - 1, 0);
+  corners[2] = XGetPixel (ximg, width - 1, height - 1);
+  corners[3] = XGetPixel (ximg, 0, height - 1);
+
+  /* Choose the most frequently found color as background.  */
+  for (i = best_count = 0; i < 4; ++i)
+    {
+      int j, n;
+
+      for (j = n = 0; j < 4; ++j)
+	if (corners[i] == corners[j])
+	  ++n;
+
+      if (n > best_count)
+	best = corners[i], best_count = n;
+    }
+
+  return best;
+}
+
+/* Return the `background' field of IMG.  If IMG doesn't have one yet,
+   it is guessed heuristically.  If non-zero, XIMG is an existing XImage
+   object to use for the heuristic.  */
+
+unsigned long
+image_background (img, f, ximg)
+     struct image *img;
+     struct frame *f;
+     XImagePtr ximg;
+{
+  if (! img->background_valid)
+    /* IMG doesn't have a background yet, try to guess a reasonable value.  */
+    {
+      int free_ximg = !ximg;
+
+      if (! ximg)
+	ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+			  0, 0, img->width, img->height, ~0, ZPixmap);
+
+      img->background = four_corners_best (ximg, img->width, img->height);
+
+      if (free_ximg)
+	XDestroyImage (ximg);
+
+      img->background_valid = 1;
+    }
+
+  return img->background;
+}
+
+/* Return the `background_transparent' field of IMG.  If IMG doesn't
+   have one yet, it is guessed heuristically.  If non-zero, MASK is an
+   existing XImage object to use for the heuristic.  */
+
+int
+image_background_transparent (img, f, mask)
+     struct image *img;
+     struct frame *f;
+     XImagePtr mask;
+{
+  if (! img->background_transparent_valid)
+    /* IMG doesn't have a background yet, try to guess a reasonable value.  */
+    {
+      if (img->mask)
+	{
+	  int free_mask = !mask;
+
+	  if (! mask)
+	    mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
+			      0, 0, img->width, img->height, ~0, ZPixmap);
+
+	  img->background_transparent
+	    = four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN (f);
+
+	  if (free_mask)
+	    XDestroyImage (mask);
+	}
+      else
+	img->background_transparent = 0;
+
+      img->background_transparent_valid = 1;
+    }
+
+  return img->background_transparent;
+}
 
 
 /***********************************************************************
 		  Helper functions for X image types
  ***********************************************************************/
 
+static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
+				 int, int));
 static void x_clear_image P_ ((struct frame *f, struct image *img));
 static unsigned long x_alloc_image_color P_ ((struct frame *f,
 					      struct image *img,
 					      Lisp_Object color_name,
 					      unsigned long dflt));
 
+
+/* Clear X resources of image IMG on frame F.  PIXMAP_P non-zero means
+   free the pixmap if any.  MASK_P non-zero means clear the mask
+   pixmap if any.  COLORS_P non-zero means free colors allocated for
+   the image, if any.  */
+
+static void
+x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
+     struct frame *f;
+     struct image *img;
+     int pixmap_p, mask_p, colors_p;
+{
+  if (pixmap_p && img->pixmap)
+    {
+      XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
+      img->pixmap = NULL;
+      img->background_valid = 0;
+    }
+
+  if (mask_p && img->mask)
+    {
+      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+      img->mask = NULL;
+      img->background_transparent_valid = 0;
+    }
+
+  if (colors_p && img->ncolors)
+    {
+#if 0  /* TODO: color table support.  */
+      x_free_colors (f, img->colors, img->ncolors);
+#endif
+      xfree (img->colors);
+      img->colors = NULL;
+      img->ncolors = 0;
+    }
+}
+
 /* Free X resources of image IMG which is used on frame F.  */
 
 static void
@@ -3906,39 +4288,9 @@
      struct frame *f;
      struct image *img;
 {
-#if 0 /* MAC_TODO: W32 image support  */
-
-  if (img->pixmap)
-    {
-      BLOCK_INPUT;
-      XFreePixmap (NULL, img->pixmap);
-      img->pixmap = 0;
-      UNBLOCK_INPUT;
-    }
-
-  if (img->ncolors)
-    {
-      int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
-
-      /* If display has an immutable color map, freeing colors is not
-	 necessary and some servers don't allow it.  So don't do it.  */
-      if (class != StaticColor
-	  && class != StaticGray
-	  && class != TrueColor)
-	{
-	  Colormap cmap;
-	  BLOCK_INPUT;
-	  cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
-	  XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
-		       img->ncolors, 0);
-	  UNBLOCK_INPUT;
-	}
-
-      xfree (img->colors);
-      img->colors = NULL;
-      img->ncolors = 0;
-    }
-#endif /* MAC_TODO */
+  BLOCK_INPUT;
+  x_clear_image_1 (f, img, 1, 1, 1);
+  UNBLOCK_INPUT;
 }
 
 
@@ -3954,13 +4306,12 @@
      Lisp_Object color_name;
      unsigned long dflt;
 {
-#if 0 /* MAC_TODO: allocing colors.  */
   XColor color;
   unsigned long result;
 
   xassert (STRINGP (color_name));
 
-  if (w32_defined_color (f, SDATA (color_name), &color, 1))
+  if (mac_defined_color (f, SDATA (color_name), &color, 1))
     {
       /* This isn't called frequently so we get away with simply
 	 reallocating the color vector to the needed size, here.  */
@@ -3973,9 +4324,8 @@
     }
   else
     result = dflt;
+
   return result;
-#endif /* MAC_TODO */
-  return 0;
 }
 
 
@@ -3985,6 +4335,7 @@
  ***********************************************************************/
 
 static void cache_image P_ ((struct frame *f, struct image *img));
+static void postprocess_image P_ ((struct frame *, struct image *));
 
 
 /* Return a new, initialized image cache that is allocated from the
@@ -4049,20 +4400,23 @@
     {
       EMACS_TIME t;
       unsigned long old;
-      int i, any_freed_p = 0;
+      int i, nfreed;
 
       EMACS_GET_TIME (t);
       old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
 
-      for (i = 0; i < c->used; ++i)
+      /* Block input so that we won't be interrupted by a SIGIO
+	 while being in an inconsistent state.  */
+      BLOCK_INPUT;
+
+      for (i = nfreed = 0; i < c->used; ++i)
 	{
 	  struct image *img = c->images[i];
 	  if (img != NULL
-	      && (force_p
-		  || (img->timestamp > old)))
+	      && (force_p || img->timestamp < old))
 	    {
 	      free_image (f, img);
-	      any_freed_p = 1;
+	      ++nfreed;
 	    }
 	}
 
@@ -4070,11 +4424,22 @@
 	 Emacs was iconified for a longer period of time.  In that
 	 case, current matrices may still contain references to
 	 images freed above.  So, clear these matrices.  */
-      if (any_freed_p)
+      if (nfreed)
 	{
-	  clear_current_matrices (f);
+	  Lisp_Object tail, frame;
+
+	  FOR_EACH_FRAME (tail, frame)
+	    {
+	      struct frame *f = XFRAME (frame);
+	      if (FRAME_MAC_P (f)
+		  && FRAME_X_IMAGE_CACHE (f) == c)
+		clear_current_matrices (f);
+	    }
+
 	  ++windows_or_buffers_changed;
 	}
+
+      UNBLOCK_INPUT;
     }
 }
 
@@ -4084,7 +4449,7 @@
        doc: /* Clear the image cache of FRAME.
 FRAME nil or omitted means use the selected frame.
 FRAME t means clear the image caches of all frames.  */)
-  (frame)
+     (frame)
      Lisp_Object frame;
 {
   if (EQ (frame, Qt))
@@ -4102,6 +4467,81 @@
 }
 
 
+/* Compute masks and transform image IMG on frame F, as specified
+   by the image's specification,  */
+
+static void
+postprocess_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  /* Manipulation of the image's mask.  */
+  if (img->pixmap)
+    {
+      Lisp_Object conversion, spec;
+      Lisp_Object mask;
+
+      spec = img->spec;
+
+      /* `:heuristic-mask t'
+	 `:mask heuristic'
+	 means build a mask heuristically.
+	 `:heuristic-mask (R G B)'
+	 `:mask (heuristic (R G B))'
+	 means build a mask from color (R G B) in the
+	 image.
+	 `:mask nil'
+	 means remove a mask, if any.  */
+
+      mask = image_spec_value (spec, QCheuristic_mask, NULL);
+      if (!NILP (mask))
+	x_build_heuristic_mask (f, img, mask);
+      else
+	{
+	  int found_p;
+
+	  mask = image_spec_value (spec, QCmask, &found_p);
+
+	  if (EQ (mask, Qheuristic))
+	    x_build_heuristic_mask (f, img, Qt);
+	  else if (CONSP (mask)
+		   && EQ (XCAR (mask), Qheuristic))
+	    {
+	      if (CONSP (XCDR (mask)))
+		x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
+	      else
+		x_build_heuristic_mask (f, img, XCDR (mask));
+	    }
+	  else if (NILP (mask) && found_p && img->mask)
+	    {
+	      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+	      img->mask = NULL;
+	    }
+	}
+
+
+      /* Should we apply an image transformation algorithm?  */
+      conversion = image_spec_value (spec, QCconversion, NULL);
+      if (EQ (conversion, Qdisabled))
+	x_disable_image (f, img);
+      else if (EQ (conversion, Qlaplace))
+	x_laplace (f, img);
+      else if (EQ (conversion, Qemboss))
+	x_emboss (f, img);
+      else if (CONSP (conversion)
+	       && EQ (XCAR (conversion), Qedge_detection))
+	{
+	  Lisp_Object tem;
+	  tem = XCDR (conversion);
+	  if (CONSP (tem))
+	    x_edge_detection (f, img,
+			      Fplist_get (tem, QCmatrix),
+			      Fplist_get (tem, QCcolor_adjustment));
+	}
+    }
+}
+
+
 /* Return the id of image with Lisp specification SPEC on frame F.
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
 
@@ -4135,11 +4575,12 @@
   /* If not found, create a new image and cache it.  */
   if (img == NULL)
     {
+      extern Lisp_Object Qpostscript;
+
       BLOCK_INPUT;
       img = make_image (spec, hash);
       cache_image (f, img);
       img->load_failed_p = img->type->load (f, img) == 0;
-      xassert (!interrupt_input_blocked);
 
       /* If we can't load the image, and we don't have a width and
 	 height, use some arbitrary width and height so that we can
@@ -4158,14 +4599,15 @@
       else
 	{
 	  /* Handle image type independent image attributes
-	     `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'.  */
-	  Lisp_Object ascent, margin, relief;
+	     `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
+	     `:background COLOR'.  */
+	  Lisp_Object ascent, margin, relief, bg;
 
 	  ascent = image_spec_value (spec, QCascent, NULL);
 	  if (INTEGERP (ascent))
 	    img->ascent = XFASTINT (ascent);
 	  else if (EQ (ascent, Qcenter))
-            img->ascent = CENTERED_IMAGE_ASCENT;
+	    img->ascent = CENTERED_IMAGE_ASCENT;
 
 	  margin = image_spec_value (spec, QCmargin, NULL);
 	  if (INTEGERP (margin) && XINT (margin) >= 0)
@@ -4186,7 +4628,26 @@
 	      img->hmargin += abs (img->relief);
 	      img->vmargin += abs (img->relief);
 	    }
+
+	  if (! img->background_valid)
+	    {
+	      bg = image_spec_value (img->spec, QCbackground, NULL);
+	      if (!NILP (bg))
+		{
+		  img->background
+		    = x_alloc_image_color (f, img, bg,
+					   FRAME_BACKGROUND_PIXEL (f));
+		  img->background_valid = 1;
+		}
+	    }
+
+	  /* Do image transformations and compute masks, unless we
+	     don't have the image yet.  */
+	  if (!EQ (*img->type->type, Qpostscript))
+	    postprocess_image (f, img);
 	}
+
+      UNBLOCK_INPUT;
     }
 
   /* We're using IMG, so set its timestamp to `now'.  */
@@ -4266,48 +4727,23 @@
 			    Mac support code
  ***********************************************************************/
 
-#if 0 /* MAC_TODO: Mac specific image code.  */
-
 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
-                                            XImage **, Pixmap *));
-static void x_destroy_x_image P_ ((XImage *));
-static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
-
-
-/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
-   frame F.  Set *XIMG and *PIXMAP to the XImage and Pixmap created.
-   Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
-   via xmalloc.  Print error messages via image_error if an error
-   occurs.  Value is non-zero if successful.  */
-
-static int
+					    XImagePtr *, Pixmap *));
+static void x_destroy_x_image P_ ((XImagePtr));
+static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
+
+
 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
      struct frame *f;
      int width, height, depth;
-     XImage **ximg;
+     XImagePtr *ximg;
      Pixmap *pixmap;
 {
-#if 0 /* MAC_TODO: Image support for Mac */
-  Display *display = FRAME_W32_DISPLAY (f);
-  Screen *screen = FRAME_X_SCREEN (f);
-  Window window = FRAME_W32_WINDOW (f);
+  Display *display = FRAME_MAC_DISPLAY (f);
+  Window window = FRAME_MAC_WINDOW (f);
 
   xassert (interrupt_input_blocked);
 
-  if (depth <= 0)
-    depth = DefaultDepthOfScreen (screen);
-  *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
-			depth, ZPixmap, 0, NULL, width, height,
-			depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
-  if (*ximg == NULL)
-    {
-      image_error ("Unable to allocate X image", Qnil, Qnil);
-      return 0;
-    }
-
-  /* Allocate image raster.  */
-  (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
-
   /* Allocate a pixmap of the same size.  */
   *pixmap = XCreatePixmap (display, window, width, height, depth);
   if (*pixmap == 0)
@@ -4317,52 +4753,39 @@
       image_error ("Unable to create X pixmap", Qnil, Qnil);
       return 0;
     }
-#endif /* MAC_TODO */
+
+  LockPixels (GetGWorldPixMap (*pixmap));
+  *ximg = *pixmap;
   return 1;
 }
 
-
-/* Destroy XImage XIMG.  Free XIMG->data.  */
-
 static void
 x_destroy_x_image (ximg)
-     XImage *ximg;
+     XImagePtr ximg;
 {
   xassert (interrupt_input_blocked);
   if (ximg)
-    {
-      xfree (ximg->data);
-      ximg->data = NULL;
-      XDestroyImage (ximg);
-    }
-}
-
-
-/* Put XImage XIMG into pixmap PIXMAP on frame F.  WIDTH and HEIGHT
-   are width and height of both the image and pixmap.  */
+    XDestroyImage (ximg);
+}
 
 static void
 x_put_x_image (f, ximg, pixmap, width, height)
      struct frame *f;
-     XImage *ximg;
+     XImagePtr ximg;
      Pixmap pixmap;
 {
-  GC gc;
-
-  xassert (interrupt_input_blocked);
-  gc = XCreateGC (NULL, pixmap, 0, NULL);
-  XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
-  XFreeGC (NULL, gc);
-}
-
-#endif /* MAC_TODO */
+  xassert (ximg == pixmap);
+}
+
 
 
 /***********************************************************************
-			      Searching files
+			      File Handling
  ***********************************************************************/
 
 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
+static char *slurp_file P_ ((char *, int *));
+
 
 /* Find image file FILE.  Look in data-directory, then
    x-bitmap-file-path.  Value is the full name of the file found, or
@@ -4383,7 +4806,7 @@
   /* Try to find FILE in data-directory, then x-bitmap-file-path.  */
   fd = openp (search_path, file, Qnil, &file_found, Qnil);
 
-  if (fd < 0)
+  if (fd == -1)
     file_found = Qnil;
   else
     close (fd);
@@ -4392,17 +4815,398 @@
   return file_found;
 }
 
+
+/* Read FILE into memory.  Value is a pointer to a buffer allocated
+   with xmalloc holding FILE's contents.  Value is null if an error
+   occurred.  *SIZE is set to the size of the file.  */
+
+static char *
+slurp_file (file, size)
+     char *file;
+     int *size;
+{
+  FILE *fp = NULL;
+  char *buf = NULL;
+  struct stat st;
+
+  if (stat (file, &st) == 0
+      && (fp = fopen (file, "r")) != NULL
+      && (buf = (char *) xmalloc (st.st_size),
+	  fread (buf, 1, st.st_size, fp) == st.st_size))
+    {
+      *size = st.st_size;
+      fclose (fp);
+    }
+  else
+    {
+      if (fp)
+	fclose (fp);
+      if (buf)
+	{
+	  xfree (buf);
+	  buf = NULL;
+	}
+    }
+
+  return buf;
+}
+
+
+
+/***********************************************************************
+			Image Load Functions
+ ***********************************************************************/
+
+static int image_load_quicktime P_ ((struct frame *, struct image *img,
+				     OSType));
+#ifdef MAC_OSX
+static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
+#endif
+
+
+static OSErr
+find_image_fsspec (specified_file, file, fss)
+     Lisp_Object specified_file, *file;
+     FSSpec *fss;
+{
+#if TARGET_API_MAC_CARBON
+  FSRef fsr;
+#else
+  Str255 mac_pathname;
+#endif
+  OSErr err;
+
+  *file = x_find_image_file (specified_file);
+  if (!STRINGP (*file))
+    return fnfErr;		/* file or directory not found;
+				   incomplete pathname */
+  /* Try to open the image file.  */
+#if TARGET_API_MAC_CARBON
+  err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
+  if (err == noErr)
+    err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
+#else
+  if (posix_to_mac_pathname (SDATA (*file), mac_pathname, MAXPATHLEN+1) == 0)
+    return fnfErr;
+  c2pstr (mac_pathname);
+  err = FSMakeFSSpec (0, 0, mac_pathname, fss);
+#endif
+  return err;
+}
+
+
+static int
+image_load_qt_1 (f, img, type, fss, dh)
+     struct frame *f;
+     struct image *img;
+     OSType type;
+     FSSpec *fss;
+     Handle dh;
+{
+  OSErr err;
+  GraphicsImportComponent gi;
+  Rect rect;
+  int width, height;
+  short draw_all_pixels;
+  Lisp_Object specified_bg;
+  XColor color;
+  XImagePtr ximg;
+  RGBColor bg_color;
+
+  err = OpenADefaultComponent (GraphicsImporterComponentType,
+			       type, &gi);
+  if (err != noErr)
+    {
+      image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
+      return 0;
+    }
+  if (dh == NULL)
+    {
+      /* read from file system spec */
+      err = GraphicsImportSetDataFile (gi, fss);
+      if (err != noErr)
+	{
+	  image_error ("Cannot set fsspec to graphics importer for '%s'",
+		       img->spec, Qnil);
+	  goto error;
+	}
+    }
+  else
+    {
+      /* read from data handle */
+      err = GraphicsImportSetDataHandle (gi, dh);
+      if (err != noErr)
+	{
+	  image_error ("Cannot set data handle to graphics importer for `%s'",
+		       img->spec, Qnil);
+	  goto error;
+	}
+    }
+  err = GraphicsImportGetNaturalBounds (gi, &rect);
+  if (err != noErr)
+    {
+      image_error ("Error reading `%s'", img->spec, Qnil);
+      goto error;
+    }
+  width = img->width = rect.right - rect.left;
+  height = img->height = rect.bottom - rect.top;
+  err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
+#if 0
+  /* Don't check the error code here.  It may have an undocumented
+     value -32766. */
+  if (err != noErr)
+    {
+      image_error ("Error reading `%s'", img->spec, Qnil);
+      goto error;
+    }
+#endif
+  if (draw_all_pixels != graphicsImporterDrawsAllPixels)
+    {
+      specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+      if (!STRINGP (specified_bg) ||
+	  !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+	{
+	  color.pixel = FRAME_BACKGROUND_PIXEL (f);
+	  color.red = RED16_FROM_ULONG (color.pixel);
+	  color.green = GREEN16_FROM_ULONG (color.pixel);
+	  color.blue = BLUE16_FROM_ULONG (color.pixel);
+	}
+    }
+
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    goto error;
+  if (draw_all_pixels != graphicsImporterDrawsAllPixels)
+    {
+      SetGWorld (ximg, NULL);
+      bg_color.red = color.red;
+      bg_color.green = color.green;
+      bg_color.blue = color.blue;
+      RGBBackColor (&bg_color);
+#if TARGET_API_MAC_CARBON
+      GetPortBounds (ximg, &rect);
+      EraseRect (&rect);
+#else
+      EraseRect (&(ximg->portRect));
+#endif
+    }
+  GraphicsImportSetGWorld (gi, ximg, NULL);
+  GraphicsImportDraw (gi);
+  CloseComponent (gi);
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
+
+  /* Put the image into the pixmap.  */
+  x_put_x_image (f, ximg, img->pixmap, width, height);
+  x_destroy_x_image (ximg);
+  return 1;
+
+ error:
+  CloseComponent (gi);
+  return 0;
+}
+
+
+/* Load an image using the QuickTime Graphics Importer.
+   Note: The alpha channel does not work for PNG images. */
+static int
+image_load_quicktime (f, img, type)
+     struct frame *f;
+     struct image *img;
+     OSType type;
+{
+  Lisp_Object specified_file;
+  Lisp_Object specified_data;
+  OSErr err;
+
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  if (NILP (specified_data))
+    {
+      /* Read from a file */
+      Lisp_Object file;
+      FSSpec fss;
+
+      err = find_image_fsspec (specified_file, &file, &fss);
+      if (err != noErr)
+	{
+	  if (err == fnfErr)
+	    image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  else
+	    image_error ("Cannot open `%s'", file, Qnil);
+	  return 0;
+	}
+      return image_load_qt_1 (f, img, type, &fss, NULL);
+    }
+  else
+    {
+      /* Memory source! */
+      int success_p;
+      Handle dh;
+
+      err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
+      if (err != noErr)
+	{
+	  image_error ("Cannot allocate data handle for `%s'",
+		       img->spec, Qnil);
+	  return 0;
+	}
+      success_p = image_load_qt_1 (f, img, type, NULL, dh);
+      DisposeHandle (dh);
+      return success_p;
+    }
+}
+
+
+#ifdef MAC_OSX
+/* Load a PNG/JPEG image using Quartz 2D decoding routines.
+   CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
+   So don't use this function directly but determine at runtime
+   whether it exists. */
+typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
+  (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
+static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
+
+
+static void
+init_image_func_pointer ()
+{
+  if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
+    {
+      MyCGImageCreateWithPNGDataProvider
+	= (CGImageCreateWithPNGDataProviderProcType)
+	NSAddressOfSymbol (NSLookupAndBindSymbol
+			   ("_CGImageCreateWithPNGDataProvider"));
+    }
+  else
+    MyCGImageCreateWithPNGDataProvider = NULL;
+}
+
+
+static int
+image_load_quartz2d (f, img, png_p)
+     struct frame *f;
+     struct image *img;
+     int png_p;
+{
+  Lisp_Object file, specified_file;
+  Lisp_Object specified_data, specified_bg;
+  struct gcpro gcpro1;
+  CGDataProviderRef source;
+  CGImageRef image;
+  int width, height;
+  XColor color;
+  XImagePtr ximg = NULL;
+  CGContextRef context;
+  CGRect rectangle;
+
+  /* Open the file.  */
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  file = Qnil;
+  GCPRO1 (file);
+
+  if (NILP (specified_data))
+    {
+      CFStringRef path;
+      CFURLRef url;
+
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+      path = CFStringCreateWithCString (NULL, SDATA (file),
+					kCFStringEncodingUTF8);
+      url = CFURLCreateWithFileSystemPath (NULL, path,
+					   kCFURLPOSIXPathStyle, 0);
+      CFRelease (path);
+      source = CGDataProviderCreateWithURL (url);
+      CFRelease (url);
+    }
+  else
+    source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
+					   SBYTES (specified_data), NULL);
+
+  if (png_p)
+    image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
+						   kCGRenderingIntentDefault);
+  else
+    image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
+					       kCGRenderingIntentDefault);
+
+  CGDataProviderRelease (source);
+  if (image == NULL)
+    {
+      UNGCPRO;
+      image_error ("Error reading image `%s'", img->spec, Qnil);
+      return 0;
+    }
+
+  if (png_p)
+    {
+      specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+      if (!STRINGP (specified_bg) ||
+	  !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+	{
+	  color.pixel = FRAME_BACKGROUND_PIXEL (f);
+	  color.red = RED16_FROM_ULONG (color.pixel);
+	  color.green = GREEN16_FROM_ULONG (color.pixel);
+	  color.blue = BLUE16_FROM_ULONG (color.pixel);
+	}
+    }
+  width = img->width = CGImageGetWidth (image);
+  height = img->height = CGImageGetHeight (image);
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    {
+      CGImageRelease (image);
+      UNGCPRO;
+      return 0;
+    }
+  rectangle = CGRectMake (0, 0, width, height);
+  QDBeginCGContext (ximg, &context);
+  if (png_p)
+    {
+      CGContextSetRGBFillColor (context, color.red / 65535.0,
+				color.green / 65535.0,
+				color.blue / 65535.0, 1.0);
+      CGContextFillRect (context, rectangle);
+    }
+  CGContextDrawImage (context, rectangle, image);
+  QDEndCGContext (ximg, &context);
+  CGImageRelease (image);
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
+
+  /* Put the image into the pixmap.  */
+  x_put_x_image (f, ximg, img->pixmap, width, height);
+  x_destroy_x_image (ximg);
+  UNGCPRO;
+  return 1;
+}
+#endif
+
+
 
 /***********************************************************************
 			      XBM images
  ***********************************************************************/
 
+static int xbm_scan P_ ((char **, char *, char *, int *));
 static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
-					 Lisp_Object file));
+static int xbm_load_image P_ ((struct frame *f, struct image *img,
+			       char *, char *));
 static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
-					  unsigned char **));
+static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
+				     unsigned char **));
+static int xbm_file_p P_ ((Lisp_Object));
 
 
 /* Indices of image specification fields in xbm_format, below.  */
@@ -4421,6 +5225,7 @@
   XBM_RELIEF,
   XBM_ALGORITHM,
   XBM_HEURISTIC_MASK,
+  XBM_MASK,
   XBM_LAST
 };
 
@@ -4434,13 +5239,14 @@
   {":width",		IMAGE_POSITIVE_INTEGER_VALUE,		0},
   {":height",		IMAGE_POSITIVE_INTEGER_VALUE,		0},
   {":data",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":foreground",	IMAGE_STRING_VALUE,			0},
-  {":background",	IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":foreground",	IMAGE_STRING_OR_NIL_VALUE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
   {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0}
 };
 
 /* Structure describing the image type XBM.  */
@@ -4483,10 +5289,14 @@
    3. a vector of strings or bool-vectors, one for each line of the
    bitmap.
 
+   4. A string containing an in-memory XBM file.  WIDTH and HEIGHT
+   may not be specified in this case because they are defined in the
+   XBM file.
+
    Both the file and data forms may contain the additional entries
    `:background COLOR' and `:foreground COLOR'.  If not present,
    foreground and background of the frame on which the image is
-   displayed, is used.  */
+   displayed is used.  */
 
 static int
 xbm_image_p (object)
@@ -4505,6 +5315,12 @@
       if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
 	return 0;
     }
+  else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
+    {
+      /* In-memory XBM file.  */
+      if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
+	return 0;
+    }
   else
     {
       Lisp_Object data;
@@ -4566,11 +5382,6 @@
 	return 0;
     }
 
-  /* Baseline must be a value between 0 and 100 (a percentage).  */
-  if (kw[XBM_ASCENT].count
-      && XFASTINT (kw[XBM_ASCENT].value) > 100)
-    return 0;
-
   return 1;
 }
 
@@ -4582,30 +5393,33 @@
    scanning a number, store its value in *IVAL.  */
 
 static int
-xbm_scan (fp, sval, ival)
-     FILE *fp;
+xbm_scan (s, end, sval, ival)
+     char **s, *end;
      char *sval;
      int *ival;
 {
   int c;
 
+ loop:
+
   /* Skip white space.  */
-  while ((c = fgetc (fp)) != EOF && isspace (c))
+  while (*s < end && (c = *(*s)++, isspace (c)))
     ;
 
-  if (c == EOF)
+  if (*s >= end)
     c = 0;
   else if (isdigit (c))
     {
       int value = 0, digit;
 
-      if (c == '0')
+      if (c == '0' && *s < end)
 	{
-	  c = fgetc (fp);
+	  c = *(*s)++;
 	  if (c == 'x' || c == 'X')
 	    {
-	      while ((c = fgetc (fp)) != EOF)
+	      while (*s < end)
 		{
+		  c = *(*s)++;
 		  if (isdigit (c))
 		    digit = c - '0';
 		  else if (c >= 'a' && c <= 'f')
@@ -4620,53 +5434,66 @@
 	  else if (isdigit (c))
 	    {
 	      value = c - '0';
-	      while ((c = fgetc (fp)) != EOF
-		     && isdigit (c))
+	      while (*s < end
+		     && (c = *(*s)++, isdigit (c)))
 		value = 8 * value + c - '0';
 	    }
 	}
       else
 	{
 	  value = c - '0';
-	  while ((c = fgetc (fp)) != EOF
-		 && isdigit (c))
+	  while (*s < end
+		 && (c = *(*s)++, isdigit (c)))
 	    value = 10 * value + c - '0';
 	}
 
-      if (c != EOF)
-	ungetc (c, fp);
+      if (*s < end)
+	*s = *s - 1;
       *ival = value;
       c = XBM_TK_NUMBER;
     }
   else if (isalpha (c) || c == '_')
     {
       *sval++ = c;
-      while ((c = fgetc (fp)) != EOF
-	     && (isalnum (c) || c == '_'))
+      while (*s < end
+	     && (c = *(*s)++, (isalnum (c) || c == '_')))
 	*sval++ = c;
       *sval = 0;
-      if (c != EOF)
-	ungetc (c, fp);
+      if (*s < end)
+	*s = *s - 1;
       c = XBM_TK_IDENT;
     }
+  else if (c == '/' && **s == '*')
+    {
+      /* C-style comment.  */
+      ++*s;
+      while (**s && (**s != '*' || *(*s + 1) != '/'))
+	++*s;
+      if (**s)
+	{
+	  *s += 2;
+	  goto loop;
+	}
+    }
 
   return c;
 }
 
 
 /* Replacement for XReadBitmapFileData which isn't available under old
-   X versions.  FILE is the name of the bitmap file to read.  Set
-   *WIDTH and *HEIGHT to the width and height of the image.  Return in
-   *DATA the bitmap data allocated with xmalloc.  Value is non-zero if
-   successful.  */
+   X versions.  CONTENTS is a pointer to a buffer to parse; END is the
+   buffer's end.  Set *WIDTH and *HEIGHT to the width and height of
+   the image.  Return in *DATA the bitmap data allocated with xmalloc.
+   Value is non-zero if successful.  DATA null means just test if
+   CONTENTS looks like an in-memory XBM file.  */
 
 static int
-xbm_read_bitmap_file_data (file, width, height, data)
-     char *file;
+xbm_read_bitmap_data (contents, end, width, height, data)
+     char *contents, *end;
      int *width, *height;
      unsigned char **data;
 {
-  FILE *fp;
+  char *s = contents;
   char buffer[BUFSIZ];
   int padding_p = 0;
   int v10 = 0;
@@ -4676,7 +5503,7 @@
   int LA1;
 
 #define match() \
-     LA1 = xbm_scan (fp, buffer, &value)
+     LA1 = xbm_scan (&s, end, buffer, &value)
 
 #define expect(TOKEN)		\
      if (LA1 != (TOKEN)) 	\
@@ -4690,13 +5517,10 @@
      else							\
        goto failure
 
-  fp = fopen (file, "r");
-  if (fp == NULL)
-    return 0;
-
   *width = *height = -1;
-  *data = NULL;
-  LA1 = xbm_scan (fp, buffer, &value);
+  if (data)
+    *data = NULL;
+  LA1 = xbm_scan (&s, end, buffer, &value);
 
   /* Parse defines for width, height and hot-spots.  */
   while (LA1 == '#')
@@ -4719,6 +5543,8 @@
 
   if (*width < 0 || *height < 0)
     goto failure;
+  else if (data == NULL)
+    goto success;
 
   /* Parse bits.  Must start with `static'.  */
   expect_ident ("static");
@@ -4756,7 +5582,6 @@
 
   if (v10)
     {
-
       for (i = 0; i < nbytes; i += 2)
 	{
 	  int val = value;
@@ -4788,13 +5613,12 @@
 	}
     }
 
-  fclose (fp);
+ success:
   return 1;
 
  failure:
 
-  fclose (fp);
-  if (*data)
+  if (data && *data)
     {
       xfree (*data);
       *data = NULL;
@@ -4807,38 +5631,24 @@
 }
 
 
-/* Load XBM image IMG which will be displayed on frame F from file
-   SPECIFIED_FILE.  Value is non-zero if successful.  */
+/* Load XBM image IMG which will be displayed on frame F from buffer
+   CONTENTS.  END is the end of the buffer.  Value is non-zero if
+   successful.  */
 
 static int
-xbm_load_image_from_file (f, img, specified_file)
+xbm_load_image (f, img, contents, end)
      struct frame *f;
      struct image *img;
-     Lisp_Object specified_file;
+     char *contents, *end;
 {
   int rc;
   unsigned char *data;
   int success_p = 0;
-  Lisp_Object file;
-  struct gcpro gcpro1;
-
-  xassert (STRINGP (specified_file));
-  file = Qnil;
-  GCPRO1 (file);
-
-  file = x_find_image_file (specified_file);
-  if (!STRINGP (file))
-    {
-      image_error ("Cannot find image file `%s'", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
-
-  rc = xbm_read_bitmap_file_data (SDATA (file), &img->width,
-				  &img->height, &data);
+
+  rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
   if (rc)
     {
-      int depth = one_mac_display_info.n_cbits;
+      int depth = one_mac_display_info.n_planes;
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       Lisp_Object value;
@@ -4849,16 +5659,17 @@
       value = image_spec_value (img->spec, QCforeground, NULL);
       if (!NILP (value))
 	foreground = x_alloc_image_color (f, img, value, foreground);
-
       value = image_spec_value (img->spec, QCbackground, NULL);
       if (!NILP (value))
-	background = x_alloc_image_color (f, img, value, background);
-
-#if 0 /* MAC_TODO : Port image display to Mac */
-      BLOCK_INPUT;
+	{
+	  background = x_alloc_image_color (f, img, value, background);
+	  img->background = background;
+	  img->background_valid = 1;
+	}
+
       img->pixmap
-	= XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
-				       FRAME_W32_WINDOW (f),
+	= XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
+				       FRAME_MAC_WINDOW (f),
 				       data,
 				       img->width, img->height,
 				       foreground, background,
@@ -4868,22 +5679,33 @@
       if (img->pixmap == 0)
 	{
 	  x_clear_image (f, img);
-	  image_error ("Unable to create X pixmap for `%s'", file, Qnil);
+	  image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
 	}
       else
 	success_p = 1;
-
-      UNBLOCK_INPUT;
-#endif /* MAC_TODO */
     }
   else
     image_error ("Error loading XBM image `%s'", img->spec, Qnil);
 
-  UNGCPRO;
   return success_p;
 }
 
 
+/* Value is non-zero if DATA looks like an in-memory XBM file.  */
+
+static int
+xbm_file_p (data)
+     Lisp_Object data;
+{
+  int w, h;
+  return (STRINGP (data)
+	  && xbm_read_bitmap_data (SDATA (data),
+				   (SDATA (data)
+				    + SBYTES (data)),
+				   &w, &h, NULL));
+}
+
+
 /* Fill image IMG which is used on frame F with pixmap data.  Value is
    non-zero if successful.  */
 
@@ -4900,7 +5722,32 @@
   /* If IMG->spec specifies a file name, create a non-file spec from it.  */
   file_name = image_spec_value (img->spec, QCfile, NULL);
   if (STRINGP (file_name))
-    success_p = xbm_load_image_from_file (f, img, file_name);
+    {
+      Lisp_Object file;
+      char *contents;
+      int size;
+      struct gcpro gcpro1;
+
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
+	{
+	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+
+      contents = slurp_file (SDATA (file), &size);
+      if (contents == NULL)
+	{
+	  image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+
+      success_p = xbm_load_image (f, img, contents, contents + size);
+      UNGCPRO;
+    }
   else
     {
       struct image_keyword fmt[XBM_LAST];
@@ -4910,75 +5757,80 @@
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       char *bits;
       int parsed_p;
-
-      /* Parse the list specification.  */
+      int in_memory_file_p = 0;
+
+      /* See if data looks like an in-memory XBM file.  */
+      data = image_spec_value (img->spec, QCdata, NULL);
+      in_memory_file_p = xbm_file_p (data);
+
+      /* Parse the image specification.  */
       bcopy (xbm_format, fmt, sizeof fmt);
       parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
       xassert (parsed_p);
 
       /* Get specified width, and height.  */
-      img->width = XFASTINT (fmt[XBM_WIDTH].value);
-      img->height = XFASTINT (fmt[XBM_HEIGHT].value);
-      xassert (img->width > 0 && img->height > 0);
-
-      BLOCK_INPUT;
-
-      if (fmt[XBM_ASCENT].count)
-	img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
+      if (!in_memory_file_p)
+	{
+	  img->width = XFASTINT (fmt[XBM_WIDTH].value);
+	  img->height = XFASTINT (fmt[XBM_HEIGHT].value);
+	  xassert (img->width > 0 && img->height > 0);
+	}
 
       /* Get foreground and background colors, maybe allocate colors.  */
-      if (fmt[XBM_FOREGROUND].count)
+      if (fmt[XBM_FOREGROUND].count
+	  && STRINGP (fmt[XBM_FOREGROUND].value))
 	foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
 					  foreground);
-      if (fmt[XBM_BACKGROUND].count)
+      if (fmt[XBM_BACKGROUND].count
+	  && STRINGP (fmt[XBM_BACKGROUND].value))
 	background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
 					  background);
 
-      /* Set bits to the bitmap image data.  */
-      data = fmt[XBM_DATA].value;
-      if (VECTORP (data))
+      if (in_memory_file_p)
+	success_p = xbm_load_image (f, img, SDATA (data),
+				    (SDATA (data)
+				     + SBYTES (data)));
+      else
 	{
-	  int i;
-	  char *p;
-	  int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
-
-	  p = bits = (char *) alloca (nbytes * img->height);
-	  for (i = 0; i < img->height; ++i, p += nbytes)
+	  if (VECTORP (data))
 	    {
-	      Lisp_Object line = XVECTOR (data)->contents[i];
-	      if (STRINGP (line))
-		bcopy (SDATA (line), p, nbytes);
-	      else
-		bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+	      int i;
+	      char *p;
+	      int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+
+	      p = bits = (char *) alloca (nbytes * img->height);
+	      for (i = 0; i < img->height; ++i, p += nbytes)
+		{
+		  Lisp_Object line = XVECTOR (data)->contents[i];
+		  if (STRINGP (line))
+		    bcopy (SDATA (line), p, nbytes);
+		  else
+		    bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+		}
+	    }
+	  else if (STRINGP (data))
+	    bits = SDATA (data);
+	  else
+	    bits = XBOOL_VECTOR (data)->data;
+
+	  /* Create the pixmap.  */
+	  depth = one_mac_display_info.n_planes;
+	  img->pixmap
+	    = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
+					   FRAME_MAC_WINDOW (f),
+					   bits,
+					   img->width, img->height,
+					   foreground, background,
+					   depth);
+	  if (img->pixmap)
+	    success_p = 1;
+	  else
+	    {
+	      image_error ("Unable to create pixmap for XBM image `%s'",
+			   img->spec, Qnil);
+	      x_clear_image (f, img);
 	    }
 	}
-      else if (STRINGP (data))
-	bits = SDATA (data);
-      else
-	bits = XBOOL_VECTOR (data)->data;
-
-#if 0 /* MAC_TODO : port Mac display code */
-      /* Create the pixmap.  */
-      depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
-      img->pixmap
-	= XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
-				       FRAME_W32_WINDOW (f),
-				       bits,
-				       img->width, img->height,
-				       foreground, background,
-				       depth);
-#endif /* MAC_TODO */
-
-      if (img->pixmap)
-	success_p = 1;
-      else
-	{
-	  image_error ("Unable to create pixmap for XBM image `%s'",
-                       img->spec, Qnil);
-	  x_clear_image (f, img);
-	}
-
-      UNBLOCK_INPUT;
     }
 
   return success_p;
@@ -5014,7 +5866,9 @@
   XPM_RELIEF,
   XPM_ALGORITHM,
   XPM_HEURISTIC_MASK,
+  XPM_MASK,
   XPM_COLOR_SYMBOLS,
+  XPM_BACKGROUND,
   XPM_LAST
 };
 
@@ -5026,12 +5880,14 @@
   {":type",		IMAGE_SYMBOL_VALUE,			1},
   {":file",		IMAGE_STRING_VALUE,			0},
   {":data",		IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
   {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
   {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":color-symbols",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":color-symbols",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type XBM.  */
@@ -5082,9 +5938,7 @@
 	  /* Either no `:color-symbols' or it's a list of conses
 	     whose car and cdr are strings.  */
 	  && (fmt[XPM_COLOR_SYMBOLS].count == 0
-	      || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
-	  && (fmt[XPM_ASCENT].count == 0
-	      || XFASTINT (fmt[XPM_ASCENT].value) < 100));
+	      || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
 }
 
 
@@ -5096,7 +5950,7 @@
      struct frame *f;
      struct image *img;
 {
-  int rc, i;
+  int rc;
   XpmAttributes attrs;
   Lisp_Object specified_file, color_symbols;
 
@@ -5111,10 +5965,10 @@
 #ifdef XpmAllocCloseColors
   attrs.alloc_close_colors = 1;
   attrs.valuemask |= XpmAllocCloseColors;
-#else
+#else /* not XpmAllocCloseColors */
   attrs.closeness = 600;
   attrs.valuemask |= XpmCloseness;
-#endif
+#endif /* not XpmAllocCloseColors */
 
   /* If image specification contains symbolic color definitions, add
      these to `attrs'.  */
@@ -5154,7 +6008,7 @@
 
   /* Create a pixmap for the image, either from a file, or from a
      string buffer containing data in the same format as an XPM file.  */
-  BLOCK_INPUT;
+
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   if (STRINGP (specified_file))
     {
@@ -5162,27 +6016,26 @@
       if (!STRINGP (file))
 	{
 	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNBLOCK_INPUT;
 	  return 0;
 	}
 
-      rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
+      rc = XpmReadFileToPixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
 				SDATA (file), &img->pixmap, &img->mask,
 				&attrs);
     }
   else
     {
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
-      rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
+      rc = XpmCreatePixmapFromBuffer (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
 				      SDATA (buffer),
 				      &img->pixmap, &img->mask,
 				      &attrs);
     }
-  UNBLOCK_INPUT;
 
   if (rc == XpmSuccess)
     {
-      /* Remember allocated colors.  */
+      int i;
+
       img->ncolors = attrs.nalloc_pixels;
       img->colors = (unsigned long *) xmalloc (img->ncolors
 					       * sizeof *img->colors);
@@ -5194,9 +6047,7 @@
       xassert (img->width > 0 && img->height > 0);
 
       /* The call to XpmFreeAttributes below frees attrs.alloc_pixels.  */
-      BLOCK_INPUT;
       XpmFreeAttributes (&attrs);
-      UNBLOCK_INPUT;
     }
   else
     {
@@ -5262,15 +6113,6 @@
 
 int ct_colors_allocated;
 
-/* Function prototypes.  */
-
-static void init_color_table P_ ((void));
-static void free_color_table P_ ((void));
-static unsigned long *colors_in_color_table P_ ((int *n));
-static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
-static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
-
-
 /* Initialize the color table.  */
 
 static void
@@ -5422,6 +6264,17 @@
   return colors;
 }
 
+#else
+static unsigned long
+lookup_rgb_color (f, r, g, b)
+     struct frame *f;
+     int r, g, b;
+{
+  unsigned long pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
+
+  gamma_correct (f, &pixel);
+  return pixel;
+}
 #endif /* MAC_TODO */
 
 
@@ -5429,151 +6282,333 @@
 			      Algorithms
  ***********************************************************************/
 
-#if 0 /* MAC_TODO : Mac versions of low level algorithms */
-static void x_laplace_write_row P_ ((struct frame *, long *,
-				     int, XImage *, int));
-static void x_laplace_read_row P_ ((struct frame *, Colormap,
-				    XColor *, int, XImage *, int));
-
-
-/* Fill COLORS with RGB colors from row Y of image XIMG.  F is the
-   frame we operate on, CMAP is the color-map in effect, and WIDTH is
-   the width of one row in the image.  */
+static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
+static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
+static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
+
+/* Non-zero means draw a cross on images having `:conversion
+   disabled'.  */
+
+int cross_disabled_images;
+
+/* Edge detection matrices for different edge-detection
+   strategies.  */
+
+static int emboss_matrix[9] = {
+   /* x - 1	x	x + 1  */
+        2,     -1,  	  0,		/* y - 1 */
+       -1,      0,        1,		/* y     */
+        0,      1,       -2		/* y + 1 */
+};
+
+static int laplace_matrix[9] = {
+   /* x - 1	x	x + 1  */
+        1,      0,  	  0,		/* y - 1 */
+        0,      0,        0,		/* y     */
+        0,      0,       -1		/* y + 1 */
+};
+
+/* Value is the intensity of the color whose red/green/blue values
+   are R, G, and B.  */
+
+#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
+
+
+/* On frame F, return an array of XColor structures describing image
+   IMG->pixmap.  Each XColor structure has its pixel color set.  RGB_P
+   non-zero means also fill the red/green/blue members of the XColor
+   structures.  Value is a pointer to the array of XColors structures,
+   allocated with xmalloc; it must be freed by the caller.  */
+
+static XColor *
+x_to_xcolors (f, img, rgb_p)
+     struct frame *f;
+     struct image *img;
+     int rgb_p;
+{
+  int x, y;
+  XColor *colors, *p;
+  XImagePtr ximg;
+
+  colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+
+  /* Get the X image IMG->pixmap.  */
+  ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+		    0, 0, img->width, img->height, ~0, ZPixmap);
+
+  /* Fill the `pixel' members of the XColor array.  I wished there
+     were an easy and portable way to circumvent XGetPixel.  */
+  p = colors;
+  for (y = 0; y < img->height; ++y)
+    {
+      XColor *row = p;
+
+      for (x = 0; x < img->width; ++x, ++p)
+	{
+	  p->pixel = XGetPixel (ximg, x, y);
+
+	  if (rgb_p)
+	    {
+	      p->red = RED16_FROM_ULONG (p->pixel);
+	      p->green = GREEN16_FROM_ULONG (p->pixel);
+	      p->blue = BLUE16_FROM_ULONG (p->pixel);
+	    }
+	}
+    }
+
+  XDestroyImage (ximg);
+  return colors;
+}
+
+
+/* Create IMG->pixmap from an array COLORS of XColor structures, whose
+   RGB members are set.  F is the frame on which this all happens.
+   COLORS will be freed; an existing IMG->pixmap will be freed, too.  */
 
 static void
-x_laplace_read_row (f, cmap, colors, width, ximg, y)
+x_from_xcolors (f, img, colors)
      struct frame *f;
-     Colormap cmap;
+     struct image *img;
      XColor *colors;
-     int width;
-     XImage *ximg;
-     int y;
-{
-  int x;
-
-  for (x = 0; x < width; ++x)
-    colors[x].pixel = XGetPixel (ximg, x, y);
-
-  XQueryColors (NULL, cmap, colors, width);
-}
-
-
-/* Write row Y of image XIMG.  PIXELS is an array of WIDTH longs
-   containing the pixel colors to write.  F is the frame we are
-   working on.  */
+{
+  int x, y;
+  XImagePtr oimg;
+  Pixmap pixmap;
+  XColor *p;
+
+#if 0   /* TODO: color tables.  */
+  init_color_table ();
+#endif
+
+  x_create_x_image_and_pixmap (f, img->width, img->height, 0,
+			       &oimg, &pixmap);
+  p = colors;
+  for (y = 0; y < img->height; ++y)
+    for (x = 0; x < img->width; ++x, ++p)
+      {
+	unsigned long pixel;
+	pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
+	XPutPixel (oimg, x, y, pixel);
+      }
+
+  xfree (colors);
+  x_clear_image_1 (f, img, 1, 0, 1);
+
+  x_put_x_image (f, oimg, pixmap, img->width, img->height);
+  x_destroy_x_image (oimg);
+  img->pixmap = pixmap;
+#if 0  /* TODO: color tables.  */
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif
+}
+
+
+/* On frame F, perform edge-detection on image IMG.
+
+   MATRIX is a nine-element array specifying the transformation
+   matrix.  See emboss_matrix for an example.
+
+   COLOR_ADJUST is a color adjustment added to each pixel of the
+   outgoing image.  */
 
 static void
-x_laplace_write_row (f, pixels, width, ximg, y)
+x_detect_edges (f, img, matrix, color_adjust)
      struct frame *f;
-     long *pixels;
-     int width;
-     XImage *ximg;
-     int y;
-{
-  int x;
-
-  for (x = 0; x < width; ++x)
-    XPutPixel (ximg, x, y, pixels[x]);
-}
-#endif /* MAC_TODO */
-
-/* Transform image IMG which is used on frame F with a Laplace
-   edge-detection algorithm.  The result is an image that can be used
-   to draw disabled buttons, for example.  */
+     struct image *img;
+     int matrix[9], color_adjust;
+{
+  XColor *colors = x_to_xcolors (f, img, 1);
+  XColor *new, *p;
+  int x, y, i, sum;
+
+  for (i = sum = 0; i < 9; ++i)
+    sum += abs (matrix[i]);
+
+#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
+
+  new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+
+  for (y = 0; y < img->height; ++y)
+    {
+      p = COLOR (new, 0, y);
+      p->red = p->green = p->blue = 0xffff/2;
+      p = COLOR (new, img->width - 1, y);
+      p->red = p->green = p->blue = 0xffff/2;
+    }
+
+  for (x = 1; x < img->width - 1; ++x)
+    {
+      p = COLOR (new, x, 0);
+      p->red = p->green = p->blue = 0xffff/2;
+      p = COLOR (new, x, img->height - 1);
+      p->red = p->green = p->blue = 0xffff/2;
+    }
+
+  for (y = 1; y < img->height - 1; ++y)
+    {
+      p = COLOR (new, 1, y);
+
+      for (x = 1; x < img->width - 1; ++x, ++p)
+	{
+	  int r, g, b, y1, x1;
+
+	  r = g = b = i = 0;
+	  for (y1 = y - 1; y1 < y + 2; ++y1)
+	    for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
+	      if (matrix[i])
+	        {
+	          XColor *t = COLOR (colors, x1, y1);
+		  r += matrix[i] * t->red;
+		  g += matrix[i] * t->green;
+		  b += matrix[i] * t->blue;
+		}
+
+	  r = (r / sum + color_adjust) & 0xffff;
+	  g = (g / sum + color_adjust) & 0xffff;
+	  b = (b / sum + color_adjust) & 0xffff;
+	  p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
+	}
+    }
+
+  xfree (colors);
+  x_from_xcolors (f, img, new);
+
+#undef COLOR
+}
+
+
+/* Perform the pre-defined `emboss' edge-detection on image IMG
+   on frame F.  */
+
+static void
+x_emboss (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
+}
+
+
+/* Perform the pre-defined `laplace' edge-detection on image IMG
+   on frame F.  */
 
 static void
 x_laplace (f, img)
      struct frame *f;
      struct image *img;
 {
-#if 0 /* MAC_TODO : Mac version */
-  Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-  XImage *ximg, *oimg;
-  XColor *in[3];
-  long *out;
-  Pixmap pixmap;
-  int x, y, i;
-  long pixel;
-  int in_y, out_y, rc;
-  int mv2 = 45000;
-
-  BLOCK_INPUT;
-
-  /* Get the X image IMG->pixmap.  */
-  ximg = XGetImage (NULL, img->pixmap,
-		    0, 0, img->width, img->height, ~0, ZPixmap);
-
-  /* Allocate 3 input rows, and one output row of colors.  */
-  for (i = 0; i < 3; ++i)
-    in[i] = (XColor *) alloca (img->width * sizeof (XColor));
-  out = (long *) alloca (img->width * sizeof (long));
-
-  /* Create an X image for output.  */
-  rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
-				    &oimg, &pixmap);
-
-  /* Fill first two rows.  */
-  x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
-  x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
-  in_y = 2;
-
-  /* Write first row, all zeros.  */
-  init_color_table ();
-  pixel = lookup_rgb_color (f, 0, 0, 0);
-  for (x = 0; x < img->width; ++x)
-    out[x] = pixel;
-  x_laplace_write_row (f, out, img->width, oimg, 0);
-  out_y = 1;
-
-  for (y = 2; y < img->height; ++y)
-    {
-      int rowa = y % 3;
-      int rowb = (y + 2) % 3;
-
-      x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
-
-      for (x = 0; x < img->width - 2; ++x)
+  x_detect_edges (f, img, laplace_matrix, 45000);
+}
+
+
+/* Perform edge-detection on image IMG on frame F, with specified
+   transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
+
+   MATRIX must be either
+
+   - a list of at least 9 numbers in row-major form
+   - a vector of at least 9 numbers
+
+   COLOR_ADJUST nil means use a default; otherwise it must be a
+   number.  */
+
+static void
+x_edge_detection (f, img, matrix, color_adjust)
+     struct frame *f;
+     struct image *img;
+     Lisp_Object matrix, color_adjust;
+{
+  int i = 0;
+  int trans[9];
+
+  if (CONSP (matrix))
+    {
+      for (i = 0;
+	   i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
+	   ++i, matrix = XCDR (matrix))
+	trans[i] = XFLOATINT (XCAR (matrix));
+    }
+  else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
+    {
+      for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
+	trans[i] = XFLOATINT (AREF (matrix, i));
+    }
+
+  if (NILP (color_adjust))
+    color_adjust = make_number (0xffff / 2);
+
+  if (i == 9 && NUMBERP (color_adjust))
+    x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
+}
+
+
+/* Transform image IMG on frame F so that it looks disabled.  */
+
+static void
+x_disable_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  if (dpyinfo->n_planes >= 2)
+    {
+      /* Color (or grayscale).  Convert to gray, and equalize.  Just
+	 drawing such images with a stipple can look very odd, so
+	 we're using this method instead.  */
+      XColor *colors = x_to_xcolors (f, img, 1);
+      XColor *p, *end;
+      const int h = 15000;
+      const int l = 30000;
+
+      for (p = colors, end = colors + img->width * img->height;
+	   p < end;
+	   ++p)
 	{
-	  int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
-	  int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
-	  int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
-
-	  out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
-					 b & 0xffff);
+	  int i = COLOR_INTENSITY (p->red, p->green, p->blue);
+	  int i2 = (0xffff - h - l) * i / 0xffff + l;
+	  p->red = p->green = p->blue = i2;
 	}
 
-      x_laplace_write_row (f, out, img->width, oimg, out_y++);
-    }
-
-  /* Write last line, all zeros.  */
-  for (x = 0; x < img->width; ++x)
-    out[x] = pixel;
-  x_laplace_write_row (f, out, img->width, oimg, out_y);
-
-  /* Free the input image, and free resources of IMG.  */
-  XDestroyImage (ximg);
-  x_clear_image (f, img);
-
-  /* Put the output image into pixmap, and destroy it.  */
-  x_put_x_image (f, oimg, pixmap, img->width, img->height);
-  x_destroy_x_image (oimg);
-
-  /* Remember new pixmap and colors in IMG.  */
-  img->pixmap = pixmap;
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
-
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-}
-
-
-/* Build a mask for image IMG which is used on frame F. FILE is the
-   name of an image file, for error messages. HOW determines how to
-   determine the background color of IMG. If it is a list '(R G B)',
+      x_from_xcolors (f, img, colors);
+    }
+
+  /* Draw a cross over the disabled image, if we must or if we
+     should.  */
+  if (dpyinfo->n_planes < 2 || cross_disabled_images)
+    {
+      Display *dpy = FRAME_MAC_DISPLAY (f);
+      GC gc;
+
+      gc = XCreateGC (dpy, NULL /*img->pixmap*/, 0, NULL);
+      XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
+      mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, 0,
+			       img->width - 1, img->height - 1);
+      mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, img->height - 1,
+			       img->width - 1, 0);
+      XFreeGC (dpy, gc);
+
+      if (img->mask)
+	{
+	  gc = XCreateGC (dpy, NULL /*img->mask*/, 0, NULL);
+	  XSetForeground (dpy, gc, PIX_MASK_DRAW (f));
+	  mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, 0,
+				   img->width - 1, img->height - 1);
+	  mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, img->height - 1,
+				   img->width - 1, 0);
+	  XFreeGC (dpy, gc);
+	}
+    }
+}
+
+
+/* Build a mask for image IMG which is used on frame F.  FILE is the
+   name of an image file, for error messages.  HOW determines how to
+   determine the background color of IMG.  If it is a list '(R G B)',
    with R, G, and B being integers >= 0, take that as the color of the
-   background. Otherwise, determine the background color of IMG
-   heuristically. Value is non-zero if successful. */
+   background.  Otherwise, determine the background color of IMG
+   heuristically.  Value is non-zero if successful. */
 
 static int
 x_build_heuristic_mask (f, img, how)
@@ -5581,39 +6616,37 @@
      struct image *img;
      Lisp_Object how;
 {
-#if 0 /* MAC_TODO : Mac version */
-  Display *dpy = FRAME_W32_DISPLAY (f);
-  XImage *ximg, *mask_img;
-  int x, y, rc, look_at_corners_p;
-  unsigned long bg;
-
-  BLOCK_INPUT;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  XImagePtr ximg, mask_img;
+  int x, y, rc, use_img_background;
+  unsigned long bg = 0;
+
+  if (img->mask)
+    {
+      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+      img->mask = 0;
+      img->background_transparent_valid = 0;
+    }
 
   /* Create an image and pixmap serving as mask.  */
   rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
 				    &mask_img, &img->mask);
   if (!rc)
-    {
-      UNBLOCK_INPUT;
-      return 0;
-    }
+    return 0;
 
   /* Get the X image of IMG->pixmap.  */
   ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
 		    ~0, ZPixmap);
 
   /* Determine the background color of ximg.  If HOW is `(R G B)'
-     take that as color.  Otherwise, try to determine the color
-     heuristically. */
-  look_at_corners_p = 1;
+     take that as color.  Otherwise, use the image's background color. */
+  use_img_background = 1;
 
   if (CONSP (how))
     {
-      int rgb[3], i = 0;
-
-      while (i < 3
-	     && CONSP (how)
-	     && NATNUMP (XCAR (how)))
+      int rgb[3], i;
+
+      for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
 	{
 	  rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
 	  how = XCDR (how);
@@ -5622,59 +6655,29 @@
       if (i == 3 && NILP (how))
 	{
 	  char color_name[30];
-	  XColor exact, color;
-	  Colormap cmap;
-
 	  sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
-
-	  cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-	  if (XLookupColor (dpy, cmap, color_name, &exact, &color))
-	    {
-	      bg = color.pixel;
-	      look_at_corners_p = 0;
-	    }
+	  bg = x_alloc_image_color (f, img, build_string (color_name), 0);
+	  use_img_background = 0;
 	}
     }
 
-  if (look_at_corners_p)
-    {
-      unsigned long corners[4];
-      int i, best_count;
-
-      /* Get the colors at the corners of ximg.  */
-      corners[0] = XGetPixel (ximg, 0, 0);
-      corners[1] = XGetPixel (ximg, img->width - 1, 0);
-      corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
-      corners[3] = XGetPixel (ximg, 0, img->height - 1);
-
-      /* Choose the most frequently found color as background.  */
-      for (i = best_count = 0; i < 4; ++i)
-	{
-	  int j, n;
-
-	  for (j = n = 0; j < 4; ++j)
-	    if (corners[i] == corners[j])
-	      ++n;
-
-	  if (n > best_count)
-	    bg = corners[i], best_count = n;
-	}
-    }
+  if (use_img_background)
+    bg = four_corners_best (ximg, img->width, img->height);
 
   /* Set all bits in mask_img to 1 whose color in ximg is different
      from the background color bg.  */
   for (y = 0; y < img->height; ++y)
     for (x = 0; x < img->width; ++x)
-      XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
+      XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
+
+  /* Fill in the background_transparent field while we have the mask handy. */
+  image_background_transparent (img, f, mask_img);
 
   /* Put mask_img into img->mask.  */
   x_put_x_image (f, mask_img, img->mask, img->width, img->height);
   x_destroy_x_image (mask_img);
   XDestroyImage (ximg);
 
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-
   return 1;
 }
 
@@ -5683,7 +6686,6 @@
 /***********************************************************************
 		       PBM (mono, gray, color)
  ***********************************************************************/
-#ifdef HAVE_PBM
 
 static int pbm_image_p P_ ((Lisp_Object object));
 static int pbm_load P_ ((struct frame *f, struct image *img));
@@ -5705,6 +6707,9 @@
   PBM_RELIEF,
   PBM_ALGORITHM,
   PBM_HEURISTIC_MASK,
+  PBM_MASK,
+  PBM_FOREGROUND,
+  PBM_BACKGROUND,
   PBM_LAST
 };
 
@@ -5716,11 +6721,14 @@
   {":type",		IMAGE_SYMBOL_VALUE,			1},
   {":file",		IMAGE_STRING_VALUE,			0},
   {":data",		IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
   {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":foreground",	IMAGE_STRING_OR_NIL_VALUE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type `pbm'.  */
@@ -5745,9 +6753,7 @@
 
   bcopy (pbm_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
-      || (fmt[PBM_ASCENT].count
-	  && XFASTINT (fmt[PBM_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
     return 0;
 
   /* Must specify either :data or :file.  */
@@ -5763,7 +6769,7 @@
 pbm_scan_number (s, end)
      unsigned char **s, *end;
 {
-  int c, val = -1;
+  int c = 0, val = -1;
 
   while (*s < end)
     {
@@ -5793,42 +6799,6 @@
 }
 
 
-/* Read FILE into memory.  Value is a pointer to a buffer allocated
-   with xmalloc holding FILE's contents.  Value is null if an error
-   occurred.  *SIZE is set to the size of the file.  */
-
-static char *
-pbm_read_file (file, size)
-     Lisp_Object file;
-     int *size;
-{
-  FILE *fp = NULL;
-  char *buf = NULL;
-  struct stat st;
-
-  if (stat (SDATA (file), &st) == 0
-      && (fp = fopen (SDATA (file), "r")) != NULL
-      && (buf = (char *) xmalloc (st.st_size),
-	  fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
-    {
-      if (fp)
-	fclose (fp);
-      if (buf)
-	{
-	  xfree (buf);
-	  buf = NULL;
-	}
-    }
-
-  return buf;
-}
-
-
 /* Load PBM image IMG for use on frame F.  */
 
 static int
@@ -5838,7 +6808,7 @@
 {
   int raw_p, x, y;
   int width, height, max_color_idx = 0;
-  XImage *ximg;
+  XImagePtr ximg;
   Lisp_Object file, specified_file;
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   struct gcpro gcpro1;
@@ -5854,13 +6824,13 @@
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
-
-      contents = pbm_read_file (file, &size);
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+
+      contents = slurp_file (SDATA (file), &size);
       if (contents == NULL)
 	{
 	  image_error ("Error reading `%s'", file, Qnil);
@@ -5937,20 +6907,37 @@
       || (type != PBM_MONO && max_color_idx < 0))
     goto error;
 
-  BLOCK_INPUT;
   if (!x_create_x_image_and_pixmap (f, width, height, 0,
 				    &ximg, &img->pixmap))
-    {
-      UNBLOCK_INPUT;
-      goto error;
-    }
-
+    goto error;
+
+#if 0  /* TODO: color tables.  */
   /* Initialize the color hash table.  */
   init_color_table ();
+#endif
 
   if (type == PBM_MONO)
     {
       int c = 0, g;
+      struct image_keyword fmt[PBM_LAST];
+      unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
+      unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
+
+      /* Parse the image specification.  */
+      bcopy (pbm_format, fmt, sizeof fmt);
+      parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
+
+      /* Get foreground and background colors, maybe allocate colors.  */
+      if (fmt[PBM_FOREGROUND].count
+	  && STRINGP (fmt[PBM_FOREGROUND].value))
+	fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
+      if (fmt[PBM_BACKGROUND].count
+	  && STRINGP (fmt[PBM_BACKGROUND].value))
+	{
+	  bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
+	  img->background = bg;
+	  img->background_valid = 1;
+	}
 
       for (y = 0; y < height; ++y)
 	for (x = 0; x < width; ++x)
@@ -5965,9 +6952,7 @@
 	    else
 	      g = pbm_scan_number (&p, end);
 
-	    XPutPixel (ximg, x, y, (g
-				    ? FRAME_FOREGROUND_PIXEL (f)
-				    : FRAME_BACKGROUND_PIXEL (f)));
+	    XPutPixel (ximg, x, y, g ? fg : bg);
 	  }
     }
   else
@@ -5994,13 +6979,10 @@
 
 	    if (r < 0 || g < 0 || b < 0)
 	      {
-		xfree (ximg->data);
-		ximg->data = NULL;
-		XDestroyImage (ximg);
-		UNBLOCK_INPUT;
+		x_destroy_x_image (ximg);
 		image_error ("Invalid pixel value in image `%s'",
 			     img->spec, Qnil);
-                goto error;
+		goto error;
 	      }
 
 	    /* RGB values are now in the range 0..max_color_idx.
@@ -6012,33 +6994,35 @@
 	  }
     }
 
+#if 0  /* TODO: color tables.  */
   /* Store in IMG->colors the colors allocated for the image, and
      free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
+
+  img->width = width;
+  img->height = height;
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
 
   /* Put the image into a pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-  UNBLOCK_INPUT;
-
-  img->width = width;
-  img->height = height;
 
   UNGCPRO;
   xfree (contents);
   return 1;
 }
-#endif /* HAVE_PBM */
+
 
 
 /***********************************************************************
 				 PNG
  ***********************************************************************/
 
-#if HAVE_PNG
-
-#include <png.h>
 
 /* Function prototypes.  */
 
@@ -6061,6 +7045,8 @@
   PNG_RELIEF,
   PNG_ALGORITHM,
   PNG_HEURISTIC_MASK,
+  PNG_MASK,
+  PNG_BACKGROUND,
   PNG_LAST
 };
 
@@ -6072,11 +7058,13 @@
   {":type",		IMAGE_SYMBOL_VALUE,			1},
   {":data",		IMAGE_STRING_VALUE,			0},
   {":file",		IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
   {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type `png'.  */
@@ -6100,9 +7088,7 @@
   struct image_keyword fmt[PNG_LAST];
   bcopy (png_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
-      || (fmt[PNG_ASCENT].count
-	  && XFASTINT (fmt[PNG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -6110,6 +7096,27 @@
 }
 
 
+#ifndef HAVE_PNG
+static int
+png_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+#ifdef MAC_OSX
+  if (MyCGImageCreateWithPNGDataProvider)
+    return image_load_quartz2d (f, img, 1);
+  else
+#endif
+    return image_load_quicktime (f, img, kQTFileTypePNG);
+}
+#else
+
+#if defined HAVE_LIBPNG_PNG_H
+# include <libpng/png.h>
+#else
+# include <png.h>
+#endif
+
 /* Error and warning handlers installed when the PNG library
    is initialized.  */
 
@@ -6174,22 +7181,20 @@
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   int x, y, i;
-  XImage *ximg, *mask_img = NULL;
+  XImagePtr ximg, mask_img = NULL;
   struct gcpro gcpro1;
   png_struct *png_ptr = NULL;
   png_info *info_ptr = NULL, *end_info = NULL;
-  FILE *fp = NULL;
+  FILE *volatile fp = NULL;
   png_byte sig[8];
-  png_byte *pixels = NULL;
-  png_byte **rows = NULL;
+  png_byte * volatile pixels = NULL;
+  png_byte ** volatile rows = NULL;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   png_byte channels;
   png_uint_32 row_bytes;
   int transparent_p;
-  char *gamma_str;
-  double screen_gamma, image_gamma;
-  int intent;
+  double screen_gamma;
   struct png_memory_storage tbr;  /* Data to be read */
 
   /* Find out what file to load.  */
@@ -6202,31 +7207,31 @@
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
 
       /* Open the image file.  */
       fp = fopen (SDATA (file), "rb");
       if (!fp)
-        {
-          image_error ("Cannot open image file `%s'", file, Qnil);
-          UNGCPRO;
-          fclose (fp);
-          return 0;
-        }
+	{
+	  image_error ("Cannot open image file `%s'", file, Qnil);
+	  UNGCPRO;
+	  fclose (fp);
+	  return 0;
+	}
 
       /* Check PNG signature.  */
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-          || !png_check_sig (sig, sizeof sig))
-        {
-          image_error ("Not a PNG file:` %s'", file, Qnil);
-          UNGCPRO;
-          fclose (fp);
-          return 0;
-        }
+	  || !png_check_sig (sig, sizeof sig))
+	{
+	  image_error ("Not a PNG file: `%s'", file, Qnil);
+	  UNGCPRO;
+	  fclose (fp);
+	  return 0;
+	}
     }
   else
     {
@@ -6325,56 +7330,76 @@
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     png_set_gray_to_rgb (png_ptr);
 
-  /* The value 2.2 is a guess for PC monitors from PNG example.c.  */
-  gamma_str = getenv ("SCREEN_GAMMA");
-  screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
-
-  /* Tell the PNG lib to handle gamma correction for us.  */
-
+  screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
+
+#if 0 /* Avoid double gamma correction for PNG images. */
+  { /* Tell the PNG lib to handle gamma correction for us.  */
+    int intent;
+    double image_gamma;
 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
-  if (png_get_sRGB (png_ptr, info_ptr, &intent))
-    /* There is a special chunk in the image specifying the gamma.  */
-    png_set_sRGB (png_ptr, info_ptr, intent);
-  else
+    if (png_get_sRGB (png_ptr, info_ptr, &intent))
+      /* The libpng documentation says this is right in this case.  */
+      png_set_gamma (png_ptr, screen_gamma, 0.45455);
+    else
 #endif
-  if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
-    /* Image contains gamma information.  */
-    png_set_gamma (png_ptr, screen_gamma, image_gamma);
-  else
-    /* Use a default of 0.5 for the image gamma.  */
-    png_set_gamma (png_ptr, screen_gamma, 0.5);
+      if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
+	/* Image contains gamma information.  */
+	png_set_gamma (png_ptr, screen_gamma, image_gamma);
+      else
+	/* Use the standard default for the image gamma.  */
+	png_set_gamma (png_ptr, screen_gamma, 0.45455);
+  }
+#endif /* if 0 */
 
   /* Handle alpha channel by combining the image with a background
      color.  Do this only if a real alpha channel is supplied.  For
      simple transparency, we prefer a clipping mask.  */
   if (!transparent_p)
     {
-      png_color_16 *image_background;
-
-      if (png_get_bKGD (png_ptr, info_ptr, &image_background))
+      png_color_16 *image_bg;
+      Lisp_Object specified_bg
+	= image_spec_value (img->spec, QCbackground, NULL);
+
+      if (STRINGP (specified_bg))
+	/* The user specified `:background', use that.  */
+	{
+	  XColor color;
+	  if (mac_defined_color (f, SDATA (specified_bg), &color, 0))
+	    {
+	      png_color_16 user_bg;
+
+	      bzero (&user_bg, sizeof user_bg);
+	      user_bg.red = color.red >> 8;
+	      user_bg.green = color.green >> 8;
+	      user_bg.blue = color.blue >> 8;
+
+	      png_set_background (png_ptr, &user_bg,
+				  PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+	    }
+	}
+      else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
 	/* Image contains a background color with which to
 	   combine the image.  */
-	png_set_background (png_ptr, image_background,
+	png_set_background (png_ptr, image_bg,
 			    PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
 	{
 	  /* Image does not contain a background color with which
 	     to combine the image data via an alpha channel.  Use
 	     the frame's background instead.  */
-	  XColor color;
-	  Colormap cmap;
+	  unsigned long color;
 	  png_color_16 frame_background;
-
-	  BLOCK_INPUT;
-	  cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-	  color.pixel = FRAME_BACKGROUND_PIXEL (f);
-	  XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
-	  UNBLOCK_INPUT;
-
+	  color = FRAME_BACKGROUND_PIXEL (f);
+#if 0 /* TODO : Colormap support.  */
+	  Colormap cmap;
+
+	  cmap = FRAME_X_COLORMAP (f);
+	  x_query_color (f, &color);
+#endif
 	  bzero (&frame_background, sizeof frame_background);
-	  frame_background.red = color.red;
-	  frame_background.green = color.green;
-	  frame_background.blue = color.blue;
+	  frame_background.red = RED_FROM_ULONG (color);
+	  frame_background.green = GREEN_FROM_ULONG (color);
+	  frame_background.blue = BLUE_FROM_ULONG (color);
 
 	  png_set_background (png_ptr, &frame_background,
 			      PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
@@ -6410,15 +7435,10 @@
       fp = NULL;
     }
 
-  BLOCK_INPUT;
-
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
 				    &img->pixmap))
-    {
-      UNBLOCK_INPUT;
-      goto error;
-    }
+    goto error;
 
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
@@ -6428,14 +7448,15 @@
 				       &mask_img, &img->mask))
     {
       x_destroy_x_image (ximg);
-      XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
-      img->pixmap = 0;
-      UNBLOCK_INPUT;
+      XFreePixmap (FRAME_MAC_DISPLAY (f), img->pixmap);
+      img->pixmap = NULL;
       goto error;
     }
 
   /* Fill the X image and mask from PNG data.  */
+#if 0 /* TODO: Color tables.  */
   init_color_table ();
+#endif
 
   for (y = 0; y < height; ++y)
     {
@@ -6469,15 +7490,29 @@
 	  if (channels == 4)
 	    {
 	      if (mask_img)
-		XPutPixel (mask_img, x, y, *p > 0);
+		XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
 	      ++p;
 	    }
 	}
     }
 
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    /* Set IMG's background color from the PNG image, unless the user
+       overrode it.  */
+    {
+      png_color_16 *bg;
+      if (png_get_bKGD (png_ptr, info_ptr, &bg))
+	{
+	  img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
+	  img->background_valid = 1;
+	}
+    }
+
+#if 0 /* TODO: Color tables.  */
   /* Remember colors allocated for this image.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 
   /* Clean up.  */
   png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
@@ -6487,6 +7522,9 @@
   img->width = width;
   img->height = height;
 
+  /* Maybe fill in the background field while we have ximg handy. */
+  IMAGE_BACKGROUND (img, f, ximg);
+
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
@@ -6494,16 +7532,19 @@
   /* Same for the mask.  */
   if (mask_img)
     {
+      /* Fill in the background_transparent field while we have the mask
+	 handy. */
+      image_background_transparent (img, f, mask_img);
+
       x_put_x_image (f, mask_img, img->mask, img->width, img->height);
       x_destroy_x_image (mask_img);
     }
 
-  UNBLOCK_INPUT;
   UNGCPRO;
   return 1;
 }
 
-#endif /* HAVE_PNG != 0 */
+#endif /* HAVE_PNG */
 
 
 
@@ -6511,23 +7552,6 @@
 				 JPEG
  ***********************************************************************/
 
-#if HAVE_JPEG
-
-/* Work around a warning about HAVE_STDLIB_H being redefined in
-   jconfig.h.  */
-#ifdef HAVE_STDLIB_H
-#define HAVE_STDLIB_H_1
-#undef HAVE_STDLIB_H
-#endif /* HAVE_STLIB_H */
-
-#include <jpeglib.h>
-#include <jerror.h>
-#include <setjmp.h>
-
-#ifdef HAVE_STLIB_H_1
-#define HAVE_STDLIB_H 1
-#endif
-
 static int jpeg_image_p P_ ((Lisp_Object object));
 static int jpeg_load P_ ((struct frame *f, struct image *img));
 
@@ -6547,6 +7571,8 @@
   JPEG_RELIEF,
   JPEG_ALGORITHM,
   JPEG_HEURISTIC_MASK,
+  JPEG_MASK,
+  JPEG_BACKGROUND,
   JPEG_LAST
 };
 
@@ -6558,11 +7584,13 @@
   {":type",		IMAGE_SYMBOL_VALUE,			1},
   {":data",		IMAGE_STRING_VALUE,			0},
   {":file",		IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
-  {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":conversions",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type `jpeg'.  */
@@ -6587,9 +7615,7 @@
 
   bcopy (jpeg_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
-      || (fmt[JPEG_ASCENT].count
-	  && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -6597,12 +7623,42 @@
 }
 
 
+#ifndef HAVE_JPEG
+static int
+jpeg_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+#ifdef MAC_OSX
+  return image_load_quartz2d (f, img, 0);
+#else
+  return image_load_quicktime (f, img, kQTFileTypeJPEG);
+#endif
+}
+#else
+
+/* Work around a warning about HAVE_STDLIB_H being redefined in
+   jconfig.h.  */
+#ifdef HAVE_STDLIB_H
+#define HAVE_STDLIB_H_1
+#undef HAVE_STDLIB_H
+#endif /* HAVE_STLIB_H */
+
+#include <jpeglib.h>
+#include <jerror.h>
+#include <setjmp.h>
+
+#ifdef HAVE_STLIB_H_1
+#define HAVE_STDLIB_H 1
+#endif
+
 struct my_jpeg_error_mgr
 {
   struct jpeg_error_mgr pub;
   jmp_buf setjmp_buffer;
 };
 
+
 static void
 my_error_exit (cinfo)
      j_common_ptr cinfo;
@@ -6611,6 +7667,7 @@
   longjmp (mgr->setjmp_buffer, 1);
 }
 
+
 /* Init source method for JPEG data source manager.  Called by
    jpeg_read_header() before any data is actually read.  See
    libjpeg.doc from the JPEG lib distribution.  */
@@ -6719,10 +7776,10 @@
   struct my_jpeg_error_mgr mgr;
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
-  FILE *fp = NULL;
+  FILE * volatile fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
-  XImage *ximg = NULL;
+  XImagePtr ximg = NULL;
   int rc;
   unsigned long *colors;
   int width, height;
@@ -6738,25 +7795,25 @@
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
 
       fp = fopen (SDATA (file), "r");
       if (fp == NULL)
-        {
-          image_error ("Cannot open `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot open `%s'", file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
     }
 
   /* Customize libjpeg's error handling to call my_error_exit when an
-     error is detected. This function will perform a longjmp. */
+     error is detected.  This function will perform a longjmp.  */
+  cinfo.err = jpeg_std_error (&mgr.pub);
   mgr.pub.error_exit = my_error_exit;
-  cinfo.err = jpeg_std_error (&mgr.pub);
 
   if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
     {
@@ -6771,28 +7828,25 @@
 
       /* Close the input file and destroy the JPEG object.  */
       if (fp)
-        fclose (fp);
+	fclose ((FILE *) fp);
       jpeg_destroy_decompress (&cinfo);
 
-      BLOCK_INPUT;
-
       /* If we already have an XImage, free that.  */
       x_destroy_x_image (ximg);
 
       /* Free pixmap and colors.  */
       x_clear_image (f, img);
 
-      UNBLOCK_INPUT;
       UNGCPRO;
       return 0;
     }
 
   /* Create the JPEG decompression object.  Let it read from fp.
-     Read the JPEG image header.  */
+	 Read the JPEG image header.  */
   jpeg_create_decompress (&cinfo);
 
   if (NILP (specified_data))
-    jpeg_stdio_src (&cinfo, fp);
+    jpeg_stdio_src (&cinfo, (FILE *) fp);
   else
     jpeg_memory_src (&cinfo, SDATA (specified_data),
 		     SBYTES (specified_data));
@@ -6800,21 +7854,15 @@
   jpeg_read_header (&cinfo, TRUE);
 
   /* Customize decompression so that color quantization will be used.
-     Start decompression.  */
+	 Start decompression.  */
   cinfo.quantize_colors = TRUE;
   jpeg_start_decompress (&cinfo);
   width = img->width = cinfo.output_width;
   height = img->height = cinfo.output_height;
 
-  BLOCK_INPUT;
-
   /* Create X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
-				    &img->pixmap))
-    {
-      UNBLOCK_INPUT;
-      longjmp (mgr.setjmp_buffer, 2);
-    }
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    longjmp (mgr.setjmp_buffer, 2);
 
   /* Allocate colors.  When color quantization is used,
      cinfo.actual_number_of_colors has been set with the number of
@@ -6831,11 +7879,13 @@
     else
       ir = 0, ig = 0, ib = 0;
 
+#if 0 /* TODO: Color tables.  */
     /* Use the color table mechanism because it handles colors that
        cannot be allocated nicely.  Such colors will be replaced with
        a default color, and we don't have to care about which colors
        can be freed safely, and which can't.  */
     init_color_table ();
+#endif
     colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
 				       * sizeof *colors);
 
@@ -6849,9 +7899,11 @@
 	colors[i] = lookup_rgb_color (f, r, g, b);
       }
 
+#if 0 /* TODO: Color tables.  */
     /* Remember those colors actually allocated.  */
     img->colors = colors_in_color_table (&img->ncolors);
     free_color_table ();
+#endif
   }
 
   /* Read pixels.  */
@@ -6869,12 +7921,15 @@
   jpeg_finish_decompress (&cinfo);
   jpeg_destroy_decompress (&cinfo);
   if (fp)
-    fclose (fp);
+    fclose ((FILE *) fp);
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
 
   /* Put the image into the pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-  UNBLOCK_INPUT;
   UNGCPRO;
   return 1;
 }
@@ -6887,10 +7942,6 @@
 				 TIFF
  ***********************************************************************/
 
-#if HAVE_TIFF
-
-#include <tiffio.h>
-
 static int tiff_image_p P_ ((Lisp_Object object));
 static int tiff_load P_ ((struct frame *f, struct image *img));
 
@@ -6910,6 +7961,8 @@
   TIFF_RELIEF,
   TIFF_ALGORITHM,
   TIFF_HEURISTIC_MASK,
+  TIFF_MASK,
+  TIFF_BACKGROUND,
   TIFF_LAST
 };
 
@@ -6921,11 +7974,13 @@
   {":type",		IMAGE_SYMBOL_VALUE,			1},
   {":data",		IMAGE_STRING_VALUE,			0},
   {":file",		IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
-  {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":conversions",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type `tiff'.  */
@@ -6949,15 +8004,26 @@
   struct image_keyword fmt[TIFF_LAST];
   bcopy (tiff_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
-      || (fmt[TIFF_ASCENT].count
-	  && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
   return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
 }
 
+#ifndef HAVE_TIFF
+
+static int
+tiff_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  return image_load_quicktime (f, img, kQTFileTypeTIFF);
+}
+
+#else
+
+#include <tiffio.h>
 
 /* Reading from a memory buffer for TIFF images Based on the PNG
    memory source, but we have to provide a lot of extra functions.
@@ -6976,6 +8042,7 @@
 }
 tiff_memory_source;
 
+
 static size_t
 tiff_read_from_memory (data, buf, size)
      thandle_t data;
@@ -6991,6 +8058,7 @@
   return size;
 }
 
+
 static size_t
 tiff_write_from_memory (data, buf, size)
      thandle_t data;
@@ -7000,6 +8068,7 @@
   return (size_t) -1;
 }
 
+
 static toff_t
 tiff_seek_in_memory (data, off, whence)
      thandle_t data;
@@ -7023,7 +8092,7 @@
       idx = src->index + off;
       break;
 
-    default:			/* Invalid `whence'.  */
+    default:			/* Invalid `whence'.   */
       return -1;
     }
 
@@ -7034,6 +8103,7 @@
   return src->index;
 }
 
+
 static int
 tiff_close_memory (data)
      thandle_t data;
@@ -7042,6 +8112,7 @@
   return 0;
 }
 
+
 static int
 tiff_mmap_memory (data, pbase, psize)
      thandle_t data;
@@ -7052,6 +8123,7 @@
   return 0;
 }
 
+
 static void
 tiff_unmap_memory (data, base, size)
      thandle_t data;
@@ -7061,6 +8133,7 @@
   /* We don't need to do this. */
 }
 
+
 static toff_t
 tiff_size_of_memory (data)
      thandle_t data;
@@ -7068,6 +8141,35 @@
   return ((tiff_memory_source *) data)->len;
 }
 
+
+static void
+tiff_error_handler (title, format, ap)
+     const char *title, *format;
+     va_list ap;
+{
+  char buf[512];
+  int len;
+
+  len = sprintf (buf, "TIFF error: %s ", title);
+  vsprintf (buf + len, format, ap);
+  add_to_log (buf, Qnil, Qnil);
+}
+
+
+static void
+tiff_warning_handler (title, format, ap)
+     const char *title, *format;
+     va_list ap;
+{
+  char buf[512];
+  int len;
+
+  len = sprintf (buf, "TIFF warning: %s ", title);
+  vsprintf (buf + len, format, ap);
+  add_to_log (buf, Qnil, Qnil);
+}
+
+
 /* Load TIFF image IMG for use on frame F.  Value is non-zero if
    successful.  */
 
@@ -7082,7 +8184,7 @@
   int width, height, x, y;
   uint32 *buf;
   int rc;
-  XImage *ximg;
+  XImagePtr ximg;
   struct gcpro gcpro1;
   tiff_memory_source memsrc;
 
@@ -7091,25 +8193,28 @@
   file = Qnil;
   GCPRO1 (file);
 
+  TIFFSetErrorHandler (tiff_error_handler);
+  TIFFSetWarningHandler (tiff_warning_handler);
+
   if (NILP (specified_data))
     {
       /* Read from a file */
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
 
       /* Try to open the image file.  */
       tiff = TIFFOpen (SDATA (file), "r");
       if (tiff == NULL)
-        {
-          image_error ("Cannot open `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot open `%s'", file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
     }
   else
     {
@@ -7151,19 +8256,18 @@
       return 0;
     }
 
-  BLOCK_INPUT;
-
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
-      UNBLOCK_INPUT;
       xfree (buf);
       UNGCPRO;
       return 0;
     }
 
+#if 0 /* TODO: Color tables.  */
   /* Initialize the color table.  */
   init_color_table ();
+#endif
 
   /* Process the pixel raster.  Origin is in the lower-left corner.  */
   for (y = 0; y < height; ++y)
@@ -7180,24 +8284,29 @@
 	}
     }
 
+#if 0 /* TODO: Color tables.  */
   /* Remember the colors allocated for the image.  Free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
+
+  img->width = width;
+  img->height = height;
+
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
 
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
   xfree (buf);
-  UNBLOCK_INPUT;
-
-  img->width = width;
-  img->height = height;
 
   UNGCPRO;
   return 1;
 }
 
-#endif /* HAVE_TIFF != 0 */
+#endif /* HAVE_TIFF */
 
 
 
@@ -7205,10 +8314,6 @@
 				 GIF
  ***********************************************************************/
 
-#if HAVE_GIF
-
-#include <gif_lib.h>
-
 static int gif_image_p P_ ((Lisp_Object object));
 static int gif_load P_ ((struct frame *f, struct image *img));
 
@@ -7228,7 +8333,9 @@
   GIF_RELIEF,
   GIF_ALGORITHM,
   GIF_HEURISTIC_MASK,
+  GIF_MASK,
   GIF_IMAGE,
+  GIF_BACKGROUND,
   GIF_LAST
 };
 
@@ -7240,12 +8347,14 @@
   {":type",		IMAGE_SYMBOL_VALUE,			1},
   {":data",		IMAGE_STRING_VALUE,			0},
   {":file",		IMAGE_STRING_VALUE,			0},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
   {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
   {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":image",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0}
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":image",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type `gif'.  */
@@ -7259,6 +8368,7 @@
   NULL
 };
 
+
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -7268,15 +8378,200 @@
   struct image_keyword fmt[GIF_LAST];
   bcopy (gif_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
-      || (fmt[GIF_ASCENT].count
-	  && XFASTINT (fmt[GIF_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
   return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
 }
 
+#ifndef HAVE_GIF
+
+static int
+gif_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  Lisp_Object specified_file, file;
+  Lisp_Object specified_data;
+  OSErr err;
+  Boolean graphic_p, movie_p, prefer_graphic_p;
+  Handle dh = NULL;
+  Movie movie = NULL;
+  Lisp_Object image;
+  Track track = NULL;
+  Media media = NULL;
+  long nsamples;
+  Rect rect;
+  Lisp_Object specified_bg;
+  XColor color;
+  RGBColor bg_color;
+  int width, height;
+  XImagePtr ximg;
+  TimeValue time;
+  struct gcpro gcpro1;
+  int ino;
+
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  if (NILP (specified_data))
+    {
+      /* Read from a file */
+      FSSpec fss;
+      short refnum;
+
+      err = find_image_fsspec (specified_file, &file, &fss);
+      if (err != noErr)
+	{
+	  if (err == fnfErr)
+	    image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  else
+	    goto open_error;
+	}
+
+      err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
+				  &graphic_p, &movie_p, &prefer_graphic_p, 0);
+      if (err != noErr)
+	goto open_error;
+
+      if (!graphic_p && !movie_p)
+	goto open_error;
+      if (prefer_graphic_p)
+	return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
+      err = OpenMovieFile (&fss, &refnum, fsRdPerm);
+      if (err != noErr)
+	goto open_error;
+      err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
+      CloseMovieFile (refnum);
+      if (err != noErr)
+	{
+	  image_error ("Error reading `%s'", file, Qnil);
+	  return 0;
+	}
+    }
+  else
+    {
+      /* Memory source! */
+      Handle dref = NULL;
+      long file_type_atom[3];
+
+      err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
+      if (err != noErr)
+	{
+	  image_error ("Cannot allocate data handle for `%s'",
+		       img->spec, Qnil);
+	  goto error;
+	}
+
+      file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
+      file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
+      file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
+      err = PtrToHand (&dh, &dref, sizeof (Handle));
+      if (err == noErr)
+	/* no file name */
+	err = PtrAndHand ("\p", dref, 1);
+      if (err == noErr)
+	err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
+      if (err != noErr)
+	{
+	  image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
+	  goto error;
+	}
+      err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
+				     &movie_p, &prefer_graphic_p, 0);
+      if (err != noErr)
+	goto open_error;
+
+      if (!graphic_p && !movie_p)
+	goto open_error;
+      if (prefer_graphic_p)
+	{
+	  int success_p;
+
+	  DisposeHandle (dref);
+	  success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
+	  DisposeHandle (dh);
+	  return success_p;
+	}
+      err = NewMovieFromDataRef (&movie, 0, NULL, dref,
+				 HandleDataHandlerSubType);
+      DisposeHandle (dref);
+      if (err != noErr)
+	goto open_error;
+    }
+
+  image = image_spec_value (img->spec, QCindex, NULL);
+  ino = INTEGERP (image) ? XFASTINT (image) : 0;
+  track = GetMovieIndTrack (movie, 1);
+  media = GetTrackMedia (track);
+  nsamples = GetMediaSampleCount (media);
+  if (ino >= nsamples)
+    {
+      image_error ("Invalid image number `%s' in image `%s'",
+		   image, img->spec);
+      goto error;
+    }
+
+  specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  if (!STRINGP (specified_bg) ||
+      !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+    {
+      color.pixel = FRAME_BACKGROUND_PIXEL (f);
+      color.red = RED16_FROM_ULONG (color.pixel);
+      color.green = GREEN16_FROM_ULONG (color.pixel);
+      color.blue = BLUE16_FROM_ULONG (color.pixel);
+    }
+  GetMovieBox (movie, &rect);
+  width = img->width = rect.right - rect.left;
+  height = img->height = rect.bottom - rect.top;
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    goto error;
+
+  SetGWorld (ximg, NULL);
+  bg_color.red = color.red;
+  bg_color.green = color.green;
+  bg_color.blue = color.blue;
+  RGBBackColor (&bg_color);
+  SetMovieActive (movie, TRUE);
+  SetMovieGWorld (movie, ximg, NULL);
+  SampleNumToMediaTime (media, ino + 1, &time, NULL);
+  SetMovieTimeValue (movie, time);
+  MoviesTask (movie, 0L);
+  DisposeTrackMedia (media);
+  DisposeMovieTrack (track);
+  DisposeMovie (movie);
+  if (dh)
+    DisposeHandle (dh);
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
+
+  /* Put the image into the pixmap.  */
+  x_put_x_image (f, ximg, img->pixmap, width, height);
+  x_destroy_x_image (ximg);
+  return 1;
+
+ open_error:
+  image_error ("Cannot open `%s'", file, Qnil);
+ error:
+  if (media)
+    DisposeTrackMedia (media);
+  if (track)
+    DisposeMovieTrack (track);
+  if (movie)
+    DisposeMovie (movie);
+  if (dh)
+    DisposeHandle (dh);
+  return 0;
+}
+
+#else
+
+#define DrawText gif_DrawText	/* avoid conflict with QuickdrawText.h */
+#include <gif_lib.h>
+#undef DrawText
+
 /* Reading a GIF image from memory
    Based on the PNG memory stuff to a certain extent. */
 
@@ -7288,6 +8583,7 @@
 }
 gif_memory_source;
 
+
 /* Make the current memory source available to gif_read_from_memory.
    It's done this way because not all versions of libungif support
    a UserData field in the GifFileType structure.  */
@@ -7321,7 +8617,7 @@
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   int rc, width, height, x, y, i;
-  XImage *ximg;
+  XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
@@ -7340,20 +8636,20 @@
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
 
       /* Open the GIF file.  */
       gif = DGifOpenFileName (SDATA (file));
       if (gif == NULL)
-        {
-          image_error ("Cannot open `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+	{
+	  image_error ("Cannot open `%s'", file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
     }
   else
     {
@@ -7363,7 +8659,7 @@
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      gif = DGifOpen(&memsrc, gif_read_from_memory);
+      gif = DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
 	{
 	  image_error ("Cannot open memory source `%s'", img->spec, Qnil);
@@ -7387,21 +8683,18 @@
   if (ino >= gif->ImageCount)
     {
       image_error ("Invalid image number `%s' in image `%s'",
-                   image, img->spec);
+		   image, img->spec);
       DGifCloseFile (gif);
       UNGCPRO;
       return 0;
     }
 
-  width = img->width = gif->SWidth;
-  height = img->height = gif->SHeight;
-
-  BLOCK_INPUT;
+  width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
+  height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
 
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
-      UNBLOCK_INPUT;
       DGifCloseFile (gif);
       UNGCPRO;
       return 0;
@@ -7411,7 +8704,9 @@
   gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
   if (!gif_color_map)
     gif_color_map = gif->SColorMap;
+#if 0 /* TODO: Color tables */
   init_color_table ();
+#endif
   bzero (pixel_colors, sizeof pixel_colors);
 
   for (i = 0; i < gif_color_map->ColorCount; ++i)
@@ -7422,8 +8717,10 @@
       pixel_colors[i] = lookup_rgb_color (f, r, g, b);
     }
 
+#if 0 /* TODO: Color tables */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 
   /* Clear the part of the screen image that are not covered by
      the image from the GIF file.  Full animated GIF support
@@ -7460,7 +8757,7 @@
     {
       static int interlace_start[] = {0, 4, 2, 1};
       static int interlace_increment[] = {8, 8, 4, 2};
-      int pass, inc;
+      int pass;
       int row = interlace_start[0];
 
       pass = 0;
@@ -7489,23 +8786,25 @@
       for (y = 0; y < image_height; ++y)
 	for (x = 0; x < image_width; ++x)
 	  {
-	    int i = raster[y* image_width + x];
+	    int i = raster[y * image_width + x];
 	    XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
 	  }
     }
 
   DGifCloseFile (gif);
 
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
+
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-  UNBLOCK_INPUT;
 
   UNGCPRO;
   return 1;
 }
-
-#endif /* HAVE_GIF != 0 */
+#endif /* HAVE_GIF */
 
 
 
@@ -7513,11 +8812,6 @@
 				Ghostscript
  ***********************************************************************/
 
-#ifdef HAVE_GHOSTSCRIPT
-static int gs_image_p P_ ((Lisp_Object object));
-static int gs_load P_ ((struct frame *f, struct image *img));
-static void gs_clear_image P_ ((struct frame *f, struct image *img));
-
 /* The symbol `postscript' identifying images of this type.  */
 
 Lisp_Object Qpostscript;
@@ -7526,6 +8820,11 @@
 
 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
 
+#ifdef HAVE_GHOSTSCRIPT
+static int gs_image_p P_ ((Lisp_Object object));
+static int gs_load P_ ((struct frame *f, struct image *img));
+static void gs_clear_image P_ ((struct frame *f, struct image *img));
+
 /* Indices of image specification fields in gs_format, below.  */
 
 enum gs_keyword_index
@@ -7541,6 +8840,8 @@
   GS_RELIEF,
   GS_ALGORITHM,
   GS_HEURISTIC_MASK,
+  GS_MASK,
+  GS_BACKGROUND,
   GS_LAST
 };
 
@@ -7555,11 +8856,13 @@
   {":file",		IMAGE_STRING_VALUE,			1},
   {":loader",		IMAGE_FUNCTION_VALUE,			0},
   {":bounding-box",	IMAGE_DONT_CHECK_VALUE_TYPE,		1},
-  {":ascent",		IMAGE_NON_NEGATIVE_INTEGER_VALUE,	0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
   {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
   {":relief",		IMAGE_INTEGER_VALUE,			0},
   {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0}
+  {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
+  {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
 };
 
 /* Structure describing the image type `ghostscript'.  */
@@ -7600,9 +8903,7 @@
 
   bcopy (gs_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
-      || (fmt[GS_ASCENT].count
-	  && XFASTINT (fmt[GS_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
     return 0;
 
   /* Bounding box must be a list or vector containing 4 integers.  */
@@ -7651,18 +8952,16 @@
      info.  */
   pt_width = image_spec_value (img->spec, QCpt_width, NULL);
   in_width = XFASTINT (pt_width) / 72.0;
-  img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
+  img->width = in_width * FRAME_MAC_DISPLAY_INFO (f)->resx;
   pt_height = image_spec_value (img->spec, QCpt_height, NULL);
   in_height = XFASTINT (pt_height) / 72.0;
-  img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
+  img->height = in_height * FRAME_MAC_DISPLAY_INFO (f)->resy;
 
   /* Create the pixmap.  */
-  BLOCK_INPUT;
-  xassert (img->pixmap == 0);
-  img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+  xassert (img->pixmap == NULL);
+  img->pixmap = XCreatePixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
 			       img->width, img->height,
-			       DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
-  UNBLOCK_INPUT;
+			       one_mac_display_info.n_planes);
 
   if (!img->pixmap)
     {
@@ -7677,7 +8976,7 @@
   GCPRO2 (window_and_pixmap_id, pixel_colors);
 
   sprintf (buffer, "%lu %lu",
-	   (unsigned long) FRAME_W32_WINDOW (f),
+	   (unsigned long) FRAME_MAC_WINDOW (f),
 	   (unsigned long) img->pixmap);
   window_and_pixmap_id = build_string (buffer);
 
@@ -7719,26 +9018,31 @@
     if (c->images[i]->pixmap == pixmap)
       break;
 
+  /* Should someone in between have cleared the image cache, for
+     instance, give up.  */
+  if (i == c->used)
+    return;
+
   /* Kill the GS process.  We should have found PIXMAP in the image
      cache and its image should contain a process object.  */
-  xassert (i < c->used);
   img = c->images[i];
   xassert (PROCESSP (img->data.lisp_val));
   Fkill_process (img->data.lisp_val, Qnil);
   img->data.lisp_val = Qnil;
 
+#if 0
   /* On displays with a mutable colormap, figure out the colors
      allocated for the image by looking at the pixels of an XImage for
      img->pixmap.  */
-  class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
+  class = FRAME_MAC_DISPLAY_INFO (f)->visual->class;
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      XImage *ximg;
+      XImagePtr ximg;
 
       BLOCK_INPUT;
 
       /* Try to get an XImage for img->pixmep.  */
-      ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
+      ximg = XGetImage (FRAME_MAC_DISPLAY (f), img->pixmap,
 			0, 0, img->width, img->height, ~0, ZPixmap);
       if (ximg)
 	{
@@ -7769,11 +9073,7 @@
 	     allocated colors on behalf of us.  So, to get the
 	     reference counts right, free them once.  */
 	  if (img->ncolors)
-	    {
-	      Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-	      XFreeColors (FRAME_W32_DISPLAY (f), cmap,
-			   img->colors, img->ncolors, 0);
-	    }
+	    x_free_colors (f, img->colors, img->ncolors);
 #endif
 	}
       else
@@ -7782,6 +9082,13 @@
 
       UNBLOCK_INPUT;
     }
+#endif
+
+  /* Now that we have the pixmap, compute mask and transform the
+     image if requested.  */
+  BLOCK_INPUT;
+  postprocess_image (f, img);
+  UNBLOCK_INPUT;
 }
 
 #endif /* HAVE_GHOSTSCRIPT */
@@ -8806,6 +10113,18 @@
 
   Qlaplace = intern ("laplace");
   staticpro (&Qlaplace);
+  Qemboss = intern ("emboss");
+  staticpro (&Qemboss);
+  Qedge_detection = intern ("edge-detection");
+  staticpro (&Qedge_detection);
+  Qheuristic = intern ("heuristic");
+  staticpro (&Qheuristic);
+  QCmatrix = intern (":matrix");
+  staticpro (&QCmatrix);
+  QCcolor_adjustment = intern (":color-adjustment");
+  staticpro (&QCcolor_adjustment);
+  QCmask = intern (":mask");
+  staticpro (&QCmask);
 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
@@ -8815,6 +10134,12 @@
   Fput (Qundefined_color, Qerror_message,
 	build_string ("Undefined color"));
 
+  DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
+    doc: /* Non-nil means always draw a cross over disabled images.
+Disabled images are those having an `:conversion disabled' property.
+A cross is always drawn on black & white displays.  */);
+  cross_disabled_images = 0;
+
   DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
 	       doc: /* List of directories to search for window system bitmap files.  */);
   Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
@@ -8880,9 +10205,11 @@
 meaning don't clear the cache.  */);
   Vimage_cache_eviction_delay = make_number (30 * 60);
 
+  /* X window properties.  */
   defsubr (&Sx_change_window_property);
   defsubr (&Sx_delete_window_property);
   defsubr (&Sx_window_property);
+
   defsubr (&Sxw_display_color_p);
   defsubr (&Sx_display_grayscale_p);
   defsubr (&Sxw_color_defined_p);
@@ -8919,15 +10246,12 @@
   load_font_func = x_load_font;
   find_ccl_program_func = x_find_ccl_program;
   query_font_func = x_query_font;
-
   set_frame_fontset_func = x_set_font;
   check_window_system_func = check_mac;
 
-#if 0 /* MAC_TODO: Image support for Mac Images.  */
+  /* Images.  */
   Qxbm = intern ("xbm");
   staticpro (&Qxbm);
-  QCtype = intern (":type");
-  staticpro (&QCtype);
   QCconversion = intern (":conversion");
   staticpro (&QCconversion);
   QCheuristic_mask = intern (":heuristic-mask");
@@ -8960,41 +10284,36 @@
   staticpro (&Qxpm);
 #endif
 
-#if HAVE_JPEG
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
-#endif
-
-#if HAVE_TIFF
+
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
-#endif
-
-#if HAVE_GIF
+
   Qgif = intern ("gif");
   staticpro (&Qgif);
-#endif
-
-#if HAVE_PNG
+
   Qpng = intern ("png");
   staticpro (&Qpng);
-#endif
 
   defsubr (&Sclear_image_cache);
+  defsubr (&Simage_size);
+  defsubr (&Simage_mask_p);
 
 #if GLYPH_DEBUG
   defsubr (&Simagep);
   defsubr (&Slookup_image);
 #endif
-#endif /* MAC_TODO */
 
   hourglass_atimer = NULL;
   hourglass_shown_p = 0;
 
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
+  tip_timer = Qnil;
   staticpro (&tip_timer);
-  tip_timer = Qnil;
+  tip_frame = Qnil;
+  staticpro (&tip_frame);
 
 #if 0 /* MAC_TODO */
   defsubr (&Sx_file_dialog);
@@ -9009,30 +10328,26 @@
   Vimage_types = Qnil;
 
   define_image_type (&xbm_type);
-#if 0 /* NTEMACS_TODO : Image support for W32 */
+#if HAVE_GHOSTSCRIPT
   define_image_type (&gs_type);
+#endif
   define_image_type (&pbm_type);
 
 #if HAVE_XPM
   define_image_type (&xpm_type);
 #endif
 
-#if HAVE_JPEG
   define_image_type (&jpeg_type);
-#endif
-
-#if HAVE_TIFF
   define_image_type (&tiff_type);
+  define_image_type (&gif_type);
+  define_image_type (&png_type);
+
+  /* Animated gifs use QuickTime Movie Toolbox.  So initialize it
+     here. */
+  EnterMovies ();
+#ifdef MAC_OSX
+  init_image_func_pointer ();
 #endif
-
-#if HAVE_GIF
-  define_image_type (&gif_type);
-#endif
-
-#if HAVE_PNG
-  define_image_type (&png_type);
-#endif
-#endif /* NTEMACS_TODO */
 }
 
 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc
--- a/src/macgui.h	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/macgui.h	Sat Feb 28 01:33:17 2004 +0000
@@ -23,9 +23,6 @@
 #ifndef EMACS_MACGUI_H
 #define EMACS_MACGUI_H
 
-typedef int Pixmap;
-typedef int Bitmap;
-
 typedef int Display;  /* fix later */
 
 typedef char * XrmDatabase;  /* fix later */
@@ -33,12 +30,43 @@
 typedef unsigned long Time;
 
 #if MAC_OSX
+#undef mktime
+#undef DEBUG
+#undef Z
+#undef free
+#undef malloc
+#undef realloc
+/* Macros max and min defined in lisp.h conflict with those in
+   precompiled header Carbon.h.  */
+#undef max
+#undef min
+#undef init_process
+#include <Carbon/Carbon.h>
+#undef Z
+#define Z (current_buffer->text->z)
+#undef free
+#define free unexec_free
+#undef malloc
+#define malloc unexec_malloc
+#undef realloc
+#define realloc unexec_realloc
+#undef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#undef init_process
+#define init_process emacs_init_process
+#undef INFINITY
 typedef struct OpaqueWindowPtr* Window;
 #else
-#include <QuickDraw.h>
+#include <QuickDraw.h>		/* for WindowPtr */
+#include <QDOffscreen.h>	/* for GWorldPtr */
+#include <Controls.h>		/* for ControlHandle in xdisp.c */
 typedef WindowPtr Window;
 #endif
 
+typedef GWorldPtr Pixmap;
+
 #define FACE_DEFAULT (~0)
 
 
--- a/src/macmenu.c	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/macmenu.c	Sat Feb 28 01:33:17 2004 +0000
@@ -35,34 +35,7 @@
 #include "charset.h"
 #include "coding.h"
 
-#ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
-#else /* not MAC_OSX */
+#ifndef MAC_OSX
 #include <MacTypes.h>
 #include <Menus.h>
 #include <QuickDraw.h>
--- a/src/macterm.c	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/macterm.c	Sat Feb 28 01:33:17 2004 +0000
@@ -35,29 +35,6 @@
 #endif
 
 #ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
    obtain events from the event queue.  If set to 0, WaitNextEvent is
    used instead.  */
@@ -303,7 +280,9 @@
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
+				   enum text_cursor_kinds));
+
 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
@@ -327,15 +306,12 @@
 
 /* X display function emulation */
 
-static void
+void
 XFreePixmap (display, pixmap)
-     Display *display;
+     Display *display;		/* not used */
      Pixmap pixmap;
 {
-  PixMap *p = (PixMap *) pixmap;
-
-  xfree (p->baseAddr);
-  xfree (p);
+  DisposeGWorld (pixmap); 
 }
 
 
@@ -347,9 +323,9 @@
 {
   RGBColor fg_color;
 
-  fg_color.red = RED_FROM_ULONG (color) * 256;
-  fg_color.green = GREEN_FROM_ULONG (color) * 256;
-  fg_color.blue = BLUE_FROM_ULONG (color) * 256;
+  fg_color.red = RED16_FROM_ULONG (color);
+  fg_color.green = GREEN16_FROM_ULONG (color);
+  fg_color.blue = BLUE16_FROM_ULONG (color);
 
   RGBForeColor (&fg_color);
 }
@@ -363,9 +339,9 @@
 {
   RGBColor bg_color;
 
-  bg_color.red = RED_FROM_ULONG (color) * 256;
-  bg_color.green = GREEN_FROM_ULONG (color) * 256;
-  bg_color.blue = BLUE_FROM_ULONG (color) * 256;
+  bg_color.red = RED16_FROM_ULONG (color);
+  bg_color.green = GREEN16_FROM_ULONG (color);
+  bg_color.blue = BLUE16_FROM_ULONG (color);
 
   RGBBackColor (&bg_color);
 }
@@ -401,6 +377,23 @@
   LineTo (x2, y2);
 }
 
+void
+mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
+     Display *display;
+     Pixmap p;
+     GC gc;
+     int x1, y1, x2, y2;
+{
+  SetGWorld (p, NULL);
+
+  mac_set_colors (gc);
+
+  LockPixels (GetGWorldPixMap (p));
+  MoveTo (x1, y1);
+  LineTo (x2, y2);
+  UnlockPixels (GetGWorldPixMap (p));
+}
+
 /* Mac version of XClearArea.  */
 
 void
@@ -479,7 +472,7 @@
   Rect r;
 
   bitmap.rowBytes = sizeof(unsigned short);
-  bitmap.baseAddr = bits;
+  bitmap.baseAddr = (char *)bits;
   SetRect (&(bitmap.bounds), 0, 0, width, height);
 
 #if TARGET_API_MAC_CARBON
@@ -489,18 +482,13 @@
 #endif
 
   mac_set_colors (gc);
-  SetRect (&r, x, y, x + bitmap.bounds.right, y + bitmap.bounds.bottom);
+  SetRect (&r, x, y, x + width, y + height);
 
 #if TARGET_API_MAC_CARBON
-  {
-    PixMapHandle pmh;
-
-    LockPortBits (GetWindowPort (w));
-    pmh = GetPortPixMap (GetWindowPort (w));
-    CopyBits (&bitmap, (BitMap *) *pmh, &(bitmap.bounds), &r,
-	      overlay_p ? srcOr : srcCopy, 0);
-    UnlockPortBits (GetWindowPort (w));
-  }
+  LockPortBits (GetWindowPort (w));
+  CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
+	    &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
+  UnlockPortBits (GetWindowPort (w));
 #else /* not TARGET_API_MAC_CARBON */
   CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
 	    overlay_p ? srcOr : srcCopy, 0);
@@ -546,6 +534,23 @@
 }
 
 
+/* XBM bits seem to be backward within bytes compared with how
+   Mac does things.  */
+static unsigned char
+reflect_byte (orig)
+     unsigned char orig;
+{
+  int i;
+  unsigned char reflected = 0x00;
+  for (i = 0; i < 8; i++)
+    {
+      if (orig & (0x01 << i))
+	reflected |= 0x80 >> i;
+    }
+  return reflected;
+}
+
+
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
 
 static void
@@ -554,18 +559,19 @@
      char *bits;
      int w, h;
 {
-  int bytes_per_row, i, j;
-
-  bitmap->rowBytes = (w + 15) / 16 * 2;  /* must be on word boundary */
+  int i, j, w1;
+  char *p;
+
+  w1 = (w + 7) / 8;         /* nb of 8bits elt in X bitmap */
+  bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
   bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
-  if (!bitmap->baseAddr)
-    abort ();
-
   bzero (bitmap->baseAddr, bitmap->rowBytes * h);
   for (i = 0; i < h; i++)
-    for (j = 0; j < w; j++)
-      if (BitTst (bits, i * w + j))
-        BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
+    {
+      p = bitmap->baseAddr + i * bitmap->rowBytes;
+      for (j = 0; j < w1; j++)
+        *p++ = reflect_byte (*bits++);
+    }
 
   SetRect (&(bitmap->bounds), 0, 0, w, h);
 }
@@ -578,6 +584,67 @@
   xfree (bitmap->baseAddr);
 }
 
+
+Pixmap
+XCreatePixmap (display, w, width, height, depth)
+     Display *display;		/* not used */
+     WindowPtr w;
+     unsigned int width, height;
+     unsigned int depth;	/* not used */
+{
+  Pixmap pixmap;
+  Rect r;
+  QDErr err;
+
+#if TARGET_API_MAC_CARBON
+  SetPort (GetWindowPort (w));
+#else
+  SetPort (w);
+#endif
+
+  SetRect (&r, 0, 0, width, height);
+  err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+  if (err != noErr)
+    return NULL;
+  return pixmap;
+}
+
+
+Pixmap
+XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
+     Display *display;		/* not used */
+     WindowPtr w;
+     char *data;
+     unsigned int width, height;
+     unsigned long fg, bg;
+     unsigned int depth;	/* not used */
+{
+  Pixmap pixmap;
+  BitMap bitmap;
+
+  pixmap = XCreatePixmap (display, w, width, height, depth);
+  if (pixmap == NULL)
+    return NULL;
+
+  SetGWorld (pixmap, NULL);
+  mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
+  mac_set_forecolor (fg);
+  mac_set_backcolor (bg);
+  LockPixels (GetGWorldPixMap (pixmap));
+#if TARGET_API_MAC_CARBON
+  CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
+	    &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
+	    &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (pixmap));
+  mac_free_bitmap (&bitmap);
+
+  return pixmap;
+}
+
+
 /* Mac replacement for XFillRectangle.  */
 
 static void
@@ -603,6 +670,26 @@
 }
 
 
+static void
+mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
+     Display *display;
+     Pixmap p;
+     GC gc;
+     int x, y;
+     unsigned int width, height;
+{
+  Rect r;
+
+  SetGWorld (p, NULL);
+  mac_set_colors (gc);
+  SetRect (&r, x, y, x + width, y + height);
+
+  LockPixels (GetGWorldPixMap (p));
+  PaintRect (&r); /* using foreground color of gc */
+  UnlockPixels (GetGWorldPixMap (p));
+}
+
+
 /* Mac replacement for XDrawRectangle: dest is a window.  */
 
 static void
@@ -638,20 +725,15 @@
      int x, y;
      unsigned int width, height;
 {
-#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
-
+  SetGWorld (p, NULL);
   mac_set_colors (gc);
-  SetRect (&r, x, y, x + width, y + height);
-
+  SetRect (&r, x, y, x + width + 1, y + height + 1);
+
+  LockPixels (GetGWorldPixMap (p));
   FrameRect (&r); /* using foreground color of gc */
-#endif /* 0 */
+  UnlockPixels (GetGWorldPixMap (p));
 }
 
 
@@ -766,23 +848,66 @@
   SetPort (dest);
 #endif
 
-  mac_set_colors (gc);
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  LockPixels (GetGWorldPixMap (src));
+#if TARGET_API_MAC_CARBON
+  LockPortBits (GetWindowPort (dest));
+  CopyBits (GetPortBitMapForCopyBits (src),
+	    GetPortBitMapForCopyBits (GetWindowPort (dest)),
+	    &src_r, &dest_r, srcCopy, 0);
+  UnlockPortBits (GetWindowPort (dest));
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
+	    &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (src));
+}
+
+
+static void
+mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
+			 width, height, dest_x, dest_y)
+     Display *display;
+     Pixmap src, mask;
+     WindowPtr dest;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y;
+{
+  Rect src_r, dest_r;
+
+#if TARGET_API_MAC_CARBON
+  SetPort (GetWindowPort (dest));
+#else
+  SetPort (dest);
+#endif
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
 
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (mask));
 #if TARGET_API_MAC_CARBON
-  {
-    PixMapHandle pmh;
-
-    LockPortBits (GetWindowPort (dest));
-    pmh = GetPortPixMap (GetWindowPort (dest));
-    CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
-    UnlockPortBits (GetWindowPort (dest));
-  }
+  LockPortBits (GetWindowPort (dest));
+  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+	    GetPortBitMapForCopyBits (GetWindowPort (dest)),
+	    &src_r, &src_r, &dest_r);
+  UnlockPortBits (GetWindowPort (dest));
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
+  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
+	    &(dest->portBits), &src_r, &src_r, &dest_r);
 #endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (mask));
+  UnlockPixels (GetGWorldPixMap (src));
 }
 
 
@@ -817,7 +942,6 @@
 {
 #if TARGET_API_MAC_CARBON
   Rect gw_r, src_r, dest_r;
-  PixMapHandle pmh;
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -828,8 +952,10 @@
   BackColor (whiteColor);
 
   LockPortBits (GetWindowPort (w));
-  pmh = GetPortPixMap (GetWindowPort (w));
-  CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
+  {
+    const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
+    CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
+  }
   UnlockPortBits (GetWindowPort (w));
 
   mac_set_colors (gc);
@@ -872,25 +998,67 @@
 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
                      dest_x, dest_y)
      Display *display;
-     Pixmap src;
-     Pixmap dest;
+     Pixmap src, dest;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
      int dest_x, dest_y;
 {
   Rect src_r, dest_r;
-  int src_right = ((PixMap *) src)->bounds.right;
-  int src_bottom = ((PixMap *) src)->bounds.bottom;
-  int w = src_right - src_x;
-  int h = src_bottom - src_y;
-
-  mac_set_colors (gc);
-
-  SetRect (&src_r, src_x, src_y, src_right, src_bottom);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
-
-  CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
+
+  SetGWorld (dest, NULL);
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (dest));
+#if TARGET_API_MAC_CARBON
+  CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
+	    &src_r, &dest_r, srcCopy, 0);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
+	    &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (dest));
+  UnlockPixels (GetGWorldPixMap (src));
+}
+
+
+static void
+mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
+				   width, height, dest_x, dest_y)
+     Display *display;
+     Pixmap src, mask, dest;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y;
+{
+  Rect src_r, dest_r;
+
+  SetGWorld (dest, NULL);
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (mask));
+  LockPixels (GetGWorldPixMap (dest));
+#if TARGET_API_MAC_CARBON
+  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+	    GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
+	    &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (dest));
+  UnlockPixels (GetGWorldPixMap (mask));
+  UnlockPixels (GetGWorldPixMap (src));
 }
 
 
@@ -947,7 +1115,7 @@
 
 /* Mac replacement for XSetForeground.  */
 
-static void
+void
 XSetForeground (display, gc, color)
      Display *display;
      GC gc;
@@ -2139,6 +2307,21 @@
 
 #endif /* MAC_TODO */
 
+
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
+
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-255) have to
+   use an additional additive factor.
+
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
+
+
 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
    If this produces the same color as COLOR, try a color where all RGB
@@ -2154,12 +2337,42 @@
      int delta;
 {
   unsigned long new;
+  long bright;
+
+  /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
+  delta /= 256;
 
   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
   xassert (factor >= 0);
   new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
                     min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
                     min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
+
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
+            + BLUE_FROM_ULONG (*color)) / 6;
+
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
+    {
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+
+      if (factor < 1)
+        new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
+			    max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
+			    max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
+      else
+        new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
+			    max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
+			    max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
+    }
+
   if (new == *color)
     new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
                       max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
@@ -2204,7 +2417,8 @@
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
   pixel = background;
-  if (mac_alloc_lighter_color (f, &pixel, factor, delta))
+  if (dpyinfo->n_planes != 1
+      && mac_alloc_lighter_color (f, &pixel, factor, delta))
     {
       relief->allocated_p = 1;
       xgcv.foreground = relief->pixel = pixel;
@@ -2234,6 +2448,10 @@
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+	   && s->img->pixmap
+	   && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
     {
       XGCValues xgcv;
@@ -2267,9 +2485,11 @@
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
 		    raised_p, left_p, right_p, clip_rect)
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
      Rect *clip_rect;
 {
+  Display *dpy = FRAME_MAC_DISPLAY (f);
+  Window window = FRAME_MAC_WINDOW (f);
   int i;
   GC gc;
 
@@ -2277,41 +2497,41 @@
     gc = f->output_data.mac->white_relief.gc;
   else
     gc = f->output_data.mac->black_relief.gc;
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
+  mac_set_clip_rectangle (dpy, window, clip_rect);
 
   /* Top.  */
   for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+    XDrawLine (dpy, window, gc,
 	       left_x + i * left_p, top_y + i,
-	       right_x + 1 - i * right_p, top_y + i);
+	       right_x - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+      XDrawLine (dpy, window, gc,
 		 left_x + i, top_y + i, left_x + i, bottom_y - i);
 
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_reset_clipping (dpy, window);
   if (raised_p)
     gc = f->output_data.mac->black_relief.gc;
   else
     gc = f->output_data.mac->white_relief.gc;
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+  mac_set_clip_rectangle (dpy, window,
 			  clip_rect);
 
   /* Bottom.  */
   for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+    XDrawLine (dpy, window, gc,
 	       left_x + i * left_p, bottom_y - i,
-	       right_x + 1 - i * right_p, bottom_y - i);
+	       right_x - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
-		 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
-
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+      XDrawLine (dpy, window, gc,
+		 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
+
+  mac_reset_clipping (dpy, window);
 }
 
 
@@ -2326,7 +2546,7 @@
 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
 		 left_p, right_p, clip_rect)
      struct glyph_string *s;
-     int left_x, top_y, right_x, bottom_y, left_p, right_p;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
      Rect *clip_rect;
 {
   XGCValues xgcv;
@@ -2336,21 +2556,21 @@
 
   /* Top.  */
   XFillRectangle (s->display, s->window, &xgcv,
-		  left_x, top_y, right_x - left_x, width);
+		  left_x, top_y, right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
     XFillRectangle (s->display, s->window, &xgcv,
-		    left_x, top_y, width, bottom_y - top_y);
+		    left_x, top_y, width, bottom_y - top_y + 1);
 
   /* Bottom.  */
   XFillRectangle (s->display, s->window, &xgcv,
-		  left_x, bottom_y - width, right_x - left_x, width);
+		  left_x, bottom_y - width + 1, right_x - left_x + 1, width);
 
   /* Right.  */
   if (right_p)
     XFillRectangle (s->display, s->window, &xgcv,
-		    right_x - width, top_y, width, bottom_y - top_y);
+		    right_x - width + 1, top_y, width, bottom_y - top_y + 1);
 
   mac_reset_clipping (s->display, s->window);
 }
@@ -2385,9 +2605,9 @@
   width = abs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
-  right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
-	      ? last_x - 1
-	      : min (last_x, s->x + s->background_width) - 1));
+  right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
+	     ? last_x - 1
+	     : min (last_x, s->x + s->background_width) - 1);
   top_y = s->y;
   bottom_y = top_y + s->height - 1;
 
@@ -2438,39 +2658,36 @@
 
   if (s->img->pixmap)
     {
-#if 0 /* MAC_TODO: image mask */
       if (s->img->mask)
 	{
-	  /* We can't set both a clip mask and use XSetClipRectangles
-	     because the latter also sets a clip mask.  We also can't
-	     trust on the shape extension to be available
-	     (XShapeCombineRegion).  So, compute the rectangle to draw
-	     manually.  */
-	  unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-				| GCFunction);
-	  XGCValues xgcv;
+	  Rect nr;
 	  XRectangle clip_rect, image_rect, r;
 
-	  xgcv.clip_mask = s->img->mask;
-	  xgcv.clip_x_origin = x;
-	  xgcv.clip_y_origin = y;
-	  xgcv.function = GXcopy;
-	  XChangeGC (s->display, s->gc, mask, &xgcv);
-
-	  get_glyph_string_clip_rect (s, &clip_rect);
+	  get_glyph_string_clip_rect (s, &nr);
+	  CONVERT_TO_XRECT (clip_rect, nr);
 	  image_rect.x = x;
 	  image_rect.y = y;
 	  image_rect.width = s->img->width;
 	  image_rect.height = s->img->height;
 	  if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-	    XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-		       r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+	    mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
+				     s->window, s->gc, r.x - x, r.y - y,
+				     r.width, r.height, r.x, r.y);
 	}
       else
-#endif /* MAC_TODO */
 	{
-	  mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
-		       0, 0, s->img->width, s->img->height, x, y);
+	  Rect nr;
+	  XRectangle clip_rect, image_rect, r;
+
+	  get_glyph_string_clip_rect (s, &nr);
+	  CONVERT_TO_XRECT (clip_rect, nr);
+	  image_rect.x = x;
+	  image_rect.y = y;
+	  image_rect.width = s->img->width;
+	  image_rect.height = s->img->height;
+	  if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+	    mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
+			   r.x - x, r.y - y, r.width, r.height, r.x, r.y);
 
 	  /* When the image has a mask, we can expect that at
 	     least part of a mouse highlight or a block cursor will
@@ -2494,7 +2711,6 @@
 }
 
 
-
 /* Draw a relief around the image glyph string S.  */
 
 static void
@@ -2567,30 +2783,12 @@
 
   if (s->img->pixmap)
     {
-#if 0 /* MAC_TODO: image mask */
       if (s->img->mask)
-	{
-	  /* We can't set both a clip mask and use XSetClipRectangles
-	     because the latter also sets a clip mask.  We also can't
-	     trust on the shape extension to be available
-	     (XShapeCombineRegion).  So, compute the rectangle to draw
-	     manually.  */
-	  unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-				| GCFunction);
-	  XGCValues xgcv;
-
-	  xgcv.clip_mask = s->img->mask;
-	  xgcv.clip_x_origin = x;
-	  xgcv.clip_y_origin = y;
-	  xgcv.function = GXcopy;
-	  XChangeGC (s->display, s->gc, mask, &xgcv);
-
-	  XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-		     0, 0, s->img->width, s->img->height, x, y);
-	  XSetClipMask (s->display, s->gc, None);
-	}
+	mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
+					   s->img->mask, pixmap, s->gc,
+					   0, 0, s->img->width, s->img->height,
+					   x, y);
       else
-#endif /* MAC_TODO */
 	{
 	  mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
 		               0, 0, s->img->width, s->img->height, x, y);
@@ -2605,15 +2803,16 @@
 	    {
 	      int r = s->img->relief;
 	      if (r < 0) r = -r;
-	      mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
-				  s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+	      mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
+				  s->img->width + r*2 - 1,
+				  s->img->height + r*2 - 1);
 	    }
 	}
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
-		              s->img->width - 1, s->img->height - 1);
+				  s->img->width - 1, s->img->height - 1);
 }
 
 
@@ -2646,7 +2845,7 @@
 	     |   s->face->box
 	     |
 	     |     +-------------------------
-	     |     |  s->img->vmargin
+	     |     |  s->img->margin
 	     |     |
 	     |     |       +-------------------
 	     |     |       |  the image
@@ -2665,6 +2864,7 @@
 
   height = s->height - 2 * box_line_vwidth;
 
+
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
@@ -2672,9 +2872,7 @@
   if (height > s->img->height
       || s->img->hmargin
       || s->img->vmargin
-#if 0 /* TODO: image mask */
       || s->img->mask
-#endif
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
@@ -2684,25 +2882,21 @@
 	x = s->x;
 
       y = s->y + box_line_vwidth;
-#if 0 /* TODO: image mask */
+
       if (s->img->mask)
 	{
 	  /* Create a pixmap as large as the glyph string.  Fill it
 	     with the background color.  Copy the image to it, using
 	     its mask.  Copy the temporary pixmap to the display.  */
-	  Screen *screen = FRAME_X_SCREEN (s->f);
-	  int depth = DefaultDepthOfScreen (screen);
+	  int depth = one_mac_display_info.n_planes;
 
 	  /* Create a pixmap as large as the glyph string.  */
  	  pixmap = XCreatePixmap (s->display, s->window,
 				  s->background_width,
 				  s->height, depth);
 
-	  /* Don't clip in the following because we're working on the
-	     pixmap.  */
-	  XSetClipMask (s->display, s->gc, None);
-
 	  /* Fill the pixmap with the background color/stipple.  */
+#if 0 /* TODO: stipple */
 	  if (s->stippled_p)
 	    {
 	      /* Fill background with a stipple pattern.  */
@@ -2712,18 +2906,19 @@
 	      XSetFillStyle (s->display, s->gc, FillSolid);
 	    }
 	  else
+#endif
 	    {
 	      XGCValues xgcv;
 	      XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
 			    &xgcv);
 	      XSetForeground (s->display, s->gc, xgcv.background);
-	      XFillRectangle (s->display, pixmap, s->gc,
-			      0, 0, s->background_width, s->height);
+	      mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
+					    0, 0, s->background_width,
+					    s->height);
 	      XSetForeground (s->display, s->gc, xgcv.foreground);
 	    }
 	}
       else
-#endif
 	x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
@@ -2735,7 +2930,7 @@
       x_draw_image_foreground_1 (s, pixmap);
       x_set_glyph_string_clipping (s);
       mac_copy_area (s->display, pixmap, s->window, s->gc,
-		   0, 0, s->background_width, s->height, s->x, s->y);
+		     0, 0, s->background_width, s->height, s->x, s->y);
       mac_reset_clipping (s->display, s->window);
       XFreePixmap (s->display, pixmap);
     }
@@ -2772,10 +2967,10 @@
       /* Clear rest using the GC of the original non-cursor face.  */
       if (width < s->background_width)
 	{
-	  GC gc = s->face->gc;
 	  int x = s->x + width, y = s->y;
 	  int w = s->background_width - width, h = s->height;
 	  Rect r;
+	  GC gc;
 
 	  if (s->row->mouse_face_p
 	      && cursor_in_mouse_face_p (s->w))
@@ -2835,7 +3030,6 @@
       x_set_glyph_string_gc (s->next);
       x_set_glyph_string_clipping (s->next);
       x_draw_glyph_string_background (s->next, 1);
-
     }
 
   /* Set up S->gc, set clipping and draw S.  */
@@ -2872,7 +3066,7 @@
       if (s->for_overlaps_p)
 	s->background_filled_p = 1;
       else
-        x_draw_glyph_string_background (s, 0);
+	x_draw_glyph_string_background (s, 0);
       x_draw_glyph_string_foreground (s);
       break;
 
@@ -2949,9 +3143,9 @@
 	    }
 	}
 
-      /* Draw relief.  */
+      /* Draw relief if not yet drawn.  */
       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
-        x_draw_glyph_string_box (s);
+	x_draw_glyph_string_box (s);
     }
 
   /* Reset clipping.  */
@@ -2971,7 +3165,6 @@
 		   x + shift_by, y);
 }
 
-
 /* Delete N glyphs at the nominal cursor position.  Not implemented
    for X frames.  */
 
@@ -3026,6 +3219,7 @@
 
 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
 
+
 /* Subtract the `struct timeval' values X and Y, storing the result in
    *RESULT.  Return 1 if the difference is negative, otherwise 0.  */
 
@@ -3129,7 +3323,7 @@
    This, and those operations, are used only within an update
    that is bounded by calls to x_update_begin and x_update_end.  */
 
-void
+static void
 XTset_terminal_window (n)
      register int n;
 {
@@ -3165,7 +3359,7 @@
 
   /* Get frame-relative bounding box of the text display area of W,
      without mode lines.  Include in this box the left and right
-     fringes of W.  */
+     fringe of W.  */
   window_box (w, -1, &x, &y, &width, &height);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
@@ -3287,8 +3481,6 @@
 XTframe_rehighlight (frame)
      struct frame *frame;
 {
-
-
   x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
 }
 
@@ -4429,13 +4621,6 @@
   struct glyph *cursor_glyph;
   GC gc;
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
-       + row->ascent - w->phys_cursor_ascent);
-  h = row->height - 1;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
@@ -4450,6 +4635,20 @@
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
     wd = min (FRAME_COLUMN_WIDTH (f), wd);
+  w->phys_cursor_width = wd;
+
+  /* Compute frame-relative coordinates from window-relative
+     coordinates.  */
+  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+  y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
+
+  /* Compute the proper height and ascent of the rectangle, based
+     on the actual glyph.  Using the full height of the row looks
+     bad when there are tall images on that row.  */
+  h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent);
+  if (h < row->height)
+    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
+  h--;
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -4476,35 +4675,49 @@
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row, width)
+x_draw_bar_cursor (w, row, width, kind)
      struct window *w;
      struct glyph_row *row;
      int width;
-{
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      struct frame *f = XFRAME (w->frame);
-      struct glyph *cursor_glyph;
-      GC gc;
-      int x;
-      unsigned long mask;
+     enum text_cursor_kinds kind;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct glyph *cursor_glyph;
+
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
+
+  /* If on an image, draw like a normal cursor.  That's usually better
+     visible than drawing a bar, esp. if the image is large so that
+     the bar might not be in the window.  */
+  if (cursor_glyph->type == IMAGE_GLYPH)
+    {
+      struct glyph_row *row;
+      row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+      draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+    }
+  else
+    {
+      Display *dpy = FRAME_MAC_DISPLAY (f);
+      Window window = FRAME_MAC_WINDOW (f);
+      GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
+      unsigned long mask = GCForeground | GCBackground;
+      struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
       XGCValues xgcv;
-      Display *dpy;
-      Window window;
-
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-	return;
-
-      xgcv.background = f->output_data.mac->cursor_pixel;
-      xgcv.foreground = f->output_data.mac->cursor_pixel;
-      mask = GCForeground | GCBackground;
-      dpy = FRAME_MAC_DISPLAY (f);
-      window = FRAME_MAC_WINDOW (f);
-      gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
+
+      /* If the glyph's background equals the color we normally draw
+	 the bar cursor in, the bar cursor in its normal color is
+	 invisible.  Use the glyph's foreground color instead in this
+	 case, on the assumption that the glyph's colors are chosen so
+	 that the glyph is legible.  */
+      if (face->background == f->output_data.mac->cursor_pixel)
+	xgcv.background = xgcv.foreground = face->foreground;
+      else
+	xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
 
       if (gc)
 	XChangeGC (dpy, gc, mask, &xgcv);
@@ -4516,14 +4729,24 @@
 
       if (width < 0)
 	width = FRAME_CURSOR_WIDTH (f);
-
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      width = min (cursor_glyph->pixel_width, width);
+
+      w->phys_cursor_width = width;
       x_clip_to_row (w, row, gc);
-      XFillRectangle (dpy, window, gc,
-		      x,
-		      WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-		      min (cursor_glyph->pixel_width, width),
-		      row->height);
+
+      if (kind == BAR_CURSOR)
+	XFillRectangle (dpy, window, gc,
+			WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+			WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+			width, row->height);
+      else
+	XFillRectangle (dpy, window, gc,
+			WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+			WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+						 row->height - width),
+			cursor_glyph->pixel_width,
+			width);
+
       mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
     }
 }
@@ -4565,7 +4788,6 @@
   if (on_p)
     {
       w->phys_cursor_type = cursor_type;
-      w->phys_cursor_width = cursor_width;
       w->phys_cursor_on_p = 1;
 
       if (glyph_row->exact_window_width_line_p
@@ -4573,9 +4795,8 @@
 	{
 	  glyph_row->cursor_in_fringe_p = 1;
 	  draw_fringe_bitmap (w, glyph_row, 0);
-	  return;
 	}
-
+      else
       switch (cursor_type)
 	{
 	case HOLLOW_BOX_CURSOR:
@@ -4586,13 +4807,16 @@
 	  draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
 	  break;
 
+	case BAR_CURSOR:
+	  x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+	  break;
+
 	case HBAR_CURSOR:
-	  /* TODO.  For now, just draw bar cursor. */
-	case BAR_CURSOR:
-	  x_draw_bar_cursor (w, glyph_row, cursor_width);
+	  x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
 	  break;
 
 	case NO_CURSOR:
+	  w->phys_cursor_width = 0;
 	  break;
 
 	default:
@@ -5117,6 +5341,8 @@
 	FRAME_SAMPLE_VISIBILITY (f);
       }
   }
+#else
+  UNBLOCK_INPUT;
 #endif /* MAC_TODO */
 }
 
@@ -5173,10 +5399,10 @@
 }
 
 
-/* Destroy the X window of frame F.  */
+/* Free X resources of frame F.  */
 
 void
-x_destroy_window (f)
+x_free_frame_resources (f)
      struct frame *f;
 {
   struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
@@ -5186,10 +5412,15 @@
   DisposeWindow (FRAME_MAC_WINDOW (f));
 
   free_frame_menubar (f);
-  free_frame_faces (f);
+
+  if (FRAME_FACE_CACHE (f))
+    free_frame_faces (f);
+
+  x_free_gcs (f);
 
   xfree (f->output_data.mac);
-  f->output_data.mac = 0;
+  f->output_data.mac = NULL;
+
   if (f == dpyinfo->x_focus_frame)
     dpyinfo->x_focus_frame = 0;
   if (f == dpyinfo->x_focus_event_frame)
@@ -5197,8 +5428,6 @@
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
 
-  dpyinfo->reference_count--;
-
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row
@@ -5212,6 +5441,21 @@
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the X window of frame F.  */
+
+void
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 
 /* Setting window manager hints.  */
 
@@ -5478,6 +5722,7 @@
 int font_name_table_size = 0;
 int font_name_count = 0;
 
+#if 0
 /* compare two strings ignoring case */
 static int
 stricmp (const char *s, const char *t)
@@ -5557,13 +5802,53 @@
           && wildstrieq (m_charset, x_charset))
          || mac_font_pattern_match (mf, xf);
 }
+#endif
+
+static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
+
+static void
+decode_mac_font_name (char *name, int size, short scriptcode)
+{
+  Lisp_Object coding_system;
+  struct coding_system coding;
+  char *buf;
+
+  switch (scriptcode)
+    {
+    case smTradChinese:
+      coding_system = Qbig5;
+      break;
+    case smSimpChinese:
+      coding_system = Qcn_gb;
+      break;
+    case smJapanese:
+      coding_system = Qsjis;
+      break;
+    case smKorean:
+      coding_system = Qeuc_kr;
+      break;        
+    default:
+      return;
+    }
+
+  setup_coding_system (coding_system, &coding);
+  coding.src_multibyte = 0;
+  coding.dst_multibyte = 1;
+  coding.mode |= CODING_MODE_LAST_BLOCK;
+  coding.composing = COMPOSITION_DISABLED;
+  buf = (char *) alloca (size);
+
+  decode_coding (&coding, name, buf, strlen (name), size - 1);
+  bcopy (buf, name, coding.produced);
+  name[coding.produced] = '\0';
+}
 
 
 static char *
 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
 {
   char foundry[32], family[32], cs[32];
-  char xf[255], *result, *p;
+  char xf[256], *result, *p;
 
   if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
     {
@@ -5622,6 +5907,8 @@
 x_font_name_to_mac_font_name (char *xf, char *mf)
 {
   char foundry[32], family[32], weight[20], slant[2], cs[32];
+  Lisp_Object coding_system = Qnil;
+  struct coding_system coding;
 
   strcpy (mf, "");
 
@@ -5631,13 +5918,29 @@
               foundry, family, weight, slant, cs) != 5)
     return;
 
-  if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
-      || strcmp (cs, "jisx0208.1983-sjis") == 0
-      || strcmp (cs, "jisx0201.1976-0") == 0
-      || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
-    strcpy(mf, family);
+  if (strcmp (cs, "big5-0") == 0)
+    coding_system = Qbig5;
+  else if (strcmp (cs, "gb2312.1980-0") == 0)
+    coding_system = Qcn_gb;
+  else if (strcmp (cs, "jisx0208.1983-sjis") == 0
+	   || strcmp (cs, "jisx0201.1976-0") == 0)
+    coding_system = Qsjis;
+  else if (strcmp (cs, "ksc5601.1989-0") == 0)
+    coding_system = Qeuc_kr;
+  else if (strcmp (cs, "mac-roman") == 0)
+    strcpy (mf, family);
   else
-    sprintf(mf, "%s-%s-%s", foundry, family, cs);
+    sprintf (mf, "%s-%s-%s", foundry, family, cs);
+
+  if (!NILP (coding_system))
+    {
+      setup_coding_system (coding_system, &coding);
+      coding.src_multibyte = 1;
+      coding.dst_multibyte = 1;
+      coding.mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
+      mf[coding.produced] = '\0';
+    }
 }
 
 
@@ -5701,36 +6004,45 @@
 	  if (FMGetFontFamilyName (ff, name) != noErr)
 	    break;
 	  p2cstr (name);
+	  if (*name == '.')
+	    continue;
 
 	  sc = FontToScript (ff);
+	  decode_mac_font_name (name, sizeof (name), sc);
 
 	  /* Point the instance iterator at the current font family.  */
-	  if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
+	  if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
 	    break;
 
 	  while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
 		 == noErr)
-	    if (size == 0)
-	      {
+	    {
+	      /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
+		 contained in Apple Japanese (SJIS) font.  */
+	    again:
+	      if (size == 0)
+		{
+		  add_font_name_table_entry (mac_to_x_fontname (name, size,
+								style, sc));
+		  add_font_name_table_entry (mac_to_x_fontname (name, size,
+								italic, sc));
+		  add_font_name_table_entry (mac_to_x_fontname (name, size,
+								bold, sc));
+		  add_font_name_table_entry (mac_to_x_fontname (name, size,
+								italic | bold,
+								sc));
+		}
+	      else
 		add_font_name_table_entry (mac_to_x_fontname (name, size,
 							      style, sc));
-		add_font_name_table_entry (mac_to_x_fontname (name, size,
-							      italic, sc));
-		add_font_name_table_entry (mac_to_x_fontname (name, size,
-							      bold, sc));
-		add_font_name_table_entry (mac_to_x_fontname (name, size,
-							      italic | bold,
-							      sc));
-	      }
-	    else
-	      {
-		add_font_name_table_entry (mac_to_x_fontname (name, size,
-							      style, sc));
-		if (smJapanese == sc)
-		  add_font_name_table_entry (mac_to_x_fontname (name, size,
-								style,
-								-smJapanese));
-	      }
+	      if (sc == smJapanese)
+		{
+		  sc = -smJapanese;
+		  goto again;
+		}
+	      else if (sc == -smJapanese)
+		sc = smJapanese;
+	    }
 	}
 
       /* Dispose of the iterators.  */
@@ -5772,6 +6084,7 @@
 
 	  TextFont (fontnum);
 	  scriptcode = FontToScript (fontnum);
+	  decode_mac_font_name (name, sizeof (name), scriptcode);
 	  do
 	    {
 	      HLock (font_handle);
@@ -5806,9 +6119,9 @@
 					     assc_entry->fontSize,
 					     assc_entry->fontStyle,
 					     scriptcode);
-		      /* Both jisx0208.1983-sjis and
-			 jisx0201.1976-sjis parts are contained in
-			 Apple Japanese (SJIS) font.  */
+		      /* Both jisx0208.1983-sjis and jisx0201.1976-0
+			 parts are contained in Apple Japanese (SJIS)
+			 font.  */
 		      if (smJapanese == scriptcode)
 			{
 			  font_name_table[font_name_count++]
@@ -5835,6 +6148,145 @@
 }
 
 
+enum xlfd_scalable_field_index
+  {
+    XLFD_SCL_PIXEL_SIZE,
+    XLFD_SCL_POINT_SIZE,
+    XLFD_SCL_AVGWIDTH,
+    XLFD_SCL_LAST
+  };
+
+static int xlfd_scalable_fields[] =
+  {
+    6,				/* PIXEL_SIZE */
+    7,				/* POINT_SIZE */
+    11,				/* AVGWIDTH */
+    -1
+  };
+
+static Lisp_Object
+mac_do_list_fonts (pattern, maxnames)
+     char *pattern;
+     int maxnames;
+{
+  int i, n_fonts = 0;
+  Lisp_Object font_list = Qnil, pattern_regex, fontname;
+  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
+  char scaled[256];
+  char *ptr;
+  int scl_val[XLFD_SCL_LAST], *field, *val;
+
+  for (i = 0; i < XLFD_SCL_LAST; i++)
+    scl_val[i] = -1;
+
+  /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
+     POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
+     fonts are scaled according to the specified size.  */
+  ptr = pattern;
+  i = 0;
+  field = xlfd_scalable_fields;
+  val = scl_val;
+  if (*ptr == '-')
+    do
+      {
+	ptr++;
+	if (i == *field)
+	  {
+	    if ('1' <= *ptr && *ptr <= '9')
+	      {
+		*val = *ptr++ - '0';
+		while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
+		  *val = *val * 10 + *ptr++ - '0';
+		if (*ptr != '-')
+		  *val = -1;
+	      }
+	    field++;
+	    val++;
+	  }
+	ptr = strchr (ptr, '-');
+	i++;
+      }
+    while (ptr && i < 14);
+
+  if (i == 14 && ptr == NULL)
+    {
+      if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
+	{
+	  scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
+	  scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
+	}
+      else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
+	{
+	  scl_val[XLFD_SCL_POINT_SIZE] =
+	    scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
+	}
+      else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
+	{
+	  scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
+	  scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
+	}
+    }
+  else
+    scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
+
+  ptr = regex;
+  *ptr++ = '^';
+
+  /* Turn pattern into a regexp and do a regexp match.  */
+  for (; *pattern; pattern++)
+    {
+      if (*pattern == '?')
+        *ptr++ = '.';
+      else if (*pattern == '*')
+        {
+          *ptr++ = '.';
+          *ptr++ = '*';
+        }
+      else
+        *ptr++ = tolower (*pattern);
+    }
+  *ptr = '$';
+  *(ptr + 1) = '\0';
+
+  pattern_regex = build_string (regex);
+
+  for (i = 0; i < font_name_count; i++)
+    {
+      fontname = build_string (font_name_table[i]);
+      if (fast_string_match (pattern_regex, fontname) >= 0)
+	{
+	  font_list = Fcons (fontname, font_list);
+
+          n_fonts++;
+          if (maxnames > 0 && n_fonts >= maxnames)
+            break;
+	}
+      else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
+	       && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
+	{
+	  int former_len = ptr - font_name_table[i];
+
+	  memcpy (scaled, font_name_table[i], former_len);
+	  sprintf (scaled + former_len,
+		   "-%d-%d-75-75-m-%d-%s",
+		   scl_val[XLFD_SCL_PIXEL_SIZE],
+		   scl_val[XLFD_SCL_POINT_SIZE],
+		   scl_val[XLFD_SCL_AVGWIDTH],
+		   ptr + sizeof ("-0-0-75-75-m-0-") - 1);
+	  fontname = build_string (scaled);
+	  if (fast_string_match (pattern_regex, fontname) >= 0)
+	    {
+	      font_list = Fcons (fontname, font_list);
+	      
+	      n_fonts++;
+	      if (maxnames > 0 && n_fonts >= maxnames)
+		break;
+	    }
+	}
+    }
+  return font_list;
+}
+
 /* Return a list of at most MAXNAMES font specs matching the one in
    PATTERN.  Cache matching fonts for patterns in
    dpyinfo->name_list_element to avoid looking them up again by
@@ -5847,11 +6299,7 @@
               int size,
               int maxnames)
 {
-  char *ptnstr;
   Lisp_Object newlist = Qnil, tem, key;
-  int n_fonts = 0;
-  int i;
-  struct gcpro gcpro1, gcpro2;
   struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
@@ -5870,27 +6318,10 @@
 	}
     }
 
-  ptnstr = SDATA (pattern);
-
-  GCPRO2 (pattern, newlist);
-
-  /* Scan and matching bitmap fonts.  */
-  for (i = 0; i < font_name_count; i++)
-    {
-      if (mac_font_pattern_match (font_name_table[i], ptnstr))
-        {
-          newlist = Fcons (build_string (font_name_table[i]), newlist);
-
-          n_fonts++;
-          if (maxnames > 0 && n_fonts >= maxnames)
-            break;
-        }
-    }
+  newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
 
   /* MAC_TODO: add code for matching outline fonts here */
 
-  UNGCPRO;
-
   if (dpyinfo)
     {
       XSETCDR (dpyinfo->name_list_element,
@@ -6050,14 +6481,12 @@
     name = fontname;
   else
     {
-      for (i = 0; i < font_name_count; i++)
-        if (mac_font_pattern_match (font_name_table[i], fontname))
-          break;
-
-      if (i >= font_name_count)
-        return NULL;
-
-      name = font_name_table[i];
+      Lisp_Object matched_fonts;
+
+      matched_fonts = mac_do_list_fonts (fontname, 1);
+      if (NILP (matched_fonts))
+	return NULL;
+      name = SDATA (XCAR (matched_fonts));
     }
 
   GetPort (&port);  /* save the current font number used */
@@ -6179,7 +6608,8 @@
         for (c = 0x20; c <= 0xff; c++)
           {
             font->per_char[c - 0x20] = font->max_bounds;
-            font->per_char[c - 0x20].width = CharWidth (c);
+            font->per_char[c - 0x20].width =
+	      font->per_char[c - 0x20].rbearing = CharWidth (c);
           }
       }
     }
@@ -7833,14 +8263,32 @@
 		    }
 		  else
 	            {
-	              bufp->kind = MOUSE_CLICK_EVENT;
+		      Lisp_Object window;
+		      
+		      bufp->kind = MOUSE_CLICK_EVENT;
 		      XSETFRAME (bufp->frame_or_window, mwp->mFP);
 		      if (er.what == mouseDown)
-		        mouse_tracking_in_progress
+			mouse_tracking_in_progress
 			  = mouse_tracking_mouse_movement;
 		      else
-		        mouse_tracking_in_progress = mouse_tracking_none;
-	            }
+			mouse_tracking_in_progress = mouse_tracking_none;
+		      window = window_from_coordinates (mwp->mFP, bufp->x, bufp->y, 0, 0, 0, 1);
+		      
+		      if (EQ (window, mwp->mFP->tool_bar_window))
+			{
+			  if (er.what == mouseDown)
+			    handle_tool_bar_click (mwp->mFP, bufp->x, bufp->y, 1, 0);
+			  else
+			    handle_tool_bar_click (mwp->mFP, bufp->x, bufp->y, 0,
+#if USE_CARBON_EVENTS
+						   mac_event_to_emacs_modifiers (eventRef)
+#else
+						   er.modifiers
+#endif
+						   );
+			  break;
+			}
+		    }
 
 #if USE_CARBON_EVENTS
 		  bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
@@ -8352,12 +8800,16 @@
   dpyinfo->reference_count = 0;
   dpyinfo->resx = 75.0;
   dpyinfo->resy = 75.0;
-  dpyinfo->n_planes = 1;
-  dpyinfo->n_cbits = 16;
+  dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
+  for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
+    if (HasDepth (main_device_handle, dpyinfo->n_planes,
+		  gdDevType, dpyinfo->color_p))
+      break;
   dpyinfo->height = (**main_device_handle).gdRect.bottom;
   dpyinfo->width = (**main_device_handle).gdRect.right;
   dpyinfo->grabbed = 0;
   dpyinfo->root_window = NULL;
+  dpyinfo->image_cache = make_image_cache ();
 
   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
@@ -8697,6 +9149,18 @@
   Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
   staticpro (&Qmac_ready_for_drag_n_drop);
 
+  Qbig5 = intern ("big5");
+  staticpro (&Qbig5);
+
+  Qcn_gb = intern ("cn-gb");
+  staticpro (&Qcn_gb);
+
+  Qsjis = intern ("sjis");
+  staticpro (&Qsjis);
+
+  Qeuc_kr = intern ("euc-kr");
+  staticpro (&Qeuc_kr);
+
   DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
     doc: /* *Non-nil means autoselect window with mouse pointer.  */);
   x_autoselect_window_p = 0;
--- a/src/macterm.h	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/macterm.h	Sat Feb 28 01:33:17 2004 +0000
@@ -23,45 +23,26 @@
 #include "macgui.h"
 #include "frame.h"
 
-/* Include Carbon.h to define Cursor and Rect.  */
-#ifdef HAVE_CARBON
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
-#endif /* MAC_OSX */
-
 #define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
 
 #define RED_FROM_ULONG(color) ((color) >> 16)
 #define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
 #define BLUE_FROM_ULONG(color) ((color) & 0xff)
 
+/* Do not change `* 0x101' in the following lines to `<< 8'.  If
+   changed, image masks in 1-bit depth will not work. */
+#define RED16_FROM_ULONG(color) (RED_FROM_ULONG(color) * 0x101)
+#define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG(color) * 0x101)
+#define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG(color) * 0x101)
+
 #define BLACK_PIX_DEFAULT(f) RGB_TO_ULONG(0,0,0)
 #define WHITE_PIX_DEFAULT(f) RGB_TO_ULONG(255,255,255)
 
+/* A black pixel in a mask bitmap/pixmap means ``draw a source
+   pixel''.  A white pixel means ``retain the current pixel''. */
+#define PIX_MASK_DRAW(f) BLACK_PIX_DEFAULT(f)
+#define PIX_MASK_RETAIN(f) WHITE_PIX_DEFAULT(f)
+
 #define FONT_WIDTH(f)   ((f)->max_bounds.width)
 #define FONT_HEIGHT(f)  ((f)->ascent + (f)->descent)
 #define FONT_BASE(f)    ((f)->ascent)
@@ -101,8 +82,13 @@
   /* Number of planes on this screen.  */
   int n_planes;
 
+  /* Whether the screen supports color */ 
+  int color_p;
+
+#if 0
   /* Number of bits per pixel on this screen.  */
   int n_cbits;
+#endif
 
   /* Dimensions of this screen.  */
   int height, width;
--- a/src/s/darwin.h	Sat Feb 28 01:23:39 2004 +0000
+++ b/src/s/darwin.h	Sat Feb 28 01:33:17 2004 +0000
@@ -247,7 +247,7 @@
    page) to leave room at the end of the header for adding load
    commands.  Needed for dumping.  0x690 is the total size of 30
    segment load commands (at 56 each).  */
-#define LD_SWITCH_SYSTEM_TEMACS -prebind -framework Carbon -lstdc++ -Xlinker -headerpad -Xlinker 690
+#define LD_SWITCH_SYSTEM_TEMACS -prebind -framework Carbon -framework QuickTime -lstdc++ -Xlinker -headerpad -Xlinker 690
 
 #define C_SWITCH_SYSTEM_TEMACS -Dtemacs