--color not available in version 21.3
[emacs.git] / src / macfns.c
blobebaf2ee49e19d1886e2e4ca6c2e80d0a48309224
1 /* Graphical user interface functions for Mac OS.
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
25 #include <signal.h>
26 #include <stdio.h>
27 #include <math.h>
28 #include <limits.h>
29 #include <errno.h>
31 #include "lisp.h"
32 #include "charset.h"
33 #include "macterm.h"
34 #include "frame.h"
35 #include "window.h"
36 #include "buffer.h"
37 #include "dispextern.h"
38 #include "fontset.h"
39 #include "intervals.h"
40 #include "keyboard.h"
41 #include "blockinput.h"
42 #include "epaths.h"
43 #include "termhooks.h"
44 #include "coding.h"
45 #include "ccl.h"
46 #include "systime.h"
48 /* #include "bitmaps/gray.xbm" */
49 #define gray_width 2
50 #define gray_height 2
51 static unsigned char gray_bits[] = {
52 0x01, 0x02};
54 /*#include <commdlg.h>
55 #include <shellapi.h>*/
56 #include <ctype.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #ifndef MAC_OSX
61 #include <alloca.h>
62 #endif
64 #ifdef MAC_OSX
65 #undef mktime
66 #undef DEBUG
67 #undef Z
68 #undef free
69 #undef malloc
70 #undef realloc
71 /* Macros max and min defined in lisp.h conflict with those in
72 precompiled header Carbon.h. */
73 #undef max
74 #undef min
75 #undef init_process
76 #include <Carbon/Carbon.h>
77 #undef Z
78 #define Z (current_buffer->text->z)
79 #undef free
80 #define free unexec_free
81 #undef malloc
82 #define malloc unexec_malloc
83 #undef realloc
84 #define realloc unexec_realloc
85 #undef min
86 #define min(a, b) ((a) < (b) ? (a) : (b))
87 #undef max
88 #define max(a, b) ((a) > (b) ? (a) : (b))
89 #undef init_process
90 #define init_process emacs_init_process
91 #else /* not MAC_OSX */
92 #include <Windows.h>
93 #include <Gestalt.h>
94 #include <TextUtils.h>
95 #endif /* not MAC_OSX */
97 /*extern void free_frame_menubar ();
98 extern double atof ();
99 extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
100 extern int quit_char;*/
102 extern char *lispy_function_keys[];
104 /* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
105 it, and including `bitmaps/gray' more than once is a problem when
106 config.h defines `static' as an empty replacement string. */
108 int gray_bitmap_width = gray_width;
109 int gray_bitmap_height = gray_height;
110 unsigned char *gray_bitmap_bits = gray_bits;
112 /* Non-zero means we're allowed to display an hourglass cursor. */
114 int display_hourglass_p;
116 /* The background and shape of the mouse pointer, and shape when not
117 over text or in the modeline. */
119 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
120 Lisp_Object Vx_hourglass_pointer_shape;
122 /* The shape when over mouse-sensitive text. */
124 Lisp_Object Vx_sensitive_text_pointer_shape;
126 /* If non-nil, the pointer shape to indicate that windows can be
127 dragged horizontally. */
129 Lisp_Object Vx_window_horizontal_drag_shape;
131 /* Color of chars displayed in cursor box. */
133 Lisp_Object Vx_cursor_fore_pixel;
135 /* Nonzero if using Windows. */
137 static int mac_in_use;
139 /* Non nil if no window manager is in use. */
141 Lisp_Object Vx_no_window_manager;
143 /* Search path for bitmap files. */
145 Lisp_Object Vx_bitmap_file_path;
147 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
149 Lisp_Object Vx_pixel_size_width_font_regexp;
151 /* Evaluate this expression to rebuild the section of syms_of_macfns
152 that initializes and staticpros the symbols declared below. Note
153 that Emacs 18 has a bug that keeps C-x C-e from being able to
154 evaluate this expression.
156 (progn
157 ;; Accumulate a list of the symbols we want to initialize from the
158 ;; declarations at the top of the file.
159 (goto-char (point-min))
160 (search-forward "/\*&&& symbols declared here &&&*\/\n")
161 (let (symbol-list)
162 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
163 (setq symbol-list
164 (cons (buffer-substring (match-beginning 1) (match-end 1))
165 symbol-list))
166 (forward-line 1))
167 (setq symbol-list (nreverse symbol-list))
168 ;; Delete the section of syms_of_... where we initialize the symbols.
169 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
170 (let ((start (point)))
171 (while (looking-at "^ Q")
172 (forward-line 2))
173 (kill-region start (point)))
174 ;; Write a new symbol initialization section.
175 (while symbol-list
176 (insert (format " %s = intern (\"" (car symbol-list)))
177 (let ((start (point)))
178 (insert (substring (car symbol-list) 1))
179 (subst-char-in-region start (point) ?_ ?-))
180 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
181 (setq symbol-list (cdr symbol-list)))))
185 /*&&& symbols declared here &&&*/
186 Lisp_Object Qnone;
187 Lisp_Object Qsuppress_icon;
188 Lisp_Object Qundefined_color;
189 Lisp_Object Qcenter;
190 Lisp_Object Qcancel_timer;
191 Lisp_Object Qhyper;
192 Lisp_Object Qsuper;
193 Lisp_Object Qmeta;
194 Lisp_Object Qalt;
195 Lisp_Object Qctrl;
196 Lisp_Object Qcontrol;
197 Lisp_Object Qshift;
199 extern Lisp_Object Vwindow_system_version;
201 extern int mac_initialized;
203 /* Functions in macterm.c. */
204 extern void x_set_window_size (struct frame *, int, int, int);
205 extern void x_make_frame_visible (struct frame *);
206 extern struct mac_display_info *mac_term_init (Lisp_Object, char *, char *);
207 extern struct font_info *x_get_font_info (FRAME_PTR, int);
208 extern struct font_info *x_load_font (struct frame *, char *, int);
209 extern void x_find_ccl_program (struct font_info *);
210 extern struct font_info *x_query_font (struct frame *, char *);
211 extern void mac_initialize ();
213 /* compare two strings ignoring case */
215 static int
216 stricmp (const char *s, const char *t)
218 for ( ; tolower (*s) == tolower (*t); s++, t++)
219 if (*s == '\0')
220 return 0;
221 return tolower (*s) - tolower (*t);
224 /* compare two strings up to n characters, ignoring case */
226 static int
227 strnicmp (const char *s, const char *t, unsigned int n)
229 for ( ; n-- > 0 && tolower (*s) == tolower (*t); s++, t++)
230 if (*s == '\0')
231 return 0;
232 return n == 0 ? 0 : tolower (*s) - tolower (*t);
236 /* Error if we are not running on Mac OS. */
238 void
239 check_mac ()
241 if (! mac_in_use)
242 error ("Mac OS not in use or not initialized");
245 /* Nonzero if we can use mouse menus.
246 You should not call this unless HAVE_MENUS is defined. */
249 have_menus_p ()
251 return mac_in_use;
254 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
255 and checking validity for Mac. */
257 FRAME_PTR
258 check_x_frame (frame)
259 Lisp_Object frame;
261 FRAME_PTR f;
263 if (NILP (frame))
264 frame = selected_frame;
265 CHECK_LIVE_FRAME (frame);
266 f = XFRAME (frame);
267 if (! FRAME_MAC_P (f))
268 error ("non-mac frame used");
269 return f;
272 /* Let the user specify a display with a frame.
273 nil stands for the selected frame--or, if that is not a mac frame,
274 the first display on the list. */
276 struct mac_display_info *
277 check_x_display_info (frame)
278 Lisp_Object frame;
280 if (!mac_initialized)
282 mac_initialize ();
283 mac_initialized = 1;
286 if (NILP (frame))
288 struct frame *sf = XFRAME (selected_frame);
290 if (FRAME_MAC_P (sf) && FRAME_LIVE_P (sf))
291 return FRAME_MAC_DISPLAY_INFO (sf);
292 else
293 return &one_mac_display_info;
295 else if (STRINGP (frame))
296 return x_display_info_for_name (frame);
297 else
299 FRAME_PTR f;
301 CHECK_LIVE_FRAME (frame);
302 f = XFRAME (frame);
303 if (! FRAME_MAC_P (f))
304 error ("non-mac frame used");
305 return FRAME_MAC_DISPLAY_INFO (f);
309 /* Return the Emacs frame-object corresponding to a mac window.
310 It could be the frame's main window or an icon window. */
312 /* This function can be called during GC, so use GC_xxx type test macros. */
314 struct frame *
315 x_window_to_frame (dpyinfo, wdesc)
316 struct mac_display_info *dpyinfo;
317 WindowPtr wdesc;
319 Lisp_Object tail, frame;
320 struct frame *f;
322 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
324 frame = XCAR (tail);
325 if (!GC_FRAMEP (frame))
326 continue;
327 f = XFRAME (frame);
328 if (!FRAME_W32_P (f) || FRAME_MAC_DISPLAY_INFO (f) != dpyinfo)
329 continue;
330 /*if (f->output_data.w32->hourglass_window == wdesc)
331 return f;*/
333 /* MAC_TODO: Check tooltips when supported. */
334 if (FRAME_MAC_WINDOW (f) == wdesc)
335 return f;
337 return 0;
342 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
343 id, which is just an int that this section returns. Bitmaps are
344 reference counted so they can be shared among frames.
346 Bitmap indices are guaranteed to be > 0, so a negative number can
347 be used to indicate no bitmap.
349 If you use x_create_bitmap_from_data, then you must keep track of
350 the bitmaps yourself. That is, creating a bitmap from the same
351 data more than once will not be caught. */
354 /* Functions to access the contents of a bitmap, given an id. */
357 x_bitmap_height (f, id)
358 FRAME_PTR f;
359 int id;
361 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].height;
365 x_bitmap_width (f, id)
366 FRAME_PTR f;
367 int id;
369 return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].width;
372 #if 0 /* MAC_TODO : not used anywhere (?) */
374 x_bitmap_pixmap (f, id)
375 FRAME_PTR f;
376 int id;
378 return (int) FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
380 #endif
382 /* Allocate a new bitmap record. Returns index of new record. */
384 static int
385 x_allocate_bitmap_record (f)
386 FRAME_PTR f;
388 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
389 int i;
391 if (dpyinfo->bitmaps == NULL)
393 dpyinfo->bitmaps_size = 10;
394 dpyinfo->bitmaps = (struct mac_bitmap_record *)
395 xmalloc (dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
396 dpyinfo->bitmaps_last = 1;
397 return 1;
400 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
401 return ++dpyinfo->bitmaps_last;
403 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
404 if (dpyinfo->bitmaps[i].refcount == 0)
405 return i + 1;
407 dpyinfo->bitmaps_size *= 2;
408 dpyinfo->bitmaps = (struct mac_bitmap_record *)
409 xrealloc (dpyinfo->bitmaps,
410 dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
411 return ++dpyinfo->bitmaps_last;
414 /* Add one reference to the reference count of the bitmap with id
415 ID. */
417 void
418 x_reference_bitmap (f, id)
419 FRAME_PTR f;
420 int id;
422 ++FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
425 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
426 BITS. */
429 x_create_bitmap_from_data (f, bits, width, height)
430 struct frame *f;
431 char *bits;
432 unsigned int width, height;
434 struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
435 int id;
437 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
439 id = x_allocate_bitmap_record (f);
441 if (width % 16 != 0)
442 return -1;
444 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
445 if (! dpyinfo->bitmaps[id - 1].bitmap_data)
446 return -1;
448 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
450 dpyinfo->bitmaps[id - 1].refcount = 1;
451 dpyinfo->bitmaps[id - 1].height = height;
452 dpyinfo->bitmaps[id - 1].width = width;
454 return id;
457 /* Create bitmap from file FILE for frame F. */
460 x_create_bitmap_from_file (f, file)
461 struct frame *f;
462 Lisp_Object file;
464 return -1;
465 #if 0 /* MAC_TODO : bitmap support */
466 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
467 unsigned int width, height;
468 HBITMAP bitmap;
469 int xhot, yhot, result, id;
470 Lisp_Object found;
471 int fd;
472 char *filename;
473 HINSTANCE hinst;
475 /* Look for an existing bitmap with the same name. */
476 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
478 if (dpyinfo->bitmaps[id].refcount
479 && dpyinfo->bitmaps[id].file
480 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
482 ++dpyinfo->bitmaps[id].refcount;
483 return id + 1;
487 /* Search bitmap-file-path for the file, if appropriate. */
488 fd = openp (Vx_bitmap_file_path, file, "", &found, Qnil);
489 if (fd < 0)
490 return -1;
491 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
492 if (fd == 0)
493 return -1;
494 emacs_close (fd);
496 filename = (char *) SDATA (found);
498 hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
500 if (hinst == NULL)
501 return -1;
504 result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
505 filename, &width, &height, &bitmap, &xhot, &yhot);
506 if (result != BitmapSuccess)
507 return -1;
509 id = x_allocate_bitmap_record (f);
510 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
511 dpyinfo->bitmaps[id - 1].refcount = 1;
512 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SCHARS (file) + 1);
513 dpyinfo->bitmaps[id - 1].depth = 1;
514 dpyinfo->bitmaps[id - 1].height = height;
515 dpyinfo->bitmaps[id - 1].width = width;
516 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
518 return id;
519 #endif /* MAC_TODO */
522 /* Remove reference to bitmap with id number ID. */
524 void
525 x_destroy_bitmap (f, id)
526 FRAME_PTR f;
527 int id;
529 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
531 if (id > 0)
533 --dpyinfo->bitmaps[id - 1].refcount;
534 if (dpyinfo->bitmaps[id - 1].refcount == 0)
536 BLOCK_INPUT;
537 dpyinfo->bitmaps[id - 1].bitmap_data = NULL;
538 UNBLOCK_INPUT;
543 /* Free all the bitmaps for the display specified by DPYINFO. */
545 static void
546 x_destroy_all_bitmaps (dpyinfo)
547 struct mac_display_info *dpyinfo;
549 int i;
550 for (i = 0; i < dpyinfo->bitmaps_last; i++)
551 if (dpyinfo->bitmaps[i].refcount > 0)
552 xfree (dpyinfo->bitmaps[i].bitmap_data);
553 dpyinfo->bitmaps_last = 0;
556 /* Connect the frame-parameter names for W32 frames
557 to the ways of passing the parameter values to the window system.
559 The name of a parameter, as a Lisp symbol,
560 has an `x-frame-parameter' property which is an integer in Lisp
561 but can be interpreted as an `enum x_frame_parm' in C. */
563 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
564 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
565 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
566 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
567 void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
568 void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
569 void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
570 void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
571 void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
572 void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
573 void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
574 void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
575 void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
576 Lisp_Object));
577 void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
578 Lisp_Object));
579 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
580 Lisp_Object,
581 Lisp_Object,
582 char *, char *,
583 int));
585 /* Store the screen positions of frame F into XPTR and YPTR.
586 These are the positions of the containing window manager window,
587 not Emacs's own window. */
589 void
590 x_real_positions (f, xptr, yptr)
591 FRAME_PTR f;
592 int *xptr, *yptr;
594 Point pt;
595 GrafPtr oldport;
597 #ifdef TARGET_API_MAC_CARBON
599 Rect r;
601 GetWindowPortBounds (f->output_data.mac->mWP, &r);
602 SetPt (&pt, r.left, r.top);
604 #else /* not TARGET_API_MAC_CARBON */
605 SetPt (&pt,
606 f->output_data.mac->mWP->portRect.left,
607 f->output_data.mac->mWP->portRect.top);
608 #endif /* not TARGET_API_MAC_CARBON */
609 GetPort (&oldport);
610 LocalToGlobal (&pt);
611 SetPort (oldport);
613 *xptr = pt.h;
614 *yptr = pt.v;
618 /* The default colors for the Mac color map */
619 typedef struct colormap_t
621 unsigned long color;
622 char *name;
623 } colormap_t;
625 colormap_t mac_color_map[] =
627 { RGB_TO_ULONG(255, 250, 250), "snow" },
628 { RGB_TO_ULONG(248, 248, 255), "ghost white" },
629 { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
630 { RGB_TO_ULONG(245, 245, 245), "white smoke" },
631 { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
632 { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
633 { RGB_TO_ULONG(255, 250, 240), "floral white" },
634 { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
635 { RGB_TO_ULONG(253, 245, 230), "old lace" },
636 { RGB_TO_ULONG(253, 245, 230), "OldLace" },
637 { RGB_TO_ULONG(250, 240, 230), "linen" },
638 { RGB_TO_ULONG(250, 235, 215), "antique white" },
639 { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
640 { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
641 { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
642 { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
643 { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
644 { RGB_TO_ULONG(255, 228, 196), "bisque" },
645 { RGB_TO_ULONG(255, 218, 185), "peach puff" },
646 { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
647 { RGB_TO_ULONG(255, 222, 173), "navajo white" },
648 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
649 { RGB_TO_ULONG(255, 228, 181), "moccasin" },
650 { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
651 { RGB_TO_ULONG(255, 255, 240), "ivory" },
652 { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
653 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
654 { RGB_TO_ULONG(255, 245, 238), "seashell" },
655 { RGB_TO_ULONG(240, 255, 240), "honeydew" },
656 { RGB_TO_ULONG(245, 255, 250), "mint cream" },
657 { RGB_TO_ULONG(245, 255, 250), "MintCream" },
658 { RGB_TO_ULONG(240, 255, 255), "azure" },
659 { RGB_TO_ULONG(240, 248, 255), "alice blue" },
660 { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
661 { RGB_TO_ULONG(230, 230, 250), "lavender" },
662 { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
663 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
664 { RGB_TO_ULONG(255, 228, 225), "misty rose" },
665 { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
666 { RGB_TO_ULONG(255, 255, 255), "white" },
667 { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
668 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
669 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
670 { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
671 { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
672 { RGB_TO_ULONG(105, 105, 105), "dim gray" },
673 { RGB_TO_ULONG(105, 105, 105), "DimGray" },
674 { RGB_TO_ULONG(105, 105, 105), "dim grey" },
675 { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
676 { RGB_TO_ULONG(112, 128, 144), "slate gray" },
677 { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
678 { RGB_TO_ULONG(112, 128, 144), "slate grey" },
679 { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
680 { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
681 { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
682 { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
683 { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
684 { RGB_TO_ULONG(190, 190, 190), "gray" },
685 { RGB_TO_ULONG(190, 190, 190), "grey" },
686 { RGB_TO_ULONG(211, 211, 211), "light grey" },
687 { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
688 { RGB_TO_ULONG(211, 211, 211), "light gray" },
689 { RGB_TO_ULONG(211, 211, 211), "LightGray" },
690 { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
691 { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
692 { RGB_TO_ULONG(0 , 0 , 128), "navy" },
693 { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
694 { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
695 { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
696 { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
697 { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
698 { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
699 { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
700 { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
701 { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
702 { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
703 { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
704 { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
705 { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
706 { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
707 { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
708 { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
709 { RGB_TO_ULONG(0 , 0 , 255), "blue" },
710 { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
711 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
712 { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
713 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
714 { RGB_TO_ULONG(135, 206, 235), "sky blue" },
715 { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
716 { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
717 { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
718 { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
719 { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
720 { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
721 { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
722 { RGB_TO_ULONG(173, 216, 230), "light blue" },
723 { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
724 { RGB_TO_ULONG(176, 224, 230), "powder blue" },
725 { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
726 { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
727 { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
728 { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
729 { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
730 { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
731 { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
732 { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
733 { RGB_TO_ULONG(0 , 255, 255), "cyan" },
734 { RGB_TO_ULONG(224, 255, 255), "light cyan" },
735 { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
736 { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
737 { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
738 { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
739 { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
740 { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
741 { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
742 { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
743 { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
744 { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
745 { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
746 { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
747 { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
748 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
749 { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
750 { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
751 { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
752 { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
753 { RGB_TO_ULONG(152, 251, 152), "pale green" },
754 { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
755 { RGB_TO_ULONG(0 , 255, 127), "spring green" },
756 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
757 { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
758 { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
759 { RGB_TO_ULONG(0 , 255, 0 ), "green" },
760 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
761 { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
762 { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
763 { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
764 { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
765 { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
766 { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
767 { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
768 { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
769 { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
770 { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
771 { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
772 { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
773 { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
774 { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
775 { RGB_TO_ULONG(240, 230, 140), "khaki" },
776 { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
777 { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
778 { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
779 { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
780 { RGB_TO_ULONG(255, 255, 224), "light yellow" },
781 { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
782 { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
783 { RGB_TO_ULONG(255, 215, 0 ), "gold" },
784 { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
785 { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
786 { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
787 { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
788 { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
789 { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
790 { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
791 { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
792 { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
793 { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
794 { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
795 { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
796 { RGB_TO_ULONG(205, 133, 63 ), "peru" },
797 { RGB_TO_ULONG(222, 184, 135), "burlywood" },
798 { RGB_TO_ULONG(245, 245, 220), "beige" },
799 { RGB_TO_ULONG(245, 222, 179), "wheat" },
800 { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
801 { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
802 { RGB_TO_ULONG(210, 180, 140), "tan" },
803 { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
804 { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
805 { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
806 { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
807 { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
808 { RGB_TO_ULONG(250, 128, 114), "salmon" },
809 { RGB_TO_ULONG(255, 160, 122), "light salmon" },
810 { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
811 { RGB_TO_ULONG(255, 165, 0 ), "orange" },
812 { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
813 { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
814 { RGB_TO_ULONG(255, 127, 80 ), "coral" },
815 { RGB_TO_ULONG(240, 128, 128), "light coral" },
816 { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
817 { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
818 { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
819 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
820 { RGB_TO_ULONG(255, 0 , 0 ), "red" },
821 { RGB_TO_ULONG(255, 105, 180), "hot pink" },
822 { RGB_TO_ULONG(255, 105, 180), "HotPink" },
823 { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
824 { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
825 { RGB_TO_ULONG(255, 192, 203), "pink" },
826 { RGB_TO_ULONG(255, 182, 193), "light pink" },
827 { RGB_TO_ULONG(255, 182, 193), "LightPink" },
828 { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
829 { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
830 { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
831 { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
832 { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
833 { RGB_TO_ULONG(208, 32 , 144), "violet red" },
834 { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
835 { RGB_TO_ULONG(255, 0 , 255), "magenta" },
836 { RGB_TO_ULONG(238, 130, 238), "violet" },
837 { RGB_TO_ULONG(221, 160, 221), "plum" },
838 { RGB_TO_ULONG(218, 112, 214), "orchid" },
839 { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
840 { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
841 { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
842 { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
843 { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
844 { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
845 { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
846 { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
847 { RGB_TO_ULONG(160, 32 , 240), "purple" },
848 { RGB_TO_ULONG(147, 112, 219), "medium purple" },
849 { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
850 { RGB_TO_ULONG(216, 191, 216), "thistle" },
851 { RGB_TO_ULONG(255, 250, 250), "snow1" },
852 { RGB_TO_ULONG(238, 233, 233), "snow2" },
853 { RGB_TO_ULONG(205, 201, 201), "snow3" },
854 { RGB_TO_ULONG(139, 137, 137), "snow4" },
855 { RGB_TO_ULONG(255, 245, 238), "seashell1" },
856 { RGB_TO_ULONG(238, 229, 222), "seashell2" },
857 { RGB_TO_ULONG(205, 197, 191), "seashell3" },
858 { RGB_TO_ULONG(139, 134, 130), "seashell4" },
859 { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
860 { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
861 { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
862 { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
863 { RGB_TO_ULONG(255, 228, 196), "bisque1" },
864 { RGB_TO_ULONG(238, 213, 183), "bisque2" },
865 { RGB_TO_ULONG(205, 183, 158), "bisque3" },
866 { RGB_TO_ULONG(139, 125, 107), "bisque4" },
867 { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
868 { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
869 { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
870 { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
871 { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
872 { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
873 { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
874 { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
875 { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
876 { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
877 { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
878 { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
879 { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
880 { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
881 { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
882 { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
883 { RGB_TO_ULONG(255, 255, 240), "ivory1" },
884 { RGB_TO_ULONG(238, 238, 224), "ivory2" },
885 { RGB_TO_ULONG(205, 205, 193), "ivory3" },
886 { RGB_TO_ULONG(139, 139, 131), "ivory4" },
887 { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
888 { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
889 { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
890 { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
891 { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
892 { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
893 { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
894 { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
895 { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
896 { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
897 { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
898 { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
899 { RGB_TO_ULONG(240, 255, 255), "azure1" },
900 { RGB_TO_ULONG(224, 238, 238), "azure2" },
901 { RGB_TO_ULONG(193, 205, 205), "azure3" },
902 { RGB_TO_ULONG(131, 139, 139), "azure4" },
903 { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
904 { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
905 { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
906 { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
907 { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
908 { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
909 { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
910 { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
911 { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
912 { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
913 { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
914 { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
915 { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
916 { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
917 { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
918 { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
919 { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
920 { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
921 { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
922 { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
923 { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
924 { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
925 { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
926 { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
927 { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
928 { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
929 { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
930 { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
931 { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
932 { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
933 { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
934 { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
935 { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
936 { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
937 { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
938 { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
939 { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
940 { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
941 { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
942 { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
943 { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
944 { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
945 { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
946 { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
947 { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
948 { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
949 { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
950 { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
951 { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
952 { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
953 { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
954 { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
955 { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
956 { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
957 { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
958 { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
959 { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
960 { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
961 { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
962 { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
963 { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
964 { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
965 { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
966 { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
967 { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
968 { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
969 { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
970 { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
971 { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
972 { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
973 { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
974 { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
975 { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
976 { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
977 { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
978 { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
979 { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
980 { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
981 { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
982 { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
983 { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
984 { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
985 { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
986 { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
987 { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
988 { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
989 { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
990 { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
991 { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
992 { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
993 { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
994 { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
995 { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
996 { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
997 { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
998 { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
999 { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
1000 { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
1001 { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
1002 { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
1003 { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
1004 { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
1005 { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
1006 { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
1007 { RGB_TO_ULONG(255, 246, 143), "khaki1" },
1008 { RGB_TO_ULONG(238, 230, 133), "khaki2" },
1009 { RGB_TO_ULONG(205, 198, 115), "khaki3" },
1010 { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
1011 { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
1012 { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
1013 { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
1014 { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
1015 { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
1016 { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
1017 { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
1018 { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
1019 { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
1020 { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
1021 { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
1022 { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
1023 { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
1024 { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
1025 { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
1026 { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
1027 { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
1028 { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
1029 { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
1030 { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
1031 { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
1032 { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
1033 { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
1034 { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
1035 { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
1036 { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
1037 { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
1038 { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
1039 { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
1040 { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
1041 { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
1042 { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
1043 { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
1044 { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
1045 { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
1046 { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
1047 { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
1048 { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
1049 { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
1050 { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
1051 { RGB_TO_ULONG(255, 231, 186), "wheat1" },
1052 { RGB_TO_ULONG(238, 216, 174), "wheat2" },
1053 { RGB_TO_ULONG(205, 186, 150), "wheat3" },
1054 { RGB_TO_ULONG(139, 126, 102), "wheat4" },
1055 { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
1056 { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
1057 { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
1058 { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
1059 { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
1060 { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
1061 { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
1062 { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
1063 { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
1064 { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
1065 { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
1066 { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
1067 { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
1068 { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
1069 { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
1070 { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
1071 { RGB_TO_ULONG(255, 140, 105), "salmon1" },
1072 { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
1073 { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
1074 { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
1075 { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
1076 { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
1077 { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
1078 { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
1079 { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
1080 { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
1081 { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
1082 { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
1083 { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
1084 { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
1085 { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
1086 { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
1087 { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
1088 { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
1089 { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
1090 { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
1091 { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
1092 { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
1093 { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
1094 { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
1095 { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
1096 { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
1097 { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
1098 { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
1099 { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
1100 { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
1101 { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
1102 { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
1103 { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
1104 { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
1105 { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
1106 { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
1107 { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
1108 { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
1109 { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
1110 { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
1111 { RGB_TO_ULONG(255, 181, 197), "pink1" },
1112 { RGB_TO_ULONG(238, 169, 184), "pink2" },
1113 { RGB_TO_ULONG(205, 145, 158), "pink3" },
1114 { RGB_TO_ULONG(139, 99 , 108), "pink4" },
1115 { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
1116 { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
1117 { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
1118 { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
1119 { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
1120 { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
1121 { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
1122 { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
1123 { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
1124 { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
1125 { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
1126 { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
1127 { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
1128 { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
1129 { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
1130 { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
1131 { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
1132 { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
1133 { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
1134 { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
1135 { RGB_TO_ULONG(255, 131, 250), "orchid1" },
1136 { RGB_TO_ULONG(238, 122, 233), "orchid2" },
1137 { RGB_TO_ULONG(205, 105, 201), "orchid3" },
1138 { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
1139 { RGB_TO_ULONG(255, 187, 255), "plum1" },
1140 { RGB_TO_ULONG(238, 174, 238), "plum2" },
1141 { RGB_TO_ULONG(205, 150, 205), "plum3" },
1142 { RGB_TO_ULONG(139, 102, 139), "plum4" },
1143 { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
1144 { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
1145 { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
1146 { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
1147 { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
1148 { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
1149 { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
1150 { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
1151 { RGB_TO_ULONG(155, 48 , 255), "purple1" },
1152 { RGB_TO_ULONG(145, 44 , 238), "purple2" },
1153 { RGB_TO_ULONG(125, 38 , 205), "purple3" },
1154 { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
1155 { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
1156 { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
1157 { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
1158 { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
1159 { RGB_TO_ULONG(255, 225, 255), "thistle1" },
1160 { RGB_TO_ULONG(238, 210, 238), "thistle2" },
1161 { RGB_TO_ULONG(205, 181, 205), "thistle3" },
1162 { RGB_TO_ULONG(139, 123, 139), "thistle4" },
1163 { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
1164 { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
1165 { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
1166 { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
1167 { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
1168 { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
1169 { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
1170 { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
1171 { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
1172 { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
1173 { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
1174 { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
1175 { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
1176 { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
1177 { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
1178 { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
1179 { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
1180 { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
1181 { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
1182 { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
1183 { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
1184 { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
1185 { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
1186 { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
1187 { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
1188 { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
1189 { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
1190 { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
1191 { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
1192 { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
1193 { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
1194 { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
1195 { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
1196 { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
1197 { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
1198 { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
1199 { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
1200 { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
1201 { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
1202 { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
1203 { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
1204 { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
1205 { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
1206 { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
1207 { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
1208 { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
1209 { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
1210 { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
1211 { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
1212 { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
1213 { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
1214 { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
1215 { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
1216 { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
1217 { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
1218 { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
1219 { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
1220 { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
1221 { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
1222 { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
1223 { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
1224 { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
1225 { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
1226 { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
1227 { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
1228 { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
1229 { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
1230 { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
1231 { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
1232 { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
1233 { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
1234 { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
1235 { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
1236 { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
1237 { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
1238 { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
1239 { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
1240 { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
1241 { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
1242 { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
1243 { RGB_TO_ULONG(102, 102, 102), "gray40" },
1244 { RGB_TO_ULONG(102, 102, 102), "grey40" },
1245 { RGB_TO_ULONG(105, 105, 105), "gray41" },
1246 { RGB_TO_ULONG(105, 105, 105), "grey41" },
1247 { RGB_TO_ULONG(107, 107, 107), "gray42" },
1248 { RGB_TO_ULONG(107, 107, 107), "grey42" },
1249 { RGB_TO_ULONG(110, 110, 110), "gray43" },
1250 { RGB_TO_ULONG(110, 110, 110), "grey43" },
1251 { RGB_TO_ULONG(112, 112, 112), "gray44" },
1252 { RGB_TO_ULONG(112, 112, 112), "grey44" },
1253 { RGB_TO_ULONG(115, 115, 115), "gray45" },
1254 { RGB_TO_ULONG(115, 115, 115), "grey45" },
1255 { RGB_TO_ULONG(117, 117, 117), "gray46" },
1256 { RGB_TO_ULONG(117, 117, 117), "grey46" },
1257 { RGB_TO_ULONG(120, 120, 120), "gray47" },
1258 { RGB_TO_ULONG(120, 120, 120), "grey47" },
1259 { RGB_TO_ULONG(122, 122, 122), "gray48" },
1260 { RGB_TO_ULONG(122, 122, 122), "grey48" },
1261 { RGB_TO_ULONG(125, 125, 125), "gray49" },
1262 { RGB_TO_ULONG(125, 125, 125), "grey49" },
1263 { RGB_TO_ULONG(127, 127, 127), "gray50" },
1264 { RGB_TO_ULONG(127, 127, 127), "grey50" },
1265 { RGB_TO_ULONG(130, 130, 130), "gray51" },
1266 { RGB_TO_ULONG(130, 130, 130), "grey51" },
1267 { RGB_TO_ULONG(133, 133, 133), "gray52" },
1268 { RGB_TO_ULONG(133, 133, 133), "grey52" },
1269 { RGB_TO_ULONG(135, 135, 135), "gray53" },
1270 { RGB_TO_ULONG(135, 135, 135), "grey53" },
1271 { RGB_TO_ULONG(138, 138, 138), "gray54" },
1272 { RGB_TO_ULONG(138, 138, 138), "grey54" },
1273 { RGB_TO_ULONG(140, 140, 140), "gray55" },
1274 { RGB_TO_ULONG(140, 140, 140), "grey55" },
1275 { RGB_TO_ULONG(143, 143, 143), "gray56" },
1276 { RGB_TO_ULONG(143, 143, 143), "grey56" },
1277 { RGB_TO_ULONG(145, 145, 145), "gray57" },
1278 { RGB_TO_ULONG(145, 145, 145), "grey57" },
1279 { RGB_TO_ULONG(148, 148, 148), "gray58" },
1280 { RGB_TO_ULONG(148, 148, 148), "grey58" },
1281 { RGB_TO_ULONG(150, 150, 150), "gray59" },
1282 { RGB_TO_ULONG(150, 150, 150), "grey59" },
1283 { RGB_TO_ULONG(153, 153, 153), "gray60" },
1284 { RGB_TO_ULONG(153, 153, 153), "grey60" },
1285 { RGB_TO_ULONG(156, 156, 156), "gray61" },
1286 { RGB_TO_ULONG(156, 156, 156), "grey61" },
1287 { RGB_TO_ULONG(158, 158, 158), "gray62" },
1288 { RGB_TO_ULONG(158, 158, 158), "grey62" },
1289 { RGB_TO_ULONG(161, 161, 161), "gray63" },
1290 { RGB_TO_ULONG(161, 161, 161), "grey63" },
1291 { RGB_TO_ULONG(163, 163, 163), "gray64" },
1292 { RGB_TO_ULONG(163, 163, 163), "grey64" },
1293 { RGB_TO_ULONG(166, 166, 166), "gray65" },
1294 { RGB_TO_ULONG(166, 166, 166), "grey65" },
1295 { RGB_TO_ULONG(168, 168, 168), "gray66" },
1296 { RGB_TO_ULONG(168, 168, 168), "grey66" },
1297 { RGB_TO_ULONG(171, 171, 171), "gray67" },
1298 { RGB_TO_ULONG(171, 171, 171), "grey67" },
1299 { RGB_TO_ULONG(173, 173, 173), "gray68" },
1300 { RGB_TO_ULONG(173, 173, 173), "grey68" },
1301 { RGB_TO_ULONG(176, 176, 176), "gray69" },
1302 { RGB_TO_ULONG(176, 176, 176), "grey69" },
1303 { RGB_TO_ULONG(179, 179, 179), "gray70" },
1304 { RGB_TO_ULONG(179, 179, 179), "grey70" },
1305 { RGB_TO_ULONG(181, 181, 181), "gray71" },
1306 { RGB_TO_ULONG(181, 181, 181), "grey71" },
1307 { RGB_TO_ULONG(184, 184, 184), "gray72" },
1308 { RGB_TO_ULONG(184, 184, 184), "grey72" },
1309 { RGB_TO_ULONG(186, 186, 186), "gray73" },
1310 { RGB_TO_ULONG(186, 186, 186), "grey73" },
1311 { RGB_TO_ULONG(189, 189, 189), "gray74" },
1312 { RGB_TO_ULONG(189, 189, 189), "grey74" },
1313 { RGB_TO_ULONG(191, 191, 191), "gray75" },
1314 { RGB_TO_ULONG(191, 191, 191), "grey75" },
1315 { RGB_TO_ULONG(194, 194, 194), "gray76" },
1316 { RGB_TO_ULONG(194, 194, 194), "grey76" },
1317 { RGB_TO_ULONG(196, 196, 196), "gray77" },
1318 { RGB_TO_ULONG(196, 196, 196), "grey77" },
1319 { RGB_TO_ULONG(199, 199, 199), "gray78" },
1320 { RGB_TO_ULONG(199, 199, 199), "grey78" },
1321 { RGB_TO_ULONG(201, 201, 201), "gray79" },
1322 { RGB_TO_ULONG(201, 201, 201), "grey79" },
1323 { RGB_TO_ULONG(204, 204, 204), "gray80" },
1324 { RGB_TO_ULONG(204, 204, 204), "grey80" },
1325 { RGB_TO_ULONG(207, 207, 207), "gray81" },
1326 { RGB_TO_ULONG(207, 207, 207), "grey81" },
1327 { RGB_TO_ULONG(209, 209, 209), "gray82" },
1328 { RGB_TO_ULONG(209, 209, 209), "grey82" },
1329 { RGB_TO_ULONG(212, 212, 212), "gray83" },
1330 { RGB_TO_ULONG(212, 212, 212), "grey83" },
1331 { RGB_TO_ULONG(214, 214, 214), "gray84" },
1332 { RGB_TO_ULONG(214, 214, 214), "grey84" },
1333 { RGB_TO_ULONG(217, 217, 217), "gray85" },
1334 { RGB_TO_ULONG(217, 217, 217), "grey85" },
1335 { RGB_TO_ULONG(219, 219, 219), "gray86" },
1336 { RGB_TO_ULONG(219, 219, 219), "grey86" },
1337 { RGB_TO_ULONG(222, 222, 222), "gray87" },
1338 { RGB_TO_ULONG(222, 222, 222), "grey87" },
1339 { RGB_TO_ULONG(224, 224, 224), "gray88" },
1340 { RGB_TO_ULONG(224, 224, 224), "grey88" },
1341 { RGB_TO_ULONG(227, 227, 227), "gray89" },
1342 { RGB_TO_ULONG(227, 227, 227), "grey89" },
1343 { RGB_TO_ULONG(229, 229, 229), "gray90" },
1344 { RGB_TO_ULONG(229, 229, 229), "grey90" },
1345 { RGB_TO_ULONG(232, 232, 232), "gray91" },
1346 { RGB_TO_ULONG(232, 232, 232), "grey91" },
1347 { RGB_TO_ULONG(235, 235, 235), "gray92" },
1348 { RGB_TO_ULONG(235, 235, 235), "grey92" },
1349 { RGB_TO_ULONG(237, 237, 237), "gray93" },
1350 { RGB_TO_ULONG(237, 237, 237), "grey93" },
1351 { RGB_TO_ULONG(240, 240, 240), "gray94" },
1352 { RGB_TO_ULONG(240, 240, 240), "grey94" },
1353 { RGB_TO_ULONG(242, 242, 242), "gray95" },
1354 { RGB_TO_ULONG(242, 242, 242), "grey95" },
1355 { RGB_TO_ULONG(245, 245, 245), "gray96" },
1356 { RGB_TO_ULONG(245, 245, 245), "grey96" },
1357 { RGB_TO_ULONG(247, 247, 247), "gray97" },
1358 { RGB_TO_ULONG(247, 247, 247), "grey97" },
1359 { RGB_TO_ULONG(250, 250, 250), "gray98" },
1360 { RGB_TO_ULONG(250, 250, 250), "grey98" },
1361 { RGB_TO_ULONG(252, 252, 252), "gray99" },
1362 { RGB_TO_ULONG(252, 252, 252), "grey99" },
1363 { RGB_TO_ULONG(255, 255, 255), "gray100" },
1364 { RGB_TO_ULONG(255, 255, 255), "grey100" },
1365 { RGB_TO_ULONG(169, 169, 169), "dark grey" },
1366 { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
1367 { RGB_TO_ULONG(169, 169, 169), "dark gray" },
1368 { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
1369 { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
1370 { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
1371 { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
1372 { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
1373 { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
1374 { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
1375 { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
1376 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
1377 { RGB_TO_ULONG(144, 238, 144), "light green" },
1378 { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
1381 unsigned long
1382 mac_color_map_lookup (colorname)
1383 char *colorname;
1385 Lisp_Object ret = Qnil;
1386 int i;
1388 BLOCK_INPUT;
1390 for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
1391 if (stricmp (colorname, mac_color_map[i].name) == 0)
1393 ret = mac_color_map[i].color;
1394 break;
1397 UNBLOCK_INPUT;
1399 return ret;
1402 Lisp_Object
1403 x_to_mac_color (colorname)
1404 char * colorname;
1406 register Lisp_Object tail, ret = Qnil;
1408 BLOCK_INPUT;
1410 if (colorname[0] == '#')
1412 /* Could be an old-style RGB Device specification. */
1413 char *color;
1414 int size;
1415 color = colorname + 1;
1417 size = strlen(color);
1418 if (size == 3 || size == 6 || size == 9 || size == 12)
1420 unsigned long colorval;
1421 int i, pos;
1422 pos = 16;
1423 size /= 3;
1424 colorval = 0;
1426 for (i = 0; i < 3; i++)
1428 char *end;
1429 char t;
1430 unsigned long value;
1432 /* The check for 'x' in the following conditional takes into
1433 account the fact that strtol allows a "0x" in front of
1434 our numbers, and we don't. */
1435 if (!isxdigit(color[0]) || color[1] == 'x')
1436 break;
1437 t = color[size];
1438 color[size] = '\0';
1439 value = strtoul(color, &end, 16);
1440 color[size] = t;
1441 if (errno == ERANGE || end - color != size)
1442 break;
1443 switch (size)
1445 case 1:
1446 value = value * 0x10;
1447 break;
1448 case 2:
1449 break;
1450 case 3:
1451 value /= 0x10;
1452 break;
1453 case 4:
1454 value /= 0x100;
1455 break;
1457 colorval |= (value << pos);
1458 pos -= 8;
1459 if (i == 2)
1461 UNBLOCK_INPUT;
1462 return (colorval);
1464 color = end;
1468 else if (strnicmp(colorname, "rgb:", 4) == 0)
1470 char *color;
1471 unsigned long colorval;
1472 int i, pos;
1473 pos = 0;
1475 colorval = 0;
1476 color = colorname + 4;
1477 for (i = 0; i < 3; i++)
1479 char *end;
1480 unsigned long value;
1482 /* The check for 'x' in the following conditional takes into
1483 account the fact that strtol allows a "0x" in front of
1484 our numbers, and we don't. */
1485 if (!isxdigit(color[0]) || color[1] == 'x')
1486 break;
1487 value = strtoul(color, &end, 16);
1488 if (errno == ERANGE)
1489 break;
1490 switch (end - color)
1492 case 1:
1493 value = value * 0x10 + value;
1494 break;
1495 case 2:
1496 break;
1497 case 3:
1498 value /= 0x10;
1499 break;
1500 case 4:
1501 value /= 0x100;
1502 break;
1503 default:
1504 value = ULONG_MAX;
1506 if (value == ULONG_MAX)
1507 break;
1508 colorval |= (value << pos);
1509 pos += 0x8;
1510 if (i == 2)
1512 if (*end != '\0')
1513 break;
1514 UNBLOCK_INPUT;
1515 return (colorval);
1517 if (*end != '/')
1518 break;
1519 color = end + 1;
1522 else if (strnicmp(colorname, "rgbi:", 5) == 0)
1524 /* This is an RGB Intensity specification. */
1525 char *color;
1526 unsigned long colorval;
1527 int i, pos;
1528 pos = 0;
1530 colorval = 0;
1531 color = colorname + 5;
1532 for (i = 0; i < 3; i++)
1534 char *end;
1535 double value;
1536 unsigned long val;
1538 value = strtod(color, &end);
1539 if (errno == ERANGE)
1540 break;
1541 if (value < 0.0 || value > 1.0)
1542 break;
1543 val = (unsigned long)(0x100 * value);
1544 /* We used 0x100 instead of 0xFF to give a continuous
1545 range between 0.0 and 1.0 inclusive. The next statement
1546 fixes the 1.0 case. */
1547 if (val == 0x100)
1548 val = 0xFF;
1549 colorval |= (val << pos);
1550 pos += 0x8;
1551 if (i == 2)
1553 if (*end != '\0')
1554 break;
1555 UNBLOCK_INPUT;
1556 return (colorval);
1558 if (*end != '/')
1559 break;
1560 color = end + 1;
1564 ret = mac_color_map_lookup (colorname);
1566 UNBLOCK_INPUT;
1567 return ret;
1570 /* Gamma-correct COLOR on frame F. */
1572 void
1573 gamma_correct (f, color)
1574 struct frame *f;
1575 unsigned long *color;
1577 if (f->gamma)
1579 unsigned long red, green, blue;
1581 red = pow (RED_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
1582 green = pow (GREEN_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
1583 blue = pow (BLUE_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
1584 *color = RGB_TO_ULONG (red, green, blue);
1588 /* Decide if color named COLOR is valid for the display associated
1589 with the selected frame; if so, return the rgb values in COLOR_DEF.
1590 If ALLOC is nonzero, allocate a new colormap cell. */
1593 mac_defined_color (f, color, color_def, alloc)
1594 FRAME_PTR f;
1595 char *color;
1596 XColor *color_def;
1597 int alloc;
1599 register Lisp_Object tem;
1600 unsigned long mac_color_ref;
1602 tem = x_to_mac_color (color);
1604 if (!NILP (tem))
1606 if (f)
1608 /* Apply gamma correction. */
1609 mac_color_ref = XUINT (tem);
1610 gamma_correct (f, &mac_color_ref);
1611 XSETINT (tem, mac_color_ref);
1614 color_def->pixel = mac_color_ref;
1615 color_def->red = RED_FROM_ULONG (mac_color_ref);
1616 color_def->green = GREEN_FROM_ULONG (mac_color_ref);
1617 color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
1619 return 1;
1621 else
1623 return 0;
1627 /* Given a string ARG naming a color, compute a pixel value from it
1628 suitable for screen F.
1629 If F is not a color screen, return DEF (default) regardless of what
1630 ARG says. */
1633 x_decode_color (f, arg, def)
1634 FRAME_PTR f;
1635 Lisp_Object arg;
1636 int def;
1638 XColor cdef;
1640 CHECK_STRING (arg);
1642 if (strcmp (SDATA (arg), "black") == 0)
1643 return BLACK_PIX_DEFAULT (f);
1644 else if (strcmp (SDATA (arg), "white") == 0)
1645 return WHITE_PIX_DEFAULT (f);
1647 #if 0
1648 if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
1649 * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
1650 return def;
1651 #endif
1653 if (mac_defined_color (f, SDATA (arg), &cdef, 1))
1654 return cdef.pixel;
1656 /* defined_color failed; return an ultimate default. */
1657 return def;
1660 /* Functions called only from `x_set_frame_param'
1661 to set individual parameters.
1663 If FRAME_MAC_WINDOW (f) is 0,
1664 the frame is being created and its window does not exist yet.
1665 In that case, just record the parameter's new value
1666 in the standard place; do not attempt to change the window. */
1668 void
1669 x_set_foreground_color (f, arg, oldval)
1670 struct frame *f;
1671 Lisp_Object arg, oldval;
1673 FRAME_FOREGROUND_PIXEL (f)
1674 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1676 if (FRAME_MAC_WINDOW (f) != 0)
1678 update_face_from_frame_parameter (f, Qforeground_color, arg);
1679 if (FRAME_VISIBLE_P (f))
1680 redraw_frame (f);
1684 void
1685 x_set_background_color (f, arg, oldval)
1686 struct frame *f;
1687 Lisp_Object arg, oldval;
1689 FRAME_BACKGROUND_PIXEL (f)
1690 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1692 if (FRAME_MAC_WINDOW (f) != 0)
1694 update_face_from_frame_parameter (f, Qbackground_color, arg);
1696 if (FRAME_VISIBLE_P (f))
1697 redraw_frame (f);
1701 void
1702 x_set_mouse_color (f, arg, oldval)
1703 struct frame *f;
1704 Lisp_Object arg, oldval;
1706 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1707 int count;
1708 int mask_color;
1710 if (!EQ (Qnil, arg))
1711 f->output_data.mac->mouse_pixel
1712 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1713 mask_color = FRAME_BACKGROUND_PIXEL (f);
1715 /* Don't let pointers be invisible. */
1716 if (mask_color == f->output_data.mac->mouse_pixel
1717 && mask_color == FRAME_BACKGROUND_PIXEL (f))
1718 f->output_data.mac->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
1720 #if 0 /* MAC_TODO : cursor changes */
1721 BLOCK_INPUT;
1723 /* It's not okay to crash if the user selects a screwy cursor. */
1724 count = x_catch_errors (FRAME_W32_DISPLAY (f));
1726 if (!EQ (Qnil, Vx_pointer_shape))
1728 CHECK_NUMBER (Vx_pointer_shape);
1729 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
1731 else
1732 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1733 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
1735 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1737 CHECK_NUMBER (Vx_nontext_pointer_shape);
1738 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1739 XINT (Vx_nontext_pointer_shape));
1741 else
1742 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
1743 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1745 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
1747 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1748 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1749 XINT (Vx_hourglass_pointer_shape));
1751 else
1752 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
1753 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
1755 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1756 if (!EQ (Qnil, Vx_mode_pointer_shape))
1758 CHECK_NUMBER (Vx_mode_pointer_shape);
1759 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1760 XINT (Vx_mode_pointer_shape));
1762 else
1763 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1764 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
1766 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1768 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1769 hand_cursor
1770 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1771 XINT (Vx_sensitive_text_pointer_shape));
1773 else
1774 hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
1776 if (!NILP (Vx_window_horizontal_drag_shape))
1778 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1779 horizontal_drag_cursor
1780 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1781 XINT (Vx_window_horizontal_drag_shape));
1783 else
1784 horizontal_drag_cursor
1785 = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
1787 /* Check and report errors with the above calls. */
1788 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
1789 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
1792 XColor fore_color, back_color;
1794 fore_color.pixel = f->output_data.w32->mouse_pixel;
1795 back_color.pixel = mask_color;
1796 XQueryColor (FRAME_W32_DISPLAY (f),
1797 DefaultColormap (FRAME_W32_DISPLAY (f),
1798 DefaultScreen (FRAME_W32_DISPLAY (f))),
1799 &fore_color);
1800 XQueryColor (FRAME_W32_DISPLAY (f),
1801 DefaultColormap (FRAME_W32_DISPLAY (f),
1802 DefaultScreen (FRAME_W32_DISPLAY (f))),
1803 &back_color);
1804 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
1805 &fore_color, &back_color);
1806 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
1807 &fore_color, &back_color);
1808 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
1809 &fore_color, &back_color);
1810 XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor,
1811 &fore_color, &back_color);
1812 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
1813 &fore_color, &back_color);
1816 if (FRAME_W32_WINDOW (f) != 0)
1817 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
1819 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
1820 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
1821 f->output_data.w32->text_cursor = cursor;
1823 if (nontext_cursor != f->output_data.w32->nontext_cursor
1824 && f->output_data.w32->nontext_cursor != 0)
1825 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
1826 f->output_data.w32->nontext_cursor = nontext_cursor;
1828 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
1829 && f->output_data.w32->hourglass_cursor != 0)
1830 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
1831 f->output_data.w32->hourglass_cursor = hourglass_cursor;
1833 if (mode_cursor != f->output_data.w32->modeline_cursor
1834 && f->output_data.w32->modeline_cursor != 0)
1835 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
1836 f->output_data.w32->modeline_cursor = mode_cursor;
1838 if (hand_cursor != f->output_data.w32->hand_cursor
1839 && f->output_data.w32->hand_cursor != 0)
1840 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hand_cursor);
1841 f->output_data.w32->hand_cursor = hand_cursor;
1843 XFlush (FRAME_W32_DISPLAY (f));
1844 UNBLOCK_INPUT;
1846 update_face_from_frame_parameter (f, Qmouse_color, arg);
1847 #endif /* MAC_TODO */
1850 void
1851 x_set_cursor_color (f, arg, oldval)
1852 struct frame *f;
1853 Lisp_Object arg, oldval;
1855 unsigned long fore_pixel;
1857 if (!NILP (Vx_cursor_fore_pixel))
1858 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1859 WHITE_PIX_DEFAULT (f));
1860 else
1861 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1862 f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1864 /* Make sure that the cursor color differs from the background color. */
1865 if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
1867 f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
1868 if (f->output_data.mac->cursor_pixel == fore_pixel)
1869 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1871 FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
1873 #if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
1874 if (FRAME_MAC_WINDOW (f) != 0)
1876 if (FRAME_VISIBLE_P (f))
1878 BLOCK_INPUT;
1879 display_and_set_cursor (f, 0);
1880 display_and_set_cursor (f, 1);
1881 UNBLOCK_INPUT;
1884 #endif
1886 update_face_from_frame_parameter (f, Qcursor_color, arg);
1889 /* Set the border-color of frame F to pixel value PIX.
1890 Note that this does not fully take effect if done before
1891 F has a window. */
1892 void
1893 x_set_border_pixel (f, pix)
1894 struct frame *f;
1895 int pix;
1897 f->output_data.mac->border_pixel = pix;
1899 if (FRAME_MAC_WINDOW (f) != 0 && f->output_data.mac->border_width > 0)
1901 if (FRAME_VISIBLE_P (f))
1902 redraw_frame (f);
1906 /* Set the border-color of frame F to value described by ARG.
1907 ARG can be a string naming a color.
1908 The border-color is used for the border that is drawn by the server.
1909 Note that this does not fully take effect if done before
1910 F has a window; it must be redone when the window is created. */
1912 void
1913 x_set_border_color (f, arg, oldval)
1914 struct frame *f;
1915 Lisp_Object arg, oldval;
1917 int pix;
1919 CHECK_STRING (arg);
1920 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1921 x_set_border_pixel (f, pix);
1922 update_face_from_frame_parameter (f, Qborder_color, arg);
1925 void
1926 x_set_cursor_type (f, arg, oldval)
1927 FRAME_PTR f;
1928 Lisp_Object arg, oldval;
1930 set_frame_cursor_types (f, arg);
1932 /* Make sure the cursor gets redrawn. This is overkill, but how
1933 often do people change cursor types? */
1934 update_mode_lines++;
1937 #if 0 /* MAC_TODO: really no icon for Mac */
1938 void
1939 x_set_icon_type (f, arg, oldval)
1940 struct frame *f;
1941 Lisp_Object arg, oldval;
1943 int result;
1945 if (NILP (arg) && NILP (oldval))
1946 return;
1948 if (STRINGP (arg) && STRINGP (oldval)
1949 && EQ (Fstring_equal (oldval, arg), Qt))
1950 return;
1952 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
1953 return;
1955 BLOCK_INPUT;
1957 result = x_bitmap_icon (f, arg);
1958 if (result)
1960 UNBLOCK_INPUT;
1961 error ("No icon window available");
1964 UNBLOCK_INPUT;
1966 #endif /* MAC_TODO */
1968 void
1969 x_set_icon_name (f, arg, oldval)
1970 struct frame *f;
1971 Lisp_Object arg, oldval;
1973 int result;
1975 if (STRINGP (arg))
1977 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1978 return;
1980 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
1981 return;
1983 f->icon_name = arg;
1985 #if 0 /* MAC_TODO */
1986 if (f->output_data.w32->icon_bitmap != 0)
1987 return;
1989 BLOCK_INPUT;
1991 result = x_text_icon (f,
1992 (char *) SDATA ((!NILP (f->icon_name)
1993 ? f->icon_name
1994 : !NILP (f->title)
1995 ? f->title
1996 : f->name)));
1998 if (result)
2000 UNBLOCK_INPUT;
2001 error ("No icon window available");
2004 /* If the window was unmapped (and its icon was mapped),
2005 the new icon is not mapped, so map the window in its stead. */
2006 if (FRAME_VISIBLE_P (f))
2008 #ifdef USE_X_TOOLKIT
2009 XtPopup (f->output_data.w32->widget, XtGrabNone);
2010 #endif
2011 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
2014 XFlush (FRAME_W32_DISPLAY (f));
2015 UNBLOCK_INPUT;
2016 #endif /* MAC_TODO */
2020 void
2021 x_set_menu_bar_lines (f, value, oldval)
2022 struct frame *f;
2023 Lisp_Object value, oldval;
2025 int nlines;
2026 int olines = FRAME_MENU_BAR_LINES (f);
2028 /* Right now, menu bars don't work properly in minibuf-only frames;
2029 most of the commands try to apply themselves to the minibuffer
2030 frame itself, and get an error because you can't switch buffers
2031 in or split the minibuffer window. */
2032 if (FRAME_MINIBUF_ONLY_P (f))
2033 return;
2035 if (INTEGERP (value))
2036 nlines = XINT (value);
2037 else
2038 nlines = 0;
2040 FRAME_MENU_BAR_LINES (f) = 0;
2041 if (nlines)
2042 FRAME_EXTERNAL_MENU_BAR (f) = 1;
2043 else
2045 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
2046 free_frame_menubar (f);
2047 FRAME_EXTERNAL_MENU_BAR (f) = 0;
2049 /* Adjust the frame size so that the client (text) dimensions
2050 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2051 set correctly. */
2052 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
2053 do_pending_window_change (0);
2055 adjust_glyphs (f);
2059 /* Set the number of lines used for the tool bar of frame F to VALUE.
2060 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
2061 is the old number of tool bar lines. This function changes the
2062 height of all windows on frame F to match the new tool bar height.
2063 The frame's height doesn't change. */
2065 void
2066 x_set_tool_bar_lines (f, value, oldval)
2067 struct frame *f;
2068 Lisp_Object value, oldval;
2070 int delta, nlines, root_height;
2071 Lisp_Object root_window;
2073 /* Treat tool bars like menu bars. */
2074 if (FRAME_MINIBUF_ONLY_P (f))
2075 return;
2077 /* Use VALUE only if an integer >= 0. */
2078 if (INTEGERP (value) && XINT (value) >= 0)
2079 nlines = XFASTINT (value);
2080 else
2081 nlines = 0;
2083 /* Make sure we redisplay all windows in this frame. */
2084 ++windows_or_buffers_changed;
2086 delta = nlines - FRAME_TOOL_BAR_LINES (f);
2088 /* Don't resize the tool-bar to more than we have room for. */
2089 root_window = FRAME_ROOT_WINDOW (f);
2090 root_height = XINT (XWINDOW (root_window)->height);
2091 if (root_height - delta < 1)
2093 delta = root_height - 1;
2094 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
2097 FRAME_TOOL_BAR_LINES (f) = nlines;
2098 change_window_heights (root_window, delta);
2099 adjust_glyphs (f);
2101 /* We also have to make sure that the internal border at the top of
2102 the frame, below the menu bar or tool bar, is redrawn when the
2103 tool bar disappears. This is so because the internal border is
2104 below the tool bar if one is displayed, but is below the menu bar
2105 if there isn't a tool bar. The tool bar draws into the area
2106 below the menu bar. */
2107 if (FRAME_MAC_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
2109 updating_frame = f;
2110 clear_frame ();
2111 clear_current_matrices (f);
2112 updating_frame = NULL;
2115 /* If the tool bar gets smaller, the internal border below it
2116 has to be cleared. It was formerly part of the display
2117 of the larger tool bar, and updating windows won't clear it. */
2118 if (delta < 0)
2120 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
2121 int width = PIXEL_WIDTH (f);
2122 int y = nlines * CANON_Y_UNIT (f);
2124 BLOCK_INPUT;
2125 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2126 0, y, width, height, 0);
2127 UNBLOCK_INPUT;
2129 if (WINDOWP (f->tool_bar_window))
2130 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
2135 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2136 w32_id_name.
2138 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2139 name; if NAME is a string, set F's name to NAME and set
2140 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2142 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2143 suggesting a new name, which lisp code should override; if
2144 F->explicit_name is set, ignore the new name; otherwise, set it. */
2146 void
2147 x_set_name (f, name, explicit)
2148 struct frame *f;
2149 Lisp_Object name;
2150 int explicit;
2152 /* Make sure that requests from lisp code override requests from
2153 Emacs redisplay code. */
2154 if (explicit)
2156 /* If we're switching from explicit to implicit, we had better
2157 update the mode lines and thereby update the title. */
2158 if (f->explicit_name && NILP (name))
2159 update_mode_lines = 1;
2161 f->explicit_name = ! NILP (name);
2163 else if (f->explicit_name)
2164 return;
2166 /* If NAME is nil, set the name to the w32_id_name. */
2167 if (NILP (name))
2169 /* Check for no change needed in this very common case
2170 before we do any consing. */
2171 if (!strcmp (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name,
2172 SDATA (f->name)))
2173 return;
2174 name = build_string (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name);
2176 else
2177 CHECK_STRING (name);
2179 /* Don't change the name if it's already NAME. */
2180 if (! NILP (Fstring_equal (name, f->name)))
2181 return;
2183 f->name = name;
2185 /* For setting the frame title, the title parameter should override
2186 the name parameter. */
2187 if (! NILP (f->title))
2188 name = f->title;
2190 if (FRAME_MAC_WINDOW (f))
2192 if (STRING_MULTIBYTE (name))
2193 #if 0 /* MAC_TODO: encoding title string */
2194 name = ENCODE_SYSTEM (name);
2195 #else
2196 return;
2197 #endif
2199 BLOCK_INPUT;
2202 Str255 windowTitle;
2203 if (strlen (SDATA (name)) < 255)
2205 strcpy (windowTitle, SDATA (name));
2206 c2pstr (windowTitle);
2207 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2211 UNBLOCK_INPUT;
2215 /* This function should be called when the user's lisp code has
2216 specified a name for the frame; the name will override any set by the
2217 redisplay code. */
2218 void
2219 x_explicitly_set_name (f, arg, oldval)
2220 FRAME_PTR f;
2221 Lisp_Object arg, oldval;
2223 x_set_name (f, arg, 1);
2226 /* This function should be called by Emacs redisplay code to set the
2227 name; names set this way will never override names set by the user's
2228 lisp code. */
2229 void
2230 x_implicitly_set_name (f, arg, oldval)
2231 FRAME_PTR f;
2232 Lisp_Object arg, oldval;
2234 x_set_name (f, arg, 0);
2237 /* Change the title of frame F to NAME.
2238 If NAME is nil, use the frame name as the title.
2240 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2241 name; if NAME is a string, set F's name to NAME and set
2242 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2244 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2245 suggesting a new name, which lisp code should override; if
2246 F->explicit_name is set, ignore the new name; otherwise, set it. */
2248 void
2249 x_set_title (f, name, old_name)
2250 struct frame *f;
2251 Lisp_Object name, old_name;
2253 /* Don't change the title if it's already NAME. */
2254 if (EQ (name, f->title))
2255 return;
2257 update_mode_lines = 1;
2259 f->title = name;
2261 if (NILP (name))
2262 name = f->name;
2264 if (FRAME_MAC_WINDOW (f))
2266 if (STRING_MULTIBYTE (name))
2267 #if 0 /* MAC_TODO: encoding title string */
2268 name = ENCODE_SYSTEM (name);
2269 #else
2270 return;
2271 #endif
2273 BLOCK_INPUT;
2276 Str255 windowTitle;
2277 if (strlen (SDATA (name)) < 255)
2279 strcpy (windowTitle, SDATA (name));
2280 c2pstr (windowTitle);
2281 SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
2285 UNBLOCK_INPUT;
2289 void
2290 x_set_scroll_bar_default_width (f)
2291 struct frame *f;
2293 /* Imitate X without X Toolkit */
2295 int wid = FONT_WIDTH (f->output_data.mac->font);
2297 #ifdef MAC_OSX
2298 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 16; /* Aqua scroll bars. */
2299 FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
2300 wid - 1) / wid;
2301 #else /* not MAC_OSX */
2302 /* Make the actual width at least 14 pixels and a multiple of a
2303 character width. */
2304 FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
2306 /* Use all of that space (aside from required margins) for the
2307 scroll bar. */
2308 FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
2309 #endif /* not MAC_OSX */
2313 /* Subroutines of creating a frame. */
2315 char *
2316 x_get_string_resource (rdb, name, class)
2317 XrmDatabase rdb;
2318 char *name, *class;
2320 /* MAC_TODO: implement resource strings */
2321 return (char *)0;
2324 /* Return the value of parameter PARAM.
2326 First search ALIST, then Vdefault_frame_alist, then the X defaults
2327 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2329 Convert the resource to the type specified by desired_type.
2331 If no default is specified, return Qunbound. If you call
2332 mac_get_arg, make sure you deal with Qunbound in a reasonable way,
2333 and don't let it get stored in any Lisp-visible variables! */
2335 static Lisp_Object
2336 mac_get_arg (alist, param, attribute, class, type)
2337 Lisp_Object alist, param;
2338 char *attribute;
2339 char *class;
2340 enum resource_types type;
2342 return x_get_arg (check_x_display_info (Qnil),
2343 alist, param, attribute, class, type);
2347 /* XParseGeometry copied from w32xfns.c */
2350 * XParseGeometry parses strings of the form
2351 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
2352 * width, height, xoffset, and yoffset are unsigned integers.
2353 * Example: "=80x24+300-49"
2354 * The equal sign is optional.
2355 * It returns a bitmask that indicates which of the four values
2356 * were actually found in the string. For each value found,
2357 * the corresponding argument is updated; for each value
2358 * not found, the corresponding argument is left unchanged.
2361 static int
2362 read_integer (string, NextString)
2363 register char *string;
2364 char **NextString;
2366 register int Result = 0;
2367 int Sign = 1;
2369 if (*string == '+')
2370 string++;
2371 else if (*string == '-')
2373 string++;
2374 Sign = -1;
2376 for (; (*string >= '0') && (*string <= '9'); string++)
2378 Result = (Result * 10) + (*string - '0');
2380 *NextString = string;
2381 if (Sign >= 0)
2382 return (Result);
2383 else
2384 return (-Result);
2388 XParseGeometry (string, x, y, width, height)
2389 char *string;
2390 int *x, *y;
2391 unsigned int *width, *height; /* RETURN */
2393 int mask = NoValue;
2394 register char *strind;
2395 unsigned int tempWidth, tempHeight;
2396 int tempX, tempY;
2397 char *nextCharacter;
2399 if ((string == NULL) || (*string == '\0')) return (mask);
2400 if (*string == '=')
2401 string++; /* ignore possible '=' at beg of geometry spec */
2403 strind = (char *)string;
2404 if (*strind != '+' && *strind != '-' && *strind != 'x')
2406 tempWidth = read_integer (strind, &nextCharacter);
2407 if (strind == nextCharacter)
2408 return (0);
2409 strind = nextCharacter;
2410 mask |= WidthValue;
2413 if (*strind == 'x' || *strind == 'X')
2415 strind++;
2416 tempHeight = read_integer (strind, &nextCharacter);
2417 if (strind == nextCharacter)
2418 return (0);
2419 strind = nextCharacter;
2420 mask |= HeightValue;
2423 if ((*strind == '+') || (*strind == '-'))
2425 if (*strind == '-')
2427 strind++;
2428 tempX = -read_integer (strind, &nextCharacter);
2429 if (strind == nextCharacter)
2430 return (0);
2431 strind = nextCharacter;
2432 mask |= XNegative;
2435 else
2437 strind++;
2438 tempX = read_integer (strind, &nextCharacter);
2439 if (strind == nextCharacter)
2440 return (0);
2441 strind = nextCharacter;
2443 mask |= XValue;
2444 if ((*strind == '+') || (*strind == '-'))
2446 if (*strind == '-')
2448 strind++;
2449 tempY = -read_integer (strind, &nextCharacter);
2450 if (strind == nextCharacter)
2451 return (0);
2452 strind = nextCharacter;
2453 mask |= YNegative;
2456 else
2458 strind++;
2459 tempY = read_integer (strind, &nextCharacter);
2460 if (strind == nextCharacter)
2461 return (0);
2462 strind = nextCharacter;
2464 mask |= YValue;
2468 /* If strind isn't at the end of the string the it's an invalid
2469 geometry specification. */
2471 if (*strind != '\0') return (0);
2473 if (mask & XValue)
2474 *x = tempX;
2475 if (mask & YValue)
2476 *y = tempY;
2477 if (mask & WidthValue)
2478 *width = tempWidth;
2479 if (mask & HeightValue)
2480 *height = tempHeight;
2481 return (mask);
2485 #if 0 /* MAC_TODO */
2486 /* Create and set up the Mac window for frame F. */
2488 static void
2489 mac_window (f, window_prompting, minibuffer_only)
2490 struct frame *f;
2491 long window_prompting;
2492 int minibuffer_only;
2494 Rect r;
2496 BLOCK_INPUT;
2498 /* Use the resource name as the top-level window name
2499 for looking up resources. Make a non-Lisp copy
2500 for the window manager, so GC relocation won't bother it.
2502 Elsewhere we specify the window name for the window manager. */
2505 char *str = (char *) SDATA (Vx_resource_name);
2506 f->namebuf = (char *) xmalloc (strlen (str) + 1);
2507 strcpy (f->namebuf, str);
2510 SetRect (&r, f->output_data.mac->left_pos, f->output_data.mac->top_pos,
2511 f->output_data.mac->left_pos + PIXEL_WIDTH (f),
2512 f->output_data.mac->top_pos + PIXEL_HEIGHT (f));
2513 FRAME_MAC_WINDOW (f)
2514 = NewCWindow (NULL, &r, "\p", 1, zoomDocProc, (WindowPtr) -1, 1, (long) f->output_data.mac);
2516 validate_x_resource_name ();
2518 /* x_set_name normally ignores requests to set the name if the
2519 requested name is the same as the current name. This is the one
2520 place where that assumption isn't correct; f->name is set, but
2521 the server hasn't been told. */
2523 Lisp_Object name;
2524 int explicit = f->explicit_name;
2526 f->explicit_name = 0;
2527 name = f->name;
2528 f->name = Qnil;
2529 x_set_name (f, name, explicit);
2532 ShowWindow (FRAME_MAC_WINDOW (f));
2534 UNBLOCK_INPUT;
2536 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
2537 initialize_frame_menubar (f);
2539 if (FRAME_MAC_WINDOW (f) == 0)
2540 error ("Unable to create window");
2542 #endif /* MAC_TODO */
2544 /* Handle the icon stuff for this window. Perhaps later we might
2545 want an x_set_icon_position which can be called interactively as
2546 well. */
2548 static void
2549 x_icon (f, parms)
2550 struct frame *f;
2551 Lisp_Object parms;
2553 Lisp_Object icon_x, icon_y;
2555 /* Set the position of the icon. Note that Windows 95 groups all
2556 icons in the tray. */
2557 icon_x = mac_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
2558 icon_y = mac_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
2559 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
2561 CHECK_NUMBER (icon_x);
2562 CHECK_NUMBER (icon_y);
2564 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
2565 error ("Both left and top icon corners of icon must be specified");
2567 BLOCK_INPUT;
2569 if (! EQ (icon_x, Qunbound))
2570 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
2572 #if 0 /* TODO */
2573 /* Start up iconic or window? */
2574 x_wm_set_window_state
2575 (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
2576 ? IconicState
2577 : NormalState));
2579 x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
2580 ? f->icon_name
2581 : f->name)));
2582 #endif
2584 UNBLOCK_INPUT;
2588 void
2589 x_make_gc (f)
2590 struct frame *f;
2592 XGCValues gc_values;
2594 BLOCK_INPUT;
2596 /* Create the GC's of this frame.
2597 Note that many default values are used. */
2599 /* Normal video */
2600 gc_values.font = f->output_data.mac->font;
2601 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
2602 gc_values.background = FRAME_BACKGROUND_PIXEL (f);
2603 f->output_data.mac->normal_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
2604 FRAME_MAC_WINDOW (f),
2605 GCFont | GCForeground | GCBackground,
2606 &gc_values);
2608 /* Reverse video style. */
2609 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
2610 gc_values.background = FRAME_FOREGROUND_PIXEL (f);
2611 f->output_data.mac->reverse_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
2612 FRAME_MAC_WINDOW (f),
2613 GCFont | GCForeground | GCBackground,
2614 &gc_values);
2616 /* Cursor has cursor-color background, background-color foreground. */
2617 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
2618 gc_values.background = f->output_data.mac->cursor_pixel;
2619 f->output_data.mac->cursor_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
2620 FRAME_MAC_WINDOW (f),
2621 GCFont | GCForeground | GCBackground,
2622 &gc_values);
2624 /* Reliefs. */
2625 f->output_data.mac->white_relief.gc = 0;
2626 f->output_data.mac->black_relief.gc = 0;
2628 UNBLOCK_INPUT;
2632 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2633 1, 1, 0,
2634 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
2635 Returns an Emacs frame object.
2636 ALIST is an alist of frame parameters.
2637 If the parameters specify that the frame should not have a minibuffer,
2638 and do not specify a specific minibuffer window to use,
2639 then `default-minibuffer-frame' must be a frame whose minibuffer can
2640 be shared by the new frame.
2642 This function is an internal primitive--use `make-frame' instead. */)
2643 (parms)
2644 Lisp_Object parms;
2646 struct frame *f;
2647 Lisp_Object frame, tem;
2648 Lisp_Object name;
2649 int minibuffer_only = 0;
2650 long window_prompting = 0;
2651 int width, height;
2652 int count = SPECPDL_INDEX ();
2653 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2654 Lisp_Object display;
2655 struct mac_display_info *dpyinfo = NULL;
2656 Lisp_Object parent;
2657 struct kboard *kb;
2658 char x_frame_name[10];
2659 static int x_frame_count = 2; /* begins at 2 because terminal frame is F1 */
2661 check_mac ();
2663 /* Use this general default value to start with
2664 until we know if this frame has a specified name. */
2665 Vx_resource_name = Vinvocation_name;
2667 display = mac_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
2668 if (EQ (display, Qunbound))
2669 display = Qnil;
2670 dpyinfo = check_x_display_info (display);
2671 #ifdef MULTI_KBOARD
2672 kb = dpyinfo->kboard;
2673 #else
2674 kb = &the_only_kboard;
2675 #endif
2677 name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
2678 if (!STRINGP (name)
2679 && ! EQ (name, Qunbound)
2680 && ! NILP (name))
2681 error ("Invalid frame name--not a string or nil");
2683 if (STRINGP (name))
2684 Vx_resource_name = name;
2686 /* See if parent window is specified. */
2687 parent = mac_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
2688 if (EQ (parent, Qunbound))
2689 parent = Qnil;
2690 if (! NILP (parent))
2691 CHECK_NUMBER (parent);
2693 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
2694 /* No need to protect DISPLAY because that's not used after passing
2695 it to make_frame_without_minibuffer. */
2696 frame = Qnil;
2697 GCPRO4 (parms, parent, name, frame);
2698 tem = mac_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
2699 RES_TYPE_SYMBOL);
2700 if (EQ (tem, Qnone) || NILP (tem))
2701 f = make_frame_without_minibuffer (Qnil, kb, display);
2702 else if (EQ (tem, Qonly))
2704 f = make_minibuffer_frame ();
2705 minibuffer_only = 1;
2707 else if (WINDOWP (tem))
2708 f = make_frame_without_minibuffer (tem, kb, display);
2709 else
2710 f = make_frame (1);
2712 if (EQ (name, Qunbound) || NILP (name))
2714 sprintf (x_frame_name, "F%d", x_frame_count++);
2715 f->name = build_string (x_frame_name);
2716 f->explicit_name = 0;
2718 else
2720 f->name = name;
2721 f->explicit_name = 1;
2724 XSETFRAME (frame, f);
2726 /* Note that X Windows does support scroll bars. */
2727 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
2729 f->output_method = output_mac;
2730 f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
2731 bzero (f->output_data.mac, sizeof (struct mac_output));
2732 FRAME_FONTSET (f) = -1;
2733 f->output_data.mac->scroll_bar_foreground_pixel = -1;
2734 f->output_data.mac->scroll_bar_background_pixel = -1;
2736 #if 0
2737 FRAME_FONTSET (f) = -1;
2738 #endif
2740 f->icon_name
2741 = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
2742 if (! STRINGP (f->icon_name))
2743 f->icon_name = Qnil;
2745 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
2746 #ifdef MULTI_KBOARD
2747 FRAME_KBOARD (f) = kb;
2748 #endif
2750 /* Specify the parent under which to make this window. */
2752 if (!NILP (parent))
2754 f->output_data.mac->parent_desc = (Window) parent;
2755 f->output_data.mac->explicit_parent = 1;
2757 else
2759 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
2760 f->output_data.mac->explicit_parent = 0;
2763 /* Set the name; the functions to which we pass f expect the name to
2764 be set. */
2765 if (EQ (name, Qunbound) || NILP (name))
2767 f->name = build_string (dpyinfo->mac_id_name);
2768 f->explicit_name = 0;
2770 else
2772 f->name = name;
2773 f->explicit_name = 1;
2774 /* use the frame's title when getting resources for this frame. */
2775 specbind (Qx_resource_name, name);
2778 /* Extract the window parameters from the supplied values
2779 that are needed to determine window geometry. */
2781 Lisp_Object font;
2783 font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
2785 BLOCK_INPUT;
2786 /* First, try whatever font the caller has specified. */
2787 if (STRINGP (font))
2789 tem = Fquery_fontset (font, Qnil);
2790 if (STRINGP (tem))
2791 font = x_new_fontset (f, SDATA (tem));
2792 else
2793 font = x_new_font (f, SDATA (font));
2795 /* Try out a font which we hope has bold and italic variations. */
2796 if (! STRINGP (font))
2797 font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
2798 /* If those didn't work, look for something which will at least work. */
2799 if (!STRINGP (font))
2800 font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
2801 if (! STRINGP (font))
2802 font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
2803 if (! STRINGP (font))
2804 error ("Cannot find any usable font");
2805 UNBLOCK_INPUT;
2807 x_default_parameter (f, parms, Qfont, font,
2808 "font", "Font", RES_TYPE_STRING);
2811 x_default_parameter (f, parms, Qborder_width, make_number (0),
2812 "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
2813 /* This defaults to 2 in order to match xterm. We recognize either
2814 internalBorderWidth or internalBorder (which is what xterm calls
2815 it). */
2816 if (NILP (Fassq (Qinternal_border_width, parms)))
2818 Lisp_Object value;
2820 value = mac_get_arg (parms, Qinternal_border_width,
2821 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
2822 if (! EQ (value, Qunbound))
2823 parms = Fcons (Fcons (Qinternal_border_width, value),
2824 parms);
2826 /* Default internalBorderWidth to 0 on Windows to match other programs. */
2827 x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
2828 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
2829 x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
2830 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
2832 /* Also do the stuff which must be set before the window exists. */
2833 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
2834 "foreground", "Foreground", RES_TYPE_STRING);
2835 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
2836 "background", "Background", RES_TYPE_STRING);
2837 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
2838 "pointerColor", "Foreground", RES_TYPE_STRING);
2839 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
2840 "cursorColor", "Foreground", RES_TYPE_STRING);
2841 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
2842 "borderColor", "BorderColor", RES_TYPE_STRING);
2843 x_default_parameter (f, parms, Qscreen_gamma, Qnil,
2844 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
2845 x_default_parameter (f, parms, Qline_spacing, Qnil,
2846 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
2847 x_default_parameter (f, parms, Qleft_fringe, Qnil,
2848 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
2849 x_default_parameter (f, parms, Qright_fringe, Qnil,
2850 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
2853 /* Init faces before x_default_parameter is called for scroll-bar
2854 parameters because that function calls x_set_scroll_bar_width,
2855 which calls change_frame_size, which calls Fset_window_buffer,
2856 which runs hooks, which call Fvertical_motion. At the end, we
2857 end up in init_iterator with a null face cache, which should not
2858 happen. */
2859 init_frame_faces (f);
2861 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
2862 "menuBar", "MenuBar", RES_TYPE_NUMBER);
2863 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
2864 "toolBar", "ToolBar", RES_TYPE_NUMBER);
2865 x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
2866 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
2867 x_default_parameter (f, parms, Qtitle, Qnil,
2868 "title", "Title", RES_TYPE_STRING);
2870 f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
2872 /* MAC_TODO: specify 1 below when toolbars are implemented. */
2873 window_prompting = x_figure_window_size (f, parms, 0);
2875 tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
2876 f->no_split = minibuffer_only || EQ (tem, Qt);
2878 /* Create the window. Add the tool-bar height to the initial frame
2879 height so that the user gets a text display area of the size he
2880 specified with -g or via the registry. Later changes of the
2881 tool-bar height don't change the frame size. This is done so that
2882 users can create tall Emacs frames without having to guess how
2883 tall the tool-bar will get. */
2884 f->height += FRAME_TOOL_BAR_LINES (f);
2886 /* mac_window (f, window_prompting, minibuffer_only); */
2887 make_mac_frame (f);
2889 x_icon (f, parms);
2891 x_make_gc (f);
2893 /* Now consider the frame official. */
2894 FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
2895 Vframe_list = Fcons (frame, Vframe_list);
2897 /* We need to do this after creating the window, so that the
2898 icon-creation functions can say whose icon they're describing. */
2899 x_default_parameter (f, parms, Qicon_type, Qnil,
2900 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
2902 x_default_parameter (f, parms, Qauto_raise, Qnil,
2903 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
2904 x_default_parameter (f, parms, Qauto_lower, Qnil,
2905 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
2906 x_default_parameter (f, parms, Qcursor_type, Qbox,
2907 "cursorType", "CursorType", RES_TYPE_SYMBOL);
2908 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
2909 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
2911 /* Dimensions, especially f->height, must be done via change_frame_size.
2912 Change will not be effected unless different from the current
2913 f->height. */
2914 width = f->width;
2915 height = f->height;
2917 f->height = 0;
2918 SET_FRAME_WIDTH (f, 0);
2919 change_frame_size (f, height, width, 1, 0, 0);
2921 /* Set up faces after all frame parameters are known. */
2922 call1 (Qface_set_after_frame_default, frame);
2924 #if 0 /* MAC_TODO: when we have window manager hints */
2925 /* Tell the server what size and position, etc, we want, and how
2926 badly we want them. This should be done after we have the menu
2927 bar so that its size can be taken into account. */
2928 BLOCK_INPUT;
2929 x_wm_set_size_hint (f, window_prompting, 0);
2930 UNBLOCK_INPUT;
2931 #endif
2933 /* Make the window appear on the frame and enable display, unless
2934 the caller says not to. However, with explicit parent, Emacs
2935 cannot control visibility, so don't try. */
2936 if (! f->output_data.mac->explicit_parent)
2938 Lisp_Object visibility;
2940 visibility = mac_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
2941 if (EQ (visibility, Qunbound))
2942 visibility = Qt;
2944 #if 0 /* MAC_TODO: really no iconify on Mac */
2945 if (EQ (visibility, Qicon))
2946 x_iconify_frame (f);
2947 else
2948 #endif
2949 if (! NILP (visibility))
2950 x_make_frame_visible (f);
2951 else
2952 /* Must have been Qnil. */
2955 UNGCPRO;
2957 /* Make sure windows on this frame appear in calls to next-window
2958 and similar functions. */
2959 Vwindow_list = Qnil;
2961 return unbind_to (count, frame);
2964 /* FRAME is used only to get a handle on the X display. We don't pass the
2965 display info directly because we're called from frame.c, which doesn't
2966 know about that structure. */
2967 Lisp_Object
2968 x_get_focus_frame (frame)
2969 struct frame *frame;
2971 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
2972 Lisp_Object xfocus;
2973 if (! dpyinfo->x_focus_frame)
2974 return Qnil;
2976 XSETFRAME (xfocus, dpyinfo->x_focus_frame);
2977 return xfocus;
2980 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2981 doc: /* Internal function called by `color-defined-p', which see. */)
2982 (color, frame)
2983 Lisp_Object color, frame;
2985 XColor foo;
2986 FRAME_PTR f = check_x_frame (frame);
2988 CHECK_STRING (color);
2990 if (mac_defined_color (f, SDATA (color), &foo, 0))
2991 return Qt;
2992 else
2993 return Qnil;
2996 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2997 doc: /* Internal function called by `color-values', which see. */)
2998 (color, frame)
2999 Lisp_Object color, frame;
3001 XColor foo;
3002 FRAME_PTR f = check_x_frame (frame);
3004 CHECK_STRING (color);
3006 if (mac_defined_color (f, SDATA (color), &foo, 0))
3008 Lisp_Object rgb[3];
3010 rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
3011 | RED_FROM_ULONG (foo.pixel));
3012 rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
3013 | GREEN_FROM_ULONG (foo.pixel));
3014 rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
3015 | BLUE_FROM_ULONG (foo.pixel));
3016 return Flist (3, rgb);
3018 else
3019 return Qnil;
3022 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
3023 doc: /* Internal function called by `display-color-p', which see. */)
3024 (display)
3025 Lisp_Object display;
3027 struct mac_display_info *dpyinfo = check_x_display_info (display);
3029 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
3030 return Qnil;
3032 return Qt;
3035 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
3036 0, 1, 0,
3037 doc: /* Return t if the X display supports shades of gray.
3038 Note that color displays do support shades of gray.
3039 The optional argument DISPLAY specifies which display to ask about.
3040 DISPLAY should be either a frame or a display name (a string).
3041 If omitted or nil, that stands for the selected frame's display. */)
3042 (display)
3043 Lisp_Object display;
3045 struct mac_display_info *dpyinfo = check_x_display_info (display);
3047 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
3048 return Qnil;
3050 return Qt;
3053 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
3054 0, 1, 0,
3055 doc: /* Returns the width in pixels of the X display DISPLAY.
3056 The optional argument DISPLAY specifies which display to ask about.
3057 DISPLAY should be either a frame or a display name (a string).
3058 If omitted or nil, that stands for the selected frame's display. */)
3059 (display)
3060 Lisp_Object display;
3062 struct mac_display_info *dpyinfo = check_x_display_info (display);
3064 return make_number (dpyinfo->width);
3067 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
3068 Sx_display_pixel_height, 0, 1, 0,
3069 doc: /* Returns the height in pixels of the X display DISPLAY.
3070 The optional argument DISPLAY specifies which display to ask about.
3071 DISPLAY should be either a frame or a display name (a string).
3072 If omitted or nil, that stands for the selected frame's display. */)
3073 (display)
3074 Lisp_Object display;
3076 struct mac_display_info *dpyinfo = check_x_display_info (display);
3078 return make_number (dpyinfo->height);
3081 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
3082 0, 1, 0,
3083 doc: /* Returns the number of bitplanes of the display DISPLAY.
3084 The optional argument DISPLAY specifies which display to ask about.
3085 DISPLAY should be either a frame or a display name (a string).
3086 If omitted or nil, that stands for the selected frame's display. */)
3087 (display)
3088 Lisp_Object display;
3090 struct mac_display_info *dpyinfo = check_x_display_info (display);
3092 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
3095 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3096 0, 1, 0,
3097 doc: /* Returns the number of color cells of the display DISPLAY.
3098 The optional argument DISPLAY specifies which display to ask about.
3099 DISPLAY should be either a frame or a display name (a string).
3100 If omitted or nil, that stands for the selected frame's display. */)
3101 (display)
3102 Lisp_Object display;
3104 struct mac_display_info *dpyinfo = check_x_display_info (display);
3106 /* MAC_TODO: check whether this is right */
3107 return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
3110 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3111 Sx_server_max_request_size,
3112 0, 1, 0,
3113 doc: /* Returns the maximum request size of the server of display DISPLAY.
3114 The optional argument DISPLAY specifies which display to ask about.
3115 DISPLAY should be either a frame or a display name (a string).
3116 If omitted or nil, that stands for the selected frame's display. */)
3117 (display)
3118 Lisp_Object display;
3120 struct mac_display_info *dpyinfo = check_x_display_info (display);
3122 return make_number (1);
3125 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
3126 doc: /* Returns the vendor ID string of the Mac OS system (Apple).
3127 The optional argument DISPLAY specifies which display to ask about.
3128 DISPLAY should be either a frame or a display name (a string).
3129 If omitted or nil, that stands for the selected frame's display. */)
3130 (display)
3131 Lisp_Object display;
3133 return build_string ("Apple Computers");
3136 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
3137 doc: /* Returns the version numbers of the server of display DISPLAY.
3138 The value is a list of three integers: the major and minor
3139 version numbers, and the vendor-specific release
3140 number. See also the function `x-server-vendor'.
3142 The optional argument DISPLAY specifies which display to ask about.
3143 DISPLAY should be either a frame or a display name (a string).
3144 If omitted or nil, that stands for the selected frame's display. */)
3145 (display)
3146 Lisp_Object display;
3148 int mac_major_version, mac_minor_version;
3149 SInt32 response;
3151 if (Gestalt (gestaltSystemVersion, &response) != noErr)
3152 error ("Cannot get Mac OS version");
3154 mac_major_version = (response >> 8) & 0xf;
3155 mac_minor_version = (response >> 4) & 0xf;
3157 return Fcons (make_number (mac_major_version),
3158 Fcons (make_number (mac_minor_version), Qnil));
3161 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
3162 doc: /* Return the number of screens on the server of display DISPLAY.
3163 The optional argument DISPLAY specifies which display to ask about.
3164 DISPLAY should be either a frame or a display name (a string).
3165 If omitted or nil, that stands for the selected frame's display. */)
3166 (display)
3167 Lisp_Object display;
3169 return make_number (1);
3172 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
3173 doc: /* Return the height in millimeters of the X display DISPLAY.
3174 The optional argument DISPLAY specifies which display to ask about.
3175 DISPLAY should be either a frame or a display name (a string).
3176 If omitted or nil, that stands for the selected frame's display. */)
3177 (display)
3178 Lisp_Object display;
3180 /* MAC_TODO: this is an approximation, and only of the main display */
3182 struct mac_display_info *dpyinfo = check_x_display_info (display);
3183 short h, v;
3185 ScreenRes (&h, &v);
3187 return make_number ((int) (v / 72.0 * 25.4));
3190 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
3191 doc: /* Return the width in millimeters of the X display DISPLAY.
3192 The optional argument DISPLAY specifies which display to ask about.
3193 DISPLAY should be either a frame or a display name (a string).
3194 If omitted or nil, that stands for the selected frame's display. */)
3195 (display)
3196 Lisp_Object display;
3198 /* MAC_TODO: this is an approximation, and only of the main display */
3200 struct mac_display_info *dpyinfo = check_x_display_info (display);
3201 short h, v;
3203 ScreenRes (&h, &v);
3205 return make_number ((int) (h / 72.0 * 25.4));
3208 DEFUN ("x-display-backing-store", Fx_display_backing_store,
3209 Sx_display_backing_store, 0, 1, 0,
3210 doc: /* Returns an indication of whether display DISPLAY does backing store.
3211 The value may be `always', `when-mapped', or `not-useful'.
3212 The optional argument DISPLAY specifies which display to ask about.
3213 DISPLAY should be either a frame or a display name (a string).
3214 If omitted or nil, that stands for the selected frame's display. */)
3215 (display)
3216 Lisp_Object display;
3218 return intern ("not-useful");
3221 DEFUN ("x-display-visual-class", Fx_display_visual_class,
3222 Sx_display_visual_class, 0, 1, 0,
3223 doc: /* Returns the visual class of the display DISPLAY.
3224 The value is one of the symbols `static-gray', `gray-scale',
3225 `static-color', `pseudo-color', `true-color', or `direct-color'.
3227 The optional argument DISPLAY specifies which display to ask about.
3228 DISPLAY should be either a frame or a display name (a string).
3229 If omitted or nil, that stands for the selected frame's display. */)
3230 (display)
3231 Lisp_Object display;
3233 struct mac_display_info *dpyinfo = check_x_display_info (display);
3235 #if 0
3236 switch (dpyinfo->visual->class)
3238 case StaticGray: return (intern ("static-gray"));
3239 case GrayScale: return (intern ("gray-scale"));
3240 case StaticColor: return (intern ("static-color"));
3241 case PseudoColor: return (intern ("pseudo-color"));
3242 case TrueColor: return (intern ("true-color"));
3243 case DirectColor: return (intern ("direct-color"));
3244 default:
3245 error ("Display has an unknown visual class");
3247 #endif /* 0 */
3249 return (intern ("true-color"));
3252 DEFUN ("x-display-save-under", Fx_display_save_under,
3253 Sx_display_save_under, 0, 1, 0,
3254 doc: /* Returns t if the display DISPLAY supports the save-under feature.
3255 The optional argument DISPLAY specifies which display to ask about.
3256 DISPLAY should be either a frame or a display name (a string).
3257 If omitted or nil, that stands for the selected frame's display. */)
3258 (display)
3259 Lisp_Object display;
3261 return Qnil;
3265 x_pixel_width (f)
3266 register struct frame *f;
3268 return PIXEL_WIDTH (f);
3272 x_pixel_height (f)
3273 register struct frame *f;
3275 return PIXEL_HEIGHT (f);
3279 x_char_width (f)
3280 register struct frame *f;
3282 return FONT_WIDTH (f->output_data.mac->font);
3286 x_char_height (f)
3287 register struct frame *f;
3289 return f->output_data.mac->line_height;
3293 x_screen_planes (f)
3294 register struct frame *f;
3296 return FRAME_MAC_DISPLAY_INFO (f)->n_planes;
3299 /* Return the display structure for the display named NAME.
3300 Open a new connection if necessary. */
3302 struct mac_display_info *
3303 x_display_info_for_name (name)
3304 Lisp_Object name;
3306 Lisp_Object names;
3307 struct mac_display_info *dpyinfo;
3309 CHECK_STRING (name);
3311 for (dpyinfo = &one_mac_display_info, names = x_display_name_list;
3312 dpyinfo;
3313 dpyinfo = dpyinfo->next, names = XCDR (names))
3315 Lisp_Object tem;
3316 tem = Fstring_equal (XCAR (XCAR (names)), name);
3317 if (!NILP (tem))
3318 return dpyinfo;
3321 /* Use this general default value to start with. */
3322 Vx_resource_name = Vinvocation_name;
3324 validate_x_resource_name ();
3326 dpyinfo = mac_term_init (name, (unsigned char *) 0,
3327 (char *) SDATA (Vx_resource_name));
3329 if (dpyinfo == 0)
3330 error ("Cannot connect to server %s", SDATA (name));
3332 mac_in_use = 1;
3333 XSETFASTINT (Vwindow_system_version, 3);
3335 return dpyinfo;
3338 #if 0 /* MAC_TODO: implement network support */
3339 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
3340 1, 3, 0,
3341 doc: /* Open a connection to a server.
3342 DISPLAY is the name of the display to connect to.
3343 Optional second arg XRM-STRING is a string of resources in xrdb format.
3344 If the optional third arg MUST-SUCCEED is non-nil,
3345 terminate Emacs if we can't open the connection. */)
3346 (display, xrm_string, must_succeed)
3347 Lisp_Object display, xrm_string, must_succeed;
3349 unsigned char *xrm_option;
3350 struct mac_display_info *dpyinfo;
3352 CHECK_STRING (display);
3353 if (! NILP (xrm_string))
3354 CHECK_STRING (xrm_string);
3356 if (! EQ (Vwindow_system, intern ("mac")))
3357 error ("Not using Mac OS");
3359 if (! NILP (xrm_string))
3360 xrm_option = (unsigned char *) SDATA (xrm_string);
3361 else
3362 xrm_option = (unsigned char *) 0;
3364 validate_x_resource_name ();
3366 /* This is what opens the connection and sets x_current_display.
3367 This also initializes many symbols, such as those used for input. */
3368 dpyinfo = mac_term_init (display, xrm_option,
3369 (char *) SDATA (Vx_resource_name));
3371 if (dpyinfo == 0)
3373 if (!NILP (must_succeed))
3374 fatal ("Cannot connect to server %s.\n",
3375 SDATA (display));
3376 else
3377 error ("Cannot connect to server %s", SDATA (display));
3380 mac_in_use = 1;
3382 XSETFASTINT (Vwindow_system_version, 3);
3383 return Qnil;
3386 DEFUN ("x-close-connection", Fx_close_connection,
3387 Sx_close_connection, 1, 1, 0,
3388 doc: /* Close the connection to DISPLAY's server.
3389 For DISPLAY, specify either a frame or a display name (a string).
3390 If DISPLAY is nil, that stands for the selected frame's display. */)
3391 (display)
3392 Lisp_Object display;
3394 struct mac_display_info *dpyinfo = check_x_display_info (display);
3395 int i;
3397 if (dpyinfo->reference_count > 0)
3398 error ("Display still has frames on it");
3400 BLOCK_INPUT;
3401 /* Free the fonts in the font table. */
3402 for (i = 0; i < dpyinfo->n_fonts; i++)
3403 if (dpyinfo->font_table[i].name)
3405 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
3406 xfree (dpyinfo->font_table[i].full_name);
3407 xfree (dpyinfo->font_table[i].name);
3408 x_unload_font (dpyinfo, dpyinfo->font_table[i].font);
3410 x_destroy_all_bitmaps (dpyinfo);
3412 x_delete_display (dpyinfo);
3413 UNBLOCK_INPUT;
3415 return Qnil;
3417 #endif /* 0 */
3419 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
3420 doc: /* Return the list of display names that Emacs has connections to. */)
3423 Lisp_Object tail, result;
3425 result = Qnil;
3426 for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
3427 result = Fcons (XCAR (XCAR (tail)), result);
3429 return result;
3432 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
3433 doc: /* If ON is non-nil, report errors as soon as the erring request is made.
3434 If ON is nil, allow buffering of requests.
3435 This is a noop on Mac OS systems.
3436 The optional second argument DISPLAY specifies which display to act on.
3437 DISPLAY should be either a frame or a display name (a string).
3438 If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
3439 (on, display)
3440 Lisp_Object display, on;
3442 return Qnil;
3446 /***********************************************************************
3447 Image types
3448 ***********************************************************************/
3450 /* Value is the number of elements of vector VECTOR. */
3452 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
3454 /* List of supported image types. Use define_image_type to add new
3455 types. Use lookup_image_type to find a type for a given symbol. */
3457 static struct image_type *image_types;
3459 /* The symbol `image' which is the car of the lists used to represent
3460 images in Lisp. */
3462 extern Lisp_Object Qimage;
3464 /* The symbol `xbm' which is used as the type symbol for XBM images. */
3466 Lisp_Object Qxbm;
3468 /* Keywords. */
3470 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
3471 extern Lisp_Object QCdata, QCtype;
3472 Lisp_Object QCascent, QCmargin, QCrelief;
3473 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
3474 Lisp_Object QCindex;
3476 /* Other symbols. */
3478 Lisp_Object Qlaplace;
3480 /* Time in seconds after which images should be removed from the cache
3481 if not displayed. */
3483 Lisp_Object Vimage_cache_eviction_delay;
3485 /* Function prototypes. */
3487 static void define_image_type P_ ((struct image_type *type));
3488 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
3489 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
3490 static void x_laplace P_ ((struct frame *, struct image *));
3491 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
3492 Lisp_Object));
3495 /* Define a new image type from TYPE. This adds a copy of TYPE to
3496 image_types and adds the symbol *TYPE->type to Vimage_types. */
3498 static void
3499 define_image_type (type)
3500 struct image_type *type;
3502 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
3503 The initialized data segment is read-only. */
3504 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
3505 bcopy (type, p, sizeof *p);
3506 p->next = image_types;
3507 image_types = p;
3508 Vimage_types = Fcons (*p->type, Vimage_types);
3512 /* Look up image type SYMBOL, and return a pointer to its image_type
3513 structure. Value is null if SYMBOL is not a known image type. */
3515 static INLINE struct image_type *
3516 lookup_image_type (symbol)
3517 Lisp_Object symbol;
3519 struct image_type *type;
3521 for (type = image_types; type; type = type->next)
3522 if (EQ (symbol, *type->type))
3523 break;
3525 return type;
3529 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
3530 valid image specification is a list whose car is the symbol
3531 `image', and whose rest is a property list. The property list must
3532 contain a value for key `:type'. That value must be the name of a
3533 supported image type. The rest of the property list depends on the
3534 image type. */
3537 valid_image_p (object)
3538 Lisp_Object object;
3540 int valid_p = 0;
3542 if (CONSP (object) && EQ (XCAR (object), Qimage))
3544 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
3545 struct image_type *type = lookup_image_type (symbol);
3547 if (type)
3548 valid_p = type->valid_p (object);
3551 return valid_p;
3555 /* Log error message with format string FORMAT and argument ARG.
3556 Signaling an error, e.g. when an image cannot be loaded, is not a
3557 good idea because this would interrupt redisplay, and the error
3558 message display would lead to another redisplay. This function
3559 therefore simply displays a message. */
3561 static void
3562 image_error (format, arg1, arg2)
3563 char *format;
3564 Lisp_Object arg1, arg2;
3566 add_to_log (format, arg1, arg2);
3571 /***********************************************************************
3572 Image specifications
3573 ***********************************************************************/
3575 enum image_value_type
3577 IMAGE_DONT_CHECK_VALUE_TYPE,
3578 IMAGE_STRING_VALUE,
3579 IMAGE_SYMBOL_VALUE,
3580 IMAGE_POSITIVE_INTEGER_VALUE,
3581 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
3582 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
3583 IMAGE_ASCENT_VALUE,
3584 IMAGE_INTEGER_VALUE,
3585 IMAGE_FUNCTION_VALUE,
3586 IMAGE_NUMBER_VALUE,
3587 IMAGE_BOOL_VALUE
3590 /* Structure used when parsing image specifications. */
3592 struct image_keyword
3594 /* Name of keyword. */
3595 char *name;
3597 /* The type of value allowed. */
3598 enum image_value_type type;
3600 /* Non-zero means key must be present. */
3601 int mandatory_p;
3603 /* Used to recognize duplicate keywords in a property list. */
3604 int count;
3606 /* The value that was found. */
3607 Lisp_Object value;
3611 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
3612 int, Lisp_Object));
3613 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
3616 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
3617 has the format (image KEYWORD VALUE ...). One of the keyword/
3618 value pairs must be `:type TYPE'. KEYWORDS is a vector of
3619 image_keywords structures of size NKEYWORDS describing other
3620 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
3622 static int
3623 parse_image_spec (spec, keywords, nkeywords, type)
3624 Lisp_Object spec;
3625 struct image_keyword *keywords;
3626 int nkeywords;
3627 Lisp_Object type;
3629 int i;
3630 Lisp_Object plist;
3632 if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
3633 return 0;
3635 plist = XCDR (spec);
3636 while (CONSP (plist))
3638 Lisp_Object key, value;
3640 /* First element of a pair must be a symbol. */
3641 key = XCAR (plist);
3642 plist = XCDR (plist);
3643 if (!SYMBOLP (key))
3644 return 0;
3646 /* There must follow a value. */
3647 if (!CONSP (plist))
3648 return 0;
3649 value = XCAR (plist);
3650 plist = XCDR (plist);
3652 /* Find key in KEYWORDS. Error if not found. */
3653 for (i = 0; i < nkeywords; ++i)
3654 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
3655 break;
3657 if (i == nkeywords)
3658 continue;
3660 /* Record that we recognized the keyword. If a keywords
3661 was found more than once, it's an error. */
3662 keywords[i].value = value;
3663 ++keywords[i].count;
3665 if (keywords[i].count > 1)
3666 return 0;
3668 /* Check type of value against allowed type. */
3669 switch (keywords[i].type)
3671 case IMAGE_STRING_VALUE:
3672 if (!STRINGP (value))
3673 return 0;
3674 break;
3676 case IMAGE_SYMBOL_VALUE:
3677 if (!SYMBOLP (value))
3678 return 0;
3679 break;
3681 case IMAGE_POSITIVE_INTEGER_VALUE:
3682 if (!INTEGERP (value) || XINT (value) <= 0)
3683 return 0;
3684 break;
3686 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
3687 if (INTEGERP (value) && XINT (value) >= 0)
3688 break;
3689 if (CONSP (value)
3690 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
3691 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
3692 break;
3693 return 0;
3695 case IMAGE_ASCENT_VALUE:
3696 if (SYMBOLP (value) && EQ (value, Qcenter))
3697 break;
3698 else if (INTEGERP (value)
3699 && XINT (value) >= 0
3700 && XINT (value) <= 100)
3701 break;
3702 return 0;
3704 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
3705 if (!INTEGERP (value) || XINT (value) < 0)
3706 return 0;
3707 break;
3709 case IMAGE_DONT_CHECK_VALUE_TYPE:
3710 break;
3712 case IMAGE_FUNCTION_VALUE:
3713 value = indirect_function (value);
3714 if (SUBRP (value)
3715 || COMPILEDP (value)
3716 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
3717 break;
3718 return 0;
3720 case IMAGE_NUMBER_VALUE:
3721 if (!INTEGERP (value) && !FLOATP (value))
3722 return 0;
3723 break;
3725 case IMAGE_INTEGER_VALUE:
3726 if (!INTEGERP (value))
3727 return 0;
3728 break;
3730 case IMAGE_BOOL_VALUE:
3731 if (!NILP (value) && !EQ (value, Qt))
3732 return 0;
3733 break;
3735 default:
3736 abort ();
3737 break;
3740 if (EQ (key, QCtype) && !EQ (type, value))
3741 return 0;
3744 /* Check that all mandatory fields are present. */
3745 for (i = 0; i < nkeywords; ++i)
3746 if (keywords[i].mandatory_p && keywords[i].count == 0)
3747 return 0;
3749 return NILP (plist);
3753 /* Return the value of KEY in image specification SPEC. Value is nil
3754 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
3755 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
3757 static Lisp_Object
3758 image_spec_value (spec, key, found)
3759 Lisp_Object spec, key;
3760 int *found;
3762 Lisp_Object tail;
3764 xassert (valid_image_p (spec));
3766 for (tail = XCDR (spec);
3767 CONSP (tail) && CONSP (XCDR (tail));
3768 tail = XCDR (XCDR (tail)))
3770 if (EQ (XCAR (tail), key))
3772 if (found)
3773 *found = 1;
3774 return XCAR (XCDR (tail));
3778 if (found)
3779 *found = 0;
3780 return Qnil;
3786 /***********************************************************************
3787 Image type independent image structures
3788 ***********************************************************************/
3790 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
3791 static void free_image P_ ((struct frame *f, struct image *img));
3794 /* Allocate and return a new image structure for image specification
3795 SPEC. SPEC has a hash value of HASH. */
3797 static struct image *
3798 make_image (spec, hash)
3799 Lisp_Object spec;
3800 unsigned hash;
3802 struct image *img = (struct image *) xmalloc (sizeof *img);
3804 xassert (valid_image_p (spec));
3805 bzero (img, sizeof *img);
3806 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
3807 xassert (img->type != NULL);
3808 img->spec = spec;
3809 img->data.lisp_val = Qnil;
3810 img->ascent = DEFAULT_IMAGE_ASCENT;
3811 img->hash = hash;
3812 return img;
3816 /* Free image IMG which was used on frame F, including its resources. */
3818 static void
3819 free_image (f, img)
3820 struct frame *f;
3821 struct image *img;
3823 if (img)
3825 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
3827 /* Remove IMG from the hash table of its cache. */
3828 if (img->prev)
3829 img->prev->next = img->next;
3830 else
3831 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
3833 if (img->next)
3834 img->next->prev = img->prev;
3836 c->images[img->id] = NULL;
3838 /* Free resources, then free IMG. */
3839 img->type->free (f, img);
3840 xfree (img);
3845 /* Prepare image IMG for display on frame F. Must be called before
3846 drawing an image. */
3848 void
3849 prepare_image_for_display (f, img)
3850 struct frame *f;
3851 struct image *img;
3853 EMACS_TIME t;
3855 /* We're about to display IMG, so set its timestamp to `now'. */
3856 EMACS_GET_TIME (t);
3857 img->timestamp = EMACS_SECS (t);
3859 /* If IMG doesn't have a pixmap yet, load it now, using the image
3860 type dependent loader function. */
3861 if (img->pixmap == 0 && !img->load_failed_p)
3862 img->load_failed_p = img->type->load (f, img) == 0;
3866 /* Value is the number of pixels for the ascent of image IMG when
3867 drawn in face FACE. */
3870 image_ascent (img, face)
3871 struct image *img;
3872 struct face *face;
3874 int height = img->height + img->vmargin;
3875 int ascent;
3877 if (img->ascent == CENTERED_IMAGE_ASCENT)
3879 if (face->font)
3880 ascent = height / 2 - (FONT_DESCENT(face->font)
3881 - FONT_BASE(face->font)) / 2;
3882 else
3883 ascent = height / 2;
3885 else
3886 ascent = height * img->ascent / 100.0;
3888 return ascent;
3893 /***********************************************************************
3894 Helper functions for X image types
3895 ***********************************************************************/
3897 static void x_clear_image P_ ((struct frame *f, struct image *img));
3898 static unsigned long x_alloc_image_color P_ ((struct frame *f,
3899 struct image *img,
3900 Lisp_Object color_name,
3901 unsigned long dflt));
3903 /* Free X resources of image IMG which is used on frame F. */
3905 static void
3906 x_clear_image (f, img)
3907 struct frame *f;
3908 struct image *img;
3910 #if 0 /* MAC_TODO: W32 image support */
3912 if (img->pixmap)
3914 BLOCK_INPUT;
3915 XFreePixmap (NULL, img->pixmap);
3916 img->pixmap = 0;
3917 UNBLOCK_INPUT;
3920 if (img->ncolors)
3922 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
3924 /* If display has an immutable color map, freeing colors is not
3925 necessary and some servers don't allow it. So don't do it. */
3926 if (class != StaticColor
3927 && class != StaticGray
3928 && class != TrueColor)
3930 Colormap cmap;
3931 BLOCK_INPUT;
3932 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
3933 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
3934 img->ncolors, 0);
3935 UNBLOCK_INPUT;
3938 xfree (img->colors);
3939 img->colors = NULL;
3940 img->ncolors = 0;
3942 #endif /* MAC_TODO */
3946 /* Allocate color COLOR_NAME for image IMG on frame F. If color
3947 cannot be allocated, use DFLT. Add a newly allocated color to
3948 IMG->colors, so that it can be freed again. Value is the pixel
3949 color. */
3951 static unsigned long
3952 x_alloc_image_color (f, img, color_name, dflt)
3953 struct frame *f;
3954 struct image *img;
3955 Lisp_Object color_name;
3956 unsigned long dflt;
3958 #if 0 /* MAC_TODO: allocing colors. */
3959 XColor color;
3960 unsigned long result;
3962 xassert (STRINGP (color_name));
3964 if (w32_defined_color (f, SDATA (color_name), &color, 1))
3966 /* This isn't called frequently so we get away with simply
3967 reallocating the color vector to the needed size, here. */
3968 ++img->ncolors;
3969 img->colors =
3970 (unsigned long *) xrealloc (img->colors,
3971 img->ncolors * sizeof *img->colors);
3972 img->colors[img->ncolors - 1] = color.pixel;
3973 result = color.pixel;
3975 else
3976 result = dflt;
3977 return result;
3978 #endif /* MAC_TODO */
3979 return 0;
3984 /***********************************************************************
3985 Image Cache
3986 ***********************************************************************/
3988 static void cache_image P_ ((struct frame *f, struct image *img));
3991 /* Return a new, initialized image cache that is allocated from the
3992 heap. Call free_image_cache to free an image cache. */
3994 struct image_cache *
3995 make_image_cache ()
3997 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
3998 int size;
4000 bzero (c, sizeof *c);
4001 c->size = 50;
4002 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
4003 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
4004 c->buckets = (struct image **) xmalloc (size);
4005 bzero (c->buckets, size);
4006 return c;
4010 /* Free image cache of frame F. Be aware that X frames share images
4011 caches. */
4013 void
4014 free_image_cache (f)
4015 struct frame *f;
4017 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4018 if (c)
4020 int i;
4022 /* Cache should not be referenced by any frame when freed. */
4023 xassert (c->refcount == 0);
4025 for (i = 0; i < c->used; ++i)
4026 free_image (f, c->images[i]);
4027 xfree (c->images);
4028 xfree (c->buckets);
4029 xfree (c);
4030 FRAME_X_IMAGE_CACHE (f) = NULL;
4035 /* Clear image cache of frame F. FORCE_P non-zero means free all
4036 images. FORCE_P zero means clear only images that haven't been
4037 displayed for some time. Should be called from time to time to
4038 reduce the number of loaded images. If image-eviction-seconds is
4039 non-nil, this frees images in the cache which weren't displayed for
4040 at least that many seconds. */
4042 void
4043 clear_image_cache (f, force_p)
4044 struct frame *f;
4045 int force_p;
4047 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4049 if (c && INTEGERP (Vimage_cache_eviction_delay))
4051 EMACS_TIME t;
4052 unsigned long old;
4053 int i, any_freed_p = 0;
4055 EMACS_GET_TIME (t);
4056 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
4058 for (i = 0; i < c->used; ++i)
4060 struct image *img = c->images[i];
4061 if (img != NULL
4062 && (force_p
4063 || (img->timestamp > old)))
4065 free_image (f, img);
4066 any_freed_p = 1;
4070 /* We may be clearing the image cache because, for example,
4071 Emacs was iconified for a longer period of time. In that
4072 case, current matrices may still contain references to
4073 images freed above. So, clear these matrices. */
4074 if (any_freed_p)
4076 clear_current_matrices (f);
4077 ++windows_or_buffers_changed;
4083 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
4084 0, 1, 0,
4085 doc: /* Clear the image cache of FRAME.
4086 FRAME nil or omitted means use the selected frame.
4087 FRAME t means clear the image caches of all frames. */)
4088 (frame)
4089 Lisp_Object frame;
4091 if (EQ (frame, Qt))
4093 Lisp_Object tail;
4095 FOR_EACH_FRAME (tail, frame)
4096 if (FRAME_MAC_P (XFRAME (frame)))
4097 clear_image_cache (XFRAME (frame), 1);
4099 else
4100 clear_image_cache (check_x_frame (frame), 1);
4102 return Qnil;
4106 /* Return the id of image with Lisp specification SPEC on frame F.
4107 SPEC must be a valid Lisp image specification (see valid_image_p). */
4110 lookup_image (f, spec)
4111 struct frame *f;
4112 Lisp_Object spec;
4114 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4115 struct image *img;
4116 int i;
4117 unsigned hash;
4118 struct gcpro gcpro1;
4119 EMACS_TIME now;
4121 /* F must be a window-system frame, and SPEC must be a valid image
4122 specification. */
4123 xassert (FRAME_WINDOW_P (f));
4124 xassert (valid_image_p (spec));
4126 GCPRO1 (spec);
4128 /* Look up SPEC in the hash table of the image cache. */
4129 hash = sxhash (spec, 0);
4130 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
4132 for (img = c->buckets[i]; img; img = img->next)
4133 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
4134 break;
4136 /* If not found, create a new image and cache it. */
4137 if (img == NULL)
4139 BLOCK_INPUT;
4140 img = make_image (spec, hash);
4141 cache_image (f, img);
4142 img->load_failed_p = img->type->load (f, img) == 0;
4143 xassert (!interrupt_input_blocked);
4145 /* If we can't load the image, and we don't have a width and
4146 height, use some arbitrary width and height so that we can
4147 draw a rectangle for it. */
4148 if (img->load_failed_p)
4150 Lisp_Object value;
4152 value = image_spec_value (spec, QCwidth, NULL);
4153 img->width = (INTEGERP (value)
4154 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
4155 value = image_spec_value (spec, QCheight, NULL);
4156 img->height = (INTEGERP (value)
4157 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
4159 else
4161 /* Handle image type independent image attributes
4162 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
4163 Lisp_Object ascent, margin, relief;
4165 ascent = image_spec_value (spec, QCascent, NULL);
4166 if (INTEGERP (ascent))
4167 img->ascent = XFASTINT (ascent);
4168 else if (EQ (ascent, Qcenter))
4169 img->ascent = CENTERED_IMAGE_ASCENT;
4171 margin = image_spec_value (spec, QCmargin, NULL);
4172 if (INTEGERP (margin) && XINT (margin) >= 0)
4173 img->vmargin = img->hmargin = XFASTINT (margin);
4174 else if (CONSP (margin) && INTEGERP (XCAR (margin))
4175 && INTEGERP (XCDR (margin)))
4177 if (XINT (XCAR (margin)) > 0)
4178 img->hmargin = XFASTINT (XCAR (margin));
4179 if (XINT (XCDR (margin)) > 0)
4180 img->vmargin = XFASTINT (XCDR (margin));
4183 relief = image_spec_value (spec, QCrelief, NULL);
4184 if (INTEGERP (relief))
4186 img->relief = XINT (relief);
4187 img->hmargin += abs (img->relief);
4188 img->vmargin += abs (img->relief);
4193 /* We're using IMG, so set its timestamp to `now'. */
4194 EMACS_GET_TIME (now);
4195 img->timestamp = EMACS_SECS (now);
4197 UNGCPRO;
4199 /* Value is the image id. */
4200 return img->id;
4204 /* Cache image IMG in the image cache of frame F. */
4206 static void
4207 cache_image (f, img)
4208 struct frame *f;
4209 struct image *img;
4211 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4212 int i;
4214 /* Find a free slot in c->images. */
4215 for (i = 0; i < c->used; ++i)
4216 if (c->images[i] == NULL)
4217 break;
4219 /* If no free slot found, maybe enlarge c->images. */
4220 if (i == c->used && c->used == c->size)
4222 c->size *= 2;
4223 c->images = (struct image **) xrealloc (c->images,
4224 c->size * sizeof *c->images);
4227 /* Add IMG to c->images, and assign IMG an id. */
4228 c->images[i] = img;
4229 img->id = i;
4230 if (i == c->used)
4231 ++c->used;
4233 /* Add IMG to the cache's hash table. */
4234 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
4235 img->next = c->buckets[i];
4236 if (img->next)
4237 img->next->prev = img;
4238 img->prev = NULL;
4239 c->buckets[i] = img;
4243 /* Call FN on every image in the image cache of frame F. Used to mark
4244 Lisp Objects in the image cache. */
4246 void
4247 forall_images_in_image_cache (f, fn)
4248 struct frame *f;
4249 void (*fn) P_ ((struct image *img));
4251 if (FRAME_LIVE_P (f) && FRAME_MAC_P (f))
4253 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
4254 if (c)
4256 int i;
4257 for (i = 0; i < c->used; ++i)
4258 if (c->images[i])
4259 fn (c->images[i]);
4266 /***********************************************************************
4267 Mac support code
4268 ***********************************************************************/
4270 #if 0 /* MAC_TODO: Mac specific image code. */
4272 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
4273 XImage **, Pixmap *));
4274 static void x_destroy_x_image P_ ((XImage *));
4275 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
4278 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
4279 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
4280 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
4281 via xmalloc. Print error messages via image_error if an error
4282 occurs. Value is non-zero if successful. */
4284 static int
4285 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
4286 struct frame *f;
4287 int width, height, depth;
4288 XImage **ximg;
4289 Pixmap *pixmap;
4291 #if 0 /* MAC_TODO: Image support for Mac */
4292 Display *display = FRAME_W32_DISPLAY (f);
4293 Screen *screen = FRAME_X_SCREEN (f);
4294 Window window = FRAME_W32_WINDOW (f);
4296 xassert (interrupt_input_blocked);
4298 if (depth <= 0)
4299 depth = DefaultDepthOfScreen (screen);
4300 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
4301 depth, ZPixmap, 0, NULL, width, height,
4302 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
4303 if (*ximg == NULL)
4305 image_error ("Unable to allocate X image", Qnil, Qnil);
4306 return 0;
4309 /* Allocate image raster. */
4310 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
4312 /* Allocate a pixmap of the same size. */
4313 *pixmap = XCreatePixmap (display, window, width, height, depth);
4314 if (*pixmap == 0)
4316 x_destroy_x_image (*ximg);
4317 *ximg = NULL;
4318 image_error ("Unable to create X pixmap", Qnil, Qnil);
4319 return 0;
4321 #endif /* MAC_TODO */
4322 return 1;
4326 /* Destroy XImage XIMG. Free XIMG->data. */
4328 static void
4329 x_destroy_x_image (ximg)
4330 XImage *ximg;
4332 xassert (interrupt_input_blocked);
4333 if (ximg)
4335 xfree (ximg->data);
4336 ximg->data = NULL;
4337 XDestroyImage (ximg);
4342 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
4343 are width and height of both the image and pixmap. */
4345 static void
4346 x_put_x_image (f, ximg, pixmap, width, height)
4347 struct frame *f;
4348 XImage *ximg;
4349 Pixmap pixmap;
4351 GC gc;
4353 xassert (interrupt_input_blocked);
4354 gc = XCreateGC (NULL, pixmap, 0, NULL);
4355 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
4356 XFreeGC (NULL, gc);
4359 #endif /* MAC_TODO */
4362 /***********************************************************************
4363 Searching files
4364 ***********************************************************************/
4366 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
4368 /* Find image file FILE. Look in data-directory, then
4369 x-bitmap-file-path. Value is the full name of the file found, or
4370 nil if not found. */
4372 static Lisp_Object
4373 x_find_image_file (file)
4374 Lisp_Object file;
4376 Lisp_Object file_found, search_path;
4377 struct gcpro gcpro1, gcpro2;
4378 int fd;
4380 file_found = Qnil;
4381 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
4382 GCPRO2 (file_found, search_path);
4384 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
4385 fd = openp (search_path, file, Qnil, &file_found, Qnil);
4387 if (fd < 0)
4388 file_found = Qnil;
4389 else
4390 close (fd);
4392 UNGCPRO;
4393 return file_found;
4397 /***********************************************************************
4398 XBM images
4399 ***********************************************************************/
4401 static int xbm_load P_ ((struct frame *f, struct image *img));
4402 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
4403 Lisp_Object file));
4404 static int xbm_image_p P_ ((Lisp_Object object));
4405 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
4406 unsigned char **));
4409 /* Indices of image specification fields in xbm_format, below. */
4411 enum xbm_keyword_index
4413 XBM_TYPE,
4414 XBM_FILE,
4415 XBM_WIDTH,
4416 XBM_HEIGHT,
4417 XBM_DATA,
4418 XBM_FOREGROUND,
4419 XBM_BACKGROUND,
4420 XBM_ASCENT,
4421 XBM_MARGIN,
4422 XBM_RELIEF,
4423 XBM_ALGORITHM,
4424 XBM_HEURISTIC_MASK,
4425 XBM_LAST
4428 /* Vector of image_keyword structures describing the format
4429 of valid XBM image specifications. */
4431 static struct image_keyword xbm_format[XBM_LAST] =
4433 {":type", IMAGE_SYMBOL_VALUE, 1},
4434 {":file", IMAGE_STRING_VALUE, 0},
4435 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
4436 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
4437 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4438 {":foreground", IMAGE_STRING_VALUE, 0},
4439 {":background", IMAGE_STRING_VALUE, 0},
4440 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
4441 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
4442 {":relief", IMAGE_INTEGER_VALUE, 0},
4443 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4444 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
4447 /* Structure describing the image type XBM. */
4449 static struct image_type xbm_type =
4451 &Qxbm,
4452 xbm_image_p,
4453 xbm_load,
4454 x_clear_image,
4455 NULL
4458 /* Tokens returned from xbm_scan. */
4460 enum xbm_token
4462 XBM_TK_IDENT = 256,
4463 XBM_TK_NUMBER
4467 /* Return non-zero if OBJECT is a valid XBM-type image specification.
4468 A valid specification is a list starting with the symbol `image'
4469 The rest of the list is a property list which must contain an
4470 entry `:type xbm..
4472 If the specification specifies a file to load, it must contain
4473 an entry `:file FILENAME' where FILENAME is a string.
4475 If the specification is for a bitmap loaded from memory it must
4476 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
4477 WIDTH and HEIGHT are integers > 0. DATA may be:
4479 1. a string large enough to hold the bitmap data, i.e. it must
4480 have a size >= (WIDTH + 7) / 8 * HEIGHT
4482 2. a bool-vector of size >= WIDTH * HEIGHT
4484 3. a vector of strings or bool-vectors, one for each line of the
4485 bitmap.
4487 Both the file and data forms may contain the additional entries
4488 `:background COLOR' and `:foreground COLOR'. If not present,
4489 foreground and background of the frame on which the image is
4490 displayed, is used. */
4492 static int
4493 xbm_image_p (object)
4494 Lisp_Object object;
4496 struct image_keyword kw[XBM_LAST];
4498 bcopy (xbm_format, kw, sizeof kw);
4499 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
4500 return 0;
4502 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
4504 if (kw[XBM_FILE].count)
4506 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
4507 return 0;
4509 else
4511 Lisp_Object data;
4512 int width, height;
4514 /* Entries for `:width', `:height' and `:data' must be present. */
4515 if (!kw[XBM_WIDTH].count
4516 || !kw[XBM_HEIGHT].count
4517 || !kw[XBM_DATA].count)
4518 return 0;
4520 data = kw[XBM_DATA].value;
4521 width = XFASTINT (kw[XBM_WIDTH].value);
4522 height = XFASTINT (kw[XBM_HEIGHT].value);
4524 /* Check type of data, and width and height against contents of
4525 data. */
4526 if (VECTORP (data))
4528 int i;
4530 /* Number of elements of the vector must be >= height. */
4531 if (XVECTOR (data)->size < height)
4532 return 0;
4534 /* Each string or bool-vector in data must be large enough
4535 for one line of the image. */
4536 for (i = 0; i < height; ++i)
4538 Lisp_Object elt = XVECTOR (data)->contents[i];
4540 if (STRINGP (elt))
4542 if (SCHARS (elt)
4543 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
4544 return 0;
4546 else if (BOOL_VECTOR_P (elt))
4548 if (XBOOL_VECTOR (elt)->size < width)
4549 return 0;
4551 else
4552 return 0;
4555 else if (STRINGP (data))
4557 if (SCHARS (data)
4558 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
4559 return 0;
4561 else if (BOOL_VECTOR_P (data))
4563 if (XBOOL_VECTOR (data)->size < width * height)
4564 return 0;
4566 else
4567 return 0;
4570 /* Baseline must be a value between 0 and 100 (a percentage). */
4571 if (kw[XBM_ASCENT].count
4572 && XFASTINT (kw[XBM_ASCENT].value) > 100)
4573 return 0;
4575 return 1;
4579 /* Scan a bitmap file. FP is the stream to read from. Value is
4580 either an enumerator from enum xbm_token, or a character for a
4581 single-character token, or 0 at end of file. If scanning an
4582 identifier, store the lexeme of the identifier in SVAL. If
4583 scanning a number, store its value in *IVAL. */
4585 static int
4586 xbm_scan (fp, sval, ival)
4587 FILE *fp;
4588 char *sval;
4589 int *ival;
4591 int c;
4593 /* Skip white space. */
4594 while ((c = fgetc (fp)) != EOF && isspace (c))
4597 if (c == EOF)
4598 c = 0;
4599 else if (isdigit (c))
4601 int value = 0, digit;
4603 if (c == '0')
4605 c = fgetc (fp);
4606 if (c == 'x' || c == 'X')
4608 while ((c = fgetc (fp)) != EOF)
4610 if (isdigit (c))
4611 digit = c - '0';
4612 else if (c >= 'a' && c <= 'f')
4613 digit = c - 'a' + 10;
4614 else if (c >= 'A' && c <= 'F')
4615 digit = c - 'A' + 10;
4616 else
4617 break;
4618 value = 16 * value + digit;
4621 else if (isdigit (c))
4623 value = c - '0';
4624 while ((c = fgetc (fp)) != EOF
4625 && isdigit (c))
4626 value = 8 * value + c - '0';
4629 else
4631 value = c - '0';
4632 while ((c = fgetc (fp)) != EOF
4633 && isdigit (c))
4634 value = 10 * value + c - '0';
4637 if (c != EOF)
4638 ungetc (c, fp);
4639 *ival = value;
4640 c = XBM_TK_NUMBER;
4642 else if (isalpha (c) || c == '_')
4644 *sval++ = c;
4645 while ((c = fgetc (fp)) != EOF
4646 && (isalnum (c) || c == '_'))
4647 *sval++ = c;
4648 *sval = 0;
4649 if (c != EOF)
4650 ungetc (c, fp);
4651 c = XBM_TK_IDENT;
4654 return c;
4658 /* Replacement for XReadBitmapFileData which isn't available under old
4659 X versions. FILE is the name of the bitmap file to read. Set
4660 *WIDTH and *HEIGHT to the width and height of the image. Return in
4661 *DATA the bitmap data allocated with xmalloc. Value is non-zero if
4662 successful. */
4664 static int
4665 xbm_read_bitmap_file_data (file, width, height, data)
4666 char *file;
4667 int *width, *height;
4668 unsigned char **data;
4670 FILE *fp;
4671 char buffer[BUFSIZ];
4672 int padding_p = 0;
4673 int v10 = 0;
4674 int bytes_per_line, i, nbytes;
4675 unsigned char *p;
4676 int value;
4677 int LA1;
4679 #define match() \
4680 LA1 = xbm_scan (fp, buffer, &value)
4682 #define expect(TOKEN) \
4683 if (LA1 != (TOKEN)) \
4684 goto failure; \
4685 else \
4686 match ()
4688 #define expect_ident(IDENT) \
4689 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
4690 match (); \
4691 else \
4692 goto failure
4694 fp = fopen (file, "r");
4695 if (fp == NULL)
4696 return 0;
4698 *width = *height = -1;
4699 *data = NULL;
4700 LA1 = xbm_scan (fp, buffer, &value);
4702 /* Parse defines for width, height and hot-spots. */
4703 while (LA1 == '#')
4705 match ();
4706 expect_ident ("define");
4707 expect (XBM_TK_IDENT);
4709 if (LA1 == XBM_TK_NUMBER);
4711 char *p = strrchr (buffer, '_');
4712 p = p ? p + 1 : buffer;
4713 if (strcmp (p, "width") == 0)
4714 *width = value;
4715 else if (strcmp (p, "height") == 0)
4716 *height = value;
4718 expect (XBM_TK_NUMBER);
4721 if (*width < 0 || *height < 0)
4722 goto failure;
4724 /* Parse bits. Must start with `static'. */
4725 expect_ident ("static");
4726 if (LA1 == XBM_TK_IDENT)
4728 if (strcmp (buffer, "unsigned") == 0)
4730 match ();
4731 expect_ident ("char");
4733 else if (strcmp (buffer, "short") == 0)
4735 match ();
4736 v10 = 1;
4737 if (*width % 16 && *width % 16 < 9)
4738 padding_p = 1;
4740 else if (strcmp (buffer, "char") == 0)
4741 match ();
4742 else
4743 goto failure;
4745 else
4746 goto failure;
4748 expect (XBM_TK_IDENT);
4749 expect ('[');
4750 expect (']');
4751 expect ('=');
4752 expect ('{');
4754 bytes_per_line = (*width + 7) / 8 + padding_p;
4755 nbytes = bytes_per_line * *height;
4756 p = *data = (char *) xmalloc (nbytes);
4758 if (v10)
4761 for (i = 0; i < nbytes; i += 2)
4763 int val = value;
4764 expect (XBM_TK_NUMBER);
4766 *p++ = val;
4767 if (!padding_p || ((i + 2) % bytes_per_line))
4768 *p++ = value >> 8;
4770 if (LA1 == ',' || LA1 == '}')
4771 match ();
4772 else
4773 goto failure;
4776 else
4778 for (i = 0; i < nbytes; ++i)
4780 int val = value;
4781 expect (XBM_TK_NUMBER);
4783 *p++ = val;
4785 if (LA1 == ',' || LA1 == '}')
4786 match ();
4787 else
4788 goto failure;
4792 fclose (fp);
4793 return 1;
4795 failure:
4797 fclose (fp);
4798 if (*data)
4800 xfree (*data);
4801 *data = NULL;
4803 return 0;
4805 #undef match
4806 #undef expect
4807 #undef expect_ident
4811 /* Load XBM image IMG which will be displayed on frame F from file
4812 SPECIFIED_FILE. Value is non-zero if successful. */
4814 static int
4815 xbm_load_image_from_file (f, img, specified_file)
4816 struct frame *f;
4817 struct image *img;
4818 Lisp_Object specified_file;
4820 int rc;
4821 unsigned char *data;
4822 int success_p = 0;
4823 Lisp_Object file;
4824 struct gcpro gcpro1;
4826 xassert (STRINGP (specified_file));
4827 file = Qnil;
4828 GCPRO1 (file);
4830 file = x_find_image_file (specified_file);
4831 if (!STRINGP (file))
4833 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4834 UNGCPRO;
4835 return 0;
4838 rc = xbm_read_bitmap_file_data (SDATA (file), &img->width,
4839 &img->height, &data);
4840 if (rc)
4842 int depth = one_mac_display_info.n_cbits;
4843 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
4844 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
4845 Lisp_Object value;
4847 xassert (img->width > 0 && img->height > 0);
4849 /* Get foreground and background colors, maybe allocate colors. */
4850 value = image_spec_value (img->spec, QCforeground, NULL);
4851 if (!NILP (value))
4852 foreground = x_alloc_image_color (f, img, value, foreground);
4854 value = image_spec_value (img->spec, QCbackground, NULL);
4855 if (!NILP (value))
4856 background = x_alloc_image_color (f, img, value, background);
4858 #if 0 /* MAC_TODO : Port image display to Mac */
4859 BLOCK_INPUT;
4860 img->pixmap
4861 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
4862 FRAME_W32_WINDOW (f),
4863 data,
4864 img->width, img->height,
4865 foreground, background,
4866 depth);
4867 xfree (data);
4869 if (img->pixmap == 0)
4871 x_clear_image (f, img);
4872 image_error ("Unable to create X pixmap for `%s'", file, Qnil);
4874 else
4875 success_p = 1;
4877 UNBLOCK_INPUT;
4878 #endif /* MAC_TODO */
4880 else
4881 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
4883 UNGCPRO;
4884 return success_p;
4888 /* Fill image IMG which is used on frame F with pixmap data. Value is
4889 non-zero if successful. */
4891 static int
4892 xbm_load (f, img)
4893 struct frame *f;
4894 struct image *img;
4896 int success_p = 0;
4897 Lisp_Object file_name;
4899 xassert (xbm_image_p (img->spec));
4901 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4902 file_name = image_spec_value (img->spec, QCfile, NULL);
4903 if (STRINGP (file_name))
4904 success_p = xbm_load_image_from_file (f, img, file_name);
4905 else
4907 struct image_keyword fmt[XBM_LAST];
4908 Lisp_Object data;
4909 int depth;
4910 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
4911 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
4912 char *bits;
4913 int parsed_p;
4915 /* Parse the list specification. */
4916 bcopy (xbm_format, fmt, sizeof fmt);
4917 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
4918 xassert (parsed_p);
4920 /* Get specified width, and height. */
4921 img->width = XFASTINT (fmt[XBM_WIDTH].value);
4922 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
4923 xassert (img->width > 0 && img->height > 0);
4925 BLOCK_INPUT;
4927 if (fmt[XBM_ASCENT].count)
4928 img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
4930 /* Get foreground and background colors, maybe allocate colors. */
4931 if (fmt[XBM_FOREGROUND].count)
4932 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
4933 foreground);
4934 if (fmt[XBM_BACKGROUND].count)
4935 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
4936 background);
4938 /* Set bits to the bitmap image data. */
4939 data = fmt[XBM_DATA].value;
4940 if (VECTORP (data))
4942 int i;
4943 char *p;
4944 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
4946 p = bits = (char *) alloca (nbytes * img->height);
4947 for (i = 0; i < img->height; ++i, p += nbytes)
4949 Lisp_Object line = XVECTOR (data)->contents[i];
4950 if (STRINGP (line))
4951 bcopy (SDATA (line), p, nbytes);
4952 else
4953 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
4956 else if (STRINGP (data))
4957 bits = SDATA (data);
4958 else
4959 bits = XBOOL_VECTOR (data)->data;
4961 #if 0 /* MAC_TODO : port Mac display code */
4962 /* Create the pixmap. */
4963 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
4964 img->pixmap
4965 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
4966 FRAME_W32_WINDOW (f),
4967 bits,
4968 img->width, img->height,
4969 foreground, background,
4970 depth);
4971 #endif /* MAC_TODO */
4973 if (img->pixmap)
4974 success_p = 1;
4975 else
4977 image_error ("Unable to create pixmap for XBM image `%s'",
4978 img->spec, Qnil);
4979 x_clear_image (f, img);
4982 UNBLOCK_INPUT;
4985 return success_p;
4990 /***********************************************************************
4991 XPM images
4992 ***********************************************************************/
4994 #if HAVE_XPM
4996 static int xpm_image_p P_ ((Lisp_Object object));
4997 static int xpm_load P_ ((struct frame *f, struct image *img));
4998 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
5000 #include "X11/xpm.h"
5002 /* The symbol `xpm' identifying XPM-format images. */
5004 Lisp_Object Qxpm;
5006 /* Indices of image specification fields in xpm_format, below. */
5008 enum xpm_keyword_index
5010 XPM_TYPE,
5011 XPM_FILE,
5012 XPM_DATA,
5013 XPM_ASCENT,
5014 XPM_MARGIN,
5015 XPM_RELIEF,
5016 XPM_ALGORITHM,
5017 XPM_HEURISTIC_MASK,
5018 XPM_COLOR_SYMBOLS,
5019 XPM_LAST
5022 /* Vector of image_keyword structures describing the format
5023 of valid XPM image specifications. */
5025 static struct image_keyword xpm_format[XPM_LAST] =
5027 {":type", IMAGE_SYMBOL_VALUE, 1},
5028 {":file", IMAGE_STRING_VALUE, 0},
5029 {":data", IMAGE_STRING_VALUE, 0},
5030 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
5031 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5032 {":relief", IMAGE_INTEGER_VALUE, 0},
5033 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5034 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5035 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5038 /* Structure describing the image type XBM. */
5040 static struct image_type xpm_type =
5042 &Qxpm,
5043 xpm_image_p,
5044 xpm_load,
5045 x_clear_image,
5046 NULL
5050 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
5051 for XPM images. Such a list must consist of conses whose car and
5052 cdr are strings. */
5054 static int
5055 xpm_valid_color_symbols_p (color_symbols)
5056 Lisp_Object color_symbols;
5058 while (CONSP (color_symbols))
5060 Lisp_Object sym = XCAR (color_symbols);
5061 if (!CONSP (sym)
5062 || !STRINGP (XCAR (sym))
5063 || !STRINGP (XCDR (sym)))
5064 break;
5065 color_symbols = XCDR (color_symbols);
5068 return NILP (color_symbols);
5072 /* Value is non-zero if OBJECT is a valid XPM image specification. */
5074 static int
5075 xpm_image_p (object)
5076 Lisp_Object object;
5078 struct image_keyword fmt[XPM_LAST];
5079 bcopy (xpm_format, fmt, sizeof fmt);
5080 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
5081 /* Either `:file' or `:data' must be present. */
5082 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
5083 /* Either no `:color-symbols' or it's a list of conses
5084 whose car and cdr are strings. */
5085 && (fmt[XPM_COLOR_SYMBOLS].count == 0
5086 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
5087 && (fmt[XPM_ASCENT].count == 0
5088 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
5092 /* Load image IMG which will be displayed on frame F. Value is
5093 non-zero if successful. */
5095 static int
5096 xpm_load (f, img)
5097 struct frame *f;
5098 struct image *img;
5100 int rc, i;
5101 XpmAttributes attrs;
5102 Lisp_Object specified_file, color_symbols;
5104 /* Configure the XPM lib. Use the visual of frame F. Allocate
5105 close colors. Return colors allocated. */
5106 bzero (&attrs, sizeof attrs);
5107 attrs.visual = FRAME_X_VISUAL (f);
5108 attrs.colormap = FRAME_X_COLORMAP (f);
5109 attrs.valuemask |= XpmVisual;
5110 attrs.valuemask |= XpmColormap;
5111 attrs.valuemask |= XpmReturnAllocPixels;
5112 #ifdef XpmAllocCloseColors
5113 attrs.alloc_close_colors = 1;
5114 attrs.valuemask |= XpmAllocCloseColors;
5115 #else
5116 attrs.closeness = 600;
5117 attrs.valuemask |= XpmCloseness;
5118 #endif
5120 /* If image specification contains symbolic color definitions, add
5121 these to `attrs'. */
5122 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
5123 if (CONSP (color_symbols))
5125 Lisp_Object tail;
5126 XpmColorSymbol *xpm_syms;
5127 int i, size;
5129 attrs.valuemask |= XpmColorSymbols;
5131 /* Count number of symbols. */
5132 attrs.numsymbols = 0;
5133 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
5134 ++attrs.numsymbols;
5136 /* Allocate an XpmColorSymbol array. */
5137 size = attrs.numsymbols * sizeof *xpm_syms;
5138 xpm_syms = (XpmColorSymbol *) alloca (size);
5139 bzero (xpm_syms, size);
5140 attrs.colorsymbols = xpm_syms;
5142 /* Fill the color symbol array. */
5143 for (tail = color_symbols, i = 0;
5144 CONSP (tail);
5145 ++i, tail = XCDR (tail))
5147 Lisp_Object name = XCAR (XCAR (tail));
5148 Lisp_Object color = XCDR (XCAR (tail));
5149 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
5150 strcpy (xpm_syms[i].name, SDATA (name));
5151 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
5152 strcpy (xpm_syms[i].value, SDATA (color));
5156 /* Create a pixmap for the image, either from a file, or from a
5157 string buffer containing data in the same format as an XPM file. */
5158 BLOCK_INPUT;
5159 specified_file = image_spec_value (img->spec, QCfile, NULL);
5160 if (STRINGP (specified_file))
5162 Lisp_Object file = x_find_image_file (specified_file);
5163 if (!STRINGP (file))
5165 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5166 UNBLOCK_INPUT;
5167 return 0;
5170 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
5171 SDATA (file), &img->pixmap, &img->mask,
5172 &attrs);
5174 else
5176 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
5177 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
5178 SDATA (buffer),
5179 &img->pixmap, &img->mask,
5180 &attrs);
5182 UNBLOCK_INPUT;
5184 if (rc == XpmSuccess)
5186 /* Remember allocated colors. */
5187 img->ncolors = attrs.nalloc_pixels;
5188 img->colors = (unsigned long *) xmalloc (img->ncolors
5189 * sizeof *img->colors);
5190 for (i = 0; i < attrs.nalloc_pixels; ++i)
5191 img->colors[i] = attrs.alloc_pixels[i];
5193 img->width = attrs.width;
5194 img->height = attrs.height;
5195 xassert (img->width > 0 && img->height > 0);
5197 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
5198 BLOCK_INPUT;
5199 XpmFreeAttributes (&attrs);
5200 UNBLOCK_INPUT;
5202 else
5204 switch (rc)
5206 case XpmOpenFailed:
5207 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
5208 break;
5210 case XpmFileInvalid:
5211 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
5212 break;
5214 case XpmNoMemory:
5215 image_error ("Out of memory (%s)", img->spec, Qnil);
5216 break;
5218 case XpmColorFailed:
5219 image_error ("Color allocation error (%s)", img->spec, Qnil);
5220 break;
5222 default:
5223 image_error ("Unknown error (%s)", img->spec, Qnil);
5224 break;
5228 return rc == XpmSuccess;
5231 #endif /* HAVE_XPM != 0 */
5234 #if 0 /* MAC_TODO : Color tables on Mac. */
5235 /***********************************************************************
5236 Color table
5237 ***********************************************************************/
5239 /* An entry in the color table mapping an RGB color to a pixel color. */
5241 struct ct_color
5243 int r, g, b;
5244 unsigned long pixel;
5246 /* Next in color table collision list. */
5247 struct ct_color *next;
5250 /* The bucket vector size to use. Must be prime. */
5252 #define CT_SIZE 101
5254 /* Value is a hash of the RGB color given by R, G, and B. */
5256 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5258 /* The color hash table. */
5260 struct ct_color **ct_table;
5262 /* Number of entries in the color table. */
5264 int ct_colors_allocated;
5266 /* Function prototypes. */
5268 static void init_color_table P_ ((void));
5269 static void free_color_table P_ ((void));
5270 static unsigned long *colors_in_color_table P_ ((int *n));
5271 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
5272 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
5275 /* Initialize the color table. */
5277 static void
5278 init_color_table ()
5280 int size = CT_SIZE * sizeof (*ct_table);
5281 ct_table = (struct ct_color **) xmalloc (size);
5282 bzero (ct_table, size);
5283 ct_colors_allocated = 0;
5287 /* Free memory associated with the color table. */
5289 static void
5290 free_color_table ()
5292 int i;
5293 struct ct_color *p, *next;
5295 for (i = 0; i < CT_SIZE; ++i)
5296 for (p = ct_table[i]; p; p = next)
5298 next = p->next;
5299 xfree (p);
5302 xfree (ct_table);
5303 ct_table = NULL;
5307 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5308 entry for that color already is in the color table, return the
5309 pixel color of that entry. Otherwise, allocate a new color for R,
5310 G, B, and make an entry in the color table. */
5312 static unsigned long
5313 lookup_rgb_color (f, r, g, b)
5314 struct frame *f;
5315 int r, g, b;
5317 unsigned hash = CT_HASH_RGB (r, g, b);
5318 int i = hash % CT_SIZE;
5319 struct ct_color *p;
5321 for (p = ct_table[i]; p; p = p->next)
5322 if (p->r == r && p->g == g && p->b == b)
5323 break;
5325 if (p == NULL)
5327 COLORREF color;
5328 Colormap cmap;
5329 int rc;
5331 color = RGB_TO_ULONG (r, g, b);
5333 ++ct_colors_allocated;
5335 p = (struct ct_color *) xmalloc (sizeof *p);
5336 p->r = r;
5337 p->g = g;
5338 p->b = b;
5339 p->pixel = color;
5340 p->next = ct_table[i];
5341 ct_table[i] = p;
5344 return p->pixel;
5348 /* Look up pixel color PIXEL which is used on frame F in the color
5349 table. If not already present, allocate it. Value is PIXEL. */
5351 static unsigned long
5352 lookup_pixel_color (f, pixel)
5353 struct frame *f;
5354 unsigned long pixel;
5356 int i = pixel % CT_SIZE;
5357 struct ct_color *p;
5359 for (p = ct_table[i]; p; p = p->next)
5360 if (p->pixel == pixel)
5361 break;
5363 if (p == NULL)
5365 XColor color;
5366 Colormap cmap;
5367 int rc;
5369 BLOCK_INPUT;
5371 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5372 color.pixel = pixel;
5373 XQueryColor (NULL, cmap, &color);
5374 rc = x_alloc_nearest_color (f, cmap, &color);
5375 UNBLOCK_INPUT;
5377 if (rc)
5379 ++ct_colors_allocated;
5381 p = (struct ct_color *) xmalloc (sizeof *p);
5382 p->r = color.red;
5383 p->g = color.green;
5384 p->b = color.blue;
5385 p->pixel = pixel;
5386 p->next = ct_table[i];
5387 ct_table[i] = p;
5389 else
5390 return FRAME_FOREGROUND_PIXEL (f);
5392 return p->pixel;
5396 /* Value is a vector of all pixel colors contained in the color table,
5397 allocated via xmalloc. Set *N to the number of colors. */
5399 static unsigned long *
5400 colors_in_color_table (n)
5401 int *n;
5403 int i, j;
5404 struct ct_color *p;
5405 unsigned long *colors;
5407 if (ct_colors_allocated == 0)
5409 *n = 0;
5410 colors = NULL;
5412 else
5414 colors = (unsigned long *) xmalloc (ct_colors_allocated
5415 * sizeof *colors);
5416 *n = ct_colors_allocated;
5418 for (i = j = 0; i < CT_SIZE; ++i)
5419 for (p = ct_table[i]; p; p = p->next)
5420 colors[j++] = p->pixel;
5423 return colors;
5426 #endif /* MAC_TODO */
5429 /***********************************************************************
5430 Algorithms
5431 ***********************************************************************/
5433 #if 0 /* MAC_TODO : Mac versions of low level algorithms */
5434 static void x_laplace_write_row P_ ((struct frame *, long *,
5435 int, XImage *, int));
5436 static void x_laplace_read_row P_ ((struct frame *, Colormap,
5437 XColor *, int, XImage *, int));
5440 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the
5441 frame we operate on, CMAP is the color-map in effect, and WIDTH is
5442 the width of one row in the image. */
5444 static void
5445 x_laplace_read_row (f, cmap, colors, width, ximg, y)
5446 struct frame *f;
5447 Colormap cmap;
5448 XColor *colors;
5449 int width;
5450 XImage *ximg;
5451 int y;
5453 int x;
5455 for (x = 0; x < width; ++x)
5456 colors[x].pixel = XGetPixel (ximg, x, y);
5458 XQueryColors (NULL, cmap, colors, width);
5462 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
5463 containing the pixel colors to write. F is the frame we are
5464 working on. */
5466 static void
5467 x_laplace_write_row (f, pixels, width, ximg, y)
5468 struct frame *f;
5469 long *pixels;
5470 int width;
5471 XImage *ximg;
5472 int y;
5474 int x;
5476 for (x = 0; x < width; ++x)
5477 XPutPixel (ximg, x, y, pixels[x]);
5479 #endif /* MAC_TODO */
5481 /* Transform image IMG which is used on frame F with a Laplace
5482 edge-detection algorithm. The result is an image that can be used
5483 to draw disabled buttons, for example. */
5485 static void
5486 x_laplace (f, img)
5487 struct frame *f;
5488 struct image *img;
5490 #if 0 /* MAC_TODO : Mac version */
5491 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5492 XImage *ximg, *oimg;
5493 XColor *in[3];
5494 long *out;
5495 Pixmap pixmap;
5496 int x, y, i;
5497 long pixel;
5498 int in_y, out_y, rc;
5499 int mv2 = 45000;
5501 BLOCK_INPUT;
5503 /* Get the X image IMG->pixmap. */
5504 ximg = XGetImage (NULL, img->pixmap,
5505 0, 0, img->width, img->height, ~0, ZPixmap);
5507 /* Allocate 3 input rows, and one output row of colors. */
5508 for (i = 0; i < 3; ++i)
5509 in[i] = (XColor *) alloca (img->width * sizeof (XColor));
5510 out = (long *) alloca (img->width * sizeof (long));
5512 /* Create an X image for output. */
5513 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5514 &oimg, &pixmap);
5516 /* Fill first two rows. */
5517 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
5518 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
5519 in_y = 2;
5521 /* Write first row, all zeros. */
5522 init_color_table ();
5523 pixel = lookup_rgb_color (f, 0, 0, 0);
5524 for (x = 0; x < img->width; ++x)
5525 out[x] = pixel;
5526 x_laplace_write_row (f, out, img->width, oimg, 0);
5527 out_y = 1;
5529 for (y = 2; y < img->height; ++y)
5531 int rowa = y % 3;
5532 int rowb = (y + 2) % 3;
5534 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
5536 for (x = 0; x < img->width - 2; ++x)
5538 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
5539 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
5540 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
5542 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
5543 b & 0xffff);
5546 x_laplace_write_row (f, out, img->width, oimg, out_y++);
5549 /* Write last line, all zeros. */
5550 for (x = 0; x < img->width; ++x)
5551 out[x] = pixel;
5552 x_laplace_write_row (f, out, img->width, oimg, out_y);
5554 /* Free the input image, and free resources of IMG. */
5555 XDestroyImage (ximg);
5556 x_clear_image (f, img);
5558 /* Put the output image into pixmap, and destroy it. */
5559 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5560 x_destroy_x_image (oimg);
5562 /* Remember new pixmap and colors in IMG. */
5563 img->pixmap = pixmap;
5564 img->colors = colors_in_color_table (&img->ncolors);
5565 free_color_table ();
5567 UNBLOCK_INPUT;
5568 #endif /* MAC_TODO */
5572 /* Build a mask for image IMG which is used on frame F. FILE is the
5573 name of an image file, for error messages. HOW determines how to
5574 determine the background color of IMG. If it is a list '(R G B)',
5575 with R, G, and B being integers >= 0, take that as the color of the
5576 background. Otherwise, determine the background color of IMG
5577 heuristically. Value is non-zero if successful. */
5579 static int
5580 x_build_heuristic_mask (f, img, how)
5581 struct frame *f;
5582 struct image *img;
5583 Lisp_Object how;
5585 #if 0 /* MAC_TODO : Mac version */
5586 Display *dpy = FRAME_W32_DISPLAY (f);
5587 XImage *ximg, *mask_img;
5588 int x, y, rc, look_at_corners_p;
5589 unsigned long bg;
5591 BLOCK_INPUT;
5593 /* Create an image and pixmap serving as mask. */
5594 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5595 &mask_img, &img->mask);
5596 if (!rc)
5598 UNBLOCK_INPUT;
5599 return 0;
5602 /* Get the X image of IMG->pixmap. */
5603 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
5604 ~0, ZPixmap);
5606 /* Determine the background color of ximg. If HOW is `(R G B)'
5607 take that as color. Otherwise, try to determine the color
5608 heuristically. */
5609 look_at_corners_p = 1;
5611 if (CONSP (how))
5613 int rgb[3], i = 0;
5615 while (i < 3
5616 && CONSP (how)
5617 && NATNUMP (XCAR (how)))
5619 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5620 how = XCDR (how);
5623 if (i == 3 && NILP (how))
5625 char color_name[30];
5626 XColor exact, color;
5627 Colormap cmap;
5629 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5631 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5632 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
5634 bg = color.pixel;
5635 look_at_corners_p = 0;
5640 if (look_at_corners_p)
5642 unsigned long corners[4];
5643 int i, best_count;
5645 /* Get the colors at the corners of ximg. */
5646 corners[0] = XGetPixel (ximg, 0, 0);
5647 corners[1] = XGetPixel (ximg, img->width - 1, 0);
5648 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
5649 corners[3] = XGetPixel (ximg, 0, img->height - 1);
5651 /* Choose the most frequently found color as background. */
5652 for (i = best_count = 0; i < 4; ++i)
5654 int j, n;
5656 for (j = n = 0; j < 4; ++j)
5657 if (corners[i] == corners[j])
5658 ++n;
5660 if (n > best_count)
5661 bg = corners[i], best_count = n;
5665 /* Set all bits in mask_img to 1 whose color in ximg is different
5666 from the background color bg. */
5667 for (y = 0; y < img->height; ++y)
5668 for (x = 0; x < img->width; ++x)
5669 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
5671 /* Put mask_img into img->mask. */
5672 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5673 x_destroy_x_image (mask_img);
5674 XDestroyImage (ximg);
5676 UNBLOCK_INPUT;
5677 #endif /* MAC_TODO */
5679 return 1;
5684 /***********************************************************************
5685 PBM (mono, gray, color)
5686 ***********************************************************************/
5687 #ifdef HAVE_PBM
5689 static int pbm_image_p P_ ((Lisp_Object object));
5690 static int pbm_load P_ ((struct frame *f, struct image *img));
5691 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5693 /* The symbol `pbm' identifying images of this type. */
5695 Lisp_Object Qpbm;
5697 /* Indices of image specification fields in gs_format, below. */
5699 enum pbm_keyword_index
5701 PBM_TYPE,
5702 PBM_FILE,
5703 PBM_DATA,
5704 PBM_ASCENT,
5705 PBM_MARGIN,
5706 PBM_RELIEF,
5707 PBM_ALGORITHM,
5708 PBM_HEURISTIC_MASK,
5709 PBM_LAST
5712 /* Vector of image_keyword structures describing the format
5713 of valid user-defined image specifications. */
5715 static struct image_keyword pbm_format[PBM_LAST] =
5717 {":type", IMAGE_SYMBOL_VALUE, 1},
5718 {":file", IMAGE_STRING_VALUE, 0},
5719 {":data", IMAGE_STRING_VALUE, 0},
5720 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
5721 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5722 {":relief", IMAGE_INTEGER_VALUE, 0},
5723 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5724 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
5727 /* Structure describing the image type `pbm'. */
5729 static struct image_type pbm_type =
5731 &Qpbm,
5732 pbm_image_p,
5733 pbm_load,
5734 x_clear_image,
5735 NULL
5739 /* Return non-zero if OBJECT is a valid PBM image specification. */
5741 static int
5742 pbm_image_p (object)
5743 Lisp_Object object;
5745 struct image_keyword fmt[PBM_LAST];
5747 bcopy (pbm_format, fmt, sizeof fmt);
5749 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
5750 || (fmt[PBM_ASCENT].count
5751 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
5752 return 0;
5754 /* Must specify either :data or :file. */
5755 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5759 /* Scan a decimal number from *S and return it. Advance *S while
5760 reading the number. END is the end of the string. Value is -1 at
5761 end of input. */
5763 static int
5764 pbm_scan_number (s, end)
5765 unsigned char **s, *end;
5767 int c, val = -1;
5769 while (*s < end)
5771 /* Skip white-space. */
5772 while (*s < end && (c = *(*s)++, isspace (c)))
5775 if (c == '#')
5777 /* Skip comment to end of line. */
5778 while (*s < end && (c = *(*s)++, c != '\n'))
5781 else if (isdigit (c))
5783 /* Read decimal number. */
5784 val = c - '0';
5785 while (*s < end && (c = *(*s)++, isdigit (c)))
5786 val = 10 * val + c - '0';
5787 break;
5789 else
5790 break;
5793 return val;
5797 /* Read FILE into memory. Value is a pointer to a buffer allocated
5798 with xmalloc holding FILE's contents. Value is null if an error
5799 occurred. *SIZE is set to the size of the file. */
5801 static char *
5802 pbm_read_file (file, size)
5803 Lisp_Object file;
5804 int *size;
5806 FILE *fp = NULL;
5807 char *buf = NULL;
5808 struct stat st;
5810 if (stat (SDATA (file), &st) == 0
5811 && (fp = fopen (SDATA (file), "r")) != NULL
5812 && (buf = (char *) xmalloc (st.st_size),
5813 fread (buf, 1, st.st_size, fp) == st.st_size))
5815 *size = st.st_size;
5816 fclose (fp);
5818 else
5820 if (fp)
5821 fclose (fp);
5822 if (buf)
5824 xfree (buf);
5825 buf = NULL;
5829 return buf;
5833 /* Load PBM image IMG for use on frame F. */
5835 static int
5836 pbm_load (f, img)
5837 struct frame *f;
5838 struct image *img;
5840 int raw_p, x, y;
5841 int width, height, max_color_idx = 0;
5842 XImage *ximg;
5843 Lisp_Object file, specified_file;
5844 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5845 struct gcpro gcpro1;
5846 unsigned char *contents = NULL;
5847 unsigned char *end, *p;
5848 int size;
5850 specified_file = image_spec_value (img->spec, QCfile, NULL);
5851 file = Qnil;
5852 GCPRO1 (file);
5854 if (STRINGP (specified_file))
5856 file = x_find_image_file (specified_file);
5857 if (!STRINGP (file))
5859 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5860 UNGCPRO;
5861 return 0;
5864 contents = pbm_read_file (file, &size);
5865 if (contents == NULL)
5867 image_error ("Error reading `%s'", file, Qnil);
5868 UNGCPRO;
5869 return 0;
5872 p = contents;
5873 end = contents + size;
5875 else
5877 Lisp_Object data;
5878 data = image_spec_value (img->spec, QCdata, NULL);
5879 p = SDATA (data);
5880 end = p + SBYTES (data);
5883 /* Check magic number. */
5884 if (end - p < 2 || *p++ != 'P')
5886 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5887 error:
5888 xfree (contents);
5889 UNGCPRO;
5890 return 0;
5893 switch (*p++)
5895 case '1':
5896 raw_p = 0, type = PBM_MONO;
5897 break;
5899 case '2':
5900 raw_p = 0, type = PBM_GRAY;
5901 break;
5903 case '3':
5904 raw_p = 0, type = PBM_COLOR;
5905 break;
5907 case '4':
5908 raw_p = 1, type = PBM_MONO;
5909 break;
5911 case '5':
5912 raw_p = 1, type = PBM_GRAY;
5913 break;
5915 case '6':
5916 raw_p = 1, type = PBM_COLOR;
5917 break;
5919 default:
5920 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5921 goto error;
5924 /* Read width, height, maximum color-component. Characters
5925 starting with `#' up to the end of a line are ignored. */
5926 width = pbm_scan_number (&p, end);
5927 height = pbm_scan_number (&p, end);
5929 if (type != PBM_MONO)
5931 max_color_idx = pbm_scan_number (&p, end);
5932 if (raw_p && max_color_idx > 255)
5933 max_color_idx = 255;
5936 if (width < 0
5937 || height < 0
5938 || (type != PBM_MONO && max_color_idx < 0))
5939 goto error;
5941 BLOCK_INPUT;
5942 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5943 &ximg, &img->pixmap))
5945 UNBLOCK_INPUT;
5946 goto error;
5949 /* Initialize the color hash table. */
5950 init_color_table ();
5952 if (type == PBM_MONO)
5954 int c = 0, g;
5956 for (y = 0; y < height; ++y)
5957 for (x = 0; x < width; ++x)
5959 if (raw_p)
5961 if ((x & 7) == 0)
5962 c = *p++;
5963 g = c & 0x80;
5964 c <<= 1;
5966 else
5967 g = pbm_scan_number (&p, end);
5969 XPutPixel (ximg, x, y, (g
5970 ? FRAME_FOREGROUND_PIXEL (f)
5971 : FRAME_BACKGROUND_PIXEL (f)));
5974 else
5976 for (y = 0; y < height; ++y)
5977 for (x = 0; x < width; ++x)
5979 int r, g, b;
5981 if (type == PBM_GRAY)
5982 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
5983 else if (raw_p)
5985 r = *p++;
5986 g = *p++;
5987 b = *p++;
5989 else
5991 r = pbm_scan_number (&p, end);
5992 g = pbm_scan_number (&p, end);
5993 b = pbm_scan_number (&p, end);
5996 if (r < 0 || g < 0 || b < 0)
5998 xfree (ximg->data);
5999 ximg->data = NULL;
6000 XDestroyImage (ximg);
6001 UNBLOCK_INPUT;
6002 image_error ("Invalid pixel value in image `%s'",
6003 img->spec, Qnil);
6004 goto error;
6007 /* RGB values are now in the range 0..max_color_idx.
6008 Scale this to the range 0..0xffff supported by X. */
6009 r = (double) r * 65535 / max_color_idx;
6010 g = (double) g * 65535 / max_color_idx;
6011 b = (double) b * 65535 / max_color_idx;
6012 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6016 /* Store in IMG->colors the colors allocated for the image, and
6017 free the color table. */
6018 img->colors = colors_in_color_table (&img->ncolors);
6019 free_color_table ();
6021 /* Put the image into a pixmap. */
6022 x_put_x_image (f, ximg, img->pixmap, width, height);
6023 x_destroy_x_image (ximg);
6024 UNBLOCK_INPUT;
6026 img->width = width;
6027 img->height = height;
6029 UNGCPRO;
6030 xfree (contents);
6031 return 1;
6033 #endif /* HAVE_PBM */
6036 /***********************************************************************
6038 ***********************************************************************/
6040 #if HAVE_PNG
6042 #include <png.h>
6044 /* Function prototypes. */
6046 static int png_image_p P_ ((Lisp_Object object));
6047 static int png_load P_ ((struct frame *f, struct image *img));
6049 /* The symbol `png' identifying images of this type. */
6051 Lisp_Object Qpng;
6053 /* Indices of image specification fields in png_format, below. */
6055 enum png_keyword_index
6057 PNG_TYPE,
6058 PNG_DATA,
6059 PNG_FILE,
6060 PNG_ASCENT,
6061 PNG_MARGIN,
6062 PNG_RELIEF,
6063 PNG_ALGORITHM,
6064 PNG_HEURISTIC_MASK,
6065 PNG_LAST
6068 /* Vector of image_keyword structures describing the format
6069 of valid user-defined image specifications. */
6071 static struct image_keyword png_format[PNG_LAST] =
6073 {":type", IMAGE_SYMBOL_VALUE, 1},
6074 {":data", IMAGE_STRING_VALUE, 0},
6075 {":file", IMAGE_STRING_VALUE, 0},
6076 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6077 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6078 {":relief", IMAGE_INTEGER_VALUE, 0},
6079 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6080 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6083 /* Structure describing the image type `png'. */
6085 static struct image_type png_type =
6087 &Qpng,
6088 png_image_p,
6089 png_load,
6090 x_clear_image,
6091 NULL
6095 /* Return non-zero if OBJECT is a valid PNG image specification. */
6097 static int
6098 png_image_p (object)
6099 Lisp_Object object;
6101 struct image_keyword fmt[PNG_LAST];
6102 bcopy (png_format, fmt, sizeof fmt);
6104 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
6105 || (fmt[PNG_ASCENT].count
6106 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
6107 return 0;
6109 /* Must specify either the :data or :file keyword. */
6110 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6114 /* Error and warning handlers installed when the PNG library
6115 is initialized. */
6117 static void
6118 my_png_error (png_ptr, msg)
6119 png_struct *png_ptr;
6120 char *msg;
6122 xassert (png_ptr != NULL);
6123 image_error ("PNG error: %s", build_string (msg), Qnil);
6124 longjmp (png_ptr->jmpbuf, 1);
6128 static void
6129 my_png_warning (png_ptr, msg)
6130 png_struct *png_ptr;
6131 char *msg;
6133 xassert (png_ptr != NULL);
6134 image_error ("PNG warning: %s", build_string (msg), Qnil);
6137 /* Memory source for PNG decoding. */
6139 struct png_memory_storage
6141 unsigned char *bytes; /* The data */
6142 size_t len; /* How big is it? */
6143 int index; /* Where are we? */
6147 /* Function set as reader function when reading PNG image from memory.
6148 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6149 bytes from the input to DATA. */
6151 static void
6152 png_read_from_memory (png_ptr, data, length)
6153 png_structp png_ptr;
6154 png_bytep data;
6155 png_size_t length;
6157 struct png_memory_storage *tbr
6158 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
6160 if (length > tbr->len - tbr->index)
6161 png_error (png_ptr, "Read error");
6163 bcopy (tbr->bytes + tbr->index, data, length);
6164 tbr->index = tbr->index + length;
6167 /* Load PNG image IMG for use on frame F. Value is non-zero if
6168 successful. */
6170 static int
6171 png_load (f, img)
6172 struct frame *f;
6173 struct image *img;
6175 Lisp_Object file, specified_file;
6176 Lisp_Object specified_data;
6177 int x, y, i;
6178 XImage *ximg, *mask_img = NULL;
6179 struct gcpro gcpro1;
6180 png_struct *png_ptr = NULL;
6181 png_info *info_ptr = NULL, *end_info = NULL;
6182 FILE *fp = NULL;
6183 png_byte sig[8];
6184 png_byte *pixels = NULL;
6185 png_byte **rows = NULL;
6186 png_uint_32 width, height;
6187 int bit_depth, color_type, interlace_type;
6188 png_byte channels;
6189 png_uint_32 row_bytes;
6190 int transparent_p;
6191 char *gamma_str;
6192 double screen_gamma, image_gamma;
6193 int intent;
6194 struct png_memory_storage tbr; /* Data to be read */
6196 /* Find out what file to load. */
6197 specified_file = image_spec_value (img->spec, QCfile, NULL);
6198 specified_data = image_spec_value (img->spec, QCdata, NULL);
6199 file = Qnil;
6200 GCPRO1 (file);
6202 if (NILP (specified_data))
6204 file = x_find_image_file (specified_file);
6205 if (!STRINGP (file))
6207 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6208 UNGCPRO;
6209 return 0;
6212 /* Open the image file. */
6213 fp = fopen (SDATA (file), "rb");
6214 if (!fp)
6216 image_error ("Cannot open image file `%s'", file, Qnil);
6217 UNGCPRO;
6218 fclose (fp);
6219 return 0;
6222 /* Check PNG signature. */
6223 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6224 || !png_check_sig (sig, sizeof sig))
6226 image_error ("Not a PNG file:` %s'", file, Qnil);
6227 UNGCPRO;
6228 fclose (fp);
6229 return 0;
6232 else
6234 /* Read from memory. */
6235 tbr.bytes = SDATA (specified_data);
6236 tbr.len = SBYTES (specified_data);
6237 tbr.index = 0;
6239 /* Check PNG signature. */
6240 if (tbr.len < sizeof sig
6241 || !png_check_sig (tbr.bytes, sizeof sig))
6243 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6244 UNGCPRO;
6245 return 0;
6248 /* Need to skip past the signature. */
6249 tbr.bytes += sizeof (sig);
6252 /* Initialize read and info structs for PNG lib. */
6253 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
6254 my_png_error, my_png_warning);
6255 if (!png_ptr)
6257 if (fp) fclose (fp);
6258 UNGCPRO;
6259 return 0;
6262 info_ptr = png_create_info_struct (png_ptr);
6263 if (!info_ptr)
6265 png_destroy_read_struct (&png_ptr, NULL, NULL);
6266 if (fp) fclose (fp);
6267 UNGCPRO;
6268 return 0;
6271 end_info = png_create_info_struct (png_ptr);
6272 if (!end_info)
6274 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6275 if (fp) fclose (fp);
6276 UNGCPRO;
6277 return 0;
6280 /* Set error jump-back. We come back here when the PNG library
6281 detects an error. */
6282 if (setjmp (png_ptr->jmpbuf))
6284 error:
6285 if (png_ptr)
6286 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6287 xfree (pixels);
6288 xfree (rows);
6289 if (fp) fclose (fp);
6290 UNGCPRO;
6291 return 0;
6294 /* Read image info. */
6295 if (!NILP (specified_data))
6296 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6297 else
6298 png_init_io (png_ptr, fp);
6300 png_set_sig_bytes (png_ptr, sizeof sig);
6301 png_read_info (png_ptr, info_ptr);
6302 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6303 &interlace_type, NULL, NULL);
6305 /* If image contains simply transparency data, we prefer to
6306 construct a clipping mask. */
6307 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6308 transparent_p = 1;
6309 else
6310 transparent_p = 0;
6312 /* This function is easier to write if we only have to handle
6313 one data format: RGB or RGBA with 8 bits per channel. Let's
6314 transform other formats into that format. */
6316 /* Strip more than 8 bits per channel. */
6317 if (bit_depth == 16)
6318 png_set_strip_16 (png_ptr);
6320 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6321 if available. */
6322 png_set_expand (png_ptr);
6324 /* Convert grayscale images to RGB. */
6325 if (color_type == PNG_COLOR_TYPE_GRAY
6326 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6327 png_set_gray_to_rgb (png_ptr);
6329 /* The value 2.2 is a guess for PC monitors from PNG example.c. */
6330 gamma_str = getenv ("SCREEN_GAMMA");
6331 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
6333 /* Tell the PNG lib to handle gamma correction for us. */
6335 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6336 if (png_get_sRGB (png_ptr, info_ptr, &intent))
6337 /* There is a special chunk in the image specifying the gamma. */
6338 png_set_sRGB (png_ptr, info_ptr, intent);
6339 else
6340 #endif
6341 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
6342 /* Image contains gamma information. */
6343 png_set_gamma (png_ptr, screen_gamma, image_gamma);
6344 else
6345 /* Use a default of 0.5 for the image gamma. */
6346 png_set_gamma (png_ptr, screen_gamma, 0.5);
6348 /* Handle alpha channel by combining the image with a background
6349 color. Do this only if a real alpha channel is supplied. For
6350 simple transparency, we prefer a clipping mask. */
6351 if (!transparent_p)
6353 png_color_16 *image_background;
6355 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
6356 /* Image contains a background color with which to
6357 combine the image. */
6358 png_set_background (png_ptr, image_background,
6359 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6360 else
6362 /* Image does not contain a background color with which
6363 to combine the image data via an alpha channel. Use
6364 the frame's background instead. */
6365 XColor color;
6366 Colormap cmap;
6367 png_color_16 frame_background;
6369 BLOCK_INPUT;
6370 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
6371 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6372 XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
6373 UNBLOCK_INPUT;
6375 bzero (&frame_background, sizeof frame_background);
6376 frame_background.red = color.red;
6377 frame_background.green = color.green;
6378 frame_background.blue = color.blue;
6380 png_set_background (png_ptr, &frame_background,
6381 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6385 /* Update info structure. */
6386 png_read_update_info (png_ptr, info_ptr);
6388 /* Get number of channels. Valid values are 1 for grayscale images
6389 and images with a palette, 2 for grayscale images with transparency
6390 information (alpha channel), 3 for RGB images, and 4 for RGB
6391 images with alpha channel, i.e. RGBA. If conversions above were
6392 sufficient we should only have 3 or 4 channels here. */
6393 channels = png_get_channels (png_ptr, info_ptr);
6394 xassert (channels == 3 || channels == 4);
6396 /* Number of bytes needed for one row of the image. */
6397 row_bytes = png_get_rowbytes (png_ptr, info_ptr);
6399 /* Allocate memory for the image. */
6400 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6401 rows = (png_byte **) xmalloc (height * sizeof *rows);
6402 for (i = 0; i < height; ++i)
6403 rows[i] = pixels + i * row_bytes;
6405 /* Read the entire image. */
6406 png_read_image (png_ptr, rows);
6407 png_read_end (png_ptr, info_ptr);
6408 if (fp)
6410 fclose (fp);
6411 fp = NULL;
6414 BLOCK_INPUT;
6416 /* Create the X image and pixmap. */
6417 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6418 &img->pixmap))
6420 UNBLOCK_INPUT;
6421 goto error;
6424 /* Create an image and pixmap serving as mask if the PNG image
6425 contains an alpha channel. */
6426 if (channels == 4
6427 && !transparent_p
6428 && !x_create_x_image_and_pixmap (f, width, height, 1,
6429 &mask_img, &img->mask))
6431 x_destroy_x_image (ximg);
6432 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
6433 img->pixmap = 0;
6434 UNBLOCK_INPUT;
6435 goto error;
6438 /* Fill the X image and mask from PNG data. */
6439 init_color_table ();
6441 for (y = 0; y < height; ++y)
6443 png_byte *p = rows[y];
6445 for (x = 0; x < width; ++x)
6447 unsigned r, g, b;
6449 r = *p++ << 8;
6450 g = *p++ << 8;
6451 b = *p++ << 8;
6452 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6454 /* An alpha channel, aka mask channel, associates variable
6455 transparency with an image. Where other image formats
6456 support binary transparency---fully transparent or fully
6457 opaque---PNG allows up to 254 levels of partial transparency.
6458 The PNG library implements partial transparency by combining
6459 the image with a specified background color.
6461 I'm not sure how to handle this here nicely: because the
6462 background on which the image is displayed may change, for
6463 real alpha channel support, it would be necessary to create
6464 a new image for each possible background.
6466 What I'm doing now is that a mask is created if we have
6467 boolean transparency information. Otherwise I'm using
6468 the frame's background color to combine the image with. */
6470 if (channels == 4)
6472 if (mask_img)
6473 XPutPixel (mask_img, x, y, *p > 0);
6474 ++p;
6479 /* Remember colors allocated for this image. */
6480 img->colors = colors_in_color_table (&img->ncolors);
6481 free_color_table ();
6483 /* Clean up. */
6484 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6485 xfree (rows);
6486 xfree (pixels);
6488 img->width = width;
6489 img->height = height;
6491 /* Put the image into the pixmap, then free the X image and its buffer. */
6492 x_put_x_image (f, ximg, img->pixmap, width, height);
6493 x_destroy_x_image (ximg);
6495 /* Same for the mask. */
6496 if (mask_img)
6498 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6499 x_destroy_x_image (mask_img);
6502 UNBLOCK_INPUT;
6503 UNGCPRO;
6504 return 1;
6507 #endif /* HAVE_PNG != 0 */
6511 /***********************************************************************
6512 JPEG
6513 ***********************************************************************/
6515 #if HAVE_JPEG
6517 /* Work around a warning about HAVE_STDLIB_H being redefined in
6518 jconfig.h. */
6519 #ifdef HAVE_STDLIB_H
6520 #define HAVE_STDLIB_H_1
6521 #undef HAVE_STDLIB_H
6522 #endif /* HAVE_STLIB_H */
6524 #include <jpeglib.h>
6525 #include <jerror.h>
6526 #include <setjmp.h>
6528 #ifdef HAVE_STLIB_H_1
6529 #define HAVE_STDLIB_H 1
6530 #endif
6532 static int jpeg_image_p P_ ((Lisp_Object object));
6533 static int jpeg_load P_ ((struct frame *f, struct image *img));
6535 /* The symbol `jpeg' identifying images of this type. */
6537 Lisp_Object Qjpeg;
6539 /* Indices of image specification fields in gs_format, below. */
6541 enum jpeg_keyword_index
6543 JPEG_TYPE,
6544 JPEG_DATA,
6545 JPEG_FILE,
6546 JPEG_ASCENT,
6547 JPEG_MARGIN,
6548 JPEG_RELIEF,
6549 JPEG_ALGORITHM,
6550 JPEG_HEURISTIC_MASK,
6551 JPEG_LAST
6554 /* Vector of image_keyword structures describing the format
6555 of valid user-defined image specifications. */
6557 static struct image_keyword jpeg_format[JPEG_LAST] =
6559 {":type", IMAGE_SYMBOL_VALUE, 1},
6560 {":data", IMAGE_STRING_VALUE, 0},
6561 {":file", IMAGE_STRING_VALUE, 0},
6562 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6563 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6564 {":relief", IMAGE_INTEGER_VALUE, 0},
6565 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6566 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6569 /* Structure describing the image type `jpeg'. */
6571 static struct image_type jpeg_type =
6573 &Qjpeg,
6574 jpeg_image_p,
6575 jpeg_load,
6576 x_clear_image,
6577 NULL
6581 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6583 static int
6584 jpeg_image_p (object)
6585 Lisp_Object object;
6587 struct image_keyword fmt[JPEG_LAST];
6589 bcopy (jpeg_format, fmt, sizeof fmt);
6591 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
6592 || (fmt[JPEG_ASCENT].count
6593 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
6594 return 0;
6596 /* Must specify either the :data or :file keyword. */
6597 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6601 struct my_jpeg_error_mgr
6603 struct jpeg_error_mgr pub;
6604 jmp_buf setjmp_buffer;
6607 static void
6608 my_error_exit (cinfo)
6609 j_common_ptr cinfo;
6611 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6612 longjmp (mgr->setjmp_buffer, 1);
6615 /* Init source method for JPEG data source manager. Called by
6616 jpeg_read_header() before any data is actually read. See
6617 libjpeg.doc from the JPEG lib distribution. */
6619 static void
6620 our_init_source (cinfo)
6621 j_decompress_ptr cinfo;
6626 /* Fill input buffer method for JPEG data source manager. Called
6627 whenever more data is needed. We read the whole image in one step,
6628 so this only adds a fake end of input marker at the end. */
6630 static boolean
6631 our_fill_input_buffer (cinfo)
6632 j_decompress_ptr cinfo;
6634 /* Insert a fake EOI marker. */
6635 struct jpeg_source_mgr *src = cinfo->src;
6636 static JOCTET buffer[2];
6638 buffer[0] = (JOCTET) 0xFF;
6639 buffer[1] = (JOCTET) JPEG_EOI;
6641 src->next_input_byte = buffer;
6642 src->bytes_in_buffer = 2;
6643 return TRUE;
6647 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6648 is the JPEG data source manager. */
6650 static void
6651 our_skip_input_data (cinfo, num_bytes)
6652 j_decompress_ptr cinfo;
6653 long num_bytes;
6655 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6657 if (src)
6659 if (num_bytes > src->bytes_in_buffer)
6660 ERREXIT (cinfo, JERR_INPUT_EOF);
6662 src->bytes_in_buffer -= num_bytes;
6663 src->next_input_byte += num_bytes;
6668 /* Method to terminate data source. Called by
6669 jpeg_finish_decompress() after all data has been processed. */
6671 static void
6672 our_term_source (cinfo)
6673 j_decompress_ptr cinfo;
6678 /* Set up the JPEG lib for reading an image from DATA which contains
6679 LEN bytes. CINFO is the decompression info structure created for
6680 reading the image. */
6682 static void
6683 jpeg_memory_src (cinfo, data, len)
6684 j_decompress_ptr cinfo;
6685 JOCTET *data;
6686 unsigned int len;
6688 struct jpeg_source_mgr *src;
6690 if (cinfo->src == NULL)
6692 /* First time for this JPEG object? */
6693 cinfo->src = (struct jpeg_source_mgr *)
6694 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6695 sizeof (struct jpeg_source_mgr));
6696 src = (struct jpeg_source_mgr *) cinfo->src;
6697 src->next_input_byte = data;
6700 src = (struct jpeg_source_mgr *) cinfo->src;
6701 src->init_source = our_init_source;
6702 src->fill_input_buffer = our_fill_input_buffer;
6703 src->skip_input_data = our_skip_input_data;
6704 src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
6705 src->term_source = our_term_source;
6706 src->bytes_in_buffer = len;
6707 src->next_input_byte = data;
6711 /* Load image IMG for use on frame F. Patterned after example.c
6712 from the JPEG lib. */
6714 static int
6715 jpeg_load (f, img)
6716 struct frame *f;
6717 struct image *img;
6719 struct jpeg_decompress_struct cinfo;
6720 struct my_jpeg_error_mgr mgr;
6721 Lisp_Object file, specified_file;
6722 Lisp_Object specified_data;
6723 FILE *fp = NULL;
6724 JSAMPARRAY buffer;
6725 int row_stride, x, y;
6726 XImage *ximg = NULL;
6727 int rc;
6728 unsigned long *colors;
6729 int width, height;
6730 struct gcpro gcpro1;
6732 /* Open the JPEG file. */
6733 specified_file = image_spec_value (img->spec, QCfile, NULL);
6734 specified_data = image_spec_value (img->spec, QCdata, NULL);
6735 file = Qnil;
6736 GCPRO1 (file);
6738 if (NILP (specified_data))
6740 file = x_find_image_file (specified_file);
6741 if (!STRINGP (file))
6743 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6744 UNGCPRO;
6745 return 0;
6748 fp = fopen (SDATA (file), "r");
6749 if (fp == NULL)
6751 image_error ("Cannot open `%s'", file, Qnil);
6752 UNGCPRO;
6753 return 0;
6757 /* Customize libjpeg's error handling to call my_error_exit when an
6758 error is detected. This function will perform a longjmp. */
6759 mgr.pub.error_exit = my_error_exit;
6760 cinfo.err = jpeg_std_error (&mgr.pub);
6762 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6764 if (rc == 1)
6766 /* Called from my_error_exit. Display a JPEG error. */
6767 char buffer[JMSG_LENGTH_MAX];
6768 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
6769 image_error ("Error reading JPEG image `%s': %s", img->spec,
6770 build_string (buffer));
6773 /* Close the input file and destroy the JPEG object. */
6774 if (fp)
6775 fclose (fp);
6776 jpeg_destroy_decompress (&cinfo);
6778 BLOCK_INPUT;
6780 /* If we already have an XImage, free that. */
6781 x_destroy_x_image (ximg);
6783 /* Free pixmap and colors. */
6784 x_clear_image (f, img);
6786 UNBLOCK_INPUT;
6787 UNGCPRO;
6788 return 0;
6791 /* Create the JPEG decompression object. Let it read from fp.
6792 Read the JPEG image header. */
6793 jpeg_create_decompress (&cinfo);
6795 if (NILP (specified_data))
6796 jpeg_stdio_src (&cinfo, fp);
6797 else
6798 jpeg_memory_src (&cinfo, SDATA (specified_data),
6799 SBYTES (specified_data));
6801 jpeg_read_header (&cinfo, TRUE);
6803 /* Customize decompression so that color quantization will be used.
6804 Start decompression. */
6805 cinfo.quantize_colors = TRUE;
6806 jpeg_start_decompress (&cinfo);
6807 width = img->width = cinfo.output_width;
6808 height = img->height = cinfo.output_height;
6810 BLOCK_INPUT;
6812 /* Create X image and pixmap. */
6813 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6814 &img->pixmap))
6816 UNBLOCK_INPUT;
6817 longjmp (mgr.setjmp_buffer, 2);
6820 /* Allocate colors. When color quantization is used,
6821 cinfo.actual_number_of_colors has been set with the number of
6822 colors generated, and cinfo.colormap is a two-dimensional array
6823 of color indices in the range 0..cinfo.actual_number_of_colors.
6824 No more than 255 colors will be generated. */
6826 int i, ir, ig, ib;
6828 if (cinfo.out_color_components > 2)
6829 ir = 0, ig = 1, ib = 2;
6830 else if (cinfo.out_color_components > 1)
6831 ir = 0, ig = 1, ib = 0;
6832 else
6833 ir = 0, ig = 0, ib = 0;
6835 /* Use the color table mechanism because it handles colors that
6836 cannot be allocated nicely. Such colors will be replaced with
6837 a default color, and we don't have to care about which colors
6838 can be freed safely, and which can't. */
6839 init_color_table ();
6840 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6841 * sizeof *colors);
6843 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6845 /* Multiply RGB values with 255 because X expects RGB values
6846 in the range 0..0xffff. */
6847 int r = cinfo.colormap[ir][i] << 8;
6848 int g = cinfo.colormap[ig][i] << 8;
6849 int b = cinfo.colormap[ib][i] << 8;
6850 colors[i] = lookup_rgb_color (f, r, g, b);
6853 /* Remember those colors actually allocated. */
6854 img->colors = colors_in_color_table (&img->ncolors);
6855 free_color_table ();
6858 /* Read pixels. */
6859 row_stride = width * cinfo.output_components;
6860 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6861 row_stride, 1);
6862 for (y = 0; y < height; ++y)
6864 jpeg_read_scanlines (&cinfo, buffer, 1);
6865 for (x = 0; x < cinfo.output_width; ++x)
6866 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6869 /* Clean up. */
6870 jpeg_finish_decompress (&cinfo);
6871 jpeg_destroy_decompress (&cinfo);
6872 if (fp)
6873 fclose (fp);
6875 /* Put the image into the pixmap. */
6876 x_put_x_image (f, ximg, img->pixmap, width, height);
6877 x_destroy_x_image (ximg);
6878 UNBLOCK_INPUT;
6879 UNGCPRO;
6880 return 1;
6883 #endif /* HAVE_JPEG */
6887 /***********************************************************************
6888 TIFF
6889 ***********************************************************************/
6891 #if HAVE_TIFF
6893 #include <tiffio.h>
6895 static int tiff_image_p P_ ((Lisp_Object object));
6896 static int tiff_load P_ ((struct frame *f, struct image *img));
6898 /* The symbol `tiff' identifying images of this type. */
6900 Lisp_Object Qtiff;
6902 /* Indices of image specification fields in tiff_format, below. */
6904 enum tiff_keyword_index
6906 TIFF_TYPE,
6907 TIFF_DATA,
6908 TIFF_FILE,
6909 TIFF_ASCENT,
6910 TIFF_MARGIN,
6911 TIFF_RELIEF,
6912 TIFF_ALGORITHM,
6913 TIFF_HEURISTIC_MASK,
6914 TIFF_LAST
6917 /* Vector of image_keyword structures describing the format
6918 of valid user-defined image specifications. */
6920 static struct image_keyword tiff_format[TIFF_LAST] =
6922 {":type", IMAGE_SYMBOL_VALUE, 1},
6923 {":data", IMAGE_STRING_VALUE, 0},
6924 {":file", IMAGE_STRING_VALUE, 0},
6925 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6926 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6927 {":relief", IMAGE_INTEGER_VALUE, 0},
6928 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6929 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
6932 /* Structure describing the image type `tiff'. */
6934 static struct image_type tiff_type =
6936 &Qtiff,
6937 tiff_image_p,
6938 tiff_load,
6939 x_clear_image,
6940 NULL
6944 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6946 static int
6947 tiff_image_p (object)
6948 Lisp_Object object;
6950 struct image_keyword fmt[TIFF_LAST];
6951 bcopy (tiff_format, fmt, sizeof fmt);
6953 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
6954 || (fmt[TIFF_ASCENT].count
6955 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
6956 return 0;
6958 /* Must specify either the :data or :file keyword. */
6959 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6963 /* Reading from a memory buffer for TIFF images Based on the PNG
6964 memory source, but we have to provide a lot of extra functions.
6965 Blah.
6967 We really only need to implement read and seek, but I am not
6968 convinced that the TIFF library is smart enough not to destroy
6969 itself if we only hand it the function pointers we need to
6970 override. */
6972 typedef struct
6974 unsigned char *bytes;
6975 size_t len;
6976 int index;
6978 tiff_memory_source;
6980 static size_t
6981 tiff_read_from_memory (data, buf, size)
6982 thandle_t data;
6983 tdata_t buf;
6984 tsize_t size;
6986 tiff_memory_source *src = (tiff_memory_source *) data;
6988 if (size > src->len - src->index)
6989 return (size_t) -1;
6990 bcopy (src->bytes + src->index, buf, size);
6991 src->index += size;
6992 return size;
6995 static size_t
6996 tiff_write_from_memory (data, buf, size)
6997 thandle_t data;
6998 tdata_t buf;
6999 tsize_t size;
7001 return (size_t) -1;
7004 static toff_t
7005 tiff_seek_in_memory (data, off, whence)
7006 thandle_t data;
7007 toff_t off;
7008 int whence;
7010 tiff_memory_source *src = (tiff_memory_source *) data;
7011 int idx;
7013 switch (whence)
7015 case SEEK_SET: /* Go from beginning of source. */
7016 idx = off;
7017 break;
7019 case SEEK_END: /* Go from end of source. */
7020 idx = src->len + off;
7021 break;
7023 case SEEK_CUR: /* Go from current position. */
7024 idx = src->index + off;
7025 break;
7027 default: /* Invalid `whence'. */
7028 return -1;
7031 if (idx > src->len || idx < 0)
7032 return -1;
7034 src->index = idx;
7035 return src->index;
7038 static int
7039 tiff_close_memory (data)
7040 thandle_t data;
7042 /* NOOP */
7043 return 0;
7046 static int
7047 tiff_mmap_memory (data, pbase, psize)
7048 thandle_t data;
7049 tdata_t *pbase;
7050 toff_t *psize;
7052 /* It is already _IN_ memory. */
7053 return 0;
7056 static void
7057 tiff_unmap_memory (data, base, size)
7058 thandle_t data;
7059 tdata_t base;
7060 toff_t size;
7062 /* We don't need to do this. */
7065 static toff_t
7066 tiff_size_of_memory (data)
7067 thandle_t data;
7069 return ((tiff_memory_source *) data)->len;
7072 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7073 successful. */
7075 static int
7076 tiff_load (f, img)
7077 struct frame *f;
7078 struct image *img;
7080 Lisp_Object file, specified_file;
7081 Lisp_Object specified_data;
7082 TIFF *tiff;
7083 int width, height, x, y;
7084 uint32 *buf;
7085 int rc;
7086 XImage *ximg;
7087 struct gcpro gcpro1;
7088 tiff_memory_source memsrc;
7090 specified_file = image_spec_value (img->spec, QCfile, NULL);
7091 specified_data = image_spec_value (img->spec, QCdata, NULL);
7092 file = Qnil;
7093 GCPRO1 (file);
7095 if (NILP (specified_data))
7097 /* Read from a file */
7098 file = x_find_image_file (specified_file);
7099 if (!STRINGP (file))
7101 image_error ("Cannot find image file `%s'", file, Qnil);
7102 UNGCPRO;
7103 return 0;
7106 /* Try to open the image file. */
7107 tiff = TIFFOpen (SDATA (file), "r");
7108 if (tiff == NULL)
7110 image_error ("Cannot open `%s'", file, Qnil);
7111 UNGCPRO;
7112 return 0;
7115 else
7117 /* Memory source! */
7118 memsrc.bytes = SDATA (specified_data);
7119 memsrc.len = SBYTES (specified_data);
7120 memsrc.index = 0;
7122 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
7123 (TIFFReadWriteProc) tiff_read_from_memory,
7124 (TIFFReadWriteProc) tiff_write_from_memory,
7125 tiff_seek_in_memory,
7126 tiff_close_memory,
7127 tiff_size_of_memory,
7128 tiff_mmap_memory,
7129 tiff_unmap_memory);
7131 if (!tiff)
7133 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7134 UNGCPRO;
7135 return 0;
7139 /* Get width and height of the image, and allocate a raster buffer
7140 of width x height 32-bit values. */
7141 TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7142 TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7143 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7145 rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
7146 TIFFClose (tiff);
7147 if (!rc)
7149 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7150 xfree (buf);
7151 UNGCPRO;
7152 return 0;
7155 BLOCK_INPUT;
7157 /* Create the X image and pixmap. */
7158 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7160 UNBLOCK_INPUT;
7161 xfree (buf);
7162 UNGCPRO;
7163 return 0;
7166 /* Initialize the color table. */
7167 init_color_table ();
7169 /* Process the pixel raster. Origin is in the lower-left corner. */
7170 for (y = 0; y < height; ++y)
7172 uint32 *row = buf + y * width;
7174 for (x = 0; x < width; ++x)
7176 uint32 abgr = row[x];
7177 int r = TIFFGetR (abgr) << 8;
7178 int g = TIFFGetG (abgr) << 8;
7179 int b = TIFFGetB (abgr) << 8;
7180 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7184 /* Remember the colors allocated for the image. Free the color table. */
7185 img->colors = colors_in_color_table (&img->ncolors);
7186 free_color_table ();
7188 /* Put the image into the pixmap, then free the X image and its buffer. */
7189 x_put_x_image (f, ximg, img->pixmap, width, height);
7190 x_destroy_x_image (ximg);
7191 xfree (buf);
7192 UNBLOCK_INPUT;
7194 img->width = width;
7195 img->height = height;
7197 UNGCPRO;
7198 return 1;
7201 #endif /* HAVE_TIFF != 0 */
7205 /***********************************************************************
7207 ***********************************************************************/
7209 #if HAVE_GIF
7211 #include <gif_lib.h>
7213 static int gif_image_p P_ ((Lisp_Object object));
7214 static int gif_load P_ ((struct frame *f, struct image *img));
7216 /* The symbol `gif' identifying images of this type. */
7218 Lisp_Object Qgif;
7220 /* Indices of image specification fields in gif_format, below. */
7222 enum gif_keyword_index
7224 GIF_TYPE,
7225 GIF_DATA,
7226 GIF_FILE,
7227 GIF_ASCENT,
7228 GIF_MARGIN,
7229 GIF_RELIEF,
7230 GIF_ALGORITHM,
7231 GIF_HEURISTIC_MASK,
7232 GIF_IMAGE,
7233 GIF_LAST
7236 /* Vector of image_keyword structures describing the format
7237 of valid user-defined image specifications. */
7239 static struct image_keyword gif_format[GIF_LAST] =
7241 {":type", IMAGE_SYMBOL_VALUE, 1},
7242 {":data", IMAGE_STRING_VALUE, 0},
7243 {":file", IMAGE_STRING_VALUE, 0},
7244 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7245 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7246 {":relief", IMAGE_INTEGER_VALUE, 0},
7247 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7248 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7249 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
7252 /* Structure describing the image type `gif'. */
7254 static struct image_type gif_type =
7256 &Qgif,
7257 gif_image_p,
7258 gif_load,
7259 x_clear_image,
7260 NULL
7263 /* Return non-zero if OBJECT is a valid GIF image specification. */
7265 static int
7266 gif_image_p (object)
7267 Lisp_Object object;
7269 struct image_keyword fmt[GIF_LAST];
7270 bcopy (gif_format, fmt, sizeof fmt);
7272 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
7273 || (fmt[GIF_ASCENT].count
7274 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
7275 return 0;
7277 /* Must specify either the :data or :file keyword. */
7278 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7281 /* Reading a GIF image from memory
7282 Based on the PNG memory stuff to a certain extent. */
7284 typedef struct
7286 unsigned char *bytes;
7287 size_t len;
7288 int index;
7290 gif_memory_source;
7292 /* Make the current memory source available to gif_read_from_memory.
7293 It's done this way because not all versions of libungif support
7294 a UserData field in the GifFileType structure. */
7295 static gif_memory_source *current_gif_memory_src;
7297 static int
7298 gif_read_from_memory (file, buf, len)
7299 GifFileType *file;
7300 GifByteType *buf;
7301 int len;
7303 gif_memory_source *src = current_gif_memory_src;
7305 if (len > src->len - src->index)
7306 return -1;
7308 bcopy (src->bytes + src->index, buf, len);
7309 src->index += len;
7310 return len;
7314 /* Load GIF image IMG for use on frame F. Value is non-zero if
7315 successful. */
7317 static int
7318 gif_load (f, img)
7319 struct frame *f;
7320 struct image *img;
7322 Lisp_Object file, specified_file;
7323 Lisp_Object specified_data;
7324 int rc, width, height, x, y, i;
7325 XImage *ximg;
7326 ColorMapObject *gif_color_map;
7327 unsigned long pixel_colors[256];
7328 GifFileType *gif;
7329 struct gcpro gcpro1;
7330 Lisp_Object image;
7331 int ino, image_left, image_top, image_width, image_height;
7332 gif_memory_source memsrc;
7333 unsigned char *raster;
7335 specified_file = image_spec_value (img->spec, QCfile, NULL);
7336 specified_data = image_spec_value (img->spec, QCdata, NULL);
7337 file = Qnil;
7338 GCPRO1 (file);
7340 if (NILP (specified_data))
7342 file = x_find_image_file (specified_file);
7343 if (!STRINGP (file))
7345 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7346 UNGCPRO;
7347 return 0;
7350 /* Open the GIF file. */
7351 gif = DGifOpenFileName (SDATA (file));
7352 if (gif == NULL)
7354 image_error ("Cannot open `%s'", file, Qnil);
7355 UNGCPRO;
7356 return 0;
7359 else
7361 /* Read from memory! */
7362 current_gif_memory_src = &memsrc;
7363 memsrc.bytes = SDATA (specified_data);
7364 memsrc.len = SBYTES (specified_data);
7365 memsrc.index = 0;
7367 gif = DGifOpen(&memsrc, gif_read_from_memory);
7368 if (!gif)
7370 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7371 UNGCPRO;
7372 return 0;
7376 /* Read entire contents. */
7377 rc = DGifSlurp (gif);
7378 if (rc == GIF_ERROR)
7380 image_error ("Error reading `%s'", img->spec, Qnil);
7381 DGifCloseFile (gif);
7382 UNGCPRO;
7383 return 0;
7386 image = image_spec_value (img->spec, QCindex, NULL);
7387 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7388 if (ino >= gif->ImageCount)
7390 image_error ("Invalid image number `%s' in image `%s'",
7391 image, img->spec);
7392 DGifCloseFile (gif);
7393 UNGCPRO;
7394 return 0;
7397 width = img->width = gif->SWidth;
7398 height = img->height = gif->SHeight;
7400 BLOCK_INPUT;
7402 /* Create the X image and pixmap. */
7403 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7405 UNBLOCK_INPUT;
7406 DGifCloseFile (gif);
7407 UNGCPRO;
7408 return 0;
7411 /* Allocate colors. */
7412 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7413 if (!gif_color_map)
7414 gif_color_map = gif->SColorMap;
7415 init_color_table ();
7416 bzero (pixel_colors, sizeof pixel_colors);
7418 for (i = 0; i < gif_color_map->ColorCount; ++i)
7420 int r = gif_color_map->Colors[i].Red << 8;
7421 int g = gif_color_map->Colors[i].Green << 8;
7422 int b = gif_color_map->Colors[i].Blue << 8;
7423 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7426 img->colors = colors_in_color_table (&img->ncolors);
7427 free_color_table ();
7429 /* Clear the part of the screen image that are not covered by
7430 the image from the GIF file. Full animated GIF support
7431 requires more than can be done here (see the gif89 spec,
7432 disposal methods). Let's simply assume that the part
7433 not covered by a sub-image is in the frame's background color. */
7434 image_top = gif->SavedImages[ino].ImageDesc.Top;
7435 image_left = gif->SavedImages[ino].ImageDesc.Left;
7436 image_width = gif->SavedImages[ino].ImageDesc.Width;
7437 image_height = gif->SavedImages[ino].ImageDesc.Height;
7439 for (y = 0; y < image_top; ++y)
7440 for (x = 0; x < width; ++x)
7441 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7443 for (y = image_top + image_height; y < height; ++y)
7444 for (x = 0; x < width; ++x)
7445 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7447 for (y = image_top; y < image_top + image_height; ++y)
7449 for (x = 0; x < image_left; ++x)
7450 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7451 for (x = image_left + image_width; x < width; ++x)
7452 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7455 /* Read the GIF image into the X image. We use a local variable
7456 `raster' here because RasterBits below is a char *, and invites
7457 problems with bytes >= 0x80. */
7458 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
7460 if (gif->SavedImages[ino].ImageDesc.Interlace)
7462 static int interlace_start[] = {0, 4, 2, 1};
7463 static int interlace_increment[] = {8, 8, 4, 2};
7464 int pass, inc;
7465 int row = interlace_start[0];
7467 pass = 0;
7469 for (y = 0; y < image_height; y++)
7471 if (row >= image_height)
7473 row = interlace_start[++pass];
7474 while (row >= image_height)
7475 row = interlace_start[++pass];
7478 for (x = 0; x < image_width; x++)
7480 int i = raster[(y * image_width) + x];
7481 XPutPixel (ximg, x + image_left, row + image_top,
7482 pixel_colors[i]);
7485 row += interlace_increment[pass];
7488 else
7490 for (y = 0; y < image_height; ++y)
7491 for (x = 0; x < image_width; ++x)
7493 int i = raster[y* image_width + x];
7494 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
7498 DGifCloseFile (gif);
7500 /* Put the image into the pixmap, then free the X image and its buffer. */
7501 x_put_x_image (f, ximg, img->pixmap, width, height);
7502 x_destroy_x_image (ximg);
7503 UNBLOCK_INPUT;
7505 UNGCPRO;
7506 return 1;
7509 #endif /* HAVE_GIF != 0 */
7513 /***********************************************************************
7514 Ghostscript
7515 ***********************************************************************/
7517 #ifdef HAVE_GHOSTSCRIPT
7518 static int gs_image_p P_ ((Lisp_Object object));
7519 static int gs_load P_ ((struct frame *f, struct image *img));
7520 static void gs_clear_image P_ ((struct frame *f, struct image *img));
7522 /* The symbol `postscript' identifying images of this type. */
7524 Lisp_Object Qpostscript;
7526 /* Keyword symbols. */
7528 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
7530 /* Indices of image specification fields in gs_format, below. */
7532 enum gs_keyword_index
7534 GS_TYPE,
7535 GS_PT_WIDTH,
7536 GS_PT_HEIGHT,
7537 GS_FILE,
7538 GS_LOADER,
7539 GS_BOUNDING_BOX,
7540 GS_ASCENT,
7541 GS_MARGIN,
7542 GS_RELIEF,
7543 GS_ALGORITHM,
7544 GS_HEURISTIC_MASK,
7545 GS_LAST
7548 /* Vector of image_keyword structures describing the format
7549 of valid user-defined image specifications. */
7551 static struct image_keyword gs_format[GS_LAST] =
7553 {":type", IMAGE_SYMBOL_VALUE, 1},
7554 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7555 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7556 {":file", IMAGE_STRING_VALUE, 1},
7557 {":loader", IMAGE_FUNCTION_VALUE, 0},
7558 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
7559 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7560 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7561 {":relief", IMAGE_INTEGER_VALUE, 0},
7562 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7563 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7566 /* Structure describing the image type `ghostscript'. */
7568 static struct image_type gs_type =
7570 &Qpostscript,
7571 gs_image_p,
7572 gs_load,
7573 gs_clear_image,
7574 NULL
7578 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7580 static void
7581 gs_clear_image (f, img)
7582 struct frame *f;
7583 struct image *img;
7585 /* IMG->data.ptr_val may contain a recorded colormap. */
7586 xfree (img->data.ptr_val);
7587 x_clear_image (f, img);
7591 /* Return non-zero if OBJECT is a valid Ghostscript image
7592 specification. */
7594 static int
7595 gs_image_p (object)
7596 Lisp_Object object;
7598 struct image_keyword fmt[GS_LAST];
7599 Lisp_Object tem;
7600 int i;
7602 bcopy (gs_format, fmt, sizeof fmt);
7604 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
7605 || (fmt[GS_ASCENT].count
7606 && XFASTINT (fmt[GS_ASCENT].value) > 100))
7607 return 0;
7609 /* Bounding box must be a list or vector containing 4 integers. */
7610 tem = fmt[GS_BOUNDING_BOX].value;
7611 if (CONSP (tem))
7613 for (i = 0; i < 4; ++i, tem = XCDR (tem))
7614 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
7615 return 0;
7616 if (!NILP (tem))
7617 return 0;
7619 else if (VECTORP (tem))
7621 if (XVECTOR (tem)->size != 4)
7622 return 0;
7623 for (i = 0; i < 4; ++i)
7624 if (!INTEGERP (XVECTOR (tem)->contents[i]))
7625 return 0;
7627 else
7628 return 0;
7630 return 1;
7634 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7635 if successful. */
7637 static int
7638 gs_load (f, img)
7639 struct frame *f;
7640 struct image *img;
7642 char buffer[100];
7643 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
7644 struct gcpro gcpro1, gcpro2;
7645 Lisp_Object frame;
7646 double in_width, in_height;
7647 Lisp_Object pixel_colors = Qnil;
7649 /* Compute pixel size of pixmap needed from the given size in the
7650 image specification. Sizes in the specification are in pt. 1 pt
7651 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7652 info. */
7653 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
7654 in_width = XFASTINT (pt_width) / 72.0;
7655 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
7656 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
7657 in_height = XFASTINT (pt_height) / 72.0;
7658 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
7660 /* Create the pixmap. */
7661 BLOCK_INPUT;
7662 xassert (img->pixmap == 0);
7663 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
7664 img->width, img->height,
7665 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
7666 UNBLOCK_INPUT;
7668 if (!img->pixmap)
7670 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
7671 return 0;
7674 /* Call the loader to fill the pixmap. It returns a process object
7675 if successful. We do not record_unwind_protect here because
7676 other places in redisplay like calling window scroll functions
7677 don't either. Let the Lisp loader use `unwind-protect' instead. */
7678 GCPRO2 (window_and_pixmap_id, pixel_colors);
7680 sprintf (buffer, "%lu %lu",
7681 (unsigned long) FRAME_W32_WINDOW (f),
7682 (unsigned long) img->pixmap);
7683 window_and_pixmap_id = build_string (buffer);
7685 sprintf (buffer, "%lu %lu",
7686 FRAME_FOREGROUND_PIXEL (f),
7687 FRAME_BACKGROUND_PIXEL (f));
7688 pixel_colors = build_string (buffer);
7690 XSETFRAME (frame, f);
7691 loader = image_spec_value (img->spec, QCloader, NULL);
7692 if (NILP (loader))
7693 loader = intern ("gs-load-image");
7695 img->data.lisp_val = call6 (loader, frame, img->spec,
7696 make_number (img->width),
7697 make_number (img->height),
7698 window_and_pixmap_id,
7699 pixel_colors);
7700 UNGCPRO;
7701 return PROCESSP (img->data.lisp_val);
7705 /* Kill the Ghostscript process that was started to fill PIXMAP on
7706 frame F. Called from XTread_socket when receiving an event
7707 telling Emacs that Ghostscript has finished drawing. */
7709 void
7710 x_kill_gs_process (pixmap, f)
7711 Pixmap pixmap;
7712 struct frame *f;
7714 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
7715 int class, i;
7716 struct image *img;
7718 /* Find the image containing PIXMAP. */
7719 for (i = 0; i < c->used; ++i)
7720 if (c->images[i]->pixmap == pixmap)
7721 break;
7723 /* Kill the GS process. We should have found PIXMAP in the image
7724 cache and its image should contain a process object. */
7725 xassert (i < c->used);
7726 img = c->images[i];
7727 xassert (PROCESSP (img->data.lisp_val));
7728 Fkill_process (img->data.lisp_val, Qnil);
7729 img->data.lisp_val = Qnil;
7731 /* On displays with a mutable colormap, figure out the colors
7732 allocated for the image by looking at the pixels of an XImage for
7733 img->pixmap. */
7734 class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
7735 if (class != StaticColor && class != StaticGray && class != TrueColor)
7737 XImage *ximg;
7739 BLOCK_INPUT;
7741 /* Try to get an XImage for img->pixmep. */
7742 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
7743 0, 0, img->width, img->height, ~0, ZPixmap);
7744 if (ximg)
7746 int x, y;
7748 /* Initialize the color table. */
7749 init_color_table ();
7751 /* For each pixel of the image, look its color up in the
7752 color table. After having done so, the color table will
7753 contain an entry for each color used by the image. */
7754 for (y = 0; y < img->height; ++y)
7755 for (x = 0; x < img->width; ++x)
7757 unsigned long pixel = XGetPixel (ximg, x, y);
7758 lookup_pixel_color (f, pixel);
7761 /* Record colors in the image. Free color table and XImage. */
7762 img->colors = colors_in_color_table (&img->ncolors);
7763 free_color_table ();
7764 XDestroyImage (ximg);
7766 #if 0 /* This doesn't seem to be the case. If we free the colors
7767 here, we get a BadAccess later in x_clear_image when
7768 freeing the colors. */
7769 /* We have allocated colors once, but Ghostscript has also
7770 allocated colors on behalf of us. So, to get the
7771 reference counts right, free them once. */
7772 if (img->ncolors)
7774 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7775 XFreeColors (FRAME_W32_DISPLAY (f), cmap,
7776 img->colors, img->ncolors, 0);
7778 #endif
7780 else
7781 image_error ("Cannot get X image of `%s'; colors will not be freed",
7782 img->spec, Qnil);
7784 UNBLOCK_INPUT;
7788 #endif /* HAVE_GHOSTSCRIPT */
7791 /***********************************************************************
7792 Window properties
7793 ***********************************************************************/
7795 DEFUN ("x-change-window-property", Fx_change_window_property,
7796 Sx_change_window_property, 2, 3, 0,
7797 doc: /* Change window property PROP to VALUE on the X window of FRAME.
7798 PROP and VALUE must be strings. FRAME nil or omitted means use the
7799 selected frame. Value is VALUE. */)
7800 (prop, value, frame)
7801 Lisp_Object frame, prop, value;
7803 #if 0 /* MAC_TODO : port window properties to Mac */
7804 struct frame *f = check_x_frame (frame);
7805 Atom prop_atom;
7807 CHECK_STRING (prop);
7808 CHECK_STRING (value);
7810 BLOCK_INPUT;
7811 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
7812 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
7813 prop_atom, XA_STRING, 8, PropModeReplace,
7814 SDATA (value), SCHARS (value));
7816 /* Make sure the property is set when we return. */
7817 XFlush (FRAME_W32_DISPLAY (f));
7818 UNBLOCK_INPUT;
7820 #endif /* MAC_TODO */
7822 return value;
7826 DEFUN ("x-delete-window-property", Fx_delete_window_property,
7827 Sx_delete_window_property, 1, 2, 0,
7828 doc: /* Remove window property PROP from X window of FRAME.
7829 FRAME nil or omitted means use the selected frame. Value is PROP. */)
7830 (prop, frame)
7831 Lisp_Object prop, frame;
7833 #if 0 /* MAC_TODO : port window properties to Mac */
7835 struct frame *f = check_x_frame (frame);
7836 Atom prop_atom;
7838 CHECK_STRING (prop);
7839 BLOCK_INPUT;
7840 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
7841 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
7843 /* Make sure the property is removed when we return. */
7844 XFlush (FRAME_W32_DISPLAY (f));
7845 UNBLOCK_INPUT;
7846 #endif /* MAC_TODO */
7848 return prop;
7852 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
7853 1, 2, 0,
7854 doc: /* Value is the value of window property PROP on FRAME.
7855 If FRAME is nil or omitted, use the selected frame. Value is nil
7856 if FRAME hasn't a property with name PROP or if PROP has no string
7857 value. */)
7858 (prop, frame)
7859 Lisp_Object prop, frame;
7861 #if 0 /* MAC_TODO : port window properties to Mac */
7863 struct frame *f = check_x_frame (frame);
7864 Atom prop_atom;
7865 int rc;
7866 Lisp_Object prop_value = Qnil;
7867 char *tmp_data = NULL;
7868 Atom actual_type;
7869 int actual_format;
7870 unsigned long actual_size, bytes_remaining;
7872 CHECK_STRING (prop);
7873 BLOCK_INPUT;
7874 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
7875 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
7876 prop_atom, 0, 0, False, XA_STRING,
7877 &actual_type, &actual_format, &actual_size,
7878 &bytes_remaining, (unsigned char **) &tmp_data);
7879 if (rc == Success)
7881 int size = bytes_remaining;
7883 XFree (tmp_data);
7884 tmp_data = NULL;
7886 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
7887 prop_atom, 0, bytes_remaining,
7888 False, XA_STRING,
7889 &actual_type, &actual_format,
7890 &actual_size, &bytes_remaining,
7891 (unsigned char **) &tmp_data);
7892 if (rc == Success)
7893 prop_value = make_string (tmp_data, size);
7895 XFree (tmp_data);
7898 UNBLOCK_INPUT;
7900 return prop_value;
7902 #endif /* MAC_TODO */
7903 return Qnil;
7908 /***********************************************************************
7909 Hourglass cursor
7910 ***********************************************************************/
7912 /* If non-null, an asynchronous timer that, when it expires, displays
7913 an hourglass cursor on all frames. */
7915 static struct atimer *hourglass_atimer;
7917 /* Non-zero means an hourglass cursor is currently shown. */
7919 static int hourglass_shown_p;
7921 /* Number of seconds to wait before displaying an hourglass cursor. */
7923 static Lisp_Object Vhourglass_delay;
7925 /* Default number of seconds to wait before displaying an hourglass
7926 cursor. */
7928 #define DEFAULT_HOURGLASS_DELAY 1
7930 /* Function prototypes. */
7932 static void show_hourglass P_ ((struct atimer *));
7933 static void hide_hourglass P_ ((void));
7936 /* Cancel a currently active hourglass timer, and start a new one. */
7938 void
7939 start_hourglass ()
7941 #if 0 /* MAC_TODO: cursor shape changes. */
7942 EMACS_TIME delay;
7943 int secs, usecs = 0;
7945 cancel_hourglass ();
7947 if (INTEGERP (Vhourglass_delay)
7948 && XINT (Vhourglass_delay) > 0)
7949 secs = XFASTINT (Vhourglass_delay);
7950 else if (FLOATP (Vhourglass_delay)
7951 && XFLOAT_DATA (Vhourglass_delay) > 0)
7953 Lisp_Object tem;
7954 tem = Ftruncate (Vhourglass_delay, Qnil);
7955 secs = XFASTINT (tem);
7956 usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
7958 else
7959 secs = DEFAULT_HOURGLASS_DELAY;
7961 EMACS_SET_SECS_USECS (delay, secs, usecs);
7962 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
7963 show_hourglass, NULL);
7964 #endif /* MAC_TODO */
7968 /* Cancel the hourglass cursor timer if active, hide an hourglass
7969 cursor if shown. */
7971 void
7972 cancel_hourglass ()
7974 if (hourglass_atimer)
7976 cancel_atimer (hourglass_atimer);
7977 hourglass_atimer = NULL;
7980 if (hourglass_shown_p)
7981 hide_hourglass ();
7985 /* Timer function of hourglass_atimer. TIMER is equal to
7986 hourglass_atimer.
7988 Display an hourglass cursor on all frames by mapping the frames'
7989 hourglass_window. Set the hourglass_p flag in the frames'
7990 output_data.x structure to indicate that an hourglass cursor is
7991 shown on the frames. */
7993 static void
7994 show_hourglass (timer)
7995 struct atimer *timer;
7997 #if 0 /* MAC_TODO: cursor shape changes. */
7998 /* The timer implementation will cancel this timer automatically
7999 after this function has run. Set hourglass_atimer to null
8000 so that we know the timer doesn't have to be canceled. */
8001 hourglass_atimer = NULL;
8003 if (!hourglass_shown_p)
8005 Lisp_Object rest, frame;
8007 BLOCK_INPUT;
8009 FOR_EACH_FRAME (rest, frame)
8010 if (FRAME_W32_P (XFRAME (frame)))
8012 struct frame *f = XFRAME (frame);
8014 f->output_data.w32->hourglass_p = 1;
8016 if (!f->output_data.w32->hourglass_window)
8018 unsigned long mask = CWCursor;
8019 XSetWindowAttributes attrs;
8021 attrs.cursor = f->output_data.w32->hourglass_cursor;
8023 f->output_data.w32->hourglass_window
8024 = XCreateWindow (FRAME_X_DISPLAY (f),
8025 FRAME_OUTER_WINDOW (f),
8026 0, 0, 32000, 32000, 0, 0,
8027 InputOnly,
8028 CopyFromParent,
8029 mask, &attrs);
8032 XMapRaised (FRAME_X_DISPLAY (f),
8033 f->output_data.w32->hourglass_window);
8034 XFlush (FRAME_X_DISPLAY (f));
8037 hourglass_shown_p = 1;
8038 UNBLOCK_INPUT;
8040 #endif /* MAC_TODO */
8044 /* Hide the hourglass cursor on all frames, if it is currently shown. */
8046 static void
8047 hide_hourglass ()
8049 #if 0 /* MAC_TODO: cursor shape changes. */
8050 if (hourglass_shown_p)
8052 Lisp_Object rest, frame;
8054 BLOCK_INPUT;
8055 FOR_EACH_FRAME (rest, frame)
8057 struct frame *f = XFRAME (frame);
8059 if (FRAME_W32_P (f)
8060 /* Watch out for newly created frames. */
8061 && f->output_data.x->hourglass_window)
8063 XUnmapWindow (FRAME_X_DISPLAY (f),
8064 f->output_data.x->hourglass_window);
8065 /* Sync here because XTread_socket looks at the
8066 hourglass_p flag that is reset to zero below. */
8067 XSync (FRAME_X_DISPLAY (f), False);
8068 f->output_data.x->hourglass_p = 0;
8072 hourglass_shown_p = 0;
8073 UNBLOCK_INPUT;
8075 #endif /* MAC_TODO */
8080 /***********************************************************************
8081 Tool tips
8082 ***********************************************************************/
8084 static Lisp_Object x_create_tip_frame P_ ((struct mac_display_info *,
8085 Lisp_Object));
8087 /* The frame of a currently visible tooltip, or null. */
8089 Lisp_Object tip_frame;
8091 /* If non-nil, a timer started that hides the last tooltip when it
8092 fires. */
8094 Lisp_Object tip_timer;
8095 Window tip_window;
8097 /* If non-nil, a vector of 3 elements containing the last args
8098 with which x-show-tip was called. See there. */
8100 Lisp_Object last_show_tip_args;
8102 /* Create a frame for a tooltip on the display described by DPYINFO.
8103 PARMS is a list of frame parameters. Value is the frame. */
8105 static Lisp_Object
8106 x_create_tip_frame (dpyinfo, parms)
8107 struct mac_display_info *dpyinfo;
8108 Lisp_Object parms;
8110 #if 0 /* MAC_TODO : Mac version */
8111 struct frame *f;
8112 Lisp_Object frame, tem;
8113 Lisp_Object name;
8114 long window_prompting = 0;
8115 int width, height;
8116 int count = SPECPDL_INDEX ();
8117 struct gcpro gcpro1, gcpro2, gcpro3;
8118 struct kboard *kb;
8120 check_x ();
8122 /* Use this general default value to start with until we know if
8123 this frame has a specified name. */
8124 Vx_resource_name = Vinvocation_name;
8126 #ifdef MULTI_KBOARD
8127 kb = dpyinfo->kboard;
8128 #else
8129 kb = &the_only_kboard;
8130 #endif
8132 /* Get the name of the frame to use for resource lookup. */
8133 name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
8134 if (!STRINGP (name)
8135 && !EQ (name, Qunbound)
8136 && !NILP (name))
8137 error ("Invalid frame name--not a string or nil");
8138 Vx_resource_name = name;
8140 frame = Qnil;
8141 GCPRO3 (parms, name, frame);
8142 tip_frame = f = make_frame (1);
8143 XSETFRAME (frame, f);
8144 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
8146 f->output_method = output_w32;
8147 f->output_data.w32 =
8148 (struct w32_output *) xmalloc (sizeof (struct w32_output));
8149 bzero (f->output_data.w32, sizeof (struct w32_output));
8150 #if 0
8151 f->output_data.w32->icon_bitmap = -1;
8152 #endif
8153 f->output_data.w32->fontset = -1;
8154 f->icon_name = Qnil;
8156 #ifdef MULTI_KBOARD
8157 FRAME_KBOARD (f) = kb;
8158 #endif
8159 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
8160 f->output_data.w32->explicit_parent = 0;
8162 /* Set the name; the functions to which we pass f expect the name to
8163 be set. */
8164 if (EQ (name, Qunbound) || NILP (name))
8166 f->name = build_string (dpyinfo->x_id_name);
8167 f->explicit_name = 0;
8169 else
8171 f->name = name;
8172 f->explicit_name = 1;
8173 /* use the frame's title when getting resources for this frame. */
8174 specbind (Qx_resource_name, name);
8177 /* Extract the window parameters from the supplied values
8178 that are needed to determine window geometry. */
8180 Lisp_Object font;
8182 font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
8184 BLOCK_INPUT;
8185 /* First, try whatever font the caller has specified. */
8186 if (STRINGP (font))
8188 tem = Fquery_fontset (font, Qnil);
8189 if (STRINGP (tem))
8190 font = x_new_fontset (f, SDATA (tem));
8191 else
8192 font = x_new_font (f, SDATA (font));
8195 /* Try out a font which we hope has bold and italic variations. */
8196 if (!STRINGP (font))
8197 font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
8198 if (!STRINGP (font))
8199 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
8200 if (! STRINGP (font))
8201 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
8202 if (! STRINGP (font))
8203 /* This was formerly the first thing tried, but it finds too many fonts
8204 and takes too long. */
8205 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
8206 /* If those didn't work, look for something which will at least work. */
8207 if (! STRINGP (font))
8208 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
8209 UNBLOCK_INPUT;
8210 if (! STRINGP (font))
8211 font = build_string ("fixed");
8213 x_default_parameter (f, parms, Qfont, font,
8214 "font", "Font", RES_TYPE_STRING);
8217 x_default_parameter (f, parms, Qborder_width, make_number (2),
8218 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
8220 /* This defaults to 2 in order to match xterm. We recognize either
8221 internalBorderWidth or internalBorder (which is what xterm calls
8222 it). */
8223 if (NILP (Fassq (Qinternal_border_width, parms)))
8225 Lisp_Object value;
8227 value = w32_get_arg (parms, Qinternal_border_width,
8228 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
8229 if (! EQ (value, Qunbound))
8230 parms = Fcons (Fcons (Qinternal_border_width, value),
8231 parms);
8234 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
8235 "internalBorderWidth", "internalBorderWidth",
8236 RES_TYPE_NUMBER);
8238 /* Also do the stuff which must be set before the window exists. */
8239 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
8240 "foreground", "Foreground", RES_TYPE_STRING);
8241 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
8242 "background", "Background", RES_TYPE_STRING);
8243 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
8244 "pointerColor", "Foreground", RES_TYPE_STRING);
8245 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
8246 "cursorColor", "Foreground", RES_TYPE_STRING);
8247 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
8248 "borderColor", "BorderColor", RES_TYPE_STRING);
8250 /* Init faces before x_default_parameter is called for scroll-bar
8251 parameters because that function calls x_set_scroll_bar_width,
8252 which calls change_frame_size, which calls Fset_window_buffer,
8253 which runs hooks, which call Fvertical_motion. At the end, we
8254 end up in init_iterator with a null face cache, which should not
8255 happen. */
8256 init_frame_faces (f);
8258 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
8260 window_prompting = x_figure_window_size (f, parms, 0);
8263 XSetWindowAttributes attrs;
8264 unsigned long mask;
8266 BLOCK_INPUT;
8267 mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
8268 /* Window managers looks at the override-redirect flag to
8269 determine whether or net to give windows a decoration (Xlib
8270 3.2.8). */
8271 attrs.override_redirect = True;
8272 attrs.save_under = True;
8273 attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
8274 /* Arrange for getting MapNotify and UnmapNotify events. */
8275 attrs.event_mask = StructureNotifyMask;
8276 tip_window
8277 = FRAME_W32_WINDOW (f)
8278 = XCreateWindow (FRAME_W32_DISPLAY (f),
8279 FRAME_W32_DISPLAY_INFO (f)->root_window,
8280 /* x, y, width, height */
8281 0, 0, 1, 1,
8282 /* Border. */
8284 CopyFromParent, InputOutput, CopyFromParent,
8285 mask, &attrs);
8286 UNBLOCK_INPUT;
8289 x_make_gc (f);
8291 x_default_parameter (f, parms, Qauto_raise, Qnil,
8292 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
8293 x_default_parameter (f, parms, Qauto_lower, Qnil,
8294 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
8295 x_default_parameter (f, parms, Qcursor_type, Qbox,
8296 "cursorType", "CursorType", RES_TYPE_SYMBOL);
8298 /* Dimensions, especially f->height, must be done via change_frame_size.
8299 Change will not be effected unless different from the current
8300 f->height. */
8301 width = f->width;
8302 height = f->height;
8303 f->height = 0;
8304 SET_FRAME_WIDTH (f, 0);
8305 change_frame_size (f, height, width, 1, 0, 0);
8307 /* Add `tooltip' frame parameter's default value. */
8308 if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
8309 Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
8310 Qnil));
8312 f->no_split = 1;
8314 UNGCPRO;
8316 /* It is now ok to make the frame official even if we get an error
8317 below. And the frame needs to be on Vframe_list or making it
8318 visible won't work. */
8319 Vframe_list = Fcons (frame, Vframe_list);
8321 /* Now that the frame is official, it counts as a reference to
8322 its display. */
8323 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
8325 return unbind_to (count, frame);
8326 #endif /* MAC_TODO */
8327 return Qnil;
8331 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
8332 doc : /* Show STRING in a "tooltip" window on frame FRAME.
8333 A tooltip window is a small window displaying a string.
8335 FRAME nil or omitted means use the selected frame.
8337 PARMS is an optional list of frame parameters which can be used to
8338 change the tooltip's appearance.
8340 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
8341 means use the default timeout of 5 seconds.
8343 If the list of frame parameters PARAMS contains a `left' parameters,
8344 the tooltip is displayed at that x-position. Otherwise it is
8345 displayed at the mouse position, with offset DX added (default is 5 if
8346 DX isn't specified). Likewise for the y-position; if a `top' frame
8347 parameter is specified, it determines the y-position of the tooltip
8348 window, otherwise it is displayed at the mouse position, with offset
8349 DY added (default is 10). */)
8350 (string, frame, parms, timeout, dx, dy)
8351 Lisp_Object string, frame, parms, timeout, dx, dy;
8353 struct frame *f;
8354 struct window *w;
8355 Window root, child;
8356 Lisp_Object buffer, top, left;
8357 struct buffer *old_buffer;
8358 struct text_pos pos;
8359 int i, width, height;
8360 int root_x, root_y, win_x, win_y;
8361 unsigned pmask;
8362 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
8363 int old_windows_or_buffers_changed = windows_or_buffers_changed;
8364 int count = SPECPDL_INDEX ();
8366 specbind (Qinhibit_redisplay, Qt);
8368 GCPRO4 (string, parms, frame, timeout);
8370 CHECK_STRING (string);
8371 f = check_x_frame (frame);
8372 if (NILP (timeout))
8373 timeout = make_number (5);
8374 else
8375 CHECK_NATNUM (timeout);
8377 if (NILP (dx))
8378 dx = make_number (5);
8379 else
8380 CHECK_NUMBER (dx);
8382 if (NILP (dy))
8383 dy = make_number (-10);
8384 else
8385 CHECK_NUMBER (dy);
8387 if (NILP (last_show_tip_args))
8388 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
8390 if (!NILP (tip_frame))
8392 Lisp_Object last_string = AREF (last_show_tip_args, 0);
8393 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
8394 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
8396 if (EQ (frame, last_frame)
8397 && !NILP (Fequal (last_string, string))
8398 && !NILP (Fequal (last_parms, parms)))
8400 struct frame *f = XFRAME (tip_frame);
8402 /* Only DX and DY have changed. */
8403 if (!NILP (tip_timer))
8405 Lisp_Object timer = tip_timer;
8406 tip_timer = Qnil;
8407 call1 (Qcancel_timer, timer);
8410 #if 0 /* MAC_TODO : Mac specifics */
8411 BLOCK_INPUT;
8412 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
8413 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8414 root_x, root_y - PIXEL_HEIGHT (f));
8415 UNBLOCK_INPUT;
8416 #endif /* MAC_TODO */
8417 goto start_timer;
8421 /* Hide a previous tip, if any. */
8422 Fx_hide_tip ();
8424 ASET (last_show_tip_args, 0, string);
8425 ASET (last_show_tip_args, 1, frame);
8426 ASET (last_show_tip_args, 2, parms);
8428 /* Add default values to frame parameters. */
8429 if (NILP (Fassq (Qname, parms)))
8430 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
8431 if (NILP (Fassq (Qinternal_border_width, parms)))
8432 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
8433 if (NILP (Fassq (Qborder_width, parms)))
8434 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
8435 if (NILP (Fassq (Qborder_color, parms)))
8436 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
8437 if (NILP (Fassq (Qbackground_color, parms)))
8438 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
8439 parms);
8441 /* Create a frame for the tooltip, and record it in the global
8442 variable tip_frame. */
8443 frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
8444 f = XFRAME (frame);
8446 /* Set up the frame's root window. Currently we use a size of 80
8447 columns x 40 lines. If someone wants to show a larger tip, he
8448 will loose. I don't think this is a realistic case. */
8449 w = XWINDOW (FRAME_ROOT_WINDOW (f));
8450 w->left = w->top = make_number (0);
8451 w->width = make_number (80);
8452 w->height = make_number (40);
8453 adjust_glyphs (f);
8454 w->pseudo_window_p = 1;
8456 /* Display the tooltip text in a temporary buffer. */
8457 buffer = Fget_buffer_create (build_string (" *tip*"));
8458 Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
8459 old_buffer = current_buffer;
8460 set_buffer_internal_1 (XBUFFER (buffer));
8461 Ferase_buffer ();
8462 Finsert (1, &string);
8463 clear_glyph_matrix (w->desired_matrix);
8464 clear_glyph_matrix (w->current_matrix);
8465 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
8466 try_window (FRAME_ROOT_WINDOW (f), pos);
8468 /* Compute width and height of the tooltip. */
8469 width = height = 0;
8470 for (i = 0; i < w->desired_matrix->nrows; ++i)
8472 struct glyph_row *row = &w->desired_matrix->rows[i];
8473 struct glyph *last;
8474 int row_width;
8476 /* Stop at the first empty row at the end. */
8477 if (!row->enabled_p || !row->displays_text_p)
8478 break;
8480 /* Let the row go over the full width of the frame. */
8481 row->full_width_p = 1;
8483 /* There's a glyph at the end of rows that is use to place
8484 the cursor there. Don't include the width of this glyph. */
8485 if (row->used[TEXT_AREA])
8487 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
8488 row_width = row->pixel_width - last->pixel_width;
8490 else
8491 row_width = row->pixel_width;
8493 height += row->height;
8494 width = max (width, row_width);
8497 /* Add the frame's internal border to the width and height the X
8498 window should have. */
8499 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
8500 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
8502 /* Move the tooltip window where the mouse pointer is. Resize and
8503 show it. */
8504 #if 0 /* TODO : Mac specifics */
8505 compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
8507 BLOCK_INPUT;
8508 XQueryPointer (FRAME_W32_DISPLAY (f), FRAME_W32_DISPLAY_INFO (f)->root_window,
8509 &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
8510 XMoveResizeWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
8511 root_x + 5, root_y - height - 5, width, height);
8512 XMapRaised (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
8513 UNBLOCK_INPUT;
8514 #endif /* MAC_TODO */
8516 /* Draw into the window. */
8517 w->must_be_updated_p = 1;
8518 update_single_window (w, 1);
8520 /* Restore original current buffer. */
8521 set_buffer_internal_1 (old_buffer);
8522 windows_or_buffers_changed = old_windows_or_buffers_changed;
8524 start_timer:
8525 /* Let the tip disappear after timeout seconds. */
8526 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
8527 intern ("x-hide-tip"));
8529 UNGCPRO;
8530 return unbind_to (count, Qnil);
8534 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
8535 doc: /* Hide the current tooltip window, if there is any.
8536 Value is t is tooltip was open, nil otherwise. */)
8539 int count;
8540 Lisp_Object deleted, frame, timer;
8541 struct gcpro gcpro1, gcpro2;
8543 /* Return quickly if nothing to do. */
8544 if (NILP (tip_timer) && NILP (tip_frame))
8545 return Qnil;
8547 frame = tip_frame;
8548 timer = tip_timer;
8549 GCPRO2 (frame, timer);
8550 tip_frame = tip_timer = deleted = Qnil;
8552 count = SPECPDL_INDEX ();
8553 specbind (Qinhibit_redisplay, Qt);
8554 specbind (Qinhibit_quit, Qt);
8556 if (!NILP (timer))
8557 call1 (Qcancel_timer, timer);
8559 if (FRAMEP (frame))
8561 Fdelete_frame (frame, Qnil);
8562 deleted = Qt;
8565 UNGCPRO;
8566 return unbind_to (count, deleted);
8571 /***********************************************************************
8572 File selection dialog
8573 ***********************************************************************/
8575 #if 0 /* MAC_TODO: can standard file dialog */
8576 extern Lisp_Object Qfile_name_history;
8578 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
8579 doc: /* Read file name, prompting with PROMPT in directory DIR.
8580 Use a file selection dialog.
8581 Select DEFAULT-FILENAME in the dialog's file selection box, if
8582 specified. Don't let the user enter a file name in the file
8583 selection dialog's entry field, if MUSTMATCH is non-nil. */)
8584 (prompt, dir, default_filename, mustmatch)
8585 Lisp_Object prompt, dir, default_filename, mustmatch;
8587 struct frame *f = SELECTED_FRAME ();
8588 Lisp_Object file = Qnil;
8589 int count = SPECPDL_INDEX ();
8590 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
8591 char filename[MAX_PATH + 1];
8592 char init_dir[MAX_PATH + 1];
8593 int use_dialog_p = 1;
8595 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
8596 CHECK_STRING (prompt);
8597 CHECK_STRING (dir);
8599 /* Create the dialog with PROMPT as title, using DIR as initial
8600 directory and using "*" as pattern. */
8601 dir = Fexpand_file_name (dir, Qnil);
8602 strncpy (init_dir, SDATA (dir), MAX_PATH);
8603 init_dir[MAX_PATH] = '\0';
8604 unixtodos_filename (init_dir);
8606 if (STRINGP (default_filename))
8608 char *file_name_only;
8609 char *full_path_name = SDATA (default_filename);
8611 unixtodos_filename (full_path_name);
8613 file_name_only = strrchr (full_path_name, '\\');
8614 if (!file_name_only)
8615 file_name_only = full_path_name;
8616 else
8618 file_name_only++;
8620 /* If default_file_name is a directory, don't use the open
8621 file dialog, as it does not support selecting
8622 directories. */
8623 if (!(*file_name_only))
8624 use_dialog_p = 0;
8627 strncpy (filename, file_name_only, MAX_PATH);
8628 filename[MAX_PATH] = '\0';
8630 else
8631 filename[0] = '\0';
8633 if (use_dialog_p)
8635 OPENFILENAME file_details;
8636 char *filename_file;
8638 /* Prevent redisplay. */
8639 specbind (Qinhibit_redisplay, Qt);
8640 BLOCK_INPUT;
8642 bzero (&file_details, sizeof (file_details));
8643 file_details.lStructSize = sizeof (file_details);
8644 file_details.hwndOwner = FRAME_W32_WINDOW (f);
8645 file_details.lpstrFile = filename;
8646 file_details.nMaxFile = sizeof (filename);
8647 file_details.lpstrInitialDir = init_dir;
8648 file_details.lpstrTitle = SDATA (prompt);
8649 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
8651 if (!NILP (mustmatch))
8652 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
8654 if (GetOpenFileName (&file_details))
8656 dostounix_filename (filename);
8657 file = build_string (filename);
8659 else
8660 file = Qnil;
8662 UNBLOCK_INPUT;
8663 file = unbind_to (count, file);
8665 /* Open File dialog will not allow folders to be selected, so resort
8666 to minibuffer completing reads for directories. */
8667 else
8668 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
8669 dir, mustmatch, dir, Qfile_name_history,
8670 default_filename, Qnil);
8672 UNGCPRO;
8674 /* Make "Cancel" equivalent to C-g. */
8675 if (NILP (file))
8676 Fsignal (Qquit, Qnil);
8678 return unbind_to (count, file);
8680 #endif /* MAC_TODO */
8684 /***********************************************************************
8685 Tests
8686 ***********************************************************************/
8688 #if GLYPH_DEBUG
8690 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8691 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8692 (spec)
8693 Lisp_Object spec;
8695 return valid_image_p (spec) ? Qt : Qnil;
8699 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8700 (spec)
8701 Lisp_Object spec;
8703 int id = -1;
8705 if (valid_image_p (spec))
8706 id = lookup_image (SELECTED_FRAME (), spec);
8708 debug_print (spec);
8709 return make_number (id);
8712 #endif /* GLYPH_DEBUG != 0 */
8716 /***********************************************************************
8717 Initialization
8718 ***********************************************************************/
8720 /* Keep this list in the same order as frame_parms in frame.c.
8721 Use 0 for unsupported frame parameters. */
8723 frame_parm_handler mac_frame_parm_handlers[] =
8725 x_set_autoraise,
8726 x_set_autolower,
8727 x_set_background_color,
8728 x_set_border_color,
8729 x_set_border_width,
8730 x_set_cursor_color,
8731 x_set_cursor_type,
8732 x_set_font,
8733 x_set_foreground_color,
8734 x_set_icon_name,
8735 0, /* MAC_TODO: x_set_icon_type, */
8736 x_set_internal_border_width,
8737 x_set_menu_bar_lines,
8738 x_set_mouse_color,
8739 x_explicitly_set_name,
8740 x_set_scroll_bar_width,
8741 x_set_title,
8742 x_set_unsplittable,
8743 x_set_vertical_scroll_bars,
8744 x_set_visibility,
8745 x_set_tool_bar_lines,
8746 0, /* MAC_TODO: x_set_scroll_bar_foreground, */
8747 0, /* MAC_TODO: x_set_scroll_bar_background, */
8748 x_set_screen_gamma,
8749 x_set_line_spacing,
8750 0, /* MAC_TODO: x_set_fringe_width, */
8751 0, /* MAC_TODO: x_set_fringe_width, */
8752 0, /* x_set_wait_for_wm, */
8753 0, /* MAC_TODO: x_set_fullscreen, */
8756 void
8757 syms_of_macfns ()
8759 /* Certainly running on Mac. */
8760 mac_in_use = 1;
8762 /* The section below is built by the lisp expression at the top of the file,
8763 just above where these variables are declared. */
8764 /*&&& init symbols here &&&*/
8765 Qnone = intern ("none");
8766 staticpro (&Qnone);
8767 Qsuppress_icon = intern ("suppress-icon");
8768 staticpro (&Qsuppress_icon);
8769 Qundefined_color = intern ("undefined-color");
8770 staticpro (&Qundefined_color);
8771 Qcenter = intern ("center");
8772 staticpro (&Qcenter);
8773 /* This is the end of symbol initialization. */
8775 Qhyper = intern ("hyper");
8776 staticpro (&Qhyper);
8777 Qsuper = intern ("super");
8778 staticpro (&Qsuper);
8779 Qmeta = intern ("meta");
8780 staticpro (&Qmeta);
8781 Qalt = intern ("alt");
8782 staticpro (&Qalt);
8783 Qctrl = intern ("ctrl");
8784 staticpro (&Qctrl);
8785 Qcontrol = intern ("control");
8786 staticpro (&Qcontrol);
8787 Qshift = intern ("shift");
8788 staticpro (&Qshift);
8790 /* Text property `display' should be nonsticky by default. */
8791 Vtext_property_default_nonsticky
8792 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
8795 Qlaplace = intern ("laplace");
8796 staticpro (&Qlaplace);
8798 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
8799 staticpro (&Qface_set_after_frame_default);
8801 Fput (Qundefined_color, Qerror_conditions,
8802 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
8803 Fput (Qundefined_color, Qerror_message,
8804 build_string ("Undefined color"));
8806 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8807 doc: /* List of directories to search for window system bitmap files. */);
8808 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
8810 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
8811 doc: /* The shape of the pointer when over text.
8812 Changing the value does not affect existing frames
8813 unless you set the mouse color. */);
8814 Vx_pointer_shape = Qnil;
8816 Vx_nontext_pointer_shape = Qnil;
8818 Vx_mode_pointer_shape = Qnil;
8820 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
8821 doc: /* The shape of the pointer when Emacs is hourglass.
8822 This variable takes effect when you create a new frame
8823 or when you set the mouse color. */);
8824 Vx_hourglass_pointer_shape = Qnil;
8826 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
8827 doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
8828 display_hourglass_p = 1;
8830 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
8831 doc: /* *Seconds to wait before displaying an hourglass pointer.
8832 Value must be an integer or float. */);
8833 Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
8835 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
8836 &Vx_sensitive_text_pointer_shape,
8837 doc: /* The shape of the pointer when over mouse-sensitive text.
8838 This variable takes effect when you create a new frame
8839 or when you set the mouse color. */);
8840 Vx_sensitive_text_pointer_shape = Qnil;
8842 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
8843 doc: /* A string indicating the foreground color of the cursor box. */);
8844 Vx_cursor_fore_pixel = Qnil;
8846 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
8847 doc: /* Non-nil if no window manager is in use.
8848 Emacs doesn't try to figure this out; this is always nil
8849 unless you set it to something else. */);
8850 /* We don't have any way to find this out, so set it to nil
8851 and maybe the user would like to set it to t. */
8852 Vx_no_window_manager = Qnil;
8854 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
8855 &Vx_pixel_size_width_font_regexp,
8856 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
8858 Since Emacs gets width of a font matching with this regexp from
8859 PIXEL_SIZE field of the name, font finding mechanism gets faster for
8860 such a font. This is especially effective for such large fonts as
8861 Chinese, Japanese, and Korean. */);
8862 Vx_pixel_size_width_font_regexp = Qnil;
8864 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
8865 doc: /* Time after which cached images are removed from the cache.
8866 When an image has not been displayed this many seconds, remove it
8867 from the image cache. Value must be an integer or nil with nil
8868 meaning don't clear the cache. */);
8869 Vimage_cache_eviction_delay = make_number (30 * 60);
8871 defsubr (&Sx_change_window_property);
8872 defsubr (&Sx_delete_window_property);
8873 defsubr (&Sx_window_property);
8874 defsubr (&Sxw_display_color_p);
8875 defsubr (&Sx_display_grayscale_p);
8876 defsubr (&Sxw_color_defined_p);
8877 defsubr (&Sxw_color_values);
8878 defsubr (&Sx_server_max_request_size);
8879 defsubr (&Sx_server_vendor);
8880 defsubr (&Sx_server_version);
8881 defsubr (&Sx_display_pixel_width);
8882 defsubr (&Sx_display_pixel_height);
8883 defsubr (&Sx_display_mm_width);
8884 defsubr (&Sx_display_mm_height);
8885 defsubr (&Sx_display_screens);
8886 defsubr (&Sx_display_planes);
8887 defsubr (&Sx_display_color_cells);
8888 defsubr (&Sx_display_visual_class);
8889 defsubr (&Sx_display_backing_store);
8890 defsubr (&Sx_display_save_under);
8891 defsubr (&Sx_create_frame);
8892 #if 0 /* MAC_TODO: implement network support */
8893 defsubr (&Sx_open_connection);
8894 defsubr (&Sx_close_connection);
8895 #endif
8896 defsubr (&Sx_display_list);
8897 defsubr (&Sx_synchronize);
8899 /* Setting callback functions for fontset handler. */
8900 get_font_info_func = x_get_font_info;
8902 #if 0 /* This function pointer doesn't seem to be used anywhere.
8903 And the pointer assigned has the wrong type, anyway. */
8904 list_fonts_func = x_list_fonts;
8905 #endif
8907 load_font_func = x_load_font;
8908 find_ccl_program_func = x_find_ccl_program;
8909 query_font_func = x_query_font;
8911 set_frame_fontset_func = x_set_font;
8912 check_window_system_func = check_mac;
8914 #if 0 /* MAC_TODO: Image support for Mac Images. */
8915 Qxbm = intern ("xbm");
8916 staticpro (&Qxbm);
8917 QCtype = intern (":type");
8918 staticpro (&QCtype);
8919 QCconversion = intern (":conversion");
8920 staticpro (&QCconversion);
8921 QCheuristic_mask = intern (":heuristic-mask");
8922 staticpro (&QCheuristic_mask);
8923 QCcolor_symbols = intern (":color-symbols");
8924 staticpro (&QCcolor_symbols);
8925 QCascent = intern (":ascent");
8926 staticpro (&QCascent);
8927 QCmargin = intern (":margin");
8928 staticpro (&QCmargin);
8929 QCrelief = intern (":relief");
8930 staticpro (&QCrelief);
8931 Qpostscript = intern ("postscript");
8932 staticpro (&Qpostscript);
8933 QCloader = intern (":loader");
8934 staticpro (&QCloader);
8935 QCbounding_box = intern (":bounding-box");
8936 staticpro (&QCbounding_box);
8937 QCpt_width = intern (":pt-width");
8938 staticpro (&QCpt_width);
8939 QCpt_height = intern (":pt-height");
8940 staticpro (&QCpt_height);
8941 QCindex = intern (":index");
8942 staticpro (&QCindex);
8943 Qpbm = intern ("pbm");
8944 staticpro (&Qpbm);
8946 #if HAVE_XPM
8947 Qxpm = intern ("xpm");
8948 staticpro (&Qxpm);
8949 #endif
8951 #if HAVE_JPEG
8952 Qjpeg = intern ("jpeg");
8953 staticpro (&Qjpeg);
8954 #endif
8956 #if HAVE_TIFF
8957 Qtiff = intern ("tiff");
8958 staticpro (&Qtiff);
8959 #endif
8961 #if HAVE_GIF
8962 Qgif = intern ("gif");
8963 staticpro (&Qgif);
8964 #endif
8966 #if HAVE_PNG
8967 Qpng = intern ("png");
8968 staticpro (&Qpng);
8969 #endif
8971 defsubr (&Sclear_image_cache);
8973 #if GLYPH_DEBUG
8974 defsubr (&Simagep);
8975 defsubr (&Slookup_image);
8976 #endif
8977 #endif /* MAC_TODO */
8979 hourglass_atimer = NULL;
8980 hourglass_shown_p = 0;
8982 defsubr (&Sx_show_tip);
8983 defsubr (&Sx_hide_tip);
8984 staticpro (&tip_timer);
8985 tip_timer = Qnil;
8987 #if 0 /* MAC_TODO */
8988 defsubr (&Sx_file_dialog);
8989 #endif
8993 void
8994 init_xfns ()
8996 image_types = NULL;
8997 Vimage_types = Qnil;
8999 define_image_type (&xbm_type);
9000 #if 0 /* NTEMACS_TODO : Image support for W32 */
9001 define_image_type (&gs_type);
9002 define_image_type (&pbm_type);
9004 #if HAVE_XPM
9005 define_image_type (&xpm_type);
9006 #endif
9008 #if HAVE_JPEG
9009 define_image_type (&jpeg_type);
9010 #endif
9012 #if HAVE_TIFF
9013 define_image_type (&tiff_type);
9014 #endif
9016 #if HAVE_GIF
9017 define_image_type (&gif_type);
9018 #endif
9020 #if HAVE_PNG
9021 define_image_type (&png_type);
9022 #endif
9023 #endif /* NTEMACS_TODO */