*** empty log message ***
[emacs/old-mirror.git] / src / macfns.c
blob1b854489480758e2b4c4bce231f4035d2aba83ad
1 /* Graphical user interface functions for Mac OS.
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
25 #include <signal.h>
26 #include <stdio.h>
27 #include <math.h>
28 #include <limits.h>
29 #include <errno.h>
31 #include "lisp.h"
32 #include "charset.h"
33 #include "macterm.h"
34 #include "frame.h"
35 #include "window.h"
36 #include "buffer.h"
37 #include "dispextern.h"
38 #include "fontset.h"
39 #include "intervals.h"
40 #include "keyboard.h"
41 #include "blockinput.h"
42 #include "epaths.h"
43 #include "termhooks.h"
44 #include "coding.h"
45 #include "ccl.h"
46 #include "systime.h"
48 /* #include "bitmaps/gray.xbm" */
49 #define gray_width 2
50 #define gray_height 2
51 static unsigned char gray_bits[] = {
52 0x01, 0x02};
54 /*#include <commdlg.h>
55 #include <shellapi.h>*/
56 #include <ctype.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #ifndef MAC_OSX
63 #include <alloca.h>
64 #endif
66 #ifdef MAC_OSX
67 #include <QuickTime/QuickTime.h>
68 #else /* not MAC_OSX */
69 #include <Windows.h>
70 #include <Gestalt.h>
71 #include <TextUtils.h>
72 #endif /* not MAC_OSX */
74 /*extern void free_frame_menubar ();
75 extern double atof ();
76 extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
77 extern int quit_char;*/
79 extern char *lispy_function_keys[];
81 /* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
82 it, and including `bitmaps/gray' more than once is a problem when
83 config.h defines `static' as an empty replacement string. */
85 int gray_bitmap_width = gray_width;
86 int gray_bitmap_height = gray_height;
87 unsigned char *gray_bitmap_bits = gray_bits;
89 /* Non-zero means we're allowed to display an hourglass cursor. */
91 int display_hourglass_p;
93 /* The background and shape of the mouse pointer, and shape when not
94 over text or in the modeline. */
96 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
97 Lisp_Object Vx_hourglass_pointer_shape;
99 /* The shape when over mouse-sensitive text. */
101 Lisp_Object Vx_sensitive_text_pointer_shape;
103 /* If non-nil, the pointer shape to indicate that windows can be
104 dragged horizontally. */
106 Lisp_Object Vx_window_horizontal_drag_shape;
108 /* Color of chars displayed in cursor box. */
110 Lisp_Object Vx_cursor_fore_pixel;
112 /* Nonzero if using Windows. */
114 static int mac_in_use;
116 /* Non nil if no window manager is in use. */
118 Lisp_Object Vx_no_window_manager;
120 /* Search path for bitmap files. */
122 Lisp_Object Vx_bitmap_file_path;
124 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
126 Lisp_Object Vx_pixel_size_width_font_regexp;
128 /* Evaluate this expression to rebuild the section of syms_of_macfns
129 that initializes and staticpros the symbols declared below. Note
130 that Emacs 18 has a bug that keeps C-x C-e from being able to
131 evaluate this expression.
133 (progn
134 ;; Accumulate a list of the symbols we want to initialize from the
135 ;; declarations at the top of the file.
136 (goto-char (point-min))
137 (search-forward "/\*&&& symbols declared here &&&*\/\n")
138 (let (symbol-list)
139 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
140 (setq symbol-list
141 (cons (buffer-substring (match-beginning 1) (match-end 1))
142 symbol-list))
143 (forward-line 1))
144 (setq symbol-list (nreverse symbol-list))
145 ;; Delete the section of syms_of_... where we initialize the symbols.
146 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
147 (let ((start (point)))
148 (while (looking-at "^ Q")
149 (forward-line 2))
150 (kill-region start (point)))
151 ;; Write a new symbol initialization section.
152 (while symbol-list
153 (insert (format " %s = intern (\"" (car symbol-list)))
154 (let ((start (point)))
155 (insert (substring (car symbol-list) 1))
156 (subst-char-in-region start (point) ?_ ?-))
157 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
158 (setq symbol-list (cdr symbol-list)))))
162 /*&&& symbols declared here &&&*/
163 Lisp_Object Qnone;
164 Lisp_Object Qsuppress_icon;
165 Lisp_Object Qundefined_color;
166 Lisp_Object Qcenter;
167 Lisp_Object Qcancel_timer;
168 Lisp_Object Qhyper;
169 Lisp_Object Qsuper;
170 Lisp_Object Qmeta;
171 Lisp_Object Qalt;
172 Lisp_Object Qctrl;
173 Lisp_Object Qcontrol;
174 Lisp_Object Qshift;
176 extern Lisp_Object Vwindow_system_version;
178 extern int mac_initialized;
180 /* Functions in macterm.c. */
181 extern void x_set_window_size (struct frame *, int, int, int);
182 extern void x_make_frame_visible (struct frame *);
183 extern struct mac_display_info *mac_term_init (Lisp_Object, char *, char *);
184 extern struct font_info *x_get_font_info (FRAME_PTR, int);
185 extern struct font_info *x_load_font (struct frame *, char *, int);
186 extern void x_find_ccl_program (struct font_info *);
187 extern struct font_info *x_query_font (struct frame *, char *);
188 extern void mac_initialize ();
189 extern Pixmap XCreatePixmap (Display *, WindowPtr, unsigned int, unsigned int, unsigned int);
190 extern Pixmap XCreatePixmapFromBitmapData (Display *, WindowPtr, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
191 extern void XFreePixmap (Display *, Pixmap);
192 extern void XSetForeground (Display *, GC, unsigned long);
193 extern void mac_draw_line_to_pixmap (Display *, Pixmap, GC, int, int, int, int);
196 /* compare two strings ignoring case */
198 static int
199 stricmp (const char *s, const char *t)
201 for ( ; tolower (*s) == tolower (*t); s++, t++)
202 if (*s == '\0')
203 return 0;
204 return tolower (*s) - tolower (*t);
207 /* compare two strings up to n characters, ignoring case */
209 static int
210 strnicmp (const char *s, const char *t, unsigned int n)
212 for ( ; n-- > 0 && tolower (*s) == tolower (*t); s++, t++)
213 if (*s == '\0')
214 return 0;
215 return n == 0 ? 0 : tolower (*s) - tolower (*t);
219 /* Error if we are not running on Mac OS. */
221 void
222 check_mac ()
224 if (! mac_in_use)
225 error ("Mac OS not in use or not initialized");
228 /* Nonzero if we can use mouse menus.
229 You should not call this unless HAVE_MENUS is defined. */
232 have_menus_p ()
234 return mac_in_use;
237 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
238 and checking validity for Mac. */
240 FRAME_PTR
241 check_x_frame (frame)
242 Lisp_Object frame;
244 FRAME_PTR f;
246 if (NILP (frame))
247 frame = selected_frame;
248 CHECK_LIVE_FRAME (frame);
249 f = XFRAME (frame);
250 if (! FRAME_MAC_P (f))
251 error ("non-mac frame used");
252 return f;
255 /* Let the user specify a display with a frame.
256 nil stands for the selected frame--or, if that is not a mac frame,
257 the first display on the list. */
259 struct mac_display_info *
260 check_x_display_info (frame)
261 Lisp_Object frame;
263 if (!mac_initialized)
265 mac_initialize ();
266 mac_initialized = 1;
269 if (NILP (frame))
271 struct frame *sf = XFRAME (selected_frame);
273 if (FRAME_MAC_P (sf) && FRAME_LIVE_P (sf))
274 return FRAME_MAC_DISPLAY_INFO (sf);
275 else
276 return &one_mac_display_info;
278 else if (STRINGP (frame))
279 return x_display_info_for_name (frame);
280 else
282 FRAME_PTR f;
284 CHECK_LIVE_FRAME (frame);
285 f = XFRAME (frame);
286 if (! FRAME_MAC_P (f))
287 error ("non-mac frame used");
288 return FRAME_MAC_DISPLAY_INFO (f);
292 /* Return the Emacs frame-object corresponding to a mac window.
293 It could be the frame's main window or an icon window. */
295 /* This function can be called during GC, so use GC_xxx type test macros. */
297 struct frame *
298 x_window_to_frame (dpyinfo, wdesc)
299 struct mac_display_info *dpyinfo;
300 WindowPtr wdesc;
302 Lisp_Object tail, frame;
303 struct frame *f;
305 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
307 frame = XCAR (tail);
308 if (!GC_FRAMEP (frame))
309 continue;
310 f = XFRAME (frame);
311 if (!FRAME_W32_P (f) || FRAME_MAC_DISPLAY_INFO (f) != dpyinfo)
312 continue;
313 /*if (f->output_data.w32->hourglass_window == wdesc)
314 return f;*/
316 /* MAC_TODO: Check tooltips when supported. */
317 if (FRAME_MAC_WINDOW (f) == wdesc)
318 return f;
320 return 0;
325 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
326 id, which is just an int that this section returns. Bitmaps are
327 reference counted so they can be shared among frames.
329 Bitmap indices are guaranteed to be > 0, so a negative number can
330 be used to indicate no bitmap.
332 If you use x_create_bitmap_from_data, then you must keep track of
333 the bitmaps yourself. That is, creating a bitmap from the same
334 data more than once will not be caught. */
337 /* Functions to access the contents of a bitmap, given an id. */
340 x_bitmap_height (f, id)
341 FRAME_PTR f;
342 int id;
344 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].height;
348 x_bitmap_width (f, id)
349 FRAME_PTR f;
350 int id;
352 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].width;
355 #if 0 /* MAC_TODO : not used anywhere (?) */
357 x_bitmap_pixmap (f, id)
358 FRAME_PTR f;
359 int id;
361 return (int) FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
363 #endif
365 /* Allocate a new bitmap record. Returns index of new record. */
367 static int
368 x_allocate_bitmap_record (f)
369 FRAME_PTR f;
371 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
372 int i;
374 if (dpyinfo->bitmaps == NULL)
376 dpyinfo->bitmaps_size = 10;
377 dpyinfo->bitmaps = (struct mac_bitmap_record *)
378 xmalloc (dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
379 dpyinfo->bitmaps_last = 1;
380 return 1;
383 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
384 return ++dpyinfo->bitmaps_last;
386 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
387 if (dpyinfo->bitmaps[i].refcount == 0)
388 return i + 1;
390 dpyinfo->bitmaps_size *= 2;
391 dpyinfo->bitmaps = (struct mac_bitmap_record *)
392 xrealloc (dpyinfo->bitmaps,
393 dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
394 return ++dpyinfo->bitmaps_last;
397 /* Add one reference to the reference count of the bitmap with id
398 ID. */
400 void
401 x_reference_bitmap (f, id)
402 FRAME_PTR f;
403 int id;
405 ++FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
408 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
409 BITS. */
412 x_create_bitmap_from_data (f, bits, width, height)
413 struct frame *f;
414 char *bits;
415 unsigned int width, height;
417 struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
418 int id;
420 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
422 id = x_allocate_bitmap_record (f);
424 if (width % 16 != 0)
425 return -1;
427 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
428 if (! dpyinfo->bitmaps[id - 1].bitmap_data)
429 return -1;
431 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
433 dpyinfo->bitmaps[id - 1].refcount = 1;
434 dpyinfo->bitmaps[id - 1].height = height;
435 dpyinfo->bitmaps[id - 1].width = width;
437 return id;
440 /* Create bitmap from file FILE for frame F. */
443 x_create_bitmap_from_file (f, file)
444 struct frame *f;
445 Lisp_Object file;
447 return -1;
448 #if 0 /* MAC_TODO : bitmap support */
449 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
450 unsigned int width, height;
451 HBITMAP bitmap;
452 int xhot, yhot, result, id;
453 Lisp_Object found;
454 int fd;
455 char *filename;
456 HINSTANCE hinst;
458 /* Look for an existing bitmap with the same name. */
459 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
461 if (dpyinfo->bitmaps[id].refcount
462 && dpyinfo->bitmaps[id].file
463 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
465 ++dpyinfo->bitmaps[id].refcount;
466 return id + 1;
470 /* Search bitmap-file-path for the file, if appropriate. */
471 fd = openp (Vx_bitmap_file_path, file, "", &found, Qnil);
472 if (fd < 0)
473 return -1;
474 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
475 if (fd == 0)
476 return -1;
477 emacs_close (fd);
479 filename = (char *) SDATA (found);
481 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
483 if (hinst == NULL)
484 return -1;
487 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
488 filename, &width, &height, &bitmap, &xhot, &yhot);
489 if (result != BitmapSuccess)
490 return -1;
492 id = x_allocate_bitmap_record (f);
493 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
494 dpyinfo->bitmaps[id - 1].refcount = 1;
495 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SCHARS (file) + 1);
496 dpyinfo->bitmaps[id - 1].depth = 1;
497 dpyinfo->bitmaps[id - 1].height = height;
498 dpyinfo->bitmaps[id - 1].width = width;
499 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
501 return id;
502 #endif /* MAC_TODO */
505 /* Remove reference to bitmap with id number ID. */
507 void
508 x_destroy_bitmap (f, id)
509 FRAME_PTR f;
510 int id;
512 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
514 if (id > 0)
516 --dpyinfo->bitmaps[id - 1].refcount;
517 if (dpyinfo->bitmaps[id - 1].refcount == 0)
519 BLOCK_INPUT;
520 dpyinfo->bitmaps[id - 1].bitmap_data = NULL;
521 UNBLOCK_INPUT;
526 /* Free all the bitmaps for the display specified by DPYINFO. */
528 static void
529 x_destroy_all_bitmaps (dpyinfo)
530 struct mac_display_info *dpyinfo;
532 int i;
533 for (i = 0; i < dpyinfo->bitmaps_last; i++)
534 if (dpyinfo->bitmaps[i].refcount > 0)
535 xfree (dpyinfo->bitmaps[i].bitmap_data);
536 dpyinfo->bitmaps_last = 0;
541 /* Mac equivalent of XImage. */
542 typedef Pixmap XImagePtr;
543 #define ZPixmap 0 /* arbitrary */
545 static XImagePtr
546 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
547 Display *display; /* not used */
548 Pixmap pixmap;
549 int x, y; /* not used */
550 unsigned int width, height; /* not used */
551 unsigned long plane_mask; /* not used */
552 int format; /* not used */
554 #if GLYPH_DEBUG
555 xassert (x == 0 && y == 0);
557 Rect ri, rp;
558 SetRect (&ri, 0, 0, width, height);
559 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
561 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
562 #endif
564 LockPixels (GetGWorldPixMap (pixmap));
566 return pixmap;
569 static void
570 XPutPixel (ximage, x, y, pixel)
571 XImagePtr ximage;
572 int x, y;
573 unsigned long pixel;
575 RGBColor color;
577 SetGWorld (ximage, NULL);
579 color.red = RED16_FROM_ULONG (pixel);
580 color.green = GREEN16_FROM_ULONG (pixel);
581 color.blue = BLUE16_FROM_ULONG (pixel);
582 SetCPixel (x, y, &color);
585 static unsigned long
586 XGetPixel (ximage, x, y)
587 XImagePtr ximage;
588 int x, y;
590 RGBColor color;
592 SetGWorld (ximage, NULL);
594 GetCPixel (x, y, &color);
595 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
598 static void
599 XDestroyImage (ximg)
600 XImagePtr ximg;
602 UnlockPixels (GetGWorldPixMap (ximg));
607 /* Useful functions defined in the section
608 `Image type independent image structures' below. */
610 static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
611 unsigned long height));
613 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
614 int depth, XImagePtr *ximg,
615 Pixmap *pixmap));
617 static void x_destroy_x_image P_ ((XImagePtr ximg));
619 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
620 static void x_disable_image P_ ((struct frame *, struct image *));
622 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
623 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
624 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
625 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
626 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
627 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
628 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
629 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
630 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
631 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
632 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
633 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
634 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
635 Lisp_Object));
636 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
637 Lisp_Object));
638 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
639 Lisp_Object,
640 Lisp_Object,
641 char *, char *,
642 int));
643 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
644 Lisp_Object));
645 static void init_color_table P_ ((void));
646 static void free_color_table P_ ((void));
647 static unsigned long *colors_in_color_table P_ ((int *n));
648 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
649 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
651 /* Store the screen positions of frame F into XPTR and YPTR.
652 These are the positions of the containing window manager window,
653 not Emacs's own window. */
655 void
656 x_real_positions (f, xptr, yptr)
657 FRAME_PTR f;
658 int *xptr, *yptr;
660 Point pt;
661 GrafPtr oldport;
663 #ifdef TARGET_API_MAC_CARBON
665 Rect r;
667 GetWindowPortBounds (f->output_data.mac->mWP, &r);
668 SetPt (&pt, r.left, r.top);
670 #else /* not TARGET_API_MAC_CARBON */
671 SetPt (&pt,
672 f->output_data.mac->mWP->portRect.left,
673 f->output_data.mac->mWP->portRect.top);
674 #endif /* not TARGET_API_MAC_CARBON */
675 GetPort (&oldport);
676 LocalToGlobal (&pt);
677 SetPort (oldport);
679 /* MAC has no frame pixel diff. */
680 f->x_pixels_diff = 0;
681 f->y_pixels_diff = 0;
683 *xptr = pt.h;
684 *yptr = pt.v;
688 /* The default colors for the Mac color map */
689 typedef struct colormap_t
691 unsigned long color;
692 char *name;
693 } colormap_t;
695 colormap_t mac_color_map[] =
697 { RGB_TO_ULONG(255, 250, 250), "snow" },
698 { RGB_TO_ULONG(248, 248, 255), "ghost white" },
699 { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
700 { RGB_TO_ULONG(245, 245, 245), "white smoke" },
701 { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
702 { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
703 { RGB_TO_ULONG(255, 250, 240), "floral white" },
704 { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
705 { RGB_TO_ULONG(253, 245, 230), "old lace" },
706 { RGB_TO_ULONG(253, 245, 230), "OldLace" },
707 { RGB_TO_ULONG(250, 240, 230), "linen" },
708 { RGB_TO_ULONG(250, 235, 215), "antique white" },
709 { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
710 { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
711 { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
712 { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
713 { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
714 { RGB_TO_ULONG(255, 228, 196), "bisque" },
715 { RGB_TO_ULONG(255, 218, 185), "peach puff" },
716 { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
717 { RGB_TO_ULONG(255, 222, 173), "navajo white" },
718 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
719 { RGB_TO_ULONG(255, 228, 181), "moccasin" },
720 { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
721 { RGB_TO_ULONG(255, 255, 240), "ivory" },
722 { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
723 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
724 { RGB_TO_ULONG(255, 245, 238), "seashell" },
725 { RGB_TO_ULONG(240, 255, 240), "honeydew" },
726 { RGB_TO_ULONG(245, 255, 250), "mint cream" },
727 { RGB_TO_ULONG(245, 255, 250), "MintCream" },
728 { RGB_TO_ULONG(240, 255, 255), "azure" },
729 { RGB_TO_ULONG(240, 248, 255), "alice blue" },
730 { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
731 { RGB_TO_ULONG(230, 230, 250), "lavender" },
732 { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
733 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
734 { RGB_TO_ULONG(255, 228, 225), "misty rose" },
735 { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
736 { RGB_TO_ULONG(255, 255, 255), "white" },
737 { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
738 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
739 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
740 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
741 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
742 { RGB_TO_ULONG(105, 105, 105), "dim gray" },
743 { RGB_TO_ULONG(105, 105, 105), "DimGray" },
744 { RGB_TO_ULONG(105, 105, 105), "dim grey" },
745 { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
746 { RGB_TO_ULONG(112, 128, 144), "slate gray" },
747 { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
748 { RGB_TO_ULONG(112, 128, 144), "slate grey" },
749 { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
750 { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
751 { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
752 { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
753 { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
754 { RGB_TO_ULONG(190, 190, 190), "gray" },
755 { RGB_TO_ULONG(190, 190, 190), "grey" },
756 { RGB_TO_ULONG(211, 211, 211), "light grey" },
757 { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
758 { RGB_TO_ULONG(211, 211, 211), "light gray" },
759 { RGB_TO_ULONG(211, 211, 211), "LightGray" },
760 { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
761 { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
762 { RGB_TO_ULONG(0 , 0 , 128), "navy" },
763 { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
764 { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
765 { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
766 { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
767 { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
768 { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
769 { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
770 { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
771 { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
772 { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
773 { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
774 { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
775 { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
776 { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
777 { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
778 { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
779 { RGB_TO_ULONG(0 , 0 , 255), "blue" },
780 { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
781 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
782 { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
783 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
784 { RGB_TO_ULONG(135, 206, 235), "sky blue" },
785 { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
786 { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
787 { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
788 { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
789 { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
790 { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
791 { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
792 { RGB_TO_ULONG(173, 216, 230), "light blue" },
793 { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
794 { RGB_TO_ULONG(176, 224, 230), "powder blue" },
795 { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
796 { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
797 { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
798 { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
799 { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
800 { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
801 { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
802 { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
803 { RGB_TO_ULONG(0 , 255, 255), "cyan" },
804 { RGB_TO_ULONG(224, 255, 255), "light cyan" },
805 { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
806 { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
807 { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
808 { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
809 { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
810 { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
811 { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
812 { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
813 { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
814 { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
815 { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
816 { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
817 { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
818 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
819 { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
820 { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
821 { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
822 { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
823 { RGB_TO_ULONG(152, 251, 152), "pale green" },
824 { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
825 { RGB_TO_ULONG(0 , 255, 127), "spring green" },
826 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
827 { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
828 { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
829 { RGB_TO_ULONG(0 , 255, 0 ), "green" },
830 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
831 { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
832 { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
833 { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
834 { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
835 { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
836 { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
837 { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
838 { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
839 { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
840 { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
841 { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
842 { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
843 { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
844 { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
845 { RGB_TO_ULONG(240, 230, 140), "khaki" },
846 { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
847 { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
848 { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
849 { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
850 { RGB_TO_ULONG(255, 255, 224), "light yellow" },
851 { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
852 { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
853 { RGB_TO_ULONG(255, 215, 0 ), "gold" },
854 { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
855 { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
856 { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
857 { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
858 { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
859 { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
860 { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
861 { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
862 { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
863 { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
864 { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
865 { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
866 { RGB_TO_ULONG(205, 133, 63 ), "peru" },
867 { RGB_TO_ULONG(222, 184, 135), "burlywood" },
868 { RGB_TO_ULONG(245, 245, 220), "beige" },
869 { RGB_TO_ULONG(245, 222, 179), "wheat" },
870 { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
871 { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
872 { RGB_TO_ULONG(210, 180, 140), "tan" },
873 { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
874 { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
875 { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
876 { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
877 { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
878 { RGB_TO_ULONG(250, 128, 114), "salmon" },
879 { RGB_TO_ULONG(255, 160, 122), "light salmon" },
880 { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
881 { RGB_TO_ULONG(255, 165, 0 ), "orange" },
882 { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
883 { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
884 { RGB_TO_ULONG(255, 127, 80 ), "coral" },
885 { RGB_TO_ULONG(240, 128, 128), "light coral" },
886 { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
887 { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
888 { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
889 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
890 { RGB_TO_ULONG(255, 0 , 0 ), "red" },
891 { RGB_TO_ULONG(255, 105, 180), "hot pink" },
892 { RGB_TO_ULONG(255, 105, 180), "HotPink" },
893 { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
894 { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
895 { RGB_TO_ULONG(255, 192, 203), "pink" },
896 { RGB_TO_ULONG(255, 182, 193), "light pink" },
897 { RGB_TO_ULONG(255, 182, 193), "LightPink" },
898 { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
899 { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
900 { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
901 { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
902 { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
903 { RGB_TO_ULONG(208, 32 , 144), "violet red" },
904 { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
905 { RGB_TO_ULONG(255, 0 , 255), "magenta" },
906 { RGB_TO_ULONG(238, 130, 238), "violet" },
907 { RGB_TO_ULONG(221, 160, 221), "plum" },
908 { RGB_TO_ULONG(218, 112, 214), "orchid" },
909 { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
910 { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
911 { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
912 { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
913 { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
914 { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
915 { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
916 { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
917 { RGB_TO_ULONG(160, 32 , 240), "purple" },
918 { RGB_TO_ULONG(147, 112, 219), "medium purple" },
919 { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
920 { RGB_TO_ULONG(216, 191, 216), "thistle" },
921 { RGB_TO_ULONG(255, 250, 250), "snow1" },
922 { RGB_TO_ULONG(238, 233, 233), "snow2" },
923 { RGB_TO_ULONG(205, 201, 201), "snow3" },
924 { RGB_TO_ULONG(139, 137, 137), "snow4" },
925 { RGB_TO_ULONG(255, 245, 238), "seashell1" },
926 { RGB_TO_ULONG(238, 229, 222), "seashell2" },
927 { RGB_TO_ULONG(205, 197, 191), "seashell3" },
928 { RGB_TO_ULONG(139, 134, 130), "seashell4" },
929 { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
930 { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
931 { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
932 { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
933 { RGB_TO_ULONG(255, 228, 196), "bisque1" },
934 { RGB_TO_ULONG(238, 213, 183), "bisque2" },
935 { RGB_TO_ULONG(205, 183, 158), "bisque3" },
936 { RGB_TO_ULONG(139, 125, 107), "bisque4" },
937 { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
938 { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
939 { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
940 { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
941 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
942 { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
943 { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
944 { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
945 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
946 { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
947 { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
948 { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
949 { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
950 { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
951 { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
952 { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
953 { RGB_TO_ULONG(255, 255, 240), "ivory1" },
954 { RGB_TO_ULONG(238, 238, 224), "ivory2" },
955 { RGB_TO_ULONG(205, 205, 193), "ivory3" },
956 { RGB_TO_ULONG(139, 139, 131), "ivory4" },
957 { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
958 { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
959 { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
960 { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
961 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
962 { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
963 { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
964 { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
965 { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
966 { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
967 { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
968 { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
969 { RGB_TO_ULONG(240, 255, 255), "azure1" },
970 { RGB_TO_ULONG(224, 238, 238), "azure2" },
971 { RGB_TO_ULONG(193, 205, 205), "azure3" },
972 { RGB_TO_ULONG(131, 139, 139), "azure4" },
973 { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
974 { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
975 { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
976 { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
977 { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
978 { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
979 { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
980 { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
981 { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
982 { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
983 { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
984 { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
985 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
986 { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
987 { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
988 { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
989 { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
990 { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
991 { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
992 { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
993 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
994 { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
995 { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
996 { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
997 { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
998 { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
999 { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
1000 { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
1001 { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
1002 { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
1003 { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
1004 { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
1005 { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
1006 { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
1007 { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
1008 { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
1009 { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
1010 { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
1011 { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
1012 { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
1013 { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
1014 { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
1015 { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
1016 { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
1017 { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
1018 { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
1019 { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
1020 { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
1021 { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
1022 { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
1023 { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
1024 { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
1025 { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
1026 { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
1027 { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
1028 { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
1029 { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
1030 { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
1031 { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
1032 { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
1033 { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
1034 { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
1035 { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
1036 { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
1037 { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
1038 { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
1039 { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
1040 { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
1041 { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
1042 { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
1043 { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
1044 { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
1045 { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
1046 { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
1047 { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
1048 { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
1049 { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
1050 { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
1051 { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
1052 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
1053 { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
1054 { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
1055 { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
1056 { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
1057 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
1058 { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
1059 { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
1060 { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
1061 { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
1062 { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
1063 { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
1064 { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
1065 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
1066 { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
1067 { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
1068 { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
1069 { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
1070 { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
1071 { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
1072 { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
1073 { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
1074 { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
1075 { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
1076 { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
1077 { RGB_TO_ULONG(255, 246, 143), "khaki1" },
1078 { RGB_TO_ULONG(238, 230, 133), "khaki2" },
1079 { RGB_TO_ULONG(205, 198, 115), "khaki3" },
1080 { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
1081 { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
1082 { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
1083 { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
1084 { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
1085 { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
1086 { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
1087 { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
1088 { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
1089 { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
1090 { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
1091 { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
1092 { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
1093 { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
1094 { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
1095 { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
1096 { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
1097 { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
1098 { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
1099 { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
1100 { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
1101 { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
1102 { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
1103 { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
1104 { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
1105 { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
1106 { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
1107 { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
1108 { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
1109 { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
1110 { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
1111 { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
1112 { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
1113 { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
1114 { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
1115 { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
1116 { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
1117 { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
1118 { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
1119 { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
1120 { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
1121 { RGB_TO_ULONG(255, 231, 186), "wheat1" },
1122 { RGB_TO_ULONG(238, 216, 174), "wheat2" },
1123 { RGB_TO_ULONG(205, 186, 150), "wheat3" },
1124 { RGB_TO_ULONG(139, 126, 102), "wheat4" },
1125 { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
1126 { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
1127 { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
1128 { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
1129 { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
1130 { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
1131 { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
1132 { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
1133 { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
1134 { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
1135 { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
1136 { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
1137 { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
1138 { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
1139 { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
1140 { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
1141 { RGB_TO_ULONG(255, 140, 105), "salmon1" },
1142 { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
1143 { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
1144 { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
1145 { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
1146 { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
1147 { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
1148 { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
1149 { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
1150 { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
1151 { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
1152 { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
1153 { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
1154 { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
1155 { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
1156 { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
1157 { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
1158 { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
1159 { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
1160 { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
1161 { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
1162 { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
1163 { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
1164 { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
1165 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
1166 { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
1167 { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
1168 { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
1169 { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
1170 { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
1171 { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
1172 { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
1173 { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
1174 { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
1175 { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
1176 { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
1177 { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
1178 { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
1179 { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
1180 { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
1181 { RGB_TO_ULONG(255, 181, 197), "pink1" },
1182 { RGB_TO_ULONG(238, 169, 184), "pink2" },
1183 { RGB_TO_ULONG(205, 145, 158), "pink3" },
1184 { RGB_TO_ULONG(139, 99 , 108), "pink4" },
1185 { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
1186 { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
1187 { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
1188 { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
1189 { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
1190 { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
1191 { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
1192 { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
1193 { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
1194 { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
1195 { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
1196 { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
1197 { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
1198 { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
1199 { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
1200 { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
1201 { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
1202 { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
1203 { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
1204 { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
1205 { RGB_TO_ULONG(255, 131, 250), "orchid1" },
1206 { RGB_TO_ULONG(238, 122, 233), "orchid2" },
1207 { RGB_TO_ULONG(205, 105, 201), "orchid3" },
1208 { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
1209 { RGB_TO_ULONG(255, 187, 255), "plum1" },
1210 { RGB_TO_ULONG(238, 174, 238), "plum2" },
1211 { RGB_TO_ULONG(205, 150, 205), "plum3" },
1212 { RGB_TO_ULONG(139, 102, 139), "plum4" },
1213 { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
1214 { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
1215 { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
1216 { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
1217 { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
1218 { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
1219 { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
1220 { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
1221 { RGB_TO_ULONG(155, 48 , 255), "purple1" },
1222 { RGB_TO_ULONG(145, 44 , 238), "purple2" },
1223 { RGB_TO_ULONG(125, 38 , 205), "purple3" },
1224 { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
1225 { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
1226 { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
1227 { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
1228 { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
1229 { RGB_TO_ULONG(255, 225, 255), "thistle1" },
1230 { RGB_TO_ULONG(238, 210, 238), "thistle2" },
1231 { RGB_TO_ULONG(205, 181, 205), "thistle3" },
1232 { RGB_TO_ULONG(139, 123, 139), "thistle4" },
1233 { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
1234 { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
1235 { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
1236 { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
1237 { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
1238 { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
1239 { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
1240 { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
1241 { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
1242 { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
1243 { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
1244 { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
1245 { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
1246 { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
1247 { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
1248 { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
1249 { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
1250 { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
1251 { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
1252 { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
1253 { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
1254 { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
1255 { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
1256 { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
1257 { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
1258 { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
1259 { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
1260 { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
1261 { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
1262 { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
1263 { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
1264 { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
1265 { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
1266 { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
1267 { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
1268 { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
1269 { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
1270 { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
1271 { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
1272 { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
1273 { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
1274 { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
1275 { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
1276 { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
1277 { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
1278 { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
1279 { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
1280 { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
1281 { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
1282 { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
1283 { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
1284 { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
1285 { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
1286 { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
1287 { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
1288 { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
1289 { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
1290 { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
1291 { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
1292 { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
1293 { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
1294 { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
1295 { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
1296 { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
1297 { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
1298 { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
1299 { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
1300 { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
1301 { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
1302 { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
1303 { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
1304 { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
1305 { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
1306 { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
1307 { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
1308 { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
1309 { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
1310 { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
1311 { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
1312 { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
1313 { RGB_TO_ULONG(102, 102, 102), "gray40" },
1314 { RGB_TO_ULONG(102, 102, 102), "grey40" },
1315 { RGB_TO_ULONG(105, 105, 105), "gray41" },
1316 { RGB_TO_ULONG(105, 105, 105), "grey41" },
1317 { RGB_TO_ULONG(107, 107, 107), "gray42" },
1318 { RGB_TO_ULONG(107, 107, 107), "grey42" },
1319 { RGB_TO_ULONG(110, 110, 110), "gray43" },
1320 { RGB_TO_ULONG(110, 110, 110), "grey43" },
1321 { RGB_TO_ULONG(112, 112, 112), "gray44" },
1322 { RGB_TO_ULONG(112, 112, 112), "grey44" },
1323 { RGB_TO_ULONG(115, 115, 115), "gray45" },
1324 { RGB_TO_ULONG(115, 115, 115), "grey45" },
1325 { RGB_TO_ULONG(117, 117, 117), "gray46" },
1326 { RGB_TO_ULONG(117, 117, 117), "grey46" },
1327 { RGB_TO_ULONG(120, 120, 120), "gray47" },
1328 { RGB_TO_ULONG(120, 120, 120), "grey47" },
1329 { RGB_TO_ULONG(122, 122, 122), "gray48" },
1330 { RGB_TO_ULONG(122, 122, 122), "grey48" },
1331 { RGB_TO_ULONG(125, 125, 125), "gray49" },
1332 { RGB_TO_ULONG(125, 125, 125), "grey49" },
1333 { RGB_TO_ULONG(127, 127, 127), "gray50" },
1334 { RGB_TO_ULONG(127, 127, 127), "grey50" },
1335 { RGB_TO_ULONG(130, 130, 130), "gray51" },
1336 { RGB_TO_ULONG(130, 130, 130), "grey51" },
1337 { RGB_TO_ULONG(133, 133, 133), "gray52" },
1338 { RGB_TO_ULONG(133, 133, 133), "grey52" },
1339 { RGB_TO_ULONG(135, 135, 135), "gray53" },
1340 { RGB_TO_ULONG(135, 135, 135), "grey53" },
1341 { RGB_TO_ULONG(138, 138, 138), "gray54" },
1342 { RGB_TO_ULONG(138, 138, 138), "grey54" },
1343 { RGB_TO_ULONG(140, 140, 140), "gray55" },
1344 { RGB_TO_ULONG(140, 140, 140), "grey55" },
1345 { RGB_TO_ULONG(143, 143, 143), "gray56" },
1346 { RGB_TO_ULONG(143, 143, 143), "grey56" },
1347 { RGB_TO_ULONG(145, 145, 145), "gray57" },
1348 { RGB_TO_ULONG(145, 145, 145), "grey57" },
1349 { RGB_TO_ULONG(148, 148, 148), "gray58" },
1350 { RGB_TO_ULONG(148, 148, 148), "grey58" },
1351 { RGB_TO_ULONG(150, 150, 150), "gray59" },
1352 { RGB_TO_ULONG(150, 150, 150), "grey59" },
1353 { RGB_TO_ULONG(153, 153, 153), "gray60" },
1354 { RGB_TO_ULONG(153, 153, 153), "grey60" },
1355 { RGB_TO_ULONG(156, 156, 156), "gray61" },
1356 { RGB_TO_ULONG(156, 156, 156), "grey61" },
1357 { RGB_TO_ULONG(158, 158, 158), "gray62" },
1358 { RGB_TO_ULONG(158, 158, 158), "grey62" },
1359 { RGB_TO_ULONG(161, 161, 161), "gray63" },
1360 { RGB_TO_ULONG(161, 161, 161), "grey63" },
1361 { RGB_TO_ULONG(163, 163, 163), "gray64" },
1362 { RGB_TO_ULONG(163, 163, 163), "grey64" },
1363 { RGB_TO_ULONG(166, 166, 166), "gray65" },
1364 { RGB_TO_ULONG(166, 166, 166), "grey65" },
1365 { RGB_TO_ULONG(168, 168, 168), "gray66" },
1366 { RGB_TO_ULONG(168, 168, 168), "grey66" },
1367 { RGB_TO_ULONG(171, 171, 171), "gray67" },
1368 { RGB_TO_ULONG(171, 171, 171), "grey67" },
1369 { RGB_TO_ULONG(173, 173, 173), "gray68" },
1370 { RGB_TO_ULONG(173, 173, 173), "grey68" },
1371 { RGB_TO_ULONG(176, 176, 176), "gray69" },
1372 { RGB_TO_ULONG(176, 176, 176), "grey69" },
1373 { RGB_TO_ULONG(179, 179, 179), "gray70" },
1374 { RGB_TO_ULONG(179, 179, 179), "grey70" },
1375 { RGB_TO_ULONG(181, 181, 181), "gray71" },
1376 { RGB_TO_ULONG(181, 181, 181), "grey71" },
1377 { RGB_TO_ULONG(184, 184, 184), "gray72" },
1378 { RGB_TO_ULONG(184, 184, 184), "grey72" },
1379 { RGB_TO_ULONG(186, 186, 186), "gray73" },
1380 { RGB_TO_ULONG(186, 186, 186), "grey73" },
1381 { RGB_TO_ULONG(189, 189, 189), "gray74" },
1382 { RGB_TO_ULONG(189, 189, 189), "grey74" },
1383 { RGB_TO_ULONG(191, 191, 191), "gray75" },
1384 { RGB_TO_ULONG(191, 191, 191), "grey75" },
1385 { RGB_TO_ULONG(194, 194, 194), "gray76" },
1386 { RGB_TO_ULONG(194, 194, 194), "grey76" },
1387 { RGB_TO_ULONG(196, 196, 196), "gray77" },
1388 { RGB_TO_ULONG(196, 196, 196), "grey77" },
1389 { RGB_TO_ULONG(199, 199, 199), "gray78" },
1390 { RGB_TO_ULONG(199, 199, 199), "grey78" },
1391 { RGB_TO_ULONG(201, 201, 201), "gray79" },
1392 { RGB_TO_ULONG(201, 201, 201), "grey79" },
1393 { RGB_TO_ULONG(204, 204, 204), "gray80" },
1394 { RGB_TO_ULONG(204, 204, 204), "grey80" },
1395 { RGB_TO_ULONG(207, 207, 207), "gray81" },
1396 { RGB_TO_ULONG(207, 207, 207), "grey81" },
1397 { RGB_TO_ULONG(209, 209, 209), "gray82" },
1398 { RGB_TO_ULONG(209, 209, 209), "grey82" },
1399 { RGB_TO_ULONG(212, 212, 212), "gray83" },
1400 { RGB_TO_ULONG(212, 212, 212), "grey83" },
1401 { RGB_TO_ULONG(214, 214, 214), "gray84" },
1402 { RGB_TO_ULONG(214, 214, 214), "grey84" },
1403 { RGB_TO_ULONG(217, 217, 217), "gray85" },
1404 { RGB_TO_ULONG(217, 217, 217), "grey85" },
1405 { RGB_TO_ULONG(219, 219, 219), "gray86" },
1406 { RGB_TO_ULONG(219, 219, 219), "grey86" },
1407 { RGB_TO_ULONG(222, 222, 222), "gray87" },
1408 { RGB_TO_ULONG(222, 222, 222), "grey87" },
1409 { RGB_TO_ULONG(224, 224, 224), "gray88" },
1410 { RGB_TO_ULONG(224, 224, 224), "grey88" },
1411 { RGB_TO_ULONG(227, 227, 227), "gray89" },
1412 { RGB_TO_ULONG(227, 227, 227), "grey89" },
1413 { RGB_TO_ULONG(229, 229, 229), "gray90" },
1414 { RGB_TO_ULONG(229, 229, 229), "grey90" },
1415 { RGB_TO_ULONG(232, 232, 232), "gray91" },
1416 { RGB_TO_ULONG(232, 232, 232), "grey91" },
1417 { RGB_TO_ULONG(235, 235, 235), "gray92" },
1418 { RGB_TO_ULONG(235, 235, 235), "grey92" },
1419 { RGB_TO_ULONG(237, 237, 237), "gray93" },
1420 { RGB_TO_ULONG(237, 237, 237), "grey93" },
1421 { RGB_TO_ULONG(240, 240, 240), "gray94" },
1422 { RGB_TO_ULONG(240, 240, 240), "grey94" },
1423 { RGB_TO_ULONG(242, 242, 242), "gray95" },
1424 { RGB_TO_ULONG(242, 242, 242), "grey95" },
1425 { RGB_TO_ULONG(245, 245, 245), "gray96" },
1426 { RGB_TO_ULONG(245, 245, 245), "grey96" },
1427 { RGB_TO_ULONG(247, 247, 247), "gray97" },
1428 { RGB_TO_ULONG(247, 247, 247), "grey97" },
1429 { RGB_TO_ULONG(250, 250, 250), "gray98" },
1430 { RGB_TO_ULONG(250, 250, 250), "grey98" },
1431 { RGB_TO_ULONG(252, 252, 252), "gray99" },
1432 { RGB_TO_ULONG(252, 252, 252), "grey99" },
1433 { RGB_TO_ULONG(255, 255, 255), "gray100" },
1434 { RGB_TO_ULONG(255, 255, 255), "grey100" },
1435 { RGB_TO_ULONG(169, 169, 169), "dark grey" },
1436 { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
1437 { RGB_TO_ULONG(169, 169, 169), "dark gray" },
1438 { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
1439 { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
1440 { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
1441 { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
1442 { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
1443 { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
1444 { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
1445 { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
1446 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
1447 { RGB_TO_ULONG(144, 238, 144), "light green" },
1448 { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
1451 Lisp_Object
1452 mac_color_map_lookup (colorname)
1453 char *colorname;
1455 Lisp_Object ret = Qnil;
1456 int i;
1458 BLOCK_INPUT;
1460 for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
1461 if (stricmp (colorname, mac_color_map[i].name) == 0)
1463 ret = make_number (mac_color_map[i].color);
1464 break;
1467 UNBLOCK_INPUT;
1469 return ret;
1472 Lisp_Object
1473 x_to_mac_color (colorname)
1474 char * colorname;
1476 register Lisp_Object tail, ret = Qnil;
1478 BLOCK_INPUT;
1480 if (colorname[0] == '#')
1482 /* Could be an old-style RGB Device specification. */
1483 char *color;
1484 int size;
1485 color = colorname + 1;
1487 size = strlen(color);
1488 if (size == 3 || size == 6 || size == 9 || size == 12)
1490 unsigned long colorval;
1491 int i, pos;
1492 pos = 16;
1493 size /= 3;
1494 colorval = 0;
1496 for (i = 0; i < 3; i++)
1498 char *end;
1499 char t;
1500 unsigned long value;
1502 /* The check for 'x' in the following conditional takes into
1503 account the fact that strtol allows a "0x" in front of
1504 our numbers, and we don't. */
1505 if (!isxdigit(color[0]) || color[1] == 'x')
1506 break;
1507 t = color[size];
1508 color[size] = '\0';
1509 value = strtoul(color, &end, 16);
1510 color[size] = t;
1511 if (errno == ERANGE || end - color != size)
1512 break;
1513 switch (size)
1515 case 1:
1516 value = value * 0x10;
1517 break;
1518 case 2:
1519 break;
1520 case 3:
1521 value /= 0x10;
1522 break;
1523 case 4:
1524 value /= 0x100;
1525 break;
1527 colorval |= (value << pos);
1528 pos -= 8;
1529 if (i == 2)
1531 UNBLOCK_INPUT;
1532 return make_number (colorval);
1534 color = end;
1538 else if (strnicmp(colorname, "rgb:", 4) == 0)
1540 char *color;
1541 unsigned long colorval;
1542 int i, pos;
1543 pos = 0;
1545 colorval = 0;
1546 color = colorname + 4;
1547 for (i = 0; i < 3; i++)
1549 char *end;
1550 unsigned long value;
1552 /* The check for 'x' in the following conditional takes into
1553 account the fact that strtol allows a "0x" in front of
1554 our numbers, and we don't. */
1555 if (!isxdigit(color[0]) || color[1] == 'x')
1556 break;
1557 value = strtoul(color, &end, 16);
1558 if (errno == ERANGE)
1559 break;
1560 switch (end - color)
1562 case 1:
1563 value = value * 0x10 + value;
1564 break;
1565 case 2:
1566 break;
1567 case 3:
1568 value /= 0x10;
1569 break;
1570 case 4:
1571 value /= 0x100;
1572 break;
1573 default:
1574 value = ULONG_MAX;
1576 if (value == ULONG_MAX)
1577 break;
1578 colorval |= (value << pos);
1579 pos += 0x8;
1580 if (i == 2)
1582 if (*end != '\0')
1583 break;
1584 UNBLOCK_INPUT;
1585 return make_number (colorval);
1587 if (*end != '/')
1588 break;
1589 color = end + 1;
1592 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1594 /* This is an RGB Intensity specification. */
1595 char *color;
1596 unsigned long colorval;
1597 int i, pos;
1598 pos = 0;
1600 colorval = 0;
1601 color = colorname + 5;
1602 for (i = 0; i < 3; i++)
1604 char *end;
1605 double value;
1606 unsigned long val;
1608 value = strtod(color, &end);
1609 if (errno == ERANGE)
1610 break;
1611 if (value < 0.0 || value > 1.0)
1612 break;
1613 val = (unsigned long)(0x100 * value);
1614 /* We used 0x100 instead of 0xFF to give a continuous
1615 range between 0.0 and 1.0 inclusive. The next statement
1616 fixes the 1.0 case. */
1617 if (val == 0x100)
1618 val = 0xFF;
1619 colorval |= (val << pos);
1620 pos += 0x8;
1621 if (i == 2)
1623 if (*end != '\0')
1624 break;
1625 UNBLOCK_INPUT;
1626 return make_number (colorval);
1628 if (*end != '/')
1629 break;
1630 color = end + 1;
1634 ret = mac_color_map_lookup (colorname);
1636 UNBLOCK_INPUT;
1637 return ret;
1640 /* Gamma-correct COLOR on frame F. */
1642 void
1643 gamma_correct (f, color)
1644 struct frame *f;
1645 unsigned long *color;
1647 if (f->gamma)
1649 unsigned long red, green, blue;
1651 red = pow (RED_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
1652 green = pow (GREEN_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
1653 blue = pow (BLUE_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
1654 *color = RGB_TO_ULONG (red, green, blue);
1658 /* Decide if color named COLOR is valid for the display associated
1659 with the selected frame; if so, return the rgb values in COLOR_DEF.
1660 If ALLOC is nonzero, allocate a new colormap cell. */
1663 mac_defined_color (f, color, color_def, alloc)
1664 FRAME_PTR f;
1665 char *color;
1666 XColor *color_def;
1667 int alloc;
1669 register Lisp_Object tem;
1670 unsigned long mac_color_ref;
1672 tem = x_to_mac_color (color);
1674 if (!NILP (tem))
1676 if (f)
1678 /* Apply gamma correction. */
1679 mac_color_ref = XUINT (tem);
1680 gamma_correct (f, &mac_color_ref);
1681 XSETINT (tem, mac_color_ref);
1684 color_def->pixel = mac_color_ref;
1685 color_def->red = RED16_FROM_ULONG (mac_color_ref);
1686 color_def->green = GREEN16_FROM_ULONG (mac_color_ref);
1687 color_def->blue = BLUE16_FROM_ULONG (mac_color_ref);
1689 return 1;
1691 else
1693 return 0;
1697 /* Given a string ARG naming a color, compute a pixel value from it
1698 suitable for screen F.
1699 If F is not a color screen, return DEF (default) regardless of what
1700 ARG says. */
1703 x_decode_color (f, arg, def)
1704 FRAME_PTR f;
1705 Lisp_Object arg;
1706 int def;
1708 XColor cdef;
1710 CHECK_STRING (arg);
1712 if (strcmp (SDATA (arg), "black") == 0)
1713 return BLACK_PIX_DEFAULT (f);
1714 else if (strcmp (SDATA (arg), "white") == 0)
1715 return WHITE_PIX_DEFAULT (f);
1717 #if 0
1718 if (FRAME_MAC_DISPLAY_INFO (f)->n_planes) == 1)
1719 return def;
1720 #endif
1722 if (mac_defined_color (f, SDATA (arg), &cdef, 1))
1723 return cdef.pixel;
1725 /* defined_color failed; return an ultimate default. */
1726 return def;
1729 /* Functions called only from `x_set_frame_param'
1730 to set individual parameters.
1732 If FRAME_MAC_WINDOW (f) is 0,
1733 the frame is being created and its window does not exist yet.
1734 In that case, just record the parameter's new value
1735 in the standard place; do not attempt to change the window. */
1737 void
1738 x_set_foreground_color (f, arg, oldval)
1739 struct frame *f;
1740 Lisp_Object arg, oldval;
1742 unsigned long fg, old_fg;
1744 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1745 old_fg = FRAME_FOREGROUND_PIXEL (f);
1746 FRAME_FOREGROUND_PIXEL (f) = fg;
1748 if (FRAME_MAC_WINDOW (f) != 0)
1750 update_face_from_frame_parameter (f, Qforeground_color, arg);
1751 if (FRAME_VISIBLE_P (f))
1752 redraw_frame (f);
1756 void
1757 x_set_background_color (f, arg, oldval)
1758 struct frame *f;
1759 Lisp_Object arg, oldval;
1761 FRAME_BACKGROUND_PIXEL (f)
1762 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1764 if (FRAME_MAC_WINDOW (f) != 0)
1766 update_face_from_frame_parameter (f, Qbackground_color, arg);
1768 if (FRAME_VISIBLE_P (f))
1769 redraw_frame (f);
1773 void
1774 x_set_mouse_color (f, arg, oldval)
1775 struct frame *f;
1776 Lisp_Object arg, oldval;
1778 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1779 int count;
1780 int mask_color;
1782 if (!EQ (Qnil, arg))
1783 f->output_data.mac->mouse_pixel
1784 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1785 mask_color = FRAME_BACKGROUND_PIXEL (f);
1787 /* Don't let pointers be invisible. */
1788 if (mask_color == f->output_data.mac->mouse_pixel
1789 && mask_color == FRAME_BACKGROUND_PIXEL (f))
1790 f->output_data.mac->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
1792 #if 0 /* MAC_TODO : cursor changes */
1793 BLOCK_INPUT;
1795 /* It's not okay to crash if the user selects a screwy cursor. */
1796 count = x_catch_errors (FRAME_W32_DISPLAY (f));
1798 if (!EQ (Qnil, Vx_pointer_shape))
1800 CHECK_NUMBER (Vx_pointer_shape);
1801 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
1803 else
1804 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1805 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
1807 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1809 CHECK_NUMBER (Vx_nontext_pointer_shape);
1810 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1811 XINT (Vx_nontext_pointer_shape));
1813 else
1814 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
1815 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1817 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
1819 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1820 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1821 XINT (Vx_hourglass_pointer_shape));
1823 else
1824 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
1825 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
1827 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1828 if (!EQ (Qnil, Vx_mode_pointer_shape))
1830 CHECK_NUMBER (Vx_mode_pointer_shape);
1831 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1832 XINT (Vx_mode_pointer_shape));
1834 else
1835 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1836 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
1838 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1840 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1841 hand_cursor
1842 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1843 XINT (Vx_sensitive_text_pointer_shape));
1845 else
1846 hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
1848 if (!NILP (Vx_window_horizontal_drag_shape))
1850 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1851 horizontal_drag_cursor
1852 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1853 XINT (Vx_window_horizontal_drag_shape));
1855 else
1856 horizontal_drag_cursor
1857 = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
1859 /* Check and report errors with the above calls. */
1860 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
1861 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
1864 XColor fore_color, back_color;
1866 fore_color.pixel = f->output_data.w32->mouse_pixel;
1867 back_color.pixel = mask_color;
1868 XQueryColor (FRAME_W32_DISPLAY (f),
1869 DefaultColormap (FRAME_W32_DISPLAY (f),
1870 DefaultScreen (FRAME_W32_DISPLAY (f))),
1871 &fore_color);
1872 XQueryColor (FRAME_W32_DISPLAY (f),
1873 DefaultColormap (FRAME_W32_DISPLAY (f),
1874 DefaultScreen (FRAME_W32_DISPLAY (f))),
1875 &back_color);
1876 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
1877 &fore_color, &back_color);
1878 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
1879 &fore_color, &back_color);
1880 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
1881 &fore_color, &back_color);
1882 XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor,
1883 &fore_color, &back_color);
1884 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
1885 &fore_color, &back_color);
1888 if (FRAME_W32_WINDOW (f) != 0)
1889 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
1891 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
1892 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
1893 f->output_data.w32->text_cursor = cursor;
1895 if (nontext_cursor != f->output_data.w32->nontext_cursor
1896 && f->output_data.w32->nontext_cursor != 0)
1897 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
1898 f->output_data.w32->nontext_cursor = nontext_cursor;
1900 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
1901 && f->output_data.w32->hourglass_cursor != 0)
1902 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
1903 f->output_data.w32->hourglass_cursor = hourglass_cursor;
1905 if (mode_cursor != f->output_data.w32->modeline_cursor
1906 && f->output_data.w32->modeline_cursor != 0)
1907 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
1908 f->output_data.w32->modeline_cursor = mode_cursor;
1910 if (hand_cursor != f->output_data.w32->hand_cursor
1911 && f->output_data.w32->hand_cursor != 0)
1912 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hand_cursor);
1913 f->output_data.w32->hand_cursor = hand_cursor;
1915 XFlush (FRAME_W32_DISPLAY (f));
1916 UNBLOCK_INPUT;
1918 update_face_from_frame_parameter (f, Qmouse_color, arg);
1919 #endif /* MAC_TODO */
1922 void
1923 x_set_cursor_color (f, arg, oldval)
1924 struct frame *f;
1925 Lisp_Object arg, oldval;
1927 unsigned long fore_pixel, pixel;
1929 if (!NILP (Vx_cursor_fore_pixel))
1930 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1931 WHITE_PIX_DEFAULT (f));
1932 else
1933 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1935 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1937 /* Make sure that the cursor color differs from the background color. */
1938 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1940 pixel = f->output_data.mac->mouse_pixel;
1941 if (pixel == fore_pixel)
1942 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1945 f->output_data.mac->cursor_foreground_pixel = fore_pixel;
1946 f->output_data.mac->cursor_pixel = pixel;
1948 if (FRAME_MAC_WINDOW (f) != 0)
1950 BLOCK_INPUT;
1951 /* Update frame's cursor_gc. */
1952 f->output_data.mac->cursor_gc->foreground = fore_pixel;
1953 f->output_data.mac->cursor_gc->background = pixel;
1955 UNBLOCK_INPUT;
1957 if (FRAME_VISIBLE_P (f))
1959 x_update_cursor (f, 0);
1960 x_update_cursor (f, 1);
1964 update_face_from_frame_parameter (f, Qcursor_color, arg);
1967 /* Set the border-color of frame F to pixel value PIX.
1968 Note that this does not fully take effect if done before
1969 F has a window. */
1971 void
1972 x_set_border_pixel (f, pix)
1973 struct frame *f;
1974 int pix;
1977 f->output_data.mac->border_pixel = pix;
1979 if (FRAME_MAC_WINDOW (f) != 0 && f->border_width > 0)
1981 if (FRAME_VISIBLE_P (f))
1982 redraw_frame (f);
1986 /* Set the border-color of frame F to value described by ARG.
1987 ARG can be a string naming a color.
1988 The border-color is used for the border that is drawn by the server.
1989 Note that this does not fully take effect if done before
1990 F has a window; it must be redone when the window is created. */
1992 void
1993 x_set_border_color (f, arg, oldval)
1994 struct frame *f;
1995 Lisp_Object arg, oldval;
1997 int pix;
1999 CHECK_STRING (arg);
2000 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
2001 x_set_border_pixel (f, pix);
2002 update_face_from_frame_parameter (f, Qborder_color, arg);
2006 void
2007 x_set_cursor_type (f, arg, oldval)
2008 FRAME_PTR f;
2009 Lisp_Object arg, oldval;
2011 set_frame_cursor_types (f, arg);
2013 /* Make sure the cursor gets redrawn. */
2014 cursor_type_changed = 1;
2017 #if 0 /* MAC_TODO: really no icon for Mac */
2018 void
2019 x_set_icon_type (f, arg, oldval)
2020 struct frame *f;
2021 Lisp_Object arg, oldval;
2023 int result;
2025 if (NILP (arg) && NILP (oldval))
2026 return;
2028 if (STRINGP (arg) && STRINGP (oldval)
2029 && EQ (Fstring_equal (oldval, arg), Qt))
2030 return;
2032 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
2033 return;
2035 BLOCK_INPUT;
2037 result = x_bitmap_icon (f, arg);
2038 if (result)
2040 UNBLOCK_INPUT;
2041 error ("No icon window available");
2044 UNBLOCK_INPUT;
2046 #endif /* MAC_TODO */
2048 void
2049 x_set_icon_name (f, arg, oldval)
2050 struct frame *f;
2051 Lisp_Object arg, oldval;
2053 int result;
2055 if (STRINGP (arg))
2057 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
2058 return;
2060 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
2061 return;
2063 f->icon_name = arg;
2065 #if 0 /* MAC_TODO */
2066 if (f->output_data.w32->icon_bitmap != 0)
2067 return;
2069 BLOCK_INPUT;
2071 result = x_text_icon (f,
2072 (char *) SDATA ((!NILP (f->icon_name)
2073 ? f->icon_name
2074 : !NILP (f->title)
2075 ? f->title
2076 : f->name)));
2078 if (result)
2080 UNBLOCK_INPUT;
2081 error ("No icon window available");
2084 /* If the window was unmapped (and its icon was mapped),
2085 the new icon is not mapped, so map the window in its stead. */
2086 if (FRAME_VISIBLE_P (f))
2088 #ifdef USE_X_TOOLKIT
2089 XtPopup (f->output_data.w32->widget, XtGrabNone);
2090 #endif
2091 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2094 XFlush (FRAME_W32_DISPLAY (f));
2095 UNBLOCK_INPUT;
2096 #endif /* MAC_TODO */
2100 void
2101 x_set_menu_bar_lines (f, value, oldval)
2102 struct frame *f;
2103 Lisp_Object value, oldval;
2105 int nlines;
2106 int olines = FRAME_MENU_BAR_LINES (f);
2108 /* Right now, menu bars don't work properly in minibuf-only frames;
2109 most of the commands try to apply themselves to the minibuffer
2110 frame itself, and get an error because you can't switch buffers
2111 in or split the minibuffer window. */
2112 if (FRAME_MINIBUF_ONLY_P (f))
2113 return;
2115 if (INTEGERP (value))
2116 nlines = XINT (value);
2117 else
2118 nlines = 0;
2120 FRAME_MENU_BAR_LINES (f) = 0;
2121 if (nlines)
2122 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2123 else
2125 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2126 free_frame_menubar (f);
2127 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2129 /* Adjust the frame size so that the client (text) dimensions
2130 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2131 set correctly. */
2132 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
2133 do_pending_window_change (0);
2135 adjust_glyphs (f);
2139 /* Set the number of lines used for the tool bar of frame F to VALUE.
2140 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2141 is the old number of tool bar lines. This function changes the
2142 height of all windows on frame F to match the new tool bar height.
2143 The frame's height doesn't change. */
2145 void
2146 x_set_tool_bar_lines (f, value, oldval)
2147 struct frame *f;
2148 Lisp_Object value, oldval;
2150 int delta, nlines, root_height;
2151 Lisp_Object root_window;
2153 /* Treat tool bars like menu bars. */
2154 if (FRAME_MINIBUF_ONLY_P (f))
2155 return;
2157 /* Use VALUE only if an integer >= 0. */
2158 if (INTEGERP (value) && XINT (value) >= 0)
2159 nlines = XFASTINT (value);
2160 else
2161 nlines = 0;
2163 /* Make sure we redisplay all windows in this frame. */
2164 ++windows_or_buffers_changed;
2166 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2168 /* Don't resize the tool-bar to more than we have room for. */
2169 root_window = FRAME_ROOT_WINDOW (f);
2170 root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
2171 if (root_height - delta < 1)
2173 delta = root_height - 1;
2174 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2177 FRAME_TOOL_BAR_LINES (f) = nlines;
2178 change_window_heights (root_window, delta);
2179 adjust_glyphs (f);
2181 /* We also have to make sure that the internal border at the top of
2182 the frame, below the menu bar or tool bar, is redrawn when the
2183 tool bar disappears. This is so because the internal border is
2184 below the tool bar if one is displayed, but is below the menu bar
2185 if there isn't a tool bar. The tool bar draws into the area
2186 below the menu bar. */
2187 if (FRAME_MAC_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2189 updating_frame = f;
2190 clear_frame ();
2191 clear_current_matrices (f);
2192 updating_frame = NULL;
2195 /* If the tool bar gets smaller, the internal border below it
2196 has to be cleared. It was formerly part of the display
2197 of the larger tool bar, and updating windows won't clear it. */
2198 if (delta < 0)
2200 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2201 int width = FRAME_PIXEL_WIDTH (f);
2202 int y = nlines * FRAME_LINE_HEIGHT (f);
2204 BLOCK_INPUT;
2205 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2206 0, y, width, height, 0);
2207 UNBLOCK_INPUT;
2209 if (WINDOWP (f->tool_bar_window))
2210 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2215 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2216 w32_id_name.
2218 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2219 name; if NAME is a string, set F's name to NAME and set
2220 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2222 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2223 suggesting a new name, which lisp code should override; if
2224 F->explicit_name is set, ignore the new name; otherwise, set it. */
2226 void
2227 x_set_name (f, name, explicit)
2228 struct frame *f;
2229 Lisp_Object name;
2230 int explicit;
2232 /* Make sure that requests from lisp code override requests from
2233 Emacs redisplay code. */
2234 if (explicit)
2236 /* If we're switching from explicit to implicit, we had better
2237 update the mode lines and thereby update the title. */
2238 if (f->explicit_name && NILP (name))
2239 update_mode_lines = 1;
2241 f->explicit_name = ! NILP (name);
2243 else if (f->explicit_name)
2244 return;
2246 /* If NAME is nil, set the name to the w32_id_name. */
2247 if (NILP (name))
2249 /* Check for no change needed in this very common case
2250 before we do any consing. */
2251 if (!strcmp (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name,
2252 SDATA (f->name)))
2253 return;
2254 name = build_string (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name);
2256 else
2257 CHECK_STRING (name);
2259 /* Don't change the name if it's already NAME. */
2260 if (! NILP (Fstring_equal (name, f->name)))
2261 return;
2263 f->name = name;
2265 /* For setting the frame title, the title parameter should override
2266 the name parameter. */
2267 if (! NILP (f->title))
2268 name = f->title;
2270 if (FRAME_MAC_WINDOW (f))
2272 if (STRING_MULTIBYTE (name))
2273 #if 0 /* MAC_TODO: encoding title string */
2274 name = ENCODE_SYSTEM (name);
2275 #else
2276 return;
2277 #endif
2279 BLOCK_INPUT;
2282 Str255 windowTitle;
2283 if (strlen (SDATA (name)) < 255)
2285 strcpy (windowTitle, SDATA (name));
2286 c2pstr (windowTitle);
2287 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2291 UNBLOCK_INPUT;
2295 /* This function should be called when the user's lisp code has
2296 specified a name for the frame; the name will override any set by the
2297 redisplay code. */
2298 void
2299 x_explicitly_set_name (f, arg, oldval)
2300 FRAME_PTR f;
2301 Lisp_Object arg, oldval;
2303 x_set_name (f, arg, 1);
2306 /* This function should be called by Emacs redisplay code to set the
2307 name; names set this way will never override names set by the user's
2308 lisp code. */
2309 void
2310 x_implicitly_set_name (f, arg, oldval)
2311 FRAME_PTR f;
2312 Lisp_Object arg, oldval;
2314 x_set_name (f, arg, 0);
2317 /* Change the title of frame F to NAME.
2318 If NAME is nil, use the frame name as the title.
2320 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2321 name; if NAME is a string, set F's name to NAME and set
2322 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2324 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2325 suggesting a new name, which lisp code should override; if
2326 F->explicit_name is set, ignore the new name; otherwise, set it. */
2328 void
2329 x_set_title (f, name, old_name)
2330 struct frame *f;
2331 Lisp_Object name, old_name;
2333 /* Don't change the title if it's already NAME. */
2334 if (EQ (name, f->title))
2335 return;
2337 update_mode_lines = 1;
2339 f->title = name;
2341 if (NILP (name))
2342 name = f->name;
2344 if (FRAME_MAC_WINDOW (f))
2346 if (STRING_MULTIBYTE (name))
2347 #if 0 /* MAC_TODO: encoding title string */
2348 name = ENCODE_SYSTEM (name);
2349 #else
2350 return;
2351 #endif
2353 BLOCK_INPUT;
2356 Str255 windowTitle;
2357 if (strlen (SDATA (name)) < 255)
2359 strcpy (windowTitle, SDATA (name));
2360 c2pstr (windowTitle);
2361 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2365 UNBLOCK_INPUT;
2369 void
2370 x_set_scroll_bar_default_width (f)
2371 struct frame *f;
2373 /* Imitate X without X Toolkit */
2375 int wid = FRAME_COLUMN_WIDTH (f);
2377 #ifdef MAC_OSX
2378 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 16; /* Aqua scroll bars. */
2379 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2380 wid - 1) / wid;
2381 #else /* not MAC_OSX */
2382 /* Make the actual width at least 14 pixels and a multiple of a
2383 character width. */
2384 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2386 /* Use all of that space (aside from required margins) for the
2387 scroll bar. */
2388 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
2389 #endif /* not MAC_OSX */
2393 /* Subroutines of creating a frame. */
2395 char *
2396 x_get_string_resource (rdb, name, class)
2397 XrmDatabase rdb;
2398 char *name, *class;
2400 /* MAC_TODO: implement resource strings */
2401 return (char *)0;
2404 /* Return the value of parameter PARAM.
2406 First search ALIST, then Vdefault_frame_alist, then the X defaults
2407 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2409 Convert the resource to the type specified by desired_type.
2411 If no default is specified, return Qunbound. If you call
2412 mac_get_arg, make sure you deal with Qunbound in a reasonable way,
2413 and don't let it get stored in any Lisp-visible variables! */
2415 static Lisp_Object
2416 mac_get_arg (alist, param, attribute, class, type)
2417 Lisp_Object alist, param;
2418 char *attribute;
2419 char *class;
2420 enum resource_types type;
2422 return x_get_arg (check_x_display_info (Qnil),
2423 alist, param, attribute, class, type);
2427 /* XParseGeometry copied from w32xfns.c */
2430 * XParseGeometry parses strings of the form
2431 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
2432 * width, height, xoffset, and yoffset are unsigned integers.
2433 * Example: "=80x24+300-49"
2434 * The equal sign is optional.
2435 * It returns a bitmask that indicates which of the four values
2436 * were actually found in the string. For each value found,
2437 * the corresponding argument is updated; for each value
2438 * not found, the corresponding argument is left unchanged.
2441 static int
2442 read_integer (string, NextString)
2443 register char *string;
2444 char **NextString;
2446 register int Result = 0;
2447 int Sign = 1;
2449 if (*string == '+')
2450 string++;
2451 else if (*string == '-')
2453 string++;
2454 Sign = -1;
2456 for (; (*string >= '0') && (*string <= '9'); string++)
2458 Result = (Result * 10) + (*string - '0');
2460 *NextString = string;
2461 if (Sign >= 0)
2462 return (Result);
2463 else
2464 return (-Result);
2468 XParseGeometry (string, x, y, width, height)
2469 char *string;
2470 int *x, *y;
2471 unsigned int *width, *height; /* RETURN */
2473 int mask = NoValue;
2474 register char *strind;
2475 unsigned int tempWidth, tempHeight;
2476 int tempX, tempY;
2477 char *nextCharacter;
2479 if ((string == NULL) || (*string == '\0')) return (mask);
2480 if (*string == '=')
2481 string++; /* ignore possible '=' at beg of geometry spec */
2483 strind = (char *)string;
2484 if (*strind != '+' && *strind != '-' && *strind != 'x')
2486 tempWidth = read_integer (strind, &nextCharacter);
2487 if (strind == nextCharacter)
2488 return (0);
2489 strind = nextCharacter;
2490 mask |= WidthValue;
2493 if (*strind == 'x' || *strind == 'X')
2495 strind++;
2496 tempHeight = read_integer (strind, &nextCharacter);
2497 if (strind == nextCharacter)
2498 return (0);
2499 strind = nextCharacter;
2500 mask |= HeightValue;
2503 if ((*strind == '+') || (*strind == '-'))
2505 if (*strind == '-')
2507 strind++;
2508 tempX = -read_integer (strind, &nextCharacter);
2509 if (strind == nextCharacter)
2510 return (0);
2511 strind = nextCharacter;
2512 mask |= XNegative;
2515 else
2517 strind++;
2518 tempX = read_integer (strind, &nextCharacter);
2519 if (strind == nextCharacter)
2520 return (0);
2521 strind = nextCharacter;
2523 mask |= XValue;
2524 if ((*strind == '+') || (*strind == '-'))
2526 if (*strind == '-')
2528 strind++;
2529 tempY = -read_integer (strind, &nextCharacter);
2530 if (strind == nextCharacter)
2531 return (0);
2532 strind = nextCharacter;
2533 mask |= YNegative;
2536 else
2538 strind++;
2539 tempY = read_integer (strind, &nextCharacter);
2540 if (strind == nextCharacter)
2541 return (0);
2542 strind = nextCharacter;
2544 mask |= YValue;
2548 /* If strind isn't at the end of the string the it's an invalid
2549 geometry specification. */
2551 if (*strind != '\0') return (0);
2553 if (mask & XValue)
2554 *x = tempX;
2555 if (mask & YValue)
2556 *y = tempY;
2557 if (mask & WidthValue)
2558 *width = tempWidth;
2559 if (mask & HeightValue)
2560 *height = tempHeight;
2561 return (mask);
2565 #if 0 /* MAC_TODO */
2566 /* Create and set up the Mac window for frame F. */
2568 static void
2569 mac_window (f, window_prompting, minibuffer_only)
2570 struct frame *f;
2571 long window_prompting;
2572 int minibuffer_only;
2574 Rect r;
2576 BLOCK_INPUT;
2578 /* Use the resource name as the top-level window name
2579 for looking up resources. Make a non-Lisp copy
2580 for the window manager, so GC relocation won't bother it.
2582 Elsewhere we specify the window name for the window manager. */
2585 char *str = (char *) SDATA (Vx_resource_name);
2586 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2587 strcpy (f->namebuf, str);
2590 SetRect (&r, f->left_pos, f->top_pos,
2591 f->left_pos + FRAME_PIXEL_WIDTH (f),
2592 f->top_pos + FRAME_PIXEL_HEIGHT (f));
2593 FRAME_MAC_WINDOW (f)
2594 = NewCWindow (NULL, &r, "\p", 1, zoomDocProc, (WindowPtr) -1, 1, (long) f->output_data.mac);
2596 validate_x_resource_name ();
2598 /* x_set_name normally ignores requests to set the name if the
2599 requested name is the same as the current name. This is the one
2600 place where that assumption isn't correct; f->name is set, but
2601 the server hasn't been told. */
2603 Lisp_Object name;
2604 int explicit = f->explicit_name;
2606 f->explicit_name = 0;
2607 name = f->name;
2608 f->name = Qnil;
2609 x_set_name (f, name, explicit);
2612 ShowWindow (FRAME_MAC_WINDOW (f));
2614 UNBLOCK_INPUT;
2616 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2617 initialize_frame_menubar (f);
2619 if (FRAME_MAC_WINDOW (f) == 0)
2620 error ("Unable to create window");
2622 #endif /* MAC_TODO */
2624 /* Handle the icon stuff for this window. Perhaps later we might
2625 want an x_set_icon_position which can be called interactively as
2626 well. */
2628 static void
2629 x_icon (f, parms)
2630 struct frame *f;
2631 Lisp_Object parms;
2633 Lisp_Object icon_x, icon_y;
2635 /* Set the position of the icon. Note that Windows 95 groups all
2636 icons in the tray. */
2637 icon_x = mac_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2638 icon_y = mac_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2639 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2641 CHECK_NUMBER (icon_x);
2642 CHECK_NUMBER (icon_y);
2644 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2645 error ("Both left and top icon corners of icon must be specified");
2647 BLOCK_INPUT;
2649 if (! EQ (icon_x, Qunbound))
2650 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2652 #if 0 /* TODO */
2653 /* Start up iconic or window? */
2654 x_wm_set_window_state
2655 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
2656 ? IconicState
2657 : NormalState));
2659 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2660 ? f->icon_name
2661 : f->name)));
2662 #endif
2664 UNBLOCK_INPUT;
2668 void
2669 x_make_gc (f)
2670 struct frame *f;
2672 XGCValues gc_values;
2674 BLOCK_INPUT;
2676 /* Create the GCs of this frame.
2677 Note that many default values are used. */
2679 /* Normal video */
2680 gc_values.font = FRAME_FONT (f);
2681 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
2682 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
2683 f->output_data.mac->normal_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
2684 FRAME_MAC_WINDOW (f),
2685 GCFont | GCForeground | GCBackground,
2686 &gc_values);
2688 /* Reverse video style. */
2689 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
2690 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
2691 f->output_data.mac->reverse_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
2692 FRAME_MAC_WINDOW (f),
2693 GCFont | GCForeground | GCBackground,
2694 &gc_values);
2696 /* Cursor has cursor-color background, background-color foreground. */
2697 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
2698 gc_values.background = f->output_data.mac->cursor_pixel;
2699 f->output_data.mac->cursor_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
2700 FRAME_MAC_WINDOW (f),
2701 GCFont | GCForeground | GCBackground,
2702 &gc_values);
2704 /* Reliefs. */
2705 f->output_data.mac->white_relief.gc = 0;
2706 f->output_data.mac->black_relief.gc = 0;
2708 #if 0
2709 /* Create the gray border tile used when the pointer is not in
2710 the frame. Since this depends on the frame's pixel values,
2711 this must be done on a per-frame basis. */
2712 f->output_data.x->border_tile
2713 = (XCreatePixmapFromBitmapData
2714 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
2715 gray_bits, gray_width, gray_height,
2716 f->output_data.x->foreground_pixel,
2717 f->output_data.x->background_pixel,
2718 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
2719 #endif
2721 UNBLOCK_INPUT;
2725 /* Free what was was allocated in x_make_gc. */
2727 void
2728 x_free_gcs (f)
2729 struct frame *f;
2731 Display *dpy = FRAME_MAC_DISPLAY (f);
2733 BLOCK_INPUT;
2735 if (f->output_data.mac->normal_gc)
2737 XFreeGC (dpy, f->output_data.mac->normal_gc);
2738 f->output_data.mac->normal_gc = 0;
2741 if (f->output_data.mac->reverse_gc)
2743 XFreeGC (dpy, f->output_data.mac->reverse_gc);
2744 f->output_data.mac->reverse_gc = 0;
2747 if (f->output_data.mac->cursor_gc)
2749 XFreeGC (dpy, f->output_data.mac->cursor_gc);
2750 f->output_data.mac->cursor_gc = 0;
2753 #if 0
2754 if (f->output_data.mac->border_tile)
2756 XFreePixmap (dpy, f->output_data.mac->border_tile);
2757 f->output_data.mac->border_tile = 0;
2759 #endif
2761 if (f->output_data.mac->white_relief.gc)
2763 XFreeGC (dpy, f->output_data.mac->white_relief.gc);
2764 f->output_data.mac->white_relief.gc = 0;
2767 if (f->output_data.mac->black_relief.gc)
2769 XFreeGC (dpy, f->output_data.mac->black_relief.gc);
2770 f->output_data.mac->black_relief.gc = 0;
2773 UNBLOCK_INPUT;
2777 /* Handler for signals raised during x_create_frame and
2778 x_create_top_frame. FRAME is the frame which is partially
2779 constructed. */
2781 static Lisp_Object
2782 unwind_create_frame (frame)
2783 Lisp_Object frame;
2785 struct frame *f = XFRAME (frame);
2787 /* If frame is ``official'', nothing to do. */
2788 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
2790 #if GLYPH_DEBUG
2791 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2792 #endif
2794 x_free_frame_resources (f);
2796 /* Check that reference counts are indeed correct. */
2797 xassert (dpyinfo->reference_count == dpyinfo_refcount);
2798 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2799 return Qt;
2802 return Qnil;
2806 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2807 1, 1, 0,
2808 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
2809 Returns an Emacs frame object.
2810 ALIST is an alist of frame parameters.
2811 If the parameters specify that the frame should not have a minibuffer,
2812 and do not specify a specific minibuffer window to use,
2813 then `default-minibuffer-frame' must be a frame whose minibuffer can
2814 be shared by the new frame.
2816 This function is an internal primitive--use `make-frame' instead. */)
2817 (parms)
2818 Lisp_Object parms;
2820 struct frame *f;
2821 Lisp_Object frame, tem;
2822 Lisp_Object name;
2823 int minibuffer_only = 0;
2824 long window_prompting = 0;
2825 int width, height;
2826 int count = SPECPDL_INDEX ();
2827 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2828 Lisp_Object display;
2829 struct mac_display_info *dpyinfo = NULL;
2830 Lisp_Object parent;
2831 struct kboard *kb;
2832 char x_frame_name[10];
2833 static int x_frame_count = 2; /* begins at 2 because terminal frame is F1 */
2835 check_mac ();
2837 /* Use this general default value to start with
2838 until we know if this frame has a specified name. */
2839 Vx_resource_name = Vinvocation_name;
2841 display = mac_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
2842 if (EQ (display, Qunbound))
2843 display = Qnil;
2844 dpyinfo = check_x_display_info (display);
2845 #ifdef MULTI_KBOARD
2846 kb = dpyinfo->kboard;
2847 #else
2848 kb = &the_only_kboard;
2849 #endif
2851 name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
2852 if (!STRINGP (name)
2853 && ! EQ (name, Qunbound)
2854 && ! NILP (name))
2855 error ("Invalid frame name--not a string or nil");
2857 if (STRINGP (name))
2858 Vx_resource_name = name;
2860 /* See if parent window is specified. */
2861 parent = mac_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
2862 if (EQ (parent, Qunbound))
2863 parent = Qnil;
2864 if (! NILP (parent))
2865 CHECK_NUMBER (parent);
2867 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
2868 /* No need to protect DISPLAY because that's not used after passing
2869 it to make_frame_without_minibuffer. */
2870 frame = Qnil;
2871 GCPRO4 (parms, parent, name, frame);
2872 tem = mac_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
2873 RES_TYPE_SYMBOL);
2874 if (EQ (tem, Qnone) || NILP (tem))
2875 f = make_frame_without_minibuffer (Qnil, kb, display);
2876 else if (EQ (tem, Qonly))
2878 f = make_minibuffer_frame ();
2879 minibuffer_only = 1;
2881 else if (WINDOWP (tem))
2882 f = make_frame_without_minibuffer (tem, kb, display);
2883 else
2884 f = make_frame (1);
2886 if (EQ (name, Qunbound) || NILP (name))
2888 sprintf (x_frame_name, "F%d", x_frame_count++);
2889 f->name = build_string (x_frame_name);
2890 f->explicit_name = 0;
2892 else
2894 f->name = name;
2895 f->explicit_name = 1;
2898 XSETFRAME (frame, f);
2900 /* Note that X Windows does support scroll bars. */
2901 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
2903 f->output_method = output_mac;
2904 f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
2905 bzero (f->output_data.mac, sizeof (struct mac_output));
2906 FRAME_FONTSET (f) = -1;
2907 f->output_data.mac->scroll_bar_foreground_pixel = -1;
2908 f->output_data.mac->scroll_bar_background_pixel = -1;
2909 record_unwind_protect (unwind_create_frame, frame);
2911 f->icon_name
2912 = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
2913 if (! STRINGP (f->icon_name))
2914 f->icon_name = Qnil;
2916 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
2917 #ifdef MULTI_KBOARD
2918 FRAME_KBOARD (f) = kb;
2919 #endif
2921 /* Specify the parent under which to make this window. */
2923 if (!NILP (parent))
2925 f->output_data.mac->parent_desc = (Window) parent;
2926 f->output_data.mac->explicit_parent = 1;
2928 else
2930 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
2931 f->output_data.mac->explicit_parent = 0;
2934 /* Set the name; the functions to which we pass f expect the name to
2935 be set. */
2936 if (EQ (name, Qunbound) || NILP (name))
2938 f->name = build_string (dpyinfo->mac_id_name);
2939 f->explicit_name = 0;
2941 else
2943 f->name = name;
2944 f->explicit_name = 1;
2945 /* use the frame's title when getting resources for this frame. */
2946 specbind (Qx_resource_name, name);
2949 /* Extract the window parameters from the supplied values
2950 that are needed to determine window geometry. */
2952 Lisp_Object font;
2954 font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
2956 BLOCK_INPUT;
2957 /* First, try whatever font the caller has specified. */
2958 if (STRINGP (font))
2960 tem = Fquery_fontset (font, Qnil);
2961 if (STRINGP (tem))
2962 font = x_new_fontset (f, SDATA (tem));
2963 else
2964 font = x_new_font (f, SDATA (font));
2967 /* Try out a font which we hope has bold and italic variations. */
2968 if (! STRINGP (font))
2969 font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
2970 /* If those didn't work, look for something which will at least work. */
2971 if (! STRINGP (font))
2972 font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
2973 if (! STRINGP (font))
2974 font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
2975 if (! STRINGP (font))
2976 error ("Cannot find any usable font");
2977 UNBLOCK_INPUT;
2979 x_default_parameter (f, parms, Qfont, font,
2980 "font", "Font", RES_TYPE_STRING);
2983 x_default_parameter (f, parms, Qborder_width, make_number (0),
2984 "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
2985 /* This defaults to 2 in order to match xterm. We recognize either
2986 internalBorderWidth or internalBorder (which is what xterm calls
2987 it). */
2988 if (NILP (Fassq (Qinternal_border_width, parms)))
2990 Lisp_Object value;
2992 value = mac_get_arg (parms, Qinternal_border_width,
2993 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
2994 if (! EQ (value, Qunbound))
2995 parms = Fcons (Fcons (Qinternal_border_width, value),
2996 parms);
2998 /* Default internalBorderWidth to 0 on Windows to match other programs. */
2999 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
3000 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
3001 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
3002 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
3004 /* Also do the stuff which must be set before the window exists. */
3005 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
3006 "foreground", "Foreground", RES_TYPE_STRING);
3007 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
3008 "background", "Background", RES_TYPE_STRING);
3009 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
3010 "pointerColor", "Foreground", RES_TYPE_STRING);
3011 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
3012 "cursorColor", "Foreground", RES_TYPE_STRING);
3013 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
3014 "borderColor", "BorderColor", RES_TYPE_STRING);
3015 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
3016 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
3017 x_default_parameter (f, parms, Qline_spacing, Qnil,
3018 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
3019 x_default_parameter (f, parms, Qleft_fringe, Qnil,
3020 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3021 x_default_parameter (f, parms, Qright_fringe, Qnil,
3022 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3025 /* Init faces before x_default_parameter is called for scroll-bar
3026 parameters because that function calls x_set_scroll_bar_width,
3027 which calls change_frame_size, which calls Fset_window_buffer,
3028 which runs hooks, which call Fvertical_motion. At the end, we
3029 end up in init_iterator with a null face cache, which should not
3030 happen. */
3031 init_frame_faces (f);
3033 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
3034 "menuBar", "MenuBar", RES_TYPE_NUMBER);
3035 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
3036 "toolBar", "ToolBar", RES_TYPE_NUMBER);
3037 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
3038 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
3039 x_default_parameter (f, parms, Qtitle, Qnil,
3040 "title", "Title", RES_TYPE_STRING);
3042 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
3044 /* MAC_TODO: specify 1 below when toolbars are implemented. */
3045 window_prompting = x_figure_window_size (f, parms, 0);
3047 tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
3048 f->no_split = minibuffer_only || EQ (tem, Qt);
3050 /* Create the window. Add the tool-bar height to the initial frame
3051 height so that the user gets a text display area of the size he
3052 specified with -g or via the registry. Later changes of the
3053 tool-bar height don't change the frame size. This is done so that
3054 users can create tall Emacs frames without having to guess how
3055 tall the tool-bar will get. */
3056 FRAME_LINES (f) += FRAME_TOOL_BAR_LINES (f);
3058 /* mac_window (f, window_prompting, minibuffer_only); */
3059 make_mac_frame (f);
3061 x_icon (f, parms);
3063 x_make_gc (f);
3065 /* Now consider the frame official. */
3066 FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
3067 Vframe_list = Fcons (frame, Vframe_list);
3069 /* We need to do this after creating the window, so that the
3070 icon-creation functions can say whose icon they're describing. */
3071 x_default_parameter (f, parms, Qicon_type, Qnil,
3072 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
3074 x_default_parameter (f, parms, Qauto_raise, Qnil,
3075 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3076 x_default_parameter (f, parms, Qauto_lower, Qnil,
3077 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
3078 x_default_parameter (f, parms, Qcursor_type, Qbox,
3079 "cursorType", "CursorType", RES_TYPE_SYMBOL);
3080 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
3081 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
3083 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
3084 Change will not be effected unless different from the current
3085 FRAME_LINES (f). */
3086 width = FRAME_COLS (f);
3087 height = FRAME_LINES (f);
3089 FRAME_LINES (f) = 0;
3090 SET_FRAME_COLS (f, 0);
3091 change_frame_size (f, height, width, 1, 0, 0);
3093 /* Set up faces after all frame parameters are known. */
3094 call1 (Qface_set_after_frame_default, frame);
3096 #if 0 /* MAC_TODO: when we have window manager hints */
3097 /* Tell the server what size and position, etc, we want, and how
3098 badly we want them. This should be done after we have the menu
3099 bar so that its size can be taken into account. */
3100 BLOCK_INPUT;
3101 x_wm_set_size_hint (f, window_prompting, 0);
3102 UNBLOCK_INPUT;
3103 #endif
3105 /* Make the window appear on the frame and enable display, unless
3106 the caller says not to. However, with explicit parent, Emacs
3107 cannot control visibility, so don't try. */
3108 if (! f->output_data.mac->explicit_parent)
3110 Lisp_Object visibility;
3112 visibility = mac_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
3113 if (EQ (visibility, Qunbound))
3114 visibility = Qt;
3116 #if 0 /* MAC_TODO: really no iconify on Mac */
3117 if (EQ (visibility, Qicon))
3118 x_iconify_frame (f);
3119 else
3120 #endif
3121 if (! NILP (visibility))
3122 x_make_frame_visible (f);
3123 else
3124 /* Must have been Qnil. */
3127 UNGCPRO;
3129 /* Make sure windows on this frame appear in calls to next-window
3130 and similar functions. */
3131 Vwindow_list = Qnil;
3133 return unbind_to (count, frame);
3136 /* FRAME is used only to get a handle on the X display. We don't pass the
3137 display info directly because we're called from frame.c, which doesn't
3138 know about that structure. */
3139 Lisp_Object
3140 x_get_focus_frame (frame)
3141 struct frame *frame;
3143 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3144 Lisp_Object xfocus;
3145 if (! dpyinfo->x_focus_frame)
3146 return Qnil;
3148 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
3149 return xfocus;
3152 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
3153 doc: /* Internal function called by `color-defined-p', which see. */)
3154 (color, frame)
3155 Lisp_Object color, frame;
3157 XColor foo;
3158 FRAME_PTR f = check_x_frame (frame);
3160 CHECK_STRING (color);
3162 if (mac_defined_color (f, SDATA (color), &foo, 0))
3163 return Qt;
3164 else
3165 return Qnil;
3168 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
3169 doc: /* Internal function called by `color-values', which see. */)
3170 (color, frame)
3171 Lisp_Object color, frame;
3173 XColor foo;
3174 FRAME_PTR f = check_x_frame (frame);
3176 CHECK_STRING (color);
3178 if (mac_defined_color (f, SDATA (color), &foo, 0))
3180 Lisp_Object rgb[3];
3182 rgb[0] = make_number (foo.red);
3183 rgb[1] = make_number (foo.green);
3184 rgb[2] = make_number (foo.blue);
3185 return Flist (3, rgb);
3187 else
3188 return Qnil;
3191 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3192 doc: /* Internal function called by `display-color-p', which see. */)
3193 (display)
3194 Lisp_Object display;
3196 struct mac_display_info *dpyinfo = check_x_display_info (display);
3198 if (!dpyinfo->color_p)
3199 return Qnil;
3201 return Qt;
3204 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3205 0, 1, 0,
3206 doc: /* Return t if the X display supports shades of gray.
3207 Note that color displays do support shades of gray.
3208 The optional argument DISPLAY specifies which display to ask about.
3209 DISPLAY should be either a frame or a display name (a string).
3210 If omitted or nil, that stands for the selected frame's display. */)
3211 (display)
3212 Lisp_Object display;
3214 struct mac_display_info *dpyinfo = check_x_display_info (display);
3216 if (dpyinfo->n_planes <= 1)
3217 return Qnil;
3219 return Qt;
3222 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3223 0, 1, 0,
3224 doc: /* Returns the width in pixels of the X display DISPLAY.
3225 The optional argument DISPLAY specifies which display to ask about.
3226 DISPLAY should be either a frame or a display name (a string).
3227 If omitted or nil, that stands for the selected frame's display. */)
3228 (display)
3229 Lisp_Object display;
3231 struct mac_display_info *dpyinfo = check_x_display_info (display);
3233 return make_number (dpyinfo->width);
3236 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3237 Sx_display_pixel_height, 0, 1, 0,
3238 doc: /* Returns the height in pixels of the X display DISPLAY.
3239 The optional argument DISPLAY specifies which display to ask about.
3240 DISPLAY should be either a frame or a display name (a string).
3241 If omitted or nil, that stands for the selected frame's display. */)
3242 (display)
3243 Lisp_Object display;
3245 struct mac_display_info *dpyinfo = check_x_display_info (display);
3247 return make_number (dpyinfo->height);
3250 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3251 0, 1, 0,
3252 doc: /* Returns the number of bitplanes of the display DISPLAY.
3253 The optional argument DISPLAY specifies which display to ask about.
3254 DISPLAY should be either a frame or a display name (a string).
3255 If omitted or nil, that stands for the selected frame's display. */)
3256 (display)
3257 Lisp_Object display;
3259 struct mac_display_info *dpyinfo = check_x_display_info (display);
3261 return make_number (dpyinfo->n_planes);
3264 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3265 0, 1, 0,
3266 doc: /* Returns the number of color cells of the display DISPLAY.
3267 The optional argument DISPLAY specifies which display to ask about.
3268 DISPLAY should be either a frame or a display name (a string).
3269 If omitted or nil, that stands for the selected frame's display. */)
3270 (display)
3271 Lisp_Object display;
3273 struct mac_display_info *dpyinfo = check_x_display_info (display);
3275 /* MAC_TODO: check whether this is right */
3276 return make_number (dpyinfo->n_planes >= 8 ? 256 : 1 << dpyinfo->n_planes - 1);
3279 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3280 Sx_server_max_request_size,
3281 0, 1, 0,
3282 doc: /* Returns the maximum request size of the server of display DISPLAY.
3283 The optional argument DISPLAY specifies which display to ask about.
3284 DISPLAY should be either a frame or a display name (a string).
3285 If omitted or nil, that stands for the selected frame's display. */)
3286 (display)
3287 Lisp_Object display;
3289 struct mac_display_info *dpyinfo = check_x_display_info (display);
3291 return make_number (1);
3294 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3295 doc: /* Returns the vendor ID string of the Mac OS system (Apple).
3296 The optional argument DISPLAY specifies which display to ask about.
3297 DISPLAY should be either a frame or a display name (a string).
3298 If omitted or nil, that stands for the selected frame's display. */)
3299 (display)
3300 Lisp_Object display;
3302 return build_string ("Apple Computers");
3305 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3306 doc: /* Returns the version numbers of the server of display DISPLAY.
3307 The value is a list of three integers: the major and minor
3308 version numbers, and the vendor-specific release
3309 number. See also the function `x-server-vendor'.
3311 The optional argument DISPLAY specifies which display to ask about.
3312 DISPLAY should be either a frame or a display name (a string).
3313 If omitted or nil, that stands for the selected frame's display. */)
3314 (display)
3315 Lisp_Object display;
3317 int mac_major_version, mac_minor_version;
3318 SInt32 response;
3320 if (Gestalt (gestaltSystemVersion, &response) != noErr)
3321 error ("Cannot get Mac OS version");
3323 mac_major_version = (response >> 8) & 0xf;
3324 mac_minor_version = (response >> 4) & 0xf;
3326 return Fcons (make_number (mac_major_version),
3327 Fcons (make_number (mac_minor_version), Qnil));
3330 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3331 doc: /* Return the number of screens on the server of display DISPLAY.
3332 The optional argument DISPLAY specifies which display to ask about.
3333 DISPLAY should be either a frame or a display name (a string).
3334 If omitted or nil, that stands for the selected frame's display. */)
3335 (display)
3336 Lisp_Object display;
3338 return make_number (1);
3341 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3342 doc: /* Return the height in millimeters of the X display DISPLAY.
3343 The optional argument DISPLAY specifies which display to ask about.
3344 DISPLAY should be either a frame or a display name (a string).
3345 If omitted or nil, that stands for the selected frame's display. */)
3346 (display)
3347 Lisp_Object display;
3349 /* MAC_TODO: this is an approximation, and only of the main display */
3351 struct mac_display_info *dpyinfo = check_x_display_info (display);
3352 short h, v;
3354 ScreenRes (&h, &v);
3356 return make_number ((int) (v / 72.0 * 25.4));
3359 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3360 doc: /* Return the width in millimeters of the X display DISPLAY.
3361 The optional argument DISPLAY specifies which display to ask about.
3362 DISPLAY should be either a frame or a display name (a string).
3363 If omitted or nil, that stands for the selected frame's display. */)
3364 (display)
3365 Lisp_Object display;
3367 /* MAC_TODO: this is an approximation, and only of the main display */
3369 struct mac_display_info *dpyinfo = check_x_display_info (display);
3370 short h, v;
3372 ScreenRes (&h, &v);
3374 return make_number ((int) (h / 72.0 * 25.4));
3377 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3378 Sx_display_backing_store, 0, 1, 0,
3379 doc: /* Returns an indication of whether display DISPLAY does backing store.
3380 The value may be `always', `when-mapped', or `not-useful'.
3381 The optional argument DISPLAY specifies which display to ask about.
3382 DISPLAY should be either a frame or a display name (a string).
3383 If omitted or nil, that stands for the selected frame's display. */)
3384 (display)
3385 Lisp_Object display;
3387 return intern ("not-useful");
3390 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3391 Sx_display_visual_class, 0, 1, 0,
3392 doc: /* Returns the visual class of the display DISPLAY.
3393 The value is one of the symbols `static-gray', `gray-scale',
3394 `static-color', `pseudo-color', `true-color', or `direct-color'.
3396 The optional argument DISPLAY specifies which display to ask about.
3397 DISPLAY should be either a frame or a display name (a string).
3398 If omitted or nil, that stands for the selected frame's display. */)
3399 (display)
3400 Lisp_Object display;
3402 struct mac_display_info *dpyinfo = check_x_display_info (display);
3404 #if 0
3405 switch (dpyinfo->visual->class)
3407 case StaticGray: return (intern ("static-gray"));
3408 case GrayScale: return (intern ("gray-scale"));
3409 case StaticColor: return (intern ("static-color"));
3410 case PseudoColor: return (intern ("pseudo-color"));
3411 case TrueColor: return (intern ("true-color"));
3412 case DirectColor: return (intern ("direct-color"));
3413 default:
3414 error ("Display has an unknown visual class");
3416 #endif /* 0 */
3418 return (intern ("true-color"));
3421 DEFUN ("x-display-save-under", Fx_display_save_under,
3422 Sx_display_save_under, 0, 1, 0,
3423 doc: /* Returns t if the display DISPLAY supports the save-under feature.
3424 The optional argument DISPLAY specifies which display to ask about.
3425 DISPLAY should be either a frame or a display name (a string).
3426 If omitted or nil, that stands for the selected frame's display. */)
3427 (display)
3428 Lisp_Object display;
3430 return Qnil;
3434 x_pixel_width (f)
3435 register struct frame *f;
3437 return FRAME_PIXEL_WIDTH (f);
3441 x_pixel_height (f)
3442 register struct frame *f;
3444 return FRAME_PIXEL_HEIGHT (f);
3448 x_char_width (f)
3449 register struct frame *f;
3451 return FRAME_COLUMN_WIDTH (f);
3455 x_char_height (f)
3456 register struct frame *f;
3458 return FRAME_LINE_HEIGHT (f);
3462 x_screen_planes (f)
3463 register struct frame *f;
3465 return FRAME_MAC_DISPLAY_INFO (f)->n_planes;
3468 /* Return the display structure for the display named NAME.
3469 Open a new connection if necessary. */
3471 struct mac_display_info *
3472 x_display_info_for_name (name)
3473 Lisp_Object name;
3475 Lisp_Object names;
3476 struct mac_display_info *dpyinfo;
3478 CHECK_STRING (name);
3480 for (dpyinfo = &one_mac_display_info, names = x_display_name_list;
3481 dpyinfo;
3482 dpyinfo = dpyinfo->next, names = XCDR (names))
3484 Lisp_Object tem;
3485 tem = Fstring_equal (XCAR (XCAR (names)), name);
3486 if (!NILP (tem))
3487 return dpyinfo;
3490 /* Use this general default value to start with. */
3491 Vx_resource_name = Vinvocation_name;
3493 validate_x_resource_name ();
3495 dpyinfo = mac_term_init (name, (unsigned char *) 0,
3496 (char *) SDATA (Vx_resource_name));
3498 if (dpyinfo == 0)
3499 error ("Cannot connect to server %s", SDATA (name));
3501 mac_in_use = 1;
3502 XSETFASTINT (Vwindow_system_version, 3);
3504 return dpyinfo;
3507 #if 0 /* MAC_TODO: implement network support */
3508 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3509 1, 3, 0,
3510 doc: /* Open a connection to a server.
3511 DISPLAY is the name of the display to connect to.
3512 Optional second arg XRM-STRING is a string of resources in xrdb format.
3513 If the optional third arg MUST-SUCCEED is non-nil,
3514 terminate Emacs if we can't open the connection. */)
3515 (display, xrm_string, must_succeed)
3516 Lisp_Object display, xrm_string, must_succeed;
3518 unsigned char *xrm_option;
3519 struct mac_display_info *dpyinfo;
3521 CHECK_STRING (display);
3522 if (! NILP (xrm_string))
3523 CHECK_STRING (xrm_string);
3525 if (! EQ (Vwindow_system, intern ("mac")))
3526 error ("Not using Mac OS");
3528 if (! NILP (xrm_string))
3529 xrm_option = (unsigned char *) SDATA (xrm_string);
3530 else
3531 xrm_option = (unsigned char *) 0;
3533 validate_x_resource_name ();
3535 /* This is what opens the connection and sets x_current_display.
3536 This also initializes many symbols, such as those used for input. */
3537 dpyinfo = mac_term_init (display, xrm_option,
3538 (char *) SDATA (Vx_resource_name));
3540 if (dpyinfo == 0)
3542 if (!NILP (must_succeed))
3543 fatal ("Cannot connect to server %s.\n",
3544 SDATA (display));
3545 else
3546 error ("Cannot connect to server %s", SDATA (display));
3549 mac_in_use = 1;
3551 XSETFASTINT (Vwindow_system_version, 3);
3552 return Qnil;
3555 DEFUN ("x-close-connection", Fx_close_connection,
3556 Sx_close_connection, 1, 1, 0,
3557 doc: /* Close the connection to DISPLAY's server.
3558 For DISPLAY, specify either a frame or a display name (a string).
3559 If DISPLAY is nil, that stands for the selected frame's display. */)
3560 (display)
3561 Lisp_Object display;
3563 struct mac_display_info *dpyinfo = check_x_display_info (display);
3564 int i;
3566 if (dpyinfo->reference_count > 0)
3567 error ("Display still has frames on it");
3569 BLOCK_INPUT;
3570 /* Free the fonts in the font table. */
3571 for (i = 0; i < dpyinfo->n_fonts; i++)
3572 if (dpyinfo->font_table[i].name)
3574 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
3575 xfree (dpyinfo->font_table[i].full_name);
3576 xfree (dpyinfo->font_table[i].name);
3577 x_unload_font (dpyinfo, dpyinfo->font_table[i].font);
3579 x_destroy_all_bitmaps (dpyinfo);
3581 x_delete_display (dpyinfo);
3582 UNBLOCK_INPUT;
3584 return Qnil;
3586 #endif /* 0 */
3588 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
3589 doc: /* Return the list of display names that Emacs has connections to. */)
3592 Lisp_Object tail, result;
3594 result = Qnil;
3595 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
3596 result = Fcons (XCAR (XCAR (tail)), result);
3598 return result;
3601 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
3602 doc: /* If ON is non-nil, report errors as soon as the erring request is made.
3603 If ON is nil, allow buffering of requests.
3604 This is a noop on Mac OS systems.
3605 The optional second argument DISPLAY specifies which display to act on.
3606 DISPLAY should be either a frame or a display name (a string).
3607 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
3608 (on, display)
3609 Lisp_Object display, on;
3611 return Qnil;
3616 /***********************************************************************
3617 Image types
3618 ***********************************************************************/
3620 /* Value is the number of elements of vector VECTOR. */
3622 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
3624 /* List of supported image types. Use define_image_type to add new
3625 types. Use lookup_image_type to find a type for a given symbol. */
3627 static struct image_type *image_types;
3629 /* The symbol `xbm' which is used as the type symbol for XBM images. */
3631 Lisp_Object Qxbm;
3633 /* Keywords. */
3635 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
3636 extern Lisp_Object QCdata, QCtype;
3637 Lisp_Object QCascent, QCmargin, QCrelief;
3638 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
3639 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
3641 /* Other symbols. */
3643 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
3645 /* Time in seconds after which images should be removed from the cache
3646 if not displayed. */
3648 Lisp_Object Vimage_cache_eviction_delay;
3650 /* Function prototypes. */
3652 static void define_image_type P_ ((struct image_type *type));
3653 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
3654 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
3655 static void x_laplace P_ ((struct frame *, struct image *));
3656 static void x_emboss P_ ((struct frame *, struct image *));
3657 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
3658 Lisp_Object));
3661 /* Define a new image type from TYPE. This adds a copy of TYPE to
3662 image_types and adds the symbol *TYPE->type to Vimage_types. */
3664 static void
3665 define_image_type (type)
3666 struct image_type *type;
3668 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
3669 The initialized data segment is read-only. */
3670 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
3671 bcopy (type, p, sizeof *p);
3672 p->next = image_types;
3673 image_types = p;
3674 Vimage_types = Fcons (*p->type, Vimage_types);
3678 /* Look up image type SYMBOL, and return a pointer to its image_type
3679 structure. Value is null if SYMBOL is not a known image type. */
3681 static INLINE struct image_type *
3682 lookup_image_type (symbol)
3683 Lisp_Object symbol;
3685 struct image_type *type;
3687 for (type = image_types; type; type = type->next)
3688 if (EQ (symbol, *type->type))
3689 break;
3691 return type;
3695 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
3696 valid image specification is a list whose car is the symbol
3697 `image', and whose rest is a property list. The property list must
3698 contain a value for key `:type'. That value must be the name of a
3699 supported image type. The rest of the property list depends on the
3700 image type. */
3703 valid_image_p (object)
3704 Lisp_Object object;
3706 int valid_p = 0;
3708 if (IMAGEP (object))
3710 Lisp_Object tem;
3712 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
3713 if (EQ (XCAR (tem), QCtype))
3715 tem = XCDR (tem);
3716 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
3718 struct image_type *type;
3719 type = lookup_image_type (XCAR (tem));
3720 if (type)
3721 valid_p = type->valid_p (object);
3724 break;
3728 return valid_p;
3732 /* Log error message with format string FORMAT and argument ARG.
3733 Signaling an error, e.g. when an image cannot be loaded, is not a
3734 good idea because this would interrupt redisplay, and the error
3735 message display would lead to another redisplay. This function
3736 therefore simply displays a message. */
3738 static void
3739 image_error (format, arg1, arg2)
3740 char *format;
3741 Lisp_Object arg1, arg2;
3743 add_to_log (format, arg1, arg2);
3748 /***********************************************************************
3749 Image specifications
3750 ***********************************************************************/
3752 enum image_value_type
3754 IMAGE_DONT_CHECK_VALUE_TYPE,
3755 IMAGE_STRING_VALUE,
3756 IMAGE_STRING_OR_NIL_VALUE,
3757 IMAGE_SYMBOL_VALUE,
3758 IMAGE_POSITIVE_INTEGER_VALUE,
3759 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
3760 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
3761 IMAGE_ASCENT_VALUE,
3762 IMAGE_INTEGER_VALUE,
3763 IMAGE_FUNCTION_VALUE,
3764 IMAGE_NUMBER_VALUE,
3765 IMAGE_BOOL_VALUE
3768 /* Structure used when parsing image specifications. */
3770 struct image_keyword
3772 /* Name of keyword. */
3773 char *name;
3775 /* The type of value allowed. */
3776 enum image_value_type type;
3778 /* Non-zero means key must be present. */
3779 int mandatory_p;
3781 /* Used to recognize duplicate keywords in a property list. */
3782 int count;
3784 /* The value that was found. */
3785 Lisp_Object value;
3789 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
3790 int, Lisp_Object));
3791 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
3794 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
3795 has the format (image KEYWORD VALUE ...). One of the keyword/
3796 value pairs must be `:type TYPE'. KEYWORDS is a vector of
3797 image_keywords structures of size NKEYWORDS describing other
3798 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
3800 static int
3801 parse_image_spec (spec, keywords, nkeywords, type)
3802 Lisp_Object spec;
3803 struct image_keyword *keywords;
3804 int nkeywords;
3805 Lisp_Object type;
3807 int i;
3808 Lisp_Object plist;
3810 if (!IMAGEP (spec))
3811 return 0;
3813 plist = XCDR (spec);
3814 while (CONSP (plist))
3816 Lisp_Object key, value;
3818 /* First element of a pair must be a symbol. */
3819 key = XCAR (plist);
3820 plist = XCDR (plist);
3821 if (!SYMBOLP (key))
3822 return 0;
3824 /* There must follow a value. */
3825 if (!CONSP (plist))
3826 return 0;
3827 value = XCAR (plist);
3828 plist = XCDR (plist);
3830 /* Find key in KEYWORDS. Error if not found. */
3831 for (i = 0; i < nkeywords; ++i)
3832 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
3833 break;
3835 if (i == nkeywords)
3836 continue;
3838 /* Record that we recognized the keyword. If a keywords
3839 was found more than once, it's an error. */
3840 keywords[i].value = value;
3841 ++keywords[i].count;
3843 if (keywords[i].count > 1)
3844 return 0;
3846 /* Check type of value against allowed type. */
3847 switch (keywords[i].type)
3849 case IMAGE_STRING_VALUE:
3850 if (!STRINGP (value))
3851 return 0;
3852 break;
3854 case IMAGE_STRING_OR_NIL_VALUE:
3855 if (!STRINGP (value) && !NILP (value))
3856 return 0;
3857 break;
3859 case IMAGE_SYMBOL_VALUE:
3860 if (!SYMBOLP (value))
3861 return 0;
3862 break;
3864 case IMAGE_POSITIVE_INTEGER_VALUE:
3865 if (!INTEGERP (value) || XINT (value) <= 0)
3866 return 0;
3867 break;
3869 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
3870 if (INTEGERP (value) && XINT (value) >= 0)
3871 break;
3872 if (CONSP (value)
3873 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
3874 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
3875 break;
3876 return 0;
3878 case IMAGE_ASCENT_VALUE:
3879 if (SYMBOLP (value) && EQ (value, Qcenter))
3880 break;
3881 else if (INTEGERP (value)
3882 && XINT (value) >= 0
3883 && XINT (value) <= 100)
3884 break;
3885 return 0;
3887 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
3888 if (!INTEGERP (value) || XINT (value) < 0)
3889 return 0;
3890 break;
3892 case IMAGE_DONT_CHECK_VALUE_TYPE:
3893 break;
3895 case IMAGE_FUNCTION_VALUE:
3896 value = indirect_function (value);
3897 if (SUBRP (value)
3898 || COMPILEDP (value)
3899 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
3900 break;
3901 return 0;
3903 case IMAGE_NUMBER_VALUE:
3904 if (!INTEGERP (value) && !FLOATP (value))
3905 return 0;
3906 break;
3908 case IMAGE_INTEGER_VALUE:
3909 if (!INTEGERP (value))
3910 return 0;
3911 break;
3913 case IMAGE_BOOL_VALUE:
3914 if (!NILP (value) && !EQ (value, Qt))
3915 return 0;
3916 break;
3918 default:
3919 abort ();
3920 break;
3923 if (EQ (key, QCtype) && !EQ (type, value))
3924 return 0;
3927 /* Check that all mandatory fields are present. */
3928 for (i = 0; i < nkeywords; ++i)
3929 if (keywords[i].mandatory_p && keywords[i].count == 0)
3930 return 0;
3932 return NILP (plist);
3936 /* Return the value of KEY in image specification SPEC. Value is nil
3937 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
3938 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
3940 static Lisp_Object
3941 image_spec_value (spec, key, found)
3942 Lisp_Object spec, key;
3943 int *found;
3945 Lisp_Object tail;
3947 xassert (valid_image_p (spec));
3949 for (tail = XCDR (spec);
3950 CONSP (tail) && CONSP (XCDR (tail));
3951 tail = XCDR (XCDR (tail)))
3953 if (EQ (XCAR (tail), key))
3955 if (found)
3956 *found = 1;
3957 return XCAR (XCDR (tail));
3961 if (found)
3962 *found = 0;
3963 return Qnil;
3967 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
3968 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
3969 PIXELS non-nil means return the size in pixels, otherwise return the
3970 size in canonical character units.
3971 FRAME is the frame on which the image will be displayed. FRAME nil
3972 or omitted means use the selected frame. */)
3973 (spec, pixels, frame)
3974 Lisp_Object spec, pixels, frame;
3976 Lisp_Object size;
3978 size = Qnil;
3979 if (valid_image_p (spec))
3981 struct frame *f = check_x_frame (frame);
3982 int id = lookup_image (f, spec);
3983 struct image *img = IMAGE_FROM_ID (f, id);
3984 int width = img->width + 2 * img->hmargin;
3985 int height = img->height + 2 * img->vmargin;
3987 if (NILP (pixels))
3988 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
3989 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
3990 else
3991 size = Fcons (make_number (width), make_number (height));
3993 else
3994 error ("Invalid image specification");
3996 return size;
4000 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
4001 doc: /* Return t if image SPEC has a mask bitmap.
4002 FRAME is the frame on which the image will be displayed. FRAME nil
4003 or omitted means use the selected frame. */)
4004 (spec, frame)
4005 Lisp_Object spec, frame;
4007 Lisp_Object mask;
4009 mask = Qnil;
4010 if (valid_image_p (spec))
4012 struct frame *f = check_x_frame (frame);
4013 int id = lookup_image (f, spec);
4014 struct image *img = IMAGE_FROM_ID (f, id);
4015 if (img->mask)
4016 mask = Qt;
4018 else
4019 error ("Invalid image specification");
4021 return mask;
4026 /***********************************************************************
4027 Image type independent image structures
4028 ***********************************************************************/
4030 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
4031 static void free_image P_ ((struct frame *f, struct image *img));
4034 /* Allocate and return a new image structure for image specification
4035 SPEC. SPEC has a hash value of HASH. */
4037 static struct image *
4038 make_image (spec, hash)
4039 Lisp_Object spec;
4040 unsigned hash;
4042 struct image *img = (struct image *) xmalloc (sizeof *img);
4044 xassert (valid_image_p (spec));
4045 bzero (img, sizeof *img);
4046 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
4047 xassert (img->type != NULL);
4048 img->spec = spec;
4049 img->data.lisp_val = Qnil;
4050 img->ascent = DEFAULT_IMAGE_ASCENT;
4051 img->hash = hash;
4052 return img;
4056 /* Free image IMG which was used on frame F, including its resources. */
4058 static void
4059 free_image (f, img)
4060 struct frame *f;
4061 struct image *img;
4063 if (img)
4065 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4067 /* Remove IMG from the hash table of its cache. */
4068 if (img->prev)
4069 img->prev->next = img->next;
4070 else
4071 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
4073 if (img->next)
4074 img->next->prev = img->prev;
4076 c->images[img->id] = NULL;
4078 /* Free resources, then free IMG. */
4079 img->type->free (f, img);
4080 xfree (img);
4085 /* Prepare image IMG for display on frame F. Must be called before
4086 drawing an image. */
4088 void
4089 prepare_image_for_display (f, img)
4090 struct frame *f;
4091 struct image *img;
4093 EMACS_TIME t;
4095 /* We're about to display IMG, so set its timestamp to `now'. */
4096 EMACS_GET_TIME (t);
4097 img->timestamp = EMACS_SECS (t);
4099 /* If IMG doesn't have a pixmap yet, load it now, using the image
4100 type dependent loader function. */
4101 if (img->pixmap == 0 && !img->load_failed_p)
4102 img->load_failed_p = img->type->load (f, img) == 0;
4106 /* Value is the number of pixels for the ascent of image IMG when
4107 drawn in face FACE. */
4110 image_ascent (img, face)
4111 struct image *img;
4112 struct face *face;
4114 int height = img->height + img->vmargin;
4115 int ascent;
4117 if (img->ascent == CENTERED_IMAGE_ASCENT)
4119 if (face->font)
4120 /* This expression is arranged so that if the image can't be
4121 exactly centered, it will be moved slightly up. This is
4122 because a typical font is `top-heavy' (due to the presence
4123 uppercase letters), so the image placement should err towards
4124 being top-heavy too. It also just generally looks better. */
4125 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
4126 else
4127 ascent = height / 2;
4129 else
4130 ascent = height * img->ascent / 100.0;
4132 return ascent;
4136 /* Image background colors. */
4138 static unsigned long
4139 four_corners_best (ximg, width, height)
4140 XImagePtr ximg;
4141 unsigned long width, height;
4143 unsigned long corners[4], best;
4144 int i, best_count;
4146 /* Get the colors at the corners of ximg. */
4147 corners[0] = XGetPixel (ximg, 0, 0);
4148 corners[1] = XGetPixel (ximg, width - 1, 0);
4149 corners[2] = XGetPixel (ximg, width - 1, height - 1);
4150 corners[3] = XGetPixel (ximg, 0, height - 1);
4152 /* Choose the most frequently found color as background. */
4153 for (i = best_count = 0; i < 4; ++i)
4155 int j, n;
4157 for (j = n = 0; j < 4; ++j)
4158 if (corners[i] == corners[j])
4159 ++n;
4161 if (n > best_count)
4162 best = corners[i], best_count = n;
4165 return best;
4168 /* Return the `background' field of IMG. If IMG doesn't have one yet,
4169 it is guessed heuristically. If non-zero, XIMG is an existing XImage
4170 object to use for the heuristic. */
4172 unsigned long
4173 image_background (img, f, ximg)
4174 struct image *img;
4175 struct frame *f;
4176 XImagePtr ximg;
4178 if (! img->background_valid)
4179 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4181 int free_ximg = !ximg;
4183 if (! ximg)
4184 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4185 0, 0, img->width, img->height, ~0, ZPixmap);
4187 img->background = four_corners_best (ximg, img->width, img->height);
4189 if (free_ximg)
4190 XDestroyImage (ximg);
4192 img->background_valid = 1;
4195 return img->background;
4198 /* Return the `background_transparent' field of IMG. If IMG doesn't
4199 have one yet, it is guessed heuristically. If non-zero, MASK is an
4200 existing XImage object to use for the heuristic. */
4203 image_background_transparent (img, f, mask)
4204 struct image *img;
4205 struct frame *f;
4206 XImagePtr mask;
4208 if (! img->background_transparent_valid)
4209 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4211 if (img->mask)
4213 int free_mask = !mask;
4215 if (! mask)
4216 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
4217 0, 0, img->width, img->height, ~0, ZPixmap);
4219 img->background_transparent
4220 = four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN (f);
4222 if (free_mask)
4223 XDestroyImage (mask);
4225 else
4226 img->background_transparent = 0;
4228 img->background_transparent_valid = 1;
4231 return img->background_transparent;
4235 /***********************************************************************
4236 Helper functions for X image types
4237 ***********************************************************************/
4239 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
4240 int, int));
4241 static void x_clear_image P_ ((struct frame *f, struct image *img));
4242 static unsigned long x_alloc_image_color P_ ((struct frame *f,
4243 struct image *img,
4244 Lisp_Object color_name,
4245 unsigned long dflt));
4248 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
4249 free the pixmap if any. MASK_P non-zero means clear the mask
4250 pixmap if any. COLORS_P non-zero means free colors allocated for
4251 the image, if any. */
4253 static void
4254 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
4255 struct frame *f;
4256 struct image *img;
4257 int pixmap_p, mask_p, colors_p;
4259 if (pixmap_p && img->pixmap)
4261 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
4262 img->pixmap = NULL;
4263 img->background_valid = 0;
4266 if (mask_p && img->mask)
4268 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
4269 img->mask = NULL;
4270 img->background_transparent_valid = 0;
4273 if (colors_p && img->ncolors)
4275 #if 0 /* TODO: color table support. */
4276 x_free_colors (f, img->colors, img->ncolors);
4277 #endif
4278 xfree (img->colors);
4279 img->colors = NULL;
4280 img->ncolors = 0;
4284 /* Free X resources of image IMG which is used on frame F. */
4286 static void
4287 x_clear_image (f, img)
4288 struct frame *f;
4289 struct image *img;
4291 BLOCK_INPUT;
4292 x_clear_image_1 (f, img, 1, 1, 1);
4293 UNBLOCK_INPUT;
4297 /* Allocate color COLOR_NAME for image IMG on frame F. If color
4298 cannot be allocated, use DFLT. Add a newly allocated color to
4299 IMG->colors, so that it can be freed again. Value is the pixel
4300 color. */
4302 static unsigned long
4303 x_alloc_image_color (f, img, color_name, dflt)
4304 struct frame *f;
4305 struct image *img;
4306 Lisp_Object color_name;
4307 unsigned long dflt;
4309 XColor color;
4310 unsigned long result;
4312 xassert (STRINGP (color_name));
4314 if (mac_defined_color (f, SDATA (color_name), &color, 1))
4316 /* This isn't called frequently so we get away with simply
4317 reallocating the color vector to the needed size, here. */
4318 ++img->ncolors;
4319 img->colors =
4320 (unsigned long *) xrealloc (img->colors,
4321 img->ncolors * sizeof *img->colors);
4322 img->colors[img->ncolors - 1] = color.pixel;
4323 result = color.pixel;
4325 else
4326 result = dflt;
4328 return result;
4333 /***********************************************************************
4334 Image Cache
4335 ***********************************************************************/
4337 static void cache_image P_ ((struct frame *f, struct image *img));
4338 static void postprocess_image P_ ((struct frame *, struct image *));
4341 /* Return a new, initialized image cache that is allocated from the
4342 heap. Call free_image_cache to free an image cache. */
4344 struct image_cache *
4345 make_image_cache ()
4347 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
4348 int size;
4350 bzero (c, sizeof *c);
4351 c->size = 50;
4352 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
4353 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4354 c->buckets = (struct image **) xmalloc (size);
4355 bzero (c->buckets, size);
4356 return c;
4360 /* Free image cache of frame F. Be aware that X frames share images
4361 caches. */
4363 void
4364 free_image_cache (f)
4365 struct frame *f;
4367 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4368 if (c)
4370 int i;
4372 /* Cache should not be referenced by any frame when freed. */
4373 xassert (c->refcount == 0);
4375 for (i = 0; i < c->used; ++i)
4376 free_image (f, c->images[i]);
4377 xfree (c->images);
4378 xfree (c->buckets);
4379 xfree (c);
4380 FRAME_X_IMAGE_CACHE (f) = NULL;
4385 /* Clear image cache of frame F. FORCE_P non-zero means free all
4386 images. FORCE_P zero means clear only images that haven't been
4387 displayed for some time. Should be called from time to time to
4388 reduce the number of loaded images. If image-eviction-seconds is
4389 non-nil, this frees images in the cache which weren't displayed for
4390 at least that many seconds. */
4392 void
4393 clear_image_cache (f, force_p)
4394 struct frame *f;
4395 int force_p;
4397 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4399 if (c && INTEGERP (Vimage_cache_eviction_delay))
4401 EMACS_TIME t;
4402 unsigned long old;
4403 int i, nfreed;
4405 EMACS_GET_TIME (t);
4406 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
4408 /* Block input so that we won't be interrupted by a SIGIO
4409 while being in an inconsistent state. */
4410 BLOCK_INPUT;
4412 for (i = nfreed = 0; i < c->used; ++i)
4414 struct image *img = c->images[i];
4415 if (img != NULL
4416 && (force_p || img->timestamp < old))
4418 free_image (f, img);
4419 ++nfreed;
4423 /* We may be clearing the image cache because, for example,
4424 Emacs was iconified for a longer period of time. In that
4425 case, current matrices may still contain references to
4426 images freed above. So, clear these matrices. */
4427 if (nfreed)
4429 Lisp_Object tail, frame;
4431 FOR_EACH_FRAME (tail, frame)
4433 struct frame *f = XFRAME (frame);
4434 if (FRAME_MAC_P (f)
4435 && FRAME_X_IMAGE_CACHE (f) == c)
4436 clear_current_matrices (f);
4439 ++windows_or_buffers_changed;
4442 UNBLOCK_INPUT;
4447 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
4448 0, 1, 0,
4449 doc: /* Clear the image cache of FRAME.
4450 FRAME nil or omitted means use the selected frame.
4451 FRAME t means clear the image caches of all frames. */)
4452 (frame)
4453 Lisp_Object frame;
4455 if (EQ (frame, Qt))
4457 Lisp_Object tail;
4459 FOR_EACH_FRAME (tail, frame)
4460 if (FRAME_MAC_P (XFRAME (frame)))
4461 clear_image_cache (XFRAME (frame), 1);
4463 else
4464 clear_image_cache (check_x_frame (frame), 1);
4466 return Qnil;
4470 /* Compute masks and transform image IMG on frame F, as specified
4471 by the image's specification, */
4473 static void
4474 postprocess_image (f, img)
4475 struct frame *f;
4476 struct image *img;
4478 /* Manipulation of the image's mask. */
4479 if (img->pixmap)
4481 Lisp_Object conversion, spec;
4482 Lisp_Object mask;
4484 spec = img->spec;
4486 /* `:heuristic-mask t'
4487 `:mask heuristic'
4488 means build a mask heuristically.
4489 `:heuristic-mask (R G B)'
4490 `:mask (heuristic (R G B))'
4491 means build a mask from color (R G B) in the
4492 image.
4493 `:mask nil'
4494 means remove a mask, if any. */
4496 mask = image_spec_value (spec, QCheuristic_mask, NULL);
4497 if (!NILP (mask))
4498 x_build_heuristic_mask (f, img, mask);
4499 else
4501 int found_p;
4503 mask = image_spec_value (spec, QCmask, &found_p);
4505 if (EQ (mask, Qheuristic))
4506 x_build_heuristic_mask (f, img, Qt);
4507 else if (CONSP (mask)
4508 && EQ (XCAR (mask), Qheuristic))
4510 if (CONSP (XCDR (mask)))
4511 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
4512 else
4513 x_build_heuristic_mask (f, img, XCDR (mask));
4515 else if (NILP (mask) && found_p && img->mask)
4517 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
4518 img->mask = NULL;
4523 /* Should we apply an image transformation algorithm? */
4524 conversion = image_spec_value (spec, QCconversion, NULL);
4525 if (EQ (conversion, Qdisabled))
4526 x_disable_image (f, img);
4527 else if (EQ (conversion, Qlaplace))
4528 x_laplace (f, img);
4529 else if (EQ (conversion, Qemboss))
4530 x_emboss (f, img);
4531 else if (CONSP (conversion)
4532 && EQ (XCAR (conversion), Qedge_detection))
4534 Lisp_Object tem;
4535 tem = XCDR (conversion);
4536 if (CONSP (tem))
4537 x_edge_detection (f, img,
4538 Fplist_get (tem, QCmatrix),
4539 Fplist_get (tem, QCcolor_adjustment));
4545 /* Return the id of image with Lisp specification SPEC on frame F.
4546 SPEC must be a valid Lisp image specification (see valid_image_p). */
4549 lookup_image (f, spec)
4550 struct frame *f;
4551 Lisp_Object spec;
4553 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4554 struct image *img;
4555 int i;
4556 unsigned hash;
4557 struct gcpro gcpro1;
4558 EMACS_TIME now;
4560 /* F must be a window-system frame, and SPEC must be a valid image
4561 specification. */
4562 xassert (FRAME_WINDOW_P (f));
4563 xassert (valid_image_p (spec));
4565 GCPRO1 (spec);
4567 /* Look up SPEC in the hash table of the image cache. */
4568 hash = sxhash (spec, 0);
4569 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
4571 for (img = c->buckets[i]; img; img = img->next)
4572 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
4573 break;
4575 /* If not found, create a new image and cache it. */
4576 if (img == NULL)
4578 extern Lisp_Object Qpostscript;
4580 BLOCK_INPUT;
4581 img = make_image (spec, hash);
4582 cache_image (f, img);
4583 img->load_failed_p = img->type->load (f, img) == 0;
4585 /* If we can't load the image, and we don't have a width and
4586 height, use some arbitrary width and height so that we can
4587 draw a rectangle for it. */
4588 if (img->load_failed_p)
4590 Lisp_Object value;
4592 value = image_spec_value (spec, QCwidth, NULL);
4593 img->width = (INTEGERP (value)
4594 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
4595 value = image_spec_value (spec, QCheight, NULL);
4596 img->height = (INTEGERP (value)
4597 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
4599 else
4601 /* Handle image type independent image attributes
4602 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
4603 `:background COLOR'. */
4604 Lisp_Object ascent, margin, relief, bg;
4606 ascent = image_spec_value (spec, QCascent, NULL);
4607 if (INTEGERP (ascent))
4608 img->ascent = XFASTINT (ascent);
4609 else if (EQ (ascent, Qcenter))
4610 img->ascent = CENTERED_IMAGE_ASCENT;
4612 margin = image_spec_value (spec, QCmargin, NULL);
4613 if (INTEGERP (margin) && XINT (margin) >= 0)
4614 img->vmargin = img->hmargin = XFASTINT (margin);
4615 else if (CONSP (margin) && INTEGERP (XCAR (margin))
4616 && INTEGERP (XCDR (margin)))
4618 if (XINT (XCAR (margin)) > 0)
4619 img->hmargin = XFASTINT (XCAR (margin));
4620 if (XINT (XCDR (margin)) > 0)
4621 img->vmargin = XFASTINT (XCDR (margin));
4624 relief = image_spec_value (spec, QCrelief, NULL);
4625 if (INTEGERP (relief))
4627 img->relief = XINT (relief);
4628 img->hmargin += abs (img->relief);
4629 img->vmargin += abs (img->relief);
4632 if (! img->background_valid)
4634 bg = image_spec_value (img->spec, QCbackground, NULL);
4635 if (!NILP (bg))
4637 img->background
4638 = x_alloc_image_color (f, img, bg,
4639 FRAME_BACKGROUND_PIXEL (f));
4640 img->background_valid = 1;
4644 /* Do image transformations and compute masks, unless we
4645 don't have the image yet. */
4646 if (!EQ (*img->type->type, Qpostscript))
4647 postprocess_image (f, img);
4650 UNBLOCK_INPUT;
4653 /* We're using IMG, so set its timestamp to `now'. */
4654 EMACS_GET_TIME (now);
4655 img->timestamp = EMACS_SECS (now);
4657 UNGCPRO;
4659 /* Value is the image id. */
4660 return img->id;
4664 /* Cache image IMG in the image cache of frame F. */
4666 static void
4667 cache_image (f, img)
4668 struct frame *f;
4669 struct image *img;
4671 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4672 int i;
4674 /* Find a free slot in c->images. */
4675 for (i = 0; i < c->used; ++i)
4676 if (c->images[i] == NULL)
4677 break;
4679 /* If no free slot found, maybe enlarge c->images. */
4680 if (i == c->used && c->used == c->size)
4682 c->size *= 2;
4683 c->images = (struct image **) xrealloc (c->images,
4684 c->size * sizeof *c->images);
4687 /* Add IMG to c->images, and assign IMG an id. */
4688 c->images[i] = img;
4689 img->id = i;
4690 if (i == c->used)
4691 ++c->used;
4693 /* Add IMG to the cache's hash table. */
4694 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
4695 img->next = c->buckets[i];
4696 if (img->next)
4697 img->next->prev = img;
4698 img->prev = NULL;
4699 c->buckets[i] = img;
4703 /* Call FN on every image in the image cache of frame F. Used to mark
4704 Lisp Objects in the image cache. */
4706 void
4707 forall_images_in_image_cache (f, fn)
4708 struct frame *f;
4709 void (*fn) P_ ((struct image *img));
4711 if (FRAME_LIVE_P (f) && FRAME_MAC_P (f))
4713 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4714 if (c)
4716 int i;
4717 for (i = 0; i < c->used; ++i)
4718 if (c->images[i])
4719 fn (c->images[i]);
4726 /***********************************************************************
4727 Mac support code
4728 ***********************************************************************/
4730 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
4731 XImagePtr *, Pixmap *));
4732 static void x_destroy_x_image P_ ((XImagePtr));
4733 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
4736 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
4737 struct frame *f;
4738 int width, height, depth;
4739 XImagePtr *ximg;
4740 Pixmap *pixmap;
4742 Display *display = FRAME_MAC_DISPLAY (f);
4743 Window window = FRAME_MAC_WINDOW (f);
4745 xassert (interrupt_input_blocked);
4747 /* Allocate a pixmap of the same size. */
4748 *pixmap = XCreatePixmap (display, window, width, height, depth);
4749 if (*pixmap == 0)
4751 x_destroy_x_image (*ximg);
4752 *ximg = NULL;
4753 image_error ("Unable to create X pixmap", Qnil, Qnil);
4754 return 0;
4757 LockPixels (GetGWorldPixMap (*pixmap));
4758 *ximg = *pixmap;
4759 return 1;
4762 static void
4763 x_destroy_x_image (ximg)
4764 XImagePtr ximg;
4766 xassert (interrupt_input_blocked);
4767 if (ximg)
4768 XDestroyImage (ximg);
4771 static void
4772 x_put_x_image (f, ximg, pixmap, width, height)
4773 struct frame *f;
4774 XImagePtr ximg;
4775 Pixmap pixmap;
4777 xassert (ximg == pixmap);
4782 /***********************************************************************
4783 File Handling
4784 ***********************************************************************/
4786 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
4787 static char *slurp_file P_ ((char *, int *));
4790 /* Find image file FILE. Look in data-directory, then
4791 x-bitmap-file-path. Value is the full name of the file found, or
4792 nil if not found. */
4794 static Lisp_Object
4795 x_find_image_file (file)
4796 Lisp_Object file;
4798 Lisp_Object file_found, search_path;
4799 struct gcpro gcpro1, gcpro2;
4800 int fd;
4802 file_found = Qnil;
4803 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
4804 GCPRO2 (file_found, search_path);
4806 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
4807 fd = openp (search_path, file, Qnil, &file_found, Qnil);
4809 if (fd == -1)
4810 file_found = Qnil;
4811 else
4812 close (fd);
4814 UNGCPRO;
4815 return file_found;
4819 /* Read FILE into memory. Value is a pointer to a buffer allocated
4820 with xmalloc holding FILE's contents. Value is null if an error
4821 occurred. *SIZE is set to the size of the file. */
4823 static char *
4824 slurp_file (file, size)
4825 char *file;
4826 int *size;
4828 FILE *fp = NULL;
4829 char *buf = NULL;
4830 struct stat st;
4832 if (stat (file, &st) == 0
4833 && (fp = fopen (file, "r")) != NULL
4834 && (buf = (char *) xmalloc (st.st_size),
4835 fread (buf, 1, st.st_size, fp) == st.st_size))
4837 *size = st.st_size;
4838 fclose (fp);
4840 else
4842 if (fp)
4843 fclose (fp);
4844 if (buf)
4846 xfree (buf);
4847 buf = NULL;
4851 return buf;
4856 /***********************************************************************
4857 Image Load Functions
4858 ***********************************************************************/
4860 static int image_load_quicktime P_ ((struct frame *, struct image *img,
4861 OSType));
4862 #ifdef MAC_OSX
4863 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
4864 #endif
4867 static OSErr
4868 find_image_fsspec (specified_file, file, fss)
4869 Lisp_Object specified_file, *file;
4870 FSSpec *fss;
4872 #if TARGET_API_MAC_CARBON
4873 FSRef fsr;
4874 #else
4875 Str255 mac_pathname;
4876 #endif
4877 OSErr err;
4879 *file = x_find_image_file (specified_file);
4880 if (!STRINGP (*file))
4881 return fnfErr; /* file or directory not found;
4882 incomplete pathname */
4883 /* Try to open the image file. */
4884 #if TARGET_API_MAC_CARBON
4885 err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
4886 if (err == noErr)
4887 err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
4888 #else
4889 if (posix_to_mac_pathname (SDATA (*file), mac_pathname, MAXPATHLEN+1) == 0)
4890 return fnfErr;
4891 c2pstr (mac_pathname);
4892 err = FSMakeFSSpec (0, 0, mac_pathname, fss);
4893 #endif
4894 return err;
4898 static int
4899 image_load_qt_1 (f, img, type, fss, dh)
4900 struct frame *f;
4901 struct image *img;
4902 OSType type;
4903 FSSpec *fss;
4904 Handle dh;
4906 OSErr err;
4907 GraphicsImportComponent gi;
4908 Rect rect;
4909 int width, height;
4910 short draw_all_pixels;
4911 Lisp_Object specified_bg;
4912 XColor color;
4913 XImagePtr ximg;
4914 RGBColor bg_color;
4916 err = OpenADefaultComponent (GraphicsImporterComponentType,
4917 type, &gi);
4918 if (err != noErr)
4920 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
4921 return 0;
4923 if (dh == NULL)
4925 /* read from file system spec */
4926 err = GraphicsImportSetDataFile (gi, fss);
4927 if (err != noErr)
4929 image_error ("Cannot set fsspec to graphics importer for '%s'",
4930 img->spec, Qnil);
4931 goto error;
4934 else
4936 /* read from data handle */
4937 err = GraphicsImportSetDataHandle (gi, dh);
4938 if (err != noErr)
4940 image_error ("Cannot set data handle to graphics importer for `%s'",
4941 img->spec, Qnil);
4942 goto error;
4945 err = GraphicsImportGetNaturalBounds (gi, &rect);
4946 if (err != noErr)
4948 image_error ("Error reading `%s'", img->spec, Qnil);
4949 goto error;
4951 width = img->width = rect.right - rect.left;
4952 height = img->height = rect.bottom - rect.top;
4953 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
4954 #if 0
4955 /* Don't check the error code here. It may have an undocumented
4956 value -32766. */
4957 if (err != noErr)
4959 image_error ("Error reading `%s'", img->spec, Qnil);
4960 goto error;
4962 #endif
4963 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
4965 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
4966 if (!STRINGP (specified_bg) ||
4967 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
4969 color.pixel = FRAME_BACKGROUND_PIXEL (f);
4970 color.red = RED16_FROM_ULONG (color.pixel);
4971 color.green = GREEN16_FROM_ULONG (color.pixel);
4972 color.blue = BLUE16_FROM_ULONG (color.pixel);
4976 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
4977 goto error;
4978 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
4980 SetGWorld (ximg, NULL);
4981 bg_color.red = color.red;
4982 bg_color.green = color.green;
4983 bg_color.blue = color.blue;
4984 RGBBackColor (&bg_color);
4985 #if TARGET_API_MAC_CARBON
4986 GetPortBounds (ximg, &rect);
4987 EraseRect (&rect);
4988 #else
4989 EraseRect (&(ximg->portRect));
4990 #endif
4992 GraphicsImportSetGWorld (gi, ximg, NULL);
4993 GraphicsImportDraw (gi);
4994 CloseComponent (gi);
4996 /* Maybe fill in the background field while we have ximg handy. */
4997 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4998 IMAGE_BACKGROUND (img, f, ximg);
5000 /* Put the image into the pixmap. */
5001 x_put_x_image (f, ximg, img->pixmap, width, height);
5002 x_destroy_x_image (ximg);
5003 return 1;
5005 error:
5006 CloseComponent (gi);
5007 return 0;
5011 /* Load an image using the QuickTime Graphics Importer.
5012 Note: The alpha channel does not work for PNG images. */
5013 static int
5014 image_load_quicktime (f, img, type)
5015 struct frame *f;
5016 struct image *img;
5017 OSType type;
5019 Lisp_Object specified_file;
5020 Lisp_Object specified_data;
5021 OSErr err;
5023 specified_file = image_spec_value (img->spec, QCfile, NULL);
5024 specified_data = image_spec_value (img->spec, QCdata, NULL);
5026 if (NILP (specified_data))
5028 /* Read from a file */
5029 Lisp_Object file;
5030 FSSpec fss;
5032 err = find_image_fsspec (specified_file, &file, &fss);
5033 if (err != noErr)
5035 if (err == fnfErr)
5036 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5037 else
5038 image_error ("Cannot open `%s'", file, Qnil);
5039 return 0;
5041 return image_load_qt_1 (f, img, type, &fss, NULL);
5043 else
5045 /* Memory source! */
5046 int success_p;
5047 Handle dh;
5049 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
5050 if (err != noErr)
5052 image_error ("Cannot allocate data handle for `%s'",
5053 img->spec, Qnil);
5054 return 0;
5056 success_p = image_load_qt_1 (f, img, type, NULL, dh);
5057 DisposeHandle (dh);
5058 return success_p;
5063 #ifdef MAC_OSX
5064 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
5065 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
5066 So don't use this function directly but determine at runtime
5067 whether it exists. */
5068 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
5069 (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
5070 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
5073 static void
5074 init_image_func_pointer ()
5076 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
5078 MyCGImageCreateWithPNGDataProvider
5079 = (CGImageCreateWithPNGDataProviderProcType)
5080 NSAddressOfSymbol (NSLookupAndBindSymbol
5081 ("_CGImageCreateWithPNGDataProvider"));
5083 else
5084 MyCGImageCreateWithPNGDataProvider = NULL;
5088 static int
5089 image_load_quartz2d (f, img, png_p)
5090 struct frame *f;
5091 struct image *img;
5092 int png_p;
5094 Lisp_Object file, specified_file;
5095 Lisp_Object specified_data, specified_bg;
5096 struct gcpro gcpro1;
5097 CGDataProviderRef source;
5098 CGImageRef image;
5099 int width, height;
5100 XColor color;
5101 XImagePtr ximg = NULL;
5102 CGContextRef context;
5103 CGRect rectangle;
5105 /* Open the file. */
5106 specified_file = image_spec_value (img->spec, QCfile, NULL);
5107 specified_data = image_spec_value (img->spec, QCdata, NULL);
5109 file = Qnil;
5110 GCPRO1 (file);
5112 if (NILP (specified_data))
5114 CFStringRef path;
5115 CFURLRef url;
5117 file = x_find_image_file (specified_file);
5118 if (!STRINGP (file))
5120 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5121 UNGCPRO;
5122 return 0;
5124 path = CFStringCreateWithCString (NULL, SDATA (file),
5125 kCFStringEncodingUTF8);
5126 url = CFURLCreateWithFileSystemPath (NULL, path,
5127 kCFURLPOSIXPathStyle, 0);
5128 CFRelease (path);
5129 source = CGDataProviderCreateWithURL (url);
5130 CFRelease (url);
5132 else
5133 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
5134 SBYTES (specified_data), NULL);
5136 if (png_p)
5137 image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
5138 kCGRenderingIntentDefault);
5139 else
5140 image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
5141 kCGRenderingIntentDefault);
5143 CGDataProviderRelease (source);
5144 if (image == NULL)
5146 UNGCPRO;
5147 image_error ("Error reading image `%s'", img->spec, Qnil);
5148 return 0;
5151 if (png_p)
5153 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
5154 if (!STRINGP (specified_bg) ||
5155 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
5157 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5158 color.red = RED16_FROM_ULONG (color.pixel);
5159 color.green = GREEN16_FROM_ULONG (color.pixel);
5160 color.blue = BLUE16_FROM_ULONG (color.pixel);
5163 width = img->width = CGImageGetWidth (image);
5164 height = img->height = CGImageGetHeight (image);
5165 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
5167 CGImageRelease (image);
5168 UNGCPRO;
5169 return 0;
5171 rectangle = CGRectMake (0, 0, width, height);
5172 QDBeginCGContext (ximg, &context);
5173 if (png_p)
5175 CGContextSetRGBFillColor (context, color.red / 65535.0,
5176 color.green / 65535.0,
5177 color.blue / 65535.0, 1.0);
5178 CGContextFillRect (context, rectangle);
5180 CGContextDrawImage (context, rectangle, image);
5181 QDEndCGContext (ximg, &context);
5182 CGImageRelease (image);
5184 /* Maybe fill in the background field while we have ximg handy. */
5185 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5186 IMAGE_BACKGROUND (img, f, ximg);
5188 /* Put the image into the pixmap. */
5189 x_put_x_image (f, ximg, img->pixmap, width, height);
5190 x_destroy_x_image (ximg);
5191 UNGCPRO;
5192 return 1;
5194 #endif
5198 /***********************************************************************
5199 XBM images
5200 ***********************************************************************/
5202 static int xbm_scan P_ ((char **, char *, char *, int *));
5203 static int xbm_load P_ ((struct frame *f, struct image *img));
5204 static int xbm_load_image P_ ((struct frame *f, struct image *img,
5205 char *, char *));
5206 static int xbm_image_p P_ ((Lisp_Object object));
5207 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
5208 unsigned char **));
5209 static int xbm_file_p P_ ((Lisp_Object));
5212 /* Indices of image specification fields in xbm_format, below. */
5214 enum xbm_keyword_index
5216 XBM_TYPE,
5217 XBM_FILE,
5218 XBM_WIDTH,
5219 XBM_HEIGHT,
5220 XBM_DATA,
5221 XBM_FOREGROUND,
5222 XBM_BACKGROUND,
5223 XBM_ASCENT,
5224 XBM_MARGIN,
5225 XBM_RELIEF,
5226 XBM_ALGORITHM,
5227 XBM_HEURISTIC_MASK,
5228 XBM_MASK,
5229 XBM_LAST
5232 /* Vector of image_keyword structures describing the format
5233 of valid XBM image specifications. */
5235 static struct image_keyword xbm_format[XBM_LAST] =
5237 {":type", IMAGE_SYMBOL_VALUE, 1},
5238 {":file", IMAGE_STRING_VALUE, 0},
5239 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5240 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
5241 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5242 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5243 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
5244 {":ascent", IMAGE_ASCENT_VALUE, 0},
5245 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5246 {":relief", IMAGE_INTEGER_VALUE, 0},
5247 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5248 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5249 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5252 /* Structure describing the image type XBM. */
5254 static struct image_type xbm_type =
5256 &Qxbm,
5257 xbm_image_p,
5258 xbm_load,
5259 x_clear_image,
5260 NULL
5263 /* Tokens returned from xbm_scan. */
5265 enum xbm_token
5267 XBM_TK_IDENT = 256,
5268 XBM_TK_NUMBER
5272 /* Return non-zero if OBJECT is a valid XBM-type image specification.
5273 A valid specification is a list starting with the symbol `image'
5274 The rest of the list is a property list which must contain an
5275 entry `:type xbm..
5277 If the specification specifies a file to load, it must contain
5278 an entry `:file FILENAME' where FILENAME is a string.
5280 If the specification is for a bitmap loaded from memory it must
5281 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
5282 WIDTH and HEIGHT are integers > 0. DATA may be:
5284 1. a string large enough to hold the bitmap data, i.e. it must
5285 have a size >= (WIDTH + 7) / 8 * HEIGHT
5287 2. a bool-vector of size >= WIDTH * HEIGHT
5289 3. a vector of strings or bool-vectors, one for each line of the
5290 bitmap.
5292 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
5293 may not be specified in this case because they are defined in the
5294 XBM file.
5296 Both the file and data forms may contain the additional entries
5297 `:background COLOR' and `:foreground COLOR'. If not present,
5298 foreground and background of the frame on which the image is
5299 displayed is used. */
5301 static int
5302 xbm_image_p (object)
5303 Lisp_Object object;
5305 struct image_keyword kw[XBM_LAST];
5307 bcopy (xbm_format, kw, sizeof kw);
5308 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
5309 return 0;
5311 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
5313 if (kw[XBM_FILE].count)
5315 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5316 return 0;
5318 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
5320 /* In-memory XBM file. */
5321 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
5322 return 0;
5324 else
5326 Lisp_Object data;
5327 int width, height;
5329 /* Entries for `:width', `:height' and `:data' must be present. */
5330 if (!kw[XBM_WIDTH].count
5331 || !kw[XBM_HEIGHT].count
5332 || !kw[XBM_DATA].count)
5333 return 0;
5335 data = kw[XBM_DATA].value;
5336 width = XFASTINT (kw[XBM_WIDTH].value);
5337 height = XFASTINT (kw[XBM_HEIGHT].value);
5339 /* Check type of data, and width and height against contents of
5340 data. */
5341 if (VECTORP (data))
5343 int i;
5345 /* Number of elements of the vector must be >= height. */
5346 if (XVECTOR (data)->size < height)
5347 return 0;
5349 /* Each string or bool-vector in data must be large enough
5350 for one line of the image. */
5351 for (i = 0; i < height; ++i)
5353 Lisp_Object elt = XVECTOR (data)->contents[i];
5355 if (STRINGP (elt))
5357 if (SCHARS (elt)
5358 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
5359 return 0;
5361 else if (BOOL_VECTOR_P (elt))
5363 if (XBOOL_VECTOR (elt)->size < width)
5364 return 0;
5366 else
5367 return 0;
5370 else if (STRINGP (data))
5372 if (SCHARS (data)
5373 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
5374 return 0;
5376 else if (BOOL_VECTOR_P (data))
5378 if (XBOOL_VECTOR (data)->size < width * height)
5379 return 0;
5381 else
5382 return 0;
5385 return 1;
5389 /* Scan a bitmap file. FP is the stream to read from. Value is
5390 either an enumerator from enum xbm_token, or a character for a
5391 single-character token, or 0 at end of file. If scanning an
5392 identifier, store the lexeme of the identifier in SVAL. If
5393 scanning a number, store its value in *IVAL. */
5395 static int
5396 xbm_scan (s, end, sval, ival)
5397 char **s, *end;
5398 char *sval;
5399 int *ival;
5401 int c;
5403 loop:
5405 /* Skip white space. */
5406 while (*s < end && (c = *(*s)++, isspace (c)))
5409 if (*s >= end)
5410 c = 0;
5411 else if (isdigit (c))
5413 int value = 0, digit;
5415 if (c == '0' && *s < end)
5417 c = *(*s)++;
5418 if (c == 'x' || c == 'X')
5420 while (*s < end)
5422 c = *(*s)++;
5423 if (isdigit (c))
5424 digit = c - '0';
5425 else if (c >= 'a' && c <= 'f')
5426 digit = c - 'a' + 10;
5427 else if (c >= 'A' && c <= 'F')
5428 digit = c - 'A' + 10;
5429 else
5430 break;
5431 value = 16 * value + digit;
5434 else if (isdigit (c))
5436 value = c - '0';
5437 while (*s < end
5438 && (c = *(*s)++, isdigit (c)))
5439 value = 8 * value + c - '0';
5442 else
5444 value = c - '0';
5445 while (*s < end
5446 && (c = *(*s)++, isdigit (c)))
5447 value = 10 * value + c - '0';
5450 if (*s < end)
5451 *s = *s - 1;
5452 *ival = value;
5453 c = XBM_TK_NUMBER;
5455 else if (isalpha (c) || c == '_')
5457 *sval++ = c;
5458 while (*s < end
5459 && (c = *(*s)++, (isalnum (c) || c == '_')))
5460 *sval++ = c;
5461 *sval = 0;
5462 if (*s < end)
5463 *s = *s - 1;
5464 c = XBM_TK_IDENT;
5466 else if (c == '/' && **s == '*')
5468 /* C-style comment. */
5469 ++*s;
5470 while (**s && (**s != '*' || *(*s + 1) != '/'))
5471 ++*s;
5472 if (**s)
5474 *s += 2;
5475 goto loop;
5479 return c;
5483 /* Replacement for XReadBitmapFileData which isn't available under old
5484 X versions. CONTENTS is a pointer to a buffer to parse; END is the
5485 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
5486 the image. Return in *DATA the bitmap data allocated with xmalloc.
5487 Value is non-zero if successful. DATA null means just test if
5488 CONTENTS looks like an in-memory XBM file. */
5490 static int
5491 xbm_read_bitmap_data (contents, end, width, height, data)
5492 char *contents, *end;
5493 int *width, *height;
5494 unsigned char **data;
5496 char *s = contents;
5497 char buffer[BUFSIZ];
5498 int padding_p = 0;
5499 int v10 = 0;
5500 int bytes_per_line, i, nbytes;
5501 unsigned char *p;
5502 int value;
5503 int LA1;
5505 #define match() \
5506 LA1 = xbm_scan (&s, end, buffer, &value)
5508 #define expect(TOKEN) \
5509 if (LA1 != (TOKEN)) \
5510 goto failure; \
5511 else \
5512 match ()
5514 #define expect_ident(IDENT) \
5515 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5516 match (); \
5517 else \
5518 goto failure
5520 *width = *height = -1;
5521 if (data)
5522 *data = NULL;
5523 LA1 = xbm_scan (&s, end, buffer, &value);
5525 /* Parse defines for width, height and hot-spots. */
5526 while (LA1 == '#')
5528 match ();
5529 expect_ident ("define");
5530 expect (XBM_TK_IDENT);
5532 if (LA1 == XBM_TK_NUMBER);
5534 char *p = strrchr (buffer, '_');
5535 p = p ? p + 1 : buffer;
5536 if (strcmp (p, "width") == 0)
5537 *width = value;
5538 else if (strcmp (p, "height") == 0)
5539 *height = value;
5541 expect (XBM_TK_NUMBER);
5544 if (*width < 0 || *height < 0)
5545 goto failure;
5546 else if (data == NULL)
5547 goto success;
5549 /* Parse bits. Must start with `static'. */
5550 expect_ident ("static");
5551 if (LA1 == XBM_TK_IDENT)
5553 if (strcmp (buffer, "unsigned") == 0)
5555 match ();
5556 expect_ident ("char");
5558 else if (strcmp (buffer, "short") == 0)
5560 match ();
5561 v10 = 1;
5562 if (*width % 16 && *width % 16 < 9)
5563 padding_p = 1;
5565 else if (strcmp (buffer, "char") == 0)
5566 match ();
5567 else
5568 goto failure;
5570 else
5571 goto failure;
5573 expect (XBM_TK_IDENT);
5574 expect ('[');
5575 expect (']');
5576 expect ('=');
5577 expect ('{');
5579 bytes_per_line = (*width + 7) / 8 + padding_p;
5580 nbytes = bytes_per_line * *height;
5581 p = *data = (char *) xmalloc (nbytes);
5583 if (v10)
5585 for (i = 0; i < nbytes; i += 2)
5587 int val = value;
5588 expect (XBM_TK_NUMBER);
5590 *p++ = val;
5591 if (!padding_p || ((i + 2) % bytes_per_line))
5592 *p++ = value >> 8;
5594 if (LA1 == ',' || LA1 == '}')
5595 match ();
5596 else
5597 goto failure;
5600 else
5602 for (i = 0; i < nbytes; ++i)
5604 int val = value;
5605 expect (XBM_TK_NUMBER);
5607 *p++ = val;
5609 if (LA1 == ',' || LA1 == '}')
5610 match ();
5611 else
5612 goto failure;
5616 success:
5617 return 1;
5619 failure:
5621 if (data && *data)
5623 xfree (*data);
5624 *data = NULL;
5626 return 0;
5628 #undef match
5629 #undef expect
5630 #undef expect_ident
5634 /* Load XBM image IMG which will be displayed on frame F from buffer
5635 CONTENTS. END is the end of the buffer. Value is non-zero if
5636 successful. */
5638 static int
5639 xbm_load_image (f, img, contents, end)
5640 struct frame *f;
5641 struct image *img;
5642 char *contents, *end;
5644 int rc;
5645 unsigned char *data;
5646 int success_p = 0;
5648 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
5649 if (rc)
5651 int depth = one_mac_display_info.n_planes;
5652 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
5653 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
5654 Lisp_Object value;
5656 xassert (img->width > 0 && img->height > 0);
5658 /* Get foreground and background colors, maybe allocate colors. */
5659 value = image_spec_value (img->spec, QCforeground, NULL);
5660 if (!NILP (value))
5661 foreground = x_alloc_image_color (f, img, value, foreground);
5662 value = image_spec_value (img->spec, QCbackground, NULL);
5663 if (!NILP (value))
5665 background = x_alloc_image_color (f, img, value, background);
5666 img->background = background;
5667 img->background_valid = 1;
5670 img->pixmap
5671 = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
5672 FRAME_MAC_WINDOW (f),
5673 data,
5674 img->width, img->height,
5675 foreground, background,
5676 depth);
5677 xfree (data);
5679 if (img->pixmap == 0)
5681 x_clear_image (f, img);
5682 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
5684 else
5685 success_p = 1;
5687 else
5688 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
5690 return success_p;
5694 /* Value is non-zero if DATA looks like an in-memory XBM file. */
5696 static int
5697 xbm_file_p (data)
5698 Lisp_Object data;
5700 int w, h;
5701 return (STRINGP (data)
5702 && xbm_read_bitmap_data (SDATA (data),
5703 (SDATA (data)
5704 + SBYTES (data)),
5705 &w, &h, NULL));
5709 /* Fill image IMG which is used on frame F with pixmap data. Value is
5710 non-zero if successful. */
5712 static int
5713 xbm_load (f, img)
5714 struct frame *f;
5715 struct image *img;
5717 int success_p = 0;
5718 Lisp_Object file_name;
5720 xassert (xbm_image_p (img->spec));
5722 /* If IMG->spec specifies a file name, create a non-file spec from it. */
5723 file_name = image_spec_value (img->spec, QCfile, NULL);
5724 if (STRINGP (file_name))
5726 Lisp_Object file;
5727 char *contents;
5728 int size;
5729 struct gcpro gcpro1;
5731 file = x_find_image_file (file_name);
5732 GCPRO1 (file);
5733 if (!STRINGP (file))
5735 image_error ("Cannot find image file `%s'", file_name, Qnil);
5736 UNGCPRO;
5737 return 0;
5740 contents = slurp_file (SDATA (file), &size);
5741 if (contents == NULL)
5743 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
5744 UNGCPRO;
5745 return 0;
5748 success_p = xbm_load_image (f, img, contents, contents + size);
5749 UNGCPRO;
5751 else
5753 struct image_keyword fmt[XBM_LAST];
5754 Lisp_Object data;
5755 int depth;
5756 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
5757 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
5758 char *bits;
5759 int parsed_p;
5760 int in_memory_file_p = 0;
5762 /* See if data looks like an in-memory XBM file. */
5763 data = image_spec_value (img->spec, QCdata, NULL);
5764 in_memory_file_p = xbm_file_p (data);
5766 /* Parse the image specification. */
5767 bcopy (xbm_format, fmt, sizeof fmt);
5768 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
5769 xassert (parsed_p);
5771 /* Get specified width, and height. */
5772 if (!in_memory_file_p)
5774 img->width = XFASTINT (fmt[XBM_WIDTH].value);
5775 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
5776 xassert (img->width > 0 && img->height > 0);
5779 /* Get foreground and background colors, maybe allocate colors. */
5780 if (fmt[XBM_FOREGROUND].count
5781 && STRINGP (fmt[XBM_FOREGROUND].value))
5782 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
5783 foreground);
5784 if (fmt[XBM_BACKGROUND].count
5785 && STRINGP (fmt[XBM_BACKGROUND].value))
5786 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
5787 background);
5789 if (in_memory_file_p)
5790 success_p = xbm_load_image (f, img, SDATA (data),
5791 (SDATA (data)
5792 + SBYTES (data)));
5793 else
5795 if (VECTORP (data))
5797 int i;
5798 char *p;
5799 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
5801 p = bits = (char *) alloca (nbytes * img->height);
5802 for (i = 0; i < img->height; ++i, p += nbytes)
5804 Lisp_Object line = XVECTOR (data)->contents[i];
5805 if (STRINGP (line))
5806 bcopy (SDATA (line), p, nbytes);
5807 else
5808 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
5811 else if (STRINGP (data))
5812 bits = SDATA (data);
5813 else
5814 bits = XBOOL_VECTOR (data)->data;
5816 /* Create the pixmap. */
5817 depth = one_mac_display_info.n_planes;
5818 img->pixmap
5819 = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
5820 FRAME_MAC_WINDOW (f),
5821 bits,
5822 img->width, img->height,
5823 foreground, background,
5824 depth);
5825 if (img->pixmap)
5826 success_p = 1;
5827 else
5829 image_error ("Unable to create pixmap for XBM image `%s'",
5830 img->spec, Qnil);
5831 x_clear_image (f, img);
5836 return success_p;
5841 /***********************************************************************
5842 XPM images
5843 ***********************************************************************/
5845 #if HAVE_XPM
5847 static int xpm_image_p P_ ((Lisp_Object object));
5848 static int xpm_load P_ ((struct frame *f, struct image *img));
5849 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
5851 #include "X11/xpm.h"
5853 /* The symbol `xpm' identifying XPM-format images. */
5855 Lisp_Object Qxpm;
5857 /* Indices of image specification fields in xpm_format, below. */
5859 enum xpm_keyword_index
5861 XPM_TYPE,
5862 XPM_FILE,
5863 XPM_DATA,
5864 XPM_ASCENT,
5865 XPM_MARGIN,
5866 XPM_RELIEF,
5867 XPM_ALGORITHM,
5868 XPM_HEURISTIC_MASK,
5869 XPM_MASK,
5870 XPM_COLOR_SYMBOLS,
5871 XPM_BACKGROUND,
5872 XPM_LAST
5875 /* Vector of image_keyword structures describing the format
5876 of valid XPM image specifications. */
5878 static struct image_keyword xpm_format[XPM_LAST] =
5880 {":type", IMAGE_SYMBOL_VALUE, 1},
5881 {":file", IMAGE_STRING_VALUE, 0},
5882 {":data", IMAGE_STRING_VALUE, 0},
5883 {":ascent", IMAGE_ASCENT_VALUE, 0},
5884 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5885 {":relief", IMAGE_INTEGER_VALUE, 0},
5886 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5887 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5888 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5889 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5890 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5893 /* Structure describing the image type XBM. */
5895 static struct image_type xpm_type =
5897 &Qxpm,
5898 xpm_image_p,
5899 xpm_load,
5900 x_clear_image,
5901 NULL
5905 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
5906 for XPM images. Such a list must consist of conses whose car and
5907 cdr are strings. */
5909 static int
5910 xpm_valid_color_symbols_p (color_symbols)
5911 Lisp_Object color_symbols;
5913 while (CONSP (color_symbols))
5915 Lisp_Object sym = XCAR (color_symbols);
5916 if (!CONSP (sym)
5917 || !STRINGP (XCAR (sym))
5918 || !STRINGP (XCDR (sym)))
5919 break;
5920 color_symbols = XCDR (color_symbols);
5923 return NILP (color_symbols);
5927 /* Value is non-zero if OBJECT is a valid XPM image specification. */
5929 static int
5930 xpm_image_p (object)
5931 Lisp_Object object;
5933 struct image_keyword fmt[XPM_LAST];
5934 bcopy (xpm_format, fmt, sizeof fmt);
5935 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
5936 /* Either `:file' or `:data' must be present. */
5937 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
5938 /* Either no `:color-symbols' or it's a list of conses
5939 whose car and cdr are strings. */
5940 && (fmt[XPM_COLOR_SYMBOLS].count == 0
5941 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
5945 /* Load image IMG which will be displayed on frame F. Value is
5946 non-zero if successful. */
5948 static int
5949 xpm_load (f, img)
5950 struct frame *f;
5951 struct image *img;
5953 int rc;
5954 XpmAttributes attrs;
5955 Lisp_Object specified_file, color_symbols;
5957 /* Configure the XPM lib. Use the visual of frame F. Allocate
5958 close colors. Return colors allocated. */
5959 bzero (&attrs, sizeof attrs);
5960 attrs.visual = FRAME_X_VISUAL (f);
5961 attrs.colormap = FRAME_X_COLORMAP (f);
5962 attrs.valuemask |= XpmVisual;
5963 attrs.valuemask |= XpmColormap;
5964 attrs.valuemask |= XpmReturnAllocPixels;
5965 #ifdef XpmAllocCloseColors
5966 attrs.alloc_close_colors = 1;
5967 attrs.valuemask |= XpmAllocCloseColors;
5968 #else /* not XpmAllocCloseColors */
5969 attrs.closeness = 600;
5970 attrs.valuemask |= XpmCloseness;
5971 #endif /* not XpmAllocCloseColors */
5973 /* If image specification contains symbolic color definitions, add
5974 these to `attrs'. */
5975 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
5976 if (CONSP (color_symbols))
5978 Lisp_Object tail;
5979 XpmColorSymbol *xpm_syms;
5980 int i, size;
5982 attrs.valuemask |= XpmColorSymbols;
5984 /* Count number of symbols. */
5985 attrs.numsymbols = 0;
5986 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
5987 ++attrs.numsymbols;
5989 /* Allocate an XpmColorSymbol array. */
5990 size = attrs.numsymbols * sizeof *xpm_syms;
5991 xpm_syms = (XpmColorSymbol *) alloca (size);
5992 bzero (xpm_syms, size);
5993 attrs.colorsymbols = xpm_syms;
5995 /* Fill the color symbol array. */
5996 for (tail = color_symbols, i = 0;
5997 CONSP (tail);
5998 ++i, tail = XCDR (tail))
6000 Lisp_Object name = XCAR (XCAR (tail));
6001 Lisp_Object color = XCDR (XCAR (tail));
6002 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
6003 strcpy (xpm_syms[i].name, SDATA (name));
6004 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
6005 strcpy (xpm_syms[i].value, SDATA (color));
6009 /* Create a pixmap for the image, either from a file, or from a
6010 string buffer containing data in the same format as an XPM file. */
6012 specified_file = image_spec_value (img->spec, QCfile, NULL);
6013 if (STRINGP (specified_file))
6015 Lisp_Object file = x_find_image_file (specified_file);
6016 if (!STRINGP (file))
6018 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6019 return 0;
6022 rc = XpmReadFileToPixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
6023 SDATA (file), &img->pixmap, &img->mask,
6024 &attrs);
6026 else
6028 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
6029 rc = XpmCreatePixmapFromBuffer (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
6030 SDATA (buffer),
6031 &img->pixmap, &img->mask,
6032 &attrs);
6035 if (rc == XpmSuccess)
6037 int i;
6039 img->ncolors = attrs.nalloc_pixels;
6040 img->colors = (unsigned long *) xmalloc (img->ncolors
6041 * sizeof *img->colors);
6042 for (i = 0; i < attrs.nalloc_pixels; ++i)
6043 img->colors[i] = attrs.alloc_pixels[i];
6045 img->width = attrs.width;
6046 img->height = attrs.height;
6047 xassert (img->width > 0 && img->height > 0);
6049 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
6050 XpmFreeAttributes (&attrs);
6052 else
6054 switch (rc)
6056 case XpmOpenFailed:
6057 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
6058 break;
6060 case XpmFileInvalid:
6061 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
6062 break;
6064 case XpmNoMemory:
6065 image_error ("Out of memory (%s)", img->spec, Qnil);
6066 break;
6068 case XpmColorFailed:
6069 image_error ("Color allocation error (%s)", img->spec, Qnil);
6070 break;
6072 default:
6073 image_error ("Unknown error (%s)", img->spec, Qnil);
6074 break;
6078 return rc == XpmSuccess;
6081 #endif /* HAVE_XPM != 0 */
6084 #if 0 /* MAC_TODO : Color tables on Mac. */
6085 /***********************************************************************
6086 Color table
6087 ***********************************************************************/
6089 /* An entry in the color table mapping an RGB color to a pixel color. */
6091 struct ct_color
6093 int r, g, b;
6094 unsigned long pixel;
6096 /* Next in color table collision list. */
6097 struct ct_color *next;
6100 /* The bucket vector size to use. Must be prime. */
6102 #define CT_SIZE 101
6104 /* Value is a hash of the RGB color given by R, G, and B. */
6106 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
6108 /* The color hash table. */
6110 struct ct_color **ct_table;
6112 /* Number of entries in the color table. */
6114 int ct_colors_allocated;
6116 /* Initialize the color table. */
6118 static void
6119 init_color_table ()
6121 int size = CT_SIZE * sizeof (*ct_table);
6122 ct_table = (struct ct_color **) xmalloc (size);
6123 bzero (ct_table, size);
6124 ct_colors_allocated = 0;
6128 /* Free memory associated with the color table. */
6130 static void
6131 free_color_table ()
6133 int i;
6134 struct ct_color *p, *next;
6136 for (i = 0; i < CT_SIZE; ++i)
6137 for (p = ct_table[i]; p; p = next)
6139 next = p->next;
6140 xfree (p);
6143 xfree (ct_table);
6144 ct_table = NULL;
6148 /* Value is a pixel color for RGB color R, G, B on frame F. If an
6149 entry for that color already is in the color table, return the
6150 pixel color of that entry. Otherwise, allocate a new color for R,
6151 G, B, and make an entry in the color table. */
6153 static unsigned long
6154 lookup_rgb_color (f, r, g, b)
6155 struct frame *f;
6156 int r, g, b;
6158 unsigned hash = CT_HASH_RGB (r, g, b);
6159 int i = hash % CT_SIZE;
6160 struct ct_color *p;
6162 for (p = ct_table[i]; p; p = p->next)
6163 if (p->r == r && p->g == g && p->b == b)
6164 break;
6166 if (p == NULL)
6168 COLORREF color;
6169 Colormap cmap;
6170 int rc;
6172 color = RGB_TO_ULONG (r, g, b);
6174 ++ct_colors_allocated;
6176 p = (struct ct_color *) xmalloc (sizeof *p);
6177 p->r = r;
6178 p->g = g;
6179 p->b = b;
6180 p->pixel = color;
6181 p->next = ct_table[i];
6182 ct_table[i] = p;
6185 return p->pixel;
6189 /* Look up pixel color PIXEL which is used on frame F in the color
6190 table. If not already present, allocate it. Value is PIXEL. */
6192 static unsigned long
6193 lookup_pixel_color (f, pixel)
6194 struct frame *f;
6195 unsigned long pixel;
6197 int i = pixel % CT_SIZE;
6198 struct ct_color *p;
6200 for (p = ct_table[i]; p; p = p->next)
6201 if (p->pixel == pixel)
6202 break;
6204 if (p == NULL)
6206 XColor color;
6207 Colormap cmap;
6208 int rc;
6210 BLOCK_INPUT;
6212 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6213 color.pixel = pixel;
6214 XQueryColor (NULL, cmap, &color);
6215 rc = x_alloc_nearest_color (f, cmap, &color);
6216 UNBLOCK_INPUT;
6218 if (rc)
6220 ++ct_colors_allocated;
6222 p = (struct ct_color *) xmalloc (sizeof *p);
6223 p->r = color.red;
6224 p->g = color.green;
6225 p->b = color.blue;
6226 p->pixel = pixel;
6227 p->next = ct_table[i];
6228 ct_table[i] = p;
6230 else
6231 return FRAME_FOREGROUND_PIXEL (f);
6233 return p->pixel;
6237 /* Value is a vector of all pixel colors contained in the color table,
6238 allocated via xmalloc. Set *N to the number of colors. */
6240 static unsigned long *
6241 colors_in_color_table (n)
6242 int *n;
6244 int i, j;
6245 struct ct_color *p;
6246 unsigned long *colors;
6248 if (ct_colors_allocated == 0)
6250 *n = 0;
6251 colors = NULL;
6253 else
6255 colors = (unsigned long *) xmalloc (ct_colors_allocated
6256 * sizeof *colors);
6257 *n = ct_colors_allocated;
6259 for (i = j = 0; i < CT_SIZE; ++i)
6260 for (p = ct_table[i]; p; p = p->next)
6261 colors[j++] = p->pixel;
6264 return colors;
6267 #else
6268 static unsigned long
6269 lookup_rgb_color (f, r, g, b)
6270 struct frame *f;
6271 int r, g, b;
6273 unsigned long pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
6275 gamma_correct (f, &pixel);
6276 return pixel;
6278 #endif /* MAC_TODO */
6281 /***********************************************************************
6282 Algorithms
6283 ***********************************************************************/
6285 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
6286 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
6287 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
6289 /* Non-zero means draw a cross on images having `:conversion
6290 disabled'. */
6292 int cross_disabled_images;
6294 /* Edge detection matrices for different edge-detection
6295 strategies. */
6297 static int emboss_matrix[9] = {
6298 /* x - 1 x x + 1 */
6299 2, -1, 0, /* y - 1 */
6300 -1, 0, 1, /* y */
6301 0, 1, -2 /* y + 1 */
6304 static int laplace_matrix[9] = {
6305 /* x - 1 x x + 1 */
6306 1, 0, 0, /* y - 1 */
6307 0, 0, 0, /* y */
6308 0, 0, -1 /* y + 1 */
6311 /* Value is the intensity of the color whose red/green/blue values
6312 are R, G, and B. */
6314 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
6317 /* On frame F, return an array of XColor structures describing image
6318 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
6319 non-zero means also fill the red/green/blue members of the XColor
6320 structures. Value is a pointer to the array of XColors structures,
6321 allocated with xmalloc; it must be freed by the caller. */
6323 static XColor *
6324 x_to_xcolors (f, img, rgb_p)
6325 struct frame *f;
6326 struct image *img;
6327 int rgb_p;
6329 int x, y;
6330 XColor *colors, *p;
6331 XImagePtr ximg;
6333 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
6335 /* Get the X image IMG->pixmap. */
6336 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
6337 0, 0, img->width, img->height, ~0, ZPixmap);
6339 /* Fill the `pixel' members of the XColor array. I wished there
6340 were an easy and portable way to circumvent XGetPixel. */
6341 p = colors;
6342 for (y = 0; y < img->height; ++y)
6344 XColor *row = p;
6346 for (x = 0; x < img->width; ++x, ++p)
6348 p->pixel = XGetPixel (ximg, x, y);
6350 if (rgb_p)
6352 p->red = RED16_FROM_ULONG (p->pixel);
6353 p->green = GREEN16_FROM_ULONG (p->pixel);
6354 p->blue = BLUE16_FROM_ULONG (p->pixel);
6359 XDestroyImage (ximg);
6360 return colors;
6364 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
6365 RGB members are set. F is the frame on which this all happens.
6366 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
6368 static void
6369 x_from_xcolors (f, img, colors)
6370 struct frame *f;
6371 struct image *img;
6372 XColor *colors;
6374 int x, y;
6375 XImagePtr oimg;
6376 Pixmap pixmap;
6377 XColor *p;
6379 #if 0 /* TODO: color tables. */
6380 init_color_table ();
6381 #endif
6383 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
6384 &oimg, &pixmap);
6385 p = colors;
6386 for (y = 0; y < img->height; ++y)
6387 for (x = 0; x < img->width; ++x, ++p)
6389 unsigned long pixel;
6390 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
6391 XPutPixel (oimg, x, y, pixel);
6394 xfree (colors);
6395 x_clear_image_1 (f, img, 1, 0, 1);
6397 x_put_x_image (f, oimg, pixmap, img->width, img->height);
6398 x_destroy_x_image (oimg);
6399 img->pixmap = pixmap;
6400 #if 0 /* TODO: color tables. */
6401 img->colors = colors_in_color_table (&img->ncolors);
6402 free_color_table ();
6403 #endif
6407 /* On frame F, perform edge-detection on image IMG.
6409 MATRIX is a nine-element array specifying the transformation
6410 matrix. See emboss_matrix for an example.
6412 COLOR_ADJUST is a color adjustment added to each pixel of the
6413 outgoing image. */
6415 static void
6416 x_detect_edges (f, img, matrix, color_adjust)
6417 struct frame *f;
6418 struct image *img;
6419 int matrix[9], color_adjust;
6421 XColor *colors = x_to_xcolors (f, img, 1);
6422 XColor *new, *p;
6423 int x, y, i, sum;
6425 for (i = sum = 0; i < 9; ++i)
6426 sum += abs (matrix[i]);
6428 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
6430 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
6432 for (y = 0; y < img->height; ++y)
6434 p = COLOR (new, 0, y);
6435 p->red = p->green = p->blue = 0xffff/2;
6436 p = COLOR (new, img->width - 1, y);
6437 p->red = p->green = p->blue = 0xffff/2;
6440 for (x = 1; x < img->width - 1; ++x)
6442 p = COLOR (new, x, 0);
6443 p->red = p->green = p->blue = 0xffff/2;
6444 p = COLOR (new, x, img->height - 1);
6445 p->red = p->green = p->blue = 0xffff/2;
6448 for (y = 1; y < img->height - 1; ++y)
6450 p = COLOR (new, 1, y);
6452 for (x = 1; x < img->width - 1; ++x, ++p)
6454 int r, g, b, y1, x1;
6456 r = g = b = i = 0;
6457 for (y1 = y - 1; y1 < y + 2; ++y1)
6458 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
6459 if (matrix[i])
6461 XColor *t = COLOR (colors, x1, y1);
6462 r += matrix[i] * t->red;
6463 g += matrix[i] * t->green;
6464 b += matrix[i] * t->blue;
6467 r = (r / sum + color_adjust) & 0xffff;
6468 g = (g / sum + color_adjust) & 0xffff;
6469 b = (b / sum + color_adjust) & 0xffff;
6470 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
6474 xfree (colors);
6475 x_from_xcolors (f, img, new);
6477 #undef COLOR
6481 /* Perform the pre-defined `emboss' edge-detection on image IMG
6482 on frame F. */
6484 static void
6485 x_emboss (f, img)
6486 struct frame *f;
6487 struct image *img;
6489 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
6493 /* Perform the pre-defined `laplace' edge-detection on image IMG
6494 on frame F. */
6496 static void
6497 x_laplace (f, img)
6498 struct frame *f;
6499 struct image *img;
6501 x_detect_edges (f, img, laplace_matrix, 45000);
6505 /* Perform edge-detection on image IMG on frame F, with specified
6506 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
6508 MATRIX must be either
6510 - a list of at least 9 numbers in row-major form
6511 - a vector of at least 9 numbers
6513 COLOR_ADJUST nil means use a default; otherwise it must be a
6514 number. */
6516 static void
6517 x_edge_detection (f, img, matrix, color_adjust)
6518 struct frame *f;
6519 struct image *img;
6520 Lisp_Object matrix, color_adjust;
6522 int i = 0;
6523 int trans[9];
6525 if (CONSP (matrix))
6527 for (i = 0;
6528 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
6529 ++i, matrix = XCDR (matrix))
6530 trans[i] = XFLOATINT (XCAR (matrix));
6532 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
6534 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
6535 trans[i] = XFLOATINT (AREF (matrix, i));
6538 if (NILP (color_adjust))
6539 color_adjust = make_number (0xffff / 2);
6541 if (i == 9 && NUMBERP (color_adjust))
6542 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
6546 /* Transform image IMG on frame F so that it looks disabled. */
6548 static void
6549 x_disable_image (f, img)
6550 struct frame *f;
6551 struct image *img;
6553 struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6555 if (dpyinfo->n_planes >= 2)
6557 /* Color (or grayscale). Convert to gray, and equalize. Just
6558 drawing such images with a stipple can look very odd, so
6559 we're using this method instead. */
6560 XColor *colors = x_to_xcolors (f, img, 1);
6561 XColor *p, *end;
6562 const int h = 15000;
6563 const int l = 30000;
6565 for (p = colors, end = colors + img->width * img->height;
6566 p < end;
6567 ++p)
6569 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
6570 int i2 = (0xffff - h - l) * i / 0xffff + l;
6571 p->red = p->green = p->blue = i2;
6574 x_from_xcolors (f, img, colors);
6577 /* Draw a cross over the disabled image, if we must or if we
6578 should. */
6579 if (dpyinfo->n_planes < 2 || cross_disabled_images)
6581 Display *dpy = FRAME_MAC_DISPLAY (f);
6582 GC gc;
6584 gc = XCreateGC (dpy, NULL /*img->pixmap*/, 0, NULL);
6585 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
6586 mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, 0,
6587 img->width - 1, img->height - 1);
6588 mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, img->height - 1,
6589 img->width - 1, 0);
6590 XFreeGC (dpy, gc);
6592 if (img->mask)
6594 gc = XCreateGC (dpy, NULL /*img->mask*/, 0, NULL);
6595 XSetForeground (dpy, gc, PIX_MASK_DRAW (f));
6596 mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, 0,
6597 img->width - 1, img->height - 1);
6598 mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, img->height - 1,
6599 img->width - 1, 0);
6600 XFreeGC (dpy, gc);
6606 /* Build a mask for image IMG which is used on frame F. FILE is the
6607 name of an image file, for error messages. HOW determines how to
6608 determine the background color of IMG. If it is a list '(R G B)',
6609 with R, G, and B being integers >= 0, take that as the color of the
6610 background. Otherwise, determine the background color of IMG
6611 heuristically. Value is non-zero if successful. */
6613 static int
6614 x_build_heuristic_mask (f, img, how)
6615 struct frame *f;
6616 struct image *img;
6617 Lisp_Object how;
6619 Display *dpy = FRAME_X_DISPLAY (f);
6620 XImagePtr ximg, mask_img;
6621 int x, y, rc, use_img_background;
6622 unsigned long bg = 0;
6624 if (img->mask)
6626 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6627 img->mask = 0;
6628 img->background_transparent_valid = 0;
6631 /* Create an image and pixmap serving as mask. */
6632 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
6633 &mask_img, &img->mask);
6634 if (!rc)
6635 return 0;
6637 /* Get the X image of IMG->pixmap. */
6638 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
6639 ~0, ZPixmap);
6641 /* Determine the background color of ximg. If HOW is `(R G B)'
6642 take that as color. Otherwise, use the image's background color. */
6643 use_img_background = 1;
6645 if (CONSP (how))
6647 int rgb[3], i;
6649 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
6651 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
6652 how = XCDR (how);
6655 if (i == 3 && NILP (how))
6657 char color_name[30];
6658 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
6659 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
6660 use_img_background = 0;
6664 if (use_img_background)
6665 bg = four_corners_best (ximg, img->width, img->height);
6667 /* Set all bits in mask_img to 1 whose color in ximg is different
6668 from the background color bg. */
6669 for (y = 0; y < img->height; ++y)
6670 for (x = 0; x < img->width; ++x)
6671 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
6673 /* Fill in the background_transparent field while we have the mask handy. */
6674 image_background_transparent (img, f, mask_img);
6676 /* Put mask_img into img->mask. */
6677 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6678 x_destroy_x_image (mask_img);
6679 XDestroyImage (ximg);
6681 return 1;
6686 /***********************************************************************
6687 PBM (mono, gray, color)
6688 ***********************************************************************/
6690 static int pbm_image_p P_ ((Lisp_Object object));
6691 static int pbm_load P_ ((struct frame *f, struct image *img));
6692 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
6694 /* The symbol `pbm' identifying images of this type. */
6696 Lisp_Object Qpbm;
6698 /* Indices of image specification fields in gs_format, below. */
6700 enum pbm_keyword_index
6702 PBM_TYPE,
6703 PBM_FILE,
6704 PBM_DATA,
6705 PBM_ASCENT,
6706 PBM_MARGIN,
6707 PBM_RELIEF,
6708 PBM_ALGORITHM,
6709 PBM_HEURISTIC_MASK,
6710 PBM_MASK,
6711 PBM_FOREGROUND,
6712 PBM_BACKGROUND,
6713 PBM_LAST
6716 /* Vector of image_keyword structures describing the format
6717 of valid user-defined image specifications. */
6719 static struct image_keyword pbm_format[PBM_LAST] =
6721 {":type", IMAGE_SYMBOL_VALUE, 1},
6722 {":file", IMAGE_STRING_VALUE, 0},
6723 {":data", IMAGE_STRING_VALUE, 0},
6724 {":ascent", IMAGE_ASCENT_VALUE, 0},
6725 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6726 {":relief", IMAGE_INTEGER_VALUE, 0},
6727 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6728 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6729 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6730 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6731 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6734 /* Structure describing the image type `pbm'. */
6736 static struct image_type pbm_type =
6738 &Qpbm,
6739 pbm_image_p,
6740 pbm_load,
6741 x_clear_image,
6742 NULL
6746 /* Return non-zero if OBJECT is a valid PBM image specification. */
6748 static int
6749 pbm_image_p (object)
6750 Lisp_Object object;
6752 struct image_keyword fmt[PBM_LAST];
6754 bcopy (pbm_format, fmt, sizeof fmt);
6756 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
6757 return 0;
6759 /* Must specify either :data or :file. */
6760 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
6764 /* Scan a decimal number from *S and return it. Advance *S while
6765 reading the number. END is the end of the string. Value is -1 at
6766 end of input. */
6768 static int
6769 pbm_scan_number (s, end)
6770 unsigned char **s, *end;
6772 int c = 0, val = -1;
6774 while (*s < end)
6776 /* Skip white-space. */
6777 while (*s < end && (c = *(*s)++, isspace (c)))
6780 if (c == '#')
6782 /* Skip comment to end of line. */
6783 while (*s < end && (c = *(*s)++, c != '\n'))
6786 else if (isdigit (c))
6788 /* Read decimal number. */
6789 val = c - '0';
6790 while (*s < end && (c = *(*s)++, isdigit (c)))
6791 val = 10 * val + c - '0';
6792 break;
6794 else
6795 break;
6798 return val;
6802 /* Load PBM image IMG for use on frame F. */
6804 static int
6805 pbm_load (f, img)
6806 struct frame *f;
6807 struct image *img;
6809 int raw_p, x, y;
6810 int width, height, max_color_idx = 0;
6811 XImagePtr ximg;
6812 Lisp_Object file, specified_file;
6813 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
6814 struct gcpro gcpro1;
6815 unsigned char *contents = NULL;
6816 unsigned char *end, *p;
6817 int size;
6819 specified_file = image_spec_value (img->spec, QCfile, NULL);
6820 file = Qnil;
6821 GCPRO1 (file);
6823 if (STRINGP (specified_file))
6825 file = x_find_image_file (specified_file);
6826 if (!STRINGP (file))
6828 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6829 UNGCPRO;
6830 return 0;
6833 contents = slurp_file (SDATA (file), &size);
6834 if (contents == NULL)
6836 image_error ("Error reading `%s'", file, Qnil);
6837 UNGCPRO;
6838 return 0;
6841 p = contents;
6842 end = contents + size;
6844 else
6846 Lisp_Object data;
6847 data = image_spec_value (img->spec, QCdata, NULL);
6848 p = SDATA (data);
6849 end = p + SBYTES (data);
6852 /* Check magic number. */
6853 if (end - p < 2 || *p++ != 'P')
6855 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6856 error:
6857 xfree (contents);
6858 UNGCPRO;
6859 return 0;
6862 switch (*p++)
6864 case '1':
6865 raw_p = 0, type = PBM_MONO;
6866 break;
6868 case '2':
6869 raw_p = 0, type = PBM_GRAY;
6870 break;
6872 case '3':
6873 raw_p = 0, type = PBM_COLOR;
6874 break;
6876 case '4':
6877 raw_p = 1, type = PBM_MONO;
6878 break;
6880 case '5':
6881 raw_p = 1, type = PBM_GRAY;
6882 break;
6884 case '6':
6885 raw_p = 1, type = PBM_COLOR;
6886 break;
6888 default:
6889 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6890 goto error;
6893 /* Read width, height, maximum color-component. Characters
6894 starting with `#' up to the end of a line are ignored. */
6895 width = pbm_scan_number (&p, end);
6896 height = pbm_scan_number (&p, end);
6898 if (type != PBM_MONO)
6900 max_color_idx = pbm_scan_number (&p, end);
6901 if (raw_p && max_color_idx > 255)
6902 max_color_idx = 255;
6905 if (width < 0
6906 || height < 0
6907 || (type != PBM_MONO && max_color_idx < 0))
6908 goto error;
6910 if (!x_create_x_image_and_pixmap (f, width, height, 0,
6911 &ximg, &img->pixmap))
6912 goto error;
6914 #if 0 /* TODO: color tables. */
6915 /* Initialize the color hash table. */
6916 init_color_table ();
6917 #endif
6919 if (type == PBM_MONO)
6921 int c = 0, g;
6922 struct image_keyword fmt[PBM_LAST];
6923 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
6924 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
6926 /* Parse the image specification. */
6927 bcopy (pbm_format, fmt, sizeof fmt);
6928 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
6930 /* Get foreground and background colors, maybe allocate colors. */
6931 if (fmt[PBM_FOREGROUND].count
6932 && STRINGP (fmt[PBM_FOREGROUND].value))
6933 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
6934 if (fmt[PBM_BACKGROUND].count
6935 && STRINGP (fmt[PBM_BACKGROUND].value))
6937 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
6938 img->background = bg;
6939 img->background_valid = 1;
6942 for (y = 0; y < height; ++y)
6943 for (x = 0; x < width; ++x)
6945 if (raw_p)
6947 if ((x & 7) == 0)
6948 c = *p++;
6949 g = c & 0x80;
6950 c <<= 1;
6952 else
6953 g = pbm_scan_number (&p, end);
6955 XPutPixel (ximg, x, y, g ? fg : bg);
6958 else
6960 for (y = 0; y < height; ++y)
6961 for (x = 0; x < width; ++x)
6963 int r, g, b;
6965 if (type == PBM_GRAY)
6966 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
6967 else if (raw_p)
6969 r = *p++;
6970 g = *p++;
6971 b = *p++;
6973 else
6975 r = pbm_scan_number (&p, end);
6976 g = pbm_scan_number (&p, end);
6977 b = pbm_scan_number (&p, end);
6980 if (r < 0 || g < 0 || b < 0)
6982 x_destroy_x_image (ximg);
6983 image_error ("Invalid pixel value in image `%s'",
6984 img->spec, Qnil);
6985 goto error;
6988 /* RGB values are now in the range 0..max_color_idx.
6989 Scale this to the range 0..0xffff supported by X. */
6990 r = (double) r * 65535 / max_color_idx;
6991 g = (double) g * 65535 / max_color_idx;
6992 b = (double) b * 65535 / max_color_idx;
6993 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6997 #if 0 /* TODO: color tables. */
6998 /* Store in IMG->colors the colors allocated for the image, and
6999 free the color table. */
7000 img->colors = colors_in_color_table (&img->ncolors);
7001 free_color_table ();
7002 #endif
7004 img->width = width;
7005 img->height = height;
7007 /* Maybe fill in the background field while we have ximg handy. */
7008 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7009 IMAGE_BACKGROUND (img, f, ximg);
7011 /* Put the image into a pixmap. */
7012 x_put_x_image (f, ximg, img->pixmap, width, height);
7013 x_destroy_x_image (ximg);
7015 UNGCPRO;
7016 xfree (contents);
7017 return 1;
7022 /***********************************************************************
7024 ***********************************************************************/
7027 /* Function prototypes. */
7029 static int png_image_p P_ ((Lisp_Object object));
7030 static int png_load P_ ((struct frame *f, struct image *img));
7032 /* The symbol `png' identifying images of this type. */
7034 Lisp_Object Qpng;
7036 /* Indices of image specification fields in png_format, below. */
7038 enum png_keyword_index
7040 PNG_TYPE,
7041 PNG_DATA,
7042 PNG_FILE,
7043 PNG_ASCENT,
7044 PNG_MARGIN,
7045 PNG_RELIEF,
7046 PNG_ALGORITHM,
7047 PNG_HEURISTIC_MASK,
7048 PNG_MASK,
7049 PNG_BACKGROUND,
7050 PNG_LAST
7053 /* Vector of image_keyword structures describing the format
7054 of valid user-defined image specifications. */
7056 static struct image_keyword png_format[PNG_LAST] =
7058 {":type", IMAGE_SYMBOL_VALUE, 1},
7059 {":data", IMAGE_STRING_VALUE, 0},
7060 {":file", IMAGE_STRING_VALUE, 0},
7061 {":ascent", IMAGE_ASCENT_VALUE, 0},
7062 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7063 {":relief", IMAGE_INTEGER_VALUE, 0},
7064 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7065 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7066 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7067 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7070 /* Structure describing the image type `png'. */
7072 static struct image_type png_type =
7074 &Qpng,
7075 png_image_p,
7076 png_load,
7077 x_clear_image,
7078 NULL
7082 /* Return non-zero if OBJECT is a valid PNG image specification. */
7084 static int
7085 png_image_p (object)
7086 Lisp_Object object;
7088 struct image_keyword fmt[PNG_LAST];
7089 bcopy (png_format, fmt, sizeof fmt);
7091 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
7092 return 0;
7094 /* Must specify either the :data or :file keyword. */
7095 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7099 #ifndef HAVE_PNG
7100 static int
7101 png_load (f, img)
7102 struct frame *f;
7103 struct image *img;
7105 #ifdef MAC_OSX
7106 if (MyCGImageCreateWithPNGDataProvider)
7107 return image_load_quartz2d (f, img, 1);
7108 else
7109 #endif
7110 return image_load_quicktime (f, img, kQTFileTypePNG);
7112 #else
7114 #if defined HAVE_LIBPNG_PNG_H
7115 # include <libpng/png.h>
7116 #else
7117 # include <png.h>
7118 #endif
7120 /* Error and warning handlers installed when the PNG library
7121 is initialized. */
7123 static void
7124 my_png_error (png_ptr, msg)
7125 png_struct *png_ptr;
7126 char *msg;
7128 xassert (png_ptr != NULL);
7129 image_error ("PNG error: %s", build_string (msg), Qnil);
7130 longjmp (png_ptr->jmpbuf, 1);
7134 static void
7135 my_png_warning (png_ptr, msg)
7136 png_struct *png_ptr;
7137 char *msg;
7139 xassert (png_ptr != NULL);
7140 image_error ("PNG warning: %s", build_string (msg), Qnil);
7143 /* Memory source for PNG decoding. */
7145 struct png_memory_storage
7147 unsigned char *bytes; /* The data */
7148 size_t len; /* How big is it? */
7149 int index; /* Where are we? */
7153 /* Function set as reader function when reading PNG image from memory.
7154 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
7155 bytes from the input to DATA. */
7157 static void
7158 png_read_from_memory (png_ptr, data, length)
7159 png_structp png_ptr;
7160 png_bytep data;
7161 png_size_t length;
7163 struct png_memory_storage *tbr
7164 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
7166 if (length > tbr->len - tbr->index)
7167 png_error (png_ptr, "Read error");
7169 bcopy (tbr->bytes + tbr->index, data, length);
7170 tbr->index = tbr->index + length;
7173 /* Load PNG image IMG for use on frame F. Value is non-zero if
7174 successful. */
7176 static int
7177 png_load (f, img)
7178 struct frame *f;
7179 struct image *img;
7181 Lisp_Object file, specified_file;
7182 Lisp_Object specified_data;
7183 int x, y, i;
7184 XImagePtr ximg, mask_img = NULL;
7185 struct gcpro gcpro1;
7186 png_struct *png_ptr = NULL;
7187 png_info *info_ptr = NULL, *end_info = NULL;
7188 FILE *volatile fp = NULL;
7189 png_byte sig[8];
7190 png_byte * volatile pixels = NULL;
7191 png_byte ** volatile rows = NULL;
7192 png_uint_32 width, height;
7193 int bit_depth, color_type, interlace_type;
7194 png_byte channels;
7195 png_uint_32 row_bytes;
7196 int transparent_p;
7197 double screen_gamma;
7198 struct png_memory_storage tbr; /* Data to be read */
7200 /* Find out what file to load. */
7201 specified_file = image_spec_value (img->spec, QCfile, NULL);
7202 specified_data = image_spec_value (img->spec, QCdata, NULL);
7203 file = Qnil;
7204 GCPRO1 (file);
7206 if (NILP (specified_data))
7208 file = x_find_image_file (specified_file);
7209 if (!STRINGP (file))
7211 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7212 UNGCPRO;
7213 return 0;
7216 /* Open the image file. */
7217 fp = fopen (SDATA (file), "rb");
7218 if (!fp)
7220 image_error ("Cannot open image file `%s'", file, Qnil);
7221 UNGCPRO;
7222 fclose (fp);
7223 return 0;
7226 /* Check PNG signature. */
7227 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
7228 || !png_check_sig (sig, sizeof sig))
7230 image_error ("Not a PNG file: `%s'", file, Qnil);
7231 UNGCPRO;
7232 fclose (fp);
7233 return 0;
7236 else
7238 /* Read from memory. */
7239 tbr.bytes = SDATA (specified_data);
7240 tbr.len = SBYTES (specified_data);
7241 tbr.index = 0;
7243 /* Check PNG signature. */
7244 if (tbr.len < sizeof sig
7245 || !png_check_sig (tbr.bytes, sizeof sig))
7247 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
7248 UNGCPRO;
7249 return 0;
7252 /* Need to skip past the signature. */
7253 tbr.bytes += sizeof (sig);
7256 /* Initialize read and info structs for PNG lib. */
7257 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
7258 my_png_error, my_png_warning);
7259 if (!png_ptr)
7261 if (fp) fclose (fp);
7262 UNGCPRO;
7263 return 0;
7266 info_ptr = png_create_info_struct (png_ptr);
7267 if (!info_ptr)
7269 png_destroy_read_struct (&png_ptr, NULL, NULL);
7270 if (fp) fclose (fp);
7271 UNGCPRO;
7272 return 0;
7275 end_info = png_create_info_struct (png_ptr);
7276 if (!end_info)
7278 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
7279 if (fp) fclose (fp);
7280 UNGCPRO;
7281 return 0;
7284 /* Set error jump-back. We come back here when the PNG library
7285 detects an error. */
7286 if (setjmp (png_ptr->jmpbuf))
7288 error:
7289 if (png_ptr)
7290 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7291 xfree (pixels);
7292 xfree (rows);
7293 if (fp) fclose (fp);
7294 UNGCPRO;
7295 return 0;
7298 /* Read image info. */
7299 if (!NILP (specified_data))
7300 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
7301 else
7302 png_init_io (png_ptr, fp);
7304 png_set_sig_bytes (png_ptr, sizeof sig);
7305 png_read_info (png_ptr, info_ptr);
7306 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
7307 &interlace_type, NULL, NULL);
7309 /* If image contains simply transparency data, we prefer to
7310 construct a clipping mask. */
7311 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
7312 transparent_p = 1;
7313 else
7314 transparent_p = 0;
7316 /* This function is easier to write if we only have to handle
7317 one data format: RGB or RGBA with 8 bits per channel. Let's
7318 transform other formats into that format. */
7320 /* Strip more than 8 bits per channel. */
7321 if (bit_depth == 16)
7322 png_set_strip_16 (png_ptr);
7324 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
7325 if available. */
7326 png_set_expand (png_ptr);
7328 /* Convert grayscale images to RGB. */
7329 if (color_type == PNG_COLOR_TYPE_GRAY
7330 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7331 png_set_gray_to_rgb (png_ptr);
7333 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
7335 #if 0 /* Avoid double gamma correction for PNG images. */
7336 { /* Tell the PNG lib to handle gamma correction for us. */
7337 int intent;
7338 double image_gamma;
7339 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
7340 if (png_get_sRGB (png_ptr, info_ptr, &intent))
7341 /* The libpng documentation says this is right in this case. */
7342 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7343 else
7344 #endif
7345 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
7346 /* Image contains gamma information. */
7347 png_set_gamma (png_ptr, screen_gamma, image_gamma);
7348 else
7349 /* Use the standard default for the image gamma. */
7350 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7352 #endif /* if 0 */
7354 /* Handle alpha channel by combining the image with a background
7355 color. Do this only if a real alpha channel is supplied. For
7356 simple transparency, we prefer a clipping mask. */
7357 if (!transparent_p)
7359 png_color_16 *image_bg;
7360 Lisp_Object specified_bg
7361 = image_spec_value (img->spec, QCbackground, NULL);
7363 if (STRINGP (specified_bg))
7364 /* The user specified `:background', use that. */
7366 XColor color;
7367 if (mac_defined_color (f, SDATA (specified_bg), &color, 0))
7369 png_color_16 user_bg;
7371 bzero (&user_bg, sizeof user_bg);
7372 user_bg.red = color.red >> 8;
7373 user_bg.green = color.green >> 8;
7374 user_bg.blue = color.blue >> 8;
7376 png_set_background (png_ptr, &user_bg,
7377 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7380 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
7381 /* Image contains a background color with which to
7382 combine the image. */
7383 png_set_background (png_ptr, image_bg,
7384 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
7385 else
7387 /* Image does not contain a background color with which
7388 to combine the image data via an alpha channel. Use
7389 the frame's background instead. */
7390 unsigned long color;
7391 png_color_16 frame_background;
7392 color = FRAME_BACKGROUND_PIXEL (f);
7393 #if 0 /* TODO : Colormap support. */
7394 Colormap cmap;
7396 cmap = FRAME_X_COLORMAP (f);
7397 x_query_color (f, &color);
7398 #endif
7399 bzero (&frame_background, sizeof frame_background);
7400 frame_background.red = RED_FROM_ULONG (color);
7401 frame_background.green = GREEN_FROM_ULONG (color);
7402 frame_background.blue = BLUE_FROM_ULONG (color);
7404 png_set_background (png_ptr, &frame_background,
7405 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7409 /* Update info structure. */
7410 png_read_update_info (png_ptr, info_ptr);
7412 /* Get number of channels. Valid values are 1 for grayscale images
7413 and images with a palette, 2 for grayscale images with transparency
7414 information (alpha channel), 3 for RGB images, and 4 for RGB
7415 images with alpha channel, i.e. RGBA. If conversions above were
7416 sufficient we should only have 3 or 4 channels here. */
7417 channels = png_get_channels (png_ptr, info_ptr);
7418 xassert (channels == 3 || channels == 4);
7420 /* Number of bytes needed for one row of the image. */
7421 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
7423 /* Allocate memory for the image. */
7424 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
7425 rows = (png_byte **) xmalloc (height * sizeof *rows);
7426 for (i = 0; i < height; ++i)
7427 rows[i] = pixels + i * row_bytes;
7429 /* Read the entire image. */
7430 png_read_image (png_ptr, rows);
7431 png_read_end (png_ptr, info_ptr);
7432 if (fp)
7434 fclose (fp);
7435 fp = NULL;
7438 /* Create the X image and pixmap. */
7439 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
7440 &img->pixmap))
7441 goto error;
7443 /* Create an image and pixmap serving as mask if the PNG image
7444 contains an alpha channel. */
7445 if (channels == 4
7446 && !transparent_p
7447 && !x_create_x_image_and_pixmap (f, width, height, 1,
7448 &mask_img, &img->mask))
7450 x_destroy_x_image (ximg);
7451 XFreePixmap (FRAME_MAC_DISPLAY (f), img->pixmap);
7452 img->pixmap = NULL;
7453 goto error;
7456 /* Fill the X image and mask from PNG data. */
7457 #if 0 /* TODO: Color tables. */
7458 init_color_table ();
7459 #endif
7461 for (y = 0; y < height; ++y)
7463 png_byte *p = rows[y];
7465 for (x = 0; x < width; ++x)
7467 unsigned r, g, b;
7469 r = *p++ << 8;
7470 g = *p++ << 8;
7471 b = *p++ << 8;
7472 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
7474 /* An alpha channel, aka mask channel, associates variable
7475 transparency with an image. Where other image formats
7476 support binary transparency---fully transparent or fully
7477 opaque---PNG allows up to 254 levels of partial transparency.
7478 The PNG library implements partial transparency by combining
7479 the image with a specified background color.
7481 I'm not sure how to handle this here nicely: because the
7482 background on which the image is displayed may change, for
7483 real alpha channel support, it would be necessary to create
7484 a new image for each possible background.
7486 What I'm doing now is that a mask is created if we have
7487 boolean transparency information. Otherwise I'm using
7488 the frame's background color to combine the image with. */
7490 if (channels == 4)
7492 if (mask_img)
7493 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
7494 ++p;
7499 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7500 /* Set IMG's background color from the PNG image, unless the user
7501 overrode it. */
7503 png_color_16 *bg;
7504 if (png_get_bKGD (png_ptr, info_ptr, &bg))
7506 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
7507 img->background_valid = 1;
7511 #if 0 /* TODO: Color tables. */
7512 /* Remember colors allocated for this image. */
7513 img->colors = colors_in_color_table (&img->ncolors);
7514 free_color_table ();
7515 #endif
7517 /* Clean up. */
7518 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7519 xfree (rows);
7520 xfree (pixels);
7522 img->width = width;
7523 img->height = height;
7525 /* Maybe fill in the background field while we have ximg handy. */
7526 IMAGE_BACKGROUND (img, f, ximg);
7528 /* Put the image into the pixmap, then free the X image and its buffer. */
7529 x_put_x_image (f, ximg, img->pixmap, width, height);
7530 x_destroy_x_image (ximg);
7532 /* Same for the mask. */
7533 if (mask_img)
7535 /* Fill in the background_transparent field while we have the mask
7536 handy. */
7537 image_background_transparent (img, f, mask_img);
7539 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7540 x_destroy_x_image (mask_img);
7543 UNGCPRO;
7544 return 1;
7547 #endif /* HAVE_PNG */
7551 /***********************************************************************
7552 JPEG
7553 ***********************************************************************/
7555 static int jpeg_image_p P_ ((Lisp_Object object));
7556 static int jpeg_load P_ ((struct frame *f, struct image *img));
7558 /* The symbol `jpeg' identifying images of this type. */
7560 Lisp_Object Qjpeg;
7562 /* Indices of image specification fields in gs_format, below. */
7564 enum jpeg_keyword_index
7566 JPEG_TYPE,
7567 JPEG_DATA,
7568 JPEG_FILE,
7569 JPEG_ASCENT,
7570 JPEG_MARGIN,
7571 JPEG_RELIEF,
7572 JPEG_ALGORITHM,
7573 JPEG_HEURISTIC_MASK,
7574 JPEG_MASK,
7575 JPEG_BACKGROUND,
7576 JPEG_LAST
7579 /* Vector of image_keyword structures describing the format
7580 of valid user-defined image specifications. */
7582 static struct image_keyword jpeg_format[JPEG_LAST] =
7584 {":type", IMAGE_SYMBOL_VALUE, 1},
7585 {":data", IMAGE_STRING_VALUE, 0},
7586 {":file", IMAGE_STRING_VALUE, 0},
7587 {":ascent", IMAGE_ASCENT_VALUE, 0},
7588 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7589 {":relief", IMAGE_INTEGER_VALUE, 0},
7590 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7591 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7592 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7593 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7596 /* Structure describing the image type `jpeg'. */
7598 static struct image_type jpeg_type =
7600 &Qjpeg,
7601 jpeg_image_p,
7602 jpeg_load,
7603 x_clear_image,
7604 NULL
7608 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7610 static int
7611 jpeg_image_p (object)
7612 Lisp_Object object;
7614 struct image_keyword fmt[JPEG_LAST];
7616 bcopy (jpeg_format, fmt, sizeof fmt);
7618 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
7619 return 0;
7621 /* Must specify either the :data or :file keyword. */
7622 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
7626 #ifndef HAVE_JPEG
7627 static int
7628 jpeg_load (f, img)
7629 struct frame *f;
7630 struct image *img;
7632 #ifdef MAC_OSX
7633 return image_load_quartz2d (f, img, 0);
7634 #else
7635 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7636 #endif
7638 #else
7640 /* Work around a warning about HAVE_STDLIB_H being redefined in
7641 jconfig.h. */
7642 #ifdef HAVE_STDLIB_H
7643 #define HAVE_STDLIB_H_1
7644 #undef HAVE_STDLIB_H
7645 #endif /* HAVE_STLIB_H */
7647 #include <jpeglib.h>
7648 #include <jerror.h>
7649 #include <setjmp.h>
7651 #ifdef HAVE_STLIB_H_1
7652 #define HAVE_STDLIB_H 1
7653 #endif
7655 struct my_jpeg_error_mgr
7657 struct jpeg_error_mgr pub;
7658 jmp_buf setjmp_buffer;
7662 static void
7663 my_error_exit (cinfo)
7664 j_common_ptr cinfo;
7666 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7667 longjmp (mgr->setjmp_buffer, 1);
7671 /* Init source method for JPEG data source manager. Called by
7672 jpeg_read_header() before any data is actually read. See
7673 libjpeg.doc from the JPEG lib distribution. */
7675 static void
7676 our_init_source (cinfo)
7677 j_decompress_ptr cinfo;
7682 /* Fill input buffer method for JPEG data source manager. Called
7683 whenever more data is needed. We read the whole image in one step,
7684 so this only adds a fake end of input marker at the end. */
7686 static boolean
7687 our_fill_input_buffer (cinfo)
7688 j_decompress_ptr cinfo;
7690 /* Insert a fake EOI marker. */
7691 struct jpeg_source_mgr *src = cinfo->src;
7692 static JOCTET buffer[2];
7694 buffer[0] = (JOCTET) 0xFF;
7695 buffer[1] = (JOCTET) JPEG_EOI;
7697 src->next_input_byte = buffer;
7698 src->bytes_in_buffer = 2;
7699 return TRUE;
7703 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7704 is the JPEG data source manager. */
7706 static void
7707 our_skip_input_data (cinfo, num_bytes)
7708 j_decompress_ptr cinfo;
7709 long num_bytes;
7711 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7713 if (src)
7715 if (num_bytes > src->bytes_in_buffer)
7716 ERREXIT (cinfo, JERR_INPUT_EOF);
7718 src->bytes_in_buffer -= num_bytes;
7719 src->next_input_byte += num_bytes;
7724 /* Method to terminate data source. Called by
7725 jpeg_finish_decompress() after all data has been processed. */
7727 static void
7728 our_term_source (cinfo)
7729 j_decompress_ptr cinfo;
7734 /* Set up the JPEG lib for reading an image from DATA which contains
7735 LEN bytes. CINFO is the decompression info structure created for
7736 reading the image. */
7738 static void
7739 jpeg_memory_src (cinfo, data, len)
7740 j_decompress_ptr cinfo;
7741 JOCTET *data;
7742 unsigned int len;
7744 struct jpeg_source_mgr *src;
7746 if (cinfo->src == NULL)
7748 /* First time for this JPEG object? */
7749 cinfo->src = (struct jpeg_source_mgr *)
7750 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7751 sizeof (struct jpeg_source_mgr));
7752 src = (struct jpeg_source_mgr *) cinfo->src;
7753 src->next_input_byte = data;
7756 src = (struct jpeg_source_mgr *) cinfo->src;
7757 src->init_source = our_init_source;
7758 src->fill_input_buffer = our_fill_input_buffer;
7759 src->skip_input_data = our_skip_input_data;
7760 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
7761 src->term_source = our_term_source;
7762 src->bytes_in_buffer = len;
7763 src->next_input_byte = data;
7767 /* Load image IMG for use on frame F. Patterned after example.c
7768 from the JPEG lib. */
7770 static int
7771 jpeg_load (f, img)
7772 struct frame *f;
7773 struct image *img;
7775 struct jpeg_decompress_struct cinfo;
7776 struct my_jpeg_error_mgr mgr;
7777 Lisp_Object file, specified_file;
7778 Lisp_Object specified_data;
7779 FILE * volatile fp = NULL;
7780 JSAMPARRAY buffer;
7781 int row_stride, x, y;
7782 XImagePtr ximg = NULL;
7783 int rc;
7784 unsigned long *colors;
7785 int width, height;
7786 struct gcpro gcpro1;
7788 /* Open the JPEG file. */
7789 specified_file = image_spec_value (img->spec, QCfile, NULL);
7790 specified_data = image_spec_value (img->spec, QCdata, NULL);
7791 file = Qnil;
7792 GCPRO1 (file);
7794 if (NILP (specified_data))
7796 file = x_find_image_file (specified_file);
7797 if (!STRINGP (file))
7799 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7800 UNGCPRO;
7801 return 0;
7804 fp = fopen (SDATA (file), "r");
7805 if (fp == NULL)
7807 image_error ("Cannot open `%s'", file, Qnil);
7808 UNGCPRO;
7809 return 0;
7813 /* Customize libjpeg's error handling to call my_error_exit when an
7814 error is detected. This function will perform a longjmp. */
7815 cinfo.err = jpeg_std_error (&mgr.pub);
7816 mgr.pub.error_exit = my_error_exit;
7818 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7820 if (rc == 1)
7822 /* Called from my_error_exit. Display a JPEG error. */
7823 char buffer[JMSG_LENGTH_MAX];
7824 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7825 image_error ("Error reading JPEG image `%s': %s", img->spec,
7826 build_string (buffer));
7829 /* Close the input file and destroy the JPEG object. */
7830 if (fp)
7831 fclose ((FILE *) fp);
7832 jpeg_destroy_decompress (&cinfo);
7834 /* If we already have an XImage, free that. */
7835 x_destroy_x_image (ximg);
7837 /* Free pixmap and colors. */
7838 x_clear_image (f, img);
7840 UNGCPRO;
7841 return 0;
7844 /* Create the JPEG decompression object. Let it read from fp.
7845 Read the JPEG image header. */
7846 jpeg_create_decompress (&cinfo);
7848 if (NILP (specified_data))
7849 jpeg_stdio_src (&cinfo, (FILE *) fp);
7850 else
7851 jpeg_memory_src (&cinfo, SDATA (specified_data),
7852 SBYTES (specified_data));
7854 jpeg_read_header (&cinfo, TRUE);
7856 /* Customize decompression so that color quantization will be used.
7857 Start decompression. */
7858 cinfo.quantize_colors = TRUE;
7859 jpeg_start_decompress (&cinfo);
7860 width = img->width = cinfo.output_width;
7861 height = img->height = cinfo.output_height;
7863 /* Create X image and pixmap. */
7864 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7865 longjmp (mgr.setjmp_buffer, 2);
7867 /* Allocate colors. When color quantization is used,
7868 cinfo.actual_number_of_colors has been set with the number of
7869 colors generated, and cinfo.colormap is a two-dimensional array
7870 of color indices in the range 0..cinfo.actual_number_of_colors.
7871 No more than 255 colors will be generated. */
7873 int i, ir, ig, ib;
7875 if (cinfo.out_color_components > 2)
7876 ir = 0, ig = 1, ib = 2;
7877 else if (cinfo.out_color_components > 1)
7878 ir = 0, ig = 1, ib = 0;
7879 else
7880 ir = 0, ig = 0, ib = 0;
7882 #if 0 /* TODO: Color tables. */
7883 /* Use the color table mechanism because it handles colors that
7884 cannot be allocated nicely. Such colors will be replaced with
7885 a default color, and we don't have to care about which colors
7886 can be freed safely, and which can't. */
7887 init_color_table ();
7888 #endif
7889 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
7890 * sizeof *colors);
7892 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
7894 /* Multiply RGB values with 255 because X expects RGB values
7895 in the range 0..0xffff. */
7896 int r = cinfo.colormap[ir][i] << 8;
7897 int g = cinfo.colormap[ig][i] << 8;
7898 int b = cinfo.colormap[ib][i] << 8;
7899 colors[i] = lookup_rgb_color (f, r, g, b);
7902 #if 0 /* TODO: Color tables. */
7903 /* Remember those colors actually allocated. */
7904 img->colors = colors_in_color_table (&img->ncolors);
7905 free_color_table ();
7906 #endif
7909 /* Read pixels. */
7910 row_stride = width * cinfo.output_components;
7911 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
7912 row_stride, 1);
7913 for (y = 0; y < height; ++y)
7915 jpeg_read_scanlines (&cinfo, buffer, 1);
7916 for (x = 0; x < cinfo.output_width; ++x)
7917 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
7920 /* Clean up. */
7921 jpeg_finish_decompress (&cinfo);
7922 jpeg_destroy_decompress (&cinfo);
7923 if (fp)
7924 fclose ((FILE *) fp);
7926 /* Maybe fill in the background field while we have ximg handy. */
7927 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7928 IMAGE_BACKGROUND (img, f, ximg);
7930 /* Put the image into the pixmap. */
7931 x_put_x_image (f, ximg, img->pixmap, width, height);
7932 x_destroy_x_image (ximg);
7933 UNGCPRO;
7934 return 1;
7937 #endif /* HAVE_JPEG */
7941 /***********************************************************************
7942 TIFF
7943 ***********************************************************************/
7945 static int tiff_image_p P_ ((Lisp_Object object));
7946 static int tiff_load P_ ((struct frame *f, struct image *img));
7948 /* The symbol `tiff' identifying images of this type. */
7950 Lisp_Object Qtiff;
7952 /* Indices of image specification fields in tiff_format, below. */
7954 enum tiff_keyword_index
7956 TIFF_TYPE,
7957 TIFF_DATA,
7958 TIFF_FILE,
7959 TIFF_ASCENT,
7960 TIFF_MARGIN,
7961 TIFF_RELIEF,
7962 TIFF_ALGORITHM,
7963 TIFF_HEURISTIC_MASK,
7964 TIFF_MASK,
7965 TIFF_BACKGROUND,
7966 TIFF_LAST
7969 /* Vector of image_keyword structures describing the format
7970 of valid user-defined image specifications. */
7972 static struct image_keyword tiff_format[TIFF_LAST] =
7974 {":type", IMAGE_SYMBOL_VALUE, 1},
7975 {":data", IMAGE_STRING_VALUE, 0},
7976 {":file", IMAGE_STRING_VALUE, 0},
7977 {":ascent", IMAGE_ASCENT_VALUE, 0},
7978 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7979 {":relief", IMAGE_INTEGER_VALUE, 0},
7980 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7981 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7982 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7983 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7986 /* Structure describing the image type `tiff'. */
7988 static struct image_type tiff_type =
7990 &Qtiff,
7991 tiff_image_p,
7992 tiff_load,
7993 x_clear_image,
7994 NULL
7998 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8000 static int
8001 tiff_image_p (object)
8002 Lisp_Object object;
8004 struct image_keyword fmt[TIFF_LAST];
8005 bcopy (tiff_format, fmt, sizeof fmt);
8007 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
8008 return 0;
8010 /* Must specify either the :data or :file keyword. */
8011 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8014 #ifndef HAVE_TIFF
8016 static int
8017 tiff_load (f, img)
8018 struct frame *f;
8019 struct image *img;
8021 return image_load_quicktime (f, img, kQTFileTypeTIFF);
8024 #else
8026 #include <tiffio.h>
8028 /* Reading from a memory buffer for TIFF images Based on the PNG
8029 memory source, but we have to provide a lot of extra functions.
8030 Blah.
8032 We really only need to implement read and seek, but I am not
8033 convinced that the TIFF library is smart enough not to destroy
8034 itself if we only hand it the function pointers we need to
8035 override. */
8037 typedef struct
8039 unsigned char *bytes;
8040 size_t len;
8041 int index;
8043 tiff_memory_source;
8046 static size_t
8047 tiff_read_from_memory (data, buf, size)
8048 thandle_t data;
8049 tdata_t buf;
8050 tsize_t size;
8052 tiff_memory_source *src = (tiff_memory_source *) data;
8054 if (size > src->len - src->index)
8055 return (size_t) -1;
8056 bcopy (src->bytes + src->index, buf, size);
8057 src->index += size;
8058 return size;
8062 static size_t
8063 tiff_write_from_memory (data, buf, size)
8064 thandle_t data;
8065 tdata_t buf;
8066 tsize_t size;
8068 return (size_t) -1;
8072 static toff_t
8073 tiff_seek_in_memory (data, off, whence)
8074 thandle_t data;
8075 toff_t off;
8076 int whence;
8078 tiff_memory_source *src = (tiff_memory_source *) data;
8079 int idx;
8081 switch (whence)
8083 case SEEK_SET: /* Go from beginning of source. */
8084 idx = off;
8085 break;
8087 case SEEK_END: /* Go from end of source. */
8088 idx = src->len + off;
8089 break;
8091 case SEEK_CUR: /* Go from current position. */
8092 idx = src->index + off;
8093 break;
8095 default: /* Invalid `whence'. */
8096 return -1;
8099 if (idx > src->len || idx < 0)
8100 return -1;
8102 src->index = idx;
8103 return src->index;
8107 static int
8108 tiff_close_memory (data)
8109 thandle_t data;
8111 /* NOOP */
8112 return 0;
8116 static int
8117 tiff_mmap_memory (data, pbase, psize)
8118 thandle_t data;
8119 tdata_t *pbase;
8120 toff_t *psize;
8122 /* It is already _IN_ memory. */
8123 return 0;
8127 static void
8128 tiff_unmap_memory (data, base, size)
8129 thandle_t data;
8130 tdata_t base;
8131 toff_t size;
8133 /* We don't need to do this. */
8137 static toff_t
8138 tiff_size_of_memory (data)
8139 thandle_t data;
8141 return ((tiff_memory_source *) data)->len;
8145 static void
8146 tiff_error_handler (title, format, ap)
8147 const char *title, *format;
8148 va_list ap;
8150 char buf[512];
8151 int len;
8153 len = sprintf (buf, "TIFF error: %s ", title);
8154 vsprintf (buf + len, format, ap);
8155 add_to_log (buf, Qnil, Qnil);
8159 static void
8160 tiff_warning_handler (title, format, ap)
8161 const char *title, *format;
8162 va_list ap;
8164 char buf[512];
8165 int len;
8167 len = sprintf (buf, "TIFF warning: %s ", title);
8168 vsprintf (buf + len, format, ap);
8169 add_to_log (buf, Qnil, Qnil);
8173 /* Load TIFF image IMG for use on frame F. Value is non-zero if
8174 successful. */
8176 static int
8177 tiff_load (f, img)
8178 struct frame *f;
8179 struct image *img;
8181 Lisp_Object file, specified_file;
8182 Lisp_Object specified_data;
8183 TIFF *tiff;
8184 int width, height, x, y;
8185 uint32 *buf;
8186 int rc;
8187 XImagePtr ximg;
8188 struct gcpro gcpro1;
8189 tiff_memory_source memsrc;
8191 specified_file = image_spec_value (img->spec, QCfile, NULL);
8192 specified_data = image_spec_value (img->spec, QCdata, NULL);
8193 file = Qnil;
8194 GCPRO1 (file);
8196 TIFFSetErrorHandler (tiff_error_handler);
8197 TIFFSetWarningHandler (tiff_warning_handler);
8199 if (NILP (specified_data))
8201 /* Read from a file */
8202 file = x_find_image_file (specified_file);
8203 if (!STRINGP (file))
8205 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8206 UNGCPRO;
8207 return 0;
8210 /* Try to open the image file. */
8211 tiff = TIFFOpen (SDATA (file), "r");
8212 if (tiff == NULL)
8214 image_error ("Cannot open `%s'", file, Qnil);
8215 UNGCPRO;
8216 return 0;
8219 else
8221 /* Memory source! */
8222 memsrc.bytes = SDATA (specified_data);
8223 memsrc.len = SBYTES (specified_data);
8224 memsrc.index = 0;
8226 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8227 (TIFFReadWriteProc) tiff_read_from_memory,
8228 (TIFFReadWriteProc) tiff_write_from_memory,
8229 tiff_seek_in_memory,
8230 tiff_close_memory,
8231 tiff_size_of_memory,
8232 tiff_mmap_memory,
8233 tiff_unmap_memory);
8235 if (!tiff)
8237 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
8238 UNGCPRO;
8239 return 0;
8243 /* Get width and height of the image, and allocate a raster buffer
8244 of width x height 32-bit values. */
8245 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8246 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8247 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8249 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
8250 TIFFClose (tiff);
8251 if (!rc)
8253 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8254 xfree (buf);
8255 UNGCPRO;
8256 return 0;
8259 /* Create the X image and pixmap. */
8260 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8262 xfree (buf);
8263 UNGCPRO;
8264 return 0;
8267 #if 0 /* TODO: Color tables. */
8268 /* Initialize the color table. */
8269 init_color_table ();
8270 #endif
8272 /* Process the pixel raster. Origin is in the lower-left corner. */
8273 for (y = 0; y < height; ++y)
8275 uint32 *row = buf + y * width;
8277 for (x = 0; x < width; ++x)
8279 uint32 abgr = row[x];
8280 int r = TIFFGetR (abgr) << 8;
8281 int g = TIFFGetG (abgr) << 8;
8282 int b = TIFFGetB (abgr) << 8;
8283 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8287 #if 0 /* TODO: Color tables. */
8288 /* Remember the colors allocated for the image. Free the color table. */
8289 img->colors = colors_in_color_table (&img->ncolors);
8290 free_color_table ();
8291 #endif
8293 img->width = width;
8294 img->height = height;
8296 /* Maybe fill in the background field while we have ximg handy. */
8297 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8298 IMAGE_BACKGROUND (img, f, ximg);
8300 /* Put the image into the pixmap, then free the X image and its buffer. */
8301 x_put_x_image (f, ximg, img->pixmap, width, height);
8302 x_destroy_x_image (ximg);
8303 xfree (buf);
8305 UNGCPRO;
8306 return 1;
8309 #endif /* HAVE_TIFF */
8313 /***********************************************************************
8315 ***********************************************************************/
8317 static int gif_image_p P_ ((Lisp_Object object));
8318 static int gif_load P_ ((struct frame *f, struct image *img));
8320 /* The symbol `gif' identifying images of this type. */
8322 Lisp_Object Qgif;
8324 /* Indices of image specification fields in gif_format, below. */
8326 enum gif_keyword_index
8328 GIF_TYPE,
8329 GIF_DATA,
8330 GIF_FILE,
8331 GIF_ASCENT,
8332 GIF_MARGIN,
8333 GIF_RELIEF,
8334 GIF_ALGORITHM,
8335 GIF_HEURISTIC_MASK,
8336 GIF_MASK,
8337 GIF_IMAGE,
8338 GIF_BACKGROUND,
8339 GIF_LAST
8342 /* Vector of image_keyword structures describing the format
8343 of valid user-defined image specifications. */
8345 static struct image_keyword gif_format[GIF_LAST] =
8347 {":type", IMAGE_SYMBOL_VALUE, 1},
8348 {":data", IMAGE_STRING_VALUE, 0},
8349 {":file", IMAGE_STRING_VALUE, 0},
8350 {":ascent", IMAGE_ASCENT_VALUE, 0},
8351 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8352 {":relief", IMAGE_INTEGER_VALUE, 0},
8353 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8354 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8355 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8356 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8357 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8360 /* Structure describing the image type `gif'. */
8362 static struct image_type gif_type =
8364 &Qgif,
8365 gif_image_p,
8366 gif_load,
8367 x_clear_image,
8368 NULL
8372 /* Return non-zero if OBJECT is a valid GIF image specification. */
8374 static int
8375 gif_image_p (object)
8376 Lisp_Object object;
8378 struct image_keyword fmt[GIF_LAST];
8379 bcopy (gif_format, fmt, sizeof fmt);
8381 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8382 return 0;
8384 /* Must specify either the :data or :file keyword. */
8385 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8388 #ifndef HAVE_GIF
8390 static int
8391 gif_load (f, img)
8392 struct frame *f;
8393 struct image *img;
8395 Lisp_Object specified_file, file;
8396 Lisp_Object specified_data;
8397 OSErr err;
8398 Boolean graphic_p, movie_p, prefer_graphic_p;
8399 Handle dh = NULL;
8400 Movie movie = NULL;
8401 Lisp_Object image;
8402 Track track = NULL;
8403 Media media = NULL;
8404 long nsamples;
8405 Rect rect;
8406 Lisp_Object specified_bg;
8407 XColor color;
8408 RGBColor bg_color;
8409 int width, height;
8410 XImagePtr ximg;
8411 TimeValue time;
8412 struct gcpro gcpro1;
8413 int ino;
8415 specified_file = image_spec_value (img->spec, QCfile, NULL);
8416 specified_data = image_spec_value (img->spec, QCdata, NULL);
8418 if (NILP (specified_data))
8420 /* Read from a file */
8421 FSSpec fss;
8422 short refnum;
8424 err = find_image_fsspec (specified_file, &file, &fss);
8425 if (err != noErr)
8427 if (err == fnfErr)
8428 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8429 else
8430 goto open_error;
8433 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
8434 &graphic_p, &movie_p, &prefer_graphic_p, 0);
8435 if (err != noErr)
8436 goto open_error;
8438 if (!graphic_p && !movie_p)
8439 goto open_error;
8440 if (prefer_graphic_p)
8441 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
8442 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
8443 if (err != noErr)
8444 goto open_error;
8445 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
8446 CloseMovieFile (refnum);
8447 if (err != noErr)
8449 image_error ("Error reading `%s'", file, Qnil);
8450 return 0;
8453 else
8455 /* Memory source! */
8456 Handle dref = NULL;
8457 long file_type_atom[3];
8459 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
8460 if (err != noErr)
8462 image_error ("Cannot allocate data handle for `%s'",
8463 img->spec, Qnil);
8464 goto error;
8467 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
8468 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
8469 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
8470 err = PtrToHand (&dh, &dref, sizeof (Handle));
8471 if (err == noErr)
8472 /* no file name */
8473 err = PtrAndHand ("\p", dref, 1);
8474 if (err == noErr)
8475 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
8476 if (err != noErr)
8478 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
8479 goto error;
8481 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8482 &movie_p, &prefer_graphic_p, 0);
8483 if (err != noErr)
8484 goto open_error;
8486 if (!graphic_p && !movie_p)
8487 goto open_error;
8488 if (prefer_graphic_p)
8490 int success_p;
8492 DisposeHandle (dref);
8493 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8494 DisposeHandle (dh);
8495 return success_p;
8497 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8498 HandleDataHandlerSubType);
8499 DisposeHandle (dref);
8500 if (err != noErr)
8501 goto open_error;
8504 image = image_spec_value (img->spec, QCindex, NULL);
8505 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8506 track = GetMovieIndTrack (movie, 1);
8507 media = GetTrackMedia (track);
8508 nsamples = GetMediaSampleCount (media);
8509 if (ino >= nsamples)
8511 image_error ("Invalid image number `%s' in image `%s'",
8512 image, img->spec);
8513 goto error;
8516 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8517 if (!STRINGP (specified_bg) ||
8518 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8520 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8521 color.red = RED16_FROM_ULONG (color.pixel);
8522 color.green = GREEN16_FROM_ULONG (color.pixel);
8523 color.blue = BLUE16_FROM_ULONG (color.pixel);
8525 GetMovieBox (movie, &rect);
8526 width = img->width = rect.right - rect.left;
8527 height = img->height = rect.bottom - rect.top;
8528 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8529 goto error;
8531 SetGWorld (ximg, NULL);
8532 bg_color.red = color.red;
8533 bg_color.green = color.green;
8534 bg_color.blue = color.blue;
8535 RGBBackColor (&bg_color);
8536 SetMovieActive (movie, TRUE);
8537 SetMovieGWorld (movie, ximg, NULL);
8538 SampleNumToMediaTime (media, ino + 1, &time, NULL);
8539 SetMovieTimeValue (movie, time);
8540 MoviesTask (movie, 0L);
8541 DisposeTrackMedia (media);
8542 DisposeMovieTrack (track);
8543 DisposeMovie (movie);
8544 if (dh)
8545 DisposeHandle (dh);
8546 /* Maybe fill in the background field while we have ximg handy. */
8547 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8548 IMAGE_BACKGROUND (img, f, ximg);
8550 /* Put the image into the pixmap. */
8551 x_put_x_image (f, ximg, img->pixmap, width, height);
8552 x_destroy_x_image (ximg);
8553 return 1;
8555 open_error:
8556 image_error ("Cannot open `%s'", file, Qnil);
8557 error:
8558 if (media)
8559 DisposeTrackMedia (media);
8560 if (track)
8561 DisposeMovieTrack (track);
8562 if (movie)
8563 DisposeMovie (movie);
8564 if (dh)
8565 DisposeHandle (dh);
8566 return 0;
8569 #else
8571 #define DrawText gif_DrawText /* avoid conflict with QuickdrawText.h */
8572 #include <gif_lib.h>
8573 #undef DrawText
8575 /* Reading a GIF image from memory
8576 Based on the PNG memory stuff to a certain extent. */
8578 typedef struct
8580 unsigned char *bytes;
8581 size_t len;
8582 int index;
8584 gif_memory_source;
8587 /* Make the current memory source available to gif_read_from_memory.
8588 It's done this way because not all versions of libungif support
8589 a UserData field in the GifFileType structure. */
8590 static gif_memory_source *current_gif_memory_src;
8592 static int
8593 gif_read_from_memory (file, buf, len)
8594 GifFileType *file;
8595 GifByteType *buf;
8596 int len;
8598 gif_memory_source *src = current_gif_memory_src;
8600 if (len > src->len - src->index)
8601 return -1;
8603 bcopy (src->bytes + src->index, buf, len);
8604 src->index += len;
8605 return len;
8609 /* Load GIF image IMG for use on frame F. Value is non-zero if
8610 successful. */
8612 static int
8613 gif_load (f, img)
8614 struct frame *f;
8615 struct image *img;
8617 Lisp_Object file, specified_file;
8618 Lisp_Object specified_data;
8619 int rc, width, height, x, y, i;
8620 XImagePtr ximg;
8621 ColorMapObject *gif_color_map;
8622 unsigned long pixel_colors[256];
8623 GifFileType *gif;
8624 struct gcpro gcpro1;
8625 Lisp_Object image;
8626 int ino, image_left, image_top, image_width, image_height;
8627 gif_memory_source memsrc;
8628 unsigned char *raster;
8630 specified_file = image_spec_value (img->spec, QCfile, NULL);
8631 specified_data = image_spec_value (img->spec, QCdata, NULL);
8632 file = Qnil;
8633 GCPRO1 (file);
8635 if (NILP (specified_data))
8637 file = x_find_image_file (specified_file);
8638 if (!STRINGP (file))
8640 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8641 UNGCPRO;
8642 return 0;
8645 /* Open the GIF file. */
8646 gif = DGifOpenFileName (SDATA (file));
8647 if (gif == NULL)
8649 image_error ("Cannot open `%s'", file, Qnil);
8650 UNGCPRO;
8651 return 0;
8654 else
8656 /* Read from memory! */
8657 current_gif_memory_src = &memsrc;
8658 memsrc.bytes = SDATA (specified_data);
8659 memsrc.len = SBYTES (specified_data);
8660 memsrc.index = 0;
8662 gif = DGifOpen (&memsrc, gif_read_from_memory);
8663 if (!gif)
8665 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8666 UNGCPRO;
8667 return 0;
8671 /* Read entire contents. */
8672 rc = DGifSlurp (gif);
8673 if (rc == GIF_ERROR)
8675 image_error ("Error reading `%s'", img->spec, Qnil);
8676 DGifCloseFile (gif);
8677 UNGCPRO;
8678 return 0;
8681 image = image_spec_value (img->spec, QCindex, NULL);
8682 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8683 if (ino >= gif->ImageCount)
8685 image_error ("Invalid image number `%s' in image `%s'",
8686 image, img->spec);
8687 DGifCloseFile (gif);
8688 UNGCPRO;
8689 return 0;
8692 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
8693 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
8695 /* Create the X image and pixmap. */
8696 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8698 DGifCloseFile (gif);
8699 UNGCPRO;
8700 return 0;
8703 /* Allocate colors. */
8704 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8705 if (!gif_color_map)
8706 gif_color_map = gif->SColorMap;
8707 #if 0 /* TODO: Color tables */
8708 init_color_table ();
8709 #endif
8710 bzero (pixel_colors, sizeof pixel_colors);
8712 for (i = 0; i < gif_color_map->ColorCount; ++i)
8714 int r = gif_color_map->Colors[i].Red << 8;
8715 int g = gif_color_map->Colors[i].Green << 8;
8716 int b = gif_color_map->Colors[i].Blue << 8;
8717 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8720 #if 0 /* TODO: Color tables */
8721 img->colors = colors_in_color_table (&img->ncolors);
8722 free_color_table ();
8723 #endif
8725 /* Clear the part of the screen image that are not covered by
8726 the image from the GIF file. Full animated GIF support
8727 requires more than can be done here (see the gif89 spec,
8728 disposal methods). Let's simply assume that the part
8729 not covered by a sub-image is in the frame's background color. */
8730 image_top = gif->SavedImages[ino].ImageDesc.Top;
8731 image_left = gif->SavedImages[ino].ImageDesc.Left;
8732 image_width = gif->SavedImages[ino].ImageDesc.Width;
8733 image_height = gif->SavedImages[ino].ImageDesc.Height;
8735 for (y = 0; y < image_top; ++y)
8736 for (x = 0; x < width; ++x)
8737 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8739 for (y = image_top + image_height; y < height; ++y)
8740 for (x = 0; x < width; ++x)
8741 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8743 for (y = image_top; y < image_top + image_height; ++y)
8745 for (x = 0; x < image_left; ++x)
8746 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8747 for (x = image_left + image_width; x < width; ++x)
8748 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8751 /* Read the GIF image into the X image. We use a local variable
8752 `raster' here because RasterBits below is a char *, and invites
8753 problems with bytes >= 0x80. */
8754 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8756 if (gif->SavedImages[ino].ImageDesc.Interlace)
8758 static int interlace_start[] = {0, 4, 2, 1};
8759 static int interlace_increment[] = {8, 8, 4, 2};
8760 int pass;
8761 int row = interlace_start[0];
8763 pass = 0;
8765 for (y = 0; y < image_height; y++)
8767 if (row >= image_height)
8769 row = interlace_start[++pass];
8770 while (row >= image_height)
8771 row = interlace_start[++pass];
8774 for (x = 0; x < image_width; x++)
8776 int i = raster[(y * image_width) + x];
8777 XPutPixel (ximg, x + image_left, row + image_top,
8778 pixel_colors[i]);
8781 row += interlace_increment[pass];
8784 else
8786 for (y = 0; y < image_height; ++y)
8787 for (x = 0; x < image_width; ++x)
8789 int i = raster[y * image_width + x];
8790 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
8794 DGifCloseFile (gif);
8796 /* Maybe fill in the background field while we have ximg handy. */
8797 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8798 IMAGE_BACKGROUND (img, f, ximg);
8800 /* Put the image into the pixmap, then free the X image and its buffer. */
8801 x_put_x_image (f, ximg, img->pixmap, width, height);
8802 x_destroy_x_image (ximg);
8804 UNGCPRO;
8805 return 1;
8807 #endif /* HAVE_GIF */
8811 /***********************************************************************
8812 Ghostscript
8813 ***********************************************************************/
8815 /* The symbol `postscript' identifying images of this type. */
8817 Lisp_Object Qpostscript;
8819 /* Keyword symbols. */
8821 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8823 #ifdef HAVE_GHOSTSCRIPT
8824 static int gs_image_p P_ ((Lisp_Object object));
8825 static int gs_load P_ ((struct frame *f, struct image *img));
8826 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8828 /* Indices of image specification fields in gs_format, below. */
8830 enum gs_keyword_index
8832 GS_TYPE,
8833 GS_PT_WIDTH,
8834 GS_PT_HEIGHT,
8835 GS_FILE,
8836 GS_LOADER,
8837 GS_BOUNDING_BOX,
8838 GS_ASCENT,
8839 GS_MARGIN,
8840 GS_RELIEF,
8841 GS_ALGORITHM,
8842 GS_HEURISTIC_MASK,
8843 GS_MASK,
8844 GS_BACKGROUND,
8845 GS_LAST
8848 /* Vector of image_keyword structures describing the format
8849 of valid user-defined image specifications. */
8851 static struct image_keyword gs_format[GS_LAST] =
8853 {":type", IMAGE_SYMBOL_VALUE, 1},
8854 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8855 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8856 {":file", IMAGE_STRING_VALUE, 1},
8857 {":loader", IMAGE_FUNCTION_VALUE, 0},
8858 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8859 {":ascent", IMAGE_ASCENT_VALUE, 0},
8860 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8861 {":relief", IMAGE_INTEGER_VALUE, 0},
8862 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8863 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8864 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8865 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8868 /* Structure describing the image type `ghostscript'. */
8870 static struct image_type gs_type =
8872 &Qpostscript,
8873 gs_image_p,
8874 gs_load,
8875 gs_clear_image,
8876 NULL
8880 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8882 static void
8883 gs_clear_image (f, img)
8884 struct frame *f;
8885 struct image *img;
8887 /* IMG->data.ptr_val may contain a recorded colormap. */
8888 xfree (img->data.ptr_val);
8889 x_clear_image (f, img);
8893 /* Return non-zero if OBJECT is a valid Ghostscript image
8894 specification. */
8896 static int
8897 gs_image_p (object)
8898 Lisp_Object object;
8900 struct image_keyword fmt[GS_LAST];
8901 Lisp_Object tem;
8902 int i;
8904 bcopy (gs_format, fmt, sizeof fmt);
8906 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8907 return 0;
8909 /* Bounding box must be a list or vector containing 4 integers. */
8910 tem = fmt[GS_BOUNDING_BOX].value;
8911 if (CONSP (tem))
8913 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8914 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8915 return 0;
8916 if (!NILP (tem))
8917 return 0;
8919 else if (VECTORP (tem))
8921 if (XVECTOR (tem)->size != 4)
8922 return 0;
8923 for (i = 0; i < 4; ++i)
8924 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8925 return 0;
8927 else
8928 return 0;
8930 return 1;
8934 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8935 if successful. */
8937 static int
8938 gs_load (f, img)
8939 struct frame *f;
8940 struct image *img;
8942 char buffer[100];
8943 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8944 struct gcpro gcpro1, gcpro2;
8945 Lisp_Object frame;
8946 double in_width, in_height;
8947 Lisp_Object pixel_colors = Qnil;
8949 /* Compute pixel size of pixmap needed from the given size in the
8950 image specification. Sizes in the specification are in pt. 1 pt
8951 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8952 info. */
8953 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8954 in_width = XFASTINT (pt_width) / 72.0;
8955 img->width = in_width * FRAME_MAC_DISPLAY_INFO (f)->resx;
8956 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8957 in_height = XFASTINT (pt_height) / 72.0;
8958 img->height = in_height * FRAME_MAC_DISPLAY_INFO (f)->resy;
8960 /* Create the pixmap. */
8961 xassert (img->pixmap == NULL);
8962 img->pixmap = XCreatePixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8963 img->width, img->height,
8964 one_mac_display_info.n_planes);
8966 if (!img->pixmap)
8968 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8969 return 0;
8972 /* Call the loader to fill the pixmap. It returns a process object
8973 if successful. We do not record_unwind_protect here because
8974 other places in redisplay like calling window scroll functions
8975 don't either. Let the Lisp loader use `unwind-protect' instead. */
8976 GCPRO2 (window_and_pixmap_id, pixel_colors);
8978 sprintf (buffer, "%lu %lu",
8979 (unsigned long) FRAME_MAC_WINDOW (f),
8980 (unsigned long) img->pixmap);
8981 window_and_pixmap_id = build_string (buffer);
8983 sprintf (buffer, "%lu %lu",
8984 FRAME_FOREGROUND_PIXEL (f),
8985 FRAME_BACKGROUND_PIXEL (f));
8986 pixel_colors = build_string (buffer);
8988 XSETFRAME (frame, f);
8989 loader = image_spec_value (img->spec, QCloader, NULL);
8990 if (NILP (loader))
8991 loader = intern ("gs-load-image");
8993 img->data.lisp_val = call6 (loader, frame, img->spec,
8994 make_number (img->width),
8995 make_number (img->height),
8996 window_and_pixmap_id,
8997 pixel_colors);
8998 UNGCPRO;
8999 return PROCESSP (img->data.lisp_val);
9003 /* Kill the Ghostscript process that was started to fill PIXMAP on
9004 frame F. Called from XTread_socket when receiving an event
9005 telling Emacs that Ghostscript has finished drawing. */
9007 void
9008 x_kill_gs_process (pixmap, f)
9009 Pixmap pixmap;
9010 struct frame *f;
9012 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
9013 int class, i;
9014 struct image *img;
9016 /* Find the image containing PIXMAP. */
9017 for (i = 0; i < c->used; ++i)
9018 if (c->images[i]->pixmap == pixmap)
9019 break;
9021 /* Should someone in between have cleared the image cache, for
9022 instance, give up. */
9023 if (i == c->used)
9024 return;
9026 /* Kill the GS process. We should have found PIXMAP in the image
9027 cache and its image should contain a process object. */
9028 img = c->images[i];
9029 xassert (PROCESSP (img->data.lisp_val));
9030 Fkill_process (img->data.lisp_val, Qnil);
9031 img->data.lisp_val = Qnil;
9033 #if 0
9034 /* On displays with a mutable colormap, figure out the colors
9035 allocated for the image by looking at the pixels of an XImage for
9036 img->pixmap. */
9037 class = FRAME_MAC_DISPLAY_INFO (f)->visual->class;
9038 if (class != StaticColor && class != StaticGray && class != TrueColor)
9040 XImagePtr ximg;
9042 BLOCK_INPUT;
9044 /* Try to get an XImage for img->pixmep. */
9045 ximg = XGetImage (FRAME_MAC_DISPLAY (f), img->pixmap,
9046 0, 0, img->width, img->height, ~0, ZPixmap);
9047 if (ximg)
9049 int x, y;
9051 /* Initialize the color table. */
9052 init_color_table ();
9054 /* For each pixel of the image, look its color up in the
9055 color table. After having done so, the color table will
9056 contain an entry for each color used by the image. */
9057 for (y = 0; y < img->height; ++y)
9058 for (x = 0; x < img->width; ++x)
9060 unsigned long pixel = XGetPixel (ximg, x, y);
9061 lookup_pixel_color (f, pixel);
9064 /* Record colors in the image. Free color table and XImage. */
9065 img->colors = colors_in_color_table (&img->ncolors);
9066 free_color_table ();
9067 XDestroyImage (ximg);
9069 #if 0 /* This doesn't seem to be the case. If we free the colors
9070 here, we get a BadAccess later in x_clear_image when
9071 freeing the colors. */
9072 /* We have allocated colors once, but Ghostscript has also
9073 allocated colors on behalf of us. So, to get the
9074 reference counts right, free them once. */
9075 if (img->ncolors)
9076 x_free_colors (f, img->colors, img->ncolors);
9077 #endif
9079 else
9080 image_error ("Cannot get X image of `%s'; colors will not be freed",
9081 img->spec, Qnil);
9083 UNBLOCK_INPUT;
9085 #endif
9087 /* Now that we have the pixmap, compute mask and transform the
9088 image if requested. */
9089 BLOCK_INPUT;
9090 postprocess_image (f, img);
9091 UNBLOCK_INPUT;
9094 #endif /* HAVE_GHOSTSCRIPT */
9097 /***********************************************************************
9098 Window properties
9099 ***********************************************************************/
9101 DEFUN ("x-change-window-property", Fx_change_window_property,
9102 Sx_change_window_property, 2, 6, 0,
9103 doc: /* Change window property PROP to VALUE on the X window of FRAME.
9104 VALUE may be a string or a list of conses, numbers and/or strings.
9105 If an element in the list is a string, it is converted to
9106 an Atom and the value of the Atom is used. If an element is a cons,
9107 it is converted to a 32 bit number where the car is the 16 top bits and the
9108 cdr is the lower 16 bits.
9109 FRAME nil or omitted means use the selected frame.
9110 If TYPE is given and non-nil, it is the name of the type of VALUE.
9111 If TYPE is not given or nil, the type is STRING.
9112 FORMAT gives the size in bits of each element if VALUE is a list.
9113 It must be one of 8, 16 or 32.
9114 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
9115 If OUTER_P is non-nil, the property is changed for the outer X window of
9116 FRAME. Default is to change on the edit X window.
9118 Value is VALUE. */)
9119 (prop, value, frame, type, format, outer_p)
9120 Lisp_Object prop, value, frame, type, format, outer_p;
9122 #if 0 /* MAC_TODO : port window properties to Mac */
9123 struct frame *f = check_x_frame (frame);
9124 Atom prop_atom;
9126 CHECK_STRING (prop);
9127 CHECK_STRING (value);
9129 BLOCK_INPUT;
9130 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
9131 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9132 prop_atom, XA_STRING, 8, PropModeReplace,
9133 SDATA (value), SCHARS (value));
9135 /* Make sure the property is set when we return. */
9136 XFlush (FRAME_W32_DISPLAY (f));
9137 UNBLOCK_INPUT;
9139 #endif /* MAC_TODO */
9141 return value;
9145 DEFUN ("x-delete-window-property", Fx_delete_window_property,
9146 Sx_delete_window_property, 1, 2, 0,
9147 doc: /* Remove window property PROP from X window of FRAME.
9148 FRAME nil or omitted means use the selected frame. Value is PROP. */)
9149 (prop, frame)
9150 Lisp_Object prop, frame;
9152 #if 0 /* MAC_TODO : port window properties to Mac */
9154 struct frame *f = check_x_frame (frame);
9155 Atom prop_atom;
9157 CHECK_STRING (prop);
9158 BLOCK_INPUT;
9159 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
9160 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
9162 /* Make sure the property is removed when we return. */
9163 XFlush (FRAME_W32_DISPLAY (f));
9164 UNBLOCK_INPUT;
9165 #endif /* MAC_TODO */
9167 return prop;
9171 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
9172 1, 2, 0,
9173 doc: /* Value is the value of window property PROP on FRAME.
9174 If FRAME is nil or omitted, use the selected frame. Value is nil
9175 if FRAME hasn't a property with name PROP or if PROP has no string
9176 value. */)
9177 (prop, frame)
9178 Lisp_Object prop, frame;
9180 #if 0 /* MAC_TODO : port window properties to Mac */
9182 struct frame *f = check_x_frame (frame);
9183 Atom prop_atom;
9184 int rc;
9185 Lisp_Object prop_value = Qnil;
9186 char *tmp_data = NULL;
9187 Atom actual_type;
9188 int actual_format;
9189 unsigned long actual_size, bytes_remaining;
9191 CHECK_STRING (prop);
9192 BLOCK_INPUT;
9193 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
9194 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9195 prop_atom, 0, 0, False, XA_STRING,
9196 &actual_type, &actual_format, &actual_size,
9197 &bytes_remaining, (unsigned char **) &tmp_data);
9198 if (rc == Success)
9200 int size = bytes_remaining;
9202 XFree (tmp_data);
9203 tmp_data = NULL;
9205 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9206 prop_atom, 0, bytes_remaining,
9207 False, XA_STRING,
9208 &actual_type, &actual_format,
9209 &actual_size, &bytes_remaining,
9210 (unsigned char **) &tmp_data);
9211 if (rc == Success)
9212 prop_value = make_string (tmp_data, size);
9214 XFree (tmp_data);
9217 UNBLOCK_INPUT;
9219 return prop_value;
9221 #endif /* MAC_TODO */
9222 return Qnil;
9227 /***********************************************************************
9228 Hourglass cursor
9229 ***********************************************************************/
9231 /* If non-null, an asynchronous timer that, when it expires, displays
9232 an hourglass cursor on all frames. */
9234 static struct atimer *hourglass_atimer;
9236 /* Non-zero means an hourglass cursor is currently shown. */
9238 static int hourglass_shown_p;
9240 /* Number of seconds to wait before displaying an hourglass cursor. */
9242 static Lisp_Object Vhourglass_delay;
9244 /* Default number of seconds to wait before displaying an hourglass
9245 cursor. */
9247 #define DEFAULT_HOURGLASS_DELAY 1
9249 /* Function prototypes. */
9251 static void show_hourglass P_ ((struct atimer *));
9252 static void hide_hourglass P_ ((void));
9255 /* Cancel a currently active hourglass timer, and start a new one. */
9257 void
9258 start_hourglass ()
9260 #if 0 /* MAC_TODO: cursor shape changes. */
9261 EMACS_TIME delay;
9262 int secs, usecs = 0;
9264 cancel_hourglass ();
9266 if (INTEGERP (Vhourglass_delay)
9267 && XINT (Vhourglass_delay) > 0)
9268 secs = XFASTINT (Vhourglass_delay);
9269 else if (FLOATP (Vhourglass_delay)
9270 && XFLOAT_DATA (Vhourglass_delay) > 0)
9272 Lisp_Object tem;
9273 tem = Ftruncate (Vhourglass_delay, Qnil);
9274 secs = XFASTINT (tem);
9275 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
9277 else
9278 secs = DEFAULT_HOURGLASS_DELAY;
9280 EMACS_SET_SECS_USECS (delay, secs, usecs);
9281 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
9282 show_hourglass, NULL);
9283 #endif /* MAC_TODO */
9287 /* Cancel the hourglass cursor timer if active, hide an hourglass
9288 cursor if shown. */
9290 void
9291 cancel_hourglass ()
9293 if (hourglass_atimer)
9295 cancel_atimer (hourglass_atimer);
9296 hourglass_atimer = NULL;
9299 if (hourglass_shown_p)
9300 hide_hourglass ();
9304 /* Timer function of hourglass_atimer. TIMER is equal to
9305 hourglass_atimer.
9307 Display an hourglass cursor on all frames by mapping the frames'
9308 hourglass_window. Set the hourglass_p flag in the frames'
9309 output_data.x structure to indicate that an hourglass cursor is
9310 shown on the frames. */
9312 static void
9313 show_hourglass (timer)
9314 struct atimer *timer;
9316 #if 0 /* MAC_TODO: cursor shape changes. */
9317 /* The timer implementation will cancel this timer automatically
9318 after this function has run. Set hourglass_atimer to null
9319 so that we know the timer doesn't have to be canceled. */
9320 hourglass_atimer = NULL;
9322 if (!hourglass_shown_p)
9324 Lisp_Object rest, frame;
9326 BLOCK_INPUT;
9328 FOR_EACH_FRAME (rest, frame)
9329 if (FRAME_W32_P (XFRAME (frame)))
9331 struct frame *f = XFRAME (frame);
9333 f->output_data.w32->hourglass_p = 1;
9335 if (!f->output_data.w32->hourglass_window)
9337 unsigned long mask = CWCursor;
9338 XSetWindowAttributes attrs;
9340 attrs.cursor = f->output_data.w32->hourglass_cursor;
9342 f->output_data.w32->hourglass_window
9343 = XCreateWindow (FRAME_X_DISPLAY (f),
9344 FRAME_OUTER_WINDOW (f),
9345 0, 0, 32000, 32000, 0, 0,
9346 InputOnly,
9347 CopyFromParent,
9348 mask, &attrs);
9351 XMapRaised (FRAME_X_DISPLAY (f),
9352 f->output_data.w32->hourglass_window);
9353 XFlush (FRAME_X_DISPLAY (f));
9356 hourglass_shown_p = 1;
9357 UNBLOCK_INPUT;
9359 #endif /* MAC_TODO */
9363 /* Hide the hourglass cursor on all frames, if it is currently shown. */
9365 static void
9366 hide_hourglass ()
9368 #if 0 /* MAC_TODO: cursor shape changes. */
9369 if (hourglass_shown_p)
9371 Lisp_Object rest, frame;
9373 BLOCK_INPUT;
9374 FOR_EACH_FRAME (rest, frame)
9376 struct frame *f = XFRAME (frame);
9378 if (FRAME_W32_P (f)
9379 /* Watch out for newly created frames. */
9380 && f->output_data.x->hourglass_window)
9382 XUnmapWindow (FRAME_X_DISPLAY (f),
9383 f->output_data.x->hourglass_window);
9384 /* Sync here because XTread_socket looks at the
9385 hourglass_p flag that is reset to zero below. */
9386 XSync (FRAME_X_DISPLAY (f), False);
9387 f->output_data.x->hourglass_p = 0;
9391 hourglass_shown_p = 0;
9392 UNBLOCK_INPUT;
9394 #endif /* MAC_TODO */
9399 /***********************************************************************
9400 Tool tips
9401 ***********************************************************************/
9403 static Lisp_Object x_create_tip_frame P_ ((struct mac_display_info *,
9404 Lisp_Object));
9406 /* The frame of a currently visible tooltip, or null. */
9408 Lisp_Object tip_frame;
9410 /* If non-nil, a timer started that hides the last tooltip when it
9411 fires. */
9413 Lisp_Object tip_timer;
9414 Window tip_window;
9416 /* If non-nil, a vector of 3 elements containing the last args
9417 with which x-show-tip was called. See there. */
9419 Lisp_Object last_show_tip_args;
9421 /* Create a frame for a tooltip on the display described by DPYINFO.
9422 PARMS is a list of frame parameters. Value is the frame. */
9424 static Lisp_Object
9425 x_create_tip_frame (dpyinfo, parms)
9426 struct mac_display_info *dpyinfo;
9427 Lisp_Object parms;
9429 #if 0 /* MAC_TODO : Mac version */
9430 struct frame *f;
9431 Lisp_Object frame, tem;
9432 Lisp_Object name;
9433 long window_prompting = 0;
9434 int width, height;
9435 int count = SPECPDL_INDEX ();
9436 struct gcpro gcpro1, gcpro2, gcpro3;
9437 struct kboard *kb;
9439 check_x ();
9441 /* Use this general default value to start with until we know if
9442 this frame has a specified name. */
9443 Vx_resource_name = Vinvocation_name;
9445 #ifdef MULTI_KBOARD
9446 kb = dpyinfo->kboard;
9447 #else
9448 kb = &the_only_kboard;
9449 #endif
9451 /* Get the name of the frame to use for resource lookup. */
9452 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
9453 if (!STRINGP (name)
9454 && !EQ (name, Qunbound)
9455 && !NILP (name))
9456 error ("Invalid frame name--not a string or nil");
9457 Vx_resource_name = name;
9459 frame = Qnil;
9460 GCPRO3 (parms, name, frame);
9461 tip_frame = f = make_frame (1);
9462 XSETFRAME (frame, f);
9463 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
9465 f->output_method = output_w32;
9466 f->output_data.w32 =
9467 (struct w32_output *) xmalloc (sizeof (struct w32_output));
9468 bzero (f->output_data.w32, sizeof (struct w32_output));
9469 #if 0
9470 f->output_data.w32->icon_bitmap = -1;
9471 #endif
9472 FRAME_FONTSET (f) = -1;
9473 f->icon_name = Qnil;
9475 #ifdef MULTI_KBOARD
9476 FRAME_KBOARD (f) = kb;
9477 #endif
9478 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
9479 f->output_data.w32->explicit_parent = 0;
9481 /* Set the name; the functions to which we pass f expect the name to
9482 be set. */
9483 if (EQ (name, Qunbound) || NILP (name))
9485 f->name = build_string (dpyinfo->x_id_name);
9486 f->explicit_name = 0;
9488 else
9490 f->name = name;
9491 f->explicit_name = 1;
9492 /* use the frame's title when getting resources for this frame. */
9493 specbind (Qx_resource_name, name);
9496 /* Extract the window parameters from the supplied values
9497 that are needed to determine window geometry. */
9499 Lisp_Object font;
9501 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
9503 BLOCK_INPUT;
9504 /* First, try whatever font the caller has specified. */
9505 if (STRINGP (font))
9507 tem = Fquery_fontset (font, Qnil);
9508 if (STRINGP (tem))
9509 font = x_new_fontset (f, SDATA (tem));
9510 else
9511 font = x_new_font (f, SDATA (font));
9514 /* Try out a font which we hope has bold and italic variations. */
9515 if (!STRINGP (font))
9516 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
9517 if (!STRINGP (font))
9518 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9519 if (! STRINGP (font))
9520 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
9521 if (! STRINGP (font))
9522 /* This was formerly the first thing tried, but it finds too many fonts
9523 and takes too long. */
9524 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
9525 /* If those didn't work, look for something which will at least work. */
9526 if (! STRINGP (font))
9527 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
9528 UNBLOCK_INPUT;
9529 if (! STRINGP (font))
9530 font = build_string ("fixed");
9532 x_default_parameter (f, parms, Qfont, font,
9533 "font", "Font", RES_TYPE_STRING);
9536 x_default_parameter (f, parms, Qborder_width, make_number (2),
9537 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
9539 /* This defaults to 2 in order to match xterm. We recognize either
9540 internalBorderWidth or internalBorder (which is what xterm calls
9541 it). */
9542 if (NILP (Fassq (Qinternal_border_width, parms)))
9544 Lisp_Object value;
9546 value = w32_get_arg (parms, Qinternal_border_width,
9547 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
9548 if (! EQ (value, Qunbound))
9549 parms = Fcons (Fcons (Qinternal_border_width, value),
9550 parms);
9553 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
9554 "internalBorderWidth", "internalBorderWidth",
9555 RES_TYPE_NUMBER);
9557 /* Also do the stuff which must be set before the window exists. */
9558 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
9559 "foreground", "Foreground", RES_TYPE_STRING);
9560 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
9561 "background", "Background", RES_TYPE_STRING);
9562 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
9563 "pointerColor", "Foreground", RES_TYPE_STRING);
9564 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
9565 "cursorColor", "Foreground", RES_TYPE_STRING);
9566 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
9567 "borderColor", "BorderColor", RES_TYPE_STRING);
9569 /* Init faces before x_default_parameter is called for scroll-bar
9570 parameters because that function calls x_set_scroll_bar_width,
9571 which calls change_frame_size, which calls Fset_window_buffer,
9572 which runs hooks, which call Fvertical_motion. At the end, we
9573 end up in init_iterator with a null face cache, which should not
9574 happen. */
9575 init_frame_faces (f);
9577 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
9579 window_prompting = x_figure_window_size (f, parms, 0);
9582 XSetWindowAttributes attrs;
9583 unsigned long mask;
9585 BLOCK_INPUT;
9586 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
9587 /* Window managers looks at the override-redirect flag to
9588 determine whether or net to give windows a decoration (Xlib
9589 3.2.8). */
9590 attrs.override_redirect = True;
9591 attrs.save_under = True;
9592 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
9593 /* Arrange for getting MapNotify and UnmapNotify events. */
9594 attrs.event_mask = StructureNotifyMask;
9595 tip_window
9596 = FRAME_W32_WINDOW (f)
9597 = XCreateWindow (FRAME_W32_DISPLAY (f),
9598 FRAME_W32_DISPLAY_INFO (f)->root_window,
9599 /* x, y, width, height */
9600 0, 0, 1, 1,
9601 /* Border. */
9603 CopyFromParent, InputOutput, CopyFromParent,
9604 mask, &attrs);
9605 UNBLOCK_INPUT;
9608 x_make_gc (f);
9610 x_default_parameter (f, parms, Qauto_raise, Qnil,
9611 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9612 x_default_parameter (f, parms, Qauto_lower, Qnil,
9613 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
9614 x_default_parameter (f, parms, Qcursor_type, Qbox,
9615 "cursorType", "CursorType", RES_TYPE_SYMBOL);
9617 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
9618 Change will not be effected unless different from the current
9619 FRAME_LINES (f). */
9620 width = FRAME_COLS (f);
9621 height = FRAME_LINES (f);
9622 FRAME_LINES (f) = 0;
9623 SET_FRAME_COLS (f, 0);
9624 change_frame_size (f, height, width, 1, 0, 0);
9626 /* Add `tooltip' frame parameter's default value. */
9627 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
9628 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
9629 Qnil));
9631 f->no_split = 1;
9633 UNGCPRO;
9635 /* It is now ok to make the frame official even if we get an error
9636 below. And the frame needs to be on Vframe_list or making it
9637 visible won't work. */
9638 Vframe_list = Fcons (frame, Vframe_list);
9640 /* Now that the frame is official, it counts as a reference to
9641 its display. */
9642 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
9644 return unbind_to (count, frame);
9645 #endif /* MAC_TODO */
9646 return Qnil;
9650 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
9651 doc : /* Show STRING in a "tooltip" window on frame FRAME.
9652 A tooltip window is a small window displaying a string.
9654 FRAME nil or omitted means use the selected frame.
9656 PARMS is an optional list of frame parameters which can be used to
9657 change the tooltip's appearance.
9659 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
9660 means use the default timeout of 5 seconds.
9662 If the list of frame parameters PARAMS contains a `left' parameters,
9663 the tooltip is displayed at that x-position. Otherwise it is
9664 displayed at the mouse position, with offset DX added (default is 5 if
9665 DX isn't specified). Likewise for the y-position; if a `top' frame
9666 parameter is specified, it determines the y-position of the tooltip
9667 window, otherwise it is displayed at the mouse position, with offset
9668 DY added (default is 10). */)
9669 (string, frame, parms, timeout, dx, dy)
9670 Lisp_Object string, frame, parms, timeout, dx, dy;
9672 struct frame *f;
9673 struct window *w;
9674 Window root, child;
9675 Lisp_Object buffer, top, left;
9676 struct buffer *old_buffer;
9677 struct text_pos pos;
9678 int i, width, height;
9679 int root_x, root_y, win_x, win_y;
9680 unsigned pmask;
9681 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9682 int old_windows_or_buffers_changed = windows_or_buffers_changed;
9683 int count = SPECPDL_INDEX ();
9685 specbind (Qinhibit_redisplay, Qt);
9687 GCPRO4 (string, parms, frame, timeout);
9689 CHECK_STRING (string);
9690 f = check_x_frame (frame);
9691 if (NILP (timeout))
9692 timeout = make_number (5);
9693 else
9694 CHECK_NATNUM (timeout);
9696 if (NILP (dx))
9697 dx = make_number (5);
9698 else
9699 CHECK_NUMBER (dx);
9701 if (NILP (dy))
9702 dy = make_number (-10);
9703 else
9704 CHECK_NUMBER (dy);
9706 if (NILP (last_show_tip_args))
9707 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
9709 if (!NILP (tip_frame))
9711 Lisp_Object last_string = AREF (last_show_tip_args, 0);
9712 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
9713 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
9715 if (EQ (frame, last_frame)
9716 && !NILP (Fequal (last_string, string))
9717 && !NILP (Fequal (last_parms, parms)))
9719 struct frame *f = XFRAME (tip_frame);
9721 /* Only DX and DY have changed. */
9722 if (!NILP (tip_timer))
9724 Lisp_Object timer = tip_timer;
9725 tip_timer = Qnil;
9726 call1 (Qcancel_timer, timer);
9729 #if 0 /* MAC_TODO : Mac specifics */
9730 BLOCK_INPUT;
9731 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
9732 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9733 root_x, root_y - FRAME_PIXEL_HEIGHT (f));
9734 UNBLOCK_INPUT;
9735 #endif /* MAC_TODO */
9736 goto start_timer;
9740 /* Hide a previous tip, if any. */
9741 Fx_hide_tip ();
9743 ASET (last_show_tip_args, 0, string);
9744 ASET (last_show_tip_args, 1, frame);
9745 ASET (last_show_tip_args, 2, parms);
9747 /* Add default values to frame parameters. */
9748 if (NILP (Fassq (Qname, parms)))
9749 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
9750 if (NILP (Fassq (Qinternal_border_width, parms)))
9751 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
9752 if (NILP (Fassq (Qborder_width, parms)))
9753 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
9754 if (NILP (Fassq (Qborder_color, parms)))
9755 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
9756 if (NILP (Fassq (Qbackground_color, parms)))
9757 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
9758 parms);
9760 /* Create a frame for the tooltip, and record it in the global
9761 variable tip_frame. */
9762 frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
9763 f = XFRAME (frame);
9765 /* Set up the frame's root window. Currently we use a size of 80
9766 columns x 40 lines. If someone wants to show a larger tip, he
9767 will loose. I don't think this is a realistic case. */
9768 w = XWINDOW (FRAME_ROOT_WINDOW (f));
9769 w->left_col = w->top_line = make_number (0);
9770 w->total_cols = make_number (80);
9771 w->total_lines = make_number (40);
9772 adjust_glyphs (f);
9773 w->pseudo_window_p = 1;
9775 /* Display the tooltip text in a temporary buffer. */
9776 buffer = Fget_buffer_create (build_string (" *tip*"));
9777 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
9778 old_buffer = current_buffer;
9779 set_buffer_internal_1 (XBUFFER (buffer));
9780 Ferase_buffer ();
9781 Finsert (1, &string);
9782 clear_glyph_matrix (w->desired_matrix);
9783 clear_glyph_matrix (w->current_matrix);
9784 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
9785 try_window (FRAME_ROOT_WINDOW (f), pos);
9787 /* Compute width and height of the tooltip. */
9788 width = height = 0;
9789 for (i = 0; i < w->desired_matrix->nrows; ++i)
9791 struct glyph_row *row = &w->desired_matrix->rows[i];
9792 struct glyph *last;
9793 int row_width;
9795 /* Stop at the first empty row at the end. */
9796 if (!row->enabled_p || !row->displays_text_p)
9797 break;
9799 /* Let the row go over the full width of the frame. */
9800 row->full_width_p = 1;
9802 /* There's a glyph at the end of rows that is use to place
9803 the cursor there. Don't include the width of this glyph. */
9804 if (row->used[TEXT_AREA])
9806 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
9807 row_width = row->pixel_width - last->pixel_width;
9809 else
9810 row_width = row->pixel_width;
9812 height += row->height;
9813 width = max (width, row_width);
9816 /* Add the frame's internal border to the width and height the X
9817 window should have. */
9818 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9819 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
9821 /* Move the tooltip window where the mouse pointer is. Resize and
9822 show it. */
9823 #if 0 /* TODO : Mac specifics */
9824 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
9826 BLOCK_INPUT;
9827 XQueryPointer (FRAME_W32_DISPLAY (f), FRAME_W32_DISPLAY_INFO (f)->root_window,
9828 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
9829 XMoveResizeWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
9830 root_x + 5, root_y - height - 5, width, height);
9831 XMapRaised (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
9832 UNBLOCK_INPUT;
9833 #endif /* MAC_TODO */
9835 /* Draw into the window. */
9836 w->must_be_updated_p = 1;
9837 update_single_window (w, 1);
9839 /* Restore original current buffer. */
9840 set_buffer_internal_1 (old_buffer);
9841 windows_or_buffers_changed = old_windows_or_buffers_changed;
9843 start_timer:
9844 /* Let the tip disappear after timeout seconds. */
9845 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
9846 intern ("x-hide-tip"));
9848 UNGCPRO;
9849 return unbind_to (count, Qnil);
9853 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
9854 doc: /* Hide the current tooltip window, if there is any.
9855 Value is t is tooltip was open, nil otherwise. */)
9858 int count;
9859 Lisp_Object deleted, frame, timer;
9860 struct gcpro gcpro1, gcpro2;
9862 /* Return quickly if nothing to do. */
9863 if (NILP (tip_timer) && NILP (tip_frame))
9864 return Qnil;
9866 frame = tip_frame;
9867 timer = tip_timer;
9868 GCPRO2 (frame, timer);
9869 tip_frame = tip_timer = deleted = Qnil;
9871 count = SPECPDL_INDEX ();
9872 specbind (Qinhibit_redisplay, Qt);
9873 specbind (Qinhibit_quit, Qt);
9875 if (!NILP (timer))
9876 call1 (Qcancel_timer, timer);
9878 if (FRAMEP (frame))
9880 Fdelete_frame (frame, Qnil);
9881 deleted = Qt;
9884 UNGCPRO;
9885 return unbind_to (count, deleted);
9890 /***********************************************************************
9891 File selection dialog
9892 ***********************************************************************/
9894 #if 0 /* MAC_TODO: can standard file dialog */
9895 extern Lisp_Object Qfile_name_history;
9897 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
9898 doc: /* Read file name, prompting with PROMPT in directory DIR.
9899 Use a file selection dialog.
9900 Select DEFAULT-FILENAME in the dialog's file selection box, if
9901 specified. Don't let the user enter a file name in the file
9902 selection dialog's entry field, if MUSTMATCH is non-nil. */)
9903 (prompt, dir, default_filename, mustmatch)
9904 Lisp_Object prompt, dir, default_filename, mustmatch;
9906 struct frame *f = SELECTED_FRAME ();
9907 Lisp_Object file = Qnil;
9908 int count = SPECPDL_INDEX ();
9909 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
9910 char filename[MAX_PATH + 1];
9911 char init_dir[MAX_PATH + 1];
9912 int use_dialog_p = 1;
9914 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
9915 CHECK_STRING (prompt);
9916 CHECK_STRING (dir);
9918 /* Create the dialog with PROMPT as title, using DIR as initial
9919 directory and using "*" as pattern. */
9920 dir = Fexpand_file_name (dir, Qnil);
9921 strncpy (init_dir, SDATA (dir), MAX_PATH);
9922 init_dir[MAX_PATH] = '\0';
9923 unixtodos_filename (init_dir);
9925 if (STRINGP (default_filename))
9927 char *file_name_only;
9928 char *full_path_name = SDATA (default_filename);
9930 unixtodos_filename (full_path_name);
9932 file_name_only = strrchr (full_path_name, '\\');
9933 if (!file_name_only)
9934 file_name_only = full_path_name;
9935 else
9937 file_name_only++;
9939 /* If default_file_name is a directory, don't use the open
9940 file dialog, as it does not support selecting
9941 directories. */
9942 if (!(*file_name_only))
9943 use_dialog_p = 0;
9946 strncpy (filename, file_name_only, MAX_PATH);
9947 filename[MAX_PATH] = '\0';
9949 else
9950 filename[0] = '\0';
9952 if (use_dialog_p)
9954 OPENFILENAME file_details;
9955 char *filename_file;
9957 /* Prevent redisplay. */
9958 specbind (Qinhibit_redisplay, Qt);
9959 BLOCK_INPUT;
9961 bzero (&file_details, sizeof (file_details));
9962 file_details.lStructSize = sizeof (file_details);
9963 file_details.hwndOwner = FRAME_W32_WINDOW (f);
9964 file_details.lpstrFile = filename;
9965 file_details.nMaxFile = sizeof (filename);
9966 file_details.lpstrInitialDir = init_dir;
9967 file_details.lpstrTitle = SDATA (prompt);
9968 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
9970 if (!NILP (mustmatch))
9971 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
9973 if (GetOpenFileName (&file_details))
9975 dostounix_filename (filename);
9976 file = build_string (filename);
9978 else
9979 file = Qnil;
9981 UNBLOCK_INPUT;
9982 file = unbind_to (count, file);
9984 /* Open File dialog will not allow folders to be selected, so resort
9985 to minibuffer completing reads for directories. */
9986 else
9987 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
9988 dir, mustmatch, dir, Qfile_name_history,
9989 default_filename, Qnil);
9991 UNGCPRO;
9993 /* Make "Cancel" equivalent to C-g. */
9994 if (NILP (file))
9995 Fsignal (Qquit, Qnil);
9997 return unbind_to (count, file);
9999 #endif /* MAC_TODO */
10003 /***********************************************************************
10004 Tests
10005 ***********************************************************************/
10007 #if GLYPH_DEBUG
10009 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
10010 doc: /* Value is non-nil if SPEC is a valid image specification. */)
10011 (spec)
10012 Lisp_Object spec;
10014 return valid_image_p (spec) ? Qt : Qnil;
10018 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
10019 (spec)
10020 Lisp_Object spec;
10022 int id = -1;
10024 if (valid_image_p (spec))
10025 id = lookup_image (SELECTED_FRAME (), spec);
10027 debug_print (spec);
10028 return make_number (id);
10031 #endif /* GLYPH_DEBUG != 0 */
10035 /***********************************************************************
10036 Initialization
10037 ***********************************************************************/
10039 /* Keep this list in the same order as frame_parms in frame.c.
10040 Use 0 for unsupported frame parameters. */
10042 frame_parm_handler mac_frame_parm_handlers[] =
10044 x_set_autoraise,
10045 x_set_autolower,
10046 x_set_background_color,
10047 x_set_border_color,
10048 x_set_border_width,
10049 x_set_cursor_color,
10050 x_set_cursor_type,
10051 x_set_font,
10052 x_set_foreground_color,
10053 x_set_icon_name,
10054 0, /* MAC_TODO: x_set_icon_type, */
10055 x_set_internal_border_width,
10056 x_set_menu_bar_lines,
10057 x_set_mouse_color,
10058 x_explicitly_set_name,
10059 x_set_scroll_bar_width,
10060 x_set_title,
10061 x_set_unsplittable,
10062 x_set_vertical_scroll_bars,
10063 x_set_visibility,
10064 x_set_tool_bar_lines,
10065 0, /* MAC_TODO: x_set_scroll_bar_foreground, */
10066 0, /* MAC_TODO: x_set_scroll_bar_background, */
10067 x_set_screen_gamma,
10068 x_set_line_spacing,
10069 0, /* MAC_TODO: x_set_fringe_width, */
10070 0, /* MAC_TODO: x_set_fringe_width, */
10071 0, /* x_set_wait_for_wm, */
10072 0, /* MAC_TODO: x_set_fullscreen, */
10075 void
10076 syms_of_macfns ()
10078 /* Certainly running on Mac. */
10079 mac_in_use = 1;
10081 /* The section below is built by the lisp expression at the top of the file,
10082 just above where these variables are declared. */
10083 /*&&& init symbols here &&&*/
10084 Qnone = intern ("none");
10085 staticpro (&Qnone);
10086 Qsuppress_icon = intern ("suppress-icon");
10087 staticpro (&Qsuppress_icon);
10088 Qundefined_color = intern ("undefined-color");
10089 staticpro (&Qundefined_color);
10090 Qcenter = intern ("center");
10091 staticpro (&Qcenter);
10092 /* This is the end of symbol initialization. */
10094 Qhyper = intern ("hyper");
10095 staticpro (&Qhyper);
10096 Qsuper = intern ("super");
10097 staticpro (&Qsuper);
10098 Qmeta = intern ("meta");
10099 staticpro (&Qmeta);
10100 Qalt = intern ("alt");
10101 staticpro (&Qalt);
10102 Qctrl = intern ("ctrl");
10103 staticpro (&Qctrl);
10104 Qcontrol = intern ("control");
10105 staticpro (&Qcontrol);
10106 Qshift = intern ("shift");
10107 staticpro (&Qshift);
10109 /* Text property `display' should be nonsticky by default. */
10110 Vtext_property_default_nonsticky
10111 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
10114 Qlaplace = intern ("laplace");
10115 staticpro (&Qlaplace);
10116 Qemboss = intern ("emboss");
10117 staticpro (&Qemboss);
10118 Qedge_detection = intern ("edge-detection");
10119 staticpro (&Qedge_detection);
10120 Qheuristic = intern ("heuristic");
10121 staticpro (&Qheuristic);
10122 QCmatrix = intern (":matrix");
10123 staticpro (&QCmatrix);
10124 QCcolor_adjustment = intern (":color-adjustment");
10125 staticpro (&QCcolor_adjustment);
10126 QCmask = intern (":mask");
10127 staticpro (&QCmask);
10129 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
10130 staticpro (&Qface_set_after_frame_default);
10132 Fput (Qundefined_color, Qerror_conditions,
10133 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
10134 Fput (Qundefined_color, Qerror_message,
10135 build_string ("Undefined color"));
10137 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
10138 doc: /* Non-nil means always draw a cross over disabled images.
10139 Disabled images are those having an `:conversion disabled' property.
10140 A cross is always drawn on black & white displays. */);
10141 cross_disabled_images = 0;
10143 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
10144 doc: /* List of directories to search for window system bitmap files. */);
10145 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
10147 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
10148 doc: /* The shape of the pointer when over text.
10149 Changing the value does not affect existing frames
10150 unless you set the mouse color. */);
10151 Vx_pointer_shape = Qnil;
10153 Vx_nontext_pointer_shape = Qnil;
10155 Vx_mode_pointer_shape = Qnil;
10157 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
10158 doc: /* The shape of the pointer when Emacs is hourglass.
10159 This variable takes effect when you create a new frame
10160 or when you set the mouse color. */);
10161 Vx_hourglass_pointer_shape = Qnil;
10163 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
10164 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
10165 display_hourglass_p = 1;
10167 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
10168 doc: /* *Seconds to wait before displaying an hourglass pointer.
10169 Value must be an integer or float. */);
10170 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
10172 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
10173 &Vx_sensitive_text_pointer_shape,
10174 doc: /* The shape of the pointer when over mouse-sensitive text.
10175 This variable takes effect when you create a new frame
10176 or when you set the mouse color. */);
10177 Vx_sensitive_text_pointer_shape = Qnil;
10179 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
10180 doc: /* A string indicating the foreground color of the cursor box. */);
10181 Vx_cursor_fore_pixel = Qnil;
10183 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
10184 doc: /* Non-nil if no window manager is in use.
10185 Emacs doesn't try to figure this out; this is always nil
10186 unless you set it to something else. */);
10187 /* We don't have any way to find this out, so set it to nil
10188 and maybe the user would like to set it to t. */
10189 Vx_no_window_manager = Qnil;
10191 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
10192 &Vx_pixel_size_width_font_regexp,
10193 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
10195 Since Emacs gets width of a font matching with this regexp from
10196 PIXEL_SIZE field of the name, font finding mechanism gets faster for
10197 such a font. This is especially effective for such large fonts as
10198 Chinese, Japanese, and Korean. */);
10199 Vx_pixel_size_width_font_regexp = Qnil;
10201 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
10202 doc: /* Time after which cached images are removed from the cache.
10203 When an image has not been displayed this many seconds, remove it
10204 from the image cache. Value must be an integer or nil with nil
10205 meaning don't clear the cache. */);
10206 Vimage_cache_eviction_delay = make_number (30 * 60);
10208 /* X window properties. */
10209 defsubr (&Sx_change_window_property);
10210 defsubr (&Sx_delete_window_property);
10211 defsubr (&Sx_window_property);
10213 defsubr (&Sxw_display_color_p);
10214 defsubr (&Sx_display_grayscale_p);
10215 defsubr (&Sxw_color_defined_p);
10216 defsubr (&Sxw_color_values);
10217 defsubr (&Sx_server_max_request_size);
10218 defsubr (&Sx_server_vendor);
10219 defsubr (&Sx_server_version);
10220 defsubr (&Sx_display_pixel_width);
10221 defsubr (&Sx_display_pixel_height);
10222 defsubr (&Sx_display_mm_width);
10223 defsubr (&Sx_display_mm_height);
10224 defsubr (&Sx_display_screens);
10225 defsubr (&Sx_display_planes);
10226 defsubr (&Sx_display_color_cells);
10227 defsubr (&Sx_display_visual_class);
10228 defsubr (&Sx_display_backing_store);
10229 defsubr (&Sx_display_save_under);
10230 defsubr (&Sx_create_frame);
10231 #if 0 /* MAC_TODO: implement network support */
10232 defsubr (&Sx_open_connection);
10233 defsubr (&Sx_close_connection);
10234 #endif
10235 defsubr (&Sx_display_list);
10236 defsubr (&Sx_synchronize);
10238 /* Setting callback functions for fontset handler. */
10239 get_font_info_func = x_get_font_info;
10241 #if 0 /* This function pointer doesn't seem to be used anywhere.
10242 And the pointer assigned has the wrong type, anyway. */
10243 list_fonts_func = x_list_fonts;
10244 #endif
10246 load_font_func = x_load_font;
10247 find_ccl_program_func = x_find_ccl_program;
10248 query_font_func = x_query_font;
10249 set_frame_fontset_func = x_set_font;
10250 check_window_system_func = check_mac;
10252 /* Images. */
10253 Qxbm = intern ("xbm");
10254 staticpro (&Qxbm);
10255 QCconversion = intern (":conversion");
10256 staticpro (&QCconversion);
10257 QCheuristic_mask = intern (":heuristic-mask");
10258 staticpro (&QCheuristic_mask);
10259 QCcolor_symbols = intern (":color-symbols");
10260 staticpro (&QCcolor_symbols);
10261 QCascent = intern (":ascent");
10262 staticpro (&QCascent);
10263 QCmargin = intern (":margin");
10264 staticpro (&QCmargin);
10265 QCrelief = intern (":relief");
10266 staticpro (&QCrelief);
10267 Qpostscript = intern ("postscript");
10268 staticpro (&Qpostscript);
10269 QCloader = intern (":loader");
10270 staticpro (&QCloader);
10271 QCbounding_box = intern (":bounding-box");
10272 staticpro (&QCbounding_box);
10273 QCpt_width = intern (":pt-width");
10274 staticpro (&QCpt_width);
10275 QCpt_height = intern (":pt-height");
10276 staticpro (&QCpt_height);
10277 QCindex = intern (":index");
10278 staticpro (&QCindex);
10279 Qpbm = intern ("pbm");
10280 staticpro (&Qpbm);
10282 #if HAVE_XPM
10283 Qxpm = intern ("xpm");
10284 staticpro (&Qxpm);
10285 #endif
10287 Qjpeg = intern ("jpeg");
10288 staticpro (&Qjpeg);
10290 Qtiff = intern ("tiff");
10291 staticpro (&Qtiff);
10293 Qgif = intern ("gif");
10294 staticpro (&Qgif);
10296 Qpng = intern ("png");
10297 staticpro (&Qpng);
10299 defsubr (&Sclear_image_cache);
10300 defsubr (&Simage_size);
10301 defsubr (&Simage_mask_p);
10303 #if GLYPH_DEBUG
10304 defsubr (&Simagep);
10305 defsubr (&Slookup_image);
10306 #endif
10308 hourglass_atimer = NULL;
10309 hourglass_shown_p = 0;
10311 defsubr (&Sx_show_tip);
10312 defsubr (&Sx_hide_tip);
10313 tip_timer = Qnil;
10314 staticpro (&tip_timer);
10315 tip_frame = Qnil;
10316 staticpro (&tip_frame);
10318 #if 0 /* MAC_TODO */
10319 defsubr (&Sx_file_dialog);
10320 #endif
10324 void
10325 init_xfns ()
10327 image_types = NULL;
10328 Vimage_types = Qnil;
10330 define_image_type (&xbm_type);
10331 #if HAVE_GHOSTSCRIPT
10332 define_image_type (&gs_type);
10333 #endif
10334 define_image_type (&pbm_type);
10336 #if HAVE_XPM
10337 define_image_type (&xpm_type);
10338 #endif
10340 define_image_type (&jpeg_type);
10341 define_image_type (&tiff_type);
10342 define_image_type (&gif_type);
10343 define_image_type (&png_type);
10345 /* Animated gifs use QuickTime Movie Toolbox. So initialize it
10346 here. */
10347 EnterMovies ();
10348 #ifdef MAC_OSX
10349 init_image_func_pointer ();
10350 #endif
10353 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc
10354 (do not change this comment) */