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)
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). */
37 #include "dispextern.h"
39 #include "intervals.h"
41 #include "blockinput.h"
43 #include "termhooks.h"
48 /* #include "bitmaps/gray.xbm" */
51 static unsigned char gray_bits
[] = {
54 /*#include <commdlg.h>
55 #include <shellapi.h>*/
57 #include <sys/types.h>
67 #include <QuickTime/QuickTime.h>
68 #else /* not MAC_OSX */
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.
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")
139 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
141 (cons (buffer-substring (match-beginning 1) (match-end 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")
150 (kill-region start (point)))
151 ;; Write a new symbol initialization section.
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 &&&*/
164 Lisp_Object Qsuppress_icon
;
165 Lisp_Object Qundefined_color
;
167 Lisp_Object Qcancel_timer
;
173 Lisp_Object Qcontrol
;
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 */
199 stricmp (const char *s
, const char *t
)
201 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
204 return tolower (*s
) - tolower (*t
);
207 /* compare two strings up to n characters, ignoring case */
210 strnicmp (const char *s
, const char *t
, unsigned int n
)
212 for ( ; n
-- > 0 && tolower (*s
) == tolower (*t
); s
++, t
++)
215 return n
== 0 ? 0 : tolower (*s
) - tolower (*t
);
219 /* Error if we are not running on Mac OS. */
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. */
237 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
238 and checking validity for Mac. */
241 check_x_frame (frame
)
247 frame
= selected_frame
;
248 CHECK_LIVE_FRAME (frame
);
250 if (! FRAME_MAC_P (f
))
251 error ("non-mac frame used");
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
)
263 if (!mac_initialized
)
271 struct frame
*sf
= XFRAME (selected_frame
);
273 if (FRAME_MAC_P (sf
) && FRAME_LIVE_P (sf
))
274 return FRAME_MAC_DISPLAY_INFO (sf
);
276 return &one_mac_display_info
;
278 else if (STRINGP (frame
))
279 return x_display_info_for_name (frame
);
284 CHECK_LIVE_FRAME (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. */
298 x_window_to_frame (dpyinfo
, wdesc
)
299 struct mac_display_info
*dpyinfo
;
302 Lisp_Object tail
, frame
;
305 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
308 if (!GC_FRAMEP (frame
))
311 if (!FRAME_W32_P (f
) || FRAME_MAC_DISPLAY_INFO (f
) != dpyinfo
)
313 /*if (f->output_data.w32->hourglass_window == wdesc)
316 /* MAC_TODO: Check tooltips when supported. */
317 if (FRAME_MAC_WINDOW (f
) == wdesc
)
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
)
344 return FRAME_MAC_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
348 x_bitmap_width (f
, 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
)
361 return (int) FRAME_MAC_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
365 /* Allocate a new bitmap record. Returns index of new record. */
368 x_allocate_bitmap_record (f
)
371 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
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;
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)
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
401 x_reference_bitmap (f
, 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
412 x_create_bitmap_from_data (f
, bits
, width
, height
)
415 unsigned int width
, height
;
417 struct x_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
420 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
422 id
= x_allocate_bitmap_record (f
);
427 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
428 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
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
;
440 /* Create bitmap from file FILE for frame F. */
443 x_create_bitmap_from_file (f
, file
)
448 #if 0 /* MAC_TODO : bitmap support */
449 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
450 unsigned int width
, height
;
452 int xhot
, yhot
, result
, id
;
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
;
470 /* Search bitmap-file-path for the file, if appropriate. */
471 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, Qnil
);
474 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
479 filename
= (char *) SDATA (found
);
481 hinst
= LoadLibraryEx (filename
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
487 result
= XReadBitmapFile (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
488 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
489 if (result
!= BitmapSuccess
)
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
));
502 #endif /* MAC_TODO */
505 /* Remove reference to bitmap with id number ID. */
508 x_destroy_bitmap (f
, id
)
512 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
516 --dpyinfo
->bitmaps
[id
- 1].refcount
;
517 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
520 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= NULL
;
526 /* Free all the bitmaps for the display specified by DPYINFO. */
529 x_destroy_all_bitmaps (dpyinfo
)
530 struct mac_display_info
*dpyinfo
;
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 */
546 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
547 Display
*display
; /* not used */
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 */
555 xassert (x
== 0 && y
== 0);
558 SetRect (&ri
, 0, 0, width
, height
);
559 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
561 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
564 LockPixels (GetGWorldPixMap (pixmap
));
570 XPutPixel (ximage
, x
, y
, pixel
)
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
);
586 XGetPixel (ximage
, x
, y
)
592 SetGWorld (ximage
, NULL
);
594 GetCPixel (x
, y
, &color
);
595 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
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
,
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
,
636 void x_set_scroll_bar_background
P_ ((struct frame
*, Lisp_Object
,
638 static Lisp_Object x_default_scroll_bar_color_parameter
P_ ((struct frame
*,
643 static void x_edge_detection
P_ ((struct frame
*, struct image
*, 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. */
656 x_real_positions (f
, xptr
, yptr
)
663 #ifdef TARGET_API_MAC_CARBON
667 GetWindowPortBounds (f
->output_data
.mac
->mWP
, &r
);
668 SetPt (&pt
, r
.left
, r
.top
);
670 #else /* not TARGET_API_MAC_CARBON */
672 f
->output_data
.mac
->mWP
->portRect
.left
,
673 f
->output_data
.mac
->mWP
->portRect
.top
);
674 #endif /* not TARGET_API_MAC_CARBON */
679 /* MAC has no frame pixel diff. */
680 f
->x_pixels_diff
= 0;
681 f
->y_pixels_diff
= 0;
688 /* The default colors for the Mac color map */
689 typedef struct 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" }
1452 mac_color_map_lookup (colorname
)
1455 Lisp_Object ret
= Qnil
;
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
);
1473 x_to_mac_color (colorname
)
1476 register Lisp_Object tail
, ret
= Qnil
;
1480 if (colorname
[0] == '#')
1482 /* Could be an old-style RGB Device specification. */
1485 color
= colorname
+ 1;
1487 size
= strlen(color
);
1488 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
1490 unsigned long colorval
;
1496 for (i
= 0; i
< 3; i
++)
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')
1509 value
= strtoul(color
, &end
, 16);
1511 if (errno
== ERANGE
|| end
- color
!= size
)
1516 value
= value
* 0x10;
1527 colorval
|= (value
<< pos
);
1532 return make_number (colorval
);
1538 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1541 unsigned long colorval
;
1546 color
= colorname
+ 4;
1547 for (i
= 0; i
< 3; i
++)
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')
1557 value
= strtoul(color
, &end
, 16);
1558 if (errno
== ERANGE
)
1560 switch (end
- color
)
1563 value
= value
* 0x10 + value
;
1576 if (value
== ULONG_MAX
)
1578 colorval
|= (value
<< pos
);
1585 return make_number (colorval
);
1592 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1594 /* This is an RGB Intensity specification. */
1596 unsigned long colorval
;
1601 color
= colorname
+ 5;
1602 for (i
= 0; i
< 3; i
++)
1608 value
= strtod(color
, &end
);
1609 if (errno
== ERANGE
)
1611 if (value
< 0.0 || value
> 1.0)
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. */
1619 colorval
|= (val
<< pos
);
1626 return make_number (colorval
);
1634 ret
= mac_color_map_lookup (colorname
);
1640 /* Gamma-correct COLOR on frame F. */
1643 gamma_correct (f
, color
)
1645 unsigned long *color
;
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
)
1669 register Lisp_Object tem
;
1670 unsigned long mac_color_ref
;
1672 tem
= x_to_mac_color (color
);
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
);
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
1703 x_decode_color (f
, arg
, def
)
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
);
1718 if (FRAME_MAC_DISPLAY_INFO (f
)->n_planes
) == 1)
1722 if (mac_defined_color (f
, SDATA (arg
), &cdef
, 1))
1725 /* defined_color failed; return an ultimate default. */
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. */
1738 x_set_foreground_color (f
, arg
, oldval
)
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
))
1757 x_set_background_color (f
, arg
, oldval
)
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
))
1774 x_set_mouse_color (f
, arg
, oldval
)
1776 Lisp_Object arg
, oldval
;
1778 Cursor cursor
, nontext_cursor
, mode_cursor
, hand_cursor
;
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 */
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
));
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
));
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
));
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
));
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
);
1842 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1843 XINT (Vx_sensitive_text_pointer_shape
));
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
));
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
))),
1872 XQueryColor (FRAME_W32_DISPLAY (f
),
1873 DefaultColormap (FRAME_W32_DISPLAY (f
),
1874 DefaultScreen (FRAME_W32_DISPLAY (f
))),
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
));
1918 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1919 #endif /* MAC_TODO */
1923 x_set_cursor_color (f
, arg
, oldval
)
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
));
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)
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
;
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
1972 x_set_border_pixel (f
, 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
))
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. */
1993 x_set_border_color (f
, arg
, oldval
)
1995 Lisp_Object arg
, oldval
;
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
);
2007 x_set_cursor_type (f
, arg
, oldval
)
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 */
2019 x_set_icon_type (f
, arg
, oldval
)
2021 Lisp_Object arg
, oldval
;
2025 if (NILP (arg
) && NILP (oldval
))
2028 if (STRINGP (arg
) && STRINGP (oldval
)
2029 && EQ (Fstring_equal (oldval
, arg
), Qt
))
2032 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
2037 result
= x_bitmap_icon (f
, arg
);
2041 error ("No icon window available");
2046 #endif /* MAC_TODO */
2049 x_set_icon_name (f
, arg
, oldval
)
2051 Lisp_Object arg
, oldval
;
2057 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2060 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2065 #if 0 /* MAC_TODO */
2066 if (f
->output_data
.w32
->icon_bitmap
!= 0)
2071 result
= x_text_icon (f
,
2072 (char *) SDATA ((!NILP (f
->icon_name
)
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
);
2091 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2094 XFlush (FRAME_W32_DISPLAY (f
));
2096 #endif /* MAC_TODO */
2101 x_set_menu_bar_lines (f
, value
, oldval
)
2103 Lisp_Object value
, oldval
;
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
))
2115 if (INTEGERP (value
))
2116 nlines
= XINT (value
);
2120 FRAME_MENU_BAR_LINES (f
) = 0;
2122 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
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
2132 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
2133 do_pending_window_change (0);
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. */
2146 x_set_tool_bar_lines (f
, value
, oldval
)
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
))
2157 /* Use VALUE only if an integer >= 0. */
2158 if (INTEGERP (value
) && XINT (value
) >= 0)
2159 nlines
= XFASTINT (value
);
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
);
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)
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. */
2200 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2201 int width
= FRAME_PIXEL_WIDTH (f
);
2202 int y
= nlines
* FRAME_LINE_HEIGHT (f
);
2205 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
2206 0, y
, width
, height
, 0);
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
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. */
2227 x_set_name (f
, name
, explicit)
2232 /* Make sure that requests from lisp code override requests from
2233 Emacs redisplay code. */
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
)
2246 /* If NAME is nil, set the name to the w32_id_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
,
2254 name
= build_string (FRAME_MAC_DISPLAY_INFO (f
)->mac_id_name
);
2257 CHECK_STRING (name
);
2259 /* Don't change the name if it's already NAME. */
2260 if (! NILP (Fstring_equal (name
, f
->name
)))
2265 /* For setting the frame title, the title parameter should override
2266 the name parameter. */
2267 if (! NILP (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
);
2283 if (strlen (SDATA (name
)) < 255)
2285 strcpy (windowTitle
, SDATA (name
));
2286 c2pstr (windowTitle
);
2287 SetWTitle (FRAME_MAC_WINDOW (f
), windowTitle
);
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
2299 x_explicitly_set_name (f
, arg
, oldval
)
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
2310 x_implicitly_set_name (f
, arg
, oldval
)
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. */
2329 x_set_title (f
, name
, old_name
)
2331 Lisp_Object name
, old_name
;
2333 /* Don't change the title if it's already NAME. */
2334 if (EQ (name
, f
->title
))
2337 update_mode_lines
= 1;
2344 if (FRAME_MAC_WINDOW (f
))
2346 if (STRING_MULTIBYTE (name
))
2347 #if 0 /* MAC_TODO: encoding title string */
2348 name
= ENCODE_SYSTEM (name
);
2357 if (strlen (SDATA (name
)) < 255)
2359 strcpy (windowTitle
, SDATA (name
));
2360 c2pstr (windowTitle
);
2361 SetWTitle (FRAME_MAC_WINDOW (f
), windowTitle
);
2370 x_set_scroll_bar_default_width (f
)
2373 /* Imitate X without X Toolkit */
2375 int wid
= FRAME_COLUMN_WIDTH (f
);
2378 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = 16; /* Aqua scroll bars. */
2379 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) +
2381 #else /* not MAC_OSX */
2382 /* Make the actual width at least 14 pixels and a multiple of a
2384 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
2386 /* Use all of that space (aside from required margins) for the
2388 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = 0;
2389 #endif /* not MAC_OSX */
2393 /* Subroutines of creating a frame. */
2396 x_get_string_resource (rdb
, name
, class)
2400 /* MAC_TODO: implement resource strings */
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! */
2416 mac_get_arg (alist
, param
, attribute
, class, type
)
2417 Lisp_Object alist
, param
;
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.
2442 read_integer (string
, NextString
)
2443 register char *string
;
2446 register int Result
= 0;
2451 else if (*string
== '-')
2456 for (; (*string
>= '0') && (*string
<= '9'); string
++)
2458 Result
= (Result
* 10) + (*string
- '0');
2460 *NextString
= string
;
2468 XParseGeometry (string
, x
, y
, width
, height
)
2471 unsigned int *width
, *height
; /* RETURN */
2474 register char *strind
;
2475 unsigned int tempWidth
, tempHeight
;
2477 char *nextCharacter
;
2479 if ((string
== NULL
) || (*string
== '\0')) return (mask
);
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
)
2489 strind
= nextCharacter
;
2493 if (*strind
== 'x' || *strind
== 'X')
2496 tempHeight
= read_integer (strind
, &nextCharacter
);
2497 if (strind
== nextCharacter
)
2499 strind
= nextCharacter
;
2500 mask
|= HeightValue
;
2503 if ((*strind
== '+') || (*strind
== '-'))
2508 tempX
= -read_integer (strind
, &nextCharacter
);
2509 if (strind
== nextCharacter
)
2511 strind
= nextCharacter
;
2518 tempX
= read_integer (strind
, &nextCharacter
);
2519 if (strind
== nextCharacter
)
2521 strind
= nextCharacter
;
2524 if ((*strind
== '+') || (*strind
== '-'))
2529 tempY
= -read_integer (strind
, &nextCharacter
);
2530 if (strind
== nextCharacter
)
2532 strind
= nextCharacter
;
2539 tempY
= read_integer (strind
, &nextCharacter
);
2540 if (strind
== nextCharacter
)
2542 strind
= nextCharacter
;
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);
2557 if (mask
& WidthValue
)
2559 if (mask
& HeightValue
)
2560 *height
= tempHeight
;
2565 #if 0 /* MAC_TODO */
2566 /* Create and set up the Mac window for frame F. */
2569 mac_window (f
, window_prompting
, minibuffer_only
)
2571 long window_prompting
;
2572 int minibuffer_only
;
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. */
2604 int explicit = f
->explicit_name
;
2606 f
->explicit_name
= 0;
2609 x_set_name (f
, name
, explicit);
2612 ShowWindow (FRAME_MAC_WINDOW (f
));
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
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");
2649 if (! EQ (icon_x
, Qunbound
))
2650 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
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
)
2659 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
2672 XGCValues gc_values
;
2676 /* Create the GCs of this frame.
2677 Note that many default values are used. */
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
,
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
,
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
,
2705 f
->output_data
.mac
->white_relief
.gc
= 0;
2706 f
->output_data
.mac
->black_relief
.gc
= 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
))));
2725 /* Free what was was allocated in x_make_gc. */
2731 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
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;
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;
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;
2777 /* Handler for signals raised during x_create_frame and
2778 x_create_top_frame. FRAME is the frame which is partially
2782 unwind_create_frame (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
))
2791 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
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
);
2806 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
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. */)
2821 Lisp_Object frame
, tem
;
2823 int minibuffer_only
= 0;
2824 long window_prompting
= 0;
2826 int count
= SPECPDL_INDEX ();
2827 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
2828 Lisp_Object display
;
2829 struct mac_display_info
*dpyinfo
= NULL
;
2832 char x_frame_name
[10];
2833 static int x_frame_count
= 2; /* begins at 2 because terminal frame is F1 */
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
))
2844 dpyinfo
= check_x_display_info (display
);
2846 kb
= dpyinfo
->kboard
;
2848 kb
= &the_only_kboard
;
2851 name
= mac_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
2853 && ! EQ (name
, Qunbound
)
2855 error ("Invalid frame name--not a string or nil");
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
))
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. */
2871 GCPRO4 (parms
, parent
, name
, frame
);
2872 tem
= mac_get_arg (parms
, Qminibuffer
, "minibuffer", "Minibuffer",
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
);
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;
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
);
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; */
2918 FRAME_KBOARD (f
) = kb
;
2921 /* Specify the parent under which to make this window. */
2925 f
->output_data
.mac
->parent_desc
= (Window
) parent
;
2926 f
->output_data
.mac
->explicit_parent
= 1;
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
2936 if (EQ (name
, Qunbound
) || NILP (name
))
2938 f
->name
= build_string (dpyinfo
->mac_id_name
);
2939 f
->explicit_name
= 0;
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. */
2954 font
= mac_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
2957 /* First, try whatever font the caller has specified. */
2960 tem
= Fquery_fontset (font
, Qnil
);
2962 font
= x_new_fontset (f
, SDATA (tem
));
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");
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
2988 if (NILP (Fassq (Qinternal_border_width
, parms
)))
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
),
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
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); */
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
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. */
3101 x_wm_set_size_hint (f
, window_prompting
, 0);
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
))
3116 #if 0 /* MAC_TODO: really no iconify on Mac */
3117 if (EQ (visibility
, Qicon
))
3118 x_iconify_frame (f
);
3121 if (! NILP (visibility
))
3122 x_make_frame_visible (f
);
3124 /* Must have been Qnil. */
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. */
3140 x_get_focus_frame (frame
)
3141 struct frame
*frame
;
3143 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3145 if (! dpyinfo
->x_focus_frame
)
3148 XSETFRAME (xfocus
, dpyinfo
->x_focus_frame
);
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. */)
3155 Lisp_Object color
, frame
;
3158 FRAME_PTR f
= check_x_frame (frame
);
3160 CHECK_STRING (color
);
3162 if (mac_defined_color (f
, SDATA (color
), &foo
, 0))
3168 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
3169 doc
: /* Internal function called by `color-values', which see. */)
3171 Lisp_Object color
, frame
;
3174 FRAME_PTR f
= check_x_frame (frame
);
3176 CHECK_STRING (color
);
3178 if (mac_defined_color (f
, SDATA (color
), &foo
, 0))
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
);
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. */)
3194 Lisp_Object display
;
3196 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
3198 if (!dpyinfo
->color_p
)
3204 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
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. */)
3212 Lisp_Object display
;
3214 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
3216 if (dpyinfo
->n_planes
<= 1)
3222 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
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. */)
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. */)
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
,
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. */)
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
,
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. */)
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
,
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. */)
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. */)
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. */)
3315 Lisp_Object display
;
3317 int mac_major_version
, mac_minor_version
;
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. */)
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. */)
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
);
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. */)
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
);
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. */)
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. */)
3400 Lisp_Object display
;
3402 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
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"));
3414 error ("Display has an unknown visual class");
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. */)
3428 Lisp_Object display
;
3435 register struct frame
*f
;
3437 return FRAME_PIXEL_WIDTH (f
);
3442 register struct frame
*f
;
3444 return FRAME_PIXEL_HEIGHT (f
);
3449 register struct frame
*f
;
3451 return FRAME_COLUMN_WIDTH (f
);
3456 register struct frame
*f
;
3458 return FRAME_LINE_HEIGHT (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
)
3476 struct mac_display_info
*dpyinfo
;
3478 CHECK_STRING (name
);
3480 for (dpyinfo
= &one_mac_display_info
, names
= x_display_name_list
;
3482 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
3485 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
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
));
3499 error ("Cannot connect to server %s", SDATA (name
));
3502 XSETFASTINT (Vwindow_system_version
, 3);
3507 #if 0 /* MAC_TODO: implement network support */
3508 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
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
);
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
));
3542 if (!NILP (must_succeed
))
3543 fatal ("Cannot connect to server %s.\n",
3546 error ("Cannot connect to server %s", SDATA (display
));
3551 XSETFASTINT (Vwindow_system_version
, 3);
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. */)
3561 Lisp_Object display
;
3563 struct mac_display_info
*dpyinfo
= check_x_display_info (display
);
3566 if (dpyinfo
->reference_count
> 0)
3567 error ("Display still has frames on it");
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
);
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
;
3595 for (tail
= x_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
3596 result
= Fcons (XCAR (XCAR (tail
)), 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. */)
3609 Lisp_Object display
, on
;
3616 /***********************************************************************
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. */
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
*,
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. */
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
;
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
)
3685 struct image_type
*type
;
3687 for (type
= image_types
; type
; type
= type
->next
)
3688 if (EQ (symbol
, *type
->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
3703 valid_image_p (object
)
3708 if (IMAGEP (object
))
3712 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
3713 if (EQ (XCAR (tem
), QCtype
))
3716 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
3718 struct image_type
*type
;
3719 type
= lookup_image_type (XCAR (tem
));
3721 valid_p
= type
->valid_p (object
);
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. */
3739 image_error (format
, arg1
, arg2
)
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
,
3756 IMAGE_STRING_OR_NIL_VALUE
,
3758 IMAGE_POSITIVE_INTEGER_VALUE
,
3759 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
3760 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
3762 IMAGE_INTEGER_VALUE
,
3763 IMAGE_FUNCTION_VALUE
,
3768 /* Structure used when parsing image specifications. */
3770 struct image_keyword
3772 /* Name of keyword. */
3775 /* The type of value allowed. */
3776 enum image_value_type type
;
3778 /* Non-zero means key must be present. */
3781 /* Used to recognize duplicate keywords in a property list. */
3784 /* The value that was found. */
3789 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
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. */
3801 parse_image_spec (spec
, keywords
, nkeywords
, type
)
3803 struct image_keyword
*keywords
;
3813 plist
= XCDR (spec
);
3814 while (CONSP (plist
))
3816 Lisp_Object key
, value
;
3818 /* First element of a pair must be a symbol. */
3820 plist
= XCDR (plist
);
3824 /* There must follow a value. */
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)
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)
3846 /* Check type of value against allowed type. */
3847 switch (keywords
[i
].type
)
3849 case IMAGE_STRING_VALUE
:
3850 if (!STRINGP (value
))
3854 case IMAGE_STRING_OR_NIL_VALUE
:
3855 if (!STRINGP (value
) && !NILP (value
))
3859 case IMAGE_SYMBOL_VALUE
:
3860 if (!SYMBOLP (value
))
3864 case IMAGE_POSITIVE_INTEGER_VALUE
:
3865 if (!INTEGERP (value
) || XINT (value
) <= 0)
3869 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
3870 if (INTEGERP (value
) && XINT (value
) >= 0)
3873 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
3874 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
3878 case IMAGE_ASCENT_VALUE
:
3879 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
3881 else if (INTEGERP (value
)
3882 && XINT (value
) >= 0
3883 && XINT (value
) <= 100)
3887 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
3888 if (!INTEGERP (value
) || XINT (value
) < 0)
3892 case IMAGE_DONT_CHECK_VALUE_TYPE
:
3895 case IMAGE_FUNCTION_VALUE
:
3896 value
= indirect_function (value
);
3898 || COMPILEDP (value
)
3899 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
3903 case IMAGE_NUMBER_VALUE
:
3904 if (!INTEGERP (value
) && !FLOATP (value
))
3908 case IMAGE_INTEGER_VALUE
:
3909 if (!INTEGERP (value
))
3913 case IMAGE_BOOL_VALUE
:
3914 if (!NILP (value
) && !EQ (value
, Qt
))
3923 if (EQ (key
, QCtype
) && !EQ (type
, value
))
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)
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. */
3941 image_spec_value (spec
, key
, found
)
3942 Lisp_Object spec
, key
;
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
))
3957 return XCAR (XCDR (tail
));
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
;
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
;
3988 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
3989 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
3991 size
= Fcons (make_number (width
), make_number (height
));
3994 error ("Invalid image specification");
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. */)
4005 Lisp_Object spec
, frame
;
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
);
4019 error ("Invalid image specification");
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
)
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
);
4049 img
->data
.lisp_val
= Qnil
;
4050 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
4056 /* Free image IMG which was used on frame F, including its resources. */
4065 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
4067 /* Remove IMG from the hash table of its cache. */
4069 img
->prev
->next
= img
->next
;
4071 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = 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
);
4085 /* Prepare image IMG for display on frame F. Must be called before
4086 drawing an image. */
4089 prepare_image_for_display (f
, img
)
4095 /* We're about to display IMG, so set its timestamp to `now'. */
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
)
4114 int height
= img
->height
+ img
->vmargin
;
4117 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
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;
4127 ascent
= height
/ 2;
4130 ascent
= height
* img
->ascent
/ 100.0;
4136 /* Image background colors. */
4138 static unsigned long
4139 four_corners_best (ximg
, width
, height
)
4141 unsigned long width
, height
;
4143 unsigned long corners
[4], best
;
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
)
4157 for (j
= n
= 0; j
< 4; ++j
)
4158 if (corners
[i
] == corners
[j
])
4162 best
= corners
[i
], best_count
= n
;
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. */
4173 image_background (img
, f
, 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
;
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
);
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
)
4208 if (! img
->background_transparent_valid
)
4209 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4213 int free_mask
= !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
);
4223 XDestroyImage (mask
);
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,
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
,
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. */
4254 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
4257 int pixmap_p
, mask_p
, colors_p
;
4259 if (pixmap_p
&& img
->pixmap
)
4261 XFreePixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
4263 img
->background_valid
= 0;
4266 if (mask_p
&& img
->mask
)
4268 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
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
);
4278 xfree (img
->colors
);
4284 /* Free X resources of image IMG which is used on frame F. */
4287 x_clear_image (f
, img
)
4292 x_clear_image_1 (f
, img
, 1, 1, 1);
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
4302 static unsigned long
4303 x_alloc_image_color (f
, img
, color_name
, dflt
)
4306 Lisp_Object color_name
;
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. */
4320 (unsigned long *) xrealloc (img
->colors
,
4321 img
->ncolors
* sizeof *img
->colors
);
4322 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
4323 result
= color
.pixel
;
4333 /***********************************************************************
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
*
4347 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
4350 bzero (c
, sizeof *c
);
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
);
4360 /* Free image cache of frame F. Be aware that X frames share images
4364 free_image_cache (f
)
4367 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
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
]);
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. */
4393 clear_image_cache (f
, force_p
)
4397 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
4399 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
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. */
4412 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
4414 struct image
*img
= c
->images
[i
];
4416 && (force_p
|| img
->timestamp
< old
))
4418 free_image (f
, img
);
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. */
4429 Lisp_Object tail
, frame
;
4431 FOR_EACH_FRAME (tail
, frame
)
4433 struct frame
*f
= XFRAME (frame
);
4435 && FRAME_X_IMAGE_CACHE (f
) == c
)
4436 clear_current_matrices (f
);
4439 ++windows_or_buffers_changed
;
4447 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
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. */)
4459 FOR_EACH_FRAME (tail
, frame
)
4460 if (FRAME_MAC_P (XFRAME (frame
)))
4461 clear_image_cache (XFRAME (frame
), 1);
4464 clear_image_cache (check_x_frame (frame
), 1);
4470 /* Compute masks and transform image IMG on frame F, as specified
4471 by the image's specification, */
4474 postprocess_image (f
, img
)
4478 /* Manipulation of the image's mask. */
4481 Lisp_Object conversion
, spec
;
4486 /* `:heuristic-mask t'
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
4494 means remove a mask, if any. */
4496 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
4498 x_build_heuristic_mask (f
, img
, mask
);
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
)));
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
);
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
))
4529 else if (EQ (conversion
, Qemboss
))
4531 else if (CONSP (conversion
)
4532 && EQ (XCAR (conversion
), Qedge_detection
))
4535 tem
= XCDR (conversion
);
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
)
4553 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
4557 struct gcpro gcpro1
;
4560 /* F must be a window-system frame, and SPEC must be a valid image
4562 xassert (FRAME_WINDOW_P (f
));
4563 xassert (valid_image_p (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
)))
4575 /* If not found, create a new image and cache it. */
4578 extern Lisp_Object Qpostscript
;
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
)
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
);
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
);
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
);
4653 /* We're using IMG, so set its timestamp to `now'. */
4654 EMACS_GET_TIME (now
);
4655 img
->timestamp
= EMACS_SECS (now
);
4659 /* Value is the image id. */
4664 /* Cache image IMG in the image cache of frame F. */
4667 cache_image (f
, img
)
4671 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
4674 /* Find a free slot in c->images. */
4675 for (i
= 0; i
< c
->used
; ++i
)
4676 if (c
->images
[i
] == NULL
)
4679 /* If no free slot found, maybe enlarge c->images. */
4680 if (i
== c
->used
&& c
->used
== c
->size
)
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. */
4693 /* Add IMG to the cache's hash table. */
4694 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
4695 img
->next
= c
->buckets
[i
];
4697 img
->next
->prev
= img
;
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. */
4707 forall_images_in_image_cache (f
, fn
)
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
);
4717 for (i
= 0; i
< c
->used
; ++i
)
4726 /***********************************************************************
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
)
4738 int width
, height
, depth
;
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
);
4751 x_destroy_x_image (*ximg
);
4753 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
4757 LockPixels (GetGWorldPixMap (*pixmap
));
4763 x_destroy_x_image (ximg
)
4766 xassert (interrupt_input_blocked
);
4768 XDestroyImage (ximg
);
4772 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
4777 xassert (ximg
== pixmap
);
4782 /***********************************************************************
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. */
4795 x_find_image_file (file
)
4798 Lisp_Object file_found
, search_path
;
4799 struct gcpro gcpro1
, gcpro2
;
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
);
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. */
4824 slurp_file (file
, size
)
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
))
4856 /***********************************************************************
4857 Image Load Functions
4858 ***********************************************************************/
4860 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
4863 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
4868 find_image_fsspec (specified_file
, file
, fss
)
4869 Lisp_Object specified_file
, *file
;
4872 #if TARGET_API_MAC_CARBON
4875 Str255 mac_pathname
;
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
);
4887 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
4889 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
4891 c2pstr (mac_pathname
);
4892 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
4899 image_load_qt_1 (f
, img
, type
, fss
, dh
)
4907 GraphicsImportComponent gi
;
4910 short draw_all_pixels
;
4911 Lisp_Object specified_bg
;
4916 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
4920 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
4925 /* read from file system spec */
4926 err
= GraphicsImportSetDataFile (gi
, fss
);
4929 image_error ("Cannot set fsspec to graphics importer for '%s'",
4936 /* read from data handle */
4937 err
= GraphicsImportSetDataHandle (gi
, dh
);
4940 image_error ("Cannot set data handle to graphics importer for `%s'",
4945 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
4948 image_error ("Error reading `%s'", img
->spec
, Qnil
);
4951 width
= img
->width
= rect
.right
- rect
.left
;
4952 height
= img
->height
= rect
.bottom
- rect
.top
;
4953 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
4955 /* Don't check the error code here. It may have an undocumented
4959 image_error ("Error reading `%s'", img
->spec
, Qnil
);
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
))
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
);
4989 EraseRect (&(ximg
->portRect
));
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
);
5006 CloseComponent (gi
);
5011 /* Load an image using the QuickTime Graphics Importer.
5012 Note: The alpha channel does not work for PNG images. */
5014 image_load_quicktime (f
, img
, type
)
5019 Lisp_Object specified_file
;
5020 Lisp_Object specified_data
;
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 */
5032 err
= find_image_fsspec (specified_file
, &file
, &fss
);
5036 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5038 image_error ("Cannot open `%s'", file
, Qnil
);
5041 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
5045 /* Memory source! */
5049 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
5052 image_error ("Cannot allocate data handle for `%s'",
5056 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
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
;
5074 init_image_func_pointer ()
5076 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
5078 MyCGImageCreateWithPNGDataProvider
5079 = (CGImageCreateWithPNGDataProviderProcType
)
5080 NSAddressOfSymbol (NSLookupAndBindSymbol
5081 ("_CGImageCreateWithPNGDataProvider"));
5084 MyCGImageCreateWithPNGDataProvider
= NULL
;
5089 image_load_quartz2d (f
, img
, png_p
)
5094 Lisp_Object file
, specified_file
;
5095 Lisp_Object specified_data
, specified_bg
;
5096 struct gcpro gcpro1
;
5097 CGDataProviderRef source
;
5101 XImagePtr ximg
= NULL
;
5102 CGContextRef context
;
5105 /* Open the file. */
5106 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5107 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5112 if (NILP (specified_data
))
5117 file
= x_find_image_file (specified_file
);
5118 if (!STRINGP (file
))
5120 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5124 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
5125 kCFStringEncodingUTF8
);
5126 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
5127 kCFURLPOSIXPathStyle
, 0);
5129 source
= CGDataProviderCreateWithURL (url
);
5133 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
5134 SBYTES (specified_data
), NULL
);
5137 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
5138 kCGRenderingIntentDefault
);
5140 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
5141 kCGRenderingIntentDefault
);
5143 CGDataProviderRelease (source
);
5147 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
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
);
5171 rectangle
= CGRectMake (0, 0, width
, height
);
5172 QDBeginCGContext (ximg
, &context
);
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
);
5198 /***********************************************************************
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
,
5206 static int xbm_image_p
P_ ((Lisp_Object object
));
5207 static int xbm_read_bitmap_data
P_ ((char *, char *, int *, int *,
5209 static int xbm_file_p
P_ ((Lisp_Object
));
5212 /* Indices of image specification fields in xbm_format, below. */
5214 enum xbm_keyword_index
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
=
5263 /* Tokens returned from xbm_scan. */
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
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
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
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. */
5302 xbm_image_p (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
))
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
)
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
)
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
)
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
5345 /* Number of elements of the vector must be >= height. */
5346 if (XVECTOR (data
)->size
< height
)
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
];
5358 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
5361 else if (BOOL_VECTOR_P (elt
))
5363 if (XBOOL_VECTOR (elt
)->size
< width
)
5370 else if (STRINGP (data
))
5373 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
5376 else if (BOOL_VECTOR_P (data
))
5378 if (XBOOL_VECTOR (data
)->size
< width
* height
)
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. */
5396 xbm_scan (s
, end
, sval
, ival
)
5405 /* Skip white space. */
5406 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5411 else if (isdigit (c
))
5413 int value
= 0, digit
;
5415 if (c
== '0' && *s
< end
)
5418 if (c
== 'x' || c
== 'X')
5425 else if (c
>= 'a' && c
<= 'f')
5426 digit
= c
- 'a' + 10;
5427 else if (c
>= 'A' && c
<= 'F')
5428 digit
= c
- 'A' + 10;
5431 value
= 16 * value
+ digit
;
5434 else if (isdigit (c
))
5438 && (c
= *(*s
)++, isdigit (c
)))
5439 value
= 8 * value
+ c
- '0';
5446 && (c
= *(*s
)++, isdigit (c
)))
5447 value
= 10 * value
+ c
- '0';
5455 else if (isalpha (c
) || c
== '_')
5459 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
5466 else if (c
== '/' && **s
== '*')
5468 /* C-style comment. */
5470 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
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. */
5491 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
5492 char *contents
, *end
;
5493 int *width
, *height
;
5494 unsigned char **data
;
5497 char buffer
[BUFSIZ
];
5500 int bytes_per_line
, i
, nbytes
;
5506 LA1 = xbm_scan (&s, end, buffer, &value)
5508 #define expect(TOKEN) \
5509 if (LA1 != (TOKEN)) \
5514 #define expect_ident(IDENT) \
5515 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
5520 *width
= *height
= -1;
5523 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
5525 /* Parse defines for width, height and hot-spots. */
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)
5538 else if (strcmp (p
, "height") == 0)
5541 expect (XBM_TK_NUMBER
);
5544 if (*width
< 0 || *height
< 0)
5546 else if (data
== NULL
)
5549 /* Parse bits. Must start with `static'. */
5550 expect_ident ("static");
5551 if (LA1
== XBM_TK_IDENT
)
5553 if (strcmp (buffer
, "unsigned") == 0)
5556 expect_ident ("char");
5558 else if (strcmp (buffer
, "short") == 0)
5562 if (*width
% 16 && *width
% 16 < 9)
5565 else if (strcmp (buffer
, "char") == 0)
5573 expect (XBM_TK_IDENT
);
5579 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
5580 nbytes
= bytes_per_line
* *height
;
5581 p
= *data
= (char *) xmalloc (nbytes
);
5585 for (i
= 0; i
< nbytes
; i
+= 2)
5588 expect (XBM_TK_NUMBER
);
5591 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
5594 if (LA1
== ',' || LA1
== '}')
5602 for (i
= 0; i
< nbytes
; ++i
)
5605 expect (XBM_TK_NUMBER
);
5609 if (LA1
== ',' || LA1
== '}')
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
5639 xbm_load_image (f
, img
, contents
, end
)
5642 char *contents
, *end
;
5645 unsigned char *data
;
5648 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
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
);
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
);
5661 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
5662 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
5665 background
= x_alloc_image_color (f
, img
, value
, background
);
5666 img
->background
= background
;
5667 img
->background_valid
= 1;
5671 = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f
),
5672 FRAME_MAC_WINDOW (f
),
5674 img
->width
, img
->height
,
5675 foreground
, background
,
5679 if (img
->pixmap
== 0)
5681 x_clear_image (f
, img
);
5682 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
5688 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
5694 /* Value is non-zero if DATA looks like an in-memory XBM file. */
5701 return (STRINGP (data
)
5702 && xbm_read_bitmap_data (SDATA (data
),
5709 /* Fill image IMG which is used on frame F with pixmap data. Value is
5710 non-zero if successful. */
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
))
5729 struct gcpro gcpro1
;
5731 file
= x_find_image_file (file_name
);
5733 if (!STRINGP (file
))
5735 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
5740 contents
= slurp_file (SDATA (file
), &size
);
5741 if (contents
== NULL
)
5743 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
5748 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
5753 struct image_keyword fmt
[XBM_LAST
];
5756 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
5757 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
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
);
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
,
5784 if (fmt
[XBM_BACKGROUND
].count
5785 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
5786 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
5789 if (in_memory_file_p
)
5790 success_p
= xbm_load_image (f
, img
, SDATA (data
),
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
];
5806 bcopy (SDATA (line
), p
, nbytes
);
5808 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
5811 else if (STRINGP (data
))
5812 bits
= SDATA (data
);
5814 bits
= XBOOL_VECTOR (data
)->data
;
5816 /* Create the pixmap. */
5817 depth
= one_mac_display_info
.n_planes
;
5819 = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f
),
5820 FRAME_MAC_WINDOW (f
),
5822 img
->width
, img
->height
,
5823 foreground
, background
,
5829 image_error ("Unable to create pixmap for XBM image `%s'",
5831 x_clear_image (f
, img
);
5841 /***********************************************************************
5843 ***********************************************************************/
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. */
5857 /* Indices of image specification fields in xpm_format, below. */
5859 enum xpm_keyword_index
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
=
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
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
);
5917 || !STRINGP (XCAR (sym
))
5918 || !STRINGP (XCDR (sym
)))
5920 color_symbols
= XCDR (color_symbols
);
5923 return NILP (color_symbols
);
5927 /* Value is non-zero if OBJECT is a valid XPM image specification. */
5930 xpm_image_p (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. */
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
))
5979 XpmColorSymbol
*xpm_syms
;
5982 attrs
.valuemask
|= XpmColorSymbols
;
5984 /* Count number of symbols. */
5985 attrs
.numsymbols
= 0;
5986 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
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;
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
);
6022 rc
= XpmReadFileToPixmap (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
6023 SDATA (file
), &img
->pixmap
, &img
->mask
,
6028 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
6029 rc
= XpmCreatePixmapFromBuffer (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
6031 &img
->pixmap
, &img
->mask
,
6035 if (rc
== XpmSuccess
)
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
);
6057 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
6060 case XpmFileInvalid
:
6061 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
6065 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
6068 case XpmColorFailed
:
6069 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
6073 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
6078 return rc
== XpmSuccess
;
6081 #endif /* HAVE_XPM != 0 */
6084 #if 0 /* MAC_TODO : Color tables on Mac. */
6085 /***********************************************************************
6087 ***********************************************************************/
6089 /* An entry in the color table mapping an RGB color to a pixel color. */
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. */
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. */
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. */
6134 struct ct_color
*p
, *next
;
6136 for (i
= 0; i
< CT_SIZE
; ++i
)
6137 for (p
= ct_table
[i
]; p
; p
= next
)
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
)
6158 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
6159 int i
= hash
% CT_SIZE
;
6162 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6163 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
6172 color
= RGB_TO_ULONG (r
, g
, b
);
6174 ++ct_colors_allocated
;
6176 p
= (struct ct_color
*) xmalloc (sizeof *p
);
6181 p
->next
= ct_table
[i
];
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
)
6195 unsigned long pixel
;
6197 int i
= pixel
% CT_SIZE
;
6200 for (p
= ct_table
[i
]; p
; p
= p
->next
)
6201 if (p
->pixel
== pixel
)
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
);
6220 ++ct_colors_allocated
;
6222 p
= (struct ct_color
*) xmalloc (sizeof *p
);
6227 p
->next
= ct_table
[i
];
6231 return FRAME_FOREGROUND_PIXEL (f
);
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
)
6246 unsigned long *colors
;
6248 if (ct_colors_allocated
== 0)
6255 colors
= (unsigned long *) xmalloc (ct_colors_allocated
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
;
6268 static unsigned long
6269 lookup_rgb_color (f
, r
, g
, b
)
6273 unsigned long pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
6275 gamma_correct (f
, &pixel
);
6278 #endif /* MAC_TODO */
6281 /***********************************************************************
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
6292 int cross_disabled_images
;
6294 /* Edge detection matrices for different edge-detection
6297 static int emboss_matrix
[9] = {
6299 2, -1, 0, /* y - 1 */
6301 0, 1, -2 /* y + 1 */
6304 static int laplace_matrix
[9] = {
6306 1, 0, 0, /* y - 1 */
6308 0, 0, -1 /* y + 1 */
6311 /* Value is the intensity of the color whose red/green/blue values
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. */
6324 x_to_xcolors (f
, img
, rgb_p
)
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. */
6342 for (y
= 0; y
< img
->height
; ++y
)
6346 for (x
= 0; x
< img
->width
; ++x
, ++p
)
6348 p
->pixel
= XGetPixel (ximg
, x
, y
);
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
);
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. */
6369 x_from_xcolors (f
, img
, colors
)
6379 #if 0 /* TODO: color tables. */
6380 init_color_table ();
6383 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
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
);
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 ();
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
6416 x_detect_edges (f
, img
, matrix
, color_adjust
)
6419 int matrix
[9], color_adjust
;
6421 XColor
*colors
= x_to_xcolors (f
, img
, 1);
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
;
6457 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
6458 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++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
);
6475 x_from_xcolors (f
, img
, new);
6481 /* Perform the pre-defined `emboss' edge-detection on image IMG
6489 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
6493 /* Perform the pre-defined `laplace' edge-detection on 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
6517 x_edge_detection (f
, img
, matrix
, color_adjust
)
6520 Lisp_Object matrix
, color_adjust
;
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. */
6549 x_disable_image (f
, 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);
6562 const int h
= 15000;
6563 const int l
= 30000;
6565 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
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
6579 if (dpyinfo
->n_planes
< 2 || cross_disabled_images
)
6581 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
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,
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,
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. */
6614 x_build_heuristic_mask (f
, img
, 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;
6626 XFreePixmap (FRAME_X_DISPLAY (f
), img
->mask
);
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
);
6637 /* Get the X image of IMG->pixmap. */
6638 ximg
= XGetImage (dpy
, img
->pixmap
, 0, 0, img
->width
, img
->height
,
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;
6649 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
6651 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
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
);
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. */
6698 /* Indices of image specification fields in gs_format, below. */
6700 enum pbm_keyword_index
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
=
6746 /* Return non-zero if OBJECT is a valid PBM image specification. */
6749 pbm_image_p (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
))
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
6769 pbm_scan_number (s
, end
)
6770 unsigned char **s
, *end
;
6772 int c
= 0, val
= -1;
6776 /* Skip white-space. */
6777 while (*s
< end
&& (c
= *(*s
)++, isspace (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. */
6790 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
6791 val
= 10 * val
+ c
- '0';
6802 /* Load PBM image IMG for use on frame F. */
6810 int width
, height
, max_color_idx
= 0;
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
;
6819 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
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
);
6833 contents
= slurp_file (SDATA (file
), &size
);
6834 if (contents
== NULL
)
6836 image_error ("Error reading `%s'", file
, Qnil
);
6842 end
= contents
+ size
;
6847 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
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
);
6865 raw_p
= 0, type
= PBM_MONO
;
6869 raw_p
= 0, type
= PBM_GRAY
;
6873 raw_p
= 0, type
= PBM_COLOR
;
6877 raw_p
= 1, type
= PBM_MONO
;
6881 raw_p
= 1, type
= PBM_GRAY
;
6885 raw_p
= 1, type
= PBM_COLOR
;
6889 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
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;
6907 || (type
!= PBM_MONO
&& max_color_idx
< 0))
6910 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
6911 &ximg
, &img
->pixmap
))
6914 #if 0 /* TODO: color tables. */
6915 /* Initialize the color hash table. */
6916 init_color_table ();
6919 if (type
== PBM_MONO
)
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
)
6953 g
= pbm_scan_number (&p
, end
);
6955 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
6960 for (y
= 0; y
< height
; ++y
)
6961 for (x
= 0; x
< width
; ++x
)
6965 if (type
== PBM_GRAY
)
6966 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
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'",
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 ();
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
);
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. */
7036 /* Indices of image specification fields in png_format, below. */
7038 enum png_keyword_index
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
=
7082 /* Return non-zero if OBJECT is a valid PNG image specification. */
7085 png_image_p (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
))
7094 /* Must specify either the :data or :file keyword. */
7095 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
7106 if (MyCGImageCreateWithPNGDataProvider
)
7107 return image_load_quartz2d (f
, img
, 1);
7110 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
7114 #if defined HAVE_LIBPNG_PNG_H
7115 # include <libpng/png.h>
7120 /* Error and warning handlers installed when the PNG library
7124 my_png_error (png_ptr
, msg
)
7125 png_struct
*png_ptr
;
7128 xassert (png_ptr
!= NULL
);
7129 image_error ("PNG error: %s", build_string (msg
), Qnil
);
7130 longjmp (png_ptr
->jmpbuf
, 1);
7135 my_png_warning (png_ptr
, msg
)
7136 png_struct
*png_ptr
;
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. */
7158 png_read_from_memory (png_ptr
, data
, length
)
7159 png_structp png_ptr
;
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
7181 Lisp_Object file
, specified_file
;
7182 Lisp_Object specified_data
;
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
;
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
;
7195 png_uint_32 row_bytes
;
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
);
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
);
7216 /* Open the image file. */
7217 fp
= fopen (SDATA (file
), "rb");
7220 image_error ("Cannot open image file `%s'", file
, Qnil
);
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
);
7238 /* Read from memory. */
7239 tbr
.bytes
= SDATA (specified_data
);
7240 tbr
.len
= SBYTES (specified_data
);
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
);
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
);
7261 if (fp
) fclose (fp
);
7266 info_ptr
= png_create_info_struct (png_ptr
);
7269 png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
7270 if (fp
) fclose (fp
);
7275 end_info
= png_create_info_struct (png_ptr
);
7278 png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
7279 if (fp
) fclose (fp
);
7284 /* Set error jump-back. We come back here when the PNG library
7285 detects an error. */
7286 if (setjmp (png_ptr
->jmpbuf
))
7290 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
7293 if (fp
) fclose (fp
);
7298 /* Read image info. */
7299 if (!NILP (specified_data
))
7300 png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
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
))
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
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. */
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);
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
);
7349 /* Use the standard default for the image gamma. */
7350 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
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. */
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. */
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);
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. */
7396 cmap
= FRAME_X_COLORMAP (f
);
7397 x_query_color (f
, &color
);
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
);
7438 /* Create the X image and pixmap. */
7439 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
7443 /* Create an image and pixmap serving as mask if the PNG image
7444 contains an alpha channel. */
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
);
7456 /* Fill the X image and mask from PNG data. */
7457 #if 0 /* TODO: Color tables. */
7458 init_color_table ();
7461 for (y
= 0; y
< height
; ++y
)
7463 png_byte
*p
= rows
[y
];
7465 for (x
= 0; x
< width
; ++x
)
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. */
7493 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
7499 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7500 /* Set IMG's background color from the PNG image, unless the user
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 ();
7518 png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
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. */
7535 /* Fill in the background_transparent field while we have the mask
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
);
7547 #endif /* HAVE_PNG */
7551 /***********************************************************************
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. */
7562 /* Indices of image specification fields in gs_format, below. */
7564 enum jpeg_keyword_index
7573 JPEG_HEURISTIC_MASK
,
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
=
7608 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7611 jpeg_image_p (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
))
7621 /* Must specify either the :data or :file keyword. */
7622 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
7633 return image_load_quartz2d (f
, img
, 0);
7635 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7640 /* Work around a warning about HAVE_STDLIB_H being redefined in
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>
7651 #ifdef HAVE_STLIB_H_1
7652 #define HAVE_STDLIB_H 1
7655 struct my_jpeg_error_mgr
7657 struct jpeg_error_mgr pub
;
7658 jmp_buf setjmp_buffer
;
7663 my_error_exit (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. */
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. */
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;
7703 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7704 is the JPEG data source manager. */
7707 our_skip_input_data (cinfo
, num_bytes
)
7708 j_decompress_ptr cinfo
;
7711 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->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. */
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. */
7739 jpeg_memory_src (cinfo
, data
, len
)
7740 j_decompress_ptr cinfo
;
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. */
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
;
7781 int row_stride
, x
, y
;
7782 XImagePtr ximg
= NULL
;
7784 unsigned long *colors
;
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
);
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
);
7804 fp
= fopen (SDATA (file
), "r");
7807 image_error ("Cannot open `%s'", file
, Qnil
);
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)
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. */
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
);
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
);
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. */
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;
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 ();
7889 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_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 ();
7910 row_stride
= width
* cinfo
.output_components
;
7911 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
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
]]);
7921 jpeg_finish_decompress (&cinfo
);
7922 jpeg_destroy_decompress (&cinfo
);
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
);
7937 #endif /* HAVE_JPEG */
7941 /***********************************************************************
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. */
7952 /* Indices of image specification fields in tiff_format, below. */
7954 enum tiff_keyword_index
7963 TIFF_HEURISTIC_MASK
,
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
=
7998 /* Return non-zero if OBJECT is a valid TIFF image specification. */
8001 tiff_image_p (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
))
8010 /* Must specify either the :data or :file keyword. */
8011 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
8021 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
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.
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
8039 unsigned char *bytes
;
8047 tiff_read_from_memory (data
, buf
, size
)
8052 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
8054 if (size
> src
->len
- src
->index
)
8056 bcopy (src
->bytes
+ src
->index
, buf
, size
);
8063 tiff_write_from_memory (data
, buf
, size
)
8073 tiff_seek_in_memory (data
, off
, whence
)
8078 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
8083 case SEEK_SET
: /* Go from beginning of source. */
8087 case SEEK_END
: /* Go from end of source. */
8088 idx
= src
->len
+ off
;
8091 case SEEK_CUR
: /* Go from current position. */
8092 idx
= src
->index
+ off
;
8095 default: /* Invalid `whence'. */
8099 if (idx
> src
->len
|| idx
< 0)
8108 tiff_close_memory (data
)
8117 tiff_mmap_memory (data
, pbase
, psize
)
8122 /* It is already _IN_ memory. */
8128 tiff_unmap_memory (data
, base
, size
)
8133 /* We don't need to do this. */
8138 tiff_size_of_memory (data
)
8141 return ((tiff_memory_source
*) data
)->len
;
8146 tiff_error_handler (title
, format
, ap
)
8147 const char *title
, *format
;
8153 len
= sprintf (buf
, "TIFF error: %s ", title
);
8154 vsprintf (buf
+ len
, format
, ap
);
8155 add_to_log (buf
, Qnil
, Qnil
);
8160 tiff_warning_handler (title
, format
, ap
)
8161 const char *title
, *format
;
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
8181 Lisp_Object file
, specified_file
;
8182 Lisp_Object specified_data
;
8184 int width
, height
, x
, y
;
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
);
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
);
8210 /* Try to open the image file. */
8211 tiff
= TIFFOpen (SDATA (file
), "r");
8214 image_error ("Cannot open `%s'", file
, Qnil
);
8221 /* Memory source! */
8222 memsrc
.bytes
= SDATA (specified_data
);
8223 memsrc
.len
= SBYTES (specified_data
);
8226 tiff
= TIFFClientOpen ("memory_source", "r", &memsrc
,
8227 (TIFFReadWriteProc
) tiff_read_from_memory
,
8228 (TIFFReadWriteProc
) tiff_write_from_memory
,
8229 tiff_seek_in_memory
,
8231 tiff_size_of_memory
,
8237 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
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);
8253 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
8259 /* Create the X image and pixmap. */
8260 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8267 #if 0 /* TODO: Color tables. */
8268 /* Initialize the color table. */
8269 init_color_table ();
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 ();
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
);
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. */
8324 /* Indices of image specification fields in gif_format, below. */
8326 enum gif_keyword_index
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
=
8372 /* Return non-zero if OBJECT is a valid GIF image specification. */
8375 gif_image_p (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
))
8384 /* Must specify either the :data or :file keyword. */
8385 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
8395 Lisp_Object specified_file
, file
;
8396 Lisp_Object specified_data
;
8398 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8406 Lisp_Object specified_bg
;
8412 struct gcpro gcpro1
;
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 */
8424 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8428 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8433 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8434 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8438 if (!graphic_p
&& !movie_p
)
8440 if (prefer_graphic_p
)
8441 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8442 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8445 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8446 CloseMovieFile (refnum
);
8449 image_error ("Error reading `%s'", file
, Qnil
);
8455 /* Memory source! */
8457 long file_type_atom
[3];
8459 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8462 image_error ("Cannot allocate data handle for `%s'",
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
));
8473 err
= PtrAndHand ("\p", dref
, 1);
8475 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8478 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8481 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8482 &movie_p
, &prefer_graphic_p
, 0);
8486 if (!graphic_p
&& !movie_p
)
8488 if (prefer_graphic_p
)
8492 DisposeHandle (dref
);
8493 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8497 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8498 HandleDataHandlerSubType
);
8499 DisposeHandle (dref
);
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'",
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
))
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
);
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
);
8556 image_error ("Cannot open `%s'", file
, Qnil
);
8559 DisposeTrackMedia (media
);
8561 DisposeMovieTrack (track
);
8563 DisposeMovie (movie
);
8571 #define DrawText gif_DrawText /* avoid conflict with QuickdrawText.h */
8572 #include <gif_lib.h>
8575 /* Reading a GIF image from memory
8576 Based on the PNG memory stuff to a certain extent. */
8580 unsigned char *bytes
;
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
;
8593 gif_read_from_memory (file
, buf
, len
)
8598 gif_memory_source
*src
= current_gif_memory_src
;
8600 if (len
> src
->len
- src
->index
)
8603 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8609 /* Load GIF image IMG for use on frame F. Value is non-zero if
8617 Lisp_Object file
, specified_file
;
8618 Lisp_Object specified_data
;
8619 int rc
, width
, height
, x
, y
, i
;
8621 ColorMapObject
*gif_color_map
;
8622 unsigned long pixel_colors
[256];
8624 struct gcpro gcpro1
;
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
);
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
);
8645 /* Open the GIF file. */
8646 gif
= DGifOpenFileName (SDATA (file
));
8649 image_error ("Cannot open `%s'", file
, Qnil
);
8656 /* Read from memory! */
8657 current_gif_memory_src
= &memsrc
;
8658 memsrc
.bytes
= SDATA (specified_data
);
8659 memsrc
.len
= SBYTES (specified_data
);
8662 gif
= DGifOpen (&memsrc
, gif_read_from_memory
);
8665 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
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
);
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'",
8687 DGifCloseFile (gif
);
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
);
8703 /* Allocate colors. */
8704 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8706 gif_color_map
= gif
->SColorMap
;
8707 #if 0 /* TODO: Color tables */
8708 init_color_table ();
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 ();
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};
8761 int row
= interlace_start
[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
,
8781 row
+= interlace_increment
[pass
];
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
);
8807 #endif /* HAVE_GIF */
8811 /***********************************************************************
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
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
=
8880 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8883 gs_clear_image (f
, 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
8900 struct image_keyword fmt
[GS_LAST
];
8904 bcopy (gs_format
, fmt
, sizeof fmt
);
8906 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8909 /* Bounding box must be a list or vector containing 4 integers. */
8910 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8913 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8914 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8919 else if (VECTORP (tem
))
8921 if (XVECTOR (tem
)->size
!= 4)
8923 for (i
= 0; i
< 4; ++i
)
8924 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8934 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8943 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8944 struct gcpro gcpro1
, gcpro2
;
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
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
);
8968 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
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
);
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
,
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. */
9008 x_kill_gs_process (pixmap
, f
)
9012 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
9016 /* Find the image containing PIXMAP. */
9017 for (i
= 0; i
< c
->used
; ++i
)
9018 if (c
->images
[i
]->pixmap
== pixmap
)
9021 /* Should someone in between have cleared the image cache, for
9022 instance, give up. */
9026 /* Kill the GS process. We should have found PIXMAP in the image
9027 cache and its image should contain a process object. */
9029 xassert (PROCESSP (img
->data
.lisp_val
));
9030 Fkill_process (img
->data
.lisp_val
, Qnil
);
9031 img
->data
.lisp_val
= Qnil
;
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
9037 class = FRAME_MAC_DISPLAY_INFO (f
)->visual
->class;
9038 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
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
);
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. */
9076 x_free_colors (f
, img
->colors
, img
->ncolors
);
9080 image_error ("Cannot get X image of `%s'; colors will not be freed",
9087 /* Now that we have the pixmap, compute mask and transform the
9088 image if requested. */
9090 postprocess_image (f
, img
);
9094 #endif /* HAVE_GHOSTSCRIPT */
9097 /***********************************************************************
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.
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
);
9126 CHECK_STRING (prop
);
9127 CHECK_STRING (value
);
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
));
9139 #endif /* MAC_TODO */
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. */)
9150 Lisp_Object prop
, frame
;
9152 #if 0 /* MAC_TODO : port window properties to Mac */
9154 struct frame
*f
= check_x_frame (frame
);
9157 CHECK_STRING (prop
);
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
));
9165 #endif /* MAC_TODO */
9171 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
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
9178 Lisp_Object prop
, frame
;
9180 #if 0 /* MAC_TODO : port window properties to Mac */
9182 struct frame
*f
= check_x_frame (frame
);
9185 Lisp_Object prop_value
= Qnil
;
9186 char *tmp_data
= NULL
;
9189 unsigned long actual_size
, bytes_remaining
;
9191 CHECK_STRING (prop
);
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
);
9200 int size
= bytes_remaining
;
9205 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
9206 prop_atom
, 0, bytes_remaining
,
9208 &actual_type
, &actual_format
,
9209 &actual_size
, &bytes_remaining
,
9210 (unsigned char **) &tmp_data
);
9212 prop_value
= make_string (tmp_data
, size
);
9221 #endif /* MAC_TODO */
9227 /***********************************************************************
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
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. */
9260 #if 0 /* MAC_TODO: cursor shape changes. */
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)
9273 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
9274 secs
= XFASTINT (tem
);
9275 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
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
9293 if (hourglass_atimer
)
9295 cancel_atimer (hourglass_atimer
);
9296 hourglass_atimer
= NULL
;
9299 if (hourglass_shown_p
)
9304 /* Timer function of hourglass_atimer. TIMER is equal to
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. */
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
;
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,
9351 XMapRaised (FRAME_X_DISPLAY (f
),
9352 f
->output_data
.w32
->hourglass_window
);
9353 XFlush (FRAME_X_DISPLAY (f
));
9356 hourglass_shown_p
= 1;
9359 #endif /* MAC_TODO */
9363 /* Hide the hourglass cursor on all frames, if it is currently shown. */
9368 #if 0 /* MAC_TODO: cursor shape changes. */
9369 if (hourglass_shown_p
)
9371 Lisp_Object rest
, frame
;
9374 FOR_EACH_FRAME (rest
, frame
)
9376 struct frame
*f
= XFRAME (frame
);
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;
9394 #endif /* MAC_TODO */
9399 /***********************************************************************
9401 ***********************************************************************/
9403 static Lisp_Object x_create_tip_frame
P_ ((struct mac_display_info
*,
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
9413 Lisp_Object tip_timer
;
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. */
9425 x_create_tip_frame (dpyinfo
, parms
)
9426 struct mac_display_info
*dpyinfo
;
9429 #if 0 /* MAC_TODO : Mac version */
9431 Lisp_Object frame
, tem
;
9433 long window_prompting
= 0;
9435 int count
= SPECPDL_INDEX ();
9436 struct gcpro gcpro1
, gcpro2
, gcpro3
;
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
;
9446 kb
= dpyinfo
->kboard
;
9448 kb
= &the_only_kboard
;
9451 /* Get the name of the frame to use for resource lookup. */
9452 name
= w32_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
9454 && !EQ (name
, Qunbound
)
9456 error ("Invalid frame name--not a string or nil");
9457 Vx_resource_name
= name
;
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
));
9470 f
->output_data
.w32
->icon_bitmap
= -1;
9472 FRAME_FONTSET (f
) = -1;
9473 f
->icon_name
= Qnil
;
9476 FRAME_KBOARD (f
) = kb
;
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
9483 if (EQ (name
, Qunbound
) || NILP (name
))
9485 f
->name
= build_string (dpyinfo
->x_id_name
);
9486 f
->explicit_name
= 0;
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. */
9501 font
= w32_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
9504 /* First, try whatever font the caller has specified. */
9507 tem
= Fquery_fontset (font
, Qnil
);
9509 font
= x_new_fontset (f
, SDATA (tem
));
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");
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
9542 if (NILP (Fassq (Qinternal_border_width
, parms
)))
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
),
9553 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
9554 "internalBorderWidth", "internalBorderWidth",
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
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
;
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
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
;
9596 = FRAME_W32_WINDOW (f
)
9597 = XCreateWindow (FRAME_W32_DISPLAY (f
),
9598 FRAME_W32_DISPLAY_INFO (f
)->root_window
,
9599 /* x, y, width, height */
9603 CopyFromParent
, InputOutput
, CopyFromParent
,
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
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
),
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
9642 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
9644 return unbind_to (count
, frame
);
9645 #endif /* MAC_TODO */
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
;
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
;
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
);
9692 timeout
= make_number (5);
9694 CHECK_NATNUM (timeout
);
9697 dx
= make_number (5);
9702 dy
= make_number (-10);
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
;
9726 call1 (Qcancel_timer
, timer
);
9729 #if 0 /* MAC_TODO : Mac specifics */
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
));
9735 #endif /* MAC_TODO */
9740 /* Hide a previous tip, if any. */
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")),
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
);
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);
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
));
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. */
9789 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
9791 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
9795 /* Stop at the first empty row at the end. */
9796 if (!row
->enabled_p
|| !row
->displays_text_p
)
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
;
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
9823 #if 0 /* TODO : Mac specifics */
9824 compute_tip_xy (f
, parms
, dx
, dy
, &root_x
, &root_y
);
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
));
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
;
9844 /* Let the tip disappear after timeout seconds. */
9845 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
9846 intern ("x-hide-tip"));
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. */)
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
))
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
);
9876 call1 (Qcancel_timer
, timer
);
9880 Fdelete_frame (frame
, Qnil
);
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
);
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
;
9939 /* If default_file_name is a directory, don't use the open
9940 file dialog, as it does not support selecting
9942 if (!(*file_name_only
))
9946 strncpy (filename
, file_name_only
, MAX_PATH
);
9947 filename
[MAX_PATH
] = '\0';
9954 OPENFILENAME file_details
;
9955 char *filename_file
;
9957 /* Prevent redisplay. */
9958 specbind (Qinhibit_redisplay
, Qt
);
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
);
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. */
9987 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
9988 dir
, mustmatch
, dir
, Qfile_name_history
,
9989 default_filename
, Qnil
);
9993 /* Make "Cancel" equivalent to C-g. */
9995 Fsignal (Qquit
, Qnil
);
9997 return unbind_to (count
, file
);
9999 #endif /* MAC_TODO */
10003 /***********************************************************************
10005 ***********************************************************************/
10009 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
10010 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
10014 return valid_image_p (spec
) ? Qt
: Qnil
;
10018 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
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 /***********************************************************************
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
[] =
10046 x_set_background_color
,
10047 x_set_border_color
,
10048 x_set_border_width
,
10049 x_set_cursor_color
,
10052 x_set_foreground_color
,
10054 0, /* MAC_TODO: x_set_icon_type, */
10055 x_set_internal_border_width
,
10056 x_set_menu_bar_lines
,
10058 x_explicitly_set_name
,
10059 x_set_scroll_bar_width
,
10061 x_set_unsplittable
,
10062 x_set_vertical_scroll_bars
,
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, */
10078 /* Certainly running on Mac. */
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");
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
);
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
;
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
;
10253 Qxbm
= intern ("xbm");
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");
10283 Qxpm
= intern ("xpm");
10287 Qjpeg
= intern ("jpeg");
10288 staticpro (&Qjpeg
);
10290 Qtiff
= intern ("tiff");
10291 staticpro (&Qtiff
);
10293 Qgif
= intern ("gif");
10296 Qpng
= intern ("png");
10299 defsubr (&Sclear_image_cache
);
10300 defsubr (&Simage_size
);
10301 defsubr (&Simage_mask_p
);
10304 defsubr (&Simagep
);
10305 defsubr (&Slookup_image
);
10308 hourglass_atimer
= NULL
;
10309 hourglass_shown_p
= 0;
10311 defsubr (&Sx_show_tip
);
10312 defsubr (&Sx_hide_tip
);
10314 staticpro (&tip_timer
);
10316 staticpro (&tip_frame
);
10318 #if 0 /* MAC_TODO */
10319 defsubr (&Sx_file_dialog
);
10327 image_types
= NULL
;
10328 Vimage_types
= Qnil
;
10330 define_image_type (&xbm_type
);
10331 #if HAVE_GHOSTSCRIPT
10332 define_image_type (&gs_type
);
10334 define_image_type (&pbm_type
);
10337 define_image_type (&xpm_type
);
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
10349 init_image_func_pointer ();
10353 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc
10354 (do not change this comment) */